Skip to content

Commit

Permalink
Merge pull request #226 from LedgerHQ/message-clear-sign
Browse files Browse the repository at this point in the history
Message clear sign
  • Loading branch information
bigspider authored Feb 21, 2024
2 parents 1b83e00 + f5ce807 commit fc8aacf
Show file tree
Hide file tree
Showing 15 changed files with 698 additions and 93 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"version": 1,
"rules": [
{
"regexp": "Path|Message hash",
"regexp": "Path|Message hash|Message content",
"actions": [
["button", 2, true],
["button", 2, false]
Expand Down
6 changes: 0 additions & 6 deletions src/handler/get_extended_pubkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,6 @@ void handler_get_extended_pubkey(dispatcher_context_t *dc, uint8_t protocol_vers

LOG_PROCESSOR(__FILE__, __LINE__, __func__);

// Device must be unlocked
if (os_global_pin_is_validated() != BOLOS_UX_OK) {
SEND_SW(dc, SW_SECURITY_STATUS_NOT_SATISFIED);
return;
}

uint8_t display;
uint8_t bip32_path_len;
if (!buffer_read_u8(&dc->read_buffer, &display) ||
Expand Down
6 changes: 0 additions & 6 deletions src/handler/get_master_fingerprint.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@
void handler_get_master_fingerprint(dispatcher_context_t *dc, uint8_t protocol_version) {
(void) protocol_version;

// Device must be unlocked
if (os_global_pin_is_validated() != BOLOS_UX_OK) {
SEND_SW(dc, SW_SECURITY_STATUS_NOT_SATISFIED);
return;
}

uint8_t master_pubkey[33];
if (!crypto_get_compressed_pubkey_at_path((uint32_t[]){}, 0, master_pubkey, NULL)) {
SEND_SW(dc, SW_BAD_STATE); // should never happen
Expand Down
6 changes: 0 additions & 6 deletions src/handler/get_wallet_address.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,6 @@ void handler_get_wallet_address(dispatcher_context_t *dc, uint8_t protocol_versi

LOG_PROCESSOR(__FILE__, __LINE__, __func__);

// Device must be unlocked
if (os_global_pin_is_validated() != BOLOS_UX_OK) {
SEND_SW(dc, SW_SECURITY_STATUS_NOT_SATISFIED);
return;
}

uint8_t display_address;

uint32_t address_index;
Expand Down
6 changes: 0 additions & 6 deletions src/handler/register_wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,6 @@ void handler_register_wallet(dispatcher_context_t *dc, uint8_t protocol_version)

size_t n_internal_keys = 0;

// Device must be unlocked
if (os_global_pin_is_validated() != BOLOS_UX_OK) {
SEND_SW(dc, SW_SECURITY_STATUS_NOT_SATISFIED);
return;
}

uint64_t serialized_policy_map_len;
if (!buffer_read_varint(&dc->read_buffer, &serialized_policy_map_len)) {
SEND_SW(dc, SW_WRONG_DATA_LENGTH);
Expand Down
117 changes: 100 additions & 17 deletions src/handler/sign_message.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,82 @@

#include "handlers.h"

#define MAX_DISPLAYBLE_CHUNK_NUMBER \
(5 * MESSAGE_CHUNK_PER_DISPLAY) // If the message is too long we will not display it

static unsigned char const BSM_SIGN_MAGIC[] = {'\x18', 'B', 'i', 't', 'c', 'o', 'i', 'n', ' ',
'S', 'i', 'g', 'n', 'e', 'd', ' ', 'M', 'e',
's', 's', 'a', 'g', 'e', ':', '\n'};

void handler_sign_message(dispatcher_context_t *dc, uint8_t protocol_version) {
static bool display_message_content_and_confirm(dispatcher_context_t* dc,
uint8_t* message_merkle_root,
size_t n_chunks,
uint8_t* path_str) {
reset_streaming_index();
while (get_streaming_index() <= (n_chunks - 1) / MESSAGE_CHUNK_PER_DISPLAY) {
uint8_t message_chunk[MESSAGE_MAX_DISPLAY_SIZE];

int total_chunk_len = 0;
uint8_t offset = 0;

if (get_streaming_index() > 0) {
message_chunk[offset++] = '.';
message_chunk[offset++] = '.';
message_chunk[offset++] = '.';
}

total_chunk_len += offset;

for (int j = 0; j < MESSAGE_CHUNK_PER_DISPLAY; j++) {
offset += j * MESSAGE_CHUNK_SIZE;

int chunk_len =
call_get_merkle_leaf_element(dc,
message_merkle_root,
n_chunks,
get_streaming_index() * MESSAGE_CHUNK_PER_DISPLAY + j,
message_chunk + offset,
MESSAGE_CHUNK_SIZE);

total_chunk_len += chunk_len;

if (chunk_len < MESSAGE_CHUNK_SIZE) {
break;
}
}

if ((get_streaming_index() + 1) * MESSAGE_CHUNK_PER_DISPLAY < n_chunks) {
message_chunk[total_chunk_len] = '.';
message_chunk[total_chunk_len + 1] = '.';
message_chunk[total_chunk_len + 2] = '.';
message_chunk[total_chunk_len + 3] = '\0';
} else {
message_chunk[total_chunk_len] = '\0';
}

if (!ui_display_path_and_message_content(dc,
(char*) path_str,
(char*) message_chunk,
(n_chunks - 1) / MESSAGE_CHUNK_PER_DISPLAY)) {
return false;
}
}

if (!ui_display_message_confirm(dc)) {
return false;
}

return true;
}

void handler_sign_message(dispatcher_context_t* dc, uint8_t protocol_version) {
(void) protocol_version;

uint8_t bip32_path_len;
uint32_t bip32_path[MAX_BIP32_PATH_STEPS];
uint64_t message_length;
uint8_t message_merkle_root[32];

// Device must be unlocked
if (os_global_pin_is_validated() != BOLOS_UX_OK) {
SEND_SW(dc, SW_SECURITY_STATUS_NOT_SATISFIED);
return;
}
bool printable = true;

if (!buffer_read_u8(&dc->read_buffer, &bip32_path_len) ||
!buffer_read_bip32_path(&dc->read_buffer, bip32_path, bip32_path_len) ||
Expand Down Expand Up @@ -74,21 +133,34 @@ void handler_sign_message(dispatcher_context_t *dc, uint8_t protocol_version) {
crypto_hash_update(&bsm_digest_context.header, BSM_SIGN_MAGIC, sizeof(BSM_SIGN_MAGIC));
crypto_hash_update_varint(&bsm_digest_context.header, message_length);

size_t n_chunks = (message_length + 63) / 64;
size_t n_chunks = (message_length + MESSAGE_CHUNK_SIZE - 1) / MESSAGE_CHUNK_SIZE;

if (n_chunks > MAX_DISPLAYBLE_CHUNK_NUMBER) {
printable = false;
}

for (unsigned int i = 0; i < n_chunks; i++) {
uint8_t message_chunk[64];
uint8_t message_chunk[MESSAGE_CHUNK_SIZE];
int chunk_len = call_get_merkle_leaf_element(dc,
message_merkle_root,
n_chunks,
i,
message_chunk,
sizeof(message_chunk));

if (chunk_len < 0 || (chunk_len != 64 && i != n_chunks - 1)) {
if (chunk_len < 0 || (chunk_len != MESSAGE_CHUNK_SIZE && i != n_chunks - 1)) {
SEND_SW(dc, SW_BAD_STATE); // should never happen
return;
}

if (printable) {
for (int j = 0; j < chunk_len; j++) {
if (message_chunk[j] < 0x20 || message_chunk[j] > 0x7E) {
printable = false;
break;
}
}
}
crypto_hash_update(&msg_hash_context.header, message_chunk, chunk_len);
crypto_hash_update(&bsm_digest_context.header, message_chunk, chunk_len);
}
Expand All @@ -100,17 +172,28 @@ void handler_sign_message(dispatcher_context_t *dc, uint8_t protocol_version) {
crypto_hash_digest(&bsm_digest_context.header, bsm_digest, 32);
cx_hash_sha256(bsm_digest, 32, bsm_digest, 32);

char message_hash_str[64 + 1];
for (int i = 0; i < 32; i++) {
char message_hash_str[MESSAGE_CHUNK_SIZE + 1];
for (int i = 0; i < MESSAGE_CHUNK_SIZE / 2; i++) {
snprintf(message_hash_str + 2 * i, 3, "%02X", message_hash[i]);
}

if (!ui_display_message_hash(dc, path_str, message_hash_str)) {
SEND_SW(dc, SW_DENY);
ui_post_processing_confirm_message(dc, false);
return;
ui_pre_processing_message();
if (printable) {
if (!display_message_content_and_confirm(dc,
message_merkle_root,
n_chunks,
(uint8_t*) path_str)) {
SEND_SW(dc, SW_DENY);
ui_post_processing_confirm_message(dc, false);
return;
}
} else {
if (!ui_display_message_path_hash_and_confirm(dc, path_str, message_hash_str)) {
SEND_SW(dc, SW_DENY);
ui_post_processing_confirm_message(dc, false);
return;
}
}

uint8_t sig[MAX_DER_SIG_LEN];

uint32_t info;
Expand Down
6 changes: 0 additions & 6 deletions src/handler/sign_psbt.c
Original file line number Diff line number Diff line change
Expand Up @@ -2504,12 +2504,6 @@ void handler_sign_psbt(dispatcher_context_t *dc, uint8_t protocol_version) {
sign_psbt_state_t st;
memset(&st, 0, sizeof(st));

// Device must be unlocked
if (os_global_pin_is_validated() != BOLOS_UX_OK) {
SEND_SW(dc, SW_SECURITY_STATUS_NOT_SATISFIED);
return;
}

st.protocol_version = protocol_version;

// read APDU inputs, intialize global state and read global PSBT map
Expand Down
Loading

0 comments on commit fc8aacf

Please sign in to comment.