Compare commits

...

16 Commits

Author SHA1 Message Date
NIIBE Yutaka
f92ee76db5 fixes two bugs 2012-01-19 14:23:01 +09:00
NIIBE Yutaka
87e4fd50c1 New API between gpg and ccid layer 2012-01-18 18:59:16 +09:00
NIIBE Yutaka
cbb2c6aab5 clean up USB API 2 2012-01-16 13:24:31 +09:00
NIIBE Yutaka
00541d7627 clean up USB API 2012-01-16 12:17:45 +09:00
NIIBE Yutaka
27277e56ee update pinpadtest.py 2012-01-12 10:39:16 +09:00
NIIBE Yutaka
4ee4417fb5 fix adding semicolon 2012-01-10 16:47:48 +09:00
NIIBE Yutaka
11351c8cae pinmodify is OK for unblock and put resetcode 2012-01-10 16:02:53 +09:00
NIIBE Yutaka
6abac73354 add an entry for NEWS 2012-01-05 17:04:00 +09:00
NIIBE Yutaka
41537cc827 check DF name on SELECT command 2012-01-05 15:14:35 +09:00
NIIBE Yutaka
a4e0e67340 pinpadtest.py: name change 2012-01-05 10:15:00 +09:00
NIIBE Yutaka
58f8470446 pinpad-test.py: comment change 2012-01-05 10:13:42 +09:00
NIIBE Yutaka
885e1c4ecb pinpad-test.py: add comment 2012-01-05 10:12:24 +09:00
NIIBE Yutaka
2c111d0b20 add result for pinpad-test 2012-01-04 17:33:34 +09:00
NIIBE Yutaka
35a62354ae pinpad-test.py: add --pinmin, --unblock2, and --put2 2012-01-04 11:57:19 +09:00
NIIBE Yutaka
18f3e72c32 fix pinpad-test.py for --add 2012-01-04 09:32:41 +09:00
NIIBE Yutaka
121df70044 fix long standing bug of RxCount setting for buffer bound (was bug in STmicro's software) 2011-12-28 22:16:14 +09:00
17 changed files with 687 additions and 329 deletions

View File

@@ -1,5 +1,85 @@
2012-01-19 Niibe Yutaka <gniibe@fsij.org>
* src/usb-icc.c (icc_handle_data): Handle the case when it only
sends 0x90 and 0x00 correctly.
* src/openpgp-do.c (gpg_do_get_data): Fix res_apdu_data_len.
2012-01-18 Niibe Yutaka <gniibe@fsij.org>
Clean up API between application layer and CCID layer.
* tool/gnuk_put_binary.py, gnuk_put_binary_libusb.py: Don't append
0x9000 at the data, any more.
* src/usb-icc.c (icc_data_size, icc_buffer, icc_seq): Make them
internal.
(res_APDU_size, res_APDU_pointer): Removed.
(icc_handle_data, USBthread): Follow new API of struct apdu.
* src/call-rsa.c (rsa_sign, rsa_decrypt): Likewise.
* src/openpgp.c (CLS, INS, P1, P2): New.
(set_res_apdu, cmd_verify, cmd_change_password)
(cmd_reset_user_password, cmd_put_data, cmd_pgp_gakp)
(cmd_read_binary, cmd_select_file, cmd_pso)
(cmd_internal_authenticate, cmd_update_binary, cmd_write_binary)
(process_command_apdu, GPGthread): Follow new API of struct apdu.
* src/openpgp-do.c (gpg_do_get_data, gpg_do_public_key): Follow
new API of struct apdu.
* src/gnuk.h (struct apdu, apdu): New.
(cmd_APDU, icc_data_size, cmd_APDU_size, icc_buffer): Removed.
(res_APDU, res_APDU_size): Use members of struct apdu.
2012-01-16 Niibe Yutaka <gniibe@fsij.org>
Adopt new USB API.
* src/usb_msc.c (usb_start_transmit): Use usb_lld_write.
(EP6_IN_Callback): Use usb_lld_tx_data_len and usb_lld_write.
(usb_start_receive): Use usb_lld_rx_enable.
(EP7_OUT_Callback): Use usb_lld_rx_data_len, usb_lld_rxcpy
and usb_lld_rx_enable
(msc_handle_command): Use usb_lld_stall_rx and usb_lld_stall_tx.
* src/usb_lld.h (usb_lld_stall_tx, usb_lld_stall_rx)
(usb_lld_tx_data_len): New.
* src/main.c (STDOUTthread): Use usb_lld_write.
* src/usb-icc.c (EP1_IN_Callback, icc_error, icc_power_on)
(icc_send_status, icc_send_data_block, icc_send_params): Use
usb_lld_write (was: USB_SIL_Write).
(EP2_OUT_Callback): Use usb_lld_rx_data_len, usb_lld_rxcpy,
and usb_lld_rx_enable (was: USB_SIL_Read and SetEPRxValid).
(icc_prepare_receive): Use usb_lld_rx_enable.
* src/stmusb.mk (STMUSBSRC): Dont' include usb_sil.c.
* src/usb_lld.h (usb_lld_txcpy, usb_lld_tx_enable)
(usb_lld_write, usb_lld_rx_enable, usb_lld_rx_data_len)
(usb_lld_rxcpy): New.
* src/usb_prop.c (SetEPRxCount_allocated_size): Fix the
implementation. (ST's SetEPRxCount is actually meant to
setup allocated size, which is confusing).
(gnuk_device_init): Don't call USB_SIL_Init.
2012-01-10 Niibe Yutaka <gniibe@fsij.org>
* src/openpgp.c (GPGthread): Allow INS_RESET_RETRY_COUNTER and
INS_PUT_DATA for pinentry targets.
2012-01-05 Niibe Yutaka <gniibe@fsij.org>
* src/openpgp.c (cmd_select_file): Check DF name.
* tool/pinpadtest.py: Rename from pinpad-test.py.
2011-12-28 Niibe Yutaka <gniibe@fsij.org>
* src/usb_prop.c (SetEPRxCount_allocated_size): New.
(gnuk_device_reset): Use SetEPRxCount_allocated_size.
* src/usb_msc.c (usb_start_receive): Don't set RxCount register
here.
* STM32_USB-FS-Device_Driver/src/usb_core.c (Standard_ClearFeature)
(Post0_Process): Don't need to set RxCount register.
* src/usb_prop.c (msc_lun_info) [PINPAD_DND_SUPPORT]: ifdef-out.
* src/usb-icc.c (EP2_OUT_Callback): Fix apdu size == 49 bug,

13
NEWS
View File

@@ -4,13 +4,18 @@ Gnuk NEWS - User visible changes
Released 2012-01-XX, by NIIBE Yutaka
** ISO 7816 SELECT command behavior is strict now
Old implementations do not check DF name for SELECT command.
This causes some trouble when Gnuk Token is identified as if it were
different card/token. Now, DF name of OpenPGP card is checked.
** USB CCID/ICCD low level bug is fixed
When the size of command APDU data is just 49, the lower level packet
size is 64. This is maximum size of BULK-OUT transfer packet, and
caused trouble in the past implementations. Example is setting url
(0x5f50) as: http://www.gniibe.org/adpu-string-size-is-just-49
This is because the past implementations expect ZLP (zero size
packet). Now, it has been fixed. You can use any size.
This is because the past implementations expect ZLP (zero length
packet). Now, it has been fixed. You can use any size of string.
** CERT.3 Data Object (0x7f21) is now optional
As there's no valid use case for this data object and it does not
@@ -22,8 +27,8 @@ configure time.
Now, user can cancel pin input by unmounting device before finishing
DnD.
** New tool: pinpad-test.py
The tool pinpad-test.py is PC/SC test tool for pinentry of pinpad with
** New tool: pinpadtest.py
The tool pinpadtest.py is PC/SC test tool for pinentry of pinpad with
OpenPGP card v2.

View File

@@ -308,7 +308,6 @@ RESULT Standard_ClearFeature(void)
if (Related_Endpoint == ENDP0)
{
/* After clear the STALL, enable the default endpoint receiver */
SetEPRxCount(Related_Endpoint, Device_Property.MaxPacketSize);
_SetEPRxStatus(Related_Endpoint, EP_RX_VALID);
}
else
@@ -1019,8 +1018,6 @@ uint8_t Post0_Process(void)
USB_OTG_EP *ep;
#endif /* STM32F10X_CL */
SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
if (pInformation->ControlState == STALLED)
{
vSetEPRxStatus(EP_RX_STALL);

View File

@@ -25,6 +25,7 @@
#include "config.h"
#include "ch.h"
#include "gnuk.h"
#include "openpgp.h"
#include "polarssl/config.h"
#include "polarssl/rsa.h"
@@ -84,10 +85,9 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
}
else
{
res_APDU[RSA_SIGNATURE_LENGTH] = 0x90;
res_APDU[RSA_SIGNATURE_LENGTH+1] = 0x00;
res_APDU_size = RSA_SIGNATURE_LENGTH + 2;
res_APDU_size = RSA_SIGNATURE_LENGTH;
DEBUG_INFO ("done.\r\n");
GPG_SUCCESS ();
return 0;
}
}
@@ -177,10 +177,9 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
}
else
{
res_APDU[output_len] = 0x90;
res_APDU[output_len+1] = 0x00;
res_APDU_size = output_len + 2;
res_APDU_size = output_len;
DEBUG_INFO ("done.\r\n");
GPG_SUCCESS ();
return 0;
}
}

View File

