/** * @file HostCryptoAPImbedtls.c * @author NXP Semiconductors * @version 1.0 * @par License * * Copyright 2017 NXP * SPDX-License-Identifier: Apache-2.0 * * @par Description * Host Crypto mbed TLS wrapper implementation * * @par HISTORY * */ #include "HostCryptoAPI.h" //#include "ax_util.h" //#include "sm_types.h" #include #include #include #include #include #include #include #ifdef MBEDTLS_CMAC_C # include #endif #include #include #include #include /*TODO check return paths and framework specified terminate paths are met */ #define AES_BLOCK_SIZE 16 /*TODO check if this can come from mbedtls */ static mbedtls_cipher_context_t cipher_ctx; HLSE_RET_CODE HLCRYPT_GetSupportedMechanisms(HLSE_MECHANISM_TYPE* mechanism, U32* mechanismLen) { #ifndef HLSE_IGNORE_PARAM_CHECK if (mechanismLen == NULL) return HLSE_ERR_API_ERROR; #endif if (mechanism == NULL) { *mechanismLen = 11; return HLSE_SW_OK; } if (mechanism != NULL && mechanismLen != NULL && *mechanismLen < 11) { *mechanismLen = 11; return HLSE_ERR_BUF_TOO_SMALL; } *mechanismLen = 11; *mechanism++ = HLSE_SHA1; *mechanism++ = HLSE_SHA256; *mechanism++ = HLSE_AES_CMAC; *mechanism++ = HLSE_AES_ECB_ENCRYPT; *mechanism++ = HLSE_AES_ECB_DECRYPT; *mechanism++ = HLSE_AES_CBC_ENCRYPT; *mechanism++ = HLSE_AES_CBC_DECRYPT; *mechanism++ = HLSE_DES_ECB_ENCRYPT; *mechanism++ = HLSE_DES_ECB_DECRYPT; *mechanism++ = HLSE_DES_CBC_ENCRYPT; *mechanism++ = HLSE_DES_CBC_DECRYPT; return HLSE_SW_OK; } HLSE_RET_CODE HLCRYPT_Single_DES_CBC_Encrypt(U8 *key, U32 keylen, U8 *iv, U16 ivlen, U8 *inData, U32 inDatalen, U8 * outData, U32 *outDatalen) { int nRet = HOST_CRYPTO_OK; int mbedtls_ret; #ifndef HLSE_IGNORE_PARAM_CHECK if (key == NULL || inData == NULL || outData == NULL || outDatalen == NULL) { return HLSE_ERR_API_ERROR; } #endif mbedtls_des_context ctx; mbedtls_des_init(&ctx); mbedtls_ret = mbedtls_des_setkey_enc(&ctx, key); if (mbedtls_ret != 0) { nRet = HOST_CRYPTO_ERROR; } mbedtls_ret = mbedtls_des_crypt_cbc(&ctx, MBEDTLS_DES_ENCRYPT, inDatalen, iv, inData, outData); if (mbedtls_ret != 0) { nRet = HOST_CRYPTO_ERROR; } mbedtls_des_free(&ctx); return nRet; } HLSE_RET_CODE HLCRYPT_Encrypt(HLSE_MECHANISM_INFO* pMechanismType, U8* inKey, U32 inKeyLen, U8* inData, U32 inDataLen, U8* outEncryptedData, U32* outEncryptedDataLen) { #ifndef HLSE_IGNORE_PARAM_CHECK if (pMechanismType == NULL || inKey == NULL || inData == NULL || outEncryptedData == NULL || outEncryptedDataLen == NULL) { return HLSE_ERR_API_ERROR; } #endif if (pMechanismType->mechanism == HLSE_AES_ECB_ENCRYPT) { for (;;) { mbedtls_aes_context ctx; int keyLenBits = inKeyLen * 8; int nRet = HOST_CRYPTO_OK; int mbedtls_ret; mbedtls_aes_init(&ctx); // This works assuming the plaintext has the same size as the key // NOTE: AES_set_encrypt_key returns 0 upon success mbedtls_ret = mbedtls_aes_setkey_enc(&ctx, inKey, keyLenBits); if (mbedtls_ret != 0) { nRet = HOST_CRYPTO_ERROR; break; } mbedtls_ret = mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, inData, outEncryptedData); if (mbedtls_ret != 0) { nRet = HOST_CRYPTO_ERROR; break; } mbedtls_aes_free(&ctx); return nRet; } } else if (pMechanismType->mechanism == HLSE_AES_CBC_ENCRYPT) { for (;;) { int nRet = HOST_CRYPTO_OK; int mbedtls_ret; int keyLenBits = inKeyLen * 8; mbedtls_aes_context ctx; unsigned char * pIv = (unsigned char *)pMechanismType->pParameter; mbedtls_aes_init(&ctx); mbedtls_ret = mbedtls_aes_setkey_enc(&ctx, inKey, keyLenBits); if (mbedtls_ret != 0) { nRet = HOST_CRYPTO_ERROR; break; } mbedtls_ret = mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, inDataLen, pIv, inData, outEncryptedData); if (mbedtls_ret != 0) { nRet = HOST_CRYPTO_ERROR; break; } mbedtls_aes_free(&ctx); return nRet; } } else if (pMechanismType->mechanism == HLSE_DES_CBC_ENCRYPT) { for (;;) { int nRet = HOST_CRYPTO_OK; int mbedtls_ret; //int keyLenBits = inKeyLen * 8; mbedtls_des3_context ctx; unsigned char * pIv = (unsigned char *)pMechanismType->pParameter; mbedtls_des3_init(&ctx); mbedtls_ret = mbedtls_des3_set2key_enc(&ctx, inKey); if (mbedtls_ret != 0) { nRet = HOST_CRYPTO_ERROR; break; } mbedtls_ret = mbedtls_des3_crypt_cbc(&ctx, MBEDTLS_DES_ENCRYPT, inDataLen, pIv, inData, outEncryptedData); if (mbedtls_ret != 0) { nRet = HOST_CRYPTO_ERROR; break; } mbedtls_des3_free(&ctx); return nRet; } } else if (pMechanismType->mechanism == HLSE_DES_ECB_ENCRYPT) { for (;;) { int nRet = HOST_CRYPTO_OK; int mbedtls_ret; mbedtls_des_context ctx; mbedtls_des_init(&ctx); mbedtls_ret = mbedtls_des_setkey_enc(&ctx, inKey); if (mbedtls_ret != 0) { nRet = HOST_CRYPTO_ERROR; break; } mbedtls_ret = mbedtls_des_crypt_ecb(&ctx, inData, outEncryptedData); if (mbedtls_ret != 0) { nRet = HOST_CRYPTO_ERROR; break; } mbedtls_des_free(&ctx); return nRet; } } return HLSE_ERR_API_ERROR; } HLSE_RET_CODE HLCRYPT_Decrypt(HLSE_MECHANISM_INFO* pMechanismType, U8* inKey, U32 inKeyLen, U8* inData, U32 inDataLen, U8* outDecryptedData, U32* outDecryptedDataLen) { #ifndef HLSE_IGNORE_PARAM_CHECK if (pMechanismType == NULL || inKey == NULL || inData == NULL || outDecryptedData == NULL || outDecryptedDataLen == NULL) { return HLSE_ERR_API_ERROR; } #endif if (pMechanismType->mechanism == HLSE_AES_ECB_DECRYPT) { for (;;) { mbedtls_aes_context ctx; int keyLenBits = inKeyLen * 8; int mbedtls_ret; int nRet = HOST_CRYPTO_OK; mbedtls_aes_init(&ctx); // This works assuming the plaintext has the same size as the key // NOTE: AES_set_encrypt_key returns 0 upon success mbedtls_ret = mbedtls_aes_setkey_dec(&ctx, inKey, keyLenBits); if (mbedtls_ret != 0) { nRet = HOST_CRYPTO_ERROR; break; } // AES_ecb_encrypt has return type void mbedtls_ret = mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_DECRYPT, inData, outDecryptedData); if (mbedtls_ret != 0) { nRet = HOST_CRYPTO_ERROR; break; } mbedtls_aes_free(&ctx); return nRet; } } else if (pMechanismType->mechanism == HLSE_AES_CBC_DECRYPT) { for (;;) { int nRet = HOST_CRYPTO_OK; int mbedtls_ret; int keyLenBits = inKeyLen * 8; unsigned char * pIv = (unsigned char *)pMechanismType->pParameter; mbedtls_aes_context ctx; mbedtls_aes_init(&ctx); if (inKeyLen != AES_BLOCK_SIZE) { // printf("Unsupported key length for HOST_AES_CBC_Process\r\n"); nRet = HLSE_ERR_API_ERROR; break; } // iv is passed in the pParameter if (pMechanismType->pParameter == NULL) { nRet = HLSE_ERR_API_ERROR; break; } if ((inDataLen % AES_BLOCK_SIZE) != 0) { // printf("Input data are not block aligned for HOST_AES_CBC_Process\r\n"); nRet = HLSE_ERR_API_ERROR; break; } // EVP_EncryptInit_ex returns 0 on failure and 1 upon success mbedtls_ret = mbedtls_aes_setkey_dec(&ctx, inKey, keyLenBits); if (mbedtls_ret != 0) { nRet = HOST_CRYPTO_ERROR; break; } mbedtls_ret = mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, inDataLen, pIv, inData, outDecryptedData); if (mbedtls_ret != 0) { nRet = HOST_CRYPTO_ERROR; break; } mbedtls_aes_free(&ctx); return nRet; } } return HLSE_ERR_API_ERROR; } HLSE_RET_CODE HLCRYPT_Digest(HLSE_MECHANISM_INFO* pMechanismType, U8* inData, U32 inDataLen, U8* outDigest, U32* outDigestLen) { return HLSE_ERR_API_ERROR; } HLSE_RET_CODE HLCRYPT_Sign(HLSE_MECHANISM_INFO* pMechanismType, U8* inKey, U32 inKeyLen, U8* inData, U32 inDataLen, U8* outSignature, U32* outSignatureLen) { #ifndef HLSE_IGNORE_PARAM_CHECK if (pMechanismType == NULL || inKey == NULL || inData == NULL || outSignature == NULL || outSignatureLen == NULL) { return HLSE_ERR_API_ERROR; } #endif if (pMechanismType->mechanism == HLSE_AES_CMAC) { int ret; //mbedtls_cipher_context_t cipher_ctx; const mbedtls_cipher_info_t *cipher_info; /*TODO CHECK mbedtls cmac does not suppot cbc but only ecb. mbedtls_cipher_cmac_starts returns error */ cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); if (cipher_info != NULL) { mbedtls_cipher_init(&cipher_ctx); ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info); if (ret == 0) { #ifdef MBEDTLS_CMAC_C ret = mbedtls_cipher_cmac_starts(&cipher_ctx, inKey, (inKeyLen * 8)); if (ret == 0) { ret = mbedtls_cipher_cmac_update(&cipher_ctx, inData, inDataLen); if (ret == 0) { ret = mbedtls_cipher_cmac_finish(&cipher_ctx, outSignature); if (ret == 0) { ret = HOST_CRYPTO_OK; } } } #else ret = 1; #endif } mbedtls_cipher_free(&cipher_ctx); } else { return 0; } return ret; } else if (pMechanismType->mechanism == HLSE_ECDSA_SIGN) { int status; size_t sigLen = *outSignatureLen; status = (mbedtls_ecdsa_write_signature(mbedtls_pk_ec(*(mbedtls_pk_context *)inKey), MBEDTLS_MD_SHA256, inData, inDataLen, outSignature, &sigLen, NULL, NULL)); *outSignatureLen = sigLen; if (status == 0) { return HLSE_SW_OK; } else { return HLSE_ERR_CRYPTO_ENGINE_FAILED; } } else { return HLSE_ERR_API_ERROR; } } HLSE_RET_CODE HLCRYPT_Verify(HLSE_MECHANISM_INFO* pMechanismType, U8* inKey, U32 inKeyLen, U8* inData, U32 inDataLen, U8* inSignature, U32 inSignatureLen) { #ifndef HLSE_IGNORE_PARAM_CHECK if (pMechanismType == NULL || inKey == NULL || inData == NULL || inSignature == NULL) { return HLSE_ERR_API_ERROR; } #endif if (pMechanismType->mechanism == HLSE_ECDSA_VERIFY) { int status; status = (mbedtls_ecdsa_read_signature(mbedtls_pk_ec(*(mbedtls_pk_context *)inKey), inData, inDataLen, inSignature, inSignatureLen)); if (status == 0) { return HLSE_SW_OK; } else { return HLSE_ERR_CRYPTO_ENGINE_FAILED; } } else { return HLSE_ERR_API_ERROR; } } HLSE_RET_CODE HLCRYPT_SignInit(HLSE_MECHANISM_INFO* pMechanismType, U8* inKey, U32 inKeyLen, HLSE_CONTEXT_HANDLE* hContext) { #ifndef HLSE_IGNORE_PARAM_CHECK if (pMechanismType == NULL || inKey == NULL || hContext == NULL) { return HLSE_ERR_API_ERROR; } #endif if (pMechanismType->mechanism == HLSE_AES_CMAC) { int ret; const mbedtls_cipher_info_t *cipher_info; *hContext = &cipher_ctx; /*TODO CHECK mbedtls cmac does not suppot cbc but only ecb. mbedtls_cipher_cmac_starts returns error */ cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); if (cipher_info != NULL) { mbedtls_cipher_init(*hContext); ret = mbedtls_cipher_setup(*hContext, cipher_info); if (ret == 0) { #ifdef MBEDTLS_CMAC_C ret = mbedtls_cipher_cmac_starts(*hContext, inKey, (inKeyLen * 8)); #else ret = 1; #endif if (ret == 0) { ret = HOST_CRYPTO_OK; } } } else { return 0; } return ret; } else { return HLSE_ERR_API_ERROR; } } HLSE_RET_CODE HLCRYPT_SignUpdate(HLSE_CONTEXT_HANDLE hContext, U8* inDataPart, U32 inDataPartLen) { int ret; #ifndef HLSE_IGNORE_PARAM_CHECK if (inDataPart == NULL) { return HLSE_ERR_API_ERROR; } #endif #ifdef MBEDTLS_CMAC_C ret = mbedtls_cipher_cmac_update(hContext, inDataPart, inDataPartLen); #else ret = 1; #endif if (ret == 0) { ret = HOST_CRYPTO_OK; } return ret; } HLSE_RET_CODE HLCRYPT_SignFinal(HLSE_CONTEXT_HANDLE hContext, U8* outSignature, U32* outSignatureLen) { int ret; #ifndef HLSE_IGNORE_PARAM_CHECK if (outSignature == NULL || outSignatureLen == NULL) { return HLSE_ERR_API_ERROR; } #endif #ifdef MBEDTLS_CMAC_C ret = mbedtls_cipher_cmac_finish(hContext, outSignature); #else ret = 1; #endif if (ret == 0) { ret = HOST_CRYPTO_OK; } mbedtls_cipher_free(hContext); return ret; } HLSE_RET_CODE HLCRYPT_GetRandom(U32 inLen, U8 * pRandom) { int nRet; #if AX_EMBEDDED size_t olen = 0; #elif defined( MBEDTLS_CTR_DRBG_C) mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; #endif #ifndef HLSE_IGNORE_PARAM_CHECK if (pRandom == NULL) { return HLSE_ERR_API_ERROR; } #endif #if AX_EMBEDDED mbedtls_hardware_poll(NULL, pRandom, inLen, &olen); nRet = HOST_CRYPTO_OK; #elif defined( MBEDTLS_CTR_DRBG_C) mbedtls_entropy_init(&entropy); mbedtls_ctr_drbg_init(&ctr_drbg); nRet = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0); if (nRet == 0) { nRet = mbedtls_ctr_drbg_random((void*)&ctr_drbg, pRandom, inLen); if (nRet == 0) { nRet = HOST_CRYPTO_OK; } } #else nRet = HOST_CRYPTO_ERROR; #endif return nRet; }