Add entropy pool and strong random number generator

Entropy pool gathers environmental noise from device drivers, user-space, etc., and returns good random numbers, suitable for cryptographic use. Based on entropy pool design from *BSDs and uses BLAKE2Xs algorithm for CSPRNG output.

Patch also adds /dev/urandom support for using entropy pool RNG and new 'getrandom' system call for getting randomness without file-descriptor usage (thus avoiding file-descriptor exhaustion attacks). The 'getrandom' interface is similar as 'getentropy' and 'getrandom' available on OpenBSD and Linux respectively.
This commit is contained in:
Jussi Kivilinna 2017-03-30 07:38:37 -06:00 committed by Gregory Nutt
parent 21545ab643
commit dffb8a67e3
50 changed files with 2005 additions and 9 deletions

View file

@ -2015,6 +2015,27 @@ config BOARD_RESET_ON_CRASH
If selected the board_crashdump should reset the machine after
saveing the state of the machine
config BOARD_ENTROPY_POOL
bool "Enable Board level storing of entropy pool structure"
default n
depends on CRYPTO_RANDOM_POOL
---help---
Entropy pool structure can be provided by board source.
Use for this is, for example, to allocate entropy pool
from special area of RAM which content is kept over
system reset.
config BOARD_INITRNGSEED
bool "Enable Board level initial seeding of entropy pool RNG"
default n
depends on CRYPTO_RANDOM_POOL
---help---
If enabled, entropy pool random number generator will call
board_init_rndseed() upon initialization. This function
can then provide early entropy seed to the pool through
entropy injection APIs provided at 'nuttx/random.h'.
#endif
config LIB_BOARDCTL
bool "Enable boardctl() interface"
default n

View file

@ -50,4 +50,35 @@ config CRYPTO_SW_AES
implemenations. This needs to support up_aesinitialize() and
aes_cypher() per include/nuttx/crypto/crypto.h.
config CRYPTO_BLAKE2S
bool "BLAKE2s hash algorithm"
default n
---help---
Enable the BLAKE2s hash algorithm
config CRYPTO_RANDOM_POOL
bool "Entropy pool and strong randon number generator"
default n
select CRYPTO_BLAKE2S
---help---
Entropy pool gathers environmental noise from device drivers,
user-space, etc., and returns good random numbers, suitable
for cryptographic use. Based on entropy pool design from
*BSDs and uses BLAKE2Xs algorithm for CSPRNG output.
NOTE: May not actually be cyptographically secure, if
not enough entropy is made available to the entropy pool.
if CRYPTO_RANDOM_POOL
config CRYPTO_RANDOM_POOL_COLLECT_IRQ_RANDOMNESS
bool "Use interrupts to feed timing randomness to entropy pool"
default y
---help---
Feed entropy pool with interrupt randomness from interrupt
dispatch function 'irq_dispatch'. This adds some overhead
for every interrupt handled.
endif # CRYPTO_RANDOM_POOL
endif # CRYPTO

View file

@ -56,6 +56,18 @@ ifeq ($(CONFIG_CRYPTO_SW_AES),y)
CRYPTO_CSRCS += aes.c
endif
# BLAKE2s hash algorithm
ifeq ($(CONFIG_CRYPTO_BLAKE2S),y)
CRYPTO_CSRCS += blake2s.c
endif
# Entropy pool random number generator
ifeq ($(CONFIG_CRYPTO_RANDOM_POOL),y)
CRYPTO_CSRCS += random_pool.c
endif
endif # CONFIG_CRYPTO
ASRCS = $(CRYPTO_ASRCS)
@ -97,4 +109,4 @@ distclean: clean
$(call DELFILE, Make.dep)
$(call DELFILE, .depend)
-include Make.dep
-include Make.dep

606
crypto/blake2s.c Normal file
View file

