Skip to content

Commit

Permalink
- added patch to distribution package
Browse files Browse the repository at this point in the history
- changed debug_sc_result to be a define. this now gets the line of code correct
- added checking for input length to functions that parse the bulkin buffer
- fixed segfault for GetReadersPACECapabilities when no card is inserted
- added length checking of input for EstablishPACEChannel
- ccid-test: fixed pbSendBufferEstablish
- pcsclite_trunk.patch:
  - fixed parsing of lengthCertificateDescription
  - fixed wrong bPINOperation for pace capabilities and execute pace


git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@156 96b47cad-a561-4643-ad3b-153ac7d7599c
  • Loading branch information
frankmorgner committed Jun 19, 2010
1 parent d931be9 commit 97e9cc2
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 40 deletions.
1 change: 1 addition & 0 deletions ccid/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
EXTRA_DIST = pcsclite_trunk.patch
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src m4
8 changes: 4 additions & 4 deletions ccid/pcsclite_trunk.patch
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,10 @@ Index: Drivers/ccid/src/commands.c
+ lengthCertificateDescription = *((uint16_t *)
+ (TxBuffer + 1 + lengthCHAT + lengthPIN));
+
+ if (TxLength != 4+lengthCHAT+lengthPIN+lengthCertificateDescription) {
+ if (TxLength != 5+lengthCHAT+lengthPIN+lengthCertificateDescription) {
+ DEBUG_CRITICAL3("Buffer too small or too big to contain only "
+ "CHAT, PIN and certificate description (expected %u, got %u)",
+ 4+lengthCHAT+lengthPIN+lengthCertificateDescription, TxLength);
+ 5+lengthCHAT+lengthPIN+lengthCertificateDescription, TxLength);
+ return_value = IFD_COMMUNICATION_ERROR;
+ goto err;
+ }
Expand All @@ -147,7 +147,7 @@ Index: Drivers/ccid/src/commands.c
+
+ /* bPINOperation: PIN PACE Capabilities */
+ return_value = SecurePINPACE(reader_index, TxBuffer, TxLength, RxBuffer,
+ RxLength, CCID_CLASS_PIN_PACE_CAPABILITIES);
+ RxLength, CCID_CLASS_PIN_PACE_EXECUTE);
+
+err:
+ ccid_descriptor -> readTimeout = old_read_timeout;
Expand All @@ -160,7 +160,7 @@ Index: Drivers/ccid/src/commands.c
+{
+ /* bPINOperation: PIN PACE Capabilities */
+ return SecurePINPACE(reader_index, TxBuffer, TxLength, RxBuffer,
+ RxLength, CCID_CLASS_PIN_PACE_EXECUTE);
+ RxLength, CCID_CLASS_PIN_PACE_CAPABILITIES);
+}
+
+static RESPONSECODE SecurePINPACE(unsigned int reader_index,
Expand Down
3 changes: 2 additions & 1 deletion ccid/src/ccid-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,14 @@ main(int argc, char *argv[])
0x00, /* lengthInputData */
0x03, /* PACE with PIN */
0x00, /* length CHAT */
0x00, /* length PIN */
0x00, /* length certificate description */
0x00, /* length certificate description */
};
BYTE pbRecvBuffer[1024];
DWORD dwActiveProtocol, dwRecvLength, dwReaders;

uint16_t lengthInputData = 4;
uint16_t lengthInputData = 5;
memcpy(pbSendBufferEstablish + 1, &lengthInputData, 2);

