#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/port/st/stm32.h>
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#ifndef NO_AES
#include <wolfssl/wolfcrypt/aes.h>
#endif
#ifdef WOLFSSL_STM32_PKA
#include <stdint.h>
#if defined(WOLFSSL_STM32L5)
#include <stm32l5xx_hal_conf.h>
#include <stm32l5xx_hal_pka.h>
#elif defined(WOLFSSL_STM32U5)
#include <stm32u5xx_hal_conf.h>
#include <stm32u5xx_hal_pka.h>
#elif defined(WOLFSSL_STM32WB)
#include <stm32wbxx_hal_conf.h>
#include <stm32wbxx_hal_pka.h>
#elif defined(WOLFSSL_STM32WL)
#include <stm32wlxx_hal_conf.h>
#include <stm32wlxx_hal_pka.h>
#elif defined(WOLFSSL_STM32MP13)
#include <stm32mp13xx_hal_conf.h>
#include <stm32mp13xx_hal_pka.h>
#elif defined(WOLFSSL_STM32H7S)
#include <stm32h7rsxx_hal_conf.h>
#include <stm32h7rsxx_hal_pka.h>
#elif defined(WOLFSSL_STM32WBA)
#include <stm32wbaxx_hal_conf.h>
#include <stm32wbaxx_hal_pka.h>
#elif defined(WOLFSSL_STM32N6)
#include <stm32n6xx_hal_conf.h>
#include <stm32n6xx_hal_pka.h>
#elif defined(WOLFSSL_STM32H5)
#include <stm32h5xx_hal_conf.h>
#include <stm32h5xx_hal_pka.h>
#else
#error Please add the hal_pk.h include
#endif
extern PKA_HandleTypeDef hpka;
#if !defined(WOLFSSL_STM32_PKA_V2) && defined(PKA_ECC_SCALAR_MUL_IN_B_COEFF)
#define WOLFSSL_STM32_PKA_V2
#endif
#ifdef HAVE_ECC
#include <wolfssl/wolfcrypt/ecc.h>
#ifndef WOLFSSL_HAVE_ECC_KEY_GET_PRIV
#define wc_ecc_key_get_priv(key) (&((key)->k))
#define WOLFSSL_HAVE_ECC_KEY_GET_PRIV
#endif
#endif
#endif
#ifdef STM32_HASH
#ifndef STM32_HASH_CLOCK_ENABLE
static WC_INLINE void wc_Stm32_Hash_Clock_Enable(STM32_HASH_Context* stmCtx)
{
#ifdef WOLFSSL_STM32_CUBEMX
__HAL_RCC_HASH_CLK_ENABLE();
#else
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_HASH, ENABLE);
#endif
(void)stmCtx;
}
#define STM32_HASH_CLOCK_ENABLE(ctx) wc_Stm32_Hash_Clock_Enable(ctx)
#endif
#ifndef STM32_HASH_CLOCK_DISABLE
static WC_INLINE void wc_Stm32_Hash_Clock_Disable(STM32_HASH_Context* stmCtx)
{
#ifdef WOLFSSL_STM32_CUBEMX
__HAL_RCC_HASH_CLK_DISABLE();
#else
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_HASH, DISABLE);
#endif
(void)stmCtx;
}
#define STM32_HASH_CLOCK_DISABLE(ctx) wc_Stm32_Hash_Clock_Disable(ctx)
#endif
static void wc_Stm32_Hash_NumValidBits(word32 len)
{
word32 nbvalidbytesdata = (len % STM32_HASH_REG_SIZE);
HASH->STR &= ~HASH_STR_NBW;
HASH->STR |= (8 * nbvalidbytesdata) & HASH_STR_NBW;
#ifdef DEBUG_STM32_HASH
printf("STM Valid Last bits (%d)\n", 8 * nbvalidbytesdata);
#endif
}
static void wc_Stm32_Hash_SaveContext(STM32_HASH_Context* ctx)
{
int i;
ctx->HASH_IMR = HASH->IMR;
ctx->HASH_STR = HASH->STR;
ctx->HASH_CR = HASH->CR;
#ifdef STM32_HASH_SHA3
ctx->SHA3CFGR = HASH->SHA3CFGR;
#endif
for (i=0; i<HASH_CR_SIZE; i++) {
ctx->HASH_CSR[i] = HASH->CSR[i];
}
#ifdef DEBUG_STM32_HASH
printf("STM Save CR %lx, IMR %lx, STR %lx\n",
HASH->CR, HASH->IMR, HASH->STR);
#endif
}
static void wc_Stm32_Hash_RestoreContext(STM32_HASH_Context* ctx, word32 algo,
word32 mode)
{
int i;
if (ctx->HASH_CR == 0) {
#if defined(HASH_IMR_DINIE) && defined(HASH_IMR_DCIE)
HASH->IMR &= ~(HASH_IMR_DINIE | HASH_IMR_DCIE);
#endif
HASH->CR = (algo | mode | HASH_DATATYPE_8B | HASH_CR_INIT);
wc_Stm32_Hash_NumValidBits(0);
#ifdef DEBUG_STM32_HASH
printf("STM Init algo %x, mode %x, CR %lx, SR %lx\n",
(unsigned int)algo, (unsigned int)mode,
HASH->CR, HASH->SR);
#endif
}
else {
HASH->IMR = ctx->HASH_IMR;
HASH->STR = ctx->HASH_STR;
#ifdef STM32_HASH_SHA3
HASH->SHA3CFGR = ctx->SHA3CFGR;
#endif
HASH->CR = ctx->HASH_CR | HASH_CR_INIT;
for (i=0; i<HASH_CR_SIZE; i++) {
HASH->CSR[i] = ctx->HASH_CSR[i];
}
#ifdef DEBUG_STM32_HASH
printf("STM Restore CR %lx, IMR %lx, STR %lx\n",
HASH->CR, HASH->IMR, HASH->STR);
#endif
}
}
static void wc_Stm32_Hash_GetDigest(byte* hash, int digestSize)
{
word32 digest[HASH_MAX_DIGEST/sizeof(word32)];
int i = 0, sz;
if (digestSize > HASH_MAX_DIGEST)
digestSize = HASH_MAX_DIGEST;
sz = digestSize;
while (sz > 0) {
if (i < 5) {
digest[i] = HASH->HR[i];
}
#ifdef HASH_DIGEST
else {
digest[i] = HASH_DIGEST->HR[i];
}
#endif
i++;
sz -= 4;
}
ByteReverseWords(digest, digest, digestSize);
XMEMCPY(hash, digest, digestSize);
#ifdef DEBUG_STM32_HASH
{
word32 ii;
printf("STM Digest %d\n", digestSize);
for (ii=0; ii<digestSize/sizeof(word32); ii++) {
printf("\tDIG 0x%04x\n", digest[ii]);
}
}
#endif
}
static int wc_Stm32_Hash_WaitDataReady(STM32_HASH_Context* stmCtx)
{
int timeout = 0;
(void)stmCtx;
while (((HASH->SR & HASH_SR_BUSY)
#ifdef HASH_IMR_DINIE
|| (HASH->SR & HASH_SR_DINIS) == 0
#endif
) && ++timeout < STM32_HASH_TIMEOUT) {
};
#ifdef DEBUG_STM32_HASH
printf("STM Wait Data %d, HASH->SR %lx\n", timeout, HASH->SR);
#endif
if (timeout >= STM32_HASH_TIMEOUT) {
return WC_TIMEOUT_E;
}
return 0;
}
static int wc_Stm32_Hash_WaitCalcComp(STM32_HASH_Context* stmCtx)
{
int timeout = 0;
(void)stmCtx;
while (((HASH->SR & HASH_SR_BUSY)
#ifdef HASH_IMR_DCIE
|| (HASH->SR & HASH_SR_DCIS) == 0
#endif
) && ++timeout < STM32_HASH_TIMEOUT) {
};
#ifdef DEBUG_STM32_HASH
printf("STM Wait Calc %d, HASH->SR %lx\n", timeout, HASH->SR);
#endif
if (timeout >= STM32_HASH_TIMEOUT) {
return WC_TIMEOUT_E;
}
return 0;
}
static void wc_Stm32_Hash_Data(STM32_HASH_Context* stmCtx, word32 len)
{
word32 i, blocks;
if (len > stmCtx->buffLen)
len = stmCtx->buffLen;
blocks = ((len + STM32_HASH_REG_SIZE-1) / STM32_HASH_REG_SIZE);
#ifdef DEBUG_STM32_HASH
printf("STM DIN %d blocks\n", blocks);
#endif
for (i=0; i<blocks; i++) {
#ifdef DEBUG_STM32_HASH
printf("\tDIN 0x%04x\n", stmCtx->buffer[i]);
#endif
HASH->DIN = stmCtx->buffer[i];
}
stmCtx->loLen += len;
stmCtx->buffLen -= len;
if (stmCtx->buffLen > 0) {
XMEMMOVE(stmCtx->buffer, (byte*)stmCtx->buffer+len, stmCtx->buffLen);
}
}
void wc_Stm32_Hash_Init(STM32_HASH_Context* stmCtx)
{
XMEMSET(stmCtx, 0, sizeof(STM32_HASH_Context));
}
int wc_Stm32_Hash_Update(STM32_HASH_Context* stmCtx, word32 algo,
const byte* data, word32 len, word32 blockSize)
{
int ret = 0;
byte* local = (byte*)stmCtx->buffer;
int wroteToFifo = 0;
word32 chunkSz;
#ifdef DEBUG_STM32_HASH
printf("STM Hash Update: algo %x, len %d, buffLen %d, fifoBytes %d\n",
algo, len, stmCtx->buffLen, stmCtx->fifoBytes);
#endif
(void)blockSize;
if (stmCtx->buffLen > (word32)sizeof(stmCtx->buffer)) {
return BUFFER_E;
}
STM32_HASH_CLOCK_ENABLE(stmCtx);
wc_Stm32_Hash_RestoreContext(stmCtx, algo, HASH_ALGOMODE_HASH);
while (len) {
word32 add;
chunkSz = blockSize;
if (!stmCtx->fifoBytes) {
chunkSz += STM32_HASH_REG_SIZE;
}
add = min(len, chunkSz - stmCtx->buffLen);
XMEMCPY(&local[stmCtx->buffLen], data, add);
stmCtx->buffLen += add;
data += add;
len -= add;
if (stmCtx->buffLen == chunkSz) {
wc_Stm32_Hash_Data(stmCtx, stmCtx->buffLen);
wroteToFifo = 1;
stmCtx->fifoBytes += chunkSz;
}
}
if (wroteToFifo) {
ret = wc_Stm32_Hash_WaitDataReady(stmCtx);
wc_Stm32_Hash_SaveContext(stmCtx);
}
STM32_HASH_CLOCK_DISABLE(stmCtx);
return ret;
}
int wc_Stm32_Hash_Final(STM32_HASH_Context* stmCtx, word32 algo,
byte* hash, word32 digestSize)
{
int ret = 0;
#ifdef DEBUG_STM32_HASH
printf("STM Hash Final: algo %x, digestSz %d, buffLen %d, fifoBytes %d\n",
algo, digestSize, stmCtx->buffLen, stmCtx->fifoBytes);
#endif
STM32_HASH_CLOCK_ENABLE(stmCtx);
wc_Stm32_Hash_RestoreContext(stmCtx, algo, HASH_ALGOMODE_HASH);
if (stmCtx->buffLen > 0) {
wc_Stm32_Hash_Data(stmCtx, stmCtx->buffLen);
}
wc_Stm32_Hash_NumValidBits(stmCtx->loLen + stmCtx->buffLen);
HASH->STR |= HASH_STR_DCAL;
ret = wc_Stm32_Hash_WaitCalcComp(stmCtx);
if (ret == 0) {
wc_Stm32_Hash_GetDigest(hash, digestSize);
}
STM32_HASH_CLOCK_DISABLE(stmCtx);
return ret;
}
#if defined(STM32_HMAC) && !defined(NO_HMAC)
#include <wolfssl/wolfcrypt/hmac.h>
int wc_Stm32_Hmac_GetAlgoInfo(int macType, word32* algo, word32* blockSize,
word32* digestSize)
{
int ret = 0;
switch (macType) {
#if !defined(NO_MD5) && !defined(STM32_NOMD5)
case WC_MD5:
if (algo) *algo = HASH_AlgoSelection_MD5;
if (blockSize) *blockSize = WC_MD5_BLOCK_SIZE;
if (digestSize) *digestSize = WC_MD5_DIGEST_SIZE;
break;
#endif
#ifndef NO_SHA
case WC_SHA:
if (algo) *algo = HASH_AlgoSelection_SHA1;
if (blockSize) *blockSize = WC_SHA_BLOCK_SIZE;
if (digestSize) *digestSize = WC_SHA_DIGEST_SIZE;
break;
#endif
#ifdef WOLFSSL_SHA224
case WC_SHA224:
if (algo) *algo = HASH_AlgoSelection_SHA224;
if (blockSize) *blockSize = WC_SHA224_BLOCK_SIZE;
if (digestSize) *digestSize = WC_SHA224_DIGEST_SIZE;
break;
#endif
#ifndef NO_SHA256
case WC_SHA256:
if (algo) *algo = HASH_AlgoSelection_SHA256;
if (blockSize) *blockSize = WC_SHA256_BLOCK_SIZE;
if (digestSize) *digestSize = WC_SHA256_DIGEST_SIZE;
break;
#endif
#if defined(STM32_HASH_SHA384) && defined(WOLFSSL_SHA384)
case WC_SHA384:
if (algo) *algo = HASH_ALGOSELECTION_SHA384;
if (blockSize) *blockSize = WC_SHA384_BLOCK_SIZE;
if (digestSize) *digestSize = WC_SHA384_DIGEST_SIZE;
break;
#endif
#if defined(STM32_HASH_SHA512) && defined(WOLFSSL_SHA512)
case WC_SHA512:
if (algo) *algo = HASH_ALGOSELECTION_SHA512;
if (blockSize) *blockSize = WC_SHA512_BLOCK_SIZE;
if (digestSize) *digestSize = WC_SHA512_DIGEST_SIZE;
break;
#endif
default:
ret = BAD_FUNC_ARG;
break;
}
return ret;
}
static void wc_Stm32_Hmac_FeedKey(const byte* key, word32 keySz)
{
word32 i, blocks;
word32 tmp;
blocks = keySz / STM32_HASH_REG_SIZE;
for (i = 0; i < blocks; i++) {
XMEMCPY(&tmp, key + (i * STM32_HASH_REG_SIZE), STM32_HASH_REG_SIZE);
HASH->DIN = tmp;
}
if (keySz % STM32_HASH_REG_SIZE) {
tmp = 0;
XMEMCPY(&tmp, key + (blocks * STM32_HASH_REG_SIZE),
keySz % STM32_HASH_REG_SIZE);
HASH->DIN = tmp;
}
ForceZero(&tmp, sizeof(tmp));
#ifdef DEBUG_STM32_HASH
printf("STM HMAC FeedKey %d bytes\n", (int)keySz);
#endif
}
int wc_Stm32_Hmac_SetKey(STM32_HASH_Context* stmCtx, int macType,
const byte* key, word32 keySz)
{
int ret;
word32 algo, blockSize, digestSize;
word32 mode;
if (stmCtx == NULL || key == NULL)
return BAD_FUNC_ARG;
ret = wc_Stm32_Hmac_GetAlgoInfo(macType, &algo, &blockSize, &digestSize);
if (ret != 0)
return ret;
#ifdef DEBUG_STM32_HASH
printf("STM HMAC SetKey: macType %d, keySz %d\n", macType, (int)keySz);
#endif
wc_Stm32_Hash_Init(stmCtx);
STM32_HASH_CLOCK_ENABLE(stmCtx);
mode = HASH_ALGOMODE_HMAC;
wc_Stm32_Hash_RestoreContext(stmCtx, algo, mode);
wc_Stm32_Hmac_FeedKey(key, keySz);
wc_Stm32_Hash_NumValidBits(keySz);
HASH->STR |= HASH_STR_DCAL;
ret = wc_Stm32_Hash_WaitDataReady(stmCtx);
if (ret == 0) {
wc_Stm32_Hash_SaveContext(stmCtx);
}
STM32_HASH_CLOCK_DISABLE(stmCtx);
return ret;
}
int wc_Stm32_Hmac_Final(STM32_HASH_Context* stmCtx, word32 algo,
const byte* key, word32 keySz, byte* hash, word32 digestSize)
{
int ret;
if (stmCtx == NULL || key == NULL || hash == NULL)
return BAD_FUNC_ARG;
#ifdef DEBUG_STM32_HASH
printf("STM HMAC Final: algo %x, keySz %d, buffLen %d, fifoBytes %d\n",
(unsigned int)algo, (int)keySz, (int)stmCtx->buffLen,
(int)stmCtx->fifoBytes);
#endif
STM32_HASH_CLOCK_ENABLE(stmCtx);
wc_Stm32_Hash_RestoreContext(stmCtx, algo, HASH_ALGOMODE_HMAC);
if (stmCtx->buffLen > 0) {
wc_Stm32_Hash_Data(stmCtx, stmCtx->buffLen);
}
wc_Stm32_Hash_NumValidBits(stmCtx->loLen + stmCtx->buffLen);
HASH->STR |= HASH_STR_DCAL;
ret = wc_Stm32_Hash_WaitDataReady(stmCtx);
if (ret != 0) {
STM32_HASH_CLOCK_DISABLE(stmCtx);
return ret;
}
wc_Stm32_Hmac_FeedKey(key, keySz);
wc_Stm32_Hash_NumValidBits(keySz);
HASH->STR |= HASH_STR_DCAL;
ret = wc_Stm32_Hash_WaitCalcComp(stmCtx);
if (ret == 0) {
wc_Stm32_Hash_GetDigest(hash, digestSize);
}
STM32_HASH_CLOCK_DISABLE(stmCtx);
return ret;
}
#endif
#endif
#ifdef STM32_CRYPTO
#ifndef NO_AES
#ifdef WOLFSSL_STM32_CUBEMX
#if defined(WOLFSSL_STM32U5_DHUK)
int wc_Stm32_Aes_SetDHUK_IV(struct Aes* aes, const byte* iv, int ivSz)
{
if (ivSz != sizeof(aes->dhukIV)) {
return BAD_FUNC_ARG;
}
XMEMCPY(aes->dhukIV, iv, ivSz);
aes->dhukIVLen = ivSz;
return 0;
}
int wc_Stm32_Aes_Wrap(struct Aes* aes, const byte* in, word32 inSz, byte* out,
word32* outSz, const byte* iv, int ivSz)
{
CRYP_HandleTypeDef hcryp;
int ret = 0;
byte key[AES_256_KEY_SIZE];
__HAL_RCC_RNG_CLK_ENABLE();
ByteReverseWords((word32*)key, (word32*)in, inSz);
XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef));
if (ret == 0) {
hcryp.Instance = SAES;
hcryp.Init.DataType = CRYP_DATATYPE_8B;
hcryp.Init.KeySize = CRYP_KEYSIZE_256B;
hcryp.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_BYTE;
hcryp.Init.KeySelect = CRYP_KEYSEL_HW;
hcryp.Init.KeyMode = CRYP_KEYMODE_WRAPPED;
if (iv != NULL) {
hcryp.Init.pInitVect = (uint32_t *)iv;
hcryp.Init.Algorithm = CRYP_AES_CBC;
}
else {
hcryp.Init.Algorithm = CRYP_AES_ECB;
}
ret = HAL_CRYP_Init(&hcryp);
}
if (ret == HAL_OK) {
ret = HAL_CRYPEx_WrapKey(&hcryp, (uint32_t*)key, (uint32_t*)out, 100);
HAL_CRYP_DeInit(&hcryp);
}
ForceZero(key, sizeof(key));
ByteReverseWords((word32*)out, (word32*)out, inSz);
*outSz = inSz;
(void)aes;
return ret;
}
int wc_Stm32_Aes_UnWrap(struct Aes* aes, CRYP_HandleTypeDef* hcryp,
const byte* in, word32 inSz, const byte* iv, int ivSz)
{
int ret = 0;
__HAL_RCC_RNG_CLK_ENABLE();
XMEMSET(hcryp, 0, sizeof(CRYP_HandleTypeDef));
hcryp->Instance = SAES;
hcryp->Init.DataType = CRYP_DATATYPE_8B;
hcryp->Init.KeySize = CRYP_KEYSIZE_256B;
hcryp->Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_BYTE;
if (ivSz > 0 && iv != NULL) {
hcryp->Init.pInitVect = (uint32_t *)iv;
hcryp->Init.Algorithm = CRYP_AES_CBC;
}
else {
hcryp->Init.Algorithm = CRYP_AES_ECB;
}
hcryp->Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ALWAYS;
hcryp->Init.KeySelect = CRYP_KEYSEL_HW;
hcryp->Init.KeyMode = CRYP_KEYMODE_WRAPPED;
ret = HAL_CRYP_Init(hcryp);
if (ret == HAL_OK) {
ret = HAL_CRYPEx_UnwrapKey(hcryp, (uint32_t*)in, 100);
}
return ret;
}
#endif
int wc_Stm32_Aes_Init(Aes* aes, CRYP_HandleTypeDef* hcryp, int useSaes)
{
int ret;
word32 keySize;
#ifdef STM32_HW_CLOCK_AUTO
__HAL_RCC_CRYP_CLK_ENABLE();
#endif
ret = wc_AesGetKeySize(aes, &keySize);
if (ret != 0)
return ret;
XMEMSET(hcryp, 0, sizeof(CRYP_HandleTypeDef));
switch (keySize) {
case 16:
hcryp->Init.KeySize = CRYP_KEYSIZE_128B;
break;
#ifdef CRYP_KEYSIZE_192B
case 24:
hcryp->Init.KeySize = CRYP_KEYSIZE_192B;
break;
#endif
case 32:
hcryp->Init.KeySize = CRYP_KEYSIZE_256B;
break;
default:
break;
}
#ifdef WOLFSSL_STM32U5_DHUK
if (useSaes && (aes->devId == WOLFSSL_STM32U5_DHUK_DEVID ||
aes->devId == WOLFSSL_STM32U5_SAES_DEVID)) {
__HAL_RCC_RNG_CLK_ENABLE();
hcryp->Instance = SAES;
hcryp->Init.DataType = CRYP_DATATYPE_8B;
if (aes->devId == WOLFSSL_STM32U5_DHUK_DEVID) {
hcryp->Init.KeySelect = CRYP_KEYSEL_HW;
}
else {
hcryp->Init.KeySelect = CRYP_KEYSEL_NORMAL;
hcryp->Init.KeyMode = CRYP_KEYMODE_NORMAL;
hcryp->Init.pKey = (uint32_t*)aes->key;
}
} else
#endif
{
hcryp->Instance = CRYP;
hcryp->Init.DataType = CRYP_DATATYPE_8B;
hcryp->Init.pKey = (STM_CRYPT_TYPE*)aes->key;
}
#ifdef STM32_HAL_V2
hcryp->Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_BYTE;
#if defined(CRYP_HEADERWIDTHUNIT_BYTE) && defined(STM_CRYPT_HEADER_WIDTH)
hcryp->Init.HeaderWidthUnit =
(STM_CRYPT_HEADER_WIDTH == 4) ?
CRYP_HEADERWIDTHUNIT_WORD :
CRYP_HEADERWIDTHUNIT_BYTE;
#endif
#endif
return 0;
}
void wc_Stm32_Aes_Cleanup(void)
{
#ifdef STM32_HW_CLOCK_AUTO
__HAL_RCC_CRYP_CLK_DISABLE();
#endif
}
#else
int wc_Stm32_Aes_Init(Aes* aes, CRYP_InitTypeDef* cryptInit,
CRYP_KeyInitTypeDef* keyInit)
{
int ret;
word32 keySize;
word32* aes_key;
ret = wc_AesGetKeySize(aes, &keySize);
if (ret != 0)
return ret;
aes_key = aes->key;
CRYP_KeyStructInit(keyInit);
CRYP_StructInit(cryptInit);
switch (keySize) {
case 16:
cryptInit->CRYP_KeySize = CRYP_KeySize_128b;
keyInit->CRYP_Key2Left = aes_key[0];
keyInit->CRYP_Key2Right = aes_key[1];
keyInit->CRYP_Key3Left = aes_key[2];
keyInit->CRYP_Key3Right = aes_key[3];
break;
case 24:
cryptInit->CRYP_KeySize = CRYP_KeySize_192b;
keyInit->CRYP_Key1Left = aes_key[0];
keyInit->CRYP_Key1Right = aes_key[1];
keyInit->CRYP_Key2Left = aes_key[2];
keyInit->CRYP_Key2Right = aes_key[3];
keyInit->CRYP_Key3Left = aes_key[4];
keyInit->CRYP_Key3Right = aes_key[5];
break;
case 32:
cryptInit->CRYP_KeySize = CRYP_KeySize_256b;
keyInit->CRYP_Key0Left = aes_key[0];
keyInit->CRYP_Key0Right = aes_key[1];
keyInit->CRYP_Key1Left = aes_key[2];
keyInit->CRYP_Key1Right = aes_key[3];
keyInit->CRYP_Key2Left = aes_key[4];
keyInit->CRYP_Key2Right = aes_key[5];
keyInit->CRYP_Key3Left = aes_key[6];
keyInit->CRYP_Key3Right = aes_key[7];
break;
default:
break;
}
cryptInit->CRYP_DataType = CRYP_DataType_8b;
return 0;
}
void wc_Stm32_Aes_Cleanup(void)
{
}
#endif
#endif
#endif
#ifdef WOLFSSL_STM32_PKA
#ifdef HAVE_ECC
static int stm32_get_from_mp_int(uint8_t *dst, const mp_int *a, int sz)
{
int res, szbin, offset;
if (dst == NULL || a == NULL || sz < 0)
return BAD_FUNC_ARG;
szbin = mp_unsigned_bin_size(a);
if (szbin < 0 || szbin > sz)
return BUFFER_E;
offset = sz - szbin;
if (offset < 0)
offset = 0;
if (offset > sz)
offset = sz;
if (offset)
XMEMSET(dst, 0, offset);
res = mp_to_unsigned_bin(a, dst + offset);
return res;
}
static int stm32_getabs_from_mp_int(uint8_t *dst, const mp_int *a, int sz,
uint32_t* abs_sign)
{
int res;
mp_int x;
if (dst == NULL || a == NULL || sz < 0 || abs_sign == NULL)
return BAD_FUNC_ARG;
res = mp_init(&x);
if (res == MP_OKAY) {
#if defined(USE_FAST_MATH) || defined(USE_INTEGER_HEAP_MATH) || \
((defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL)) && \
defined(WOLFSSL_SP_INT_NEGATIVE))
*abs_sign = x.sign;
#else
*abs_sign = 1;
#endif
res = mp_abs((mp_int*)a, &x);
if (res == MP_OKAY)
res = stm32_get_from_mp_int(dst, &x, sz);
mp_clear(&x);
}
return res;
}
static int stm32_getabs_from_hexstr(const char* hex, uint8_t* dst, int sz,
uint32_t *abs_sign)
{
int res;
mp_int x;
if (hex == NULL || dst == NULL || sz < 0)
return BAD_FUNC_ARG;
res = mp_init(&x);
if (res == MP_OKAY) {
res = mp_read_radix(&x, hex, MP_RADIX_HEX);
if (res == MP_OKAY && abs_sign != NULL) {
#if defined(USE_FAST_MATH) || defined(USE_INTEGER_HEAP_MATH) || \
((defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL)) && \
defined(WOLFSSL_SP_INT_NEGATIVE))
*abs_sign = x.sign;
#else
*abs_sign = 1;
#endif
res = mp_abs(&x, &x);
}
if (res == MP_OKAY)
res = stm32_get_from_mp_int(dst, &x, sz);
mp_clear(&x);
}
return res;
}
static int stm32_get_from_hexstr(const char* hex, uint8_t* dst, int sz)
{
return stm32_getabs_from_hexstr(hex, dst, sz, NULL);
}
#define STM32_MAX_ECC_SIZE (80)
#ifdef WOLFSSL_STM32_PKA_V2
static int stm32_get_curve_params(mp_int* modulus,
uint8_t* order, uint8_t* coefB)
{
int res, i, found = 0;
mp_int modulusChk;
res = mp_init(&modulusChk);
if (res != MP_OKAY)
return res;
for (i = 0; ecc_sets[i].size != 0 && ecc_sets[i].name != NULL; i++) {
const ecc_set_type* curve = &ecc_sets[i];
if ((res = mp_read_radix(&modulusChk, curve->prime, MP_RADIX_HEX)) ==
MP_OKAY && (mp_cmp(modulus, &modulusChk) == MP_EQ))
{
found = 1;
if (order) {
res = stm32_get_from_hexstr(curve->order, order, curve->size);
}
if (coefB) {
res = stm32_get_from_hexstr(curve->Bf, coefB, curve->size);
}
break;
}
}
mp_clear(&modulusChk);
if (!found && res == MP_OKAY) {
res = MP_RANGE;
}
return res;
}
#endif
int wc_ecc_mulmod_ex2(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
mp_int* modulus, mp_int* o, WC_RNG* rng, int map,
void* heap)
{
PKA_ECCMulInTypeDef pka_mul;
PKA_ECCMulOutTypeDef pka_mul_res;
int szModulus;
int status;
int res;
uint8_t Gxbin[STM32_MAX_ECC_SIZE];
uint8_t Gybin[STM32_MAX_ECC_SIZE];
uint8_t kbin[STM32_MAX_ECC_SIZE];
uint8_t PtXbin[STM32_MAX_ECC_SIZE];
uint8_t PtYbin[STM32_MAX_ECC_SIZE];
uint8_t prime[STM32_MAX_ECC_SIZE];
uint8_t coefA[STM32_MAX_ECC_SIZE];
#ifdef WOLFSSL_STM32_PKA_V2
uint8_t coefB[STM32_MAX_ECC_SIZE];
uint8_t order[STM32_MAX_ECC_SIZE];
#endif
uint32_t coefA_sign = 1;
(void)rng;
XMEMSET(&pka_mul, 0x00, sizeof(PKA_ECCMulInTypeDef));
XMEMSET(&pka_mul_res, 0x00, sizeof(PKA_ECCMulOutTypeDef));
pka_mul_res.ptX = PtXbin;
pka_mul_res.ptY = PtYbin;
if (k == NULL || G == NULL || R == NULL || modulus == NULL) {
return ECC_BAD_ARG_E;
}
szModulus = mp_unsigned_bin_size(modulus);
res = stm32_get_from_mp_int(kbin, k, szModulus);
if (res == MP_OKAY)
res = stm32_get_from_mp_int(Gxbin, G->x, szModulus);
if (res == MP_OKAY)
res = stm32_get_from_mp_int(Gybin, G->y, szModulus);
if (res == MP_OKAY)
res = stm32_get_from_mp_int(prime, modulus, szModulus);
if (res == MP_OKAY)
res = stm32_getabs_from_mp_int(coefA, a, szModulus, &coefA_sign);
#ifdef WOLFSSL_STM32_PKA_V2
XMEMSET(order, 0, sizeof(order));
XMEMSET(coefB, 0, sizeof(coefB));
if (res == MP_OKAY) {
if (o != NULL) {
res = stm32_get_from_mp_int(order, o, szModulus);
if (res == MP_OKAY) {
res = stm32_get_curve_params(modulus, NULL, coefB);
}
}
else {
res = stm32_get_curve_params(modulus, order, coefB);
}
}
#endif
if (res != MP_OKAY) {
ForceZero(kbin, sizeof(kbin));
return res;
}
pka_mul.modulusSize = szModulus;
pka_mul.coefSign = coefA_sign;
pka_mul.coefA = coefA;
pka_mul.modulus = prime;
pka_mul.pointX = Gxbin;
pka_mul.pointY = Gybin;
pka_mul.scalarMulSize = szModulus;
pka_mul.scalarMul = kbin;
#ifdef WOLFSSL_STM32_PKA_V2
pka_mul.coefB = coefB;
pka_mul.primeOrder = order;
#endif
status = HAL_PKA_ECCMul(&hpka, &pka_mul, HAL_MAX_DELAY);
if (status != HAL_OK) {
ForceZero(kbin, sizeof(kbin));
HAL_PKA_RAMReset(&hpka);
return WC_HW_E;
}
pka_mul_res.ptX = Gxbin;
pka_mul_res.ptY = Gybin;
HAL_PKA_ECCMul_GetResult(&hpka, &pka_mul_res);
ForceZero(kbin, sizeof(kbin));
res = mp_read_unsigned_bin(R->x, Gxbin, szModulus);
if (res == MP_OKAY) {
res = mp_read_unsigned_bin(R->y, Gybin, szModulus);
#if defined(USE_FAST_MATH) || defined(USE_INTEGER_HEAP_MATH) || \
((defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL)) && \
defined(WOLFSSL_SP_INT_NEGATIVE))
R->y->sign = k->sign;
#endif
}
if (res == MP_OKAY)
res = mp_set(R->z, 1);
HAL_PKA_RAMReset(&hpka);
(void)heap;
return res;
}
int wc_ecc_mulmod_ex(const mp_int *k, ecc_point *G, ecc_point *R, mp_int* a,
mp_int *modulus, int map, void* heap)
{
return wc_ecc_mulmod_ex2(k, G, R, a, modulus, NULL, NULL, map, heap);
}
int ecc_map_ex(ecc_point* P, mp_int* modulus, mp_digit mp, int ct)
{
(void)P;
(void)modulus;
(void)mp;
(void)ct;
return MP_OKAY;
}
int stm32_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash,
word32 hashlen, int* res, ecc_key* key)
{
PKA_ECDSAVerifInTypeDef pka_ecc;
int size;
int status;
uint8_t Rbin[STM32_MAX_ECC_SIZE];
uint8_t Sbin[STM32_MAX_ECC_SIZE];
uint8_t Qxbin[STM32_MAX_ECC_SIZE];
uint8_t Qybin[STM32_MAX_ECC_SIZE];
uint8_t Hashbin[STM32_MAX_ECC_SIZE];
uint8_t prime[STM32_MAX_ECC_SIZE];
uint8_t coefA[STM32_MAX_ECC_SIZE];
uint8_t gen_x[STM32_MAX_ECC_SIZE];
uint8_t gen_y[STM32_MAX_ECC_SIZE];
uint8_t order[STM32_MAX_ECC_SIZE];
uint32_t coefA_sign = 1;
XMEMSET(&pka_ecc, 0x00, sizeof(PKA_ECDSAVerifInTypeDef));
if (r == NULL || s == NULL || hash == NULL || res == NULL || key == NULL ||
key->dp == NULL) {
return ECC_BAD_ARG_E;
}
*res = 0;
size = wc_ecc_size(key);
status = stm32_get_from_mp_int(Rbin, r, size);
if (status == MP_OKAY)
status = stm32_get_from_mp_int(Sbin, s, size);
if (status == MP_OKAY)
status = stm32_get_from_mp_int(Qxbin, key->pubkey.x, size);
if (status == MP_OKAY)
status = stm32_get_from_mp_int(Qybin, key->pubkey.y, size);
if (status != MP_OKAY)
return status;
status = stm32_get_from_hexstr(key->dp->prime, prime, size);
if (status == MP_OKAY)
status = stm32_get_from_hexstr(key->dp->order, order, size);
if (status == MP_OKAY)
status = stm32_get_from_hexstr(key->dp->Gx, gen_x, size);
if (status == MP_OKAY)
status = stm32_get_from_hexstr(key->dp->Gy, gen_y, size);
if (status == MP_OKAY)
status = stm32_getabs_from_hexstr(key->dp->Af, coefA, size, &coefA_sign);
if (status != MP_OKAY)
return status;
pka_ecc.primeOrderSize = size;
pka_ecc.modulusSize = size;
pka_ecc.coefSign = coefA_sign;
pka_ecc.coef = coefA;
pka_ecc.modulus = prime;
pka_ecc.basePointX = gen_x;
pka_ecc.basePointY = gen_y;
pka_ecc.primeOrder = order;
pka_ecc.pPubKeyCurvePtX = Qxbin;
pka_ecc.pPubKeyCurvePtY = Qybin;
pka_ecc.RSign = Rbin;
pka_ecc.SSign = Sbin;
XMEMSET(Hashbin, 0, STM32_MAX_ECC_SIZE);
if (hashlen > STM32_MAX_ECC_SIZE) {
return ECC_BAD_ARG_E;
}
else if ((int)hashlen > size) {
XMEMCPY(Hashbin, hash, size);
}
else {
XMEMCPY(Hashbin + (size - hashlen), hash, hashlen);
}
pka_ecc.hash = Hashbin;
status = HAL_PKA_ECDSAVerif(&hpka, &pka_ecc, HAL_MAX_DELAY);
if (status != HAL_OK) {
HAL_PKA_RAMReset(&hpka);
return WC_HW_E;
}
*res = HAL_PKA_ECDSAVerif_IsValidSignature(&hpka);
HAL_PKA_RAMReset(&hpka);
return status;
}
int stm32_ecc_sign_hash_ex(const byte* hash, word32 hashlen, WC_RNG* rng,
ecc_key* key, mp_int *r, mp_int *s)
{
PKA_ECDSASignInTypeDef pka_ecc;
PKA_ECDSASignOutTypeDef pka_ecc_out;
int size;
int status;
mp_int gen_k;
mp_int order_mp;
uint8_t Keybin[STM32_MAX_ECC_SIZE];
uint8_t Intbin[STM32_MAX_ECC_SIZE];
uint8_t Rbin[STM32_MAX_ECC_SIZE];
uint8_t Sbin[STM32_MAX_ECC_SIZE];
uint8_t Hashbin[STM32_MAX_ECC_SIZE];
uint8_t prime[STM32_MAX_ECC_SIZE];
uint8_t coefA[STM32_MAX_ECC_SIZE];
#ifdef WOLFSSL_STM32_PKA_V2
uint8_t coefB[STM32_MAX_ECC_SIZE];
#endif
uint8_t gen_x[STM32_MAX_ECC_SIZE];
uint8_t gen_y[STM32_MAX_ECC_SIZE];
uint8_t order[STM32_MAX_ECC_SIZE];
uint32_t coefA_sign = 1;
XMEMSET(&pka_ecc, 0x00, sizeof(PKA_ECDSASignInTypeDef));
XMEMSET(&pka_ecc_out, 0x00, sizeof(PKA_ECDSASignOutTypeDef));
if (r == NULL || s == NULL || hash == NULL || key == NULL ||
key->dp == NULL) {
return ECC_BAD_ARG_E;
}
size = wc_ecc_size(key);
status = stm32_get_from_hexstr(key->dp->prime, prime, size);
if (status == MP_OKAY)
status = stm32_get_from_hexstr(key->dp->order, order, size);
if (status == MP_OKAY)
status = stm32_get_from_hexstr(key->dp->Gx, gen_x, size);
if (status == MP_OKAY)
status = stm32_get_from_hexstr(key->dp->Gy, gen_y, size);
if (status == MP_OKAY)
status = stm32_getabs_from_hexstr(key->dp->Af, coefA, size, &coefA_sign);
#ifdef WOLFSSL_STM32_PKA_V2
if (status == MP_OKAY)
status = stm32_get_from_hexstr(key->dp->Bf, coefB, size);
#endif
if (status != MP_OKAY)
return status;
mp_init(&gen_k);
mp_init(&order_mp);
status = mp_read_unsigned_bin(&order_mp, order, size);
if (status == MP_OKAY)
status = wc_ecc_gen_k(rng, size, &gen_k, &order_mp);
if (status == MP_OKAY)
status = stm32_get_from_mp_int(Intbin, &gen_k, size);
mp_clear(&gen_k);
mp_clear(&order_mp);
if (status != MP_OKAY) {
ForceZero(Intbin, sizeof(Intbin));
return status;
}
status = stm32_get_from_mp_int(Keybin, wc_ecc_key_get_priv(key), size);
if (status != MP_OKAY) {
ForceZero(Keybin, sizeof(Keybin));
ForceZero(Intbin, sizeof(Intbin));
return status;
}
pka_ecc.primeOrderSize = size;
pka_ecc.modulusSize = size;
pka_ecc.coefSign = coefA_sign;
pka_ecc.coef = coefA;
#ifdef WOLFSSL_STM32_PKA_V2
pka_ecc.coefB = coefB;
#endif
pka_ecc.modulus = prime;
pka_ecc.basePointX = gen_x;
pka_ecc.basePointY = gen_y;
pka_ecc.primeOrder = order;
XMEMSET(Hashbin, 0, STM32_MAX_ECC_SIZE);
if (hashlen > STM32_MAX_ECC_SIZE) {
ForceZero(Keybin, sizeof(Keybin));
ForceZero(Intbin, sizeof(Intbin));
return ECC_BAD_ARG_E;
}
else if ((int)hashlen > size) {
XMEMCPY(Hashbin, hash, size);
}
else {
XMEMCPY(Hashbin + (size - hashlen), hash, hashlen);
}
pka_ecc.hash = Hashbin;
pka_ecc.integer = Intbin;
pka_ecc.privateKey = Keybin;
pka_ecc_out.RSign = Rbin;
pka_ecc_out.SSign = Sbin;
status = HAL_PKA_ECDSASign(&hpka, &pka_ecc, HAL_MAX_DELAY);
if (status != HAL_OK) {
ForceZero(Keybin, sizeof(Keybin));
ForceZero(Intbin, sizeof(Intbin));
HAL_PKA_RAMReset(&hpka);
return WC_HW_E;
}
HAL_PKA_ECDSASign_GetResult(&hpka, &pka_ecc_out, NULL);
ForceZero(Keybin, sizeof(Keybin));
ForceZero(Intbin, sizeof(Intbin));
status = mp_read_unsigned_bin(r, pka_ecc_out.RSign, size);
if (status == MP_OKAY)
status = mp_read_unsigned_bin(s, pka_ecc_out.SSign, size);
HAL_PKA_RAMReset(&hpka);
return status;
}
#endif
#endif