1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * This file implements the setpin operation for this tool. 31 * The basic flow of the process is to load the PKCS#11 module, 32 * finds the soft token, log into it, prompt the user for the 33 * new PIN, change the token's PIN, and log out. 34 */ 35 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <cryptoutil.h> 40 #include <security/cryptoki.h> 41 #include "common.h" 42 43 static int 44 set_token_pin(CK_SESSION_HANDLE hdl, CK_UTF8CHAR_PTR oldpin, CK_ULONG oldpinlen) 45 { 46 CK_UTF8CHAR_PTR pin1, pin2; 47 int len1, len2; 48 int rv; 49 50 cryptodebug("inside set_token_pin"); 51 52 if ((len1 = get_password(gettext("Enter new PIN:"), 53 (char **)&pin1)) < 0) 54 return (PK_ERR_NEWPIN); 55 56 if ((len2 = get_password(gettext("Re-enter new PIN:"), 57 (char **)&pin2)) < 0) { 58 free(pin1); 59 return (PK_ERR_PINCONFIRM); 60 } 61 62 /* NOTE: Do not use strcmp on pin1 and pin2; they are UTF strings */ 63 if (len1 != len2 || memcmp(pin1, pin2, len1) != 0) { 64 free(pin1); 65 free(pin2); 66 return (PK_ERR_PINMATCH); 67 } 68 69 if ((rv = C_SetPIN(hdl, oldpin, oldpinlen, pin1, (CK_ULONG)len1)) 70 != CKR_OK) { 71 pk11_errno = rv; 72 free(pin1); 73 free(pin2); 74 return (PK_ERR_PK11SETPIN); 75 } 76 77 free(pin1); 78 free(pin2); 79 return (PK_ERR_NONE); 80 } 81 82 /* 83 * This is the main entry point in this module. It controls the process 84 * by which the token's PIN is changed. It relies on set_token_pin() to 85 * handle the extra work of prompting and confirming the new PIN. 86 */ 87 int 88 pk_setpin(int argc, char *argv[]) 89 /* ARGSUSED */ 90 { 91 char *token_name = NULL; 92 char *manuf_id = NULL; 93 char *serial_no = NULL; 94 CK_SLOT_ID slot_id; 95 CK_FLAGS pin_state; 96 CK_SESSION_HANDLE hdl; 97 CK_UTF8CHAR_PTR pin; 98 int pinlen; 99 int rv; 100 101 cryptodebug("inside pk_setpin"); 102 103 /* 104 * Token_name, manuf_id, and serial_no are all optional. 105 * If unspecified, token_name must have a default value 106 * at least. 107 */ 108 token_name = SOFT_TOKEN_LABEL; 109 manuf_id = SOFT_MANUFACTURER_ID; 110 111 /* No additional args allowed. */ 112 if (argc != 1) 113 return (PK_ERR_USAGE); 114 /* Done parsing command line options. */ 115 116 /* Initialize PKCS11, find the slot with token. */ 117 if ((rv = init_pk11()) != PK_ERR_NONE) 118 return (rv); 119 if ((rv = find_token_slot(token_name, manuf_id, serial_no, 120 &slot_id, &pin_state)) != PK_ERR_NONE) 121 return (rv); 122 123 /* Check if the token flags show the PIN has not be set yet. */ 124 if (pin_state == CKF_USER_PIN_TO_BE_CHANGED) { 125 cryptodebug("pin_state: first time pin is being set"); 126 if ((pin = (CK_UTF8CHAR_PTR)strdup(SOFT_DEFAULT_PIN)) == NULL) 127 return (PK_ERR_NOMEMORY); 128 pinlen = strlen(SOFT_DEFAULT_PIN); 129 } else { 130 cryptodebug("pin_state: changing an existing pin "); 131 /* Have user unlock token with correct password */ 132 if ((pinlen = get_password(gettext("Enter token PIN:"), 133 (char **)&pin)) < 0) 134 return (PK_ERR_PASSPHRASE); 135 } 136 137 /* 138 * Log into the token. If login fails with an uninitialized PIN, 139 * it means this is the first time the token has been used. 140 * Or if the login is successful, but all subsequent calls to 141 * any function return with an expired PIN, then this is the 142 * first time the token is used. In either case, use the 143 * passphrase "changeme" as the initial PIN. 144 */ 145 if ((rv = login_token(slot_id, pin, (CK_ULONG)pinlen, &hdl)) 146 != PK_ERR_NONE) { 147 free(pin); 148 return (rv); 149 } 150 151 /* Set the pin for the PKCS11 token. */ 152 if ((rv = set_token_pin(hdl, pin, (CK_ULONG)pinlen)) != PK_ERR_NONE) { 153 free(pin); 154 logout_token(hdl); 155 return (rv); 156 } 157 158 free(pin); 159 logout_token(hdl); 160 return (PK_ERR_NONE); 161 } 162