2022-05-16 10:59:20 +02:00
|
|
|
#ifdef HAVE_EIP712_FULL_SUPPORT
|
|
|
|
|
|
2022-05-02 15:30:14 +02:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include "encode_field.h"
|
|
|
|
|
#include "mem.h"
|
|
|
|
|
#include "shared_context.h"
|
2022-07-19 11:49:18 +02:00
|
|
|
#include "apdu_constants.h" // APDU response codes
|
2022-05-02 15:30:14 +02:00
|
|
|
|
2022-07-19 11:49:18 +02:00
|
|
|
typedef enum { MSB, LSB } e_padding_type;
|
2022-05-02 15:30:14 +02:00
|
|
|
|
|
|
|
|
/**
|
2022-06-08 18:31:16 +02:00
|
|
|
* Encode a field value to 32 bytes (padded)
|
2022-05-02 15:30:14 +02:00
|
|
|
*
|
2022-04-14 18:22:35 +02:00
|
|
|
* @param[in] value field value to encode
|
|
|
|
|
* @param[in] length field length before encoding
|
2022-06-08 18:31:16 +02:00
|
|
|
* @param[in] ptype padding direction (LSB vs MSB)
|
|
|
|
|
* @param[in] pval value used for padding
|
2022-04-14 18:22:35 +02:00
|
|
|
* @return encoded field value
|
2022-05-02 15:30:14 +02:00
|
|
|
*/
|
2022-06-08 18:31:16 +02:00
|
|
|
static void *field_encode(const uint8_t *const value,
|
|
|
|
|
uint8_t length,
|
|
|
|
|
e_padding_type ptype,
|
2022-07-19 11:49:18 +02:00
|
|
|
uint8_t pval) {
|
2022-05-02 15:30:14 +02:00
|
|
|
uint8_t *padded_value;
|
2022-05-02 11:05:25 +02:00
|
|
|
uint8_t start_idx;
|
2022-05-02 15:30:14 +02:00
|
|
|
|
2022-07-19 11:49:18 +02:00
|
|
|
if (length > EIP_712_ENCODED_FIELD_LENGTH) // sanity check
|
2022-05-02 15:30:26 +02:00
|
|
|
{
|
2022-07-19 11:04:16 +02:00
|
|
|
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
2022-05-02 15:30:26 +02:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2022-07-19 11:49:18 +02:00
|
|
|
if ((padded_value = mem_alloc(EIP_712_ENCODED_FIELD_LENGTH)) != NULL) {
|
|
|
|
|
switch (ptype) {
|
2022-05-02 11:05:25 +02:00
|
|
|
case MSB:
|
2022-06-08 18:31:16 +02:00
|
|
|
memset(padded_value, pval, EIP_712_ENCODED_FIELD_LENGTH - length);
|
2022-05-02 11:05:25 +02:00
|
|
|
start_idx = EIP_712_ENCODED_FIELD_LENGTH - length;
|
|
|
|
|
break;
|
|
|
|
|
case LSB:
|
|
|
|
|
explicit_bzero(padded_value + length, EIP_712_ENCODED_FIELD_LENGTH - length);
|
|
|
|
|
start_idx = 0;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2022-07-12 10:24:46 +02:00
|
|
|
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
2022-07-19 11:49:18 +02:00
|
|
|
return NULL; // should not be here
|
2022-05-02 11:05:25 +02:00
|
|
|
}
|
2022-06-08 18:31:16 +02:00
|
|
|
memcpy(&padded_value[start_idx], value, length);
|
2022-07-19 11:49:18 +02:00
|
|
|
} else {
|
2022-07-19 11:04:16 +02:00
|
|
|
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
|
|
|
|
}
|
2022-04-14 18:22:35 +02:00
|
|
|
return padded_value;
|
2022-05-02 15:30:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2022-06-08 18:31:16 +02:00
|
|
|
* Encode an unsigned integer
|
2022-05-02 15:30:14 +02:00
|
|
|
*
|
2022-04-14 18:22:35 +02:00
|
|
|
* @param[in] value pointer to the "packed" integer received
|
2022-05-02 15:30:14 +02:00
|
|
|
* @param[in] length its byte-length
|
2022-05-02 11:05:25 +02:00
|
|
|
* @return the encoded value
|
2022-05-02 15:30:14 +02:00
|
|
|
*/
|
2022-07-19 11:49:18 +02:00
|
|
|
void *encode_uint(const uint8_t *const value, uint8_t length) {
|
2022-04-14 18:22:35 +02:00
|
|
|
// no length check here since it will be checked by field_encode
|
2022-06-08 18:31:16 +02:00
|
|
|
return field_encode(value, length, MSB, 0x00);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Encode a signed integer
|
|
|
|
|
*
|
|
|
|
|
* @param[in] value pointer to the "packed" integer received
|
|
|
|
|
* @param[in] length its byte-length
|
|
|
|
|
* @param[in] typesize the type size in bytes
|
|
|
|
|
* @return the encoded value
|
|
|
|
|
*/
|
2022-07-19 11:49:18 +02:00
|
|
|
void *encode_int(const uint8_t *const value, uint8_t length, uint8_t typesize) {
|
2022-06-08 18:31:16 +02:00
|
|
|
uint8_t padding_value;
|
|
|
|
|
|
2022-08-08 13:53:41 +02:00
|
|
|
if (length < 1) {
|
|
|
|
|
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
2022-08-08 13:55:45 +02:00
|
|
|
return NULL;
|
2022-08-08 13:53:41 +02:00
|
|
|
}
|
|
|
|
|
|
2022-07-19 11:49:18 +02:00
|
|
|
if ((length == typesize) && (value[0] & (1 << 7))) // negative number
|
2022-06-08 18:31:16 +02:00
|
|
|
{
|
|
|
|
|
padding_value = 0xFF;
|
2022-07-19 11:49:18 +02:00
|
|
|
} else {
|
2022-06-08 18:31:16 +02:00
|
|
|
padding_value = 0x00;
|
|
|
|
|
}
|
|
|
|
|
// no length check here since it will be checked by field_encode
|
|
|
|
|
return field_encode(value, length, MSB, padding_value);
|
2022-05-02 11:05:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Encode a fixed-size byte array
|
|
|
|
|
*
|
|
|
|
|
* @param[in] value pointer to the "packed" bytes array
|
|
|
|
|
* @param[in] length its byte-length
|
|
|
|
|
* @return the encoded value
|
|
|
|
|
*/
|
2022-07-19 11:49:18 +02:00
|
|
|
void *encode_bytes(const uint8_t *const value, uint8_t length) {
|
2022-05-02 11:05:25 +02:00
|
|
|
// no length check here since it will be checked by field_encode
|
2022-06-08 18:31:16 +02:00
|
|
|
return field_encode(value, length, LSB, 0x00);
|
2022-05-02 15:30:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2022-04-14 18:22:35 +02:00
|
|
|
* Encode a boolean
|
2022-05-02 15:30:14 +02:00
|
|
|
*
|
|
|
|
|
* @param[in] value pointer to the boolean received
|
|
|
|
|
* @param[in] length its byte-length
|
2022-05-02 11:05:25 +02:00
|
|
|
* @return the encoded value
|
2022-05-02 15:30:14 +02:00
|
|
|
*/
|
2022-07-19 11:49:18 +02:00
|
|
|
void *encode_boolean(const bool *const value, uint8_t length) {
|
|
|
|
|
if (length != 1) // sanity check
|
2022-05-02 15:30:14 +02:00
|
|
|
{
|
2022-07-19 11:04:16 +02:00
|
|
|
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
2022-05-02 15:30:14 +02:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2022-07-19 11:49:18 +02:00
|
|
|
return encode_uint((uint8_t *) value, length);
|
2022-05-02 15:30:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2022-04-14 18:22:35 +02:00
|
|
|
* Encode an address
|
2022-05-02 15:30:14 +02:00
|
|
|
*
|
|
|
|
|
* @param[in] value pointer to the address received
|
|
|
|
|
* @param[in] length its byte-length
|
2022-05-02 11:05:25 +02:00
|
|
|
* @return the encoded value
|
2022-05-02 15:30:14 +02:00
|
|
|
*/
|
2022-07-19 11:49:18 +02:00
|
|
|
void *encode_address(const uint8_t *const value, uint8_t length) {
|
|
|
|
|
if (length != ADDRESS_LENGTH) // sanity check
|
2022-05-02 15:30:14 +02:00
|
|
|
{
|
2022-07-19 11:04:16 +02:00
|
|
|
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
2022-05-02 15:30:14 +02:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2022-06-08 18:31:16 +02:00
|
|
|
return encode_uint(value, length);
|
2022-05-02 15:30:14 +02:00
|
|
|
}
|
2022-05-16 10:59:20 +02:00
|
|
|
|
2022-07-19 11:49:18 +02:00
|
|
|
#endif // HAVE_EIP712_FULL_SUPPORT
|