From 1b9e575d3ef4de6c7ccbc3f6b0d2964a4133de03 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Tue, 25 Jan 2022 22:50:43 +0100 Subject: [PATCH] refactor(legacy): Move path constants to crypto.h. --- legacy/firmware/crypto.c | 48 ++++++++++++++---------------- legacy/firmware/crypto.h | 6 ++++ legacy/firmware/fsm_msg_coin.h | 2 +- legacy/firmware/fsm_msg_crypto.h | 20 ++++++------- legacy/firmware/fsm_msg_ethereum.h | 2 +- legacy/firmware/layout2.c | 37 ++++++++++++----------- legacy/firmware/u2f.c | 5 ++-- 7 files changed, 63 insertions(+), 57 deletions(-) diff --git a/legacy/firmware/crypto.c b/legacy/firmware/crypto.c index faca68e9c..ddcfc8444 100644 --- a/legacy/firmware/crypto.c +++ b/legacy/firmware/crypto.c @@ -36,10 +36,6 @@ #include "cash_addr.h" #endif -#define PATH_MAX_ACCOUNT 100 -#define PATH_MAX_CHANGE 1 -#define PATH_MAX_ADDRESS_INDEX 1000000 - uint32_t ser_length(uint32_t len, uint8_t *out) { if (len < 253) { out[0] = len & 0xFF; @@ -508,7 +504,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, bool valid = true; // m/44' : BIP44 Legacy // m / purpose' / coin_type' / account' / change / address_index - if (address_n_count > 0 && address_n[0] == (0x80000000 + 44)) { + if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 44)) { if (check_known) { valid = valid && (address_n_count == 5); } else { @@ -520,7 +516,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, valid = valid && (!has_multisig); } if (check_known) { - valid = valid && ((address_n[2] & 0x80000000) == 0x80000000); + valid = valid && (address_n[2] & PATH_HARDENED); valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); valid = valid && (address_n[3] <= PATH_MAX_CHANGE); valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); @@ -528,7 +524,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, return valid; } - if (address_n_count > 0 && address_n[0] == (0x80000000 + 45)) { + if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 45)) { if (check_script_type) { valid = valid && has_multisig; } @@ -556,7 +552,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, script_type == InputScriptType_SPENDMULTISIG); } if (check_known) { - valid = valid && ((address_n[2] & 0x80000000) == 0x80000000); + valid = valid && (address_n[2] & PATH_HARDENED); valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); valid = valid && (address_n[3] <= 1000000); valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); @@ -566,15 +562,15 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, // future. // m/45'/coin_type'/account'/[0-1000000]/change/address_index // m/45'/coin_type/account/[0-1000000]/change/address_index - valid = - valid && check_cointype(coin, 0x80000000 | address_n[1], check_known); + valid = valid && + check_cointype(coin, PATH_HARDENED | address_n[1], check_known); if (check_script_type) { valid = valid && (script_type == InputScriptType_SPENDADDRESS || script_type == InputScriptType_SPENDMULTISIG); } if (check_known) { - valid = valid && - ((address_n[1] & 0x80000000) == (address_n[2] & 0x80000000)); + valid = valid && ((address_n[1] & PATH_HARDENED) == + (address_n[2] & PATH_HARDENED)); valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); valid = valid && (address_n[3] <= 1000000); valid = valid && (address_n[4] <= PATH_MAX_CHANGE); @@ -593,7 +589,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, // m / purpose' / coin_type' / account' / change / address_index // Electrum: // m / purpose' / coin_type' / account' / type' / change / address_index - if (address_n_count > 0 && address_n[0] == (0x80000000 + 48)) { + if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 48)) { if (check_known) { valid = valid && (address_n_count == 5 || address_n_count == 6); } else { @@ -608,13 +604,13 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, script_type == InputScriptType_SPENDWITNESS); } if (check_known) { - valid = valid && ((address_n[2] & 0x80000000) == 0x80000000); + valid = valid && (address_n[2] & PATH_HARDENED); valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); if (address_n_count == 5) { valid = valid && (address_n[3] <= PATH_MAX_CHANGE); valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); } else if (address_n_count == 6) { - valid = valid && ((address_n[3] & 0x80000000) == 0x80000000); + valid = valid && (address_n[3] & PATH_HARDENED); valid = valid && ((address_n[3] & 0x7fffffff) <= 3); valid = valid && (address_n[4] <= PATH_MAX_CHANGE); valid = valid && (address_n[5] <= PATH_MAX_ADDRESS_INDEX); @@ -627,7 +623,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, // m/49' : BIP49 SegWit // m / purpose' / coin_type' / account' / change / address_index - if (address_n_count > 0 && address_n[0] == (0x80000000 + 49)) { + if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 49)) { valid = valid && coin->has_segwit; if (check_known) { valid = valid && (address_n_count == 5); @@ -639,7 +635,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, valid = valid && (script_type == InputScriptType_SPENDP2SHWITNESS); } if (check_known) { - valid = valid && ((address_n[2] & 0x80000000) == 0x80000000); + valid = valid && (address_n[2] & PATH_HARDENED); valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); valid = valid && (address_n[3] <= PATH_MAX_CHANGE); valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); @@ -649,7 +645,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, // m/84' : BIP84 Native SegWit // m / purpose' / coin_type' / account' / change / address_index - if (address_n_count > 0 && address_n[0] == (0x80000000 + 84)) { + if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 84)) { valid = valid && coin->has_segwit; valid = valid && (coin->bech32_prefix != NULL); if (check_known) { @@ -662,7 +658,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, valid = valid && (script_type == InputScriptType_SPENDWITNESS); } if (check_known) { - valid = valid && ((address_n[2] & 0x80000000) == 0x80000000); + valid = valid && (address_n[2] & PATH_HARDENED); valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); valid = valid && (address_n[3] <= PATH_MAX_CHANGE); valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); @@ -672,7 +668,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, // m/86' : BIP86 Taproot // m / purpose' / coin_type' / account' / change / address_index - if (address_n_count > 0 && address_n[0] == (0x80000000 + 86)) { + if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 86)) { valid = valid && coin->has_taproot; valid = valid && (coin->bech32_prefix != NULL); if (check_known) { @@ -687,7 +683,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, valid = valid && (script_type == InputScriptType_SPENDTAPROOT); } if (check_known) { - valid = valid && ((address_n[2] & 0x80000000) == 0x80000000); + valid = valid && (address_n[2] & PATH_HARDENED); valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); valid = valid && (address_n[3] <= PATH_MAX_CHANGE); valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); @@ -708,11 +704,11 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, // Green Address compatibility pattern. Will be removed in the future. // m / 3' / [1-100]' / [1,4] / address_index - if (address_n_count > 0 && address_n[0] == (0x80000000 + 3)) { + if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 3)) { valid = valid && (coin->coin_type == SLIP44_BITCOIN); if (check_known) { valid = valid && (address_n_count == 4); - valid = valid && ((address_n[1] & 0x80000000) == 0x80000000); + valid = valid && (address_n[1] & PATH_HARDENED); valid = valid && ((address_n[1] & 0x7fffffff) <= 100); valid = valid && (address_n[2] == 1 || address_n[2] == 4); valid = valid && (address_n[3] <= PATH_MAX_ADDRESS_INDEX); @@ -744,13 +740,13 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, } else { valid = valid && (address_n_count >= 2); } - valid = - valid && check_cointype(coin, 0x80000000 | address_n[1], check_known); + valid = valid && + check_cointype(coin, PATH_HARDENED | address_n[1], check_known); if (check_script_type) { valid = valid && (script_type == InputScriptType_SPENDP2SHWITNESS); } if (check_known) { - valid = valid && ((address_n[1] & 0x80000000) == 0); + valid = valid && ((address_n[1] & PATH_HARDENED) == 0); valid = valid && (address_n[2] <= PATH_MAX_ACCOUNT); valid = valid && (address_n[3] <= PATH_MAX_CHANGE); valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); diff --git a/legacy/firmware/crypto.h b/legacy/firmware/crypto.h index 2c26b8905..b8675ccb6 100644 --- a/legacy/firmware/crypto.h +++ b/legacy/firmware/crypto.h @@ -38,6 +38,12 @@ typedef enum _CoinPathCheckLevel { CoinPathCheckLevel_SCRIPT_TYPE = 2, } CoinPathCheckLevel; +#define PATH_HARDENED 0x80000000 +#define PATH_UNHARDEN_MASK 0x7fffffff +#define PATH_MAX_ACCOUNT 100 +#define PATH_MAX_CHANGE 1 +#define PATH_MAX_ADDRESS_INDEX 1000000 + #define ser_length_size(len) ((len) < 253 ? 1 : (len) < 0x10000 ? 3 : 5) uint32_t ser_length(uint32_t len, uint8_t *out); diff --git a/legacy/firmware/fsm_msg_coin.h b/legacy/firmware/fsm_msg_coin.h index 778805af1..b36cadb53 100644 --- a/legacy/firmware/fsm_msg_coin.h +++ b/legacy/firmware/fsm_msg_coin.h @@ -37,7 +37,7 @@ void fsm_msgGetPublicKey(const GetPublicKey *msg) { // derive m/0' to obtain root_fingerprint uint32_t root_fingerprint; - uint32_t path[1] = {0x80000000 | 0}; + uint32_t path[1] = {PATH_HARDENED | 0}; HDNode *node = fsm_getDerivedNode(curve, path, 1, &root_fingerprint); if (!node) return; diff --git a/legacy/firmware/fsm_msg_crypto.h b/legacy/firmware/fsm_msg_crypto.h index da9e76cd4..cae8e2bea 100644 --- a/legacy/firmware/fsm_msg_crypto.h +++ b/legacy/firmware/fsm_msg_crypto.h @@ -93,14 +93,14 @@ void fsm_msgSignIdentity(const SignIdentity *msg) { } uint32_t address_n[5]; - address_n[0] = 0x80000000 | 13; - address_n[1] = 0x80000000 | hash[0] | (hash[1] << 8) | (hash[2] << 16) | + address_n[0] = PATH_HARDENED | 13; + address_n[1] = PATH_HARDENED | hash[0] | (hash[1] << 8) | (hash[2] << 16) | ((uint32_t)hash[3] << 24); - address_n[2] = 0x80000000 | hash[4] | (hash[5] << 8) | (hash[6] << 16) | + address_n[2] = PATH_HARDENED | hash[4] | (hash[5] << 8) | (hash[6] << 16) | ((uint32_t)hash[7] << 24); - address_n[3] = 0x80000000 | hash[8] | (hash[9] << 8) | (hash[10] << 16) | + address_n[3] = PATH_HARDENED | hash[8] | (hash[9] << 8) | (hash[10] << 16) | ((uint32_t)hash[11] << 24); - address_n[4] = 0x80000000 | hash[12] | (hash[13] << 8) | (hash[14] << 16) | + address_n[4] = PATH_HARDENED | hash[12] | (hash[13] << 8) | (hash[14] << 16) | ((uint32_t)hash[15] << 24); const char *curve = SECP256K1_NAME; @@ -196,14 +196,14 @@ void fsm_msgGetECDHSessionKey(const GetECDHSessionKey *msg) { } uint32_t address_n[5]; - address_n[0] = 0x80000000 | 17; - address_n[1] = 0x80000000 | hash[0] | (hash[1] << 8) | (hash[2] << 16) | + address_n[0] = PATH_HARDENED | 17; + address_n[1] = PATH_HARDENED | hash[0] | (hash[1] << 8) | (hash[2] << 16) | ((uint32_t)hash[3] << 24); - address_n[2] = 0x80000000 | hash[4] | (hash[5] << 8) | (hash[6] << 16) | + address_n[2] = PATH_HARDENED | hash[4] | (hash[5] << 8) | (hash[6] << 16) | ((uint32_t)hash[7] << 24); - address_n[3] = 0x80000000 | hash[8] | (hash[9] << 8) | (hash[10] << 16) | + address_n[3] = PATH_HARDENED | hash[8] | (hash[9] << 8) | (hash[10] << 16) | ((uint32_t)hash[11] << 24); - address_n[4] = 0x80000000 | hash[12] | (hash[13] << 8) | (hash[14] << 16) | + address_n[4] = PATH_HARDENED | hash[12] | (hash[13] << 8) | (hash[14] << 16) | ((uint32_t)hash[15] << 24); const char *curve = SECP256K1_NAME; diff --git a/legacy/firmware/fsm_msg_ethereum.h b/legacy/firmware/fsm_msg_ethereum.h index 43337f92d..3ca3b1070 100644 --- a/legacy/firmware/fsm_msg_ethereum.h +++ b/legacy/firmware/fsm_msg_ethereum.h @@ -110,7 +110,7 @@ void fsm_msgEthereumGetAddress(const EthereumGetAddress *msg) { if (!hdnode_get_ethereum_pubkeyhash(node, pubkeyhash)) return; uint32_t slip44 = - (msg->address_n_count > 1) ? (msg->address_n[1] & 0x7fffffff) : 0; + (msg->address_n_count > 1) ? (msg->address_n[1] & PATH_UNHARDEN_MASK) : 0; bool rskip60 = false; uint64_t chain_id = 0; // constants from trezor-common/defs/ethereum/networks.json diff --git a/legacy/firmware/layout2.c b/legacy/firmware/layout2.c index 89daa1a26..adbd22d4f 100644 --- a/legacy/firmware/layout2.c +++ b/legacy/firmware/layout2.c @@ -27,6 +27,7 @@ #include "bignum.h" #include "bitmaps.h" #include "config.h" +#include "crypto.h" #include "gettext.h" #include "layout2.h" #include "memzero.h" @@ -43,10 +44,10 @@ #if !BITCOIN_ONLY static const char *slip44_extras(uint32_t coin_type) { - if ((coin_type & 0x80000000) == 0) { + if ((coin_type & PATH_HARDENED) == 0) { return 0; } - switch (coin_type & 0x7fffffff) { + switch (coin_type & PATH_UNHARDEN_MASK) { case 40: return "EXP"; // Expanse case 43: @@ -82,14 +83,15 @@ static const char *address_n_str(const uint32_t *address_n, // known BIP44/49/84/86 path static char path[100]; if (address_n_count == 5 && - (address_n[0] == (0x80000000 + 44) || address_n[0] == (0x80000000 + 49) || - address_n[0] == (0x80000000 + 84) || - address_n[0] == (0x80000000 + 86)) && - (address_n[1] & 0x80000000) && (address_n[2] & 0x80000000) && + (address_n[0] == (PATH_HARDENED + 44) || + address_n[0] == (PATH_HARDENED + 49) || + address_n[0] == (PATH_HARDENED + 84) || + address_n[0] == (PATH_HARDENED + 86)) && + (address_n[1] & PATH_HARDENED) && (address_n[2] & PATH_HARDENED) && (address_n[3] <= 1) && (address_n[4] <= BIP32_MAX_LAST_ELEMENT)) { - bool taproot = (address_n[0] == (0x80000000 + 86)); - bool native_segwit = (address_n[0] == (0x80000000 + 84)); - bool p2sh_segwit = (address_n[0] == (0x80000000 + 49)); + bool taproot = (address_n[0] == (PATH_HARDENED + 86)); + bool native_segwit = (address_n[0] == (PATH_HARDENED + 84)); + bool p2sh_segwit = (address_n[0] == (PATH_HARDENED + 49)); bool legacy = false; const CoinInfo *coin = coinBySlip44(address_n[1]); const char *abbr = 0; @@ -118,8 +120,8 @@ static const char *address_n_str(const uint32_t *address_n, } } const uint32_t accnum = address_is_account - ? ((address_n[4] & 0x7fffffff) + 1) - : (address_n[2] & 0x7fffffff) + 1; + ? ((address_n[4] & PATH_UNHARDEN_MASK) + 1) + : (address_n[2] & PATH_UNHARDEN_MASK) + 1; if (abbr && accnum < 100) { memzero(path, sizeof(path)); strlcpy(path, abbr, sizeof(path)); @@ -164,11 +166,11 @@ static const char *address_n_str(const uint32_t *address_n, for (int n = (int)address_n_count - 1; n >= 0; n--) { uint32_t i = address_n[n]; - if (i & 0x80000000) { + if (i & PATH_HARDENED) { *c = '\''; c--; } - i = i & 0x7fffffff; + i = i & PATH_UNHARDEN_MASK; do { *c = '0' + (i % 10); c--; @@ -1176,8 +1178,9 @@ void layoutNEMLevy(const NEMMosaicDefinition *definition, uint8_t network) { static inline bool is_slip18(const uint32_t *address_n, size_t address_n_count) { - return address_n_count == 2 && address_n[0] == (0x80000000 + 10018) && - (address_n[1] & 0x80000000) && (address_n[1] & 0x7FFFFFFF) <= 9; + return address_n_count == 2 && address_n[0] == (PATH_HARDENED + 10018) && + (address_n[1] & PATH_HARDENED) && + (address_n[1] & PATH_UNHARDEN_MASK) <= 9; } void layoutCosiCommitSign(const uint32_t *address_n, size_t address_n_count, @@ -1187,10 +1190,10 @@ void layoutCosiCommitSign(const uint32_t *address_n, size_t address_n_count, if (is_slip18(address_n, address_n_count)) { if (final_sign) { strlcpy(desc_buf, _("CoSi sign index #?"), sizeof(desc_buf)); - desc_buf[16] = '0' + (address_n[1] & 0x7FFFFFFF); + desc_buf[16] = '0' + (address_n[1] & PATH_UNHARDEN_MASK); } else { strlcpy(desc_buf, _("CoSi commit index #?"), sizeof(desc_buf)); - desc_buf[18] = '0' + (address_n[1] & 0x7FFFFFFF); + desc_buf[18] = '0' + (address_n[1] & PATH_UNHARDEN_MASK); } desc = desc_buf; } diff --git a/legacy/firmware/u2f.c b/legacy/firmware/u2f.c index 1dbfb7a17..c71c74316 100644 --- a/legacy/firmware/u2f.c +++ b/legacy/firmware/u2f.c @@ -23,6 +23,7 @@ #include "bip32.h" #include "buttons.h" #include "config.h" +#include "crypto.h" #include "curves.h" #include "debug.h" #include "gettext.h" @@ -481,7 +482,7 @@ static const HDNode *generateKeyHandle(const uint8_t app_id[], uint32_t key_path[KEY_PATH_ENTRIES] = {0}; for (uint32_t i = 0; i < KEY_PATH_ENTRIES; i++) { // high bit for hardened keys - key_path[i] = 0x80000000 | random32(); + key_path[i] = PATH_HARDENED | random32(); } // First half of keyhandle is key_path @@ -508,7 +509,7 @@ static const HDNode *validateKeyHandle(const uint8_t app_id[], memcpy(key_path, key_handle, KEY_PATH_LEN); for (unsigned int i = 0; i < KEY_PATH_ENTRIES; i++) { // check high bit for hardened keys - if (!(key_path[i] & 0x80000000)) { + if (!(key_path[i] & PATH_HARDENED)) { return NULL; } }