if (argc > 1) {
Expand Down
101 changes: 77 additions & 24 deletions ccid/src/ccid.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,12 @@ ccid_desc = {
.bMaxCCIDBusySlots = 0x01,
};

static void
debug_sc_result(int sc_result)
{
sc_debug(ctx, sc_strerror(sc_result));
#define debug_sc_result(sc_result) \
{ \
if (sc_result < 0) \
sc_error(ctx, sc_strerror(sc_result)); \
else \
sc_debug(ctx, sc_strerror(sc_result)); \
}

static int
Expand Down Expand Up @@ -329,13 +331,16 @@ get_RDR_to_PC_DataBlock(__u8 bSlot, __u8 bSeq, int sc_result, RDR_to_PC_DataBloc
}

static int
perform_PC_to_RDR_GetSlotStatus(const __u8 *in, __u8 **out, size_t *outlen)
perform_PC_to_RDR_GetSlotStatus(const __u8 *in, size_t inlen, __u8 **out, size_t *outlen)
{
const PC_to_RDR_GetSlotStatus_t *request = (PC_to_RDR_GetSlotStatus_t *) in;

if (!out || !outlen || !in)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_ARGUMENTS);

if (inlen < sizeof *request)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_DATA);

*outlen = sizeof(RDR_to_PC_SlotStatus_t);

if ( request->bMessageType != 0x65 ||
Expand All @@ -350,7 +355,7 @@ perform_PC_to_RDR_GetSlotStatus(const __u8 *in, __u8 **out, size_t *outlen)
}

static int
perform_PC_to_RDR_IccPowerOn(const __u8 *in, __u8 **out, size_t *outlen)
perform_PC_to_RDR_IccPowerOn(const __u8 *in, size_t inlen, __u8 **out, size_t *outlen)
{
const PC_to_RDR_IccPowerOn_t *request = (PC_to_RDR_IccPowerOn_t *) in;
int sc_result;
Expand All @@ -359,6 +364,9 @@ perform_PC_to_RDR_IccPowerOn(const __u8 *in, __u8 **out, size_t *outlen)
if (!out || !outlen || !in)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_ARGUMENTS);

if (inlen < sizeof *request)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_DATA);

if ( request->bMessageType != 0x62 ||
request->dwLength != __constant_cpu_to_le32(0) ||
!( request->bPowerSelect == 0 ||
Expand Down Expand Up @@ -408,14 +416,17 @@ perform_PC_to_RDR_IccPowerOn(const __u8 *in, __u8 **out, size_t *outlen)
}

static int
perform_PC_to_RDR_IccPowerOff(const __u8 *in, __u8 **out, size_t *outlen)
perform_PC_to_RDR_IccPowerOff(const __u8 *in, size_t inlen, __u8 **out, size_t *outlen)
{
const PC_to_RDR_IccPowerOff_t *request = (PC_to_RDR_IccPowerOff_t *) in;
int sc_result;

if (!in || !out || !outlen)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_ARGUMENTS);

if (inlen < sizeof *request)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_DATA);

if ( request->bMessageType != 0x63 ||
request->dwLength != __constant_cpu_to_le32(0) ||
request->abRFU1 != 0 ||
Expand All @@ -438,7 +449,7 @@ perform_PC_to_RDR_IccPowerOff(const __u8 *in, __u8 **out, size_t *outlen)
}

static int
perform_PC_to_RDR_XfrBlock(const u8 *in, __u8** out, size_t *outlen)
perform_PC_to_RDR_XfrBlock(const u8 *in, size_t inlen, __u8** out, size_t *outlen)
{
const PC_to_RDR_XfrBlock_t *request = (PC_to_RDR_XfrBlock_t *) in;
const __u8 *abDataIn = in + sizeof *request;
Expand All @@ -451,6 +462,9 @@ perform_PC_to_RDR_XfrBlock(const u8 *in, __u8** out, size_t *outlen)
if (!in || !out || !outlen)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_ARGUMENTS);

if (inlen < sizeof *request)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_DATA);

if ( request->bMessageType != 0x6F ||
request->bBWI != 0)
sc_debug(ctx, "malformed PC_to_RDR_XfrBlock, will continue anyway");
Expand Down Expand Up @@ -497,7 +511,7 @@ perform_PC_to_RDR_XfrBlock(const u8 *in, __u8** out, size_t *outlen)
}

static int
perform_PC_to_RDR_GetParamters(const __u8 *in, __u8** out, size_t *outlen)
perform_PC_to_RDR_GetParamters(const __u8 *in, size_t inlen, __u8** out, size_t *outlen)
{
const PC_to_RDR_GetParameters_t *request = (PC_to_RDR_GetParameters_t *) in;
RDR_to_PC_Parameters_t *result;
Expand All @@ -508,6 +522,9 @@ perform_PC_to_RDR_GetParamters(const __u8 *in, __u8** out, size_t *outlen)
if (!in || !out || !outlen)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_ARGUMENTS);

if (inlen < sizeof *request)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_DATA);

