- added patch to distribution package

- 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
This commit is contained in:
frankmorgner
2010-06-19 16:19:51 +00:00
parent d931be9df0
commit 97e9cc2091
9 changed files with 131 additions and 40 deletions

View File

@@ -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) {

View File

@@ -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
@@ -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 ||
@@ -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;
@@ -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 ||
@@ -408,7 +416,7 @@ 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;
@@ -416,6 +424,9 @@ perform_PC_to_RDR_IccPowerOff(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 != 0x63 ||
request->dwLength != __constant_cpu_to_le32(0) ||
request->abRFU1 != 0 ||
@@ -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;
@@ -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");
@@ -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;
@@ -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");
@@ -751,7 +768,7 @@ 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;
@@ -759,6 +776,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, __u8** out, size_t *outlen)
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;
@@ -766,6 +784,9 @@ perform_PC_to_RDR_Secure(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 + 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");
@@ -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;
@@ -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;
@@ -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;
}
@@ -1039,7 +1089,7 @@ 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;
@@ -1047,6 +1097,9 @@ perform_unknown(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);
result = realloc(*out, sizeof *result);
if (!result)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_OUT_OF_MEMORY);
@@ -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;
@@ -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) {

View File

@@ -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);

View File

@@ -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)

View File

@@ -161,13 +161,17 @@ IMPLEMENT_ASN1_FUNCTIONS(PACE_GEN_AUTH_R)
const size_t maxresp = SC_MAX_APDU_BUFFER_SIZE - 2;
int GetReadersPACECapabilities(sc_card_t *card,
const __u8 *in, __u8 **out, size_t *outlen) {
const __u8 *in, size_t inlen, __u8 **out, size_t *outlen) {
if (!out || !outlen)
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_ARGUMENTS);
__u8 *result = realloc(*out, 2);
if (!result)
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_OUT_OF_MEMORY);
if (!result) {
if (card)
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_OUT_OF_MEMORY);
else
return SC_ERROR_OUT_OF_MEMORY;
}
*out = result;
*outlen = 2;
@@ -177,7 +181,10 @@ int GetReadersPACECapabilities(sc_card_t *card,
/* BitMap */
*result = PACE_BITMAP_PACE|PACE_BITMAP_EID;
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_SUCCESS);
if (card)
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_SUCCESS);
else
return SC_SUCCESS;
}
/** select and read EF.CardAccess */
@@ -675,7 +682,7 @@ void debug_ossl(sc_context_t *ctx) {
}
int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
const __u8 *in, __u8 **out, size_t *outlen, struct sm_ctx *sctx)
const __u8 *in, size_t inlen, __u8 **out, size_t *outlen, struct sm_ctx *sctx)
{
__u8 pin_id;
size_t length_chat, length_pin, length_cert_desc, length_ef_cardaccess;
@@ -692,15 +699,27 @@ int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
int r, second_execution;
if (!card)
return SC_ERROR_INVALID_ARGUMENTS;
return SC_ERROR_CARD_NOT_PRESENT;
if (!in || !out || !outlen)
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_ARGUMENTS);
if (inlen < 1) {
sc_error(card->ctx, "Buffer too small, could not get PinID");
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_DATA);
}
pin_id = *in;
in++;
if (inlen < 1+1) {
sc_error(card->ctx, "Buffer too small, could not get lengthCHAT");
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_DATA);
}
length_chat = *in;
in++;
if (inlen < 1+1+length_chat) {
sc_error(card->ctx, "Buffer too small, could not get CHAT");
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_DATA);
}
chat = in;
in += length_chat;
/* XXX make this human readable */
@@ -708,14 +727,30 @@ int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
bin_log(card->ctx, "Card holder authorization template",
chat, length_chat);
if (inlen < 1+1+length_chat+1) {
sc_error(card->ctx, "Buffer too small, could not get lengthPIN");
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_DATA);
}
length_pin = *in;
in++;
if (inlen < 1+1+length_chat+1+length_pin) {
sc_error(card->ctx, "Buffer too small, could not get PIN");
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_DATA);
}
pin = in;
in += length_pin;
if (inlen < 1+1+length_chat+1+length_pin+sizeof(word)) {
sc_error(card->ctx, "Buffer too small, could not get lengthCertificateDescription %d %d",1+1+length_chat+1+length_pin+sizeof(word), inlen);
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_DATA);
}
memcpy(&word, in, sizeof word);
length_cert_desc = __le16_to_cpu(word);
in += sizeof word;
if (inlen < 1+1+length_chat+1+length_pin+sizeof(word)+length_cert_desc) {
sc_error(card->ctx, "Buffer too small, could not get CertificateDescription");
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_DATA);
}
certificate_description = in;
/* XXX make this human readable */
if (length_cert_desc)

View File

@@ -64,9 +64,9 @@ int pace_sm_post_transmit(sc_card_t *card, const struct sm_ctx *ctx,
sc_apdu_t *sm_apdu);
int GetReadersPACECapabilities(sc_card_t *card, const unsigned char *in,
unsigned char **out, size_t *outlen);
size_t inlen, unsigned char **out, size_t *outlen);
int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
const unsigned char *in, unsigned char **out, size_t *outlen, struct sm_ctx *sctx);
const unsigned char *in, size_t inlen, unsigned char **out, size_t *outlen, struct sm_ctx *sctx);
int pace_reset_retry_counter(struct sm_ctx *ctx, sc_card_t *card,
enum s_type pin_id, int ask_for_secret,

View File

@@ -1056,7 +1056,7 @@ static void *ccid (void *param)
fprintf(stderr, "got %d, done.\n", result);
if (!result) break;
result = ccid_parse_bulkin(inbuf, &outbuf);
result = ccid_parse_bulkin(inbuf, result, &outbuf);
if (result < 0) break;
if (verbose > 1)