added support for changing CAN and PIN for PACE

git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@83 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
frankmorgner
2010-04-28 13:14:40 +00:00
parent 576aaca098
commit 06375ec693
5 changed files with 130 additions and 31 deletions

View File

@@ -1308,14 +1308,16 @@ int ccid_state_changed(RDR_to_PC_NotifySlotChange_t **slotchange, int timeout)
} }
#ifdef NO_PACE #ifdef NO_PACE
int ccid_testpace(u8 pin_id, const char *pin, size_t pinlen) 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."); sc_error(ctx, "ccid not compiled with support for PACE.");
return SC_ERROR_NOT_SUPPORTED; return SC_ERROR_NOT_SUPPORTED;
} }
#else #else
int ccid_testpace(u8 pin_id, const char *pin, size_t pinlen) 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; int i;
for (i = 0; i < sizeof *card_in_slot; i++) { for (i = 0; i < sizeof *card_in_slot; i++) {
@@ -1323,7 +1325,8 @@ int ccid_testpace(u8 pin_id, const char *pin, size_t pinlen)
if (!card_in_slot[i] || !sc_card_valid(card_in_slot[i])) { if (!card_in_slot[i] || !sc_card_valid(card_in_slot[i])) {
sc_connect_card(reader, i, &card_in_slot[i]); sc_connect_card(reader, i, &card_in_slot[i]);
} }
return pace_test(card_in_slot[i], pin_id, pin, pinlen); return pace_test(card_in_slot[i], pin_id, pin, pinlen,
new_pin_id, new_pin, new_pinlen);
} }
} }

View File

@@ -272,7 +272,8 @@ 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); 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); int build_apdu(const __u8 *buf, size_t len, sc_apdu_t *apdu);

View File

