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