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 599ebb4caSwyllys * Common Development and Distribution License (the "License"). 699ebb4caSwyllys * 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*30a5e8faSwyllys * Copyright 2007 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 4399ebb4caSwyllys static int 4499ebb4caSwyllys setpin_nss(KMF_HANDLE_T handle, 4599ebb4caSwyllys char *token_spec, char *dir, char *prefix) 467c478bd9Sstevel@tonic-gate { 4799ebb4caSwyllys int rv = 0; 48*30a5e8faSwyllys KMF_CREDENTIAL oldcred = {NULL, 0}; 4999ebb4caSwyllys KMF_CREDENTIAL newpincred = {NULL, 0}; 5099ebb4caSwyllys CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL; 5199ebb4caSwyllys CK_ULONG old_pinlen = 0, new_pinlen = 0; 52*30a5e8faSwyllys KMF_ATTRIBUTE setpinattrs[6]; 53*30a5e8faSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 54*30a5e8faSwyllys int numattrs = 0; 5599ebb4caSwyllys 5699ebb4caSwyllys rv = configure_nss(handle, dir, prefix); 5799ebb4caSwyllys if (rv != KMF_OK) 5899ebb4caSwyllys return (rv); 5999ebb4caSwyllys 60*30a5e8faSwyllys kmf_set_attr_at_index(setpinattrs, numattrs, KMF_KEYSTORE_TYPE_ATTR, 61*30a5e8faSwyllys &kstype, sizeof (kstype)); 62*30a5e8faSwyllys numattrs++; 63*30a5e8faSwyllys if (token_spec != NULL) { 64*30a5e8faSwyllys kmf_set_attr_at_index(setpinattrs, numattrs, 65*30a5e8faSwyllys KMF_TOKEN_LABEL_ATTR, 66*30a5e8faSwyllys token_spec, strlen(token_spec)); 67*30a5e8faSwyllys numattrs++; 68*30a5e8faSwyllys } 6999ebb4caSwyllys 7099ebb4caSwyllys if ((rv = get_pin(gettext("Enter current token passphrase " 71*30a5e8faSwyllys "(<CR> if not set):"), NULL, &old_pin, &old_pinlen)) != CKR_OK) { 7299ebb4caSwyllys cryptoerror(LOG_STDERR, 7399ebb4caSwyllys gettext("Unable to get token passphrase.")); 7499ebb4caSwyllys return (PK_ERR_NSS); 7599ebb4caSwyllys } 7699ebb4caSwyllys /* Get the user's new PIN. */ 7799ebb4caSwyllys if ((rv = get_pin(gettext("Create new passphrase:"), gettext( 7899ebb4caSwyllys "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) { 7999ebb4caSwyllys if (rv == CKR_PIN_INCORRECT) 8099ebb4caSwyllys cryptoerror(LOG_STDERR, gettext( 8199ebb4caSwyllys "Passphrases do not match.")); 8299ebb4caSwyllys else 8399ebb4caSwyllys cryptoerror(LOG_STDERR, gettext( 8499ebb4caSwyllys "Unable to get and confirm new passphrase.")); 8599ebb4caSwyllys if (old_pin != NULL) 8699ebb4caSwyllys free(old_pin); 8799ebb4caSwyllys return (PK_ERR_NSS); 8899ebb4caSwyllys } 8999ebb4caSwyllys 90*30a5e8faSwyllys oldcred.cred = (char *)old_pin; 91*30a5e8faSwyllys oldcred.credlen = old_pinlen; 92*30a5e8faSwyllys 93*30a5e8faSwyllys kmf_set_attr_at_index(setpinattrs, numattrs, KMF_CREDENTIAL_ATTR, 94*30a5e8faSwyllys &oldcred, sizeof (oldcred)); 95*30a5e8faSwyllys numattrs++; 9699ebb4caSwyllys 9799ebb4caSwyllys newpincred.cred = (char *)new_pin; 9899ebb4caSwyllys newpincred.credlen = new_pinlen; 99*30a5e8faSwyllys kmf_set_attr_at_index(setpinattrs, numattrs, KMF_NEWPIN_ATTR, 100*30a5e8faSwyllys &newpincred, sizeof (newpincred)); 101*30a5e8faSwyllys numattrs++; 10299ebb4caSwyllys 103*30a5e8faSwyllys rv = kmf_set_token_pin(handle, numattrs, setpinattrs); 10499ebb4caSwyllys 10599ebb4caSwyllys if (new_pin) 10699ebb4caSwyllys free(new_pin); 10799ebb4caSwyllys if (old_pin) 10899ebb4caSwyllys free(old_pin); 10999ebb4caSwyllys 11099ebb4caSwyllys return (rv); 11199ebb4caSwyllys } 11299ebb4caSwyllys 11399ebb4caSwyllys static int 11499ebb4caSwyllys setpin_pkcs11(KMF_HANDLE_T handle, char *token_spec) 11599ebb4caSwyllys { 1167c478bd9Sstevel@tonic-gate CK_SLOT_ID slot_id; 1177c478bd9Sstevel@tonic-gate CK_FLAGS pin_state; 1187711facfSdinak CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL; 1197711facfSdinak CK_ULONG old_pinlen = 0, new_pinlen = 0; 1207711facfSdinak CK_RV rv = CKR_OK; 12199ebb4caSwyllys char *token_name = NULL; 12299ebb4caSwyllys CK_TOKEN_INFO token_info; 12399ebb4caSwyllys KMF_CREDENTIAL newpincred = {NULL, 0}; 124*30a5e8faSwyllys KMF_CREDENTIAL oldcred = {NULL, 0}; 125*30a5e8faSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 126*30a5e8faSwyllys KMF_ATTRIBUTE attrlist[6]; 127*30a5e8faSwyllys int numattr = 0; 12849e21299Sdinak 12949e21299Sdinak /* If nothing is specified, default is to use softtoken. */ 13049e21299Sdinak if (token_spec == NULL) { 13199ebb4caSwyllys token_spec = SOFT_TOKEN_LABEL ":" SOFT_MANUFACTURER_ID; 13249e21299Sdinak token_name = SOFT_TOKEN_LABEL; 13349e21299Sdinak } 1347711facfSdinak 135*30a5e8faSwyllys rv = kmf_pk11_token_lookup(NULL, token_spec, &slot_id); 13699ebb4caSwyllys if (rv == KMF_OK) { 13799ebb4caSwyllys /* find the pin state for the selected token */ 13899ebb4caSwyllys if (C_GetTokenInfo(slot_id, &token_info) != CKR_OK) 1397711facfSdinak return (PK_ERR_PK11); 14099ebb4caSwyllys 14199ebb4caSwyllys pin_state = token_info.flags & CKF_USER_PIN_TO_BE_CHANGED; 14299ebb4caSwyllys if (token_name == NULL) 14399ebb4caSwyllys token_name = (char *)token_info.label; 1447c478bd9Sstevel@tonic-gate } 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate /* 1477711facfSdinak * If the token is the softtoken, check if the token flags show the 1487711facfSdinak * PIN has not been set yet. If not then set the old PIN to the 1497711facfSdinak * default "changeme". Otherwise, let user type in the correct old 1507711facfSdinak * PIN to unlock token. 1517c478bd9Sstevel@tonic-gate */ 1527711facfSdinak if (pin_state == CKF_USER_PIN_TO_BE_CHANGED && 1537711facfSdinak strcmp(token_name, SOFT_TOKEN_LABEL) == 0) { 1547711facfSdinak if ((old_pin = (CK_UTF8CHAR_PTR) strdup(SOFT_DEFAULT_PIN)) == 1557711facfSdinak NULL) { 1567711facfSdinak cryptoerror(LOG_STDERR, "%s.", strerror(errno)); 1577711facfSdinak final_pk11(NULL); 1587711facfSdinak return (PK_ERR_PK11); 1597711facfSdinak } 1607711facfSdinak old_pinlen = strlen(SOFT_DEFAULT_PIN); 1617711facfSdinak } else { 1627711facfSdinak if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, 1637711facfSdinak &old_pin, &old_pinlen)) != CKR_OK) { 1647711facfSdinak cryptoerror(LOG_STDERR, 1657711facfSdinak gettext("Unable to get token passphrase (%s)."), 1667711facfSdinak pkcs11_strerror(rv)); 1677711facfSdinak final_pk11(NULL); 1687711facfSdinak return (PK_ERR_PK11); 1697711facfSdinak } 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate 1727711facfSdinak /* Get the user's new PIN. */ 1737711facfSdinak if ((rv = get_pin(gettext("Create new passphrase:"), gettext( 1747711facfSdinak "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) { 1757711facfSdinak if (rv == CKR_PIN_INCORRECT) 1767711facfSdinak cryptoerror(LOG_STDERR, gettext( 1777711facfSdinak "Passphrases do not match.")); 1787711facfSdinak else 1797711facfSdinak cryptoerror(LOG_STDERR, gettext( 1807711facfSdinak "Unable to get and confirm new passphrase (%s)."), 1817711facfSdinak pkcs11_strerror(rv)); 1827711facfSdinak free(old_pin); 1837711facfSdinak final_pk11(NULL); 1847711facfSdinak return (PK_ERR_PK11); 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate 187*30a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 188*30a5e8faSwyllys &kstype, sizeof (kstype)); 189*30a5e8faSwyllys numattr++; 190*30a5e8faSwyllys if (token_name != NULL) { 191*30a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR, 192*30a5e8faSwyllys token_name, strlen(token_name)); 193*30a5e8faSwyllys numattr++; 194*30a5e8faSwyllys } 195*30a5e8faSwyllys oldcred.cred = (char *)old_pin; 196*30a5e8faSwyllys oldcred.credlen = old_pinlen; 197*30a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 198*30a5e8faSwyllys &oldcred, sizeof (oldcred)); 199*30a5e8faSwyllys numattr++; 200*30a5e8faSwyllys 201*30a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_SLOT_ID_ATTR, 202*30a5e8faSwyllys &slot_id, sizeof (slot_id)); 203*30a5e8faSwyllys numattr++; 2047711facfSdinak 20599ebb4caSwyllys newpincred.cred = (char *)new_pin; 20699ebb4caSwyllys newpincred.credlen = new_pinlen; 207*30a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_NEWPIN_ATTR, 208*30a5e8faSwyllys &newpincred, sizeof (newpincred)); 209*30a5e8faSwyllys numattr++; 21099ebb4caSwyllys 211*30a5e8faSwyllys rv = kmf_set_token_pin(handle, numattr, attrlist); 2127711facfSdinak 2137711facfSdinak /* Clean up. */ 21499ebb4caSwyllys if (old_pin != NULL) 2157711facfSdinak free(old_pin); 21699ebb4caSwyllys if (new_pin != NULL) 2177711facfSdinak free(new_pin); 2187711facfSdinak 21999ebb4caSwyllys return (rv); 2207711facfSdinak } 2217711facfSdinak 22299ebb4caSwyllys /* 22399ebb4caSwyllys * Changes the token's PIN. 22499ebb4caSwyllys */ 22599ebb4caSwyllys int 22699ebb4caSwyllys pk_setpin(int argc, char *argv[]) 22799ebb4caSwyllys /* ARGSUSED */ 22899ebb4caSwyllys { 22999ebb4caSwyllys int opt; 23099ebb4caSwyllys int rv; 23199ebb4caSwyllys extern int optind_av; 23299ebb4caSwyllys extern char *optarg_av; 23399ebb4caSwyllys char *token_spec = NULL; 23499ebb4caSwyllys char *dir = NULL; 23599ebb4caSwyllys char *prefix = NULL; 23699ebb4caSwyllys KMF_HANDLE_T handle; 23799ebb4caSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 23899ebb4caSwyllys 23999ebb4caSwyllys /* Parse command line options. Do NOT i18n/l10n. */ 24099ebb4caSwyllys while ((opt = getopt_av(argc, argv, 24199ebb4caSwyllys "T:(token)k:(keystore)d:(dir)" 24299ebb4caSwyllys "p:(prefix)")) != EOF) { 24399ebb4caSwyllys switch (opt) { 24499ebb4caSwyllys case 'k': 24599ebb4caSwyllys kstype = KS2Int(optarg_av); 24699ebb4caSwyllys if (kstype == 0) 24799ebb4caSwyllys return (PK_ERR_USAGE); 24899ebb4caSwyllys break; 24999ebb4caSwyllys case 'T': /* token specifier */ 25099ebb4caSwyllys if (token_spec) 25199ebb4caSwyllys return (PK_ERR_USAGE); 25299ebb4caSwyllys token_spec = optarg_av; 25399ebb4caSwyllys break; 25499ebb4caSwyllys case 'd': 25599ebb4caSwyllys if (dir) 25699ebb4caSwyllys return (PK_ERR_USAGE); 25799ebb4caSwyllys dir = optarg_av; 25899ebb4caSwyllys break; 25999ebb4caSwyllys case 'p': 26099ebb4caSwyllys if (prefix) 26199ebb4caSwyllys return (PK_ERR_USAGE); 26299ebb4caSwyllys prefix = optarg_av; 26399ebb4caSwyllys break; 26499ebb4caSwyllys default: 26599ebb4caSwyllys return (PK_ERR_USAGE); 26699ebb4caSwyllys break; 26799ebb4caSwyllys } 26899ebb4caSwyllys } 26999ebb4caSwyllys 27099ebb4caSwyllys 27199ebb4caSwyllys /* No additional args allowed. */ 27299ebb4caSwyllys argc -= optind_av; 27399ebb4caSwyllys argv += optind_av; 27499ebb4caSwyllys if (argc != 0) 27599ebb4caSwyllys return (PK_ERR_USAGE); 27699ebb4caSwyllys 27799ebb4caSwyllys /* Done parsing command line options. */ 27899ebb4caSwyllys if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) { 27999ebb4caSwyllys token_spec = PK_DEFAULT_PK11TOKEN; 28099ebb4caSwyllys } else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) { 28199ebb4caSwyllys token_spec = DEFAULT_NSS_TOKEN; 28299ebb4caSwyllys } 28399ebb4caSwyllys 284*30a5e8faSwyllys if ((rv = kmf_initialize(&handle, NULL, NULL)) != KMF_OK) 28599ebb4caSwyllys return (rv); 28699ebb4caSwyllys 28799ebb4caSwyllys switch (kstype) { 28899ebb4caSwyllys case KMF_KEYSTORE_PK11TOKEN: 28999ebb4caSwyllys rv = setpin_pkcs11(handle, token_spec); 29099ebb4caSwyllys break; 29199ebb4caSwyllys case KMF_KEYSTORE_NSS: 29299ebb4caSwyllys rv = setpin_nss(handle, token_spec, dir, prefix); 29399ebb4caSwyllys break; 29499ebb4caSwyllys default: 29599ebb4caSwyllys cryptoerror(LOG_STDERR, 29699ebb4caSwyllys gettext("incorrect keystore.")); 29799ebb4caSwyllys return (PK_ERR_USAGE); 29899ebb4caSwyllys } 29999ebb4caSwyllys 300*30a5e8faSwyllys (void) kmf_finalize(handle); 30199ebb4caSwyllys 30299ebb4caSwyllys if (rv == KMF_ERR_AUTH_FAILED) { 30399ebb4caSwyllys cryptoerror(LOG_STDERR, 30499ebb4caSwyllys gettext("Incorrect passphrase.")); 30599ebb4caSwyllys return (PK_ERR_SYSTEM); 30699ebb4caSwyllys } else if (rv != CKR_OK) { 30799ebb4caSwyllys cryptoerror(LOG_STDERR, 30899ebb4caSwyllys gettext("Unable to change passphrase.")); 30999ebb4caSwyllys return (PK_ERR_SYSTEM); 31099ebb4caSwyllys } else { 3117711facfSdinak (void) fprintf(stdout, gettext("Passphrase changed.\n")); 31299ebb4caSwyllys } 3137711facfSdinak return (0); 3147c478bd9Sstevel@tonic-gate } 315