diff --git a/src/libopensc/internal.h b/src/libopensc/internal.h index 7e0e874d..3852e4c9 100644 --- a/src/libopensc/internal.h +++ b/src/libopensc/internal.h @@ -110,6 +110,8 @@ int _sc_match_atr(struct sc_card *card, struct sc_atr_table *table, int *type_ou int _sc_card_add_algorithm(struct sc_card *card, const struct sc_algorithm_info *info); int _sc_card_add_rsa_alg(struct sc_card *card, unsigned int key_length, unsigned long flags, unsigned long exponent); +int _sc_card_add_ec_alg(struct sc_card *card, unsigned int key_length, + unsigned long flags, unsigned long ext_flags); int sc_asn1_read_tag(const u8 ** buf, size_t buflen, unsigned int *cla_out, unsigned int *tag_out, size_t *taglen); diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 42791915..e990a4a9 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -78,7 +78,7 @@ extern "C" { #define SC_ALGORITHM_ONBOARD_KEY_GEN 0x80000000 /* need usage = either sign or decrypt. keys with both? decrypt, emulate sign */ #define SC_ALGORITHM_NEED_USAGE 0x40000000 -#define SC_ALGORITHM_SPECIFIC_FLAGS 0x0000FFFF +#define SC_ALGORITHM_SPECIFIC_FLAGS 0x0001FFFF #define SC_ALGORITHM_RSA_RAW 0x00000001 /* If the card is willing to produce a cryptogram padded with the following @@ -106,6 +106,36 @@ extern "C" { #define SC_ALGORITHM_GOSTR3410_HASH_NONE 0x00004000 #define SC_ALGORITHM_GOSTR3410_HASH_GOSTR3411 0x00008000 #define SC_ALGORITHM_GOSTR3410_HASHES 0x00008000 +/*TODO: -DEE Should the above be 0x0000E000 */ +/* Or should the HASH_NONE be 0x00000010 and HASHES be 0x00008010 */ + +/* May need more bits if card can do more hashes */ +/* TODO: -DEE Will overload RSA_HASHES with EC_HASHES */ +/* Not clear if these need their own bits or not */ +/* The PIV card does not support and hashes */ +#define SC_ALGORITHM_ECDSA_RAW 0x00010000 +#define SC_ALGORITHM_ECDSA_HASH_NONE SC_ALGORITHM_RSA_HASH_NONE +#define SC_ALGORITHM_ECDSA_HASH_SHA1 SC_ALGORITHM_RSA_HASH_SHA1 +#define SC_ALGORITHM_ECDSA_HASH_SHA224 SC_ALGORITHM_RSA_HASH_SHA224 +#define SC_ALGORITHM_ECDSA_HASH_SHA256 SC_ALGORITHM_RSA_HASH_SHA256 +#define SC_ALGORITHM_ECDSA_HASH_SHA384 SC_ALGORITHM_RSA_HASH_SHA384 +#define SC_ALGORITHM_ECDSA_HASH_SHA512 SC_ALGORITHM_RSA_HASH_SHA512 +#define SC_ALGORITHM_ECDSA_HASHES (SC_ALGORITHM_ECDSA_HASH_SHA1 | \ + SC_ALGORITHM_ECDSA_HASH_SHA224 | \ + SC_ALGORITHM_ECDSA_HASH_SHA256 | \ + SC_ALGORITHM_ECDSA_HASH_SHA384 | \ + SC_ALGORITHM_ECDSA_HASH_SHA512) + +/* define mask of all algorithms that can do raw */ +#define SC_ALGORITHM_RAW_MASK (SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_GOSTR3410_RAW | SC_ALGORITHM_ECDSA_RAW) + +/* extened algorithm bits for selected mechs */ +#define SC_ALGORITHM_EXT_EC_F_P 0x00000001 +#define SC_ALGORITHM_EXT_EC_F_2M 0x00000002 +#define SC_ALGORITHM_EXT_EC_ECPARAMETERS 0x00000004 +#define SC_ALGORITHM_EXT_EC_NAMEDCURVE 0x00000008 +#define SC_ALGORITHM_EXT_EC_UNCOMPRESES 0x00000010 +#define SC_ALGORITHM_EXT_EC_COMPRESS 0x00000020 /* Event masks for sc_wait_for_event() */ #define SC_EVENT_CARD_INSERTED 0x0001 @@ -155,6 +185,12 @@ struct sc_pbes2_params { struct sc_algorithm_id key_encr_alg; }; +struct sc_ec_params { + int type; + u8 * der; + size_t der_len; +}; + typedef struct sc_algorithm_info { unsigned int algorithm; unsigned int key_length; @@ -164,6 +200,9 @@ typedef struct sc_algorithm_info { struct sc_rsa_info { unsigned long exponent; } _rsa; + struct sc_ec_info { + unsigned ext_flags; + } _ec; } u; } sc_algorithm_info_t; @@ -1068,6 +1107,8 @@ int sc_update_dir(sc_card_t *card, sc_app_info_t *app); struct sc_algorithm_info * sc_card_find_rsa_alg(sc_card_t *card, unsigned int key_length); +struct sc_algorithm_info * sc_card_find_ec_alg(sc_card_t *card, + unsigned int field_length); struct sc_card_error { diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index a7ce0f99..e5baab4c 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -89,6 +89,7 @@ static const struct sc_asn1_entry c_asn1_pubkey_choice[] = { { "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, 3 | 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 } }; @@ -287,6 +288,7 @@ int sc_pkcs15_encode_pukdf_entry(sc_context_t *ctx, } break; default: + /* TODO: -DEE Should add ECC but dont have PKCS15 card with ECC */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unsupported public key type: %X\n", obj->type); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INTERNAL); break; @@ -336,6 +338,11 @@ static struct sc_asn1_entry c_asn1_gostr3410_pub_coefficients[2] = { { NULL, 0, 0, 0, NULL, NULL } }; +static struct sc_asn1_entry c_asn1_ec_pointQ[2] = { + { "ecpointQ", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_ALLOC, NULL, NULL }, + { NULL, 0, 0, 0, NULL, NULL } +}; + int sc_pkcs15_decode_pubkey_rsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_rsa *key, @@ -475,6 +482,64 @@ sc_pkcs15_encode_pubkey_gostr3410(sc_context_t *ctx, return 0; } + /* + * We are storing the ec_pointQ as a octet string. + * Thus we will just copy the string. + * But to get the field length we decode it. + */ +int +sc_pkcs15_decode_pubkey_ec(sc_context_t *ctx, + struct sc_pkcs15_pubkey_ec *key, + const u8 *buf, size_t buflen) +{ + int r; + u8 * ecpoint_data; + size_t ecpoint_len; + struct sc_asn1_entry asn1_ec_pointQ[2]; + + sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); + sc_format_asn1_entry(asn1_ec_pointQ + 0, &ecpoint_data, &ecpoint_len, 1); + r = sc_asn1_decode(ctx, asn1_ec_pointQ, buf, buflen, NULL, NULL); + if (r < 0) + SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "ASN.1 encoding failed"); + +sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"DEE-EC key=%p, buf=%p, buflen=%d", key, buf, buflen); + key->ecpointQ.value = malloc(buflen); + if (key->ecpointQ.value == NULL) + return SC_ERROR_OUT_OF_MEMORY; + + key->ecpointQ.len = buflen; + memcpy(key->ecpointQ.value, buf, buflen); + + /* An uncompressed ecpoint is of the form 04||x||y + * The 04 indicates uncompressed + * x and y are same size, and field_length = sizeof(x) in bits. */ + /* TODO: -DEE support more then uncompressed */ + key->field_length = (ecpoint_len - 1)/2 * 8; + if (ecpoint_data); + free (ecpoint_data); + + return r; +} + +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); + if (*buf == NULL) + return SC_ERROR_OUT_OF_MEMORY; + + memcpy(*buf, key->ecpointQ.value, key->ecpointQ.len); + *buflen = key->ecpointQ.len; + +sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"DEE-EC key->ecpointQ=%p:%d *buf=%p:%d", + key->ecpointQ.value, key->ecpointQ.len, *buf, *buflen); + + return 0; +} + + int sc_pkcs15_encode_pubkey(sc_context_t *ctx, struct sc_pkcs15_pubkey *key, @@ -487,6 +552,8 @@ sc_pkcs15_encode_pubkey(sc_context_t *ctx, if (key->algorithm == SC_ALGORITHM_GOSTR3410) return sc_pkcs15_encode_pubkey_gostr3410(ctx, &key->u.gostr3410, buf, len); + if (key->algorithm == SC_ALGORITHM_EC) + return sc_pkcs15_encode_pubkey_ec(ctx, &key->u.ec, buf, len); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Encoding of public key type %u not supported\n", key->algorithm); return SC_ERROR_NOT_SUPPORTED; @@ -504,6 +571,8 @@ sc_pkcs15_decode_pubkey(sc_context_t *ctx, if (key->algorithm == SC_ALGORITHM_GOSTR3410) return sc_pkcs15_decode_pubkey_gostr3410(ctx, &key->u.gostr3410, buf, len); + if (key->algorithm == SC_ALGORITHM_EC) + return sc_pkcs15_decode_pubkey_ec(ctx, &key->u.ec, buf, len); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Decoding of public key type %u not supported\n", key->algorithm); return SC_ERROR_NOT_SUPPORTED; @@ -536,6 +605,9 @@ sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card, case SC_PKCS15_TYPE_PUBKEY_GOSTR3410: algorithm = SC_ALGORITHM_GOSTR3410; break; + case SC_PKCS15_TYPE_PUBKEY_EC: + algorithm = SC_ALGORITHM_EC; + break; default: sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Unsupported public key type."); return SC_ERROR_NOT_SUPPORTED; @@ -654,6 +726,12 @@ void sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *key) if (key->u.gostr3410.xy.data) free(key->u.gostr3410.xy.data); break; + case SC_ALGORITHM_EC: + if (key->u.ec.ecparameters.value) + free(key->u.ec.ecparameters.value); + if (key->u.ec.ecpointQ.value) + free(key->u.ec.ecpointQ.value); + break; } if (key->data.value) free(key->data.value); @@ -752,7 +830,8 @@ int sc_pkcs15_pubkey_from_spki(sc_context_t *ctx, sc_pkcs15_pubkey_t ** outpubke sc_pkcs15_der_t pk = { NULL, 0 }; struct sc_algorithm_id pk_alg; struct sc_asn1_entry asn1_pkinfo[3]; - + struct sc_asn1_entry asn1_ec_pointQ[2]; + sc_debug(ctx,SC_LOG_DEBUG_NORMAL,"sc_pkcs15_pubkey_from_spki %p:%d", buf, buflen); memset(&pk_alg, 0, sizeof(pk_alg)); @@ -778,15 +857,40 @@ int sc_pkcs15_pubkey_from_spki(sc_context_t *ctx, sc_pkcs15_pubkey_t ** outpubke memcpy(pubkey->alg_id, &pk_alg, sizeof(struct sc_algorithm_id)); pubkey->algorithm = pk_alg.algorithm; - pk.len >>= 3; /* convert number of bits to bytes */ - pubkey->data = pk; /* save in publey */ - pk.value = NULL; - - /* Now decode what every is in pk as it depends on the key algorthim */ + sc_debug(ctx,SC_LOG_DEBUG_NORMAL,"DEE pk_alg.algorithm=%d",pk_alg.algorithm); - r = sc_pkcs15_decode_pubkey(ctx, pubkey, pubkey->data.value, pubkey->data.len); - if (r < 0) - goto err; + /* pk.len is in bits at this point */ + switch (pk_alg.algorithm) { + case SC_ALGORITHM_EC: + /* + * For most keys, the above ASN.1 parsing of a key works, but for EC keys, + * the ec_pointQ in a certificate is stored in a bitstring, but + * in PKCS#11 it is an octet string and we just decoded its + * contents from the bitstring in the certificate. So we need to encode it + * back to an octet string so we can store it as an octet string. + */ + pk.len >>= 3; /* Assume it is multiple of 8 */ +// pubkey->u.ec.field_length = (pk.len - 1)/2 * 8; + + sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); + sc_format_asn1_entry(&asn1_ec_pointQ[0], pk.value, &pk.len, 1); + r = sc_asn1_encode(ctx, asn1_ec_pointQ, + &pubkey->data.value, &pubkey->data.len); + sc_debug(ctx,SC_LOG_DEBUG_NORMAL,"DEE r=%d data=%p:%d", + r,pubkey->data.value, pubkey->data.len); + break; + default: + pk.len >>= 3; /* convert number of bits to bytes */ + pubkey->data = pk; /* save in publey */ + pk.value = NULL; + break; + } + + /* Now decode what every is in pk as it depends on the key algorthim */ + + r = sc_pkcs15_decode_pubkey(ctx, pubkey, pubkey->data.value, pubkey->data.len); + if (r < 0) + goto err; *outpubkey = pubkey; pubkey = NULL; diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c index 56cea6bd..c6f9f570 100644 --- a/src/libopensc/pkcs15-syn.c +++ b/src/libopensc/pkcs15-syn.c @@ -359,6 +359,30 @@ int sc_pkcs15emu_add_rsa_pubkey(sc_pkcs15_card_t *p15card, return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PUBKEY_RSA, obj, &key); } +int sc_pkcs15emu_add_ec_prkey(sc_pkcs15_card_t *p15card, + const sc_pkcs15_object_t *obj, const sc_pkcs15_prkey_info_t *in_key) +{ + sc_pkcs15_prkey_info_t key = *in_key; + + if (key.access_flags == 0) + key.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE + | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE + | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE + | SC_PKCS15_PRKEY_ACCESS_LOCAL; + + return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PRKEY_EC, obj, &key); +} +int sc_pkcs15emu_add_ec_pubkey(sc_pkcs15_card_t *p15card, + const sc_pkcs15_object_t *obj, const sc_pkcs15_pubkey_info_t *in_key) +{ + sc_pkcs15_pubkey_info_t key = *in_key; + + if (key.access_flags == 0) + key.access_flags = SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE; + + return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PUBKEY_EC, obj, &key); +} + int sc_pkcs15emu_add_x509_cert(sc_pkcs15_card_t *p15card, const sc_pkcs15_object_t *obj, const sc_pkcs15_cert_info_t *cert) { diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h index 61ee3c40..fde0ab7c 100644 --- a/src/libopensc/pkcs15.h +++ b/src/libopensc/pkcs15.h @@ -149,6 +149,21 @@ struct sc_pkcs15_prkey_dsa { sc_pkcs15_bignum_t priv; }; + /* The ecParameters are kept in DER format + * as certificates, and pkcs11 process them as DER + * If needed, they can be parsed + */ +struct sc_pkcs15_pubkey_ec { + sc_pkcs15_der_t ecparameters; + sc_pkcs15_der_t ecpointQ; /* note this is der */ + size_t field_length; /* in bits */ +}; + +struct sc_pkcs15_prkey_ec { + sc_pkcs15_der_t ecparameters; + sc_pkcs15_bignum_t privateD; /* note this is bignum */ +}; + struct sc_pkcs15_pubkey_gostr3410 { sc_pkcs15_bignum_t xy; }; @@ -166,6 +181,7 @@ struct sc_pkcs15_pubkey { union { struct sc_pkcs15_pubkey_rsa rsa; struct sc_pkcs15_pubkey_dsa dsa; + struct sc_pkcs15_pubkey_ec ec; struct sc_pkcs15_pubkey_gostr3410 gostr3410; } u; @@ -181,6 +197,7 @@ struct sc_pkcs15_prkey { union { struct sc_pkcs15_prkey_rsa rsa; struct sc_pkcs15_prkey_dsa dsa; + struct sc_pkcs15_prkey_ec ec; struct sc_pkcs15_prkey_gostr3410 gostr3410; } u; }; @@ -298,7 +315,9 @@ struct sc_pkcs15_prkey_info { struct sc_pkcs15_id id; /* correlates to public certificate id */ unsigned int usage, access_flags; int native, key_reference; - size_t modulus_length; + /* convert to union if other types are supported */ + size_t modulus_length; /* RSA */ + size_t field_length; /* EC in bits */ struct sc_pkcs15_der subject; @@ -313,7 +332,9 @@ struct sc_pkcs15_pubkey_info { struct sc_pkcs15_id id; /* correlates to private key id */ unsigned int usage, access_flags; int native, key_reference; - size_t modulus_length; + /* convert to union if other types are supported */ + size_t modulus_length; /* RSA */ + size_t field_length; /* EC in bits */ struct sc_pkcs15_der subject; @@ -330,11 +351,13 @@ typedef struct sc_pkcs15_pubkey_info sc_pkcs15_pubkey_info_t; #define SC_PKCS15_TYPE_PRKEY_RSA 0x101 #define SC_PKCS15_TYPE_PRKEY_DSA 0x102 #define SC_PKCS15_TYPE_PRKEY_GOSTR3410 0x103 +#define SC_PKCS15_TYPE_PRKEY_EC 0x104 #define SC_PKCS15_TYPE_PUBKEY 0x200 #define SC_PKCS15_TYPE_PUBKEY_RSA 0x201 #define SC_PKCS15_TYPE_PUBKEY_DSA 0x202 #define SC_PKCS15_TYPE_PUBKEY_GOSTR3410 0x203 +#define SC_PKCS15_TYPE_PUBKEY_EC 0x204 #define SC_PKCS15_TYPE_CERT 0x400 #define SC_PKCS15_TYPE_CERT_X509 0x401 @@ -368,6 +391,7 @@ struct sc_pkcs15_object { /* emulated object pointer */ void *emulated; + struct sc_pkcs15_df *df; /* can be NULL, if object is 'floating' */ struct sc_pkcs15_object *next, *prev; /* used only internally */ @@ -526,6 +550,10 @@ int sc_pkcs15_decode_pubkey_gostr3410(sc_context_t *, struct sc_pkcs15_pubkey_gostr3410 *, const u8 *, size_t); int sc_pkcs15_encode_pubkey_gostr3410(sc_context_t *, struct sc_pkcs15_pubkey_gostr3410 *, u8 **, size_t *); +int sc_pkcs15_decode_pubkey_ec(struct sc_context *, + struct sc_pkcs15_pubkey_ec *, const u8 *, size_t); +int sc_pkcs15_encode_pubkey_ec(struct sc_context *, + struct sc_pkcs15_pubkey_ec *, u8 **, size_t *); int sc_pkcs15_decode_pubkey(struct sc_context *, struct sc_pkcs15_pubkey *, const u8 *, size_t); int sc_pkcs15_encode_pubkey(struct sc_context *, @@ -793,6 +821,10 @@ int sc_pkcs15emu_add_rsa_prkey(sc_pkcs15_card_t *, const sc_pkcs15_object_t *, const sc_pkcs15_prkey_info_t *); int sc_pkcs15emu_add_rsa_pubkey(sc_pkcs15_card_t *, const sc_pkcs15_object_t *, const sc_pkcs15_pubkey_info_t *); +int sc_pkcs15emu_add_ec_prkey(sc_pkcs15_card_t *, + const sc_pkcs15_object_t *, const sc_pkcs15_prkey_info_t *); +int sc_pkcs15emu_add_ec_pubkey(sc_pkcs15_card_t *, + const sc_pkcs15_object_t *, const sc_pkcs15_pubkey_info_t *); int sc_pkcs15emu_add_x509_cert(sc_pkcs15_card_t *, const sc_pkcs15_object_t *, const sc_pkcs15_cert_info_t *); int sc_pkcs15emu_add_data_object(sc_pkcs15_card_t *, diff --git a/src/pkcs11/pkcs11.h b/src/pkcs11/pkcs11.h index fe50a403..55b24ada 100644 --- a/src/pkcs11/pkcs11.h +++ b/src/pkcs11/pkcs11.h @@ -711,6 +711,12 @@ struct ck_mechanism_info #define CKF_DERIVE (1UL << 19) #define CKF_EXTENSION (1UL << 31) +#define CKF_EC_F_P (1UL << 20) +#define CKF_EC_F_2M (1UL << 21) +#define CKF_EC_ECPARAMETERS (1UL << 22) +#define CKF_EC_NAMEDCURVE (1UL << 23) +#define CKF_EC_UNCOMPRESES (1UL << 24) +#define CKF_EC_COMPRESS (1UL << 25) /* Flags for C_WaitForSlotEvent. */ #define CKF_DONT_BLOCK (1UL)