Update the ragger app client to support "set external plugin" APDU and take into account PR review remarks
This commit is contained in:
committed by
Alexandre Paillier
parent
eeb52344df
commit
5d1d16c2de
@@ -2,7 +2,7 @@ import rlp
|
|||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
from ragger.backend import BackendInterface
|
from ragger.backend import BackendInterface
|
||||||
from ragger.utils import RAPDU
|
from ragger.utils import RAPDU
|
||||||
from typing import List, Optional, Union
|
from typing import List, Optional
|
||||||
|
|
||||||
from .command_builder import CommandBuilder
|
from .command_builder import CommandBuilder
|
||||||
from .eip712 import EIP712FieldType
|
from .eip712 import EIP712FieldType
|
||||||
@@ -30,8 +30,7 @@ class StatusWord(IntEnum):
|
|||||||
CONDITION_NOT_SATISFIED = 0x6985
|
CONDITION_NOT_SATISFIED = 0x6985
|
||||||
REF_DATA_NOT_FOUND = 0x6a88
|
REF_DATA_NOT_FOUND = 0x6a88
|
||||||
|
|
||||||
|
class DomainNameTag(IntEnum):
|
||||||
class DOMAIN_NAME_TAG(IntEnum):
|
|
||||||
STRUCTURE_TYPE = 0x01
|
STRUCTURE_TYPE = 0x01
|
||||||
STRUCTURE_VERSION = 0x02
|
STRUCTURE_VERSION = 0x02
|
||||||
CHALLENGE = 0x12
|
CHALLENGE = 0x12
|
||||||
@@ -52,7 +51,7 @@ class EthAppClient:
|
|||||||
return self._client.exchange_async_raw(payload)
|
return self._client.exchange_async_raw(payload)
|
||||||
|
|
||||||
def response(self) -> Optional[RAPDU]:
|
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):
|
def eip712_send_struct_def_struct_name(self, name: str):
|
||||||
return self._send(self._cmd_builder.eip712_send_struct_def_struct_name(name))
|
return self._send(self._cmd_builder.eip712_send_struct_def_struct_name(name))
|
||||||
@@ -190,15 +189,15 @@ class EthAppClient:
|
|||||||
chain_id))
|
chain_id))
|
||||||
|
|
||||||
def provide_domain_name(self, challenge: int, name: str, addr: bytes):
|
def provide_domain_name(self, challenge: int, name: str, addr: bytes):
|
||||||
payload = format_tlv(DOMAIN_NAME_TAG.STRUCTURE_TYPE, 3) # TrustedDomainName
|
payload = format_tlv(DomainNameTag.STRUCTURE_TYPE, 3) # TrustedDomainName
|
||||||
payload += format_tlv(DOMAIN_NAME_TAG.STRUCTURE_VERSION, 1)
|
payload += format_tlv(DomainNameTag.STRUCTURE_VERSION, 1)
|
||||||
payload += format_tlv(DOMAIN_NAME_TAG.SIGNER_KEY_ID, 0) # test key
|
payload += format_tlv(DomainNameTag.SIGNER_KEY_ID, 0) # test key
|
||||||
payload += format_tlv(DOMAIN_NAME_TAG.SIGNER_ALGO, 1) # secp256k1
|
payload += format_tlv(DomainNameTag.SIGNER_ALGO, 1) # secp256k1
|
||||||
payload += format_tlv(DOMAIN_NAME_TAG.CHALLENGE, challenge)
|
payload += format_tlv(DomainNameTag.CHALLENGE, challenge)
|
||||||
payload += format_tlv(DOMAIN_NAME_TAG.COIN_TYPE, 0x3c) # ETH in slip-44
|
payload += format_tlv(DomainNameTag.COIN_TYPE, 0x3c) # ETH in slip-44
|
||||||
payload += format_tlv(DOMAIN_NAME_TAG.DOMAIN_NAME, name)
|
payload += format_tlv(DomainNameTag.DOMAIN_NAME, name)
|
||||||
payload += format_tlv(DOMAIN_NAME_TAG.ADDRESS, addr)
|
payload += format_tlv(DomainNameTag.ADDRESS, addr)
|
||||||
payload += format_tlv(DOMAIN_NAME_TAG.SIGNATURE,
|
payload += format_tlv(DomainNameTag.SIGNATURE,
|
||||||
sign_data(Key.DOMAIN_NAME, payload))
|
sign_data(Key.DOMAIN_NAME, payload))
|
||||||
|
|
||||||
chunks = self._cmd_builder.provide_domain_name(payload)
|
chunks = self._cmd_builder.provide_domain_name(payload)
|
||||||
@@ -271,3 +270,7 @@ class EthAppClient:
|
|||||||
key_id,
|
key_id,
|
||||||
algo_id,
|
algo_id,
|
||||||
sig))
|
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))
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# documentation about APDU format is available here:
|
||||||
|
# https://github.com/LedgerHQ/app-ethereum/blob/develop/doc/ethapp.adoc
|
||||||
|
|
||||||
import struct
|
import struct
|
||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
@@ -18,6 +21,7 @@ class InsType(IntEnum):
|
|||||||
EIP712_SIGN = 0x0c
|
EIP712_SIGN = 0x0c
|
||||||
GET_CHALLENGE = 0x20
|
GET_CHALLENGE = 0x20
|
||||||
PROVIDE_DOMAIN_NAME = 0x22
|
PROVIDE_DOMAIN_NAME = 0x22
|
||||||
|
EXTERNAL_PLUGIN_SETUP = 0x12
|
||||||
|
|
||||||
|
|
||||||
class P1Type(IntEnum):
|
class P1Type(IntEnum):
|
||||||
@@ -178,6 +182,19 @@ class CommandBuilder:
|
|||||||
P2Type.FILTERING_FIELD_NAME,
|
P2Type.FILTERING_FIELD_NAME,
|
||||||
self._eip712_filtering_send_name(name, sig))
|
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]:
|
def sign(self, bip32_path: str, rlp_data: bytes) -> list[bytes]:
|
||||||
apdus = list()
|
apdus = list()
|
||||||
payload = pack_derivation_path(bip32_path)
|
payload = pack_derivation_path(bip32_path)
|
||||||
|
|||||||
@@ -49,20 +49,36 @@ __attribute__((section(".boot"))) int main(int arg0) {
|
|||||||
|
|
||||||
check_api_level(CX_COMPAT_APILEVEL);
|
check_api_level(CX_COMPAT_APILEVEL);
|
||||||
|
|
||||||
// Check if plugin is called from the dashboard.
|
BEGIN_TRY {
|
||||||
if (!arg0) {
|
TRY {
|
||||||
// Called from dashboard, launch Ethereum app
|
// Check if plugin is called from the dashboard.
|
||||||
call_app_ethereum();
|
if (!arg0) {
|
||||||
return 0;
|
// Called from dashboard, launch Ethereum app
|
||||||
} else {
|
call_app_ethereum();
|
||||||
// Not called from dashboard: called from the ethereum app!
|
|
||||||
// launch plugin main
|
// Will not get reached.
|
||||||
plugin_main(arg0);
|
__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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
END_TRY;
|
||||||
// Call `os_lib_end`, go back to the ethereum app.
|
}
|
||||||
os_lib_end();
|
|
||||||
|
|
||||||
// Will not get reached.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -16,4 +16,4 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
// applicative main for plugins
|
// applicative main for plugins
|
||||||
void plugin_main(int arg0);
|
void plugin_main(int arg0);
|
||||||
|
|||||||
Reference in New Issue
Block a user