Fix hashing of signed negative integers smaller than 256 bits
This commit is contained in:
@@ -14,28 +14,32 @@ typedef enum
|
|||||||
} e_padding_type;
|
} e_padding_type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode a field value to 32 bytes (0 padded)
|
* Encode a field value to 32 bytes (padded)
|
||||||
*
|
*
|
||||||
* @param[in] value field value to encode
|
* @param[in] value field value to encode
|
||||||
* @param[in] length field length before encoding
|
* @param[in] length field length before encoding
|
||||||
|
* @param[in] ptype padding direction (LSB vs MSB)
|
||||||
|
* @param[in] pval value used for padding
|
||||||
* @return encoded field value
|
* @return encoded field value
|
||||||
*/
|
*/
|
||||||
static void *field_encode(const uint8_t *const value, uint8_t length, e_padding_type ptype)
|
static void *field_encode(const uint8_t *const value,
|
||||||
|
uint8_t length,
|
||||||
|
e_padding_type ptype,
|
||||||
|
uint8_t pval)
|
||||||
{
|
{
|
||||||
uint8_t *padded_value;
|
uint8_t *padded_value;
|
||||||
uint8_t start_idx;
|
uint8_t start_idx;
|
||||||
|
|
||||||
if (length > 32) // sanity check
|
if (length > EIP_712_ENCODED_FIELD_LENGTH) // sanity check
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// 0-pad the value to 32 bytes
|
|
||||||
if ((padded_value = mem_alloc(EIP_712_ENCODED_FIELD_LENGTH)) != NULL)
|
if ((padded_value = mem_alloc(EIP_712_ENCODED_FIELD_LENGTH)) != NULL)
|
||||||
{
|
{
|
||||||
switch (ptype)
|
switch (ptype)
|
||||||
{
|
{
|
||||||
case MSB:
|
case MSB:
|
||||||
explicit_bzero(padded_value, EIP_712_ENCODED_FIELD_LENGTH - length);
|
memset(padded_value, pval, EIP_712_ENCODED_FIELD_LENGTH - length);
|
||||||
start_idx = EIP_712_ENCODED_FIELD_LENGTH - length;
|
start_idx = EIP_712_ENCODED_FIELD_LENGTH - length;
|
||||||
break;
|
break;
|
||||||
case LSB:
|
case LSB:
|
||||||
@@ -45,25 +49,46 @@ static void *field_encode(const uint8_t *const value, uint8_t length, e_padding_
|
|||||||
default:
|
default:
|
||||||
return NULL; // should not be here
|
return NULL; // should not be here
|
||||||
}
|
}
|
||||||
for (uint8_t idx = 0; idx < length; ++idx)
|
memcpy(&padded_value[start_idx], value, length);
|
||||||
{
|
|
||||||
padded_value[start_idx + idx] = value[idx];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return padded_value;
|
return padded_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode an integer
|
* Encode an unsigned integer
|
||||||
*
|
*
|
||||||
* @param[in] value pointer to the "packed" integer received
|
* @param[in] value pointer to the "packed" integer received
|
||||||
* @param[in] length its byte-length
|
* @param[in] length its byte-length
|
||||||
* @return the encoded value
|
* @return the encoded value
|
||||||
*/
|
*/
|
||||||
void *encode_integer(const uint8_t *const value, uint8_t length)
|
void *encode_uint(const uint8_t *const value, uint8_t length)
|
||||||
{
|
{
|
||||||
// no length check here since it will be checked by field_encode
|
// no length check here since it will be checked by field_encode
|
||||||
return field_encode(value, length, MSB);
|
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
|
||||||
|
*/
|
||||||
|
void *encode_int(const uint8_t *const value, uint8_t length, uint8_t typesize)
|
||||||
|
{
|
||||||
|
uint8_t padding_value;
|
||||||
|
|
||||||
|
if ((length == typesize) && (value[0] & (1 << 7))) // negative number
|
||||||
|
{
|
||||||
|
padding_value = 0xFF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
padding_value = 0x00;
|
||||||
|
}
|
||||||
|
// no length check here since it will be checked by field_encode
|
||||||
|
return field_encode(value, length, MSB, padding_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,7 +101,7 @@ void *encode_integer(const uint8_t *const value, uint8_t length)
|
|||||||
void *encode_bytes(const uint8_t *const value, uint8_t length)
|
void *encode_bytes(const uint8_t *const value, uint8_t length)
|
||||||
{
|
{
|
||||||
// no length check here since it will be checked by field_encode
|
// no length check here since it will be checked by field_encode
|
||||||
return field_encode(value, length, LSB);
|
return field_encode(value, length, LSB, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,7 +117,7 @@ void *encode_boolean(const bool *const value, uint8_t length)
|
|||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return encode_integer((uint8_t*)value, length);
|
return encode_uint((uint8_t*)value, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -108,7 +133,7 @@ void *encode_address(const uint8_t *const value, uint8_t length)
|
|||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return encode_integer(value, length);
|
return encode_uint(value, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||||
|
|||||||
@@ -8,7 +8,8 @@
|
|||||||
|
|
||||||
#define EIP_712_ENCODED_FIELD_LENGTH 32
|
#define EIP_712_ENCODED_FIELD_LENGTH 32
|
||||||
|
|
||||||
void *encode_integer(const uint8_t *const value, uint8_t length);
|
void *encode_uint(const uint8_t *const value, uint8_t length);
|
||||||
|
void *encode_int(const uint8_t *const value, uint8_t length, uint8_t typesize);
|
||||||
void *encode_boolean(const bool *const value, uint8_t length);
|
void *encode_boolean(const bool *const value, uint8_t length);
|
||||||
void *encode_address(const uint8_t *const value, uint8_t length);
|
void *encode_address(const uint8_t *const value, uint8_t length);
|
||||||
void *encode_bytes(const uint8_t *const value, uint8_t length);
|
void *encode_bytes(const uint8_t *const value, uint8_t length);
|
||||||
|
|||||||
@@ -115,8 +115,10 @@ bool field_hash(const uint8_t *data,
|
|||||||
switch (field_type)
|
switch (field_type)
|
||||||
{
|
{
|
||||||
case TYPE_SOL_INT:
|
case TYPE_SOL_INT:
|
||||||
|
value = encode_int(data, data_length, get_struct_field_typesize(field_ptr));
|
||||||
|
break;
|
||||||
case TYPE_SOL_UINT:
|
case TYPE_SOL_UINT:
|
||||||
value = encode_integer(data, data_length);
|
value = encode_uint(data, data_length);
|
||||||
break;
|
break;
|
||||||
case TYPE_SOL_BYTES_FIX:
|
case TYPE_SOL_BYTES_FIX:
|
||||||
value = encode_bytes(data, data_length);
|
value = encode_bytes(data, data_length);
|
||||||
|
|||||||
Reference in New Issue
Block a user