Commit 5c8819d8 authored by schneider's avatar schneider
Browse files

feat(rng): add CSPRNG core

parent ad61af45
......@@ -119,6 +119,7 @@ typedef _Bool bool;
#define API_GPIO_READ_PIN 0xA3
#define API_TRNG_READ 0xB0
#define API_CSPRNG_READ 0XB1
#define API_PERSONAL_STATE_SET 0xc0
#define API_PERSONAL_STATE_GET 0xc1
......@@ -1921,13 +1922,19 @@ API(API_RTC_SCHEDULE_ALARM, int epic_rtc_schedule_alarm(uint32_t timestamp));
API_ISR(EPIC_INT_RTC_ALARM, epic_isr_rtc_alarm);
/**
* TRNG
* RNG
* ====
*/
/**
* Read random bytes from the TRNG.
*
* Be aware that this function returns raw unprocessed bytes from
* the TRNG. They might be biased or have other kinds of imperfections.
*
* Use :c:func:`epic_csprng_read` for cryptographically safe random
* numbers instead.
*
* :param uint8_t * dest: Destination buffer
* :param size: Number of bytes to read.
* :return: `0` on success or a negative value if an error occured. Possible
......@@ -1937,6 +1944,20 @@ API_ISR(EPIC_INT_RTC_ALARM, epic_isr_rtc_alarm);
*/
API(API_TRNG_READ, int epic_trng_read(uint8_t *dest, size_t size));
/**
* Read random bytes from the CSPRNG.
*
* The random bytes returned are safe to be used for cryptography.
*
* :param uint8_t * dest: Destination buffer
* :param size: Number of bytes to read.
* :return: `0` on success or a negative value if an error occured. Possible
* errors:
*
* - ``-EFAULT``: Invalid destination address.
*/
API(API_CSPRNG_READ, int epic_csprng_read(uint8_t *dest, size_t size));
/**
* MAX30001
* ========
......
......@@ -18,7 +18,6 @@
#include "i2c.h"
#include "rtc.h"
#include "spi.h"
#include "trng.h"
#include "wdt.h"
/*
......@@ -83,6 +82,11 @@ int hardware_early_init(void)
E_BUSY)
;
/*
* RNG
*/
rng_init();
/* If we don't have a valid time yet, set it to 2019-01-01 */
if (RTC_GetSecond() < 1546300800L) {
epic_rtc_set_milliseconds(1546300800UL * 1000);
......
......@@ -136,4 +136,8 @@ extern gpio_cfg_t gpio_configs[];
/* ---------- Sleep -------------------------------------------------------- */
void sleep_deepsleep(void);
void rng_init(void);
#endif /* MODULES_H */
#include "epicardium.h"
#include "modules.h"
#include "MAX77650-Arduino-Library.h"
#include "tiny-AES-c/aes.h"
#include "mxc_sys.h"
#include "adc.h"
#include "mxc_delay.h"
#include "rtc.h"
#include "trng.h"
#include <string.h>
static struct AES_ctx ctx;
int epic_trng_read(uint8_t *dest, size_t size)
{
if (dest == NULL)
......@@ -11,3 +25,81 @@ int epic_trng_read(uint8_t *dest, size_t size)
return 0;
}
int epic_csprng_read(uint8_t *dest, size_t size)
{
if (size >= AES_BLOCKLEN) {
int block_count = size / AES_BLOCKLEN;
AES_CTR_xcrypt_buffer(&ctx, dest, block_count * AES_BLOCKLEN);
size -= block_count * AES_BLOCKLEN;
dest += block_count * AES_BLOCKLEN;
}
if (size > 0) {
uint8_t out[AES_BLOCKLEN];
AES_CTR_xcrypt_buffer(&ctx, out, sizeof(out));
memcpy(dest, out, size);
}
return 0;
}
static void xor
(uint8_t * a, uint8_t *b, size_t size) {
while (size--) {
*a = *a ^ *b;
a++;
b++;
}
}
static void seed(uint8_t *entropy, size_t size)
{
uint8_t key_new[AES_BLOCKLEN];
uint8_t iv[AES_BLOCKLEN] = { 0 };
epic_csprng_read(key_new, AES_BLOCKLEN);
xor(key_new, entropy, size);
AES_init_ctx_iv(&ctx, key_new, iv);
}
void rng_init(void)
{
uint8_t key[AES_BLOCKLEN] = { 0 };
uint8_t iv[AES_BLOCKLEN] = { 0 };
int i;
AES_init_ctx_iv(&ctx, key, iv);
/* Seed from TRNG.
* Takes about 30 ms. */
for (i = 0; i < 256; i++) {
uint8_t entropy[AES_BLOCKLEN];
epic_trng_read(entropy, AES_BLOCKLEN);
seed(entropy, AES_BLOCKLEN);
}
// Seed from RTC
uint32_t sec, subsec;
while (RTC_GetTime(&sec, &subsec) == E_BUSY) {
mxc_delay(4000);
}
seed((uint8_t *)&sec, sizeof(sec));
seed((uint8_t *)&subsec, sizeof(subsec));
// Seed from SysTick
uint32_t systick = SysTick->VAL;
seed((uint8_t *)&systick, sizeof(systick));
/* Seed from ADC.
* Takes about 80 ms */
ADC_Init(0x9, NULL);
GPIO_Config(&gpio_cfg_adc0);
MAX77650_setMUX_SEL(PMIC_AMUX_BATT_U);
for (i = 0; i < 256; i++) {
uint16_t adc_data;
ADC_StartConvert(ADC_CH_0, 0, 0);
ADC_GetData(&adc_data);
seed((uint8_t *)&adc_data, sizeof(adc_data));
}
MAX77650_setMUX_SEL(PMIC_AMUX_DISABLED);
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment