diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index f008843a6..aba26594b 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -243,9 +243,11 @@ #include #endif -#if !defined(WOLFSSL_ARMASM) && !defined(WOLFSSL_IMX6_CAAM) +#if !defined(WOLFSSL_ARMASM) #ifdef WOLFSSL_IMX6_CAAM_BLOB + /* case of possibly not using hardware acceleration for AES but using key + blobs */ #include #endif @@ -785,6 +787,17 @@ } #endif /* HAVE_AES_DECRYPT */ +#elif defined(WOLFSSL_IMX6_CAAM) + 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 */ @@ -1978,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) + /* 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) @@ -2289,6 +2305,9 @@ int wc_AesSetIV(Aes* aes, const byte* iv) key, keySize, kLTC_EncryptKey); } + #elif defined(WOLFSSL_IMX6_CAAM) + /* 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) @@ -2856,6 +2875,9 @@ int wc_AesSetIV(Aes* aes, const byte* iv) } #endif /* HAVE_AES_DECRYPT */ +#elif defined(WOLFSSL_IMX6_CAAM) + /* implemented in wolfcrypt/src/port/caam/caam_aes.c */ + #else int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) @@ -3246,6 +3268,9 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) return 0; } + #elif defined(WOLFSSL_IMX6_CAAM) + /* implemented in wolfcrypt/src/port/caam/caam_aes.c */ + #else /* Use software based AES counter */ @@ -3432,10 +3457,10 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) 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) { + 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; } diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index 9c87f1111..e537d1927 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -437,6 +437,9 @@ const char* wc_GetErrorString(int error) case WC_CAAM_E: return "Error with CAAM use"; + case WC_CAAM_WAIT: + return "CAAM Driver waiting on resource"; + default: return "unknown error number"; diff --git a/wolfcrypt/src/port/caam/caam_aes.c b/wolfcrypt/src/port/caam/caam_aes.c index f404f80ef..082c6d294 100644 --- a/wolfcrypt/src/port/caam/caam_aes.c +++ b/wolfcrypt/src/port/caam/caam_aes.c @@ -46,51 +46,50 @@ 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; + return BAD_FUNC_ARG; } - + if (len > 32) { - byte out[32]; /* max AES key size */ - word32 outSz; + 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, NULL, 0)) != 0) { - return ret; - } + if (len != 64 && len != 72 && len != 80) { + return BAD_FUNC_ARG; + } - XMEMCPY((byte*)aes->key, out, outSz); + 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; - } + 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; + 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 @@ -99,35 +98,18 @@ int wc_AesSetKey(Aes* aes, const byte* key, word32 len, } -int wc_AesSetIV(Aes* aes, const byte* iv) -{ - if (aes == NULL) { - return BAD_FUNC_ARG; - } - - if (iv == NULL) { - XMEMSET((byte*)aes->reg, 0, AES_BLOCK_SIZE); - } - else { - XMEMCPY((byte*)aes->reg, iv, AES_BLOCK_SIZE); - } - - 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]; @@ -146,7 +128,7 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, 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; @@ -154,17 +136,17 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, 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] = sz; - + if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCBC)) != 0) { - WOLFSSL_MSG("Error with CAAM AES CBC encrypt"); - return ret; + WOLFSSL_MSG("Error with CAAM AES CBC encrypt"); + return ret; } } - + return 0; } @@ -173,14 +155,14 @@ 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]; @@ -188,7 +170,7 @@ int wc_AesCbcDecrypt(Aes* aes, byte* out, int ret; if (wc_AesGetKeySize(aes, &keySz) != 0) { - return BAD_FUNC_ARG; + return BAD_FUNC_ARG; } /* Set buffers for key, cipher text, and plain text */ @@ -199,7 +181,7 @@ int wc_AesCbcDecrypt(Aes* aes, byte* out, 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; @@ -207,17 +189,17 @@ int wc_AesCbcDecrypt(Aes* aes, byte* out, 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] = sz; - + if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCBC)) != 0) { - WOLFSSL_MSG("Error with CAAM AES CBC decrypt"); - return ret; + WOLFSSL_MSG("Error with CAAM AES CBC decrypt"); + return ret; } } - + return 0; } @@ -227,20 +209,20 @@ int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { word32 blocks; - + if (aes == NULL || out == NULL || in == NULL) { BAD_FUNC_ARG; } blocks = sz / AES_BLOCK_SIZE; - + while (blocks > 0) { wc_AesEncryptDirect(aes, out, in); - blocks--; - out += AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; + blocks--; + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; } - + return 0; } @@ -249,7 +231,7 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { word32 blocks; - + if (aes == NULL || out == NULL || in == NULL) { BAD_FUNC_ARG; } @@ -259,11 +241,11 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, /* @TODO search for more efficient solution */ while (blocks > 0) { wc_AesDecryptDirect(aes, out, in); - blocks--; - out += AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; + blocks--; + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; } - + return 0; } #endif @@ -281,62 +263,62 @@ static INLINE void IncrementAesCounter(byte* inOutCtr) } } - + 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; + 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 (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } - if (wc_AesGetKeySize(aes, &keySz) != 0) { - 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--; - } + /* 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; + /* 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[1].BufferType = DataBuffer; + buf[1].TheAddress = (Address)aes->reg; + buf[1].Length = 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] = sz; - - if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCTR)) != 0) { - WOLFSSL_MSG("Error with CAAM AES CTR encrypt"); - return ret; - } - out += blocks * AES_BLOCK_SIZE; - sz -= blocks * 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] = sz; + + if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCTR)) != 0) { + WOLFSSL_MSG("Error with CAAM AES CTR encrypt"); + return ret; + } + out += blocks * AES_BLOCK_SIZE; + sz -= blocks * AES_BLOCK_SIZE; } if (sz) { @@ -351,7 +333,7 @@ int wc_AesCtrEncrypt(Aes* aes, byte* out, aes->left--; } } - + return 0; } #endif @@ -366,13 +348,13 @@ void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) word32 keySz; if (aes == NULL || out == NULL || in == NULL) { - //return BAD_FUNC_ARG; + /* return BAD_FUNC_ARG; */ return; } if (wc_AesGetKeySize(aes, &keySz) != 0) { - //return BAD_FUNC_ARG; - return; + /* return BAD_FUNC_ARG; */ + return; } /* Set buffers for key, cipher text, and plain text */ @@ -387,11 +369,11 @@ void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) 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"); } @@ -405,12 +387,12 @@ void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) word32 keySz; if (aes == NULL || out == NULL || in == NULL) { - //return BAD_FUNC_ARG; + /* return BAD_FUNC_ARG; */ return; } if (wc_AesGetKeySize(aes, &keySz) != 0) { - //return BAD_FUNC_ARG; + /* return BAD_FUNC_ARG; */ return; } @@ -426,11 +408,11 @@ void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) 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"); } @@ -445,78 +427,26 @@ int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len, #endif #ifdef HAVE_AESCCM - -#warning AES-CCM mode not complete - -/* from wolfcrypt/src/aes.c */ -static void roll_auth(const byte* in, word32 inSz, byte* out) -{ - word32 authLenSz; - word32 remainder; - - /* encode the length in */ - if (inSz <= 0xFEFF) { - authLenSz = 2; - out[0] ^= ((inSz & 0xFF00) >> 8); - out[1] ^= (inSz & 0x00FF); - } - else if (inSz <= 0xFFFFFFFF) { - authLenSz = 6; - out[0] ^= 0xFF; out[1] ^= 0xFE; - out[2] ^= ((inSz & 0xFF000000) >> 24); - out[3] ^= ((inSz & 0x00FF0000) >> 16); - out[4] ^= ((inSz & 0x0000FF00) >> 8); - out[5] ^= (inSz & 0x000000FF); - } - /* Note, the protocol handles auth data up to 2^64, but we are - * using 32-bit sizes right now, so the bigger data isn't handled - * else if (inSz <= 0xFFFFFFFFFFFFFFFF) {} */ - else - return; - - /* start fill out the rest of the first block */ - remainder = AES_BLOCK_SIZE - authLenSz; - if (inSz >= remainder) { - /* plenty of bulk data to fill the remainder of this block */ - xorbuf(out + authLenSz, in, remainder); - inSz -= remainder; - in += remainder; - } - else { - /* not enough bulk data, copy what is available, and pad zero */ - xorbuf(out + authLenSz, in, inSz); - inSz = 0; - } -} - - -int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) -{ - return wc_AesSetKey(aes, key, keySz, NULL, AES_ENCRYPTION); -} - - 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[4]; + Buffer buf[5]; word32 arg[4]; word32 keySz; word32 i; byte B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE]; - byte A[AES_BLOCK_SIZE]; - byte ASz = 0; 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) + || authTag == NULL || nonceSz < 7 || nonceSz > 13 || + authTagSz > AES_BLOCK_SIZE) return BAD_FUNC_ARG; if (wc_AesGetKeySize(aes, &keySz) != 0) { @@ -525,6 +455,7 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, /* 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)) @@ -533,18 +464,10 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, 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; } - - if (authInSz > 0) { - ASz = AES_BLOCK_SIZE; - roll_auth(authIn, authInSz, A); - } - B0Ctr0[AES_BLOCK_SIZE] = lenSz - 1; - for (i = 0; i < lenSz; i++) - B0Ctr0[(AES_BLOCK_SIZE + AES_BLOCK_SIZE) - 1 - i] = 0; - B0Ctr0[(AES_BLOCK_SIZE + AES_BLOCK_SIZE) - 1] = 1; - + /* Set buffers for key, cipher text, and plain text */ buf[0].BufferType = DataBuffer; buf[0].TheAddress = (Address)aes->key; @@ -553,32 +476,33 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, 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)in; - buf[2].Length = inSz; + buf[2].TheAddress = (Address)authIn; + buf[2].Length = authInSz; buf[3].BufferType = DataBuffer; - buf[3].TheAddress = (Address)out; + buf[3].TheAddress = (Address)in; buf[3].Length = inSz; - buf[3].BufferType = DataBuffer | LastBuffer; - buf[3].TheAddress = (Address)A; - buf[3].Length = ASz; - + 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] = ASz; - + arg[3] = authInSz; + if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCCM)) != 0) { WOLFSSL_MSG("Error with CAAM AES-CCM encrypt"); - return ret; + return ret; } + XMEMCPY(authTag, B0Ctr0, authTagSz); return 0; } - + #ifdef HAVE_AES_DECRYPT int wc_AesCcmDecrypt(Aes* aes, byte* out, @@ -587,21 +511,21 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz) { - Buffer buf[4]; + Buffer buf[5]; word32 arg[4]; word32 keySz; word32 i; byte B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE]; - byte A[AES_BLOCK_SIZE]; - byte ASz = 0; + 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) + || authTag == NULL || nonceSz < 7 || nonceSz > 13 || + authTagSz > AES_BLOCK_SIZE) return BAD_FUNC_ARG; if (wc_AesGetKeySize(aes, &keySz) != 0) { @@ -610,6 +534,7 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, /* 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)) @@ -618,18 +543,11 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, 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; } - - if (authInSz > 0) { - ASz = AES_BLOCK_SIZE; - roll_auth(authIn, authInSz, A); - } - B0Ctr0[AES_BLOCK_SIZE] = lenSz - 1; - for (i = 0; i < lenSz; i++) - B0Ctr0[(AES_BLOCK_SIZE + AES_BLOCK_SIZE) - 1 - i] = 0; - B0Ctr0[(AES_BLOCK_SIZE + AES_BLOCK_SIZE) - 1] = 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; @@ -638,72 +556,46 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, 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)in; - buf[2].Length = inSz; + buf[2].TheAddress = (Address)authIn; + buf[2].Length = authInSz; buf[3].BufferType = DataBuffer; - buf[3].TheAddress = (Address)out; + buf[3].TheAddress = (Address)in; buf[3].Length = inSz; - buf[3].BufferType = DataBuffer | LastBuffer; - buf[3].TheAddress = (Address)A; - buf[3].Length = ASz; - + 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] = ASz; - + arg[3] = authInSz; + if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCCM)) != 0) { WOLFSSL_MSG("Error with CAAM AES-CCM derypt"); - return ret; + return ret; } - return 0; + 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 */ - -int wc_AesGetKeySize(Aes* aes, word32* keySize) -{ - if (aes != NULL && keySize != NULL) { - *keySize = aes->keylen; - - /* preform sanity check on rounds to conform with test case */ - if (aes->rounds != 10 && aes->rounds != 12 && aes->rounds != 14) { - return BAD_FUNC_ARG; - } - - return 0; - } - - return BAD_FUNC_ARG; -} - - -int wc_AesInit(Aes* aes, void* heap, int devId) -{ - if (aes == NULL) { - return BAD_FUNC_ARG; - } - - aes->heap = heap; - (void)devId; - - return 0; -} - - -void wc_AesFree(Aes* aes) -{ - if (aes != NULL) { - ForceZero((byte*)aes->key, 32); - } -} - - #endif /* WOLFSSL_IMX6_CAAM && !NO_AES */ diff --git a/wolfcrypt/src/port/caam/caam_driver.c b/wolfcrypt/src/port/caam/caam_driver.c index f857c82de..8c0c877d6 100644 --- a/wolfcrypt/src/port/caam/caam_driver.c +++ b/wolfcrypt/src/port/caam/caam_driver.c @@ -1,1382 +1,1794 @@ -/* caam_driver.c - * - * Copyright (C) 2006-2016 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 -#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) - X2 for split keys */ -#define MAX_CTX 36 - -#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 */ - Address output; /* address to output buffer */ - Address ctxOut; /* address to update buffer holding state */ - UINT4 desc[MAX_DESC_SZ]; /* max size of 64 word32 */ - UINT4 shaBuf[ALIGN_BUF]; /* 64 byte buffer for non page align */ - UINT4 iv[MAX_CTX]; /* AES IV and also hash state */ - UINT4 ctxBuf[MAX_CTX]; /* key */ - Value shaIdx; /* index for descriptor 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 interupts 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 prgress */ - 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 permisions, 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 inquery 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 unavialbale */ - } - } - 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 inquery 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 avialable 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; - - /* set desc size */ - desc->desc[0] += desc->idx; - - /* check input slot is avialable 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->output != 0) { /* for testing */ - // memcpy((char*)desc->output, msg, sizeof(msg)); - //} - if (desc->ctxOut != 0) { /* for testing */ - memcpy((char*)desc->ctxOut, 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 potental overlap */ - int tmpSz = dataSz % align; - int add = (tmpSz < (align - desc->shaIdx)) ? tmpSz : align - desc->shaIdx; - unsigned char* local = (unsigned char*)desc->shaBuf; - - /* if already something in the buffer then add from front */ - if (desc->shaIdx > 0) { - memcpy((unsigned char*)&local[desc->shaIdx], - (unsigned char*)data, add); - data += add; - } - else { - memcpy((unsigned char*)&local[desc->shaIdx], - (unsigned char*)data + (blocks * align), add); - } - dataSz -= add; - desc->shaIdx += add; - } - - if (desc->shaIdx == align) { - desc->lastFifo = desc->idx; - if (desc->idx + 2 > MAX_DESC_SZ) { - return -1; - } - desc->desc[desc->idx++] = options + desc->shaIdx; - desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->shaBuf); - ASP_FlushCaches((Address)desc->shaBuf, desc->shaIdx); - outSz += desc->shaIdx; - } - - 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->shaIdx == align) { - desc->shaIdx = 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 - ****************************************************************************/ - -/* AES operations follow the buffer sequence of KEY -> (IV or B0 | CTR0) -> - * Input -> Output -> (AD) - */ -static Error caamAes(struct DescStruct* desc) -{ - Value ofst = 0; - Error err; - struct buffer* ctx[3]; - struct buffer* iv[3]; - int ctxIdx = 0; - int ivIdx = 0; - int offset = 0; - int align = 1; - int sz = 0; - UINT4 i; - - 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[i]->data, - ctx[i]->dataSz); - offset += ctx[i]->dataSz; - } - 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 offest changes */ - - case CAAM_AESCBC: - case CAAM_AESCCM: - { - int maxSz = 16; /* default to CBC/CTR max size */ - - if (desc->type == CAAM_AESCCM) { - maxSz = 32; /* size of B0 | CTR0 for CCM mode */ - } - - 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_INITF | desc->state; - - /* load input and set flush of FIFO input */ - caamAddIO(desc, (CAAM_FIFO_L | CAAM_CLASS1 | FIFOL_TYPE_MSG), - desc->inputSz, align, &i); - - /* handle output buffers */ - desc->outputIdx = i; - sz = 0; - for (; i < desc->DescriptorCount; i++) { - struct buffer* buf = &desc->buf[i]; - if (sz < desc->inputSz) { - if (desc->idx + 2 > MAX_DESC_SZ) { - return TransferFailed; - } - desc->desc[desc->idx++] = CAAM_FIFO_S | FIFOS_TYPE_MSG + - buf->dataSz; - desc->desc[desc->idx++] = BSP_VirtualToPhysical(buf->data); - sz += buf->dataSz; - } - else { - break; - } - } - desc->lastIdx = i; - - /* if is CCM mode handle AAD */ - if (desc->type == CAAM_AESCCM && 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 | FIFOL_TYPE_AAD + - buf->dataSz; - desc->desc[desc->idx++] = BSP_VirtualToPhysical(buf->data); - sz += buf->dataSz; - } - else { - break; - } - } - } - desc->desc[desc->lastFifo] |= FIFOL_TYPE_LC1; - - /* 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; - } - - /* flush output buffers */ - sz = 0; - 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, 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 SHA Operations - ****************************************************************************/ -static int shaSize(struct DescStruct* desc) -{ - /* sanity check on dataSz for context */ - switch (desc->type) { - case CAAM_HMAC_MD5: - case CAAM_MD5: - return CAAM_MD5_CTXSZ; - - case CAAM_HMAC_SHA: - case CAAM_SHA: - return CAAM_SHA_CTXSZ; - - case CAAM_HMAC_SHA224: - case CAAM_SHA224: - return CAAM_SHA224_CTXSZ; - - case CAAM_HMAC_SHA256: - case CAAM_SHA256: - return CAAM_SHA256_CTXSZ; - - case CAAM_HMAC_SHA384: - case CAAM_SHA384: - return CAAM_SHA384_CTXSZ; - - case CAAM_HMAC_SHA512: - 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; - int sz = 0; - int ctxIdx = 0; - int offset = 0; - UINT4 i; - - 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) { - /* dont 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 */ - { - int j; - unsigned char* pt = (unsigned char*)desc->iv; - for (j = 0; j < ctxIdx; j++) { - memcpy((unsigned char*)ctx[j]->data, pt, ctx[j]->dataSz); - pt += ctx[j]->dataSz; - ASP_FlushCaches(ctx[j]->data, ctx[j]->dataSz); - } - } - - return Success; -} - - -/****************************************************************************** - CAAM HMAC Operations - ****************************************************************************/ - -/* Warning currently can only handle a single call not multiple updates and - * finalize. - * - * The only thing HMAC has in addtition to regular SHA/MD5 operations is that - * there is a key loaded in. This gets the key buffers than calls the pre - * existing SHA/MD5 function. - * - * NOTE: It is expected that the key is smaller than the algorithms digest size - * - */ -static Error caamHmac(struct DescStruct* desc) -{ - int maxSz = (MAX_CTX * sizeof(UINT4)); - int keySz = desc->ctxSz; /* from user args[1] */ - struct buffer* ctx[2]; - int offset = 0; - int sz = 0; - int ctxIdx = 0; - int i; - - int ctxSz = shaSize(desc); - - /* get key */ - for (i = 0; i < desc->DescriptorCount; i++) { - struct buffer* buf = &desc->buf[i]; - unsigned char* local = (unsigned char*)desc->ctxBuf; - - if (sz < keySz) { - ctx[ctxIdx++] = buf; - sz += buf->dataSz; - - if (sz >= maxSz) { - return SizeIsTooLarge; - } - memcpy((unsigned char*)&local[offset], (unsigned char*)ctx[i]->data, - ctx[i]->dataSz); - offset += ctx[i]->dataSz; - desc->outputIdx = i; - } - else { - break; - } - } - if (sz > maxSz) { - return SizeIsTooLarge; - } - - /* Add Key command and flush its buffer - * Add KEY Load command 0x0240000X - * Add address to read key from 0xXXXXXXXX */ - ASP_FlushCaches((Address)desc->ctxBuf, sz); - desc->desc[desc->idx++] = (CAAM_KEY | CAAM_CLASS2) + sz; - desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->ctxBuf); - - /* since calling SHA fuction "as is" the descriptor count needs to be set*/ - return caamSha(desc, i); -} - - -/****************************************************************************** - 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 DescStruct* desc; - struct CAAM_DEVICE* local = (struct CAAM_DEVICE*)ioCaam; - - /* 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->shaIdx = 0; - desc->lastFifo = 0; - desc->state = args[0]; - desc->ctxSz = args[1]; - desc->inputSz = args[2]; - desc->aadSz = args[3]; - desc->desc[desc->idx++] = CAAM_HEAD; /* later will put size to header*/ - - switch (type) { - case CAAM_AESECB: - case CAAM_AESCBC: - case CAAM_AESCTR: - case CAAM_AESCCM: - break; - - case CAAM_MD5: - case CAAM_SHA: - case CAAM_SHA224: - case CAAM_SHA256: - case CAAM_SHA384: - case CAAM_SHA512: - break; - - case CAAM_HMAC_MD5: - case CAAM_HMAC_SHA: - case CAAM_HMAC_SHA224: - case CAAM_HMAC_SHA256: - case CAAM_HMAC_SHA384: - case CAAM_HMAC_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) -{ - Error err; - struct DescStruct* desc = (struct DescStruct*)req; - - 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_HMAC_MD5: - case CAAM_HMAC_SHA: - case CAAM_HMAC_SHA224: - case CAAM_HMAC_SHA256: - case CAAM_HMAC_SHA384: - case CAAM_HMAC_SHA512: - - case CAAM_BLOB_ENCAP: - case CAAM_BLOB_DECAP: - case CAAM_ENTROPY: - { /* set buffer for transfer finish */ - struct buffer* 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: - case CAAM_AESCCM: - ret = caamAes(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_HMAC_MD5: - case CAAM_HMAC_SHA: - case CAAM_HMAC_SHA224: - case CAAM_HMAC_SHA256: - case CAAM_HMAC_SHA384: - case CAAM_HMAC_SHA512: - ret = caamHmac(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 decriptors 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 interupt 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 partion 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; +/* caam_driver.c + * + * Copyright (C) 2006-2016 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 +#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 shaBuf[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 shaIdx; /* index for descriptor 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 interupts 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 prgress */ + 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 permisions, 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 inquery 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 unavialbale */ + } + } + 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 inquery 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 avialable 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 avialable 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->output != 0) { /* for testing */ + // memcpy((char*)desc->output, msg, sizeof(msg)); + //} + if (desc->ctxOut != 0) { /* for testing */ + memcpy((char*)desc->ctxOut, 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 potental overlap */ + int tmpSz = dataSz % align; + int add = (tmpSz < (align - desc->shaIdx)) ? tmpSz : + align - desc->shaIdx; + unsigned char* local = (unsigned char*)desc->shaBuf; + + /* if already something in the buffer then add from front */ + if (desc->shaIdx > 0) { + memcpy((unsigned char*)&local[desc->shaIdx], + (unsigned char*)data, add); + data += add; + } + else { + memcpy((unsigned char*)&local[desc->shaIdx], + (unsigned char*)data + (blocks * align), add); + } + dataSz -= add; + desc->shaIdx += add; + } + + if (desc->shaIdx == align) { + desc->lastFifo = desc->idx; + if (desc->idx + 2 > MAX_DESC_SZ) { + return -1; + } + desc->desc[desc->idx++] = options + desc->shaIdx; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->shaBuf); + ASP_FlushCaches((Address)desc->shaBuf, desc->shaIdx); + outSz += desc->shaIdx; + } + + 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->shaIdx == align) { + desc->shaIdx = 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 + ****************************************************************************/ + +/* AES operations follow the buffer sequence of KEY -> (IV or B0 | CTR0) -> (AD) + * -> Input -> Output + */ +static Error caamAes(struct DescStruct* desc) +{ + struct buffer* ctx[3]; + struct buffer* iv[3]; + Value ofst = 0; + Error err; + UINT4 i; + 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 offest 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 */ + sz = 0; + for (desc->outputIdx = i; desc->outputIdx < desc->DescriptorCount && + sz < desc->inputSz; desc->outputIdx++) { + sz += desc->buf[desc->outputIdx].dataSz; + } + + + /* indefinit loop for AES operations */ + desc->lastIdx = desc->outputIdx; + 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 (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + sz = desc->buf[i].dataSz; + 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++; + + /* handle output buffers */ + if (desc->output != 0 && offset > 0 && sz > 0) { + /* handle potential leftovers */ + sz -= offset; + desc->desc[desc->idx++] = CAAM_FIFO_S | FIFOS_TYPE_MSG + offset; + if (sz > 0) { /* check if expecting more output */ + desc->desc[desc->idx - 1] |= CAAM_FIFOS_CONT; + } + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->output); + + /* reset */ + desc->output = 0; + offset = 0; + } + + for (; desc->lastIdx < desc->DescriptorCount; desc->lastIdx++) { + struct buffer* buf = &desc->buf[desc->lastIdx]; + + if (sz > 0) { + int tmp; + + if (buf->dataSz <= sz) { + tmp = buf->dataSz; + } + else { + offset = buf->dataSz - sz; + tmp = sz; + desc->output = buf->data + tmp; + } + + sz -= tmp; + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = CAAM_FIFO_S | FIFOS_TYPE_MSG + tmp; + if (sz > 0) { /* check if expecting more output */ + desc->desc[desc->idx - 1] |= CAAM_FIFOS_CONT; + } + desc->desc[desc->idx++] = BSP_VirtualToPhysical(buf->data); + } + else { + break; + } + } + + /* 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); + + /* 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 unformated 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 */ + 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; + } + + /* handle alignment constraints on input */ + if (desc->shaIdx > 0) { + sz = desc->shaIdx; + + /* if there is more input buffers then add part of it */ + if (i < desc->outputIdx && i < desc->DescriptorCount) { + sz = align - desc->shaIdx; + sz = (sz <= desc->buf[i].dataSz) ? sz : desc->buf[i].dataSz; + memcpy((unsigned char*)(desc->shaBuf) + desc->shaIdx, + (unsigned char*)(desc->buf[i].data), sz); + + desc->buf[i].dataSz -= sz; + desc->buf[i].data += sz; + sz += desc->shaIdx; + } + + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + ASP_FlushCaches((Address)desc->shaBuf, sz); + desc->desc[desc->idx++] = (CAAM_FIFO_L | FIFOL_TYPE_LC1 | + CAAM_CLASS1 | FIFOL_TYPE_MSG) + sz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->shaBuf); + desc->shaIdx = 0; + } + else { + sz = desc->buf[i].dataSz; + totalSz += sz; + if (totalSz == desc->inputSz) { /* not an issue on final */ + align = 1; + } + + desc->shaIdx = sz % align; + if (desc->shaIdx != 0) { + sz -= desc->shaIdx; + memcpy((unsigned char*)desc->shaBuf, + (unsigned char*)(desc->buf[i].data) + sz, + desc->shaIdx); + } + + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + 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++; + } + + /************** handle output buffers *******************************/ + if (desc->output != 0 && offset > 0 && sz > 0) { + UINT4 addSz; + + /* handle potential leftovers */ + addSz = (sz >= offset) ? offset : sz; + + sz -= addSz; + desc->desc[desc->idx++] = CAAM_FIFO_S | FIFOS_TYPE_MSG + addSz; + if (sz > 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 Failure; + } + } + } + + for (; desc->lastIdx < desc->DescriptorCount; desc->lastIdx++) { + struct buffer* buf = &desc->buf[desc->lastIdx]; + + if (sz > 0) { + int tmp; + + if (buf->dataSz <= sz) { + tmp = buf->dataSz; + } + else { + offset = buf->dataSz - sz; + tmp = sz; + desc->output = buf->data + tmp; + } + + sz -= tmp; + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = CAAM_FIFO_S | FIFOS_TYPE_MSG + tmp; + if (sz > 0) { /* check if expecting more output */ + desc->desc[desc->idx - 1] |= CAAM_FIFOS_CONT; + } + desc->desc[desc->idx++] = BSP_VirtualToPhysical(buf->data); + } + else { + break; + } + } + + /* 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_HMAC_MD5: + case CAAM_MD5: + return CAAM_MD5_CTXSZ; + + case CAAM_HMAC_SHA: + case CAAM_SHA: + return CAAM_SHA_CTXSZ; + + case CAAM_HMAC_SHA224: + case CAAM_SHA224: + return CAAM_SHA224_CTXSZ; + + case CAAM_HMAC_SHA256: + case CAAM_SHA256: + return CAAM_SHA256_CTXSZ; + + case CAAM_HMAC_SHA384: + case CAAM_SHA384: + return CAAM_SHA384_CTXSZ; + + case CAAM_HMAC_SHA512: + 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) { + /* dont 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 HMAC Operations + ****************************************************************************/ + +/* Warning currently can only handle a single call not multiple updates and + * finalize. + * + * The only thing HMAC has in addtition to regular SHA/MD5 operations is that + * there is a key loaded in. This gets the key buffers than calls the pre + * existing SHA/MD5 function. + * + * NOTE: It is expected that the key is smaller than the algorithms digest size + * + */ +static Error caamHmac(struct DescStruct* desc) +{ + int maxSz = (MAX_CTX * sizeof(UINT4)); + int keySz = desc->ctxSz; /* from user args[1] */ + struct buffer* ctx[2]; + int offset = 0; + int sz = 0; + int ctxIdx = 0; + int i; + + int ctxSz = shaSize(desc); + + /* get key */ + for (i = 0; i < desc->DescriptorCount; i++) { + struct buffer* buf = &desc->buf[i]; + unsigned char* local = (unsigned char*)desc->ctxBuf; + + if (sz < keySz) { + ctx[ctxIdx++] = buf; + sz += buf->dataSz; + + if (sz >= maxSz) { + return SizeIsTooLarge; + } + memcpy((unsigned char*)&local[offset], (unsigned char*)ctx[i]->data, + ctx[i]->dataSz); + offset += ctx[i]->dataSz; + desc->outputIdx = i; + } + else { + break; + } + } + if (sz > maxSz) { + return SizeIsTooLarge; + } + + /* Add Key command and flush its buffer + * Add KEY Load command 0x0240000X + * Add address to read key from 0xXXXXXXXX */ + ASP_FlushCaches((Address)desc->ctxBuf, sz); + desc->desc[desc->idx++] = (CAAM_KEY | CAAM_CLASS2) + sz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->ctxBuf); + + /* since calling SHA fuction "as is" the descriptor count needs to be set*/ + return caamSha(desc, i); +} + + +/****************************************************************************** + 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->shaIdx = 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: + 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_HMAC_MD5: + case CAAM_HMAC_SHA: + case CAAM_HMAC_SHA224: + case CAAM_HMAC_SHA256: + case CAAM_HMAC_SHA384: + case CAAM_HMAC_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_HMAC_MD5: + case CAAM_HMAC_SHA: + case CAAM_HMAC_SHA224: + case CAAM_HMAC_SHA256: + case CAAM_HMAC_SHA384: + case CAAM_HMAC_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_HMAC_MD5: + case CAAM_HMAC_SHA: + case CAAM_HMAC_SHA224: + case CAAM_HMAC_SHA256: + case CAAM_HMAC_SHA384: + case CAAM_HMAC_SHA512: + ret = caamHmac(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 decriptors 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 interupt 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 partion 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; diff --git a/wolfcrypt/src/port/caam/caam_init.c b/wolfcrypt/src/port/caam/caam_init.c index 69c926d0d..2fe749280 100644 --- a/wolfcrypt/src/port/caam/caam_init.c +++ b/wolfcrypt/src/port/caam/caam_init.c @@ -86,14 +86,17 @@ int wc_caamSetResource(IODevice ioDev) */ int wc_caamInit() { + int ret; word32 reg; /* get the driver up */ if (caam == NULLIODevice) { WOLFSSL_MSG("Starting CAAM driver"); - if (RequestResource((Object *)&caam, "wolfSSL_CAAM_Driver", - WC_CAAM_PASSWORD) != Success) { + 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 */ } } @@ -135,6 +138,7 @@ int wc_caamInit() } #endif + (void)ret; return 0; } @@ -174,6 +178,8 @@ void wc_caamWriteRegister(word32 reg, word32 value) } +/* return 0 on success and WC_CAAM_E on failure. Can also return WC_CAAM_WAIT + * in the case that the driver is waiting for a resource. */ int wc_caamAddAndWait(Buffer* buf, word32 arg[4], word32 type) { int ret; @@ -187,6 +193,13 @@ int wc_caamAddAndWait(Buffer* buf, word32 arg[4], word32 type) #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 CAAM driver"); + return WC_CAAM_WAIT; + } + return WC_CAAM_E; } diff --git a/wolfcrypt/src/port/caam/caam_sha.c b/wolfcrypt/src/port/caam/caam_sha.c index 044a4d37f..b92530d4d 100644 --- a/wolfcrypt/src/port/caam/caam_sha.c +++ b/wolfcrypt/src/port/caam/caam_sha.c @@ -63,7 +63,7 @@ Common Code Between SHA Functions ****************************************************************************/ -static int _InitSha(Sha* sha, void* heap, int devId, word32 digestSz, +static int _InitSha(wc_Sha* sha, void* heap, int devId, word32 digestSz, word32 type) { Buffer buf[1]; @@ -97,7 +97,7 @@ static int _InitSha(Sha* sha, void* heap, int devId, word32 digestSz, } -static int _ShaUpdate(Sha* sha, const byte* data, word32 len, word32 digestSz, +static int _ShaUpdate(wc_Sha* sha, const byte* data, word32 len, word32 digestSz, word32 type) { Buffer buf[2]; @@ -185,7 +185,7 @@ static int _ShaUpdate(Sha* sha, const byte* data, word32 len, word32 digestSz, } -static int _ShaFinal(Sha* sha, byte* out, word32 digestSz, +static int _ShaFinal(wc_Sha* sha, byte* out, word32 digestSz, word32 type) { Buffer buf[2]; @@ -322,7 +322,7 @@ int wc_Sha256Update(wc_Sha256* sha, const byte* data, word32 len) } -int wc_Sha256Final(wc-Sha256* sha, byte* out) +int wc_Sha256Final(wc_Sha256* sha, byte* out) { int ret; if ((ret = _ShaFinal(sha, out, SHA256_DIGEST_SIZE, CAAM_SHA256)) != 0) { diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 4e74e84b1..c27e19e98 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -1655,7 +1655,9 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) if (ret == Success) { break; } - if (ret != Waiting) { + + /* driver could be waiting for entropy */ + if (ret != WC_CAAM_WAIT) { return ret; } sleep(1); diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index af4954ea8..ef98d8728 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -192,8 +192,9 @@ enum { ECC_PRIVATEONLY_E = -246, /* Invalid use of private only ECC key*/ EXTKEYUSAGE_E = -247, /* Bad Extended Key Usage value */ WC_CAAM_E = -248, /* Error with CAAM use */ + WC_CAAM_WAIT = -249, /* CAAM Driver waiting on resource */ - WC_LAST_E = -248, /* 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 diff --git a/wolfssl/wolfcrypt/port/caam/caam_driver.h b/wolfssl/wolfcrypt/port/caam/caam_driver.h index a9930a358..8091778a7 100644 --- a/wolfssl/wolfcrypt/port/caam/caam_driver.h +++ b/wolfssl/wolfcrypt/port/caam/caam_driver.h @@ -1,184 +1,187 @@ -/* caam_driver.h - * - * Copyright (C) 2006-2016 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 0x0000000D/* init and finalize with enc */ -#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_LC1 0x00020000 -#define FIFOL_TYPE_LC2 0x00040000 - -#define FIFOS_TYPE_MSG 0x00300000 - -#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 */ +/* caam_driver.h + * + * Copyright (C) 2006-2016 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 */ diff --git a/wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h b/wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h index 34f274cfe..51c9a1942 100644 --- a/wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h +++ b/wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h @@ -63,22 +63,22 @@ #endif /* WC_CAAM_MAX_DIGEST */ -typedef struct Sha { +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)]; -} Sha; +} wc_Sha; #ifndef NO_MD5 - typedef struct Sha wc_Md5; + typedef struct wc_Sha wc_Md5; #endif #ifndef NO_SHA256 - typedef struct Sha wc_Sha256; + typedef struct wc_Sha wc_Sha256; #endif #ifdef WOLFSSL_SHA512 - typedef struct Sha wc_Sha512; + typedef struct wc_Sha wc_Sha512; #endif #endif /* WOLFSSL_IMX6_CAAM */