pkcs15: for 'sc_pkcs15_cer's data use the 'der' object type

To hold the raw certificate blob in 'sc_pkcs15_cert' data use the 'sc_pkcs15_der' data type.
also:
; in 'pkcs15-cert.c' use short call of the debug messages;
; in 'destroy-object' pkcs15 framework handler take into account the multi-application cards:
-- when binding card use the application info;
-- when finalizing profile use the application ID.
This commit is contained in:
Viktor Tarasov 2012-09-30 22:38:27 +02:00
parent ea40e7fe24
commit df9a4d0b2c
9 changed files with 107 additions and 96 deletions

View File

@ -33,7 +33,8 @@
#include "asn1.h"
#include "pkcs15.h"
static int parse_x509_cert(sc_context_t *ctx, const u8 *buf, size_t buflen, struct sc_pkcs15_cert *cert)
static int
parse_x509_cert(sc_context_t *ctx, const u8 *buf, size_t buflen, struct sc_pkcs15_cert *cert)
{
int r;
struct sc_algorithm_id sig_alg;
@ -80,29 +81,27 @@ static int parse_x509_cert(sc_context_t *ctx, const u8 *buf, size_t buflen, stru
};
const u8 *obj;
size_t objlen;
memset(cert, 0, sizeof(*cert));
obj = sc_asn1_verify_tag(ctx, buf, buflen, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS,
&objlen);
if (obj == NULL) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "X.509 certificate not found");
return SC_ERROR_INVALID_ASN1_OBJECT;
}
cert->data_len = objlen + (obj - buf);
obj = sc_asn1_verify_tag(ctx, buf, buflen, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, &objlen);
if (obj == NULL)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "X.509 certificate not found");
cert->data.len = objlen + (obj - buf);
r = sc_asn1_decode(ctx, asn1_cert, obj, objlen, NULL, NULL);
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "ASN.1 parsing of certificate failed");
LOG_TEST_RET(ctx, r, "ASN.1 parsing of certificate failed");
cert->version++;
if (pubkey) {
cert->key = pubkey;
pubkey = NULL;
} else {
sc_debug(ctx,SC_LOG_DEBUG_VERBOSE, "Unable to decode subjectPublicKeyInfo from cert");
r = SC_ERROR_INVALID_ASN1_OBJECT;
}
else {
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "Unable to decode subjectPublicKeyInfo from cert");
}
sc_asn1_clear_algorithm_id(&sig_alg);
if (r < 0)
if (r < 0)
return r;
if (serial && serial_len) {
@ -114,6 +113,7 @@ 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)
@ -124,33 +124,35 @@ sc_pkcs15_pubkey_from_cert(struct sc_context *ctx,
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);
LOG_FUNC_RETURN(ctx, rv);
}
int sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_cert_info *info,
struct sc_pkcs15_cert **cert_out)
int
sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_cert_info *info,
struct sc_pkcs15_cert **cert_out)
{
int r;
struct sc_pkcs15_cert *cert;
u8 *data = NULL;
size_t len;
assert(p15card != NULL && info != NULL && cert_out != NULL);
SC_FUNC_CALLED(p15card->card->ctx, SC_LOG_DEBUG_VERBOSE);
LOG_FUNC_CALLED(p15card->card->ctx);
if (info->path.len) {
r = sc_pkcs15_read_file(p15card, &info->path, &data, &len);
if (r)
return r;
} else {
}
else {
sc_pkcs15_der_t copy;
sc_der_copy(&copy, &info->value);
@ -169,7 +171,8 @@ int sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card,
sc_pkcs15_free_certificate(cert);
return SC_ERROR_INVALID_ASN1_OBJECT;
}
cert->data = data;
cert->data.value = data;
*cert_out = cert;
return 0;
}
@ -204,9 +207,10 @@ static const struct sc_asn1_entry c_asn1_cert[] = {
{ NULL, 0, 0, 0, NULL, NULL }
};
int sc_pkcs15_decode_cdf_entry(struct sc_pkcs15_card *p15card,
struct sc_pkcs15_object *obj,
const u8 ** buf, size_t *buflen)
int
sc_pkcs15_decode_cdf_entry(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj,
const u8 ** buf, size_t *buflen)
{
sc_context_t *ctx = p15card->card->ctx;
struct sc_pkcs15_cert_info info;
@ -227,7 +231,7 @@ int sc_pkcs15_decode_cdf_entry(struct sc_pkcs15_card *p15card,
sc_copy_asn1_entry(c_asn1_x509_cert_value_choice, asn1_x509_cert_value_choice);
sc_copy_asn1_entry(c_asn1_type_cert_attr, asn1_type_cert_attr);
sc_copy_asn1_entry(c_asn1_cert, asn1_cert);
sc_format_asn1_entry(asn1_cred_ident + 0, &id_type, NULL, 0);
sc_format_asn1_entry(asn1_cred_ident + 1, &id_value, &id_value_len, 0);
sc_format_asn1_entry(asn1_com_cert_attr + 0, &info.id, NULL, 0);
@ -242,36 +246,37 @@ int sc_pkcs15_decode_cdf_entry(struct sc_pkcs15_card *p15card,
/* Fill in defaults */
memset(&info, 0, sizeof(info));
info.authority = 0;
r = sc_asn1_decode(ctx, asn1_cert, *buf, *buflen, buf, buflen);
/* In case of error, trash the cert value (direct coding) */
if (r < 0 && der->value)
free(der->value);
if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
return r;
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "ASN.1 decoding failed");
LOG_TEST_RET(ctx, r, "ASN.1 decoding failed");
if (!p15card->app || !p15card->app->ddo.aid.len) {
r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &info.path);
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot make absolute path");
LOG_TEST_RET(ctx, r, "Cannot make absolute path");
}
else {
else {
info.path.aid = p15card->app->ddo.aid;
}
sc_debug(ctx, SC_LOG_DEBUG_ASN1, "Certificate path '%s'", sc_print_path(&info.path));
sc_log(ctx, "Certificate path '%s'", sc_print_path(&info.path));
obj->type = SC_PKCS15_TYPE_CERT_X509;
obj->data = malloc(sizeof(info));
if (obj->data == NULL)
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY);
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
memcpy(obj->data, &info, sizeof(info));
return 0;
}
int sc_pkcs15_encode_cdf_entry(sc_context_t *ctx,
const struct sc_pkcs15_object *obj,
u8 **buf, size_t *bufsize)
int
sc_pkcs15_encode_cdf_entry(sc_context_t *ctx, const struct sc_pkcs15_object *obj,
u8 **buf, size_t *bufsize)
{
struct sc_asn1_entry asn1_cred_ident[3], asn1_com_cert_attr[4],
asn1_x509_cert_attr[2], asn1_type_cert_attr[2],
@ -289,7 +294,7 @@ int sc_pkcs15_encode_cdf_entry(sc_context_t *ctx,
sc_copy_asn1_entry(c_asn1_x509_cert_value_choice, asn1_x509_cert_value_choice);
sc_copy_asn1_entry(c_asn1_type_cert_attr, asn1_type_cert_attr);
sc_copy_asn1_entry(c_asn1_cert, asn1_cert);
sc_format_asn1_entry(asn1_com_cert_attr + 0, (void *) &infop->id, NULL, 1);
if (infop->authority)
sc_format_asn1_entry(asn1_com_cert_attr + 1, (void *) &infop->authority, NULL, 1);
@ -306,7 +311,9 @@ int sc_pkcs15_encode_cdf_entry(sc_context_t *ctx,
return r;
}
void sc_pkcs15_free_certificate(struct sc_pkcs15_cert *cert)
void
sc_pkcs15_free_certificate(struct sc_pkcs15_cert *cert)
{
assert(cert != NULL);
@ -315,12 +322,14 @@ void sc_pkcs15_free_certificate(struct sc_pkcs15_cert *cert)
free(cert->subject);
free(cert->issuer);
free(cert->serial);
free(cert->data);
free(cert->data.value);
free(cert->crl);
free(cert);
}
void sc_pkcs15_free_cert_info(sc_pkcs15_cert_info_t *cert)
void
sc_pkcs15_free_cert_info(sc_pkcs15_cert_info_t *cert)
{
if (!cert)
return;

View File

@ -100,7 +100,7 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card)
memset(&cert_info, 0, sizeof(cert_info));
memset(&cert_obj, 0, sizeof(cert_obj));
cert_info.id.value[0] = esteid_cert_ids[i];
cert_info.id.len = 1;
sc_format_path(esteid_cert_paths[i], &cert_info.path);
@ -117,7 +117,7 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card)
unsigned char *tmp = NULL;
r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert);
if (r == SC_SUCCESS) {
mem = BIO_new_mem_buf(cert->data, cert->data_len);
mem = BIO_new_mem_buf(cert->data.value, cert->data.len);
if (!mem)
return SC_ERROR_INTERNAL;
x509 = d2i_X509_bio(mem, NULL);

View File

@ -236,8 +236,8 @@ static int itacns_add_cert(sc_pkcs15_card_t *p15card,
"Could not read X.509 certificate");
{
const u8 *throwaway = cert->data;
x509 = d2i_X509(NULL, &throwaway, cert->data_len);
const u8 *throwaway = cert->data.value;
x509 = d2i_X509(NULL, &throwaway, cert->data.len);
}
sc_pkcs15_free_certificate(cert);
if (!x509) return SC_SUCCESS;

View File

@ -287,8 +287,9 @@ struct sc_pkcs15_cert {
size_t crl_len;
struct sc_pkcs15_pubkey * key;
u8 *data; /* DER encoded raw cert */
size_t data_len;
/* DER encoded raw cert */
struct sc_pkcs15_der data;
};
typedef struct sc_pkcs15_cert sc_pkcs15_cert_t;

View File

@ -1141,9 +1141,9 @@ md_fs_read_content(PCARD_DATA pCardData, char *parent, struct md_file *file)
return;
}
file->size = cert->data_len;
file->blob = pCardData->pfnCspAlloc(cert->data_len);
CopyMemory(file->blob, cert->data, cert->data_len);
file->size = cert->data.len;
file->blob = pCardData->pfnCspAlloc(cert->data.len);
CopyMemory(file->blob, cert->data.value, cert->data.len);
sc_pkcs15_free_certificate(cert);
}
}

