Merge pull request #194 from dengert/ecpointQ

EcpointQ
This commit is contained in:
Doug Engert 2013-11-12 06:56:10 -08:00
commit 5dd5994492
5 changed files with 68 additions and 24 deletions

View File

@ -912,7 +912,7 @@ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "DEE Adding pin %d label=%s",i, label);
}
else if (ckis[i].pubkey_from_cert && ckis[i].pubkey_from_cert->data.value) {
sc_der_copy(&pubkey_obj.content, &ckis[i].pubkey_from_cert->data);
sc_pkcs15_free_pubkey(ckis[i].pubkey_from_cert);
pubkey_obj.emulated = ckis[i].pubkey_from_cert;
}
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"adding pubkey for %d keyalg=%d",i, ckis[i].key_alg);

View File

@ -602,9 +602,7 @@ sc_pkcs15_encode_pubkey_gostr3410(sc_context_t *ctx,
}
/*
* 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.
* We are storing the ec_pointQ as u8 string. not as DER
*/
int
sc_pkcs15_decode_pubkey_ec(sc_context_t *ctx,
@ -620,23 +618,18 @@ sc_pkcs15_decode_pubkey_ec(sc_context_t *ctx,
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)
LOG_TEST_RET(ctx, r, "ASN.1 encoding failed");
LOG_TEST_RET(ctx, r, "ASN.1 decoding failed");
sc_log(ctx, "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;
sc_log(ctx, "decode-EC key=%p, buf=%p, buflen=%d", key, buf, buflen);
key->ecpointQ.len = buflen;
memcpy(key->ecpointQ.value, buf, buflen);
key->ecpointQ.len = ecpoint_len;
key->ecpointQ.value = ecpoint_data;
/* 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->params.field_length = (ecpoint_len - 1)/2 * 8;
if (ecpoint_data)
free (ecpoint_data);
return r;
}
@ -1010,26 +1003,45 @@ sc_pkcs15_pubkey_from_spki(sc_context_t *ctx, sc_pkcs15_pubkey_t ** outpubkey,
}
memcpy(pubkey->alg_id, &pk_alg, sizeof(struct sc_algorithm_id));
pubkey->algorithm = pk_alg.algorithm;
pk_alg.params = NULL;
sc_log(ctx, "DEE pk_alg.algorithm=%d", pk_alg.algorithm);
/* pk.len is in bits at this point */
switch (pk_alg.algorithm) {
case SC_ALGORITHM_EC:
/*
* TODO we really should only have params in one place!
* The alg_id may have the sc_ec_params,
* we want to get the curve OID into the
* u.ec.params and get the field length too.
*/
if (pubkey->alg_id->params) {
struct sc_ec_params * ecp = (struct sc_ec_params *)pubkey->alg_id->params;
pubkey->u.ec.params.der.value = malloc(ecp->der_len);
if (pubkey->u.ec.params.der.value) {
memcpy(&pubkey->u.ec.params.der.value, &ecp->der, ecp->der_len);
pubkey->u.ec.params.der.len = ecp->der_len;
sc_pkcs15_fix_ec_parameters(ctx,&pubkey->u.ec.params);
}
}
/*
* 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.
* the ec_pointQ in a certificate is stored in the bitstring, in its raw format.
* RSA for example is stored in the bitstring, as a ASN1 DER
* So we encoded the raw ecpointQ into ASN1 DER as the pubkey->data
* and let the sc_pkcs15_decode_pubkey below get the ecpointQ out later.
*/
pk.len >>= 3; /* Assume it is multiple of 8 */
/* pubkey->u.ec.field_length = (pk.len - 1)/2 * 8; */
if (pubkey->u.ec.params.field_length == 0)
pubkey->u.ec.params.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);
pk.value = NULL;
sc_log(ctx, "DEE r=%d data=%p:%d", r, pubkey->data.value, pubkey->data.len);
break;
default:

View File

@ -154,6 +154,12 @@ struct sc_pkcs15_der {
};
typedef struct sc_pkcs15_der sc_pkcs15_der_t;
struct sc_pkcs15_u8 {
u8 * value;
size_t len;
};
typedef struct sc_pkcs15_u8 sc_pkcs15_u8_t;
struct sc_pkcs15_pubkey_rsa {
sc_pkcs15_bignum_t modulus;
sc_pkcs15_bignum_t exponent;
@ -214,13 +220,13 @@ struct sc_pkcs15_gost_parameters {
struct sc_pkcs15_pubkey_ec {
struct sc_pkcs15_ec_parameters params;
struct sc_pkcs15_der ecpointQ; /* note this is der */
struct sc_pkcs15_u8 ecpointQ; /* This is NOT DER, just value and length */
};
struct sc_pkcs15_prkey_ec {
struct sc_pkcs15_ec_parameters params;
sc_pkcs15_bignum_t privateD; /* note this is bignum */
struct sc_pkcs15_der ecpointQ; /* note this is der */
struct sc_pkcs15_u8 ecpointQ; /* This is NOT DER, just value and length */
};
struct sc_pkcs15_pubkey_gostr3410 {

View File

@ -3294,10 +3294,10 @@ pkcs15_prkey_get_attribute(struct sc_pkcs11_session *session,
check_attribute_buffer(attr, sizeof(CK_ULONG));
switch (prkey->prv_p15obj->type) {
case SC_PKCS15_TYPE_PRKEY_EC:
if (key)
if (key && key->u.ec.params.field_length > 0)
*(CK_ULONG *) attr->pValue = key->u.ec.params.field_length;
else
*(CK_ULONG *) attr->pValue = 384; /* TODO -DEE needs work */
*(CK_ULONG *) attr->pValue = (key->u.ec.ecpointQ.len - 1) / 2 *8;
return CKR_OK;
default:
*(CK_ULONG *) attr->pValue = prkey->prv_info->modulus_length;
@ -4251,6 +4251,13 @@ get_ec_pubkey_params(struct sc_pkcs15_pubkey *key, CK_ATTRIBUTE_PTR attr)
switch (key->algorithm) {
case SC_ALGORITHM_EC:
/* TODO parms should not be in two places */
/* ec_params may be in key->alg_id or in key->u.ec */
if (key->u.ec.params.der.value) {
check_attribute_buffer(attr,key->u.ec.params.der.len);
memcpy(attr->pValue, key->u.ec.params.der.value, key->u.ec.params.der.len);
return CKR_OK;
}
check_attribute_buffer(attr, ecp->der_len);
memcpy(attr->pValue, ecp->der, ecp->der_len);
return CKR_OK;
@ -4266,8 +4273,16 @@ get_ec_pubkey_point(struct sc_pkcs15_pubkey *key, CK_ATTRIBUTE_PTR attr)
switch (key->algorithm) {
case SC_ALGORITHM_EC:
check_attribute_buffer(attr, key->u.ec.ecpointQ.len);
memcpy(attr->pValue, key->u.ec.ecpointQ.value, key->u.ec.ecpointQ.len);
/*
* TODO Verify that pubkey->data is DER encoded ecpointQ
* It should be. If not we need to encode the ecpointQ to
* DER. But can not use sc_pkcs15_encode_pubkey as it
* needs ctx, and ctx is not available here.
* Original ECC code stored ecpointQ as DER, so there was
* no issue.
*/
check_attribute_buffer(attr, key->data.len);
memcpy(attr->pValue, key->data.value, key->data.len);
return CKR_OK;
}
return CKR_ATTRIBUTE_TYPE_INVALID;

View File

@ -651,6 +651,17 @@ myeid_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
r = sc_card_ctl(card, SC_CARDCTL_MYEID_GETDATA, &data_obj);
LOG_TEST_RET(ctx, r, "Cannot get EC public key: 'MYEID_GETDATA' failed");
/*
* TODO DEE - this looks like a bug...
* pubkey->u.ec.ecpointQ.value is just value. "04||X||Y"
* pubkey->data.value should be DER OCTET STRING
* but
* pubkey->data.value looks like TLV with TAG if 0x86
* and single byte length.
* Could call sc_pkcs15_encode_pubkey
* to set pubkey->data.value
*/
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);