mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-10 15:30:55 +00:00
ethereum: address in messages is now string
This commit is contained in:
parent
5d32308dfb
commit
77a6718f76
@ -421,19 +421,21 @@ static void layoutEthereumFee(const uint8_t *value, uint32_t value_len,
|
||||
* - data (0 ..)
|
||||
*/
|
||||
|
||||
static bool ethereum_signing_check(EthereumSignTx *msg)
|
||||
static bool ethereum_signing_check(const EthereumSignTx *msg)
|
||||
{
|
||||
if (!msg->has_gas_price || !msg->has_gas_limit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (msg->to.size != 20 && msg->to.size != 0) {
|
||||
size_t tolen = msg->has_to ? strlen(msg->to) : 0;
|
||||
|
||||
if (tolen != 42 && tolen != 40 && tolen != 0) {
|
||||
/* Address has wrong length */
|
||||
return false;
|
||||
}
|
||||
|
||||
// sending transaction to address 0 (contract creation) without a data field
|
||||
if (msg->to.size == 0 && (!msg->has_data_length || msg->data_length == 0)) {
|
||||
if (tolen == 0 && (!msg->has_data_length || msg->data_length == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -456,8 +458,15 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node)
|
||||
msg->value.size = 0;
|
||||
if (!msg->has_data_initial_chunk)
|
||||
msg->data_initial_chunk.size = 0;
|
||||
if (!msg->has_to)
|
||||
msg->to.size = 0;
|
||||
bool toset;
|
||||
uint8_t pubkeyhash[20];
|
||||
if (msg->has_to && ethereum_parse(msg->to, pubkeyhash)) {
|
||||
toset = true;
|
||||
} else {
|
||||
msg->to[0] = 0;
|
||||
toset = false;
|
||||
memzero(pubkeyhash, sizeof(pubkeyhash));
|
||||
}
|
||||
if (!msg->has_nonce)
|
||||
msg->nonce.size = 0;
|
||||
|
||||
@ -520,15 +529,15 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node)
|
||||
const TokenType *token = NULL;
|
||||
|
||||
// detect ERC-20 token
|
||||
if (msg->to.size == 20 && msg->value.size == 0 && data_total == 68 && msg->data_initial_chunk.size == 68
|
||||
if (toset && msg->value.size == 0 && data_total == 68 && msg->data_initial_chunk.size == 68
|
||||
&& memcmp(msg->data_initial_chunk.bytes, "\xa9\x05\x9c\xbb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) == 0) {
|
||||
token = tokenByChainAddress(chain_id, msg->to.bytes);
|
||||
token = tokenByChainAddress(chain_id, pubkeyhash);
|
||||
}
|
||||
|
||||
if (token != NULL) {
|
||||
layoutEthereumConfirmTx(msg->data_initial_chunk.bytes + 16, 20, msg->data_initial_chunk.bytes + 36, 32, token);
|
||||
} else {
|
||||
layoutEthereumConfirmTx(msg->to.bytes, msg->to.size, msg->value.bytes, msg->value.size, NULL);
|
||||
layoutEthereumConfirmTx(pubkeyhash, 20, msg->value.bytes, msg->value.size, NULL);
|
||||
}
|
||||
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_SignTx, false)) {
|
||||
@ -563,7 +572,7 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node)
|
||||
rlp_length += rlp_calculate_length(msg->nonce.size, msg->nonce.bytes[0]);
|
||||
rlp_length += rlp_calculate_length(msg->gas_price.size, msg->gas_price.bytes[0]);
|
||||
rlp_length += rlp_calculate_length(msg->gas_limit.size, msg->gas_limit.bytes[0]);
|
||||
rlp_length += rlp_calculate_length(msg->to.size, msg->to.bytes[0]);
|
||||
rlp_length += rlp_calculate_length(toset ? 20 : 0, pubkeyhash[0]);
|
||||
rlp_length += rlp_calculate_length(msg->value.size, msg->value.bytes[0]);
|
||||
rlp_length += rlp_calculate_length(data_total, msg->data_initial_chunk.bytes[0]);
|
||||
if (tx_type) {
|
||||
@ -586,7 +595,7 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node)
|
||||
hash_rlp_field(msg->nonce.bytes, msg->nonce.size);
|
||||
hash_rlp_field(msg->gas_price.bytes, msg->gas_price.size);
|
||||
hash_rlp_field(msg->gas_limit.bytes, msg->gas_limit.size);
|
||||
hash_rlp_field(msg->to.bytes, msg->to.size);
|
||||
hash_rlp_field(pubkeyhash, toset ? 20 : 0);
|
||||
hash_rlp_field(msg->value.bytes, msg->value.size);
|
||||
hash_rlp_length(data_total, msg->data_initial_chunk.bytes[0]);
|
||||
hash_data(msg->data_initial_chunk.bytes, msg->data_initial_chunk.size);
|
||||
@ -663,13 +672,18 @@ static void ethereum_message_hash(const uint8_t *message, size_t message_len, ui
|
||||
|
||||
void ethereum_message_sign(const EthereumSignMessage *msg, const HDNode *node, EthereumMessageSignature *resp)
|
||||
{
|
||||
uint8_t hash[32];
|
||||
|
||||
if (!hdnode_get_ethereum_pubkeyhash(node, resp->address.bytes)) {
|
||||
uint8_t pubkeyhash[20];
|
||||
if (!hdnode_get_ethereum_pubkeyhash(node, pubkeyhash)) {
|
||||
return;
|
||||
}
|
||||
|
||||
resp->has_address = true;
|
||||
resp->address.size = 20;
|
||||
resp->address[0] = '0';
|
||||
resp->address[1] = 'x';
|
||||
ethereum_address_checksum(pubkeyhash, resp->address + 2, false, 0);
|
||||
// ethereum_address_checksum adds trailing zero
|
||||
|
||||
uint8_t hash[32];
|
||||
ethereum_message_hash(msg->message.bytes, msg->message.size, hash);
|
||||
|
||||
uint8_t v;
|
||||
@ -686,8 +700,14 @@ void ethereum_message_sign(const EthereumSignMessage *msg, const HDNode *node, E
|
||||
|
||||
int ethereum_message_verify(const EthereumVerifyMessage *msg)
|
||||
{
|
||||
if (msg->signature.size != 65 || msg->address.size != 20) {
|
||||
fsm_sendFailure(FailureType_Failure_DataError, _("Malformed data"));
|
||||
if (msg->signature.size != 65) {
|
||||
fsm_sendFailure(FailureType_Failure_DataError, _("Malformed signature"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t pubkeyhash[20];
|
||||
if (!ethereum_parse(msg->address, pubkeyhash)) {
|
||||
fsm_sendFailure(FailureType_Failure_DataError, _("Malformed address"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -714,8 +734,40 @@ int ethereum_message_verify(const EthereumVerifyMessage *msg)
|
||||
keccak_Final(&ctx, hash);
|
||||
|
||||
/* result are the least significant 160 bits */
|
||||
if (memcmp(msg->address.bytes, hash + 12, 20) != 0) {
|
||||
if (memcmp(pubkeyhash, hash + 12, 20) != 0) {
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ethereum_parse(const char *address, uint8_t pubkeyhash[20])
|
||||
{
|
||||
memzero(pubkeyhash, 20);
|
||||
size_t len = strlen(address);
|
||||
if (len == 40) {
|
||||
// do nothing
|
||||
} else
|
||||
if (len == 42) {
|
||||
// check for "0x" prefix and strip it when required
|
||||
if (address[0] != '0') return false;
|
||||
if (address[1] != 'x' && address[1] != 'X') return false;
|
||||
address += 2;
|
||||
len -= 2;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (address[i] >= '0' && address[i] <= '9') {
|
||||
pubkeyhash[i / 2] |= (address[i] - '0') << ((1 - (i % 2)) * 4);
|
||||
} else
|
||||
if (address[i] >= 'a' && address[i] <= 'f') {
|
||||
pubkeyhash[i / 2] |= ((address[i] - 'a') + 10) << ((1 - (i % 2)) * 4);
|
||||
} else
|
||||
if (address[i] >= 'A' && address[i] <= 'F') {
|
||||
pubkeyhash[i / 2] |= ((address[i] - 'A') + 10) << ((1 - (i % 2)) * 4);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -31,5 +31,6 @@ void ethereum_signing_txack(const EthereumTxAck *msg);
|
||||
|
||||
void ethereum_message_sign(const EthereumSignMessage *msg, const HDNode *node, EthereumMessageSignature *resp);
|
||||
int ethereum_message_verify(const EthereumVerifyMessage *msg);
|
||||
bool ethereum_parse(const char *address, uint8_t pubkeyhash[20]);
|
||||
|
||||
#endif
|
||||
|
@ -89,28 +89,31 @@ void fsm_msgEthereumGetAddress(const EthereumGetAddress *msg)
|
||||
const HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count, NULL);
|
||||
if (!node) return;
|
||||
|
||||
resp->address.size = 20;
|
||||
uint8_t pubkeyhash[20];
|
||||
|
||||
if (!hdnode_get_ethereum_pubkeyhash(node, resp->address.bytes))
|
||||
if (!hdnode_get_ethereum_pubkeyhash(node, pubkeyhash))
|
||||
return;
|
||||
|
||||
uint32_t slip44 = (msg->address_n_count > 1) ? (msg->address_n[1] & 0x7fffffff) : 0;
|
||||
bool rskip60 = false;
|
||||
uint32_t chain_id = 0;
|
||||
// constants from trezor-common/defs/ethereum/networks.json
|
||||
switch (slip44) {
|
||||
case 137: rskip60 = true; chain_id = 30; break;
|
||||
case 37310: rskip60 = true; chain_id = 31; break;
|
||||
}
|
||||
|
||||
resp->has_address = true;
|
||||
resp->address[0] = '0';
|
||||
resp->address[1] = 'x';
|
||||
ethereum_address_checksum(pubkeyhash, resp->address + 2, rskip60, chain_id);
|
||||
// ethereum_address_checksum adds trailing zero
|
||||
|
||||
if (msg->has_show_display && msg->show_display) {
|
||||
char desc[16];
|
||||
strlcpy(desc, "Address:", sizeof(desc));
|
||||
|
||||
uint32_t slip44 = msg->address_n[1] & 0x7fffffff;
|
||||
bool rskip60 = false;
|
||||
uint32_t chain_id = 0;
|
||||
// constants from trezor-common/defs/ethereum/networks.json
|
||||
switch (slip44) {
|
||||
case 137: rskip60 = true; chain_id = 30; break;
|
||||
case 37310: rskip60 = true; chain_id = 31; break;
|
||||
}
|
||||
|
||||
char address[43] = { '0', 'x' };
|
||||
ethereum_address_checksum(resp->address.bytes, address + 2, rskip60, chain_id);
|
||||
|
||||
if (!fsm_layoutAddress(address, desc, false, 0, msg->address_n, msg->address_n_count, true)) {
|
||||
if (!fsm_layoutAddress(resp->address, desc, false, 0, msg->address_n, msg->address_n_count, true)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -151,9 +154,13 @@ void fsm_msgEthereumVerifyMessage(const EthereumVerifyMessage *msg)
|
||||
return;
|
||||
}
|
||||
|
||||
char address[43] = { '0', 'x' };
|
||||
ethereum_address_checksum(msg->address.bytes, address + 2, false, 0);
|
||||
layoutVerifyAddress(NULL, address);
|
||||
uint8_t pubkeyhash[20];
|
||||
if (!ethereum_parse(msg->address, pubkeyhash)) {
|
||||
fsm_sendFailure(FailureType_Failure_DataError, _("Invalid address"));
|
||||
return;
|
||||
}
|
||||
|
||||
layoutVerifyAddress(NULL, msg->address);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_Other, false)) {
|
||||
fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL);
|
||||
layoutHome();
|
||||
|
@ -2,7 +2,7 @@ EthereumSignTx.address_n max_count:8
|
||||
EthereumSignTx.nonce max_size:32
|
||||
EthereumSignTx.gas_price max_size:32
|
||||
EthereumSignTx.gas_limit max_size:32
|
||||
EthereumSignTx.to max_size:20
|
||||
EthereumSignTx.to max_size:43
|
||||
EthereumSignTx.value max_size:32
|
||||
EthereumSignTx.data_initial_chunk max_size:1024
|
||||
|
||||
@ -14,15 +14,15 @@ EthereumTxAck.data_chunk max_size:1024
|
||||
EthereumSignMessage.address_n max_count:8
|
||||
EthereumSignMessage.message max_size:1024
|
||||
|
||||
EthereumVerifyMessage.address max_size:20
|
||||
EthereumVerifyMessage.address max_size:43
|
||||
EthereumVerifyMessage.signature max_size:65
|
||||
EthereumVerifyMessage.message max_size:1024
|
||||
|
||||
EthereumMessageSignature.address max_size:20
|
||||
EthereumMessageSignature.address max_size:43
|
||||
EthereumMessageSignature.signature max_size:65
|
||||
|
||||
EthereumGetAddress.address_n max_count:8
|
||||
EthereumGetPublicKey.address_n max_count:8
|
||||
|
||||
EthereumAddress.address max_size:20
|
||||
EthereumAddress.address max_size:43
|
||||
EthereumPublicKey.xpub max_size:113
|
||||
|
2
vendor/trezor-common
vendored
2
vendor/trezor-common
vendored
@ -1 +1 @@
|
||||
Subproject commit 78e232cf30d5d30ec1c7f06a740bbc990cc648e9
|
||||
Subproject commit 495b35e212f48ea2ac9e356febd5a49c3ee5254b
|
Loading…
Reference in New Issue
Block a user