Skip to content

Commit

Permalink
EIP-712 trusted name filtering support
Browse files Browse the repository at this point in the history
  • Loading branch information
apaillier-ledger committed Sep 20, 2024
1 parent 42ec12a commit 8afb956
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 6 deletions.
6 changes: 6 additions & 0 deletions src_features/signMessageEIP712/commands_712.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#define P2_FILT_ACTIVATE 0x00
#define P2_FILT_DISCARDED_PATH 0x01
#define P2_FILT_MESSAGE_INFO 0x0F
#define P2_FILT_CONTRACT_NAME 0xFB
#define P2_FILT_DATE_TIME 0xFC
#define P2_FILT_AMOUNT_JOIN_TOKEN 0xFD
#define P2_FILT_AMOUNT_JOIN_VALUE 0xFE
Expand Down Expand Up @@ -198,6 +199,11 @@ uint16_t handle_eip712_filtering(uint8_t p1,
reply_apdu = false;
}
break;
#ifdef HAVE_TRUSTED_NAME
case P2_FILT_CONTRACT_NAME:
ret = filtering_trusted_name(cdata, length, p1 == 1);
break;
#endif
case P2_FILT_DATE_TIME:
ret = filtering_date_time(cdata, length, p1 == 1);
break;
Expand Down
123 changes: 119 additions & 4 deletions src_features/signMessageEIP712/filtering.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@
#ifdef HAVE_LEDGER_PKI
#include "os_pki.h"
#endif
#include "trusted_name.h"

#define FILT_MAGIC_MESSAGE_INFO 183
#define FILT_MAGIC_AMOUNT_JOIN_TOKEN 11
#define FILT_MAGIC_AMOUNT_JOIN_VALUE 22
#define FILT_MAGIC_DATETIME 33
#define FILT_MAGIC_TRUSTED_NAME 44
#define FILT_MAGIC_RAW_FIELD 72

#define TOKEN_IDX_ADDR_IN_DOMAIN 0xff
Expand Down Expand Up @@ -319,6 +321,119 @@ bool filtering_discarded_path(const uint8_t *payload, uint8_t length) {
return true;
}

#ifdef HAVE_TRUSTED_NAME
/**
* Command to display a field as a trusted name
*
* @param[in] payload the payload to parse
* @param[in] length the payload length
* @param[in] discarded if the filter targets a field that is does not exist (within an empty array)
* @return whether it was successful or not
*/
bool filtering_trusted_name(const uint8_t *payload, uint8_t length, bool discarded) {
uint8_t name_len;
const char *name;
uint8_t types_count;
e_name_type *types;
uint8_t sources_count;
e_name_source *sources;
uint8_t sig_len;
const uint8_t *sig;
uint8_t offset = 0;

if (path_get_root_type() != ROOT_MESSAGE) {
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
return false;
}

// Parsing
if ((offset + sizeof(name_len)) > length) {
return false;
}
name_len = payload[offset++];
if ((offset + name_len) > length) {
return false;
}
name = (char *) &payload[offset];
offset += name_len;
if ((offset + sizeof(types_count)) > length) {
return false;
}
types_count = payload[offset++];
if ((offset + types_count) > length) {
return false;
}
types = (e_name_type *) &payload[offset];
// sanity check
for (int i = 0; i < types_count; ++i) {
switch (types[i]) {
case TYPE_ACCOUNT:
case TYPE_CONTRACT:
break;
default:
return false;
}
}
offset += types_count;
if ((offset + sizeof(sources_count)) > length) {
return false;
}
sources_count = payload[offset++];
if ((offset + sources_count) > length) {
return false;
}
sources = (e_name_source *) &payload[offset];
// sanity check
for (int i = 0; i < sources_count; ++i) {
switch (sources[i]) {
case SOURCE_LAB:
case SOURCE_CAL:
case SOURCE_ENS:
case SOURCE_UD:
case SOURCE_FN:
case SOURCE_DNS:
break;
default:
return false;
}
}
offset += sources_count;
//
if ((offset + sizeof(sig_len)) > length) {
return false;
}
sig_len = payload[offset++];
if ((offset + sig_len) != length) {
return false;
}
sig = &payload[offset];

// Verification
cx_sha256_t hash_ctx;
if (!sig_verif_start(&hash_ctx, FILT_MAGIC_TRUSTED_NAME)) {
return false;
}
hash_filtering_path((cx_hash_t *) &hash_ctx, discarded);
hash_nbytes((uint8_t *) name, sizeof(char) * name_len, (cx_hash_t *) &hash_ctx);
hash_nbytes(types, types_count, (cx_hash_t *) &hash_ctx);
hash_nbytes(sources, sources_count, (cx_hash_t *) &hash_ctx);
if (!sig_verif_end(&hash_ctx, sig, sig_len)) {
return false;
}

// Handling
if (!check_typename("address")) {
return false;
}
if (name_len > 0) { // don't substitute for an empty name
ui_712_set_title(name, name_len);
}
ui_712_flag_field(true, name_len > 0, false, false, true);
ui_712_set_trusted_name_requirements(types_count, types);
return true;
}
#endif // HAVE_TRUSTED_NAME

