Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_uc_crypto_pal.c Source File

arm_uc_crypto_pal.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 #if defined(ARM_UC_FEATURE_CRYPTO_PAL) && (ARM_UC_FEATURE_CRYPTO_PAL == 1)
00026 #include "pal.h"
00027 #include "sotp.h"
00028 #ifndef palMDHandle_t
00029 #include "pal_Crypto.h"
00030 #include "pal_plat_rot.h"
00031 #else
00032 #include "mbedtls/md.h"
00033 #endif
00034 
00035 arm_uc_error_t ARM_UC_cryptoHashSetup(arm_uc_mdHandle_t *hDigest, arm_uc_mdType_t mdType)
00036 {
00037     arm_uc_error_t result = (arm_uc_error_t) { ARM_UC_CU_ERR_INVALID_PARAMETER };
00038     if (hDigest) {
00039         palStatus_t rc = pal_mdInit(hDigest, mdType);
00040         if (rc == PAL_SUCCESS) {
00041             result.code = ERR_NONE;
00042         }
00043     }
00044     return result;
00045 }
00046 
00047 arm_uc_error_t ARM_UC_cryptoHashUpdate(arm_uc_mdHandle_t *hDigest, arm_uc_buffer_t *input)
00048 {
00049     arm_uc_error_t result = (arm_uc_error_t) { ARM_UC_CU_ERR_INVALID_PARAMETER };
00050     if (hDigest && input) {
00051         palStatus_t rc = pal_mdUpdate(*hDigest, input->ptr, input->size);
00052         if (rc == PAL_SUCCESS) {
00053             result = (arm_uc_error_t) { ERR_NONE };
00054         }
00055     }
00056     return result;
00057 }
00058 
00059 arm_uc_error_t ARM_UC_cryptoHashFinish(arm_uc_mdHandle_t *hDigest, arm_uc_buffer_t *output)
00060 {
00061     arm_uc_error_t result = (arm_uc_error_t) { ARM_UC_CU_ERR_INVALID_PARAMETER };
00062 
00063     // TODO: validate buffer size? I guess we just hope for the best!
00064     if (hDigest && output && output->size_max >= 256 / 8) { // FIXME:PAL does not provide a method to extract this
00065         palStatus_t rc = pal_mdFinal(*hDigest, output->ptr);
00066 
00067         if (rc == PAL_SUCCESS) {
00068             result = (arm_uc_error_t) { ERR_NONE };
00069             output->size = 256 / 8; // FIXME:PAL does not provide a method to extract this
00070         }
00071     }
00072     if (hDigest) {
00073         palStatus_t rc = pal_mdFree(hDigest);
00074         if (rc != PAL_SUCCESS && result.error == ERR_NONE) {
00075             result.module = TWO_CC('P', 'A');
00076             result.error  = rc;
00077         }
00078     }
00079     return result;
00080 }
00081 
00082 arm_uc_error_t ARM_UC_cryptoDecryptSetup(arm_uc_cipherHandle_t *hCipher, arm_uc_buffer_t *key, arm_uc_buffer_t *iv,
00083                                          int32_t aesKeySize)
00084 {
00085     arm_uc_error_t result = (arm_uc_error_t) { ARM_UC_CU_ERR_INVALID_PARAMETER };
00086 
00087     if (key && key->ptr && iv && iv->ptr) {
00088         palStatus_t rc = 1;
00089 
00090         switch (aesKeySize) {
00091             case 128:
00092             case 256: {
00093                 rc = pal_initAes(&hCipher->aes_context);
00094                 /* NOTE: From the mbedtls documentation:
00095                  * Due to the nature of CTR you should use the same key schedule for
00096                  * both encryption and decryption. So a context initialized with
00097                  * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
00098                  */
00099                 if (rc == PAL_SUCCESS) {
00100                     rc = pal_setAesKey(hCipher->aes_context, key->ptr, aesKeySize, PAL_KEY_TARGET_ENCRYPTION);
00101                 }
00102                 hCipher->aes_iv = iv->ptr;
00103                 break;
00104             }
00105             default:
00106                 // rc is still 1, this means the function returns Invalid Parameter
00107                 break;
00108         }
00109 
00110         if (rc == PAL_SUCCESS) {
00111             result = (arm_uc_error_t) { ERR_NONE };
00112         }
00113     }
00114 
00115     return result;
00116 }
00117 
00118 arm_uc_error_t ARM_UC_cryptoDecryptUpdate(arm_uc_cipherHandle_t *hCipher, const uint8_t *input_ptr, uint32_t input_size,
00119                                           arm_uc_buffer_t *output)
00120 {
00121     arm_uc_error_t result = (arm_uc_error_t) { ARM_UC_CU_ERR_INVALID_PARAMETER };
00122     size_t data_size = input_size < output->size_max ? input_size : output->size_max;
00123     output->size = 0;
00124     palStatus_t rc = pal_aesCTR(
00125                          hCipher->aes_context,
00126                          input_ptr,
00127                          output->ptr,
00128                          data_size,
00129                          hCipher->aes_iv
00130                      );
00131     if (rc == PAL_SUCCESS) {
00132         result = (arm_uc_error_t) { ERR_NONE };
00133         output->size = data_size;
00134     }
00135     return result;
00136 }
00137 
00138 arm_uc_error_t ARM_UC_cryptoDecryptFinish(arm_uc_cipherHandle_t *hCipher, arm_uc_buffer_t *output)
00139 {
00140     pal_freeAes(&hCipher->aes_context);
00141     (void) output;
00142     return (arm_uc_error_t) {ERR_NONE};
00143 }
00144 
00145 arm_uc_error_t ARM_UC_cryptoHMACSHA256(arm_uc_buffer_t *key,
00146                                        arm_uc_buffer_t *input,
00147                                        arm_uc_buffer_t *output)
00148 {
00149     arm_uc_error_t result = (arm_uc_error_t) { ARM_UC_CU_ERR_INVALID_PARAMETER };
00150 
00151 
00152     size_t outPutSize = 0;
00153     palStatus_t pal_st = pal_mdHmacSha256(key->ptr, key->size,
00154                                           input->ptr, input->size,
00155                                           output->ptr, &outPutSize);
00156 
00157     output->size = (uint32_t) outPutSize;  // we lose here some bits in 64 bit systems,
00158                                            // but as long as we are under u32 MAX size it does not matter
00159                                            // and as input size is read from u32 this should be safe
00160 
00161 
00162     if ((pal_st == PAL_SUCCESS) && (output->size == ARM_UC_SHA256_SIZE)) {
00163         result = (arm_uc_error_t) { ERR_NONE };
00164     }
00165 
00166     return result;
00167 }
00168 
00169 int8_t mbed_cloud_client_get_rot_128bit(uint8_t *key_buf, uint32_t length)
00170 {
00171     int8_t rv = -1;
00172     palStatus_t status = PAL_ERR_GENERIC_FAILURE ;
00173 
00174     if (length < ARM_UC_ROT_SIZE) {
00175            return -1;
00176     }
00177     //Get RoT
00178     status = pal_plat_osGetRoT(key_buf, ARM_UC_ROT_SIZE);
00179 
00180     if (status == PAL_SUCCESS) {
00181         rv = 0;
00182     } else {
00183         /* clear buffer on failure so we don't leak the rot */
00184         memset(key_buf, 0, length);
00185     }
00186 
00187     return rv;
00188 }
00189 
00190 #endif