diff --git a/core/SConscript.firmware b/core/SConscript.firmware index 23a391b72..5bacf966f 100644 --- a/core/SConscript.firmware +++ b/core/SConscript.firmware @@ -463,7 +463,12 @@ if FROZEN: SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/wallet/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/wallet/*/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/wallet/*/*.py', + exclude=[ + SOURCE_PY_DIR + 'apps/wallet/sign_tx/decred.py', + SOURCE_PY_DIR + 'apps/wallet/sign_tx/zcash.py', + ]) + ) if EVERYTHING: SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/binance/*.py')) @@ -505,6 +510,9 @@ if FROZEN: SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/webauthn/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/wallet/sign_tx/decred.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/wallet/sign_tx/zcash.py')) + source_mpy = env.FrozenModule(source=SOURCE_PY, source_dir=SOURCE_PY_DIR, bitcoin_only=BITCOIN_ONLY) source_mpyc = env.FrozenCFile( diff --git a/core/SConscript.unix b/core/SConscript.unix index 87f352c05..790ce72fc 100644 --- a/core/SConscript.unix +++ b/core/SConscript.unix @@ -426,7 +426,12 @@ if FROZEN: SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/wallet/*.py')) - SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/wallet/*/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/wallet/*/*.py', + exclude=[ + SOURCE_PY_DIR + 'apps/wallet/sign_tx/decred.py', + SOURCE_PY_DIR + 'apps/wallet/sign_tx/zcash.py', + ]) + ) if EVERYTHING: SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/binance/*.py')) @@ -468,6 +473,9 @@ if FROZEN: SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/webauthn/*.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/wallet/sign_tx/decred.py')) + SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/wallet/sign_tx/zcash.py')) + source_mpy = env.FrozenModule(source=SOURCE_PY, source_dir=SOURCE_PY_DIR, bitcoin_only=BITCOIN_ONLY) source_mpyc = env.FrozenCFile( diff --git a/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-secp256k1.h b/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-secp256k1.h index 7e8c9bab1..ada940e1e 100644 --- a/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-secp256k1.h +++ b/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-secp256k1.h @@ -80,6 +80,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( mod_trezorcrypto_secp256k1_publickey_obj, 1, 2, mod_trezorcrypto_secp256k1_publickey); +#if !BITCOIN_ONLY + static int ethereum_is_canonical(uint8_t v, uint8_t signature[64]) { (void)signature; return (v & 2) == 0; @@ -98,6 +100,8 @@ enum { CANONICAL_SIG_EOS = 2, }; +#endif + /// def sign( /// secret_key: bytes, /// digest: bytes, @@ -113,6 +117,7 @@ STATIC mp_obj_t mod_trezorcrypto_secp256k1_sign(size_t n_args, mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); mp_get_buffer_raise(args[1], &dig, MP_BUFFER_READ); bool compressed = (n_args < 3) || (args[2] == mp_const_true); +#if !BITCOIN_ONLY mp_int_t canonical = (n_args > 3) ? mp_obj_get_int(args[3]) : 0; int (*is_canonical)(uint8_t by, uint8_t sig[64]) = NULL; switch (canonical) { @@ -123,6 +128,7 @@ STATIC mp_obj_t mod_trezorcrypto_secp256k1_sign(size_t n_args, is_canonical = eos_is_canonical; break; } +#endif if (sk.len != 32) { mp_raise_ValueError("Invalid length of secret key"); } @@ -250,9 +256,11 @@ STATIC const mp_rom_map_elem_t mod_trezorcrypto_secp256k1_globals_table[] = { MP_ROM_PTR(&mod_trezorcrypto_secp256k1_verify_recover_obj)}, {MP_ROM_QSTR(MP_QSTR_multiply), MP_ROM_PTR(&mod_trezorcrypto_secp256k1_multiply_obj)}, +#if !BITCOIN_ONLY {MP_ROM_QSTR(MP_QSTR_CANONICAL_SIG_ETHEREUM), MP_ROM_INT(CANONICAL_SIG_ETHEREUM)}, {MP_ROM_QSTR(MP_QSTR_CANONICAL_SIG_EOS), MP_ROM_INT(CANONICAL_SIG_EOS)}, +#endif }; STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_secp256k1_globals, mod_trezorcrypto_secp256k1_globals_table); diff --git a/core/src/apps/common/signverify.py b/core/src/apps/common/signverify.py index 0bd94df2f..d175d9edc 100644 --- a/core/src/apps/common/signverify.py +++ b/core/src/apps/common/signverify.py @@ -1,7 +1,7 @@ from ubinascii import hexlify +from trezor import utils from trezor.crypto.hashlib import blake256, sha256 -from trezor.utils import HashWriter from apps.wallet.sign_tx.writers import write_varint @@ -11,10 +11,10 @@ if False: def message_digest(coin: CoinType, message: bytes) -> bytes: - if coin.decred: - h = HashWriter(blake256()) + if not utils.BITCOIN_ONLY and coin.decred: + h = utils.HashWriter(blake256()) else: - h = HashWriter(sha256()) + h = utils.HashWriter(sha256()) write_varint(h, len(coin.signed_message_header)) h.extend(coin.signed_message_header) write_varint(h, len(message)) diff --git a/core/src/apps/wallet/sign_tx/scripts.py b/core/src/apps/wallet/sign_tx/scripts.py index 5f1dc7dcc..1aed3a025 100644 --- a/core/src/apps/wallet/sign_tx/scripts.py +++ b/core/src/apps/wallet/sign_tx/scripts.py @@ -1,5 +1,5 @@ +from trezor import utils from trezor.messages.MultisigRedeemScriptType import MultisigRedeemScriptType -from trezor.utils import ensure from apps.common.coininfo import CoinInfo from apps.common.writers import empty_bytearray @@ -31,7 +31,7 @@ def input_script_p2pkh_or_p2sh( def output_script_p2pkh(pubkeyhash: bytes) -> bytearray: - ensure(len(pubkeyhash) == 20) + utils.ensure(len(pubkeyhash) == 20) s = bytearray(25) s[0] = 0x76 # OP_DUP s[1] = 0xA9 # OP_HASH_160 @@ -44,7 +44,7 @@ def output_script_p2pkh(pubkeyhash: bytes) -> bytearray: def output_script_p2sh(scripthash: bytes) -> bytearray: # A9 14 87 - ensure(len(scripthash) == 20) + utils.ensure(len(scripthash) == 20) s = bytearray(23) s[0] = 0xA9 # OP_HASH_160 s[1] = 0x14 # pushing 20 bytes @@ -58,7 +58,7 @@ def script_replay_protection_bip115( ) -> bytearray: if block_hash is None or block_height is None: return bytearray() - ensure(len(block_hash) == 32) + utils.ensure(len(block_hash) == 32) s = bytearray(33) s[0] = 0x20 # 32 bytes for block hash s[1:33] = block_hash # block hash @@ -88,7 +88,7 @@ def output_script_native_p2wpkh_or_p2wsh(witprog: bytes) -> bytearray: # Either: # 00 14 <20-byte-key-hash> # 00 20 <32-byte-script-hash> - ensure(len(witprog) == 20 or len(witprog) == 32) + utils.ensure(len(witprog) == 20 or len(witprog) == 32) w = empty_bytearray(3 + len(witprog)) w.append(0x00) # witness version byte @@ -108,7 +108,7 @@ def output_script_native_p2wpkh_or_p2wsh(witprog: bytes) -> bytearray: def input_script_p2wpkh_in_p2sh(pubkeyhash: bytes) -> bytearray: # 16 00 14 # Signature is moved to the witness. - ensure(len(pubkeyhash) == 20) + utils.ensure(len(pubkeyhash) == 20) w = empty_bytearray(3 + len(pubkeyhash)) w.append(0x16) # length of the data @@ -223,7 +223,7 @@ def input_script_multisig( # length of the result total_length = 0 - if not coin.decred: + if utils.BITCOIN_ONLY or not coin.decred: total_length += 1 # OP_FALSE for s in signatures: total_length += 1 + len(s) + 1 # length, signature, sighash diff --git a/core/src/apps/wallet/sign_tx/signing.py b/core/src/apps/wallet/sign_tx/signing.py index f05554cb1..fca7fe77b 100644 --- a/core/src/apps/wallet/sign_tx/signing.py +++ b/core/src/apps/wallet/sign_tx/signing.py @@ -17,7 +17,6 @@ from trezor.messages.TxRequestSerializedType import TxRequestSerializedType from apps.common import address_type, coininfo, coins, seed from apps.wallet.sign_tx import ( addresses, - decred, helpers, multisig, progress, @@ -25,9 +24,11 @@ from apps.wallet.sign_tx import ( segwit_bip143, tx_weight, writers, - zcash, ) +if not utils.BITCOIN_ONLY: + from apps.wallet.sign_tx import decred, zcash + # the number of bip32 levels used in a wallet (chain and address) _BIP32_WALLET_DEPTH = const(2) @@ -62,10 +63,10 @@ async def check_tx_fee(tx: SignTx, keychain: seed.Keychain): # tx, as the SignTx info is streamed only once h_first = utils.HashWriter(sha256()) # not a real tx hash - if coin.decred: + if not utils.BITCOIN_ONLY and coin.decred: hash143 = decred.DecredPrefixHasher(tx) # pseudo BIP-0143 prefix hashing tx_ser = TxRequestSerializedType() - elif tx.overwintered: + elif not utils.BITCOIN_ONLY and tx.overwintered: if tx.version == 3: branch_id = tx.branch_id or 0x5BA81B19 # Overwinter hash143 = zcash.Zip143(branch_id) # ZIP-0143 transaction hashing @@ -129,7 +130,7 @@ async def check_tx_fee(tx: SignTx, keychain: seed.Keychain): InputScriptType.SPENDADDRESS, InputScriptType.SPENDMULTISIG, ): - if coin.force_bip143 or tx.overwintered: + if coin.force_bip143 or (not utils.BITCOIN_ONLY and tx.overwintered): if not txi.amount: raise SigningError( FailureType.DataError, "Expected input with amount" @@ -146,7 +147,7 @@ async def check_tx_fee(tx: SignTx, keychain: seed.Keychain): else: raise SigningError(FailureType.DataError, "Wrong input script type") - if coin.decred: + if not utils.BITCOIN_ONLY and coin.decred: w_txi = writers.empty_bytearray(8 if i == 0 else 0 + 9 + len(txi.prev_hash)) if i == 0: # serializing first input => prepend headers writers.write_bytes(w_txi, get_tx_header(coin, tx)) @@ -154,7 +155,7 @@ async def check_tx_fee(tx: SignTx, keychain: seed.Keychain): tx_ser.serialized_tx = w_txi tx_req.serialized = tx_ser - if coin.decred: + if not utils.BITCOIN_ONLY and coin.decred: hash143.add_output_count(tx) for o in range(tx.outputs_count): @@ -170,7 +171,7 @@ async def check_tx_fee(tx: SignTx, keychain: seed.Keychain): elif not await helpers.confirm_output(txo, coin): raise SigningError(FailureType.ActionCancelled, "Output cancelled") - if coin.decred: + if not utils.BITCOIN_ONLY and coin.decred: if txo.decred_script_version is not None and txo.decred_script_version != 0: raise SigningError( FailureType.ActionCancelled, @@ -212,7 +213,7 @@ async def check_tx_fee(tx: SignTx, keychain: seed.Keychain): if not await helpers.confirm_total(total_in - change_out, fee, coin): raise SigningError(FailureType.ActionCancelled, "Total cancelled") - if coin.decred: + if not utils.BITCOIN_ONLY and coin.decred: hash143.add_locktime_expiry(tx) return h_first, hash143, segwit, total_in, wallet_path @@ -241,7 +242,7 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): tx_req.details = TxRequestDetailsType() tx_req.serialized = None - if coin.decred: + if not utils.BITCOIN_ONLY and coin.decred: prefix_hash = hash143.prefix_hash() for i_sign in range(tx.inputs_count): @@ -275,7 +276,7 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): tx_ser.signature = None tx_req.serialized = tx_ser - elif coin.force_bip143 or tx.overwintered: + elif coin.force_bip143 or (not utils.BITCOIN_ONLY and tx.overwintered): # STAGE_REQUEST_SEGWIT_INPUT txi_sign = await helpers.request_tx_input(tx_req, i_sign) input_check_wallet_path(txi_sign, wallet_path) @@ -323,7 +324,7 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): tx_req.serialized = tx_ser - elif coin.decred: + elif not utils.BITCOIN_ONLY and coin.decred: txi_sign = await helpers.request_tx_input(tx_req, i_sign) input_check_wallet_path(txi_sign, wallet_path) @@ -397,7 +398,7 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): # same as h_first, checked before signing the digest h_second = utils.HashWriter(sha256()) - if tx.overwintered: + if not utils.BITCOIN_ONLY and tx.overwintered: writers.write_uint32( h_sign, tx.version | zcash.OVERWINTERED ) # nVersion | fOverwintered @@ -453,7 +454,7 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): writers.write_tx_output(h_sign, txo_bin) writers.write_uint32(h_sign, tx.lock_time) - if tx.overwintered: + if not utils.BITCOIN_ONLY and tx.overwintered: writers.write_uint32(h_sign, tx.expiry) # expiryHeight writers.write_varint(h_sign, 0) # nJoinSplit @@ -491,7 +492,7 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): tx_req.serialized = tx_ser - if coin.decred: + if not utils.BITCOIN_ONLY and coin.decred: return await helpers.request_tx_finish(tx_req) for o in range(tx.outputs_count): @@ -564,7 +565,7 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): writers.write_uint32(tx_ser.serialized_tx, tx.lock_time) - if tx.overwintered: + if not utils.BITCOIN_ONLY and tx.overwintered: if tx.version == 3: writers.write_uint32(tx_ser.serialized_tx, tx.expiry) # expiryHeight writers.write_varint(tx_ser.serialized_tx, 0) # nJoinSplit @@ -591,17 +592,17 @@ async def get_prevtx_output_value( # STAGE_REQUEST_2_PREV_META tx = await helpers.request_tx_meta(tx_req, prev_hash) - if coin.decred: + if not utils.BITCOIN_ONLY and coin.decred: txh = utils.HashWriter(blake256()) else: txh = utils.HashWriter(sha256()) - if tx.overwintered: + if not utils.BITCOIN_ONLY and tx.overwintered: writers.write_uint32( txh, tx.version | zcash.OVERWINTERED ) # nVersion | fOverwintered writers.write_uint32(txh, tx.version_group_id) # nVersionGroupId - elif coin.decred: + elif not utils.BITCOIN_ONLY and coin.decred: writers.write_uint32(txh, tx.version | decred.DECRED_SERIALIZE_NO_WITNESS) else: writers.write_uint32(txh, tx.version) # nVersion @@ -613,7 +614,7 @@ async def get_prevtx_output_value( for i in range(tx.inputs_cnt): # STAGE_REQUEST_2_PREV_INPUT txi = await helpers.request_tx_input(tx_req, i, prev_hash) - if coin.decred: + if not utils.BITCOIN_ONLY and coin.decred: writers.write_tx_input_decred(txh, txi) else: writers.write_tx_input(txh, txi) @@ -627,7 +628,8 @@ async def get_prevtx_output_value( if o == prev_index: total_out += txo_bin.amount if ( - coin.decred + not utils.BITCOIN_ONLY + and coin.decred and txo_bin.decred_script_version is not None and txo_bin.decred_script_version != 0 ): @@ -638,7 +640,7 @@ async def get_prevtx_output_value( writers.write_uint32(txh, tx.lock_time) - if tx.overwintered or coin.decred: + if not utils.BITCOIN_ONLY and (tx.overwintered or coin.decred): writers.write_uint32(txh, tx.expiry) ofs = 0 @@ -672,7 +674,7 @@ def get_hash_type(coin: coininfo.CoinInfo) -> int: def get_tx_header(coin: coininfo.CoinInfo, tx: SignTx, segwit: bool = False): w_txi = bytearray() - if tx.overwintered: + if not utils.BITCOIN_ONLY and tx.overwintered: writers.write_uint32( w_txi, tx.version | zcash.OVERWINTERED ) # nVersion | fOverwintered