/**
* Command to display a field as a date-time
*
Expand Down Expand Up @@ -376,7 +491,7 @@ bool filtering_date_time(const uint8_t *payload, uint8_t length, bool discarded)
if (name_len > 0) { // don't substitute for an empty name
ui_712_set_title(name, name_len);
}
ui_712_flag_field(true, name_len > 0, false, true);
ui_712_flag_field(true, name_len > 0, false, true, false);
return true;
}

Expand Down Expand Up @@ -428,7 +543,7 @@ bool filtering_amount_join_token(const uint8_t *payload, uint8_t length, bool di
if (!check_typename("address") || !check_token_index(token_idx)) {
return false;
}
ui_712_flag_field(false, false, true, false);
ui_712_flag_field(false, false, true, false, false);
ui_712_token_join_prepare_addr_check(token_idx);
return true;
}
Expand Down Expand Up @@ -509,7 +624,7 @@ bool filtering_amount_join_value(const uint8_t *payload, uint8_t length, bool di
if (!check_typename("uint") || !check_token_index(token_idx)) {
return false;
}
ui_712_flag_field(false, false, true, false);
ui_712_flag_field(false, false, true, false, false);
ui_712_token_join_prepare_amount(token_idx, name, name_len);
return true;
}
Expand Down Expand Up @@ -569,7 +684,7 @@ bool filtering_raw_field(const uint8_t *payload, uint8_t length, bool discarded)
if (name_len > 0) { // don't substitute for an empty name
ui_712_set_title(name, name_len);
}
ui_712_flag_field(true, name_len > 0, false, false);
ui_712_flag_field(true, name_len > 0, false, false, false);
}
return true;
}
Expand Down
1 change: 1 addition & 0 deletions src_features/signMessageEIP712/filtering.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#define MAX_FILTERS 50

bool filtering_message_info(const uint8_t *payload, uint8_t length);
bool filtering_trusted_name(const uint8_t *payload, uint8_t length, bool discarded);
bool filtering_date_time(const uint8_t *payload, uint8_t length, bool discarded);
bool filtering_amount_join_token(const uint8_t *payload, uint8_t length, bool discarded);
bool filtering_amount_join_value(const uint8_t *payload, uint8_t length, bool discarded);
Expand Down
65 changes: 64 additions & 1 deletion src_features/signMessageEIP712/ui_logic.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "common_ui.h"
#include "uint_common.h"
#include "filtering.h"
#include "trusted_name.h"

#define AMOUNT_JOIN_FLAG_TOKEN (1 << 0)
#define AMOUNT_JOIN_FLAG_VALUE (1 << 1)
Expand All @@ -42,6 +43,7 @@ typedef enum {
#define UI_712_FIELD_NAME_PROVIDED (1 << 1)
#define UI_712_AMOUNT_JOIN (1 << 2)
#define UI_712_DATETIME (1 << 3)
#define UI_712_TRUSTED_NAME (1 << 4)

typedef struct {
s_amount_join joins[MAX_ASSETS];
Expand All @@ -61,6 +63,9 @@ typedef struct {
uint32_t filters_crc[MAX_FILTERS];
uint8_t discarded_path_length;
char discarded_path[255];
#ifdef HAVE_TRUSTED_NAME
e_name_type name_types;
#endif
#ifdef SCREEN_SIZE_WALLET
char ui_pairs_buffer[(SHARED_CTX_FIELD_1_SIZE + SHARED_CTX_FIELD_2_SIZE) * 2];
#endif
Expand Down Expand Up @@ -491,6 +496,38 @@ static bool update_amount_join(const uint8_t *data, uint8_t length) {
return true;
}

#ifdef HAVE_TRUSTED_NAME
/**
* Try to substitute given address by a matching contract name
*
* Fallback on showing the address if no match is found.
*
* @param[in] data the data that needs formatting
* @param[in] length its length
* @return whether it was successful or not
*/
static bool ui_712_format_trusted_name(const uint8_t *data, uint8_t length) {
uint8_t types_count = 0;
e_name_type types[8];
uint8_t types_bak = ui_ctx->name_types;

if (length != ADDRESS_LENGTH) {
return false;
}
for (int i = 0; types_bak > 0; ++i) {
if (types_bak & 1) {
types[types_count++] = i;
}
types_bak >>= 1;
}
if (has_trusted_name(types_count, types, &eip712_context->chain_id, data)) {
strcpy(strings.tmp.tmp, g_trusted_name);
PRINTF("IT'S A MATCH!\n");
}
return true;
}
#endif

