Date/Time EIP-712 filtering implementation
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(×tamp, &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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user