Skip to content

Commit

Permalink
Support for ECC keys (part 1) header files and
Browse files Browse the repository at this point in the history
support routines. Add definitions for EC keys,
parameters and extensions to structures. 
Add the sc_card_find_ec_alg, sc_pkcs15_decode_pubkey_ec,
sc_pkcs15_encode_pubkey_ec, sc_pkcs15emu_add_ec_prkey,
sc_pkcs15emu_add_ec_pubkey routines. 
Only EC named curves are currently supported. 



git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4902 c6295689-39f2-0310-b995-f0e70906c6a9
  • Loading branch information
dengert committed Nov 30, 2010
1 parent 137a728 commit c34caeb
Show file tree
Hide file tree
Showing 6 changed files with 220 additions and 11 deletions.
2 changes: 2 additions & 0 deletions src/libopensc/internal.h
Expand Up @@ -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);
Expand Down
43 changes: 42 additions & 1 deletion src/libopensc/opensc.h
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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 {
Expand Down
120 changes: 112 additions & 8 deletions src/libopensc/pkcs15-pubkey.c
Expand Up @@ -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 }
};

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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));
Expand All @@ -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;
sc_debug(ctx,SC_LOG_DEBUG_NORMAL,"DEE pk_alg.algorithm=%d",pk_alg.algorithm);

/* 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 */
/* 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;
r = sc_pkcs15_decode_pubkey(ctx, pubkey, pubkey->data.value, pubkey->data.len);
if (r < 0)
goto err;

*outpubkey = pubkey;
pubkey = NULL;
Expand Down
24 changes: 24 additions & 0 deletions src/libopensc/pkcs15-syn.c
Expand Up @@ -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)
{
Expand Down

0 comments on commit c34caeb

Please sign in to comment.