diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c index 0b4f3340..6b3754f0 100644 --- a/src/libopensc/card-myeid.c +++ b/src/libopensc/card-myeid.c @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ + */ #include "config.h" @@ -35,10 +35,17 @@ #define LOAD_KEY_DP1 0x85 #define LOAD_KEY_DQ1 0x86 #define LOAD_KEY_INVQ 0x87 +#define LOAD_KEY_MODE_EC_PRIV 0x87 +#define LOAD_KEY_MODE_EC_PUB 0x86 + +#define LOAD_KEY_EC_PRIVATE 0x97 +#define LOAD_KEY_EC_PUBLIC 0x96 #define MYEID_STATE_CREATION 0x01 #define MYEID_STATE_ACTIVATED 0x07 +#define MYEID_ECC_SUPPORT + static struct sc_card_operations myeid_ops; static struct sc_card_driver myeid_drv = { "MyEID cards with PKCS#15 applet", @@ -52,7 +59,9 @@ static struct sc_card_driver myeid_drv = { static const char *myeid_atrs[] = { "3B:F5:18:00:FF:81:31:FE:45:4D:79:45:49:44:65", "3B:F5:18:00:00:81:31:FE:45:4D:79:45:49:44:9A", - NULL + "3B:85:80:01:4D:79:45:49:44:78", + "3B:89:80:01:09:38:33:B1:4D:79:45:49:44:4C", + NULL }; typedef struct myeid_private_data { @@ -86,7 +95,8 @@ static int myeid_match_card(struct sc_card *card) static int myeid_init(struct sc_card *card) { - unsigned long flags =0; + unsigned long flags = 0, + ext_flags = 0; myeid_private_data_t *priv; LOG_FUNC_CALLED(card->ctx); @@ -97,11 +107,23 @@ static int myeid_init(struct sc_card *card) card->drv_data = priv; flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_ONBOARD_KEY_GEN; - flags |= SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_HASH_SHA1 | SC_ALGORITHM_ONBOARD_KEY_GEN; - + flags |= SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_HASH_SHA1; + + _sc_card_add_rsa_alg(card, 512, flags, 0); + _sc_card_add_rsa_alg(card, 768, flags, 0); _sc_card_add_rsa_alg(card, 1024, flags, 0); + _sc_card_add_rsa_alg(card, 1536, flags, 0); _sc_card_add_rsa_alg(card, 2048, flags, 0); +#ifdef MYEID_ECC_SUPPORT + flags |= SC_ALGORITHM_ECDSA_RAW; + ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES; + + _sc_card_add_ec_alg(card, 192, flags, ext_flags); + _sc_card_add_ec_alg(card, 224, flags, ext_flags); + _sc_card_add_ec_alg(card, 256, flags, ext_flags); +#endif + /* State that we have an RNG */ card->caps |= SC_CARD_CAP_RNG; @@ -282,7 +304,7 @@ static int myeid_process_fci(struct sc_card *card, struct sc_file *file, static int encode_file_structure(sc_card_t *card, const sc_file_t *file, u8 *out, size_t *outlen) { - const sc_acl_entry_t *read, *update, *delete, *generate; + const sc_acl_entry_t *read, *update, *delete, *generate; u8 buf[40]; int i; @@ -290,12 +312,12 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file, /* PrivateKey * 0E0000019 6217 81020400 820111 83024B01 8603000000 85028000 8A0100 RESULT 6984 * 6217 81020400 820111 83024B01 8603000000 85021000 8A0100 */ - memset(buf,0x0,sizeof(buf)); + memset(buf, 0x0, sizeof(buf)); buf[0] = 0x62; buf[1] = 0x17; /* File size */ - buf[2] = (SC_FILE_TYPE_WORKING_EF == file->type ?0x80:0x81); + buf[2] = (SC_FILE_TYPE_WORKING_EF == file->type ? 0x80 : 0x81); buf[3] = 0x02; buf[4] = (file->size >> 8) & 0xFF; buf[5] = file->size & 0xFF; @@ -365,8 +387,9 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file, buf[18] = 0x85; buf[19] = 0x02; /* AC right to clear default 0 */ - buf[20] = (SC_FILE_TYPE_INTERNAL_EF == file->type ?0x0:0x80); - buf[21] = 0x0; + /* TODO: Implement this */ + buf[20] = 0x00; /*(SC_FILE_TYPE_INTERNAL_EF == file->type ? 0x00 : 0x80);*/ + buf[21] = 0x00; /* Life Cycle Status tag */ buf[22] = 0x8A; @@ -379,7 +402,7 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file, break; case SC_FILE_TYPE_INTERNAL_EF: - buf[8] = 0x11; + buf[8] = file->ef_structure; /* RSA or EC */ break; case SC_FILE_TYPE_DF: @@ -479,7 +502,7 @@ static int myeid_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, LOG_FUNC_RETURN(card->ctx, iso_ops->pin_cmd(card, data, tries_left)); } -static int myeid_set_security_env2(sc_card_t *card, const sc_security_env_t *env, +static int myeid_set_security_env_rsa(sc_card_t *card, const sc_security_env_t *env, int se_num) { sc_apdu_t apdu; @@ -576,6 +599,103 @@ err: LOG_FUNC_RETURN(card->ctx, r); } +static int myeid_set_security_env_ec(sc_card_t *card, const sc_security_env_t *env, + int se_num) +{ + sc_apdu_t apdu; + u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; + u8 *p; + int r, locked = 0; + + assert(card != NULL && env != NULL); + LOG_FUNC_CALLED(card->ctx); + + if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC) + { + sc_log(card->ctx, "asymmetric keyref not supported.\n"); + return SC_ERROR_NOT_SUPPORTED; + } + if (se_num > 0) + { + sc_log(card->ctx, "restore security environment not supported.\n"); + return SC_ERROR_NOT_SUPPORTED; + } + + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0); + switch (env->operation) + { + case SC_SEC_OPERATION_DECIPHER: + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Decipher operation is not supported with EC keys.\n"); + return SC_ERROR_NOT_SUPPORTED; + break; + case SC_SEC_OPERATION_SIGN: + apdu.p1 = 0x41; + apdu.p2 = 0xB6; + break; + default: + return SC_ERROR_INVALID_ARGUMENTS; + } + apdu.le = 0; + p = sbuf; + if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) + { + *p++ = 0x80; /* algorithm reference */ + *p++ = 0x01; + *p++ = env->algorithm_ref & 0xFF; + } + if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) + { + *p++ = 0x81; + *p++ = 0x02; + memcpy(p, env->file_ref.value, 2); + p += 2; + } + if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) + { + *p++ = 0x84; + *p++ = 1; + *p++ = 0; + } + r = p - sbuf; + apdu.lc = r; + apdu.datalen = r; + apdu.data = sbuf; + apdu.resplen = 0; + if (se_num > 0) { + r = sc_lock(card); + LOG_TEST_RET(card->ctx, r, "sc_lock() failed"); + locked = 1; + } + if (apdu.datalen != 0) + { + r = sc_transmit_apdu(card, &apdu); + if (r) + { + sc_log(card->ctx, + "%s: APDU transmit failed", sc_strerror(r)); + goto err; + } + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + if (r) + { + sc_log(card->ctx, + "%s: Card returned error", sc_strerror(r)); + goto err; + } + } + if (se_num <= 0) + return 0; + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xF2, se_num); + r = sc_transmit_apdu(card, &apdu); + sc_unlock(card); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + return sc_check_sw(card, apdu.sw1, apdu.sw2); +err: + if (locked) + sc_unlock(card); + LOG_FUNC_RETURN(card->ctx, r); +} + static int myeid_set_security_env(struct sc_card *card, const struct sc_security_env *env, int se_num) { @@ -588,22 +708,39 @@ static int myeid_set_security_env(struct sc_card *card, tmp = *env; tmp.flags &= ~SC_SEC_ENV_ALG_PRESENT; tmp.flags |= SC_SEC_ENV_ALG_REF_PRESENT; - if (tmp.algorithm != SC_ALGORITHM_RSA) + + if (tmp.algorithm == SC_ALGORITHM_RSA) { - sc_log(card->ctx, "Only RSA algorithm supported.\n"); - return SC_ERROR_NOT_SUPPORTED; - } + tmp.algorithm_ref = 0x00; + /* potential FIXME: return an error, if an unsupported + * pad or hash was requested, although this shouldn't happen */ + if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) + tmp.algorithm_ref = 0x02; + if (tmp.algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1) + tmp.algorithm_ref |= 0x10; - tmp.algorithm_ref = 0x00; - /* potential FIXME: return an error, if an unsupported - * pad or hash was requested, although this shouldn't happen */ - if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) - tmp.algorithm_ref = 0x02; - if (tmp.algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1) - tmp.algorithm_ref |= 0x10; - return myeid_set_security_env2(card, &tmp, se_num); + return myeid_set_security_env_rsa(card, &tmp, se_num); + } + else if (tmp.algorithm == SC_ALGORITHM_EC) + { +#ifdef MYEID_ECC_SUPPORT + /* TODO: Update the algorithm_ref */ + tmp.algorithm_ref = 0xAA; + tmp.algorithm_flags = 0; + return myeid_set_security_env_ec(card, &tmp, se_num); +#else + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Elliptic curves are not supported in this version.\n"); + return SC_ERROR_NOT_SUPPORTED; +#endif + } + else + { + + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unsupported algorithm.\n"); + return SC_ERROR_NOT_SUPPORTED; + } } - return myeid_set_security_env2(card, env, se_num); + return myeid_set_security_env_rsa(card, env, se_num); } static int myeid_compute_signature(struct sc_card *card, const u8 * data, @@ -618,42 +755,42 @@ static int myeid_compute_signature(struct sc_card *card, const u8 * data, assert(card != NULL && data != NULL && out != NULL); if (datalen > 256) - LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); - /* INS: 0x2A PERFORM SECURITY OPERATION - * P1: 0x9E Resp: Digital Signature - * P2: 0x9A Cmd: Input for Digital Signature */ - sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E, 0x9A); - apdu.resp = rbuf; - apdu.resplen = sizeof(rbuf); - apdu.le = 256; + /* INS: 0x2A PERFORM SECURITY OPERATION + * P1: 0x9E Resp: Digital Signature + * P2: 0x9A Cmd: Input for Digital Signature */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E, 0x9A); + apdu.resp = rbuf; + apdu.resplen = sizeof(rbuf); + apdu.le = 256; if (datalen == 256) { - apdu.p2 = data[0]; - memcpy(sbuf, data+1, datalen-1); - apdu.lc = datalen - 1; - apdu.datalen = datalen - 1; + apdu.p2 = data[0]; + memcpy(sbuf, data+1, datalen-1); + apdu.lc = datalen - 1; + apdu.datalen = datalen - 1; } else { - memcpy(sbuf, data, datalen); - apdu.lc = datalen; - apdu.datalen = datalen; + memcpy(sbuf, data, datalen); + apdu.lc = datalen; + apdu.datalen = datalen; } - apdu.data = sbuf; - r = sc_transmit_apdu(card, &apdu); - LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + apdu.data = sbuf; + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); - if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) + if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) { int len = apdu.resplen > outlen ? outlen : apdu.resplen; memcpy(out, apdu.resp, len); LOG_FUNC_RETURN(card->ctx, len); - } + } - LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2)); + LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2)); } static int myeid_decipher(struct sc_card *card, const u8 * crgram, @@ -683,7 +820,8 @@ static int myeid_decipher(struct sc_card *card, const u8 * crgram, apdu.le = crgram_len; if (crgram_len == 256) - { apdu.le = 0; + { + apdu.le = 0; /* padding indicator byte, 0x81 = first half of 2048 bit cryptogram */ sbuf[0] = 0x81; memcpy(sbuf + 1, crgram, crgram_len / 2); @@ -696,7 +834,8 @@ static int myeid_decipher(struct sc_card *card, const u8 * crgram, apdu.lc = crgram_len + 1; } - apdu.datalen = apdu.lc; apdu.data = sbuf; + apdu.datalen = apdu.lc; + apdu.data = sbuf; r = sc_transmit_apdu(card, &apdu); LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); @@ -818,8 +957,6 @@ static int myeid_loadkey(sc_card_t *card, int mode, u8* value, int value_len) mode != LOAD_KEY_PUBLIC_EXPONENT) sbuf[len++] = 0x0; - LOG_FUNC_CALLED(card->ctx); - if(mode == LOAD_KEY_MODULUS && value_len >= 256) { r=0; @@ -852,6 +989,16 @@ static int myeid_loadkey(sc_card_t *card, int mode, u8* value, int value_len) memset(&sbuf, 0, SC_MAX_APDU_BUFFER_SIZE); memcpy(sbuf,value + 128, value_len - 128); } + else if(mode == LOAD_KEY_EC_PRIVATE) { + memcpy(sbuf, value, value_len); + len = value_len; + mode = LOAD_KEY_MODE_EC_PRIV; + } + else if(mode == LOAD_KEY_EC_PUBLIC) { + memcpy(sbuf, value, value_len); + len = value_len; + mode = LOAD_KEY_MODE_EC_PUB; + } else { memcpy(sbuf + len, value, value_len); @@ -865,7 +1012,7 @@ static int myeid_loadkey(sc_card_t *card, int mode, u8* value, int value_len) apdu.data = sbuf; apdu.datalen = len; apdu.lc = len; - + r = sc_transmit_apdu(card, &apdu); LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); @@ -886,22 +1033,34 @@ static int myeid_generate_store_key(struct sc_card *card, if (data->op_type == OP_TYPE_GENERATE) { len = 0; - - sbuf[len++] = 0x30; - sbuf[len++] = 0x05; - sbuf[len++] = 0x81; - sbuf[len++] = data->pubexp_len; - - memcpy(sbuf + len, data->pubexp, data->pubexp_len); - len += data->pubexp_len; - memset(&apdu, 0, sizeof(apdu)); - sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x46, 0x00, 0x00); + + if(data->key_type == SC_CARDCTL_MYEID_KEY_RSA) + { + sbuf[len++] = 0x30; + sbuf[len++] = 0x05; + sbuf[len++] = 0x81; + sbuf[len++] = data->pubexp_len; + + memcpy(sbuf + len, data->pubexp, data->pubexp_len); + len += data->pubexp_len; + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x46, 0x00, 0x00); + apdu.data = sbuf; + } + else if(data->key_type == SC_CARDCTL_MYEID_KEY_EC) { + + sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x46, 0x00, 0x00); + + apdu.data = NULL; + apdu.resp = sbuf; + apdu.resplen = 0x00; + apdu.le = 0x00; + } + apdu.cla = 0x00; - apdu.data = sbuf; apdu.datalen = len; apdu.lc = len; - + r = sc_transmit_apdu(card, &apdu); LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); @@ -910,21 +1069,31 @@ static int myeid_generate_store_key(struct sc_card *card, } else { - if((r=myeid_loadkey(card, LOAD_KEY_PRIME_P, - data->primep, data->primep_len)) >= 0 && - (r=myeid_loadkey(card, LOAD_KEY_PRIME_Q, - data->primeq, data->primeq_len)) >= 0 && - (r=myeid_loadkey(card, LOAD_KEY_DP1, - data->dp1, data->dp1_len)) >= 0 && - (r=myeid_loadkey(card, LOAD_KEY_DQ1, - data->dq1, data->dq1_len)) >= 0 && - (r=myeid_loadkey(card, LOAD_KEY_INVQ, - data->invq, data->invq_len)) >= 0 && - (r=myeid_loadkey(card, LOAD_KEY_MODULUS, - data->mod, data->mod_len)) >= 0 && - (r=myeid_loadkey(card, LOAD_KEY_PUBLIC_EXPONENT, - data->pubexp, data->pubexp_len)) >= 0) + if(data->key_type == SC_CARDCTL_MYEID_KEY_RSA) + { + if((r=myeid_loadkey(card, LOAD_KEY_PRIME_P, + data->primep, data->primep_len)) >= 0 && + (r=myeid_loadkey(card, LOAD_KEY_PRIME_Q, + data->primeq, data->primeq_len)) >= 0 && + (r=myeid_loadkey(card, LOAD_KEY_DP1, + data->dp1, data->dp1_len)) >= 0 && + (r=myeid_loadkey(card, LOAD_KEY_DQ1, + data->dq1, data->dq1_len)) >= 0 && + (r=myeid_loadkey(card, LOAD_KEY_INVQ, + data->invq, data->invq_len)) >= 0 && + (r=myeid_loadkey(card, LOAD_KEY_MODULUS, + data->mod, data->key_len_bits)) >= 0 && + (r=myeid_loadkey(card, LOAD_KEY_PUBLIC_EXPONENT, + data->pubexp, data->pubexp_len)) >= 0) + LOG_FUNC_RETURN(card->ctx, r); + } + else if(data->key_type == SC_CARDCTL_MYEID_KEY_EC) { + if((r = myeid_loadkey(card, LOAD_KEY_EC_PRIVATE, data->d, + data->d_len)) >= 0 && + (r = myeid_loadkey(card, LOAD_KEY_EC_PUBLIC, data->ecpublic_point, + data->ecpublic_point_len)) >= 0) LOG_FUNC_RETURN(card->ctx, r); + } } LOG_FUNC_RETURN(card->ctx, r); @@ -952,17 +1121,17 @@ static int myeid_activate_card(struct sc_card *card) LOG_FUNC_RETURN(card->ctx, r); } -static int myeid_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) +static int myeid_get_info(struct sc_card *card, u8 *rbuf, size_t buflen) { int r; sc_apdu_t apdu; - u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; - + LOG_FUNC_CALLED(card->ctx); + sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0xA0); apdu.resp = rbuf; - apdu.resplen = sizeof(rbuf); - apdu.le = 256; + apdu.resplen = buflen; + apdu.le = buflen; r = sc_transmit_apdu(card, &apdu); LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); @@ -972,13 +1141,41 @@ static int myeid_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) if (apdu.resplen != 20) { - sc_log(card->ctx, "unexpected response to GET DATA serial number\n"); + sc_log(card->ctx, "Unexpected response to GET DATA (applet info)\n"); return SC_ERROR_INTERNAL; - } + } + + /* store the applet version */ + card->version.fw_major = rbuf[5] * 10 + rbuf[6]; + card->version.fw_minor = rbuf[7]; + /* add version to name */ + u8 nameBuf[100]; + sprintf(nameBuf, "%s %d.%d.%d", card->name, rbuf[5], rbuf[6], rbuf[7]); + card->name = nameBuf; + //card->driver->name + LOG_FUNC_RETURN(card->ctx, r); +} + +static int myeid_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) +{ + int r; + u8 rbuf[256]; + + LOG_FUNC_CALLED(card->ctx); + + /* if number cached, get it + if(card->serialnr.value) { + memcpy(serial, &card->serialnr, sizeof(*serial)); + LOG_FUNC_RETURN(card->ctx, r); + }*/ + + /* get number from card */ + r = myeid_get_info(card, rbuf, sizeof(rbuf)); + LOG_TEST_RET(card->ctx, r, "Get applet info failed"); /* cache serial number */ - memcpy(card->serialnr.value, &rbuf[10], 8); - card->serialnr.len = 8; + memcpy(card->serialnr.value, &rbuf[8], 10); + card->serialnr.len = 10; /* copy and return serial number */ memcpy(serial, &card->serialnr, sizeof(*serial)); diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h index e32ad8c1..370cff42 100644 --- a/src/libopensc/cardctl.h +++ b/src/libopensc/cardctl.h @@ -821,8 +821,16 @@ typedef struct sc_rtecp_genkey_data { } sc_rtecp_genkey_data_t; /* -* MyEID stuff -*/ + * MyEID stuff + */ + enum SC_CARDCTL_MYEID_KEY_TYPE { + SC_CARDCTL_MYEID_KEY_RSA = 0x11, + SC_CARDCTL_MYEID_KEY_EC = 0x21, + /* SC_CARDCTL_MYEID_KEY_AES = 0x?, // for future use + SC_CARDCTL_MYEID_KEY_DES = 0x?, + SC_CARDCTL_MYEID_KEY_3DES = 0x?, */ + }; + struct sc_cardctl_myeid_data_obj { int P1; int P2; @@ -832,22 +840,28 @@ typedef struct sc_rtecp_genkey_data { }; struct sc_cardctl_myeid_gen_store_key_info { - int op_type; - unsigned int mod_len; - unsigned char *mod; - unsigned int pubexp_len; - unsigned char *pubexp; - unsigned int primep_len; - unsigned char *primep; - unsigned int primeq_len; - unsigned char *primeq; - unsigned int dp1_len; - unsigned char *dp1; - unsigned int dq1_len; - unsigned char *dq1; - unsigned int invq_len; - unsigned char *invq; -}; + int op_type; + unsigned int key_type; /* value of SC_CARDCTL_MYEID_KEY_TYPE */ + unsigned int key_len_bits; + unsigned char *mod; + unsigned int pubexp_len; + unsigned char *pubexp; + unsigned int primep_len; + unsigned char *primep; + unsigned int primeq_len; + unsigned char *primeq; + unsigned int dp1_len; + unsigned char *dp1; + unsigned int dq1_len; + unsigned char *dq1; + unsigned int invq_len; + unsigned char *invq; + /* new for MyEID > 3.6.0 */ + unsigned char *d; /* EC private key */ + unsigned int d_len; /* EC */ + unsigned char *ecpublic_point; /* EC public key */ + unsigned int ecpublic_point_len; /* EC */ + }; /* * PIV info diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c index 109eeee0..ea5f118b 100644 --- a/src/libopensc/pkcs15-prkey.c +++ b/src/libopensc/pkcs15-prkey.c @@ -576,6 +576,14 @@ sc_pkcs15_free_prkey(struct sc_pkcs15_prkey *key) break; case SC_ALGORITHM_EC: /* TODO: -DEE may not need much */ + if (key->u.ec.params.der.value) + free(key->u.ec.params.der.value); + if (key->u.ec.params.named_curve) + free(key->u.ec.params.named_curve); + if (key->u.ec.privateD.data) + free(key->u.ec.privateD.data); + if (key->u.ec.ecpointQ.value) + free(key->u.ec.ecpointQ.value); break; } } @@ -658,6 +666,53 @@ sc_pkcs15_convert_prkey(struct sc_pkcs15_prkey *pkcs15_key, void *evp_key) sc_pkcs15_convert_bignum(&dst->d, EC_KEY_get0_private_key(src)); break; } + case EVP_PKEY_EC: { + struct sc_pkcs15_prkey_ec *dst = &pkcs15_key->u.ec; + EC_KEY *src = EVP_PKEY_get0(pk); + + assert(src); + pkcs15_key->algorithm = SC_ALGORITHM_EC; + assert(EC_KEY_get0_private_key(src)); + if (!sc_pkcs15_convert_bignum(&dst->privateD, EC_KEY_get0_private_key(src))) + return SC_ERROR_INCOMPATIBLE_KEY; + + assert(EC_KEY_get0_public_key(src)); + + unsigned char buf[255]; + size_t buflen = 255; + + const EC_GROUP *grp = EC_KEY_get0_group(src); + if(grp == 0) { + //EC_KEY_free(src); + return SC_ERROR_INCOMPATIBLE_KEY; + } + + /* get curve name */ + int nid; + nid = EC_GROUP_get_curve_name(grp); + if(nid != 0) + dst->params.named_curve = strdup(OBJ_nid2sn(nid)); + + /* Decode EC_POINT from a octet string */ + buflen = EC_POINT_point2oct(grp, (const EC_POINT *) EC_KEY_get0_public_key(src), + POINT_CONVERSION_UNCOMPRESSED, buf, buflen, NULL); + + /* clean up */ + //EC_KEY_free(src); + + /* copy the public key */ + if (buflen > 0) { + dst->ecpointQ.value = malloc(buflen); + memcpy(dst->ecpointQ.value, buf, buflen); + dst->ecpointQ.len = buflen; + /* calculate the field length */ + dst->params.field_length = (buflen - 1) / 2 * 8; + } + else + return SC_ERROR_INCOMPATIBLE_KEY; + + break; + } #endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_EC) */ default: return SC_ERROR_NOT_SUPPORTED; diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 37cc17f7..98cf2e94 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -81,12 +81,33 @@ static const struct sc_asn1_entry c_asn1_rsakey_attr[C_ASN1_RSAKEY_ATTR_SIZE] = { NULL, 0, 0, 0, NULL, NULL } }; +#define C_ASN1_ECKEY_VALUE_CHOICE_SIZE 3 +static const struct sc_asn1_entry c_asn1_eckey_value_choice[C_ASN1_ECKEY_VALUE_CHOICE_SIZE] = { + { "path", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_EMPTY_ALLOWED, NULL, NULL }, + { "direct", SC_ASN1_OCTET_STRING, SC_ASN1_CTX | 0 | SC_ASN1_CONS, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL }, + { NULL, 0, 0, 0, NULL, NULL } +}; + +#define C_ASN1_ECKEY_ATTR_SIZE 4 +static const struct sc_asn1_entry c_asn1_eckey_attr[C_ASN1_ECKEY_ATTR_SIZE] = { + { "value", SC_ASN1_CHOICE, 0, 0, NULL, NULL }, + { "fieldSize", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "keyInfo", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { NULL, 0, 0, 0, NULL, NULL } +}; + #define C_ASN1_RSA_TYPE_ATTR_SIZE 2 static const struct sc_asn1_entry c_asn1_rsa_type_attr[C_ASN1_RSA_TYPE_ATTR_SIZE] = { { "publicRSAKeyAttributes", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; +#define C_ASN1_EC_TYPE_ATTR_SIZE 2 +static const struct sc_asn1_entry c_asn1_ec_type_attr[C_ASN1_EC_TYPE_ATTR_SIZE] = { + { "publicECKeyAttributes", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, + { NULL, 0, 0, 0, NULL, NULL } +}; + #define C_ASN1_DSAKEY_ATTR_SIZE 2 static const struct sc_asn1_entry c_asn1_dsakey_attr[C_ASN1_DSAKEY_ATTR_SIZE] = { { "value", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, @@ -114,11 +135,12 @@ static const struct sc_asn1_entry c_asn1_gostr3410_type_attr[C_ASN1_GOST3410_TYP { NULL, 0, 0, 0, NULL, NULL } }; -#define C_ASN1_PUBKEY_CHOICE_SIZE 4 +#define C_ASN1_PUBKEY_CHOICE_SIZE 5 static const struct sc_asn1_entry c_asn1_pubkey_choice[C_ASN1_PUBKEY_CHOICE_SIZE] = { { "publicRSAKey", SC_ASN1_PKCS15_OBJECT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, { "publicDSAKey", SC_ASN1_PKCS15_OBJECT, 2 | SC_ASN1_CTX | SC_ASN1_CONS, 0, NULL, NULL }, { "publicGOSTR3410Key", SC_ASN1_PKCS15_OBJECT, 4 | SC_ASN1_CTX | SC_ASN1_CONS, 0, NULL, NULL }, + { "publicECKey", SC_ASN1_PKCS15_OBJECT, 0 | SC_ASN1_CTX | SC_ASN1_CONS, 0, NULL, NULL }, /*TODO: -DEE not clear EC is needed here as look like it is for pukdf */ { NULL, 0, 0, 0, NULL, NULL } }; @@ -145,6 +167,9 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card, struct sc_asn1_entry asn1_rsakey_value_choice[C_ASN1_RSAKEY_VALUE_CHOICE_SIZE]; struct sc_asn1_entry asn1_rsakey_attr[C_ASN1_RSAKEY_ATTR_SIZE]; struct sc_asn1_entry asn1_rsa_type_attr[C_ASN1_RSA_TYPE_ATTR_SIZE]; + struct sc_asn1_entry asn1_eckey_value_choice[C_ASN1_ECKEY_VALUE_CHOICE_SIZE]; + struct sc_asn1_entry asn1_eckey_attr[C_ASN1_ECKEY_ATTR_SIZE]; + struct sc_asn1_entry asn1_ec_type_attr[C_ASN1_EC_TYPE_ATTR_SIZE]; struct sc_asn1_entry asn1_dsakey_attr[C_ASN1_DSAKEY_ATTR_SIZE]; struct sc_asn1_entry asn1_dsa_type_attr[C_ASN1_DSA_TYPE_ATTR_SIZE]; struct sc_asn1_entry asn1_gostr3410key_attr[C_ASN1_GOST3410KEY_ATTR_SIZE]; @@ -153,6 +178,8 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card, struct sc_asn1_entry asn1_pubkey[C_ASN1_PUBKEY_SIZE]; struct sc_asn1_pkcs15_object rsakey_obj = { obj, asn1_com_key_attr, asn1_com_pubkey_attr, asn1_rsa_type_attr }; + struct sc_asn1_pkcs15_object eckey_obj = { obj, asn1_com_key_attr, + asn1_com_pubkey_attr, asn1_ec_type_attr }; struct sc_asn1_pkcs15_object dsakey_obj = { obj, asn1_com_key_attr, asn1_com_pubkey_attr, asn1_dsa_type_attr }; struct sc_asn1_pkcs15_object gostr3410key_obj = { obj, asn1_com_key_attr, @@ -163,6 +190,9 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card, sc_copy_asn1_entry(c_asn1_rsa_type_attr, asn1_rsa_type_attr); sc_copy_asn1_entry(c_asn1_rsakey_value_choice, asn1_rsakey_value_choice); sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr); + sc_copy_asn1_entry(c_asn1_ec_type_attr, asn1_ec_type_attr); + sc_copy_asn1_entry(c_asn1_eckey_value_choice, asn1_eckey_value_choice); + sc_copy_asn1_entry(c_asn1_eckey_attr, asn1_eckey_attr); sc_copy_asn1_entry(c_asn1_dsa_type_attr, asn1_dsa_type_attr); sc_copy_asn1_entry(c_asn1_dsakey_attr, asn1_dsakey_attr); sc_copy_asn1_entry(c_asn1_gostr3410_type_attr, asn1_gostr3410_type_attr); @@ -175,6 +205,7 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card, sc_format_asn1_entry(asn1_pubkey_choice + 0, &rsakey_obj, NULL, 0); sc_format_asn1_entry(asn1_pubkey_choice + 1, &dsakey_obj, NULL, 0); sc_format_asn1_entry(asn1_pubkey_choice + 2, &gostr3410key_obj, NULL, 0); + sc_format_asn1_entry(asn1_pubkey_choice + 3, &eckey_obj, NULL, 0); sc_format_asn1_entry(asn1_rsa_type_attr + 0, asn1_rsakey_attr, NULL, 0); @@ -184,6 +215,14 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card, sc_format_asn1_entry(asn1_rsakey_attr + 0, asn1_rsakey_value_choice, NULL, 0); sc_format_asn1_entry(asn1_rsakey_attr + 1, &info.modulus_length, NULL, 0); + sc_format_asn1_entry(asn1_ec_type_attr + 0, asn1_eckey_attr, NULL, 0); + + sc_format_asn1_entry(asn1_eckey_value_choice + 0, &info.path, NULL, 0); + sc_format_asn1_entry(asn1_eckey_value_choice + 1, &der->value, &der->len, 0); + + sc_format_asn1_entry(asn1_eckey_attr + 0, asn1_eckey_value_choice, NULL, 0); + sc_format_asn1_entry(asn1_eckey_attr + 1, &info.field_length, NULL, 0); + sc_format_asn1_entry(asn1_dsa_type_attr + 0, asn1_dsakey_attr, NULL, 0); sc_format_asn1_entry(asn1_dsakey_attr + 0, &info.path, NULL, 0); @@ -229,7 +268,11 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card, keyinfo_gostparams->gostr3410 = (unsigned int)gostr3410_params[0]; keyinfo_gostparams->gostr3411 = (unsigned int)gostr3410_params[1]; keyinfo_gostparams->gost28147 = (unsigned int)gostr3410_params[2]; - } else { + } + else if (asn1_pubkey_choice[3].flags & SC_ASN1_PRESENT) { + obj->type = SC_PKCS15_TYPE_PUBKEY_EC; + } + else { obj->type = SC_PKCS15_TYPE_PUBKEY_DSA; } if (!p15card->app || !p15card->app->ddo.aid.len) { @@ -269,17 +312,24 @@ int sc_pkcs15_encode_pukdf_entry(sc_context_t *ctx, struct sc_asn1_entry asn1_rsakey_value_choice[C_ASN1_RSAKEY_VALUE_CHOICE_SIZE]; struct sc_asn1_entry asn1_rsakey_attr[C_ASN1_RSAKEY_ATTR_SIZE]; struct sc_asn1_entry asn1_rsa_type_attr[C_ASN1_RSA_TYPE_ATTR_SIZE]; + struct sc_asn1_entry asn1_eckey_value_choice[C_ASN1_ECKEY_VALUE_CHOICE_SIZE]; + struct sc_asn1_entry asn1_eckey_attr[C_ASN1_ECKEY_ATTR_SIZE]; + struct sc_asn1_entry asn1_ec_type_attr[C_ASN1_EC_TYPE_ATTR_SIZE]; struct sc_asn1_entry asn1_dsakey_attr[C_ASN1_DSAKEY_ATTR_SIZE]; struct sc_asn1_entry asn1_dsa_type_attr[C_ASN1_DSA_TYPE_ATTR_SIZE]; struct sc_asn1_entry asn1_gostr3410key_attr[C_ASN1_GOST3410KEY_ATTR_SIZE]; struct sc_asn1_entry asn1_gostr3410_type_attr[C_ASN1_GOST3410_TYPE_ATTR_SIZE]; struct sc_asn1_entry asn1_pubkey_choice[C_ASN1_PUBKEY_CHOICE_SIZE]; struct sc_asn1_entry asn1_pubkey[C_ASN1_PUBKEY_SIZE]; + struct sc_pkcs15_pubkey_info *pubkey = (struct sc_pkcs15_pubkey_info *) obj->data; struct sc_asn1_pkcs15_object rsakey_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr, asn1_com_pubkey_attr, asn1_rsa_type_attr }; + struct sc_asn1_pkcs15_object eckey_obj = { (struct sc_pkcs15_object *) obj, + asn1_com_key_attr, + asn1_com_pubkey_attr, asn1_ec_type_attr }; struct sc_asn1_pkcs15_object dsakey_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr, asn1_com_pubkey_attr, asn1_dsa_type_attr }; @@ -295,6 +345,9 @@ int sc_pkcs15_encode_pukdf_entry(sc_context_t *ctx, sc_copy_asn1_entry(c_asn1_rsa_type_attr, asn1_rsa_type_attr); sc_copy_asn1_entry(c_asn1_rsakey_value_choice, asn1_rsakey_value_choice); sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr); + sc_copy_asn1_entry(c_asn1_ec_type_attr, asn1_ec_type_attr); + sc_copy_asn1_entry(c_asn1_eckey_value_choice, asn1_eckey_value_choice); + sc_copy_asn1_entry(c_asn1_eckey_attr, asn1_eckey_attr); sc_copy_asn1_entry(c_asn1_dsa_type_attr, asn1_dsa_type_attr); sc_copy_asn1_entry(c_asn1_dsakey_attr, asn1_dsakey_attr); sc_copy_asn1_entry(c_asn1_gostr3410_type_attr, asn1_gostr3410_type_attr); @@ -338,9 +391,21 @@ int sc_pkcs15_encode_pukdf_entry(sc_context_t *ctx, sc_format_asn1_entry(asn1_gostr3410key_attr + 3, &keyinfo_gostparams->gost28147, NULL, 1); } + break; + case SC_PKCS15_TYPE_PUBKEY_EC: + /* MyEID is a PKCS15 card with ECC */ + sc_format_asn1_entry(asn1_pubkey_choice + 3, &eckey_obj, NULL, 1); + + sc_format_asn1_entry(asn1_ec_type_attr + 0, asn1_eckey_attr, NULL, 1); + if (pubkey->path.len || !obj->content.value) + sc_format_asn1_entry(asn1_eckey_value_choice + 0, &pubkey->path, NULL, 1); + else + sc_format_asn1_entry(asn1_eckey_value_choice + 1, obj->content.value, (void *)&obj->content.len, 1); + sc_format_asn1_entry(asn1_eckey_attr + 0, asn1_eckey_value_choice, NULL, 1); + sc_format_asn1_entry(asn1_eckey_attr + 1, &pubkey->field_length, NULL, 1); + break; default: - /* TODO: -DEE Should add ECC but don't have PKCS15 card with ECC */ sc_log(ctx, "Unsupported public key type: %X", obj->type); LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); break; @@ -581,12 +646,22 @@ int sc_pkcs15_encode_pubkey_ec(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key, u8 **buf, size_t *buflen) { - *buf = malloc(key->ecpointQ.len); + int r; + /*u8 * ecpoint_data; + size_t ecpoint_len;*/ + struct sc_asn1_entry asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE]; + + /*buf = malloc(key->ecpointQ.len); if (*buf == NULL) - return SC_ERROR_OUT_OF_MEMORY; - - memcpy(*buf, key->ecpointQ.value, key->ecpointQ.len); + return SC_ERROR_OUT_OF_MEMORY;*/ + + sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); + sc_format_asn1_entry(asn1_ec_pointQ + 0, key->ecpointQ.value, &key->ecpointQ.len, 1); + +/* memcpy(*buf, key->ecpointQ.value, key->ecpointQ.len); *buflen = key->ecpointQ.len; +*/ + r = sc_asn1_encode(ctx, asn1_ec_pointQ, buf, buflen); sc_log(ctx, "DEE-EC key->ecpointQ=%p:%d *buf=%p:%d", key->ecpointQ.value, key->ecpointQ.len, *buf, *buflen); return 0; @@ -754,6 +829,12 @@ sc_pkcs15_pubkey_from_prvkey(struct sc_context *ctx, struct sc_pkcs15_prkey *prv break; case SC_ALGORITHM_GOSTR3410: break; + case SC_ALGORITHM_EC: + pubkey->u.ec.ecpointQ.value = malloc(prvkey->u.ec.ecpointQ.len); + memcpy(pubkey->u.ec.ecpointQ.value, prvkey->u.ec.ecpointQ.value, prvkey->u.ec.ecpointQ.len); + pubkey->u.ec.ecpointQ.len = prvkey->u.ec.ecpointQ.len; + rv = SC_SUCCESS; + break; default: sc_log(ctx, "Unsupported private key algorithm"); return SC_ERROR_NOT_SUPPORTED; @@ -1175,6 +1256,52 @@ sc_pkcs15_convert_pubkey(struct sc_pkcs15_pubkey *pkcs15_key, void *evp_key) return SC_ERROR_INTERNAL; break; } + case EVP_PKEY_EC: { + struct sc_pkcs15_pubkey_ec *dst = &pkcs15_key->u.ec; + EC_KEY *src = EVP_PKEY_get0(pk); + + assert(src); + pkcs15_key->algorithm = SC_ALGORITHM_EC; + + assert(EC_KEY_get0_public_key(src)); + + unsigned char buf[255]; + size_t buflen = 255; + + const EC_GROUP *grp = EC_KEY_get0_group(src); + if(grp == 0) { + //EC_KEY_free(src); + return SC_ERROR_INCOMPATIBLE_KEY; + } + + /* Decode EC_POINT from a octet string */ + buflen = EC_POINT_point2oct(grp, (const EC_POINT *) EC_KEY_get0_public_key(src), + POINT_CONVERSION_UNCOMPRESSED, buf, buflen, NULL); + + /* get curve name */ + int nid; + nid = EC_GROUP_get_curve_name(grp); + if(nid != 0) { + const char *name = OBJ_nid2sn(nid); + if(sizeof(name) > 0) + dst->params.named_curve = strdup(name); + } + /* clean up */ + //EC_KEY_free(src); + + /* copy the public key */ + if (buflen > 0) { + dst->ecpointQ.value = malloc(buflen); + memcpy(dst->ecpointQ.value, buf, buflen); + dst->ecpointQ.len = buflen; + /* calculate the field length */ + dst->params.field_length = (buflen - 1) / 2 * 8; + } + else + return SC_ERROR_INCOMPATIBLE_KEY; + + break; + } #endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_EC) */ default: return SC_ERROR_NOT_SUPPORTED; diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c index e08b00ac..963b9629 100644 --- a/src/libopensc/pkcs15-sec.c +++ b/src/libopensc/pkcs15-sec.c @@ -303,7 +303,7 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card, sc_security_env_t senv; sc_algorithm_info_t *alg_info; const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data; - u8 buf[512], *tmp; + u8 buf[1024], *tmp; size_t modlen; unsigned long pad_flags = 0, sec_flags = 0; diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h index 23799d09..a72cc747 100644 --- a/src/libopensc/pkcs15.h +++ b/src/libopensc/pkcs15.h @@ -220,6 +220,7 @@ struct sc_pkcs15_pubkey_ec { struct sc_pkcs15_prkey_ec { struct sc_pkcs15_ec_parameters params; sc_pkcs15_bignum_t privateD; /* note this is bignum */ + sc_pkcs15_der_t ecpointQ; /* note this is der */ }; struct sc_pkcs15_pubkey_gostr3410 { diff --git a/src/pkcs15init/myeid.profile b/src/pkcs15init/myeid.profile index 7b244a96..46ae44c3 100644 --- a/src/pkcs15init/myeid.profile +++ b/src/pkcs15init/myeid.profile @@ -17,17 +17,17 @@ cardinfo { # pkcs15 { # Put certificates into the CDF itself? - direct-certificates = no; + direct-certificates = no; # Put the DF length into the ODF file? - encode-df-length = no; + encode-df-length = no; # Have a lastUpdate field in the EF(TokenInfo)? - do-last-update = no; + do-last-update = no; } option default { macros { - #protected = READ=NONE, UPDATE=CHV1, DELETE=CHV2; - #unprotected = READ=NONE, UPDATE=CHV1, DELETE=CHV1; + #protected = READ=NONE, UPDATE=CHV1, DELETE=CHV2; + #unprotected = READ=NONE, UPDATE=CHV1, DELETE=CHV1; unusedspace-size = 510; odf-size = 255; @@ -36,7 +36,7 @@ option default { cdf-trusted-size = 510; prkdf-size = 1530; pukdf-size = 1530; - dodf-size = 255; + dodf-size = 1530; } } @@ -195,6 +195,16 @@ filesystem { structure = transparent; acl = READ=NONE, UPDATE=$PIN, DELETE=$PIN; } + EF privdata { + file-id = 4501; + structure = transparent; + acl = READ=$PIN, UPDATE=$PIN, DELETE=$PIN; + } + EF data { + file-id = 4501; + structure = transparent; + acl = READ=NONE, UPDATE=$PIN, DELETE=$PIN; + } } } } diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index 7d715b5c..b6028df5 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -1528,7 +1528,9 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card, keyinfo_gostparams->gostr3411 = keyargs->params.gost.gostr3411; keyinfo_gostparams->gost28147 = keyargs->params.gost.gost28147; } - + else if(key.algorithm == SC_ALGORITHM_EC) + key_info->field_length = keybits; + /* Select a intrinsic Key ID if the user didn't specify one */ r = select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_PUBKEY, &keyargs->id, &key); LOG_TEST_RET(ctx, r, "Get intrinsic ID error"); @@ -1974,7 +1976,8 @@ check_key_compatibility(struct sc_pkcs15_card *p15card, struct sc_pkcs15_prkey * count = p15card->card->algorithm_count; for (info = p15card->card->algorithms; count--; info++) { - if (info->algorithm != key->algorithm || info->key_length != key_length || (info->flags & flags) != flags) + /* don't check flags if none was specified */ + if (info->algorithm != key->algorithm || info->key_length != key_length || (flags != 0 && (info->flags & flags) != flags)) continue; if (key->algorithm == SC_ALGORITHM_RSA) { @@ -2106,7 +2109,11 @@ prkey_bits(struct sc_pkcs15_card *p15card, struct sc_pkcs15_prkey *key) sc_log(ctx, "Unsupported key (keybits %u)", sc_pkcs15init_keybits(&key->u.gostr3410.d)); return SC_ERROR_OBJECT_NOT_VALID; } - return SC_PKCS15_GOSTR3410_KEYSIZE; + return SC_PKCS15_GOSTR3410_KEYSIZE; + case SC_ALGORITHM_EC: + /* calculation returns one bit too small, add one bu default */ + sc_log(ctx, "Private EC key length %u", sc_pkcs15init_keybits(&key->u.ec.privateD) + 1); + return sc_pkcs15init_keybits(&key->u.ec.privateD) + 1; } sc_log(ctx, "Unsupported key algorithm."); return SC_ERROR_NOT_SUPPORTED; @@ -2197,6 +2204,8 @@ select_intrinsic_id(struct sc_pkcs15_card *p15card, struct sc_profile *profile, else if (pubkey->algorithm == SC_ALGORITHM_GOSTR3410 && !pubkey->u.gostr3410.xy.data) goto done; + else if (pubkey->algorithm == SC_ALGORITHM_EC && !pubkey->u.ec.ecpointQ.value) + goto done; /* In Mozilla 'GOST R 34.10' is not yet supported. * So, switch to the ID recommended by RFC2459 */ @@ -2208,8 +2217,11 @@ select_intrinsic_id(struct sc_pkcs15_card *p15card, struct sc_profile *profile, SHA1(pubkey->u.rsa.modulus.data, pubkey->u.rsa.modulus.len, id->value); else if (pubkey->algorithm == SC_ALGORITHM_DSA) SHA1(pubkey->u.dsa.pub.data, pubkey->u.dsa.pub.len, id->value); - else if (pubkey->algorithm == SC_ALGORITHM_EC) - SHA1(pubkey->u.ec.ecpointQ.value, pubkey->u.ec.ecpointQ.len, id->value); + else if (pubkey->algorithm == SC_ALGORITHM_EC) { + /* ID should be SHA1 of the X coordinate according to PKCS#15 v1.1 */ + /* skip the 04 tag and get the X component */ + SHA1(pubkey->u.ec.ecpointQ.value+1, (pubkey->u.ec.ecpointQ.len - 1) / 2, id->value); + } else goto done; diff --git a/src/pkcs15init/pkcs15-myeid.c b/src/pkcs15init/pkcs15-myeid.c index 07012b40..816e039b 100644 --- a/src/pkcs15init/pkcs15-myeid.c +++ b/src/pkcs15init/pkcs15-myeid.c @@ -41,21 +41,18 @@ unsigned char MYEID_DEFAULT_PUBKEY[] = {0x01, 0x00, 0x01}; /* For Myeid, all objects are files that can be deleted in any order */ static int myeid_delete_object(struct sc_profile *profile, struct sc_pkcs15_card *p15card, - struct sc_pkcs15_object *object, const struct sc_path *path) -{ + struct sc_pkcs15_object *object, const struct sc_path *path) { LOG_FUNC_CALLED(p15card->card->ctx); return sc_pkcs15init_delete_by_path(profile, p15card, path); } - /* * Get 'Initialize Applet' data * using the ACLs defined in card profile. */ static int myeid_get_init_applet_data(struct sc_profile *profile, struct sc_pkcs15_card *p15card, - unsigned char *data, size_t data_len) -{ + unsigned char *data, size_t data_len) { struct sc_context *ctx = p15card->card->ctx; struct sc_file *tmp_file = NULL; const struct sc_acl_entry *entry = NULL; @@ -77,17 +74,17 @@ myeid_get_init_applet_data(struct sc_profile *profile, struct sc_pkcs15_card *p1 LOG_TEST_RET(ctx, r, "MF fixup failed"); /* AC 'Create DF' and 'Create EF' */ - *(data + 2) = 0x00; /* 'NONE' */ - entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_CREATE); + *(data + 2) = 0x00; /* 'NONE' */ + entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_CREATE); if (entry->method == SC_AC_CHV) - *(data + 2) = entry->key_ref | (entry->key_ref << 4); /* 'CHVx'. */ + *(data + 2) = entry->key_ref | (entry->key_ref << 4); /* 'CHVx'. */ else if (entry->method == SC_AC_NEVER) - *(data + 2) = 0xFF; /* 'NEVER'. */ + *(data + 2) = 0xFF; /* 'NEVER'. */ /* AC 'INITIALISE APPLET'. */ - *(data + 3) = 0x0F; /* 'NONE' */ + *(data + 3) = 0x0F; /* 'NONE' */ #ifndef KEEP_AC_NONE_FOR_INIT_APPLET - entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_DELETE); + entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_DELETE); if (entry->method == SC_AC_CHV) *(data + 3) = (entry->key_ref << 4) | 0xF; else if (entry->method == SC_AC_NEVER) @@ -106,33 +103,31 @@ myeid_get_init_applet_data(struct sc_profile *profile, struct sc_pkcs15_card *p1 LOG_TEST_RET(ctx, r, "Application DF fixup failed"); /* AC 'Create DF' and 'Create EF' */ - *(data + 5) = 0x00; /* 'NONE' */ - entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_CREATE); + *(data + 5) = 0x00; /* 'NONE' */ + entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_CREATE); if (entry->method == SC_AC_CHV) - *(data + 5) = entry->key_ref | (entry->key_ref << 4); /* 'CHVx' */ + *(data + 5) = entry->key_ref | (entry->key_ref << 4); /* 'CHVx' */ else if (entry->method == SC_AC_NEVER) - *(data + 5) = 0xFF; /* 'NEVER'. */ + *(data + 5) = 0xFF; /* 'NEVER'. */ /* AC 'Self delete' */ - *(data + 6) = 0x0F; /* 'NONE' */ - entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_DELETE); + *(data + 6) = 0x0F; /* 'NONE' */ + entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_DELETE); if (entry->method == SC_AC_CHV) - *(data + 6) = (entry->key_ref << 4) | 0xF; /* 'CHVx' */ + *(data + 6) = (entry->key_ref << 4) | 0xF; /* 'CHVx' */ else if (entry->method == SC_AC_NEVER) - *(data + 6) = 0xFF; /* 'NEVER'. */ - *(data + 7)= 0xFF; + *(data + 6) = 0xFF; /* 'NEVER'. */ + *(data + 7) = 0xFF; sc_file_free(tmp_file); LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS); } - /* * Erase the card. */ static int -myeid_erase_card(struct sc_profile *profile, struct sc_pkcs15_card *p15card) -{ +myeid_erase_card(struct sc_profile *profile, struct sc_pkcs15_card *p15card) { struct sc_context *ctx = p15card->card->ctx; struct sc_cardctl_myeid_data_obj data_obj; struct sc_file *mf = NULL; @@ -141,7 +136,7 @@ myeid_erase_card(struct sc_profile *profile, struct sc_pkcs15_card *p15card) LOG_FUNC_CALLED(ctx); - r = myeid_get_init_applet_data(profile, p15card, data, sizeof(data)); + r = myeid_get_init_applet_data(profile, p15card, data, sizeof (data)); LOG_TEST_RET(ctx, r, "Get init applet date error"); /* Select parent DF and verify PINs/key as necessary */ @@ -153,48 +148,51 @@ myeid_erase_card(struct sc_profile *profile, struct sc_pkcs15_card *p15card) r = sc_pkcs15init_authenticate(profile, p15card, mf, SC_AC_OP_DELETE); LOG_TEST_RET(ctx, r, "'DELETE' authentication failed on MF"); - data_obj.P1 = 0x01; - data_obj.P2 = 0xE0; - data_obj.Data = data; - data_obj.DataLen = sizeof(data); + data_obj.P1 = 0x01; + data_obj.P2 = 0xE0; + data_obj.Data = data; + data_obj.DataLen = sizeof (data); r = sc_card_ctl(p15card->card, SC_CARDCTL_MYEID_PUTDATA, &data_obj); LOG_FUNC_RETURN(p15card->card->ctx, r); } + + static int myeid_init_card(sc_profile_t *profile, - sc_pkcs15_card_t *p15card) -{ + sc_pkcs15_card_t *p15card) { struct sc_path path; struct sc_file *file = NULL; + u8 rbuf[256]; int r; LOG_FUNC_CALLED(p15card->card->ctx); - sc_format_path("3F00", &path); - r = sc_select_file(p15card->card, &path, &file); - p15card->tokeninfo->flags = SC_PKCS15_TOKEN_PRN_GENERATION | SC_PKCS15_TOKEN_EID_COMPLIANT; + r = sc_card_ctl(p15card->card, SC_CARDCTL_GET_SERIALNR, &rbuf); + LOG_TEST_RET(p15card->card->ctx, r, "Get applet info failed"); + + sc_format_path("3F00", &path); + r = sc_select_file(p15card->card, &path, &file); + if (file) sc_file_free(file); LOG_FUNC_RETURN(p15card->card->ctx, r); } - /* * Create a DF */ static int -myeid_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df) -{ +myeid_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df) { struct sc_context *ctx = p15card->card->ctx; struct sc_file *file = NULL; - int r=0, ii; - static const char *create_dfs[] = { + int r = 0, ii; + static const char *create_dfs[] = { "PKCS15-PrKDF", "PKCS15-PuKDF", "PKCS15-CDF", @@ -204,28 +202,27 @@ myeid_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df }; static const int create_dfs_val[] = { - SC_PKCS15_PRKDF, - SC_PKCS15_PUKDF, - SC_PKCS15_CDF, - SC_PKCS15_CDF_TRUSTED, - SC_PKCS15_DODF + SC_PKCS15_PRKDF, + SC_PKCS15_PUKDF, + SC_PKCS15_CDF, + SC_PKCS15_CDF_TRUSTED, + SC_PKCS15_DODF }; if (!profile || !p15card || !df) return SC_ERROR_INVALID_ARGUMENTS; LOG_FUNC_CALLED(ctx); - sc_log(ctx, "id (%x)",df->id); + sc_log(ctx, "id (%x)", df->id); - if(df->id == 0x5015) - { - sc_log(ctx, "Select (%x)",df->id); + if (df->id == 0x5015) { + sc_log(ctx, "Select (%x)", df->id); r = sc_select_file(p15card->card, &df->path, NULL); - for (ii = 0; create_dfs[ii]; ii++) { + for (ii = 0; create_dfs[ii]; ii++) { sc_log(ctx, "Create '%s'", create_dfs[ii]); - if (sc_profile_get_file(profile, create_dfs[ii], &file)) { + if (sc_profile_get_file(profile, create_dfs[ii], &file)) { sc_log(ctx, "Inconsistent profile: cannot find %s", create_dfs[ii]); LOG_FUNC_RETURN(ctx, SC_ERROR_INCONSISTENT_PROFILE); } @@ -240,30 +237,25 @@ myeid_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df LOG_FUNC_RETURN(p15card->card->ctx, r); } - /* * Select the PIN reference */ static int myeid_select_pin_reference(sc_profile_t *profile, sc_pkcs15_card_t *p15card, - sc_pkcs15_auth_info_t *auth_info) -{ + sc_pkcs15_auth_info_t *auth_info) { SC_FUNC_CALLED(p15card->card->ctx, SC_LOG_DEBUG_VERBOSE); if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) return SC_ERROR_OBJECT_NOT_VALID; - if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) - { - sc_log(p15card->card->ctx, - "PIN_FLAG_SO_PIN, ref (%d), tries_left (%d)", - auth_info->attrs.pin.reference, auth_info->tries_left); - } - else - { - sc_log(p15card->card->ctx, - "PIN_FLAG_PIN, ref (%d), tries_left (%d)", - auth_info->attrs.pin.reference, auth_info->tries_left); + if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) { + sc_log(p15card->card->ctx, + "PIN_FLAG_SO_PIN, ref (%d), tries_left (%d)", + auth_info->attrs.pin.reference, auth_info->tries_left); + } else { + sc_log(p15card->card->ctx, + "PIN_FLAG_PIN, ref (%d), tries_left (%d)", + auth_info->attrs.pin.reference, auth_info->tries_left); } @@ -280,18 +272,17 @@ static int myeid_create_pin(struct sc_profile *profile, struct sc_pkcs15_card *p15card, struct sc_file *df, struct sc_pkcs15_object *pin_obj, const unsigned char *pin, size_t pin_len, - const unsigned char *puk, size_t puk_len) -{ + const unsigned char *puk, size_t puk_len) { struct sc_context *ctx = p15card->card->ctx; - unsigned char data[20]; + unsigned char data[20]; struct sc_cardctl_myeid_data_obj data_obj; - struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data; - struct sc_pkcs15_auth_info puk_ainfo; - int r; + struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *) pin_obj->data; + struct sc_pkcs15_auth_info puk_ainfo; + int r; LOG_FUNC_CALLED(ctx); sc_log(ctx, "PIN('%s',ref:%i,flags:0x%X,pin_len:%d,puk_len:%d)\n", - pin_obj->label, auth_info->attrs.pin.reference, auth_info->attrs.pin.flags, pin_len, puk_len); + pin_obj->label, auth_info->attrs.pin.reference, auth_info->attrs.pin.flags, pin_len, puk_len); if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) return SC_ERROR_OBJECT_NOT_VALID; @@ -304,30 +295,30 @@ myeid_create_pin(struct sc_profile *profile, struct sc_pkcs15_card *p15card, ? SC_PKCS15INIT_SO_PUK : SC_PKCS15INIT_USER_PUK, &puk_ainfo); - memset(data, 0, sizeof(data)); + memset(data, 0, sizeof (data)); /* Make command to add a pin-record */ data_obj.P1 = 0x01; - data_obj.P2 = auth_info->attrs.pin.reference; /* myeid pin number */ + data_obj.P2 = auth_info->attrs.pin.reference; /* myeid pin number */ memset(data, auth_info->attrs.pin.pad_char, 8); - memcpy(&data[0], (u8 *)pin, pin_len); /* copy pin */ + memcpy(&data[0], (u8 *) pin, pin_len); /* copy pin */ memset(&data[8], puk_ainfo.attrs.pin.pad_char, 8); - memcpy(&data[8], (u8 *)puk, puk_len); /* copy puk */ + memcpy(&data[8], (u8 *) puk, puk_len); /* copy puk */ - if(auth_info->tries_left > 0 && auth_info->tries_left < 15) + if (auth_info->tries_left > 0 && auth_info->tries_left < 15) data[16] = auth_info->tries_left; else - data[16] = 5; /* default value */ + data[16] = 5; /* default value */ - if(puk_ainfo.tries_left > 0 && puk_ainfo.tries_left < 15) + if (puk_ainfo.tries_left > 0 && puk_ainfo.tries_left < 15) data[17] = puk_ainfo.tries_left; else - data[17] = 5; /* default value */ + data[17] = 5; /* default value */ data[18] = 0x00; - data_obj.Data = data; + data_obj.Data = data; data_obj.DataLen = 19; r = sc_card_ctl(p15card->card, SC_CARDCTL_MYEID_PUTDATA, &data_obj); @@ -336,7 +327,6 @@ myeid_create_pin(struct sc_profile *profile, struct sc_pkcs15_card *p15card, LOG_FUNC_RETURN(ctx, r); } - /* * Setup file struct & path: get correct template from the profile, construct full path * num = number of objects of this type already on the card @@ -344,8 +334,7 @@ myeid_create_pin(struct sc_profile *profile, struct sc_pkcs15_card *p15card, static int myeid_new_file(sc_profile_t *profile, sc_card_t *card, unsigned int type, unsigned int num, - sc_file_t **out) -{ + sc_file_t **out) { sc_file_t *file; sc_path_t *p; char name[64]; @@ -353,24 +342,22 @@ myeid_new_file(sc_profile_t *profile, sc_card_t *card, int r; LOG_FUNC_CALLED(card->ctx); - if (type == SC_PKCS15_TYPE_PRKEY_RSA) + if (type == SC_PKCS15_TYPE_PRKEY_RSA || type == SC_PKCS15_TYPE_PRKEY_EC) tag = "private-key"; - else if (type == SC_PKCS15_TYPE_PUBKEY_RSA) + else if (type == SC_PKCS15_TYPE_PUBKEY_RSA || type == SC_PKCS15_TYPE_PUBKEY_EC) tag = "public-key"; else if ((type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_CERT) tag = "certificate"; else if ((type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_DATA_OBJECT) tag = "data"; - else - { + else { sc_log(card->ctx, "Unsupported file type"); return SC_ERROR_INVALID_ARGUMENTS; } /* Get template from profile */ - snprintf(name, sizeof(name), "template-%s", tag); - if (sc_profile_get_file(profile, name, &file) < 0) - { + snprintf(name, sizeof (name), "template-%s", tag); + if (sc_profile_get_file(profile, name, &file) < 0) { sc_log(card->ctx, "Profile doesn't define %s", name); return SC_ERROR_NOT_SUPPORTED; } @@ -384,8 +371,7 @@ myeid_new_file(sc_profile_t *profile, sc_card_t *card, /* Increment FID until there's no file with such path */ r = sc_select_file(card, p, NULL); - while(r == 0) - { + while (r == 0) { file->id++; p->value[p->len - 2] = (u8) (file->id / 256); p->value[p->len - 1] = (u8) (file->id % 256); @@ -396,12 +382,10 @@ myeid_new_file(sc_profile_t *profile, sc_card_t *card, LOG_FUNC_RETURN(card->ctx, 0); } - static int myeid_encode_private_key(sc_profile_t *profile, sc_card_t *card, struct sc_pkcs15_prkey_rsa *rsa, u8 *key, - size_t *keysize, int key_ref) -{ + size_t *keysize, int key_ref) { LOG_FUNC_CALLED(card->ctx); LOG_FUNC_RETURN(card->ctx, 0); } @@ -409,159 +393,62 @@ myeid_encode_private_key(sc_profile_t *profile, sc_card_t *card, static int myeid_encode_public_key(sc_profile_t *profile, sc_card_t *card, struct sc_pkcs15_prkey_rsa *rsa, u8 *key, - size_t *keysize, int key_ref) -{ + size_t *keysize, int key_ref) { LOG_FUNC_CALLED(card->ctx); LOG_FUNC_RETURN(card->ctx, 0); } -#if 0 -/* - * Generate RSA key - */ -static int myeid_generate_key(sc_profile_t *profile, sc_card_t *card, - unsigned int index, /* keyref: 0 for 1st key, ... */ - unsigned int keybits, - sc_pkcs15_pubkey_t *pubkey, - struct sc_pkcs15_prkey_info *info) -{ - return myeid_generate_store_key(profile, card, index, keybits, - pubkey, NULL, info); -} - -/* - * Store RSA key - */ -static int myeid_new_key(sc_profile_t *profile, sc_card_t *card, - struct sc_pkcs15_prkey *key, unsigned int index, - struct sc_pkcs15_prkey_info *info) -{ - return myeid_generate_store_key(profile, card, index, - key->u.rsa.modulus.len * 8, NULL, key, info); -} - -/* - * Common code for generating or storing a private key. - * If pubkey == NULL and prkey != NULL, we have to store a private key - * In the oposite case, we have to generate a private key - */ -static int myeid_generate_store_key(sc_profile_t *profile, sc_card_t *card, - unsigned int index, /* keynumber: 0 for 1st priv key, ... */ - unsigned int keybits, - sc_pkcs15_pubkey_t *pubkey, - sc_pkcs15_prkey_t *prkey, - sc_pkcs15_prkey_info_t *info) -{ - struct sc_cardctl_myeid_gen_store_key_info args; - int r; - sc_file_t *prkf = NULL; - - LOG_FUNC_CALLED(card->ctx); - /* Parameter check */ - if ( (keybits < 1024) || (keybits > 2048) || (keybits & 0X7)) { - sc_log(card->ctx, - "Unsupported key size [%u]: 1024-2048 bit + 8-multiple\n", keybits); - return SC_ERROR_INVALID_ARGUMENTS; - } - - /* Get the private key file */ - r = myeid_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, index, &prkf); - if (r < 0) - goto done; - - /* Take enough room for a 1024 bit key */ - if (prkf->size < 1024) - prkf->size = 1024; - - /* Now create the key file */ - r = sc_pkcs15init_create_file(profile, card, prkf); - if (r < 0) - goto done; - - /* Fill in data structure */ - memset(&args, 0, sizeof(args)); - args.mod_len = keybits; - if (prkey == NULL) - { - args.op_type = OP_TYPE_GENERATE; - args.pubexp_len = MYEID_DEFAULT_PUBKEY_LEN; - args.pubexp = MYEID_DEFAULT_PUBKEY; - } - else - { - args.op_type = OP_TYPE_STORE; - args.pubexp_len = prkey->u.rsa.exponent.len; - args.pubexp = prkey->u.rsa.exponent.data; - args.primep_len = prkey->u.rsa.p.len; - args.primep = prkey->u.rsa.p.data; - args.primeq_len = prkey->u.rsa.q.len; - args.primeq = prkey->u.rsa.q.data; - - args.dp1_len = prkey->u.rsa.dmp1.len; - args.dp1 = prkey->u.rsa.dmp1.data; - args.dq1_len = prkey->u.rsa.dmq1.len; - args.dq1 = prkey->u.rsa.dmq1.data; - args.invq_len = prkey->u.rsa.iqmp.len; - args.invq = prkey->u.rsa.iqmp.data; - - args.mod_len = prkey->u.rsa.modulus.len; - args.mod = prkey->u.rsa.modulus.data; - } - - /* Authenticate */ - r = sc_pkcs15init_authenticate(profile, card, prkf, SC_AC_OP_UPDATE); - if (r < 0) - goto done; - - /* Generate/store rsa key */ - r = sc_card_ctl(card, SC_CARDCTL_MYEID_GENERATE_KEY, &args); - if (r < 0) - goto done; - - info->key_reference = 0; - info->path = prkf->path; - -done: - if (prkf) - sc_file_free(prkf); - - LOG_FUNC_RETURN(card->ctx, r); -} - -#endif - /* * Store a private key */ static int myeid_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, - struct sc_pkcs15_object *object) -{ + struct sc_pkcs15_object *object) { struct sc_context *ctx = p15card->card->ctx; struct sc_card *card = p15card->card; - struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data; + struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data; struct sc_file *file = NULL; int keybits = key_info->modulus_length, r; LOG_FUNC_CALLED(card->ctx); - /* Check that the card supports the requested modulus length */ - if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL) - LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key size"); - sc_log(ctx, "create MyEID private key ID:%s", sc_pkcs15_print_id(&key_info->id)); + /* Check that the card supports the requested modulus length */ + switch (object->type) { + case SC_PKCS15_TYPE_PRKEY_RSA: + if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL) + LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, + "Unsupported RSA key size"); + break; + case SC_PKCS15_TYPE_PRKEY_EC: + if (sc_card_find_ec_alg(p15card->card, keybits) == NULL) + LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, + "Unsupported EC key size"); + break; + default: + LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, + "Unsupported key type"); + break; + } + + sc_log(ctx, "create MyEID private key ID:%s", sc_pkcs15_print_id(&key_info->id)); /* Get the private key file */ - r = myeid_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, key_info->key_reference, &file); + r = myeid_new_file(profile, card, object->type, key_info->key_reference, &file); LOG_TEST_RET(ctx, r, "Cannot get new MyEID private key file"); sc_log(ctx, "Key file size %d", keybits); file->size = keybits; + if (object->type == SC_PKCS15_TYPE_PRKEY_RSA) + file->ef_structure = SC_CARDCTL_MYEID_KEY_RSA; + else if (object->type == SC_PKCS15_TYPE_PRKEY_EC) + file->ef_structure = SC_CARDCTL_MYEID_KEY_EC; + memcpy(&key_info->path.value, &file->path.value, file->path.len); key_info->key_reference = file->path.value[file->path.len - 1] & 0xFF; - sc_log(ctx, "Path of MyEID private key file to create %s", + sc_log(ctx, "Path of MyEID private key file to create %s", sc_print_path(&file->path)); /* Now create the key file */ @@ -572,30 +459,41 @@ myeid_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, LOG_FUNC_RETURN(ctx, r); } - /* * Store a private key */ static int myeid_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object, - struct sc_pkcs15_prkey *prkey) -{ + struct sc_pkcs15_prkey *prkey) { struct sc_context *ctx = p15card->card->ctx; struct sc_card *card = p15card->card; - struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data; + struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data; struct sc_cardctl_myeid_gen_store_key_info args; struct sc_file *file = NULL; int r, keybits = key_info->modulus_length; LOG_FUNC_CALLED(ctx); - if (object->type != SC_PKCS15_TYPE_PRKEY_RSA) - LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Store key failed: RSA only supported"); - - /* Check that the card supports the requested modulus length */ - if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL) - LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key size"); - + + switch (object->type) { + case SC_PKCS15_TYPE_PRKEY_RSA: + if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL) + LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported RSA key size"); + break; + case SC_PKCS15_TYPE_PRKEY_EC: + if (sc_card_find_ec_alg(p15card->card, keybits) == NULL) + LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported EC key size"); + if(key_info->field_length != 0) + keybits = key_info->field_length; + else + key_info->field_length = keybits; + + break; + default: + LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Store key failed: Unsupported key type"); + break; + } + sc_log(ctx, "store MyEID key with ID:%s and path:%s", sc_pkcs15_print_id(&key_info->id), sc_print_path(&key_info->path)); @@ -609,26 +507,37 @@ myeid_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, sc_file_free(file); /* Fill in data structure */ - memset(&args, 0, sizeof(args)); - args.mod_len = keybits; - args.op_type = OP_TYPE_STORE; - args.pubexp_len = prkey->u.rsa.exponent.len; - args.pubexp = prkey->u.rsa.exponent.data; - args.primep_len = prkey->u.rsa.p.len; - args.primep = prkey->u.rsa.p.data; - args.primeq_len = prkey->u.rsa.q.len; - args.primeq = prkey->u.rsa.q.data; + memset(&args, 0, sizeof (args)); - args.dp1_len = prkey->u.rsa.dmp1.len; - args.dp1 = prkey->u.rsa.dmp1.data; - args.dq1_len = prkey->u.rsa.dmq1.len; - args.dq1 = prkey->u.rsa.dmq1.data; - args.invq_len = prkey->u.rsa.iqmp.len; - args.invq = prkey->u.rsa.iqmp.data; + args.op_type = OP_TYPE_STORE; + if(object->type == SC_PKCS15_TYPE_PRKEY_RSA) { + //args.key_len_bits = keybits; + args.key_type = SC_CARDCTL_MYEID_KEY_RSA; + args.pubexp_len = prkey->u.rsa.exponent.len; + args.pubexp = prkey->u.rsa.exponent.data; + args.primep_len = prkey->u.rsa.p.len; + args.primep = prkey->u.rsa.p.data; + args.primeq_len = prkey->u.rsa.q.len; + args.primeq = prkey->u.rsa.q.data; - args.mod_len = prkey->u.rsa.modulus.len; - args.mod = prkey->u.rsa.modulus.data; + args.dp1_len = prkey->u.rsa.dmp1.len; + args.dp1 = prkey->u.rsa.dmp1.data; + args.dq1_len = prkey->u.rsa.dmq1.len; + args.dq1 = prkey->u.rsa.dmq1.data; + args.invq_len = prkey->u.rsa.iqmp.len; + args.invq = prkey->u.rsa.iqmp.data; + args.key_len_bits = prkey->u.rsa.modulus.len; + args.mod = prkey->u.rsa.modulus.data; + } + else { + args.key_type = SC_CARDCTL_MYEID_KEY_EC; + args.d = prkey->u.ec.privateD.data; + args.d_len = prkey->u.ec.privateD.len; + args.ecpublic_point = prkey->u.ec.ecpointQ.value; + args.ecpublic_point_len = prkey->u.ec.ecpointQ.len; + args.key_len_bits = prkey->u.ec.params.field_length; + } /* Store RSA key */ r = sc_card_ctl(card, SC_CARDCTL_MYEID_GENERATE_STORE_KEY, &args); LOG_TEST_RET(ctx, r, "Card control 'MYEID_GENERATE_STORE_KEY' failed"); @@ -636,15 +545,13 @@ myeid_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, LOG_FUNC_RETURN(ctx, r); } - static int myeid_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object, - struct sc_pkcs15_pubkey *pubkey) -{ + struct sc_pkcs15_pubkey *pubkey) { struct sc_context *ctx = p15card->card->ctx; struct sc_card *card = p15card->card; - struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data; + struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data; struct sc_cardctl_myeid_gen_store_key_info args; struct sc_file *file = NULL; int r; @@ -652,61 +559,107 @@ myeid_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, unsigned char raw_pubkey[256]; LOG_FUNC_CALLED(ctx); - if (object->type != SC_PKCS15_TYPE_PRKEY_RSA) - LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Store key failed: RSA only supported"); + if (object->type != SC_PKCS15_TYPE_PRKEY_RSA && object->type != SC_PKCS15_TYPE_PRKEY_EC) + LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Generate key failed: only RSA and EC supported"); /* Check that the card supports the requested modulus length */ - if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL) - LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key size"); + switch (object->type) { + case SC_PKCS15_TYPE_PRKEY_RSA: + if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL) + LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported RSA key size"); + break; + case SC_PKCS15_TYPE_PRKEY_EC: + if (sc_card_find_ec_alg(p15card->card, keybits) == NULL) + LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported EC key size"); + if(key_info->field_length != 0) + keybits = key_info->field_length; + else + key_info->field_length = keybits; + + break; + default: + LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key type"); + break; + } - sc_log(ctx, "store MyEID key with ID:%s and path:%s", + sc_log(ctx, "Generate key with ID:%s and path:%s", sc_pkcs15_print_id(&key_info->id), sc_print_path(&key_info->path)); r = sc_select_file(card, &key_info->path, &file); - LOG_TEST_RET(ctx, r, "Cannot store MyEID key: select key file failed"); + LOG_TEST_RET(ctx, r, "Cannot generate key: failed to select key file"); r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_GENERATE); - LOG_TEST_RET(ctx, r, "No authorisation to generate MyEID private key"); + LOG_TEST_RET(ctx, r, "No authorisation to generate private key"); /* Fill in data structure */ - memset(&args, 0, sizeof(args)); - args.mod_len = keybits; - args.op_type = OP_TYPE_GENERATE; - args.pubexp_len = MYEID_DEFAULT_PUBKEY_LEN; - args.pubexp = MYEID_DEFAULT_PUBKEY; + memset(&args, 0, sizeof (args)); + args.key_len_bits = keybits; + args.op_type = OP_TYPE_GENERATE; + if (object->type == SC_PKCS15_TYPE_PRKEY_RSA) { + args.key_type = SC_CARDCTL_MYEID_KEY_RSA; + args.pubexp_len = MYEID_DEFAULT_PUBKEY_LEN; + args.pubexp = MYEID_DEFAULT_PUBKEY; + } else if (object->type == SC_PKCS15_TYPE_PRKEY_EC) { + args.key_type = SC_CARDCTL_MYEID_KEY_EC; + } /* Generate RSA key */ r = sc_card_ctl(card, SC_CARDCTL_MYEID_GENERATE_STORE_KEY, &args); LOG_TEST_RET(ctx, r, "Card control 'MYEID_GENERATE_STORE_KEY' failed"); /* Keypair generation -> collect public key info */ - /* FIXME: was not preset in original Aventra version. Need to be tested. (VT) */ - if (pubkey != NULL) { + if (pubkey != NULL) { struct sc_cardctl_myeid_data_obj data_obj; - pubkey->algorithm = SC_ALGORITHM_RSA; - pubkey->u.rsa.modulus.len = (keybits + 7) / 8; - pubkey->u.rsa.modulus.data = malloc(pubkey->u.rsa.modulus.len); - pubkey->u.rsa.exponent.len = MYEID_DEFAULT_PUBKEY_LEN; - pubkey->u.rsa.exponent.data = malloc(MYEID_DEFAULT_PUBKEY_LEN); - memcpy(pubkey->u.rsa.exponent.data, MYEID_DEFAULT_PUBKEY, MYEID_DEFAULT_PUBKEY_LEN); + if (object->type == SC_PKCS15_TYPE_PRKEY_RSA) { + pubkey->algorithm = SC_ALGORITHM_RSA; + pubkey->u.rsa.modulus.len = (keybits + 7) / 8; + pubkey->u.rsa.modulus.data = malloc(pubkey->u.rsa.modulus.len); + pubkey->u.rsa.exponent.len = MYEID_DEFAULT_PUBKEY_LEN; + pubkey->u.rsa.exponent.data = malloc(MYEID_DEFAULT_PUBKEY_LEN); + memcpy(pubkey->u.rsa.exponent.data, MYEID_DEFAULT_PUBKEY, MYEID_DEFAULT_PUBKEY_LEN); - /* Get public key modulus */ - r = sc_select_file(card, &file->path, NULL); - LOG_TEST_RET(ctx, r, "Cannot get key modulus: select key file failed"); + /* Get public key modulus */ + r = sc_select_file(card, &file->path, NULL); + LOG_TEST_RET(ctx, r, "Cannot get key modulus: select key file failed"); - data_obj.P1 = 0x01; - data_obj.P2 = 0x01; - data_obj.Data = raw_pubkey; - data_obj.DataLen = sizeof(raw_pubkey); + data_obj.P1 = 0x01; + data_obj.P2 = 0x01; + data_obj.Data = raw_pubkey; + data_obj.DataLen = sizeof (raw_pubkey); - r = sc_card_ctl(card, SC_CARDCTL_MYEID_GETDATA, &data_obj); - LOG_TEST_RET(ctx, r, "Cannot get key modulus: 'MYEID_GETDATA' failed"); + r = sc_card_ctl(card, SC_CARDCTL_MYEID_GETDATA, &data_obj); + LOG_TEST_RET(ctx, r, "Cannot get RSA key modulus: 'MYEID_GETDATA' failed"); - if ((data_obj.DataLen * 8) != key_info->modulus_length) - LOG_TEST_RET(ctx, SC_ERROR_PKCS15INIT, "Cannot get key modulus: invalid key-size"); + if ((data_obj.DataLen * 8) != key_info->modulus_length) + LOG_TEST_RET(ctx, SC_ERROR_PKCS15INIT, "Cannot get RSA key modulus: invalid key-size"); - memcpy (pubkey->u.rsa.modulus.data, raw_pubkey, pubkey->u.rsa.modulus.len); + memcpy(pubkey->u.rsa.modulus.data, raw_pubkey, pubkey->u.rsa.modulus.len); + } + else if (object->type == SC_PKCS15_TYPE_PRKEY_EC) { + + pubkey->algorithm = SC_ALGORITHM_EC; + + r = sc_select_file(card, &file->path, NULL); + LOG_TEST_RET(ctx, r, "Cannot get public key: select key file failed"); + + data_obj.P1 = 0x01; + data_obj.P2 = 0x86; /* Get public EC key (Q) */ + data_obj.Data = raw_pubkey; + data_obj.DataLen = sizeof (raw_pubkey); + + r = sc_card_ctl(card, SC_CARDCTL_MYEID_GETDATA, &data_obj); + LOG_TEST_RET(ctx, r, "Cannot get EC public key: 'MYEID_GETDATA' failed"); + + pubkey->u.ec.ecpointQ.value = malloc(data_obj.DataLen - 2); + pubkey->u.ec.ecpointQ.len = data_obj.DataLen - 2; + pubkey->data.value = malloc(data_obj.DataLen); + pubkey->data.len = data_obj.DataLen; + pubkey->u.ec.params.field_length = keybits; + /* Omit the first 2 bytes (0x86??) */ + memcpy(pubkey->u.ec.ecpointQ.value, data_obj.Data + 2, data_obj.DataLen - 2); + memcpy(pubkey->data.value, data_obj.Data, data_obj.DataLen); + } } if (file) @@ -716,8 +669,7 @@ myeid_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, } /* Finish initialization. After this ACL is in affect */ -static int myeid_finalize_card(sc_card_t *card) -{ +static int myeid_finalize_card(sc_card_t *card) { LOG_FUNC_CALLED(card->ctx); LOG_FUNC_RETURN(card->ctx, sc_card_ctl(card, SC_CARDCTL_MYEID_ACTIVATE_CARD, NULL)); } @@ -728,24 +680,23 @@ static int myeid_finalize_card(sc_card_t *card) */ static struct sc_pkcs15init_operations sc_pkcs15init_myeid_operations = { myeid_erase_card, - myeid_init_card, /* init_card */ - myeid_create_dir, /* create_dir */ - NULL, /* create_domain */ + myeid_init_card, /* init_card */ + myeid_create_dir, /* create_dir */ + NULL, /* create_domain */ myeid_select_pin_reference, myeid_create_pin, - NULL, /* select_key_reference */ + NULL, /* select_key_reference */ myeid_create_key, myeid_store_key, myeid_generate_key, myeid_encode_private_key, myeid_encode_public_key, myeid_finalize_card, - myeid_delete_object, /* delete_object */ - NULL, NULL, NULL, NULL, NULL, /* pkcs15init emulation */ - NULL /* sanity_check */ + myeid_delete_object, /* delete_object */ + NULL, NULL, NULL, NULL, NULL, /* pkcs15init emulation */ + NULL /* sanity_check */ }; -struct sc_pkcs15init_operations *sc_pkcs15init_get_myeid_ops(void) -{ +struct sc_pkcs15init_operations *sc_pkcs15init_get_myeid_ops(void) { return &sc_pkcs15init_myeid_operations; } diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index b10b93cc..808a9473 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -61,9 +61,15 @@ static struct ec_curve_info { const char *oid_encoded; size_t size; } ec_curve_infos[] = { - {"prime192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, - {"prime256v1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, - {"secp384r1", "1.3.132.0.34", "06052B81040022", 384}, + {"secp192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, + {"prime192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, + {"ansiX9p192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, + {"prime256v1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, + {"secp256r1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, + {"ansiX9p256r1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, + {"secp384r1", "1.3.132.0.34", "06052B81040022", 384}, + {"prime384v1", "1.3.132.0.34", "06052B81040022", 384}, + {"ansiX9p384r1", "1.3.132.0.34", "06052B81040022", 384}, {"brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3", "06092B2403030208010103", 192}, {"brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5", "06092B2403030208010105", 224}, {"brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7", "06092B2403030208010107", 256}, @@ -4231,9 +4237,9 @@ static void test_kpgen_certwrite(CK_SLOT_ID slot, CK_SESSION_HANDLE session) data = md5_and_digestinfo; data_len = 20; rv = p11->C_SignInit(session, &mech, priv_key); + rv = p11->C_Sign(session, data, data_len, sig, &sig_len); if (rv != CKR_OK) p11_fatal("C_SignInit", rv); - rv = p11->C_Sign(session, data, data_len, sig, &sig_len); if (rv != CKR_OK) p11_fatal("C_Sign", rv);