Browse Source

Merge pull request #1270 from JacobBarthelmeh/CAAM

add CAAM with INTEGRITY support
dgarske 6 years ago
parent
commit
3f53e8d1dd

+ 4 - 4
src/internal.c

@@ -6084,7 +6084,7 @@ static void AddFragHeaders(byte* output, word32 fragSz, word32 fragOffset,
 
 
 /* return bytes received, -1 on error */
-static int Receive(WOLFSSL* ssl, byte* buf, word32 sz)
+static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz)
 {
     int recvd;
 
@@ -11613,7 +11613,7 @@ static int GetInputData(WOLFSSL *ssl, word32 size)
 
     /* read data from network */
     do {
-        in = Receive(ssl,
+        in = wolfSSLReceive(ssl,
                      ssl->buffers.inputBuffer.buffer +
                      ssl->buffers.inputBuffer.length,
                      inSz);
@@ -19615,8 +19615,6 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
 #if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)
     int      keySz;
     word32   idx;
-    (void)idx;
-    (void)keySz;
 #else
     (void)length;
 #endif
@@ -19743,6 +19741,8 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
     }
 #endif
 
+    (void)idx;
+    (void)keySz;
 exit_dpk:
     return ret;
 }

+ 6 - 6
src/wolfio.c

@@ -88,7 +88,7 @@ static INLINE int TranslateReturnCode(int old, int sd)
     return old;
 }
 
-static INLINE int LastError(void)
+static INLINE int wolfSSL_LastError(void)
 {
 #ifdef USE_WINDOWS_API
     return WSAGetLastError();
@@ -135,7 +135,7 @@ int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
 
     recvd = wolfIO_Recv(sd, buf, sz, ssl->rflags);
     if (recvd < 0) {
-        int err = LastError();
+        int err = wolfSSL_LastError();
         WOLFSSL_MSG("Embed Receive error");
 
         if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
@@ -187,7 +187,7 @@ int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
 
     sent = wolfIO_Send(sd, buf, sz, ssl->wflags);
     if (sent < 0) {
-        int err = LastError();
+        int err = wolfSSL_LastError();
         WOLFSSL_MSG("Embed Send error");
 
         if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
@@ -262,7 +262,7 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
     recvd = TranslateReturnCode(recvd, sd);
 
     if (recvd < 0) {
-        err = LastError();
+        err = wolfSSL_LastError();
         WOLFSSL_MSG("Embed Receive From error");
 
         if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
@@ -325,7 +325,7 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
     sent = TranslateReturnCode(sent, sd);
 
     if (sent < 0) {
-        err = LastError();
+        err = wolfSSL_LastError();
         WOLFSSL_MSG("Embed Send To error");
 
         if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
@@ -373,7 +373,7 @@ int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx)
     recvd = TranslateReturnCode(recvd, sd);
 
     if (recvd < 0) {
-        err = LastError();
+        err = wolfSSL_LastError();
         WOLFSSL_MSG("Embed Receive From error");
 
         if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {

+ 218 - 4
wolfcrypt/src/aes.c

@@ -243,7 +243,13 @@
     #include <wolfcrypt/src/misc.c>
 #endif
 
-#ifndef WOLFSSL_ARMASM
+#if !defined(WOLFSSL_ARMASM)
+
+#ifdef WOLFSSL_IMX6_CAAM_BLOB
+    /* case of possibly not using hardware acceleration for AES but using key
+       blobs */
+    #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
+#endif
 
 #ifdef DEBUG_AESNI
     #include <stdio.h>
@@ -781,6 +787,17 @@
         }
     #endif /* HAVE_AES_DECRYPT */
 
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+        static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+        {
+            wc_AesEncryptDirect(aes, outBlock, inBlock);
+            return 0;
+        }
+        static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+        {
+            wc_AesDecryptDirect(aes, outBlock, inBlock);
+            return 0;
+        }
 #else
 
     /* using wolfCrypt software AES implementation */
@@ -1974,6 +1991,9 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
         return wc_AesSetKey(aes, userKey, keylen, iv, dir);
     }
 
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+      /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
+
 #else
     static int wc_AesSetKeyLocal(Aes* aes, const byte* userKey, word32 keylen,
                 const byte* iv, int dir)
@@ -2131,10 +2151,27 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
     int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
         const byte* iv, int dir)
     {
+        int ret;
     #if defined(AES_MAX_KEY_SIZE)
         const word32 max_key_len = (AES_MAX_KEY_SIZE / 8);
     #endif
 
+    #ifdef WOLFSSL_IMX6_CAAM_BLOB
+        byte   local[32];
+        word32 localSz = 32;
+
+        if (keylen == (16 + WC_CAAM_BLOB_SZ) ||
+                keylen == (24 + WC_CAAM_BLOB_SZ) ||
+                keylen == (32 + WC_CAAM_BLOB_SZ)) {
+            if (wc_caamOpenBlob((byte*)userKey, keylen, local, &localSz) != 0) {
+                return BAD_FUNC_ARG;
+            }
+
+            /* set local values */
+            userKey = local;
+            keylen = localSz;
+        }
+    #endif
         if (aes == NULL ||
                 !((keylen == 16) || (keylen == 24) || (keylen == 32))) {
             return BAD_FUNC_ARG;
@@ -2178,7 +2215,12 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
         }
     #endif /* WOLFSSL_AESNI */
 
-        return wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir);
+        ret = wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir);
+
+    #ifdef WOLFSSL_IMX6_CAAM_BLOB
+        ForceZero(local, sizeof(local));
+    #endif
+        return ret;
     }
 
     #if defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER)
@@ -2186,7 +2228,32 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
         int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen,
                             const byte* iv, int dir)
         {
-            return wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir);
+            int ret;
+
+        #ifdef WOLFSSL_IMX6_CAAM_BLOB
+            byte   local[32];
+            word32 localSz = 32;
+
+            if (keylen == (16 + WC_CAAM_BLOB_SZ) ||
+             keylen == (24 + WC_CAAM_BLOB_SZ) ||
+             keylen == (32 + WC_CAAM_BLOB_SZ)) {
+                if (wc_caamOpenBlob((byte*)userKey, keylen, local, &localSz)
+                        != 0) {
+                    return BAD_FUNC_ARG;
+                }
+
+                /* set local values */
+                userKey = local;
+                keylen = localSz;
+            }
+        #endif
+            ret = wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir);
+
+        #ifdef WOLFSSL_IMX6_CAAM_BLOB
+            ForceZero(local, sizeof(local));
+        #endif
+
+            return ret;
         }
     #endif /* WOLFSSL_AES_DIRECT || WOLFSSL_AES_COUNTER */
 #endif /* wc_AesSetKey block */
@@ -2238,6 +2305,9 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
                 key, keySize, kLTC_EncryptKey);
         }
 
+    #elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+        /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
+
     #else
         /* Allow direct access to one block encrypt */
         void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
@@ -2805,6 +2875,9 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
     }
     #endif /* HAVE_AES_DECRYPT */
 
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+      /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
+
 #else
 
     int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
@@ -2977,6 +3050,11 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
 #endif /* HAVE_AES_CBC */
 
 #ifdef HAVE_AES_ECB
+#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+    /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
+#else
+
+/* software implementation */
 int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
 {
     word32 blocks = sz / AES_BLOCK_SIZE;
@@ -3010,6 +3088,7 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
     return 0;
 }
 #endif
+#endif
 
 /* AES-CTR */
 #if defined(WOLFSSL_AES_COUNTER)
@@ -3195,6 +3274,9 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
             return 0;
         }
 
+    #elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+        /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
+
     #else
 
         /* Use software based AES counter */
@@ -3377,6 +3459,23 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
     int  ret;
     byte iv[AES_BLOCK_SIZE];
 
+    #ifdef WOLFSSL_IMX6_CAAM_BLOB
+        byte   local[32];
+        word32 localSz = 32;
+
+        if (len == (16 + WC_CAAM_BLOB_SZ) ||
+          len == (24 + WC_CAAM_BLOB_SZ) ||
+          len == (32 + WC_CAAM_BLOB_SZ)) {
+            if (wc_caamOpenBlob((byte*)key, len, local, &localSz) != 0) {
+                 return BAD_FUNC_ARG;
+            }
+
+            /* set local values */
+            key = local;
+            len = localSz;
+        }
+    #endif
+
     if (!((len == 16) || (len == 24) || (len == 32)))
         return BAD_FUNC_ARG;
 
@@ -3402,6 +3501,10 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
     wc_AesGcmSetKey_ex(aes, key, len, XSECURE_CSU_AES_KEY_SRC_KUP);
 #endif
 
+#ifdef WOLFSSL_IMX6_CAAM_BLOB
+    ForceZero(local, sizeof(local));
+#endif
+
     return ret;
 }
 
@@ -6858,6 +6961,25 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
     }
     /* process remainder using partial handling */
 #endif
+
+#if defined(HAVE_AES_ECB) && !defined(WOLFSSL_PIC32MZ_CRYPT)
+    /* some hardware acceleration can gain performance from doing AES encryption
+     * of the whole buffer at once */
+    if (c != p) { /* can not handle inline encryption */
+        while (blocks--) {
+            IncrementGcmCounter(ctr);
+            XMEMCPY(c, ctr, AES_BLOCK_SIZE);
+            c += AES_BLOCK_SIZE;
+        }
+
+        /* reset number of blocks and then do encryption */
+        blocks = sz / AES_BLOCK_SIZE;
+        wc_AesEcbEncrypt(aes, out, out, AES_BLOCK_SIZE * blocks);
+        xorbuf(out, p, AES_BLOCK_SIZE * blocks);
+        p += AES_BLOCK_SIZE * blocks;
+    }
+    else
+#endif /* HAVE_AES_ECB */
     while (blocks--) {
         IncrementGcmCounter(ctr);
     #ifndef WOLFSSL_PIC32MZ_CRYPT
@@ -7137,6 +7259,24 @@ int  wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
     /* process remainder using partial handling */
 #endif
 
+#if defined(HAVE_AES_ECB) && !defined(WOLFSSL_PIC32MZ_CRYPT)
+    /* some hardware acceleration can gain performance from doing AES encryption
+     * of the whole buffer at once */
+    if (c != p) { /* can not handle inline decryption */
+        while (blocks--) {
+            IncrementGcmCounter(ctr);
+            XMEMCPY(p, ctr, AES_BLOCK_SIZE);
+            p += AES_BLOCK_SIZE;
+        }
+
+        /* reset number of blocks and then do encryption */
+        blocks = sz / AES_BLOCK_SIZE;
+        wc_AesEcbEncrypt(aes, out, out, AES_BLOCK_SIZE * blocks);
+        xorbuf(out, c, AES_BLOCK_SIZE * blocks);
+        c += AES_BLOCK_SIZE * blocks;
+    }
+    else
+#endif /* HAVE_AES_ECB */
     while (blocks--) {
         IncrementGcmCounter(ctr);
     #ifndef WOLFSSL_PIC32MZ_CRYPT
@@ -7147,13 +7287,13 @@ int  wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
         p += AES_BLOCK_SIZE;
         c += AES_BLOCK_SIZE;
     }
+
     if (partial != 0) {
         IncrementGcmCounter(ctr);
         wc_AesEncrypt(aes, ctr, scratch);
         xorbuf(scratch, c, partial);
         XMEMCPY(p, scratch, partial);
     }
-
 #endif
 
     return ret;
@@ -7192,6 +7332,9 @@ int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz)
 #if defined(HAVE_COLDFIRE_SEC)
     #error "Coldfire SEC doesn't currently support AES-CCM mode"
 
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+    /* implemented in wolfcrypt/src/port/caam_aes.c */
+
 #elif defined(FREESCALE_LTC)
 
 /* return 0 on success */
@@ -7869,6 +8012,45 @@ int wc_AesXtsDecryptSector(XtsAes* aes, byte* out, const byte* in, word32 sz,
     return wc_AesXtsDecrypt(aes, out, in, sz, (const byte*)i, AES_BLOCK_SIZE);
 }
 
+#ifdef HAVE_AES_ECB
+/* helper function for encrypting / decrypting full buffer at once */
+static int _AesXtsHelper(Aes* aes, byte* out, const byte* in, word32 sz, int dir)
+{
+    word32 outSz   = sz;
+    word32 totalSz = (sz / AES_BLOCK_SIZE) * AES_BLOCK_SIZE; /* total bytes */
+    byte*  pt      = out;
+
+    outSz -= AES_BLOCK_SIZE;
+
+    while (outSz > 0) {
+        word32 j;
+        byte carry = 0;
+
+        /* multiply by shift left and propogate carry */
+        for (j = 0; j < AES_BLOCK_SIZE && outSz > 0; j++, outSz--) {
+            byte tmpC;
+
+            tmpC   = (pt[j] >> 7) & 0x01;
+            pt[j+AES_BLOCK_SIZE] = ((pt[j] << 1) + carry) & 0xFF;
+            carry  = tmpC;
+        }
+        if (carry) {
+            pt[AES_BLOCK_SIZE] ^= GF_XTS;
+        }
+
+        pt += AES_BLOCK_SIZE;
+    }
+
+    xorbuf(out, in, totalSz);
+    if (dir == AES_ENCRYPTION) {
+        return wc_AesEcbEncrypt(aes, out, out, totalSz);
+    }
+    else {
+        return wc_AesEcbDecrypt(aes, out, out, totalSz);
+    }
+}
+#endif /* HAVE_AES_ECB */
+
 
 /* AES with XTS mode. (XTS) XEX encryption with Tweak and cipher text Stealing.
  *
@@ -7908,14 +8090,30 @@ int wc_AesXtsEncrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
 
         wc_AesEncryptDirect(tweak, tmp, i);
 
+    #ifdef HAVE_AES_ECB
+        /* encrypt all of buffer at once when possible */
+        if (in != out) { /* can not handle inline */
+            XMEMCPY(out, tmp, AES_BLOCK_SIZE);
+            if ((ret = _AesXtsHelper(aes, out, in, sz, AES_ENCRYPTION)) != 0) {
+                return ret;
+            }
+        }
+    #endif
+
         while (blocks > 0) {
             word32 j;
             byte carry = 0;
             byte buf[AES_BLOCK_SIZE];
 
+    #ifdef HAVE_AES_ECB
+            if (in == out) { /* check for if inline */
+    #endif
             XMEMCPY(buf, in, AES_BLOCK_SIZE);
             xorbuf(buf, tmp, AES_BLOCK_SIZE);
             wc_AesEncryptDirect(aes, out, buf);
+    #ifdef HAVE_AES_ECB
+            }
+    #endif
             xorbuf(out, tmp, AES_BLOCK_SIZE);
 
             /* multiply by shift left and propogate carry */
@@ -8008,12 +8206,28 @@ int wc_AesXtsDecrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
             blocks--;
         }
 