@@ -1,3 +1,17 @@
/*
* We declare some of libc functions here, because we will
* remove dependency on libc in future, possibly.
*/
extern size_t strlen (const char *s);
extern int strncmp(const char *s1, const char *s2, size_t n);
extern void *memcpy (void *dest, const void *src, size_t n);
extern void *memset (void *s, int c, size_t n);
extern int memcmp (const void *s1, const void *s2, size_t n);
extern void *memmove(void *dest, const void *src, size_t n);
/*
* Debug functions
*/
extern Thread *stdout_thread;
#define EV_TX_READY ((eventmask_t)1)
@@ -11,16 +25,26 @@ extern void put_binary (const char *s, int len);
extern void _write (const char *, int);
/*
* We declare some of libc functions here, because we will
* remove dependency on libc in future.
* Application layer <-> CCID layer data structure
*/
extern size_t strlen (const char *s);
extern int strncmp(const char *s1, const char *s2, size_t n);
extern void *memcpy (void *dest, const void *src, size_t n);
extern void *memset (void *s, int c, size_t n);
extern int memcmp (const void *s1, const void *s2, size_t n);
extern void *memmove(void *dest, const void *src, size_t n);
struct apdu {
uint8_t seq;
/* command APDU */
uint8_t *cmd_apdu_head; /* CLS INS P1 P2 [ internal Lc ] */
uint8_t *cmd_apdu_data;
uint16_t cmd_apdu_data_len; /* Nc, calculated by Lc field */
uint32_t expected_res_size; /* Ne, calculated by Le field */
/* response APDU */
uint16_t sw;
uint8_t *res_apdu_data;
uint16_t res_apdu_data_len;
};
extern struct apdu apdu;
#define EV_EXEC_FINISHED ((eventmask_t)2) /* GPG Execution finished */
@@ -38,12 +62,8 @@ extern void *memmove(void *dest, const void *src, size_t n);
#define ICC_MSG_HEADER_SIZE 10
#define cmd_APDU (&icc_buffer[ICC_MSG_HEADER_SIZE])
#define res_APDU (&icc_buffer[ICC_MSG_HEADER_SIZE])
extern int icc_data_size;
#define cmd_APDU_size icc_data_size
extern int res_APDU_size;
extern const uint8_t *res_APDU_pointer;
#define res_APDU apdu.res_apdu_data
#define res_APDU_size apdu.res_apdu_data_len
/* USB buffer size of LL (Low-level): size of single Bulk transaction */
#define USB_LL_BUF_SIZE 64
@@ -54,7 +74,6 @@ extern const uint8_t *res_APDU_pointer;
*/
#define USB_BUF_SIZE ((10 + 10 + MAX_CMD_APDU_SIZE + USB_LL_BUF_SIZE - 1) \
/ USB_LL_BUF_SIZE * USB_LL_BUF_SIZE)
extern uint8_t icc_buffer[USB_BUF_SIZE];
enum icc_state
{

View File

@@ -132,8 +132,7 @@ STDOUTthread (void *arg)
chEvtClear (EV_TX_READY);
USB_SIL_Write (EP3_IN, buffer_in, count_in);
SetEPTxValid (ENDP3);
usb_lld_write (ENDP3, buffer_in, count_in);
chEvtWaitOne (EV_TX_READY);
}

View File

@@ -417,10 +417,12 @@ do_kgtime_all (uint16_t tag, int with_tag)
}
const uint8_t openpgpcard_aid[] = {
0xd2, 0x76, 0x00, 0x01, 0x24, 0x01,
0x02, 0x00, /* Version 2.0 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* To be overwritten */
0xd2, 0x76, /* D: National, 276: DEU ISO 3166-1 */
0x00, 0x01, 0x24, /* Registered Application Provider Identifier */
0x01, /* Application: OpenPGPcard */
0x02, 0x00, /* Version 2.0 */
/* v. id */ /* serial number */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* To be overwritten */
};
static int
@@ -1248,16 +1250,16 @@ gpg_do_get_data (uint16_t tag, int with_tag)
#if defined(CERTDO_SUPPORT)
if (tag == GPG_DO_CH_CERTIFICATE)
{
res_APDU_pointer = &ch_certificate_start;
res_APDU_size = ((res_APDU_pointer[2] << 8) | res_APDU_pointer[3]);
if (res_APDU_size == 0xffff)
apdu.res_apdu_data = &ch_certificate_start;
apdu.res_apdu_data_len = ((apdu.res_apdu_data[2] << 8) | apdu.res_apdu_data[3]);
if (apdu.res_apdu_data_len == 0xffff)
{
res_APDU_pointer = NULL;
apdu.res_apdu_data_len = 0;
GPG_NO_RECORD ();
}
else
/* Add length of (tag+len) and status word (0x9000) at the end */
res_APDU_size += 4 + 2;
/* Add length of (tag+len) */
apdu.res_apdu_data_len += 4;
}
else
#endif
@@ -1276,9 +1278,8 @@ gpg_do_get_data (uint16_t tag, int with_tag)
GPG_SECURITY_FAILURE ();
else
{
*res_p++ = 0x90;
*res_p++ = 0x00;
res_APDU_size = res_p - res_APDU;
GPG_SUCCESS ();
}
}
else
@@ -1412,8 +1413,8 @@ gpg_do_public_key (uint8_t kk_byte)
*res_p++ = 0x01; *res_p++ = 0x00; *res_p++ = 0x01;
/* Success */
*res_p++ = 0x90; *res_p++ = 0x00;
res_APDU_size = res_p - res_APDU;
GPG_SUCCESS ();
}
DEBUG_INFO ("done.\r\n");

View File

