subsys/random: Add cryptographically secure and bulk fill functions
1) Add cryptographically secure random functions to provide FIPS 140-2 compliant random functions. 2) Add name to random function choice selectors to ease selection in SOC .defconfig files 3) Add bulk fill random functions. Signed-off-by: David Leach <david.leach@nxp.com>
This commit is contained in:
parent
07bf345db3
commit
afdc63f320
|
@ -364,6 +364,7 @@
|
|||
/subsys/net/l2/ @jukkar @tbursztyka
|
||||
/subsys/net/l2/canbus/ @alexanderwachter @jukkar
|
||||
/subsys/power/ @wentongwu @pizi-nordic
|
||||
/subsys/random/ @dleach02
|
||||
/subsys/settings/ @nvlsianpu
|
||||
/subsys/shell/ @jakub-uC @nordic-krch
|
||||
/subsys/storage/ @nvlsianpu
|
||||
|
|
|
@ -12,5 +12,4 @@ CONFIG_GPIO=y
|
|||
CONFIG_PINMUX=y
|
||||
CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=40000000
|
||||
CONFIG_OSC_EXTERNAL=y
|
||||
CONFIG_XOROSHIRO_RANDOM_GENERATOR=y
|
||||
CONFIG_ADC_MCUX_ADC16_VREF_ALTERNATE=y
|
||||
|
|
|
@ -38,13 +38,17 @@ are listed below.
|
|||
* **Serial communication**: This device driver is used by the kernel's
|
||||
system console subsystem.
|
||||
|
||||
* **Random number generator**: This device driver provides a source of random
|
||||
numbers.
|
||||
* **Entropy**: This device driver provides a source of entropy numbers
|
||||
for the random number generator subsystem.
|
||||
|
||||
.. important::
|
||||
|
||||
Certain implementations of the random number generator device driver
|
||||
do not generate sequences of values that are truly random.
|
||||
Use the :ref:`random API functions <random_api>` for random
|
||||
values. :ref:`Entropy functions <entropy_interface>` should not be
|
||||
directly used as a random number generator source as some hardware
|
||||
implementations are designed to be an entropy seed source for random
|
||||
number generators and will not provide cryptographically secure
|
||||
random number streams.
|
||||
|
||||
Synchronous Calls
|
||||
*****************
|
||||
|
|
|
@ -17,6 +17,7 @@ API Reference
|
|||
networking/index.rst
|
||||
peripherals/index.rst
|
||||
power_management/index.rst
|
||||
random/index.rst
|
||||
shell/index.rst
|
||||
storage/index.rst
|
||||
usb/index.rst
|
||||
|
|
|
@ -6,6 +6,10 @@ Entropy
|
|||
Overview
|
||||
********
|
||||
|
||||
The entropy API provides functions to retrieve entropy values from
|
||||
entropy hardware present on the platform. The entropy APIs are provided
|
||||
for use by the random subsystem and cryptographic services. They are not
|
||||
suitable to be used as random number generation functions.
|
||||
|
||||
API Reference
|
||||
*************
|
||||
|
|
101
doc/reference/random/index.rst
Normal file
101
doc/reference/random/index.rst
Normal file
|
@ -0,0 +1,101 @@
|
|||
.. _random_reference:
|
||||
|
||||
Random
|
||||
######
|
||||
|
||||
The random API subsystem provides random number generation APIs in both
|
||||
cryptographically and non-cryptographically secure instances. Which
|
||||
random API to use is based on the cryptographic requirements of the
|
||||
random number. The non-cryptographic APIs will return random values
|
||||
much faster if non-cryptographic values are needed.
|
||||
|
||||
The cryptographically secure random functions shall be compliant to the
|
||||
FIPS 140-2 [NIST02]_ recommended algorithms. Hardware based random-number
|
||||
generators (RNG) can be used on platforms with appropriate hardware support.
|
||||
Platforms without hardware RNG support shall use the `CTR-DRBG algorithm
|
||||
<https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf>`_.
|
||||
The algorithm can be provided by `TinyCrypt <https://01.org/tinycrypt>`_
|
||||
or `mbedTLS <https://tls.mbed.org/ctr-drbg-source-code>`_ depending on
|
||||
your application performance and resource requirements.
|
||||
|
||||
.. note::
|
||||
|
||||
The CTR-DRBG generator needs an entropy source to establish and
|
||||
maintain the cryptographic security of the PRNG.
|
||||
|
||||
.. _random_kconfig:
|
||||
|
||||
Kconfig Options
|
||||
***************
|
||||
|
||||
These options can be found in the following path :zephyr_file:`subsys/random/Kconfig`.
|
||||
|
||||
:option:`CONFIG_TEST_RANDOM_GENERATOR`
|
||||
For testing, this option permits random number APIs to return values
|
||||
that are not truly random.
|
||||
|
||||
The random number generator choice group allows selection of the RNG
|
||||
source function for the system via the RNG_GENERATOR_CHOICE choice group.
|
||||
An override of the default value can be specified in the SOC or board
|
||||
.defconfig file by using:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
choice RNG_GENERATOR_CHOICE
|
||||
default XOROSHIRO_RANDOM_GENERATOR
|
||||
endchoice
|
||||
|
||||
The random number generators available include:
|
||||
|
||||
:option:`CONFIG_X86_TSC_RANDOM_GENERATOR`
|
||||
enables number generator based on timestamp counter of x86 boards,
|
||||
obtained with rdtsc instruction.
|
||||
|
||||
:option:`CONFIG_TIMER_RANDOM_GENERATOR`
|
||||
enables number generator based on system timer clock. This number
|
||||
generator is not random and used for testing only.
|
||||
|
||||
:option:`CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR`
|
||||
enables a random number generator that uses the enabled hardware
|
||||
entropy gathering driver to generate random numbers.
|
||||
|
||||
:option:`CONFIG_XOROSHIRO_RANDOM_GENERATOR`
|
||||
enables the Xoroshiro128+ pseudo-random number generator, that uses the
|
||||
entropy driver as a seed source.
|
||||
|
||||
The CSPRNG_GENERATOR_CHOICE choice group provides selection of the
|
||||
cryptographically secure random number generator source function. An
|
||||
override of the default value can be specified in the SOC or board
|
||||
.defconfig file by using:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
choice CSPRNG_GENERATOR_CHOICE
|
||||
default CTR_DRBG_CSPRNG_GENERATOR
|
||||
endchoice
|
||||
|
||||
The cryptographically secure random number generators available include:
|
||||
|
||||
:option:`CONFIG_HARDWARE_DEVICE_CS_GENERATOR`
|
||||
enables a cryptographically secure random number generator using the
|
||||
hardware random generator driver
|
||||
|
||||
:option:`CONFIG_CTR_DRBG_CSPRNG_GENERATOR`
|
||||
enables the CTR-DRBG pseudo-random number generator. The CTR-DRBG is
|
||||
a FIPS140-2 recommended cryptographically secure random number generator.
|
||||
|
||||
Personalization data can be provided in addition to the entropy source
|
||||
to make the initialization of the CTR-DRBG as unique as possible.
|
||||
|
||||
:option:`CONFIG_CS_CTR_DRBG_PERSONALIZATION`
|
||||
CTR-DRBG Initialization Personalization string
|
||||
|
||||
.. _random_api:
|
||||
|
||||
API Reference
|
||||
*************
|
||||
|
||||
.. doxygengroup:: random_api
|
||||
:project: Zephyr
|
||||
|
||||
|
|
@ -8,16 +8,15 @@ config TINYCRYPT
|
|||
help
|
||||
This option enables the TinyCrypt cryptography library.
|
||||
|
||||
if TINYCRYPT
|
||||
config TINYCRYPT_CTR_PRNG
|
||||
bool "PRNG in counter mode"
|
||||
depends on TINYCRYPT
|
||||
help
|
||||
This option enables support for the pseudo-random number
|
||||
generator in counter mode.
|
||||
|
||||
config TINYCRYPT_SHA256
|
||||
bool "SHA-256 Hash function support"
|
||||
depends on TINYCRYPT
|
||||
help
|
||||
This option enables support for SHA-256
|
||||
hash function primitive.
|
||||
|
@ -38,7 +37,6 @@ config TINYCRYPT_SHA256_HMAC_PRNG
|
|||
|
||||
config TINYCRYPT_ECC_DH
|
||||
bool "ECC_DH anonymous key agreement protocol"
|
||||
depends on TINYCRYPT
|
||||
help
|
||||
This option enables support for the Elliptic curve
|
||||
Diffie-Hellman anonymous key agreement protocol.
|
||||
|
@ -48,7 +46,6 @@ config TINYCRYPT_ECC_DH
|
|||
|
||||
config TINYCRYPT_ECC_DSA
|
||||
bool "ECC_DSA digital signature algorithm"
|
||||
depends on TINYCRYPT
|
||||
help
|
||||
This option enables support for the Elliptic Curve Digital
|
||||
Signature Algorithm (ECDSA).
|
||||
|
@ -58,7 +55,6 @@ config TINYCRYPT_ECC_DSA
|
|||
|
||||
config TINYCRYPT_AES
|
||||
bool "AES-128 decrypt/encrypt"
|
||||
depends on TINYCRYPT
|
||||
help
|
||||
This option enables support for AES-128 decrypt and encrypt.
|
||||
|
||||
|
@ -85,3 +81,4 @@ config TINYCRYPT_AES_CMAC
|
|||
depends on TINYCRYPT_AES
|
||||
help
|
||||
This option enables support for AES-128 CMAC mode.
|
||||
endif
|
||||
|
|
|
@ -8,28 +8,75 @@
|
|||
* @file
|
||||
* @brief Random number generator header file
|
||||
*
|
||||
* This header file declares prototypes for the kernel's random number generator
|
||||
* APIs.
|
||||
* This header file declares prototypes for the kernel's random number
|
||||
* generator APIs.
|
||||
*
|
||||
* Typically, a platform enables the hidden CUSTOM_RANDOM_GENERATOR or
|
||||
* Typically, a platform enables the appropriate source for the random
|
||||
* number generation based on the hardware platform's capabilities or
|
||||
* (for testing purposes only) enables the TEST_RANDOM_GENERATOR
|
||||
* configuration option and provide its own driver that implements
|
||||
* sys_rand32_get().
|
||||
* configuration option.
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_RANDOM_RAND32_H_
|
||||
#define ZEPHYR_INCLUDE_RANDOM_RAND32_H_
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* @brief Random Function APIs
|
||||
* @defgroup random_api Random Function APIs
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Return a 32-bit random value that should pass general
|
||||
* randomness tests.
|
||||
*
|
||||
* @note The random value returned is not a cryptographically secure
|
||||
* random number value.
|
||||
*
|
||||
* @return 32-bit random value.
|
||||
*/
|
||||
extern u32_t sys_rand32_get(void);
|
||||
/**
|
||||
* @brief Fill the destination buffer with random data values that should
|
||||
* pass general randomness tests.
|
||||
*
|
||||
* @note The random values returned are not considered cryptographically
|
||||
* secure random number values.
|
||||
*
|
||||
* @param [out] dst destination buffer to fill with random data.
|
||||
* @param len size of the destination buffer.
|
||||
*
|
||||
*/
|
||||
extern void sys_rand_get(void *dst, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Fill the destination buffer with cryptographically secure
|
||||
* random data values.
|
||||
*
|
||||
* @note If the random values requested do not need to be cryptographically
|
||||
* secure then use sys_rand_get() instead.
|
||||
*
|
||||
* @param [out] dst destination buffer to fill.
|
||||
* @param len size of the destination buffer.
|
||||
*
|
||||
* @return 0 if success, -EIO if entropy reseed error
|
||||
*
|
||||
*/
|
||||
extern int sys_csrand_get(void *dst, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_RANDOM_RAND32_H_ */
|
||||
|
|
|
@ -66,6 +66,17 @@ config ENTROPY_MCUX_TRNG
|
|||
|
||||
endif # ENTROPY_GENERATOR
|
||||
|
||||
choice CSPRNG_GENERATOR_CHOICE
|
||||
default CTR_DRBG_CSPRNG_GENERATOR
|
||||
endchoice
|
||||
|
||||
choice RNG_GENERATOR_CHOICE
|
||||
default XOROSHIRO_RANDOM_GENERATOR
|
||||
endchoice
|
||||
|
||||
config TINYCRYPT
|
||||
default y
|
||||
|
||||
if FLASH
|
||||
|
||||
config SOC_FLASH_MCUX
|
||||
|
|
|
@ -96,4 +96,25 @@ config NET_CONFIG_IEEE802154_DEV_NAME
|
|||
|
||||
endif # NETWORKING
|
||||
|
||||
choice CSPRNG_GENERATOR_CHOICE
|
||||
default CTR_DRBG_CSPRNG_GENERATOR
|
||||
endchoice
|
||||
|
||||
if ENTROPY_GENERATOR
|
||||
#
|
||||
# MBEDTLS is larger but much faster than TinyCrypt so choose wisely
|
||||
#
|
||||
#config MBEDTLS
|
||||
config TINYCRYPT
|
||||
default y
|
||||
endif
|
||||
|
||||
#
|
||||
# KW41Z TRNG entropy source cannot be used as a Hardware RNG source so
|
||||
# use XOROSHIRO for PRNG
|
||||
#
|
||||
choice RNG_GENERATOR_CHOICE
|
||||
default XOROSHIRO_RANDOM_GENERATOR
|
||||
endchoice
|
||||
|
||||
endif # SOC_MKW41Z4
|
||||
|
|
|
@ -1,6 +1,21 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_sources_ifdef(CONFIG_TIMER_RANDOM_GENERATOR rand32_timer.c)
|
||||
zephyr_sources_ifdef(CONFIG_X86_TSC_RANDOM_GENERATOR rand32_timestamp.c)
|
||||
zephyr_sources_ifdef(CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR rand32_entropy_device.c)
|
||||
zephyr_sources_ifdef(CONFIG_XOROSHIRO_RANDOM_GENERATOR rand32_xoroshiro128.c)
|
||||
if (CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR OR
|
||||
CONFIG_TIMER_RANDOM_GENERATOR OR
|
||||
CONFIG_X86_TSC_RANDOM_GENERATOR OR
|
||||
CONFIG_XOROSHIRO_RANDOM_GENERATOR)
|
||||
zephyr_library()
|
||||
endif()
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_TIMER_RANDOM_GENERATOR rand32_timer.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_X86_TSC_RANDOM_GENERATOR rand32_timestamp.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_XOROSHIRO_RANDOM_GENERATOR rand32_xoroshiro128.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_CTR_DRBG_CSPRNG_GENERATOR rand32_ctr_drbg.c)
|
||||
|
||||
if (CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR OR CONFIG_HARDWARE_DEVICE_CS_GENERATOR)
|
||||
zephyr_library_sources(rand32_entropy_device.c)
|
||||
endif()
|
||||
|
||||
if (CONFIG_CTR_DRBG_CSPRNG_GENERATOR)
|
||||
zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS)
|
||||
endif()
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
# Copyright (c) 2017 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
menu "Random subsystem"
|
||||
|
||||
config TEST_RANDOM_GENERATOR
|
||||
bool "Non-random number generator"
|
||||
depends on !ENTROPY_HAS_DRIVER
|
||||
|
@ -13,10 +15,16 @@ config TEST_RANDOM_GENERATOR
|
|||
number generator is not available. The non-random number generator
|
||||
should not be used in a production environment.
|
||||
|
||||
choice
|
||||
choice RNG_GENERATOR_CHOICE
|
||||
prompt "Random generator"
|
||||
default ENTROPY_DEVICE_RANDOM_GENERATOR
|
||||
depends on ENTROPY_HAS_DRIVER || TEST_RANDOM_GENERATOR
|
||||
help
|
||||
Platform dependent non-cryptographically secure random number support.
|
||||
|
||||
If the entropy support of the platform has sufficient performance
|
||||
to support random request then select that. Otherwise, select the
|
||||
XOROSHIRO algorithm
|
||||
|
||||
config X86_TSC_RANDOM_GENERATOR
|
||||
bool "x86 timestamp counter based number generator"
|
||||
|
@ -37,18 +45,73 @@ config ENTROPY_DEVICE_RANDOM_GENERATOR
|
|||
bool "Use entropy driver to generate random numbers"
|
||||
depends on ENTROPY_HAS_DRIVER
|
||||
help
|
||||
Enables a random number generator that uses the enabled
|
||||
hardware entropy gathering driver to generate random
|
||||
numbers.
|
||||
Enables a random number generator that uses the enabled hardware
|
||||
entropy gathering driver to generate random numbers. Should only be
|
||||
selected if hardware entropy driver is designed to be a random
|
||||
number generator source.
|
||||
|
||||
config XOROSHIRO_RANDOM_GENERATOR
|
||||
bool "Use Xoroshiro128+ as PRNG"
|
||||
depends on ENTROPY_HAS_DRIVER
|
||||
help
|
||||
Enables the Xoroshiro128+ pseudo-random number generator, that
|
||||
uses the entropy driver as a seed source. This is not a
|
||||
cryptographically secure random number generator.
|
||||
Enables the Xoroshiro128+ pseudo-random number generator, that uses
|
||||
the entropy driver as a seed source. This is a fast non-cryptographically
|
||||
secure random number generator.
|
||||
|
||||
It is so named because it uses 128 bits of state.
|
||||
|
||||
endchoice
|
||||
endchoice # RNG_GENERATOR_CHOICE
|
||||
|
||||
#
|
||||
# Implied dependency on a cryptographically secure entropy source when
|
||||
# enabling CS generators. ENTROPY_HAS_DRIVER is the flag indicating the
|
||||
# CS entropy source.
|
||||
#
|
||||
config CSPRING_ENABLED
|
||||
# bool "Cryptographically secure RNG functions enabled"
|
||||
bool
|
||||
default y
|
||||
depends on ENTROPY_HAS_DRIVER
|
||||
|
||||
choice CSPRNG_GENERATOR_CHOICE
|
||||
prompt "Cryptographically secure random generator"
|
||||
default HARDWARE_DEVICE_CS_GENERATOR
|
||||
help
|
||||
Platform dependent cryptographically secure random number support.
|
||||
|
||||
If the hardware entropy support of the platform has sufficient
|
||||
performance to support CSRNG then select that. Otherwise, select
|
||||
CTR-DRBG CSPRNG as that is a FIPS140-2 recommmended CSPRNG.
|
||||
|
||||
config HARDWARE_DEVICE_CS_GENERATOR
|
||||
bool "Use hardware random driver for CS random numbers"
|
||||
depends on ENTROPY_HAS_DRIVER
|
||||
help
|
||||
Enables a cryptographically secure random number generator that
|
||||
uses the enabled hardware random number driver to generate
|
||||
random numbers.
|
||||
|
||||
config CTR_DRBG_CSPRNG_GENERATOR
|
||||
bool "Use CTR-DRBG CSPRNG"
|
||||
depends on MBEDTLS || TINYCRYPT
|
||||
depends on ENTROPY_HAS_DRIVER
|
||||
select TINYCRYPT_CTR_PRNG if TINYCRYPT
|
||||
select TINYCRYPT_AES if TINYCRYPT
|
||||
help
|
||||
Enables the CTR-DRBG pseudo-random number generator. This CSPRNG
|
||||
shall use the entropy API for an initialization seed. The CTR-DRBG
|
||||
is a a FIPS140-2 recommended cryptographically secure random number
|
||||
generator.
|
||||
|
||||
endchoice # CSPRNG_GENERATOR_CHOICE
|
||||
|
||||
config CS_CTR_DRBG_PERSONALIZATION
|
||||
string "CTR-DRBG Personalization string"
|
||||
default "zephyr ctr-drbg seed"
|
||||
depends on CTR_DRBG_CSPRNG_GENERATOR
|
||||
help
|
||||
Personalization data can be provided in addition to the entropy
|
||||
source to make the initialization of the CTR-DRBG as unique as
|
||||
possible.
|
||||
|
||||
endmenu
|
||||
|
|
149
subsys/random/rand32_ctr_drbg.c
Normal file
149
subsys/random/rand32_ctr_drbg.c
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright (c) 2019, NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <init.h>
|
||||
#include <device.h>
|
||||
#include <entropy.h>
|
||||
#include <kernel.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(CONFIG_MBEDTLS)
|
||||
#if !defined(CONFIG_MBEDTLS_CFG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include CONFIG_MBEDTLS_CFG_FILE
|
||||
#endif /* CONFIG_MBEDTLS_CFG_FILE */
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
|
||||
#elif defined(CONFIG_TINYCRYPT)
|
||||
|
||||
#include <tinycrypt/ctr_prng.h>
|
||||
#include <tinycrypt/aes.h>
|
||||
#include <tinycrypt/constants.h>
|
||||
|
||||
#endif /* CONFIG_MBEDTLS */
|
||||
|
||||
static K_SEM_DEFINE(state_sem, 1, 1);
|
||||
|
||||
static struct device *entropy_driver;
|
||||
static const unsigned char drbg_seed[] = CONFIG_CS_CTR_DRBG_PERSONALIZATION;
|
||||
|
||||
#if defined(CONFIG_MBEDTLS)
|
||||
|
||||
static mbedtls_ctr_drbg_context ctr_ctx;
|
||||
|
||||
static int ctr_drbg_entropy_func(void *ctx, unsigned char *buf, size_t len)
|
||||
{
|
||||
return entropy_get_entropy(ctx, (void *)buf, len);
|
||||
}
|
||||
|
||||
#elif defined(CONFIG_TINYCRYPT)
|
||||
|
||||
static TCCtrPrng_t ctr_ctx;
|
||||
|
||||
#endif /* CONFIG_MBEDTLS */
|
||||
|
||||
|
||||
static int ctr_drbg_initialize(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Only one entropy device exists, so this is safe even
|
||||
* if the whole operation isn't atomic.
|
||||
*/
|
||||
entropy_driver = device_get_binding(CONFIG_ENTROPY_NAME);
|
||||
if (!entropy_driver) {
|
||||
__ASSERT((entropy_driver != NULL),
|
||||
"Device driver for %s (CONFIG_ENTROPY_NAME) not found. "
|
||||
"Check your build configuration!",
|
||||
CONFIG_ENTROPY_NAME);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MBEDTLS)
|
||||
|
||||
mbedtls_ctr_drbg_init(&ctr_ctx);
|
||||
|
||||
ret = mbedtls_ctr_drbg_seed(&ctr_ctx,
|
||||
ctr_drbg_entropy_func,
|
||||
entropy_driver,
|
||||
drbg_seed,
|
||||
sizeof(drbg_seed));
|
||||
|
||||
if (ret != 0) {
|
||||
mbedtls_ctr_drbg_free(&ctr_ctx);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#elif defined(CONFIG_TINYCRYPT)
|
||||
|
||||
u8_t entropy[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
|
||||
|
||||
entropy_get_entropy(entropy_driver, (void *)&entropy, sizeof(entropy));
|
||||
|
||||
ret = tc_ctr_prng_init(&ctr_ctx,
|
||||
(uint8_t *)&entropy,
|
||||
sizeof(entropy),
|
||||
(uint8_t *)drbg_seed,
|
||||
sizeof(drbg_seed));
|
||||
|
||||
if (ret == TC_CRYPTO_FAIL) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int sys_csrand_get(void *dst, u32_t outlen)
|
||||
{
|
||||
int ret;
|
||||
unsigned int key = irq_lock();
|
||||
|
||||
if (unlikely(!entropy_driver)) {
|
||||
ret = ctr_drbg_initialize();
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MBEDTLS)
|
||||
|
||||
ret = mbedtls_ctr_drbg_random(&ctr_ctx, (unsigned char *)dst, outlen);
|
||||
|
||||
#elif defined(CONFIG_TINYCRYPT)
|
||||
|
||||
u8_t entropy[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
|
||||
|
||||
ret = tc_ctr_prng_generate(&ctr_ctx, 0, 0, (uint8_t *)dst, outlen);
|
||||
|
||||
if (ret == TC_CRYPTO_SUCCESS) {
|
||||
ret = 0;
|
||||
} else if (ret == TC_CTR_PRNG_RESEED_REQ) {
|
||||
|
||||
entropy_get_entropy(entropy_driver,
|
||||
(void *)&entropy, sizeof(entropy));
|
||||
|
||||
ret = tc_ctr_prng_reseed(&ctr_ctx,
|
||||
entropy,
|
||||
sizeof(entropy),
|
||||
drbg_seed,
|
||||
sizeof(drbg_seed));
|
||||
|
||||
ret = tc_ctr_prng_generate(&ctr_ctx, 0, 0,
|
||||
(uint8_t *)dst, outlen);
|
||||
|
||||
ret = (ret == TC_CRYPTO_SUCCESS) ? 0 : -EIO;
|
||||
} else {
|
||||
ret = -EIO;
|
||||
}
|
||||
#endif
|
||||
irq_unlock(key);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -7,9 +7,11 @@
|
|||
#include <sys/atomic.h>
|
||||
#include <kernel.h>
|
||||
#include <drivers/entropy.h>
|
||||
#include <string.h>
|
||||
|
||||
static struct device *entropy_driver;
|
||||
|
||||
#if defined(CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR)
|
||||
u32_t sys_rand32_get(void)
|
||||
{
|
||||
struct device *dev = entropy_driver;
|
||||
|
@ -42,3 +44,70 @@ u32_t sys_rand32_get(void)
|
|||
|
||||
return random_num;
|
||||
}
|
||||
#endif /* CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR */
|
||||
|
||||
static void rand_get(u8_t *dst, size_t outlen)
|
||||
{
|
||||
struct device *dev = entropy_driver;
|
||||
u32_t random_num;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!dev)) {
|
||||
/* Only one entropy device exists, so this is safe even
|
||||
* if the whole operation isn't atomic.
|
||||
*/
|
||||
dev = device_get_binding(CONFIG_ENTROPY_NAME);
|
||||
__ASSERT((dev != NULL),
|
||||
"Device driver for %s (CONFIG_ENTROPY_NAME) not found. "
|
||||
"Check your build configuration!",
|
||||
CONFIG_ENTROPY_NAME);
|
||||
entropy_driver = dev;
|
||||
}
|
||||
|
||||
ret = entropy_get_entropy(dev, dst, outlen);
|
||||
|
||||
if (unlikely(ret < 0)) {
|
||||
/* Use system timer in case the entropy device couldn't deliver
|
||||
* 32-bit of data. There's not much that can be done in this
|
||||
* situation. An __ASSERT() isn't used here as the HWRNG might
|
||||
* still be gathering entropy during early boot situations.
|
||||
*/
|
||||
|
||||
u32_t len = 0;
|
||||
u32_t blocksize = 4;
|
||||
|
||||
while (len < outlen) {
|
||||
random_num = k_cycle_get_32();
|
||||
if ((outlen-len) < sizeof(random_num)) {
|
||||
blocksize = len;
|
||||
(void *)memcpy(&(dst[random_num]),
|
||||
&random_num, blocksize);
|
||||
} else {
|
||||
*((u32_t *)&dst[len]) = random_num;
|
||||
}
|
||||
|
||||
len += blocksize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR)
|
||||
void sys_rand_get(void *dst, size_t outlen)
|
||||
{
|
||||
return rand_get(dst, outlen);
|
||||
}
|
||||
#endif /* CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR */
|
||||
|
||||
#if defined(CONFIG_HARDWARE_DEVICE_CS_GENERATOR)
|
||||
|
||||
int sys_csrand_get(void *dst, size_t outlen)
|
||||
{
|
||||
rand_get(dst, outlen);
|
||||
/* need deeper inspection on hardware based RNG error cases. Right
|
||||
* now the assumption is that the HW will continue providing a stream
|
||||
* of RNG values
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_HARDWARE_DEVICE_CS_GENERATOR */
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <drivers/timer/system_timer.h>
|
||||
#include <kernel.h>
|
||||
#include <sys/atomic.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__GNUC__)
|
||||
|
||||
|
@ -45,4 +46,36 @@ u32_t sys_rand32_get(void)
|
|||
return k_cycle_get_32() + atomic_add(&_rand32_counter, _RAND32_INC);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Fill destination buffer with random numbers
|
||||
*
|
||||
* The non-random number generator returns values that are based off the
|
||||
* target's clock counter, which means that successive calls will return
|
||||
* different values.
|
||||
*
|
||||
* @param dst destination buffer to fill
|
||||
* @param outlen size of destination buffer to fill
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void sys_rand_get(void *dst, size_t outlen)
|
||||
{
|
||||
u32_t len = 0;
|
||||
u32_t blocksize = 4;
|
||||
u32_t ret;
|
||||
u32_t *udst = (u32_t *)dst;
|
||||
|
||||
while (len < outlen) {
|
||||
ret = sys_rand32_get();
|
||||
if ((outlen-len) < sizeof(ret)) {
|
||||
blocksize = len;
|
||||
(void *)memcpy(udst, &ret, blocksize);
|
||||
} else {
|
||||
(*udst++) = ret;
|
||||
}
|
||||
len += blocksize;
|
||||
}
|
||||
}
|
||||
#endif /* __GNUC__ */
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <kernel.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <random/rand32.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -33,3 +34,36 @@ u32_t sys_rand32_get(void)
|
|||
{
|
||||
return z_do_read_cpu_timestamp32();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Fill destination buffer with random numbers
|
||||
*
|
||||
* The non-random number generator returns values that are based off the
|
||||
* target's clock counter, which means that successive calls will return
|
||||
* different values.
|
||||
*
|
||||
* @param dst destination buffer to fill
|
||||
* @param outlen size of destination buffer to fill
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void sys_rand_get(void *dst, size_t outlen)
|
||||
{
|
||||
u32_t len = 0;
|
||||
u32_t blocksize = 4;
|
||||
u32_t ret;
|
||||
u32_t *udst = (u32_t *)dst;
|
||||
|
||||
while (len < outlen) {
|
||||
ret = sys_rand32_get();
|
||||
if ((outlen-len) < sizeof(ret)) {
|
||||
blocksize = len;
|
||||
(void *)memcpy(udst, &ret, blocksize);
|
||||
} else {
|
||||
(*udst++) = ret;
|
||||
}
|
||||
len += blocksize;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,11 +41,10 @@
|
|||
#include <device.h>
|
||||
#include <drivers/entropy.h>
|
||||
#include <kernel.h>
|
||||
#include <string.h>
|
||||
|
||||
static u64_t state[2];
|
||||
|
||||
K_SEM_DEFINE(state_sem, 1, 1);
|
||||
|
||||
static inline u64_t rotl(const u64_t x, int k)
|
||||
{
|
||||
return (x << k) | (x >> (64 - k));
|
||||
|
@ -72,8 +71,6 @@ static int xoroshiro128_initialize(struct device *dev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
k_object_access_all_grant(&state_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -94,22 +91,30 @@ u32_t sys_rand32_get(void)
|
|||
{
|
||||
u32_t ret;
|
||||
|
||||
if (k_sem_take(&state_sem, K_FOREVER) < 0) {
|
||||
/* FIXME: with all threads having access to this semaphore,
|
||||
* it's possible that they can corrupt state_sem in a way
|
||||
* that k_sem_take will fail. This can be abused to
|
||||
* generate numbers without using the xoroshiro128+ RNG.
|
||||
*/
|
||||
return k_cycle_get_32();
|
||||
}
|
||||
|
||||
ret = xoroshiro128_next();
|
||||
|
||||
k_sem_give(&state_sem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void sys_rand_get(void *dst, size_t outlen)
|
||||
{
|
||||
u32_t ret;
|
||||
u32_t blocksize = 4;
|
||||
u32_t len = 0;
|
||||
u32_t *udst = (u32_t *)dst;
|
||||
|
||||
while (len < outlen) {
|
||||
ret = xoroshiro128_next();
|
||||
if ((outlen-len) < sizeof(ret)) {
|
||||
blocksize = len;
|
||||
(void *)memcpy(udst, &ret, blocksize);
|
||||
} else {
|
||||
(*udst++) = ret;
|
||||
}
|
||||
len += blocksize;
|
||||
}
|
||||
}
|
||||
|
||||
/* In-tree entropy drivers will initialize in PRE_KERNEL_1; ensure that they're
|
||||
* initialized properly before initializing ourselves.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue