From 9e4df4b65548ff1983aecd9b4d467d7ffee600a1 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Wed, 17 Aug 2022 10:45:43 +0200 Subject: [PATCH] Updated EIP712 filtering signature specs to start with a magic number Making it impossible for a signature of one type to be valid as another --- doc/ethapp.adoc | 6 ++++-- src_features/signMessageEIP712/filtering.c | 14 ++++++++++++++ src_features/signMessageEIP712/filtering.h | 3 +++ tests/ragger/eip712/InputData.py | 2 ++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/doc/ethapp.adoc b/doc/ethapp.adoc index 3aaf738..7a30e33 100644 --- a/doc/ethapp.adoc +++ b/doc/ethapp.adoc @@ -816,19 +816,21 @@ If activated, fields will be by default hidden unless they receive a field name Name substitution commands should come right after the contract address from the domain has been sent with a *SEND STRUCT IMPLEMENTATION*. Perfect moment to do it is when the domain implementation has been sent, just before sending the message implementation. +The first byte is used so that a signature of one type cannot be valid as another type. The signature is computed on : -chain ID (BE) || contract address || schema hash || display name +183 || chain ID (BE) || contract address || schema hash || display name ##### Field name substitution Name substitution commands should come before the corresponding *SEND STRUCT IMPLEMENTATION* and are only usable for message fields (and not domain ones). +The first byte is used so that a signature of one type cannot be valid as another type. The signature is computed on : -chain ID (BE) || contract address || schema hash || field path || display name +72 || chain ID (BE) || contract address || schema hash || field path || display name #### Coding diff --git a/src_features/signMessageEIP712/filtering.c b/src_features/signMessageEIP712/filtering.c index 7984714..19eb2f0 100644 --- a/src_features/signMessageEIP712/filtering.c +++ b/src_features/signMessageEIP712/filtering.c @@ -65,6 +65,20 @@ static bool verify_filtering_signature(uint8_t dname_length, cx_sha256_init(&hash_ctx); + // Magic number, makes it so a signature of one type can't be used as another + switch (type) { + case FILTERING_STRUCT_FIELD: + hash_byte(FILTERING_MAGIC_STRUCT_FIELD, (cx_hash_t *) &hash_ctx); + break; + case FILTERING_CONTRACT_NAME: + hash_byte(FILTERING_MAGIC_CONTRACT_NAME, (cx_hash_t *) &hash_ctx); + break; + default: + apdu_response_code = APDU_RESPONSE_INVALID_DATA; + PRINTF("Invalid filtering type when verifying signature!\n"); + return false; + } + // Chain ID chain_id = __builtin_bswap64(eip712_context->chain_id); hash_nbytes((uint8_t *) &chain_id, sizeof(chain_id), (cx_hash_t *) &hash_ctx); diff --git a/src_features/signMessageEIP712/filtering.h b/src_features/signMessageEIP712/filtering.h index 541521c..04d20dc 100644 --- a/src_features/signMessageEIP712/filtering.h +++ b/src_features/signMessageEIP712/filtering.h @@ -6,6 +6,9 @@ #include #include +#define FILTERING_MAGIC_CONTRACT_NAME 0b10110111 // 183 +#define FILTERING_MAGIC_STRUCT_FIELD 0b01001000 // ~183 = 72 + typedef enum { FILTERING_CONTRACT_NAME, FILTERING_STRUCT_FIELD } e_filtering_type; bool provide_filtering_info(const uint8_t *const payload, uint8_t length, e_filtering_type type); diff --git a/tests/ragger/eip712/InputData.py b/tests/ragger/eip712/InputData.py index 47c3018..359ca69 100644 --- a/tests/ragger/eip712/InputData.py +++ b/tests/ragger/eip712/InputData.py @@ -246,6 +246,7 @@ def send_filtering_contract_name(display_name: str): global sig_ctx msg = bytearray() + msg.append(183) msg += sig_ctx["chainid"] msg += sig_ctx["caddr"] msg += sig_ctx["schema_hash"] @@ -262,6 +263,7 @@ def send_filtering_field_name(display_name): path_str = ".".join(current_path) msg = bytearray() + msg.append(72) msg += sig_ctx["chainid"] msg += sig_ctx["caddr"] msg += sig_ctx["schema_hash"]