blob: 0f5a998284d431b7966f157925db59020dee26d8 [file] [log] [blame]
/**
* @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 <assert.h>
#include <stdio.h>
#include <string.h>
#include <mbedtls/aes.h>
#include <mbedtls/des.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h>
#ifdef MBEDTLS_CMAC_C
# include <mbedtls/cmac.h>
#endif
#include <mbedtls/cipher.h>
#include <mbedtls/ecdsa.h>
#include <mbedtls/pk.h>
#include <mbedtls/entropy_poll.h>
/*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;
}