CARPLAY版本整理

This commit is contained in:
2025-01-21 16:49:37 +08:00
commit f0fb64e4e6
26542 changed files with 13719676 additions and 0 deletions

View File

@ -0,0 +1 @@
See caam_doc.pdf for documentation about building and using.

View File

@ -0,0 +1,665 @@
/* caam_aes.c
*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_AES) && \
!defined(NO_IMX6_CAAM_AES)
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/aes.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
#include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
#include <stdio.h>
#endif
int wc_AesSetKey(Aes* aes, const byte* key, word32 len,
const byte* iv, int dir)
{
int ret;
if (aes == NULL || key == NULL) {
return BAD_FUNC_ARG;
}
if (len > 32) {
byte out[32]; /* max AES key size */
word32 outSz;
if (len != 64 && len != 72 && len != 80) {
return BAD_FUNC_ARG;
}
outSz = sizeof(out);
/* if length greater then 32 then try to unencapsulate */
if ((ret = wc_caamOpenBlob((byte*)key, len, out, &outSz)) != 0) {
return ret;
}
XMEMCPY((byte*)aes->key, out, outSz);
aes->keylen = outSz;
}
else {
if (len != 16 && len != 24 && len != 32) {
return BAD_FUNC_ARG;
}
XMEMCPY((byte*)aes->key, key, len);
aes->keylen = len;
}
switch (aes->keylen) {
case 16: aes->rounds = 10; break;
case 24: aes->rounds = 12; break;
case 32: aes->rounds = 14; break;
default:
return BAD_FUNC_ARG;
}
if ((ret = wc_AesSetIV(aes, iv)) != 0) {
return ret;
}
#ifdef WOLFSSL_AES_COUNTER
aes->left = 0;
#endif
return 0;
}
int wc_AesCbcEncrypt(Aes* aes, byte* out,
const byte* in, word32 sz)
{
word32 blocks;
WOLFSSL_ENTER("wc_AesCbcEncrypt");
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
blocks = sz / AES_BLOCK_SIZE;
if (blocks > 0) {
Buffer buf[4];
word32 arg[4];
word32 keySz;
int ret;
if ((ret = wc_AesGetKeySize(aes, &keySz)) != 0) {
return ret;
}
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)aes->key;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (Address)aes->reg;
buf[1].Length = AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer;
buf[2].TheAddress = (Address)in;
buf[2].Length = blocks * AES_BLOCK_SIZE;
buf[3].BufferType = DataBuffer | LastBuffer;
buf[3].TheAddress = (Address)out;
buf[3].Length = blocks * AES_BLOCK_SIZE;
arg[0] = CAAM_ENC;
arg[1] = keySz;
arg[2] = blocks * AES_BLOCK_SIZE;
if ((ret = wc_caamAddAndWait(buf, 4, arg, CAAM_AESCBC)) != 0) {
WOLFSSL_MSG("Error with CAAM AES CBC encrypt");
return ret;
}
}
return 0;
}
int wc_AesCbcDecrypt(Aes* aes, byte* out,
const byte* in, word32 sz)
{
word32 blocks;
WOLFSSL_ENTER("wc_AesCbcDecrypt");
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
blocks = sz / AES_BLOCK_SIZE;
if (blocks > 0) {
Buffer buf[4];
word32 arg[4];
word32 keySz;
int ret;
if ((ret = wc_AesGetKeySize(aes, &keySz)) != 0) {
return ret;
}
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)aes->key;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (Address)aes->reg;
buf[1].Length = AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer;
buf[2].TheAddress = (Address)in;
buf[2].Length = blocks * AES_BLOCK_SIZE;
buf[3].BufferType = DataBuffer | LastBuffer;
buf[3].TheAddress = (Address)out;
buf[3].Length = blocks * AES_BLOCK_SIZE;
arg[0] = CAAM_DEC;
arg[1] = keySz;
arg[2] = blocks * AES_BLOCK_SIZE;
if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCBC)) != 0) {
WOLFSSL_MSG("Error with CAAM AES CBC decrypt");
return ret;
}
}
return 0;
}
#if defined(HAVE_AES_ECB)
/* is assumed that input size is a multiple of AES_BLOCK_SIZE */
int wc_AesEcbEncrypt(Aes* aes, byte* out,
const byte* in, word32 sz)
{
word32 blocks;
Buffer buf[3];
word32 arg[4];
word32 keySz;
int ret;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
blocks = sz / AES_BLOCK_SIZE;
if ((ret = wc_AesGetKeySize(aes, &keySz)) != 0) {
return ret;
}
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)aes->key;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (Address)in;
buf[1].Length = blocks * AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer | LastBuffer;
buf[2].TheAddress = (Address)out;
buf[2].Length = blocks * AES_BLOCK_SIZE;
arg[0] = CAAM_ENC;
arg[1] = keySz;
arg[2] = blocks * AES_BLOCK_SIZE;
if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESECB)) != 0) {
WOLFSSL_MSG("Error with CAAM AES ECB encrypt");
return ret;
}
return 0;
}
int wc_AesEcbDecrypt(Aes* aes, byte* out,
const byte* in, word32 sz)
{
word32 blocks;
Buffer buf[3];
word32 arg[4];
word32 keySz;
int ret;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
blocks = sz / AES_BLOCK_SIZE;
if ((ret = wc_AesGetKeySize(aes, &keySz)) != 0) {
return ret;
}
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)aes->key;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (Address)in;
buf[1].Length = blocks * AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer | LastBuffer;
buf[2].TheAddress = (Address)out;
buf[2].Length = blocks * AES_BLOCK_SIZE;
arg[0] = CAAM_DEC;
arg[1] = keySz;
arg[2] = blocks * AES_BLOCK_SIZE;
if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESECB)) != 0) {
WOLFSSL_MSG("Error with CAAM AES ECB decrypt");
return ret;
}
return 0;
}
#endif
/* AES-CTR */
#ifdef WOLFSSL_AES_COUNTER
/* Increment AES counter (from wolfcrypt/src/aes.c) */
static WC_INLINE void IncrementAesCounter(byte* inOutCtr)
{
/* in network byte order so start at end and work back */
int i;
for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) {
if (++inOutCtr[i]) /* we're done unless we overflow */
return;
}
}
int wc_AesCtrEncrypt(Aes* aes, byte* out,
const byte* in, word32 sz)
{
byte* tmp;
Buffer buf[4];
word32 arg[4];
word32 keySz;
int ret, blocks;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
if ((ret = wc_AesGetKeySize(aes, &keySz)) != 0) {
return ret;
}
/* consume any unused bytes left in aes->tmp */
tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left;
while (aes->left && sz) {
*(out++) = *(in++) ^ *(tmp++);
aes->left--;
sz--;
}
/* do full blocks to then get potential left over amount */
blocks = sz / AES_BLOCK_SIZE;
if (blocks > 0) {
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)aes->key;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (Address)aes->reg;
buf[1].Length = AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer;
buf[2].TheAddress = (Address)in;
buf[2].Length = blocks * AES_BLOCK_SIZE;
buf[3].BufferType = DataBuffer | LastBuffer;
buf[3].TheAddress = (Address)out;
buf[3].Length = blocks * AES_BLOCK_SIZE;
arg[0] = CAAM_ENC;
arg[1] = keySz;
arg[2] = blocks * AES_BLOCK_SIZE;
if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCTR)) != 0) {
WOLFSSL_MSG("Error with CAAM AES CTR encrypt");
return ret;
}
out += blocks * AES_BLOCK_SIZE;
in += blocks * AES_BLOCK_SIZE;
sz -= blocks * AES_BLOCK_SIZE;
}
if (sz) {
if ((ret = wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg)) != 0)
return ret;
IncrementAesCounter((byte*)aes->reg);
aes->left = AES_BLOCK_SIZE;
tmp = (byte*)aes->tmp;
while (sz--) {
*(out++) = *(in++) ^ *(tmp++);
aes->left--;
}
}
return 0;
}
#endif
/* AES-DIRECT */
#if defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER)
int wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
{
Buffer buf[3];
word32 arg[4];
word32 keySz;
int ret;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
if ((ret = wc_AesGetKeySize(aes, &keySz)) != 0) {
return ret;
}
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)aes->key;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (Address)in;
buf[1].Length = AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer | LastBuffer;
buf[2].TheAddress = (Address)out;
buf[2].Length = AES_BLOCK_SIZE;
arg[0] = CAAM_ENC;
arg[1] = keySz;
arg[2] = AES_BLOCK_SIZE;
if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESECB)) != 0) {
WOLFSSL_MSG("Error with CAAM AES direct encrypt");
return ret;
}
return ret;
}
int wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
{
Buffer buf[3];
word32 arg[4];
word32 keySz;
int ret;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
if ((ret = wc_AesGetKeySize(aes, &keySz)) != 0) {
return ret;
}
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)aes->key;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (Address)in;
buf[1].Length = AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer | LastBuffer;
buf[2].TheAddress = (Address)out;
buf[2].Length = AES_BLOCK_SIZE;
arg[0] = CAAM_DEC;
arg[1] = keySz;
arg[2] = AES_BLOCK_SIZE;
if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESECB)) != 0) {
WOLFSSL_MSG("Error with CAAM AES direct decrypt");
return ret;
}
return 0;
}
int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len,
const byte* iv, int dir)
{
return wc_AesSetKey(aes, key, len, iv, dir);
}
#endif
#ifdef HAVE_AESCCM
int wc_AesCcmEncrypt(Aes* aes, byte* out,
const byte* in, word32 inSz,
const byte* nonce, word32 nonceSz,
byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz)
{
Buffer buf[5];
word32 arg[4];
word32 keySz;
word32 i;
byte B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE];
int lenSz;
byte mask = 0xFF;
const word32 wordSz = (word32)sizeof(word32);
int ret;
/* sanity check on arguments */
if (aes == NULL || out == NULL || in == NULL || nonce == NULL
|| authTag == NULL || nonceSz < 7 || nonceSz > 13 ||
authTagSz > AES_BLOCK_SIZE)
return BAD_FUNC_ARG;
if ((ret = wc_AesCcmCheckTagSize(authTagSz)) != 0) {
return ret;
}
if ((ret = wc_AesGetKeySize(aes, &keySz)) != 0) {
return ret;
}
/* set up B0 and CTR0 similar to how wolfcrypt/src/aes.c does */
XMEMCPY(B0Ctr0+1, nonce, nonceSz);
XMEMCPY(B0Ctr0+AES_BLOCK_SIZE+1, nonce, nonceSz);
lenSz = AES_BLOCK_SIZE - 1 - (byte)nonceSz;
B0Ctr0[0] = (authInSz > 0 ? 64 : 0)
+ (8 * (((byte)authTagSz - 2) / 2))
+ (lenSz - 1);
for (i = 0; i < lenSz; i++) {
if (mask && i >= wordSz)
mask = 0x00;
B0Ctr0[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask;
B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE - 1 - i] = 0;
}
B0Ctr0[AES_BLOCK_SIZE] = lenSz - 1;
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)aes->key;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (Address)B0Ctr0;
buf[1].Length = AES_BLOCK_SIZE + AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer;
buf[2].TheAddress = (Address)authIn;
buf[2].Length = authInSz;
buf[3].BufferType = DataBuffer;
buf[3].TheAddress = (Address)in;
buf[3].Length = inSz;
buf[4].BufferType = DataBuffer | LastBuffer;
buf[4].TheAddress = (Address)out;
buf[4].Length = inSz;
arg[0] = CAAM_ENC;
arg[1] = keySz;
arg[2] = inSz;
arg[3] = authInSz;
if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCCM)) != 0) {
WOLFSSL_MSG("Error with CAAM AES-CCM encrypt");
return ret;
}
XMEMCPY(authTag, B0Ctr0, authTagSz);
return 0;
}
#ifdef HAVE_AES_DECRYPT
int wc_AesCcmDecrypt(Aes* aes, byte* out,
const byte* in, word32 inSz,
const byte* nonce, word32 nonceSz,
const byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz)
{
Buffer buf[5];
word32 arg[4];
word32 keySz;
word32 i;
byte B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE];
byte tag[AES_BLOCK_SIZE];
int lenSz;
byte mask = 0xFF;
const word32 wordSz = (word32)sizeof(word32);
int ret;
/* sanity check on arguments */
if (aes == NULL || out == NULL || in == NULL || nonce == NULL
|| authTag == NULL || nonceSz < 7 || nonceSz > 13 ||
authTagSz > AES_BLOCK_SIZE)
return BAD_FUNC_ARG;
if ((ret = wc_AesCcmCheckTagSize(authTagSz)) != 0) {
return ret;
}
if ((ret = wc_AesGetKeySize(aes, &keySz)) != 0) {
return ret;
}
/* set up B0 and CTR0 similar to how wolfcrypt/src/aes.c does */
XMEMCPY(B0Ctr0+1, nonce, nonceSz);
XMEMCPY(B0Ctr0+AES_BLOCK_SIZE+1, nonce, nonceSz);
lenSz = AES_BLOCK_SIZE - 1 - (byte)nonceSz;
B0Ctr0[0] = (authInSz > 0 ? 64 : 0)
+ (8 * (((byte)authTagSz - 2) / 2))
+ (lenSz - 1);
for (i = 0; i < lenSz; i++) {
if (mask && i >= wordSz)
mask = 0x00;
B0Ctr0[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask;
B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE - 1 - i] = 0;
}
B0Ctr0[AES_BLOCK_SIZE] = lenSz - 1;
if ((ret = wc_AesEncryptDirect(aes, tag, B0Ctr0 + AES_BLOCK_SIZE)) != 0)
return ret;
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)aes->key;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (Address)B0Ctr0;
buf[1].Length = AES_BLOCK_SIZE + AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer;
buf[2].TheAddress = (Address)authIn;
buf[2].Length = authInSz;
buf[3].BufferType = DataBuffer;
buf[3].TheAddress = (Address)in;
buf[3].Length = inSz;
buf[4].BufferType = DataBuffer | LastBuffer;
buf[4].TheAddress = (Address)out;
buf[4].Length = inSz;
arg[0] = CAAM_DEC;
arg[1] = keySz;
arg[2] = inSz;
arg[3] = authInSz;
if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCCM)) != 0) {
WOLFSSL_MSG("Error with CAAM AES-CCM derypt");
return ret;
}
xorbuf(tag, B0Ctr0, authTagSz);
if (ConstantCompare(tag, authTag, authTagSz) != 0) {
/* If the authTag check fails, don't keep the decrypted data.
* Unfortunately, you need the decrypted data to calculate the
* check value. */
XMEMSET(out, 0, inSz);
ret = AES_CCM_AUTH_E;
}
ForceZero(tag, AES_BLOCK_SIZE);
ForceZero(B0Ctr0, AES_BLOCK_SIZE * 2);
return ret;
}
#endif /* HAVE_AES_DECRYPT */
#endif /* HAVE_AESCCM */
#endif /* WOLFSSL_IMX6_CAAM && !NO_AES */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,228 @@
/* caam_error.c
*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#if (defined(__INTEGRITY) || defined(INTEGRITY)) || \
(defined(__QNX__) || defined(__QNXNTO__))
#include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
#include <wolfssl/wolfcrypt/port/caam/caam_error.h>
/* return a negative value if CAAM reset needed */
int caamParseCCBError(unsigned int error)
{
int ret = 0;
switch((error >> 4) & 0xF) {
case 0:
WOLFSSL_MSG("\tCHAID: CCB");
break;
case 1:
WOLFSSL_MSG("\tCHAID: AESA");
switch (error & 0xF) {
case 0xC:
WOLFSSL_MSG("\tAAD size error");
}
break;
case 2:
WOLFSSL_MSG("\tCHAID: DESA");
break;
case 3:
WOLFSSL_MSG("\tCHAID: AFHA (ARC4)");
break;
case 4:
WOLFSSL_MSG("\tCHAID: MDHA hash");
break;
case 5:
WOLFSSL_MSG("\tCHAID: RNG - ERRID:");
ret = -1; /* treat RNG errors as fatal */
switch(error & 0xF) {
case 3:
WOLFSSL_MSG("\tRNG instantiate error");
break;
case 4:
WOLFSSL_MSG("\tRNG not instantiated error");
break;
case 5:
WOLFSSL_MSG("\tRNG test instantiate error");
break;
case 6:
WOLFSSL_MSG("\tRNG prediction resistance error");
break;
default:
WOLFSSL_MSG("\tUnknown");
}
break;
case 8:
WOLFSSL_MSG("\tCHAID: PKHA");
break;
default:
WOLFSSL_MSG("\tCHAID: Unknown CCB error");
}
return ret;
}
/* return a negative value for an error that requires CAAM reset */
int caamParseDECOError(unsigned int error)
{
int ret = 0;
switch (error & 0xFF) {
case 0x04:
WOLFSSL_MSG("\tInvalid Descriptor Command");
break;
case 0x06:
WOLFSSL_MSG("\tInvalid KEY Command");
break;
case 0x07:
WOLFSSL_MSG("\tInvalid Load Command");
break;
case 0x08:
WOLFSSL_MSG("\tInvalid Store Command");
break;
case 0x09:
WOLFSSL_MSG("\tInvalid Operation Command");
break;
case 0x82:
WOLFSSL_MSG("\tInvalid PRB setting");
break;
case 0x86:
WOLFSSL_MSG("\tVerify ECC/RSA signature fail");
break;
default:
WOLFSSL_MSG("\tUnknown error");
}
return ret;
}
/* return a negative value if CAAM should be reset after error */
int caamParseError(unsigned int error)
{
int ret = 0;
/* print out of index of error
unsigned int idx;
idx = (error >> 8) & 0xFF;
printf("idx of error = %d\n", idx);
*/
if ((error & 0x40000000) > 0) {
WOLFSSL_MSG("[DECO Error]");
ret = caamParseDECOError(error);
}
if ((error & 0x20000000) > 0) {
WOLFSSL_MSG("[CCB Error]");
ret = caamParseCCBError(error);
}
return ret;
}
/* parses a Job Ring Interrupt Status report
* returns 0 if there is no error */
unsigned int caamParseJRError(unsigned int error)
{
unsigned int err = (error >> 8) & 0x1F;
if (error & 0x10) {
WOLFSSL_MSG("Job Ring Interrupt ENTER_FAIL");
}
if (error & 0x20) {
WOLFSSL_MSG("Job Ring Interrupt EXIT_FAIL");
}
switch (err) {
case 0x00:
/* no error */
break;
case 0x01:
WOLFSSL_MSG("Error writing status to output ring");
break;
case 0x03:
WOLFSSL_MSG("Bad input ring address");
break;
case 0x04:
WOLFSSL_MSG("Bad output ring address");
break;
case 0x05:
WOLFSSL_MSG("Fatal, invalid write to input ring");
break;
case 0x06:
WOLFSSL_MSG("Invalid write to output ring");
break;
case 0x07:
WOLFSSL_MSG("Job ring released before halted");
break;
case 0x08:
WOLFSSL_MSG("Removed too many jobs");
break;
case 0x09:
WOLFSSL_MSG("Added too many jobs");
break;
default:
WOLFSSL_MSG("Unknown error");
break;
}
return err;
}
#ifdef WOLFSSL_CAAM_PRINT
void DEBUG_PRINT_ARRAY(void* a, int aSz, char* str)
{
int i;
unsigned char* pt = (unsigned char*)a;
printf("%s [%d] : ", str, aSz);
for (i = 0; i < aSz; i++)
printf("%02X", pt[i]);
printf("\n");
}
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,401 @@
/* caam_sha.c
*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
#include <wolfssl/wolfcrypt/logging.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
#if defined(__INTEGRITY) || defined(INTEGRITY)
#include <INTEGRITY.h>
#endif
#include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
#include <stdio.h>
#endif
#ifndef NO_SHA
#include <wolfssl/wolfcrypt/sha.h>
#endif
#if !defined(NO_SHA256) || defined(WOLFSSL_SHA224)
#include <wolfssl/wolfcrypt/sha256.h>
#endif
#if defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)
#include <wolfssl/wolfcrypt/sha512.h>
#endif
#ifndef NO_MD5
#include <wolfssl/wolfcrypt/md5.h>
#endif
/******************************************************************************
Common Code Between SHA Functions
****************************************************************************/
static int _InitSha(wc_Sha* sha, void* heap, int devId, word32 digestSz,
word32 type)
{
Buffer buf[1];
word32 arg[4];
int ret;
(void)heap;
(void)devId;
if (sha == NULL) {
return BAD_FUNC_ARG;
}
XMEMSET(sha, 0, sizeof(Sha));
/* Set buffer for context */
buf[0].BufferType = DataBuffer | LastBuffer;
buf[0].TheAddress = (Address)sha->ctx;
buf[0].Length = digestSz + WC_CAAM_CTXLEN;
buf[0].Transferred = 0;
arg[0] = CAAM_ALG_INIT;
arg[1] = digestSz + WC_CAAM_CTXLEN;
if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) {
WOLFSSL_MSG("Error with CAAM SHA init");
return ret;
}
return 0;
}
static int _ShaUpdate(wc_Sha* sha, const byte* data, word32 len, word32 digestSz,
word32 type)
{
Buffer buf[2];
word32 arg[4];
int ret;
byte* local;
if (sha == NULL ||(data == NULL && len > 0)) {
return BAD_FUNC_ARG;
}
if (len == 0) return 0; /* nothing to do */
local = (byte*)sha->buffer;
/* check for filling out existing buffer */
if (sha->buffLen > 0) {
word32 add = min(len, WC_CAAM_HASH_BLOCK - sha->buffLen);
XMEMCPY(&local[sha->buffLen], data, add);
sha->buffLen += add;
data += add;
len -= add;
if (sha->buffLen == WC_CAAM_HASH_BLOCK) {
/* Set buffer for context */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)sha->ctx;
buf[0].Length = digestSz + WC_CAAM_CTXLEN;
buf[0].Transferred = 0;
/* data to update with */
buf[1].BufferType = DataBuffer | LastBuffer;
buf[1].TheAddress = (Address)sha->buffer;
buf[1].Length = sha->buffLen;
buf[1].Transferred = 0;
arg[0] = CAAM_ALG_UPDATE;
arg[1] = digestSz + WC_CAAM_CTXLEN;
if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) {
WOLFSSL_MSG("Error with CAAM SHA update");
return ret;
}
sha->buffLen = 0; /* cleared out buffer */
}
}
/* check if multiple full blocks can be done */
if (len >= WC_CAAM_HASH_BLOCK) {
word32 sz = len / WC_CAAM_HASH_BLOCK;
sz = sz * WC_CAAM_HASH_BLOCK;
/* Set buffer for context */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)sha->ctx;
buf[0].Length = digestSz + WC_CAAM_CTXLEN;
buf[0].Transferred = 0;
/* data to update with */
buf[1].BufferType = DataBuffer | LastBuffer;
buf[1].TheAddress = (Address)data;
buf[1].Length = sz;
buf[1].Transferred = 0;
arg[0] = CAAM_ALG_UPDATE;
arg[1] = digestSz + WC_CAAM_CTXLEN;
if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) {
WOLFSSL_MSG("Error with CAAM SHA update");
return ret;
}
len -= sz;
data += sz;
}
/* check for left overs */
if (len > 0) {
word32 add = min(len, WC_CAAM_HASH_BLOCK - sha->buffLen);
XMEMCPY(&local[sha->buffLen], data, add);
sha->buffLen += add;
}
return 0;
}
static int _ShaFinal(wc_Sha* sha, byte* out, word32 digestSz,
word32 type)
{
Buffer buf[2];
word32 arg[4];
int ret;
if (sha == NULL || out == NULL) {
return BAD_FUNC_ARG;
}
/* Set buffer for context */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)sha->ctx;
buf[0].Length = digestSz + WC_CAAM_CTXLEN;
buf[0].Transferred = 0;
/* add any potential left overs */
buf[1].BufferType = DataBuffer | LastBuffer;
buf[1].TheAddress = (Address)sha->buffer;
buf[1].Length = sha->buffLen;
buf[1].Transferred = 0;
arg[0] = CAAM_ALG_FINAL;
arg[1] = digestSz + WC_CAAM_CTXLEN;
if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) {
WOLFSSL_MSG("Error with CAAM SHA init");
return ret;
}
return 0;
}
/******************************************************************************
MD5
****************************************************************************/
#if !defined(NO_MD5)
int wc_InitMd5_ex(wc_Md5* sha, void* heap, int devId)
{
return _InitSha(sha, heap, devId, MD5_DIGEST_SIZE, CAAM_MD5);
}
int wc_Md5Update(wc_Md5* sha, const byte* data, word32 len)
{
return _ShaUpdate(sha, data, len, MD5_DIGEST_SIZE, CAAM_MD5);
}
int wc_Md5Final(wc_Md5* sha, byte* hash)
{
int ret;
if ((ret = _ShaFinal(sha, hash, MD5_DIGEST_SIZE, CAAM_MD5)) != 0) {
return ret;
}
XMEMCPY(hash, (byte*)sha->ctx, MD5_DIGEST_SIZE);
return _InitSha(sha, NULL, 0, MD5_DIGEST_SIZE, CAAM_MD5);
}
#endif /* !NO_MD5 */
/******************************************************************************
SHA 1
****************************************************************************/
#if !defined(NO_SHA)
int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
{
return _InitSha(sha, heap, devId, SHA_DIGEST_SIZE, CAAM_SHA);
}
int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
{
return _ShaUpdate(sha, data, len, SHA_DIGEST_SIZE, CAAM_SHA);
}
int wc_ShaFinal(wc_Sha* sha, byte* out)
{
int ret;
if ((ret = _ShaFinal(sha, out, SHA_DIGEST_SIZE, CAAM_SHA)) != 0) {
return ret;
}
XMEMCPY(out, (byte*)sha->ctx, SHA_DIGEST_SIZE);
return _InitSha(sha, NULL, 0, SHA_DIGEST_SIZE, CAAM_SHA);
}
#endif /* !NO_SHA */
/******************************************************************************
SHA 224
****************************************************************************/
#ifdef WOLFSSL_SHA224
int wc_InitSha224_ex(wc_Sha224* sha, void* heap, int devId)
{
return _InitSha(sha, heap, devId, SHA256_DIGEST_SIZE, CAAM_SHA224);
}
int wc_Sha224Update(wc_Sha224* sha, const byte* data, word32 len)
{
return _ShaUpdate(sha, data, len, SHA256_DIGEST_SIZE, CAAM_SHA224);
}
int wc_Sha224Final(wc_Sha224* sha, byte* out)
{
int ret;
if ((ret = _ShaFinal(sha, out, SHA256_DIGEST_SIZE, CAAM_SHA224)) != 0) {
return ret;
}
XMEMCPY(out, (byte*)sha->ctx, SHA224_DIGEST_SIZE);
return _InitSha(sha, NULL, 0, SHA256_DIGEST_SIZE, CAAM_SHA224);
}
#endif /* WOLFSSL_SHA224 */
/******************************************************************************
SHA 256
****************************************************************************/
#if !defined(NO_SHA256)
int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devId)
{
return _InitSha(sha, heap, devId, SHA256_DIGEST_SIZE, CAAM_SHA256);
}
int wc_Sha256Update(wc_Sha256* sha, const byte* data, word32 len)
{
return _ShaUpdate(sha, data, len, SHA256_DIGEST_SIZE, CAAM_SHA256);
}
int wc_Sha256Final(wc_Sha256* sha, byte* out)
{
int ret;
if ((ret = _ShaFinal(sha, out, SHA256_DIGEST_SIZE, CAAM_SHA256)) != 0) {
return ret;
}
XMEMCPY(out, (byte*)sha->ctx, SHA256_DIGEST_SIZE);
return _InitSha(sha, NULL, 0, SHA256_DIGEST_SIZE, CAAM_SHA256);
}
#endif /* !NO_SHA256 */
/******************************************************************************
SHA 384
****************************************************************************/
#ifdef WOLFSSL_SHA384
int wc_InitSha384_ex(wc_Sha384* sha, void* heap, int devId)
{
return _InitSha(sha, heap, devId, SHA512_DIGEST_SIZE, CAAM_SHA384);
}
int wc_Sha384Update(wc_Sha384* sha, const byte* data, word32 len)
{
return _ShaUpdate(sha, data, len, SHA512_DIGEST_SIZE, CAAM_SHA384);
}
int wc_Sha384Final(wc_Sha384* sha, byte* out)
{
int ret;
if ((ret = _ShaFinal(sha, out, SHA512_DIGEST_SIZE, CAAM_SHA384)) != 0) {
return ret;
}
XMEMCPY(out, (byte*)sha->ctx, SHA384_DIGEST_SIZE);
return _InitSha(sha, NULL, 0, SHA512_DIGEST_SIZE, CAAM_SHA384);
}
#endif /* WOLFSSL_SHA384 */
/******************************************************************************
SHA 512
****************************************************************************/
#ifdef WOLFSSL_SHA512
int wc_InitSha512_ex(wc_Sha512* sha, void* heap, int devId)
{
return _InitSha(sha, heap, devId, SHA512_DIGEST_SIZE, CAAM_SHA512);
}
int wc_Sha512Update(wc_Sha512* sha, const byte* data, word32 len)
{
return _ShaUpdate(sha, data, len, SHA512_DIGEST_SIZE, CAAM_SHA512);
}
int wc_Sha512Final(wc_Sha512* sha, byte* out)
{
int ret;
if ((ret = _ShaFinal(sha, out, SHA512_DIGEST_SIZE, CAAM_SHA512)) != 0) {
return ret;
}
XMEMCPY(out, (byte*)sha->ctx, SHA512_DIGEST_SIZE);
return _InitSha(sha, NULL, 0, SHA512_DIGEST_SIZE, CAAM_SHA512);
}
#endif /* WOLFSSL_SHA512 */
#endif /* WOLFSSL_IMX6_CAAM && !NO_IMX6_CAAM_HASH */

