Skip to content

Commit ce6ef8a

Browse files
committed
Merge remote-tracking branch 'benma/test-keystore'
2 parents 0310e8c + e2741ab commit ce6ef8a

File tree

2 files changed

+35
-72
lines changed

2 files changed

+35
-72
lines changed

test/unit-test/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ set(TEST_LIST
210210
cleanup
211211
"-Wl,--wrap=util_cleanup_32"
212212
keystore
213-
"-Wl,--wrap=secp256k1_anti_exfil_sign,--wrap=memory_is_initialized,--wrap=memory_is_seeded,--wrap=memory_get_failed_unlock_attempts,--wrap=memory_reset_failed_unlock_attempts,--wrap=memory_increment_failed_unlock_attempts,--wrap=memory_set_encrypted_seed_and_hmac,--wrap=memory_get_encrypted_seed_and_hmac,--wrap=reset_reset,--wrap=salt_hash_data,--wrap=cipher_aes_hmac_encrypt,--wrap=random_32_bytes,--wrap=securechip_kdf"
213+
"-Wl,--wrap=secp256k1_anti_exfil_sign,--wrap=memory_is_initialized,--wrap=memory_is_seeded,--wrap=memory_get_failed_unlock_attempts,--wrap=memory_reset_failed_unlock_attempts,--wrap=memory_increment_failed_unlock_attempts,--wrap=memory_set_encrypted_seed_and_hmac,--wrap=memory_get_encrypted_seed_and_hmac,--wrap=memory_get_salt_root,--wrap=reset_reset,--wrap=salt_hash_data,--wrap=cipher_aes_hmac_encrypt,--wrap=random_32_bytes,--wrap=securechip_kdf"
214214
keystore_antiklepto
215215
""
216216
keystore_functional

test/unit-test/test_keystore.c

Lines changed: 34 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <memory/bitbox02_smarteeprom.h>
2323
#include <memory/memory.h>
2424
#include <memory/smarteeprom.h>
25+
#include <mock_memory.h>
2526
#include <secp256k1_ecdsa_s2c.h>
2627
#include <secp256k1_recovery.h>
2728
#include <secp256k1_schnorrsig.h>
@@ -34,14 +35,18 @@
3435

3536
#define PASSWORD ("password")
3637

38+
int __real_securechip_kdf(securechip_slot_t slot, const uint8_t* msg, size_t len, uint8_t* kdf_out);
3739
int __wrap_securechip_kdf(securechip_slot_t slot, const uint8_t* msg, size_t len, uint8_t* kdf_out)
3840
{
3941
check_expected(slot);
40-
check_expected(msg);
41-
memcpy(kdf_out, (const uint8_t*)mock(), 32);
42-
return 0;
42+
return __real_securechip_kdf(slot, msg, len, kdf_out);
4343
}
4444

45+
static uint8_t _salt_root[KEYSTORE_MAX_SEED_LENGTH] = {
46+
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
47+
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
48+
};
49+
4550
static uint8_t _mock_seed[32] = {
4651
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
4752
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
@@ -74,42 +79,9 @@ static const uint8_t _expected_seckey[32] = {
7479
0x58, 0x92, 0x32, 0x9d, 0x67, 0xdf, 0xd4, 0xad, 0x05, 0xe9, 0xc3, 0xd0, 0x6e, 0xdf, 0x74, 0xfb,
7580
};
7681

77-
static uint8_t _password_salted_hashed_stretch_in[32] = {
78-
0x5e, 0x88, 0x48, 0x98, 0xda, 0x28, 0x04, 0x71, 0x51, 0xd0, 0xe5, 0x6f, 0x8d, 0xc6, 0x29, 0x27,
79-
0x73, 0x60, 0x3d, 0x0d, 0x6a, 0xab, 0xbd, 0xd6, 0x2a, 0x11, 0xef, 0x72, 0x1d, 0x15, 0x42, 0xd8,
80-
};
81-
82-
static uint8_t _password_salted_hashed_stretch_out[32] = {
83-
0x73, 0x60, 0x3d, 0x0d, 0x6a, 0xab, 0xbd, 0xd6, 0x2a, 0x11, 0xef, 0x72, 0x1d, 0x15, 0x42, 0xd8,
84-
0x5e, 0x88, 0x48, 0x98, 0xda, 0x28, 0x04, 0x71, 0x51, 0xd0, 0xe5, 0x6f, 0x8d, 0xc6, 0x29, 0x27,
85-
};
86-
87-
static uint8_t _password_salted_hashed_stretch_out_invalid[32] = {
88-
0x72, 0x60, 0x3d, 0x0d, 0x6a, 0xab, 0xbd, 0xd6, 0x2a, 0x11, 0xef, 0x72, 0x1d, 0x15, 0x42, 0xd8,
89-
0x5e, 0x88, 0x48, 0x98, 0xda, 0x28, 0x04, 0x71, 0x51, 0xd0, 0xe5, 0x6f, 0x8d, 0xc6, 0x29, 0x27,
90-
};
91-
92-
static uint8_t _kdf_out_1[32] = {
93-
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
94-
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
95-
};
96-
97-
static uint8_t _kdf_out_2[32] = {
98-
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
99-
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
100-
};
101-
102-
static uint8_t _kdf_out_3[32] = {
103-
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
104-
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
105-
};
106-
107-
// Fixture: hmac.new(_password_salted_hashed_stretch_out, _kdf_out_3,
108-
// hashlib.sha256).hexdigest()
109-
static uint8_t _expected_secret[32] = {
110-
0x39, 0xa7, 0x4f, 0x75, 0xb6, 0x9d, 0x6c, 0x84, 0x5e, 0x18, 0x91, 0x5b, 0xae, 0x29, 0xd1, 0x06,
111-
0x12, 0x12, 0x40, 0x37, 0x7a, 0x79, 0x97, 0x55, 0xd7, 0xcc, 0xe9, 0x26, 0x1e, 0x16, 0x91, 0x71,
112-
};
82+
static uint8_t _expected_secret[32] =
83+
"\xa8\xf4\xfe\x54\x33\x0e\x1a\xb7\xa0\xe3\xbe\x8a\x8d\x75\xd2\x22\xb2\xae\xc2\xb3\xab\x41\xca"
84+
"\x2a\x04\x0e\xa0\x08\x60\x6b\xaf\xce";
11385

11486
int __real_secp256k1_anti_exfil_sign(
11587
const secp256k1_context* ctx,
@@ -140,6 +112,11 @@ int __wrap_secp256k1_anti_exfil_sign(
140112
return __real_secp256k1_anti_exfil_sign(ctx, sig, msg32, seckey, host_data32, recid);
141113
}
142114

115+
bool __real_salt_hash_data(
116+
const uint8_t* data,
117+
size_t data_len,
118+
const char* purpose,
119+
uint8_t* hash_out);
143120
bool __wrap_salt_hash_data(
144121
const uint8_t* data,
145122
size_t data_len,
@@ -149,8 +126,7 @@ bool __wrap_salt_hash_data(
149126
check_expected(data);
150127
check_expected(data_len);
151128
check_expected(purpose);
152-
memcpy(hash_out, (const void*)mock(), 32);
153-
return true;
129+
return __real_salt_hash_data(data, data_len, purpose, hash_out);
154130
}
155131

156132
bool __real_cipher_aes_hmac_encrypt(
@@ -324,42 +300,32 @@ static void _test_keystore_secp256k1_sign(void** state)
324300
}
325301
}
326302

327-
static void _expect_stretch(bool valid)
303+
static void _expect_stretch(const char* password)
328304
{
329-
expect_memory(__wrap_salt_hash_data, data, PASSWORD, strlen(PASSWORD));
330-
expect_value(__wrap_salt_hash_data, data_len, strlen(PASSWORD));
305+
expect_memory(__wrap_salt_hash_data, data, password, strlen(password));
306+
expect_value(__wrap_salt_hash_data, data_len, strlen(password));
331307
expect_string(__wrap_salt_hash_data, purpose, "keystore_seed_access_in");
332-
will_return(__wrap_salt_hash_data, _password_salted_hashed_stretch_in);
333308

334309
// KDF 1
335310
expect_value(__wrap_securechip_kdf, slot, SECURECHIP_SLOT_ROLLKEY);
336-
expect_memory(__wrap_securechip_kdf, msg, _password_salted_hashed_stretch_in, 32);
337-
will_return(__wrap_securechip_kdf, _kdf_out_1);
338311

339312
// KDF 2
340313
expect_value(__wrap_securechip_kdf, slot, SECURECHIP_SLOT_KDF);
341-
expect_memory(__wrap_securechip_kdf, msg, _kdf_out_1, 32);
342-
will_return(__wrap_securechip_kdf, _kdf_out_2);
343314

344315
// KDF 3
345316
expect_value(__wrap_securechip_kdf, slot, SECURECHIP_SLOT_KDF);
346-
expect_memory(__wrap_securechip_kdf, msg, _kdf_out_2, 32);
347-
will_return(__wrap_securechip_kdf, _kdf_out_3);
348317

349-
expect_memory(__wrap_salt_hash_data, data, PASSWORD, strlen(PASSWORD));
350-
expect_value(__wrap_salt_hash_data, data_len, strlen(PASSWORD));
318+
expect_memory(__wrap_salt_hash_data, data, password, strlen(password));
319+
expect_value(__wrap_salt_hash_data, data_len, strlen(password));
351320
expect_string(__wrap_salt_hash_data, purpose, "keystore_seed_access_out");
352-
will_return(
353-
__wrap_salt_hash_data,
354-
valid ? _password_salted_hashed_stretch_out : _password_salted_hashed_stretch_out_invalid);
355321
}
356322

357323
static void _expect_encrypt_and_store_seed(void)
358324
{
359325
will_return(__wrap_memory_is_initialized, false);
360326

361-
_expect_stretch(true); // first stretch to encrypt
362-
_expect_stretch(true); // second stretch to verify
327+
_expect_stretch(PASSWORD); // first stretch to encrypt
328+
_expect_stretch(PASSWORD); // second stretch to verify
363329

364330
expect_memory(__wrap_cipher_aes_hmac_encrypt, secret, _expected_secret, 32);
365331
// For the AES IV:
@@ -384,15 +350,15 @@ static void _test_keystore_create_and_unlock_twice(void** state)
384350
_smarteeprom_reset();
385351

386352
will_return(__wrap_memory_is_seeded, true);
387-
_expect_stretch(true);
353+
_expect_stretch(PASSWORD);
388354
assert_int_equal(KEYSTORE_OK, keystore_unlock(PASSWORD, &remaining_attempts, NULL));
389355

390356
// Create new (different) seed.
391357
_expect_encrypt_and_store_seed();
392358
assert_int_equal(keystore_encrypt_and_store_seed(_mock_seed_2, 32, PASSWORD), KEYSTORE_OK);
393359

394360
will_return(__wrap_memory_is_seeded, true);
395-
_expect_stretch(true);
361+
_expect_stretch(PASSWORD);
396362
assert_int_equal(KEYSTORE_OK, keystore_unlock(PASSWORD, &remaining_attempts, NULL));
397363
}
398364

@@ -410,7 +376,7 @@ static void _perform_some_unlocks(void)
410376
for (int i = 0; i < 3; i++) {
411377
_reset_reset_called = false;
412378
will_return(__wrap_memory_is_seeded, true);
413-
_expect_stretch(true);
379+
_expect_stretch(PASSWORD);
414380
assert_int_equal(KEYSTORE_OK, keystore_unlock(PASSWORD, &remaining_attempts, NULL));
415381
assert_int_equal(remaining_attempts, MAX_UNLOCK_ATTEMPTS);
416382
assert_false(_reset_reset_called);
@@ -437,11 +403,11 @@ static void _test_keystore_unlock(void** state)
437403
for (int i = 1; i <= MAX_UNLOCK_ATTEMPTS; i++) {
438404
_reset_reset_called = false;
439405
will_return(__wrap_memory_is_seeded, true);
440-
_expect_stretch(false);
406+
_expect_stretch("invalid password");
441407
assert_int_equal(
442408
i >= MAX_UNLOCK_ATTEMPTS ? KEYSTORE_ERR_MAX_ATTEMPTS_EXCEEDED
443409
: KEYSTORE_ERR_INCORRECT_PASSWORD,
444-
keystore_unlock(PASSWORD, &remaining_attempts, NULL));
410+
keystore_unlock("invalid password", &remaining_attempts, NULL));
445411
assert_int_equal(remaining_attempts, MAX_UNLOCK_ATTEMPTS - i);
446412
// Wrong password does not lock the keystore again if already unlocked.
447413
_expect_seeded(true);
@@ -567,13 +533,10 @@ static void _test_keystore_create_and_store_seed(void** state)
567533
const uint8_t host_entropy[32] =
568534
"\x25\x56\x9b\x9a\x11\xf9\xdb\x65\x60\x45\x9e\x8e\x48\xb4\x72\x7a\x4c\x93\x53\x00\x14\x3d"
569535
"\x97\x89\x89\xed\x55\xdb\x1d\x1b\x9c\xbe";
570-
const uint8_t password_salted_hashed[32] =
571-
"\xad\xee\x84\x29\xf5\xb6\x70\xa9\xd7\x34\x17\x1b\x70\x87\xf3\x8f\x86\x6a\x7e\x26\x5f\x9d"
572-
"\x7d\x06\xf0\x0e\x6f\xa4\x17\x54\xac\x77";
573536
// expected_seed = seed_random ^ host_entropy ^ password_salted_hashed
574537
const uint8_t expected_seed[32] =
575-
"\x10\x57\xbe\x05\xee\xcc\x92\xda\xd6\xd3\xc4\x52\x72\xb3\xce\xc1\xfc\x11\x1e\xc6\xe1\x1e"
576-
"\x9f\x66\x08\xfd\x67\x90\x30\xc0\xaf\xb5";
538+
"\x55\x7e\x30\x0c\xc2\x6a\x6d\xc8\x95\xb3\x62\xf1\xe0\xe3\x0a\x70\x02\xb0\xcf\x7d\x5e\xa6"
539+
"\x49\x4d\xb7\xbe\x34\x4e\x40\x85\x6a\x8e";
577540

578541
// Invalid seed lengths.
579542
assert_int_equal(
@@ -591,7 +554,6 @@ static void _test_keystore_create_and_store_seed(void** state)
591554
expect_memory(__wrap_salt_hash_data, data, PASSWORD, strlen(PASSWORD));
592555
expect_value(__wrap_salt_hash_data, data_len, strlen(PASSWORD));
593556
expect_string(__wrap_salt_hash_data, purpose, "keystore_seed_generation");
594-
will_return(__wrap_salt_hash_data, password_salted_hashed);
595557
_expect_encrypt_and_store_seed();
596558
assert_int_equal(
597559
keystore_create_and_store_seed(PASSWORD, host_entropy, seed_len), KEYSTORE_OK);
@@ -604,8 +566,7 @@ static void _test_keystore_create_and_store_seed(void** state)
604566
uint8_t out[decrypted_len];
605567
assert_true(cipher_aes_hmac_decrypt(
606568
encrypted_seed_and_hmac, len, out, &decrypted_len, _expected_secret));
607-
assert_true(decrypted_len == seed_len);
608-
569+
assert_int_equal(decrypted_len, seed_len);
609570
assert_memory_equal(expected_seed, out, seed_len);
610571
}
611572
}
@@ -818,6 +779,8 @@ static void _test_keystore_secp256k1_schnorr_bip86_sign(void** state)
818779

819780
int main(void)
820781
{
782+
mock_memory_set_salt_root(_salt_root);
783+
821784
const struct CMUnitTest tests[] = {
822785
cmocka_unit_test(_test_keystore_get_xpub),
823786
cmocka_unit_test(_test_keystore_get_root_fingerprint),

0 commit comments

Comments
 (0)