if ( request->bMessageType != 0x6C ||
request->dwLength != __constant_cpu_to_le32(0))
sc_debug(ctx, "warning: malformed PC_to_RDR_GetParamters");
Expand Down Expand Up @@ -751,21 +768,25 @@ write_pin(sc_apdu_t *apdu, struct sc_pin_cmd_pin *pin, uint8_t blocksize,
}

static int
perform_PC_to_RDR_Secure(const __u8 *in, __u8** out, size_t *outlen)
perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outlen)
{
int sc_result, r;
struct sc_pin_cmd_pin curr_pin, new_pin;
sc_apdu_t apdu;
sc_ui_hints_t hints;
const PC_to_RDR_Secure_t *request = (PC_to_RDR_Secure_t *) in;
const __u8* abData = in + sizeof *request;
size_t abDatalen = inlen - sizeof *request;
u8 *abDataOut = NULL;
size_t resplen = 0;
RDR_to_PC_DataBlock_t *result;

if (!in || !out || !outlen)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_ARGUMENTS);

if (inlen < sizeof *request + 1)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_DATA);

if (request->bMessageType != 0x69)
sc_debug(ctx, "warning: malformed PC_to_RDR_Secure");

Expand Down Expand Up @@ -793,6 +814,12 @@ perform_PC_to_RDR_Secure(const __u8 *in, __u8** out, size_t *outlen)
// PIN Verification
verify = (abPINDataStucture_Verification_t *)
(abData + sizeof(__u8));

if (abDatalen < sizeof *verify) {
sc_result = SC_ERROR_INVALID_DATA;
goto err;
}

wPINMaxExtraDigit = verify->wPINMaxExtraDigit;
bmPINLengthFormat = verify->bmPINLengthFormat;
bmPINBlockString = verify->bmPINBlockString;
Expand All @@ -805,6 +832,13 @@ perform_PC_to_RDR_Secure(const __u8 *in, __u8** out, size_t *outlen)
// PIN Modification
modify = (abPINDataStucture_Modification_t *)
(abData + sizeof(__u8));

if (abDatalen < sizeof *modify) {
sc_error(ctx, "Not enough data for abPINDataStucture_Modification_t");
sc_result = SC_ERROR_INVALID_DATA;
goto err;
}

wPINMaxExtraDigit = modify->wPINMaxExtraDigit;
bmPINLengthFormat = modify->bmPINLengthFormat;
bmPINBlockString = modify->bmPINBlockString;
Expand All @@ -815,21 +849,37 @@ perform_PC_to_RDR_Secure(const __u8 *in, __u8** out, size_t *outlen)
break;
#ifdef WITH_PACE
case 0x10:

if (abDatalen < 1) {
sc_error(ctx, "Not enough data for input of GetReadersPACECapabilities");
sc_result = SC_ERROR_INVALID_DATA;
goto err;
}

sc_result =
GetReadersPACECapabilities(card_in_slot[request->bSlot],
abData + 1, &abDataOut, &resplen);
abData + 1, abDatalen-1, &abDataOut, &resplen);
goto err;
break;
case 0x20:

if (abDatalen < 1) {
sc_error(ctx, "Not enough data for input of EstablishPACEChannel");
sc_result = SC_ERROR_INVALID_DATA;
goto err;
}

sc_result = EstablishPACEChannel(&sctx,
card_in_slot[request->bSlot], abData + 1, &abDataOut,
&resplen, &sctx);
card_in_slot[request->bSlot], abData + 1, abDatalen-1,
&abDataOut, &resplen, &sctx);
goto err;
break;
#endif
case 0x04:
// Cancel PIN function
default:
sc_error(ctx, "PIN operation not supported (bPINOperation=%02x).",
*abData);
sc_result = SC_ERROR_NOT_SUPPORTED;
goto err;
}
Expand Down Expand Up @@ -1039,14 +1089,17 @@ get_RDR_to_PC_NotifySlotChange(RDR_to_PC_NotifySlotChange_t **out)
}

static int
perform_unknown(const __u8 *in, __u8 **out, size_t *outlen)
perform_unknown(const __u8 *in, size_t inlen, __u8 **out, size_t *outlen)
{
const PC_to_RDR_GetSlotStatus_t *request = (PC_to_RDR_GetSlotStatus_t *) in;
RDR_to_PC_SlotStatus_t *result;

if (!in || !out || !outlen)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_ARGUMENTS);

