Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Ledger Vulnerabilities #2

Merged
merged 35 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
cd1ff73
fix: app update audit fix
Z4karia Oct 28, 2024
4758913
bump version
Z4karia Oct 28, 2024
980875b
Merge pull request #19 from blooo-io/fix/app-update-audit-fix
Z4karia Oct 29, 2024
a8126c8
ui: update function name
Z4karia Oct 29, 2024
3dfc63e
update credits
Z4karia Oct 29, 2024
1c2a34a
ui: update function name
Z4karia Oct 29, 2024
50b42c2
Merge pull request #20 from blooo-io/fix/app-update-audit-fix
Z4karia Oct 30, 2024
c3118e2
fix: resolve possible out of bound issue
keiff3r Nov 6, 2024
cede993
fix: patch potential integer underflow
keiff3r Nov 6, 2024
1f68a32
fix: disable debuging
keiff3r Nov 6, 2024
f958dd5
fix: add a check before using variable
keiff3r Nov 6, 2024
7a10c09
fix: handle weakness
keiff3r Nov 6, 2024
e3c24ae
fix: add a condition in display_data_content_and_confirm
keiff3r Nov 7, 2024
e6b9553
chore: bump version
keiff3r Nov 7, 2024
3443fb6
fix: remove compilation warning
keiff3r Nov 7, 2024
a7d8e22
fix: always include debug helpers header
keiff3r Nov 7, 2024
a71d92e
test: generate golden snapshots
keiff3r Nov 7, 2024
256eecc
style: change copyright from Blooo to Acre
keiff3r Nov 7, 2024
f560302
chore: update Makefile for debug configuration
keiff3r Nov 7, 2024
4a187a7
fix: added missing refs for debug tools
n4l5u0r Nov 7, 2024
6b22bc5
style: change developer from Blooo to Acre
keiff3r Nov 7, 2024
cf8f68c
Merge pull request #21 from blooo-io/fix/address-ledger-audit-vuln
keiff3r Nov 7, 2024
f704e80
fix: applied similar derivation path as bitcoin app to enable fingerp…
n4l5u0r Nov 9, 2024
1f7273a
Merge pull request #23 from blooo-io/fix/LDG-494--app-fix-fingerprint…
n4l5u0r Nov 11, 2024
fe7d6a4
fix:bump version
n4l5u0r Nov 11, 2024
375fff4
fix: adjusted snapshot
n4l5u0r Nov 11, 2024
a0b66f4
fxi: aligned snapshots
n4l5u0r Nov 11, 2024
67d9467
Merge pull request #24 from blooo-io/fix/bump-version-1-1-3
n4l5u0r Nov 12, 2024
b3d0952
fix: initialise DEBUG properly
keiff3r Nov 7, 2024
a28051a
fix(handler/withdraw): Correct `compute_tx_hash` 's implementation
keiff3r Nov 14, 2024
0ec4af6
chore: bump version
keiff3r Nov 14, 2024
7677568
fix: disable DEBUG in Makefile
keiff3r Nov 14, 2024
5e69551
test: generate golden snapshots
keiff3r Nov 14, 2024
3b072b1
fix: correct expected signature
keiff3r Nov 14, 2024
07dc817
Merge pull request #25 from blooo-io/fix/LDG-493--app-fix-withdrawal-…
keiff3r Nov 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,5 @@ doc/latex

tests/snapshots-tmp
tests/bitcoin

.DS_Store
7 changes: 5 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
"C_Cpp.clang_format_path": "/usr/bin/clang-format",
"editor.formatOnSave": true,
"ledgerDevTools.appSettings": {
"selectedUseCase": "release"
}
"selectedUseCase": "release",
"selectedDevice": "Stax",
"selectedVariant": "acre"
},
"makefile.configureOnOpen": false
}
15 changes: 10 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ include $(BOLOS_SDK)/Makefile.defines
CURVE_APP_LOAD_PARAMS = secp256k1

# Application allowed derivation paths.
PATH_APP_LOAD_PARAMS = "44'/0'" "44'/1'" "48'/0'" "48'/1'" "49'/0'" "49'/1'" "84'/0'" "84'/1'" "86'/0'" "86'/1'"
PATH_APP_LOAD_PARAMS = ""
# Specific paths below are not supported for fingerprinting methods on real devices, supported by speculos
# PATH_APP_LOAD_PARAMS = "0'/0'" "0'/1'" "44'/0'" "44'/1'" "48'/0'" "48'/1'" "49'/0'" "49'/1'" "84'/0'" "84'/1'" "86'/0'" "86'/1'"