+    #ifdef HAVE_AES_ECB
+        /* decrypt all of buffer at once when possible */
+        if (in != out) { /* can not handle inline */
+            XMEMCPY(out, tmp, AES_BLOCK_SIZE);
+            if ((ret = _AesXtsHelper(aes, out, in, sz, AES_DECRYPTION)) != 0) {
+                return ret;
+            }
+        }
+    #endif
+
         while (blocks > 0) {
             byte buf[AES_BLOCK_SIZE];
 
+    #ifdef HAVE_AES_ECB
+            if (in == out) { /* check for if inline */
+    #endif
             XMEMCPY(buf, in, AES_BLOCK_SIZE);
             xorbuf(buf, tmp, AES_BLOCK_SIZE);
             wc_AesDecryptDirect(aes, out, buf);
+    #ifdef HAVE_AES_ECB
+            }
+    #endif
             xorbuf(out, tmp, AES_BLOCK_SIZE);
 
             /* multiply by shift left and propogate carry */

+ 6 - 0
wolfcrypt/src/error.c

@@ -434,6 +434,12 @@ const char* wc_GetErrorString(int error)
     case ECC_PRIVATEONLY_E:
         return "Invalid use of private only ECC key";
 
+    case WC_HW_E:
+        return "Error with hardware crypto use";
+
+    case WC_HW_WAIT_E:
+        return "Hardware waiting on resource";
+
     default:
         return "unknown error number";
 

+ 2 - 0
wolfcrypt/src/hmac.c

@@ -166,6 +166,8 @@ int wc_HmacSizeByType(int type)
     return ret;
 }
 
