Toyomasa Watarai / Mbed OS Mbed-example-WS-W27

Dependencies:   MMA7660 LM75B

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers key_config_manager.c Source File

key_config_manager.c

00001 // ----------------------------------------------------------------------------
00002 // Copyright 2016-2017 ARM Ltd.
00003 //
00004 // Licensed under the Apache License, Version 2.0 (the "License");
00005 // you may not use this file except in compliance with the License.
00006 // You may obtain a copy of the License at
00007 //
00008 //     http://www.apache.org/licenses/LICENSE-2.0
00009 //
00010 // Unless required by applicable law or agreed to in writing, software
00011 // distributed under the License is distributed on an "AS IS" BASIS,
00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 // See the License for the specific language governing permissions and
00014 // limitations under the License.
00015 // ----------------------------------------------------------------------------
00016 #include <stdbool.h>
00017 #include "key_config_manager.h"
00018 #include "storage.h"
00019 #include "pv_error_handling.h"
00020 #include "kcm_file_prefix_defs.h"
00021 #include "cs_der_certs.h"
00022 #include "cs_der_keys.h"
00023 #include "fcc_malloc.h"
00024 
00025 
00026 typedef enum {
00027     KCM_PRIVATE_KEY_DATA,
00028     KCM_PUBLIC_KEY_DATA,
00029     KCM_SYMMETRIC_KEY_DATA,
00030     KCM_CERTIFICATE_DATA,
00031     KCM_CONFIG_DATA,
00032 } kcm_data_type;
00033 
00034 static bool kcm_initialized = false;
00035 
00036 static kcm_status_e kcm_add_prefix_to_name(const uint8_t *kcm_name, size_t kcm_name_len, const char *prefix, uint8_t **kcm_buffer_out, size_t *kcm_buffer_size_allocated_out)
00037 {
00038     size_t prefix_length;
00039 
00040     SA_PV_LOG_TRACE_FUNC_ENTER("name len=%" PRIu32 "", (uint32_t)kcm_name_len);
00041 
00042     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_buffer_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_buffer_out parameter");
00043     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_buffer_size_allocated_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_buffer_size_allocated_out parameter");
00044 
00045     prefix_length = strlen(prefix);
00046 
00047     *kcm_buffer_out = (uint8_t *)fcc_malloc(kcm_name_len + prefix_length);
00048     SA_PV_ERR_RECOVERABLE_RETURN_IF((*kcm_buffer_out == NULL), KCM_STATUS_OUT_OF_MEMORY, "Failed allocating kcm_buffer_out");
00049 
00050     /* Append prefix and name to allocated buffer */
00051     memcpy(*kcm_buffer_out, (uint8_t *)prefix, prefix_length);
00052     memcpy(*kcm_buffer_out + prefix_length, kcm_name, kcm_name_len);
00053 
00054     *kcm_buffer_size_allocated_out = kcm_name_len + prefix_length;
00055 
00056     SA_PV_LOG_TRACE_FUNC_EXIT("kcm_buffer_size_allocated_out=  %" PRIu32 "", (uint32_t)*kcm_buffer_size_allocated_out);
00057     return KCM_STATUS_SUCCESS;
00058 }
00059 
00060 
00061 static kcm_status_e kcm_item_name_get_prefix(kcm_item_type_e kcm_item_type, const char** prefix)
00062 {
00063     kcm_status_e status = KCM_STATUS_SUCCESS;
00064 
00065     switch (kcm_item_type) {
00066         case KCM_PRIVATE_KEY_ITEM:
00067             *prefix = KCM_FILE_PREFIX_PRIVATE_KEY;
00068             break;
00069         case KCM_PUBLIC_KEY_ITEM:
00070             *prefix = KCM_FILE_PREFIX_PUBLIC_KEY;
00071             break;
00072         case KCM_SYMMETRIC_KEY_ITEM:
00073             *prefix = KCM_FILE_PREFIX_SYMMETRIC_KEY;
00074             break;
00075         case KCM_CERTIFICATE_ITEM:
00076             *prefix = KCM_FILE_PREFIX_CERTIFICATE;
00077             break;
00078         case KCM_CONFIG_ITEM:
00079             *prefix = KCM_FILE_PREFIX_CONFIG_PARAM;
00080             break;
00081         case KCM_CERTIFICATE_CHAIN_ITEM:
00082             *prefix = KCM_FILE_PREFIX_CERTIFICATE_CHAIN;
00083             break;
00084         default:
00085             status = KCM_STATUS_INVALID_PARAMETER;
00086             break;
00087     }
00088     return status;
00089 }
00090 
00091 kcm_status_e kcm_init(void)
00092 {
00093     kcm_status_e status = KCM_STATUS_SUCCESS;
00094 
00095     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00096 
00097     if (!kcm_initialized) {
00098         status = storage_init();
00099         SA_PV_ERR_RECOVERABLE_RETURN_IF((status != KCM_STATUS_SUCCESS), status, "Failed initializing storage\n");
00100         kcm_initialized = true;
00101     }
00102 
00103     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00104 
00105     return status;
00106 }
00107 
00108 kcm_status_e kcm_finalize(void)
00109 {
00110     kcm_status_e status = KCM_STATUS_SUCCESS;
00111 
00112     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00113 
00114     if (kcm_initialized) {
00115         status = storage_finalize();
00116         SA_PV_ERR_RECOVERABLE_RETURN_IF((status != KCM_STATUS_SUCCESS), status, "Failed finalizing storage\n");
00117         kcm_initialized = false;
00118     }
00119 
00120     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00121 
00122     return status;
00123 }
00124 
00125 kcm_status_e kcm_item_store(const uint8_t * kcm_item_name, size_t kcm_item_name_len, kcm_item_type_e kcm_item_type, bool kcm_item_is_factory, const uint8_t * kcm_item_data, size_t kcm_item_data_size, const kcm_security_desc_s security_desc)
00126 {
00127     kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
00128     kcm_ctx_s ctx;
00129     uint8_t *kcm_complete_name = NULL; // Filename including prefix
00130     size_t kcm_complete_name_size;
00131     const char *prefix;
00132     bool kcm_item_is_encrypted = true; //encrypt by default
00133 
00134     SA_PV_LOG_INFO_FUNC_ENTER("item name =  %.*s len=%" PRIu32 ", data size=%" PRIu32 "", (int)kcm_item_name_len, (char*)kcm_item_name, (uint32_t)kcm_item_name_len, (uint32_t)kcm_item_data_size);
00135 
00136     // Check if KCM initialized, if not initialize it
00137     if (!kcm_initialized) {
00138         kcm_status = kcm_init();
00139         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00140     }
00141 
00142 
00143     // Validate function parameters
00144     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name");
00145     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name_len");
00146     SA_PV_ERR_RECOVERABLE_RETURN_IF(((kcm_item_data == NULL) && (kcm_item_data_size > 0)), KCM_STATUS_INVALID_PARAMETER, "Provided kcm_item_data NULL and kcm_item_data_size greater than 0");
00147 
00148     //temporary check that security descriptor is NULL
00149     SA_PV_ERR_RECOVERABLE_RETURN_IF((security_desc != NULL), KCM_STATUS_INVALID_PARAMETER, "Security descriptor is not NULL!");
00150     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_type != KCM_CONFIG_ITEM && kcm_item_data_size == 0), KCM_STATUS_ITEM_IS_EMPTY, "The data of current item is empty!");
00151 
00152     switch (kcm_item_type) {
00153         case KCM_PRIVATE_KEY_ITEM:
00154             kcm_status = cs_der_priv_key_verify(kcm_item_data, kcm_item_data_size);
00155             SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Private key validation failed");
00156             break;
00157         case KCM_PUBLIC_KEY_ITEM:
00158             kcm_status = cs_der_public_key_verify(kcm_item_data, kcm_item_data_size);
00159             SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Public key validation failed");
00160             kcm_item_is_encrypted = false; //do not encrypt public key
00161             break;
00162         case KCM_SYMMETRIC_KEY_ITEM:
00163             //currently possible to write a symmetric key of size 0 since we do not check format
00164             break;
00165         case KCM_CERTIFICATE_ITEM:
00166             kcm_status = cs_parse_der_x509_cert(kcm_item_data, kcm_item_data_size);
00167             SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Certificate validation failed");
00168             kcm_item_is_encrypted = false; //do not encrypt certificates
00169             break;
00170         case KCM_CONFIG_ITEM:
00171             break;
00172         default:
00173             SA_PV_ERR_RECOVERABLE_RETURN_IF((true), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type");
00174     }
00175 
00176     kcm_status = kcm_item_name_get_prefix(kcm_item_type, &prefix);
00177     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed during kcm_item_name_get_prefix");
00178 
00179     kcm_status = kcm_add_prefix_to_name(kcm_item_name, kcm_item_name_len, prefix, &kcm_complete_name, &kcm_complete_name_size);
00180     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed during kcm_add_prefix_to_name");
00181 
00182     kcm_status = storage_file_write(&ctx, kcm_complete_name, kcm_complete_name_size, kcm_item_data, kcm_item_data_size, kcm_item_is_factory, kcm_item_is_encrypted);
00183     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed writing file to storage");
00184 
00185 Exit:
00186     fcc_free(kcm_complete_name);
00187     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00188 
00189     return kcm_status;
00190 }
00191 
00192 
00193 kcm_status_e kcm_item_get_data_size(const uint8_t *kcm_item_name, size_t kcm_item_name_len, kcm_item_type_e kcm_item_type, size_t *kcm_item_data_size_out)
00194 {
00195     kcm_status_e status = KCM_STATUS_SUCCESS;
00196     uint8_t *kcm_complete_name = NULL; // Filename including prefix
00197     size_t kcm_complete_name_size;
00198     kcm_ctx_s ctx;
00199     size_t kcm_data_size = 0;
00200     const char *prefix;
00201 
00202     SA_PV_LOG_INFO_FUNC_ENTER("item name = %.*s len=%" PRIu32 "", (int)kcm_item_name_len, (char*)kcm_item_name, (uint32_t)kcm_item_name_len);
00203 
00204     // Check if KCM initialized, if not initialize it
00205     if (!kcm_initialized) {
00206         status = kcm_init();
00207         SA_PV_ERR_RECOVERABLE_RETURN_IF((status != KCM_STATUS_SUCCESS), status, "KCM initialization failed\n");
00208     }
00209 
00210     // Validate function parameters
00211     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name");
00212     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name_len");
00213     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_type >= KCM_LAST_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type");
00214     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_data_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Kcm size out pointer is NULL");
00215 
00216     status = kcm_item_name_get_prefix(kcm_item_type, &prefix);
00217     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != KCM_STATUS_SUCCESS), (status = status), Exit, "Failed during kcm_item_name_get_prefix");
00218 
00219     status = kcm_add_prefix_to_name(kcm_item_name, kcm_item_name_len, prefix, &kcm_complete_name, &kcm_complete_name_size);
00220     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != KCM_STATUS_SUCCESS), (status = status), Exit, "Failed during kcm_add_prefix_to_name");
00221 
00222     status = storage_file_size_get(&ctx, kcm_complete_name, kcm_complete_name_size, &kcm_data_size);
00223     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != KCM_STATUS_SUCCESS), (status = status), Exit, "Failed in getting file size");
00224 
00225     *kcm_item_data_size_out = kcm_data_size;
00226     SA_PV_LOG_INFO_FUNC_EXIT("kcm data size = %" PRIu32 "", (uint32_t)*kcm_item_data_size_out);
00227 Exit:
00228     fcc_free(kcm_complete_name);
00229 
00230     return status;
00231 }
00232 
00233 
00234 kcm_status_e kcm_item_get_data(const uint8_t * kcm_item_name, size_t kcm_item_name_len, kcm_item_type_e kcm_item_type, uint8_t * kcm_item_data_out, size_t kcm_item_data_max_size, size_t * kcm_item_data_act_size_out)
00235 {
00236     kcm_status_e status = KCM_STATUS_SUCCESS;
00237     uint8_t *kcm_complete_name = NULL; // Filename including prefix
00238     size_t kcm_complete_name_size;
00239     kcm_ctx_s ctx;
00240     const char *prefix;
00241 
00242     SA_PV_LOG_INFO_FUNC_ENTER("item name = %.*s len = %" PRIu32 ", data max size = %" PRIu32 "", (int)kcm_item_name_len, (char*)kcm_item_name, (uint32_t)kcm_item_name_len, (uint32_t)kcm_item_data_max_size);
00243 
00244     // Check if KCM initialized, if not initialize it
00245     if (!kcm_initialized) {
00246         status = kcm_init();
00247         SA_PV_ERR_RECOVERABLE_RETURN_IF((status != KCM_STATUS_SUCCESS), status, "KCM initialization failed\n");
00248     }
00249 
00250     // Validate function parameters
00251     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name");
00252     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name_len");
00253     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_type >= KCM_LAST_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type");
00254     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_data_act_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_data_act_size_out");
00255     SA_PV_ERR_RECOVERABLE_RETURN_IF(((kcm_item_data_out == NULL) && (kcm_item_data_max_size > 0)), KCM_STATUS_INVALID_PARAMETER, "Provided kcm_item_data NULL and kcm_item_data_size greater than 0");
00256 
00257     memset(&ctx, 0, sizeof(ctx));
00258     status = kcm_item_name_get_prefix(kcm_item_type, &prefix);
00259     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != KCM_STATUS_SUCCESS), (status = status), Exit, "Failed during kcm_item_name_get_prefix");
00260 
00261     status = kcm_add_prefix_to_name(kcm_item_name, kcm_item_name_len, prefix, &kcm_complete_name, &kcm_complete_name_size);
00262     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != KCM_STATUS_SUCCESS), (status = status), Exit, "Failed during kcm_add_prefix_to_name");
00263 
00264     status = storage_file_read(&ctx, kcm_complete_name, kcm_complete_name_size, kcm_item_data_out, kcm_item_data_max_size, kcm_item_data_act_size_out);
00265     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != KCM_STATUS_SUCCESS), (status = status), Exit, "Failed reading file from storage (%d)", status);
00266 
00267     SA_PV_LOG_INFO_FUNC_EXIT("kcm data size = %" PRIu32 "", (uint32_t)*kcm_item_data_act_size_out);
00268 Exit:
00269     fcc_free(kcm_complete_name);
00270 
00271     return status;
00272 }
00273 
00274 
00275 kcm_status_e kcm_item_delete(const uint8_t * kcm_item_name, size_t kcm_item_name_len, kcm_item_type_e kcm_item_type)
00276 {
00277     kcm_status_e status = KCM_STATUS_SUCCESS;
00278     uint8_t *kcm_complete_name = NULL; // Filename including prefix
00279     size_t kcm_complete_name_size;
00280     kcm_ctx_s ctx; // FIXME - Currently not implemented
00281     const char *prefix;
00282 
00283     SA_PV_LOG_INFO_FUNC_ENTER("item name = %.*s len = %" PRIu32 "", (int)kcm_item_name_len, (char*)kcm_item_name, (uint32_t)kcm_item_name_len);
00284 
00285     // Check if KCM initialized, if not initialize it
00286     if (!kcm_initialized) {
00287         status = kcm_init();
00288         SA_PV_ERR_RECOVERABLE_RETURN_IF((status != KCM_STATUS_SUCCESS), status, "KCM initialization failed\n");
00289     }
00290 
00291     // Validate function parameters
00292     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name");
00293     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name_len");
00294     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_type >= KCM_LAST_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type");
00295 
00296     status = kcm_item_name_get_prefix(kcm_item_type, &prefix);
00297     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != KCM_STATUS_SUCCESS), (status = status), Exit, "Failed during kcm_item_name_get_prefix");
00298 
00299     status = kcm_add_prefix_to_name(kcm_item_name, kcm_item_name_len, prefix, &kcm_complete_name, &kcm_complete_name_size);
00300     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != KCM_STATUS_SUCCESS), (status = status), Exit, "Failed during kcm_add_prefix_to_name");
00301 
00302     status = storage_file_delete(&ctx, kcm_complete_name, kcm_complete_name_size);
00303     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != KCM_STATUS_SUCCESS), (status = status), Exit, "Failed deleting kcm data");
00304 
00305 Exit:
00306     fcc_free(kcm_complete_name);
00307     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00308 
00309     return status;
00310 }
00311 
00312 kcm_status_e kcm_factory_reset(void)
00313 {
00314     kcm_status_e status = KCM_STATUS_SUCCESS;
00315 
00316     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00317 
00318     // Check if KCM initialized, if not initialize it
00319     if (!kcm_initialized) {
00320         status = kcm_init();
00321         SA_PV_ERR_RECOVERABLE_RETURN_IF((status != KCM_STATUS_SUCCESS), status, "KCM initialization failed\n");
00322     }
00323 
00324     status = storage_factory_reset();
00325     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != KCM_STATUS_SUCCESS), (status = status), Exit, "Failed perform factory reset");
00326 
00327 Exit:
00328     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00329     return status;
00330 }
00331