46#include "os_helpers.h"
50#include "status_words.h"
52#ifdef HAVE_ADDRESS_BOOK_LEDGER_ACCOUNT
56#if defined(HAVE_ADDRESS_BOOK)
59#define P1_REGISTER_IDENTITY 0x01
60#define P1_EDIT_CONTACT_NAME 0x02
61#define P1_EDIT_IDENTIFIER 0x03
62#define P1_EDIT_SCOPE 0x04
63#define P1_PROVIDE_CONTACT 0x20
65#ifdef HAVE_ADDRESS_BOOK_LEDGER_ACCOUNT
66#define P1_REGISTER_LEDGER_ACCOUNT 0x11
67#define P1_EDIT_LEDGER_ACCOUNT 0x12
68#define P1_PROVIDE_LEDGER_ACCOUNT_CONTACT 0x21
72#define P2_FIRST_CHUNK 0x00
74#define P2_NEXT_CHUNK 0x80
86#ifdef CUSTOM_IO_APDU_BUFFER_SIZE
87#define ADDRESS_BOOK_MAX_CHUNKED_PAYLOAD (CUSTOM_IO_APDU_BUFFER_SIZE - 3 - 5)
89#define ADDRESS_BOOK_MAX_CHUNKED_PAYLOAD (OS_IO_SEPH_BUFFER_SIZE - 3 - 5)
100static uint8_t s_chunk_buf[ADDRESS_BOOK_MAX_CHUNKED_PAYLOAD] = {0};
101static uint16_t s_chunk_total = 0;
102static uint16_t s_chunk_received = 0;
120static reassembly_status_t reassemble_chunks(uint8_t *data,
126 if (p2 == P2_FIRST_CHUNK) {
128 PRINTF(
"[Address Book] First chunk too short (no length header)\n");
129 return REASSEMBLY_ERROR;
131 s_chunk_total = U2BE(data, 0);
132 s_chunk_received = 0;
135 if (s_chunk_total == 0 || s_chunk_total >
sizeof(s_chunk_buf)) {
136 PRINTF(
"[Address Book] Invalid total length: %u\n", s_chunk_total);
138 return REASSEMBLY_ERROR;
142 if (s_chunk_total == 0) {
143 PRINTF(
"[Address Book] Unexpected continuation chunk\n");
144 return REASSEMBLY_ERROR;
148 if ((s_chunk_received > s_chunk_total) || (len > (s_chunk_total - s_chunk_received))) {
150 "[Address Book] Chunk overflow: %u + %zu > %u\n", s_chunk_received, len, s_chunk_total);
152 return REASSEMBLY_ERROR;
154 memmove(s_chunk_buf + s_chunk_received, data, len);
155 s_chunk_received += (uint16_t) len;
157 if (s_chunk_received < s_chunk_total) {
158 return REASSEMBLY_PENDING;
161 *out_buf = s_chunk_buf;
162 *out_len = s_chunk_received;
164 return REASSEMBLY_COMPLETE;
170 bolos_err_t err = SWO_CONDITIONS_NOT_SATISFIED;
171 uint8_t *payload = NULL;
172 size_t payload_len = 0;
175 case P1_REGISTER_IDENTITY:
176 err = register_identity(buffer, buffer_len);
179 case P1_EDIT_CONTACT_NAME:
180 err = edit_contact_name(buffer, buffer_len);
183 case P1_EDIT_IDENTIFIER:
184 switch (reassemble_chunks(buffer, buffer_len, p2, &payload, &payload_len)) {
185 case REASSEMBLY_ERROR:
186 err = SWO_INCORRECT_DATA;
188 case REASSEMBLY_PENDING:
191 case REASSEMBLY_COMPLETE:
192 err = edit_identifier(payload, payload_len);
198 switch (reassemble_chunks(buffer, buffer_len, p2, &payload, &payload_len)) {
199 case REASSEMBLY_ERROR:
200 err = SWO_INCORRECT_DATA;
202 case REASSEMBLY_PENDING:
205 case REASSEMBLY_COMPLETE:
206 err = edit_scope(payload, payload_len);
211#ifdef HAVE_ADDRESS_BOOK_LEDGER_ACCOUNT
212 case P1_REGISTER_LEDGER_ACCOUNT:
216 case P1_EDIT_LEDGER_ACCOUNT:
221 case P1_PROVIDE_CONTACT:
222 switch (reassemble_chunks(buffer, buffer_len, p2, &payload, &payload_len)) {
223 case REASSEMBLY_ERROR:
224 err = SWO_INCORRECT_DATA;
226 case REASSEMBLY_PENDING:
229 case REASSEMBLY_COMPLETE:
230 err = provide_contact(payload, payload_len);
235#ifdef HAVE_ADDRESS_BOOK_LEDGER_ACCOUNT
236 case P1_PROVIDE_LEDGER_ACCOUNT_CONTACT:
237 switch (reassemble_chunks(buffer, buffer_len, p2, &payload, &payload_len)) {
238 case REASSEMBLY_ERROR:
239 err = SWO_INCORRECT_DATA;
241 case REASSEMBLY_PENDING:
244 case REASSEMBLY_COMPLETE:
bolos_err_t addr_book_handle_apdu(uint8_t *buffer, size_t buffer_len, uint8_t p1, uint8_t p2)
Register / Edit Contact Name / Edit Scope / Edit Identifier.
bolos_err_t provide_ledger_account_contact(uint8_t *buffer_in, size_t buffer_in_length)
bolos_err_t register_ledger_account(uint8_t *buffer_in, size_t buffer_in_length)
bolos_err_t edit_ledger_account(uint8_t *buffer_in, size_t buffer_in_length)