Skip to content

Commit

Permalink
Merge pull request #3 from LedgerHQ/Zondax-main
Browse files Browse the repository at this point in the history
  • Loading branch information
fbeutin-ledger authored Dec 13, 2023
2 parents ba79be1 + 7fad233 commit e37c61e
Show file tree
Hide file tree
Showing 116 changed files with 237 additions and 724 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/guidelines_enforcer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,3 @@ jobs:
guidelines_enforcer:
name: Call Ledger guidelines_enforcer
uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_guidelines_enforcer.yml@v1
with:
relative_app_directory: app
run_for_devices: '["nanos", "nanosp", "nanox", "stax"]'
37 changes: 0 additions & 37 deletions .github/workflows/ledger.yml

This file was deleted.

55 changes: 55 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,27 @@ jobs:
make deps
- run: make cpp_test

build_rust:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: true
- name: Install rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: rustfmt
run: |
cd ./rs
cargo fmt --version
cargo fmt -- --check
- name: audit
run: |
cd ./rs
cargo audit
build_ledger:
needs: configure
runs-on: ubuntu-latest
Expand Down Expand Up @@ -160,3 +181,37 @@ jobs:
tag_name: ${{ steps.nanosp.outputs.tag_name }}
draft: false
prerelease: false

build_package_stax:
needs: [configure, build, build_ledger, test_zemu]
if: ${{ github.ref == 'refs/heads/main' }}
runs-on: ubuntu-latest
container:
image: zondax/ledger-app-builder:latest
options: --user ${{ needs.configure.outputs.uid_gid }}
env:
BOLOS_SDK: /opt/stax-secure-sdk
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: true
- name: Install deps
run: pip install ledgerblue

- name: Build Stax
shell: bash -l {0}
run: make SUBSTRATE_PARSER_FULL=1
- name: Set tag
id: stax
run: echo "tag_name=$(./app/pkg/installer_stax.sh version)" >> $GITHUB_OUTPUT
- name: Update Release
id: update_release_2
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
with:
files: ./app/pkg/installer_stax.sh
tag_name: ${{ steps.stax.outputs.tag_name }}
draft: false
prerelease: false
1 change: 0 additions & 1 deletion app/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ APP_LOAD_PARAMS = --curve ed25519 $(COMMON_LOAD_PARAMS) --path $(APPPATH)
APP_LOAD_PARAMS += --tlvraw 9F:01
DEFINES += HAVE_PENDING_REVIEW_SCREEN

NANOS_STACK_SIZE := 2555
include $(CURDIR)/../deps/ledger-zxlib/makefiles/Makefile.devices

$(info TARGET_NAME = [$(TARGET_NAME)])
Expand Down
2 changes: 1 addition & 1 deletion app/Makefile.version
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ APPVERSION_M=0
# This is the `spec_version` field of `Runtime`
APPVERSION_N=0
# This is the patch version of this release
APPVERSION_P=11
APPVERSION_P=13
59 changes: 26 additions & 33 deletions app/src/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ static zxerr_t crypto_extractPublicKey_ed25519(uint8_t *pubKey, uint16_t pubKeyL
privateKeyData,
NULL,
NULL,
0))
0));

CATCH_CXERROR(cx_ecfp_init_private_key_no_throw(CX_CURVE_Ed25519, privateKeyData, SK_LEN_25519, &cx_privateKey))
CATCH_CXERROR(cx_ecfp_init_public_key_no_throw(CX_CURVE_Ed25519, NULL, 0, &cx_publicKey))
CATCH_CXERROR(cx_ecfp_generate_pair_no_throw(CX_CURVE_Ed25519, &cx_publicKey, &cx_privateKey, 1))
CATCH_CXERROR(cx_ecfp_init_private_key_no_throw(CX_CURVE_Ed25519, privateKeyData, SK_LEN_25519, &cx_privateKey));
CATCH_CXERROR(cx_ecfp_init_public_key_no_throw(CX_CURVE_Ed25519, NULL, 0, &cx_publicKey));
CATCH_CXERROR(cx_ecfp_generate_pair_no_throw(CX_CURVE_Ed25519, &cx_publicKey, &cx_privateKey, 1));
for (unsigned int i = 0; i < PK_LEN_25519; i++) {
pubKey[i] = cx_publicKey.W[64 - i];
}
Expand Down Expand Up @@ -88,15 +88,15 @@ static zxerr_t crypto_sign_ed25519(uint8_t *output, uint16_t outputLen, const ui
privateKeyData,
NULL,
NULL,
0))
0));

