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  */
26 
27 /*
28  * This file implements the token object delete operation for this tool.
29  * It loads the PKCS#11 modules, finds the object to delete, deletes it,
30  * and cleans up.  User must be R/W logged into the token.
31  */
32 
33 #include <stdio.h>
34 #include <string.h>
35 #include <cryptoutil.h>
36 #include <security/cryptoki.h>
37 #include "common.h"
38 #include <kmfapi.h>
39 
40 static KMF_RETURN
41 pk_destroy_keys(void *handle, KMF_ATTRIBUTE *attrlist, int numattr)
42 {
43 	int i;
44 	KMF_RETURN rv = KMF_OK;
45 	uint32_t *numkeys;
46 	KMF_KEY_HANDLE *keys = NULL;
47 	int del_num = 0;
48 	KMF_ATTRIBUTE delete_attlist[16];
49 	KMF_KEYSTORE_TYPE kstype;
50 	uint32_t len;
51 	boolean_t destroy = B_TRUE;
52 	KMF_CREDENTIAL cred;
53 	char *slotlabel = NULL;
54 
55 	len = sizeof (kstype);
56 	rv = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, numattr,
57 	    &kstype, &len);
58 	if (rv != KMF_OK)
59 		return (rv);
60 
61 	kmf_set_attr_at_index(delete_attlist, del_num,
62 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
63 	del_num++;
64 
65 	/* "destroy" is optional. Default is TRUE */
66 	(void) kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
67 	    (void *)&destroy, NULL);
68 
69 	kmf_set_attr_at_index(delete_attlist, del_num,
70 	    KMF_DESTROY_BOOL_ATTR, &destroy, sizeof (boolean_t));
71 	del_num++;
72 
73 	switch (kstype) {
74 	case KMF_KEYSTORE_NSS:
75 		rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
76 		    (void *)&cred, NULL);
77 		if (rv == KMF_OK) {
78 			if (cred.credlen > 0) {
79 				kmf_set_attr_at_index(delete_attlist, del_num,
80 				    KMF_CREDENTIAL_ATTR, &cred,
81 				    sizeof (KMF_CREDENTIAL));
82 				del_num++;
83 			}
84 		}
85 
86 		slotlabel = kmf_get_attr_ptr(KMF_TOKEN_LABEL_ATTR, attrlist,
87 		    numattr);
88 		if (slotlabel != NULL) {
89 			kmf_set_attr_at_index(delete_attlist, del_num,
90 			    KMF_TOKEN_LABEL_ATTR, slotlabel,
91 			    strlen(slotlabel));
92 			del_num++;
93 		}
94 		break;
95 	case KMF_KEYSTORE_OPENSSL:
96 		break;
97 	case KMF_KEYSTORE_PK11TOKEN:
98 		rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
99 		    (void *)&cred, NULL);
100 		if (rv == KMF_OK) {
101 			if (cred.credlen > 0) {
102 				kmf_set_attr_at_index(delete_attlist, del_num,
103 				    KMF_CREDENTIAL_ATTR, &cred,
104 				    sizeof (KMF_CREDENTIAL));
105 				del_num++;
106 			}
107 		}
108 		break;
109 	default:
110 		return (PK_ERR_USAGE);
111 	}
112 
113 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
114 	if (numkeys == NULL)
115 		return (PK_ERR_USAGE);
116 
117 	keys = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
118 	if (keys == NULL)
119 		return (PK_ERR_USAGE);
120 
121 	for (i = 0; rv == KMF_OK && i < *numkeys; i++) {
122 		int num = del_num;
123 
124 		kmf_set_attr_at_index(delete_attlist, num,
125 		    KMF_KEY_HANDLE_ATTR, &keys[i], sizeof (KMF_KEY_HANDLE));
126 		num++;
127 
128 		rv = kmf_delete_key_from_keystore(handle, num, delete_attlist);
129 	}
130 	return (rv);
131 }
132 
133 static KMF_RETURN
134 pk_delete_keys(KMF_HANDLE_T kmfhandle, KMF_ATTRIBUTE *attlist, int numattr,
135 	char *desc, int *keysdeleted)
136 {
137 	KMF_RETURN rv = KMF_OK;
138 	uint32_t numkeys = 0;
139 	int num = numattr;
140 
141 	*keysdeleted = 0;
142 	numkeys = 0;
143 
144 	kmf_set_attr_at_index(attlist, num,
145 	    KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
146 	num++;
147 
148 	rv = kmf_find_key(kmfhandle, num, attlist);
149 
150 	if (rv == KMF_OK && numkeys > 0) {
151 		KMF_KEY_HANDLE *keys = NULL;
152 		char prompt[1024];
153 
154 		(void) snprintf(prompt, sizeof (prompt),
155 		    gettext("%d %s key(s) found, do you want "
156 		    "to delete them (y/N) ?"), numkeys,
157 		    (desc != NULL ? desc : ""));
158 
159 		if (!yesno(prompt,
160 		    gettext("Respond with yes or no.\n"),
161 		    B_FALSE)) {
162 			*keysdeleted = numkeys;
163 			return (KMF_OK);
164 		}
165 		keys = (KMF_KEY_HANDLE *)malloc(numkeys *
166 		    sizeof (KMF_KEY_HANDLE));
167 		if (keys == NULL)
168 			return (KMF_ERR_MEMORY);
169 		(void) memset(keys, 0, numkeys *
170 		    sizeof (KMF_KEY_HANDLE));
171 
172 		kmf_set_attr_at_index(attlist, num,
173 		    KMF_KEY_HANDLE_ATTR, keys, sizeof (KMF_KEY_HANDLE));
174 		num++;
175 
176 		rv = kmf_find_key(kmfhandle, num, attlist);
177 		if (rv == KMF_OK) {
178 			rv = pk_destroy_keys(kmfhandle, attlist, num);
179 		}
180 
181 		free(keys);
182 	}
183 
184 	*keysdeleted = numkeys;
185 	return (rv);
186 }
187 
188 static KMF_RETURN
189 pk_delete_certs(KMF_HANDLE_T kmfhandle, KMF_ATTRIBUTE *attlist, int numattr)
190 {
191 	KMF_RETURN rv = KMF_OK;
192 	uint32_t numcerts = 0;
193 	int num = numattr;
194 
195 	kmf_set_attr_at_index(attlist, num,
196 	    KMF_COUNT_ATTR, &numcerts, sizeof (uint32_t));
197 	num++;
198 
199 	rv = kmf_find_cert(kmfhandle, num, attlist);
200 	if (rv == KMF_OK && numcerts > 0) {
201 		char prompt[1024];
202 		(void) snprintf(prompt, sizeof (prompt),
203 		    gettext("%d certificate(s) found, do you want "
204 		    "to delete them (y/N) ?"), numcerts);
205 
206 		if (!yesno(prompt,
207 		    gettext("Respond with yes or no.\n"),
208 		    B_FALSE)) {
209 			return (KMF_OK);
210 		}
211 
212 		/*
213 		 * Use numattr because delete cert does not require
214 		 * KMF_COUNT_ATTR attribute.
215 		 */
216 		rv = kmf_delete_cert_from_keystore(kmfhandle, numattr, attlist);
217 
218 	}
219 
220 	return (rv);
221 }
222 
223 static KMF_RETURN
224 delete_nss_keys(KMF_HANDLE_T kmfhandle, char *dir, char *prefix,
225 	char *token, int oclass, char *objlabel,
226 	KMF_CREDENTIAL *tokencred)
227 {
228 	KMF_RETURN rv = KMF_OK;
229 	char *keytype = NULL;
230 	int nk, numkeys = 0;
231 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
232 	int numattr = 0;
233 	KMF_ATTRIBUTE attrlist[16];
234 	KMF_KEY_CLASS keyclass;
235 
236 	rv = configure_nss(kmfhandle, dir, prefix);
237 	if (rv != KMF_OK)
238 		return (rv);
239 
240 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
241 	    &kstype, sizeof (kstype));
242 	numattr++;
243 
244 	if (objlabel != NULL) {
245 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
246 		    objlabel, strlen(objlabel));
247 		numattr++;
248 	}
249 
250 	if (tokencred->credlen > 0) {
251 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
252 		    tokencred, sizeof (KMF_CREDENTIAL));
253 		numattr++;
254 	}
255 
256 	if (token && strlen(token)) {
257 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
258 		    token, strlen(token));
259 		numattr++;
260 	}
261 
262 	if (oclass & PK_PRIKEY_OBJ) {
263 		int num = numattr;
264 
265 		keyclass = KMF_ASYM_PRI;
266 		kmf_set_attr_at_index(attrlist, num, KMF_KEYCLASS_ATTR,
267 		    &keyclass, sizeof (keyclass));
268 		num++;
269 
270 		keytype = "private";
271 		rv = pk_delete_keys(kmfhandle, attrlist, num, keytype, &nk);
272 		numkeys += nk;
273 		if (rv == KMF_ERR_KEY_NOT_FOUND &&
274 		    oclass != PK_PRIKEY_OBJ)
275 			rv = KMF_OK;
276 	}
277 	if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
278 		int num = numattr;
279 
280 		keyclass = KMF_SYMMETRIC;
281 		kmf_set_attr_at_index(attrlist, num, KMF_KEYCLASS_ATTR,
282 		    &keyclass, sizeof (keyclass));
283 		num++;
284 
285 		keytype = "symmetric";
286 		rv = pk_delete_keys(kmfhandle, attrlist, num, keytype, &nk);
287 		numkeys += nk;
288 		if (rv == KMF_ERR_KEY_NOT_FOUND &&
289 		    oclass != PK_SYMKEY_OBJ)
290 			rv = KMF_OK;
291 	}
292 	if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) {
293 		int num = numattr;
294 
295 		keyclass = KMF_ASYM_PUB;
296 		kmf_set_attr_at_index(attrlist, num, KMF_KEYCLASS_ATTR,
297 		    &keyclass, sizeof (keyclass));
298 		num++;
299 
300 		keytype = "public";
301 		rv = pk_delete_keys(kmfhandle, attrlist, num, keytype, &nk);
302 		numkeys += nk;
303 		if (rv == KMF_ERR_KEY_NOT_FOUND &&
304 		    oclass != PK_PUBKEY_OBJ)
305 			rv = KMF_OK;
306 	}
307 	if (rv == KMF_OK && numkeys == 0)
308 		rv = KMF_ERR_KEY_NOT_FOUND;
309 
310 	return (rv);
311 }
312 
313 static KMF_RETURN
314 delete_nss_certs(KMF_HANDLE_T kmfhandle,
315 	char *dir, char *prefix,
316 	char *token, char *objlabel,
317 	KMF_BIGINT *serno, char *issuer, char *subject,
318 	KMF_CERT_VALIDITY find_criteria_flag)
319 {
320 	KMF_RETURN rv = KMF_OK;
321 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
322 	int numattr = 0;
323 	KMF_ATTRIBUTE attrlist[16];
324 
325 	rv = configure_nss(kmfhandle, dir, prefix);
326 	if (rv != KMF_OK)
327 		return (rv);
328 
329 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
330 		    &kstype, sizeof (kstype));
331 		numattr++;
332 
333 		if (objlabel != NULL) {
334 			kmf_set_attr_at_index(attrlist, numattr,
335 			    KMF_CERT_LABEL_ATTR, objlabel,
336 			    strlen(objlabel));
337 			numattr++;
338 		}
339 
340 		if (issuer != NULL) {
341 			kmf_set_attr_at_index(attrlist, numattr,
342 			    KMF_ISSUER_NAME_ATTR, issuer,
343 			    strlen(issuer));
344 			numattr++;
345 		}
346 
347 		if (subject != NULL) {
348 			kmf_set_attr_at_index(attrlist, numattr,
349 			    KMF_SUBJECT_NAME_ATTR, subject,
350 			    strlen(subject));
351 			numattr++;
352 		}
353 
354 		if (serno != NULL) {
355 			kmf_set_attr_at_index(attrlist, numattr,
356 			    KMF_BIGINT_ATTR, serno,
357 			    sizeof (KMF_BIGINT));
358 			numattr++;
359 		}
360 
361 		kmf_set_attr_at_index(attrlist, numattr,
362 		    KMF_CERT_VALIDITY_ATTR, &find_criteria_flag,
363 		    sizeof (KMF_CERT_VALIDITY));
364 		numattr++;
365 
366 		if (token != NULL) {
367 			kmf_set_attr_at_index(attrlist, numattr,
368 			    KMF_TOKEN_LABEL_ATTR, token,
369 			    strlen(token));
370 			numattr++;
371 		}
372 
373 	rv = pk_delete_certs(kmfhandle, attrlist, numattr);
374 
375 	return (rv);
376 }
377 
378 static KMF_RETURN
379 delete_nss_crl(void *kmfhandle,
380 	char *dir, char *prefix, char *token,
381 	char *issuer, char *subject)
382 {
383 	KMF_RETURN rv = KMF_OK;
384 	int numattr = 0;
385 	KMF_ATTRIBUTE attrlist[8];
386 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
387 
388 	rv = configure_nss(kmfhandle, dir, prefix);
389 	if (rv != KMF_OK)
390 		return (rv);
391 
392 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
393 	    &kstype, sizeof (kstype));
394 	numattr++;
395 
396 	if (token != NULL) {
397 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
398 		    token, strlen(token));
399 		numattr++;
400 	}
401 	if (issuer != NULL) {
402 		kmf_set_attr_at_index(attrlist, numattr, KMF_ISSUER_NAME_ATTR,
403 		    issuer, strlen(issuer));
404 		numattr++;
405 	}
406 	if (subject != NULL) {
407 		kmf_set_attr_at_index(attrlist, numattr, KMF_SUBJECT_NAME_ATTR,
408 		    subject, strlen(subject));
409 		numattr++;
410 	}
411 
412 	rv = kmf_delete_crl(kmfhandle, numattr, attrlist);
413 
414 	return (rv);
415 }
416 
417 static KMF_RETURN
418 delete_pk11_keys(KMF_HANDLE_T kmfhandle,
419 	char *token, int oclass, char *objlabel,
420 	KMF_CREDENTIAL *tokencred)
421 {
422 	KMF_RETURN rv = KMF_OK;
423 	int nk, numkeys = 0;
424 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
425 	int numattr = 0;
426 	KMF_ATTRIBUTE attrlist[16];
427 	KMF_KEY_CLASS keyclass;
428 	boolean_t token_bool = B_TRUE;
429 	boolean_t private;
430 	/*
431 	 * Symmetric keys and RSA/DSA private keys are always
432 	 * created with the "CKA_PRIVATE" field == TRUE, so
433 	 * make sure we search for them with it also set.
434 	 */
435 	if (oclass & (PK_SYMKEY_OBJ | PK_PRIKEY_OBJ))
436 		oclass |= PK_PRIVATE_OBJ;
437 
438 	rv = select_token(kmfhandle, token, FALSE);
439 	if (rv != KMF_OK) {
440 		return (rv);
441 	}
442 
443 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
444 	    &kstype, sizeof (kstype));
445 	numattr++;
446 
447 	if (objlabel != NULL) {
448 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
449 		    objlabel, strlen(objlabel));
450 		numattr++;
451 	}
452 
453 	if (tokencred != NULL && tokencred->credlen > 0) {
454 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
455 		    tokencred, sizeof (KMF_CREDENTIAL));
456 		numattr++;
457 	}
458 
459 	private = ((oclass & PK_PRIVATE_OBJ) > 0);
460 
461 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVATE_BOOL_ATTR,
462 	    &private, sizeof (private));
463 	numattr++;
464 
465 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
466 	    &token_bool, sizeof (token_bool));
467 	numattr++;
468 
469 	if (oclass & PK_PRIKEY_OBJ) {
470 		int num = numattr;
471 
472 		keyclass = KMF_ASYM_PRI;
473 		kmf_set_attr_at_index(attrlist, num, KMF_KEYCLASS_ATTR,
474 		    &keyclass, sizeof (keyclass));
475 		num++;
476 
477 		rv = pk_delete_keys(kmfhandle, attrlist, num, "private", &nk);
478 		numkeys += nk;
479 		if (rv == KMF_ERR_KEY_NOT_FOUND &&
480 		    oclass != PK_PRIKEY_OBJ)
481 			rv = KMF_OK;
482 	}
483 
484 	if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
485 		int num = numattr;
486 
487 		keyclass = KMF_SYMMETRIC;
488 		kmf_set_attr_at_index(attrlist, num, KMF_KEYCLASS_ATTR,
489 		    &keyclass, sizeof (keyclass));
490 		num++;
491 
492 		rv = pk_delete_keys(kmfhandle, attrlist, num, "symmetric", &nk);
493 		numkeys += nk;
494 		if (rv == KMF_ERR_KEY_NOT_FOUND &&
495 		    oclass != PK_SYMKEY_OBJ)
496 			rv = KMF_OK;
497 	}
498 
499 	if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) {
500 		int num = numattr;
501 
502 		private = B_FALSE;
503 		keyclass = KMF_ASYM_PUB;
504 		kmf_set_attr_at_index(attrlist, num, KMF_KEYCLASS_ATTR,
505 		    &keyclass, sizeof (keyclass));
506 		num++;
507 
508 		rv = pk_delete_keys(kmfhandle, attrlist, num, "public", &nk);
509 		numkeys += nk;
510 		if (rv == KMF_ERR_KEY_NOT_FOUND &&
511 		    oclass != PK_PUBKEY_OBJ)
512 			rv = KMF_OK;
513 	}
514 	if (rv == KMF_OK && numkeys == 0)
515 		rv = KMF_ERR_KEY_NOT_FOUND;
516 
517 	return (rv);
518 }
519 
520 static KMF_RETURN
521 delete_pk11_certs(KMF_HANDLE_T kmfhandle,
522 	char *token, char *objlabel,
523 	KMF_BIGINT *serno, char *issuer, char *subject,
524 	KMF_CERT_VALIDITY find_criteria_flag)
525 {
526 	KMF_RETURN kmfrv;
527 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
528 	int numattr = 0;
529 	KMF_ATTRIBUTE attrlist[16];
530 
531 	kmfrv = select_token(kmfhandle, token, FALSE);
532 
533 	if (kmfrv != KMF_OK) {
534 		return (kmfrv);
535 	}
536 
537 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
538 	    &kstype, sizeof (kstype));
539 	numattr++;
540 
541 	if (objlabel != NULL) {
542 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
543 		    objlabel, strlen(objlabel));
544 		numattr++;
545 	}
546 
547 	if (issuer != NULL) {
548 		kmf_set_attr_at_index(attrlist, numattr, KMF_ISSUER_NAME_ATTR,
549 		    issuer, strlen(issuer));
550 		numattr++;
551 	}
552 
553 	if (subject != NULL) {
554 		kmf_set_attr_at_index(attrlist, numattr, KMF_SUBJECT_NAME_ATTR,
555 		    subject, strlen(subject));
556 		numattr++;
557 	}
558 
559 	if (serno != NULL) {
560 		kmf_set_attr_at_index(attrlist, numattr, KMF_BIGINT_ATTR,
561 		    serno, sizeof (KMF_BIGINT));
562 		numattr++;
563 	}
564 
565 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_VALIDITY_ATTR,
566 	    &find_criteria_flag, sizeof (KMF_CERT_VALIDITY));
567 	numattr++;
568 
569 	kmfrv = pk_delete_certs(kmfhandle, attrlist, numattr);
570 
571 	return (kmfrv);
572 }
573 
574 static KMF_RETURN
575 delete_file_certs(KMF_HANDLE_T kmfhandle,
576 	char *dir, char *filename, KMF_BIGINT *serial, char *issuer,
577 	char *subject, KMF_CERT_VALIDITY find_criteria_flag)
578 {
579 	KMF_RETURN rv;
580 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
581 	int numattr = 0;
582 	KMF_ATTRIBUTE attrlist[16];
583 
584 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
585 	    &kstype, sizeof (kstype));
586 	numattr++;
587 
588 	if (issuer != NULL) {
589 		kmf_set_attr_at_index(attrlist, numattr, KMF_ISSUER_NAME_ATTR,
590 		    issuer, strlen(issuer));
591 		numattr++;
592 	}
593 
594 	if (subject != NULL) {
595 		kmf_set_attr_at_index(attrlist, numattr, KMF_SUBJECT_NAME_ATTR,
596 		    subject, strlen(subject));
597 		numattr++;
598 	}
599 
600 	if (serial != NULL) {
601 		kmf_set_attr_at_index(attrlist, numattr, KMF_BIGINT_ATTR,
602 		    serial, sizeof (KMF_BIGINT));
603 		numattr++;
604 	}
605 
606 	if (dir != NULL) {
607 		kmf_set_attr_at_index(attrlist, numattr, KMF_DIRPATH_ATTR,
608 		    dir, strlen(dir));
609 		numattr++;
610 	}
611 
612 	if (filename != NULL) {
613 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_FILENAME_ATTR,
614 		    filename, strlen(filename));
615 		numattr++;
616 	}
617 
618 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_VALIDITY_ATTR,
619 	    &find_criteria_flag, sizeof (KMF_CERT_VALIDITY));
620 	numattr++;
621 
622 	rv = pk_delete_certs(kmfhandle, attrlist, numattr);
623 
624 	return (rv);
625 }
626 
627 static KMF_RETURN
628 delete_file_keys(KMF_HANDLE_T kmfhandle, int oclass,
629 	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