mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-24 23:38:09 +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 <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "bignum.h"
|
#include "bignum.h"
|
||||||
#include "hmac.h"
|
#include "hmac.h"
|
||||||
@ -176,6 +177,73 @@ int hdnode_public_ckd(HDNode *inout, uint32_t i)
|
|||||||
return 1;
|
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)
|
void hdnode_fill_public_key(HDNode *node)
|
||||||
{
|
{
|
||||||
ecdsa_get_public_key33(node->private_key, node->public_key);
|
ecdsa_get_public_key33(node->private_key, node->public_key);
|
||||||
|
7
bip32.h
7
bip32.h
@ -25,6 +25,7 @@
|
|||||||
#define __BIP32_H__
|
#define __BIP32_H__
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "options.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t depth;
|
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);
|
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_fill_public_key(HDNode *node);
|
||||||
|
|
||||||
void hdnode_serialize_public(const HDNode *node, char *str, int strsize);
|
void hdnode_serialize_public(const HDNode *node, char *str, int strsize);
|
||||||
|
@ -53,4 +53,11 @@
|
|||||||
#define USE_PUBKEY_VALIDATE 1
|
#define USE_PUBKEY_VALIDATE 1
|
||||||
#endif
|
#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
|
#endif
|
||||||
|
48
tests.c
48
tests.c
@ -427,6 +427,52 @@ START_TEST(test_bip32_compare)
|
|||||||
}
|
}
|
||||||
END_TEST
|
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 { \
|
#define test_deterministic(KEY, MSG, K) do { \
|
||||||
sha256_Raw((uint8_t *)MSG, strlen(MSG), buf); \
|
sha256_Raw((uint8_t *)MSG, strlen(MSG), buf); \
|
||||||
res = generate_k_rfc6979(&k, fromhex(KEY), buf); \
|
res = generate_k_rfc6979(&k, fromhex(KEY), buf); \
|
||||||
@ -1139,6 +1185,7 @@ Suite *test_suite(void)
|
|||||||
Suite *s = suite_create("trezor-crypto");
|
Suite *s = suite_create("trezor-crypto");
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
|
|
||||||
|
|
||||||
tc = tcase_create("base58");
|
tc = tcase_create("base58");
|
||||||
tcase_add_test(tc, test_base58);
|
tcase_add_test(tc, test_base58);
|
||||||
suite_add_tcase(s, tc);
|
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_1);
|
||||||
tcase_add_test(tc, test_bip32_vector_2);
|
tcase_add_test(tc, test_bip32_vector_2);
|
||||||
tcase_add_test(tc, test_bip32_compare);
|
tcase_add_test(tc, test_bip32_compare);
|
||||||
|
tcase_add_test(tc, test_bip32_cache);
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
tc = tcase_create("rfc6979");
|
tc = tcase_create("rfc6979");
|
||||||
|
Loading…
Reference in New Issue
Block a user