blob: 405ec40d6f43e6ed4aabbb47441b81e0482c2920 [file] [log] [blame]
/*
* Copyright (c) 2015-2017, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
/*
* By default disable both asserts and log for this module.
* This must be done before DebugP.h is included.
*/
#ifndef DebugP_ASSERT_ENABLED
#define DebugP_ASSERT_ENABLED 0
#endif
#ifndef DebugP_LOG_ENABLED
#define DebugP_LOG_ENABLED 0
#endif
#include <ti/drivers/dpl/DebugP.h>
#include <ti/drivers/dpl/ClockP.h>
#include <ti/drivers/dpl/HwiP.h>
#include <ti/drivers/dpl/SemaphoreP.h>
#include <ti/drivers/Power.h>
#include <ti/drivers/power/PowerCC32XX.h>
#include <ti/drivers/crypto/CryptoCC32XX.h>
#include <ti/devices/cc32xx/inc/hw_types.h>
#include <ti/devices/cc32xx/inc/hw_ints.h>
#include <ti/devices/cc32xx/inc/hw_memmap.h>
#include <ti/devices/cc32xx/inc/hw_shamd5.h>
#include <ti/devices/cc32xx/driverlib/rom.h>
#include <ti/devices/cc32xx/driverlib/rom_map.h>
#include <ti/devices/cc32xx/driverlib/aes.h>
#include <ti/devices/cc32xx/driverlib/des.h>
#include <ti/devices/cc32xx/driverlib/shamd5.h>
#include <ti/devices/cc32xx/driverlib/prcm.h>
#define CryptoCC32XX_SHAMD5_SIGNATURE_LEN_MD5 16
#define CryptoCC32XX_SHAMD5_SIGNATURE_LEN_SHA1 20
#define CryptoCC32XX_SHAMD5_SIGNATURE_LEN_SHA224 28
#define CryptoCC32XX_SHAMD5_SIGNATURE_LEN_SHA256 32
#define CryptoCC32XX_CONTEXT_READY_MAX_COUNTER 1000
#define CryptoCC32XX_SHAMD5GetSignatureSize(_mode) ((_mode == SHAMD5_ALGO_MD5) ? CryptoCC32XX_SHAMD5_SIGNATURE_LEN_MD5: \
(_mode == SHAMD5_ALGO_SHA1) ? CryptoCC32XX_SHAMD5_SIGNATURE_LEN_SHA1: \
(_mode == SHAMD5_ALGO_SHA224) ? CryptoCC32XX_SHAMD5_SIGNATURE_LEN_SHA224: \
(_mode == SHAMD5_ALGO_SHA256) ? CryptoCC32XX_SHAMD5_SIGNATURE_LEN_SHA256:0)
#define SHAMD5_SIGNATURE_MAX_LEN CryptoCC32XX_SHAMD5_SIGNATURE_LEN_SHA256
typedef int8_t CryptoCC32XX_SHAMD5Signature[SHAMD5_SIGNATURE_MAX_LEN];
typedef struct CryptoCC32XX_HwiP {
/*! Crypto Peripheral's interrupt handler */
HwiP_Fxn hwiIntFxn;
/*! Crypto Peripheral's interrupt vector */
uint32_t intNum;
/*! Crypto Peripheral's interrupt priority */
uint32_t intPriority;
} CryptoCC32XX_HwiP;
/* Prototypes */
int32_t CryptoCC32XX_aesProcess(uint32_t cryptoMode , uint32_t cryptoDirection, uint8_t* pInBuff, uint16_t inLen, uint8_t* pOutBuff , CryptoCC32XX_EncryptParams* pParams);
int32_t CryptoCC32XX_desProcess(uint32_t cryptoMode , uint32_t cryptoDirection, uint8_t* pInBuff, uint16_t inLen, uint8_t* pOutBuff , CryptoCC32XX_EncryptParams* pParams);
int32_t CryptoCC32XX_shamd5Process(uint32_t cryptoMode , uint8_t* pBuff, uint32_t len, uint8_t *pSignature, CryptoCC32XX_HmacParams* pParams);
void CryptoCC32XX_aesIntHandler(void);
void CryptoCC32XX_desIntHandler(void);
void CryptoCC32XX_shamd5IntHandler(void);
HwiP_Handle CryptoCC32XX_register(CryptoCC32XX_Handle handle, CryptoCC32XX_HwiP *hwiP);
void CryptoCC32XX_unregister(HwiP_Handle handle);
/* Crypto CC32XX interrupts implementation */
CryptoCC32XX_HwiP CryptoCC32XX_HwiPTable[] = {
{ (HwiP_Fxn)CryptoCC32XX_aesIntHandler, INT_AES, (~0) }, /* AES */
{ (HwiP_Fxn)CryptoCC32XX_desIntHandler, INT_DES, (~0) }, /* DES */
{ (HwiP_Fxn)CryptoCC32XX_shamd5IntHandler, INT_SHA, (~0) } /* SHAMD5 */
};
/* Crypto AES key size to Crypto CC32XX AES key size */
#define CryptoCC32XX_getAesKeySize(_keySize) ( \
(_keySize == CryptoCC32XX_AES_KEY_SIZE_128BIT)? AES_CFG_KEY_SIZE_128BIT: \
(_keySize == CryptoCC32XX_AES_KEY_SIZE_192BIT)? AES_CFG_KEY_SIZE_192BIT: \
(_keySize == CryptoCC32XX_AES_KEY_SIZE_256BIT)? AES_CFG_KEY_SIZE_256BIT: \
CryptoCC32XX_STATUS_ERROR_NOT_SUPPORTED)
/* Crypto DES key size to Crypto CC32XX DES key size */
#define CryptoCC32XX_getDesKeySize(_keySize) ( \
(_keySize == CryptoCC32XX_DES_KEY_SIZE_SINGLE)? DES_CFG_SINGLE: \
(_keySize == CryptoCC32XX_DES_KEY_SIZE_TRIPLE)? DES_CFG_TRIPLE: \
CryptoCC32XX_STATUS_ERROR_NOT_SUPPORTED)
/* Crypto method to Crypto CC32XX mode */
#define CryptoCC32XX_getMode(_method) ( \
(_method == CryptoCC32XX_AES_ECB)? AES_CFG_MODE_ECB: \
(_method == CryptoCC32XX_AES_CBC)? AES_CFG_MODE_CBC: \
(_method == CryptoCC32XX_AES_CTR)? AES_CFG_MODE_CTR: \
(_method == CryptoCC32XX_AES_ICM)? AES_CFG_MODE_ICM: \
(_method == CryptoCC32XX_AES_CFB)? AES_CFG_MODE_CFB: \
(_method == CryptoCC32XX_AES_GCM)? AES_CFG_MODE_GCM_HY0CALC: \
(_method == CryptoCC32XX_AES_CCM)? AES_CFG_MODE_CCM: \
(_method == CryptoCC32XX_DES_ECB)? DES_CFG_MODE_ECB: \
(_method == CryptoCC32XX_DES_CBC)? DES_CFG_MODE_CBC: \
(_method == CryptoCC32XX_DES_CFB)? DES_CFG_MODE_CFB: \
(_method == CryptoCC32XX_HMAC_MD5)? SHAMD5_ALGO_MD5: \
(_method == CryptoCC32XX_HMAC_SHA1)? SHAMD5_ALGO_SHA1: \
(_method == CryptoCC32XX_HMAC_SHA224)? SHAMD5_ALGO_SHA224: \
(_method == CryptoCC32XX_HMAC_SHA256)? SHAMD5_ALGO_SHA256: \
CryptoCC32XX_STATUS_ERROR_NOT_SUPPORTED)
/* global variables for the interrupt handles */
static volatile bool g_bAESReadyFlag;
static volatile bool g_bDESReadyFlag;
static volatile bool g_bSHAMD5ReadyFlag;
/* Externs */
extern const CryptoCC32XX_Config CryptoCC32XX_config[];
extern const uint8_t CryptoCC32XX_count;
/*
* ======== CryptoCC32XX_close ========
*/
void CryptoCC32XX_close(CryptoCC32XX_Handle handle)
{
uintptr_t key;
CryptoCC32XX_Object *object = handle->object;
int32_t type;
/* Mask Crypto interrupts */
/* Power off the Crypto module */
Power_releaseDependency(PowerCC32XX_PERIPH_DTHE);
for (type = 0; type < CryptoCC32XX_MAX_TYPES;type++)
{
if (object->sem[type] != NULL)
{
SemaphoreP_delete(object->sem[type]);
}
if (object->hwiHandle[type] != NULL)
{
CryptoCC32XX_unregister(object->hwiHandle[type]);
}
}
/* Mark the module as available */
key = HwiP_disable();
object->isOpen = false;
HwiP_restore(key);
return;
}
/*
* ======== CryptoCC32XX_init ========
*/
void CryptoCC32XX_init(void)
{
}
/*
* ======== CryptoCC32XX_open ========
*/
CryptoCC32XX_Handle CryptoCC32XX_open(uint32_t index, uint32_t types)
{
CryptoCC32XX_Handle handle;
uintptr_t key;
CryptoCC32XX_Object *object;
SemaphoreP_Params semParams;
int32_t type;
if (index >= CryptoCC32XX_count)
{
return (NULL);
}
/* Get handle for this driver instance */
handle = (CryptoCC32XX_Handle)&(CryptoCC32XX_config[index]);
object = handle->object;
/* Determine if the device index was already opened */
key = HwiP_disable();
if(object->isOpen == true)
{
HwiP_restore(key);
return (NULL);
}
/* Mark the handle as being used */
object->isOpen = true;
HwiP_restore(key);
/* Power on the Crypto module */
Power_setDependency(PowerCC32XX_PERIPH_DTHE);
MAP_PRCMPeripheralReset(PRCM_DTHE);
/* create the semaphore for each crypto type*/
SemaphoreP_Params_init(&semParams);
semParams.mode = SemaphoreP_Mode_BINARY;
for (type=0 ;type < CryptoCC32XX_MAX_TYPES; type++)
{
if ((types & (1<<type)) != 0)
{
object->sem[type] = SemaphoreP_create(1, &semParams);
if (object->sem[type] == NULL)
{
CryptoCC32XX_close(handle);
return (NULL);
}
/* interrupt handler */
object->hwiHandle[type] = CryptoCC32XX_register(handle,&CryptoCC32XX_HwiPTable[type]);
if (object->hwiHandle[type] == NULL)
{
CryptoCC32XX_close(handle);
return (NULL);
}
}
else
{
object->sem[type] = NULL;
}
}
/* Return the address of the handle */
return (handle);
}
/*
* ======== CryptoCC32XX_HmacParams_init ========
*/
void CryptoCC32XX_HmacParams_init(CryptoCC32XX_HmacParams *params)
{
memset(params, 0, sizeof(CryptoCC32XX_HmacParams));
params->first = 1;
/* All supported hashing algorithms block size are equal, set one as default */
params->blockSize = CryptoCC32XX_SHA256_BLOCK_SIZE;
}
/*
* ======== CryptoCC32XX_encrypt ========
*/
int32_t CryptoCC32XX_encrypt(CryptoCC32XX_Handle handle, CryptoCC32XX_EncryptMethod method , void *pInBuff, size_t inLen, void *pOutBuff , size_t *outLen , CryptoCC32XX_EncryptParams *pParams)
{
CryptoCC32XX_Object *object = handle->object;
uint8_t cryptoType = method >> 8;
uint32_t cryptoMode = CryptoCC32XX_getMode((uint32_t)method);
int32_t status = CryptoCC32XX_STATUS_ERROR;
/* Convert crypto type bitwise to index */
uint8_t cryptoIndex = cryptoType >> 1;
/* check semaphore created */
if (object->sem[cryptoIndex] == NULL)
{
return CryptoCC32XX_STATUS_ERROR_NOT_SUPPORTED;
}
/* get the semaphore */
if (SemaphoreP_OK == SemaphoreP_pend(object->sem[cryptoIndex],
SemaphoreP_WAIT_FOREVER))
{
switch (cryptoType)
{
case CryptoCC32XX_AES:
status = CryptoCC32XX_aesProcess(cryptoMode , AES_CFG_DIR_ENCRYPT, pInBuff, inLen, pOutBuff , pParams);
break;
case CryptoCC32XX_DES:
status = CryptoCC32XX_desProcess(cryptoMode , DES_CFG_DIR_ENCRYPT, pInBuff, inLen, pOutBuff , pParams);
break;
default:
break;
}
/* release the semaphore */
SemaphoreP_post(object->sem[cryptoIndex]);
}
return status;
}
/*
* ======== CryptoCC32XX_decrypt ========
*/
int32_t CryptoCC32XX_decrypt(CryptoCC32XX_Handle handle, CryptoCC32XX_EncryptMethod method , void *pInBuff, size_t inLen, void *pOutBuff , size_t *outLen , CryptoCC32XX_EncryptParams *pParams)
{
CryptoCC32XX_Object *object = handle->object;
uint8_t cryptoType = method >> 8;
uint32_t cryptoMode = CryptoCC32XX_getMode((uint32_t)method);
int32_t status = CryptoCC32XX_STATUS_ERROR;
/* Convert crypto type bitwise to index */
uint8_t cryptoIndex = cryptoType >> 1;
/* check semaphore created */
if (object->sem[cryptoIndex] == NULL)
{
return CryptoCC32XX_STATUS_ERROR_NOT_SUPPORTED;
}
/* get the semaphore */
if (SemaphoreP_OK == SemaphoreP_pend(object->sem[cryptoIndex],
SemaphoreP_WAIT_FOREVER))
{
switch (cryptoType)
{
case CryptoCC32XX_AES:
status = CryptoCC32XX_aesProcess(cryptoMode , AES_CFG_DIR_DECRYPT, pInBuff, inLen, pOutBuff , pParams);
break;
case CryptoCC32XX_DES:
status = CryptoCC32XX_desProcess(cryptoMode , DES_CFG_DIR_DECRYPT, pInBuff, inLen, pOutBuff , pParams);
break;
default:
break;
}
/* release the semaphore */
SemaphoreP_post(object->sem[cryptoIndex]);
}
return status;
}
/*
* ======== CryptoCC32XX_sign ========
*/
int32_t CryptoCC32XX_sign(CryptoCC32XX_Handle handle, CryptoCC32XX_HmacMethod method , void *pBuff, size_t len, uint8_t *pSignature, CryptoCC32XX_HmacParams *pParams)
{
CryptoCC32XX_Object *object = handle->object;
uint8_t cryptoType = CryptoCC32XX_HMAC;
uint32_t cryptoMode = CryptoCC32XX_getMode((uint32_t)method);
int32_t status = CryptoCC32XX_STATUS_ERROR;
/* Convert crypto type bitwise to index */
uint8_t cryptoIndex = cryptoType >> 1;
/* check semaphore created */
if (object->sem[cryptoIndex] == NULL)
{
return CryptoCC32XX_STATUS_ERROR_NOT_SUPPORTED;
}
/* get the semaphore */
if (SemaphoreP_OK == SemaphoreP_pend(object->sem[cryptoIndex],
SemaphoreP_WAIT_FOREVER))
{
switch (cryptoType)
{
case CryptoCC32XX_HMAC:
status = CryptoCC32XX_shamd5Process(cryptoMode , pBuff, len, pSignature , pParams);
break;
default:
break;
}
/* release the semaphore */
SemaphoreP_post(object->sem[cryptoIndex]);
}
return status;
}
/*
* ======== CryptoCC32XX_verify ========
*/
int32_t CryptoCC32XX_verify(CryptoCC32XX_Handle handle, CryptoCC32XX_HmacMethod method , void *pBuff, size_t len, uint8_t *pSignature, CryptoCC32XX_HmacParams *pParams)
{
CryptoCC32XX_Object *object = handle->object;
uint8_t cryptoType = CryptoCC32XX_HMAC;
uint32_t cryptoMode = CryptoCC32XX_getMode((uint32_t)method);
int32_t status = CryptoCC32XX_STATUS_ERROR;
uint16_t shamd5SignatureSize;
CryptoCC32XX_SHAMD5Signature shamd5Signature;
/* Convert crypto type bitwise to index */
uint8_t cryptoIndex = cryptoType >> 1;
/* check semaphore created */
if (object->sem[cryptoIndex] == NULL)
{
return CryptoCC32XX_STATUS_ERROR_NOT_SUPPORTED;
}
/* get the semaphore */
if (SemaphoreP_OK == SemaphoreP_pend(object->sem[cryptoIndex],
SemaphoreP_WAIT_FOREVER))
{
switch (cryptoType)
{
case CryptoCC32XX_HMAC:
shamd5SignatureSize = CryptoCC32XX_SHAMD5GetSignatureSize(cryptoMode);
if (shamd5SignatureSize > 0)
{
if (pParams->moreData == 0)
{
/* save the received signature */
memcpy(shamd5Signature,pSignature,shamd5SignatureSize);
}
/* calculate the signature */
status = CryptoCC32XX_shamd5Process(cryptoMode , pBuff, len, pSignature , pParams);
/* compare the calculated signature to the received signature */
if (status == CryptoCC32XX_STATUS_SUCCESS)
{
if (pParams->moreData == 0)
{
if (memcmp(shamd5Signature,pSignature,shamd5SignatureSize) != 0)
{
status = CryptoCC32XX_STATUS_ERROR_VERIFY;
}
}
}
}
break;
default:
break;
}
/* release the semaphore */
SemaphoreP_post(object->sem[cryptoIndex]);
}
return status;
}
/*
* ======== CryptoCC32XX_shamd5Process ========
*/
int32_t CryptoCC32XX_shamd5Process(uint32_t cryptoMode , uint8_t *pBuff, uint32_t len, uint8_t *pSignature, CryptoCC32XX_HmacParams *pParams)
{
int32_t count = CryptoCC32XX_CONTEXT_READY_MAX_COUNTER;
uint32_t blockComplementLen = 0;
uint32_t newLen = 0;
uint32_t copyLen = 0;
uint32_t totalLen = 0;
uint32_t blockRemainder = 0;
/*
Step1: Enable Interrupts
Step2: Wait for Context Ready Interrupt
Step3: Set the Configuration Parameters (Hash Algorithm)
Step4: Set Key
Step5: Start Hash Generation
*/
if((pBuff == NULL) || (0 == len))
{
return CryptoCC32XX_STATUS_ERROR;
}
/* Clear the flag */
g_bSHAMD5ReadyFlag = false;
/* Enable interrupts. */
MAP_SHAMD5IntEnable(SHAMD5_BASE, SHAMD5_INT_CONTEXT_READY |
SHAMD5_INT_PARTHASH_READY |
SHAMD5_INT_INPUT_READY |
SHAMD5_INT_OUTPUT_READY);
/* Wait for the context ready flag. */
while ((!g_bSHAMD5ReadyFlag) && (count > 0))
{
count --;
}
if (count == 0)
{
return CryptoCC32XX_STATUS_ERROR;
}
if (pParams->moreData == 1)
{
/* Less than block size available. Copy the received data to the internal buffer and return */
if((pParams->buffLen + len) < pParams->blockSize)
{
memcpy(&pParams->buff[pParams->buffLen], pBuff, len);
pParams->buffLen += len;
return CryptoCC32XX_STATUS_SUCCESS;
}
if(pParams->first)
{
/* If Keyed Hashing is used, set Key */
if (pParams->pKey != NULL)
{
MAP_SHAMD5HMACKeySet(SHAMD5_BASE, pParams->pKey);
MAP_SHAMD5ConfigSet(SHAMD5_BASE, cryptoMode, 0, 0, 1, 0);
}
else
{
MAP_SHAMD5ConfigSet(SHAMD5_BASE, cryptoMode, 1, 0, 0, 0);
}
/* Will write data in this iteration. Unset first */
pParams->first = 0;
}
else
{
MAP_SHAMD5ConfigSet(SHAMD5_BASE, cryptoMode, 0, 0, 0, 0);
/* Write the intermediate digest and count in case it isn't the first round */
SHAMD5ResultWrite(SHAMD5_BASE, pParams->innerDigest);
SHAMD5WriteDigestCount(SHAMD5_BASE, pParams->digestCount);
}
}
else
{
if(pParams->first)
{
/* If Keyed Hashing is used, set Key */
if (pParams->pKey != NULL)
{
MAP_SHAMD5HMACKeySet(SHAMD5_BASE, pParams->pKey);
MAP_SHAMD5ConfigSet(SHAMD5_BASE, cryptoMode, 0, 1, 1, 1);
}
else
{
MAP_SHAMD5ConfigSet(SHAMD5_BASE, cryptoMode, 1, 1, 0, 0);
}
}
else
{
/* Write the intermediate digest and count in case it isn't the first round */
SHAMD5ResultWrite(SHAMD5_BASE, pParams->innerDigest);
SHAMD5WriteDigestCount(SHAMD5_BASE, pParams->digestCount);
if (pParams->pKey != NULL)
{
MAP_SHAMD5ConfigSet(SHAMD5_BASE, cryptoMode, 0, 1, 0, 1);
}
else
{
MAP_SHAMD5ConfigSet(SHAMD5_BASE, cryptoMode, 0, 1, 0, 0);
}
/* This is the last iteration for the requested calculation */
/* Set the first flag to 1 (initial value) for next calculations */
pParams->first = 1;
}
}
/* Set the length of the data that will be written to the SHA module in this iteration */
/* In case it isn't the last iteration, it has to be an integer multiple of block size */
if (pParams->moreData)
{
totalLen = ((pParams->buffLen + len) / pParams->blockSize) * pParams->blockSize;
}
else
{
totalLen = pParams->buffLen + len;
}
SHAMD5DataLengthSet(SHAMD5_BASE, totalLen);
/* In case there is data in the internal buffer, complement to a block size (if the length is sufficient) and write */
if (pParams->buffLen)
{
blockComplementLen = pParams->blockSize - pParams->buffLen;
/* Copy to the internal buffer */
/* The length to copy is the minimum between the block complement and the data length */
copyLen = len < blockComplementLen ? len : blockComplementLen;
memcpy(&pParams->buff[pParams->buffLen], pBuff, copyLen);
pParams->buffLen += copyLen;
/* If buffLen is smaller than block size this must be the last iteration */
/* Write and set the buffer and buffer length to zero */
SHAMD5DataWriteMultiple(SHAMD5_BASE, pParams->buff, pParams->buffLen);
pParams->buffLen = 0;
memset(pParams->buff, 0, sizeof(pParams->buff));
}
/* If data length is greater than block complement, write the rest of the data */
if (len > blockComplementLen)
{
newLen= len - blockComplementLen;
pBuff += blockComplementLen;
}
if (pParams->moreData)
{
/* Remaining length is smaller than block size - Save data to the internal buffer */
if (newLen < pParams->blockSize)
{
memcpy(&pParams->buff[pParams->buffLen], pBuff, newLen);
pParams->buffLen = newLen;
}
/* Remaining length is greater than block size - write blocks and save remainder to the internal buffer */
else
{
blockRemainder = newLen % pParams->blockSize;
newLen -= blockRemainder;
SHAMD5DataWriteMultiple(SHAMD5_BASE, pBuff, newLen);
if (blockRemainder)
{
pBuff += newLen;
memcpy(&pParams->buff[pParams->buffLen], pBuff, blockRemainder);
pParams->buffLen += blockRemainder;
}
}
}
else
{
/* Last iteration, write all the data */
if (newLen)
{
SHAMD5DataWriteMultiple(SHAMD5_BASE, pBuff, newLen);
}
}
/* Wait for the output to be ready */
while((HWREG(SHAMD5_BASE + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_OUTPUT_READY) == 0)
{
}
/* Read the result */
if (pParams->moreData == 1)
{
/* Read the digest and count to an internal parameter (will be used in the next iteration) */
MAP_SHAMD5ResultRead(SHAMD5_BASE, pParams->innerDigest);
SHAMD5ReadDigestCount(SHAMD5_BASE, &(pParams->digestCount));
}
else
{
/* Read the final digest result to an outer pointer */
MAP_SHAMD5ResultRead(SHAMD5_BASE, pSignature);
}
return CryptoCC32XX_STATUS_SUCCESS;
}
/*
* ======== CryptoCC32XX_aesProcess ========
*/
int32_t CryptoCC32XX_aesProcess(uint32_t cryptoMode , uint32_t cryptoDirection, uint8_t *pInBuff, uint16_t inLen, uint8_t *pOutBuff , CryptoCC32XX_EncryptParams *pParams)
{
int32_t count = CryptoCC32XX_CONTEXT_READY_MAX_COUNTER;
/*
Step1: Enable Interrupts
Step2: Wait for Context Ready Interrupt
Step3: Set the Configuration Parameters (Direction,AES Mode and Key Size)
Step4: Set the Initialization Vector
Step5: Write Key
Step6: Start the Crypt Process
*/
/* Clear the flag. */
g_bAESReadyFlag = false;
/* Enable all interrupts. */
MAP_AESIntEnable(AES_BASE, AES_INT_CONTEXT_IN | AES_INT_CONTEXT_OUT | AES_INT_DATA_IN | AES_INT_DATA_OUT);
/* Wait for the context in flag, the flag will be set in the Interrupt handler. */
while((!g_bAESReadyFlag) && (count > 0))
{
count --;
}
if (count == 0)
{
return CryptoCC32XX_STATUS_ERROR;
}
/* Configure the AES module with direction (encryption or decryption) and */
/* the key size. */
MAP_AESConfigSet(AES_BASE, cryptoDirection | cryptoMode | CryptoCC32XX_getAesKeySize(pParams->aes.keySize));
/* Write the initial value registers if needed, depends on the mode. */
if ((cryptoMode == AES_CFG_MODE_CBC) || (cryptoMode == AES_CFG_MODE_CFB) ||
(cryptoMode == AES_CFG_MODE_CTR) || (cryptoMode == AES_CFG_MODE_ICM) ||
(cryptoMode == AES_CFG_MODE_CCM) || (cryptoMode == AES_CFG_MODE_GCM_HY0CALC))
{
MAP_AESIVSet(AES_BASE, pParams->aes.pIV);
}
/* Write key1. */
MAP_AESKey1Set(AES_BASE, (uint8_t *)pParams->aes.pKey,CryptoCC32XX_getAesKeySize(pParams->aes.keySize));
/* Write key2. */
if (cryptoMode == AES_CFG_MODE_CCM)
{
MAP_AESKey2Set(AES_BASE, pParams->aes.aadParams.input.pKey2, CryptoCC32XX_getAesKeySize(pParams->aes.aadParams.input.key2Size));
}
/* Start Crypt Process */
if ((cryptoMode == AES_CFG_MODE_CCM) || (cryptoMode == AES_CFG_MODE_GCM_HY0CALC))
{
MAP_AESDataProcessAE(AES_BASE, (uint8_t *)(pInBuff+(pParams->aes.aadParams.input.len)), pOutBuff ,inLen, pInBuff, pParams->aes.aadParams.input.len, pParams->aes.aadParams.tag);
}
else
{
MAP_AESDataProcess(AES_BASE, pInBuff, pOutBuff, inLen);
}
/* Read the initial value registers if needed, depends on the mode. */
if ((cryptoMode == AES_CFG_MODE_CBC) || (cryptoMode == AES_CFG_MODE_CFB) ||
(cryptoMode == AES_CFG_MODE_CTR) || (cryptoMode == AES_CFG_MODE_ICM) ||
(cryptoMode == AES_CFG_MODE_CCM) || (cryptoMode == AES_CFG_MODE_GCM_HY0CALC))
{
MAP_AESIVGet(AES_BASE, pParams->aes.pIV);
}
return CryptoCC32XX_STATUS_SUCCESS;
}
/*
* ======== CryptoCC32XX_desProcess ========
*/
int32_t CryptoCC32XX_desProcess(uint32_t cryptoMode , uint32_t cryptoDirection, uint8_t *pInBuff, uint16_t inLen, uint8_t *pOutBuff , CryptoCC32XX_EncryptParams *pParams)
{
int32_t count = CryptoCC32XX_CONTEXT_READY_MAX_COUNTER;
/*
Step1: Enable Interrupts
Step2: Wait for Context Ready Interrupt
Step3: Set the Configuration Parameters (Direction,AES Mode)
Step4: Set the Initialization Vector
Step5: Write Key
Step6: Start the Crypt Process
*/
/* Clear the flag. */
g_bDESReadyFlag = false;
/* Enable all interrupts. */
MAP_DESIntEnable(DES_BASE, DES_INT_CONTEXT_IN | DES_INT_DATA_IN | DES_INT_DATA_OUT);
/* Wait for the context in flag. */
while((!g_bDESReadyFlag) && (count > 0))
{
count --;
}
if (count == 0)
{
return CryptoCC32XX_STATUS_ERROR;
}
/* Configure the DES module. */
MAP_DESConfigSet(DES_BASE, cryptoDirection | cryptoMode | CryptoCC32XX_getDesKeySize(pParams->des.keySize));
/* Set the key. */
MAP_DESKeySet(DES_BASE, (uint8_t *)pParams->des.pKey);
/* Write the initial value registers if needed. */
if((cryptoMode & DES_CFG_MODE_CBC) || (cryptoMode & DES_CFG_MODE_CFB))
{
MAP_DESIVSet(DES_BASE, pParams->des.pIV);
}
MAP_DESDataProcess(DES_BASE, pInBuff, pOutBuff,inLen);
return CryptoCC32XX_STATUS_SUCCESS;
}
/*
* ======== CryptoCC32XX_aesIntHandler ========
*/
void CryptoCC32XX_aesIntHandler(void)
{
uint32_t uiIntStatus;
/* Read the AES masked interrupt status. */
uiIntStatus = MAP_AESIntStatus(AES_BASE, true);
/* Set Different flags depending on the interrupt source. */
if(uiIntStatus & AES_INT_CONTEXT_IN)
{
MAP_AESIntDisable(AES_BASE, AES_INT_CONTEXT_IN);
g_bAESReadyFlag = true;
}
if(uiIntStatus & AES_INT_DATA_IN)
{
MAP_AESIntDisable(AES_BASE, AES_INT_DATA_IN);
}
if(uiIntStatus & AES_INT_CONTEXT_OUT)
{
MAP_AESIntDisable(AES_BASE, AES_INT_CONTEXT_OUT);
}
if(uiIntStatus & AES_INT_DATA_OUT)
{
MAP_AESIntDisable(AES_BASE, AES_INT_DATA_OUT);
}
}
/*
* ======== CryptoCC32XX_desIntHandler ========
*/
void CryptoCC32XX_desIntHandler(void)
{
uint32_t ui32IntStatus;
/* Read the DES masked interrupt status. */
ui32IntStatus = MAP_DESIntStatus(DES_BASE, true);
/* set flags depending on the interrupt source. */
if(ui32IntStatus & DES_INT_CONTEXT_IN)
{
MAP_DESIntDisable(DES_BASE, DES_INT_CONTEXT_IN);
g_bDESReadyFlag = true;
}
if(ui32IntStatus & DES_INT_DATA_IN)
{
MAP_DESIntDisable(DES_BASE, DES_INT_DATA_IN);
}
if(ui32IntStatus & DES_INT_DATA_OUT)
{
MAP_DESIntDisable(DES_BASE, DES_INT_DATA_OUT);
}
}
/*
* ======== CryptoCC32XX_shamd5IntHandler ========
*/
void CryptoCC32XX_shamd5IntHandler(void)
{
uint32_t ui32IntStatus;
/* Read the SHA/MD5 masked interrupt status. */
ui32IntStatus = MAP_SHAMD5IntStatus(SHAMD5_BASE, true);
if(ui32IntStatus & SHAMD5_INT_CONTEXT_READY)
{
MAP_SHAMD5IntDisable(SHAMD5_BASE, SHAMD5_INT_CONTEXT_READY);
g_bSHAMD5ReadyFlag = true;
}
if(ui32IntStatus & SHAMD5_INT_PARTHASH_READY)
{
MAP_SHAMD5IntDisable(SHAMD5_BASE, SHAMD5_INT_PARTHASH_READY);
}
if(ui32IntStatus & SHAMD5_INT_INPUT_READY)
{
MAP_SHAMD5IntDisable(SHAMD5_BASE, SHAMD5_INT_INPUT_READY);
}
if(ui32IntStatus & SHAMD5_INT_OUTPUT_READY)
{
MAP_SHAMD5IntDisable(SHAMD5_BASE, SHAMD5_INT_OUTPUT_READY);
}
}
/*
* ======== CryptoCC32XX_register ========
*/
HwiP_Handle CryptoCC32XX_register(CryptoCC32XX_Handle handle, CryptoCC32XX_HwiP *hwiP)
{
HwiP_Params hwiParams;
HwiP_Handle hwiHandle = NULL;
if (hwiP->hwiIntFxn != NULL)
{
/* Create Hwi object for this CryptoCC32XX peripheral. */
HwiP_Params_init(&hwiParams);
hwiParams.arg = (uintptr_t)handle;
hwiParams.priority = hwiP->intPriority;
hwiHandle = HwiP_create(hwiP->intNum, hwiP->hwiIntFxn,&hwiParams);
}
return hwiHandle;
}
/*
* ======== CryptoCC32XX_unregister ========
*/
void CryptoCC32XX_unregister(HwiP_Handle handle)
{
if (handle != NULL)
{
/* Delete Hwi object */
HwiP_delete(handle);
}
}