#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_MAX3266X) || defined(WOLFSSL_MAX3266X_OLD)
#include <stdint.h>
#include <stdarg.h>
#include <wolfssl/wolfcrypt/wolfmath.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/port/maxim/max3266x.h>
#include <wolfssl/wolfcrypt/hash.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#ifdef WOLF_CRYPTO_CB
#include <wolfssl/wolfcrypt/port/maxim/max3266x-cryptocb.h>
#endif
#if defined(USE_FAST_MATH) || defined(USE_INTEGER_HEAP_MATH)
#error MXC Not Compatible with Fast Math or Heap Math
#include <wolfssl/wolfcrypt/tfm.h>
#define MXC_WORD_SIZE DIGIT_BIT
#elif defined(WOLFSSL_SP_MATH_ALL)
#include <wolfssl/wolfcrypt/sp_int.h>
#define MXC_WORD_SIZE SP_WORD_SIZE
#else
#error MXC HW port needs #define WOLFSSL_SP_MATH_ALL
#endif
#define MXC_MAA_MAX_SIZE (2048 / MXC_WORD_SIZE)
int wc_MXC_TPU_Init(void)
{
if (MXC_TPU_Init(MXC_SYS_PERIPH_CLOCK_TRNG) != 0) {
MAX3266X_MSG("Device did not initialize");
return RNG_FAILURE_E;
}
return 0;
}
int wc_MXC_TPU_Shutdown(void)
{
#if defined(WOLFSSL_MAX3266X_OLD)
MXC_TPU_Shutdown();
#else
if (MXC_TPU_Shutdown(MXC_SYS_PERIPH_CLOCK_TRNG) != 0) {
MAX3266X_MSG("Device did not shutdown");
return RNG_FAILURE_E;
}
#endif
MAX3266X_MSG("TPU Hardware Shutdown");
return 0;
}
#ifdef WOLF_CRYPTO_CB
int wc_MxcAesCryptoCb(wc_CryptoInfo* info)
{
switch (info->cipher.type) {
#ifdef HAVE_AES_CBC
case WC_CIPHER_AES_CBC:
if (info->cipher.enc == 1) {
return wc_MxcCb_AesCbcEncrypt(info->cipher.aescbc.aes,
info->cipher.aescbc.out,
info->cipher.aescbc.in,
info->cipher.aescbc.sz);
}
#ifdef HAVE_AES_DECRYPT
else if (info->cipher.enc == 0) {
return wc_MxcCb_AesCbcDecrypt(info->cipher.aescbc.aes,
info->cipher.aescbc.out,
info->cipher.aescbc.in,
info->cipher.aescbc.sz);
}
#endif
break;
#endif
#ifdef HAVE_AES_ECB
case WC_CIPHER_AES_ECB:
if (info->cipher.enc == 1) {
return wc_MxcCb_AesEcbEncrypt(info->cipher.aesecb.aes,
info->cipher.aesecb.out,
info->cipher.aesecb.in,
info->cipher.aesecb.sz);
}
#ifdef HAVE_AES_DECRYPT
else if (info->cipher.enc == 0) {
return wc_MxcCb_AesEcbDecrypt(info->cipher.aesecb.aes,
info->cipher.aesecb.out,
info->cipher.aesecb.in,
info->cipher.aesecb.sz);
}
#endif
break;
#endif
default:
return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
}
return BAD_FUNC_ARG;
}
#ifdef MAX3266X_SHA_CB
static int wc_MxcShaCbDispatch(byte** msg, word32* used, word32* len,
void* heap, const byte* in, word32 inSz,
byte* digest, MXC_TPU_HASH_TYPE algo)
{
if (in != NULL && digest == NULL) {
MAX3266X_MSG("Update CB");
return _wc_Hash_Grow(msg, used, len, in, (int)inSz, heap);
}
if (in == NULL && digest != NULL) {
MAX3266X_MSG("Final CB");
return wc_MXC_TPU_SHA_Final(msg, used, len, heap, digest, algo);
}
if (inSz == 0) {
return 0;
}
return BAD_FUNC_ARG;
}
int wc_MxcShaCryptoCb(wc_CryptoInfo* info)
{
switch (info->hash.type) {
#ifndef NO_SHA
case WC_HASH_TYPE_SHA:
return wc_MxcShaCbDispatch(&info->hash.sha1->msg,
&info->hash.sha1->used, &info->hash.sha1->len,
info->hash.sha1->heap, info->hash.in,
info->hash.inSz, info->hash.digest,
MXC_TPU_HASH_SHA1);
#endif
#ifdef WOLFSSL_SHA224
case WC_HASH_TYPE_SHA224:
return wc_MxcShaCbDispatch(&info->hash.sha224->msg,
&info->hash.sha224->used, &info->hash.sha224->len,
info->hash.sha224->heap, info->hash.in,
info->hash.inSz, info->hash.digest,
MXC_TPU_HASH_SHA224);
#endif
#ifndef NO_SHA256
case WC_HASH_TYPE_SHA256:
return wc_MxcShaCbDispatch(&info->hash.sha256->msg,
&info->hash.sha256->used, &info->hash.sha256->len,
info->hash.sha256->heap, info->hash.in,
info->hash.inSz, info->hash.digest,
MXC_TPU_HASH_SHA256);
#endif
#ifdef WOLFSSL_SHA384
case WC_HASH_TYPE_SHA384:
return wc_MxcShaCbDispatch(&info->hash.sha384->msg,
&info->hash.sha384->used, &info->hash.sha384->len,
info->hash.sha384->heap, info->hash.in,
info->hash.inSz, info->hash.digest,
MXC_TPU_HASH_SHA384);
#endif
#ifdef WOLFSSL_SHA512
case WC_HASH_TYPE_SHA512:
return wc_MxcShaCbDispatch(&info->hash.sha512->msg,
&info->hash.sha512->used, &info->hash.sha512->len,
info->hash.sha512->heap, info->hash.in,
info->hash.inSz, info->hash.digest,
MXC_TPU_HASH_SHA512);
#endif
default:
return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
}
}
#endif
#ifdef WOLF_CRYPTO_CB_COPY
static int wc_MxcCopyCb(wc_CryptoInfo* info)
{
if (info == NULL || info->copy.src == NULL || info->copy.dst == NULL) {
return BAD_FUNC_ARG;
}
switch (info->copy.type) {
#ifdef MAX3266X_SHA_CB
#ifndef NO_SHA
case WC_HASH_TYPE_SHA:
return wc_MXC_TPU_SHA_Copy(info->copy.src, info->copy.dst,
sizeof(wc_Sha),
&((wc_Sha*)info->copy.dst)->msg,
&((wc_Sha*)info->copy.dst)->used,
&((wc_Sha*)info->copy.dst)->len,
((wc_Sha*)info->copy.dst)->heap,
((wc_Sha*)info->copy.src)->heap);
#endif
#ifdef WOLFSSL_SHA224
case WC_HASH_TYPE_SHA224:
return wc_MXC_TPU_SHA_Copy(info->copy.src, info->copy.dst,
sizeof(wc_Sha224),
&((wc_Sha224*)info->copy.dst)->msg,
&((wc_Sha224*)info->copy.dst)->used,
&((wc_Sha224*)info->copy.dst)->len,
((wc_Sha224*)info->copy.dst)->heap,
((wc_Sha224*)info->copy.src)->heap);
#endif
#ifndef NO_SHA256
case WC_HASH_TYPE_SHA256:
return wc_MXC_TPU_SHA_Copy(info->copy.src, info->copy.dst,
sizeof(wc_Sha256),
&((wc_Sha256*)info->copy.dst)->msg,
&((wc_Sha256*)info->copy.dst)->used,
&((wc_Sha256*)info->copy.dst)->len,
((wc_Sha256*)info->copy.dst)->heap,
((wc_Sha256*)info->copy.src)->heap);
#endif
#ifdef WOLFSSL_SHA384
case WC_HASH_TYPE_SHA384:
return wc_MXC_TPU_SHA_Copy(info->copy.src, info->copy.dst,
sizeof(wc_Sha384),
&((wc_Sha384*)info->copy.dst)->msg,
&((wc_Sha384*)info->copy.dst)->used,
&((wc_Sha384*)info->copy.dst)->len,
((wc_Sha384*)info->copy.dst)->heap,
((wc_Sha384*)info->copy.src)->heap);
#endif
#ifdef WOLFSSL_SHA512
case WC_HASH_TYPE_SHA512:
return wc_MXC_TPU_SHA_Copy(info->copy.src, info->copy.dst,
sizeof(wc_Sha512),
&((wc_Sha512*)info->copy.dst)->msg,
&((wc_Sha512*)info->copy.dst)->used,
&((wc_Sha512*)info->copy.dst)->len,
((wc_Sha512*)info->copy.dst)->heap,
((wc_Sha512*)info->copy.src)->heap);
#endif
#endif
default:
return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
}
}
#endif
#ifdef WOLF_CRYPTO_CB_FREE
static int wc_MxcFreeCb(wc_CryptoInfo* info)
{
if (info == NULL || info->free.obj == NULL) {
return BAD_FUNC_ARG;
}
switch (info->free.type) {
#ifdef MAX3266X_SHA_CB
#ifndef NO_SHA
case WC_HASH_TYPE_SHA:
wc_MXC_TPU_SHA_FreeCtx(info->free.obj, sizeof(wc_Sha),
&((wc_Sha*)info->free.obj)->msg,
&((wc_Sha*)info->free.obj)->used,
&((wc_Sha*)info->free.obj)->len,
((wc_Sha*)info->free.obj)->heap);
return 0;
#endif
#ifdef WOLFSSL_SHA224
case WC_HASH_TYPE_SHA224:
wc_MXC_TPU_SHA_FreeCtx(info->free.obj, sizeof(wc_Sha224),
&((wc_Sha224*)info->free.obj)->msg,
&((wc_Sha224*)info->free.obj)->used,
&((wc_Sha224*)info->free.obj)->len,
((wc_Sha224*)info->free.obj)->heap);
return 0;
#endif
#ifndef NO_SHA256
case WC_HASH_TYPE_SHA256:
wc_MXC_TPU_SHA_FreeCtx(info->free.obj, sizeof(wc_Sha256),
&((wc_Sha256*)info->free.obj)->msg,
&((wc_Sha256*)info->free.obj)->used,
&((wc_Sha256*)info->free.obj)->len,
((wc_Sha256*)info->free.obj)->heap);
return 0;
#endif
#ifdef WOLFSSL_SHA384
case WC_HASH_TYPE_SHA384:
wc_MXC_TPU_SHA_FreeCtx(info->free.obj, sizeof(wc_Sha384),
&((wc_Sha384*)info->free.obj)->msg,
&((wc_Sha384*)info->free.obj)->used,
&((wc_Sha384*)info->free.obj)->len,
((wc_Sha384*)info->free.obj)->heap);
return 0;
#endif
#ifdef WOLFSSL_SHA512
case WC_HASH_TYPE_SHA512:
wc_MXC_TPU_SHA_FreeCtx(info->free.obj, sizeof(wc_Sha512),
&((wc_Sha512*)info->free.obj)->msg,
&((wc_Sha512*)info->free.obj)->used,
&((wc_Sha512*)info->free.obj)->len,
((wc_Sha512*)info->free.obj)->heap);
return 0;
#endif
#endif
default:
return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
}
}
#endif
int wc_MxcCryptoCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
{
int ret;
(void)ctx;
(void)devIdArg;
if (info == NULL) {
return BAD_FUNC_ARG;
}
#ifdef DEBUG_CRYPTOCB
wc_CryptoCb_InfoString(info);
#endif
switch (info->algo_type) {
case WC_ALGO_TYPE_CIPHER:
MAX3266X_MSG("Using MXC AES HW Callback:");
ret = wc_MxcAesCryptoCb(info);
break;
#ifdef MAX3266X_SHA_CB
case WC_ALGO_TYPE_HASH:
MAX3266X_MSG("Using MXC SHA HW Callback:");
ret = wc_MxcShaCryptoCb(info);
break;
#endif
#ifdef WOLF_CRYPTO_CB_COPY
case WC_ALGO_TYPE_COPY:
MAX3266X_MSG("Using MXC Copy Callback:");
ret = wc_MxcCopyCb(info);
break;
#endif
#ifdef WOLF_CRYPTO_CB_FREE
case WC_ALGO_TYPE_FREE:
MAX3266X_MSG("Using MXC Free Callback:");
ret = wc_MxcFreeCb(info);
break;
#endif
default:
MAX3266X_MSG("Callback not support with MXC, using SW");
ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
}
return ret;
}
#endif
int wc_MXC_error(int *ret)
{
if (ret == NULL) {
return BAD_FUNC_ARG;
}
switch (*ret) {
case E_SUCCESS:
return 0;
case E_INVALID:
MAX3266X_MSG("HW Reported: E_INVALID Error");
*ret = WC_HW_E;
break;
case E_NULL_PTR:
MAX3266X_MSG("HW Reported: E_NULL_PTR Error");
*ret = BAD_FUNC_ARG;
break;
case E_BAD_PARAM:
MAX3266X_MSG("HW Reported: E_BAD_PARAM Error");
*ret = BAD_FUNC_ARG;
break;
case E_BAD_STATE:
MAX3266X_MSG("HW Reported: E_BAD_STATE Error");
*ret = WC_HW_E;
break;
default:
MAX3266X_MSG("HW Reported an Unknown Error");
*ret = WC_HW_E;
break;
}
return *ret;
}
#if defined(MAX3266X_RNG)
int wc_MXC_TRNG_Random(unsigned char* output, unsigned int sz)
{
int status;
if (output == NULL) {
return BAD_FUNC_ARG;
}
status = wolfSSL_HwRngMutexLock();
if (status != 0) {
return status;
}
status = MXC_TPU_Init(MXC_SYS_PERIPH_CLOCK_TRNG);
if (status == 0) {
MXC_TPU_TRNG_Read(MXC_TRNG, output, sz);
MAX3266X_MSG("TRNG Hardware Used");
}
else {
MAX3266X_MSG("TRNG Device did not initialize");
status = RNG_FAILURE_E;
}
wolfSSL_HwRngMutexUnLock();
return status;
}
#endif
#if defined(MAX3266X_AES)
int wc_MXC_TPU_AesEncrypt(const unsigned char* in, const unsigned char* iv,
const unsigned char* enc_key,
MXC_TPU_MODE_TYPE mode, unsigned int data_size,
unsigned char* out, unsigned int keySize)
{
int status;
if (in == NULL || iv == NULL || enc_key == NULL || out == NULL) {
return BAD_FUNC_ARG;
}
status = wolfSSL_HwAesMutexLock();
MAX3266X_MSG("AES HW Encryption");
if (status != 0) {
MAX3266X_MSG("Hardware Mutex Failure");
return status;
}
switch (keySize) {
case MXC_AES_KEY_128_LEN:
MXC_TPU_Cipher_Config(mode, MXC_TPU_CIPHER_AES128);
status = MXC_TPU_Cipher_AES_Encrypt((const char*)in,
(const char*)iv, (const char*)enc_key,
MXC_TPU_CIPHER_AES128, mode, data_size, (char*)out);
MAX3266X_MSG("AES HW Acceleration Used: 128 Bit");
break;
case MXC_AES_KEY_192_LEN:
MXC_TPU_Cipher_Config(mode, MXC_TPU_CIPHER_AES192);
status = MXC_TPU_Cipher_AES_Encrypt((const char*)in,
(const char*)iv, (const char*)enc_key,
MXC_TPU_CIPHER_AES192, mode, data_size, (char*)out);
MAX3266X_MSG("AES HW Acceleration Used: 192 Bit");
break;
case MXC_AES_KEY_256_LEN:
MXC_TPU_Cipher_Config(mode, MXC_TPU_CIPHER_AES256);
status = MXC_TPU_Cipher_AES_Encrypt((const char*)in,
(const char*)iv, (const char*)enc_key,
MXC_TPU_CIPHER_AES256, mode, data_size, (char*)out);
MAX3266X_MSG("AES HW Acceleration Used: 256 Bit");
break;
default:
MAX3266X_MSG("AES HW ERROR: Length Not Supported");
wolfSSL_HwAesMutexUnLock();
return BAD_FUNC_ARG;
}
wolfSSL_HwAesMutexUnLock();
if (status != 0) {
MAX3266X_MSG("AES HW Acceleration Error Occurred");
return WC_HW_E;
}
return status;
}
#if defined(WOLF_CRYPTO_CB)
#ifdef HAVE_AES_ECB
int wc_MxcCb_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
int status;
word32 keySize;
if ((in == NULL) || (out == NULL) || (aes == NULL)) {
return BAD_FUNC_ARG;
}
status = wc_AesGetKeySize(aes, &keySize);
if (status != 0) {
return status;
}
status = wc_MXC_TPU_AesEncrypt(in, (byte*)aes->reg, (byte*)aes->devKey,
MXC_TPU_MODE_ECB, sz, out, keySize);
return status;
}
#endif
#ifdef HAVE_AES_CBC
int wc_MxcCb_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
word32 keySize;
int status;
byte *iv;
if ((in == NULL) || (out == NULL) || (aes == NULL)) {
return BAD_FUNC_ARG;
}
if (sz % WC_AES_BLOCK_SIZE) {
#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS
return BAD_LENGTH_E;
#else
return BAD_FUNC_ARG;
#endif
}
if (sz == 0) {
return 0;
}
iv = (byte*)aes->reg;
status = wc_AesGetKeySize(aes, &keySize);
if (status != 0) {
return status;
}
status = wc_MXC_TPU_AesEncrypt(in, iv, (byte*)aes->devKey,
MXC_TPU_MODE_CBC, sz, out,
(unsigned int)keySize);
if (status == 0) {
XMEMCPY(iv, out + sz - WC_AES_BLOCK_SIZE, WC_AES_BLOCK_SIZE);
}
return status;
}
#endif
#endif
#ifdef HAVE_AES_DECRYPT
int wc_MXC_TPU_AesDecrypt(const unsigned char* in, const unsigned char* iv,
const unsigned char* dec_key,
MXC_TPU_MODE_TYPE mode, unsigned int data_size,
unsigned char* out, unsigned int keySize)
{
int status;
if (in == NULL || iv == NULL || dec_key == NULL || out == NULL) {
return BAD_FUNC_ARG;
}
status = wolfSSL_HwAesMutexLock();
if (status != 0) {
return status;
}
switch (keySize) {
case MXC_AES_KEY_128_LEN:
MXC_TPU_Cipher_Config(mode, MXC_TPU_CIPHER_AES128);
status = MXC_TPU_Cipher_AES_Decrypt((const char*)in,
(const char*)iv, (const char*)dec_key,
MXC_TPU_CIPHER_AES128, mode, data_size, (char*)out);
MAX3266X_MSG("AES HW Acceleration Used: 128 Bit");
break;
case MXC_AES_KEY_192_LEN:
MXC_TPU_Cipher_Config(mode, MXC_TPU_CIPHER_AES192);
status = MXC_TPU_Cipher_AES_Decrypt((const char*)in,
(const char*)iv, (const char*)dec_key,
MXC_TPU_CIPHER_AES192, mode, data_size, (char*)out);
MAX3266X_MSG("AES HW Acceleration Used: 192 Bit");
break;
case MXC_AES_KEY_256_LEN:
MXC_TPU_Cipher_Config(mode, MXC_TPU_CIPHER_AES256);
status = MXC_TPU_Cipher_AES_Decrypt((const char*)in,
(const char*)iv, (const char*)dec_key,
MXC_TPU_CIPHER_AES256, mode, data_size, (char*)out);
MAX3266X_MSG("AES HW Acceleration Used: 256 Bit");
break;
default:
MAX3266X_MSG("AES HW ERROR: Length Not Supported");
wolfSSL_HwAesMutexUnLock();
return BAD_FUNC_ARG;
}
wolfSSL_HwAesMutexUnLock();
if (status != 0) {
MAX3266X_MSG("AES HW Acceleration Error Occurred");
return WC_HW_E;
}
return status;
}
#if defined(WOLF_CRYPTO_CB)
#ifdef HAVE_AES_ECB
int wc_MxcCb_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
int status;
word32 keySize;
if ((in == NULL) || (out == NULL) || (aes == NULL)) {
return BAD_FUNC_ARG;
}
status = wc_AesGetKeySize(aes, &keySize);
if (status != 0) {
return status;
}
status = wc_MXC_TPU_AesDecrypt(in, (byte*)aes->reg, (byte*)aes->devKey,
MXC_TPU_MODE_ECB, sz, out, keySize);
return status;
}
#endif
#ifdef HAVE_AES_CBC
int wc_MxcCb_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
word32 keySize;
int status;
byte *iv;
byte temp_block[WC_AES_BLOCK_SIZE];
if ((in == NULL) || (out == NULL) || (aes == NULL)) {
return BAD_FUNC_ARG;
}
if (sz % WC_AES_BLOCK_SIZE) {
#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS
return BAD_LENGTH_E;
#else
return BAD_FUNC_ARG;
#endif
}
if (sz == 0) {
return 0;
}
iv = (byte*)aes->reg;
status = wc_AesGetKeySize(aes, &keySize);
if (status != 0) {
return status;
}
XMEMCPY(temp_block, in + sz - WC_AES_BLOCK_SIZE, WC_AES_BLOCK_SIZE);
status = wc_MXC_TPU_AesDecrypt(in, iv, (byte*)aes->devKey,
MXC_TPU_MODE_CBC, sz, out,
keySize);
if (status == 0) {
XMEMCPY(iv, temp_block, WC_AES_BLOCK_SIZE);
}
return status;
}
#endif
#endif
#endif
#endif
#if defined(MAX3266X_SHA) || defined(MAX3266X_SHA_CB)
int wc_MXC_TPU_SHA_GetDigest(const unsigned char* msg, unsigned int msgSz,
unsigned char* digest,
MXC_TPU_HASH_TYPE algo)
{
if (digest == NULL) {
return BAD_FUNC_ARG;
}
if (msg == NULL && msgSz == 0) {
switch (algo) {
#ifndef NO_SHA
case MXC_TPU_HASH_SHA1:
XMEMCPY(digest, MXC_EMPTY_DIGEST_SHA1, WC_SHA_DIGEST_SIZE);
break;
#endif
#ifdef WOLFSSL_SHA224
case MXC_TPU_HASH_SHA224:
XMEMCPY(digest, MXC_EMPTY_DIGEST_SHA224, WC_SHA224_DIGEST_SIZE);
break;
#endif
#ifndef NO_SHA256
case MXC_TPU_HASH_SHA256:
XMEMCPY(digest, MXC_EMPTY_DIGEST_SHA256, WC_SHA256_DIGEST_SIZE);
break;
#endif
#ifdef WOLFSSL_SHA384
case MXC_TPU_HASH_SHA384:
XMEMCPY(digest, MXC_EMPTY_DIGEST_SHA384, WC_SHA384_DIGEST_SIZE);
break;
#endif
#ifdef WOLFSSL_SHA512
case MXC_TPU_HASH_SHA512:
XMEMCPY(digest, MXC_EMPTY_DIGEST_SHA512, WC_SHA512_DIGEST_SIZE);
break;
#endif
default:
return BAD_FUNC_ARG;
}
return 1;
}
return 0;
}
int wc_MXC_TPU_SHA_GetHash(const unsigned char* msg, unsigned int msgSz,
unsigned char* digest,
MXC_TPU_HASH_TYPE algo)
{
int status;
if (digest == NULL || (msg == NULL && msgSz != 0)) {
return BAD_FUNC_ARG;
}
status = wc_MXC_TPU_SHA_GetDigest(msg, msgSz, digest, algo);
if (status == 1) {
return 0;
}
else if (status == 0) {
status = wolfSSL_HwHashMutexLock();
if (status != 0) {
return status;
}
MXC_TPU_Init(MXC_SYS_PERIPH_CLOCK_TPU);
MXC_TPU_Hash_Config(algo);
status = MXC_TPU_Hash_SHA((const char *)msg, algo, msgSz,
(char *)digest);
MAX3266X_MSG("SHA HW Acceleration Used");
wolfSSL_HwHashMutexUnLock();
if (wc_MXC_error(&status) != 0) {
MAX3266X_MSG("SHA HW Error Occurred");
return status;
}
}
return status;
}
void wc_MXC_TPU_SHA_Free(byte** msg, word32* used, word32* len, void* heap)
{
if (msg == NULL) {
return;
}
if (*msg != NULL) {
XFREE(*msg, heap, DYNAMIC_TYPE_TMP_BUFFER);
*msg = NULL;
}
if (used != NULL) {
*used = 0;
}
if (len != NULL) {
*len = 0;
}
}
void wc_MXC_TPU_SHA_FreeCtx(void* ctx, word32 ctxSz, byte** msg, word32* used,
word32* len, void* heap)
{
if (ctx == NULL) {
return;
}
wc_MXC_TPU_SHA_Free(msg, used, len, heap);
XMEMSET(ctx, 0, ctxSz);
}
int wc_MXC_TPU_SHA_Copy(void* src, void* dst, word32 ctxSz,
byte** dstMsg, word32* dstUsed, word32* dstLen,
void* dstHeap, void* srcHeap)
{
byte* srcBuf = NULL;
if (src == NULL || dst == NULL || dstMsg == NULL ||
dstUsed == NULL || dstLen == NULL || ctxSz == 0) {
return BAD_FUNC_ARG;
}
wc_MXC_TPU_SHA_Free(dstMsg, dstUsed, dstLen, dstHeap);
XMEMCPY(dst, src, ctxSz);
if (*dstMsg != NULL) {
srcBuf = *dstMsg;
*dstMsg = (byte*)XMALLOC(*dstLen, srcHeap, DYNAMIC_TYPE_TMP_BUFFER);
if (*dstMsg == NULL) {
return MEMORY_E;
}
XMEMCPY(*dstMsg, srcBuf, *dstUsed);
}
return 0;
}
int wc_MXC_TPU_SHA_Final(unsigned char** msg, unsigned int* used,
unsigned int* len, void* heap,
unsigned char* digest,
MXC_TPU_HASH_TYPE algo)
{
int status;
if (msg == NULL || used == NULL || len == NULL || digest == NULL) {
return BAD_FUNC_ARG;
}
status = wc_MXC_TPU_SHA_GetHash(*msg, *used, digest, algo);
wc_MXC_TPU_SHA_Free(msg, used, len, heap);
return status;
}
#ifndef MAX3266X_SHA_CB
#if !defined(NO_SHA)
WOLFSSL_API int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
{
if (sha == NULL) {
return BAD_FUNC_ARG;
}
(void)devId;
XMEMSET(sha, 0, sizeof(*sha));
sha->heap = heap;
return 0;
}
WOLFSSL_API int wc_ShaUpdate(wc_Sha* sha, const unsigned char* data,
unsigned int len)
{
if (sha == NULL || (data == NULL && len > 0)) {
return BAD_FUNC_ARG;
}
return _wc_Hash_Grow(&sha->msg, &sha->used, &sha->len,
data, (int)len, sha->heap);
}
WOLFSSL_API int wc_ShaFinal(wc_Sha* sha, unsigned char* hash)
{
if (sha == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
return wc_MXC_TPU_SHA_Final(&sha->msg, &sha->used, &sha->len,
sha->heap, hash, MXC_TPU_HASH_SHA1);
}
WOLFSSL_API int wc_ShaGetHash(wc_Sha* sha, unsigned char* hash)
{
if (sha == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
return wc_MXC_TPU_SHA_GetHash((const unsigned char*)sha->msg,
sha->used, hash, MXC_TPU_HASH_SHA1);
}
WOLFSSL_API int wc_ShaCopy(wc_Sha* src, wc_Sha* dst)
{
if (src == NULL || dst == NULL) {
return BAD_FUNC_ARG;
}
return wc_MXC_TPU_SHA_Copy(src, dst, sizeof(wc_Sha),
&dst->msg, &dst->used, &dst->len,
dst->heap, src->heap);
}
WOLFSSL_API void wc_ShaFree(wc_Sha* sha)
{
if (sha == NULL) {
return;
}
wc_MXC_TPU_SHA_FreeCtx(sha, sizeof(wc_Sha), &sha->msg, &sha->used,
&sha->len, sha->heap);
}
#endif
#if defined(WOLFSSL_SHA224)
WOLFSSL_API int wc_InitSha224_ex(wc_Sha224* sha224, void* heap, int devId)
{
if (sha224 == NULL) {
return BAD_FUNC_ARG;
}
(void)devId;
XMEMSET(sha224, 0, sizeof(*sha224));
sha224->heap = heap;
return 0;
}
WOLFSSL_API int wc_InitSha224(wc_Sha224* sha224)
{
return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID);
}
WOLFSSL_API int wc_Sha224Update(wc_Sha224* sha224, const unsigned char* data,
unsigned int len)
{
if (sha224 == NULL || (data == NULL && len > 0)) {
return BAD_FUNC_ARG;
}
return _wc_Hash_Grow(&sha224->msg, &sha224->used, &sha224->len,
data, (int)len, sha224->heap);
}
WOLFSSL_API int wc_Sha224Final(wc_Sha224* sha224, unsigned char* hash)
{
if (sha224 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
return wc_MXC_TPU_SHA_Final(&sha224->msg, &sha224->used, &sha224->len,
sha224->heap, hash,
MXC_TPU_HASH_SHA224);
}
WOLFSSL_API int wc_Sha224GetHash(wc_Sha224* sha224, unsigned char* hash)
{
if (sha224 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
return wc_MXC_TPU_SHA_GetHash((const unsigned char*)sha224->msg,
sha224->used, hash,
MXC_TPU_HASH_SHA224);
}
WOLFSSL_API int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst)
{
if (src == NULL || dst == NULL) {
return BAD_FUNC_ARG;
}
return wc_MXC_TPU_SHA_Copy(src, dst, sizeof(wc_Sha224),
&dst->msg, &dst->used, &dst->len,
dst->heap, src->heap);
}
WOLFSSL_API void wc_Sha224Free(wc_Sha224* sha224)
{
if (sha224 == NULL) {
return;
}
wc_MXC_TPU_SHA_FreeCtx(sha224, sizeof(wc_Sha224), &sha224->msg,
&sha224->used, &sha224->len,
sha224->heap);
}
#endif
#if !defined(NO_SHA256)
WOLFSSL_API int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
{
if (sha256 == NULL) {
return BAD_FUNC_ARG;
}
(void)devId;
XMEMSET(sha256, 0, sizeof(*sha256));
sha256->heap = heap;
return 0;
}
WOLFSSL_API int wc_InitSha256(wc_Sha256* sha256)
{
return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID);
}
WOLFSSL_API int wc_Sha256Update(wc_Sha256* sha256, const unsigned char* data,
unsigned int len)
{
if (sha256 == NULL || (data == NULL && len > 0)) {
return BAD_FUNC_ARG;
}
return _wc_Hash_Grow(&sha256->msg, &sha256->used, &sha256->len,
data, (int)len, sha256->heap);
}
WOLFSSL_API int wc_Sha256Final(wc_Sha256* sha256, unsigned char* hash)
{
if (sha256 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
return wc_MXC_TPU_SHA_Final(&sha256->msg, &sha256->used, &sha256->len,
sha256->heap, hash,
MXC_TPU_HASH_SHA256);
}
WOLFSSL_API int wc_Sha256GetHash(wc_Sha256* sha256, unsigned char* hash)
{
if (sha256 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
return wc_MXC_TPU_SHA_GetHash((const unsigned char*)sha256->msg,
sha256->used, hash,
MXC_TPU_HASH_SHA256);
}
WOLFSSL_API int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
{
if (src == NULL || dst == NULL) {
return BAD_FUNC_ARG;
}
return wc_MXC_TPU_SHA_Copy(src, dst, sizeof(wc_Sha256),
&dst->msg, &dst->used, &dst->len,
dst->heap, src->heap);
}
WOLFSSL_API void wc_Sha256Free(wc_Sha256* sha256)
{
if (sha256 == NULL) {
return;
}
wc_MXC_TPU_SHA_FreeCtx(sha256, sizeof(wc_Sha256), &sha256->msg,
&sha256->used, &sha256->len,
sha256->heap);
}
#endif
#if defined(WOLFSSL_SHA384)
WOLFSSL_API int wc_InitSha384_ex(wc_Sha384* sha384, void* heap, int devId)
{
if (sha384 == NULL) {
return BAD_FUNC_ARG;
}
(void)devId;
XMEMSET(sha384, 0, sizeof(*sha384));
sha384->heap = heap;
return 0;
}
WOLFSSL_API int wc_InitSha384(wc_Sha384* sha384)
{
return wc_InitSha384_ex(sha384, NULL, INVALID_DEVID);
}
WOLFSSL_API int wc_Sha384Update(wc_Sha384* sha384, const unsigned char* data,
unsigned int len)
{
if (sha384 == NULL || (data == NULL && len > 0)) {
return BAD_FUNC_ARG;
}
return _wc_Hash_Grow(&sha384->msg, &sha384->used, &sha384->len,
data, (int)len, sha384->heap);
}
WOLFSSL_API int wc_Sha384Final(wc_Sha384* sha384, unsigned char* hash)
{
if (sha384 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
return wc_MXC_TPU_SHA_Final(&sha384->msg, &sha384->used, &sha384->len,
sha384->heap, hash,
MXC_TPU_HASH_SHA384);
}
WOLFSSL_API int wc_Sha384GetHash(wc_Sha384* sha384, unsigned char* hash)
{
if (sha384 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
return wc_MXC_TPU_SHA_GetHash((const unsigned char*)sha384->msg,
sha384->used, hash,
MXC_TPU_HASH_SHA384);
}
WOLFSSL_API int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst)
{
if (src == NULL || dst == NULL) {
return BAD_FUNC_ARG;
}
return wc_MXC_TPU_SHA_Copy(src, dst, sizeof(wc_Sha384),
&dst->msg, &dst->used, &dst->len,
dst->heap, src->heap);
}
WOLFSSL_API void wc_Sha384Free(wc_Sha384* sha384)
{
if (sha384 == NULL) {
return;
}
wc_MXC_TPU_SHA_FreeCtx(sha384, sizeof(wc_Sha384), &sha384->msg,
&sha384->used, &sha384->len,
sha384->heap);
}
#endif
#if defined(WOLFSSL_SHA512)
WOLFSSL_API int wc_InitSha512_ex(wc_Sha512* sha512, void* heap, int devId)
{
if (sha512 == NULL) {
return BAD_FUNC_ARG;
}
(void)devId;
XMEMSET(sha512, 0, sizeof(*sha512));
sha512->heap = heap;
return 0;
}
WOLFSSL_API int wc_InitSha512(wc_Sha512* sha512)
{
return wc_InitSha512_ex(sha512, NULL, INVALID_DEVID);
}
WOLFSSL_API int wc_Sha512Update(wc_Sha512* sha512, const unsigned char* data,
unsigned int len)
{
if (sha512 == NULL || (data == NULL && len > 0)) {
return BAD_FUNC_ARG;
}
return _wc_Hash_Grow(&sha512->msg, &sha512->used, &sha512->len,
data, (int)len, sha512->heap);
}
WOLFSSL_API int wc_Sha512Final(wc_Sha512* sha512, unsigned char* hash)
{
if (sha512 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
return wc_MXC_TPU_SHA_Final(&sha512->msg, &sha512->used, &sha512->len,
sha512->heap, hash,
MXC_TPU_HASH_SHA512);
}
WOLFSSL_API int wc_Sha512GetHash(wc_Sha512* sha512, unsigned char* hash)
{
if (sha512 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
return wc_MXC_TPU_SHA_GetHash((const unsigned char*)sha512->msg,
sha512->used, hash,
MXC_TPU_HASH_SHA512);
}
WOLFSSL_API int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst)
{
if (src == NULL || dst == NULL) {
return BAD_FUNC_ARG;
}
return wc_MXC_TPU_SHA_Copy(src, dst, sizeof(wc_Sha512),
&dst->msg, &dst->used, &dst->len,
dst->heap, src->heap);
}
WOLFSSL_API void wc_Sha512Free(wc_Sha512* sha512)
{
if (sha512 == NULL) {
return;
}
wc_MXC_TPU_SHA_FreeCtx(sha512, sizeof(wc_Sha512), &sha512->msg,
&sha512->used, &sha512->len,
sha512->heap);
}
#endif
#endif
#endif
#if defined(MAX3266X_MATH)
int wc_MXC_MAA_init(unsigned int len)
{
int status;
MAX3266X_MSG("Setting Hardware Mutex and Starting MAA");
status = wolfSSL_HwPkMutexLock();
if (status == 0) {
status = MXC_TPU_MAA_Init(len);
}
return wc_MXC_error(&status);
}
int wc_MXC_MAA_Shutdown(void)
{
int status;
MAX3266X_MSG("Unlocking Hardware Mutex and Shutting Down MAA");
status = MXC_TPU_MAA_Shutdown();
if (status == E_BAD_PARAM) {
status = WC_HW_E;
}
wolfSSL_HwPkMutexUnLock();
return wc_MXC_error(&status);
}
int wc_MXC_MAA_adjustUsed(unsigned int *array, unsigned int length)
{
int i, lastNonZeroIndex;
lastNonZeroIndex = -1;
for (i = 0; i < length; i++) {
if (array[i] != 0) {
lastNonZeroIndex = i;
}
}
return (lastNonZeroIndex + 1);
}
unsigned int wc_MXC_MAA_Largest(unsigned int count, ...)
{
va_list args;
int i;
unsigned int largest, num;
va_start(args, count);
largest = va_arg(args, unsigned int);
for (i = 1; i < count; i++) {
num = va_arg(args, unsigned int);
if (num > largest) {
largest = num;
}
}
va_end(args);
return largest;
}
int wc_MXC_MAA_Fallback(unsigned int count, ...)
{
va_list args;
int num, i;
va_start(args, count);
for (i = 0; i < count; i++) {
num = va_arg(args, unsigned int);
if (num > MXC_MAA_MAX_SIZE) {
MAX3266X_MSG("HW Falling Back to Software");
return 1;
}
}
va_end(args);
MAX3266X_MSG("HW Can Handle Input");
return 0;
}
int wc_MXC_MAA_zeroPad(mp_int* multiplier, mp_int* multiplicand,
mp_int* exp, mp_int* mod, mp_int* result,
MXC_TPU_MAA_TYPE clc, unsigned int length)
{
mp_digit* zero_tmp;
MAX3266X_MSG("Zero Padding Buffers for Hardware");
if (length > MXC_MAA_MAX_SIZE) {
MAX3266X_MSG("Hardware cannot exceed 2048 bit input");
return BAD_FUNC_ARG;
}
if ((result == NULL) || (multiplier == NULL) || (multiplicand == NULL) ||
((exp == NULL) && (clc == MXC_TPU_MAA_EXP)) || (mod == NULL)) {
return BAD_FUNC_ARG;
}
zero_tmp = (mp_digit*)XMALLOC(multiplier->size*sizeof(mp_digit), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (zero_tmp == NULL) {
MAX3266X_MSG("NULL pointer found after XMALLOC call");
return MEMORY_E;
}
XMEMSET(zero_tmp, 0x00, multiplier->size*sizeof(mp_digit));
switch ((char)clc) {
case MXC_TPU_MAA_EXP:
if (XMEMCMP(zero_tmp, exp, (exp->used*sizeof(mp_digit))) == 0) {
XFREE(zero_tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
MAX3266X_MSG("Cannot use Value 0 for Exp");
return BAD_FUNC_ARG;
}
if ((exp != NULL) && (clc == MXC_TPU_MAA_EXP)) {
if ((exp->dp != NULL) && (exp->used < length)) {
MAX3266X_MSG("Zero Padding Exp Buffer");
XMEMSET(exp->dp + exp->used, 0x00,
sizeof(int) *(length - exp->used));
}
}
case MXC_TPU_MAA_SQ:
case MXC_TPU_MAA_MUL:
case MXC_TPU_MAA_SQMUL:
case MXC_TPU_MAA_ADD:
case MXC_TPU_MAA_SUB:
if (XMEMCMP(zero_tmp, mod, (exp->used*sizeof(mp_digit))) == 0) {
XFREE(zero_tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
MAX3266X_MSG("Cannot use Value 0 for Exp");
return BAD_FUNC_ARG;
}
if ((multiplier->dp != NULL) && (multiplier->used < length)) {
MAX3266X_MSG("Zero Padding Multiplier Buffer");
XMEMSET(multiplier->dp + multiplier->used, 0x00,
sizeof(int) * (length - multiplier->used));
}
if ((multiplicand->dp != NULL) && (multiplicand->used < length)) {
MAX3266X_MSG("Zero Padding Multiplicand Buffer");
XMEMSET(multiplicand->dp + multiplicand->used, 0x00,
sizeof(int) * (length - multiplicand->used));
}
if ((mod->dp != NULL) && (mod->used < length)) {
MAX3266X_MSG("Zero Padding Mod Buffer");
XMEMSET(mod->dp + mod->used, 0x00,
sizeof(int) *(length - mod->used));
}
break;
default:
XFREE(zero_tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return BAD_FUNC_ARG;
}
XFREE(zero_tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (result->dp != NULL) {
ForceZero(result->dp, sizeof(int)*(length));
result->used = length;
}
return 0;
}
int wc_MXC_MAA_math(mp_int* multiplier, mp_int* multiplicand, mp_int* exp,
mp_int* mod, mp_int* result,
MXC_TPU_MAA_TYPE clc)
{
int ret;
int length;
mp_int* result_tmp_ptr;
mp_int result_tmp;
if (multiplier == NULL || multiplicand == NULL || mod == NULL ||
(exp == NULL && clc == MXC_TPU_MAA_EXP) || result == NULL) {
return BAD_FUNC_ARG;
}
if ((multiplier == result) || (multiplicand == result) || (exp == result) ||
(mod == result)) {
MAX3266X_MSG("Creating Temp Result Buffer for Hardware");
result_tmp_ptr = &result_tmp;
}
else {
result_tmp_ptr = result;
}
if (result_tmp_ptr == NULL) {
MAX3266X_MSG("tmp ptr is null");
return MP_VAL;
}
if (clc == MXC_TPU_MAA_EXP) {
length = wc_MXC_MAA_Largest(5, multiplier->used, multiplicand->used,
exp->used, mod->used, result->used);
}
else {
length = wc_MXC_MAA_Largest(4, multiplier->used, multiplicand->used,
mod->used, result->used);
}
ret = wc_MXC_MAA_zeroPad(multiplier, multiplicand, exp, mod, result_tmp_ptr,
clc, length);
if (ret != 0) {
MAX3266X_MSG("Zero Padding Failed");
return ret;
}
ret = wc_MXC_MAA_init(length*sizeof(mp_digit)*8);
if (ret != 0) {
MAX3266X_MSG("HW Init Failed");
wolfSSL_HwPkMutexUnLock();
return ret;
}
MAX3266X_MSG("Starting Computation in MAA");
ret = MXC_TPU_MAA_Compute(clc, (char *)(multiplier->dp),
(char *)(multiplicand->dp),
(char *)((exp == NULL) ? NULL: exp->dp),
(char *)(mod->dp),
(int *)(result_tmp_ptr->dp),
(length*sizeof(mp_digit)));
MAX3266X_MSG("MAA Finished Computation");
if (wc_MXC_error(&ret) != 0) {
MAX3266X_MSG("HW Computation Error");
wolfSSL_HwPkMutexUnLock();
return ret;
}
ret = wc_MXC_MAA_Shutdown();
if (ret != 0) {
MAX3266X_MSG("HW Shutdown Failure");
return ret;
}
if ((multiplier == result) || (multiplicand == result) || (exp == result) ||
(mod == result)) {
mp_copy(result_tmp_ptr, result);
ForceZero(result_tmp_ptr, sizeof(mp_int));
}
result->used = wc_MXC_MAA_adjustUsed(result->dp, length);
return ret;
}
int wc_MXC_MAA_expmod(mp_int* base, mp_int* exp, mp_int* mod,
mp_int* result)
{
mp_int multiplicand;
if (base == NULL || exp == NULL || mod == NULL || result == NULL) {
return BAD_FUNC_ARG;
}
XMEMSET(&multiplicand, 0, sizeof(mp_int));
multiplicand.dp[0] = 0x01;
multiplicand.used = mod->used;
MAX3266X_MSG("Preparing exptmod MAA HW Call");
return wc_MXC_MAA_math(base, &multiplicand, exp, mod, result,
MXC_TPU_MAA_EXP);
}
int wc_MXC_MAA_sqrmod(mp_int* multiplier, mp_int* mod, mp_int* result)
{
mp_int multiplicand;
if (multiplier == NULL || mod == NULL || result == NULL) {
return BAD_FUNC_ARG;
}
XMEMSET(&multiplicand, 0, sizeof(mp_int));
multiplicand.dp[0] = 0x01;
multiplicand.used = mod->used;
MAX3266X_MSG("Preparing sqrmod MAA HW Call");
return wc_MXC_MAA_math(multiplier, &multiplicand, NULL, mod, result,
MXC_TPU_MAA_SQ);
}
int wc_MXC_MAA_mulmod(mp_int* multiplier, mp_int* multiplicand, mp_int* mod,
mp_int* result)
{
if (multiplier == NULL || multiplicand == NULL || mod == NULL ||
result == NULL) {
return BAD_FUNC_ARG;
}
MAX3266X_MSG("Preparing mulmod MAA HW Call");
return wc_MXC_MAA_math(multiplier, multiplicand, NULL, mod, result,
MXC_TPU_MAA_MUL);
}
int wc_MXC_MAA_sqrmulmod(mp_int* multiplier, mp_int* multiplicand,
mp_int* exp, mp_int* mod, mp_int* result)
{
if (multiplier == NULL || multiplicand == NULL || exp == NULL ||
mod == NULL || result == NULL) {
return BAD_FUNC_ARG;
}
MAX3266X_MSG("Preparing sqrmulmod MAA HW Call");
return wc_MXC_MAA_math(multiplier, multiplicand, NULL, mod, result,
MXC_TPU_MAA_SQMUL);
}
int wc_MXC_MAA_addmod(mp_int* multiplier, mp_int* multiplicand, mp_int* mod,
mp_int* result)
{
if (multiplier == NULL || multiplicand == NULL || mod == NULL ||
result == NULL) {
return BAD_FUNC_ARG;
}
MAX3266X_MSG("Preparing addmod MAA HW Call");
return wc_MXC_MAA_math(multiplier, multiplicand, NULL, mod, result,
MXC_TPU_MAA_ADD);
}
int wc_MXC_MAA_submod(mp_int* multiplier, mp_int* multiplicand, mp_int* mod,
mp_int* result)
{
if (multiplier == NULL || multiplicand == NULL || mod == NULL ||
result == NULL) {
return BAD_FUNC_ARG;
}
MAX3266X_MSG("Preparing submod MAA HW Call");
if ((mod->used < multiplier->used) || (mod->used < multiplicand->used)) {
MAX3266X_MSG("HW Limitation: Defaulting back to software");
return mxc_submod(multiplier, multiplicand, mod, result);
}
else {
return wc_MXC_MAA_math(multiplier, multiplicand, NULL, mod, result,
MXC_TPU_MAA_SUB);
}
}
int hw_mulmod(mp_int* multiplier, mp_int* multiplicand, mp_int* mod,
mp_int* result)
{
if (multiplier == NULL || multiplicand == NULL || mod == NULL ||
result == NULL) {
return MP_VAL;
}
if ((multiplier->used == 0) || (multiplicand->used == 0)) {
mp_zero(result);
return 0;
}
else {
if (wc_MXC_MAA_Fallback(3, multiplier->used, mod->used,
multiplicand->used) != 0) {
return mxc_mulmod(multiplier, multiplicand, mod, result);
}
else {
return wc_MXC_MAA_mulmod(multiplier, multiplicand, mod, result);
}
}
}
int hw_addmod(mp_int* a, mp_int* b, mp_int* mod, mp_int* result)
{
int err = MP_OKAY;
if ((a == NULL) || (b == NULL) || (mod == NULL) || (result == NULL)) {
err = MP_VAL;
}
if (err == MP_OKAY) {
if (wc_MXC_MAA_Fallback(3, a->used, b->used, mod->used) != 0) {
err = mxc_addmod(a, b, mod, result);
}
else {
err = wc_MXC_MAA_addmod(a, b, mod, result);
}
}
return err;
}
int hw_submod(mp_int* a, mp_int* b, mp_int* mod, mp_int* result)
{
int err = MP_OKAY;
if ((a == NULL) || (b == NULL) || (mod == NULL) || (result == NULL)) {
err = MP_VAL;
}
if (err == MP_OKAY) {
if (wc_MXC_MAA_Fallback(3, a->used, b->used, mod->used) != 0) {
err = mxc_submod(a, b, mod, result);
}
else{
err = wc_MXC_MAA_submod(a, b, mod, result);
}
}
return err;
}
int hw_exptmod(mp_int* base, mp_int* exp, mp_int* mod, mp_int* result)
{
int err = MP_OKAY;
if ((base == NULL) || (exp == NULL) || (mod == NULL) || (result == NULL)) {
err = MP_VAL;
}
if (err == MP_OKAY) {
if ((mod->used < exp->used) || (mod->used < base->used)) {
err = mxc_exptmod(base, exp, mod, result);
}
else if (wc_MXC_MAA_Fallback(3, base->used, exp->used, mod->used)
!= 0) {
return mxc_exptmod(base, exp, mod, result);
}
else{
err = wc_MXC_MAA_expmod(base, exp, mod, result);
}
}
return err;
}
int hw_mod(mp_int* a, mp_int* mod, mp_int* result)
{
mp_int b;
if (a == NULL || mod == NULL || result == NULL) {
return MP_VAL;
}
if (wc_MXC_MAA_Fallback(2, a->used, mod->used) != 0) {
return mxc_mod(a, mod, result);
}
XMEMSET(&b, 0, sizeof(mp_int));
b.used = mod->used;
return hw_submod(a, &b, mod, result);
}
int hw_sqrmod(mp_int* base, mp_int* mod, mp_int* result)
{
if (base == NULL || mod == NULL || result == NULL) {
return MP_VAL;
}
if (base->used == 0) {
mp_zero(result);
return 0;
}
return wc_MXC_MAA_sqrmod(base, mod, result);
}
#endif
#if defined(MAX3266X_RTC)
int wc_MXC_RTC_Init(void)
{
if (MXC_RTC_Init(0, 0) != E_NO_ERROR) {
return WC_HW_E;
}
if (MXC_RTC_DisableInt(MXC_RTC_INT_EN_LONG) == E_BUSY) {
return WC_HW_E;
}
if (MXC_RTC_SquareWaveStart(MXC_RTC_F_512HZ) == E_BUSY) {
return E_BUSY;
}
if (MXC_RTC_Start() != E_NO_ERROR) {
return WC_HW_E;
}
return 0;
}
int wc_MXC_RTC_Reset(void)
{
if (MXC_RTC_Stop() != E_NO_ERROR) {
return WC_HW_E;
}
if (wc_MXC_RTC_Init() != E_NO_ERROR) {
return WC_HW_E;
}
return 0;
}
void wc_MXC_RTC_GetRTCValue(int32_t (*rtcGetFunction)(uint32_t*),
uint32_t* outValue, int32_t* err)
{
*err = rtcGetFunction(outValue);
while (*err != E_NO_ERROR) {
*err = rtcGetFunction(outValue);
}
}
double wc_MXC_RTC_Time(void)
{
int32_t err;
uint32_t rtc_seconds, rtc_subseconds;
wc_MXC_RTC_GetRTCValue((int32_t (*)(uint32_t*))MXC_RTC_GetSubSeconds,
&rtc_subseconds, &err);
if (err != E_NO_ERROR) {
return (double)err;
}
wc_MXC_RTC_GetRTCValue((int32_t (*)(uint32_t*))MXC_RTC_GetSeconds,
&rtc_seconds, &err);
if (err != E_NO_ERROR) {
return (double)err;
}
return ((double)rtc_seconds + ((double)rtc_subseconds / 4096));
}
#endif
#endif