Initial PR for MAX32665 and MAX32666 TPU HW Support

This commit is contained in:
msi-debian
2024-07-08 08:51:24 -06:00
committed by ZackLabPC
parent d796d8c107
commit 2e8cf39feb
15 changed files with 1493 additions and 16 deletions

View File

@@ -14254,6 +14254,14 @@ void bench_sphincsKeySign(byte level, byte optim)
return (double)tv.SECONDS + (double)tv.MILLISECONDS / 1000;
}
#elif (defined(WOLFSSL_MAX3266X_OLD) || defined(WOLFSSL_MAX3266X)) \
&& defined(MAX3266X_RTC)
double current_time(int reset)
{
return wc_MXC_RTC_Time();
}
#elif defined(FREESCALE_KSDK_BM)
double current_time(int reset)

View File

@@ -82,6 +82,10 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits
#include <wolfssl/wolfcrypt/port/psa/psa.h>
#endif
#if defined(WOLFSSL_MAX3266X) || defined(WOLFSSL_MAX3266X_OLD)
#include <wolfssl/wolfcrypt/port/maxim/max3266x.h>
#endif
#if defined(WOLFSSL_TI_CRYPT)
#include <wolfcrypt/src/port/ti/ti-aes.c>
#else
@@ -2789,6 +2793,9 @@ extern void AesEncryptBlocks_C(Aes* aes, const byte* in, byte* out, word32 sz);
static WARN_UNUSED_RESULT int wc_AesEncrypt(
Aes* aes, const byte* inBlock, byte* outBlock)
{
#if defined(MAX3266X_AES)
word32 keySize;
#endif
word32 r;
if (aes == NULL) {
@@ -2892,6 +2899,14 @@ static WARN_UNUSED_RESULT int wc_AesEncrypt(
}
#endif
#if defined(MAX3266X_AES)
if (wc_AesGetKeySize(aes, &keySize) == 0) {
return wc_MXC_TPU_AesEncrypt(inBlock, (byte*)aes->reg, (byte*)aes->key,
MXC_TPU_MODE_ECB, AES_BLOCK_SIZE,
outBlock, (unsigned int)keySize);
}
#endif
AesEncrypt_C(aes, inBlock, outBlock, r);
return 0;
@@ -3539,6 +3554,9 @@ static void AesDecryptBlocks_C(Aes* aes, const byte* in, byte* out, word32 sz)
static WARN_UNUSED_RESULT int wc_AesDecrypt(
Aes* aes, const byte* inBlock, byte* outBlock)
{
#if defined(MAX3266X_AES)
word32 keySize;
#endif
word32 r;
if (aes == NULL) {
@@ -3615,6 +3633,14 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(
} /* else !wc_esp32AesSupportedKeyLen for ESP32 */
#endif
#if defined(MAX3266X_AES)
if (wc_AesGetKeySize(aes, &keySize) == 0) {
return wc_MXC_TPU_AesDecrypt(inBlock, (byte*)aes->reg, (byte*)aes->key,
MXC_TPU_MODE_ECB, AES_BLOCK_SIZE,
outBlock, (unsigned int)keySize);
}
#endif
AesDecrypt_C(aes, inBlock, outBlock, r);
return 0;
@@ -4103,7 +4129,8 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir)
XMEMCPY(rk, key, keySz);
#if defined(LITTLE_ENDIAN_ORDER) && !defined(WOLFSSL_PIC32MZ_CRYPT) && \
(!defined(WOLFSSL_ESP32_CRYPT) || defined(NO_WOLFSSL_ESP32_CRYPT_AES))
(!defined(WOLFSSL_ESP32_CRYPT) || defined(NO_WOLFSSL_ESP32_CRYPT_AES)) && \
!defined(MAX3266X_AES)
/* Always reverse words when using only SW */
{
ByteReverseWords(rk, rk, keySz);
@@ -4250,7 +4277,7 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir)
} /* switch */
ForceZero(&temp, sizeof(temp));
#if defined(HAVE_AES_DECRYPT)
#if defined(HAVE_AES_DECRYPT) && !defined(MAX3266X_AES)
if (dir == AES_DECRYPTION) {
unsigned int j;
@@ -4546,8 +4573,8 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir)
#ifndef WC_AES_BITSLICED
#if defined(LITTLE_ENDIAN_ORDER) && !defined(WOLFSSL_PIC32MZ_CRYPT) && \
(!defined(WOLFSSL_ESP32_CRYPT) || \
defined(NO_WOLFSSL_ESP32_CRYPT_AES))
(!defined(WOLFSSL_ESP32_CRYPT) || defined(NO_WOLFSSL_ESP32_CRYPT_AES)) \
&& !defined(MAX3266X_AES)
/* software */
ByteReverseWords(aes->key, aes->key, keylen);
@@ -5378,6 +5405,82 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
}
#endif /* HAVE_AES_DECRYPT */
#elif defined(MAX3266X_AES)
int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
word32 keySize;
int status;
byte *iv;
#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS
if (sz % AES_BLOCK_SIZE) {
return BAD_LENGTH_E;
}
#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->key,
MXC_TPU_MODE_CBC, sz, out,
(unsigned int)keySize);
/* store iv for next call */
if (status == 0) {
XMEMCPY(iv, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
}
return (status == 0) ? 0 : -1;
}
#ifdef HAVE_AES_DECRYPT
int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
word32 keySize;
int status;
byte *iv;
byte temp_block[AES_BLOCK_SIZE];
#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS
if (sz % AES_BLOCK_SIZE) {
return BAD_LENGTH_E;
}
#endif
if (sz == 0)
return 0;
iv = (byte*)aes->reg;
status = wc_AesGetKeySize(aes, &keySize);
if (status != 0) {
return status;
}
/* get IV for next call */
XMEMCPY(temp_block, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
status = wc_MXC_TPU_AesDecrypt(in, iv, (byte*)aes->key,
MXC_TPU_MODE_CBC, sz, out,
keySize);
/* store iv for next call */
if (status == 0) {
XMEMCPY(iv, temp_block, AES_BLOCK_SIZE);
}
return (status == 0) ? 0 : -1;
}
#endif /* HAVE_AES_DECRYPT */
#elif defined(WOLFSSL_PIC32MZ_CRYPT)
int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)