/**
* Format given data as a human-readable date/time representation
*
Expand Down Expand Up @@ -606,6 +643,14 @@ bool ui_712_feed_to_display(const void *field_ptr,
}
}

#ifdef HAVE_TRUSTED_NAME
if (ui_ctx->field_flags & UI_712_TRUSTED_NAME) {
if (!ui_712_format_trusted_name(data, length)) {
return false;
}
}
#endif

// Check if this field is supposed to be displayed
if (last && ui_712_field_shown()) {
ui_712_redraw_generic_step();
Expand Down Expand Up @@ -682,8 +727,13 @@ unsigned int ui_712_reject() {
* @param[in] name_provided if a substitution name has been provided
* @param[in] token_join if this field is part of a token join
* @param[in] datetime if this field should be shown and formatted as a date/time
* @param[in] trusted_name if this field should be shown as a trusted contract name
*/
void ui_712_flag_field(bool show, bool name_provided, bool token_join, bool datetime) {
void ui_712_flag_field(bool show,
bool name_provided,
bool token_join,
bool datetime,
bool trusted_name) {
if (show) {
ui_ctx->field_flags |= UI_712_FIELD_SHOWN;
}
Expand All @@ -696,6 +746,9 @@ void ui_712_flag_field(bool show, bool name_provided, bool token_join, bool date
if (datetime) {
ui_ctx->field_flags |= UI_712_DATETIME;
}
if (trusted_name) {
ui_ctx->field_flags |= UI_712_TRUSTED_NAME;
}
}

/**
Expand Down Expand Up @@ -841,6 +894,16 @@ const char *ui_712_get_discarded_path(uint8_t *length) {
return ui_ctx->discarded_path;
}

#ifdef HAVE_TRUSTED_NAME
void ui_712_set_trusted_name_requirements(uint8_t types_count, const e_name_type *types) {
// pack into one byte to save on space
ui_ctx->name_types = 0;
for (int i = 0; i < types_count; ++i) {
ui_ctx->name_types |= (1 << types[i]);
}
}
#endif

#ifdef SCREEN_SIZE_WALLET
/*
* Get UI pairs buffer
Expand Down
10 changes: 9 additions & 1 deletion src_features/signMessageEIP712/ui_logic.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <stdint.h>
#include "ux.h"
#include "uint256.h"
#include "trusted_name.h"

typedef enum { EIP712_FILTERING_BASIC, EIP712_FILTERING_FULL } e_eip712_filtering_mode;
typedef enum {
Expand All @@ -30,7 +31,11 @@ void ui_712_set_title(const char *str, size_t length);
void ui_712_set_value(const char *str, size_t length);
void ui_712_message_hash(void);
void ui_712_redraw_generic_step(void);
void ui_712_flag_field(bool show, bool name_provided, bool token_join, bool datetime);
void ui_712_flag_field(bool show,
bool name_provided,
bool token_join,
bool datetime,
bool contract_name);
void ui_712_field_flags_reset(void);
void ui_712_finalize_field(void);
void ui_712_set_filtering_mode(e_eip712_filtering_mode mode);
Expand All @@ -46,6 +51,9 @@ bool ui_712_show_raw_key(const void *field_ptr);
bool ui_712_push_new_filter_path(void);
void ui_712_set_discarded_path(const char *path, uint8_t length);
const char *ui_712_get_discarded_path(uint8_t *length);
#ifdef HAVE_TRUSTED_NAME
void ui_712_set_trusted_name_requirements(uint8_t types_count, const e_name_type *types);
#endif
#ifdef SCREEN_SIZE_WALLET
char *get_ui_pairs_buffer(size_t *size);
#endif
Expand Down

0 comments on commit 8afb956

Please sign in to comment.