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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * This file implements the setpin operation for this tool. 30 * The basic flow of the process is to load the PKCS#11 module, 31 * finds the soft token, prompt the user for the old PIN (if 32 * any) and the new PIN, change the token's PIN, and clean up. 33 */ 34 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <errno.h> 38 #include <string.h> 39 #include <cryptoutil.h> 40 #include <security/cryptoki.h> 41 #include "common.h" 42 43 static int 44 setpin_nss(KMF_HANDLE_T handle, 45 char *token_spec, char *dir, char *prefix) 46 { 47 int rv = 0; 48 KMF_SETPIN_PARAMS params; 49 KMF_CREDENTIAL newpincred = { NULL, 0 }; 50 CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL; 51 CK_ULONG old_pinlen = 0, new_pinlen = 0; 52 53 rv = configure_nss(handle, dir, prefix); 54 if (rv != KMF_OK) 55 return (rv); 56 57 (void) memset(¶ms, 0, sizeof (params)); 58 params.kstype = KMF_KEYSTORE_NSS; 59 params.tokenname = token_spec; 60 params.nssparms.slotlabel = token_spec; 61 62 if ((rv = get_pin(gettext("Enter current token passphrase " 63 "(<CR> if not set):"), NULL, &old_pin, &old_pinlen)) != 64 CKR_OK) { 65 cryptoerror(LOG_STDERR, 66 gettext("Unable to get token passphrase.")); 67 return (PK_ERR_NSS); 68 } 69 /* Get the user's new PIN. */ 70 if ((rv = get_pin(gettext("Create new passphrase:"), gettext( 71 "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) { 72 if (rv == CKR_PIN_INCORRECT) 73 cryptoerror(LOG_STDERR, gettext( 74 "Passphrases do not match.")); 75 else 76 cryptoerror(LOG_STDERR, gettext( 77 "Unable to get and confirm new passphrase.")); 78 if (old_pin != NULL) 79 free(old_pin); 80 return (PK_ERR_NSS); 81 } 82 83 params.cred.cred = (char *)old_pin; 84 params.cred.credlen = old_pinlen; 85 86 newpincred.cred = (char *)new_pin; 87 newpincred.credlen = new_pinlen; 88 89 rv = KMF_SetTokenPin(handle, ¶ms, &newpincred); 90 91 if (new_pin) 92 free(new_pin); 93 if (old_pin) 94 free(old_pin); 95 96 return (rv); 97 } 98 99 static int 100 setpin_pkcs11(KMF_HANDLE_T handle, char *token_spec) 101 { 102 CK_SLOT_ID slot_id; 103 CK_FLAGS pin_state; 104 CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL; 105 CK_ULONG old_pinlen = 0, new_pinlen = 0; 106 CK_RV rv = CKR_OK; 107 char *token_name = NULL; 108 KMF_SETPIN_PARAMS params; 109 CK_TOKEN_INFO token_info; 110 KMF_CREDENTIAL newpincred = { NULL, 0 }; 111 112 /* If nothing is specified, default is to use softtoken. */ 113 if (token_spec == NULL) { 114 token_spec = SOFT_TOKEN_LABEL ":" SOFT_MANUFACTURER_ID; 115 token_name = SOFT_TOKEN_LABEL; 116 } 117 118 rv = KMF_PK11TokenLookup(NULL, token_spec, &slot_id); 119 if (rv == KMF_OK) { 120 /* find the pin state for the selected token */ 121 if (C_GetTokenInfo(slot_id, &token_info) != CKR_OK) 122 return (PK_ERR_PK11); 123 124 pin_state = token_info.flags & CKF_USER_PIN_TO_BE_CHANGED; 125 if (token_name == NULL) 126 token_name = (char *)token_info.label; 127 } 128 129 /* 130 * If the token is the softtoken, check if the token flags show the 131 * PIN has not been set yet. If not then set the old PIN to the 132 * default "changeme". Otherwise, let user type in the correct old 133 * PIN to unlock token. 134 */ 135 if (pin_state == CKF_USER_PIN_TO_BE_CHANGED && 136 strcmp(token_name, SOFT_TOKEN_LABEL) == 0) { 137 if ((old_pin = (CK_UTF8CHAR_PTR) strdup(SOFT_DEFAULT_PIN)) == 138 NULL) { 139 cryptoerror(LOG_STDERR, "%s.", strerror(errno)); 140 final_pk11(NULL); 141 return (PK_ERR_PK11); 142 } 143 old_pinlen = strlen(SOFT_DEFAULT_PIN); 144 } else { 145 if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, 146 &old_pin, &old_pinlen)) != CKR_OK) { 147 cryptoerror(LOG_STDERR, 148 gettext("Unable to get token passphrase (%s)."), 149 pkcs11_strerror(rv)); 150 final_pk11(NULL); 151 return (PK_ERR_PK11); 152 } 153 } 154 155 /* Get the user's new PIN. */ 156 if ((rv = get_pin(gettext("Create new passphrase:"), gettext( 157 "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) { 158 if (rv == CKR_PIN_INCORRECT) 159 cryptoerror(LOG_STDERR, gettext( 160 "Passphrases do not match.")); 161 else 162 cryptoerror(LOG_STDERR, gettext( 163 "Unable to get and confirm new passphrase (%s)."), 164 pkcs11_strerror(rv)); 165 free(old_pin); 166 final_pk11(NULL); 167 return (PK_ERR_PK11); 168 } 169 170 (void) memset(¶ms, 0, sizeof (params)); 171 params.kstype = KMF_KEYSTORE_PK11TOKEN; 172 params.tokenname = (char *)token_info.label; 173 params.cred.cred = (char *)old_pin; 174 params.cred.credlen = old_pinlen; 175 params.pkcs11parms.slot = slot_id; 176 177 newpincred.cred = (char *)new_pin; 178 newpincred.credlen = new_pinlen; 179 180 rv = KMF_SetTokenPin(handle, ¶ms, &newpincred); 181 182 /* Clean up. */ 183 if (old_pin != NULL) 184 free(old_pin); 185 if (new_pin != NULL) 186 free(new_pin); 187 188 return (rv); 189 } 190 191 /* 192 * Changes the token's PIN. 193 */ 194 int 195 pk_setpin(int argc, char *argv[]) 196 /* ARGSUSED */ 197 { 198 int opt; 199 int rv; 200 extern int optind_av; 201 extern char *optarg_av; 202 char *token_spec = NULL; 203 char *dir = NULL; 204 char *prefix = NULL; 205 KMF_HANDLE_T handle; 206 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 207 208 /* Parse command line options. Do NOT i18n/l10n. */ 209 while ((opt = getopt_av(argc, argv, 210 "T:(token)k:(keystore)d:(dir)" 211 "p:(prefix)")) != EOF) { 212 switch (opt) { 213 case 'k': 214 kstype = KS2Int(optarg_av); 215 if (kstype == 0) 216 return (PK_ERR_USAGE); 217 break; 218 case 'T': /* token specifier */ 219 if (token_spec) 220 return (PK_ERR_USAGE); 221 token_spec = optarg_av; 222 break; 223 case 'd': 224 if (dir) 225 return (PK_ERR_USAGE); 226 dir = optarg_av; 227 break; 228 case 'p': 229 if (prefix) 230 return (PK_ERR_USAGE); 231 prefix = optarg_av; 232 break; 233 default: 234 return (PK_ERR_USAGE); 235 break; 236 } 237 } 238 239 240 /* No additional args allowed. */ 241 argc -= optind_av; 242 argv += optind_av; 243 if (argc != 0) 244 return (PK_ERR_USAGE); 245 246 /* Done parsing command line options. */ 247 if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) { 248 token_spec = PK_DEFAULT_PK11TOKEN; 249 } else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) { 250 token_spec = DEFAULT_NSS_TOKEN; 251 } 252 253 if ((rv = KMF_Initialize(&handle, NULL, NULL)) != KMF_OK) 254 return (rv); 255 256 switch (kstype) { 257 case KMF_KEYSTORE_PK11TOKEN: 258 rv = setpin_pkcs11(handle, token_spec); 259 break; 260 case KMF_KEYSTORE_NSS: 261 rv = setpin_nss(handle, token_spec, dir, prefix); 262 break; 263 default: 264 cryptoerror(LOG_STDERR, 265 gettext("incorrect keystore.")); 266 return (PK_ERR_USAGE); 267 } 268 269 (void) KMF_Finalize(handle); 270 271 if (rv == KMF_ERR_AUTH_FAILED) { 272 cryptoerror(LOG_STDERR, 273 gettext("Incorrect passphrase.")); 274 return (PK_ERR_SYSTEM); 275 } else if (rv != CKR_OK) { 276 cryptoerror(LOG_STDERR, 277 gettext("Unable to change passphrase.")); 278 return (PK_ERR_SYSTEM); 279 } else { 280 (void) fprintf(stdout, gettext("Passphrase changed.\n")); 281 } 282 return (0); 283 } 284