Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CloudClientStorage.c Source File

CloudClientStorage.c

00001 // ----------------------------------------------------------------------------
00002 // Copyright 2016-2017 ARM Ltd.
00003 //
00004 // SPDX-License-Identifier: Apache-2.0
00005 //
00006 // Licensed under the Apache License, Version 2.0 (the "License");
00007 // you may not use this file except in compliance with the License.
00008 // You may obtain a copy of the License at
00009 //
00010 //     http://www.apache.org/licenses/LICENSE-2.0
00011 //
00012 // Unless required by applicable law or agreed to in writing, software
00013 // distributed under the License is distributed on an "AS IS" BASIS,
00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015 // See the License for the specific language governing permissions and
00016 // limitations under the License.
00017 // ----------------------------------------------------------------------------
00018 
00019 #include <string.h>
00020 #include <assert.h>
00021 #include "key_config_manager.h"
00022 #include "CloudClientStorage.h"
00023 #include "mbed-trace/mbed_trace.h"
00024 #include "mbed-client-libservice/common_functions.h"
00025 
00026 #define TRACE_GROUP "mClt"
00027 
00028 ccs_status_e uninitialize_storage(void)
00029 {
00030     tr_debug("CloudClientStorage::uninitialize_storage");
00031 
00032     kcm_status_e  status = kcm_finalize();
00033     if(status != KCM_STATUS_SUCCESS) {
00034         tr_error("CloudClientStorage::uninitialize_storage - error %d", status);
00035         return CCS_STATUS_ERROR;
00036     }
00037     return CCS_STATUS_SUCCESS;
00038 }
00039 
00040 ccs_status_e initialize_storage(void)
00041 {
00042     tr_debug("CloudClientStorage::initialize_storage");
00043     kcm_status_e  status = kcm_init();
00044     if(status != KCM_STATUS_SUCCESS) {
00045         tr_error("CloudClientStorage::::initialize_storage - error %d", status);
00046         return CCS_STATUS_ERROR;
00047     }
00048     return CCS_STATUS_SUCCESS;
00049 }
00050 
00051 ccs_status_e ccs_get_string_item(const char* key,
00052                                  uint8_t *buffer,
00053                                  const size_t buffer_size,
00054                                  ccs_item_type_e item_type)
00055 {
00056     size_t len = 0;
00057     ccs_status_e status = ccs_get_item(key, buffer, buffer_size - 1, &len, item_type);
00058 
00059     if (status == CCS_STATUS_SUCCESS) {
00060         // Null terminate after buffer value
00061         buffer[len] = 0;
00062     }
00063 
00064     return status;
00065 }
00066 
00067 ccs_status_e ccs_check_item(const char* key, ccs_item_type_e item_type)
00068 {
00069     if (key == NULL) {
00070         return CCS_STATUS_ERROR;
00071     }
00072 
00073     size_t real_size = 0;
00074     kcm_status_e  kcm_status = kcm_item_get_data_size((const uint8_t*)key, strlen(key), item_type, &real_size);
00075     if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
00076         return CCS_STATUS_KEY_DOESNT_EXIST;
00077     }
00078     return CCS_STATUS_SUCCESS;
00079 }
00080 
00081 ccs_status_e ccs_delete_item(const char* key, ccs_item_type_e item_type)
00082 {
00083     if (key == NULL) {
00084         tr_error("CloudClientStorage::ccs_delete_item error, invalid parameters");
00085         return CCS_STATUS_ERROR;
00086     }
00087 
00088     ccs_status_e status = ccs_check_item(key, item_type);
00089     if (status == CCS_STATUS_KEY_DOESNT_EXIST) {
00090         // No need to call delete as item does not exist.
00091         tr_debug("CloudClientStorage::ccs_delete_item [%s], type [%d] does not exist.", key, item_type);
00092         return CCS_STATUS_SUCCESS;
00093     } else if (status == CCS_STATUS_ERROR) {
00094         return CCS_STATUS_ERROR;
00095     }
00096 
00097     // Delete parameter from storage
00098     tr_debug("CloudClientStorage::ccs_delete_item [%s], type [%d] ", key, item_type);
00099     kcm_status_e  kcm_status = kcm_item_delete((const uint8_t*)key,
00100                                   strlen(key),
00101                                   item_type);
00102 
00103     if (kcm_status != KCM_STATUS_SUCCESS) {
00104         tr_debug("CloudClientStorage::ccs_delete_item [%s] kcm get error %d", key, kcm_status);
00105         return CCS_STATUS_ERROR;
00106     }
00107 
00108     return CCS_STATUS_SUCCESS;
00109 }
00110 
00111 ccs_status_e ccs_item_size(const char* key, size_t* size_out, ccs_item_type_e item_type)
00112 {
00113     if (key == NULL) {
00114         tr_error("CloudClientStorage::ccs_item_size error, invalid parameters");
00115         return CCS_STATUS_ERROR;
00116     }
00117 
00118     tr_debug("CloudClientStorage::ccs_item_size [%s], item [%d]", key, item_type);
00119 
00120     // Get kcm item size
00121     kcm_status_e  kcm_status = kcm_item_get_data_size((const uint8_t*)key,
00122                                          strlen(key),
00123                                          item_type,
00124                                          size_out);
00125 
00126     if (kcm_status != KCM_STATUS_SUCCESS) {
00127         tr_debug("CloudClientStorage::ccs_item_size [%s] kcm get error %d", key, kcm_status);
00128         return CCS_STATUS_ERROR;
00129     }
00130 
00131     return CCS_STATUS_SUCCESS;
00132 }
00133 
00134 ccs_status_e ccs_get_item(const char* key,
00135                           uint8_t *buffer,
00136                           const size_t buffer_size,
00137                           size_t *value_length,
00138                           ccs_item_type_e item_type)
00139 {
00140     if (key == NULL || buffer == NULL || buffer_size == 0) {
00141         tr_error("CloudClientStorage::ccs_get_item error, invalid parameters");
00142         return CCS_STATUS_ERROR;
00143     }
00144 
00145     tr_debug("CloudClientStorage::ccs_get_item [%s], type [%d]", key, item_type);
00146 
00147     kcm_status_e  kcm_status = kcm_item_get_data((const uint8_t*)key,
00148                                     strlen(key),
00149                                     item_type,
00150                                     buffer,
00151                                     buffer_size,
00152                                     value_length);
00153 
00154     if (kcm_status != KCM_STATUS_SUCCESS) {
00155         tr_debug("CloudClientStorage::ccs_get_item [%s] kcm get error %d", key, kcm_status);
00156         return CCS_STATUS_ERROR;
00157     }
00158 
00159     return CCS_STATUS_SUCCESS;
00160 }
00161 
00162 ccs_status_e ccs_set_item(const char* key,
00163                           const uint8_t *buffer,
00164                           const size_t buffer_size,
00165                           ccs_item_type_e item_type)
00166 {
00167     if (key == NULL || buffer == NULL || buffer_size == 0) {
00168         tr_error("CloudClientStorage::ccs_set_item error, invalid parameters");
00169         return CCS_STATUS_ERROR;
00170     }
00171 
00172     tr_debug("CloudClientStorage::ccs_set_item kcm [%s], type [%d]", key, item_type);
00173 
00174     kcm_status_e  kcm_status = kcm_item_store((const uint8_t*)key,
00175                                  strlen(key),
00176                                  item_type,
00177                                  false,
00178                                  buffer,
00179                                  buffer_size,
00180                                  NULL);
00181 
00182     if (kcm_status == KCM_CRYPTO_STATUS_PRIVATE_KEY_VERIFICATION_FAILED) {
00183         tr_error("CloudClientStorage::ccs_set_item kcm validation error");
00184         return CCS_STATUS_VALIDATION_FAIL;
00185     }
00186     else if (kcm_status != KCM_STATUS_SUCCESS) {
00187         tr_debug("CloudClientStorage::ccs_set_item kcm [%s] get error %d", key, kcm_status);
00188         return CCS_STATUS_ERROR;
00189     }
00190 
00191     return CCS_STATUS_SUCCESS;
00192 }
00193 
00194 void *ccs_create_certificate_chain(const char *chain_file_name, size_t chain_len)
00195 {
00196     kcm_status_e  kcm_status;
00197     kcm_cert_chain_handle chain_handle;
00198 
00199     kcm_status = kcm_cert_chain_create(&chain_handle,
00200                                        (uint8_t*)chain_file_name,
00201                                        strlen(chain_file_name),
00202                                        chain_len,
00203                                        false);
00204 
00205     if (kcm_status != KCM_STATUS_SUCCESS) {
00206         tr_error("CloudClientStorage::ccs_create_certificate_chain - error %d", kcm_status);
00207         return NULL;
00208     } else {
00209         return (void*)chain_handle;
00210     }
00211 }
00212 
00213 void *ccs_open_certificate_chain(const char *chain_file_name, size_t *chain_size)
00214 {
00215     kcm_status_e  kcm_status;
00216     kcm_cert_chain_handle handle;
00217 
00218     kcm_status = kcm_cert_chain_open(&handle,
00219                                      (uint8_t*)chain_file_name,
00220                                      strlen(chain_file_name),
00221                                      chain_size);
00222 
00223     if (kcm_status == KCM_STATUS_SUCCESS) {
00224         return (void*)handle;
00225     } else {
00226         tr_error("CloudClientStorage::ccs_open_certificate_chain - error %d", kcm_status);
00227         return NULL;
00228     }
00229 }
00230 
00231 ccs_status_e ccs_get_next_cert_chain(void *chain_handle, void *cert_data, size_t *data_size)
00232 {
00233     kcm_status_e  kcm_status;
00234     size_t max_size = 1024;
00235 
00236     kcm_status = kcm_cert_chain_get_next_size((kcm_cert_chain_handle *) chain_handle, data_size);
00237 
00238     if (kcm_status != KCM_STATUS_SUCCESS) {
00239         tr_error("CloudClientStorage::ccs_get_next_cert_chain - get_next_size error %d", kcm_status);
00240         data_size = 0;
00241         return CCS_STATUS_ERROR;
00242     }
00243 
00244 
00245     kcm_status = kcm_cert_chain_get_next_data((kcm_cert_chain_handle *) chain_handle, (uint8_t*)cert_data, max_size, data_size);
00246 
00247     if (kcm_status != KCM_STATUS_SUCCESS) {
00248         tr_error("CloudClientStorage::ccs_get_next_cert_chain - get_next_data error %d", kcm_status);
00249         data_size = 0;
00250         return CCS_STATUS_ERROR;
00251     } else {
00252         return CCS_STATUS_SUCCESS;
00253     }
00254 }
00255 
00256 ccs_status_e ccs_close_certificate_chain(void *chain_handle)
00257 {
00258     kcm_status_e  kcm_status;
00259     kcm_cert_chain_handle *handle = (kcm_cert_chain_handle *) chain_handle;
00260     kcm_status = kcm_cert_chain_close(handle);
00261     if (kcm_status != KCM_STATUS_SUCCESS) {
00262         tr_error("CloudClientStorage::ccs_close_certificate_chain - error %d", kcm_status);
00263         return CCS_STATUS_ERROR;
00264     } else {
00265         return CCS_STATUS_SUCCESS;
00266     }
00267 }
00268 
00269 ccs_status_e ccs_add_next_cert_chain(void *chain_handle, const uint8_t *cert_data, size_t data_size)
00270 {
00271     kcm_status_e  kcm_status;
00272     kcm_status = kcm_cert_chain_add_next((kcm_cert_chain_handle *) chain_handle, cert_data, data_size);
00273 
00274     if (kcm_status != KCM_STATUS_SUCCESS) {
00275         tr_error("CloudClientStorage::ccs_add_next_cert_chain - error %d", kcm_status);
00276         return CCS_STATUS_ERROR;
00277     } else {
00278         return CCS_STATUS_SUCCESS;
00279     }
00280 }
00281 
00282 ccs_status_e ccs_parse_cert_chain_and_store(const uint8_t *cert_chain_name,
00283                                             const size_t cert_chain_name_len,
00284                                             const uint8_t *cert_chain_data,
00285                                             const uint16_t cert_chain_data_len)
00286 {
00287     assert(cert_chain_data);
00288     assert(cert_chain_data_len > 0);
00289 
00290     const uint8_t *ptr = cert_chain_data;
00291     uint8_t version = *ptr++;
00292     uint8_t chain_length = *ptr++;
00293     ccs_status_e success = CCS_STATUS_SUCCESS;
00294     kcm_cert_chain_handle chain_handle;
00295     kcm_status_e  status = KCM_STATUS_ERROR;
00296 
00297     // Check overflow
00298     if (ptr - cert_chain_data > cert_chain_data_len) {
00299         success = CCS_STATUS_VALIDATION_FAIL;
00300     }
00301 
00302     // Check version is correct and there are certs in the chain
00303     if (version != 1 || chain_length == 0) {
00304         success = CCS_STATUS_VALIDATION_FAIL;
00305     }
00306 
00307     // Create KCM cert chain
00308     if (success == CCS_STATUS_SUCCESS) {
00309         status = kcm_cert_chain_create(&chain_handle,
00310                                        cert_chain_name,
00311                                        cert_chain_name_len,
00312                                        chain_length,
00313                                        false);
00314         tr_debug("Cert chain create %d", status);
00315         if (status != KCM_STATUS_SUCCESS) {
00316             success = CCS_STATUS_ERROR;
00317         }
00318     }
00319 
00320     if (success == CCS_STATUS_SUCCESS) {
00321         for (uint8_t i = 0; i < chain_length; i++) {
00322             // Parse certificate length (2 bytes)
00323             uint16_t cert_len = common_read_16_bit(ptr);
00324             ptr += 2;
00325             // Check overflow
00326             if (ptr - cert_chain_data > cert_chain_data_len) {
00327                 success = CCS_STATUS_VALIDATION_FAIL;
00328                 break;
00329             }
00330 
00331             // Store certificate
00332             tr_debug("Storing cert\r\n%s", tr_array(ptr, cert_len));
00333             status = kcm_cert_chain_add_next(chain_handle, ptr, cert_len);
00334             if (status != KCM_STATUS_SUCCESS) {
00335                 success = CCS_STATUS_ERROR;
00336                 break;
00337             }
00338 
00339             ptr += cert_len;
00340 
00341             // Check overflow
00342             if (ptr - cert_chain_data > cert_chain_data_len) {
00343                 success = CCS_STATUS_VALIDATION_FAIL;
00344                 break;
00345             }
00346         }
00347     }
00348 
00349     status = kcm_cert_chain_close(chain_handle);
00350     if (status != KCM_STATUS_SUCCESS) {
00351         success = CCS_STATUS_ERROR;
00352     }
00353 
00354     if (success != CCS_STATUS_SUCCESS) {
00355         kcm_cert_chain_delete(cert_chain_name, cert_chain_name_len);
00356     }
00357 
00358     return success;
00359 }