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

Merge latest ledgerhq app exchange #5

Merged
merged 58 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
db2c419
Security review
fbeutin-ledger Sep 26, 2023
8a37c79
Second review taken into account
fbeutin-ledger Oct 5, 2023
d6bb7a1
Bump version
fbeutin-ledger Oct 6, 2023
3fea729
Merge pull request #149 from LedgerHQ/fbe/security_review
fbeutin-ledger Oct 6, 2023
8eac76b
Update API spec
fbeutin-ledger Oct 5, 2023
c5222ae
Add a field for curve selection in SET_PARTNER_DATA command on NG flows
fbeutin-ledger Oct 10, 2023
eca3c2c
Tests: Rework craft_tx and encode_tx into a more simple and usable si…
fbeutin-ledger Oct 11, 2023
7dcd10b
Add a field for tx encoding selection in PROCESS_TRANSACTION_RESPONSE…
fbeutin-ledger Oct 11, 2023
6a2af71
Add a field for signature format selection in CHECK_TRANSACTION_SIGNA…
fbeutin-ledger Oct 13, 2023
d20c7cc
Add a field for prefix used during TX signature computation in CHECK_…
fbeutin-ledger Oct 13, 2023
7aed884
Lint and fix error with SDK
fbeutin-ledger Oct 17, 2023
ea5f522
Add tests for ng configuration
fbeutin-ledger Oct 17, 2023
31ad1be
Misspelings
fbeutin-ledger Oct 17, 2023
87a749b
Merge pull request #148 from LedgerHQ/fbe/unified_protocol_v2
fbeutin-ledger Oct 18, 2023
48719b0
Bump version 3.3.0
fbeutin-ledger Oct 18, 2023
a22b3fd
Merge pull request #151 from LedgerHQ/fbe/release_v3.3.0
fbeutin-ledger Oct 18, 2023
f1dad98
Allow different error codes
fbeutin-ledger Oct 4, 2023
2c42653
Add tests for Polkadot
fbeutin-ledger Oct 4, 2023
a488539
Use DOT as coin name
fbeutin-ledger Oct 16, 2023
e48dfe1
Merge pull request #147 from LedgerHQ/fbe/add_polkadot_tests
fbeutin-ledger Oct 18, 2023
7b6339b
test: Add TRON tests
Jun 27, 2023
7700d4a
Merge pull request #116 from LedgerHQ/xch/tron-swap
xchapron-ledger Oct 19, 2023
5377899
[Fix]: Add HAVE_WEBUSB flag
sgliner-ledger Oct 31, 2023
3c6c162
Merge pull request #152 from LedgerHQ/add-have-webusb-flag
fbeutin-ledger Nov 6, 2023
0f98755
Bump version
sgliner-ledger Nov 8, 2023
5be90bc
Merge pull request #153 from LedgerHQ/bump-version
fbeutin-ledger Nov 8, 2023
04bec25
Clean reusable workflow parameters
fbeutin-ledger Nov 9, 2023
a06422e
Merge pull request #154 from LedgerHQ/fbe/remove_useless_parameters
fbeutin-ledger Nov 9, 2023
f0f0daa
Add manifest file at project root
fbeutin-ledger Nov 9, 2023
7e903b3
Merge pull request #155 from LedgerHQ/fbe/add_manifest
fbeutin-ledger Nov 9, 2023
a9e00aa
Increase decoded protobuf buffer size
fbeutin-ledger Nov 13, 2023
8bb47ed
Merge pull request #157 from LedgerHQ/fbe/increase_decoded_protobuf_b…
fbeutin-ledger Nov 14, 2023
f86c26d
import bitcoin_client
sgliner-ledger Oct 30, 2023
8608b97
bitcoin_client: use ragger for as TransportClient
sgliner-ledger Nov 6, 2023
d67a5d6
tests: add bitcoin
sgliner-ledger Nov 6, 2023
bbdc4d5
bitcoin_tests: add snapshots
sgliner-ledger Nov 10, 2023
b05bd5d
old_tests: change payout_address now that derivation path has changed
sgliner-ledger Nov 14, 2023
8a837bb
Merge pull request #156 from LedgerHQ/btc-swap-tests
sgliner-ledger Nov 16, 2023
13d4d65
Rename tezos by tezos_legacy
spalmer25 Sep 11, 2023
2faf957
Add a way to communicate with the application
spalmer25 Sep 14, 2023
d1c6772
Add tests for the new tezos app
spalmer25 Sep 14, 2023
300f0c0
Provide snapshot
spalmer25 Sep 15, 2023
3d96472
Add a golden comparison for the signing step too
spalmer25 Sep 15, 2023
86c8e88
Provide signing snapshot
spalmer25 Sep 15, 2023
4c3ee85
Add a relative_app_directory for build in CI
spalmer25 Sep 11, 2023
6a86364
Precise the repo for build in CI
spalmer25 Sep 11, 2023
7ed4166
Allowing LedgerHQ/app-exchange fork to run CI
spalmer25 Sep 14, 2023
21c6b79
Add a way to choose the device for which CI ragger tests will be run
spalmer25 Sep 14, 2023
2352e57
Run the new-tezos app tests on reusable_swap_functional_tests call
spalmer25 Sep 11, 2023
31cd7ec
Do not run tezos_legacy tests
spalmer25 Sep 25, 2023
dd56206
Only run what is required for tezos_new test
spalmer25 Oct 26, 2023
0fb925e
Change sign accept screen
spalmer25 Nov 2, 2023
2b15d84
Change screens according to tezos MR 124
spalmer25 Nov 15, 2023
44447af
Change screens according to tezos MR 118
spalmer25 Nov 20, 2023
a91656e
CI: fix the ethereum version
spalmer25 Nov 22, 2023
ed379ab
CI: build apps only for run_for_devices
spalmer25 Nov 22, 2023
287f6d6
Merge branch 'develop' into merge-latest-ledgerhq-app-exchange
ajinkyaraj-23 Nov 23, 2023
7f3e18f
fix merge errors to rebase to latest ledgerhq repo
ajinkyaraj-23 Nov 23, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .codespellignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nin
2 changes: 2 additions & 0 deletions .github/workflows/ci-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ jobs:
uses: ./.github/workflows/reusable_swap_functional_tests.yml
with:
branch_for_exchange: ${{ github.ref }}
run_for_devices: '["nanos", "nanosp"]'
test_filter: '"tezos_new"'
30 changes: 30 additions & 0 deletions .github/workflows/misspellings_checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Misspellings checks

