mirror of https://github.com/ARMmbed/mbed-os.git
Add TRNG support
Adding support for the TRNG peripheral present on Series 1 Configuration 2 devices.pull/4521/head
parent
c678ac8f50
commit
aaac6adaa9
|
@ -148,6 +148,12 @@ typedef enum {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if DEVICE_TRNG
|
||||||
|
struct trng_s {
|
||||||
|
TRNG_TypeDef *instance;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,373 @@
|
||||||
|
/*
|
||||||
|
* True Random Number Generator (TRNG) driver for Silicon Labs devices
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#include "sl_trng.h"
|
||||||
|
|
||||||
|
#if defined(TRNG_PRESENT)
|
||||||
|
#include "em_cmu.h"
|
||||||
|
#include "em_common.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define FIFO_LEVEL_RETRY (1000)
|
||||||
|
#define TEST_WORDS_MIN (257)
|
||||||
|
|
||||||
|
#define TEST_VECTOR_CONDITIONING_KEY_SIZE (4)
|
||||||
|
static const uint32_t
|
||||||
|
test_vector_conditioning_key[TEST_VECTOR_CONDITIONING_KEY_SIZE] =
|
||||||
|
{0x16157E2B, 0xA6D2AE28, 0x8815F7AB, 0x3C4FCF09};
|
||||||
|
|
||||||
|
#define TEST_VECTOR_CONDITIONING_INPUT_SIZE (16)
|
||||||
|
static const uint32_t
|
||||||
|
test_vector_conditioning_input[TEST_VECTOR_CONDITIONING_INPUT_SIZE] =
|
||||||
|
{0xE1BCC06B, 0x9199452A, 0x1A7434E1, 0x25199E7F,
|
||||||
|
0x578A2DAE, 0x9CAC031E, 0xAC6FB79E, 0x518EAF45,
|
||||||
|
0x461CC830, 0x11E45CA3, 0x19C1FBE5, 0xEF520A1A,
|
||||||
|
0x45249FF6, 0x179B4FDF, 0x7B412BAD, 0x10376CE6};
|
||||||
|
|
||||||
|
#define TEST_VECTOR_CONDITIONING_OUTPUT_SIZE (4)
|
||||||
|
static const uint32_t
|
||||||
|
test_vector_conditioning_output[TEST_VECTOR_CONDITIONING_OUTPUT_SIZE] =
|
||||||
|
{0xA1CAF13F, 0x09AC1F68, 0x30CA0E12, 0xA7E18675};
|
||||||
|
|
||||||
|
#define TRNG_STARTUP_TEST_WAIT_RETRY (10000)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
TRNG_TypeDef *instance;
|
||||||
|
CMU_Clock_TypeDef clock;
|
||||||
|
} sl_trng_device_t;
|
||||||
|
|
||||||
|
static const sl_trng_device_t sl_trng_devices[TRNG_COUNT] =
|
||||||
|
{
|
||||||
|
#if defined(TRNG0)
|
||||||
|
{
|
||||||
|
TRNG0,
|
||||||
|
cmuClock_TRNG0
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static CMU_Clock_TypeDef sl_trng_get_clock( TRNG_TypeDef *device )
|
||||||
|
{
|
||||||
|
for(int i = 0; i < TRNG_COUNT; i++) {
|
||||||
|
if(sl_trng_devices[i].instance == device) {
|
||||||
|
return sl_trng_devices[i].clock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cmuClock_TRNG0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sl_trng_init( TRNG_TypeDef *device )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Enable the TRNG's clock. */
|
||||||
|
CMU_ClockEnable( sl_trng_get_clock(device), true );
|
||||||
|
|
||||||
|
device->CONTROL =
|
||||||
|
TRNG_CONTROL_ENABLE |
|
||||||
|
TRNG_CONTROL_REPCOUNTIEN |
|
||||||
|
TRNG_CONTROL_APT64IEN |
|
||||||
|
TRNG_CONTROL_APT4096IEN |
|
||||||
|
TRNG_CONTROL_PREIEN |
|
||||||
|
TRNG_CONTROL_ALMIEN;
|
||||||
|
|
||||||
|
/* Apply software reset */
|
||||||
|
sl_trng_soft_reset(device);
|
||||||
|
|
||||||
|
/* Wait for TRNG to complete startup tests and start filling the FIFO. */
|
||||||
|
for (i=0; (device->FIFOLEVEL == 0) && (i<TRNG_STARTUP_TEST_WAIT_RETRY); i++);
|
||||||
|
EFM_ASSERT(i<TRNG_STARTUP_TEST_WAIT_RETRY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sl_trng_free( TRNG_TypeDef *device )
|
||||||
|
{
|
||||||
|
/* Disable TRNG. */
|
||||||
|
device->CONTROL = 0;
|
||||||
|
|
||||||
|
/* Disable the TRNG clock. */
|
||||||
|
CMU_ClockEnable( sl_trng_get_clock(device), false );
|
||||||
|
}
|
||||||
|
|
||||||
|
void sl_trng_soft_reset( TRNG_TypeDef *device )
|
||||||
|
{
|
||||||
|
uint32_t ctrl = device->CONTROL;
|
||||||
|
|
||||||
|
ctrl |= TRNG_CONTROL_SOFTRESET;
|
||||||
|
|
||||||
|
device->CONTROL = ctrl;
|
||||||
|
|
||||||
|
ctrl &= ~TRNG_CONTROL_SOFTRESET;
|
||||||
|
device->CONTROL = ctrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void sl_trng_write_test_data( TRNG_TypeDef *device, uint32_t data )
|
||||||
|
{
|
||||||
|
/* Wait for TESTDATA register to become ready for next word. */
|
||||||
|
while (device->STATUS & TRNG_STATUS_TESTDATABUSY);
|
||||||
|
device->TESTDATA = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sl_trng_clear_fifo( TRNG_TypeDef *device )
|
||||||
|
{
|
||||||
|
volatile uint32_t val32;
|
||||||
|
|
||||||
|
/* Empty FIFO */
|
||||||
|
while ( device->FIFOLEVEL )
|
||||||
|
{
|
||||||
|
val32 = device->FIFO;
|
||||||
|
(void)val32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int sl_trng_set_key( TRNG_TypeDef *device, const unsigned char *key )
|
||||||
|
{
|
||||||
|
uint32_t *_key = (uint32_t*) key;
|
||||||
|
|
||||||
|
sl_trng_clear_fifo(device);
|
||||||
|
|
||||||
|
/* Program key in KEY registers of the TRNG. */
|
||||||
|
device->KEY0 = *_key++;
|
||||||
|
device->KEY1 = *_key++;
|
||||||
|
device->KEY2 = *_key++;
|
||||||
|
device->KEY3 = *_key++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sl_trng_check_conditioning( TRNG_TypeDef *device )
|
||||||
|
{
|
||||||
|
uint32_t val32;
|
||||||
|
int i, ret=0;
|
||||||
|
uint32_t ctrl = device->CONTROL;
|
||||||
|
|
||||||
|
/* Setup control register */
|
||||||
|
device->CONTROL = TRNG_CONTROL_ENABLE | TRNG_CONTROL_TESTEN |
|
||||||
|
TRNG_CONTROL_BYPNIST | TRNG_CONTROL_BYPAIS31;
|
||||||
|
|
||||||
|
/* Apply software reset */
|
||||||
|
sl_trng_soft_reset(device);
|
||||||
|
|
||||||
|
/* Write test vector to the key register. */
|
||||||
|
sl_trng_set_key(device,
|
||||||
|
(const unsigned char*)test_vector_conditioning_key);
|
||||||
|
|
||||||
|
/* Write test vector to the TESTDATA register */
|
||||||
|
for (i=0; i<TEST_VECTOR_CONDITIONING_INPUT_SIZE; i++)
|
||||||
|
{
|
||||||
|
sl_trng_write_test_data(device,
|
||||||
|
test_vector_conditioning_input[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<TEST_VECTOR_CONDITIONING_OUTPUT_SIZE; i++)
|
||||||
|
{
|
||||||
|
/* Wait for data to become available in the FIFO. */
|
||||||
|
while ( 0 == device->FIFOLEVEL );
|
||||||
|
/* Read output from the conditioning function */
|
||||||
|
val32 = device->FIFO;
|
||||||
|
/* Compare with expected test vector. */
|
||||||
|
if (val32 != test_vector_conditioning_output[i])
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
mbedtls_printf("Conditioning test failed. "
|
||||||
|
"Test output word %d 0x%lx. Expected 0x%lx\n",
|
||||||
|
i, val32, test_vector_conditioning_output[i]);
|
||||||
|
*/
|
||||||
|
ret = SL_TRNG_ERR_CONDITIONING_TEST_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore initial value of control register */
|
||||||
|
device->CONTROL = ctrl;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sl_trng_check_status( TRNG_TypeDef *device )
|
||||||
|
{
|
||||||
|
uint32_t status = device->STATUS;
|
||||||
|
|
||||||
|
if ( (status & (TRNG_STATUS_PREIF
|
||||||
|
| TRNG_STATUS_REPCOUNTIF
|
||||||
|
| TRNG_STATUS_APT64IF
|
||||||
|
| TRNG_STATUS_APT4096IF
|
||||||
|
| TRNG_STATUS_ALMIF)) == 0 )
|
||||||
|
{
|
||||||
|
/* No errors */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( status & TRNG_STATUS_PREIF )
|
||||||
|
{
|
||||||
|
/* On a preliminary noise alarm we clear the FIFO and clear
|
||||||
|
* the alarm. The preliminary noise alarm is not critical. */
|
||||||
|
status &= ~TRNG_STATUS_PREIF;
|
||||||
|
device->STATUS = status;
|
||||||
|
sl_trng_clear_fifo(device);
|
||||||
|
return SL_TRNG_ERR_PRELIMINARY_NOISE_ALARM;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Clear alarm conditions by doing a TRNG soft reset. */
|
||||||
|
sl_trng_soft_reset( device );
|
||||||
|
if ( status & TRNG_STATUS_REPCOUNTIF )
|
||||||
|
{
|
||||||
|
return SL_TRNG_ERR_REPETITION_COUNT_TEST_FAILED;
|
||||||
|
}
|
||||||
|
if ( status & TRNG_STATUS_APT64IF )
|
||||||
|
{
|
||||||
|
return SL_TRNG_ERR_ADAPTIVE_PROPORTION_TEST_64_FAILED;
|
||||||
|
}
|
||||||
|
if ( status & TRNG_STATUS_APT4096IF )
|
||||||
|
{
|
||||||
|
return SL_TRNG_ERR_ADAPTIVE_PROPORTION_TEST_4096_FAILED;
|
||||||
|
}
|
||||||
|
if ( status & TRNG_STATUS_ALMIF )
|
||||||
|
{
|
||||||
|
return SL_TRNG_ERR_NOISE_ALARM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sl_trng_check_entropy( TRNG_TypeDef *device )
|
||||||
|
{
|
||||||
|
volatile uint32_t val32;
|
||||||
|
int i, ret = 0;
|
||||||
|
uint32_t ctrl = device->CONTROL;
|
||||||
|
|
||||||
|
/* Setup control register */
|
||||||
|
device->CONTROL =
|
||||||
|
TRNG_CONTROL_ENABLE |
|
||||||
|
TRNG_CONTROL_REPCOUNTIEN |
|
||||||
|
TRNG_CONTROL_APT64IEN |
|
||||||
|
TRNG_CONTROL_APT4096IEN |
|
||||||
|
TRNG_CONTROL_PREIEN |
|
||||||
|
TRNG_CONTROL_ALMIEN;
|
||||||
|
|
||||||
|
/* Apply software reset */
|
||||||
|
sl_trng_soft_reset(device);
|
||||||
|
|
||||||
|
/* Check FIFO level is non-zero . */
|
||||||
|
for (i=0; i<FIFO_LEVEL_RETRY; i++)
|
||||||
|
{
|
||||||
|
if ( device->FIFOLEVEL )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Check for no data within timeout (max retry count) */
|
||||||
|
if (i>=FIFO_LEVEL_RETRY)
|
||||||
|
{
|
||||||
|
ret = SL_TRNG_ERR_NO_DATA;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Read at least 4097x2 bits (~257 x 32 bits) in order for the longest
|
||||||
|
test to complete (adaptive proportion test of 4096 samples). */
|
||||||
|
for (i=0; i<TEST_WORDS_MIN; i++)
|
||||||
|
{
|
||||||
|
val32 = device->FIFO;
|
||||||
|
(void)val32;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check in status register for errors. */
|
||||||
|
ret = sl_trng_check_status( device );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore initial value of control register */
|
||||||
|
device->CONTROL = ctrl;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sl_trng_read_chunk( TRNG_TypeDef *device,
|
||||||
|
unsigned char *output,
|
||||||
|
size_t len )
|
||||||
|
{
|
||||||
|
uint32_t * out32 = (uint32_t *) output;
|
||||||
|
uint32_t tmp;
|
||||||
|
|
||||||
|
/* Read known good available data. */
|
||||||
|
while ( len >= 4)
|
||||||
|
{
|
||||||
|
*out32++ = device->FIFO;
|
||||||
|
len -= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle the case where len is not a multiple of 4. */
|
||||||
|
if ( len < 4 )
|
||||||
|
{
|
||||||
|
tmp = device->FIFO;
|
||||||
|
memcpy((uint8_t *)out32, (const uint8_t *) &tmp, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int sl_trng_poll( TRNG_TypeDef *device,
|
||||||
|
unsigned char *output,
|
||||||
|
size_t len,
|
||||||
|
size_t *olen )
|
||||||
|
{
|
||||||
|
size_t output_len = 0;
|
||||||
|
size_t count = 0;
|
||||||
|
size_t available;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
while (len > 0)
|
||||||
|
{
|
||||||
|
available = device->FIFOLEVEL * 4;
|
||||||
|
if (available == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(SL_TRNG_IGNORE_ALL_ALARMS)
|
||||||
|
/* Check status for current data in FIFO
|
||||||
|
* and handle any error conditions. */
|
||||||
|
ret = sl_trng_check_status( device );
|
||||||
|
#if defined(SL_TRNG_IGNORE_NOISE_ALARMS)
|
||||||
|
/* Ignore noise alarms by returning 0 (OK) if they occur and
|
||||||
|
* keeping the already generated random data. */
|
||||||
|
if ( (ret == SL_TRNG_ERR_PRELIMINARY_NOISE_ALARM) ||
|
||||||
|
(ret == SL_TRNG_ERR_NOISE_ALARM) )
|
||||||
|
{
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* Alarm has been signaled so we throw the generated data away. */
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
output_len = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
count = SL_MIN(len, available);
|
||||||
|
sl_trng_read_chunk(device, output, count);
|
||||||
|
output += count;
|
||||||
|
output_len += count;
|
||||||
|
len -= count;
|
||||||
|
}
|
||||||
|
|
||||||
|
*olen = output_len;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* TRNG_PRESENT */
|
|
@ -0,0 +1,239 @@
|
||||||
|
/**
|
||||||
|
* \file sl_trng.h
|
||||||
|
*
|
||||||
|
* \brief True Random Number Generator (TRNG) driver for Silicon Labs devices
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#ifndef SL_TRNG_H
|
||||||
|
#define SL_TRNG_H
|
||||||
|
|
||||||
|
/***************************************************************************//**
|
||||||
|
* \addtogroup sl_crypto_trng Silicon Labs True Random Number Generator Plugin
|
||||||
|
* \brief True Random Number Generator (TRNG) driver for Silicon Labs devices.
|
||||||
|
*
|
||||||
|
* \details The EFR32xG12 and EFM32xG12 and newer Silicon Labs devices contains
|
||||||
|
* a True Random Number Generator (TRNG) peripheral. The TRNG is a
|
||||||
|
* non-deterministic random number generator based on a full hardware solution.
|
||||||
|
* The TRNG contains a 64 x 32-bit FIFO for reading out random numbers.
|
||||||
|
*
|
||||||
|
* The samples from entropy source within the TRNG are monitored permanently by
|
||||||
|
* 4 built in tests that detect issues with the noise source. The tests are
|
||||||
|
* specified in NIST-800-90B and AIS31. The tests that are always checking the
|
||||||
|
* entropy source are "Repetition Count Test", "Adaptive Proportion Test
|
||||||
|
* (64-sample window)", "Adaptive Proportion Test (4096-sample window)" and
|
||||||
|
* the "AIS31 Online Test".
|
||||||
|
*
|
||||||
|
* In addition the TRNG has options for running startup tests. When these tests
|
||||||
|
* are enabled the TRNG FIFO will not contains any data before all the startup
|
||||||
|
* tests have passed. There are 4 TRNG startup tests, 3 of the tests are
|
||||||
|
* specified in NIST-800-90B. These are the "Repetition Count Test", "Adaptive
|
||||||
|
* Proportion Test (64-sample window)" and "Adaptive Proportion Test
|
||||||
|
* (4096-sample window)". The last startup test is the AIS31 startup test. By
|
||||||
|
* default when using this driver all the startup tests are enabled.
|
||||||
|
|
||||||
|
* The TRNG module implements an entropy source plugin module for mbed TLS that can
|
||||||
|
* be used in applications needing random numbers or indirectly using mbed TLS
|
||||||
|
* modules that depend on the random number generation interfaces of mbed TLS.
|
||||||
|
* The define @ref MBEDTLS_TRNG_C will compile the TRNG module. The TRNG is enabled as
|
||||||
|
* an mbed TLS entropy source by defining @ref MBEDTLS_ENTROPY_ALT,
|
||||||
|
* @ref MBEDTLS_ENTROPY_INIT_ALT and @ref MBEDTLS_ENTROPY_FREE_ALT.
|
||||||
|
* The TRNG functions are declared in the 'mbedtls/sl_crypto/include/trng.h' file.
|
||||||
|
*
|
||||||
|
* \{
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "em_device.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/* TRNG specific error codes: */
|
||||||
|
#define SL_TRNG_ERR_BASE (0xF100E000)
|
||||||
|
|
||||||
|
/** Conditioning test failed. */
|
||||||
|
#define SL_TRNG_ERR_CONDITIONING_TEST_FAILED ((int)SL_TRNG_ERR_BASE | 0x00000001)
|
||||||
|
|
||||||
|
/** No data received in the TRNG FIFO. */
|
||||||
|
#define SL_TRNG_ERR_NO_DATA ((int)SL_TRNG_ERR_BASE | 0x00000002)
|
||||||
|
|
||||||
|
/** Repetition Count test failed. The repetition count test fails when the
|
||||||
|
* TRNG detects that the output become "stuck" on a single value for a long
|
||||||
|
* period of time. The repetition count test is described in NIST-800-90B.
|
||||||
|
*
|
||||||
|
* If an application detects this error then the TRNG should be reset. The
|
||||||
|
* repetition count test is always enabled. */
|
||||||
|
#define SL_TRNG_ERR_REPETITION_COUNT_TEST_FAILED ((int)SL_TRNG_ERR_BASE | 0x00000003)
|
||||||
|
|
||||||
|
/** Adaptive Proportion test over 64 samples failed. The adaptive proportion
|
||||||
|
* test is designed to detect a large loss of entropy that might occur as a
|
||||||
|
* result of some physical failure or environmental change affecting the
|
||||||
|
* TRNG.
|
||||||
|
*
|
||||||
|
* The test will fail when a 2 bit sample from the TRNG is repeated an
|
||||||
|
* unusual amount of times within a window of 64 bits. The adaptive
|
||||||
|
* proportion test is further described in NIST-800-90B.
|
||||||
|
*
|
||||||
|
* If an application detects this error then the TRNG should be reset. The
|
||||||
|
* adaptive proportion test over 64 samples is always enabled. */
|
||||||
|
#define SL_TRNG_ERR_ADAPTIVE_PROPORTION_TEST_64_FAILED ((int)SL_TRNG_ERR_BASE | 0x00000004)
|
||||||
|
|
||||||
|
/** Adaptive Proportion test over 4096 samples failed. The adaptive proportion
|
||||||
|
* test is designed to detect a large loss of entropy that might occur as a
|
||||||
|
* result of some physical failure or environmental change affecting the
|
||||||
|
* TRNG.
|
||||||
|
*
|
||||||
|
* The test will fail when a 2 bit sample from the TRNG is repeated an
|
||||||
|
* unusual amount of times within a window of 4096 bits. The adaptive
|
||||||
|
* proportion test is further described in NIST-800-90B.
|
||||||
|
*
|
||||||
|
* If an application detects this error then the TRNG should be reset. The
|
||||||
|
* adaptive proportion test over 4096 samples is always enabled. */
|
||||||
|
#define SL_TRNG_ERR_ADAPTIVE_PROPORTION_TEST_4096_FAILED ((int)SL_TRNG_ERR_BASE | 0x00000005)
|
||||||
|
|
||||||
|
/** AIS31 test noise alarm. The AIS31 test is designed to monitor and verify
|
||||||
|
* the statistical distribution of the random numbers from the TRNG. The test
|
||||||
|
* performs 512 consecutive 128 bit X^2 calculations with 4 bit words. The
|
||||||
|
* details of the AIS31 test can be found in the AIS31 specification.
|
||||||
|
*
|
||||||
|
* The test will fail when an unusual statistical distribution of the TRNG
|
||||||
|
* output is found.
|
||||||
|
*
|
||||||
|
* If an application detects this error then the TRNG should be reset. The
|
||||||
|
* AIS31 test is always enabled. */
|
||||||
|
#define SL_TRNG_ERR_NOISE_ALARM ((int)SL_TRNG_ERR_BASE | 0x00000006)
|
||||||
|
|
||||||
|
/** AIS31 test Preliminary Noise alarm. The preliminary noise alarms generated
|
||||||
|
* from the same AIS31 test that generates \ref SL_TRNG_ERR_NOISE_ALARM.
|
||||||
|
* The difference between a preliminary noise alarm and a noise alarm is the
|
||||||
|
* severity and the expected frequency. A preliminary noise alarm will happen
|
||||||
|
* more frequently than a noise alarm, and a preliminary noise alarm is not
|
||||||
|
* considered critical. The preliminary noise alarm is not uncommon and should
|
||||||
|
* be expected from time to time when reading data from the TRNG.
|
||||||
|
*
|
||||||
|
* If an application detects a preliminary noise alarm then the recommended
|
||||||
|
* action is to flush the TRNG FIFO, or reset the TRNG. */
|
||||||
|
#define SL_TRNG_ERR_PRELIMINARY_NOISE_ALARM ((int)SL_TRNG_ERR_BASE | 0x00000007)
|
||||||
|
|
||||||
|
#if defined(TRNG_PRESENT)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initialize TRNG context
|
||||||
|
*
|
||||||
|
* \details This function will enable the TRNG device by starting
|
||||||
|
* the device's clock, initializing the control register, perform
|
||||||
|
* soft reset and wait until data is available in the FIFO.
|
||||||
|
*
|
||||||
|
* \param ctx TRNG device to be initialized
|
||||||
|
*/
|
||||||
|
void sl_trng_init( TRNG_TypeDef *ctx );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Free TRNG context
|
||||||
|
*
|
||||||
|
* \details This function will disable the TRNG peripheral by stopping
|
||||||
|
* the TRNG's clock.
|
||||||
|
*
|
||||||
|
* \param ctx TRNG device to be released
|
||||||
|
*/
|
||||||
|
void sl_trng_free( TRNG_TypeDef *ctx );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Set the TRNG conditioning key
|
||||||
|
*
|
||||||
|
* \param ctx TRNG device
|
||||||
|
* \param key 128-bit AES key
|
||||||
|
*
|
||||||
|
* \return
|
||||||
|
* 0 if success. Error code if failure.
|
||||||
|
*/
|
||||||
|
int sl_trng_set_key( TRNG_TypeDef *ctx, const unsigned char *key );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check the TRNG conditioning function
|
||||||
|
*
|
||||||
|
* \param ctx TRNG device
|
||||||
|
*
|
||||||
|
* \return
|
||||||
|
* 0 if success. \ref SL_TRNG_ERR_CONDITIONING_TEST_FAILED on failure.
|
||||||
|
*/
|
||||||
|
int sl_trng_check_conditioning( TRNG_TypeDef *ctx );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check the TRNG entropy source is producing random data
|
||||||
|
*
|
||||||
|
* \param ctx TRNG device
|
||||||
|
*
|
||||||
|
* \return
|
||||||
|
* 0 if success. Error code if failure. Note that this function can return
|
||||||
|
* a \ref SL_TRNG_ERR_PRELIMINARY_NOISE_ALARM on some occasions.
|
||||||
|
*/
|
||||||
|
int sl_trng_check_entropy( TRNG_TypeDef *ctx );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Poll for entropy data
|
||||||
|
*
|
||||||
|
* \details This function will read available random data from the TRNG
|
||||||
|
* FIFO and place it into the output buffer. The len parameter
|
||||||
|
* tells this function the maximum number of bytes to read.
|
||||||
|
*
|
||||||
|
* Note that the number of bytes read from the TRNG might differ
|
||||||
|
* from the number of bytes requested. If any alarms are signaled
|
||||||
|
* or the TRNG FIFO is empty then this function will return early.
|
||||||
|
*
|
||||||
|
* The return value should be used to see if the operation was
|
||||||
|
* successful of if an alarm was encountered while reading the
|
||||||
|
* FIFO. The content of the olen parameter can be used to check
|
||||||
|
* how many bytes were actually read.
|
||||||
|
*
|
||||||
|
* \param ctx TRNG context
|
||||||
|
* \param output Buffer to fill with data from the TRNG
|
||||||
|
* \param len Maximum number of bytes to fill in output buffer.
|
||||||
|
* \param olen The actual amount of bytes put into the buffer (Can be 0)
|
||||||
|
*
|
||||||
|
* \return \li 0 if no critical failures occurred,
|
||||||
|
* \li SL_TRNG_ERR_PRELIMINARY_NOISE_ALARM if a AIS31
|
||||||
|
* preliminary noise alarm was detected while reading the FIFO,
|
||||||
|
* \li SL_TRNG_ERR_NOISE_ALARM if an AIS31 noise alarm
|
||||||
|
* was detected.
|
||||||
|
* \li SL_TRNG_ERR_REPETITION_COUNT_TEST_FAILED if the
|
||||||
|
* repetition count test failed while reading the FIFO.
|
||||||
|
* \li SL_TRNG_ERR_ADAPTIVE_PROPORTION_TEST_64_FAILED if the
|
||||||
|
* adaptive proportion test over 64 samples failed while reading
|
||||||
|
* the FIFO.
|
||||||
|
* \li SL_TRNG_ERR_ADAPTIVE_PROPORTION_TEST_4096_FAILED if
|
||||||
|
* the adaptive proportion test over 4096 samples failed while
|
||||||
|
* reading from the FIFO.
|
||||||
|
*/
|
||||||
|
int sl_trng_poll( TRNG_TypeDef *ctx,
|
||||||
|
unsigned char *output,
|
||||||
|
size_t len,
|
||||||
|
size_t *olen );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Execute TRNG soft reset
|
||||||
|
*
|
||||||
|
* \details This function performs a TRNG soft reset. The TRNG soft
|
||||||
|
* reset can be used to clear error conditions such as Noise
|
||||||
|
* Alarms, etc.
|
||||||
|
*
|
||||||
|
* \param ctx TRNG device
|
||||||
|
*/
|
||||||
|
void sl_trng_soft_reset( TRNG_TypeDef *ctx );
|
||||||
|
|
||||||
|
#endif /* TRNG_PRESENT */
|
||||||
|
|
||||||
|
/** \} (end addtogroup sl_crypto_trng) */
|
||||||
|
|
||||||
|
#endif /* SL_TRNG_H */
|
|
@ -0,0 +1,55 @@
|
||||||
|
/***************************************************************************//**
|
||||||
|
* @file trng_api.c
|
||||||
|
*******************************************************************************
|
||||||
|
* @section License
|
||||||
|
* <b>(C) Copyright 2017 Silicon Labs, http://www.silabs.com</b>
|
||||||
|
*******************************************************************************
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "trng_api.h"
|
||||||
|
#include "sl_trng.h"
|
||||||
|
|
||||||
|
#if defined(DEVICE_TRNG)
|
||||||
|
static bool is_trng_enabled = false;
|
||||||
|
|
||||||
|
void trng_init(trng_t *obj)
|
||||||
|
{
|
||||||
|
/* Use TRNG0 for all HW entropy collection */
|
||||||
|
obj->instance = TRNG0;
|
||||||
|
|
||||||
|
if(!is_trng_enabled) {
|
||||||
|
sl_trng_init(obj->instance);
|
||||||
|
is_trng_enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void trng_free(trng_t *obj)
|
||||||
|
{
|
||||||
|
/* Don't turn off the TRNG to avoid clearing its FIFO */
|
||||||
|
(void) obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_length)
|
||||||
|
{
|
||||||
|
int ret = sl_trng_poll(obj->instance,
|
||||||
|
output,
|
||||||
|
length,
|
||||||
|
output_length);
|
||||||
|
return (ret == 0) ? 0 : -1;
|
||||||
|
}
|
||||||
|
#endif /* DEVICE_TRNG */
|
|
@ -2454,7 +2454,7 @@
|
||||||
},
|
},
|
||||||
"EFM32PG12_STK3402": {
|
"EFM32PG12_STK3402": {
|
||||||
"inherits": ["EFM32PG12B500F1024GL125"],
|
"inherits": ["EFM32PG12B500F1024GL125"],
|
||||||
"device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
"device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG"],
|
||||||
"forced_reset_timeout": 2,
|
"forced_reset_timeout": 2,
|
||||||
"config": {
|
"config": {
|
||||||
"hf_clock_src": {
|
"hf_clock_src": {
|
||||||
|
@ -2505,7 +2505,7 @@
|
||||||
},
|
},
|
||||||
"TB_SENSE_12": {
|
"TB_SENSE_12": {
|
||||||
"inherits": ["EFR32MG12P332F1024GL125"],
|
"inherits": ["EFR32MG12P332F1024GL125"],
|
||||||
"device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
"device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG"],
|
||||||
"forced_reset_timeout": 5,
|
"forced_reset_timeout": 5,
|
||||||
"config": {
|
"config": {
|
||||||
"hf_clock_src": {
|
"hf_clock_src": {
|
||||||
|
|
Loading…
Reference in New Issue