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