Skip to content

Commit

Permalink
Merge pull request #33 from LedgerHQ/develop
Browse files Browse the repository at this point in the history
Merge to master
  • Loading branch information
cedelavergne-ledger authored Sep 20, 2024
2 parents 5089b38 + 9922a20 commit ac22933
Show file tree
Hide file tree
Showing 24 changed files with 234 additions and 178 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/continuous-integration-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,18 @@ jobs:

steps:
- name: Clone
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Download app binary
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: binaries
path: bin

- name: Install Speculos
run: |
sudo apt-get update && sudo apt-get install -y qemu-user-static
pip install --extra-index-url https://test.pypi.org/simple/ speculos
pip install speculos
- name: Setup node
uses: actions/setup-node@v3
Expand Down
16 changes: 9 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ GIT_DESCRIBE ?= $(shell git describe --tags --abbrev=8 --always --long --dirty 2

VERSION_TAG ?= $(shell echo "$(GIT_DESCRIBE)" | cut -f1 -d-)
APPVERSION_M=0
APPVERSION_N=5
APPVERSION_P=7
APPVERSION_N=6
APPVERSION_P=0
APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)

# Only warn about version tags if specified/inferred
Expand All @@ -32,11 +32,13 @@ else
endif

ifeq ($(TARGET_NAME),TARGET_NANOS)
ICONNAME=icons/nano-s-nervos.gif
ICONNAME=icons/nanos-nervos.gif
else ifeq ($(TARGET_NAME), TARGET_STAX)
ICONNAME=icons/stax_app_nervos.gif
else ifeq ($(TARGET_NAME), TARGET_FLEX)
ICONNAME=icons/flex_app_nervos.gif
else # NANOX & NANOS+
ICONNAME=icons/nano-x-nervos.gif
ICONNAME=icons/nanox-nervos.gif
endif

################
Expand All @@ -63,7 +65,7 @@ DEFINES += COMMIT=\"$(COMMIT)\" APPVERSION_N=$(APPVERSION_N) APPVERSION_P=$(AP
# DEFINES += _Static_assert\(...\)=
DEFINES += APPNAME=\"$(APPNAME)\"

ifneq (,$(filter $(TARGET_NAME),TARGET_NANOX TARGET_STAX))
ifneq (,$(filter $(TARGET_NAME),TARGET_NANOX TARGET_STAX TARGET_FLEX))
APP_LOAD_PARAMS += --appFlags 0x240 # with BLE support
DEFINES += HAVE_BLE BLE_COMMAND_TIMEOUT_MS=2000
DEFINES += HAVE_BLE_APDU # basic ledger apdu transport over BLE
Expand All @@ -78,7 +80,7 @@ else
DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300
endif

ifeq ($(TARGET_NAME),TARGET_STAX)
ifneq (,$(filter $(TARGET_NAME),TARGET_STAX TARGET_FLEX))
DEFINES += NBGL_QRCODE
SDK_SOURCE_PATH += qrcode
else
Expand Down Expand Up @@ -161,7 +163,7 @@ include $(BOLOS_SDK)/Makefile.glyphs
APP_SOURCE_PATH += src
SDK_SOURCE_PATH += lib_stusb lib_stusb_impl

ifneq ($(TARGET_NAME),TARGET_STAX)
ifeq (,$(filter $(TARGET_NAME),TARGET_STAX TARGET_FLEX))
SDK_SOURCE_PATH += lib_ux
endif

