diff --git a/tests/speculos/ethereum_client/ethereum_cmd.py b/tests/speculos/ethereum_client/ethereum_cmd.py index a9949b2..50e38c0 100644 --- a/tests/speculos/ethereum_client/ethereum_cmd.py +++ b/tests/speculos/ethereum_client/ethereum_cmd.py @@ -98,6 +98,27 @@ class EthereumCommand: result.append(eth_addr) result.append(chain_code) + + @contextmanager + def perform_privacy_operation(self, bip32_path: str, display: bool = False, shared_secret: bool = False, result: List = list()) -> Tuple[bytes, bytes, bytes]: + try: + chunk: bytes = self.builder.perform_privacy_operation(bip32_path=bip32_path, display=display, shared_secret=shared_secret) + + 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() + print(response) + + except ApduException as error: + raise DeviceException(error_code=error.sw, ins=InsType.INS_PERFORM_PRIVACY_OPERATION) + + # response = Public encryption key or shared secret (32) + assert len(response) == 32 + + result.append(response) + def send_apdu(self, apdu: bytes) -> bytes: try: self.client.apdu_exchange(cla=apdu[0], ins=apdu[1], diff --git a/tests/speculos/ethereum_client/ethereum_cmd_builder.py b/tests/speculos/ethereum_client/ethereum_cmd_builder.py index 92b10a3..594e054 100644 --- a/tests/speculos/ethereum_client/ethereum_cmd_builder.py +++ b/tests/speculos/ethereum_client/ethereum_cmd_builder.py @@ -195,6 +195,30 @@ class EthereumCommandBuilder: p2=0x01, cdata=cdata) + def perform_privacy_operation(self, bip32_path: str, display: bool, shared_secret: bool) -> bytes: + """Command builder for INS_PERFORM_PRIVACY_OPERATION. + + Parameters + ---------- + bip32_path : str + String representation of BIP32 path. + Third party public key on Curve25519 : 32 bytes + Optionnal if returning the shared secret + + """ + bip32_paths: List[bytes] = bip32_path_from_string(bip32_path) + + cdata: bytes = b"".join([ + len(bip32_paths).to_bytes(1, byteorder="big"), + *bip32_paths + ]) + + return self.serialize(cla=self.CLA, + ins=InsType.INS_PERFORM_PRIVACY_OPERATION, + p1=0x01 if display else 0x00, + p2=0x01 if shared_secret else 0x00, + cdata=cdata) + # Not use def sign_tx(self, bip32_path: str, transaction: Transaction) -> Iterator[Tuple[bool, bytes]]: """Command builder for INS_SIGN_TX.