# Application version
APPVERSION_M = 1
APPVERSION_N = 1
APPVERSION_P = 0
APPVERSION_P = 4
APPVERSION_SUFFIX = # if not empty, appended at the end. Do not add a dash.

ifeq ($(APPVERSION_SUFFIX),)
Expand Down Expand Up @@ -158,17 +160,20 @@ DEFINES += HAVE_BOLOS_APP_STACK_CANARY

DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300

# debugging helper functions and macros
CFLAGS += -g -include debug-helpers/debug.h

# DEFINES += HAVE_PRINT_STACK_POINTER

DEBUG = 0 # 0 for production, 1 for debug
# 0 for production, 1 for debug
DEBUG = 0
ifeq ($(DEBUG),10)
$(warning Using semihosted PRINTF. Only run with speculos!)
DEFINES += HAVE_PRINTF HAVE_SEMIHOSTED_PRINTF PRINTF=semihosted_printf
endif

ifeq ($(DEBUG),1)
# debugging helper functions and macros
CFLAGS += -include debug-helpers/debug.h -g
endif
# Needed to be able to include the definition of G_cx
INCLUDES_PATH += $(BOLOS_SDK)/lib_cxng/src

Expand Down
1 change: 1 addition & 0 deletions src/debug-helpers/debug.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdarg.h>
#include "printf.h"
#include "debug.h"

#pragma GCC diagnostic ignored "-Wunused-function"