Expand Down
File renamed without changes
Binary file added icons/flex_app_nervos.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
File renamed without changes
2 changes: 1 addition & 1 deletion ledger_app.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[app]
build_directory = "./"
sdk = "C"
devices = ["nanos", "nanox", "nanos+", "stax"]
devices = ["nanos", "nanox", "nanos+", "stax", "flex"]
7 changes: 4 additions & 3 deletions src/apdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ void handle_apdu_get_wallet_id(uint8_t __attribute__((unused)) instruction) {

int rv = 0;
cx_blake2b_t hashState;
cx_blake2b_init(&hashState, 512);
CX_ASSERT(cx_blake2b_init_no_throw(&hashState, 512));

WITH_KEY_PAIR(id_path, key_pair, size_t, ({
PRINTF("\nPublic Key: %.*h\n", key_pair->public_key.W_len, key_pair->public_key.W);
Expand All @@ -73,8 +73,9 @@ void handle_apdu_get_wallet_id(uint8_t __attribute__((unused)) instruction) {
// Stubbed until we have the sign step working.
// rv = cx_hash((cx_hash_t*) &hashState, CX_LAST, signedToken, sizeof(signedToken),
// G_io_apdu_buffer, sizeof(G_io_apdu_buffer));
rv = cx_hash((cx_hash_t *)&hashState, CX_LAST, (uint8_t *)key_pair->public_key.W,
key_pair->public_key.W_len, G_io_apdu_buffer, sizeof(G_io_apdu_buffer));
CX_ASSERT(cx_hash_no_throw((cx_hash_t *)&hashState, CX_LAST, (uint8_t *)key_pair->public_key.W,
key_pair->public_key.W_len, G_io_apdu_buffer, sizeof(G_io_apdu_buffer)));
rv = cx_hash_get_size((cx_hash_t *)&hashState);
}));
delay_successful(rv);
}
Expand Down
4 changes: 0 additions & 4 deletions src/apdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@

#include "apdu_pubkey.h"

#if CX_APILEVEL < 8
#error "May only compile with API level 8 or higher; requires newer firmware"
#endif

#define OFFSET_CLA 0
#define OFFSET_INS 1 // instruction code
#define OFFSET_P1 2 // user-defined 1-byte parameter
Expand Down
15 changes: 4 additions & 11 deletions src/apdu_pubkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,9 @@ static void bip32_path_to_string(char *const out, size_t const out_size, apdu_pu
}

void render_pkh(char *const out, size_t const out_size,
render_address_payload_t const *const payload) {
render_address_payload_t const *const payload, size_t payload_len) {
uint8_t base32_buf[256];
size_t base32_len = 0;
size_t payload_len = 0;
bool is_bech32m = 0;
if (payload->full_version.address_format_type == ADDRESS_FORMAT_TYPE_FULL_VERSION) {
payload_len = sizeof(payload->full_version);
is_bech32m = 1;
} else if (payload->short_version.address_format_type == ADDRESS_FORMAT_TYPE_SHORT) {
payload_len = sizeof(payload->short_version);
} else {
payload_len = sizeof(payload->code_hash_data_or_type);
}

if (!convert_bits(base32_buf, sizeof(base32_buf), &base32_len,
5,
Expand All @@ -75,6 +65,9 @@ void render_pkh(char *const out, size_t const out_size,
THROW(EXC_MEMORY_ERROR);
}
static const char hrbs[][4] = {"ckb", "ckt"};
// https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0021-ckb-address-format/0021-ckb-address-format.md#full-payload-format
// CKB addresses are all encoded with bech32m. The bech32 encoding method is deprecated from CKB2021.
bool is_bech32m = true;
if (!bech32_encode(out, out_size, hrbs[N_data.address_type&ADDRESS_TYPE_MASK], base32_buf, base32_len, is_bech32m)) {
THROW(EXC_MEMORY_ERROR);
}
Expand Down
2 changes: 1 addition & 1 deletion src/apdu_pubkey.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
#include "apdu.h"

void handle_apdu_get_public_key(uint8_t instruction);
void render_pkh(char *const out, size_t const out_size, render_address_payload_t const *const payload);
void render_pkh(char *const out, size_t const out_size, render_address_payload_t const *const payload, size_t payload_len);
8 changes: 4 additions & 4 deletions src/apdu_sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
static inline void conditional_init_hash_state(blake2b_hash_state_t *const state) {
check_null(state);
if (!state->initialized) {
cx_blake2b_init2(&state->state, SIGN_HASH_SIZE * 8, NULL, 0, (uint8_t *)blake2b_personalization,
sizeof(blake2b_personalization) - 1);
CX_ASSERT(cx_blake2b_init2_no_throw(&state->state, SIGN_HASH_SIZE * 8, NULL, 0, (uint8_t *)blake2b_personalization,
sizeof(blake2b_personalization) - 1));
state->initialized = true;
}
}
Expand All @@ -39,7 +39,7 @@ static void blake2b_incremental_hash(
check_null(state);

conditional_init_hash_state(state);
cx_hash((cx_hash_t *)&state->state, 0, out, out_size, NULL, 0);
CX_ASSERT(cx_hash_no_throw((cx_hash_t *)&state->state, 0, out, out_size, NULL, 0));
}

static void blake2b_finish_hash(
Expand All @@ -49,7 +49,7 @@ static void blake2b_finish_hash(
check_null(state);

conditional_init_hash_state(state);
cx_hash((cx_hash_t *)&state->state, CX_LAST, NULL, 0, out, out_size);
CX_ASSERT(cx_hash_no_throw((cx_hash_t *)&state->state, CX_LAST, NULL, 0, out, out_size));
}

static int perform_signature(bool const on_hash, bool const send_hash);
Expand Down
32 changes: 19 additions & 13 deletions src/keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,21 @@ key_pair_t *generate_extended_key_pair_return_global(bip32_path_t const *const b

cx_curve_t const cx_curve = CX_CURVE_SECP256K1;

os_perso_derive_node_bip32(cx_curve, bip32_path->components, bip32_path->length, priv->private_key_data, chain_code);
unsigned char temp_privkey[64] = {0};
CX_ASSERT(os_derive_bip32_no_throw(cx_curve, bip32_path->components, bip32_path->length, temp_privkey, chain_code));
memcpy(priv->private_key_data, temp_privkey, 32);
// clear the temporary buffer
explicit_bzero(temp_privkey, sizeof(temp_privkey));
// os_perso_derive_node_bip32(cx_curve, bip32_path->components, bip32_path->length, priv->private_key_data, chain_code);

BEGIN_TRY {
TRY {
cx_ecfp_init_private_key(cx_curve, priv->private_key_data, sizeof(priv->private_key_data),
&priv->res.private_key);
cx_ecfp_generate_pair(cx_curve, &priv->res.public_key, &priv->res.private_key, 1);
CX_ASSERT(cx_ecfp_init_private_key_no_throw(cx_curve, priv->private_key_data, sizeof(priv->private_key_data),
&priv->res.private_key));
CX_ASSERT(cx_ecfp_generate_pair_no_throw(cx_curve, &priv->res.public_key, &priv->res.private_key, 1));

if (cx_curve == CX_CURVE_Ed25519) {
cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, priv->res.public_key.W, priv->res.public_key.W_len);
CX_ASSERT(cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, priv->res.public_key.W, priv->res.public_key.W_len));
priv->res.public_key.W_len = 33;
}
}
Expand Down Expand Up @@ -97,10 +102,11 @@ size_t sign(uint8_t *const out, size_t const out_size, key_pair_t const *const p
explicit_bzero(sig, sizeof(sig));

unsigned int info = 0;
size_t sig_len = sizeof(sig);

cx_ecdsa_sign(&pair->private_key, CX_LAST | CX_RND_RFC6979,
CX_ASSERT(cx_ecdsa_sign_no_throw(&pair->private_key, CX_LAST | CX_RND_RFC6979,
CX_SHA256, // historical reasons...semantically CX_NONE
(uint8_t const *const)PIC(in), in_size, sig, sizeof(sig), &info);
(uint8_t const *const)PIC(in), in_size, sig, &sig_len, &info));

// Converting to compressed format
int const r_size = sig[3];
Expand Down Expand Up @@ -132,13 +138,13 @@ void generate_lock_arg_for_pubkey(const cx_ecfp_public_key_t *const key, standar

cx_blake2b_t hash_state;

cx_blake2b_init2(&hash_state, 32*8, NULL, 0, (uint8_t *)blake2b_personalization,
sizeof(blake2b_personalization) - 1);
CX_ASSERT(cx_blake2b_init2_no_throw(&hash_state, 32*8, NULL, 0, (uint8_t *)blake2b_personalization,
sizeof(blake2b_personalization) - 1));

cx_hash((cx_hash_t *)&hash_state, 0, (uint8_t *const) & tag_byte, 1, NULL, 0);
cx_hash((cx_hash_t *)&hash_state, 0, (uint8_t *const) key->W+1, 32, NULL, 0);
cx_hash((cx_hash_t *)&hash_state, CX_LAST, NULL, 0, (uint8_t *const) temp_hash,
sizeof(temp_hash));
CX_ASSERT(cx_hash_no_throw((cx_hash_t *)&hash_state, 0, (uint8_t *const) & tag_byte, 1, NULL, 0));
CX_ASSERT(cx_hash_no_throw((cx_hash_t *)&hash_state, 0, (uint8_t *const) key->W+1, 32, NULL, 0));
CX_ASSERT(cx_hash_no_throw((cx_hash_t *)&hash_state, CX_LAST, NULL, 0, (uint8_t *const) temp_hash,
sizeof(temp_hash)));

memcpy(dest, temp_hash, sizeof(standard_lock_arg_t));

Expand Down
4 changes: 0 additions & 4 deletions src/keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@
#include "os_cx.h"
#include "types.h"

#if CX_APILEVEL <= 8
#error "CX_APILEVEL 8 and below is not supported"
#endif

struct bip32_path_wire {
uint8_t length;
uint32_t components[0];
Expand Down
11 changes: 10 additions & 1 deletion src/segwit_addr.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,16 @@ int bech32_encode(char *const output, const size_t out_len, const char *const hr
chk = bech32_polymod_step(chk) ^ (hrp[i] >> 5);
++i;
}
if (i + 7 + data_len > 108)
// An CKB address is encoded from a CKB script,
// which consists of three fields:
// code_hash (32 bytes), hash_type (1 byte), and args (variable).
// It is often longer than a Bitcoin address.
// Since a bech32 character can represent 5-bits of data,
// the original limit of 107 has been changed to 1023
// to increase the script limit to approximately 640 bytes (1023 * 5 / 8 ≈ 1023)
// allowing support for ultra-long addresses.
size_t max_data_len = 1023;
if (i + 7 + data_len > max_data_len)
return 0;
chk = bech32_polymod_step(chk);
}
Expand Down
11 changes: 8 additions & 3 deletions src/to_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,11 +220,12 @@ void lock_arg_to_sighash_address(char *const dest, size_t const buff_size, lock_
render_address_payload.full_version.hash_type = 1;

memcpy(&render_address_payload.full_version.hash, lock_arg->hash, sizeof(render_address_payload.full_version.hash));
render_pkh(dest, buff_size, &render_address_payload);
render_pkh(dest, buff_size, &render_address_payload, sizeof(render_address_payload.full_version));
}

void lock_arg_to_multisig_address(char *const dest, size_t const buff_size, lock_arg_t const *const lock_arg) {
render_address_payload_t render_address_payload;
size_t payload_len = 0;
bool has_timelock = false;
for (int i = 0; i < 8; i++) {
if (lock_arg->lock_period[i] != 0) {
Expand All @@ -233,19 +234,23 @@ void lock_arg_to_multisig_address(char *const dest, size_t const buff_size, lock
}
}
if (has_timelock) {
render_address_payload.code_hash_data_or_type.address_format_type = ADDRESS_FORMAT_TYPE_CODE_HASH_TYPE;
render_address_payload.code_hash_data_or_type.address_format_type = ADDRESS_FORMAT_TYPE_FULL_VERSION;
memcpy(&render_address_payload.code_hash_data_or_type.code_hash, multisigLockScript,
sizeof(render_address_payload.code_hash_data_or_type.code_hash));
render_address_payload.code_hash_data_or_type.hash_type = 1;
memcpy(&render_address_payload.code_hash_data_or_type.lock_arg, lock_arg, sizeof(render_address_payload.code_hash_data_or_type.lock_arg));
payload_len = sizeof(render_address_payload.code_hash_data_or_type);
} else {
render_address_payload.full_version.address_format_type = ADDRESS_FORMAT_TYPE_FULL_VERSION;
memcpy(&render_address_payload.full_version.code_hash, multisigLockScript,
sizeof(render_address_payload.full_version.code_hash));
render_address_payload.full_version.hash_type = 1;
memcpy(&render_address_payload.full_version.hash, lock_arg->hash,
sizeof(render_address_payload.full_version.hash));
payload_len = sizeof(render_address_payload.full_version);
}

render_pkh(dest, buff_size, &render_address_payload);
render_pkh(dest, buff_size, &render_address_payload, payload_len);
}

// (x, h) -> "x of y"
Expand Down
1 change: 1 addition & 0 deletions src/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ typedef union {
struct {
uint8_t address_format_type;
uint8_t code_hash[32];
uint8_t hash_type;
lock_arg_t lock_arg;
} code_hash_data_or_type; // code_hash_data or code_hash_type
} render_address_payload_t;
Expand Down
Loading

0 comments on commit ac22933

Please sign in to comment.