From c6e32a36fbcb9fde0c883d95bfcf1d85b52bedad Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 27 Sep 2018 07:30:17 +0900 Subject: [PATCH] Experimental Ack-button feature added (not yet finished). --- src/Makefile | 1 + src/ack-button.c | 35 +++++++++++++++++++++++++++++++++++ src/gnuk.h | 33 +++++++++++++++++++++++++-------- src/openpgp-do.c | 18 +++++++++++++++--- src/openpgp.c | 12 ++++++++---- src/usb-ccid.c | 45 ++++++++++++++++++++++++++++++++++++--------- src/usb_ctrl.c | 2 +- 7 files changed, 121 insertions(+), 25 deletions(-) create mode 100644 src/ack-button.c diff --git a/src/Makefile b/src/Makefile index b864e60..f46738f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -51,6 +51,7 @@ endif ifeq ($(CHIP),stm32f103) CSRC += mcu-stm32f103.c +CSRC += ack-button.c endif ################################### diff --git a/src/ack-button.c b/src/ack-button.c new file mode 100644 index 0000000..6de8b7b --- /dev/null +++ b/src/ack-button.c @@ -0,0 +1,35 @@ +#include +#include +#include + +#include "board.h" +#include "mcu/stm32f103.h" + +void +ackbtn_init (chopstx_intr_t *intr) +{ + chopstx_claim_irq (intr, INTR_REQ_EXTI); + + /* Configure EXTI line */ +#ifdef AFIO_EXTICR_INDEX + AFIO->EXTICR[AFIO_EXTICR_INDEX] = AFIO_EXTICR1_EXTIx_Py; +#endif + EXTI->IMR &= ~EXTI_IMR; + EXTI->RTSR |= EXTI_RTSR_TR; +} + +void +ackbtn_enable (void) +{ + EXTI->PR |= EXTI_PR; + EXTI->IMR |= EXTI_IMR; +} + +void +ackbtn_disable (void) +{ + EXTI->IMR &= ~EXTI_IMR; + EXTI->PR |= EXTI_PR; +} + + diff --git a/src/gnuk.h b/src/gnuk.h index e0e05cf..bca8af8 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -24,10 +24,11 @@ extern struct apdu apdu; void ccid_card_change_signal (int how); /* CCID thread */ -#define EV_RX_DATA_READY 1 /* USB Rx data available */ -#define EV_EXEC_FINISHED 2 /* OpenPGP Execution finished */ -#define EV_TX_FINISHED 4 /* CCID Tx finished */ -#define EV_CARD_CHANGE 8 +#define EV_RX_DATA_READY 1 /* USB Rx data available */ +#define EV_EXEC_FINISHED 2 /* OpenPGP Execution finished */ +#define EV_EXEC_FINISHED_ACK 4 /* OpenPGP Execution finished, requires ACK */ +#define EV_TX_FINISHED 8 /* CCID Tx finished */ +#define EV_CARD_CHANGE 16 /* OpenPGPcard thread */ #define EV_PINPAD_INPUT_DONE 1 @@ -53,12 +54,12 @@ enum ccid_state { CCID_STATE_NOCARD, /* No card available */ CCID_STATE_START, /* Initial */ CCID_STATE_WAIT, /* Waiting APDU */ - /* Busy1, Busy2, Busy3, Busy5 */ - CCID_STATE_EXECUTE, /* Busy4 */ + CCID_STATE_EXECUTE, /* Executing command */ + CCID_STATE_CONFIRM_ACK, /* Execution finished, waiting user's ACK */ CCID_STATE_RECEIVE, /* APDU Received Partially */ CCID_STATE_SEND, /* APDU Sent Partially */ - CCID_STATE_EXITED, /* ICC Thread Terminated */ + CCID_STATE_EXITED, /* CCID Thread Terminated */ CCID_STATE_EXEC_REQUESTED, /* Exec requested */ }; @@ -378,7 +379,17 @@ extern uint8_t admin_authorized; #define NR_KEY_ALGO_ATTR_DEC 0xf2 #define NR_KEY_ALGO_ATTR_AUT 0xf3 /* - * NR_UINT_SOMETHING could be here... Use 0xf[456789abcd] + * Representation of User Interaction Flag: + * 0 (UIF disabled): No record in flash memory + * 1 (UIF enabled): 0xf?ff + * 2 (UIF permanently enabled): 0xf?00 + * + */ +#define NR_DO_UIF_SIG 0xf6 +#define NR_DO_UIF_DEC 0xf7 +#define NR_DO_UIF_AUT 0xf8 +/* + * NR_UINT_SOMETHING could be here... Use 0xf[459abcd] */ /* 123-counters: Recorded in flash memory by 2-halfword (4-byte). */ /* @@ -461,6 +472,12 @@ int pinpad_getline (int msg_code, uint32_t timeout_usec); #endif +struct chx_intr; +void ackbtn_init (struct chx_intr *intr); +void ackbtn_enable (void); +void ackbtn_disable (void); + + extern uint8_t _regnual_start, __heap_end__[]; uint8_t * sram_address (uint32_t offset); diff --git a/src/openpgp-do.c b/src/openpgp-do.c index a7ac155..c463aad 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -135,6 +135,12 @@ static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = { 0x01, 0x00, }; +/* General Feature Management */ +static const uint8_t feature_mngmnt[] __attribute__ ((aligned (1))) = { + 3, + 0x81, 0x01, 0x20, +}; + /* Algorithm Attributes */ #define OPENPGP_ALGO_RSA 0x01 #define OPENPGP_ALGO_ECDH 0x12 @@ -1614,18 +1620,20 @@ static const uint16_t cmp_ch_data[] = { }; static const uint16_t cmp_app_data[] = { - 3, + 4, GPG_DO_AID, GPG_DO_HIST_BYTES, GPG_DO_DISCRETIONARY, + GPG_DO_FEATURE_MNGMNT, }; static const uint16_t cmp_discretionary[] = { - 8, + 11, GPG_DO_EXTCAP, GPG_DO_ALG_SIG, GPG_DO_ALG_DEC, GPG_DO_ALG_AUT, GPG_DO_PW_STATUS, - GPG_DO_FP_ALL, GPG_DO_CAFP_ALL, GPG_DO_KGTIME_ALL + GPG_DO_FP_ALL, GPG_DO_CAFP_ALL, GPG_DO_KGTIME_ALL, + GPG_DO_UIF_SIG, GPG_DO_UIF_DEC, GPG_DO_UIF_AUT }; static const uint16_t cmp_ss_temp[] = { 1, GPG_DO_DS_COUNT }; @@ -1664,11 +1672,15 @@ gpg_do_table[] = { rw_algorithm_attr }, { GPG_DO_ALG_AUT, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, rw_algorithm_attr }, + { GPG_DO_UIF_SIG, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, rw_uif }, + { GPG_DO_UIF_DEC, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, rw_uif }, + { GPG_DO_UIF_AUT, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, rw_uif }, { GPG_DO_KDF, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, rw_kdf }, /* Fixed data */ { GPG_DO_HIST_BYTES, DO_FIXED, AC_ALWAYS, AC_NEVER, historical_bytes }, { GPG_DO_EXTCAP, DO_FIXED, AC_ALWAYS, AC_NEVER, extended_capabilities }, + { GPG_DO_FEATURE_MNGMNT, DO_FIXED, AC_ALWAYS, AC_NEVER, feature_mngmnt }, /* Compound data: Read access only */ { GPG_DO_CH_DATA, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_ch_data }, { GPG_DO_APP_DATA, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_app_data }, diff --git a/src/openpgp.c b/src/openpgp.c index 134a8d2..15c024c 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -1501,7 +1501,7 @@ const struct command cmds[] = { }; #define NUM_CMDS ((int)(sizeof (cmds) / sizeof (struct command))) -static void +static int process_command_apdu (void) { int i; @@ -1536,6 +1536,8 @@ process_command_apdu (void) DEBUG_BYTE (cmd); GPG_NO_INS (); } + + return (cmd == INS_PSO) | (cmd == INS_INTERNAL_AUTHENTICATE); } void * @@ -1553,6 +1555,7 @@ openpgp_card_thread (void *arg) int len, pw_len, newpw_len; #endif eventmask_t m = eventflag_wait (openpgp_comm); + int r = 0; DEBUG_INFO ("GPG!: "); @@ -1640,10 +1643,11 @@ openpgp_card_thread (void *arg) break; led_blink (LED_START_COMMAND); - process_command_apdu (); - led_blink (LED_FINISH_COMMAND); + r = process_command_apdu (); + if (!r) + led_blink (LED_FINISH_COMMAND); done: - eventflag_signal (ccid_comm, EV_EXEC_FINISHED); + eventflag_signal (ccid_comm, r? EV_EXEC_FINISHED_ACK : EV_EXEC_FINISHED); } gpg_fini (); diff --git a/src/usb-ccid.c b/src/usb-ccid.c index 8fd3505..759a2e7 100644 --- a/src/usb-ccid.c +++ b/src/usb-ccid.c @@ -1,7 +1,7 @@ /* * usb-ccid.c -- USB CCID protocol handling * - * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 + * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 * Free Software Initiative of Japan * Author: NIIBE Yutaka * @@ -1076,7 +1076,9 @@ ccid_send_data_block (struct ccid *c) static void ccid_send_data_block_time_extension (struct ccid *c) { - ccid_send_data_block_internal (c, CCID_CMD_STATUS_TIMEEXT, 1); + ccid_send_data_block_internal (c, CCID_CMD_STATUS_TIMEEXT, + (c->ccid_state == CCID_STATE_CONFIRM_ACK? + 0xff : 1)); } static void @@ -1461,6 +1463,7 @@ ccid_handle_data (struct ccid *c) } break; case CCID_STATE_EXECUTE: + case CCID_STATE_CONFIRM_ACK: if (c->ccid_header.msg_type == CCID_POWER_OFF) next_state = ccid_power_off (c); else if (c->ccid_header.msg_type == CCID_SLOT_STATUS) @@ -1489,6 +1492,7 @@ ccid_handle_timeout (struct ccid *c) switch (c->ccid_state) { case CCID_STATE_EXECUTE: + case CCID_STATE_CONFIRM_ACK: ccid_send_data_block_time_extension (c); break; default: @@ -1561,7 +1565,8 @@ extern int usb_get_descriptor (struct usb_dev *dev); extern void random_init (void); extern void random_fini (void); -static chopstx_intr_t interrupt; +static chopstx_intr_t ack_intr; +static chopstx_intr_t usb_intr; /* * Return 0 for normal USB event @@ -1576,7 +1581,7 @@ usb_event_handle (struct usb_dev *dev) e = usb_lld_event_handler (dev); ep_num = USB_EVENT_ENDP (e); - chopstx_intr_done (&interrupt); + chopstx_intr_done (&usb_intr); /* Transfer to endpoint (not control endpoint) */ if (ep_num != 0) @@ -1678,7 +1683,8 @@ usb_event_handle (struct usb_dev *dev) static chopstx_poll_cond_t ccid_event_poll_desc; static struct chx_poll_head *const ccid_poll[] = { - (struct chx_poll_head *const)&interrupt, + (struct chx_poll_head *const)&ack_intr, + (struct chx_poll_head *const)&usb_intr, (struct chx_poll_head *const)&ccid_event_poll_desc }; #define CCID_POLL_NUM (sizeof (ccid_poll)/sizeof (struct chx_poll_head *)) @@ -1697,9 +1703,10 @@ ccid_thread (void *arg) eventflag_init (&ccid.openpgp_comm); usb_lld_init (&dev, USB_INITIAL_FEATURE); - chopstx_claim_irq (&interrupt, INTR_REQ_USB); + chopstx_claim_irq (&usb_intr, INTR_REQ_USB); usb_event_handle (&dev); /* For old SYS < 3.0 */ + ackbtn_init (&ack_intr); eventflag_prepare_poll (&c->ccid_comm, &ccid_event_poll_desc); reset: @@ -1732,7 +1739,7 @@ ccid_thread (void *arg) chopstx_poll (timeout_p, CCID_POLL_NUM, ccid_poll); - if (interrupt.ready) + if (usb_intr.ready) { if (usb_event_handle (&dev) == 0) continue; @@ -1752,6 +1759,15 @@ ccid_thread (void *arg) goto reset; } + if (ack_intr.ready) + { + ackbtn_disable (); + chopstx_intr_done (&ack_intr); + led_blink (LED_FINISH_COMMAND); + if (c->ccid_state == CCID_STATE_CONFIRM_ACK) + goto exec_done; + } + timeout = USB_CCID_TIMEOUT; m = eventflag_get (&c->ccid_comm); @@ -1779,6 +1795,7 @@ ccid_thread (void *arg) else if (m == EV_EXEC_FINISHED) if (c->ccid_state == CCID_STATE_EXECUTE) { + exec_done: if (c->a->sw == GPG_THREAD_TERMINATED) { c->sw1sw2[0] = 0x90; @@ -1810,7 +1827,17 @@ ccid_thread (void *arg) } else { - DEBUG_INFO ("ERR07\r\n"); + DEBUG_INFO ("ERR05\r\n"); + } + else if (m == EV_EXEC_FINISHED_ACK) + if (c->ccid_state == CCID_STATE_EXECUTE) + { + ackbtn_enable (); + c->ccid_state = CCID_STATE_CONFIRM_ACK; + } + else + { + DEBUG_INFO ("ERR06\r\n"); } else if (m == EV_TX_FINISHED) { @@ -1842,7 +1869,7 @@ ccid_thread (void *arg) /* Loading reGNUal. */ while (bDeviceState != USB_DEVICE_STATE_UNCONNECTED) { - chopstx_intr_wait (&interrupt); + chopstx_intr_wait (&usb_intr); usb_event_handle (&dev); } diff --git a/src/usb_ctrl.c b/src/usb_ctrl.c index 7b33ac9..c494b97 100644 --- a/src/usb_ctrl.c +++ b/src/usb_ctrl.c @@ -1,7 +1,7 @@ /* * usb_ctrl.c - USB control pipe device specific code for Gnuk * - * Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016, 2017 + * Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016, 2017, 2018 * Free Software Initiative of Japan * Author: NIIBE Yutaka *