Skip to content

Commit

Permalink
fix: ton encode mismatch && add hash check (#114)
Browse files Browse the repository at this point in the history
Signed-off-by: Lu1zz <[email protected]>
  • Loading branch information
Lu1zz authored Oct 28, 2024
1 parent bfe26c1 commit c93ccad
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 24 deletions.
22 changes: 15 additions & 7 deletions legacy/firmware/ton.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,13 @@ bool ton_sign_message(const TonSignMessage *msg, const HDNode *node,
CellRef_t payload_data;
CellRef_t *payload = &payload_data;

BitString_t payload_bits_data;
bitstring_init(&payload_bits_data);
BitString_t *payload_bits = &payload_bits_data;

CellRef_t payload_ref_data;
CellRef_t *payload_ref = &payload_ref_data;

unsigned char raw_data[1024];
bool is_raw_data = false;
size_t data_len = 0;
Expand Down Expand Up @@ -203,7 +210,7 @@ bool ton_sign_message(const TonSignMessage *msg, const HDNode *node,

// create payload
if (is_raw_data) {
if (!ton_parse_boc(raw_data, data_len, payload)) {
if (!ton_parse_boc(raw_data, data_len, payload, payload_bits, payload_ref)) {
fsm_sendFailure(FailureType_Failure_ProcessError,
"Failed to create raw data body");
return false;
Expand Down Expand Up @@ -328,14 +335,15 @@ bool ton_sign_message(const TonSignMessage *msg, const HDNode *node,
return false;
}
}
bool comment_inline = (msg->jetton_amount_bytes.size == 0) && (!is_raw_data);
bool is_jetton = msg->jetton_amount_bytes.size != 0;

bool create_digest = ton_create_message_digest(
msg->expire_at, msg->seqno, parsed_dest.is_bounceable,
parsed_dest.workchain, parsed_dest.hash, msg->ton_amount, msg->mode,
msg->jetton_amount_bytes.size != 0 ? payload : NULL,
msg->jetton_amount_bytes.size == 0 ? msg->comment : NULL,
ext_destination_ptrs, msg->ext_ton_amount, ext_payload_ptrs,
ext_dest_count, digest);
!comment_inline ? payload : NULL, is_jetton,
comment_inline ? msg->comment : NULL, payload_bits, payload_ref, ext_destination_ptrs,
msg->ext_ton_amount, ext_payload_ptrs, ext_dest_count, digest);

if (!create_digest) {
fsm_sendFailure(FailureType_Failure_ProcessError,
Expand All @@ -355,8 +363,8 @@ bool ton_sign_message(const TonSignMessage *msg, const HDNode *node,
resp->signature.size = 64;
resp->has_signature = true;

resp->signning_message.size = 0;
memset(resp->signning_message.bytes, 0, resp->signning_message.size);
resp->signning_message.size = 32;
memcpy(resp->signning_message.bytes, digest, resp->signning_message.size);
resp->has_signning_message = true;

return true;
Expand Down
66 changes: 51 additions & 15 deletions legacy/firmware/ton_cell.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ bool ton_create_jetton_transfer_body(uint8_t dest_workchain, uint8_t* dest_hash,
}

bool build_message_ref(bool is_bounceable, uint8_t dest_workchain,
uint8_t* dest_hash, uint64_t value, CellRef_t* payload,
const char* payload_str, CellRef_t* out_message_ref) {
uint8_t* dest_hash, uint64_t value, CellRef_t* payload, bool is_jetton,
const char* payload_str, BitString_t* payload_bits, CellRef_t* payload_ref, CellRef_t* out_message_ref) {
BitString_t bits;
bitstring_init(&bits);

Expand Down Expand Up @@ -134,11 +134,35 @@ bool build_message_ref(bool is_bounceable, uint8_t dest_workchain,
return ton_hash_cell(&bits, NULL, 0, out_message_ref);

} else if (payload != NULL) {
bitstring_write_bit(&bits, 0); // no state-init
bitstring_write_bit(&bits, 1); // body in ref
// check if raw data inline
// if (false) {
if (bits.data_cursor + payload_bits->data_cursor <= 1023 && !is_jetton) {
bitstring_write_bit(&bits, 0); // no state-init
bitstring_write_bit(&bits, 0); // body in line

for (int i = 0; i < payload_bits->data_cursor; i++) {
int src_byte = i / 8;
int src_bit = 7 - (i % 8);
int src_value = (payload_bits->data[src_byte] >> src_bit) & 1;
bitstring_write_bit(&bits, src_value);
}

// append payload ref in message ref
if (payload->max_depth > 0) {
struct CellRef_t refs[1] = {*payload_ref};
return ton_hash_cell(&bits, refs, 1, out_message_ref);

} else {
return ton_hash_cell(&bits, NULL, 0, out_message_ref);
}

struct CellRef_t refs[1] = {*payload};
return ton_hash_cell(&bits, refs, 1, out_message_ref);
} else {
bitstring_write_bit(&bits, 0); // no state-init
bitstring_write_bit(&bits, 1); // body in ref

struct CellRef_t refs[1] = {*payload};
return ton_hash_cell(&bits, refs, 1, out_message_ref);
}
} else {
bitstring_write_bit(&bits, 0); // no state-init
bitstring_write_bit(&bits, 0); // body inline
Expand All @@ -150,15 +174,15 @@ bool build_message_ref(bool is_bounceable, uint8_t dest_workchain,
bool ton_create_message_digest(uint32_t expire_at, uint32_t seqno,
bool is_bounceable, uint8_t dest_workchain,
uint8_t* dest_hash, uint64_t value, uint8_t mode,
CellRef_t* payload, const char* payload_str,
const char** ext_dest,
CellRef_t* payload, bool is_jetton, const char* payload_str,
BitString_t* payload_bits, CellRef_t* payload_ref, const char** ext_dest,
const uint64_t* ext_ton_amount,
const char** ext_payload, uint8_t ext_dest_count,
uint8_t* digest) {
// Build Internal Message
struct CellRef_t internalMessageRef;
if (!build_message_ref(is_bounceable, dest_workchain, dest_hash, value,
payload, payload_str, &internalMessageRef)) {
payload, is_jetton, payload_str, payload_bits, payload_ref, &internalMessageRef)) {
return false;
}

Expand All @@ -180,7 +204,7 @@ bool ton_create_message_digest(uint32_t expire_at, uint32_t seqno,
unsigned int data_len = strlen(ext_payload[i]) / 2;
uint8_t raw_data[data_len];
hex2data(ext_payload[i], raw_data, &data_len);
if (!ton_parse_boc(raw_data, data_len, &ext_payload_ref)) {
if (!ton_parse_boc(raw_data, data_len, &ext_payload_ref, NULL, NULL)) {
return false;
}
} else {
Expand All @@ -197,8 +221,8 @@ bool ton_create_message_digest(uint32_t expire_at, uint32_t seqno,
if (!build_message_ref(parsed_addr.is_bounceable,
(uint8_t)parsed_addr.workchain, parsed_addr.hash,
ext_ton_amount[i],
ext_payload[i] ? &ext_payload_ref : NULL, NULL,
&extMessageRefs[ext_message_count])) {
ext_payload[i] ? &ext_payload_ref : NULL, false, NULL, NULL,
NULL, &extMessageRefs[ext_message_count])) {
return false;
}
ext_message_count++;
Expand Down Expand Up @@ -268,7 +292,7 @@ void set_top_upped_array(uint8_t* array, size_t array_len,
}

bool ton_parse_boc(const uint8_t* input_boc, size_t input_boc_len,
CellRef_t* payload) {
CellRef_t* payload, BitString_t* payload_bits, CellRef_t* payload_ref) {
if (input_boc_len < 5 || input_boc_len > 1024) {
return false;
}
Expand All @@ -287,7 +311,7 @@ bool ton_parse_boc(const uint8_t* input_boc, size_t input_boc_len,

// Parse BOC header
uint8_t flags_byte = boc[index++];
// bool has_idx = flags_byte & 0x80;
bool has_idx = flags_byte & 0x80;
// bool hash_crc32 = flags_byte & 0x40;
// bool has_cache_bits = flags_byte & 0x20;
// uint8_t flags = ((flags_byte & 0x10) << 1) | (flags_byte & 0x08);
Expand Down Expand Up @@ -328,11 +352,13 @@ bool ton_parse_boc(const uint8_t* input_boc, size_t input_boc_len,
// Read root list (always zero)
uint32_t root_cell_index = 0;
if (roots_num > 0) {
for (int i = 0; i < offset_bytes; i++) {
for (int i = 0; i < size_bytes; i++) {
root_cell_index = (root_cell_index << 8) | boc[index++];
}
}

if (has_idx) index += cells_num * offset_bytes;

// First pass: Record data and references for each cell
CellData_t cell_data[cells_num];
for (uint32_t i = 0; i < cells_num; i++) {
Expand All @@ -353,6 +379,11 @@ bool ton_parse_boc(const uint8_t* input_boc, size_t input_boc_len,
&data_cursor);
cell_data[i].bits.data_cursor = data_cursor;

if (i == 0) {
memcpy(payload_bits->data, cell_data[i].bits.data, data_bytes);
payload_bits->data_cursor = data_cursor;
}

// Read reference indices
for (int j = 0; j < cell_data[i].refs_count; j++) {
uint32_t ref_index = 0;
Expand All @@ -369,11 +400,16 @@ bool ton_parse_boc(const uint8_t* input_boc, size_t input_boc_len,
for (int j = 0; j < cell_data[i].refs_count; j++) {
refs[j] = cell_data[cell_data[i].ref_indices[j]].cell_ref;
}

if (!ton_hash_cell(&cell_data[i].bits, refs, cell_data[i].refs_count,
&cell_data[i].cell_ref)) {
fsm_sendFailure(FailureType_Failure_ProcessError, "Hash cell failed");
return false;
}

if (i == 1) {
memcpy(payload_ref, &cell_data[i].cell_ref, sizeof(CellRef_t));
}
}

// Assign the value of cell[0] to payload
Expand Down
5 changes: 3 additions & 2 deletions legacy/firmware/ton_cell.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ bool ton_create_jetton_transfer_body(uint8_t dest_workchain, uint8_t* dest_hash,
bool ton_create_message_digest(uint32_t expire_at, uint32_t seqno,
bool is_bounceable, uint8_t dest_workchain,
uint8_t* dest_hash, uint64_t value, uint8_t mode,
CellRef_t* payload, const char* payload_str,
CellRef_t* payload, bool is_jetton, const char* payload_str,
BitString_t* payload_bits, CellRef_t* payload_ref,
const char** ext_dest,
const uint64_t* ext_ton_amount,
const char** ext_payload, uint8_t ext_dest_count,
uint8_t* digest);

bool ton_parse_boc(const uint8_t* input_boc, size_t input_boc_len,
CellRef_t* payload);
CellRef_t* payload, BitString_t* payload_bits, CellRef_t* payload_ref);

0 comments on commit c93ccad

Please sign in to comment.