@@ -29,6 +29,11 @@
#include "polarssl/config.h"
#include "polarssl/sha1.h"
#define CLS(a) a.cmd_apdu_head[0]
#define INS(a) a.cmd_apdu_head[1]
#define P1(a) a.cmd_apdu_head[2]
#define P2(a) a.cmd_apdu_head[3]
#define INS_VERIFY 0x20
#define INS_CHANGE_REFERENCE_DATA 0x24
#define INS_PSO 0x2a
@@ -64,9 +69,7 @@ select_file_TOP_result[] __attribute__ ((aligned (1))) = {
void
set_res_apdu (uint8_t sw1, uint8_t sw2)
{
res_APDU_size = 2;
res_APDU[0] = sw1;
res_APDU[1] = sw2;
apdu.sw = (sw1 << 8) | sw2;
}
#define FILE_NONE 0
@@ -117,22 +120,15 @@ static void
cmd_verify (void)
{
int len;
uint8_t p2 = cmd_APDU[3];
uint8_t p2 = P2 (apdu);
int r;
int data_start = 5;
const uint8_t *pw;
DEBUG_INFO (" - VERIFY\r\n");
DEBUG_BYTE (p2);
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 = apdu.cmd_apdu_data_len;
pw = apdu.cmd_apdu_data;
if (p2 == 0x81)
r = verify_pso_cds (pw, len);
@@ -213,8 +209,8 @@ 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];
uint8_t p1 = P1 (apdu); /* 0: change (old+new), 1: exchange (new) */
uint8_t p2 = P2 (apdu);
int len;
const uint8_t *pw;
const uint8_t *newpw;
@@ -225,13 +221,8 @@ cmd_change_password (void)
DEBUG_INFO ("Change PW\r\n");
DEBUG_BYTE (who);
len = cmd_APDU[4];
pw = &cmd_APDU[5];
if (len == 0) /* extended length */
{
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
pw += 2;
}
len = apdu.cmd_apdu_data_len;
pw = apdu.cmd_apdu_data;
if (p1 != 0)
{
@@ -329,7 +320,7 @@ cmd_change_password (void)
static void
cmd_reset_user_password (void)
{
uint8_t p1 = cmd_APDU[2];
uint8_t p1 = P1 (apdu);
int len;
const uint8_t *pw;
const uint8_t *newpw;
@@ -341,13 +332,8 @@ cmd_reset_user_password (void)
DEBUG_INFO ("Reset PW1\r\n");
DEBUG_BYTE (p1);
len = cmd_APDU[4];
pw = &cmd_APDU[5];
if (len == 0) /* extended length */
{
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
pw += 2;
}
len = apdu.cmd_apdu_data_len;
pw = apdu.cmd_apdu_data;
if (p1 == 0x00) /* by User with Reseting Code */
{
@@ -469,17 +455,9 @@ cmd_put_data (void)
if (file_selection != FILE_DF_OPENPGP)
GPG_NO_RECORD();
tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]);
data = &cmd_APDU[5];
len = cmd_APDU_size - 5;
if (len >= 256)
/* extended Lc */
{
data += 2;
len -= 2;
}
tag = ((P1 (apdu)<<8) | P2 (apdu));
len = apdu.cmd_apdu_data_len;
data = apdu.cmd_apdu_data;
gpg_do_put_data (tag, data, len);
}
@@ -487,16 +465,11 @@ static void
cmd_pgp_gakp (void)
{
DEBUG_INFO (" - Generate Asymmetric Key Pair\r\n");
DEBUG_BYTE (cmd_APDU[2]);
DEBUG_BYTE (P1 (apdu));
if (cmd_APDU[2] == 0x81)
if (P1 (apdu) == 0x81)
/* Get public key */
{
if (cmd_APDU[4] == 0)
gpg_do_public_key (cmd_APDU[7]);
else
gpg_do_public_key (cmd_APDU[5]);
}
gpg_do_public_key (apdu.cmd_apdu_data[0]);
else
{ /* Generate key pair */
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
@@ -514,7 +487,7 @@ cmd_read_binary (void)
if (file_selection == FILE_EF_SERIAL)
{
if (cmd_APDU[3] >= 6)
if (P2 (apdu) >= 6)
GPG_BAD_P0_P1 ();
else
{
@@ -529,16 +502,23 @@ cmd_read_binary (void)
static void
cmd_select_file (void)
{
if (cmd_APDU[2] == 4) /* Selection by DF name: it must be OpenPGP card */
if (P1 (apdu) == 4) /* Selection by DF name */
{
DEBUG_INFO (" - select DF by name\r\n");
/*
* P2 == 0, LC=6, name = D2 76 00 01 24 01
*/
/* name = D2 76 00 01 24 01 */
if (apdu.cmd_apdu_data_len != 6
|| memcmp (openpgpcard_aid, apdu.cmd_apdu_data, 6) != 0)
{
DEBUG_WORD (apdu.cmd_apdu_data_len);
DEBUG_BINARY (apdu.cmd_apdu_data, apdu.cmd_apdu_data_len);
GPG_NO_FILE ();
return;
}
file_selection = FILE_DF_OPENPGP;
if (cmd_APDU[3] == 0x0c) /* No FCI */
if ((P2 (apdu) & 0x0c) == 0x0c) /* No FCI */
GPG_SUCCESS ();
else
{
@@ -550,8 +530,8 @@ cmd_select_file (void)
res_APDU_size += 2;
}
}
else if (cmd_APDU[4] == 2
&& cmd_APDU[5] == 0x2f && cmd_APDU[6] == 0x02)
else if (apdu.cmd_apdu_data_len == 2
&& apdu.cmd_apdu_data[0] == 0x2f && apdu.cmd_apdu_data[1] == 0x02)
{
DEBUG_INFO (" - select 0x2f02 EF\r\n");
/*
@@ -560,11 +540,11 @@ cmd_select_file (void)
GPG_SUCCESS ();
file_selection = FILE_EF_SERIAL;
}
else if (cmd_APDU[4] == 2
&& cmd_APDU[5] == 0x3f && cmd_APDU[6] == 0x00)
else if (apdu.cmd_apdu_data_len == 2
&& apdu.cmd_apdu_data[0] == 0x3f && apdu.cmd_apdu_data[1] == 0x00)
{
DEBUG_INFO (" - select ROOT MF\r\n");
if (cmd_APDU[3] == 0x0c)
if (P2 (apdu) == 0x0c)
{
GPG_SUCCESS ();
}
@@ -572,12 +552,11 @@ cmd_select_file (void)
{
int len = sizeof (select_file_TOP_result);
res_APDU_size = 2 + len;
res_APDU_size = len;
memcpy (res_APDU, select_file_TOP_result, len);
res_APDU[2] = (data_objects_number_of_bytes & 0xff);
res_APDU[3] = (data_objects_number_of_bytes >> 8);
res_APDU[len] = 0x90;
res_APDU[len+1] = 0x00;
GPG_SUCCESS ();
}
file_selection = FILE_MF;
@@ -595,7 +574,7 @@ cmd_select_file (void)
static void
cmd_get_data (void)
{
uint16_t tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]);
uint16_t tag = ((P1 (apdu)<<8) | P2 (apdu));
DEBUG_INFO (" - Get Data\r\n");
@@ -608,21 +587,14 @@ cmd_get_data (void)
static void
cmd_pso (void)
{
int len = cmd_APDU[4];
int data_start = 5;
int len = apdu.cmd_apdu_data_len;
int r;
if (len == 0)
{
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
data_start = 7;
}
DEBUG_INFO (" - PSO: ");
DEBUG_WORD ((uint32_t)&r);
DEBUG_BINARY (cmd_APDU, cmd_APDU_size);
DEBUG_BINARY (apdu.cmd_apdu_data, apdu.cmd_apdu_data_len);
if (cmd_APDU[2] == 0x9e && cmd_APDU[3] == 0x9a)
if (P1 (apdu) == 0x9e && P2 (apdu) == 0x9a)
{
if (!ac_check_status (AC_PSO_CDS_AUTHORIZED))
{
@@ -631,24 +603,24 @@ cmd_pso (void)
return;
}
if (cmd_APDU_size != 7 + 34 + 2 /* MD5 */
/* Header (with Extended Lc)=7, size of digestInfo, and Le=2-byte */
&& cmd_APDU_size != 7 + 35 + 2 /* SHA1 / RIPEMD-160 */
&& cmd_APDU_size != 7 + 47 + 2 /* SHA224 */
&& cmd_APDU_size != 7 + 51 + 2 /* SHA256 */
&& cmd_APDU_size != 7 + 67 + 2 /* SHA384 */
&& cmd_APDU_size != 7 + 83 + 2) /* SHA512 */
/* Check size of digestInfo */
if (len != 34 /* MD5 */
&& len != 35 /* SHA1 / RIPEMD-160 */
&& len != 47 /* SHA224 */
&& len != 51 /* SHA256 */
&& len != 67 /* SHA384 */
&& len != 83) /* SHA512 */
{
DEBUG_INFO (" wrong length: ");
DEBUG_SHORT (cmd_APDU_size);
DEBUG_SHORT (len);
GPG_ERROR ();
}
else
{
DEBUG_SHORT (len); /* Should be cmd_APDU_size - 8 [- 1] */
DEBUG_SHORT (len);
DEBUG_BINARY (&kd[GPG_KEY_FOR_SIGNING], KEY_CONTENT_LEN);
r = rsa_sign (&cmd_APDU[data_start], res_APDU, len,
r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len,
&kd[GPG_KEY_FOR_SIGNING]);
if (r < 0)
{
@@ -660,7 +632,7 @@ cmd_pso (void)
gpg_increment_digital_signature_counter ();
}
}
else if (cmd_APDU[2] == 0x80 && cmd_APDU[3] == 0x86)
else if (P1 (apdu) == 0x80 && P2 (apdu) == 0x86)
{
DEBUG_SHORT (len);
DEBUG_BINARY (&kd[GPG_KEY_FOR_DECRYPTION], KEY_CONTENT_LEN);
@@ -673,9 +645,8 @@ cmd_pso (void)
}
/* Skip padding 0x00 */
data_start++;
len--;
r = rsa_decrypt (&cmd_APDU[data_start], res_APDU, len,
r = rsa_decrypt (apdu.cmd_apdu_data+1, res_APDU, len,
&kd[GPG_KEY_FOR_DECRYPTION]);
if (r < 0)
GPG_ERROR ();
@@ -683,9 +654,9 @@ cmd_pso (void)
else
{
DEBUG_INFO (" - ??");
DEBUG_BYTE (cmd_APDU[2]);
DEBUG_BYTE (P1 (apdu));
DEBUG_INFO (" - ??");
DEBUG_BYTE (cmd_APDU[3]);
DEBUG_BYTE (P2 (apdu));
GPG_ERROR ();
}
@@ -695,19 +666,12 @@ cmd_pso (void)
static void
cmd_internal_authenticate (void)
{
int len = cmd_APDU[4];
int data_start = 5;
int len = apdu.cmd_apdu_data_len;
int r;
if (len == 0)
{
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
data_start = 7;
}
DEBUG_INFO (" - INTERNAL AUTHENTICATE\r\n");
if (cmd_APDU[2] == 0x00 && cmd_APDU[3] == 0x00)
if (P1 (apdu) == 0x00 && P2 (apdu) == 0x00)
{
DEBUG_SHORT (len);
@@ -718,7 +682,7 @@ cmd_internal_authenticate (void)
return;
}
r = rsa_sign (&cmd_APDU[data_start], res_APDU, len,
r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len,
&kd[GPG_KEY_FOR_AUTHENTICATION]);
if (r < 0)
GPG_ERROR ();
@@ -726,9 +690,9 @@ cmd_internal_authenticate (void)
else
{
DEBUG_INFO (" - ??");
DEBUG_BYTE (cmd_APDU[2]);
DEBUG_BYTE (P1 (apdu));
DEBUG_INFO (" - ??");
DEBUG_BYTE (cmd_APDU[3]);
DEBUG_BYTE (P2 (apdu));
GPG_ERROR ();
}
@@ -739,17 +703,10 @@ cmd_internal_authenticate (void)
static void
cmd_update_binary (void)
{
int len = cmd_APDU[4];
int data_start = 5;
int len = apdu.cmd_apdu_data_len;
uint16_t offset;
int r;
if (len == 0)
{
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
data_start = 7;
}
DEBUG_INFO (" - UPDATE BINARY\r\n");
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
@@ -759,10 +716,10 @@ cmd_update_binary (void)
return;
}
if ((cmd_APDU[2] & 0x80))
if ((cmd_APDU[2] & 0x7f) <= FILEID_RANDOM)
if ((P1 (apdu) & 0x80))
if ((P1 (apdu) & 0x7f) <= FILEID_RANDOM)
{
file_selection = FILE_EF_CH_CERTIFICATE + (cmd_APDU[2] & 0x7f);
file_selection = FILE_EF_CH_CERTIFICATE + (P1 (apdu) & 0x7f);
r = flash_erase_binary (file_selection - FILE_EF_CH_CERTIFICATE);
if (r < 0)
{
@@ -787,14 +744,14 @@ cmd_update_binary (void)
return;
}
offset = (cmd_APDU[2] << 8) | cmd_APDU[3];
offset = (P1 (apdu) << 8) | P2 (apdu);
}
DEBUG_SHORT (len);
DEBUG_SHORT (offset);
r = flash_write_binary (file_selection - FILE_EF_CH_CERTIFICATE,
&cmd_APDU[data_start], len, offset);
apdu.cmd_apdu_data, len, offset);
if (r < 0)
{
DEBUG_INFO ("memory error.\r\n");
@@ -810,17 +767,10 @@ cmd_update_binary (void)
static void
cmd_write_binary (void)
{
int len = cmd_APDU[4];
int data_start = 5;
int len = apdu.cmd_apdu_data_len;
uint16_t offset;
int r;
if (len == 0)
{
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
data_start = 7;
}
DEBUG_INFO (" - WRITE BINARY\r\n");
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
@@ -830,10 +780,10 @@ cmd_write_binary (void)
return;
}
if ((cmd_APDU[2] & 0x80))
if ((cmd_APDU[2] & 0x7f) <= FILEID_SERIAL_NO)
if ((P1 (apdu) & 0x80))
if ((P1 (apdu) & 0x7f) <= FILEID_SERIAL_NO)
{
file_selection = FILE_EF_CH_CERTIFICATE + (cmd_APDU[2] & 0x7f);
file_selection = FILE_EF_CH_CERTIFICATE + (P1 (apdu) & 0x7f);
offset = 0;
}
else
@@ -851,14 +801,14 @@ cmd_write_binary (void)
return;
}
offset = (cmd_APDU[2] << 8) | cmd_APDU[3];
offset = (P1 (apdu) << 8) | P2 (apdu);
}
DEBUG_SHORT (len);
DEBUG_SHORT (offset);
r = flash_write_binary (file_selection - FILE_EF_CH_CERTIFICATE,
&cmd_APDU[data_start], len, offset);
apdu.cmd_apdu_data, len, offset);
if (r < 0)
{
DEBUG_INFO ("memory error.\r\n");
@@ -898,7 +848,7 @@ static void
process_command_apdu (void)
{
int i;
uint8_t cmd = cmd_APDU[1];
uint8_t cmd = INS (apdu);
for (i = 0; i < NUM_CMDS; i++)
if (cmds[i].command == cmd)
@@ -932,12 +882,10 @@ GPGthread (void *arg)
DEBUG_INFO ("GPG!: ");
res_APDU_pointer = NULL;
if (m == EV_VERIFY_CMD_AVAILABLE)
{
#if defined(PINPAD_SUPPORT)
if (cmd_APDU[1] != INS_VERIFY)
if (INS (apdu) != INS_VERIFY)
{
GPG_CONDITION_NOT_SATISFIED ();
goto done;
@@ -949,9 +897,8 @@ GPGthread (void *arg)
GPG_ERROR ();
goto done;
}
memcpy (&cmd_APDU[5], pin_input_buffer, pw_len);
cmd_APDU[4] = pw_len;
icc_data_size = 5 + pw_len;
memcpy (apdu.cmd_apdu_data, pin_input_buffer, pw_len);
apdu.cmd_apdu_data_len = pw_len;
#else
GPG_ERROR ();
goto done;
@@ -960,10 +907,12 @@ GPGthread (void *arg)
else if (m == EV_MODIFY_CMD_AVAILABLE)
{
#if defined(PINPAD_SUPPORT)
uint8_t bConfirmPIN = cmd_APDU[4];
uint8_t *p = &cmd_APDU[5];
uint8_t bConfirmPIN = apdu.cmd_apdu_data[5];
uint8_t *p = apdu.cmd_apdu_data;
if (cmd_APDU[1] != INS_CHANGE_REFERENCE_DATA)
if (INS (apdu) != INS_CHANGE_REFERENCE_DATA
&& INS (apdu) != INS_RESET_RETRY_COUNTER
&& INS (apdu) != INS_PUT_DATA)
{
GPG_CONDITION_NOT_SATISFIED ();
goto done;
@@ -1007,8 +956,7 @@ GPGthread (void *arg)
}
}
len = cmd_APDU[4] = pw_len + newpw_len;
icc_data_size = 5 + len;
apdu.cmd_apdu_data_len = pw_len + newpw_len;
#else
GPG_ERROR ();
goto done;
@@ -1017,12 +965,9 @@ GPGthread (void *arg)
else if (m == EV_NOP)
continue;
if (icc_data_size != 0)
{
process_command_apdu ();
done:
chEvtSignal (icc_thread, EV_EXEC_FINISHED);
}
process_command_apdu ();
done:
chEvtSignal (icc_thread, EV_EXEC_FINISHED);
}
gpg_fini ();

View File

@@ -1,7 +1,7 @@
STMUSBDIR = ../STM32_USB-FS-Device_Driver
STMUSBSRCDIR = $(STMUSBDIR)/src
STMUSBINCDIR = $(STMUSBDIR)/inc
STMUSBSRC= $(STMUSBSRCDIR)/usb_sil.c \
STMUSBSRC= \
$(STMUSBSRCDIR)/usb_init.c $(STMUSBSRCDIR)/usb_int.c \
$(STMUSBSRCDIR)/usb_mem.c $(STMUSBSRCDIR)/usb_core.c \
$(STMUSBSRCDIR)/usb_regs.c

View File

@@ -1,7 +1,7 @@
/*
* usb-icc.c -- USB CCID/ICCD protocol handling
*
* Copyright (C) 2010, 2011 Free Software Initiative of Japan
* Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -29,6 +29,9 @@
#include "usb_mem.h"
#include "hw_config.h"
#include "usb_istr.h"
#include "usb_lld.h"
struct apdu apdu;
#define ICC_SET_PARAMS 0x61 /* non-ICCD command */
#define ICC_POWER_ON 0x62
@@ -73,7 +76,7 @@ struct icc_header {
uint16_t param;
} __attribute__((packed));
int icc_data_size;
static int icc_data_size;
/*
* USB-ICC communication could be considered "half duplex".
@@ -93,8 +96,8 @@ int icc_data_size;
* The buffer will be filled by multiple RX transactions (Bulk-OUT)
* or will be used for multiple TX transactions (Bulk-IN)
*/
uint8_t icc_buffer[USB_BUF_SIZE];
uint8_t icc_seq;
static uint8_t icc_buffer[USB_BUF_SIZE];
static uint8_t icc_seq;
/*
* Pointer to ICC_BUFFER
@@ -131,8 +134,7 @@ EP1_IN_Callback (void)
{
/* Send the last 0-DATA transcation of Bulk-IN in the transactions */
icc_next_p = NULL;
USB_SIL_Write (EP1_IN, icc_buffer, 0);
SetEPTxValid (ENDP1);
usb_lld_write (ENDP1, icc_buffer, 0);
}
else
{
@@ -146,8 +148,7 @@ EP1_IN_Callback (void)
tx_size = &icc_buffer[icc_tx_size] - p;
}
USB_SIL_Write (EP1_IN, p, tx_size);
SetEPTxValid (ENDP1);
usb_lld_write (ENDP1, p, tx_size);
}
}
@@ -159,7 +160,7 @@ icc_prepare_receive (int chain)
else
icc_next_p = icc_buffer;
SetEPRxValid (ENDP2);
usb_lld_rx_enable (ENDP2);
}
/*
@@ -173,10 +174,11 @@ EP2_OUT_Callback (void)
int data_len_so_far;
int data_len;
len = USB_SIL_Read (EP2_OUT, icc_next_p);
len = usb_lld_rx_data_len (ENDP2);
usb_lld_rxcpy (icc_next_p, ENDP2, 0, len);
if (len == 0)
{ /* Just ignore Zero Length Packet (ZLP), if any */
SetEPRxValid (ENDP2);
usb_lld_rx_enable (ENDP2);
return;
}
@@ -194,7 +196,7 @@ EP2_OUT_Callback (void)
&& data_len != data_len_so_far)
/* The sequence of transactions continues */
{
SetEPRxValid (ENDP2);
usb_lld_rx_enable (ENDP2);
if ((icc_next_p - icc_buffer) >= USB_BUF_SIZE)
/* No room to receive any more */
{
@@ -298,8 +300,7 @@ icc_error (int offset)
icc_next_p = NULL; /* This is a single transaction Bulk-IN */
icc_tx_size = ICC_MSG_HEADER_SIZE;
USB_SIL_Write (EP1_IN, icc_reply, icc_tx_size);
SetEPTxValid (ENDP1);
usb_lld_write (ENDP1, icc_reply, icc_tx_size);
}
static Thread *gpg_thread;
@@ -332,8 +333,7 @@ icc_power_on (void)
icc_next_p = NULL; /* This is a single transaction Bulk-IN */
icc_tx_size = ICC_MSG_HEADER_SIZE + size_atr;
USB_SIL_Write (EP1_IN, icc_buffer, icc_tx_size);
SetEPTxValid (ENDP1);
usb_lld_write (ENDP1, icc_buffer, icc_tx_size);
DEBUG_INFO ("ON\r\n");
return ICC_STATE_WAIT;
@@ -367,8 +367,7 @@ icc_send_status (void)
icc_next_p = NULL; /* This is a single transaction Bulk-IN */
icc_tx_size = ICC_MSG_HEADER_SIZE;
USB_SIL_Write (EP1_IN, icc_reply, icc_tx_size);
SetEPTxValid (ENDP1);
usb_lld_write (ENDP1, icc_reply, icc_tx_size);
#ifdef DEBUG_MORE
DEBUG_INFO ("St\r\n");
@@ -394,9 +393,6 @@ icc_power_off (void)
return ICC_STATE_START;
}
int res_APDU_size;
const uint8_t *res_APDU_pointer;
static void
icc_send_data_block (int len, uint8_t status, uint8_t chain)
{
@@ -428,8 +424,7 @@ icc_send_data_block (int len, uint8_t status, uint8_t chain)
else
icc_next_p = p + USB_LL_BUF_SIZE;
USB_SIL_Write (EP1_IN, p, tx_size);
SetEPTxValid (ENDP1);
usb_lld_write (ENDP1, p, tx_size);
#ifdef DEBUG_MORE
DEBUG_INFO ("DATA\r\n");
#endif
@@ -458,8 +453,7 @@ icc_send_params (void)
icc_next_p = NULL; /* This is a single transaction Bulk-IN */
icc_tx_size = ICC_MSG_HEADER_SIZE + 7;
USB_SIL_Write (EP1_IN, icc_buffer, icc_tx_size);
SetEPTxValid (ENDP1);
usb_lld_write (ENDP1, icc_buffer, icc_tx_size);
#ifdef DEBUG_MORE
DEBUG_INFO ("DATA\r\n");
#endif
@@ -506,6 +500,87 @@ icc_handle_data (void)
{
if (icc_header->param == 0)
{ /* Give this message to GPG thread */
run_gpg_thread:
apdu.seq = icc_seq;
apdu.cmd_apdu_head = &icc_buffer[ICC_MSG_HEADER_SIZE];
apdu.sw = 0x9000;
apdu.res_apdu_data_len = 0;
apdu.res_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE];
if (icc_data_size < 4)
{
icc_error (ICC_MSG_HEADER_SIZE + icc_data_size);
next_state = ICC_STATE_WAIT;
break;
}
else if (icc_data_size == 4)
{ /* No Lc and No Le */
apdu.cmd_apdu_data = NULL;
apdu.cmd_apdu_data_len = 0;
apdu.expected_res_size = 0;
apdu.cmd_apdu_head[4] = 0;
}
else if (icc_data_size == 5)
{ /* No Lc but Le */
apdu.cmd_apdu_data = NULL;
apdu.cmd_apdu_data_len = 0;
apdu.expected_res_size = apdu.cmd_apdu_head[4];
if (apdu.expected_res_size == 0)
apdu.expected_res_size = 256;
apdu.cmd_apdu_head[4] = 0;
}
else if (apdu.cmd_apdu_head[4] == 0)
{ /* extended Lc or extended Le */
apdu.cmd_apdu_data = apdu.cmd_apdu_head + 7;
apdu.cmd_apdu_data_len
= (apdu.cmd_apdu_head[5] << 8) + apdu.cmd_apdu_head[6];
if (icc_data_size == 7)
{ /* No Lc but extended Le */
apdu.expected_res_size = apdu.cmd_apdu_data_len;
apdu.cmd_apdu_data_len = 0;
}
else if (icc_data_size == apdu.cmd_apdu_data_len + 7)
apdu.expected_res_size = 0;
else if (icc_data_size == apdu.cmd_apdu_data_len + 7 + 2)
{
apdu.expected_res_size
= (icc_buffer[ICC_MSG_HEADER_SIZE + 7
+ apdu.cmd_apdu_data_len] << 8)
| icc_buffer[ICC_MSG_HEADER_SIZE + 7
+ apdu.cmd_apdu_data_len + 1];
if (apdu.expected_res_size == 0)
apdu.expected_res_size = 65536;
}
else
{
icc_error (ICC_MSG_HEADER_SIZE + 5);
next_state = ICC_STATE_WAIT;
break;
}
}
else /* short Lc */
{
apdu.cmd_apdu_data = apdu.cmd_apdu_head + 5;
apdu.cmd_apdu_data_len = apdu.cmd_apdu_head[4];
if (icc_data_size == apdu.cmd_apdu_data_len + 5)
apdu.expected_res_size = 0;
else if (icc_data_size == apdu.cmd_apdu_data_len + 5 + 1)
{
apdu.expected_res_size
= icc_buffer[ICC_MSG_HEADER_SIZE + 5
+ apdu.cmd_apdu_data_len];
if (apdu.expected_res_size == 0)
apdu.expected_res_size = 256;
}
else
{
icc_error (ICC_MSG_HEADER_SIZE + 5);
next_state = ICC_STATE_WAIT;
break;
}
}
chEvtSignal (gpg_thread, EV_CMD_AVAILABLE);
next_state = ICC_STATE_EXECUTE;
}
@@ -528,19 +603,28 @@ icc_handle_data (void)
{
if (icc_buffer[10] == 0x00) /* PIN verification */
{
cmd_APDU[0] = icc_buffer[25];
cmd_APDU[1] = icc_buffer[26];
cmd_APDU[2] = icc_buffer[27];
cmd_APDU[3] = icc_buffer[28];
icc_data_size = 4;
cmd_APDU[4] = 0; /* bConfirmPIN */
cmd_APDU[5] = icc_buffer[17]; /* bEntryValidationCondition */
cmd_APDU[6] = icc_buffer[18]; /* bNumberMessage */
cmd_APDU[7] = icc_buffer[19]; /* wLangId L */
cmd_APDU[8] = icc_buffer[20]; /* wLangId H */
cmd_APDU[9] = icc_buffer[21]; /* bMsgIndex, bMsgIndex1 */
cmd_APDU[10] = 0; /* bMsgIndex2 */
cmd_APDU[11] = 0; /* bMsgIndex3 */
icc_buffer[ICC_MSG_HEADER_SIZE+0] = icc_buffer[25];
icc_buffer[ICC_MSG_HEADER_SIZE+1] = icc_buffer[26];
icc_buffer[ICC_MSG_HEADER_SIZE+2] = icc_buffer[27];
icc_buffer[ICC_MSG_HEADER_SIZE+3] = icc_buffer[28];
/**/
icc_buffer[ICC_MSG_HEADER_SIZE+5] = 0; /* bConfirmPIN */
icc_buffer[ICC_MSG_HEADER_SIZE+6] = icc_buffer[17]; /* bEntryValidationCondition */
icc_buffer[ICC_MSG_HEADER_SIZE+7] = icc_buffer[18]; /* bNumberMessage */
icc_buffer[ICC_MSG_HEADER_SIZE+8] = icc_buffer[19]; /* wLangId L */
icc_buffer[ICC_MSG_HEADER_SIZE+9] = icc_buffer[20]; /* wLangId H */
icc_buffer[ICC_MSG_HEADER_SIZE+10] = icc_buffer[21]; /* bMsgIndex */
apdu.seq = icc_seq;
apdu.cmd_apdu_head = &icc_buffer[ICC_MSG_HEADER_SIZE+0];
apdu.cmd_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE+5];
apdu.cmd_apdu_data_len = 6;
apdu.expected_res_size = 0;
apdu.sw = 0x9000;
apdu.res_apdu_data_len = 0;
apdu.res_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE];
chEvtSignal (gpg_thread, EV_VERIFY_CMD_AVAILABLE);
next_state = ICC_STATE_EXECUTE;
}
@@ -552,22 +636,32 @@ icc_handle_data (void)
num_msgs = 1;
else if (num_msgs == 0xff)
num_msgs = 3;
cmd_APDU[0] = icc_buffer[27 + num_msgs];
cmd_APDU[1] = icc_buffer[28 + num_msgs];
cmd_APDU[2] = icc_buffer[29 + num_msgs];
cmd_APDU[3] = icc_buffer[30 + num_msgs];
icc_data_size = 4;
cmd_APDU[4] = icc_buffer[19]; /* bConfirmPIN */
cmd_APDU[5] = icc_buffer[20]; /* bEntryValidationCondition */
cmd_APDU[6] = icc_buffer[21]; /* bNumberMessage */
cmd_APDU[7] = icc_buffer[22]; /* wLangId L */
cmd_APDU[8] = icc_buffer[23]; /* wLangId H */
cmd_APDU[9] = icc_buffer[24]; /* bMsgIndex, bMsgIndex1 */
cmd_APDU[10] = cmd_APDU[11] = 0;
icc_buffer[ICC_MSG_HEADER_SIZE+0] = icc_buffer[27 + num_msgs];
icc_buffer[ICC_MSG_HEADER_SIZE+1] = icc_buffer[28 + num_msgs];
icc_buffer[ICC_MSG_HEADER_SIZE+2] = icc_buffer[29 + num_msgs];
icc_buffer[ICC_MSG_HEADER_SIZE+3] = icc_buffer[30 + num_msgs];
/**/
icc_buffer[ICC_MSG_HEADER_SIZE+5] = icc_buffer[19]; /* bConfirmPIN */
icc_buffer[ICC_MSG_HEADER_SIZE+6] = icc_buffer[20]; /* bEntryValidationCondition */
icc_buffer[ICC_MSG_HEADER_SIZE+7] = icc_buffer[21]; /* bNumberMessage */
icc_buffer[ICC_MSG_HEADER_SIZE+8] = icc_buffer[22]; /* wLangId L */
icc_buffer[ICC_MSG_HEADER_SIZE+9] = icc_buffer[23]; /* wLangId H */
icc_buffer[ICC_MSG_HEADER_SIZE+10] = icc_buffer[24]; /* bMsgIndex, bMsgIndex1 */
if (num_msgs >= 2)
cmd_APDU[10] = icc_buffer[25]; /* bMsgIndex2 */
icc_buffer[ICC_MSG_HEADER_SIZE+11] = icc_buffer[25]; /* bMsgIndex2 */
if (num_msgs == 3)
cmd_APDU[11] = icc_buffer[26]; /* bMsgIndex3 */
icc_buffer[ICC_MSG_HEADER_SIZE+12] = icc_buffer[26]; /* bMsgIndex3 */
apdu.seq = icc_seq;
apdu.cmd_apdu_head = &icc_buffer[ICC_MSG_HEADER_SIZE+0];
apdu.cmd_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE+5];
apdu.cmd_apdu_data_len = 5 + num_msgs;
apdu.expected_res_size = 0;
apdu.sw = 0x9000;
apdu.res_apdu_data_len = 0;
apdu.res_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE];
chEvtSignal (gpg_thread, EV_MODIFY_CMD_AVAILABLE);
next_state = ICC_STATE_EXECUTE;
}
@@ -599,8 +693,7 @@ icc_handle_data (void)
icc_next_p -= ICC_MSG_HEADER_SIZE;
icc_data_size = icc_next_p - icc_buffer - ICC_MSG_HEADER_SIZE;
icc_chain_p = NULL;
next_state = ICC_STATE_EXECUTE;
chEvtSignal (gpg_thread, EV_CMD_AVAILABLE);
goto run_gpg_thread;
}
else /* icc_header->param == 3 is not supported. */
{
@@ -638,26 +731,78 @@ icc_handle_data (void)
{
if (icc_header->param == 0x10)
{
if (res_APDU_pointer != NULL)
int len = apdu.res_apdu_data_len;
if (apdu.res_apdu_data == NULL)
{ /* send status word(s) of 0x9000 */
len = 0;
if (apdu.res_apdu_data_len == 2)
{
icc_buffer[ICC_MSG_HEADER_SIZE] = 0x90;
len++;
}
icc_buffer[ICC_MSG_HEADER_SIZE+len] = 0x00;
len++;
}
else if (apdu.res_apdu_data != &icc_buffer[ICC_MSG_HEADER_SIZE])
{
memcpy (res_APDU, res_APDU_pointer,
ICC_RESPONSE_MSG_DATA_SIZE);
res_APDU_pointer += ICC_RESPONSE_MSG_DATA_SIZE;
if (apdu.res_apdu_data_len > ICC_RESPONSE_MSG_DATA_SIZE)
{
memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE],
apdu.res_apdu_data, ICC_RESPONSE_MSG_DATA_SIZE);
apdu.res_apdu_data += ICC_RESPONSE_MSG_DATA_SIZE;
apdu.res_apdu_data_len -= ICC_RESPONSE_MSG_DATA_SIZE;
}
else if (apdu.res_apdu_data_len == ICC_RESPONSE_MSG_DATA_SIZE)
{
memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE],
apdu.res_apdu_data, ICC_RESPONSE_MSG_DATA_SIZE);
apdu.res_apdu_data = NULL;
apdu.res_apdu_data_len = 2;
}
else if (apdu.res_apdu_data_len
== ICC_RESPONSE_MSG_DATA_SIZE - 1)
{
memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE],
apdu.res_apdu_data, apdu.res_apdu_data_len);
icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len]
= 0x90;
apdu.res_apdu_data = NULL;
apdu.res_apdu_data_len = 1;
len += 1;
}
else if (apdu.res_apdu_data_len
<= ICC_RESPONSE_MSG_DATA_SIZE - 2)
{
memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE],
apdu.res_apdu_data, apdu.res_apdu_data_len);
icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len]
= 0x90;
icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len+1]
= 0x00;
apdu.res_apdu_data = NULL;
apdu.res_apdu_data_len = 0;
len += 2;
}
}
else
memmove (res_APDU, res_APDU+ICC_RESPONSE_MSG_DATA_SIZE,
res_APDU_size);
if (res_APDU_size <= ICC_RESPONSE_MSG_DATA_SIZE)
{
icc_send_data_block (res_APDU_size, 0, 0x02);
memmove (&icc_buffer[ICC_MSG_HEADER_SIZE],
&icc_buffer[ICC_MSG_HEADER_SIZE]
+ICC_RESPONSE_MSG_DATA_SIZE,
apdu.res_apdu_data_len);
apdu.res_apdu_data_len -= ICC_RESPONSE_MSG_DATA_SIZE;
}
if (len <= ICC_RESPONSE_MSG_DATA_SIZE)
{
icc_send_data_block (len, 0, 0x02);
next_state = ICC_STATE_WAIT;
}
else
{
icc_send_data_block (ICC_RESPONSE_MSG_DATA_SIZE, 0, 0x03);
res_APDU_size -= ICC_RESPONSE_MSG_DATA_SIZE;
}
icc_send_data_block (ICC_RESPONSE_MSG_DATA_SIZE, 0, 0x03);
}
else
{
@@ -726,26 +871,36 @@ USBthread (void *arg)
else if (m == EV_EXEC_FINISHED)
if (icc_state == ICC_STATE_EXECUTE)
{
if (res_APDU_pointer != NULL)
if (apdu.res_apdu_data != &icc_buffer[ICC_MSG_HEADER_SIZE])
{
memcpy (res_APDU, res_APDU_pointer, ICC_RESPONSE_MSG_DATA_SIZE);
res_APDU_pointer += ICC_RESPONSE_MSG_DATA_SIZE;
/* Assume that
* apdu.res_apdu_data_len > ICC_RESPONSE_MSG_DATA_SIZE
*/
memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE],
apdu.res_apdu_data, ICC_RESPONSE_MSG_DATA_SIZE);
apdu.res_apdu_data += ICC_RESPONSE_MSG_DATA_SIZE;
}
else
{
icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len] = (apdu.sw >> 8);
icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len+1] = (apdu.sw & 0xff);
apdu.res_apdu_data_len += 2;
}
if (res_APDU_size <= ICC_RESPONSE_MSG_DATA_SIZE)
if (apdu.res_apdu_data_len <= ICC_RESPONSE_MSG_DATA_SIZE)
{
icc_send_data_block (res_APDU_size, 0, 0);
icc_send_data_block (apdu.res_apdu_data_len, 0, 0);
icc_state = ICC_STATE_WAIT;
}
else
{
icc_send_data_block (ICC_RESPONSE_MSG_DATA_SIZE, 0, 0x01);
res_APDU_size -= ICC_RESPONSE_MSG_DATA_SIZE;
apdu.res_apdu_data_len -= ICC_RESPONSE_MSG_DATA_SIZE;
icc_state = ICC_STATE_SEND;
}
}
else
{ /* XXX: error */
{ /* error */
DEBUG_INFO ("ERR07\r\n");
}
else if (m == EV_TX_FINISHED)

View File

@@ -1,5 +1,6 @@
#include "ch.h"
#include "hal.h"
#include "usb_lib.h"
#include "usb_lld.h"
extern void USB_Istr (void);

View File

@@ -1,2 +1,52 @@
#define STM32_USB_IRQ_PRIORITY 11
void usb_lld_init (void);
extern inline void usb_lld_stall_tx (int ep_num)
{
SetEPTxStatus (ep_num, EP_TX_STALL);
}
extern inline void usb_lld_stall_rx (int ep_num)
{
SetEPRxStatus (ep_num, EP_RX_STALL);
}
extern inline int usb_lld_tx_data_len (int ep_num)
{
return GetEPTxCount (ep_num);
}
extern inline void usb_lld_txcpy (const uint8_t *src,
int ep_num, int offset, size_t len)
{
UserToPMABufferCopy ((uint8_t *)src, GetEPTxAddr (ep_num) + offset, len);
}
extern inline void usb_lld_tx_enable (int ep_num, size_t len)
{
SetEPTxCount (ep_num, len);
SetEPTxValid (ep_num);
}
extern inline void usb_lld_write (uint8_t ep_num, void *buf, size_t len)
{
UserToPMABufferCopy (buf, GetEPTxAddr (ep_num), len);
SetEPTxCount (ep_num, len);
SetEPTxValid (ep_num);
}
extern inline void usb_lld_rx_enable (int ep_num)
{
SetEPRxValid (ep_num);
}
extern inline int usb_lld_rx_data_len (int ep_num)
{
return GetEPRxCount (ep_num);
}
extern inline void usb_lld_rxcpy (uint8_t *dst,
int ep_num, int offset, size_t len)
{
PMAToUserBufferCopy (dst, GetEPRxAddr (ep_num) + offset, len);
}

View File

@@ -1,7 +1,7 @@
/*
* usb_msc.c -- USB Mass Storage Class protocol handling
*
* Copyright (C) 2011 Free Software Initiative of Japan
* Copyright (C) 2011, 2012 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -26,6 +26,7 @@
#include "config.h"
#include "ch.h"
#include "gnuk.h"
#include "usb_lld.h"
#include "usb_msc.h"
struct usb_endp_in {
@@ -50,11 +51,6 @@ static Thread *the_thread;
static uint8_t msc_state;
static void usb_stall_transmit (void)
{
SetEPTxStatus (ENDP6, EP_TX_STALL);
}
static void usb_start_transmit (const uint8_t *p, size_t n)
{
size_t pkt_len = n > ENDP_MAX_SIZE ? ENDP_MAX_SIZE : n;
@@ -63,14 +59,13 @@ static void usb_start_transmit (const uint8_t *p, size_t n)
ep6_in.txsize = n;
ep6_in.txcnt = 0;
USB_SIL_Write (EP6_IN, (uint8_t *)ep6_in.txbuf, pkt_len);
SetEPTxValid (ENDP6);
usb_lld_write (ENDP6, (uint8_t *)ep6_in.txbuf, pkt_len);
}
/* "Data Transmitted" callback */
void EP6_IN_Callback (void)
{
size_t n = (size_t)GetEPTxCount (ENDP6);
size_t n = (size_t)usb_lld_tx_data_len (ENDP6);
ep6_in.txbuf += n;
ep6_in.txcnt += n;
@@ -82,8 +77,7 @@ void EP6_IN_Callback (void)
n = ENDP_MAX_SIZE;
else
n = ep6_in.txsize;
USB_SIL_Write (EP6_IN, (uint8_t *)ep6_in.txbuf, n);
SetEPTxValid (ENDP6);
usb_lld_write (ENDP6, (uint8_t *)ep6_in.txbuf, n);
return;
}
@@ -108,43 +102,34 @@ void EP6_IN_Callback (void)
}
static void usb_stall_receive (void)
{
SetEPRxStatus (ENDP7, EP_RX_STALL);
}
static void usb_start_receive (uint8_t *p, size_t n)
{
ep7_out.rxbuf = p;
ep7_out.rxsize = n;
ep7_out.rxcnt = 0;
if (n < ENDP_MAX_SIZE)
SetEPRxCount (ENDP7, n);
else
SetEPRxCount (ENDP7, ENDP_MAX_SIZE);
SetEPRxValid (ENDP7);
usb_lld_rx_enable (ENDP7);
}
/* "Data Received" call back */
void EP7_OUT_Callback (void)
{
size_t n = (size_t)GetEPRxCount (ENDP7);
size_t n = (size_t)usb_lld_rx_data_len (ENDP7);
int err = 0;
if (n > ep7_out.rxsize)
{ /* buffer overflow */
err = 1;
SetEPRxCount (ENDP7, ep7_out.rxsize);
n = ep7_out.rxsize;
}
n = USB_SIL_Read (EP7_OUT, ep7_out.rxbuf);
usb_lld_rxcpy (ep7_out.rxbuf, ENDP7, 0, n);
ep7_out.rxbuf += n;
ep7_out.rxcnt += n;
ep7_out.rxsize -= n;
if (n == ENDP_MAX_SIZE && ep7_out.rxsize != 0)
{ /* More data to be received */
SetEPRxValid (ENDP7);
usb_lld_rx_enable (ENDP7);
return;
}
@@ -333,7 +318,7 @@ void msc_handle_command (void)
if (msg != RDY_TIMEOUT)
{
chSysLock ();
usb_stall_receive ();
usb_lld_stall_rx (ENDP7);
chSysUnlock ();
}
return;
@@ -345,7 +330,7 @@ void msc_handle_command (void)
{
msc_state = MSC_ERROR;
chSysLock ();
usb_stall_receive ();
usb_lld_stall_rx (ENDP7);
chSysUnlock ();
return;
}
@@ -448,8 +433,8 @@ void msc_handle_command (void)
{
msc_state = MSC_ERROR;
chSysLock ();
usb_stall_transmit ();
usb_stall_receive ();
usb_lld_stall_tx (ENDP6);
usb_lld_stall_rx (ENDP7);
chSysUnlock ();
return;
}

View File

@@ -41,6 +41,20 @@
#endif
static void
SetEPRxCount_allocated_size (uint8_t bEpNum, uint16_t wCount)
{ /* Assume wCount is even */
uint32_t *pdwReg = _pEPRxCount (bEpNum);
uint16_t value;
if (wCount <= 62)
value = (wCount & 0x3e) << 9;
else
value = 0x8000 | (((wCount >> 5) - 1) << 10);
*pdwReg = (uint32_t)value;
}
static void
gnuk_device_init (void)
{
@@ -50,7 +64,9 @@ gnuk_device_init (void)
PowerOn ();
/* Perform basic device initialization operations */
USB_SIL_Init ();
_SetISTR (0);
wInterrupt_Mask = IMR_MSK;
_SetCNTR (wInterrupt_Mask);
bDeviceState = UNCONNECTED;
}
@@ -75,7 +91,7 @@ gnuk_device_reset (void)
SetEPRxAddr (ENDP0, ENDP0_RXADDR);
SetEPTxAddr (ENDP0, ENDP0_TXADDR);
Clear_Status_Out (ENDP0);
SetEPRxCount (ENDP0, GNUK_MAX_PACKET_SIZE);
SetEPRxCount_allocated_size (ENDP0, GNUK_MAX_PACKET_SIZE);
SetEPRxValid (ENDP0);
/* Initialize Endpoint 1 */
@@ -87,7 +103,7 @@ gnuk_device_reset (void)
/* Initialize Endpoint 2 */
SetEPType (ENDP2, EP_BULK);
SetEPRxAddr (ENDP2, ENDP2_RXADDR);
SetEPRxCount (ENDP2, GNUK_MAX_PACKET_SIZE);
SetEPRxCount_allocated_size (ENDP2, GNUK_MAX_PACKET_SIZE);
SetEPRxStatus (ENDP2, EP_RX_VALID);
SetEPTxStatus (ENDP2, EP_TX_DIS);
@@ -107,7 +123,7 @@ gnuk_device_reset (void)
/* Initialize Endpoint 5 */
SetEPType (ENDP5, EP_BULK);
SetEPRxAddr (ENDP5, ENDP5_RXADDR);
SetEPRxCount (ENDP5, VIRTUAL_COM_PORT_DATA_SIZE);
SetEPRxCount_allocated_size (ENDP5, VIRTUAL_COM_PORT_DATA_SIZE);
SetEPRxStatus (ENDP5, EP_RX_VALID);
SetEPTxStatus (ENDP5, EP_TX_DIS);
#endif
@@ -122,6 +138,7 @@ gnuk_device_reset (void)
/* Initialize Endpoint 7 */
SetEPType (ENDP7, EP_BULK);
SetEPRxAddr (ENDP7, ENDP7_RXADDR);
SetEPRxCount_allocated_size (ENDP7, 64);
SetEPRxStatus (ENDP7, EP_RX_STALL);
SetEPTxStatus (ENDP7, EP_TX_DIS);
#endif

View File

@@ -47,7 +47,7 @@ class GnukToken(object):
apdu = [0x00, 0x20, 0x00, 0x80+who, 0, 0, len(passwd)] + s2l(passwd)
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, "cmd_verify"
raise ValueError, ("%02x%02x" % (sw1, sw2))
def cmd_write_binary(self, fileid, data, is_update):
count = 0
@@ -66,22 +66,22 @@ class GnukToken(object):
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
if is_update:
raise ValueError, "cmd_update_binary"
raise ValueError, ("%02x%02x" % (sw1, sw2))
else:
raise ValueError, "cmd_write_binary"
raise ValueError, ("%02x%02x" % (sw1, sw2))
count += 1
def cmd_select_openpgp(self):
apdu = [0x00, 0xa4, 0x04, 0x00, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ]
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, "cmd_select_openpgp"
raise ValueError, ("%02x%02x" % (sw1, sw2))
def cmd_get_data(self, tagh, tagl):
apdu = [0x00, 0xca, tagh, tagl]
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, "cmd_get_data"
raise ValueError, ("%02x%02x" % (sw1, sw2))
return response
def compare(data_original, data_in_device):
@@ -165,6 +165,5 @@ if __name__ == '__main__':
data = f.read()
f.close()
print "%s: %d" % (filename, len(data))
data += "\x90\x00"
print "Updating card holder certificate"
main(fileid, is_update, data, passwd)

View File

@@ -289,6 +289,5 @@ if __name__ == '__main__':
data = f.read()
f.close()
print "%s: %d" % (filename, len(data))
data += "\x90\x00"
print "Updating card holder certificate"
main(fileid, is_update, data)

View File

@@ -1,9 +1,9 @@
#! /usr/bin/python
"""
pinpad-test.py - a tool to test pinpad support by card reader.
pinpadtest.py - a tool to test variable length pin entry with pinpad
Copyright (C) 2011 Free Software Initiative of Japan
Copyright (C) 2011, 2012 Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -30,14 +30,20 @@ from smartcard.CardType import AnyCardType
from smartcard.CardRequest import CardRequest
from smartcard.util import toHexString
from getpass import getpass
CM_IOCTL_GET_FEATURE_REQUEST = (0x42000000 + 3400)
FEATURE_VERIFY_PIN_DIRECT = 0x06
FEATURE_MODIFY_PIN_DIRECT = 0x07
BY_ADMIN = 3
BY_USER = 1
PIN_MIN_DEFAULT = 6 # min of OpenPGP card
PIN_MAX_DEFAULT = 15 # max of VASCO DIGIPASS 920
def s2l(s):
return [ ord(c) for c in s ]
def confirm_pin_setting(single_step):
if single_step:
return 0x01 # bConfirmPIN: new PIN twice
@@ -45,14 +51,15 @@ def confirm_pin_setting(single_step):
return 0x03 # bConfirmPIN: old PIN and new PIN twice
class Card(object):
def __init__(self, add_a_byte, pinmax):
def __init__(self, add_a_byte, pinmin, pinmax):
cardtype = AnyCardType()
cardrequest = CardRequest(timeout=1, cardType=cardtype)
cardrequest = CardRequest(timeout=10, cardType=cardtype)
cardservice = cardrequest.waitforcard()
self.connection = cardservice.connection
self.verify_ioctl = -1
self.modify_ioctl = -1
self.another_byte = add_a_byte
self.pinmin = pinmin
self.pinmax = pinmax
def get_features(self):
@@ -97,7 +104,7 @@ class Card(object):
0x00, # bmPINBlockString
0x00, # bmPINLengthFormat
self.pinmax, # wPINMaxExtraDigit Low (PINmax)
1, # wPINMaxExtraDigit High (PINmin)
self.pinmin, # wPINMaxExtraDigit High (PINmin)
0x02, # bEntryValidationCondition
0x01, # bNumberMessage
0x00, # wLangId Low
@@ -107,7 +114,8 @@ class Card(object):
0x00, # bTeoPrologue[1]
0x00 # bTeoPrologue[2]
]
pin_verify += [ len(apdu), 0, 0, 0 ] + apdu + self.possibly_add_dummy_byte()
apdu += self.possibly_add_dummy_byte()
pin_verify += [ len(apdu), 0, 0, 0 ] + apdu
data = self.connection.control(self.verify_ioctl,pin_verify)
sw1 = data[0]
sw2 = data[1]
@@ -125,7 +133,7 @@ class Card(object):
0x00, # bInsertionOffsetOld
0x00, # bInsertionOffsetNew
self.pinmax, # wPINMaxExtraDigit Low (PINmax)
1, # wPINMaxExtraDigit High (PINmin)
self.pinmin, # wPINMaxExtraDigit High (PINmin)
confirm_pin_setting(single_step),
0x02, # bEntryValidationCondition
0x03, # bNumberMessage
@@ -138,20 +146,37 @@ class Card(object):
0x00, # bTeoPrologue[1]
0x00 # bTeoPrologue[2]
]
pin_modify += [ len(apdu), 0, 0, 0 ] + apdu + self.possibly_add_dummy_byte()
apdu += self.possibly_add_dummy_byte()
pin_modify += [ len(apdu), 0, 0, 0 ] + apdu
data = self.connection.control(self.modify_ioctl,pin_modify)
sw1 = data[0]
sw2 = data[1]
if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%s %02x %02x" % (command, sw1, sw2))
def cmd_reset_retry_counter(self, who, data):
if who == BY_ADMIN:
apdu = [0x00, 0x2c, 0x02, 0x81, len(data) ] + data # BY_ADMIN
else:
apdu = [0x00, 0x2c, 0x00, 0x81, len(data) ] + data # BY_USER with resetcode
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("cmd_reset_retry_counter %02x %02x" % (sw1, sw2))
# Note: CCID specification doesn't permit this (only 0x20 and 0x24)
def cmd_reset_retry_counter_pinpad(self, who):
if who == BY_ADMIN:
apdu = [0x00, 0x2c, 0x02, 0x81] # BY_ADMIN
self.send_modify_pinpad(apdu, True, "cmd_reset_retry_counter_pinpad")
else:
apdu = [0x00, 0x2c, 0x00, 0x81] # BY_USER with resetcode
self.send_modify_pinpad(apdu, False, "cmd_reset_retry_counter_pinpad")
self.send_modify_pinpad(apdu, False, "cmd_reset_retry_counter_pinpad")
def cmd_put_resetcode(self, data):
apdu = [0x00, 0xda, 0x00, 0xd3, len(data) ] + data # BY_ADMIN
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("cmd_put_resetcode %02x %02x" % (sw1, sw2))
# Note: CCID specification doesn't permit this (only 0x20 and 0x24)
def cmd_put_resetcode_pinpad(self):
@@ -166,11 +191,8 @@ class Card(object):
self.send_modify_pinpad(apdu, is_exchange,
"cmd_change_reference_data_pinpad")
# "Vasco DIGIPASS 920 [CCID] 00 00"
# "FSIJ Gnuk (0.16-34006F06) 00 00"
def main(who, method, add_a_byte, pinmax, change_by_two_steps):
card = Card(add_a_byte, pinmax)
def main(who, method, add_a_byte, pinmin, pinmax, change_by_two_steps):
card = Card(add_a_byte, pinmin, pinmax)
card.connection.connect()
print "Reader/Token:", card.connection.getReader()
@@ -206,20 +228,38 @@ def main(who, method, add_a_byte, pinmax, change_by_two_steps):
print "and New Admin's PIN twice"
card.cmd_change_reference_data_pinpad(who, False)
elif method == "unblock":
# It's always by single step
if who == BY_USER:
print "Please input reset code"
print "and New User's PIN twice"
if change_by_two_steps:
# It means using keyboard for new PIN
if who == BY_USER:
resetcode=s2l(getpass("Please input reset code from keyboard: "))
newpin=s2l(getpass("Please input New User's PIN from keyboard: "))
card.cmd_reset_retry_counter(who,resetcode+newpin)
else:
print "Please input Admin's PIN"
card.cmd_verify_pinpad(BY_ADMIN)
newpin=s2l(getpass("Please input New User's PIN from keyboard: "))
card.cmd_reset_retry_counter(who,newpin)
else:
if who == BY_USER:
print "Please input reset code"
print "and New User's PIN twice"
else:
print "Please input Admin's PIN"
card.cmd_verify_pinpad(BY_ADMIN)
print "Please input New User's PIN twice"
card.cmd_reset_retry_counter_pinpad(who)
elif method == "put":
if change_by_two_steps:
# It means using keyboard for new PIN
print "Please input Admin's PIN"
card.cmd_verify_pinpad(BY_ADMIN)
resetcode=s2l(getpass("Please input New Reset Code from keyboard: "))
card.cmd_put_resetcode(resetcode)
else:
print "Please input Admin's PIN"
print "and New User's PIN twice"
card.cmd_reset_retry_counter_pinpad(who)
elif method == "put":
# It's always by two steps
print "Please input Admin's PIN"
card.cmd_verify_pinpad(BY_ADMIN)
print "Please input New Reset Code twice"
card.cmd_put_resetcode_pinpad()
card.cmd_verify_pinpad(BY_ADMIN)
print "Please input New Reset Code twice"
card.cmd_put_resetcode_pinpad()
else:
raise ValueError, method
card.connection.disconnect()
@@ -236,10 +276,13 @@ def print_usage():
print "\t--change:\tchange PIN (old PIN, new PIN twice)"
print "\t--change2:\tchange PIN by two steps (old PIN, new PIN twice)"
print "\t--unblock:\tunblock PIN (admin PIN/resetcode, new PIN twice)"
print "\t--unblock2:\tunblock PIN (admin PIN:pinpad, new PIN:kbd)"
print "\t--put:\t\tsetup resetcode (admin PIN, new PIN twice)"
print "\t--put2::\t\tsetup resetcode (admin PIN:pinpad, new PIN:kbd)"
print " options:"
print "\t--admin:\tby administrator\t\t\t[False]"
print "\t--add:\t\tadd a dummy byte at the end of APDU\t[False]"
print "\t--pinmin:\tspecify minimum length of PIN\t\t[6]"
print "\t--pinmax:\tspecify maximum length of PIN\t\t[15]"
print "EXAMPLES:"
print " $ pinpad-test # verify user's PIN "
@@ -256,6 +299,7 @@ if __name__ == '__main__':
who = BY_USER
method = "verify"
add_a_byte = False
pinmin = PIN_MIN_DEFAULT
pinmax = PIN_MAX_DEFAULT
change_by_two_steps = False
while len(sys.argv) >= 2:
@@ -270,13 +314,22 @@ if __name__ == '__main__':
change_by_two_steps = True
elif option == '--unblock':
method = "unblock"
elif option == '--unblock2':
method = "unblock"
change_by_two_steps = True
elif option == '--add':
add_a_byte = True
elif option == '--pinmin':
pinmin = int(sys.argv[1])
sys.argv.pop(1)
elif option == '--pinmax':
pinmax = int(sys.argv[1])
sys.argv.pop(1)
elif option == '--put':
method = "put"
elif option == '--put2':
method = "put"
change_by_two_steps = True
elif option == "verify":
method = "verify"
elif option == '--help':
@@ -284,8 +337,62 @@ if __name__ == '__main__':
exit(0)
else:
raise ValueError, option
main(who, method, add_a_byte, pinmax, change_by_two_steps)
main(who, method, add_a_byte, pinmin, pinmax, change_by_two_steps)
# Failure
# 67 00: Wrong length; no further indication
# 69 82: Security status not satisfied: pin doesn't match
# 69 85: Conditions of use not satisfied
# 6b 00: Wrong parameters P1-P2
# 6b 80
# 64 02: PIN different
# General
# OpenPGP card v2 doesn't support CHANGE REFERENCE DATA in exchanging
# mode (with P1 == 01, replacing PIN).
# FAIL: --change2 fails with 6b 00 (after input of PIN)
# FAIL: --change2 --admin fails with 6b 00 (after input of PIN)
# "FSIJ Gnuk (0.16-34006F06) 00 00"
# Works well except --change2
# It could support --put and --unblock, but currently it's disabled.
# "Vasco DIGIPASS 920 [CCID] 00 00"
# OK: --verify
# OK: --verify --admin
# OK: --change
# OK: --change --admin
# OK: --unblock
# FAIL: --unblock --admin fails with 69 85 (after input of PIN)
# FAIL: --put fails with 6b 80 (before input of resetcode)
# OK: --put2
# FAIL: --unblock2 fails with 69 85
# FAIL: --unblock2 --admin fails with 69 85 (after input of PIN)
# 0c4b:0500 Reiner SCT Kartensysteme GmbH
# "REINER SCT cyberJack RFID standard (7592671050) 00 00"
# OK: --verify
# OK: --verify --admin
# OK: --change
# OK: --change --admin
# OK: --unblock
# OK: --unblock --admin
# FAIL: --put fails with 69 85
# Gemalto GemPC Pinpad 00 00
# It asks users PIN with --add but it results 67 00
# It seems that it doesn't support variable length PIN
# Firmware version: GemTwRC2-V2.10-GL04
# 072f:90d2 Advanced Card Systems, Ltd
# ACS ACR83U 01 00
# --verify failed with 6b 80
# 08e6:34c2 Gemplus
# Gemalto Ezio Shield PinPad 01 00
# works well
# FAIL: --unblock2 fails with 6d 00
# 076b:3821 OmniKey AG CardMan 3821
# OmniKey CardMan 3821 01 00
# Works well with --pinmax 31 --pinmin 1