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