View File

@@ -139,7 +139,8 @@ EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \
wolfcrypt/src/port/Renesas/renesas_rx64_hw_util.c \
wolfcrypt/src/port/Renesas/README.md \
wolfcrypt/src/port/cypress/psoc6_crypto.c \
wolfcrypt/src/port/liboqs/liboqs.c
wolfcrypt/src/port/liboqs/liboqs.c \
wolfcrypt/src/port/maxim/max3266x.c
$(ASYNC_FILES):
$(AM_V_at)touch $(srcdir)/$@

View File

@@ -1,14 +1,113 @@
wolfSSL using Analog Devices MAXQ1065 or MAX1080
wolfSSL using Analog Devices MAXQ1065, MAX1080, MAX32665 or MAX32666
================================================
## Overview
wolfSSL can be configured to use the MAXQ1065 or MAX1080 cryptographic
controllers. Product datasheets, user guides and other resources can be found at
controllers. wolfSSL can also be configure to utilize the TPU
(crypto accelerator), MAA (math accelerator), and TRNG available on select
MAX32665 and MAX32666 microcontrollers.
Product datasheets, user guides and other resources can be found at
Analog Devices website:
https://www.analog.com
# MAX32665/MAX32666
## Build and Usage
wolfSSL supports the [Maxim SDK](https://github.com/analogdevicesinc/msdk), to
utilize the TPU and MAA located on the devices.
Building is supported by adding `#define WOLFSSL_MAX3266X` to `user_settings.h`.
wolfSSL supports the usage of the older style API Maxim provides with the
`#define WOLFSSL_MAX3266X_OLD` to `user_settings.h`.
When using `WOLFSSL_MAX3266X` or `WOLFSSL_MAX3266X_OLD` you will also need to
add `#define WOLFSSL_SP_MATH_ALL` to `user_settings.h`.
If you want to be more specific on what hardware acceleration you want to use,
this can be done by adding any combination of these defines:
```
#define MAX3266X_RNG - Allows usage of TRNG device
#define MAX3266X_AES - Allows usage of TPU for AES Acceleration
#define MAX3266X_SHA - Allows usage of TPU for Hash Acceleration
#define MAX3266X_MATH - Allows usage of MAA for MOD based Math Acceleration
```
For this you will still need to use `#define WOLFSSL_MAX3266X` or `#define WOLFSSL_MAX3266X_OLD`. When you use a specific hardware define like
`#define MAX3266X_RNG` this will mean only the TRNG device is being used, and
all other operations will use the default software implementations.
The other prerequisite is that a change needs to be made to the Maxim SDK. This
is to use the MAA Math Accelerator, this change only needs to be made if you are
using `#define WOLFSSL_MAX3266X` or `define WOLFSSL_MAX3266X_OLD` by themselves
or you are specifing `#define MAX3266X_MATH`.
In the SDK you will need to find the underlying function that
`MXC_TPU_MAA_Compute()` from `tpu.h` compute calls in the newer SDK. In the
older SDK this function is called `MAA_Compute()` in `maa.h`. In the underlying
function you will need to change this error check:
```
// Check that we're performing a valid operation
if (clc >= 0x6) {
return E_INVALID;
}
```
to
```
// Check that we're performing a valid operation
if (clc >= 0b1111) {
return E_INVALID;
}
```
This bug has been reported to Analog Devices
[here](https://github.com/analogdevicesinc/msdk/issues/1089)
if you want to know more details on the issue.
## Supported Algos
Using these defines will replace software implentations with a call to the
hardware.
`#define MAX3266X_RNG`
- Uses entropy from TRNG to seed HASHDRBG
`#define MAX3266X_AES`:
- AES-CBC: 128, 192, 256
- AES-ECB: 128, 192, 256
`#define MAX3266X_SHA`:
- SHA-256
`#define MAX3266X_MATH` (Replaces math operation calls for algos
like RSA and ECC key generation):
- mod - `a mod m = r`
- addmod - `(a+b)mod m = r`
- submod - `(a-b)mod m = r`
- mulmod - `(a*b)mod m = r`
- sqrmod - `(b^2)mod m = r`
- exptmod - `(b^e)mod m = r`
## Extra Information
For more Verbose info you can use `#define DEBUG_WOLFSSL` in combination with
`#define MAX3266X_VERBOSE` to see if errors are occuring during the hardware
setup/
To reproduce benchmark numbers you can use `#define MAX3266X_RTC`.
Do note that this will only work with `#define WOLFSSL_MAX3266X` and not
`#define WOLFSSL_MAX3266X_OLD`. This is only meant for benchmark reproduction
and not for any other application. Please implement your own rtc/time code for
anything else.
For more infromation about the TPU, MAA, and TRNG please refer to the
[MAX32665/MAX32666 User Guide: UG6971](https://www.analog.com/media/en/technical-documentation/user-guides/max32665max32666-user-guide.pdf)
# MAXQ1065/MAX1080
## Build and Usage
Please use the appropriate SDK or Evkit to build wolfSSL.

View File

@@ -0,0 +1,906 @@
/* max3266x.c
*
* Copyright (C) 2006-2024 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
*/
#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>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#if defined(USE_FAST_MATH)
#error MXC Not Compatible with Fast 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
#endif
#define MXC_MAA_MAX_SIZE (2048 / MXC_WORD_SIZE)
int wc_MXC_TPU_Init(void)
{
/* Initialize the TPU device */
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)
{
/* Shutdown the TPU device */
#if defined(WOLFSSL_MAX3266X_OLD)
MXC_TPU_Shutdown(); /* Is a void return in older SDK */
#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;
}
/* Convert Error Codes Correctly */
/* TODO: Convert to correct wolfCrypt Codes */
/* TODO: Add wolfssl Message Statements to report HW issue on bad return */
int wc_MXC_error(int *ret)
{
switch(*ret){
case E_SUCCESS:
return 0;
case E_NULL_PTR:
return E_NULL_PTR;
case E_INVALID: /* Process Failed */
return E_INVALID;
case E_BAD_PARAM:
return BAD_FUNC_ARG;
case E_BAD_STATE:
return E_BAD_STATE;
default:
*ret = WC_HW_E; /* If something else return HW Error */
return *ret;
}
}
#if defined(MAX3266X_RNG)
/* Use this RNG_FAILURE_E for RNG Errors*/
int wc_MXC_TRNG_Random(unsigned char* output, unsigned int sz)
{
if (MXC_TPU_Init(MXC_SYS_PERIPH_CLOCK_TRNG) != 0) {
MAX3266X_MSG("TRNG Device did not initialize");
return RNG_FAILURE_E;
}
/* void return function */
MXC_TPU_TRNG_Read(MXC_TRNG, output, sz);
MAX3266X_MSG("TRNG Hardware Used");
return 0;
}
#endif /* MAX3266x_RNG */
#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;
status = wolfSSL_CryptHwMutexLock();
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_CryptHwMutexUnLock();
return WC_HW_E;
break;
}
wolfSSL_CryptHwMutexUnLock();
if (status != 0) {
MAX3266X_MSG("AES HW Acceleration Error Occured");
return WC_HW_E;
}
return 0;
}
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;
status = wolfSSL_CryptHwMutexLock();
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_CryptHwMutexUnLock();
return WC_HW_E;
break;
}
wolfSSL_CryptHwMutexUnLock();
if (status != 0) {
MAX3266X_MSG("AES HW Acceleration Error Occured");
return WC_HW_E;
}
return 0;
}
#endif
#if defined(MAX3266X_SHA)
int wc_MXC_TPU_SHA_Init(wc_MXC_Sha *hash)
{
if (hash == NULL) {
return BAD_FUNC_ARG; /* Appropriate error handling for null argument */
}
hash->msg = NULL;
hash->used = 0;
hash->size = 0;
return 0;
}
int wc_MXC_TPU_SHA_Update(wc_MXC_Sha *hash, const unsigned char* data,
unsigned int size)
{
void *p;
if (size != (0 || NULL)) {
if ((hash == NULL) || (data == NULL)) {
return BAD_FUNC_ARG;
}
if (hash->size < hash->used+size) {
if (hash->msg == NULL) {
p = XMALLOC(hash->used+size, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
else {
#ifdef WOLFSSL_NO_REALLOC
p = XMALLOC(hash->used + size, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (p != NULL) {
XMEMCPY(p, hash->msg, hash->used);
XFREE(hash->msg, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
#else
p = XREALLOC(hash->msg, hash->used+size, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
#endif
}
if (p == NULL) {
return -1;
}
hash->msg = p;
hash->size = hash->used+size;
}
XMEMCPY(hash->msg+hash->used, data, size);
hash->used += size;
if (hash->msg == NULL) {
return BAD_FUNC_ARG;
}
}
return 0;
}
int wc_MXC_TPU_SHA_GetHash(wc_MXC_Sha *hash, unsigned char* digest,
MXC_TPU_HASH_TYPE algo)
{
int status;
status = wc_MXC_TPU_SHA_GetDigest(hash, digest, algo);
/* True Case that msg is an empty string */
if (status == 1) {
return 0;
}
/* False Case where msg needs to be processed */
else if (status == 0) {
status = wolfSSL_CryptHwMutexLock();
if (wc_MXC_error(&status) != 0) {
return status;
}
MXC_TPU_Init(MXC_SYS_PERIPH_CLOCK_TPU);
MXC_TPU_Hash_Config(algo);
status = MXC_TPU_Hash_SHA((const char *)hash->msg, algo, hash->size,
(char *)digest);
MAX3266X_MSG("SHA HW Acceleration Used");
wolfSSL_CryptHwMutexUnLock();
if (wc_MXC_error(&status) != 0) {
MAX3266X_MSG("SHA HW Error Occured");
return status;
}
}
/* Error Occured */
return status;
}
int wc_MXC_TPU_SHA_Final(wc_MXC_Sha *hash, unsigned char* digest,
MXC_TPU_HASH_TYPE algo)
{
int status;
status = wc_MXC_TPU_SHA_GetHash(hash, digest, algo);
if (status != 0) {
return status;
}
XFREE(hash->msg, NULL, DYNAMIC_TYPE_TMP_BUFFER);
status = wc_MXC_TPU_SHA_Init(hash);
if (status != 0) {
return status;
}
return status;
}
int wc_MXC_TPU_SHA_Copy(wc_MXC_Sha* src, wc_MXC_Sha* dst)
{
if (src == NULL || dst == NULL) {
return BAD_FUNC_ARG;
}
dst->used = src->used;
dst->size = src->size;
XMEMCPY(dst->hash, src->hash, sizeof(dst->hash));
return 0;
}
void wc_MXC_TPU_SHA_Free(wc_MXC_Sha* hash)
{
XFREE(hash->msg, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wc_MXC_TPU_SHA_Init(hash); /* sets hash->msg to null + zero's attributes */
return;
}
/* Acts as a True/False if true it will provide the stored digest */
/* for the edge case of an empty string */
int wc_MXC_TPU_SHA_GetDigest(wc_MXC_Sha *hash, unsigned char* digest,
MXC_TPU_HASH_TYPE algo)
{
if (hash->msg == 0 && hash->size == 0 && digest != NULL) {
switch(algo) {
#ifndef NO_SHA256
case MXC_TPU_HASH_SHA256:
XMEMCPY(digest, MXC_EMPTY_DIGEST_SHA256, WC_SHA256_DIGEST_SIZE);
break;
#endif
default:
return BAD_FUNC_ARG;
}
return 1; /* True */
}
return 0; /* False */
}
#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)heap;
(void)devId;
return wc_MXC_TPU_SHA_Init((wc_MXC_Sha *)sha256);
}
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)
{
return wc_MXC_TPU_SHA_Update(sha256, data, len);
}
WOLFSSL_API int wc_Sha256Final(wc_Sha256* sha256, unsigned char* hash)
{
return wc_MXC_TPU_SHA_Final((wc_MXC_Sha *)sha256, hash,
MXC_TPU_HASH_SHA256);
}
WOLFSSL_API int wc_Sha256GetHash(wc_Sha256* sha256, unsigned char* hash)
{
return wc_MXC_TPU_SHA_GetHash((wc_MXC_Sha *)sha256, hash,
MXC_TPU_HASH_SHA256);
}
WOLFSSL_API int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
{
return wc_MXC_TPU_SHA_Copy((wc_MXC_Sha *)src, (wc_MXC_Sha *)dst);
}
WOLFSSL_API void wc_Sha256Free(wc_Sha256* sha256)
{
wc_MXC_TPU_SHA_Free((wc_MXC_Sha *)sha256);
return;
}
#endif
#endif /* MAX3266X_SHA */
#if defined(MAX3266X_MATH)
/* Sets mutex and initializes hardware according to need operation size */
int wc_MXC_MAA_init(unsigned int len)
{
int status;
MAX3266X_MSG("Setting Hardware Mutex and Starting MAA");
status = wolfSSL_CryptHwMutexLock();
if (status != 0) {
return status;
}
status = MXC_TPU_MAA_Init(len);
return wc_MXC_error(&status); /* Return Status of Init */
}
/* Unlocks mutex and preforms graceful shutdown of hardware */
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) { /* Miss leading, Send WC_HW_ERROR */
/* This is returned when MAA cannot stop */
return WC_HW_E;
}
else if(wc_MXC_error(&status) != 0) {
return status;
}
wolfSSL_CryptHwMutexUnLock();
return status;
}
/* Update used number for mp_int struct for results */
int wc_MXC_MAA_adjustUsed(unsigned int *array, unsigned int length)
{
int i, lastNonZeroIndex;
lastNonZeroIndex = -1; /* Track the last non-zero index */
for (i = 0; i < length; i++) {
if (array[i] != 0) {
lastNonZeroIndex = i;
}
}
return (lastNonZeroIndex + 1);
}
/* Determines the size of operation that needs to happen */
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;
}
/* Determines if we need to fallback to Software */
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;
}
/* Have to zero pad the entire data array up to 256 bytes(2048 bits) */
/* If length > 256 bytes then error */
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 == WC_MXC_TPU_MAA_EXP)) || (mod == NULL)) {
return BAD_FUNC_ARG;
}
/* Create an array to compare values to to check edge for error edge case */
zero_tmp = (mp_digit*)XMALLOC(multiplier->size*sizeof(mp_digit), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
XMEMSET(zero_tmp, 0x00, multiplier->size*sizeof(mp_digit));
/* Check for invalid arguments befor padding */
switch((char)clc){
case WC_MXC_TPU_MAA_EXP:
/* Cannot be 0 for a^e mod m operation */
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;
break;
}
/* Padd out rest of data if used != length to ensure no */
/* garbage is used in calculation */
if ((exp != NULL) && (clc == WC_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));
}
}
/* Fall through to check mod is not 0 */
case WC_MXC_TPU_MAA_SQ:
case WC_MXC_TPU_MAA_MUL:
case WC_MXC_TPU_MAA_SQMUL:
case WC_MXC_TPU_MAA_ADD:
case WC_MXC_TPU_MAA_SUB:
/* Cannot be 0 for mod m value */
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;
break;
}
/* Padd out rest of data if used != length to ensure no */
/* garbage is used in calculation */
if ((multiplier->dp != NULL) && (multiplier->used < length)) {
MAX3266X_MSG("Zero Padding Multipler 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:
return BAD_FUNC_ARG; /* Invalid clc given */
}
/* Free the zero array used to check values */
XFREE(zero_tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
/* Make sure result is 0 padded */
if (result->dp != NULL) {
ForceZero(result->dp, sizeof(int)*(length));
result->used = length;
}
else if (result == NULL) {
return BAD_FUNC_ARG; /* Cannot be null */
}
return 0;
}
/* General Control Over MAA Hardware to handle all needed Cases */
int wc_MXC_MAA_math(mp_int* multipler, 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;
/* Check if result shares struct pointer */
if ((multipler == result) || (multiplicand == result) || (exp == result) ||
(mod == result)) {
MAX3266X_MSG("Creating Temp Result Buffer for Hardware");
result_tmp_ptr = &result_tmp; /* Assign point to temp struct */
}
else {
result_tmp_ptr = result; /* No Shared Point to directly assign */
}
if (result_tmp_ptr == NULL) {
MAX3266X_MSG("tmp ptr is null");
return MP_VAL;
}
if (clc == WC_MXC_TPU_MAA_EXP) {
length = wc_MXC_MAA_Largest(5, multipler->used, multiplicand->used,
exp->used, mod->used, result->used);
}
else {
length = wc_MXC_MAA_Largest(4, multipler->used, multiplicand->used,
mod->used, result->used);
}
/* Zero Pad everything if needed */
ret = wc_MXC_MAA_zeroPad(multipler, multiplicand, exp, mod, result_tmp_ptr,
clc, length);
if (ret != 0) {
MAX3266X_MSG("Zero Padding Failed");
return ret;
}
/* Init MAA HW */
ret = wc_MXC_MAA_init(length*sizeof(mp_digit)*8);
if (ret != 0) {
MAX3266X_MSG("HW Init Failed");
wolfSSL_CryptHwMutexUnLock();
return ret;
}
/* Start Math And Cast to expect types for SDK */
MAX3266X_MSG("Starting Computation in MAA");
ret = MXC_TPU_MAA_Compute(clc, (char *)(multipler->dp),
(char *)(multiplicand->dp),
(char *)(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_CryptHwMutexUnLock();
return ret;
}
ret = wc_MXC_MAA_Shutdown();
if (ret != 0) {
MAX3266X_MSG("HW Shutdown Failure");
wolfSSL_CryptHwMutexUnLock();
return ret;
}
/* Copy tmp result if needed */
if ((multipler == result) || (multiplicand == result) || (exp == result) ||
(mod == result)) {
mp_copy(result_tmp_ptr, result);
ForceZero(result_tmp_ptr, sizeof(result_tmp_ptr)); /* force zero */
}
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;
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,
WC_MXC_TPU_MAA_EXP);
}
int wc_MXC_MAA_sqrmod(mp_int* multipler, mp_int* mod, mp_int* result)
{
mp_int multiplicand;
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(multipler, &multiplicand, NULL, mod, result,
WC_MXC_TPU_MAA_SQ);
}
int wc_MXC_MAA_mulmod(mp_int* multipler, mp_int* multiplicand, mp_int* mod,
mp_int* result)
{
MAX3266X_MSG("Preparing mulmod MAA HW Call");
return wc_MXC_MAA_math(multipler, multiplicand, NULL, mod, result,
WC_MXC_TPU_MAA_MUL);
}
int wc_MXC_MAA_sqrmulmod(mp_int* multipler, mp_int* multiplicand,
mp_int* exp, mp_int* mod, mp_int* result)
{
MAX3266X_MSG("Preparing sqrmulmod MAA HW Call");
return wc_MXC_MAA_math(multipler, multiplicand, NULL, mod, result,
WC_MXC_TPU_MAA_SQMUL);
}
int wc_MXC_MAA_addmod(mp_int* multipler, mp_int* multiplicand, mp_int* mod,
mp_int* result)
{
MAX3266X_MSG("Preparing addmod MAA HW Call");
return wc_MXC_MAA_math(multipler, multiplicand, NULL, mod, result,
WC_MXC_TPU_MAA_ADD);
}
int wc_MXC_MAA_submod(mp_int* multipler, mp_int* multiplicand, mp_int* mod,
mp_int* result)
{
MAX3266X_MSG("Preparing submod MAA HW Call");
if ((mod->used < multipler->used) || (mod->used < multiplicand->used)) {
MAX3266X_MSG("HW Limitation: Defaulting back to software");
return mxc_submod(multipler, multiplicand, mod, result);
}
else {
return wc_MXC_MAA_math(multipler, multiplicand, NULL, mod, result,
WC_MXC_TPU_MAA_SUB);
}
}
/* General Function to call hardware control */
int hw_mulmod(mp_int* multiplier, mp_int* multiplicand, mp_int* mod,
mp_int* result)
{
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;
/* Validate parameters. */
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;
/* Validate parameters. */
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;
/* Validate parameters. */
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;
}
/* No mod function avaliable with hardware, however preform a submod */
/* (a - 0) mod m will essentially preform the same operation as a mod m */
int hw_mod(mp_int* a, mp_int* mod, mp_int* result)
{
mp_int b;
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; /* assume mod is determining size */
return hw_submod(a, &b, mod, result);
}
int hw_sqrmod(mp_int* base, mp_int* mod, mp_int* result)
{
if (base->used == 0) {
mp_zero(result);
return 0;
}
return wc_MXC_MAA_sqrmod(base, mod, result);
}
#endif
#if defined(MAX3266X_RTC)
/* Initialize the RTC */
int wc_MXC_RTC_Init(void)
{
/* RTC Init for benchmark */
if (MXC_RTC_Init(0, 0) != E_NO_ERROR) {
return WC_HW_E;
}
/* Disable the Interrupt */
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;
}
/* Reset the RTC */
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;
}
/* Function to handle RTC read retries */
void wc_MXC_RTC_GetRTCValue(int32_t (*rtcGetFunction)(uint32_t*),
uint32_t* outValue, int32_t* err)
{
*err = rtcGetFunction(outValue); /* Initial attempt to get the value */
while (*err != E_NO_ERROR) {
*err = rtcGetFunction(outValue); /* Retry if the error persists */
}
}
/* Function to provide the current time as a double */
double wc_MXC_RTC_Time(void)
{
int32_t err;
uint32_t rtc_seconds, rtc_subseconds;
/* Retrieve sub-seconds from RTC */
wc_MXC_RTC_GetRTCValue((int32_t (*)(uint32_t*))MXC_RTC_GetSubSeconds,
&rtc_subseconds, &err);
if (err != E_NO_ERROR){
return (double)err;
}
/* Retrieve seconds from RTC */
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 /* MAX3266X_RTC */
#endif /* WOLFSSL_MAX32665 || WOLFSSL_MAX32666 */

View File

@@ -136,6 +136,8 @@ This library contains implementation for the random number generator.
#elif defined(WOLFSSL_GETRANDOM)
#include <errno.h>
#include <sys/random.h>
#elif defined(WOLFSSL_MAX3266X) || defined(WOLFSSL_MAX3266X_OLD)
#include "wolfssl/wolfcrypt/port/maxim/max3266x.h"
#else
/* include headers that may be needed to get good seed */
#include <fcntl.h>
@@ -3834,6 +3836,13 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
return maxq10xx_random(output, sz);
}
#elif defined(MAX3266X_RNG)
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
{
(void)os;
return wc_MXC_TRNG_Random(output, sz);
}
#elif defined(WOLFSSL_GETRANDOM)
/* getrandom() was added to the Linux kernel in version 3.17.

View File

@@ -122,7 +122,9 @@ on the specific device platform.
#elif defined(WOLFSSL_PSOC6_CRYPTO)
#elif defined(MAX3266X_SHA)
/* Already brought in by sha256.h */
/* #include <wolfssl/wolfcrypt/port/maxim/max3266x.h> */
#else
#include <wolfssl/wolfcrypt/logging.h>
@@ -2487,7 +2489,8 @@ int wc_Sha224_Grow(wc_Sha224* sha224, const byte* in, int inSz)
/* implemented in wolfcrypt/src/port/psa/psa_hash.c */
#elif defined(WOLFSSL_RENESAS_RX64_HASH)
/* implemented in wolfcrypt/src/port/Renesas/renesas_rx64_hw_sha.c */
#elif defined(MAX3266X_SHA)
/* Implemented in wolfcrypt/src/port/maxim/max3266x.c */
#else
int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash)

View File

@@ -44,6 +44,10 @@
#include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
#endif
#if defined(WOLFSSL_MAX3266X) || defined(WOLFSSL_MAX3266X_OLD)
#include <wolfssl/wolfcrypt/port/maxim/max3266x.h>
#endif
#ifdef WOLFSSL_PSOC6_CRYPTO
#include <wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h>
#endif
@@ -251,6 +255,14 @@ int wolfCrypt_Init(void)
}
#endif
#if defined(MAX3266X_RTC)
ret = wc_MXC_RTC_Init();
if (ret != 0){
WOLFSSL_MSG("MXC RTC Init Failed");
return WC_HW_E;
}
#endif
#if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A) || \
defined(WOLFSSL_ATECC608A)
ret = atmel_init();
@@ -3149,6 +3161,9 @@ time_t mqx_time(time_t* timer)
#endif /* FREESCALE_MQX || FREESCALE_KSDK_MQX */
#if defined(MAX3266X_RTC)
#define XTIME wc_MXC_RTC_Time
#endif
#if defined(WOLFSSL_TIRTOS) && defined(USER_TIME)