117Sdinak /* 217Sdinak * CDDL HEADER START 317Sdinak * 417Sdinak * The contents of this file are subject to the terms of the 517Sdinak * Common Development and Distribution License, Version 1.0 only 617Sdinak * (the "License"). You may not use this file except in compliance 717Sdinak * with the License. 817Sdinak * 917Sdinak * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 1017Sdinak * or http://www.opensolaris.org/os/licensing. 1117Sdinak * See the License for the specific language governing permissions 1217Sdinak * and limitations under the License. 1317Sdinak * 1417Sdinak * When distributing Covered Code, include this CDDL HEADER in each 1517Sdinak * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1617Sdinak * If applicable, add the following below this CDDL HEADER, with the 1717Sdinak * fields enclosed by brackets "[]" replaced with your own identifying 1817Sdinak * information: Portions Copyright [yyyy] [name of copyright owner] 1917Sdinak * 2017Sdinak * CDDL HEADER END 2117Sdinak */ 2217Sdinak /* 2317Sdinak * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 2417Sdinak * Use is subject to license terms. 2517Sdinak */ 2617Sdinak 2717Sdinak #pragma ident "%Z%%M% %I% %E% SMI" 2817Sdinak 2917Sdinak /* 3017Sdinak * This file implements the token object delete operation for this tool. 3117Sdinak * It loads the PKCS#11 modules, finds the object to delete, deletes it, 3217Sdinak * and cleans up. User must be R/W logged into the token. 3317Sdinak */ 3417Sdinak 3517Sdinak #include <stdio.h> 3617Sdinak #include <string.h> 3717Sdinak #include <cryptoutil.h> 3817Sdinak #include <security/cryptoki.h> 3917Sdinak #include "common.h" 4017Sdinak 4117Sdinak /* 4217Sdinak * Delete token objects. 4317Sdinak */ 4417Sdinak int 4517Sdinak pk_delete(int argc, char *argv[]) 4617Sdinak { 4717Sdinak int opt; 48*864Sdinak extern int optind_av; 49*864Sdinak extern char *optarg_av; 50*864Sdinak char *token_spec = NULL; 5117Sdinak char *token_name = NULL; 5217Sdinak char *manuf_id = NULL; 5317Sdinak char *serial_no = NULL; 54*864Sdinak char *type_spec = NULL; 5517Sdinak char full_name[FULL_NAME_LEN]; 5617Sdinak boolean_t public_objs = B_FALSE; 5717Sdinak boolean_t private_objs = B_FALSE; 5817Sdinak CK_BYTE *object_label = NULL; 5917Sdinak int obj_type = 0x00; 6017Sdinak CK_SLOT_ID slot_id; 6117Sdinak CK_FLAGS pin_state; 6217Sdinak CK_UTF8CHAR_PTR pin = NULL; 6317Sdinak CK_ULONG pinlen = 0; 6417Sdinak CK_SESSION_HANDLE sess; 6517Sdinak CK_OBJECT_HANDLE *objs; 6617Sdinak CK_ULONG num_objs; 6717Sdinak CK_ATTRIBUTE label = { CKA_LABEL, NULL, 0 }; 6817Sdinak CK_RV rv = CKR_OK; 6917Sdinak int i; 7017Sdinak 7117Sdinak cryptodebug("inside pk_delete"); 7217Sdinak 7317Sdinak /* Parse command line options. Do NOT i18n/l10n. */ 74*864Sdinak while ((opt = getopt_av(argc, argv, 75*864Sdinak "T:(token)y:(objtype)l:(label)")) != EOF) { 7617Sdinak switch (opt) { 77*864Sdinak case 'T': /* token specifier */ 78*864Sdinak if (token_spec) 79*864Sdinak return (PK_ERR_USAGE); 80*864Sdinak token_spec = optarg_av; 8117Sdinak break; 82*864Sdinak case 'y': /* object type: public, private, both */ 83*864Sdinak if (type_spec) 84*864Sdinak return (PK_ERR_USAGE); 85*864Sdinak type_spec = optarg_av; 8617Sdinak break; 8717Sdinak case 'l': /* objects with specific label */ 8817Sdinak if (object_label) 8917Sdinak return (PK_ERR_USAGE); 90*864Sdinak object_label = (CK_BYTE *)optarg_av; 9117Sdinak break; 9217Sdinak default: 9317Sdinak return (PK_ERR_USAGE); 9417Sdinak break; 9517Sdinak } 9617Sdinak } 9717Sdinak 98*864Sdinak /* If no token is specified, default is to use softtoken. */ 99*864Sdinak if (token_spec == NULL) { 100*864Sdinak token_name = SOFT_TOKEN_LABEL; 101*864Sdinak manuf_id = SOFT_MANUFACTURER_ID; 102*864Sdinak serial_no = SOFT_TOKEN_SERIAL; 103*864Sdinak } else { 104*864Sdinak /* 105*864Sdinak * Parse token specifier into token_name, manuf_id, serial_no. 106*864Sdinak * Token_name is required; manuf_id and serial_no are optional. 107*864Sdinak */ 108*864Sdinak if (parse_token_spec(token_spec, &token_name, &manuf_id, 109*864Sdinak &serial_no) < 0) 110*864Sdinak return (PK_ERR_USAGE); 111*864Sdinak } 112*864Sdinak 113*864Sdinak /* If no object type specified, default is public objects. */ 114*864Sdinak if (!type_spec) { 115*864Sdinak public_objs = B_TRUE; 116*864Sdinak } else { 117*864Sdinak /* 118*864Sdinak * Otherwise, the object type must be "public", "private", 119*864Sdinak * or "both". 120*864Sdinak */ 121*864Sdinak if (strcmp(type_spec, "private") == 0) { 122*864Sdinak private_objs = B_TRUE; 123*864Sdinak } else if (strcmp(type_spec, "public") == 0) { 124*864Sdinak public_objs = B_TRUE; 125*864Sdinak } else if (strcmp(type_spec, "both") == 0) { 126*864Sdinak private_objs = B_TRUE; 127*864Sdinak public_objs = B_TRUE; 128*864Sdinak } else 129*864Sdinak return (PK_ERR_USAGE); 130*864Sdinak } 131*864Sdinak 132*864Sdinak if (private_objs) 133*864Sdinak obj_type |= PK_PRIVATE_OBJ; 134*864Sdinak if (public_objs) 135*864Sdinak obj_type |= PK_PUBLIC_OBJ; 136*864Sdinak 13717Sdinak /* At least one of public, private, or object label is required. */ 13817Sdinak if (!private_objs && !public_objs && object_label == NULL) 13917Sdinak return (PK_ERR_USAGE); 14017Sdinak 14117Sdinak /* 14217Sdinak * If object label is given but neither public/private is specified, 14317Sdinak * delete all objects with that label. 14417Sdinak */ 14517Sdinak if (!private_objs && !public_objs && object_label != NULL) 14617Sdinak obj_type = PK_ALL_OBJ; 14717Sdinak 14817Sdinak /* No additional args allowed. */ 149*864Sdinak argc -= optind_av; 150*864Sdinak argv += optind_av; 15117Sdinak if (argc) 15217Sdinak return (PK_ERR_USAGE); 15317Sdinak /* Done parsing command line options. */ 15417Sdinak 15517Sdinak full_token_name(token_name, manuf_id, serial_no, full_name); 15617Sdinak 15717Sdinak /* Find the slot with token. */ 15817Sdinak if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id, 15917Sdinak &pin_state)) != CKR_OK) { 16017Sdinak cryptoerror(LOG_STDERR, gettext( 16117Sdinak "Unable to find token %s (%s)."), full_name, 16217Sdinak pkcs11_strerror(rv)); 16317Sdinak return (PK_ERR_PK11); 16417Sdinak } 16517Sdinak 16617Sdinak /* Always get the user's PIN for delete operations. */ 16717Sdinak if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin, 16817Sdinak &pinlen)) != CKR_OK) { 16917Sdinak cryptoerror(LOG_STDERR, gettext( 17017Sdinak "Unable to get token passphrase (%s)."), 17117Sdinak pkcs11_strerror(rv)); 17217Sdinak quick_finish(NULL); 17317Sdinak return (PK_ERR_PK11); 17417Sdinak } 17517Sdinak 17617Sdinak /* Log the user R/W into the token. */ 17717Sdinak if ((rv = quick_start(slot_id, CKF_RW_SESSION, pin, pinlen, &sess)) != 17817Sdinak CKR_OK) { 17917Sdinak cryptoerror(LOG_STDERR, gettext( 18017Sdinak "Unable to log into token (%s)."), pkcs11_strerror(rv)); 18117Sdinak quick_finish(sess); 18217Sdinak return (PK_ERR_PK11); 18317Sdinak } 18417Sdinak 18517Sdinak /* Find the object(s) with the given label and/or type. */ 18617Sdinak if ((rv = find_objs(sess, obj_type, object_label, &objs, &num_objs)) != 18717Sdinak CKR_OK) { 18817Sdinak cryptoerror(LOG_STDERR, gettext( 18917Sdinak "Unable to find token objects (%s)."), pkcs11_strerror(rv)); 19017Sdinak quick_finish(sess); 19117Sdinak return (PK_ERR_PK11); 19217Sdinak } 19317Sdinak 19417Sdinak if (num_objs == 0) { 19517Sdinak (void) fprintf(stdout, gettext("No matching objects found.\n")); 19617Sdinak quick_finish(sess); 19717Sdinak return (0); 19817Sdinak } 19917Sdinak 20017Sdinak if (num_objs != 1) { 20117Sdinak (void) fprintf(stdout, gettext( 20217Sdinak "Warning: %d matching objects found, deleting all.\n"), 20317Sdinak num_objs); 20417Sdinak if (yesno(gettext("Continue with delete? "), 20517Sdinak gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) { 20617Sdinak quick_finish(sess); 20717Sdinak return (0); 20817Sdinak } 20917Sdinak } 21017Sdinak 21117Sdinak /* Destroy the objects if found. */ 21217Sdinak for (i = 0; i < num_objs; i++) { 21317Sdinak /* 21417Sdinak * To give nice feedback to the user, get the object's 21517Sdinak * label before deleting it. 21617Sdinak */ 21717Sdinak cryptodebug("calling C_GetAttributeValue for label"); 21817Sdinak label.pValue = NULL; 21917Sdinak label.ulValueLen = 0; 22017Sdinak if (C_GetAttributeValue(sess, objs[i], &label, 1) == CKR_OK) { 22117Sdinak if (label.ulValueLen != (CK_ULONG)-1 && 22217Sdinak label.ulValueLen != 0 && 22317Sdinak (label.pValue = malloc(label.ulValueLen)) != NULL) { 22417Sdinak if (C_GetAttributeValue(sess, objs[i], &label, 22517Sdinak 1) != CKR_OK) { 22617Sdinak free(label.pValue); 22717Sdinak label.pValue = NULL; 22817Sdinak label.ulValueLen = 0; 22917Sdinak } 23017Sdinak } else { 23117Sdinak label.ulValueLen = 0; 23217Sdinak } 23317Sdinak } 23417Sdinak 23517Sdinak cryptodebug("calling C_DestroyObject"); 23617Sdinak if ((rv = C_DestroyObject(sess, objs[i])) != CKR_OK) { 23717Sdinak if (label.pValue != NULL) 23817Sdinak cryptoerror(LOG_STDERR, gettext( 23917Sdinak "Unable to delete object #%d \"%.*s\" " 24017Sdinak "(%s)."), i+1, label.ulValueLen, 24117Sdinak label.pValue, pkcs11_strerror(rv)); 24217Sdinak else 24317Sdinak cryptoerror(LOG_STDERR, gettext( 24417Sdinak "Unable to delete object #%d (%s)."), 24517Sdinak i+1, pkcs11_strerror(rv)); 24617Sdinak } else { 24717Sdinak if (label.pValue != NULL) 24817Sdinak (void) fprintf(stdout, gettext("Object #%d " 24917Sdinak "\"%.*s\" successfully deleted.\n"), 25017Sdinak i+1, label.ulValueLen, label.pValue); 25117Sdinak else 25217Sdinak (void) fprintf(stdout, gettext( 25317Sdinak "Object #%d successfully deleted.\n"), i+1); 25417Sdinak } 25517Sdinak 25617Sdinak if (label.pValue != NULL) 25717Sdinak free(label.pValue); 25817Sdinak } 25917Sdinak 26017Sdinak /* Clean up. */ 26117Sdinak quick_finish(sess); 26217Sdinak return (0); 26317Sdinak } 264