diff options
Diffstat (limited to 'bsps/arm/imxrt/nxp/devices/MIMXRT1052/drivers/fsl_dcp.c')
-rw-r--r-- | bsps/arm/imxrt/nxp/devices/MIMXRT1052/drivers/fsl_dcp.c | 1465 |
1 files changed, 0 insertions, 1465 deletions
diff --git a/bsps/arm/imxrt/nxp/devices/MIMXRT1052/drivers/fsl_dcp.c b/bsps/arm/imxrt/nxp/devices/MIMXRT1052/drivers/fsl_dcp.c deleted file mode 100644 index fff5e6fe35..0000000000 --- a/bsps/arm/imxrt/nxp/devices/MIMXRT1052/drivers/fsl_dcp.c +++ /dev/null @@ -1,1465 +0,0 @@ -/* - * Copyright 2017-2019 NXP - * All rights reserved. - * - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include "fsl_dcp.h" - -/******************************************************************************* - * Definitions - ******************************************************************************/ - -/* Component ID definition, used by tools. */ -#ifndef FSL_COMPONENT_ID -#define FSL_COMPONENT_ID "platform.drivers.dcp" -#endif - -#ifndef DCP_USE_DCACHE -#define DCP_USE_DCACHE 0 -#endif -/* 1 - driver supports DCACHE, 0 - drivers does not support DCACHE */ -/* When enable (DCP_USE_DCACHE = 1) Input/output buffers and hash ctx should be in */ -/* non-cached memory or handled properly (Clean & Invalidate DCACHE) */ - -/*! Compile time sizeof() check */ -#define BUILD_ASSURE(condition, msg) extern int msg[1 - 2 * (!(condition))] __attribute__((unused)) - -#define dcp_memcpy memcpy - -/*! Internal states of the HASH creation process */ -typedef enum _dcp_hash_algo_state -{ - kDCP_StateHashInit = 1u, /*!< Init state. */ - kDCP_StateHashUpdate, /*!< Update state. */ -} dcp_hash_algo_state_t; - -/*! multiple of 64-byte block represented as byte array of 32-bit words */ -typedef union _dcp_hash_block -{ - uint32_t w[DCP_HASH_BLOCK_SIZE / 4]; /*!< array of 32-bit words */ - uint8_t b[DCP_HASH_BLOCK_SIZE]; /*!< byte array */ -} dcp_hash_block_t; - -/*! internal dcp_hash context structure */ -typedef struct _dcp_hash_ctx_internal -{ - dcp_hash_block_t blk; /*!< memory buffer. only full blocks are written to DCP during hash updates */ - size_t blksz; /*!< number of valid bytes in memory buffer */ - dcp_hash_algo_t algo; /*!< selected algorithm from the set of supported algorithms */ - dcp_hash_algo_state_t state; /*!< finite machine state of the hash software process */ - uint32_t fullMessageSize; /*!< track message size */ - uint32_t ctrl0; /*!< HASH_INIT and HASH_TERM flags */ - uint32_t runningHash[9]; /*!< running hash. up to SHA-256 plus size, that is 36 bytes. */ - dcp_handle_t *handle; -} dcp_hash_ctx_internal_t; - -/*!< SHA-1/SHA-2 digest length in bytes */ -enum _dcp_hash_digest_len -{ - kDCP_OutLenSha1 = 20u, - kDCP_OutLenSha256 = 32u, - kDCP_OutLenCrc32 = 4u, -}; - -enum _dcp_work_packet_bit_definitions -{ - kDCP_CONTROL0_DECR_SEMAPHOR = 1u << 1, /* DECR_SEMAPHOR */ - kDCP_CONTROL0_ENABLE_HASH = 1u << 6, /* ENABLE_HASH */ - kDCP_CONTROL0_HASH_INIT = 1u << 12, /* HASH_INIT */ - kDCP_CONTROL0_HASH_TERM = 1u << 13, /* HASH_TERM */ - kDCP_CONTROL1_HASH_SELECT_SHA256 = 2u << 16, - kDCP_CONTROL1_HASH_SELECT_SHA1 = 0u << 16, - kDCP_CONTROL1_HASH_SELECT_CRC32 = 1u << 16, -}; - -/*! 64-byte block represented as byte array of 16 32-bit words */ -typedef union _dcp_sha_block -{ - uint32_t w[64 / 4]; /*!< array of 32-bit words */ - uint8_t b[64]; /*!< byte array */ -} dcp_sha_block_t; - -#if defined(DCP_HASH_CAVP_COMPATIBLE) -/* result of sha1 hash for message with zero size */ -static uint8_t s_nullSha1[] = {0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, - 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09}; -/* result of sha256 hash for message with zero size */ -static uint8_t s_nullSha256[] = {0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, - 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, - 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; -#endif /* DCP_HASH_CAVP_COMPATIBLE */ - -/******************************************************************************* - * Variables - ******************************************************************************/ -AT_NONCACHEABLE_SECTION_INIT(static dcp_context_t s_dcpContextSwitchingBuffer); - -/******************************************************************************* - * Code - ******************************************************************************/ - -static void dcp_reverse_and_copy(uint8_t *src, uint8_t *dest, size_t src_len) -{ - for (uint32_t i = 0; i < src_len; i++) - { - dest[i] = src[src_len - 1U - i]; - } -} - -#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U) -static uint32_t *DCP_FindCacheLine(uint8_t *dcpWorkExt) -{ - while ((uint32_t)dcpWorkExt & (FSL_FEATURE_L1DCACHE_LINESIZE_BYTE - 1)) - dcpWorkExt++; - return (uint32_t *)dcpWorkExt; -} -#endif - -static status_t dcp_get_channel_status(DCP_Type *base, dcp_channel_t channel) -{ - uint32_t statReg = 0; - uint32_t semaReg = 0; - status_t status = kStatus_Fail; - - switch (channel) - { - case kDCP_Channel0: - statReg = base->CH0STAT; - semaReg = base->CH0SEMA; - break; - - case kDCP_Channel1: - statReg = base->CH1STAT; - semaReg = base->CH1SEMA; - break; - - case kDCP_Channel2: - statReg = base->CH2STAT; - semaReg = base->CH2SEMA; - break; - - case kDCP_Channel3: - statReg = base->CH3STAT; - semaReg = base->CH3SEMA; - break; - - default: - /* All the cases have been listed above, the default clause should not be reached. */ - break; - } - - if (!((0U != (semaReg & DCP_CH0SEMA_VALUE_MASK)) || (0U != (statReg & DCP_CH0STAT_ERROR_CODE_MASK)))) - { - status = kStatus_Success; - } - - return status; -} - -static void dcp_clear_status(DCP_Type *base) -{ - volatile uint32_t *dcpStatClrPtr = (volatile uint32_t *)&base->STAT + 2u; - *dcpStatClrPtr = 0xFFu; - - while ((base->STAT & 0xffu) != 0U) - { - } -} - -static void dcp_clear_channel_status(DCP_Type *base, uint32_t mask) -{ - volatile uint32_t *chStatClrPtr; - - if (0U != (mask & (uint32_t)kDCP_Channel0)) - { - chStatClrPtr = &base->CH0STAT_CLR; - *chStatClrPtr = 0xFFu; - } - if (0U != (mask & (uint32_t)kDCP_Channel1)) - { - chStatClrPtr = &base->CH1STAT_CLR; - *chStatClrPtr = 0xFFu; - } - if (0U != (mask & (uint32_t)kDCP_Channel2)) - { - chStatClrPtr = &base->CH2STAT_CLR; - *chStatClrPtr = 0xFFu; - } - if (0U != (mask & (uint32_t)kDCP_Channel3)) - { - chStatClrPtr = &base->CH3STAT_CLR; - *chStatClrPtr = 0xFFu; - } -} - -static status_t dcp_aes_set_sram_based_key(DCP_Type *base, dcp_handle_t *handle, const uint8_t *key) -{ - base->KEY = DCP_KEY_INDEX(handle->keySlot) | DCP_KEY_SUBWORD(0); - /* move the key by 32-bit words */ - int i = 0; - size_t keySize = 16u; - while (keySize != 0U) - { - keySize -= sizeof(uint32_t); - base->KEYDATA = ((uint32_t *)(uintptr_t)key)[i]; - i++; - } - return kStatus_Success; -} - -/* Disable optimizations for GCC to prevent instruction reordering */ -#if defined(__GNUC__) -#pragma GCC push_options -#pragma GCC optimize("O0") -#endif -static status_t dcp_schedule_work(DCP_Type *base, dcp_handle_t *handle, dcp_work_packet_t *dcpPacket) -{ - status_t status; - - /* check if our channel is active */ - if ((base->STAT & (uint32_t)handle->channel) != (uint32_t)handle->channel) - { - /* disable global interrupt */ - uint32_t currPriMask = DisableGlobalIRQ(); - - /* re-check if our channel is still available */ - if ((base->STAT & (uint32_t)handle->channel) == 0U) - { - volatile uint32_t *cmdptr = NULL; - volatile uint32_t *chsema = NULL; - - switch (handle->channel) - { - case kDCP_Channel0: - cmdptr = &base->CH0CMDPTR; - chsema = &base->CH0SEMA; - break; - - case kDCP_Channel1: - cmdptr = &base->CH1CMDPTR; - chsema = &base->CH1SEMA; - break; - - case kDCP_Channel2: - cmdptr = &base->CH2CMDPTR; - chsema = &base->CH2SEMA; - break; - - case kDCP_Channel3: - cmdptr = &base->CH3CMDPTR; - chsema = &base->CH3SEMA; - break; - - default: - /* All the cases have been listed above, the default clause should not be reached. */ - break; - } - - if ((NULL != cmdptr) && (NULL != chsema)) - { - /* set out packet to DCP CMDPTR */ - *cmdptr = (uint32_t)dcpPacket; - -#if defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U) - /* Clean DCACHE before sending DCP packet to engine */ - SCB_CleanDCache_by_Addr((uint32_t *)dcpPacket, sizeof(dcp_work_packet_t)); -#endif - /* Make sure that all data memory accesses are completed before starting of the job */ - __DSB(); - __ISB(); - - /* set the channel semaphore to start the job */ - *chsema = 1u; - } - - status = kStatus_Success; - } - - else - { - status = (int32_t)kStatus_DCP_Again; - } - /* global interrupt enable */ - EnableGlobalIRQ(currPriMask); - } - - else - { - return (int32_t)kStatus_DCP_Again; - } - - return status; -} -#if defined(__GNUC__) -#pragma GCC pop_options -#endif - -/*! - * brief Set AES key to dcp_handle_t struct and optionally to DCP. - * - * Sets the AES key for encryption/decryption with the dcp_handle_t structure. - * The dcp_handle_t input argument specifies keySlot. - * If the keySlot is kDCP_OtpKey, the function will check the OTP_KEY_READY bit and will return it's ready to use - * status. - * For other keySlot selections, the function will copy and hold the key in dcp_handle_t struct. - * If the keySlot is one of the four DCP SRAM-based keys (one of kDCP_KeySlot0, kDCP_KeySlot1, kDCP_KeySlot2, - * kDCP_KeySlot3), - * this function will also load the supplied key to the specified keySlot in DCP. - * - * param base DCP peripheral base address. - * param handle Handle used for the request. - * param key 0-mod-4 aligned pointer to AES key. - * param keySize AES key size in bytes. Shall equal 16. - * return status from set key operation - */ -status_t DCP_AES_SetKey(DCP_Type *base, dcp_handle_t *handle, const uint8_t *key, size_t keySize) -{ - status_t status = kStatus_Fail; - - if ((kDCP_OtpKey == handle->keySlot) || (kDCP_OtpUniqueKey == handle->keySlot)) - { - /* for AES OTP and unique key, check and return read from fuses status */ - if ((base->STAT & DCP_STAT_OTP_KEY_READY_MASK) == DCP_STAT_OTP_KEY_READY_MASK) - { - status = kStatus_Success; - } - } - else - { - /* only work with aligned key[] */ - if ((0x3U & (uintptr_t)key) != 0U) - { - return kStatus_InvalidArgument; - } - - /* keySize must be 16. */ - if (keySize != 16U) - { - return kStatus_InvalidArgument; - } - - /* move the key by 32-bit words */ - int i = 0; - while (keySize != 0U) - { - keySize -= sizeof(uint32_t); - handle->keyWord[i] = ((uint32_t *)(uintptr_t)key)[i]; - i++; - } - - if (kDCP_PayloadKey != handle->keySlot) - { - /* move the key by 32-bit words to DCP SRAM-based key storage */ - status = dcp_aes_set_sram_based_key(base, handle, key); - } - else - { - /* for PAYLOAD_KEY, just return Ok status now */ - status = kStatus_Success; - } - } - - return status; -} - -/*! - * brief Encrypts AES on one or multiple 128-bit block(s). - * - * Encrypts AES. - * The source plaintext and destination ciphertext can overlap in system memory. - * - * param base DCP peripheral base address - * param handle Handle used for this request. - * param plaintext Input plain text to encrypt - * param[out] ciphertext Output cipher text - * param size Size of input and output data in bytes. Must be multiple of 16 bytes. - * return Status from encrypt operation - */ -status_t DCP_AES_EncryptEcb( - DCP_Type *base, dcp_handle_t *handle, const uint8_t *plaintext, uint8_t *ciphertext, size_t size) -{ - status_t completionStatus = kStatus_Fail; - - /* Use extended DCACHE line size aligned structure */ -#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U) - dcp_work_packet_t *dcpWork; - uint8_t dcpWorkExt[sizeof(dcp_work_packet_t) + FSL_FEATURE_L1DCACHE_LINESIZE_BYTE] = {0U}; - dcpWork = (dcp_work_packet_t *)DCP_FindCacheLine(dcpWorkExt); -#else - dcp_work_packet_t dcpWorkPacket = {0}; - dcp_work_packet_t *dcpWork = &dcpWorkPacket; -#endif - - do - { - completionStatus = DCP_AES_EncryptEcbNonBlocking(base, handle, dcpWork, plaintext, ciphertext, size); - } while (completionStatus == (int32_t)kStatus_DCP_Again); - - if (completionStatus != kStatus_Success) - { - return completionStatus; - } - - return DCP_WaitForChannelComplete(base, handle); -} - -/*! - * brief Encrypts AES using the ECB block mode. - * - * Puts AES ECB encrypt work packet to DCP channel. - * - * param base DCP peripheral base address - * param handle Handle used for this request. - * param[out] dcpPacket Memory for the DCP work packet. - * param plaintext Input plain text to encrypt. - * param[out] ciphertext Output cipher text - * param size Size of input and output data in bytes. Must be multiple of 16 bytes. - * return kStatus_Success The work packet has been scheduled at DCP channel. - * return kStatus_DCP_Again The DCP channel is busy processing previous request. - */ -status_t DCP_AES_EncryptEcbNonBlocking(DCP_Type *base, - dcp_handle_t *handle, - dcp_work_packet_t *dcpPacket, - const uint8_t *plaintext, - uint8_t *ciphertext, - size_t size) -{ - /* Size must be 16-byte multiple */ - if ((size < 16u) || (0U != (size % 16u))) - { - return kStatus_InvalidArgument; - } - - dcpPacket->control0 = - 0x122u | (handle->swapConfig & 0xFC0000u); /* CIPHER_ENCRYPT | ENABLE_CIPHER | DECR_SEMAPHORE */ - dcpPacket->sourceBufferAddress = (uint32_t)plaintext; - dcpPacket->destinationBufferAddress = (uint32_t)ciphertext; - dcpPacket->bufferSize = (uint32_t)size; - - if (handle->keySlot == kDCP_OtpKey) - { - dcpPacket->control0 |= ((uint32_t)1u << 10); /* OTP_KEY */ - dcpPacket->control1 = ((uint32_t)0xFFu << 8); /* KEY_SELECT = OTP_KEY */ - } - else if (handle->keySlot == kDCP_OtpUniqueKey) - { - dcpPacket->control0 |= ((uint32_t)1u << 10); /* OTP_KEY */ - dcpPacket->control1 = ((uint32_t)0xFEu << 8); /* KEY_SELECT = UNIQUE_KEY */ - } - else if (handle->keySlot == kDCP_PayloadKey) - { - /* ECB does not have IV, so we can point payload directly to keyWord[] stored in handle. */ - dcpPacket->payloadPointer = (uint32_t)&handle->keyWord[0]; - dcpPacket->control0 |= ((uint32_t)1u << 11); /* PAYLOAD_KEY */ - } - else - { - dcpPacket->control1 = ((uint32_t)handle->keySlot << 8); /* KEY_SELECT = keySlot */ - } - - return dcp_schedule_work(base, handle, dcpPacket); -} - -/*! - * brief Decrypts AES on one or multiple 128-bit block(s). - * - * Decrypts AES. - * The source ciphertext and destination plaintext can overlap in system memory. - * - * param base DCP peripheral base address - * param handle Handle used for this request. - * param ciphertext Input plain text to encrypt - * param[out] plaintext Output cipher text - * param size Size of input and output data in bytes. Must be multiple of 16 bytes. - * return Status from decrypt operation - */ -status_t DCP_AES_DecryptEcb( - DCP_Type *base, dcp_handle_t *handle, const uint8_t *ciphertext, uint8_t *plaintext, size_t size) -{ - status_t completionStatus = kStatus_Fail; - - /* Use extended DCACHE line size aligned structure */ -#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U) - dcp_work_packet_t *dcpWork; - uint8_t dcpWorkExt[sizeof(dcp_work_packet_t) + FSL_FEATURE_L1DCACHE_LINESIZE_BYTE] = {0U}; - dcpWork = (dcp_work_packet_t *)DCP_FindCacheLine(dcpWorkExt); -#else - dcp_work_packet_t dcpWorkPacket = {0}; - dcp_work_packet_t *dcpWork = &dcpWorkPacket; -#endif - - do - { - completionStatus = DCP_AES_DecryptEcbNonBlocking(base, handle, dcpWork, ciphertext, plaintext, size); - } while (completionStatus == (int32_t)(kStatus_DCP_Again)); - - if (completionStatus != kStatus_Success) - { - return completionStatus; - } - - return DCP_WaitForChannelComplete(base, handle); -} - -/*! - * brief Decrypts AES using ECB block mode. - * - * Puts AES ECB decrypt dcpPacket to DCP input job ring. - * - * param base DCP peripheral base address - * param handle Handle used for this request. - * param[out] dcpPacket Memory for the DCP work packet. - * param ciphertext Input cipher text to decrypt - * param[out] plaintext Output plain text - * param size Size of input and output data in bytes. Must be multiple of 16 bytes. - * return kStatus_Success The work packet has been scheduled at DCP channel. - * return kStatus_DCP_Again The DCP channel is busy processing previous request. - */ -status_t DCP_AES_DecryptEcbNonBlocking(DCP_Type *base, - dcp_handle_t *handle, - dcp_work_packet_t *dcpPacket, - const uint8_t *ciphertext, - uint8_t *plaintext, - size_t size) -{ - /* Size must be 16-byte multiple */ - if ((size < 16u) || (0U != (size % 16u))) - { - return kStatus_InvalidArgument; - } - - dcpPacket->control0 = 0x22u | (handle->swapConfig & 0xFC0000u); /* ENABLE_CIPHER | DECR_SEMAPHORE */ - dcpPacket->sourceBufferAddress = (uint32_t)ciphertext; - dcpPacket->destinationBufferAddress = (uint32_t)plaintext; - dcpPacket->bufferSize = (uint32_t)size; - - if (handle->keySlot == kDCP_OtpKey) - { - dcpPacket->control0 |= ((uint32_t)1u << 10); /* OTP_KEY */ - dcpPacket->control1 = ((uint32_t)0xFFu << 8); /* KEY_SELECT = OTP_KEY */ - } - else if (handle->keySlot == kDCP_OtpUniqueKey) - { - dcpPacket->control0 |= ((uint32_t)1u << 10); /* OTP_KEY */ - dcpPacket->control1 = ((uint32_t)0xFEu << 8); /* KEY_SELECT = UNIQUE_KEY */ - } - else if (handle->keySlot == kDCP_PayloadKey) - { - /* ECB does not have IV, so we can point payload directly to keyWord[] stored in handle. */ - dcpPacket->payloadPointer = (uint32_t)&handle->keyWord[0]; - dcpPacket->control0 |= ((uint32_t)1u << 11); /* PAYLOAD_KEY */ - } - else - { - dcpPacket->control1 = ((uint32_t)handle->keySlot << 8); /* KEY_SELECT = keySlot */ - } - - return dcp_schedule_work(base, handle, dcpPacket); -} - -/*! - * brief Encrypts AES using CBC block mode. - * - * Encrypts AES using CBC block mode. - * The source plaintext and destination ciphertext can overlap in system memory. - * - * param base DCP peripheral base address - * param handle Handle used for this request. - * param plaintext Input plain text to encrypt - * param[out] ciphertext Output cipher text - * param size Size of input and output data in bytes. Must be multiple of 16 bytes. - * param iv Input initial vector to combine with the first input block. - * return Status from encrypt operation - */ -status_t DCP_AES_EncryptCbc(DCP_Type *base, - dcp_handle_t *handle, - const uint8_t *plaintext, - uint8_t *ciphertext, - size_t size, - const uint8_t iv[16]) -{ - status_t completionStatus = kStatus_Fail; - - /* Use extended DCACHE line size aligned structure */ -#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U) - dcp_work_packet_t *dcpWork; - uint8_t dcpWorkExt[sizeof(dcp_work_packet_t) + FSL_FEATURE_L1DCACHE_LINESIZE_BYTE] = {0U}; - dcpWork = (dcp_work_packet_t *)DCP_FindCacheLine(dcpWorkExt); -#else - dcp_work_packet_t dcpWorkPacket = {0}; - dcp_work_packet_t *dcpWork = &dcpWorkPacket; -#endif - - do - { - completionStatus = DCP_AES_EncryptCbcNonBlocking(base, handle, dcpWork, plaintext, ciphertext, size, iv); - } while (completionStatus == (int32_t)kStatus_DCP_Again); - - if (completionStatus != kStatus_Success) - { - return completionStatus; - } - - return DCP_WaitForChannelComplete(base, handle); -} - -/*! - * brief Encrypts AES using CBC block mode. - * - * Puts AES CBC encrypt dcpPacket to DCP input job ring. - * - * param base DCP peripheral base address - * param handle Handle used for this request. Specifies jobRing. - * param[out] dcpPacket Memory for the DCP work packet. - * param plaintext Input plain text to encrypt - * param[out] ciphertext Output cipher text - * param size Size of input and output data in bytes. Must be multiple of 16 bytes. - * param iv Input initial vector to combine with the first input block. - * return kStatus_Success The work packet has been scheduled at DCP channel. - * return kStatus_DCP_Again The DCP channel is busy processing previous request. - */ -status_t DCP_AES_EncryptCbcNonBlocking(DCP_Type *base, - dcp_handle_t *handle, - dcp_work_packet_t *dcpPacket, - const uint8_t *plaintext, - uint8_t *ciphertext, - size_t size, - const uint8_t *iv) -{ - /* Size must be 16-byte multiple */ - if ((size < 16u) || (0U != (size % 16u))) - { - return kStatus_InvalidArgument; - } - - dcpPacket->control0 = - 0x322u | (handle->swapConfig & 0xFC0000u); /* CIPHER_INIT | CIPHER_ENCRYPT | ENABLE_CIPHER | DECR_SEMAPHORE */ - dcpPacket->control1 = 0x10u; /* CBC */ - dcpPacket->sourceBufferAddress = (uint32_t)plaintext; - dcpPacket->destinationBufferAddress = (uint32_t)ciphertext; - dcpPacket->bufferSize = (uint32_t)size; - - if (handle->keySlot == kDCP_OtpKey) - { - dcpPacket->payloadPointer = (uint32_t)iv; - dcpPacket->control0 |= ((uint32_t)1u << 10); /* OTP_KEY */ - dcpPacket->control1 |= ((uint32_t)0xFFu << 8); /* KEY_SELECT = OTP_KEY */ - } - else if (handle->keySlot == kDCP_OtpUniqueKey) - { - dcpPacket->payloadPointer = (uint32_t)iv; - dcpPacket->control0 |= ((uint32_t)1u << 10); /* OTP_KEY */ - dcpPacket->control1 |= ((uint32_t)0xFEu << 8); /* KEY_SELECT = UNIQUE_KEY */ - } - else if (handle->keySlot == kDCP_PayloadKey) - { - /* In this case payload must contain key & iv in one array. */ - /* Copy iv into handle right behind the keyWord[] so we can point payload to keyWord[]. */ - (void)dcp_memcpy(handle->iv, (const uint32_t *)(uintptr_t)iv, 16); - dcpPacket->payloadPointer = (uint32_t)&handle->keyWord[0]; - dcpPacket->control0 |= ((uint32_t)1u << 11); /* PAYLOAD_KEY */ - } - else - { - dcpPacket->payloadPointer = (uint32_t)iv; - dcpPacket->control1 |= ((uint32_t)handle->keySlot << 8); /* KEY_SELECT = keySlot */ - } - - return dcp_schedule_work(base, handle, dcpPacket); -} - -/*! - * brief Decrypts AES using CBC block mode. - * - * Decrypts AES using CBC block mode. - * The source ciphertext and destination plaintext can overlap in system memory. - * - * param base DCP peripheral base address - * param handle Handle used for this request. - * param ciphertext Input cipher text to decrypt - * param[out] plaintext Output plain text - * param size Size of input and output data in bytes. Must be multiple of 16 bytes. - * param iv Input initial vector to combine with the first input block. - * return Status from decrypt operation - */ -status_t DCP_AES_DecryptCbc(DCP_Type *base, - dcp_handle_t *handle, - const uint8_t *ciphertext, - uint8_t *plaintext, - size_t size, - const uint8_t iv[16]) -{ - status_t completionStatus = kStatus_Fail; - - /* Use extended DCACHE line size aligned structure */ -#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U) - dcp_work_packet_t *dcpWork; - uint8_t dcpWorkExt[sizeof(dcp_work_packet_t) + FSL_FEATURE_L1DCACHE_LINESIZE_BYTE] = {0U}; - dcpWork = (dcp_work_packet_t *)DCP_FindCacheLine(dcpWorkExt); -#else - dcp_work_packet_t dcpWorkPacket = {0}; - dcp_work_packet_t *dcpWork = &dcpWorkPacket; -#endif - - do - { - completionStatus = DCP_AES_DecryptCbcNonBlocking(base, handle, dcpWork, ciphertext, plaintext, size, iv); - } while (completionStatus == (int32_t)kStatus_DCP_Again); - - if (completionStatus != (int32_t)kStatus_Success) - { - return completionStatus; - } - - return DCP_WaitForChannelComplete(base, handle); -} - -/*! - * brief Decrypts AES using CBC block mode. - * - * Puts AES CBC decrypt dcpPacket to DCP input job ring. - * - * param base DCP peripheral base address - * param handle Handle used for this request. Specifies jobRing. - * param[out] dcpPacket Memory for the DCP work packet. - * param ciphertext Input cipher text to decrypt - * param[out] plaintext Output plain text - * param size Size of input and output data in bytes. Must be multiple of 16 bytes. - * param iv Input initial vector to combine with the first input block. - * return kStatus_Success The work packet has been scheduled at DCP channel. - * return kStatus_DCP_Again The DCP channel is busy processing previous request. - */ -status_t DCP_AES_DecryptCbcNonBlocking(DCP_Type *base, - dcp_handle_t *handle, - dcp_work_packet_t *dcpPacket, - const uint8_t *ciphertext, - uint8_t *plaintext, - size_t size, - const uint8_t *iv) -{ - /* Size must be 16-byte multiple */ - if ((size < 16u) || (0U != (size % 16u))) - { - return kStatus_InvalidArgument; - } - - dcpPacket->control0 = 0x222u | (handle->swapConfig & 0xFC0000u); /* CIPHER_INIT | ENABLE_CIPHER | DECR_SEMAPHORE */ - dcpPacket->control1 = 0x10u; /* CBC */ - dcpPacket->sourceBufferAddress = (uint32_t)ciphertext; - dcpPacket->destinationBufferAddress = (uint32_t)plaintext; - dcpPacket->bufferSize = (uint32_t)size; - - if (handle->keySlot == kDCP_OtpKey) - { - dcpPacket->payloadPointer = (uint32_t)iv; - dcpPacket->control0 |= ((uint32_t)1u << 10); /* OTP_KEY */ - dcpPacket->control1 |= ((uint32_t)0xFFu << 8); /* OTP_KEY */ - } - else if (handle->keySlot == kDCP_OtpUniqueKey) - { - dcpPacket->payloadPointer = (uint32_t)iv; - dcpPacket->control0 |= ((uint32_t)1u << 10); /* OTP_KEY */ - dcpPacket->control1 |= ((uint32_t)0xFEu << 8); /* UNIQUE_KEY */ - } - else if (handle->keySlot == kDCP_PayloadKey) - { - /* in this case payload must contain KEY + IV together */ - /* copy iv into handle struct so we can point payload directly to keyWord[]. */ - (void)dcp_memcpy(handle->iv, (const uint32_t *)(uintptr_t)iv, 16); - dcpPacket->payloadPointer = (uint32_t)&handle->keyWord[0]; - dcpPacket->control0 |= ((uint32_t)1u << 11); /* PAYLOAD_KEY */ - } - else - { - dcpPacket->payloadPointer = (uint32_t)iv; - dcpPacket->control1 |= ((uint32_t)handle->keySlot << 8); /* KEY_SELECT */ - } - - return dcp_schedule_work(base, handle, dcpPacket); -} - -/*! - * brief Gets the default configuration structure. - * - * This function initializes the DCP configuration structure to a default value. The default - * values are as follows. - * dcpConfig->gatherResidualWrites = true; - * dcpConfig->enableContextCaching = true; - * dcpConfig->enableContextSwitching = true; - * dcpConfig->enableChannnel = kDCP_chEnableAll; - * dcpConfig->enableChannelInterrupt = kDCP_chIntDisable; - * - * param[out] config Pointer to configuration structure. - */ -void DCP_GetDefaultConfig(dcp_config_t *config) -{ - /* ENABLE_CONTEXT_CACHING is disabled by default as the DCP Hash driver uses - * dcp_hash_save_running_hash() and dcp_hash_restore_running_hash() to support - * Hash context switch (different messages interleaved) on the same channel. - */ - - /* Initializes the configure structure to zero. */ - (void)memset(config, 0, sizeof(*config)); - - dcp_config_t userConfig = { - true, false, true, (uint8_t)kDCP_chEnableAll, (uint8_t)kDCP_chIntDisable, - }; - - *config = userConfig; -} - -/*! - * brief Enables clock to and enables DCP - * - * Enable DCP clock and configure DCP. - * - * param base DCP base address - * param config Pointer to configuration structure. - */ -void DCP_Init(DCP_Type *base, const dcp_config_t *config) -{ -#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) - CLOCK_EnableClock(kCLOCK_Dcp); -#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ - - base->CTRL = 0xF0800000u; /* reset value */ - base->CTRL = 0x30800000u; /* default value */ - - dcp_clear_status(base); - dcp_clear_channel_status( - base, (uint32_t)kDCP_Channel0 | (uint32_t)kDCP_Channel1 | (uint32_t)kDCP_Channel2 | (uint32_t)kDCP_Channel3); - - base->CTRL = DCP_CTRL_GATHER_RESIDUAL_WRITES(config->gatherResidualWrites) | - DCP_CTRL_ENABLE_CONTEXT_CACHING(config->enableContextCaching) | - DCP_CTRL_ENABLE_CONTEXT_SWITCHING(config->enableContextSwitching) | - DCP_CTRL_CHANNEL_INTERRUPT_ENABLE(config->enableChannelInterrupt); - - /* enable DCP channels */ - base->CHANNELCTRL = DCP_CHANNELCTRL_ENABLE_CHANNEL(config->enableChannel); - - /* use context switching buffer */ - base->CONTEXT = (uint32_t)&s_dcpContextSwitchingBuffer; -} - -/*! - * brief Disable DCP clock - * - * Reset DCP and Disable DCP clock. - * - * param base DCP base address - */ -void DCP_Deinit(DCP_Type *base) -{ - base->CTRL = 0xF0800000u; /* reset value */ - (void)memset(&s_dcpContextSwitchingBuffer, 0, sizeof(s_dcpContextSwitchingBuffer)); - -#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) - CLOCK_DisableClock(kCLOCK_Dcp); -#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ -} - -/*! - * brief Poll and wait on DCP channel. - * - * Polls the specified DCP channel until current it completes activity. - * - * param base DCP peripheral base address. - * param handle Specifies DCP channel. - * return kStatus_Success When data processing completes without error. - * return kStatus_Fail When error occurs. - */ -status_t DCP_WaitForChannelComplete(DCP_Type *base, dcp_handle_t *handle) -{ - /* wait if our channel is still active */ - while ((base->STAT & (uint32_t)handle->channel) == (uint32_t)handle->channel) - { - } - - if (dcp_get_channel_status(base, handle->channel) != kStatus_Success) - { - dcp_clear_status(base); - dcp_clear_channel_status(base, (uint32_t)handle->channel); - return kStatus_Fail; - } - - dcp_clear_status(base); - return kStatus_Success; -} - -/*! - * @brief Check validity of algoritm. - * - * This function checks the validity of input argument. - * - * @param algo Tested algorithm value. - * @return kStatus_Success if valid, kStatus_InvalidArgument otherwise. - */ -static status_t dcp_hash_check_input_alg(dcp_hash_algo_t algo) -{ - if ((algo != kDCP_Sha256) && (algo != kDCP_Sha1) && (algo != kDCP_Crc32)) - { - return kStatus_InvalidArgument; - } - return kStatus_Success; -} - -/*! - * @brief Check validity of input arguments. - * - * This function checks the validity of input arguments. - * - * @param base DCP peripheral base address. - * @param ctx Memory buffer given by user application where the DCP_HASH_Init/DCP_HASH_Update/DCP_HASH_Finish store - * context. - * @param algo Tested algorithm value. - * @return kStatus_Success if valid, kStatus_InvalidArgument otherwise. - */ -static status_t dcp_hash_check_input_args(DCP_Type *base, dcp_hash_ctx_t *ctx, dcp_hash_algo_t algo) -{ - /* Check validity of input algorithm */ - if (kStatus_Success != dcp_hash_check_input_alg(algo)) - { - return kStatus_InvalidArgument; - } - - if ((NULL == ctx) || (NULL == base)) - { - return kStatus_InvalidArgument; - } - - return kStatus_Success; -} - -/*! - * @brief Check validity of internal software context. - * - * This function checks if the internal context structure looks correct. - * - * @param ctxInternal Internal context. - * @param message Input message address. - * @return kStatus_Success if valid, kStatus_InvalidArgument otherwise. - */ -static status_t dcp_hash_check_context(dcp_hash_ctx_internal_t *ctxInternal, const uint8_t *message) -{ - if ((NULL == message) || (NULL == ctxInternal) || (kStatus_Success != dcp_hash_check_input_alg(ctxInternal->algo))) - { - return kStatus_InvalidArgument; - } - -#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U) - else if ((uint32_t)ctxInternal & (FSL_FEATURE_L1DCACHE_LINESIZE_BYTE - 1)) - { - /* ctx must be cache line aligned when using DCACHE */ - return kStatus_InvalidArgument; - } -#endif - - return kStatus_Success; -} - -/*! - * @brief Initialize the SHA engine for new hash. - * - * This function sets kDCP_CONTROL0_HASH_INIT for control0 in work packet to start a new hash. - * - * @param base SHA peripheral base address. - * @param ctxInternal Internal context. - */ -static status_t dcp_hash_engine_init(DCP_Type *base, dcp_hash_ctx_internal_t *ctxInternal) -{ - status_t status; - - status = kStatus_InvalidArgument; - - if ((kDCP_Sha256 == ctxInternal->algo) || (kDCP_Sha1 == ctxInternal->algo) || (kDCP_Crc32 == ctxInternal->algo)) - { - ctxInternal->ctrl0 = (uint32_t)kDCP_CONTROL0_HASH_INIT; - status = kStatus_Success; - } - - return status; -} - -static status_t dcp_hash_update_non_blocking( - DCP_Type *base, dcp_hash_ctx_internal_t *ctxInternal, dcp_work_packet_t *dcpPacket, const uint8_t *msg, size_t size) -{ - dcpPacket->control0 = ctxInternal->ctrl0 | (ctxInternal->handle->swapConfig & 0xFC0000u) | - (uint32_t)kDCP_CONTROL0_ENABLE_HASH | (uint32_t)kDCP_CONTROL0_DECR_SEMAPHOR; - if (ctxInternal->algo == kDCP_Sha256) - { - dcpPacket->control1 = (uint32_t)kDCP_CONTROL1_HASH_SELECT_SHA256; - } - else if (ctxInternal->algo == kDCP_Sha1) - { - dcpPacket->control1 = (uint32_t)kDCP_CONTROL1_HASH_SELECT_SHA1; - } - else if (ctxInternal->algo == kDCP_Crc32) - { - /* In CRC-32 case if size is zero, do not schedule other computing */ - if (size == 0U) - { -#if defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U) - /* Clear DCACHE memory before starting the engine */ - SCB_CleanDCache_by_Addr((uint32_t *)ctxInternal, sizeof(dcp_hash_ctx_internal_t)); -#endif - /* Make sure that all data memory accesses are completed before starting of the job */ - __DSB(); - __ISB(); - return kStatus_Success; - } - dcpPacket->control1 = (uint32_t)kDCP_CONTROL1_HASH_SELECT_CRC32; - } - else - { - return kStatus_Fail; - } - dcpPacket->sourceBufferAddress = (uint32_t)msg; - dcpPacket->destinationBufferAddress = 0; - dcpPacket->bufferSize = size; - dcpPacket->payloadPointer = (uint32_t)ctxInternal->runningHash; - -#if defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U) - /* Clear DCACHE memory before starting the engine */ - SCB_CleanDCache_by_Addr((uint32_t *)ctxInternal, sizeof(dcp_hash_ctx_internal_t)); -#endif - /* Make sure that all data memory accesses are completed before starting of the job */ - __DSB(); - __ISB(); - - return dcp_schedule_work(base, ctxInternal->handle, dcpPacket); -} - -static status_t dcp_hash_update(DCP_Type *base, dcp_hash_ctx_internal_t *ctxInternal, const uint8_t *msg, size_t size) -{ - status_t completionStatus = kStatus_Fail; - - /* Use extended DCACHE line size aligned structure */ -#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U) - dcp_work_packet_t *dcpWork; - uint8_t dcpWorkExt[sizeof(dcp_work_packet_t) + FSL_FEATURE_L1DCACHE_LINESIZE_BYTE] = {0U}; - dcpWork = (dcp_work_packet_t *)DCP_FindCacheLine(dcpWorkExt); -#else - dcp_work_packet_t dcpWorkPacket = {0}; - dcp_work_packet_t *dcpWork = &dcpWorkPacket; -#endif - - do - { - completionStatus = dcp_hash_update_non_blocking(base, ctxInternal, dcpWork, msg, size); - } while (completionStatus == (int32_t)kStatus_DCP_Again); - - completionStatus = DCP_WaitForChannelComplete(base, ctxInternal->handle); - - ctxInternal->ctrl0 = 0; /* clear kDCP_CONTROL0_HASH_INIT and kDCP_CONTROL0_HASH_TERM flags */ - return (completionStatus); -} - -/*! - * @brief Adds message to current hash. - * - * This function merges the message to fill the internal buffer, empties the internal buffer if - * it becomes full, then process all remaining message data. - * - * - * @param base DCP peripheral base address. - * @param ctxInternal Internal context. - * @param message Input message. - * @param messageSize Size of input message in bytes. - * @return kStatus_Success. - */ -static status_t dcp_hash_process_message_data(DCP_Type *base, - dcp_hash_ctx_internal_t *ctxInternal, - const uint8_t *message, - size_t messageSize) -{ - status_t status = kStatus_Fail; - - /* if there is partially filled internal buffer, fill it to full block */ - if (ctxInternal->blksz > 0U) - { - size_t toCopy = DCP_HASH_BLOCK_SIZE - ctxInternal->blksz; - (void)dcp_memcpy(&ctxInternal->blk.b[ctxInternal->blksz], message, toCopy); - message += toCopy; - messageSize -= toCopy; - - /* process full internal block */ - status = dcp_hash_update(base, ctxInternal, &ctxInternal->blk.b[0], DCP_HASH_BLOCK_SIZE); - if (kStatus_Success != status) - { - return status; - } - } - - /* process all full blocks in message[] */ - uint32_t fullBlocksSize = ((messageSize >> 6) << 6); /* (X / 64) * 64 */ - if (fullBlocksSize > 0U) - { - status = dcp_hash_update(base, ctxInternal, message, fullBlocksSize); - if (kStatus_Success != status) - { - return status; - } - message += fullBlocksSize; - messageSize -= fullBlocksSize; - } - - /* copy last incomplete message bytes into internal block */ - (void)dcp_memcpy(&ctxInternal->blk.b[0], message, messageSize); - ctxInternal->blksz = messageSize; - - return status; -} - -/*! - * @brief Finalize the running hash to make digest. - * - * This function empties the internal buffer, adds padding bits, and generates final digest. - * - * @param base SHA peripheral base address. - * @param ctxInternal Internal context. - * @return kStatus_Success. - */ -static status_t dcp_hash_finalize(DCP_Type *base, dcp_hash_ctx_internal_t *ctxInternal) -{ - status_t status; - - ctxInternal->ctrl0 |= (uint32_t)kDCP_CONTROL0_HASH_TERM; - status = dcp_hash_update(base, ctxInternal, &ctxInternal->blk.b[0], ctxInternal->blksz); - - return status; -} - -static void dcp_hash_save_running_hash(dcp_hash_ctx_internal_t *ctxInternal) -{ - uint32_t *srcAddr = NULL; - - switch (ctxInternal->handle->channel) - { - case kDCP_Channel0: - srcAddr = &s_dcpContextSwitchingBuffer.x[43]; - break; - - case kDCP_Channel1: - srcAddr = &s_dcpContextSwitchingBuffer.x[30]; - break; - - case kDCP_Channel2: - srcAddr = &s_dcpContextSwitchingBuffer.x[17]; - break; - - case kDCP_Channel3: - srcAddr = &s_dcpContextSwitchingBuffer.x[4]; - break; - - default: - /* All the cases have been listed above, the default clause should not be reached. */ - break; - } - if (srcAddr != NULL) - { - (void)dcp_memcpy(ctxInternal->runningHash, srcAddr, sizeof(ctxInternal->runningHash)); - } -} - -static void dcp_hash_restore_running_hash(dcp_hash_ctx_internal_t *ctxInternal) -{ - uint32_t *destAddr = NULL; - - switch (ctxInternal->handle->channel) - { - case kDCP_Channel0: - destAddr = &s_dcpContextSwitchingBuffer.x[43]; - break; - - case kDCP_Channel1: - destAddr = &s_dcpContextSwitchingBuffer.x[30]; - break; - - case kDCP_Channel2: - destAddr = &s_dcpContextSwitchingBuffer.x[17]; - break; - - case kDCP_Channel3: - destAddr = &s_dcpContextSwitchingBuffer.x[4]; - break; - - default: - /* No valid channel */ - break; - } - if (destAddr != NULL) - { - (void)dcp_memcpy(destAddr, ctxInternal->runningHash, sizeof(ctxInternal->runningHash)); - } -} - -/*! - * brief Initialize HASH context - * - * This function initializes the HASH. - * - * param base DCP peripheral base address - * param handle Specifies the DCP channel used for hashing. - * param[out] ctx Output hash context - * param algo Underlaying algorithm to use for hash computation. - * return Status of initialization - */ -status_t DCP_HASH_Init(DCP_Type *base, dcp_handle_t *handle, dcp_hash_ctx_t *ctx, dcp_hash_algo_t algo) -{ - status_t status; - - dcp_hash_ctx_internal_t *ctxInternal; -#ifndef __rtems__ - /* compile time check for the correct structure size */ - BUILD_ASSURE(sizeof(dcp_hash_ctx_t) >= sizeof(dcp_hash_ctx_internal_t), dcp_hash_ctx_t_size); -#else /* __rtems__ */ - assert(sizeof(dcp_hash_ctx_t) >= sizeof(dcp_hash_ctx_internal_t)); -#endif /* __rtems__ */ - uint32_t i; - - status = dcp_hash_check_input_args(base, ctx, algo); - if (status != kStatus_Success) - { - return status; - } - - /* set algorithm in context struct for later use */ - ctxInternal = (dcp_hash_ctx_internal_t *)(uint32_t)ctx; - ctxInternal->algo = algo; - ctxInternal->blksz = 0u; - - const uint32_t j = sizeof(ctxInternal->blk.w) / sizeof(ctxInternal->blk.w[0]); - for (i = 0; i < j; i++) - { - ctxInternal->blk.w[i] = 0u; - } - ctxInternal->state = kDCP_StateHashInit; - ctxInternal->fullMessageSize = 0; - ctxInternal->handle = handle; - return status; -} - -/*! - * brief Add data to current HASH - * - * Add data to current HASH. This can be called repeatedly with an arbitrary amount of data to be - * hashed. The functions blocks. If it returns kStatus_Success, the running hash - * has been updated (DCP has processed the input data), so the memory at ref input pointer - * can be released back to system. The DCP context buffer is updated with the running hash - * and with all necessary information to support possible context switch. - * - * param base DCP peripheral base address - * param[in,out] ctx HASH context - * param input Input data - * param inputSize Size of input data in bytes - * return Status of the hash update operation - */ -status_t DCP_HASH_Update(DCP_Type *base, dcp_hash_ctx_t *ctx, const uint8_t *input, size_t inputSize) -{ - bool isUpdateState; - status_t status; - dcp_hash_ctx_internal_t *ctxInternal; - size_t blockSize; - - if (inputSize == 0U) - { - return kStatus_Success; - } - - ctxInternal = (dcp_hash_ctx_internal_t *)(uint32_t)ctx; - status = dcp_hash_check_context(ctxInternal, input); - if (kStatus_Success != status) - { - return status; - } - - ctxInternal->fullMessageSize += inputSize; - blockSize = DCP_HASH_BLOCK_SIZE; - /* if we are still less than DCP_HASH_BLOCK_SIZE bytes, keep only in context */ - if ((ctxInternal->blksz + inputSize) <= blockSize) - { - (void)dcp_memcpy((&ctxInternal->blk.b[0]) + ctxInternal->blksz, input, inputSize); - ctxInternal->blksz += inputSize; - return status; - } - else - { - isUpdateState = ctxInternal->state == kDCP_StateHashUpdate; - if (!isUpdateState) - { - /* start NEW hash */ - status = dcp_hash_engine_init(base, ctxInternal); - if (status != kStatus_Success) - { - return status; - } - ctxInternal->state = kDCP_StateHashUpdate; - } - else - { - dcp_hash_restore_running_hash(ctxInternal); - } - } - - /* process input data */ - status = dcp_hash_process_message_data(base, ctxInternal, input, inputSize); - dcp_hash_save_running_hash(ctxInternal); - return status; -} - -/*! - * brief Finalize hashing - * - * Outputs the final hash (computed by DCP_HASH_Update()) and erases the context. - * - * param[in,out] ctx Input hash context - * param[out] output Output hash data - * param[in,out] outputSize Optional parameter (can be passed as NULL). On function entry, it specifies the size of - * output[] buffer. On function return, it stores the number of updated output bytes. - * return Status of the hash finish operation - */ -status_t DCP_HASH_Finish(DCP_Type *base, dcp_hash_ctx_t *ctx, uint8_t *output, size_t *outputSize) -{ - size_t algOutSize = 0; - status_t status; - dcp_hash_ctx_internal_t *ctxInternal; - - ctxInternal = (dcp_hash_ctx_internal_t *)(uint32_t)ctx; - status = dcp_hash_check_context(ctxInternal, output); - - if (kStatus_Success != status) - { - return status; - } - - if (ctxInternal->state == kDCP_StateHashInit) - { - status = dcp_hash_engine_init(base, ctxInternal); - if (status != kStatus_Success) - { - return status; - } - } - else - { - dcp_hash_restore_running_hash(ctxInternal); - } - - size_t outSize = 0u; - - /* compute algorithm output length */ - switch (ctxInternal->algo) - { - case kDCP_Sha256: - outSize = (uint32_t)kDCP_OutLenSha256; - break; - case kDCP_Sha1: - outSize = (uint32_t)kDCP_OutLenSha1; - break; - case kDCP_Crc32: - outSize = (uint32_t)kDCP_OutLenCrc32; - break; - default: - /* All the cases have been listed above, the default clause should not be reached. */ - break; - } - algOutSize = outSize; - -#if defined(DCP_HASH_CAVP_COMPATIBLE) - if (ctxInternal->fullMessageSize == 0U) - { - switch (ctxInternal->algo) - { - case kDCP_Sha256: - (void)dcp_memcpy(&output[0], &s_nullSha256, 32); - break; - case kDCP_Sha1: - (void)dcp_memcpy(&output[0], &s_nullSha1, 20); - break; - default: - /* All the cases have been listed above, the default clause should not be reached. */ - break; - } - - return kStatus_Success; - } -#endif /* DCP_HASH_CAVP_COMPATIBLE */ - - /* flush message last incomplete block, if there is any, and add padding bits */ - status = dcp_hash_finalize(base, ctxInternal); - - if (outputSize != NULL) - { - if (algOutSize < *outputSize) - { - *outputSize = algOutSize; - } - else - { - algOutSize = *outputSize; - } - } - -#if defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U) - SCB_InvalidateDCache_by_Addr(ctx, sizeof(dcp_hash_ctx_t)); -#endif - /* Reverse and copy result to output[] */ - dcp_reverse_and_copy((uint8_t *)ctxInternal->runningHash, &output[0], algOutSize); - - (void)memset(ctx, 0, sizeof(dcp_hash_ctx_t)); - return status; -} - -/*! - * brief Create HASH on given data - * - * Perform the full SHA or CRC32 in one function call. The function is blocking. - * - * param base DCP peripheral base address - * param handle Handle used for the request. - * param algo Underlaying algorithm to use for hash computation. - * param input Input data - * param inputSize Size of input data in bytes - * param[out] output Output hash data - * param[out] outputSize Output parameter storing the size of the output hash in bytes - * return Status of the one call hash operation. - */ -status_t DCP_HASH(DCP_Type *base, - dcp_handle_t *handle, - dcp_hash_algo_t algo, - const uint8_t *input, - size_t inputSize, - uint8_t *output, - size_t *outputSize) -{ - /* Use extended DCACHE line size aligned structure */ -#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U) - dcp_hash_ctx_t *hashCtx; - uint8_t hashCtxExt[sizeof(dcp_hash_ctx_t) + FSL_FEATURE_L1DCACHE_LINESIZE_BYTE] = {0U}; - hashCtx = (dcp_hash_ctx_t *)DCP_FindCacheLine(hashCtxExt); -#else - dcp_hash_ctx_t hashCtxStruct = {0}; - dcp_hash_ctx_t *hashCtx = &hashCtxStruct; -#endif - - status_t status; - - status = DCP_HASH_Init(base, handle, hashCtx, algo); - if (status != kStatus_Success) - { - return status; - } - - status = DCP_HASH_Update(base, hashCtx, input, inputSize); - if (status != kStatus_Success) - { - return status; - } - - status = DCP_HASH_Finish(base, hashCtx, output, outputSize); - - return status; -} |