Skip to content

Commit 3a1604d

Browse files
Merge pull request #447 from LedgerHQ/fix/apa/eip712
Fix EIP-712 improper handling of empty arrays
2 parents f0df04a + cace9d6 commit 3a1604d

File tree

5 files changed

+78
-12
lines changed

5 files changed

+78
-12
lines changed

src_features/signMessageEIP712/commands_712.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
#include "schema_hash.h"
1414
#include "filtering.h"
1515
#include "common_712.h"
16-
#include "ethUtils.h" // allzeroes
16+
#include "ethUtils.h" // allzeroes
17+
#include "common_ui.h" // ui_idle
1718

1819
/**
1920
* Send the response to the previous APDU command
@@ -38,6 +39,7 @@ void handle_eip712_return_code(bool success) {
3839

3940
if (!success) {
4041
eip712_context_deinit();
42+
ui_idle();
4143
}
4244
}
4345

src_features/signMessageEIP712/path.c

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -143,14 +143,18 @@ static cx_sha3_t *get_last_hash_ctx(void) {
143143
* Finalize the last hashing context
144144
*
145145
* @param[out] hash pointer to buffer where the hash will be stored
146+
* @return whether there was anything hashed at this depth
146147
*/
147-
static void finalize_hash_depth(uint8_t *hash) {
148+
static bool finalize_hash_depth(uint8_t *hash) {
148149
const cx_sha3_t *hash_ctx;
150+
size_t hashed_bytes;
149151

150152
hash_ctx = get_last_hash_ctx();
153+
hashed_bytes = hash_ctx->blen;
151154
// finalize hash
152155
cx_hash((cx_hash_t *) hash_ctx, CX_LAST, NULL, 0, hash, KECCAK256_HASH_BYTESIZE);
153156
mem_dealloc(sizeof(*hash_ctx)); // remove hash context
157+
return hashed_bytes > 0;
154158
}
155159

156160
/**
@@ -192,6 +196,7 @@ static bool push_new_hash_depth(bool init) {
192196
*/
193197
static bool path_depth_list_pop(void) {
194198
uint8_t hash[KECCAK256_HASH_BYTESIZE];
199+
bool to_feed;
195200

196201
if (path_struct == NULL) {
197202
return false;
@@ -201,9 +206,11 @@ static bool path_depth_list_pop(void) {
201206
}
202207
path_struct->depth_count -= 1;
203208

204-
finalize_hash_depth(hash);
209+
to_feed = finalize_hash_depth(hash);
205210
if (path_struct->depth_count > 0) {
206-
feed_last_hash_depth(hash);
211+
if (to_feed) {
212+
feed_last_hash_depth(hash);
213+
}
207214
} else {
208215
switch (path_struct->root_type) {
209216
case ROOT_DOMAIN:
@@ -261,7 +268,7 @@ static bool array_depth_list_pop(void) {
261268
return false;
262269
}
263270

264-
finalize_hash_depth(hash);
271+
finalize_hash_depth(hash); // return value not checked on purpose
265272
feed_last_hash_depth(hash);
266273

267274
path_struct->array_depth_count -= 1;
@@ -307,7 +314,10 @@ static bool path_update(void) {
307314
}
308315
feed_last_hash_depth(hash);
309316

310-
ui_712_queue_struct_to_review();
317+
// TODO: Find a better way to show inner structs in verbose mode when it might be
318+
// an empty array of structs in which case we don't want to show it but the
319+
// size is only known later
320+
// ui_712_queue_struct_to_review();
311321
path_depth_list_push();
312322
}
313323
return true;
@@ -421,6 +431,8 @@ bool path_new_array_depth(const uint8_t *const data, uint8_t length) {
421431
uint8_t total_count = 0;
422432
uint8_t pidx;
423433
bool is_custom;
434+
uint8_t array_size;
435+
uint8_t array_depth_count_bak;
424436

425437
if (path_struct == NULL) {
426438
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
@@ -430,6 +442,8 @@ bool path_new_array_depth(const uint8_t *const data, uint8_t length) {
430442
return false;
431443
}
432444

445+
array_size = *data;
446+
array_depth_count_bak = path_struct->array_depth_count;
433447
for (pidx = 0; pidx < path_struct->depth_count; ++pidx) {
434448
if ((field_ptr = get_nth_field(NULL, pidx + 1)) == NULL) {
435449
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
@@ -442,7 +456,7 @@ bool path_new_array_depth(const uint8_t *const data, uint8_t length) {
442456
}
443457
total_count += depth_count;
444458
if (total_count > path_struct->array_depth_count) {
445-
if (!check_and_add_array_depth(depth, total_count, pidx, *data)) {
459+
if (!check_and_add_array_depth(depth, total_count, pidx, array_size)) {
446460
return false;
447461
}
448462
break;
@@ -463,9 +477,18 @@ bool path_new_array_depth(const uint8_t *const data, uint8_t length) {
463477
cx_sha3_t *hash_ctx = get_last_hash_ctx();
464478
cx_sha3_t *old_ctx = hash_ctx - 1;
465479

466-
memcpy(hash_ctx, old_ctx, sizeof(*old_ctx));
480+
if (array_size > 0) {
481+
memcpy(hash_ctx, old_ctx, sizeof(*old_ctx));
482+
} else {
483+
cx_keccak_init(hash_ctx, 256);
484+
}
467485
cx_keccak_init(old_ctx, 256); // init hash
468486
}
487+
if (array_size == 0) {
488+
do {
489+
path_advance();
490+
} while (path_struct->array_depth_count != array_depth_count_bak);
491+
}
469492

470493
return true;
471494
}
@@ -515,7 +538,7 @@ static bool path_advance_in_array(void) {
515538

516539
if ((path_struct->array_depth_count > 0) &&
517540
(arr_depth->path_index == (path_struct->depth_count - 1))) {
518-
arr_depth->size -= 1;
541+
if (arr_depth->size > 0) arr_depth->size -= 1;
519542
if (arr_depth->size == 0) {
520543
array_depth_list_pop();
521544
end_reached = true;

src_nbgl/ui_message_signing.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include "ui_nbgl.h"
22
#include "ui_signing.h"
3-
#include "common_712.h"
3+
#include "ui_logic.h"
44
#include "ui_message_signing.h"
55
#include "glyphs.h"
66

@@ -42,9 +42,9 @@ void ui_message_start(const char *title,
4242
}
4343

4444
void ui_message_712_approved(void) {
45-
ui_712_approve_cb();
45+
ui_712_approve();
4646
}
4747

4848
void ui_message_712_rejected(void) {
49-
ui_712_reject_cb();
49+
ui_712_reject();
5050
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"domain": {
3+
"chainId": 5,
4+
"name": "Empty Arrays",
5+
"verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
6+
"version": "1"
7+
},
8+
"message": {
9+
"list1": [],
10+
"list2": [],
11+
"list3": [
12+
[
13+
"1",
14+
"2"
15+
],
16+
[],
17+
[
18+
"3",
19+
"4"
20+
]
21+
]
22+
},
23+
"primaryType": "Struct",
24+
"types": {
25+
"EIP712Domain": [
26+
{ "name": "name", "type": "string" },
27+
{ "name": "version", "type": "string" },
28+
{ "name": "chainId", "type": "uint256" },
29+
{ "name": "verifyingContract", "type": "address" }
30+
],
31+
"Struct": [
32+
{ "name": "list1", "type": "EIP712Domain[]" },
33+
{ "name": "list2", "type": "uint8[]" },
34+
{ "name": "list3", "type": "string[][]" }
35+
]
36+
}
37+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[signature]
2+
v = 1b
3+
r = 5d0635a868602e29366da6328f8fadf2d6a9b4e69ee7a65928e85ca56fb1b515
4+
s = 257364d6faaf5687edf90c3984f4240b0ce7b2dee55aa1f8f39c32d0d4d8c93d

0 commit comments

Comments
 (0)