From e7fca8ee88b407bf340bc16829a8d12c56b814be Mon Sep 17 00:00:00 2001 From: Coline Date: Wed, 13 Apr 2022 13:23:37 +0200 Subject: [PATCH] feat: zemu approve test for speculos (hard APDU) --- .../boilerplate_client/boilerplate_cmd.py | 67 ++++++++++++++----- .../boilerplate_cmd_builder.py | 11 +-- tests/speculos/test_sign_cmd.py | 16 +++-- 3 files changed, 68 insertions(+), 26 deletions(-) diff --git a/tests/speculos/boilerplate_client/boilerplate_cmd.py b/tests/speculos/boilerplate_client/boilerplate_cmd.py index a7874ba..f491f1f 100644 --- a/tests/speculos/boilerplate_client/boilerplate_cmd.py +++ b/tests/speculos/boilerplate_client/boilerplate_cmd.py @@ -77,32 +77,65 @@ class BoilerplateCommand: result.append(eth_addr) result.append(chain_code) - def simple_sign_tx(self, bip32_path: str, transaction) -> Tuple[int, int, int]: - chunk: bytes = self.builder.simple_sign_tx(bip32_path=bip32_path, transaction=transaction) - response: bytes = b"" + @contextmanager + def simple_sign_tx(self, bip32_path: str, transaction, result: List = list()) -> Tuple[bytes, bytes, bytes]: + try: + chunk: bytes = self.builder.simple_sign_tx(bip32_path=bip32_path, transaction=transaction) + - with self.client.apdu_exchange_nowait(cla=chunk[0], ins=chunk[1], - p1=chunk[2], p2=chunk[3], - data=chunk[5:]) as exchange: - # Review Transaction - self.client.press_and_release('right') - # Address 1/3, 2/3, 3/3 - self.client.press_and_release('right') - self.client.press_and_release('right') - self.client.press_and_release('right') - # Amount - self.client.press_and_release('right') - # Approve - self.client.press_and_release('both') - response = exchange.receive() + with self.client.apdu_exchange_nowait(cla=chunk[0], ins=chunk[1], + p1=chunk[2], p2=chunk[3], + data=chunk[5:]) as exchange: + yield exchange + response: bytes = exchange.receive() + + except ApduException as error: + raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_TX) + + print("HERE: ", response) # response = V (1) || R (32) || S (32) assert len(response) == 65 v, r, s = struct.unpack("BII", response) + result.append(v) + result.append(r) + result.append(s) + + def test_zemu_hard_apdu_sign(self) -> Tuple[int, int, int]: + sign: bytes = b'\xe0\x04\x00\x00\x80\x05\x80\x00\x00\x2c\x80\x00\x00\x3c\x80\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\xf8\x69\x46\x85\x06\xa8\xb1\x5e\x00\x82\xeb\xeb\x94\x6b\x17\x54\x74\xe8\x90\x94\xc4\x4d\xa9\x8b\x95\x4e\xed\xea\xc4\x95\x27\x1d\x0f\x80\xb8\x44\x09\x5e\xa7\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7d\x27\x68\xde\x32\xb0\xb8\x0b\x7a\x34\x54\xc0\x6b\xda\xc9\x4a\x69\xdd\xc7\xa9\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x80' + provide_erc20: bytes = b'\xe0\x0a\x00\x00\x67\x03\x44\x41\x49\x6b\x17\x54\x74\xe8\x90\x94\xc4\x4d\xa9\x8b\x95\x4e\xed\xea\xc4\x95\x27\x1d\x0f\x00\x00\x00\x12\x00\x00\x00\x01\x30\x45\x02\x21\x00\xb3\xaa\x97\x96\x33\x28\x4e\xb0\xf5\x54\x59\x09\x93\x33\xab\x92\xcf\x06\xfd\xd5\x8d\xc9\x0e\x9c\x07\x00\x00\xc8\xe9\x68\x86\x4c\x02\x20\x7b\x10\xec\x7d\x66\x09\xf5\x1d\xda\x53\xd0\x83\xa6\xe1\x65\xa0\xab\xf3\xa7\x7e\x13\x25\x0e\x6f\x26\x07\x72\x80\x9b\x49\xaf\xf5' + + try: + response = self.client._apdu_exchange( + provide_erc20 + ) # type: int, bytes + + response = self.client._apdu_exchange( + sign + ) + except ApduException as error: + raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_TX) + + # response = V (1) || R (32) || S (32) + assert len(response) == 65 + print(response.hex()) + + offset: int = 0 + + v: bytes = response[offset] + offset += 1 + + r: bytes = response[offset:offset + 32] + offset += 32 + + s: bytes = response[offset:] + return v, r, s + + def sign_tx(self, bip32_path: str, transaction: Transaction) -> Tuple[int, bytes]: sw: int response: bytes = b"" diff --git a/tests/speculos/boilerplate_client/boilerplate_cmd_builder.py b/tests/speculos/boilerplate_client/boilerplate_cmd_builder.py index 2cc54d6..cb50d91 100644 --- a/tests/speculos/boilerplate_client/boilerplate_cmd_builder.py +++ b/tests/speculos/boilerplate_client/boilerplate_cmd_builder.py @@ -1,5 +1,6 @@ import enum import logging +import string import struct from typing import List, Tuple, Union, Iterator, cast @@ -213,15 +214,17 @@ class BoilerplateCommandBuilder: """ bip32_paths: List[bytes] = bip32_path_from_string(bip32_path) + tx_encode = rlp.encode(transaction) + lc = len(bip32_paths) + len(tx_encode) + + hard_length = 5 + fake_data = [0xcc, 0x85, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x85, 0x77, 0x6f, 0x72, 0x6c, 0x64] cdata: bytes = b"".join([ - len(bip32_paths).to_bytes(1, byteorder="big"), + hard_length.to_bytes(1, byteorder="big"), *bip32_paths, - rlp.encode(transaction) ]) - print(cdata) - return self.serialize(cla=self.CLA, ins=InsType.INS_SIGN_TX, p1=0x00, diff --git a/tests/speculos/test_sign_cmd.py b/tests/speculos/test_sign_cmd.py index 21f0c40..8905cdb 100644 --- a/tests/speculos/test_sign_cmd.py +++ b/tests/speculos/test_sign_cmd.py @@ -4,10 +4,16 @@ import struct def test_sign(cmd): - transaction = "dog" - - response = cmd.simple_sign_tx(bip32_path="44'/60'/1'/0/0", transaction=transaction) - - print(response) + # result: list = [] + # transaction = "dog" + # with cmd.simple_sign_tx(bip32_path="44'/60'/1'/0/0", transaction=transaction, result=result) as ex: + # pass + # v, r, s = result + # print("HERE: ", result) + # assert 2 == 1 + v, r, s = cmd.test_zemu_hard_apdu_sign() + assert v == 0x25 + assert r.hex() == "92243511396b65a4faa735a5472ea99b3ce0f7f2338eab426206730bc0ddc57f" + assert s.hex() == "161bc0f861064d840de4f4304cfd19a571017e62df7d8f70cf605c0f025593b6" \ No newline at end of file