17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*99ebb4caSwyllys * Common Development and Distribution License (the "License"). 6*99ebb4caSwyllys * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*99ebb4caSwyllys * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * This file implements the setpin operation for this tool. 307c478bd9Sstevel@tonic-gate * The basic flow of the process is to load the PKCS#11 module, 317711facfSdinak * finds the soft token, prompt the user for the old PIN (if 327711facfSdinak * any) and the new PIN, change the token's PIN, and clean up. 337c478bd9Sstevel@tonic-gate */ 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate #include <stdio.h> 367c478bd9Sstevel@tonic-gate #include <stdlib.h> 377711facfSdinak #include <errno.h> 387c478bd9Sstevel@tonic-gate #include <string.h> 397c478bd9Sstevel@tonic-gate #include <cryptoutil.h> 407c478bd9Sstevel@tonic-gate #include <security/cryptoki.h> 417c478bd9Sstevel@tonic-gate #include "common.h" 427c478bd9Sstevel@tonic-gate 43*99ebb4caSwyllys static int 44*99ebb4caSwyllys setpin_nss(KMF_HANDLE_T handle, 45*99ebb4caSwyllys char *token_spec, char *dir, char *prefix) 467c478bd9Sstevel@tonic-gate { 47*99ebb4caSwyllys int rv = 0; 48*99ebb4caSwyllys KMF_SETPIN_PARAMS params; 49*99ebb4caSwyllys KMF_CREDENTIAL newpincred = { NULL, 0 }; 50*99ebb4caSwyllys CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL; 51*99ebb4caSwyllys CK_ULONG old_pinlen = 0, new_pinlen = 0; 52*99ebb4caSwyllys 53*99ebb4caSwyllys rv = configure_nss(handle, dir, prefix); 54*99ebb4caSwyllys if (rv != KMF_OK) 55*99ebb4caSwyllys return (rv); 56*99ebb4caSwyllys 57*99ebb4caSwyllys (void) memset(¶ms, 0, sizeof (params)); 58*99ebb4caSwyllys params.kstype = KMF_KEYSTORE_NSS; 59*99ebb4caSwyllys params.tokenname = token_spec; 60*99ebb4caSwyllys params.nssparms.slotlabel = token_spec; 61*99ebb4caSwyllys 62*99ebb4caSwyllys if ((rv = get_pin(gettext("Enter current token passphrase " 63*99ebb4caSwyllys "(<CR> if not set):"), NULL, &old_pin, &old_pinlen)) != 64*99ebb4caSwyllys CKR_OK) { 65*99ebb4caSwyllys cryptoerror(LOG_STDERR, 66*99ebb4caSwyllys gettext("Unable to get token passphrase.")); 67*99ebb4caSwyllys return (PK_ERR_NSS); 68*99ebb4caSwyllys } 69*99ebb4caSwyllys /* Get the user's new PIN. */ 70*99ebb4caSwyllys if ((rv = get_pin(gettext("Create new passphrase:"), gettext( 71*99ebb4caSwyllys "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) { 72*99ebb4caSwyllys if (rv == CKR_PIN_INCORRECT) 73*99ebb4caSwyllys cryptoerror(LOG_STDERR, gettext( 74*99ebb4caSwyllys "Passphrases do not match.")); 75*99ebb4caSwyllys else 76*99ebb4caSwyllys cryptoerror(LOG_STDERR, gettext( 77*99ebb4caSwyllys "Unable to get and confirm new passphrase.")); 78*99ebb4caSwyllys if (old_pin != NULL) 79*99ebb4caSwyllys free(old_pin); 80*99ebb4caSwyllys return (PK_ERR_NSS); 81*99ebb4caSwyllys } 82*99ebb4caSwyllys 83*99ebb4caSwyllys params.cred.cred = (char *)old_pin; 84*99ebb4caSwyllys params.cred.credlen = old_pinlen; 85*99ebb4caSwyllys 86*99ebb4caSwyllys newpincred.cred = (char *)new_pin; 87*99ebb4caSwyllys newpincred.credlen = new_pinlen; 88*99ebb4caSwyllys 89*99ebb4caSwyllys rv = KMF_SetTokenPin(handle, ¶ms, &newpincred); 90*99ebb4caSwyllys 91*99ebb4caSwyllys if (new_pin) 92*99ebb4caSwyllys free(new_pin); 93*99ebb4caSwyllys if (old_pin) 94*99ebb4caSwyllys free(old_pin); 95*99ebb4caSwyllys 96*99ebb4caSwyllys return (rv); 97*99ebb4caSwyllys } 98*99ebb4caSwyllys 99*99ebb4caSwyllys static int 100*99ebb4caSwyllys setpin_pkcs11(KMF_HANDLE_T handle, char *token_spec) 101*99ebb4caSwyllys { 1027c478bd9Sstevel@tonic-gate CK_SLOT_ID slot_id; 1037c478bd9Sstevel@tonic-gate CK_FLAGS pin_state; 1047711facfSdinak CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL; 1057711facfSdinak CK_ULONG old_pinlen = 0, new_pinlen = 0; 1067711facfSdinak CK_RV rv = CKR_OK; 107*99ebb4caSwyllys char *token_name = NULL; 108*99ebb4caSwyllys KMF_SETPIN_PARAMS params; 109*99ebb4caSwyllys CK_TOKEN_INFO token_info; 110*99ebb4caSwyllys KMF_CREDENTIAL newpincred = { NULL, 0 }; 11149e21299Sdinak 11249e21299Sdinak /* If nothing is specified, default is to use softtoken. */ 11349e21299Sdinak if (token_spec == NULL) { 114*99ebb4caSwyllys token_spec = SOFT_TOKEN_LABEL ":" SOFT_MANUFACTURER_ID; 11549e21299Sdinak token_name = SOFT_TOKEN_LABEL; 11649e21299Sdinak } 1177711facfSdinak 118*99ebb4caSwyllys rv = KMF_PK11TokenLookup(NULL, token_spec, &slot_id); 119*99ebb4caSwyllys if (rv == KMF_OK) { 120*99ebb4caSwyllys /* find the pin state for the selected token */ 121*99ebb4caSwyllys if (C_GetTokenInfo(slot_id, &token_info) != CKR_OK) 1227711facfSdinak return (PK_ERR_PK11); 123*99ebb4caSwyllys 124*99ebb4caSwyllys pin_state = token_info.flags & CKF_USER_PIN_TO_BE_CHANGED; 125*99ebb4caSwyllys if (token_name == NULL) 126*99ebb4caSwyllys token_name = (char *)token_info.label; 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate /* 1307711facfSdinak * If the token is the softtoken, check if the token flags show the 1317711facfSdinak * PIN has not been set yet. If not then set the old PIN to the 1327711facfSdinak * default "changeme". Otherwise, let user type in the correct old 1337711facfSdinak * PIN to unlock token. 1347c478bd9Sstevel@tonic-gate */ 1357711facfSdinak if (pin_state == CKF_USER_PIN_TO_BE_CHANGED && 1367711facfSdinak strcmp(token_name, SOFT_TOKEN_LABEL) == 0) { 1377711facfSdinak if ((old_pin = (CK_UTF8CHAR_PTR) strdup(SOFT_DEFAULT_PIN)) == 1387711facfSdinak NULL) { 1397711facfSdinak cryptoerror(LOG_STDERR, "%s.", strerror(errno)); 1407711facfSdinak final_pk11(NULL); 1417711facfSdinak return (PK_ERR_PK11); 1427711facfSdinak } 1437711facfSdinak old_pinlen = strlen(SOFT_DEFAULT_PIN); 1447711facfSdinak } else { 1457711facfSdinak if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, 1467711facfSdinak &old_pin, &old_pinlen)) != CKR_OK) { 1477711facfSdinak cryptoerror(LOG_STDERR, 1487711facfSdinak gettext("Unable to get token passphrase (%s)."), 1497711facfSdinak pkcs11_strerror(rv)); 1507711facfSdinak final_pk11(NULL); 1517711facfSdinak return (PK_ERR_PK11); 1527711facfSdinak } 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate 1557711facfSdinak /* Get the user's new PIN. */ 1567711facfSdinak if ((rv = get_pin(gettext("Create new passphrase:"), gettext( 1577711facfSdinak "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) { 1587711facfSdinak if (rv == CKR_PIN_INCORRECT) 1597711facfSdinak cryptoerror(LOG_STDERR, gettext( 1607711facfSdinak "Passphrases do not match.")); 1617711facfSdinak else 1627711facfSdinak cryptoerror(LOG_STDERR, gettext( 1637711facfSdinak "Unable to get and confirm new passphrase (%s)."), 1647711facfSdinak pkcs11_strerror(rv)); 1657711facfSdinak free(old_pin); 1667711facfSdinak final_pk11(NULL); 1677711facfSdinak return (PK_ERR_PK11); 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate 170*99ebb4caSwyllys (void) memset(¶ms, 0, sizeof (params)); 171*99ebb4caSwyllys params.kstype = KMF_KEYSTORE_PK11TOKEN; 172*99ebb4caSwyllys params.tokenname = (char *)token_info.label; 173*99ebb4caSwyllys params.cred.cred = (char *)old_pin; 174*99ebb4caSwyllys params.cred.credlen = old_pinlen; 175*99ebb4caSwyllys params.pkcs11parms.slot = slot_id; 1767711facfSdinak 177*99ebb4caSwyllys newpincred.cred = (char *)new_pin; 178*99ebb4caSwyllys newpincred.credlen = new_pinlen; 179*99ebb4caSwyllys 180*99ebb4caSwyllys rv = KMF_SetTokenPin(handle, ¶ms, &newpincred); 1817711facfSdinak 1827711facfSdinak /* Clean up. */ 183*99ebb4caSwyllys if (old_pin != NULL) 1847711facfSdinak free(old_pin); 185*99ebb4caSwyllys if (new_pin != NULL) 1867711facfSdinak free(new_pin); 1877711facfSdinak 188*99ebb4caSwyllys return (rv); 1897711facfSdinak } 1907711facfSdinak 191*99ebb4caSwyllys /* 192*99ebb4caSwyllys * Changes the token's PIN. 193*99ebb4caSwyllys */ 194*99ebb4caSwyllys int 195*99ebb4caSwyllys pk_setpin(int argc, char *argv[]) 196*99ebb4caSwyllys /* ARGSUSED */ 197*99ebb4caSwyllys { 198*99ebb4caSwyllys int opt; 199*99ebb4caSwyllys int rv; 200*99ebb4caSwyllys extern int optind_av; 201*99ebb4caSwyllys extern char *optarg_av; 202*99ebb4caSwyllys char *token_spec = NULL; 203*99ebb4caSwyllys char *dir = NULL; 204*99ebb4caSwyllys char *prefix = NULL; 205*99ebb4caSwyllys KMF_HANDLE_T handle; 206*99ebb4caSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 207*99ebb4caSwyllys 208*99ebb4caSwyllys /* Parse command line options. Do NOT i18n/l10n. */ 209*99ebb4caSwyllys while ((opt = getopt_av(argc, argv, 210*99ebb4caSwyllys "T:(token)k:(keystore)d:(dir)" 211*99ebb4caSwyllys "p:(prefix)")) != EOF) { 212*99ebb4caSwyllys switch (opt) { 213*99ebb4caSwyllys case 'k': 214*99ebb4caSwyllys kstype = KS2Int(optarg_av); 215*99ebb4caSwyllys if (kstype == 0) 216*99ebb4caSwyllys return (PK_ERR_USAGE); 217*99ebb4caSwyllys break; 218*99ebb4caSwyllys case 'T': /* token specifier */ 219*99ebb4caSwyllys if (token_spec) 220*99ebb4caSwyllys return (PK_ERR_USAGE); 221*99ebb4caSwyllys token_spec = optarg_av; 222*99ebb4caSwyllys break; 223*99ebb4caSwyllys case 'd': 224*99ebb4caSwyllys if (dir) 225*99ebb4caSwyllys return (PK_ERR_USAGE); 226*99ebb4caSwyllys dir = optarg_av; 227*99ebb4caSwyllys break; 228*99ebb4caSwyllys case 'p': 229*99ebb4caSwyllys if (prefix) 230*99ebb4caSwyllys return (PK_ERR_USAGE); 231*99ebb4caSwyllys prefix = optarg_av; 232*99ebb4caSwyllys break; 233*99ebb4caSwyllys default: 234*99ebb4caSwyllys return (PK_ERR_USAGE); 235*99ebb4caSwyllys break; 236*99ebb4caSwyllys } 237*99ebb4caSwyllys } 238*99ebb4caSwyllys 239*99ebb4caSwyllys 240*99ebb4caSwyllys /* No additional args allowed. */ 241*99ebb4caSwyllys argc -= optind_av; 242*99ebb4caSwyllys argv += optind_av; 243*99ebb4caSwyllys if (argc != 0) 244*99ebb4caSwyllys return (PK_ERR_USAGE); 245*99ebb4caSwyllys 246*99ebb4caSwyllys /* Done parsing command line options. */ 247*99ebb4caSwyllys if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) { 248*99ebb4caSwyllys token_spec = PK_DEFAULT_PK11TOKEN; 249*99ebb4caSwyllys } else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) { 250*99ebb4caSwyllys token_spec = DEFAULT_NSS_TOKEN; 251*99ebb4caSwyllys } 252*99ebb4caSwyllys 253*99ebb4caSwyllys if ((rv = KMF_Initialize(&handle, NULL, NULL)) != KMF_OK) 254*99ebb4caSwyllys return (rv); 255*99ebb4caSwyllys 256*99ebb4caSwyllys switch (kstype) { 257*99ebb4caSwyllys case KMF_KEYSTORE_PK11TOKEN: 258*99ebb4caSwyllys rv = setpin_pkcs11(handle, token_spec); 259*99ebb4caSwyllys break; 260*99ebb4caSwyllys case KMF_KEYSTORE_NSS: 261*99ebb4caSwyllys rv = setpin_nss(handle, token_spec, dir, prefix); 262*99ebb4caSwyllys break; 263*99ebb4caSwyllys default: 264*99ebb4caSwyllys cryptoerror(LOG_STDERR, 265*99ebb4caSwyllys gettext("incorrect keystore.")); 266*99ebb4caSwyllys return (PK_ERR_USAGE); 267*99ebb4caSwyllys } 268*99ebb4caSwyllys 269*99ebb4caSwyllys (void) KMF_Finalize(handle); 270*99ebb4caSwyllys 271*99ebb4caSwyllys if (rv == KMF_ERR_AUTH_FAILED) { 272*99ebb4caSwyllys cryptoerror(LOG_STDERR, 273*99ebb4caSwyllys gettext("Incorrect passphrase.")); 274*99ebb4caSwyllys return (PK_ERR_SYSTEM); 275*99ebb4caSwyllys } else if (rv != CKR_OK) { 276*99ebb4caSwyllys cryptoerror(LOG_STDERR, 277*99ebb4caSwyllys gettext("Unable to change passphrase.")); 278*99ebb4caSwyllys return (PK_ERR_SYSTEM); 279*99ebb4caSwyllys } else { 2807711facfSdinak (void) fprintf(stdout, gettext("Passphrase changed.\n")); 281*99ebb4caSwyllys } 2827711facfSdinak return (0); 2837c478bd9Sstevel@tonic-gate } 284