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 2007 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_CREDENTIAL oldcred = {NULL, 0}; 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 KMF_ATTRIBUTE setpinattrs[6]; 53 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 54 int numattrs = 0; 55 56 rv = configure_nss(handle, dir, prefix); 57 if (rv != KMF_OK) 58 return (rv); 59 60 kmf_set_attr_at_index(setpinattrs, numattrs, KMF_KEYSTORE_TYPE_ATTR, 61 &kstype, sizeof (kstype)); 62 numattrs++; 63 if (token_spec != NULL) { 64 kmf_set_attr_at_index(setpinattrs, numattrs, 65 KMF_TOKEN_LABEL_ATTR, 66 token_spec, strlen(token_spec)); 67 numattrs++; 68 } 69 70 if ((rv = get_pin(gettext("Enter current token passphrase " 71 "(<CR> if not set):"), NULL, &old_pin, &old_pinlen)) != CKR_OK) { 72 cryptoerror(LOG_STDERR, 73 gettext("Unable to get token passphrase.")); 74 return (PK_ERR_NSS); 75 } 76 /* Get the user's new PIN. */ 77 if ((rv = get_pin(gettext("Create new passphrase:"), gettext( 78 "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) { 79 if (rv == CKR_PIN_INCORRECT) 80 cryptoerror(LOG_STDERR, gettext( 81 "Passphrases do not match.")); 82 else 83 cryptoerror(LOG_STDERR, gettext( 84 "Unable to get and confirm new passphrase.")); 85 if (old_pin != NULL) 86 free(old_pin); 87 return (PK_ERR_NSS); 88 } 89 90 oldcred.cred = (char *)old_pin; 91 oldcred.credlen = old_pinlen; 92 93 kmf_set_attr_at_index(setpinattrs, numattrs, KMF_CREDENTIAL_ATTR, 94 &oldcred, sizeof (oldcred)); 95 numattrs++; 96 97 newpincred.cred = (char *)new_pin; 98 newpincred.credlen = new_pinlen; 99 kmf_set_attr_at_index(setpinattrs, numattrs, KMF_NEWPIN_ATTR, 100 &newpincred, sizeof (newpincred)); 101 numattrs++; 102 103 rv = kmf_set_token_pin(handle, numattrs, setpinattrs); 104 105 if (new_pin) 106 free(new_pin); 107 if (old_pin) 108 free(old_pin); 109 110 return (rv); 111 } 112 113 static int 114 setpin_pkcs11(KMF_HANDLE_T handle, char *token_spec) 115 { 116 CK_SLOT_ID slot_id; 117 CK_FLAGS pin_state; 118 CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL; 119 CK_ULONG old_pinlen = 0, new_pinlen = 0; 120 CK_RV rv = CKR_OK; 121 char *token_name = NULL; 122 CK_TOKEN_INFO token_info; 123 KMF_CREDENTIAL newpincred = {NULL, 0}; 124 KMF_CREDENTIAL oldcred = {NULL, 0}; 125 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 126 KMF_ATTRIBUTE attrlist[6]; 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 rv = kmf_set_token_pin(handle, numattr, attrlist); 212 213 /* Clean up. */ 214 if (old_pin != NULL) 215 free(old_pin); 216 if (new_pin != NULL) 217 free(new_pin); 218 219 return (rv); 220 } 221 222 /* 223 * Changes the token's PIN. 224 */ 225 int 226 pk_setpin(int argc, char *argv[]) 227 /* ARGSUSED */ 228 { 229 int opt; 230 int rv; 231 extern int optind_av; 232 extern char *optarg_av; 233 char *token_spec = NULL; 234 char *dir = NULL; 235 char *prefix = NULL; 236 KMF_HANDLE_T handle; 237 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 238 239 /* Parse command line options. Do NOT i18n/l10n. */ 240 while ((opt = getopt_av(argc, argv, 241 "T:(token)k:(keystore)d:(dir)" 242 "p:(prefix)")) != EOF) { 243 switch (opt) { 244 case 'k': 245 kstype = KS2Int(optarg_av); 246 if (kstype == 0) 247 return (PK_ERR_USAGE); 248 break; 249 case 'T': /* token specifier */ 250 if (token_spec) 251 return (PK_ERR_USAGE); 252 token_spec = optarg_av; 253 break; 254 case 'd': 255 if (dir) 256 return (PK_ERR_USAGE); 257 dir = optarg_av; 258 break; 259 case 'p': 260 if (prefix) 261 return (PK_ERR_USAGE); 262 prefix = optarg_av; 263 break; 264 default: 265 return (PK_ERR_USAGE); 266 break; 267 } 268 } 269 270 271 /* No additional args allowed. */ 272 argc -= optind_av; 273 argv += optind_av; 274 if (argc != 0) 275 return (PK_ERR_USAGE); 276 277 /* Done parsing command line options. */ 278 if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) { 279 token_spec = PK_DEFAULT_PK11TOKEN; 280 } else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) { 281 token_spec = DEFAULT_NSS_TOKEN; 282 } 283 284 if ((rv = kmf_initialize(&handle, NULL, NULL)) != KMF_OK) 285 return (rv); 286 287 switch (kstype) { 288 case KMF_KEYSTORE_PK11TOKEN: 289 rv = setpin_pkcs11(handle, token_spec); 290 break; 291 case KMF_KEYSTORE_NSS: 292 rv = setpin_nss(handle, token_spec, dir, prefix); 293 break; 294 default: 295 cryptoerror(LOG_STDERR, 296 gettext("incorrect keystore.")); 297 return (PK_ERR_USAGE); 298 } 299 300 (void) kmf_finalize(handle); 301 302 if (rv == KMF_ERR_AUTH_FAILED) { 303 cryptoerror(LOG_STDERR, 304 gettext("Incorrect passphrase.")); 305 return (PK_ERR_SYSTEM); 306 } else if (rv != CKR_OK) { 307 cryptoerror(LOG_STDERR, 308 gettext("Unable to change passphrase.")); 309 return (PK_ERR_SYSTEM); 310 } else { 311 (void) fprintf(stdout, gettext("Passphrase changed.\n")); 312 } 313 return (0); 314 } 315