Skip to content

Commit e199e4c

Browse files
Merge pull request #744 from LedgerHQ/feat/apa/network_info_improvements
Improve network info support
2 parents bf517f1 + 648c684 commit e199e4c

File tree

5 files changed

+68
-61
lines changed

5 files changed

+68
-61
lines changed

client/src/ledger_app_clients/ethereum/command_builder.py

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import struct
55
from enum import IntEnum
6-
from typing import List, Optional
6+
from typing import Optional
77
from ragger.bip import pack_derivation_path
88

99
from .eip712 import EIP712FieldType
@@ -414,30 +414,6 @@ def provide_erc20_token_information(self,
414414
0x00,
415415
payload)
416416

417-
def provide_network_information(self,
418-
tlv_payload: bytes,
419-
icon: Optional[bytes] = None) -> list[bytes]:
420-
chunks: List[bytes] = []
421-
422-
# Check if the TLV payload is larger than 0xff
423-
assert len(tlv_payload) < 0xff, "Payload too large"
424-
# Serialize the payload
425-
chunks.append(self._serialize(InsType.PROVIDE_NETWORK_INFORMATION,
426-
0x00,
427-
P2Type.NETWORK_CONFIG,
428-
tlv_payload))
429-
430-
if icon:
431-
p1 = P1Type.FIRST_CHUNK
432-
while len(icon) > 0:
433-
chunks.append(self._serialize(InsType.PROVIDE_NETWORK_INFORMATION,
434-
p1,
435-
P2Type.NETWORK_ICON,
436-
icon[:0xff]))
437-
icon = icon[0xff:]
438-
p1 = P1Type.FOLLOWING_CHUNK
439-
return chunks
440-
441417
def common_tlv_serialize(self,
442418
ins: InsType,
443419
tlv_payload: bytes,
@@ -461,6 +437,24 @@ def common_tlv_serialize(self,
461437
p2 = p2l[-1]
462438
return chunks
463439

440+
def provide_network_information(self,
441+
tlv_payload: bytes,
442+
icon: Optional[bytes] = None) -> list[bytes]:
443+
chunks = self.common_tlv_serialize(InsType.PROVIDE_NETWORK_INFORMATION,
444+
tlv_payload,
445+
p2l=[P2Type.NETWORK_CONFIG])
446+
447+
if icon:
448+
p1 = P1Type.FIRST_CHUNK
449+
while len(icon) > 0:
450+
chunks.append(self._serialize(InsType.PROVIDE_NETWORK_INFORMATION,
451+
p1,
452+
P2Type.NETWORK_ICON,
453+
icon[:0xff]))
454+
icon = icon[0xff:]
455+
p1 = P1Type.FOLLOWING_CHUNK
456+
return chunks
457+
464458
def provide_enum_value(self, tlv_payload: bytes) -> list[bytes]:
465459
return self.common_tlv_serialize(InsType.PROVIDE_ENUM_VALUE, tlv_payload)
466460

doc/ethapp.adoc

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,25 +1230,38 @@ _Command_
12301230
12311231
[width="80%"]
12321232
|==============================================================
1233-
| *CLA* | *INS* | *P1* | *P2* | *LC* | *Le*
1234-
.3+| E0 .3+| 30 | 00 | 00 : Network configuration | variable | variable
1235-
| 01 : First chunk
1233+
| *CLA* | *INS* | *P1* | *P2* | *LC*
1234+
.2+| E0 .2+| 30 | 01 : first chunk
12361235
1237-
00: Next chunks | 01 : Network Icon | variable | variable
1238-
| 00 | 02 : Get Info | |
1236+
00 : following chunk
1237+
| 00 : Network configuration
1238+
1239+
01 : Network icon | variable
1240+
| 00 | 02 : Get info | 0
12391241
|==============================================================
12401242
12411243
_Input data_
12421244
1243-
##### If P1 == Network configuration
1245+
##### If P2 == Network configuration
1246+
1247+
###### If P1 == first chunk
12441248
12451249
[width="80%"]
12461250
|==========================================
12471251
| *Description* | *Length (byte)*
1248-
| TLV payload data | variable
1252+
| Payload length | 2
1253+
| TLV payload | variable
1254+
|==========================================
1255+
1256+
###### If P1 == following chunk
1257+
1258+
[width="80%"]
1259+
|==========================================
1260+
| *Description* | *Length (byte)*
1261+
| TLV payload | variable
12491262
|==========================================
12501263
1251-
##### If P1 == Network Icon
1264+
##### If P2 == Network Icon
12521265
12531266
[width="80%"]
12541267
|==========================================
@@ -1268,7 +1281,7 @@ _Input data_
12681281
12691282
_Output data_
12701283
1271-
##### If P1 == Get Info
1284+
##### If P2 == Get Info
12721285
12731286
[width="80%"]
12741287
|==========================================

src/network.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,9 @@ static const network_info_t *get_network_from_chain_id(const uint64_t *chain_id)
126126
// Look if the network is available
127127
for (size_t i = 0; i < MAX_DYNAMIC_NETWORKS; i++) {
128128
if (DYNAMIC_NETWORK_INFO[i].chain_id == *chain_id) {
129-
PRINTF("[NETWORK] - Found dynamic %s\n", DYNAMIC_NETWORK_INFO[i].name);
129+
PRINTF("[NETWORK] - Found dynamic \"%s\" in slot %u\n",
130+
DYNAMIC_NETWORK_INFO[i].name,
131+
i);
130132
return (const network_info_t *) &DYNAMIC_NETWORK_INFO[i];
131133
}
132134
}

src_features/provide_network_info/cmd_network_info.c

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include "apdu_constants.h"
66
#include "network_info.h"
77
#include "write.h"
8+
#include "tlv_apdu.h"
9+
#include "mem.h"
810

911
#define P2_NETWORK_CONFIG 0x00
1012
#define P2_NETWORK_ICON 0x01
@@ -210,7 +212,7 @@ static void print_network_info(void) {
210212
u64_to_string(DYNAMIC_NETWORK_INFO[g_current_network_slot].chain_id,
211213
chain_str,
212214
sizeof(chain_str));
213-
PRINTF("[NETWORK] - Registered in slot %d: %s (%s), for chain_id %s\n",
215+
PRINTF("[NETWORK] - Registered in slot %u: \"%s\" (%s), for chain_id %s\n",
214216
g_current_network_slot,
215217
DYNAMIC_NETWORK_INFO[g_current_network_slot].name,
216218
DYNAMIC_NETWORK_INFO[g_current_network_slot].ticker,
@@ -243,18 +245,15 @@ static uint16_t handle_get_config(void) {
243245
return tx;
244246
}
245247

246-
static bool handle_tlv_payload(const uint8_t *payload, uint16_t size) {
248+
static bool handle_tlv_payload(const uint8_t *payload, uint16_t size, bool to_free) {
249+
bool parsing_ret;
247250
s_network_info_ctx ctx = {0};
248251

249-
// Set the current slot here, because the corresponding icon will be received
250-
// separately, after the network configuration, and should keep the same slot
251-
g_current_network_slot = (g_current_network_slot + 1) % MAX_DYNAMIC_NETWORKS;
252-
253252
// Initialize the hash context
254253
cx_sha256_init(&ctx.hash_ctx);
255-
if (!tlv_parse(payload, size, (f_tlv_data_handler) &handle_network_info_struct, &ctx) ||
256-
!verify_network_info_struct(&ctx)) {
257-
explicit_bzero(&DYNAMIC_NETWORK_INFO[g_current_network_slot], sizeof(network_info_t));
254+
parsing_ret = tlv_parse(payload, size, (f_tlv_data_handler) &handle_network_info_struct, &ctx);
255+
if (to_free) mem_dealloc(sizeof(size));
256+
if (!parsing_ret || !verify_network_info_struct(&ctx)) {
258257
return false;
259258
}
260259
print_network_info();
@@ -280,16 +279,10 @@ uint16_t handle_network_info(uint8_t p1,
280279

281280
switch (p2) {
282281
case P2_NETWORK_CONFIG:
283-
if (p1 != 0x00) {
284-
PRINTF("Error: Unexpected P1 (%u)!\n", p1);
285-
sw = APDU_RESPONSE_INVALID_P1_P2;
286-
break;
287-
}
288-
if (handle_tlv_payload(data, length)) {
289-
sw = APDU_RESPONSE_OK;
290-
} else {
291-
sw = APDU_RESPONSE_INVALID_DATA;
282+
if (!tlv_from_apdu(p1 == P1_FIRST_CHUNK, length, data, &handle_tlv_payload)) {
283+
return APDU_RESPONSE_INVALID_DATA;
292284
}
285+
sw = APDU_RESPONSE_OK;
293286
break;
294287

295288
case P2_NETWORK_ICON:

src_features/provide_network_info/network_info.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ static bool handle_chain_id(const s_tlv_data *data, s_network_info_ctx *context)
9090
uint64_t chain_id;
9191
uint8_t buf[sizeof(chain_id)];
9292
uint64_t max_range;
93-
uint8_t i;
9493

9594
(void) context;
9695
if (data->length > sizeof(buf)) {
@@ -106,13 +105,6 @@ static bool handle_chain_id(const s_tlv_data *data, s_network_info_ctx *context)
106105
PRINTF("Unsupported chain ID: %u\n", chain_id);
107106
return false;
108107
}
109-
// Check if the chain_id is already registered
110-
for (i = 0; i < MAX_DYNAMIC_NETWORKS; i++) {
111-
if (DYNAMIC_NETWORK_INFO[i].chain_id == chain_id) {
112-
PRINTF("CHAIN_ID already exist!\n");
113-
return false;
114-
}
115-
}
116108
context->network.chain_id = chain_id;
117109
return true;
118110
}
@@ -281,6 +273,19 @@ bool verify_network_info_struct(const s_network_info_ctx *context) {
281273
context->signature_length) != CX_OK) {
282274
return false;
283275
}
276+
277+
// Check if the chain ID is already registered, if so delete it silently to prevent duplicates
278+
for (int i = 0; i < MAX_DYNAMIC_NETWORKS; ++i) {
279+
if (DYNAMIC_NETWORK_INFO[i].chain_id == context->network.chain_id) {
280+
explicit_bzero(&DYNAMIC_NETWORK_INFO[i], sizeof(DYNAMIC_NETWORK_INFO[i]));
281+
break;
282+
}
283+
}
284+
285+
// Set the current slot here, because the corresponding icon will be received
286+
// separately, after the network configuration, and should keep the same slot
287+
g_current_network_slot = (g_current_network_slot + 1) % MAX_DYNAMIC_NETWORKS;
288+
284289
memcpy(&DYNAMIC_NETWORK_INFO[g_current_network_slot],
285290
&context->network,
286291
sizeof(network_info_t));

0 commit comments

Comments
 (0)