diff --git a/common.h b/common.h index 912f73c54..a4fd9886e 100644 --- a/common.h +++ b/common.h @@ -23,7 +23,7 @@ #include #include "secbool.h" -#define HW_ENTROPY_LEN 12 +#define HW_ENTROPY_LEN (12 + 32) extern uint8_t HW_ENTROPY_DATA[HW_ENTROPY_LEN]; void __attribute__((noreturn)) __fatal_error(const char *expr, const char *msg, const char *file, int line, const char *func); diff --git a/firmware/Makefile b/firmware/Makefile index 672a063a4..91e84acad 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -7,6 +7,7 @@ OBJS += udp.o else OBJS += usb.o OBJS += bl_check.o +OBJS += otp.o endif OBJS += u2f.o diff --git a/firmware/otp.c b/firmware/otp.c new file mode 100644 index 000000000..74810f668 --- /dev/null +++ b/firmware/otp.c @@ -0,0 +1,65 @@ +/* + * This file is part of the TREZOR project, https://trezor.io/ + * + * Copyright (C) 2019 Pavol Rusnak + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include +#include "otp.h" + +#define FLASH_OTP_BASE 0x1FFF7800U +#define FLASH_OTP_LOCK_BASE 0x1FFF7A00U + +bool flash_otp_is_locked(uint8_t block) +{ + return 0x00 == *(volatile uint8_t *)(FLASH_OTP_LOCK_BASE + block); +} + +bool flash_otp_lock(uint8_t block) +{ + if (block >= FLASH_OTP_NUM_BLOCKS) { + return false; + } + flash_unlock(); + flash_program_byte(FLASH_OTP_LOCK_BASE + block, 0x00); + flash_lock(); + return true; +} + +bool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data, uint8_t datalen) +{ + if (block >= FLASH_OTP_NUM_BLOCKS || offset + datalen > FLASH_OTP_BLOCK_SIZE) { + return false; + } + for (uint8_t i = 0; i < datalen; i++) { + data[i] = *(volatile uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + offset + i); + } + return true; +} + +bool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, uint8_t datalen) +{ + if (block >= FLASH_OTP_NUM_BLOCKS || offset + datalen > FLASH_OTP_BLOCK_SIZE) { + return false; + } + flash_unlock(); + for (uint8_t i = 0; i < datalen; i++) { + uint32_t address = FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + offset + i; + flash_program_byte(address, data[i]); + } + flash_lock(); + return true; +} diff --git a/firmware/otp.h b/firmware/otp.h new file mode 100644 index 000000000..471e230c0 --- /dev/null +++ b/firmware/otp.h @@ -0,0 +1,36 @@ +/* + * This file is part of the TREZOR project, https://trezor.io/ + * + * Copyright (C) 2019 Pavol Rusnak + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#ifndef __OTP_H__ +#define __OTP_H__ + +#include +#include + +#define FLASH_OTP_NUM_BLOCKS 16 +#define FLASH_OTP_BLOCK_SIZE 32 + +#define FLASH_OTP_BLOCK_RANDOMNESS 3 + +bool flash_otp_is_locked(uint8_t block); +bool flash_otp_lock(uint8_t block); +bool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data, uint8_t datalen); +bool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, uint8_t datalen); + +#endif diff --git a/firmware/trezor.c b/firmware/trezor.c index 90cf928ad..dff99dd7f 100644 --- a/firmware/trezor.c +++ b/firmware/trezor.c @@ -34,6 +34,7 @@ #include "bl_check.h" #include "memzero.h" #if !EMULATOR +#include "otp.h" #include #endif @@ -89,6 +90,29 @@ void check_lock_screen(void) } } +static void collect_hw_entropy(bool privileged) +{ +#if EMULATOR + memzero(HW_ENTROPY_DATA, HW_ENTROPY_LEN); +#else + if (privileged) { + desig_get_unique_id((uint32_t *)HW_ENTROPY_DATA); + // set entropy in the OTP randomness block + if (!flash_otp_is_locked(FLASH_OTP_BLOCK_RANDOMNESS)) { + uint8_t entropy[FLASH_OTP_BLOCK_SIZE]; + random_buffer(entropy, FLASH_OTP_BLOCK_SIZE); + flash_otp_write(FLASH_OTP_BLOCK_RANDOMNESS, 0, entropy, FLASH_OTP_BLOCK_SIZE); + flash_otp_lock(FLASH_OTP_BLOCK_RANDOMNESS); + } + // collect entropy from OTP randomness block + flash_otp_read(FLASH_OTP_BLOCK_RANDOMNESS, 0, HW_ENTROPY_DATA + 12, FLASH_OTP_BLOCK_SIZE); + } else { + // unprivileged mode => use fixed HW_ENTROPY + memset(HW_ENTROPY_DATA, 0x3C, HW_ENTROPY_LEN); + } +#endif +} + int main(void) { #ifndef APPVER @@ -100,26 +124,15 @@ int main(void) setupApp(); __stack_chk_guard = random32(); // this supports compiler provided unpredictable stack protection checks #endif - -#if EMULATOR - memzero(HW_ENTROPY_DATA, HW_ENTROPY_LEN); -#endif - if (!is_mode_unprivileged()) { -#if !EMULATOR - desig_get_unique_id((uint32_t*)HW_ENTROPY_DATA); -#endif + collect_hw_entropy(true); timer_init(); #ifdef APPVER // enable MPU (Memory Protection Unit) mpu_config(); #endif } else { -#if !EMULATOR - // we are running in unprivileged mode - // use fixed HW_ENTROPY - memset(HW_ENTROPY_DATA, 0x3C, HW_ENTROPY_LEN); -#endif + collect_hw_entropy(false); } #if DEBUG_LINK