sc_pkcs15_pubkey_from_cert now uses parse_x509_cert without OpenSSL.

sc_pkcs15_cert now has pointer to sc_pkcs15_pubkey, allowing it to 
be removed and used separatly.  
sc_pkcs15_pubkey now has pointer to sc_algorithm_id to faclitate
addition of other key algorithms and their parameters. 
Various code changes to free these structures and references
to the structures have been changed. 



git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4805 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
dengert 2010-10-12 15:26:45 +00:00
parent 6b4cb93c84
commit 0f2a44b33e
7 changed files with 63 additions and 95 deletions

View File

@ -998,8 +998,10 @@ static int piv_get_data(sc_card_t * card, int enumtag,
/* end of read pub key from file */
#else
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"Requires OpenSSL");
r = SC_ERROR_NOT_SUPPORTED;
if (getenv(keyenvname))
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"Requires OpenSSL");
r = SC_ERROR_FILE_NOT_FOUND;
goto err;
#endif /* ENABLE_OPENSSL */
} else {

View File

@ -37,6 +37,7 @@ static int parse_x509_cert(sc_context_t *ctx, const u8 *buf, size_t buflen, stru
{
int r;
struct sc_algorithm_id pk_alg, sig_alg;
struct sc_pkcs15_pubkey pubkey;
sc_pkcs15_der_t pk = { NULL, 0 };
u8 *serial = NULL;
size_t serial_len = 0;
@ -86,6 +87,8 @@ static int parse_x509_cert(sc_context_t *ctx, const u8 *buf, size_t buflen, stru
size_t objlen;
memset(cert, 0, sizeof(*cert));
memset(&pk_alg, 0, sizeof(pk_alg));
memset(&pubkey, 0, sizeof(pubkey));
obj = sc_asn1_verify_tag(ctx, buf, buflen, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS,
&objlen);
if (obj == NULL) {
@ -98,14 +101,23 @@ static int parse_x509_cert(sc_context_t *ctx, const u8 *buf, size_t buflen, stru
cert->version++;
cert->key.algorithm = pk_alg.algorithm;
pk.len >>= 3; /* convert number of bits to bytes */
cert->key.data = pk;
cert->key = malloc(sizeof(struct sc_pkcs15_pubkey));
if (cert->key == NULL)
return SC_ERROR_OUT_OF_MEMORY;
memcpy(cert->key, &pubkey, sizeof(struct sc_pkcs15_pubkey));
r = sc_pkcs15_decode_pubkey(ctx, &cert->key, pk.value, pk.len);
cert->key->alg_id = malloc(sizeof(struct sc_algorithm_id));
if (cert->key->alg_id == NULL)
return SC_ERROR_OUT_OF_MEMORY;
memcpy(cert->key->alg_id, &pk_alg, sizeof(struct sc_algorithm_id));
cert->key->algorithm = pk_alg.algorithm;
pk.len >>= 3; /* convert number of bits to bytes */
cert->key->data = pk;
r = sc_pkcs15_decode_pubkey(ctx, cert->key, pk.value, pk.len);
if (r < 0)
free(pk.value);
sc_asn1_clear_algorithm_id(&pk_alg);
sc_asn1_clear_algorithm_id(&sig_alg);
if (serial && serial_len) {
@ -117,6 +129,26 @@ static int parse_x509_cert(sc_context_t *ctx, const u8 *buf, size_t buflen, stru
return r;
}
int
sc_pkcs15_pubkey_from_cert(struct sc_context *ctx,
struct sc_pkcs15_der *cert_blob, struct sc_pkcs15_pubkey **out)
{
int rv;
struct sc_pkcs15_cert * cert;
cert = calloc(1, sizeof(struct sc_pkcs15_cert));
if (cert == NULL)
return SC_ERROR_OUT_OF_MEMORY;
rv = parse_x509_cert(ctx, cert_blob->value, cert_blob->len, cert);
*out = cert->key;
cert->key = NULL;
sc_pkcs15_free_certificate(cert);
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, rv);
}
int sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_cert_info *info,
struct sc_pkcs15_cert **cert_out)
@ -149,7 +181,7 @@ int sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card,
memset(cert, 0, sizeof(struct sc_pkcs15_cert));
if (parse_x509_cert(p15card->card->ctx, data, len, cert)) {
free(data);
free(cert);
sc_pkcs15_free_certificate(cert);
return SC_ERROR_INVALID_ASN1_OBJECT;
}
cert->data = data;
@ -286,7 +318,8 @@ void sc_pkcs15_free_certificate(struct sc_pkcs15_cert *cert)
{
assert(cert != NULL);
sc_pkcs15_erase_pubkey(&cert->key);
if (cert->key)
sc_pkcs15_free_pubkey(cert->key);
free(cert->subject);
free(cert->issuer);
free(cert->serial);

View File

@ -408,9 +408,9 @@ static int sc_pkcs15emu_gemsafeGPK_init(sc_pkcs15_card_t *p15card)
}
for (j = 0; j < num_keyinfo; j++) {
if (cert_out->key.u.rsa.modulus.len == kinfo[j].modulus_len &&
memcmp(cert_out->key.u.rsa.modulus.data,
&kinfo[j].modulus, cert_out->key.u.rsa.modulus.len) == 0) {
if (cert_out->key->u.rsa.modulus.len == kinfo[j].modulus_len &&
memcmp(cert_out->key->u.rsa.modulus.data,
&kinfo[j].modulus, cert_out->key->u.rsa.modulus.len) == 0) {
memcpy(&kinfo[j].id, &cert_info.id, sizeof(sc_pkcs15_id_t));
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "found match");
}

View File

@ -557,14 +557,14 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
continue;
}
/* TODO support EC keys */
ckis[i].key_alg = cert_out->key.algorithm;
if (cert_out->key.algorithm == SC_ALGORITHM_RSA) {
ckis[i].key_alg = cert_out->key->algorithm;
if (cert_out->key->algorithm == SC_ALGORITHM_RSA) {
/* save modulus_len for pub and priv */
ckis[i].modulus_len = cert_out->key.u.rsa.modulus.len * 8;
ckis[i].modulus_len = cert_out->key->u.rsa.modulus.len * 8;
} else {
/*TODO add the SC_ALGORITHM_EC */
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unsuported key.algorithm %d", cert_out->key.algorithm);
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unsuported key.algorithm %d", cert_out->key->algorithm);
ckis[i].modulus_len = 1024; /* set some value for now */
}
sc_pkcs15_free_certificate(cert_out);

View File

@ -623,81 +623,13 @@ sc_pkcs15_pubkey_from_prvkey(struct sc_context *ctx,
return SC_SUCCESS;
}
int
sc_pkcs15_pubkey_from_cert(struct sc_context *ctx,
struct sc_pkcs15_der *cert_blob, struct sc_pkcs15_pubkey **out)
{
#ifndef ENABLE_OPENSSL
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED);
#else
EVP_PKEY *pkey = NULL;
X509 *x = NULL;
BIO *mem = NULL;
struct sc_pkcs15_pubkey *pubkey = NULL;
int rv = 0;
assert(cert_blob && out);
pubkey = calloc(1, sizeof(struct sc_pkcs15_pubkey));
if (!pubkey)
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate pubkey");
pubkey->algorithm = SC_ALGORITHM_RSA;
do {
rv = SC_ERROR_INVALID_DATA;
mem = BIO_new_mem_buf(cert_blob->value, cert_blob->len);
if (!mem)
break;
x = d2i_X509_bio(mem, NULL);
if (!x)
break;
pkey=X509_get_pubkey(x);
if (!pkey || pkey->type != EVP_PKEY_RSA)
break;
pubkey->u.rsa.modulus.len = BN_num_bytes(pkey->pkey.rsa->n);
pubkey->u.rsa.modulus.data = calloc(1, pubkey->u.rsa.modulus.len);
pubkey->u.rsa.exponent.len = BN_num_bytes(pkey->pkey.rsa->e);
pubkey->u.rsa.exponent.data = calloc(1, pubkey->u.rsa.exponent.len);
rv = SC_ERROR_OUT_OF_MEMORY;
if (!pubkey->u.rsa.modulus.data || !pubkey->u.rsa.exponent.data)
break;
BN_bn2bin(pkey->pkey.rsa->n, pubkey->u.rsa.modulus.data);
BN_bn2bin(pkey->pkey.rsa->e, pubkey->u.rsa.exponent.data);
rv = SC_SUCCESS;
} while (0);
if (pkey)
EVP_PKEY_free(pkey);
if (x)
X509_free(x);
if (mem)
BIO_free(mem);
if (rv) {
sc_pkcs15_free_pubkey(pubkey);
pubkey = NULL;
}
*out = pubkey;
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, rv);
#endif
}
void sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *key)
{
assert(key != NULL);
if (key->alg_id) {
sc_asn1_clear_algorithm_id(key->alg_id);
free(key->alg_id);
}
switch (key->algorithm) {
case SC_ALGORITHM_RSA:
if (key->u.rsa.modulus.data)

View File

@ -160,6 +160,7 @@ struct sc_pkcs15_prkey_gostr3410 {
struct sc_pkcs15_pubkey {
int algorithm;
struct sc_algorithm_id * alg_id;
/* Decoded key */
union {
@ -175,6 +176,8 @@ typedef struct sc_pkcs15_pubkey sc_pkcs15_pubkey_t;
struct sc_pkcs15_prkey {
unsigned int algorithm;
/* TODO do we need: struct sc_algorithm_id * alg_id; */
union {
struct sc_pkcs15_prkey_rsa rsa;
struct sc_pkcs15_prkey_dsa dsa;
@ -207,7 +210,7 @@ struct sc_pkcs15_cert {
u8 *crl;
size_t crl_len;
struct sc_pkcs15_pubkey key;
struct sc_pkcs15_pubkey * key;
u8 *data; /* DER encoded raw cert */
size_t data_len;
};

View File

@ -426,16 +426,14 @@ __pkcs15_create_cert_object(struct pkcs15_fw_data *fw_data,
return rv;
if (p15_cert) {
obj2->pub_data = &p15_cert->key;
obj2->pub_data = (sc_pkcs15_pubkey_t *)calloc(1, sizeof(sc_pkcs15_pubkey_t));
if (!obj2->pub_data)
return SC_ERROR_OUT_OF_MEMORY;
memcpy(obj2->pub_data, &p15_cert->key, sizeof(sc_pkcs15_pubkey_t));
/* we take the pubkey from the cert, as it in not needed */
obj2->pub_data = p15_cert->key;
/* invalidate public data of the cert object so that sc_pkcs15_cert_free
* does not free the public key data as well (something like
* sc_pkcs15_pubkey_dup would have been nice here) -- Nils
*/
memset(&p15_cert->key, 0, sizeof(sc_pkcs15_pubkey_t));
p15_cert->key = NULL;
} else
obj2->pub_data = NULL; /* will copy from cert when cert is read */