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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * This file implements the setpin operation for this tool.
28 * The basic flow of the process is to load the PKCS#11 module,
29 * finds the soft token, prompt the user for the old PIN (if
30 * any) and the new PIN, change the token's PIN, and clean up.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <errno.h>
36 #include <string.h>
37 #include <cryptoutil.h>
38 #include <security/cryptoki.h>
39 #include "common.h"
40
41 static int
setpin_nss(KMF_HANDLE_T handle,char * token_spec,char * dir,char * prefix)42 setpin_nss(KMF_HANDLE_T handle,
43 char *token_spec, char *dir, char *prefix)
44 {
45 int rv = 0;
46 KMF_CREDENTIAL oldcred = {NULL, 0};
47 KMF_CREDENTIAL newpincred = {NULL, 0};
48 CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL;
49 CK_ULONG old_pinlen = 0, new_pinlen = 0;
50 KMF_ATTRIBUTE setpinattrs[6];
51 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
52 int numattrs = 0;
53
54 rv = configure_nss(handle, dir, prefix);
55 if (rv != KMF_OK)
56 return (rv);
57
58 kmf_set_attr_at_index(setpinattrs, numattrs, KMF_KEYSTORE_TYPE_ATTR,
59 &kstype, sizeof (kstype));
60 numattrs++;
61 if (token_spec != NULL) {
62 kmf_set_attr_at_index(setpinattrs, numattrs,
63 KMF_TOKEN_LABEL_ATTR,
64 token_spec, strlen(token_spec));
65 numattrs++;
66 }
67
68 if ((rv = get_pin(gettext("Enter current token passphrase "
69 "(<CR> if not set):"), NULL, &old_pin, &old_pinlen)) != CKR_OK) {
70 cryptoerror(LOG_STDERR,
71 gettext("Unable to get token passphrase."));
72 return (PK_ERR_NSS);
73 }
74 /* Get the user's new PIN. */
75 if ((rv = get_pin(gettext("Create new passphrase:"), gettext(
76 "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) {
77 if (rv == CKR_PIN_INCORRECT)
78 cryptoerror(LOG_STDERR, gettext(
79 "Passphrases do not match."));
80 else
81 cryptoerror(LOG_STDERR, gettext(
82 "Unable to get and confirm new passphrase."));
83 if (old_pin != NULL)
84 free(old_pin);
85 return (PK_ERR_NSS);
86 }
87
88 oldcred.cred = (char *)old_pin;
89 oldcred.credlen = old_pinlen;
90
91 kmf_set_attr_at_index(setpinattrs, numattrs, KMF_CREDENTIAL_ATTR,
92 &oldcred, sizeof (oldcred));
93 numattrs++;
94
95 newpincred.cred = (char *)new_pin;
96 newpincred.credlen = new_pinlen;
97 kmf_set_attr_at_index(setpinattrs, numattrs, KMF_NEWPIN_ATTR,
98 &newpincred, sizeof (newpincred));
99 numattrs++;
100
101 rv = kmf_set_token_pin(handle, numattrs, setpinattrs);
102
103 if (new_pin)
104 free(new_pin);
105 if (old_pin)
106 free(old_pin);
107
108 return (rv);
109 }
110
111 static int
setpin_pkcs11(KMF_HANDLE_T handle,char * token_spec,boolean_t souser)112 setpin_pkcs11(KMF_HANDLE_T handle, char *token_spec, boolean_t souser)
113 {
114 CK_SLOT_ID slot_id;
115 CK_FLAGS pin_state;
116 CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL;
117 CK_ULONG old_pinlen = 0, new_pinlen = 0;
118 CK_RV rv = CKR_OK;
119 char *token_name = NULL;
120 CK_TOKEN_INFO token_info;
121 KMF_CREDENTIAL newpincred = {NULL, 0};
122 KMF_CREDENTIAL oldcred = {NULL, 0};
123 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
124 KMF_ATTRIBUTE attrlist[6];
125 CK_USER_TYPE user = CKU_USER;
126 int numattr = 0;
127
128 /* If nothing is specified, default is to use softtoken. */
129 if (token_spec == NULL) {
130 token_spec = SOFT_TOKEN_LABEL ":" SOFT_MANUFACTURER_ID;
131 token_name = SOFT_TOKEN_LABEL;
132 }
133
134 rv = kmf_pk11_token_lookup(NULL, token_spec, &slot_id);
135 if (rv == KMF_OK) {
136 /* find the pin state for the selected token */
137 if (C_GetTokenInfo(slot_id, &token_info) != CKR_OK)
138 return (PK_ERR_PK11);
139
140 pin_state = token_info.flags & CKF_USER_PIN_TO_BE_CHANGED;
141 if (token_name == NULL)
142 token_name = (char *)token_info.label;
143 }
144
145 /*
146 * If the token is the softtoken, check if the token flags show the
147 * PIN has not been set yet. If not then set the old PIN to the
148 * default "changeme". Otherwise, let user type in the correct old
149 * PIN to unlock token.
150 */
151 if (pin_state == CKF_USER_PIN_TO_BE_CHANGED &&
152 strcmp(token_name, SOFT_TOKEN_LABEL) == 0) {
153 if ((old_pin = (CK_UTF8CHAR_PTR) strdup(SOFT_DEFAULT_PIN)) ==
154 NULL) {
155 cryptoerror(LOG_STDERR, "%s.", strerror(errno));
156 final_pk11(NULL);
157 return (PK_ERR_PK11);
158 }
159 old_pinlen = strlen(SOFT_DEFAULT_PIN);
160 } else {
161 if ((rv = get_pin(gettext("Enter token passphrase:"), NULL,
162 &old_pin, &old_pinlen)) != CKR_OK) {
163 cryptoerror(LOG_STDERR,
164 gettext("Unable to get token passphrase (%s)."),
165 pkcs11_strerror(rv));
166 final_pk11(NULL);
167 return (PK_ERR_PK11);
168 }
169 }
170
171 /* Get the user's new PIN. */
172 if ((rv = get_pin(gettext("Create new passphrase:"), gettext(
173 "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) {
174 if (rv == CKR_PIN_INCORRECT)
175 cryptoerror(LOG_STDERR, gettext(
176 "Passphrases do not match."));
177 else
178 cryptoerror(LOG_STDERR, gettext(
179 "Unable to get and confirm new passphrase (%s)."),
180 pkcs11_strerror(rv));
181 free(old_pin);
182 final_pk11(NULL);
183 return (PK_ERR_PK11);
184 }
185
186 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
187 &kstype, sizeof (kstype));
188 numattr++;
189 if (token_name != NULL) {
190 kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
191 token_name, strlen(token_name));
192 numattr++;
193 }
194 oldcred.cred = (char *)old_pin;
195 oldcred.credlen = old_pinlen;
196 kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
197 &oldcred, sizeof (oldcred));
198 numattr++;
199
200 kmf_set_attr_at_index(attrlist, numattr, KMF_SLOT_ID_ATTR,
201 &slot_id, sizeof (slot_id));
202 numattr++;
203
204 newpincred.cred = (char *)new_pin;
205 newpincred.credlen = new_pinlen;
206 kmf_set_attr_at_index(attrlist, numattr, KMF_NEWPIN_ATTR,
207 &newpincred, sizeof (newpincred));
208 numattr++;
209
210 if (souser) {
211 user = CKU_SO;
212 kmf_set_attr_at_index(attrlist, numattr,
213 KMF_PK11_USER_TYPE_ATTR,
214 &user, sizeof (user));
215 numattr++;
216 }
217
218 rv = kmf_set_token_pin(handle, numattr, attrlist);
219
220 /* Clean up. */
221 if (old_pin != NULL)
222 free(old_pin);
223 if (new_pin != NULL)
224 free(new_pin);
225
226 return (rv);
227 }
228
229 /*
230 * Changes the token's PIN.
231 */
232 int
pk_setpin(int argc,char * argv[])233 pk_setpin(int argc, char *argv[])
234 /* ARGSUSED */
235 {
236 int opt;
237 int rv;
238 extern int optind_av;
239 extern char *optarg_av;
240 char *token_spec = NULL;
241 char *dir = NULL;
242 char *prefix = NULL;
243 char *utype = NULL;
244 KMF_HANDLE_T handle;
245 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
246 boolean_t souser = 0;
247
248 /* Parse command line options. Do NOT i18n/l10n. */
249 while ((opt = getopt_av(argc, argv,
250 "T:(token)k:(keystore)d:(dir)"
251 "p:(prefix)u:(usertype)")) != EOF) {
252 switch (opt) {
253 case 'k':
254 kstype = KS2Int(optarg_av);
255 if (kstype == 0)
256 return (PK_ERR_USAGE);
257 break;
258 case 'T': /* token specifier */
259 if (token_spec)
260 return (PK_ERR_USAGE);
261 token_spec = optarg_av;
262 break;
263 case 'd':
264 if (dir)
265 return (PK_ERR_USAGE);
266 dir = optarg_av;
267 break;
268 case 'p':
269 if (prefix)
270 return (PK_ERR_USAGE);
271 prefix = optarg_av;
272 break;
273 case 'u':
274 utype = optarg_av;
275 break;
276 default:
277 return (PK_ERR_USAGE);
278 break;
279 }
280 }
281
282
283 /* No additional args allowed. */
284 argc -= optind_av;
285 argv += optind_av;
286 if (argc != 0)
287 return (PK_ERR_USAGE);
288
289 /* Done parsing command line options. */
290 if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) {
291 token_spec = PK_DEFAULT_PK11TOKEN;
292 } else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) {
293 token_spec = DEFAULT_NSS_TOKEN;
294 }
295
296 if ((rv = kmf_initialize(&handle, NULL, NULL)) != KMF_OK)
297 return (rv);
298
299 if (utype != NULL) {
300 if (strcmp(utype, "so") == 0)
301 souser = 1;
302 else if (strcmp(utype, "user") == 0)
303 souser = 0;
304 else /* Wrong option string */
305 return (PK_ERR_USAGE);
306 }
307
308 switch (kstype) {
309 case KMF_KEYSTORE_PK11TOKEN:
310 rv = setpin_pkcs11(handle, token_spec, souser);
311 break;
312 case KMF_KEYSTORE_NSS:
313 rv = setpin_nss(handle, token_spec, dir, prefix);
314 break;
315 default:
316 cryptoerror(LOG_STDERR,
317 gettext("incorrect keystore."));
318 return (PK_ERR_USAGE);
319 }
320
321 (void) kmf_finalize(handle);
322
323 if (rv == KMF_ERR_AUTH_FAILED) {
324 cryptoerror(LOG_STDERR,
325 gettext("Incorrect passphrase."));
326 return (PK_ERR_SYSTEM);
327 } else if (rv != CKR_OK) {
328 cryptoerror(LOG_STDERR,
329 gettext("Unable to change passphrase."));
330 return (PK_ERR_SYSTEM);
331 } else {
332 (void) fprintf(stdout, gettext("Passphrase changed.\n"));
333 }
334 return (0);
335 }
336