@ -0,0 +1,606 @@
/****************************************************************************
* crypto/blake2s.c
*
* This code is based on public-domain/CC0 BLAKE2 reference implementation
* by Samual Neves, at https://github.com/BLAKE2/BLAKE2/tree/master/ref
* Copyright 2012, Samuel Neves <sneves@dei.uc.pt>
*
* Copyright (C) 2017 Haltian Ltd. All rights reserved.
* Authors: Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <debug.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/crypto/blake2s.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static const uint32_t blake2s_IV[8] =
{
0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, 0x510e527ful,
0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul
};
static const uint8_t blake2s_sigma[10][16] =
{
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }
};
/****************************************************************************
* Private Functions
****************************************************************************/
static inline uint32_t rotr32(const uint32_t w, const unsigned int c)
{
return (w >> (c & 31)) | (w << ((32 - c) & 31));
}
static void blake2_memcpy(FAR void *dst, FAR const void *src, size_t len)
{
#ifdef BLAKE2_UNALIGNED
FAR uint32_alias_t *idst = dst;
FAR const uint32_alias_t *isrc = src;
FAR uint8_t *bdst;
FAR const uint8_t *bsrc;
while (len >= sizeof(uint32_alias_t))
{
*idst = *isrc;
idst++;
isrc++;
len -= sizeof(uint32_alias_t);
}
bdst = (FAR uint8_t *)idst;
bsrc = (FAR const uint8_t *)isrc;
while (len)
{
*bdst = *bsrc;
bdst++;
bsrc++;
len--;
}
#else
memcpy(dst, set, len);
#endif
}
static void blake2_memset(FAR void *dst, int set, size_t len)
{
#ifdef BLAKE2_UNALIGNED
FAR uint32_alias_t *idst = dst;
FAR uint8_t *bdst;
uint32_t mset;
set &= 0xff;
mset = (uint32_t)set * 0x01010101UL;
while (len >= sizeof(uint32_alias_t))
{
*idst = mset;
idst++;
len -= sizeof(uint32_alias_t);
}
bdst = (FAR uint8_t *)idst;
set &= 0xff;
while (len)
{
*bdst = set;
bdst++;
len--;
}
#else
memset(dst, set, len);
#endif
}
static inline void secure_zero_memory(FAR void *v, size_t n)
{
explicit_bzero(v, n);
}
/* Some helper functions, not necessarily useful */
static int blake2s_is_lastblock(FAR const blake2s_state *S)
{
return S->f[0] != 0;
}
static void blake2s_set_lastblock(FAR blake2s_state *S)
{
S->f[0] = (uint32_t)-1;
}
static void blake2s_increment_counter(FAR blake2s_state *S, const uint32_t inc)
{
S->t[0] += inc;
S->t[1] += (S->t[0] < inc);
}
static void blake2s_init0(FAR blake2s_state *S)
{
size_t i;
blake2_memset(S, 0, sizeof(*S) - sizeof(S->buf));
for (i = 0; i < 8; ++i)
S->h[i] = blake2s_IV[i];
}
static void blake2s_compress(FAR blake2s_state *S,
const uint8_t in[BLAKE2S_BLOCKBYTES])
{
uint32_t m[16];
uint32_t v[16];
size_t i;
unsigned int round;
for (i = 0; i < 16; ++i)
{
m[i] = blake2_load32(in + i * sizeof(m[i]));
}
for (i = 0; i < 8; ++i)
{
v[i] = S->h[i];
}
v[8] = blake2s_IV[0];
v[9] = blake2s_IV[1];
v[10] = blake2s_IV[2];
v[11] = blake2s_IV[3];
v[12] = S->t[0] ^ blake2s_IV[4];
v[13] = S->t[1] ^ blake2s_IV[5];
v[14] = S->f[0] ^ blake2s_IV[6];
v[15] = S->f[1] ^ blake2s_IV[7];
#define G(r,i,a,b,c,d) \
do { \
a = a + b + m[blake2s_sigma[r][2*i+0]]; \
d = rotr32(d ^ a, 16); \
c = c + d; \
b = rotr32(b ^ c, 12); \
a = a + b + m[blake2s_sigma[r][2*i+1]]; \
d = rotr32(d ^ a, 8); \
c = c + d; \
b = rotr32(b ^ c, 7); \
} while(0)
#define ROUND(r) \
do { \
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
} while(0)
/* Size vs performance trade-off. With unrolling, on ARMv7-M function text
* is ~4 KiB and without ~1 KiB. Without unrolling we take ~25% performance
* hit. */
#if 1
/* Smaller, slightly slower. */
for (round = 0; round < 10; round++)
{
ROUND(round);
}
#else
/* Larger, slightly faster. */
(void)(round=0);
ROUND(0);
ROUND(1);
ROUND(2);
ROUND(3);
ROUND(4);
ROUND(5);
ROUND(6);
ROUND(7);
ROUND(8);
ROUND(9);
#endif
#undef G
#undef ROUND
for (i = 0; i < 8; ++i)
{
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
}
}
#ifdef CONFIG_BLAKE2_SELFTEST
/* BLAKE2s self-test from RFC 7693 */
static void selftest_seq(FAR uint8_t *out, size_t len, uint32_t seed)
{
size_t i;
uint32_t t, a, b;
a = 0xDEAD4BAD * seed; /* prime */
b = 1;
/* fill the buf */
for (i = 0; i < len; i++)
{
t = a + b;
a = b;
b = t;
out[i] = (t >> 24) & 0xFF;
}
}
static int blake2s_selftest(void)
{
/* Grand hash of hash results. */
static const uint8_t blake2s_res[32] =
{
0x6a, 0x41, 0x1f, 0x08, 0xce, 0x25, 0xad, 0xcd, 0xfb, 0x02, 0xab, 0xa6,
0x41, 0x45, 0x1c, 0xec, 0x53, 0xc5, 0x98, 0xb2, 0x4f, 0x4f, 0xc7, 0x87,
0xfb, 0xdc, 0x88, 0x79, 0x7f, 0x4c, 0x1d, 0xfe
};
/* Parameter sets. */
static const size_t b2s_md_len[4] = { 16, 20, 28, 32 };
static const size_t b2s_in_len[6] = { 0, 3, 64, 65, 255, 1024 };
size_t i, j, outlen, inlen;
FAR uint8_t *in;
uint8_t md[32], key[32];
blake2s_state ctx;
int ret = -1;
in = malloc(1024);
if (!in)
{
goto out;
}
/* 256-bit hash for testing. */
if (blake2s_init(&ctx, 32))
{
goto out;
}
for (i = 0; i < 4; i++)
{
outlen = b2s_md_len[i];
for (j = 0; j < 6; j++)
{
inlen = b2s_in_len[j];
selftest_seq(in, inlen, inlen); /* unkeyed hash */
blake2s(md, outlen, in, inlen, NULL, 0);
blake2s_update(&ctx, md, outlen); /* hash the hash */
selftest_seq(key, outlen, outlen); /* keyed hash */
blake2s(md, outlen, in, inlen, key, outlen);
blake2s_update(&ctx, md, outlen); /* hash the hash */
}
}
/* Compute and compare the hash of hashes. */
blake2s_final(&ctx, md, 32);
for (i = 0; i < 32; i++)
{
if (md[i] != blake2s_res[i])
goto out;
}
ret = 0;
out:
free(in);
return ret;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/* init2 xors IV with input parameter block */
int blake2s_init_param(FAR blake2s_state *S, FAR const blake2s_param *P)
{
FAR const unsigned char *p = (FAR const unsigned char *)(P);
size_t i;
#ifdef CONFIG_BLAKE2_SELFTEST
static bool selftest_done = false;
int ret;
if (!selftest_done)
{
selftest_done = true;
ret = blake2s_selftest();
DEBUGASSERT(ret == 0);
if (ret)
return -1;
}
#endif
blake2s_init0(S);
/* IV XOR ParamBlock */
for (i = 0; i < 8; ++i)
{
S->h[i] ^= blake2_load32(&p[i * 4]);
}
S->outlen = P->digest_length;
return 0;
}
/* Sequential blake2s initialization */
int blake2s_init(FAR blake2s_state *S, size_t outlen)
{
blake2s_param P[1];
/* Move interval verification here? */
if ((!outlen) || (outlen > BLAKE2S_OUTBYTES))
{
return -1;
}
P->digest_length = (uint8_t)outlen;
P->key_length = 0;
P->fanout = 1;
P->depth = 1;
blake2_store32(P->leaf_length, 0);
blake2_store32(P->node_offset, 0);
blake2_store16(P->xof_length, 0);
P->node_depth = 0;
P->inner_length = 0;
/* memset(P->reserved, 0, sizeof(P->reserved)); */
blake2_memset(P->salt, 0, sizeof(P->salt));
blake2_memset(P->personal, 0, sizeof(P->personal));
return blake2s_init_param(S, P);
}
int blake2s_init_key(FAR blake2s_state *S, size_t outlen, FAR const void *key,
size_t keylen)
{
blake2s_param P[1];
uint8_t block[BLAKE2S_BLOCKBYTES];
if ((!outlen) || (outlen > BLAKE2S_OUTBYTES))
{
return -1;
}
if (!key || !keylen || keylen > BLAKE2S_KEYBYTES)
{
return -1;
}
P->digest_length = (uint8_t) outlen;
P->key_length = (uint8_t) keylen;
P->fanout = 1;
P->depth = 1;
blake2_store32(P->leaf_length, 0);
blake2_store32(P->node_offset, 0);
blake2_store16(P->xof_length, 0);
P->node_depth = 0;
P->inner_length = 0;
/* memset(P->reserved, 0, sizeof(P->reserved)); */
blake2_memset(P->salt, 0, sizeof(P->salt));
blake2_memset(P->personal, 0, sizeof(P->personal));
blake2s_init_param(S, P);
blake2_memset(block, 0, BLAKE2S_BLOCKBYTES);
blake2_memcpy(block, key, keylen);
blake2s_update(S, block, BLAKE2S_BLOCKBYTES);
secure_zero_memory(block, BLAKE2S_BLOCKBYTES); /* Burn the key from stack */
return 0;
}
int blake2s_update(FAR blake2s_state *S, FAR const void *pin, size_t inlen)
{
FAR const unsigned char * in = FAR (const unsigned char *)pin;
size_t left, fill;
if (inlen <= 0)
{
return 0;
}
left = S->buflen;
fill = BLAKE2S_BLOCKBYTES - left;
if (inlen > fill)
{
S->buflen = 0;
if (fill)
{
blake2_memcpy(S->buf + left, in, fill); /* Fill buffer */
}
blake2s_increment_counter(S, BLAKE2S_BLOCKBYTES);
blake2s_compress(S, S->buf); /* Compress */
in += fill;
inlen -= fill;
while (inlen > BLAKE2S_BLOCKBYTES)
{
blake2s_increment_counter(S, BLAKE2S_BLOCKBYTES);
blake2s_compress(S, in);
in += BLAKE2S_BLOCKBYTES;
inlen -= BLAKE2S_BLOCKBYTES;
}
}
blake2_memcpy(S->buf + S->buflen, in, inlen);
S->buflen += inlen;
return 0;
}
int blake2s_final(FAR blake2s_state *S, FAR void *out, size_t outlen)
{
FAR uint8_t *outbuf = out;
uint32_t tmp = 0;
size_t outwords;
size_t padding;
size_t i;
if (out == NULL || outlen < S->outlen)
{
return -1;
}
if (blake2s_is_lastblock(S))
{
return -1;
}
blake2s_increment_counter(S, (uint32_t)S->buflen);
blake2s_set_lastblock(S);
padding = BLAKE2S_BLOCKBYTES - S->buflen;
if (padding)
{
blake2_memset(S->buf + S->buflen, 0, padding);
}
blake2s_compress(S, S->buf);
/* Output hash to out buffer */
outwords = outlen / sizeof(uint32_t);
outwords = (outwords < 8) ? outwords : 8;
for (i = 0; i < outwords; ++i)
{
/* Store full words */
blake2_store32(outbuf, S->h[i]);
outlen -= sizeof(uint32_t);
outbuf += sizeof(uint32_t);
}
if (outwords < 8 && outlen > 0 && outlen < sizeof(uint32_t))
{
/* Store partial word */
blake2_store32(&tmp, S->h[i]);
blake2_memcpy(outbuf, &tmp, outlen);
}
return 0;
}
int blake2s(FAR void *out, size_t outlen, FAR const void *in, size_t inlen,
FAR const void *key, size_t keylen)
{
blake2s_state S[1];
/* Verify parameters */
if (NULL == in && inlen > 0)
{
return -1;
}
if (NULL == out)
{
return -1;
}
if (NULL == key && keylen > 0)
{
return -1;
}
if (!outlen || outlen > BLAKE2S_OUTBYTES)
{
return -1;
}
if (keylen > BLAKE2S_KEYBYTES)
{
return -1;
}
if (keylen > 0)
{
if (blake2s_init_key(S, outlen, key, keylen) < 0)
{
return -1;
}
}
else
{
if (blake2s_init(S, outlen) < 0)
{
return -1;
}
}
blake2s_update(S, (const uint8_t *)in, inlen);
blake2s_final(S, out, outlen);
return 0;
}

561
crypto/random_pool.c Normal file
View file

@ -0,0 +1,561 @@
/****************************************************************************
* crypto/random_pool.c
*
* Copyright (C) 2015-2017 Haltian Ltd. All rights reserved.
* Authors: Juha Niskanen <juha.niskanen@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <debug.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/arch.h>
#include <nuttx/random.h>
#include <nuttx/board.h>
#include <nuttx/crypto/blake2s.h>
/****************************************************************************
* Definitions
****************************************************************************/
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
#define ROTL_32(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
#define ROTR_32(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) )
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
struct blake2xs_rng_s
{
uint32_t out_node_offset;
blake2s_param param;
blake2s_state ctx;
char out_root[BLAKE2S_OUTBYTES];
};
struct rng_s
{
sem_t rd_sem; /* Threads can only exclusively access the RNG */
volatile uint32_t rd_addptr;
volatile uint32_t rd_newentr;
volatile uint8_t rd_rotate;
volatile uint8_t rd_prev_time;
volatile uint16_t rd_prev_irq;
bool output_initialized;
struct blake2xs_rng_s blake2xs;
};
enum
{
POOL_SIZE = ENTROPY_POOL_SIZE,
POOL_MASK = (POOL_SIZE - 1),
MIN_SEED_NEW_ENTROPY_WORDS = 128,
MAX_SEED_NEW_ENTROPY_WORDS = 1024
};
/****************************************************************************
* Private Data
****************************************************************************/
static struct rng_s g_rng;
#ifdef CONFIG_BOARD_ENTROPY_POOL
/* Entropy pool structure can be provided by board source. Use for this is,
* for example, allocate entropy pool from special area of RAM which content
* is kept over system reset. */
# define entropy_pool board_entropy_pool
#else
static struct entropy_pool_s entropy_pool;
#endif
/* Polynomial from paper "The Linux Pseudorandom Number Generator Revisited"
* x^POOL_SIZE + x^104 + x^76 + x^51 + x^25 + x + 1 */
static const uint32_t pool_stir[] = { POOL_SIZE, 104, 76, 51, 25, 1 };
/* Derived from IEEE 802.3 CRC-32 */
static const uint32_t pool_twist[8] =
{
0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Function: addentropy
*
* Description:
*
* This function adds a number of integers into the entropy pool.
* The pool is stirred with a polynomial of degree POOL_SIZE over GF(2).
*
* Code is inspired by add_entropy_words() function of OpenBSD kernel.
*
* Parameters:
* buf - Buffer of integers to be added
* n - Number of elements in buf
* inc_new - Count element as new entry
*
* Returned Value:
* None
*
****************************************************************************/
static void addentropy(FAR const uint32_t *buf, size_t n, bool inc_new)
{
/* Compile time check for that POOL_SIZE is power of two. */
static char pool_size_p2_check[1 - ((POOL_SIZE & (POOL_SIZE - 1)) * 2)];
UNUSED(pool_size_p2_check);
while (n-- > 0)
{
uint32_t rotate;
uint32_t w;
uint32_t i;
rotate = g_rng.rd_rotate;
w = ROTL_32(*buf, rotate);
i = g_rng.rd_addptr = (g_rng.rd_addptr - 1) & POOL_MASK;
/* Normal round, we add 7 bits of rotation to the pool.
* At the beginning of the pool, we add extra 7 bits
* rotation, in order for successive passes spread the
* input bits across the pool evenly.
*/
g_rng.rd_rotate = (rotate + (i ? 7 : 14)) & 31;
/* XOR pool contents corresponding to polynomial terms */
w ^= entropy_pool.pool[(i + pool_stir[1]) & POOL_MASK];
w ^= entropy_pool.pool[(i + pool_stir[2]) & POOL_MASK];
w ^= entropy_pool.pool[(i + pool_stir[3]) & POOL_MASK];
w ^= entropy_pool.pool[(i + pool_stir[4]) & POOL_MASK];
w ^= entropy_pool.pool[(i + pool_stir[5]) & POOL_MASK];
w ^= entropy_pool.pool[i]; /* 2^POOL_SIZE */
entropy_pool.pool[i] = (w >> 3) ^ pool_twist[w & 7];
buf++;
if (inc_new)
{
g_rng.rd_newentr += 1;
}
}
}
/****************************************************************************
* Function: getentropy
*
* Description:
* Hash entropy pool to BLAKE2s context. This is an internal interface for
* seeding out-facing BLAKE2Xs random bit generator from entropy pool.
*
* Code is inspired by extract_entropy() function of OpenBSD kernel.
*
* Note that this function cannot fail, other than by asserting.
*
* Warning: In protected kernel builds, this interface MUST NOT be
* exported to userspace. This interface MUST NOT be used as a
* general-purpose random bit generator!
*
* Parameters:
* S - BLAKE2s instance that will absorb entropy pool
*
* Returned Value:
* None
*
****************************************************************************/
static void getentropy(FAR blake2s_state *S)
{
#ifdef CONFIG_SCHED_CPULOAD
struct cpuload_s load;
#endif
uint32_t tmp;
add_sw_randomness(g_rng.rd_newentr);
/* Absorb the entropy pool */
blake2s_update(S, (FAR const uint32_t *)entropy_pool.pool,
sizeof(entropy_pool.pool));
/* Add something back so repeated calls to this function
* return different values.
*/
tmp = sizeof(entropy_pool.pool);
tmp <<= 27;
#ifdef CONFIG_SCHED_CPULOAD
clock_cpuload(0, &load);
tmp += load.total ^ ROTL_32(load.active, 23);
#endif
add_sw_randomness(tmp);
g_rng.rd_newentr = 0;
}
/* The BLAKE2Xs based random number generator algorithm.
*
* BLAKE2X is a extensible-output function (XOF) variant of BLAKE2 hash
* function. One application of XOFs is use as deterministic random bit
* number generator (DRBG) as used here. BLAKE2 specification is available
* at https://blake2.net/
*
* BLAKE2Xs here implementation is based on public-domain/CC0 BLAKE2 reference
* implementation by Samual Neves, at
* https://github.com/BLAKE2/BLAKE2/tree/master/ref
* Copyright 2012, Samuel Neves <sneves@dei.uc.pt>
*/
static void rng_reseed(void)
{
blake2s_param P = {};
/* Reset output node counter. */
g_rng.blake2xs.out_node_offset = 0;
/* Initialize parameter block */
P.digest_length = BLAKE2S_OUTBYTES;
P.key_length = 0;
P.fanout = 1;
P.depth = 1;
blake2_store32(P.leaf_length, 0);
blake2_store32(P.node_offset, 0);
blake2_store16(P.xof_length, 0xffff);
P.node_depth = 0;
P.inner_length = 0;
g_rng.blake2xs.param = P;
blake2s_init_param(&g_rng.blake2xs.ctx, &g_rng.blake2xs.param);
/* Initialize with randomness from entropy pool */
getentropy(&g_rng.blake2xs.ctx);
/* Absorb also the previous root */
blake2s_update(&g_rng.blake2xs.ctx, g_rng.blake2xs.out_root,
sizeof(g_rng.blake2xs.out_root));
/* Finalize the new root hash */
blake2s_final(&g_rng.blake2xs.ctx, g_rng.blake2xs.out_root,
BLAKE2S_OUTBYTES);
explicit_bzero(&g_rng.blake2xs.ctx, sizeof(g_rng.blake2xs.ctx));
/* Setup parameters for output phase. */
g_rng.blake2xs.param.key_length = 0;
g_rng.blake2xs.param.fanout = 0;
blake2_store32(g_rng.blake2xs.param.leaf_length, BLAKE2S_OUTBYTES);
g_rng.blake2xs.param.inner_length = BLAKE2S_OUTBYTES;
g_rng.blake2xs.param.node_depth = 0;
g_rng.output_initialized = true;
}
static void rng_buf_internal(FAR void *bytes, size_t nbytes)
{
if (!g_rng.output_initialized)
{
if (g_rng.rd_newentr < MIN_SEED_NEW_ENTROPY_WORDS)
{
cryptwarn("Entropy pool RNG initialized with very low entropy. "
" Consider implementing CONFIG_BOARD_INITRNGSEED!\n");
}
rng_reseed();
}
else if (g_rng.rd_newentr >= MAX_SEED_NEW_ENTROPY_WORDS)
{
/* Initial entropy is low. Reseed when we have accumulated more. */
rng_reseed();
}
else if (g_rng.blake2xs.out_node_offset == UINT32_MAX)
{
/* Maximum BLAKE2Xs output reached (2^32-1 output blocks, maximum 128 GiB
* bytes), reseed. */
rng_reseed();
}
/* Output phase for BLAKE2Xs. */
for (; nbytes > 0; ++g_rng.blake2xs.out_node_offset)
{
size_t block_size = MIN(nbytes, BLAKE2S_OUTBYTES);
/* Initialize state */
g_rng.blake2xs.param.digest_length = block_size;
blake2_store32(g_rng.blake2xs.param.node_offset,
g_rng.blake2xs.out_node_offset);
blake2s_init_param(&g_rng.blake2xs.ctx, &g_rng.blake2xs.param);
/* Process state and output random bytes */
blake2s_update(&g_rng.blake2xs.ctx, g_rng.blake2xs.out_root,
sizeof(g_rng.blake2xs.out_root));
blake2s_final(&g_rng.blake2xs.ctx, bytes, block_size);
bytes += block_size;
nbytes -= block_size;
}
}
static void rng_init(void)
{
crypinfo("Initializing RNG\n");
memset(&g_rng, 0, sizeof(struct rng_s));
sem_init(&g_rng.rd_sem, 0, 1);
/* We do not initialize output here because this is called
* quite early in boot and there may not be enough entropy.
*
* Board level may define CONFIG_BOARD_INITRNGSEED if it implements
* early random seeding.
*/
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Function: up_rngaddint
*
* Description:
* Add one integer to entropy pool, contributing a specific kind
* of entropy to pool.
*
* Parameters:
* kindof - Enumeration constant telling where val came from
* val - Integer to be added
*
* Returned Value:
* None
*
****************************************************************************/
void up_rngaddint(enum rnd_source_t kindof, int val)
{
uint32_t buf[1];
buf[0] = val;
up_rngaddentropy(kindof, buf, 1);
}
/****************************************************************************
* Function: up_rngaddentropy
*
* Description:
* Add buffer of integers to entropy pool.
*
* Parameters:
* kindof - Enumeration constant telling where val came from
* buf - Buffer of integers to be added
* n - Number of elements in buf
*
* Returned Value:
* None
*
****************************************************************************/
void up_rngaddentropy(enum rnd_source_t kindof, FAR const uint32_t *buf,
size_t n)
{
uint32_t tbuf[1];
struct timespec ts;
bool new_inc = true;
if (kindof == RND_SRC_IRQ && n > 0)
{
/* Ignore interrupt randomness if previous interrupt was from same
* source. */
if (buf[0] == g_rng.rd_prev_irq)
{
return;
}
g_rng.rd_prev_irq = buf[0];
}
/* We don't actually track what kind of entropy we receive,
* just add it all to pool. One exception is interrupt
* and timer randomness, where we limit rate of new pool entry
* counting to prevent high interrupt rate triggering RNG
* reseeding too fast.
*/
(void)clock_gettime(CLOCK_REALTIME, &ts);
tbuf[0] = ROTL_32(ts.tv_nsec, 17) ^ ROTL_32(ts.tv_sec, 3);
tbuf[0] += ROTL_32(kindof, 27);
tbuf[0] += ROTL_32((uintptr_t)&tbuf[0], 11);
if (kindof == RND_SRC_TIME || kindof == RND_SRC_IRQ)
{
uint8_t curr_time = ts.tv_sec * 8 + ts.tv_nsec / (NSEC_PER_SEC / 8);
/* Allow interrupts/timers increase entropy counter at max rate
* of 8 Hz. */
if (g_rng.rd_prev_time == curr_time)
{
new_inc = false;
}
else
{
g_rng.rd_prev_time = curr_time;
}
}
if (n > 0)
{
tbuf[0] ^= buf[0];
buf++;
n--;
}
addentropy(tbuf, 1, new_inc);
if (n > 0)
{
addentropy(buf, n, new_inc);
}
}
/****************************************************************************
* Function: up_rngreseed
*
* Description:
* Force reseeding random number generator from entropy pool
*
****************************************************************************/
void up_rngreseed(void)
{
while (sem_wait(&g_rng.rd_sem) != 0)
{
assert(errno == EINTR);
}
if (g_rng.rd_newentr >= MIN_SEED_NEW_ENTROPY_WORDS)
{
rng_reseed();
}
sem_post(&g_rng.rd_sem);
}
/****************************************************************************
* Function: up_randompool_initialize
*
* Description:
* Initialize entropy pool and random number generator
*
****************************************************************************/
void up_randompool_initialize(void)
{
rng_init();
#ifdef CONFIG_BOARD_INITRNGSEED
board_init_rngseed();
#endif
}
/****************************************************************************
* Function: getrandom
*
* Description:
* Fill a buffer of arbitrary length with randomness. This is the
* preferred interface for getting random numbers. The traditional
* /dev/random approach is susceptible for things like the attacker
* exhausting file descriptors on purpose.
*
* Note that this function cannot fail, other than by asserting.
*
* Parameters:
* bytes - Buffer for returned random bytes
* nbytes - Number of bytes requested.
*
* Returned Value:
* None
*
****************************************************************************/
void getrandom(FAR void *bytes, size_t nbytes)
{
while (sem_wait(&g_rng.rd_sem) != 0)
{
assert(errno == EINTR);
}
rng_buf_internal(bytes, nbytes);
sem_post(&g_rng.rd_sem);
}

View file

@ -69,6 +69,15 @@ config DEV_URANDOM_CONGRUENTIAL
NOTE: Not cyptographically secure
config DEV_URANDOM_RANDOM_POOL
bool "Entropy pool"
depends on CRYPTO_RANDOM_POOL
---help---
Use the entropy pool CPRNG output for urandom algorithm.
NOTE: May or may not be cyptographically secure, depending upon the
quality entropy available to entropy pool.
config DEV_URANDOM_ARCH
bool "Architecture-specific"
depends on ARCH_HAVE_RNG

View file

@ -60,6 +60,7 @@
#include <nuttx/arch.h>
#include <nuttx/semaphore.h>
#include <nuttx/analog/adc.h>
#include <nuttx/random.h>
#include <nuttx/irq.h>
@ -296,6 +297,10 @@ static ssize_t adc_read(FAR struct file *filep, FAR char *buffer, size_t buflen)
break;
}
/* Feed ADC data to entropy pool */
add_sensor_randomness(msg->am_data);
/* Copy the message to the user buffer */
if (msglen == 1)

View file

@ -49,11 +49,13 @@
#include <string.h>
#include <poll.h>
#include <errno.h>
#include <assert.h>
#include <nuttx/lib/lib.h>
#include <nuttx/lib/xorshift128.h>
#include <nuttx/fs/fs.h>
#include <nuttx/drivers/drivers.h>
#include <nuttx/random.h>
#if defined(CONFIG_DEV_URANDOM) && !defined(CONFIG_DEV_URANDOM_ARCH)
@ -62,13 +64,18 @@
****************************************************************************/
#if !defined(CONFIG_DEV_URANDOM_CONGRUENTIAL) && \
!defined(CONFIG_DEV_URANDOM_XORSHIFT128)
# define CONFIG_DEV_URANDOM_XORSHIFT128 1
!defined(CONFIG_DEV_URANDOM_XORSHIFT128) && \
!defined(CONFIG_DEV_URANDOM_RANDOM_POOL)
# ifdef CONFIG_CRYPTO_RANDOM_POOL
# define CONFIG_DEV_URANDOM_RANDOM_POOL 1
# else
# define CONFIG_DEV_URANDOM_XORSHIFT128 1
# endif
#endif
#ifdef CONFIG_DEV_URANDOM_XORSHIFT128
# define PRNG() do_xorshift128()
#else /* CONFIG_DEV_URANDOM_CONGRUENTIAL */
#elif defined(CONFIG_DEV_URANDOM_CONGRUENTIAL)
# define PRNG() do_congruential()
#endif
@ -158,6 +165,12 @@ static inline uint32_t do_congruential(void)
static ssize_t devurand_read(FAR struct file *filep, FAR char *buffer,
size_t len)
{
#ifdef CONFIG_DEV_URANDOM_RANDOM_POOL
if (len)
{
getrandom(buffer, len);
}
#else
size_t n;
uint32_t rnd;
@ -208,6 +221,7 @@ static ssize_t devurand_read(FAR struct file *filep, FAR char *buffer,
}
while (--n > 0);
}
#endif /* CONFIG_DEV_URANDOM_RANDOM_POOL */
return len;
}
@ -228,6 +242,56 @@ static ssize_t devurand_write(FAR struct file *filep, FAR const char *buffer,
memcpy(&seed, buffer, len);
srand(seed);
return len;
#elif defined(CONFIG_DEV_URANDOM_RANDOM_POOL)
const unsigned int alignmask = sizeof(uint32_t) - 1;
const size_t initlen = len;
uint32_t tmp = 0;
size_t currlen;
if (!len)
{
return 0;
}
/* Seed entropy pool with data from user. */
if ((uintptr_t)buffer & alignmask)
{
/* Make unaligned input aligned. */
currlen = min(sizeof(uint32_t) - ((uintptr_t)buffer & alignmask), len);
memcpy(&tmp, buffer, currlen);
up_rngaddint(RND_SRC_SW, tmp);
len -= currlen;
buffer += currlen;
}
if (len >= sizeof(uint32_t))
{
/* Handle bulk aligned, word-sized data. */
DEBUGASSERT(((uintptr_t)buffer & alignmask) == 0);
currlen = len / sizeof(uint32_t);
up_rngaddentropy(RND_SRC_SW, (FAR uint32_t *)buffer, currlen);
buffer += currlen * sizeof(uint32_t);
len %= sizeof(uint32_t);
}
if (len > 0)
{
/* Handle trailing bytes. */
DEBUGASSERT(len < sizeof(uint32_t));
memcpy(&tmp, buffer, len);
up_rngaddint(RND_SRC_SW, tmp);
}
/* Reseeding of random number generator from entropy pool. */
up_rngreseed();
return initlen;
#else
len = min(len, sizeof(g_prng.u));
memcpy(&g_prng.u, buffer, len);
@ -274,6 +338,8 @@ void devurandom_register(void)
#ifdef CONFIG_DEV_URANDOM_CONGRUENTIAL
srand(10197);
#elif defined(CONFIG_DEV_URANDOM_RANDOM_POOL)
up_randompool_initialize();
#else
g_prng.state.w = 97;
g_prng.state.x = 101;

View file

@ -70,6 +70,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/spi/spi.h>
#include <nuttx/wqueue.h>
#include <nuttx/random.h>
#include <nuttx/semaphore.h>
#include <nuttx/input/touchscreen.h>
@ -624,6 +625,8 @@ static void ads7843e_worker(FAR void *arg)
y = ads7843e_sendcmd(priv, ADS7843_CMD_YPOSITION);
#endif
add_ui_randomness((x << 16) | y);
/* Perform a thresholding operation so that the results will be more stable.
* If the difference from the last sample is small, then ignore the event.
* REVISIT: Should a large change in pressure also generate a event?

View file

@ -60,6 +60,7 @@
#include <nuttx/kmalloc.h>
#include <nuttx/fs/fs.h>
#include <nuttx/input/ajoystick.h>
#include <nuttx/random.h>
#include <nuttx/irq.h>
@ -321,6 +322,8 @@ static void ajoy_sample(FAR struct ajoy_upperhalf_s *priv)
DEBUGASSERT(lower->al_buttons);
sample = lower->al_buttons(lower);
add_ui_randomness(sample);
#if !defined(CONFIG_DISABLE_POLL) || !defined(CONFIG_DISABLE_SIGNALS)
/* Determine which buttons have been newly pressed and which have been
* newly released.

View file

@ -56,6 +56,7 @@
#include <nuttx/kmalloc.h>
#include <nuttx/fs/fs.h>
#include <nuttx/input/buttons.h>
#include <nuttx/random.h>
#include <nuttx/irq.h>
@ -317,6 +318,8 @@ static void btn_sample(FAR struct btn_upperhalf_s *priv)
DEBUGASSERT(lower->bl_buttons);
sample = lower->bl_buttons(lower);
add_ui_randomness(sample);
#if !defined(CONFIG_DISABLE_POLL) || !defined(CONFIG_DISABLE_SIGNALS)
/* Determine which buttons have been newly pressed and which have been
* newly released.

View file

@ -60,6 +60,7 @@
#include <nuttx/kmalloc.h>
#include <nuttx/fs/fs.h>
#include <nuttx/input/djoystick.h>
#include <nuttx/random.h>
#include <nuttx/irq.h>
@ -321,6 +322,8 @@ static void djoy_sample(FAR struct djoy_upperhalf_s *priv)
DEBUGASSERT(lower->dl_sample);
sample = lower->dl_sample(lower);
add_ui_randomness(sample);
#if !defined(CONFIG_DISABLE_POLL) || !defined(CONFIG_DISABLE_SIGNALS)
/* Determine which buttons have been newly pressed and which have been
* newly released.

View file

@ -64,6 +64,7 @@
#include <nuttx/wqueue.h>
#include <nuttx/fs/fs.h>
#include <nuttx/spi/spi.h>
#include <nuttx/random.h>
#include <nuttx/semaphore.h>
#include <nuttx/input/touchscreen.h>
@ -628,6 +629,8 @@ static void max11802_worker(FAR void *arg)
}
while (readycount < 2);
add_ui_randomness((x << 16) | y);
/* Continue to sample the position while the pen is down */
wd_start(priv->wdog, MAX11802_WDOG_DELAY, max11802_wdog, 1,

View file

@ -64,6 +64,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/wqueue.h>
#include <nuttx/random.h>
#include <nuttx/semaphore.h>
#include <nuttx/input/touchscreen.h>
@ -889,6 +890,8 @@ static void mxt_touch_event(FAR struct mxt_dev_s *priv,
sample->pressure = pressure;
sample->valid = true;
add_ui_randomness((x << 16) ^ y ^ (area << 9) ^ (pressure << 1));
/* If this is not the first touch report, then report it as a move:
* Same contact, same ID, but with a new, updated position.
* The CONTACT_REPORT state means that a contacted has been detected,

View file

@ -48,6 +48,7 @@
#include <debug.h>
#include <nuttx/input/stmpe811.h>
#include <nuttx/random.h>
#include "stmpe811.h"
@ -139,6 +140,8 @@ uint16_t stmpe811_tempread(STMPE811_HANDLE handle)
temp1 = stmpe811_getreg8(priv, STMPE811_SYS_CTRL2);
temp2 = stmpe811_getreg8(priv, STMPE811_SYS_CTRL2+1);
add_sensor_randomness((temp1 << 8) | temp2);
/* Scale the temperature (where Vio is assumed to be .33) */
temp = ((uint32_t)(temp1 & 3) << 8) | temp2;

View file

@ -62,6 +62,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/wqueue.h>
#include <nuttx/random.h>
#include <nuttx/arch.h>
#include <nuttx/input/touchscreen.h>
@ -534,6 +535,8 @@ static ssize_t stmpe811_read(FAR struct file *filep, FAR char *buffer, size_t le
report->point[0].y = sample.y;
report->point[0].pressure = sample.z;
add_ui_randomness((sample.x << 16) ^ (sample.y << 8) ^ sample.z);
/* Report the appropriate flags */
if (sample.contact == CONTACT_UP)

View file

@ -68,6 +68,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/wqueue.h>
#include <nuttx/random.h>
#include <nuttx/input/touchscreen.h>
#include <nuttx/input/tsc2007.h>
@ -619,7 +620,7 @@ static void tsc2007_worker(FAR void *arg)
* vertical or horizontal resistive network. The A/D converter converts
* the voltage measured at the point where the panel is touched. A measurement
* of the Y position of the pointing device is made by connecting the X+
* input to a data converter chip, turning on the Y+ and Y drivers, and
* input to a data converter chip, turning on the Y+ and Y- drivers, and
* digitizing the voltage seen at the X+ input ..."
*
* "... it is recommended that whenever the host writes to the TSC2007, the
@ -698,6 +699,8 @@ static void tsc2007_worker(FAR void *arg)
priv->sample.y = y;
priv->sample.pressure = pressure;
priv->sample.valid = true;
add_ui_randomness((x << 16) ^ y ^ (pressure << 9));
}
/* Note the availability of new measurements */

View file

@ -48,6 +48,7 @@
#include <nuttx/kmalloc.h>
#include <nuttx/sensors/adxl345.h>
#include <nuttx/random.h>
#include "adxl345.h"
@ -165,6 +166,9 @@ static ssize_t adxl345_read(FAR struct file *filep, FAR char *buffer, size_t len
sample.data_z = adxl345_getreg8(priv, ADXL345_DATAZ1);
sample.data_z = (sample.data_z << 8) | adxl345_getreg8(priv, ADXL345_DATAZ0);
add_sensor_randomness(sample.data_x);
add_sensor_randomness((sample.data_z << 16) | sample.data_y);
/* Return read sample */
buffer = (FAR char *) &sample;

View file

@ -51,6 +51,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/sensors/bh1750fvi.h>
#include <nuttx/random.h>
#if defined(CONFIG_I2C) && defined(CONFIG_BH1750FVI)
@ -250,6 +251,8 @@ static ssize_t bh1750fvi_read(FAR struct file *filep, FAR char *buffer,
buffer[0] = lux & 0xFF;
buffer[1] = (lux & 0xFF00) >> 8;
add_sensor_randomness(lux);
return buflen;
}

View file

@ -51,6 +51,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/sensors/bmg160.h>
#include <nuttx/random.h>
#if defined(CONFIG_SPI) && defined(CONFIG_BMG160)
@ -243,6 +244,10 @@ static void bmg160_read_measurement_data(FAR struct bmg160_dev_s *dev)
/* Give back the semaphore */
sem_post(&dev->datasem);
/* Feed sensor data to entropy pool */
add_sensor_randomness((x_gyr << 16) ^ (y_gyr << 8) ^ z_gyr);
}
/****************************************************************************

View file

@ -53,6 +53,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/sensors/bmp180.h>
#include <nuttx/random.h>
#if defined(CONFIG_I2C) && defined(CONFIG_BMP180)
@ -464,6 +465,10 @@ static int bmp180_getpressure(FAR struct bmp180_dev_s *priv)
bmp180_read_press_temp(priv);
/* Feed raw sensor data to entropy pool */
add_sensor_randomness((priv->bmp180_utemp << 16) ^ priv->bmp180_upress);
/* Calculate true temperature */
x1 = ((priv->bmp180_utemp - priv->bmp180_cal_ac6) * priv->bmp180_cal_ac5) >> 15;

View file

@ -51,6 +51,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/sensors/kxtj9.h>
#include <nuttx/random.h>
#if defined(CONFIG_I2C) && defined(CONFIG_SENSOR_KXTJ9)
@ -459,6 +460,12 @@ static int kxtj9_read_sensor_data(FAR struct kxtj9_dev_s *priv,
kxtj9_reg_read(priv, INT_REL, &data, 1);
sem_post(&priv->exclsem);
/* Feed sensor data to entropy pool */
add_sensor_randomness((acc_data[0] << 16) ^ (acc_data[1] << 8) ^
acc_data[2]);
return OK;
}

View file

@ -49,6 +49,7 @@
#include <nuttx/kmalloc.h>
#include <nuttx/wqueue.h>
#include <nuttx/random.h>
#include <nuttx/fs/fs.h>
@ -257,6 +258,10 @@ static void l3gd20_read_measurement_data(FAR struct l3gd20_dev_s *dev)
/* Give back the semaphore */
sem_post(&dev->datasem);
/* Feed sensor data to entropy pool */
add_sensor_randomness((x_gyr << 16) ^ (y_gyr << 8) ^ (z_gyr << 0));
}
/****************************************************************************

View file

@ -48,6 +48,7 @@
#include <nuttx/kmalloc.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/sensors/lis331dl.h>
#include <nuttx/random.h>
#if defined(CONFIG_I2C) && defined(CONFIG_LIS331DL)
@ -414,6 +415,11 @@ lis331dl_getreadings(FAR struct lis331dl_dev_s * dev)
return NULL;
}
/* Feed sensor data to entropy pool */
add_sensor_randomness((retval[2] << 16) ^ (retval[4] << 8) ^
(retval[6] << 0));
dev->a.x = retval[2];
dev->a.y = retval[4];
dev->a.z = retval[6];

View file

@ -48,6 +48,7 @@
#include <nuttx/kmalloc.h>
#include <nuttx/wqueue.h>
#include <nuttx/random.h>
#include <nuttx/fs/fs.h>
#include <nuttx/sensors/lis3dsh.h>
@ -245,6 +246,10 @@ static void lis3dsh_read_measurement_data(FAR struct lis3dsh_dev_s *dev)
/* Give back the semaphore */
sem_post(&dev->datasem);
/* Feed sensor data to entropy pool */
add_sensor_randomness((x_acc << 16) ^ (y_acc << 8) ^ (z_acc << 0));
}
/****************************************************************************

View file

@ -47,6 +47,7 @@
#include <nuttx/kmalloc.h>
#include <nuttx/wqueue.h>
#include <nuttx/random.h>
#include <nuttx/fs/fs.h>
#include <nuttx/sensors/lis3mdl.h>
@ -251,6 +252,11 @@ static void lis3mdl_read_measurement_data(FAR struct lis3mdl_dev_s *dev)
/* Give back the semaphore */
sem_post(&dev->datasem);
/* Feed sensor data to entropy pool */
add_sensor_randomness((x_mag << 16) ^ (y_mag << 10) ^ (z_mag << 2) ^
temperature);
}
/****************************************************************************

View file

@ -49,6 +49,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/sensors/lm75.h>
#include <nuttx/random.h>
#if defined(CONFIG_I2C) && defined(CONFIG_I2C_LM75)
@ -269,6 +270,8 @@ static int lm75_readtemp(FAR struct lm75_dev_s *priv, FAR b16_t *temp)
return ret;
}
add_sensor_randomness(temp16);
sninfo("Centigrade: %08x\n", temp16);
/* Was fahrenheit requested? */

View file

@ -51,6 +51,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/sensors/lm92.h>
#include <nuttx/random.h>
#if defined(CONFIG_I2C) && defined(CONFIG_LM92)
@ -272,6 +273,8 @@ static int lm92_readtemp(FAR struct lm92_dev_s *priv, FAR b16_t *temp)
return ret;
}
add_sensor_randomness(temp16);
sninfo("Centigrade: %08x\n", temp16);
/* Was Fahrenheit requested? */