Expand Down
17 changes: 14 additions & 3 deletions src/handler/lib/get_merkle_preimage.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ int call_get_merkle_preimage(dispatcher_context_t *dispatcher_context,
cx_sha256_init(&hash_context);

// update hash
crypto_hash_update(&hash_context.header, data_ptr, partial_data_len);
int ret = cx_hash_no_throw(&hash_context.header, 0, data_ptr, partial_data_len, NULL, 0);
if (ret != 0) {
PRINTF("Error updating hash\n");
return -11;
}

buffer_t out_buffer = buffer_create(out_ptr, out_ptr_len);

Expand Down Expand Up @@ -98,10 +102,17 @@ int call_get_merkle_preimage(dispatcher_context_t *dispatcher_context,
}

// update hash
crypto_hash_update(
ret = cx_hash_no_throw(
&hash_context.header,
0,
dispatcher_context->read_buffer.ptr + dispatcher_context->read_buffer.offset,
n_bytes);
n_bytes,
NULL,
0);
if (ret != 0) {
PRINTF("Error updating hash\n");
return -12;
}

// write bytes to output
buffer_write_bytes(&out_buffer, data_ptr, n_bytes);
Expand Down
85 changes: 59 additions & 26 deletions src/handler/sign_erc4361_message.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,35 @@ typedef struct {
size_t max_length;
} ERC4361Field;

static size_t parse_field(const uint8_t *buffer,
size_t buffer_len,
char *output,
size_t max_length) {
static int parse_field(const uint8_t *buffer, size_t buffer_len, char *output, size_t max_length) {
// Add NULL check
if (buffer == NULL || output == NULL) {
return -1;
}

// Check buffer_len to prevent buffer overflow
if (buffer_len == 0 || max_length == 0) {
return -1;
}

size_t field_length = 0;
while (field_length < buffer_len && field_length < max_length - 1) {
// Ensure we don't exceed buffer_len or max_length-1 (for null terminator)
const size_t max_field_length = (buffer_len < max_length - 1) ? buffer_len : max_length - 1;

while (field_length < max_field_length) {
// Safe to dereference buffer here as we've checked both pointer and bounds
if (buffer[field_length] == '\n' || buffer[field_length] == '\0' ||
buffer[field_length] == ' ') {
break;
}
field_length++;
}

// Safe to use memcpy as we've validated both source and destination
memcpy(output, buffer, field_length);
output[field_length] = '\0';

return field_length;
return (int) field_length; // Safe cast as field_length is bounded by max_field_length
}

static bool has_newline(const char *buffer, size_t length) {
Expand All @@ -62,6 +74,12 @@ static bool has_newline(const char *buffer, size_t length) {
}

void handler_sign_erc4361_message(dispatcher_context_t *dc, uint8_t protocol_version) {
// Add NULL check with status word
if (dc == NULL) {
SAFE_SEND_SW(dc, SW_BAD_STATE);
return;
}

(void) protocol_version;

uint8_t bip32_path_len;
Expand Down Expand Up @@ -172,15 +190,23 @@ void handler_sign_erc4361_message(dispatcher_context_t *dc, uint8_t protocol_ver
}

if (current_line == 0) {
size_t domain_length =
int domain_length =
parse_field(parsing_buffer, parsing_buffer_len, domain, MAX_DOMAIN_LENGTH);
if (domain_length < 0) {
SAFE_SEND_SW(dc, SW_BAD_STATE);
return;
}
total_bytes_read += domain_length;
PRINTF("Domain: %s\n", domain);
}

if (current_line == 1) {
size_t address_length =
int address_length =
parse_field(parsing_buffer, parsing_buffer_len, address, MAX_ADDRESS_LENGTH_STR);
if (address_length < 0) {
SAFE_SEND_SW(dc, SW_BAD_STATE);
return;
}
total_bytes_read += address_length;
PRINTF("Address: %s\n", address);
}
Expand All @@ -191,10 +217,14 @@ void handler_sign_erc4361_message(dispatcher_context_t *dc, uint8_t protocol_ver
ERC4361Field *field = &fields[i];
if (parsing_buffer_len >= field->name_length &&
memcmp(parsing_buffer, field->name, field->name_length) == 0) {
size_t field_length = parse_field(parsing_buffer + field->name_length,
parsing_buffer_len - field->name_length,
field->output,
field->max_length);
int field_length = parse_field(parsing_buffer + field->name_length,
parsing_buffer_len - field->name_length,
field->output,
field->max_length);
if (field_length < 0) {
SAFE_SEND_SW(dc, SW_BAD_STATE);
return;
}
total_bytes_read += field_length + field->name_length;
PRINTF("%s%s\n", field->name, field->output);
break;
Expand Down Expand Up @@ -247,9 +277,7 @@ void handler_sign_erc4361_message(dispatcher_context_t *dc, uint8_t protocol_ver
issued_at,
expiration_time)) {
SAFE_SEND_SW(dc, SW_DENY);
if (!ui_post_processing_confirm_message(dc, false)) {
PRINTF("Error in ui_post_processing_confirm_message");
}
ui_post_processing_confirm_message(dc, false);
return;
}
#endif
Expand All @@ -265,9 +293,7 @@ void handler_sign_erc4361_message(dispatcher_context_t *dc, uint8_t protocol_ver
if (sig_len < 0) {
// unexpected error when signing
SAFE_SEND_SW(dc, SW_BAD_STATE);
if (!ui_post_processing_confirm_message(dc, false)) {
PRINTF("Error in ui_post_processing_confirm_message");
}
ui_post_processing_confirm_message(dc, false);
return;
}

Expand All @@ -277,15 +303,24 @@ void handler_sign_erc4361_message(dispatcher_context_t *dc, uint8_t protocol_ver
uint8_t result[65];
memset(result, 0, sizeof(result));

// Verify r_length won't cause buffer overflow
if (sig[3] > MAX_DER_SIG_LEN - 5) { // -5 accounts for DER header and s_length byte
SAFE_SEND_SW(dc, SW_BAD_STATE);
ui_post_processing_confirm_message(dc, false);
return;
}
// # Format signature into standard bitcoin format
int r_length = sig[3];
int s_length = sig[4 + r_length + 1];
if (r_length < 0 || r_length > 33) {
SAFE_SEND_SW(dc, SW_BAD_STATE); // can never happen
ui_post_processing_confirm_message(dc, false);
return;
}

if (r_length > 33 || s_length > 33) {
int s_length = sig[4 + r_length + 1];
if (s_length < 0 || s_length > 33) {
SAFE_SEND_SW(dc, SW_BAD_STATE); // can never happen
if (!ui_post_processing_confirm_message(dc, false)) {
PRINTF("Error in ui_post_processing_confirm_message");
}
ui_post_processing_confirm_message(dc, false);
return;
}

Expand All @@ -301,9 +336,7 @@ void handler_sign_erc4361_message(dispatcher_context_t *dc, uint8_t protocol_ver
result[0] = 27 + 4 + ((info & CX_ECCINFO_PARITY_ODD) ? 1 : 0);

SEND_RESPONSE(dc, result, sizeof(result), SW_OK);
if (!ui_post_processing_confirm_message(dc, true)) {
PRINTF("Error in ui_post_processing_confirm_message");
}
ui_post_processing_confirm_message(dc, true);
return;
}
}
Loading
Loading