Skip to content

Commit

Permalink
Merge pull request #316 from keepkey/eip712-signing
Browse files Browse the repository at this point in the history
Eip712 signing
  • Loading branch information
markrypt0 authored Jul 22, 2022
2 parents b0e6c13 + 6b398a3 commit 85e266b
Show file tree
Hide file tree
Showing 15 changed files with 181 additions and 44 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.7.2)

project(KeepKeyFirmware

VERSION 7.3.2
VERSION 7.4.0

LANGUAGES C CXX ASM)

Expand Down
2 changes: 1 addition & 1 deletion deps/device-protocol
2 changes: 2 additions & 0 deletions include/keepkey/board/confirm_sm.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
{\
(void)review(ButtonRequestType_ButtonRequest_Other, TITLE, " ");\
}
// Example
// DEBUG_DISPLAY_VAL("sig", "sig %s", 65, resp->signature.bytes[ctr]);
#define DEBUG_DISPLAY_VAL(TITLE,VALNAME,SIZE,BYTES) \
{\
char str[SIZE+1];\
Expand Down
11 changes: 9 additions & 2 deletions include/keepkey/firmware/ethereum.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
#ifndef __ETHEREUM_H__
#define __ETHEREUM_H__

#include "trezor/crypto/bip32.h"

#include <stdint.h>
#include <stdbool.h>
#include "trezor/crypto/bip32.h"
#include "messages-ethereum.pb.h"

typedef struct _EthereumSignTx EthereumSignTx;
typedef struct _EthereumTxAck EthereumTxAck;
Expand Down Expand Up @@ -67,4 +67,11 @@ void ethereumFormatAmount(const bignum256 *amnt, const TokenType *token,

void bn_from_bytes(const uint8_t *value, size_t value_len, bignum256 *val);


void ethereum_typed_hash_sign(const EthereumSignTypedHash *msg,
const HDNode *node,
EthereumTypedDataSignature *resp);
bool ethereum_path_check(uint32_t address_n_count, const uint32_t *address_n,
bool pubkey_export, uint64_t chain);

#endif
8 changes: 5 additions & 3 deletions include/keepkey/firmware/fsm.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,16 @@ void fsm_msgDecryptMessage(DecryptMessage *msg);
void fsm_msgRecoveryDevice(RecoveryDevice *msg);
void fsm_msgWordAck(WordAck *msg);

void fsm_msgCharacterAck(CharacterAck *msg);
void fsm_msgApplyPolicies(ApplyPolicies *msg);

// ethereum
void fsm_msgEthereumGetAddress(EthereumGetAddress *msg);
void fsm_msgEthereumSignTx(EthereumSignTx *msg);
void fsm_msgEthereumTxAck(EthereumTxAck *msg);
void fsm_msgEthereumSignMessage(EthereumSignMessage *msg);
void fsm_msgEthereumVerifyMessage(const EthereumVerifyMessage *msg);

void fsm_msgCharacterAck(CharacterAck *msg);
void fsm_msgApplyPolicies(ApplyPolicies *msg);
void fsm_msgEthereumSignTypedHash(const EthereumSignTypedHash *msg);

void fsm_msgNanoGetAddress(NanoGetAddress *msg);
void fsm_msgNanoSignTx(NanoSignTx *msg);
Expand Down
1 change: 1 addition & 0 deletions include/keepkey/transport/interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "messages-nano.pb.h"
#undef delete

#include "messages-ethereum.pb.h"
#include "messages-binance.pb.h"
#include "messages-cosmos.pb.h"
#include "messages-eos.pb.h"
Expand Down
41 changes: 41 additions & 0 deletions include/keepkey/transport/messages-ethereum.options
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
EthereumGetAddress.address_n max_count:8
EthereumAddress.address max_size:20
EthereumAddress.address_str max_size:43

EthereumSignTx.address_n max_count:8
EthereumSignTx.nonce max_size:32
EthereumSignTx.gas_price max_size:32
EthereumSignTx.gas_limit max_size:32
EthereumSignTx.max_fee_per_gas max_size:32
EthereumSignTx.max_priority_fee_per_gas max_size:32
EthereumSignTx.to max_size:20
EthereumSignTx.value max_size:32
EthereumSignTx.data_initial_chunk max_size:1024
EthereumSignTx.to_address_n max_count:8
EthereumSignTx.token_value max_size:32
EthereumSignTx.token_to max_size:0
EthereumSignTx.token_shortcut max_size:8

EthereumTxRequest.signature_r max_size:32
EthereumTxRequest.signature_s max_size:32
EthereumTxRequest.hash max_size:32
EthereumTxRequest.signature_der max_size:73

EthereumTxAck.data_chunk max_size:1024

EthereumSignMessage.address_n max_count:8
EthereumSignMessage.message max_size:1024

EthereumVerifyMessage.address max_size:20
EthereumVerifyMessage.signature max_size:65
EthereumVerifyMessage.message max_size:1024

EthereumMessageSignature.address max_size:20
EthereumMessageSignature.signature max_size:65

EthereumSignTypedHash.address_n max_count:8
EthereumSignTypedHash.domain_separator_hash max_size:32
EthereumSignTypedHash.message_hash max_size:32

EthereumTypedDataSignature.address max_size:43
EthereumTypedDataSignature.signature max_size:65
35 changes: 0 additions & 35 deletions include/keepkey/transport/messages.options
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ GetAddress.coin_name max_size:21

Address.address max_size:130

EthereumGetAddress.address_n max_count:8
EthereumAddress.address max_size:20
EthereumAddress.address_str max_size:43

LoadDevice.mnemonic max_size:241
LoadDevice.pin max_size:10
LoadDevice.language max_size:17
Expand Down Expand Up @@ -99,37 +95,6 @@ CipheredKeyValue.value max_size:1024

SignTx.coin_name max_size:21

EthereumSignTx.address_n max_count:8
EthereumSignTx.nonce max_size:32
EthereumSignTx.gas_price max_size:32
EthereumSignTx.gas_limit max_size:32
EthereumSignTx.max_fee_per_gas max_size:32
EthereumSignTx.max_priority_fee_per_gas max_size:32
EthereumSignTx.to max_size:20
EthereumSignTx.value max_size:32
EthereumSignTx.data_initial_chunk max_size:1024
EthereumSignTx.to_address_n max_count:8
EthereumSignTx.token_value max_size:32
EthereumSignTx.token_to max_size:0
EthereumSignTx.token_shortcut max_size:8

EthereumTxRequest.signature_r max_size:32
EthereumTxRequest.signature_s max_size:32
EthereumTxRequest.hash max_size:32
EthereumTxRequest.signature_der max_size:73

EthereumTxAck.data_chunk max_size:1024

EthereumSignMessage.address_n max_count:8
EthereumSignMessage.message max_size:1024

EthereumVerifyMessage.address max_size:20
EthereumVerifyMessage.signature max_size:65
EthereumVerifyMessage.message max_size:1024

EthereumMessageSignature.address max_size:20
EthereumMessageSignature.signature max_size:65

SignIdentity.challenge_hidden max_size:256
SignIdentity.challenge_visual max_size:256
SignIdentity.ecdsa_curve_name max_size:32
Expand Down
39 changes: 39 additions & 0 deletions lib/firmware/ethereum.c
Original file line number Diff line number Diff line change
Expand Up @@ -1026,3 +1026,42 @@ int ethereum_message_verify(const EthereumVerifyMessage *msg) {
}
return 0;
}


//
/*
* EIP-712 hashes might have no message_hash if primaryType="EIP712Domain".
* In this case, set has_message_hash=false.
*/
static void ethereum_typed_hash(const uint8_t domain_separator_hash[32],
const uint8_t message_hash[32],
bool has_message_hash, uint8_t hash[32]) {
struct SHA3_CTX ctx = {0};
sha3_256_Init(&ctx);
sha3_Update(&ctx, (const uint8_t *)"\x19\x01", 2);
sha3_Update(&ctx, domain_separator_hash, 32);
if (has_message_hash) {
sha3_Update(&ctx, message_hash, 32);
}
keccak_Final(&ctx, hash);
}

void ethereum_typed_hash_sign(const EthereumSignTypedHash *msg,
const HDNode *node,
EthereumTypedDataSignature *resp) {
uint8_t hash[32] = {0};

ethereum_typed_hash(msg->domain_separator_hash.bytes, msg->message_hash.bytes,
msg->has_message_hash, hash);

uint8_t v = 0;
if (ecdsa_sign_digest(&secp256k1, node->private_key, hash,
resp->signature.bytes, &v, ethereum_is_canonic) != 0) {
fsm_sendFailure(FailureType_Failure_Other, _("EIP-712 typed hash signing failed"));
return;
}

resp->signature.bytes[64] = 27 + v;
resp->signature.size = 65;
msg_write(MessageType_MessageType_EthereumTypedDataSignature, resp);
}
2 changes: 1 addition & 1 deletion lib/firmware/ethereum.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#include <stdint.h>
#include <stdbool.h>
#include "bip32.h"
#include "messages.pb.h"
#include "ethereum-messages.pb.h"

void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node);
void ethereum_signing_abort(void);
Expand Down
1 change: 1 addition & 0 deletions lib/firmware/fsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
#include "trezor/crypto/secp256k1.h"

