Subsections

VERIFY_PIN and MODIFY_PIN

The CCID specification [#!ccid_spec!#] describes a PC_to_RDR_Secure command to perform a PIN verification or PIN modification without sending the PIN to the host. The reader must have a keyboard, and optionnaly a display.

The command format is described in the PCSCv2 part 10 specifications [#!pcsc_v2_part10!#].

The bSendBuffer to pass to SCardControl() contains:

Example:

#include <winscard.h>
#include <reader.h>

LONG rv;
SCARDHANDLE hCard;
unsigned char bSendBuffer[MAX_BUFFER_SIZE];
unsigned char bRecvBuffer[MAX_BUFFER_SIZE];
DWORD verify_ioctl = 0;
DWORD modify_ioctl = 0;
PIN_VERIFY_STRUCTURE *pin_verify;

/* does the reader support PIN verification? */
rv = SCardControl(hCard, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0,
    bRecvBuffer, sizeof(bRecvBuffer), &length);

/* get the number of elements instead of the complete size */
length /= sizeof(PCSC_TLV_STRUCTURE);

pcsc_tlv = (PCSC_TLV_STRUCTURE *)bRecvBuffer;
for (i = 0; i < length; i++)
{
    if (pcsc_tlv[i].tag == FEATURE_VERIFY_PIN_DIRECT)
        verify_ioctl = pcsc_tlv[i].value;
    if (pcsc_tlv[i].tag == FEATURE_MODIFY_PIN_DIRECT)
        modify_ioctl = pcsc_tlv[i].value;
}

if (0 == verify_ioctl)
{
    printf("Reader %s does not support PIN verification\n",
        readers[reader_nb]);
    return;
}

pin_verify = (PIN_VERIFY_STRUCTURE *)bSendBuffer;

/* PC/SC v2.0.2 Part 10 PIN verification data structure */
pin_verify -> bTimerOut = 0x00;
pin_verify -> bTimerOut2 = 0x00;
pin_verify -> bmFormatString = 0x82;
pin_verify -> bmPINBlockString = 0x04;
pin_verify -> bmPINLengthFormat = 0x00;
pin_verify -> wPINMaxExtraDigit = HOST_TO_CCID_16(0x0408); /* Min Max */
pin_verify -> bEntryValidationCondition = 0x02; /* validation key pressed */
pin_verify -> bNumberMessage = 0x01;
pin_verify -> wLangId = HOST_TO_CCID_16(0x0904);
pin_verify -> bMsgIndex = 0x00;
pin_verify -> bTeoPrologue[0] = 0x00;
pin_verify -> bTeoPrologue[1] = 0x00;
pin_verify -> bTeoPrologue[2] = 0x00;
/* pin_verify -> ulDataLength = 0x00; we don't know the size yet */

/* APDU: 00 20 00 00 08 30 30 30 30 00 00 00 00 */
offset = 0;
pin_verify -> abData[offset++] = 0x00;  /* CLA */
pin_verify -> abData[offset++] = 0x20;  /* INS: VERIFY */
pin_verify -> abData[offset++] = 0x00;  /* P1 */
pin_verify -> abData[offset++] = 0x00;  /* P2 */
pin_verify -> abData[offset++] = 0x08;  /* Lc: 8 data bytes */
pin_verify -> abData[offset++] = 0x30;  /* '0' */
pin_verify -> abData[offset++] = 0x30;  /* '0' */
pin_verify -> abData[offset++] = 0x30;  /* '0' */
pin_verify -> abData[offset++] = 0x30;  /* '0' */
pin_verify -> abData[offset++] = 0x00;  /* '\0' */
pin_verify -> abData[offset++] = 0x00;  /* '\0' */
pin_verify -> abData[offset++] = 0x00;  /* '\0' */
pin_verify -> abData[offset++] = 0x00;  /* '\0' */
pin_verify -> ulDataLength = HOST_TO_CCID_32(offset);   /* APDU size */

length = sizeof(PIN_VERIFY_STRUCTURE) + offset -1;
    /* -1 because PIN_VERIFY_STRUCTURE contains the first byte of abData[] */

printf("Enter your PIN: ");
fflush(stdout);

rv = SCardControl(hCard, verify_ioctl, bSendBuffer,
    length, bRecvBuffer, sizeof(bRecvBuffer), &length);



2007-06-17