Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions src/commander.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@
#include "ecdh.h"


#if defined(TESTING) && defined(__SAM4S4A__)
#error TESTING should not be defined for embedded code
#endif


#define BRACED(x) (strlens(x) ? (((x[0]) == '{') && ((x[strlens(x) - 1]) == '}')) : 0)


Expand Down Expand Up @@ -467,13 +472,11 @@ static void commander_process_seed(yajl_val json_node)
int ret;

const char *key_path[] = { cmd_str(CMD_seed), cmd_str(CMD_key), NULL };
const char *raw_path[] = { cmd_str(CMD_seed), cmd_str(CMD_raw), NULL };
const char *source_path[] = { cmd_str(CMD_seed), cmd_str(CMD_source), NULL };
const char *entropy_path[] = { cmd_str(CMD_seed), cmd_str(CMD_entropy), NULL };
const char *filename_path[] = { cmd_str(CMD_seed), cmd_str(CMD_filename), NULL };
const char *u2f_counter_path[] = { cmd_str(CMD_seed), cmd_str(CMD_U2F_counter), NULL };
const char *key = YAJL_GET_STRING(yajl_tree_get(json_node, key_path, yajl_t_string));
const char *raw = YAJL_GET_STRING(yajl_tree_get(json_node, raw_path, yajl_t_string));
const char *source = YAJL_GET_STRING(yajl_tree_get(json_node, source_path,
yajl_t_string));
const char *entropy = YAJL_GET_STRING(yajl_tree_get(json_node, entropy_path,
Expand Down Expand Up @@ -510,7 +513,7 @@ static void commander_process_seed(yajl_val json_node)

if (STREQ(source, attr_str(ATTR_create))) {
// Generate a new wallet, optionally with entropy entered via USB
uint8_t i, add_entropy, entropy_b[MEM_PAGE_LEN];
uint8_t i, add_entropy = 1, entropy_b[MEM_PAGE_LEN];
char entropy_c[MEM_PAGE_LEN * 2 + 1];

memset(entropy_b, 0, sizeof(entropy_b));
Expand All @@ -521,20 +524,23 @@ static void commander_process_seed(yajl_val json_node)
}

if (strlens(entropy)) {
if (strlens(entropy) == MEM_PAGE_LEN * 2 && utils_is_hex(entropy)) {
// Allows recover from a Digital Bitbox backup text entered via USB
memcpy(entropy_b, utils_hex_to_uint8(entropy), sizeof(entropy_b));
if (strlens(entropy) != SHA256_DIGEST_LENGTH * 2) {
commander_fill_report(cmd_str(CMD_seed), NULL, DBB_ERR_IO_INVALID_CMD);
return;
}
sha256_Raw((const uint8_t *)entropy, strlens(entropy), entropy_b);
}

#ifdef TESTING
// Add extra entropy from device unless raw is set
add_entropy = 1;
const char *raw_path[] = { cmd_str(CMD_seed), cmd_str(CMD_raw), NULL };
const char *raw = YAJL_GET_STRING(yajl_tree_get(json_node, raw_path, yajl_t_string));
if (strlens(entropy) && strlens(raw)) {
if (STREQ(raw, attr_str(ATTR_true))) {
add_entropy = 0;
}
}
#endif

if (add_entropy) {
uint8_t number[MEM_PAGE_LEN];
Expand All @@ -545,6 +551,7 @@ static void commander_process_seed(yajl_val json_node)
for (i = 0; i < MEM_PAGE_LEN; i++) {
entropy_b[i] ^= number[i];
}
sha256_Raw(entropy_b, sizeof(entropy_b), entropy_b);
}

snprintf(entropy_c, sizeof(entropy_c), "%s", utils_uint8_to_hex(entropy_b,
Expand Down
13 changes: 9 additions & 4 deletions src/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ int random_bytes(uint8_t *buf, uint32_t len, uint8_t update_seed)
for (i = 0; i < MIN(len, MEM_PAGE_LEN); i++) {
buf[i] ^= entropy[i];
}
// Add entropy from usersig
// Add entropy from the random number stored in the MCU's 'user signature' memory area
flash_read_user_signature((uint32_t *)usersig, FLASH_USERSIG_SIZE / sizeof(uint32_t));
sha256_Raw(usersig, FLASH_USERSIG_SIZE, entropy);
for (i = 0; i < MIN(len, MEM_PAGE_LEN); i++) {
Expand All @@ -105,13 +105,13 @@ int random_bytes(uint8_t *buf, uint32_t len, uint8_t update_seed)
while (len > n) {
if (update_seed) {
ret = ataes_process(ataes_cmd_up, sizeof(ataes_cmd_up), ataes_ret, sizeof(ataes_ret));
update_seed = 0;
} else {
ret = ataes_process(ataes_cmd, sizeof(ataes_cmd), ataes_ret, sizeof(ataes_ret));
}
if (ret == DBB_OK && ataes_ret[0] && !ataes_ret[1]) {
for (i = 0; i < MIN(len - n, ATAES_RAND_LEN); i++) {
buf[(n + i) % len] ^= ataes_ret[(2 + i) % sizeof(ataes_ret)];
sha256_Raw(ataes_ret + 2, ATAES_RAND_LEN, entropy);
for (i = 0; i < MIN(len - n, MEM_PAGE_LEN); i++) {
buf[(n + i)] ^= entropy[i];
}
} else {
flash_erase_user_signature();
Expand All @@ -121,6 +121,11 @@ int random_bytes(uint8_t *buf, uint32_t len, uint8_t update_seed)
}
n += ATAES_RAND_LEN;
}
// Replaces up to the first 32B of the random number with a SHA256 hash
// Helps protect against a backdoored HRNG
sha256_Raw(buf, len, entropy);
memcpy(buf, entropy, MIN(len, MEM_PAGE_LEN));
utils_zero(entropy, sizeof(entropy));
#endif
return DBB_OK;
}
7 changes: 6 additions & 1 deletion src/sha2.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,13 @@ typedef uint64_t sha2_word64; /* Exactly 8 bytes */
} \
}

#define MEMSET_BZERO(p,l) memset((p), 0, (l))
#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l))
static volatile void *MEMSET_BZERO(volatile void *dst, size_t len)
{
volatile char *buf;
for (buf = (volatile char *)dst; len; buf[--len] = 0);
return dst;
}

/*** THE SIX LOGICAL FUNCTIONS ****************************************/
/*
Expand Down
2 changes: 1 addition & 1 deletion src/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ static uint8_t utils_buffer[UTILS_BUFFER_LEN];
volatile void *utils_zero(volatile void *dst, size_t len)
{
volatile char *buf;
for (buf = (volatile char *)dst; len; buf[--len] = 0);
for (buf = (volatile char *)dst; len; buf[--len] = 0);
return dst;
}

Expand Down
24 changes: 24 additions & 0 deletions tests/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,30 @@ static const char *api_read_value_depth_2(int cmd, int cmd_2)
}


static const char *api_read_array_value(int cmd, int cmd_2, int index)
{
const char *path[] = { cmd_str(cmd), NULL };
const char *a_path[] = { cmd_str(cmd_2), NULL };
static char value[HID_REPORT_SIZE];
memset(value, 0, sizeof(value));

yajl_val json_node = yajl_tree_parse(api_read_decrypted_report(), NULL, 0);
if (json_node && YAJL_IS_OBJECT(json_node)) {
yajl_val data = yajl_tree_get(json_node, path, yajl_t_array);
if (YAJL_IS_ARRAY(data) && data->u.array.len != 0) {
yajl_val obj = data->u.array.values[index];
const char *a = YAJL_GET_STRING(yajl_tree_get(obj, a_path, yajl_t_string));
if (a) {
snprintf(value, sizeof(value), "%s", a);
}
}
}

yajl_tree_free(json_node);
return value;
}


static char *api_read_value_decrypt(int cmd, uint8_t *key)
{
const char *val = api_read_value(cmd);
Expand Down
Loading