+
+/* software implementation */
 static int _InitHmac(Hmac* hmac, int type, void* heap)
 {
     int ret = 0;

+ 6 - 1
wolfcrypt/src/include.am

@@ -55,7 +55,12 @@ EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \
               wolfcrypt/src/port/atmel/atmel.c \
               wolfcrypt/src/port/atmel/README.md \
               wolfcrypt/src/port/xilinx/xil-sha3.c \
-              wolfcrypt/src/port/xilinx/xil-aesgcm.c
+              wolfcrypt/src/port/xilinx/xil-aesgcm.c \
+              wolfcrypt/src/port/caam/caam_aes.c \
+              wolfcrypt/src/port/caam/caam_driver.c \
+              wolfcrypt/src/port/caam/caam_init.c \
+              wolfcrypt/src/port/caam/caam_sha.c \
+              wolfcrypt/src/port/caam/caam_doc.pdf
 
 if BUILD_CAVIUM
 src_libwolfssl_la_SOURCES += wolfcrypt/src/port/cavium/cavium_nitrox.c

+ 3 - 0
wolfcrypt/src/md5.c

@@ -225,6 +225,9 @@ static INLINE void AddLength(wc_Md5* md5, word32 len);
     #include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
     #define HAVE_MD5_CUST_API
 
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
+    /* functions implemented in wolfcrypt/src/port/caam/caam_sha.c */
+    #define HAVE_MD5_CUST_API
 #else
     #define NEED_SOFT_MD5
 

+ 1 - 0
wolfcrypt/src/port/caam/README.md

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

+ 649 - 0
wolfcrypt/src/port/caam/caam_aes.c

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

BIN
wolfcrypt/src/port/caam/caam_doc.pdf


+ 1709 - 0
wolfcrypt/src/port/caam/caam_driver.c

@@ -0,0 +1,1709 @@
+/* caam_driver.c
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* build into Integrity kernel */
+#include <bsp.h>
+#include "wolfssl/wolfcrypt/port/caam/caam_driver.h"
+
+#define CAAM_READ(reg) *(volatile unsigned int*)(reg)
+#define CAAM_WRITE(reg, in) *(volatile unsigned int*)(reg) = (in);
+
+#define DESC_COUNT 1
+#define MAX_BUF 20
+#define BUFFER_COUNT (MAX_BUF * DESC_COUNT)
+
+/* CAAM descriptors can only be 64 unsigned ints */
+#define MAX_DESC_SZ 64
+
+/* 64 byte buffer for when data crosses a page boundary */
+#define ALIGN_BUF 16
+
+/* MAX_CTX is 64 bytes (sha512 digest) + 8 bytes (CAAM length value) */
+#define MAX_CTX 18
+
+#define MIN_READ_REG 0xF2100000
+#define MAX_READ_REG 0XF2110000
+
+struct JobRing {
+    Address JobIn;
+    Address JobOut;
+    Address Desc;
+    Value   page;    /* page allocation for descriptor to use */
+};
+
+struct buffer {
+    Address data;
+    Address dataSz;
+};
+
+/* CAAM descriptor */
+struct DescStruct {
+    struct IORequestStruct TheIORequest;
+    struct CAAM_DEVICE*    caam;
+    struct buffer          buf[MAX_BUF]; /* buffers holding data input address */
+    UINT4                  desc[MAX_DESC_SZ]; /* max size of 64 word32 */
+    UINT4                  aadSzBuf[4];       /* Formated AAD size for CCM */
+    UINT4                  alignBuf[ALIGN_BUF]; /* 64 byte buffer for non page
+                                                   align */
+    UINT4                  iv[MAX_CTX]; /* AES IV and also hash state */
+    UINT4                  ctxBuf[MAX_CTX]; /* key */
+    Address                output; /* address to output buffer */
+    Address                ctxOut; /* address to update buffer holding state */
+    Value                  alignIdx;/* index for align buffer */
+    Value                  idx;     /* index for descriptor buffer */
+    Value                  headIdx; /* for first portion of descriptor buffer */
+    Value                  lastIdx; /* for last portion of descriptor buffer */
+    Value                  outputIdx; /* idx to output buffer in "buf" */
+    Value                  inputSz;   /* size of input buffer */
+    Value                  ctxSz;     /* size of CTX/Key buffer */
+    Value                  aadSz;     /* AAD size for CCM */
+    Value                  lastFifo;
+    Value                  type;
+    Value                  state;
+    Value                  DescriptorCount;
+    Boolean                running; /* True if building/running descriptor is
+                                       in process */
+};
+
+struct CAAM_DEVICE {
+    struct IODeviceVectorStruct caamVector;
+    struct IODescriptorStruct   IODescriptorArray[BUFFER_COUNT];
+    struct DescStruct           DescArray[DESC_COUNT];
+    volatile Value              InterruptStatus;
+    CALL                        HandleInterruptCall;
+    struct JobRing              ring;
+};
+
+#define DRIVER_NAME "wolfSSL_CAAM_Driver"
+
+static struct CAAM_DEVICE caam;
+
+/******************************************************************************
+  Internal CAAM Job Ring and partition functions
+  ****************************************************************************/
+
+/* flush job ring and reset */
+static Error caamReset()
+{
+    int t = 100000; /* time out counter for flushing job ring */
+
+    /* make sure interrupts are masked in JRCFGR0_LS register */
+    CAAM_WRITE(CAAM_BASE | 0x1054, CAAM_READ(CAAM_BASE | 0x1054) | 1);
+
+    /* flush and reset job rings using JRCR0 register */
+    CAAM_WRITE(CAAM_BASE | 0x106C, 1);
+
+    /* check register JRINTR for if halt is in progress */
+    while (t > 0 && ((CAAM_READ(CAAM_BASE | 0x104C) & 0x4) == 0x4)) t--;
+    if (t == 0) {
+        /*unrecoverable failure, the job ring is locked, up hard reset needed*/
+        return NotRestartable;
+    }
+
+    /* now that flush has been done restart the job ring */
+    t = 100000;
+    CAAM_WRITE(CAAM_BASE | 0x106C, 1);
+    while (t > 0 && ((CAAM_READ(CAAM_BASE | 0x106C) & 1) == 1)) t--;
+    if (t == 0) {
+        /*unrecoverable failure, reset bit did not return to 0 */
+        return NotRestartable;
+    }
+
+    /* reset most registers and state machines in CAAM using MCFGR register
+       also reset DMA */
+    CAAM_WRITE(CAAM_BASE | 0x0004, 0x90000000);
+
+    return Success;
+}
+
+/* returns MemoryMapMayNotBeEmpty if page/par is already owned
+ * returns Success on success
+ * all other returns is an error state
+ */
+static Error caamCreatePartition(unsigned char page, unsigned char par)
+{
+    /* check ownership of partition */
+    if ((CAAM_READ(CAAM_BASE | 0x1FBC) & (0x3 << (par * 2))) > 0) {
+        return MemoryMapMayNotBeEmpty;
+    }
+
+    /* set generic all access permissions, gets reset later */
+    CAAM_WRITE(CAAM_BASE | (0x1108 + (par * 16)), 0xF);
+    CAAM_WRITE(CAAM_BASE | (0x110C + (par * 16)), 0xF);
+    CAAM_WRITE(CAAM_BASE | (0x1104 + (par * 16)), 0xFF);
+
+    /* check ownership of page */
+    CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | 0x5);
+    /* wait for inquiry cmd to complete */
+    while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 &&
+       (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000)  == 0) {
+    }
+    if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x000000C0) == 0xC0) {
+        /* owns the page can dealloc it */
+        CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | 0x2);
+        while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 &&
+               (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000)  == 0) {}
+        if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000)  > 0) {
+            /* error while deallocating page */
+            return MemoryMapMayNotBeEmpty; /* PSP set on page or is unavailable */
+        }
+    }
+    else {
+        /* check if owned by someone else */
+        if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x000000C0) != 0) {
+            return MemoryMapMayNotBeEmpty;
+        }
+    }
+
+    /* allocate page to partition */
+    CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | (par << 8) | 0x1);
+    /* wait for alloc cmd to complete */
+    while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 &&
+       (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000)  == 0) {
+    }
+
+    if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) > 0) {
+        return MemoryOperationNotPerformed;
+    }
+
+    /* double check ownership now of page */
+    CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | 0x5);
+    /* wait for inquiry cmd to complete */
+    while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 &&
+       (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000)  == 0) {
+    }
+    if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000000F) == 0 ||
+        (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) > 0) {
+        /* page not owned */
+        return MemoryOperationNotPerformed;
+    }
+
+    return Success;
+}
+
+
+/* Gets the status of a job. Returns Waiting if no output jobs ready to be
+ * read.
+ * If no jobs are done then return Waiting
+ * If jobs are done but does not match desc then return NoActivityReady
+ * Status holds the error values if any */
+static Error caamGetJob(struct CAAM_DEVICE* dev, UINT4* status)
+{
+    UINT4 reg = CAAM_READ(CAAM_BASE | 0x1044); /* JRSTAR0 status */
+    if (status) {
+        *status = 0;
+    }
+
+    /* check for DECO, CCB, and Job Ring error state JRSTAR0 register */
+    if (((reg & 0xF0000000) == 0x20000000) ||         /* CCB error */
+        ((reg & 0xF0000000) == 0x40000000)||  /* DECO error */
+        ((reg & 0xF0000000) == 0x60000000)) { /* Job Ring error */
+
+        if ((reg & 0x0000000F) > 0) {
+            *status = reg;
+            return Failure;
+        }
+    }
+
+    /* Check number of done jobs in output list */
+    reg = CAAM_READ(CAAM_BASE | 0x103C);
+    if ((reg & 0x000003FF) > 0) {
+        UINT4* out = (UINT4*)(dev->ring.JobOut);
+        if (status) {
+            *status = out[1];
+        }
+
+        if ((dev->ring.Desc ^ 0xF0000000) != out[0]) {
+            db_printf("CAAM job completed vs expected mismatch");
+            return NoActivityReady;
+        }
+
+        if (out[1] > 0) {
+            return Failure;
+        }
+
+        /* increment jobs removed */
+        CAAM_WRITE(CAAM_BASE | 0x1034, 1);
+    }
+    else {
+        /* check if the CAAM is idle and not processing any descriptors */
+        if ((CAAM_READ(CAAM_BASE | 0x0FD4) & 0x00000002) == 2 /* idle */
+        && (CAAM_READ(CAAM_BASE | 0x0FD4) & 0x00000001) == 0) {
+            return NoActivityReady;
+        }
+
+        return Waiting;
+    }
+
+    return Success;
+}
+
+
+/* Initialize CAAM RNG
+ * returns 0 on success */
+static int caamInitRng(struct CAAM_DEVICE* dev)
+{
+    UINT4 reg, status;
+    int ret = 0;
+
+    /* Set up use of the TRNG for seeding wolfSSL HASH-DRBG */
+    CAAM_WRITE(CAAM_RTMCTL, CAAM_PRGM);
+    CAAM_WRITE(CAAM_RTMCTL, CAAM_READ(CAAM_RTMCTL) | 0x40); /* reset */
+
+    /* Set up reading from TRNG */
+    CAAM_WRITE(CAAM_RTMCTL, CAAM_READ(CAAM_RTMCTL) | CAAM_TRNG);
+
+    /* Set up delay for TRNG @TODO Optimizations?
+     * Shift left with RTSDCTL because 0-15 is for sample number
+     * Also setting the max and min frequencies */
+    CAAM_WRITE(CAAM_RTSDCTL, (CAAM_ENT_DLY << 16) | 0x09C4);
+    CAAM_WRITE(CAAM_RTFRQMIN, CAAM_ENT_DLY >> 1); /* 1/2      */
+    CAAM_WRITE(CAAM_RTFRQMAX, CAAM_ENT_DLY << 3); /* up to 8x */
+
+    /* Set back to run mode and clear RTMCL error bit */
+    reg = CAAM_READ(CAAM_RTMCTL) ^ CAAM_PRGM;
+
+    CAAM_WRITE(CAAM_RTMCTL, reg);
+    reg = CAAM_READ(CAAM_RTMCTL);
+    reg |= CAAM_CTLERR;
+    CAAM_WRITE(CAAM_RTMCTL, reg);
+
+    /* check input slot is available and then add */
+    if (CAAM_READ(CAAM_BASE | 0x1014) > 0) {
+        UINT4* in = (UINT4*)dev->ring.JobIn;
+
+        memcpy((unsigned char*)dev->ring.Desc, (unsigned char*)wc_rng_start,
+        sizeof(wc_rng_start));
+
+        in[0] = dev->ring.Desc ^ 0xF0000000; /* physical address */
+        CAAM_WRITE(CAAM_IRJAR0, 0x00000001);
+    }
+    else {
+        return Waiting;
+    }
+
+    do {
+        ret = caamGetJob(dev, &status);
+        /* @TODO use a better way to chill out CPU. */
+    } while (ret == Waiting);
+
+    return ret;
+}
+
+
+static Error caamDoJob(struct DescStruct* desc)
+{
+    Error ret;
+    UINT4 status;
+
+    /* clear and set desc size */
+    desc->desc[0] &= 0xFFFFFF80;
+    desc->desc[0] += desc->idx;
+
+    /* check input slot is available and then add */
+    if (CAAM_READ(CAAM_BASE | 0x1014) > 0) {
+        UINT4* in = (UINT4*)desc->caam->ring.JobIn;
+
+        memcpy((unsigned char*)desc->caam->ring.Desc, (unsigned char*)desc->desc,
+        (desc->idx + 1) * sizeof(UINT4));
+
+        in[0] = desc->caam->ring.Desc ^ 0xF0000000; /* physical address */
+        CAAM_WRITE(CAAM_IRJAR0, 0x00000001);
+    }
+    else {
+        return Waiting;
+    }
+
+    do {
+        ret = caamGetJob(desc->caam, &status);
+    /* @TODO use a better way to chill out CPU. */
+    } while (ret == Waiting);
+
+    if (status != 0 || ret != Success) {
+        #if 0
+        /* Used during testing to print out descriptor */
+        {
+        char msg[2048];
+        char* pt = msg;
+        int z;
+
+        memset(msg, 0, sizeof(msg));
+        for (z = 0; z < desc->idx; z++) {
+                    snprintf(pt, sizeof(msg) - (z * 21), "desc[%d] = 0x%8.8x, ",
+                z, desc->desc[z]);
+            pt += 21;
+        }
+        snprintf(pt, sizeof(msg) - (z * 21), "status = 0x%8.8x\n", status);
+        if (desc->buf[0].data != 0) { /* for testing */
+            memcpy((char*)desc->buf[0].data, msg, sizeof(msg));
+        }
+        }
+        #endif
+
+
+        /* try to reset after error */
+        caamReset();
+        return ret;
+    }
+
+    return Success;
+}
+
+
+/* handle input or output buffers
+ * NOTES: if sz == 0 then read all the rest of the buffers available
+ * when align == 1 then there is no alignment constraints
+ *
+ * returns the data size in bytes on success. With failure a negative value is
+ * returned.
+ */
+static int caamAddIO(struct DescStruct* desc, UINT4 options, UINT4 sz,
+    UINT4 align, UINT4* idx)
+{
+    int i, outSz = 0;
+
+    if (align == 0) {
+        return -1; /* programming error */
+    }
+
+    for (i = *idx; i < desc->DescriptorCount; i++) {
+        /* input must be a multiple of "align" bytes */
+        struct buffer* buf = &desc->buf[i];
+        int blocks = buf->dataSz / align;
+        Address data   = buf->data;
+        Address dataSz = buf->dataSz;
+
+        if (outSz >= sz && sz != 0) {
+            break;
+        }
+
+        if (dataSz % align > 0) {
+            /* store potential overlap */
+            int tmpSz  = dataSz % align;
+            int add = (tmpSz < (align - desc->alignIdx)) ? tmpSz :
+                align - desc->alignIdx;
+            unsigned char* local = (unsigned char*)desc->alignBuf;
+
+            /* if already something in the buffer then add from front */
+            if (desc->alignIdx > 0) {
+                memcpy((unsigned char*)&local[desc->alignIdx],
+                (unsigned char*)data, add);
+                data += add;
+            }
+            else {
+                memcpy((unsigned char*)&local[desc->alignIdx],
+                (unsigned char*)data + (blocks * align), add);
+            }
+            dataSz -= add;
+            desc->alignIdx += add;
+        }
+
+        if (desc->alignIdx == align) {
+            desc->lastFifo = desc->idx;
+            if (desc->idx + 2 > MAX_DESC_SZ) {
+                return -1;
+            }
+            desc->desc[desc->idx++] = options + desc->alignIdx;
+            desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->alignBuf);
+            ASP_FlushCaches((Address)desc->alignBuf, desc->alignIdx);
+            outSz += desc->alignIdx;
+        }
+
+        if (blocks > 0) {
+            desc->lastFifo = desc->idx;
+            if (desc->idx + 2 > MAX_DESC_SZ) {
+                return -1;
+            }
+            desc->desc[desc->idx++] = options + (blocks * align);
+            desc->desc[desc->idx++] = BSP_VirtualToPhysical(data);
+            outSz += (blocks * align);
+
+            /* only one buffer available for align cases so exit here and make
+            a new descriptor after running current one */
+            if (desc->alignIdx == align) {
+                desc->alignIdx = 0;
+                i++; /* start at next buffer */
+                break;
+            }
+        }
+    }
+
+    *idx = i;
+    return outSz;
+}
+
+
+/******************************************************************************
+  IODevice Register Read and Write
+  ****************************************************************************/
+
+static Error caamReadRegister(IODeviceVector ioCaam, Value reg, Value *out)
+{
+    if (reg < MIN_READ_REG || reg > MAX_READ_REG) {
+         return IllegalRegisterNumber;
+    }
+
+    switch (reg) {
+    case CAAM_STATUS:
+    case CAAM_VERSION_MS:
+    case CAAM_VERSION_LS:
+    case CAMM_SUPPORT_MS:
+    case CAMM_SUPPORT_LS:
+    case CAAM_RTMCTL:
+        *out = CAAM_READ(reg);
+        break;
+
+    default:
+        return IllegalRegisterNumber;
+    }
+
+    (void)ioCaam;
+    return Success;
+}
+
+
+static Error caamWriteRegister(IODeviceVector ioCaam, Value reg, Value in)
+{
+    /* Should be no need for writes */
+    return OperationNotAllowedOnTheUniversalIODevice;
+}
+
+
+/******************************************************************************
+  CAAM Blob Operations
+  ****************************************************************************/
+
+/* limit on size due to size of job ring being 64 word32's */
+static Error caamBlob(struct DescStruct* desc)
+{
+    Error err;
+    UINT4 keyType = 0x00000C08; /* default red */
+    UINT4 i = 0;
+    int sz = 0, ret;
+
+    if (desc->idx + 3 > MAX_DESC_SZ) {
+        return Failure;
+    }
+
+    /*default to Red Key type, with offset of 12 and 8 byte load to context 2*/
+    desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS2 | CAAM_IMM | keyType);
+
+    /* add key modifier */
+    if (i < desc->DescriptorCount) {
+        UINT4* pt;
+        Address data   = desc->buf[i].data;
+        Address dataSz = desc->buf[i].dataSz;
+
+        pt = (UINT4*)data;
+        if (dataSz < 8) { /* expecting 8 bytes for key modifier*/
+            return TooManyBuffers;
+        }
+        desc->desc[desc->idx++] = pt[0];
+        desc->desc[desc->idx++] = pt[1];
+    }
+
+    /* add input */
+    while (sz < desc->inputSz && i < desc->DescriptorCount) {
+        ret = caamAddIO(desc, CAAM_SEQI, desc->inputSz - sz, 1, &i);
+        if (ret < 0) { /* handle error case */
+            return TooManyBuffers;
+        }
+        sz += ret;
+    }
+    desc->outputIdx = i;
+
+    /* add output */
+    if (caamAddIO(desc, CAAM_SEQO, 0, 1, &i) < 0) {
+        return TooManyBuffers;
+    }
+
+    if (desc->idx + 1 > MAX_DESC_SZ) {
+        return Failure;
+    }
+    desc->desc[desc->idx++] = CAAM_OP |  CAAM_OPID_BLOB | desc->type;
+
+    if ((err = caamDoJob(desc)) != Success) {
+        return err;
+    }
+
+    /* flush output buffers */
+    for (i = desc->outputIdx; i < desc->DescriptorCount; i++) {
+        ASP_FlushCaches(desc->buf[i].data, desc->buf[i].dataSz);
+    }
+
+    return Success;
+}
+
+
+/******************************************************************************
+  CAAM AES Operations
+  ****************************************************************************/
+
+/* returns amount written on success and negative value in error case.
+ * Is different from caamAddIO in that it only adds a single input buffer
+ * rather than multiple ones.
+ */
+static int caamAesInput(struct DescStruct* desc, UINT4* idx, int align,
+    UINT4 totalSz)
+{
+    int sz;
+    UINT4 i = *idx;
+
+    /* handle alignment constraints on input */
+    if (desc->alignIdx > 0) {
+        sz = desc->alignIdx;
+
+        /* if there is more input buffers then add part of it */
+        if (i < desc->outputIdx && i < desc->DescriptorCount) {
+            sz = align - desc->alignIdx;
+            sz = (sz <= desc->buf[i].dataSz) ? sz : desc->buf[i].dataSz;
+            memcpy((unsigned char*)(desc->alignBuf) + desc->alignIdx,
+                   (unsigned char*)(desc->buf[i].data), sz);
+
+            desc->buf[i].dataSz -= sz;
+            desc->buf[i].data   += sz;
+            sz += desc->alignIdx;
+        }
+
+        if (desc->idx + 2 > MAX_DESC_SZ) {
+            return -1;
+        }
+        ASP_FlushCaches((Address)desc->alignBuf, sz);
+        desc->desc[desc->idx++] = (CAAM_FIFO_L | FIFOL_TYPE_LC1 |
+                                   CAAM_CLASS1 | FIFOL_TYPE_MSG) + sz;
+        desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->alignBuf);
+        desc->alignIdx = 0;
+    }
+    else {
+        sz = desc->buf[i].dataSz;
+        if ((totalSz + sz) == desc->inputSz) { /* not an issue on final */
+            align = 1;
+        }
+
+        desc->alignIdx = sz % align;
+        if (desc->alignIdx != 0) {
+            sz -= desc->alignIdx;
+            memcpy((unsigned char*)desc->alignBuf,
+                   (unsigned char*)(desc->buf[i].data) + sz,
+                   desc->alignIdx);
+        }
+
+        if (desc->idx + 2 > MAX_DESC_SZ) {
+            return -1;
+        }
+        desc->desc[desc->idx++] = (CAAM_FIFO_L | FIFOL_TYPE_LC1 |
+                                   CAAM_CLASS1 | FIFOL_TYPE_MSG) + sz;
+        desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->buf[i].data);
+        i++;
+    }
+
+    *idx = i;
+    return sz;
+}
+
+
+/* returns enum Success on success, all other return values should be
+ * considered an error.
+ *
+ * ofst    is the amount of leftover buffer from previous calls
+ * inputSz is the amount of input in bytes that is being matched to output
+ */
+static Error caamAesOutput(struct DescStruct* desc, int* ofst, UINT4 inputSz)
+{
+    int offset = *ofst;
+
+    if (desc->output != 0 && offset > 0 && inputSz > 0) {
+        UINT4 addSz;
+
+        /* handle potential leftovers */
+        addSz = (inputSz >= offset) ? offset : inputSz;
+
+        inputSz -= addSz;
+        desc->desc[desc->idx++] = CAAM_FIFO_S | FIFOS_TYPE_MSG + addSz;
+        if (inputSz > 0) { /* check if expecting more output */
+            desc->desc[desc->idx - 1] |= CAAM_FIFOS_CONT;
+        }
+        desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->output);
+
+        if (addSz == offset) {
+            /* reset */
+            desc->output = 0;
+            offset       = 0;
+        }
+        else {
+            offset -= addSz;
+            desc->output += addSz;
+
+            if (offset < 0) {
+                return TransferFailed;
+            }
+        }
+    }
+
+    for (; desc->lastIdx < desc->DescriptorCount; desc->lastIdx++) {
+        struct buffer* buf = &desc->buf[desc->lastIdx];
+
+        if (inputSz > 0) {
+            int tmp;
+
+            if (buf->dataSz <= inputSz) {
+                tmp = buf->dataSz;
+            }
+            else {
+                offset = buf->dataSz - inputSz;
+                tmp    = inputSz;
+                desc->output = buf->data + tmp;
+            }
+            inputSz -= tmp;
+            if (desc->idx + 2 > MAX_DESC_SZ) {
+                return TransferFailed;
+            }
+            desc->desc[desc->idx++] = CAAM_FIFO_S | FIFOS_TYPE_MSG + tmp;
+            if (inputSz > 0) { /* check if expecting more output */
+                desc->desc[desc->idx - 1] |= CAAM_FIFOS_CONT;
+            }
+            desc->desc[desc->idx++] = BSP_VirtualToPhysical(buf->data);
+        }
+        else {
+            break;
+        }
+    }
+
+    *ofst = offset;
+    return Success;
+}
+
+
+/* check size of output and get starting buffer for it */
+static Error caamAesOutSz(struct DescStruct* desc, UINT4 i)
+{
+    int sz = 0;
+
+    for (desc->outputIdx = i; desc->outputIdx < desc->DescriptorCount &&
+    sz < desc->inputSz; desc->outputIdx++) {
+        sz += desc->buf[desc->outputIdx].dataSz;
+    }
+    desc->lastIdx = desc->outputIdx;
+
+    /* make certain that output size is same as input */
+    sz = 0;
+    for (; desc->lastIdx < desc->DescriptorCount; desc->lastIdx++) {
+        sz += desc->buf[desc->lastIdx].dataSz;
+    }
+    if (sz != desc->inputSz) {
+        return SizeIsTooLarge;
+    }
+    desc->lastIdx = desc->outputIdx;
+
+    return Success;
+}
+
+
+/* AES operations follow the buffer sequence of KEY -> (IV) -> Input -> Output
+ */
+static Error caamAes(struct DescStruct* desc)
+{
+    struct buffer* ctx[3];
+    struct buffer* iv[3];
+    Value ofst = 0;
+    Error err;
+    UINT4 i, totalSz = 0;
+    int ctxIdx = 0;
+    int ivIdx  = 0;
+    int offset = 0;
+    int align  = 1;
+    int sz     = 0;
+
+    int ctxSz = desc->ctxSz;
+
+    if (desc->state != CAAM_ENC && desc->state != CAAM_DEC) {
+        return IllegalStatusNumber;
+    }
+
+    if (ctxSz != 16 && ctxSz != 24 && ctxSz != 32) {
+        return ArgumentError;
+    }
+
+    /* get key */
+    for (i = 0; i < desc->DescriptorCount; i++) {
+        struct buffer* buf = &desc->buf[i];
+        unsigned char* local = (unsigned char*)desc->ctxBuf;
+
+        if (sz < ctxSz && sz < (MAX_CTX * sizeof(UINT4))) {
+            ctx[ctxIdx] = buf;
+            sz += buf->dataSz;
+
+            memcpy((unsigned char*)&local[offset],
+                   (unsigned char*)ctx[ctxIdx]->data, ctx[ctxIdx]->dataSz);
+            offset += ctx[ctxIdx]->dataSz;
+            ctxIdx++;
+        }
+        else {
+            break;
+        }
+    }
+
+    /* sanity checks on size of key */
+    if (sz > ctxSz) {
+        return SizeIsTooLarge;
+    }
+    if (ctxSz > (MAX_CTX * sizeof(UINT4)) - 16) {
+        return ArgumentError;
+    }
+
+    /* Flush cache of ctx buffer then :
+       Add KEY Load command          0x0220000X
+       Add address to read key from  0xXXXXXXXX */
+    ASP_FlushCaches((Address)desc->ctxBuf, ctxSz);
+    if (desc->idx + 2 > MAX_DESC_SZ) {
+        return TransferFailed;
+    }
+    desc->desc[desc->idx++] = (CAAM_KEY | CAAM_CLASS1 | CAAM_NWB) + ctxSz;
+    desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->ctxBuf);
+
+    /* 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 */
+
+            sz = 0;
+            offset = 0;
+            for (; i < desc->DescriptorCount; i++) {
+                struct buffer* buf = &desc->buf[i];
+                unsigned char* local = (unsigned char*)desc->iv;
+
+                if (sz < maxSz) {
+                    iv[ivIdx] = buf;
+
+                    if (buf->dataSz + sz > maxSz) {
+                        return SizeIsTooLarge;
+                    }
+
+                    sz += buf->dataSz;
+                    memcpy((unsigned char*)&local[offset],
+                        (unsigned char*)iv[ivIdx]->data, iv[ivIdx]->dataSz);
+                    offset += iv[ivIdx]->dataSz;
+                    ivIdx++;
+                }
+                else {
+                    break;
+                }
+            }
+
+            if (sz != maxSz) {
+                /* invalid IV size */
+                return SizeIsTooLarge;
+            }
+
+            ASP_FlushCaches((Address)desc->iv, maxSz);
+            if (desc->idx + 2 > MAX_DESC_SZ) {
+                return TransferFailed;
+            }
+            desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS1 | ofst) + maxSz;
+            desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->iv);
+         }
+         break;
+
+        default:
+            return OperationNotImplemented;
+    }
+
+    /* write operation */
+    if (desc->idx + 1 > MAX_DESC_SZ) {
+        return TransferFailed;
+    }
+    desc->desc[desc->idx++] = CAAM_OP | CAAM_CLASS1 | desc->type |
+             CAAM_ALG_UPDATE | desc->state;
+
+    /* find output buffers */
+    if (caamAesOutSz(desc, i) != Success) {
+        return SizeIsTooLarge;
+    }
+
+    /* set alignment constraints */
+    if (desc->type == CAAM_AESCBC || desc->type == CAAM_AESECB) {
+        align = 16;
+    }
+
+    /* indefinite loop for input/output buffers */
+    desc->headIdx = desc->idx;
+    desc->output  = 0;
+    offset = 0; /* store left over amount for output buffer */
+    do {
+        desc->idx = desc->headIdx; /* reset for each loop */
+
+        /* add a single input buffer (multiple ones was giving deco watch dog
+         * time out errors on the FIFO load of 1c.
+         * @TODO this could be a place for optimization if more data could be
+         * loaded in at one time */
+        if ((sz = caamAesInput(desc, &i, align, totalSz)) < 0) {
+            return TransferFailed;
+        }
+        totalSz += sz;
+
+        if (caamAesOutput(desc, &offset, sz) != Success) {
+            return TransferFailed;
+        }
+
+        /* store updated IV */
+        if (ivIdx > 0) {
+            if (desc->idx + 2 > MAX_DESC_SZ) {
+                return TransferFailed;
+            }
+            desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS1 | ofst | 16;
+            desc->desc[desc->idx++] = BSP_VirtualToPhysical((Address)desc->iv);
+        }
+
+        if ((err = caamDoJob(desc)) != Success) {
+            return err;
+        }
+        ASP_FlushCaches((Address)desc->iv, 16);
+    } while (desc->lastIdx < desc->DescriptorCount || offset > 0);
+
+    /* flush output buffers */
+    for (i = desc->outputIdx; i < desc->lastIdx; i++) {
+        ASP_FlushCaches(desc->buf[i].data, desc->buf[i].dataSz);
+    }
+
+    /* handle case with IV */
+    if (ivIdx > 0) {
+        unsigned char* pt = (unsigned char*)desc->iv;
+        ASP_FlushCaches((Address)pt, 16);
+        for (i = 0; i < ivIdx; i++) {
+            memcpy((unsigned char*)iv[i]->data, pt, iv[i]->dataSz);
+            pt += iv[i]->dataSz;
+            ASP_FlushCaches(iv[i]->data, iv[i]->dataSz);
+        }
+    }
+
+    return Success;
+}
+
+
+/******************************************************************************
+  CAAM AEAD Operations
+  ****************************************************************************/
+
+/* AEAD operations follow the buffer sequence of KEY -> (IV or B0 | CTR0) -> (AD)
+ * -> Input -> Output
+ *
+ */
+static Error caamAead(struct DescStruct* desc)
+{
+    struct buffer* ctx[3];
+    struct buffer* iv[3];
+    Value ofst    = 0;
+    UINT4 state   = CAAM_ALG_INIT;
+    UINT4 totalSz = 0;
+    Error err;
+    UINT4 i;
+    int ctxIdx = 0;
+    int ivIdx  = 0;
+    int offset = 0;
+    int sz     = 0;
+    int ivSz   = 32; /* size of B0 | CTR0 for CCM mode */
+    int ctxSz  = desc->ctxSz;
+    int align  = 16; /* input should be multiples of 16 bytes unless is final */
+    int opIdx;
+
+    if (desc->state != CAAM_ENC && desc->state != CAAM_DEC) {
+        return IllegalStatusNumber;
+    }
+
+    /* sanity check is valid AES key size */
+    if (ctxSz != 16 && ctxSz != 24 && ctxSz != 32) {
+        return ArgumentError;
+    }
+
+    /* get key */
+    for (i = 0; i < desc->DescriptorCount; i++) {
+        struct buffer* buf = &desc->buf[i];
+        unsigned char* local = (unsigned char*)desc->ctxBuf;
+
+        if (sz < ctxSz && sz < (MAX_CTX * sizeof(UINT4))) {
+            ctx[ctxIdx] = buf;
+            sz += buf->dataSz;
+
+            memcpy((unsigned char*)&local[offset],
+                   (unsigned char*)ctx[ctxIdx]->data, ctx[ctxIdx]->dataSz);
+            offset += ctx[ctxIdx]->dataSz;
+            ctxIdx++;
+        }
+        else {
+            break;
+        }
+    }
+
+    /* sanity checks on size of key */
+    if (sz > ctxSz) {
+        return SizeIsTooLarge;
+    }
+
+    /* Flush cache of ctx buffer then :
+       Add KEY Load command          0x0220000X
+       Add address to read key from  0xXXXXXXXX */
+    ASP_FlushCaches((Address)desc->ctxBuf, ctxSz);
+    if (desc->idx + 2 > MAX_DESC_SZ) {
+        return TransferFailed;
+    }
+    desc->desc[desc->idx++] = (CAAM_KEY | CAAM_CLASS1 | CAAM_NWB) + ctxSz;
+    desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->ctxBuf);
+
+    desc->headIdx = desc->idx;
+    desc->output  = 0;
+    offset = 0; /* store left over amount for output buffer */
+    do {
+        desc->idx = desc->headIdx; /* reset for each loop */
+
+        /* write operation */
+        if (desc->idx + 1 > MAX_DESC_SZ) {
+            return TransferFailed;
+        }
+        opIdx = desc->idx;
+        desc->desc[desc->idx++] = CAAM_OP | CAAM_CLASS1 | state | desc->type |
+                                  desc->state;
+
+        /* get IV if needed by algorithm */
+        switch (desc->type) {
+            case CAAM_AESCCM:
+                if ((state & CAAM_ALG_INIT) == CAAM_ALG_INIT) {
+                    sz = 0;
+                    offset = 0;
+                    for (; i < desc->DescriptorCount; i++) {
+                        struct buffer* buf = &desc->buf[i];
+                        unsigned char* local = (unsigned char*)desc->iv;
+
+                        if (sz < ivSz) {
+                            iv[ivIdx] = buf;
+
+                            if (buf->dataSz + sz > ivSz) {
+                                return SizeIsTooLarge;
+                            }
+
+                            sz += buf->dataSz;
+                            memcpy((unsigned char*)&local[offset],
+                            (unsigned char*)iv[ivIdx]->data, iv[ivIdx]->dataSz);
+                            offset += iv[ivIdx]->dataSz;
+                            ivIdx++;
+                        }
+                        else {
+                            break;
+                        }
+                    }
+
+                    if (sz != ivSz) {
+                        /* invalid IV size */
+                        return SizeIsTooLarge;
+                    }
+                    offset = 0;
+                }
+
+                ASP_FlushCaches((Address)desc->iv, ivSz);
+                if (desc->idx + 2 > MAX_DESC_SZ) {
+                    return TransferFailed;
+                }
+                desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS1 | ofst)
+                                           + ivSz;
+                desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->iv);
+                break;
+
+            default:
+                return OperationNotImplemented;
+        }
+
+
+        /********* handle AAD -- is only done with Init **********************/
+        if ((state & CAAM_ALG_INIT) == CAAM_ALG_INIT) {
+            if ((desc->type == CAAM_AESCCM) && (desc->aadSz > 0)) {
+                /* set formated AAD buffer size for CCM */
+                ASP_FlushCaches((Address)desc->aadSzBuf, sizeof(desc->aadSzBuf));
+                desc->desc[desc->idx++] = CAAM_FIFO_L | CAAM_CLASS1 |
+                    FIFOL_TYPE_AAD + desc->aadSz;
+                desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->aadSzBuf);
+
+                /* now set aadSz to unformatted version for getting buffers */
+                if (desc->aadSz == 2) {
+                    unsigned char* pt = (unsigned char*)desc->aadSzBuf;
+                    desc->aadSz = (((UINT4)pt[0] & 0xFF) << 8) |
+                           ((UINT4)pt[1] & 0xFF);
+                }
+                else {
+                    unsigned char* pt = (unsigned char*)desc->aadSzBuf;
+                    desc->aadSz = (((UINT4)pt[2] & 0xFF) << 24) |
+                                  (((UINT4)pt[3] & 0xFF) << 16) |
+                                  (((UINT4)pt[4] & 0xFF) <<  8) |
+                                   ((UINT4)pt[5] & 0xFF);
+                }
+            }
+
+            /* get additional data buffers */
+            if (desc->aadSz > 0) {
+                sz = 0;
+                for (; i < desc->DescriptorCount; i++) {
+                    struct buffer* buf = &desc->buf[i];
+                    if (sz < desc->aadSz) {
+                        if (desc->idx + 2 > MAX_DESC_SZ) {
+                            return TransferFailed;
+                        }
+                        desc->lastFifo = desc->idx;
+                        desc->desc[desc->idx++] = CAAM_FIFO_L | CAAM_CLASS1 |
+                                                  FIFOL_TYPE_AAD + buf->dataSz;
+                        desc->desc[desc->idx++] = BSP_VirtualToPhysical(buf->data);
+                        sz += buf->dataSz;
+                    }
+                    else {
+                        break;
+                    }
+                }
+
+                /* flush AAD from FIFO and pad it to 16 byte block */
+                desc->desc[desc->lastFifo] |= FIFOL_TYPE_FC1;
+            }
+
+            /* find output buffers */
+            if (caamAesOutSz(desc, i) != Success) {
+                return SizeIsTooLarge;
+            }
+        }
+
+        /* handle alignment constraints on input */
+        if ((sz = caamAesInput(desc, &i, align, totalSz)) < 0) {
+            return TransferFailed;
+        }
+        totalSz += sz;
+
+        /* handle output buffers  */
+        if (caamAesOutput(desc, &offset, sz) != Success) {
+            return TransferFailed;
+        }
+
+        /* store updated IV, if is last then set offset and final for MAC */
+        if ((desc->lastIdx == desc->DescriptorCount) && (offset == 0)) {
+            ivSz = 16;
+            if (desc->state == CAAM_ENC) {
+                ofst = 32 << 8; /* offset is in 15-8 bits */
+            }
+            else {
+                ofst = 0;
+            }
+            desc->desc[opIdx] |= CAAM_ALG_FINAL;
+        }
+        else {
+            /* if not final then store and use ctr and encrypted ctr from
+                context dword 2,3 and 4,5. Also store MAC and AAD info from
+                context dword 6. */
+            ivSz = 56;
+            ofst = 0;
+        }
+
+        if (desc->idx + 2 > MAX_DESC_SZ) {
+            return TransferFailed;
+        }
+        desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS1 | ofst | ivSz;
+        desc->desc[desc->idx++] = BSP_VirtualToPhysical((Address)desc->iv);
+
+        if ((err = caamDoJob(desc)) != Success) {
+            return err;
+        }
+        state = CAAM_ALG_UPDATE;
+    } while (desc->lastIdx < desc->DescriptorCount || offset > 0);
+
+    /* flush output buffers */
+    for (i = desc->outputIdx; i < desc->lastIdx; i++) {
+        ASP_FlushCaches(desc->buf[i].data, desc->buf[i].dataSz);
+    }
+
+    /* handle case with IV (This is also the output of MAC with AES-CCM) */
+    if (ivIdx > 0) {
+        unsigned char* pt = (unsigned char*)desc->iv;
+        ASP_FlushCaches((Address)pt, ivSz);
+        for (i = 0; i < ivIdx; i++) {
+            memcpy((unsigned char*)iv[i]->data, pt, iv[i]->dataSz);
+            pt += iv[i]->dataSz;
+            ASP_FlushCaches(iv[i]->data, iv[i]->dataSz);
+        }
+    }
+
+    return Success;
+}
+
+
+/******************************************************************************
+  CAAM SHA Operations
+  ****************************************************************************/
+static int shaSize(struct DescStruct* desc)
+{
+    /* sanity check on dataSz for context */
+    switch (desc->type) {
+        case CAAM_MD5:
+            return CAAM_MD5_CTXSZ;
+
+        case CAAM_SHA:
+            return CAAM_SHA_CTXSZ;
+
+        case CAAM_SHA224:
+            return CAAM_SHA224_CTXSZ;
+
+        case CAAM_SHA256:
+            return CAAM_SHA256_CTXSZ;
+
+        case CAAM_SHA384:
+            return CAAM_SHA384_CTXSZ;
+
+        case CAAM_SHA512:
+            return CAAM_SHA512_CTXSZ;
+
+        default:
+            return 0;
+    }
+}
+
+/* SHA operations
+ * start: the index to start traversing through buffers. It's needed to allow
+ *       for HMAC to reuse this code.
+ *
+ * return Success on success. All other return values are considered a fail
+ *         case.
+ */
+static Error caamSha(struct DescStruct* desc, int start)
+{
+    struct buffer* ctx[3];
+    Error err;
+    UINT4 i;
+    int sz     = 0;
+    int ctxIdx = 0;
+    int offset = 0;
+
+    int ctxSz = shaSize(desc);
+
+    /* get context */
+    for (i = start; i < desc->DescriptorCount; i++) {
+        struct buffer* buf = &desc->buf[i];
+        unsigned char* local = (unsigned char*)desc->iv;
+
+        if (sz < ctxSz && sz < (MAX_CTX * sizeof(UINT4))) {
+            ctx[ctxIdx] = buf;
+            sz += buf->dataSz;
+
+            if (ctx[ctxIdx]->dataSz + offset > (MAX_CTX * sizeof(UINT4))) {
+                return SizeIsTooLarge;
+            }
+            memcpy((unsigned char*)&local[offset], (unsigned char*)ctx[ctxIdx]->data,
+            ctx[ctxIdx]->dataSz);
+            offset += ctx[ctxIdx]->dataSz;
+            ctxIdx++;
+        }
+        else {
+            break;
+        }
+    }
+    if (sz > ctxSz || ctxSz > (MAX_CTX * sizeof(UINT4))) {
+        return SizeIsTooLarge;
+    }
+
+    ASP_FlushCaches((Address)desc->iv, ctxSz);
+    /*Manage Context (current digest + 8 byte running message length)*/
+    if ((desc->state & CAAM_ALG_INIT) != CAAM_ALG_INIT) {
+        /* don't load into the class 2 context register on inti.
+           Found that loading in caused context to not get set. */
+        if (desc->idx + 2 > MAX_DESC_SZ) {
+            return TransferFailed;
+        }
+        desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS2) + ctxSz;
+        desc->desc[desc->idx++] = BSP_VirtualToPhysical((Address)desc->iv);
+    }
+
+    /* add operation command */
+    desc->desc[desc->idx++] = CAAM_OP | CAAM_CLASS2 | desc->state |
+        desc->type;
+
+    /* Check case where there is no input.
+       In all cases the FIFO Load should be flushed. */
+    if (i == desc->DescriptorCount) {
+        desc->lastFifo = desc->idx;
+        if (desc->idx + 1 > MAX_DESC_SZ) {
+            return TransferFailed;
+        }
+        desc->desc[desc->idx++] = CAAM_FIFO_L | CAAM_CLASS2 |
+        FIFOL_TYPE_MSG | CAAM_IMM;
+    }
+
+    /* save index for looping over input */
+    desc->headIdx = desc->idx;
+    do {
+        desc->idx = desc->headIdx; /* reset for each loop */
+        if (i < desc->DescriptorCount) {
+            /* input must be a multiple of 64 bytes unless in final call */
+            if (((desc->state & CAAM_ALG_FINAL) == CAAM_ALG_FINAL)) {
+                if (caamAddIO(desc, (CAAM_FIFO_L | CAAM_CLASS2 |
+                    FIFOL_TYPE_MSG), 0, 1, &i) < 0) {
+                    return TooManyBuffers;
+                }
+            }
+            else {
+                if (caamAddIO(desc, (CAAM_FIFO_L | CAAM_CLASS2 |
+                    FIFOL_TYPE_MSG), 0, 64, &i) < 0) {
+                    return TooManyBuffers;
+                }
+            }
+        }
+
+        desc->desc[desc->lastFifo] |= FIFOL_TYPE_LC2;
+
+        /* set context out */
+        if (desc->idx + 2 > MAX_DESC_SZ) {
+            return TransferFailed;
+        }
+        desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS2 + ctxSz;
+        desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->iv);
+
+        if ((err = caamDoJob(desc)) != Success) {
+            return err;
+        }
+        /* flush context output for each loop */
+        ASP_FlushCaches((Address)desc->iv, ctxSz);
+    } while (i < desc->DescriptorCount);
+
+    /* store context to buffers */
+    {
+        unsigned char* pt = (unsigned char*)desc->iv;
+        for (i = 0; i < ctxIdx; i++) {
+            memcpy((unsigned char*)ctx[i]->data, pt, ctx[i]->dataSz);
+            pt += ctx[i]->dataSz;
+            ASP_FlushCaches(ctx[i]->data, ctx[i]->dataSz);
+        }
+    }
+
+    return Success;
+}
+
+
+/******************************************************************************
+  CAAM TRNG Operations
+  ****************************************************************************/
+
+/* If Entropy is not ready then return Waiting */
+static Error caamRng(struct DescStruct* desc)
+{
+    int sz = 0;
+    int i;
+
+    Address  reg; /* RTENT reg to read */
+    int ofst = sizeof(UINT4);
+
+
+    /* Check ENT_VAL bit to make sure entropy is ready */
+    if ((CAAM_READ(CAAM_RTMCTL) & CAAM_ENTVAL) !=
+            CAAM_ENTVAL) {
+        return Waiting;
+    }
+
+    /* check state of TRNG */
+    if ((CAAM_READ(CAAM_RTSTATUS) & 0x0000FFFF) > 0) {
+        return Failure;
+    }
+
+    /* read entropy from RTENT registers */
+    reg = CAAM_RTENT0;
+
+    for (i = 0; i < desc->DescriptorCount; i++) {
+        struct buffer* buf = &desc->buf[i];
+        unsigned char* local = (unsigned char*)buf->data;
+        sz = buf->dataSz;
+
+        while (sz > 3 && reg <= CAAM_RTENT11) {
+            *((UINT4*)local) = CAAM_READ(reg);
+            reg    += ofst;
+            local  += ofst;
+            sz     -= ofst;
+        }
+
+        if (reg > CAAM_RTENT11 && sz > 0) {
+            return SizeIsTooLarge;
+        }
+
+        /* handle non word32 size amount left over */
+        if (sz > 0) {
+            UINT4 tmp = CAAM_READ(reg);
+            memcpy(local, (unsigned char*)&tmp, sz);
+        }
+
+        ASP_FlushCaches(buf->data, buf->dataSz);
+    }
+
+
+    /* read RTENT11 to trigger new entropy generation */
+    if (reg != CAAM_RTENT11) {
+        CAAM_READ(CAAM_RTENT11);
+    }
+
+    return Success;
+}
+
+
+/******************************************************************************
+  IODevice Start, Transfer and Finish Buffer
+  ****************************************************************************/
+/* args[0] holds the state such as encrypt/decrypt or init/update/final
+ * args[1] holds the ctx/key size
+ * args[2] holds the input size
+ * args[3] dependent on algo (such as AAD size with AES-CCM) */
+static Error caamTransferStart(IODeviceVector ioCaam,
+    Value type, const volatile Value args[4])
+{
+    struct CAAM_DEVICE* local = (struct CAAM_DEVICE*)ioCaam;
+    struct DescStruct*  desc;
+
+    /* currently only one desc is available for use */
+    desc = &local->DescArray[0];
+
+    /* check if the desc is idle before using */
+    if (GetIORequestStatus((IORequest)desc) != IdleIORequest) {
+         return ResourceNotAvailable;
+    }
+
+    desc->idx    = 0;
+    desc->output = 0;
+    desc->ctxOut = 0;
+    desc->outputIdx = 0;
+    desc->alignIdx = 0;
+    desc->lastFifo = 0;
+    desc->state    = args[0];
+    desc->ctxSz    = args[1];
+    desc->inputSz  = args[2];
+    desc->aadSz    = 0;
+    desc->desc[desc->idx++] = CAAM_HEAD; /* later will put size to header*/
+
+    switch (type) {
+        case CAAM_AESECB:
+        case CAAM_AESCBC:
+            if (desc->inputSz % 16 != 0) {
+                return ArgumentError;
+            }
+            /* fall through to break */
+        case CAAM_AESCTR:
+            break;
+
+        case CAAM_AESCCM:
+            memset((unsigned char*)desc->aadSzBuf, 0, sizeof(desc->aadSzBuf));
+            if (args[3] > 0) {
+                /* encode the length in */
+                if (args[3] <= 0xFEFF) {
+                    unsigned char* pt = (unsigned char*)desc->aadSzBuf;
+                    desc->aadSz = 2;
+                    pt[0] = ((args[3] & 0xFF00) >> 8);
+                    pt[1] =  (args[3] & 0x00FF);
+                }
+                else if (args[3] <= 0xFFFFFFFF) {
+                    unsigned char* pt = (unsigned char*)desc->aadSzBuf;
+                    desc->aadSz = 6;
+                    pt[0] = 0xFF; pt[1] = 0xFE;
+                    pt[2] = ((args[3] & 0xFF000000) >> 24);
+                    pt[3] = ((args[3] & 0x00FF0000) >> 16);
+                    pt[4] = ((args[3] & 0x0000FF00) >>  8);
+                    pt[5] =  (args[3] & 0x000000FF);
+                }
+            }
+            break;
+
+        case CAAM_MD5:
+        case CAAM_SHA:
+        case CAAM_SHA224:
+        case CAAM_SHA256:
+        case CAAM_SHA384:
+        case CAAM_SHA512:
+            break;
+
+        case CAAM_BLOB_ENCAP:
+        case CAAM_BLOB_DECAP:
+            break;
+
+        case CAAM_ENTROPY:
+            break;
+
+        default:
+            /* unknown type */
+            return UsageNotSupported;
+    }
+
+    desc->DescriptorCount = 0;
+    desc->type    = type;
+    desc->running = true;
+    StartIORequest((IORequest)desc);
+
+    /* For now only require READ permissions */
+    SetIORequestBufferPermissions((IORequest)desc, MEMORY_READ);
+    return Success;
+}
+
+
+static Error caamTransferBuffer(IODeviceVector TheIODeviceVector,
+    IORequest req, IODescriptor NewIODescriptor,
+    Address data, Address dataSz)
+{
+    struct DescStruct* desc = (struct DescStruct*)req;
+    Error  err;
+
+    switch (desc->type) {
+        case CAAM_AESECB:
+        case CAAM_AESCTR:
+        case CAAM_AESCBC:
+        case CAAM_AESCCM:
+
+        case CAAM_MD5:
+        case CAAM_SHA:
+        case CAAM_SHA224:
+        case CAAM_SHA256:
+        case CAAM_SHA384:
+        case CAAM_SHA512:
+
+        case CAAM_BLOB_ENCAP:
+        case CAAM_BLOB_DECAP:
+        case CAAM_ENTROPY:
+            { /* set buffer for transfer finish */
+                struct buffer* buf;
+                if (desc->DescriptorCount >= MAX_BUF) {
+                    return TooManyBuffers;
+                }
+                buf = &desc->buf[desc->DescriptorCount];
+                buf->data = data;
+                buf->dataSz = dataSz;
+            }
+                err = Success;
+            break;
+
+        default:
+            err = UsageNotSupported;
+    }
+
+    if (err != Success) {
+        desc->running = false;
+        DismissIORequest(req);
+        return err;
+    }
+
+    desc->DescriptorCount++;
+    return Success;
+}
+
+
+static Error caamTransferFinish(IODeviceVector ioCaam, IORequest req)
+{
+    struct DescStruct* desc = (struct DescStruct*)req;
+    Error ret;
+
+    /* construct desc */
+    switch (desc->type) {
+        case CAAM_AESECB:
+        case CAAM_AESCTR:
+        case CAAM_AESCBC:
+            ret = caamAes(desc);
+            break;
+
+        case CAAM_AESCCM:
+            ret = caamAead(desc);
+            break;
+
+        case CAAM_MD5:
+        case CAAM_SHA:
+        case CAAM_SHA224:
+        case CAAM_SHA256:
+        case CAAM_SHA384:
+        case CAAM_SHA512:
+            ret = caamSha(desc, 0);
+            break;
+
+        case CAAM_ENTROPY:
+            ret = caamRng(desc);
+            break;
+
+        case CAAM_BLOB_ENCAP:
+        case CAAM_BLOB_DECAP:
+            ret = caamBlob(desc);
+            break;
+
+        default:
+            ret = UsageNotSupported;
+    }
+
+    desc->running = false;
+    DismissIORequest(req);
+    return ret;
+}
+
+
+/******************************************************************************
+  IODevice Interupt and Init
+  ****************************************************************************/
+
+static Error caamTransferWrite(IODeviceVector ioCaam,
+    IORequest req, Value dataSz, const volatile Value *data)
+{
+    DismissIORequest(req);
+    return UsageNotSupported;
+}
+
+
+static void caamTransferAbort(IODeviceVector ioCaam, IORequest req)
+{
+    DismissIORequest(req);
+}
+
+
+static void caamTransferRecall(IODeviceVector ioCaam, IODescriptor req)
+{
+
+}
+
+
+static void HandleInterrupt(Address id)
+{
+    struct CAAM_DEVICE* local = (struct CAAM_DEVICE*)id;
+    Value InterruptStatus = INTERRUPT_AtomicWrite(&local->InterruptStatus, 0);
+    int i;
+
+    /* Loop through descriptors and try to dismiss them */
+    for (i = 0; i < DESC_COUNT; i++) {
+        struct DescStruct* desc = &local->DescArray[i];
+        if (InterruptStatus & (1 << i)) {
+            desc->running = false;
+            if (GetIORequestStatus((IORequest)desc) == IORequestSuspended) {
+                ContinueIORequest((IORequest)desc);
+            }
+            else {
+                DismissIORequest((IORequest)desc);
+            }
+        }
+    }
+}
+
+
+static Error caamCreate(IODeviceVector ioCaam)
+{
+    return Success;
+}
+
+
+void  InitCAAM(void)
+{
+    /* get IO vector and set it up */
+    IODeviceVector ioCaam = &caam.caamVector;
+    unsigned int reg;
+    int   i;
+    Error ret;
+
+
+    ioCaam->Create         = &caamCreate;
+    ioCaam->ReadRegister   = &caamReadRegister;
+    ioCaam->WriteRegister  = &caamWriteRegister;
+
+    ioCaam->TransferStart  = &caamTransferStart;
+    ioCaam->TransferBuffer = &caamTransferBuffer;
+    ioCaam->TransferWrite  = &caamTransferWrite;
+    ioCaam->TransferFinish = &caamTransferFinish;
+    ioCaam->TransferAbort  = &caamTransferAbort;
+    ioCaam->TransferRecall = &caamTransferRecall;
+#ifdef HARDWARE_CACHE_COHERENCY
+    ioCaam->IOSynchronizationNotRequired = 1;
+#endif
+
+    RegisterIODeviceVector(ioCaam, DRIVER_NAME);
+    RequestIOTerminationTask(ioCaam, 10);
+
+    /* Initialize descriptors */
+    for (i = 0; i < BUFFER_COUNT; i++) {
+        InitializeIODescriptor(ioCaam, &caam.IODescriptorArray[i]);
+    }
+
+    /* Initialize Descriptors */
+    for (i = 0; i < DESC_COUNT; i++) {
+         InitializeIORequest(ioCaam, &caam.DescArray[i].TheIORequest,
+                             IOREQUEST_STANDARD);
+         caam.DescArray[i].running = false;
+         caam.DescArray[i].caam    = &caam;
+    }
+
+
+    /* call interrupt to make IORequests available */
+    caam.InterruptStatus = 0;
+    INTERRUPT_InitCall(&caam.HandleInterruptCall,
+        &HandleInterrupt, "Start up CAAM IORequest");
+
+    /* set clock speed for CAAM. Setting it here to allow for restricting
+       access */
+    #define REGS_CCM_BASE     (0xf20c4000)
+    #define HW_CCM_CCGR0_ADDR (0xf20c4068)
+    #define CG(x) (3 << (x*2))
+
+    reg = CG(6) | CG(5) | CG(4);
+    *(volatile unsigned int*)HW_CCM_CCGR0_ADDR =
+    *(volatile unsigned int*)HW_CCM_CCGR0_ADDR | reg;
+
+    /* set up job ring */
+
+    /* @TODO create partition in physical memory for job rings
+       current partion security is set to the default */
+    for (i = 1; i < CAAM_PAGE_MAX; i++) {
+        ret = caamCreatePartition(i, i);
+        if (ret == 0) {
+            break;
+        }
+
+        if (ret != MemoryMapMayNotBeEmpty) {
+            INTERRUPT_Panic();
+        }
+    }
+
+    if (ret != 0) {
+        INTERRUPT_Panic();
+    }
+
+    caam.ring.page = i;
+    caam.ring.JobIn  =  (CAAM_PAGE + (i << 12));
+    caam.ring.JobOut  = caam.ring.JobIn  + 16;
+    caam.ring.Desc    = caam.ring.JobOut + 16;
+
+    /* set physical address of job rings */
+    CAAM_WRITE(CAAM_IRBAR0, caam.ring.JobIn  ^ 0xF0000000);
+    CAAM_WRITE(CAAM_ORBAR0, caam.ring.JobOut ^ 0xF0000000);
+
+    /* Initialize job ring sizes to 1 */
+    CAAM_WRITE(CAAM_IRSR0, 1);
+    CAAM_WRITE(CAAM_ORSR0, 1);
+
+    /* set DECO watchdog to time out and flush jobs that cause the DECO to hang */
+    CAAM_WRITE((CAAM_BASE | 0x0004), CAAM_READ(CAAM_BASE | 0x0004) | 0x40000000);
+
+    /* start up RNG if not already started */
+    if (caamInitRng(&caam) != 0) {
+        INTERRUPT_Panic();
+    }
+}
+
+void (*__ghsentry_bspuserinit_InitCAAM)(void) = &InitCAAM;