View File

@ -0,0 +1,450 @@
/* wolfcaam_aes.c
*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_CAAM) && !defined(NO_AES)
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
#include <wolfssl/wolfcrypt/port/caam/wolfcaam_aes.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#if (defined(HAVE_AESGCM) && defined(WOLFSSL_CAAM_AESGCM)) || \
defined(HAVE_AESCCM)
/* return 0 on success */
static int wc_CAAM_AesAeadCommon(Aes* aes, const byte* in, byte* out, word32 sz,
const byte* nonce, word32 nonceSz, byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz, int dir, int type)
{
CAAM_BUFFER buf[7];
int ret, idx = 0;
word32 arg[4];
word32 keySz;
if (aes == NULL) {
return BAD_FUNC_ARG;
}
if (wc_AesGetKeySize(aes, &keySz) != 0 && aes->blackKey == 0) {
return BAD_FUNC_ARG;
}
buf[idx].BufferType = DataBuffer;
buf[idx].TheAddress = (CAAM_ADDRESS)aes->devKey;
buf[idx].Length = keySz;
idx++;
buf[idx].BufferType = DataBuffer;
buf[idx].TheAddress = (CAAM_ADDRESS)nonce;
buf[idx].Length = nonceSz;
idx++;
buf[idx].BufferType = DataBuffer;
buf[idx].TheAddress = (CAAM_ADDRESS)in;
buf[idx].Length = sz;
idx++;
buf[idx].BufferType = DataBuffer;
buf[idx].TheAddress = (CAAM_ADDRESS)out;
buf[idx].Length = sz;
idx++;
buf[idx].BufferType = DataBuffer;
buf[idx].TheAddress = (CAAM_ADDRESS)authTag;
buf[idx].Length = authTagSz;
idx++;
buf[idx].BufferType = DataBuffer | LastBuffer;
buf[idx].TheAddress = (CAAM_ADDRESS)authIn;
buf[idx].Length = authInSz;
idx++;
/* authInSz must fit into a short (note that only 16 bits are ava in CAAM
* for AAD size anyway) */
arg[0] = ((authInSz & 0xFFFF) << 16) | (dir & 0xFFFF);
arg[1] = ((nonceSz & 0xFF) << 24) | ((authTagSz & 0xFF) << 16) |
(keySz & 0xFFFF);
arg[2] = sz;
arg[3] = aes->blackKey;
if ((ret = wc_caamAddAndWait(buf, idx, arg, type)) != 0) {
WOLFSSL_MSG("Error with CAAM AES AEAD operation");
return ret;
}
return 0;
}
#endif /* HAVE_AESGCM || HAVE_AESCCM */
#if defined(HAVE_AESCCM)
#ifndef WOLFSSL_SECO_CAAM
/* B0 is [ reserved | adata | M | L ] [ nonce ] [ l(m) ]
* Ctr is current counter
*/
static word32 CreateB0CTR(byte* B0Ctr0, const byte* nonce, word32 nonceSz,
word32 authInSz, word32 authTagSz, word32 inSz)
{
word32 i;
word32 lenSz;
byte mask = 0xFF;
const word32 wordSz = (word32)sizeof(word32);
/* set up B0 and CTR0 similar to how wolfcrypt/src/aes.c does */
XMEMCPY(B0Ctr0+1, nonce, nonceSz);
XMEMCPY(B0Ctr0+AES_BLOCK_SIZE+1, nonce, nonceSz);
lenSz = AES_BLOCK_SIZE - 1 - (byte)nonceSz;
B0Ctr0[0] = 0;
if (authInSz > 0) {
B0Ctr0[0] |= 0x40; /* set aad bit */
}
/* add size of tag encoded as (sz - 2)/2 (i.e M) */
B0Ctr0[0] |= (((byte)authTagSz - 2) / 2) << 3;
/* size of l(m) */
B0Ctr0[0] |= lenSz - 1;
/* add in l(m), length of message to be encrypted and sent */
for (i = 0; i < lenSz; i++) {
if (mask && i >= wordSz)
mask = 0x00;
B0Ctr0[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask;
B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE - 1 - i] = 0;
}
B0Ctr0[AES_BLOCK_SIZE] = lenSz - 1;
return 0;
}
#endif
/* plaintext in ciphertext and mac out
* return 0 on success
*/
int wc_CAAM_AesCcmEncrypt(Aes* aes, const byte* in, byte* out, word32 sz,
const byte* nonce, word32 nonceSz, byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz)
{
#ifndef WOLFSSL_SECO_CAAM
byte B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE];
#endif
if (aes == NULL || (sz != 0 && (in == NULL || out == NULL)) ||
nonce == NULL || authTag == NULL || nonceSz < 7 || nonceSz > 13 ||
authTagSz > AES_BLOCK_SIZE)
return BAD_FUNC_ARG;
/* sanity check on tag size */
if (wc_AesCcmCheckTagSize(authTagSz) != 0) {
return BAD_FUNC_ARG;
}
#ifndef WOLFSSL_SECO_CAAM
CreateB0CTR(B0Ctr0, nonce, nonceSz, authInSz, authTagSz, sz);
return wc_CAAM_AesAeadCommon(aes, in, out, sz, B0Ctr0, 2*AES_BLOCK_SIZE,
authTag, authTagSz, authIn, authInSz, CAAM_ENC, CAAM_AESCCM);
#else
return wc_CAAM_AesAeadCommon(aes, in, out, sz, nonce, nonceSz,
authTag, authTagSz, authIn, authInSz, CAAM_ENC, CAAM_AESCCM);
#endif
}
/* ciphertext in plaintext out
* return 0 on success
*/
int wc_CAAM_AesCcmDecrypt(Aes* aes, const byte* in, byte* out, word32 sz,
const byte* nonce, word32 nonceSz, const byte* authTag,
word32 authTagSz, const byte* authIn, word32 authInSz)
{
int ret;
#ifndef WOLFSSL_SECO_CAAM
byte B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE];
#endif
/* sanity check on arguments */
if (aes == NULL || (sz != 0 && (in == NULL || out == NULL)) ||
nonce == NULL || authTag == NULL || nonceSz < 7 || nonceSz > 13 ||
authTagSz > AES_BLOCK_SIZE)
return BAD_FUNC_ARG;
/* sanity check on tag size */
if (wc_AesCcmCheckTagSize(authTagSz) != 0) {
return BAD_FUNC_ARG;
}
#ifndef WOLFSSL_SECO_CAAM
CreateB0CTR(B0Ctr0, nonce, nonceSz, authInSz, authTagSz, sz);
ret = wc_CAAM_AesAeadCommon(aes, in, out, sz, B0Ctr0, 2*AES_BLOCK_SIZE,
(byte*)authTag, authTagSz, authIn, authInSz, CAAM_DEC, CAAM_AESCCM);
#else
ret = wc_CAAM_AesAeadCommon(aes, in, out, sz, nonce, nonceSz,
(byte*)authTag, authTagSz, authIn, authInSz, CAAM_DEC, CAAM_AESCCM);
#endif
if (ret != 0) {
/* If the authTag check fails, don't keep the decrypted data.
* Unfortunately, you need the decrypted data to calculate the
* check value. */
#if defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) && \
defined(ACVP_VECTOR_TESTING)
WOLFSSL_MSG("Preserve output for vector responses");
#else
if (sz > 0)
XMEMSET(out, 0, sz);
#endif
}
return ret;
}
#endif /* HAVE_AESCCM */
#if defined(HAVE_AESGCM) && defined(WOLFSSL_CAAM_AESGCM)
int wc_CAAM_AesGcmEncrypt(Aes* aes, const byte* in, byte* out, word32 sz,
const byte* nonce, word32 nonceSz, byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz)
{
return wc_CAAM_AesAeadCommon(aes, in, out, sz, nonce, nonceSz, authTag,
authTagSz, authIn, authInSz, CAAM_ENC, CAAM_AESGCM);
}
int wc_CAAM_AesGcmDecrypt(Aes* aes, const byte* in, byte* out, word32 sz,
const byte* nonce, word32 nonceSz, const byte* authTag,
word32 authTagSz, const byte* authIn, word32 authInSz)
{
return wc_CAAM_AesAeadCommon(aes, in, out, sz, nonce, nonceSz,
(byte*)authTag, authTagSz, authIn, authInSz, CAAM_DEC, CAAM_AESGCM);
}
#endif
static int wc_CAAM_AesCbcCtrCommon(Aes* aes, byte* out, const byte* in,
word32 sz, int dir, int mode)
{
word32 blocks;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
blocks = sz / AES_BLOCK_SIZE;
if (blocks > 0) {
CAAM_BUFFER buf[5];
word32 arg[4];
word32 keySz;
int ret;
if (wc_AesGetKeySize(aes, &keySz) != 0 && aes->blackKey == 0) {
return BAD_FUNC_ARG;
}
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (CAAM_ADDRESS)(void*)aes->devKey;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (CAAM_ADDRESS)aes->reg;
buf[1].Length = AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer;
buf[2].TheAddress = (CAAM_ADDRESS)in;
buf[2].Length = blocks * AES_BLOCK_SIZE;
buf[3].BufferType = DataBuffer | LastBuffer;
buf[3].TheAddress = (CAAM_ADDRESS)out;
buf[3].Length = blocks * AES_BLOCK_SIZE;
/* buffer for updated IV */
buf[4].BufferType = DataBuffer;
buf[4].TheAddress = (CAAM_ADDRESS)aes->reg;
buf[4].Length = AES_BLOCK_SIZE;
arg[0] = dir;
arg[1] = keySz;
arg[2] = blocks * AES_BLOCK_SIZE;
arg[3] = aes->blackKey;
if ((ret = wc_caamAddAndWait(buf, 5, arg, mode)) != 0) {
WOLFSSL_MSG("Error with CAAM AES CBC operation");
return ret;
}
}
return 0;
}
#ifdef WOLFSSL_AES_COUNTER
/* Increment AES counter (from wolfcrypt/src/aes.c) */
static WC_INLINE void IncrementAesCounter(byte* inOutCtr)
{
/* in network byte order so start at end and work back */
int i;
for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) {
if (++inOutCtr[i]) /* we're done unless we overflow */
return;
}
}
int wc_CAAM_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
byte* tmp;
word32 keySz;
int ret, blocks;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
if ((ret = wc_AesGetKeySize(aes, &keySz)) != 0) {
return ret;
}
/* consume any unused bytes left in aes->tmp */
tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left;
while (aes->left && sz) {
*(out++) = *(in++) ^ *(tmp++);
aes->left--;
sz--;
}
/* do full blocks to then get potential left over amount */
blocks = sz / AES_BLOCK_SIZE;
if (blocks > 0) {
ret = wc_CAAM_AesCbcCtrCommon(aes, out, in, blocks * AES_BLOCK_SIZE,
CAAM_ENC, CAAM_AESCTR);
out += blocks * AES_BLOCK_SIZE;
in += blocks * AES_BLOCK_SIZE;
sz -= blocks * AES_BLOCK_SIZE;
}
if (sz) {
if ((ret = wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg))
!= 0) {
return ret;
}
IncrementAesCounter((byte*)aes->reg);
aes->left = AES_BLOCK_SIZE;
tmp = (byte*)aes->tmp;
while (sz--) {
*(out++) = *(in++) ^ *(tmp++);
aes->left--;
}
}
return ret;
}
#endif /* WOLFSSL_AES_COUNTER */
int wc_CAAM_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
return wc_CAAM_AesCbcCtrCommon(aes, out, in, sz, CAAM_ENC, CAAM_AESCBC);
}
int wc_CAAM_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
return wc_CAAM_AesCbcCtrCommon(aes, out, in, sz, CAAM_DEC, CAAM_AESCBC);
}
#if defined(HAVE_AES_ECB)
static int wc_CAAM_AesEcbCommon(Aes* aes, byte* out, const byte* in, word32 sz,
int dir)
{
word32 blocks;
CAAM_BUFFER buf[4];
word32 arg[4];
word32 keySz = 0;
int ret;
int idx = 0;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
blocks = sz / AES_BLOCK_SIZE;
if (wc_AesGetKeySize(aes, &keySz) != 0 && aes->blackKey == 0) {
return BAD_FUNC_ARG;
}
/* Set buffers for key, cipher text, and plain text */
buf[idx].BufferType = DataBuffer;
buf[idx].TheAddress = (CAAM_ADDRESS)aes->devKey;
buf[idx].Length = keySz;
idx++;
buf[idx].BufferType = DataBuffer;
buf[idx].TheAddress = (CAAM_ADDRESS)in;
buf[idx].Length = blocks * AES_BLOCK_SIZE;
idx++;
buf[idx].BufferType = DataBuffer | LastBuffer;
buf[idx].TheAddress = (CAAM_ADDRESS)out;
buf[idx].Length = blocks * AES_BLOCK_SIZE;
idx++;
arg[0] = dir;
arg[1] = keySz;
arg[2] = blocks * AES_BLOCK_SIZE;
arg[3] = aes->blackKey;
if ((ret = wc_caamAddAndWait(buf, idx, arg, CAAM_AESECB)) != 0) {
WOLFSSL_MSG("Error with CAAM AES ECB encrypt");
return ret;
}
return 0;
}
/* is assumed that input size is a multiple of AES_BLOCK_SIZE */
int wc_CAAM_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
return wc_CAAM_AesEcbCommon(aes, out, in, sz, CAAM_ENC);
}
int wc_CAAM_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
return wc_CAAM_AesEcbCommon(aes, out, in, sz, CAAM_DEC);
}
#endif /* HAVE_AES_ECB */
#endif /* WOLFSSL_CAAM && !NO_AES */

