From 18b2b94acdc8ba7dc38e76ed3036563bbe5c90ec Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 17 Jan 2011 17:32:31 +0900 Subject: [PATCH] support PIN modification --- ChangeLog | 9 +++++ src/gnuk.h | 3 ++ src/openpgp.c | 91 ++++++++++++++++++++++++++++++++++++++++++--------- src/pin-cir.c | 3 +- 4 files changed, 89 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index b0e192d..2142adb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2011-01-17 NIIBE Yutaka + * src/gnuk.h (PIN_INPUT_CURRENT, PIN_INPUT_NEW) + (PIN_INPUT_CONFIRM): New. + + * src/pin-cir.c (pin_main): New argument MSG_CODE. + + * src/openpgp.c (get_pinpad_input): New. + (cmd_verify): Use get_pinpad_input. + (cmd_change_password): Added PINPAD_SUPPORT. + * src/openpgp.c (cmd_nop): Removed. * src/config.h.in: ifdef-out (not for ASSEMBLER). diff --git a/src/gnuk.h b/src/gnuk.h index 67cbf2f..ca4e5a2 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -319,5 +319,8 @@ extern void cir_ext_enable (void); extern uint8_t pin_input_buffer[MAX_PIN_CHARS]; extern uint8_t pin_input_len; +#define PIN_INPUT_CURRENT 1 +#define PIN_INPUT_NEW 2 +#define PIN_INPUT_CONFIRM 3 extern msg_t pin_main (void *arg); #endif diff --git a/src/openpgp.c b/src/openpgp.c index 1125aeb..bdc1c78 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -94,6 +94,27 @@ gpg_fini (void) ac_fini (); } +/* + * Invoke the thread PIN_MAIN, and let user input PIN string. + * Return length of the string. + * The string itself is in PIN_INPUT_BUFFER. + */ +static int +get_pinpad_input (int msg_code) +{ + Thread *t; + + t = chThdCreateFromHeap (NULL, THD_WA_SIZE (128), + NORMALPRIO, pin_main, (void *)msg_code); + if (t == NULL) + return -1; + else + { + chThdWait (t); + return pin_input_len; + } +} + static void cmd_verify (void) { @@ -108,23 +129,16 @@ cmd_verify (void) #if defined(PINPAD_SUPPORT) if (cmd_APDU_size == 4) - /* Verify with pinpad */ + /* Verification with pinpad */ { - Thread *t; - - t = chThdCreateFromHeap (NULL, THD_WA_SIZE (128), - NORMALPRIO, pin_main, NULL); - if (t == NULL) + len = get_pinpad_input (PIN_INPUT_CURRENT); + if (len < 0) { GPG_ERROR (); return; } else - { - chThdWait (t); - pw = pin_input_buffer; - len = pin_input_len; - } + pw = pin_input_buffer; } else #endif @@ -220,8 +234,8 @@ cmd_change_password (void) uint8_t new_ks0[KEYSTRING_MD_SIZE+1]; uint8_t *new_ks = &new_ks0[1]; uint8_t p2 = cmd_APDU[3]; - int len = cmd_APDU[4]; - const uint8_t *pw = &cmd_APDU[5]; + int len; + const uint8_t *pw; const uint8_t *newpw; int pw_len, newpw_len; int who = p2 - 0x80; @@ -230,10 +244,55 @@ cmd_change_password (void) DEBUG_INFO ("Change PW\r\n"); DEBUG_BYTE (who); - if (len == 0) /* extended length */ +#if defined(PINPAD_SUPPORT) + if (cmd_APDU_size == 4) + /* Modification with pinpad */ { - len = (cmd_APDU[5]<<8) | cmd_APDU[6]; - pw += 2; + 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; + } + 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; + } } if (who == BY_USER) /* PW1 */ diff --git a/src/pin-cir.c b/src/pin-cir.c index 86fe175..f8936a1 100644 --- a/src/pin-cir.c +++ b/src/pin-cir.c @@ -240,8 +240,9 @@ msg_t pin_main (void *arg) { uint8_t s = 0; + int msg_code = (int)arg; - (void)arg; + (void)msg_code; pin_thread = chThdSelf (); #if defined(DEBUG_CIR)