xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/setpin.c (revision 17:003a85e6a25c)
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
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
23*17Sdinak  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * This file implements the setpin operation for this tool.
310Sstevel@tonic-gate  * The basic flow of the process is to load the PKCS#11 module,
32*17Sdinak  * finds the soft token, prompt the user for the old PIN (if
33*17Sdinak  * any) and the new PIN, change the token's PIN, and clean up.
340Sstevel@tonic-gate  */
350Sstevel@tonic-gate 
360Sstevel@tonic-gate #include <stdio.h>
370Sstevel@tonic-gate #include <stdlib.h>
38*17Sdinak #include <errno.h>
390Sstevel@tonic-gate #include <string.h>
400Sstevel@tonic-gate #include <cryptoutil.h>
410Sstevel@tonic-gate #include <security/cryptoki.h>
420Sstevel@tonic-gate #include "common.h"
430Sstevel@tonic-gate 
440Sstevel@tonic-gate /*
45*17Sdinak  * Changes the token's PIN.
460Sstevel@tonic-gate  */
470Sstevel@tonic-gate int
480Sstevel@tonic-gate pk_setpin(int argc, char *argv[])
490Sstevel@tonic-gate /* ARGSUSED */
500Sstevel@tonic-gate {
510Sstevel@tonic-gate 	char		*token_name = NULL;
520Sstevel@tonic-gate 	char		*manuf_id = NULL;
530Sstevel@tonic-gate 	char		*serial_no = NULL;
540Sstevel@tonic-gate 	CK_SLOT_ID		slot_id;
550Sstevel@tonic-gate 	CK_FLAGS		pin_state;
56*17Sdinak 	CK_SESSION_HANDLE	sess;
57*17Sdinak 	CK_UTF8CHAR_PTR		old_pin = NULL, new_pin = NULL;
58*17Sdinak 	CK_ULONG		old_pinlen = 0, new_pinlen = 0;
59*17Sdinak 	CK_RV			rv = CKR_OK;
60*17Sdinak 	char		full_name[FULL_NAME_LEN];
610Sstevel@tonic-gate 
620Sstevel@tonic-gate 	cryptodebug("inside pk_setpin");
630Sstevel@tonic-gate 
64*17Sdinak 	/* Get rid of subcommand word "setpin". */
65*17Sdinak 	argc--;
66*17Sdinak 	argv++;
67*17Sdinak 
68*17Sdinak 	/* No additional args allowed. */
69*17Sdinak 	if (argc != 0)
70*17Sdinak 		return (PK_ERR_USAGE);
71*17Sdinak 	/* Done parsing command line options. */
72*17Sdinak 
730Sstevel@tonic-gate 	/*
740Sstevel@tonic-gate 	 * Token_name, manuf_id, and serial_no are all optional.
750Sstevel@tonic-gate 	 * If unspecified, token_name must have a default value
76*17Sdinak 	 * at least, so set it to the default softtoken value.
770Sstevel@tonic-gate 	 */
78*17Sdinak 	if (token_name == NULL)
79*17Sdinak 		token_name = SOFT_TOKEN_LABEL;
80*17Sdinak 	if (manuf_id == NULL)
81*17Sdinak 		manuf_id = SOFT_MANUFACTURER_ID;
82*17Sdinak 	if (serial_no == NULL)
83*17Sdinak 		serial_no = SOFT_TOKEN_SERIAL;
84*17Sdinak 	full_token_name(token_name, manuf_id, serial_no, full_name);
850Sstevel@tonic-gate 
86*17Sdinak 	/* Find the slot with token. */
87*17Sdinak 	if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
88*17Sdinak 	    &pin_state)) != CKR_OK) {
89*17Sdinak 		cryptoerror(LOG_STDERR,
90*17Sdinak 		    gettext("Unable to find token %s (%s)."), full_name,
91*17Sdinak 		    pkcs11_strerror(rv));
92*17Sdinak 		final_pk11(NULL);
93*17Sdinak 		return (PK_ERR_PK11);
940Sstevel@tonic-gate 	}
950Sstevel@tonic-gate 
960Sstevel@tonic-gate 	/*
97*17Sdinak 	 * If the token is the softtoken, check if the token flags show the
98*17Sdinak 	 * PIN has not been set yet.  If not then set the old PIN to the
99*17Sdinak 	 * default "changeme".  Otherwise, let user type in the correct old
100*17Sdinak 	 * PIN to unlock token.
1010Sstevel@tonic-gate 	 */
102*17Sdinak 	if (pin_state == CKF_USER_PIN_TO_BE_CHANGED &&
103*17Sdinak 	    strcmp(token_name, SOFT_TOKEN_LABEL) == 0) {
104*17Sdinak 		cryptodebug("pin_state: first time passphrase is being set");
105*17Sdinak 		if ((old_pin = (CK_UTF8CHAR_PTR) strdup(SOFT_DEFAULT_PIN)) ==
106*17Sdinak 		    NULL) {
107*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
108*17Sdinak 			final_pk11(NULL);
109*17Sdinak 			return (PK_ERR_PK11);
110*17Sdinak 		}
111*17Sdinak 		old_pinlen = strlen(SOFT_DEFAULT_PIN);
112*17Sdinak 	} else {
113*17Sdinak 		cryptodebug("pin_state: changing an existing pin ");
114*17Sdinak 		if ((rv = get_pin(gettext("Enter token passphrase:"), NULL,
115*17Sdinak 		    &old_pin, &old_pinlen)) != CKR_OK) {
116*17Sdinak 			cryptoerror(LOG_STDERR,
117*17Sdinak 			    gettext("Unable to get token passphrase (%s)."),
118*17Sdinak 			    pkcs11_strerror(rv));
119*17Sdinak 			final_pk11(NULL);
120*17Sdinak 			return (PK_ERR_PK11);
121*17Sdinak 		}
1220Sstevel@tonic-gate 	}
1230Sstevel@tonic-gate 
124*17Sdinak 	/* Get the user's new PIN. */
125*17Sdinak 	if ((rv = get_pin(gettext("Create new passphrase:"), gettext(
126*17Sdinak 	    "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) {
127*17Sdinak 		if (rv == CKR_PIN_INCORRECT)
128*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
129*17Sdinak 			    "Passphrases do not match."));
130*17Sdinak 		else
131*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
132*17Sdinak 			    "Unable to get and confirm new passphrase (%s)."),
133*17Sdinak 			    pkcs11_strerror(rv));
134*17Sdinak 		free(old_pin);
135*17Sdinak 		final_pk11(NULL);
136*17Sdinak 		return (PK_ERR_PK11);
1370Sstevel@tonic-gate 	}
1380Sstevel@tonic-gate 
139*17Sdinak 	/* Open a R/W session to the token to change the PIN. */
140*17Sdinak 	if ((rv = open_sess(slot_id, CKF_RW_SESSION, &sess)) != CKR_OK) {
141*17Sdinak 		cryptoerror(LOG_STDERR,
142*17Sdinak 		    gettext("Unable to open token session (%s)."),
143*17Sdinak 		    pkcs11_strerror(rv));
144*17Sdinak 		free(old_pin);
145*17Sdinak 		final_pk11(NULL);
146*17Sdinak 		return (PK_ERR_PK11);
147*17Sdinak 	}
148*17Sdinak 
149*17Sdinak 	/* Change the PIN if possible. */
150*17Sdinak 	cryptodebug("calling C_SetPIN");
151*17Sdinak 	rv = C_SetPIN(sess, old_pin, old_pinlen, new_pin, new_pinlen);
152*17Sdinak 
153*17Sdinak 	/* Clean up. */
154*17Sdinak 	free(old_pin);
155*17Sdinak 	free(new_pin);
156*17Sdinak 	quick_finish(sess);
157*17Sdinak 
158*17Sdinak 	if (rv != CKR_OK) {
159*17Sdinak 		if (rv == CKR_PIN_INCORRECT)
160*17Sdinak 			cryptoerror(LOG_STDERR,
161*17Sdinak 			    gettext("Incorrect passphrase."));
162*17Sdinak 		else
163*17Sdinak 			cryptoerror(LOG_STDERR,
164*17Sdinak 			    gettext("Unable to change passphrase (%s)."),
165*17Sdinak 			    pkcs11_strerror(rv));
166*17Sdinak 		return (PK_ERR_PK11);
167*17Sdinak 	}
168*17Sdinak 
169*17Sdinak 	(void) fprintf(stdout, gettext("Passphrase changed.\n"));
170*17Sdinak 	return (0);
1710Sstevel@tonic-gate }
172