Mbed Cloud example program for workshop in W27 2018.

Dependencies:   MMA7660 LM75B

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 #ifndef palMDHandle_t
00029 #include "pal_Crypto.h"
00030 #endif
00031 
00032 #define ARM_UC_CU_SHA256 PAL_SHA256
00033 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)
00034 {
00035     arm_uc_error_t err = {MFST_ERR_CERT_INVALID};
00036     palX509Handle_t x509Cert;
00037     if (PAL_SUCCESS == pal_x509Initiate(&x509Cert))
00038     {
00039         err.code = MFST_ERR_CERT_INVALID;
00040         if (PAL_SUCCESS == pal_x509CertParse(x509Cert, ca->ptr, ca->size))
00041         {
00042             // if (PAL_SUCCESS == pal_x509CertVerify(x509Cert, palX509Handle_t x509CertChain))
00043             // {
00044                 err.code = MFST_ERR_INVALID_SIGNATURE;
00045                 if (PAL_SUCCESS == pal_verifySignature(x509Cert, PAL_SHA256, hash->ptr, hash->size, sig->ptr, sig->size))
00046                 {
00047                     err.code = MFST_ERR_NONE;
00048                 }
00049             // }
00050         }
00051         pal_x509Free(&x509Cert);
00052     }
00053     return err;
00054 }
00055 
00056 arm_uc_error_t ARM_UC_cryptoHashSetup(arm_uc_mdHandle_t* hDigest, arm_uc_mdType_t mdType)
00057 {
00058     arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
00059     if (hDigest)
00060     {
00061         palStatus_t rc = pal_mdInit(hDigest, mdType);
00062         if (rc == PAL_SUCCESS)
00063         {
00064             result.code = ARM_UC_CU_ERR_NONE;
00065         }
00066     }
00067     return result;
00068 }
00069 
00070 arm_uc_error_t ARM_UC_cryptoHashUpdate(arm_uc_mdHandle_t* hDigest, arm_uc_buffer_t* input)
00071 {
00072     arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
00073     if (hDigest && input)
00074     {
00075         palStatus_t rc = pal_mdUpdate(*hDigest, input->ptr, input->size);
00076         if (rc == PAL_SUCCESS)
00077         {
00078             result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
00079         }
00080     }
00081     return result;
00082 }
00083 
00084 arm_uc_error_t ARM_UC_cryptoHashFinish(arm_uc_mdHandle_t* hDigest, arm_uc_buffer_t* output)
00085 {
00086     arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
00087 
00088     // TODO: validate buffer size? I guess we just hope for the best!
00089     if (hDigest && output && output->size_max >= 256/8) // FIXME:PAL does not provide a method to extract this
00090     {
00091         palStatus_t rc = pal_mdFinal(*hDigest, output->ptr);
00092 
00093         if (rc == PAL_SUCCESS)
00094         {
00095             result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
00096             output->size = 256/8; // FIXME:PAL does not provide a method to extract this
00097         }
00098     }
00099     if (hDigest)
00100     {
00101         palStatus_t rc = pal_mdFree(hDigest);
00102         if (rc != PAL_SUCCESS && result.error == ERR_NONE)
00103         {
00104             result.module = TWO_CC('P','A');
00105             result.error  = rc;
00106         }
00107     }
00108     return result;
00109 }
00110 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)
00111 {
00112     arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
00113 
00114     if (key && key->ptr && iv && iv->ptr)
00115     {
00116         palStatus_t rc = 1;
00117 
00118         switch (aesKeySize)
00119         {
00120             case 128:
00121             case 256:
00122             {
00123                 rc = pal_initAes(&hCipher->aes_context);
00124                 /* NOTE: From the mbedtls documentation:
00125                  * Due to the nature of CTR you should use the same key schedule for
00126                  * both encryption and decryption. So a context initialized with
00127                  * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
00128                  */
00129                 if (rc == PAL_SUCCESS)
00130                 {
00131                     rc = pal_setAesKey(hCipher->aes_context, key->ptr, aesKeySize, PAL_KEY_TARGET_DECRYPTION);
00132                 }
00133                 hCipher->aes_iv = iv->ptr;
00134                 break;
00135             }
00136             default:
00137                 // rc is still 1, this means the function returns Invalid Parameter
00138                 break;
00139         }
00140 
00141         if (rc == PAL_SUCCESS)
00142         {
00143             result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
00144         }
00145     }
00146 
00147     return result;
00148 }
00149 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)
00150 {
00151     arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
00152     size_t data_size = input_size < output->size_max ? input_size : output->size_max;
00153     output->size = 0;
00154     palStatus_t rc = pal_aesCTR(
00155         hCipher->aes_context,
00156         input_ptr,
00157         output->ptr,
00158         data_size,
00159         hCipher->aes_iv
00160     );
00161     if (rc == PAL_SUCCESS)
00162     {
00163         result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
00164         output->size = data_size;
00165     }
00166     return result;
00167 }
00168 arm_uc_error_t ARM_UC_cryptoDecryptFinish(arm_uc_cipherHandle_t* hCipher, arm_uc_buffer_t* output)
00169 {
00170     pal_freeAes(&hCipher->aes_context);
00171     (void) output;
00172     return (arm_uc_error_t){ARM_UC_CU_ERR_NONE};
00173 }
00174 
00175 #else
00176 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)
00177 {
00178     int rc = 1;
00179     arm_uc_error_t err = {MFST_ERR_NONE};
00180     mbedtls_x509_crt crt;
00181     mbedtls_x509_crt_init(&crt);
00182     rc = mbedtls_x509_crt_parse_der(&crt, ca->ptr, ca->size);
00183     if (rc < 0) {
00184         err.code = MFST_ERR_CERT_INVALID;
00185     } else {
00186         rc = mbedtls_pk_verify(&crt.pk, MBEDTLS_MD_SHA256, hash->ptr, hash->size, sig->ptr, sig->size);
00187         if (rc < 0) {
00188             err.code = MFST_ERR_INVALID_SIGNATURE;
00189         }
00190     }
00191     return err;
00192 }
00193 arm_uc_error_t ARM_UC_cryptoHashSetup(arm_uc_mdHandle_t* hDigest, arm_uc_mdType_t mdType)
00194 {
00195     arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
00196 
00197     const mbedtls_md_info_t* md_info = NULL;
00198     int mbedtls_result = 1;
00199 
00200     if (hDigest)
00201     {
00202         mbedtls_md_init(hDigest);
00203         md_info = mbedtls_md_info_from_type(mdType);
00204         mbedtls_result = mbedtls_md_setup(hDigest, md_info, 0);
00205         mbedtls_result |= mbedtls_md_starts(hDigest);
00206 
00207         if (mbedtls_result == 0)
00208         {
00209             result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
00210         }
00211     }
00212 
00213     return result;
00214 }
00215 
00216 arm_uc_error_t ARM_UC_cryptoHashUpdate(arm_uc_mdHandle_t* hDigest, arm_uc_buffer_t* input)
00217 {
00218     arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
00219 
00220     if (hDigest && input)
00221     {
00222         int mbedtls_result = 1;
00223 
00224         mbedtls_result = mbedtls_md_update(hDigest, input->ptr, input->size);
00225 
00226         if (mbedtls_result == 0)
00227         {
00228             result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
00229         }
00230     }
00231 
00232     return result;
00233 }
00234 arm_uc_error_t ARM_UC_cryptoHashFinish(arm_uc_mdHandle_t* hDigest, arm_uc_buffer_t* output)
00235 {
00236     arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
00237 
00238     if (hDigest && output && (output->size_max >= (unsigned)hDigest->md_info->size))
00239     {
00240         int mbedtls_result = 1;
00241 
00242         mbedtls_result = mbedtls_md_finish(hDigest, output->ptr);
00243 
00244         if (mbedtls_result == 0)
00245         {
00246             result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
00247 
00248             output->size = hDigest->md_info->size;
00249         }
00250     }
00251 
00252     // free memory
00253     mbedtls_md_free(hDigest);
00254 
00255     return result;
00256 }
00257 
00258 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)
00259 {
00260     arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
00261 
00262     if (key && key->ptr && iv && iv->ptr)
00263     {
00264         int mbedtls_result = 1;
00265 
00266         switch (aesKeySize)
00267         {
00268             case 128:
00269             case 256:
00270             {
00271                 memset(hCipher->aes_partial, 0, sizeof(hCipher->aes_partial));
00272                 hCipher->aes_nc_off = 0;
00273                 mbedtls_aes_init(&hCipher->aes_context);
00274                 /* NOTE: From the mbedtls documentation:
00275                  * Due to the nature of CTR you should use the same key schedule for
00276                  * both encryption and decryption. So a context initialized with
00277                  * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
00278                  */
00279                 mbedtls_result = mbedtls_aes_setkey_enc(&hCipher->aes_context, key->ptr, aesKeySize);
00280                 hCipher->aes_iv = iv->ptr;
00281                 break;
00282             }
00283             default:
00284                 // mbedtls_result is still 1, this means the function returns Invalid Parameter
00285                 break;
00286         }
00287 
00288         if (mbedtls_result == 0)
00289         {
00290             result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
00291         }
00292     }
00293 
00294     return result;
00295 }
00296 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)
00297 {
00298     arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
00299     size_t data_size = input_size < output->size_max ? input_size : output->size_max;
00300     output->size = 0;
00301     int mbedtls_result = mbedtls_aes_crypt_ctr(
00302         &hCipher->aes_context,
00303         data_size,
00304         &hCipher->aes_nc_off,
00305         hCipher->aes_iv,
00306         hCipher->aes_partial,
00307         input_ptr,
00308         output->ptr
00309 
00310     );
00311     if (mbedtls_result == 0)
00312     {
00313         result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
00314         output->size = data_size;
00315     }
00316     return result;
00317 }
00318 arm_uc_error_t ARM_UC_cryptoDecryptFinish(arm_uc_cipherHandle_t* hCipher, arm_uc_buffer_t* output)
00319 {
00320     (void) output;
00321     return (arm_uc_error_t){ARM_UC_CU_ERR_NONE};
00322 }
00323 
00324 #endif