xref: /illumos-gate/usr/src/cmd/cmd-crypto/pktool/delete.c (revision 2983dda76a6d296fdb560c88114fe41caad1b84f)
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  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
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,
630 	char *dir, char *infile)
631 {
632 	KMF_RETURN rv = KMF_OK;
633 	char *keytype = "";
634 	int nk, numkeys = 0;
635 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
636 	int numattr = 0;
637 	KMF_ATTRIBUTE attrlist[16];
638 	KMF_KEY_CLASS keyclass;
639 
640 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
641 	    &kstype, sizeof (kstype));
642 	numattr++;
643 
644 	if (dir != NULL) {
645 		kmf_set_attr_at_index(attrlist, numattr, KMF_DIRPATH_ATTR,
646 		    dir, strlen(dir));
647 		numattr++;
648 	}
649 
650 	if (infile != NULL) {
651 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
652 		    infile, strlen(infile));
653 		numattr++;
654 	}
655 
656 	if (oclass & (PK_PUBKEY_OBJ | PK_PRIKEY_OBJ)) {
657 		int num = numattr;
658 
659 		keyclass = KMF_ASYM_PRI;
660 		kmf_set_attr_at_index(attrlist, num, KMF_KEYCLASS_ATTR,
661 		    &keyclass, sizeof (keyclass));
662 		num++;
663 
664 		keytype = "Asymmetric";
665 		rv = pk_delete_keys(kmfhandle, attrlist, num, keytype, &nk);
666 		numkeys += nk;
667 	}
668 	if (oclass & PK_SYMKEY_OBJ) {
669 		int num = numattr;
670 
671 		keyclass = KMF_SYMMETRIC;
672 		kmf_set_attr_at_index(attrlist, num, KMF_KEYCLASS_ATTR,
673 		    &keyclass, sizeof (keyclass));
674 		num++;
675 
676 		keytype = "symmetric";
677 		rv = pk_delete_keys(kmfhandle, attrlist, num, keytype, &nk);
678 		numkeys += nk;
679 		if (rv == KMF_ERR_KEY_NOT_FOUND && numkeys > 0)
680 			rv = KMF_OK;
681 	}
682 	if (rv == KMF_OK && numkeys == 0)
683 		rv = KMF_ERR_KEY_NOT_FOUND;
684 
685 	return (rv);
686 }
687 
688 static KMF_RETURN
689 delete_file_crl(void *kmfhandle, char *filename)
690 {
691 	KMF_RETURN rv;
692 	int numattr = 0;
693 	KMF_ATTRIBUTE attrlist[4];
694 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
695 
696 	if (filename == NULL || strlen(filename) == 0)
697 		return (KMF_ERR_BAD_PARAMETER);
698 
699 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
700 	    &kstype, sizeof (kstype));
701 	numattr++;
702 
703 	if (filename) {
704 		kmf_set_attr_at_index(attrlist, numattr, KMF_CRL_FILENAME_ATTR,
705 		    filename, strlen(filename));
706 		numattr++;
707 	}
708 
709 	rv = kmf_delete_crl(kmfhandle, numattr, attrlist);
710 
711 	return (rv);
712 }
713 
714 /*
715  * Delete token objects.
716  */
717 int
718 pk_delete(int argc, char *argv[])
719 {
720 	int		opt;
721 	extern int	optind_av;
722 	extern char	*optarg_av;
723 	char		*token_spec = NULL;
724 	char		*subject = NULL;
725 	char		*issuer = NULL;
726 	char		*dir = NULL;
727 	char		*prefix = NULL;
728 	char		*infile = NULL;
729 	char		*object_label = NULL;
730 	char		*serstr = NULL;
731 
732 	int		oclass = 0;
733 	KMF_BIGINT	serial = { NULL, 0 };
734 	KMF_HANDLE_T	kmfhandle = NULL;
735 	KMF_KEYSTORE_TYPE	kstype = 0;
736 	KMF_RETURN	kmfrv, keyrv, certrv, crlrv;
737 	int		rv = 0;
738 	char			*find_criteria = NULL;
739 	KMF_CERT_VALIDITY	find_criteria_flag = KMF_ALL_CERTS;
740 	KMF_CREDENTIAL	tokencred = {NULL, 0};
741 
742 	/* Parse command line options.  Do NOT i18n/l10n. */
743 	while ((opt = getopt_av(argc, argv,
744 	    "T:(token)y:(objtype)l:(label)"
745 	    "k:(keystore)s:(subject)n:(nickname)"
746 	    "d:(dir)p:(prefix)S:(serial)i:(issuer)"
747 	    "c:(criteria)"
748 	    "f:(infile)")) != EOF) {
749 
750 		if (EMPTYSTRING(optarg_av))
751 			return (PK_ERR_USAGE);
752 		switch (opt) {
753 		case 'T':	/* token specifier */
754 			if (token_spec)
755 				return (PK_ERR_USAGE);
756 			token_spec = optarg_av;
757 			break;
758 		case 'y':	/* object type:  public, private, both */
759 			if (oclass)
760 				return (PK_ERR_USAGE);
761 			oclass = OT2Int(optarg_av);
762 			if (oclass == -1)
763 				return (PK_ERR_USAGE);
764 			break;
765 		case 'l':	/* objects with specific label */
766 		case 'n':
767 			if (object_label)
768 				return (PK_ERR_USAGE);
769 			object_label = (char *)optarg_av;
770 			break;
771 		case 'k':
772 			kstype = KS2Int(optarg_av);
773 			if (kstype == 0)
774 				return (PK_ERR_USAGE);
775 			break;
776 		case 's':
777 			subject = optarg_av;
778 			break;
779 		case 'i':
780 			issuer = optarg_av;
781 			break;
782 		case 'd':
783 			dir = optarg_av;
784 			break;
785 		case 'p':
786 			prefix = optarg_av;
787 			break;
788 		case 'S':
789 			serstr = optarg_av;
790 			break;
791 		case 'f':
792 			infile = optarg_av;
793 			break;
794 		case 'c':
795 			find_criteria = optarg_av;
796 			if (!strcasecmp(find_criteria, "valid"))
797 				find_criteria_flag =
798 				    KMF_NONEXPIRED_CERTS;
799 			else if (!strcasecmp(find_criteria, "expired"))
800 				find_criteria_flag = KMF_EXPIRED_CERTS;
801 			else if (!strcasecmp(find_criteria, "both"))
802 				find_criteria_flag = KMF_ALL_CERTS;
803 			else
804 				return (PK_ERR_USAGE);
805 			break;
806 		default:
807 			return (PK_ERR_USAGE);
808 			break;
809 		}
810 	}
811 
812 	/* Assume keystore = PKCS#11 if not specified */
813 	if (kstype == 0)
814 		kstype = KMF_KEYSTORE_PK11TOKEN;
815 
816 	/* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
817 	if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
818 	    kstype != KMF_KEYSTORE_PK11TOKEN) {
819 
820 		(void) fprintf(stderr, gettext("The objtype parameter "
821 		    "is only relevant if keystore=pkcs11\n"));
822 		return (PK_ERR_USAGE);
823 	}
824 
825 
826 	/* No additional args allowed. */
827 	argc -= optind_av;
828 	argv += optind_av;
829 	if (argc)
830 		return (PK_ERR_USAGE);
831 	/* Done parsing command line options. */
832 
833 	DIR_OPTION_CHECK(kstype, dir);
834 
835 	if (kstype == KMF_KEYSTORE_PK11TOKEN && token_spec == NULL) {
836 		token_spec = PK_DEFAULT_PK11TOKEN;
837 	} else if (kstype == KMF_KEYSTORE_NSS && token_spec == NULL) {
838 		token_spec = DEFAULT_NSS_TOKEN;
839 	}
840 
841 	if (serstr != NULL) {
842 		uchar_t *bytes = NULL;
843 		size_t bytelen;
844 
845 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
846 		if (rv != KMF_OK || bytes == NULL) {
847 			(void) fprintf(stderr, gettext("serial number "
848 			    "must be specified as a hex number "
849 			    "(ex: 0x0102030405ffeeddee)\n"));
850 			return (PK_ERR_USAGE);
851 		}
852 		serial.val = bytes;
853 		serial.len = bytelen;
854 		/* If serial number was given, it must be a cert search */
855 		if (oclass == 0)
856 			oclass = PK_CERT_OBJ;
857 	}
858 	/*
859 	 * If no object type was given but subject or issuer was,
860 	 * it must be a certificate we are looking to delete.
861 	 */
862 	if ((issuer != NULL || subject != NULL) && oclass == 0)
863 		oclass = PK_CERT_OBJ;
864 	/* If no object class specified, delete everything but CRLs */
865 	if (oclass == 0)
866 		oclass = PK_CERT_OBJ | PK_KEY_OBJ;
867 
868 	if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
869 	    kstype == KMF_KEYSTORE_NSS) &&
870 	    (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ))) {
871 
872 		(void) get_token_password(kstype, token_spec,
873 		    &tokencred);
874 	}
875 
876 	if ((kmfrv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK)
877 		return (kmfrv);
878 
879 	keyrv = certrv = crlrv = KMF_OK;
880 	switch (kstype) {
881 		case KMF_KEYSTORE_PK11TOKEN:
882 			if (oclass & PK_KEY_OBJ) {
883 				keyrv = delete_pk11_keys(kmfhandle,
884 				    token_spec, oclass,
885 				    object_label, &tokencred);
886 				/*
887 				 * If deleting groups of objects, it is OK
888 				 * to ignore the "key not found" case so that
889 				 * we can continue to find other objects.
890 				 */
891 				if (keyrv != KMF_OK &&
892 				    keyrv != KMF_ERR_KEY_NOT_FOUND)
893 					break;
894 			}
895 			if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
896 				certrv = delete_pk11_certs(kmfhandle,
897 				    token_spec, object_label,
898 				    &serial, issuer,
899 				    subject, find_criteria_flag);
900 				/*
901 				 * If cert delete failed, but we are looking at
902 				 * other objects, then it is OK.
903 				 */
904 				if (certrv != KMF_OK &&
905 				    certrv != KMF_ERR_CERT_NOT_FOUND)
906 					break;
907 			}
908 			if (oclass & PK_CRL_OBJ)
909 				crlrv = delete_file_crl(kmfhandle,
910 				    infile);
911 			break;
912 		case KMF_KEYSTORE_NSS:
913 			keyrv = certrv = crlrv = KMF_OK;
914 			if (oclass & PK_KEY_OBJ) {
915 				keyrv = delete_nss_keys(kmfhandle,
916 				    dir, prefix, token_spec,
917 				    oclass, (char  *)object_label,
918 				    &tokencred);
919 				if (keyrv != KMF_OK &&
920 				    keyrv != KMF_ERR_KEY_NOT_FOUND)
921 					break;
922 			}
923 			if (oclass & PK_CERT_OBJ) {
924 				certrv = delete_nss_certs(kmfhandle,
925 				    dir, prefix, token_spec,
926 				    (char  *)object_label,
927 				    &serial, issuer, subject,
928 				    find_criteria_flag);
929 				if (certrv != KMF_OK &&
930 				    certrv != KMF_ERR_CERT_NOT_FOUND)
931 					break;
932 			}
933 			if (oclass & PK_CRL_OBJ)
934 				crlrv = delete_nss_crl(kmfhandle,
935 				    dir, prefix, token_spec,
936 				    (char  *)object_label, subject);
937 			break;
938 		case KMF_KEYSTORE_OPENSSL:
939 			if (oclass & PK_KEY_OBJ) {
940 				keyrv = delete_file_keys(kmfhandle, oclass,
941 				    dir, infile);
942 				if (keyrv != KMF_OK)
943 					break;
944 			}
945 			if (oclass & (PK_CERT_OBJ)) {
946 				certrv = delete_file_certs(kmfhandle,
947 				    dir, infile, &serial, issuer,
948 				    subject, find_criteria_flag);
949 				if (certrv != KMF_OK)
950 					break;
951 			}
952 			if (oclass & PK_CRL_OBJ)
953 				crlrv = delete_file_crl(kmfhandle,
954 				    infile);
955 			break;
956 		default:
957 			rv = PK_ERR_USAGE;
958 			break;
959 	}
960 
961 	/*
962 	 * Logic here:
963 	 *    If searching for more than just one class of object (key or cert)
964 	 *    and only 1 of the classes was not found, it is not an error.
965 	 *    If searching for just one class of object, that failure should
966 	 *    be reported.
967 	 *
968 	 *    Any error other than "KMF_ERR_[key/cert]_NOT_FOUND" should
969 	 *    be reported either way.
970 	 */
971 	if (keyrv != KMF_ERR_KEY_NOT_FOUND && keyrv != KMF_OK)
972 		kmfrv = keyrv;
973 	else if (certrv != KMF_OK && certrv != KMF_ERR_CERT_NOT_FOUND)
974 		kmfrv = certrv;
975 	else if (crlrv != KMF_OK && crlrv != KMF_ERR_CRL_NOT_FOUND)
976 		kmfrv = crlrv;
977 
978 	/*
979 	 * If nothing was found, return error.
980 	 */
981 	if ((keyrv == KMF_ERR_KEY_NOT_FOUND && (oclass & PK_KEY_OBJ)) &&
982 	    (certrv == KMF_ERR_CERT_NOT_FOUND && (oclass & PK_CERT_OBJ)))
983 		kmfrv = KMF_ERR_KEY_NOT_FOUND;
984 
985 	if (kmfrv != KMF_OK)
986 		goto out;
987 
988 	if (keyrv != KMF_OK && (oclass == PK_KEY_OBJ))
989 		kmfrv = keyrv;
990 	else if (certrv != KMF_OK && (oclass == PK_CERT_OBJ))
991 		kmfrv = certrv;
992 	else if (crlrv != KMF_OK && (oclass == PK_CRL_OBJ))
993 		kmfrv = crlrv;
994 
995 out:
996 	if (kmfrv != KMF_OK) {
997 		display_error(kmfhandle, kmfrv,
998 		    gettext("Error deleting objects"));
999 	}
1000 
1001 	if (serial.val != NULL)
1002 		free(serial.val);
1003 	(void) kmf_finalize(kmfhandle);
1004 	return (kmfrv);
1005 }
1006