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