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