From c93ccad1861d4201a0d1e6aaaf8ba671428dd9d2 Mon Sep 17 00:00:00 2001 From: Lu1zz <63384033+Lu1zz@users.noreply.github.com> Date: Mon, 28 Oct 2024 22:45:52 +0800 Subject: [PATCH] fix: ton encode mismatch && add hash check (#114) Signed-off-by: Lu1zz --- legacy/firmware/ton.c | 22 +++++++++---- legacy/firmware/ton_cell.c | 66 +++++++++++++++++++++++++++++--------- legacy/firmware/ton_cell.h | 5 +-- 3 files changed, 69 insertions(+), 24 deletions(-) diff --git a/legacy/firmware/ton.c b/legacy/firmware/ton.c index a22893f81..5f2c53168 100644 --- a/legacy/firmware/ton.c +++ b/legacy/firmware/ton.c @@ -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; @@ -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; @@ -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, @@ -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; diff --git a/legacy/firmware/ton_cell.c b/legacy/firmware/ton_cell.c index a08f9b223..9f19a3a3d 100644 --- a/legacy/firmware/ton_cell.c +++ b/legacy/firmware/ton_cell.c @@ -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); @@ -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 @@ -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; } @@ -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 { @@ -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++; @@ -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; } @@ -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); @@ -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++) { @@ -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; @@ -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 diff --git a/legacy/firmware/ton_cell.h b/legacy/firmware/ton_cell.h index fd81b89e7..0c7896ea6 100644 --- a/legacy/firmware/ton_cell.h +++ b/legacy/firmware/ton_cell.h @@ -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); \ No newline at end of file + CellRef_t* payload, BitString_t* payload_bits, CellRef_t* payload_ref); \ No newline at end of file