supporting only one slot due to new opensc limitations
git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@386 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
210
ccid/src/ccid.c
210
ccid/src/ccid.c
@@ -45,8 +45,7 @@ static size_t ef_cardaccess_length = 0;
|
||||
#endif
|
||||
|
||||
static sc_context_t *ctx = NULL;
|
||||
#define SC_MAX_SLOTS 1
|
||||
static sc_card_t *card_in_slot[SC_MAX_SLOTS];
|
||||
static sc_card_t *card = NULL;
|
||||
static sc_reader_t *reader;
|
||||
|
||||
struct ccid_class_descriptor
|
||||
@@ -54,7 +53,7 @@ ccid_desc = {
|
||||
.bLength = sizeof ccid_desc,
|
||||
.bDescriptorType = 0x21,
|
||||
.bcdCCID = __constant_cpu_to_le16(0x0110),
|
||||
.bMaxSlotIndex = SC_MAX_SLOTS,
|
||||
.bMaxSlotIndex = 1,
|
||||
.bVoltageSupport = 0x01, // 5.0V
|
||||
.dwProtocols = __constant_cpu_to_le32(
|
||||
0x01| // T=0
|
||||
@@ -108,16 +107,16 @@ detect_card_presence(void)
|
||||
sc_result = sc_detect_card_presence(reader);
|
||||
|
||||
if (sc_result == 0
|
||||
&& card_in_slot[0]) {
|
||||
sc_disconnect_card(card_in_slot[0]);
|
||||
&& card) {
|
||||
sc_disconnect_card(card);
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Card removed from slot 0");
|
||||
}
|
||||
if (sc_result & SC_READER_CARD_CHANGED) {
|
||||
sc_disconnect_card(card_in_slot[0]);
|
||||
sc_disconnect_card(card);
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Card exchanged in slot 0");
|
||||
}
|
||||
if (sc_result & SC_READER_CARD_PRESENT
|
||||
&& !card_in_slot[0]) {
|
||||
&& !card) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unused card in slot 0");
|
||||
}
|
||||
|
||||
@@ -129,9 +128,6 @@ int ccid_initialize(int reader_id, const char *cdriver, int verbose)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof card_in_slot/sizeof *card_in_slot; i++)
|
||||
card_in_slot[i] = NULL;
|
||||
|
||||
i = initialize(reader_id, cdriver, verbose, &ctx, &reader);
|
||||
if (i < 0)
|
||||
return i;
|
||||
@@ -153,10 +149,8 @@ int ccid_initialize(int reader_id, const char *cdriver, int verbose)
|
||||
void ccid_shutdown()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < sizeof card_in_slot/sizeof *card_in_slot; i++) {
|
||||
if (card_in_slot[i]) {
|
||||
sc_disconnect_card(card_in_slot[i]);
|
||||
}
|
||||
if (card) {
|
||||
sc_disconnect_card(card);
|
||||
}
|
||||
if (ctx)
|
||||
sc_release_context(ctx);
|
||||
@@ -176,7 +170,7 @@ static int get_rapdu(sc_apdu_t *apdu, size_t slot, __u8 **buf, size_t *resplen)
|
||||
{
|
||||
int sc_result;
|
||||
|
||||
if (!apdu || !buf || !resplen || slot >= sizeof card_in_slot/sizeof *card_in_slot) {
|
||||
if (!apdu || !buf || !resplen) {
|
||||
sc_result = SC_ERROR_INVALID_ARGUMENTS;
|
||||
goto err;
|
||||
}
|
||||
@@ -191,9 +185,9 @@ static int get_rapdu(sc_apdu_t *apdu, size_t slot, __u8 **buf, size_t *resplen)
|
||||
*buf = apdu->resp;
|
||||
|
||||
#ifdef WITH_PACE
|
||||
sc_result = sm_transmit_apdu(&sctx, card_in_slot[slot], apdu);
|
||||
sc_result = sm_transmit_apdu(&sctx, card, apdu);
|
||||
#else
|
||||
sc_result = sc_transmit_apdu(&sctx, card_in_slot[slot], apdu);
|
||||
sc_result = sc_transmit_apdu(card, apdu);
|
||||
#endif
|
||||
if (sc_result < 0) {
|
||||
goto err;
|
||||
@@ -256,7 +250,7 @@ static __u8 get_bStatus(int sc_result, __u8 bSlot)
|
||||
if (sc_result < 0) {
|
||||
if (flags & SC_READER_CARD_PRESENT) {
|
||||
if (flags & SC_READER_CARD_CHANGED
|
||||
|| (card_in_slot[bSlot])) {
|
||||
|| card) {
|
||||
/*sc_debug(ctx, SC_LOG_DEBUG_NORMAL, SC_LOG_DEBUG_NORMAL, "error inactive");*/
|
||||
bstatus = CCID_BSTATUS_ERROR_INACTIVE;
|
||||
} else {
|
||||
@@ -269,8 +263,8 @@ static __u8 get_bStatus(int sc_result, __u8 bSlot)
|
||||
}
|
||||
} else {
|
||||
if (flags & SC_READER_CARD_PRESENT) {
|
||||
if (flags & SC_READER_CARD_CHANGED || (
|
||||
card_in_slot[bSlot])) {
|
||||
if (flags & SC_READER_CARD_CHANGED
|
||||
|| card) {
|
||||
/*sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "ok inactive");*/
|
||||
bstatus = CCID_BSTATUS_OK_INACTIVE;
|
||||
} else {
|
||||
@@ -397,31 +391,24 @@ perform_PC_to_RDR_IccPowerOn(const __u8 *in, size_t inlen, __u8 **out, size_t *o
|
||||
request->abRFU != 0)
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "warning: malformed PC_to_RDR_IccPowerOn");
|
||||
|
||||
if (request->bSlot < sizeof card_in_slot/sizeof *card_in_slot) {
|
||||
if (card_in_slot[request->bSlot]) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Card is already powered on.");
|
||||
/*sc_reset(card_in_slot[request->bSlot], 0);*/
|
||||
/*sc_disconnect_card(card_in_slot[request->bSlot]);*/
|
||||
} else {
|
||||
sc_result = sc_connect_card(reader,
|
||||
&card_in_slot[request->bSlot]);
|
||||
#ifdef BUERGERCLIENT_WORKAROUND
|
||||
if (sc_result >= 0) {
|
||||
if (get_ef_card_access(card_in_slot[request->bSlot],
|
||||
(u8 **) &ef_cardaccess, &ef_cardaccess_length) < 0) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Could not get EF.CardAccess.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (card) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Card is already powered on.");
|
||||
sc_result = SC_SUCCESS;
|
||||
} else {
|
||||
sc_result = SC_ERROR_INVALID_DATA;
|
||||
sc_result = sc_connect_card(reader, &card);
|
||||
#ifdef BUERGERCLIENT_WORKAROUND
|
||||
if (sc_result >= 0) {
|
||||
if (get_ef_card_access(card,
|
||||
(u8 **) &ef_cardaccess, &ef_cardaccess_length) < 0) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Could not get EF.CardAccess.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (sc_result >= 0) {
|
||||
return get_RDR_to_PC_SlotStatus(request->bSlot, request->bSeq,
|
||||
sc_result, out, outlen, card_in_slot[request->bSlot]->atr,
|
||||
card_in_slot[request->bSlot]->atr_len);
|
||||
sc_result, out, outlen, card->atr, card->atr_len);
|
||||
} else {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Returning default status package.");
|
||||
return get_RDR_to_PC_SlotStatus(request->bSlot, request->bSeq,
|
||||
@@ -447,12 +434,8 @@ perform_PC_to_RDR_IccPowerOff(const __u8 *in, size_t inlen, __u8 **out, size_t *
|
||||
request->abRFU2 != 0)
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "warning: malformed PC_to_RDR_IccPowerOff");
|
||||
|
||||
if (request->bSlot > sizeof card_in_slot/sizeof *card_in_slot)
|
||||
sc_result = SC_ERROR_INVALID_DATA;
|
||||
else {
|
||||
sc_reset(card_in_slot[request->bSlot], 1);
|
||||
sc_result = sc_disconnect_card(card_in_slot[request->bSlot]);
|
||||
}
|
||||
sc_reset(card, 1);
|
||||
sc_result = sc_disconnect_card(card);
|
||||
|
||||
return get_RDR_to_PC_SlotStatus(request->bSlot, request->bSeq, sc_result,
|
||||
out, outlen, NULL, 0);
|
||||
@@ -478,18 +461,14 @@ perform_PC_to_RDR_XfrBlock(const u8 *in, size_t inlen, __u8** out, size_t *outle
|
||||
request->bBWI != 0)
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "malformed PC_to_RDR_XfrBlock, will continue anyway");
|
||||
|
||||
if (request->bSlot > sizeof card_in_slot/sizeof *card_in_slot)
|
||||
sc_result = SC_ERROR_INVALID_DATA;
|
||||
else {
|
||||
sc_result = build_apdu(ctx, abDataIn, __le32_to_cpu(request->dwLength),
|
||||
&apdu);
|
||||
if (sc_result >= 0)
|
||||
sc_result = get_rapdu(&apdu, request->bSlot, &abDataOut,
|
||||
&abDataOutLen);
|
||||
else
|
||||
bin_log(ctx, SC_LOG_DEBUG_VERBOSE, "Invalid APDU", abDataIn,
|
||||
__le32_to_cpu(request->dwLength));
|
||||
}
|
||||
sc_result = build_apdu(ctx, abDataIn, __le32_to_cpu(request->dwLength),
|
||||
&apdu);
|
||||
if (sc_result >= 0)
|
||||
sc_result = get_rapdu(&apdu, request->bSlot, &abDataOut,
|
||||
&abDataOutLen);
|
||||
else
|
||||
bin_log(ctx, SC_LOG_DEBUG_VERBOSE, "Invalid APDU", abDataIn,
|
||||
__le32_to_cpu(request->dwLength));
|
||||
|
||||
sc_result = get_RDR_to_PC_DataBlock(request->bSlot, request->bSeq, sc_result,
|
||||
out, outlen, abDataOut, abDataOutLen);
|
||||
@@ -518,65 +497,63 @@ perform_PC_to_RDR_GetParamters(const __u8 *in, size_t inlen, __u8** out, size_t
|
||||
request->dwLength != __constant_cpu_to_le32(0))
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "warning: malformed PC_to_RDR_GetParamters");
|
||||
|
||||
if (request->bSlot < sizeof card_in_slot/sizeof *card_in_slot) {
|
||||
switch (reader->active_protocol) {
|
||||
case SC_PROTO_T0:
|
||||
result = realloc(*out, sizeof *result + sizeof *t0);
|
||||
if (!result)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
*out = (__u8 *) result;
|
||||
switch (reader->active_protocol) {
|
||||
case SC_PROTO_T0:
|
||||
result = realloc(*out, sizeof *result + sizeof *t0);
|
||||
if (!result)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
*out = (__u8 *) result;
|
||||
|
||||
result->bProtocolNum = 0;
|
||||
result->dwLength = __constant_cpu_to_le32(sizeof *t0);
|
||||
result->bProtocolNum = 0;
|
||||
result->dwLength = __constant_cpu_to_le32(sizeof *t0);
|
||||
|
||||
t0 = (abProtocolDataStructure_T0_t *) result + sizeof *result;
|
||||
/* values taken from ISO 7816-3 defaults
|
||||
* FIXME analyze ATR to get values */
|
||||
t0->bmFindexDindex =
|
||||
1<<4| // index to table 7 ISO 7816-3 (Fi)
|
||||
1; // index to table 8 ISO 7816-3 (Di)
|
||||
t0->bmTCCKST0 = 0<<1; // convention (direct)
|
||||
t0->bGuardTimeT0 = 0xFF;
|
||||
t0->bWaitingIntegerT0 = 0x10;
|
||||
t0->bClockStop = 0; // (not allowed)
|
||||
t0 = (abProtocolDataStructure_T0_t *) result + sizeof *result;
|
||||
/* values taken from ISO 7816-3 defaults
|
||||
* FIXME analyze ATR to get values */
|
||||
t0->bmFindexDindex =
|
||||
1<<4| // index to table 7 ISO 7816-3 (Fi)
|
||||
1; // index to table 8 ISO 7816-3 (Di)
|
||||
t0->bmTCCKST0 = 0<<1; // convention (direct)
|
||||
t0->bGuardTimeT0 = 0xFF;
|
||||
t0->bWaitingIntegerT0 = 0x10;
|
||||
t0->bClockStop = 0; // (not allowed)
|
||||
|
||||
sc_result = SC_SUCCESS;
|
||||
break;
|
||||
sc_result = SC_SUCCESS;
|
||||
break;
|
||||
|
||||
case SC_PROTO_T1:
|
||||
result = realloc(*out, sizeof *result + sizeof *t1);
|
||||
if (!result)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
*out = (__u8 *) result;
|
||||
case SC_PROTO_T1:
|
||||
result = realloc(*out, sizeof *result + sizeof *t1);
|
||||
if (!result)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
*out = (__u8 *) result;
|
||||
|
||||
result->bProtocolNum = 1;
|
||||
result->dwLength = __constant_cpu_to_le32(sizeof *t1);
|
||||
result->bProtocolNum = 1;
|
||||
result->dwLength = __constant_cpu_to_le32(sizeof *t1);
|
||||
|
||||
t1 = (abProtocolDataStructure_T1_t *) result + sizeof *result;
|
||||
/* values taken from OpenPGP-card
|
||||
* FIXME analyze ATR to get values */
|
||||
t1->bmFindexDindex =
|
||||
1<<4| // index to table 7 ISO 7816-3 (Fi)
|
||||
3; // index to table 8 ISO 7816-3 (Di)
|
||||
t1->bmTCCKST1 =
|
||||
0| // checksum type (CRC)
|
||||
0<<1| // convention (direct)
|
||||
0x10;
|
||||
t1->bGuardTimeT1 = 0xFF;
|
||||
t1->bWaitingIntegersT1 =
|
||||
4<<4| // BWI
|
||||
5; // CWI
|
||||
t1->bClockStop = 0; // (not allowed)
|
||||
t1->bIFSC = 0x80;
|
||||
t1->bNadValue = 0; // see 7816-3 9.4.2.1 (only default value)
|
||||
t1 = (abProtocolDataStructure_T1_t *) result + sizeof *result;
|
||||
/* values taken from OpenPGP-card
|
||||
* FIXME analyze ATR to get values */
|
||||
t1->bmFindexDindex =
|
||||
1<<4| // index to table 7 ISO 7816-3 (Fi)
|
||||
3; // index to table 8 ISO 7816-3 (Di)
|
||||
t1->bmTCCKST1 =
|
||||
0| // checksum type (CRC)
|
||||
0<<1| // convention (direct)
|
||||
0x10;
|
||||
t1->bGuardTimeT1 = 0xFF;
|
||||
t1->bWaitingIntegersT1 =
|
||||
4<<4| // BWI
|
||||
5; // CWI
|
||||
t1->bClockStop = 0; // (not allowed)
|
||||
t1->bIFSC = 0x80;
|
||||
t1->bNadValue = 0; // see 7816-3 9.4.2.1 (only default value)
|
||||
|
||||
sc_result = SC_SUCCESS;
|
||||
break;
|
||||
sc_result = SC_SUCCESS;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto invaliddata;
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
goto invaliddata;
|
||||
}
|
||||
invaliddata:
|
||||
result = realloc(*out, sizeof *result);
|
||||
if (!result)
|
||||
@@ -584,7 +561,6 @@ invaliddata:
|
||||
*out = (__u8 *) result;
|
||||
|
||||
sc_result = SC_ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
result->bMessageType = 0x82;
|
||||
result->bSlot = request->bSlot;
|
||||
@@ -1074,11 +1050,6 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle
|
||||
if (request->bMessageType != 0x69)
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "warning: malformed PC_to_RDR_Secure");
|
||||
|
||||
if (request->bSlot > sizeof card_in_slot/sizeof *card_in_slot) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Received request to invalid slot (bSlot=0x%02x)", request->bSlot);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (request->wLevelParameter != CCID_WLEVEL_DIRECT) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Received request with unsupported wLevelParameter (0x%04x)",
|
||||
__le16_to_cpu(request->wLevelParameter));
|
||||
@@ -1135,16 +1106,15 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle
|
||||
sc_result = perform_PC_to_RDR_Secure_GetReadersPACECapabilities(
|
||||
&abDataOut, &abDataOutLen);
|
||||
|
||||
if (card_in_slot[request->bSlot])
|
||||
bin_log(card_in_slot[request->bSlot]->ctx, SC_LOG_DEBUG_VERBOSE, "PACE Capabilities", abDataOut, abDataOutLen);
|
||||
if (card)
|
||||
bin_log(card->ctx, SC_LOG_DEBUG_VERBOSE, "PACE Capabilities", abDataOut, abDataOutLen);
|
||||
|
||||
goto err;
|
||||
break;
|
||||
case 0x20:
|
||||
|
||||
sc_result = perform_PC_to_RDR_Secure_EstablishPACEChannel(
|
||||
card_in_slot[request->bSlot], abData+1, abDatalen-1,
|
||||
&abDataOut, &abDataOutLen);
|
||||
sc_result = perform_PC_to_RDR_Secure_EstablishPACEChannel(card,
|
||||
abData+1, abDatalen-1, &abDataOut, &abDataOutLen);
|
||||
goto err;
|
||||
break;
|
||||
case 0x04:
|
||||
|
||||
Reference in New Issue
Block a user