| /** | |
| * @file HostCryptoAPIOpenSSL.c | |
| * @author NXP Semiconductors | |
| * @version 1.0 | |
| * @par License | |
| * | |
| * Copyright 2017 NXP | |
| * SPDX-License-Identifier: Apache-2.0 | |
| * | |
| * @par Description | |
| * Host Crypto OpenSSL wrapper implementation | |
| * | |
| * @par HISTORY | |
| * | |
| */ | |
| #include "HostCryptoAPI.h" | |
| //#include "ax_util.h" | |
| //#include "sm_types.h" | |
| #include <assert.h> | |
| #include <stdio.h> | |
| #include <string.h> | |
| #ifdef OPENSSL | |
| #include <openssl/sha.h> | |
| #include <openssl/aes.h> | |
| #include <openssl/cmac.h> | |
| #include <openssl/rand.h> | |
| #include <openssl/des.h> | |
| #include <openssl/ecdsa.h> | |
| 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_NOT_SUPPORTED; | |
| #ifndef HLSE_IGNORE_PARAM_CHECK | |
| if (key == NULL || inData == NULL || outData == NULL || outDatalen == NULL) { | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| #endif | |
| 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 || outEncryptedDataLen == NULL) { | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| #endif | |
| // { Check if user requests to obtain the length only | |
| if (outEncryptedData == NULL) { | |
| if ((pMechanismType->mechanism == HLSE_AES_ECB_ENCRYPT) || (pMechanismType->mechanism == HLSE_AES_CBC_ENCRYPT)) | |
| { | |
| *outEncryptedDataLen = 16; | |
| return HLSE_SW_OK; | |
| } | |
| else if ((pMechanismType->mechanism == HLSE_DES_ECB_ENCRYPT) || (pMechanismType->mechanism == HLSE_DES_CBC_ENCRYPT)) | |
| { | |
| *outEncryptedDataLen = 8; | |
| return HLSE_SW_OK; | |
| } | |
| else { | |
| // type requested not found | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| } | |
| // } end section obtaining only the length | |
| if (pMechanismType->mechanism == HLSE_AES_ECB_ENCRYPT) { | |
| AES_KEY keyLocal; | |
| int keyLenBits = inKeyLen * 8; | |
| int nRet = 0; | |
| // This works assuming the plaintext has the same size as the key | |
| // NOTE: AES_set_encrypt_key returns 0 upon success | |
| nRet = AES_set_encrypt_key(inKey, keyLenBits, &keyLocal); | |
| if (nRet != 0) | |
| { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| // AES_ecb_encrypt has return type void | |
| AES_ecb_encrypt(inData, outEncryptedData, &keyLocal, AES_ENCRYPT); | |
| return HOST_CRYPTO_OK; | |
| } | |
| else if (pMechanismType->mechanism == HLSE_AES_CBC_ENCRYPT) { | |
| // int outLen = 0; | |
| int nRet; | |
| #if (OPENSSL_VERSION_NUMBER < 0x10100000L) | |
| EVP_CIPHER_CTX aesCtx; | |
| #else | |
| EVP_CIPHER_CTX *aesCtx = NULL; | |
| #endif | |
| int outEncryptedDataLenInt = (int)(*outEncryptedDataLen); | |
| #if (OPENSSL_VERSION_NUMBER < 0x10100000L) | |
| EVP_CIPHER_CTX_init(&aesCtx); | |
| #else | |
| aesCtx = EVP_CIPHER_CTX_new(); | |
| if (aesCtx == NULL) { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| #endif | |
| if (inKeyLen != AES_BLOCK_SIZE) { | |
| // printf("Unsupported key length for HOST_AES_CBC_Process\r\n"); | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| // iv is passed in the pParameter | |
| if (pMechanismType->pParameter == NULL) { | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| if ((inDataLen % AES_BLOCK_SIZE) != 0) { | |
| // printf("Input data are not block aligned for HOST_AES_CBC_Process\r\n"); | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| #if (OPENSSL_VERSION_NUMBER < 0x10100000L) | |
| // EVP_EncryptInit_ex returns 0 on failure and 1 upon success | |
| if (!EVP_EncryptInit_ex(&aesCtx, EVP_aes_128_cbc(), NULL, inKey, pMechanismType->pParameter)) { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| if (!EVP_EncryptUpdate(&aesCtx, outEncryptedData, &outEncryptedDataLenInt, inData, inDataLen)) { | |
| *outEncryptedDataLen = (U32)outEncryptedDataLenInt; | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| #else | |
| // EVP_EncryptInit_ex returns 0 on failure and 1 upon success | |
| if (!EVP_EncryptInit_ex(aesCtx, EVP_aes_128_cbc(), NULL, inKey, pMechanismType->pParameter)) { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| if (!EVP_EncryptUpdate(aesCtx, outEncryptedData, &outEncryptedDataLenInt, inData, inDataLen)) { | |
| *outEncryptedDataLen = (U32)outEncryptedDataLenInt; | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| #endif | |
| *outEncryptedDataLen = (U32)outEncryptedDataLenInt; | |
| #if (OPENSSL_VERSION_NUMBER < 0x10100000L) | |
| nRet = EVP_CIPHER_CTX_cleanup(&aesCtx); | |
| #else | |
| EVP_CIPHER_CTX_free(aesCtx); | |
| nRet = 1; | |
| #endif | |
| return nRet; | |
| } | |
| else if (pMechanismType->mechanism == HLSE_DES_ECB_ENCRYPT) { | |
| int nRet = 0; | |
| // DES_cblock key1, key2, key3; | |
| DES_key_schedule ks1, ks2, ks3; | |
| U32 i; | |
| if (inKeyLen >= 8) { | |
| nRet = DES_set_key((DES_cblock *)inKey, &ks1); | |
| if (nRet != 0) { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| } | |
| if (inKeyLen >= 16) { | |
| nRet = DES_set_key((DES_cblock *)(&inKey[8]), &ks2); | |
| if (nRet != 0) { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| } | |
| if (inKeyLen == 24) { | |
| nRet = DES_set_key((DES_cblock *)(&inKey[16]), &ks3); | |
| if (nRet != 0) { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| } | |
| for (i = 0; i < inDataLen; i += 8) { | |
| if (inKeyLen == 24) { | |
| DES_ecb3_encrypt((DES_cblock *)(inData + i), (DES_cblock *)(outEncryptedData + i), &ks1, &ks2, &ks3, DES_ENCRYPT); | |
| } | |
| else if (inKeyLen == 16) { | |
| DES_ecb2_encrypt((DES_cblock *)(inData + i), (DES_cblock *)(outEncryptedData + i), &ks1, &ks2, DES_ENCRYPT); | |
| } | |
| else { | |
| DES_ecb_encrypt((DES_cblock *)(inData + i), (DES_cblock *)(outEncryptedData + i), &ks1, DES_ENCRYPT); | |
| } | |
| } | |
| return HOST_CRYPTO_OK; | |
| } | |
| else if (pMechanismType->mechanism == HLSE_DES_CBC_ENCRYPT) { | |
| int nRet = 0; | |
| // DES_cblock key1, key2, key3; | |
| DES_key_schedule ks1, ks2, ks3; | |
| // iv is passed in the pParameter | |
| if (pMechanismType->pParameter == NULL) { | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| if (inKeyLen >= 8) { | |
| nRet = DES_set_key((DES_cblock *)inKey, &ks1); | |
| if (nRet != 0) { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| } | |
| if (inKeyLen >= 16) { | |
| nRet = DES_set_key((DES_cblock *)(&inKey[8]), &ks2); | |
| if (nRet != 0) { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| } | |
| if (inKeyLen == 24) { | |
| nRet = DES_set_key((DES_cblock *)(&inKey[16]), &ks3); | |
| if (nRet != 0) { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| } | |
| if (inKeyLen == 24) { | |
| DES_ede3_cbc_encrypt(inData, outEncryptedData, inDataLen, &ks1, &ks2, &ks3, pMechanismType->pParameter, DES_ENCRYPT); | |
| } | |
| else if (inKeyLen == 16) { | |
| DES_ede2_cbc_encrypt(inData, outEncryptedData, inDataLen, &ks1, &ks2, pMechanismType->pParameter, DES_ENCRYPT); | |
| } | |
| else { | |
| DES_cbc_encrypt(inData, outEncryptedData, inDataLen, &ks1, pMechanismType->pParameter, DES_ENCRYPT); | |
| } | |
| return HOST_CRYPTO_OK; | |
| } | |
| 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 || outDecryptedDataLen == NULL) { | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| #endif | |
| // { Check if user requets to obtain the length only | |
| if (outDecryptedData == NULL) { | |
| if ((pMechanismType->mechanism == HLSE_AES_ECB_DECRYPT) || (pMechanismType->mechanism == HLSE_AES_CBC_DECRYPT)) | |
| { | |
| *outDecryptedDataLen = 16; | |
| return HLSE_SW_OK; | |
| } | |
| else if ((pMechanismType->mechanism == HLSE_DES_ECB_DECRYPT) || (pMechanismType->mechanism == HLSE_DES_CBC_DECRYPT)) | |
| { | |
| *outDecryptedDataLen = 8; | |
| return HLSE_SW_OK; | |
| } | |
| else { | |
| // type requested not found | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| } | |
| // } end section obtaining only the length | |
| if (pMechanismType->mechanism == HLSE_AES_ECB_DECRYPT) { | |
| AES_KEY keyLocal; | |
| int keyLenBits = inKeyLen * 8; | |
| int nRet = 0; | |
| // This works assuming the plaintext has the same size as the key | |
| // NOTE: AES_set_encrypt_key returns 0 upon success | |
| nRet = AES_set_decrypt_key(inKey, keyLenBits, &keyLocal); | |
| if (nRet != 0) | |
| { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| // AES_ecb_encrypt has return type void | |
| AES_ecb_encrypt(inData, outDecryptedData, &keyLocal, AES_DECRYPT); | |
| return HOST_CRYPTO_OK; | |
| } | |
| else if (pMechanismType->mechanism == HLSE_AES_CBC_DECRYPT) { | |
| // int outLen = 0; | |
| int nRet; | |
| int outDecryptedDataLenInt = (int)(*outDecryptedDataLen); | |
| #if (OPENSSL_VERSION_NUMBER < 0x10100000L) | |
| EVP_CIPHER_CTX aesCtx; | |
| #else | |
| EVP_CIPHER_CTX *aesCtx = NULL; | |
| #endif | |
| #if (OPENSSL_VERSION_NUMBER < 0x10100000L) | |
| EVP_CIPHER_CTX_init(&aesCtx); | |
| #else | |
| aesCtx = EVP_CIPHER_CTX_new(); | |
| if (aesCtx == NULL) { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| #endif | |
| if (inKeyLen != AES_BLOCK_SIZE) { | |
| // printf("Unsupported key length for HOST_AES_CBC_Process\r\n"); | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| // iv is passed in the pParameter | |
| if (pMechanismType->pParameter == NULL) { | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| if ((inDataLen % AES_BLOCK_SIZE) != 0) { | |
| // printf("Input data are not block aligned for HOST_AES_CBC_Process\r\n"); | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| #if (OPENSSL_VERSION_NUMBER < 0x10100000L) | |
| // EVP_EncryptInit_ex returns 0 on failure and 1 upon success | |
| if (!EVP_DecryptInit_ex(&aesCtx, EVP_aes_128_cbc(), NULL, inKey, pMechanismType->pParameter)) { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| if (!EVP_DecryptUpdate(&aesCtx, outDecryptedData, &outDecryptedDataLenInt, inData, inDataLen)) { | |
| *outDecryptedDataLen = outDecryptedDataLenInt; | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| #else | |
| // EVP_EncryptInit_ex returns 0 on failure and 1 upon success | |
| if (!EVP_DecryptInit_ex(aesCtx, EVP_aes_128_cbc(), NULL, inKey, pMechanismType->pParameter)) { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| if (!EVP_DecryptUpdate(aesCtx, outDecryptedData, &outDecryptedDataLenInt, inData, inDataLen)) { | |
| *outDecryptedDataLen = outDecryptedDataLenInt; | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| #endif | |
| *outDecryptedDataLen = outDecryptedDataLenInt; | |
| #if (OPENSSL_VERSION_NUMBER < 0x10100000L) | |
| nRet = EVP_CIPHER_CTX_cleanup(&aesCtx); | |
| #else | |
| EVP_CIPHER_CTX_free(aesCtx); | |
| nRet = 1; | |
| #endif | |
| return nRet; | |
| } | |
| else if (pMechanismType->mechanism == HLSE_DES_ECB_DECRYPT) { | |
| int nRet = 0; | |
| // DES_cblock key1, key2, key3; | |
| DES_key_schedule ks1, ks2, ks3; | |
| U32 i; | |
| if (inKeyLen >= 8) { | |
| nRet = DES_set_key((DES_cblock *)inKey, &ks1); | |
| if (nRet != 0) { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| } | |
| if (inKeyLen >= 16) { | |
| nRet = DES_set_key((DES_cblock *)(&inKey[8]), &ks2); | |
| if (nRet != 0) { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| } | |
| if (inKeyLen == 24) { | |
| nRet = DES_set_key((DES_cblock *)(&inKey[16]), &ks3); | |
| if (nRet != 0) { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| } | |
| for (i = 0; i < inDataLen; i += 8) { | |
| if (inKeyLen == 24) { | |
| DES_ecb3_encrypt((DES_cblock *)(inData + i), (DES_cblock *)(outDecryptedData + i), &ks1, &ks2, &ks3, DES_DECRYPT); | |
| } | |
| else if (inKeyLen == 16) { | |
| DES_ecb2_encrypt((DES_cblock *)(inData + i), (DES_cblock *)(outDecryptedData + i), &ks1, &ks2, DES_DECRYPT); | |
| } | |
| else { | |
| DES_ecb_encrypt((DES_cblock *)(inData + i), (DES_cblock *)(outDecryptedData + i), &ks1, DES_DECRYPT); | |
| } | |
| } | |
| return HOST_CRYPTO_OK; | |
| } | |
| else if (pMechanismType->mechanism == HLSE_DES_CBC_DECRYPT) { | |
| int nRet = 0; | |
| // DES_cblock key1, key2, key3; | |
| DES_key_schedule ks1, ks2, ks3; | |
| // iv is passed in the pParameter | |
| if (pMechanismType->pParameter == NULL) { | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| if (inKeyLen >= 8) { | |
| nRet = DES_set_key((DES_cblock *)inKey, &ks1); | |
| if (nRet != 0) { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| } | |
| if (inKeyLen >= 16) { | |
| nRet = DES_set_key((DES_cblock *)(&inKey[8]), &ks2); | |
| if (nRet != 0) { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| } | |
| if (inKeyLen == 24) { | |
| nRet = DES_set_key((DES_cblock *)(&inKey[16]), &ks3); | |
| if (nRet != 0) { | |
| return HOST_CRYPTO_ERROR; | |
| } | |
| } | |
| if (inKeyLen == 24) { | |
| DES_ede3_cbc_encrypt(inData, outDecryptedData, inDataLen, &ks1, &ks2, &ks3, pMechanismType->pParameter, DES_DECRYPT); | |
| } | |
| else if (inKeyLen == 16) { | |
| DES_ede2_cbc_encrypt(inData, outDecryptedData, inDataLen, &ks1, &ks2, pMechanismType->pParameter, DES_DECRYPT); | |
| } | |
| else { | |
| DES_cbc_encrypt(inData, outDecryptedData, inDataLen, &ks1, pMechanismType->pParameter, DES_DECRYPT); | |
| } | |
| return HOST_CRYPTO_OK; | |
| } | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| HLSE_RET_CODE HLCRYPT_Digest(HLSE_MECHANISM_INFO* pMechanismType, | |
| U8* inData, U32 inDataLen, | |
| U8* outDigest, U32* outDigestLen) | |
| { | |
| #ifndef HLSE_IGNORE_PARAM_CHECK | |
| if (pMechanismType == NULL || inData == NULL || outDigestLen == NULL) { | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| #endif | |
| // Check for a request for digest Len | |
| if (outDigest == NULL) { | |
| if (pMechanismType->mechanism == HLSE_SHA256) { | |
| *outDigestLen = 32; | |
| return HLSE_SW_OK; | |
| } | |
| else if (pMechanismType->mechanism == HLSE_SHA1) { | |
| *outDigestLen = 20; | |
| return HLSE_SW_OK; | |
| } | |
| else { | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| } | |
| if (pMechanismType->mechanism == HLSE_SHA256) { | |
| SHA256_CTX ctx256; | |
| int ret; | |
| ret = SHA256_Init(&ctx256); | |
| if (ret == HOST_CRYPTO_OK) { | |
| ret = SHA256_Update(&ctx256, inData, inDataLen); | |
| if (ret == HOST_CRYPTO_OK) | |
| { | |
| ret = SHA256_Final(outDigest, &ctx256); | |
| *outDigestLen = 32; | |
| } | |
| } | |
| return ret; | |
| } | |
| else if (pMechanismType->mechanism == HLSE_SHA1) { | |
| SHA_CTX ctx; | |
| int ret; | |
| ret = SHA1_Init(&ctx); | |
| if (ret == HOST_CRYPTO_OK) | |
| { | |
| ret = SHA1_Update(&ctx, inData, inDataLen); | |
| if (ret == HOST_CRYPTO_OK) | |
| { | |
| ret = SHA1_Final(outDigest, &ctx); | |
| *outDigestLen = 20; | |
| } | |
| } | |
| return ret; | |
| } | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| static S32 HOST_CMAC_Init_Des(CMAC_CTX **ctx, const U8 *pKey, U8 keySizeInBytes) | |
| { | |
| int ret; | |
| *ctx = CMAC_CTX_new(); | |
| if (*ctx == NULL) | |
| { | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| // CMAC_Init() returns | |
| // 1 = success | |
| // 0 = failure | |
| ret = CMAC_Init(*ctx, pKey, keySizeInBytes, EVP_des_ede3_cbc(), NULL); | |
| return ret; | |
| } | |
| 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 || outSignatureLen == NULL) { | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| #endif | |
| // Check for a request to get the required signature len | |
| if (outSignature == NULL) { | |
| if (pMechanismType->mechanism == HLSE_AES_CMAC) { | |
| *outSignatureLen = 16; // AES_KEY_LEN_nBYTE | |
| return HLSE_SW_OK; | |
| } | |
| else { | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| } | |
| if (pMechanismType->mechanism == HLSE_AES_CMAC) { | |
| int ret; | |
| CMAC_CTX *ctx; | |
| size_t outSignatureLenSizeT = (size_t)(*outSignatureLen); | |
| ctx = CMAC_CTX_new(); | |
| if (ctx == NULL) | |
| { | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| // CMAC_Init() returns | |
| // 1 = success | |
| // 0 = failure | |
| ret = CMAC_Init(ctx, inKey, inKeyLen, EVP_aes_128_cbc(), NULL); | |
| if (ret == HOST_CRYPTO_OK) | |
| { | |
| ret = CMAC_Update(ctx, inData, inDataLen); | |
| if (ret == HOST_CRYPTO_OK) | |
| { | |
| ret = CMAC_Final(ctx, outSignature, &outSignatureLenSizeT); | |
| *outSignatureLen = (U32)outSignatureLenSizeT; | |
| } | |
| } | |
| if (ret != HLSE_ERR_MEMORY) | |
| { | |
| CMAC_CTX_free(ctx); | |
| } | |
| return ret; | |
| } | |
| else if (pMechanismType->mechanism == HLSE_DES_CMAC) { | |
| int ret; | |
| size_t size; | |
| CMAC_CTX *ctx; | |
| ret = HOST_CMAC_Init_Des(&ctx, inKey, inKeyLen); | |
| if (ret == HOST_CRYPTO_OK) | |
| { | |
| ret = CMAC_Update(ctx, inData, inDataLen); | |
| if (ret == HOST_CRYPTO_OK) | |
| { | |
| ret = CMAC_Final(ctx, outSignature, &size); | |
| } | |
| } | |
| if (ret != HLSE_ERR_MEMORY) | |
| { | |
| CMAC_CTX_free(ctx); | |
| } | |
| return ret; | |
| } | |
| else if (pMechanismType->mechanism == HLSE_ECDSA_SIGN) | |
| { | |
| unsigned int lclOutSignatureLen = (unsigned int)(*outSignatureLen); | |
| int status; | |
| status = ECDSA_sign(0, inData, inDataLen, outSignature, &lclOutSignatureLen, (EC_KEY *)inKey); | |
| *outSignatureLen = lclOutSignatureLen; | |
| if (status == 1) | |
| { | |
| return HLSE_SW_OK; | |
| } | |
| else | |
| { | |
| return HLSE_ERR_CRYPTO_ENGINE_FAILED; | |
| } | |
| } | |
| 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 = ECDSA_verify(0, inData, inDataLen, inSignature, inSignatureLen, (EC_KEY *)inKey); | |
| if (status == 1) | |
| { | |
| 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; | |
| *hContext = CMAC_CTX_new(); | |
| if (*hContext == NULL) | |
| { | |
| return HLSE_ERR_MEMORY; | |
| } | |
| // CMAC_Init() returns | |
| // 1 = success | |
| // 0 = failure | |
| ret = CMAC_Init(*hContext, inKey, inKeyLen, EVP_aes_128_cbc(), NULL); | |
| return ret; | |
| } | |
| 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 | |
| // CMAC_Update() returns | |
| // 1 = success | |
| // 0 = failure | |
| ret = CMAC_Update(hContext, inDataPart, inDataPartLen); | |
| return ret; | |
| } | |
| HLSE_RET_CODE HLCRYPT_SignFinal(HLSE_CONTEXT_HANDLE hContext, U8* outSignature, U32* outSignatureLen) | |
| { | |
| int ret; | |
| size_t outSignatureLenSizeT; | |
| #ifndef HLSE_IGNORE_PARAM_CHECK | |
| if (outSignatureLen == NULL) { | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| #endif | |
| outSignatureLenSizeT = (size_t)(*outSignatureLen); | |
| // Check for a request to get the required signature len | |
| if (outSignature == NULL) | |
| { | |
| *outSignatureLen = 16; | |
| return HLSE_SW_OK; | |
| } | |
| // CMAC_Final() returns | |
| // 1 = success | |
| // 0 = failure | |
| ret = CMAC_Final(hContext, outSignature, &outSignatureLenSizeT); | |
| *outSignatureLen = (U32)outSignatureLenSizeT; | |
| CMAC_CTX_free(hContext); | |
| return ret; | |
| } | |
| HLSE_RET_CODE HLCRYPT_GetRandom(U32 inLen, U8 * pRandom) | |
| { | |
| int nRet; | |
| #ifndef HLSE_IGNORE_PARAM_CHECK | |
| if (pRandom == NULL) { | |
| return HLSE_ERR_API_ERROR; | |
| } | |
| #endif | |
| nRet = RAND_bytes(pRandom, inLen); | |
| return nRet; | |
| } | |
| #endif // OPENSSL |