27#define TYPE_TRANSACTION_CHECK 0x09
28#define TRANSACTION_CHECK_VERSION 0x01
65 &tlv_extracted->
output->tx_hash,
73 &tlv_extracted->
output->domain_hash,
81 &tlv_extracted->
output->address,
95 PRINTF(
"TX_CHECK_NORMALIZED_RISK: failed to extract\n");
99 PRINTF(
"TX_CHECK_NORMALIZED_RISK: value %d out of range\n", value);
110 PRINTF(
"TX_CHECK_NORMALIZED_CATEGORY: failed to extract\n");
114 PRINTF(
"TX_CHECK_NORMALIZED_CATEGORY: value %d out of range\n", value);
125 PRINTF(
"TX_CHECK_SIMULATION_TYPE: failed to extract\n");
129 PRINTF(
"TX_CHECK_SIMULATION_TYPE: value %d out of range\n", value);
139 tlv_extracted->
output->provider_msg,
141 sizeof(tlv_extracted->
output->provider_msg))) {
142 PRINTF(
"TX_CHECK_PROVIDER_MESSAGE: failed to extract\n");
145 if (!is_printable_string(tlv_extracted->
output->provider_msg,
146 strlen(tlv_extracted->
output->provider_msg))) {
147 PRINTF(
"TX_CHECK_PROVIDER_MESSAGE: not printable\n");
156 data, tlv_extracted->
output->tiny_url, 0,
sizeof(tlv_extracted->
output->tiny_url))) {
157 PRINTF(
"TX_CHECK_TINY_URL: failed to extract\n");
160 if (!is_printable_string(tlv_extracted->
output->tiny_url,
161 strlen(tlv_extracted->
output->tiny_url))) {
162 PRINTF(
"TX_CHECK_TINY_URL: not printable\n");
172 CX_ECDSA_SHA256_SIG_MIN_ASN1_LENGTH,
173 CX_ECDSA_SHA256_SIG_MAX_ASN1_LENGTH);
183#define TRANSACTION_CHECK_TLV_TAGS(X) \
184 X(0x01, TAG_STRUCTURE_TYPE, handle_structure_type, ENFORCE_UNIQUE_TAG) \
185 X(0x02, TAG_STRUCTURE_VERSION, handle_structure_version, ENFORCE_UNIQUE_TAG) \
186 X(0x22, TAG_ADDRESS, handle_address, ENFORCE_UNIQUE_TAG) \
187 X(0x23, TAG_CHAIN_ID, handle_chain_id, ENFORCE_UNIQUE_TAG) \
188 X(0x27, TAG_TX_HASH, handle_tx_hash, ENFORCE_UNIQUE_TAG) \
189 X(0x28, TAG_DOMAIN_HASH, handle_domain_hash, ENFORCE_UNIQUE_TAG) \
190 X(0x80, TAG_NORMALIZED_RISK, handle_risk, ENFORCE_UNIQUE_TAG) \
191 X(0x81, TAG_NORMALIZED_CATEGORY, handle_category, ENFORCE_UNIQUE_TAG) \
192 X(0x82, TAG_PROVIDER_MSG, handle_provider_msg, ENFORCE_UNIQUE_TAG) \
193 X(0x83, TAG_TINY_URL, handle_tiny_url, ENFORCE_UNIQUE_TAG) \
194 X(0x84, TAG_SIMULATION_TYPE, handle_type, ENFORCE_UNIQUE_TAG) \
195 X(0x85, TAG_ADDITIONAL_DATA, NULL, ENFORCE_UNIQUE_TAG) \
196 X(0x15, TAG_DER_SIGNATURE, handle_signature, ENFORCE_UNIQUE_TAG)
206 if (data->tag != TAG_DER_SIGNATURE) {
208 cx_hash_update((cx_hash_t *) &tlv_extracted->hash_ctx, data->raw.ptr, data->raw.size));
221 PRINTF(
"Error: no struct type specified!\n");
226 PRINTF(
"Error: unexpected struct type %d\n", tlv_extracted->
structure_type);
232 TAG_STRUCTURE_VERSION,
236 TAG_NORMALIZED_CATEGORY,
239 TAG_DER_SIGNATURE)) {
240 PRINTF(
"Error: missing mandatory tags in Transaction Check TLV\n");
246 PRINTF(
"Error: unsupported Transaction Check version %d\n",
252 tlv_extracted->
output->chain_id_received
254 tlv_extracted->
output->domain_hash_received
256 tlv_extracted->
output->provider_msg_received
258 tlv_extracted->
output->additional_data_received
267 uint8_t tlv_hash[CX_SHA256_SIZE] = {0};
268 CX_ASSERT(cx_hash_final((cx_hash_t *) &tlv_extracted->
hash_ctx, tlv_hash));
269 buffer_t hash = {.
ptr = tlv_hash, .size =
sizeof(tlv_hash)};
272 uint8_t expected_key_usage = CERTIFICATE_PUBLIC_KEY_USAGE_TX_SIMU_SIGNER;
273 cx_curve_t expected_curve = CX_CURVE_SECP256K1;
277 hash, &expected_key_usage, &expected_curve, tlv_extracted->
input_sig);
279 PRINTF(
"Failed to verify Transaction Check signature\n");
295 tlv_extracted.
output = out;
298 memset(out, 0,
sizeof(*out));
301 CX_ASSERT(cx_sha256_init_no_throw(&tlv_extracted.
hash_ctx));
304 if (!parse_transaction_check_tlv(payload, &tlv_extracted, &tlv_extracted.
received_tags)) {
305 PRINTF(
"Failed to parse Transaction Check TLV payload\n");
312 PRINTF(
"Failed to verify Transaction Check TLV structure\n");
319 PRINTF(
"Failed to verify Transaction Check signature\n");
324 uint8_t key_usage = 0;
325 size_t trusted_name_len = 0;
326 uint8_t trusted_name[CERTIFICATE_TRUSTED_NAME_MAXLEN] = {0};
327 cx_ecfp_384_public_key_t public_key = {0};
328 if (os_pki_get_info(&key_usage, trusted_name, &trusted_name_len, &public_key) == 0) {
329 PRINTF(
"Using certificate name as partner name\n");
330 strlcpy(out->
partner, (
char *) trusted_name,
sizeof(out->
partner));
333 if (strlen(out->
partner) == 0) {
334 PRINTF(
"Using default name as partner name\n");
335 snprintf(out->
partner,
sizeof(out->
partner),
"Transaction Checks");
check_signature_with_pki_status_t check_signature_with_pki(const buffer_t hash, const uint8_t *expected_key_usage, const cx_curve_t *expected_curve, const buffer_t signature)
Checks a signature using the PKI certificate.
@ CHECK_SIGNATURE_WITH_PKI_SUCCESS
enum check_signature_with_pki_status_e check_signature_with_pki_status_t
char partner[TRANSACTION_CHECK_PARTNER_SIZE+1]
bool get_string_from_tlv_data(const tlv_data_t *data, char *out, uint16_t min_length, uint16_t out_size)
Copy a NUL-terminated string from TLV data.
bool get_uint64_t_from_tlv_data(const tlv_data_t *data, uint64_t *value)
Extract a uint64_t value from TLV data.
bool get_uint8_t_from_tlv_data(const tlv_data_t *data, uint8_t *value)
Extract a uint8_t value from TLV data.
bool get_buffer_from_tlv_data(const tlv_data_t *data, buffer_t *out, uint16_t min_size, uint16_t max_size)
Extract a sized buffer from TLV data (zero-copy).
#define DEFINE_TLV_PARSER(TAG_LIST, COMMON_HANDLER, PARSE_FUNCTION_NAME)
Creates a parser function for a given TLV use case.
#define TLV_CHECK_RECEIVED_TAGS(received,...)
static bool handle_signature(const tlv_data_t *data, tlv_extracted_t *tlv_extracted)
static bool handle_tx_hash(const tlv_data_t *data, tlv_extracted_t *tlv_extracted)
static bool handle_tiny_url(const tlv_data_t *data, tlv_extracted_t *tlv_extracted)
static bool handle_domain_hash(const tlv_data_t *data, tlv_extracted_t *tlv_extracted)
static bool handle_chain_id(const tlv_data_t *data, tlv_extracted_t *tlv_extracted)
static bool handle_category(const tlv_data_t *data, tlv_extracted_t *tlv_extracted)
struct tlv_extracted_s tlv_extracted_t
static bool handle_address(const tlv_data_t *data, tlv_extracted_t *tlv_extracted)
#define TRANSACTION_CHECK_TLV_TAGS(X)
static tlv_transaction_check_status_t verify_signature(tlv_extracted_t *tlv_extracted)
tlv_transaction_check_status_t tlv_use_case_transaction_check(const buffer_t *payload, tlv_transaction_check_out_t *out)
Parse a Transaction Check TLV payload.
static bool handle_provider_msg(const tlv_data_t *data, tlv_extracted_t *tlv_extracted)
#define TRANSACTION_CHECK_VERSION
static tlv_transaction_check_status_t verify_struct(const tlv_extracted_t *tlv_extracted)
static bool handle_structure_version(const tlv_data_t *data, tlv_extracted_t *tlv_extracted)
#define TYPE_TRANSACTION_CHECK
static bool handle_type(const tlv_data_t *data, tlv_extracted_t *tlv_extracted)
static bool handle_structure_type(const tlv_data_t *data, tlv_extracted_t *tlv_extracted)
static bool handle_risk(const tlv_data_t *data, tlv_extracted_t *tlv_extracted)
static bool handle_common(const tlv_data_t *data, tlv_extracted_t *tlv_extracted)
Common handler called for all tags to progressively hash them (except signature).
#define TRANSACTION_CHECK_HASH_SIZE
#define TRANSACTION_CHECK_MIN_ADDRESS_SIZE
enum transaction_check_risk_e transaction_check_risk_t
#define TRANSACTION_CHECK_MAX_ADDRESS_SIZE
enum tlv_transaction_check_status_e tlv_transaction_check_status_t
enum transaction_check_type_e transaction_check_type_t
@ TRANSACTION_CHECK_CATEGORY_COUNT
@ TRANSACTION_CHECK_TYPE_COUNT
@ TRANSACTION_CHECK_RISK_COUNT
@ TLV_TRANSACTION_CHECK_SUCCESS
@ TLV_TRANSACTION_CHECK_SIGNATURE_ERROR
@ TLV_TRANSACTION_CHECK_WRONG_TYPE
@ TLV_TRANSACTION_CHECK_UNKNOWN_VERSION
@ TLV_TRANSACTION_CHECK_MISSING_STRUCTURE_TAG
@ TLV_TRANSACTION_CHECK_MISSING_TAG
@ TLV_TRANSACTION_CHECK_PARSING_ERROR
enum transaction_check_category_e transaction_check_category_t