From 5fa9455bf9fbaa27c4331b07fb0dc257f712dc09 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Thu, 14 Dec 2017 11:46:20 -0700 Subject: [PATCH] add CAAM with INTEGRITY support --- src/internal.c | 4 +- src/wolfio.c | 12 +- wolfcrypt/src/aes.c | 81 +- wolfcrypt/src/error.c | 3 + wolfcrypt/src/hmac.c | 2 + wolfcrypt/src/md5.c | 3 + wolfcrypt/src/port/caam/caam_aes.c | 709 ++++++++++ wolfcrypt/src/port/caam/caam_driver.c | 1382 ++++++++++++++++++++ wolfcrypt/src/port/caam/caam_init.c | 269 ++++ wolfcrypt/src/port/caam/caam_sha.c | 397 ++++++ wolfcrypt/src/random.c | 43 + wolfcrypt/src/sha.c | 2 + wolfcrypt/src/sha256.c | 24 +- wolfcrypt/src/sha512.c | 12 +- wolfcrypt/src/wc_port.c | 17 + wolfcrypt/test/test.c | 92 ++ wolfssl/test.h | 9 +- wolfssl/wolfcrypt/error-crypt.h | 3 +- wolfssl/wolfcrypt/include.am | 5 +- wolfssl/wolfcrypt/md5.h | 2 + wolfssl/wolfcrypt/port/caam/caam_driver.h | 184 +++ wolfssl/wolfcrypt/port/caam/wolfcaam.h | 70 + wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h | 86 ++ wolfssl/wolfcrypt/settings.h | 6 + wolfssl/wolfcrypt/sha.h | 10 +- wolfssl/wolfcrypt/sha256.h | 9 +- wolfssl/wolfcrypt/sha512.h | 4 + wolfssl/wolfcrypt/types.h | 1 + 28 files changed, 3411 insertions(+), 30 deletions(-) create mode 100644 wolfcrypt/src/port/caam/caam_aes.c create mode 100644 wolfcrypt/src/port/caam/caam_driver.c create mode 100644 wolfcrypt/src/port/caam/caam_init.c create mode 100644 wolfcrypt/src/port/caam/caam_sha.c create mode 100644 wolfssl/wolfcrypt/port/caam/caam_driver.h create mode 100644 wolfssl/wolfcrypt/port/caam/wolfcaam.h create mode 100644 wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h diff --git a/src/internal.c b/src/internal.c index d76ace244f..ee83663f2a 100644 --- a/src/internal.c +++ b/src/internal.c @@ -6078,7 +6078,7 @@ static void AddFragHeaders(byte* output, word32 fragSz, word32 fragOffset, /* return bytes received, -1 on error */ -static int Receive(WOLFSSL* ssl, byte* buf, word32 sz) +static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz) { int recvd; @@ -11607,7 +11607,7 @@ static int GetInputData(WOLFSSL *ssl, word32 size) /* read data from network */ do { - in = Receive(ssl, + in = wolfSSLReceive(ssl, ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.length, inSz); diff --git a/src/wolfio.c b/src/wolfio.c index fca3f557c7..52a9b0076e 100644 --- a/src/wolfio.c +++ b/src/wolfio.c @@ -88,7 +88,7 @@ static INLINE int TranslateReturnCode(int old, int sd) return old; } -static INLINE int LastError(void) +static INLINE int wolfSSL_LastError(void) { #ifdef USE_WINDOWS_API return WSAGetLastError(); @@ -135,7 +135,7 @@ int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx) recvd = wolfIO_Recv(sd, buf, sz, ssl->rflags); if (recvd < 0) { - int err = LastError(); + int err = wolfSSL_LastError(); WOLFSSL_MSG("Embed Receive error"); if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { @@ -187,7 +187,7 @@ int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx) sent = wolfIO_Send(sd, buf, sz, ssl->wflags); if (sent < 0) { - int err = LastError(); + int err = wolfSSL_LastError(); WOLFSSL_MSG("Embed Send error"); if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { @@ -262,7 +262,7 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) recvd = TranslateReturnCode(recvd, sd); if (recvd < 0) { - err = LastError(); + err = wolfSSL_LastError(); WOLFSSL_MSG("Embed Receive From error"); if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { @@ -325,7 +325,7 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) sent = TranslateReturnCode(sent, sd); if (sent < 0) { - err = LastError(); + err = wolfSSL_LastError(); WOLFSSL_MSG("Embed Send To error"); if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { @@ -373,7 +373,7 @@ int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx) recvd = TranslateReturnCode(recvd, sd); if (recvd < 0) { - err = LastError(); + err = wolfSSL_LastError(); WOLFSSL_MSG("Embed Receive From error"); if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 9acbaa54fe..f008843a62 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -243,7 +243,11 @@ #include #endif -#ifndef WOLFSSL_ARMASM +#if !defined(WOLFSSL_ARMASM) && !defined(WOLFSSL_IMX6_CAAM) + +#ifdef WOLFSSL_IMX6_CAAM_BLOB + #include +#endif #ifdef DEBUG_AESNI #include @@ -2131,10 +2135,27 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, int dir) { + int ret; #if defined(AES_MAX_KEY_SIZE) const word32 max_key_len = (AES_MAX_KEY_SIZE / 8); #endif + #ifdef WOLFSSL_IMX6_CAAM_BLOB + byte local[32]; + word32 localSz = 32; + + if (keylen == (16 + WC_CAAM_BLOB_SZ) || + keylen == (24 + WC_CAAM_BLOB_SZ) || + keylen == (32 + WC_CAAM_BLOB_SZ)) { + if (wc_caamOpenBlob((byte*)userKey, keylen, local, &localSz) != 0) { + return BAD_FUNC_ARG; + } + + /* set local values */ + userKey = local; + keylen = localSz; + } + #endif if (aes == NULL || !((keylen == 16) || (keylen == 24) || (keylen == 32))) { return BAD_FUNC_ARG; @@ -2178,7 +2199,12 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) } #endif /* WOLFSSL_AESNI */ - return wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir); + ret = wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir); + + #ifdef WOLFSSL_IMX6_CAAM_BLOB + ForceZero(local, sizeof(local)); + #endif + return ret; } #if defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER) @@ -2186,7 +2212,32 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, int dir) { - return wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir); + int ret; + + #ifdef WOLFSSL_IMX6_CAAM_BLOB + byte local[32]; + word32 localSz = 32; + + if (keylen == (16 + WC_CAAM_BLOB_SZ) || + keylen == (24 + WC_CAAM_BLOB_SZ) || + keylen == (32 + WC_CAAM_BLOB_SZ)) { + if (wc_caamOpenBlob((byte*)userKey, keylen, local, &localSz) + != 0) { + return BAD_FUNC_ARG; + } + + /* set local values */ + userKey = local; + keylen = localSz; + } + #endif + ret = wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir); + + #ifdef WOLFSSL_IMX6_CAAM_BLOB + ForceZero(local, sizeof(local)); + #endif + + return ret; } #endif /* WOLFSSL_AES_DIRECT || WOLFSSL_AES_COUNTER */ #endif /* wc_AesSetKey block */ @@ -3377,6 +3428,23 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) int ret; byte iv[AES_BLOCK_SIZE]; + #ifdef WOLFSSL_IMX6_CAAM_BLOB + byte local[32]; + word32 localSz = 32; + + if (keylen == (16 + WC_CAAM_BLOB_SZ) || + keylen == (24 + WC_CAAM_BLOB_SZ) || + keylen == (32 + WC_CAAM_BLOB_SZ)) { + if (wc_caamOpenBlob((byte*)userKey, keylen, local, &localSz) != 0) { + return BAD_FUNC_ARG; + } + + /* set local values */ + key = local; + len = localSz; + } + #endif + if (!((len == 16) || (len == 24) || (len == 32))) return BAD_FUNC_ARG; @@ -3402,6 +3470,10 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) wc_AesGcmSetKey_ex(aes, key, len, XSECURE_CSU_AES_KEY_SRC_KUP); #endif +#ifdef WOLFSSL_IMX6_CAAM_BLOB + ForceZero(local, sizeof(local)); +#endif + return ret; } @@ -7192,6 +7264,9 @@ int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) #if defined(HAVE_COLDFIRE_SEC) #error "Coldfire SEC doesn't currently support AES-CCM mode" +#elif defined(WOLFSSL_IMX6_CAAM) + /* implemented in wolfcrypt/src/port/caam_aes.c */ + #elif defined(FREESCALE_LTC) /* return 0 on success */ diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index 83e9e3f9d8..9c87f11118 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -434,6 +434,9 @@ const char* wc_GetErrorString(int error) case ECC_PRIVATEONLY_E: return "Invalid use of private only ECC key"; + case WC_CAAM_E: + return "Error with CAAM use"; + default: return "unknown error number"; diff --git a/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c index e7fa2a612b..704cc977f5 100644 --- a/wolfcrypt/src/hmac.c +++ b/wolfcrypt/src/hmac.c @@ -166,6 +166,8 @@ int wc_HmacSizeByType(int type) return ret; } + +/* software implementation */ static int _InitHmac(Hmac* hmac, int type, void* heap) { int ret = 0; diff --git a/wolfcrypt/src/md5.c b/wolfcrypt/src/md5.c index e9f041c7ba..3097c53371 100644 --- a/wolfcrypt/src/md5.c +++ b/wolfcrypt/src/md5.c @@ -225,6 +225,9 @@ static INLINE void AddLength(wc_Md5* md5, word32 len); #include #define HAVE_MD5_CUST_API +#elif defined(WOLFSSL_IMX6_CAAM) + /* functions implemented in wolfcrypt/src/port/caam/caam_sha.c */ + #define HAVE_MD5_CUST_API #else #define NEED_SOFT_MD5 diff --git a/wolfcrypt/src/port/caam/caam_aes.c b/wolfcrypt/src/port/caam/caam_aes.c new file mode 100644 index 0000000000..f404f80efa --- /dev/null +++ b/wolfcrypt/src/port/caam/caam_aes.c @@ -0,0 +1,709 @@ +/* caam_aes.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 + */ + + +#include + +#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_AES) + +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#include +#include + +#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) +#include +#endif + +int wc_AesSetKey(Aes* aes, const byte* key, word32 len, + const byte* iv, int dir) +{ + int ret; + + if (aes == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + if (len > 32) { + byte out[32]; /* max AES key size */ + word32 outSz; + int ret; + + if (len != 64 && len != 72 && len != 80) { + return BAD_FUNC_ARG; + } + + outSz = sizeof(out); + /* if length greater then 32 then try to unencapsulate */ + if ((ret = wc_caamOpenBlob((byte*)key, len, out, &outSz, NULL, 0)) != 0) { + return ret; + } + + XMEMCPY((byte*)aes->key, out, outSz); + aes->keylen = outSz; + } + else { + if (len != 16 && len != 24 && len != 32) { + return BAD_FUNC_ARG; + } + + XMEMCPY((byte*)aes->key, key, len); + aes->keylen = len; + } + + + switch (aes->keylen) { + case 16: aes->rounds = 10; break; + case 24: aes->rounds = 12; break; + case 32: aes->rounds = 14; break; + default: + return BAD_FUNC_ARG; + } + + if ((ret = wc_AesSetIV(aes, iv)) != 0) { + return ret; + } + +#ifdef WOLFSSL_AES_COUNTER + aes->left = 0; +#endif + + return 0; +} + + +int wc_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]; + word32 keySz; + int ret; + + if (wc_AesGetKeySize(aes, &keySz) != 0) { + return BAD_FUNC_ARG; + } + + /* Set buffers for key, cipher text, and plain text */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)aes->key; + buf[0].Length = keySz; + + buf[1].BufferType = DataBuffer; + buf[1].TheAddress = (Address)aes->reg; + buf[1].Length = AES_BLOCK_SIZE; + + buf[2].BufferType = DataBuffer; + buf[2].TheAddress = (Address)in; + buf[2].Length = blocks * AES_BLOCK_SIZE; + + buf[3].BufferType = DataBuffer | LastBuffer; + buf[3].TheAddress = (Address)out; + buf[3].Length = blocks * AES_BLOCK_SIZE; + + arg[0] = CAAM_ENC; + arg[1] = keySz; + arg[2] = sz; + + if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCBC)) != 0) { + WOLFSSL_MSG("Error with CAAM AES CBC encrypt"); + return ret; + } + } + + return 0; +} + + +int wc_AesCbcDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz) +{ + word32 blocks; + + WOLFSSL_ENTER("wc_AesCbcDecrypt"); + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + blocks = sz / AES_BLOCK_SIZE; + + if (blocks > 0) { + Buffer buf[4]; + word32 arg[4]; + word32 keySz; + int ret; + + if (wc_AesGetKeySize(aes, &keySz) != 0) { + return BAD_FUNC_ARG; + } + + /* Set buffers for key, cipher text, and plain text */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)aes->key; + buf[0].Length = keySz; + + buf[1].BufferType = DataBuffer; + buf[1].TheAddress = (Address)aes->reg; + buf[1].Length = AES_BLOCK_SIZE; + + buf[2].BufferType = DataBuffer; + buf[2].TheAddress = (Address)in; + buf[2].Length = blocks * AES_BLOCK_SIZE; + + buf[3].BufferType = DataBuffer | LastBuffer; + buf[3].TheAddress = (Address)out; + buf[3].Length = blocks * AES_BLOCK_SIZE; + + arg[0] = CAAM_DEC; + arg[1] = keySz; + arg[2] = sz; + + if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCBC)) != 0) { + WOLFSSL_MSG("Error with CAAM AES CBC decrypt"); + return ret; + } + } + + return 0; +} + +#ifdef HAVE_AES_ECB +/* is assumed that input size is a multiple of AES_BLOCK_SIZE */ +int wc_AesEcbEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz) +{ + word32 blocks; + + 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; + } + + return 0; +} + + +int wc_AesEcbDecrypt(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; + + /* @TODO search for more efficient solution */ + while (blocks > 0) { + wc_AesDecryptDirect(aes, out, in); + blocks--; + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + } + + return 0; +} +#endif + +/* AES-CTR */ +#ifdef WOLFSSL_AES_COUNTER +/* Increment AES counter (from wolfcrypt/src/aes.c) */ +static INLINE void IncrementAesCounter(byte* inOutCtr) +{ + /* in network byte order so start at end and work back */ + int i; + for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { + if (++inOutCtr[i]) /* we're done unless we overflow */ + return; + } +} + + +int wc_AesCtrEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz) +{ + byte* tmp; + Buffer buf[4]; + word32 arg[4]; + word32 keySz; + int ret, blocks; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + if (wc_AesGetKeySize(aes, &keySz) != 0) { + return BAD_FUNC_ARG; + } + + /* consume any unused bytes left in aes->tmp */ + tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; + while (aes->left && sz) { + *(out++) = *(in++) ^ *(tmp++); + aes->left--; + sz--; + } + + /* do full blocks to then get potential left over amount */ + blocks = sz / AES_BLOCK_SIZE; + if (blocks > 0) { + /* Set buffers for key, cipher text, and plain text */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)aes->key; + buf[0].Length = keySz; + + buf[1].BufferType = DataBuffer; + buf[1].TheAddress = (Address)aes->reg; + buf[1].Length = AES_BLOCK_SIZE; + + buf[2].BufferType = DataBuffer; + buf[2].TheAddress = (Address)in; + buf[2].Length = blocks * AES_BLOCK_SIZE; + + buf[3].BufferType = DataBuffer | LastBuffer; + buf[3].TheAddress = (Address)out; + buf[3].Length = blocks * AES_BLOCK_SIZE; + + arg[0] = CAAM_ENC; + arg[1] = keySz; + arg[2] = 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) { + wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg); + IncrementAesCounter((byte*)aes->reg); + + aes->left = AES_BLOCK_SIZE; + tmp = (byte*)aes->tmp; + + while (sz--) { + *(out++) = *(in++) ^ *(tmp++); + aes->left--; + } + } + + return 0; +} +#endif + + +/* AES-DIRECT */ +#if defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER) +void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) +{ + Buffer buf[3]; + word32 arg[4]; + word32 keySz; + + if (aes == NULL || out == NULL || in == NULL) { + //return BAD_FUNC_ARG; + return; + } + + if (wc_AesGetKeySize(aes, &keySz) != 0) { + //return BAD_FUNC_ARG; + return; + } + + /* Set buffers for key, cipher text, and plain text */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)aes->key; + buf[0].Length = keySz; + + buf[1].BufferType = DataBuffer; + buf[1].TheAddress = (Address)in; + buf[1].Length = AES_BLOCK_SIZE; + + buf[2].BufferType = DataBuffer | LastBuffer; + buf[2].TheAddress = (Address)out; + buf[2].Length = AES_BLOCK_SIZE; + + arg[0] = CAAM_ENC; + arg[1] = keySz; + arg[2] = AES_BLOCK_SIZE; + + if (wc_caamAddAndWait(buf, arg, CAAM_AESECB) != 0) { + WOLFSSL_MSG("Error with CAAM AES direct encrypt"); + } +} + + +void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) +{ + Buffer buf[3]; + word32 arg[4]; + word32 keySz; + + if (aes == NULL || out == NULL || in == NULL) { + //return BAD_FUNC_ARG; + return; + } + + if (wc_AesGetKeySize(aes, &keySz) != 0) { + //return BAD_FUNC_ARG; + return; + } + + /* Set buffers for key, cipher text, and plain text */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)aes->key; + buf[0].Length = keySz; + + buf[1].BufferType = DataBuffer; + buf[1].TheAddress = (Address)in; + buf[1].Length = AES_BLOCK_SIZE; + + buf[2].BufferType = DataBuffer | LastBuffer; + buf[2].TheAddress = (Address)out; + buf[2].Length = AES_BLOCK_SIZE; + + arg[0] = CAAM_DEC; + arg[1] = keySz; + arg[2] = AES_BLOCK_SIZE; + + if (wc_caamAddAndWait(buf, arg, CAAM_AESECB) != 0) { + WOLFSSL_MSG("Error with CAAM AES direct decrypt"); + } +} + + +int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len, + const byte* iv, int dir) +{ + return wc_AesSetKey(aes, key, len, iv, dir); +} +#endif + +#ifdef HAVE_AESCCM + +#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]; + 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) + return BAD_FUNC_ARG; + + if (wc_AesGetKeySize(aes, &keySz) != 0) { + return BAD_FUNC_ARG; + } + + /* set up B0 and CTR0 similar to how wolfcrypt/src/aes.c does */ + XMEMCPY(B0Ctr0+1, nonce, nonceSz); + lenSz = AES_BLOCK_SIZE - 1 - (byte)nonceSz; + B0Ctr0[0] = (authInSz > 0 ? 64 : 0) + + (8 * (((byte)authTagSz - 2) / 2)) + + (lenSz - 1); + for (i = 0; i < lenSz; i++) { + if (mask && i >= wordSz) + mask = 0x00; + B0Ctr0[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask; + } + + 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; + buf[0].Length = keySz; + + buf[1].BufferType = DataBuffer; + buf[1].TheAddress = (Address)B0Ctr0; + buf[1].Length = AES_BLOCK_SIZE + AES_BLOCK_SIZE; + + buf[2].BufferType = DataBuffer; + buf[2].TheAddress = (Address)in; + buf[2].Length = inSz; + + buf[3].BufferType = DataBuffer; + buf[3].TheAddress = (Address)out; + buf[3].Length = inSz; + + buf[3].BufferType = DataBuffer | LastBuffer; + buf[3].TheAddress = (Address)A; + buf[3].Length = ASz; + + arg[0] = CAAM_ENC; + arg[1] = keySz; + arg[2] = inSz; + arg[3] = ASz; + + if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCCM)) != 0) { + WOLFSSL_MSG("Error with CAAM AES-CCM encrypt"); + return ret; + } + + return 0; +} + + +#ifdef HAVE_AES_DECRYPT +int wc_AesCcmDecrypt(Aes* aes, byte* out, + const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + Buffer buf[4]; + 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) + return BAD_FUNC_ARG; + + if (wc_AesGetKeySize(aes, &keySz) != 0) { + return BAD_FUNC_ARG; + } + + /* set up B0 and CTR0 similar to how wolfcrypt/src/aes.c does */ + XMEMCPY(B0Ctr0+1, nonce, nonceSz); + lenSz = AES_BLOCK_SIZE - 1 - (byte)nonceSz; + B0Ctr0[0] = (authInSz > 0 ? 64 : 0) + + (8 * (((byte)authTagSz - 2) / 2)) + + (lenSz - 1); + for (i = 0; i < lenSz; i++) { + if (mask && i >= wordSz) + mask = 0x00; + B0Ctr0[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask; + } + + 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; + buf[0].Length = keySz; + + buf[1].BufferType = DataBuffer; + buf[1].TheAddress = (Address)B0Ctr0; + buf[1].Length = AES_BLOCK_SIZE + AES_BLOCK_SIZE; + + buf[2].BufferType = DataBuffer; + buf[2].TheAddress = (Address)in; + buf[2].Length = inSz; + + buf[3].BufferType = DataBuffer; + buf[3].TheAddress = (Address)out; + buf[3].Length = inSz; + + buf[3].BufferType = DataBuffer | LastBuffer; + buf[3].TheAddress = (Address)A; + buf[3].Length = ASz; + + arg[0] = CAAM_DEC; + arg[1] = keySz; + arg[2] = inSz; + arg[3] = ASz; + + if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCCM)) != 0) { + WOLFSSL_MSG("Error with CAAM AES-CCM derypt"); + return ret; + } + + return 0; +} +#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 new file mode 100644 index 0000000000..f857c82dea --- /dev/null +++ b/wolfcrypt/src/port/caam/caam_driver.c @@ -0,0 +1,1382 @@ +/* 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; diff --git a/wolfcrypt/src/port/caam/caam_init.c b/wolfcrypt/src/port/caam/caam_init.c new file mode 100644 index 0000000000..8985069e2e --- /dev/null +++ b/wolfcrypt/src/port/caam/caam_init.c @@ -0,0 +1,269 @@ +/* caam_init.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 + */ + + +#include + +#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ + defined(WOLFSSL_IMX6_CAAM_BLOB) + +#include +#include +#include + +#define WC_CAAM_BLOB_SZ 48 + +#ifndef WC_CAAM_PASSWORD + #define WC_CAAM_PASSWORD "!systempassword" +#endif + +#if defined(__INTEGRITY) || defined(INTEGRITY) + #include + #include + static IODevice caam = NULLIODevice; +#endif + +#if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG) +#include +#include + +static void wc_caamBanner(void) +{ + printf("********* wolfSSL Version %s : Printing Out CAAM Information ********\n", + LIBWOLFSSL_VERSION_STRING); + printf("CAAM Status [0x%8.8x] = 0x%8.8x\n", + CAAM_STATUS, WC_CAAM_READ(CAAM_STATUS)); + printf("CAAM Version MS Register [0x%8.8x] = 0x%8.8x\n", + CAAM_VERSION_MS, WC_CAAM_READ(CAAM_VERSION_MS)); + printf("CAAM Version LS Register [0x%8.8x] = 0x%8.8x\n", + CAAM_VERSION_LS, WC_CAAM_READ(CAAM_VERSION_LS)); + printf("CAAM Support MS Register [0x%8.8x] = 0x%8.8x\n", + CAMM_SUPPORT_MS, WC_CAAM_READ(CAMM_SUPPORT_MS)); + printf("CAAM Support LS [0x%8.8x] = 0x%8.8x\n", + CAMM_SUPPORT_LS, WC_CAAM_READ(CAMM_SUPPORT_LS)); + printf("********************************************************************\n\n"); +} +#endif + + +/* Allow runtime setting for CAAM IODevice in case user wants to use password + * at run time. + * + * returns 0 on success + * + * NOTE this is how IODevice is defined in INTEGRITY "typedef struct + * IODeviceStruct *IODevice;" + */ +int wc_caamSetResource(IODevice ioDev) +{ + WOLFSSL_MSG("Setting CAAM driver"); + caam = ioDev; + + return 0; +} + +/* Check hardware support + * + * returns 0 on success + */ +int wc_caamInit() +{ + 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) { + WOLFSSL_MSG("Unable to get the CAAM IODevice, check password?"); + } + } + +#if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG) + /* print out CAAM version/info and wolfSSL version */ + wc_caamBanner(); +#endif + + /* check that for implemented modules + * bits 0-3 AES, 4-7 DES, 12-15 Hashing , 16-19 RNG */ + reg = WC_CAAM_READ(CAMM_SUPPORT_LS); + + #ifndef WC_NO_RNG + if (((reg & 0x000F0000) >> 16) > 0) { + WOLFSSL_MSG("Found CAAM RNG hardware module"); + if ((WC_CAAM_READ(CAAM_RTMCTL) & 0x40000001) != 0x40000001) { + WOLFSSL_MSG("Error CAAM RNG has not been set up"); + } + } + #endif + + #ifndef NO_SHA256 + if ((reg & 0x0000F000) > 0) { + WOLFSSL_MSG("Found CAAM MDHA module"); + } + else { + WOLFSSL_MSG("Hashing not supported by CAAM"); + return WC_CAAM_E; + } + #endif + + + #ifndef NO_AES + if ((reg & 0x0000000F) > 0) { + WOLFSSL_MSG("Found CAAM AES module"); + } + else { + WOLFSSL_MSG("AES not supported by CAAM"); + return WC_CAAM_E; + } + #endif + + return 0; +} + + +int wc_caamFree() +{ + return 0; +} + + +word32 wc_caamReadRegister(word32 reg) +{ + Value out = 0; + + if (caam == NULLIODevice) { + WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?"); + return 0; + } + + if (ReadIODeviceRegister(caam, reg, &out) != Success) { + WOLFSSL_MSG("Error reading register\n"); + } + + return (word32)out; +} + +void wc_caamWriteRegister(word32 reg, word32 value) +{ + if (caam == NULLIODevice) { + WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?"); + return; + } + + if (WriteIODeviceRegister(caam, reg, value) != Success) { + WOLFSSL_MSG("Error writing to register\n"); + } +} + + +int wc_caamAddAndWait(Buffer* buf, word32 arg[4], word32 type) +{ + int ret; + if (caam == NULLIODevice) { + WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?"); + return WC_CAAM_E; + } + + if ((ret = SynchronousSendIORequest(caam, type, (const Value*)arg, buf)) + != Success) { + #if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG) + printf("ret of SynchronousSendIORequest = %d type = %d\n", ret, type); + #endif + return WC_CAAM_E; + } + + (void)ret; + return 0; +} + + +int wc_caamCreateBlob(byte* data, word32 dataSz, byte* out, word32* outSz) +{ + Buffer in[3]; + word32 arg[4]; + int ret; + word32 local[2] = {0,0}; + + if (*outSz < dataSz + WC_CAAM_BLOB_SZ) { + return BAD_FUNC_ARG; + } + + in[0].BufferType = DataBuffer; + in[0].TheAddress = (Address)local; + in[0].Length = sizeof(local); + + in[1].BufferType = DataBuffer; + in[1].TheAddress = (Address)data; + in[1].Length = dataSz; + + in[2].BufferType = DataBuffer | LastBuffer; + in[2].TheAddress = (Address)out; + in[2].Length = dataSz + WC_CAAM_BLOB_SZ; + + arg[2] = dataSz; + + if ((ret = wc_caamAddAndWait(in, arg, CAAM_BLOB_ENCAP)) != 0) { + WOLFSSL_MSG("Error with CAAM blob create"); + return ret; + } + + *outSz = dataSz + WC_CAAM_BLOB_SZ; + return 0; +} + + +int wc_caamOpenBlob(byte* data, word32 dataSz, byte* out, word32* outSz) +{ + Buffer in[3]; + word32 arg[4]; + int ret; + word32 local[2] = {0,0}; + + if (*outSz < dataSz - WC_CAAM_BLOB_SZ) { + return BAD_FUNC_ARG; + } + + in[0].BufferType = DataBuffer; + in[0].TheAddress = (Address)local; + in[0].Length = sizeof(local); + + in[0].BufferType = DataBuffer; + in[0].TheAddress = (Address)data; + in[0].Length = dataSz; + + in[1].BufferType = DataBuffer | LastBuffer; + in[1].TheAddress = (Address)out; + in[1].Length = dataSz - WC_CAAM_BLOB_SZ; + + arg[2] = dataSz; + + if ((ret = wc_caamAddAndWait(in, arg, CAAM_BLOB_DECAP)) != 0) { + WOLFSSL_MSG("Error with CAAM blob create"); + return ret; + } + + *outSz = dataSz - WC_CAAM_BLOB_SZ; + return 0; +} + +#endif /* WOLFSSL_IMX6_CAAM */ + diff --git a/wolfcrypt/src/port/caam/caam_sha.c b/wolfcrypt/src/port/caam/caam_sha.c new file mode 100644 index 0000000000..044a4d37ff --- /dev/null +++ b/wolfcrypt/src/port/caam/caam_sha.c @@ -0,0 +1,397 @@ +/* caam_sha.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 + */ + + +#include + +#if defined(WOLFSSL_IMX6_CAAM) + +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#include +#include +#include + +#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) +#include +#endif + +#ifndef NO_SHA +#include +#endif + +#if !defined(NO_SHA256) || defined(WOLFSSL_SHA224) +#include +#endif + +#if defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) +#include +#endif + +#ifndef NO_MD5 +#include +#endif + +/****************************************************************************** + Common Code Between SHA Functions + ****************************************************************************/ + +static int _InitSha(Sha* sha, void* heap, int devId, word32 digestSz, + word32 type) +{ + Buffer buf[1]; + word32 arg[4]; + int ret; + + (void)heap; + (void)devId; + + if (sha == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(sha, 0, sizeof(Sha)); + + /* Set buffer for context */ + buf[0].BufferType = DataBuffer | LastBuffer; + buf[0].TheAddress = (Address)sha->ctx; + buf[0].Length = digestSz + WC_CAAM_CTXLEN; + buf[0].Transferred = 0; + + arg[0] = CAAM_ALG_INIT; + arg[1] = digestSz + WC_CAAM_CTXLEN; + + if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) { + WOLFSSL_MSG("Error with CAAM SHA init"); + return ret; + } + + return 0; +} + + +static int _ShaUpdate(Sha* sha, const byte* data, word32 len, word32 digestSz, + word32 type) +{ + Buffer buf[2]; + word32 arg[4]; + int ret; + byte* local; + + if (sha == NULL ||(data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + if (len == 0) return 0; /* nothing to do */ + + local = (byte*)sha->buffer; + /* check for filling out existing buffer */ + if (sha->buffLen > 0) { + word32 add = min(len, WC_CAAM_HASH_BLOCK - sha->buffLen); + XMEMCPY(&local[sha->buffLen], data, add); + + sha->buffLen += add; + data += add; + len -= add; + + if (sha->buffLen == WC_CAAM_HASH_BLOCK) { + /* Set buffer for context */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)sha->ctx; + buf[0].Length = digestSz + WC_CAAM_CTXLEN; + buf[0].Transferred = 0; + + /* data to update with */ + buf[1].BufferType = DataBuffer | LastBuffer; + buf[1].TheAddress = (Address)sha->buffer; + buf[1].Length = sha->buffLen; + buf[1].Transferred = 0; + + arg[0] = CAAM_ALG_UPDATE; + arg[1] = digestSz + WC_CAAM_CTXLEN; + + if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) { + WOLFSSL_MSG("Error with CAAM SHA update"); + return ret; + } + sha->buffLen = 0; /* cleared out buffer */ + } + } + + /* check if multiple full blocks can be done */ + if (len >= WC_CAAM_HASH_BLOCK) { + word32 sz = len / WC_CAAM_HASH_BLOCK; + sz = sz * WC_CAAM_HASH_BLOCK; + + /* Set buffer for context */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)sha->ctx; + buf[0].Length = digestSz + WC_CAAM_CTXLEN; + buf[0].Transferred = 0; + + /* data to update with */ + buf[1].BufferType = DataBuffer | LastBuffer; + buf[1].TheAddress = (Address)data; + buf[1].Length = sz; + buf[1].Transferred = 0; + + arg[0] = CAAM_ALG_UPDATE; + arg[1] = digestSz + WC_CAAM_CTXLEN; + + if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) { + WOLFSSL_MSG("Error with CAAM SHA update"); + return ret; + } + + len -= sz; + data += sz; + } + + /* check for left overs */ + if (len > 0) { + word32 add = min(len, WC_CAAM_HASH_BLOCK - sha->buffLen); + XMEMCPY(&local[sha->buffLen], data, add); + sha->buffLen += add; + } + + return 0; +} + + +static int _ShaFinal(Sha* sha, byte* out, word32 digestSz, + word32 type) +{ + Buffer buf[2]; + word32 arg[4]; + int ret; + + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + /* Set buffer for context */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)sha->ctx; + buf[0].Length = digestSz + WC_CAAM_CTXLEN; + buf[0].Transferred = 0; + + /* add any potential left overs */ + buf[1].BufferType = DataBuffer | LastBuffer; + buf[1].TheAddress = (Address)sha->buffer; + buf[1].Length = sha->buffLen; + buf[1].Transferred = 0; + + arg[0] = CAAM_ALG_FINAL; + arg[1] = digestSz + WC_CAAM_CTXLEN; + + if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) { + WOLFSSL_MSG("Error with CAAM SHA init"); + return ret; + } + + return 0; +} + +/****************************************************************************** + MD5 + ****************************************************************************/ +#if !defined(NO_MD5) +int wc_InitMd5_ex(wc_Md5* sha, void* heap, int devId) +{ + return _InitSha(sha, heap, devId, MD5_DIGEST_SIZE, CAAM_MD5); +} + + +int wc_Md5Update(wc_Md5* sha, const byte* data, word32 len) +{ + return _ShaUpdate(sha, data, len, MD5_DIGEST_SIZE, CAAM_MD5); +} + + +int wc_Md5Final(wc_Md5* sha, byte* hash) +{ + int ret; + if ((ret = _ShaFinal(sha, hash, MD5_DIGEST_SIZE, CAAM_MD5)) != 0) { + return ret; + } + + XMEMCPY(hash, (byte*)sha->ctx, MD5_DIGEST_SIZE); + return _InitSha(sha, NULL, 0, MD5_DIGEST_SIZE, CAAM_MD5); +} +#endif /* !NO_MD5 */ + + +/****************************************************************************** + SHA 1 + ****************************************************************************/ +#if !defined(NO_SHA) +int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) +{ + return _InitSha(sha, heap, devId, SHA_DIGEST_SIZE, CAAM_SHA); +} + + +int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len) +{ + return _ShaUpdate(sha, data, len, SHA_DIGEST_SIZE, CAAM_SHA); +} + + +int wc_ShaFinal(wc_Sha* sha, byte* out) +{ + int ret; + if ((ret = _ShaFinal(sha, out, SHA_DIGEST_SIZE, CAAM_SHA)) != 0) { + return ret; + } + + XMEMCPY(out, (byte*)sha->ctx, SHA_DIGEST_SIZE); + return _InitSha(sha, NULL, 0, SHA_DIGEST_SIZE, CAAM_SHA); +} +#endif /* !NO_SHA */ + + +/****************************************************************************** + SHA 224 + ****************************************************************************/ +#ifdef WOLFSSL_SHA224 +int wc_InitSha224_ex(wc_Sha224* sha, void* heap, int devId) +{ + return _InitSha(sha, heap, devId, SHA256_DIGEST_SIZE, CAAM_SHA224); +} + + +int wc_Sha224Update(wc_Sha224* sha, const byte* data, word32 len) +{ + return _ShaUpdate(sha, data, len, SHA256_DIGEST_SIZE, CAAM_SHA224); +} + + +int wc_Sha224Final(wc_Sha224* sha, byte* out) +{ + int ret; + if ((ret = _ShaFinal(sha, out, SHA256_DIGEST_SIZE, CAAM_SHA224)) != 0) { + return ret; + } + + XMEMCPY(out, (byte*)sha->ctx, SHA224_DIGEST_SIZE); + return _InitSha(sha, NULL, 0, SHA256_DIGEST_SIZE, CAAM_SHA224); +} +#endif /* WOLFSSL_SHA224 */ + + +/****************************************************************************** + SHA 256 + ****************************************************************************/ +#if !defined(NO_SHA256) +int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devId) +{ + return _InitSha(sha, heap, devId, SHA256_DIGEST_SIZE, CAAM_SHA256); +} + + +int wc_Sha256Update(wc_Sha256* sha, const byte* data, word32 len) +{ + return _ShaUpdate(sha, data, len, SHA256_DIGEST_SIZE, CAAM_SHA256); +} + + +int wc_Sha256Final(wc-Sha256* sha, byte* out) +{ + int ret; + if ((ret = _ShaFinal(sha, out, SHA256_DIGEST_SIZE, CAAM_SHA256)) != 0) { + return ret; + } + + XMEMCPY(out, (byte*)sha->ctx, SHA256_DIGEST_SIZE); + return _InitSha(sha, NULL, 0, SHA256_DIGEST_SIZE, CAAM_SHA256); +} +#endif /* !NO_SHA256 */ + + +/****************************************************************************** + SHA 384 + ****************************************************************************/ +#ifdef WOLFSSL_SHA384 +int wc_InitSha384_ex(wc_Sha384* sha, void* heap, int devId) +{ + return _InitSha(sha, heap, devId, SHA512_DIGEST_SIZE, CAAM_SHA384); +} + + +int wc_Sha384Update(wc_Sha384* sha, const byte* data, word32 len) +{ + return _ShaUpdate(sha, data, len, SHA512_DIGEST_SIZE, CAAM_SHA384); +} + + +int wc_Sha384Final(wc_Sha384* sha, byte* out) +{ + int ret; + if ((ret = _ShaFinal(sha, out, SHA512_DIGEST_SIZE, CAAM_SHA384)) != 0) { + return ret; + } + + XMEMCPY(out, (byte*)sha->ctx, SHA384_DIGEST_SIZE); + return _InitSha(sha, NULL, 0, SHA512_DIGEST_SIZE, CAAM_SHA384); +} +#endif /* WOLFSSL_SHA384 */ + + + +/****************************************************************************** + SHA 512 + ****************************************************************************/ +#ifdef WOLFSSL_SHA512 +int wc_InitSha512_ex(wc_Sha512* sha, void* heap, int devId) +{ + return _InitSha(sha, heap, devId, SHA512_DIGEST_SIZE, CAAM_SHA512); +} + + +int wc_Sha512Update(wc_Sha512* sha, const byte* data, word32 len) +{ + return _ShaUpdate(sha, data, len, SHA512_DIGEST_SIZE, CAAM_SHA512); +} + + +int wc_Sha512Final(wc_Sha512* sha, byte* out) +{ + int ret; + if ((ret = _ShaFinal(sha, out, SHA512_DIGEST_SIZE, CAAM_SHA512)) != 0) { + return ret; + } + + XMEMCPY(out, (byte*)sha->ctx, SHA512_DIGEST_SIZE); + return _InitSha(sha, NULL, 0, SHA512_DIGEST_SIZE, CAAM_SHA512); +} +#endif /* WOLFSSL_SHA512 */ + +#endif /* WOLFSSL_IMX6_CAAM */ + diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 1f0d641853..4e74e84b10 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -1628,6 +1628,49 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return 0; } +#elif (defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG)) + + #include + #include + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + Buffer buf[1]; + int ret = 0; + int times = 10, i; + + (void)os; + + if (output == NULL) { + return BUFFER_E; + } + + buf[0].BufferType = DataBuffer | LastBuffer; + buf[0].TheAddress = (Address)output; + buf[0].Length = sz; + + /* Check Waiting to make sure entropy is ready */ + for (i = 0; i < times; i++) { + ret = wc_caamAddAndWait(buf, NULL, CAAM_ENTROPY); + if (ret == Success) { + break; + } + if (ret != Waiting) { + return ret; + } + sleep(1); + } + + if (i == times && ret != Success) { + return RNG_FAILURE_E; + } + else { /* Success case */ + ret = 0; + } + + return ret; + } + #elif defined(CUSTOM_RAND_GENERATE_BLOCK) /* #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc * extern int myRngFunc(byte* output, word32 sz); diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index 16a38b02cf..e62719282e 100644 --- a/wolfcrypt/src/sha.c +++ b/wolfcrypt/src/sha.c @@ -316,6 +316,8 @@ static INLINE void AddLength(wc_Sha* sha, word32 len); return ret; } +#elif defined(WOLFSSL_IMX6_CAAM) + /* wolfcrypt/src/port/caam/caam_sha.c */ #else /* Software implementation */ diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 2f19b92748..60406e59d9 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -117,7 +117,8 @@ static INLINE void AddLength(wc_Sha256* sha256, word32 len); -#if !defined(WOLFSSL_PIC32MZ_HASH) && !defined(STM32_HASH) +#if !defined(WOLFSSL_PIC32MZ_HASH) && !defined(STM32_HASH) && \ + !defined(WOLFSSL_IMX6_CAAM) static int InitSha256(wc_Sha256* sha256) { int ret = 0; @@ -518,7 +519,8 @@ static int InitSha256(wc_Sha256* sha256) return ret; } - +#elif defined(WOLFSSL_IMX6_CAAM) + /* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */ #else #define NEED_SOFT_SHA256 @@ -2706,8 +2708,13 @@ SHA256_NOINLINE static int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256, return ret; } +#elif defined(WOLFSSL_IMX6_CAAM) + /* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */ #else + #define NEED_SOFT_SHA224 + + static int InitSha224(wc_Sha224* sha224) { int ret = 0; @@ -2739,6 +2746,7 @@ SHA256_NOINLINE static int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256, #endif /* STM32_HASH */ +#if defined(NEED_SOFT_SHA224) || defined(STM32_HASH) int wc_InitSha224_ex(wc_Sha224* sha224, void* heap, int devId) { int ret = 0; @@ -2762,11 +2770,6 @@ SHA256_NOINLINE static int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256, return ret; } - int wc_InitSha224(wc_Sha224* sha224) - { - return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID); - } - int wc_Sha224Update(wc_Sha224* sha224, const byte* data, word32 len) { int ret; @@ -2816,6 +2819,12 @@ SHA256_NOINLINE static int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256, return InitSha224(sha224); /* reset state */ } +#endif /* end of SHA224 software implementation */ + + int wc_InitSha224(wc_Sha224* sha224) + { + return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID); + } void wc_Sha224Free(wc_Sha224* sha224) { @@ -2826,7 +2835,6 @@ SHA256_NOINLINE static int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256, wolfAsync_DevCtxFree(&sha224->asyncDev, WOLFSSL_ASYNC_MARKER_SHA224); #endif /* WOLFSSL_ASYNC_CRYPT */ } - #endif /* WOLFSSL_SHA224 */ diff --git a/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c index 9c29bced94..73b2f9cd3c 100644 --- a/wolfcrypt/src/sha512.c +++ b/wolfcrypt/src/sha512.c @@ -168,6 +168,10 @@ } #endif +#ifdef WOLFSSL_IMX6_CAAM /* hardware */ + /* functions defined in wolfcrypt/src/port/caam/caam_sha.c */ +#else + static int InitSha512(wc_Sha512* sha512) { if (sha512 == NULL) @@ -623,7 +627,7 @@ int wc_Sha512Update(wc_Sha512* sha512, const byte* data, word32 len) return Sha512Update(sha512, data, len); } - +#endif /* WOLFSSL_IMX6_CAAM */ static INLINE int Sha512Final(wc_Sha512* sha512) { @@ -2540,6 +2544,11 @@ static int Transform_Sha512_AVX2_RORX_Len(wc_Sha512* sha512, word32 len) /* SHA384 */ /* -------------------------------------------------------------------------- */ #ifdef WOLFSSL_SHA384 + +#ifdef WOLFSSL_IMX6_CAAM /* hardware */ + /* functions defined in wolfcrypt/src/port/caam/caam_sha.c */ +#else + static int InitSha384(wc_Sha384* sha384) { if (sha384 == NULL) { @@ -2644,6 +2653,7 @@ int wc_InitSha384_ex(wc_Sha384* sha384, void* heap, int devId) return ret; } #endif +#endif /* WOLFSSL_IMX6_CAAM */ int wc_InitSha384(wc_Sha384* sha384) { diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index 8d10007e9e..68c8955db5 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -59,6 +59,11 @@ #include #endif +#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ + defined(WOLFSSL_IMX6_CAAM_BLOB) + #include +#endif + #ifdef _MSC_VER /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ #pragma warning(disable: 4996) @@ -153,6 +158,13 @@ int wolfCrypt_Init(void) #endif #endif +#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ + defined(WOLFSSL_IMX6_CAAM_BLOB) + if ((ret = wc_caamInit()) != 0) { + return ret; + } +#endif + initRefCount = 1; } @@ -189,6 +201,11 @@ int wolfCrypt_Cleanup(void) wolfAsync_HardwareStop(); #endif + #if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ + defined(WOLFSSL_IMX6_CAAM_BLOB) + wc_caamFree(); + #endif + initRefCount = 0; /* allow re-init */ } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index a70d01b0b2..f699e99e62 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -113,6 +113,9 @@ #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) #include #endif +#ifdef WOLFSSL_IMX6_CAAM_BLOB + #include +#endif /* only for stack size check */ #ifdef HAVE_STACK_SIZE @@ -317,6 +320,9 @@ int mutex_test(void); #if defined(USE_WOLFSSL_MEMORY) && !defined(FREERTOS) int memcb_test(void); #endif +#ifdef WOLFSSL_IMX6_CAAM_BLOB +int blob_test(void); +#endif #if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) && \ !defined(OPENSSL_EXTRA) && !defined(HAVE_STACK_SIZE) @@ -874,6 +880,13 @@ int wolfcrypt_test(void* args) printf( "memcb test passed!\n"); #endif +#ifdef WOLFSSL_IMX6_CAAM_BLOB + if ( (ret = blob_test()) != 0) + return err_sys("blob test failed!\n", ret); + else + printf( "blob test passed!\n"); +#endif + #ifdef WOLFSSL_ASYNC_CRYPT wolfAsync_DevClose(&devId); #endif @@ -15266,6 +15279,85 @@ exit_memcb: } #endif + +#ifdef WOLFSSL_IMX6_CAAM_BLOB +int blob_test(void) +{ + int ret = 0; + byte out[112]; + byte blob[112]; + word32 outSz; + + const byte iv[] = + { + 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, + 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff + }; + + const byte text[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, + 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11, + 0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, + 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17, + 0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10 + }; + + + memset(blob, 0, sizeof(blob)); + outSz = sizeof(blob); + ret = wc_caamCreateBlob((byte*)iv, sizeof(iv), blob, &outSz); + if (ret != 0) { + ERROR_OUT(-8200, exit_blob); + } + + blob[outSz - 2] += 1; + ret = wc_caamOpenBlob(blob, outSz, out, &outSz); + if (ret == 0) { /* should fail with altered blob */ + ERROR_OUT(-8201, exit_blob); + } + + memset(blob, 0, sizeof(blob)); + outSz = sizeof(blob); + ret = wc_caamCreateBlob((byte*)iv, sizeof(iv), blob, &outSz); + if (ret != 0) { + ERROR_OUT(-8202, exit_blob); + } + + ret = wc_caamOpenBlob(blob, outSz, out, &outSz); + if (ret != 0) { + ERROR_OUT(-8203, exit_blob); + } + + if (XMEMCMP(out, iv, sizeof(iv))) { + ERROR_OUT(-8204, exit_blob); + } + + memset(blob, 0, sizeof(blob)); + outSz = sizeof(blob); + ret = wc_caamCreateBlob((byte*)text, sizeof(text), blob, &outSz); + if (ret != 0) { + ERROR_OUT(-8205, exit_blob); + } + + ret = wc_caamOpenBlob(blob, outSz, out, &outSz); + if (ret != 0) { + ERROR_OUT(-8206, exit_blob); + } + + if (XMEMCMP(out, text, sizeof(text))) { + ERROR_OUT(-8207, exit_blob); + } + + exit_blob: + + return ret; +} +#endif /* WOLFSSL_IMX6_CAAM_BLOB */ + #undef ERROR_OUT #else diff --git a/wolfssl/test.h b/wolfssl/test.h index f4aa9e64c1..577fe4571f 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -790,7 +790,11 @@ static INLINE int tcp_select(SOCKET_T socketfd, int to_sec) { fd_set recvfds, errfds; SOCKET_T nfds = socketfd + 1; - struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0}; +#if !defined(__INTEGRITY) + struct timeval timeout = {(to_sec > 0) ? to_sec : 0, 0}; +#else + struct timeval timeout; +#endif int result; FD_ZERO(&recvfds); @@ -798,6 +802,9 @@ static INLINE int tcp_select(SOCKET_T socketfd, int to_sec) FD_ZERO(&errfds); FD_SET(socketfd, &errfds); +#if defined(__INTEGRITY) + timeout.tv_sec = (long long)(to_sec > 0) ? to_sec : 0, 0; +#endif result = select(nfds, &recvfds, NULL, &errfds, &timeout); if (result == 0) diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 6c0abea549..af4954ea87 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -191,8 +191,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_LAST_E = -247, /* Update this to indicate last error */ + WC_LAST_E = -248, /* 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/include.am b/wolfssl/wolfcrypt/include.am index fc458c51ed..b03a516180 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -70,7 +70,10 @@ noinst_HEADERS+= \ wolfssl/wolfcrypt/port/nrf51.h \ wolfssl/wolfcrypt/port/nxp/ksdk_port.h \ wolfssl/wolfcrypt/port/atmel/atmel.h \ - wolfssl/wolfcrypt/port/xilinx/xil-sha3.h + wolfssl/wolfcrypt/port/xilinx/xil-sha3.h \ + wolfssl/wolfcrypt/port/caam/caam_driver.h \ + wolfssl/wolfcrypt/port/caam/wolfcaam.h \ + wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h if BUILD_ASYNCCRYPT nobase_include_HEADERS+= wolfssl/wolfcrypt/async.h diff --git a/wolfssl/wolfcrypt/md5.h b/wolfssl/wolfcrypt/md5.h index 45b5d3703e..c0db601e22 100644 --- a/wolfssl/wolfcrypt/md5.h +++ b/wolfssl/wolfcrypt/md5.h @@ -63,6 +63,8 @@ enum { #ifdef WOLFSSL_TI_HASH #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#elif defined(WOLFSSL_IMX6_CAAM) + #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" #else /* MD5 digest */ diff --git a/wolfssl/wolfcrypt/port/caam/caam_driver.h b/wolfssl/wolfcrypt/port/caam/caam_driver.h new file mode 100644 index 0000000000..a9930a358f --- /dev/null +++ b/wolfssl/wolfcrypt/port/caam/caam_driver.h @@ -0,0 +1,184 @@ +/* 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 */ diff --git a/wolfssl/wolfcrypt/port/caam/wolfcaam.h b/wolfssl/wolfcrypt/port/caam/wolfcaam.h new file mode 100644 index 0000000000..e80949d193 --- /dev/null +++ b/wolfssl/wolfcrypt/port/caam/wolfcaam.h @@ -0,0 +1,70 @@ +/* wolfcaam.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 WOLF_CRYPT_CAAM_INIT_H +#define WOLF_CRYPT_CAAM_INIT_H + +#include + +#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) + +#include + +#if defined(__INTEGRITY) || defined(INTEGRITY) + #include +#endif + +WOLFSSL_LOCAL int wc_caamInit(void); +WOLFSSL_LOCAL int wc_caamFree(void); +WOLFSSL_LOCAL int wc_caamInitRng(void); +WOLFSSL_LOCAL int wc_caamFreeRng(void); + +WOLFSSL_LOCAL word32 wc_caamReadRegister(word32 reg); +WOLFSSL_LOCAL void wc_caamWriteRegister(word32 reg, word32 value); +WOLFSSL_LOCAL int wc_caamAddAndWait(Buffer* buf, word32 arg[4], word32 type); + +WOLFSSL_API int wc_caamSetResource(IODevice ioDev); + +WOLFSSL_API int wc_caamOpenBlob(byte* data, word32 dataSz, byte* out, + word32* outSz); +WOLFSSL_API int wc_caamCreateBlob(byte* data, word32 dataSz, byte* out, + word32* outSz); + +/* Status Registers */ +#define WC_CAAM_STATUS WC_CAAM_BASE + 0x0FD4 +#define WC_CAAM_VERSION_MS WC_CAAM_BASE + 0x0FE8 +#define WC_CAAM_VERSION_LS WC_CAAM_BASE + 0x0FEC +#define WC_CAMM_SUPPORT_MS WC_CAAM_BASE + 0x0FF0 +#define WC_CAMM_SUPPORT_LS WC_CAAM_BASE + 0x0FF4 + +/* additional size that is added by CAAM when creating a blob */ +#define WC_CAAM_BLOB_SZ 48 + +#ifndef WC_CAAM_READ + #define WC_CAAM_READ(reg) wc_caamReadRegister((reg)) +#endif +#ifndef WC_CAAM_WRITE + #define WC_CAAM_WRITE(reg, x) wc_caamWriteRegister((reg), (x)) +#endif + +#endif /* WOLFSSL_IMX6_CAAM */ + +#endif /* WOLF_CRYPT_CAAM_INIT_H */ diff --git a/wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h b/wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h new file mode 100644 index 0000000000..34f274cfe3 --- /dev/null +++ b/wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h @@ -0,0 +1,86 @@ +/* wolfcaam_sha.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 WOLF_CRYPT_CAAM_SHA_H +#define WOLF_CRYPT_CAAM_SHA_H + +#include + +#ifdef WOLFSSL_IMX6_CAAM + +#include + +#ifndef WC_CAAM_CTXLEN +/* last 8 bytes of context is for length */ +#define WC_CAAM_CTXLEN 8 +#endif + +#ifndef WC_CAAM_HASH_BLOCK +/* define sha structures and also get the max possible digest. Start with SHA + digest size */ +#define WC_CAAM_HASH_BLOCK 64 +#endif + +#ifndef WC_CAAM_MAX_DIGEST +#define WC_CAAM_MAX_DIGEST 20 +#ifdef WOLFSSL_SHA224 + #undef WC_CAAM_MAX_DIGEST + #define WC_CAAM_MAX_DIGEST 32 +#endif + +#ifndef NO_SHA256 + #undef WC_CAAM_MAX_DIGEST + #define WC_CAAM_MAX_DIGEST 32 +#endif + +#ifdef WOLFSSL_SHA384 + #undef WC_CAAM_MAX_DIGEST + #define WC_CAAM_MAX_DIGEST 64 +#endif + +#ifdef WOLFSSL_SHA512 + #undef WC_CAAM_MAX_DIGEST + #define WC_CAAM_MAX_DIGEST 64 +#endif +#endif /* WC_CAAM_MAX_DIGEST */ + + +typedef struct 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; + +#ifndef NO_MD5 + typedef struct Sha wc_Md5; +#endif + +#ifndef NO_SHA256 + typedef struct Sha wc_Sha256; +#endif + +#ifdef WOLFSSL_SHA512 + typedef struct Sha wc_Sha512; +#endif + +#endif /* WOLFSSL_IMX6_CAAM */ + +#endif /* WOLF_CRYPT_CAAM_SHA_H */ diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 41bab112c4..98ce625469 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -1183,6 +1183,12 @@ extern void uITRON4_free(void *p) ; #endif #endif /*(WOLFSSL_XILINX_CRYPT)*/ +#ifdef WOLFSSL_IMX6 + #ifndef SIZEOF_LONG_LONG + #define SIZEOF_LONG_LONG 8 + #endif +#endif + #if !defined(XMALLOC_USER) && !defined(MICRIUM_MALLOC) && \ !defined(WOLFSSL_LEANPSK) && !defined(NO_WOLFSSL_MEMORY) && \ !defined(XMALLOC_OVERRIDE) diff --git a/wolfssl/wolfcrypt/sha.h b/wolfssl/wolfcrypt/sha.h index 97ce2e63cb..7b742f0cc1 100644 --- a/wolfssl/wolfcrypt/sha.h +++ b/wolfssl/wolfcrypt/sha.h @@ -72,7 +72,13 @@ enum { }; -#ifndef WOLFSSL_TI_HASH +#if defined(WOLFSSL_TI_HASH) + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" + +#elif defined(WOLFSSL_IMX6_CAAM) + #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" + +#else /* Sha digest */ typedef struct wc_Sha { #ifdef FREESCALE_LTC_SHA @@ -100,8 +106,6 @@ typedef struct wc_Sha { #endif /* FREESCALE_LTC_SHA */ } wc_Sha; -#else - #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" #endif /* WOLFSSL_TI_HASH */ diff --git a/wolfssl/wolfcrypt/sha256.h b/wolfssl/wolfcrypt/sha256.h index 0cc9beb3cf..7fb3a696c7 100644 --- a/wolfssl/wolfcrypt/sha256.h +++ b/wolfssl/wolfcrypt/sha256.h @@ -90,8 +90,11 @@ enum { WC_SHA256_PAD_SIZE = 56 }; -#ifndef WOLFSSL_TI_HASH - +#ifdef WOLFSSL_TI_HASH + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#elif defined(WOLFSSL_IMX6_CAAM) + #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" +#else /* wc_Sha256 digest */ typedef struct wc_Sha256 { #ifdef FREESCALE_LTC_SHA @@ -119,8 +122,6 @@ typedef struct wc_Sha256 { #endif /* FREESCALE_LTC_SHA */ } wc_Sha256; -#else - #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" #endif #endif /* HAVE_FIPS */ diff --git a/wolfssl/wolfcrypt/sha512.h b/wolfssl/wolfcrypt/sha512.h index 277f1a6874..9dd6950883 100644 --- a/wolfssl/wolfcrypt/sha512.h +++ b/wolfssl/wolfcrypt/sha512.h @@ -84,6 +84,9 @@ enum { }; +#ifdef WOLFSSL_IMX6_CAAM + #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" +#else /* wc_Sha512 digest */ typedef struct wc_Sha512 { word64 digest[WC_SHA512_DIGEST_SIZE / sizeof(word64)]; @@ -99,6 +102,7 @@ typedef struct wc_Sha512 { WC_ASYNC_DEV asyncDev; #endif /* WOLFSSL_ASYNC_CRYPT */ } wc_Sha512; +#endif #endif /* HAVE_FIPS */ diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index f7766d49ca..f3faad367f 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -449,6 +449,7 @@ DYNAMIC_TYPE_QSH = 86, DYNAMIC_TYPE_SALT = 87, DYNAMIC_TYPE_HASH_TMP = 88, + DYNAMIC_TYPE_BLOB = 89, }; /* max error buffer string size */