Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
arm_uc_certificate_kcm_api.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 "update-client-common/arm_uc_crypto.h" 00020 #if defined(ARM_UC_FEATURE_CERT_STORE_KCM) && (ARM_UC_FEATURE_CERT_STORE_KCM == 1) 00021 00022 #include "update-client-control-center/arm_uc_certificate.h" 00023 #include "update-client-common/arm_uc_config.h" 00024 #include "update-client-metadata-header/arm_uc_buffer_utilities.h" 00025 #include "key-config-manager/key_config_manager.h" 00026 00027 static arm_uc_error_t kerr2ucerr(int kerr) 00028 { 00029 arm_uc_error_t err; 00030 switch (kerr) { 00031 case KCM_STATUS_SUCCESS: 00032 err.code = ERR_NONE; 00033 break; 00034 case KCM_STATUS_INVALID_PARAMETER: 00035 err.code = ARM_UC_CM_ERR_INVALID_PARAMETER; 00036 break; 00037 case KCM_STATUS_ITEM_NOT_FOUND: 00038 case KCM_STATUS_ESFS_ERROR: 00039 err.code = ARM_UC_CM_ERR_NOT_FOUND; 00040 break; 00041 case KCM_CRYPTO_STATUS_PARSING_DER_CERT: 00042 err.code = ARM_UC_CM_ERR_INVALID_CERT; 00043 break; 00044 case KCM_STATUS_OUT_OF_MEMORY: 00045 case KCM_STATUS_INSUFFICIENT_BUFFER: 00046 default: 00047 err.modulecc[0] = 'K'; 00048 err.modulecc[1] = 'C'; 00049 err.error = kerr; 00050 break; 00051 } 00052 return err; 00053 } 00054 00055 static arm_uc_error_t arm_uc_kcm_cert_fetcher(arm_uc_buffer_t *certificate, 00056 const arm_uc_buffer_t *fingerprint, 00057 const arm_uc_buffer_t *DERCertificateList, 00058 void (*callback)(arm_uc_error_t, const arm_uc_buffer_t *, const arm_uc_buffer_t *)) 00059 { 00060 uint8_t certName[MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_NAME_SIZE] = MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_DEFAULT; 00061 // uint8_t certName[MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_NAME_SIZE] = MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_PREFIX; 00062 // uint8_t* b64hash = &certName[sizeof(MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_PREFIX)-1]; 00063 // uint8_t defaultInUse = 0; 00064 00065 UC_CONT_TRACE("Attempting to fetch certificate from: %s", certName); 00066 // Format the certificate name into the certName buffer 00067 // ARM_UC_Base64Enc(b64hash, sizeof(b64hash), fingerprint); 00068 00069 // The arm_uc_buffer_t's size variable is 32bit, but kcm_item_get_data() needs 00070 // a pointer to size_t, so we need to use a temp variable for it or we would get 00071 // a corrupted arm_uc_buffer_t structure. 00072 size_t cert_data_size = 0; 00073 00074 // Look up the certificate by fingerprint 00075 kcm_status_e kerr = kcm_item_get_data(certName, 00076 strlen((char *)certName), 00077 KCM_CERTIFICATE_ITEM, 00078 certificate->ptr, 00079 certificate->size_max, 00080 &cert_data_size); 00081 00082 // Check if the certificate was found. 00083 // if (kerr == KCM_STATUS_ITEM_NOT_FOUND || kerr == KCM_STATUS_ESFS_ERROR) 00084 // { 00085 // printf("fingerprinted certificate not found. Checking for default...\n"); 00086 // // If not, try the default location. 00087 // kerr = kcm_item_get_data(MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_DEFAULT, 00088 // sizeof(MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_DEFAULT) - 1, 00089 // KCM_CERTIFICATE_ITEM, 00090 // certificate->ptr, 00091 // certificate->size_max, 00092 // &cert_data_size); 00093 // defaultInUse = 1; 00094 // } 00095 // Translate the KCM error to an update client error 00096 arm_uc_error_t err = kerr2ucerr(kerr); 00097 arm_uc_error_t errFinish = {ARM_UC_CM_ERR_INVALID_PARAMETER}; 00098 00099 // Prepare to calculate the fingerprint of the certificate. 00100 arm_uc_mdHandle_t h = { 0 }; 00101 uint8_t fingerprintLocal[MBED_CLOUD_SHA256_BYTES]; 00102 arm_uc_buffer_t fingerprintLocalBuffer = { 00103 .size_max = sizeof(fingerprintLocal), 00104 .size = 0, 00105 .ptr = fingerprintLocal 00106 }; 00107 00108 // Check for overflow before continuing. This is actually unnecessary 00109 // belts and suspenders type of code, as the max value given to kcm_item_get_data() 00110 // is at most UINT32_MAX, but the Coverity might point this as a error. 00111 if (cert_data_size <= UINT32_MAX) { 00112 certificate->size = (uint32_t)cert_data_size; 00113 } else { 00114 err.code = ARM_UC_CM_ERR_INVALID_CERT; 00115 } 00116 00117 // Calculate the fingerprint of the certificate 00118 if (err.error == ERR_NONE) { 00119 err = ARM_UC_cryptoHashSetup(&h, ARM_UC_CU_SHA256); 00120 } 00121 if (err.error == ERR_NONE) { 00122 err = ARM_UC_cryptoHashUpdate(&h, certificate); 00123 00124 // The cryptoHashFinish needs to be called no matter if the update succeeded or not as 00125 // it will do memory freeing. But in order to have valid result, the update & finish 00126 // must both have succeeded. 00127 errFinish = ARM_UC_cryptoHashFinish(&h, &fingerprintLocalBuffer); 00128 00129 // Compare the calculated fingerprint to the requested fingerprint. 00130 if ((err.error == ERR_NONE) && (errFinish.error == ERR_NONE)) { 00131 uint32_t rc = ARM_UC_BinCompareCT(fingerprint, &fingerprintLocalBuffer); 00132 if (rc) { 00133 err.code = ARM_UC_CM_ERR_NOT_FOUND; 00134 } else { 00135 UC_CONT_TRACE("Certificate lookup fingerprint matched."); 00136 err.code = ERR_NONE; 00137 } 00138 00139 if (callback && (err.error == ERR_NONE)) { 00140 callback(err, certificate, fingerprint); 00141 } 00142 } 00143 } 00144 00145 return err; 00146 } 00147 00148 static arm_uc_error_t arm_uc_kcm_cert_storer( 00149 const arm_uc_buffer_t *cert, 00150 const arm_uc_buffer_t *fingerprint, 00151 void(*callback)(arm_uc_error_t, const arm_uc_buffer_t *)) 00152 { 00153 // uint8_t certName[MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_NAME_SIZE] = MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_PREFIX; 00154 // uint8_t* b64hash = &certName[sizeof(MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_PREFIX)-1]; 00155 uint8_t certName[MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_NAME_SIZE] = MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_DEFAULT; 00156 00157 UC_CONT_TRACE("Storing certificate to: %s\n", certName); 00158 // ARM_UC_Base64Enc(b64hash, sizeof(b64hash), fingerprint); 00159 00160 kcm_status_e kerr = kcm_item_store(certName, 00161 strlen((char *) certName), 00162 KCM_CERTIFICATE_ITEM, 00163 true, 00164 cert->ptr, 00165 cert->size, 00166 NULL); 00167 00168 arm_uc_error_t err = kerr2ucerr(kerr); 00169 00170 if (callback && (err.code == ERR_NONE)) { 00171 callback(err, fingerprint); 00172 } 00173 00174 return err; 00175 } 00176 00177 const struct arm_uc_certificate_api arm_uc_certificate_kcm_api = { 00178 .fetch = arm_uc_kcm_cert_fetcher, 00179 .store = arm_uc_kcm_cert_storer 00180 }; 00181 00182 #endif /* ARM_UC_FEATURE_CERT_STORE_KCM */
Generated on Mon Aug 29 2022 19:53:37 by
