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