delete.c revision 3089:8ddeb2ace8aa
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 2006 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.cred.cred = tokencred->cred;
284	parms.cred.credlen = tokencred->credlen;
285
286	if (oclass & PK_PRIKEY_OBJ) {
287		parms.keyclass = KMF_ASYM_PRI;
288		rv = pk_delete_keys(kmfhandle, &parms, "private", &nk);
289		numkeys += nk;
290	}
291
292	if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
293		parms.keyclass = KMF_SYMMETRIC;
294		rv = pk_delete_keys(kmfhandle, &parms, "symmetric", &nk);
295		numkeys += nk;
296	}
297
298	if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) {
299		parms.keyclass = KMF_ASYM_PUB;
300		rv = pk_delete_keys(kmfhandle, &parms, "public", &nk);
301		numkeys += nk;
302	}
303	if (rv == KMF_OK && numkeys == 0)
304		rv = KMF_ERR_KEY_NOT_FOUND;
305
306	return (rv);
307}
308
309static KMF_RETURN
310delete_pk11_certs(KMF_HANDLE_T kmfhandle,
311	char *token, char *objlabel,
312	KMF_BIGINT *serno, char *issuer, char *subject,
313	KMF_CERT_VALIDITY find_criteria_flag)
314{
315	KMF_RETURN kmfrv;
316	KMF_DELETECERT_PARAMS dparms;
317	KMF_FINDCERT_PARAMS fcargs;
318
319	kmfrv = select_token(kmfhandle, token, FALSE);
320
321	if (kmfrv != KMF_OK) {
322		return (kmfrv);
323	}
324
325	(void) memset(&dparms, 0, sizeof (dparms));
326	dparms.kstype = KMF_KEYSTORE_PK11TOKEN;
327	dparms.certLabel = objlabel;
328	dparms.issuer = issuer;
329	dparms.subject = subject;
330	dparms.serial = serno;
331	dparms.find_cert_validity = find_criteria_flag;
332
333	fcargs = dparms;
334	kmfrv = pk_delete_certs(kmfhandle, &fcargs, &dparms);
335
336	return (kmfrv);
337}
338
339static KMF_RETURN
340delete_file_certs(KMF_HANDLE_T kmfhandle,
341	char *dir, char *filename, KMF_BIGINT *serial, char *issuer,
342	char *subject, KMF_CERT_VALIDITY find_criteria_flag)
343{
344	KMF_RETURN rv;
345	KMF_DELETECERT_PARAMS dparms;
346	KMF_FINDCERT_PARAMS fcargs;
347
348	(void *)memset(&dparms, 0, sizeof (dparms));
349	(void *)memset(&fcargs, 0, sizeof (fcargs));
350	fcargs.kstype = KMF_KEYSTORE_OPENSSL;
351	fcargs.certLabel = NULL;
352	fcargs.issuer = issuer;
353	fcargs.subject = subject;
354	fcargs.serial = serial;
355	fcargs.sslparms.dirpath = dir;
356	fcargs.sslparms.certfile = filename;
357	fcargs.find_cert_validity = find_criteria_flag;
358
359	/* For now, delete parameters and find parameters are the same */
360	dparms = fcargs;
361
362	rv = pk_delete_certs(kmfhandle, &fcargs, &dparms);
363
364	return (rv);
365}
366
367static KMF_RETURN
368delete_file_keys(KMF_HANDLE_T kmfhandle, int oclass,
369	char *dir, char *infile)
370{
371	KMF_RETURN rv = KMF_OK;
372	KMF_FINDKEY_PARAMS parms;
373	char *keytype = "";
374	int nk, numkeys = 0;
375
376	(void) memset(&parms, 0, sizeof (parms));
377	parms.kstype = KMF_KEYSTORE_OPENSSL;
378	parms.sslparms.dirpath = dir;
379	parms.sslparms.keyfile = infile;
380
381	if (oclass & (PK_PUBKEY_OBJ | PK_PRIKEY_OBJ)) {
382		parms.keyclass = KMF_ASYM_PRI;
383		keytype = "Asymmetric";
384		rv = pk_delete_keys(kmfhandle, &parms, keytype, &nk);
385		numkeys += nk;
386	}
387	if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
388		parms.keyclass = KMF_SYMMETRIC;
389		keytype = "symmetric";
390		rv = pk_delete_keys(kmfhandle, &parms, keytype, &nk);
391		numkeys += nk;
392	}
393	if (rv == KMF_OK && numkeys == 0)
394		rv = KMF_ERR_KEY_NOT_FOUND;
395
396	return (rv);
397}
398
399static KMF_RETURN
400delete_file_crl(void *kmfhandle, char *dir, char *filename)
401{
402	KMF_RETURN rv;
403	KMF_DELETECRL_PARAMS dcrlparms;
404
405	(void) memset(&dcrlparms, 0, sizeof (dcrlparms));
406
407	dcrlparms.kstype = KMF_KEYSTORE_OPENSSL;
408	dcrlparms.sslparms.dirpath = dir;
409	dcrlparms.sslparms.crlfile = filename;
410
411	rv = KMF_DeleteCRL(kmfhandle, &dcrlparms);
412
413	return (rv);
414}
415
416/*
417 * Delete token objects.
418 */
419int
420pk_delete(int argc, char *argv[])
421{
422	int		opt;
423	extern int	optind_av;
424	extern char	*optarg_av;
425	char		*token_spec = NULL;
426	char		*subject = NULL;
427	char		*issuer = NULL;
428	char		*dir = NULL;
429	char		*prefix = NULL;
430	char		*infile = NULL;
431	char		*object_label = NULL;
432	char		*serstr = NULL;
433
434	int		oclass = 0;
435	KMF_BIGINT	serial = { NULL, 0 };
436	KMF_HANDLE_T	kmfhandle = NULL;
437	KMF_KEYSTORE_TYPE	kstype = 0;
438	KMF_RETURN	kmfrv;
439	int		rv = 0;
440	char			*find_criteria = NULL;
441	KMF_CERT_VALIDITY	find_criteria_flag = KMF_ALL_CERTS;
442	KMF_CREDENTIAL	tokencred = {NULL, 0};
443
444	/* Parse command line options.  Do NOT i18n/l10n. */
445	while ((opt = getopt_av(argc, argv,
446		"T:(token)y:(objtype)l:(label)"
447		"k:(keystore)s:(subject)n:(nickname)"
448		"d:(dir)p:(prefix)S:(serial)i:(issuer)"
449		"c:(criteria)"
450		"f:(infile)")) != EOF) {
451
452		if (EMPTYSTRING(optarg_av))
453			return (PK_ERR_USAGE);
454		switch (opt) {
455		case 'T':	/* token specifier */
456			if (token_spec)
457				return (PK_ERR_USAGE);
458			token_spec = optarg_av;
459			break;
460		case 'y':	/* object type:  public, private, both */
461			if (oclass)
462				return (PK_ERR_USAGE);
463			oclass = OT2Int(optarg_av);
464			if (oclass == -1)
465				return (PK_ERR_USAGE);
466			break;
467		case 'l':	/* objects with specific label */
468		case 'n':
469			if (object_label)
470				return (PK_ERR_USAGE);
471			object_label = (char *)optarg_av;
472			break;
473		case 'k':
474			kstype = KS2Int(optarg_av);
475			if (kstype == 0)
476				return (PK_ERR_USAGE);
477			break;
478		case 's':
479			subject = optarg_av;
480			break;
481		case 'i':
482			issuer = optarg_av;
483			break;
484		case 'd':
485			dir = optarg_av;
486			break;
487		case 'p':
488			prefix = optarg_av;
489			break;
490		case 'S':
491			serstr = optarg_av;
492			break;
493		case 'f':
494			infile = optarg_av;
495			break;
496		case 'c':
497			find_criteria = optarg_av;
498			if (!strcasecmp(find_criteria, "valid"))
499				find_criteria_flag =
500					KMF_NONEXPIRED_CERTS;
501			else if (!strcasecmp(find_criteria, "expired"))
502				find_criteria_flag = KMF_EXPIRED_CERTS;
503			else if (!strcasecmp(find_criteria, "both"))
504				find_criteria_flag = KMF_ALL_CERTS;
505			else
506				return (PK_ERR_USAGE);
507			break;
508		default:
509			return (PK_ERR_USAGE);
510			break;
511		}
512	}
513
514	/* Assume keystore = PKCS#11 if not specified */
515	if (kstype == 0)
516		kstype = KMF_KEYSTORE_PK11TOKEN;
517
518	/* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
519	if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
520		kstype != KMF_KEYSTORE_PK11TOKEN) {
521
522		(void) fprintf(stderr, gettext("The objtype parameter "
523			"is only relevant if keystore=pkcs11\n"));
524		return (PK_ERR_USAGE);
525	}
526
527	/* If no object class specified, delete everything but CRLs */
528	if (oclass == 0)
529		oclass = PK_CERT_OBJ | PK_PUBKEY_OBJ | PK_PRIKEY_OBJ |
530			PK_SYMKEY_OBJ;
531
532	/* No additional args allowed. */
533	argc -= optind_av;
534	argv += optind_av;
535	if (argc)
536		return (PK_ERR_USAGE);
537	/* Done parsing command line options. */
538
539	if (kstype == KMF_KEYSTORE_PK11TOKEN && token_spec == NULL) {
540		token_spec = PK_DEFAULT_PK11TOKEN;
541	} else if (kstype == KMF_KEYSTORE_NSS && token_spec == NULL) {
542		token_spec = DEFAULT_NSS_TOKEN;
543	}
544
545	if (serstr != NULL) {
546		uchar_t *bytes = NULL;
547		size_t bytelen;
548
549		rv = KMF_HexString2Bytes((uchar_t *)serstr, &bytes, &bytelen);
550		if (rv != KMF_OK || bytes == NULL) {
551			(void) fprintf(stderr, gettext("serial number "
552				"must be specified as a hex number "
553				"(ex: 0x0102030405ffeeddee)\n"));
554			return (PK_ERR_USAGE);
555		}
556		serial.val = bytes;
557		serial.len = bytelen;
558	}
559
560	if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
561		kstype == KMF_KEYSTORE_NSS) &&
562		(oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ))) {
563
564		(void) get_token_password(kstype, token_spec,
565			&tokencred);
566	}
567
568	if ((kmfrv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK)
569		return (kmfrv);
570
571	switch (kstype) {
572		case KMF_KEYSTORE_PK11TOKEN:
573			if (oclass & PK_KEY_OBJ) {
574				kmfrv = delete_pk11_keys(kmfhandle,
575						token_spec, oclass,
576						object_label,
577						&tokencred);
578				/*
579				 * If deleting groups of objects, it is OK
580				 * to ignore the "key not found" case so that
581				 * we can continue to find other objects.
582				 */
583				if (kmfrv == KMF_ERR_KEY_NOT_FOUND &&
584					(oclass != PK_KEY_OBJ))
585					kmfrv = KMF_OK;
586				if (kmfrv != KMF_OK)
587					break;
588			}
589			if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
590				kmfrv = delete_pk11_certs(kmfhandle,
591						token_spec,
592						object_label,
593						&serial, issuer,
594						subject, find_criteria_flag);
595				/*
596				 * If cert delete failed, but we are looking at
597				 * other objects, then it is OK.
598				 */
599				if (kmfrv == KMF_ERR_CERT_NOT_FOUND &&
600					(oclass & (PK_CRL_OBJ | PK_KEY_OBJ)))
601					kmfrv = KMF_OK;
602				if (kmfrv != KMF_OK)
603					break;
604			}
605			if (oclass & PK_CRL_OBJ)
606				kmfrv = delete_file_crl(kmfhandle,
607						dir, infile);
608			break;
609		case KMF_KEYSTORE_NSS:
610			if (oclass & PK_KEY_OBJ) {
611				kmfrv = delete_nss_keys(kmfhandle,
612					dir, prefix, token_spec,
613					oclass, (char  *)object_label,
614					&tokencred);
615				if (kmfrv != KMF_OK)
616					break;
617			}
618			if (oclass & PK_CERT_OBJ) {
619				kmfrv = delete_nss_certs(kmfhandle,
620					dir, prefix, token_spec,
621					(char  *)object_label,
622					&serial, issuer, subject,
623					find_criteria_flag);
624				if (kmfrv != KMF_OK)
625					break;
626			}
627			if (oclass & PK_CRL_OBJ)
628				kmfrv = delete_nss_crl(kmfhandle,
629					dir, prefix, token_spec,
630					(char  *)object_label, subject);
631			break;
632		case KMF_KEYSTORE_OPENSSL:
633			if (oclass & PK_KEY_OBJ) {
634				kmfrv = delete_file_keys(kmfhandle, oclass,
635					dir, infile);
636				if (kmfrv != KMF_OK)
637					break;
638			}
639			if (oclass & (PK_CERT_OBJ)) {
640				kmfrv = delete_file_certs(kmfhandle,
641					dir, infile, &serial, issuer,
642					subject, find_criteria_flag);
643				if (kmfrv != KMF_OK)
644					break;
645			}
646			if (oclass & PK_CRL_OBJ)
647				kmfrv = delete_file_crl(kmfhandle,
648					dir, infile);
649			break;
650		default:
651			rv = PK_ERR_USAGE;
652			break;
653	}
654
655	if (kmfrv != KMF_OK) {
656		display_error(kmfhandle, kmfrv,
657			gettext("Error deleting objects"));
658	}
659
660	if (serial.val != NULL)
661		free(serial.val);
662	(void) KMF_Finalize(kmfhandle);
663	return (kmfrv);
664}
665