From be35d3d026634ad7eaacf898c2935b3558ac612e Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Fri, 27 Oct 2017 20:51:33 +0300 Subject: [PATCH] EstEID ECDSA token support (#1158) --- src/libopensc/card-mcrd.c | 10 +++++--- src/libopensc/pkcs15-esteid.c | 47 ++++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/libopensc/card-mcrd.c b/src/libopensc/card-mcrd.c index cbba3fdf..28f8abfa 100644 --- a/src/libopensc/card-mcrd.c +++ b/src/libopensc/card-mcrd.c @@ -304,7 +304,7 @@ static int mcrd_match_card(sc_card_t * card) static int mcrd_init(sc_card_t * card) { - unsigned long flags; + unsigned long flags, ext_flags; struct mcrd_priv_data *priv; int r; sc_path_t tmppath; @@ -329,6 +329,10 @@ static int mcrd_init(sc_card_t * card) flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_HASH_SHA1 | SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA256; /* EstEID v3.0 has 2048 bit keys */ _sc_card_add_rsa_alg(card, 2048, flags, 0); + + flags = SC_ALGORITHM_ECDSA_RAW | SC_ALGORITHM_ECDH_CDH_RAW | SC_ALGORITHM_ECDSA_HASH_NONE; + ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES; + _sc_card_add_ec_alg(card, 384, flags, ext_flags, NULL); sc_reset(card, 0); sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xA4, 0x04, 0x00); @@ -1188,7 +1192,7 @@ static int mcrd_set_security_env(sc_card_t * card, if (is_esteid_card(card)) { /* some sanity checks */ if (env->flags & SC_SEC_ENV_ALG_PRESENT) { - if (env->algorithm != SC_ALGORITHM_RSA) + if (env->algorithm != SC_ALGORITHM_RSA && env->algorithm != SC_ALGORITHM_EC) return SC_ERROR_INVALID_ARGUMENTS; } if (!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT) @@ -1375,7 +1379,7 @@ static int mcrd_compute_signature(sc_card_t * card, apdu.lc = datalen; apdu.data = data; apdu.datalen = datalen; - apdu.le = 0x80; + apdu.le = MIN(0x80u, outlen); apdu.resp = out; apdu.resplen = outlen; diff --git a/src/libopensc/pkcs15-esteid.c b/src/libopensc/pkcs15-esteid.c index 361b2525..a4655b7f 100644 --- a/src/libopensc/pkcs15-esteid.c +++ b/src/libopensc/pkcs15-esteid.c @@ -33,6 +33,7 @@ #include "common/compat_strlcat.h" #include "internal.h" +#include "opensc.h" #include "pkcs15.h" #include "esteid.h" @@ -64,6 +65,7 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card) sc_card_t *card = p15card->card; unsigned char buff[128]; int r, i; + size_t field_length = 0, modulus_length = 0; sc_path_t tmppath; set_string (&p15card->tokeninfo->label, "ID-kaart"); @@ -74,7 +76,7 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card) r = sc_select_file (card, &tmppath, NULL); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "select esteid PD failed"); - /* read the serial (document number) */ + /* read the serial (document number) */ r = sc_read_record (card, SC_ESTEID_PD_DOCUMENT_NR, buff, sizeof(buff), SC_RECORD_BY_REC_NR); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "read document number failed"); buff[r] = '\0'; @@ -93,10 +95,10 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card) "3f00eeeeaace", "3f00eeeeddce"}; static int esteid_cert_ids[2] = {1, 2}; - + struct sc_pkcs15_cert_info cert_info; struct sc_pkcs15_object cert_obj; - + memset(&cert_info, 0, sizeof(cert_info)); memset(&cert_obj, 0, sizeof(cert_obj)); @@ -110,6 +112,10 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card) if (i == 0) { sc_pkcs15_cert_t *cert; r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert); + if (cert->key->algorithm == SC_ALGORITHM_EC) + field_length = cert->key->u.ec.params.field_length; + else + modulus_length = cert->key->u.rsa.modulus.len * 8; if (r == SC_SUCCESS) { static const struct sc_object_id cn_oid = {{ 2, 5, 4, 3, -1 }}; u8 *cn_name = NULL; @@ -155,16 +161,16 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card) memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); - + /* read the number of tries left for the PIN */ r = sc_read_record (card, i + 1, buff, sizeof(buff), SC_RECORD_BY_REC_NR); if (r < 0) return SC_ERROR_INTERNAL; tries_left = buff[5]; - + pin_info.auth_id.len = 1; pin_info.auth_id.value[0] = esteid_pin_authid[i]; - pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; + pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; pin_info.attrs.pin.reference = esteid_pin_ref[i]; pin_info.attrs.pin.flags = esteid_pin_flags[i]; pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; @@ -188,16 +194,11 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card) if (r < 0) return SC_ERROR_INTERNAL; } - + /* add private keys */ for (i = 0; i < 2; i++) { static int prkey_pin[2] = {1, 2}; - static int prkey_usage[2] = { - SC_PKCS15_PRKEY_USAGE_ENCRYPT - | SC_PKCS15_PRKEY_USAGE_DECRYPT - | SC_PKCS15_PRKEY_USAGE_SIGN, - SC_PKCS15_PRKEY_USAGE_NONREPUDIATION}; - + static const char *prkey_name[2] = { "Isikutuvastus", "Allkirjastamine"}; @@ -207,16 +208,19 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card) memset(&prkey_info, 0, sizeof(prkey_info)); memset(&prkey_obj, 0, sizeof(prkey_obj)); - + prkey_info.id.len = 1; prkey_info.id.value[0] = prkey_pin[i]; - prkey_info.usage = prkey_usage[i]; prkey_info.native = 1; prkey_info.key_reference = i + 1; - if (card->type == SC_CARD_TYPE_MCRD_ESTEID_V30) - prkey_info.modulus_length = 2048; + prkey_info.field_length = field_length; + prkey_info.modulus_length = modulus_length; + if (i == 1) + prkey_info.usage = SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; + else if(field_length > 0) // ECC has only sign usage + prkey_info.usage = SC_PKCS15_PRKEY_USAGE_SIGN; else - prkey_info.modulus_length = 1024; + prkey_info.usage = SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT; strlcpy(prkey_obj.label, prkey_name[i], sizeof(prkey_obj.label)); prkey_obj.auth_id.len = 1; @@ -224,7 +228,10 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card) prkey_obj.user_consent = 0; prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; - r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); + if(field_length > 0) + r = sc_pkcs15emu_add_ec_prkey(p15card, &prkey_obj, &prkey_info); + else + r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); if (r < 0) return SC_ERROR_INTERNAL; } @@ -236,7 +243,7 @@ static int esteid_detect_card(sc_pkcs15_card_t *p15card) { if (is_esteid_card(p15card->card)) return SC_SUCCESS; - else + else return SC_ERROR_WRONG_CARD; }