# This workflow performs some misspelling checks on the repository
# It is there to help us maintain a level of quality in our codebase and does not have to be kept on forked
# applications.

on:
workflow_dispatch:
push:
branches:
- master
- main
- develop
pull_request:

jobs:
misspell:
name: Check misspellings
runs-on: ubuntu-latest
steps:
- name: Clone
uses: actions/checkout@v3

- name: Check misspellings
uses: codespell-project/actions-codespell@v1
with:
builtin: clear,rare
check_filenames: true
ignore_words_file: .codespellignore
path: src/,test/python/,protocol.md,Makefile,README.md
2 changes: 1 addition & 1 deletion .github/workflows/reusable_swap_functional_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
inputs:
repo_for_exchange:
required: false
default: 'LedgerHQ/app-exchange'
default: 'functori/app-exchange'
type: string
branch_for_exchange:
required: false
Expand Down
7 changes: 3 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ APP_LOAD_PARAMS += $(COMMON_LOAD_PARAMS)

APPNAME = "Exchange"
APPVERSION_M = 3
APPVERSION_N = 1
APPVERSION_P = 0
APPVERSION_N = 3
APPVERSION_P = 2
APPVERSION = $(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)-dev

ifdef TESTING
Expand Down Expand Up @@ -70,12 +70,11 @@ DEFINES += LEDGER_MAJOR_VERSION=$(APPVERSION_M) LEDGER_MINOR_VERSION=$(APPVERS
DEFINES += OS_IO_SEPROXYHAL
DEFINES += HAVE_SPRINTF
DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=4 IO_HID_EP_LENGTH=64 HAVE_USB_APDU
DEFINES += HAVE_WEBUSB WEBUSB_URL_SIZE_B=0 WEBUSB_URL=""

DEFINES += USB_SEGMENT_SIZE=64
DEFINES += BLE_SEGMENT_SIZE=32 #max MTU, min 20

DEFINES += UNUSED\(x\)=\(void\)x

ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_NANOX TARGET_STAX))
DEFINES += HAVE_BLE BLE_COMMAND_TIMEOUT_MS=2000 HAVE_BLE_APDU
endif
Expand Down
80 changes: 0 additions & 80 deletions include/swap_lib_calls.h

