xref: /titanic_50/usr/src/cmd/cmd-crypto/pktool/setpin.c (revision 7711facfe58561dd91d6ece0f5f41150c3956c83)
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
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23*7711facfSdinak  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * This file implements the setpin operation for this tool.
317c478bd9Sstevel@tonic-gate  * The basic flow of the process is to load the PKCS#11 module,
32*7711facfSdinak  * finds the soft token, prompt the user for the old PIN (if
33*7711facfSdinak  * any) and the new PIN, change the token's PIN, and clean up.
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #include <stdio.h>
377c478bd9Sstevel@tonic-gate #include <stdlib.h>
38*7711facfSdinak #include <errno.h>
397c478bd9Sstevel@tonic-gate #include <string.h>
407c478bd9Sstevel@tonic-gate #include <cryptoutil.h>
417c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
427c478bd9Sstevel@tonic-gate #include "common.h"
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /*
45*7711facfSdinak  * Changes the token's PIN.
467c478bd9Sstevel@tonic-gate  */
477c478bd9Sstevel@tonic-gate int
487c478bd9Sstevel@tonic-gate pk_setpin(int argc, char *argv[])
497c478bd9Sstevel@tonic-gate /* ARGSUSED */
507c478bd9Sstevel@tonic-gate {
517c478bd9Sstevel@tonic-gate 	char		*token_name = NULL;
527c478bd9Sstevel@tonic-gate 	char		*manuf_id = NULL;
537c478bd9Sstevel@tonic-gate 	char		*serial_no = NULL;
547c478bd9Sstevel@tonic-gate 	CK_SLOT_ID		slot_id;
557c478bd9Sstevel@tonic-gate 	CK_FLAGS		pin_state;
56*7711facfSdinak 	CK_SESSION_HANDLE	sess;
57*7711facfSdinak 	CK_UTF8CHAR_PTR		old_pin = NULL, new_pin = NULL;
58*7711facfSdinak 	CK_ULONG		old_pinlen = 0, new_pinlen = 0;
59*7711facfSdinak 	CK_RV			rv = CKR_OK;
60*7711facfSdinak 	char		full_name[FULL_NAME_LEN];
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate 	cryptodebug("inside pk_setpin");
637c478bd9Sstevel@tonic-gate 
64*7711facfSdinak 	/* Get rid of subcommand word "setpin". */
65*7711facfSdinak 	argc--;
66*7711facfSdinak 	argv++;
67*7711facfSdinak 
68*7711facfSdinak 	/* No additional args allowed. */
69*7711facfSdinak 	if (argc != 0)
70*7711facfSdinak 		return (PK_ERR_USAGE);
71*7711facfSdinak 	/* Done parsing command line options. */
72*7711facfSdinak 
737c478bd9Sstevel@tonic-gate 	/*
747c478bd9Sstevel@tonic-gate 	 * Token_name, manuf_id, and serial_no are all optional.
757c478bd9Sstevel@tonic-gate 	 * If unspecified, token_name must have a default value
76*7711facfSdinak 	 * at least, so set it to the default softtoken value.
777c478bd9Sstevel@tonic-gate 	 */
78*7711facfSdinak 	if (token_name == NULL)
797c478bd9Sstevel@tonic-gate 		token_name = SOFT_TOKEN_LABEL;
80*7711facfSdinak 	if (manuf_id == NULL)
817c478bd9Sstevel@tonic-gate 		manuf_id = SOFT_MANUFACTURER_ID;
82*7711facfSdinak 	if (serial_no == NULL)
83*7711facfSdinak 		serial_no = SOFT_TOKEN_SERIAL;
84*7711facfSdinak 	full_token_name(token_name, manuf_id, serial_no, full_name);
857c478bd9Sstevel@tonic-gate 
86*7711facfSdinak 	/* Find the slot with token. */
87*7711facfSdinak 	if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
88*7711facfSdinak 	    &pin_state)) != CKR_OK) {
89*7711facfSdinak 		cryptoerror(LOG_STDERR,
90*7711facfSdinak 		    gettext("Unable to find token %s (%s)."), full_name,
91*7711facfSdinak 		    pkcs11_strerror(rv));
92*7711facfSdinak 		final_pk11(NULL);
93*7711facfSdinak 		return (PK_ERR_PK11);
947c478bd9Sstevel@tonic-gate 	}
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	/*
97*7711facfSdinak 	 * If the token is the softtoken, check if the token flags show the
98*7711facfSdinak 	 * PIN has not been set yet.  If not then set the old PIN to the
99*7711facfSdinak 	 * default "changeme".  Otherwise, let user type in the correct old
100*7711facfSdinak 	 * PIN to unlock token.
1017c478bd9Sstevel@tonic-gate 	 */
102*7711facfSdinak 	if (pin_state == CKF_USER_PIN_TO_BE_CHANGED &&
103*7711facfSdinak 	    strcmp(token_name, SOFT_TOKEN_LABEL) == 0) {
104*7711facfSdinak 		cryptodebug("pin_state: first time passphrase is being set");
105*7711facfSdinak 		if ((old_pin = (CK_UTF8CHAR_PTR) strdup(SOFT_DEFAULT_PIN)) ==
106*7711facfSdinak 		    NULL) {
107*7711facfSdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
108*7711facfSdinak 			final_pk11(NULL);
109*7711facfSdinak 			return (PK_ERR_PK11);
110*7711facfSdinak 		}
111*7711facfSdinak 		old_pinlen = strlen(SOFT_DEFAULT_PIN);
112*7711facfSdinak 	} else {
113*7711facfSdinak 		cryptodebug("pin_state: changing an existing pin ");
114*7711facfSdinak 		if ((rv = get_pin(gettext("Enter token passphrase:"), NULL,
115*7711facfSdinak 		    &old_pin, &old_pinlen)) != CKR_OK) {
116*7711facfSdinak 			cryptoerror(LOG_STDERR,
117*7711facfSdinak 			    gettext("Unable to get token passphrase (%s)."),
118*7711facfSdinak 			    pkcs11_strerror(rv));
119*7711facfSdinak 			final_pk11(NULL);
120*7711facfSdinak 			return (PK_ERR_PK11);
121*7711facfSdinak 		}
1227c478bd9Sstevel@tonic-gate 	}
1237c478bd9Sstevel@tonic-gate 
124*7711facfSdinak 	/* Get the user's new PIN. */
125*7711facfSdinak 	if ((rv = get_pin(gettext("Create new passphrase:"), gettext(
126*7711facfSdinak 	    "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) {
127*7711facfSdinak 		if (rv == CKR_PIN_INCORRECT)
128*7711facfSdinak 			cryptoerror(LOG_STDERR, gettext(
129*7711facfSdinak 			    "Passphrases do not match."));
130*7711facfSdinak 		else
131*7711facfSdinak 			cryptoerror(LOG_STDERR, gettext(
132*7711facfSdinak 			    "Unable to get and confirm new passphrase (%s)."),
133*7711facfSdinak 			    pkcs11_strerror(rv));
134*7711facfSdinak 		free(old_pin);
135*7711facfSdinak 		final_pk11(NULL);
136*7711facfSdinak 		return (PK_ERR_PK11);
1377c478bd9Sstevel@tonic-gate 	}
1387c478bd9Sstevel@tonic-gate 
139*7711facfSdinak 	/* Open a R/W session to the token to change the PIN. */
140*7711facfSdinak 	if ((rv = open_sess(slot_id, CKF_RW_SESSION, &sess)) != CKR_OK) {
141*7711facfSdinak 		cryptoerror(LOG_STDERR,
142*7711facfSdinak 		    gettext("Unable to open token session (%s)."),
143*7711facfSdinak 		    pkcs11_strerror(rv));
144*7711facfSdinak 		free(old_pin);
145*7711facfSdinak 		final_pk11(NULL);
146*7711facfSdinak 		return (PK_ERR_PK11);
147*7711facfSdinak 	}
148*7711facfSdinak 
149*7711facfSdinak 	/* Change the PIN if possible. */
150*7711facfSdinak 	cryptodebug("calling C_SetPIN");
151*7711facfSdinak 	rv = C_SetPIN(sess, old_pin, old_pinlen, new_pin, new_pinlen);
152*7711facfSdinak 
153*7711facfSdinak 	/* Clean up. */
154*7711facfSdinak 	free(old_pin);
155*7711facfSdinak 	free(new_pin);
156*7711facfSdinak 	quick_finish(sess);
157*7711facfSdinak 
158*7711facfSdinak 	if (rv != CKR_OK) {
159*7711facfSdinak 		if (rv == CKR_PIN_INCORRECT)
160*7711facfSdinak 			cryptoerror(LOG_STDERR,
161*7711facfSdinak 			    gettext("Incorrect passphrase."));
162*7711facfSdinak 		else
163*7711facfSdinak 			cryptoerror(LOG_STDERR,
164*7711facfSdinak 			    gettext("Unable to change passphrase (%s)."),
165*7711facfSdinak 			    pkcs11_strerror(rv));
166*7711facfSdinak 		return (PK_ERR_PK11);
167*7711facfSdinak 	}
168*7711facfSdinak 
169*7711facfSdinak 	(void) fprintf(stdout, gettext("Passphrase changed.\n"));
170*7711facfSdinak 	return (0);
1717c478bd9Sstevel@tonic-gate }
172