+ 289 - 0
wolfcrypt/src/port/caam/caam_init.c

@@ -0,0 +1,289 @@
+/* caam_init.c
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \
+    defined(WOLFSSL_IMX6_CAAM_BLOB)
+
+#include <wolfssl/wolfcrypt/logging.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
+
+#define WC_CAAM_BLOB_SZ 48
+
+#ifndef WC_CAAM_PASSWORD
+    #define WC_CAAM_PASSWORD "!systempassword"
+#endif
+
+#if defined(__INTEGRITY) || defined(INTEGRITY)
+    #include <INTEGRITY.h>
+    #include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
+    static IODevice caam = NULLIODevice;
+#endif
+
+#if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG)
+#include <stdio.h>
+#include <wolfssl/version.h>
+
+static void wc_caamBanner(void)
+{
+    printf("********* wolfSSL Version %s : Printing Out CAAM Information ********\n",
+        LIBWOLFSSL_VERSION_STRING);
+    printf("CAAM Status [0x%8.8x]   = 0x%8.8x\n",
+        CAAM_STATUS, WC_CAAM_READ(CAAM_STATUS));
+    printf("CAAM Version MS Register [0x%8.8x]  = 0x%8.8x\n",
+        CAAM_VERSION_MS, WC_CAAM_READ(CAAM_VERSION_MS));
+    printf("CAAM Version LS Register [0x%8.8x]  = 0x%8.8x\n",
+        CAAM_VERSION_LS, WC_CAAM_READ(CAAM_VERSION_LS));
+    printf("CAAM Support MS Register [0x%8.8x] = 0x%8.8x\n",
+        CAMM_SUPPORT_MS, WC_CAAM_READ(CAMM_SUPPORT_MS));
+    printf("CAAM Support LS [0x%8.8x] = 0x%8.8x\n",
+        CAMM_SUPPORT_LS, WC_CAAM_READ(CAMM_SUPPORT_LS));
+    printf("********************************************************************\n\n");
+}
+#endif
+
+
+/* Allow runtime setting for CAAM IODevice in case user wants to use password
+ * at run time.
+ *
+ * returns 0 on success
+ *
+ * NOTE this is how IODevice is defined in INTEGRITY "typedef struct
+ *      IODeviceStruct        *IODevice;"
+ */
+int wc_caamSetResource(IODevice ioDev)
+{
+    WOLFSSL_MSG("Setting CAAM driver");
+    caam = ioDev;
+
+    return 0;
+}
+
+/* Check hardware support
+ *
+ * returns 0 on success
+ */
+int wc_caamInit()
+{
+    int    ret;
+    word32 reg;
+
+    /* get the driver up */
+    if (caam == NULLIODevice) {
+        WOLFSSL_MSG("Starting CAAM driver");
+        if ((ret = (int)RequestResource((Object *)&caam, "wolfSSL_CAAM_Driver",
+            WC_CAAM_PASSWORD)) != (int)Success) {
+            WOLFSSL_MSG("Unable to get the CAAM IODevice, check password?");
+            WOLFSSL_LEAVE("wc_caamInit: error from driver = ", ret);
+            ret = 0; /* not a hard failure because user can set resource */
+        }
+    }
+
+#if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG)
+    /* print out CAAM version/info and wolfSSL version */
+    wc_caamBanner();
+#endif
+
+    /* check that for implemented modules
+     * bits 0-3 AES, 4-7 DES, 12-15 Hashing , 16-19 RNG */
+    reg = WC_CAAM_READ(CAMM_SUPPORT_LS);
+
+    #ifndef WC_NO_RNG
+    if (((reg & 0x000F0000) >> 16) > 0) {
+        WOLFSSL_MSG("Found CAAM RNG hardware module");
+        if ((WC_CAAM_READ(CAAM_RTMCTL) & 0x40000001) != 0x40000001) {
+             WOLFSSL_MSG("Error CAAM RNG has not been set up");
+        }
+    }
+    #endif
+
+    #ifndef NO_SHA256
+    if ((reg & 0x0000F000) > 0) {
+        WOLFSSL_MSG("Found CAAM MDHA module");
+    }
+    else {
+        WOLFSSL_MSG("Hashing not supported by CAAM");
+        return WC_HW_E;
+    }
+    #endif
+
+    #ifndef NO_AES
+    if ((reg & 0x0000000F) > 0) {
+        WOLFSSL_MSG("Found CAAM AES module");
+    }
+    else {
+        WOLFSSL_MSG("AES not supported by CAAM");
+        return WC_HW_E;
+    }
+    #endif
+
+    (void)ret;
+    return 0;
+}
+
+
+int wc_caamFree()
+{
+    return 0;
+}
+
+
+word32 wc_caamReadRegister(word32 reg)
+{
+    Value out = 0;
+
+    if (caam == NULLIODevice) {
+         WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?");
+         return 0;
+    }
+
+    if (ReadIODeviceRegister(caam, reg, &out) != Success) {
+         WOLFSSL_MSG("Error reading register\n");
+    }
+
+    return (word32)out;
+}
+
+void wc_caamWriteRegister(word32 reg, word32 value)
+{
+    if (caam == NULLIODevice) {
+         WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?");
+         return;
+    }
+
+    if (WriteIODeviceRegister(caam, reg, value) != Success) {
+         WOLFSSL_MSG("Error writing to register\n");
+    }
+}
+
+
+/* return 0 on success and WC_HW_E on failure. Can also return WC_HW_WAIT_E
+ * in the case that the driver is waiting for a resource or RAN_BLOCK_E if
+ * waiting for entropy. */
+int wc_caamAddAndWait(Buffer* buf, word32 arg[4], word32 type)
+{
+    int ret;
+    if (caam == NULLIODevice) {
+        WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?");
+        return WC_HW_E;
+    }
+
+    if ((ret = SynchronousSendIORequest(caam, type, (const Value*)arg, buf))
+         != Success) {
+    #if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG)
+        printf("ret of SynchronousSendIORequest = %d type = %d\n", ret, type);
+    #endif
+
+        /* if waiting for resource or RNG return waiting */
+        if (ret == Waiting) {
+            WOLFSSL_MSG("Waiting on entropy from driver");
+            return RAN_BLOCK_E;
+        }
+
+        if (ret == ResourceNotAvailable) {
+            WOLFSSL_MSG("Waiting on CAAM driver");
+            return WC_HW_WAIT_E;
+        }
+
+        return WC_HW_E;
+    }
+
+    (void)ret;
+    return 0;
+}
+
+
+int wc_caamCreateBlob(byte* data, word32 dataSz, byte* out, word32* outSz)
+{
+    Buffer in[3];
+    word32 arg[4];
+    int ret;
+    word32 local[2] = {0,0};
+
+    if (data == NULL || out == NULL || outSz == NULL ||
+            *outSz < dataSz + WC_CAAM_BLOB_SZ) {
+        return BAD_FUNC_ARG;
+    }
+
+    in[0].BufferType = DataBuffer;
+    in[0].TheAddress = (Address)local;
+    in[0].Length = sizeof(local);
+
+    in[1].BufferType = DataBuffer;
+    in[1].TheAddress = (Address)data;
+    in[1].Length = dataSz;
+
+    in[2].BufferType = DataBuffer | LastBuffer;
+    in[2].TheAddress = (Address)out;
+    in[2].Length = dataSz + WC_CAAM_BLOB_SZ;
+
+    arg[2] = dataSz;
+
+    if ((ret = wc_caamAddAndWait(in, arg, CAAM_BLOB_ENCAP)) != 0) {
+        WOLFSSL_MSG("Error with CAAM blob create");
+        return ret;
+    }
+
+    *outSz = dataSz + WC_CAAM_BLOB_SZ;
+    return 0;
+}
+
+
+int wc_caamOpenBlob(byte* data, word32 dataSz, byte* out, word32* outSz)
+{
+    Buffer in[3];
+    word32 arg[4];
+    int ret;
+    word32 local[2] = {0,0};
+
+    if (data == NULL || out == NULL || outSz == NULL ||
+            *outSz < dataSz - WC_CAAM_BLOB_SZ) {
+        return BAD_FUNC_ARG;
+    }
+
+    in[0].BufferType = DataBuffer;
+    in[0].TheAddress = (Address)local;
+    in[0].Length = sizeof(local);
+
+    in[0].BufferType = DataBuffer;
+    in[0].TheAddress = (Address)data;
+    in[0].Length = dataSz;
+
+    in[1].BufferType = DataBuffer | LastBuffer;
+    in[1].TheAddress = (Address)out;
+    in[1].Length = dataSz - WC_CAAM_BLOB_SZ;
+
+    arg[2] = dataSz;
+
+    if ((ret = wc_caamAddAndWait(in, arg, CAAM_BLOB_DECAP)) != 0) {
+        WOLFSSL_MSG("Error with CAAM blob create");
+        return ret;
+    }
+
+    *outSz = dataSz - WC_CAAM_BLOB_SZ;
+    return 0;
+}
+
+#endif /* WOLFSSL_IMX6_CAAM */
+