This file was deleted.

7 changes: 7 additions & 0 deletions ledger_app.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[app]
build_directory = "./"
sdk = "C"
devices = ["nanos", "nanox", "nanos+", "stax"]

[tests]
pytest_directory = "./test/python/"
74 changes: 56 additions & 18 deletions protocol.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Protocol to speak with EXCHANGE application

Communication is done through a serie of request-response exchanges (APDU / RAPDU).
Communication is done through a series of request-response exchanges (APDU / RAPDU).


## Request:
Expand All @@ -19,7 +19,7 @@ Communication is done through a serie of request-response exchanges (APDU / RAPD

| Name | Value | Description |
| ---------------------------- | ----- | ------------------------------------------------------------------------------------- |
| GET_VERSION | 0x02 | Get application version. This APDU can be sent independantly of the current app state |
| GET_VERSION | 0x02 | Get application version. This APDU can be sent independently of the current app state |
| START_NEW_TRANSACTION | 0x03 | Start new EXCHANGE transaction. This APDU resets the app state |
| SET_PARTNER_KEY | 0x04 | Set the credentials of the exchange partner |
| CHECK_PARTNER | 0x05 | Check that the credentials of the exchange partner are signed by the Ledger key |
Expand Down Expand Up @@ -111,12 +111,25 @@ No data expected.

#### SET_PARTNER_KEY

##### For all LEGACY TYPES, the data for this command is:

| Bytes | Description |
| ------------------ | ------------------------------------ |
| 1 byte | Length N of the encoded partner name |
| N bytes | Partner name encoded with utf-8 |
| LC - (1 + N) bytes | Partner public key |

##### For all UNIFIED TYPES, the data for this command is:

| Bytes | Description |
| ------------------ | ------------------------------------ |
| 1 byte | Length N of the encoded partner name |
| N bytes | Partner name encoded with utf-8 |
| 1 byte | Curve used by the partner |
| LC - (2 + N) bytes | Partner public key |

With the possible values for the curve being 0x00 for SECP256K1, and 0x01 for SECP256R1.

#### CHECK_PARTNER

| Bytes | Description |
Expand All @@ -125,31 +138,56 @@ No data expected.

#### PROCESS_TRANSACTION_RESPONSE

| Bytes | Description |
| ------------ | ----------------------------------------------------------------------------------------------- |
| 1 or 2 bytes | Length N of the encoded transaction proposal. 1 bytes on Legacy TYPES, 2 bytes on new TYPES |
| N bytes | Transaction proposal. No encoding for SWAP_LEGACY, URLsafe base 64 encoding for all other TYPES |
| 1 byte | Length M of the transaction fees |
| M bytes | Transaction fees |

Please refer to the src/protobuf files for the actual transaction proposal content.

##### For all LEGACY TYPES, the data for this command is:

| Bytes | Description |
| ------- | ----------------------------------------------------------------------------------------------------------- |
| 1 byte | Length N of the encoded transaction proposal |
| N bytes | Transaction proposal. Bytes array for SWAP_LEGACY, URLsafe base 64 encoding for SELL_LEGACY and FUND_LEGACY |
| 1 byte | Length M of the transaction fees |
| M bytes | Transaction fees |

##### For all UNIFIED TYPES, the data for this command is:

| Bytes | Description |
| ------- | -------------------------------------------- |
| 1 byte | Format used for the transaction encoding |
| 2 bytes | Length N of the encoded transaction proposal |
| N bytes | Encoded transaction proposal |
| 1 byte | Length M of the transaction fees |
| M bytes | Transaction fees |

With the possible values for the format being 0x00 for Bytes Array (no encoding), and 0x01 for Base 64 Url encoding.

The DATA of this command may exceed the capacity of a single APDU (255 bytes), in this case use the EXTENSION feature.

#### CHECK_TRANSACTION_SIGNATURE

| Bytes | Description |
| -------- | ---------------------------------------------------------------------------------------------------------- |
| LC bytes | Signature of the proposed transaction by the partner. |
##### For all LEGACY TYPES, the data for this command is:

| Bytes | Description |
| -------- | ------------------------------------------------------------- |
| LC bytes | Signature of the computed transaction proposed by the partner |

For SWAP_LEGACY TYPE, the signature is computed on the transaction proposal. \
For SELL_LEGACY and FUND_LEGACY the signature is computed on the transaction proposal prefixed with a DOT ('.').

For SWAP_LEGACY and FUND_LEGACY, the signature is in DER format. \
For SELL_LEGACY the signature is in (R,S) format.

##### For all UNIFIED TYPES, the data for this command is:

For SWAP_LEGACY TYPE, the signature is computed on the sha256 hash of the transaction. \
For all other TYPES the signature is computed on the sha256 hash of the transaction prefixed with a DOT ('.').
| Bytes | Description |
| ------------ | ------------------------------------------------------------- |
| 1 byte | If the signature is computed on a prefixed transaction |
| 1 byte | Format of the signature itself |
| LC - 2 bytes | Signature of the computed transaction proposed by the partner |

For SWAP_LEGACY and FUND_LEGACY TYPES, the signature is in DER format. \
For all other TYPES the signature is in (R,S) format.
With the possible values for the format of the transaction used for signing being 0x01 if it was DOT ('.') prefixed, 0x00 otherwise.

For SWAP_LEGACY TYPE, the signature is computed on the secp256k1 curve. \
For all other TYPES the signature is computed on the secp256r1 curve.
With the possible values for the format of the signature itself being 0x00 for DER format, and 0x01 for (R,S) format.

#### CHECK_ASSET_IN_LEGACY

Expand Down
14 changes: 11 additions & 3 deletions src/apdu_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ typedef struct apdu_s {
uint8_t rate;
uint8_t subcommand;
uint16_t data_length;
// We could have put the recontructed apdu buffer here but it would increase the RAM usage by
// We could have put the reconstructed apdu buffer here but it would increase the RAM usage by
// 512 bytes which is a lot on NANOS
// Instead the recontructed apdu buffer is G_swap_ctx.raw_transaction
// Instead the reconstructed apdu buffer is G_swap_ctx.raw_transaction
// It is unionized with the decoded protobuf transaction requests
// Pro: less memory usage
// Cons: use cautiously and only during the command PROCESS_TRANSACTION_RESPONSE_COMMAND
Expand All @@ -48,8 +48,11 @@ apdu_t G_received_apdu;

// Dedicated function for instruction checking as it's self contained
static uint16_t check_instruction(uint8_t instruction, uint8_t subcommand) {
// True if the instruction is part of a flow and the context must be checked
bool check_subcommand_context = false;
// True if the instruction can be received between user approval and child lib start
bool allowed_during_waiting_for_signing = false;
// {STATE} if this command is only accepted at a specific state, -1 otherwise
int check_current_state = -1;

if (instruction == CHECK_ASSET_IN && (subcommand == SWAP || subcommand == SWAP_NG)) {
Expand All @@ -62,11 +65,16 @@ static uint16_t check_instruction(uint8_t instruction, uint8_t subcommand) {
return INVALID_INSTRUCTION;
}

if (instruction == CHECK_REFUND_ADDRESS && subcommand != SWAP && subcommand != SWAP_NG) {
PRINTF("Instruction CHECK_REFUND_ADDRESS is only for SWAP based flows\n");
return INVALID_INSTRUCTION;
}

switch (instruction) {
case GET_VERSION_COMMAND:
// We ignore the current context for this command as it doesn't modify anything
check_subcommand_context = false;
// No strict dependancy on the current state as long as it is not a protected state
// No strict dependency on the current state as long as it is not a protected state
// (WAITING_USER_VALIDATION and WAITING_SIGNING)
check_current_state = -1;
break;
Expand Down
44 changes: 30 additions & 14 deletions src/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,37 @@
#include "os.h"

// Parse a buffer at a given offset to read a buf_t, the offset is incremented accordingly
// param[in] <in_buffer> the total buffer to parse
// param[in] <in_size> the total size of the buffer to parse
// param[out] <out> the buf_t read from in_buffer at offset, can by 0 sized
// param[in/out] <offset> the current offset at wich we are in <in_buffer>
// param[in] <in_buffer> the total buffer to parse
// param[in] <in_size> the total size of the buffer to parse
// param[in] <size_of_length_field> the size of the length field in the header
// param[out] <out> the buf_t read from in_buffer at offset, can by 0 sized
// param[in/out] <offset> the current offset at which we are in <in_buffer>
bool parse_to_sized_buffer(uint8_t *in_buffer,
uint16_t in_size,
uint8_t size_of_lenght_field,
uint8_t size_of_length_field,
buf_t *out,
uint16_t *offset) {
if (*offset + size_of_lenght_field > in_size) {
if (*offset + size_of_length_field > in_size) {
// We can't even read the size
PRINTF("Failed to read the header sized %d, only %d bytes available\n",
size_of_lenght_field,
size_of_length_field,
in_size);
return false;
}

// Read the size
if (size_of_lenght_field == 1) {
if (size_of_length_field == 1) {
out->size = in_buffer[*offset];
} else if (size_of_lenght_field == 2) {
} else if (size_of_length_field == 2) {
out->size = U2BE(in_buffer, *offset);
} else if (size_of_lenght_field == 4) {
out->size = U4BE(in_buffer, *offset);
} else {
PRINTF("Unable to read a %d sized header\n", size_of_lenght_field);
PRINTF("Unable to read a %d sized header\n", size_of_length_field);
return false;
}
*offset += size_of_lenght_field;
*offset += size_of_length_field;

if (*offset + out->size > in_size) {
// Cast before comparison to avoid potential int overflow
if (((uint32_t) *offset) + out->size > in_size) {
PRINTF("Not enough remaining bytes to read. Total %d, offset %d, claims %d bytes\n",
in_size,
*offset,
Expand All @@ -50,3 +50,19 @@ bool parse_to_sized_buffer(uint8_t *in_buffer,

return true;
}

// Parse a buffer at a given offset to read a buf_t, the offset is incremented accordingly
// param[in] <in_buffer> the total buffer to parse
// param[in] <in_size> the total size of the buffer to parse
// param[out] <out> the int read from in_buffer at offset
// param[in/out] <offset> the current offset at which we are in <in_buffer>
bool pop_uint8_from_buffer(uint8_t *in_buffer, uint16_t in_size, uint8_t *out, uint16_t *offset) {
if (*offset + 1 > in_size) {
PRINTF("Failed to read the uint, only %d bytes available\n", in_size);
return false;
}
*out = in_buffer[*offset];
*offset += 1;

return true;
}
Loading
Loading