Skip to content

Commit

Permalink
Factor out common APDU code and normalize
Browse files Browse the repository at this point in the history
  • Loading branch information
3noch committed Feb 20, 2019
1 parent b6977cb commit 020a47d
Show file tree
Hide file tree
Showing 12 changed files with 62 additions and 82 deletions.
32 changes: 12 additions & 20 deletions src/apdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,38 +10,30 @@ size_t provide_pubkey(uint8_t *const io_buffer, cx_ecfp_public_key_t const *cons
io_buffer[tx++] = pubkey->W_len;
memmove(io_buffer + tx, pubkey->W, pubkey->W_len);
tx += pubkey->W_len;
io_buffer[tx++] = 0x90;
io_buffer[tx++] = 0x00;
return tx;
return finalize_successful_send(tx);
}

unsigned int handle_apdu_error(uint8_t __attribute__((unused)) instruction) {
size_t handle_apdu_error(uint8_t __attribute__((unused)) instruction) {
THROW(EXC_INVALID_INS);
}

unsigned int handle_apdu_version(uint8_t __attribute__((unused)) instruction) {
int tx = 0;
size_t handle_apdu_version(uint8_t __attribute__((unused)) instruction) {
memcpy(G_io_apdu_buffer, &version, sizeof(version_t));
tx += sizeof(version_t);
G_io_apdu_buffer[tx++] = 0x90;
G_io_apdu_buffer[tx++] = 0x00;
return tx;
size_t tx = sizeof(version_t);
return finalize_successful_send(tx);
}

unsigned int handle_apdu_git(uint8_t __attribute__((unused)) instruction) {
size_t handle_apdu_git(uint8_t __attribute__((unused)) instruction) {
static const char commit[] = COMMIT;
memcpy(G_io_apdu_buffer, commit, sizeof(commit));

uint32_t tx = sizeof(commit);
G_io_apdu_buffer[tx++] = 0x90;
G_io_apdu_buffer[tx++] = 0x00;
return tx;
size_t tx = sizeof(commit);
return finalize_successful_send(tx);
}

#define CLA 0x80

__attribute__((noreturn))
void main_loop(apdu_handler handlers[INS_MAX]) {
void main_loop(apdu_handler const *const handlers, size_t const handlers_size) {
volatile uint32_t rx = io_exchange(CHANNEL_APDU, 0);
while (true) {
BEGIN_TRY {
Expand All @@ -65,12 +57,12 @@ void main_loop(apdu_handler handlers[INS_MAX]) {
THROW(EXC_WRONG_LENGTH);
}

const uint8_t instruction = G_io_apdu_buffer[OFFSET_INS];
const apdu_handler cb = (instruction >= INS_MAX)
uint8_t const instruction = G_io_apdu_buffer[OFFSET_INS];
apdu_handler const cb = instruction >= handlers_size
? handle_apdu_error
: handlers[instruction];

const uint32_t tx = cb(instruction);
size_t const tx = cb(instruction);
rx = io_exchange(CHANNEL_APDU, tx);
}
CATCH(ASYNC_EXCEPTION) {
Expand Down
23 changes: 15 additions & 8 deletions src/apdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,28 @@
#define INS_DEAUTHORIZE 0x0C

__attribute__((noreturn))
void main_loop(apdu_handler handlers[INS_MAX]);
void main_loop(apdu_handler const *const handlers, size_t const handlers_size);

static inline void return_ok(void) {
THROW(EXC_NO_ERROR);
}

static inline size_t finalize_successful_send(size_t tx) {
G_io_apdu_buffer[tx++] = 0x90;
G_io_apdu_buffer[tx++] = 0x00;
return tx;
}

// Send back response; do not restart the event loop
static inline void delayed_send(uint32_t tx) {
static inline void delayed_send(size_t tx) {
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
}

static inline bool delay_reject(void) {
G_io_apdu_buffer[0] = EXC_REJECT >> 8;
G_io_apdu_buffer[1] = EXC_REJECT & 0xFF;
delayed_send(2);
size_t tx = 0;
G_io_apdu_buffer[tx++] = EXC_REJECT >> 8;
G_io_apdu_buffer[tx++] = EXC_REJECT & 0xFF;
delayed_send(tx);
return true;
}

Expand All @@ -63,6 +70,6 @@ static inline void require_hid(void) {

size_t provide_pubkey(uint8_t *const io_buffer, cx_ecfp_public_key_t const *const pubkey);

uint32_t handle_apdu_error(uint8_t instruction);
uint32_t handle_apdu_version(uint8_t instruction);
uint32_t handle_apdu_git(uint8_t instruction);
size_t handle_apdu_error(uint8_t instruction);
size_t handle_apdu_version(uint8_t instruction);
size_t handle_apdu_git(uint8_t instruction);
41 changes: 14 additions & 27 deletions src/apdu_baking.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

static bool reset_ok(void);

unsigned int handle_apdu_reset(__attribute__((unused)) uint8_t instruction) {
size_t handle_apdu_reset(__attribute__((unused)) uint8_t instruction) {
uint8_t *dataBuffer = G_io_apdu_buffer + OFFSET_CDATA;
uint32_t dataLength = G_io_apdu_buffer[OFFSET_LC];
if (dataLength != sizeof(int)) {
Expand Down Expand Up @@ -42,16 +42,12 @@ bool reset_ok(void) {
ram->hwm.test.had_endorsement = false;
});

uint32_t tx = 0;
G_io_apdu_buffer[tx++] = 0x90;
G_io_apdu_buffer[tx++] = 0x00;

// Send back the response, do not restart the event loop
delayed_send(tx);
delayed_send(finalize_successful_send(0));
return true;
}

uint32_t send_word_big_endian(uint32_t tx, uint32_t word) {
size_t send_word_big_endian(size_t tx, uint32_t word) {
char word_bytes[sizeof(word)];

memcpy(word_bytes, &word, sizeof(word));
Expand All @@ -65,49 +61,40 @@ uint32_t send_word_big_endian(uint32_t tx, uint32_t word) {
return tx + i;
}

unsigned int handle_apdu_all_hwm(__attribute__((unused)) uint8_t instruction) {
uint32_t tx = 0;
size_t handle_apdu_all_hwm(__attribute__((unused)) uint8_t instruction) {
size_t tx = 0;
tx = send_word_big_endian(tx, N_data.hwm.main.highest_level);
tx = send_word_big_endian(tx, N_data.hwm.test.highest_level);
tx = send_word_big_endian(tx, N_data.main_chain_id.v);
G_io_apdu_buffer[tx++] = 0x90;
G_io_apdu_buffer[tx++] = 0x00;
return tx;
return finalize_successful_send(tx);
}

unsigned int handle_apdu_main_hwm(__attribute__((unused)) uint8_t instruction) {
uint32_t tx = 0;
size_t handle_apdu_main_hwm(__attribute__((unused)) uint8_t instruction) {
size_t tx = 0;
tx = send_word_big_endian(tx, N_data.hwm.main.highest_level);
G_io_apdu_buffer[tx++] = 0x90;
G_io_apdu_buffer[tx++] = 0x00;
return tx;
return finalize_successful_send(tx);
}


unsigned int handle_apdu_query_auth_key(__attribute__((unused)) uint8_t instruction) {
size_t handle_apdu_query_auth_key(__attribute__((unused)) uint8_t instruction) {
uint8_t const length = N_data.baking_key.bip32_path.length;

uint32_t tx = 0;
size_t tx = 0;
G_io_apdu_buffer[tx++] = length;

for (uint8_t i = 0; i < length; ++i) {
tx = send_word_big_endian(tx, N_data.baking_key.bip32_path.components[i]);
}

G_io_apdu_buffer[tx++] = 0x90;
G_io_apdu_buffer[tx++] = 0x00;
return tx;
return finalize_successful_send(tx);
}

unsigned int handle_apdu_deauthorize(__attribute__((unused)) uint8_t instruction) {
size_t handle_apdu_deauthorize(__attribute__((unused)) uint8_t instruction) {
if (READ_UNALIGNED_BIG_ENDIAN(uint8_t, &G_io_apdu_buffer[OFFSET_P1]) != 0) THROW(EXC_WRONG_PARAM);
if (READ_UNALIGNED_BIG_ENDIAN(uint8_t, &G_io_apdu_buffer[OFFSET_LC]) != 0) THROW(EXC_PARSE_ERROR);
UPDATE_NVRAM(ram, {
memset(&ram->baking_key, 0, sizeof(ram->baking_key));
});

unsigned int tx = 0;
G_io_apdu_buffer[tx++] = 0x90;
G_io_apdu_buffer[tx++] = 0x00;
return tx;
return finalize_successful_send(0);
}
11 changes: 6 additions & 5 deletions src/apdu_baking.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#pragma once

#include <stddef.h>
#include <stdint.h>

unsigned int handle_apdu_reset(uint8_t instruction);
unsigned int handle_apdu_query_auth_key(uint8_t instruction);
unsigned int handle_apdu_main_hwm(uint8_t instruction);
unsigned int handle_apdu_all_hwm(uint8_t instruction);
unsigned int handle_apdu_deauthorize(uint8_t instruction);
size_t handle_apdu_reset(uint8_t instruction);
size_t handle_apdu_query_auth_key(uint8_t instruction);
size_t handle_apdu_main_hwm(uint8_t instruction);
size_t handle_apdu_all_hwm(uint8_t instruction);
size_t handle_apdu_deauthorize(uint8_t instruction);
2 changes: 1 addition & 1 deletion src/apdu_pubkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ static bool baking_ok(void) {
}
#endif

unsigned int handle_apdu_get_public_key(uint8_t instruction) {
size_t handle_apdu_get_public_key(uint8_t instruction) {
uint8_t *dataBuffer = G_io_apdu_buffer + OFFSET_CDATA;

if (READ_UNALIGNED_BIG_ENDIAN(uint8_t, &G_io_apdu_buffer[OFFSET_P1]) != 0) THROW(EXC_WRONG_PARAM);
Expand Down
2 changes: 1 addition & 1 deletion src/apdu_pubkey.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

#include "apdu.h"

unsigned int handle_apdu_get_public_key(uint8_t instruction);
size_t handle_apdu_get_public_key(uint8_t instruction);
2 changes: 1 addition & 1 deletion src/apdu_setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ __attribute__((noreturn)) static void prompt_setup(
ui_prompt(prompts, NULL, ok_cb, cxl_cb);
}

__attribute__((noreturn)) unsigned int handle_apdu_setup(__attribute__((unused)) uint8_t instruction) {
__attribute__((noreturn)) size_t handle_apdu_setup(__attribute__((unused)) uint8_t instruction) {
if (READ_UNALIGNED_BIG_ENDIAN(uint8_t, &G_io_apdu_buffer[OFFSET_P1]) != 0) THROW(EXC_WRONG_PARAM);

uint32_t const buff_size = READ_UNALIGNED_BIG_ENDIAN(uint8_t, &G_io_apdu_buffer[OFFSET_LC]);
Expand Down
3 changes: 2 additions & 1 deletion src/apdu_setup.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <stddef.h>
#include <stdint.h>

unsigned int handle_apdu_setup(uint8_t instruction);
size_t handle_apdu_setup(uint8_t instruction);
22 changes: 7 additions & 15 deletions src/apdu_sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,13 @@ static void finish_hashing(uint8_t *hash, size_t hash_size) {
static int perform_signature(bool hash_first);

static bool sign_ok(void) {
int tx = perform_signature(true);
delayed_send(tx);
delayed_send(perform_signature(true));
return true;
}

#ifndef BAKING_APP
static bool sign_unsafe_ok(void) {
int tx = perform_signature(false);
delayed_send(tx);
delayed_send(perform_signature(false));
return true;
}
#endif
Expand Down Expand Up @@ -477,7 +475,7 @@ uint32_t wallet_sign_complete(uint8_t instruction) {
#define P1_HASH_ONLY_NEXT 0x03 // You only need it once
#define P1_LAST_MARKER 0x80

unsigned int handle_apdu_sign(uint8_t instruction) {
size_t handle_apdu_sign(uint8_t instruction) {
uint8_t p1 = G_io_apdu_buffer[OFFSET_P1];
uint8_t *dataBuffer = G_io_apdu_buffer + OFFSET_CDATA;
uint32_t dataLength = G_io_apdu_buffer[OFFSET_LC];
Expand Down Expand Up @@ -552,18 +550,15 @@ static int perform_signature(bool hash_first) {
#ifndef BAKING_APP
if (G.hash_only) {
memcpy(G_io_apdu_buffer, data, datalen);
uint32_t tx = datalen;

G_io_apdu_buffer[tx++] = 0x90;
G_io_apdu_buffer[tx++] = 0x00;
return tx;
size_t tx = datalen;
return finalize_successful_send(tx);
}
#endif
}

struct key_pair *const pair = generate_key_pair(G.key.curve, &G.key.bip32_path);

uint32_t tx;
size_t tx = 0;
switch (G.key.curve) {
case CX_CURVE_Ed25519: {
tx = cx_eddsa_sign(&pair->private_key,
Expand Down Expand Up @@ -601,10 +596,7 @@ static int perform_signature(bool hash_first) {

memset(&pair->private_key, 0, sizeof(pair->private_key));

G_io_apdu_buffer[tx++] = 0x90;
G_io_apdu_buffer[tx++] = 0x00;

clear_data();

return tx;
return finalize_successful_send(tx);
}
2 changes: 1 addition & 1 deletion src/apdu_sign.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

#include "apdu.h"

unsigned int handle_apdu_sign(uint8_t instruction);
size_t handle_apdu_sign(uint8_t instruction);
2 changes: 1 addition & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,5 @@ void app_main(void) {
#else
global.handlers[APDU_INS(INS_SIGN_UNSAFE)] = handle_apdu_sign;
#endif
main_loop(global.handlers);
main_loop(global.handlers, sizeof(global.handlers));
}
2 changes: 1 addition & 1 deletion src/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <string.h>

// Return number of bytes to transmit (tx)
typedef uint32_t (*apdu_handler)(uint8_t instruction);
typedef size_t (*apdu_handler)(uint8_t instruction);

typedef uint32_t level_t;

Expand Down

0 comments on commit 020a47d

Please sign in to comment.