View file

@ -50,6 +50,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/sensors/lsm9ds1.h>
#include <nuttx/random.h>
#if defined(CONFIG_I2C) && defined(CONFIG_SN_LSM9DS1)
@ -1244,6 +1245,7 @@ static ssize_t lsm9ds1_read(FAR struct file *filep, FAR char *buffer,
uint8_t regaddr;
uint8_t lo;
uint8_t hi;
uint32_t merge = 0;
/* Sanity check */
@ -1301,6 +1303,10 @@ static ssize_t lsm9ds1_read(FAR struct file *filep, FAR char *buffer,
data = ((uint16_t)hi << 8) | (uint16_t)lo;
/* Collect entropy */
merge += data ^ (merge >> 16);
/* The value is positive */
if (data < 0x8000)
@ -1329,6 +1335,10 @@ static ssize_t lsm9ds1_read(FAR struct file *filep, FAR char *buffer,
}
}
/* Feed sensor data to entropy pool */
add_sensor_randomness(merge);
return nsamples * samplesize;
}

View file

@ -54,6 +54,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/spi/spi.h>
#include <nuttx/sensors/max31855.h>
#include <nuttx/random.h>
#if defined(CONFIG_SPI) && defined(CONFIG_MAX31855)
@ -220,6 +221,10 @@ static ssize_t max31855_read(FAR struct file *filep, FAR char *buffer, size_t bu
sninfo("Read from MAX31855 = 0x%08X\n", regval);
/* Feed sensor data to entropy pool */
add_sensor_randomness(regval);
/* If negative, fix signal bits */
if (regval & 0x80000000)

View file

@ -54,6 +54,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/spi/spi.h>
#include <nuttx/sensors/max6675.h>
#include <nuttx/random.h>
#if defined(CONFIG_SPI) && defined(CONFIG_MAX6675)
@ -230,6 +231,10 @@ static ssize_t max6675_read(FAR struct file *filep, FAR char *buffer, size_t buf
ret = -EINVAL;
}
/* Feed sensor data to entropy pool */
add_sensor_randomness(regval);
/* Get the temperature */
*temp = (regval & MAX6675_TEMP_COUPLE) >> 3;

View file

@ -51,6 +51,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/sensors/mb7040.h>
#include <nuttx/random.h>
#if defined(CONFIG_I2C) && defined(CONFIG_MB7040)
@ -323,6 +324,10 @@ static int mb7040_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
if (ret == OK)
{
*ptr = (int32_t)range;
/* Feed sensor data to entropy pool */
add_sensor_randomness(range);
}
sninfo("range: %04x ret: %d\n", *ptr, ret);

View file

@ -50,6 +50,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/sensors/mcp9844.h>
#include <nuttx/random.h>
#if defined(CONFIG_I2C) && defined(CONFIG_MCP9844)
@ -274,6 +275,10 @@ static int mcp9844_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
if (ret == OK)
{
/* Feed sensor data to entropy pool */
add_sensor_randomness(raw_temperature);
/* BIT15 - 13 contain information if preset temperature values
* have been exceeded or undercut. BIT12 is now not any longer
* needed since we do have the sign information retrieved.

View file

@ -50,6 +50,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/sensors/mlx90393.h>
#include <nuttx/random.h>
#if defined(CONFIG_SPI) && defined(CONFIG_MLX90393)
@ -232,6 +233,11 @@ static void mlx90393_read_measurement_data(FAR struct mlx90393_dev_s *dev)
/* Give back the semaphore */
sem_post(&dev->datasem);
/* Feed sensor data to entropy pool */
add_sensor_randomness((x_mag << 17) ^ (y_mag << 9) ^ (z_mag << 1) ^
temperature);
}
/****************************************************************************

View file

@ -50,6 +50,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/spi/spi.h>
#include <nuttx/sensors/mpl115a.h>
#include <nuttx/random.h>
#if defined(CONFIG_SPI) && defined(CONFIG_MPL115A)
@ -227,6 +228,11 @@ static void mpl115a_read_press_temp(FAR struct mpl115a_dev_s *priv)
priv->mpl115a_temperature >>= 6; /* Tadc is 10bit unsigned */
sninfo("Temperature = %d\n", priv->mpl115a_temperature);
/* Feed sensor data to entropy pool */
add_sensor_randomness((priv->mpl115a_pressure << 16) ^
priv->mpl115a_temperature);
}
/****************************************************************************

View file

@ -53,6 +53,7 @@
#include <nuttx/arch.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/sensors/ms58xx.h>
#include <nuttx/random.h>
#if defined(CONFIG_I2C) && defined(CONFIG_MS58XX)
@ -725,6 +726,8 @@ static int ms58xx_measure(FAR struct ms58xx_dev_s *priv)
return ret;
}
add_sensor_randomness(rawpress ^ rawtemp);
diff = (int32_t)rawtemp - (int32_t)priv->c5 * ((int32_t)1 << 8);
temp = (int32_t)((int64_t)2000 +
(int64_t)diff * (int64_t)priv->c6 / ((int64_t)1 << 23));

View file

@ -48,6 +48,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/sensors/veml6070.h>
#include <nuttx/random.h>
#if defined(CONFIG_I2C) && defined(CONFIG_VEML6070)
@ -272,6 +273,10 @@ static ssize_t veml6070_read(FAR struct file *filep, FAR char *buffer,
buffer[0] = regdata;
/* Feed sensor data to entropy pool */
add_sensor_randomness((buffer[1] << 16) ^ buffer[0]);
return buflen;
}

