34#include "status_words.h"
35#include "tlv_library.h"
46#if defined(HAVE_ADDRESS_BOOK)
49#define STRUCT_VERSION 0x01
56 s_register_state_t *state;
57 TLV_reception_t received_tags;
61#define REGISTER_IDENTITY_TAGS(X) \
62 X(0x01, TAG_STRUCTURE_TYPE, handle_struct_type, ENFORCE_UNIQUE_TAG) \
63 X(0x02, TAG_STRUCTURE_VERSION, handle_struct_version, ENFORCE_UNIQUE_TAG) \
64 X(0xf0, TAG_CONTACT_NAME, handle_contact_name, ENFORCE_UNIQUE_TAG) \
65 X(0xf1, TAG_SCOPE, handle_scope, ENFORCE_UNIQUE_TAG) \
66 X(0xf2, TAG_ACCOUNT_IDENTIFIER, handle_identifier, ENFORCE_UNIQUE_TAG) \
67 X(0x21, TAG_DERIVATION_PATH, handle_derivation_path, ENFORCE_UNIQUE_TAG) \
68 X(0x23, TAG_CHAIN_ID, handle_chain_id, ENFORCE_UNIQUE_TAG) \
69 X(0x51, TAG_BLOCKCHAIN_FAMILY, handle_blockchain_family, ENFORCE_UNIQUE_TAG) \
70 X(0xf6, TAG_GROUP_HANDLE, handle_group_handle, ENFORCE_UNIQUE_TAG) \
71 X(0x29, TAG_HMAC_PROOF, handle_hmac_proof, ENFORCE_UNIQUE_TAG)
84static bool handle_struct_type(
const tlv_data_t *data, s_identity_ctx *context)
87 if (!tlv_enforce_u8_value(data, TYPE_REGISTER_IDENTITY)) {
88 PRINTF(
"[Register Identity] Invalid STRUCTURE_TYPE value\n");
101static bool handle_struct_version(
const tlv_data_t *data, s_identity_ctx *context)
104 if (!tlv_enforce_u8_value(data, STRUCT_VERSION)) {
105 PRINTF(
"[Register Identity] Invalid STRUCTURE_VERSION value\n");
118static bool handle_contact_name(
const tlv_data_t *data, s_identity_ctx *context)
120 if (!address_book_handle_printable_string(data,
121 context->state->identity.contact_name,
122 sizeof(context->state->identity.contact_name))) {
123 PRINTF(
"CONTACT_NAME: failed to parse\n");
136static bool handle_scope(
const tlv_data_t *data, s_identity_ctx *context)
138 if (!address_book_handle_printable_string(
139 data, context->state->identity.scope,
sizeof(context->state->identity.scope))) {
140 PRINTF(
"SCOPE: failed to parse\n");
153static bool handle_identifier(
const tlv_data_t *data, s_identity_ctx *context)
156 if (!get_buffer_from_tlv_data(data, &buf, 1, IDENTIFIER_MAX_LENGTH)) {
157 PRINTF(
"IDENTIFIER: failed to extract\n");
160 memmove(context->state->identity.identifier, buf.
ptr, buf.
size);
161 context->state->identity.identifier_len = (uint8_t) buf.
size;
172static bool handle_derivation_path(
const tlv_data_t *data, s_identity_ctx *context)
174 return address_book_handle_derivation_path(data, &context->state->identity.bip32_path);
184static bool handle_chain_id(
const tlv_data_t *data, s_identity_ctx *context)
186 return address_book_handle_chain_id(data, &context->state->identity.chain_id);
196static bool handle_blockchain_family(
const tlv_data_t *data, s_identity_ctx *context)
198 return address_book_handle_blockchain_family(data, &context->state->identity.blockchain_family);
208static bool handle_group_handle(
const tlv_data_t *data, s_identity_ctx *context)
211 if (!get_buffer_from_tlv_data(data, &buf, GROUP_HANDLE_SIZE, GROUP_HANDLE_SIZE)) {
212 PRINTF(
"[Register Identity] GROUP_HANDLE: invalid length (expected %d bytes)\n",
216 memmove(context->state->group_handle, buf.
ptr, GROUP_HANDLE_SIZE);
227static bool handle_hmac_proof(
const tlv_data_t *data, s_identity_ctx *context)
230 if (!get_buffer_from_tlv_data(data, &buf, CX_SHA256_SIZE, CX_SHA256_SIZE)) {
231 PRINTF(
"[Register Identity] HMAC_PROOF: invalid length (expected %d bytes)\n",
235 memmove(context->state->hmac_proof, buf.
ptr, CX_SHA256_SIZE);
239DEFINE_TLV_PARSER(REGISTER_IDENTITY_TAGS, NULL, identity_tlv_parser)
247static bool verify_fields(
const s_identity_ctx *context)
249 bool result = TLV_CHECK_RECEIVED_TAGS(context->received_tags,
251 TAG_STRUCTURE_VERSION,
254 TAG_ACCOUNT_IDENTIFIER,
256 TAG_BLOCKCHAIN_FAMILY);
258 PRINTF(
"Missing mandatory fields in Register Identity descriptor!\n");
262 result = TLV_CHECK_RECEIVED_TAGS(context->received_tags, TAG_CHAIN_ID);
264 PRINTF(
"Missing CHAIN_ID for Ethereum family in Register Identity descriptor!\n");
269 bool has_group_handle = TLV_CHECK_RECEIVED_TAGS(context->received_tags, TAG_GROUP_HANDLE);
270 bool has_hmac_proof = TLV_CHECK_RECEIVED_TAGS(context->received_tags, TAG_HMAC_PROOF);
271 if (has_group_handle != has_hmac_proof) {
272 PRINTF(
"GROUP_HANDLE and HMAC_PROOF must be provided together!\n");
284static void print_payload(
const s_identity_ctx *context)
289 PRINTF(
"****************************************************************************\n");
290 PRINTF(
"[Register Identity] - Retrieved Descriptor:\n");
291 PRINTF(
"[Register Identity] - Contact name: %s\n",
292 context->state->identity.contact_name);
293 if (context->state->identity.scope[0] !=
'\0') {
294 PRINTF(
"[Register Identity] - Contact scope: %s\n",
295 context->state->identity.scope);
298 PRINTF(
"[Register Identity] - Derivation path[%d]: %s\n",
299 context->state->identity.bip32_path.length,
303 PRINTF(
"[Register Identity] - Derivation path length[%d] (failed to format)\n",
304 context->state->identity.bip32_path.length);
306 PRINTF(
"[Register Identity] - Blockchain family: %s\n",
309 PRINTF(
"[Register Identity] - Chain ID: %llu\n",
310 context->state->identity.chain_id);
327static bool build_and_send_response(
void)
329 uint8_t group_handle[GROUP_HANDLE_SIZE] = {0};
330 uint8_t hmac_proof[CX_SHA256_SIZE] = {0};
331 uint8_t hmac_rest[CX_SHA256_SIZE] = {0};
334 if (g_ab_payload.reg.active) {
337 if (!address_book_compute_hmac_rest(&g_ab_payload.reg.identity.bip32_path,
338 g_ab_payload.reg.gid,
339 g_ab_payload.reg.identity.scope,
340 g_ab_payload.reg.identity.identifier,
341 g_ab_payload.reg.identity.identifier_len,
342 g_ab_payload.reg.identity.blockchain_family,
343 g_ab_payload.reg.identity.chain_id,
345 PRINTF(
"[Register Identity] Error: Failed to compute HMAC_REST for new address\n");
349 memmove(group_handle, g_ab_payload.reg.group_handle, GROUP_HANDLE_SIZE);
350 memmove(hmac_proof, g_ab_payload.reg.hmac_proof, CX_SHA256_SIZE);
353 if (!address_book_generate_group_handle(&g_ab_payload.reg.identity.bip32_path,
355 PRINTF(
"[Register Identity] Error: Failed to generate group handle\n");
359 const uint8_t *gid = group_handle;
360 if (!address_book_compute_hmac_proof(&g_ab_payload.reg.identity.bip32_path,
362 g_ab_payload.reg.identity.contact_name,
364 PRINTF(
"[Register Identity] Error: Failed to compute HMAC_PROOF\n");
367 if (!address_book_compute_hmac_rest(&g_ab_payload.reg.identity.bip32_path,
369 g_ab_payload.reg.identity.scope,
370 g_ab_payload.reg.identity.identifier,
371 g_ab_payload.reg.identity.identifier_len,
372 g_ab_payload.reg.identity.blockchain_family,
373 g_ab_payload.reg.identity.chain_id,
375 PRINTF(
"[Register Identity] Error: Failed to compute HMAC_REST\n");
379 ok = address_book_send_register_identity_response(group_handle, hmac_proof, hmac_rest);
382 explicit_bzero(group_handle,
sizeof(group_handle));
383 explicit_bzero(hmac_proof,
sizeof(hmac_proof));
384 explicit_bzero(hmac_rest,
sizeof(hmac_rest));
393static void review_choice(
bool confirm)
396 bool ok = build_and_send_response();
398 PRINTF(
"[Register Identity] Error: Failed to build and send HMAC proof\n");
400 address_book_finalize_review(ok,
401 "Saved to your Contacts",
402 "Error during registration",
403 finalize_ui_register_identity);
406 address_book_handle_review_rejected(finalize_ui_register_identity);
413static void ui_display(
void)
415 memset(&g_ab_ui.list, 0,
sizeof(g_ab_ui.list));
416 g_ab_ui.list.nbPairs = 4;
417 g_ab_ui.list.callback = get_register_identity_tagValue;
419 "Review contact details",
420#ifdef SCREEN_SIZE_WALLET
421 "Confirm contact details?",
423 "Confirm contact details",
437bolos_err_t register_identity(uint8_t *buffer_in,
size_t buffer_in_length)
439 const buffer_t payload = {.
ptr = buffer_in, .size = buffer_in_length};
440 s_identity_ctx ctx = {0};
443 memset(&g_ab_payload.reg, 0,
sizeof(g_ab_payload.reg));
444 ctx.state = &g_ab_payload.reg;
447 if (!identity_tlv_parser(&payload, &ctx, &ctx.received_tags)) {
448 PRINTF(
"[Register Identity] Failed to parse TLV payload\n");
449 return SWO_INCORRECT_DATA;
451 if (!verify_fields(&ctx)) {
452 return SWO_INCORRECT_DATA;
459 if (TLV_CHECK_RECEIVED_TAGS(ctx.received_tags, TAG_GROUP_HANDLE)) {
460 g_ab_payload.reg.active =
true;
461 if (!address_book_verify_group_handle(&g_ab_payload.reg.identity.bip32_path,
462 g_ab_payload.reg.group_handle,
463 g_ab_payload.reg.gid)) {
464 PRINTF(
"[Register Identity] Error: Group handle verification failed\n");
465 return SWO_SECURITY_CONDITION_NOT_SATISFIED;
467 if (!address_book_verify_hmac_proof(&g_ab_payload.reg.identity.bip32_path,
468 g_ab_payload.reg.gid,
469 g_ab_payload.reg.identity.contact_name,
470 g_ab_payload.reg.hmac_proof)) {
471 PRINTF(
"[Register Identity] Error: HMAC_PROOF verification failed\n");
472 return SWO_SECURITY_CONDITION_NOT_SATISFIED;
477 if (!handle_check_register_identity(&g_ab_payload.reg.identity)) {
478 PRINTF(
"[Register Identity] Error: Identity rejected by coin application\n");
479 return SWO_WRONG_PARAMETER_VALUE;
484 return SWO_NO_RESPONSE;
bool bip32_path_format_simple(path_bip32_t *bip32, char *out, size_t out_len)
Format a BIP32 path as a string.
Register / Edit Contact Name / Edit Scope / Edit Identifier.
#define LARGE_ADDRESS_BOOK_ICON
API of the Advanced BOLOS Graphical Library, for typical application use-cases.
size_t size
Pointer to byte buffer.