xref: /titanic_44/usr/src/cmd/cmd-crypto/pktool/setpin.c (revision 99ebb4ca412cb0a19d77a3899a87c055b9c30fa8)
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(&params, 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, &params, &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(&params, 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, &params, &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