add cardano output address validation

pull/25/head
refi93 6 years ago
parent 2b2e2d0145
commit 516dc4608d
No known key found for this signature in database
GPG Key ID: C9499103CDA97FC0

@ -1,3 +1,4 @@
from trezor import log
from trezor.crypto import base58, crc, hashlib
from apps.cardano import cbor
@ -5,6 +6,14 @@ from apps.common import HARDENED
from apps.common.seed import remove_ed25519_prefix
def _encode_address_raw(address_data_encoded):
return base58.encode(
cbor.encode(
[cbor.Tagged(24, address_data_encoded), crc.crc32(address_data_encoded)]
)
)
def derive_address_and_node(keychain, path: list):
node = keychain.derive(path)
@ -16,12 +25,31 @@ def derive_address_and_node(keychain, path: list):
address_data = [address_root, address_attributes, address_type]
address_data_encoded = cbor.encode(address_data)
address = base58.encode(
cbor.encode(
[cbor.Tagged(24, address_data_encoded), crc.crc32(address_data_encoded)]
)
)
return (address, node)
return (_encode_address_raw(address_data_encoded), node)
def is_safe_output_address(address) -> bool:
"""
Determines whether it is safe to include the address as-is as
a tx output, preventing unintended side effects (e.g. CBOR injection)
"""
try:
address_hex = base58.decode(address)
address_unpacked = cbor.decode(address_hex)
except ValueError as e:
if __debug__:
log.exception(__name__, e)
return False
if not isinstance(address_unpacked, list) or len(address_unpacked) != 2:
return False
address_data_encoded = address_unpacked[0]
if not isinstance(address_data_encoded, bytes):
return False
return _encode_address_raw(address_data_encoded) == address
def validate_full_path(path: list) -> bool:

@ -8,7 +8,11 @@ from trezor.messages.CardanoTxRequest import CardanoTxRequest
from trezor.messages.MessageType import CardanoTxAck
from apps.cardano import cbor, seed
from apps.cardano.address import derive_address_and_node, validate_full_path
from apps.cardano.address import (
derive_address_and_node,
is_safe_output_address,
validate_full_path,
)
from apps.cardano.layout import confirm_sending, confirm_transaction, progress
from apps.common.paths import validate_path
from apps.common.seed import remove_ed25519_prefix
@ -184,6 +188,8 @@ class Transaction:
raise wire.ProcessError(
"Each output must have address or address_n field!"
)
if not is_safe_output_address(output.address):
raise wire.ProcessError("Invalid output address!")
outgoing_coins.append(output.amount)
output_addresses.append(output.address)

Loading…
Cancel
Save