From 5d1d16c2dee970a24f60b7a419f2d3b34b6038d9 Mon Sep 17 00:00:00 2001 From: tdejoigny-ledger Date: Fri, 4 Aug 2023 13:43:03 +0200 Subject: [PATCH] Update the ragger app client to support "set external plugin" APDU and take into account PR review remarks --- .../src/ledger_app_clients/ethereum/client.py | 29 ++++++----- .../ethereum/command_builder.py | 17 +++++++ src_plugins_sdk/plugin_main.c | 48 ++++++++++++------- src_plugins_sdk/plugin_main.h | 2 +- 4 files changed, 66 insertions(+), 30 deletions(-) diff --git a/client/src/ledger_app_clients/ethereum/client.py b/client/src/ledger_app_clients/ethereum/client.py index f8b98e2..150cfb9 100644 --- a/client/src/ledger_app_clients/ethereum/client.py +++ b/client/src/ledger_app_clients/ethereum/client.py @@ -2,7 +2,7 @@ import rlp from enum import IntEnum from ragger.backend import BackendInterface from ragger.utils import RAPDU -from typing import List, Optional, Union +from typing import List, Optional from .command_builder import CommandBuilder from .eip712 import EIP712FieldType @@ -30,8 +30,7 @@ class StatusWord(IntEnum): CONDITION_NOT_SATISFIED = 0x6985 REF_DATA_NOT_FOUND = 0x6a88 - -class DOMAIN_NAME_TAG(IntEnum): +class DomainNameTag(IntEnum): STRUCTURE_TYPE = 0x01 STRUCTURE_VERSION = 0x02 CHALLENGE = 0x12 @@ -52,7 +51,7 @@ class EthAppClient: return self._client.exchange_async_raw(payload) def response(self) -> Optional[RAPDU]: - return self._client._last_async_response + return self._client.last_async_response def eip712_send_struct_def_struct_name(self, name: str): return self._send(self._cmd_builder.eip712_send_struct_def_struct_name(name)) @@ -190,15 +189,15 @@ class EthAppClient: chain_id)) def provide_domain_name(self, challenge: int, name: str, addr: bytes): - payload = format_tlv(DOMAIN_NAME_TAG.STRUCTURE_TYPE, 3) # TrustedDomainName - payload += format_tlv(DOMAIN_NAME_TAG.STRUCTURE_VERSION, 1) - payload += format_tlv(DOMAIN_NAME_TAG.SIGNER_KEY_ID, 0) # test key - payload += format_tlv(DOMAIN_NAME_TAG.SIGNER_ALGO, 1) # secp256k1 - payload += format_tlv(DOMAIN_NAME_TAG.CHALLENGE, challenge) - payload += format_tlv(DOMAIN_NAME_TAG.COIN_TYPE, 0x3c) # ETH in slip-44 - payload += format_tlv(DOMAIN_NAME_TAG.DOMAIN_NAME, name) - payload += format_tlv(DOMAIN_NAME_TAG.ADDRESS, addr) - payload += format_tlv(DOMAIN_NAME_TAG.SIGNATURE, + payload = format_tlv(DomainNameTag.STRUCTURE_TYPE, 3) # TrustedDomainName + payload += format_tlv(DomainNameTag.STRUCTURE_VERSION, 1) + payload += format_tlv(DomainNameTag.SIGNER_KEY_ID, 0) # test key + payload += format_tlv(DomainNameTag.SIGNER_ALGO, 1) # secp256k1 + payload += format_tlv(DomainNameTag.CHALLENGE, challenge) + payload += format_tlv(DomainNameTag.COIN_TYPE, 0x3c) # ETH in slip-44 + payload += format_tlv(DomainNameTag.DOMAIN_NAME, name) + payload += format_tlv(DomainNameTag.ADDRESS, addr) + payload += format_tlv(DomainNameTag.SIGNATURE, sign_data(Key.DOMAIN_NAME, payload)) chunks = self._cmd_builder.provide_domain_name(payload) @@ -271,3 +270,7 @@ class EthAppClient: key_id, algo_id, sig)) + + + def external_plugin_setup(self, plugin_name: str, contract_address: bytes, method_selelector: bytes, sig: bytes): + return self._send(self._cmd_builder.external_plugin_setup(plugin_name, contract_address, method_selelector, sig)) diff --git a/client/src/ledger_app_clients/ethereum/command_builder.py b/client/src/ledger_app_clients/ethereum/command_builder.py index e63f061..caed1d9 100644 --- a/client/src/ledger_app_clients/ethereum/command_builder.py +++ b/client/src/ledger_app_clients/ethereum/command_builder.py @@ -1,3 +1,6 @@ +# documentation about APDU format is available here: +# https://github.com/LedgerHQ/app-ethereum/blob/develop/doc/ethapp.adoc + import struct from enum import IntEnum from typing import Optional @@ -18,6 +21,7 @@ class InsType(IntEnum): EIP712_SIGN = 0x0c GET_CHALLENGE = 0x20 PROVIDE_DOMAIN_NAME = 0x22 + EXTERNAL_PLUGIN_SETUP = 0x12 class P1Type(IntEnum): @@ -178,6 +182,19 @@ class CommandBuilder: P2Type.FILTERING_FIELD_NAME, self._eip712_filtering_send_name(name, sig)) + def external_plugin_setup(self, plugin_name: str, contract_address: bytes, method_selelector: bytes, sig: bytes) -> bytes: + data = bytearray() + data.append(len(plugin_name)) + data += self._string_to_bytes(plugin_name) + data += contract_address + data += method_selelector + data += sig + + return self._serialize(InsType.EXTERNAL_PLUGIN_SETUP, + P1Type.COMPLETE_SEND, + 0x00, + data) + def sign(self, bip32_path: str, rlp_data: bytes) -> list[bytes]: apdus = list() payload = pack_derivation_path(bip32_path) diff --git a/src_plugins_sdk/plugin_main.c b/src_plugins_sdk/plugin_main.c index 06bd3a4..881ad70 100644 --- a/src_plugins_sdk/plugin_main.c +++ b/src_plugins_sdk/plugin_main.c @@ -49,20 +49,36 @@ __attribute__((section(".boot"))) int main(int arg0) { check_api_level(CX_COMPAT_APILEVEL); - // Check if plugin is called from the dashboard. - if (!arg0) { - // Called from dashboard, launch Ethereum app - call_app_ethereum(); - return 0; - } else { - // Not called from dashboard: called from the ethereum app! - // launch plugin main - plugin_main(arg0); + BEGIN_TRY { + TRY { + // Check if plugin is called from the dashboard. + if (!arg0) { + // Called from dashboard, launch Ethereum app + call_app_ethereum(); + + // Will not get reached. + __builtin_unreachable(); + + os_sched_exit(-1); + + } else { + // Not called from dashboard: called from the ethereum app! + // launch plugin main + plugin_main(arg0); + } + + // Call `os_lib_end`, go back to the ethereum app. + os_lib_end(); + + // Will not get reached. + __builtin_unreachable(); + } + CATCH_OTHER(e) { + PRINTF("Exiting following exception: %d\n", e); + } + FINALLY { + os_lib_end(); + } } - - // Call `os_lib_end`, go back to the ethereum app. - os_lib_end(); - - // Will not get reached. - return 0; -} \ No newline at end of file + END_TRY; +} diff --git a/src_plugins_sdk/plugin_main.h b/src_plugins_sdk/plugin_main.h index 5801aa9..a120c5a 100644 --- a/src_plugins_sdk/plugin_main.h +++ b/src_plugins_sdk/plugin_main.h @@ -16,4 +16,4 @@ *****************************************************************************/ // applicative main for plugins -void plugin_main(int arg0); \ No newline at end of file +void plugin_main(int arg0);