cleaned up command line options of pace-tool and made it independant from ccid

git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@89 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
frankmorgner
2010-05-04 20:03:54 +00:00
parent fcfbca19d7
commit 170ec3c703
8 changed files with 240 additions and 231 deletions

View File

@@ -21,7 +21,7 @@ INSTALL_PROGRAM = $(INSTALL)
TARGETS = ccid TARGETS = ccid
CCID_OBJ = ccid.o sm.o usbstring.o usb.o util.o CCID_OBJ = ccid.o sm.o usbstring.o usb.o util.o
PTOOL_OBJ = ccid.o sm.o pace-tool.o util.o pace.o pace_lib.o PTOOL_OBJ = sm.o pace-tool.o util.o pace.o pace_lib.o
ifdef PACE ifdef PACE
CCID_OBJ += pace.o pace_lib.o CCID_OBJ += pace.o pace_lib.o
@@ -64,4 +64,4 @@ uninstall:
.PHONY: clean .PHONY: clean
clean: clean:
rm -f $(TARGETS) $(CCID_OBJ) $(PTOOL_OBJ) rm -f $(TARGETS) $(CCID_OBJ) pace-tool $(PTOOL_OBJ)

View File

@@ -27,9 +27,7 @@
#include <opensc/log.h> #include <opensc/log.h>
#include "ccid.h" #include "ccid.h"
#ifndef NO_PACE #include "util.h"
#include "pace.h"
#endif
static sc_context_t *ctx = NULL; static sc_context_t *ctx = NULL;
static sc_card_t *card_in_slot[SC_MAX_SLOTS]; static sc_card_t *card_in_slot[SC_MAX_SLOTS];
@@ -117,56 +115,19 @@ detect_card_presence(int slot)
int ccid_initialize(int reader_id, const char *cdriver, int verbose) int ccid_initialize(int reader_id, const char *cdriver, int verbose)
{ {
unsigned int i, reader_count; int i;
int r = sc_context_create(&ctx, NULL);
if (r < 0) {
printf("Failed to create initial context: %s", sc_strerror(r));
return r;
}
if (cdriver != NULL) {
r = sc_set_card_driver(ctx, cdriver);
if (r < 0) {
sc_error(ctx, "Card driver '%s' not found!\n", cdriver);
return r;
}
}
ctx->debug = verbose;
for (i = 0; i < sizeof *card_in_slot; i++) { for (i = 0; i < sizeof *card_in_slot; i++) {
card_in_slot[i] = NULL; card_in_slot[i] = NULL;
} }
reader_count = sc_ctx_get_reader_count(ctx); i = initialize(reader_id, cdriver, verbose, &ctx, &reader);
if (i < 0)
return i;
if (reader_count == 0)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_NO_READERS_FOUND);
if (reader_id < 0) {
/* Automatically try to skip to a reader with a card if reader not specified */
for (i = 0; i < reader_count; i++) {
reader = sc_ctx_get_reader(ctx, i);
if (sc_detect_card_presence(reader, 0) & SC_SLOT_CARD_PRESENT) {
reader_id = i;
sc_debug(ctx, "Using reader with a card: %s", reader->name);
break;
}
}
if (reader_id >= reader_count) {
/* no reader found, use the first */
reader_id = 0;
}
}
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);
ccid_desc.bMaxSlotIndex = reader->slot_count - 1; ccid_desc.bMaxSlotIndex = reader->slot_count - 1;
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_SUCCESS); return SC_SUCCESS;
} }
void ccid_shutdown() void ccid_shutdown()
@@ -181,71 +142,6 @@ void ccid_shutdown()
sc_release_context(ctx); sc_release_context(ctx);
} }
int build_apdu(const __u8 *buf, size_t len, sc_apdu_t *apdu)
{
const __u8 *p;
size_t len0;
if (!buf || !apdu)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
len0 = len;
if (len < 4) {
sc_error(ctx, "APDU too short (must be at least 4 bytes)");
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_DATA);
}
memset(apdu, 0, sizeof(*apdu));
p = buf;
apdu->cla = *p++;
apdu->ins = *p++;
apdu->p1 = *p++;
apdu->p2 = *p++;
len -= 4;
if (len > 1) {
apdu->lc = *p++;
len--;
apdu->data = p;
apdu->datalen = apdu->lc;
if (len < apdu->lc) {
sc_error(ctx, "APDU too short (need %lu bytes)\n",
(unsigned long) apdu->lc - len);
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_DATA);
}
len -= apdu->lc;
p += apdu->lc;
if (len) {
apdu->le = *p++;
if (apdu->le == 0)
apdu->le = 256;
len--;
apdu->cse = SC_APDU_CASE_4_SHORT;
} else {
apdu->cse = SC_APDU_CASE_3_SHORT;
}
if (len) {
sc_error(ctx, "APDU too long (%lu bytes extra)\n",
(unsigned long) len);
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_DATA);
}
} else if (len == 1) {
apdu->le = *p++;
if (apdu->le == 0)
apdu->le = 256;
len--;
apdu->cse = SC_APDU_CASE_2_SHORT;
} else {
apdu->cse = SC_APDU_CASE_1;
}
apdu->flags = SC_APDU_FLAGS_NO_GET_RESP|SC_APDU_FLAGS_NO_RETRY_WL;
sc_debug(ctx, "APDU, %d bytes:\tins=%02x p1=%02x p2=%02x",
(unsigned int) len0, apdu->ins, apdu->p1, apdu->p2);
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_SUCCESS);
}
static int get_rapdu(sc_apdu_t *apdu, size_t slot, __u8 **buf, size_t *resplen) static int get_rapdu(sc_apdu_t *apdu, size_t slot, __u8 **buf, size_t *resplen)
{ {
int sc_result; int sc_result;
@@ -542,7 +438,7 @@ perform_PC_to_RDR_XfrBlock(const u8 *in, __u8** out, size_t *outlen)
if (request->bSlot > sizeof *card_in_slot) if (request->bSlot > sizeof *card_in_slot)
sc_result = SC_ERROR_INVALID_DATA; sc_result = SC_ERROR_INVALID_DATA;
else { else {
sc_result = build_apdu(abDataIn, request->dwLength, &apdu); sc_result = build_apdu(ctx, abDataIn, request->dwLength, &apdu);
if (sc_result >= 0) if (sc_result >= 0)
sc_result = get_rapdu(&apdu, request->bSlot, &abDataOut, &resplen); sc_result = get_rapdu(&apdu, request->bSlot, &abDataOut, &resplen);
} }
@@ -903,7 +799,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, __u8** out, size_t *outlen)
goto err; goto err;
} }
sc_result = build_apdu(abPINApdu, apdulen, &apdu); sc_result = build_apdu(ctx, abPINApdu, apdulen, &apdu);
if (sc_result < 0) if (sc_result < 0)
goto err; goto err;
apdu.sensitive = 1; apdu.sensitive = 1;
@@ -1306,88 +1202,3 @@ int ccid_state_changed(RDR_to_PC_NotifySlotChange_t **slotchange, int timeout)
return 0; return 0;
} }
#ifdef NO_PACE
int ccid_testpace(u8 pin_id, const char *pin, size_t pinlen,
u8 new_pin_id, const char *new_pin, size_t new_pinlen)
{
sc_error(ctx, "ccid not compiled with support for PACE.");
return SC_ERROR_NOT_SUPPORTED;
}
#else
int ccid_testpace(u8 pin_id, const char *pin, size_t pinlen,
u8 new_pin_id, const char *new_pin, size_t new_pinlen)
{
int i;
for (i = 0; i < sizeof *card_in_slot; i++) {
if (sc_detect_card_presence(reader, 0) & SC_SLOT_CARD_PRESENT) {
if (!card_in_slot[i] || !sc_card_valid(card_in_slot[i])) {
sc_connect_card(reader, i, &card_in_slot[i]);
}
return pace_test(card_in_slot[i], pin_id, pin, pinlen,
new_pin_id, new_pin, new_pinlen);
}
}
sc_error(ctx, "No card found.");
return SC_ERROR_SLOT_NOT_FOUND;
}
#endif
static int ccid_list_readers(sc_context_t *ctx)
{
unsigned int i, rcount = sc_ctx_get_reader_count(ctx);
if (rcount == 0) {
printf("No smart card readers found.\n");
return 0;
}
printf("Readers known about:\n");
printf("Nr. Driver Name\n");
for (i = 0; i < rcount; i++) {
sc_reader_t *screader = sc_ctx_get_reader(ctx, i);
printf("%-7d%-11s%s\n", i, screader->driver->short_name,
screader->name);
}
return 0;
}
static int ccid_list_drivers(sc_context_t *ctx)
{
int i;
if (ctx->card_drivers[0] == NULL) {
printf("No card drivers installed!\n");
return 0;
}
printf("Configured card drivers:\n");
for (i = 0; ctx->card_drivers[i] != NULL; i++) {
printf(" %-16s %s\n", ctx->card_drivers[i]->short_name,
ctx->card_drivers[i]->name);
}
return 0;
}
int ccid_print_avail(int verbose)
{
sc_context_t *ctx = NULL;
int r;
r = sc_context_create(&ctx, NULL);
if (r) {
fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r));
return 1;
}
ctx->debug = verbose;
r = ccid_list_readers(ctx)|ccid_list_drivers(ctx);
if (ctx)
sc_release_context(ctx);
return r;
}

