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 5*3089Swyllys * Common Development and Distribution License (the "License"). 6*3089Swyllys * 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*3089Swyllys * Copyright 2006 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 43*3089Swyllys static int 44*3089Swyllys setpin_nss(KMF_HANDLE_T handle, 45*3089Swyllys char *token_spec, char *dir, char *prefix) 460Sstevel@tonic-gate { 47*3089Swyllys int rv = 0; 48*3089Swyllys KMF_SETPIN_PARAMS params; 49*3089Swyllys KMF_CREDENTIAL newpincred = { NULL, 0 }; 50*3089Swyllys CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL; 51*3089Swyllys CK_ULONG old_pinlen = 0, new_pinlen = 0; 52*3089Swyllys 53*3089Swyllys rv = configure_nss(handle, dir, prefix); 54*3089Swyllys if (rv != KMF_OK) 55*3089Swyllys return (rv); 56*3089Swyllys 57*3089Swyllys (void) memset(¶ms, 0, sizeof (params)); 58*3089Swyllys params.kstype = KMF_KEYSTORE_NSS; 59*3089Swyllys params.tokenname = token_spec; 60*3089Swyllys params.nssparms.slotlabel = token_spec; 61*3089Swyllys 62*3089Swyllys if ((rv = get_pin(gettext("Enter current token passphrase " 63*3089Swyllys "(<CR> if not set):"), NULL, &old_pin, &old_pinlen)) != 64*3089Swyllys CKR_OK) { 65*3089Swyllys cryptoerror(LOG_STDERR, 66*3089Swyllys gettext("Unable to get token passphrase.")); 67*3089Swyllys return (PK_ERR_NSS); 68*3089Swyllys } 69*3089Swyllys /* Get the user's new PIN. */ 70*3089Swyllys if ((rv = get_pin(gettext("Create new passphrase:"), gettext( 71*3089Swyllys "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) { 72*3089Swyllys if (rv == CKR_PIN_INCORRECT) 73*3089Swyllys cryptoerror(LOG_STDERR, gettext( 74*3089Swyllys "Passphrases do not match.")); 75*3089Swyllys else 76*3089Swyllys cryptoerror(LOG_STDERR, gettext( 77*3089Swyllys "Unable to get and confirm new passphrase.")); 78*3089Swyllys if (old_pin != NULL) 79*3089Swyllys free(old_pin); 80*3089Swyllys return (PK_ERR_NSS); 81*3089Swyllys } 82*3089Swyllys 83*3089Swyllys params.cred.cred = (char *)old_pin; 84*3089Swyllys params.cred.credlen = old_pinlen; 85*3089Swyllys 86*3089Swyllys newpincred.cred = (char *)new_pin; 87*3089Swyllys newpincred.credlen = new_pinlen; 88*3089Swyllys 89*3089Swyllys rv = KMF_SetTokenPin(handle, ¶ms, &newpincred); 90*3089Swyllys 91*3089Swyllys if (new_pin) 92*3089Swyllys free(new_pin); 93*3089Swyllys if (old_pin) 94*3089Swyllys free(old_pin); 95*3089Swyllys 96*3089Swyllys return (rv); 97*3089Swyllys } 98*3089Swyllys 99*3089Swyllys static int 100*3089Swyllys setpin_pkcs11(KMF_HANDLE_T handle, char *token_spec) 101*3089Swyllys { 1020Sstevel@tonic-gate CK_SLOT_ID slot_id; 1030Sstevel@tonic-gate CK_FLAGS pin_state; 10417Sdinak CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL; 10517Sdinak CK_ULONG old_pinlen = 0, new_pinlen = 0; 10617Sdinak CK_RV rv = CKR_OK; 107*3089Swyllys char *token_name = NULL; 108*3089Swyllys KMF_SETPIN_PARAMS params; 109*3089Swyllys CK_TOKEN_INFO token_info; 110*3089Swyllys KMF_CREDENTIAL newpincred = { NULL, 0 }; 111864Sdinak 112864Sdinak /* If nothing is specified, default is to use softtoken. */ 113864Sdinak if (token_spec == NULL) { 114*3089Swyllys token_spec = SOFT_TOKEN_LABEL ":" SOFT_MANUFACTURER_ID; 115864Sdinak token_name = SOFT_TOKEN_LABEL; 116864Sdinak } 11717Sdinak 118*3089Swyllys rv = KMF_PK11TokenLookup(NULL, token_spec, &slot_id); 119*3089Swyllys if (rv == KMF_OK) { 120*3089Swyllys /* find the pin state for the selected token */ 121*3089Swyllys if (C_GetTokenInfo(slot_id, &token_info) != CKR_OK) 122*3089Swyllys return (PK_ERR_PK11); 1230Sstevel@tonic-gate 124*3089Swyllys pin_state = token_info.flags & CKF_USER_PIN_TO_BE_CHANGED; 125*3089Swyllys if (token_name == NULL) 126*3089Swyllys token_name = (char *)token_info.label; 1270Sstevel@tonic-gate } 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate /* 13017Sdinak * If the token is the softtoken, check if the token flags show the 13117Sdinak * PIN has not been set yet. If not then set the old PIN to the 13217Sdinak * default "changeme". Otherwise, let user type in the correct old 13317Sdinak * PIN to unlock token. 1340Sstevel@tonic-gate */ 13517Sdinak if (pin_state == CKF_USER_PIN_TO_BE_CHANGED && 13617Sdinak strcmp(token_name, SOFT_TOKEN_LABEL) == 0) { 13717Sdinak if ((old_pin = (CK_UTF8CHAR_PTR) strdup(SOFT_DEFAULT_PIN)) == 13817Sdinak NULL) { 13917Sdinak cryptoerror(LOG_STDERR, "%s.", strerror(errno)); 14017Sdinak final_pk11(NULL); 14117Sdinak return (PK_ERR_PK11); 14217Sdinak } 14317Sdinak old_pinlen = strlen(SOFT_DEFAULT_PIN); 14417Sdinak } else { 14517Sdinak if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, 14617Sdinak &old_pin, &old_pinlen)) != CKR_OK) { 14717Sdinak cryptoerror(LOG_STDERR, 14817Sdinak gettext("Unable to get token passphrase (%s)."), 14917Sdinak pkcs11_strerror(rv)); 15017Sdinak final_pk11(NULL); 15117Sdinak return (PK_ERR_PK11); 15217Sdinak } 1530Sstevel@tonic-gate } 1540Sstevel@tonic-gate 15517Sdinak /* Get the user's new PIN. */ 15617Sdinak if ((rv = get_pin(gettext("Create new passphrase:"), gettext( 15717Sdinak "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) { 15817Sdinak if (rv == CKR_PIN_INCORRECT) 15917Sdinak cryptoerror(LOG_STDERR, gettext( 16017Sdinak "Passphrases do not match.")); 16117Sdinak else 16217Sdinak cryptoerror(LOG_STDERR, gettext( 16317Sdinak "Unable to get and confirm new passphrase (%s)."), 16417Sdinak pkcs11_strerror(rv)); 16517Sdinak free(old_pin); 16617Sdinak final_pk11(NULL); 16717Sdinak return (PK_ERR_PK11); 1680Sstevel@tonic-gate } 1690Sstevel@tonic-gate 170*3089Swyllys (void) memset(¶ms, 0, sizeof (params)); 171*3089Swyllys params.kstype = KMF_KEYSTORE_PK11TOKEN; 172*3089Swyllys params.tokenname = (char *)token_info.label; 173*3089Swyllys params.cred.cred = (char *)old_pin; 174*3089Swyllys params.cred.credlen = old_pinlen; 175*3089Swyllys params.pkcs11parms.slot = slot_id; 17617Sdinak 177*3089Swyllys newpincred.cred = (char *)new_pin; 178*3089Swyllys newpincred.credlen = new_pinlen; 179*3089Swyllys 180*3089Swyllys rv = KMF_SetTokenPin(handle, ¶ms, &newpincred); 18117Sdinak 18217Sdinak /* Clean up. */ 183*3089Swyllys if (old_pin != NULL) 184*3089Swyllys free(old_pin); 185*3089Swyllys if (new_pin != NULL) 186*3089Swyllys free(new_pin); 187*3089Swyllys 188*3089Swyllys return (rv); 189*3089Swyllys } 190*3089Swyllys 191*3089Swyllys /* 192*3089Swyllys * Changes the token's PIN. 193*3089Swyllys */ 194*3089Swyllys int 195*3089Swyllys pk_setpin(int argc, char *argv[]) 196*3089Swyllys /* ARGSUSED */ 197*3089Swyllys { 198*3089Swyllys int opt; 199*3089Swyllys int rv; 200*3089Swyllys extern int optind_av; 201*3089Swyllys extern char *optarg_av; 202*3089Swyllys char *token_spec = NULL; 203*3089Swyllys char *dir = NULL; 204*3089Swyllys char *prefix = NULL; 205*3089Swyllys KMF_HANDLE_T handle; 206*3089Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 20717Sdinak 208*3089Swyllys /* Parse command line options. Do NOT i18n/l10n. */ 209*3089Swyllys while ((opt = getopt_av(argc, argv, 210*3089Swyllys "T:(token)k:(keystore)d:(dir)" 211*3089Swyllys "p:(prefix)")) != EOF) { 212*3089Swyllys switch (opt) { 213*3089Swyllys case 'k': 214*3089Swyllys kstype = KS2Int(optarg_av); 215*3089Swyllys if (kstype == 0) 216*3089Swyllys return (PK_ERR_USAGE); 217*3089Swyllys break; 218*3089Swyllys case 'T': /* token specifier */ 219*3089Swyllys if (token_spec) 220*3089Swyllys return (PK_ERR_USAGE); 221*3089Swyllys token_spec = optarg_av; 222*3089Swyllys break; 223*3089Swyllys case 'd': 224*3089Swyllys if (dir) 225*3089Swyllys return (PK_ERR_USAGE); 226*3089Swyllys dir = optarg_av; 227*3089Swyllys break; 228*3089Swyllys case 'p': 229*3089Swyllys if (prefix) 230*3089Swyllys return (PK_ERR_USAGE); 231*3089Swyllys prefix = optarg_av; 232*3089Swyllys break; 233*3089Swyllys default: 234*3089Swyllys return (PK_ERR_USAGE); 235*3089Swyllys break; 236*3089Swyllys } 23717Sdinak } 23817Sdinak 239*3089Swyllys 240*3089Swyllys /* No additional args allowed. */ 241*3089Swyllys argc -= optind_av; 242*3089Swyllys argv += optind_av; 243*3089Swyllys if (argc != 0) 244*3089Swyllys return (PK_ERR_USAGE); 245*3089Swyllys 246*3089Swyllys /* Done parsing command line options. */ 247*3089Swyllys if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) { 248*3089Swyllys token_spec = PK_DEFAULT_PK11TOKEN; 249*3089Swyllys } else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) { 250*3089Swyllys token_spec = DEFAULT_NSS_TOKEN; 251*3089Swyllys } 252*3089Swyllys 253*3089Swyllys if ((rv = KMF_Initialize(&handle, NULL, NULL)) != KMF_OK) 254*3089Swyllys return (rv); 255*3089Swyllys 256*3089Swyllys switch (kstype) { 257*3089Swyllys case KMF_KEYSTORE_PK11TOKEN: 258*3089Swyllys rv = setpin_pkcs11(handle, token_spec); 259*3089Swyllys break; 260*3089Swyllys case KMF_KEYSTORE_NSS: 261*3089Swyllys rv = setpin_nss(handle, token_spec, dir, prefix); 262*3089Swyllys break; 263*3089Swyllys default: 264*3089Swyllys cryptoerror(LOG_STDERR, 265*3089Swyllys gettext("incorrect keystore.")); 266*3089Swyllys return (PK_ERR_USAGE); 267*3089Swyllys } 268*3089Swyllys 269*3089Swyllys (void) KMF_Finalize(handle); 270*3089Swyllys 271*3089Swyllys if (rv == KMF_ERR_AUTH_FAILED) { 272*3089Swyllys cryptoerror(LOG_STDERR, 273*3089Swyllys gettext("Incorrect passphrase.")); 274*3089Swyllys return (PK_ERR_SYSTEM); 275*3089Swyllys } else if (rv != CKR_OK) { 276*3089Swyllys cryptoerror(LOG_STDERR, 277*3089Swyllys gettext("Unable to change passphrase.")); 278*3089Swyllys return (PK_ERR_SYSTEM); 279*3089Swyllys } else { 280*3089Swyllys (void) fprintf(stdout, gettext("Passphrase changed.\n")); 281*3089Swyllys } 28217Sdinak return (0); 2830Sstevel@tonic-gate } 284