mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-02-18 10:32:02 +00:00
parent
ccb0cd82b6
commit
c5e927fac2
@ -36,7 +36,7 @@
|
|||||||
|
|
||||||
static bool ethereum_signing = false;
|
static bool ethereum_signing = false;
|
||||||
static uint32_t data_total, data_left;
|
static uint32_t data_total, data_left;
|
||||||
static EthereumTxRequest resp;
|
static EthereumTxRequest msg_tx_request;
|
||||||
static uint8_t privkey[32];
|
static uint8_t privkey[32];
|
||||||
static uint8_t chain_id;
|
static uint8_t chain_id;
|
||||||
struct SHA3_CTX keccak_ctx;
|
struct SHA3_CTX keccak_ctx;
|
||||||
@ -138,9 +138,9 @@ static void send_request_chunk(void)
|
|||||||
? data_left / (data_total/800)
|
? data_left / (data_total/800)
|
||||||
: data_left * 800 / data_total);
|
: data_left * 800 / data_total);
|
||||||
layoutProgress(_("Signing"), progress);
|
layoutProgress(_("Signing"), progress);
|
||||||
resp.has_data_length = true;
|
msg_tx_request.has_data_length = true;
|
||||||
resp.data_length = data_left <= 1024 ? data_left : 1024;
|
msg_tx_request.data_length = data_left <= 1024 ? data_left : 1024;
|
||||||
msg_write(MessageType_MessageType_EthereumTxRequest, &resp);
|
msg_write(MessageType_MessageType_EthereumTxRequest, &msg_tx_request);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ethereum_is_canonic(uint8_t v, uint8_t signature[64])
|
static int ethereum_is_canonic(uint8_t v, uint8_t signature[64])
|
||||||
@ -173,24 +173,24 @@ static void send_signature(void)
|
|||||||
memset(privkey, 0, sizeof(privkey));
|
memset(privkey, 0, sizeof(privkey));
|
||||||
|
|
||||||
/* Send back the result */
|
/* Send back the result */
|
||||||
resp.has_data_length = false;
|
msg_tx_request.has_data_length = false;
|
||||||
|
|
||||||
resp.has_signature_v = true;
|
msg_tx_request.has_signature_v = true;
|
||||||
if (chain_id) {
|
if (chain_id) {
|
||||||
resp.signature_v = v + 2 * chain_id + 35;
|
msg_tx_request.signature_v = v + 2 * chain_id + 35;
|
||||||
} else {
|
} else {
|
||||||
resp.signature_v = v + 27;
|
msg_tx_request.signature_v = v + 27;
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.has_signature_r = true;
|
msg_tx_request.has_signature_r = true;
|
||||||
resp.signature_r.size = 32;
|
msg_tx_request.signature_r.size = 32;
|
||||||
memcpy(resp.signature_r.bytes, sig, 32);
|
memcpy(msg_tx_request.signature_r.bytes, sig, 32);
|
||||||
|
|
||||||
resp.has_signature_s = true;
|
msg_tx_request.has_signature_s = true;
|
||||||
resp.signature_s.size = 32;
|
msg_tx_request.signature_s.size = 32;
|
||||||
memcpy(resp.signature_s.bytes, sig + 32, 32);
|
memcpy(msg_tx_request.signature_s.bytes, sig + 32, 32);
|
||||||
|
|
||||||
msg_write(MessageType_MessageType_EthereumTxRequest, &resp);
|
msg_write(MessageType_MessageType_EthereumTxRequest, &msg_tx_request);
|
||||||
|
|
||||||
ethereum_signing_abort();
|
ethereum_signing_abort();
|
||||||
}
|
}
|
||||||
@ -401,7 +401,7 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node)
|
|||||||
ethereum_signing = true;
|
ethereum_signing = true;
|
||||||
sha3_256_Init(&keccak_ctx);
|
sha3_256_Init(&keccak_ctx);
|
||||||
|
|
||||||
memset(&resp, 0, sizeof(EthereumTxRequest));
|
memset(&msg_tx_request, 0, sizeof(EthereumTxRequest));
|
||||||
/* set fields to 0, to avoid conditions later */
|
/* set fields to 0, to avoid conditions later */
|
||||||
if (!msg->has_value)
|
if (!msg->has_value)
|
||||||
msg->value.size = 0;
|
msg->value.size = 0;
|
||||||
@ -572,3 +572,72 @@ void ethereum_signing_abort(void)
|
|||||||
ethereum_signing = false;
|
ethereum_signing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ethereum_message_hash(const uint8_t *message, size_t message_len, uint8_t hash[32])
|
||||||
|
{
|
||||||
|
struct SHA3_CTX ctx;
|
||||||
|
|
||||||
|
sha3_256_Init(&ctx);
|
||||||
|
sha3_Update(&ctx, message, message_len);
|
||||||
|
keccak_Final(&ctx, hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ethereum_message_sign(EthereumSignMessage *msg, const HDNode *node, EthereumMessageSignature *resp)
|
||||||
|
{
|
||||||
|
uint8_t hash[32];
|
||||||
|
|
||||||
|
if (!hdnode_get_ethereum_pubkeyhash(node, resp->address.bytes)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resp->has_address = true;
|
||||||
|
resp->address.size = 20;
|
||||||
|
ethereum_message_hash(msg->message.bytes, msg->message.size, hash);
|
||||||
|
|
||||||
|
uint8_t v;
|
||||||
|
if (ecdsa_sign_digest(&secp256k1, node->private_key, hash, resp->signature.bytes, &v, ethereum_is_canonic) != 0) {
|
||||||
|
fsm_sendFailure(FailureType_Failure_ProcessError, _("Signing failed"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resp->has_signature = true;
|
||||||
|
resp->signature.bytes[64] = 27 + v;
|
||||||
|
resp->signature.size = 65;
|
||||||
|
msg_write(MessageType_MessageType_EthereumMessageSignature, resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ethereum_message_verify(EthereumVerifyMessage *msg)
|
||||||
|
{
|
||||||
|
if (msg->signature.size != 65
|
||||||
|
|| msg->address.size != 20) {
|
||||||
|
fsm_sendFailure(FailureType_Failure_DataError, _("Malformed data"));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t pubkey[65];
|
||||||
|
uint8_t hash[32];
|
||||||
|
|
||||||
|
ethereum_message_hash(msg->message.bytes, msg->message.size, hash);
|
||||||
|
|
||||||
|
/* v should be 27, 28 but some implementations use 0,1. We are
|
||||||
|
* compatible with both.
|
||||||
|
*/
|
||||||
|
uint8_t v = msg->signature.bytes[64];
|
||||||
|
if (v >= 27)
|
||||||
|
v -= 27;
|
||||||
|
|
||||||
|
if (v >= 2 ||
|
||||||
|
ecdsa_verify_digest_recover(&secp256k1, pubkey, msg->signature.bytes, hash, v) != 0) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SHA3_CTX ctx;
|
||||||
|
sha3_256_Init(&ctx);
|
||||||
|
sha3_Update(&ctx, pubkey + 1, 64);
|
||||||
|
keccak_Final(&ctx, hash);
|
||||||
|
|
||||||
|
/* result are the least significant 160 bits */
|
||||||
|
if (memcmp(msg->address.bytes, hash + 12, 20) != 0) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -29,4 +29,7 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node);
|
|||||||
void ethereum_signing_abort(void);
|
void ethereum_signing_abort(void);
|
||||||
void ethereum_signing_txack(EthereumTxAck *msg);
|
void ethereum_signing_txack(EthereumTxAck *msg);
|
||||||
|
|
||||||
|
void ethereum_message_sign(EthereumSignMessage *msg, const HDNode *node, EthereumMessageSignature *resp);
|
||||||
|
int ethereum_message_verify(EthereumVerifyMessage *msg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -703,6 +703,57 @@ void fsm_msgEthereumGetAddress(EthereumGetAddress *msg)
|
|||||||
layoutHome();
|
layoutHome();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fsm_msgEthereumSignMessage(EthereumSignMessage *msg)
|
||||||
|
{
|
||||||
|
RESP_INIT(EthereumMessageSignature);
|
||||||
|
|
||||||
|
CHECK_INITIALIZED
|
||||||
|
|
||||||
|
layoutSignMessage(msg->message.bytes, msg->message.size);
|
||||||
|
if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) {
|
||||||
|
fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL);
|
||||||
|
layoutHome();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK_PIN
|
||||||
|
|
||||||
|
const HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count);
|
||||||
|
if (!node) return;
|
||||||
|
|
||||||
|
ethereum_message_sign(msg, node, resp);
|
||||||
|
layoutHome();
|
||||||
|
}
|
||||||
|
|
||||||
|
void fsm_msgEthereumVerifyMessage(EthereumVerifyMessage *msg)
|
||||||
|
{
|
||||||
|
CHECK_PARAM(msg->has_address, _("No address provided"));
|
||||||
|
CHECK_PARAM(msg->has_message, _("No message provided"));
|
||||||
|
|
||||||
|
if (ethereum_message_verify(msg) != 0) {
|
||||||
|
fsm_sendFailure(FailureType_Failure_DataError, _("Invalid signature"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char address[41];
|
||||||
|
data2hex(msg->address.bytes, 20, address);
|
||||||
|
layoutVerifyAddress(address);
|
||||||
|
if (!protectButton(ButtonRequestType_ButtonRequest_Other, false)) {
|
||||||
|
fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL);
|
||||||
|
layoutHome();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
layoutVerifyMessage(msg->message.bytes, msg->message.size);
|
||||||
|
if (!protectButton(ButtonRequestType_ButtonRequest_Other, false)) {
|
||||||
|
fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL);
|
||||||
|
layoutHome();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fsm_sendSuccess(_("Message verified"));
|
||||||
|
|
||||||
|
layoutHome();
|
||||||
|
}
|
||||||
|
|
||||||
void fsm_msgEntropyAck(EntropyAck *msg)
|
void fsm_msgEntropyAck(EntropyAck *msg)
|
||||||
{
|
{
|
||||||
if (msg->has_entropy) {
|
if (msg->has_entropy) {
|
||||||
|
@ -62,6 +62,8 @@ void fsm_msgSetU2FCounter(SetU2FCounter *msg);
|
|||||||
void fsm_msgEthereumGetAddress(EthereumGetAddress *msg);
|
void fsm_msgEthereumGetAddress(EthereumGetAddress *msg);
|
||||||
void fsm_msgEthereumSignTx(EthereumSignTx *msg);
|
void fsm_msgEthereumSignTx(EthereumSignTx *msg);
|
||||||
void fsm_msgEthereumTxAck(EthereumTxAck *msg);
|
void fsm_msgEthereumTxAck(EthereumTxAck *msg);
|
||||||
|
void fsm_msgEthereumSignMessage(EthereumSignMessage *msg);
|
||||||
|
void fsm_msgEthereumVerifyMessage(EthereumVerifyMessage *msg);
|
||||||
|
|
||||||
// debug message functions
|
// debug message functions
|
||||||
#if DEBUG_LINK
|
#if DEBUG_LINK
|
||||||
|
Loading…
Reference in New Issue
Block a user