@@ -151,7 +151,8 @@ inline int EstablishPACEChannel(sc_card_t *card, const __u8 *in,
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, SC_ERROR_NOT_SUPPORTED); SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, SC_ERROR_NOT_SUPPORTED);
} }
int pace_test(sc_card_t *card, int pace_test(sc_card_t *card,
enum s_type pin_id, const char *pin, size_t pinlen) enum s_type pin_id, const char *pin, size_t pinlen,
enum s_type new_pin_id, const char *new_pin, size_t new_pinlen)
{ {
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, SC_ERROR_NOT_SUPPORTED); SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, SC_ERROR_NOT_SUPPORTED);
} }
@@ -176,6 +177,11 @@ int pace_sm_verify_authentication(sc_card_t *card, struct sm_ctx *ctx,
{ {
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, SC_ERROR_NOT_SUPPORTED); SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, SC_ERROR_NOT_SUPPORTED);
} }
int pace_change_p(struct sm_ctx *ctx, sc_card_t *card, enum s_type pin_id,
const char *newp, size_t newplen)
{
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, SC_ERROR_NOT_SUPPORTED);
}
#else #else
#include <asm/byteorder.h> #include <asm/byteorder.h>
@@ -568,38 +574,62 @@ err:
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, r); SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, r);
} }
static int
pace_reset_retry_counter(struct sm_ctx *ctx, sc_card_t *card,
enum s_type pin_id, const char *new, size_t new_len)
{
sc_apdu_t apdu;
apdu.cla = 0;
apdu.ins = 0x2C;
apdu.p2 = pin_id;
apdu.data = (u8 *) new;
apdu.datalen = new_len;
apdu.lc = apdu.datalen;
apdu.flags = SC_APDU_FLAGS_NO_GET_RESP|SC_APDU_FLAGS_NO_RETRY_WL;
if (new_len) {
apdu.p1 = 0x02;
apdu.cse = SC_APDU_CASE_3_SHORT;
} else {
apdu.p1 = 0x03;
apdu.cse = SC_APDU_CASE_1;
}
return pace_transmit_apdu(ctx, card, &apdu);
}
static PACE_SEC * static PACE_SEC *
get_psec(sc_card_t *card, const char *pin, size_t length_pin, u8 pin_id) get_psec(sc_card_t *card, const char *pin, size_t length_pin, enum s_type pin_id)
{ {
sc_ui_hints_t hints; sc_ui_hints_t hints;
char *p = NULL; char *p = NULL;
PACE_SEC *r; PACE_SEC *r;
int sc_result; int sc_result;
size_t len;
if (pin && length_pin) if (!length_pin || !pin) {
return PACE_SEC_new(pin, length_pin, pin_id); memset(&hints, 0, sizeof(hints));
hints.dialog_name = "ccid.PACE";
memset(&hints, 0, sizeof(hints)); hints.card = card;
hints.dialog_name = "ccid.PACE"; hints.prompt = NULL;
hints.card = card; hints.obj_label = pace_secret_name(pin_id);
hints.prompt = NULL; hints.usage = SC_UI_USAGE_OTHER;
hints.obj_label = pace_secret_name(pin_id); sc_result = sc_ui_get_pin(&hints, &p);
hints.usage = SC_UI_USAGE_OTHER; if (sc_result < 0) {
sc_result = sc_ui_get_pin(&hints, &p); sc_error(card->ctx, "Could not read PACE secret (%s).\n",
if (sc_result < 0) { sc_strerror(sc_result));
sc_error(card->ctx, "Could not read PACE secret (%s).\n", return NULL;
sc_strerror(sc_result)); }
return NULL; length_pin = strlen(p);
pin = p;
} }
len = strlen(p); r = PACE_SEC_new(pin, length_pin, pin_id);
r = PACE_SEC_new(p, len, pin_id);
if (len) { if (p) {
OPENSSL_cleanse(p, len); OPENSSL_cleanse(p, length_pin);
free(p);
} }
free(p);
return r; return r;
} }
@@ -854,7 +884,8 @@ const char *pace_secret_name(enum s_type pin_id) {
} }
int pace_test(sc_card_t *card, int pace_test(sc_card_t *card,
enum s_type pin_id, const char *pin, size_t pinlen) enum s_type pin_id, const char *pin, size_t pinlen,
enum s_type new_pin_id, const char *new_pin, size_t new_pinlen)
{ {
u8 buf[0xff + 5]; u8 buf[0xff + 5];
char *read = NULL; char *read = NULL;
@@ -894,6 +925,12 @@ int pace_test(sc_card_t *card,
EstablishPACEChannel(card, buf, &out, &outlen, &sctx), EstablishPACEChannel(card, buf, &out, &outlen, &sctx),
"Could not establish PACE channel."); "Could not establish PACE channel.");
if (new_pin_id) {
SC_TEST_RET(card->ctx,
pace_change_p(&sctx, card, new_pin_id, new_pin, new_pinlen),
"Could not change PACE secret.");
}
while (1) { while (1) {
printf("Enter unencrypted APDU (empty line to exit)\n"); printf("Enter unencrypted APDU (empty line to exit)\n");
@@ -1332,4 +1369,38 @@ int pace_transmit_apdu(struct sm_ctx *ctx, sc_card_t *card,
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, r); SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, r);
} }
int pace_change_p(struct sm_ctx *ctx, sc_card_t *card, enum s_type pin_id,
const char *newp, size_t newplen)
{
sc_ui_hints_t hints;
char *p = NULL;
int r;
if (!newplen || !newp) {
memset(&hints, 0, sizeof(hints));
hints.dialog_name = "ccid.PACE";
hints.card = card;
hints.prompt = NULL;
hints.obj_label = pace_secret_name(pin_id);
hints.usage = SC_UI_USAGE_NEW_PIN;
r = sc_ui_get_pin(&hints, &p);
if (r < 0) {
sc_error(card->ctx, "Could not read new %s (%s).\n",
hints.obj_label, sc_strerror(r));
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, r);
}
newplen = strlen(p);
newp = p;
}
r = pace_reset_retry_counter(ctx, card, pin_id, newp, newplen);
if (p) {
OPENSSL_cleanse(p, newplen);
free(p);
}
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, r);
}
#endif #endif

View File

