pkcs15init: in select_object_path() look for the template also outside the 'key-domain'.

To use New API with the cards that do not have 'key-domain' in their profile,
when setting object data path,
the object template has to be also looked for outside the 'key-domain'.

;migrate Oberthur to the New API;
;use macros SC_CALLED, SC_TEST_.., SC_RETURN in pkcs15-lib.c




git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3940 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
viktor.tarasov 2010-01-25 16:42:22 +00:00
parent 986309db79
commit bc140126e9
2 changed files with 225 additions and 181 deletions

View File

@ -1206,7 +1206,7 @@ sc_pkcs15init_init_prkdf(struct sc_pkcs15_card *p15card,
} }
r = select_object_path(p15card, profile, object, &key_info->id, &key_info->path); r = select_object_path(p15card, profile, object, &key_info->id, &key_info->path);
SC_TEST_RET(ctx, r, "Failed to select object path"); SC_TEST_RET(ctx, r, "Failed to select private key object path");
/* See if we need to select a key reference for this object */ /* See if we need to select a key reference for this object */
if (profile->ops->select_key_reference) { if (profile->ops->select_key_reference) {
@ -1234,6 +1234,7 @@ sc_pkcs15init_init_prkdf(struct sc_pkcs15_card *p15card,
SC_FUNC_RETURN(ctx, 3, SC_SUCCESS); SC_FUNC_RETURN(ctx, 3, SC_SUCCESS);
} }
/* /*
* Generate a new private key * Generate a new private key
*/ */
@ -1244,42 +1245,41 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card,
unsigned int keybits, unsigned int keybits,
struct sc_pkcs15_object **res_obj) struct sc_pkcs15_object **res_obj)
{ {
struct sc_context *ctx = p15card->card->ctx;
struct sc_pkcs15init_pubkeyargs pubkey_args; struct sc_pkcs15init_pubkeyargs pubkey_args;
struct sc_pkcs15_object *object; struct sc_pkcs15_object *object;
struct sc_pkcs15_prkey_info *key_info; struct sc_pkcs15_prkey_info *key_info;
int r, caller_supplied_id = 0; int r, caller_supplied_id = 0;
SC_FUNC_CALLED(ctx, 3);
/* check supported key size */ /* check supported key size */
r = check_key_size(p15card->card, keygen_args->prkey_args.key.algorithm, keybits); r = check_key_size(p15card->card, keygen_args->prkey_args.key.algorithm, keybits);
if (r != SC_SUCCESS) SC_TEST_RET(ctx, r, "Invalid key size");
return r;
/* For now, we support just RSA and GOST key pair generation */ /* For now, we support just RSA and GOST key pair generation */
if (!check_key_compatibility(p15card, &keygen_args->prkey_args.key, if (!check_key_compatibility(p15card, &keygen_args->prkey_args.key,
keygen_args->prkey_args.x509_usage, keygen_args->prkey_args.x509_usage,
keybits, SC_ALGORITHM_ONBOARD_KEY_GEN)) keybits, SC_ALGORITHM_ONBOARD_KEY_GEN))
return SC_ERROR_NOT_SUPPORTED; SC_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Generation of RSA and GOST keys is only supported");
if (profile->ops->generate_key == NULL && profile->ops->old_generate_key == NULL) if (profile->ops->generate_key == NULL && profile->ops->old_generate_key == NULL)
return SC_ERROR_NOT_SUPPORTED; SC_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Key generation not supported");
/* Set the USER PIN reference from args */ /* Set the USER PIN reference from args */
r = set_user_pin_from_authid(p15card, profile, r = set_user_pin_from_authid(p15card, profile, &keygen_args->prkey_args.auth_id);
&keygen_args->prkey_args.auth_id); SC_TEST_RET(ctx, r, "Cannot set User PIN from auth. ID");
if (r < 0)
return r;
/* Set the SO PIN reference from card */ /* Set the SO PIN reference from card */
if ((r = set_so_pin_from_card(p15card, profile)) < 0) r = set_so_pin_from_card(p15card, profile);
return r; SC_TEST_RET(ctx, r, "Cannot set SO PIN from card");
caller_supplied_id = keygen_args->prkey_args.id.len != 0; caller_supplied_id = keygen_args->prkey_args.id.len != 0;
/* Set up the PrKDF object */ /* Set up the PrKDF object */
r = sc_pkcs15init_init_prkdf(p15card, profile, &keygen_args->prkey_args, r = sc_pkcs15init_init_prkdf(p15card, profile, &keygen_args->prkey_args,
&keygen_args->prkey_args.key, keybits, &object); &keygen_args->prkey_args.key, keybits, &object);
if (r < 0) SC_TEST_RET(ctx, r, "Set up private key object error");
return r;
key_info = (struct sc_pkcs15_prkey_info *) object->data; key_info = (struct sc_pkcs15_prkey_info *) object->data;
/* Set up the PuKDF info. The public key will be filled in /* Set up the PuKDF info. The public key will be filled in
@ -1298,57 +1298,49 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card,
if (profile->ops->create_key) { if (profile->ops->create_key) {
/* New API */ /* New API */
r = profile->ops->create_key(profile, p15card->card, object); r = profile->ops->create_key(profile, p15card->card, object);
if (r < 0) SC_TEST_RET(ctx, r, "Cannot generate key: create key failed");
return r;
r = profile->ops->generate_key(profile, p15card->card, r = profile->ops->generate_key(profile, p15card->card, object, &pubkey_args.key);
object, &pubkey_args.key); SC_TEST_RET(ctx, r, "Failed to generate key");
if (r < 0)
return r;
} else { } else {
int idx; int idx;
idx = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY, NULL, 0); idx = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY, NULL, 0);
r = profile->ops->old_generate_key(profile, p15card->card, idx, keybits, r = profile->ops->old_generate_key(profile, p15card->card, idx, keybits,
&pubkey_args.key, key_info); &pubkey_args.key, key_info);
SC_TEST_RET(ctx, r, "Failed to generate key in an old manner");
} }
/* update PrKDF entry */ /* update PrKDF entry */
if (r >= 0) { if (!caller_supplied_id) {
if (!caller_supplied_id) { struct sc_pkcs15_id iid;
struct sc_pkcs15_id iid;
/* Caller not supplied ID, so, /* Caller not supplied ID, so,
* if intrinsic ID can be calculated -- overwrite the native one */ * if intrinsic ID can be calculated -- overwrite the native one */
memset(&iid, 0, sizeof(iid)); memset(&iid, 0, sizeof(iid));
r = select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_PUBKEY, &iid, &pubkey_args.key); r = select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_PUBKEY, &iid, &pubkey_args.key);
if (r < 0) SC_TEST_RET(ctx, r, "Select intrinsic ID error");
return r;
if (iid.len) { if (iid.len) {
key_info->id = iid; key_info->id = iid;
pubkey_args.id = iid; pubkey_args.id = iid;
}
} }
r = sc_pkcs15init_add_object(p15card, profile, SC_PKCS15_PRKDF, object);
} }
if (r >= 0) { r = sc_pkcs15init_add_object(p15card, profile, SC_PKCS15_PRKDF, object);
sc_pkcs15_object_t *pub_object; SC_TEST_RET(ctx, r, "Failed to add generated private key object");
r = sc_pkcs15init_store_public_key(p15card, profile, r = sc_pkcs15init_store_public_key(p15card, profile, &pubkey_args, NULL);
&pubkey_args, &pub_object); SC_TEST_RET(ctx, r, "Failed to store public key");
}
if (r >= 0 && res_obj) if (res_obj)
*res_obj = object; *res_obj = object;
sc_pkcs15_erase_pubkey(&pubkey_args.key); sc_pkcs15_erase_pubkey(&pubkey_args.key);
profile->dirty = 1; profile->dirty = 1;
return r; SC_FUNC_RETURN(ctx, 3, r);
} }
@ -1506,6 +1498,8 @@ sc_pkcs15init_store_split_key(struct sc_pkcs15_card *p15card,
/* /*
* Store a public key * Store a public key
*
* TODO: set public key reference
*/ */
int int
sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card, sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card,
@ -1525,7 +1519,7 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card,
int r; int r;
SC_FUNC_CALLED(ctx, 3); SC_FUNC_CALLED(ctx, 3);
if (!res_obj || !keyargs) if (!keyargs)
SC_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Store public key aborted"); SC_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Store public key aborted");
/* Create a copy of the key first */ /* Create a copy of the key first */
@ -1629,12 +1623,14 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card,
struct sc_pkcs15init_certargs *args, struct sc_pkcs15init_certargs *args,
struct sc_pkcs15_object **res_obj) struct sc_pkcs15_object **res_obj)
{ {
struct sc_context *ctx = p15card->card->ctx;
struct sc_pkcs15_cert_info *cert_info; struct sc_pkcs15_cert_info *cert_info;
struct sc_pkcs15_object *object; struct sc_pkcs15_object *object;
unsigned int usage; unsigned int usage;
const char *label; const char *label;
int r; int r;
SC_FUNC_CALLED(ctx, 3);
usage = SC_PKCS15_PRKEY_USAGE_SIGN; usage = SC_PKCS15_PRKEY_USAGE_SIGN;
if (args->x509_usage) if (args->x509_usage)
usage = sc_pkcs15init_map_usage(args->x509_usage, 0); usage = sc_pkcs15init_map_usage(args->x509_usage, 0);
@ -1642,17 +1638,16 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card,
label = "Certificate"; label = "Certificate";
/* Set the SO PIN reference from card */ /* Set the SO PIN reference from card */
if ((r = set_so_pin_from_card(p15card, profile)) < 0) r = set_so_pin_from_card(p15card, profile);
return r; SC_TEST_RET(ctx, r, "Set SO PIN from card error");
r = select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_CERT_X509, &args->id, &args->der_encoded); r = select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_CERT_X509, &args->id, &args->der_encoded);
if (r < 0) SC_TEST_RET(ctx, r, "Get certificate 'intrinsic ID' error");
return r;
/* Select an ID if the user didn't specify one, otherwise /* Select an ID if the user didn't specify one, otherwise
* make sure it's unique */ * make sure it's unique */
if ((r = select_id(p15card, SC_PKCS15_TYPE_CERT, &args->id)) < 0) r = select_id(p15card, SC_PKCS15_TYPE_CERT, &args->id);
return r; SC_TEST_RET(ctx, r, "Select certificate ID error");
if (profile->protect_certificates) { if (profile->protect_certificates) {
/* If there is a private key corresponding to the ID given /* If there is a private key corresponding to the ID given
@ -1663,12 +1658,8 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card,
if (args->id.len != 0 if (args->id.len != 0
&& sc_pkcs15_find_prkey_by_id(p15card, &args->id, &object) == 0) { && sc_pkcs15_find_prkey_by_id(p15card, &args->id, &object) == 0) {
r = set_user_pin_from_authid(p15card, profile, &object->auth_id); r = set_user_pin_from_authid(p15card, profile, &object->auth_id);
if (r < 0) { SC_TEST_RET(ctx, r, "Failed to assign user pin reference "
sc_debug(p15card->card->ctx, "(copied from private key auth_id)");
"Failed to assign user pin reference "
"(copied from private key auth_id)\n");
return r;
}
} }
if (r == -1) /* User pin ref not yet set */ if (r == -1) /* User pin ref not yet set */
set_user_pin_from_authid(p15card, profile, NULL); set_user_pin_from_authid(p15card, profile, NULL);
@ -1676,7 +1667,7 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card,
object = sc_pkcs15init_new_object(SC_PKCS15_TYPE_CERT_X509, label, NULL, NULL); object = sc_pkcs15init_new_object(SC_PKCS15_TYPE_CERT_X509, label, NULL, NULL);
if (object == NULL) if (object == NULL)
return SC_ERROR_OUT_OF_MEMORY; SC_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Failed to allocate certificate object");
cert_info = (sc_pkcs15_cert_info_t *) object->data; cert_info = (sc_pkcs15_cert_info_t *) object->data;
cert_info->id = args->id; cert_info->id = args->id;
cert_info->authority = args->authority; cert_info->authority = args->authority;
@ -1711,7 +1702,7 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card,
profile->dirty = 1; profile->dirty = 1;
return r; SC_FUNC_RETURN(ctx, 3, r);
} }
@ -1801,9 +1792,10 @@ sc_pkcs15init_store_data_object(struct sc_pkcs15_card *p15card,
static int static int
sc_pkcs15init_store_data(struct sc_pkcs15_card *p15card, sc_pkcs15init_store_data(struct sc_pkcs15_card *p15card,
struct sc_profile *profile, struct sc_profile *profile,
sc_pkcs15_object_t *object, sc_pkcs15_id_t *id, struct sc_pkcs15_object *object,
sc_pkcs15_der_t *data, struct sc_pkcs15_id *id,
sc_path_t *path) struct sc_pkcs15_der *data,
struct sc_path *path)
{ {
struct sc_context *ctx = p15card->card->ctx; struct sc_context *ctx = p15card->card->ctx;
struct sc_file *file = NULL; struct sc_file *file = NULL;
@ -2423,6 +2415,14 @@ select_object_path(sc_pkcs15_card_t *p15card, sc_profile_t *profile,
for (indx = TEMPLATE_INSTANTIATE_MIN_INDEX; indx <= TEMPLATE_INSTANTIATE_MAX_INDEX; indx++) { for (indx = TEMPLATE_INSTANTIATE_MIN_INDEX; indx <= TEMPLATE_INSTANTIATE_MAX_INDEX; indx++) {
indx_id.value[0] = indx; indx_id.value[0] = indx;
r = sc_profile_instantiate_template(profile, "key-domain", path, name, &indx_id, &file); r = sc_profile_instantiate_template(profile, "key-domain", path, name, &indx_id, &file);
if (r == SC_ERROR_TEMPLATE_NOT_FOUND) {
/* No template in 'key-domain' -- try to instantiate the template
* outside of the 'key-domain' scope. */
char t_name[0x40];
snprintf(t_name, sizeof(t_name), "template-%s", name);
r = sc_profile_get_file_instance(profile, t_name, indx, &file);
}
if (r == SC_ERROR_TEMPLATE_NOT_FOUND) if (r == SC_ERROR_TEMPLATE_NOT_FOUND)
SC_FUNC_RETURN(ctx, 3, SC_SUCCESS); SC_FUNC_RETURN(ctx, 3, SC_SUCCESS);
SC_TEST_RET(ctx, r, "Template instantiation error"); SC_TEST_RET(ctx, r, "Template instantiation error");

View File

@ -433,6 +433,7 @@ cosm_create_reference_data(struct sc_profile *profile, struct sc_card *card,
SC_FUNC_RETURN(card->ctx, 1, rv); SC_FUNC_RETURN(card->ctx, 1, rv);
} }
/* /*
* Update PIN * Update PIN
*/ */
@ -629,61 +630,87 @@ cosm_new_file(struct sc_profile *profile, struct sc_card *card,
} }
/*
* RSA key generation
*/
static int static int
cosm_old_generate_key(struct sc_profile *profile, struct sc_card *card, cosm_get_temporary_public_key_file(struct sc_card *card,
unsigned int idx, unsigned int keybits, struct sc_file *prvkey_file, struct sc_file **pubkey_file)
struct sc_pkcs15_pubkey *pubkey,
struct sc_pkcs15_prkey_info *info)
{ {
struct sc_cardctl_oberthur_genkey_info args; struct sc_context *ctx = card->ctx;
struct sc_file *prkf = NULL, *tmpf = NULL; const struct sc_acl_entry *entry = NULL;
struct sc_path path; struct sc_file *file = NULL;
int rv; int rv;
SC_FUNC_CALLED(card->ctx, 1); SC_FUNC_CALLED(card->ctx, 1);
sc_debug(card->ctx, "cosm_generate_key() index %i; nn %i\n", idx, keybits); if (!pubkey_file || !prvkey_file)
if (keybits < 512 || keybits > 2048 || (keybits%0x20)) { SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
sc_debug(card->ctx, "Unsupported key size %u\n", keybits);
SC_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key size"); file = sc_file_new();
} if (!file)
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_OUT_OF_MEMORY);
/* Get private key file from profile. */
rv = cosm_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, idx, &prkf); file->status = SC_FILE_STATUS_ACTIVATED;
SC_TEST_RET(card->ctx, rv, "cosm_generate_key() cannot allocate new file SC_PKCS15_TYPE_PRKEY_RSA"); file->type = SC_FILE_TYPE_INTERNAL_EF;
prkf->size = keybits; file->ef_structure = SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC;
file->id = 0x1012;
/* Access condition of private object DF. */ memcpy(&file->path, &prvkey_file->path, sizeof(file->path));
path = prkf->path; file->path.value[file->path.len - 2] = 0x10;
file->path.value[file->path.len - 1] = 0x12;
file->size = prvkey_file->size;
entry = sc_file_get_acl_entry(prvkey_file, SC_AC_OP_UPDATE);
rv = sc_file_add_acl_entry(file, SC_AC_OP_UPDATE, entry->method, entry->key_ref);
if (!rv)
rv = sc_file_add_acl_entry(file, SC_AC_OP_PSO_ENCRYPT, SC_AC_NONE, 0);
if (!rv)
rv = sc_file_add_acl_entry(file, SC_AC_OP_PSO_VERIFY_SIGNATURE, SC_AC_NONE, 0);
if (!rv)
rv = sc_file_add_acl_entry(file, SC_AC_OP_EXTERNAL_AUTHENTICATE, SC_AC_NONE, 0);
SC_TEST_RET(ctx, rv, "Failed to add ACL entry to the temporary public key file");
*pubkey_file = file;
SC_FUNC_RETURN(card->ctx, 1, rv);
}
static int
cosm_generate_key(struct sc_profile *profile, struct sc_card *card,
struct sc_pkcs15_object *object,
struct sc_pkcs15_pubkey *pubkey)
{
struct sc_context *ctx = card->ctx;
struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data;
struct sc_file *file = NULL;
struct sc_cardctl_oberthur_genkey_info args;
struct sc_file *prkf = NULL, *tmpf = NULL;
struct sc_path path;
int rv = 0;
SC_FUNC_CALLED(card->ctx, 1);
if (object->type != SC_PKCS15_TYPE_PRKEY_RSA)
SC_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Generate key failed: RSA only supported");
path = key_info->path;
path.len -= 2; path.len -= 2;
rv = sc_select_file(card, &path, &tmpf); rv = sc_select_file(card, &path, &tmpf);
SC_TEST_RET(card->ctx, rv, "cosm_generate_key() no private object DF"); SC_TEST_RET(card->ctx, rv, "Cannot generate key: failed to select private object DF");
rv = sc_pkcs15init_authenticate(profile, card, tmpf, SC_AC_OP_CRYPTO); rv = sc_pkcs15init_authenticate(profile, card, tmpf, SC_AC_OP_CRYPTO);
SC_TEST_RET(card->ctx, rv, "cosm_generate_key() pkcs15init_authenticate(SC_AC_OP_CRYPTO) failed"); SC_TEST_RET(card->ctx, rv, "Cannot generate key: 'CRYPTO' authentication failed");
rv = sc_pkcs15init_authenticate(profile, card, tmpf, SC_AC_OP_CREATE); rv = sc_pkcs15init_authenticate(profile, card, tmpf, SC_AC_OP_CREATE);
SC_TEST_RET(card->ctx, rv, "cosm_generate_key() pkcs15init_authenticate(SC_AC_OP_CREATE) failed"); SC_TEST_RET(card->ctx, rv, "Cannot generate key: 'CREATE' authentication failed");
sc_file_free(tmpf); sc_file_free(tmpf);
rv = sc_select_file(card, &key_info->path, &prkf);
SC_TEST_RET(card->ctx, rv, "Failed to generate key: cannot select private key file");
/* In the private key DF create the temporary public RSA file. */ /* In the private key DF create the temporary public RSA file. */
sc_debug(card->ctx, "cosm_generate_key() ready to create temporary public key\n"); rv = cosm_get_temporary_public_key_file(card, prkf, &tmpf);
sc_file_dup(&tmpf, prkf); SC_TEST_RET(card->ctx, rv, "Error while getting temporary public key file");
if (!tmpf)
SC_TEST_RET(card->ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot duplicate private key file");
tmpf->type = SC_FILE_TYPE_INTERNAL_EF;
tmpf->ef_structure = SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC;
tmpf->id = 0x1012;
tmpf->path.value[tmpf->path.len - 2] = 0x10;
tmpf->path.value[tmpf->path.len - 1] = 0x12;
rv = sc_pkcs15init_create_file(profile, card, prkf);
SC_TEST_RET(card->ctx, rv, "cosm_generate_key() failed to create private key EF");
rv = sc_pkcs15init_create_file(profile, card, tmpf); rv = sc_pkcs15init_create_file(profile, card, tmpf);
SC_TEST_RET(card->ctx, rv, "cosm_generate_key() failed to create temporary public key EF"); SC_TEST_RET(card->ctx, rv, "cosm_generate_key() failed to create temporary public key EF");
@ -691,9 +718,9 @@ cosm_old_generate_key(struct sc_profile *profile, struct sc_card *card,
args.id_prv = prkf->id; args.id_prv = prkf->id;
args.id_pub = tmpf->id; args.id_pub = tmpf->id;
args.exponent = 0x10001; args.exponent = 0x10001;
args.key_bits = keybits; args.key_bits = key_info->modulus_length;
args.pubkey_len = keybits/8; args.pubkey_len = key_info->modulus_length / 8;
args.pubkey = (unsigned char *) malloc(keybits/8); args.pubkey = (unsigned char *) malloc(key_info->modulus_length / 8);
if (!args.pubkey) if (!args.pubkey)
SC_TEST_RET(card->ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot allocate pubkey"); SC_TEST_RET(card->ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot allocate pubkey");
@ -702,8 +729,8 @@ cosm_old_generate_key(struct sc_profile *profile, struct sc_card *card,
/* extract public key */ /* extract public key */
pubkey->algorithm = SC_ALGORITHM_RSA; pubkey->algorithm = SC_ALGORITHM_RSA;
pubkey->u.rsa.modulus.len = keybits / 8; pubkey->u.rsa.modulus.len = key_info->modulus_length / 8;
pubkey->u.rsa.modulus.data = (unsigned char *) malloc(keybits / 8); pubkey->u.rsa.modulus.data = (unsigned char *) malloc(key_info->modulus_length / 8);
if (!pubkey->u.rsa.modulus.data) if (!pubkey->u.rsa.modulus.data)
SC_TEST_RET(card->ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot allocate modulus buf"); SC_TEST_RET(card->ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot allocate modulus buf");
@ -715,118 +742,135 @@ cosm_old_generate_key(struct sc_profile *profile, struct sc_card *card,
memcpy(pubkey->u.rsa.exponent.data, "\x01\x00\x01", 3); memcpy(pubkey->u.rsa.exponent.data, "\x01\x00\x01", 3);
memcpy(pubkey->u.rsa.modulus.data, args.pubkey, args.pubkey_len); memcpy(pubkey->u.rsa.modulus.data, args.pubkey, args.pubkey_len);
info->key_reference = 1; key_info->key_reference = 1;
info->path = prkf->path; key_info->path = prkf->path;
sc_debug(card->ctx, "cosm_generate_key() now delete temporary public key\n"); sc_debug(card->ctx, "cosm_generate_key() now delete temporary public key\n");
rv = cosm_delete_file(card, profile, tmpf); rv = cosm_delete_file(card, profile, tmpf);
if (tmpf) sc_file_free(tmpf);
sc_file_free(tmpf); sc_file_free(prkf);
if (prkf)
sc_file_free(prkf);
SC_FUNC_RETURN(card->ctx, 1, rv); SC_FUNC_RETURN(card->ctx, 1, rv);
} }
/*
* Create private key file
*/
static int
cosm_create_key(struct sc_profile *profile, struct sc_card *card,
struct sc_pkcs15_object *object)
{
struct sc_context *ctx = card->ctx;
struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data;
struct sc_file *file = NULL;
int rv = 0;
SC_FUNC_CALLED(ctx, 1);
if (object->type != SC_PKCS15_TYPE_PRKEY_RSA)
SC_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "Create key failed: RSA only supported");
sc_debug(ctx, "create private key ID:%s\n", sc_pkcs15_print_id(&key_info->id));
/* Here, the path of private key file should be defined.
* Neverthelles, we need to instanciate private key to get the ACLs. */
rv = cosm_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, key_info->key_reference, &file);
SC_TEST_RET(ctx, rv, "Cannot create key: failed to allocate new key object");
file->size = key_info->modulus_length;
memcpy(&file->path, &key_info->path, sizeof(file->path));
file->id = file->path.value[file->path.len - 2] * 0x100
+ file->path.value[file->path.len - 1];
sc_debug(ctx, "Path of private key file to create %s\n", sc_print_path(&file->path));
rv = sc_select_file(card, &file->path, NULL);
if (rv == 0) {
rv = cosm_delete_file(card, profile, file);
SC_TEST_RET(ctx, rv, "Failed to delete private key file");
}
else if (rv != SC_ERROR_FILE_NOT_FOUND) {
SC_TEST_RET(ctx, rv, "Select private key file error");
}
rv = sc_pkcs15init_create_file(profile, card, file);
SC_TEST_RET(ctx, rv, "Failed to create private key file");
key_info->key_reference = file->path.value[file->path.len - 1];
sc_file_free(file);
SC_FUNC_RETURN(ctx, 1, rv);
}
/* /*
* Store a private key * Store a private key
*/ */
static int static int
cosm_new_key(struct sc_profile *profile, struct sc_card *card, cosm_store_key(struct sc_profile *profile, struct sc_card *card,
struct sc_pkcs15_prkey *key, unsigned int idx, struct sc_pkcs15_object *object,
struct sc_pkcs15_prkey_info *info) struct sc_pkcs15_prkey *prkey)
{ {
struct sc_file *prvfile = NULL; struct sc_context *ctx = card->ctx;
struct sc_pkcs15_prkey_rsa *rsa = NULL; struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data;
struct sc_file *file = NULL;
struct sc_cardctl_oberthur_updatekey_info update_info; struct sc_cardctl_oberthur_updatekey_info update_info;
char pbuf[SC_MAX_PATH_STRING_SIZE]; int rv = 0;
int rv;
SC_FUNC_CALLED(card->ctx, 1); SC_FUNC_CALLED(ctx, 1);
sc_debug(card->ctx, "index %i; id %s\n", idx, sc_pkcs15_print_id(&info->id)); if (object->type != SC_PKCS15_TYPE_PRKEY_RSA || prkey->algorithm != SC_ALGORITHM_RSA)
if (key->algorithm != SC_ALGORITHM_RSA) SC_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Store key failed: RSA only supported");
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
/* Create and populate the private part. */ sc_debug(ctx, "store key with ID:%s and path:%s\n", sc_pkcs15_print_id(&key_info->id),
rv = cosm_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, idx, sc_print_path(&key_info->path));
&prvfile);
SC_TEST_RET(card->ctx, rv, "Update RSA: cosm_new_file failed"); rv = sc_select_file(card, &key_info->path, &file);
SC_TEST_RET(ctx, rv, "Cannot store key: select key file failed");
rv = sc_path_print(pbuf, sizeof(pbuf), &prvfile->path); rv = sc_pkcs15init_authenticate(profile, card, file, SC_AC_OP_UPDATE);
sc_debug(card->ctx, "rv %i\n", rv); SC_TEST_RET(ctx, rv, "No authorisation to store private key");
if (rv != SC_SUCCESS)
pbuf[0] = '\0';
sc_debug(card->ctx, " prvfile->id %i; path=%s\n", prvfile->id, pbuf);
rsa = &key->u.rsa; if (key_info->id.len > sizeof(update_info.id))
prvfile->size = rsa->modulus.len << 3;
rv = sc_select_file(card, &prvfile->path, NULL);
sc_debug(card->ctx, "rv %i", rv);
if (rv == SC_ERROR_FILE_NOT_FOUND) {
sc_debug(card->ctx, "Before create file");
rv = sc_pkcs15init_create_file(profile, card, prvfile);
}
SC_TEST_RET(card->ctx, rv, "Update RSA: select/create key file failed");
rv = sc_pkcs15init_authenticate(profile, card, prvfile, SC_AC_OP_UPDATE);
SC_TEST_RET(card->ctx, rv, "Update RSA: no authorisation");
#ifdef ENABLE_OPENSSL
/* Mozilla style ID */
if (!info->id.len) {
SHA1(rsa->modulus.data, rsa->modulus.len, info->id.value);
info->id.len = SHA_DIGEST_LENGTH;
sc_debug(card->ctx, "ID: %s\n", sc_pkcs15_print_id(&info->id));
}
#endif
if (info->id.len > sizeof(update_info.id))
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS); SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
memset(&update_info, 0, sizeof(update_info)); memset(&update_info, 0, sizeof(update_info));
update_info.type = SC_CARDCTL_OBERTHUR_KEY_RSA_CRT; update_info.type = SC_CARDCTL_OBERTHUR_KEY_RSA_CRT;
update_info.data = (void *)rsa; update_info.data = (void *)&prkey->u.rsa;
update_info.data_len = sizeof(void *); update_info.data_len = sizeof(void *);
update_info.id_len = info->id.len; update_info.id_len = key_info->id.len;
memcpy(update_info.id, info->id.value, update_info.id_len); memcpy(update_info.id, key_info->id.value, update_info.id_len);
rv = sc_card_ctl(card, SC_CARDCTL_OBERTHUR_UPDATE_KEY, &update_info); rv = sc_card_ctl(card, SC_CARDCTL_OBERTHUR_UPDATE_KEY, &update_info);
SC_TEST_RET(card->ctx, rv, "Update KEY failed"); SC_TEST_RET(ctx, rv, "Cannot update private key");
info->path = prvfile->path; if (file)
info->modulus_length = rsa->modulus.len << 3; sc_file_free(file);
if (prvfile) SC_FUNC_RETURN(ctx, 1, rv);
sc_file_free(prvfile);
SC_FUNC_RETURN(card->ctx, 1, rv);
} }
static struct sc_pkcs15init_operations static struct sc_pkcs15init_operations
sc_pkcs15init_oberthur_operations = { sc_pkcs15init_oberthur_operations = {
cosm_erase_card, cosm_erase_card,
NULL, /* init_card */ NULL, /* init_card */
NULL, /* create_dir */ NULL, /* create_dir */
NULL, /* create_domain */ NULL, /* create_domain */
cosm_select_pin_reference, cosm_select_pin_reference,
cosm_create_pin, cosm_create_pin,
NULL, /* select_key_reference */ NULL, /* select_key_reference */
NULL, /* create_key */ cosm_create_key, /* create_key */
NULL, /* store_key */ cosm_store_key, /* store_key */
NULL, /* generate_key */ cosm_generate_key, /* generate_key */
NULL, NULL,
NULL, /* encode private/public key */ NULL, /* encode private/public key */
NULL, /* finalize_card */ NULL, /* finalize_card */
cosm_init_app, /* old */ cosm_init_app, /* old */
NULL, /* new_pin */ NULL, /* new_pin */
cosm_new_key, NULL, /* cosm_new_key, */
cosm_new_file, NULL, /* cosm_new_file, */
cosm_old_generate_key, NULL, /* cosm_old_generate_key, */
NULL NULL
}; };