#include "messages.pb.h"
#include "messages-ethereum.pb.h"
#include "messages-binance.pb.h"
#include "messages-cosmos.pb.h"
#include "messages-eos.pb.h"
Expand Down
64 changes: 64 additions & 0 deletions lib/firmware/fsm_msg_ethereum.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@

/*
* This file is part of the Keepkey project
*
* Copyright (C) 2022
*
* 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/>.
*/

static int process_ethereum_xfer(const CoinType *coin, EthereumSignTx *msg) {
if (!ethereum_isStandardERC20Transfer(msg) && msg->data_length != 0)
Expand Down Expand Up @@ -221,3 +239,49 @@ void fsm_msgEthereumVerifyMessage(const EthereumVerifyMessage *msg) {

layoutHome();
}

void fsm_msgEthereumSignTypedHash(const EthereumSignTypedHash *msg) {
RESP_INIT(EthereumTypedDataSignature);

CHECK_INITIALIZED

CHECK_PIN

if (msg->domain_separator_hash.size != 32 ||
(msg->has_message_hash && msg->message_hash.size != 32)) {
fsm_sendFailure(FailureType_Failure_Other, _("Invalid EIP-712 hash length"));
return;
}

const HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n,
msg->address_n_count, NULL);
if (!node) return;

uint8_t pubkeyhash[20] = {0};
if (!hdnode_get_ethereum_pubkeyhash(node, pubkeyhash)) {
layoutHome();
return;
}

resp->address[0] = '0';
resp->address[1] = 'x';
ethereum_address_checksum(pubkeyhash, resp->address+2, false, 0);

// No message hash when setting primaryType="EIP712Domain"
// https://ethereum-magicians.org/t/eip-712-standards-clarification-primarytype-as-domaintype/3286
if (msg->has_message_hash) {
char str[64+1];
int ctr;
char *addrTitleStr = "Verify Address";
confirm(ButtonRequestType_ButtonRequest_Other, addrTitleStr, "Confirm address: %s", resp->address);

char *hashTitleStr = "EIP-712 domain hash";
for (ctr=0; ctr<64/2; ctr++) {
snprintf(&str[2*ctr], 3, "%02x", msg->domain_separator_hash.bytes[ctr]);
}
confirm(ButtonRequestType_ButtonRequest_Other, hashTitleStr, "Confirm hash digest: %s", str);
}

ethereum_typed_hash_sign(msg, node, resp);
layoutHome();
}
6 changes: 6 additions & 0 deletions lib/firmware/messagemap.def
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
MSG_IN(MessageType_MessageType_EthereumTxAck, EthereumTxAck, fsm_msgEthereumTxAck)
MSG_IN(MessageType_MessageType_EthereumSignMessage, EthereumSignMessage, fsm_msgEthereumSignMessage)
MSG_IN(MessageType_MessageType_EthereumVerifyMessage, EthereumVerifyMessage, fsm_msgEthereumVerifyMessage)