+ 397 - 0
wolfcrypt/src/port/caam/caam_sha.c

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

+ 45 - 0
wolfcrypt/src/random.c

@@ -1628,6 +1628,51 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
         return 0;
     }
 
+#elif (defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG))
+
+    #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
+    #include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
+
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        Buffer buf[1];
+        int ret  = 0;
+        int times = 1000, i;
+
+        (void)os;
+
+        if (output == NULL) {
+            return BUFFER_E;
+        }
+
+        buf[0].BufferType = DataBuffer | LastBuffer;
+        buf[0].TheAddress = (Address)output;
+        buf[0].Length     = sz;
+
+        /* Check Waiting to make sure entropy is ready */
+        for (i = 0; i < times; i++) {
+            ret = wc_caamAddAndWait(buf, NULL, CAAM_ENTROPY);
+            if (ret == Success) {
+                break;
+            }
+
+            /* driver could be waiting for entropy */
+            if (ret != RAN_BLOCK_E) {
+                return ret;
+            }
+            usleep(100);
+        }
+
+        if (i == times && ret != Success) {
+             return RNG_FAILURE_E;
+        }
+        else { /* Success case */
+            ret = 0;
+        }
+
+        return ret;
+    }
+
 #elif defined(CUSTOM_RAND_GENERATE_BLOCK)
     /* #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc
      * extern int myRngFunc(byte* output, word32 sz);

+ 2 - 0
wolfcrypt/src/sha.c

@@ -316,6 +316,8 @@ static INLINE void AddLength(wc_Sha* sha, word32 len);
         return ret;
     }
 
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
+    /* wolfcrypt/src/port/caam/caam_sha.c */
 #else
 
     /* Software implementation */

