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