xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/setpin.c (revision 864:75df3e9f93de)
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 /*
2317Sdinak  * 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,
3217Sdinak  * finds the soft token, prompt the user for the old PIN (if
3317Sdinak  * 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>
3817Sdinak #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 /*
4517Sdinak  * 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 {
51*864Sdinak 	int		opt;
52*864Sdinak 	extern int	optind_av;
53*864Sdinak 	extern char	*optarg_av;
54*864Sdinak 	char		*token_spec = NULL;
550Sstevel@tonic-gate 	char		*token_name = NULL;
560Sstevel@tonic-gate 	char		*manuf_id = NULL;
570Sstevel@tonic-gate 	char		*serial_no = NULL;
580Sstevel@tonic-gate 	CK_SLOT_ID		slot_id;
590Sstevel@tonic-gate 	CK_FLAGS		pin_state;
6017Sdinak 	CK_SESSION_HANDLE	sess;
6117Sdinak 	CK_UTF8CHAR_PTR		old_pin = NULL, new_pin = NULL;
6217Sdinak 	CK_ULONG		old_pinlen = 0, new_pinlen = 0;
6317Sdinak 	CK_RV			rv = CKR_OK;
6417Sdinak 	char		full_name[FULL_NAME_LEN];
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 	cryptodebug("inside pk_setpin");
670Sstevel@tonic-gate 
68*864Sdinak 	/* Parse command line options.  Do NOT i18n/l10n. */
69*864Sdinak 	while ((opt = getopt_av(argc, argv, "T:(token)")) != EOF) {
70*864Sdinak 		switch (opt) {
71*864Sdinak 		case 'T':	/* token specifier */
72*864Sdinak 			if (token_spec)
73*864Sdinak 				return (PK_ERR_USAGE);
74*864Sdinak 			token_spec = optarg_av;
75*864Sdinak 			break;
76*864Sdinak 		default:
77*864Sdinak 			return (PK_ERR_USAGE);
78*864Sdinak 			break;
79*864Sdinak 		}
80*864Sdinak 	}
81*864Sdinak 
82*864Sdinak 	/* If nothing is specified, default is to use softtoken. */
83*864Sdinak 	if (token_spec == NULL) {
84*864Sdinak 		token_name = SOFT_TOKEN_LABEL;
85*864Sdinak 		manuf_id = SOFT_MANUFACTURER_ID;
86*864Sdinak 		serial_no = SOFT_TOKEN_SERIAL;
87*864Sdinak 	} else {
88*864Sdinak 		/*
89*864Sdinak 		 * Parse token specifier into token_name, manuf_id, serial_no.
90*864Sdinak 		 * Token_name is required; manuf_id and serial_no are optional.
91*864Sdinak 		 */
92*864Sdinak 		if (parse_token_spec(token_spec, &token_name, &manuf_id,
93*864Sdinak 		    &serial_no) < 0)
94*864Sdinak 			return (PK_ERR_USAGE);
95*864Sdinak 	}
9617Sdinak 
9717Sdinak 	/* No additional args allowed. */
98*864Sdinak 	argc -= optind_av;
99*864Sdinak 	argv += optind_av;
10017Sdinak 	if (argc != 0)
10117Sdinak 		return (PK_ERR_USAGE);
10217Sdinak 	/* Done parsing command line options. */
10317Sdinak 
10417Sdinak 	full_token_name(token_name, manuf_id, serial_no, full_name);
1050Sstevel@tonic-gate 
10617Sdinak 	/* Find the slot with token. */
10717Sdinak 	if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
10817Sdinak 	    &pin_state)) != CKR_OK) {
10917Sdinak 		cryptoerror(LOG_STDERR,
11017Sdinak 		    gettext("Unable to find token %s (%s)."), full_name,
11117Sdinak 		    pkcs11_strerror(rv));
11217Sdinak 		final_pk11(NULL);
11317Sdinak 		return (PK_ERR_PK11);
1140Sstevel@tonic-gate 	}
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate 	/*
11717Sdinak 	 * If the token is the softtoken, check if the token flags show the
11817Sdinak 	 * PIN has not been set yet.  If not then set the old PIN to the
11917Sdinak 	 * default "changeme".  Otherwise, let user type in the correct old
12017Sdinak 	 * PIN to unlock token.
1210Sstevel@tonic-gate 	 */
12217Sdinak 	if (pin_state == CKF_USER_PIN_TO_BE_CHANGED &&
12317Sdinak 	    strcmp(token_name, SOFT_TOKEN_LABEL) == 0) {
12417Sdinak 		cryptodebug("pin_state: first time passphrase is being set");
12517Sdinak 		if ((old_pin = (CK_UTF8CHAR_PTR) strdup(SOFT_DEFAULT_PIN)) ==
12617Sdinak 		    NULL) {
12717Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
12817Sdinak 			final_pk11(NULL);
12917Sdinak 			return (PK_ERR_PK11);
13017Sdinak 		}
13117Sdinak 		old_pinlen = strlen(SOFT_DEFAULT_PIN);
13217Sdinak 	} else {
13317Sdinak 		cryptodebug("pin_state: changing an existing pin ");
13417Sdinak 		if ((rv = get_pin(gettext("Enter token passphrase:"), NULL,
13517Sdinak 		    &old_pin, &old_pinlen)) != CKR_OK) {
13617Sdinak 			cryptoerror(LOG_STDERR,
13717Sdinak 			    gettext("Unable to get token passphrase (%s)."),
13817Sdinak 			    pkcs11_strerror(rv));
13917Sdinak 			final_pk11(NULL);
14017Sdinak 			return (PK_ERR_PK11);
14117Sdinak 		}
1420Sstevel@tonic-gate 	}
1430Sstevel@tonic-gate 
14417Sdinak 	/* Get the user's new PIN. */
14517Sdinak 	if ((rv = get_pin(gettext("Create new passphrase:"), gettext(
14617Sdinak 	    "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) {
14717Sdinak 		if (rv == CKR_PIN_INCORRECT)
14817Sdinak 			cryptoerror(LOG_STDERR, gettext(
14917Sdinak 			    "Passphrases do not match."));
15017Sdinak 		else
15117Sdinak 			cryptoerror(LOG_STDERR, gettext(
15217Sdinak 			    "Unable to get and confirm new passphrase (%s)."),
15317Sdinak 			    pkcs11_strerror(rv));
15417Sdinak 		free(old_pin);
15517Sdinak 		final_pk11(NULL);
15617Sdinak 		return (PK_ERR_PK11);
1570Sstevel@tonic-gate 	}
1580Sstevel@tonic-gate 
15917Sdinak 	/* Open a R/W session to the token to change the PIN. */
16017Sdinak 	if ((rv = open_sess(slot_id, CKF_RW_SESSION, &sess)) != CKR_OK) {
16117Sdinak 		cryptoerror(LOG_STDERR,
16217Sdinak 		    gettext("Unable to open token session (%s)."),
16317Sdinak 		    pkcs11_strerror(rv));
16417Sdinak 		free(old_pin);
16517Sdinak 		final_pk11(NULL);
16617Sdinak 		return (PK_ERR_PK11);
16717Sdinak 	}
16817Sdinak 
16917Sdinak 	/* Change the PIN if possible. */
17017Sdinak 	cryptodebug("calling C_SetPIN");
17117Sdinak 	rv = C_SetPIN(sess, old_pin, old_pinlen, new_pin, new_pinlen);
17217Sdinak 
17317Sdinak 	/* Clean up. */
17417Sdinak 	free(old_pin);
17517Sdinak 	free(new_pin);
17617Sdinak 	quick_finish(sess);
17717Sdinak 
17817Sdinak 	if (rv != CKR_OK) {
17917Sdinak 		if (rv == CKR_PIN_INCORRECT)
18017Sdinak 			cryptoerror(LOG_STDERR,
18117Sdinak 			    gettext("Incorrect passphrase."));
18217Sdinak 		else
18317Sdinak 			cryptoerror(LOG_STDERR,
18417Sdinak 			    gettext("Unable to change passphrase (%s)."),
18517Sdinak 			    pkcs11_strerror(rv));
18617Sdinak 		return (PK_ERR_PK11);
18717Sdinak 	}
18817Sdinak 
18917Sdinak 	(void) fprintf(stdout, gettext("Passphrase changed.\n"));
19017Sdinak 	return (0);
1910Sstevel@tonic-gate }
192