diff --git a/ChangeLog b/ChangeLog index 04800c6..9e57599 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2011-12-01 Niibe Yutaka + + * src/gnuk.h (EV_PINPAD_INPUT_DONE, EV_NOP, EV_CMD_AVAILABLE) + (EV_VERIFY_CMD_AVAILABLE, EV_MODIFY_CMD_AVAILABLE): New. + * src/usb-icc.c (icc_power_off, icc_handle_data): Use EV_NOP, + EV_CMD_AVAILABLE, EV_VERIFY_CMD_AVAILABLE, and EV_MODIFY_CMD_AVAILABLE. + * src/pin-cir.c (cir_timer_interrupt): Use EV_PINPAD_INPUT_DONE. + * src/pin-dial.c (dial_sw_interrupt, pinpad_getline): Ditto. + (EV_SW_PUSH): Remove. + + * src/openpgp.h (GPG_FUNCTION_NOT_SUPPORTED): New. + (GPG_CONDITION_NOT_SATISFIED): New. + * src/openpgp.c (cmd_change_password): Use GPG_FUNCTION_NOT_SUPPORTED. + + * src/openpgp.c (cmd_verify, cmd_change_password) + (cmd_reset_user_password, cmd_put_data): Remove pinpad handling... + (GPGthread): ... and implement pinpad handling here. + 2011-11-29 Niibe Yutaka * src/openpgp.c (cmd_put_data) [PINPAD_SUPPORT]: Support pinpad diff --git a/src/gnuk.h b/src/gnuk.h index 994e789..2df1def 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -24,6 +24,13 @@ extern void *memmove(void *dest, const void *src, size_t n); #define EV_EXEC_FINISHED ((eventmask_t)2) /* GPG Execution finished */ +/* GPG thread */ +#define EV_PINPAD_INPUT_DONE ((eventmask_t)1) +#define EV_NOP ((eventmask_t)2) +#define EV_CMD_AVAILABLE ((eventmask_t)4) +#define EV_VERIFY_CMD_AVAILABLE ((eventmask_t)8) +#define EV_MODIFY_CMD_AVAILABLE ((eventmask_t)16) + /* maximum cmd apdu data is key import 22+4+128+128 (proc_key_import) */ #define MAX_CMD_APDU_SIZE (7+282) /* header + data */ /* maximum res apdu data is public key 5+9+256+2 (gpg_do_public_key) */ diff --git a/src/openpgp.c b/src/openpgp.c index 646f9be..19377d7 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -125,32 +125,14 @@ cmd_verify (void) DEBUG_INFO (" - VERIFY\r\n"); DEBUG_BYTE (p2); -#if defined(PINPAD_SUPPORT) - if (cmd_APDU_size == 4) - /* Verification with pinpad */ + len = cmd_APDU[4]; + if (len == 0) /* extended length */ { - len = get_pinpad_input (PIN_INPUT_CURRENT); - if (len < 0) - { - GPG_ERROR (); - return; - } - - pw = pin_input_buffer; - } - else -#endif - { - len = cmd_APDU[4]; - if (len == 0) /* extended length */ - { - len = (cmd_APDU[5]<<8) | cmd_APDU[6]; - data_start = 7; - } - - pw = &cmd_APDU[data_start]; + len = (cmd_APDU[5]<<8) | cmd_APDU[6]; + data_start = 7; } + pw = &cmd_APDU[data_start]; if (p2 == 0x81) r = verify_pso_cds (pw, len); @@ -231,6 +213,7 @@ cmd_change_password (void) uint8_t old_ks[KEYSTRING_MD_SIZE]; uint8_t new_ks0[KEYSTRING_MD_SIZE+1]; uint8_t *new_ks = &new_ks0[1]; + uint8_t p1 = cmd_APDU[2]; /* 0: change (old+new), 1: exchange (new) */ uint8_t p2 = cmd_APDU[3]; int len; const uint8_t *pw; @@ -242,55 +225,18 @@ cmd_change_password (void) DEBUG_INFO ("Change PW\r\n"); DEBUG_BYTE (who); -#if defined(PINPAD_SUPPORT) - if (cmd_APDU_size == 4) - /* Modification with pinpad */ + len = cmd_APDU[4]; + pw = &cmd_APDU[5]; + if (len == 0) /* extended length */ { - pw_len = get_pinpad_input (PIN_INPUT_CURRENT); - if (pw_len < 0) - { - GPG_ERROR (); - return; - } - - pw = &cmd_APDU[5]; - memcpy (&cmd_APDU[5], pin_input_buffer, pw_len); - newpw = pw + pw_len; - - newpw_len = get_pinpad_input (PIN_INPUT_NEW); - if (newpw_len < 0) - { - GPG_ERROR (); - return; - } - - memcpy (&cmd_APDU[5]+pw_len, pin_input_buffer, newpw_len); - - len = get_pinpad_input (PIN_INPUT_CONFIRM); - if (len < 0) - { - GPG_ERROR (); - return; - } - - if (len != newpw_len || memcmp (newpw, pin_input_buffer, len) != 0) - { - GPG_SECURITY_FAILURE (); - return; - } - - len = cmd_APDU[4] = pw_len + newpw_len; + len = (cmd_APDU[5]<<8) | cmd_APDU[6]; + pw += 2; } - else -#endif + + if (p1 != 0) { - len = cmd_APDU[4]; - pw = &cmd_APDU[5]; - if (len == 0) /* extended length */ - { - len = (cmd_APDU[5]<<8) | cmd_APDU[6]; - pw += 2; - } + GPG_FUNCTION_NOT_SUPPORTED(); + return; } if (who == BY_USER) /* PW1 */ @@ -395,60 +341,12 @@ cmd_reset_user_password (void) DEBUG_INFO ("Reset PW1\r\n"); DEBUG_BYTE (p1); -#if defined(PINPAD_SUPPORT) - if (cmd_APDU_size == 4) - /* Modification with pinpad */ + len = cmd_APDU[4]; + pw = &cmd_APDU[5]; + if (len == 0) /* extended length */ { - if (p1 == 0x00) /* by User with Reseting Code */ - { - pw_len = get_pinpad_input (PIN_INPUT_CURRENT); - if (pw_len < 0) - { - GPG_ERROR (); - return; - } - - memcpy (&cmd_APDU[5], pin_input_buffer, pw_len); - } - else - pw_len = 0; - - pw = &cmd_APDU[5]; - newpw = pw + pw_len; - newpw_len = get_pinpad_input (PIN_INPUT_NEW); - if (newpw_len < 0) - { - GPG_ERROR (); - return; - } - - memcpy (&cmd_APDU[5]+pw_len, pin_input_buffer, newpw_len); - - len = get_pinpad_input (PIN_INPUT_CONFIRM); - if (len < 0) - { - GPG_ERROR (); - return; - } - - if (len != newpw_len || memcmp (newpw, pin_input_buffer, len) != 0) - { - GPG_SECURITY_FAILURE (); - return; - } - - len = cmd_APDU[4] = pw_len + newpw_len; - } - else -#endif - { - len = cmd_APDU[4]; - pw = &cmd_APDU[5]; - if (len == 0) /* extended length */ - { - len = (cmd_APDU[5]<<8) | cmd_APDU[6]; - pw += 2; - } + len = (cmd_APDU[5]<<8) | cmd_APDU[6]; + pw += 2; } if (p1 == 0x00) /* by User with Reseting Code */ @@ -574,42 +472,12 @@ cmd_put_data (void) tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]); data = &cmd_APDU[5]; -#if defined(PINPAD_SUPPORT) - if (cmd_APDU_size == 4) /* For 0xD3: reset code */ + len = cmd_APDU_size - 5; + if (len >= 256) + /* extended Lc */ { - len = get_pinpad_input (PIN_INPUT_NEW); - if (len < 0) - { - GPG_ERROR (); - return; - } - - cmd_APDU[4] = len; - memcpy (data, pin_input_buffer, len); - - len = get_pinpad_input (PIN_INPUT_CONFIRM); - if (len < 0) - { - GPG_ERROR (); - return; - } - - if (len != cmd_APDU[4] || memcmp (data, pin_input_buffer, len) !=0) - { - GPG_SECURITY_FAILURE (); - return; - } - } - else -#endif - { - len = cmd_APDU_size - 5; - if (len >= 256) - /* extended Lc */ - { - data += 2; - len -= 2; - } + data += 2; + len -= 2; } gpg_do_put_data (tag, data, len); @@ -1057,15 +925,91 @@ GPGthread (void *arg) while (!chThdShouldTerminate ()) { - chEvtWaitOne (ALL_EVENTS); + eventmask_t m = chEvtWaitOne (ALL_EVENTS); +#if defined(PINPAD_SUPPORT) + int len, pw_len, newpw_len; +#endif DEBUG_INFO ("GPG!: "); - res_APDU_pointer = NULL; /* default */ + res_APDU_pointer = NULL; + + if (m == EV_VERIFY_CMD_AVAILABLE) + { +#if defined(PINPAD_SUPPORT) + if (cmd_APDU[1] != INS_VERIFY) + { + GPG_CONDITION_NOT_SATISFIED (); + goto done; + } + + pw_len = get_pinpad_input (PIN_INPUT_CURRENT); + if (pw_len < 0) + { + GPG_ERROR (); + goto done; + } + memcpy (&cmd_APDU[5], pin_input_buffer, pw_len); + cmd_APDU[4] = pw_len; + icc_data_size = 5 + pw_len; +#else + GPG_ERROR (); + goto done; +#endif + } + else if (m == EV_MODIFY_CMD_AVAILABLE) + { +#if defined(PINPAD_SUPPORT) + if (cmd_APDU[1] != INS_CHANGE_REFERENCE_DATA) + { + GPG_CONDITION_NOT_SATISFIED (); + goto done; + } + + pw_len = get_pinpad_input (PIN_INPUT_CURRENT); + if (pw_len < 0) + { + GPG_ERROR (); + goto done; + } + memcpy (&cmd_APDU[5], pin_input_buffer, pw_len); + + newpw_len = get_pinpad_input (PIN_INPUT_NEW); + if (newpw_len < 0) + { + GPG_ERROR (); + goto done; + } + memcpy (&cmd_APDU[5]+pw_len, pin_input_buffer, newpw_len); + + len = get_pinpad_input (PIN_INPUT_CONFIRM); + if (len < 0) + { + GPG_ERROR (); + goto done; + } + + if (len != newpw_len + || memcmp (&cmd_APDU[5]+pw_len, pin_input_buffer, len) != 0) + { + GPG_SECURITY_FAILURE (); + goto done; + } + + len = cmd_APDU[4] = pw_len + newpw_len; + icc_data_size = 5 + len; +#else + GPG_ERROR (); + goto done; +#endif + } + else if (m == EV_NOP) + continue; if (icc_data_size != 0) { process_command_apdu (); + done: chEvtSignal (icc_thread, EV_EXEC_FINISHED); } } diff --git a/src/openpgp.h b/src/openpgp.h index 0d039c9..8cd3f8c 100644 --- a/src/openpgp.h +++ b/src/openpgp.h @@ -1,7 +1,9 @@ #define GPG_MEMORY_FAILURE() set_res_apdu (0x65, 0x81) #define GPG_SECURITY_FAILURE() set_res_apdu (0x69, 0x82) #define GPG_SECURITY_AUTH_BLOCKED() set_res_apdu (0x69, 0x83) +#define GPG_CONDITION_NOT_SATISFIED() set_res_apdu (0x69, 0x85) #define GPG_COMMAND_NOT_ALLOWED() set_res_apdu (0x69, 0x86) +#define GPG_FUNCTION_NOT_SUPPORTED() set_res_apdu (0x6a, 0x81) #define GPG_NO_FILE() set_res_apdu (0x6a, 0x82) #define GPG_NO_RECORD() set_res_apdu (0x6a, 0x88) #define GPG_BAD_P0_P1() set_res_apdu (0x6b, 0x00) diff --git a/src/pin-cir.c b/src/pin-cir.c index 7093e6a..4bf1052 100644 --- a/src/pin-cir.c +++ b/src/pin-cir.c @@ -910,7 +910,7 @@ cir_timer_interrupt (void) cir_input_last = now; /* Notify thread */ if (pin_thread) - chEvtSignalI (pin_thread, (eventmask_t)1); + chEvtSignalI (pin_thread, EV_PINPAD_INPUT_DONE); } #if defined(DEBUG_CIR) diff --git a/src/pin-dial.c b/src/pin-dial.c index 67758bc..5fd471e 100644 --- a/src/pin-dial.c +++ b/src/pin-dial.c @@ -117,13 +117,12 @@ blink_dp (void) } static Thread *pin_thread; -#define EV_SW_PUSH (eventmask_t)1 void dial_sw_interrupt (void) { dial_sw_disable (); - chEvtSignalI (pin_thread, EV_SW_PUSH); + chEvtSignalI (pin_thread, EV_PINPAD_INPUT_DONE); palClearPad (IOPORT1, GPIOA_LED2); } @@ -157,7 +156,7 @@ pinpad_getline (int msg_code, systime_t timeout) dial_sw_enable (); m = chEvtWaitOneTimeout (ALL_EVENTS, LED_DISP_BLINK_INTERVAL0); - if (m == EV_SW_PUSH || sw_push_count) + if (m == EV_PINPAD_INPUT_DONE || sw_push_count) { if (palReadPad (IOPORT2, GPIOB_BUTTON) == 0) sw_push_count++; diff --git a/src/usb-icc.c b/src/usb-icc.c index d526513..156d19a 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -374,7 +374,7 @@ icc_power_off (void) if (gpg_thread) { chThdTerminate (gpg_thread); - chEvtSignal (gpg_thread, (eventmask_t)1); + chEvtSignal (gpg_thread, EV_NOP); chThdWait (gpg_thread); gpg_thread = NULL; } @@ -497,7 +497,7 @@ icc_handle_data (void) { if (icc_header->param == 0) { /* Give this message to GPG thread */ - chEvtSignal (gpg_thread, (eventmask_t)1); + chEvtSignal (gpg_thread, EV_CMD_AVAILABLE); next_state = ICC_STATE_EXECUTE; } else if (icc_header->param == 1) @@ -524,7 +524,7 @@ icc_handle_data (void) cmd_APDU[2] = icc_buffer[27]; cmd_APDU[3] = icc_buffer[28]; icc_data_size = 4; - chEvtSignal (gpg_thread, (eventmask_t)1); + chEvtSignal (gpg_thread, EV_VERIFY_CMD_AVAILABLE); next_state = ICC_STATE_EXECUTE; } else if (icc_buffer[10] == 0x01) /* PIN Modification */ @@ -540,7 +540,7 @@ icc_handle_data (void) cmd_APDU[2] = icc_buffer[29 + num_msgs]; cmd_APDU[3] = icc_buffer[30 + num_msgs]; icc_data_size = 4; - chEvtSignal (gpg_thread, (eventmask_t)1); + chEvtSignal (gpg_thread, EV_MODIFY_CMD_AVAILABLE); next_state = ICC_STATE_EXECUTE; } else @@ -572,7 +572,7 @@ icc_handle_data (void) icc_data_size = icc_next_p - icc_buffer - ICC_MSG_HEADER_SIZE; icc_chain_p = NULL; next_state = ICC_STATE_EXECUTE; - chEvtSignal (gpg_thread, (eventmask_t)1); + chEvtSignal (gpg_thread, EV_CMD_AVAILABLE); } else /* icc_header->param == 3 is not supported. */ {