delete.c revision 3408:67ca9373b99e
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 2007 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
41static KMF_RETURN
42pk_destroy_keys(void *handle, KMF_KEY_HANDLE *keys,
43	KMF_FINDKEY_PARAMS *fkparams, uint32_t numkeys)
44{
45	int i;
46	KMF_RETURN rv = KMF_OK;
47	KMF_DELETEKEY_PARAMS dkparams;
48
49	(void) memset(&dkparams, 0, sizeof (dkparams));
50	dkparams.kstype = fkparams->kstype;
51
52	switch (fkparams->kstype) {
53	case KMF_KEYSTORE_NSS:
54		dkparams.nssparms = fkparams->nssparms;
55		dkparams.cred = fkparams->cred;
56		break;
57	case KMF_KEYSTORE_OPENSSL:
58		break;
59	case KMF_KEYSTORE_PK11TOKEN:
60		dkparams.cred = fkparams->cred;
61		break;
62	default:
63		return (PK_ERR_USAGE);
64	}
65
66	for (i = 0; rv == KMF_OK && i < numkeys; i++) {
67		rv = KMF_DeleteKeyFromKeystore(handle, &dkparams, &keys[i]);
68	}
69	return (rv);
70}
71
72static KMF_RETURN
73pk_delete_keys(KMF_HANDLE_T kmfhandle, KMF_FINDKEY_PARAMS *parms, char *desc,
74	int *keysdeleted)
75{
76	KMF_RETURN rv = KMF_OK;
77	uint32_t numkeys = 0;
78
79	*keysdeleted = 0;
80	numkeys = 0;
81	rv = KMF_FindKey(kmfhandle, parms, NULL, &numkeys);
82	if (rv == KMF_OK && numkeys > 0) {
83		KMF_KEY_HANDLE *keys = NULL;
84		char prompt[1024];
85
86		(void) snprintf(prompt, sizeof (prompt),
87			gettext("%d %s key(s) found, do you want "
88			"to delete them (y/N) ?"), numkeys,
89			(desc != NULL ? desc : ""));
90
91		if (!yesno(prompt,
92			gettext("Respond with yes or no.\n"),
93			B_FALSE)) {
94			return (KMF_OK);
95		}
96		keys = (KMF_KEY_HANDLE *)malloc(numkeys *
97				sizeof (KMF_KEY_HANDLE));
98		if (keys == NULL)
99			return (KMF_ERR_MEMORY);
100		(void) memset(keys, 0, numkeys *
101			sizeof (KMF_KEY_HANDLE));
102
103		rv = KMF_FindKey(kmfhandle, parms, keys, &numkeys);
104		if (rv == KMF_OK) {
105			rv = pk_destroy_keys(kmfhandle, keys,
106				parms, numkeys);
107		}
108
109		free(keys);
110	}
111
112	if (rv == KMF_ERR_KEY_NOT_FOUND) {
113		rv = KMF_OK;
114	}
115
116	*keysdeleted = numkeys;
117	return (rv);
118}
119
120static KMF_RETURN
121pk_delete_certs(KMF_HANDLE_T kmfhandle, KMF_FINDCERT_PARAMS *fcparms,
122	KMF_DELETECERT_PARAMS *dcparms)
123{
124	KMF_RETURN rv = KMF_OK;
125	uint32_t numcerts = 0;
126
127	rv = KMF_FindCert(kmfhandle, fcparms, NULL, &numcerts);
128	if (rv == KMF_OK && numcerts > 0) {
129		char prompt[1024];
130		(void) snprintf(prompt, sizeof (prompt),
131			gettext("%d certificate(s) found, do you want "
132			"to delete them (y/N) ?"), numcerts);
133
134		if (!yesno(prompt,
135			gettext("Respond with yes or no.\n"),
136			B_FALSE)) {
137			return (KMF_OK);
138		}
139
140		rv = KMF_DeleteCertFromKeystore(kmfhandle, dcparms);
141
142	} else if (rv == KMF_ERR_CERT_NOT_FOUND) {
143		rv = KMF_OK;
144	}
145
146	return (rv);
147}
148
149static KMF_RETURN
150delete_nss_keys(KMF_HANDLE_T kmfhandle, char *dir, char *prefix,
151	char *token, int oclass, char *objlabel,
152	KMF_CREDENTIAL *tokencred)
153{
154	KMF_RETURN rv = KMF_OK;
155	KMF_FINDKEY_PARAMS parms;
156	char *keytype = NULL;
157	int nk, numkeys = 0;
158
159	rv = configure_nss(kmfhandle, dir, prefix);
160	if (rv != KMF_OK)
161		return (rv);
162
163	(void) memset(&parms, 0, sizeof (parms));
164	parms.kstype = KMF_KEYSTORE_NSS;
165	parms.findLabel = objlabel;
166	parms.cred = *tokencred;
167	parms.nssparms.slotlabel = token;
168
169	if (oclass & PK_PRIKEY_OBJ) {
170		parms.keyclass = KMF_ASYM_PRI;
171		keytype = "private";
172		rv = pk_delete_keys(kmfhandle, &parms, keytype, &nk);
173		numkeys += nk;
174	}
175	if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
176		parms.keyclass = KMF_SYMMETRIC;
177		keytype = "symmetric";
178		rv = pk_delete_keys(kmfhandle, &parms, keytype, &nk);
179		numkeys += nk;
180	}
181	if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) {
182		parms.keyclass = KMF_ASYM_PUB;
183		keytype = "public";
184		rv = pk_delete_keys(kmfhandle, &parms, keytype, &nk);
185		numkeys += nk;
186	}
187	if (rv == KMF_OK && numkeys == 0)
188		rv = KMF_ERR_KEY_NOT_FOUND;
189
190	return (rv);
191}
192
193
194static KMF_RETURN
195delete_nss_certs(KMF_HANDLE_T kmfhandle,
196	char *dir, char *prefix,
197	char *token, char *objlabel,
198	KMF_BIGINT *serno, char *issuer, char *subject,
199	KMF_CERT_VALIDITY find_criteria_flag)
200{
201	KMF_RETURN rv = KMF_OK;
202	KMF_DELETECERT_PARAMS dcparms;
203	KMF_FINDCERT_PARAMS fcargs;
204
205	rv = configure_nss(kmfhandle, dir, prefix);
206	if (rv != KMF_OK)
207		return (rv);
208
209	(void) memset(&dcparms, 0, sizeof (dcparms));
210	dcparms.kstype = KMF_KEYSTORE_NSS;
211	dcparms.certLabel = objlabel;
212	dcparms.issuer = issuer;
213	dcparms.subject = subject;
214	dcparms.serial = serno;
215	dcparms.find_cert_validity = find_criteria_flag;
216	dcparms.nssparms.slotlabel = token;
217
218	(void) memset(&fcargs, 0, sizeof (fcargs));
219	fcargs.kstype = KMF_KEYSTORE_NSS;
220	fcargs.certLabel = objlabel;
221	fcargs.issuer = issuer;
222	fcargs.subject = subject;
223	fcargs.serial = serno;
224	fcargs.find_cert_validity = find_criteria_flag;
225	fcargs.nssparms.slotlabel = token;
226
227	rv = pk_delete_certs(kmfhandle, &fcargs, &dcparms);
228
229	return (rv);
230}
231
232static KMF_RETURN
233delete_nss_crl(void *kmfhandle,
234	char *dir, char *prefix, char *token,
235	char *issuernickname, char *subject)
236{
237	KMF_RETURN rv = KMF_OK;
238	KMF_DELETECRL_PARAMS dcrlparms;
239
240	rv = configure_nss(kmfhandle, dir, prefix);
241	if (rv != KMF_OK)
242		return (rv);
243
244	(void) memset(&dcrlparms, 0, sizeof (dcrlparms));
245
246	dcrlparms.kstype = KMF_KEYSTORE_NSS;
247	dcrlparms.nssparms.slotlabel = token;
248	dcrlparms.nssparms.crl_issuerName = issuernickname;
249	dcrlparms.nssparms.crl_subjName = subject;
250
251	rv = KMF_DeleteCRL(kmfhandle, &dcrlparms);
252
253	return (rv);
254}
255
256static KMF_RETURN
257delete_pk11_keys(KMF_HANDLE_T kmfhandle,
258	char *token, int oclass, char *objlabel,
259	KMF_CREDENTIAL *tokencred)
260{
261	KMF_RETURN rv = KMF_OK;
262	KMF_FINDKEY_PARAMS parms;
263	int nk, numkeys = 0;
264
265	/*
266	 * Symmetric keys and RSA/DSA private keys are always
267	 * created with the "CKA_PRIVATE" field == TRUE, so
268	 * make sure we search for them with it also set.
269	 */
270	if (oclass & (PK_SYMKEY_OBJ | PK_PRIKEY_OBJ))
271		oclass |= PK_PRIVATE_OBJ;
272
273	rv = select_token(kmfhandle, token, FALSE);
274	if (rv != KMF_OK) {
275		return (rv);
276	}
277
278	(void) memset(&parms, 0, sizeof (parms));
279	parms.kstype = KMF_KEYSTORE_PK11TOKEN;
280	parms.findLabel = (char *)objlabel;
281	parms.keytype = 0;
282	parms.pkcs11parms.private = ((oclass & PK_PRIVATE_OBJ) > 0);
283	parms.pkcs11parms.token = 1;
284	parms.cred.cred = tokencred->cred;
285	parms.cred.credlen = tokencred->credlen;
286
287	if (oclass & PK_PRIKEY_OBJ) {
288		parms.keyclass = KMF_ASYM_PRI;
289		rv = pk_delete_keys(kmfhandle, &parms, "private", &nk);
290		numkeys += nk;
291	}
292
293	if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
294		parms.keyclass = KMF_SYMMETRIC;
295		rv = pk_delete_keys(kmfhandle, &parms, "symmetric", &nk);
296		numkeys += nk;
297	}
298
299	if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) {
300		parms.keyclass = KMF_ASYM_PUB;
301		rv = pk_delete_keys(kmfhandle, &parms, "public", &nk);
302		numkeys += nk;
303	}
304	if (rv == KMF_OK && numkeys == 0)
305		rv = KMF_ERR_KEY_NOT_FOUND;
306
307	return (rv);
308}
309
310static KMF_RETURN
311delete_pk11_certs(KMF_HANDLE_T kmfhandle,
312	char *token, char *objlabel,
313	KMF_BIGINT *serno, char *issuer, char *subject,
314	KMF_CERT_VALIDITY find_criteria_flag)
315{
316	KMF_RETURN kmfrv;
317	KMF_DELETECERT_PARAMS dparms;
318	KMF_FINDCERT_PARAMS fcargs;
319
320	kmfrv = select_token(kmfhandle, token, FALSE);
321
322	if (kmfrv != KMF_OK) {
323		return (kmfrv);
324	}
325
326	(void) memset(&dparms, 0, sizeof (dparms));
327	dparms.kstype = KMF_KEYSTORE_PK11TOKEN;
328	dparms.certLabel = objlabel;
329	dparms.issuer = issuer;
330	dparms.subject = subject;
331	dparms.serial = serno;
332	dparms.find_cert_validity = find_criteria_flag;
333
334	fcargs = dparms;
335	kmfrv = pk_delete_certs(kmfhandle, &fcargs, &dparms);
336
337	return (kmfrv);
338}
339
340static KMF_RETURN
341delete_file_certs(KMF_HANDLE_T kmfhandle,
342	char *dir, char *filename, KMF_BIGINT *serial, char *issuer,
343	char *subject, KMF_CERT_VALIDITY find_criteria_flag)
344{
345	KMF_RETURN rv;
346	KMF_DELETECERT_PARAMS dparms;
347	KMF_FINDCERT_PARAMS fcargs;
348
349	(void *)memset(&dparms, 0, sizeof (dparms));
350	(void *)memset(&fcargs, 0, sizeof (fcargs));
351	fcargs.kstype = KMF_KEYSTORE_OPENSSL;
352	fcargs.certLabel = NULL;
353	fcargs.issuer = issuer;
354	fcargs.subject = subject;
355	fcargs.serial = serial;
356	fcargs.sslparms.dirpath = dir;
357	fcargs.sslparms.certfile = filename;
358	fcargs.find_cert_validity = find_criteria_flag;
359
360	/* For now, delete parameters and find parameters are the same */
361	dparms = fcargs;
362
363	rv = pk_delete_certs(kmfhandle, &fcargs, &dparms);
364
365	return (rv);
366}
367
368static KMF_RETURN
369delete_file_keys(KMF_HANDLE_T kmfhandle, int oclass,
370	char *dir, char *infile)
371{
372	KMF_RETURN rv = KMF_OK;
373	KMF_FINDKEY_PARAMS parms;
374	char *keytype = "";
375	int nk, numkeys = 0;
376
377	(void) memset(&parms, 0, sizeof (parms));
378	parms.kstype = KMF_KEYSTORE_OPENSSL;
379	parms.sslparms.dirpath = dir;
380	parms.sslparms.keyfile = infile;
381
382	if (oclass & (PK_PUBKEY_OBJ | PK_PRIKEY_OBJ)) {
383		parms.keyclass = KMF_ASYM_PRI;
384		keytype = "Asymmetric";
385		rv = pk_delete_keys(kmfhandle, &parms, keytype, &nk);
386		numkeys += nk;
387	}
388	if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
389		parms.keyclass = KMF_SYMMETRIC;
390		keytype = "symmetric";
391		rv = pk_delete_keys(kmfhandle, &parms, keytype, &nk);
392		numkeys += nk;
393	}
394	if (rv == KMF_OK && numkeys == 0)
395		rv = KMF_ERR_KEY_NOT_FOUND;
396
397	return (rv);
398}
399
400static KMF_RETURN
401delete_file_crl(void *kmfhandle, char *dir, char *filename)
402{
403	KMF_RETURN rv;
404	KMF_DELETECRL_PARAMS dcrlparms;
405
406	(void) memset(&dcrlparms, 0, sizeof (dcrlparms));
407
408	dcrlparms.kstype = KMF_KEYSTORE_OPENSSL;
409	dcrlparms.sslparms.dirpath = dir;
410	dcrlparms.sslparms.crlfile = filename;
411
412	rv = KMF_DeleteCRL(kmfhandle, &dcrlparms);
413
414	return (rv);
415}
416
417/*
418 * Delete token objects.
419 */
420int
421pk_delete(int argc, char *argv[])
422{
423	int		opt;
424	extern int	optind_av;
425	extern char	*optarg_av;
426	char		*token_spec = NULL;
427	char		*subject = NULL;
428	char		*issuer = NULL;
429	char		*dir = NULL;
430	char		*prefix = NULL;
431	char		*infile = NULL;
432	char		*object_label = NULL;
433	char		*serstr = NULL;
434
435	int		oclass = 0;
436	KMF_BIGINT	serial = { NULL, 0 };
437	KMF_HANDLE_T	kmfhandle = NULL;
438	KMF_KEYSTORE_TYPE	kstype = 0;
439	KMF_RETURN	kmfrv;
440	int		rv = 0;
441	char			*find_criteria = NULL;
442	KMF_CERT_VALIDITY	find_criteria_flag = KMF_ALL_CERTS;
443	KMF_CREDENTIAL	tokencred = {NULL, 0};
444
445	/* Parse command line options.  Do NOT i18n/l10n. */
446	while ((opt = getopt_av(argc, argv,
447		"T:(token)y:(objtype)l:(label)"
448		"k:(keystore)s:(subject)n:(nickname)"
449		"d:(dir)p:(prefix)S:(serial)i:(issuer)"
450		"c:(criteria)"
451		"f:(infile)")) != EOF) {
452
453		if (EMPTYSTRING(optarg_av))
454			return (PK_ERR_USAGE);
455		switch (opt) {
456		case 'T':	/* token specifier */
457			if (token_spec)
458				return (PK_ERR_USAGE);
459			token_spec = optarg_av;
460			break;
461		case 'y':	/* object type:  public, private, both */
462			if (oclass)
463				return (PK_ERR_USAGE);
464			oclass = OT2Int(optarg_av);
465			if (oclass == -1)
466				return (PK_ERR_USAGE);
467			break;
468		case 'l':	/* objects with specific label */
469		case 'n':
470			if (object_label)
471				return (PK_ERR_USAGE);
472			object_label = (char *)optarg_av;
473			break;
474		case 'k':
475			kstype = KS2Int(optarg_av);
476			if (kstype == 0)
477				return (PK_ERR_USAGE);
478			break;
479		case 's':
480			subject = optarg_av;
481			break;
482		case 'i':
483			issuer = optarg_av;
484			break;
485		case 'd':
486			dir = optarg_av;
487			break;
488		case 'p':
489			prefix = optarg_av;
490			break;
491		case 'S':
492			serstr = optarg_av;
493			break;
494		case 'f':
495			infile = optarg_av;
496			break;
497		case 'c':
498			find_criteria = optarg_av;
499			if (!strcasecmp(find_criteria, "valid"))
500				find_criteria_flag =
501					KMF_NONEXPIRED_CERTS;
502			else if (!strcasecmp(find_criteria, "expired"))
503				find_criteria_flag = KMF_EXPIRED_CERTS;
504			else if (!strcasecmp(find_criteria, "both"))
505				find_criteria_flag = KMF_ALL_CERTS;
506			else
507				return (PK_ERR_USAGE);
508			break;
509		default:
510			return (PK_ERR_USAGE);
511			break;
512		}
513	}
514
515	/* Assume keystore = PKCS#11 if not specified */
516	if (kstype == 0)
517		kstype = KMF_KEYSTORE_PK11TOKEN;
518
519	/* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
520	if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
521		kstype != KMF_KEYSTORE_PK11TOKEN) {
522
523		(void) fprintf(stderr, gettext("The objtype parameter "
524			"is only relevant if keystore=pkcs11\n"));
525		return (PK_ERR_USAGE);
526	}
527
528	/* If no object class specified, delete everything but CRLs */
529	if (oclass == 0)
530		oclass = PK_CERT_OBJ | PK_PUBKEY_OBJ | PK_PRIKEY_OBJ |
531			PK_SYMKEY_OBJ;
532
533	/* No additional args allowed. */
534	argc -= optind_av;
535	argv += optind_av;
536	if (argc)
537		return (PK_ERR_USAGE);
538	/* Done parsing command line options. */
539
540	if (kstype == KMF_KEYSTORE_PK11TOKEN && token_spec == NULL) {
541		token_spec = PK_DEFAULT_PK11TOKEN;
542	} else if (kstype == KMF_KEYSTORE_NSS && token_spec == NULL) {
543		token_spec = DEFAULT_NSS_TOKEN;
544	}
545
546	if (serstr != NULL) {
547		uchar_t *bytes = NULL;
548		size_t bytelen;
549
550		rv = KMF_HexString2Bytes((uchar_t *)serstr, &bytes, &bytelen);
551		if (rv != KMF_OK || bytes == NULL) {
552			(void) fprintf(stderr, gettext("serial number "
553				"must be specified as a hex number "
554				"(ex: 0x0102030405ffeeddee)\n"));
555			return (PK_ERR_USAGE);
556		}
557		serial.val = bytes;
558		serial.len = bytelen;
559	}
560
561	if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
562		kstype == KMF_KEYSTORE_NSS) &&
563		(oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ))) {
564
565		(void) get_token_password(kstype, token_spec,
566			&tokencred);
567	}
568
569	if ((kmfrv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK)
570		return (kmfrv);
571
572	switch (kstype) {
573		case KMF_KEYSTORE_PK11TOKEN:
574			if (oclass & PK_KEY_OBJ) {
575				kmfrv = delete_pk11_keys(kmfhandle,
576						token_spec, oclass,
577						object_label,
578						&tokencred);
579				/*
580				 * If deleting groups of objects, it is OK
581				 * to ignore the "key not found" case so that
582				 * we can continue to find other objects.
583				 */
584				if (kmfrv == KMF_ERR_KEY_NOT_FOUND &&
585					(oclass != PK_KEY_OBJ))
586					kmfrv = KMF_OK;
587				if (kmfrv != KMF_OK)
588					break;
589			}
590			if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
591				kmfrv = delete_pk11_certs(kmfhandle,
592						token_spec,
593						object_label,
594						&serial, issuer,
595						subject, find_criteria_flag);
596				/*
597				 * If cert delete failed, but we are looking at
598				 * other objects, then it is OK.
599				 */
600				if (kmfrv == KMF_ERR_CERT_NOT_FOUND &&
601					(oclass & (PK_CRL_OBJ | PK_KEY_OBJ)))
602					kmfrv = KMF_OK;
603				if (kmfrv != KMF_OK)
604					break;
605			}
606			if (oclass & PK_CRL_OBJ)
607				kmfrv = delete_file_crl(kmfhandle,
608						dir, infile);
609			break;
610		case KMF_KEYSTORE_NSS:
611			if (oclass & PK_KEY_OBJ) {
612				kmfrv = delete_nss_keys(kmfhandle,
613					dir, prefix, token_spec,
614					oclass, (char  *)object_label,
615					&tokencred);
616				if (kmfrv != KMF_OK)
617					break;
618			}
619			if (oclass & PK_CERT_OBJ) {
620				kmfrv = delete_nss_certs(kmfhandle,
621					dir, prefix, token_spec,
622					(char  *)object_label,
623					&serial, issuer, subject,
624					find_criteria_flag);
625				if (kmfrv != KMF_OK)
626					break;
627			}
628			if (oclass & PK_CRL_OBJ)
629				kmfrv = delete_nss_crl(kmfhandle,
630					dir, prefix, token_spec,
631					(char  *)object_label, subject);
632			break;
633		case KMF_KEYSTORE_OPENSSL:
634			if (oclass & PK_KEY_OBJ) {
635				kmfrv = delete_file_keys(kmfhandle, oclass,
636					dir, infile);
637				if (kmfrv != KMF_OK)
638					break;
639			}
640			if (oclass & (PK_CERT_OBJ)) {
641				kmfrv = delete_file_certs(kmfhandle,
642					dir, infile, &serial, issuer,
643					subject, find_criteria_flag);
644				if (kmfrv != KMF_OK)
645					break;
646			}
647			if (oclass & PK_CRL_OBJ)
648				kmfrv = delete_file_crl(kmfhandle,
649					dir, infile);
650			break;
651		default:
652			rv = PK_ERR_USAGE;
653			break;
654	}
655
656	if (kmfrv != KMF_OK) {
657		display_error(kmfhandle, kmfrv,
658			gettext("Error deleting objects"));
659	}
660
661	if (serial.val != NULL)
662		free(serial.val);
663	(void) KMF_Finalize(kmfhandle);
664	return (kmfrv);
665}
666