Skip to content

Commit

Permalink
Merge pull request #231 from LedgerHQ/xch/simplify-cx-calls
Browse files Browse the repository at this point in the history
src: Use new standalone SDK hashing functions
  • Loading branch information
bigspider authored Feb 23, 2024
2 parents 4c95b0a + 1d46674 commit 205a65a
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 74 deletions.
51 changes: 13 additions & 38 deletions src/common/merkle.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,54 +24,29 @@

#include "merkle.h"

#include "cx_ram.h"
#include "debug-helpers/debug.h"

#include "ledger_assert.h"

void merkle_compute_element_hash(const uint8_t *in, size_t in_len, uint8_t out[static 32]) {
cx_sha256_t hash;
cx_sha256_init(&hash);

void merkle_compute_element_hash(const uint8_t *in,
size_t in_len,
uint8_t out[static CX_SHA256_SIZE]) {
// H(0x00 | in)
crypto_hash_update_u8(&hash.header, 0x00);
crypto_hash_update(&hash.header, in, in_len);

crypto_hash_digest(&hash.header, out, 32);
uint8_t data = 0x00;
cx_iovec_t iovec[2] = {{.iov_base = &data, .iov_len = 1}, {.iov_base = in, .iov_len = in_len}};
cx_sha256_hash_iovec(iovec, 2, out);
}

// void merkle_combine_hashes(const uint8_t left[static 32],
// const uint8_t right[static 32],
// uint8_t out[static 32]) {
// PRINT_STACK_POINTER();

// cx_sha256_t hash;
// cx_sha256_init(&hash);

// // H(0x01 | left | right)
// crypto_hash_update_u8(&hash.header, 0x01);
// crypto_hash_update(&hash.header, left, 32);
// crypto_hash_update(&hash.header, right, 32);

// crypto_hash_digest(&hash.header, out, 32);
// }

// implementation using the cxram section, in order to save ram
void merkle_combine_hashes(const uint8_t left[static 32],
const uint8_t right[static 32],
uint8_t out[static 32]) {
void merkle_combine_hashes(const uint8_t left[static CX_SHA256_SIZE],
const uint8_t right[static CX_SHA256_SIZE],
uint8_t out[static CX_SHA256_SIZE]) {
PRINT_STACK_POINTER();

cx_sha256_init_no_throw(&G_cx.sha256);

uint8_t prefix = 0x01;
LEDGER_ASSERT(cx_sha256_update(&G_cx.sha256, &prefix, 1) == CX_OK, "It never fails");

LEDGER_ASSERT(cx_sha256_update(&G_cx.sha256, left, 32) == CX_OK, "It never fails");
LEDGER_ASSERT(cx_sha256_update(&G_cx.sha256, right, 32) == CX_OK, "It never fails");

cx_sha256_final(&G_cx.sha256, out);
explicit_bzero(&G_cx.sha256, sizeof(cx_sha256_t));
cx_iovec_t iovec[3] = {{.iov_base = &prefix, .iov_len = 1},
{.iov_base = left, .iov_len = CX_SHA256_SIZE},
{.iov_base = right, .iov_len = CX_SHA256_SIZE}};
cx_sha256_hash_iovec(iovec, 3, out);
}

// TODO: make this O(log n), or possibly O(1). Currently O(log^2 n).
Expand Down
54 changes: 20 additions & 34 deletions src/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,25 +155,8 @@ int bip32_CKDpub(const serialized_extended_pubkey_t *parent,
return 0;
}

#ifndef _NR_cx_hash_ripemd160
/** Missing in some SDKs, we implement it using the cxram section if needed. */
static size_t cx_hash_ripemd160(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len) {
PRINT_STACK_POINTER();

if (out_len < CX_RIPEMD160_SIZE) {
return 0;
}
LEDGER_ASSERT(cx_ripemd160_init_no_throw((cx_ripemd160_t *) &G_cx) == CX_OK, "It never fails");
LEDGER_ASSERT(cx_ripemd160_update((cx_ripemd160_t *) &G_cx, in, in_len) == CX_OK,
"It never fails");
LEDGER_ASSERT(cx_ripemd160_final((cx_ripemd160_t *) &G_cx, out) == CX_OK, "It never fails");
explicit_bzero((cx_ripemd160_t *) &G_cx, sizeof(cx_sha256_t));
return CX_RIPEMD160_SIZE;
}
#endif // _NR_cx_hash_ripemd160

void crypto_ripemd160(const uint8_t *in, uint16_t inlen, uint8_t out[static 20]) {
cx_hash_ripemd160(in, inlen, out, 20);
cx_ripemd160_hash(in, inlen, out);
}

void crypto_hash160(const uint8_t *in, uint16_t inlen, uint8_t out[static 20]) {
Expand Down Expand Up @@ -473,22 +456,25 @@ static int crypto_tr_lift_x(const uint8_t x[static 32], uint8_t out[static 65])

// Computes a tagged hash according to BIP-340.
// If data2_len > 0, then data2 must be non-NULL and the `data` and `data2` arrays are concatenated.
// Somewhat weird signature, but this helps to optimize stack usage.
static void __attribute__((noinline)) crypto_tr_tagged_hash(const uint8_t *tag,
uint16_t tag_len,
const uint8_t *data,
uint16_t data_len,
const uint8_t *data2,
uint16_t data2_len,
uint8_t out[static 32]) {
cx_sha256_t hash_context;
cx_sha256_init(&hash_context);

crypto_tr_tagged_hash_init(&hash_context, tag, tag_len);

crypto_hash_update(&hash_context.header, data, data_len);
if (data2_len > 0) crypto_hash_update(&hash_context.header, data2, data2_len);
crypto_hash_digest(&hash_context.header, out, 32);
static void crypto_tr_tagged_hash(const uint8_t *tag,
uint16_t tag_len,
const uint8_t *data,
uint16_t data_len,
const uint8_t *data2,
uint16_t data2_len,
uint8_t out[static CX_SHA256_SIZE]) {
// First compute hashtag, reuse out buffer for that
cx_sha256_hash(tag, tag_len, out);

cx_iovec_t iovec[4] = {{.iov_base = out, .iov_len = CX_SHA256_SIZE},
{.iov_base = out, .iov_len = CX_SHA256_SIZE},
{.iov_base = data, .iov_len = data_len},
{.iov_base = data2, .iov_len = data2_len}};
if (data2_len > 0) {
cx_sha256_hash_iovec(iovec, 4, out);
} else {
cx_sha256_hash_iovec(iovec, 3, out);
}
}

void crypto_tr_combine_taptree_hashes(const uint8_t left_h[static 32],
Expand Down
3 changes: 1 addition & 2 deletions src/cxram_stash.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
#include "cxram_stash.h"
#include "cx_ram.h"

#ifdef USE_CXRAM_SECTION
#ifndef G_cx
// The G_cx symbol is only defined in the sdk if compiled with certain libs are included.
// This makes sure that the symbol exists nonetheless.
union cx_u G_cx;
#endif

#ifdef USE_CXRAM_SECTION

uint8_t *get_cxram_buffer() {
return (uint8_t *) &G_cx;
}
Expand Down

0 comments on commit 205a65a

Please sign in to comment.