+ 16 - 8
wolfcrypt/src/sha256.c

@@ -123,7 +123,8 @@
 
 static INLINE void AddLength(wc_Sha256* sha256, word32 len);
 
-#if !defined(WOLFSSL_PIC32MZ_HASH) && !defined(STM32_HASH)
+#if !defined(WOLFSSL_PIC32MZ_HASH) && !defined(STM32_HASH) && \
+    (!defined(WOLFSSL_IMX6_CAAM) || defined(NO_IMX6_CAAM_HASH))
 static int InitSha256(wc_Sha256* sha256)
 {
     int ret = 0;
@@ -529,7 +530,8 @@ static int InitSha256(wc_Sha256* sha256)
 
         return ret;
     }
-
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
+    /* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */
 #else
     #define NEED_SOFT_SHA256
 
@@ -2722,8 +2724,13 @@ SHA256_NOINLINE static int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256,
         return ret;
     }
 
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
+    /* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */
 #else
 
+    #define NEED_SOFT_SHA224
+
+
     static int InitSha224(wc_Sha224* sha224)
     {
         int ret = 0;
@@ -2755,6 +2762,7 @@ SHA256_NOINLINE static int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256,
 
 #endif /* STM32_HASH */
 
+#if defined(NEED_SOFT_SHA224) || defined(STM32_HASH)
     int wc_InitSha224_ex(wc_Sha224* sha224, void* heap, int devId)
     {
         int ret = 0;
@@ -2778,11 +2786,6 @@ SHA256_NOINLINE static int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256,
         return ret;
     }
 
-    int wc_InitSha224(wc_Sha224* sha224)
-    {
-        return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID);
-    }
-
     int wc_Sha224Update(wc_Sha224* sha224, const byte* data, word32 len)
     {
         int ret;
@@ -2832,6 +2835,12 @@ SHA256_NOINLINE static int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256,
 
         return InitSha224(sha224);  /* reset state */
     }