MSG_IN(MessageType_MessageType_EthereumSignTypedHash, EthereumSignTypedHash, fsm_msgEthereumSignTypedHash)

MSG_IN(MessageType_MessageType_NanoGetAddress, NanoGetAddress, fsm_msgNanoGetAddress)
MSG_IN(MessageType_MessageType_NanoSignTx, NanoSignTx, fsm_msgNanoSignTx)

Expand Down Expand Up @@ -85,6 +88,9 @@
MSG_OUT(MessageType_MessageType_EthereumAddress, EthereumAddress, NO_PROCESS_FUNC)
MSG_OUT(MessageType_MessageType_EthereumTxRequest, EthereumTxRequest, NO_PROCESS_FUNC)
MSG_OUT(MessageType_MessageType_EthereumMessageSignature, EthereumMessageSignature, NO_PROCESS_FUNC)

MSG_OUT(MessageType_MessageType_EthereumTypedDataSignature, EthereumTypedDataSignature, NO_PROCESS_FUNC)

MSG_OUT(MessageType_MessageType_NanoAddress, NanoAddress, NO_PROCESS_FUNC)
MSG_OUT(MessageType_MessageType_NanoSignedTx, NanoSignedTx, NO_PROCESS_FUNC)

Expand Down
9 changes: 9 additions & 0 deletions lib/transport/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ set(sources

set(protoc_pb_sources
${DEVICE_PROTOCOL}/types.proto
${DEVICE_PROTOCOL}/messages-ethereum.proto
${DEVICE_PROTOCOL}/messages-eos.proto
${DEVICE_PROTOCOL}/messages-nano.proto
${DEVICE_PROTOCOL}/messages-binance.proto
Expand All @@ -16,6 +17,7 @@ set(protoc_pb_sources

set(protoc_pb_options
${CMAKE_SOURCE_DIR}/include/keepkey/transport/types.options
${CMAKE_SOURCE_DIR}/include/keepkey/transport/messages-ethereum.options
${CMAKE_SOURCE_DIR}/include/keepkey/transport/messages-eos.options
${CMAKE_SOURCE_DIR}/include/keepkey/transport/messages-nano.options
${CMAKE_SOURCE_DIR}/include/keepkey/transport/messages-binance.options
Expand All @@ -27,6 +29,7 @@ set(protoc_pb_options

set(protoc_c_sources
${CMAKE_BINARY_DIR}/lib/transport/types.pb.c
${CMAKE_BINARY_DIR}/lib/transport/messages-ethereum.pb.c
${CMAKE_BINARY_DIR}/lib/transport/messages-eos.pb.c
${CMAKE_BINARY_DIR}/lib/transport/messages-nano.pb.c
${CMAKE_BINARY_DIR}/lib/transport/messages-binance.pb.c
Expand All @@ -38,6 +41,7 @@ set(protoc_c_sources

set(protoc_c_headers
${CMAKE_BINARY_DIR}/include/types.pb.h
${CMAKE_BINARY_DIR}/include/messages-ethereum.pb.h
${CMAKE_BINARY_DIR}/include/messages-eos.pb.h
${CMAKE_BINARY_DIR}/include/messages-nano.pb.h
${CMAKE_BINARY_DIR}/include/messages-binance.pb.h
Expand All @@ -49,6 +53,7 @@ set(protoc_c_headers

set(protoc_pb_sources_moved
${CMAKE_BINARY_DIR}/lib/transport/types.proto
${CMAKE_BINARY_DIR}/lib/transport/messages-ethereum.proto
${CMAKE_BINARY_DIR}/lib/transport/messages-eos.proto
${CMAKE_BINARY_DIR}/lib/transport/messages-nano.proto
${CMAKE_BINARY_DIR}/lib/transport/messages-binance.proto
Expand Down Expand Up @@ -81,6 +86,10 @@ add_custom_command(
${PROTOC_BINARY} -I. -I/usr/include
--plugin=nanopb=${NANOPB_DIR}/generator/protoc-gen-nanopb
"--nanopb_out=-f types.options:." types.proto
COMMAND
${PROTOC_BINARY} -I. -I/usr/include
--plugin=nanopb=${NANOPB_DIR}/generator/protoc-gen-nanopb
"--nanopb_out=-f messages-ethereum.options:." messages-ethereum.proto
COMMAND
${PROTOC_BINARY} -I. -I/usr/include
--plugin=nanopb=${NANOPB_DIR}/generator/protoc-gen-nanopb
Expand Down

0 comments on commit 85e266b

Please sign in to comment.