10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 53089Swyllys * Common Development and Distribution License (the "License"). 63089Swyllys * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*5051Swyllys * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 290Sstevel@tonic-gate * This file implements the setpin operation for this tool. 300Sstevel@tonic-gate * The basic flow of the process is to load the PKCS#11 module, 3117Sdinak * finds the soft token, prompt the user for the old PIN (if 3217Sdinak * any) and the new PIN, change the token's PIN, and clean up. 330Sstevel@tonic-gate */ 340Sstevel@tonic-gate 350Sstevel@tonic-gate #include <stdio.h> 360Sstevel@tonic-gate #include <stdlib.h> 3717Sdinak #include <errno.h> 380Sstevel@tonic-gate #include <string.h> 390Sstevel@tonic-gate #include <cryptoutil.h> 400Sstevel@tonic-gate #include <security/cryptoki.h> 410Sstevel@tonic-gate #include "common.h" 420Sstevel@tonic-gate 433089Swyllys static int 443089Swyllys setpin_nss(KMF_HANDLE_T handle, 453089Swyllys char *token_spec, char *dir, char *prefix) 460Sstevel@tonic-gate { 473089Swyllys int rv = 0; 48*5051Swyllys KMF_CREDENTIAL oldcred = {NULL, 0}; 49*5051Swyllys KMF_CREDENTIAL newpincred = {NULL, 0}; 503089Swyllys CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL; 513089Swyllys CK_ULONG old_pinlen = 0, new_pinlen = 0; 52*5051Swyllys KMF_ATTRIBUTE setpinattrs[6]; 53*5051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 54*5051Swyllys int numattrs = 0; 553089Swyllys 563089Swyllys rv = configure_nss(handle, dir, prefix); 573089Swyllys if (rv != KMF_OK) 583089Swyllys return (rv); 593089Swyllys 60*5051Swyllys kmf_set_attr_at_index(setpinattrs, numattrs, KMF_KEYSTORE_TYPE_ATTR, 61*5051Swyllys &kstype, sizeof (kstype)); 62*5051Swyllys numattrs++; 63*5051Swyllys if (token_spec != NULL) { 64*5051Swyllys kmf_set_attr_at_index(setpinattrs, numattrs, 65*5051Swyllys KMF_TOKEN_LABEL_ATTR, 66*5051Swyllys token_spec, strlen(token_spec)); 67*5051Swyllys numattrs++; 68*5051Swyllys } 693089Swyllys 703089Swyllys if ((rv = get_pin(gettext("Enter current token passphrase " 71*5051Swyllys "(<CR> if not set):"), NULL, &old_pin, &old_pinlen)) != CKR_OK) { 723089Swyllys cryptoerror(LOG_STDERR, 733089Swyllys gettext("Unable to get token passphrase.")); 743089Swyllys return (PK_ERR_NSS); 753089Swyllys } 763089Swyllys /* Get the user's new PIN. */ 773089Swyllys if ((rv = get_pin(gettext("Create new passphrase:"), gettext( 783089Swyllys "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) { 793089Swyllys if (rv == CKR_PIN_INCORRECT) 803089Swyllys cryptoerror(LOG_STDERR, gettext( 813089Swyllys "Passphrases do not match.")); 823089Swyllys else 833089Swyllys cryptoerror(LOG_STDERR, gettext( 843089Swyllys "Unable to get and confirm new passphrase.")); 853089Swyllys if (old_pin != NULL) 863089Swyllys free(old_pin); 873089Swyllys return (PK_ERR_NSS); 883089Swyllys } 893089Swyllys 90*5051Swyllys oldcred.cred = (char *)old_pin; 91*5051Swyllys oldcred.credlen = old_pinlen; 92*5051Swyllys 93*5051Swyllys kmf_set_attr_at_index(setpinattrs, numattrs, KMF_CREDENTIAL_ATTR, 94*5051Swyllys &oldcred, sizeof (oldcred)); 95*5051Swyllys numattrs++; 963089Swyllys 973089Swyllys newpincred.cred = (char *)new_pin; 983089Swyllys newpincred.credlen = new_pinlen; 99*5051Swyllys kmf_set_attr_at_index(setpinattrs, numattrs, KMF_NEWPIN_ATTR, 100*5051Swyllys &newpincred, sizeof (newpincred)); 101*5051Swyllys numattrs++; 1023089Swyllys 103*5051Swyllys rv = kmf_set_token_pin(handle, numattrs, setpinattrs); 1043089Swyllys 1053089Swyllys if (new_pin) 1063089Swyllys free(new_pin); 1073089Swyllys if (old_pin) 1083089Swyllys free(old_pin); 1093089Swyllys 1103089Swyllys return (rv); 1113089Swyllys } 1123089Swyllys 1133089Swyllys static int 1143089Swyllys setpin_pkcs11(KMF_HANDLE_T handle, char *token_spec) 1153089Swyllys { 1160Sstevel@tonic-gate CK_SLOT_ID slot_id; 1170Sstevel@tonic-gate CK_FLAGS pin_state; 11817Sdinak CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL; 11917Sdinak CK_ULONG old_pinlen = 0, new_pinlen = 0; 12017Sdinak CK_RV rv = CKR_OK; 1213089Swyllys char *token_name = NULL; 1223089Swyllys CK_TOKEN_INFO token_info; 123*5051Swyllys KMF_CREDENTIAL newpincred = {NULL, 0}; 124*5051Swyllys KMF_CREDENTIAL oldcred = {NULL, 0}; 125*5051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 126*5051Swyllys KMF_ATTRIBUTE attrlist[6]; 127*5051Swyllys int numattr = 0; 128864Sdinak 129864Sdinak /* If nothing is specified, default is to use softtoken. */ 130864Sdinak if (token_spec == NULL) { 1313089Swyllys token_spec = SOFT_TOKEN_LABEL ":" SOFT_MANUFACTURER_ID; 132864Sdinak token_name = SOFT_TOKEN_LABEL; 133864Sdinak } 13417Sdinak 135*5051Swyllys rv = kmf_pk11_token_lookup(NULL, token_spec, &slot_id); 1363089Swyllys if (rv == KMF_OK) { 1373089Swyllys /* find the pin state for the selected token */ 1383089Swyllys if (C_GetTokenInfo(slot_id, &token_info) != CKR_OK) 1393089Swyllys return (PK_ERR_PK11); 1400Sstevel@tonic-gate 1413089Swyllys pin_state = token_info.flags & CKF_USER_PIN_TO_BE_CHANGED; 1423089Swyllys if (token_name == NULL) 1433089Swyllys token_name = (char *)token_info.label; 1440Sstevel@tonic-gate } 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate /* 14717Sdinak * If the token is the softtoken, check if the token flags show the 14817Sdinak * PIN has not been set yet. If not then set the old PIN to the 14917Sdinak * default "changeme". Otherwise, let user type in the correct old 15017Sdinak * PIN to unlock token. 1510Sstevel@tonic-gate */ 15217Sdinak if (pin_state == CKF_USER_PIN_TO_BE_CHANGED && 15317Sdinak strcmp(token_name, SOFT_TOKEN_LABEL) == 0) { 15417Sdinak if ((old_pin = (CK_UTF8CHAR_PTR) strdup(SOFT_DEFAULT_PIN)) == 15517Sdinak NULL) { 15617Sdinak cryptoerror(LOG_STDERR, "%s.", strerror(errno)); 15717Sdinak final_pk11(NULL); 15817Sdinak return (PK_ERR_PK11); 15917Sdinak } 16017Sdinak old_pinlen = strlen(SOFT_DEFAULT_PIN); 16117Sdinak } else { 16217Sdinak if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, 16317Sdinak &old_pin, &old_pinlen)) != CKR_OK) { 16417Sdinak cryptoerror(LOG_STDERR, 16517Sdinak gettext("Unable to get token passphrase (%s)."), 16617Sdinak pkcs11_strerror(rv)); 16717Sdinak final_pk11(NULL); 16817Sdinak return (PK_ERR_PK11); 16917Sdinak } 1700Sstevel@tonic-gate } 1710Sstevel@tonic-gate 17217Sdinak /* Get the user's new PIN. */ 17317Sdinak if ((rv = get_pin(gettext("Create new passphrase:"), gettext( 17417Sdinak "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) { 17517Sdinak if (rv == CKR_PIN_INCORRECT) 17617Sdinak cryptoerror(LOG_STDERR, gettext( 17717Sdinak "Passphrases do not match.")); 17817Sdinak else 17917Sdinak cryptoerror(LOG_STDERR, gettext( 18017Sdinak "Unable to get and confirm new passphrase (%s)."), 18117Sdinak pkcs11_strerror(rv)); 18217Sdinak free(old_pin); 18317Sdinak final_pk11(NULL); 18417Sdinak return (PK_ERR_PK11); 1850Sstevel@tonic-gate } 1860Sstevel@tonic-gate 187*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 188*5051Swyllys &kstype, sizeof (kstype)); 189*5051Swyllys numattr++; 190*5051Swyllys if (token_name != NULL) { 191*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR, 192*5051Swyllys token_name, strlen(token_name)); 193*5051Swyllys numattr++; 194*5051Swyllys } 195*5051Swyllys oldcred.cred = (char *)old_pin; 196*5051Swyllys oldcred.credlen = old_pinlen; 197*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 198*5051Swyllys &oldcred, sizeof (oldcred)); 199*5051Swyllys numattr++; 200*5051Swyllys 201*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_SLOT_ID_ATTR, 202*5051Swyllys &slot_id, sizeof (slot_id)); 203*5051Swyllys numattr++; 20417Sdinak 2053089Swyllys newpincred.cred = (char *)new_pin; 2063089Swyllys newpincred.credlen = new_pinlen; 207*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_NEWPIN_ATTR, 208*5051Swyllys &newpincred, sizeof (newpincred)); 209*5051Swyllys numattr++; 2103089Swyllys 211*5051Swyllys rv = kmf_set_token_pin(handle, numattr, attrlist); 21217Sdinak 21317Sdinak /* Clean up. */ 2143089Swyllys if (old_pin != NULL) 2153089Swyllys free(old_pin); 2163089Swyllys if (new_pin != NULL) 2173089Swyllys free(new_pin); 2183089Swyllys 2193089Swyllys return (rv); 2203089Swyllys } 2213089Swyllys 2223089Swyllys /* 2233089Swyllys * Changes the token's PIN. 2243089Swyllys */ 2253089Swyllys int 2263089Swyllys pk_setpin(int argc, char *argv[]) 2273089Swyllys /* ARGSUSED */ 2283089Swyllys { 2293089Swyllys int opt; 2303089Swyllys int rv; 2313089Swyllys extern int optind_av; 2323089Swyllys extern char *optarg_av; 2333089Swyllys char *token_spec = NULL; 2343089Swyllys char *dir = NULL; 2353089Swyllys char *prefix = NULL; 2363089Swyllys KMF_HANDLE_T handle; 2373089Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 23817Sdinak 2393089Swyllys /* Parse command line options. Do NOT i18n/l10n. */ 2403089Swyllys while ((opt = getopt_av(argc, argv, 2413089Swyllys "T:(token)k:(keystore)d:(dir)" 2423089Swyllys "p:(prefix)")) != EOF) { 2433089Swyllys switch (opt) { 2443089Swyllys case 'k': 2453089Swyllys kstype = KS2Int(optarg_av); 2463089Swyllys if (kstype == 0) 2473089Swyllys return (PK_ERR_USAGE); 2483089Swyllys break; 2493089Swyllys case 'T': /* token specifier */ 2503089Swyllys if (token_spec) 2513089Swyllys return (PK_ERR_USAGE); 2523089Swyllys token_spec = optarg_av; 2533089Swyllys break; 2543089Swyllys case 'd': 2553089Swyllys if (dir) 2563089Swyllys return (PK_ERR_USAGE); 2573089Swyllys dir = optarg_av; 2583089Swyllys break; 2593089Swyllys case 'p': 2603089Swyllys if (prefix) 2613089Swyllys return (PK_ERR_USAGE); 2623089Swyllys prefix = optarg_av; 2633089Swyllys break; 2643089Swyllys default: 2653089Swyllys return (PK_ERR_USAGE); 2663089Swyllys break; 2673089Swyllys } 26817Sdinak } 26917Sdinak 2703089Swyllys 2713089Swyllys /* No additional args allowed. */ 2723089Swyllys argc -= optind_av; 2733089Swyllys argv += optind_av; 2743089Swyllys if (argc != 0) 2753089Swyllys return (PK_ERR_USAGE); 2763089Swyllys 2773089Swyllys /* Done parsing command line options. */ 2783089Swyllys if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) { 2793089Swyllys token_spec = PK_DEFAULT_PK11TOKEN; 2803089Swyllys } else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) { 2813089Swyllys token_spec = DEFAULT_NSS_TOKEN; 2823089Swyllys } 2833089Swyllys 284*5051Swyllys if ((rv = kmf_initialize(&handle, NULL, NULL)) != KMF_OK) 2853089Swyllys return (rv); 2863089Swyllys 2873089Swyllys switch (kstype) { 2883089Swyllys case KMF_KEYSTORE_PK11TOKEN: 2893089Swyllys rv = setpin_pkcs11(handle, token_spec); 2903089Swyllys break; 2913089Swyllys case KMF_KEYSTORE_NSS: 2923089Swyllys rv = setpin_nss(handle, token_spec, dir, prefix); 2933089Swyllys break; 2943089Swyllys default: 2953089Swyllys cryptoerror(LOG_STDERR, 296*5051Swyllys gettext("incorrect keystore.")); 2973089Swyllys return (PK_ERR_USAGE); 2983089Swyllys } 2993089Swyllys 300*5051Swyllys (void) kmf_finalize(handle); 3013089Swyllys 3023089Swyllys if (rv == KMF_ERR_AUTH_FAILED) { 3033089Swyllys cryptoerror(LOG_STDERR, 3043089Swyllys gettext("Incorrect passphrase.")); 3053089Swyllys return (PK_ERR_SYSTEM); 3063089Swyllys } else if (rv != CKR_OK) { 3073089Swyllys cryptoerror(LOG_STDERR, 3083089Swyllys gettext("Unable to change passphrase.")); 3093089Swyllys return (PK_ERR_SYSTEM); 3103089Swyllys } else { 3113089Swyllys (void) fprintf(stdout, gettext("Passphrase changed.\n")); 3123089Swyllys } 31317Sdinak return (0); 3140Sstevel@tonic-gate } 315