From 7e35b96ec0982a9f0fea4a93c08d6303967d1a2b Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Mon, 2 May 2022 15:30:14 +0200 Subject: [PATCH] WIP field hashing --- src_features/signMessageEIP712/encode_field.c | 129 ++++++++++++++++++ src_features/signMessageEIP712/encode_field.h | 15 ++ src_features/signMessageEIP712/entrypoint.c | 2 + src_features/signMessageEIP712/field_hash.c | 14 ++ src_features/signMessageEIP712/field_hash.h | 9 ++ 5 files changed, 169 insertions(+) create mode 100644 src_features/signMessageEIP712/encode_field.c create mode 100644 src_features/signMessageEIP712/encode_field.h create mode 100644 src_features/signMessageEIP712/field_hash.c create mode 100644 src_features/signMessageEIP712/field_hash.h diff --git a/src_features/signMessageEIP712/encode_field.c b/src_features/signMessageEIP712/encode_field.c new file mode 100644 index 0000000..e075f4d --- /dev/null +++ b/src_features/signMessageEIP712/encode_field.c @@ -0,0 +1,129 @@ +#include +#include +#include "encode_field.h" +#include "mem.h" +#include "eip712.h" +#include "shared_context.h" + + +/** + * Hash field value + * + * @param[in] value pointer to value + * @param[in] length its bytelength + * @param[in] dealloc if the value length should be deallocated from the memory + */ +static void *hash_field_value(const void *const value, uint16_t length, bool dealloc) +{ + uint8_t *hash_ptr = NULL; + + if (value != NULL) + { + cx_keccak_init((cx_hash_t*)&global_sha3, 256); + cx_hash((cx_hash_t*)&global_sha3, + 0, + (uint8_t*)value, + length, + NULL, + 0); + + if (dealloc) + { + // restore the memory location + mem_dealloc(length); + } + + if ((hash_ptr = mem_alloc(KECCAK256_HASH_BYTESIZE)) == NULL) + { + return NULL; + } + + // copy hash into memory + cx_hash((cx_hash_t*)&global_sha3, + CX_LAST, + NULL, + 0, + hash_ptr, + KECCAK256_HASH_BYTESIZE); + } + return hash_ptr; +} + +/** + * Encode an integer and hash it + * + * @param[in] value pointer to the "packed" integer received + * @param[in] length its byte-length + * @return the encoded (hashed) value + */ +void *encode_integer(const uint8_t *const value, uint16_t length) +{ + uint8_t *padded_value; + + // 0-pad the value to 32 bytes + if ((padded_value = mem_alloc(EIP_712_ENCODED_FIELD_LENGTH)) != NULL) + { + explicit_bzero(padded_value, EIP_712_ENCODED_FIELD_LENGTH - length); + for (uint8_t idx = 0; idx < length; ++idx) + { + padded_value[EIP_712_ENCODED_FIELD_LENGTH - (length - idx)] = value[idx]; + } + } + return hash_field_value(padded_value, EIP_712_ENCODED_FIELD_LENGTH, true); +} + +/** + * Encode a string and hash it + * + * @param[in] value pointer to the string received + * @param[in] length its byte-length + * @return the encoded (hashed) value + */ +void *encode_string(const char *const value, uint16_t length) +{ + return hash_field_value(value, length, false); +} + +/** + * Encode a boolean and hash it + * + * @param[in] value pointer to the boolean received + * @param[in] length its byte-length + * @return the encoded (hashed) value + */ +void *encode_bool(const bool *const value, uint16_t length) +{ + if (length != 1) + { + return NULL; + } + return encode_integer((uint8_t*)value, length); +} + +/** + * Encode an address and hash it + * + * @param[in] value pointer to the address received + * @param[in] length its byte-length + * @return the encoded (hashed) value + */ +void *encode_address(const uint8_t *const value, uint16_t length) +{ + if (length != ADDRESS_LENGTH) + { + return NULL; + } + return encode_integer(value, length); +} + +/** + * Encode bytes and hash it + * + * @param[in] value pointer to the bytes received + * @param[in] length its byte-length + * @return the encoded (hashed) value + */ +void *encode_bytes(const uint8_t *const value, uint16_t length) +{ + return hash_field_value(value, length, false); +} diff --git a/src_features/signMessageEIP712/encode_field.h b/src_features/signMessageEIP712/encode_field.h new file mode 100644 index 0000000..eea2429 --- /dev/null +++ b/src_features/signMessageEIP712/encode_field.h @@ -0,0 +1,15 @@ +#ifndef ENCODE_FIELD_H_ +#define ENCODE_FIELD_H_ + +#include +#include + +#define EIP_712_ENCODED_FIELD_LENGTH 32 + +void *encode_integer(const uint8_t *const value, uint16_t length); +void *encode_string(const char *const value, uint16_t length); +void *encode_bool(const bool *const value, uint16_t length); +void *encode_address(const uint8_t *const value, uint16_t length); +void *encode_bytes(const uint8_t *const value, uint16_t length); + +#endif // ENCODE_FIELD_H_ diff --git a/src_features/signMessageEIP712/entrypoint.c b/src_features/signMessageEIP712/entrypoint.c index 9e85e40..f265ad7 100644 --- a/src_features/signMessageEIP712/entrypoint.c +++ b/src_features/signMessageEIP712/entrypoint.c @@ -9,6 +9,7 @@ #include "type_hash.h" #include "context.h" #include "sol_typenames.h" +#include "field_hash.h" // lib functions @@ -381,6 +382,7 @@ bool handle_apdu(const uint8_t *const data) type_hash(structs_array, (char*)&data[OFFSET_DATA], data[OFFSET_LC]); break; case P2_FIELD: + field_hash(structs_array, &data[OFFSET_DATA], data[OFFSET_LC]); break; case P2_ARRAY: break; diff --git a/src_features/signMessageEIP712/field_hash.c b/src_features/signMessageEIP712/field_hash.c new file mode 100644 index 0000000..db7b38f --- /dev/null +++ b/src_features/signMessageEIP712/field_hash.c @@ -0,0 +1,14 @@ +#include +#include "field_hash.h" +#include "encode_field.h" + +const uint8_t *field_hash(const void *const structs_array, + const uint8_t *const data, + const uint8_t data_length) +{ + (void)structs_array; + (void)data; + (void)data_length; + encode_integer(data, data_length); + return NULL; +} diff --git a/src_features/signMessageEIP712/field_hash.h b/src_features/signMessageEIP712/field_hash.h new file mode 100644 index 0000000..9b2a2ac --- /dev/null +++ b/src_features/signMessageEIP712/field_hash.h @@ -0,0 +1,9 @@ +#ifndef FIELD_HASH_H_ +#define FIELD_HASH_H_ + +#include + +const uint8_t *field_hash(const void *const structs_array, + const uint8_t *const data, + const uint8_t data_length); +#endif // FIELD_HASH_H_