CATCH_CXERROR(cx_ecfp_init_private_key_no_throw(CX_CURVE_Ed25519, privateKeyData, SK_LEN_25519, &cx_privateKey))
CATCH_CXERROR(cx_ecfp_init_private_key_no_throw(CX_CURVE_Ed25519, privateKeyData, SK_LEN_25519, &cx_privateKey));
CATCH_CXERROR(cx_eddsa_sign_no_throw(&cx_privateKey,
CX_SHA512,
message,
messageLen,
output,
outputLen))
outputLen));
error = zxerr_ok;

catch_cx_error:
Expand Down Expand Up @@ -125,10 +125,9 @@ zxerr_t crypto_fillAddress_ed25519(uint8_t *buffer, uint16_t bufferLen, uint16_t
if (bufferLen < PK_LEN_25519_PLUS_TAG + ADDRESS_LEN_TESTNET) {
return zxerr_unknown;
}
CHECK_ZXERR(crypto_extractPublicKey_ed25519(answer->publicKey + 1, PK_LEN_25519))
CHECK_ZXERR(crypto_extractPublicKey_ed25519(answer->publicKey + 1, PK_LEN_25519));

const bool isTestnet = hdPath[1] == HDPATH_1_TESTNET;
outLen = crypto_encodePubkey_ed25519(answer->address, sizeof(answer->address), answer->publicKey + 1, isTestnet);
outLen = crypto_encodePubkey_ed25519(answer->address, sizeof(answer->address), answer->publicKey + 1);

if (outLen == 0) {
MEMZERO(buffer, bufferLen);
Expand Down Expand Up @@ -160,9 +159,9 @@ static zxerr_t crypto_hashFeeHeader(const header_t *header, uint8_t *output, uin
cx_sha256_t sha256 = {0};
cx_sha256_init(&sha256);
const uint8_t discriminant = 0x07;
cx_sha256_update(&sha256, &discriminant, sizeof(discriminant));
cx_sha256_update(&sha256, header->extBytes.ptr, header->extBytes.len);
cx_sha256_final(&sha256, output);
CHECK_CX_OK(cx_sha256_update(&sha256, &discriminant, sizeof(discriminant)));
CHECK_CX_OK(cx_sha256_update(&sha256, header->extBytes.ptr, header->extBytes.len));
CHECK_CX_OK(cx_sha256_final(&sha256, output));
return zxerr_ok;
}

Expand All @@ -174,11 +173,11 @@ static zxerr_t crypto_hashRawHeader(const header_t *header, uint8_t *output, uin
cx_sha256_t sha256 = {0};
cx_sha256_init(&sha256);
const uint8_t discriminant = 0x07;
cx_sha256_update(&sha256, &discriminant, sizeof(discriminant));
cx_sha256_update(&sha256, header->bytes.ptr, header->bytes.len);
CHECK_CX_OK(cx_sha256_update(&sha256, &discriminant, sizeof(discriminant)));
CHECK_CX_OK(cx_sha256_update(&sha256, header->bytes.ptr, header->bytes.len));
const uint8_t header_discriminant = 0x00;
cx_sha256_update(&sha256, &header_discriminant, sizeof(header_discriminant));
cx_sha256_final(&sha256, output);
CHECK_CX_OK(cx_sha256_update(&sha256, &header_discriminant, sizeof(header_discriminant)));
CHECK_CX_OK(cx_sha256_final(&sha256, output));
return zxerr_ok;
}

Expand All @@ -190,15 +189,15 @@ zxerr_t crypto_hashSigSection(const signature_section_t *signature_section, cons
cx_sha256_t sha256 = {0};
cx_sha256_init(&sha256);
if (prefix != NULL) {
cx_sha256_update(&sha256, prefix, prefixLen);
CHECK_CX_OK(cx_sha256_update(&sha256, prefix, prefixLen));
}
cx_sha256_update(&sha256, (uint8_t*) &signature_section->hashes.hashesLen, 4);
cx_sha256_update(&sha256, signature_section->hashes.hashes.ptr, HASH_LEN * signature_section->hashes.hashesLen);
cx_sha256_update(&sha256, (uint8_t*) &signature_section->signerDiscriminant, 1);
CHECK_CX_OK(cx_sha256_update(&sha256, (uint8_t*) &signature_section->hashes.hashesLen, 4));
CHECK_CX_OK(cx_sha256_update(&sha256, signature_section->hashes.hashes.ptr, HASH_LEN * signature_section->hashes.hashesLen));
CHECK_CX_OK(cx_sha256_update(&sha256, (uint8_t*) &signature_section->signerDiscriminant, 1));

switch (signature_section->signerDiscriminant) {
case PubKeys: {
cx_sha256_update(&sha256, (uint8_t*) &signature_section->pubKeysLen, 4);
CHECK_CX_OK(cx_sha256_update(&sha256, (uint8_t*) &signature_section->pubKeysLen, 4));
uint32_t pos = 0;
for (uint32_t i = 0; i < signature_section->pubKeysLen; i++) {
uint8_t tag = signature_section->pubKeys.ptr[pos++];
Expand All @@ -211,19 +210,19 @@ zxerr_t crypto_hashSigSection(const signature_section_t *signature_section, cons
pos += pubKeySize;
}
if(pos > 0) {
cx_sha256_update(&sha256, signature_section->pubKeys.ptr, pos);
CHECK_CX_OK(cx_sha256_update(&sha256, signature_section->pubKeys.ptr, pos));
}
break;
}
case Address:
cx_sha256_update(&sha256, signature_section->address.ptr, signature_section->address.len);
CHECK_CX_OK(cx_sha256_update(&sha256, signature_section->address.ptr, signature_section->address.len));
break;

default:
return zxerr_invalid_crypto_settings;
}

cx_sha256_update(&sha256, (const uint8_t*) &signature_section->signaturesLen, 4);
CHECK_CX_OK(cx_sha256_update(&sha256, (const uint8_t*) &signature_section->signaturesLen, 4));
uint32_t pos = 0;
for (uint32_t i = 0; i < signature_section->signaturesLen; i++) {
// Skip the signature's 1 byte index
Expand All @@ -238,9 +237,9 @@ zxerr_t crypto_hashSigSection(const signature_section_t *signature_section, cons
pos += signatureSize;
}
if(pos > 0) {
cx_sha256_update(&sha256, signature_section->indexedSignatures.ptr, pos);
CHECK_CX_OK(cx_sha256_update(&sha256, signature_section->indexedSignatures.ptr, pos));
}
cx_sha256_final(&sha256, output);
CHECK_CX_OK(cx_sha256_final(&sha256, output));
return zxerr_ok;
}

Expand All @@ -257,12 +256,6 @@ static zxerr_t crypto_addTxnHashes(const parser_tx_t *txObj, concatenated_hashes
hashes->hashesLen++;
break;

case InitValidator:
MEMCPY(hashes->hashes.ptr + hashes->hashesLen * HASH_LEN, txObj->initValidator.vp_type_sechash.ptr, HASH_LEN);
hashes->indices.ptr[hashes->hashesLen] = txObj->initValidator.vp_type_secidx;
hashes->hashesLen++;
break;

case UpdateVP:
MEMCPY(hashes->hashes.ptr + hashes->hashesLen * HASH_LEN, txObj->updateVp.vp_type_sechash.ptr, HASH_LEN);
hashes->indices.ptr[hashes->hashesLen] = txObj->updateVp.vp_type_secidx;
Expand Down
52 changes: 25 additions & 27 deletions app/src/crypto_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "bech32.h"
#include "zxformat.h"
#include "leb128.h"
#include "zxmacros.h"

#ifdef LEDGER_SPECIFIC
#include "bolos_target.h"
Expand Down Expand Up @@ -70,17 +71,15 @@ static zxerr_t crypto_publicKeyHash_ed25519(uint8_t *publicKeyHash, const uint8_
return zxerr_ok;
}

uint8_t crypto_encodePubkey_ed25519(uint8_t *buffer, uint16_t bufferLen, const uint8_t *pubkey, bool isTestnet) {
uint8_t crypto_encodePubkey_ed25519(uint8_t *buffer, uint16_t bufferLen, const uint8_t *pubkey) {
if (buffer == NULL || pubkey == NULL) {
return 0;
}

if ((bufferLen < ADDRESS_LEN_TESTNET && isTestnet) || bufferLen < ADDRESS_LEN_MAINNET) {
if (bufferLen < ADDRESS_LEN_TESTNET) {
return 0;
}

const char *hrp = isTestnet ? "tnam" : "a";

// Step 1: Compute the hash of the Ed25519 public key
uint8_t publicKeyHash[21] = {0};
crypto_publicKeyHash_ed25519(publicKeyHash, pubkey);
Expand All @@ -89,7 +88,7 @@ uint8_t crypto_encodePubkey_ed25519(uint8_t *buffer, uint16_t bufferLen, const u
char addr_out[79] = {0};
zxerr_t err = bech32EncodeFromBytes(addr_out,
sizeof(addr_out),
hrp,
"tnam",
publicKeyHash,
sizeof(publicKeyHash),
1,
Expand All @@ -99,9 +98,8 @@ uint8_t crypto_encodePubkey_ed25519(uint8_t *buffer, uint16_t bufferLen, const u
return 0;
}

const uint8_t addressLen = isTestnet ? ADDRESS_LEN_TESTNET : ADDRESS_LEN_MAINNET;
memcpy(buffer, addr_out, addressLen);
return addressLen;
memcpy(buffer, addr_out, ADDRESS_LEN_TESTNET);
return ADDRESS_LEN_TESTNET;
}

zxerr_t crypto_sha256(const uint8_t *input, uint16_t inputLen, uint8_t *output, uint16_t outputLen) {
Expand Down Expand Up @@ -130,14 +128,14 @@ zxerr_t crypto_hashExtraDataSection(const section_t *extraData, uint8_t *output,
#if defined(TARGET_NANOS) || defined(TARGET_NANOS2) || defined(TARGET_NANOX) || defined(TARGET_STAX)
cx_sha256_t sha256 = {0};
cx_sha256_init(&sha256);
cx_sha256_update(&sha256, &extraData->discriminant, 1);
cx_sha256_update(&sha256, extraData->salt.ptr, extraData->salt.len);
cx_sha256_update(&sha256, extraData->bytes.ptr, extraData->bytes.len);
CHECK_CX_OK(cx_sha256_update(&sha256, &extraData->discriminant, 1));
CHECK_CX_OK(cx_sha256_update(&sha256, extraData->salt.ptr, extraData->salt.len));
CHECK_CX_OK(cx_sha256_update(&sha256, extraData->bytes.ptr, extraData->bytes.len));
uint8_t has_tag = (extraData->tag.ptr == NULL) ? 0 : 1;
cx_sha256_update(&sha256, &has_tag, 1);
cx_sha256_update(&sha256, (uint8_t*) &extraData->tag.len, has_tag*sizeof(extraData->tag.len));
cx_sha256_update(&sha256, extraData->tag.ptr, has_tag*extraData->tag.len);
cx_sha256_final(&sha256, output);
CHECK_CX_OK(cx_sha256_update(&sha256, &has_tag, 1));
CHECK_CX_OK(cx_sha256_update(&sha256, (uint8_t*) &extraData->tag.len, has_tag*sizeof(extraData->tag.len)));
CHECK_CX_OK(cx_sha256_update(&sha256, extraData->tag.ptr, has_tag*extraData->tag.len));
CHECK_CX_OK(cx_sha256_final(&sha256, output));
#else
picohash_ctx_t sha256 = {0};
picohash_init_sha256(&sha256);
Expand All @@ -162,11 +160,11 @@ zxerr_t crypto_hashDataSection(const section_t *data, uint8_t *output, uint32_t
#if defined(TARGET_NANOS) || defined(TARGET_NANOS2) || defined(TARGET_NANOX) || defined(TARGET_STAX)
cx_sha256_t sha256 = {0};
cx_sha256_init(&sha256);
cx_sha256_update(&sha256, &data->discriminant, 1);
cx_sha256_update(&sha256, data->salt.ptr, data->salt.len);
cx_sha256_update(&sha256, (uint8_t*) &data->bytes.len, sizeof(data->bytes.len));
cx_sha256_update(&sha256, data->bytes.ptr, data->bytes.len);
cx_sha256_final(&sha256, output);
CHECK_CX_OK(cx_sha256_update(&sha256, &data->discriminant, 1));
CHECK_CX_OK(cx_sha256_update(&sha256, data->salt.ptr, data->salt.len));
CHECK_CX_OK(cx_sha256_update(&sha256, (uint8_t*) &data->bytes.len, sizeof(data->bytes.len)));
CHECK_CX_OK(cx_sha256_update(&sha256, data->bytes.ptr, data->bytes.len));
CHECK_CX_OK(cx_sha256_final(&sha256, output));
#else
picohash_ctx_t sha256 = {0};
picohash_init_sha256(&sha256);
Expand All @@ -188,14 +186,14 @@ zxerr_t crypto_hashCodeSection(const section_t *code, uint8_t *output, uint32_t
#if defined(TARGET_NANOS) || defined(TARGET_NANOS2) || defined(TARGET_NANOX) || defined(TARGET_STAX)
cx_sha256_t sha256 = {0};
cx_sha256_init(&sha256);
cx_sha256_update(&sha256, &code->discriminant, 1);
cx_sha256_update(&sha256, code->salt.ptr, code->salt.len);
cx_sha256_update(&sha256, code->bytes.ptr, code->bytes.len);
CHECK_CX_OK(cx_sha256_update(&sha256, &code->discriminant, 1));
CHECK_CX_OK(cx_sha256_update(&sha256, code->salt.ptr, code->salt.len));
CHECK_CX_OK(cx_sha256_update(&sha256, code->bytes.ptr, code->bytes.len));
uint8_t has_tag = (code->tag.ptr == NULL) ? 0 : 1;
cx_sha256_update(&sha256, &has_tag, 1);
cx_sha256_update(&sha256, (uint8_t*) &code->tag.len, has_tag*sizeof(code->tag.len));
cx_sha256_update(&sha256, code->tag.ptr, has_tag*code->tag.len);
cx_sha256_final(&sha256, output);
CHECK_CX_OK(cx_sha256_update(&sha256, &has_tag, 1));
CHECK_CX_OK(cx_sha256_update(&sha256, (uint8_t*) &code->tag.len, has_tag*sizeof(code->tag.len)));
CHECK_CX_OK(cx_sha256_update(&sha256, code->tag.ptr, has_tag*code->tag.len));
CHECK_CX_OK(cx_sha256_final(&sha256, output));
#else
picohash_ctx_t sha256 = {0};
picohash_init_sha256(&sha256);
Expand Down
3 changes: 1 addition & 2 deletions app/src/crypto_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ extern "C" {
#define CODE_HASH_INFO_SIZE 2


uint8_t crypto_encodePubkey_ed25519(uint8_t *buffer, uint16_t bufferLen,
const uint8_t *pubkey, bool isTestnet);
uint8_t crypto_encodePubkey_ed25519(uint8_t *buffer, uint16_t bufferLen, const uint8_t *pubkey);

zxerr_t crypto_sha256(const uint8_t *input, uint16_t inputLen,
uint8_t *output, uint16_t outputLen);
Expand Down
1 change: 1 addition & 0 deletions app/src/leb128.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
******************************************************************************* */
#include "leb128.h"
#include <stddef.h>

zxerr_t encodeLEB128(uint64_t number, uint8_t *encoded, uint8_t encodedLen, uint8_t *encodedBytes) {
if (encoded == NULL || encodedBytes == NULL) {
Expand Down
Loading

0 comments on commit e37c61e

Please sign in to comment.