View File

@ -0,0 +1,205 @@
/* wolfcaam_cmac.c
*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_CAAM) && defined(WOLFSSL_CMAC) && defined(WOLFSSL_CAAM_CMAC)
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
#include <wolfssl/wolfcrypt/port/caam/wolfcaam_cmac.h>
/* returns 0 on success */
int wc_CAAM_Cmac(Cmac* cmac, const byte* key, word32 keySz, const byte* in,
word32 inSz, byte* out, word32* outSz, int type, void* ctx)
{
word32 args[4] = {0};
CAAM_BUFFER buf[9];
word32 idx = 0;
byte scratch[AES_BLOCK_SIZE];
int ret;
int blocks = 0;
byte* pt = (byte*)in;
int sz = inSz;
(void)type;
args[0] = 0;
if (outSz != NULL && *outSz > 16) {
return BAD_FUNC_ARG;
}
if (out != NULL && outSz == NULL) {
return BAD_FUNC_ARG;
}
if (key != NULL || ctx != NULL) {
XMEMSET(&cmac->aes, 0, sizeof(Aes));
if (cmac->blackKey == 0) {
if (ctx != NULL) {
cmac->blackKey = 1;
XMEMCPY((byte*)cmac->aes.key, (byte*)ctx, keySz + 16);
}
else {
XMEMCPY((byte*)cmac->aes.key, (byte*)key, keySz);
}
}
cmac->keylen = keySz;
cmac->initialized = 0;
cmac->bufferSz = 0;
XMEMSET(cmac->buffer, 0, AES_BLOCK_SIZE);
return 0;
}
buf[idx].TheAddress = (CAAM_ADDRESS)cmac->aes.key;
buf[idx].Length = cmac->keylen;
idx++;
buf[idx].TheAddress = (CAAM_ADDRESS)cmac->ctx;
buf[idx].Length = sizeof(cmac->ctx);
idx++;
if (in != NULL) {
#ifdef WOLFSSL_HASH_KEEP
if (wc_CMAC_Grow(cmac, in, inSz) != 0) {
WOLFSSL_MSG("Error growing CMAC buffer");
return -1;
}
#else
args[0] |= CAAM_ALG_UPDATE;
/* first take care of any left overs */
if (cmac->bufferSz > 0) {
word32 add;
if (cmac->bufferSz > AES_BLOCK_SIZE) {
WOLFSSL_MSG("Error with CMAC buffer size");
return -1;
}
add = (sz < ((int)(AES_BLOCK_SIZE - cmac->bufferSz))) ? sz :
(int)(AES_BLOCK_SIZE - cmac->bufferSz);
XMEMCPY(&cmac->buffer[cmac->bufferSz], pt, add);
cmac->bufferSz += add;
pt += add;
sz -= add;
}
/* flash out temporary storage for block size if full and more data
* is coming, otherwise hold it until final operation */
if (cmac->bufferSz == AES_BLOCK_SIZE && (sz > 0)) {
buf[idx].TheAddress = (CAAM_ADDRESS)scratch;
buf[idx].Length = cmac->bufferSz;
idx++;
blocks++;
cmac->bufferSz = 0;
XMEMCPY(scratch, (byte*)cmac->buffer, AES_BLOCK_SIZE);
}
/* In order to trigger read of CTX state there needs to be some data
* saved until final call */
if ((sz >= AES_BLOCK_SIZE) && (sz % AES_BLOCK_SIZE == 0)) {
if (cmac->bufferSz > 0) {
/* this case should never be hit */
return BAD_FUNC_ARG;
}
XMEMCPY(&cmac->buffer[0], pt + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
cmac->bufferSz = AES_BLOCK_SIZE;
sz -= AES_BLOCK_SIZE;
}
if (sz >= AES_BLOCK_SIZE) {
buf[idx].TheAddress = (CAAM_ADDRESS)pt;
buf[idx].Length = sz - (sz % AES_BLOCK_SIZE);
blocks += sz / AES_BLOCK_SIZE;
sz -= buf[idx].Length;
pt += buf[idx].Length;
idx++;
}
#endif
}
if (out != NULL) {
#ifdef WOLFSSL_HASH_KEEP
if (cmac->msg != NULL) {
buf[idx].TheAddress = (CAAM_ADDRESS)cmac->msg;
buf[idx].Length = cmac->used;
idx++;
}
#else
/* handle any leftovers */
if (cmac->bufferSz > 0) {
buf[idx].TheAddress = (CAAM_ADDRESS)cmac->buffer;
buf[idx].Length = cmac->bufferSz;
idx++;
}
#endif
args[0] |= CAAM_ALG_FINAL;
blocks++; /* always run on final call */
}
/* set key size */
args[1] = cmac->keylen;
args[2] = cmac->blackKey;
/* only call down to CAAM if we have a full block to do or is final */
if (blocks > 0) {
if (cmac->initialized == 0) {
args[0] |= CAAM_ALG_INIT;
cmac->initialized = 1;
}
ret = wc_caamAddAndWait(buf, idx, args, CAAM_CMAC);
if (ret != 0) {
return -1;
}
}
if (out != NULL) {
XMEMCPY(out, cmac->ctx, *outSz);
}
/* store leftovers */
if (sz > 0) {
word32 add = (sz < (int)(AES_BLOCK_SIZE - cmac->bufferSz))?
(word32)sz :
(AES_BLOCK_SIZE - cmac->bufferSz);
if (pt == NULL) {
return MEMORY_E;
}
XMEMCPY(&cmac->buffer[cmac->bufferSz], pt, add);
cmac->bufferSz += add;
}
(void)scratch;
return 0;
}
#endif /* WOLFSSL_CAAM && WOLFSSL_CMAC */

View File

@ -0,0 +1,770 @@
/* wolfcaam_ecdsa.c
*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_CAAM) && defined(HAVE_ECC) && defined(WOLFSSL_CAAM_ECC)
#include <wolfssl/wolfcrypt/logging.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
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
#include <wolfssl/wolfcrypt/port/caam/wolfcaam_ecdsa.h>
#include <wolfssl/wolfcrypt/coding.h>
#include <wolfssl/wolfcrypt/asn.h>
#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
#include <stdio.h>
#endif
#ifndef WOLFSSL_HAVE_ECC_KEY_GET_PRIV
/* FIPS build has replaced ecc.h. */
#define wc_ecc_key_get_priv(key) (&((key)->k))
#define WOLFSSL_HAVE_ECC_KEY_GET_PRIV
#endif
#if defined(WOLFSSL_DEVCRYPTO_ECDSA)
/* offload calls through devcrypto support */
/* create signature using CAAM
* returns MP_OKAY on success
*/
static int wc_CAAM_DevEccSign(const byte* in, int inlen, byte* out,
word32* outlen, WC_RNG *rng, ecc_key *key)
{
const ecc_set_type* dp;
int ret, keySz;
byte r[MAX_ECC_BYTES] = {0};
byte s[MAX_ECC_BYTES] = {0};
byte pk[MAX_ECC_BYTES + WC_CAAM_MAC_SZ] = {0};
(void)rng;
if (key->dp != NULL) {
dp = key->dp;
}
else {
dp = wc_ecc_get_curve_params(key->idx);
}
if (dp->id != ECC_SECP256R1 && dp->id != ECC_SECP384R1) {
WOLFSSL_MSG("Limiting CAAM to P256 and P384 for now");
return CRYPTOCB_UNAVAILABLE;
}
keySz = wc_ecc_size(key);
/* private key */
if (mp_to_unsigned_bin_len(wc_ecc_key_get_priv(key), pk, keySz) != MP_OKAY)
{
return MP_TO_E;
}
ret = wc_DevCryptoEccSign(dp->id, key->blackKey, pk, keySz, in, inlen,
r, keySz, s, keySz);
/* convert signature from raw bytes to signature format */
if (ret == 0) {
mp_int mpr, mps;
mp_init(&mpr);
mp_init(&mps);
mp_read_unsigned_bin(&mpr, r, keySz);
mp_read_unsigned_bin(&mps, s, keySz);
ret = StoreECC_DSA_Sig(out, outlen, &mpr, &mps);
mp_free(&mpr);
mp_free(&mps);
if (ret != 0) {
WOLFSSL_MSG("Issue converting to signature\n");
return -1;
}
}
return ret;
}
/* verify with individual r and s signature parts
* returns MP_OKAY on success and sets 'res' to 1 if verified
*/
static int wc_CAAM_DevEccVerify_ex(mp_int* r, mp_int *s, const byte* hash,
word32 hashlen, int* res, ecc_key* key)
{
const ecc_set_type* dp;
int ret;
int keySz;
byte rbuf[MAX_ECC_BYTES] = {0};
byte sbuf[MAX_ECC_BYTES] = {0};
byte qx[MAX_ECC_BYTES] = {0};
byte qy[MAX_ECC_BYTES] = {0};
byte qxy[MAX_ECC_BYTES * 2] = {0};
word32 qxLen, qyLen;
if (key->dp != NULL) {
dp = key->dp;
}
else {
dp = wc_ecc_get_curve_params(key->idx);
}
/* Wx,y public key */
keySz = wc_ecc_size(key);
qxLen = qyLen = MAX_ECC_BYTES;
wc_ecc_export_public_raw(key, qx, &qxLen, qy, &qyLen);
XMEMCPY(qxy, qx, qxLen);
XMEMCPY(qxy+qxLen, qy, qyLen);
if (mp_to_unsigned_bin_len(r, rbuf, keySz) != MP_OKAY) {
return MP_TO_E;
}
if (mp_to_unsigned_bin_len(s, sbuf, keySz) != MP_OKAY) {
return MP_TO_E;
}
ret = wc_DevCryptoEccVerify(dp->id, qxy, qxLen + qyLen, hash, hashlen,
rbuf, keySz, sbuf, keySz);
*res = 0;
if (ret == 0)
*res = 1;
return ret;
}
/* Does ECDH operation using CAAM and returns MP_OKAY on success */
static int wc_CAAM_DevEcdh(ecc_key* private_key, ecc_key* public_key, byte* out,
word32* outlen)
{
const ecc_set_type* dp;
int ret, keySz;
byte pk[MAX_ECC_BYTES + WC_CAAM_MAC_SZ] = {0};
byte qx[MAX_ECC_BYTES] = {0};
byte qy[MAX_ECC_BYTES] = {0};
byte qxy[MAX_ECC_BYTES * 2] = {0};
word32 qxSz, qySz;
if (private_key->dp != NULL) {
dp = private_key->dp;
}
else {
dp = wc_ecc_get_curve_params(private_key->idx);
}
keySz = wc_ecc_size(private_key);
if (*outlen < (word32)keySz) {
WOLFSSL_MSG("out buffer is to small");
return BUFFER_E;
}
/* public key */
qxSz = qySz = MAX_ECC_BYTES;
wc_ecc_export_public_raw(public_key, qx, &qxSz, qy, &qySz);
XMEMCPY(qxy, qx, qxSz);
XMEMCPY(qxy+qxSz, qy, qySz);
/* private key */
if (mp_to_unsigned_bin_len(wc_ecc_key_get_priv(private_key), pk, keySz) !=
MP_OKAY) {
WOLFSSL_MSG("error getting private key buffer");
return MP_TO_E;
}
ret = wc_DevCryptoEccEcdh(dp->id, private_key->blackKey, pk, keySz,
qxy, qxSz + qySz, out, *outlen);
if (ret == 0) {
*outlen = keySz;
}
return ret;
}
#ifdef WOLFSSL_KEY_GEN
/* [ private black key ] [ x , y ] */
static int wc_CAAM_DevMakeEccKey(WC_RNG* rng, int keySize, ecc_key* key,
int curveId)
{
int ret;
int blackKey = 1; /* default to using black encrypted keys */
byte s[MAX_ECC_BYTES + WC_CAAM_MAC_SZ] = {0};
byte xy[MAX_ECC_BYTES*2] = {0};
key->type = ECC_PRIVATEKEY;
/* if set to default curve then assume SECP256R1 */
if (keySize == 32 && curveId == ECC_CURVE_DEF) curveId = ECC_SECP256R1;
if (curveId != ECC_SECP256R1 &&
curveId != ECC_SECP384R1) {
return CRYPTOCB_UNAVAILABLE;
}
ret = wc_DevCryptoEccKeyGen(curveId, blackKey, s, keySize, xy, keySize*2);
if (wc_ecc_import_unsigned(key, xy, xy + keySize, s, curveId) != 0) {
WOLFSSL_MSG("issue importing key");
return -1;
}
key->blackKey = blackKey;
(void)rng;
return ret;
}
#endif /* WOLFSSL_KEY_GEN */
#endif /* WOLFSSL_DEVCRYPTO_ECDSA */
#ifndef WOLFSSL_IMXRT1170_CAAM
/* helper function get the ECDSEL value, this is a value that signals the
* hardware to use preloaded curve parameters
*/
static word32 GetECDSEL(int curveId, word32 PD_BIT)
{
word32 ecdsel = 0;
switch (curveId) {
case ECC_SECP192R1:
ecdsel = (PD_BIT | CAAM_ECDSA_P192);
break;
case ECC_SECP224R1:
ecdsel = (PD_BIT | CAAM_ECDSA_P224);
break;
case ECC_CURVE_DEF:
case ECC_SECP256R1:
ecdsel = (PD_BIT | CAAM_ECDSA_P256);
break;
case ECC_SECP384R1:
ecdsel = (PD_BIT | CAAM_ECDSA_P384);
break;
case ECC_SECP521R1:
ecdsel = (PD_BIT | CAAM_ECDSA_P521);
break;
default:
WOLFSSL_MSG("not using preset curve parameters");
}
return ecdsel;
}
/* create signature using CAAM
* returns MP_OKAY on success
*/
int wc_CAAM_EccSign(const byte* in, int inlen, byte* out, word32* outlen,
WC_RNG *rng, ecc_key *key, int devId)
{
const ecc_set_type* dp;
word32 args[4] = {0};
CAAM_BUFFER buf[9];
int ret, keySz;
word32 ecdsel = 0;
byte r[MAX_ECC_BYTES] = {0};
byte s[MAX_ECC_BYTES] = {0};
word32 idx = 0;
byte pk[MAX_ECC_BYTES + WC_CAAM_MAC_SZ] = {0};
#if defined(WOLFSSL_DEVCRYPTO_ECDSA)
if (devId == WOLFSSL_CAAM_DEVID) {
return wc_CAAM_DevEccSign(in, inlen, out, outlen, rng, key);
}
#endif
(void)rng;
if (key->dp != NULL) {
dp = key->dp;
}
else {
dp = wc_ecc_get_curve_params(key->idx);
}
if (dp->id != ECC_SECP256R1 && dp->id != ECC_SECP384R1) {
WOLFSSL_MSG("Limiting CAAM to P256/P384 for now");
return CRYPTOCB_UNAVAILABLE;
}
/* check for known predetermined parameters */
ecdsel = GetECDSEL(dp->id, CAAM_ECDSA_PD);
if (ecdsel == 0) {
WOLFSSL_MSG("Unsupported curve type");
return BAD_FUNC_ARG;
}
keySz = wc_ecc_size(key);
/* private key */
if (key->blackKey == CAAM_BLACK_KEY_SM) {
buf[idx].TheAddress = (CAAM_ADDRESS)key->blackKey;
args[0] = CAAM_BLACK_KEY_SM; /* is a black key in sm */
buf[idx].Length = keySz;
}
else {
if (key->blackKey == CAAM_BLACK_KEY_CCM) {
if (mp_to_unsigned_bin_len(wc_ecc_key_get_priv(key), pk,
keySz + WC_CAAM_MAC_SZ) != MP_OKAY) {
return MP_TO_E;
}
buf[idx].Length = keySz + WC_CAAM_MAC_SZ;
}
else {
if (mp_to_unsigned_bin_len(wc_ecc_key_get_priv(key), pk, keySz) !=
MP_OKAY) {
return MP_TO_E;
}
buf[idx].Length = keySz;
}
buf[idx].TheAddress = (CAAM_ADDRESS)pk;
args[0] = key->blackKey; /* potential black key, not in sm */
}
idx++;
/* hash to sign */
buf[idx].TheAddress = (CAAM_ADDRESS)in;
buf[idx].Length = inlen;
idx++;
/* r output */
buf[idx].TheAddress = (CAAM_ADDRESS)r;
buf[idx].Length = keySz;
idx++;
/* s output */
buf[idx].TheAddress = (CAAM_ADDRESS)s;
buf[idx].Length = keySz;
idx++;
args[1] = ecdsel;
args[2] = inlen;
args[3] = keySz;
ret = wc_caamAddAndWait(buf, idx, args, CAAM_ECDSA_SIGN);
if (ret != 0)
return -1;
/* convert signature from raw bytes to signature format */
{
mp_int mpr, mps;
mp_init(&mpr);
mp_init(&mps);
mp_read_unsigned_bin(&mpr, r, keySz);
mp_read_unsigned_bin(&mps, s, keySz);
ret = StoreECC_DSA_Sig(out, outlen, &mpr, &mps);
mp_free(&mpr);
mp_free(&mps);
if (ret != 0) {
WOLFSSL_MSG("Issue converting to signature");
return -1;
}
}
(void)devId;
return MP_OKAY;
}
/* verify with individual r and s signature parts
* returns MP_OKAY on success and sets 'res' to 1 if verified
*/
static int wc_CAAM_EccVerify_ex(mp_int* r, mp_int *s, const byte* hash,
word32 hashlen, int* res, ecc_key* key)
{
const ecc_set_type* dp;
word32 args[4] = {0};
CAAM_BUFFER buf[9];
int ret;
int keySz;
word32 idx = 0;
word32 ecdsel = 0;
byte rbuf[MAX_ECC_BYTES] = {0};
byte sbuf[MAX_ECC_BYTES] = {0};
byte qx[MAX_ECC_BYTES] = {0};
byte qy[MAX_ECC_BYTES] = {0};
byte qxy[MAX_ECC_BYTES * 2] = {0};
byte tmp[MAX_ECC_BYTES * 2] = {0};
word32 qxLen, qyLen;
if (key->dp != NULL) {
dp = key->dp;
}
else {
dp = wc_ecc_get_curve_params(key->idx);
}
/* right now only support P256/P384 @TODO */
if (dp->id != ECC_SECP256R1 && dp->id != ECC_SECP384R1) {
WOLFSSL_MSG("Only support P256 and P384 verify with CAAM for now");
return CRYPTOCB_UNAVAILABLE;
}
/* check for known predetermined parameters */
ecdsel = GetECDSEL(dp->id, CAAM_ECDSA_PD);
if (ecdsel == 0) {
WOLFSSL_MSG("Curve parameters not supported");
return CRYPTOCB_UNAVAILABLE;
}
/* Wx,y public key */
keySz = wc_ecc_size(key);
if (key->securePubKey > 0) {
buf[idx].TheAddress = (CAAM_ADDRESS)key->securePubKey;
buf[idx].Length = keySz * 2;
args[0] = 1; /* using public key in secure memory */
}
else {
qxLen = qyLen = MAX_ECC_BYTES;
wc_ecc_export_public_raw(key, qx, &qxLen, qy, &qyLen);
XMEMCPY(qxy, qx, qxLen);
XMEMCPY(qxy+qxLen, qy, qyLen);
buf[idx].TheAddress = (CAAM_ADDRESS)qxy;
buf[idx].Length = qxLen + qyLen;
}
idx++;
buf[idx].TheAddress = (CAAM_ADDRESS)hash;
buf[idx].Length = hashlen;
idx++;
if (mp_to_unsigned_bin_len(r, rbuf, keySz) != MP_OKAY) {
return MP_TO_E;
}
buf[idx].TheAddress = (CAAM_ADDRESS)rbuf;
buf[idx].Length = keySz;
idx++;
if (mp_to_unsigned_bin_len(s, sbuf, keySz) != MP_OKAY) {
return MP_TO_E;
}
buf[idx].TheAddress = (CAAM_ADDRESS)sbuf;
buf[idx].Length = keySz;
idx++;
/* temporary scratch buffer, the manual calls for it and HW expects it */
buf[idx].TheAddress = (CAAM_ADDRESS)tmp;
buf[idx].Length = sizeof(tmp);
idx++;
args[1] = ecdsel;
args[2] = hashlen;
args[3] = wc_ecc_size(key);
ret = wc_caamAddAndWait(buf, idx, args, CAAM_ECDSA_VERIFY);
*res = 0;
if (ret == 0)
*res = 1;
return MP_OKAY;
}
/* Verify with ASN1 syntax around the signature
* returns MP_OKAY on success
*/
int wc_CAAM_EccVerify(const byte* sig, word32 siglen, const byte* hash,
word32 hashlen, int* res, ecc_key* key, int devId)
{
int ret;
mp_int r, s;
ret = DecodeECC_DSA_Sig(sig, siglen, &r, &s);
if (ret == 0) {
#if defined(WOLFSSL_DEVCRYPTO_ECDSA)
if (devId == WOLFSSL_CAAM_DEVID) {
ret = wc_CAAM_DevEccVerify_ex(&r, &s, hash, hashlen, res, key);
}
else
#endif
{
ret = wc_CAAM_EccVerify_ex(&r, &s, hash, hashlen, res, key);
}
mp_free(&r);
mp_free(&s);
}
(void)devId;
return ret;
}
/* Does ECDH operation using CAAM and returns MP_OKAY on success */
int wc_CAAM_Ecdh(ecc_key* private_key, ecc_key* public_key, byte* out,
word32* outlen, int devId)
{
const ecc_set_type* dp;
word32 args[4] = {0};
CAAM_BUFFER buf[9];
int ret, keySz;
word32 ecdsel = 0; /* ecc parameters in hardware */
word32 idx = 0;
byte pk[MAX_ECC_BYTES + WC_CAAM_MAC_SZ] = {0};
byte qx[MAX_ECC_BYTES] = {0};
byte qy[MAX_ECC_BYTES] = {0};
byte qxy[MAX_ECC_BYTES * 2] = {0};
word32 qxSz, qySz;
#if defined(WOLFSSL_DEVCRYPTO_ECDSA)
if (devId == WOLFSSL_CAAM_DEVID) {
return wc_CAAM_DevEcdh(private_key, public_key, out, outlen);
}
#endif
if (private_key->dp != NULL) {
dp = private_key->dp;
}
else {
dp = wc_ecc_get_curve_params(private_key->idx);
}
if (dp->id != ECC_SECP256R1 && dp->id != ECC_SECP384R1) {
return CRYPTOCB_UNAVAILABLE;
}
/* check for known predetermined parameters */
ecdsel = GetECDSEL(dp->id, CAAM_ECDSA_KEYGEN_PD);
if (ecdsel == 0) { /* predefined value not known, loading all parameters */
WOLFSSL_MSG("Unsupported curve parameters");
return CRYPTOCB_UNAVAILABLE;
}
keySz = wc_ecc_size(private_key);
if (*outlen < (word32)keySz) {
WOLFSSL_MSG("out buffer is to small");
return BUFFER_E;
}
/* public key */
if (public_key->securePubKey > 0) {
buf[idx].TheAddress = (CAAM_ADDRESS)public_key->securePubKey;
buf[idx].Length = keySz * 2;
args[1] = 1; /* using public key with secure memory address */
}
else {
qxSz = qySz = MAX_ECC_BYTES;
wc_ecc_export_public_raw(public_key, qx, &qxSz, qy, &qySz);
XMEMCPY(qxy, qx, qxSz);
XMEMCPY(qxy+qxSz, qy, qySz);
buf[idx].TheAddress = (CAAM_ADDRESS)qxy;
buf[idx].Length = qxSz + qySz;
}
idx++;
/* private key */
if (private_key->blackKey > 0 &&
(private_key->blackKey != CAAM_BLACK_KEY_CCM &&
private_key->blackKey != CAAM_BLACK_KEY_ECB)) {
buf[idx].TheAddress = (CAAM_ADDRESS)private_key->blackKey;
args[0] = CAAM_BLACK_KEY_SM; /* is a black key */
buf[idx].Length = sizeof(unsigned int);
}
else {
if (keySz > MAX_ECC_BYTES) {
return BUFFER_E;
}
if (private_key->blackKey == CAAM_BLACK_KEY_CCM) {
if (mp_to_unsigned_bin_len(wc_ecc_key_get_priv(private_key), pk,
keySz + WC_CAAM_MAC_SZ) != MP_OKAY) {
return MP_TO_E;
}
buf[idx].Length = keySz + WC_CAAM_MAC_SZ;
}
else {
if (mp_to_unsigned_bin_len(wc_ecc_key_get_priv(private_key), pk,
keySz) != MP_OKAY) {
return MP_TO_E;
}
buf[idx].Length = keySz;
}
buf[idx].TheAddress = (CAAM_ADDRESS)pk;
args[0] = private_key->blackKey; /* potential black key, but not sm */
}
#if 0
{
int z;
unsigned char* pt = (unsigned char*)buf[idx].TheAddress;
printf("sending private key [%d] :", buf[idx].Length);
for (z = 0; z < buf[idx].Length; z++)
printf("%02X", pt[z]);
printf("\n");
}
#endif
idx++;
/* output shared secret */
buf[idx].TheAddress = (CAAM_ADDRESS)out;
buf[idx].Length = keySz;
idx++;
args[2] = ecdsel;
args[3] = keySz;
ret = wc_caamAddAndWait(buf, idx, args, CAAM_ECDSA_ECDH);
(void)devId;
if (ret == 0) {
*outlen = keySz;
return MP_OKAY;
}
else {
return -1;
}
}
#ifdef WOLFSSL_KEY_GEN
/* [ private black key ] [ x , y ] */
int wc_CAAM_MakeEccKey(WC_RNG* rng, int keySize, ecc_key* key, int curveId,
int devId)
{
word32 args[4] = {0};
CAAM_BUFFER buf[2] = {0};
word32 ecdsel = 0;
int ret;
byte s[MAX_ECC_BYTES + WC_CAAM_MAC_SZ] = {0};
byte xy[MAX_ECC_BYTES*2] = {0};
#if defined(WOLFSSL_DEVCRYPTO_ECDSA)
if (devId == WOLFSSL_CAAM_DEVID) {
return wc_CAAM_DevMakeEccKey(rng, keySize, key, curveId);
}
#endif
key->type = ECC_PRIVATEKEY;
/* if set to default curve then assume SECP256R1 */
if (keySize == 32 && curveId == ECC_CURVE_DEF) curveId = ECC_SECP256R1;
if (keySize == 48 && curveId == ECC_CURVE_DEF) curveId = ECC_SECP384R1;
if (curveId != ECC_SECP256R1 && curveId != ECC_SECP384R1) {
/* currently only implemented P256/P384 support */
return CRYPTOCB_UNAVAILABLE;
}
ecdsel = GetECDSEL(curveId, CAAM_ECDSA_KEYGEN_PD);
if (ecdsel == 0) {
WOLFSSL_MSG("unknown key type or size");
return CRYPTOCB_UNAVAILABLE;
}
(void)rng;
(void)devId;
if (key->blackKey == 0) {
#ifdef WOLFSSL_CAAM_NO_BLACK_KEY
args[0] = 0;
#elif defined(WOLFSSL_CAAM_BLACK_KEY_AESCCM)
args[0] = CAAM_BLACK_KEY_CCM;
#elif defined(WOLFSSL_CAAM_BLACK_KEY_SM)
args[0] = CAAM_BLACK_KEY_SM;
#else
args[0] = CAAM_BLACK_KEY_ECB;
#endif
}
else {
/* type of black key was already set in the ecc key struct */
args[0] = key->blackKey;
}
args[1] = ecdsel;
args[3] = keySize;
buf[0].TheAddress = (CAAM_ADDRESS)s;
if (args[0] == CAAM_BLACK_KEY_SM) {
/* only get a physical address */
buf[0].Length = sizeof(unsigned int);
}
else if (args[0] == CAAM_BLACK_KEY_CCM) {
/* account for additional MAC */
buf[0].Length = keySize + WC_CAAM_MAC_SZ;
}
else {
buf[0].Length = keySize;
}
buf[1].TheAddress = (CAAM_ADDRESS)xy;
buf[1].Length = keySize*2;
key->blackKey = args[0];
ret = wc_caamAddAndWait(buf, 2, args, CAAM_ECDSA_KEYPAIR);
if (args[0] == CAAM_BLACK_KEY_SM && ret == 0) {
unsigned char* pt = (unsigned char*)buf[0].TheAddress;
key->blackKey = (pt[0] << 24) | (pt[1] << 16) | (pt[2] << 8) | pt[3];
if (wc_ecc_import_unsigned(key, xy, xy + keySize, NULL, curveId) != 0) {
WOLFSSL_MSG("issue importing public key");
return -1;
}
key->partNum = args[2];
return MP_OKAY;
}
else if (ret == 0) {
if (wc_ecc_import_unsigned(key, xy, xy + keySize,
s, curveId) != 0) {
WOLFSSL_MSG("issue importing key");
return -1;
}
key->blackKey = args[0];
return MP_OKAY;
}
return -1;
}
#endif /* WOLFSSL_KEY_GEN */
#endif /* WOLFSSL_IMXRT1170_CAAM */
/* if dealing with a black encrypted key then it can not be checked */
int wc_CAAM_EccCheckPrivKey(ecc_key* key, const byte* pubKey, word32 pubKeySz) {
(void)pubKey;
(void)pubKeySz;
if (key->dp->id == ECC_SECP256R1 && key->blackKey > 0) {
return 0;
}
return CRYPTOCB_UNAVAILABLE;
}
#endif /* WOLFSSL_QNX_CAAM && HAVE_ECC */

View File

@ -0,0 +1,871 @@
/* wolfcaam_fsl_nxp.c
*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_IMXRT1170_CAAM)
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
#ifndef WOLFSSL_HAVE_ECC_KEY_GET_PRIV
/* FIPS build has replaced ecc.h. */
#define wc_ecc_key_get_priv(key) (&((key)->k))
#define WOLFSSL_HAVE_ECC_KEY_GET_PRIV
#endif
#if defined(FSL_FEATURE_HAS_L1CACHE) || defined(__DCACHE_PRESENT)
/* Setup for if memory is cached */
AT_NONCACHEABLE_SECTION(static caam_job_ring_interface_t jr0);
AT_NONCACHEABLE_SECTION(static caam_job_ring_interface_t jr1);
AT_NONCACHEABLE_SECTION(static caam_job_ring_interface_t jr2);
AT_NONCACHEABLE_SECTION(static caam_job_ring_interface_t jr3);
#else
/* If not cached */
static caam_job_ring_interface_t jr0;
static caam_job_ring_interface_t jr1;
static caam_job_ring_interface_t jr2;
static caam_job_ring_interface_t jr3;
#endif
static wolfSSL_Mutex caamMutex;
/* Initialize CAAM resources.
* return 0 on success */
int wc_CAAMInitInterface()
{
CAAM_Type *base = CAAM;
caam_config_t caamConfig;
if (wc_InitMutex(&caamMutex) != 0) {
WOLFSSL_MSG("Could not init mutex");
return -1;
}
/* Get default configuration. */
CAAM_GetDefaultConfig(&caamConfig);
/* set the job rings */
caamConfig.jobRingInterface[0] = &jr0;
caamConfig.jobRingInterface[1] = &jr1;
caamConfig.jobRingInterface[2] = &jr2;
caamConfig.jobRingInterface[3] = &jr3;
/* Init CAAM driver, including CAAM's internal RNG */
if (CAAM_Init(base, &caamConfig) != kStatus_Success) {
return -1;
}
return 0;
}
/* free up CAAM resources */
void wc_CAAMFreeInterface()
{
wc_FreeMutex(&caamMutex);
if (CAAM_Deinit(CAAM) != kStatus_Success) {
WOLFSSL_MSG("Failed to deinit CAAM!");
}
}
#if !defined(NO_SHA) || defined(WOLFSSL_SHA224) || !defined(NO_SHA256) \
|| defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)
/* convert the wolfCrypt hash type to NXP enum */
static caam_hash_algo_t WC2NXP(int type)
{
switch (type) {
case WC_HASH_TYPE_SHA:
return kCAAM_Sha1;
case WC_HASH_TYPE_SHA224:
return kCAAM_Sha224;
case WC_HASH_TYPE_SHA256:
return kCAAM_Sha256;
case WC_HASH_TYPE_SHA384:
return kCAAM_Sha384;
case WC_HASH_TYPE_SHA512:
return kCAAM_Sha512;
default:
return -1;
}
}
/* Common init code for hash algorithms.
* returns 0 on success
*/
int wc_CAAM_HashInit(caam_handle_t* hndl, caam_hash_ctx_t* ctx, int type)
{
if (hndl == NULL || ctx == NULL) {
return BAD_FUNC_ARG;
}
/* only using job ring0 for now */
hndl->jobRing = kCAAM_JobRing0;
if (CAAM_HASH_Init(CAAM, hndl, ctx, WC2NXP(type), NULL, 0u)
!= kStatus_Success) {
return WC_HW_E;
}
return 0;
}
/* All hashing algorithms have common code except the 'type' to perform.
* This helper function implements the common code.
* returns 0 on success
*/
static int wc_CAAM_CommonHash(caam_handle_t* hndl, caam_hash_ctx_t *ctx,
const byte* in, int inSz, byte* digest, size_t digestSz, int hashType)
{
int ret = 0;
status_t status;
if (in != NULL && inSz > 0) {
byte *alignedIn = NULL;
byte *tmpIn = NULL;
if ((wc_ptr_t)in % CAAM_BUFFER_ALIGN) {
/* input not aligned */
tmpIn = (byte*)XMALLOC(inSz + CAAM_BUFFER_ALIGN, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
alignedIn = tmpIn + (CAAM_BUFFER_ALIGN -
((wc_ptr_t)tmpIn % CAAM_BUFFER_ALIGN));
XMEMCPY(alignedIn, in, inSz);
}
else {
alignedIn = (byte*)in;
}
status = CAAM_HASH_Update(ctx, alignedIn, inSz);
if (tmpIn != NULL) {
XFREE(tmpIn, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
if (status != kStatus_Success) {
return WC_HW_E;
}
}
if (digest != NULL) {
byte *tmpOut = NULL;
byte *alignedOut = NULL;
size_t sz = digestSz;
if ((wc_ptr_t)digest % CAAM_BUFFER_ALIGN) {
/* input not aligned */
tmpOut = (byte*)XMALLOC(sz + CAAM_BUFFER_ALIGN, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
alignedOut = tmpOut + (CAAM_BUFFER_ALIGN -
((wc_ptr_t)tmpOut % CAAM_BUFFER_ALIGN));
}
else {
alignedOut = digest;
}
status = CAAM_HASH_Finish(ctx, alignedOut, &sz);
if (tmpOut != NULL) {
XMEMCPY(digest, alignedOut, sz);
XFREE(tmpOut, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
if (status != kStatus_Success) {
WOLFSSL_MSG("Failed on CAAM_HASH_Finish");
return WC_HW_E;
}
else {
ret = wc_CAAM_HashInit(hndl, ctx, hashType);
}
}
return ret;
}
#endif
#if !defined(NO_SHA)
/* SHA returns 0 on success */
int wc_CAAM_ShaHash(wc_Sha* sha, const byte* in, word32 inSz, byte* digest)
{
return wc_CAAM_CommonHash(&sha->hndl, &sha->ctx, in, inSz, digest,
WC_SHA_DIGEST_SIZE, WC_HASH_TYPE_SHA);
}
#endif
#ifdef WOLFSSL_SHA224
/* SHA224 returns 0 on success */
int wc_CAAM_Sha224Hash(wc_Sha224* sha, const byte* in, word32 inSz,
byte* digest)
{
return wc_CAAM_CommonHash(&sha->hndl, &sha->ctx, in, inSz, digest,
WC_SHA224_DIGEST_SIZE, WC_HASH_TYPE_SHA224);
}
#endif
#if !defined(NO_SHA256)
/* SHA256 returns 0 on success */
int wc_CAAM_Sha256Hash(wc_Sha256* sha, const byte* in, word32 inSz,
byte* digest)
{
return wc_CAAM_CommonHash(&sha->hndl, &sha->ctx, in, inSz, digest,
WC_SHA256_DIGEST_SIZE, WC_HASH_TYPE_SHA256);
}
#endif
#ifdef WOLFSSL_SHA384
/* SHA384 returns 0 on success */
int wc_CAAM_Sha384Hash(wc_Sha384* sha, const byte* in, word32 inSz,
byte* digest)
{
return wc_CAAM_CommonHash(&sha->hndl, &sha->ctx, in, inSz, digest,
WC_SHA384_DIGEST_SIZE, WC_HASH_TYPE_SHA384);
}
#endif
#ifdef WOLFSSL_SHA512
/* SHA512 returns 0 on success */
int wc_CAAM_Sha512Hash(wc_Sha512* sha, const byte* in, word32 inSz,
byte* digest)
{
return wc_CAAM_CommonHash(&sha->hndl, &sha->ctx, in, inSz, digest,
WC_SHA512_DIGEST_SIZE, WC_HASH_TYPE_SHA512);
}
#endif
#ifndef NO_AES_CBC
/* AES-CBC returns 0 on success */
static int DoAesCBC(unsigned int args[4], CAAM_BUFFER *buf, int sz)
{
status_t status;
caam_handle_t hndl;
/* @TODO running on alternate job rings - performance enhancement */
hndl.jobRing = kCAAM_JobRing0;
if (args[0] == CAAM_DEC) {
status = CAAM_AES_DecryptCbc(CAAM, &hndl,
(const uint8_t*)buf[2].TheAddress, (uint8_t*)buf[3].TheAddress,
buf[3].Length, (const uint8_t*)buf[4].TheAddress,
(const uint8_t*)buf[0].TheAddress, buf[0].Length);
/* store updated CBC state */
XMEMCPY((byte*)buf[4].TheAddress,
(byte*)buf[2].TheAddress + buf[2].Length - AES_BLOCK_SIZE,
AES_BLOCK_SIZE);
}
else {
status = CAAM_AES_EncryptCbc(CAAM, &hndl,
(const uint8_t*)buf[2].TheAddress, (uint8_t*)buf[3].TheAddress,
buf[3].Length, (const uint8_t*)buf[4].TheAddress,
(const uint8_t*)buf[0].TheAddress, buf[0].Length);
/* store updated CBC state */
XMEMCPY((byte*)buf[4].TheAddress,
(byte*)buf[3].TheAddress + buf[3].Length - AES_BLOCK_SIZE,
AES_BLOCK_SIZE);
}
if (status != kStatus_Success) {
return -1;
}
return 0;
}
#endif
#ifdef WOLFSSL_AES_COUNTER
/* AES-CTR returns 0 on success */
static int DoAesCTR(unsigned int args[4], CAAM_BUFFER *buf, int sz)
{
status_t status;
caam_handle_t hndl;
byte *tmpIn = NULL;
byte *tmpOut = NULL;
byte *alignedIn = NULL;
byte *alignedOut = NULL;
if (buf[2].TheAddress % CAAM_BUFFER_ALIGN) {
/* input not aligned */
tmpIn = (byte*)XMALLOC(buf[2].Length + CAAM_BUFFER_ALIGN, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
alignedIn = tmpIn + (CAAM_BUFFER_ALIGN -
((wc_ptr_t)tmpIn % CAAM_BUFFER_ALIGN));
XMEMCPY(alignedIn, (byte*)buf[2].TheAddress, buf[2].Length);
}
else {
alignedIn = (byte*)buf[2].TheAddress;
}
if (buf[3].TheAddress % CAAM_BUFFER_ALIGN) {
/* output not aligned */
tmpOut = (byte*)XMALLOC(buf[3].Length + CAAM_BUFFER_ALIGN, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
alignedOut = tmpOut + (CAAM_BUFFER_ALIGN -
((wc_ptr_t)tmpOut % CAAM_BUFFER_ALIGN));
}
else {
alignedOut = (byte*)buf[3].TheAddress;
}
/* @TODO running on alternate job rings - performance enhancement */
hndl.jobRing = kCAAM_JobRing0;
status = CAAM_AES_CryptCtr(CAAM, &hndl, alignedIn, alignedOut,
buf[3].Length, (byte*)buf[4].TheAddress, (byte*)buf[0].TheAddress,
buf[0].Length, (byte*)buf[2].TheAddress, NULL);
if (tmpOut != NULL) {
XMEMCPY((byte*)buf[3].TheAddress, alignedOut, buf[3].Length);
XFREE(tmpOut, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
if (tmpIn != NULL) {
XFREE(tmpIn, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
if (status != kStatus_Success) {
return -1;
}
return 0;
}
#endif
#if defined(HAVE_ECC) && defined(WOLFSSL_CAAM_ECC)
#include <wolfssl/wolfcrypt/asn.h>
/* helper function get the ECDSEL value, this is a value that signals the
* hardware to use preloaded curve parameters
*/
static word32 GetECDSEL(int curveId)
{
word32 ecdsel = 0;
switch (curveId) {
case ECC_SECP192R1:
ecdsel = CAAM_ECDSA_P192;
break;
case ECC_SECP224R1:
ecdsel = CAAM_ECDSA_P224;
break;
case ECC_CURVE_DEF:
case ECC_SECP256R1:
ecdsel = CAAM_ECDSA_P256;
break;
case ECC_SECP384R1:
ecdsel = CAAM_ECDSA_P384;
break;
case ECC_SECP521R1:
ecdsel = CAAM_ECDSA_P521;
break;
default:
WOLFSSL_MSG("not using preset curve parameters");
}
return ecdsel;
}
/* ECC sign operation on hardware, can handle black keys
* returns 0 on success
*/
int wc_CAAM_EccSign(const byte* in, int inlen, byte* out, word32* outlen,
WC_RNG *rng, ecc_key *key, int devId)
{
const ecc_set_type* dp;
int ret = 0;
ALIGN16 byte k[MAX_ECC_BYTES + WC_CAAM_MAC_SZ];
word32 kSz = MAX_ECC_BYTES + WC_CAAM_MAC_SZ;
/* input needs to be aligned */
byte *alignedIn = NULL;
byte *tmpIn = NULL;
ALIGN16 byte r[MAX_ECC_BYTES] = {0};
ALIGN16 byte s[MAX_ECC_BYTES] = {0};
word32 rSz = MAX_ECC_BYTES;
word32 sSz = MAX_ECC_BYTES;
int keySz;
word32 ecdsel;
word32 enc = 0;
status_t status;
caam_handle_t hndl;
/* @TODO running on alternate job rings - performance enhancement */
hndl.jobRing = kCAAM_JobRing0;
(void)rng;
if (key->dp != NULL) {
dp = key->dp;
}
else {
dp = wc_ecc_get_curve_params(key->idx);
}
if (dp->id != ECC_SECP256R1 && dp->id != ECC_SECP384R1) {
WOLFSSL_MSG("Limiting CAAM to P256/P384 for now");
return CRYPTOCB_UNAVAILABLE;
}
/* check for known predetermined parameters */
ecdsel = GetECDSEL(dp->id);
if (ecdsel == 0) {
WOLFSSL_MSG("Unsupported curve type");
return BAD_FUNC_ARG;
}
keySz = kSz = wc_ecc_size(key);
/* private key */
if (key->blackKey == CAAM_BLACK_KEY_SM) {
ret = -1; /* only handling black keys not SM (secure memory) ones */
}
else {
if (key->blackKey == CAAM_BLACK_KEY_CCM) {
if (mp_to_unsigned_bin_len(wc_ecc_key_get_priv(key), k,
kSz + WC_CAAM_MAC_SZ) != MP_OKAY) {
return MP_TO_E;
}
}
else {
if (mp_to_unsigned_bin_len(wc_ecc_key_get_priv(key), k, kSz) !=
MP_OKAY) {
return MP_TO_E;
}
}
}
ecdsel = GetECDSEL(dp->id);
if (ecdsel == 0) {
WOLFSSL_MSG("unknown key type or size");
return CRYPTOCB_UNAVAILABLE;
}
switch (key->blackKey) {
case 0:
enc = 0;
break;
case CAAM_BLACK_KEY_ECB:
enc = CAAM_PKHA_ENC_PRI_AESECB;
break;
default:
WOLFSSL_MSG("unknown/unsupported key type");
return BAD_FUNC_ARG;
}
if ((wc_ptr_t)in % CAAM_BUFFER_ALIGN) {
/* input not aligned */
tmpIn = (byte*)XMALLOC(inlen + CAAM_BUFFER_ALIGN, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
alignedIn = tmpIn + (CAAM_BUFFER_ALIGN -
((wc_ptr_t)tmpIn % CAAM_BUFFER_ALIGN));
XMEMCPY(alignedIn, in, inlen);
}
else {
alignedIn = (byte*)in;
}
status = CAAM_ECC_Sign(CAAM, &hndl, k, kSz, alignedIn, inlen, r, rSz, s,
sSz, ecdsel, enc);
if (tmpIn != NULL) {
XFREE(tmpIn, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
if (status != kStatus_Success) {
ret = -1;
}
/* convert signature from raw bytes to signature format */
if (ret == 0) {
mp_int mpr, mps;
mp_init(&mpr);
mp_init(&mps);
mp_read_unsigned_bin(&mpr, r, keySz);
mp_read_unsigned_bin(&mps, s, keySz);
ret = StoreECC_DSA_Sig(out, outlen, &mpr, &mps);
mp_free(&mpr);
mp_free(&mps);
if (ret != 0) {
WOLFSSL_MSG("Issue converting to signature");
return -1;
}
}
return ret;
}
/* helper function to handle r/s with verify
* returns 0 on success
*/
static int wc_CAAM_EccVerify_ex(mp_int* r, mp_int *s, const byte* hash,
word32 hashlen, int* res, ecc_key* key)
{
const ecc_set_type* dp;
int keySz;
word32 ecdsel = 0;
/* input needs to be aligned */
byte *alignedIn = NULL;
byte *tmpIn = NULL;
ALIGN16 byte rbuf[MAX_ECC_BYTES] = {0};
ALIGN16 byte sbuf[MAX_ECC_BYTES] = {0};
ALIGN16 byte qx[MAX_ECC_BYTES] = {0};
ALIGN16 byte qy[MAX_ECC_BYTES] = {0};
ALIGN16 byte qxy[MAX_ECC_BYTES * 2] = {0};
word32 qxLen, qyLen;
status_t status;
caam_handle_t hndl;
/* @TODO running on alternate job rings - performance enhancement */
hndl.jobRing = kCAAM_JobRing0;
if (key->dp != NULL) {
dp = key->dp;
}
else {
dp = wc_ecc_get_curve_params(key->idx);
}
/* right now only support P256/P384 @TODO */
if (dp->id != ECC_SECP256R1 && dp->id != ECC_SECP384R1) {
WOLFSSL_MSG("Only support P256 and P384 verify with CAAM for now");
return CRYPTOCB_UNAVAILABLE;
}
/* check for known predetermined parameters */
ecdsel = GetECDSEL(dp->id);
if (ecdsel == 0) {
WOLFSSL_MSG("Curve parameters not supported");
return CRYPTOCB_UNAVAILABLE;
}
/* Wx,y public key */
keySz = wc_ecc_size(key);
qxLen = qyLen = MAX_ECC_BYTES;
if (wc_ecc_export_public_raw(key, qx, &qxLen, qy, &qyLen) != 0) {
WOLFSSL_MSG("Issue exporting public key part");
return -1;
}
XMEMCPY(qxy, qx, qxLen);
XMEMCPY(qxy+qxLen, qy, qyLen);
if (mp_to_unsigned_bin_len(r, rbuf, keySz) != MP_OKAY) {
return MP_TO_E;
}
if (mp_to_unsigned_bin_len(s, sbuf, keySz) != MP_OKAY) {
return MP_TO_E;
}
if ((wc_ptr_t)hash % CAAM_BUFFER_ALIGN) {
/* input not aligned */
tmpIn = (byte*)XMALLOC(hashlen + CAAM_BUFFER_ALIGN, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
alignedIn = tmpIn + (CAAM_BUFFER_ALIGN -
((wc_ptr_t)tmpIn % CAAM_BUFFER_ALIGN));
XMEMCPY(alignedIn, hash, hashlen);
}
else {
alignedIn = (byte*)hash;
}
status = CAAM_ECC_Verify(CAAM, &hndl, qxy, qxLen+qyLen, rbuf,
keySz, sbuf, keySz, alignedIn, hashlen, ecdsel);
if (tmpIn != NULL) {
XFREE(tmpIn, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
*res = 0;
if (status == kStatus_Success) {
*res = 1;
}
return MP_OKAY;
}
/* ECC verify operation using hardware
* returns 0 on success, and sets "res" with verify result (1 for verify ok)
*/
int wc_CAAM_EccVerify(const byte* sig, word32 siglen, const byte* hash,
word32 hashlen, int* res, ecc_key* key, int devId)
{
int ret;
mp_int r, s;
ret = DecodeECC_DSA_Sig(sig, siglen, &r, &s);
if (ret == 0) {
ret = wc_CAAM_EccVerify_ex(&r, &s, hash, hashlen, res, key);
mp_free(&r);
mp_free(&s);
}
(void)devId;
return ret;
}
/* ECDH operation using hardware, can handle black keys
* returns 0 on success
*/
int wc_CAAM_Ecdh(ecc_key* private_key, ecc_key* public_key, byte* out,
word32* outlen, int devId)
{
const ecc_set_type* dp;
int keySz;
word32 ecdsel = 0; /* ecc parameters in hardware */
int enc;
status_t status;
ALIGN16 byte k[MAX_ECC_BYTES + WC_CAAM_MAC_SZ] = {0};
ALIGN16 byte qx[MAX_ECC_BYTES] = {0};
ALIGN16 byte qy[MAX_ECC_BYTES] = {0};
ALIGN16 byte qxy[MAX_ECC_BYTES * 2] = {0};
word32 qxSz, qySz;
caam_handle_t hndl;
/* @TODO running on alternate job rings - performance enhancement */
hndl.jobRing = kCAAM_JobRing0;
if (private_key->dp != NULL) {
dp = private_key->dp;
}
else {
dp = wc_ecc_get_curve_params(private_key->idx);
}
if (dp->id != ECC_SECP256R1 && dp->id != ECC_SECP384R1) {
return CRYPTOCB_UNAVAILABLE;
}
/* check for known predetermined parameters */
ecdsel = GetECDSEL(dp->id);
if (ecdsel == 0) { /* predefined value not known, loading all parameters */
WOLFSSL_MSG("Unsupported curve parameters");
return CRYPTOCB_UNAVAILABLE;
}
keySz = wc_ecc_size(private_key);
if (*outlen < (word32)keySz) {
WOLFSSL_MSG("out buffer is to small");
return BUFFER_E;
}
/* public key */
qxSz = qySz = MAX_ECC_BYTES;
if (wc_ecc_export_public_raw(public_key, qx, &qxSz, qy, &qySz) != 0) {
WOLFSSL_MSG("Issue exporting public key part");
return -1;
}
XMEMCPY(qxy, qx, qxSz);
XMEMCPY(qxy+qxSz, qy, qySz);
/* private key */
if (keySz > MAX_ECC_BYTES) {
return BUFFER_E;
}
enc = 0;
if (private_key->blackKey == CAAM_BLACK_KEY_ECB) {
enc = CAAM_PKHA_ENC_PRI_AESECB;
}
if (private_key->blackKey == CAAM_BLACK_KEY_CCM) {
if (mp_to_unsigned_bin_len(wc_ecc_key_get_priv(private_key), k,
keySz + WC_CAAM_MAC_SZ) != MP_OKAY) {
return MP_TO_E;
}
}
else {
if (mp_to_unsigned_bin_len(wc_ecc_key_get_priv(private_key), k, keySz)
!= MP_OKAY) {
return MP_TO_E;
}
}
if (*outlen < (word32)keySz) {
return -1;
}
status = CAAM_ECC_ECDH(CAAM, &hndl, k, keySz, qxy, keySz*2, out, keySz,
ecdsel, enc);
if (status == kStatus_Success) {
*outlen = keySz;
return MP_OKAY;
}
else {
return -1;
}
}
#ifdef WOLFSSL_KEY_GEN
/* creates a [ private black key ] [ x , y ]
* returns 0 on success
*/
int wc_CAAM_MakeEccKey(WC_RNG* rng, int keySize, ecc_key* key, int curveId,
int devId)
{
int ret = 0;
ALIGN16 byte xy[MAX_ECC_BYTES * 2];
ALIGN16 byte k[MAX_ECC_BYTES];
word32 kSz = MAX_ECC_BYTES;
word32 xySz = MAX_ECC_BYTES * 2;
word32 ecdsel;
word32 enc;
status_t status;
caam_handle_t hndl;
XMEMSET(xy, 0, MAX_ECC_BYTES * 2);
XMEMSET(k, 0, MAX_ECC_BYTES);
/* @TODO running on alternate job rings - performance enhancement */
hndl.jobRing = kCAAM_JobRing0;
key->type = ECC_PRIVATEKEY;
/* if set to default curve then assume SECP256R1 */
if (keySize == 32 && curveId == ECC_CURVE_DEF) curveId = ECC_SECP256R1;
if (keySize == 48 && curveId == ECC_CURVE_DEF) curveId = ECC_SECP384R1;
if (curveId != ECC_SECP256R1 && curveId != ECC_SECP384R1) {
/* currently only implemented P256/P384 support */
return CRYPTOCB_UNAVAILABLE;
}
ecdsel = GetECDSEL(curveId);
if (ecdsel == 0) {
WOLFSSL_MSG("unknown key type or size");
return CRYPTOCB_UNAVAILABLE;
}
if (key->blackKey == CAAM_BLACK_KEY_ECB) {
enc = CAAM_PKHA_ENC_PRI_AESECB;
}
if (key->blackKey == 0) {
#ifdef WOLFSSL_CAAM_NO_BLACK_KEY
enc = 0;
#else
key->blackKey = CAAM_BLACK_KEY_ECB;
enc = CAAM_PKHA_ENC_PRI_AESECB;
#endif
}
status = CAAM_ECC_Keygen(CAAM, &hndl, k, &kSz, xy, &xySz, ecdsel,
enc);
if (status != kStatus_Success) {
ret = -1;
}
if (ret == 0 &&
wc_ecc_import_unsigned(key, xy, xy + keySize, k, curveId) != 0) {
WOLFSSL_MSG("issue importing key");
ret = -1;
}
return ret;
}
#endif /* WOLFSSL_KEY_GEN */
#endif /* HAVE_ECC */
/* Do a synchronous operations and block till done
* returns 0 on success */
int SynchronousSendRequest(int type, unsigned int args[4], CAAM_BUFFER *buf,
int sz)
{
int ret = 0;
caam_handle_t hndl;
hndl.jobRing = kCAAM_JobRing0;
switch (type) {
case CAAM_ENTROPY:
if (CAAM_RNG_GetRandomData(CAAM, &hndl, kCAAM_RngStateHandle0,
(uint8_t *)buf[0].TheAddress, buf[0].Length,
kCAAM_RngDataAny, NULL) != kStatus_Success) {
ret = WC_HW_E;
}
break;
#ifndef NO_AES_CBC
case CAAM_AESCBC:
ret = DoAesCBC(args, buf, sz);
break;
#endif
#ifdef WOLFSSL_AES_COUNTER
case CAAM_AESCTR:
ret = DoAesCTR(args, buf, sz);
break;
#endif
#ifdef CAAM_BLOB_EXPANSION
case CAAM_BLOB_ENCAP:
if (CAAM_Blob(CAAM, &hndl, (byte*)buf[1].TheAddress,
buf[1].Length, (byte*)buf[2].TheAddress,
buf[2].Length, (byte*)buf[0].TheAddress,
buf[0].Length, CAAM_ENCAP_BLOB,
(args[0] == 0)? CAAM_RED_BLOB : CAAM_BLACK_BLOB)
!= kStatus_Success) {
ret = WC_HW_E;
}
break;
case CAAM_BLOB_DECAP:
if (CAAM_Blob(CAAM, &hndl, (byte*)buf[1].TheAddress, buf[1].Length,
(byte*)buf[2].TheAddress, buf[2].Length,
(byte*)buf[0].TheAddress, buf[0].Length,
CAAM_DECAP_BLOB,
(args[0] == 0)? CAAM_RED_BLOB : CAAM_BLACK_BLOB)
!= kStatus_Success) {
ret = WC_HW_E;
}
break;
#endif
default:
WOLFSSL_MSG("Unknown/unsupported type");
return -1;
}
if (ret != 0) {
return -1;
}
return Success;
}
#endif /* WOLFSSL_IMXRT1170_CAAM */

View File

@ -0,0 +1,404 @@
/* wolfcaam_hash.c
*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_CAAM) && defined(WOLFSSL_CAAM_HASH) \
&& !defined(WOLFSSL_IMXRT1170_CAAM)
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#if defined(__INTEGRITY) || defined(INTEGRITY)
#include <INTEGRITY.h>
#endif
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
#include <wolfssl/wolfcrypt/port/caam/wolfcaam_hash.h>
#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
#include <stdio.h>
#endif
#ifndef NO_SHA
#include <wolfssl/wolfcrypt/sha.h>
#endif
#if !defined(NO_SHA256) || defined(WOLFSSL_SHA224)
#include <wolfssl/wolfcrypt/sha256.h>
#endif
#if defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)
#include <wolfssl/wolfcrypt/sha512.h>
#endif
#ifndef NO_MD5
#include <wolfssl/wolfcrypt/md5.h>
#endif
#ifndef WC_CAAM_CTXLEN
#define WC_CAAM_CTXLEN 0
#endif
/******************************************************************************
Common Code Between SHA Functions
****************************************************************************/
#ifndef WOLFSSL_HASH_KEEP
static int _ShaUpdate(byte* buffer, word32* buffLen, const byte* ctx,
const byte* data, word32 len, word32 digestSz, word32 type)
{
CAAM_BUFFER buf[2];
word32 arg[4];
int ret;
if (buffer == NULL || ctx == NULL || (data == NULL && len > 0)) {
return BAD_FUNC_ARG;
}
if (len == 0) return 0; /* nothing to do */
/* check for filling out existing buffer */
if (*buffLen > 0) {
word32 add = min(len, WC_CAAM_HASH_BLOCK - *buffLen);
XMEMCPY(&buffer[*buffLen], data, add);
*buffLen += add;
data += add;
len -= add;
if (*buffLen == WC_CAAM_HASH_BLOCK) {
/* Set buffer for context */
buf[idx].BufferType = DataBuffer;
buf[idx].TheAddress = (CAAM_ADDRESS)sha->ctx;
buf[idx].Length = digestSz + WC_CAAM_CTXLEN;
#if defined(__INTEGRITY) || defined(INTEGRITY)
buf[idx].Transferred = 0;
#endif
idx++;
/* data to update with */
buf[idx].BufferType = DataBuffer | LastBuffer;
buf[idx].TheAddress = (CAAM_ADDRESS)sha->buffer;
buf[idx].Length = *buffLen;
#if defined(__INTEGRITY) || defined(INTEGRITY)
buf[idx].Transferred = 0;
#endif
idx++;
arg[0] = CAAM_ALG_UPDATE;
arg[1] = digestSz + WC_CAAM_CTXLEN;
if ((ret = wc_caamAddAndWait(buf, idx, arg, type)) != 0) {
WOLFSSL_MSG("Error with CAAM SHA update");
return ret;
}
*buffLen = 0; /* cleared out buffer */
}
}
/* check if multiple full blocks can be done */
if (len >= WC_CAAM_HASH_BLOCK) {
word32 sz = len / WC_CAAM_HASH_BLOCK;
sz = sz * WC_CAAM_HASH_BLOCK;
idx = 0;
/* Set buffer for context */
buf[idx].BufferType = DataBuffer;
buf[idx].TheAddress = (CAAM_ADDRESS)sha->ctx;
buf[idx].Length = digestSz + WC_CAAM_CTXLEN;
#if defined(__INTEGRITY) || defined(INTEGRITY)
buf[idx].Transferred = 0;
#endif
idx++;
/* data to update with */
buf[idx].BufferType = DataBuffer | LastBuffer;
buf[idx].TheAddress = (CAAM_ADDRESS)data;
buf[idx].Length = sz;
#if defined(__INTEGRITY) || defined(INTEGRITY)
buf[idx].Transferred = 0;
#endif
idx++;
arg[0] = CAAM_ALG_UPDATE;
arg[1] = digestSz + WC_CAAM_CTXLEN;
if ((ret = wc_caamAddAndWait(buf, idx, arg, type)) != 0) {
WOLFSSL_MSG("Error with CAAM SHA update");
return ret;
}
len -= sz;
data += sz;
}
/* check for left overs */
if (len > 0) {
word32 add = min(len, WC_CAAM_HASH_BLOCK - *buffLen);
XMEMCPY(&buffer[*buffLen], data, add);
*buffLen += add;
}
return 0;
}
#endif /* !WOLFSSL_HASH_KEEP */
static int _ShaFinal(byte* ctx, word32 ctxSz, byte* in, word32 inSz, byte* out,
word32 type)
{
CAAM_BUFFER buf[2];
word32 arg[4];
int ret, idx = 0;
if (ctx == NULL || out == NULL) {
return BAD_FUNC_ARG;
}
/* Set buffer for context */
buf[idx].BufferType = DataBuffer;
buf[idx].TheAddress = (CAAM_ADDRESS)ctx;
buf[idx].Length = ctxSz;
#if defined(__INTEGRITY) || defined(INTEGRITY)
buf[idx].Transferred = 0;
#endif
idx++;
/* add any potential left overs */
buf[idx].BufferType = DataBuffer | LastBuffer;
buf[idx].TheAddress = (CAAM_ADDRESS)in;
buf[idx].Length = inSz;
#if defined(__INTEGRITY) || defined(INTEGRITY)
buf[idx].Transferred = 0;
#endif
idx++;
arg[0] = CAAM_ALG_FINAL;
arg[1] = ctxSz + WC_CAAM_CTXLEN;
if ((ret = wc_caamAddAndWait(buf, idx, arg, type)) != 0) {
WOLFSSL_MSG("Error with CAAM SHA Final");
return ret;
}
XMEMCPY(out, ctx, ctxSz);
return 0;
}
/******************************************************************************
SHA 1
****************************************************************************/
#if !defined(NO_SHA)
int wc_CAAM_ShaHash(wc_Sha* sha, const byte* in, word32 inSz, byte* digest)
{
int ret = 0;
/* in the case of update's just store up all data */
if (in != NULL) {
#ifdef WOLFSSL_HASH_KEEP
ret = _wc_Hash_Grow(&(sha->msg), &(sha->used), &(sha->len), in,
inSz, sha->heap);
#else
ret = _ShaUpdate((byte*)sha->buffer, &sha->buffLen, (byte*)sha->digest,
in, inSz, SHA_DIGEST_SIZE, CAAM_SHA);
#endif
}
if (digest != NULL) {
#ifdef WOLFSSL_HASH_KEEP
int devId = sha->devId;
void* heap = sha->heap;
ret = _ShaFinal((byte*)sha->digest, SHA_DIGEST_SIZE, sha->msg,
sha->used, digest, CAAM_SHA);
wc_ShaFree(sha);
wc_InitSha_ex(sha, heap, devId);
#else
ret = _ShaFinal((byte*)sha->digest, SHA_DIGEST_SIZE,
(byte*)sha->buffer, sha->buffLen, digest, CAAM_SHA);
#endif
}
return ret;
}
#endif /* !NO_SHA */
/******************************************************************************
SHA 224
****************************************************************************/
#ifdef WOLFSSL_SHA224
int wc_CAAM_Sha224Hash(wc_Sha224* sha224, const byte* in, word32 inSz,
byte* digest)
{
int ret = 0;
/* in the case of update's just store up all data */
if (in != NULL) {
#ifdef WOLFSSL_HASH_KEEP
ret = wc_Sha224_Grow(sha224, in, inSz);
#else
ret = _ShaUpdate(sha224->buffer, &sha224->bufferLen,
(byte*)sha224->digest, data, len, SHA224_DIGEST_SIZE, CAAM_SHA224);
#endif
}
if (digest != NULL) {
#ifdef WOLFSSL_HASH_KEEP
int devId = sha224->devId;
void* heap = sha224->heap;
ret = _ShaFinal((byte*)sha224->digest, SHA224_DIGEST_SIZE, sha224->msg,
sha224->used, digest, CAAM_SHA224);
wc_Sha224Free(sha224);
wc_InitSha224_ex(sha224, heap, devId);
#else
ret = _ShaFinal((byte*)sha224->digest, SHA224_DIGEST_SIZE,
(byte*)sha224->buffer, sha224->bufferLen, digest, CAAM_SHA224);
#endif
}
return ret;
}
#endif /* WOLFSSL_SHA224 */
/******************************************************************************
SHA 256
****************************************************************************/
#if !defined(NO_SHA256)
int wc_CAAM_Sha256Hash(wc_Sha256* sha256, const byte* in, word32 inSz,
byte* digest)
{
int ret = 0;
/* in the case of update's just store up all data */
if (in != NULL) {
#ifdef WOLFSSL_HASH_KEEP
ret = wc_Sha256_Grow(sha256, in, inSz);
#else
ret = _ShaUpdate((byte*)sha256->buffer, &sha256->buffLen,
(byte*)sha256->digest, in, inSz, SHA256_DIGEST_SIZE, CAAM_SHA256);
#endif
}
if (digest != NULL) {
#ifdef WOLFSSL_HASH_KEEP
int devId = sha256->devId;
void* heap = sha256->heap;
ret = _ShaFinal((byte*)sha256->digest, SHA256_DIGEST_SIZE, sha256->msg,
sha256->used, digest, CAAM_SHA256);
wc_Sha256Free(sha256);
wc_InitSha256_ex(sha256, heap, devId);
#else
ret = _ShaFinal((byte*)sha256->digest, SHA256_DIGEST_SIZE,
(byte*)sha256->buffer, sha256->buffLen, digest, CAAM_SHA256);
#endif
}
return ret;
}
#endif /* !NO_SHA256 */
/******************************************************************************
SHA 384
****************************************************************************/
#ifdef WOLFSSL_SHA384
int wc_CAAM_Sha384Hash(wc_Sha384* sha384, const byte* in, word32 inSz,
byte* digest)
{
int ret = 0;
/* in the case of update's just store up all data */
if (in != NULL) {
#ifdef WOLFSSL_HASH_KEEP
ret = wc_Sha384_Grow(sha384, in, inSz);
#else
ret = _ShaUpdate((byte*)sha384->buffer, &sha384->buffLen,
(byte*)sha384->digest, in, inSz, SHA384_DIGEST_SIZE, CAAM_SHA384);
#endif
}
if (digest != NULL) {
#ifdef WOLFSSL_HASH_KEEP
int devId = sha384->devId;
void* heap = sha384->heap;
ret = _ShaFinal((byte*)sha384->digest, SHA384_DIGEST_SIZE, sha384->msg,
sha384->used, digest, CAAM_SHA384);
wc_Sha384Free(sha384);
wc_InitSha384_ex(sha384, heap, devId);
#else
ret = _ShaFinal((byte*)sha384->digest, SHA384_DIGEST_SIZE,
(byte*)sha384->buffer, sha384->buffLen, digest, CAAM_SHA384);
#endif
}
return ret;
}
#endif /* WOLFSSL_SHA384 */
/******************************************************************************
SHA 512
****************************************************************************/
#ifdef WOLFSSL_SHA512
int wc_CAAM_Sha512Hash(wc_Sha512* sha512, const byte* in, word32 inSz,
byte* digest)
{
int ret = 0;
/* in the case of update's just store up all data */
if (in != NULL) {
#ifdef WOLFSSL_HASH_KEEP
ret = wc_Sha512_Grow(sha512, in, inSz);
#else
ret = _ShaUpdate((byte*)sha512->buffer, &sha512->buffLen,
(byte*)sha512->digest, in, inSz, SHA512_DIGEST_SIZE, CAAM_SHA512);
#endif
}
if (digest != NULL) {
#ifdef WOLFSSL_HASH_KEEP
int devId = sha512->devId;
void* heap = sha512->heap;
ret = _ShaFinal((byte*)sha512->digest, SHA512_DIGEST_SIZE, sha512->msg,
sha512->used, digest, CAAM_SHA512);
wc_Sha512Free(sha512);
wc_InitSha512_ex(sha512, heap, devId);
#else
ret = _ShaFinal((byte*)sha512->digest, SHA512_DIGEST_SIZE,
(byte*)sha512->buffer, sha512->buffLen, digest, CAAM_SHA512);
#endif
}
return ret;
}
#endif /* WOLFSSL_SHA512 */
#endif /* WOLFSSL_CAAM && WOLFSSL_CAAM_HASH */

View File

@ -0,0 +1,100 @@
/* wolfcaam_hmac.c
*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_CAAM) && !defined(NO_HMAC) && defined(WOLFSSL_CAAM_HMAC)
#include <wolfssl/wolfcrypt/logging.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
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
#include <wolfssl/wolfcrypt/coding.h>
#include <wolfssl/wolfcrypt/asn.h>
#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
#include <stdio.h>
#endif
#if defined(WOLFSSL_DEVCRYPTO_HMAC)
#include <wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h>
/* HSM lib does not support HMAC with QXP board, use devcrypto instead */
int wc_CAAM_Hmac(Hmac* hmac, int macType, const byte* msg, int msgSz,
byte* digest)
{
int ret = 0;
if (hmac->ctx.cfd == -1 && hmac->keyLen > 0) {
ret = wc_DevCrypto_HmacSetKey(hmac, macType, hmac->keyRaw,
hmac->keyLen);
if (ret != 0) {
WOLFSSL_MSG("Error with set key");
if (ret == WC_NO_ERR_TRACE(HASH_TYPE_E)) {
ret = CRYPTOCB_UNAVAILABLE; /* that hash type is not supported*/
}
}
}
if (ret == 0 && msgSz > 0) {
ret = wc_DevCrypto_HmacUpdate(hmac, msg, msgSz);
if (ret != 0) {
WOLFSSL_MSG("Issue with hmac update");
}
}
if (ret == 0 && digest != NULL) {
ret = wc_DevCrypto_HmacFinal(hmac, digest);
if (ret != 0) {
WOLFSSL_MSG("Issue with hmac final");
}
else {
wc_DevCrypto_HmacFree(hmac);
}
}
return ret;
}
#else
int wc_CAAM_Hmac(Hmac* hmac, int macType, const byte* msg, int msgSz,
byte* digest)
{
(void)hmac;
(void)macType;
(void)msg;
(void)msgSz;
(void)digest;
return CRYPTOCB_UNAVAILABLE;
}
#endif /* WOLFSSL_DEVCRYPTO_HMAC */
#endif

View File

@ -0,0 +1,838 @@
/*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
/*
* WOLFSSL_CAAM is used to enable CAAM support
*
* Different Hardware Ports
* WOLFSSL_IMX6_CAAM build for QNX + IMX6
* WOLFSSL_SECO_CAAM make use of NXP's SECO HSM library on i.MX8
* WOLFSSL_IMXRT1170_CAAM make use of NXP's CAAM driver for RT1170 series boards
*
*/
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_CAAM)
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
#ifdef DEBUG_WOLFSSL
#include <stdio.h>
#endif
/* determine which porting header to include */
#if defined(__INTEGRITY) || defined(INTEGRITY)
#ifndef WC_CAAM_PASSWORD
#define WC_CAAM_PASSWORD "!systempassword"
#endif
#include <INTEGRITY.h>
static IODevice caam = NULLIODevice;
#define CAAM_SEND_REQUEST(type, sz, arg, buf) \
SynchronousSendIORequest(caam, (type), (const Value*)(arg), (buf))
#endif
#if defined(__INTEGRITY) || defined(INTEGRITY)
/* Allow runtime setting for CAAM IODevice in case user wants to use password
* at run time.
*
* returns 0 on success
*
* NOTE this is how IODevice is defined in INTEGRITY "typedef struct
* IODeviceStruct *IODevice;"
*/
int wc_caamSetResource(IODevice ioDev)
{
WOLFSSL_MSG("Setting CAAM driver");
caam = ioDev;
return 0;
}
#endif
/* used to route crypto operations through crypto callback */
static int wc_CAAM_router(int devId, wc_CryptoInfo* info, void* ctx)
{
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
(void)ctx;
(void)devId;
switch (info->algo_type) {
case WC_ALGO_TYPE_PK:
switch (info->pk.type) {
#if defined(HAVE_ECC) && defined(WOLFSSL_CAAM_ECC)
case WC_PK_TYPE_ECDSA_SIGN:
ret = wc_CAAM_EccSign(info->pk.eccsign.in,
info->pk.eccsign.inlen, info->pk.eccsign.out,
info->pk.eccsign.outlen, info->pk.eccsign.rng,
info->pk.eccsign.key, devId);
break;
case WC_PK_TYPE_ECDSA_VERIFY:
ret = wc_CAAM_EccVerify(info->pk.eccverify.sig,
info->pk.eccverify.siglen, info->pk.eccverify.hash,
info->pk.eccverify.hashlen, info->pk.eccverify.res,
info->pk.eccverify.key, devId);
break;
#ifdef WOLFSSL_KEY_GEN
case WC_PK_TYPE_EC_KEYGEN:
ret = wc_CAAM_MakeEccKey(info->pk.eckg.rng,
info->pk.eckg.size, info->pk.eckg.key,
info->pk.eckg.curveId, devId);
break;
#endif /* WOLFSSL_KEY_GEN */
case WC_PK_TYPE_ECDH:
ret = wc_CAAM_Ecdh(info->pk.ecdh.private_key,
info->pk.ecdh.public_key,
info->pk.ecdh.out,
info->pk.ecdh.outlen, devId);
break;
case WC_PK_TYPE_EC_CHECK_PRIV_KEY:
ret = wc_CAAM_EccCheckPrivKey(info->pk.ecc_check.key,
info->pk.ecc_check.pubKey,
info->pk.ecc_check.pubKeySz);
break;
#endif /* HAVE_ECC && WOLFSSL_CAAM_ECC */
#if !defined(NO_RSA) && defined(WOLFSSL_DEVCRYPTO_RSA)
case WC_PK_TYPE_RSA:
ret = wc_CAAM_Rsa(info->pk.rsa.in,
info->pk.rsa.inLen,
info->pk.rsa.out,
info->pk.rsa.outLen,
info->pk.rsa.type,
info->pk.rsa.key,
info->pk.rsa.rng);
break;
#ifdef WOLFSSL_KEY_GEN
case WC_PK_TYPE_RSA_KEYGEN:
ret = wc_CAAM_MakeRsaKey(info->pk.rsakg.key,
info->pk.rsakg.size,
info->pk.rsakg.e,
info->pk.rsakg.rng);
break;
#endif
#endif /* !NO_RSA */
#if defined(HAVE_CURVE25519) && defined(WOLFSSL_CAAM_CURVE25519)
case WC_PK_TYPE_CURVE25519_KEYGEN:
ret = wc_CAAM_MakeCurve25519Key(info->pk.curve25519kg.key,
info->pk.curve25519kg.size,
info->pk.curve25519kg.rng);
break;
case WC_PK_TYPE_CURVE25519:
ret = wc_CAAM_Curve25519(info->pk.curve25519.out,
info->pk.curve25519.outlen,
info->pk.curve25519.private_key,
info->pk.curve25519.public_key,
info->pk.curve25519.endian);
break;
#endif /* HAVE_CURVE25519 && WOLFSSL_CAAM_CURVE25519 */
default:
WOLFSSL_MSG("unsupported public key operation");
}
break;
case WC_ALGO_TYPE_CMAC:
#if defined(WOLFSSL_CMAC) && defined(WOLFSSL_CAAM_CMAC)
#ifdef WOLFSSL_SECO_CAAM
if (devId != WOLFSSL_SECO_DEVID)
break;
#endif
#if defined(WOLFSSL_CMAC) && !defined(NO_AES) && \
defined(WOLFSSL_AES_DIRECT)
ret = wc_CAAM_Cmac(info->cmac.cmac,
info->cmac.key,
info->cmac.keySz,
info->cmac.in,
info->cmac.inSz,
info->cmac.out,
info->cmac.outSz,
info->cmac.type,
info->cmac.ctx);
#else
WOLFSSL_MSG("CMAC not compiled in");
ret = NOT_COMPILED_IN;
#endif
#endif /* WOLFSSL_CMAC && WOLFSSL_CAAM_CMAC */
break;
case WC_ALGO_TYPE_HASH:
#ifdef WOLFSSL_CAAM_HASH
switch(info->hash.type) {
#ifdef WOLFSSL_SHA224
case WC_HASH_TYPE_SHA224:
ret = wc_CAAM_Sha224Hash(info->hash.sha224,
info->hash.in,
info->hash.inSz,
info->hash.digest);
break;
#endif
case WC_HASH_TYPE_SHA256:
ret = wc_CAAM_Sha256Hash(info->hash.sha256,
info->hash.in,
info->hash.inSz,
info->hash.digest);
break;
#ifdef WOLFSSL_SHA384
case WC_HASH_TYPE_SHA384:
ret = wc_CAAM_Sha384Hash(info->hash.sha384,
info->hash.in,
info->hash.inSz,
info->hash.digest);
break;
#endif
#ifdef WOLFSSL_SHA512
case WC_HASH_TYPE_SHA512:
ret = wc_CAAM_Sha512Hash(info->hash.sha512,
info->hash.in,
info->hash.inSz,
info->hash.digest);
break;
#endif
default:
WOLFSSL_MSG("Unknown or unsupported hash type");
ret = CRYPTOCB_UNAVAILABLE;
}
#endif /* WOLFSSL_CAAM_HASH */
break;
case WC_ALGO_TYPE_HMAC:
#if defined(WOLFSSL_CAAM_HMAC)
ret = wc_CAAM_Hmac(info->hmac.hmac,
info->hmac.macType,
info->hmac.in, info->hmac.inSz,
info->hmac.digest);
#endif
break;
case WC_ALGO_TYPE_CIPHER:
#if defined(WOLFSSL_CAAM_CIPHER)
#ifdef WOLFSSL_SECO_CAAM
if (devId != WOLFSSL_SECO_DEVID)
break; /* only call to SECO if using WOLFSSL_SECO_DEVID */
#endif
switch (info->cipher.type) {
#if defined(HAVE_AESCCM) && defined(WOLFSSL_CAAM_AESCCM)
case WC_CIPHER_AES_CCM:
if (info->cipher.enc == 1) {
ret = wc_CAAM_AesCcmEncrypt(
info->cipher.aesccm_enc.aes,
info->cipher.aesccm_enc.in,
info->cipher.aesccm_enc.out,
info->cipher.aesccm_enc.sz,
info->cipher.aesccm_enc.nonce,
info->cipher.aesccm_enc.nonceSz,
info->cipher.aesccm_enc.authTag,
info->cipher.aesccm_enc.authTagSz,
info->cipher.aesccm_enc.authIn,
info->cipher.aesccm_enc.authInSz);
}
else {
ret = wc_CAAM_AesCcmDecrypt(
info->cipher.aesccm_dec.aes,
info->cipher.aesccm_dec.in,
info->cipher.aesccm_dec.out,
info->cipher.aesccm_dec.sz,
info->cipher.aesccm_dec.nonce,
info->cipher.aesccm_dec.nonceSz,
info->cipher.aesccm_dec.authTag,
info->cipher.aesccm_dec.authTagSz,
info->cipher.aesccm_dec.authIn,
info->cipher.aesccm_dec.authInSz);
}
break;
#endif /* HAVE_AESCCM */
#if defined(HAVE_AESGCM) && defined(WOLFSSL_CAAM_AESGCM)
case WC_CIPHER_AES_GCM:
if (info->cipher.enc == 1) {
ret = wc_CAAM_AesGcmEncrypt(
info->cipher.aesgcm_enc.aes,
info->cipher.aesgcm_enc.in,
info->cipher.aesgcm_enc.out,
info->cipher.aesgcm_enc.sz,
info->cipher.aesgcm_enc.iv,
info->cipher.aesgcm_enc.ivSz,
info->cipher.aesgcm_enc.authTag,
info->cipher.aesgcm_enc.authTagSz,
info->cipher.aesgcm_enc.authIn,
info->cipher.aesgcm_enc.authInSz);
}
else {
ret = wc_CAAM_AesGcmDecrypt(
info->cipher.aesgcm_dec.aes,
info->cipher.aesgcm_dec.in,
info->cipher.aesgcm_dec.out,
info->cipher.aesgcm_dec.sz,
info->cipher.aesgcm_dec.iv,
info->cipher.aesgcm_dec.ivSz,
info->cipher.aesgcm_dec.authTag,
info->cipher.aesgcm_dec.authTagSz,
info->cipher.aesgcm_dec.authIn,
info->cipher.aesgcm_dec.authInSz);
}
break;
#endif /* HAVE_AESGCM && WOLFSSL_CAAM_AESGCM */
case WC_CIPHER_AES_CBC:
if (info->cipher.enc == 1) {
ret = wc_CAAM_AesCbcEncrypt(info->cipher.aescbc.aes,
info->cipher.aescbc.out,
info->cipher.aescbc.in,
info->cipher.aescbc.sz);
}
else {
ret = wc_CAAM_AesCbcDecrypt(info->cipher.aescbc.aes,
info->cipher.aescbc.out,
info->cipher.aescbc.in,
info->cipher.aescbc.sz);
}
break;
#ifdef WOLFSSL_AES_COUNTER
case WC_CIPHER_AES_CTR:
ret = wc_CAAM_AesCtrEncrypt(info->cipher.aesctr.aes,
info->cipher.aesctr.out,
info->cipher.aesctr.in,
info->cipher.aesctr.sz);
break;
#endif /* WOLFSSL_AES_COUNTER */
#if defined(HAVE_AES_ECB)
case WC_CIPHER_AES_ECB:
if (info->cipher.enc == 1) {
ret = wc_CAAM_AesEcbEncrypt(info->cipher.aesecb.aes,
info->cipher.aesecb.out,
info->cipher.aesecb.in,
info->cipher.aesecb.sz);
}
else {
ret = wc_CAAM_AesEcbDecrypt(info->cipher.aesecb.aes,
info->cipher.aesecb.out,
info->cipher.aesecb.in,
info->cipher.aesecb.sz);
}
#endif /* HAVE_AES_ECB */
}
#endif /* WOLFSSL_CAAM_CIPHER */
break;
case WC_ALGO_TYPE_RNG:
case WC_ALGO_TYPE_SEED:
case WC_ALGO_TYPE_NONE:
default:
/* Not implemented yet with CAAM */
ret = CRYPTOCB_UNAVAILABLE;
}
return ret;
}
/* Check hardware support
*
* returns 0 on success
*/
int wc_caamInit(void)
{
int ret = 0;
WOLFSSL_MSG("Starting interface with CAAM driver");
if (CAAM_INIT_INTERFACE() != 0) {
WOLFSSL_MSG("Error initializing CAAM");
return -1;
}
#if 0
/* check that for implemented modules
* bits 0-3 AES, 4-7 DES, 12-15 Hashing , 16-19 RNG, 28-31 public key module */
reg = WC_CAAM_READ(CAMM_SUPPORT_LS);
#ifndef WC_NO_RNG
if (((reg & 0x000F0000) >> 16) > 0) {
WOLFSSL_MSG("Found CAAM RNG hardware module");
if ((WC_CAAM_READ(CAAM_RTMCTL) & 0x40000001) != 0x40000001) {
WOLFSSL_MSG("Error CAAM RNG has not been set up");
}
}
#endif
#ifndef NO_SHA256
if ((reg & 0x0000F000) > 0) {
WOLFSSL_MSG("Found CAAM MDHA module");
}
else {
WOLFSSL_MSG("Hashing not supported by CAAM");
return WC_HW_E;
}
#endif
#ifndef NO_AES
if ((reg & 0x0000000F) > 0) {
WOLFSSL_MSG("Found CAAM AES module");
}
else {
WOLFSSL_MSG("AES not supported by CAAM");
return WC_HW_E;
}
#endif
#ifdef HAVE_ECC
if ((reg & 0xF0000000) > 0) {
WOLFSSL_MSG("Found CAAM Public Key module");
}
else {
WOLFSSL_MSG("Public Key not supported by CAAM");
}
#endif
#endif
#ifdef WOLFSSL_SECO_CAAM
ret = wc_CryptoDev_RegisterDevice(WOLFSSL_SECO_DEVID, wc_CAAM_router,
NULL);
#endif
if (ret == 0) {
ret = wc_CryptoDev_RegisterDevice(WOLFSSL_CAAM_DEVID, wc_CAAM_router,
NULL);
}
return ret;
}
/* free up all resources used for CAAM */
int wc_caamFree(void)
{
CAAM_FREE_INTERFACE();
return 0;
}
#if defined(__INTEGRITY) || defined(INTEGRITY)
word32 wc_caamReadRegister(word32 reg)
{
word32 out = 0;
if (caam == NULLIODevice) {
WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?");
return 0;
}
if (ReadIODeviceRegister(caam, reg, &out) != Success) {
WOLFSSL_MSG("Error reading register");
}
return (word32)out;
}
/* returns 0 on success */
int wc_caamWriteRegister(word32 reg, word32 value)
{
if (caam == NULLIODevice) {
WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?");
return -1;
}
if (WriteIODeviceRegister(caam, reg, value) != Success) {
WOLFSSL_MSG("Error writing to register");
}
return 0;
}
#endif
/* return 0 on success and WC_HW_E on failure. Can also return WC_HW_WAIT_E
* in the case that the driver is waiting for a resource or RAN_BLOCK_E if
* waiting for entropy. */
int wc_caamAddAndWait(CAAM_BUFFER* buf, int sz, word32 arg[4], word32 type)
{
int ret;
#ifdef DEBUG_WOLFSSL
static int wait = 0;
#endif
#if defined(__INTEGRITY) || defined(INTEGRITY)
if (caam == NULLIODevice) {
WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?");
return WC_HW_E;
}
#endif
if ((ret = CAAM_SEND_REQUEST(type, sz, arg, buf)) != Success) {
/* if waiting for resource or RNG return waiting */
if (ret == CAAM_WAITING) {
#ifdef DEBUG_WOLFSSL
if (wait == 0) {
wait = 1;
WOLFSSL_MSG("Waiting on entropy from driver");
}
fprintf(stderr, ".");
#endif
return RAN_BLOCK_E;
}
if (ret == ResourceNotAvailable) {
WOLFSSL_MSG("Waiting on CAAM driver");
return WC_HW_WAIT_E;
}
return WC_HW_E;
}
#ifdef DEBUG_WOLFSSL
if (wait) {
wait = 0;
fprintf(stderr, "\n");
}
#endif
(void)ret;
return 0;
}
#ifdef WOLFSSL_CAAM_BLOB
/* Create a red or black blob
*
* mod : key modifier, expected 8 bytes for RED key types and 16 for BLACK
* if 'mod' is null than 0's are used
*
* returns 0 on success
*/
int wc_caamCreateBlob_ex(byte* data, word32 dataSz, byte* out, word32* outSz,
int type, byte* mod, word32 modSz)
{
CAAM_BUFFER in[3];
word32 arg[4];
int ret;
byte local[WC_CAAM_BLACK_KEYMOD_SZ] = {0};
byte* keyMod;
int keyModSz;
keyMod = mod;
XMEMSET(local, 0, sizeof(local));
if (data == NULL || out == NULL || outSz == NULL ||
*outSz < dataSz + WC_CAAM_BLOB_SZ) {
return BAD_FUNC_ARG;
}
if (type == WC_CAAM_BLOB_RED) {
arg[0] = 0;
if (mod != NULL) {
if (modSz != WC_CAAM_RED_KEYMOD_SZ) {
WOLFSSL_MSG("bad key mod red size");
return BAD_FUNC_ARG;
}
}
keyModSz = WC_CAAM_RED_KEYMOD_SZ;
}
else if (type == WC_CAAM_BLOB_BLACK) {
arg[0] = 1;
if (mod != NULL) {
if (modSz != WC_CAAM_BLACK_KEYMOD_SZ) {
WOLFSSL_MSG("bad key mod black size");
return BAD_FUNC_ARG;
}
}
keyModSz = WC_CAAM_BLACK_KEYMOD_SZ;
}
else {
WOLFSSL_MSG("unknown blob type!");
return BAD_FUNC_ARG;
}
if (mod == NULL) {
WOLFSSL_MSG("using local all 0's key modifier");
keyMod = local;
}
in[0].BufferType = DataBuffer;
in[0].TheAddress = (CAAM_ADDRESS)keyMod;
in[0].Length = keyModSz;
in[1].BufferType = DataBuffer;
in[1].TheAddress = (CAAM_ADDRESS)data;
in[1].Length = dataSz;
in[2].BufferType = DataBuffer | LastBuffer;
in[2].TheAddress = (CAAM_ADDRESS)out;
in[2].Length = dataSz + WC_CAAM_BLOB_SZ;
arg[2] = dataSz;
arg[3] = keyModSz;
if ((ret = wc_caamAddAndWait(in, 3, arg, CAAM_BLOB_ENCAP)) != 0) {
WOLFSSL_MSG("Error with CAAM blob create");
return ret;
}
*outSz = dataSz + WC_CAAM_BLOB_SZ;
return 0;
}
/* create a red key blob
* returns 0 on success */
int wc_caamCreateBlob(byte* data, word32 dataSz, byte* out, word32* outSz)
{
return wc_caamCreateBlob_ex(data, dataSz, out, outSz, WC_CAAM_BLOB_RED,
NULL, 0);
}
/* uncover black or red keys
* returns 0 on success */
int wc_caamOpenBlob_ex(byte* data, word32 dataSz, byte* out, word32* outSz,
int type, byte* mod, word32 modSz)
{
CAAM_BUFFER in[3];
word32 arg[4];
int ret;
byte local[WC_CAAM_BLACK_KEYMOD_SZ];
byte* keyMod;
int keyModSz;
keyMod = mod;
XMEMSET(local, 0, sizeof(local));
if (data == NULL || out == NULL || outSz == NULL ||
*outSz < dataSz - WC_CAAM_BLOB_SZ) {
WOLFSSL_MSG("NULL argument or outSz is too small");
return BAD_FUNC_ARG;
}
if (type == WC_CAAM_BLOB_RED) {
arg[0] = 0;
if (mod != NULL) {
if (modSz != WC_CAAM_RED_KEYMOD_SZ) {
WOLFSSL_MSG("bad key mod red size");
return BAD_FUNC_ARG;
}
}
keyModSz = WC_CAAM_RED_KEYMOD_SZ;
}
else if (type == WC_CAAM_BLOB_BLACK) {
arg[0] = 1;
if (mod != NULL) {
if (modSz != WC_CAAM_BLACK_KEYMOD_SZ) {
WOLFSSL_MSG("bad key mod black size");
return BAD_FUNC_ARG;
}
}
keyModSz = WC_CAAM_BLACK_KEYMOD_SZ;
}
else {
WOLFSSL_MSG("unknown blob type!");
return BAD_FUNC_ARG;
}
if (mod == NULL) {
WOLFSSL_MSG("using local all 0's key modifier");
keyMod = local;
}
in[0].BufferType = DataBuffer;
in[0].TheAddress = (CAAM_ADDRESS)keyMod;
in[0].Length = keyModSz;
in[1].BufferType = DataBuffer;
in[1].TheAddress = (CAAM_ADDRESS)data;
in[1].Length = dataSz;
in[2].BufferType = DataBuffer | LastBuffer;
in[2].TheAddress = (CAAM_ADDRESS)out;
in[2].Length = dataSz - WC_CAAM_BLOB_SZ;
arg[2] = dataSz;
arg[3] = keyModSz;
if ((ret = wc_caamAddAndWait(in, 3, arg, CAAM_BLOB_DECAP)) != 0) {
WOLFSSL_MSG("Error with CAAM blob open");
return ret;
}
*outSz = dataSz - WC_CAAM_BLOB_SZ;
return 0;
}
/* open a red blob
* returns 0 on success */
int wc_caamOpenBlob(byte* data, word32 dataSz, byte* out, word32* outSz)
{
return wc_caamOpenBlob_ex(data, dataSz, out, outSz, WC_CAAM_BLOB_RED,
NULL, 0);
}
#endif /* WOLFSSL_CAAM_BLOB */
/* outSz gets set to key size plus 16 for mac and padding
* return 0 on success
*/
int wc_caamCoverKey(byte* in, word32 inSz, byte* out, word32* outSz, int flag)
{
CAAM_BUFFER buf[2];
word32 arg[4];
int ret;
if (*outSz < inSz + WC_CAAM_MAC_SZ) {
return BUFFER_E;
}
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (CAAM_ADDRESS)in;
buf[0].Length = inSz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (CAAM_ADDRESS)out;
buf[1].Length = inSz;
(void)flag; /* for now defaulting to use highest security AES-CCM here */
arg[0] = CAAM_FIFO_CCM_FLAG;
arg[1] = inSz;
if ((ret = wc_caamAddAndWait(buf, 2, arg, CAAM_FIFO_S)) != 0) {
WOLFSSL_MSG("Error with CAAM blob create");
return ret;
}
*outSz = inSz + WC_CAAM_MAC_SZ;
return 0;
}
/* return 0 or greater on success for the partition number available
* returns a negative value on failure
*/
int caamFindUnusedPartition()
{
CAAM_BUFFER buf[1];
word32 arg[4];
int ret = 0;
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (CAAM_ADDRESS)&ret;
buf[0].Length = sizeof(int);
if ((wc_caamAddAndWait(buf, 1, arg, CAAM_FIND_PART)) != 0) {
WOLFSSL_MSG("Error finding a partition to use");
return -1;
}
return ret;
}
/* return the address of the given partition number "part" */
CAAM_ADDRESS caamGetPartition(int part, int sz)
{
CAAM_BUFFER buf[1];
word32 arg[4];
CAAM_ADDRESS ret = 0;
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (CAAM_ADDRESS)(&ret);
buf[0].Length = sizeof(int);
arg[0] = part;
arg[1] = sz;
if ((wc_caamAddAndWait(buf, 1, arg, CAAM_GET_PART)) != 0) {
WOLFSSL_MSG("Error getting a partition");
return -1;
}
return ret;
}
/* Internal function to free a secure partition
* return 0 on success */
int caamFreePart(int partNum)
{
word32 arg[4];
arg[0] = partNum;
if ((wc_caamAddAndWait(NULL, 0, arg, CAAM_FREE_PART)) != 0) {
WOLFSSL_MSG("Error freeing a partition");
return -1;
}
return 0;
}
/* Internal function to help write to a secure partition
* return 0 on success */
int caamWriteToPartition(CAAM_ADDRESS addr, const unsigned char* in, int inSz)
{
CAAM_BUFFER buf[1];
word32 arg[4];
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (CAAM_ADDRESS)in;
buf[0].Length = inSz;
arg[0] = addr;
arg[1] = inSz;
if ((wc_caamAddAndWait(buf, 1, arg, CAAM_WRITE_PART)) != 0) {
WOLFSSL_MSG("Error writing to a partition");
return -1;
}
return 0;
}
/* Internal function to help read from a secure partition
* return 0 on success */
int caamReadPartition(CAAM_ADDRESS addr, unsigned char* out, int outSz)
{
CAAM_BUFFER buf[1];
word32 arg[4];
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (CAAM_ADDRESS)out;
buf[0].Length = outSz;
arg[0] = addr;
arg[1] = outSz;
if ((wc_caamAddAndWait(buf, 1, arg, CAAM_READ_PART)) != 0) {
WOLFSSL_MSG("Error reading a partition");
return -1;
}
return 0;
}
#endif /* WOLFSSL_CAAM */

View File

@ -0,0 +1,469 @@
/* wolfcaam_qnx.c
*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_QNX_CAAM) && (defined(__QNX__) || defined(__QNXNTO__))
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <devctl.h>
#include <errno.h>
/* for devctl use */
int caamFd = -1;
static wolfSSL_Mutex caamMutex;
/* return 0 on success */
int wc_CAAMInitInterface()
{
if (wc_InitMutex(&caamMutex) != 0) {
WOLFSSL_MSG("Could not init mutex");
return -1;
}
caamFd = open("/dev/wolfCrypt", O_RDWR);
if (caamFd < 0) {
WOLFSSL_MSG("Could not open /dev/wolfCrypt");
return -1;
}
return 0;
}
void wc_CAAMFreeInterface()
{
wc_FreeMutex(&caamMutex);
if (caamFd >= 0)
close(caamFd);
}
#define WC_TRNG_CMD __DIOTF(_DCMD_ALL, CAAM_ENTROPY, iov_t)
#define WC_CAAM_GET_PART __DIOTF(_DCMD_ALL, CAAM_GET_PART, iov_t)
#define WC_CAAM_FREE_PART __DIOT(_DCMD_ALL, CAAM_FREE_PART, iov_t)
#define WC_CAAM_FIND_PART __DIOTF(_DCMD_ALL, CAAM_FIND_PART, iov_t)
#define WC_CAAM_READ_PART __DIOTF(_DCMD_ALL, CAAM_READ_PART, iov_t)
#define WC_CAAM_WRITE_PART __DIOT(_DCMD_ALL, CAAM_WRITE_PART, iov_t)
#define WC_CAAM_ECDSA_KEYPAIR __DIOTF(_DCMD_ALL, CAAM_ECDSA_KEYPAIR, iov_t)
#define WC_CAAM_ECDSA_VERIFY __DIOT(_DCMD_ALL, CAAM_ECDSA_VERIFY, iov_t)
#define WC_CAAM_ECDSA_SIGN __DIOTF(_DCMD_ALL, CAAM_ECDSA_SIGN, iov_t)
#define WC_CAAM_ECDSA_ECDH __DIOTF(_DCMD_ALL, CAAM_ECDSA_ECDH, iov_t)
#define WC_CAAM_BLOB_ENCAP __DIOTF(_DCMD_ALL, CAAM_BLOB_ENCAP, iov_t)
#define WC_CAAM_BLOB_DECAP __DIOTF(_DCMD_ALL, CAAM_BLOB_DECAP, iov_t)
#define WC_CAAM_CMAC __DIOTF(_DCMD_ALL, CAAM_CMAC, iov_t)
#define WC_CAAM_AESECB __DIOTF(_DCMD_ALL, CAAM_AESECB, iov_t)
#define WC_CAAM_AESCTR __DIOTF(_DCMD_ALL, CAAM_AESCTR, iov_t)
#define WC_CAAM_AESCBC __DIOTF(_DCMD_ALL, CAAM_AESCBC, iov_t)
#define WC_CAAM_AESCCM __DIOTF(_DCMD_ALL, CAAM_AESCCM, iov_t)
#define WC_CAAM_AESGCM __DIOTF(_DCMD_ALL, CAAM_AESGCM, iov_t)
#define WC_CAAM_FIFO_S __DIOTF(_DCMD_ALL, CAAM_FIFO_S, iov_t)
#define MAX_IN_IOVS 6
#define MAX_OUT_IOVS 3
/* Do a synchronous operations and block till done
* returns 0 on success */
int SynchronousSendRequest(int type, unsigned int args[4], CAAM_BUFFER *buf,
int sz)
{
int ret, inIdx = 0, outIdx = 0;
int cmd = 0;
iov_t in[MAX_IN_IOVS], out[MAX_OUT_IOVS];
CAAM_ADDRESS privkey;
if (args != NULL) {
SETIOV(&in[inIdx], args, sizeof(unsigned int) * 4);
inIdx = inIdx + 1;
}
else {
unsigned int localArgs[4] = {0};
SETIOV(&in[inIdx], localArgs, sizeof(unsigned int) * 4);
inIdx = inIdx + 1;
}
switch (type) {
case CAAM_ENTROPY:
SETIOV(&out[outIdx], (buf->TheAddress), (buf->Length));
outIdx = outIdx + 1;
cmd = WC_TRNG_CMD;
break;
case CAAM_GET_PART:
SETIOV(&out[outIdx], (buf->TheAddress), (buf->Length));
outIdx = outIdx + 1;
cmd = WC_CAAM_GET_PART;
break;
case CAAM_FREE_PART:
cmd = WC_CAAM_FREE_PART;
break;
case CAAM_FIND_PART:
SETIOV(&out[outIdx], (buf->TheAddress), (buf->Length));
outIdx = outIdx + 1;
cmd = WC_CAAM_FIND_PART;
break;
case CAAM_READ_PART:
SETIOV(&out[outIdx], (buf->TheAddress), (buf->Length));
outIdx = outIdx + 1;
cmd = WC_CAAM_READ_PART;
break;
case CAAM_WRITE_PART:
SETIOV(&in[inIdx], (buf->TheAddress), (buf->Length));
inIdx = inIdx + 1;
cmd = WC_CAAM_WRITE_PART;
break;
case CAAM_ECDSA_KEYPAIR:
/* set output to store directly to CAAM_BUFFER's */
SETIOV(&out[outIdx], buf[0].TheAddress, buf[0].Length);
outIdx = outIdx + 1;
SETIOV(&out[outIdx], buf[1].TheAddress, buf[1].Length);
outIdx = outIdx + 1;
/* get args for updated partition number used */
SETIOV(&out[outIdx], args, sizeof(unsigned int) * 4);
outIdx = outIdx + 1;
cmd = WC_CAAM_ECDSA_KEYPAIR;
break;
case CAAM_ECDSA_VERIFY:
/* public key */
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
/* msg */
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
/* r */
SETIOV(&in[inIdx], buf[2].TheAddress, buf[2].Length);
inIdx = inIdx + 1;
/* s */
SETIOV(&in[inIdx], buf[3].TheAddress, buf[3].Length);
inIdx = inIdx + 1;
cmd = WC_CAAM_ECDSA_VERIFY;
break;
case CAAM_ECDSA_SIGN:
/* private key */
if (args[0] == 1) {
privkey = buf[0].TheAddress;
SETIOV(&in[inIdx], &privkey, sizeof(unsigned int));
inIdx = inIdx + 1;
}
else {
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
}
/* msg */
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
/* r out */
SETIOV(&out[outIdx], buf[2].TheAddress, buf[2].Length);
outIdx = outIdx + 1;
/* s out */
SETIOV(&out[outIdx], buf[3].TheAddress, buf[3].Length);
outIdx = outIdx + 1;
cmd = WC_CAAM_ECDSA_SIGN;
break;
case CAAM_ECDSA_ECDH:
/* when using memory in secure partition just send the address */
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
/* private key */
if (args[0] == CAAM_BLACK_KEY_SM) {
privkey = buf[1].TheAddress;
SETIOV(&in[inIdx], &privkey, sizeof(unsigned int));
inIdx = inIdx + 1;
}
else {
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
}
/* shared secret */
SETIOV(&out[outIdx], buf[2].TheAddress, buf[2].Length);
outIdx = outIdx + 1;
cmd = WC_CAAM_ECDSA_ECDH;
break;
case CAAM_BLOB_ENCAP:
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
if (args[0] == 1) {
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length + WC_CAAM_MAC_SZ);
inIdx = inIdx + 1;
}
else {
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
}
SETIOV(&out[outIdx], buf[2].TheAddress, buf[2].Length);
outIdx = outIdx + 1;
cmd = WC_CAAM_BLOB_ENCAP;
break;
case CAAM_BLOB_DECAP:
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
if (args[0] == 1) {
SETIOV(&out[outIdx], buf[2].TheAddress,
buf[2].Length + WC_CAAM_MAC_SZ);
outIdx = outIdx + 1;
}
else {
SETIOV(&out[outIdx], buf[2].TheAddress, buf[2].Length);
outIdx = outIdx + 1;
}
cmd = WC_CAAM_BLOB_DECAP;
break;
case CAAM_AESECB:
/* key */
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
/* in */
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
/* out */
SETIOV(&out[outIdx], buf[2].TheAddress, buf[2].Length);
outIdx = outIdx + 1;
cmd = WC_CAAM_AESECB;
break;
case CAAM_AESCBC:
/* key */
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
/* in */
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
/* iv */
SETIOV(&in[inIdx], buf[2].TheAddress, buf[2].Length);
inIdx = inIdx + 1;
/* out */
SETIOV(&out[outIdx], buf[3].TheAddress, buf[3].Length);
outIdx = outIdx + 1;
/* out updated IV */
SETIOV(&out[outIdx], buf[4].TheAddress, buf[4].Length);
outIdx = outIdx + 1;
cmd = WC_CAAM_AESCBC;
break;
case CAAM_AESCTR:
/* key */
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
/* iv */
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
/* in */
SETIOV(&in[inIdx], buf[2].TheAddress, buf[2].Length);
inIdx = inIdx + 1;
/* out */
SETIOV(&out[outIdx], buf[3].TheAddress, buf[3].Length);
outIdx = outIdx + 1;
/* out updated IV */
SETIOV(&out[outIdx], buf[4].TheAddress, buf[4].Length);
outIdx = outIdx + 1;
cmd = WC_CAAM_AESCTR;
break;
case CAAM_AESCCM:
/* key */
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
/* iv */
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
/* in */
SETIOV(&in[inIdx], buf[2].TheAddress, buf[2].Length);
inIdx = inIdx + 1;
/* out */
SETIOV(&out[outIdx], buf[3].TheAddress, buf[3].Length);
outIdx = outIdx + 1;
/* set TAG as input or output */
if ((args[0] & 0xFFFF) == CAAM_ENC) {
SETIOV(&out[outIdx], buf[4].TheAddress, buf[4].Length);
outIdx = outIdx + 1;
}
else {
SETIOV(&in[inIdx], buf[4].TheAddress, buf[4].Length);
inIdx = inIdx + 1;
}
/* aad */
SETIOV(&in[inIdx], buf[5].TheAddress, buf[5].Length);
inIdx = inIdx + 1;
cmd = WC_CAAM_AESCCM;
break;
case CAAM_AESGCM:
/* key */
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
/* iv */
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
/* in */
SETIOV(&in[inIdx], buf[2].TheAddress, buf[2].Length);
inIdx = inIdx + 1;
/* out */
SETIOV(&out[outIdx], buf[3].TheAddress, buf[3].Length);
outIdx = outIdx + 1;
/* set TAG as input or output */
if ((args[0] & 0xFFFF) == CAAM_ENC) {
SETIOV(&out[outIdx], buf[4].TheAddress, buf[4].Length);
outIdx = outIdx + 1;
}
else {
SETIOV(&in[inIdx], buf[4].TheAddress, buf[4].Length);
inIdx = inIdx + 1;
}
/* aad */
SETIOV(&in[inIdx], buf[5].TheAddress, buf[5].Length);
inIdx = inIdx + 1;
cmd = WC_CAAM_AESGCM;
break;
case CAAM_CMAC:
{
int i;
if (args[2] == 1) {
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length + 16);
inIdx = inIdx + 1;
}
else {
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
}
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
/* get input buffers */
args[3] = 0;
for (i = 2; i < sz && i < MAX_IN_IOVS; i++) {
SETIOV(&in[inIdx], buf[i].TheAddress, buf[i].Length);
inIdx = inIdx + 1;
args[3] += buf[i].Length;
}
SETIOV(&out[outIdx], buf[1].TheAddress, buf[1].Length);
outIdx = outIdx + 1;
}
cmd = WC_CAAM_CMAC;
break;
case CAAM_FIFO_S:
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
SETIOV(&out[outIdx], buf[1].TheAddress, buf[1].Length + WC_CAAM_MAC_SZ);
outIdx = outIdx + 1;
cmd = WC_CAAM_FIFO_S;
break;
default:
WOLFSSL_MSG("Unknown/unsupported type");
return -1;
}
ret = wc_LockMutex(&caamMutex);
if (ret == 0) {
ret = devctlv(caamFd, cmd, inIdx, outIdx, in, out, NULL);
wc_UnLockMutex(&caamMutex);
}
if (ret != 0) {
if (ret == EFAULT) {
WOLFSSL_MSG("bad address on one of the in/out buffers");
return -1;
}
if (ret == EAGAIN && type == CAAM_ENTROPY) {
return CAAM_WAITING;
}
return -1;
}
return Success;
}
#endif /* WOLFSSL_QNX_CAAM && (__QNX__ || __QNXNTO__) */

View File

@ -0,0 +1,106 @@
/* wolfcaam_rsa.c
*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_CAAM) && !defined(NO_RSA)
#include <wolfssl/wolfcrypt/logging.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
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
#include <wolfssl/wolfcrypt/port/caam/wolfcaam_rsa.h>
#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
#include <stdio.h>
#endif
#if defined(WOLFSSL_DEVCRYPTO_RSA)
#include <wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h>
/* HSM lib does not support RSA with QXP board, use devcrypto instead */
int wc_CAAM_Rsa(const byte* in, word32 inLen, byte* out, word32* outLen,
int type, RsaKey* key, WC_RNG* rng)
{
int ret = -1;
switch (type) {
case RSA_PUBLIC_ENCRYPT:
case RSA_PRIVATE_ENCRYPT:
ret = wc_DevCrypto_RsaEncrypt(in, inLen, out, outLen, key, type);
break;
case RSA_PUBLIC_DECRYPT:
case RSA_PRIVATE_DECRYPT:
ret = wc_DevCrypto_RsaDecrypt(in, inLen, out, *outLen, key, type);
}
(void)rng;
return ret;
}
#ifdef WOLFSSL_KEY_GEN
int wc_CAAM_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng)
{
return wc_DevCrypto_MakeRsaKey(key, size, e, rng);
}
#endif
#else
int wc_CAAM_Rsa(const byte* in, word32 inLen, byte* out, word32* outLen,
int type, RsaKey* key, WC_RNG* rng)
{
(void)in;
(void)inLen;
(void)out;
(void)outLen;
(void)type;
(void)key;
(void)rng;
return CRYPTOCB_UNAVAILABLE;
}
#ifdef WOLFSSL_KEY_GEN
int wc_CAAM_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng)
{
(void)size;
(void)e;
(void)key;
(void)rng;
return CRYPTOCB_UNAVAILABLE;
}
#endif
#endif /* WOLFSSL_DEVCRYPTO_RSA */
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,129 @@
/* wolfcaam_x25519.c
*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_CAAM) && defined(HAVE_CURVE25519)
#include <wolfssl/wolfcrypt/logging.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
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
#include <wolfssl/wolfcrypt/port/caam/wolfcaam_x25519.h>
#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
#include <stdio.h>
#endif
#if defined(WOLFSSL_DEVCRYPTO_CURVE25519)
#include <wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h>
/* HSM lib does not support Curve25519 with QXP board, use devcrypto instead */
static int wc_CAAM_Curve25519Generic(byte* out, word32 outSz, const byte* k,
word32 kSz, const byte* a, word32 aSz, int endian)
{
return wc_DevCryptoCurve25519(out, outSz, k, kSz, a, aSz, endian);
}
int wc_CAAM_MakeCurve25519Key(curve25519_key* key, int keySize, WC_RNG* rng)
{
int ret = 0;
if (keySize != CURVE25519_KEYSIZE || rng == NULL || key == NULL) {
ret = BAD_FUNC_ARG;
}
if (ret == 0) {
ret = wc_curve25519_make_priv(rng, keySize, key->k);
}
/* create public key from private key */
if (ret == 0) {
static const unsigned char basePoint[CURVE25519_KEYSIZE] = {9};
word32 outlen = (word32)keySize;
key->privSet = 1;
ret = wc_CAAM_Curve25519Generic(key->p.point, outlen, key->k,
CURVE25519_KEYSIZE, basePoint, CURVE25519_KEYSIZE,
EC25519_LITTLE_ENDIAN);
if (ret == 0) {
key->pubSet = 1;
}
}
return ret;
}
int wc_CAAM_Curve25519(byte* out, word32* outlen, curve25519_key* k,
curve25519_key* pubKey, int endian)
{
int ret = 0;
if (*outlen < CURVE25519_KEYSIZE) {
ret = BAD_FUNC_ARG;
}
if (ret == 0) {
*outlen = CURVE25519_KEYSIZE;
ret = wc_CAAM_Curve25519Generic(out, *outlen, k->k, CURVE25519_KEYSIZE,
pubKey->p.point, CURVE25519_KEYSIZE, endian);
}
return ret;
}
#else
int wc_CAAM_MakeCurve25519Key(curve25519_key* key, int keySize, WC_RNG* rng)
{
(void)keySize;
(void)key;
(void)rng;
return CRYPTOCB_UNAVAILABLE;
}
int wc_CAAM_Curve25519(byte* out, word32* outlen, curve25519_key* k,
curve25519_key* pubKey, int endian)
{
(void)out;
(void)outlen;
(void)k;
(void)pubKey;
(void)endian;
return CRYPTOCB_UNAVAILABLE;
}
#endif /* WOLFSSL_DEVCRYPTO_CURVE25519 */
#endif