View file

@ -49,6 +49,7 @@
#include <nuttx/kmalloc.h>
#include <nuttx/spi/spi.h>
#include <nuttx/sensors/xen1210.h>
#include <nuttx/random.h>
#include "xen1210.h"
@ -442,6 +443,12 @@ void xen1210_getdata(FAR struct xen1210_dev_s *priv)
#ifdef CONFIG_XEN1210_REGDEBUG
_err("%02x->%02x\n", regaddr, regval);
#endif
/* Feed sensor data to entropy pool */
add_sensor_randomness((priv->sample.data_x << 8) ^
(priv->sample.data_y << 4) ^
(priv->sample.data_z << 4));
}
/****************************************************************************

View file

@ -646,4 +646,20 @@ void board_crashdump(uintptr_t currentsp, FAR void *tcb,
int lineno);
#endif
/****************************************************************************
* Name: board_initrngseed
*
* Description:
* If CONFIG_BOARD_INITRNGSEED is selected then board_init_rngseed is
* called at up_randompool_initialize() to feed initial random seed
* to RNG. Implemenation of this functions should feed at least
* MIN_SEED_NEW_ENTROPY_WORDS 32-bit random words to entropy-pool using
* up_rngaddentropy() or up_rngaddint().
*
****************************************************************************/
#ifdef CONFIG_BOARD_INITRNGSEED
void board_init_rngseed(void);
#endif
#endif /* __INCLUDE_NUTTX_BOARD_H */

