From c0d7f3b2e6769a533e0381ba104814590e762cab Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Wed, 27 Apr 2022 02:27:05 -0700 Subject: [PATCH] add support for i.MX8 with QNX CAAM --- IDE/QNX/CAAM-DRIVER/Makefile | 3 + configure.ac | 1 + wolfcrypt/src/aes.c | 9 + wolfcrypt/src/asn.c | 4 +- wolfcrypt/src/cryptocb.c | 33 + wolfcrypt/src/ecc.c | 76 +- wolfcrypt/src/port/caam/caam_driver.c | 853 ++++++++++++++------- wolfcrypt/src/port/caam/caam_error.c | 27 +- wolfcrypt/src/port/caam/caam_qnx.c | 514 +++++++++++-- wolfcrypt/src/port/caam/wolfcaam_aes.c | 198 ++++- wolfcrypt/src/port/caam/wolfcaam_ecdsa.c | 111 ++- wolfcrypt/src/port/caam/wolfcaam_init.c | 37 +- wolfcrypt/src/port/caam/wolfcaam_qnx.c | 179 ++++- wolfcrypt/src/random.c | 2 +- wolfcrypt/test/test.c | 29 +- wolfssl/wolfcrypt/cryptocb.h | 12 + wolfssl/wolfcrypt/port/caam/caam_driver.h | 109 ++- wolfssl/wolfcrypt/port/caam/caam_qnx.h | 29 +- wolfssl/wolfcrypt/port/caam/wolfcaam.h | 9 + wolfssl/wolfcrypt/port/caam/wolfcaam_aes.h | 3 + wolfssl/wolfcrypt/port/caam/wolfcaam_qnx.h | 3 +- 21 files changed, 1749 insertions(+), 492 deletions(-) diff --git a/IDE/QNX/CAAM-DRIVER/Makefile b/IDE/QNX/CAAM-DRIVER/Makefile index 0a77ea28c..e483355f0 100644 --- a/IDE/QNX/CAAM-DRIVER/Makefile +++ b/IDE/QNX/CAAM-DRIVER/Makefile @@ -12,6 +12,9 @@ LD = $(CC) INCLUDES += -I../../../ -I../../../wolfssl/wolfcrypt/port/caam/ CCFLAGS += -O2 -Wall +# For debugging print outs build with WOLFSSL_CAAM_PRINT defined +#CCFLAGS += -DWOLFSSL_CAAM_PRINT -O2 -Wall + SRCS = \ ../../../wolfcrypt/src/port/caam/caam_driver.c \ ../../../wolfcrypt/src/port/caam/caam_error.c \ diff --git a/configure.ac b/configure.ac index 9f5198f25..fb47ee415 100644 --- a/configure.ac +++ b/configure.ac @@ -1941,6 +1941,7 @@ then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CAAM -DWOLFSSL_IMX6_CAAM -DWOLFSSL_QNX_CAAM" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CAAM_ECC" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CAAM_CMAC" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CAAM_CIPHER" fi if test "$ENABLED_CAAM" = "seco" diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 6a1af1f72..dfa76e5dc 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -4430,6 +4430,15 @@ int wc_AesSetIV(Aes* aes, const byte* iv) return BAD_FUNC_ARG; } + #ifdef WOLF_CRYPTO_CB + if (aes->devId != INVALID_DEVID) { + int crypto_cb_ret = wc_CryptoCb_AesCtrEncrypt(aes, out, in, sz); + if (crypto_cb_ret != CRYPTOCB_UNAVAILABLE) + return crypto_cb_ret; + /* fall-through when unavailable */ + } + #endif + /* consume any unused bytes left in aes->tmp */ tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; while (aes->left && sz) { diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index c483eb338..bef97ac00 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -28200,8 +28200,8 @@ static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 *inLen, privSz = key->dp->size; #ifdef WOLFSSL_QNX_CAAM - /* check if is a black key, and add MAC size if so */ - if (key->blackKey > 0) { + /* check if is a black key, and add MAC size if needed */ + if (key->blackKey > 0 && key->blackKey != CAAM_BLACK_KEY_ECB) { privSz = privSz + WC_CAAM_MAC_SZ; } #endif diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index dc4ccaddb..c198f639c 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -727,6 +727,39 @@ int wc_CryptoCb_AesCbcDecrypt(Aes* aes, byte* out, return wc_CryptoCb_TranslateErrorCode(ret); } #endif /* HAVE_AES_CBC */ +#ifdef WOLFSSL_AES_COUNTER +int wc_CryptoCb_AesCtrEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (aes) { + dev = wc_CryptoCb_FindDevice(aes->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_AES_CTR; + cryptoInfo.cipher.enc = 1; + cryptoInfo.cipher.aesctr.aes = aes; + cryptoInfo.cipher.aesctr.out = out; + cryptoInfo.cipher.aesctr.in = in; + cryptoInfo.cipher.aesctr.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* WOLFSSL_AES_COUNTER */ #ifdef HAVE_AES_ECB int wc_CryptoCb_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 6c7349810..41a6b1ccc 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -6866,7 +6866,8 @@ int wc_ecc_free(ecc_key* key) #ifdef WOLFSSL_QNX_CAAM /* free secure memory */ - if (key->blackKey > 0) { + if ((key->blackKey != CAAM_BLACK_KEY_CCM && + key->blackKey != CAAM_BLACK_KEY_ECB) && key->blackKey > 0) { caamFreePart(key->partNum); } #endif @@ -9619,22 +9620,31 @@ int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, } #endif #ifdef WOLFSSL_QNX_CAAM - if (encType == WC_TYPE_BLACK_KEY) { - if (key->blackKey > 0) { + if (key->blackKey == CAAM_BLACK_KEY_CCM) { if (*dLen < keySz + WC_CAAM_MAC_SZ) { *dLen = keySz + WC_CAAM_MAC_SZ; return BUFFER_E; } - if (caamReadPartition(key->blackKey, d, keySz + WC_CAAM_MAC_SZ) != 0) - return WC_HW_E; + err = wc_export_int(&key->k, d, dLen, keySz + WC_CAAM_MAC_SZ, encType); + *dLen = keySz + WC_CAAM_MAC_SZ; + } + else if (encType == WC_TYPE_BLACK_KEY && + key->blackKey != CAAM_BLACK_KEY_ECB && + key->blackKey > 0) { + if (*dLen < keySz + WC_CAAM_MAC_SZ) { + *dLen = keySz + WC_CAAM_MAC_SZ; + return BUFFER_E; + } + + if (key->blackKey != CAAM_BLACK_KEY_CCM) { + if (caamReadPartition(key->blackKey, d, keySz + WC_CAAM_MAC_SZ) != 0) + return WC_HW_E; + } + else { + } *dLen = keySz + WC_CAAM_MAC_SZ; - } - else { - WOLFSSL_MSG("No black key stored in structure"); - return BAD_FUNC_ARG; - } } else #endif @@ -9680,7 +9690,8 @@ int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen) #ifdef WOLFSSL_QNX_CAAM /* check if black key in secure memory */ - if (key->blackKey > 0) { + if ((key->blackKey != CAAM_BLACK_KEY_CCM && + key->blackKey != CAAM_BLACK_KEY_ECB) && key->blackKey > 0) { return wc_ecc_export_ex(key, NULL, NULL, NULL, NULL, out, outLen, WC_TYPE_BLACK_KEY); } @@ -9785,6 +9796,7 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, } #elif defined(WOLFSSL_QNX_CAAM) if ((wc_ecc_size(key) + WC_CAAM_MAC_SZ) == (int)privSz) { + #ifdef WOLFSSL_CAAM_BLACK_KEY_SM int part = caamFindUnusedPartition(); if (part >= 0) { CAAM_ADDRESS vaddr = caamGetPartition(part, privSz*3); @@ -9809,10 +9821,33 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, WOLFSSL_MSG("Unable to find an unused partition"); return MEMORY_E; } + #else + key->blackKey = CAAM_BLACK_KEY_CCM; + ret = mp_read_unsigned_bin(&key->k, priv, privSz); + #endif } else { - WOLFSSL_MSG("Importing key that is not a black key!"); + key->blackKey = 0; ret = mp_read_unsigned_bin(&key->k, priv, privSz); + + /* If using AES-ECB encrypted black keys check here if key is valid, + * if not valid than assume is an encrypted key. A public key is needed + * for testing validity. */ + if (key->devId == WOLFSSL_CAAM_DEVID && ( + wc_ecc_get_curve_id(key->idx) == ECC_SECP256R1 || + wc_ecc_get_curve_id(key->idx) == ECC_SECP384R1)) { + if ((pub != NULL) && (ret == MP_OKAY) && + (_ecc_validate_public_key(key, 1, 1) != MP_OKAY)) { + key->blackKey = CAAM_BLACK_KEY_ECB; + } + else if ((pub == NULL) && (ret == MP_OKAY)) { + WOLFSSL_MSG("Assuming encrypted key with no public key to check"); + key->blackKey = CAAM_BLACK_KEY_ECB; + } + else { + WOLFSSL_MSG("Importing key that is not a black key!"); + } + } } #else @@ -9835,6 +9870,7 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, if ((pub != NULL) && (ret == MP_OKAY)) /* public key needed to perform key validation */ ret = _ecc_validate_public_key(key, 1, 1); + #endif #ifdef WOLFSSL_VALIDATE_ECC_IMPORT @@ -10146,12 +10182,21 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, #else key->type = ECC_PRIVATEKEY; - if (encType == WC_TYPE_HEX_STR) err = mp_read_radix(&key->k, d, MP_RADIX_HEX); - else - err = mp_read_unsigned_bin(&key->k, (const byte*)d, + else { + #ifdef WOLFSSL_QNX_CAAM + if (key->blackKey == CAAM_BLACK_KEY_CCM) { + err = mp_read_unsigned_bin(&key->k, (const byte*)d, + key->dp->size + WC_CAAM_MAC_SZ); + } + else + #endif /* WOLFSSL_QNX_CAAM */ + { + err = mp_read_unsigned_bin(&key->k, (const byte*)d, key->dp->size); + } + } #endif /* WOLFSSL_ATECC508A */ if (mp_iszero(&key->k) || mp_isneg(&key->k)) { WOLFSSL_MSG("Invalid private key"); @@ -13006,6 +13051,7 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, ret = wc_HmacUpdate(hmac, msg, msgSz-digestSz); if (ret == 0) ret = wc_HmacUpdate(hmac, ctx->macSalt, ctx->macSaltSz); + if (ret == 0) ret = wc_HmacFinal(hmac, verify); if ((ret == 0) && (XMEMCMP(verify, msg + msgSz - digestSz, diff --git a/wolfcrypt/src/port/caam/caam_driver.c b/wolfcrypt/src/port/caam/caam_driver.c index cd625a946..580da0e10 100644 --- a/wolfcrypt/src/port/caam/caam_driver.c +++ b/wolfcrypt/src/port/caam/caam_driver.c @@ -24,7 +24,11 @@ #if defined(__QNX__) || defined(__QNXNTO__) #include - #include + #ifdef __aarch64__ + #include + #else + #include + #endif #include #include @@ -36,11 +40,16 @@ #include /* for memcpy / memset */ - struct JobRing { + /* base address for job ring */ + CAAM_ADDRESS BaseAddr; + + /* physical address */ CAAM_ADDRESS JobIn; CAAM_ADDRESS JobOut; CAAM_ADDRESS Desc; + + /* virtual address */ void* VirtualIn; void* VirtualOut; void* VirtualDesc; @@ -56,7 +65,9 @@ struct CAAM_DEVICE { volatile Value InterruptStatus; CALL HandleInterruptCall; #endif - struct JobRing ring; + struct JobRing ring; + CAAM_ADDRESS baseAddr; /* base address for CAAM */ + unsigned short vrs; /* era version number of CAAM */ }; #define DRIVER_NAME "wolfSSL_CAAM_Driver" @@ -149,10 +160,10 @@ static void printSecureMemoryInfo() { unsigned int SMVID_MS, SMVID_LS; - printf("SMSTA = 0x%08X\n", CAAM_READ(0x1FB4)); - printf("SMPO = 0x%08X\n", CAAM_READ(CAAM_SM_SMPO)); - SMVID_MS = CAAM_READ(CAAM_SM_SMVID_MS); - SMVID_LS = CAAM_READ(CAAM_SM_SMVID_LS); + printf("SMSTA = 0x%08X\n", CAAM_READ(caam.ring.BaseAddr + 0x0FB4)); + printf("SMPO = 0x%08X\n", CAAM_READ(caam.ring.BaseAddr + CAAM_SM_SMPO)); + SMVID_MS = CAAM_READ(caam.ring.BaseAddr + CAAM_SM_SMVID_MS); + SMVID_LS = CAAM_READ(caam.ring.BaseAddr + CAAM_SM_SMVID_LS); printf("\tNumber Partitions : %d\n", ((SMVID_MS >> 12) & 0xFU)); printf("\tNumber Pages : %d\n", (SMVID_MS & 0x3FFU)); printf("\tPage Size : 2^%d\n", ((SMVID_LS >> 16) & 0x7U)); @@ -165,35 +176,41 @@ static Error caamReset(void) int t = 100000; /* time out counter for flushing job ring */ /* make sure interrupts are masked in JRCFGR0_LS register */ - CAAM_WRITE(0x1054, CAAM_READ(0x1054) | 1); + CAAM_WRITE(caam.ring.BaseAddr + JRCFGR_JR, + CAAM_READ(caam.ring.BaseAddr + JRCFGR_JR) | 1); /* flush and reset job rings using JRCR0 register */ - CAAM_WRITE(0x106C, 1); + CAAM_WRITE(caam.ring.BaseAddr + JRCR_JR, 1); /* check register JRINTR for if halt is in progress */ - while (t > 0 && ((CAAM_READ(0x104C) & 0x4) == 0x4)) { t = t - 1; } + while (t > 0 && ((CAAM_READ(caam.ring.BaseAddr + JRINTR_JR) & 0x4) + == 0x4)) { + t = t - 1; + } if (t == 0) { /*unrecoverable failure, the job ring is locked, up hard reset needed*/ - return -1;//NotRestartable; + return -1; } /* now that flush has been done restart the job ring */ t = 100000; - CAAM_WRITE(0x106C, 1); - while (t > 0 && ((CAAM_READ(0x106C) & 1) == 1)) { t = t - 1; } + CAAM_WRITE(caam.ring.BaseAddr + JRCR_JR, 1); + while (t > 0 && ((CAAM_READ(caam.ring.BaseAddr + JRCR_JR) & 1) == 1)) { + t = t - 1; + } if (t == 0) { /*unrecoverable failure, reset bit did not return to 0 */ - return -1;//NotRestartable; + return -1; } - /* reset most registers and state machines in CAAM using MCFGR register - also reset DMA */ - CAAM_WRITE(0x0004, 0x90000000); + if (caam.vrs < 9) { + /* reset most registers and state machines in CAAM using MCFGR register + also reset DMA */ + CAAM_WRITE(caam.baseAddr + CAAM_RSTA, 0x90000000); - /* DAR 0x0120 can be used to check if hung */ - - /* DDR */ - CAAM_WRITE(0x0124, 1); + /* DDR */ + CAAM_WRITE(caam.baseAddr + CAAM_DRR, 1); + } return Success; } @@ -203,12 +220,12 @@ static Error caamReset(void) static Error caamFreePage(unsigned int page) { /* owns the page can dealloc it */ - CAAM_WRITE(CAAM_SM_CMD, (page << 16U) | 0x2U); - while ((CAAM_READ(CAAM_SM_STATUS) & 0x00004000) > 0 && - (CAAM_READ(CAAM_SM_STATUS) & 0x00003000) == 0) { + CAAM_WRITE(caam.ring.BaseAddr + CAAM_SM_CMD, (page << 16U) | 0x2U); + while ((CAAM_READ(caam.ring.BaseAddr + CAAM_SM_STATUS) & 0x00004000) > 0 && + (CAAM_READ(caam.ring.BaseAddr + CAAM_SM_STATUS) & 0x00003000) == 0) { CAAM_CPU_CHILL(); } - if ((CAAM_READ(CAAM_SM_STATUS) & 0x00003000) > 0) { + if ((CAAM_READ(caam.ring.BaseAddr + CAAM_SM_STATUS) & 0x00003000) > 0) { /* error while deallocating page */ WOLFSSL_MSG("error while deallocating page"); return MemoryMapMayNotBeEmpty; /* PSP set on page or is unavailable */ @@ -250,7 +267,7 @@ static Error caamFreeAllPart() unsigned int i; WOLFSSL_MSG("Free all partitions"); - SMPO = CAAM_READ(0x1FBC); + SMPO = CAAM_READ(caam.ring.BaseAddr + CAAM_SM_SMPO); for (i = 0; i < 15U; i = i + 1U) { if ((SMPO & (0x3U << (i * 2U))) == (0x3U << (i * 2U))) { caamFreePart(i); @@ -270,7 +287,7 @@ int caamFindUnusedPartition() unsigned int i; int ret = -1; - SMPO = CAAM_READ(0x1FBC); + SMPO = CAAM_READ(caam.ring.BaseAddr + CAAM_SM_SMPO); for (i = 0; i < 15U; i = i + 1) { if ((SMPO & (0x3U << (i * 2U))) == 0U) { ret = (int)i; @@ -285,14 +302,14 @@ int caamFindUnusedPartition() /* flag contains how the parition is set i.e CSP flag and read/write access * it also contains if locked */ -static Error caamCreatePartition(unsigned int page, unsigned int par, +static Error caamCreatePartition(unsigned int* page, unsigned int par, unsigned int flag) { - + int testPage; unsigned int status; /* check ownership of partition */ - status = CAAM_READ(0x1FBC); + status = CAAM_READ(caam.ring.BaseAddr + CAAM_SM_SMPO); if ((status & (0x3U << (par * 2))) > 0) { if ((status & (0x3U << (par * 2))) == (0x3U << (par * 2))) { WOLFSSL_MSG("we own this partition!"); @@ -301,34 +318,43 @@ static Error caamCreatePartition(unsigned int page, unsigned int par, return MemoryMapMayNotBeEmpty; } } - - CAAM_WRITE(0x1A04 + (par * 16), flag); + CAAM_WRITE(caam.ring.BaseAddr + CAAM_SMAPR + (par * 16), flag); /* dealloc page if we own it */ - CAAM_WRITE(CAAM_SM_CMD, (page << 16) | 0x5); - while ((CAAM_READ(CAAM_SM_STATUS) & 0x00004000) > 0 && - (CAAM_READ(CAAM_SM_STATUS) & 0x00003000) == 0) { - CAAM_CPU_CHILL(); - } - if ((CAAM_READ(CAAM_SM_STATUS) & 0x000000C0) == 0xC0) { - if (caamFreePage(page) != Success) { - return MemoryMapMayNotBeEmpty; + for (testPage = 0; testPage < 16; testPage++) { + CAAM_WRITE(caam.ring.BaseAddr + CAAM_SM_CMD, (testPage << 16) | 0x5); + while ((CAAM_READ(caam.ring.BaseAddr + CAAM_SM_STATUS) & 0x00004000) > 0 + && (CAAM_READ(caam.ring.BaseAddr + CAAM_SM_STATUS) & 0x00003000) + == 0) { + CAAM_CPU_CHILL(); + } + if ((CAAM_READ(caam.ring.BaseAddr + CAAM_SM_STATUS) & 0x000000C0) == + 0xC0) { + if (caamFreePage(testPage) != Success) { + continue; + } + } + else if ((CAAM_READ(caam.ring.BaseAddr + CAAM_SM_STATUS) & 0x000000C0) + == 0x00) { + WOLFSSL_MSG("testPage available and un-owned"); + } + else { + WOLFSSL_MSG("we don't own the testPage..."); + continue; } - } - else if ((CAAM_READ(CAAM_SM_STATUS) & 0x000000C0) == 0x00) { - WOLFSSL_MSG("page available and un-owned"); - } - else { - WOLFSSL_MSG("we don't own the page..."); - return -1; - } - CAAM_WRITE(CAAM_SM_CMD, (page << 16) | (par << 8) | 0x1); - /* wait for alloc cmd to complete */ - while ((CAAM_READ(CAAM_SM_STATUS) & 0x00004000) > 0 && - (CAAM_READ(CAAM_SM_STATUS) & 0x00003000) == 0) { - CAAM_CPU_CHILL(); + CAAM_WRITE(caam.ring.BaseAddr + CAAM_SM_CMD, (testPage << 16) | + (par << 8) | 0x1); + /* wait for alloc cmd to complete */ + while ((CAAM_READ(caam.ring.BaseAddr + CAAM_SM_STATUS) & 0x00004000) > 0 && + (CAAM_READ(caam.ring.BaseAddr + CAAM_SM_STATUS) & 0x00003000) == 0) { + CAAM_CPU_CHILL(); + } + break; } + if (testPage == 16) + return -1; + *page=testPage; return Success; } @@ -342,7 +368,7 @@ CAAM_ADDRESS caamGetPartition(unsigned int part, int partSz, unsigned int flag) (void)flag; /* flag is for future changes to flag passed when creating */ /* create and claim the partition */ - err = caamCreatePartition(part, part, CAAM_SM_CSP | CAAM_SM_SMAP_LOCK | + err = caamCreatePartition(&part, part, CAAM_SM_CSP | CAAM_SM_SMAP_LOCK | CAAM_SM_CSP | CAAM_SM_ALL_RW); if (err != Success) { WOLFSSL_MSG("Error creating partiions for secure ecc key"); @@ -360,18 +386,21 @@ CAAM_ADDRESS caamGetPartition(unsigned int part, int partSz, unsigned int flag) * Status holds the error values if any */ static Error caamGetJob(struct CAAM_DEVICE* dev, unsigned int* status) { + CAAM_ADDRESS baseAddr; unsigned int reg; if (status) { *status = 0; } + baseAddr = caam.ring.BaseAddr; + #ifdef CAAM_DEBUG_MODE (void)dev; return Success; #endif /* Check number of done jobs in output list */ - reg = CAAM_READ(0x103C); + reg = CAAM_READ(baseAddr + CAAM_ORJAR); #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) printf("number of jobs in output list = 0x%08X\n", reg); #endif @@ -385,25 +414,27 @@ static Error caamGetJob(struct CAAM_DEVICE* dev, unsigned int* status) /* sanity check on job out */ pt = (unsigned int*)caam.ring.VirtualOut; - if (pt[0] != caam.ring.Desc) { + if (pt[0] != (unsigned int)caam.ring.Desc) { + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("Job found %08X does not match expected job %08X\n", + pt[0], (unsigned int)caam.ring.Desc); + #endif return -1; } - #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) - printf("\tjob 0x%08X done - result 0x%08X\n", pt[0], pt[1]); - #endif *status = pt[1]; /* increment jobs removed */ #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("\tjob 0x%08X done - result 0x%08X\n", pt[0], pt[1]); printf("removing job from list\n"); fflush(stdout); #endif - CAAM_WRITE(0x1034, 1); + CAAM_WRITE(baseAddr + CAAM_ORJRR, 1); } else { /* check if the CAAM is idle and not processing any descriptors */ - if ((CAAM_READ(0x0FD4) & 0x00000002) == 2 /* idle */ - && (CAAM_READ(0x0FD4) & 0x00000001) == 0) { + if ((CAAM_READ(baseAddr + 0x0FD4) & 0x00000002) == 2 /* idle */ + && (CAAM_READ(baseAddr + 0x0FD4) & 0x00000001) == 0) { WOLFSSL_MSG("caam is idle....."); return NoActivityReady; } @@ -411,7 +442,7 @@ static Error caamGetJob(struct CAAM_DEVICE* dev, unsigned int* status) } (void)dev; - CAAM_WRITE(JRCFGR_JR0_LS, 0); + CAAM_WRITE(baseAddr + JRCFGR_JR, 0); if (*status == 0) { return Success; } @@ -419,21 +450,6 @@ static Error caamGetJob(struct CAAM_DEVICE* dev, unsigned int* status) } -#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) -/* debug print out JDKEK */ -static void print_jdkek() -{ - int i; - - printf("JDKEK = "); - for (i = 0; i < 8; i = i + 1) { - printf("%08X ", CAAM_READ(0x0400 + (i*4))); - } - printf("\n"); -} -#endif - - /* instantiate RNG and create JDKEK, TDKEK, and TDSK key */ #define WC_RNG_START_SIZE 6 static unsigned int wc_rng_start[WC_RNG_START_SIZE] = { @@ -534,13 +550,17 @@ int caamInitRng(struct CAAM_DEVICE* dev) /* Take in a descriptor and add it to the job list */ Error caamAddJob(DESCSTRUCT* desc) { + CAAM_ADDRESS baseAddr; + /* clear and set desc size */ desc->desc[0] &= 0xFFFFFF80; desc->desc[0] += desc->idx + (desc->startIdx << 16); CAAM_LOCK_MUTEX(&caam.ring.jr_lock); + baseAddr = caam.ring.BaseAddr; + /* check input slot is available and then add */ - if (CAAM_READ(0x1014) > 0) { + if (CAAM_READ(baseAddr + CAAM_IRSAR_JR) > 0) { int i; unsigned int *pt; @@ -577,14 +597,14 @@ Error caamAddJob(DESCSTRUCT* desc) #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) printf("started job 0x%08X done\n", (unsigned int)caam.ring.Desc); #endif - CAAM_WRITE(CAAM_IRJAR0, 0x00000001); + CAAM_WRITE(baseAddr + CAAM_IRJAR0, 0x00000001); #endif } else { #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) - printf("SLOT = 0x%08X, IRJAR0 = 0x%08X\n", CAAM_READ(0x1014), - CAAM_READ(CAAM_IRJAR0)); - printf("Number of job in done queue = 0x%08X\n", CAAM_READ(0x103C)); + printf("SLOT = 0x%08X, IRJAR0 = 0x%08X\n", CAAM_READ(baseAddr + 0x0014), + CAAM_READ(baseAddr + CAAM_IRJAR0)); + printf("Number of job in done queue = 0x%08X\n", CAAM_READ(baseAddr+ 0x103C)); #endif CAAM_UNLOCK_MUTEX(&caam.ring.jr_lock); return CAAM_WAITING; @@ -614,17 +634,10 @@ Error caamDoJob(DESCSTRUCT* desc) printf("job status = 0x%08X, ret = %d\n", status, ret); #endif + /* try to reset after error */ if (status != 0 || ret != Success) { - /* try to reset after error */ - #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) - int i; - for (i = 0; i < desc->idx; i = i + 1) { - printf("\tCMD %02d = 0x%08X\n", i+1, desc->desc[i]); - } - printf("\n"); - #endif /* consider any job ring errors as fatal, and try reset */ - if (caamParseJRError(CAAM_READ(JRINTR_JR0)) != 0) { + if (caamParseJRError(CAAM_READ(caam.ring.BaseAddr + JRINTR_JR)) != 0) { caamReset(); } caamParseError(status); @@ -715,6 +728,38 @@ int caamBlob(DESCSTRUCT* desc) CAAM AES Operations ****************************************************************************/ +static void caamAddFIFOL(DESCSTRUCT* desc, void* in, int inSz, + unsigned int flush) +{ + /* if size is larger than short type then use extended length option */ + if (inSz > 0xFFFF) { + desc->desc[desc->idx++] = (CAAM_FIFO_L | flush | FIFOS_EXT | + CAAM_CLASS1 | FIFOL_TYPE_MSG); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(in, inSz); + desc->desc[desc->idx++] = inSz; + } + else { + desc->desc[desc->idx++] = (CAAM_FIFO_L | flush | + CAAM_CLASS1 | FIFOL_TYPE_MSG) + inSz; + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(in, inSz); + } +} + + +static void caamAddFIFOS(DESCSTRUCT* desc, void* out, int outSz) +{ + /* if size is larger than short type then use extended length option */ + if (outSz > 0xFFFF) { + desc->desc[desc->idx++] = CAAM_FIFO_S | FIFOS_TYPE_MSG | FIFOS_EXT; + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(out, outSz); + desc->desc[desc->idx++] = outSz; + } + else { + desc->desc[desc->idx++] = (CAAM_FIFO_S | FIFOS_TYPE_MSG) + outSz; + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(out, outSz); + } +} + int caamAesCmac(DESCSTRUCT* desc, int sz, unsigned int args[4]) { Error err; @@ -744,15 +789,7 @@ int caamAesCmac(DESCSTRUCT* desc, int sz, unsigned int args[4]) vaddr[vidx] = CAAM_ADR_MAP(desc->buf[0].data, desc->buf[0].dataSz + macSz, 1); desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], desc->buf[0].dataSz + macSz); - #if 0 - { - unsigned int p; byte* pt = (byte*)vaddr[vidx]; - printf("Using key [%d]:", desc->buf[0].dataSz + macSz); - for (p = 0; p < keySz; p++) - printf("%02X", pt[p]); - printf("\n"); - } - #endif + DEBUG_PRINT_ARRAY(vaddr[vidx], keySz, "AES CMAC Key"); vidx++; /* Load in CTX only when not initialization */ @@ -761,16 +798,7 @@ int caamAesCmac(DESCSTRUCT* desc, int sz, unsigned int args[4]) desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS1 | ofst) + desc->buf[1].dataSz; desc->desc[desc->idx++] = ctx; - - #if 0 - { - unsigned int z; byte* pt = (byte*)vaddr[0]; - printf("loading in CTX [%d] :", desc->buf[1].dataSz); - for (z = 0; z < 32; z++) - printf("%02X", pt[z]); - printf("\n"); - } - #endif + DEBUG_PRINT_ARRAY(vaddr[0], 32, "AES CMAC CTX"); } /* add protinfo to operation command */ @@ -789,17 +817,7 @@ int caamAesCmac(DESCSTRUCT* desc, int sz, unsigned int args[4]) vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], desc->buf[i].dataSz); - - #if 0 - { - unsigned int z; byte* pt = (byte*)vaddr[vidx]; - printf("MSG [%d] :", desc->buf[i].dataSz); - for (z = 0; z < desc->buf[i].dataSz; z++) - printf("%02X", pt[z]); - printf("\n"); - } - #endif - + DEBUG_PRINT_ARRAY(vaddr[vidx], desc->buf[i].dataSz, "AES CMAC Input"); vidx++; } @@ -819,16 +837,7 @@ int caamAesCmac(DESCSTRUCT* desc, int sz, unsigned int args[4]) do { err = caamDoJob(desc); } while (err == CAAM_WAITING); - - #if 0 - { - unsigned int z; byte* pt = (byte*)vaddr[0]; - printf("CTX: "); - for (z = 0; z < 32; z++) - printf("%02X", pt[z]); - printf("\n"); - } - #endif + DEBUG_PRINT_ARRAY(vaddr[0], 32, "AES CMAC CTX"); vidx = 0; CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[1].data, desc->buf[1].dataSz, 1); @@ -847,6 +856,281 @@ int caamAesCmac(DESCSTRUCT* desc, int sz, unsigned int args[4]) } +int caamAead(DESCSTRUCT* desc, CAAM_BUFFER* buf, unsigned int args[4]) +{ + int fifol = 0; /* last index for FIFO */ + Value ofst = 0; + Error err; + int ivSz = 0; + void *iv, *key, *in, *out, *tag; + int keySz; + int tagSz; + int inSz; + int outSz; + int idx = 0; + void* aadCtxBuf = NULL; + int state = CAAM_ALG_INITF; /* single shot mode */ + unsigned int aadSz; + + if (desc->state != CAAM_ENC && desc->state != CAAM_DEC) { + return CAAM_ARGS_E; + } + + keySz = buf[idx].Length; + if (keySz != 16 && keySz != 24 && keySz != 32) { + WOLFSSL_MSG("Bad AES key size found"); + return CAAM_ARGS_E; + } + aadSz = (args[0] >> 16) & 0xFFFF; + + /* map and copy over key */ + key = (void*)buf[idx].TheAddress; + desc->desc[desc->idx++] = (CAAM_KEY | CAAM_CLASS1 | CAAM_NWB) + keySz; + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(key, keySz); + DEBUG_PRINT_ARRAY(key, keySz, "AES AEAD Key"); + idx++; + + /* write operation, in the case of decryption add IVC to check tag */ + desc->desc[desc->idx] = CAAM_OP | CAAM_CLASS1 | desc->type | + state | desc->state; + if (desc->state == CAAM_DEC) { + desc->desc[desc->idx] |= CAAM_ALG_IVC; + } + desc->idx++; + + /* get IV if needed by algorithm */ + switch (desc->type) { + case CAAM_AESGCM: + { + ivSz = buf[idx].Length; + iv = (void*)buf[idx].TheAddress; + fifol = desc->idx; + desc->desc[desc->idx++] = (CAAM_FIFO_L | CAAM_CLASS1 | + FIFOL_TYPE_FC1 | FIFOL_TYPE_IV) + ivSz; + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(iv, ivSz); + idx++; + } + break; + + case CAAM_AESCCM: + { + ivSz = buf[idx].Length; + iv = (void*)buf[idx].TheAddress; + desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS1 | ofst) + + ivSz; + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(iv, ivSz); + idx++; + } + break; + + default: + WOLFSSL_MSG("Mode of AES not implemented"); + return CAAM_ARGS_E; + } + DEBUG_PRINT_ARRAY(iv, ivSz, "AES AEAD IV"); + + /* get input */ + inSz = buf[idx].Length; + in = (void*)buf[idx].TheAddress; + DEBUG_PRINT_ARRAY(in, inSz, "AES AEAD Input"); + idx++; + + /* set output */ + outSz = buf[idx].Length; + out = (void*)buf[idx].TheAddress; + idx++; + + /* TAG in/out */ + tagSz = buf[idx].Length; + tag = (void*)buf[idx].TheAddress; + idx++; + + /* set aad if present */ + if (aadSz > 0) { + /* special AAD size setup of context register for CCM mode */ + if (desc->type == CAAM_AESCCM) { + unsigned char* pt; + + aadCtxBuf = CAAM_ADR_MAP(0, 4, 0); + pt = (unsigned char*)aadCtxBuf; + memset(pt, 0, 4); + if (aadSz <= 0xFEFF) { + pt[0] = (aadSz & 0xFF00) >> 8; + pt[1] = (aadSz & 0x00FF); + desc->desc[desc->idx++] = (CAAM_FIFO_L | CAAM_CLASS1 | + FIFOL_TYPE_AAD) + 2; + } + else { + pt[0] = (aadSz >> 24) & 0xFF; + pt[1] = (aadSz >> 16) & 0xFF; + pt[2] = (aadSz >> 8 ) & 0xFF; + pt[3] = aadSz & 0xFF; + fifol = desc->idx; + desc->desc[desc->idx++] = (CAAM_FIFO_L | CAAM_CLASS1 | + FIFOL_TYPE_AAD) + 4; + } + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(aadCtxBuf, 4); + CAAM_ADR_SYNC(aadCtxBuf, 4); + } + + /* Load in AAD */ + fifol = desc->idx; + desc->desc[desc->idx++] = (CAAM_FIFO_L | CAAM_CLASS1 | FIFOL_TYPE_FC1 | + FIFOL_TYPE_AAD) + aadSz; + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL((void*)buf[idx].TheAddress, + buf[idx].Length); + DEBUG_PRINT_ARRAY((void*)buf[idx].TheAddress, aadSz, "AES AEAD AAD"); + idx++; + } + + /* set input/output in descriptor */ + if (outSz > 0) { + caamAddFIFOS(desc, out, outSz); + } + + if (inSz > 0) { + fifol = desc->idx; + caamAddFIFOL(desc, in, inSz, FIFOL_TYPE_FC1); + } + + if (desc->state == CAAM_DEC) { + fifol = desc->idx; + desc->desc[desc->idx++] = (CAAM_FIFO_L | FIFOL_TYPE_FC1 | + CAAM_CLASS1 | FIFOL_TYPE_IVC) + tagSz; + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(tag, tagSz); + } + + /* remove FC1 and set LC1 for last FIFO load */ + desc->desc[fifol] &= ~FIFOL_TYPE_FC1; + desc->desc[fifol] |= FIFOL_TYPE_LC1; + + /* store updated IV / MAC */ + if (desc->state == CAAM_ENC) { + switch (desc->type) { + case CAAM_AESGCM: + desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS1 | tagSz; + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(tag, tagSz); + break; + + case CAAM_AESCCM: + desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS1 | + (32 << 8) | tagSz; + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(tag, tagSz); + break; + } + } + + do { + err = caamDoJob(desc); + } while (err == CAAM_WAITING); + + if (aadCtxBuf != NULL) + CAAM_ADR_UNMAP(aadCtxBuf, 0, 4, 0); + + DEBUG_PRINT_ARRAY(tag, tagSz, "AES AEAD Tag Out"); + DEBUG_PRINT_ARRAY(out, outSz, "AES AEAD Output"); + return err; +} + + +/* AES operations follow the buffer sequence of KEY -> (IV) -> Input -> Output + */ +int caamAes(DESCSTRUCT* desc, CAAM_BUFFER* buf, unsigned int args[4]) +{ + Value ofst = 0; + Error err; + int ivSz = 0; + void *iv = NULL, *key, *in, *out; + int keySz; + int inSz; + int outSz; + int idx = 0; + int state = CAAM_ALG_UPDATE; + + if (desc->state != CAAM_ENC && desc->state != CAAM_DEC) { + return CAAM_ARGS_E; + } + + keySz = buf[idx].Length; + if (keySz != 16 && keySz != 24 && keySz != 32) { + WOLFSSL_MSG("Bad AES key size found"); + return CAAM_ARGS_E; + } + + /* map and copy over key */ + key = (void*)buf[idx].TheAddress; + desc->desc[desc->idx++] = (CAAM_KEY | CAAM_CLASS1 | CAAM_NWB) + keySz; + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(key, keySz); + idx++; + + /* get IV if needed by algorithm */ + switch (desc->type) { + case CAAM_AESECB: + break; + + case CAAM_AESCTR: + ofst = 0x00001000; + /* fall through because states are the same only the offset changes */ + + case CAAM_AESCBC: + { + int maxSz = 16; /* default to CBC/CTR max size */ + + ivSz = buf[idx].Length; + if (ivSz != maxSz) { + WOLFSSL_MSG("Invalid AES-CBC IV size\n"); + return CAAM_ARGS_E; + } + + iv = (void*)buf[idx].TheAddress; + desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS1 | ofst) + maxSz; + desc->desc[desc->idx++] = (CAAM_ADDRESS)CAAM_ADR_TO_PHYSICAL(iv, ivSz); + idx++; + } + break; + + default: + WOLFSSL_MSG("Mode of AES not implemented"); + return CAAM_ARGS_E; + } + + /* write operation */ + desc->desc[desc->idx++] = CAAM_OP | CAAM_CLASS1 | desc->type | + state | desc->state; + + /* get input */ + inSz = buf[idx].Length; + in = (void*)buf[idx].TheAddress; + idx++; + + /* set output */ + outSz = buf[idx].Length; + out = (void*)buf[idx].TheAddress; + idx++; + + /* set input/output in descriptor */ + caamAddFIFOL(desc, in, inSz, FIFOL_TYPE_LC1); + caamAddFIFOS(desc, out, outSz); + + /* store updated IV */ + switch (desc->type) { + case CAAM_AESCBC: + case CAAM_AESCTR: + if (ivSz > 0) { + desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS1 | ofst | 16; + desc->desc[desc->idx++] = (CAAM_ADDRESS)CAAM_ADR_TO_PHYSICAL(iv, ivSz); + } + break; + } + + do { + err = caamDoJob(desc); + } while (err == CAAM_WAITING); + + return err; +} + + /* ECDSA generate black key * * return Success on success. All other return values are considered a fail @@ -869,7 +1153,9 @@ int caamECDSAMake(DESCSTRUCT* desc, CAAM_BUFFER* buf, unsigned int args[4]) vaddr[1] = NULL; desc->desc[desc->idx++] = pdECDSEL; - if (isBlackKey == 1) { + if (isBlackKey == CAAM_BLACK_KEY_SM) { + unsigned char* pt; + /* create secure partition for private key out */ part = caamFindUnusedPartition(); if (part < 0) { @@ -878,7 +1164,7 @@ int caamECDSAMake(DESCSTRUCT* desc, CAAM_BUFFER* buf, unsigned int args[4]) } /* create and claim the partition */ - err = caamCreatePartition(part, part, CAAM_SM_CSP | CAAM_SM_SMAP_LOCK | + err = caamCreatePartition(&part, part, CAAM_SM_CSP | CAAM_SM_SMAP_LOCK | CAAM_SM_CSP | CAAM_SM_ALL_RW); if (err != Success) { WOLFSSL_MSG("error creating partition for secure ecc key"); @@ -887,36 +1173,39 @@ int caamECDSAMake(DESCSTRUCT* desc, CAAM_BUFFER* buf, unsigned int args[4]) /* map secure partition to virtual address */ phys = (CAAM_PAGE + (part << 12)); - buf[0].TheAddress = phys; + pt = (unsigned char*)buf[0].TheAddress; + pt[0] = (phys >> 24) & 0xFF; + pt[1] = (phys >> 16) & 0xFF; + pt[2] = (phys >> 8) & 0xFF; + pt[3] = (phys) & 0xFF; desc->desc[desc->idx++] = phys; - - /* public x,y out */ - buf[1].TheAddress = buf[0].TheAddress + BLACK_KEY_MAC_SZ + buf[0].Length; - desc->desc[desc->idx++] = phys + BLACK_KEY_MAC_SZ + buf[0].Length; } else { vaddr[0] = CAAM_ADR_MAP(0, buf[0].Length, 0); desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[0], buf[0].Length); - vaddr[1] = CAAM_ADR_MAP(0, buf[1].Length, 0); - desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[1], buf[1].Length); } + vaddr[1] = CAAM_ADR_MAP(0, buf[1].Length, 0); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[1], buf[1].Length); /* add protinfo to operation command */ desc->startIdx = desc->idx; /* add operation command OPTYPE PROTOID */ desc->desc[desc->idx] = CAAM_OP | CAAM_PROT_UNIDI | desc->type; - if (isBlackKey == 1) { + if (isBlackKey == CAAM_BLACK_KEY_SM || isBlackKey == CAAM_BLACK_KEY_CCM) { desc->desc[desc->idx] |= CAAM_PKHA_ENC_PRI_AESCCM; } + if (isBlackKey == CAAM_BLACK_KEY_ECB) { + desc->desc[desc->idx] |= CAAM_PKHA_ENC_PRI_AESECB; + } desc->desc[desc->idx++] |= CAAM_PKHA_ECC; do { err = caamDoJob(desc); } while (err == CAAM_WAITING); - if (isBlackKey == 1) { + if (isBlackKey == CAAM_BLACK_KEY_SM) { /* store partition number holding black keys */ if (err != Success) caamFreePart(part); @@ -926,8 +1215,8 @@ int caamECDSAMake(DESCSTRUCT* desc, CAAM_BUFFER* buf, unsigned int args[4]) else { /* copy non black keys out to buffers */ CAAM_ADR_UNMAP(vaddr[0], buf[0].TheAddress, buf[0].Length, 1); - CAAM_ADR_UNMAP(vaddr[1], buf[1].TheAddress, buf[1].Length, 1); } + CAAM_ADR_UNMAP(vaddr[1], buf[1].TheAddress, buf[1].Length, 1); return err; } @@ -970,7 +1259,7 @@ int caamECDSAVerify(DESCSTRUCT* desc, CAAM_BUFFER* buf, int sz, } /* public key */ - if (!isBlackKey) { + if (isBlackKey != CAAM_BLACK_KEY_SM) { vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], desc->buf[i].dataSz); @@ -1069,7 +1358,7 @@ int caamECDSASign(DESCSTRUCT* desc, int sz, unsigned int args[4]) desc->desc[desc->idx++] = pdECDSEL; /* private key */ - if (isBlackKey != 1) { + if (isBlackKey != CAAM_BLACK_KEY_SM) { vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], desc->buf[i].dataSz); @@ -1114,9 +1403,14 @@ int caamECDSASign(DESCSTRUCT* desc, int sz, unsigned int args[4]) /* add operation command OPTYPE PROTOID */ desc->desc[desc->idx] = CAAM_OP | CAAM_PROT_UNIDI | desc->type; - if (isBlackKey) { /* set flag to use AES-CCM with black key */ + if (isBlackKey == CAAM_BLACK_KEY_SM || isBlackKey == CAAM_BLACK_KEY_CCM) { + /* set flag to use AES-CCM with black key */ desc->desc[desc->idx] |= CAAM_PKHA_ENC_PRI_AESCCM; } + if (isBlackKey == CAAM_BLACK_KEY_ECB) { + /* set flag to use AES-ECB with black key */ + desc->desc[desc->idx] |= CAAM_PKHA_ENC_PRI_AESECB; + } /* add protinfo to operation command */ desc->desc[desc->idx++] |= CAAM_ECDSA_MESREP_HASHED | CAAM_PKHA_ECC; @@ -1126,7 +1420,7 @@ int caamECDSASign(DESCSTRUCT* desc, int sz, unsigned int args[4]) } while (err == CAAM_WAITING); vidx = 0; i = 0; - if (!isBlackKey) { + if (isBlackKey != CAAM_BLACK_KEY_SM) { CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0); } i++; @@ -1172,20 +1466,12 @@ int caamECDSA_ECDH(DESCSTRUCT* desc, int sz, unsigned int args[4]) } /* public key */ - if (!peerBlackKey) { + if (peerBlackKey != CAAM_BLACK_KEY_SM) { vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], desc->buf[i].dataSz); - #if 0 - { - unsigned int z; byte* pt; - printf("pubkey :"); - pt = (byte*)desc->buf[i].data; - for (z = 0; z < desc->buf[i].dataSz; z++) - printf("%02X", pt[z]); - printf("\n"); - } - #endif + DEBUG_PRINT_ARRAY((void*)desc->buf[i].data, desc->buf[i].dataSz, + "ECDH Public Key"); vidx++; } else { @@ -1194,20 +1480,22 @@ int caamECDSA_ECDH(DESCSTRUCT* desc, int sz, unsigned int args[4]) i++; /* private key */ - if (isBlackKey != 1) { - vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); - desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], - desc->buf[i].dataSz); - #if 0 - { - unsigned int z; byte* pt; - printf("private :"); - pt = (byte*)desc->buf[i].data; - for (z = 0; z < desc->buf[i].dataSz; z++) - printf("%02X", pt[z]); - printf("\n"); + if (isBlackKey != CAAM_BLACK_KEY_SM) { + if (isBlackKey == CAAM_BLACK_KEY_CCM) { + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz + + BLACK_KEY_MAC_SZ, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz + BLACK_KEY_MAC_SZ); + DEBUG_PRINT_ARRAY((void*)desc->buf[i].data, desc->buf[i].dataSz + + BLACK_KEY_MAC_SZ, "ECDH Private Key w/CCM "); + } + else { + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + DEBUG_PRINT_ARRAY((void*)desc->buf[i].data, desc->buf[i].dataSz, + "ECDH Private Key"); } - #endif vidx++; } else { @@ -1226,9 +1514,12 @@ int caamECDSA_ECDH(DESCSTRUCT* desc, int sz, unsigned int args[4]) /* add operation command OPTYPE PROTOID */ desc->desc[desc->idx] = CAAM_OP | CAAM_PROT_UNIDI | desc->type; - if (isBlackKey == 1) { + if (isBlackKey == CAAM_BLACK_KEY_SM || isBlackKey == CAAM_BLACK_KEY_CCM) { desc->desc[desc->idx] |= CAAM_PKHA_ENC_PRI_AESCCM; } + if (isBlackKey == CAAM_BLACK_KEY_ECB) { + desc->desc[desc->idx] |= CAAM_PKHA_ENC_PRI_AESECB; + } /* add protinfo to operation command */ desc->desc[desc->idx++] |= CAAM_PKHA_ECC; @@ -1250,7 +1541,7 @@ int caamECDSA_ECDH(DESCSTRUCT* desc, int sz, unsigned int args[4]) } i++; - if (isBlackKey != 1) { + if (isBlackKey != CAAM_BLACK_KEY_SM) { CAAM_ADR_UNMAP(vaddr[vidx], desc->buf[i].data, desc->buf[i].dataSz, 0); vidx++; } @@ -1271,7 +1562,7 @@ int caamECDSA_ECDH(DESCSTRUCT* desc, int sz, unsigned int args[4]) IODevice Start, Transfer and Finish Buffer ****************************************************************************/ /* If Entropy is not ready then return CAAM_WAITING */ -int caamTRNG(unsigned char *out, int outSz) +static int caamTRNG(unsigned char *out, int outSz) { int sz = 0; @@ -1321,6 +1612,39 @@ int caamTRNG(unsigned char *out, int outSz) } +/* out is the virtual address to store resulting RNG data in */ +static int caamRNG(unsigned char *out, int outSz) +{ + DESCSTRUCT desc; + int ret; + + /* set up the job description for RNG initialization */ + caamDescInit(&desc, 0, NULL, NULL, 0); + desc.desc[desc.idx++] = CAAM_OP | CAAM_CLASS1 | CAAM_RNG; + desc.desc[desc.idx++] = (CAAM_FIFO_S | FIFOS_TYPE_RNG) + outSz; + desc.desc[desc.idx++] = CAAM_ADR_TO_PHYSICAL(out, outSz); + + do { + ret = caamDoJob(&desc); + } while (ret == CAAM_WAITING); + + return ret; +} + + +int caamEntropy(unsigned char *out, int outSz) +{ + if (caam.vrs < 9) { + /* can access TRNG directly */ + return caamTRNG(out, outSz); + } + else { + /* use CAAM RNG as source of entropy */ + return caamRNG(out, outSz); + } +} + + /* cover a plain text key and make it a black key */ int caamKeyCover(DESCSTRUCT* desc, int sz, unsigned int args[4]) { @@ -1393,8 +1717,8 @@ void caamDescInit(DESCSTRUCT* desc, int type, unsigned int args[4], desc->inputSz = 0; } else { - desc->state = args[0]; - desc->ctxSz = args[1]; + desc->state = args[0] & 0xFFFF; + desc->ctxSz = args[1] & 0xFFFF; desc->inputSz = args[2]; } desc->aadSz = 0; @@ -1409,110 +1733,101 @@ void caamDescInit(DESCSTRUCT* desc, int type, unsigned int args[4], } +static int SetupJobRing(struct JobRing* r) +{ + /* get enviornment specific addresses to use for job rings */ + CAAM_SET_JOBRING_ADDR(&r->BaseAddr, &r->JobIn, &r->VirtualIn); + + /* register the in/out and sizes of job ring */ + r->JobOut = r->JobIn + (CAAM_JOBRING_SIZE * sizeof(unsigned int)); + r->Desc = r->JobOut + (2 * CAAM_JOBRING_SIZE * sizeof(unsigned int)); + + CAAM_INIT_MUTEX(&caam.ring.jr_lock); + + r->VirtualOut = r->VirtualIn + (CAAM_JOBRING_SIZE * sizeof(unsigned int)); + r->VirtualDesc = r->VirtualOut + (2 * CAAM_JOBRING_SIZE * sizeof(unsigned int)); + + memset(r->VirtualIn, 0, CAAM_JOBRING_SIZE * sizeof(unsigned int)); + memset(r->VirtualOut, 0, 2 * CAAM_JOBRING_SIZE * sizeof(unsigned int)); + memset(r->VirtualDesc, 0, CAAM_DESC_MAX * CAAM_JOBRING_SIZE); + + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("Setting JOB IN 0x%08X\n", (unsigned int)caam.ring.JobIn); + printf("Setting JOB OUT 0x%08X\n", (unsigned int)caam.ring.JobOut); + printf("Setting DESC 0x%08X\n", (unsigned int)caam.ring.Desc); + #endif + + /* set the job ring in/out address's */ + CAAM_WRITE(r->BaseAddr + CAAM_IRBAR0, r->JobIn); + CAAM_WRITE(r->BaseAddr + CAAM_ORBAR, r->JobOut); + + /* Initialize job ring sizes */ + CAAM_WRITE(r->BaseAddr + CAAM_IRSR0, CAAM_JOBRING_SIZE); + CAAM_WRITE(r->BaseAddr + CAAM_ORSR0, CAAM_JOBRING_SIZE); + + /* if the job ring is busy, park it, flush it, and reset it */ + if (((CAAM_READ(r->BaseAddr + CAAM_STATUS) & 0x00000001) != 0) && + (CAAM_READ(r->BaseAddr + JRINTR_JR) != 0)) { + unsigned int reg; + + /* JRCR job ring command register */ + CAAM_WRITE(r->BaseAddr + JRCR_JR, 0x2); /* park it */ + CAAM_WRITE(r->BaseAddr + JRCR_JR, 0x1); /* flush it */ + do { + reg = CAAM_READ(r->BaseAddr + JRINTR_JR); + } while (!(reg & 0x8) && (reg != 0)); /* bit 3 hot signals is halted */ + + if (reg != 0) { + CAAM_WRITE(r->BaseAddr + JRCR_JR, 0x1); /* reset it */ + } + } + return 0; +} + + int InitCAAM(void) { Error ret; /* map to memory addresses needed for accessing CAAM */ - ret = CAAM_SET_BASEADDR(); + ret = CAAM_SET_BASEADDR(&caam.baseAddr); if (ret != 0) { return ret; } + ret = SetupJobRing(&caam.ring); + if (ret != 0) { + WOLFSSL_MSG("Error initializing job ring"); + INTERRUPT_Panic(); + return ret; + } + + /* get CHA era */ + caam.vrs = CAAM_READ(caam.ring.BaseAddr + CAAM_CHA_CCBVID) >> 24; #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) - printf("CHANUM_MS = 0x%08X\n", CAAM_READ(0x0FF0)); - printf("DECO0MIDR_MS = 0x%08X\n", CAAM_READ(0x00A0)); - printf("SCFGR = 0x%08X\n", CAAM_READ(0x000C)); - print_jdkek(); - printSecureMemoryInfo(); - printf("JR0MIDR_MS, _LS = 0x%08X , 0x%08X\n", CAAM_READ(0x0010), - CAAM_READ(0x0014)); - printf("JR1MIDR_MS, _LS = 0x%08X , 0x%08X\n", CAAM_READ(0x0018), - CAAM_READ(0x001C)); - printf("JR2MIDR_MS, _LS = 0x%08X , 0x%08X\n", CAAM_READ(0x0020), - CAAM_READ(0x0024)); + printf("CAAM version = %04X\n", + CAAM_READ(caam.ring.BaseAddr + CAAM_VERSION_MS) & 0xFFFF); + printf("CAAM era = %d\n", caam.vrs); + printf("RNG revision number = %08X\n", + CAAM_READ(caam.ring.BaseAddr + CAAM_CRNR_LS)); + printSecureMemoryInfo(); #endif - ret = Failure; - for (caam.ring.page = 1; caam.ring.page < 7; - caam.ring.page = caam.ring.page + 1) { - ret = caamCreatePartition(caam.ring.page, caam.ring.page, - CAAM_SM_CSP | CAAM_SM_ALL_RW); - if (ret == Success) - break; - } - if (ret != Success) { - WOLFSSL_MSG("Failed to find a partition on startup"); - INTERRUPT_Panic(); - return -1; + /* when on i.MX8 with SECO the SECO has control of this */ + if (caam.vrs < 9) { + /* set DECO watchdog to time out and flush jobs that cause the DECO to + hang */ + CAAM_WRITE(caam.baseAddr + CAAM_RSTA, + CAAM_READ(caam.baseAddr + CAAM_RSTA) | 0x40000000); + + /* start up RNG if not already started */ + if (caamInitRng(&caam) != 0) { + WOLFSSL_MSG("Error initializing RNG"); + INTERRUPT_Panic(); + return -1; + } } - caam.ring.JobIn = CAAM_PAGE + (caam.ring.page << 12U); - caam.ring.JobOut = caam.ring.JobIn + (CAAM_JOBRING_SIZE * - sizeof(unsigned int)); - caam.ring.Desc = caam.ring.JobOut + (2 * CAAM_JOBRING_SIZE * - sizeof(unsigned int)); - - CAAM_INIT_MUTEX(&caam.ring.jr_lock); - - caam.ring.VirtualIn = mmap_device_memory(NULL, - CAAM_JOBRING_SIZE * sizeof(unsigned int), - PROT_READ | PROT_WRITE | PROT_NOCACHE, - MAP_SHARED | MAP_PHYS, caam.ring.JobIn); - if (caam.ring.VirtualIn == MAP_FAILED) { - WOLFSSL_MSG("Error mapping virtual in"); - INTERRUPT_Panic(); - return -1; - } - memset(caam.ring.VirtualIn, 0, CAAM_JOBRING_SIZE * sizeof(unsigned int)); - caam.ring.VirtualOut = mmap_device_memory(NULL, - 2 * CAAM_JOBRING_SIZE * sizeof(unsigned int), - PROT_READ | PROT_WRITE | PROT_NOCACHE, - MAP_SHARED | MAP_PHYS, caam.ring.JobOut); - if (caam.ring.VirtualOut == MAP_FAILED) { - WOLFSSL_MSG("Error mapping virtual out"); - INTERRUPT_Panic(); - return -1; - } - memset(caam.ring.VirtualOut, 0, 2 * CAAM_JOBRING_SIZE * sizeof(unsigned int)); - caam.ring.VirtualDesc = mmap_device_memory(NULL, - CAAM_DESC_MAX * CAAM_JOBRING_SIZE, - PROT_READ | PROT_WRITE | PROT_NOCACHE, - MAP_SHARED | MAP_PHYS, caam.ring.Desc); - if (caam.ring.VirtualDesc == MAP_FAILED) { - WOLFSSL_MSG("Error mapping virtual desc"); - INTERRUPT_Panic(); - return -1; - } - memset(caam.ring.VirtualDesc, 0, CAAM_DESC_MAX * CAAM_JOBRING_SIZE); - - #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) - printf("extra wolfssl debug - Setting JOB IN 0x%08X\n", caam.ring.JobIn); - printf("extra wolfssl debug - Setting JOB OUT 0x%08X\n", caam.ring.JobOut); - printf("extra wolfssl debug - Setting DESC 0x%08X\n", caam.ring.Desc); - #endif - CAAM_WRITE(CAAM_IRBAR0, caam.ring.JobIn); - CAAM_WRITE(CAAM_ORBAR0, caam.ring.JobOut); - - /* Initialize job ring sizes */ - CAAM_WRITE(CAAM_IRSR0, CAAM_JOBRING_SIZE); - CAAM_WRITE(CAAM_ORSR0, CAAM_JOBRING_SIZE); - - /* set DECO watchdog to time out and flush jobs that cause the DECO to hang */ - CAAM_WRITE(0x0004, CAAM_READ(0x0004) | 0x40000000); - - /* start up RNG if not already started */ - if (caamInitRng(&caam) != 0) { - WOLFSSL_MSG("Error initializing RNG"); - INTERRUPT_Panic(); - return -1; - } - - #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) - print_jdkek(); - printf("FADR = 0x%08X\n", CAAM_READ(0x0FCC)); - printf("RTMCTL = 0x%08X\n", CAAM_READ(0x0600)); - #endif WOLFSSL_MSG("Successfully initilazed CAAM driver"); #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) fflush(stdout); @@ -1523,8 +1838,10 @@ int InitCAAM(void) int CleanupCAAM() { + CAAM_UNSET_JOBRING_ADDR(caam.ring.BaseAddr, caam.ring.JobIn, + caam.ring.VirtualIn); CAAM_FREE_MUTEX(&caam.ring.jr_lock); - CAAM_UNSET_BASEADDR(); + CAAM_UNSET_BASEADDR(caam.baseAddr); caamFreeAllPart(); return 0; } diff --git a/wolfcrypt/src/port/caam/caam_error.c b/wolfcrypt/src/port/caam/caam_error.c index 8219d1990..f88283ebe 100644 --- a/wolfcrypt/src/port/caam/caam_error.c +++ b/wolfcrypt/src/port/caam/caam_error.c @@ -36,6 +36,10 @@ int caamParseCCBError(unsigned int error) case 1: WOLFSSL_MSG("\tCHAID: AESA"); + switch (error & 0xF) { + case 0xC: + WOLFSSL_MSG("\tAAD size error"); + } break; case 2: @@ -55,23 +59,23 @@ int caamParseCCBError(unsigned int error) ret = -1; /* treat RNG errors as fatal */ switch(error & 0xF) { case 3: - WOLFSSL_MSG(" RNG instantiate error"); + WOLFSSL_MSG("\tRNG instantiate error"); break; case 4: - WOLFSSL_MSG(" RNG not instantiated error"); + WOLFSSL_MSG("\tRNG not instantiated error"); break; case 5: - WOLFSSL_MSG(" RNG test instantiate error"); + WOLFSSL_MSG("\tRNG test instantiate error"); break; case 6: - WOLFSSL_MSG(" RNG prediction resistance error"); + WOLFSSL_MSG("\tRNG prediction resistance error"); break; default: - WOLFSSL_MSG(" Unknown"); + WOLFSSL_MSG("\tUnknown"); } break; @@ -208,4 +212,17 @@ unsigned int caamParseJRError(unsigned int error) 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 diff --git a/wolfcrypt/src/port/caam/caam_qnx.c b/wolfcrypt/src/port/caam/caam_qnx.c index bf6a62994..ac6aa2ef2 100644 --- a/wolfcrypt/src/port/caam/caam_qnx.c +++ b/wolfcrypt/src/port/caam/caam_qnx.c @@ -23,6 +23,10 @@ #include #endif +/* settings.h is only included for wolfSSL version and IAR build warnings + * wolfssl/wolfcrypt/- path includes other than + * wolfssl/wolfcrypt/port/caam/caam_* should be avoided!! */ +#define WC_NO_HARDEN /* silence warning, it is irrelavent here */ #include #if defined(__QNX__) || defined(__QNXNTO__) @@ -67,37 +71,86 @@ int io_close_ocb(resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb); /* read the contents at offset from BASE address */ -unsigned int CAAM_READ(unsigned int ofst) { - return in32(virtual_base + ofst); +unsigned int CAAM_READ(CAAM_ADDRESS reg) { + return in32(reg); } /* takes in offset from BASE address */ -void CAAM_WRITE(unsigned int ofst, unsigned int in) +void CAAM_WRITE(CAAM_ADDRESS reg, unsigned int in) { - out32(virtual_base + ofst, in); + out32(reg, in); } /* Sets the base address to use for read/write * returns 0 on success */ -int CAAM_SET_BASEADDR() +int CAAM_SET_BASEADDR(CAAM_ADDRESS* baseAddr) { +#ifndef __aarch64__ + void* vaddr; + /* address range for CAAM is CAAM_BASE plus 0x10000 */ - virtual_base = mmap_device_io(0x00010000, CAAM_BASE); - if (virtual_base == (uintptr_t)MAP_FAILED) { + vaddr = mmap_device_io(0x0000FFFF, CAAM_BASE); + if (vaddr == (uintptr_t)MAP_FAILED) { WOLFSSL_MSG("Unable to map virtual memory"); return -1; } + *baseAddr = (CAAM_ADDRESS)vaddr; +#endif + return 0; } -/* cleans up having set the base address */ -void CAAM_UNSET_BASEADDR() +int CAAM_SET_JOBRING_ADDR(CAAM_ADDRESS* base, CAAM_ADDRESS* ringInPhy, + void** ringInVir) { - munmap_device_io(virtual_base, 0x00010000); + void* vaddr; + +#ifdef __aarch64__ + /* if on an AArch64 system make assumption that it is an i.MX8 QXP */ + /* use block of memory set aside for job ring 2 */ + /* try to map to job rings 2 address */ + *base = mmap_device_io(0x0000FFFF, CAAM_BASE + 0x00030000); +#else + /* try to map to job rings 1 address */ + *base = mmap_device_io(0x0000FFFF, CAAM_BASE + 0x00001000); +#endif + if (*base == (uintptr_t)MAP_FAILED) { + WOLFSSL_MSG("Unable to map virtual memory"); + return -1; + } + + /* create DMA buffer for job rings */ + vaddr = mmap(0, 1024, PROT_READ | PROT_WRITE | PROT_NOCACHE, + MAP_SHARED | MAP_PHYS | MAP_ANON, NOFD, 0); + if (vaddr == (void*)MAP_FAILED) { + WOLFSSL_MSG("mmap failed\n"); + return -1; + } + + *ringInPhy = CAAM_ADR_TO_PHYSICAL(vaddr, 1024); + *ringInVir = vaddr; + return 0; +} + + +void CAAM_UNSET_JOBRING_ADDR(CAAM_ADDRESS base, CAAM_ADDRESS ringInPhy, + void* ringInVir) +{ + munmap_device_io(base, 0x0000FFFF); + munmap(ringInVir, 1024); +} + + +/* cleans up having set the base address */ +void CAAM_UNSET_BASEADDR(CAAM_ADDRESS baseAddr) +{ +#ifndef __aarch64__ + munmap_device_io(baseAddr, 0x0000FFFF); +#endif } /* convert a virtual address to a physical address @@ -145,7 +198,7 @@ CAAM_ADDRESS CAAM_ADR_TO_VIRTUAL(CAAM_ADDRESS in, int len) /* map a virtual address to a created coherent physical address * returns the mapped address on success */ -void* CAAM_ADR_MAP(unsigned int in, int inSz, unsigned char copy) +void* CAAM_ADR_MAP(CAAM_ADDRESS in, int inSz, unsigned char copy) { int sz; void *vaddr; @@ -162,10 +215,11 @@ void* CAAM_ADR_MAP(unsigned int in, int inSz, unsigned char copy) #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) perror("Failed to map memory : "); #endif + return NULL; } else { if (copy && in != 0 && inSz > 0) { - memcpy((unsigned char*)vaddr, (unsigned char*)in, inSz); + memcpy(vaddr, (void*)in, inSz); } if (msync(vaddr, sz, MS_SYNC) != 0) { @@ -177,7 +231,7 @@ void* CAAM_ADR_MAP(unsigned int in, int inSz, unsigned char copy) /* un map address, should be called when done with a mapped address */ -void CAAM_ADR_UNMAP(void* vaddr, unsigned int out, int outSz, +void CAAM_ADR_UNMAP(void* vaddr, CAAM_ADDRESS out, int outSz, unsigned char copy) { int sz; @@ -232,6 +286,11 @@ int CAAM_ADR_SYNC(void* vaddr, int sz) #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_AESCBC __DIOTF(_DCMD_ALL, CAAM_AESCBC, iov_t) +#define WC_CAAM_AESCTR __DIOTF(_DCMD_ALL, CAAM_AESCTR, 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) @@ -243,7 +302,7 @@ int CAAM_ADR_SYNC(void* vaddr, int sz) */ static int sanityCheckPartitionAddress(CAAM_ADDRESS partAddr, int partSz) { - if (partAddr < CAAM_PAGE || partAddr > CAAM_PAGE * MAX_PART || + if (partAddr < CAAM_PAGE || partAddr > CAAM_PAGE + (MAX_PART*4096) || partSz > 4096) { WOLFSSL_MSG("error in physical address range"); return -1; @@ -379,7 +438,7 @@ static int doTRNG(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4], return ECANCELED; } - ret = caamTRNG(buf, length); + ret = caamEntropy(buf, length); if (ret == CAAM_WAITING) { /* waiting for more entropy */ CAAM_ADR_UNMAP(buf, 0, length, 0); @@ -388,6 +447,7 @@ static int doTRNG(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4], SETIOV(&out_iov, buf, length); ret = resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o)); + DEBUG_PRINT_ARRAY(buf, length, "RNG data"); CAAM_ADR_UNMAP(buf, 0, length, 0); if (ret < 0) { return ECANCELED; @@ -509,42 +569,364 @@ static int doBLOB(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4], /* helper function to setup and make ECC key * returns EOK on success */ -static int doECDSA_KEYPAIR(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4], - unsigned int idx, iofunc_ocb_t *ocb) +static int doAEAD(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4], + unsigned int idx, int type) { - int ret; + int ret = EOK, i = 0; DESCSTRUCT desc; - CAAM_BUFFER tmp[2]; - iov_t in_iovs[2], out_iovs[3]; + CAAM_BUFFER tmp[6] = {0}; + iov_t in_iovs[6], out_iovs[2]; + int inIdx = 0, outIdx = 0, algo; + unsigned char *key = NULL, *iv = NULL, *in = NULL, *out = NULL, *aad = NULL, + *tag = NULL; + int keySz, ivSz = 0, inSz, outSz, aadSz = 0, tagSz = 0; - SETIOV(&in_iovs[0], &tmp[0], sizeof(CAAM_BUFFER)); - SETIOV(&in_iovs[1], &tmp[1], sizeof(CAAM_BUFFER)); - ret = resmgr_msgreadv(ctp, in_iovs, 2, idx); + /* get key info */ + keySz = args[1] & 0xFFFF; /* key size */ + key = (unsigned char*)CAAM_ADR_MAP(0, keySz, 0); + if (key == NULL) { + ret = ECANCELED; + } + SETIOV(&in_iovs[inIdx], key, keySz); + inIdx++; - caamDescInit(&desc, CAAM_ECDSA_KEYPAIR, args, tmp, 2); - ret = caamECDSAMake(&desc, tmp, args); - if (ret != Success) { - return ECANCELED; + /* check for IV */ + if (ret == EOK) { + ivSz = (args[1] >> 24) & 0xFF; + iv = (unsigned char*)CAAM_ADR_MAP(0, ivSz, 0); + if (iv == NULL) { + ret = ECANCELED; + } + SETIOV(&in_iovs[inIdx], iv, ivSz); + inIdx++; } - SETIOV(&out_iovs[0], &tmp[0], sizeof(CAAM_BUFFER)); - SETIOV(&out_iovs[1], &tmp[1], sizeof(CAAM_BUFFER)); - SETIOV(&out_iovs[2], args, sizeof(int) * 4); - ret = resmgr_msgwritev(ctp, &out_iovs[0], 3, sizeof(msg->o)); - if (ret < 0) { - return ECANCELED; + /* get input buffer */ + if (ret == EOK) { + inSz = args[2]; /* input size */ + in = (unsigned char*)CAAM_ADR_MAP(0, inSz, 0); + if (in == NULL) { + ret = ECANCELED; + } + SETIOV(&in_iovs[inIdx], in, inSz); + inIdx++; + } + + /* create output buffer to store results */ + if (ret == EOK) { + outSz = args[2]; /* output size */ + out = (unsigned char*)CAAM_ADR_MAP(0, outSz, 0); + } + + /* add in TAG and AAD if set */ + if (ret == EOK) { + tagSz = (args[1] >> 16) & 0xFF; + tag = (unsigned char*)CAAM_ADR_MAP(0, tagSz, 0); + if (tag == NULL) { + ret = ECANCELED; + } + } + + /* when decrypting the TAG is an input */ + if (ret == EOK) { + if ((args[0] & 0xFFFF) == CAAM_DEC) { + SETIOV(&in_iovs[inIdx], tag, tagSz); + inIdx++; + } + + /* AAD input */ + aadSz = (args[0] >> 16) & 0xFFFF; + if (aadSz > 0) { + aad = (unsigned char*)CAAM_ADR_MAP(0, aadSz, 0); + if (aad == NULL) { + ret = ECANCELED; + } + SETIOV(&in_iovs[inIdx], aad, aadSz); + inIdx++; + } + } + + if (ret == EOK) { + if (resmgr_msgreadv(ctp, in_iovs, inIdx, idx) < 0) { + ret = EBADMSG; + } + } + + if (ret == EOK) { + switch (type) { + case WC_CAAM_AESCCM: algo = CAAM_AESCCM; break; + case WC_CAAM_AESGCM: algo = CAAM_AESGCM; break; + default: + WOLFSSL_MSG("Unknown/supported AES mode"); + ret = ECANCELED; + } + } + + if (ret == EOK) { + tmp[i].Length = keySz; + tmp[i].TheAddress = (CAAM_ADDRESS)key; + i++; + + tmp[i].Length = ivSz; + tmp[i].TheAddress = (CAAM_ADDRESS)iv; + i++; + + tmp[i].Length = inSz; + tmp[i].TheAddress = (CAAM_ADDRESS)in; + i++; + + tmp[i].Length = outSz; + tmp[i].TheAddress = (CAAM_ADDRESS)out; + i++; + + tmp[i].Length = tagSz; + tmp[i].TheAddress = (CAAM_ADDRESS)tag; + i++; + + tmp[i].Length = aadSz; + tmp[i].TheAddress = (CAAM_ADDRESS)aad; + i++; + + caamDescInit(&desc, algo, args, tmp, 6); + if (caamAead(&desc, tmp, args) != Success) { + ret = ECANCELED; + } + } + + /* sync the new IV/MAC and output buffer */ + if (ret == EOK) { + CAAM_ADR_SYNC(out, outSz); + SETIOV(&out_iovs[0], out, outSz); + outIdx++; + + if ((desc.state == CAAM_ENC && + (type == WC_CAAM_AESCCM || type == WC_CAAM_AESGCM))) { + CAAM_ADR_SYNC(tag, tagSz); + SETIOV(&out_iovs[1], tag, tagSz); + outIdx++; + } + + if (resmgr_msgwritev(ctp, &out_iovs[0], outIdx, sizeof(msg->o)) < 0) { + ret = ECANCELED; + } + } + + if (key != NULL) + CAAM_ADR_UNMAP(key, 0, keySz, 0); + if (iv != NULL) + CAAM_ADR_UNMAP(iv, 0, ivSz, 0); + if (in != NULL) + CAAM_ADR_UNMAP(in, 0, inSz, 0); + if (out != NULL) + CAAM_ADR_UNMAP(out, 0, outSz, 0); + if (tag != NULL) + CAAM_ADR_UNMAP(tag, 0, tagSz, 0); + if (aad != NULL) + CAAM_ADR_UNMAP(aad, 0, aadSz, 0); + + return ret; +} + + +/* helper function to setup and make ECC key + * returns EOK on success + */ +static int doAES(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4], + unsigned int idx, int type) +{ + int ret = EOK, i = 0; + DESCSTRUCT desc; + CAAM_BUFFER tmp[6] = {0}; + iov_t in_iovs[6], out_iovs[2]; + int inIdx = 0, outIdx = 0; + int algo; + unsigned char *key = NULL, *iv = NULL, *in = NULL, *out = NULL; + int keySz, ivSz = 0, inSz, outSz; + + /* get key info */ + keySz = args[1] & 0xFFFF; /* key size */ + key = (unsigned char*)CAAM_ADR_MAP(0, keySz, 0); + if (key == NULL) { + ret = ECANCELED; + } + SETIOV(&in_iovs[inIdx], key, keySz); + inIdx++; + + /* check for IV */ + if (ret == EOK) { + if (type == WC_CAAM_AESCBC || type == WC_CAAM_AESCTR) { + ivSz = 16; + iv = (unsigned char*)CAAM_ADR_MAP(0, ivSz, 0); + if (iv == NULL) { + ret = ECANCELED; + } + SETIOV(&in_iovs[inIdx], iv, ivSz); + inIdx++; + } + } + + /* get input buffer */ + if (ret == EOK) { + inSz = args[2]; /* input size */ + in = (unsigned char*)CAAM_ADR_MAP(0, inSz, 0); + if (in == NULL) { + ret = ECANCELED; + } + SETIOV(&in_iovs[inIdx], in, inSz); + inIdx++; + } + + /* create output buffer to store results */ + if (ret == EOK) { + outSz = args[2]; /* output size */ + out = (unsigned char*)CAAM_ADR_MAP(0, outSz, 0); + if (out == NULL) { + ret = ECANCELED; + } + } + + if (ret == EOK) { + if (resmgr_msgreadv(ctp, in_iovs, inIdx, idx) < 0) { + ret = ECANCELED; + } + } + + if (ret == EOK) { + switch (type) { + case WC_CAAM_AESCBC: algo = CAAM_AESCBC; break; + case WC_CAAM_AESCTR: algo = CAAM_AESCTR; break; + case WC_CAAM_AESECB: algo = CAAM_AESECB; break; + default: + WOLFSSL_MSG("Unknown/supported AES mode"); + ret = ECANCELED; + } + } + + if (ret == EOK) { + tmp[i].Length = keySz; + tmp[i].TheAddress = (CAAM_ADDRESS)key; + i++; + + if (type == WC_CAAM_AESCBC || type == WC_CAAM_AESCTR) { + tmp[i].Length = ivSz; + tmp[i].TheAddress = (CAAM_ADDRESS)iv; + i++; + } + + tmp[i].Length = inSz; + tmp[i].TheAddress = (CAAM_ADDRESS)in; + i++; + + tmp[i].Length = outSz; + tmp[i].TheAddress = (CAAM_ADDRESS)out; + + caamDescInit(&desc, algo, args, tmp, 6); + if (caamAes(&desc, tmp, args) != Success) { + ret = ECANCELED; + } + } + + /* sync the new IV/MAC and output buffer */ + if (ret == EOK) { + if (type == WC_CAAM_AESCBC || type == WC_CAAM_AESCTR) { + CAAM_ADR_SYNC(iv, ivSz); + SETIOV(&out_iovs[1], iv, ivSz); + outIdx++; + } + CAAM_ADR_SYNC(out, outSz); + SETIOV(&out_iovs[0], out, outSz); + outIdx++; + + if (resmgr_msgwritev(ctp, &out_iovs[0], outIdx, sizeof(msg->o)) < 0) { + ret = ECANCELED; + } + } + + if (key != NULL) + CAAM_ADR_UNMAP(key, 0, keySz, 0); + if (iv != NULL) + CAAM_ADR_UNMAP(iv, 0, ivSz, 0); + if (in != NULL) + CAAM_ADR_UNMAP(in, 0, inSz, 0); + if (out != NULL) + CAAM_ADR_UNMAP(out, 0, outSz, 0); + + return ret; +} + + +/* helper function to setup and make ECC key + * returns EOK on success + */ +static int doECDSA_KEYPAIR(resmgr_context_t *ctp, io_devctl_t *msg, + unsigned int args[4], unsigned int idx, iofunc_ocb_t *ocb) +{ + int ret = EOK; + int keySz; + int privSz; + DESCSTRUCT desc; + CAAM_BUFFER tmp[2]; + iov_t out_iovs[3]; + unsigned char *priv = NULL, *pub = NULL; + + privSz = keySz = args[3]; + if (args[0] == CAAM_BLACK_KEY_CCM) { + privSz += BLACK_KEY_MAC_SZ; + } + if (args[0] == CAAM_BLACK_KEY_SM) { + privSz = sizeof(unsigned int); + } + + /* private key */ + tmp[0].Length = privSz; + priv = (unsigned char*)CAAM_ADR_MAP(0, privSz, 0); + if (priv == NULL) { + ret = ECANCELED; + } + tmp[0].TheAddress = (CAAM_ADDRESS)priv; + + /* public key */ + if (ret == EOK) { + tmp[1].Length = keySz * 2; + pub = (unsigned char*)CAAM_ADR_MAP(0, keySz * 2, 0); + if (pub == NULL) { + ret = ECANCELED; + } + tmp[1].TheAddress = (CAAM_ADDRESS)pub; + } + + if (ret == EOK) { + caamDescInit(&desc, CAAM_ECDSA_KEYPAIR, args, tmp, 2); + if (caamECDSAMake(&desc, tmp, args) != Success) { + ret = ECANCELED; + } + } + + if (ret == EOK) { + SETIOV(&out_iovs[0], tmp[0].TheAddress, privSz); + SETIOV(&out_iovs[1], tmp[1].TheAddress, keySz * 2); + SETIOV(&out_iovs[2], args, sizeof(int) * 4); + if (resmgr_msgwritev(ctp, &out_iovs[0], 3, sizeof(msg->o)) < 0) { + ret = ECANCELED; + } } /* claim ownership of a secure memory location */ - if (pthread_mutex_lock(&sm_mutex) != EOK) { - return ECANCELED; - } - else { - sm_ownerId[args[2]] = (CAAM_ADDRESS)ocb; - pthread_mutex_unlock(&sm_mutex); + if (ret == EOK && args[0] == CAAM_BLACK_KEY_SM) { + if (pthread_mutex_lock(&sm_mutex) != EOK) { + ret = ECANCELED; + } + else { + sm_ownerId[args[2]] = (CAAM_ADDRESS)ocb; + pthread_mutex_unlock(&sm_mutex); + } } - return EOK; + if (priv != NULL) + CAAM_ADR_UNMAP(priv, 0, privSz, 0); + if (pub != NULL) + CAAM_ADR_UNMAP(pub, 0, keySz*2, 0); + return ret; } @@ -562,7 +944,7 @@ static int doECDSA_VERIFY(resmgr_context_t *ctp, io_devctl_t *msg, unsigned char *hash, *pubkey = NULL, *r, *s; CAAM_ADDRESS securePub; - if (args[0] == 1) { + if (args[0] == CAAM_BLACK_KEY_SM) { pubSz = sizeof(CAAM_ADDRESS); SETIOV(&in_iovs[0], &securePub, sizeof(CAAM_ADDRESS)); @@ -615,7 +997,7 @@ static int doECDSA_VERIFY(resmgr_context_t *ctp, io_devctl_t *msg, } /* setup CAAM buffers to pass to driver */ - if (args[0] == 1) { + if (args[0] == CAAM_BLACK_KEY_SM) { tmp[0].TheAddress = securePub; } else { @@ -669,12 +1051,15 @@ static int doECDSA_SIGN(resmgr_context_t *ctp, io_devctl_t *msg, iov_t in_iovs[2], out_iovs[2]; - if (args[0] == 1) { + if (args[0] == CAAM_BLACK_KEY_SM) { keySz = sizeof(CAAM_ADDRESS); SETIOV(&in_iovs[0], &blackKey, sizeof(CAAM_ADDRESS)); } else { keySz = args[3]; + if (args[0] == CAAM_BLACK_KEY_CCM) { + keySz += BLACK_KEY_MAC_SZ; + } key = (unsigned char*)CAAM_ADR_MAP(0, keySz, 0); if (key == NULL) { return ECANCELED; @@ -691,6 +1076,7 @@ static int doECDSA_SIGN(resmgr_context_t *ctp, io_devctl_t *msg, SETIOV(&in_iovs[1], hash, args[2]); ret = resmgr_msgreadv(ctp, in_iovs, 2, idx); if ((keySz + args[2]) > ret) { + WOLFSSL_MSG("Overflow reading key and hash"); CAAM_ADR_UNMAP(hash, 0, args[2], 0); if (key != NULL) CAAM_ADR_UNMAP(key, 0, keySz, 0); @@ -699,13 +1085,14 @@ static int doECDSA_SIGN(resmgr_context_t *ctp, io_devctl_t *msg, /* setup CAAM buffers to pass to driver */ - if (args[0] == 1) { + if (args[0] == CAAM_BLACK_KEY_SM) { tmp[0].TheAddress = blackKey; + tmp[0].Length = args[3]; } else { tmp[0].TheAddress = (CAAM_ADDRESS)key; + tmp[0].Length = keySz; } - tmp[0].Length = args[3]; tmp[1].TheAddress = (CAAM_ADDRESS)hash; tmp[1].Length = args[2]; @@ -779,7 +1166,7 @@ static int doECDSA_ECDH(resmgr_context_t *ctp, io_devctl_t *msg, CAAM_ADDRESS securePub, blackKey; /* when using memory in secure partition just send the address */ - if (args[1] == 1) { + if (args[1] == CAAM_BLACK_KEY_SM) { SETIOV(&in_iovs[0], &securePub, sizeof(CAAM_ADDRESS)); expectedSz += sizeof(CAAM_ADDRESS); } @@ -793,20 +1180,31 @@ static int doECDSA_ECDH(resmgr_context_t *ctp, io_devctl_t *msg, expectedSz += args[3]*2; } - if (args[0] == 1) { + if (args[0] == CAAM_BLACK_KEY_SM) { SETIOV(&in_iovs[1], &blackKey, sizeof(CAAM_ADDRESS)); expectedSz += sizeof(CAAM_ADDRESS); } else { - key = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0); + if (args[0] == CAAM_BLACK_KEY_CCM) { + key = (unsigned char*)CAAM_ADR_MAP(0, args[3] + BLACK_KEY_MAC_SZ, 0); + } + else { + key = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0); + } if (key == NULL) { if (pubkey != NULL) CAAM_ADR_UNMAP(pubkey, 0, args[3]*2, 0); return ECANCELED; } - SETIOV(&in_iovs[1], key, args[3]); - expectedSz += args[3]; + if (args[0] == CAAM_BLACK_KEY_CCM) { + SETIOV(&in_iovs[1], key, args[3] + BLACK_KEY_MAC_SZ); + expectedSz += args[3] + BLACK_KEY_MAC_SZ; + } + else { + SETIOV(&in_iovs[1], key, args[3]); + expectedSz += args[3]; + } } ret = resmgr_msgreadv(ctp, in_iovs, 2, idx); @@ -819,7 +1217,7 @@ static int doECDSA_ECDH(resmgr_context_t *ctp, io_devctl_t *msg, } /* setup CAAM buffers to pass to driver */ - if (args[1] == 1) { + if (args[1] == CAAM_BLACK_KEY_SM) { tmp[0].TheAddress = securePub; } else { @@ -827,7 +1225,7 @@ static int doECDSA_ECDH(resmgr_context_t *ctp, io_devctl_t *msg, } tmp[0].Length = args[3]*2; - if (args[0] == 1) { + if (args[0] == CAAM_BLACK_KEY_SM) { tmp[1].TheAddress = blackKey; } else { @@ -1097,6 +1495,17 @@ int io_devctl (resmgr_context_t *ctp, io_devctl_t *msg, iofunc_ocb_t *ocb) ret = doBLOB(ctp, msg, args, idx); break; + case WC_CAAM_AESECB: + case WC_CAAM_AESCTR: + case WC_CAAM_AESCBC: + ret = doAES(ctp, msg, args, idx, msg->i.dcmd); + break; + + case WC_CAAM_AESCCM: + case WC_CAAM_AESGCM: + ret = doAEAD(ctp, msg, args, idx, msg->i.dcmd); + break; + case WC_CAAM_ECDSA_KEYPAIR: ret = doECDSA_KEYPAIR(ctp, msg, args, idx, ocb); break; @@ -1219,6 +1628,7 @@ char cannedResponse[] = { LIBWOLFSSL_VERSION_STRING "\nSupports:\n" "\tAES-CMAC\n" + "\tAES (GCM/CCM/ECB/CBC/CTR)\n" "\tECC (sign, verify, ecdh, keygen)\n" "\tBlobs (black and red)\n" }; diff --git a/wolfcrypt/src/port/caam/wolfcaam_aes.c b/wolfcrypt/src/port/caam/wolfcaam_aes.c index 23fecb2e8..07581d9d7 100644 --- a/wolfcrypt/src/port/caam/wolfcaam_aes.c +++ b/wolfcrypt/src/port/caam/wolfcaam_aes.c @@ -32,6 +32,13 @@ #include #include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + /* 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, @@ -51,7 +58,7 @@ static int wc_CAAM_AesAeadCommon(Aes* aes, const byte* in, byte* out, word32 sz, } buf[idx].BufferType = DataBuffer; - buf[idx].TheAddress = (CAAM_ADDRESS)aes->key; + buf[idx].TheAddress = (CAAM_ADDRESS)aes->devKey; buf[idx].Length = keySz; idx++; @@ -80,13 +87,15 @@ static int wc_CAAM_AesAeadCommon(Aes* aes, const byte* in, byte* out, word32 sz, buf[idx].Length = authInSz; idx++; - arg[0] = dir; - arg[1] = keySz; + /* 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; + arg[1] = ((nonceSz & 0xFF) << 24) | ((authTagSz & 0xFF) << 16) | keySz; arg[2] = sz; arg[3] = aes->blackKey; if ((ret = wc_caamAddAndWait(buf, idx, arg, type)) != 0) { - WOLFSSL_MSG("Error with CAAM AES CCM operation"); + WOLFSSL_MSG("Error with CAAM AES AEAD operation"); return ret; } @@ -94,6 +103,46 @@ static int wc_CAAM_AesAeadCommon(Aes* aes, const byte* in, byte* out, word32 sz, } +#if defined(HAVE_AESCCM) +/* 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; +} + + /* plaintext in ciphertext and mac out * return 0 on success */ @@ -101,8 +150,21 @@ 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) { - return wc_CAAM_AesAeadCommon(aes, in, out, sz, nonce, nonceSz, authTag, - authTagSz, authIn, authInSz, CAAM_ENC, CAAM_AESCCM); + byte B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE]; + + 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; + } + + 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); } @@ -113,9 +175,40 @@ 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) { - return wc_CAAM_AesAeadCommon(aes, in, out, sz, nonce, nonceSz, + int ret; + byte B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE]; + + /* 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; + } + + 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); + + 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 */ int wc_CAAM_AesGcmEncrypt(Aes* aes, const byte* in, byte* out, word32 sz, @@ -136,8 +229,8 @@ int wc_CAAM_AesGcmDecrypt(Aes* aes, const byte* in, byte* out, word32 sz, } -static int wc_CAAM_AesCbcCommon(Aes* aes, byte* out, const byte* in, word32 sz, - int dir) +static int wc_CAAM_AesCbcCtrCommon(Aes* aes, byte* out, const byte* in, + word32 sz, int dir, int mode) { word32 blocks; @@ -148,7 +241,7 @@ static int wc_CAAM_AesCbcCommon(Aes* aes, byte* out, const byte* in, word32 sz, blocks = sz / AES_BLOCK_SIZE; if (blocks > 0) { - CAAM_BUFFER buf[4]; + CAAM_BUFFER buf[5]; word32 arg[4]; word32 keySz; int ret; @@ -159,7 +252,7 @@ static int wc_CAAM_AesCbcCommon(Aes* aes, byte* out, const byte* in, word32 sz, /* Set buffers for key, cipher text, and plain text */ buf[0].BufferType = DataBuffer; - buf[0].TheAddress = (CAAM_ADDRESS)aes->key; + buf[0].TheAddress = (CAAM_ADDRESS)(void*)aes->devKey; buf[0].Length = keySz; buf[1].BufferType = DataBuffer; @@ -174,12 +267,17 @@ static int wc_CAAM_AesCbcCommon(Aes* aes, byte* out, const byte* in, word32 sz, 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, 4, arg, CAAM_AESCBC)) != 0) { + if ((ret = wc_caamAddAndWait(buf, 5, arg, mode)) != 0) { WOLFSSL_MSG("Error with CAAM AES CBC operation"); return ret; } @@ -188,15 +286,80 @@ static int wc_CAAM_AesCbcCommon(Aes* aes, byte* out, const byte* in, word32 sz, 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_AesCbcCommon(aes, out, in, sz, CAAM_ENC); + 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_AesCbcCommon(aes, out, in, sz, CAAM_DEC); + return wc_CAAM_AesCbcCtrCommon(aes, out, in, sz, CAAM_DEC, CAAM_AESCBC); } #if defined(HAVE_AES_ECB) @@ -222,15 +385,10 @@ static int wc_CAAM_AesEcbCommon(Aes* aes, byte* out, const byte* in, word32 sz, /* Set buffers for key, cipher text, and plain text */ buf[idx].BufferType = DataBuffer; - buf[idx].TheAddress = (CAAM_ADDRESS)aes->key; + buf[idx].TheAddress = (CAAM_ADDRESS)aes->devKey; buf[idx].Length = keySz; idx++; - buf[idx].BufferType = DataBuffer; - buf[idx].TheAddress = (CAAM_ADDRESS)aes->reg; - buf[idx].Length = 0; /* NO IV */ - idx++; - buf[idx].BufferType = DataBuffer; buf[idx].TheAddress = (CAAM_ADDRESS)in; buf[idx].Length = blocks * AES_BLOCK_SIZE; diff --git a/wolfcrypt/src/port/caam/wolfcaam_ecdsa.c b/wolfcrypt/src/port/caam/wolfcaam_ecdsa.c index 83cdba955..ab81a3a25 100644 --- a/wolfcrypt/src/port/caam/wolfcaam_ecdsa.c +++ b/wolfcrypt/src/port/caam/wolfcaam_ecdsa.c @@ -322,18 +322,28 @@ int wc_CAAM_EccSign(const byte* in, int inlen, byte* out, word32* outlen, keySz = wc_ecc_size(key); /* private key */ - if (key->blackKey > 0) { + if (key->blackKey == CAAM_BLACK_KEY_SM) { buf[idx].TheAddress = (CAAM_ADDRESS)key->blackKey; - args[0] = 1; /* is a black key */ + args[0] = CAAM_BLACK_KEY_SM; /* is a black key in sm */ + buf[idx].Length = keySz; } else { - if (mp_to_unsigned_bin_len(&key->k, pk, keySz) != MP_OKAY) { - return MP_TO_E; + if (key->blackKey == CAAM_BLACK_KEY_CCM) { + if (mp_to_unsigned_bin_len(&key->k, 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(&key->k, pk, keySz) != MP_OKAY) { + return MP_TO_E; + } + buf[idx].Length = keySz; } buf[idx].TheAddress = (CAAM_ADDRESS)pk; - args[0] = 0; /* non black key */ + args[0] = key->blackKey; /* potentail black key, not in sm */ } - buf[idx].Length = keySz; idx++; /* hash to sign */ @@ -541,7 +551,7 @@ int wc_CAAM_Ecdh(ecc_key* private_key, ecc_key* public_key, byte* out, dp = wc_ecc_get_curve_params(private_key->idx); } - if (dp->id != ECC_SECP256R1) { + if (dp->id != ECC_SECP256R1 && dp->id != ECC_SECP384R1) { return CRYPTOCB_UNAVAILABLE; } @@ -575,23 +585,46 @@ int wc_CAAM_Ecdh(ecc_key* private_key, ecc_key* public_key, byte* out, idx++; /* private key */ - if (private_key->blackKey > 0) { + 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] = 1; /* is a black key */ + 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 (mp_to_unsigned_bin_len(&private_key->k, pk, keySz) != MP_OKAY) { - return MP_TO_E; + if (private_key->blackKey == CAAM_BLACK_KEY_CCM) { + if (mp_to_unsigned_bin_len(&private_key->k, 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(&private_key->k, pk, keySz) != MP_OKAY) { + return MP_TO_E; + } + buf[idx].Length = keySz; } buf[idx].TheAddress = (CAAM_ADDRESS)pk; - args[0] = 0; /* non black key */ + args[0] = private_key->blackKey; /* potential black key, but not sm */ } - buf[idx].Length = keySz; + +#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 */ @@ -618,8 +651,8 @@ int wc_CAAM_Ecdh(ecc_key* private_key, ecc_key* public_key, byte* out, 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 args[4] = {0}; + CAAM_BUFFER buf[2] = {0}; word32 ecdsel = 0; int ret; @@ -636,6 +669,7 @@ int wc_CAAM_MakeEccKey(WC_RNG* rng, int keySize, ecc_key* key, int curveId, /* 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 */ @@ -651,34 +685,59 @@ int wc_CAAM_MakeEccKey(WC_RNG* rng, int keySize, ecc_key* key, int curveId, (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; - buf[0].Length = keySize; + 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; - - args[0] = 1; /* Creating Black Key */ - args[1] = ecdsel; + key->blackKey = args[0]; ret = wc_caamAddAndWait(buf, 2, args, CAAM_ECDSA_KEYPAIR); - if (args[0] == 1 && ret == 0) { - key->blackKey = (word32)buf[0].TheAddress; - #if defined(WOLFSSL_SECO_CAAM) + 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; } - #else - key->securePubKey = (word32)buf[1].TheAddress; key->partNum = args[2]; - #endif return MP_OKAY; } - if (args[0] == 0 && ret == 0) { + 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; diff --git a/wolfcrypt/src/port/caam/wolfcaam_init.c b/wolfcrypt/src/port/caam/wolfcaam_init.c index 4661f91bd..61835cae8 100644 --- a/wolfcrypt/src/port/caam/wolfcaam_init.c +++ b/wolfcrypt/src/port/caam/wolfcaam_init.c @@ -307,21 +307,30 @@ static int wc_CAAM_router(int devId, wc_CryptoInfo* info, void* ctx) } break; - #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); + #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); } - #endif /* HAVE_AES_ECB */ + 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; diff --git a/wolfcrypt/src/port/caam/wolfcaam_qnx.c b/wolfcrypt/src/port/caam/wolfcaam_qnx.c index 0e6466ecc..0bcef42d1 100644 --- a/wolfcrypt/src/port/caam/wolfcaam_qnx.c +++ b/wolfcrypt/src/port/caam/wolfcaam_qnx.c @@ -79,10 +79,15 @@ void wc_CAAMFreeInterface() #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 5 +#define MAX_IN_IOVS 6 #define MAX_OUT_IOVS 3 /* Do a synchronous operations and block till done @@ -93,7 +98,7 @@ int SynchronousSendRequest(int type, unsigned int args[4], CAAM_BUFFER *buf, int ret, inIdx = 0, outIdx = 0; int cmd = 0; iov_t in[MAX_IN_IOVS], out[MAX_OUT_IOVS]; - CAAM_ADDRESS pubkey, privkey; + CAAM_ADDRESS privkey; if (args != NULL) { SETIOV(&in[inIdx], args, sizeof(unsigned int) * 4); @@ -141,18 +146,11 @@ int SynchronousSendRequest(int type, unsigned int args[4], CAAM_BUFFER *buf, break; case CAAM_ECDSA_KEYPAIR: - /* set input to get lengths */ - SETIOV(&in[inIdx], &buf[0], sizeof(CAAM_BUFFER)); - inIdx = inIdx + 1; - - SETIOV(&in[inIdx], &buf[1], sizeof(CAAM_BUFFER)); - inIdx = inIdx + 1; - /* set output to store directly to CAAM_BUFFER's */ - SETIOV(&out[outIdx], &buf[0], sizeof(CAAM_BUFFER)); + SETIOV(&out[outIdx], buf[0].TheAddress, buf[0].Length); outIdx = outIdx + 1; - SETIOV(&out[outIdx], &buf[1], sizeof(CAAM_BUFFER)); + SETIOV(&out[outIdx], buf[1].TheAddress, buf[1].Length); outIdx = outIdx + 1; /* get args for updated partition number used */ @@ -164,15 +162,8 @@ int SynchronousSendRequest(int type, unsigned int args[4], CAAM_BUFFER *buf, case CAAM_ECDSA_VERIFY: /* public key */ - if (args[0] == 1) { - pubkey = buf[0].TheAddress; - SETIOV(&in[inIdx], &pubkey, sizeof(CAAM_ADDRESS)); - inIdx = inIdx + 1; - } - else { - SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length); - inIdx = inIdx + 1; - } + SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length); + inIdx = inIdx + 1; /* msg */ SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length); @@ -193,7 +184,7 @@ int SynchronousSendRequest(int type, unsigned int args[4], CAAM_BUFFER *buf, /* private key */ if (args[0] == 1) { privkey = buf[0].TheAddress; - SETIOV(&in[inIdx], &privkey, sizeof(CAAM_ADDRESS)); + SETIOV(&in[inIdx], &privkey, sizeof(unsigned int)); inIdx = inIdx + 1; } else { @@ -218,20 +209,13 @@ int SynchronousSendRequest(int type, unsigned int args[4], CAAM_BUFFER *buf, case CAAM_ECDSA_ECDH: /* when using memory in secure partition just send the address */ - if (args[1] == 1) { - pubkey = buf[0].TheAddress; - SETIOV(&in[inIdx], &pubkey, sizeof(CAAM_ADDRESS)); - inIdx = inIdx + 1; - } - else { - SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length); - inIdx = inIdx + 1; - } + SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length); + inIdx = inIdx + 1; /* private key */ - if (args[0] == 1) { + if (args[0] == CAAM_BLACK_KEY_SM) { privkey = buf[1].TheAddress; - SETIOV(&in[inIdx], &privkey, sizeof(CAAM_ADDRESS)); + SETIOV(&in[inIdx], &privkey, sizeof(unsigned int)); inIdx = inIdx + 1; } else { @@ -284,6 +268,137 @@ int SynchronousSendRequest(int type, unsigned int args[4], CAAM_BUFFER *buf, 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; diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index fbd91d468..93662e145 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -2385,7 +2385,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) } #elif (defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ - defined(WOLFSSL_SECO_CAAM)) + defined(WOLFSSL_SECO_CAAM) || defined(WOLFSSL_QNX_CAAM)) #include diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 9fb993b3b..abfc65f3f 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -10587,6 +10587,10 @@ WOLFSSL_TEST_SUBROUTINE int aesccm_test(void) XMEMSET(c2, 0, sizeof(c2)); XMEMSET(p2, 0, sizeof(p2)); + result = wc_AesInit(enc, HEAP_HINT, devId); + if (result != 0) + ERROR_OUT(-6499, out); + result = wc_AesCcmSetKey(enc, k, sizeof(k)); if (result != 0) ERROR_OUT(-6500, out); @@ -25086,7 +25090,7 @@ static int ecc_encrypt_kat(WC_RNG *rng) 0xd3, 0xb0, 0x7f, 0x7e, 0x7f, 0x86, 0x8a, 0x49, 0xee, 0xb4, 0xaa, 0x09, 0x2d, 0x1e, 0x1d, 0x02 }; -#ifdef WOLFSSL_ECIES_OLD +#if defined(WOLFSSL_ECIES_OLD) || defined(WOLFSSL_QNX_CAAM) WOLFSSL_SMALL_STACK_STATIC const byte pubKey[] = { 0x04, /* X */ @@ -25203,8 +25207,13 @@ static int ecc_encrypt_kat(WC_RNG *rng) if (ret == 0) { +#ifdef WOLFSSL_QNX_CAAM + ret = wc_ecc_import_private_key_ex(privKey, sizeof(privKey), pubKey, + sizeof(pubKey), userB, ECC_SECP256R1); +#else ret = wc_ecc_import_private_key_ex(privKey, sizeof(privKey), NULL, 0, userB, ECC_SECP256R1); +#endif if (ret != 0) ret = -10454; } @@ -39882,7 +39891,23 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) info->cipher.aesecb.aes->devId = devIdArg; } } - #endif /* HAVE_AES_CBC */ + #endif /* HAVE_AES_ECB */ + #if defined(WOLFSSL_AES_COUNTER) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + if (info->cipher.type == WC_CIPHER_AES_CTR) { + /* set devId to invalid, so software is used */ + info->cipher.aesctr.aes->devId = INVALID_DEVID; + + ret = wc_AesCtrEncrypt( + info->cipher.aesctr.aes, + info->cipher.aesctr.out, + info->cipher.aesctr.in, + info->cipher.aesctr.sz); + + /* reset devId */ + info->cipher.aesctr.aes->devId = devIdArg; + } + #endif /* WOLFSSL_AES_COUNTER */ #if defined(HAVE_AESCCM) && defined(WOLFSSL_AES_128) if (info->cipher.type == WC_CIPHER_AES_CCM) { if (info->cipher.enc) { diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h index 6b20e72e2..daeb3567e 100644 --- a/wolfssl/wolfcrypt/cryptocb.h +++ b/wolfssl/wolfcrypt/cryptocb.h @@ -259,6 +259,14 @@ typedef struct wc_CryptoInfo { word32 sz; } aescbc; #endif /* HAVE_AES_CBC */ + #if defined(WOLFSSL_AES_COUNTER) + struct { + Aes* aes; + byte* out; + const byte* in; + word32 sz; + } aesctr; + #endif /* WOLFSSL_AES_COUNTER */ #if defined(HAVE_AES_ECB) struct { Aes* aes; @@ -442,6 +450,10 @@ WOLFSSL_LOCAL int wc_CryptoCb_AesCbcEncrypt(Aes* aes, byte* out, WOLFSSL_LOCAL int wc_CryptoCb_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz); #endif /* HAVE_AES_CBC */ +#ifdef WOLFSSL_AES_COUNTER +WOLFSSL_LOCAL int wc_CryptoCb_AesCtrEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif /* WOLFSSL_AES_COUNTER */ #ifdef HAVE_AES_ECB WOLFSSL_LOCAL int wc_CryptoCb_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz); diff --git a/wolfssl/wolfcrypt/port/caam/caam_driver.h b/wolfssl/wolfcrypt/port/caam/caam_driver.h index 878cd0722..131685a49 100644 --- a/wolfssl/wolfcrypt/port/caam/caam_driver.h +++ b/wolfssl/wolfcrypt/port/caam/caam_driver.h @@ -31,6 +31,14 @@ #define CAAM_PAGE 0xf0100000 #endif +#ifdef WOLFSSL_CAAM_PRINT + #include + #define WOLFSSL_MSG(in) printf("%s\n", (in)) + void DEBUG_PRINT_ARRAY(void* a, int aSz, char* str); +#else + #define WOLFSSL_MSG(in) + #define DEBUG_PRINT_ARRAY(a,aSz,str) +#endif #define CAAM_PAGE_MAX 6 @@ -41,6 +49,15 @@ #define CAAM_JOBRING_SIZE 1 #endif +/* black key stored in secure memory location */ +#define CAAM_BLACK_KEY_SM 1 + +/* black key encrypted with AES-CCM (has MAC) */ +#define CAAM_BLACK_KEY_CCM 2 + +/* black key encrypted with AES-ECB (no MAC) */ +#define CAAM_BLACK_KEY_ECB 3 + /****************************************************************************** Basic Descriptors ****************************************************************************/ @@ -82,6 +99,7 @@ #define CAAM_ALG_INITF 0x0000000C #define CAAM_ALG_UPDATE 0x00000000 #define CAAM_ALG_FINAL 0x00000008 +#define CAAM_ALG_IVC 0x00000002 /* AES 10h */ #define CAAM_AESCTR 0x00100000 @@ -91,6 +109,7 @@ #define CAAM_AESOFB 0x00100400 #define CAAM_CMAC 0x00100600 #define CAAM_AESCCM 0x00100800 +#define CAAM_AESGCM 0x00100900 /* HASH 40h */ #define CAAM_MD5 0x00400000 @@ -130,8 +149,8 @@ /* key encryption bit */ #define CAAM_PKHA_ECC 0x00000002 -#define CAAM_PKHA_ENC_PRI_AESCBC 0x00000004 -#define CAAM_PKHA_ENC_PRI_AESCCM (0x00000010 | CAAM_PKHA_ENC_PRI_AESCBC) +#define CAAM_PKHA_ENC_PRI_AESECB 0x00000004 +#define CAAM_PKHA_ENC_PRI_AESCCM (0x00000010 | CAAM_PKHA_ENC_PRI_AESECB) #define CAAM_PKHA_NO_TIMING_RESISTANCE 0x40000000 #define CAAM_LOAD_BLACK_KEY 0x500000 @@ -154,12 +173,16 @@ #define CAAM_ENTROPY 0x00500001 #define FIFOL_TYPE_MSG 0x00100000 +#define FIFOL_TYPE_IV 0x00200000 +#define FIFOL_TYPE_IVC 0x00380000 #define FIFOL_TYPE_AAD 0x00300000 #define FIFOL_TYPE_FC1 0x00010000 #define FIFOL_TYPE_LC1 0x00020000 #define FIFOL_TYPE_LC2 0x00040000 #define FIFOS_TYPE_MSG 0x00300000 +#define FIFOS_TYPE_RNG 0x00340000 +#define FIFOS_EXT 0x00400000 /* continue bit set if more output is expected */ #define CAAM_FIFOS_CONT 0x00800000 @@ -212,44 +235,40 @@ #define CAAM_ENTVAL 0x00000400 /* checking RTMCTL for entropy ready */ /* Input Job Ring Registers */ -#define CAAM_IRBAR0 0x1004 - //0x1004 -#define CAAM_IRSR0 0x100C -#define CAAM_IRJAR0 0x101C +#define CAAM_IRBAR0 0x0004 +#define CAAM_IRSR0 0x000C +#define CAAM_IRJAR0 0x001C -#define CAAM_IRBAR2 0x3000 +#define CAAM_IRBAR2 0x3004 #define CAAM_IRSR2 0x300C #define CAAM_IRJAR2 0x301C -#define CAAM_IRSAR_JR2 0x3014 - - +#define CAAM_IRSAR_JR 0x0014 /* Output Job Ring Registers */ -#define CAAM_ORBAR0 0x1024 - //0x1024 -#define CAAM_ORSR0 0x102C -#define CAAM_ORJAR0 0x103C +#define CAAM_ORBAR 0x0024 +#define CAAM_ORSR0 0x002C +#define CAAM_ORJAR 0x003C +#define CAAM_ORJRR 0x0034 - -#define CAAM_ORBAR2 0x3024 - //0x1024 -#define CAAM_ORSR2 0x302C -#define CAAM_ORJAR2 0x303C - -#define JRCFGR_JR0_LS 0x1054 +#define JRCFGR_JR 0x0054 +#define JRCR_JR 0x006C /* Status Registers */ #define CAAM_STATUS 0x0FD4 -#define CAAM_VERSION_MS 0x0FE8 -#define CAAM_VERSION_LS 0x0FEC -#define CAMM_SUPPORT_MS 0x0FF0 -#define CAMM_SUPPORT_LS 0x0FF4 +#define CAAM_CHA_VERSION_MS 0x0FE8 +#define CAAM_CHA_VERSION_LS 0x0FEC +#define CAMM_CHA_SUPPORT_MS 0x0FF0 +#define CAMM_CHA_SUPPORT_LS 0x0FF4 +#define CAAM_VERSION_MS 0x0FF8 +#define CAAM_VERSION_LS 0x0FFC +#define CAAM_CHA_CCBVID 0x0FE4 -#define CAAM_SM_CMD 0x1BE4 -#define CAAM_SM_SMPO 0x1FBC -#define CAAM_SM_SMVID_MS 0x1FD8 -#define CAAM_SM_SMVID_LS 0x1FDC -#define CAAM_SM_STATUS 0x1BEC +#define CAAM_SM_CMD 0x0BE4 +#define CAAM_SM_SMPO 0x0FBC +#define CAAM_SMAPR 0x0A04 +#define CAAM_SM_SMVID_MS 0x0FD8 +#define CAAM_SM_SMVID_LS 0x0FDC +#define CAAM_SM_STATUS 0x0BEC #define CAAM_SM_CSP 0x00008000 #define CAAM_SM_SMAP_LOCK 0x00002000 #define CAAM_SM_SMAG_LOCK 0x00001000 @@ -257,6 +276,9 @@ #define CAAM_C1DSR_LS 0x8014 #define CAAM_C1MR 0x8004 +#define CAAM_RSTA 0x0004 +#define CAAM_DRR 0x0124 +#define CAAM_CRNR_LS 0x0FA4 /* output FIFO is 16 entries deep and each entry has a two 4 byte registers */ @@ -281,22 +303,23 @@ #define CAAM_DODAR 0x8808 /* address of current descriptor */ #define CAAM_DODESB 0x8A00 /* 64 registers that hold the current descriptor buffer */ - -#define JRINTR_JR0 0x104C -#define JRINTR_JR1 0x204C -#define JRINTR_JR2 0x304C +#define JRINTR_JR 0x004C #define CAAM_SINGLE_STEP_MODE 0x40000000 #define CAAM_STEP 0x80000000 /* Port layer for CAAM driver, functions defined in caam_.c */ -unsigned int CAAM_READ(unsigned int reg); -void CAAM_WRITE(unsigned int reg, unsigned int in); -int CAAM_SET_BASEADDR(void); -void CAAM_UNSET_BASEADDR(void); -unsigned int CAAM_ADR_TO_PHYSICAL(void* in, int inSz); -void* CAAM_ADR_MAP(unsigned int in, int inSz, unsigned char copy); -void CAAM_ADR_UNMAP(void* vaddr, unsigned int out, int outSz, +unsigned int CAAM_READ(CAAM_ADDRESS reg); +void CAAM_WRITE(CAAM_ADDRESS reg, unsigned int in); +int CAAM_SET_BASEADDR(CAAM_ADDRESS* baseAddr); +void CAAM_UNSET_BASEADDR(CAAM_ADDRESS baseAddr); +void CAAM_UNSET_JOBRING_ADDR(CAAM_ADDRESS base, CAAM_ADDRESS ringInPhy, + void* ringInVir); +int CAAM_SET_JOBRING_ADDR(CAAM_ADDRESS* base, CAAM_ADDRESS* ringInPhy, + void** ringInVir); +CAAM_ADDRESS CAAM_ADR_TO_PHYSICAL(void* in, int inSz); +void* CAAM_ADR_MAP(CAAM_ADDRESS in, int inSz, unsigned char copy); +void CAAM_ADR_UNMAP(void* vaddr, CAAM_ADDRESS out, int outSz, unsigned char copy); int CAAM_ADR_SYNC(void* vaddr, int sz); CAAM_ADDRESS CAAM_ADR_TO_VIRTUAL(CAAM_ADDRESS in, int length); @@ -319,7 +342,7 @@ int CleanupCAAM(void); typedef struct DESCSTRUCT DESCSTRUCT; int caamKeyCover(DESCSTRUCT *desc, int sz, unsigned int args[4]); -int caamTRNG(unsigned char *out, int outSz); +int caamEntropy(unsigned char *out, int outSz); int caamECDSA_ECDH(DESCSTRUCT *desc, int sz, unsigned int args[4]); int caamECDSASign(DESCSTRUCT *desc, int sz, unsigned int args[4]); int caamECDSAVerify(DESCSTRUCT *desc, CAAM_BUFFER *buf, int sz, @@ -327,6 +350,8 @@ int caamECDSAVerify(DESCSTRUCT *desc, CAAM_BUFFER *buf, int sz, int caamECDSAMake(DESCSTRUCT *desc, CAAM_BUFFER *buf, unsigned int args[4]); +int caamAes(DESCSTRUCT* desc, CAAM_BUFFER* buf, unsigned int args[4]); +int caamAead(DESCSTRUCT* desc, CAAM_BUFFER* buf, unsigned int args[4]); int caamAesCmac(DESCSTRUCT *desc, int sz, unsigned int args[4]); int caamBlob(DESCSTRUCT *desc); diff --git a/wolfssl/wolfcrypt/port/caam/caam_qnx.h b/wolfssl/wolfcrypt/port/caam/caam_qnx.h index 3a9150933..b803e89dd 100644 --- a/wolfssl/wolfcrypt/port/caam/caam_qnx.h +++ b/wolfssl/wolfcrypt/port/caam/caam_qnx.h @@ -25,15 +25,12 @@ #ifndef CAAM_QNX_H #define CAAM_QNX_H -#ifdef WOLFSSL_CAAM_PRINT -#include -#define WOLFSSL_MSG(in) printf("%s\n", (in)) -#else -#define WOLFSSL_MSG(in) -#endif - #include -#include +#ifdef __aarch64__ + #include +#else + #include +#endif #include #include #include @@ -47,7 +44,7 @@ #define Error int #define Value int #define Boolean int -#define CAAM_ADDRESS unsigned int +#define CAAM_ADDRESS uintptr_t #define Success 1 #define Failure 0 #define INTERRUPT_Panic() @@ -55,6 +52,7 @@ #define CAAM_WAITING -2 #define NoActivityReady -1 #define MemoryOperationNotPerformed -1 +#define CAAM_ARGS_E -3 #ifndef WOLFSSL_CAAM_BUFFER #define WOLFSSL_CAAM_BUFFER @@ -68,8 +66,15 @@ /* check kernel and yield to same priority threads waiting */ #define CAAM_CPU_CHILL() sched_yield() -/* IMX6UL */ -#define CAAM_BASE 0x02140000 -#define CAAM_PAGE 0x00100000 +#ifdef __aarch64__ + /* if on an AArch64 system make assumption that it is an i.MX8 QXP */ + /* use block of memory set aside for job ring 2 */ + #define CAAM_BASE 0x31400000 + #define CAAM_PAGE 0x31800000 +#else + /* IMX6UL */ + #define CAAM_BASE 0x02140000 + #define CAAM_PAGE 0x00100000 +#endif #endif /* CAAM_QNX_H */ diff --git a/wolfssl/wolfcrypt/port/caam/wolfcaam.h b/wolfssl/wolfcrypt/port/caam/wolfcaam.h index 7fbed0e88..4b7a374f2 100644 --- a/wolfssl/wolfcrypt/port/caam/wolfcaam.h +++ b/wolfssl/wolfcrypt/port/caam/wolfcaam.h @@ -41,6 +41,15 @@ #define WOLFSSL_CAAM_DEVID 7 #endif +/* black key stored in secure memory location */ +#define CAAM_BLACK_KEY_SM 1 + +/* black key encrypted with AES-CCM (has MAC) */ +#define CAAM_BLACK_KEY_CCM 2 + +/* black key encrypted with AES-ECB (no MAC) */ +#define CAAM_BLACK_KEY_ECB 3 + #if defined(__INTEGRITY) || defined(INTEGRITY) #include typedef Buffer CAAM_BUFFER; diff --git a/wolfssl/wolfcrypt/port/caam/wolfcaam_aes.h b/wolfssl/wolfcrypt/port/caam/wolfcaam_aes.h index 40c58f65c..02ac4b8c0 100644 --- a/wolfssl/wolfcrypt/port/caam/wolfcaam_aes.h +++ b/wolfssl/wolfcrypt/port/caam/wolfcaam_aes.h @@ -45,6 +45,9 @@ WOLFSSL_LOCAL 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); +WOLFSSL_LOCAL int wc_CAAM_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, + word32 sz); + WOLFSSL_LOCAL int wc_CAAM_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz); diff --git a/wolfssl/wolfcrypt/port/caam/wolfcaam_qnx.h b/wolfssl/wolfcrypt/port/caam/wolfcaam_qnx.h index 526d6c486..9e4eb7d04 100644 --- a/wolfssl/wolfcrypt/port/caam/wolfcaam_qnx.h +++ b/wolfssl/wolfcrypt/port/caam/wolfcaam_qnx.h @@ -41,7 +41,7 @@ #define NoActivityReady -1 #define MemoryOperationNotPerformed -1 -#define CAAM_ADDRESS unsigned int +#define CAAM_ADDRESS uintptr_t #ifndef WOLFSSL_CAAM_BUFFER #define WOLFSSL_CAAM_BUFFER typedef struct CAAM_BUFFER { @@ -65,6 +65,7 @@ #include #include +#include #include #define ResourceNotAvailable -3