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

Split Logic vs Display & Enable FLEX/STAX Build & Test #21

Merged
merged 20 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
96 changes: 11 additions & 85 deletions src/app_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
keyDerivationPath_t path;
tx_state_t global_tx_state;

const internal_storage_t N_storage_real;

// The expected CLA byte
#define CLA 0xE0

Expand All @@ -53,6 +55,15 @@ void app_main() {
volatile unsigned int tx = 0;
volatile unsigned int flags = 0;

// Initialize the NVM data if required
if (N_storage.initialized != 0x01) {
internal_storage_t storage;
storage.dummy1_allowed = 0x00;
storage.dummy2_allowed = 0x00;
storage.initialized = 0x01;
nvm_write((void *) &N_storage, &storage, sizeof(internal_storage_t));
}

for (;;) {
volatile unsigned short sw = 0;

Expand Down Expand Up @@ -127,88 +138,3 @@ void app_main() {
END_TRY;
}
}

// Required Ledger magic starts here and ends at the end of the file.
// The only way to understand what is happening is to look at the source code in the SDK,
// as there is no help to get anywhere else. The magic has been taken from the helloworld sample
// application provided by Ledger at:
// https://github.com/LedgerHQ/ledger-sample-apps/blob/master/blue-app-helloworld/src/main.c.
// unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B];

// void io_seproxyhal_display(const bagl_element_t *element) {
// io_seproxyhal_display_default((bagl_element_t *) element);
// }

// unsigned char io_event(__attribute__((unused)) unsigned char channel) {
// // can't have more than one tag in the reply, not supported yet.
// switch (G_io_seproxyhal_spi_buffer[0]) {
// case SEPROXYHAL_TAG_FINGER_EVENT:
// UX_FINGER_EVENT(G_io_seproxyhal_spi_buffer);
// break;

// case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT:
// UX_BUTTON_PUSH_EVENT(G_io_seproxyhal_spi_buffer);
// break;

// case SEPROXYHAL_TAG_STATUS_EVENT:
// if (G_io_apdu_media == IO_APDU_MEDIA_USB_HID &&
// !(U4BE(G_io_seproxyhal_spi_buffer, 3) &
// SEPROXYHAL_TAG_STATUS_EVENT_FLAG_USB_POWERED)) {
// THROW(EXCEPTION_IO_RESET);
// }
// UX_DEFAULT_EVENT();
// break;

// case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT:
// UX_DISPLAYED_EVENT({});
// break;

// case SEPROXYHAL_TAG_TICKER_EVENT:
// UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, {});
// break;

// default:
// UX_DEFAULT_EVENT();
// break;
// }

// // close the event if not done previously (by a display or whatever)
// if (!io_seproxyhal_spi_is_status_sent()) {
// io_seproxyhal_general_status();
// }

// // command has been processed, DO NOT reset the current APDU transport
// return 1;
// }

// unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) {
// switch (channel & ~(IO_FLAGS)) {
// case CHANNEL_KEYBOARD:
// break;
// // multiplexed io exchange over a SPI channel and TLV encapsulated protocol
// case CHANNEL_SPI:
// if (tx_len) {
// io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len);
// if (channel & IO_RESET_AFTER_REPLIED) {
// reset();
// }
// return 0; // nothing received from the master so far (it's a tx transaction)
// } else {
// return io_seproxyhal_spi_recv(G_io_apdu_buffer, sizeof(G_io_apdu_buffer), 0);
// }
// default:
// THROW(INVALID_PARAMETER);
// }
// return 0;
// }

// void app_exit(void) {
// BEGIN_TRY_L(exit) {
// TRY_L(exit) {
// os_sched_exit(-1);
// }
// FINALLY_L(exit) {
// }
// }
// END_TRY_L(exit);
// }
122 changes: 104 additions & 18 deletions src/common/sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,12 @@
#include "os.h"
#include "util.h"
#include "ux.h"
#include "sign.h"
#include "display.h"
#include "responseCodes.h"

static tx_state_t *tx_state = &global_tx_state;

void buildAndSignTransactionHash();

// Common initial view for signing flows.
UX_STEP_NOCB(ux_sign_flow_shared_review, nn, {"Review", "transaction"});

// Common signature flow for all transactions allowing the user to either sign the transaction hash
// that is currently being processed, or declining to do so (sending back a user rejection error to
// the caller).
UX_STEP_CB(ux_sign_flow_shared_sign,
pnn,
buildAndSignTransactionHash(),
{&C_icon_validate_14, "Sign", "transaction"});
UX_STEP_CB(ux_sign_flow_shared_decline,
pnn,
sendUserRejection(),
{&C_icon_crossmark, "Decline to", "sign transaction"});
UX_FLOW(ux_sign_flow_shared, &ux_sign_flow_shared_sign, &ux_sign_flow_shared_decline);
static cborContext_t *ctx = &global.withDataBlob.cborContext;

// Hashes transaction, signs it and sends the signature back to the computer.
void buildAndSignTransactionHash() {
Expand All @@ -39,3 +25,103 @@
memmove(G_io_apdu_buffer, signedHash, sizeof(signedHash));
sendSuccess(sizeof(signedHash));
}

void handleCborStep(void) {
if (ctx->cborLength < 0) {
Dismissed Show dismissed Hide dismissed
THROW(ERROR_INVALID_STATE);
} else {
sendSuccessNoIdle(); // Request more data from the computer.
}
}

void readCborInitial(uint8_t *cdata, uint8_t dataLength) {
uint8_t header = cdata[0];
cdata += 1;
ctx->cborLength -= 1;
// the first byte of an cbor encoding contains the type (3 high bits) and the shortCount (5
// lower bits);
ctx->majorType = header >> 5;
uint8_t shortCount = header & 0x1f;

// Calculate length of cbor payload
// sizeLength: number of bytes (beside the header) used to indicate the payload length
uint8_t sizeLength = 0;
// length: payload byte size.
uint64_t length = 0;

ctx->displayUsed = 0;

if (shortCount < 24) {
// shortCount is the length, no extra bytes are used.
sizeLength = 0;
length = shortCount;
} else if (shortCount == 24) {
length = cdata[0];
sizeLength = 1;
} else if (shortCount == 25) {
length = U2BE(cdata, 0);
sizeLength = 2;
} else if (shortCount == 26) {
length = U4BE(cdata, 0);
sizeLength = 4;
} else if (shortCount == 27) {
length = U8BE(cdata, 0);
sizeLength = 8;
} else if (shortCount == 31) {
THROW(ERROR_UNSUPPORTED_CBOR);
} else {
THROW(ERROR_INVALID_PARAM);
}
cdata += sizeLength;

ctx->cborLength -= sizeLength;
switch (ctx->majorType) {
case 0:
// non-negative integer
bin2dec(ctx->display, sizeof(ctx->display), length);
if (ctx->cborLength != 0) {
THROW(ERROR_INVALID_STATE);
}
break;
case 1:
// negative integer
memmove(ctx->display, "-", 1);
if (length == UINT64_MAX) {
bin2dec(ctx->display + 1, sizeof(ctx->display) - 1, length);
memmove(ctx->display + 1 + 20, " - 1", 4);
} else {
bin2dec(ctx->display + 1, sizeof(ctx->display) - 1, 1 + length);
}
if (ctx->cborLength != 0) {
THROW(ERROR_INVALID_STATE);
}
break;
case 3:
// utf-8 string
if (ctx->cborLength != length) {
THROW(ERROR_INVALID_STATE);
}
readCborContent(cdata, dataLength - 1 - sizeLength);
break;
default:
THROW(ERROR_UNSUPPORTED_CBOR);
}
}

void readCborContent(uint8_t *cdata, uint8_t contentLength) {
ctx->cborLength -= contentLength;
switch (ctx->majorType) {
case 3:
memmove(ctx->display + ctx->displayUsed, cdata, contentLength);
ctx->displayUsed += contentLength;
break;
case 0:
case 1:
// Type 0 and 1 fails, because we don't support integers that can't fit in the initial
// payload.
THROW(ERROR_UNSUPPORTED_CBOR);
break;
default:
THROW(ERROR_INVALID_STATE);
}
}
26 changes: 21 additions & 5 deletions src/common/sign.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
#ifndef _SIGN_H_
#define _SIGN_H_
#pragma once

#include "ux.h"
#include "globals.h"

#ifdef HAVE_BAGL

extern const ux_flow_step_t ux_sign_flow_shared_review;
extern const ux_flow_step_t ux_sign_flow_shared_sign;
extern const ux_flow_step_t ux_sign_flow_shared_decline;
extern const ux_flow_step_t* const ux_sign_flow_shared[];

void buildAndSignTransactionHash();
extern const ux_flow_step_t *const ux_sign_flow_shared[];

#endif

/**
* Read a CBOR encoded dataBlob's initial part, i.e. the header, which contains the major type and
* length Only supports major type 0, 1 and 3 (non-negative integers, negative integers and utf-8
* strings) Does not support streaming (shortCount = 31).
*/
void readCborInitial(uint8_t *cdata, uint8_t dataLength);
/**
* Read part of a CBOR encoded dataBlob. Should only be used after readCborInitial.
*/
void readCborContent(uint8_t *cdata, uint8_t dataLength);
// extern const ux_flow_step_t *const ux_display_memo[];

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.

void handleCborStep(void);

void buildAndSignTransactionHash();
86 changes: 66 additions & 20 deletions src/common/ui/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,6 @@

#include "ux.h"

/**
* Read a CBOR encoded dataBlob's initial part, i.e. the header, which contains the major type and
* length Only supports major type 0, 1 and 3 (non-negative integers, negative integers and utf-8
* strings) Does not support streaming (shortCount = 31).
*/
void readCborInitial(uint8_t *cdata, uint8_t dataLength);
/**
* Read part of a CBOR encoded dataBlob. Should only be used after readCborInitial.
*/
void readCborContent(uint8_t *cdata, uint8_t dataLength);
// extern const ux_flow_step_t *const ux_display_memo[];
typedef struct {
uint32_t cborLength;
uint32_t displayUsed;
uint8_t display[255];
uint8_t majorType;
} cborContext_t;

void handleCborStep(void);

#endif

#ifdef HAVE_BAGL
Expand All @@ -34,3 +14,69 @@ extern const ux_flow_step_t ux_sign_flow_account_sender_view;

void uiComparePubkey(void);
void uiGeneratePubkey(volatile unsigned int *flags);
void uiExportPrivateKey(volatile unsigned int *flags);

#ifdef HAVE_BAGL
// Define the dynamic UI elements. These are required as the majority of
// the transaction elements are optional, so the UI has to be dynamically set.
extern const ux_flow_step_t *ux_sign_configure_baker_first[8];
extern const ux_flow_step_t *ux_sign_configure_baker_url[6];
extern const ux_flow_step_t *ux_sign_configure_baker_commission[9];
#endif

void startConfigureBakerCommissionDisplay(void);
void startConfigureBakerUrlDisplay(bool lastUrlPage);
void startConfigureBakerDisplay(void);

void startConfigureDelegationDisplay();

void uiSignUpdateCredentialInitialDisplay(volatile unsigned int *flags);
void uiSignUpdateCredentialIdDisplay(volatile unsigned int *flags);
void uiSignUpdateCredentialThresholdDisplay(volatile unsigned int *flags);
void uiSignCredentialDeploymentVerificationKeyDisplay(volatile unsigned int *flags);
void uiSignCredentialDeploymentVerificationKeyFlowDisplay(volatile unsigned int *flags);
void uiSignCredentialDeploymentNewIntroDisplay(void);
void uiSignCredentialDeploymentNewDisplay(void);

void uiSignCredentialDeploymentExistingIntroDisplay(void);
void uiSignCredentialDeploymentExistingDisplay(void);

// Encrypted amount transfer

#ifdef HAVE_BAGL
extern const ux_flow_step_t *ux_sign_encrypted_amount_transfer[8];
#endif

void startEncryptedTransferDisplay(bool displayMemo);

// Public information for IP
void uiReviewPublicInformationForIpDisplay(void);
void uiSignPublicInformationForIpPublicKeyDisplay(void);
void uiSignPublicInformationForIpCompleteDisplay(void);
void uiSignPublicInformationForIpFinalDisplay(void);

// Register data
void uiSignFlowSharedDisplay(void);
void uiRegisterDataInitialDisplay(volatile unsigned int *flags);
void uiRegisterDataPayloadDisplay(volatile unsigned int *flags);

// Sign Transfer
#ifdef HAVE_BAGL
extern const ux_flow_step_t *ux_sign_amount_transfer[8];
#endif

void startTransferDisplay(bool displayMemo, volatile unsigned int *flags);

// Sign Transfer to Encrypted
void uiSignTransferToEncryptedDisplay(volatile unsigned int *flags);
// Sign Transfer to Public
void uiSignTransferToPublicDisplay(volatile unsigned int *flags);

// Sign Transfer with Schedule
#ifdef HAVE_BAGL
extern const ux_flow_step_t *ux_sign_scheduled_amount_transfer[8];
#endif

void startInitialScheduledTransferDisplay(bool displayMemo);
void uiSignScheduledTransferPairFlowSignDisplay(void);
void uiSignScheduledTransferPairFlowDisplay(void);
Loading
Loading