View File

@ -507,13 +507,13 @@ public_key_created(struct pkcs15_fw_data *fw_data, const unsigned int num_object
static int
__pkcs15_create_cert_object(struct pkcs15_fw_data *fw_data,
struct sc_pkcs15_object *cert, struct pkcs15_any_object **cert_object)
__pkcs15_create_cert_object(struct pkcs15_fw_data *fw_data, struct sc_pkcs15_object *cert,
struct pkcs15_any_object **cert_object)
{
struct sc_pkcs15_cert_info *p15_info;
struct sc_pkcs15_cert *p15_cert;
struct pkcs15_cert_object *object;
struct pkcs15_pubkey_object *obj2;
struct sc_pkcs15_cert_info *p15_info = NULL;
struct sc_pkcs15_cert *p15_cert = NULL;
struct pkcs15_cert_object *object = NULL;
struct pkcs15_pubkey_object *obj2 = NULL;
int rv;
p15_info = (struct sc_pkcs15_cert_info *) cert->data;
@ -537,9 +537,8 @@ __pkcs15_create_cert_object(struct pkcs15_fw_data *fw_data,
object->cert_data = p15_cert;
/* Corresponding public key */
rv = public_key_created(fw_data, fw_data->num_objects, p15_info->id.value, p15_info->id.len,
rv = public_key_created(fw_data, fw_data->num_objects, p15_info->id.value, p15_info->id.len,
(struct pkcs15_any_object **) &obj2);
if (rv != SC_SUCCESS)
rv = __pkcs15_create_object(fw_data, (struct pkcs15_any_object **) &obj2,
NULL, &pkcs15_pubkey_ops, sizeof(struct pkcs15_pubkey_object));
@ -799,12 +798,10 @@ pkcs15_bind_related_objects(struct pkcs15_fw_data *fw_data)
continue;
sc_log(context, "Looking for objects related to object %d", i);
if (is_privkey(obj)) {
if (is_privkey(obj))
__pkcs15_prkey_bind_related(fw_data, (struct pkcs15_prkey_object *) obj);
} else if (is_cert(obj)) {
else if (is_cert(obj))
__pkcs15_cert_bind_related(fw_data, (struct pkcs15_cert_object *) obj);
}
}
}
@ -2067,10 +2064,8 @@ out:
static CK_RV
pkcs15_create_public_key(struct sc_pkcs11_slot *slot,
struct sc_profile *profile,
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
CK_OBJECT_HANDLE_PTR phObject)
pkcs15_create_public_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile,
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject)
{
struct sc_pkcs11_card *p11card = slot->card;
struct pkcs15_fw_data *fw_data = NULL;
@ -2740,8 +2735,10 @@ pkcs15_any_destroy(struct sc_pkcs11_session *session, void *object)
#else
struct pkcs15_data_object *obj = (struct pkcs15_data_object*) object;
struct pkcs15_any_object *any_obj = (struct pkcs15_any_object*) object;
struct sc_pkcs11_card *p11card = session->slot->card;
struct pkcs15_fw_data *fw_data = NULL;
struct sc_pkcs11_slot *slot = session->slot;
struct sc_pkcs11_card *p11card = slot->card;
struct pkcs15_fw_data *fw_data = NULL;
struct sc_aid *aid = NULL;
struct sc_profile *profile = NULL;
int rv;
@ -2754,13 +2751,15 @@ pkcs15_any_destroy(struct sc_pkcs11_session *session, void *object)
return sc_to_cryptoki_error(rv, "C_DestroyObject");
/* Bind the profile */
rv = sc_pkcs15init_bind(p11card->card, "pkcs15", NULL, NULL, &profile);
rv = sc_pkcs15init_bind(p11card->card, "pkcs15", NULL, slot->app_info, &profile);
if (rv < 0) {
sc_unlock(p11card->card);
return sc_to_cryptoki_error(rv, "C_DestroyObject");
}
rv = sc_pkcs15init_finalize_profile(p11card->card, profile, NULL);
if(slot->app_info)
aid = &slot->app_info->aid;
rv = sc_pkcs15init_finalize_profile(p11card->card, profile, aid);
if (rv != CKR_OK) {
sc_log(context, "Cannot finalize profile: %i", rv);
return sc_to_cryptoki_error(rv, "C_DestroyObject");
@ -2979,8 +2978,8 @@ pkcs15_cert_get_attribute(struct sc_pkcs11_session *session, void *object, CK_AT
attr->ulValueLen = 0;
return CKR_OK;
}
check_attribute_buffer(attr, cert->cert_data->data_len);
memcpy(attr->pValue, cert->cert_data->data, cert->cert_data->data_len);
check_attribute_buffer(attr, cert->cert_data->data.len);
memcpy(attr->pValue, cert->cert_data->data.value, cert->cert_data->data.len);
break;
case CKA_SERIAL_NUMBER:
if (check_cert_data_read(fw_data, cert) != 0) {
@ -3670,15 +3669,12 @@ pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session,
break;
case CKA_PRIVATE:
check_attribute_buffer(attr, sizeof(CK_BBOOL));
if (pubkey->pub_p15obj) {
*(CK_BBOOL*)attr->pValue =
(pubkey->pub_p15obj->flags & SC_PKCS15_CO_FLAG_PRIVATE) != 0;
} else if (cert && cert->cert_p15obj) {
*(CK_BBOOL*)attr->pValue =
(cert->pub_p15obj->flags & SC_PKCS15_CO_FLAG_PRIVATE) != 0;
} else {
if (pubkey->pub_p15obj)
*(CK_BBOOL*)attr->pValue = (pubkey->pub_p15obj->flags & SC_PKCS15_CO_FLAG_PRIVATE) != 0;
else if (cert && cert->cert_p15obj)
*(CK_BBOOL*)attr->pValue = (cert->pub_p15obj->flags & SC_PKCS15_CO_FLAG_PRIVATE) != 0;
else
return CKR_ATTRIBUTE_TYPE_INVALID;
}
break;
case CKA_MODIFIABLE:
case CKA_EXTRACTABLE:
@ -3690,11 +3686,13 @@ pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session,
len = strlen(pubkey->pub_p15obj->label);
check_attribute_buffer(attr, len);
memcpy(attr->pValue, pubkey->pub_p15obj->label, len);
} else if (cert && cert->cert_p15obj) {
}
else if (cert && cert->cert_p15obj) {
len = strlen(cert->cert_p15obj->label);
check_attribute_buffer(attr, len);
memcpy(attr->pValue, cert->cert_p15obj->label, len);
} else {
}
else {
return CKR_ATTRIBUTE_TYPE_INVALID;
}
break;
@ -3713,10 +3711,12 @@ pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session,
if (pubkey->pub_info) {
check_attribute_buffer(attr, pubkey->pub_info->id.len);
memcpy(attr->pValue, pubkey->pub_info->id.value, pubkey->pub_info->id.len);
} else if (cert && cert->cert_info) {
}
else if (cert && cert->cert_info) {
check_attribute_buffer(attr, cert->cert_info->id.len);
memcpy(attr->pValue, cert->cert_info->id.value, cert->cert_info->id.len);
} else {
}
else {
return CKR_ATTRIBUTE_TYPE_INVALID;
}
break;
@ -3750,15 +3750,16 @@ pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session,
case CKA_VALUE:
if (pubkey->pub_data) {
/* TODO: -DEE Not all pubkeys have CKA_VALUE attribute. RSA and EC
* for example don't. So why is this here?
* for example don't. So why is this here?
* Why checking for cert in this pkcs15_pubkey_get_attribute?
*/
*/
check_attribute_buffer(attr, pubkey->pub_data->data.len);
memcpy(attr->pValue, pubkey->pub_data->data.value,
pubkey->pub_data->data.len);
} else if (cert && cert->cert_data) {
check_attribute_buffer(attr, cert->cert_data->data_len);
memcpy(attr->pValue, cert->cert_data->data, cert->cert_data->data_len);
}
else if (cert && cert->cert_data) {
check_attribute_buffer(attr, cert->cert_data->data.len);
memcpy(attr->pValue, cert->cert_data->data.value, cert->cert_data->data.len);
}
break;
case CKA_GOSTR3410_PARAMS:

View File

@ -1427,7 +1427,7 @@ awp_update_df_create_prvkey(struct sc_pkcs15_card *p15card, struct sc_profile *p
rv = sc_pkcs15_read_certificate(p15card, cert_info, &p15cert);
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "AWP 'update private key' DF failed: cannot get certificate");
rv = sc_pkcs15_allocate_object_content(ctx, cert_obj, p15cert->data, p15cert->data_len);
rv = sc_pkcs15_allocate_object_content(ctx, cert_obj, p15cert->data.value, p15cert->data.len);
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "AWP 'update private key' DF failed: cannot allocate content");
rv = awp_encode_cert_info(p15card, cert_obj, &icert);

View File

@ -1005,12 +1005,12 @@ is_cacert_already_present(struct sc_pkcs15init_certargs *args)
if (r < 0 || !cert)
continue;
if (cert->data_len == args->der_encoded.len
&& !memcmp(cert->data, args->der_encoded.value,
cert->data_len)) {
if (cert->data.len == args->der_encoded.len
&& !memcmp(cert->data.value, args->der_encoded.value, cert->data.len)) {
sc_pkcs15_free_certificate(cert);
return 1;
}
sc_pkcs15_free_certificate(cert);
cert=NULL;
}
@ -1087,8 +1087,8 @@ do_read_check_certificate(sc_pkcs15_cert_t *sc_oldcert,
int r;
/* Get the public key from the old cert */
ptr = sc_oldcert->data;
oldcert = d2i_X509(NULL, &ptr, sc_oldcert->data_len);
ptr = sc_oldcert->data.value;
oldcert = d2i_X509(NULL, &ptr, sc_oldcert->data.len);
if (oldcert == NULL)
return SC_ERROR_INTERNAL;

View File

@ -388,7 +388,7 @@ static int read_certificate(void)
fprintf(stderr, "Certificate read failed: %s\n", sc_strerror(r));
return 1;
}
r = print_pem_object("CERTIFICATE", cert->data, cert->data_len);
r = print_pem_object("CERTIFICATE", cert->data.value, cert->data.len);
sc_pkcs15_free_certificate(cert);
return r;
}