- added defines for pin modification

- debugging apdu and rapdu there where they are created
- splitted pin block operations into several functions


git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@26 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
frankmorgner
2010-01-23 21:37:52 +00:00
parent ca8e202b53
commit afeea72f23
3 changed files with 216 additions and 143 deletions

View File

@@ -58,15 +58,10 @@ ccid_desc = {
int ccid_initialize(int reader_id, int verbose)
{
sc_context_param_t ctx_param;
int sc_result;
int i;
memset(&ctx_param, 0, sizeof(ctx_param));
//ctx_param.ver = 0;
//ctx_param.app_name = app_name;
sc_result = sc_context_create(&ctx, &ctx_param);
sc_result = sc_context_create(&ctx, NULL);
if (sc_result < 0) {
fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(sc_result));
return 0;
@@ -126,11 +121,11 @@ int ccid_shutdown()
return 1;
}
int build_apdu(const __u8 *buf, size_t len, sc_apdu_t *apdu)
{
const __u8 *p;
size_t len0;
char dbg[40];
len0 = len;
if (len < 4) {
@@ -183,13 +178,22 @@ int build_apdu(const __u8 *buf, size_t len, sc_apdu_t *apdu)
apdu->flags = SC_APDU_FLAGS_NO_GET_RESP|SC_APDU_FLAGS_NO_RETRY_WL;
snprintf(dbg, sizeof dbg, "APDU, %d byte(s):\tins=%02x p1=%02x p2=%02x",
(unsigned int) len, apdu->ins, apdu->p1, apdu->p2);
sc_ui_display_debug(ctx, dbg);
return 1;
}
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 || !sc_result)
char dbg[40];
if (!apdu || !buf || !resplen || slot > sizeof card_in_slot || !sc_result) {
if (sc_result)
*sc_result = SC_ERROR_INVALID_ARGUMENTS;
goto err;
}
apdu->resplen = apdu->le;
/* Get two more bytes to later use as return buffer including sw1 and sw2 */
@@ -215,6 +219,10 @@ int get_rapdu(sc_apdu_t *apdu, size_t slot, __u8 **buf, size_t *resplen, int *sc
*buf = apdu->resp;
*resplen = apdu->resplen + sizeof(__u8) + sizeof(__u8);
snprintf(dbg, sizeof dbg, "R-APDU, %d byte(s):\tsw1=%02x sw2=%02x",
(unsigned int) *resplen, apdu->sw1, apdu->sw2);
sc_ui_display_debug(ctx, dbg);
return 1;
err:
@@ -403,7 +411,6 @@ RDR_to_PC_DataBlock_t
perform_PC_to_RDR_XfrBlock(const PC_to_RDR_XfrBlock_t request, const __u8*
abDataIn, __u8** abDataOut)
{
char buf[50];
int sc_result;
size_t resplen = 0;
sc_apdu_t apdu;
@@ -420,20 +427,12 @@ perform_PC_to_RDR_XfrBlock(const PC_to_RDR_XfrBlock_t request, const __u8*
goto err;
}
snprintf(buf, sizeof buf, "APDU, %d byte(s):\tins=%02x p1=%02x p2=%02x lc=%02x le=%02x",
request.dwLength, apdu.ins, apdu.p1, apdu.p2, (int) apdu.lc, (int) apdu.le);
sc_ui_display_debug(ctx, buf);
if (!get_rapdu(&apdu, request.bSlot, abDataOut, &resplen, &sc_result))
goto err;
snprintf(buf, sizeof buf, "RAPDU, %d byte(s):\tsw1=%02x sw2=%02x",
(int) resplen, apdu.sw1, apdu.sw2);
sc_ui_display_debug(ctx, buf);
get_rapdu(&apdu, request.bSlot, abDataOut, &resplen, &sc_result);
err:
if (sc_result < 0)
sc_ui_display_error(ctx, sc_strerror(sc_result));
return get_RDR_to_PC_DataBlock(request.bSlot, request.bSeq,
sc_result, __cpu_to_le32(resplen));
}
@@ -536,11 +535,165 @@ perform_PC_to_RDR_GetParamters(const PC_to_RDR_GetParameters_t request,
SC_SUCCESS, abProtocolDataStructure);
}
int
get_effective_offset(uint8_t system_units, uint8_t off, size_t *eff_off,
int *sc_result)
{
if (!eff_off || !sc_result) {
if (sc_result)
*sc_result = SC_ERROR_INVALID_ARGUMENTS;
return 0;
}
if (system_units)
*eff_off = off;
else
if (off == 0)
*eff_off = 0;
else if (off == 8)
*eff_off = 1;
*sc_result = SC_SUCCESS;
return 1;
}
int
write_pin_length(sc_apdu_t *apdu, const struct sc_pin_cmd_pin *pin,
uint8_t system_units, uint8_t length_size, int *sc_result)
{
u8 *p;
if (!apdu || !apdu->data || !pin || apdu->datalen <= pin->length_offset || !sc_result) {
if (sc_result)
*sc_result = SC_ERROR_INVALID_ARGUMENTS;
return 0;
}
if (length_size) {
if (length_size != 8) {
*sc_result = SC_ERROR_NOT_SUPPORTED;
return 0;
}
p = (u8 *) apdu->data;
p[pin->length_offset] = pin->len;
}
*sc_result = SC_SUCCESS;
return 1;
}
int
encode_pin(u8 *buf, size_t buf_len, struct sc_pin_cmd_pin *pin,
uint8_t encoding, int *sc_result)
{
const u8 *p;
if (!pin || !buf || !sc_result) {
if (sc_result)
*sc_result = SC_ERROR_INVALID_ARGUMENTS;
return 0;
}
if (encoding == CCID_PIN_ENCODING_BIN) {
for (p = pin->data; *p && buf_len>0; buf++, p++, buf_len--) {
switch (*p) {
case '0':
*buf = 0x00;
break;
case '1':
*buf = 0x01;
break;
case '2':
*buf = 0x02;
break;
case '3':
*buf = 0x03;
break;
case '4':
*buf = 0x04;
break;
case '5':
*buf = 0x05;
break;
case '6':
*buf = 0x06;
break;
case '7':
*buf = 0x07;
break;
case '8':
*buf = 0x08;
break;
case '9':
*buf = 0x09;
break;
default:
*sc_result = SC_ERROR_INVALID_ARGUMENTS;
return 0;
}
}
if (!buf_len && *p) {
*sc_result = SC_ERROR_OUT_OF_MEMORY;
return 0;
}
*sc_result = SC_SUCCESS;
} else {
if (encoding == CCID_PIN_ENCODING_BCD)
pin->encoding = SC_PIN_ENCODING_BCD;
else if (encoding == CCID_PIN_ENCODING_ASCII)
pin->encoding = SC_PIN_ENCODING_ASCII;
else {
*sc_result = SC_ERROR_NOT_SUPPORTED;
return 0;
}
*sc_result = sc_build_pin(buf, buf_len, pin, 0);
if (*sc_result < 0)
return 0;
}
return 1;
}
int
write_pin(sc_apdu_t *apdu, struct sc_pin_cmd_pin *pin, uint8_t blocksize,
uint8_t justify_right, uint8_t encoding, int *sc_result)
{
/* offset due to right alignment */
uint8_t justify_offset;
if (!apdu || !pin || !sc_result) {
if (sc_result)
*sc_result = SC_ERROR_INVALID_ARGUMENTS;
return 0;
}
if (justify_right) {
if (encoding == CCID_PIN_ENCODING_BCD) {
if (pin->len % 2) {
*sc_result = SC_ERROR_NOT_SUPPORTED;
return 0;
} else
justify_offset = blocksize - pin->len/2;
} else
justify_offset = blocksize - pin->len;
}
else
justify_offset = 0;
return encode_pin((u8 *) apdu->data + justify_offset,
blocksize - justify_offset, pin, encoding, sc_result);
}
RDR_to_PC_DataBlock_t
perform_PC_to_RDR_Secure(const PC_to_RDR_Secure_t request,
const __u8* abData, __u8** abDataOut)
{
char buf[50];
char dbg[256];
int sc_result = SC_SUCCESS;
size_t resplen = 0;
sc_apdu_t apdu;
@@ -603,21 +756,33 @@ perform_PC_to_RDR_Secure(const PC_to_RDR_Secure_t request,
}
apdu.sensitive = 1;
snprintf(buf, sizeof buf, "APDU, %d byte(s):\tins=%02x p1=%02x p2=%02x lc=%02x le=%02x",
request.dwLength, apdu.ins, apdu.p1, apdu.p2, (int) apdu.lc, (int) apdu.le);
sc_ui_display_debug(ctx, buf);
__u8 *p;
/* Note: offset and length_offset are relative to the first databyte */
pin.min_length = wPINMaxExtraDigit >> 8;
pin.max_length = wPINMaxExtraDigit & 0x00ff;
pin.offset = (bmFormatString >> 3) & 0xf;
uint8_t system_units_bytes = bmFormatString & CCID_PIN_UNITS_BYTES;
uint8_t system_units = bmFormatString & CCID_PIN_UNITS_BYTES;
uint8_t pin_offset = (bmFormatString >> 3) & 0xf;
uint8_t length_offset = bmPINLengthFormat & 0xf;
uint8_t length_size = bmPINBlockString >> 4;
uint8_t justify_right = bmFormatString & CCID_PIN_JUSTIFY_RIGHT;
uint8_t encoding = bmFormatString & 2;
uint8_t offset_length = bmPINBlockString >> 4;
uint8_t blocksize = bmPINBlockString & 0xf;
uint8_t length_shift = bmPINLengthFormat & 0xf;
snprintf(dbg, sizeof dbg,
"PIN block (%d bytes) proberties:\n"
"\tminimum %d, maximum %d PIN digits\n"
"\t%s PIN encoding, %s justification\n"
"\tsystem units are %s\n"
"\twrite PIN length on %d bits with %d system units offset\n"
"\tPIN offset is %d %s\n",
blocksize, (unsigned int) pin.min_length,
(unsigned int) pin.max_length,
encoding == CCID_PIN_ENCODING_BIN ? "binary" :
encoding == CCID_PIN_ENCODING_BCD ? "BCD" :
encoding == CCID_PIN_ENCODING_ASCII ? "ASCII" :"unknown",
justify_right ? "right" : "left",
system_units ? "bytes" : "bits",
length_size, length_offset, pin_offset,
modify ? "bytes" : "system units");
sc_ui_display_debug(ctx, dbg);
/* get the PIN */
hints.prompt = "PIN Verification";
@@ -628,123 +793,28 @@ perform_PC_to_RDR_Secure(const PC_to_RDR_Secure_t request,
if (sc_result < 0)
goto err;
/* check length of PIN */
pin.len = strlen((char *)pin.data);
if (pin.len > pin.max_length || pin.len < pin.min_length) {
/* set and check length of PIN */
pin.len = strlen((char *) pin.data);
if ((pin.max_length && pin.len > pin.max_length)
|| pin.len < pin.min_length) {
sc_result = SC_ERROR_PIN_CODE_INCORRECT;
goto err;
}
/* write length of PIN */
if (offset_length) {
if (offset_length == 8) {
if (system_units_bytes) {
pin.length_offset = length_shift;
} else {
if (length_shift == 0)
pin.length_offset = 0;
if (length_shift == 8)
pin.length_offset = 1;
else {
goto err;
}
}
p = (u8 *) apdu.data + pin.length_offset;
*p = pin.len;
} else {
goto err;
}
}
/* offset due to right alignment */
uint8_t justify_offset;
if (justify_right) {
if (encoding == CCID_PIN_ENCODING_BCD) {
if (pin.len % 2)
goto err;
else
justify_offset = pin.len/2;
} else
justify_offset = blocksize - pin.len;
}
else
justify_offset = 0;
/* set p to the first byte where to write the PIN */
if (system_units_bytes) {
p = (u8 *) apdu.data + pin.offset + justify_offset;
} else {
if (pin.offset == 0)
p = (u8 *) apdu.data + justify_offset;
else if (pin.offset == 8)
p = (u8 *) apdu.data + 1 + justify_offset;
else {
goto err;
}
}
/* encode and write the pin into the APDU */
const u8 *ppin;
if (encoding == CCID_PIN_ENCODING_BIN) {
for (ppin = pin.data; *ppin; p++, ppin++) {
switch (*ppin) {
case '0':
*p = 0x00;
break;
case '1':
*p = 0x01;
break;
case '2':
*p = 0x02;
break;
case '3':
*p = 0x03;
break;
case '4':
*p = 0x04;
break;
case '5':
*p = 0x05;
break;
case '6':
*p = 0x06;
break;
case '7':
*p = 0x07;
break;
case '8':
*p = 0x08;
break;
case '9':
*p = 0x09;
break;
default:
sc_result = SC_ERROR_PIN_CODE_INCORRECT;
goto err;
}
}
} else {
if (encoding == CCID_PIN_ENCODING_BCD)
pin.encoding = SC_PIN_ENCODING_BCD;
else if (encoding == CCID_PIN_ENCODING_ASCII)
pin.encoding = SC_PIN_ENCODING_ASCII;
else {
sc_result = SC_ERROR_NOT_SUPPORTED;
goto err;
}
sc_result = sc_build_pin(p, abPINApdu - p, &pin, 0);
if (sc_result < 0) {
goto err;
}
}
if (!get_rapdu(&apdu, request.bSlot, abDataOut, &resplen, &sc_result))
/* Note: pin.offset and pin.length_offset are relative to the first
* databyte */
if (!get_effective_offset(system_units, pin_offset, &pin.offset,
&sc_result)
|| !get_effective_offset(system_units, length_offset,
&pin.length_offset, &sc_result)
|| !write_pin_length(&apdu, &pin, system_units, length_size,
&sc_result)
|| !write_pin(&apdu, &pin, blocksize, justify_right, encoding,
&sc_result)
|| !get_rapdu(&apdu, request.bSlot, abDataOut, &resplen,
&sc_result))
goto err;
snprintf(buf, sizeof buf, "RAPDU, %d byte(s):\tsw1=%02x sw2=%02x",
(int) resplen, apdu.sw1, apdu.sw2);
sc_ui_display_debug(ctx, buf);
err:
if (sc_result < 0)
sc_ui_display_error(ctx, sc_strerror(sc_result));

View File

@@ -69,6 +69,9 @@ extern "C" {
#define CCID_PIN_UNITS_BYTES 0x80
#define CCID_PIN_JUSTIFY_RIGHT 0x04
#define CCID_PIN_CONFIRM_NEW 0x01
#define CCID_PIN_INSERT_OLD 0x02
#define CCID_SLOTS_UNCHANGED 0x00
#define CCID_SLOT1_CARD_PRESENT 0x01
#define CCID_SLOT1_CHANGED 0x02

View File

@@ -54,8 +54,8 @@
#define DRIVER_PRODUCT_NUM 0x3010 /* KOBIL Class 3 Reader */
static int vendorid = DRIVER_VENDOR_NUM;
static int productid = DRIVER_PRODUCT_NUM;
static int verbose = 1;
static int debug = 1;
static int verbose = 0;
static int debug = 0;
static int dohid = 0;
static int doint = 0;
int usb_reader_num = 0;