mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-23 23:08:14 +00:00
implement BIP32 cache
This commit is contained in:
parent
40b023b1f4
commit
f4e6010e18
68
bip32.c
68
bip32.c
@ -22,6 +22,7 @@
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "bignum.h"
|
||||
#include "hmac.h"
|
||||
@ -176,6 +177,73 @@ int hdnode_public_ckd(HDNode *inout, uint32_t i)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if USE_BIP32_CACHE
|
||||
|
||||
static bool private_ckd_cache_root_set = false;
|
||||
static HDNode private_ckd_cache_root;
|
||||
static int private_ckd_cache_index = 0;
|
||||
|
||||
static struct {
|
||||
bool set;
|
||||
size_t depth;
|
||||
uint32_t i[BIP32_CACHE_MAXDEPTH];
|
||||
HDNode node;
|
||||
} private_ckd_cache[BIP32_CACHE_SIZE];
|
||||
|
||||
int hdnode_private_ckd_cached(HDNode *inout, const uint32_t *i, size_t i_count)
|
||||
{
|
||||
if (i_count == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (i_count == 1) {
|
||||
if (hdnode_private_ckd(inout, i[0]) == 0) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
// if root is not set or not the same
|
||||
if (!private_ckd_cache_root_set || memcmp(&private_ckd_cache_root, inout, sizeof(HDNode)) != 0) {
|
||||
// clear the cache
|
||||
private_ckd_cache_index = 0;
|
||||
memset(private_ckd_cache, 0, sizeof(private_ckd_cache));
|
||||
// setup new root
|
||||
memcpy(&private_ckd_cache_root, inout, sizeof(HDNode));
|
||||
private_ckd_cache_root_set = true;
|
||||
} else {
|
||||
// try to find parent
|
||||
int j;
|
||||
for (j = 0; j < BIP32_CACHE_SIZE; j++) {
|
||||
if (private_ckd_cache[j].set &&
|
||||
private_ckd_cache[j].depth == i_count - 1 &&
|
||||
memcmp(private_ckd_cache[j].i, i, (i_count - 1) * sizeof(uint32_t)) == 0) {
|
||||
memcpy(inout, &(private_ckd_cache[j].node), sizeof(HDNode));
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// else derive parent
|
||||
if (!found) {
|
||||
size_t k;
|
||||
for (k = 0; k < i_count - 1; k++) {
|
||||
if (hdnode_private_ckd(inout, i[k]) == 0) return 0;
|
||||
}
|
||||
// and save it
|
||||
private_ckd_cache[private_ckd_cache_index].set = true;
|
||||
private_ckd_cache[private_ckd_cache_index].depth = i_count - 1;
|
||||
memcpy(private_ckd_cache[private_ckd_cache_index].i, i, (i_count - 1) * sizeof(uint32_t));
|
||||
memcpy(&(private_ckd_cache[private_ckd_cache_index].node), inout, sizeof(HDNode));
|
||||
private_ckd_cache_index = (private_ckd_cache_index + 1) % BIP32_CACHE_SIZE;
|
||||
}
|
||||
|
||||
if (hdnode_private_ckd(inout, i[i_count - 1]) == 0) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void hdnode_fill_public_key(HDNode *node)
|
||||
{
|
||||
ecdsa_get_public_key33(node->private_key, node->public_key);
|
||||
|
7
bip32.h
7
bip32.h
@ -25,6 +25,7 @@
|
||||
#define __BIP32_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "options.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t depth;
|
||||
@ -47,6 +48,12 @@ int hdnode_private_ckd(HDNode *inout, uint32_t i);
|
||||
|
||||
int hdnode_public_ckd(HDNode *inout, uint32_t i);
|
||||
|
||||
#if USE_BIP32_CACHE
|
||||
|
||||
int hdnode_private_ckd_cached(HDNode *inout, const uint32_t *i, size_t i_count);
|
||||
|
||||
#endif
|
||||
|
||||
void hdnode_fill_public_key(HDNode *node);
|
||||
|
||||
void hdnode_serialize_public(const HDNode *node, char *str, int strsize);
|
||||
|
@ -53,4 +53,11 @@
|
||||
#define USE_PUBKEY_VALIDATE 1
|
||||
#endif
|
||||
|
||||
// implement BIP32 caching
|
||||
#ifndef USE_BIP32_CACHE
|
||||
#define USE_BIP32_CACHE 1
|
||||
#define BIP32_CACHE_SIZE 10
|
||||
#define BIP32_CACHE_MAXDEPTH 8
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
48
tests.c
48
tests.c
@ -427,6 +427,52 @@ START_TEST(test_bip32_compare)
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bip32_cache)
|
||||
{
|
||||
HDNode node1, node2;
|
||||
int r;
|
||||
|
||||
// test 1 .. 8
|
||||
hdnode_from_seed(fromhex("301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), 64, &node1);
|
||||
hdnode_from_seed(fromhex("301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), 64, &node2);
|
||||
|
||||
uint32_t i;
|
||||
for (i = 1; i < 8; i++) {
|
||||
r = hdnode_private_ckd(&node1, i); ck_assert_int_eq(r, 1);
|
||||
}
|
||||
r = hdnode_private_ckd(&node1, 8); ck_assert_int_eq(r, 1);
|
||||
|
||||
uint32_t ii[] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
r = hdnode_private_ckd_cached(&node2, ii, 8); ck_assert_int_eq(r, 1);
|
||||
ck_assert_mem_eq(&node1, &node2, sizeof(HDNode));
|
||||
|
||||
// test 1 .. 7, 20
|
||||
hdnode_from_seed(fromhex("301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), 64, &node1);
|
||||
hdnode_from_seed(fromhex("301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), 64, &node2);
|
||||
|
||||
for (i = 1; i < 8; i++) {
|
||||
r = hdnode_private_ckd(&node1, i); ck_assert_int_eq(r, 1);
|
||||
}
|
||||
r = hdnode_private_ckd(&node1, 20); ck_assert_int_eq(r, 1);
|
||||
|
||||
ii[7] = 20;
|
||||
r = hdnode_private_ckd_cached(&node2, ii, 8); ck_assert_int_eq(r, 1);
|
||||
ck_assert_mem_eq(&node1, &node2, sizeof(HDNode));
|
||||
|
||||
// test different root node
|
||||
hdnode_from_seed(fromhex("000000002ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), 64, &node1);
|
||||
hdnode_from_seed(fromhex("000000002ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), 64, &node2);
|
||||
|
||||
for (i = 1; i < 8; i++) {
|
||||
r = hdnode_private_ckd(&node1, i); ck_assert_int_eq(r, 1);
|
||||
}
|
||||
r = hdnode_private_ckd(&node1, 20); ck_assert_int_eq(r, 1);
|
||||
|
||||
r = hdnode_private_ckd_cached(&node2, ii, 8); ck_assert_int_eq(r, 1);
|
||||
ck_assert_mem_eq(&node1, &node2, sizeof(HDNode));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
#define test_deterministic(KEY, MSG, K) do { \
|
||||
sha256_Raw((uint8_t *)MSG, strlen(MSG), buf); \
|
||||
res = generate_k_rfc6979(&k, fromhex(KEY), buf); \
|
||||
@ -1139,6 +1185,7 @@ Suite *test_suite(void)
|
||||
Suite *s = suite_create("trezor-crypto");
|
||||
TCase *tc;
|
||||
|
||||
|
||||
tc = tcase_create("base58");
|
||||
tcase_add_test(tc, test_base58);
|
||||
suite_add_tcase(s, tc);
|
||||
@ -1147,6 +1194,7 @@ Suite *test_suite(void)
|
||||
tcase_add_test(tc, test_bip32_vector_1);
|
||||
tcase_add_test(tc, test_bip32_vector_2);
|
||||
tcase_add_test(tc, test_bip32_compare);
|
||||
tcase_add_test(tc, test_bip32_cache);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("rfc6979");
|
||||
|
Loading…
Reference in New Issue
Block a user