pkcs15init: call sc_profile_finish() with 'app-info' data ...

call sc_profile_finish() with application info data as an argument;
in delete-by-path procedure, when getting authorization to delete file, make distinction between 'DELETE' and 'DELETE-SELF';
call card specific 'store' handler updating PrKDF and PubKDF files;
deduce the private key pkcs#15 attributes (like subject) from the friend certificate;
ignore SM authentication type when getting authorisation for operation;
copy GUID from the object create data to the pkcs#15 object attributes.
This commit is contained in:
Viktor Tarasov 2012-05-31 18:13:20 +02:00
parent 7819e5ab89
commit 635be92a0c
1 changed files with 113 additions and 47 deletions

View File

@ -365,7 +365,7 @@ sc_pkcs15init_bind(struct sc_card *card, const char *name, const char *profile_o
break;
}
r = sc_profile_finish(profile, NULL);
r = sc_profile_finish(profile, app_info);
if (r < 0)
sc_log(ctx, "Failed to finalize profile: %s", sc_strerror(r));
} while (0);
@ -422,8 +422,7 @@ sc_pkcs15init_unbind(struct sc_profile *profile)
void
sc_pkcs15init_set_p15card(struct sc_profile *profile,
struct sc_pkcs15_card *p15card)
sc_pkcs15init_set_p15card(struct sc_profile *profile, struct sc_pkcs15_card *p15card)
{
struct sc_context *ctx = p15card->card->ctx;
struct sc_pkcs15_object *p15objects[10];
@ -451,8 +450,7 @@ sc_pkcs15init_set_p15card(struct sc_profile *profile,
if (!sc_select_file(p15card->card, &auth_info->path, &file)) {
char pin_name[16];
sprintf(pin_name, "pin-dir-%02X%02X",
file->path.value[file->path.len - 2],
sprintf(pin_name, "pin-dir-%02X%02X", file->path.value[file->path.len - 2],
file->path.value[file->path.len - 1]);
sc_log(ctx, "add '%s' to profile file list", pin_name);
sc_profile_add_file(profile, pin_name, file);
@ -540,13 +538,13 @@ sc_pkcs15init_erase_card_recursively(struct sc_pkcs15_card *p15card,
int
sc_pkcs15init_delete_by_path(struct sc_profile *profile,
struct sc_pkcs15_card *p15card, const struct sc_path *file_path)
sc_pkcs15init_delete_by_path(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
const struct sc_path *file_path)
{
struct sc_context *ctx = p15card->card->ctx;
struct sc_file *parent = NULL, *file = NULL;
struct sc_path path;
int rv;
int rv, file_type = SC_FILE_TYPE_DF;
LOG_FUNC_CALLED(ctx);
sc_log(ctx, "trying to delete '%s'", sc_print_path(file_path));
@ -555,19 +553,27 @@ sc_pkcs15init_delete_by_path(struct sc_profile *profile,
* for the others the 'DELETE' ACL of parent.
* Let's start from the file's 'DELETE' ACL.
*
* FIXME: will it be better to introduce the ACLs 'DELETE-CHILD' and 'DELETE-ITSELF',
* or dedicated card flag ?
* TODO: 'DELETE_SELF' exists. Proper solution would be to use this acl by every
* card (driver and profile) that uses self delete ACL.
*/
/* Select the file itself */
path = *file_path;
rv = sc_select_file(p15card->card, &path, &file);
LOG_TEST_RET(ctx, rv, "cannot select file to delete");
rv = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_DELETE);
sc_file_free(file);
if (rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
if (sc_file_get_acl_entry(file, SC_AC_OP_DELETE_SELF)) {
sc_log(ctx, "Found 'DELETE-SELF' acl");
rv = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_DELETE_SELF);
sc_file_free(file);
}
else if (sc_file_get_acl_entry(file, SC_AC_OP_DELETE)) {
sc_log(ctx, "Found 'DELETE' acl");
rv = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_DELETE);
sc_file_free(file);
}
else {
sc_log(ctx, "Try to get the parent's 'DELETE' access");
file_type = file->type;
if (file_path->len >= 2) {
/* Select the parent DF */
path.len -= 2;
@ -587,6 +593,13 @@ sc_pkcs15init_delete_by_path(struct sc_profile *profile,
path.value[1] = file_path->value[file_path->len - 1];
path.len = 2;
/* Reselect file to delete if the parent DF was selected and it's not DF. */
if (file_type != SC_FILE_TYPE_DF) {
rv = sc_select_file(p15card->card, &path, &file);
LOG_TEST_RET(ctx, rv, "cannot select file to delete");
}
sc_log(ctx, "Now really delete file");
rv = sc_delete_file(p15card->card, &path);
LOG_FUNC_RETURN(ctx, rv);
}
@ -1203,6 +1216,7 @@ sc_pkcs15init_init_prkdf(struct sc_pkcs15_card *p15card,
/* See if we need to select a key reference for this object */
if (profile->ops->select_key_reference) {
while (1) {
sc_log(ctx, "Look for usable key reference starting from %i", key_info->key_reference);
r = profile->ops->select_key_reference(profile, p15card, key_info);
LOG_TEST_RET(ctx, r, "Failed to select card specific key reference");
@ -1269,6 +1283,12 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card, struct sc_profile *pr
LOG_TEST_RET(ctx, r, "Set up private key object error");
key_info = (struct sc_pkcs15_prkey_info *) object->data;
if (keygen_args->prkey_args.guid) {
object->guid = strdup(keygen_args->prkey_args.guid);
if (!object->guid)
LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate guid");
sc_log(ctx, "new key GUID: '%s'", object->guid);
}
/* Set up the PuKDF info. The public key will be filled in
* by the card driver's generate_key function called below.
@ -1308,6 +1328,13 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card, struct sc_profile *pr
r = sc_pkcs15init_add_object(p15card, profile, SC_PKCS15_PRKDF, object);
LOG_TEST_RET(ctx, r, "Failed to add generated private key object");
if (!r && profile->ops->emu_store_data) {
r = profile->ops->emu_store_data(p15card, profile, object, NULL, NULL);
if (r == SC_ERROR_NOT_IMPLEMENTED)
r = SC_SUCCESS;
LOG_TEST_RET(ctx, r, "Card specific 'store data' failed");
}
r = sc_pkcs15init_store_public_key(p15card, profile, &pubkey_args, NULL);
LOG_TEST_RET(ctx, r, "Failed to store public key");
@ -1383,8 +1410,27 @@ sc_pkcs15init_store_private_key(struct sc_pkcs15_card *p15card,
r = profile->ops->store_key(profile, p15card, object, &key);
LOG_TEST_RET(ctx, r, "Card specific 'store key' failed");
sc_pkcs15_free_object_content(object);
r = sc_pkcs15init_encode_prvkey_content(p15card, &key, object);
LOG_TEST_RET(ctx, r, "Failed to encode public key");
/* Now update the PrKDF */
r = sc_pkcs15init_add_object(p15card, profile, SC_PKCS15_PRKDF, object);
LOG_TEST_RET(ctx, r, "Failed to add new private key PKCS#15 object");
if (keyargs->guid) {
object->guid = strdup(keyargs->guid);
if (!object->guid)
LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate guid");
sc_log(ctx, "new key GUID: '%s'", object->guid);
}
if (!r && profile->ops->emu_store_data) {
r = profile->ops->emu_store_data(p15card, profile, object, NULL, NULL);
if (r == SC_ERROR_NOT_IMPLEMENTED)
r = SC_SUCCESS;
LOG_TEST_RET(ctx, r, "Card specific 'store data' failed");
}
if (r >= 0 && res_obj)
*res_obj = object;
@ -1529,9 +1575,10 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card,
struct sc_pkcs15_object **res_obj)
{
struct sc_context *ctx = p15card->card->ctx;
struct sc_pkcs15_cert_info *cert_info;
struct sc_pkcs15_object *object;
const char *label;
struct sc_pkcs15_cert_info *cert_info = NULL;
struct sc_pkcs15_object *object = NULL;
struct sc_pkcs15_object *key_object = NULL;
const char *label = NULL;
int r;
LOG_FUNC_CALLED(ctx);
@ -1569,11 +1616,24 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card,
/* TODO: update private key PKCS#15 object with the certificate's attributes */
}
if (r < 0)
sc_pkcs15_free_object(object);
if (r >= 0) {
r = sc_pkcs15_prkey_attrs_from_cert(p15card, object, &key_object);
if (r) {
r = 0;
}
else if (key_object) {
r = sc_pkcs15init_update_any_df(p15card, profile, key_object->df, 0);
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "sc_pkcs15init_store_certificate() update_any_df returned %i", r);
}
}
if (r >= 0 && res_obj)
if (r < 0) {
sc_pkcs15_remove_object(p15card, object);
sc_pkcs15_free_object(object);
}
else if (res_obj) {
*res_obj = object;
}
profile->dirty = 1;
@ -2296,14 +2356,13 @@ select_object_path(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
struct sc_context *ctx = p15card->card->ctx;
struct sc_file *file;
struct sc_pkcs15_object *objs[32];
struct sc_pkcs15_id indx_id;
struct sc_path obj_path;
int ii, r, nn_objs, indx;
const char *name;
struct sc_pkcs15_id indx_id;
struct sc_path obj_path;
int ii, r, nn_objs, indx;
const char *name;
LOG_FUNC_CALLED(ctx);
r = sc_pkcs15_get_objects(p15card, obj->type & SC_PKCS15_TYPE_CLASS_MASK,
objs, sizeof(objs)/sizeof(objs[0]));
r = sc_pkcs15_get_objects(p15card, obj->type & SC_PKCS15_TYPE_CLASS_MASK, objs, sizeof(objs)/sizeof(objs[0]));
LOG_TEST_RET(ctx, r, "Get PKCS#15 objects error");
nn_objs = r;
@ -2545,8 +2604,7 @@ sc_pkcs15init_update_lastupdate(struct sc_pkcs15_card *p15card, struct sc_profil
static int
sc_pkcs15init_update_odf(struct sc_pkcs15_card *p15card,
struct sc_profile *profile)
sc_pkcs15init_update_odf(struct sc_pkcs15_card *p15card, struct sc_profile *profile)
{
struct sc_context *ctx = p15card->card->ctx;
unsigned char *buf = NULL;
@ -2556,8 +2614,7 @@ sc_pkcs15init_update_odf(struct sc_pkcs15_card *p15card,
LOG_FUNC_CALLED(ctx);
r = sc_pkcs15_encode_odf(ctx, p15card, &buf, &size);
if (r >= 0)
r = sc_pkcs15init_update_file(profile, p15card,
p15card->file_odf, buf, size);
r = sc_pkcs15init_update_file(profile, p15card, p15card->file_odf, buf, size);
if (buf)
free(buf);
LOG_FUNC_RETURN(ctx, r);
@ -2614,7 +2671,7 @@ sc_pkcs15init_update_any_df(struct sc_pkcs15_card *p15card,
r = sc_pkcs15init_update_odf(p15card, profile);
LOG_TEST_RET(ctx, r, "Failed to encode or update ODF");
LOG_FUNC_RETURN(ctx, r);
LOG_FUNC_RETURN(ctx, r > 0 ? SC_SUCCESS : r);
}
/*
@ -2670,7 +2727,7 @@ sc_pkcs15init_add_object(struct sc_pkcs15_card *p15card, struct sc_profile *prof
if (r < 0 && object_added)
sc_pkcs15_remove_object(p15card, object);
LOG_FUNC_RETURN(ctx, r);
LOG_FUNC_RETURN(ctx, r > 0 ? SC_SUCCESS : r);
}
@ -3154,7 +3211,7 @@ sc_pkcs15init_verify_secret(struct sc_profile *profile, struct sc_pkcs15_card *p
if (pin_obj->content.len > pinsize)
LOG_TEST_RET(ctx, SC_ERROR_BUFFER_TOO_SMALL, "PIN buffer is too small");
memcpy(pinbuf, pin_obj->content.value, pin_obj->content.len);
pinsize = pin_obj->content.len;
pinsize = pin_obj->content.len;
sc_log(ctx, "'ve got '%s' value from cache", ident);
goto found;
}
@ -3170,6 +3227,11 @@ sc_pkcs15init_verify_secret(struct sc_profile *profile, struct sc_pkcs15_card *p
sc_log(ctx, "'get_pin' callback returned %i; pinsize:%i", r, pinsize);
}
break;
case SC_AC_SCB:
case SC_AC_PRO:
pinsize = 0;
r = 0;
break;
default:
r = sc_pkcs15init_get_transport_key(profile, p15card, type, reference, pinbuf, &pinsize);
break;
@ -3177,12 +3239,16 @@ sc_pkcs15init_verify_secret(struct sc_profile *profile, struct sc_pkcs15_card *p
if (r == SC_ERROR_OBJECT_NOT_FOUND) {
if (p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD)
r = 0, use_pinpad = 1;
r = 0, use_pinpad = 1;
else
r = SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
}
LOG_TEST_RET(ctx, r, "Failed to get secret");
if (type == SC_AC_PRO) {
sc_log(ctx, "No 'verify' for secure messaging");
LOG_FUNC_RETURN(ctx, r);
}
found:
if (pin_obj) {
@ -3415,7 +3481,7 @@ sc_pkcs15init_update_file(struct sc_profile *profile,
if (copy)
free(copy);
sc_file_free(selected_file);
return r;
LOG_FUNC_RETURN(ctx, r);
}
/*
@ -3549,7 +3615,7 @@ sc_pkcs15init_get_pin_path(struct sc_pkcs15_card *p15card,
if (r < 0)
return r;
*path = ((struct sc_pkcs15_auth_info *) obj->data)->path;
return 0;
return SC_SUCCESS;
}
@ -3557,7 +3623,7 @@ int
sc_pkcs15init_get_pin_info(struct sc_profile *profile, int id, struct sc_pkcs15_auth_info *pin)
{
sc_profile_get_pin_info(profile, id, pin);
return 0;
return SC_SUCCESS;
}
@ -3565,14 +3631,14 @@ int
sc_pkcs15init_get_manufacturer(struct sc_profile *profile, const char **res)
{
*res = profile->p15_spec->tokeninfo->manufacturer_id;
return 0;
return SC_SUCCESS;
}
int
sc_pkcs15init_get_serial(struct sc_profile *profile, const char **res)
{
*res = profile->p15_spec->tokeninfo->serial_number;
return 0;
return SC_SUCCESS;
}
@ -3583,7 +3649,7 @@ sc_pkcs15init_set_serial(struct sc_profile *profile, const char *serial)
free(profile->p15_spec->tokeninfo->serial_number);
profile->p15_spec->tokeninfo->serial_number = strdup(serial);
return 0;
return SC_SUCCESS;
}
@ -3606,13 +3672,13 @@ sc_pkcs15init_sanity_check(struct sc_pkcs15_card *p15card, struct sc_profile *pr
static int
sc_pkcs15init_qualify_pin(struct sc_card *card, const char *pin_name,
unsigned int pin_len, struct sc_pkcs15_auth_info *auth_info)
unsigned int pin_len, struct sc_pkcs15_auth_info *auth_info)
{
struct sc_context *ctx = card->ctx;
struct sc_pkcs15_pin_attributes *pin_attrs;
if (pin_len == 0 || auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
return 0;
return SC_SUCCESS;
pin_attrs = &auth_info->attrs.pin;
@ -3625,7 +3691,7 @@ sc_pkcs15init_qualify_pin(struct sc_card *card, const char *pin_name,
return SC_ERROR_WRONG_LENGTH;
}
return 0;
return SC_SUCCESS;
}
@ -3675,7 +3741,7 @@ set_info_string(char **strp, const u8 *p, size_t len)
if (*strp)
free(*strp);
*strp = s;
return 0;
return SC_SUCCESS;
}
/*
@ -3689,8 +3755,7 @@ set_info_string(char **strp, const u8 *p, size_t len)
*/
static int
sc_pkcs15init_parse_info(struct sc_card *card,
const unsigned char *p, size_t len,
struct sc_profile *profile)
const unsigned char *p, size_t len, struct sc_profile *profile)
{
unsigned char tag;
const unsigned char *end;
@ -3742,6 +3807,7 @@ error:
return SC_ERROR_PKCS15INIT;
}
static int
do_encode_string(unsigned char **memp, unsigned char *end,
unsigned char tag, const char *s)