pinpad support change

This commit is contained in:
NIIBE Yutaka
2011-12-01 18:23:10 +09:00
parent 268c41634a
commit 1e94b262af
7 changed files with 138 additions and 168 deletions

View File

@@ -1,3 +1,21 @@
2011-12-01 Niibe Yutaka <gniibe@fsij.org>
* 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 <gniibe@fsij.org>
* src/openpgp.c (cmd_put_data) [PINPAD_SUPPORT]: Support pinpad

View File

@@ -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) */

View File

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

View File

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

View File

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

View File

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

View File

@@ -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. */
{