Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
ledger_account_provide_contact.c
Go to the documentation of this file.
1/*****************************************************************************
2 * (c) 2026 Ledger SAS.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
42/* Includes ------------------------------------------------------------------*/
43#include <string.h>
44#include "os_utils.h"
45#include "status_words.h"
46#include "tlv_library.h"
47#include "buffer.h"
48#include "bip32.h"
49#include "address_book.h"
51#include "address_book_crypto.h"
52#include "address_book_common.h"
53#include "ledger_account.h"
54
55#if defined(HAVE_ADDRESS_BOOK) && defined(HAVE_ADDRESS_BOOK_LEDGER_ACCOUNT)
56
57/* Private defines------------------------------------------------------------*/
58#define STRUCT_VERSION 0x01
59
60/* Private types, structures, unions -----------------------------------------*/
61typedef struct {
62 ledger_account_t *ledger_account;
63 TLV_reception_t received_tags;
64 uint8_t hmac_proof[CX_SHA256_SIZE];
65} s_provide_ledger_account_ctx;
66
67/* Private macros-------------------------------------------------------------*/
68#define PROVIDE_LEDGER_ACCOUNT_TAGS(X) \
69 X(0x01, TAG_STRUCTURE_TYPE, handle_struct_type, ENFORCE_UNIQUE_TAG) \
70 X(0x02, TAG_STRUCTURE_VERSION, handle_struct_version, ENFORCE_UNIQUE_TAG) \
71 X(0xf0, TAG_CONTACT_NAME, handle_contact_name, ENFORCE_UNIQUE_TAG) \
72 X(0x21, TAG_DERIVATION_PATH, handle_derivation_path, ENFORCE_UNIQUE_TAG) \
73 X(0x23, TAG_CHAIN_ID, handle_chain_id, ENFORCE_UNIQUE_TAG) \
74 X(0x51, TAG_BLOCKCHAIN_FAMILY, handle_blockchain_family, ENFORCE_UNIQUE_TAG) \
75 X(0x29, TAG_HMAC_PROOF, handle_hmac_proof, ENFORCE_UNIQUE_TAG)
76
77/* Private variables ---------------------------------------------------------*/
78
79/* Private functions ---------------------------------------------------------*/
80
88static bool handle_struct_type(const tlv_data_t *data, s_provide_ledger_account_ctx *context)
89{
90 UNUSED(context);
91 if (!tlv_enforce_u8_value(data, TYPE_PROVIDE_LEDGER_ACCOUNT_CONTACT)) {
92 PRINTF("[Provide Ledger Account] Invalid STRUCTURE_TYPE value\n");
93 return false;
94 }
95 return true;
96}
97
105static bool handle_struct_version(const tlv_data_t *data, s_provide_ledger_account_ctx *context)
106{
107 UNUSED(context);
108 if (!tlv_enforce_u8_value(data, STRUCT_VERSION)) {
109 PRINTF("[Provide Ledger Account] Invalid STRUCTURE_VERSION value\n");
110 return false;
111 }
112 return true;
113}
114
122static bool handle_contact_name(const tlv_data_t *data, s_provide_ledger_account_ctx *context)
123{
124 if (!address_book_handle_printable_string(data,
125 context->ledger_account->account_name,
126 sizeof(context->ledger_account->account_name))) {
127 PRINTF("[Provide Ledger Account] CONTACT_NAME: failed to parse\n");
128 return false;
129 }
130 return true;
131}
132
140static bool handle_derivation_path(const tlv_data_t *data, s_provide_ledger_account_ctx *context)
141{
142 return address_book_handle_derivation_path(data, &context->ledger_account->bip32_path);
143}
144
152static bool handle_chain_id(const tlv_data_t *data, s_provide_ledger_account_ctx *context)
153{
154 return address_book_handle_chain_id(data, &context->ledger_account->chain_id);
155}
156
164static bool handle_blockchain_family(const tlv_data_t *data, s_provide_ledger_account_ctx *context)
165{
166 return address_book_handle_blockchain_family(data, &context->ledger_account->blockchain_family);
167}
168
176static bool handle_hmac_proof(const tlv_data_t *data, s_provide_ledger_account_ctx *context)
177{
178 buffer_t buf = {0};
179 if (!get_buffer_from_tlv_data(data, &buf, CX_SHA256_SIZE, CX_SHA256_SIZE)) {
180 PRINTF("[Provide Ledger Account] HMAC_PROOF: invalid length (expected %d bytes)\n",
181 CX_SHA256_SIZE);
182 return false;
183 }
184 memmove(context->hmac_proof, buf.ptr, CX_SHA256_SIZE);
185 return true;
186}
187
188DEFINE_TLV_PARSER(PROVIDE_LEDGER_ACCOUNT_TAGS, NULL, provide_ledger_account_tlv_parser)
189
190
196static bool verify_fields(const s_provide_ledger_account_ctx *context)
197{
198 bool result = TLV_CHECK_RECEIVED_TAGS(context->received_tags,
199 TAG_STRUCTURE_TYPE,
200 TAG_STRUCTURE_VERSION,
201 TAG_CONTACT_NAME,
202 TAG_DERIVATION_PATH,
203 TAG_BLOCKCHAIN_FAMILY,
204 TAG_HMAC_PROOF);
205 if (!result) {
206 PRINTF("[Provide Ledger Account] Missing mandatory fields!\n");
207 return false;
208 }
209 if (context->ledger_account->blockchain_family == FAMILY_ETHEREUM) {
210 result = TLV_CHECK_RECEIVED_TAGS(context->received_tags, TAG_CHAIN_ID);
211 if (!result) {
212 PRINTF("[Provide Ledger Account] Missing CHAIN_ID for Ethereum family!\n");
213 return false;
214 }
215 }
216 return true;
217}
218
224static void print_payload(const s_provide_ledger_account_ctx *context)
225{
226 UNUSED(context);
227 char out[50] = {0};
228
229 PRINTF("****************************************************************************\n");
230 PRINTF("[Provide Ledger Account] - Retrieved Descriptor:\n");
231 PRINTF("[Provide Ledger Account] - Account name: %s\n",
232 context->ledger_account->account_name);
233 if (bip32_path_format_simple(&context->ledger_account->bip32_path, out, sizeof(out))) {
234 PRINTF("[Provide Ledger Account] - Derivation path[%d]: %s\n",
235 context->ledger_account->bip32_path.length,
236 out);
237 }
238 else {
239 PRINTF("[Provide Ledger Account] - Derivation path length[%d] (failed to format)\n",
240 context->ledger_account->bip32_path.length);
241 }
242 PRINTF("[Provide Ledger Account] - Blockchain family: %s\n",
243 FAMILY_AS_STR(context->ledger_account->blockchain_family));
244 if (context->ledger_account->blockchain_family == FAMILY_ETHEREUM) {
245 PRINTF("[Provide Ledger Account] - Chain ID: %llu\n",
246 context->ledger_account->chain_id);
247 }
248}
249
250/* Exported functions --------------------------------------------------------*/
251
262bolos_err_t provide_ledger_account_contact(uint8_t *buffer_in, size_t buffer_in_length)
263{
264 const buffer_t payload = {.ptr = buffer_in, .size = buffer_in_length};
265 s_provide_ledger_account_ctx ctx = {0};
266
267 // Init the structure
268 ctx.ledger_account = &g_ab_payload.ledger_account;
269 memset(&g_ab_payload.ledger_account, 0, sizeof(g_ab_payload.ledger_account));
270
271 // Parse using SDK TLV parser
272 if (!provide_ledger_account_tlv_parser(&payload, &ctx, &ctx.received_tags)) {
273 PRINTF("[Provide Ledger Account] TLV parsing failed\n");
274 return SWO_INCORRECT_DATA;
275 }
276 if (!verify_fields(&ctx)) {
277 return SWO_INCORRECT_DATA;
278 }
279 print_payload(&ctx);
280
281 // Verify HMAC Proof of Registration: HMAC(bip32_path, account_name, family, chain_id)
282 if (!address_book_verify_hmac_proof_ledger_account(
283 &g_ab_payload.ledger_account.bip32_path,
284 g_ab_payload.ledger_account.account_name,
285 g_ab_payload.ledger_account.blockchain_family,
286 g_ab_payload.ledger_account.chain_id,
287 ctx.hmac_proof)) {
288 PRINTF("[Provide Ledger Account] HMAC proof verification failed\n");
289 return SWO_SECURITY_CONDITION_NOT_SATISFIED;
290 }
291
292 // Pass verified contact to the coin app for storage
293 if (!handle_provide_ledger_account(&g_ab_payload.ledger_account)) {
294 PRINTF("[Provide Ledger Account] Rejected by coin application\n");
295 return SWO_WRONG_PARAMETER_VALUE;
296 }
297
298 return SWO_SUCCESS;
299}
300
301#endif // HAVE_ADDRESS_BOOK && HAVE_ADDRESS_BOOK_LEDGER_ACCOUNT
@ FAMILY_ETHEREUM
#define FAMILY_AS_STR(x)
bool bip32_path_format_simple(path_bip32_t *bip32, char *out, size_t out_len)
Format a BIP32 path as a string.
Definition bip32.c:92
bolos_err_t provide_ledger_account_contact(uint8_t *buffer_in, size_t buffer_in_length)
#define TYPE_PROVIDE_LEDGER_ACCOUNT_CONTACT
uint8_t * ptr
Definition buffer.h:22
Data extracted from a Register Ledger Account TLV payload.