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 #include <stdio.h>
27 #include <string.h>
28 #include <ctype.h>
29 #include <malloc.h>
30 #include <libgen.h>
31 #include <errno.h>
32 #include <cryptoutil.h>
33 #include <security/cryptoki.h>
34 #include "common.h"
35 
36 #include <kmfapi.h>
37 
38 #define	SET_VALUE(f, s) \
39 	kmfrv = f; \
40 	if (kmfrv != KMF_OK) { \
41 		cryptoerror(LOG_STDERR, \
42 			gettext("Failed to %s: 0x%02\n"), \
43 			s, kmfrv); \
44 		goto cleanup; \
45 	}
46 
47 static KMF_RETURN
48 gencsr_pkcs11(KMF_HANDLE_T kmfhandle,
49 	char *token, char *subject, char *altname,
50 	KMF_GENERALNAMECHOICES alttype, int altcrit,
51 	char *certlabel, KMF_KEY_ALG keyAlg,
52 	int keylen, uint16_t kubits, int kucrit,
53 	KMF_ENCODE_FORMAT fmt, char *csrfile,
54 	KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist)
55 {
56 	KMF_RETURN kmfrv = KMF_OK;
57 	KMF_KEY_HANDLE pubk, prik;
58 	KMF_X509_NAME	csrSubject;
59 	KMF_CSR_DATA	csr;
60 	KMF_ALGORITHM_INDEX sigAlg;
61 	KMF_DATA signedCsr = {NULL, 0};
62 
63 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
64 	int numattr = 0;
65 	KMF_ATTRIBUTE attrlist[16];
66 	boolean_t storekey = TRUE;
67 
68 	(void) memset(&csr, 0, sizeof (csr));
69 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
70 
71 	if (keyAlg == KMF_DSA)
72 		sigAlg = KMF_ALGID_SHA1WithDSA;
73 	else
74 		sigAlg = KMF_ALGID_SHA1WithRSA;
75 
76 
77 	/* If the subject name cannot be parsed, flag it now and exit */
78 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
79 		return (kmfrv);
80 	}
81 
82 	/* Select a PKCS11 token */
83 	kmfrv = select_token(kmfhandle, token, FALSE);
84 	if (kmfrv != KMF_OK) {
85 		return (kmfrv);
86 	}
87 
88 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
89 	    &kstype, sizeof (kstype));
90 	numattr++;
91 
92 	if (certlabel != NULL && strlen(certlabel)) {
93 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
94 		    certlabel, strlen(certlabel));
95 		numattr++;
96 	}
97 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR,
98 	    &keylen, sizeof (keylen));
99 	numattr++;
100 
101 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR,
102 	    &keyAlg, sizeof (keyAlg));
103 	numattr++;
104 
105 	kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
106 	    tokencred, sizeof (KMF_CREDENTIAL));
107 	numattr++;
108 
109 	if (token && strlen(token)) {
110 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
111 		    token, strlen(token));
112 		numattr++;
113 	}
114 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
115 	    &pubk, sizeof (KMF_KEY_HANDLE));
116 	numattr++;
117 
118 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR,
119 	    &prik, sizeof (KMF_KEY_HANDLE));
120 	numattr++;
121 
122 	kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR,
123 	    &storekey, sizeof (storekey));
124 	numattr++;
125 
126 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
127 	if (kmfrv != KMF_OK) {
128 		return (kmfrv);
129 	}
130 
131 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), "keypair");
132 
133 	SET_VALUE(kmf_set_csr_version(&csr, 2), "version number");
134 
135 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), "subject name");
136 
137 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg),
138 	    "SignatureAlgorithm");
139 
140 	if (altname != NULL) {
141 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
142 		    alttype), "SetCSRSubjectAltName");
143 	}
144 
145 	if (kubits != 0) {
146 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
147 		    "SetCSRKeyUsage");
148 	}
149 	if (ekulist != NULL) {
150 		int i;
151 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
152 			SET_VALUE(kmf_add_csr_eku(&csr,
153 			    &ekulist->ekulist[i],
154 			    ekulist->critlist[i]),
155 			    "Extended Key Usage");
156 		}
157 	}
158 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
159 	    KMF_OK) {
160 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile);
161 	}
162 
163 cleanup:
164 	(void) kmf_free_data(&signedCsr);
165 	(void) kmf_free_signed_csr(&csr);
166 
167 	/* delete the public key */
168 	numattr = 0;
169 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
170 	    &kstype, sizeof (kstype));
171 	numattr++;
172 
173 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
174 	    &pubk, sizeof (KMF_KEY_HANDLE));
175 	numattr++;
176 
177 	if (tokencred != NULL && tokencred->cred != NULL) {
178 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
179 		    tokencred, sizeof (KMF_CREDENTIAL));
180 		numattr++;
181 	}
182 
183 	(void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist);
184 
185 	/*
186 	 * If there is an error, then we need to remove the private key
187 	 * from the token.
188 	 */
189 	if (kmfrv != KMF_OK) {
190 		numattr = 0;
191 		kmf_set_attr_at_index(attrlist, numattr,
192 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
193 		numattr++;
194 
195 		kmf_set_attr_at_index(attrlist, numattr,
196 		    KMF_KEY_HANDLE_ATTR, &prik, sizeof (KMF_KEY_HANDLE));
197 		numattr++;
198 
199 		if (tokencred != NULL && tokencred->cred != NULL) {
200 			kmf_set_attr_at_index(attrlist, numattr,
201 			    KMF_CREDENTIAL_ATTR, tokencred,
202 			    sizeof (KMF_CREDENTIAL));
203 			numattr++;
204 		}
205 
206 		(void) kmf_delete_key_from_keystore(kmfhandle, numattr,
207 		    attrlist);
208 	}
209 
210 	(void) kmf_free_kmf_key(kmfhandle, &prik);
211 	return (kmfrv);
212 }
213 
214 static KMF_RETURN
215 gencsr_file(KMF_HANDLE_T kmfhandle,
216 	KMF_KEY_ALG keyAlg,
217 	int keylen, KMF_ENCODE_FORMAT fmt,
218 	char *subject, char *altname, KMF_GENERALNAMECHOICES alttype,
219 	int altcrit, uint16_t kubits, int kucrit,
220 	char *outcsr, char *outkey, EKU_LIST *ekulist)
221 {
222 	KMF_RETURN kmfrv;
223 	KMF_KEY_HANDLE pubk, prik;
224 	KMF_X509_NAME	csrSubject;
225 	KMF_CSR_DATA	csr;
226 	KMF_ALGORITHM_INDEX sigAlg;
227 	KMF_DATA signedCsr = {NULL, 0};
228 	char *fullcsrpath = NULL;
229 	char *fullkeypath = NULL;
230 
231 	int numattr = 0;
232 	KMF_ATTRIBUTE attrlist[16];
233 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
234 	boolean_t	storekey = TRUE;
235 
236 	(void) memset(&csr, 0, sizeof (csr));
237 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
238 
239 	if (EMPTYSTRING(outcsr) || EMPTYSTRING(outkey)) {
240 		cryptoerror(LOG_STDERR,
241 		    gettext("No output file was specified for "
242 		    "the csr or key\n"));
243 		return (KMF_ERR_BAD_PARAMETER);
244 	}
245 	fullcsrpath = strdup(outcsr);
246 	if (verify_file(fullcsrpath)) {
247 		cryptoerror(LOG_STDERR,
248 		    gettext("Cannot write the indicated output "
249 		    "certificate file (%s).\n"), fullcsrpath);
250 		free(fullcsrpath);
251 		return (PK_ERR_USAGE);
252 	}
253 
254 	fullkeypath = strdup(outkey);
255 	if (verify_file(fullcsrpath)) {
256 		cryptoerror(LOG_STDERR,
257 		    gettext("Cannot write the indicated output "
258 		    "key file (%s).\n"), fullkeypath);
259 		free(fullcsrpath);
260 		return (PK_ERR_USAGE);
261 	}
262 
263 	if (keyAlg == KMF_DSA)
264 		sigAlg = KMF_ALGID_SHA1WithDSA;
265 	else
266 		sigAlg = KMF_ALGID_SHA1WithRSA;
267 
268 	/* If the subject name cannot be parsed, flag it now and exit */
269 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
270 		return (kmfrv);
271 	}
272 
273 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
274 	    &kstype, sizeof (kstype));
275 	numattr++;
276 
277 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
278 	    fullkeypath, strlen(fullkeypath));
279 	numattr++;
280 
281 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR,
282 	    &keylen, sizeof (keylen));
283 	numattr++;
284 
285 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR,
286 	    &keyAlg, sizeof (keyAlg));
287 	numattr++;
288 
289 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
290 	    &fmt, sizeof (fmt));
291 	numattr++;
292 
293 	(void) memset(&prik, 0, sizeof (prik));
294 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR,
295 	    &prik, sizeof (KMF_KEY_HANDLE));
296 	numattr++;
297 
298 	(void) memset(&pubk, 0, sizeof (pubk));
299 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
300 	    &pubk, sizeof (KMF_KEY_HANDLE));
301 	numattr++;
302 
303 	kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR,
304 	    &storekey, sizeof (storekey));
305 	numattr++;
306 
307 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
308 	if (kmfrv != KMF_OK) {
309 		goto cleanup;
310 	}
311 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
312 	    "SetCSRPubKey");
313 
314 	SET_VALUE(kmf_set_csr_version(&csr, 2), "SetCSRVersion");
315 
316 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
317 	    "kmf_set_csr_subject");
318 
319 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");
320 
321 	if (altname != NULL) {
322 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
323 		    alttype), "kmf_set_csr_subject_altname");
324 	}
325 	if (kubits != NULL) {
326 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
327 		    "kmf_set_csr_ku");
328 	}
329 	if (ekulist != NULL) {
330 		int i;
331 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
332 			SET_VALUE(kmf_add_csr_eku(&csr,
333 			    &ekulist->ekulist[i],
334 			    ekulist->critlist[i]),
335 			    "Extended Key Usage");
336 		}
337 	}
338 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
339 	    KMF_OK) {
340 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, fullcsrpath);
341 	}
342 
343 cleanup:
344 	if (fullkeypath)
345 		free(fullkeypath);
346 	if (fullcsrpath)
347 		free(fullcsrpath);
348 
349 	kmf_free_data(&signedCsr);
350 	kmf_free_kmf_key(kmfhandle, &prik);
351 	kmf_free_signed_csr(&csr);
352 
353 	return (kmfrv);
354 }
355 
356 static KMF_RETURN
357 gencsr_nss(KMF_HANDLE_T kmfhandle,
358 	char *token, char *subject, char *altname,
359 	KMF_GENERALNAMECHOICES alttype, int altcrit,
360 	char *nickname, char *dir, char *prefix,
361 	KMF_KEY_ALG keyAlg, int keylen,
362 	uint16_t kubits, int kucrit,
363 	KMF_ENCODE_FORMAT fmt, char *csrfile,
364 	KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist)
365 {
366 	KMF_RETURN kmfrv;
367 	KMF_KEY_HANDLE pubk, prik;
368 	KMF_X509_NAME	csrSubject;
369 	KMF_CSR_DATA	csr;
370 	KMF_ALGORITHM_INDEX sigAlg;
371 	KMF_DATA signedCsr = {NULL, 0};
372 
373 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
374 	int numattr = 0;
375 	KMF_ATTRIBUTE attrlist[16];
376 	boolean_t storekey = TRUE;
377 
378 	if (token == NULL)
379 		token = DEFAULT_NSS_TOKEN;
380 
381 	if (keyAlg == KMF_DSA)
382 		sigAlg = KMF_ALGID_SHA1WithDSA;
383 	else
384 		sigAlg = KMF_ALGID_SHA1WithRSA;
385 
386 	kmfrv = configure_nss(kmfhandle, dir, prefix);
387 	if (kmfrv != KMF_OK)
388 		return (kmfrv);
389 
390 	(void) memset(&csr, 0, sizeof (csr));
391 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
392 	(void) memset(&pubk, 0, sizeof (pubk));
393 	(void) memset(&prik, 0, sizeof (prik));
394 
395 	/* If the subject name cannot be parsed, flag it now and exit */
396 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
397 		return (kmfrv);
398 	}
399 
400 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
401 	    &kstype, sizeof (kstype));
402 	numattr++;
403 
404 	if (nickname != NULL && strlen(nickname)) {
405 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
406 		    nickname, strlen(nickname));
407 		numattr++;
408 	}
409 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR,
410 	    &keylen, sizeof (keylen));
411 	numattr++;
412 
413 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR,
414 	    &keyAlg, sizeof (keyAlg));
415 	numattr++;
416 
417 	if (tokencred != NULL && tokencred->credlen > 0) {
418 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
419 		    tokencred, sizeof (KMF_CREDENTIAL));
420 		numattr++;
421 	}
422 
423 	if (token && strlen(token)) {
424 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
425 		    token, strlen(token));
426 		numattr++;
427 	}
428 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
429 	    &pubk, sizeof (KMF_KEY_HANDLE));
430 	numattr++;
431 
432 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR,
433 	    &prik, sizeof (KMF_KEY_HANDLE));
434 	numattr++;
435 
436 	kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR,
437 	    &storekey, sizeof (storekey));
438 	numattr++;
439 
440 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
441 	if (kmfrv != KMF_OK) {
442 		goto cleanup;
443 	}
444 
445 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
446 	    "kmf_set_csr_pubkey");
447 	SET_VALUE(kmf_set_csr_version(&csr, 2), "kmf_set_csr_version");
448 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
449 	    "kmf_set_csr_subject");
450 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");
451 
452 	if (altname != NULL) {
453 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
454 		    alttype), "kmf_set_csr_subject_altname");
455 	}
456 	if (kubits != NULL) {
457 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
458 		    "kmf_set_csr_ku");
459 	}
460 	if (ekulist != NULL) {
461 		int i;
462 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
463 			SET_VALUE(kmf_add_csr_eku(&csr,
464 			    &ekulist->ekulist[i],
465 			    ekulist->critlist[i]),
466 			    "Extended Key Usage");
467 		}
468 	}
469 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
470 	    KMF_OK) {
471 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile);
472 	}
473 
474 cleanup:
475 	(void) kmf_free_data(&signedCsr);
476 	(void) kmf_free_kmf_key(kmfhandle, &prik);
477 
478 	/* delete the key */
479 	numattr = 0;
480 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
481 	    &kstype, sizeof (kstype));
482 	numattr++;
483 
484 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
485 	    &pubk, sizeof (KMF_KEY_HANDLE));
486 	numattr++;
487 
488 	if (tokencred != NULL && tokencred->credlen > 0) {
489 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
490 		    tokencred, sizeof (KMF_CREDENTIAL));
491 		numattr++;
492 	}
493 
494 	if (token && strlen(token)) {
495 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
496 		    token, strlen(token));
497 		numattr++;
498 	}
499 
500 	(void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist);
501 
502 	(void) kmf_free_signed_csr(&csr);
503 
504 	return (kmfrv);
505 }
506 
507 int
508 pk_gencsr(int argc, char *argv[])
509 {
510 	KMF_RETURN rv;
511 	int opt;
512 	extern int	optind_av;
513 	extern char	*optarg_av;
514 	KMF_KEYSTORE_TYPE kstype = 0;
515 	char *subject = NULL;
516 	char *tokenname = NULL;
517 	char *dir = NULL;
518 	char *prefix = NULL;
519 	int keylen = PK_DEFAULT_KEYLENGTH;
520 	char *certlabel = NULL;
521 	char *outcsr = NULL;
522 	char *outkey = NULL;
523 	char *format = NULL;
524 	char *altname = NULL;
525 	char *kustr = NULL;
526 	char *ekustr = NULL;
527 	uint16_t kubits = 0;
528 	char *keytype = PK_DEFAULT_KEYTYPE;
529 	KMF_HANDLE_T kmfhandle = NULL;
530 	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
531 	KMF_KEY_ALG keyAlg = KMF_RSA;
532 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_SHA1WithRSA;
533 	boolean_t interactive = B_FALSE;
534 	char *subname = NULL;
535 	KMF_CREDENTIAL tokencred = {NULL, 0};
536 	KMF_GENERALNAMECHOICES alttype = 0;
537 	int altcrit = 0, kucrit = 0;
538 	EKU_LIST *ekulist = NULL;
539 
540 	while ((opt = getopt_av(argc, argv,
541 	    "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
542 	    "u:(keyusage)T:(token)d:(dir)p:(prefix)t:(keytype)"
543 	    "y:(keylen)l:(label)c:(outcsr)e:(eku)"
544 	    "K:(outkey)F:(format)")) != EOF) {
545 
546 		if (opt != 'i' && EMPTYSTRING(optarg_av))
547 			return (PK_ERR_USAGE);
548 
549 		switch (opt) {
550 			case 'A':
551 				altname = optarg_av;
552 				break;
553 			case 'i':
554 				if (interactive)
555 					return (PK_ERR_USAGE);
556 				else if (subject) {
557 					cryptoerror(LOG_STDERR,
558 					    gettext("Interactive (-i) and "
559 					    "subject options are mutually "
560 					    "exclusive.\n"));
561 					return (PK_ERR_USAGE);
562 				} else
563 					interactive = B_TRUE;
564 				break;
565 			case 'k':
566 				kstype = KS2Int(optarg_av);
567 				if (kstype == 0)
568 					return (PK_ERR_USAGE);
569 				break;
570 			case 's':
571 				if (subject)
572 					return (PK_ERR_USAGE);
573 				else if (interactive) {
574 					cryptoerror(LOG_STDERR,
575 					    gettext("Interactive (-i) and "
576 					    "subject options are mutually "
577 					    "exclusive.\n"));
578 					return (PK_ERR_USAGE);
579 				} else
580 					subject = optarg_av;
581 				break;
582 			case 'l':
583 			case 'n':
584 				if (certlabel)
585 					return (PK_ERR_USAGE);
586 				certlabel = optarg_av;
587 				break;
588 			case 'T':
589 				if (tokenname)
590 					return (PK_ERR_USAGE);
591 				tokenname = optarg_av;
592 				break;
593 			case 'd':
594 				dir = optarg_av;
595 				break;
596 			case 'p':
597 				if (prefix)
598 					return (PK_ERR_USAGE);
599 				prefix = optarg_av;
600 				break;
601 			case 't':
602 				keytype = optarg_av;
603 				break;
604 			case 'u':
605 				kustr = optarg_av;
606 				break;
607 			case 'y':
608 				if (sscanf(optarg_av, "%d",
609 				    &keylen) != 1) {
610 					cryptoerror(LOG_STDERR,
611 					    gettext("Unrecognized "
612 					    "key length (%s)\n"), optarg_av);
613 					return (PK_ERR_USAGE);
614 				}
615 				break;
616 			case 'c':
617 				if (outcsr)
618 					return (PK_ERR_USAGE);
619 				outcsr = optarg_av;
620 				break;
621 			case 'K':
622 				if (outkey)
623 					return (PK_ERR_USAGE);
624 				outkey = optarg_av;
625 				break;
626 			case 'F':
627 				if (format)
628 					return (PK_ERR_USAGE);
629 				format = optarg_av;
630 				break;
631 			case 'e':
632 				ekustr = optarg_av;
633 				break;
634 			default:
635 				cryptoerror(LOG_STDERR, gettext(
636 				    "unrecognized gencsr option '%s'\n"),
637 				    argv[optind_av]);
638 				return (PK_ERR_USAGE);
639 		}
640 	}
641 	/* No additional args allowed. */
642 	argc -= optind_av;
643 	argv += optind_av;
644 	if (argc) {
645 		return (PK_ERR_USAGE);
646 	}
647 
648 	/* Assume keystore = PKCS#11 if not specified. */
649 	if (kstype == 0)
650 		kstype = KMF_KEYSTORE_PK11TOKEN;
651 
652 	DIR_OPTION_CHECK(kstype, dir);
653 
654 	if (EMPTYSTRING(outcsr) && interactive) {
655 		(void) get_filename("CSR", &outcsr);
656 	}
657 	if (EMPTYSTRING(outcsr)) {
658 		(void) printf(gettext("A filename must be specified to hold"
659 		    "the final certificate request data.\n"));
660 		return (PK_ERR_USAGE);
661 	}
662 	/*
663 	 * verify that the outcsr file does not already exist
664 	 * and that it can be created.
665 	 */
666 	rv = verify_file(outcsr);
667 	if (rv != KMF_OK) {
668 		cryptoerror(LOG_STDERR, gettext("output file (%s) "
669 		    "cannot be created.\n"), outcsr);
670 		return (PK_ERR_USAGE);
671 	}
672 
673 	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) {
674 		if (EMPTYSTRING(certlabel) && interactive)
675 			(void) get_certlabel(&certlabel);
676 
677 		if (EMPTYSTRING(certlabel)) {
678 			cryptoerror(LOG_STDERR, gettext("A label must be "
679 			    "specified to create a certificate request.\n"));
680 			return (PK_ERR_USAGE);
681 		}
682 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
683 		if (EMPTYSTRING(outkey) && interactive)
684 			(void) get_filename("private key", &outkey);
685 
686 		if (EMPTYSTRING(outkey)) {
687 			cryptoerror(LOG_STDERR, gettext("A key filename "
688 			    "must be specified to create a certificate "
689 			    "request.\n"));
690 			return (PK_ERR_USAGE);
691 		}
692 	}
693 
694 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
695 		cryptoerror(LOG_STDERR,
696 		    gettext("Error parsing format string (%s).\n"), format);
697 		return (PK_ERR_USAGE);
698 	}
699 	if (format && fmt != KMF_FORMAT_ASN1 && fmt != KMF_FORMAT_PEM) {
700 		cryptoerror(LOG_STDERR,
701 		    gettext("CSR must be DER or PEM format.\n"));
702 		return (PK_ERR_USAGE);
703 	}
704 
705 	/*
706 	 * Check the subject name.
707 	 * If interactive is true, get it now interactively.
708 	 */
709 	if (interactive) {
710 		if (get_subname(&subname) != KMF_OK) {
711 			cryptoerror(LOG_STDERR, gettext("Failed to get the "
712 			    "subject name interactively.\n"));
713 			return (PK_ERR_USAGE);
714 		}
715 	} else {
716 		if (EMPTYSTRING(subject)) {
717 			cryptoerror(LOG_STDERR, gettext("A subject name or "
718 			    "-i must be specified to create a certificate "
719 			    "request.\n"));
720 			return (PK_ERR_USAGE);
721 		} else {
722 			subname = strdup(subject);
723 			if (subname == NULL) {
724 				cryptoerror(LOG_STDERR,
725 				    gettext("Out of memory.\n"));
726 				return (PK_ERR_SYSTEM);
727 			}
728 		}
729 	}
730 	if (altname != NULL) {
731 		rv = verify_altname(altname, &alttype, &altcrit);
732 		if (rv != KMF_OK) {
733 			cryptoerror(LOG_STDERR, gettext("Subject AltName "
734 			    "must be specified as a name=value pair. "
735 			    "See the man page for details."));
736 			goto end;
737 		} else {
738 			/* advance the altname past the '=' sign */
739 			char *p = strchr(altname, '=');
740 			if (p != NULL)
741 				altname = p + 1;
742 		}
743 	}
744 
745 	if (kustr != NULL) {
746 		rv = verify_keyusage(kustr, &kubits, &kucrit);
747 		if (rv != KMF_OK) {
748 			cryptoerror(LOG_STDERR, gettext("KeyUsage "
749 			    "must be specified as a comma-separated list. "
750 			    "See the man page for details."));
751 			goto end;
752 		}
753 	}
754 	if (ekustr != NULL) {
755 		rv = verify_ekunames(ekustr, &ekulist);
756 		if (rv != KMF_OK) {
757 			(void) fprintf(stderr, gettext("EKUs must "
758 			    "be specified as a comma-separated list. "
759 			    "See the man page for details.\n"));
760 			rv = PK_ERR_USAGE;
761 			goto end;
762 		}
763 	}
764 
765 	if ((rv = Str2KeyType(keytype, &keyAlg, &sigAlg)) != 0) {
766 		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
767 		    keytype);
768 		goto end;
769 	}
770 
771 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
772 		if (tokenname == NULL || !strlen(tokenname)) {
773 			if (kstype == KMF_KEYSTORE_NSS) {
774 				tokenname = "internal";
775 			} else  {
776 				tokenname = PK_DEFAULT_PK11TOKEN;
777 			}
778 		}
779 
780 		(void) get_token_password(kstype, tokenname, &tokencred);
781 	}
782 
783 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
784 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
785 		return (PK_ERR_USAGE);
786 	}
787 
788 
789 	if (kstype == KMF_KEYSTORE_NSS) {
790 		if (dir == NULL)
791 			dir = PK_DEFAULT_DIRECTORY;
792 
793 		rv = gencsr_nss(kmfhandle,
794 		    tokenname, subname, altname, alttype, altcrit,
795 		    certlabel, dir, prefix,
796 		    keyAlg, keylen, kubits, kucrit,
797 		    fmt, outcsr, &tokencred, ekulist);
798 
799 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
800 		rv = gencsr_pkcs11(kmfhandle,
801 		    tokenname, subname, altname, alttype, altcrit,
802 		    certlabel, keyAlg, keylen,
803 		    kubits, kucrit, fmt, outcsr, &tokencred, ekulist);
804 
805 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
806 		rv = gencsr_file(kmfhandle,
807 		    keyAlg, keylen, fmt, subname, altname,
808 		    alttype, altcrit, kubits, kucrit,
809 		    outcsr, outkey, ekulist);
810 	}
811 
812 end:
813 	if (rv != KMF_OK) {
814 		display_error(kmfhandle, rv,
815 		    gettext("Error creating CSR or keypair"));
816 
817 		if (rv == KMF_ERR_RDN_PARSER) {
818 			cryptoerror(LOG_STDERR, gettext("subject or "
819 			    "issuer name must be in proper DN format.\n"));
820 		}
821 	}
822 
823 	if (ekulist != NULL)
824 		free_eku_list(ekulist);
825 
826 	if (subname)
827 		free(subname);
828 
829 	if (tokencred.cred != NULL)
830 		free(tokencred.cred);
831 
832 	(void) kmf_finalize(kmfhandle);
833 	if (rv != KMF_OK)
834 		return (PK_ERR_USAGE);
835 
836 	return (0);
837 }
838