xref: /titanic_44/usr/src/cmd/cmd-crypto/pktool/setpin.c (revision 49e212991a3065f7e499a4b29ae8d8eaf33f3135)
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 /*
237711facfSdinak  * 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,
327711facfSdinak  * finds the soft token, prompt the user for the old PIN (if
337711facfSdinak  * 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>
387711facfSdinak #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 /*
457711facfSdinak  * 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 {
51*49e21299Sdinak 	int		opt;
52*49e21299Sdinak 	extern int	optind_av;
53*49e21299Sdinak 	extern char	*optarg_av;
54*49e21299Sdinak 	char		*token_spec = NULL;
557c478bd9Sstevel@tonic-gate 	char		*token_name = NULL;
567c478bd9Sstevel@tonic-gate 	char		*manuf_id = NULL;
577c478bd9Sstevel@tonic-gate 	char		*serial_no = NULL;
587c478bd9Sstevel@tonic-gate 	CK_SLOT_ID		slot_id;
597c478bd9Sstevel@tonic-gate 	CK_FLAGS		pin_state;
607711facfSdinak 	CK_SESSION_HANDLE	sess;
617711facfSdinak 	CK_UTF8CHAR_PTR		old_pin = NULL, new_pin = NULL;
627711facfSdinak 	CK_ULONG		old_pinlen = 0, new_pinlen = 0;
637711facfSdinak 	CK_RV			rv = CKR_OK;
647711facfSdinak 	char		full_name[FULL_NAME_LEN];
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate 	cryptodebug("inside pk_setpin");
677c478bd9Sstevel@tonic-gate 
68*49e21299Sdinak 	/* Parse command line options.  Do NOT i18n/l10n. */
69*49e21299Sdinak 	while ((opt = getopt_av(argc, argv, "T:(token)")) != EOF) {
70*49e21299Sdinak 		switch (opt) {
71*49e21299Sdinak 		case 'T':	/* token specifier */
72*49e21299Sdinak 			if (token_spec)
73*49e21299Sdinak 				return (PK_ERR_USAGE);
74*49e21299Sdinak 			token_spec = optarg_av;
75*49e21299Sdinak 			break;
76*49e21299Sdinak 		default:
77*49e21299Sdinak 			return (PK_ERR_USAGE);
78*49e21299Sdinak 			break;
79*49e21299Sdinak 		}
80*49e21299Sdinak 	}
81*49e21299Sdinak 
82*49e21299Sdinak 	/* If nothing is specified, default is to use softtoken. */
83*49e21299Sdinak 	if (token_spec == NULL) {
84*49e21299Sdinak 		token_name = SOFT_TOKEN_LABEL;
85*49e21299Sdinak 		manuf_id = SOFT_MANUFACTURER_ID;
86*49e21299Sdinak 		serial_no = SOFT_TOKEN_SERIAL;
87*49e21299Sdinak 	} else {
88*49e21299Sdinak 		/*
89*49e21299Sdinak 		 * Parse token specifier into token_name, manuf_id, serial_no.
90*49e21299Sdinak 		 * Token_name is required; manuf_id and serial_no are optional.
91*49e21299Sdinak 		 */
92*49e21299Sdinak 		if (parse_token_spec(token_spec, &token_name, &manuf_id,
93*49e21299Sdinak 		    &serial_no) < 0)
94*49e21299Sdinak 			return (PK_ERR_USAGE);
95*49e21299Sdinak 	}
967711facfSdinak 
977711facfSdinak 	/* No additional args allowed. */
98*49e21299Sdinak 	argc -= optind_av;
99*49e21299Sdinak 	argv += optind_av;
1007711facfSdinak 	if (argc != 0)
1017711facfSdinak 		return (PK_ERR_USAGE);
1027711facfSdinak 	/* Done parsing command line options. */
1037711facfSdinak 
1047711facfSdinak 	full_token_name(token_name, manuf_id, serial_no, full_name);
1057c478bd9Sstevel@tonic-gate 
1067711facfSdinak 	/* Find the slot with token. */
1077711facfSdinak 	if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
1087711facfSdinak 	    &pin_state)) != CKR_OK) {
1097711facfSdinak 		cryptoerror(LOG_STDERR,
1107711facfSdinak 		    gettext("Unable to find token %s (%s)."), full_name,
1117711facfSdinak 		    pkcs11_strerror(rv));
1127711facfSdinak 		final_pk11(NULL);
1137711facfSdinak 		return (PK_ERR_PK11);
1147c478bd9Sstevel@tonic-gate 	}
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	/*
1177711facfSdinak 	 * If the token is the softtoken, check if the token flags show the
1187711facfSdinak 	 * PIN has not been set yet.  If not then set the old PIN to the
1197711facfSdinak 	 * default "changeme".  Otherwise, let user type in the correct old
1207711facfSdinak 	 * PIN to unlock token.
1217c478bd9Sstevel@tonic-gate 	 */
1227711facfSdinak 	if (pin_state == CKF_USER_PIN_TO_BE_CHANGED &&
1237711facfSdinak 	    strcmp(token_name, SOFT_TOKEN_LABEL) == 0) {
1247711facfSdinak 		cryptodebug("pin_state: first time passphrase is being set");
1257711facfSdinak 		if ((old_pin = (CK_UTF8CHAR_PTR) strdup(SOFT_DEFAULT_PIN)) ==
1267711facfSdinak 		    NULL) {
1277711facfSdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
1287711facfSdinak 			final_pk11(NULL);
1297711facfSdinak 			return (PK_ERR_PK11);
1307711facfSdinak 		}
1317711facfSdinak 		old_pinlen = strlen(SOFT_DEFAULT_PIN);
1327711facfSdinak 	} else {
1337711facfSdinak 		cryptodebug("pin_state: changing an existing pin ");
1347711facfSdinak 		if ((rv = get_pin(gettext("Enter token passphrase:"), NULL,
1357711facfSdinak 		    &old_pin, &old_pinlen)) != CKR_OK) {
1367711facfSdinak 			cryptoerror(LOG_STDERR,
1377711facfSdinak 			    gettext("Unable to get token passphrase (%s)."),
1387711facfSdinak 			    pkcs11_strerror(rv));
1397711facfSdinak 			final_pk11(NULL);
1407711facfSdinak 			return (PK_ERR_PK11);
1417711facfSdinak 		}
1427c478bd9Sstevel@tonic-gate 	}
1437c478bd9Sstevel@tonic-gate 
1447711facfSdinak 	/* Get the user's new PIN. */
1457711facfSdinak 	if ((rv = get_pin(gettext("Create new passphrase:"), gettext(
1467711facfSdinak 	    "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) {
1477711facfSdinak 		if (rv == CKR_PIN_INCORRECT)
1487711facfSdinak 			cryptoerror(LOG_STDERR, gettext(
1497711facfSdinak 			    "Passphrases do not match."));
1507711facfSdinak 		else
1517711facfSdinak 			cryptoerror(LOG_STDERR, gettext(
1527711facfSdinak 			    "Unable to get and confirm new passphrase (%s)."),
1537711facfSdinak 			    pkcs11_strerror(rv));
1547711facfSdinak 		free(old_pin);
1557711facfSdinak 		final_pk11(NULL);
1567711facfSdinak 		return (PK_ERR_PK11);
1577c478bd9Sstevel@tonic-gate 	}
1587c478bd9Sstevel@tonic-gate 
1597711facfSdinak 	/* Open a R/W session to the token to change the PIN. */
1607711facfSdinak 	if ((rv = open_sess(slot_id, CKF_RW_SESSION, &sess)) != CKR_OK) {
1617711facfSdinak 		cryptoerror(LOG_STDERR,
1627711facfSdinak 		    gettext("Unable to open token session (%s)."),
1637711facfSdinak 		    pkcs11_strerror(rv));
1647711facfSdinak 		free(old_pin);
1657711facfSdinak 		final_pk11(NULL);
1667711facfSdinak 		return (PK_ERR_PK11);
1677711facfSdinak 	}
1687711facfSdinak 
1697711facfSdinak 	/* Change the PIN if possible. */
1707711facfSdinak 	cryptodebug("calling C_SetPIN");
1717711facfSdinak 	rv = C_SetPIN(sess, old_pin, old_pinlen, new_pin, new_pinlen);
1727711facfSdinak 
1737711facfSdinak 	/* Clean up. */
1747711facfSdinak 	free(old_pin);
1757711facfSdinak 	free(new_pin);
1767711facfSdinak 	quick_finish(sess);
1777711facfSdinak 
1787711facfSdinak 	if (rv != CKR_OK) {
1797711facfSdinak 		if (rv == CKR_PIN_INCORRECT)
1807711facfSdinak 			cryptoerror(LOG_STDERR,
1817711facfSdinak 			    gettext("Incorrect passphrase."));
1827711facfSdinak 		else
1837711facfSdinak 			cryptoerror(LOG_STDERR,
1847711facfSdinak 			    gettext("Unable to change passphrase (%s)."),
1857711facfSdinak 			    pkcs11_strerror(rv));
1867711facfSdinak 		return (PK_ERR_PK11);
1877711facfSdinak 	}
1887711facfSdinak 
1897711facfSdinak 	(void) fprintf(stdout, gettext("Passphrase changed.\n"));
1907711facfSdinak 	return (0);
1917c478bd9Sstevel@tonic-gate }
192