34#include "status_words.h"
46#if defined(HAVE_ADDRESS_BOOK)
49#define STRUCT_VERSION 0x01
56 s_register_state_t *state;
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(0x23, TAG_CHAIN_ID, handle_chain_id, ENFORCE_UNIQUE_TAG) \
68 X(0x51, TAG_BLOCKCHAIN_FAMILY, handle_blockchain_family, ENFORCE_UNIQUE_TAG) \
69 X(0xf6, TAG_GROUP_HANDLE, handle_group_handle, ENFORCE_UNIQUE_TAG) \
70 X(0x29, TAG_HMAC_PROOF, handle_hmac_proof, ENFORCE_UNIQUE_TAG)
83static bool handle_struct_type(
const tlv_data_t *data, s_identity_ctx *context)
87 PRINTF(
"[Register Identity] Invalid STRUCTURE_TYPE value\n");
100static bool handle_struct_version(
const tlv_data_t *data, s_identity_ctx *context)
104 PRINTF(
"[Register Identity] Invalid STRUCTURE_VERSION value\n");
117static bool handle_contact_name(
const tlv_data_t *data, s_identity_ctx *context)
119 if (!address_book_handle_printable_string(data,
120 context->state->identity.contact_name,
121 sizeof(context->state->identity.contact_name))) {
122 PRINTF(
"CONTACT_NAME: failed to parse\n");
135static bool handle_scope(
const tlv_data_t *data, s_identity_ctx *context)
137 if (!address_book_handle_printable_string(
138 data, context->state->identity.scope,
sizeof(context->state->identity.scope))) {
139 PRINTF(
"SCOPE: failed to parse\n");
152static bool handle_identifier(
const tlv_data_t *data, s_identity_ctx *context)
156 PRINTF(
"IDENTIFIER: failed to extract\n");
159 memmove(context->state->identity.identifier, buf.
ptr, buf.
size);
160 context->state->identity.identifier_len = (uint8_t) buf.
size;
173 return address_book_handle_chain_id(data, &context->state->identity.chain_id);
185 return address_book_handle_blockchain_family(data, &context->state->identity.blockchain_family);
195static bool handle_group_handle(
const tlv_data_t *data, s_identity_ctx *context)
199 PRINTF(
"[Register Identity] GROUP_HANDLE: invalid length (expected %d bytes)\n",
203 memmove(context->state->group_handle, buf.
ptr, GROUP_HANDLE_SIZE);
214static bool handle_hmac_proof(
const tlv_data_t *data, s_identity_ctx *context)
218 PRINTF(
"[Register Identity] HMAC_PROOF: invalid length (expected %d bytes)\n",
222 memmove(context->state->hmac_proof, buf.
ptr, CX_SHA256_SIZE);
234static bool verify_fields(
const s_identity_ctx *context)
238 TAG_STRUCTURE_VERSION,
241 TAG_ACCOUNT_IDENTIFIER,
242 TAG_BLOCKCHAIN_FAMILY);
244 PRINTF(
"Missing mandatory fields in Register Identity descriptor!\n");
250 PRINTF(
"Missing CHAIN_ID for Ethereum family in Register Identity descriptor!\n");
257 if (has_group_handle != has_hmac_proof) {
258 PRINTF(
"GROUP_HANDLE and HMAC_PROOF must be provided together!\n");
270static void print_payload(
const s_identity_ctx *context)
273 PRINTF(
"****************************************************************************\n");
274 PRINTF(
"[Register Identity] - Retrieved Descriptor:\n");
275 PRINTF(
"[Register Identity] - Contact name: %s\n",
276 context->state->identity.contact_name);
277 if (context->state->identity.scope[0] !=
'\0') {
278 PRINTF(
"[Register Identity] - Contact scope: %s\n",
279 context->state->identity.scope);
281 PRINTF(
"[Register Identity] - Blockchain family: %s\n",
284 PRINTF(
"[Register Identity] - Chain ID: %llu\n",
285 context->state->identity.chain_id);
302static bool build_and_send_response(
void)
304 uint8_t group_handle[GROUP_HANDLE_SIZE] = {0};
305 uint8_t hmac_proof[CX_SHA256_SIZE] = {0};
306 uint8_t hmac_rest[CX_SHA256_SIZE] = {0};
309 if (g_ab_payload.reg.active) {
312 if (!address_book_compute_hmac_rest(g_ab_payload.reg.gid,
313 g_ab_payload.reg.identity.scope,
314 g_ab_payload.reg.identity.identifier,
315 g_ab_payload.reg.identity.identifier_len,
316 g_ab_payload.reg.identity.blockchain_family,
317 g_ab_payload.reg.identity.chain_id,
319 PRINTF(
"[Register Identity] Error: Failed to compute HMAC_REST for new address\n");
323 memmove(group_handle, g_ab_payload.reg.group_handle, GROUP_HANDLE_SIZE);
324 memmove(hmac_proof, g_ab_payload.reg.hmac_proof, CX_SHA256_SIZE);
327 if (!address_book_generate_group_handle(group_handle)) {
328 PRINTF(
"[Register Identity] Error: Failed to generate group handle\n");
332 const uint8_t *gid = group_handle;
333 if (!address_book_compute_hmac_proof(
334 gid, g_ab_payload.reg.identity.contact_name, hmac_proof)) {
335 PRINTF(
"[Register Identity] Error: Failed to compute HMAC_PROOF\n");
338 if (!address_book_compute_hmac_rest(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\n");
349 ok = address_book_send_register_identity_response(group_handle, hmac_proof, hmac_rest);
352 explicit_bzero(group_handle,
sizeof(group_handle));
353 explicit_bzero(hmac_proof,
sizeof(hmac_proof));
354 explicit_bzero(hmac_rest,
sizeof(hmac_rest));
363static void review_choice(
bool confirm)
366 bool ok = build_and_send_response();
368 PRINTF(
"[Register Identity] Error: Failed to build and send HMAC proof\n");
370 address_book_finalize_review(ok,
371 "Saved to your Contacts",
372 "Error during registration",
373 finalize_ui_register_identity);
376 address_book_handle_review_rejected(finalize_ui_register_identity);
383static void ui_display(
const s_identity_ctx *context)
385 memset(&g_ab_ui.list, 0,
sizeof(g_ab_ui.list));
386 g_ab_ui.list.nbPairs = 3;
388 g_ab_ui.list.nbPairs++;
390 g_ab_ui.list.callback = get_register_identity_tagValue;
392 "Review contact details",
393#ifdef SCREEN_SIZE_WALLET
394 "Confirm contact details?",
396 "Confirm contact details",
410bolos_err_t register_identity(uint8_t *buffer_in,
size_t buffer_in_length)
412 const buffer_t payload = {.
ptr = buffer_in, .size = buffer_in_length};
413 s_identity_ctx ctx = {0};
416 memset(&g_ab_payload.reg, 0,
sizeof(g_ab_payload.reg));
417 ctx.state = &g_ab_payload.reg;
420 if (!identity_tlv_parser(&payload, &ctx, &ctx.received_tags)) {
421 PRINTF(
"[Register Identity] Failed to parse TLV payload\n");
422 return SWO_INCORRECT_DATA;
424 if (!verify_fields(&ctx)) {
425 return SWO_INCORRECT_DATA;
433 g_ab_payload.reg.active =
true;
434 if (!address_book_verify_group_handle(g_ab_payload.reg.group_handle,
435 g_ab_payload.reg.gid)) {
436 PRINTF(
"[Register Identity] Error: Group handle verification failed\n");
437 return SWO_SECURITY_CONDITION_NOT_SATISFIED;
439 if (!address_book_verify_hmac_proof(g_ab_payload.reg.gid,
440 g_ab_payload.reg.identity.contact_name,
441 g_ab_payload.reg.hmac_proof)) {
442 PRINTF(
"[Register Identity] Error: HMAC_PROOF verification failed\n");
443 return SWO_SECURITY_CONDITION_NOT_SATISFIED;
448 if (!handle_check_register_identity(&g_ab_payload.reg.identity)) {
449 PRINTF(
"[Register Identity] Error: Identity rejected by coin application\n");
450 return SWO_WRONG_PARAMETER_VALUE;
455 return SWO_NO_RESPONSE;
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.
bool tlv_enforce_u8_value(const tlv_data_t *data, uint8_t expected_value)
Enforce that a TLV data contains the expected uint8 value.
bool get_buffer_from_tlv_data(const tlv_data_t *data, buffer_t *out, uint16_t min_size, uint16_t max_size)
Extract a sized buffer from TLV data (zero-copy).
#define DEFINE_TLV_PARSER(TAG_LIST, COMMON_HANDLER, PARSE_FUNCTION_NAME)
Creates a parser function for a given TLV use case.
#define TLV_CHECK_RECEIVED_TAGS(received,...)
static bool handle_chain_id(const tlv_data_t *data, tlv_extracted_t *tlv_extracted)
static bool handle_blockchain_family(const tlv_data_t *data, tlv_extracted_t *tlv_extracted)