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