Date/Time EIP-712 filtering implementation

This commit is contained in:
Alexandre Paillier
2024-05-13 17:40:26 +02:00
parent d6a533b720
commit 2fdb3bcb34
5 changed files with 119 additions and 5 deletions

View File

@@ -28,6 +28,7 @@
#define P2_IMPL_FIELD P2_DEF_FIELD
#define P2_FILT_ACTIVATE 0x00
#define P2_FILT_MESSAGE_INFO 0x0F
#define P2_FILT_DATE_TIME 0xFC
#define P2_FILT_AMOUNT_JOIN_TOKEN 0xFD
#define P2_FILT_AMOUNT_JOIN_VALUE 0xFE
#define P2_FILT_RAW_FIELD 0xFF
@@ -177,6 +178,9 @@ bool handle_eip712_filtering(const uint8_t *const apdu_buf) {
reply_apdu = false;
}
break;
case P2_FILT_DATE_TIME:
ret = filtering_date_time(&apdu_buf[OFFSET_CDATA], apdu_buf[OFFSET_LC]);
break;
case P2_FILT_AMOUNT_JOIN_TOKEN:
ret = filtering_amount_join_token(&apdu_buf[OFFSET_CDATA], apdu_buf[OFFSET_LC]);
break;

View File

@@ -14,6 +14,7 @@
#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_RAW_FIELD 72
/**
@@ -214,6 +215,66 @@ bool filtering_message_info(const uint8_t *payload, uint8_t length) {
return true;
}
/**
* Command to display a field as a date-time
*
* @param[in] payload the payload to parse
* @param[in] length the payload length
* @return whether it was successful or not
*/
bool filtering_date_time(const uint8_t *payload, uint8_t length) {
uint8_t name_len;
const char *name;
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(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_DATETIME)) {
return false;
}
hash_filtering_path((cx_hash_t *) &hash_ctx);
hash_nbytes((uint8_t *) name, sizeof(char) * name_len, (cx_hash_t *) &hash_ctx);
if (!sig_verif_end(&hash_ctx, sig, sig_len)) {
return false;
}
// Handling
if (!check_typename("uint")) {
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, true);
return true;
}
/**
* Command to display a field as an amount-join (token part)
*
@@ -261,7 +322,7 @@ bool filtering_amount_join_token(const uint8_t *payload, uint8_t length) {
if (!check_typename("address") || !check_token_index(token_idx)) {
return false;
}
ui_712_flag_field(false, false, true);
ui_712_flag_field(false, false, true, false);
ui_712_token_join_prepare_addr_check(token_idx);
return true;
}
@@ -328,7 +389,7 @@ bool filtering_amount_join_value(const uint8_t *payload, uint8_t length) {
if (!check_typename("uint") || !check_token_index(token_idx)) {
return false;
}
ui_712_flag_field(false, false, true);
ui_712_flag_field(false, false, true, false);
ui_712_token_join_prepare_amount(token_idx, name, name_len);
return true;
}
@@ -386,7 +447,7 @@ bool filtering_raw_field(const uint8_t *payload, uint8_t length) {
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);
ui_712_flag_field(true, name_len > 0, false, false);
return true;
}

View File

@@ -7,6 +7,7 @@
#include <stdint.h>
bool filtering_message_info(const uint8_t *payload, uint8_t length);
bool filtering_date_time(const uint8_t *payload, uint8_t length);
bool filtering_amount_join_token(const uint8_t *payload, uint8_t length);
bool filtering_amount_join_value(const uint8_t *payload, uint8_t length);
bool filtering_raw_field(const uint8_t *payload, uint8_t length);

View File

@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include "ui_logic.h"
#include "mem.h"
#include "mem_utils.h"
@@ -39,6 +40,7 @@ typedef enum {
#define UI_712_FIELD_SHOWN (1 << 0)
#define UI_712_FIELD_NAME_PROVIDED (1 << 1)
#define UI_712_AMOUNT_JOIN (1 << 2)
#define UI_712_DATETIME (1 << 3)
typedef struct {
s_amount_join joins[MAX_ASSETS];
@@ -426,6 +428,42 @@ static bool update_amount_join(const uint8_t *data, uint8_t length) {
return true;
}
/**
* Format given data as a human-readable date/time representation
*
* @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_datetime(const uint8_t *data, uint8_t length) {
struct tm tstruct;
int shown_hour;
time_t timestamp = u64_from_BE(data, length);
if (gmtime_r(&timestamp, &tstruct) == NULL) {
return false;
}
if (tstruct.tm_hour == 0) {
shown_hour = 12;
} else {
shown_hour = tstruct.tm_hour;
if (shown_hour > 12) {
shown_hour -= 12;
}
}
snprintf(strings.tmp.tmp,
sizeof(strings.tmp.tmp),
"%04d-%02d-%02d\n%02d:%02d:%02d %s UTC",
tstruct.tm_year + 1900,
tstruct.tm_mon + 1,
tstruct.tm_mday,
shown_hour,
tstruct.tm_min,
tstruct.tm_sec,
(tstruct.tm_hour < 12) ? "AM" : "PM");
return true;
}
/**
* Used to notify of a new field to review in the current struct (key + value)
*
@@ -497,6 +535,12 @@ bool ui_712_new_field(const void *const field_ptr, const uint8_t *const data, ui
}
}
if (ui_ctx->field_flags & UI_712_DATETIME) {
if (!ui_712_format_datetime(data, length)) {
return false;
}
}
// Check if this field is supposed to be displayed
if (ui_712_field_shown()) {
ui_712_redraw_generic_step();
@@ -573,8 +617,9 @@ unsigned int ui_712_reject() {
* @param[in] show if this field should be shown on the device
* @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
*/
void ui_712_flag_field(bool show, bool name_provided, bool token_join) {
void ui_712_flag_field(bool show, bool name_provided, bool token_join, bool datetime) {
if (show) {
ui_ctx->field_flags |= UI_712_FIELD_SHOWN;
}
@@ -584,6 +629,9 @@ void ui_712_flag_field(bool show, bool name_provided, bool token_join) {
if (token_join) {
ui_ctx->field_flags |= UI_712_AMOUNT_JOIN;
}
if (datetime) {
ui_ctx->field_flags |= UI_712_DATETIME;
}
}
/**

View File

@@ -26,7 +26,7 @@ void ui_712_set_title(const char *const str, uint8_t length);
void ui_712_set_value(const char *const str, uint8_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);
void ui_712_flag_field(bool show, bool name_provided, bool token_join, bool datetime);
void ui_712_field_flags_reset(void);
void ui_712_finalize_field(void);
void ui_712_set_filtering_mode(e_eip712_filtering_mode mode);