mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
(ccid_open_reader): Store the vendor ID.
(ccid_transceive_secure): New. (parse_ccid_descriptor): Workaround for an SCM reader problem.
This commit is contained in:
parent
ad5d5fce4f
commit
f0c793c5a7
@ -1,3 +1,13 @@
|
|||||||
|
2004-10-06 Werner Koch <wk@g10code.de>
|
||||||
|
|
||||||
|
* ccid-driver.c (ccid_open_reader): Store the vendor ID.
|
||||||
|
(ccid_transceive_secure): New.
|
||||||
|
(parse_ccid_descriptor): Workaround for an SCM reader problem.
|
||||||
|
|
||||||
|
2004-10-04 Werner Koch <wk@g10code.de>
|
||||||
|
|
||||||
|
* ccid-driver.c (send_escape_cmd): New.
|
||||||
|
|
||||||
2004-09-30 Werner Koch <wk@g10code.com>
|
2004-09-30 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* Makefile.am: Adjusted for gettext 0.14.
|
* Makefile.am: Adjusted for gettext 0.14.
|
||||||
|
@ -154,8 +154,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
RDR_to_PC_NotifySlotChange= 0x50,
|
RDR_to_PC_NotifySlotChange= 0x50,
|
||||||
RDR_to_PC_HardwareError = 0x51,
|
RDR_to_PC_HardwareError = 0x51,
|
||||||
@ -183,12 +181,21 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* We need to know the vendor to do some hacks. */
|
||||||
|
enum {
|
||||||
|
VENDOR_SCM = 0x04e6
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Store information on the driver's state. A pointer to such a
|
/* Store information on the driver's state. A pointer to such a
|
||||||
structure is used as handle for most functions. */
|
structure is used as handle for most functions. */
|
||||||
struct ccid_driver_s
|
struct ccid_driver_s
|
||||||
{
|
{
|
||||||
usb_dev_handle *idev;
|
usb_dev_handle *idev;
|
||||||
char *rid;
|
char *rid;
|
||||||
|
unsigned short id_vendor;
|
||||||
|
unsigned short id_product;
|
||||||
|
unsigned short bcd_device;
|
||||||
int seqno;
|
int seqno;
|
||||||
unsigned char t1_ns;
|
unsigned char t1_ns;
|
||||||
unsigned char t1_nr;
|
unsigned char t1_nr;
|
||||||
@ -251,6 +258,8 @@ parse_ccid_descriptor (ccid_driver_t handle,
|
|||||||
handle->max_ifsd = 32;
|
handle->max_ifsd = 32;
|
||||||
handle->ifsd = 0;
|
handle->ifsd = 0;
|
||||||
handle->has_pinpad = 0;
|
handle->has_pinpad = 0;
|
||||||
|
DEBUGOUT_3 ("idVendor: %04X idProduct: %04X bcdDevice: %04X\n",
|
||||||
|
handle->id_vendor, handle->id_product, handle->bcd_device);
|
||||||
if (buflen < 54 || buf[0] < 54)
|
if (buflen < 54 || buf[0] < 54)
|
||||||
{
|
{
|
||||||
DEBUGOUT ("CCID device descriptor is too short\n");
|
DEBUGOUT ("CCID device descriptor is too short\n");
|
||||||
@ -417,8 +426,25 @@ parse_ccid_descriptor (ccid_driver_t handle,
|
|||||||
"this is not available\n");
|
"this is not available\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
|
/* SCM drivers get stuck in their internal USB stack if they try to
|
||||||
|
send a frame of n*wMaxPacketSize back to us. Given that
|
||||||
|
wMaxPacketSize is 64 for these readers we set the IFSD to a value
|
||||||
|
lower than that:
|
||||||
|
64 - 10 CCID header - 4 T1frame - 2 reserved = 48 */
|
||||||
|
if (handle->id_vendor == VENDOR_SCM
|
||||||
|
/* FIXME: check whether it is the same
|
||||||
|
firmware version for all drivers. */
|
||||||
|
&& handle->bcd_device < 0x0513
|
||||||
|
&& handle->max_ifsd > 48)
|
||||||
|
{
|
||||||
|
DEBUGOUT ("enabling workaround for buggy SCM readers\n");
|
||||||
|
handle->max_ifsd = 48;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -436,7 +462,7 @@ get_escaped_usb_string (usb_dev_handle *idev, int idx,
|
|||||||
if (!idx)
|
if (!idx)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Fixme: The next line for the current Valgrid without support
|
/* Fixme: The next line is for the current Valgrid without support
|
||||||
for USB IOCTLs. */
|
for USB IOCTLs. */
|
||||||
memset (buf, 0, sizeof buf);
|
memset (buf, 0, sizeof buf);
|
||||||
|
|
||||||
@ -825,6 +851,9 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid)
|
|||||||
}
|
}
|
||||||
(*handle)->idev = idev;
|
(*handle)->idev = idev;
|
||||||
(*handle)->rid = rid;
|
(*handle)->rid = rid;
|
||||||
|
(*handle)->id_vendor = dev->descriptor.idVendor;
|
||||||
|
(*handle)->id_product = dev->descriptor.idProduct;
|
||||||
|
(*handle)->bcd_device = dev->descriptor.bcdDevice;
|
||||||
|
|
||||||
DEBUGOUT_2 ("using CCID reader %d (ID=%s)\n", readerno, rid );
|
DEBUGOUT_2 ("using CCID reader %d (ID=%s)\n", readerno, rid );
|
||||||
|
|
||||||
@ -1082,6 +1111,43 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Note that this fucntion won't return the error codes NO_CARD or
|
||||||
|
CARD_INACTIVE */
|
||||||
|
static int
|
||||||
|
send_escape_cmd (ccid_driver_t handle,
|
||||||
|
const unsigned char *data, size_t datalen)
|
||||||
|
{
|
||||||
|
int i, rc;
|
||||||
|
unsigned char msg[100];
|
||||||
|
size_t msglen;
|
||||||
|
unsigned char seqno;
|
||||||
|
|
||||||
|
if (datalen > sizeof msg - 10)
|
||||||
|
return CCID_DRIVER_ERR_INV_VALUE; /* Escape data too large. */
|
||||||
|
|
||||||
|
msg[0] = PC_to_RDR_Escape;
|
||||||
|
msg[5] = 0; /* slot */
|
||||||
|
msg[6] = seqno = handle->seqno++;
|
||||||
|
msg[7] = 0; /* RFU */
|
||||||
|
msg[8] = 0; /* RFU */
|
||||||
|
msg[9] = 0; /* RFU */
|
||||||
|
memcpy (msg+10, data, datalen);
|
||||||
|
msglen = 10 + datalen;
|
||||||
|
set_msg_len (msg, datalen);
|
||||||
|
|
||||||
|
DEBUGOUT ("sending");
|
||||||
|
for (i=0; i < msglen; i++)
|
||||||
|
DEBUGOUT_CONT_1 (" %02X", msg[i]);
|
||||||
|
DEBUGOUT_LF ();
|
||||||
|
rc = bulk_out (handle, msg, msglen);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Escape, seqno);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* experimental */
|
/* experimental */
|
||||||
int
|
int
|
||||||
ccid_poll (ccid_driver_t handle)
|
ccid_poll (ccid_driver_t handle)
|
||||||
@ -1617,10 +1683,232 @@ ccid_transceive (ccid_driver_t handle,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Send the CCID Secure command to the reader. APDU_BUF should contain the APDU template. PIN_MODE defines now the pin gets formatted:
|
||||||
|
|
||||||
|
1 := The PIN is ASCII encoded and of variable length. The
|
||||||
|
length of the PIN entered will be put into Lc by the reader.
|
||||||
|
The APDU should me made up of 4 bytes without Lc.
|
||||||
|
|
||||||
|
PINLEN_MIN and PINLEN_MAX define the limits for the pin length. 0
|
||||||
|
may be used t enable usbale defaults. PIN_PADLEN should be 0
|
||||||
|
|
||||||
|
When called with RESP and NRESP set to NULL, the function will
|
||||||
|
merely check whether the reader supports the secure command for the
|
||||||
|
given APDU and PIN_MODE. */
|
||||||
|
int
|
||||||
|
ccid_transceive_secure (ccid_driver_t handle,
|
||||||
|
const unsigned char *apdu_buf, size_t apdu_buflen,
|
||||||
|
int pin_mode, int pinlen_min, int pinlen_max,
|
||||||
|
int pin_padlen,
|
||||||
|
unsigned char *resp, size_t maxresplen, size_t *nresp)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
unsigned char send_buffer[10+259], recv_buffer[10+259];
|
||||||
|
unsigned char *msg, *tpdu, *p;
|
||||||
|
size_t msglen, tpdulen, n;
|
||||||
|
unsigned char seqno;
|
||||||
|
int i;
|
||||||
|
size_t dummy_nresp;
|
||||||
|
int testmode;
|
||||||
|
|
||||||
|
testmode = !resp && !nresp;
|
||||||
|
|
||||||
|
if (!nresp)
|
||||||
|
nresp = &dummy_nresp;
|
||||||
|
*nresp = 0;
|
||||||
|
|
||||||
|
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))
|
||||||
|
return CCID_DRIVER_ERR_NOT_SUPPORTED; /* Not yet by our code. */
|
||||||
|
else
|
||||||
|
return CCID_DRIVER_ERR_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
if (pin_mode != 1)
|
||||||
|
return CCID_DRIVER_ERR_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
if (pin_padlen != 0)
|
||||||
|
return CCID_DRIVER_ERR_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
if (!pinlen_min)
|
||||||
|
pinlen_min = 1;
|
||||||
|
if (!pinlen_max)
|
||||||
|
pinlen_max = 25;
|
||||||
|
|
||||||
|
/* Note that the 25 is the maximum value the SPR532 allows. */
|
||||||
|
if (pinlen_min < 1 || pinlen_min > 25
|
||||||
|
|| pinlen_max < 1 || pinlen_max > 25
|
||||||
|
|| pinlen_min > pinlen_max)
|
||||||
|
return CCID_DRIVER_ERR_INV_VALUE;
|
||||||
|
|
||||||
|
/* We have only tested this with an SCM reader so better don't risk
|
||||||
|
anything and do not allow the use with other readers. */
|
||||||
|
if (handle->id_vendor != VENDOR_SCM)
|
||||||
|
return CCID_DRIVER_ERR_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
if (testmode)
|
||||||
|
return 0; /* Success */
|
||||||
|
|
||||||
|
msg = send_buffer;
|
||||||
|
if (handle->id_vendor == VENDOR_SCM)
|
||||||
|
{
|
||||||
|
DEBUGOUT ("sending escape sequence to switch to a case 1 APDU\n");
|
||||||
|
rc = send_escape_cmd (handle, "\x80\x02\x00", 3);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg[0] = PC_to_RDR_Secure;
|
||||||
|
msg[5] = 0; /* slot */
|
||||||
|
msg[6] = seqno = handle->seqno++;
|
||||||
|
msg[7] = 4; /* bBWI */
|
||||||
|
msg[8] = 0; /* RFU */
|
||||||
|
msg[9] = 0; /* RFU */
|
||||||
|
msg[10] = 0; /* Perform PIN verification. */
|
||||||
|
msg[11] = 0; /* Timeout in seconds. */
|
||||||
|
msg[12] = 0x82; /* bmFormatString: Byte, pos=0, left, ASCII. */
|
||||||
|
if (handle->id_vendor == VENDOR_SCM)
|
||||||
|
{
|
||||||
|
/* For the SPR532 the next 2 bytes need to be zero. We do this
|
||||||
|
for all SCM product. Kudos to to Martin Paljak for this
|
||||||
|
hint. */
|
||||||
|
msg[13] = msg[14] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg[13] = 0x00; /* bmPINBlockString:
|
||||||
|
0 bits of pin length to insert.
|
||||||
|
0 bytes of PIN block size. */
|
||||||
|
msg[14] = 0x00; /* bmPINLengthFormat:
|
||||||
|
Units are bytes, position is 0. */
|
||||||
|
}
|
||||||
|
msg[15] = pinlen_min; /* wPINMaxExtraDigit-Minimum. */
|
||||||
|
msg[16] = pinlen_max; /* wPINMaxExtraDigit-Maximum. */
|
||||||
|
msg[17] = 0x02; /* bEntryValidationCondition:
|
||||||
|
Validation key pressed */
|
||||||
|
if (pinlen_min && pinlen_max && pinlen_min == pinlen_max)
|
||||||
|
msg[17] |= 0x01; /* Max size reached. */
|
||||||
|
msg[18] = 0xff; /* bNumberMessage: Default. */
|
||||||
|
msg[19] = 0x04; /* wLangId-High. */
|
||||||
|
msg[20] = 0x09; /* wLangId-Low: English FIXME: use the first entry. */
|
||||||
|
msg[21] = 0; /* bMsgIndex. */
|
||||||
|
/* bTeoProlog follows: */
|
||||||
|
msg[22] = handle->nonnull_nad? ((1 << 4) | 0): 0;
|
||||||
|
msg[23] = ((handle->t1_ns & 1) << 6); /* I-block */
|
||||||
|
msg[24] = 4; /* apdulen. */
|
||||||
|
/* APDU follows: */
|
||||||
|
msg[25] = apdu_buf[0]; /* CLA */
|
||||||
|
msg[26] = apdu_buf[1]; /* INS */
|
||||||
|
msg[27] = apdu_buf[2]; /* P1 */
|
||||||
|
msg[28] = apdu_buf[3]; /* P2 */
|
||||||
|
msglen = 29;
|
||||||
|
set_msg_len (msg, msglen - 10);
|
||||||
|
|
||||||
|
DEBUGOUT ("sending");
|
||||||
|
for (i=0; i < msglen; i++)
|
||||||
|
DEBUGOUT_CONT_1 (" %02X", msg[i]);
|
||||||
|
DEBUGOUT_LF ();
|
||||||
|
|
||||||
|
rc = bulk_out (handle, msg, msglen);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
msg = recv_buffer;
|
||||||
|
rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
|
||||||
|
RDR_to_PC_DataBlock, seqno);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
tpdu = msg + 10;
|
||||||
|
tpdulen = msglen - 10;
|
||||||
|
|
||||||
|
if (tpdulen < 4)
|
||||||
|
{
|
||||||
|
usb_clear_halt (handle->idev, 0x82);
|
||||||
|
return CCID_DRIVER_ERR_ABORTED;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_T1
|
||||||
|
fprintf (stderr, "T1: got %c-block seq=%d err=%d\n",
|
||||||
|
((msg[11] & 0xc0) == 0x80)? 'R' :
|
||||||
|
(msg[11] & 0x80)? 'S' : 'I',
|
||||||
|
((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)),
|
||||||
|
((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!(tpdu[1] & 0x80))
|
||||||
|
{ /* This is an I-block. */
|
||||||
|
/* Last block sent was successful. */
|
||||||
|
handle->t1_ns ^= 1;
|
||||||
|
|
||||||
|
if (!!(tpdu[1] & 0x40) != handle->t1_nr)
|
||||||
|
{ /* Reponse does not match our sequence number. */
|
||||||
|
DEBUGOUT ("I-block with wrong seqno received\n");
|
||||||
|
return CCID_DRIVER_ERR_CARD_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle->t1_nr ^= 1;
|
||||||
|
|
||||||
|
p = tpdu + 3; /* Skip the prologue field. */
|
||||||
|
n = tpdulen - 3 - 1; /* Strip the epilogue field. */
|
||||||
|
/* fixme: verify the checksum. */
|
||||||
|
if (resp)
|
||||||
|
{
|
||||||
|
if (n > maxresplen)
|
||||||
|
{
|
||||||
|
DEBUGOUT_2 ("provided buffer too short for received data "
|
||||||
|
"(%u/%u)\n",
|
||||||
|
(unsigned int)n, (unsigned int)maxresplen);
|
||||||
|
return CCID_DRIVER_ERR_INV_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (resp, p, n);
|
||||||
|
resp += n;
|
||||||
|
*nresp += n;
|
||||||
|
maxresplen -= n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(tpdu[1] & 0x20))
|
||||||
|
return 0; /* No chaining requested - ready. */
|
||||||
|
|
||||||
|
DEBUGOUT ("chaining requested but not supported for Secure operation\n");
|
||||||
|
return CCID_DRIVER_ERR_CARD_IO_ERROR;
|
||||||
|
}
|
||||||
|
else if ((tpdu[1] & 0xc0) == 0x80)
|
||||||
|
{ /* This is a R-block. */
|
||||||
|
if ( (tpdu[1] & 0x0f))
|
||||||
|
{ /* Error: repeat last block */
|
||||||
|
DEBUGOUT ("No retries supported for Secure operation\n");
|
||||||
|
return CCID_DRIVER_ERR_CARD_IO_ERROR;
|
||||||
|
}
|
||||||
|
else if (!!(tpdu[1] & 0x40) == handle->t1_ns)
|
||||||
|
{ /* Reponse does not match our sequence number. */
|
||||||
|
DEBUGOUT ("R-block with wrong seqno received on more bit\n");
|
||||||
|
return CCID_DRIVER_ERR_CARD_IO_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* Send next chunk. */
|
||||||
|
DEBUGOUT ("chaining not supported on Secure operation\n");
|
||||||
|
return CCID_DRIVER_ERR_CARD_IO_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* This is a S-block. */
|
||||||
|
DEBUGOUT_2 ("T1 S-block %s received cmd=%d for Secure operation\n",
|
||||||
|
(tpdu[1] & 0x20)? "response": "request",
|
||||||
|
(tpdu[1] & 0x1f));
|
||||||
|
return CCID_DRIVER_ERR_CARD_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_error (int err)
|
print_error (int err)
|
||||||
{
|
{
|
||||||
@ -1682,6 +1970,9 @@ main (int argc, char **argv)
|
|||||||
unsigned int slotstat;
|
unsigned int slotstat;
|
||||||
unsigned char result[512];
|
unsigned char result[512];
|
||||||
size_t resultlen;
|
size_t resultlen;
|
||||||
|
int no_pinpad = 0;
|
||||||
|
int verify_123456 = 0;
|
||||||
|
int did_verify = 0;
|
||||||
|
|
||||||
if (argc)
|
if (argc)
|
||||||
{
|
{
|
||||||
@ -1706,6 +1997,16 @@ main (int argc, char **argv)
|
|||||||
ccid_set_debug_level (1);
|
ccid_set_debug_level (1);
|
||||||
argc--; argv++;
|
argc--; argv++;
|
||||||
}
|
}
|
||||||
|
else if ( !strcmp (*argv, "--no-pinpad"))
|
||||||
|
{
|
||||||
|
no_pinpad = 1;
|
||||||
|
argc--; argv++;
|
||||||
|
}
|
||||||
|
else if ( !strcmp (*argv, "--verify-123456"))
|
||||||
|
{
|
||||||
|
verify_123456 = 1;
|
||||||
|
argc--; argv++;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1755,28 +2056,55 @@ main (int argc, char **argv)
|
|||||||
print_result (rc, result, resultlen);
|
print_result (rc, result, resultlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
ccid_poll (ccid);
|
if (!no_pinpad)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/* if (!ccid->has_pinpad) */
|
if (!no_pinpad)
|
||||||
/* { */
|
{
|
||||||
/* fputs ("verifying that CHV1 is 123456....\n", stderr); */
|
static unsigned char apdu[] = { 0, 0x20, 0, 0x81 };
|
||||||
/* { */
|
|
||||||
/* static unsigned char apdu[] = {0, 0x20, 0, 0x81, */
|
|
||||||
/* 6, '1','2','3','4','5','6'}; */
|
if (ccid_transceive_secure (ccid,
|
||||||
/* rc = ccid_transceive (ccid, apdu, sizeof apdu, */
|
apdu, sizeof apdu,
|
||||||
/* result, sizeof result, &resultlen); */
|
1, 0, 0, 0,
|
||||||
/* print_result (rc, result, resultlen); */
|
NULL, 0, NULL))
|
||||||
/* } */
|
fputs ("can't verify using a PIN-Pad reader\n", stderr);
|
||||||
/* } */
|
else
|
||||||
/* else */
|
{
|
||||||
/* { */
|
fputs ("verifying CHV1 using the PINPad ....\n", stderr);
|
||||||
/* fputs ("verifying CHV1 using the PINPad ....\n", stderr); */
|
|
||||||
/* { */
|
rc = ccid_transceive_secure (ccid,
|
||||||
/* rc = ccid_secure_transceive (ccid, */
|
apdu, sizeof apdu,
|
||||||
/* result, sizeof result, &resultlen); */
|
1, 0, 0, 0,
|
||||||
/* print_result (rc, result, resultlen); */
|
result, sizeof result, &resultlen);
|
||||||
/* } */
|
print_result (rc, result, resultlen);
|
||||||
/* } */
|
did_verify = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verify_123456 && !did_verify)
|
||||||
|
{
|
||||||
|
fputs ("verifying that CHV1 is 123456....\n", stderr);
|
||||||
|
{
|
||||||
|
static unsigned char apdu[] = {0, 0x20, 0, 0x81,
|
||||||
|
6, '1','2','3','4','5','6'};
|
||||||
|
rc = ccid_transceive (ccid, apdu, sizeof apdu,
|
||||||
|
result, sizeof result, &resultlen);
|
||||||
|
print_result (rc, result, resultlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rc)
|
||||||
|
{
|
||||||
|
fputs ("getting OpenPGP DO 0x5E ....\n", stderr);
|
||||||
|
{
|
||||||
|
static unsigned char apdu[] = { 0, 0xCA, 0, 0x5E, 254 };
|
||||||
|
rc = ccid_transceive (ccid, apdu, sizeof apdu,
|
||||||
|
result, sizeof result, &resultlen);
|
||||||
|
print_result (rc, result, resultlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ccid_close_reader (ccid);
|
ccid_close_reader (ccid);
|
||||||
|
|
||||||
|
@ -86,6 +86,11 @@ int ccid_slot_status (ccid_driver_t handle, int *statusbits);
|
|||||||
int ccid_transceive (ccid_driver_t handle,
|
int ccid_transceive (ccid_driver_t handle,
|
||||||
const unsigned char *apdu, size_t apdulen,
|
const unsigned char *apdu, size_t apdulen,
|
||||||
unsigned char *resp, size_t maxresplen, size_t *nresp);
|
unsigned char *resp, size_t maxresplen, size_t *nresp);
|
||||||
|
int ccid_transceive_secure (ccid_driver_t handle,
|
||||||
|
const unsigned char *apdu, size_t apdulen,
|
||||||
|
int pin_mode,
|
||||||
|
int pinlen_min, int pinlen_max, int pin_padlen,
|
||||||
|
unsigned char *resp, size_t maxresplen, size_t *nresp);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user