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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * This file implements the token object delete operation for this tool. 31 * It loads the PKCS#11 modules, finds the object to delete, deletes it, 32 * and cleans up. User must be R/W logged into the token. 33 */ 34 35 #include <stdio.h> 36 #include <string.h> 37 #include <cryptoutil.h> 38 #include <security/cryptoki.h> 39 #include "common.h" 40 41 /* 42 * Delete token objects. 43 */ 44 int 45 pk_delete(int argc, char *argv[]) 46 { 47 int opt; 48 extern int optind; 49 extern char *optarg; 50 char *token_name = NULL; 51 char *manuf_id = NULL; 52 char *serial_no = NULL; 53 char full_name[FULL_NAME_LEN]; 54 boolean_t public_objs = B_FALSE; 55 boolean_t private_objs = B_FALSE; 56 CK_BYTE *object_label = NULL; 57 int obj_type = 0x00; 58 CK_SLOT_ID slot_id; 59 CK_FLAGS pin_state; 60 CK_UTF8CHAR_PTR pin = NULL; 61 CK_ULONG pinlen = 0; 62 CK_SESSION_HANDLE sess; 63 CK_OBJECT_HANDLE *objs; 64 CK_ULONG num_objs; 65 CK_ATTRIBUTE label = { CKA_LABEL, NULL, 0 }; 66 CK_RV rv = CKR_OK; 67 int i; 68 69 cryptodebug("inside pk_delete"); 70 71 /* Parse command line options. Do NOT i18n/l10n. */ 72 while ((opt = getopt(argc, argv, "p(private)P(public)l:(label)")) != 73 EOF) { 74 switch (opt) { 75 case 'p': /* private objects */ 76 private_objs = B_TRUE; 77 obj_type |= PK_PRIVATE_OBJ; 78 break; 79 case 'P': /* public objects */ 80 public_objs = B_TRUE; 81 obj_type |= PK_PUBLIC_OBJ; 82 break; 83 case 'l': /* objects with specific label */ 84 if (object_label) 85 return (PK_ERR_USAGE); 86 object_label = (CK_BYTE *)optarg; 87 break; 88 default: 89 return (PK_ERR_USAGE); 90 break; 91 } 92 } 93 94 /* At least one of public, private, or object label is required. */ 95 if (!private_objs && !public_objs && object_label == NULL) 96 return (PK_ERR_USAGE); 97 98 /* 99 * If object label is given but neither public/private is specified, 100 * delete all objects with that label. 101 */ 102 if (!private_objs && !public_objs && object_label != NULL) 103 obj_type = PK_ALL_OBJ; 104 105 /* No additional args allowed. */ 106 argc -= optind; 107 argv += optind; 108 if (argc) 109 return (PK_ERR_USAGE); 110 /* Done parsing command line options. */ 111 112 /* Delete operation only supported on softtoken. */ 113 if (token_name == NULL) 114 token_name = SOFT_TOKEN_LABEL; 115 if (manuf_id == NULL) 116 manuf_id = SOFT_MANUFACTURER_ID; 117 if (serial_no == NULL) 118 serial_no = SOFT_TOKEN_SERIAL; 119 full_token_name(token_name, manuf_id, serial_no, full_name); 120 121 /* Find the slot with token. */ 122 if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id, 123 &pin_state)) != CKR_OK) { 124 cryptoerror(LOG_STDERR, gettext( 125 "Unable to find token %s (%s)."), full_name, 126 pkcs11_strerror(rv)); 127 return (PK_ERR_PK11); 128 } 129 130 /* Always get the user's PIN for delete operations. */ 131 if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin, 132 &pinlen)) != CKR_OK) { 133 cryptoerror(LOG_STDERR, gettext( 134 "Unable to get token passphrase (%s)."), 135 pkcs11_strerror(rv)); 136 quick_finish(NULL); 137 return (PK_ERR_PK11); 138 } 139 140 /* Log the user R/W into the token. */ 141 if ((rv = quick_start(slot_id, CKF_RW_SESSION, pin, pinlen, &sess)) != 142 CKR_OK) { 143 cryptoerror(LOG_STDERR, gettext( 144 "Unable to log into token (%s)."), pkcs11_strerror(rv)); 145 quick_finish(sess); 146 return (PK_ERR_PK11); 147 } 148 149 /* Find the object(s) with the given label and/or type. */ 150 if ((rv = find_objs(sess, obj_type, object_label, &objs, &num_objs)) != 151 CKR_OK) { 152 cryptoerror(LOG_STDERR, gettext( 153 "Unable to find token objects (%s)."), pkcs11_strerror(rv)); 154 quick_finish(sess); 155 return (PK_ERR_PK11); 156 } 157 158 if (num_objs == 0) { 159 (void) fprintf(stdout, gettext("No matching objects found.\n")); 160 quick_finish(sess); 161 return (0); 162 } 163 164 if (num_objs != 1) { 165 (void) fprintf(stdout, gettext( 166 "Warning: %d matching objects found, deleting all.\n"), 167 num_objs); 168 if (yesno(gettext("Continue with delete? "), 169 gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) { 170 quick_finish(sess); 171 return (0); 172 } 173 } 174 175 /* Destroy the objects if found. */ 176 for (i = 0; i < num_objs; i++) { 177 /* 178 * To give nice feedback to the user, get the object's 179 * label before deleting it. 180 */ 181 cryptodebug("calling C_GetAttributeValue for label"); 182 label.pValue = NULL; 183 label.ulValueLen = 0; 184 if (C_GetAttributeValue(sess, objs[i], &label, 1) == CKR_OK) { 185 if (label.ulValueLen != (CK_ULONG)-1 && 186 label.ulValueLen != 0 && 187 (label.pValue = malloc(label.ulValueLen)) != NULL) { 188 if (C_GetAttributeValue(sess, objs[i], &label, 189 1) != CKR_OK) { 190 free(label.pValue); 191 label.pValue = NULL; 192 label.ulValueLen = 0; 193 } 194 } else { 195 label.ulValueLen = 0; 196 } 197 } 198 199 cryptodebug("calling C_DestroyObject"); 200 if ((rv = C_DestroyObject(sess, objs[i])) != CKR_OK) { 201 if (label.pValue != NULL) 202 cryptoerror(LOG_STDERR, gettext( 203 "Unable to delete object #%d \"%.*s\" " 204 "(%s)."), i+1, label.ulValueLen, 205 label.pValue, pkcs11_strerror(rv)); 206 else 207 cryptoerror(LOG_STDERR, gettext( 208 "Unable to delete object #%d (%s)."), 209 i+1, pkcs11_strerror(rv)); 210 } else { 211 if (label.pValue != NULL) 212 (void) fprintf(stdout, gettext("Object #%d " 213 "\"%.*s\" successfully deleted.\n"), 214 i+1, label.ulValueLen, label.pValue); 215 else 216 (void) fprintf(stdout, gettext( 217 "Object #%d successfully deleted.\n"), i+1); 218 } 219 220 if (label.pValue != NULL) 221 free(label.pValue); 222 } 223 224 /* Clean up. */ 225 quick_finish(sess); 226 return (0); 227 } 228