Skip to content

Commit d676685

Browse files
authored
Merge pull request #299 from keepkey/bugfix-1559-signatures
Bugfix 1559 signatures
2 parents abb852d + 577e228 commit d676685

File tree

3 files changed

+61
-28
lines changed

3 files changed

+61
-28
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.7.2)
22

33
project(KeepKeyFirmware
44

5-
VERSION 7.2.0
5+
VERSION 7.2.1
66

77
LANGUAGES C CXX ASM)
88

lib/firmware/ethereum.c

+59-26
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@
4747

4848
#define MAX_CHAIN_ID 2147483630
4949

50-
#define ETHEREUM_TX_TYPE_LEGACY 0
51-
#define ETHEREUM_TX_TYPE_EIP_2930 1
52-
#define ETHEREUM_TX_TYPE_EIP_1559 2
50+
#define ETHEREUM_TX_TYPE_LEGACY 0UL
51+
#define ETHEREUM_TX_TYPE_EIP_2930 1UL
52+
#define ETHEREUM_TX_TYPE_EIP_1559 2UL
5353

5454
static bool ethereum_signing = false;
5555
static uint32_t data_total, data_left;
@@ -270,12 +270,14 @@ static void send_signature(void) {
270270
uint8_t v;
271271
layoutProgress(_("Signing"), 1000);
272272

273-
/* eip-155 replay protection */
274-
if (chain_id) {
275-
/* hash v=chain_id, r=0, s=0 */
276-
hash_rlp_number(chain_id);
277-
hash_rlp_length(0, 0);
278-
hash_rlp_length(0, 0);
273+
if (ethereum_tx_type == ETHEREUM_TX_TYPE_LEGACY) {
274+
/* legacy eip-155 replay protection */
275+
if (chain_id) {
276+
/* hash v=chain_id, r=0, s=0 */
277+
hash_rlp_number(chain_id);
278+
hash_rlp_length(0, 0);
279+
hash_rlp_length(0, 0);
280+
}
279281
}
280282

281283
keccak_Final(&keccak_ctx, hash);
@@ -574,7 +576,7 @@ static void layoutEthereumFee(const EthereumSignTx *msg, bool is_token,
574576
}
575577

576578
/*
577-
* RLP fields:
579+
* RLP fields: (legacy)
578580
* - nonce (0 .. 32)
579581
* - gas_price (0 .. 32)
580582
* - gas_limit (0 .. 32)
@@ -651,7 +653,7 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node,
651653

652654
/* Ethereum tx type */
653655
if (msg->has_type) {
654-
if (msg->type == 0 || msg->type == 1 || msg->type == 2) {
656+
if (msg->type == 0 || msg->type == 2) {
655657
ethereum_tx_type = msg->type;
656658
} else {
657659
fsm_sendFailure(FailureType_Failure_SyntaxError,
@@ -799,14 +801,21 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node,
799801
uint32_t rlp_length = 0;
800802
layoutProgress(_("Signing"), 0);
801803

804+
if (ethereum_tx_type == ETHEREUM_TX_TYPE_EIP_1559) {
805+
// This is the chain ID length for 1559 tx (only one byte for now)
806+
rlp_length += rlp_calculate_number_length(chain_id);
807+
808+
//rlp_length += 1;
809+
}
810+
802811
rlp_length += rlp_calculate_length(msg->nonce.size, msg->nonce.bytes[0]);
803812
if (msg->has_max_fee_per_gas) {
804-
rlp_length += rlp_calculate_length(msg->max_fee_per_gas.size,
805-
msg->max_fee_per_gas.bytes[0]);
806813
if (msg->has_max_priority_fee_per_gas) {
807814
rlp_length += rlp_calculate_length(msg->max_priority_fee_per_gas.size,
808815
msg->max_priority_fee_per_gas.bytes[0]);
809816
}
817+
rlp_length += rlp_calculate_length(msg->max_fee_per_gas.size,
818+
msg->max_fee_per_gas.bytes[0]);
810819
} else {
811820
rlp_length += rlp_calculate_length(msg->gas_price.size, msg->gas_price.bytes[0]);
812821
}
@@ -816,38 +825,56 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node,
816825
rlp_length += rlp_calculate_length(msg->value.size, msg->value.bytes[0]);
817826
rlp_length += rlp_calculate_length(data_total, msg->data_initial_chunk.bytes[0]);
818827

828+
if (ethereum_tx_type == ETHEREUM_TX_TYPE_EIP_1559) {
829+
// access list size
830+
rlp_length += 1; // c0, keepkey does not support >0 length access list at this time
831+
}
832+
819833
if (wanchain_tx_type) {
820834
rlp_length += rlp_calculate_number_length(wanchain_tx_type);
821835
}
822-
823-
if (ethereum_tx_type) {
824-
rlp_length += rlp_calculate_number_length(ethereum_tx_type);
836+
837+
if (ethereum_tx_type == ETHEREUM_TX_TYPE_LEGACY) {
838+
// legacy EIP-155 replay protection
839+
if (chain_id) {
840+
rlp_length += rlp_calculate_number_length(chain_id);
841+
rlp_length += rlp_calculate_length(0, 0);
842+
rlp_length += rlp_calculate_length(0, 0);
843+
}
825844
}
826-
827-
if (chain_id) {
828-
rlp_length += rlp_calculate_number_length(chain_id);
829-
rlp_length += rlp_calculate_length(0, 0);
830-
rlp_length += rlp_calculate_length(0, 0);
845+
846+
// Start the hash:
847+
// keccak256(0x02 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas,
848+
// gas_limit, destination, amount, data, access_list]))
849+
850+
// tx type should never be greater than one byte in length
851+
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2718.md#transactiontype-only-goes-up-to-0x7f
852+
if (ethereum_tx_type == ETHEREUM_TX_TYPE_EIP_1559) {
853+
uint8_t datbuf[1] = {0x02};
854+
hash_data(datbuf, sizeof(datbuf));
831855
}
832856

857+
layoutProgress(_("Signing"), 100);
833858
/* Stage 2: Store header fields */
834859
hash_rlp_list_length(rlp_length);
835-
layoutProgress(_("Signing"), 100);
836-
if (ethereum_tx_type) {
837-
hash_rlp_number(ethereum_tx_type);
838-
}
860+
839861
if (wanchain_tx_type) {
840862
hash_rlp_number(wanchain_tx_type);
841863
}
842864

865+
if (ethereum_tx_type == ETHEREUM_TX_TYPE_EIP_1559) {
866+
// chain id goes here for 1559 (only one byte for now)
867+
hash_rlp_field((uint8_t *)(&chain_id), sizeof(uint8_t));
868+
}
869+
843870
hash_rlp_field(msg->nonce.bytes, msg->nonce.size);
844871

845872
if (msg->has_max_fee_per_gas) {
846-
hash_rlp_field(msg->max_fee_per_gas.bytes, msg->max_fee_per_gas.size);
847873
if (msg->has_max_priority_fee_per_gas) {
848874
hash_rlp_field(msg->max_priority_fee_per_gas.bytes,
849875
msg->max_priority_fee_per_gas.size);
850876
}
877+
hash_rlp_field(msg->max_fee_per_gas.bytes, msg->max_fee_per_gas.size);
851878
} else {
852879
hash_rlp_field(msg->gas_price.bytes, msg->gas_price.size);
853880
}
@@ -859,6 +886,12 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node,
859886
hash_data(msg->data_initial_chunk.bytes, msg->data_initial_chunk.size);
860887
data_left = data_total - msg->data_initial_chunk.size;
861888

889+
if (ethereum_tx_type == ETHEREUM_TX_TYPE_EIP_1559) {
890+
// Keepkey does not support an access list size >0 at this time
891+
uint8_t datbuf[1] = {0xC0}; // size of empty access list
892+
hash_data(datbuf, sizeof(datbuf));
893+
}
894+
862895
memcpy(privkey, node->private_key, 32);
863896

864897
if (data_left > 0) {

0 commit comments

Comments
 (0)