added support for pinpad. doesn't work atm, somehow abPINApdu is wrong.

git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@16 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
frankmorgner
2010-01-10 23:09:11 +00:00
parent e30640e43d
commit 8d5b7f8744

View File

@@ -69,7 +69,6 @@ typedef struct {
} __attribute__ ((packed)) abProtocolDataStructure_T1_t; } __attribute__ ((packed)) abProtocolDataStructure_T1_t;
typedef struct { typedef struct {
__u8 bPINOperation;
__u8 bTimeOut; __u8 bTimeOut;
__u8 bmFormatString; __u8 bmFormatString;
__u8 bmPINBlockString; __u8 bmPINBlockString;
@@ -81,7 +80,25 @@ typedef struct {
__u8 bMsgIndex; __u8 bMsgIndex;
__u8 bTeoPrologue1; __u8 bTeoPrologue1;
__le16 bTeoPrologue2; __le16 bTeoPrologue2;
} __attribute__ ((packed)) abPINOperationDataStucture } __attribute__ ((packed)) abPINDataStucture_Verification_t;
typedef struct {
__u8 bTimeOut;
__u8 bmFormatString;
__u8 bmPINBlockString;
__u8 bmPINLengthFormat;
__u8 bInsertionOffsetOld;
__u8 bInsertionOffsetNew;
__le16 wPINMaxExtraDigit;
__u8 bConfirmPIN;
__u8 bEntryValidationCondition;
__u8 bNumberMessage;
__le16 wLangId;
__u8 bMsgIndex1;
__u8 bMsgIndex2;
__u8 bMsgIndex3;
__u8 bTeoPrologue1;
__le16 bTeoPrologue2;
} __attribute__ ((packed)) abPINDataStucture_Modification_t;
typedef struct { typedef struct {
__u8 bMessageType; __u8 bMessageType;
@@ -221,12 +238,12 @@ ccid_desc = {
.bClassGetResponse = 0xFF, .bClassGetResponse = 0xFF,
.bclassEnvelope = 0xFF, .bclassEnvelope = 0xFF,
.wLcdLayout = __constant_cpu_to_le16( .wLcdLayout = __constant_cpu_to_le16(
0), //0),
//0xFF00| // Number of lines for the LCD display 0xFF00| // Number of lines for the LCD display
//0x00FF), // Number of characters per line 0x00FF), // Number of characters per line
.bPINSupport = 0, // PIN Modification supported //.bPINSupport = 0,
//.bPINSupport = 0x1| // PIN Verification supported .bPINSupport = 0x1| // PIN Verification supported
//0x2, // PIN Modification supported 0x2, // PIN Modification supported
.bMaxCCIDBusySlots = 0x01, .bMaxCCIDBusySlots = 0x01,
}; };
@@ -378,12 +395,12 @@ __u8 get_bStatus(LONG pcsc_result)
bStatus = 1; bStatus = 1;
} else { } else {
// active // active
fprintf(stderr, "card active\n"); /*fprintf(stderr, "card active\n");*/
bStatus = 0; bStatus = 0;
} }
} else { } else {
// absent // absent
fprintf(stderr, "card absent\n"); /*fprintf(stderr, "card absent\n");*/
bStatus = 2; bStatus = 2;
if (hcard != 0) { if (hcard != 0) {
pcsc_result = SCardDisconnect(hcard, SCARD_UNPOWER_CARD); pcsc_result = SCardDisconnect(hcard, SCARD_UNPOWER_CARD);
@@ -621,16 +638,232 @@ perform_PC_to_RDR_GetParamters(const PC_to_RDR_GetParameters_t request,
pcsc_result, abProtocolDataStructure); pcsc_result, abProtocolDataStructure);
} }
//RDR_to_PC_Parameters_t RDR_to_PC_DataBlock_t
//perform_PC_to_RDR_Secure(const PC_to_RDR_Secure_t request, perform_PC_to_RDR_Secure(const PC_to_RDR_Secure_t request,
//__u8* abData) const __u8* abData, __u8** abDataOut)
//{ {
//if ( request.bMessageType != 0x69 || /* only short APDUs supported so Lc is always the fiths byte */
//request.bSlot != 0 || if ( request.bMessageType != 0x69 ||
//request.wLevelParameter != __constant_cpu_to_le16(0)) request.bSlot != 0)
//fprintf(stderr, "warning: malformed PC_to_RDR_Secure\n"); fprintf(stderr, "warning: malformed PC_to_RDR_Secure\n");
//} if (request.wLevelParameter != __constant_cpu_to_le16(0)) {
fprintf(stderr, "warning: Only APDUs, that begin and end with this command are supported.\n");
return get_RDR_to_PC_DataBlock(request.bSlot, request.bSeq,
SCARD_E_READER_UNSUPPORTED, __constant_cpu_to_le32(0));
}
__u8 PINMin, PINMax, bmPINLengthFormat, bmPINBlockString, bmFormatString;
__u8 *abPINApdu;
uint32_t apdulen;
abPINDataStucture_Verification_t *verify = NULL;
abPINDataStucture_Modification_t *modify = NULL;
switch (*abData) { // first byte of abData is bPINOperation
case 0x00:
// PIN Verification
verify = (abPINDataStucture_Verification_t *)
(abData + sizeof(__u8));
PINMin = verify->wPINMaxExtraDigit >> 8;
PINMax = verify->wPINMaxExtraDigit & 0x00ff;
bmPINLengthFormat = verify->bmPINLengthFormat;
bmPINBlockString = verify->bmPINBlockString;
bmFormatString = verify->bmFormatString;
abPINApdu = (__u8*) (verify + sizeof(*verify));
apdulen = __le32_to_cpu(request.dwLength) - sizeof(*verify);
break;
case 0x01:
// PIN Modification
modify = (abPINDataStucture_Modification_t *)
(abData + sizeof(__u8));
PINMin = modify->wPINMaxExtraDigit >> 8;
PINMax = modify->wPINMaxExtraDigit & 0x00ff;
bmPINLengthFormat = modify->bmPINLengthFormat;
bmPINBlockString = modify->bmPINBlockString;
bmFormatString = modify->bmFormatString;
abPINApdu = (__u8*) (modify + sizeof(*modify));
apdulen = __le32_to_cpu(request.dwLength) - sizeof(*modify);
break;
case 0x04:
// Cancel PIN function
default:
fprintf(stderr, "warning: unknown pin operation\n");
return get_RDR_to_PC_DataBlock(request.bSlot, request.bSeq,
SCARD_E_READER_UNSUPPORTED, __constant_cpu_to_le32(0));
}
printf("verify=%d abPINApdu=%d sizoeof(verify)=%d\n", verify, abPINApdu, sizeof(*verify));
printf("%x %x %x %x %x %x\n", abPINApdu[0], abPINApdu[1], abPINApdu[2], abPINApdu[3], abPINApdu[4], abPINApdu[5]);
// copy the apdu
__u8 *apdu = (__u8*) malloc(apdulen);
if (!apdu) {
return get_RDR_to_PC_DataBlock(request.bSlot, request.bSeq,
SCARD_E_NO_MEMORY, __constant_cpu_to_le32(0));
}
memcpy(apdu, abPINApdu, apdulen);
// TODO
char *pin = "123456";
__u8 *p;
/* if system units are bytes or bits */
uint8_t bytes = bmFormatString >> 7;
/* PIN position after format in the APDU command (relative to the first
* data after Lc). The position is based on the system units type
* indicator (maximum1111 for fifteen system units */
uint8_t pos = (bmFormatString >> 3) & 0xf;
/* Right or left justify data */
uint8_t right = (bmFormatString >> 2) & 1;
/* Bit wise for the PIN format type */
uint8_t type = bmFormatString & 2;
uint8_t pinlen = strnlen(pin, PINMax + 1);
if (pinlen > PINMax) {
fprintf(stderr, "warning: PIN was too long, "
"should be between %d and %d\n", PINMin, PINMax);
return get_RDR_to_PC_DataBlock(request.bSlot, request.bSeq,
SCARD_F_INTERNAL_ERROR, __constant_cpu_to_le32(0));
}
/* Size in bits of the PIN length inserted in the APDU command. */
uint8_t lenlen = bmPINBlockString >> 4;
/* PIN block size in bytes after justification and formatting. */
uint8_t blocksize = bmPINBlockString & 0xf;
/* PIN length position in the APDU command */
uint8_t lenshift = bmPINLengthFormat & 0xf;
if (lenlen) {
/* write PIN Length */
if (lenlen == 8) {
if (bytes) {
p = apdu + 5 + lenshift;
} else {
if (lenshift == 0)
p = apdu + 5;
if (lenshift == 8)
p = apdu + 5 + 1;
else {
fprintf(stderr, "warning: PIN Block too complex, aborting\n");
fprintf(stderr, "%s:%d\n", __FILE__, __LINE__);
return get_RDR_to_PC_DataBlock(request.bSlot, request.bSeq,
SCARD_F_INTERNAL_ERROR,
__constant_cpu_to_le32(0));
}
}
*p = pinlen;
}
fprintf(stderr, "warning: PIN Block too complex, aborting\n");
fprintf(stderr, "%s:%d\n", __FILE__, __LINE__);
return get_RDR_to_PC_DataBlock(request.bSlot, request.bSeq,
SCARD_F_INTERNAL_ERROR, __constant_cpu_to_le32(0));
}
uint8_t justify;
if (right)
justify = blocksize - pinlen;
else
justify = 0;
if (bytes) {
p = apdu + 5 + pos + justify;
} else {
if (pos == 0)
p = apdu + 5 + justify;
else if (pos == 8)
p = apdu + 5 + 1 + justify;
else {
fprintf(stderr, "warning: PIN Block too complex, aborting\n");
fprintf(stderr, "%s:%d\n", __FILE__, __LINE__);
fprintf(stderr, "%x\n", bmFormatString);
return get_RDR_to_PC_DataBlock(request.bSlot, request.bSeq,
SCARD_F_INTERNAL_ERROR,
__constant_cpu_to_le32(0));
}
}
while (*pin) {
uint8_t c;
switch (type) {
case 0:
// binary
switch (*pin) {
case '0':
c = 0x00;
break;
case '1':
c = 0x01;
break;
case '2':
c = 0x02;
break;
case '3':
c = 0x03;
break;
case '4':
c = 0x04;
break;
case '5':
c = 0x05;
break;
case '6':
c = 0x06;
break;
case '7':
c = 0x07;
break;
case '8':
c = 0x08;
break;
case '9':
c = 0x09;
break;
default:
fprintf(stderr, "warning: PIN character %c not supported, aborting", *pin);
return get_RDR_to_PC_DataBlock(request.bSlot,
request.bSeq, SCARD_F_INTERNAL_ERROR,
__constant_cpu_to_le32(0));
}
break;
case 1:
// BCD
fprintf(stderr, "warning: BCD format not supported, aborting");
return get_RDR_to_PC_DataBlock(request.bSlot, request.bSeq,
SCARD_F_INTERNAL_ERROR, __constant_cpu_to_le32(0));
case 2:
// ASCII
c = *pin;
break;
default:
fprintf(stderr, "warning: unknown formatting, aborting");
return get_RDR_to_PC_DataBlock(request.bSlot, request.bSeq,
SCARD_F_INTERNAL_ERROR, __constant_cpu_to_le32(0));
}
*p = c;
p++;
pin++;
}
printf("%x %x %x %x %x %x\n", apdu[0], apdu[1], apdu[2], apdu[3], apdu[4], apdu[5]);
DWORD dwRecvLength = MAX_BUFFER_SIZE;
*abDataOut = (__u8 *) malloc(dwRecvLength);
if (*abDataOut == NULL) {
return get_RDR_to_PC_DataBlock(request.bSlot, request.bSeq,
SCARD_E_NO_MEMORY, __constant_cpu_to_le32(0));
}
LPCSCARD_IO_REQUEST pioSendPci;
if (dwActiveProtocol == SCARD_PROTOCOL_T0)
pioSendPci = SCARD_PCI_T0;
else
pioSendPci = SCARD_PCI_T1;
int pcsc_result = SCardTransmit(hcard, pioSendPci, apdu, apdulen, NULL,
*abDataOut, &dwRecvLength);
return get_RDR_to_PC_DataBlock(request.bSlot, request.bSeq,
pcsc_result, __cpu_to_le32(dwRecvLength));
}
RDR_to_PC_NotifySlotChange_t RDR_to_PC_NotifySlotChange_t
get_RDR_to_PC_NotifySlotChange () get_RDR_to_PC_NotifySlotChange ()
@@ -744,7 +977,7 @@ int parse_ccid(const __u8* inbuf, __u8** outbuf) {
} break; } break;
case 0x65: case 0x65:
{ fprintf(stderr, "PC_to_RDR_GetSlotStatus\n"); { /*fprintf(stderr, "PC_to_RDR_GetSlotStatus\n");*/
PC_to_RDR_GetSlotStatus_t input = PC_to_RDR_GetSlotStatus_t input =
*(PC_to_RDR_GetSlotStatus_t*) inbuf; *(PC_to_RDR_GetSlotStatus_t*) inbuf;
@@ -809,6 +1042,29 @@ int parse_ccid(const __u8* inbuf, __u8** outbuf) {
free(abProtocolDataStructure); free(abProtocolDataStructure);
} break; } break;
case 0x69:
{ fprintf(stderr, "PC_to_RDR_Secure\n");
__u8* rapdu;
PC_to_RDR_Secure_t input = *(PC_to_RDR_Secure_t *) inbuf;
RDR_to_PC_DataBlock_t output =
perform_PC_to_RDR_Secure(input, inbuf + sizeof input,
&rapdu);
result = sizeof output + __le32_to_cpu(output.dwLength);
*outbuf = realloc(*outbuf, result);
if (*outbuf == NULL) {
free(rapdu);
result = -1;
break;
}
memcpy(*outbuf, &output, sizeof output);
memcpy(*outbuf + sizeof output, rapdu,
__le32_to_cpu(output.dwLength));
free(rapdu);
} break;
default: default:
error: error:
{ fprintf(stderr, "unknown ccid command: 0x%4X\n", *inbuf); { fprintf(stderr, "unknown ccid command: 0x%4X\n", *inbuf);
@@ -886,6 +1142,8 @@ int parse_ccid_control(struct usb_ctrlrequest *setup, __u8 **outbuf) {
__le32 drate = ccid_desc.dwDataRate; __le32 drate = ccid_desc.dwDataRate;
memcpy(*outbuf, &drate, sizeof (__le32)); memcpy(*outbuf, &drate, sizeof (__le32));
} break; } break;
default:
printf("unknown status setup->bRequest == %d", setup->bRequest);
} }
return result; return result;