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*9126SWyllys.Ingersoll@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * This file implements the setpin operation for this tool.
280Sstevel@tonic-gate * The basic flow of the process is to load the PKCS#11 module,
2917Sdinak * finds the soft token, prompt the user for the old PIN (if
3017Sdinak * any) and the new PIN, change the token's PIN, and clean up.
310Sstevel@tonic-gate */
320Sstevel@tonic-gate
330Sstevel@tonic-gate #include <stdio.h>
340Sstevel@tonic-gate #include <stdlib.h>
3517Sdinak #include <errno.h>
360Sstevel@tonic-gate #include <string.h>
370Sstevel@tonic-gate #include <cryptoutil.h>
380Sstevel@tonic-gate #include <security/cryptoki.h>
390Sstevel@tonic-gate #include "common.h"
400Sstevel@tonic-gate
413089Swyllys static int
setpin_nss(KMF_HANDLE_T handle,char * token_spec,char * dir,char * prefix)423089Swyllys setpin_nss(KMF_HANDLE_T handle,
433089Swyllys char *token_spec, char *dir, char *prefix)
440Sstevel@tonic-gate {
453089Swyllys int rv = 0;
465051Swyllys KMF_CREDENTIAL oldcred = {NULL, 0};
475051Swyllys KMF_CREDENTIAL newpincred = {NULL, 0};
483089Swyllys CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL;
493089Swyllys CK_ULONG old_pinlen = 0, new_pinlen = 0;
505051Swyllys KMF_ATTRIBUTE setpinattrs[6];
515051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
525051Swyllys int numattrs = 0;
533089Swyllys
543089Swyllys rv = configure_nss(handle, dir, prefix);
553089Swyllys if (rv != KMF_OK)
563089Swyllys return (rv);
573089Swyllys
585051Swyllys kmf_set_attr_at_index(setpinattrs, numattrs, KMF_KEYSTORE_TYPE_ATTR,
595051Swyllys &kstype, sizeof (kstype));
605051Swyllys numattrs++;
615051Swyllys if (token_spec != NULL) {
625051Swyllys kmf_set_attr_at_index(setpinattrs, numattrs,
635051Swyllys KMF_TOKEN_LABEL_ATTR,
645051Swyllys token_spec, strlen(token_spec));
655051Swyllys numattrs++;
665051Swyllys }
673089Swyllys
683089Swyllys if ((rv = get_pin(gettext("Enter current token passphrase "
695051Swyllys "(<CR> if not set):"), NULL, &old_pin, &old_pinlen)) != CKR_OK) {
703089Swyllys cryptoerror(LOG_STDERR,
713089Swyllys gettext("Unable to get token passphrase."));
723089Swyllys return (PK_ERR_NSS);
733089Swyllys }
743089Swyllys /* Get the user's new PIN. */
753089Swyllys if ((rv = get_pin(gettext("Create new passphrase:"), gettext(
763089Swyllys "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) {
773089Swyllys if (rv == CKR_PIN_INCORRECT)
783089Swyllys cryptoerror(LOG_STDERR, gettext(
793089Swyllys "Passphrases do not match."));
803089Swyllys else
813089Swyllys cryptoerror(LOG_STDERR, gettext(
823089Swyllys "Unable to get and confirm new passphrase."));
833089Swyllys if (old_pin != NULL)
843089Swyllys free(old_pin);
853089Swyllys return (PK_ERR_NSS);
863089Swyllys }
873089Swyllys
885051Swyllys oldcred.cred = (char *)old_pin;
895051Swyllys oldcred.credlen = old_pinlen;
905051Swyllys
915051Swyllys kmf_set_attr_at_index(setpinattrs, numattrs, KMF_CREDENTIAL_ATTR,
925051Swyllys &oldcred, sizeof (oldcred));
935051Swyllys numattrs++;
943089Swyllys
953089Swyllys newpincred.cred = (char *)new_pin;
963089Swyllys newpincred.credlen = new_pinlen;
975051Swyllys kmf_set_attr_at_index(setpinattrs, numattrs, KMF_NEWPIN_ATTR,
985051Swyllys &newpincred, sizeof (newpincred));
995051Swyllys numattrs++;
1003089Swyllys
1015051Swyllys rv = kmf_set_token_pin(handle, numattrs, setpinattrs);
1023089Swyllys
1033089Swyllys if (new_pin)
1043089Swyllys free(new_pin);
1053089Swyllys if (old_pin)
1063089Swyllys free(old_pin);
1073089Swyllys
1083089Swyllys return (rv);
1093089Swyllys }
1103089Swyllys
1113089Swyllys static int
setpin_pkcs11(KMF_HANDLE_T handle,char * token_spec,boolean_t souser)112*9126SWyllys.Ingersoll@Sun.COM setpin_pkcs11(KMF_HANDLE_T handle, char *token_spec, boolean_t souser)
1133089Swyllys {
1140Sstevel@tonic-gate CK_SLOT_ID slot_id;
1150Sstevel@tonic-gate CK_FLAGS pin_state;
11617Sdinak CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL;
11717Sdinak CK_ULONG old_pinlen = 0, new_pinlen = 0;
11817Sdinak CK_RV rv = CKR_OK;
1193089Swyllys char *token_name = NULL;
1203089Swyllys CK_TOKEN_INFO token_info;
1215051Swyllys KMF_CREDENTIAL newpincred = {NULL, 0};
1225051Swyllys KMF_CREDENTIAL oldcred = {NULL, 0};
1235051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
1245051Swyllys KMF_ATTRIBUTE attrlist[6];
125*9126SWyllys.Ingersoll@Sun.COM CK_USER_TYPE user = CKU_USER;
1265051Swyllys int numattr = 0;
127864Sdinak
128864Sdinak /* If nothing is specified, default is to use softtoken. */
129864Sdinak if (token_spec == NULL) {
1303089Swyllys token_spec = SOFT_TOKEN_LABEL ":" SOFT_MANUFACTURER_ID;
131864Sdinak token_name = SOFT_TOKEN_LABEL;
132864Sdinak }
13317Sdinak
1345051Swyllys rv = kmf_pk11_token_lookup(NULL, token_spec, &slot_id);
1353089Swyllys if (rv == KMF_OK) {
1363089Swyllys /* find the pin state for the selected token */
1373089Swyllys if (C_GetTokenInfo(slot_id, &token_info) != CKR_OK)
1383089Swyllys return (PK_ERR_PK11);
1390Sstevel@tonic-gate
1403089Swyllys pin_state = token_info.flags & CKF_USER_PIN_TO_BE_CHANGED;
1413089Swyllys if (token_name == NULL)
1423089Swyllys token_name = (char *)token_info.label;
1430Sstevel@tonic-gate }
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate /*
14617Sdinak * If the token is the softtoken, check if the token flags show the
14717Sdinak * PIN has not been set yet. If not then set the old PIN to the
14817Sdinak * default "changeme". Otherwise, let user type in the correct old
14917Sdinak * PIN to unlock token.
1500Sstevel@tonic-gate */
15117Sdinak if (pin_state == CKF_USER_PIN_TO_BE_CHANGED &&
15217Sdinak strcmp(token_name, SOFT_TOKEN_LABEL) == 0) {
15317Sdinak if ((old_pin = (CK_UTF8CHAR_PTR) strdup(SOFT_DEFAULT_PIN)) ==
15417Sdinak NULL) {
15517Sdinak cryptoerror(LOG_STDERR, "%s.", strerror(errno));
15617Sdinak final_pk11(NULL);
15717Sdinak return (PK_ERR_PK11);
15817Sdinak }
15917Sdinak old_pinlen = strlen(SOFT_DEFAULT_PIN);
16017Sdinak } else {
16117Sdinak if ((rv = get_pin(gettext("Enter token passphrase:"), NULL,
16217Sdinak &old_pin, &old_pinlen)) != CKR_OK) {
16317Sdinak cryptoerror(LOG_STDERR,
16417Sdinak gettext("Unable to get token passphrase (%s)."),
16517Sdinak pkcs11_strerror(rv));
16617Sdinak final_pk11(NULL);
16717Sdinak return (PK_ERR_PK11);
16817Sdinak }
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate
17117Sdinak /* Get the user's new PIN. */
17217Sdinak if ((rv = get_pin(gettext("Create new passphrase:"), gettext(
17317Sdinak "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) {
17417Sdinak if (rv == CKR_PIN_INCORRECT)
17517Sdinak cryptoerror(LOG_STDERR, gettext(
17617Sdinak "Passphrases do not match."));
17717Sdinak else
17817Sdinak cryptoerror(LOG_STDERR, gettext(
17917Sdinak "Unable to get and confirm new passphrase (%s)."),
18017Sdinak pkcs11_strerror(rv));
18117Sdinak free(old_pin);
18217Sdinak final_pk11(NULL);
18317Sdinak return (PK_ERR_PK11);
1840Sstevel@tonic-gate }
1850Sstevel@tonic-gate
1865051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
1875051Swyllys &kstype, sizeof (kstype));
1885051Swyllys numattr++;
1895051Swyllys if (token_name != NULL) {
1905051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
1915051Swyllys token_name, strlen(token_name));
1925051Swyllys numattr++;
1935051Swyllys }
1945051Swyllys oldcred.cred = (char *)old_pin;
1955051Swyllys oldcred.credlen = old_pinlen;
1965051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
1975051Swyllys &oldcred, sizeof (oldcred));
1985051Swyllys numattr++;
1995051Swyllys
2005051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_SLOT_ID_ATTR,
2015051Swyllys &slot_id, sizeof (slot_id));
2025051Swyllys numattr++;
20317Sdinak
2043089Swyllys newpincred.cred = (char *)new_pin;
2053089Swyllys newpincred.credlen = new_pinlen;
2065051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_NEWPIN_ATTR,
2075051Swyllys &newpincred, sizeof (newpincred));
2085051Swyllys numattr++;
2093089Swyllys
210*9126SWyllys.Ingersoll@Sun.COM if (souser) {
211*9126SWyllys.Ingersoll@Sun.COM user = CKU_SO;
212*9126SWyllys.Ingersoll@Sun.COM kmf_set_attr_at_index(attrlist, numattr,
213*9126SWyllys.Ingersoll@Sun.COM KMF_PK11_USER_TYPE_ATTR,
214*9126SWyllys.Ingersoll@Sun.COM &user, sizeof (user));
215*9126SWyllys.Ingersoll@Sun.COM numattr++;
216*9126SWyllys.Ingersoll@Sun.COM }
217*9126SWyllys.Ingersoll@Sun.COM
2185051Swyllys rv = kmf_set_token_pin(handle, numattr, attrlist);
21917Sdinak
22017Sdinak /* Clean up. */
2213089Swyllys if (old_pin != NULL)
2223089Swyllys free(old_pin);
2233089Swyllys if (new_pin != NULL)
2243089Swyllys free(new_pin);
2253089Swyllys
2263089Swyllys return (rv);
2273089Swyllys }
2283089Swyllys
2293089Swyllys /*
2303089Swyllys * Changes the token's PIN.
2313089Swyllys */
2323089Swyllys int
pk_setpin(int argc,char * argv[])2333089Swyllys pk_setpin(int argc, char *argv[])
2343089Swyllys /* ARGSUSED */
2353089Swyllys {
2363089Swyllys int opt;
2373089Swyllys int rv;
2383089Swyllys extern int optind_av;
2393089Swyllys extern char *optarg_av;
2403089Swyllys char *token_spec = NULL;
2413089Swyllys char *dir = NULL;
2423089Swyllys char *prefix = NULL;
243*9126SWyllys.Ingersoll@Sun.COM char *utype = NULL;
2443089Swyllys KMF_HANDLE_T handle;
2453089Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
246*9126SWyllys.Ingersoll@Sun.COM boolean_t souser = 0;
24717Sdinak
2483089Swyllys /* Parse command line options. Do NOT i18n/l10n. */
2493089Swyllys while ((opt = getopt_av(argc, argv,
2503089Swyllys "T:(token)k:(keystore)d:(dir)"
251*9126SWyllys.Ingersoll@Sun.COM "p:(prefix)u:(usertype)")) != EOF) {
2523089Swyllys switch (opt) {
2533089Swyllys case 'k':
2543089Swyllys kstype = KS2Int(optarg_av);
2553089Swyllys if (kstype == 0)
2563089Swyllys return (PK_ERR_USAGE);
2573089Swyllys break;
2583089Swyllys case 'T': /* token specifier */
2593089Swyllys if (token_spec)
2603089Swyllys return (PK_ERR_USAGE);
2613089Swyllys token_spec = optarg_av;
2623089Swyllys break;
2633089Swyllys case 'd':
2643089Swyllys if (dir)
2653089Swyllys return (PK_ERR_USAGE);
2663089Swyllys dir = optarg_av;
2673089Swyllys break;
2683089Swyllys case 'p':
2693089Swyllys if (prefix)
2703089Swyllys return (PK_ERR_USAGE);
2713089Swyllys prefix = optarg_av;
2723089Swyllys break;
273*9126SWyllys.Ingersoll@Sun.COM case 'u':
274*9126SWyllys.Ingersoll@Sun.COM utype = optarg_av;
275*9126SWyllys.Ingersoll@Sun.COM break;
2763089Swyllys default:
2773089Swyllys return (PK_ERR_USAGE);
2783089Swyllys break;
2793089Swyllys }
28017Sdinak }
28117Sdinak
2823089Swyllys
2833089Swyllys /* No additional args allowed. */
2843089Swyllys argc -= optind_av;
2853089Swyllys argv += optind_av;
2863089Swyllys if (argc != 0)
2873089Swyllys return (PK_ERR_USAGE);
2883089Swyllys
2893089Swyllys /* Done parsing command line options. */
2903089Swyllys if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) {
2913089Swyllys token_spec = PK_DEFAULT_PK11TOKEN;
2923089Swyllys } else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) {
2933089Swyllys token_spec = DEFAULT_NSS_TOKEN;
2943089Swyllys }
2953089Swyllys
2965051Swyllys if ((rv = kmf_initialize(&handle, NULL, NULL)) != KMF_OK)
2973089Swyllys return (rv);
2983089Swyllys
299*9126SWyllys.Ingersoll@Sun.COM if (utype != NULL) {
300*9126SWyllys.Ingersoll@Sun.COM if (strcmp(utype, "so") == 0)
301*9126SWyllys.Ingersoll@Sun.COM souser = 1;
302*9126SWyllys.Ingersoll@Sun.COM else if (strcmp(utype, "user") == 0)
303*9126SWyllys.Ingersoll@Sun.COM souser = 0;
304*9126SWyllys.Ingersoll@Sun.COM else /* Wrong option string */
305*9126SWyllys.Ingersoll@Sun.COM return (PK_ERR_USAGE);
306*9126SWyllys.Ingersoll@Sun.COM }
307*9126SWyllys.Ingersoll@Sun.COM
3083089Swyllys switch (kstype) {
3093089Swyllys case KMF_KEYSTORE_PK11TOKEN:
310*9126SWyllys.Ingersoll@Sun.COM rv = setpin_pkcs11(handle, token_spec, souser);
3113089Swyllys break;
3123089Swyllys case KMF_KEYSTORE_NSS:
3133089Swyllys rv = setpin_nss(handle, token_spec, dir, prefix);
3143089Swyllys break;
3153089Swyllys default:
3163089Swyllys cryptoerror(LOG_STDERR,
3175051Swyllys gettext("incorrect keystore."));
3183089Swyllys return (PK_ERR_USAGE);
3193089Swyllys }
3203089Swyllys
3215051Swyllys (void) kmf_finalize(handle);
3223089Swyllys
3233089Swyllys if (rv == KMF_ERR_AUTH_FAILED) {
3243089Swyllys cryptoerror(LOG_STDERR,
3253089Swyllys gettext("Incorrect passphrase."));
3263089Swyllys return (PK_ERR_SYSTEM);
3273089Swyllys } else if (rv != CKR_OK) {
3283089Swyllys cryptoerror(LOG_STDERR,
3293089Swyllys gettext("Unable to change passphrase."));
3303089Swyllys return (PK_ERR_SYSTEM);
3313089Swyllys } else {
3323089Swyllys (void) fprintf(stdout, gettext("Passphrase changed.\n"));
3333089Swyllys }
33417Sdinak return (0);
3350Sstevel@tonic-gate }
336