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 * Copyright 2012 Milan Jurik. All rights reserved.
25 */
26
27 /*
28 * This file implements the setpin operation for this tool.
29 * The basic flow of the process is to load the PKCS#11 module,
30 * finds the soft token, prompt the user for the old PIN (if
31 * any) and the new PIN, change the token's PIN, and clean up.
32 */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <errno.h>
37 #include <string.h>
38 #include <cryptoutil.h>
39 #include <security/cryptoki.h>
40 #include "common.h"
41
42 static int
setpin_nss(KMF_HANDLE_T handle,char * token_spec,char * dir,char * prefix)43 setpin_nss(KMF_HANDLE_T handle,
44 char *token_spec, char *dir, char *prefix)
45 {
46 int rv = 0;
47 KMF_CREDENTIAL oldcred = { NULL, 0 };
48 KMF_CREDENTIAL newpincred = { NULL, 0 };
49 CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL;
50 CK_ULONG old_pinlen = 0, new_pinlen = 0;
51 KMF_ATTRIBUTE setpinattrs[6];
52 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
53 int numattrs = 0;
54
55 rv = configure_nss(handle, dir, prefix);
56 if (rv != KMF_OK)
57 return (rv);
58
59 kmf_set_attr_at_index(setpinattrs, numattrs, KMF_KEYSTORE_TYPE_ATTR,
60 &kstype, sizeof (kstype));
61 numattrs++;
62 if (token_spec != NULL) {
63 kmf_set_attr_at_index(setpinattrs, numattrs,
64 KMF_TOKEN_LABEL_ATTR,
65 token_spec, strlen(token_spec));
66 numattrs++;
67 }
68
69 if ((rv = get_pin(gettext("Enter current token passphrase "
70 "(<CR> if not set):"), NULL, &old_pin, &old_pinlen)) != CKR_OK) {
71 cryptoerror(LOG_STDERR,
72 gettext("Unable to get token passphrase."));
73 return (PK_ERR_NSS);
74 }
75 /* Get the user's new PIN. */
76 if ((rv = get_pin(gettext("Create new passphrase:"), gettext(
77 "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) {
78 if (rv == CKR_PIN_INCORRECT)
79 cryptoerror(LOG_STDERR, gettext(
80 "Passphrases do not match."));
81 else
82 cryptoerror(LOG_STDERR, gettext(
83 "Unable to get and confirm new passphrase."));
84 if (old_pin != NULL)
85 free(old_pin);
86 return (PK_ERR_NSS);
87 }
88
89 oldcred.cred = (char *)old_pin;
90 oldcred.credlen = old_pinlen;
91
92 kmf_set_attr_at_index(setpinattrs, numattrs, KMF_CREDENTIAL_ATTR,
93 &oldcred, sizeof (oldcred));
94 numattrs++;
95
96 newpincred.cred = (char *)new_pin;
97 newpincred.credlen = new_pinlen;
98 kmf_set_attr_at_index(setpinattrs, numattrs, KMF_NEWPIN_ATTR,
99 &newpincred, sizeof (newpincred));
100 numattrs++;
101
102 rv = kmf_set_token_pin(handle, numattrs, setpinattrs);
103
104 if (new_pin)
105 free(new_pin);
106 if (old_pin)
107 free(old_pin);
108
109 return (rv);
110 }
111
112 static int
setpin_pkcs11(KMF_HANDLE_T handle,char * token_spec,boolean_t souser)113 setpin_pkcs11(KMF_HANDLE_T handle, char *token_spec, boolean_t souser)
114 {
115 CK_SLOT_ID slot_id;
116 CK_FLAGS pin_state;
117 CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL;
118 CK_ULONG old_pinlen = 0, new_pinlen = 0;
119 CK_RV rv = CKR_OK;
120 char *token_name = NULL;
121 CK_TOKEN_INFO token_info;
122 KMF_CREDENTIAL newpincred = { NULL, 0 };
123 KMF_CREDENTIAL oldcred = { NULL, 0 };
124 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
125 KMF_ATTRIBUTE attrlist[6];
126 CK_USER_TYPE user = CKU_USER;
127 int numattr = 0;
128
129 /* If nothing is specified, default is to use softtoken. */
130 if (token_spec == NULL) {
131 token_spec = SOFT_TOKEN_LABEL ":" SOFT_MANUFACTURER_ID;
132 token_name = SOFT_TOKEN_LABEL;
133 }
134
135 rv = kmf_pk11_token_lookup(NULL, token_spec, &slot_id);
136 if (rv == KMF_OK) {
137 /* find the pin state for the selected token */
138 if (C_GetTokenInfo(slot_id, &token_info) != CKR_OK)
139 return (PK_ERR_PK11);
140
141 pin_state = token_info.flags & CKF_USER_PIN_TO_BE_CHANGED;
142 if (token_name == NULL)
143 token_name = (char *)token_info.label;
144 }
145
146 /*
147 * If the token is the softtoken, check if the token flags show the
148 * PIN has not been set yet. If not then set the old PIN to the
149 * default "changeme". Otherwise, let user type in the correct old
150 * PIN to unlock token.
151 */
152 if (pin_state == CKF_USER_PIN_TO_BE_CHANGED &&
153 strcmp(token_name, SOFT_TOKEN_LABEL) == 0) {
154 if ((old_pin = (CK_UTF8CHAR_PTR) strdup(SOFT_DEFAULT_PIN)) ==
155 NULL) {
156 cryptoerror(LOG_STDERR, "%s.", strerror(errno));
157 final_pk11(0);
158 return (PK_ERR_PK11);
159 }
160 old_pinlen = strlen(SOFT_DEFAULT_PIN);
161 } else {
162 if ((rv = get_pin(gettext("Enter token passphrase:"), NULL,
163 &old_pin, &old_pinlen)) != CKR_OK) {
164 cryptoerror(LOG_STDERR,
165 gettext("Unable to get token passphrase (%s)."),
166 pkcs11_strerror(rv));
167 final_pk11(0);
168 return (PK_ERR_PK11);
169 }
170 }
171
172 /* Get the user's new PIN. */
173 if ((rv = get_pin(gettext("Create new passphrase:"), gettext(
174 "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) {
175 if (rv == CKR_PIN_INCORRECT)
176 cryptoerror(LOG_STDERR, gettext(
177 "Passphrases do not match."));
178 else
179 cryptoerror(LOG_STDERR, gettext(
180 "Unable to get and confirm new passphrase (%s)."),
181 pkcs11_strerror(rv));
182 free(old_pin);
183 final_pk11(0);
184 return (PK_ERR_PK11);
185 }
186
187 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
188 &kstype, sizeof (kstype));
189 numattr++;
190 if (token_name != NULL) {
191 kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
192 token_name, strlen(token_name));
193 numattr++;
194 }
195 oldcred.cred = (char *)old_pin;
196 oldcred.credlen = old_pinlen;
197 kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
198 &oldcred, sizeof (oldcred));
199 numattr++;
200
201 kmf_set_attr_at_index(attrlist, numattr, KMF_SLOT_ID_ATTR,
202 &slot_id, sizeof (slot_id));
203 numattr++;
204
205 newpincred.cred = (char *)new_pin;
206 newpincred.credlen = new_pinlen;
207 kmf_set_attr_at_index(attrlist, numattr, KMF_NEWPIN_ATTR,
208 &newpincred, sizeof (newpincred));
209 numattr++;
210
211 if (souser) {
212 user = CKU_SO;
213 kmf_set_attr_at_index(attrlist, numattr,
214 KMF_PK11_USER_TYPE_ATTR,
215 &user, sizeof (user));
216 numattr++;
217 }
218
219 rv = kmf_set_token_pin(handle, numattr, attrlist);
220
221 /* Clean up. */
222 if (old_pin != NULL)
223 free(old_pin);
224 if (new_pin != NULL)
225 free(new_pin);
226
227 return (rv);
228 }
229
230 /*
231 * Changes the token's PIN.
232 */
233 int
pk_setpin(int argc,char * argv[])234 pk_setpin(int argc, char *argv[])
235 /* ARGSUSED */
236 {
237 int opt;
238 int rv;
239 extern int optind_av;
240 extern char *optarg_av;
241 char *token_spec = NULL;
242 char *dir = NULL;
243 char *prefix = NULL;
244 char *utype = NULL;
245 KMF_HANDLE_T handle;
246 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
247 boolean_t souser = 0;
248
249 /* Parse command line options. Do NOT i18n/l10n. */
250 while ((opt = getopt_av(argc, argv,
251 "T:(token)k:(keystore)d:(dir)"
252 "p:(prefix)u:(usertype)")) != EOF) {
253 switch (opt) {
254 case 'k':
255 kstype = KS2Int(optarg_av);
256 if (kstype == 0)
257 return (PK_ERR_USAGE);
258 break;
259 case 'T': /* token specifier */
260 if (token_spec)
261 return (PK_ERR_USAGE);
262 token_spec = optarg_av;
263 break;
264 case 'd':
265 if (dir)
266 return (PK_ERR_USAGE);
267 dir = optarg_av;
268 break;
269 case 'p':
270 if (prefix)
271 return (PK_ERR_USAGE);
272 prefix = optarg_av;
273 break;
274 case 'u':
275 utype = optarg_av;
276 break;
277 default:
278 return (PK_ERR_USAGE);
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