mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-08 22:40:59 +00:00
feat(legacy): support external Ethereum definitions
This commit is contained in:
parent
c2c0900c5d
commit
0f07d74063
1
legacy/firmware/.changelog.d/15.added
Normal file
1
legacy/firmware/.changelog.d/15.added
Normal file
@ -0,0 +1 @@
|
||||
Signed Ethereum network and token definitions from host
|
5
legacy/firmware/.gitignore
vendored
5
legacy/firmware/.gitignore
vendored
@ -1,7 +1,8 @@
|
||||
coin_info.[ch]
|
||||
nem_mosaics.[ch]
|
||||
ethereum_networks.h
|
||||
ethereum_tokens.[ch]
|
||||
ethereum_definitions_constants.h
|
||||
ethereum_networks.c
|
||||
ethereum_tokens.c
|
||||
u2f_knownapps.h
|
||||
|
||||
bl_data.h
|
||||
|
@ -61,6 +61,8 @@ OBJS += crypto.o
|
||||
ifneq ($(BITCOIN_ONLY),1)
|
||||
OBJS += u2f.o
|
||||
OBJS += ethereum.o
|
||||
OBJS += ethereum_definitions.o
|
||||
OBJS += ethereum_networks.o
|
||||
OBJS += ethereum_tokens.o
|
||||
OBJS += nem2.o
|
||||
OBJS += nem_mosaics.o
|
||||
@ -140,6 +142,7 @@ OBJS += protob/messages-management.pb.o
|
||||
ifneq ($(BITCOIN_ONLY),1)
|
||||
OBJS += ../vendor/trezor-crypto/cash_addr.o
|
||||
OBJS += protob/messages-ethereum.pb.o
|
||||
OBJS += protob/messages-ethereum-definitions.pb.o
|
||||
OBJS += protob/messages-nem.pb.o
|
||||
OBJS += protob/messages-stellar.pb.o
|
||||
endif
|
||||
|
@ -51,6 +51,7 @@ static uint32_t data_total, data_left;
|
||||
static EthereumTxRequest msg_tx_request;
|
||||
static CONFIDENTIAL uint8_t privkey[32];
|
||||
static uint64_t chain_id;
|
||||
static const char *chain_suffix;
|
||||
static bool eip1559;
|
||||
struct SHA3_CTX keccak_ctx = {0};
|
||||
|
||||
@ -64,6 +65,7 @@ struct signing_params {
|
||||
bool pubkeyhash_set;
|
||||
uint8_t pubkeyhash[20];
|
||||
uint64_t chain_id;
|
||||
const char *chain_suffix;
|
||||
|
||||
uint32_t data_length;
|
||||
uint32_t data_initial_chunk_size;
|
||||
@ -72,7 +74,7 @@ struct signing_params {
|
||||
bool has_to;
|
||||
const char *to;
|
||||
|
||||
const TokenType *token;
|
||||
const EthereumTokenInfo *token;
|
||||
|
||||
uint32_t value_size;
|
||||
const uint8_t *value_bytes;
|
||||
@ -313,30 +315,28 @@ static void send_signature(void) {
|
||||
* using standard ethereum units.
|
||||
* The buffer must be at least 25 bytes.
|
||||
*/
|
||||
static void ethereumFormatAmount(const bignum256 *amnt, const TokenType *token,
|
||||
char *buf, int buflen) {
|
||||
static void ethereumFormatAmount(const bignum256 *amnt,
|
||||
const EthereumTokenInfo *token, char *buf,
|
||||
int buflen) {
|
||||
bignum256 bn1e9 = {0};
|
||||
bn_read_uint32(1000000000, &bn1e9);
|
||||
const char *suffix = NULL;
|
||||
char suffix[50] = {' ', 0};
|
||||
int decimals = 18;
|
||||
if (token == UnknownToken) {
|
||||
strlcpy(buf, "Unknown token value", buflen);
|
||||
return;
|
||||
} else if (token != NULL) {
|
||||
suffix = token->ticker;
|
||||
if (token) {
|
||||
strlcpy(suffix + 1, token->symbol, sizeof(suffix) - 1);
|
||||
decimals = token->decimals;
|
||||
} else if (bn_is_less(amnt, &bn1e9)) {
|
||||
suffix = " Wei";
|
||||
strlcpy(suffix + 1, "Wei", sizeof(suffix) - 1);
|
||||
decimals = 0;
|
||||
} else {
|
||||
ASSIGN_ETHEREUM_SUFFIX(suffix, chain_id);
|
||||
strlcpy(suffix + 1, chain_suffix, sizeof(suffix) - 1);
|
||||
}
|
||||
bn_format(amnt, NULL, suffix, decimals, 0, false, ',', buf, buflen);
|
||||
}
|
||||
|
||||
static void layoutEthereumConfirmTx(const uint8_t *to, uint32_t to_len,
|
||||
const uint8_t *value, uint32_t value_len,
|
||||
const TokenType *token) {
|
||||
const EthereumTokenInfo *token) {
|
||||
bignum256 val = {0};
|
||||
uint8_t pad_val[32] = {0};
|
||||
memzero(pad_val, sizeof(pad_val));
|
||||
@ -508,6 +508,7 @@ static bool ethereum_signing_init_common(struct signing_params *params) {
|
||||
return false;
|
||||
}
|
||||
chain_id = params->chain_id;
|
||||
chain_suffix = params->chain_suffix;
|
||||
|
||||
if (params->data_length > 0) {
|
||||
if (params->data_initial_chunk_size == 0) {
|
||||
@ -550,7 +551,8 @@ static bool ethereum_signing_init_common(struct signing_params *params) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ethereum_signing_handle_erc20(struct signing_params *params) {
|
||||
static void ethereum_signing_handle_erc20(struct signing_params *params,
|
||||
const EthereumTokenInfo *token) {
|
||||
if (params->has_to && ethereum_parse(params->to, params->pubkeyhash)) {
|
||||
params->pubkeyhash_set = true;
|
||||
} else {
|
||||
@ -564,7 +566,7 @@ static void ethereum_signing_handle_erc20(struct signing_params *params) {
|
||||
memcmp(params->data_initial_chunk_bytes,
|
||||
"\xa9\x05\x9c\xbb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
|
||||
16) == 0) {
|
||||
params->token = tokenByChainAddress(chain_id, params->pubkeyhash);
|
||||
params->token = token;
|
||||
}
|
||||
}
|
||||
|
||||
@ -594,10 +596,11 @@ static bool ethereum_signing_confirm_common(
|
||||
return true;
|
||||
}
|
||||
|
||||
void ethereum_signing_init(const EthereumSignTx *msg, const HDNode *node) {
|
||||
void ethereum_signing_init(const EthereumSignTx *msg, const HDNode *node,
|
||||
const EthereumDefinitionsDecoded *defs) {
|
||||
struct signing_params params = {
|
||||
.chain_id = msg->chain_id,
|
||||
|
||||
.chain_suffix = defs->network->symbol,
|
||||
.data_length = msg->data_length,
|
||||
.data_initial_chunk_size = msg->data_initial_chunk.size,
|
||||
.data_initial_chunk_bytes = msg->data_initial_chunk.bytes,
|
||||
@ -634,7 +637,7 @@ void ethereum_signing_init(const EthereumSignTx *msg, const HDNode *node) {
|
||||
}
|
||||
}
|
||||
|
||||
ethereum_signing_handle_erc20(¶ms);
|
||||
ethereum_signing_handle_erc20(¶ms, defs->token);
|
||||
|
||||
if (!ethereum_signing_confirm_common(¶ms)) {
|
||||
fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL);
|
||||
@ -700,9 +703,11 @@ void ethereum_signing_init(const EthereumSignTx *msg, const HDNode *node) {
|
||||
}
|
||||
|
||||
void ethereum_signing_init_eip1559(const EthereumSignTxEIP1559 *msg,
|
||||
const HDNode *node) {
|
||||
const HDNode *node,
|
||||
const EthereumDefinitionsDecoded *defs) {
|
||||
struct signing_params params = {
|
||||
.chain_id = msg->chain_id,
|
||||
.chain_suffix = defs->network->symbol,
|
||||
|
||||
.data_length = msg->data_length,
|
||||
.data_initial_chunk_size = msg->data_initial_chunk.size,
|
||||
@ -729,7 +734,7 @@ void ethereum_signing_init_eip1559(const EthereumSignTxEIP1559 *msg,
|
||||
return;
|
||||
}
|
||||
|
||||
ethereum_signing_handle_erc20(¶ms);
|
||||
ethereum_signing_handle_erc20(¶ms, defs->token);
|
||||
|
||||
if (!ethereum_signing_confirm_common(¶ms)) {
|
||||
fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL);
|
||||
@ -1040,9 +1045,23 @@ bool ethereum_parse(const char *address, uint8_t pubkeyhash[20]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool check_ethereum_slip44_unhardened(
|
||||
uint32_t slip44, const EthereumNetworkInfo *network) {
|
||||
if (is_unknown_network(network)) {
|
||||
// Allow Ethereum or testnet paths for unknown networks.
|
||||
return slip44 == 60 || slip44 == 1;
|
||||
} else if (network->slip44 != 60 && network->slip44 != 1) {
|
||||
// Allow cross-signing with Ethereum unless it's testnet.
|
||||
return (slip44 == network->slip44 || slip44 == 60);
|
||||
} else {
|
||||
return (slip44 == network->slip44);
|
||||
}
|
||||
}
|
||||
|
||||
static bool ethereum_path_check_bip44(uint32_t address_n_count,
|
||||
const uint32_t *address_n,
|
||||
bool pubkey_export, uint64_t chain) {
|
||||
bool pubkey_export,
|
||||
const EthereumNetworkInfo *network) {
|
||||
bool valid = (address_n_count >= 3);
|
||||
valid = valid && (address_n[0] == (PATH_HARDENED | 44));
|
||||
valid = valid && (address_n[1] & PATH_HARDENED);
|
||||
@ -1050,20 +1069,7 @@ static bool ethereum_path_check_bip44(uint32_t address_n_count,
|
||||
valid = valid && ((address_n[2] & PATH_UNHARDEN_MASK) <= PATH_MAX_ACCOUNT);
|
||||
|
||||
uint32_t path_slip44 = address_n[1] & PATH_UNHARDEN_MASK;
|
||||
if (chain == CHAIN_ID_UNKNOWN) {
|
||||
valid = valid && (is_ethereum_slip44(path_slip44));
|
||||
} else {
|
||||
uint32_t chain_slip44 = ethereum_slip44_by_chain_id(chain);
|
||||
if (chain_slip44 == SLIP44_UNKNOWN) {
|
||||
// Allow Ethereum or testnet paths for unknown networks.
|
||||
valid = valid && (path_slip44 == 60 || path_slip44 == 1);
|
||||
} else if (chain_slip44 != 60 && chain_slip44 != 1) {
|
||||
// Allow cross-signing with Ethereum unless it's testnet.
|
||||
valid = valid && (path_slip44 == chain_slip44 || path_slip44 == 60);
|
||||
} else {
|
||||
valid = valid && (path_slip44 == chain_slip44);
|
||||
}
|
||||
}
|
||||
valid = valid && check_ethereum_slip44_unhardened(path_slip44, network);
|
||||
|
||||
if (pubkey_export) {
|
||||
// m/44'/coin_type'/account'/*
|
||||
@ -1101,7 +1107,7 @@ static bool ethereum_path_check_bip44(uint32_t address_n_count,
|
||||
|
||||
static bool ethereum_path_check_casa45(uint32_t address_n_count,
|
||||
const uint32_t *address_n,
|
||||
uint64_t chain) {
|
||||
const EthereumNetworkInfo *network) {
|
||||
bool valid = (address_n_count == 5);
|
||||
valid = valid && (address_n[0] == (PATH_HARDENED | 45));
|
||||
valid = valid && (address_n[1] < PATH_HARDENED);
|
||||
@ -1110,35 +1116,23 @@ static bool ethereum_path_check_casa45(uint32_t address_n_count,
|
||||
valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX);
|
||||
|
||||
uint32_t path_slip44 = address_n[1];
|
||||
if (chain == CHAIN_ID_UNKNOWN) {
|
||||
valid = valid && (is_ethereum_slip44(path_slip44));
|
||||
} else {
|
||||
uint32_t chain_slip44 = ethereum_slip44_by_chain_id(chain);
|
||||
if (chain_slip44 == SLIP44_UNKNOWN) {
|
||||
// Allow Ethereum or testnet paths for unknown networks.
|
||||
valid = valid && (path_slip44 == 60 || path_slip44 == 1);
|
||||
} else if (chain_slip44 != 60 && chain_slip44 != 1) {
|
||||
// Allow cross-signing with Ethereum unless it's testnet.
|
||||
valid = valid && (path_slip44 == chain_slip44 || path_slip44 == 60);
|
||||
} else {
|
||||
valid = valid && (path_slip44 == chain_slip44);
|
||||
}
|
||||
}
|
||||
valid = valid && check_ethereum_slip44_unhardened(path_slip44, network);
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
bool ethereum_path_check(uint32_t address_n_count, const uint32_t *address_n,
|
||||
bool pubkey_export, uint64_t chain) {
|
||||
bool pubkey_export,
|
||||
const EthereumNetworkInfo *network) {
|
||||
if (address_n_count == 0) {
|
||||
return false;
|
||||
}
|
||||
if (address_n[0] == (PATH_HARDENED | 44)) {
|
||||
return ethereum_path_check_bip44(address_n_count, address_n, pubkey_export,
|
||||
chain);
|
||||
network);
|
||||
}
|
||||
if (address_n[0] == (PATH_HARDENED | 45)) {
|
||||
return ethereum_path_check_casa45(address_n_count, address_n, chain);
|
||||
return ethereum_path_check_casa45(address_n_count, address_n, network);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -23,13 +23,16 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "bip32.h"
|
||||
#include "ethereum_definitions.h"
|
||||
#include "messages-ethereum.pb.h"
|
||||
|
||||
#define CHAIN_ID_UNKNOWN UINT64_MAX
|
||||
|
||||
void ethereum_signing_init(const EthereumSignTx *msg, const HDNode *node);
|
||||
void ethereum_signing_init(const EthereumSignTx *msg, const HDNode *node,
|
||||
const EthereumDefinitionsDecoded *defs);
|
||||
void ethereum_signing_init_eip1559(const EthereumSignTxEIP1559 *msg,
|
||||
const HDNode *node);
|
||||
const HDNode *node,
|
||||
const EthereumDefinitionsDecoded *defs);
|
||||
void ethereum_signing_abort(void);
|
||||
void ethereum_signing_txack(const EthereumTxAck *msg);
|
||||
|
||||
@ -42,5 +45,6 @@ void ethereum_typed_hash_sign(const EthereumSignTypedHash *msg,
|
||||
bool ethereum_parse(const char *address, uint8_t pubkeyhash[20]);
|
||||
|
||||
bool ethereum_path_check(uint32_t address_n_count, const uint32_t *address_n,
|
||||
bool pubkey_export, uint64_t chain);
|
||||
bool pubkey_export,
|
||||
const EthereumNetworkInfo *network);
|
||||
#endif
|
||||
|
313
legacy/firmware/ethereum_definitions.c
Normal file
313
legacy/firmware/ethereum_definitions.c
Normal file
@ -0,0 +1,313 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (C) 2022 Martin Novak <martin.novak@satoshilabs.com>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "crypto.h"
|
||||
#include "ethereum.h"
|
||||
#include "ethereum_definitions.h"
|
||||
#include "ethereum_definitions_constants.h"
|
||||
#include "ethereum_networks.h"
|
||||
#include "ethereum_tokens.h"
|
||||
#include "fsm.h"
|
||||
#include "gettext.h"
|
||||
#include "memzero.h"
|
||||
#include "messages.h"
|
||||
#include "pb.h"
|
||||
#include "pb_decode.h"
|
||||
#include "trezor.h" // because of the "VERSTR" macro used in "fsm_sendFailureDebug" function
|
||||
#include "util.h"
|
||||
|
||||
typedef pb_byte_t proof_entry[SHA256_DIGEST_LENGTH];
|
||||
|
||||
struct EncodedDefinition {
|
||||
// prefix
|
||||
pb_byte_t format_version[FORMAT_VERSION_LENGTH];
|
||||
uint8_t definition_type;
|
||||
uint32_t data_version;
|
||||
uint16_t payload_length;
|
||||
|
||||
// payload
|
||||
const pb_byte_t *payload;
|
||||
|
||||
// suffix
|
||||
uint8_t proof_length;
|
||||
const proof_entry *proof;
|
||||
|
||||
const ed25519_signature *signed_root_hash;
|
||||
};
|
||||
|
||||
static bool parse_encoded_definition(struct EncodedDefinition *const result,
|
||||
const pb_size_t size,
|
||||
const pb_byte_t *bytes) {
|
||||
// format version + definition type + data version + payload length + payload
|
||||
// (at least 1B) + proof length + signed Merkle tree root hash
|
||||
if (size < (FORMAT_VERSION_LENGTH + 1 + 4 + 2 + 1 + 1 +
|
||||
MERKLE_TREE_SIGNED_ROOT_SIZE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const pb_byte_t *cursor = bytes;
|
||||
memcpy(result->format_version, cursor, FORMAT_VERSION_LENGTH);
|
||||
cursor += FORMAT_VERSION_LENGTH;
|
||||
|
||||
result->definition_type = *cursor;
|
||||
cursor += 1;
|
||||
|
||||
result->data_version = *(uint32_t *)cursor;
|
||||
cursor += 4;
|
||||
|
||||
result->payload_length = *(uint16_t *)cursor;
|
||||
cursor += 2;
|
||||
|
||||
result->payload = cursor;
|
||||
cursor += result->payload_length;
|
||||
|
||||
if (size <= cursor - bytes) {
|
||||
return false;
|
||||
}
|
||||
result->proof_length = *cursor;
|
||||
cursor += 1;
|
||||
|
||||
// check the whole size of incoming bytes array
|
||||
if (size != (cursor - bytes) + result->proof_length * sizeof(proof_entry) +
|
||||
MERKLE_TREE_SIGNED_ROOT_SIZE) {
|
||||
return false;
|
||||
}
|
||||
result->proof = (proof_entry *)cursor;
|
||||
cursor += result->proof_length * sizeof(proof_entry);
|
||||
|
||||
result->signed_root_hash = (ed25519_signature *)cursor;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool decode_definition(const pb_size_t size, const pb_byte_t *bytes,
|
||||
const EthereumDefinitionType expected_type,
|
||||
void *definition) {
|
||||
// parse received definition
|
||||
static struct EncodedDefinition parsed_def;
|
||||
const char *error_str = _("Invalid Ethereum definition");
|
||||
|
||||
memzero(&parsed_def, sizeof(parsed_def));
|
||||
if (!parse_encoded_definition(&parsed_def, size, bytes)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
// check definition fields
|
||||
if (memcmp(FORMAT_VERSION, parsed_def.format_version,
|
||||
FORMAT_VERSION_LENGTH)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (expected_type != parsed_def.definition_type) {
|
||||
error_str = _("Definition type mismatch");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (MIN_DATA_VERSION > parsed_def.data_version) {
|
||||
error_str = _("Definition is outdated");
|
||||
goto err;
|
||||
}
|
||||
|
||||
// compute Merkle tree root hash from proof
|
||||
uint8_t hash[SHA256_DIGEST_LENGTH] = {0};
|
||||
SHA256_CTX context = {0};
|
||||
sha256_Init(&context);
|
||||
|
||||
// leaf hash = sha256('\x00' + leaf data)
|
||||
sha256_Update(&context, (uint8_t[]){0}, 1);
|
||||
// signed data is everything from start of `bytes` to the end of `payload`
|
||||
const pb_byte_t *payload_end = parsed_def.payload + parsed_def.payload_length;
|
||||
size_t signed_data_size = payload_end - bytes;
|
||||
sha256_Update(&context, bytes, signed_data_size);
|
||||
|
||||
sha256_Final(&context, hash);
|
||||
|
||||
const uint8_t *min, *max;
|
||||
for (uint8_t i = 0; i < parsed_def.proof_length; i++) {
|
||||
sha256_Init(&context);
|
||||
// node hash = sha256('\x01' + min(hash, next_proof) + max(hash,
|
||||
// next_proof))
|
||||
sha256_Update(&context, (uint8_t[]){1}, 1);
|
||||
if (memcmp(hash, parsed_def.proof[i], SHA256_DIGEST_LENGTH) <= 0) {
|
||||
min = hash;
|
||||
max = parsed_def.proof[i];
|
||||
} else {
|
||||
min = parsed_def.proof[i];
|
||||
max = hash;
|
||||
}
|
||||
sha256_Update(&context, min, SHA256_DIGEST_LENGTH);
|
||||
sha256_Update(&context, max, SHA256_DIGEST_LENGTH);
|
||||
sha256_Final(&context, hash);
|
||||
}
|
||||
|
||||
// and verify its signature
|
||||
if (ed25519_sign_open(hash, SHA256_DIGEST_LENGTH, DEFINITIONS_PUBLIC_KEY,
|
||||
*(parsed_def.signed_root_hash)) != 0
|
||||
#if DEBUG_LINK
|
||||
&&
|
||||
ed25519_sign_open(hash, SHA256_DIGEST_LENGTH, DEFINITIONS_DEV_PUBLIC_KEY,
|
||||
*(parsed_def.signed_root_hash)) != 0
|
||||
#endif
|
||||
) {
|
||||
// invalid signature
|
||||
error_str = _("Invalid definition signature");
|
||||
goto err;
|
||||
}
|
||||
|
||||
// decode message
|
||||
const pb_msgdesc_t *fields = (expected_type == EthereumDefinitionType_NETWORK
|
||||
? EthereumNetworkInfo_fields
|
||||
: EthereumTokenInfo_fields);
|
||||
pb_istream_t stream =
|
||||
pb_istream_from_buffer(parsed_def.payload, parsed_def.payload_length);
|
||||
bool status = pb_decode(&stream, fields, definition);
|
||||
if (status) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// fallthrough to error handling in case of decoding failure
|
||||
|
||||
err:
|
||||
memzero(&parsed_def, sizeof(parsed_def));
|
||||
fsm_sendFailure(FailureType_Failure_DataError, error_str);
|
||||
return false;
|
||||
}
|
||||
|
||||
static const EthereumNetworkInfo *get_network(
|
||||
const EncodedNetwork *encoded_network, const uint64_t chain_id,
|
||||
const uint32_t slip44) {
|
||||
static EthereumNetworkInfo decoded_network;
|
||||
const EthereumNetworkInfo *network = &UNKNOWN_NETWORK;
|
||||
|
||||
// try to get built-in definition
|
||||
if (chain_id != CHAIN_ID_UNKNOWN) {
|
||||
network = ethereum_get_network_by_chain_id(chain_id);
|
||||
} else if (slip44 != SLIP44_UNKNOWN) {
|
||||
network = ethereum_get_network_by_slip44(slip44);
|
||||
} else {
|
||||
// if both chain_id and slip44 is unspecified, we do not have anything to
|
||||
// match to the encoded definition, so just short-circuit here
|
||||
return &UNKNOWN_NETWORK;
|
||||
}
|
||||
// if we found built-in definition, or if there's no data to decode, we are
|
||||
// done
|
||||
if (!is_unknown_network(network) || encoded_network == NULL) {
|
||||
return network;
|
||||
}
|
||||
|
||||
// if we still do not have any network definition try to decode received data
|
||||
memzero(&decoded_network, sizeof(decoded_network));
|
||||
if (!decode_definition(encoded_network->size, encoded_network->bytes,
|
||||
EthereumDefinitionType_NETWORK, &decoded_network)) {
|
||||
// error already sent by decode_definition
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (chain_id != CHAIN_ID_UNKNOWN && decoded_network.chain_id != chain_id) {
|
||||
fsm_sendFailure(FailureType_Failure_DataError,
|
||||
_("Network definition mismatch"));
|
||||
return NULL;
|
||||
}
|
||||
if (slip44 != SLIP44_UNKNOWN && decoded_network.slip44 != slip44) {
|
||||
fsm_sendFailure(FailureType_Failure_DataError,
|
||||
_("Network definition mismatch"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &decoded_network;
|
||||
}
|
||||
|
||||
static const EthereumTokenInfo *get_token(const EncodedToken *encoded_token,
|
||||
const uint64_t chain_id,
|
||||
const char *address) {
|
||||
static EthereumTokenInfo decoded_token;
|
||||
|
||||
// if we do not know the chain_id, we cannot get the token
|
||||
if (chain_id == CHAIN_ID_UNKNOWN) {
|
||||
return &UNKNOWN_TOKEN;
|
||||
}
|
||||
|
||||
// convert address string to bytes
|
||||
EthereumTokenInfo_address_t address_bytes;
|
||||
bool address_parsed = address && ethereum_parse(address, address_bytes.bytes);
|
||||
if (!address_parsed) {
|
||||
// without a valid address, we cannot get the token
|
||||
return &UNKNOWN_TOKEN;
|
||||
}
|
||||
|
||||
// try to get built-in definition
|
||||
const EthereumTokenInfo *token =
|
||||
ethereum_token_by_address(chain_id, address_bytes.bytes);
|
||||
if (!is_unknown_token(token) || encoded_token == NULL) {
|
||||
// if we found one, or if there's no data to decode, we are done
|
||||
return token;
|
||||
}
|
||||
|
||||
// try to decode received definition
|
||||
memzero(&decoded_token, sizeof(decoded_token));
|
||||
if (!decode_definition(encoded_token->size, encoded_token->bytes,
|
||||
EthereumDefinitionType_TOKEN, &decoded_token)) {
|
||||
// error already sent by decode_definition
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (decoded_token.chain_id != chain_id ||
|
||||
memcmp(decoded_token.address.bytes, address_bytes.bytes,
|
||||
sizeof(decoded_token.address.bytes))) {
|
||||
// receiving a mismatched token is not an error (we expect being able to get
|
||||
// multiple token definitions in the future, for multiple networks)
|
||||
// but we must not accept the mismatched definition
|
||||
memzero(&decoded_token, sizeof(decoded_token));
|
||||
return &UNKNOWN_TOKEN;
|
||||
}
|
||||
|
||||
return &decoded_token;
|
||||
}
|
||||
|
||||
const EthereumDefinitionsDecoded *ethereum_get_definitions(
|
||||
const EncodedNetwork *encoded_network, const EncodedToken *encoded_token,
|
||||
const uint64_t chain_id, const uint32_t slip44, const char *token_address) {
|
||||
static EthereumDefinitionsDecoded defs;
|
||||
memzero(&defs, sizeof(defs));
|
||||
|
||||
const EthereumNetworkInfo *network =
|
||||
get_network(encoded_network, chain_id, slip44);
|
||||
if (network == NULL) {
|
||||
// error while decoding, failure was sent by get_network
|
||||
return NULL;
|
||||
}
|
||||
defs.network = network;
|
||||
|
||||
if (!is_unknown_network(network) && token_address != NULL) {
|
||||
const EthereumTokenInfo *token =
|
||||
get_token(encoded_token, network->chain_id, token_address);
|
||||
if (token == NULL) {
|
||||
// error while decoding, failure was sent by get_token
|
||||
return NULL;
|
||||
}
|
||||
defs.token = token;
|
||||
} else {
|
||||
defs.token = &UNKNOWN_TOKEN;
|
||||
}
|
||||
|
||||
return &defs;
|
||||
}
|
37
legacy/firmware/ethereum_definitions.h
Normal file
37
legacy/firmware/ethereum_definitions.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (C) 2022 Martin Novak <martin.novak@satoshilabs.com>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ETHEREUM_DEFINITIONS_H__
|
||||
#define __ETHEREUM_DEFINITIONS_H__
|
||||
|
||||
#include "messages-ethereum-definitions.pb.h"
|
||||
|
||||
typedef EthereumDefinitions_encoded_network_t EncodedNetwork;
|
||||
typedef EthereumDefinitions_encoded_token_t EncodedToken;
|
||||
|
||||
typedef struct {
|
||||
const EthereumNetworkInfo *network;
|
||||
const EthereumTokenInfo *token;
|
||||
} EthereumDefinitionsDecoded;
|
||||
|
||||
const EthereumDefinitionsDecoded *ethereum_get_definitions(
|
||||
const EncodedNetwork *encoded_network, const EncodedToken *encoded_token,
|
||||
const uint64_t chain_id, const uint32_t slip44, const char *token_address);
|
||||
|
||||
#endif
|
26
legacy/firmware/ethereum_definitions_constants.h.mako
Normal file
26
legacy/firmware/ethereum_definitions_constants.h.mako
Normal file
@ -0,0 +1,26 @@
|
||||
// This file is automatically generated from ethereum_definitions_constants.h.mako
|
||||
// DO NOT EDIT
|
||||
|
||||
#ifndef __ETHEREUM_DEFINITIONS_CONSTANTS_H__
|
||||
#define __ETHEREUM_DEFINITIONS_CONSTANTS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "crypto.h"
|
||||
#include "messages-ethereum-definitions.pb.h"
|
||||
#include "pb.h"
|
||||
|
||||
static const uint8_t DEFINITIONS_PUBLIC_KEY[] =
|
||||
" "; // TODO: update
|
||||
#if DEBUG_LINK
|
||||
static const uint8_t DEFINITIONS_DEV_PUBLIC_KEY[] =
|
||||
"\xdb\x99\x5f\xe2\x51\x69\xd1\x41\xca\xb9\xbb\xba\x92\xba\xa0\x1f\x9f\x2e"
|
||||
"\x1e\xce\x7d\xf4\xcb\x2a\xc0\x51\x90\xf3\x7f\xcc\x1f\x9d";
|
||||
#endif
|
||||
|
||||
#define MIN_DATA_VERSION ${ethereum_defs_timestamp}
|
||||
#define FORMAT_VERSION_LENGTH 5
|
||||
#define FORMAT_VERSION (const pb_byte_t *)"trzd1"
|
||||
#define MERKLE_TREE_SIGNED_ROOT_SIZE sizeof(ed25519_signature)
|
||||
|
||||
#endif
|
48
legacy/firmware/ethereum_networks.c.mako
Normal file
48
legacy/firmware/ethereum_networks.c.mako
Normal file
@ -0,0 +1,48 @@
|
||||
<% networks = list(supported_on("trezor1", eth)) %>\
|
||||
// This file is automatically generated from ethereum_networks.c.mako
|
||||
// DO NOT EDIT
|
||||
|
||||
#include "ethereum.h"
|
||||
#include "ethereum_networks.h"
|
||||
|
||||
#define NETWORKS_COUNT ${len(networks)}
|
||||
|
||||
static const EthereumNetworkInfo networks[NETWORKS_COUNT] = {
|
||||
% for n in networks:
|
||||
{
|
||||
.chain_id = ${n.chain_id},
|
||||
.slip44 = ${n.slip44},
|
||||
.symbol = ${c_str(n.shortcut)}, /* ${n.name} */
|
||||
.name = "",
|
||||
},
|
||||
% endfor
|
||||
};
|
||||
|
||||
const EthereumNetworkInfo UNKNOWN_NETWORK = {
|
||||
.chain_id = CHAIN_ID_UNKNOWN,
|
||||
.slip44 = SLIP44_UNKNOWN,
|
||||
.symbol = "UNKN",
|
||||
.name = "",
|
||||
};
|
||||
|
||||
const EthereumNetworkInfo *ethereum_get_network_by_chain_id(uint64_t chain_id) {
|
||||
for (size_t i = 0; i < NETWORKS_COUNT; i++) {
|
||||
if (networks[i].chain_id == chain_id) {
|
||||
return &networks[i];
|
||||
}
|
||||
}
|
||||
return &UNKNOWN_NETWORK;
|
||||
}
|
||||
|
||||
const EthereumNetworkInfo *ethereum_get_network_by_slip44(uint32_t slip44) {
|
||||
for (size_t i = 0; i < NETWORKS_COUNT; i++) {
|
||||
if (networks[i].slip44 == slip44) {
|
||||
return &networks[i];
|
||||
}
|
||||
}
|
||||
return &UNKNOWN_NETWORK;
|
||||
}
|
||||
|
||||
bool is_unknown_network(const EthereumNetworkInfo *network) {
|
||||
return network->chain_id == CHAIN_ID_UNKNOWN;
|
||||
}
|
34
legacy/firmware/ethereum_networks.h
Normal file
34
legacy/firmware/ethereum_networks.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (C) 2018 Pavol Rusnak <stick@satoshilabs.com>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ETHEREUM_NETWORKS_H__
|
||||
#define __ETHEREUM_NETWORKS_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "messages-ethereum-definitions.pb.h"
|
||||
|
||||
extern const EthereumNetworkInfo UNKNOWN_NETWORK;
|
||||
#define SLIP44_UNKNOWN UINT32_MAX
|
||||
|
||||
const EthereumNetworkInfo *ethereum_get_network_by_chain_id(uint64_t chain_id);
|
||||
const EthereumNetworkInfo *ethereum_get_network_by_slip44(uint32_t slip44);
|
||||
bool is_unknown_network(const EthereumNetworkInfo *network);
|
||||
|
||||
#endif
|
@ -1,61 +0,0 @@
|
||||
<%
|
||||
BKSL = "\\"
|
||||
|
||||
networks = list(supported_on("trezor1", eth))
|
||||
max_chain_id_length = 0
|
||||
max_slip44_length = 0
|
||||
max_suffix_length = 0
|
||||
for n in networks:
|
||||
max_chain_id_length = max(len(str(n.chain_id)), max_chain_id_length)
|
||||
max_slip44_length = max(len(str(n.slip44)), max_slip44_length)
|
||||
max_suffix_length = max(len(n.shortcut), max_suffix_length)
|
||||
|
||||
def align_chain_id(n):
|
||||
return "{:>{w}}".format(n.chain_id, w=max_chain_id_length)
|
||||
|
||||
def align_slip44(n):
|
||||
return "{:>{w}}".format(n.slip44, w=max_slip44_length)
|
||||
|
||||
def align_suffix(n):
|
||||
cstr = c_str(" " + n.shortcut) + ";"
|
||||
# we add two quotes, a space and a semicolon. hence +4 chars
|
||||
return "{:<{w}}".format(cstr, w=max_suffix_length + 4)
|
||||
|
||||
%>\
|
||||
// This file is automatically generated from ethereum_networks.h.mako
|
||||
// DO NOT EDIT
|
||||
|
||||
#ifndef __ETHEREUM_NETWORKS_H__
|
||||
#define __ETHEREUM_NETWORKS_H__
|
||||
|
||||
#define SLIP44_UNKNOWN UINT32_MAX
|
||||
|
||||
#define ASSIGN_ETHEREUM_SUFFIX(suffix, chain_id) ${BKSL}
|
||||
switch (chain_id) { ${BKSL}
|
||||
% for n in networks:
|
||||
case ${align_chain_id(n)}: suffix = ${align_suffix(n)} break; /* ${n.name} */ ${BKSL}
|
||||
% endfor
|
||||
default: suffix = " UNKN"; break; /* unknown chain */ ${BKSL}
|
||||
}
|
||||
|
||||
static bool is_ethereum_slip44(uint32_t slip44) {
|
||||
switch (slip44) {
|
||||
% for slip44 in sorted(set(n.slip44 for n in networks)):
|
||||
case ${slip44}:
|
||||
% endfor
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t ethereum_slip44_by_chain_id(uint64_t chain_id) {
|
||||
switch (chain_id) {
|
||||
% for n in networks:
|
||||
case ${align_chain_id(n)}: return ${align_slip44(n)}; /* ${n.name} */
|
||||
% endfor
|
||||
default: return SLIP44_UNKNOWN; /* unknown chain */
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -2,24 +2,50 @@
|
||||
// DO NOT EDIT
|
||||
|
||||
#include <string.h>
|
||||
#include "ethereum.h"
|
||||
#include "ethereum_tokens.h"
|
||||
|
||||
const TokenType tokens[TOKENS_COUNT] = {
|
||||
% for t in supported_on("trezor1", erc20):
|
||||
{${"{:>2}".format(t.chain_id)}, ${c_str(t.address_bytes)}, " ${ascii(t.symbol)}", ${t.decimals}}, // ${t.chain} / ${t.name}
|
||||
<% erc20_list = list(supported_on("trezor1", erc20)) %>\
|
||||
#define TOKENS_COUNT ${len(erc20_list)}
|
||||
|
||||
static const EthereumTokenInfo tokens[TOKENS_COUNT] = {
|
||||
% for t in sorted(erc20_list, key=lambda token: (token.chain_id, token.name)):
|
||||
{
|
||||
.symbol = "${ascii(t.symbol)}",
|
||||
.decimals = ${t.decimals},
|
||||
.address = {
|
||||
.size = 20,
|
||||
.bytes = ${c_str(t.address_bytes)}
|
||||
},
|
||||
.chain_id = ${t.chain_id},
|
||||
## .name = "${t.name}"
|
||||
.name = "",
|
||||
},
|
||||
% endfor
|
||||
};
|
||||
|
||||
static const TokenType _UnknownToken = { 0, "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", " UNKN", 0 };
|
||||
const TokenType *UnknownToken = &_UnknownToken;
|
||||
const EthereumTokenInfo UNKNOWN_TOKEN = {
|
||||
.symbol = "Wei UNKN",
|
||||
.decimals = 0,
|
||||
.address = {
|
||||
.size = 20,
|
||||
.bytes = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
|
||||
},
|
||||
.chain_id = CHAIN_ID_UNKNOWN,
|
||||
.name = "",
|
||||
};
|
||||
|
||||
const TokenType *tokenByChainAddress(uint64_t chain_id, const uint8_t *address)
|
||||
const EthereumTokenInfo *ethereum_token_by_address(uint64_t chain_id, const uint8_t *address)
|
||||
{
|
||||
if (!address) return 0;
|
||||
for (int i = 0; i < TOKENS_COUNT; i++) {
|
||||
if (chain_id == tokens[i].chain_id && memcmp(address, tokens[i].address, 20) == 0) {
|
||||
return &(tokens[i]);
|
||||
}
|
||||
}
|
||||
return UnknownToken;
|
||||
if (!address) return 0;
|
||||
for (int i = 0; i < TOKENS_COUNT; i++) {
|
||||
if (chain_id == tokens[i].chain_id && memcmp(address, tokens[i].address.bytes, sizeof(tokens[i].address.bytes)) == 0) {
|
||||
return &(tokens[i]);
|
||||
}
|
||||
}
|
||||
return &UNKNOWN_TOKEN;
|
||||
}
|
||||
|
||||
bool is_unknown_token(const EthereumTokenInfo *token) {
|
||||
return token->chain_id == CHAIN_ID_UNKNOWN;
|
||||
}
|
||||
|
32
legacy/firmware/ethereum_tokens.h
Normal file
32
legacy/firmware/ethereum_tokens.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (C) 2023 Trezor Company s.r.o.
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ETHEREUM_TOKENS_H__
|
||||
#define __ETHEREUM_TOKENS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "ethereum_definitions.h"
|
||||
|
||||
extern const EthereumTokenInfo UNKNOWN_TOKEN;
|
||||
|
||||
const EthereumTokenInfo *ethereum_token_by_address(uint64_t chain_id,
|
||||
const uint8_t *address);
|
||||
bool is_unknown_token(const EthereumTokenInfo *token);
|
||||
|
||||
#endif
|
@ -1,25 +0,0 @@
|
||||
// This file is automatically generated from ethereum_tokens.h.mako
|
||||
// DO NOT EDIT
|
||||
|
||||
#ifndef __ETHEREUM_TOKENS_H__
|
||||
#define __ETHEREUM_TOKENS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
<% erc20_list = list(supported_on("trezor1", erc20)) %>\
|
||||
#define TOKENS_COUNT ${len(erc20_list)}
|
||||
|
||||
typedef struct {
|
||||
uint64_t chain_id;
|
||||
const char * const address;
|
||||
const char * const ticker;
|
||||
int decimals;
|
||||
} TokenType;
|
||||
|
||||
extern const TokenType tokens[TOKENS_COUNT];
|
||||
|
||||
extern const TokenType *UnknownToken;
|
||||
|
||||
const TokenType *tokenByChainAddress(uint64_t chain_id, const uint8_t *address);
|
||||
|
||||
#endif
|
@ -56,6 +56,8 @@
|
||||
|
||||
#if !BITCOIN_ONLY
|
||||
#include "ethereum.h"
|
||||
#include "ethereum_definitions.h"
|
||||
#include "ethereum_networks.h"
|
||||
#include "nem.h"
|
||||
#include "nem2.h"
|
||||
#include "stellar.h"
|
||||
|
@ -19,9 +19,8 @@
|
||||
|
||||
static bool fsm_ethereumCheckPath(uint32_t address_n_count,
|
||||
const uint32_t *address_n, bool pubkey_export,
|
||||
uint64_t chain_id) {
|
||||
if (ethereum_path_check(address_n_count, address_n, pubkey_export,
|
||||
chain_id)) {
|
||||
const EthereumNetworkInfo *network) {
|
||||
if (ethereum_path_check(address_n_count, address_n, pubkey_export, network)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -33,6 +32,38 @@ static bool fsm_ethereumCheckPath(uint32_t address_n_count,
|
||||
return fsm_layoutPathWarning();
|
||||
}
|
||||
|
||||
static const EthereumDefinitionsDecoded *get_definitions(
|
||||
bool has_definitions, const EthereumDefinitions *definitions,
|
||||
uint64_t chain_id, const char *to) {
|
||||
const EncodedNetwork *encoded_network = NULL;
|
||||
const EncodedToken *encoded_token = NULL;
|
||||
if (has_definitions && definitions) {
|
||||
if (definitions->has_encoded_network) {
|
||||
encoded_network = &definitions->encoded_network;
|
||||
}
|
||||
if (definitions->has_encoded_token) {
|
||||
encoded_token = &definitions->encoded_token;
|
||||
}
|
||||
}
|
||||
|
||||
return ethereum_get_definitions(encoded_network, encoded_token, chain_id,
|
||||
SLIP44_UNKNOWN, to);
|
||||
}
|
||||
|
||||
static const EthereumNetworkInfo *get_network_definition_only(
|
||||
bool has_encoded_network, const EncodedNetwork *encoded_network,
|
||||
const uint32_t slip44) {
|
||||
const EncodedNetwork *en = NULL;
|
||||
if (has_encoded_network) {
|
||||
en = encoded_network;
|
||||
}
|
||||
|
||||
const EthereumDefinitionsDecoded *defs =
|
||||
ethereum_get_definitions(en, NULL, CHAIN_ID_UNKNOWN, slip44, NULL);
|
||||
|
||||
return defs ? defs->network : NULL;
|
||||
}
|
||||
|
||||
void fsm_msgEthereumGetPublicKey(const EthereumGetPublicKey *msg) {
|
||||
RESP_INIT(EthereumPublicKey);
|
||||
|
||||
@ -44,12 +75,6 @@ void fsm_msgEthereumGetPublicKey(const EthereumGetPublicKey *msg) {
|
||||
const CoinInfo *coin = fsm_getCoin(true, "Bitcoin");
|
||||
if (!coin) return;
|
||||
|
||||
if (!fsm_ethereumCheckPath(msg->address_n_count, msg->address_n, true,
|
||||
CHAIN_ID_UNKNOWN)) {
|
||||
layoutHome();
|
||||
return;
|
||||
}
|
||||
|
||||
const char *curve = coin->curve_name;
|
||||
uint32_t fingerprint;
|
||||
HDNode *node = fsm_getDerivedNode(curve, msg->address_n, msg->address_n_count,
|
||||
@ -93,8 +118,12 @@ void fsm_msgEthereumSignTx(const EthereumSignTx *msg) {
|
||||
|
||||
CHECK_PIN
|
||||
|
||||
if (!fsm_ethereumCheckPath(msg->address_n_count, msg->address_n, false,
|
||||
msg->chain_id)) {
|
||||
const EthereumDefinitionsDecoded *defs =
|
||||
get_definitions(msg->has_definitions, &msg->definitions, msg->chain_id,
|
||||
msg->has_to ? msg->to : NULL);
|
||||
|
||||
if (!defs || !fsm_ethereumCheckPath(msg->address_n_count, msg->address_n,
|
||||
false, defs->network)) {
|
||||
layoutHome();
|
||||
return;
|
||||
}
|
||||
@ -103,7 +132,7 @@ void fsm_msgEthereumSignTx(const EthereumSignTx *msg) {
|
||||
msg->address_n_count, NULL);
|
||||
if (!node) return;
|
||||
|
||||
ethereum_signing_init(msg, node);
|
||||
ethereum_signing_init(msg, node, defs);
|
||||
}
|
||||
|
||||
void fsm_msgEthereumSignTxEIP1559(const EthereumSignTxEIP1559 *msg) {
|
||||
@ -111,8 +140,12 @@ void fsm_msgEthereumSignTxEIP1559(const EthereumSignTxEIP1559 *msg) {
|
||||
|
||||
CHECK_PIN
|
||||
|
||||
if (!fsm_ethereumCheckPath(msg->address_n_count, msg->address_n, false,
|
||||
msg->chain_id)) {
|
||||
const EthereumDefinitionsDecoded *defs =
|
||||
get_definitions(msg->has_definitions, &msg->definitions, msg->chain_id,
|
||||
msg->has_to ? msg->to : NULL);
|
||||
|
||||
if (!defs || !fsm_ethereumCheckPath(msg->address_n_count, msg->address_n,
|
||||
false, defs->network)) {
|
||||
layoutHome();
|
||||
return;
|
||||
}
|
||||
@ -121,7 +154,7 @@ void fsm_msgEthereumSignTxEIP1559(const EthereumSignTxEIP1559 *msg) {
|
||||
msg->address_n_count, NULL);
|
||||
if (!node) return;
|
||||
|
||||
ethereum_signing_init_eip1559(msg, node);
|
||||
ethereum_signing_init_eip1559(msg, node, defs);
|
||||
}
|
||||
|
||||
void fsm_msgEthereumTxAck(const EthereumTxAck *msg) {
|
||||
@ -137,8 +170,16 @@ void fsm_msgEthereumGetAddress(const EthereumGetAddress *msg) {
|
||||
|
||||
CHECK_PIN
|
||||
|
||||
if (!fsm_ethereumCheckPath(msg->address_n_count, msg->address_n, false,
|
||||
CHAIN_ID_UNKNOWN)) {
|
||||
uint32_t slip44 = (msg->address_n_count > 1)
|
||||
? (msg->address_n[1] & PATH_UNHARDEN_MASK)
|
||||
: SLIP44_UNKNOWN;
|
||||
|
||||
const EthereumNetworkInfo *network = get_network_definition_only(
|
||||
msg->has_encoded_network, (const EncodedNetwork *)&msg->encoded_network,
|
||||
slip44);
|
||||
|
||||
if (!network || !fsm_ethereumCheckPath(msg->address_n_count, msg->address_n,
|
||||
false, network)) {
|
||||
layoutHome();
|
||||
return;
|
||||
}
|
||||
@ -153,9 +194,6 @@ void fsm_msgEthereumGetAddress(const EthereumGetAddress *msg) {
|
||||
layoutHome();
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t slip44 =
|
||||
(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
|
||||
@ -195,8 +233,16 @@ void fsm_msgEthereumSignMessage(const EthereumSignMessage *msg) {
|
||||
|
||||
CHECK_PIN
|
||||
|
||||
if (!fsm_ethereumCheckPath(msg->address_n_count, msg->address_n, false,
|
||||
CHAIN_ID_UNKNOWN)) {
|
||||
uint32_t slip44 = (msg->address_n_count > 1)
|
||||
? (msg->address_n[1] & PATH_UNHARDEN_MASK)
|
||||
: SLIP44_UNKNOWN;
|
||||
|
||||
const EthereumNetworkInfo *network = get_network_definition_only(
|
||||
msg->has_encoded_network, (const EncodedNetwork *)&msg->encoded_network,
|
||||
slip44);
|
||||
|
||||
if (!network || !fsm_ethereumCheckPath(msg->address_n_count, msg->address_n,
|
||||
false, network)) {
|
||||
layoutHome();
|
||||
return;
|
||||
}
|
||||
@ -282,8 +328,16 @@ void fsm_msgEthereumSignTypedHash(const EthereumSignTypedHash *msg) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fsm_ethereumCheckPath(msg->address_n_count, msg->address_n, false,
|
||||
CHAIN_ID_UNKNOWN)) {
|
||||
uint32_t slip44 = (msg->address_n_count > 1)
|
||||
? (msg->address_n[1] & PATH_UNHARDEN_MASK)
|
||||
: SLIP44_UNKNOWN;
|
||||
|
||||
const EthereumNetworkInfo *network = get_network_definition_only(
|
||||
msg->has_encoded_network, (const EncodedNetwork *)&msg->encoded_network,
|
||||
slip44);
|
||||
|
||||
if (!network || !fsm_ethereumCheckPath(msg->address_n_count, msg->address_n,
|
||||
false, network)) {
|
||||
layoutHome();
|
||||
return;
|
||||
}
|
||||
|
@ -14,7 +14,8 @@ SKIPPED_MESSAGES += Ethereum NEM Stellar
|
||||
endif
|
||||
|
||||
PROTO_NAMES = messages messages-bitcoin messages-common messages-crypto messages-debug \
|
||||
messages-ethereum messages-management messages-nem messages-stellar
|
||||
messages-ethereum messages-ethereum-definitions messages-management messages-nem \
|
||||
messages-stellar
|
||||
|
||||
PROTO_OPTIONS = $(PROTO_NAMES:=.options)
|
||||
PROTO_COMPILED = $(PROTO_NAMES:=.pb)
|
||||
|
@ -0,0 +1,9 @@
|
||||
EthereumNetworkInfo.name max_size:256
|
||||
EthereumNetworkInfo.symbol max_size:256
|
||||
|
||||
EthereumTokenInfo.name max_size:256
|
||||
EthereumTokenInfo.address max_size:20
|
||||
EthereumTokenInfo.symbol max_size:256
|
||||
|
||||
EthereumDefinitions.encoded_network max_size:1024
|
||||
EthereumDefinitions.encoded_token max_size:1024
|
1
legacy/firmware/protob/messages-ethereum-definitions.proto
Symbolic link
1
legacy/firmware/protob/messages-ethereum-definitions.proto
Symbolic link
@ -0,0 +1 @@
|
||||
../../vendor/trezor-common/protob/messages-ethereum-definitions.proto
|
@ -26,6 +26,7 @@ EthereumTxAck.data_chunk max_size:1024
|
||||
|
||||
EthereumSignMessage.address_n max_count:8
|
||||
EthereumSignMessage.message max_size:1024
|
||||
EthereumSignMessage.encoded_network max_size:1024
|
||||
|
||||
EthereumVerifyMessage.address max_size:43
|
||||
EthereumVerifyMessage.signature max_size:65
|
||||
@ -37,11 +38,14 @@ EthereumMessageSignature.signature max_size:65
|
||||
EthereumSignTypedHash.address_n max_count:8
|
||||
EthereumSignTypedHash.domain_separator_hash max_size:32
|
||||
EthereumSignTypedHash.message_hash max_size:32
|
||||
EthereumSignTypedHash.encoded_network max_size:1024
|
||||
|
||||
EthereumTypedDataSignature.address max_size:43
|
||||
EthereumTypedDataSignature.signature max_size:65
|
||||
|
||||
EthereumGetAddress.address_n max_count:8
|
||||
EthereumGetAddress.encoded_network max_size:1024
|
||||
|
||||
EthereumGetPublicKey.address_n max_count:8
|
||||
|
||||
EthereumAddress._old_address max_size:20
|
||||
|
Loading…
Reference in New Issue
Block a user