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 <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos 2022-04-06 14:38:22 +02:00
parent 24b1d6807b
commit 878eae9787
No known key found for this signature in database
GPG key ID: C0095B7870A4CCD3
3 changed files with 75 additions and 22 deletions

View file

@ -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();
}

View file

@ -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

View file

@ -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);