Commit 73fbb3eb authored by Rahix's avatar Rahix
Browse files

Merge branch 'Add CSPRNG'

See merge request card10/firmware!399
parents 7422956c bd7f01a1
......@@ -4,3 +4,9 @@
[submodule "lib/micropython/micropython-lib"]
path = lib/micropython/micropython-lib
url = https://github.com/micropython/micropython-lib.git
[submodule "lib/crypto/tiny-AES-c"]
path = lib/crypto/tiny-AES-c
url = https://github.com/kokke/tiny-AES-c
[submodule "lib/crypto/SHA256"]
path = lib/crypto/SHA256
url = https://github.com/ilvn/SHA256
......@@ -4,7 +4,8 @@ set -xe
cd "$(dirname "$0")"
test -d build/ && rm -r build/
git submodule update --init ./lib/micropython
# Get external libs (MicroPython, tiny-AES-c, SHA256)
git submodule update --init ./lib
meson --cross-file card10-cross.ini build/ "$@"
set +x
......
......@@ -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,26 @@ 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.
*
* .. warning::
*
* The exact behaviour of the TRNG is not well understood. Its
* distribution and other parameters are unknown. Only use this
* function if you really want the unmodified values from the
* hardware TRNG to experiment with it.
*
* :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 +1951,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
* ========
......
......@@ -91,7 +91,7 @@ elf = executable(
l0der_sources,
ble_sources,
version_hdr,
dependencies: [libcard10, max32665_startup_core0, maxusb, libff13, ble, bhy1],
dependencies: [libcard10, max32665_startup_core0, maxusb, libff13, ble, bhy1, libcrypto],
link_with: [api_dispatcher_lib, freertos],
link_whole: [max32665_startup_core0_lib, board_card10_lib, newlib_heap_lib],
include_directories: [freertos_includes],
......
......@@ -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);
......
......@@ -24,7 +24,7 @@ module_sources = files(
'serial.c',
'sleep.c',
'stream.c',
'trng.c',
'rng.c',
'usb.c',
'vibra.c',
'watchdog.c',
......
......@@ -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 "SHA256/mark2/sha256.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 aes_ctx;
int epic_trng_read(uint8_t *dest, size_t size)
{
if (dest == NULL)
return -EFAULT;
TRNG_Init(NULL);
TRNG_Read(MXC_TRNG, dest, 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(
&aes_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(&aes_ctx, out, sizeof(out));
memcpy(dest, out, size);
}
return 0;
}
void rng_init(void)
{
uint8_t key[AES_BLOCKLEN];
uint8_t iv[AES_BLOCKLEN];
uint8_t hash[32];
sha256_context ctx;
int i;
sha256_init(&ctx);
/* Seed from TRNG.
* Takes about 10 ms. */
for (i = 0; i < 256; i++) {
uint8_t entropy[AES_BLOCKLEN];
epic_trng_read(entropy, AES_BLOCKLEN);
sha256_hash(&ctx, entropy, AES_BLOCKLEN);
}
// Seed from RTC
uint32_t sec, subsec;
while (RTC_GetTime(&sec, &subsec) == E_BUSY) {
mxc_delay(4000);
}
sha256_hash(&ctx, &sec, sizeof(sec));
sha256_hash(&ctx, &subsec, sizeof(subsec));
// Seed from SysTick
uint32_t systick = SysTick->VAL;
sha256_hash(&ctx, &systick, sizeof(systick));
/* Seed from ADC.
* Takes about 50 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);
sha256_hash(&ctx, &adc_data, sizeof(adc_data));
}
MAX77650_setMUX_SEL(PMIC_AMUX_DISABLED);
sha256_done(&ctx, hash);
memcpy(key, hash, AES_BLOCKLEN);
memcpy(iv, hash + AES_BLOCKLEN, AES_BLOCKLEN);
AES_init_ctx_iv(&aes_ctx, key, iv);
}
#include "epicardium.h"
#include "trng.h"
int epic_trng_read(uint8_t *dest, size_t size)
{
if (dest == NULL)
return -EFAULT;
TRNG_Init(NULL);
TRNG_Read(MXC_TRNG, dest, size);
return 0;
}
Subproject commit 1c9e3886f69f9ca83c1af49968d8e4389035ff44
includes = include_directories(
'./',
)
sources = files(
'./tiny-AES-c/aes.c',
'./SHA256/mark2/sha256.c',
)
lib = static_library(
'crypto',
sources,
include_directories: includes,
c_args: '-w',
)
libcrypto = declare_dependency(
include_directories: includes,
link_with: lib,
)
Subproject commit 3f69a5899e58e2e398e8c32ce7b3a954dd593ed4
......@@ -10,6 +10,7 @@ subdir('./gfx/')
subdir('./FreeRTOS/')
subdir('./FreeRTOS-Plus/')
subdir('./micropython/')
subdir('./crypto/')
subdir('./card10/')
subdir('./mx25lba/')
......
......@@ -188,7 +188,7 @@ static mp_obj_t mp_os_urandom(mp_obj_t size_in)
vstr_t vstr;
vstr_init_len(&vstr, size);
epic_trng_read((uint8_t *)vstr.buf, size);
epic_csprng_read((uint8_t *)vstr.buf, size);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
......
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