View file

@ -0,0 +1,197 @@
/****************************************************************************
* include/nuttx/crypto/blake2s.h
*
* This code is based on public-domain/CC0 BLAKE2 reference implementation
* by Samual Neves, at https://github.com/BLAKE2/BLAKE2/tree/master/ref
* Copyright 2012, Samuel Neves <sneves@dei.uc.pt>
*
* Copyright (C) 2017 Haltian Ltd. All rights reserved.
* Authors: Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_CRYPTO_BLAKE2S_H
#define __INCLUDE_NUTTX_CRYPTO_BLAKE2S_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
enum blake2s_constant
{
BLAKE2S_BLOCKBYTES = 64,
BLAKE2S_OUTBYTES = 32,
BLAKE2S_KEYBYTES = 32,
BLAKE2S_SALTBYTES = 8,
BLAKE2S_PERSONALBYTES = 8
};
typedef struct blake2s_state__
{
uint32_t h[8];
uint32_t t[2];
uint32_t f[2];
size_t buflen;
size_t outlen;
uint8_t buf[BLAKE2S_BLOCKBYTES];
} blake2s_state;
typedef struct blake2s_param__
{
uint8_t digest_length; /* 1 */
uint8_t key_length; /* 2 */
uint8_t fanout; /* 3 */
uint8_t depth; /* 4 */
uint8_t leaf_length[4]; /* 8 */
uint8_t node_offset[4]; /* 12 */
uint8_t xof_length[2]; /* 14 */
uint8_t node_depth; /* 15 */
uint8_t inner_length; /* 16 */
/* uint8_t reserved[0]; */
uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */
uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */
} blake2s_param;
#ifdef __GNUC__ > 3
#define BLAKE2_UNALIGNED 1
typedef uint32_t uint32_alias_t __attribute__((may_alias, aligned(1)));
typedef uint16_t uint16_alias_t __attribute__((may_alias, aligned(1)));
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/* Streaming API */
int blake2s_init(FAR blake2s_state *S, size_t outlen);
int blake2s_init_key(FAR blake2s_state *S, size_t outlen, FAR const void *key,
size_t keylen);
int blake2s_init_param(FAR blake2s_state *S, FAR const blake2s_param *P);
int blake2s_update(FAR blake2s_state *S, FAR const void *in, size_t inlen);
int blake2s_final(FAR blake2s_state *S, FAR void *out, size_t outlen);
/* Simple API */
int blake2s(FAR void *out, size_t outlen, FAR const void *in, size_t inlen,
FAR const void *key, size_t keylen);
/****************************************************************************
* Public Inline Functions
****************************************************************************/
static inline uint32_t blake2_load32(FAR const void *src)
{
#if defined(BLAKE2_UNALIGNED) && !defined(CONFIG_ENDIAN_BIG)
return *(FAR uint32_alias_t *)src;
#elif !defined(CONFIG_ENDIAN_BIG)
FAR const uint8_t *p = (FAR const uint8_t *)src;
return ((uint32_t)(p[0]) << 24) |
((uint32_t)(p[1]) << 16) |
((uint32_t)(p[2]) << 8) |
((uint32_t)(p[3]) << 0);
#else
FAR const uint8_t *p = (FAR const uint8_t *)src;
return ((uint32_t)(p[0]) << 0) |
((uint32_t)(p[1]) << 8) |
((uint32_t)(p[2]) << 16) |
((uint32_t)(p[3]) << 24);
#endif
}
static inline uint16_t blake2_load16(FAR const void *src)
{
#if defined(BLAKE2_UNALIGNED) && !defined(CONFIG_ENDIAN_BIG)
return *(FAR uint16_alias_t *)src;
#elif !defined(CONFIG_ENDIAN_BIG)
const uint8_t *p = (FAR const uint8_t *)src;
return ((uint16_t)(p[0]) << 8) | ((uint16_t)(p[1]) << 0);
#else
const uint8_t *p = (FAR const uint8_t *)src;
return ((uint16_t)(p[0]) << 0) | ((uint16_t)(p[1]) << 8);
#endif
}
static inline void blake2_store16(FAR void *dst, uint16_t w)
{
#if defined(BLAKE2_UNALIGNED) && !defined(CONFIG_ENDIAN_BIG)
*(FAR uint16_alias_t *)dst = w;
#elif !defined(CONFIG_ENDIAN_BIG)
FAR uint8_t *p = (FAR uint8_t *)dst;
p[1] = (uint8_t)w; w >>= 8;
p[0] = (uint8_t)w;
#else
FAR uint8_t *p = (FAR uint8_t *)dst;
p[0] = (uint8_t)w; w >>= 8;
p[1] = (uint8_t)w;
#endif
}
static inline void blake2_store32(FAR void *dst, uint32_t w)
{
#if defined(BLAKE2_UNALIGNED) && !defined(CONFIG_ENDIAN_BIG)
*(FAR uint32_alias_t *)dst = w;
#elif !defined(CONFIG_ENDIAN_BIG)
FAR uint8_t *p = (FAR uint8_t *) dst;
p[0] = (uint8_t)(w >> 24);
p[1] = (uint8_t)(w >> 16);
p[2] = (uint8_t)(w >> 8);
p[3] = (uint8_t)(w >> 0);
#else
FAR uint8_t *p = (FAR uint8_t *) dst;
p[0] = (uint8_t)(w >> 0);
p[1] = (uint8_t)(w >> 8);
p[2] = (uint8_t)(w >> 16);
p[3] = (uint8_t)(w >> 24);
#endif
}
#ifdef __cplusplus
}
#endif
#endif /* __INCLUDE_NUTTX_CRYPTO_BLAKE2S_H */

171
include/nuttx/random.h Normal file
View file

@ -0,0 +1,171 @@
/****************************************************************************
* include/nuttx/random.h
*
* Copyright (C) 2015-2017 Haltian Ltd. All rights reserved.
* Authors: Juha Niskanen <juha.niskanen@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_RANDOM_H
#define __INCLUDE_NUTTX_RANDOM_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stddef.h>
#include <sys/random.h> /* getrandom() */
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Size of entropy pool in 32-bit integers, must be power of two */
#define ENTROPY_POOL_SIZE 128
#define add_irq_randomness(x) up_rngaddint(RND_SRC_IRQ, (x))
#define add_sensor_randomness(x) up_rngaddint(RND_SRC_SENSOR, (x))
#define add_time_randomness(x) up_rngaddint(RND_SRC_TIME, (x))
#define add_hw_randomness(x) up_rngaddint(RND_SRC_HW, (x))
#define add_sw_randomness(x) up_rngaddint(RND_SRC_SW, (x))
#define add_ui_randomness(x) up_rngaddint(RND_SRC_UI, (x))
/* Allow above macros to always exist in source without ifdefs */
#ifndef CONFIG_CRYPTO_RANDOM_POOL
# define up_rngaddint(k, x) ((void)(k),(void)(x))
# define up_rngaddentropy(k, buf, n) ((void)(k),(void)(buf),(void)(x))
#endif
/****************************************************************************
* Public Type Definitions
****************************************************************************/
/* Entropy pool structure */
struct entropy_pool_s
{
volatile uint32_t pool[ENTROPY_POOL_SIZE];
};
/* Randomness sources */
enum rnd_source_t
{
RND_SRC_TIME = 0,
RND_SRC_IRQ,
RND_SRC_SENSOR,
RND_SRC_HW, /* unique per HW UID or coming from factory line. */
RND_SRC_SW, /* unique per SW version. */
RND_SRC_UI /* buttons etc. user-visible interface elements. */
};
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef CONFIG_BOARD_ENTROPY_POOL
/* Entropy pool structure can be provided by board source. Use for this is,
* for example, allocate entropy pool from special area of RAM which content
* is kept over system reset. */
extern struct entropy_pool_s board_entropy_pool;
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifdef CONFIG_CRYPTO_RANDOM_POOL
/****************************************************************************
* Function: up_rngaddint
*
* Description:
* Add one integer to entropy pool, contributing a specific kind
* of entropy to pool.
*
* Parameters:
* kindof - Enumeration constant telling where val came from
* val - Integer to be added
*
* Returned Value:
* None
*
****************************************************************************/
void up_rngaddint(enum rnd_source_t kindof, int val);
/****************************************************************************
* Function: up_rngaddentropy
*
* Description:
* Add buffer of integers to entropy pool.
*
* Parameters:
* kindof - Enumeration constant telling where val came from
* buf - Buffer of integers to be added
* n - Number of elements in buf
*
* Returned Value:
* None
*
****************************************************************************/
void up_rngaddentropy(enum rnd_source_t kindof, FAR const uint32_t *buf,
size_t n);
/****************************************************************************
* Function: up_rngreseed
*
* Description:
* Force reseeding random number generator from entropy pool
*
****************************************************************************/
void up_rngreseed(void);
/****************************************************************************
* Function: up_randompool_initialize
*
* Description:
* Initialize entropy pool and random number generator
*
****************************************************************************/
void up_randompool_initialize(void);
#endif /* CONFIG_CRYPTO_RANDOM_POOL */
#endif /* __INCLUDE_NUTTX_RANDOM_H */

