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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * This file implements the setpin operation for this tool. 28 * The basic flow of the process is to load the PKCS#11 module, 29 * finds the soft token, prompt the user for the old PIN (if 30 * any) and the new PIN, change the token's PIN, and clean up. 31 */ 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <errno.h> 36 #include <string.h> 37 #include <cryptoutil.h> 38 #include <security/cryptoki.h> 39 #include "common.h" 40 41 static int 42 setpin_nss(KMF_HANDLE_T handle, 43 char *token_spec, char *dir, char *prefix) 44 { 45 int rv = 0; 46 KMF_CREDENTIAL oldcred = {NULL, 0}; 47 KMF_CREDENTIAL newpincred = {NULL, 0}; 48 CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL; 49 CK_ULONG old_pinlen = 0, new_pinlen = 0; 50 KMF_ATTRIBUTE setpinattrs[6]; 51 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 52 int numattrs = 0; 53 54 rv = configure_nss(handle, dir, prefix); 55 if (rv != KMF_OK) 56 return (rv); 57 58 kmf_set_attr_at_index(setpinattrs, numattrs, KMF_KEYSTORE_TYPE_ATTR, 59 &kstype, sizeof (kstype)); 60 numattrs++; 61 if (token_spec != NULL) { 62 kmf_set_attr_at_index(setpinattrs, numattrs, 63 KMF_TOKEN_LABEL_ATTR, 64 token_spec, strlen(token_spec)); 65 numattrs++; 66 } 67 68 if ((rv = get_pin(gettext("Enter current token passphrase " 69 "(<CR> if not set):"), NULL, &old_pin, &old_pinlen)) != CKR_OK) { 70 cryptoerror(LOG_STDERR, 71 gettext("Unable to get token passphrase.")); 72 return (PK_ERR_NSS); 73 } 74 /* Get the user's new PIN. */ 75 if ((rv = get_pin(gettext("Create new passphrase:"), gettext( 76 "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) { 77 if (rv == CKR_PIN_INCORRECT) 78 cryptoerror(LOG_STDERR, gettext( 79 "Passphrases do not match.")); 80 else 81 cryptoerror(LOG_STDERR, gettext( 82 "Unable to get and confirm new passphrase.")); 83 if (old_pin != NULL) 84 free(old_pin); 85 return (PK_ERR_NSS); 86 } 87 88 oldcred.cred = (char *)old_pin; 89 oldcred.credlen = old_pinlen; 90 91 kmf_set_attr_at_index(setpinattrs, numattrs, KMF_CREDENTIAL_ATTR, 92 &oldcred, sizeof (oldcred)); 93 numattrs++; 94 95 newpincred.cred = (char *)new_pin; 96 newpincred.credlen = new_pinlen; 97 kmf_set_attr_at_index(setpinattrs, numattrs, KMF_NEWPIN_ATTR, 98 &newpincred, sizeof (newpincred)); 99 numattrs++; 100 101 rv = kmf_set_token_pin(handle, numattrs, setpinattrs); 102 103 if (new_pin) 104 free(new_pin); 105 if (old_pin) 106 free(old_pin); 107 108 return (rv); 109 } 110 111 static int 112 setpin_pkcs11(KMF_HANDLE_T handle, char *token_spec, boolean_t souser) 113 { 114 CK_SLOT_ID slot_id; 115 CK_FLAGS pin_state; 116 CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL; 117 CK_ULONG old_pinlen = 0, new_pinlen = 0; 118 CK_RV rv = CKR_OK; 119 char *token_name = NULL; 120 CK_TOKEN_INFO token_info; 121 KMF_CREDENTIAL newpincred = {NULL, 0}; 122 KMF_CREDENTIAL oldcred = {NULL, 0}; 123 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 124 KMF_ATTRIBUTE attrlist[6]; 125 CK_USER_TYPE user = CKU_USER; 126 int numattr = 0; 127 128 /* If nothing is specified, default is to use softtoken. */ 129 if (token_spec == NULL) { 130 token_spec = SOFT_TOKEN_LABEL ":" SOFT_MANUFACTURER_ID; 131 token_name = SOFT_TOKEN_LABEL; 132 } 133 134 rv = kmf_pk11_token_lookup(NULL, token_spec, &slot_id); 135 if (rv == KMF_OK) { 136 /* find the pin state for the selected token */ 137 if (C_GetTokenInfo(slot_id, &token_info) != CKR_OK) 138 return (PK_ERR_PK11); 139 140 pin_state = token_info.flags & CKF_USER_PIN_TO_BE_CHANGED; 141 if (token_name == NULL) 142 token_name = (char *)token_info.label; 143 } 144 145 /* 146 * If the token is the softtoken, check if the token flags show the 147 * PIN has not been set yet. If not then set the old PIN to the 148 * default "changeme". Otherwise, let user type in the correct old 149 * PIN to unlock token. 150 */ 151 if (pin_state == CKF_USER_PIN_TO_BE_CHANGED && 152 strcmp(token_name, SOFT_TOKEN_LABEL) == 0) { 153 if ((old_pin = (CK_UTF8CHAR_PTR) strdup(SOFT_DEFAULT_PIN)) == 154 NULL) { 155 cryptoerror(LOG_STDERR, "%s.", strerror(errno)); 156 final_pk11(NULL); 157 return (PK_ERR_PK11); 158 } 159 old_pinlen = strlen(SOFT_DEFAULT_PIN); 160 } else { 161 if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, 162 &old_pin, &old_pinlen)) != CKR_OK) { 163 cryptoerror(LOG_STDERR, 164 gettext("Unable to get token passphrase (%s)."), 165 pkcs11_strerror(rv)); 166 final_pk11(NULL); 167 return (PK_ERR_PK11); 168 } 169 } 170 171 /* Get the user's new PIN. */ 172 if ((rv = get_pin(gettext("Create new passphrase:"), gettext( 173 "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) { 174 if (rv == CKR_PIN_INCORRECT) 175 cryptoerror(LOG_STDERR, gettext( 176 "Passphrases do not match.")); 177 else 178 cryptoerror(LOG_STDERR, gettext( 179 "Unable to get and confirm new passphrase (%s)."), 180 pkcs11_strerror(rv)); 181 free(old_pin); 182 final_pk11(NULL); 183 return (PK_ERR_PK11); 184 } 185 186 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 187 &kstype, sizeof (kstype)); 188 numattr++; 189 if (token_name != NULL) { 190 kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR, 191 token_name, strlen(token_name)); 192 numattr++; 193 } 194 oldcred.cred = (char *)old_pin; 195 oldcred.credlen = old_pinlen; 196 kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 197 &oldcred, sizeof (oldcred)); 198 numattr++; 199 200 kmf_set_attr_at_index(attrlist, numattr, KMF_SLOT_ID_ATTR, 201 &slot_id, sizeof (slot_id)); 202 numattr++; 203 204 newpincred.cred = (char *)new_pin; 205 newpincred.credlen = new_pinlen; 206 kmf_set_attr_at_index(attrlist, numattr, KMF_NEWPIN_ATTR, 207 &newpincred, sizeof (newpincred)); 208 numattr++; 209 210 if (souser) { 211 user = CKU_SO; 212 kmf_set_attr_at_index(attrlist, numattr, 213 KMF_PK11_USER_TYPE_ATTR, 214 &user, sizeof (user)); 215 numattr++; 216 } 217 218 rv = kmf_set_token_pin(handle, numattr, attrlist); 219 220 /* Clean up. */ 221 if (old_pin != NULL) 222 free(old_pin); 223 if (new_pin != NULL) 224 free(new_pin); 225 226 return (rv); 227 } 228 229 /* 230 * Changes the token's PIN. 231 */ 232 int 233 pk_setpin(int argc, char *argv[]) 234 /* ARGSUSED */ 235 { 236 int opt; 237 int rv; 238 extern int optind_av; 239 extern char *optarg_av; 240 char *token_spec = NULL; 241 char *dir = NULL; 242 char *prefix = NULL; 243 char *utype = NULL; 244 KMF_HANDLE_T handle; 245 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 246 boolean_t souser = 0; 247 248 /* Parse command line options. Do NOT i18n/l10n. */ 249 while ((opt = getopt_av(argc, argv, 250 "T:(token)k:(keystore)d:(dir)" 251 "p:(prefix)u:(usertype)")) != EOF) { 252 switch (opt) { 253 case 'k': 254 kstype = KS2Int(optarg_av); 255 if (kstype == 0) 256 return (PK_ERR_USAGE); 257 break; 258 case 'T': /* token specifier */ 259 if (token_spec) 260 return (PK_ERR_USAGE); 261 token_spec = optarg_av; 262 break; 263 case 'd': 264 if (dir) 265 return (PK_ERR_USAGE); 266 dir = optarg_av; 267 break; 268 case 'p': 269 if (prefix) 270 return (PK_ERR_USAGE); 271 prefix = optarg_av; 272 break; 273 case 'u': 274 utype = optarg_av; 275 break; 276 default: 277 return (PK_ERR_USAGE); 278 break; 279 } 280 } 281 282 283 /* No additional args allowed. */ 284 argc -= optind_av; 285 argv += optind_av; 286 if (argc != 0) 287 return (PK_ERR_USAGE); 288 289 /* Done parsing command line options. */ 290 if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) { 291 token_spec = PK_DEFAULT_PK11TOKEN; 292 } else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) { 293 token_spec = DEFAULT_NSS_TOKEN; 294 } 295 296 if ((rv = kmf_initialize(&handle, NULL, NULL)) != KMF_OK) 297 return (rv); 298 299 if (utype != NULL) { 300 if (strcmp(utype, "so") == 0) 301 souser = 1; 302 else if (strcmp(utype, "user") == 0) 303 souser = 0; 304 else /* Wrong option string */ 305 return (PK_ERR_USAGE); 306 } 307 308 switch (kstype) { 309 case KMF_KEYSTORE_PK11TOKEN: 310 rv = setpin_pkcs11(handle, token_spec, souser); 311 break; 312 case KMF_KEYSTORE_NSS: 313 rv = setpin_nss(handle, token_spec, dir, prefix); 314 break; 315 default: 316 cryptoerror(LOG_STDERR, 317 gettext("incorrect keystore.")); 318 return (PK_ERR_USAGE); 319 } 320 321 (void) kmf_finalize(handle); 322 323 if (rv == KMF_ERR_AUTH_FAILED) { 324 cryptoerror(LOG_STDERR, 325 gettext("Incorrect passphrase.")); 326 return (PK_ERR_SYSTEM); 327 } else if (rv != CKR_OK) { 328 cryptoerror(LOG_STDERR, 329 gettext("Unable to change passphrase.")); 330 return (PK_ERR_SYSTEM); 331 } else { 332 (void) fprintf(stdout, gettext("Passphrase changed.\n")); 333 } 334 return (0); 335 } 336