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

Feat/ldg 510 nano app implement signtransfer method #8

Merged
merged 21 commits into from
Nov 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b03dc9b
test(verify_address): write the skeleton for the test
Meg4me Nov 19, 2024
290d1ac
test(verify_address): implement test for verify address
keiff3r Nov 21, 2024
1677a47
Merge branch 'feat/LDG-506--nano-app-implement-verifyaddress-method' …
keiff3r Nov 26, 2024
40ebe77
test: edit verify_address function to handle new derivation path
keiff3r Nov 26, 2024
b435ea4
test: generate golden snapshots
keiff3r Nov 26, 2024
eb79346
fix(tests): edit ledger_app.toml to run all tests
keiff3r Nov 26, 2024
e569e4b
test: correct issue in test_verify_address and generate golden snapshots
keiff3r Nov 26, 2024
3bb1514
Merge remote-tracking branch 'origin/main' into test/LDG-505--nano-ap…
keiff3r Nov 26, 2024
e8de030
style(tests): format python code
keiff3r Nov 26, 2024
b177a3e
fix(test): correct typo in test_verify_address.py
keiff3r Nov 26, 2024
3ccc081
test: write test for simple transfer
keiff3r Nov 26, 2024
54c9367
feat: implement simple transfer parsing and display
keiff3r Nov 28, 2024
f08e9a7
tests: comment out the old implementation of test_pubkey_cmd
keiff3r Nov 28, 2024
8c1f8a3
fix(tests): update sign_simple_transfer test and related commands
keiff3r Nov 28, 2024
af1db2c
feat(crypto): switch from ECDSA to EdDSA signature scheme
keiff3r Nov 28, 2024
7397267
style: format the codebase
keiff3r Nov 28, 2024
b2e46c4
Merge remote-tracking branch 'origin/main' into feat/LDG-510--nano-ap…
keiff3r Nov 28, 2024
fba65e7
fix(verify_address): remove redefinition of rtn
keiff3r Nov 28, 2024
d3d9ae5
test: delete unused snapshots
keiff3r Nov 28, 2024
c4a877f
test: updated snapshot with new sdk
GuilaneDen Nov 29, 2024
84f1ede
test: updated nanox snapshot with new sdk
GuilaneDen Nov 29, 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
1 change: 0 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ services:
volumes:
- ./bin:/speculos/apps
- ./src:/speculos/sources
- ./lib-app-bitcoin:/speculos/lib
- ./build:/speculos/build
ports:
- "5000:5000" # api
Expand Down
6 changes: 3 additions & 3 deletions src/apdu/dispatcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
#include "../handler/verify_address.h"
#include "../handler/get_app_name.h"
#include "../handler/get_public_key.h"
#include "../handler/sign_tx.h"
#include "../handler/sign_transfer.h"

