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:
parent
6b4cb93c84
commit
0f2a44b33e
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Reference in New Issue