View file

@ -93,6 +93,8 @@ FAR void *memcpy(FAR void *dest, FAR const void *src, size_t n);
FAR void *memmove(FAR void *dest, FAR const void *src, size_t count);
FAR void *memset(FAR void *s, int c, size_t n);
void explicit_bzero(FAR void *s, size_t n);
#undef EXTERN
#if defined(__cplusplus)
}

77
include/sys/random.h Normal file
View file

@ -0,0 +1,77 @@
/****************************************************************************
* include/sys/random.h
*
* Copyright (C) 2015-2017 Haltian Ltd. All rights reserved.
* Authors: Juha Niskanen <juha.niskanen@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __INCLUDE_SYS_RANDOM_H
#define __INCLUDE_SYS_RANDOM_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stddef.h>
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifdef CONFIG_CRYPTO_RANDOM_POOL
/****************************************************************************
* Function: getrandom
*
* Description:
* Fill a buffer of arbitrary length with randomness. This is the
* preferred interface for getting random numbers. The traditional
* /dev/random approach is susceptible for things like the attacker
* exhausting file descriptors on purpose.
*
* Note that this function cannot fail, other than by asserting.
*
* Parameters:
* bytes - Buffer for returned random bytes
* nbytes - Number of bytes requested.
*
* Returned Value:
* None
*
****************************************************************************/
void getrandom(FAR void *bytes, size_t nbytes);
#endif /* CONFIG_CRYPTO_RANDOM_POOL */
#endif /* __INCLUDE_SYS_RANDOM_H */

