Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_uc_crypto.c Source File

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 }