Update the ragger app client to support "set external plugin" APDU and take into account PR review remarks

This commit is contained in:
tdejoigny-ledger
2023-08-04 13:43:03 +02:00
committed by Alexandre Paillier
parent eeb52344df
commit 5d1d16c2de
4 changed files with 66 additions and 30 deletions

View File

@@ -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))

View File

@@ -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)

View File

@@ -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;
}
END_TRY;
}

View File

@@ -16,4 +16,4 @@
*****************************************************************************/
// applicative main for plugins
void plugin_main(int arg0);
void plugin_main(int arg0);