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