17
17
#include <stddef.h>
18
18
#include <cmocka.h>
19
19
20
+ #include <cipher/cipher.h>
20
21
#include <keystore.h>
21
22
#include <memory/bitbox02_smarteeprom.h>
23
+ #include <memory/memory.h>
22
24
#include <memory/smarteeprom.h>
23
25
#include <secp256k1_ecdsa_s2c.h>
24
26
#include <secp256k1_recovery.h>
29
31
#include <stdio.h>
30
32
#include <string.h>
31
33
34
+ #define PASSWORD ("password")
35
+
32
36
static uint8_t _mock_seed [32 ] = {
33
37
0x11 , 0x11 , 0x11 , 0x11 , 0x11 , 0x11 , 0x11 , 0x11 , 0x22 , 0x22 , 0x22 , 0x22 , 0x22 , 0x22 , 0x22 , 0x22 ,
34
38
0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x44 , 0x44 , 0x44 , 0x44 , 0x44 , 0x44 , 0x44 , 0x44 ,
@@ -46,6 +50,8 @@ static uint8_t _mock_bip39_seed[64] = {
46
50
0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x44 , 0x44 , 0x44 , 0x44 , 0x44 , 0x44 , 0x44 , 0x44 ,
47
51
};
48
52
53
+ const uint8_t _aes_iv [32 ] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ;
54
+
49
55
static const uint32_t _keypath [] = {
50
56
44 + BIP32_INITIAL_HARDENED_CHILD ,
51
57
0 + BIP32_INITIAL_HARDENED_CHILD ,
@@ -89,6 +95,13 @@ static uint8_t _kdf_out_3[32] = {
89
95
0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x33 , 0x33 ,
90
96
};
91
97
98
+ // Fixture: hmac.new(_password_salted_hashed_stretch_out, _kdf_out_3,
99
+ // hashlib.sha256).hexdigest()
100
+ static uint8_t _expected_secret [32 ] = {
101
+ 0x39 , 0xa7 , 0x4f , 0x75 , 0xb6 , 0x9d , 0x6c , 0x84 , 0x5e , 0x18 , 0x91 , 0x5b , 0xae , 0x29 , 0xd1 , 0x06 ,
102
+ 0x12 , 0x12 , 0x40 , 0x37 , 0x7a , 0x79 , 0x97 , 0x55 , 0xd7 , 0xcc , 0xe9 , 0x26 , 0x1e , 0x16 , 0x91 , 0x71 ,
103
+ };
104
+
92
105
int __real_secp256k1_anti_klepto_sign (
93
106
const secp256k1_context * ctx ,
94
107
secp256k1_ecdsa_signature * sig ,
@@ -124,6 +137,8 @@ bool __wrap_salt_hash_data(
124
137
const char * purpose ,
125
138
uint8_t * hash_out )
126
139
{
140
+ check_expected (data );
141
+ check_expected (data_len );
127
142
check_expected (purpose );
128
143
memcpy (hash_out , (const void * )mock (), 32 );
129
144
return true;
@@ -163,6 +178,11 @@ void __wrap_reset_reset(void)
163
178
_reset_reset_called = true;
164
179
}
165
180
181
+ void __wrap_random_32_bytes (uint8_t * buf )
182
+ {
183
+ memcpy (buf , (const void * )mock (), 32 );
184
+ }
185
+
166
186
static bool _pubkeys_equal (
167
187
const secp256k1_context * ctx ,
168
188
const secp256k1_pubkey * pubkey1 ,
@@ -296,6 +316,8 @@ static void _test_keystore_secp256k1_sign(void** state)
296
316
297
317
static void _expect_stretch (bool valid )
298
318
{
319
+ expect_memory (__wrap_salt_hash_data , data , PASSWORD , strlen (PASSWORD ));
320
+ expect_value (__wrap_salt_hash_data , data_len , strlen (PASSWORD ));
299
321
expect_string (__wrap_salt_hash_data , purpose , "keystore_seed_access_in" );
300
322
will_return (__wrap_salt_hash_data , _password_salted_hashed_stretch_in );
301
323
@@ -314,6 +336,8 @@ static void _expect_stretch(bool valid)
314
336
expect_memory (securechip_kdf , msg , _kdf_out_2 , 32 );
315
337
will_return (securechip_kdf , _kdf_out_3 );
316
338
339
+ expect_memory (__wrap_salt_hash_data , data , PASSWORD , strlen (PASSWORD ));
340
+ expect_value (__wrap_salt_hash_data , data_len , strlen (PASSWORD ));
317
341
expect_string (__wrap_salt_hash_data , purpose , "keystore_seed_access_out" );
318
342
will_return (
319
343
__wrap_salt_hash_data ,
@@ -327,18 +351,11 @@ static void _expect_encrypt_and_store_seed(void)
327
351
_expect_stretch (true); // first stretch to encrypt
328
352
_expect_stretch (true); // second stretch to verify
329
353
330
- // Fixture: hmac.new(_password_salted_hashed_stretch_out, _kdf_out_3,
331
- // hashlib.sha256).hexdigest()
332
- static uint8_t expected_secret [32 ] = {
333
- 0x39 , 0xa7 , 0x4f , 0x75 , 0xb6 , 0x9d , 0x6c , 0x84 , 0x5e , 0x18 , 0x91 ,
334
- 0x5b , 0xae , 0x29 , 0xd1 , 0x06 , 0x12 , 0x12 , 0x40 , 0x37 , 0x7a , 0x79 ,
335
- 0x97 , 0x55 , 0xd7 , 0xcc , 0xe9 , 0x26 , 0x1e , 0x16 , 0x91 , 0x71 ,
336
- };
337
- expect_memory (__wrap_cipher_aes_hmac_encrypt , secret , expected_secret , 32 );
354
+ expect_memory (__wrap_cipher_aes_hmac_encrypt , secret , _expected_secret , 32 );
355
+ // For the AES IV:
356
+ will_return (__wrap_random_32_bytes , _aes_iv );
338
357
}
339
358
340
- #define PASSWORD ("password")
341
-
342
359
static void _test_keystore_encrypt_and_store_seed (void * * state )
343
360
{
344
361
_expect_encrypt_and_store_seed ();
@@ -532,6 +549,53 @@ static void _test_keystore_encode_xpub(void** state)
532
549
"mzoD84tXp15pviBjgS4df" );
533
550
}
534
551
552
+ static void _test_keystore_create_and_store_seed (void * * state )
553
+ {
554
+ const uint8_t seed_random [32 ] =
555
+ "\x98\xef\xa1\xb6\x0a\x83\x39\x16\x61\xa2\x4d\xc7\x4a\x80\x4f\x34\x36\xe8\x33\xe0\xaa\xbe"
556
+ "\x75\xe9\x71\x1e\x5d\xef\x3a\x8f\x9f\x7c" ;
557
+ const uint8_t host_entropy [32 ] =
558
+ "\x25\x56\x9b\x9a\x11\xf9\xdb\x65\x60\x45\x9e\x8e\x48\xb4\x72\x7a\x4c\x93\x53\x00\x14\x3d"
559
+ "\x97\x89\x89\xed\x55\xdb\x1d\x1b\x9c\xbe" ;
560
+ const uint8_t password_salted_hashed [32 ] =
561
+ "\xad\xee\x84\x29\xf5\xb6\x70\xa9\xd7\x34\x17\x1b\x70\x87\xf3\x8f\x86\x6a\x7e\x26\x5f\x9d"
562
+ "\x7d\x06\xf0\x0e\x6f\xa4\x17\x54\xac\x77" ;
563
+ // expected_seed = seed_random ^ host_entropy ^ password_salted_hashed
564
+ const uint8_t expected_seed [32 ] =
565
+ "\x10\x57\xbe\x05\xee\xcc\x92\xda\xd6\xd3\xc4\x52\x72\xb3\xce\xc1\xfc\x11\x1e\xc6\xe1\x1e"
566
+ "\x9f\x66\x08\xfd\x67\x90\x30\xc0\xaf\xb5" ;
567
+
568
+ // Invalid seed lengths.
569
+ assert_false (keystore_create_and_store_seed (PASSWORD , host_entropy , 8 ));
570
+ assert_false (keystore_create_and_store_seed (PASSWORD , host_entropy , 24 ));
571
+ assert_false (keystore_create_and_store_seed (PASSWORD , host_entropy , 40 ));
572
+
573
+ size_t test_sizes [2 ] = {16 , 32 };
574
+ for (size_t i = 0 ; i < sizeof (test_sizes ) / sizeof (test_sizes [0 ]); i ++ ) {
575
+ size_t seed_len = test_sizes [i ];
576
+ // Seed random is xored with host entropy and the salted/hashed user password.
577
+ will_return (__wrap_random_32_bytes , seed_random );
578
+ expect_memory (__wrap_salt_hash_data , data , PASSWORD , strlen (PASSWORD ));
579
+ expect_value (__wrap_salt_hash_data , data_len , strlen (PASSWORD ));
580
+ expect_string (__wrap_salt_hash_data , purpose , "keystore_seed_generation" );
581
+ will_return (__wrap_salt_hash_data , password_salted_hashed );
582
+ _expect_encrypt_and_store_seed ();
583
+ assert_true (keystore_create_and_store_seed (PASSWORD , host_entropy , seed_len ));
584
+
585
+ // Decrypt and check seed.
586
+ uint8_t encrypted_seed_and_hmac [96 ] = {0 };
587
+ uint8_t len = 0 ;
588
+ assert_true (memory_get_encrypted_seed_and_hmac (encrypted_seed_and_hmac , & len ));
589
+ size_t decrypted_len = len - 48 ;
590
+ uint8_t out [decrypted_len ];
591
+ assert_true (cipher_aes_hmac_decrypt (
592
+ encrypted_seed_and_hmac , len , out , & decrypted_len , _expected_secret ));
593
+ assert_true (decrypted_len == seed_len );
594
+
595
+ assert_memory_equal (expected_seed , out , seed_len );
596
+ }
597
+ }
598
+
535
599
int main (void )
536
600
{
537
601
const struct CMUnitTest tests [] = {
@@ -545,6 +609,7 @@ int main(void)
545
609
cmocka_unit_test (_test_keystore_lock ),
546
610
cmocka_unit_test (_test_keystore_get_bip39_mnemonic ),
547
611
cmocka_unit_test (_test_keystore_encode_xpub ),
612
+ cmocka_unit_test (_test_keystore_create_and_store_seed ),
548
613
};
549
614
return cmocka_run_group_tests (tests , NULL , NULL );
550
615
}
0 commit comments