@@ -64,7 +64,14 @@ int GetReadersPACECapabilities(sc_card_t *card, const __u8
int EstablishPACEChannel(sc_card_t *card, const __u8 *in, int EstablishPACEChannel(sc_card_t *card, const __u8 *in,
__u8 **out, size_t *outlen, struct sm_ctx *ctx); __u8 **out, size_t *outlen, struct sm_ctx *ctx);
int pace_test(sc_card_t *card, int pace_test(sc_card_t *card,
enum s_type pin_id, const char *pin, size_t pinlen); enum s_type pin_id, const char *pin, size_t pinlen,
enum s_type new_pin_id, const char *new_pin, size_t new_pinlen);
int pace_change_p(struct sm_ctx *ctx, sc_card_t *card, enum s_type pin_id,
const char *newp, size_t newplen);
#define pace_change_pin(ctx, card, newpin, newpinlen) \
pace_change_p(ctx, card, PACE_PIN, newpin, newpinlen)
#define pace_change_can(ctx, card, newcan, newcanlen) \
pace_change_p(ctx, card, PACE_CAN, newcan, newcanlen)
int pace_transmit_apdu(struct sm_ctx *sctx, sc_card_t *card, int pace_transmit_apdu(struct sm_ctx *sctx, sc_card_t *card,
sc_apdu_t *apdu); sc_apdu_t *apdu);

View File

@@ -58,6 +58,8 @@ static int dohid = 0;
static int doint = 0; static int doint = 0;
static int doinfo = 0; static int doinfo = 0;
static u8 dopacetest = 0; static u8 dopacetest = 0;
static u8 dochangepin = 0;
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;
@@ -70,6 +72,8 @@ static const char *cdriver = NULL;
#define OPT_PUK 'u' #define OPT_PUK 'u'
#define OPT_CAN 'a' #define OPT_CAN 'a'
#define OPT_MRZ 'z' #define OPT_MRZ 'z'
#define OPT_CHANGE_PIN 'I'
#define OPT_CHANGE_CAN 'A'
#define OPT_PRODUCT 'p' #define OPT_PRODUCT 'p'
#define OPT_VENDOR 'e' #define OPT_VENDOR 'e'
#define OPT_VERBOSE 'v' #define OPT_VERBOSE 'v'
@@ -85,6 +89,8 @@ static const struct option options[] = {
{ "test-puk", optional_argument, NULL, OPT_PUK }, { "test-puk", optional_argument, NULL, OPT_PUK },
{ "test-can", optional_argument, NULL, OPT_CAN }, { "test-can", optional_argument, NULL, OPT_CAN },
{ "test-mrz", optional_argument, NULL, OPT_MRZ }, { "test-mrz", optional_argument, NULL, OPT_MRZ },
{ "new-pin", optional_argument, NULL, OPT_CHANGE_PIN },
{ "new-can", optional_argument, NULL, OPT_CHANGE_CAN },
{ "serial", required_argument, NULL, OPT_SERIAL }, { "serial", required_argument, NULL, OPT_SERIAL },
{ "product", required_argument, NULL, OPT_PRODUCT }, { "product", required_argument, NULL, OPT_PRODUCT },
{ "vendor", required_argument, NULL, OPT_VENDOR }, { "vendor", required_argument, NULL, OPT_VENDOR },
@@ -102,6 +108,8 @@ 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",
"Change CAN when PACE is finished",
"USB serial number (default: random)", "USB serial number (default: random)",
"USB product ID (default: 0x3010)", "USB product ID (default: 0x3010)",
"USB vendor ID (default: 0x0D46)", "USB vendor ID (default: 0x0D46)",
@@ -1772,7 +1780,7 @@ main (int argc, char **argv)
} }
while (1) { while (1) {
c = getopt_long(argc, argv, "hnr:s:i::u::a::z::p:e:voc:", options, &oindex); c = getopt_long(argc, argv, "hnr:s:i::u::a::z::I::A::p:e:voc:", options, &oindex);
if (c == -1) if (c == -1)
break; break;
switch (c) { switch (c) {
@@ -1821,10 +1829,18 @@ main (int argc, char **argv)
pin = optarg; pin = optarg;
break; break;
case OPT_MRZ: case OPT_MRZ:
/* PACE_PIN from openssl/pace.h */ /* PACE_MRZ from openssl/pace.h */
dopacetest = 1; dopacetest = 1;
pin = optarg; pin = optarg;
break; break;
case OPT_CHANGE_CAN:
dochangepin = 2;
newpin = optarg;
break;
case OPT_CHANGE_PIN:
dochangepin = 3;
newpin = optarg;
break;
case '?': case '?':
/* fall through */ /* fall through */
default: default:
@@ -1855,7 +1871,8 @@ main (int argc, char **argv)
} }
if (dopacetest) { if (dopacetest) {
i = ccid_testpace(dopacetest, pin, !pin ? 0 : strlen(pin)); i = ccid_testpace(dopacetest, pin, !pin ? 0 : strlen(pin),
dochangepin, newpin, !newpin ? 0 : strlen(newpin));
ccid_shutdown(); ccid_shutdown();
return i; return i;
} }