dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / cmd-crypto / pktool / setpin.c
blobc9933270bcd1ecdade73fc78ef88d62f4fe2e2d9
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2012 Milan Jurik. All rights reserved.
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.
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"
42 static int
43 setpin_nss(KMF_HANDLE_T handle,
44 char *token_spec, char *dir, char *prefix)
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;
55 rv = configure_nss(handle, dir, prefix);
56 if (rv != KMF_OK)
57 return (rv);
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++;
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);
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 free(old_pin);
85 return (PK_ERR_NSS);
88 oldcred.cred = (char *)old_pin;
89 oldcred.credlen = old_pinlen;
91 kmf_set_attr_at_index(setpinattrs, numattrs, KMF_CREDENTIAL_ATTR,
92 &oldcred, sizeof (oldcred));
93 numattrs++;
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++;
101 rv = kmf_set_token_pin(handle, numattrs, setpinattrs);
103 free(new_pin);
104 free(old_pin);
106 return (rv);
109 static int
110 setpin_pkcs11(KMF_HANDLE_T handle, char *token_spec, boolean_t souser)
112 CK_SLOT_ID slot_id;
113 CK_FLAGS pin_state;
114 CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL;
115 CK_ULONG old_pinlen = 0, new_pinlen = 0;
116 CK_RV rv = CKR_OK;
117 char *token_name = NULL;
118 CK_TOKEN_INFO token_info;
119 KMF_CREDENTIAL newpincred = { NULL, 0 };
120 KMF_CREDENTIAL oldcred = { NULL, 0 };
121 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
122 KMF_ATTRIBUTE attrlist[6];
123 CK_USER_TYPE user = CKU_USER;
124 int numattr = 0;
126 /* If nothing is specified, default is to use softtoken. */
127 if (token_spec == NULL) {
128 token_spec = SOFT_TOKEN_LABEL ":" SOFT_MANUFACTURER_ID;
129 token_name = SOFT_TOKEN_LABEL;
132 rv = kmf_pk11_token_lookup(NULL, token_spec, &slot_id);
133 if (rv == KMF_OK) {
134 /* find the pin state for the selected token */
135 if (C_GetTokenInfo(slot_id, &token_info) != CKR_OK)
136 return (PK_ERR_PK11);
138 pin_state = token_info.flags & CKF_USER_PIN_TO_BE_CHANGED;
139 if (token_name == NULL)
140 token_name = (char *)token_info.label;
144 * If the token is the softtoken, check if the token flags show the
145 * PIN has not been set yet. If not then set the old PIN to the
146 * default "changeme". Otherwise, let user type in the correct old
147 * PIN to unlock token.
149 if (pin_state == CKF_USER_PIN_TO_BE_CHANGED &&
150 strcmp(token_name, SOFT_TOKEN_LABEL) == 0) {
151 if ((old_pin = (CK_UTF8CHAR_PTR) strdup(SOFT_DEFAULT_PIN)) ==
152 NULL) {
153 cryptoerror(LOG_STDERR, "%s.", strerror(errno));
154 final_pk11(0);
155 return (PK_ERR_PK11);
157 old_pinlen = strlen(SOFT_DEFAULT_PIN);
158 } else {
159 if ((rv = get_pin(gettext("Enter token passphrase:"), NULL,
160 &old_pin, &old_pinlen)) != CKR_OK) {
161 cryptoerror(LOG_STDERR,
162 gettext("Unable to get token passphrase (%s)."),
163 pkcs11_strerror(rv));
164 final_pk11(0);
165 return (PK_ERR_PK11);
169 /* Get the user's new PIN. */
170 if ((rv = get_pin(gettext("Create new passphrase:"), gettext(
171 "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) {
172 if (rv == CKR_PIN_INCORRECT)
173 cryptoerror(LOG_STDERR, gettext(
174 "Passphrases do not match."));
175 else
176 cryptoerror(LOG_STDERR, gettext(
177 "Unable to get and confirm new passphrase (%s)."),
178 pkcs11_strerror(rv));
179 free(old_pin);
180 final_pk11(0);
181 return (PK_ERR_PK11);
184 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
185 &kstype, sizeof (kstype));
186 numattr++;
187 if (token_name != NULL) {
188 kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
189 token_name, strlen(token_name));
190 numattr++;
192 oldcred.cred = (char *)old_pin;
193 oldcred.credlen = old_pinlen;
194 kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
195 &oldcred, sizeof (oldcred));
196 numattr++;
198 kmf_set_attr_at_index(attrlist, numattr, KMF_SLOT_ID_ATTR,
199 &slot_id, sizeof (slot_id));
200 numattr++;
202 newpincred.cred = (char *)new_pin;
203 newpincred.credlen = new_pinlen;
204 kmf_set_attr_at_index(attrlist, numattr, KMF_NEWPIN_ATTR,
205 &newpincred, sizeof (newpincred));
206 numattr++;
208 if (souser) {
209 user = CKU_SO;
210 kmf_set_attr_at_index(attrlist, numattr,
211 KMF_PK11_USER_TYPE_ATTR,
212 &user, sizeof (user));
213 numattr++;
216 rv = kmf_set_token_pin(handle, numattr, attrlist);
218 /* Clean up. */
219 if (old_pin != NULL)
220 free(old_pin);
221 if (new_pin != NULL)
222 free(new_pin);
224 return (rv);
228 * Changes the token's PIN.
231 pk_setpin(int argc, char *argv[])
232 /* ARGSUSED */
234 int opt;
235 int rv;
236 extern int optind_av;
237 extern char *optarg_av;
238 char *token_spec = NULL;
239 char *dir = NULL;
240 char *prefix = NULL;
241 char *utype = NULL;
242 KMF_HANDLE_T handle;
243 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
244 boolean_t souser = 0;
246 /* Parse command line options. Do NOT i18n/l10n. */
247 while ((opt = getopt_av(argc, argv,
248 "T:(token)k:(keystore)d:(dir)"
249 "p:(prefix)u:(usertype)")) != EOF) {
250 switch (opt) {
251 case 'k':
252 kstype = KS2Int(optarg_av);
253 if (kstype == 0)
254 return (PK_ERR_USAGE);
255 break;
256 case 'T': /* token specifier */
257 if (token_spec)
258 return (PK_ERR_USAGE);
259 token_spec = optarg_av;
260 break;
261 case 'd':
262 if (dir)
263 return (PK_ERR_USAGE);
264 dir = optarg_av;
265 break;
266 case 'p':
267 if (prefix)
268 return (PK_ERR_USAGE);
269 prefix = optarg_av;
270 break;
271 case 'u':
272 utype = optarg_av;
273 break;
274 default:
275 return (PK_ERR_USAGE);
280 /* No additional args allowed. */
281 argc -= optind_av;
282 argv += optind_av;
283 if (argc != 0)
284 return (PK_ERR_USAGE);
286 /* Done parsing command line options. */
287 if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) {
288 token_spec = PK_DEFAULT_PK11TOKEN;
289 } else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) {
290 token_spec = DEFAULT_NSS_TOKEN;
293 if ((rv = kmf_initialize(&handle, NULL, NULL)) != KMF_OK)
294 return (rv);
296 if (utype != NULL) {
297 if (strcmp(utype, "so") == 0)
298 souser = 1;
299 else if (strcmp(utype, "user") == 0)
300 souser = 0;
301 else /* Wrong option string */
302 return (PK_ERR_USAGE);
305 switch (kstype) {
306 case KMF_KEYSTORE_PK11TOKEN:
307 rv = setpin_pkcs11(handle, token_spec, souser);
308 break;
309 case KMF_KEYSTORE_NSS:
310 rv = setpin_nss(handle, token_spec, dir, prefix);
311 break;
312 default:
313 cryptoerror(LOG_STDERR,
314 gettext("incorrect keystore."));
315 return (PK_ERR_USAGE);
318 (void) kmf_finalize(handle);
320 if (rv == KMF_ERR_AUTH_FAILED) {
321 cryptoerror(LOG_STDERR,
322 gettext("Incorrect passphrase."));
323 return (PK_ERR_SYSTEM);
324 } else if (rv != CKR_OK) {
325 cryptoerror(LOG_STDERR,
326 gettext("Unable to change passphrase."));
327 return (PK_ERR_SYSTEM);
328 } else {
329 (void) fprintf(stdout, gettext("Passphrase changed.\n"));
331 return (0);