Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

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), (kcm_item_type_e)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. Not deleting anything.", 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                                   (kcm_item_type_e)item_type);
00102 
00103     if (kcm_status != KCM_STATUS_SUCCESS) {
00104         tr_debug("CloudClientStorage::ccs_delete_item [%s] kcm 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                                          (kcm_item_type_e)item_type,
00124                                          size_out);
00125 
00126     if (kcm_status != KCM_STATUS_SUCCESS) {
00127         tr_debug("CloudClientStorage::ccs_item_size [%s] kcm 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                                     (kcm_item_type_e)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 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                                  (kcm_item_type_e)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] 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         return CCS_STATUS_ERROR;
00241     }
00242 
00243 
00244     kcm_status = kcm_cert_chain_get_next_data((kcm_cert_chain_handle *) chain_handle, (uint8_t*)cert_data, max_size, data_size);
00245 
00246     if (kcm_status != KCM_STATUS_SUCCESS) {
00247         tr_error("CloudClientStorage::ccs_get_next_cert_chain - get_next_data error %d", kcm_status);
00248         return CCS_STATUS_ERROR;
00249     } else {
00250         return CCS_STATUS_SUCCESS;
00251     }
00252 }
00253 
00254 ccs_status_e ccs_close_certificate_chain(void *chain_handle)
00255 {
00256     kcm_status_e  kcm_status;
00257     kcm_cert_chain_handle *handle = (kcm_cert_chain_handle *) chain_handle;
00258     kcm_status = kcm_cert_chain_close(handle);
00259     if (kcm_status != KCM_STATUS_SUCCESS) {
00260         tr_error("CloudClientStorage::ccs_close_certificate_chain - error %d", kcm_status);
00261         return CCS_STATUS_ERROR;
00262     } else {
00263         return CCS_STATUS_SUCCESS;
00264     }
00265 }
00266 
00267 ccs_status_e ccs_add_next_cert_chain(void *chain_handle, const uint8_t *cert_data, size_t data_size)
00268 {
00269     kcm_status_e  kcm_status;
00270     kcm_status = kcm_cert_chain_add_next((kcm_cert_chain_handle *) chain_handle, cert_data, data_size);
00271 
00272     if (kcm_status != KCM_STATUS_SUCCESS) {
00273         tr_error("CloudClientStorage::ccs_add_next_cert_chain - error %d", kcm_status);
00274         return CCS_STATUS_ERROR;
00275     } else {
00276         return CCS_STATUS_SUCCESS;
00277     }
00278 }
00279 
00280 ccs_status_e ccs_parse_cert_chain_and_store(const uint8_t *cert_chain_name,
00281                                             const size_t cert_chain_name_len,
00282                                             const uint8_t *cert_chain_data,
00283                                             const uint16_t cert_chain_data_len)
00284 {
00285     assert(cert_chain_data);
00286     assert(cert_chain_data_len > 0);
00287 
00288     const uint8_t *ptr = cert_chain_data;
00289     uint8_t version = *ptr++;
00290     uint8_t chain_length = *ptr++;
00291     ccs_status_e success = CCS_STATUS_SUCCESS;
00292     kcm_cert_chain_handle chain_handle;
00293     kcm_status_e  status;
00294 
00295     // Check overflow
00296     if (ptr - cert_chain_data > cert_chain_data_len) {
00297         success = CCS_STATUS_VALIDATION_FAIL;
00298     }
00299 
00300     // Check version is correct and there are certs in the chain
00301     if (version != 1 || chain_length == 0) {
00302         success = CCS_STATUS_VALIDATION_FAIL;
00303     }
00304 
00305     // Create KCM cert chain
00306     if (success == CCS_STATUS_SUCCESS) {
00307         status = kcm_cert_chain_create(&chain_handle,
00308                                        cert_chain_name,
00309                                        cert_chain_name_len,
00310                                        chain_length,
00311                                        false);
00312         tr_debug("Cert chain create %d", status);
00313         if (status != KCM_STATUS_SUCCESS) {
00314             success = CCS_STATUS_ERROR;
00315         }
00316     }
00317 
00318     if (success == CCS_STATUS_SUCCESS) {
00319         for (uint8_t i = 0; i < chain_length; i++) {
00320             // Parse certificate length (2 bytes)
00321             uint16_t cert_len = common_read_16_bit(ptr);
00322             ptr += 2;
00323             // Check overflow
00324             if (ptr - cert_chain_data > cert_chain_data_len) {
00325                 success = CCS_STATUS_VALIDATION_FAIL;
00326                 break;
00327             }
00328 
00329             // Store certificate
00330             tr_debug("Storing cert\r\n%s", tr_array(ptr, cert_len));
00331             status = kcm_cert_chain_add_next(chain_handle, ptr, cert_len);
00332             if (status != KCM_STATUS_SUCCESS) {
00333                 success = CCS_STATUS_ERROR;
00334                 break;
00335             }
00336 
00337             ptr += cert_len;
00338 
00339             // Check overflow
00340             if (ptr - cert_chain_data > cert_chain_data_len) {
00341                 success = CCS_STATUS_VALIDATION_FAIL;
00342                 break;
00343             }
00344         }
00345 
00346         status = kcm_cert_chain_close(chain_handle);
00347         if (status != KCM_STATUS_SUCCESS) {
00348             success = CCS_STATUS_ERROR;
00349         }
00350     }
00351 
00352     if (success != CCS_STATUS_SUCCESS) {
00353         kcm_cert_chain_delete(cert_chain_name, cert_chain_name_len);
00354     }
00355 
00356     return success;
00357 }