Skip to content

Commit 476f1a8

Browse files
committed
Added TRNG support for the Vorago VA416XX
1 parent 2f7b8b2 commit 476f1a8

2 files changed

Lines changed: 159 additions & 4 deletions

File tree

.wolfssl_known_macro_extras

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,7 @@ WOLFSSL_USE_ESP32C3_CRYPT_HASH_HW
967967
WOLFSSL_USE_FLASHMEM
968968
WOLFSSL_USE_FORCE_ZERO
969969
WOLFSSL_USE_OPTIONS_H
970+
WOLFSSL_VA416X0_TRNG
970971
WOLFSSL_VALIDATE_DH_KEYGEN
971972
WOLFSSL_WC_SLHDSA_RECURSIVE
972973
WOLFSSL_WC_XMSS_NO_SHA256

wolfcrypt/src/random.c

Lines changed: 158 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,18 +88,24 @@ This library contains implementation for the random number generator.
8888
* FREESCALE_RNGA: Freescale RNGA default: off
8989
* FREESCALE_K70_RNGA: Freescale K70 RNGA default: off
9090
* FREESCALE_RNGB: Freescale RNGB default: off
91-
* FREESCALE_KSDK_2_0_RNGA: Freescale KSDK 2.0 RNGA default: off
92-
* FREESCALE_KSDK_2_0_TRNG: Freescale KSDK 2.0 TRNG default: off
93-
* MAX3266X_RNG: MAX3266X hardware RNG default: off
91+
* FREESCALE_KSDK_2_0_RNGA: Freescale KSDK 2.0 RNGA default: off
92+
* FREESCALE_KSDK_2_0_TRNG: Freescale KSDK 2.0 TRNG default: off
93+
* MAX3266X_RNG: MAX3266X hardware RNG default: off
9494
* QAT_ENABLE_RNG: Intel QAT hardware RNG default: off
95-
* WOLFSSL_ATECC_RNG: ATECC508/608 hardware RNG default: off
95+
* WOLFSSL_ATECC_RNG: ATECC508/608 hardware RNG default: off
9696
* WOLFSSL_SILABS_TRNG: Silicon Labs TRNG default: off
9797
* WOLFSSL_SCE_NO_TRNG: Disable Renesas SCE TRNG default: off
9898
* WOLFSSL_SCE_TRNG_HANDLE: Renesas SCE TRNG handle default: off
9999
* WOLFSSL_SE050_NO_TRNG: Disable SE050 TRNG default: off
100100
* WOLFSSL_PSA_NO_RNG: Disable PSA RNG default: off
101101
* HAVE_IOTSAFE_HWRNG: IoT-Safe hardware RNG default: off
102102
* WOLFSSL_XILINX_CRYPT_VERSAL: Xilinx Versal crypto RNG default: off
103+
* WOLFSSL_VA416X0_TRNG: Vorago VA416x0 hardware TRNG default: off
104+
* (seeds Hash-DRBG; needs the VA416xx
105+
* SDK header va416xx.h on the include
106+
* path). See the wc_GenerateSeed()
107+
* implementation below for SDK API and
108+
* tuning details.
103109
*/
104110

105111
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
@@ -5171,6 +5177,154 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
51715177
return 0;
51725178
}
51735179

