xref: /titanic_44/usr/src/cmd/cmd-crypto/pktool/delete.c (revision 49e212991a3065f7e499a4b29ae8d8eaf33f3135)
17711facfSdinak /*
27711facfSdinak  * CDDL HEADER START
37711facfSdinak  *
47711facfSdinak  * The contents of this file are subject to the terms of the
57711facfSdinak  * Common Development and Distribution License, Version 1.0 only
67711facfSdinak  * (the "License").  You may not use this file except in compliance
77711facfSdinak  * with the License.
87711facfSdinak  *
97711facfSdinak  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107711facfSdinak  * or http://www.opensolaris.org/os/licensing.
117711facfSdinak  * See the License for the specific language governing permissions
127711facfSdinak  * and limitations under the License.
137711facfSdinak  *
147711facfSdinak  * When distributing Covered Code, include this CDDL HEADER in each
157711facfSdinak  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167711facfSdinak  * If applicable, add the following below this CDDL HEADER, with the
177711facfSdinak  * fields enclosed by brackets "[]" replaced with your own identifying
187711facfSdinak  * information: Portions Copyright [yyyy] [name of copyright owner]
197711facfSdinak  *
207711facfSdinak  * CDDL HEADER END
217711facfSdinak  */
227711facfSdinak /*
237711facfSdinak  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247711facfSdinak  * Use is subject to license terms.
257711facfSdinak  */
267711facfSdinak 
277711facfSdinak #pragma ident	"%Z%%M%	%I%	%E% SMI"
287711facfSdinak 
297711facfSdinak /*
307711facfSdinak  * This file implements the token object delete operation for this tool.
317711facfSdinak  * It loads the PKCS#11 modules, finds the object to delete, deletes it,
327711facfSdinak  * and cleans up.  User must be R/W logged into the token.
337711facfSdinak  */
347711facfSdinak 
357711facfSdinak #include <stdio.h>
367711facfSdinak #include <string.h>
377711facfSdinak #include <cryptoutil.h>
387711facfSdinak #include <security/cryptoki.h>
397711facfSdinak #include "common.h"
407711facfSdinak 
417711facfSdinak /*
427711facfSdinak  * Delete token objects.
437711facfSdinak  */
447711facfSdinak int
457711facfSdinak pk_delete(int argc, char *argv[])
467711facfSdinak {
477711facfSdinak 	int		opt;
48*49e21299Sdinak 	extern int	optind_av;
49*49e21299Sdinak 	extern char	*optarg_av;
50*49e21299Sdinak 	char		*token_spec = NULL;
517711facfSdinak 	char		*token_name = NULL;
527711facfSdinak 	char		*manuf_id = NULL;
537711facfSdinak 	char		*serial_no = NULL;
54*49e21299Sdinak 	char		*type_spec = NULL;
557711facfSdinak 	char		full_name[FULL_NAME_LEN];
567711facfSdinak 	boolean_t	public_objs = B_FALSE;
577711facfSdinak 	boolean_t	private_objs = B_FALSE;
587711facfSdinak 	CK_BYTE		*object_label = NULL;
597711facfSdinak 	int		obj_type = 0x00;
607711facfSdinak 	CK_SLOT_ID	slot_id;
617711facfSdinak 	CK_FLAGS	pin_state;
627711facfSdinak 	CK_UTF8CHAR_PTR	pin = NULL;
637711facfSdinak 	CK_ULONG	pinlen = 0;
647711facfSdinak 	CK_SESSION_HANDLE	sess;
657711facfSdinak 	CK_OBJECT_HANDLE	*objs;
667711facfSdinak 	CK_ULONG	num_objs;
677711facfSdinak 	CK_ATTRIBUTE	label = { CKA_LABEL, NULL, 0 };
687711facfSdinak 	CK_RV		rv = CKR_OK;
697711facfSdinak 	int		i;
707711facfSdinak 
717711facfSdinak 	cryptodebug("inside pk_delete");
727711facfSdinak 
737711facfSdinak 	/* Parse command line options.  Do NOT i18n/l10n. */
74*49e21299Sdinak 	while ((opt = getopt_av(argc, argv,
75*49e21299Sdinak 	    "T:(token)y:(objtype)l:(label)")) != EOF) {
767711facfSdinak 		switch (opt) {
77*49e21299Sdinak 		case 'T':	/* token specifier */
78*49e21299Sdinak 			if (token_spec)
79*49e21299Sdinak 				return (PK_ERR_USAGE);
80*49e21299Sdinak 			token_spec = optarg_av;
817711facfSdinak 			break;
82*49e21299Sdinak 		case 'y':	/* object type:  public, private, both */
83*49e21299Sdinak 			if (type_spec)
84*49e21299Sdinak 				return (PK_ERR_USAGE);
85*49e21299Sdinak 			type_spec = optarg_av;
867711facfSdinak 			break;
877711facfSdinak 		case 'l':	/* objects with specific label */
887711facfSdinak 			if (object_label)
897711facfSdinak 				return (PK_ERR_USAGE);
90*49e21299Sdinak 			object_label = (CK_BYTE *)optarg_av;
917711facfSdinak 			break;
927711facfSdinak 		default:
937711facfSdinak 			return (PK_ERR_USAGE);
947711facfSdinak 			break;
957711facfSdinak 		}
967711facfSdinak 	}
977711facfSdinak 
98*49e21299Sdinak 	/* If no token is specified, default is to use softtoken. */
99*49e21299Sdinak 	if (token_spec == NULL) {
100*49e21299Sdinak 		token_name = SOFT_TOKEN_LABEL;
101*49e21299Sdinak 		manuf_id = SOFT_MANUFACTURER_ID;
102*49e21299Sdinak 		serial_no = SOFT_TOKEN_SERIAL;
103*49e21299Sdinak 	} else {
104*49e21299Sdinak 		/*
105*49e21299Sdinak 		 * Parse token specifier into token_name, manuf_id, serial_no.
106*49e21299Sdinak 		 * Token_name is required; manuf_id and serial_no are optional.
107*49e21299Sdinak 		 */
108*49e21299Sdinak 		if (parse_token_spec(token_spec, &token_name, &manuf_id,
109*49e21299Sdinak 		    &serial_no) < 0)
110*49e21299Sdinak 			return (PK_ERR_USAGE);
111*49e21299Sdinak 	}
112*49e21299Sdinak 
113*49e21299Sdinak 	/* If no object type specified, default is public objects. */
114*49e21299Sdinak 	if (!type_spec) {
115*49e21299Sdinak 		public_objs = B_TRUE;
116*49e21299Sdinak 	} else {
117*49e21299Sdinak 		/*
118*49e21299Sdinak 		 * Otherwise, the object type must be "public", "private",
119*49e21299Sdinak 		 * or "both".
120*49e21299Sdinak 		 */
121*49e21299Sdinak 		if (strcmp(type_spec, "private") == 0) {
122*49e21299Sdinak 			private_objs = B_TRUE;
123*49e21299Sdinak 		} else if (strcmp(type_spec, "public") == 0) {
124*49e21299Sdinak 			public_objs = B_TRUE;
125*49e21299Sdinak 		} else if (strcmp(type_spec, "both") == 0) {
126*49e21299Sdinak 			private_objs = B_TRUE;
127*49e21299Sdinak 			public_objs = B_TRUE;
128*49e21299Sdinak 		} else
129*49e21299Sdinak 			return (PK_ERR_USAGE);
130*49e21299Sdinak 	}
131*49e21299Sdinak 
132*49e21299Sdinak 	if (private_objs)
133*49e21299Sdinak 		obj_type |= PK_PRIVATE_OBJ;
134*49e21299Sdinak 	if (public_objs)
135*49e21299Sdinak 		obj_type |= PK_PUBLIC_OBJ;
136*49e21299Sdinak 
1377711facfSdinak 	/* At least one of public, private, or object label is required. */
1387711facfSdinak 	if (!private_objs && !public_objs && object_label == NULL)
1397711facfSdinak 		return (PK_ERR_USAGE);
1407711facfSdinak 
1417711facfSdinak 	/*
1427711facfSdinak 	 * If object label is given but neither public/private is specified,
1437711facfSdinak 	 * delete all objects with that label.
1447711facfSdinak 	 */
1457711facfSdinak 	if (!private_objs && !public_objs && object_label != NULL)
1467711facfSdinak 		obj_type = PK_ALL_OBJ;
1477711facfSdinak 
1487711facfSdinak 	/* No additional args allowed. */
149*49e21299Sdinak 	argc -= optind_av;
150*49e21299Sdinak 	argv += optind_av;
1517711facfSdinak 	if (argc)
1527711facfSdinak 		return (PK_ERR_USAGE);
1537711facfSdinak 	/* Done parsing command line options. */
1547711facfSdinak 
1557711facfSdinak 	full_token_name(token_name, manuf_id, serial_no, full_name);
1567711facfSdinak 
1577711facfSdinak 	/* Find the slot with token. */
1587711facfSdinak 	if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
1597711facfSdinak 	    &pin_state)) != CKR_OK) {
1607711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
1617711facfSdinak 		    "Unable to find token %s (%s)."), full_name,
1627711facfSdinak 		    pkcs11_strerror(rv));
1637711facfSdinak 		return (PK_ERR_PK11);
1647711facfSdinak 	}
1657711facfSdinak 
1667711facfSdinak 	/* Always get the user's PIN for delete operations. */
1677711facfSdinak 	if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin,
1687711facfSdinak 	    &pinlen)) != CKR_OK) {
1697711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
1707711facfSdinak 		    "Unable to get token passphrase (%s)."),
1717711facfSdinak 		    pkcs11_strerror(rv));
1727711facfSdinak 		quick_finish(NULL);
1737711facfSdinak 		return (PK_ERR_PK11);
1747711facfSdinak 	}
1757711facfSdinak 
1767711facfSdinak 	/* Log the user R/W into the token. */
1777711facfSdinak 	if ((rv = quick_start(slot_id, CKF_RW_SESSION, pin, pinlen, &sess)) !=
1787711facfSdinak 	    CKR_OK) {
1797711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
1807711facfSdinak 		    "Unable to log into token (%s)."), pkcs11_strerror(rv));
1817711facfSdinak 		quick_finish(sess);
1827711facfSdinak 		return (PK_ERR_PK11);
1837711facfSdinak 	}
1847711facfSdinak 
1857711facfSdinak 	/* Find the object(s) with the given label and/or type. */
1867711facfSdinak 	if ((rv = find_objs(sess, obj_type, object_label, &objs, &num_objs)) !=
1877711facfSdinak 	    CKR_OK) {
1887711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
1897711facfSdinak 		    "Unable to find token objects (%s)."), pkcs11_strerror(rv));
1907711facfSdinak 		quick_finish(sess);
1917711facfSdinak 		return (PK_ERR_PK11);
1927711facfSdinak 	}
1937711facfSdinak 
1947711facfSdinak 	if (num_objs == 0) {
1957711facfSdinak 		(void) fprintf(stdout, gettext("No matching objects found.\n"));
1967711facfSdinak 		quick_finish(sess);
1977711facfSdinak 		return (0);
1987711facfSdinak 	}
1997711facfSdinak 
2007711facfSdinak 	if (num_objs != 1) {
2017711facfSdinak 		(void) fprintf(stdout, gettext(
2027711facfSdinak 		    "Warning: %d matching objects found, deleting all.\n"),
2037711facfSdinak 		    num_objs);
2047711facfSdinak 		if (yesno(gettext("Continue with delete? "),
2057711facfSdinak 		    gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
2067711facfSdinak 			quick_finish(sess);
2077711facfSdinak 			return (0);
2087711facfSdinak 		}
2097711facfSdinak 	}
2107711facfSdinak 
2117711facfSdinak 	/* Destroy the objects if found. */
2127711facfSdinak 	for (i = 0; i < num_objs; i++) {
2137711facfSdinak 		/*
2147711facfSdinak 		 * To give nice feedback to the user, get the object's
2157711facfSdinak 		 * label before deleting it.
2167711facfSdinak 		 */
2177711facfSdinak 		cryptodebug("calling C_GetAttributeValue for label");
2187711facfSdinak 		label.pValue = NULL;
2197711facfSdinak 		label.ulValueLen = 0;
2207711facfSdinak 		if (C_GetAttributeValue(sess, objs[i], &label, 1) == CKR_OK) {
2217711facfSdinak 			if (label.ulValueLen != (CK_ULONG)-1 &&
2227711facfSdinak 			    label.ulValueLen != 0 &&
2237711facfSdinak 			    (label.pValue = malloc(label.ulValueLen)) != NULL) {
2247711facfSdinak 				if (C_GetAttributeValue(sess, objs[i], &label,
2257711facfSdinak 				    1) != CKR_OK) {
2267711facfSdinak 					free(label.pValue);
2277711facfSdinak 					label.pValue = NULL;
2287711facfSdinak 					label.ulValueLen = 0;
2297711facfSdinak 				}
2307711facfSdinak 			} else {
2317711facfSdinak 				label.ulValueLen = 0;
2327711facfSdinak 			}
2337711facfSdinak 		}
2347711facfSdinak 
2357711facfSdinak 		cryptodebug("calling C_DestroyObject");
2367711facfSdinak 		if ((rv = C_DestroyObject(sess, objs[i])) != CKR_OK) {
2377711facfSdinak 			if (label.pValue != NULL)
2387711facfSdinak 				cryptoerror(LOG_STDERR, gettext(
2397711facfSdinak 				    "Unable to delete object #%d \"%.*s\" "
2407711facfSdinak 				    "(%s)."), i+1, label.ulValueLen,
2417711facfSdinak 				    label.pValue, pkcs11_strerror(rv));
2427711facfSdinak 			else
2437711facfSdinak 				cryptoerror(LOG_STDERR, gettext(
2447711facfSdinak 				    "Unable to delete object #%d (%s)."),
2457711facfSdinak 				    i+1, pkcs11_strerror(rv));
2467711facfSdinak 		} else {
2477711facfSdinak 			if (label.pValue != NULL)
2487711facfSdinak 				(void) fprintf(stdout, gettext("Object #%d "
2497711facfSdinak 				    "\"%.*s\" successfully deleted.\n"),
2507711facfSdinak 				    i+1, label.ulValueLen, label.pValue);
2517711facfSdinak 			else
2527711facfSdinak 				(void) fprintf(stdout, gettext(
2537711facfSdinak 				    "Object #%d successfully deleted.\n"), i+1);
2547711facfSdinak 		}
2557711facfSdinak 
2567711facfSdinak 		if (label.pValue != NULL)
2577711facfSdinak 			free(label.pValue);
2587711facfSdinak 	}
2597711facfSdinak 
2607711facfSdinak 	/* Clean up. */
2617711facfSdinak 	quick_finish(sess);
2627711facfSdinak 	return (0);
2637711facfSdinak }
264