1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-04-20 09:09:02 +00:00

feat(core): Include address_n in address MAC.

This commit is contained in:
Andrew Kozlik 2025-04-15 09:56:19 +02:00
parent 83f447c429
commit 982e67b711
5 changed files with 21 additions and 8 deletions

View File

@ -101,7 +101,7 @@ async def get_address(msg: GetAddress, keychain: Keychain, coin: CoinInfo) -> Ad
keychain.is_in_keychain(address_n)
and validate_path_against_script_type(coin, msg)
):
mac = get_address_mac(address, coin.slip44, keychain)
mac = get_address_mac(address, coin.slip44, address_n, keychain)
if msg.show_display:
path = address_n_to_str(address_n)

View File

@ -4,22 +4,25 @@ from trezor import utils
if TYPE_CHECKING:
from apps.common.keychain import Keychain
from apps.common.paths import Bip32Path
_ADDRESS_MAC_KEY_PATH = [b"SLIP-0024", b"Address MAC key"]
def check_address_mac(
address: str, mac: bytes, slip44: int, keychain: Keychain
address: str, mac: bytes, slip44: int, address_n: Bip32Path, keychain: Keychain
) -> None:
from trezor import wire
from trezor.crypto import hashlib
expected_mac = get_address_mac(address, slip44, keychain)
expected_mac = get_address_mac(address, slip44, address_n, keychain)
if len(mac) != hashlib.sha256.digest_size or not utils.consteq(expected_mac, mac):
raise wire.DataError("Invalid address MAC.")
def get_address_mac(address: str, slip44: int, keychain: Keychain) -> bytes:
def get_address_mac(
address: str, slip44: int, address_n: Bip32Path, keychain: Keychain
) -> bytes:
from trezor.crypto import hmac
from .writers import write_bytes_unchecked, write_compact_size, write_uint32_le
@ -31,6 +34,9 @@ def get_address_mac(address: str, slip44: int, keychain: Keychain) -> bytes:
mac = utils.HashWriter(hmac(hmac.SHA256, node.key()))
address_bytes = address.encode()
write_uint32_le(mac, slip44)
write_compact_size(mac, len(address_n))
for n in address_n:
write_uint32_le(mac, n)
write_compact_size(mac, len(address_bytes))
write_bytes_unchecked(mac, address_bytes)
return mac.get_digest()

View File

@ -59,12 +59,16 @@ class PaymentRequestVerifier:
elif m.refund_memo is not None:
memo = m.refund_memo
# Unlike in a coin purchase memo, the coin type is implied by the payment request.
check_address_mac(memo.address, memo.mac, slip44_id, keychain)
check_address_mac(
memo.address, memo.mac, slip44_id, memo.address_n, keychain
)
writers.write_uint32_le(self.h_pr, _MEMO_TYPE_REFUND)
writers.write_bytes_prefixed(self.h_pr, memo.address.encode())
elif m.coin_purchase_memo is not None:
memo = m.coin_purchase_memo
check_address_mac(memo.address, memo.mac, memo.coin_type, keychain)
check_address_mac(
memo.address, memo.mac, memo.coin_type, memo.address_n, keychain
)
writers.write_uint32_le(self.h_pr, _MEMO_TYPE_COIN_PURCHASE)
writers.write_uint32_le(self.h_pr, memo.coin_type)
writers.write_bytes_prefixed(self.h_pr, memo.amount.encode())

View File

@ -33,7 +33,7 @@ async def get_address(
address = address_from_bytes(node.ethereum_pubkeyhash(), defs.network)
slip44_id = address_n[1] # it depends on the network (ETH vs ETC...)
mac = get_address_mac(address, paths.unharden(slip44_id), keychain)
mac = get_address_mac(address, paths.unharden(slip44_id), address_n, keychain)
if msg.show_display:
await show_address(

View File

@ -71,7 +71,9 @@ def make_payment_request(
hash_bytes_prefixed(h_pr, memo.text.encode())
elif isinstance(memo, RefundMemo):
msg_memo = messages.RefundMemo(
address=memo.address_resp.address, mac=memo.address_resp.mac
address=memo.address_resp.address,
address_n=memo.address_n,
mac=memo.address_resp.mac,
)
msg_memos.append(messages.PaymentRequestMemo(refund_memo=msg_memo))
memo_type = 2
@ -82,6 +84,7 @@ def make_payment_request(
coin_type=memo.slip44,
amount=memo.amount,
address=memo.address_resp.address,
address_n=memo.address_n,
mac=memo.address_resp.mac,
)
msg_memos.append(messages.PaymentRequestMemo(coin_purchase_memo=msg_memo))