int apdu_dispatcher(const command_t *cmd) {
LEDGER_ASSERT(cmd != NULL, "NULL cmd");
Expand Down Expand Up @@ -84,7 +84,7 @@ int apdu_dispatcher(const command_t *cmd) {
buf.offset = 0;

return handler_get_public_key(&buf, (bool) cmd->p1);
case SIGN_TX:
case SIGN_SIMPLE_TRANSFER:
if ((cmd->p1 == P1_START && cmd->p2 != P2_MORE) || //
cmd->p1 > P1_MAX || //
(cmd->p2 != P2_LAST && cmd->p2 != P2_MORE)) {
Expand All @@ -99,7 +99,7 @@ int apdu_dispatcher(const command_t *cmd) {
buf.size = cmd->lc;
buf.offset = 0;

return handler_sign_tx(&buf, cmd->p1, (bool) (cmd->p2 & P2_MORE));
return handler_sign_simple_transfer(&buf, cmd->p1, (bool) (cmd->p2 & P2_MORE));
default:
return io_send_sw(SW_INS_NOT_SUPPORTED);
}
Expand Down
7 changes: 6 additions & 1 deletion src/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@
/**
* Maximum signature length (bytes).
*/
#define MAX_DER_SIG_LEN 72
#define MAX_DER_SIG_LEN 64

/**
* Maximum BIP32 path length supported by the app.
*/
#define MAX_BIP32_PATH_SUPPORTED 8

/**
* Exponent used to convert mCCD to CCD unit (N CCD = N * 10^3 mCCD).
Expand Down
32 changes: 14 additions & 18 deletions src/handler/sign_tx.c → src/handler/sign_simple_transfer.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,18 @@

#include "os.h"
#include "cx.h"
// #include "cx_sha256.h"

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.
#include "buffer.h"

#include "sign_tx.h"
#include "sign_transfer.h"
#include "../sw.h"
#include "../globals.h"
#include "../ui/display.h"
#include "../transaction/types.h"
#include "../transaction/deserialize.h"

int handler_sign_tx(buffer_t *cdata, uint8_t chunk, bool more) {
// TODO: FINISH THIS
int handler_sign_simple_transfer(buffer_t *cdata, uint8_t chunk, bool more) {
if (chunk == 0) { // first APDU, parse BIP32 path
explicit_bzero(&G_context, sizeof(G_context));
G_context.req_type = CONFIRM_TRANSACTION;
Expand Down Expand Up @@ -73,33 +75,27 @@
.size = G_context.tx_info.raw_tx_len,
.offset = 0};

parser_status_e status = transaction_deserialize(&buf, &G_context.tx_info.transaction);
parser_status_e status = simple_transfer_deserialize(&buf, &G_context.tx_info);
PRINTF("Parsing status: %d.\n", status);
if (status != PARSING_OK) {
return io_send_sw(SW_TX_PARSING_FAIL);
}
// TODO: add a specific SW for wrong type
if (G_context.tx_info.type != TRANSACTION_TYPE_SIMPLE_TRANSFER) {
return io_send_sw(SW_BAD_STATE);
}

G_context.state = STATE_PARSED;

if (cx_keccak_256_hash(G_context.tx_info.raw_tx,
G_context.tx_info.raw_tx_len,
G_context.tx_info.m_hash) != CX_OK) {
if (cx_hash_sha256(G_context.tx_info.raw_tx,
G_context.tx_info.raw_tx_len,
G_context.tx_info.m_hash,
sizeof(G_context.tx_info.m_hash)) == 0) {
return io_send_sw(SW_TX_HASH_FAIL);
}

PRINTF("Hash: %.*H\n", sizeof(G_context.tx_info.m_hash), G_context.tx_info.m_hash);

// Example to trig a blind-sign flow
if (strcmp((char *) G_context.tx_info.transaction.memo, "Blind-sign") == 0) {
// to remove when Nbgl will be available for Nanos
#ifdef HAVE_NBGL
return ui_display_blind_signed_transaction();
#else
return ui_display_transaction();
#endif
} else {
return ui_display_transaction();
}
return ui_display_simple_transfer();
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/handler/sign_tx.h → src/handler/sign_transfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include "buffer.h"

/**
* Handler for SIGN_TX command. If successfully parse BIP32 path
* Handler for SIGN_SIMPLE_TRANSFER command. If successfully parse BIP32 path
* and transaction, sign transaction and send APDU response.
*
* @see G_context.bip32_path, G_context.tx_info.raw_transaction,
Expand All @@ -22,4 +22,4 @@
* @return zero or positive integer if success, negative integer otherwise.
*
*/
int handler_sign_tx(buffer_t *cdata, uint8_t chunk, bool more);
int handler_sign_simple_transfer(buffer_t *cdata, uint8_t chunk, bool more);
1 change: 1 addition & 0 deletions src/handler/verify_address.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ int handler_verify_address(buffer_t *cdata, bool is_new_address) {
size_t address_len = sizeof(G_context.verify_address_info.address);

// This function will return the number of bytes encoded, or -1 on error.
// TODO: Move this inside the function ui_display_verify_address()
rtn = address_to_base58(account_address,
sizeof(account_address),
G_context.verify_address_info.address,
Expand Down
12 changes: 3 additions & 9 deletions src/helper/send_reponse.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,7 @@ int helper_send_response_pubkey() {
}

int helper_send_response_sig() {
uint8_t resp[1 + MAX_DER_SIG_LEN + 1] = {0};
size_t offset = 0;

resp[offset++] = G_context.tx_info.signature_len;
memmove(resp + offset, G_context.tx_info.signature, G_context.tx_info.signature_len);
offset += G_context.tx_info.signature_len;
resp[offset++] = (uint8_t) G_context.tx_info.v;

return io_send_response_pointer(resp, offset, SW_OK);
return io_send_response_pointer(G_context.tx_info.signature,
G_context.tx_info.signature_len,
SW_OK);
}
15 changes: 14 additions & 1 deletion src/helper/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,20 @@ int get_bls_private_key(uint32_t *path,
size_t private_key_len);

/**
* Convert an address to a base58 encoded string.
* Converts a Concordium address to its Base58 string representation.
* The function adds version byte and checksum before encoding.
*
* @param[in] address Pointer to the raw address bytes to encode
* @param[in] address_len Length of the input address (must be CONCORDIUM_ADDRESS_LEN)
* @param[out] encoded_address Buffer to store the resulting Base58 encoded string
* @param[in] encoded_address_len Size of the output buffer
*
* @return The number of bytes written to encoded_address (excluding null terminator) on
* success, or -1 on error (e.g., if address_len is invalid)
*
* @note The function will automatically append a null terminator to the encoded string
* @note The encoded address format is: Base58(version_byte || address || checksum)
* where checksum is the first 4 bytes of double SHA256 of (version_byte || address)
*/
int address_to_base58(const uint8_t *address,
size_t address_len,
Expand Down
52 changes: 31 additions & 21 deletions src/transaction/deserialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,46 +27,56 @@
#include "ledger_assert.h"
#endif

parser_status_e transaction_deserialize(buffer_t *buf, transaction_t *tx) {
// TODO: EDIT THIS FUNCTION
parser_status_e simple_transfer_deserialize(buffer_t *buf, transaction_ctx_t *tx) {
LEDGER_ASSERT(buf != NULL, "NULL buf");
LEDGER_ASSERT(tx != NULL, "NULL tx");

if (buf->size > MAX_TX_LEN) {
return WRONG_LENGTH_ERROR;
}

// nonce
if (!buffer_read_u64(buf, &tx->nonce, BE)) {
return NONCE_PARSING_ERROR;
// Sender address (32 bytes)
tx->transaction.simple_transfer.sender = (uint8_t *) (buf->ptr + buf->offset);
if (!buffer_seek_cur(buf, ADDRESS_LEN)) {
return SENDER_PARSING_ERROR;
}

tx->to = (uint8_t *) (buf->ptr + buf->offset);
// Skip sequence number (8 bytes)
if (!buffer_seek_cur(buf, 8)) {
return PARSING_ERROR;
}

// TO address
if (!buffer_seek_cur(buf, ADDRESS_LEN)) {
return TO_PARSING_ERROR;
// Skip energy allowance (8 bytes)
if (!buffer_seek_cur(buf, 8)) {
return PARSING_ERROR;
}

// amount value
if (!buffer_read_u64(buf, &tx->value, BE)) {
return VALUE_PARSING_ERROR;
// Skip payload size (4 bytes)
if (!buffer_seek_cur(buf, 4)) {
return PARSING_ERROR;
}

// length of memo
if (!buffer_read_varint(buf, &tx->memo_len) && tx->memo_len > MAX_MEMO_LEN) {
return MEMO_LENGTH_ERROR;
// Skip expiration (8 bytes)
if (!buffer_seek_cur(buf, 8)) {
return PARSING_ERROR;
}

// memo
tx->memo = (uint8_t *) (buf->ptr + buf->offset);
// Transaction type (1 byte)
if (!buffer_read_u8(buf, &tx->type)) {
return TYPE_PARSING_ERROR;
}

if (!buffer_seek_cur(buf, tx->memo_len)) {
return MEMO_PARSING_ERROR;
// Recipient address (32 bytes)
tx->transaction.simple_transfer.recipient = (uint8_t *) (buf->ptr + buf->offset);
if (!buffer_seek_cur(buf, ADDRESS_LEN)) {
return RECIPIENT_PARSING_ERROR;
}

if (!transaction_utils_check_encoding(tx->memo, tx->memo_len)) {
return MEMO_ENCODING_ERROR;
// Amount (8 bytes)
if (!buffer_read_u64(buf, &tx->transaction.simple_transfer.value, BE)) {
return AMOUNT_PARSING_ERROR;
}

return (buf->offset == buf->size) ? PARSING_OK : WRONG_LENGTH_ERROR;
return PARSING_OK;
}
3 changes: 2 additions & 1 deletion src/transaction/deserialize.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "buffer.h"

#include "types.h"
#include "../types.h"

/**
* Deserialize raw transaction in structure.
Expand All @@ -15,4 +16,4 @@
* @return PARSING_OK if success, error status otherwise.
*
*/
parser_status_e transaction_deserialize(buffer_t *buf, transaction_t *tx);
parser_status_e simple_transfer_deserialize(buffer_t *buf, transaction_ctx_t *tx);
112 changes: 56 additions & 56 deletions src/transaction/serialize.c
Original file line number Diff line number Diff line change
@@ -1,69 +1,69 @@
/*****************************************************************************
* Ledger App Concordium.
* (c) 2024 Concordium.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
// /*****************************************************************************
// * Ledger App Concordium.
// * (c) 2024 Concordium.
// *
// * Licensed under the Apache License, Version 2.0 (the "License");
// * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at
// *
// * http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS,
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// * See the License for the specific language governing permissions and
// * limitations under the License.
// *****************************************************************************/

#include <stdint.h> // uint*_t
#include <stdbool.h> // bool
#include <stddef.h> // size_t
#include <string.h> // memmove
// #include <stdint.h> // uint*_t
// #include <stdbool.h> // bool
// #include <stddef.h> // size_t
// #include <string.h> // memmove

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.

#include "write.h"
#include "varint.h"
// #include "write.h"
// #include "varint.h"

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.

#include "serialize.h"
// #include "serialize.h"

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.

#if defined(TEST) || defined(FUZZ)
#include "assert.h"
#define LEDGER_ASSERT(x, y) assert(x)
#else
#include "ledger_assert.h"
#endif
// #if defined(TEST) || defined(FUZZ)
// #include "assert.h"
// #define LEDGER_ASSERT(x, y) assert(x)
// #else
// #include "ledger_assert.h"
// #endif

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.

int transaction_serialize(const transaction_t *tx, uint8_t *out, size_t out_len) {
size_t offset = 0;
// int transaction_serialize(const transaction_t *tx, uint8_t *out, size_t out_len) {
// size_t offset = 0;

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.

LEDGER_ASSERT(tx != NULL, "NULL tx");
LEDGER_ASSERT(out != NULL, "NULL out");
// LEDGER_ASSERT(tx != NULL, "NULL tx");
// LEDGER_ASSERT(out != NULL, "NULL out");

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.

if (8 + ADDRESS_LEN + 8 + varint_size(tx->memo_len) + tx->memo_len > out_len) {
return -1;
}
// if (8 + ADDRESS_LEN + 8 + varint_size(tx->memo_len) + tx->memo_len > out_len) {
// return -1;
// }

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.

// nonce
write_u64_be(out, offset, tx->nonce);
offset += 8;
// // nonce
// write_u64_be(out, offset, tx->nonce);
// offset += 8;

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.

// to
memmove(out + offset, tx->to, ADDRESS_LEN);
offset += ADDRESS_LEN;
// // to
// memmove(out + offset, tx->to, ADDRESS_LEN);
// offset += ADDRESS_LEN;

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.

// value
write_u64_be(out, offset, tx->value);
offset += 8;
// // value
// write_u64_be(out, offset, tx->value);
// offset += 8;

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.

// memo length
int varint_len = varint_write(out, offset, tx->memo_len);
if (varint_len < 0) {
return -1;
}
offset += varint_len;
// // memo length
// int varint_len = varint_write(out, offset, tx->memo_len);
// if (varint_len < 0) {
// return -1;
// }
// offset += varint_len;

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.

// memo
memmove(out + offset, tx->memo, tx->memo_len);
offset += tx->memo_len;
// // memo
// memmove(out + offset, tx->memo, tx->memo_len);
// offset += tx->memo_len;

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.

return (int) offset;
}
// return (int) offset;
// }

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.
Loading
Loading