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