From 878eae9787b96e667124627f237d192c8956ee7f Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Wed, 6 Apr 2022 14:38:22 +0200 Subject: [PATCH] Added press button to confirm. Everytime a private/secret key is loaded, the Pico HSM waits for BOOTSEL button press. This mechanism guarantees that no private/secret operations are made without user consent. To confirm the operation, the user must press the BOOTSEL button. In the meanwhile, the device gets into waiting state and no other operation is performed. After release the button, the operation continues normally. Signed-off-by: Pol Henarejos --- src/hsm/hsm2040.c | 59 +++++++++++++++++++++++++++++++---------------- src/hsm/hsm2040.h | 22 ++++++++++++++++-- src/hsm/sc_hsm.c | 16 +++++++++++++ 3 files changed, 75 insertions(+), 22 deletions(-) diff --git a/src/hsm/hsm2040.c b/src/hsm/hsm2040.c index 93d2cd6..6b4e337 100644 --- a/src/hsm/hsm2040.c +++ b/src/hsm/hsm2040.c @@ -29,7 +29,6 @@ #include "tusb.h" #include "usb_descriptors.h" #include "device/usbd_pvt.h" -#include "pico/util/queue.h" #include "pico/multicore.h" #include "random.h" #include "hsm2040.h" @@ -94,7 +93,8 @@ app_t *current_app = NULL; extern void card_thread(); -static queue_t *card_comm; +queue_t *card_comm = NULL; +queue_t *ccid_comm = NULL; extern void low_flash_init_core1(); int register_app(app_t * (*select_aid)()) { @@ -374,18 +374,28 @@ usbd_class_driver_t const *usbd_app_driver_get_cb(uint8_t *driver_count) { return &ccid_driver; } -enum { - BLINK_NOT_MOUNTED = (250 << 16) | 250, - BLINK_MOUNTED = (250 << 16) | 250, - BLINK_SUSPENDED = (500 << 16) | 1000, - BLINK_PROCESSING = (50 << 16) | 50, - - BLINK_ALWAYS_ON = UINT32_MAX, - BLINK_ALWAYS_OFF = 0 -}; static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; +void led_set_blink(uint32_t mode) { + blink_interval_ms = mode; +} + +void execute_tasks(); + +static void wait_button() { + led_set_blink((1000 << 16) | 100); + while (board_button_read() == false) { + execute_tasks(); + //sleep_ms(10); + } + while (board_button_read() == true) { + execute_tasks(); + //sleep_ms(10); + } + led_set_blink(BLINK_PROCESSING); +} + void usb_tx_enable(const uint8_t *buf, uint32_t len) { if (len > 0) { @@ -485,7 +495,7 @@ static enum ccid_state ccid_power_on(struct ccid *c) DEBUG_INFO("ON\r\n"); c->tx_busy = 1; - blink_interval_ms = BLINK_MOUNTED; + led_set_blink(BLINK_MOUNTED); return CCID_STATE_WAIT; } @@ -532,7 +542,7 @@ static enum ccid_state ccid_power_off(struct ccid *c) ccid_send_status (c); DEBUG_INFO ("OFF\r\n"); c->tx_busy = 1; - blink_interval_ms = BLINK_SUSPENDED; + led_set_blink(BLINK_SUSPENDED); return CCID_STATE_START; } @@ -1376,7 +1386,7 @@ void prepare_ccid() } int process_apdu() { - blink_interval_ms = BLINK_PROCESSING; + led_set_blink(BLINK_PROCESSING); if (!current_app) { if (INS(apdu) == 0xA4 && P1(apdu) == 0x04 && (P2(apdu) == 0x00 || P2(apdu) == 0x4)) { //select by AID for (int a = 0; a < num_apps; a++) { @@ -1406,7 +1416,7 @@ static void card_init (void) void card_thread() { - queue_t *ccid_comm = (queue_t *)multicore_fifo_pop_blocking(); + ccid_comm = (queue_t *)multicore_fifo_pop_blocking(); card_comm = (queue_t *)multicore_fifo_pop_blocking(); card_init (); @@ -1531,7 +1541,7 @@ void ccid_task(void) { DEBUG_INFO ("ERR05\r\n"); } - blink_interval_ms = BLINK_MOUNTED; + led_set_blink(BLINK_MOUNTED); } else if (m == EV_TX_FINISHED) { @@ -1542,6 +1552,11 @@ void ccid_task(void) if (c->state == APDU_STATE_WAIT_COMMAND || c->state == APDU_STATE_COMMAND_CHAINING || c->state == APDU_STATE_RESULT_GET_RESPONSE) ccid_prepare_receive(c); } + else if (m == EV_PRESS_BUTTON) { + wait_button(); + uint32_t flag = EV_BUTTON_PRESSED; + queue_try_add(&c->card_comm, &flag); + } } else /* Timeout */ { @@ -1624,6 +1639,13 @@ extern void neug_task(); pico_unique_board_id_t unique_id; +void execute_tasks() { + prev_millis = board_millis(); + ccid_task(); + tud_task(); // tinyusb device task + led_blinking_task(); +} + int main(void) { struct apdu *a = &apdu; @@ -1660,10 +1682,7 @@ int main(void) while (1) { - prev_millis = board_millis(); - ccid_task(); - tud_task(); // tinyusb device task - led_blinking_task(); + execute_tasks(); neug_task(); do_flash(); } diff --git a/src/hsm/hsm2040.h b/src/hsm/hsm2040.h index 3e74ad2..996e29d 100644 --- a/src/hsm/hsm2040.h +++ b/src/hsm/hsm2040.h @@ -22,6 +22,7 @@ #include "tusb.h" #include "file.h" #include "pico/unique_id.h" +#include "pico/util/queue.h" #define USB_REQ_CCID 0xA1 @@ -79,13 +80,18 @@ struct apdu { #define EV_EXEC_ACK_REQUIRED 4 /* OpenPGPcard Execution ACK required */ #define EV_EXEC_FINISHED 8 /* OpenPGPcard Execution finished */ #define EV_RX_DATA_READY 16 /* USB Rx data available */ +#define EV_PRESS_BUTTON 32 -/* OpenPGPcard thread */ +/* SC HSM thread */ #define EV_MODIFY_CMD_AVAILABLE 1 #define EV_VERIFY_CMD_AVAILABLE 2 #define EV_CMD_AVAILABLE 4 #define EV_EXIT 8 -#define EV_PINPAD_INPUT_DONE 16 +#define EV_BUTTON_PRESSED 16 + +//Variables set by core1 +extern queue_t *ccid_comm; +extern queue_t *card_comm; enum ccid_state { CCID_STATE_NOCARD, /* No card available */ @@ -157,4 +163,16 @@ extern void low_flash_available(); extern int flash_clear_file(file_t *file); extern pico_unique_board_id_t unique_id; + +enum { + BLINK_NOT_MOUNTED = (250 << 16) | 250, + BLINK_MOUNTED = (250 << 16) | 250, + BLINK_SUSPENDED = (500 << 16) | 1000, + BLINK_PROCESSING = (50 << 16) | 50, + + BLINK_ALWAYS_ON = UINT32_MAX, + BLINK_ALWAYS_OFF = 0 +}; +extern void led_set_blink(uint32_t mode); + #endif \ No newline at end of file diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 1203991..dd4076b 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -101,6 +101,17 @@ uint16_t get_device_options() { return 0x0; } +extern uint32_t board_button_read(void); + +static void wait_button() { + uint32_t val = EV_PRESS_BUTTON; + queue_try_add(ccid_comm, &val); + do { + queue_remove_blocking(card_comm, &val); + } + while (val != EV_BUTTON_PRESSED); +} + static int cmd_select() { uint8_t p1 = P1(apdu); uint8_t p2 = P2(apdu); @@ -1191,6 +1202,7 @@ static int cmd_key_gen() { } int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) { + wait_button(); int key_size = file_read_uint16(fkey->data); uint8_t kdata[4096/8]; memcpy(kdata, file_read(fkey->data+2), key_size); @@ -1225,6 +1237,7 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) { } int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) { + wait_button(); int key_size = file_read_uint16(fkey->data); uint8_t kdata[67]; //Worst case, 521 bit + 1byte memcpy(kdata, file_read(fkey->data+2), key_size); @@ -1417,6 +1430,7 @@ static int cmd_key_wrap() { } else if (*dprkd == P15_KEYTYPE_AES) { uint8_t kdata[32]; //maximum AES key size + wait_button(); int key_size = file_read_uint16(ef->data), aes_type = HSM_KEY_AES; memcpy(kdata, file_read(ef->data+2), key_size); if (dkek_decrypt(kdata, key_size) != 0) { @@ -1526,6 +1540,7 @@ static int cmd_decrypt_asym() { } else if (P2(apdu) == ALGO_EC_DH) { mbedtls_ecdh_context ctx; + wait_button(); int key_size = file_read_uint16(ef->data); uint8_t *kdata = (uint8_t *)calloc(1,key_size); memcpy(kdata, file_read(ef->data+2), key_size); @@ -1580,6 +1595,7 @@ static int cmd_cipher_sym() { if ((apdu.cmd_apdu_data_len % 16) != 0) { return SW_WRONG_LENGTH(); } + wait_button(); int key_size = file_read_uint16(ef->data); uint8_t kdata[32]; //maximum AES key size memcpy(kdata, file_read(ef->data+2), key_size);