+#endif /* end of SHA224 software implementation */
+
+    int wc_InitSha224(wc_Sha224* sha224)
+    {
+        return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID);
+    }
 
     void wc_Sha224Free(wc_Sha224* sha224)
     {
@@ -2842,7 +2851,6 @@ SHA256_NOINLINE static int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256,
         wolfAsync_DevCtxFree(&sha224->asyncDev, WOLFSSL_ASYNC_MARKER_SHA224);
     #endif /* WOLFSSL_ASYNC_CRYPT */
     }
-
 #endif /* WOLFSSL_SHA224 */
 
 

+ 11 - 1
wolfcrypt/src/sha512.c

@@ -168,6 +168,10 @@
         }
 #endif
 
+#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
+    /* functions defined in wolfcrypt/src/port/caam/caam_sha.c */
+#else
+
 static int InitSha512(wc_Sha512* sha512)
 {
     if (sha512 == NULL)
@@ -623,7 +627,7 @@ int wc_Sha512Update(wc_Sha512* sha512, const byte* data, word32 len)
 
     return Sha512Update(sha512, data, len);
 }
-
+#endif /* WOLFSSL_IMX6_CAAM */
 
 static INLINE int Sha512Final(wc_Sha512* sha512)
 {
@@ -2540,6 +2544,11 @@ static int Transform_Sha512_AVX2_RORX_Len(wc_Sha512* sha512, word32 len)
 /* SHA384 */
 /* -------------------------------------------------------------------------- */
 #ifdef WOLFSSL_SHA384
+
+#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
+    /* functions defined in wolfcrypt/src/port/caam/caam_sha.c */
+#else
+
 static int InitSha384(wc_Sha384* sha384)
 {
     if (sha384 == NULL) {
@@ -2644,6 +2653,7 @@ int wc_InitSha384_ex(wc_Sha384* sha384, void* heap, int devId)
     return ret;
 }
 #endif
+#endif /* WOLFSSL_IMX6_CAAM */
 
 int wc_InitSha384(wc_Sha384* sha384)
 {

+ 17 - 0
wolfcrypt/src/wc_port.c

@@ -59,6 +59,11 @@
     #include <wolfssl/wolfcrypt/mem_track.h>
 #endif
 
+#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \
+    defined(WOLFSSL_IMX6_CAAM_BLOB)
+    #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
+#endif
+
 #ifdef _MSC_VER
     /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */
     #pragma warning(disable: 4996)
@@ -153,6 +158,13 @@ int wolfCrypt_Init(void)
     #endif
 #endif
 
+#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \
+    defined(WOLFSSL_IMX6_CAAM_BLOB)
+        if ((ret = wc_caamInit()) != 0) {
+            return ret;
+        }
+#endif
+
         initRefCount = 1;
     }
 
@@ -189,6 +201,11 @@ int wolfCrypt_Cleanup(void)
         wolfAsync_HardwareStop();
     #endif
 
+    #if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \
+        defined(WOLFSSL_IMX6_CAAM_BLOB)
+        wc_caamFree();
+    #endif
+
         initRefCount = 0; /* allow re-init */
     }
 

+ 92 - 0
wolfcrypt/test/test.c

@@ -113,6 +113,9 @@
 #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
     #include <wolfssl/wolfcrypt/logging.h>
 #endif
+#ifdef WOLFSSL_IMX6_CAAM_BLOB
+    #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
+#endif
 
 /* only for stack size check */
 #ifdef HAVE_STACK_SIZE
@@ -317,6 +320,9 @@ int mutex_test(void);
 #if defined(USE_WOLFSSL_MEMORY) && !defined(FREERTOS)
 int memcb_test(void);
 #endif
+#ifdef WOLFSSL_IMX6_CAAM_BLOB
+int blob_test(void);
+#endif
 
 #if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) && \
         !defined(OPENSSL_EXTRA) && !defined(HAVE_STACK_SIZE)
@@ -874,6 +880,13 @@ int wolfcrypt_test(void* args)
         printf( "memcb    test passed!\n");
 #endif
 
+#ifdef WOLFSSL_IMX6_CAAM_BLOB
+    if ( (ret = blob_test()) != 0)
+        return err_sys("blob     test failed!\n", ret);
+    else
+        printf( "blob     test passed!\n");
+#endif
+
 #ifdef WOLFSSL_ASYNC_CRYPT
     wolfAsync_DevClose(&devId);
 #endif
@@ -15266,6 +15279,85 @@ exit_memcb:
 }
 #endif
 
+
+#ifdef WOLFSSL_IMX6_CAAM_BLOB
+int blob_test(void)
+{
+    int ret = 0;
+    byte out[112];
+    byte blob[112];
+    word32 outSz;
+
+    const byte iv[] =
+        {
+            0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,
+            0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
+        };
+
+    const byte text[] =
+        {
+            0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,
+            0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a,
+            0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,
+            0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51,
+            0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11,
+            0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef,
+            0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17,
+            0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10
+        };
+
+
+    memset(blob, 0, sizeof(blob));
+    outSz = sizeof(blob);
+    ret = wc_caamCreateBlob((byte*)iv, sizeof(iv), blob, &outSz);
+    if (ret != 0) {
+        ERROR_OUT(-8200, exit_blob);
+    }
+
+    blob[outSz - 2] += 1;
+    ret = wc_caamOpenBlob(blob, outSz, out, &outSz);
+    if (ret == 0) { /* should fail with altered blob */
+        ERROR_OUT(-8201, exit_blob);
+    }
+
+    memset(blob, 0, sizeof(blob));
+    outSz = sizeof(blob);
+    ret = wc_caamCreateBlob((byte*)iv, sizeof(iv), blob, &outSz);
+    if (ret != 0) {
+        ERROR_OUT(-8202, exit_blob);
+    }
+
+    ret = wc_caamOpenBlob(blob, outSz, out, &outSz);
+    if (ret != 0) {
+        ERROR_OUT(-8203, exit_blob);
+    }
+
+    if (XMEMCMP(out, iv, sizeof(iv))) {
+        ERROR_OUT(-8204, exit_blob);
+    }
+
+    memset(blob, 0, sizeof(blob));
+    outSz = sizeof(blob);
+    ret = wc_caamCreateBlob((byte*)text, sizeof(text), blob, &outSz);
+    if (ret != 0) {
+        ERROR_OUT(-8205, exit_blob);
+    }
+
+    ret = wc_caamOpenBlob(blob, outSz, out, &outSz);
+    if (ret != 0) {
+        ERROR_OUT(-8206, exit_blob);
+    }
+
+    if (XMEMCMP(out, text, sizeof(text))) {
+        ERROR_OUT(-8207, exit_blob);
+    }
+
+    exit_blob:
+
+    return ret;
+}
+#endif /* WOLFSSL_IMX6_CAAM_BLOB */
+
 #undef ERROR_OUT
 
 #else

+ 8 - 1
wolfssl/test.h

@@ -790,7 +790,11 @@ static INLINE int tcp_select(SOCKET_T socketfd, int to_sec)
 {
     fd_set recvfds, errfds;
     SOCKET_T nfds = socketfd + 1;
-    struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0};
+#if !defined(__INTEGRITY)
+    struct timeval timeout = {(to_sec > 0) ? to_sec : 0, 0};
+#else
+    struct timeval timeout;
+#endif
     int result;
 
     FD_ZERO(&recvfds);
@@ -798,6 +802,9 @@ static INLINE int tcp_select(SOCKET_T socketfd, int to_sec)
     FD_ZERO(&errfds);
     FD_SET(socketfd, &errfds);
 
+#if defined(__INTEGRITY)
+    timeout.tv_sec = (long long)(to_sec > 0) ? to_sec : 0, 0;
+#endif
     result = select(nfds, &recvfds, NULL, &errfds, &timeout);
 
     if (result == 0)

+ 3 - 1
wolfssl/wolfcrypt/error-crypt.h