View file

@ -524,10 +524,19 @@
/* The following is defined only if CONFIG_TASK_NAME_SIZE > 0 */
#if CONFIG_TASK_NAME_SIZE > 0
# define SYS_prctl (SYS_nnetsocket+0)
# define SYS_maxsyscall (SYS_nnetsocket+1)
# define SYS_prctl (SYS_nnetsocket+1)
#else
# define SYS_maxsyscall SYS_nnetsocket
# define SYS_prctl SYS_nnetsocket
#endif
/* The following is defined only if entropy pool random number generator
* is enabled. */
#ifdef CONFIG_CRYPTO_RANDOM_POOL
# define SYS_getrandom (SYS_prctl+1)
# define SYS_maxsyscall (SYS_prctl+2)
#else
# define SYS_maxsyscall SYS_prctl
#endif
/* Note that the reported number of system calls does *NOT* include the

View file

@ -44,6 +44,7 @@ CSRCS += lib_strerror.c lib_strlen.c lib_strnlen.c lib_strncasecmp.c
CSRCS += lib_strncat.c lib_strncmp.c lib_strncpy.c lib_strndup.c
CSRCS += lib_strcasestr.c lib_strpbrk.c lib_strrchr.c lib_strspn.c
CSRCS += lib_strstr.c lib_strtok.c lib_strtokr.c lib_strerrorr.c
CSRCS += lib_explicit_bzero.c
ifneq ($(CONFIG_LIBC_ARCH_MEMCPY),y)
ifeq ($(CONFIG_MEMCPY_VIK),y)

View file

@ -0,0 +1,56 @@
/****************************************************************************
* libc/string/lib_explicit_bzero.c
*
* Copyright (C) 2015,2017 Haltian Ltd. All rights reserved.
* Author: Juha Niskanen <juha.niskanen@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <string.h>
/****************************************************************************
* Global Functions
****************************************************************************/
/* memset that must not be optimized away by compiler (not even with LTO). */
void explicit_bzero(FAR void *s, size_t n)
{
static FAR void *(*FAR const volatile memset_v)(FAR void *, int, size_t) =
&memset;
memset_v(s, 0, n);
}

View file

@ -42,6 +42,7 @@
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/random.h>
#include "irq/irq.h"
@ -53,7 +54,7 @@
* Name: irq_dispatch
*
* Description:
* This function must be called from the achitecture-specific logic in
* This function must be called from the architecture-specific logic in
* order to dispatch an interrupt to the appropriate, registered handling
* logic.
*
@ -97,6 +98,12 @@ void irq_dispatch(int irq, FAR void *context)
arg = NULL;
#endif
#ifdef CONFIG_CRYPTO_RANDOM_POOL_COLLECT_IRQ_RANDOMNESS
/* Add interrupt timing randomness to entropy pool */
add_irq_randomness(irq);
#endif
/* Then dispatch to the interrupt handler */
vector(irq, context, arg);

View file

@ -30,6 +30,7 @@
"get_errno_ptr","errno.h","defined(__DIRECT_ERRNO_ACCESS)","FAR int*"
"getenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","FAR char*","FAR const char*"
"getpid","unistd.h","","pid_t"
"getrandom","sys/random.h","defined(CONFIG_CRYPTO_RANDOM_POOL)","void","FAR void*","size_t"
"getsockopt","sys/socket.h","CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET)","int","int","int","int","FAR void*","FAR socklen_t*"
"insmod","nuttx/module.h","defined(CONFIG_MODULE)","FAR void *","FAR const char *","FAR const char *"
"ioctl","sys/ioctl.h","!defined(CONFIG_LIBC_IOCTL_VARIADIC) && (CONFIG_NSOCKET_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0)","int","int","int","unsigned long"

Can't render this file because it has a wrong number of fields in line 2.

View file

@ -379,6 +379,13 @@ SYSCALL_LOOKUP(up_assert, 2, STUB_up_assert)
SYSCALL_LOOKUP(prctl, 5, STUB_prctl)
#endif
/* The following is defined only if entropy pool random number generator
* is enabled. */
#ifdef CONFIG_CRYPTO_RANDOM_POOL
SYSCALL_LOOKUP(getrandom, 2, STUB_getrandom)
#endif
/****************************************************************************
* Private Functions
****************************************************************************/

View file

@ -391,6 +391,11 @@ uintptr_t STUB_socket(int nbr, uintptr_t parm1, uintptr_t parm2,
uintptr_t STUB_prctl(int nbr, uintptr_t parm1, uintptr_t parm2,
uintptr_t parm3, uintptr_t parm4, uintptr_t parm5);
/* The following is defined only if entropy pool random number generator
* is enabled. */
uintptr_t STUB_getrandom(int nbr, uintptr_t parm1, uintptr_t parm2);
/****************************************************************************
* Public Data
****************************************************************************/