diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 99e6519..876bc57 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -1012,6 +1012,22 @@ CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len) { return CKR_OK; } +CK_RV delete_cert(piv_obj_id_t cert_id) { + CK_RV rv; + + // Clear the object containing the certificate + rv = do_delete_cert(&cert_objects[piv_objects[cert_id].sub_id].data); + if (rv != CKR_OK) + return rv; + + // Clear the object containing the public key + rv = do_delete_pubk(&pubkey_objects[piv_objects[cert_id].sub_id].data); + if (rv != CKR_OK) + return rv; + + return CKR_OK; +} + CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BYTE_PTR *value, CK_ULONG_PTR cert_len) { @@ -1263,3 +1279,13 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, return CKR_OK; } + +CK_RV check_delete_cert(CK_OBJECT_HANDLE hObject, CK_BYTE_PTR id) { + + if (hObject < PIV_CERT_OBJ_X509_PIV_AUTH || hObject >= PIV_CERT_OBJ_LAST) + return CKR_ACTION_PROHIBITED; + + *id = hObject - PIV_CERT_OBJ_X509_PIV_AUTH; + + return CKR_OK; +} diff --git a/ykcs11/objects.h b/ykcs11/objects.h index 860f3a8..be9db19 100644 --- a/ykcs11/objects.h +++ b/ykcs11/objects.h @@ -11,6 +11,7 @@ CK_BBOOL is_private_object(ykcs11_session_t *s, CK_OBJECT_HANDLE obj); CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, CK_ULONG n_certs); CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len); +CK_RV delete_cert(piv_obj_id_t cert_id); CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BYTE_PTR *value, CK_ULONG_PTR cert_len); @@ -19,6 +20,6 @@ CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BYTE_PTR *p, CK_BYTE_PTR *q, CK_BYTE_PTR *dp, CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined); - +CK_RV check_delete_cert(CK_OBJECT_HANDLE hObject, CK_BYTE_PTR id); #endif diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 8b68c2d..cc2085a 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -256,12 +256,21 @@ CK_RV do_get_raw_cert(X509 *cert, CK_BYTE_PTR out, CK_ULONG_PTR out_len) { return CKR_OK; } -CK_RV free_cert(X509 *cert) { +CK_RV do_delete_cert(X509 **cert) { + + X509_free(*cert); + cert = NULL; + + return CKR_OK; + +} + +/*CK_RV free_cert(X509 *cert) { X509_free((X509 *) cert); return CKR_OK; -} +}*/ CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key) { @@ -438,13 +447,22 @@ CK_RV do_get_curve_parameters(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) return CKR_OK; } -CK_RV free_key(EVP_PKEY *key) { +CK_RV do_delete_pubk(EVP_PKEY **key) { + + EVP_PKEY_free(*key); + key = NULL; + + return CKR_OK; + +} + +/*CK_RV free_key(EVP_PKEY *key) { EVP_PKEY_free(key); return CKR_OK; -} + }*/ CK_RV do_pkcs_1_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len, CK_ULONG key_len) { unsigned char buffer[512]; diff --git a/ykcs11/openssl_utils.h b/ykcs11/openssl_utils.h index 09f6482..35461a5 100644 --- a/ykcs11/openssl_utils.h +++ b/ykcs11/openssl_utils.h @@ -14,7 +14,8 @@ CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, CK_BYTE_PTR out, CK_ULONG_PTR out_len); CK_RV do_check_cert(CK_BYTE_PTR in, CK_ULONG_PTR cert_len); CK_RV do_get_raw_cert(X509 *cert, CK_BYTE_PTR out, CK_ULONG_PTR out_len); -CK_RV free_cert(X509 *cert); +CK_RV do_delete_cert(X509 **cert); +//CK_RV free_cert(X509 *cert); CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key); CK_KEY_TYPE do_get_key_type(EVP_PKEY *key); @@ -23,7 +24,8 @@ CK_ULONG do_get_public_exponent(EVP_PKEY *key); CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len); CK_RV do_encode_rsa_public_key(CK_BYTE_PTR data, CK_ULONG len, RSA **key); CK_RV do_get_curve_parameters(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len); -CK_RV free_key(EVP_PKEY *key); +CK_RV do_delete_pubk(EVP_PKEY **key); +//CK_RV free_key(EVP_PKEY *key); CK_RV do_pkcs_1_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len, CK_ULONG key_len); CK_RV do_pkcs_1_digest_info(CK_BYTE_PTR in, CK_ULONG in_len, int nid, CK_BYTE_PTR out, CK_ULONG_PTR out_len); diff --git a/ykcs11/pkcs11t.h b/ykcs11/pkcs11t.h index bcdd9e0..d357092 100644 --- a/ykcs11/pkcs11t.h +++ b/ykcs11/pkcs11t.h @@ -755,6 +755,8 @@ typedef CK_ULONG CK_RV; #define CKR_ATTRIBUTE_SENSITIVE 0x00000011UL #define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012UL #define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013UL +#define CKR_COPY_PROHIBITED 0x0000001AUL +#define CKR_ACTION_PROHIBITED 0x0000001BUL #define CKR_DATA_INVALID 0x00000020UL #define CKR_DATA_LEN_RANGE 0x00000021UL #define CKR_DEVICE_ERROR 0x00000030UL diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index c185f7e..cb62e83 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -257,6 +257,14 @@ CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, CK_BYT } +CK_RV COMMON_token_delete_cert(ykpiv_state *state, CK_ULONG cert_id) { + + if (ykpiv_save_object(state, cert_id, NULL, 0) != YKPIV_OK) + return CKR_DEVICE_ERROR; + + return CKR_OK; +} + token_vendor_t get_token_vendor(vendor_id_t vid) { token_vendor_t v; @@ -278,6 +286,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) { v.token_generate_key = COMMON_token_generate_key; v.token_import_cert = COMMON_token_import_cert; v.token_import_private_key = COMMON_token_import_private_key; + v.token_delete_cert = COMMON_token_delete_cert; break; case UNKNOWN: @@ -298,6 +307,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) { v.token_generate_key = NULL; v.token_import_cert = NULL; v.token_import_private_key = NULL; + v.token_delete_cert = NULL; } return v; diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h index 9513063..3b57209 100644 --- a/ykcs11/token_vendors.h +++ b/ykcs11/token_vendors.h @@ -25,6 +25,7 @@ typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG, CK typedef CK_RV (*t_import_cert_f)(ykpiv_state *, CK_ULONG, CK_BYTE_PTR); typedef CK_RV (*t_import_private_key_f)(ykpiv_state *, CK_BYTE, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_ULONG, CK_ULONG); +typedef CK_RV (*t_delete_cert_f)(ykpiv_state *, CK_ULONG); // TODO: replace all the common calls with functions defined in .c that use libykpiv @@ -45,6 +46,7 @@ typedef struct { t_generate_key_f token_generate_key; t_import_cert_f token_import_cert; t_import_private_key_f token_import_private_key; + t_delete_cert_f token_delete_cert; } token_vendor_t; token_vendor_t get_token_vendor(vendor_id_t vid); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 32715c0..4d76606 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -1044,7 +1044,93 @@ CK_DEFINE_FUNCTION(CK_RV, C_DestroyObject)( ) { DIN; - DBG(("TODO!!!")); + + CK_RV rv; + token_vendor_t token; + CK_ULONG i; + CK_ULONG j; + CK_BYTE id; + CK_ULONG cert_id; + CK_ULONG pvtk_id; + CK_ULONG pubk_id; + piv_obj_id_t *obj_ptr; + + DBG(("Deleting object %lu", hObject)); + + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); + return CKR_CRYPTOKI_NOT_INITIALIZED; + } + + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); + return CKR_SESSION_CLOSED; + } + + if (hSession != session.handle) { + DBG(("Unknown session %lu", hSession)); + return CKR_SESSION_HANDLE_INVALID; + } + + // Only certificates can be deleted + // SO must be logged in + if (session.info.state != CKS_RW_SO_FUNCTIONS) { + DBG(("Unable to delete objects, SO must be logged in")); + return CKR_ACTION_PROHIBITED; + } + + rv = check_delete_cert(hObject, &id); + if (rv != CKR_OK) { + DBG(("Object %lu can not be deleted", hObject)); + return rv; + } + + token = get_token_vendor(session.slot->token->vid); + + rv = token.token_delete_cert(piv_state, piv_2_ykpiv(hObject)); + if (rv != CKR_OK) { + DBG(("Unable to delete object %lu", hObject)); + return rv; + } + + // Remove the object from the session + // Do it in a slightly inefficient way but preserve ordering + + cert_id = PIV_CERT_OBJ_X509_PIV_AUTH + id; // TODO: make function for these + pvtk_id = PIV_PVTK_OBJ_PIV_AUTH + id; + pubk_id = PIV_PUBK_OBJ_PIV_AUTH + id; + + obj_ptr = malloc((session.slot->token->n_objects - 3) * sizeof(piv_obj_id_t)); + if (obj_ptr == NULL) { + DBG(("Unable to allocate memory")); + return CKR_HOST_MEMORY; + } + + i = 0; + j = 0; + while (i < session.slot->token->n_objects) { + if (session.slot->token->objects[i] == cert_id || + session.slot->token->objects[i] == pvtk_id || + session.slot->token->objects[i] == pubk_id) { + i++; + continue; + } + + obj_ptr[j++] = session.slot->token->objects[i++]; + } + + rv = delete_cert(cert_id); + if (rv != CKR_OK) { + DBG(("Unable to delete certificate data")); + return CKR_FUNCTION_FAILED; + } + + free(session.slot->token->objects); + + session.slot->token->n_objects -= 3; + session.slot->token->n_certs--; + session.slot->token->objects = obj_ptr; + DOUT; return CKR_OK; }