49#ifdef HAVE_ADDRESS_BOOK
64static bool address_book_derive_hmac_key(
const cx_ecfp_256_private_key_t *privkey,
67 uint8_t hmac_key[CX_SHA256_SIZE])
69 cx_sha256_t hash_ctx = {0};
70 uint8_t hash[CX_SHA256_SIZE] = {0};
71 cx_err_t error = CX_INTERNAL_ERROR;
74 cx_sha256_init(&hash_ctx);
75 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &hash_ctx, 0, salt, salt_len, NULL, 0));
76 CX_CHECK(cx_hash_no_throw(
77 (cx_hash_t *) &hash_ctx,
CX_LAST, privkey->d, privkey->d_len, hash,
sizeof(hash)));
78 memmove(hmac_key, hash, CX_SHA256_SIZE);
82 explicit_bzero(hash,
sizeof(hash));
102 cx_hmac_sha256_t *hmac_ctx)
104 cx_ecfp_256_private_key_t private_key = {0};
105 uint8_t hmac_key[CX_SHA256_SIZE] = {0};
106 cx_err_t error = CX_INTERNAL_ERROR;
107 bool success =
false;
109 CX_CHECK(bip32_derive_init_privkey_256(
110 CX_CURVE_SECP256K1, bip32_path->
path, bip32_path->
length, &private_key, NULL));
111 if (!address_book_derive_hmac_key(&private_key, salt, salt_len, hmac_key)) {
114 CX_CHECK(cx_hmac_sha256_init_no_throw(hmac_ctx, hmac_key, CX_SHA256_SIZE));
118 explicit_bzero(&private_key,
sizeof(private_key));
119 explicit_bzero(hmac_key,
sizeof(hmac_key));
134bool address_book_send_hmac_proof(uint8_t type,
const uint8_t hmac_proof[CX_SHA256_SIZE])
139 G_io_tx_buffer[tx++] = type;
140 memmove(&G_io_tx_buffer[tx], hmac_proof, CX_SHA256_SIZE);
141 tx += CX_SHA256_SIZE;
143 io_send_response_pointer(G_io_tx_buffer, tx, SWO_SUCCESS);
158bool address_book_send_register_identity_response(
const uint8_t group_handle[GROUP_HANDLE_SIZE],
159 const uint8_t hmac_proof[CX_SHA256_SIZE],
160 const uint8_t hmac_rest[CX_SHA256_SIZE])
164 G_io_tx_buffer[tx++] = TYPE_REGISTER_IDENTITY;
165 memmove(&G_io_tx_buffer[tx], group_handle, GROUP_HANDLE_SIZE);
166 tx += GROUP_HANDLE_SIZE;
167 memmove(&G_io_tx_buffer[tx], hmac_proof, CX_SHA256_SIZE);
168 tx += CX_SHA256_SIZE;
169 memmove(&G_io_tx_buffer[tx], hmac_rest, CX_SHA256_SIZE);
170 tx += CX_SHA256_SIZE;
172 io_send_response_pointer(G_io_tx_buffer, tx, SWO_SUCCESS);
188bool address_book_generate_group_handle(
const path_bip32_t *bip32_path,
189 uint8_t group_handle[GROUP_HANDLE_SIZE])
191 static const uint8_t salt[] =
"AddressBook-Group";
192 cx_hmac_sha256_t hmac_ctx = {0};
193 cx_err_t error = CX_INTERNAL_ERROR;
194 bool success =
false;
195 uint8_t *gid = group_handle;
196 uint8_t *mac = group_handle + GID_SIZE;
198 cx_rng_no_throw(gid, GID_SIZE);
199 if (!init_hmac_ctx(bip32_path, salt,
sizeof(salt) - 1, &hmac_ctx)) {
203 cx_hmac_no_throw((cx_hmac_t *) &hmac_ctx,
CX_LAST, gid, GID_SIZE, mac, CX_SHA256_SIZE));
221bool address_book_verify_group_handle(
const path_bip32_t *bip32_path,
222 const uint8_t group_handle[GROUP_HANDLE_SIZE],
223 uint8_t gid_out[GID_SIZE])
225 static const uint8_t salt[] =
"AddressBook-Group";
226 cx_hmac_sha256_t hmac_ctx = {0};
227 uint8_t mac_expected[CX_SHA256_SIZE] = {0};
228 cx_err_t error = CX_INTERNAL_ERROR;
229 bool success =
false;
230 const uint8_t *gid = group_handle;
231 const uint8_t *mac = group_handle + GID_SIZE;
233 if (!init_hmac_ctx(bip32_path, salt,
sizeof(salt) - 1, &hmac_ctx)) {
236 CX_CHECK(cx_hmac_no_throw(
237 (cx_hmac_t *) &hmac_ctx,
CX_LAST, gid, GID_SIZE, mac_expected, CX_SHA256_SIZE));
238 if (os_secure_memcmp(mac, mac_expected, CX_SHA256_SIZE) != 0) {
239 PRINTF(
"[Address Book] Group handle MAC verification failed\n");
242 memmove(gid_out, gid, GID_SIZE);
246 explicit_bzero(mac_expected,
sizeof(mac_expected));
262bool address_book_compute_hmac_proof(
const path_bip32_t *bip32_path,
263 const uint8_t gid[GID_SIZE],
265 uint8_t hmac_out[CX_SHA256_SIZE])
267 static const uint8_t salt[] =
"AddressBook-Identity";
268 cx_hmac_sha256_t hmac_ctx = {0};
269 cx_err_t error = CX_INTERNAL_ERROR;
270 bool success =
false;
271 uint8_t name_len = (uint8_t) strlen(name);
273 if (!init_hmac_ctx(bip32_path, salt,
sizeof(salt) - 1, &hmac_ctx)) {
277 CX_CHECK(cx_hmac_no_throw((cx_hmac_t *) &hmac_ctx, 0, gid, GID_SIZE, NULL, 0));
279 CX_CHECK(cx_hmac_no_throw((cx_hmac_t *) &hmac_ctx, 0, &name_len, 1, NULL, 0));
280 CX_CHECK(cx_hmac_no_throw((cx_hmac_t *) &hmac_ctx,
282 (
const uint8_t *) name,
301bool address_book_verify_hmac_proof(
const path_bip32_t *bip32_path,
302 const uint8_t gid[GID_SIZE],
304 const uint8_t hmac_expected[CX_SHA256_SIZE])
306 uint8_t hmac_computed[CX_SHA256_SIZE] = {0};
307 bool success =
false;
309 if (!address_book_compute_hmac_proof(bip32_path, gid, name, hmac_computed)) {
312 if (os_secure_memcmp(hmac_computed, hmac_expected, CX_SHA256_SIZE) != 0) {
313 PRINTF(
"HMAC_PROOF mismatch\n");
319 explicit_bzero(hmac_computed,
sizeof(hmac_computed));
340bool address_book_compute_hmac_rest(
const path_bip32_t *bip32_path,
341 const uint8_t gid[GID_SIZE],
343 const uint8_t *identifier,
344 uint8_t identifier_len,
347 uint8_t hmac_out[CX_SHA256_SIZE])
349 static const uint8_t salt[] =
"AddressBook-Identity";
350 cx_hmac_sha256_t hmac_ctx = {0};
351 cx_err_t error = CX_INTERNAL_ERROR;
352 bool success =
false;
353 uint8_t scope_len = (scope != NULL) ? (uint8_t) strlen(scope) : 0;
354 uint8_t family_byte = (uint8_t) family;
356 if (!init_hmac_ctx(bip32_path, salt,
sizeof(salt) - 1, &hmac_ctx)) {
360 CX_CHECK(cx_hmac_no_throw((cx_hmac_t *) &hmac_ctx, 0, gid, GID_SIZE, NULL, 0));
362 CX_CHECK(cx_hmac_no_throw((cx_hmac_t *) &hmac_ctx, 0, &scope_len, 1, NULL, 0));
364 CX_CHECK(cx_hmac_no_throw(
365 (cx_hmac_t *) &hmac_ctx, 0, (
const uint8_t *) scope, scope_len, NULL, 0));
368 CX_CHECK(cx_hmac_no_throw((cx_hmac_t *) &hmac_ctx, 0, &identifier_len, 1, NULL, 0));
369 CX_CHECK(cx_hmac_no_throw((cx_hmac_t *) &hmac_ctx, 0, identifier, identifier_len, NULL, 0));
371 CX_CHECK(cx_hmac_no_throw((cx_hmac_t *) &hmac_ctx, 0, &family_byte, 1, NULL, 0));
374 uint8_t chain_id_be[8] = {0};
375 U8BE_ENCODE(chain_id_be, 0, chain_id);
376 CX_CHECK(cx_hmac_no_throw(
377 (cx_hmac_t *) &hmac_ctx, 0, chain_id_be,
sizeof(chain_id_be), NULL, 0));
379 CX_CHECK(cx_hmac_no_throw((cx_hmac_t *) &hmac_ctx,
CX_LAST, NULL, 0, hmac_out, CX_SHA256_SIZE));
399bool address_book_verify_hmac_rest(
const path_bip32_t *bip32_path,
400 const uint8_t gid[GID_SIZE],
402 const uint8_t *identifier,
403 uint8_t identifier_len,
406 const uint8_t hmac_expected[CX_SHA256_SIZE])
408 uint8_t hmac_computed[CX_SHA256_SIZE] = {0};
409 bool success =
false;
411 if (!address_book_compute_hmac_rest(
412 bip32_path, gid, scope, identifier, identifier_len, family, chain_id, hmac_computed)) {
415 if (os_secure_memcmp(hmac_computed, hmac_expected, CX_SHA256_SIZE) != 0) {
416 PRINTF(
"HMAC_REST mismatch\n");
422 explicit_bzero(hmac_computed,
sizeof(hmac_computed));
426#ifdef HAVE_ADDRESS_BOOK_LEDGER_ACCOUNT
443bool address_book_compute_hmac_proof_ledger_account(
const path_bip32_t *bip32_path,
447 uint8_t hmac_out[CX_SHA256_SIZE])
449 static const uint8_t salt[] =
"AddressBook-LedgerAccount";
450 cx_hmac_sha256_t hmac_ctx = {0};
451 cx_err_t error = CX_INTERNAL_ERROR;
452 bool success =
false;
453 uint8_t name_len = (uint8_t) strlen(name);
454 uint8_t family_byte = (uint8_t) family;
456 if (!init_hmac_ctx(bip32_path, salt,
sizeof(salt) - 1, &hmac_ctx)) {
460 CX_CHECK(cx_hmac_no_throw((cx_hmac_t *) &hmac_ctx, 0, &name_len, 1, NULL, 0));
462 cx_hmac_no_throw((cx_hmac_t *) &hmac_ctx, 0, (
const uint8_t *) name, name_len, NULL, 0));
464 CX_CHECK(cx_hmac_no_throw((cx_hmac_t *) &hmac_ctx, 0, &family_byte, 1, NULL, 0));
467 uint8_t chain_id_be[8] = {0};
468 U8BE_ENCODE(chain_id_be, 0, chain_id);
469 CX_CHECK(cx_hmac_no_throw(
470 (cx_hmac_t *) &hmac_ctx, 0, chain_id_be,
sizeof(chain_id_be), NULL, 0));
472 CX_CHECK(cx_hmac_no_throw((cx_hmac_t *) &hmac_ctx,
CX_LAST, NULL, 0, hmac_out, CX_SHA256_SIZE));
489bool address_book_verify_hmac_proof_ledger_account(
const path_bip32_t *bip32_path,
493 const uint8_t hmac_expected[CX_SHA256_SIZE])
495 uint8_t hmac_computed[CX_SHA256_SIZE] = {0};
496 bool success =
false;
498 if (!address_book_compute_hmac_proof_ledger_account(
499 bip32_path, name, family, chain_id, hmac_computed)) {
502 if (os_secure_memcmp(hmac_computed, hmac_expected, CX_SHA256_SIZE) != 0) {
503 PRINTF(
"HMAC proof mismatch\n");
509 explicit_bzero(hmac_computed,
sizeof(hmac_computed));
Register / Edit Contact Name / Edit Scope / Edit Identifier.
HMAC (Keyed-Hash Message Authentication Code)
Random Number Generation.
SHA-2 (Secure Hash Algorithm 2)
uint32_t path[MAX_BIP32_PATH]