From 69b8e3fc65f773f8cd5e9c2a30befac5712a3b1d Mon Sep 17 00:00:00 2001 From: frankmorgner Date: Mon, 1 Mar 2010 16:22:41 +0000 Subject: [PATCH] - bugfix: moved ASN.1 declaration of PACE-APDUs to pace.c - added commandline-option to test PACE currently with hard coded secret etc. git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@41 96b47cad-a561-4643-ad3b-153ac7d7599c --- ccid/ccid.c | 6 +++ ccid/ccid.h | 1 + ccid/pace.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++- ccid/pace.h | 112 ++------------------------------------------ ccid/usb.c | 10 +++- 5 files changed, 152 insertions(+), 109 deletions(-) diff --git a/ccid/ccid.c b/ccid/ccid.c index 1734cb7..5118d7e 100644 --- a/ccid/ccid.c +++ b/ccid/ccid.c @@ -27,6 +27,7 @@ #include #include "ccid.h" +#include "pace.h" //static const char *app_name = "ccid"; static sc_context_t *ctx = NULL; @@ -1277,3 +1278,8 @@ int ccid_state_changed(RDR_to_PC_NotifySlotChange_t **slotchange, int timeout) return 0; } + +void ccid_testpace() +{ + pace_test(ctx, card_in_slot[0]); +} diff --git a/ccid/ccid.h b/ccid/ccid.h index 48d0a77..b0cc28e 100644 --- a/ccid/ccid.h +++ b/ccid/ccid.h @@ -270,6 +270,7 @@ void ccid_shutdown(); int ccid_parse_bulkin(const __u8* inbuf, __u8** outbuf); int ccid_parse_control(struct usb_ctrlrequest *setup, __u8 **outbuf); int ccid_state_changed(RDR_to_PC_NotifySlotChange_t **slotchange, int timeout); +void ccid_testpace(); #ifdef __cplusplus } diff --git a/ccid/pace.c b/ccid/pace.c index 4aecc8c..a6387e7 100644 --- a/ccid/pace.c +++ b/ccid/pace.c @@ -19,6 +19,109 @@ #include #include "pace.h" + +#define ASN1_APP_EXP_OPT(stname, field, type, tag) ASN1_EX_TYPE(ASN1_TFLG_EXPTAG|ASN1_TFLG_APPLICATION|ASN1_TFLG_OPTIONAL, tag, stname, field, type) + +/* + * MSE:Set AT + */ + +typedef struct pace_mse_set_at_cd_st { + ASN1_OBJECT *cryptographic_mechanism_reference; + ASN1_INTEGER *key_reference1; + ASN1_INTEGER *key_reference2; + ASN1_INTEGER *auxiliary_data; + ASN1_INTEGER *eph_pub_key; + ASN1_INTEGER *cha_template; +} PACE_MSE_SET_AT_C; +ASN1_SEQUENCE(PACE_MSE_SET_AT_C) = { + /* 0x80 + * Cryptographic mechanism reference */ + ASN1_IMP_OPT(PACE_MSE_SET_AT_C, cryptographic_mechanism_reference, ASN1_OBJECT, 0), + /* 0x83 + * Reference of a public key / secret key */ + ASN1_IMP_OPT(PACE_MSE_SET_AT_C, key_reference1, ASN1_INTEGER, 3), + /* 0x84 + * Reference of a private key / Reference for computing a session key */ + ASN1_IMP_OPT(PACE_MSE_SET_AT_C, key_reference2, ASN1_INTEGER, 4), + /* 0x67 + * Auxiliary authenticated data */ + ASN1_APP_EXP_OPT(PACE_MSE_SET_AT_C, auxiliary_data, ASN1_INTEGER, 7), + /* 0x91 + * Ephemeral Public Key */ + ASN1_IMP_OPT(PACE_MSE_SET_AT_C, eph_pub_key, ASN1_INTEGER, 0x11), + /* 0x7F4C + * Certificate Holder Authorization Template */ + ASN1_APP_EXP_OPT(PACE_MSE_SET_AT_C, cha_template, ASN1_INTEGER, 0x4c), +} ASN1_SEQUENCE_END(PACE_MSE_SET_AT_C) +IMPLEMENT_ASN1_FUNCTIONS(PACE_MSE_SET_AT_C) + + +/* + * General Authenticate + */ + +/* Protocol Command Data */ +typedef struct pace_gen_auth_cd_st { + ASN1_OCTET_STRING *mapping_data; + ASN1_OCTET_STRING *eph_pub_key; + ASN1_OCTET_STRING *auth_token; +} PACE_GEN_AUTH_C; +ASN1_SEQUENCE(PACE_GEN_AUTH_C) = { + /* 0x81 + * Mapping Data */ + ASN1_IMP_OPT(PACE_GEN_AUTH_C, mapping_data, ASN1_INTEGER, 1), + /* 0x83 + * Ephemeral Public Key */ + ASN1_IMP_OPT(PACE_GEN_AUTH_C, eph_pub_key, ASN1_INTEGER, 3), + /* 0x85 + * Authentication Token */ + ASN1_IMP_OPT(PACE_GEN_AUTH_C, auth_token, ASN1_INTEGER, 5), +} ASN1_SEQUENCE_END(PACE_GEN_AUTH_C) +IMPLEMENT_ASN1_FUNCTIONS(PACE_GEN_AUTH_C) + +/* Protocol Response Data */ +typedef struct pace_gen_auth_rapdu_body_st { + ASN1_INTEGER *enc_nonce; + ASN1_INTEGER *mapping_data; + ASN1_INTEGER *eph_pub_key; + ASN1_INTEGER *auth_token; + ASN1_INTEGER *cert_auth1; + ASN1_INTEGER *cert_auth2; +} PACE_GEN_AUTH_R_BODY; +ASN1_SEQUENCE(PACE_GEN_AUTH_R_BODY) = { + /* 0x80 + * Encrypted Nonce */ + ASN1_IMP_OPT(PACE_GEN_AUTH_R_BODY, enc_nonce, ASN1_INTEGER, 0), + /* 0x82 + * Mapping Data */ + ASN1_IMP_OPT(PACE_GEN_AUTH_R_BODY, mapping_data, ASN1_INTEGER, 2), + /* 0x84 + * Ephemeral Public Key */ + ASN1_IMP_OPT(PACE_GEN_AUTH_R_BODY, eph_pub_key, ASN1_INTEGER, 4), + /* 0x86 + * Authentication Token */ + ASN1_IMP_OPT(PACE_GEN_AUTH_R_BODY, auth_token, ASN1_INTEGER, 6), + /* 0x87 + * Certification Authority Reference */ + ASN1_IMP_OPT(PACE_GEN_AUTH_R_BODY, cert_auth1, ASN1_INTEGER, 7), + /* 0x88 + * Certification Authority Reference */ + ASN1_IMP_OPT(PACE_GEN_AUTH_R_BODY, cert_auth2, ASN1_INTEGER, 8), +} ASN1_SEQUENCE_END(PACE_GEN_AUTH_R_BODY) +IMPLEMENT_ASN1_FUNCTIONS(PACE_GEN_AUTH_R_BODY) + +typedef PACE_GEN_AUTH_R_BODY PACE_GEN_AUTH_R; +/* 0x7C + * Dynamic Authentication Data */ +ASN1_ITEM_TEMPLATE(PACE_GEN_AUTH_R) = + ASN1_EX_TEMPLATE_TYPE( + ASN1_TFLG_IMPTAG|ASN1_TFLG_APPLICATION, + 0x1c, PACE_GEN_AUTH_R, PACE_GEN_AUTH_R_BODY) +ASN1_ITEM_TEMPLATE_END(PACE_GEN_AUTH_R) +IMPLEMENT_ASN1_FUNCTIONS(PACE_GEN_AUTH_R) + + #ifdef NO_PACE inline int GetReadersPACECapabilities(sc_context_t *ctx, sc_card_t *card, const __u8 *in, __u8 **out, size_t *outlen) { @@ -28,15 +131,18 @@ inline int EstablishPACEChannel(sc_context_t *ctx, sc_card_t *card, const __u8 *in, __u8 **out, size_t *outlen) { SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_NOT_SUPPORTED); } +void pace_test(sc_context_t *ctx, sc_card_t *card) { + SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_NOT_SUPPORTED); +} #else #include #include -#include #include #include #include #include +#include uint16_t ssc = 0; @@ -72,8 +178,10 @@ int get_ef_card_access(sc_context_t *ctx, sc_card_t *card, snprintf(buf, sizeof buf, "3f00%04x", FID_EF_CARDACCESS); sc_format_path(buf, &path); + //printf("%s:%d\n", __FILE__, __LINE__); SC_TEST_RET(ctx, sc_select_file(card, &path, &file), "Could not select EF.CardAccess."); + //printf("%s:%d\n", __FILE__, __LINE__); ssc++; *length_ef_cardaccess = file->size; @@ -580,4 +688,26 @@ err: SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, r); } + +void pace_test(sc_context_t *ctx, sc_card_t *card) +{ + __u8 in[16]; + __u8 *out = NULL; + size_t outlen; + + in[0] = PACE_CAN; // pin_id + in[1] = 0; // length_chat + in[2] = 6; // length_pin + in[3] = '8'; + in[4] = '4'; + in[5] = '0'; + in[6] = '1'; + in[7] = '7'; + in[8] = '9'; + in[9] = 0; // length_cert_desc + in[10]= 0; // length_cert_desc + + EstablishPACEChannel(ctx, card, in, &out, &outlen); +} + #endif diff --git a/ccid/pace.h b/ccid/pace.h index d9b6cac..21dfd52 100644 --- a/ccid/pace.h +++ b/ccid/pace.h @@ -31,120 +31,18 @@ extern "C" { #define PACE_BITMAP_EID 0x20 #define PACE_BITMAP_ESIGN 0x10 -#define PACE_MRZ 0x01 -#define PACE_CAN 0x02 -#define PACE_PIN 0x03 -#define PACE_PUK 0x04 +//#define PACE_MRZ 0x01 +//#define PACE_CAN 0x02 +//#define PACE_PIN 0x03 +//#define PACE_PUK 0x04 #define FID_EF_CARDACCESS 0x011C -#define ASN1_APP_EXP_OPT(stname, field, type, tag) ASN1_EX_TYPE(ASN1_TFLG_EXPTAG|ASN1_TFLG_APPLICATION|ASN1_TFLG_OPTIONAL, tag, stname, field, type) - - -/* - * MSE:Set AT - */ - -typedef struct pace_mse_set_at_cd_st { - ASN1_OBJECT *cryptographic_mechanism_reference; - ASN1_INTEGER *key_reference1; - ASN1_INTEGER *key_reference2; - ASN1_INTEGER *auxiliary_data; - ASN1_INTEGER *eph_pub_key; - ASN1_INTEGER *cha_template; -} PACE_MSE_SET_AT_C; -ASN1_SEQUENCE(PACE_MSE_SET_AT_C) = { - /* 0x80 - * Cryptographic mechanism reference */ - ASN1_IMP_OPT(PACE_MSE_SET_AT_C, cryptographic_mechanism_reference, ASN1_OBJECT, 0), - /* 0x83 - * Reference of a public key / secret key */ - ASN1_IMP_OPT(PACE_MSE_SET_AT_C, key_reference1, ASN1_INTEGER, 3), - /* 0x84 - * Reference of a private key / Reference for computing a session key */ - ASN1_IMP_OPT(PACE_MSE_SET_AT_C, key_reference2, ASN1_INTEGER, 4), - /* 0x67 - * Auxiliary authenticated data */ - ASN1_APP_EXP_OPT(PACE_MSE_SET_AT_C, auxiliary_data, ASN1_INTEGER, 7), - /* 0x91 - * Ephemeral Public Key */ - ASN1_IMP_OPT(PACE_MSE_SET_AT_C, eph_pub_key, ASN1_INTEGER, 0x11), - /* 0x7F4C - * Certificate Holder Authorization Template */ - ASN1_APP_EXP_OPT(PACE_MSE_SET_AT_C, cha_template, ASN1_INTEGER, 0x4c), -} ASN1_SEQUENCE_END(PACE_MSE_SET_AT_C) -IMPLEMENT_ASN1_FUNCTIONS(PACE_MSE_SET_AT_C) - - -/* - * General Authenticate - */ - -/* Protocol Command Data */ -typedef struct pace_gen_auth_cd_st { - ASN1_OCTET_STRING *mapping_data; - ASN1_OCTET_STRING *eph_pub_key; - ASN1_OCTET_STRING *auth_token; -} PACE_GEN_AUTH_C; -ASN1_SEQUENCE(PACE_GEN_AUTH_C) = { - /* 0x81 - * Mapping Data */ - ASN1_IMP_OPT(PACE_GEN_AUTH_C, mapping_data, ASN1_INTEGER, 1), - /* 0x83 - * Ephemeral Public Key */ - ASN1_IMP_OPT(PACE_GEN_AUTH_C, eph_pub_key, ASN1_INTEGER, 3), - /* 0x85 - * Authentication Token */ - ASN1_IMP_OPT(PACE_GEN_AUTH_C, auth_token, ASN1_INTEGER, 5), -} ASN1_SEQUENCE_END(PACE_GEN_AUTH_C) -IMPLEMENT_ASN1_FUNCTIONS(PACE_GEN_AUTH_C) - -/* Protocol Response Data */ -typedef struct pace_gen_auth_rapdu_body_st { - ASN1_INTEGER *enc_nonce; - ASN1_INTEGER *mapping_data; - ASN1_INTEGER *eph_pub_key; - ASN1_INTEGER *auth_token; - ASN1_INTEGER *cert_auth1; - ASN1_INTEGER *cert_auth2; -} PACE_GEN_AUTH_R_BODY; -ASN1_SEQUENCE(PACE_GEN_AUTH_R_BODY) = { - /* 0x80 - * Encrypted Nonce */ - ASN1_IMP_OPT(PACE_GEN_AUTH_R_BODY, enc_nonce, ASN1_INTEGER, 0), - /* 0x82 - * Mapping Data */ - ASN1_IMP_OPT(PACE_GEN_AUTH_R_BODY, mapping_data, ASN1_INTEGER, 2), - /* 0x84 - * Ephemeral Public Key */ - ASN1_IMP_OPT(PACE_GEN_AUTH_R_BODY, eph_pub_key, ASN1_INTEGER, 4), - /* 0x86 - * Authentication Token */ - ASN1_IMP_OPT(PACE_GEN_AUTH_R_BODY, auth_token, ASN1_INTEGER, 6), - /* 0x87 - * Certification Authority Reference */ - ASN1_IMP_OPT(PACE_GEN_AUTH_R_BODY, cert_auth1, ASN1_INTEGER, 7), - /* 0x88 - * Certification Authority Reference */ - ASN1_IMP_OPT(PACE_GEN_AUTH_R_BODY, cert_auth2, ASN1_INTEGER, 8), -} ASN1_SEQUENCE_END(PACE_GEN_AUTH_R_BODY) -IMPLEMENT_ASN1_FUNCTIONS(PACE_GEN_AUTH_R_BODY) - -typedef PACE_GEN_AUTH_R_BODY PACE_GEN_AUTH_R; -/* 0x7C - * Dynamic Authentication Data */ -ASN1_ITEM_TEMPLATE(PACE_GEN_AUTH_R) = - ASN1_EX_TEMPLATE_TYPE( - ASN1_TFLG_IMPTAG|ASN1_TFLG_APPLICATION, - 0x1c, PACE_GEN_AUTH_R, PACE_GEN_AUTH_R_BODY) -ASN1_ITEM_TEMPLATE_END(PACE_GEN_AUTH_R) -IMPLEMENT_ASN1_FUNCTIONS(PACE_GEN_AUTH_R) - - int GetReadersPACECapabilities(sc_context_t *ctx, sc_card_t *card, const __u8 *in, __u8 **out, size_t *outlen); int EstablishPACEChannel(sc_context_t *ctx, sc_card_t *card, const __u8 *in, __u8 **out, size_t *outlen); +void pace_test(sc_context_t *ctx, sc_card_t *card); #ifdef __cplusplus } diff --git a/ccid/usb.c b/ccid/usb.c index 7a959c3..3117158 100644 --- a/ccid/usb.c +++ b/ccid/usb.c @@ -57,6 +57,7 @@ static int verbose = 0; static int debug = 0; static int dohid = 0; static int doint = 0; +static int dotest = 0; int usb_reader_num = 0; static const struct option options[] = { @@ -65,6 +66,7 @@ static const struct option options[] = { { "interrupt", no_argument, &doint, 'n' }, { "reader", required_argument, NULL, 'r' }, { "serial", required_argument, NULL, 's' }, + { "test-pace", no_argument, &dotest, 't' }, { "product", required_argument, NULL, 'p' }, { "vendor", required_argument, NULL, 'e' }, { "verbose", no_argument, NULL, 'v' }, @@ -77,6 +79,7 @@ static const char *option_help[] = { "Add interrupt pipe for CCID", "Number of the reader to use (default: auto-detect)", "Serial number (max 56 bytes) of gadget (default: random)", + "test PACE implementation", "USB product ID (default: 0x3010)", "USB vendor ID (0default: x0D46)", "Use (several times) to be more verbose", @@ -927,7 +930,7 @@ ep_config (char *name, const char *label, /* ccid thread, forwards ccid requests to pcsc and returns results */ static void *ccid (void *param) -{ +{ pthread_t interrupt_thread; void *interrupt (void *param) @@ -1028,6 +1031,11 @@ static void *ccid (void *param) goto error; } + if (dotest) { + sleep(2); + ccid_testpace(); + } + do { /* original LinuxThreads cancelation didn't work right