Browse Source

add support for i.MX8 with QNX CAAM

JacobBarthelmeh 2 years ago
parent
commit
c0d7f3b2e6

+ 3 - 0
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 \

+ 1 - 0
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"

+ 9 - 0
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) {

+ 2 - 2
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

+ 33 - 0
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)

+ 61 - 15
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,

File diff suppressed because it is too large
+ 498 - 174
wolfcrypt/src/port/caam/caam_driver.c


+ 22 - 5
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

+ 461 - 51
wolfcrypt/src/port/caam/caam_qnx.c

@@ -23,6 +23,10 @@
     #include <config.h>
 #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 <wolfssl/wolfcrypt/settings.h>
 
 #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;
 }
 
 
+int CAAM_SET_JOBRING_ADDR(CAAM_ADDRESS* base, CAAM_ADDRESS* ringInPhy,
+    void** ringInVir)
+{
+    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()
+void CAAM_UNSET_BASEADDR(CAAM_ADDRESS baseAddr)
 {
-    munmap_device_io(virtual_base, 0x00010000);
+#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;
+
+    /* 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) {
+        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(&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 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++;
+    }
 
-    caamDescInit(&desc, CAAM_ECDSA_KEYPAIR, args, tmp, 2);
-    ret = caamECDSAMake(&desc, tmp, args);
-    if (ret != Success) {
-        return ECANCELED;
+    /* create output buffer to store results */
+    if (ret == EOK) {
+        outSz = args[2]; /* output size */
+        out   = (unsigned char*)CAAM_ADR_MAP(0, outSz, 0);
     }
 
-    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;
+    /* 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;
+        }
     }
 
-    /* claim ownership of a secure memory location */
-    if (pthread_mutex_lock(&sm_mutex) != EOK) {
-        return 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++;
+        }
     }
-    else {
-        sm_ownerId[args[2]] = (CAAM_ADDRESS)ocb;
-        pthread_mutex_unlock(&sm_mutex);
+
+    if (ret == EOK) {
+        if (resmgr_msgreadv(ctp, in_iovs, inIdx, idx) < 0) {
+            ret = EBADMSG;
+        }
     }
 
-    return EOK;
+    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 (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);
+        }
+    }
+
+    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"
 };

+ 178 - 20
wolfcrypt/src/port/caam/wolfcaam_aes.c

@@ -32,6 +32,13 @@
 #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
 #include <wolfssl/wolfcrypt/port/caam/wolfcaam_aes.h>
 
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
 /* 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;

+ 85 - 26
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;

+ 23 - 14
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;

+ 147 - 32
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;

+ 1 - 1
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 <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
 

+ 27 - 2
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) {

+ 12 - 0
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);

+ 68 - 43
wolfssl/wolfcrypt/port/caam/caam_driver.h

@@ -31,6 +31,14 @@
     #define CAAM_PAGE 0xf0100000
 #endif
 
+#ifdef WOLFSSL_CAAM_PRINT
+    #include <stdio.h>
+    #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_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_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  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_<env>.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);
 

+ 16 - 11
wolfssl/wolfcrypt/port/caam/caam_qnx.h

@@ -25,15 +25,12 @@
 #ifndef CAAM_QNX_H
 #define CAAM_QNX_H
 
-#ifdef WOLFSSL_CAAM_PRINT
-#include <stdio.h>
-#define WOLFSSL_MSG(in) printf("%s\n", (in))
+#include <sys/mman.h>
+#ifdef __aarch64__
+    #include <aarch64/inout.h>
 #else
-#define WOLFSSL_MSG(in)
+    #include <hw/inout.h>
 #endif
-
-#include <sys/mman.h>
-#include <hw/inout.h>
 #include <sys/iofunc.h>
 #include <sys/neutrino.h>
 #include <pthread.h>
@@ -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 */

+ 9 - 0
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 <INTEGRITY.h>
     typedef Buffer CAAM_BUFFER;

+ 3 - 0
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);
 

+ 2 - 1
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 <wolfssl/wolfcrypt/port/caam/wolfcaam_ecdsa.h>
 #include <wolfssl/wolfcrypt/port/caam/wolfcaam_cmac.h>
+#include <wolfssl/wolfcrypt/port/caam/wolfcaam_aes.h>
 #include <wolfssl/wolfcrypt/cryptocb.h>
 
 #define ResourceNotAvailable -3

Some files were not shown because too many files changed in this diff