From 7a1e773b49c8d13eb3055261e94c4f20b9e84fa9 Mon Sep 17 00:00:00 2001 From: gabrielkerekes Date: Wed, 29 Jul 2020 11:01:27 +0200 Subject: [PATCH] Validate transaction metadata --- core/src/apps/cardano/helpers/__init__.py | 1 + core/src/apps/cardano/sign_tx.py | 22 +++++- .../test_msg_cardano_sign_transaction.py | 71 ++++++++++++++++++- 3 files changed, 90 insertions(+), 4 deletions(-) diff --git a/core/src/apps/cardano/helpers/__init__.py b/core/src/apps/cardano/helpers/__init__.py index 91d0e1d48a..d748f16865 100644 --- a/core/src/apps/cardano/helpers/__init__.py +++ b/core/src/apps/cardano/helpers/__init__.py @@ -4,3 +4,4 @@ INVALID_ADDRESS = wire.ProcessError("Invalid address") NETWORK_MISMATCH = wire.ProcessError("Output address network mismatch!") INVALID_CERTIFICATE = wire.ProcessError("Invalid certificate") INVALID_WITHDRAWAL = wire.ProcessError("Invalid withdrawal") +INVALID_METADATA = wire.ProcessError("Invalid metadata") diff --git a/core/src/apps/cardano/sign_tx.py b/core/src/apps/cardano/sign_tx.py index a2f48acf81..32f29cd856 100644 --- a/core/src/apps/cardano/sign_tx.py +++ b/core/src/apps/cardano/sign_tx.py @@ -24,6 +24,7 @@ from .address import ( from .byron_address import get_address_attributes from .helpers import ( INVALID_CERTIFICATE, + INVALID_METADATA, INVALID_WITHDRAWAL, network_ids, protocol_magics, @@ -79,9 +80,7 @@ async def sign_tx( _validate_outputs(keychain, msg.outputs, msg.protocol_magic, msg.network_id) _validate_certificates(msg.certificates) _validate_withdrawals(msg.withdrawals) - - if msg.metadata and len(msg.metadata) > MAX_METADATA_LENGTH: - raise wire.ProcessError("Invalid metadata") + _validate_metadata(msg.metadata) # display the transaction in UI await _show_tx(ctx, keychain, msg) @@ -158,6 +157,23 @@ def _validate_withdrawals(withdrawals: List[CardanoTxWithdrawalType]) -> None: raise INVALID_WITHDRAWAL +def _validate_metadata(metadata: bytes) -> None: + if not metadata: + return + + if len(metadata) > MAX_METADATA_LENGTH: + raise INVALID_METADATA + + try: + # this also raises an error if there's some data remaining + decoded = cbor.decode(metadata) + except: + raise INVALID_METADATA + + if not isinstance(decoded, dict): + raise INVALID_METADATA + + def _serialize_tx(keychain: seed.Keychain, msg: CardanoSignTx) -> Tuple[bytes, bytes]: tx_body = _build_tx_body(keychain, msg) tx_hash = _hash_tx_body(tx_body) diff --git a/tests/device_tests/test_msg_cardano_sign_transaction.py b/tests/device_tests/test_msg_cardano_sign_transaction.py index b623d82c54..c79841ebcc 100644 --- a/tests/device_tests/test_msg_cardano_sign_transaction.py +++ b/tests/device_tests/test_msg_cardano_sign_transaction.py @@ -998,7 +998,76 @@ INVALID_VECTORS = [ # withdrawals [], # metadata - "A200A11864A118C843AA00FF01A119012C590202AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "a200a11864a118c843aa00ff01a119012c590202aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + # error message + "Invalid metadata", + ), + # Metadata is a list + ( + # protocol magic + PROTOCOL_MAGICS["mainnet"], + # network id + NETWORK_IDS["mainnet"], + # inputs + [SAMPLE_INPUTS["shelley_input"]], + # outputs + [SAMPLE_OUTPUTS["simple_byron_output"]], + # fee + 42, + # ttl + 10, + # certificates + [], + # withdrawals + [], + # metadata + "82a200a11864a118c843aa00ff01a119012c590100aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0A", + # error message + "Invalid metadata", + ), + # Metadata is incomplete + ( + # protocol magic + PROTOCOL_MAGICS["mainnet"], + # network id + NETWORK_IDS["mainnet"], + # inputs + [SAMPLE_INPUTS["shelley_input"]], + # outputs + [SAMPLE_OUTPUTS["simple_byron_output"]], + # fee + 42, + # ttl + 10, + # certificates + [], + # withdrawals + [], + # metadata + "a200a11864a118c843aa00ff01", + # error message + "Invalid metadata", + ), + # Metadata has leftover data + ( + # protocol magic + PROTOCOL_MAGICS["mainnet"], + # network id + NETWORK_IDS["mainnet"], + # inputs + [SAMPLE_INPUTS["shelley_input"]], + # outputs + [SAMPLE_OUTPUTS["simple_byron_output"]], + # fee + 42, + # ttl + 10, + # certificates + [], + # withdrawals + [], + # metadata + "a200a11864a118c843aa00ff01a119012c590100aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa000000", # error message "Invalid metadata", ),