Simple interface for Mbed Cloud Client
Embed:
(wiki syntax)
Show/hide line numbers
arm_uc_crypto.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_config.h" 00020 #include "update-client-common/arm_uc_error.h" 00021 #include "update-client-common/arm_uc_crypto.h" 00022 00023 #include <string.h> 00024 00025 00026 #if ARM_UC_USE_PAL_CRYPTO 00027 #include "pal.h" 00028 #include "sotp.h" 00029 #ifndef palMDHandle_t 00030 #include "pal_Crypto.h" 00031 #else 00032 #include "mbedtls/md.h" 00033 #endif 00034 00035 #define ARM_UC_CU_SHA256 PAL_SHA256 00036 arm_uc_error_t ARM_UC_verifyPkSignature(const arm_uc_buffer_t* ca, const arm_uc_buffer_t* hash, const arm_uc_buffer_t* sig) 00037 { 00038 arm_uc_error_t err = {MFST_ERR_CERT_INVALID}; 00039 palX509Handle_t x509Cert; 00040 if (PAL_SUCCESS == pal_x509Initiate(&x509Cert)) 00041 { 00042 err.code = MFST_ERR_CERT_INVALID; 00043 if (PAL_SUCCESS == pal_x509CertParse(x509Cert, ca->ptr, ca->size)) 00044 { 00045 // if (PAL_SUCCESS == pal_x509CertVerify(x509Cert, palX509Handle_t x509CertChain)) 00046 // { 00047 err.code = MFST_ERR_INVALID_SIGNATURE; 00048 if (PAL_SUCCESS == pal_verifySignature(x509Cert, PAL_SHA256, hash->ptr, hash->size, sig->ptr, sig->size)) 00049 { 00050 err.code = MFST_ERR_NONE; 00051 } 00052 // } 00053 } 00054 pal_x509Free(&x509Cert); 00055 } 00056 return err; 00057 } 00058 00059 arm_uc_error_t ARM_UC_cryptoHashSetup(arm_uc_mdHandle_t* hDigest, arm_uc_mdType_t mdType) 00060 { 00061 arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER }; 00062 if (hDigest) 00063 { 00064 palStatus_t rc = pal_mdInit(hDigest, mdType); 00065 if (rc == PAL_SUCCESS) 00066 { 00067 result.code = ARM_UC_CU_ERR_NONE; 00068 } 00069 } 00070 return result; 00071 } 00072 00073 arm_uc_error_t ARM_UC_cryptoHashUpdate(arm_uc_mdHandle_t* hDigest, arm_uc_buffer_t* input) 00074 { 00075 arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER }; 00076 if (hDigest && input) 00077 { 00078 palStatus_t rc = pal_mdUpdate(*hDigest, input->ptr, input->size); 00079 if (rc == PAL_SUCCESS) 00080 { 00081 result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE }; 00082 } 00083 } 00084 return result; 00085 } 00086 00087 arm_uc_error_t ARM_UC_cryptoHashFinish(arm_uc_mdHandle_t* hDigest, arm_uc_buffer_t* output) 00088 { 00089 arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER }; 00090 00091 // TODO: validate buffer size? I guess we just hope for the best! 00092 if (hDigest && output && output->size_max >= 256/8) // FIXME:PAL does not provide a method to extract this 00093 { 00094 palStatus_t rc = pal_mdFinal(*hDigest, output->ptr); 00095 00096 if (rc == PAL_SUCCESS) 00097 { 00098 result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE }; 00099 output->size = 256/8; // FIXME:PAL does not provide a method to extract this 00100 } 00101 } 00102 if (hDigest) 00103 { 00104 palStatus_t rc = pal_mdFree(hDigest); 00105 if (rc != PAL_SUCCESS && result.error == ERR_NONE) 00106 { 00107 result.module = TWO_CC('P','A'); 00108 result.error = rc; 00109 } 00110 } 00111 return result; 00112 } 00113 00114 arm_uc_error_t ARM_UC_cryptoDecryptSetup(arm_uc_cipherHandle_t* hCipher, arm_uc_buffer_t* key, arm_uc_buffer_t* iv, int32_t aesKeySize) 00115 { 00116 arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER }; 00117 00118 if (key && key->ptr && iv && iv->ptr) 00119 { 00120 palStatus_t rc = 1; 00121 00122 switch (aesKeySize) 00123 { 00124 case 128: 00125 case 256: 00126 { 00127 rc = pal_initAes(&hCipher->aes_context); 00128 /* NOTE: From the mbedtls documentation: 00129 * Due to the nature of CTR you should use the same key schedule for 00130 * both encryption and decryption. So a context initialized with 00131 * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT. 00132 */ 00133 if (rc == PAL_SUCCESS) 00134 { 00135 rc = pal_setAesKey(hCipher->aes_context, key->ptr, aesKeySize, PAL_KEY_TARGET_ENCRYPTION); 00136 } 00137 hCipher->aes_iv = iv->ptr; 00138 break; 00139 } 00140 default: 00141 // rc is still 1, this means the function returns Invalid Parameter 00142 break; 00143 } 00144 00145 if (rc == PAL_SUCCESS) 00146 { 00147 result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE }; 00148 } 00149 } 00150 00151 return result; 00152 } 00153 00154 arm_uc_error_t ARM_UC_cryptoDecryptUpdate(arm_uc_cipherHandle_t* hCipher, const uint8_t* input_ptr, uint32_t input_size, arm_uc_buffer_t* output) 00155 { 00156 arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER }; 00157 size_t data_size = input_size < output->size_max ? input_size : output->size_max; 00158 output->size = 0; 00159 palStatus_t rc = pal_aesCTR( 00160 hCipher->aes_context, 00161 input_ptr, 00162 output->ptr, 00163 data_size, 00164 hCipher->aes_iv 00165 ); 00166 if (rc == PAL_SUCCESS) 00167 { 00168 result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE }; 00169 output->size = data_size; 00170 } 00171 return result; 00172 } 00173 00174 arm_uc_error_t ARM_UC_cryptoDecryptFinish(arm_uc_cipherHandle_t* hCipher, arm_uc_buffer_t* output) 00175 { 00176 pal_freeAes(&hCipher->aes_context); 00177 (void) output; 00178 return (arm_uc_error_t){ARM_UC_CU_ERR_NONE}; 00179 } 00180 00181 arm_uc_error_t ARM_UC_cryptoHMACSHA256(arm_uc_buffer_t* key, 00182 arm_uc_buffer_t* input, 00183 arm_uc_buffer_t* output) 00184 { 00185 arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER }; 00186 00187 palStatus_t pal_st = pal_mdHmacSha256(key->ptr, key->size, 00188 input->ptr, input->size, 00189 output->ptr, &(output->size)); 00190 if ((pal_st == PAL_SUCCESS) && (output->size == ARM_UC_SHA256_SIZE)) 00191 { 00192 result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE }; 00193 } 00194 00195 return result; 00196 } 00197 00198 int8_t mbed_cloud_client_get_rot_128bit(uint8_t *key_buf, uint32_t length) 00199 { 00200 int8_t rv = -1; 00201 palStatus_t status = PAL_ERR_GENERIC_FAILURE; 00202 00203 #if (PAL_USE_HW_ROT) 00204 status = pal_plat_osGetRoTFromHW (key_buf, length); 00205 #else 00206 uint16_t actual_size; 00207 00208 sotp_result_e sotp_status = sotp_get(SOTP_TYPE_ROT, length, (uint32_t *)key_buf, &actual_size); 00209 if (SOTP_SUCCESS == sotp_status && actual_size == ARM_UC_ROT_SIZE) 00210 { 00211 status = PAL_SUCCESS; 00212 } 00213 #endif 00214 00215 if (status == PAL_SUCCESS) 00216 { 00217 rv = 0; 00218 } 00219 else 00220 { 00221 /* clear buffer on failure so we don't leak the rot */ 00222 memset(key_buf, 0, length); 00223 } 00224 00225 return rv; 00226 } 00227 00228 #else 00229 00230 arm_uc_error_t ARM_UC_verifyPkSignature(const arm_uc_buffer_t* ca, const arm_uc_buffer_t* hash, const arm_uc_buffer_t* sig) 00231 { 00232 arm_uc_error_t err = {MFST_ERR_NONE}; 00233 mbedtls_x509_crt crt; 00234 mbedtls_x509_crt_init(&crt); 00235 int rc = mbedtls_x509_crt_parse_der(&crt, ca->ptr, ca->size); 00236 if (rc < 0) { 00237 err.code = MFST_ERR_CERT_INVALID; 00238 } else { 00239 rc = mbedtls_pk_verify(&crt.pk, MBEDTLS_MD_SHA256, hash->ptr, hash->size, sig->ptr, sig->size); 00240 if (rc < 0) { 00241 err.code = MFST_ERR_INVALID_SIGNATURE; 00242 } 00243 } 00244 return err; 00245 } 00246 00247 arm_uc_error_t ARM_UC_cryptoHashSetup(arm_uc_mdHandle_t* hDigest, arm_uc_mdType_t mdType) 00248 { 00249 arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER }; 00250 00251 const mbedtls_md_info_t* md_info = NULL; 00252 00253 if (hDigest) 00254 { 00255 mbedtls_md_init(hDigest); 00256 md_info = mbedtls_md_info_from_type(mdType); 00257 int mbedtls_result = mbedtls_md_setup(hDigest, md_info, 0); 00258 mbedtls_result |= mbedtls_md_starts(hDigest); 00259 00260 if (mbedtls_result == 0) 00261 { 00262 result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE }; 00263 } 00264 } 00265 00266 return result; 00267 } 00268 00269 arm_uc_error_t ARM_UC_cryptoHashUpdate(arm_uc_mdHandle_t* hDigest, arm_uc_buffer_t* input) 00270 { 00271 arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER }; 00272 00273 if (hDigest && input) 00274 { 00275 int mbedtls_result = mbedtls_md_update(hDigest, input->ptr, input->size); 00276 00277 if (mbedtls_result == 0) 00278 { 00279 result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE }; 00280 } 00281 } 00282 00283 return result; 00284 } 00285 00286 arm_uc_error_t ARM_UC_cryptoHashFinish(arm_uc_mdHandle_t* hDigest, arm_uc_buffer_t* output) 00287 { 00288 arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER }; 00289 00290 if (hDigest && output && (output->size_max >= (unsigned)hDigest->md_info->size)) 00291 { 00292 int mbedtls_result = mbedtls_md_finish(hDigest, output->ptr); 00293 00294 if (mbedtls_result == 0) 00295 { 00296 result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE }; 00297 00298 output->size = hDigest->md_info->size; 00299 } 00300 } 00301 00302 // free memory 00303 mbedtls_md_free(hDigest); 00304 00305 return result; 00306 } 00307 00308 arm_uc_error_t ARM_UC_cryptoDecryptSetup(arm_uc_cipherHandle_t* hCipher, arm_uc_buffer_t* key, arm_uc_buffer_t* iv, int32_t aesKeySize) 00309 { 00310 arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER }; 00311 00312 if (key && key->ptr && iv && iv->ptr) 00313 { 00314 int mbedtls_result = 1; 00315 00316 switch (aesKeySize) 00317 { 00318 case 128: 00319 case 256: 00320 { 00321 memset(hCipher->aes_partial, 0, sizeof(hCipher->aes_partial)); 00322 hCipher->aes_nc_off = 0; 00323 mbedtls_aes_init(&hCipher->aes_context); 00324 /* NOTE: From the mbedtls documentation: 00325 * Due to the nature of CTR you should use the same key schedule for 00326 * both encryption and decryption. So a context initialized with 00327 * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT. 00328 */ 00329 mbedtls_result = mbedtls_aes_setkey_enc(&hCipher->aes_context, key->ptr, aesKeySize); 00330 hCipher->aes_iv = iv->ptr; 00331 break; 00332 } 00333 default: 00334 // mbedtls_result is still 1, this means the function returns Invalid Parameter 00335 break; 00336 } 00337 00338 if (mbedtls_result == 0) 00339 { 00340 result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE }; 00341 } 00342 } 00343 00344 return result; 00345 } 00346 00347 arm_uc_error_t ARM_UC_cryptoDecryptUpdate(arm_uc_cipherHandle_t* hCipher, const uint8_t* input_ptr, uint32_t input_size, arm_uc_buffer_t* output) 00348 { 00349 arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER }; 00350 size_t data_size = input_size < output->size_max ? input_size : output->size_max; 00351 output->size = 0; 00352 int mbedtls_result = mbedtls_aes_crypt_ctr( 00353 &hCipher->aes_context, 00354 data_size, 00355 &hCipher->aes_nc_off, 00356 hCipher->aes_iv, 00357 hCipher->aes_partial, 00358 input_ptr, 00359 output->ptr 00360 00361 ); 00362 if (mbedtls_result == 0) 00363 { 00364 result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE }; 00365 output->size = data_size; 00366 } 00367 return result; 00368 } 00369 00370 arm_uc_error_t ARM_UC_cryptoDecryptFinish(arm_uc_cipherHandle_t* hCipher, arm_uc_buffer_t* output) 00371 { 00372 (void) output; 00373 return (arm_uc_error_t){ARM_UC_CU_ERR_NONE}; 00374 } 00375 00376 arm_uc_error_t ARM_UC_cryptoHMACSHA256(arm_uc_buffer_t* key, 00377 arm_uc_buffer_t* input, 00378 arm_uc_buffer_t* output) 00379 { 00380 arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER }; 00381 00382 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); 00383 if (md_info != NULL) 00384 { 00385 int8_t rv = mbedtls_md_hmac(md_info, 00386 key->ptr, key->size, 00387 input->ptr, input->size, 00388 output->ptr); 00389 if (rv == 0) 00390 { 00391 output->size = ARM_UC_SHA256_SIZE; 00392 result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE }; 00393 } 00394 } 00395 00396 return result; 00397 } 00398 00399 #endif 00400 00401 arm_uc_error_t ARM_UC_getDeviceKey256Bit(arm_uc_buffer_t* output) 00402 { 00403 arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER }; 00404 00405 if (output->size_max >= ARM_UC_DEVICE_KEY_SIZE) 00406 { 00407 int8_t rv = mbed_cloud_client_get_rot_128bit(output->ptr, output->size_max); 00408 if (rv == 0) 00409 { 00410 arm_uc_buffer_t input = { 00411 .size_max = ARM_UC_DEVICE_HMAC_KEY_SIZE, 00412 .size = ARM_UC_DEVICE_HMAC_KEY_SIZE, 00413 .ptr = (uint8_t *) &ARM_UC_DEVICE_HMAC_KEY 00414 }; 00415 output->size = ARM_UC_ROT_SIZE; 00416 #if defined(PAL_DEVICE_KEY_DERIVATION_BACKWARD_COMPATIBILITY_CALC) && \ 00417 (PAL_DEVICE_KEY_DERIVATION_BACKWARD_COMPATIBILITY_CALC == 1) 00418 result = ARM_UC_cryptoHMACSHA256(&input, output, output); 00419 #else 00420 result = ARM_UC_cryptoHMACSHA256(output, &input, output); 00421 #endif 00422 } 00423 } 00424 00425 if (result.code != ARM_UC_CU_ERR_NONE) 00426 { 00427 /* clear buffer on failure so we don't leak the rot */ 00428 memset(output->ptr, 0, output->size_max); 00429 } 00430 00431 return result; 00432 }
Generated on Tue Jul 12 2022 19:01:32 by 1.7.2