mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-24 10:39:57 +01:00
Merge ccid_driver_improvement branch. (backport)
* scd/apdu.c (ccid_keypad_operation): Rename from ccid_keypad_verify. (open_ccid_reader): Use ccid_keypad_operation for verify and modify. * scd/ccid-driver.c (VENDOR_VASCO, VASCO_920): New. (ccid_transceive_apdu_level): Permit sending packet where apdulen <= 289. Support receiving packets in a chain. (ccid_transceive_secure): Maximum is 15 for VASCO DIGIPASS 920. Support keypad_modify method such as CHANGE_REFERENCE_DATA: 0x24.
This commit is contained in:
parent
2f90d09902
commit
262a3b2336
@ -2339,8 +2339,8 @@ check_ccid_keypad (int slot, int command, int pin_mode,
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ccid_keypad_verify (int slot, int class, int ins, int p0, int p1,
|
ccid_keypad_operation (int slot, int class, int ins, int p0, int p1,
|
||||||
struct pininfo_s *pininfo)
|
struct pininfo_s *pininfo)
|
||||||
{
|
{
|
||||||
unsigned char apdu[4];
|
unsigned char apdu[4];
|
||||||
int err, sw;
|
int err, sw;
|
||||||
@ -2411,8 +2411,8 @@ open_ccid_reader (const char *portstr)
|
|||||||
reader_table[slot].check_keypad = check_ccid_keypad;
|
reader_table[slot].check_keypad = check_ccid_keypad;
|
||||||
reader_table[slot].dump_status_reader = dump_ccid_reader_status;
|
reader_table[slot].dump_status_reader = dump_ccid_reader_status;
|
||||||
reader_table[slot].set_progress_cb = set_progress_cb_ccid_reader;
|
reader_table[slot].set_progress_cb = set_progress_cb_ccid_reader;
|
||||||
reader_table[slot].keypad_verify = ccid_keypad_verify;
|
reader_table[slot].keypad_verify = ccid_keypad_operation;
|
||||||
reader_table[slot].keypad_modify = NULL;
|
reader_table[slot].keypad_modify = ccid_keypad_operation;
|
||||||
/* Our CCID reader code does not support T=0 at all, thus reset the
|
/* Our CCID reader code does not support T=0 at all, thus reset the
|
||||||
flag. */
|
flag. */
|
||||||
reader_table[slot].is_t0 = 0;
|
reader_table[slot].is_t0 = 0;
|
||||||
|
@ -210,7 +210,8 @@ enum {
|
|||||||
VENDOR_OMNIKEY= 0x076b,
|
VENDOR_OMNIKEY= 0x076b,
|
||||||
VENDOR_GEMPC = 0x08e6,
|
VENDOR_GEMPC = 0x08e6,
|
||||||
VENDOR_KAAN = 0x0d46,
|
VENDOR_KAAN = 0x0d46,
|
||||||
VENDOR_FSIJ = 0x234B
|
VENDOR_FSIJ = 0x234b,
|
||||||
|
VENDOR_VASCO = 0x1a44
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Some product ids. */
|
/* Some product ids. */
|
||||||
@ -220,7 +221,7 @@ enum {
|
|||||||
#define SCM_SCR3320 0x5117
|
#define SCM_SCR3320 0x5117
|
||||||
#define SCM_SPR532 0xe003
|
#define SCM_SPR532 0xe003
|
||||||
#define CHERRY_ST2000 0x003e
|
#define CHERRY_ST2000 0x003e
|
||||||
|
#define VASCO_920 0x0920
|
||||||
|
|
||||||
/* A list and a table with special transport descriptions. */
|
/* A list and a table with special transport descriptions. */
|
||||||
enum {
|
enum {
|
||||||
@ -2589,8 +2590,8 @@ ccid_transceive_apdu_level (ccid_driver_t handle,
|
|||||||
|
|
||||||
/* The maximum length for a short APDU T=1 block is 261. For an
|
/* The maximum length for a short APDU T=1 block is 261. For an
|
||||||
extended APDU T=1 block the maximum length 65544; however
|
extended APDU T=1 block the maximum length 65544; however
|
||||||
extended APDU exchange level is not yet supported. */
|
extended APDU exchange level is not fully supported yet. */
|
||||||
if (apdulen > 261)
|
if (apdulen > 289)
|
||||||
return CCID_DRIVER_ERR_INV_VALUE; /* Invalid length. */
|
return CCID_DRIVER_ERR_INV_VALUE; /* Invalid length. */
|
||||||
|
|
||||||
msg[0] = PC_to_RDR_XfrBlock;
|
msg[0] = PC_to_RDR_XfrBlock;
|
||||||
@ -2613,8 +2614,51 @@ ccid_transceive_apdu_level (ccid_driver_t handle,
|
|||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
apdu = msg + 10;
|
if (msg[9] == 1)
|
||||||
apdulen = msglen - 10;
|
{
|
||||||
|
size_t total_msglen = msglen;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
unsigned char status;
|
||||||
|
|
||||||
|
msg = recv_buffer + total_msglen;
|
||||||
|
|
||||||
|
msg[0] = PC_to_RDR_XfrBlock;
|
||||||
|
msg[5] = 0; /* slot */
|
||||||
|
msg[6] = seqno = handle->seqno++;
|
||||||
|
msg[7] = bwi; /* bBWI */
|
||||||
|
msg[8] = 0x10; /* Request next data block */
|
||||||
|
msg[9] = 0;
|
||||||
|
set_msg_len (msg, 0);
|
||||||
|
msglen = 10;
|
||||||
|
|
||||||
|
rc = bulk_out (handle, msg, msglen, 0);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = bulk_in (handle, msg, sizeof recv_buffer - total_msglen, &msglen,
|
||||||
|
RDR_to_PC_DataBlock, seqno, 5000, 0);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
status = msg[9];
|
||||||
|
memmove (msg, msg+10, msglen - 10);
|
||||||
|
total_msglen += msglen - 10;
|
||||||
|
if (total_msglen >= sizeof recv_buffer)
|
||||||
|
return CCID_DRIVER_ERR_OUT_OF_CORE;
|
||||||
|
|
||||||
|
if (status == 0x02)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
apdu = recv_buffer + 10;
|
||||||
|
apdulen = total_msglen - 10;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
apdu = msg + 10;
|
||||||
|
apdulen = msglen - 10;
|
||||||
|
}
|
||||||
|
|
||||||
if (resp)
|
if (resp)
|
||||||
{
|
{
|
||||||
@ -3058,7 +3102,7 @@ ccid_transceive_secure (ccid_driver_t handle,
|
|||||||
if (apdu_buflen >= 4 && apdu_buf[1] == 0x20 && (handle->has_pinpad & 1))
|
if (apdu_buflen >= 4 && apdu_buf[1] == 0x20 && (handle->has_pinpad & 1))
|
||||||
;
|
;
|
||||||
else if (apdu_buflen >= 4 && apdu_buf[1] == 0x24 && (handle->has_pinpad & 2))
|
else if (apdu_buflen >= 4 && apdu_buf[1] == 0x24 && (handle->has_pinpad & 2))
|
||||||
return CCID_DRIVER_ERR_NOT_SUPPORTED; /* Not yet by our code. */
|
;
|
||||||
else
|
else
|
||||||
return CCID_DRIVER_ERR_NO_KEYPAD;
|
return CCID_DRIVER_ERR_NO_KEYPAD;
|
||||||
|
|
||||||
@ -3086,6 +3130,9 @@ ccid_transceive_secure (ccid_driver_t handle,
|
|||||||
case VENDOR_SCM: /* Tested with SPR 532. */
|
case VENDOR_SCM: /* Tested with SPR 532. */
|
||||||
case VENDOR_KAAN: /* Tested with KAAN Advanced (1.02). */
|
case VENDOR_KAAN: /* Tested with KAAN Advanced (1.02). */
|
||||||
break;
|
break;
|
||||||
|
case VENDOR_VASCO: /* Tested with DIGIPASS 920 */
|
||||||
|
pinlen_max = 15;
|
||||||
|
break;
|
||||||
case VENDOR_CHERRY:
|
case VENDOR_CHERRY:
|
||||||
/* The CHERRY XX44 keyboard echos an asterisk for each entered
|
/* The CHERRY XX44 keyboard echos an asterisk for each entered
|
||||||
character on the keyboard channel. We use a special variant
|
character on the keyboard channel. We use a special variant
|
||||||
@ -3120,7 +3167,8 @@ ccid_transceive_secure (ccid_driver_t handle,
|
|||||||
msg[7] = 0; /* bBWI */
|
msg[7] = 0; /* bBWI */
|
||||||
msg[8] = 0; /* RFU */
|
msg[8] = 0; /* RFU */
|
||||||
msg[9] = 0; /* RFU */
|
msg[9] = 0; /* RFU */
|
||||||
msg[10] = 0; /* Perform PIN verification. */
|
msg[10] = apdu_buf[1] == 0x20 ? 0 : 1;
|
||||||
|
/* Perform PIN verification or PIN modification. */
|
||||||
msg[11] = 0; /* Timeout in seconds. */
|
msg[11] = 0; /* Timeout in seconds. */
|
||||||
msg[12] = 0x82; /* bmFormatString: Byte, pos=0, left, ASCII. */
|
msg[12] = 0x82; /* bmFormatString: Byte, pos=0, left, ASCII. */
|
||||||
if (handle->id_vendor == VENDOR_SCM)
|
if (handle->id_vendor == VENDOR_SCM)
|
||||||
@ -3139,28 +3187,58 @@ ccid_transceive_secure (ccid_driver_t handle,
|
|||||||
Units are bytes, position is 0. */
|
Units are bytes, position is 0. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The following is a little endian word. */
|
msglen = 15;
|
||||||
msg[15] = pinlen_max; /* wPINMaxExtraDigit-Maximum. */
|
if (apdu_buf[1] == 0x24)
|
||||||
msg[16] = pinlen_min; /* wPINMaxExtraDigit-Minimum. */
|
{
|
||||||
|
msg[msglen++] = 0; /* bInsertionOffsetOld */
|
||||||
|
msg[msglen++] = 0; /* bInsertionOffsetNew */
|
||||||
|
}
|
||||||
|
|
||||||
msg[17] = 0x02; /* bEntryValidationCondition:
|
/* The following is a little endian word. */
|
||||||
Validation key pressed */
|
msg[msglen++] = pinlen_max; /* wPINMaxExtraDigit-Maximum. */
|
||||||
|
msg[msglen++] = pinlen_min; /* wPINMaxExtraDigit-Minimum. */
|
||||||
|
|
||||||
|
if (apdu_buf[1] == 0x24)
|
||||||
|
msg[msglen++] = apdu_buf[2] == 0 ? 0x03 : 0x01;
|
||||||
|
/* bConfirmPIN
|
||||||
|
* 0x00: new PIN once
|
||||||
|
* 0x01: new PIN twice (confirmation)
|
||||||
|
* 0x02: old PIN and new PIN once
|
||||||
|
* 0x03: old PIN and new PIN twice (confirmation)
|
||||||
|
*/
|
||||||
|
|
||||||
|
msg[msglen] = 0x02; /* bEntryValidationCondition:
|
||||||
|
Validation key pressed */
|
||||||
if (pinlen_min && pinlen_max && pinlen_min == pinlen_max)
|
if (pinlen_min && pinlen_max && pinlen_min == pinlen_max)
|
||||||
msg[17] |= 0x01; /* Max size reached. */
|
msg[msglen] |= 0x01; /* Max size reached. */
|
||||||
msg[18] = 0xff; /* bNumberMessage: Default. */
|
msglen++;
|
||||||
msg[19] = 0x09; /* wLangId-Low: English FIXME: use the first entry. */
|
|
||||||
msg[20] = 0x04; /* wLangId-High. */
|
if (apdu_buf[1] == 0x20)
|
||||||
msg[21] = 0; /* bMsgIndex. */
|
msg[msglen++] = 0xff; /* bNumberMessage: Default. */
|
||||||
|
else
|
||||||
|
msg[msglen++] = 0x03; /* bNumberMessage. */
|
||||||
|
|
||||||
|
msg[msglen++] = 0x09; /* wLangId-Low: English FIXME: use the first entry. */
|
||||||
|
msg[msglen++] = 0x04; /* wLangId-High. */
|
||||||
|
|
||||||
|
if (apdu_buf[1] == 0x20)
|
||||||
|
msg[msglen++] = 0; /* bMsgIndex. */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg[msglen++] = 0; /* bMsgIndex1. */
|
||||||
|
msg[msglen++] = 1; /* bMsgIndex2. */
|
||||||
|
msg[msglen++] = 2; /* bMsgIndex3. */
|
||||||
|
}
|
||||||
|
|
||||||
/* bTeoProlog follows: */
|
/* bTeoProlog follows: */
|
||||||
msg[22] = handle->nonnull_nad? ((1 << 4) | 0): 0;
|
msg[msglen++] = handle->nonnull_nad? ((1 << 4) | 0): 0;
|
||||||
msg[23] = ((handle->t1_ns & 1) << 6); /* I-block */
|
msg[msglen++] = ((handle->t1_ns & 1) << 6); /* I-block */
|
||||||
msg[24] = 0; /* The apdulen will be filled in by the reader. */
|
msg[msglen++] = 0; /* The apdulen will be filled in by the reader. */
|
||||||
/* APDU follows: */
|
/* APDU follows: */
|
||||||
msg[25] = apdu_buf[0]; /* CLA */
|
msg[msglen++] = apdu_buf[0]; /* CLA */
|
||||||
msg[26] = apdu_buf[1]; /* INS */
|
msg[msglen++] = apdu_buf[1]; /* INS */
|
||||||
msg[27] = apdu_buf[2]; /* P1 */
|
msg[msglen++] = apdu_buf[2]; /* P1 */
|
||||||
msg[28] = apdu_buf[3]; /* P2 */
|
msg[msglen++] = apdu_buf[3]; /* P2 */
|
||||||
msglen = 29;
|
|
||||||
if (cherry_mode)
|
if (cherry_mode)
|
||||||
msg[msglen++] = 0;
|
msg[msglen++] = 0;
|
||||||
/* An EDC is not required. */
|
/* An EDC is not required. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user