- Some minor code improvements: catch and fix some rare errors, taking more
usage of opensc debugging methods, removed not needed variables and code fragments git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@36 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
467
ccid/ccid.c
467
ccid/ccid.c
@@ -67,7 +67,7 @@ detect_card_presence(int slot)
|
|||||||
int sc_result;
|
int sc_result;
|
||||||
|
|
||||||
if (slot >= sizeof *card_in_slot)
|
if (slot >= sizeof *card_in_slot)
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
|
|
||||||
if (card_in_slot[slot] && sc_card_valid(card_in_slot[slot])) {
|
if (card_in_slot[slot] && sc_card_valid(card_in_slot[slot])) {
|
||||||
sc_result = SC_SLOT_CARD_PRESENT;
|
sc_result = SC_SLOT_CARD_PRESENT;
|
||||||
@@ -91,18 +91,15 @@ detect_card_presence(int slot)
|
|||||||
sc_debug(ctx, "Unused card in slot %d", slot);
|
sc_debug(ctx, "Unused card in slot %d", slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, sc_result);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, sc_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ccid_initialize(int reader_id, int verbose)
|
int ccid_initialize(int reader_id, int verbose)
|
||||||
{
|
{
|
||||||
int sc_result, i;
|
unsigned int i, reader_count;
|
||||||
|
|
||||||
sc_result = sc_context_create(&ctx, NULL);
|
SC_TEST_RET(ctx, sc_context_create(&ctx, NULL), "Failed to create initial context.");
|
||||||
if (sc_result < 0) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->debug = verbose;
|
ctx->debug = verbose;
|
||||||
|
|
||||||
@@ -110,42 +107,41 @@ int ccid_initialize(int reader_id, int verbose)
|
|||||||
card_in_slot[i] = NULL;
|
card_in_slot[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sc_ctx_get_reader_count(ctx) == 0) {
|
reader_count = sc_ctx_get_reader_count(ctx);
|
||||||
sc_result = SC_ERROR_NO_READERS_FOUND;
|
|
||||||
goto err;
|
if (reader_count == 0)
|
||||||
}
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_NO_READERS_FOUND);
|
||||||
|
|
||||||
if (reader_id < 0) {
|
if (reader_id < 0) {
|
||||||
/* Automatically try to skip to a reader with a card if reader not specified */
|
/* Automatically try to skip to a reader with a card if reader not specified */
|
||||||
for (i = 0; i < sc_ctx_get_reader_count(ctx); i++) {
|
for (i = 0; i < reader_count; i++) {
|
||||||
reader = sc_ctx_get_reader(ctx, i);
|
reader = sc_ctx_get_reader(ctx, i);
|
||||||
if (sc_detect_card_presence(reader, 0) & SC_SLOT_CARD_PRESENT) {
|
if (sc_detect_card_presence(reader, 0) & SC_SLOT_CARD_PRESENT) {
|
||||||
reader_id = i;
|
reader_id = i;
|
||||||
sc_debug(ctx, "Using reader with a card: %s", reader->name);
|
sc_debug(ctx, "Using reader with a card: %s", reader->name);
|
||||||
goto autofound;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reader_id = 0;
|
if (reader_id >= reader_count) {
|
||||||
}
|
/* no reader found, use the first */
|
||||||
autofound:
|
reader_id = 0;
|
||||||
if ((unsigned int)reader_id >= sc_ctx_get_reader_count(ctx)) {
|
}
|
||||||
sc_result = SC_ERROR_NO_READERS_FOUND;
|
|
||||||
goto err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (reader_id >= reader_count)
|
||||||
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_NO_READERS_FOUND);
|
||||||
|
|
||||||
reader = sc_ctx_get_reader(ctx, reader_id);
|
reader = sc_ctx_get_reader(ctx, reader_id);
|
||||||
ccid_desc.bMaxSlotIndex = reader->slot_count - 1;
|
ccid_desc.bMaxSlotIndex = reader->slot_count - 1;
|
||||||
|
|
||||||
err:
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_SUCCESS);
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, sc_result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ccid_shutdown()
|
void ccid_shutdown()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < sizeof *card_in_slot; i++) {
|
for (i = 0; i < sizeof *card_in_slot; i++) {
|
||||||
if (card_in_slot[i]) {
|
if (card_in_slot[i] && sc_card_valid(card_in_slot[i])) {
|
||||||
sc_unlock(card_in_slot[i]);
|
|
||||||
sc_disconnect_card(card_in_slot[i], 0);
|
sc_disconnect_card(card_in_slot[i], 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -304,14 +300,14 @@ __u8 get_bStatus(int sc_result, __u8 bSlot)
|
|||||||
if (flags & SC_SLOT_CARD_CHANGED || (
|
if (flags & SC_SLOT_CARD_CHANGED || (
|
||||||
card_in_slot[bSlot]
|
card_in_slot[bSlot]
|
||||||
&& !sc_card_valid(card_in_slot[bSlot]))) {
|
&& !sc_card_valid(card_in_slot[bSlot]))) {
|
||||||
sc_debug(ctx, "error inactive");
|
/*sc_debug(ctx, "error inactive");*/
|
||||||
result = CCID_BSTATUS_ERROR_INACTIVE;
|
result = CCID_BSTATUS_ERROR_INACTIVE;
|
||||||
} else {
|
} else {
|
||||||
sc_debug(ctx, "error active");
|
/*sc_debug(ctx, "error active");*/
|
||||||
result = CCID_BSTATUS_ERROR_ACTIVE;
|
result = CCID_BSTATUS_ERROR_ACTIVE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sc_debug(ctx, "error no icc");
|
/*sc_debug(ctx, "error no icc");*/
|
||||||
result = CCID_BSTATUS_ERROR_NOICC;
|
result = CCID_BSTATUS_ERROR_NOICC;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -319,14 +315,14 @@ __u8 get_bStatus(int sc_result, __u8 bSlot)
|
|||||||
if (flags & SC_SLOT_CARD_CHANGED || (
|
if (flags & SC_SLOT_CARD_CHANGED || (
|
||||||
card_in_slot[bSlot]
|
card_in_slot[bSlot]
|
||||||
&& !sc_card_valid(card_in_slot[bSlot]))) {
|
&& !sc_card_valid(card_in_slot[bSlot]))) {
|
||||||
sc_debug(ctx, "ok inactive");
|
/*sc_debug(ctx, "ok inactive");*/
|
||||||
result = CCID_BSTATUS_OK_INACTIVE;
|
result = CCID_BSTATUS_OK_INACTIVE;
|
||||||
} else {
|
} else {
|
||||||
sc_debug(ctx, "ok active");
|
sc_debug(ctx, "ok active");
|
||||||
result = CCID_BSTATUS_OK_ACTIVE;
|
result = CCID_BSTATUS_OK_ACTIVE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sc_debug(ctx, "ok no icc");
|
/*sc_debug(ctx, "ok no icc");*/
|
||||||
result = CCID_BSTATUS_OK_NOICC;
|
result = CCID_BSTATUS_OK_NOICC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -341,11 +337,11 @@ int
|
|||||||
get_RDR_to_PC_SlotStatus(__u8 bSlot, __u8 bSeq, int sc_result, RDR_to_PC_SlotStatus_t **out)
|
get_RDR_to_PC_SlotStatus(__u8 bSlot, __u8 bSeq, int sc_result, RDR_to_PC_SlotStatus_t **out)
|
||||||
{
|
{
|
||||||
if (!out)
|
if (!out)
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
|
|
||||||
RDR_to_PC_SlotStatus_t *result = realloc(*out, sizeof *result);
|
RDR_to_PC_SlotStatus_t *result = realloc(*out, sizeof *result);
|
||||||
if (!result)
|
if (!result)
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_OUT_OF_MEMORY);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_OUT_OF_MEMORY);
|
||||||
*out = result;
|
*out = result;
|
||||||
|
|
||||||
result->bMessageType = 0x81;
|
result->bMessageType = 0x81;
|
||||||
@@ -356,18 +352,18 @@ get_RDR_to_PC_SlotStatus(__u8 bSlot, __u8 bSeq, int sc_result, RDR_to_PC_SlotSta
|
|||||||
result->bError = get_bError(sc_result);
|
result->bError = get_bError(sc_result);
|
||||||
result->bClockStatus = 0;
|
result->bClockStatus = 0;
|
||||||
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_SUCCESS);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
get_RDR_to_PC_DataBlock(__u8 bSlot, __u8 bSeq, int sc_result, RDR_to_PC_DataBlock_t **out)
|
get_RDR_to_PC_DataBlock(__u8 bSlot, __u8 bSeq, int sc_result, RDR_to_PC_DataBlock_t **out)
|
||||||
{
|
{
|
||||||
if (!out)
|
if (!out)
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
|
|
||||||
RDR_to_PC_DataBlock_t *result = realloc(*out, sizeof *result);
|
RDR_to_PC_DataBlock_t *result = realloc(*out, sizeof *result);
|
||||||
if (!result)
|
if (!result)
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_OUT_OF_MEMORY);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_OUT_OF_MEMORY);
|
||||||
*out = result;
|
*out = result;
|
||||||
|
|
||||||
result->bMessageType = 0x80;
|
result->bMessageType = 0x80;
|
||||||
@@ -378,23 +374,18 @@ get_RDR_to_PC_DataBlock(__u8 bSlot, __u8 bSeq, int sc_result, RDR_to_PC_DataBloc
|
|||||||
result->bError = get_bError(sc_result);
|
result->bError = get_bError(sc_result);
|
||||||
result->bChainParameter = 0;
|
result->bChainParameter = 0;
|
||||||
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_SUCCESS);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
perform_PC_to_RDR_GetSlotStatus(const __u8 *in, __u8 **out, size_t *outlen)
|
perform_PC_to_RDR_GetSlotStatus(const __u8 *in, __u8 **out, size_t *outlen)
|
||||||
{
|
{
|
||||||
int r;
|
|
||||||
const PC_to_RDR_GetSlotStatus_t *request = (PC_to_RDR_GetSlotStatus_t *) in;
|
const PC_to_RDR_GetSlotStatus_t *request = (PC_to_RDR_GetSlotStatus_t *) in;
|
||||||
RDR_to_PC_SlotStatus_t *result = realloc(*out, sizeof *result);
|
|
||||||
if (!result)
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_OUT_OF_MEMORY);
|
|
||||||
*out = (__u8 *) result;
|
|
||||||
|
|
||||||
if (!out || !outlen)
|
if (!out || !outlen || !in)
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
|
|
||||||
*outlen = 0;
|
*outlen = sizeof(RDR_to_PC_SlotStatus_t);
|
||||||
|
|
||||||
if ( request->bMessageType != 0x65 ||
|
if ( request->bMessageType != 0x65 ||
|
||||||
request->dwLength != __constant_cpu_to_le32(0) ||
|
request->dwLength != __constant_cpu_to_le32(0) ||
|
||||||
@@ -402,24 +393,20 @@ perform_PC_to_RDR_GetSlotStatus(const __u8 *in, __u8 **out, size_t *outlen)
|
|||||||
request->abRFU2 != 0)
|
request->abRFU2 != 0)
|
||||||
sc_debug(ctx, "warning: malformed PC_to_RDR_GetSlotStatus");
|
sc_debug(ctx, "warning: malformed PC_to_RDR_GetSlotStatus");
|
||||||
|
|
||||||
r = get_RDR_to_PC_SlotStatus(request->bSlot, request->bSeq, SC_SUCCESS, &result);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR,
|
||||||
|
get_RDR_to_PC_SlotStatus(request->bSlot, request->bSeq, SC_SUCCESS,
|
||||||
if (r >= 0) {
|
(RDR_to_PC_SlotStatus_t **) out));
|
||||||
*outlen = sizeof *result;
|
|
||||||
}
|
|
||||||
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, r);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
perform_PC_to_RDR_IccPowerOn(const __u8 *in, __u8 **out, size_t *outlen)
|
perform_PC_to_RDR_IccPowerOn(const __u8 *in, __u8 **out, size_t *outlen)
|
||||||
{
|
{
|
||||||
const PC_to_RDR_IccPowerOn_t *request = (PC_to_RDR_IccPowerOn_t *) in;
|
const PC_to_RDR_IccPowerOn_t *request = (PC_to_RDR_IccPowerOn_t *) in;
|
||||||
int sc_result, r;
|
int sc_result;
|
||||||
RDR_to_PC_SlotStatus_t *result = realloc(*out, sizeof *result);
|
RDR_to_PC_SlotStatus_t *result;
|
||||||
if (!result)
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_OUT_OF_MEMORY);
|
if (!out || !outlen || !in)
|
||||||
*out = (__u8 *) result;
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
|
|
||||||
if ( request->bMessageType != 0x62 ||
|
if ( request->bMessageType != 0x62 ||
|
||||||
request->dwLength != __constant_cpu_to_le32(0) ||
|
request->dwLength != __constant_cpu_to_le32(0) ||
|
||||||
@@ -428,10 +415,6 @@ perform_PC_to_RDR_IccPowerOn(const __u8 *in, __u8 **out, size_t *outlen)
|
|||||||
request->abRFU != 0)
|
request->abRFU != 0)
|
||||||
sc_debug(ctx, "warning: malformed PC_to_RDR_IccPowerOn");
|
sc_debug(ctx, "warning: malformed PC_to_RDR_IccPowerOn");
|
||||||
|
|
||||||
if (!out || !outlen)
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_ARGUMENTS);
|
|
||||||
|
|
||||||
*outlen = 0;
|
|
||||||
if (request->bSlot < sizeof *card_in_slot) {
|
if (request->bSlot < sizeof *card_in_slot) {
|
||||||
if (card_in_slot[request->bSlot]
|
if (card_in_slot[request->bSlot]
|
||||||
&& sc_card_valid(card_in_slot[request->bSlot])) {
|
&& sc_card_valid(card_in_slot[request->bSlot])) {
|
||||||
@@ -443,24 +426,30 @@ perform_PC_to_RDR_IccPowerOn(const __u8 *in, __u8 **out, size_t *outlen)
|
|||||||
sc_result = SC_ERROR_INVALID_DATA;
|
sc_result = SC_ERROR_INVALID_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = get_RDR_to_PC_SlotStatus(request->bSlot, request->bSeq, sc_result, &result);
|
SC_TEST_RET(ctx,
|
||||||
|
get_RDR_to_PC_SlotStatus(request->bSlot, request->bSeq, sc_result,
|
||||||
|
(RDR_to_PC_SlotStatus_t **) out),
|
||||||
|
"Could not get RDR_to_PC_SlotStatus object");
|
||||||
|
result = (RDR_to_PC_SlotStatus_t *) *out;
|
||||||
|
|
||||||
if (r >= 0) {
|
if (sc_result >= 0) {
|
||||||
if (sc_result >= 0) {
|
*outlen = sizeof *result + card_in_slot[request->bSlot]->atr_len;
|
||||||
result->dwLength = __cpu_to_le32(card_in_slot[request->bSlot]->atr_len);
|
result = realloc(*out, *outlen);
|
||||||
*outlen = sizeof *result + card_in_slot[request->bSlot]->atr_len;
|
if (result) {
|
||||||
result = realloc(*out, *outlen);
|
|
||||||
if (!result)
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_OUT_OF_MEMORY);
|
|
||||||
*out = (__u8 *) result;
|
*out = (__u8 *) result;
|
||||||
memcpy(*out + sizeof *result, card_in_slot[request->bSlot]->atr, card_in_slot[request->bSlot]->atr_len);
|
memcpy(*out + sizeof *result, card_in_slot[request->bSlot]->atr,
|
||||||
|
card_in_slot[request->bSlot]->atr_len);
|
||||||
|
result->dwLength = __cpu_to_le32(card_in_slot[request->bSlot]->atr_len);
|
||||||
} else {
|
} else {
|
||||||
debug_sc_result(sc_result);
|
debug_sc_result(SC_ERROR_OUT_OF_MEMORY);
|
||||||
*outlen = sizeof *result;
|
*outlen = sizeof *result;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
debug_sc_result(sc_result);
|
||||||
|
*outlen = sizeof *result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, r);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -483,31 +472,29 @@ perform_PC_to_RDR_IccPowerOff(const __u8 *in, __u8 **out, size_t *outlen)
|
|||||||
else
|
else
|
||||||
sc_result = sc_disconnect_card(card_in_slot[request->bSlot], 0);
|
sc_result = sc_disconnect_card(card_in_slot[request->bSlot], 0);
|
||||||
|
|
||||||
if (sc_result < 0)
|
SC_TEST_RET(ctx,
|
||||||
debug_sc_result(sc_result);
|
get_RDR_to_PC_SlotStatus(request->bSlot, request->bSeq, sc_result,
|
||||||
|
(RDR_to_PC_SlotStatus_t **) out),
|
||||||
|
"Could not get RDR_to_PC_SlotStatus object");
|
||||||
|
|
||||||
sc_result = get_RDR_to_PC_SlotStatus(request->bSlot, request->bSeq,
|
*outlen = sizeof(RDR_to_PC_SlotStatus_t);
|
||||||
sc_result, (RDR_to_PC_SlotStatus_t **) out);
|
|
||||||
|
|
||||||
if (sc_result >= 0)
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_SUCCESS);
|
||||||
*outlen = sizeof(RDR_to_PC_SlotStatus_t);
|
|
||||||
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, sc_result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
perform_PC_to_RDR_XfrBlock(const u8 *in, __u8** out, size_t *outlen)
|
perform_PC_to_RDR_XfrBlock(const u8 *in, __u8** out, size_t *outlen)
|
||||||
{
|
{
|
||||||
|
const PC_to_RDR_XfrBlock_t *request = (PC_to_RDR_XfrBlock_t *) in;
|
||||||
|
const __u8 *abDataIn = in + sizeof *request;
|
||||||
int sc_result, r;
|
int sc_result, r;
|
||||||
size_t resplen = 0;
|
size_t resplen = 0;
|
||||||
sc_apdu_t apdu;
|
sc_apdu_t apdu;
|
||||||
const PC_to_RDR_XfrBlock_t *request = (PC_to_RDR_XfrBlock_t *) in;
|
|
||||||
const __u8 *abDataIn = in + sizeof *request;
|
|
||||||
__u8 *abDataOut;
|
__u8 *abDataOut;
|
||||||
RDR_to_PC_DataBlock_t *result = realloc(*out, sizeof *result);
|
RDR_to_PC_DataBlock_t *result;
|
||||||
if (!result)
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_OUT_OF_MEMORY);
|
if (!in || !out || !outlen)
|
||||||
*out = (__u8 *) result;
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
|
|
||||||
if ( request->bMessageType != 0x6F ||
|
if ( request->bMessageType != 0x6F ||
|
||||||
request->bBWI != 0)
|
request->bBWI != 0)
|
||||||
@@ -521,30 +508,35 @@ perform_PC_to_RDR_XfrBlock(const u8 *in, __u8** out, size_t *outlen)
|
|||||||
sc_result = get_rapdu(&apdu, request->bSlot, &abDataOut, &resplen);
|
sc_result = get_rapdu(&apdu, request->bSlot, &abDataOut, &resplen);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = get_RDR_to_PC_DataBlock(request->bSlot, request->bSeq, sc_result, &result);
|
r = get_RDR_to_PC_DataBlock(request->bSlot, request->bSeq, sc_result,
|
||||||
|
(RDR_to_PC_DataBlock_t **) out);
|
||||||
|
result = (RDR_to_PC_DataBlock_t *) *out;
|
||||||
|
if (r < 0) {
|
||||||
|
if (sc_result >= 0)
|
||||||
|
free(abDataOut);
|
||||||
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, r);
|
||||||
|
}
|
||||||
|
|
||||||
if (r >= 0) {
|
if (sc_result >= 0) {
|
||||||
*outlen = sizeof *result + resplen;
|
*outlen = sizeof *result + resplen;
|
||||||
result = realloc(*out, *outlen);
|
result = realloc(*out, *outlen);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
|
*outlen = sizeof *result;
|
||||||
free(abDataOut);
|
free(abDataOut);
|
||||||
sc_result = SC_ERROR_OUT_OF_MEMORY;
|
sc_result = SC_ERROR_OUT_OF_MEMORY;
|
||||||
result->bError = get_bError(sc_result);
|
|
||||||
result->bStatus = get_bStatus(sc_result, request->bSlot);
|
|
||||||
*outlen = sizeof *result;
|
|
||||||
} else {
|
} else {
|
||||||
*out = (__u8 *) result;
|
*out = (__u8 *) result;
|
||||||
result->dwLength = __cpu_to_le32(resplen);
|
result->dwLength = __cpu_to_le32(resplen);
|
||||||
memcpy(*out + sizeof *result, abDataOut, resplen);
|
memcpy(*out + sizeof *result, abDataOut, resplen);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
free(abDataOut);
|
*outlen = sizeof *result;
|
||||||
}
|
|
||||||
|
|
||||||
if (sc_result < 0)
|
|
||||||
debug_sc_result(sc_result);
|
debug_sc_result(sc_result);
|
||||||
|
}
|
||||||
|
result->bError = get_bError(sc_result);
|
||||||
|
result->bStatus = get_bStatus(sc_result, request->bSlot);
|
||||||
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, r);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -556,75 +548,81 @@ perform_PC_to_RDR_GetParamters(const __u8 *in, __u8** out, size_t *outlen)
|
|||||||
abProtocolDataStructure_T0_t *t0;
|
abProtocolDataStructure_T0_t *t0;
|
||||||
int sc_result;
|
int sc_result;
|
||||||
|
|
||||||
if (!in || !out || !outlen || request->bSlot > sizeof *card_in_slot)
|
if (!in || !out || !outlen)
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
|
|
||||||
if ( request->bMessageType != 0x6C ||
|
if ( request->bMessageType != 0x6C ||
|
||||||
request->dwLength != __constant_cpu_to_le32(0))
|
request->dwLength != __constant_cpu_to_le32(0))
|
||||||
sc_debug(ctx, "warning: malformed PC_to_RDR_GetParamters");
|
sc_debug(ctx, "warning: malformed PC_to_RDR_GetParamters");
|
||||||
|
|
||||||
switch (reader->slot[request->bSlot].active_protocol) {
|
if (request->bSlot < sizeof *card_in_slot) {
|
||||||
case SC_PROTO_T0:
|
switch (reader->slot[request->bSlot].active_protocol) {
|
||||||
result = realloc(*out, sizeof *result + sizeof *t0);
|
case SC_PROTO_T0:
|
||||||
if (!result)
|
result = realloc(*out, sizeof *result + sizeof *t0);
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_OUT_OF_MEMORY);
|
if (!result)
|
||||||
*out = (__u8 *) result;
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_OUT_OF_MEMORY);
|
||||||
|
*out = (__u8 *) result;
|
||||||
|
|
||||||
result->bProtocolNum = 0;
|
result->bProtocolNum = 0;
|
||||||
result->dwLength = __constant_cpu_to_le32(sizeof *t0);
|
result->dwLength = __constant_cpu_to_le32(sizeof *t0);
|
||||||
|
|
||||||
t0 = (abProtocolDataStructure_T0_t *) result + sizeof *result;
|
t0 = (abProtocolDataStructure_T0_t *) result + sizeof *result;
|
||||||
/* values taken from ISO 7816-3 defaults
|
/* values taken from ISO 7816-3 defaults
|
||||||
* FIXME analyze ATR to get values */
|
* FIXME analyze ATR to get values */
|
||||||
t0->bmFindexDindex =
|
t0->bmFindexDindex =
|
||||||
1<<4| // index to table 7 ISO 7816-3 (Fi)
|
1<<4| // index to table 7 ISO 7816-3 (Fi)
|
||||||
1; // index to table 8 ISO 7816-3 (Di)
|
1; // index to table 8 ISO 7816-3 (Di)
|
||||||
t0->bmTCCKST0 = 0<<1; // convention (direct)
|
t0->bmTCCKST0 = 0<<1; // convention (direct)
|
||||||
t0->bGuardTimeT0 = 0xFF;
|
t0->bGuardTimeT0 = 0xFF;
|
||||||
t0->bWaitingIntegerT0 = 0x10;
|
t0->bWaitingIntegerT0 = 0x10;
|
||||||
t0->bClockStop = 0; // (not allowed)
|
t0->bClockStop = 0; // (not allowed)
|
||||||
|
|
||||||
sc_result = SC_SUCCESS;
|
sc_result = SC_SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SC_PROTO_T1:
|
case SC_PROTO_T1:
|
||||||
result = realloc(*out, sizeof *result + sizeof *t1);
|
result = realloc(*out, sizeof *result + sizeof *t1);
|
||||||
if (!result)
|
if (!result)
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_OUT_OF_MEMORY);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_OUT_OF_MEMORY);
|
||||||
*out = (__u8 *) result;
|
*out = (__u8 *) result;
|
||||||
|
|
||||||
result->bProtocolNum = 1;
|
result->bProtocolNum = 1;
|
||||||
result->dwLength = __constant_cpu_to_le32(sizeof *t1);
|
result->dwLength = __constant_cpu_to_le32(sizeof *t1);
|
||||||
|
|
||||||
t1 = (abProtocolDataStructure_T1_t *) result + sizeof *result;
|
t1 = (abProtocolDataStructure_T1_t *) result + sizeof *result;
|
||||||
/* values taken from OpenPGP-card
|
/* values taken from OpenPGP-card
|
||||||
* FIXME analyze ATR to get values */
|
* FIXME analyze ATR to get values */
|
||||||
t1->bmFindexDindex =
|
t1->bmFindexDindex =
|
||||||
1<<4| // index to table 7 ISO 7816-3 (Fi)
|
1<<4| // index to table 7 ISO 7816-3 (Fi)
|
||||||
3; // index to table 8 ISO 7816-3 (Di)
|
3; // index to table 8 ISO 7816-3 (Di)
|
||||||
t1->bmTCCKST1 =
|
t1->bmTCCKST1 =
|
||||||
0| // checksum type (CRC)
|
0| // checksum type (CRC)
|
||||||
0<<1| // convention (direct)
|
0<<1| // convention (direct)
|
||||||
0x10;
|
0x10;
|
||||||
t1->bGuardTimeT1 = 0xFF;
|
t1->bGuardTimeT1 = 0xFF;
|
||||||
t1->bWaitingIntegersT1 =
|
t1->bWaitingIntegersT1 =
|
||||||
4<<4| // BWI
|
4<<4| // BWI
|
||||||
5; // CWI
|
5; // CWI
|
||||||
t1->bClockStop = 0; // (not allowed)
|
t1->bClockStop = 0; // (not allowed)
|
||||||
t1->bIFSC = 0x80;
|
t1->bIFSC = 0x80;
|
||||||
t1->bNadValue = 0; // see 7816-3 9.4.2.1 (only default value)
|
t1->bNadValue = 0; // see 7816-3 9.4.2.1 (only default value)
|
||||||
|
|
||||||
sc_result = SC_SUCCESS;
|
sc_result = SC_SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
result = realloc(*out, sizeof *result);
|
goto invaliddata;
|
||||||
if (!result)
|
}
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_OUT_OF_MEMORY);
|
} else {
|
||||||
*out = (__u8 *) result;
|
invaliddata:
|
||||||
|
result = realloc(*out, sizeof *result);
|
||||||
|
if (!result)
|
||||||
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_OUT_OF_MEMORY);
|
||||||
|
*out = (__u8 *) result;
|
||||||
|
|
||||||
sc_result = SC_ERROR_INVALID_DATA;
|
sc_result = SC_ERROR_INVALID_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
result->bMessageType = 0x82;
|
result->bMessageType = 0x82;
|
||||||
result->bSlot = request->bSlot;
|
result->bSlot = request->bSlot;
|
||||||
result->bSeq = request->bSeq;
|
result->bSeq = request->bSeq;
|
||||||
@@ -666,7 +664,8 @@ write_pin_length(sc_apdu_t *apdu, const struct sc_pin_cmd_pin *pin,
|
|||||||
{
|
{
|
||||||
u8 *p;
|
u8 *p;
|
||||||
|
|
||||||
if (!apdu || !apdu->data || !pin || apdu->datalen <= pin->length_offset || !sc_result) {
|
if (!apdu || !apdu->data || !pin || apdu->datalen <= pin->length_offset ||
|
||||||
|
!sc_result) {
|
||||||
if (sc_result)
|
if (sc_result)
|
||||||
*sc_result = SC_ERROR_INVALID_ARGUMENTS;
|
*sc_result = SC_ERROR_INVALID_ARGUMENTS;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -674,6 +673,7 @@ write_pin_length(sc_apdu_t *apdu, const struct sc_pin_cmd_pin *pin,
|
|||||||
|
|
||||||
if (length_size) {
|
if (length_size) {
|
||||||
if (length_size != 8) {
|
if (length_size != 8) {
|
||||||
|
/* only write pin length if it fits into a full byte */
|
||||||
*sc_result = SC_ERROR_NOT_SUPPORTED;
|
*sc_result = SC_ERROR_NOT_SUPPORTED;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -737,6 +737,7 @@ encode_pin(u8 *buf, size_t buf_len, struct sc_pin_cmd_pin *pin,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!buf_len && *p) {
|
if (!buf_len && *p) {
|
||||||
|
/* pin is longer than buf_len */
|
||||||
*sc_result = SC_ERROR_OUT_OF_MEMORY;
|
*sc_result = SC_ERROR_OUT_OF_MEMORY;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -777,6 +778,7 @@ write_pin(sc_apdu_t *apdu, struct sc_pin_cmd_pin *pin, uint8_t blocksize,
|
|||||||
if (justify_right) {
|
if (justify_right) {
|
||||||
if (encoding == CCID_PIN_ENCODING_BCD) {
|
if (encoding == CCID_PIN_ENCODING_BCD) {
|
||||||
if (pin->len % 2) {
|
if (pin->len % 2) {
|
||||||
|
/* only do right aligned BCD which fits into full bytes */
|
||||||
*sc_result = SC_ERROR_NOT_SUPPORTED;
|
*sc_result = SC_ERROR_NOT_SUPPORTED;
|
||||||
return 0;
|
return 0;
|
||||||
} else
|
} else
|
||||||
@@ -795,25 +797,25 @@ int
|
|||||||
perform_PC_to_RDR_Secure(const __u8 *in, __u8** out, size_t *outlen)
|
perform_PC_to_RDR_Secure(const __u8 *in, __u8** out, size_t *outlen)
|
||||||
{
|
{
|
||||||
int sc_result, r;
|
int sc_result, r;
|
||||||
sc_apdu_t apdu;
|
|
||||||
struct sc_pin_cmd_pin curr_pin, new_pin;
|
struct sc_pin_cmd_pin curr_pin, new_pin;
|
||||||
|
sc_apdu_t apdu;
|
||||||
sc_ui_hints_t hints;
|
sc_ui_hints_t hints;
|
||||||
const PC_to_RDR_Secure_t *request = (PC_to_RDR_Secure_t *) in;
|
const PC_to_RDR_Secure_t *request = (PC_to_RDR_Secure_t *) in;
|
||||||
const __u8* abData = in + sizeof *request;
|
const __u8* abData = in + sizeof *request;
|
||||||
u8 *abDataOut;
|
u8 *abDataOut;
|
||||||
size_t resplen = 0;
|
size_t resplen = 0;
|
||||||
RDR_to_PC_DataBlock_t *result = realloc(*out, sizeof *result);
|
RDR_to_PC_DataBlock_t *result;
|
||||||
if (!result)
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_OUT_OF_MEMORY);
|
if (!in || !out || !outlen)
|
||||||
*out = (__u8 *) result;
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
|
|
||||||
|
if (request->bMessageType != 0x69)
|
||||||
|
sc_debug(ctx, "warning: malformed PC_to_RDR_Secure");
|
||||||
|
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
memset(&curr_pin, 0, sizeof(curr_pin));
|
memset(&curr_pin, 0, sizeof(curr_pin));
|
||||||
memset(&new_pin, 0, sizeof(new_pin));
|
memset(&new_pin, 0, sizeof(new_pin));
|
||||||
|
|
||||||
if (request->bMessageType != 0x69)
|
|
||||||
sc_debug(ctx, "warning: malformed PC_to_RDR_Secure");
|
|
||||||
|
|
||||||
if (request->bSlot > sizeof *card_in_slot)
|
if (request->bSlot > sizeof *card_in_slot)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
@@ -973,6 +975,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, __u8** out, size_t *outlen)
|
|||||||
|
|
||||||
sc_result = get_rapdu(&apdu, request->bSlot, &abDataOut, &resplen);
|
sc_result = get_rapdu(&apdu, request->bSlot, &abDataOut, &resplen);
|
||||||
|
|
||||||
|
sc_mem_clear(abPINApdu, apdulen);
|
||||||
err:
|
err:
|
||||||
if (curr_pin.data) {
|
if (curr_pin.data) {
|
||||||
sc_mem_clear((u8 *) curr_pin.data, curr_pin.len);
|
sc_mem_clear((u8 *) curr_pin.data, curr_pin.len);
|
||||||
@@ -982,31 +985,33 @@ err:
|
|||||||
sc_mem_clear((u8 *) new_pin.data, new_pin.len);
|
sc_mem_clear((u8 *) new_pin.data, new_pin.len);
|
||||||
free((u8 *) new_pin.data);
|
free((u8 *) new_pin.data);
|
||||||
}
|
}
|
||||||
sc_mem_clear(abPINApdu, apdulen);
|
|
||||||
|
|
||||||
r = get_RDR_to_PC_DataBlock(request->bSlot, request->bSeq, sc_result, &result);
|
r = get_RDR_to_PC_DataBlock(request->bSlot, request->bSeq, sc_result, (RDR_to_PC_DataBlock_t **) out);
|
||||||
|
result = (RDR_to_PC_DataBlock_t *) *out;
|
||||||
if (r >= 0) {
|
if (r < 0) {
|
||||||
*outlen = sizeof *result + resplen;
|
if (sc_result >= 0)
|
||||||
*out = realloc(result, *outlen);
|
free(abDataOut);
|
||||||
if (!*out) {
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, r);
|
||||||
if (abDataOut) {
|
|
||||||
free(abDataOut);
|
|
||||||
}
|
|
||||||
sc_result = SC_ERROR_OUT_OF_MEMORY;
|
|
||||||
result->bError = get_bError(sc_result);
|
|
||||||
result->bStatus = get_bStatus(sc_result, request->bSlot);
|
|
||||||
result->dwLength = __constant_cpu_to_le32(0);
|
|
||||||
*outlen = sizeof *result;
|
|
||||||
*out = (__u8 *) result;
|
|
||||||
} else {
|
|
||||||
memcpy(*out + sizeof *result, abDataOut, resplen);
|
|
||||||
result->dwLength = __cpu_to_le32(resplen);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sc_result < 0)
|
if (sc_result >= 0) {
|
||||||
|
*outlen = sizeof *result + resplen;
|
||||||
|
result = realloc(*out, *outlen);
|
||||||
|
if (!result) {
|
||||||
|
*outlen = sizeof *result;
|
||||||
|
free(abDataOut);
|
||||||
|
sc_result = SC_ERROR_OUT_OF_MEMORY;
|
||||||
|
} else {
|
||||||
|
*out = (__u8 *) result;
|
||||||
|
result->dwLength = __cpu_to_le32(resplen);
|
||||||
|
memcpy(*out + sizeof *result, abDataOut, resplen);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*outlen = sizeof *result;
|
||||||
debug_sc_result(sc_result);
|
debug_sc_result(sc_result);
|
||||||
|
}
|
||||||
|
result->bError = get_bError(sc_result);
|
||||||
|
result->bStatus = get_bStatus(sc_result, request->bSlot);
|
||||||
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, r);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, r);
|
||||||
}
|
}
|
||||||
@@ -1030,11 +1035,11 @@ get_RDR_to_PC_NotifySlotChange(RDR_to_PC_NotifySlotChange_t **out)
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (!out)
|
if (!out)
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
|
|
||||||
RDR_to_PC_NotifySlotChange_t *result = realloc(*out, sizeof *result);
|
RDR_to_PC_NotifySlotChange_t *result = realloc(*out, sizeof *result);
|
||||||
if (!result)
|
if (!result)
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_OUT_OF_MEMORY);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_OUT_OF_MEMORY);
|
||||||
*out = result;
|
*out = result;
|
||||||
|
|
||||||
result->bMessageType = 0x50;
|
result->bMessageType = 0x50;
|
||||||
@@ -1054,16 +1059,19 @@ get_RDR_to_PC_NotifySlotChange(RDR_to_PC_NotifySlotChange_t **out)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*out = result;
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_SUCCESS);
|
||||||
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
perform_unknown(const __u8 *in, __u8 **out, size_t *outlen)
|
perform_unknown(const __u8 *in, __u8 **out, size_t *outlen)
|
||||||
{
|
{
|
||||||
const PC_to_RDR_GetSlotStatus_t *request = (PC_to_RDR_GetSlotStatus_t *) in;
|
const PC_to_RDR_GetSlotStatus_t *request = (PC_to_RDR_GetSlotStatus_t *) in;
|
||||||
RDR_to_PC_SlotStatus_t *result = realloc(*out, sizeof *result);
|
RDR_to_PC_SlotStatus_t *result;
|
||||||
|
|
||||||
|
if (!in || !out || !outlen)
|
||||||
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
|
|
||||||
|
result = realloc(*out, sizeof *result);
|
||||||
if (!result)
|
if (!result)
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_OUT_OF_MEMORY);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_OUT_OF_MEMORY);
|
||||||
*out = (__u8 *) result;
|
*out = (__u8 *) result;
|
||||||
@@ -1100,11 +1108,11 @@ perform_unknown(const __u8 *in, __u8 **out, size_t *outlen)
|
|||||||
result->dwLength = __constant_cpu_to_le32(0);
|
result->dwLength = __constant_cpu_to_le32(0);
|
||||||
result->bSlot = request->bSlot,
|
result->bSlot = request->bSlot,
|
||||||
result->bSeq = request->bSeq;
|
result->bSeq = request->bSeq;
|
||||||
result->bStatus = get_bStatus(SC_ERROR_UNKNOWN_DATA_RECEIVED, request->bSlot);
|
result->bStatus = get_bStatus(SC_ERROR_UNKNOWN_DATA_RECEIVED,
|
||||||
|
request->bSlot);
|
||||||
result->bError = 0;
|
result->bError = 0;
|
||||||
result->bClockStatus = 0;
|
result->bClockStatus = 0;
|
||||||
|
|
||||||
*out = (__u8 *) result;
|
|
||||||
*outlen = sizeof *result;
|
*outlen = sizeof *result;
|
||||||
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_SUCCESS);
|
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_SUCCESS);
|
||||||
@@ -1112,11 +1120,12 @@ perform_unknown(const __u8 *in, __u8 **out, size_t *outlen)
|
|||||||
|
|
||||||
int ccid_parse_bulkin(const __u8* inbuf, __u8** outbuf)
|
int ccid_parse_bulkin(const __u8* inbuf, __u8** outbuf)
|
||||||
{
|
{
|
||||||
if (inbuf == NULL)
|
|
||||||
return 0;
|
|
||||||
int sc_result;
|
int sc_result;
|
||||||
size_t outlen;
|
size_t outlen;
|
||||||
|
|
||||||
|
if (!inbuf)
|
||||||
|
return 0;
|
||||||
|
|
||||||
switch (*inbuf) {
|
switch (*inbuf) {
|
||||||
case 0x62:
|
case 0x62:
|
||||||
sc_debug(ctx, "PC_to_RDR_IccPowerOn");
|
sc_debug(ctx, "PC_to_RDR_IccPowerOn");
|
||||||
@@ -1163,62 +1172,72 @@ int ccid_parse_bulkin(const __u8* inbuf, __u8** outbuf)
|
|||||||
|
|
||||||
int ccid_parse_control(struct usb_ctrlrequest *setup, __u8 **outbuf)
|
int ccid_parse_control(struct usb_ctrlrequest *setup, __u8 **outbuf)
|
||||||
{
|
{
|
||||||
int result = -1;
|
int result;
|
||||||
__u16 value, index, length;
|
__u16 value, index, length;
|
||||||
__u8 *tmp;
|
__u8 *tmp;
|
||||||
|
|
||||||
|
if (!setup || !outbuf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
value = __le16_to_cpu(setup->wValue);
|
value = __le16_to_cpu(setup->wValue);
|
||||||
index = __le16_to_cpu(setup->wIndex);
|
index = __le16_to_cpu(setup->wIndex);
|
||||||
length = __le16_to_cpu(setup->wLength);
|
length = __le16_to_cpu(setup->wLength);
|
||||||
|
|
||||||
if (setup->bRequestType == USB_REQ_CCID) {
|
if (setup->bRequestType == USB_REQ_CCID) {
|
||||||
switch(setup->bRequest) {
|
switch(setup->bRequest) {
|
||||||
case CCID_CONTROL_ABORT:
|
case CCID_CONTROL_ABORT:
|
||||||
{
|
sc_debug(ctx, "ABORT");
|
||||||
sc_debug(ctx, "ABORT");
|
if (length != 0x00) {
|
||||||
if (length != 0x00) {
|
sc_debug(ctx, "warning: malformed ABORT");
|
||||||
sc_debug(ctx, "warning: malformed ABORT");
|
}
|
||||||
}
|
|
||||||
result = 0;
|
result = 0;
|
||||||
} break;
|
break;
|
||||||
|
|
||||||
case CCID_CONTROL_GET_CLOCK_FREQUENCIES:
|
case CCID_CONTROL_GET_CLOCK_FREQUENCIES:
|
||||||
{
|
sc_debug(ctx, "GET_CLOCK_FREQUENCIES");
|
||||||
sc_debug(ctx, "GET_CLOCK_FREQUENCIES");
|
if (value != 0x00) {
|
||||||
if (value != 0x00) {
|
sc_debug(ctx, "warning: malformed GET_CLOCK_FREQUENCIES");
|
||||||
sc_debug(ctx, "warning: malformed GET_CLOCK_FREQUENCIES");
|
}
|
||||||
}
|
|
||||||
|
result = sizeof(__le32);
|
||||||
|
tmp = realloc(*outbuf, result);
|
||||||
|
if (!tmp) {
|
||||||
|
result = SC_ERROR_OUT_OF_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*outbuf = tmp;
|
||||||
|
__le32 clock = ccid_desc.dwDefaultClock;
|
||||||
|
memcpy(*outbuf, &clock, sizeof (__le32));
|
||||||
|
break;
|
||||||
|
|
||||||
result = sizeof(__le32);
|
|
||||||
tmp = realloc(*outbuf, result);
|
|
||||||
if (tmp == NULL) {
|
|
||||||
result = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*outbuf = tmp;
|
|
||||||
__le32 clock = ccid_desc.dwDefaultClock;
|
|
||||||
memcpy(*outbuf, &clock, sizeof (__le32));
|
|
||||||
} break;
|
|
||||||
case CCID_CONTROL_GET_DATA_RATES:
|
case CCID_CONTROL_GET_DATA_RATES:
|
||||||
{
|
sc_debug(ctx, "GET_DATA_RATES");
|
||||||
sc_debug(ctx, "GET_DATA_RATES");
|
if (value != 0x00) {
|
||||||
if (value != 0x00) {
|
sc_debug(ctx, "warning: malformed GET_DATA_RATES");
|
||||||
sc_debug(ctx, "warning: malformed GET_DATA_RATES");
|
}
|
||||||
}
|
|
||||||
|
result = sizeof (__le32);
|
||||||
|
tmp = realloc(*outbuf, result);
|
||||||
|
if (tmp == NULL) {
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*outbuf = tmp;
|
||||||
|
__le32 drate = ccid_desc.dwDataRate;
|
||||||
|
memcpy(*outbuf, &drate, sizeof (__le32));
|
||||||
|
break;
|
||||||
|
|
||||||
result = sizeof (__le32);
|
|
||||||
tmp = realloc(*outbuf, result);
|
|
||||||
if (tmp == NULL) {
|
|
||||||
result = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*outbuf = tmp;
|
|
||||||
__le32 drate = ccid_desc.dwDataRate;
|
|
||||||
memcpy(*outbuf, &drate, sizeof (__le32));
|
|
||||||
} break;
|
|
||||||
default:
|
default:
|
||||||
sc_debug(ctx, "unknown ccid control command");
|
sc_debug(ctx, "unknown ccid control command");
|
||||||
|
|
||||||
|
result = SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result < 0)
|
||||||
|
debug_sc_result(result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user