View File

@@ -265,17 +265,12 @@ struct hid_class_descriptor {
__u8 bNumDescriptors; __u8 bNumDescriptors;
} __attribute__ ((packed)); } __attribute__ ((packed));
int ccid_print_avail(int verbose);
int ccid_initialize(int reader_id, const char *cdriver, int verbose); int ccid_initialize(int reader_id, const char *cdriver, int verbose);
void ccid_shutdown(); void ccid_shutdown();
int ccid_parse_bulkin(const __u8* inbuf, __u8** outbuf); 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 ccid_state_changed(RDR_to_PC_NotifySlotChange_t **slotchange, int timeout); int ccid_state_changed(RDR_to_PC_NotifySlotChange_t **slotchange, int timeout);
int ccid_testpace(u8 pin_id, const char *pin, size_t pinlen,
u8 new_pin_id, const char *new_pin, size_t new_pinlen);
int build_apdu(const __u8 *buf, size_t len, sc_apdu_t *apdu);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -16,20 +16,23 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* ccid. If not, see <http://www.gnu.org/licenses/>. * ccid. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "ccid.h"
#include "util.h" #include "util.h"
#include "pace.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
static int verbose = 0; static int verbose = 0;
static int doinfo = 0; static int doinfo = 0;
static u8 dopacetest = 0; static u8 pin_id = 0;
static u8 dochangepin = 0; static u8 dochangepin = 0;
static const char *newpin = NULL; static const char *newpin = NULL;
static int usb_reader_num = -1; static int usb_reader_num = -1;
static const char *pin = NULL; static const char *pin = NULL;
static const char *cdriver = NULL; static const char *cdriver = NULL;
static sc_context_t *ctx = NULL;
static sc_reader_t *reader;
#define OPT_HELP 'h' #define OPT_HELP 'h'
#define OPT_READER 'r' #define OPT_READER 'r'
#define OPT_PIN 'i' #define OPT_PIN 'i'
@@ -37,7 +40,6 @@ static const char *cdriver = NULL;
#define OPT_CAN 'a' #define OPT_CAN 'a'
#define OPT_MRZ 'z' #define OPT_MRZ 'z'
#define OPT_CHANGE_PIN 'I' #define OPT_CHANGE_PIN 'I'
#define OPT_CHANGE_CAN 'A'
#define OPT_VERBOSE 'v' #define OPT_VERBOSE 'v'
#define OPT_INFO 'o' #define OPT_INFO 'o'
#define OPT_CARD 'c' #define OPT_CARD 'c'
@@ -46,12 +48,11 @@ static const struct option options[] = {
{ "help", no_argument, NULL, OPT_HELP }, { "help", no_argument, NULL, OPT_HELP },
{ "reader", required_argument, NULL, OPT_READER }, { "reader", required_argument, NULL, OPT_READER },
{ "card-driver", required_argument, NULL, OPT_CARD }, { "card-driver", required_argument, NULL, OPT_CARD },
{ "test-pin", optional_argument, NULL, OPT_PIN }, { "pin", optional_argument, NULL, OPT_PIN },
{ "test-puk", optional_argument, NULL, OPT_PUK }, { "puk", optional_argument, NULL, OPT_PUK },
{ "test-can", optional_argument, NULL, OPT_CAN }, { "can", optional_argument, NULL, OPT_CAN },
{ "test-mrz", optional_argument, NULL, OPT_MRZ }, { "mrz", optional_argument, NULL, OPT_MRZ },
{ "new-pin", optional_argument, NULL, OPT_CHANGE_PIN }, { "new-pin", optional_argument, NULL, OPT_CHANGE_PIN },
{ "new-can", optional_argument, NULL, OPT_CHANGE_CAN },
{ "verbose", no_argument, NULL, OPT_VERBOSE }, { "verbose", no_argument, NULL, OPT_VERBOSE },
{ "info", no_argument, NULL, OPT_INFO }, { "info", no_argument, NULL, OPT_INFO },
{ NULL, 0, NULL, 0 } { NULL, 0, NULL, 0 }
@@ -64,19 +65,39 @@ static const char *option_help[] = {
"Run PACE with PUK", "Run PACE with PUK",
"Run PACE with CAN", "Run PACE with CAN",
"Run PACE with MRZ", "Run PACE with MRZ",
"Change PIN when PACE is finished", "Install a new PIN",
"Change CAN when PACE is finished",
"Use (several times) to be more verbose", "Use (several times) to be more verbose",
"Print version, available readers and drivers.", "Print version, available readers and drivers.",
}; };
int testpace(u8 pin_id, const char *pin, size_t pinlen,
u8 new_pin_id, const char *new_pin, size_t new_pinlen)
{
int i;
sc_card_t *card;
for (i = 0; i < SC_MAX_SLOTS; i++) {
if (sc_detect_card_presence(reader, 0) & SC_SLOT_CARD_PRESENT) {
sc_connect_card(reader, i, &card);
i = pace_test(card, pin_id, pin, pinlen,
new_pin_id, new_pin, new_pinlen);
if (card && sc_card_valid(card))
sc_disconnect_card(card, 0);
return i;
}
}
fprintf (stderr, "No card found.");
return SC_ERROR_SLOT_NOT_FOUND;
}
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
int i, oindex = 0; int i, oindex = 0;
while (1) { while (1) {
i = getopt_long(argc, argv, "hr:i::u::a::z::I::A::voc:", options, &oindex); i = getopt_long(argc, argv, "hr:i::u::a::z::I::voc:", options, &oindex);
if (i == -1) if (i == -1)
break; break;
switch (i) { switch (i) {
@@ -101,28 +122,24 @@ main (int argc, char **argv)
break; break;
case OPT_PUK: case OPT_PUK:
/* PACE_PIN from openssl/pace.h */ /* PACE_PIN from openssl/pace.h */
dopacetest = 4; pin_id = 4;
pin = optarg; pin = optarg;
break; break;
case OPT_PIN: case OPT_PIN:
/* PACE_PIN from openssl/pace.h */ /* PACE_PIN from openssl/pace.h */
dopacetest = 3; pin_id = 3;
pin = optarg; pin = optarg;
break; break;
case OPT_CAN: case OPT_CAN:
/* PACE_PIN from openssl/pace.h */ /* PACE_PIN from openssl/pace.h */
dopacetest = 2; pin_id = 2;
pin = optarg; pin = optarg;
break; break;
case OPT_MRZ: case OPT_MRZ:
/* PACE_MRZ from openssl/pace.h */ /* PACE_MRZ from openssl/pace.h */
dopacetest = 1; pin_id = 1;
pin = optarg; pin = optarg;
break; break;
case OPT_CHANGE_CAN:
dochangepin = 2;
newpin = optarg;
break;
case OPT_CHANGE_PIN: case OPT_CHANGE_PIN:
dochangepin = 3; dochangepin = 3;
newpin = optarg; newpin = optarg;
@@ -148,16 +165,20 @@ main (int argc, char **argv)
if (doinfo) { if (doinfo) {
fprintf(stderr, "%s 0.9 written by Frank Morgner.\n\n" , fprintf(stderr, "%s 0.9 written by Frank Morgner.\n\n" ,
argv[0]); argv[0]);
return ccid_print_avail(verbose); return print_avail(verbose);
} }
if (ccid_initialize(usb_reader_num, cdriver, verbose) < 0) { i = initialize(usb_reader_num, cdriver, verbose, &ctx, &reader);
perror("Can't initialize ccid"); if (i < 0) {
perror("Can't initialize reader");
return 1; return 1;
} }
i = ccid_testpace(dopacetest, pin, !pin ? 0 : strlen(pin), i = testpace(pin_id, pin, !pin ? 0 : strlen(pin),
dochangepin, newpin, !newpin ? 0 : strlen(newpin)); dochangepin, newpin, !newpin ? 0 : strlen(newpin));
ccid_shutdown();
if (ctx)
sc_release_context(ctx);
return i; return i;
} }

View File

@@ -18,7 +18,7 @@
*/ */
#include "pace.h" #include "pace.h"
#include "sm.h" #include "sm.h"
#include "ccid.h" #include "util.h"
#include <stdio.h> #include <stdio.h>
#include <opensc/log.h> #include <opensc/log.h>
#include <openssl/evp.h> #include <openssl/evp.h>
@@ -953,7 +953,7 @@ int pace_test(sc_card_t *card,
sc_error(card->ctx, "Could not format binary string"); sc_error(card->ctx, "Could not format binary string");
} }
r = build_apdu(buf, apdulen, &apdu); r = build_apdu(card->ctx, buf, apdulen, &apdu);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not format APDU"); sc_error(card->ctx, "Could not format APDU");
continue; continue;

View File

@@ -1771,7 +1771,7 @@ main (int argc, char **argv)
if (doinfo) { if (doinfo) {
fprintf(stderr, "%s 0.9 written by Frank Morgner.\n\n" , fprintf(stderr, "%s 0.9 written by Frank Morgner.\n\n" ,
argv[0]); argv[0]);
return ccid_print_avail(verbose); return print_avail(verbose);
} }
if (ccid_initialize(usb_reader_num, cdriver, verbose) < 0) { if (ccid_initialize(usb_reader_num, cdriver, verbose) < 0) {

View File

@@ -19,6 +19,7 @@
#include "util.h" #include "util.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <opensc/log.h>
void print_usage(const char *app_name, const struct option options[], void print_usage(const char *app_name, const struct option options[],
const char *option_help[]) const char *option_help[])
@@ -67,3 +68,177 @@ void parse_error(const char *app_name, const struct option options[],
printf("Could not parse %s ('%s').\n", options[opt_ind].name, optarg); printf("Could not parse %s ('%s').\n", options[opt_ind].name, optarg);
print_usage(app_name , options, option_help); print_usage(app_name , options, option_help);
} }
int initialize(int reader_id, const char *cdriver, int verbose,
sc_context_t **ctx, sc_reader_t **reader)
{
unsigned int i, reader_count;
if (!ctx || !reader)
return SC_ERROR_INVALID_ARGUMENTS;
int r = sc_context_create(ctx, NULL);
if (r < 0) {
printf("Failed to create initial context: %s", sc_strerror(r));
return r;
}
if (cdriver != NULL) {
r = sc_set_card_driver(*ctx, cdriver);
if (r < 0) {
sc_error(*ctx, "Card driver '%s' not found!\n", cdriver);
return r;
}
}
(*ctx)->debug = verbose;
reader_count = sc_ctx_get_reader_count(*ctx);
if (reader_count == 0)
SC_FUNC_RETURN((*ctx), SC_LOG_TYPE_ERROR, SC_ERROR_NO_READERS_FOUND);
if (reader_id < 0) {
/* Automatically try to skip to a reader with a card if reader not specified */
for (i = 0; i < reader_count; i++) {
*reader = sc_ctx_get_reader(*ctx, i);
if (sc_detect_card_presence(*reader, 0) & SC_SLOT_CARD_PRESENT) {
reader_id = i;
sc_debug(*ctx, "Using reader with a card: %s", (*reader)->name);
break;
}
}
if (reader_id >= reader_count) {
/* no reader found, use the first */
reader_id = 0;
}
}
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);
SC_FUNC_RETURN((*ctx), SC_LOG_TYPE_ERROR, SC_SUCCESS);
}
static int list_readers(sc_context_t *ctx)
{
unsigned int i, rcount = sc_ctx_get_reader_count(ctx);
if (rcount == 0) {
printf("No smart card readers found.\n");
return 0;
}
printf("Readers known about:\n");
printf("Nr. Driver Name\n");
for (i = 0; i < rcount; i++) {
sc_reader_t *screader = sc_ctx_get_reader(ctx, i);
printf("%-7d%-11s%s\n", i, screader->driver->short_name,
screader->name);
}
return 0;
}
static int list_drivers(sc_context_t *ctx)
{
int i;
if (ctx->card_drivers[0] == NULL) {
printf("No card drivers installed!\n");
return 0;
}
printf("Configured card drivers:\n");
for (i = 0; ctx->card_drivers[i] != NULL; i++) {
printf(" %-16s %s\n", ctx->card_drivers[i]->short_name,
ctx->card_drivers[i]->name);
}
return 0;
}
int print_avail(int verbose)
{
sc_context_t *ctx = NULL;
int r;
r = sc_context_create(&ctx, NULL);
if (r) {
fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r));
return 1;
}
ctx->debug = verbose;
r = list_readers(ctx)|list_drivers(ctx);
if (ctx)
sc_release_context(ctx);
return r;
}
int build_apdu(sc_context_t *ctx, const u8 *buf, size_t len, sc_apdu_t *apdu)
{
const u8 *p;
size_t len0;
if (!buf || !apdu)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
len0 = len;
if (len < 4) {
sc_error(ctx, "APDU too short (must be at least 4 bytes)");
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_DATA);
}
memset(apdu, 0, sizeof(*apdu));
p = buf;
apdu->cla = *p++;
apdu->ins = *p++;
apdu->p1 = *p++;
apdu->p2 = *p++;
len -= 4;
if (len > 1) {
apdu->lc = *p++;
len--;
apdu->data = p;
apdu->datalen = apdu->lc;
if (len < apdu->lc) {
sc_error(ctx, "APDU too short (need %lu bytes)\n",
(unsigned long) apdu->lc - len);
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_DATA);
}
len -= apdu->lc;
p += apdu->lc;
if (len) {
apdu->le = *p++;
if (apdu->le == 0)
apdu->le = 256;
len--;
apdu->cse = SC_APDU_CASE_4_SHORT;
} else {
apdu->cse = SC_APDU_CASE_3_SHORT;
}
if (len) {
sc_error(ctx, "APDU too long (%lu bytes extra)\n",
(unsigned long) len);
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_DATA);
}
} else if (len == 1) {
apdu->le = *p++;
if (apdu->le == 0)
apdu->le = 256;
len--;
apdu->cse = SC_APDU_CASE_2_SHORT;
} else {
apdu->cse = SC_APDU_CASE_1;
}
apdu->flags = SC_APDU_FLAGS_NO_GET_RESP|SC_APDU_FLAGS_NO_RETRY_WL;
sc_debug(ctx, "APDU, %d bytes:\tins=%02x p1=%02x p2=%02x",
(unsigned int) len0, apdu->ins, apdu->p1, apdu->p2);
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_SUCCESS);
}

View File

@@ -20,10 +20,17 @@
#define _CCID_UTIL_H #define _CCID_UTIL_H
#include <getopt.h> #include <getopt.h>
#include <opensc/opensc.h>
void print_usage(const char *app_name, const struct option options[], void print_usage(const char *app_name, const struct option options[],
const char *option_help[]); const char *option_help[]);
void parse_error(const char *app_name, const struct option options[], void parse_error(const char *app_name, const struct option options[],
const char *option_help[], const char *optarg, int opt_ind); const char *option_help[], const char *optarg, int opt_ind);
int print_avail(int verbose);
int initialize(int reader_id, const char *cdriver, int verbose,
sc_context_t **ctx, sc_reader_t **reader);
int build_apdu(sc_context_t *ctx, const u8 *buf, size_t len, sc_apdu_t *apdu);
#endif #endif