5180+
#elif defined(WOLFSSL_VA416X0_TRNG)
5181+
/* Vorago VA416x0 hardware TRNG (an Arm CryptoCell-style entropy block).
5182+
* Used to seed the SP800-90A Hash-DRBG (keep HAVE_HASHDRBG enabled); the
5183+
* TRNG yields only ~1.25 kb/s of entropy, so the DRBG expands it.
5184+
*
5185+
* Build: define WOLFSSL_VA416X0_TRNG, and have the VA416xx SDK header
5186+
* "va416xx.h" on the include path (provides VOR_SYSCONFIG / VOR_TRNG and
5187+
* the register field macros). There is no SDK HAL driver for the TRNG, so
5188+
* it is accessed at the register level below. The tuning macros
5189+
* WOLFSSL_VA416X0_TRNG_SAMPLE_CNT, WOLFSSL_VA416X0_TRNG_MAX_RETRY and
5190+
* WOLFSSL_VA416X0_TRNG_TIMEOUT have overridable defaults defined below.
5191+
*
5192+
* Note: the TRNG PERIPHERAL_RESET bit is active low and must be released
5193+
* or every TRNG register write is silently ignored. */
5194+
#include "va416xx.h"
5195+
5196+
/* Ring-oscillator sample count (must be non-zero). May need tuning on
5197+
* hardware: too low results in repeated autocorrelation/CRNGT errors. */
5198+
#ifndef WOLFSSL_VA416X0_TRNG_SAMPLE_CNT
5199+
#define WOLFSSL_VA416X0_TRNG_SAMPLE_CNT 1000
5200+
#endif
5201+
#ifndef WOLFSSL_VA416X0_TRNG_MAX_RETRY
5202+
#define WOLFSSL_VA416X0_TRNG_MAX_RETRY 10
5203+
#endif
5204+
/* Max poll iterations waiting for one 192-bit entropy block before
5205+
* giving up (guards against a non-responsive TRNG). */
5206+
#ifndef WOLFSSL_VA416X0_TRNG_TIMEOUT
5207+
#define WOLFSSL_VA416X0_TRNG_TIMEOUT 1000000
5208+
#endif
5209+
#if WOLFSSL_VA416X0_TRNG_SAMPLE_CNT == 0
5210+
#error "WOLFSSL_VA416X0_TRNG_SAMPLE_CNT must be non-zero"
5211+
#endif
5212+
#if WOLFSSL_VA416X0_TRNG_TIMEOUT == 0
5213+
#error "WOLFSSL_VA416X0_TRNG_TIMEOUT must be non-zero"
5214+
#endif
5215+
5216+
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
5217+
{
5218+
word32 i;
5219+
word32 reg;
5220+
word32 chunk;
5221+
word32 timeout;
5222+
word32 ehr[6]; /* 192-bit entropy holding register */
5223+
int retry;
5224+
int ret;
5225+
5226+
(void)os;
5227+
5228+
if (output == NULL) {
5229+
return BUFFER_E;
5230+
}
5231+
5232+
/* serialize access to the shared TRNG hardware */
5233+
ret = wolfSSL_CryptHwMutexLock();
5234+
if (ret != 0) {
5235+
return ret;
5236+
}
5237+
5238+
/* enable the TRNG peripheral clock and release it from reset (the
5239+
* reset bit is active low: 0 = held in reset, 1 = released) */
5240+
VOR_SYSCONFIG->PERIPHERAL_CLK_ENABLE |=
5241+
SYSCONFIG_PERIPHERAL_CLK_ENABLE_TRNG_Msk;
5242+
VOR_SYSCONFIG->PERIPHERAL_RESET |=
5243+
SYSCONFIG_PERIPHERAL_RESET_TRNG_Msk;
5244+
5245+
/* mask all interrupts (poll instead) and clear any stale status */
5246+
VOR_TRNG->IMR = TRNG_IMR_EHR_VALID_INT_MASK_Msk |
5247+
TRNG_IMR_AUTOCORR_ERR_INT_MASK_Msk |
5248+
TRNG_IMR_CRNGT_ERR_INT_MASK_Msk |
5249+
TRNG_IMR_VN_ERR_INT_MASK_Msk;
5250+
VOR_TRNG->ICR = TRNG_ICR_EHR_VALID_Msk | TRNG_ICR_AUTOCORR_ERR_Msk |
5251+
TRNG_ICR_CRNGT_ERR_Msk | TRNG_ICR_VN_ERR_Msk;
5252+
5253+
/* CONFIG = 0 sets RND_SRC_SEL = 0, which selects the ring-oscillator
5254+
* entropy source (per the VA416x0 reference manual) and clears the
5255+
* rest of the register; set the sample rate and keep the health tests
5256+
* enabled (no DEBUG_CONTROL bypass) */
5257+
VOR_TRNG->CONFIG = 0;
5258+
VOR_TRNG->SAMPLE_CNT1 = WOLFSSL_VA416X0_TRNG_SAMPLE_CNT;
5259+
VOR_TRNG->DEBUG_CONTROL = 0;
5260+
5261+
for (i = 0; i < sz; ) {
5262+
retry = 0;
5263+
timeout = WOLFSSL_VA416X0_TRNG_TIMEOUT;
5264+
5265+
/* start entropy collection */
5266+
VOR_TRNG->RND_SOURCE_ENABLE =
5267+
TRNG_RND_SOURCE_ENABLE_RND_SRC_EN_Msk;
5268+
5269+
for (;;) {
5270+
reg = VOR_TRNG->ISR;
5271+
if ((reg & (TRNG_ISR_AUTOCORR_ERR_Msk |
5272+
TRNG_ISR_CRNGT_ERR_Msk |
5273+
TRNG_ISR_VN_ERR_Msk)) != 0) {
5274+
/* health-test failure: stop, then clear the error flags
5275+
* and any latched EHR_VALID so a stale/invalid block is
5276+
* not consumed on the next iteration, then re-collect */
5277+
VOR_TRNG->RND_SOURCE_ENABLE = 0;
5278+
VOR_TRNG->ICR = TRNG_ICR_EHR_VALID_Msk |
5279+
TRNG_ICR_AUTOCORR_ERR_Msk |
5280+
TRNG_ICR_CRNGT_ERR_Msk |
5281+
TRNG_ICR_VN_ERR_Msk;
5282+
if (++retry > WOLFSSL_VA416X0_TRNG_MAX_RETRY) {
5283+
ForceZero(ehr, sizeof(ehr));
5284+
wolfSSL_CryptHwMutexUnLock();
5285+
return RNG_FAILURE_E;
5286+
}
5287+
timeout = WOLFSSL_VA416X0_TRNG_TIMEOUT;
5288+
VOR_TRNG->RND_SOURCE_ENABLE =
5289+
TRNG_RND_SOURCE_ENABLE_RND_SRC_EN_Msk;
5290+
continue;
5291+
}
5292+
if ((VOR_TRNG->VALID & TRNG_VALID_EHR_VALID_Msk) != 0) {
5293+
break;
5294+
}
5295+
if (--timeout == 0) {
5296+
VOR_TRNG->RND_SOURCE_ENABLE = 0;
5297+
ForceZero(ehr, sizeof(ehr));
5298+
wolfSSL_CryptHwMutexUnLock();
5299+
return RNG_FAILURE_E;
5300+
}
5301+
}
5302+
5303+
/* read 192 bits of entropy (6 x 32-bit words) */
5304+
ehr[0] = VOR_TRNG->EHR_DATA0;
5305+
ehr[1] = VOR_TRNG->EHR_DATA1;
5306+
ehr[2] = VOR_TRNG->EHR_DATA2;
5307+
ehr[3] = VOR_TRNG->EHR_DATA3;
5308+
ehr[4] = VOR_TRNG->EHR_DATA4;
5309+
ehr[5] = VOR_TRNG->EHR_DATA5;
5310+
5311+
/* reading the EHR clears EHR_VALID; stop the source and ack */
5312+
VOR_TRNG->RND_SOURCE_ENABLE = 0;
5313+
VOR_TRNG->ICR = TRNG_ICR_EHR_VALID_Msk;
5314+
5315+
chunk = sz - i;
5316+
if (chunk > sizeof(ehr)) {
5317+
chunk = sizeof(ehr);
5318+
}
5319+
XMEMCPY(&output[i], (byte*)ehr, chunk);
5320+
i += chunk;
5321+
}
5322+
5323+
ForceZero(ehr, sizeof(ehr)); /* scrub seed material from stack */
5324+
wolfSSL_CryptHwMutexUnLock();
5325+
return 0;
5326+
}
5327+
51745328
#elif defined(DOLPHIN_EMULATOR) || defined (WOLFSSL_NDS)
51755329

51765330
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)

0 commit comments

Comments
 (0)