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 setpin operation for this tool. 31 * The basic flow of the process is to load the PKCS#11 module, 32 * finds the soft token, prompt the user for the old PIN (if 33 * any) and the new PIN, change the token's PIN, and clean up. 34 */ 35 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <errno.h> 39 #include <string.h> 40 #include <cryptoutil.h> 41 #include <security/cryptoki.h> 42 #include "common.h" 43 44 /* 45 * Changes the token's PIN. 46 */ 47 int 48 pk_setpin(int argc, char *argv[]) 49 /* ARGSUSED */ 50 { 51 int opt; 52 extern int optind_av; 53 extern char *optarg_av; 54 char *token_spec = NULL; 55 char *token_name = NULL; 56 char *manuf_id = NULL; 57 char *serial_no = NULL; 58 CK_SLOT_ID slot_id; 59 CK_FLAGS pin_state; 60 CK_SESSION_HANDLE sess; 61 CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL; 62 CK_ULONG old_pinlen = 0, new_pinlen = 0; 63 CK_RV rv = CKR_OK; 64 char full_name[FULL_NAME_LEN]; 65 66 cryptodebug("inside pk_setpin"); 67 68 /* Parse command line options. Do NOT i18n/l10n. */ 69 while ((opt = getopt_av(argc, argv, "T:(token)")) != EOF) { 70 switch (opt) { 71 case 'T': /* token specifier */ 72 if (token_spec) 73 return (PK_ERR_USAGE); 74 token_spec = optarg_av; 75 break; 76 default: 77 return (PK_ERR_USAGE); 78 break; 79 } 80 } 81 82 /* If nothing is specified, default is to use softtoken. */ 83 if (token_spec == NULL) { 84 token_name = SOFT_TOKEN_LABEL; 85 manuf_id = SOFT_MANUFACTURER_ID; 86 serial_no = SOFT_TOKEN_SERIAL; 87 } else { 88 /* 89 * Parse token specifier into token_name, manuf_id, serial_no. 90 * Token_name is required; manuf_id and serial_no are optional. 91 */ 92 if (parse_token_spec(token_spec, &token_name, &manuf_id, 93 &serial_no) < 0) 94 return (PK_ERR_USAGE); 95 } 96 97 /* No additional args allowed. */ 98 argc -= optind_av; 99 argv += optind_av; 100 if (argc != 0) 101 return (PK_ERR_USAGE); 102 /* Done parsing command line options. */ 103 104 full_token_name(token_name, manuf_id, serial_no, full_name); 105 106 /* Find the slot with token. */ 107 if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id, 108 &pin_state)) != CKR_OK) { 109 cryptoerror(LOG_STDERR, 110 gettext("Unable to find token %s (%s)."), full_name, 111 pkcs11_strerror(rv)); 112 final_pk11(NULL); 113 return (PK_ERR_PK11); 114 } 115 116 /* 117 * If the token is the softtoken, check if the token flags show the 118 * PIN has not been set yet. If not then set the old PIN to the 119 * default "changeme". Otherwise, let user type in the correct old 120 * PIN to unlock token. 121 */ 122 if (pin_state == CKF_USER_PIN_TO_BE_CHANGED && 123 strcmp(token_name, SOFT_TOKEN_LABEL) == 0) { 124 cryptodebug("pin_state: first time passphrase is being set"); 125 if ((old_pin = (CK_UTF8CHAR_PTR) strdup(SOFT_DEFAULT_PIN)) == 126 NULL) { 127 cryptoerror(LOG_STDERR, "%s.", strerror(errno)); 128 final_pk11(NULL); 129 return (PK_ERR_PK11); 130 } 131 old_pinlen = strlen(SOFT_DEFAULT_PIN); 132 } else { 133 cryptodebug("pin_state: changing an existing pin "); 134 if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, 135 &old_pin, &old_pinlen)) != CKR_OK) { 136 cryptoerror(LOG_STDERR, 137 gettext("Unable to get token passphrase (%s)."), 138 pkcs11_strerror(rv)); 139 final_pk11(NULL); 140 return (PK_ERR_PK11); 141 } 142 } 143 144 /* Get the user's new PIN. */ 145 if ((rv = get_pin(gettext("Create new passphrase:"), gettext( 146 "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) { 147 if (rv == CKR_PIN_INCORRECT) 148 cryptoerror(LOG_STDERR, gettext( 149 "Passphrases do not match.")); 150 else 151 cryptoerror(LOG_STDERR, gettext( 152 "Unable to get and confirm new passphrase (%s)."), 153 pkcs11_strerror(rv)); 154 free(old_pin); 155 final_pk11(NULL); 156 return (PK_ERR_PK11); 157 } 158 159 /* Open a R/W session to the token to change the PIN. */ 160 if ((rv = open_sess(slot_id, CKF_RW_SESSION, &sess)) != CKR_OK) { 161 cryptoerror(LOG_STDERR, 162 gettext("Unable to open token session (%s)."), 163 pkcs11_strerror(rv)); 164 free(old_pin); 165 final_pk11(NULL); 166 return (PK_ERR_PK11); 167 } 168 169 /* Change the PIN if possible. */ 170 cryptodebug("calling C_SetPIN"); 171 rv = C_SetPIN(sess, old_pin, old_pinlen, new_pin, new_pinlen); 172 173 /* Clean up. */ 174 free(old_pin); 175 free(new_pin); 176 quick_finish(sess); 177 178 if (rv != CKR_OK) { 179 if (rv == CKR_PIN_INCORRECT) 180 cryptoerror(LOG_STDERR, 181 gettext("Incorrect passphrase.")); 182 else 183 cryptoerror(LOG_STDERR, 184 gettext("Unable to change passphrase (%s)."), 185 pkcs11_strerror(rv)); 186 return (PK_ERR_PK11); 187 } 188 189 (void) fprintf(stdout, gettext("Passphrase changed.\n")); 190 return (0); 191 } 192