diff --git a/src/pkcs15init/pkcs15-cflex.c b/src/pkcs15init/pkcs15-cflex.c index 7fb94c59..94998b5d 100644 --- a/src/pkcs15init/pkcs15-cflex.c +++ b/src/pkcs15init/pkcs15-cflex.c @@ -886,7 +886,8 @@ static struct sc_pkcs15init_operations sc_pkcs15init_cyberflex_operations = { cyberflex_encode_private_key, cyberflex_encode_public_key, NULL, /* finalize_card */ - NULL, NULL, NULL, NULL, NULL /* old style api */ + NULL, NULL, NULL, NULL, NULL, /* old style api */ + NULL /* delete_object */ }; struct sc_pkcs15init_operations * diff --git a/src/pkcs15init/pkcs15-etoken.c b/src/pkcs15init/pkcs15-etoken.c index 978a8b3f..efe55393 100644 --- a/src/pkcs15init/pkcs15-etoken.c +++ b/src/pkcs15init/pkcs15-etoken.c @@ -624,7 +624,8 @@ static struct sc_pkcs15init_operations sc_pkcs15init_etoken_operations = { etoken_generate_key, NULL, NULL, /* encode private/public key */ NULL, /* finalize_card */ - NULL, NULL, NULL, NULL, NULL /* old style api */ + NULL, NULL, NULL, NULL, NULL, /* old style api */ + NULL /* delete_object */ }; struct sc_pkcs15init_operations * diff --git a/src/pkcs15init/pkcs15-gpk.c b/src/pkcs15init/pkcs15-gpk.c index 5f52d764..e1b424d8 100644 --- a/src/pkcs15init/pkcs15-gpk.c +++ b/src/pkcs15init/pkcs15-gpk.c @@ -1131,7 +1131,8 @@ static struct sc_pkcs15init_operations sc_pkcs15init_gpk_operations = { gpk_generate_key, NULL, NULL, /* encode private/public key */ NULL, /* finalize_card */ - NULL, NULL, NULL, NULL, NULL /* old style api */ + NULL, NULL, NULL, NULL, NULL, /* old style api */ + NULL /* delete_object */ }; struct sc_pkcs15init_operations *sc_pkcs15init_get_gpk_ops(void) diff --git a/src/pkcs15init/pkcs15-init.h b/src/pkcs15init/pkcs15-init.h index 75661de9..6403dfbd 100644 --- a/src/pkcs15init/pkcs15-init.h +++ b/src/pkcs15init/pkcs15-init.h @@ -159,6 +159,11 @@ struct sc_pkcs15init_operations { sc_pkcs15_pubkey_t *pubkey_res, struct sc_pkcs15_prkey_info *); + /* + * Delete object + */ + int (*delete_object)(struct sc_profile *, struct sc_card *, + unsigned int type, const void *data, const sc_path_t *path); }; /* Do not change these or reorder these */ @@ -317,6 +322,9 @@ extern int sc_pkcs15init_change_attrib(struct sc_pkcs15_card *p15card, int new_attrib_type, void *new_value, int new_len); +extern int sc_pkcs15init_delete_object(sc_pkcs15_card_t *p15card, + sc_profile_t *profile, + sc_pkcs15_object_t *obj); extern int sc_pkcs15init_create_file(struct sc_profile *, struct sc_card *, struct sc_file *); @@ -344,6 +352,8 @@ extern int sc_pkcs15init_set_pin_data(struct sc_profile *, int, const u8 *, size_t); extern int sc_pkcs15init_verify_key(struct sc_profile *, struct sc_card *, sc_file_t *, unsigned int, unsigned int); +extern int sc_pkcs15init_delete_by_path(struct sc_profile *, + struct sc_card *, const sc_path_t *path); /* Erasing the card structure via rm -rf */ extern int sc_pkcs15init_erase_card_recursively(struct sc_card *, diff --git a/src/pkcs15init/pkcs15-jcop.c b/src/pkcs15init/pkcs15-jcop.c index 34d4a34b..a9268d54 100644 --- a/src/pkcs15init/pkcs15-jcop.c +++ b/src/pkcs15init/pkcs15-jcop.c @@ -357,7 +357,8 @@ static struct sc_pkcs15init_operations sc_pkcs15init_jcop_operations = { NULL, NULL, /* encode private/public key */ NULL, /* finalize_card */ jcop_init_app, /* old */ - NULL, NULL, NULL, NULL /* rest of old style api */ + NULL, NULL, NULL, NULL, /* rest of old style api */ + NULL /* delete_object */ }; struct sc_pkcs15init_operations *sc_pkcs15init_get_jcop_ops(void) diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index bd89b8a4..a0486323 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -447,6 +447,48 @@ out: /* Forget any cached keys, the objects on card are all gone. */ return r; } +int sc_pkcs15init_delete_by_path(struct sc_profile *profile, + struct sc_card *card, const sc_path_t *file_path) +{ + sc_file_t *parent, *file; + sc_path_t path; + int r; + + if (file_path->len >= 2) { + /* Select the parent DF */ + path = *file_path; + path.len -= 2; + r = sc_select_file(card, &path, &parent); + if (r < 0) + return r; + + r = sc_pkcs15init_authenticate(profile, card, parent, SC_AC_OP_DELETE); + sc_file_free(parent); + if (r < 0) + return r; + } + + /* Select the file itself */ + path = *file_path; + r = sc_select_file(card, &path, &file); + if (r < 0) + return r; + + r = sc_pkcs15init_authenticate(profile, card, file, SC_AC_OP_DELETE); + sc_file_free(file); + if (r < 0) + return r; + + memset(&path, 0, sizeof(path)); + path.type = SC_PATH_TYPE_FILE_ID; + path.value[0] = file_path->value[file_path->len - 2]; + path.value[1] = file_path->value[file_path->len - 1]; + path.len = 2; + + r = sc_delete_file(card, &path); + return r; +} + /* * Try to delete a file (and, in the DF case, its contents). * Note that this will not work if a pkcs#15 file's ERASE AC @@ -505,11 +547,13 @@ sc_pkcs15init_rmdir(sc_card_t *card, struct sc_profile *profile, if (r < 0) return r; + r = sc_pkcs15init_authenticate(profile, card, df, SC_AC_OP_DELETE); + if (r < 0) { + sc_file_free(parent); + return r; + } r = sc_pkcs15init_authenticate(profile, card, parent, SC_AC_OP_DELETE); sc_file_free(parent); - if (r < 0) - return r; - r = sc_pkcs15init_authenticate(profile, card, df, SC_AC_OP_ERASE); if (r < 0) return r; @@ -2478,6 +2522,57 @@ sc_pkcs15init_change_attrib(struct sc_pkcs15_card *p15card, return r < 0 ? r : 0; } +int sc_pkcs15init_delete_object(sc_pkcs15_card_t *p15card, + sc_profile_t *profile, sc_pkcs15_object_t *obj) +{ + sc_path_t path; + struct sc_pkcs15_df *df; + int r; + + if (profile->ops->delete_object == NULL) + return SC_ERROR_NOT_SUPPORTED; + + switch(obj->type & SC_PKCS15_TYPE_CLASS_MASK) + { + case SC_PKCS15_TYPE_PUBKEY: + path = ((sc_pkcs15_pubkey_info_t *)obj->data)->path; + break; + case SC_PKCS15_TYPE_PRKEY: + path = ((sc_pkcs15_prkey_info_t *)obj->data)->path; + break; + case SC_PKCS15_TYPE_CERT: + path = ((sc_pkcs15_cert_info_t *)obj->data)->path; + break; + case SC_PKCS15_TYPE_DATA_OBJECT: + path = ((sc_pkcs15_data_info_t *)obj->data)->path; + break; + default: + return SC_ERROR_NOT_SUPPORTED; + } + + /* Set the SO PIN reference from card */ + if ((r = set_so_pin_from_card(p15card, profile)) < 0) + return r; + + r = profile->ops->delete_object(profile, p15card->card, + obj->type, obj->data, &path); + if (r < 0) { + sc_error(p15card->card->ctx, "ops->delete_object() failed: %d", r); + return r; + } + + /* Get the DF we're part of. If there's no DF, fine, we haven't + * been added yet. */ + if ((df = obj->df) == NULL) + return 0; + + /* Unlink the object and update the DF */ + sc_pkcs15_remove_object(p15card, obj); + r = sc_pkcs15init_update_any_df(p15card, profile, df, 0); + + return r; +} + /* * PIN verification */ diff --git a/src/pkcs15init/pkcs15-miocos.c b/src/pkcs15init/pkcs15-miocos.c index efa85a92..dc6bf011 100644 --- a/src/pkcs15init/pkcs15-miocos.c +++ b/src/pkcs15init/pkcs15-miocos.c @@ -218,7 +218,8 @@ static struct sc_pkcs15init_operations sc_pkcs15init_miocos_operations = { miocos_new_pin, miocos_new_key, miocos_new_file, - NULL /* old_generate_key */ + NULL, /* old_generate_key */ + NULL /* delete_object */ }; struct sc_pkcs15init_operations *sc_pkcs15init_get_miocos_ops(void) diff --git a/src/pkcs15init/pkcs15-oberthur.c b/src/pkcs15init/pkcs15-oberthur.c index 167beca0..0e554a8e 100644 --- a/src/pkcs15init/pkcs15-oberthur.c +++ b/src/pkcs15init/pkcs15-oberthur.c @@ -707,7 +707,8 @@ static struct sc_pkcs15init_operations sc_pkcs15init_oberthur_operations = { NULL, /* new_pin */ cosm_new_key, cosm_new_file, - cosm_old_generate_key + cosm_old_generate_key, + NULL /* delete_object */ }; struct sc_pkcs15init_operations * diff --git a/src/pkcs15init/pkcs15-setcos.c b/src/pkcs15init/pkcs15-setcos.c index 52003d4f..922edf8f 100644 --- a/src/pkcs15init/pkcs15-setcos.c +++ b/src/pkcs15init/pkcs15-setcos.c @@ -566,6 +566,13 @@ static int setcos_puk_retries(sc_profile_t *profile, int pin_ref) return pin_info.tries_left; } +static int setcos_delete_object(struct sc_profile *profile, struct sc_card *card, + unsigned int type, const void *data, const sc_path_t *path) +{ + /* For Setcos, all objects are files that can be deleted in any order */ + return sc_pkcs15init_delete_by_path(profile, card, path); +} + static struct sc_pkcs15init_operations sc_pkcs15init_setcos_operations = { setcos_erase_card, NULL, /* init_card */ @@ -584,7 +591,8 @@ static struct sc_pkcs15init_operations sc_pkcs15init_setcos_operations = { NULL, /* old style api */ setcos_new_key, setcos_new_file, - setcos_old_generate_key + setcos_old_generate_key, + setcos_delete_object }; struct sc_pkcs15init_operations * diff --git a/src/pkcs15init/pkcs15-starcos.c b/src/pkcs15init/pkcs15-starcos.c index 0f3ed136..7a4e9ee5 100644 --- a/src/pkcs15init/pkcs15-starcos.c +++ b/src/pkcs15init/pkcs15-starcos.c @@ -926,7 +926,8 @@ static struct sc_pkcs15init_operations sc_pkcs15init_starcos_operations = { starcos_generate_key, NULL, NULL, /* encode private/public key */ starcos_finalize_card, - NULL, NULL, NULL, NULL, NULL /* old style api */ + NULL, NULL, NULL, NULL, NULL, /* old style api */ + NULL /* delete_object */ }; struct sc_pkcs15init_operations *sc_pkcs15init_get_starcos_ops(void)