@@ -191,8 +191,10 @@ enum {
 
     ECC_PRIVATEONLY_E   = -246,  /* Invalid use of private only ECC key*/
     EXTKEYUSAGE_E       = -247,  /* Bad Extended Key Usage value */
+    WC_HW_E             = -248,  /* Error with hardware crypto use */
+    WC_HW_WAIT_E        = -249,  /* Hardware waiting on resource */
 
-    WC_LAST_E           = -247,  /* Update this to indicate last error */
+    WC_LAST_E           = -249,  /* Update this to indicate last error */
     MIN_CODE_E          = -300   /* errors -101 - -299 */
 
     /* add new companion error id strings for any new error codes

+ 4 - 1
wolfssl/wolfcrypt/include.am

@@ -70,7 +70,10 @@ noinst_HEADERS+= \
                          wolfssl/wolfcrypt/port/nrf51.h \
                          wolfssl/wolfcrypt/port/nxp/ksdk_port.h \
                          wolfssl/wolfcrypt/port/atmel/atmel.h \
-                         wolfssl/wolfcrypt/port/xilinx/xil-sha3.h
+                         wolfssl/wolfcrypt/port/xilinx/xil-sha3.h \
+                         wolfssl/wolfcrypt/port/caam/caam_driver.h \
+                         wolfssl/wolfcrypt/port/caam/wolfcaam.h \
+                         wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h
 
 if BUILD_ASYNCCRYPT
 nobase_include_HEADERS+= wolfssl/wolfcrypt/async.h

+ 2 - 0
wolfssl/wolfcrypt/md5.h

@@ -63,6 +63,8 @@ enum {
 
 #ifdef WOLFSSL_TI_HASH
     #include "wolfssl/wolfcrypt/port/ti/ti-hash.h"
+#elif defined(WOLFSSL_IMX6_CAAM)
+    #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h"
 #else
 
 /* MD5 digest */

+ 187 - 0
wolfssl/wolfcrypt/port/caam/caam_driver.h

@@ -0,0 +1,187 @@
+/* caam_driver.h
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#ifndef CAAM_DRIVER_H
+#define CAAM_DRIVER_H
+
+#define CAAM_BASE 0xf2100000
+
+#define CAAM_PAGE 0xf0100000
+#define CAAM_PAGE_MAX 6
+
+/******************************************************************************
+  Basic Descriptors
+  ****************************************************************************/
+
+/* descriptor commands */
+#define CAAM_KEY      0x00000000
+#define CAAM_LOAD     0x10000000
+#define CAAM_LOAD_CTX 0x10200000
+#define CAAM_IMM      0x00800000
+#define CAAM_FIFO_L   0x20000000
+#define CAAM_FIFO_S   0x60000000
+#define CAAM_FIFO_S_SKEY 0x60260000
+#define CAAM_STORE       0x50000000
+#define CAAM_STORE_CTX   0x50200000
+#define CAAM_MOVE        0x78000000
+#define CAAM_OP          0x80000000
+#define CAAM_SIG         0x90000000
+#define CAAM_JUMP        0xA0000000
+#define CAAM_SEQI        0xF0000000/* SEQ in  */
+#define CAAM_SEQO        0xF8000000/* SEQ out */
+#define CAAM_HEAD        0xB0800000
+#define CAAM_NWB         0x00200000
+
+#define CAAM_BLOB_ENCAP 0x07000000
+#define CAAM_BLOB_DECAP 0x06000000
+#define CAAM_OPID_BLOB  0x000D0000
+
+/* algorithms modes and types */
+#define CAAM_CLASS1 0x02000000/* i.e. AES */
+#define CAAM_CLASS2 0x04000000/* i.e. hash algos */
+
+#define CAAM_ENC    0x00000001
+#define CAAM_DEC    0x00000000
+#define CAAM_ALG_INIT   0x00000004
+#define CAAM_ALG_INITF  0x0000000C
+#define CAAM_ALG_UPDATE 0x00000000
+#define CAAM_ALG_FINAL  0x00000008
+
+    /* AES 10h */
+#define CAAM_AESCTR 0x00100000
+#define CAAM_AESCBC 0x00100100
+#define CAAM_AESECB 0x00100200
+#define CAAM_AESCFB 0x00100300
+#define CAAM_AESOFB 0x00100400
+#define CAAM_CMAC   0x00100600
+#define CAAM_AESCCM 0x00100800
+
+    /* HASH 40h */
+#define CAAM_MD5    0x00400000
+#define CAAM_SHA    0x00410000
+#define CAAM_SHA224 0x00420000
+#define CAAM_SHA256 0x00430000
+#define CAAM_SHA384 0x00440000
+#define CAAM_SHA512 0x00450000
+
+    /* HMAC 40h + 10 AAI */
+#define CAAM_HMAC_MD5    0x00400010
+#define CAAM_HMAC_SHA    0x00410010
+#define CAAM_HMAC_SHA224 0x00420010
+#define CAAM_HMAC_SHA256 0x00430010
+#define CAAM_HMAC_SHA384 0x00440010
+#define CAAM_HMAC_SHA512 0x00450010
+
+#define CAAM_MD5_CTXSZ (16 + 8)
+#define CAAM_SHA_CTXSZ (20 + 8)
+#define CAAM_SHA224_CTXSZ (32 + 8)
+#define CAAM_SHA256_CTXSZ (32 + 8)
+#define CAAM_SHA384_CTXSZ (64 + 8)
+#define CAAM_SHA512_CTXSZ (64 + 8)
+
+    /* RNG 50h */
+#define CAAM_RNG 0x00500000
+
+    /* Used to get raw entropy from TRNG */
+#define CAAM_ENTROPY 0x00500001
+
+#define FIFOL_TYPE_MSG 0x00100000
+#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
+
+/* continue bit set if more output is expected */
+#define CAAM_FIFOS_CONT 0x00800000
+
+#define CAAM_PAGE_SZ 4096
+
+/* RNG Registers */
+#define CAAM_RTMCTL      CAAM_BASE + 0X0600
+#define CAAM_RTSDCTL     CAAM_BASE + 0X0610
+#define CAAM_RTFRQMIN    CAAM_BASE + 0X0618
+#define CAAM_RTFRQMAX    CAAM_BASE + 0X061C
+#define CAAM_RDSTA       CAAM_BASE + 0X06C0
+#define CAAM_RTSTATUS    CAAM_BASE + 0x063C
+
+/* each of the following 11 RTENT registers are an offset of 4 from RTENT0 */
+#define CAAM_RTENT0      CAAM_BASE + 0x0640
+#define CAAM_RTENT11     CAAM_BASE + 0x066C /* Max RTENT register */
+
+/* RNG Masks/Values */
+#ifndef CAAM_ENT_DLY
+    #define CAAM_ENT_DLY   1200 /* @TODO lower value may gain performance */
+#endif
+#define CAAM_PRGM      0x00010000 /* Set RTMCTL to program state */
+#define CAAM_TRNG      0x00000020 /* Set TRNG access */
+#define CAAM_CTLERR    0x00001000
+#define CAAM_ENTVAL    0x00000400 /* checking RTMCTL for entropy ready */
+
+/* Input Job Ring Registers */
+#define CAAM_IRBAR0      CAAM_BASE + 0x1004
+#define CAAM_IRSR0       CAAM_BASE + 0x100C
+#define CAAM_IRJAR0      CAAM_BASE + 0x101C
+
+/* Ouput Job Ring Registers */
+#define CAAM_ORBAR0      CAAM_BASE + 0x1024
+#define CAAM_ORSR0       CAAM_BASE + 0x102C
+#define CAAM_ORJAR0      CAAM_BASE + 0x103C
+
+
+/* Status Registers */
+#define CAAM_STATUS      CAAM_BASE + 0x0FD4
+#define CAAM_VERSION_MS  CAAM_BASE + 0x0FE8
+#define CAAM_VERSION_LS  CAAM_BASE + 0x0FEC
+#define CAMM_SUPPORT_MS  CAAM_BASE + 0x0FF0
+#define CAMM_SUPPORT_LS  CAAM_BASE + 0x0FF4
+
+
+#define CAAM_C1DSR_LS    CAAM_BASE + 0x8014
+#define CAAM_C1MR        CAAM_BASE + 0x8004
+
+
+/* output FIFO  is 16 entries deep and each entry has a two 4 byte registers */
+#define CAAM_FIFOO_MS    CAAM_BASE + 0x87F0
+#define CAAM_FIFOO_LS    CAAM_BASE + 0x87F4
+
+/* input FIFO is 16 entries deep with each entry having two 4 byte registers
+   All data writin to it from IP bus should be in big endian format */
+#define CAAM_FIFOI_LS    CAAM_BASE + 0x87E0
+
+/* offset of 4 with range 0 .. 13 */
+#define CAAM_CTX1        CAAM_BASE + 0x8100
+#define CAAM_CTRIV       CAAM_CTX1 + 8 /* AES-CTR iv is in 2 and 3 */
+#define CAAM_CBCIV       CAAM_CTX1     /* AES-CBC iv is in 1 and 2 */
+
+
+/* instantiate RNG and create JDKEK, TDKEK, and TDSK key */
+static unsigned int wc_rng_start[] = {
+    CAAM_HEAD | 0x00000006,
+    CAAM_OP | CAAM_CLASS1 | CAAM_RNG | 0x00000004, /* Instantiate RNG handle 0 with TRNG */
+    CAAM_JUMP | 0x02000001,  /* wait for Class1 RNG and jump to next cmd */
+    CAAM_LOAD | 0x00880004,  /* Load to clear written register */
+    0x00000001, /* reset done interupt */
+    CAAM_OP | CAAM_CLASS1 | CAAM_RNG | 0x00001000   /* Generate secure keys */
+};
+
+#endif /* CAAM_DRIVER_H */

+ 63 - 0
wolfssl/wolfcrypt/port/caam/wolfcaam.h

@@ -0,0 +1,63 @@
+/* wolfcaam.h
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#ifndef WOLF_CRYPT_CAAM_INIT_H
+#define WOLF_CRYPT_CAAM_INIT_H
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG)
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#if defined(__INTEGRITY) || defined(INTEGRITY)
+    #include <INTEGRITY.h>
+#endif
+
+WOLFSSL_LOCAL int wc_caamInit(void);
+WOLFSSL_LOCAL int wc_caamFree(void);
+WOLFSSL_LOCAL int wc_caamInitRng(void);
+WOLFSSL_LOCAL int wc_caamFreeRng(void);
+
+WOLFSSL_LOCAL word32 wc_caamReadRegister(word32 reg);
+WOLFSSL_LOCAL void wc_caamWriteRegister(word32 reg, word32 value);
+WOLFSSL_LOCAL int  wc_caamAddAndWait(Buffer* buf, word32 arg[4], word32 type);
+
+WOLFSSL_API int wc_caamSetResource(IODevice ioDev);
+
+WOLFSSL_API int wc_caamOpenBlob(byte* data, word32 dataSz, byte* out,
+	word32* outSz);
+WOLFSSL_API int wc_caamCreateBlob(byte* data, word32 dataSz, byte* out,
+	word32* outSz);
+
+/* additional size that is added by CAAM when creating a blob */
+#define WC_CAAM_BLOB_SZ 48
+
+#ifndef WC_CAAM_READ
+    #define WC_CAAM_READ(reg)      wc_caamReadRegister((reg))
+#endif
+#ifndef WC_CAAM_WRITE
+    #define WC_CAAM_WRITE(reg, x)  wc_caamWriteRegister((reg), (x))
+#endif
+
+#endif /* WOLFSSL_IMX6_CAAM */
+
+#endif /* WOLF_CRYPT_CAAM_INIT_H */

+ 86 - 0
wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h

@@ -0,0 +1,86 @@
+/* wolfcaam_sha.h
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#ifndef WOLF_CRYPT_CAAM_SHA_H
+#define WOLF_CRYPT_CAAM_SHA_H
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifdef WOLFSSL_IMX6_CAAM
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifndef WC_CAAM_CTXLEN
+/* last 8 bytes of context is for length */
+#define WC_CAAM_CTXLEN 8
+#endif
+
+#ifndef WC_CAAM_HASH_BLOCK
+/* define sha structures and also get the max possible digest. Start with SHA
+   digest size */
+#define WC_CAAM_HASH_BLOCK 64
+#endif
+
+#ifndef WC_CAAM_MAX_DIGEST
+#define WC_CAAM_MAX_DIGEST 20
+#ifdef WOLFSSL_SHA224
+    #undef WC_CAAM_MAX_DIGEST
+    #define WC_CAAM_MAX_DIGEST 32
+#endif
+
+#ifndef NO_SHA256
+    #undef WC_CAAM_MAX_DIGEST
+    #define WC_CAAM_MAX_DIGEST 32
+#endif
+
+#ifdef WOLFSSL_SHA384
+    #undef WC_CAAM_MAX_DIGEST
+    #define WC_CAAM_MAX_DIGEST 64
+#endif
+
+#ifdef WOLFSSL_SHA512
+    #undef WC_CAAM_MAX_DIGEST
+    #define WC_CAAM_MAX_DIGEST 64
+#endif
+#endif /* WC_CAAM_MAX_DIGEST */
+
+
+typedef struct wc_Sha {
+    word32  ctx[(WC_CAAM_MAX_DIGEST + WC_CAAM_CTXLEN) / sizeof(word32)];
+    word32  buffLen;   /* in bytes          */
+    word32  buffer[WC_CAAM_HASH_BLOCK  / sizeof(word32)];
+} wc_Sha;
+
+#ifndef NO_MD5
+    typedef struct wc_Sha wc_Md5;
+#endif
+
+#ifndef NO_SHA256
+    typedef struct wc_Sha wc_Sha256;
+#endif
+
+#ifdef WOLFSSL_SHA512
+    typedef struct wc_Sha wc_Sha512;
+#endif
+
+#endif /* WOLFSSL_IMX6_CAAM */
+
+#endif /* WOLF_CRYPT_CAAM_SHA_H */

+ 21 - 0
wolfssl/wolfcrypt/settings.h

@@ -1183,6 +1183,27 @@ extern void uITRON4_free(void *p) ;
     #endif
 #endif /*(WOLFSSL_XILINX_CRYPT)*/
 
+#ifdef WOLFSSL_IMX6
+    #ifndef SIZEOF_LONG_LONG
+        #define SIZEOF_LONG_LONG 8
+    #endif
+#endif
+
+/* if defined turn on all CAAM support */
+#ifdef WOLFSSL_IMX6_CAAM
+    #undef  WOLFSSL_IMX6_CAAM_RNG
+    #define WOLFSSL_IMX6_CAAM_RNG
+
+    #undef  WOLFSSL_IMX6_CAAM_BLOB
+    #define WOLFSSL_IMX6_CAAM_BLOB
+
+#if defined(HAVE_AESGCM) || defined(WOLFSSL_AES_XTS)
+    /* large performance gain with HAVE_AES_ECB defined */
+    #undef HAVE_AES_ECB
+    #define HAVE_AES_ECB
+#endif
+#endif
+
 #if !defined(XMALLOC_USER) && !defined(MICRIUM_MALLOC) && \
     !defined(WOLFSSL_LEANPSK) && !defined(NO_WOLFSSL_MEMORY) && \
     !defined(XMALLOC_OVERRIDE)

+ 7 - 3
wolfssl/wolfcrypt/sha.h

@@ -72,7 +72,13 @@ enum {
 };
 
 
-#ifndef WOLFSSL_TI_HASH
+#if defined(WOLFSSL_TI_HASH)
+    #include "wolfssl/wolfcrypt/port/ti/ti-hash.h"
+
+#elif defined(WOLFSSL_IMX6_CAAM)
+    #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h"
+
+#else
 /* Sha digest */
 typedef struct wc_Sha {
     #ifdef FREESCALE_LTC_SHA
@@ -100,8 +106,6 @@ typedef struct wc_Sha {
 #endif /* FREESCALE_LTC_SHA */
 } wc_Sha;
 
-#else
-    #include "wolfssl/wolfcrypt/port/ti/ti-hash.h"
 #endif /* WOLFSSL_TI_HASH */
 
 

+ 5 - 4
wolfssl/wolfcrypt/sha256.h

@@ -90,8 +90,11 @@ enum {
     WC_SHA256_PAD_SIZE     = 56
 };
 
-#ifndef WOLFSSL_TI_HASH
-
+#ifdef WOLFSSL_TI_HASH
+    #include "wolfssl/wolfcrypt/port/ti/ti-hash.h"
+#elif defined(WOLFSSL_IMX6_CAAM)
+    #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h"
+#else
 /* wc_Sha256 digest */
 typedef struct wc_Sha256 {
 #ifdef FREESCALE_LTC_SHA
@@ -119,8 +122,6 @@ typedef struct wc_Sha256 {
 #endif /* FREESCALE_LTC_SHA */
 } wc_Sha256;
 
-#else
-    #include "wolfssl/wolfcrypt/port/ti/ti-hash.h"
 #endif
 
 #endif /* HAVE_FIPS */

+ 4 - 0
wolfssl/wolfcrypt/sha512.h

@@ -84,6 +84,9 @@ enum {
 };
 
 
+#ifdef WOLFSSL_IMX6_CAAM
+    #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h"
+#else
 /* wc_Sha512 digest */
 typedef struct wc_Sha512 {
     word64  digest[WC_SHA512_DIGEST_SIZE / sizeof(word64)];
@@ -99,6 +102,7 @@ typedef struct wc_Sha512 {
     WC_ASYNC_DEV asyncDev;
 #endif /* WOLFSSL_ASYNC_CRYPT */
 } wc_Sha512;
+#endif
 
 #endif /* HAVE_FIPS */
 

+ 1 - 0
wolfssl/wolfcrypt/types.h

@@ -449,6 +449,7 @@
         DYNAMIC_TYPE_QSH          = 86,
         DYNAMIC_TYPE_SALT         = 87,
         DYNAMIC_TYPE_HASH_TMP     = 88,
+        DYNAMIC_TYPE_BLOB         = 89,
 	};
 
 	/* max error buffer string size */