Merge pull request #592 from LedgerHQ/cev/add-ledger-pki
Add Ledger PKI
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import rlp
|
||||
from enum import IntEnum
|
||||
from ragger.backend import BackendInterface
|
||||
from ragger.firmware import Firmware
|
||||
from ragger.error import ExceptionRAPDU
|
||||
from ragger.utils import RAPDU
|
||||
from typing import Optional
|
||||
|
||||
@@ -22,6 +24,7 @@ class StatusWord(IntEnum):
|
||||
CONDITION_NOT_SATISFIED = 0x6985
|
||||
REF_DATA_NOT_FOUND = 0x6a88
|
||||
EXCEPTION_OVERFLOW = 0x6807
|
||||
NOT_IMPLEMENTED = 0x911c
|
||||
|
||||
|
||||
class DomainNameTag(IntEnum):
|
||||
@@ -36,10 +39,52 @@ class DomainNameTag(IntEnum):
|
||||
ADDRESS = 0x22
|
||||
|
||||
|
||||
class PKIPubKeyUsage(IntEnum):
|
||||
PUBKEY_USAGE_GENUINE_CHECK = 0x01
|
||||
PUBKEY_USAGE_EXCHANGE_PAYLOAD = 0x02
|
||||
PUBKEY_USAGE_NFT_METADATA = 0x03
|
||||
PUBKEY_USAGE_TRUSTED_NAME = 0x04
|
||||
PUBKEY_USAGE_BACKUP_PROVIDER = 0x05
|
||||
PUBKEY_USAGE_RECOVER_ORCHESTRATOR = 0x06
|
||||
PUBKEY_USAGE_PLUGIN_METADATA = 0x07
|
||||
PUBKEY_USAGE_COIN_META = 0x08
|
||||
PUBKEY_USAGE_SEED_ID_AUTH = 0x09
|
||||
|
||||
|
||||
class PKIClient:
|
||||
_CLA: int = 0xB0
|
||||
_INS: int = 0x06
|
||||
|
||||
def __init__(self, client: BackendInterface) -> None:
|
||||
self._client = client
|
||||
|
||||
def send_certificate(self, p1: PKIPubKeyUsage, payload: bytes) -> RAPDU:
|
||||
try:
|
||||
response = self.send_raw(p1, payload)
|
||||
assert response.status == StatusWord.OK
|
||||
except ExceptionRAPDU as err:
|
||||
if err.status == StatusWord.NOT_IMPLEMENTED:
|
||||
print("Ledger-PKI APDU not yet implemented. Legacy path will be used")
|
||||
|
||||
def send_raw(self, p1: PKIPubKeyUsage, payload: bytes) -> RAPDU:
|
||||
header = bytearray()
|
||||
header.append(self._CLA)
|
||||
header.append(self._INS)
|
||||
header.append(p1)
|
||||
header.append(0x00)
|
||||
header.append(len(payload))
|
||||
return self._client.exchange_raw(header + payload)
|
||||
|
||||
|
||||
class EthAppClient:
|
||||
def __init__(self, client: BackendInterface):
|
||||
self._client = client
|
||||
self._firmware = client.firmware
|
||||
self._cmd_builder = CommandBuilder()
|
||||
self._pki_client: Optional[PKIClient] = None
|
||||
if self._firmware != Firmware.NANOS:
|
||||
# LedgerPKI not supported on Nanos
|
||||
self._pki_client = PKIClient(self._client)
|
||||
|
||||
def _exchange_async(self, payload: bytes):
|
||||
return self._client.exchange_async_raw(payload)
|
||||
@@ -168,6 +213,23 @@ class EthAppClient:
|
||||
pubkey))
|
||||
|
||||
def provide_domain_name(self, challenge: int, name: str, addr: bytes) -> RAPDU:
|
||||
|
||||
if self._pki_client is None:
|
||||
print(f"Ledger-PKI Not supported on '{self._firmware.name}'")
|
||||
else:
|
||||
# pylint: disable=line-too-long
|
||||
if self._firmware == Firmware.NANOSP:
|
||||
cert_apdu = "01010102010210040102000011040000000212010013020002140101160400000000200b446f6d61696e5f4e616d6530020007310108320121332102b91fbec173e3ba4a714e014ebc827b6f899a9fa7f4ac769cde284317a00f4f653401013501031546304402201b5188f5af5cd4d40d2e5eee85609323ee129b789082d079644c89c0df9b6ce0022076c5d26bb5c8db8ab02771ecd577f63f68eaf1c90523173f161f9c12f6e978bd" # noqa: E501
|
||||
elif self._firmware == Firmware.NANOX:
|
||||
cert_apdu = "01010102010211040000000212010013020002140101160400000000200B446F6D61696E5F4E616D6530020007310108320121332102B91FBEC173E3BA4A714E014EBC827B6F899A9FA7F4AC769CDE284317A00F4F653401013501021546304402202CD052029B756890F0C56713409C58C24785FEFFD1A997E9C840A7BDB176B512022059A30E04E491CD27BD1DA1B5CB810CF8E4EAE67F6406F054FDFC371F7EB9F2C4" # noqa: E501
|
||||
elif self._firmware == Firmware.STAX:
|
||||
cert_apdu = "01010102010211040000000212010013020002140101160400000000200B446F6D61696E5F4E616D6530020007310108320121332102B91FBEC173E3BA4A714E014EBC827B6F899A9FA7F4AC769CDE284317A00F4F65340101350104154630440220741DB4E738749D4188436419B20B9AEF8F07581312A9B3C9BAA3F3E879690F6002204C4A3510569247777BC43DB830D129ACA8985B88552E2E234E14D8AA2863026B" # noqa: E501
|
||||
elif self._firmware == Firmware.FLEX:
|
||||
cert_apdu = "01010102010211040000000212010013020002140101160400000000200B446F6D61696E5F4E616D6530020007310108320121332102B91FBEC173E3BA4A714E014EBC827B6F899A9FA7F4AC769CDE284317A00F4F65340101350105154730450221008B6BBCE1716C0A06F110C77FE181F8395D1692441459A106411463F01A45D4A7022044AB69037E6FA9D1D1A409E00B202C2D4451D464C8E5D4962D509FE63153FE93" # noqa: E501
|
||||
# pylint: enable=line-too-long
|
||||
|
||||
self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_COIN_META, bytes.fromhex(cert_apdu))
|
||||
|
||||
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
|
||||
@@ -194,6 +256,23 @@ class EthAppClient:
|
||||
key_id: int = 2,
|
||||
algo_id: int = 1,
|
||||
sig: Optional[bytes] = None) -> RAPDU:
|
||||
|
||||
if self._pki_client is None:
|
||||
print(f"Ledger-PKI Not supported on '{self._firmware.name}'")
|
||||
else:
|
||||
# pylint: disable=line-too-long
|
||||
if self._firmware == Firmware.NANOSP:
|
||||
cert_apdu = "01010102010210040102000011040000000212010013020002140101160400000000200A53657420506C7567696E30020003310107320121332103C055BC4ECF055E2D85085D35127A3DE6705C7F885055CD7071E87671BF191FE3340101350103154630440220401824348DA0E435C9BF16C3591665CFA1B7D8E729971BE884027E02BD3C35A102202289EE207B73D98E9E6110CC143EB929F03B99D54C63023C99561D3CE164D30F" # noqa: E501
|
||||
elif self._firmware == Firmware.NANOX:
|
||||
cert_apdu = "01010102010211040000000212010013020002140101160400000000200A53657420506C7567696E30020003310107320121332103C055BC4ECF055E2D85085D35127A3DE6705C7F885055CD7071E87671BF191FE334010135010215473045022100E657DE255F954779E14D281E2E739D89DEF2E943B7FD4B4AFE49CF4FF7E1D84F022057F29C9AEA8FAA25C8438FDEE85C6DABF270E5CEC1655F17F2D9A6ADCD3ADC0E" # noqa: E501
|
||||
elif self._firmware == Firmware.STAX:
|
||||
cert_apdu = "01010102010211040000000212010013020002140101160400000000200A53657420506C7567696E30020003310107320121332103C055BC4ECF055E2D85085D35127A3DE6705C7F885055CD7071E87671BF191FE334010135010415473045022100B8AF9667C190B60BF350D8F8CA66A4BCEA22BF47D757CB7F88F8D16C7794BCDC02205F7D6C8E9294F73744A82E1062B10FFEB809252682112E71A419EFC78227211B" # noqa: E501
|
||||
elif self._firmware == Firmware.FLEX:
|
||||
cert_apdu = "01010102010211040000000212010013020002140101160400000000200A53657420506C7567696E30020003310107320121332103C055BC4ECF055E2D85085D35127A3DE6705C7F885055CD7071E87671BF191FE334010135010515473045022100F5069D8BCEDCF7CC55273266E3871B09FFCACD084B5753347A809DDDA67E6235022003CE65364BFA96B6FE7A9D8C13EC87B8E727E8B7BF4A63176F5D61AB8F97807E" # noqa: E501
|
||||
# pylint: enable=line-too-long
|
||||
|
||||
self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_PLUGIN_METADATA, bytes.fromhex(cert_apdu))
|
||||
|
||||
if sig is None:
|
||||
# Temporarily get a command with an empty signature to extract the payload and
|
||||
# compute the signature on it
|
||||
@@ -227,6 +306,23 @@ class EthAppClient:
|
||||
key_id: int = 1,
|
||||
algo_id: int = 1,
|
||||
sig: Optional[bytes] = None) -> RAPDU:
|
||||
|
||||
if self._pki_client is None:
|
||||
print(f"Ledger-PKI Not supported on '{self._firmware.name}'")
|
||||
else:
|
||||
# pylint: disable=line-too-long
|
||||
if self._firmware == Firmware.NANOSP:
|
||||
cert_apdu = "0101010201021004010200001104000000021201001302000214010116040000000020084e46545f496e666f300200043101033201213321023cfb5fb31905f4bd39d9d535a40c26aab51c5d7d3219b28ac942b980fb206cfb34010135010315473045022100d43e142a6639b27a79bc4f021854df48f1bc1e828ac47b105578cb527b69f525022078f6e6b3eb9bb787a0a29e85531ce3512c2d6481e761e840db0fb6b0898911a1" # noqa: E501
|
||||
elif self._firmware == Firmware.NANOX:
|
||||
cert_apdu = "0101010201021104000000021201001302000214010116040000000020084E46545F496E666F300200043101033201213321023CFB5FB31905F4BD39D9D535A40C26AAB51C5D7D3219B28AC942B980FB206CFB340101350102154730450221009BAE21BB8CBA6F95DDFF86AEEA991D63FA36A469A3071F61BDA8895F1A5F0AC3022061661F95D1513D3FDE81FFEA4B0C6D48ADCB27ED70915EE3ACD16A2A64CDE916" # noqa: E501
|
||||
elif self._firmware == Firmware.STAX:
|
||||
cert_apdu = "0101010201021104000000021201001302000214010116040000000020084E46545F496E666F300200043101033201213321023CFB5FB31905F4BD39D9D535A40C26AAB51C5D7D3219B28AC942B980FB206CFB3401013501041546304402201DEE04EC830FFDE5C98A708EC6865605FC14FF6105A54BE5230F2B954C673B940220581A0A5E42A7779140963703E43B3BEABE4C69284EDEF00E76BB5875E0810C9B" # noqa: E501
|
||||
elif self._firmware == Firmware.FLEX:
|
||||
cert_apdu = "0101010201021104000000021201001302000214010116040000000020084E46545F496E666F300200043101033201213321023CFB5FB31905F4BD39D9D535A40C26AAB51C5D7D3219B28AC942B980FB206CFB340101350105154730450221009ABCC7056D54C1B5DBB353178B13850C20521EE6884AA415AA61B329DB1D87F602204E308F273B8D18080184695438577F770524F717E5D08EE20ECBF1BC599F3538" # noqa: E501
|
||||
# pylint: enable=line-too-long
|
||||
|
||||
self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_NFT_METADATA, bytes.fromhex(cert_apdu))
|
||||
|
||||
if sig is None:
|
||||
# Temporarily get a command with an empty signature to extract the payload and
|
||||
# compute the signature on it
|
||||
@@ -278,6 +374,23 @@ class EthAppClient:
|
||||
decimals: int,
|
||||
chain_id: int,
|
||||
sig: Optional[bytes] = None) -> RAPDU:
|
||||
|
||||
if self._pki_client is None:
|
||||
print(f"Ledger-PKI Not supported on '{self._firmware.name}'")
|
||||
else:
|
||||
# pylint: disable=line-too-long
|
||||
if self._firmware == Firmware.NANOSP:
|
||||
cert_apdu = "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010310040102000015473045022100C15795C2AE41E6FAE6B1362EE1AE216428507D7C1D6939B928559CC7A1F6425C02206139CF2E133DD62F3E00F183E42109C9853AC62B6B70C5079B9A80DBB9D54AB5" # noqa: E501
|
||||
elif self._firmware == Firmware.NANOX:
|
||||
cert_apdu = "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010215473045022100E3B956F93FBFF0D41908483888F0F75D4714662A692F7A38DC6C41A13294F9370220471991BECB3CA4F43413CADC8FF738A8CC03568BFA832B4DCFE8C469080984E5" # noqa: E501
|
||||
elif self._firmware == Firmware.STAX:
|
||||
cert_apdu = "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C6405618873401013501041546304402206731FCD3E2432C5CA162381392FD17AD3A41EEF852E1D706F21A656AB165263602204B89FAE8DBAF191E2D79FB00EBA80D613CB7EDF0BE960CB6F6B29D96E1437F5F" # noqa: E501
|
||||
elif self._firmware == Firmware.FLEX:
|
||||
cert_apdu = "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010515473045022100B59EA8B958AA40578A6FBE9BBFB761020ACD5DBD8AA863C11DA17F42B2AFDE790220186316059EFA58811337D47C7F815F772EA42BBBCEA4AE123D1118C80588F5CB" # noqa: E501
|
||||
# pylint: enable=line-too-long
|
||||
|
||||
self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_COIN_META, bytes.fromhex(cert_apdu))
|
||||
|
||||
if sig is None:
|
||||
# Temporarily get a command with an empty signature to extract the payload and
|
||||
# compute the signature on it
|
||||
|
||||
@@ -12,6 +12,8 @@ from client.client import EthAppClient, EIP712FieldType
|
||||
|
||||
from ragger.firmware import Firmware
|
||||
|
||||
from client.client import PKIPubKeyUsage
|
||||
|
||||
# global variables
|
||||
app_client: EthAppClient = None
|
||||
filtering_paths: dict = {}
|
||||
@@ -450,6 +452,22 @@ def process_data(aclient: EthAppClient,
|
||||
pass
|
||||
prepare_filtering(filters, message)
|
||||
|
||||
if aclient._pki_client is None:
|
||||
print(f"Ledger-PKI Not supported on '{aclient._firmware.name}'")
|
||||
else:
|
||||
# pylint: disable=line-too-long
|
||||
if aclient._firmware == Firmware.NANOSP:
|
||||
cert_apdu = "0101010201021004010200001104000000021201001302000214010116040000000020104549503731325f46696c746572696e67300200053101083201213321024cca8fad496aa5040a00a7eb2f5cc3b85376d88ba147a7d7054a99c64056188734010135010315473045022100ef197e5b1cabb3de5dfc62f965db8536b0463d272c6fea38ebc73605715b1df9022017bef619d52a9728b37a9b5a33f0143bcdcc714694eed07c326796ffbb7c2958" # noqa: E501
|
||||
elif aclient._firmware == Firmware.NANOX:
|
||||
cert_apdu = "0101010201021104000000021201001302000214010116040000000020104549503731325F46696C746572696E67300200053101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010215473045022100E07E129B0DC2A571D5205C3DB43BF4BB3463A2E9D2A4EEDBEC8FD3518CC5A95902205F80306EEF785C4D45BDCA1F25394A1341571BD1921C2740392DD22EB1ACDD8B" # noqa: E501
|
||||
elif aclient._firmware == Firmware.STAX:
|
||||
cert_apdu = "0101010201021104000000021201001302000214010116040000000020104549503731325F46696C746572696E67300200053101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C6405618873401013501041546304402204EA7B30F0EEFEF25FAB3ADDA6609E25296C41DD1C5969A92FAE6B600AAC2902E02206212054E123F5F965F787AE7EE565E243F21B11725626D3FF058522D6BDCD995" # noqa: E501
|
||||
elif aclient._firmware == Firmware.FLEX:
|
||||
cert_apdu = "0101010201021104000000021201001302000214010116040000000020104549503731325F46696C746572696E67300200053101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C6405618873401013501051546304402205FB5E970065A95C57F00FFA3964946251815527613724ED6745C37E303934BE702203CC9F4124B42806F0A7CA765CFAB5AADEB280C35AB8F809FC49ADC97D9B9CE15" # noqa: E501
|
||||
# pylint: enable=line-too-long
|
||||
|
||||
aclient._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_COIN_META, bytes.fromhex(cert_apdu))
|
||||
|
||||
# send domain implementation
|
||||
with app_client.eip712_send_struct_impl_root_struct(domain_typename):
|
||||
enable_autonext()
|
||||
|
||||
@@ -25,32 +25,35 @@ def get_device_settings(firmware: Firmware) -> list[SettingID]:
|
||||
]
|
||||
|
||||
|
||||
def get_setting_per_page(firmware: Firmware) -> int:
|
||||
if firmware == Firmware.STAX:
|
||||
return 3
|
||||
return 2
|
||||
|
||||
|
||||
def get_setting_position(firmware: Firmware, setting: Union[NavInsID, SettingID]) -> tuple[int, int]:
|
||||
settings_per_page = get_setting_per_page(firmware)
|
||||
def get_setting_position(firmware: Firmware, setting_idx: int, per_page: int) -> tuple[int, int]:
|
||||
if firmware == Firmware.STAX:
|
||||
screen_height = 672 # px
|
||||
header_height = 88 # px
|
||||
footer_height = 92 # px
|
||||
option_offset = 350 # px
|
||||
x_offset = 350 # px
|
||||
else:
|
||||
screen_height = 600 # px
|
||||
header_height = 92 # px
|
||||
footer_height = 97 # px
|
||||
option_offset = 420 # px
|
||||
usable_height = screen_height - (header_height + footer_height)
|
||||
setting_height = usable_height // settings_per_page
|
||||
index_in_page = get_device_settings(firmware).index(SettingID(setting)) % settings_per_page
|
||||
return option_offset, header_height + (setting_height * index_in_page) + (setting_height // 2)
|
||||
x_offset = 420 # px
|
||||
index_in_page = setting_idx % per_page
|
||||
if index_in_page == 0:
|
||||
y_offset = header_height + 10
|
||||
elif per_page == 3:
|
||||
if setting_idx == 1:
|
||||
# 2nd setting over 3: middle of the screen
|
||||
y_offset = screen_height // 2
|
||||
else:
|
||||
# Last setting
|
||||
y_offset = screen_height - footer_height - 10
|
||||
else:
|
||||
# 2 per page, requesting the 2nd one; middle of screen is ok
|
||||
y_offset = screen_height // 2
|
||||
return x_offset, y_offset
|
||||
|
||||
|
||||
def settings_toggle(firmware: Firmware, nav: Navigator, to_toggle: list[SettingID]):
|
||||
moves: list[Union[NavIns, NavInsID]] = list()
|
||||
moves: list[Union[NavIns, NavInsID]] = []
|
||||
settings = get_device_settings(firmware)
|
||||
# Assume the app is on the home page
|
||||
if firmware.is_nano:
|
||||
@@ -63,12 +66,12 @@ def settings_toggle(firmware: Firmware, nav: Navigator, to_toggle: list[SettingI
|
||||
moves += [NavInsID.BOTH_CLICK] # Back
|
||||
else:
|
||||
moves += [NavInsID.USE_CASE_HOME_SETTINGS]
|
||||
settings_per_page = get_setting_per_page(firmware)
|
||||
settings_per_page = 3 if firmware == Firmware.STAX else 2
|
||||
for setting in settings:
|
||||
setting_idx = settings.index(setting)
|
||||
if (setting_idx > 0) and (setting_idx % settings_per_page) == 0:
|
||||
moves += [NavInsID.USE_CASE_SETTINGS_NEXT]
|
||||
if setting in to_toggle:
|
||||
moves += [NavIns(NavInsID.TOUCH, get_setting_position(firmware, setting))]
|
||||
moves += [NavIns(NavInsID.TOUCH, get_setting_position(firmware, setting_idx, settings_per_page))]
|
||||
moves += [NavInsID.USE_CASE_SETTINGS_MULTI_PAGE_EXIT]
|
||||
nav.navigate(moves, screen_change_before_first_instruction=False)
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
|
||||
#ifdef HAVE_TOKENS_EXTRA_LIST
|
||||
|
||||
#include "extra_tokens.h"
|
||||
|
||||
const tokenDefinition_t TOKENS_EXTRA[NUM_TOKENS_EXTRA] = {
|
||||
|
||||
// Ropsten DeversiFi tokens
|
||||
{{0x4c, 0x5f, 0x66, 0x59, 0x61, 0x97, 0xa8, 0x6f, 0xb3, 0x0a,
|
||||
0x24, 0x35, 0xe2, 0xef, 0x4d, 0xdc, 0xb3, 0x93, 0x42, 0xc9},
|
||||
"tUSDT",
|
||||
6},
|
||||
{{0x1c, 0x0f, 0x17, 0x43, 0x67, 0x40, 0xbf, 0xb9, 0x2c, 0x10,
|
||||
0x70, 0xee, 0x86, 0x32, 0x2d, 0xe8, 0x90, 0x83, 0x7c, 0x6a},
|
||||
"tUSDT",
|
||||
6},
|
||||
{{0xcd, 0x07, 0x7a, 0xbe, 0xdd, 0x83, 0x1a, 0x34, 0x43, 0xff,
|
||||
0xbe, 0x24, 0xfb, 0x76, 0x66, 0x1b, 0xbb, 0x17, 0xeb, 0x69},
|
||||
"tZRX",
|
||||
18},
|
||||
{{0x40, 0xd8, 0x97, 0x85, 0x00, 0xbf, 0x68, 0x32, 0x4a, 0x51,
|
||||
0x53, 0x3c, 0xd6, 0xa2, 0x1e, 0x3e, 0x59, 0xbe, 0x32, 0x4a},
|
||||
"tBTC",
|
||||
18},
|
||||
// Goerli DeversiFi tokens
|
||||
{{0xd9, 0x97, 0xa8, 0x63, 0x46, 0xe7, 0x65, 0x18, 0xe6, 0x92,
|
||||
0x25, 0x56, 0xf3, 0x4d, 0x76, 0x61, 0x30, 0xc0, 0xbb, 0xfd},
|
||||
"tUSDT",
|
||||
6},
|
||||
{{0xc1, 0xd5, 0x79, 0xeb, 0xff, 0x7c, 0x0f, 0x6c, 0xfd, 0x9a,
|
||||
0xd5, 0xfb, 0x26, 0x7f, 0xec, 0x73, 0xbe, 0x70, 0xc8, 0xf7},
|
||||
"tBTC",
|
||||
18},
|
||||
{{0xa8, 0xf3, 0x14, 0x4f, 0xea, 0x2c, 0x37, 0x5a, 0xd0, 0x58,
|
||||
0xec, 0x12, 0x09, 0x9a, 0x5a, 0x21, 0xa2, 0x6f, 0xe9, 0x96},
|
||||
"tDVF",
|
||||
18},
|
||||
{{0x4c, 0xda, 0xbe, 0xc1, 0x2a, 0x39, 0x7f, 0xb6, 0xef, 0xaf,
|
||||
0x46, 0x13, 0xd5, 0xdf, 0xd7, 0x9b, 0x30, 0x9a, 0xe9, 0xfa},
|
||||
"tXDVF",
|
||||
18},
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,28 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "asset_info.h"
|
||||
|
||||
#ifdef HAVE_TOKENS_EXTRA_LIST
|
||||
|
||||
#define NUM_TOKENS_EXTRA 8
|
||||
|
||||
extern tokenDefinition_t const TOKENS_EXTRA[NUM_TOKENS_EXTRA];
|
||||
|
||||
#endif
|
||||
76
src/ledger_pki.c
Normal file
76
src/ledger_pki.c
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "apdu_constants.h"
|
||||
#include "public_keys.h"
|
||||
#ifdef HAVE_LEDGER_PKI
|
||||
#include "os_pki.h"
|
||||
#endif
|
||||
|
||||
#define KEY_USAGE_STR(x) \
|
||||
(x == CERTIFICATE_PUBLIC_KEY_USAGE_GENUINE_CHECK ? "GENUINE_CHECK" \
|
||||
: x == CERTIFICATE_PUBLIC_KEY_USAGE_EXCHANGE_PAYLOAD ? "EXCHANGE_PAYLOAD" \
|
||||
: x == CERTIFICATE_PUBLIC_KEY_USAGE_NFT_METADATA ? "NFT_METADATA" \
|
||||
: x == CERTIFICATE_PUBLIC_KEY_USAGE_TRUSTED_NAME ? "TRUSTED_NAME" \
|
||||
: x == CERTIFICATE_PUBLIC_KEY_USAGE_BACKUP_PROVIDER ? "BACKUP_PROVIDER" \
|
||||
: x == CERTIFICATE_PUBLIC_KEY_USAGE_RECOVER_ORCHESTRATOR ? "RECOVER_ORCHESTRATOR" \
|
||||
: x == CERTIFICATE_PUBLIC_KEY_USAGE_PLUGIN_METADATA ? "PLUGIN_METADATA" \
|
||||
: x == CERTIFICATE_PUBLIC_KEY_USAGE_COIN_META ? "COIN_META" \
|
||||
: x == CERTIFICATE_PUBLIC_KEY_USAGE_SEED_ID_AUTH ? "SEED_ID_AUTH" \
|
||||
: "Unknown")
|
||||
|
||||
int check_signature_with_pubkey(const char *tag,
|
||||
uint8_t *buffer,
|
||||
const uint8_t bufLen,
|
||||
const uint8_t *PubKey,
|
||||
const uint8_t keyLen,
|
||||
#ifdef HAVE_LEDGER_PKI
|
||||
const uint8_t keyUsageExp,
|
||||
#endif
|
||||
uint8_t *signature,
|
||||
const uint8_t sigLen) {
|
||||
UNUSED(tag);
|
||||
cx_ecfp_public_key_t verif_key = {0};
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
#ifdef HAVE_LEDGER_PKI
|
||||
uint8_t key_usage = 0;
|
||||
size_t trusted_name_len = 0;
|
||||
uint8_t trusted_name[CERTIFICATE_TRUSTED_NAME_MAXLEN] = {0};
|
||||
cx_ecfp_384_public_key_t public_key = {0};
|
||||
#endif
|
||||
|
||||
PRINTF(
|
||||
"[%s] "
|
||||
"=======================================================================================\n",
|
||||
tag);
|
||||
#ifdef HAVE_LEDGER_PKI
|
||||
error = os_pki_get_info(&key_usage, trusted_name, &trusted_name_len, &public_key);
|
||||
if ((error == 0) && (key_usage == keyUsageExp)) {
|
||||
PRINTF("[%s] Certificate '%s' loaded for usage 0x%x (%s)\n",
|
||||
tag,
|
||||
trusted_name,
|
||||
key_usage,
|
||||
KEY_USAGE_STR(key_usage));
|
||||
|
||||
// Checking the signature with PKI
|
||||
if (!os_pki_verify(buffer, bufLen, signature, sigLen)) {
|
||||
PRINTF("%s: Invalid signature\n", tag);
|
||||
#ifndef HAVE_BYPASS_SIGNATURES
|
||||
error = APDU_RESPONSE_INVALID_DATA;
|
||||
goto end;
|
||||
#endif
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
PRINTF("[%s] ********** No certificate loaded. Using legacy path **********\n", tag);
|
||||
CX_CHECK(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1, PubKey, keyLen, &verif_key));
|
||||
if (!cx_ecdsa_verify_no_throw(&verif_key, buffer, bufLen, signature, sigLen)) {
|
||||
PRINTF("%s: Invalid signature\n", tag);
|
||||
#ifndef HAVE_BYPASS_SIGNATURES
|
||||
error = APDU_RESPONSE_INVALID_DATA;
|
||||
goto end;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
error = CX_OK;
|
||||
end:
|
||||
return error;
|
||||
}
|
||||
@@ -150,6 +150,15 @@ void handleApdu(unsigned int *flags, unsigned int *tx) {
|
||||
|
||||
BEGIN_TRY {
|
||||
TRY {
|
||||
#ifndef HAVE_LEDGER_PKI
|
||||
if ((G_io_apdu_buffer[OFFSET_CLA] == 0xB0 && (G_io_apdu_buffer[OFFSET_INS] == 0x06))) {
|
||||
// Ledger-PKI APDU not yet caught by the running OS.
|
||||
// Command code not supported
|
||||
PRINTF("Ledger-PKI not yet supported!\n");
|
||||
THROW(0x911C);
|
||||
}
|
||||
#endif // HAVE_LEDGER_PKI
|
||||
|
||||
if (G_io_apdu_buffer[OFFSET_CLA] != CLA) {
|
||||
THROW(0x6E00);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
static const uint8_t LEDGER_SIGNATURE_PUBLIC_KEY[] = {
|
||||
#if defined(HAVE_CAL_TEST_KEY)
|
||||
@@ -101,3 +102,14 @@ static const uint8_t LEDGER_NFT_SELECTOR_PUBLIC_KEY[] = {
|
||||
0x92, 0xc7, 0xc6, 0x48, 0x0d, 0x39, 0xce, 0xbb, 0xa3
|
||||
#endif
|
||||
};
|
||||
|
||||
extern int check_signature_with_pubkey(const char *tag,
|
||||
uint8_t *buffer,
|
||||
const uint8_t bufLen,
|
||||
const uint8_t *PubKey,
|
||||
const uint8_t keyLen,
|
||||
#ifdef HAVE_LEDGER_PKI
|
||||
const uint8_t keyUsageExp,
|
||||
#endif
|
||||
uint8_t *signature,
|
||||
const uint8_t sigLen);
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
#include "hash_bytes.h"
|
||||
#include "network.h"
|
||||
#include "public_keys.h"
|
||||
#ifdef HAVE_LEDGER_PKI
|
||||
#include "os_pki.h"
|
||||
#endif
|
||||
|
||||
#define P1_FIRST_CHUNK 0x01
|
||||
#define P1_FOLLOWING_CHUNK 0x00
|
||||
@@ -364,39 +367,36 @@ static bool handle_address(const s_tlv_data *data,
|
||||
*/
|
||||
static bool verify_signature(const s_sig_ctx *sig_ctx) {
|
||||
uint8_t hash[INT256_LENGTH];
|
||||
cx_ecfp_public_key_t verif_key;
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
#ifdef HAVE_DOMAIN_NAME_TEST_KEY
|
||||
e_key_id valid_key_id = KEY_ID_TEST;
|
||||
#else
|
||||
e_key_id valid_key_id = KEY_ID_PROD;
|
||||
#endif
|
||||
bool ret_code = false;
|
||||
|
||||
if (sig_ctx->key_id != valid_key_id) {
|
||||
PRINTF("Error: Unknown metadata key ID %u\n", sig_ctx->key_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
CX_CHECK(
|
||||
cx_hash_no_throw((cx_hash_t *) &sig_ctx->hash_ctx, CX_LAST, NULL, 0, hash, INT256_LENGTH));
|
||||
switch (sig_ctx->key_id) {
|
||||
#ifdef HAVE_DOMAIN_NAME_TEST_KEY
|
||||
case KEY_ID_TEST:
|
||||
#else
|
||||
case KEY_ID_PROD:
|
||||
|
||||
CX_CHECK(check_signature_with_pubkey("Domain Name",
|
||||
hash,
|
||||
sizeof(hash),
|
||||
DOMAIN_NAME_PUB_KEY,
|
||||
sizeof(DOMAIN_NAME_PUB_KEY),
|
||||
#ifdef HAVE_LEDGER_PKI
|
||||
CERTIFICATE_PUBLIC_KEY_USAGE_COIN_META,
|
||||
#endif
|
||||
CX_CHECK(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1,
|
||||
DOMAIN_NAME_PUB_KEY,
|
||||
sizeof(DOMAIN_NAME_PUB_KEY),
|
||||
&verif_key));
|
||||
break;
|
||||
default:
|
||||
PRINTF("Error: Unknown metadata key ID %u\n", sig_ctx->key_id);
|
||||
return false;
|
||||
}
|
||||
if (!cx_ecdsa_verify_no_throw(&verif_key,
|
||||
hash,
|
||||
sizeof(hash),
|
||||
sig_ctx->input_sig,
|
||||
sig_ctx->input_sig_size)) {
|
||||
PRINTF("Domain name signature verification failed!\n");
|
||||
#ifndef HAVE_BYPASS_SIGNATURES
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
(uint8_t *) (sig_ctx->input_sig),
|
||||
sig_ctx->input_sig_size));
|
||||
|
||||
ret_code = true;
|
||||
end:
|
||||
return false;
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,101 +3,11 @@
|
||||
#include "public_keys.h"
|
||||
#include "common_ui.h"
|
||||
#include "os_io_seproxyhal.h"
|
||||
#include "extra_tokens.h"
|
||||
#include "network.h"
|
||||
#include "manage_asset_info.h"
|
||||
|
||||
#ifdef HAVE_CONTRACT_NAME_IN_DESCRIPTOR
|
||||
|
||||
void handleProvideErc20TokenInformation(uint8_t p1,
|
||||
uint8_t p2,
|
||||
const uint8_t *workBuffer,
|
||||
uint8_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
UNUSED(p1);
|
||||
UNUSED(p2);
|
||||
UNUSED(flags);
|
||||
uint32_t offset = 0;
|
||||
uint8_t tickerLength, contractNameLength;
|
||||
uint32_t chainId;
|
||||
uint8_t hash[INT256_LENGTH];
|
||||
cx_sha256_t sha256;
|
||||
cx_ecfp_public_key_t tokenKey;
|
||||
|
||||
cx_sha256_init(&sha256);
|
||||
|
||||
tokenDefinition_t *token = &get_current_asset_info()->token;
|
||||
|
||||
if (dataLength < 1) {
|
||||
THROW(0x6A80);
|
||||
}
|
||||
tickerLength = workBuffer[offset++];
|
||||
dataLength--;
|
||||
if ((tickerLength + 2) >= sizeof(token->ticker)) { // +2 because ' \0' is appended to ticker
|
||||
THROW(0x6A80);
|
||||
}
|
||||
if (dataLength < tickerLength + 1) {
|
||||
THROW(0x6A80);
|
||||
}
|
||||
cx_hash((cx_hash_t *) &sha256, 0, workBuffer + offset, tickerLength, NULL, 0);
|
||||
memmove(token->ticker, workBuffer + offset, tickerLength);
|
||||
token->ticker[tickerLength] = '\0';
|
||||
offset += tickerLength;
|
||||
dataLength -= tickerLength;
|
||||
|
||||
contractNameLength = workBuffer[offset++];
|
||||
dataLength--;
|
||||
if (dataLength < contractNameLength + 20 + 4 + 4) {
|
||||
THROW(0x6A80);
|
||||
}
|
||||
cx_hash((cx_hash_t *) &sha256,
|
||||
CX_LAST,
|
||||
workBuffer + offset,
|
||||
contractNameLength + 20 + 4 + 4,
|
||||
hash,
|
||||
32);
|
||||
memmove(token->contractName,
|
||||
workBuffer + offset,
|
||||
MIN(contractNameLength, sizeof(token->contractName) - 1));
|
||||
token->contractName[MIN(contractNameLength, sizeof(token->contractName) - 1)] = '\0';
|
||||
offset += contractNameLength;
|
||||
dataLength -= contractNameLength;
|
||||
|
||||
memmove(token->address, workBuffer + offset, 20);
|
||||
offset += 20;
|
||||
dataLength -= 20;
|
||||
token->decimals = U4BE(workBuffer, offset);
|
||||
offset += 4;
|
||||
dataLength -= 4;
|
||||
chainId = U4BE(workBuffer, offset);
|
||||
if ((chainConfig->chainId != 0) && (chainConfig->chainId != chainId)) {
|
||||
PRINTF("ChainId token mismatch\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
offset += 4;
|
||||
dataLength -= 4;
|
||||
cx_ecfp_init_public_key(CX_CURVE_256K1,
|
||||
LEDGER_SIGNATURE_PUBLIC_KEY,
|
||||
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
|
||||
&tokenKey);
|
||||
if (!cx_ecdsa_verify(&tokenKey,
|
||||
CX_LAST,
|
||||
CX_SHA256,
|
||||
hash,
|
||||
32,
|
||||
workBuffer + offset,
|
||||
dataLength)) {
|
||||
#ifndef HAVE_BYPASS_SIGNATURES
|
||||
PRINTF("Invalid token signature\n");
|
||||
THROW(0x6A80);
|
||||
#ifdef HAVE_LEDGER_PKI
|
||||
#include "os_pki.h"
|
||||
#endif
|
||||
}
|
||||
validate_current_asset_info();
|
||||
THROW(0x9000);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void handleProvideErc20TokenInformation(uint8_t p1,
|
||||
uint8_t p2,
|
||||
@@ -113,22 +23,21 @@ void handleProvideErc20TokenInformation(uint8_t p1,
|
||||
uint8_t tickerLength;
|
||||
uint64_t chain_id;
|
||||
uint8_t hash[INT256_LENGTH];
|
||||
cx_ecfp_public_key_t tokenKey;
|
||||
|
||||
tokenDefinition_t *token = &get_current_asset_info()->token;
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
|
||||
PRINTF("Provisioning currentAssetIndex %d\n", tmpCtx.transactionContext.currentAssetIndex);
|
||||
|
||||
if (dataLength < 1) {
|
||||
THROW(0x6A80);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
tickerLength = workBuffer[offset++];
|
||||
dataLength--;
|
||||
if ((tickerLength + 1) > sizeof(token->ticker)) {
|
||||
THROW(0x6A80);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
if (dataLength < tickerLength + 20 + 4 + 4) {
|
||||
THROW(0x6A80);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
cx_hash_sha256(workBuffer + offset, tickerLength + 20 + 4 + 4, hash, 32);
|
||||
memmove(token->ticker, workBuffer + offset, tickerLength);
|
||||
@@ -146,43 +55,29 @@ void handleProvideErc20TokenInformation(uint8_t p1,
|
||||
chain_id = U4BE(workBuffer, offset);
|
||||
if (!app_compatible_with_chain_id(&chain_id)) {
|
||||
UNSUPPORTED_CHAIN_ID_MSG(chain_id);
|
||||
THROW(0x6A80);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
offset += 4;
|
||||
dataLength -= 4;
|
||||
|
||||
#ifdef HAVE_TOKENS_EXTRA_LIST
|
||||
tokenDefinition_t *currentToken = NULL;
|
||||
uint32_t index;
|
||||
for (index = 0; index < NUM_TOKENS_EXTRA; index++) {
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_EXTRA[index]);
|
||||
if (memcmp(currentToken->address, token->address, 20) == 0) {
|
||||
strcpy((char *) token->ticker, (char *) currentToken->ticker);
|
||||
token->decimals = currentToken->decimals;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index < NUM_TOKENS_EXTRA) {
|
||||
PRINTF("Descriptor whitelisted\n");
|
||||
} else
|
||||
error = check_signature_with_pubkey("ERC20 Token Info",
|
||||
hash,
|
||||
sizeof(hash),
|
||||
LEDGER_SIGNATURE_PUBLIC_KEY,
|
||||
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
|
||||
#ifdef HAVE_LEDGER_PKI
|
||||
CERTIFICATE_PUBLIC_KEY_USAGE_COIN_META,
|
||||
#endif
|
||||
{
|
||||
CX_ASSERT(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1,
|
||||
LEDGER_SIGNATURE_PUBLIC_KEY,
|
||||
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
|
||||
&tokenKey));
|
||||
if (!cx_ecdsa_verify_no_throw(&tokenKey, hash, 32, workBuffer + offset, dataLength)) {
|
||||
(uint8_t *) (workBuffer + offset),
|
||||
dataLength);
|
||||
#ifndef HAVE_BYPASS_SIGNATURES
|
||||
PRINTF("Invalid token signature\n");
|
||||
THROW(0x6A80);
|
||||
#endif
|
||||
}
|
||||
if (error != CX_OK) {
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
#endif
|
||||
|
||||
G_io_apdu_buffer[0] = tmpCtx.transactionContext.currentAssetIndex;
|
||||
validate_current_asset_info();
|
||||
U2BE_ENCODE(G_io_apdu_buffer, 1, APDU_RESPONSE_OK);
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 3);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
#include "network.h"
|
||||
#include "public_keys.h"
|
||||
#include "manage_asset_info.h"
|
||||
#ifdef HAVE_LEDGER_PKI
|
||||
#include "os_pki.h"
|
||||
#endif
|
||||
|
||||
#define TYPE_SIZE 1
|
||||
#define VERSION_SIZE 1
|
||||
@@ -50,19 +53,29 @@ void handleProvideNFTInformation(uint8_t p1,
|
||||
UNUSED(tx);
|
||||
UNUSED(flags);
|
||||
uint8_t hash[INT256_LENGTH];
|
||||
cx_ecfp_public_key_t nftKey;
|
||||
nftInfo_t *nft = NULL;
|
||||
size_t offset = 0;
|
||||
size_t payloadSize = 0;
|
||||
uint8_t collectionNameLength = 0;
|
||||
uint64_t chain_id = 0;
|
||||
uint8_t signatureLen = 0;
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
#ifdef HAVE_NFT_STAGING_KEY
|
||||
uint8_t valid_keyId = STAGING_NFT_METADATA_KEY;
|
||||
#else
|
||||
uint8_t valid_keyId = PROD_NFT_METADATA_KEY;
|
||||
#endif
|
||||
|
||||
PRINTF("In handle provide NFTInformation\n");
|
||||
|
||||
if ((pluginType != ERC721) && (pluginType != ERC1155)) {
|
||||
PRINTF("NFT metadata provided without proper plugin loaded!\n");
|
||||
THROW(0x6985);
|
||||
}
|
||||
nftInfo_t *nft = &get_current_asset_info()->nft;
|
||||
nft = &get_current_asset_info()->nft;
|
||||
|
||||
PRINTF("Provisioning currentAssetIndex %d\n", tmpCtx.transactionContext.currentAssetIndex);
|
||||
|
||||
size_t offset = 0;
|
||||
|
||||
if (dataLength <= HEADER_SIZE) {
|
||||
PRINTF("Data too small for headers: expected at least %d, got %d\n",
|
||||
HEADER_SIZE,
|
||||
@@ -70,34 +83,24 @@ void handleProvideNFTInformation(uint8_t p1,
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
|
||||
uint8_t type = workBuffer[offset];
|
||||
switch (type) {
|
||||
case TYPE_1:
|
||||
break;
|
||||
default:
|
||||
PRINTF("Unsupported type %d\n", type);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
break;
|
||||
if (workBuffer[offset] != TYPE_1) {
|
||||
PRINTF("Unsupported type %d\n", workBuffer[offset]);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
offset += TYPE_SIZE;
|
||||
|
||||
uint8_t version = workBuffer[offset];
|
||||
switch (version) {
|
||||
case VERSION_1:
|
||||
break;
|
||||
default:
|
||||
PRINTF("Unsupported version %d\n", version);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
break;
|
||||
if (workBuffer[offset] != VERSION_1) {
|
||||
PRINTF("Unsupported version %d\n", workBuffer[offset]);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
offset += VERSION_SIZE;
|
||||
|
||||
uint8_t collectionNameLength = workBuffer[offset];
|
||||
collectionNameLength = workBuffer[offset];
|
||||
offset += NAME_LENGTH_SIZE;
|
||||
|
||||
// Size of the payload (everything except the signature)
|
||||
size_t payloadSize = HEADER_SIZE + collectionNameLength + ADDRESS_LENGTH + CHAIN_ID_SIZE +
|
||||
KEY_ID_SIZE + ALGORITHM_ID_SIZE;
|
||||
payloadSize = HEADER_SIZE + collectionNameLength + ADDRESS_LENGTH + CHAIN_ID_SIZE +
|
||||
KEY_ID_SIZE + ALGORITHM_ID_SIZE;
|
||||
if (dataLength < payloadSize) {
|
||||
PRINTF("Data too small for payload: expected at least %d, got %d\n",
|
||||
payloadSize,
|
||||
@@ -124,7 +127,7 @@ void handleProvideNFTInformation(uint8_t p1,
|
||||
PRINTF("Address: %.*H\n", ADDRESS_LENGTH, workBuffer + offset);
|
||||
offset += ADDRESS_LENGTH;
|
||||
|
||||
uint64_t chain_id = u64_from_BE(workBuffer + offset, CHAIN_ID_SIZE);
|
||||
chain_id = u64_from_BE(workBuffer + offset, CHAIN_ID_SIZE);
|
||||
// this prints raw data, so to have a more meaningful print, display
|
||||
// the buffer before the endianness swap
|
||||
PRINTF("ChainID: %.*H\n", sizeof(chain_id), (workBuffer + offset));
|
||||
@@ -134,35 +137,18 @@ void handleProvideNFTInformation(uint8_t p1,
|
||||
}
|
||||
offset += CHAIN_ID_SIZE;
|
||||
|
||||
uint8_t keyId = workBuffer[offset];
|
||||
const uint8_t *rawKey;
|
||||
uint8_t rawKeyLen;
|
||||
|
||||
PRINTF("KeyID: %d\n", keyId);
|
||||
switch (keyId) {
|
||||
#ifdef HAVE_NFT_STAGING_KEY
|
||||
case STAGING_NFT_METADATA_KEY:
|
||||
#endif
|
||||
case PROD_NFT_METADATA_KEY:
|
||||
rawKey = LEDGER_NFT_METADATA_PUBLIC_KEY;
|
||||
rawKeyLen = sizeof(LEDGER_NFT_METADATA_PUBLIC_KEY);
|
||||
break;
|
||||
default:
|
||||
PRINTF("KeyID %d not supported\n", keyId);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
break;
|
||||
if (workBuffer[offset] != valid_keyId) {
|
||||
PRINTF("Unsupported KeyID %d\n", workBuffer[offset]);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
PRINTF("RawKey: %.*H\n", rawKeyLen, rawKey);
|
||||
offset += KEY_ID_SIZE;
|
||||
|
||||
uint8_t algorithmId = workBuffer[offset];
|
||||
PRINTF("Algorithm: %d\n", algorithmId);
|
||||
|
||||
if (algorithmId != ALGORITHM_ID_1) {
|
||||
PRINTF("Incorrect algorithmId %d\n", algorithmId);
|
||||
if (workBuffer[offset] != ALGORITHM_ID_1) {
|
||||
PRINTF("Incorrect algorithmId %d\n", workBuffer[offset]);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
offset += ALGORITHM_ID_SIZE;
|
||||
|
||||
PRINTF("hashing: %.*H\n", payloadSize, workBuffer);
|
||||
cx_hash_sha256(workBuffer, payloadSize, hash, sizeof(hash));
|
||||
|
||||
@@ -171,7 +157,7 @@ void handleProvideNFTInformation(uint8_t p1,
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
|
||||
uint8_t signatureLen = workBuffer[offset];
|
||||
signatureLen = workBuffer[offset];
|
||||
PRINTF("Signature len: %d\n", signatureLen);
|
||||
if (signatureLen < MIN_DER_SIG_SIZE || signatureLen > MAX_DER_SIG_SIZE) {
|
||||
PRINTF("SignatureLen too big or too small. Must be between %d and %d, got %d\n",
|
||||
@@ -187,17 +173,21 @@ void handleProvideNFTInformation(uint8_t p1,
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
|
||||
CX_ASSERT(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1, rawKey, rawKeyLen, &nftKey));
|
||||
if (!cx_ecdsa_verify_no_throw(&nftKey,
|
||||
hash,
|
||||
sizeof(hash),
|
||||
(uint8_t *) workBuffer + offset,
|
||||
signatureLen)) {
|
||||
#ifndef HAVE_BYPASS_SIGNATURES
|
||||
PRINTF("Invalid NFT signature\n");
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
error = check_signature_with_pubkey("NFT Info",
|
||||
hash,
|
||||
sizeof(hash),
|
||||
LEDGER_NFT_METADATA_PUBLIC_KEY,
|
||||
sizeof(LEDGER_NFT_METADATA_PUBLIC_KEY),
|
||||
#ifdef HAVE_LEDGER_PKI
|
||||
CERTIFICATE_PUBLIC_KEY_USAGE_NFT_METADATA,
|
||||
#endif
|
||||
(uint8_t *) (workBuffer + offset),
|
||||
signatureLen);
|
||||
#ifndef HAVE_BYPASS_SIGNATURES
|
||||
if (error != CX_OK) {
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
#endif
|
||||
|
||||
G_io_apdu_buffer[0] = tmpCtx.transactionContext.currentAssetIndex;
|
||||
validate_current_asset_info();
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
#include "plugin_utils.h"
|
||||
#include "common_ui.h"
|
||||
#include "os_io_seproxyhal.h"
|
||||
#ifdef HAVE_LEDGER_PKI
|
||||
#include "os_pki.h"
|
||||
#endif
|
||||
|
||||
void handleSetExternalPlugin(uint8_t p1,
|
||||
uint8_t p2,
|
||||
@@ -18,41 +21,43 @@ void handleSetExternalPlugin(uint8_t p1,
|
||||
UNUSED(flags);
|
||||
PRINTF("Handling set Plugin\n");
|
||||
uint8_t hash[INT256_LENGTH];
|
||||
cx_ecfp_public_key_t tokenKey;
|
||||
uint8_t pluginNameLength = *workBuffer;
|
||||
uint32_t params[2];
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
|
||||
PRINTF("plugin Name Length: %d\n", pluginNameLength);
|
||||
const size_t payload_size = 1 + pluginNameLength + ADDRESS_LENGTH + SELECTOR_SIZE;
|
||||
|
||||
if (dataLength <= payload_size) {
|
||||
PRINTF("data too small: expected at least %d got %d\n", payload_size, dataLength);
|
||||
THROW(0x6A80);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
|
||||
if (pluginNameLength + 1 > sizeof(dataContext.tokenContext.pluginName)) {
|
||||
PRINTF("name length too big: expected max %d, got %d\n",
|
||||
sizeof(dataContext.tokenContext.pluginName),
|
||||
pluginNameLength + 1);
|
||||
THROW(0x6A80);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
|
||||
// check Ledger's signature over the payload
|
||||
cx_hash_sha256(workBuffer, payload_size, hash, sizeof(hash));
|
||||
CX_ASSERT(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1,
|
||||
LEDGER_SIGNATURE_PUBLIC_KEY,
|
||||
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
|
||||
&tokenKey));
|
||||
if (!cx_ecdsa_verify_no_throw(&tokenKey,
|
||||
hash,
|
||||
sizeof(hash),
|
||||
workBuffer + payload_size,
|
||||
dataLength - payload_size)) {
|
||||
#ifndef HAVE_BYPASS_SIGNATURES
|
||||
PRINTF("Invalid plugin signature %.*H\n",
|
||||
dataLength - payload_size,
|
||||
workBuffer + payload_size);
|
||||
THROW(0x6A80);
|
||||
|
||||
error = check_signature_with_pubkey("External Plugin",
|
||||
hash,
|
||||
sizeof(hash),
|
||||
LEDGER_SIGNATURE_PUBLIC_KEY,
|
||||
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
|
||||
#ifdef HAVE_LEDGER_PKI
|
||||
CERTIFICATE_PUBLIC_KEY_USAGE_COIN_META,
|
||||
#endif
|
||||
(uint8_t *) (workBuffer + payload_size),
|
||||
dataLength - payload_size);
|
||||
#ifndef HAVE_BYPASS_SIGNATURES
|
||||
if (error != CX_OK) {
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
#endif
|
||||
|
||||
// move on to the rest of the payload parsing
|
||||
workBuffer++;
|
||||
@@ -63,7 +68,6 @@ void handleSetExternalPlugin(uint8_t p1,
|
||||
PRINTF("Check external plugin %s\n", dataContext.tokenContext.pluginName);
|
||||
|
||||
// Check if the plugin is present on the device
|
||||
uint32_t params[2];
|
||||
params[0] = (uint32_t) dataContext.tokenContext.pluginName;
|
||||
params[1] = ETH_PLUGIN_CHECK_PRESENCE;
|
||||
BEGIN_TRY {
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
#include "os_io_seproxyhal.h"
|
||||
#include "network.h"
|
||||
#include "public_keys.h"
|
||||
#ifdef HAVE_LEDGER_PKI
|
||||
#include "os_pki.h"
|
||||
#endif
|
||||
|
||||
// Supported internal plugins
|
||||
#define ERC721_STR "ERC721"
|
||||
@@ -82,53 +85,51 @@ void handleSetPlugin(uint8_t p1,
|
||||
UNUSED(flags);
|
||||
PRINTF("Handling set Plugin\n");
|
||||
uint8_t hash[INT256_LENGTH] = {0};
|
||||
cx_ecfp_public_key_t pluginKey = {0};
|
||||
tokenContext_t *tokenContext = &dataContext.tokenContext;
|
||||
|
||||
size_t offset = 0;
|
||||
uint8_t pluginNameLength = 0;
|
||||
size_t payloadSize = 0;
|
||||
uint64_t chain_id = 0;
|
||||
uint8_t signatureLen = 0;
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
#ifdef HAVE_NFT_STAGING_KEY
|
||||
enum KeyId valid_keyId = TEST_PLUGIN_KEY;
|
||||
#else
|
||||
enum KeyId valid_keyId = PROD_PLUGIN_KEY;
|
||||
#endif
|
||||
enum KeyId keyId;
|
||||
uint32_t params[2];
|
||||
|
||||
if (dataLength <= HEADER_SIZE) {
|
||||
PRINTF("Data too small for headers: expected at least %d, got %d\n",
|
||||
HEADER_SIZE,
|
||||
dataLength);
|
||||
THROW(0x6A80);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
|
||||
enum Type type = workBuffer[offset];
|
||||
PRINTF("Type: %d\n", type);
|
||||
switch (type) {
|
||||
case ETH_PLUGIN:
|
||||
break;
|
||||
default:
|
||||
PRINTF("Unsupported type %d\n", type);
|
||||
THROW(0x6a80);
|
||||
break;
|
||||
if (workBuffer[offset] != ETH_PLUGIN) {
|
||||
PRINTF("Unsupported type %d\n", workBuffer[offset]);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
offset += TYPE_SIZE;
|
||||
|
||||
uint8_t version = workBuffer[offset];
|
||||
PRINTF("version: %d\n", version);
|
||||
switch (version) {
|
||||
case VERSION_1:
|
||||
break;
|
||||
default:
|
||||
PRINTF("Unsupported version %d\n", version);
|
||||
THROW(0x6a80);
|
||||
break;
|
||||
if (workBuffer[offset] != VERSION_1) {
|
||||
PRINTF("Unsupported version %d\n", workBuffer[offset]);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
offset += VERSION_SIZE;
|
||||
|
||||
uint8_t pluginNameLength = workBuffer[offset];
|
||||
pluginNameLength = workBuffer[offset];
|
||||
offset += PLUGIN_NAME_LENGTH_SIZE;
|
||||
|
||||
// Size of the payload (everything except the signature)
|
||||
size_t payloadSize = HEADER_SIZE + pluginNameLength + ADDRESS_LENGTH + SELECTOR_SIZE +
|
||||
CHAIN_ID_SIZE + KEY_ID_SIZE + ALGORITHM_ID_SIZE;
|
||||
payloadSize = HEADER_SIZE + pluginNameLength + ADDRESS_LENGTH + SELECTOR_SIZE + CHAIN_ID_SIZE +
|
||||
KEY_ID_SIZE + ALGORITHM_ID_SIZE;
|
||||
if (dataLength < payloadSize) {
|
||||
PRINTF("Data too small for payload: expected at least %d, got %d\n",
|
||||
payloadSize,
|
||||
dataLength);
|
||||
THROW(0x6A80);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
|
||||
// `+ 1` because we want to add a null terminating character.
|
||||
@@ -136,7 +137,7 @@ void handleSetPlugin(uint8_t p1,
|
||||
PRINTF("plugin name too big: expected max %d, got %d\n",
|
||||
sizeof(dataContext.tokenContext.pluginName),
|
||||
pluginNameLength + 1);
|
||||
THROW(0x6A80);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
|
||||
// Safe because we've checked the size before.
|
||||
@@ -155,7 +156,7 @@ void handleSetPlugin(uint8_t p1,
|
||||
PRINTF("Selector: %.*H\n", SELECTOR_SIZE, tokenContext->methodSelector);
|
||||
offset += SELECTOR_SIZE;
|
||||
|
||||
uint64_t chain_id = u64_from_BE(workBuffer + offset, CHAIN_ID_SIZE);
|
||||
chain_id = u64_from_BE(workBuffer + offset, CHAIN_ID_SIZE);
|
||||
// this prints raw data, so to have a more meaningful print, display
|
||||
// the buffer before the endianness swap
|
||||
PRINTF("ChainID: %.*H\n", sizeof(chain_id), (workBuffer + offset));
|
||||
@@ -165,105 +166,86 @@ void handleSetPlugin(uint8_t p1,
|
||||
}
|
||||
offset += CHAIN_ID_SIZE;
|
||||
|
||||
enum KeyId keyId = workBuffer[offset];
|
||||
uint8_t const *rawKey;
|
||||
uint8_t rawKeyLen;
|
||||
|
||||
PRINTF("KeyID: %d\n", keyId);
|
||||
switch (keyId) {
|
||||
#ifdef HAVE_NFT_STAGING_KEY
|
||||
case TEST_PLUGIN_KEY:
|
||||
#endif
|
||||
case PROD_PLUGIN_KEY:
|
||||
rawKey = LEDGER_NFT_SELECTOR_PUBLIC_KEY;
|
||||
rawKeyLen = sizeof(LEDGER_NFT_SELECTOR_PUBLIC_KEY);
|
||||
break;
|
||||
default:
|
||||
PRINTF("KeyID %d not supported\n", keyId);
|
||||
THROW(0x6A80);
|
||||
break;
|
||||
keyId = workBuffer[offset];
|
||||
if (keyId != valid_keyId) {
|
||||
PRINTF("Unsupported KeyID %d\n", keyId);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
|
||||
PRINTF("RawKey: %.*H\n", rawKeyLen, rawKey);
|
||||
offset += KEY_ID_SIZE;
|
||||
|
||||
uint8_t algorithmId = workBuffer[offset];
|
||||
PRINTF("Algorithm: %d\n", algorithmId);
|
||||
|
||||
if (algorithmId != ECC_SECG_P256K1__ECDSA_SHA_256) {
|
||||
PRINTF("Incorrect algorithmId %d\n", algorithmId);
|
||||
THROW(0x6a80);
|
||||
if (workBuffer[offset] != ECC_SECG_P256K1__ECDSA_SHA_256) {
|
||||
PRINTF("Incorrect algorithmId %d\n", workBuffer[offset]);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
offset += ALGORITHM_ID_SIZE;
|
||||
|
||||
PRINTF("hashing: %.*H\n", payloadSize, workBuffer);
|
||||
cx_hash_sha256(workBuffer, payloadSize, hash, sizeof(hash));
|
||||
|
||||
if (dataLength < payloadSize + SIGNATURE_LENGTH_SIZE) {
|
||||
PRINTF("Data too short to hold signature length\n");
|
||||
THROW(0x6a80);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
|
||||
uint8_t signatureLen = workBuffer[offset];
|
||||
signatureLen = workBuffer[offset];
|
||||
PRINTF("Signature len: %d\n", signatureLen);
|
||||
if (signatureLen < MIN_DER_SIG_SIZE || signatureLen > MAX_DER_SIG_SIZE) {
|
||||
PRINTF("SignatureLen too big or too small. Must be between %d and %d, got %d\n",
|
||||
MIN_DER_SIG_SIZE,
|
||||
MAX_DER_SIG_SIZE,
|
||||
signatureLen);
|
||||
THROW(0x6a80);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
offset += SIGNATURE_LENGTH_SIZE;
|
||||
|
||||
if (dataLength < payloadSize + SIGNATURE_LENGTH_SIZE + signatureLen) {
|
||||
PRINTF("Signature could not fit in data\n");
|
||||
THROW(0x6a80);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
|
||||
CX_ASSERT(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1, rawKey, rawKeyLen, &pluginKey));
|
||||
if (!cx_ecdsa_verify_no_throw(&pluginKey,
|
||||
hash,
|
||||
sizeof(hash),
|
||||
(unsigned char *) (workBuffer + offset),
|
||||
signatureLen)) {
|
||||
#ifndef HAVE_BYPASS_SIGNATURES
|
||||
PRINTF("Invalid NFT signature\n");
|
||||
THROW(0x6A80);
|
||||
error = check_signature_with_pubkey("Set Plugin",
|
||||
hash,
|
||||
sizeof(hash),
|
||||
LEDGER_NFT_SELECTOR_PUBLIC_KEY,
|
||||
sizeof(LEDGER_NFT_SELECTOR_PUBLIC_KEY),
|
||||
#ifdef HAVE_LEDGER_PKI
|
||||
CERTIFICATE_PUBLIC_KEY_USAGE_PLUGIN_METADATA,
|
||||
#endif
|
||||
(uint8_t *) (workBuffer + offset),
|
||||
signatureLen);
|
||||
#ifndef HAVE_BYPASS_SIGNATURES
|
||||
if (error != CX_OK) {
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
#endif
|
||||
|
||||
pluginType = getPluginType(tokenContext->pluginName, pluginNameLength);
|
||||
if (keyId == PROD_PLUGIN_KEY) {
|
||||
if (pluginType != ERC721 && pluginType != ERC1155) {
|
||||
PRINTF("AWS key must only be used to set NFT internal plugins\n");
|
||||
THROW(0x6A80);
|
||||
THROW(APDU_RESPONSE_INVALID_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
switch (pluginType) {
|
||||
case EXTERNAL: {
|
||||
PRINTF("Check external plugin %s\n", tokenContext->pluginName);
|
||||
if (pluginType == EXTERNAL) {
|
||||
PRINTF("Check external plugin %s\n", tokenContext->pluginName);
|
||||
|
||||
// Check if the plugin is present on the device
|
||||
uint32_t params[2];
|
||||
params[0] = (uint32_t) tokenContext->pluginName;
|
||||
params[1] = ETH_PLUGIN_CHECK_PRESENCE;
|
||||
BEGIN_TRY {
|
||||
TRY {
|
||||
os_lib_call(params);
|
||||
}
|
||||
CATCH_OTHER(e) {
|
||||
PRINTF("%s external plugin is not present\n", tokenContext->pluginName);
|
||||
memset(tokenContext->pluginName, 0, sizeof(tokenContext->pluginName));
|
||||
THROW(0x6984);
|
||||
}
|
||||
FINALLY {
|
||||
}
|
||||
// Check if the plugin is present on the device
|
||||
params[0] = (uint32_t) tokenContext->pluginName;
|
||||
params[1] = ETH_PLUGIN_CHECK_PRESENCE;
|
||||
BEGIN_TRY {
|
||||
TRY {
|
||||
os_lib_call(params);
|
||||
}
|
||||
CATCH_OTHER(e) {
|
||||
PRINTF("%s external plugin is not present\n", tokenContext->pluginName);
|
||||
memset(tokenContext->pluginName, 0, sizeof(tokenContext->pluginName));
|
||||
THROW(0x6984);
|
||||
}
|
||||
FINALLY {
|
||||
}
|
||||
END_TRY;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
END_TRY;
|
||||
}
|
||||
|
||||
G_io_apdu_buffer[(*tx)++] = 0x90;
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
#include "path.h"
|
||||
#include "ui_logic.h"
|
||||
#include "filtering.h"
|
||||
#ifdef HAVE_LEDGER_PKI
|
||||
#include "os_pki.h"
|
||||
#endif
|
||||
|
||||
#define FILT_MAGIC_MESSAGE_INFO 183
|
||||
#define FILT_MAGIC_AMOUNT_JOIN_TOKEN 11
|
||||
@@ -95,26 +98,26 @@ static bool sig_verif_start(cx_sha256_t *hash_ctx, uint8_t magic) {
|
||||
*/
|
||||
static bool sig_verif_end(cx_sha256_t *hash_ctx, const uint8_t *sig, uint8_t sig_length) {
|
||||
uint8_t hash[INT256_LENGTH];
|
||||
cx_ecfp_public_key_t verifying_key;
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
bool ret_code = false;
|
||||
|
||||
// Finalize hash
|
||||
CX_CHECK(cx_hash_no_throw((cx_hash_t *) hash_ctx, CX_LAST, NULL, 0, hash, INT256_LENGTH));
|
||||
|
||||
CX_CHECK(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1,
|
||||
LEDGER_SIGNATURE_PUBLIC_KEY,
|
||||
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
|
||||
&verifying_key));
|
||||
if (!cx_ecdsa_verify_no_throw(&verifying_key, hash, sizeof(hash), sig, sig_length)) {
|
||||
#ifndef HAVE_BYPASS_SIGNATURES
|
||||
PRINTF("Invalid EIP-712 filtering signature\n");
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
CX_CHECK(check_signature_with_pubkey("EIP712 Filtering",
|
||||
hash,
|
||||
sizeof(hash),
|
||||
LEDGER_SIGNATURE_PUBLIC_KEY,
|
||||
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
|
||||
#ifdef HAVE_LEDGER_PKI
|
||||
CERTIFICATE_PUBLIC_KEY_USAGE_COIN_META,
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
(uint8_t *) (sig),
|
||||
sig_length));
|
||||
|
||||
ret_code = true;
|
||||
end:
|
||||
return false;
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,6 +13,7 @@ disable = C0114, # missing-module-docstring
|
||||
R0912, # too-many-branches
|
||||
R0913, # too-many-arguments
|
||||
R0914, # too-many-locals
|
||||
R0915, # too-many-statements
|
||||
W0603, # global-statement
|
||||
E0401 # import-error
|
||||
extension-pkg-whitelist=hid
|
||||
|
||||
@@ -34,7 +34,7 @@ def common_tx_params() -> dict:
|
||||
abi=json.load(file),
|
||||
address=None
|
||||
)
|
||||
data = contract.encodeABI("approve", [
|
||||
data = contract.encode_abi("approve", [
|
||||
# Uniswap Protocol: Permit2
|
||||
bytes.fromhex("000000000022d473030f116ddee9f6b43ac78ba3"),
|
||||
Web3.to_wei("2", "ether")
|
||||
|
||||
@@ -34,6 +34,7 @@ def common(firmware: Firmware, app_client: EthAppClient) -> int:
|
||||
|
||||
if firmware == Firmware.NANOS:
|
||||
pytest.skip("Not supported on LNS")
|
||||
|
||||
challenge = app_client.get_challenge()
|
||||
return ResponseParser.challenge(challenge.data)
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ from ragger.backend import BackendInterface
|
||||
|
||||
from client.client import EthAppClient, StatusWord
|
||||
|
||||
|
||||
def test_provide_erc20_token(backend: BackendInterface):
|
||||
|
||||
app_client = EthAppClient(backend)
|
||||
@@ -21,7 +20,7 @@ def test_provide_erc20_token_error(backend: BackendInterface):
|
||||
|
||||
addr = bytes.fromhex("e41d2489571d322189246dafa5ebde1f4699f498")
|
||||
sign = bytes.fromhex("deadbeef")
|
||||
with pytest.raises(ExceptionRAPDU) as e:
|
||||
with pytest.raises(ExceptionRAPDU) as err:
|
||||
app_client.provide_token_metadata("ZRX", addr, 18, 1, sign)
|
||||
|
||||
assert e.value.status == StatusWord.INVALID_DATA
|
||||
assert err.value.status == StatusWord.INVALID_DATA
|
||||
|
||||
@@ -65,11 +65,12 @@ def common_test_nft(firmware: Firmware,
|
||||
pass
|
||||
_, DEVICE_ADDR, _ = ResponseParser.pk_addr(app_client.response().data)
|
||||
|
||||
data = collec.contract.encodeABI(action.fn_name, action.fn_args)
|
||||
data = collec.contract.encode_abi(action.fn_name, action.fn_args)
|
||||
app_client.set_plugin(plugin_name,
|
||||
collec.addr,
|
||||
get_selector_from_data(data),
|
||||
collec.chain_id)
|
||||
|
||||
app_client.provide_nft_metadata(collec.name, collec.addr, collec.chain_id)
|
||||
tx_params = {
|
||||
"nonce": NONCE,
|
||||
|
||||
Reference in New Issue
Block a user