xref: /illumos-gate/usr/src/cmd/cmd-crypto/pktool/delete.c (revision d1aea6f139360e9e7f1504facb24f8521047b15c)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  * Copyright 2012 Milan Jurik. All rights reserved.
25  * Copyright 2017 Toomas Soome <tsoome@me.com>
26  */
27 
28 /*
29  * This file implements the token object delete operation for this tool.
30  * It loads the PKCS#11 modules, finds the object to delete, deletes it,
31  * and cleans up.  User must be R/W logged into the token.
32  */
33 
34 #include <stdio.h>
35 #include <string.h>
36 #include <cryptoutil.h>
37 #include <security/cryptoki.h>
38 #include "common.h"
39 #include <kmfapi.h>
40 
41 static KMF_RETURN
42 pk_destroy_keys(void *handle, KMF_ATTRIBUTE *attrlist, int numattr)
43 {
44 	int i;
45 	KMF_RETURN rv = KMF_OK;
46 	uint32_t *numkeys;
47 	KMF_KEY_HANDLE *keys = NULL;
48 	int del_num = 0;
49 	KMF_ATTRIBUTE delete_attlist[16];
50 	KMF_KEYSTORE_TYPE kstype;
51 	uint32_t len;
52 	boolean_t destroy = B_TRUE;
53 	KMF_CREDENTIAL cred;
54 	char *slotlabel = NULL;
55 
56 	len = sizeof (kstype);
57 	rv = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, numattr,
58 	    &kstype, &len);
59 	if (rv != KMF_OK)
60 		return (rv);
61 
62 	kmf_set_attr_at_index(delete_attlist, del_num,
63 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
64 	del_num++;
65 
66 	/* "destroy" is optional. Default is TRUE */
67 	(void) kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
68 	    (void *)&destroy, NULL);
69 
70 	kmf_set_attr_at_index(delete_attlist, del_num,
71 	    KMF_DESTROY_BOOL_ATTR, &destroy, sizeof (boolean_t));
72 	del_num++;
73 
74 	switch (kstype) {
75 	case KMF_KEYSTORE_NSS:
76 		rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
77 		    (void *)&cred, NULL);
78 		if (rv == KMF_OK) {
79 			if (cred.credlen > 0) {
80 				kmf_set_attr_at_index(delete_attlist, del_num,
81 				    KMF_CREDENTIAL_ATTR, &cred,
82 				    sizeof (KMF_CREDENTIAL));
83 				del_num++;
84 			}
85 		}
86 
87 		slotlabel = kmf_get_attr_ptr(KMF_TOKEN_LABEL_ATTR, attrlist,
88 		    numattr);
89 		if (slotlabel != NULL) {
90 			kmf_set_attr_at_index(delete_attlist, del_num,
91 			    KMF_TOKEN_LABEL_ATTR, slotlabel,
92 			    strlen(slotlabel));
93 			del_num++;
94 		}
95 		break;
96 	case KMF_KEYSTORE_OPENSSL:
97 		break;
98 	case KMF_KEYSTORE_PK11TOKEN:
99 		rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
100 		    (void *)&cred, NULL);
101 		if (rv == KMF_OK) {
102 			if (cred.credlen > 0) {
103 				kmf_set_attr_at_index(delete_attlist, del_num,
104 				    KMF_CREDENTIAL_ATTR, &cred,
105 				    sizeof (KMF_CREDENTIAL));
106 				del_num++;
107 			}
108 		}
109 		break;
110 	default:
111 		return (PK_ERR_USAGE);
112 	}
113 
114 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
115 	if (numkeys == NULL)
116 		return (PK_ERR_USAGE);
117 
118 	keys = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
119 	if (keys == NULL)
120 		return (PK_ERR_USAGE);
121 
122 	for (i = 0; rv == KMF_OK && i < *numkeys; i++) {
123 		int num = del_num;
124 
125 		kmf_set_attr_at_index(delete_attlist, num,
126 		    KMF_KEY_HANDLE_ATTR, &keys[i], sizeof (KMF_KEY_HANDLE));
127 		num++;
128 
129 		rv = kmf_delete_key_from_keystore(handle, num, delete_attlist);
130 	}
131 	return (rv);
132 }
133 
134 static KMF_RETURN
135 pk_delete_keys(KMF_HANDLE_T kmfhandle, KMF_ATTRIBUTE *attlist, int numattr,
136     char *desc, int *keysdeleted)
137 {
138 	KMF_RETURN rv = KMF_OK;
139 	uint32_t numkeys = 0;
140 	int num = numattr;
141 
142 	*keysdeleted = 0;
143 	numkeys = 0;
144 
145 	kmf_set_attr_at_index(attlist, num,
146 	    KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
147 	num++;
148 
149 	rv = kmf_find_key(kmfhandle, num, attlist);
150 
151 	if (rv == KMF_OK && numkeys > 0) {
152 		KMF_KEY_HANDLE *keys = NULL;
153 		char prompt[1024];
154 
155 		(void) snprintf(prompt, sizeof (prompt),
156 		    gettext("%d %s key(s) found, do you want "
157 		    "to delete them (y/N) ?"), numkeys,
158 		    (desc != NULL ? desc : ""));
159 
160 		if (!yesno(prompt,
161 		    gettext("Respond with yes or no.\n"),
162 		    B_FALSE)) {
163 			*keysdeleted = numkeys;
164 			return (KMF_OK);
165 		}
166 		keys = (KMF_KEY_HANDLE *)malloc(numkeys *
167 		    sizeof (KMF_KEY_HANDLE));
168 		if (keys == NULL)
169 			return (KMF_ERR_MEMORY);
170 		(void) memset(keys, 0, numkeys *
171 		    sizeof (KMF_KEY_HANDLE));
172 
173 		kmf_set_attr_at_index(attlist, num,
174 		    KMF_KEY_HANDLE_ATTR, keys, sizeof (KMF_KEY_HANDLE));
175 		num++;
176 
177 		rv = kmf_find_key(kmfhandle, num, attlist);
178 		if (rv == KMF_OK) {
179 			rv = pk_destroy_keys(kmfhandle, attlist, num);
180 		}
181 
182 		free(keys);
183 	}
184 
185 	*keysdeleted = numkeys;
186 	return (rv);
187 }
188 
189 static KMF_RETURN
190 pk_delete_certs(KMF_HANDLE_T kmfhandle, KMF_ATTRIBUTE *attlist, int numattr)
191 {
192 	KMF_RETURN rv = KMF_OK;
193 	uint32_t numcerts = 0;
194 	int num = numattr;
195 
196 	kmf_set_attr_at_index(attlist, num,
197 	    KMF_COUNT_ATTR, &numcerts, sizeof (uint32_t));
198 	num++;
199 
200 	rv = kmf_find_cert(kmfhandle, num, attlist);
201 	if (rv == KMF_OK && numcerts > 0) {
202 		char prompt[1024];
203 		(void) snprintf(prompt, sizeof (prompt),
204 		    gettext("%d certificate(s) found, do you want "
205 		    "to delete them (y/N) ?"), numcerts);
206 
207 		if (!yesno(prompt,
208 		    gettext("Respond with yes or no.\n"),
209 		    B_FALSE)) {
210 			return (KMF_OK);
211 		}
212 
213 		/*
214 		 * Use numattr because delete cert does not require
215 		 * KMF_COUNT_ATTR attribute.
216 		 */
217 		rv = kmf_delete_cert_from_keystore(kmfhandle, numattr, attlist);
218 
219 	}
220 
221 	return (rv);
222 }
223 
224 static KMF_RETURN
225 delete_nss_keys(KMF_HANDLE_T kmfhandle, char *dir, char *prefix,
226     char *token, int oclass, char *objlabel,
227     KMF_CREDENTIAL *tokencred)
228 {
229 	KMF_RETURN rv = KMF_OK;
230 	char *keytype = NULL;
231 	int nk, numkeys = 0;
232 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
233 	int numattr = 0;
234 	KMF_ATTRIBUTE attrlist[16];
235 	KMF_KEY_CLASS keyclass;
236 
237 	rv = configure_nss(kmfhandle, dir, prefix);
238 	if (rv != KMF_OK)
239 		return (rv);
240 
241 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
242 	    &kstype, sizeof (kstype));
243 	numattr++;
244 
245 	if (objlabel != NULL) {
246 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
247 		    objlabel, strlen(objlabel));
248 		numattr++;
249 	}
250 
251 	if (tokencred->credlen > 0) {
252 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
253 		    tokencred, sizeof (KMF_CREDENTIAL));
254 		numattr++;
255 	}
256 
257 	if (token && strlen(token)) {
258 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
259 		    token, strlen(token));
260 		numattr++;
261 	}
262 
263 	if (oclass & PK_PRIKEY_OBJ) {
264 		int num = numattr;
265 
266 		keyclass = KMF_ASYM_PRI;
267 		kmf_set_attr_at_index(attrlist, num, KMF_KEYCLASS_ATTR,
268 		    &keyclass, sizeof (keyclass));
269 		num++;
270 
271 		keytype = "private";
272 		rv = pk_delete_keys(kmfhandle, attrlist, num, keytype, &nk);
273 		numkeys += nk;
274 		if (rv == KMF_ERR_KEY_NOT_FOUND &&
275 		    oclass != PK_PRIKEY_OBJ)
276 			rv = KMF_OK;
277 	}
278 	if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
279 		int num = numattr;
280 
281 		keyclass = KMF_SYMMETRIC;
282 		kmf_set_attr_at_index(attrlist, num, KMF_KEYCLASS_ATTR,
283 		    &keyclass, sizeof (keyclass));
284 		num++;
285 
286 		keytype = "symmetric";
287 		rv = pk_delete_keys(kmfhandle, attrlist, num, keytype, &nk);
288 		numkeys += nk;
289 		if (rv == KMF_ERR_KEY_NOT_FOUND &&
290 		    oclass != PK_SYMKEY_OBJ)
291 			rv = KMF_OK;
292 	}
293 	if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) {
294 		int num = numattr;
295 
296 		keyclass = KMF_ASYM_PUB;
297 		kmf_set_attr_at_index(attrlist, num, KMF_KEYCLASS_ATTR,
298 		    &keyclass, sizeof (keyclass));
299 		num++;
300 
301 		keytype = "public";
302 		rv = pk_delete_keys(kmfhandle, attrlist, num, keytype, &nk);
303 		numkeys += nk;
304 		if (rv == KMF_ERR_KEY_NOT_FOUND &&
305 		    oclass != PK_PUBKEY_OBJ)
306 			rv = KMF_OK;
307 	}
308 	if (rv == KMF_OK && numkeys == 0)
309 		rv = KMF_ERR_KEY_NOT_FOUND;
310 
311 	return (rv);
312 }
313 
314 static KMF_RETURN
315 delete_nss_certs(KMF_HANDLE_T kmfhandle,
316     char *dir, char *prefix,
317     char *token, char *objlabel,
318     KMF_BIGINT *serno, char *issuer, char *subject,
319     KMF_CERT_VALIDITY find_criteria_flag)
320 {
321 	KMF_RETURN rv = KMF_OK;
322 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
323 	int numattr = 0;
324 	KMF_ATTRIBUTE attrlist[16];
325 
326 	rv = configure_nss(kmfhandle, dir, prefix);
327 	if (rv != KMF_OK)
328 		return (rv);
329 
330 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
331 	    &kstype, sizeof (kstype));
332 	numattr++;
333 
334 	if (objlabel != NULL) {
335 		kmf_set_attr_at_index(attrlist, numattr,
336 		    KMF_CERT_LABEL_ATTR, objlabel,
337 		    strlen(objlabel));
338 		numattr++;
339 	}
340 
341 	if (issuer != NULL) {
342 		kmf_set_attr_at_index(attrlist, numattr,
343 		    KMF_ISSUER_NAME_ATTR, issuer,
344 		    strlen(issuer));
345 		numattr++;
346 	}
347 
348 	if (subject != NULL) {
349 		kmf_set_attr_at_index(attrlist, numattr,
350 		    KMF_SUBJECT_NAME_ATTR, subject,
351 		    strlen(subject));
352 		numattr++;
353 	}
354 
355 	if (serno != NULL) {
356 		kmf_set_attr_at_index(attrlist, numattr,
357 		    KMF_BIGINT_ATTR, serno,
358 		    sizeof (KMF_BIGINT));
359 		numattr++;
360 	}
361 
362 	kmf_set_attr_at_index(attrlist, numattr,
363 	    KMF_CERT_VALIDITY_ATTR, &find_criteria_flag,
364 	    sizeof (KMF_CERT_VALIDITY));
365 	numattr++;
366 
367 	if (token != NULL) {
368 		kmf_set_attr_at_index(attrlist, numattr,
369 		    KMF_TOKEN_LABEL_ATTR, token,
370 		    strlen(token));
371 		numattr++;
372 	}
373 
374 	rv = pk_delete_certs(kmfhandle, attrlist, numattr);
375 
376 	return (rv);
377 }
378 
379 static KMF_RETURN
380 delete_nss_crl(void *kmfhandle,
381     char *dir, char *prefix, char *token,
382     char *issuer, char *subject)
383 {
384 	KMF_RETURN rv = KMF_OK;
385 	int numattr = 0;
386 	KMF_ATTRIBUTE attrlist[8];
387 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
388 
389 	rv = configure_nss(kmfhandle, dir, prefix);
390 	if (rv != KMF_OK)
391 		return (rv);
392 
393 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
394 	    &kstype, sizeof (kstype));
395 	numattr++;
396 
397 	if (token != NULL) {
398 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
399 		    token, strlen(token));
400 		numattr++;
401 	}
402 	if (issuer != NULL) {
403 		kmf_set_attr_at_index(attrlist, numattr, KMF_ISSUER_NAME_ATTR,
404 		    issuer, strlen(issuer));
405 		numattr++;
406 	}
407 	if (subject != NULL) {
408 		kmf_set_attr_at_index(attrlist, numattr, KMF_SUBJECT_NAME_ATTR,
409 		    subject, strlen(subject));
410 		numattr++;
411 	}
412 
413 	rv = kmf_delete_crl(kmfhandle, numattr, attrlist);
414 
415 	return (rv);
416 }
417 
418 static KMF_RETURN
419 delete_pk11_keys(KMF_HANDLE_T kmfhandle,
420     char *token, int oclass, char *objlabel,
421     KMF_CREDENTIAL *tokencred)
422 {
423 	KMF_RETURN rv = KMF_OK;
424 	int nk, numkeys = 0;
425 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
426 	int numattr = 0;
427 	KMF_ATTRIBUTE attrlist[16];
428 	KMF_KEY_CLASS keyclass;
429 	boolean_t token_bool = B_TRUE;
430 	boolean_t private;
431 	/*
432 	 * Symmetric keys and RSA/DSA private keys are always
433 	 * created with the "CKA_PRIVATE" field == TRUE, so
434 	 * make sure we search for them with it also set.
435 	 */
436 	if (oclass & (PK_SYMKEY_OBJ | PK_PRIKEY_OBJ))
437 		oclass |= PK_PRIVATE_OBJ;
438 
439 	rv = select_token(kmfhandle, token, FALSE);
440 	if (rv != KMF_OK) {
441 		return (rv);
442 	}
443 
444 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
445 	    &kstype, sizeof (kstype));
446 	numattr++;
447 
448 	if (objlabel != NULL) {
449 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
450 		    objlabel, strlen(objlabel));
451 		numattr++;
452 	}
453 
454 	if (tokencred != NULL && tokencred->credlen > 0) {
455 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
456 		    tokencred, sizeof (KMF_CREDENTIAL));
457 		numattr++;
458 	}
459 
460 	private = ((oclass & PK_PRIVATE_OBJ) > 0);
461 
462 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVATE_BOOL_ATTR,
463 	    &private, sizeof (private));
464 	numattr++;
465 
466 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
467 	    &token_bool, sizeof (token_bool));
468 	numattr++;
469 
470 	if (oclass & PK_PRIKEY_OBJ) {
471 		int num = numattr;
472 
473 		keyclass = KMF_ASYM_PRI;
474 		kmf_set_attr_at_index(attrlist, num, KMF_KEYCLASS_ATTR,
475 		    &keyclass, sizeof (keyclass));
476 		num++;
477 
478 		rv = pk_delete_keys(kmfhandle, attrlist, num, "private", &nk);
479 		numkeys += nk;
480 		if (rv == KMF_ERR_KEY_NOT_FOUND &&
481 		    oclass != PK_PRIKEY_OBJ)
482 			rv = KMF_OK;
483 	}
484 
485 	if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
486 		int num = numattr;
487 
488 		keyclass = KMF_SYMMETRIC;
489 		kmf_set_attr_at_index(attrlist, num, KMF_KEYCLASS_ATTR,
490 		    &keyclass, sizeof (keyclass));
491 		num++;
492 
493 		rv = pk_delete_keys(kmfhandle, attrlist, num, "symmetric", &nk);
494 		numkeys += nk;
495 		if (rv == KMF_ERR_KEY_NOT_FOUND &&
496 		    oclass != PK_SYMKEY_OBJ)
497 			rv = KMF_OK;
498 	}
499 
500 	if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) {
501 		int num = numattr;
502 
503 		private = B_FALSE;
504 		keyclass = KMF_ASYM_PUB;
505 		kmf_set_attr_at_index(attrlist, num, KMF_KEYCLASS_ATTR,
506 		    &keyclass, sizeof (keyclass));
507 		num++;
508 
509 		rv = pk_delete_keys(kmfhandle, attrlist, num, "public", &nk);
510 		numkeys += nk;
511 		if (rv == KMF_ERR_KEY_NOT_FOUND &&
512 		    oclass != PK_PUBKEY_OBJ)
513 			rv = KMF_OK;
514 	}
515 	if (rv == KMF_OK && numkeys == 0)
516 		rv = KMF_ERR_KEY_NOT_FOUND;
517 
518 	return (rv);
519 }
520 
521 static KMF_RETURN
522 delete_pk11_certs(KMF_HANDLE_T kmfhandle,
523     char *token, char *objlabel,
524     KMF_BIGINT *serno, char *issuer, char *subject,
525     KMF_CERT_VALIDITY find_criteria_flag)
526 {
527 	KMF_RETURN kmfrv;
528 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
529 	int numattr = 0;
530 	KMF_ATTRIBUTE attrlist[16];
531 
532 	kmfrv = select_token(kmfhandle, token, FALSE);
533 
534 	if (kmfrv != KMF_OK) {
535 		return (kmfrv);
536 	}
537 
538 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
539 	    &kstype, sizeof (kstype));
540 	numattr++;
541 
542 	if (objlabel != NULL) {
543 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
544 		    objlabel, strlen(objlabel));
545 		numattr++;
546 	}
547 
548 	if (issuer != NULL) {
549 		kmf_set_attr_at_index(attrlist, numattr, KMF_ISSUER_NAME_ATTR,
550 		    issuer, strlen(issuer));
551 		numattr++;
552 	}
553 
554 	if (subject != NULL) {
555 		kmf_set_attr_at_index(attrlist, numattr, KMF_SUBJECT_NAME_ATTR,
556 		    subject, strlen(subject));
557 		numattr++;
558 	}
559 
560 	if (serno != NULL) {
561 		kmf_set_attr_at_index(attrlist, numattr, KMF_BIGINT_ATTR,
562 		    serno, sizeof (KMF_BIGINT));
563 		numattr++;
564 	}
565 
566 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_VALIDITY_ATTR,
567 	    &find_criteria_flag, sizeof (KMF_CERT_VALIDITY));
568 	numattr++;
569 
570 	kmfrv = pk_delete_certs(kmfhandle, attrlist, numattr);
571 
572 	return (kmfrv);
573 }
574 
575 static KMF_RETURN
576 delete_file_certs(KMF_HANDLE_T kmfhandle,
577     char *dir, char *filename, KMF_BIGINT *serial, char *issuer,
578     char *subject, KMF_CERT_VALIDITY find_criteria_flag)
579 {
580 	KMF_RETURN rv;
581 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
582 	int numattr = 0;
583 	KMF_ATTRIBUTE attrlist[16];
584 
585 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
586 	    &kstype, sizeof (kstype));
587 	numattr++;
588 
589 	if (issuer != NULL) {
590 		kmf_set_attr_at_index(attrlist, numattr, KMF_ISSUER_NAME_ATTR,
591 		    issuer, strlen(issuer));
592 		numattr++;
593 	}
594 
595 	if (subject != NULL) {
596 		kmf_set_attr_at_index(attrlist, numattr, KMF_SUBJECT_NAME_ATTR,
597 		    subject, strlen(subject));
598 		numattr++;
599 	}
600 
601 	if (serial != NULL) {
602 		kmf_set_attr_at_index(attrlist, numattr, KMF_BIGINT_ATTR,
603 		    serial, sizeof (KMF_BIGINT));
604 		numattr++;
605 	}
606 
607 	if (dir != NULL) {
608 		kmf_set_attr_at_index(attrlist, numattr, KMF_DIRPATH_ATTR,
609 		    dir, strlen(dir));
610 		numattr++;
611 	}
612 
613 	if (filename != NULL) {
614 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_FILENAME_ATTR,
615 		    filename, strlen(filename));
616 		numattr++;
617 	}
618 
619 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_VALIDITY_ATTR,
620 	    &find_criteria_flag, sizeof (KMF_CERT_VALIDITY));
621 	numattr++;
622 
623 	rv = pk_delete_certs(kmfhandle, attrlist, numattr);
624 
625 	return (rv);
626 }
627 
628 static KMF_RETURN
629 delete_file_keys(KMF_HANDLE_T kmfhandle, int oclass, char *dir, char *infile)
630 {
631 	KMF_RETURN rv = KMF_OK;
632 	char *keytype = "";
633 	int nk, numkeys = 0;
634 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
635 	int numattr = 0;
636 	KMF_ATTRIBUTE attrlist[16];
637 	KMF_KEY_CLASS keyclass;
638 
639 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
640 	    &kstype, sizeof (kstype));
641 	numattr++;
642 
643 	if (dir != NULL) {
644 		kmf_set_attr_at_index(attrlist, numattr, KMF_DIRPATH_ATTR,
645 		    dir, strlen(dir));
646 		numattr++;
647 	}
648 
649 	if (infile != NULL) {
650 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
651 		    infile, strlen(infile));
652 		numattr++;
653 	}
654 
655 	if (oclass & (PK_PUBKEY_OBJ | PK_PRIKEY_OBJ)) {
656 		int num = numattr;
657 
658 		keyclass = KMF_ASYM_PRI;
659 		kmf_set_attr_at_index(attrlist, num, KMF_KEYCLASS_ATTR,
660 		    &keyclass, sizeof (keyclass));
661 		num++;
662 
663 		keytype = "Asymmetric";
664 		rv = pk_delete_keys(kmfhandle, attrlist, num, keytype, &nk);
665 		numkeys += nk;
666 	}
667 	if (oclass & PK_SYMKEY_OBJ) {
668 		int num = numattr;
669 
670 		keyclass = KMF_SYMMETRIC;
671 		kmf_set_attr_at_index(attrlist, num, KMF_KEYCLASS_ATTR,
672 		    &keyclass, sizeof (keyclass));
673 		num++;
674 
675 		keytype = "symmetric";
676 		rv = pk_delete_keys(kmfhandle, attrlist, num, keytype, &nk);
677 		numkeys += nk;
678 		if (rv == KMF_ERR_KEY_NOT_FOUND && numkeys > 0)
679 			rv = KMF_OK;
680 	}
681 	if (rv == KMF_OK && numkeys == 0)
682 		rv = KMF_ERR_KEY_NOT_FOUND;
683 
684 	return (rv);
685 }
686 
687 static KMF_RETURN
688 delete_file_crl(void *kmfhandle, char *filename)
689 {
690 	KMF_RETURN rv;
691 	int numattr = 0;
692 	KMF_ATTRIBUTE attrlist[4];
693 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
694 
695 	if (filename == NULL || strlen(filename) == 0)
696 		return (KMF_ERR_BAD_PARAMETER);
697 
698 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
699 	    &kstype, sizeof (kstype));
700 	numattr++;
701 
702 	if (filename) {
703 		kmf_set_attr_at_index(attrlist, numattr, KMF_CRL_FILENAME_ATTR,
704 		    filename, strlen(filename));
705 		numattr++;
706 	}
707 
708 	rv = kmf_delete_crl(kmfhandle, numattr, attrlist);
709 
710 	return (rv);
711 }
712 
713 /*
714  * Delete token objects.
715  */
716 int
717 pk_delete(int argc, char *argv[])
718 {
719 	int		opt;
720 	extern int	optind_av;
721 	extern char	*optarg_av;
722 	char		*token_spec = NULL;
723 	char		*subject = NULL;
724 	char		*issuer = NULL;
725 	char		*dir = NULL;
726 	char		*prefix = NULL;
727 	char		*infile = NULL;
728 	char		*object_label = NULL;
729 	char		*serstr = NULL;
730 
731 	int		oclass = 0;
732 	KMF_BIGINT	serial = { NULL, 0 };
733 	KMF_HANDLE_T	kmfhandle = NULL;
734 	KMF_KEYSTORE_TYPE	kstype = 0;
735 	KMF_RETURN	kmfrv, keyrv, certrv, crlrv;
736 	int		rv = 0;
737 	char			*find_criteria = NULL;
738 	KMF_CERT_VALIDITY	find_criteria_flag = KMF_ALL_CERTS;
739 	KMF_CREDENTIAL	tokencred = { NULL, 0 };
740 
741 	/* Parse command line options.  Do NOT i18n/l10n. */
742 	while ((opt = getopt_av(argc, argv,
743 	    "T:(token)y:(objtype)l:(label)"
744 	    "k:(keystore)s:(subject)n:(nickname)"
745 	    "d:(dir)p:(prefix)S:(serial)i:(issuer)"
746 	    "c:(criteria)"
747 	    "f:(infile)")) != EOF) {
748 
749 		if (EMPTYSTRING(optarg_av))
750 			return (PK_ERR_USAGE);
751 		switch (opt) {
752 		case 'T':	/* token specifier */
753 			if (token_spec)
754 				return (PK_ERR_USAGE);
755 			token_spec = optarg_av;
756 			break;
757 		case 'y':	/* object type:  public, private, both */
758 			if (oclass)
759 				return (PK_ERR_USAGE);
760 			oclass = OT2Int(optarg_av);
761 			if (oclass == -1)
762 				return (PK_ERR_USAGE);
763 			break;
764 		case 'l':	/* objects with specific label */
765 		case 'n':
766 			if (object_label)
767 				return (PK_ERR_USAGE);
768 			object_label = (char *)optarg_av;
769 			break;
770 		case 'k':
771 			kstype = KS2Int(optarg_av);
772 			if (kstype == 0)
773 				return (PK_ERR_USAGE);
774 			break;
775 		case 's':
776 			subject = optarg_av;
777 			break;
778 		case 'i':
779 			issuer = optarg_av;
780 			break;
781 		case 'd':
782 			dir = optarg_av;
783 			break;
784 		case 'p':
785 			prefix = optarg_av;
786 			break;
787 		case 'S':
788 			serstr = optarg_av;
789 			break;
790 		case 'f':
791 			infile = optarg_av;
792 			break;
793 		case 'c':
794 			find_criteria = optarg_av;
795 			if (!strcasecmp(find_criteria, "valid"))
796 				find_criteria_flag =
797 				    KMF_NONEXPIRED_CERTS;
798 			else if (!strcasecmp(find_criteria, "expired"))
799 				find_criteria_flag = KMF_EXPIRED_CERTS;
800 			else if (!strcasecmp(find_criteria, "both"))
801 				find_criteria_flag = KMF_ALL_CERTS;
802 			else
803 				return (PK_ERR_USAGE);
804 			break;
805 		default:
806 			return (PK_ERR_USAGE);
807 		}
808 	}
809 
810 	/* Assume keystore = PKCS#11 if not specified */
811 	if (kstype == 0)
812 		kstype = KMF_KEYSTORE_PK11TOKEN;
813 
814 	/* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
815 	if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
816 	    kstype != KMF_KEYSTORE_PK11TOKEN) {
817 
818 		(void) fprintf(stderr, gettext("The objtype parameter "
819 		    "is only relevant if keystore=pkcs11\n"));
820 		return (PK_ERR_USAGE);
821 	}
822 
823 
824 	/* No additional args allowed. */
825 	argc -= optind_av;
826 	argv += optind_av;
827 	if (argc)
828 		return (PK_ERR_USAGE);
829 	/* Done parsing command line options. */
830 
831 	DIR_OPTION_CHECK(kstype, dir);
832 
833 	if (kstype == KMF_KEYSTORE_PK11TOKEN && token_spec == NULL) {
834 		token_spec = PK_DEFAULT_PK11TOKEN;
835 	} else if (kstype == KMF_KEYSTORE_NSS && token_spec == NULL) {
836 		token_spec = DEFAULT_NSS_TOKEN;
837 	}
838 
839 	if (serstr != NULL) {
840 		uchar_t *bytes = NULL;
841 		size_t bytelen;
842 
843 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
844 		if (rv != KMF_OK || bytes == NULL) {
845 			(void) fprintf(stderr, gettext("serial number "
846 			    "must be specified as a hex number "
847 			    "(ex: 0x0102030405ffeeddee)\n"));
848 			return (PK_ERR_USAGE);
849 		}
850 		serial.val = bytes;
851 		serial.len = bytelen;
852 		/* If serial number was given, it must be a cert search */
853 		if (oclass == 0)
854 			oclass = PK_CERT_OBJ;
855 	}
856 	/*
857 	 * If no object type was given but subject or issuer was,
858 	 * it must be a certificate we are looking to delete.
859 	 */
860 	if ((issuer != NULL || subject != NULL) && oclass == 0)
861 		oclass = PK_CERT_OBJ;
862 	/* If no object class specified, delete everything but CRLs */
863 	if (oclass == 0)
864 		oclass = PK_CERT_OBJ | PK_KEY_OBJ;
865 
866 	if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
867 	    kstype == KMF_KEYSTORE_NSS) &&
868 	    (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ))) {
869 
870 		(void) get_token_password(kstype, token_spec,
871 		    &tokencred);
872 	}
873 
874 	if ((kmfrv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK)
875 		return (kmfrv);
876 
877 	keyrv = certrv = crlrv = KMF_OK;
878 	switch (kstype) {
879 		case KMF_KEYSTORE_PK11TOKEN:
880 			if (oclass & PK_KEY_OBJ) {
881 				keyrv = delete_pk11_keys(kmfhandle,
882 				    token_spec, oclass,
883 				    object_label, &tokencred);
884 				/*
885 				 * If deleting groups of objects, it is OK
886 				 * to ignore the "key not found" case so that
887 				 * we can continue to find other objects.
888 				 */
889 				if (keyrv != KMF_OK &&
890 				    keyrv != KMF_ERR_KEY_NOT_FOUND)
891 					break;
892 			}
893 			if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
894 				certrv = delete_pk11_certs(kmfhandle,
895 				    token_spec, object_label,
896 				    &serial, issuer,
897 				    subject, find_criteria_flag);
898 				/*
899 				 * If cert delete failed, but we are looking at
900 				 * other objects, then it is OK.
901 				 */
902 				if (certrv != KMF_OK &&
903 				    certrv != KMF_ERR_CERT_NOT_FOUND)
904 					break;
905 			}
906 			if (oclass & PK_CRL_OBJ)
907 				crlrv = delete_file_crl(kmfhandle,
908 				    infile);
909 			break;
910 		case KMF_KEYSTORE_NSS:
911 			keyrv = certrv = crlrv = KMF_OK;
912 			if (oclass & PK_KEY_OBJ) {
913 				keyrv = delete_nss_keys(kmfhandle,
914 				    dir, prefix, token_spec,
915 				    oclass, (char  *)object_label,
916 				    &tokencred);
917 				if (keyrv != KMF_OK &&
918 				    keyrv != KMF_ERR_KEY_NOT_FOUND)
919 					break;
920 			}
921 			if (oclass & PK_CERT_OBJ) {
922 				certrv = delete_nss_certs(kmfhandle,
923 				    dir, prefix, token_spec,
924 				    (char  *)object_label,
925 				    &serial, issuer, subject,
926 				    find_criteria_flag);
927 				if (certrv != KMF_OK &&
928 				    certrv != KMF_ERR_CERT_NOT_FOUND)
929 					break;
930 			}
931 			if (oclass & PK_CRL_OBJ)
932 				crlrv = delete_nss_crl(kmfhandle,
933 				    dir, prefix, token_spec,
934 				    (char  *)object_label, subject);
935 			break;
936 		case KMF_KEYSTORE_OPENSSL:
937 			if (oclass & PK_KEY_OBJ) {
938 				keyrv = delete_file_keys(kmfhandle, oclass,
939 				    dir, infile);
940 				if (keyrv != KMF_OK)
941 					break;
942 			}
943 			if (oclass & (PK_CERT_OBJ)) {
944 				certrv = delete_file_certs(kmfhandle,
945 				    dir, infile, &serial, issuer,
946 				    subject, find_criteria_flag);
947 				if (certrv != KMF_OK)
948 					break;
949 			}
950 			if (oclass & PK_CRL_OBJ)
951 				crlrv = delete_file_crl(kmfhandle,
952 				    infile);
953 			break;
954 		default:
955 			rv = PK_ERR_USAGE;
956 			break;
957 	}
958 
959 	/*
960 	 * Logic here:
961 	 *    If searching for more than just one class of object (key or cert)
962 	 *    and only 1 of the classes was not found, it is not an error.
963 	 *    If searching for just one class of object, that failure should
964 	 *    be reported.
965 	 *
966 	 *    Any error other than "KMF_ERR_[key/cert]_NOT_FOUND" should
967 	 *    be reported either way.
968 	 */
969 	if (keyrv != KMF_ERR_KEY_NOT_FOUND && keyrv != KMF_OK)
970 		kmfrv = keyrv;
971 	else if (certrv != KMF_OK && certrv != KMF_ERR_CERT_NOT_FOUND)
972 		kmfrv = certrv;
973 	else if (crlrv != KMF_OK && crlrv != KMF_ERR_CRL_NOT_FOUND)
974 		kmfrv = crlrv;
975 
976 	/*
977 	 * If nothing was found, return error.
978 	 */
979 	if ((keyrv == KMF_ERR_KEY_NOT_FOUND && (oclass & PK_KEY_OBJ)) &&
980 	    (certrv == KMF_ERR_CERT_NOT_FOUND && (oclass & PK_CERT_OBJ)))
981 		kmfrv = KMF_ERR_KEY_NOT_FOUND;
982 
983 	if (kmfrv != KMF_OK)
984 		goto out;
985 
986 	if (keyrv != KMF_OK && (oclass == PK_KEY_OBJ))
987 		kmfrv = keyrv;
988 	else if (certrv != KMF_OK && (oclass == PK_CERT_OBJ))
989 		kmfrv = certrv;
990 	else if (crlrv != KMF_OK && (oclass == PK_CRL_OBJ))
991 		kmfrv = crlrv;
992 
993 out:
994 	if (kmfrv != KMF_OK) {
995 		display_error(kmfhandle, kmfrv,
996 		    gettext("Error deleting objects"));
997 	}
998 
999 	if (serial.val != NULL)
1000 		free(serial.val);
1001 	(void) kmf_finalize(kmfhandle);
1002 	return (kmfrv);
1003 }
1004