if (inlen < sizeof *request)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_DATA);

result = realloc(*out, sizeof *result);
if (!result)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_OUT_OF_MEMORY);
Expand Down Expand Up @@ -1096,7 +1149,7 @@ perform_unknown(const __u8 *in, __u8 **out, size_t *outlen)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_SUCCESS);
}

int ccid_parse_bulkin(const __u8* inbuf, __u8** outbuf)
int ccid_parse_bulkin(const __u8* inbuf, size_t inlen, __u8** outbuf)
{
int sc_result;
size_t outlen;
Expand All @@ -1107,38 +1160,38 @@ int ccid_parse_bulkin(const __u8* inbuf, __u8** outbuf)
switch (*inbuf) {
case 0x62:
sc_debug(ctx, "PC_to_RDR_IccPowerOn");
sc_result = perform_PC_to_RDR_IccPowerOn(inbuf, outbuf, &outlen);
sc_result = perform_PC_to_RDR_IccPowerOn(inbuf, inlen, outbuf, &outlen);
break;

case 0x63:
sc_debug(ctx, "PC_to_RDR_IccPowerOff");
sc_result = perform_PC_to_RDR_IccPowerOff(inbuf, outbuf, &outlen);
sc_result = perform_PC_to_RDR_IccPowerOff(inbuf, inlen, outbuf, &outlen);
break;

case 0x65:
sc_debug(ctx, "PC_to_RDR_GetSlotStatus");
sc_result = perform_PC_to_RDR_GetSlotStatus(inbuf, outbuf, &outlen);
sc_result = perform_PC_to_RDR_GetSlotStatus(inbuf, inlen, outbuf, &outlen);
break;

case 0x6F:
sc_debug(ctx, "PC_to_RDR_XfrBlock");
sc_result = perform_PC_to_RDR_XfrBlock(inbuf, outbuf, &outlen);
sc_result = perform_PC_to_RDR_XfrBlock(inbuf, inlen, outbuf, &outlen);
break;

case 0x6C:
sc_debug(ctx, "PC_to_RDR_GetParameters");
sc_result = perform_PC_to_RDR_GetParamters(inbuf, outbuf, &outlen);
sc_result = perform_PC_to_RDR_GetParamters(inbuf, inlen, outbuf, &outlen);
break;

case 0x69:
sc_debug(ctx, "PC_to_RDR_Secure");
sc_result = perform_PC_to_RDR_Secure(inbuf, outbuf, &outlen);
sc_result = perform_PC_to_RDR_Secure(inbuf, inlen, outbuf, &outlen);
break;

default:
sc_debug(ctx, "Unknown ccid bulk-in message. "
"Starting default handler.");
sc_result = perform_unknown(inbuf, outbuf, &outlen);
sc_error(ctx, "Unknown ccid bulk-in message. "
"Starting default handler...");
sc_result = perform_unknown(inbuf, inlen, outbuf, &outlen);
}

if (sc_result < 0) {
Expand Down
2 changes: 1 addition & 1 deletion ccid/src/ccid.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ struct hid_class_descriptor {
int ccid_initialize(int reader_id, const char *cdriver, int verbose);
void ccid_shutdown();

int ccid_parse_bulkin(const __u8* inbuf, __u8** outbuf);
int ccid_parse_bulkin(const __u8* inbuf, size_t inlen, __u8** outbuf);
int ccid_parse_control(struct usb_ctrlrequest *setup, __u8 **outbuf);
int ccid_state_changed(RDR_to_PC_NotifySlotChange_t **slotchange, int timeout);

Expand Down
3 changes: 2 additions & 1 deletion ccid/src/pace-tool.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ int pace_get_channel(struct sm_ctx *oldpacectx, sc_card_t *card,
memcpy(&buf[3 + chatlen + pinlen + sizeof word],
desc, desclen);

return EstablishPACEChannel(oldpacectx, card, buf, out, outlen, sctx);
return EstablishPACEChannel(oldpacectx, card, buf,
1+pinlen+1+chatlen+2+desclen, out, outlen, sctx);
}

int pace_translate_apdus(struct sm_ctx *sctx, sc_card_t *card)
Expand Down
Loading

0 comments on commit 97e9cc2

Please sign in to comment.