xref: /titanic_52/usr/src/cmd/cmd-crypto/pktool/gencsr.c (revision a93a1f58a8763fa69172980b98e3d24720c1136e)
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) && interactive) {
605 		(void) get_filename("CSR", &outcsr);
606 	}
607 	if (EMPTYSTRING(outcsr)) {
608 		(void) printf(gettext("A filename must be specified to hold"
609 		    "the final certificate request data.\n"));
610 		return (PK_ERR_USAGE);
611 	}
612 	/*
613 	 * verify that the outcsr file does not already exist
614 	 * and that it can be created.
615 	 */
616 	rv = verify_file(outcsr);
617 	if (rv != KMF_OK) {
618 		cryptoerror(LOG_STDERR, gettext("output file (%s) "
619 		    "cannot be created.\n"), outcsr);
620 		return (PK_ERR_USAGE);
621 	}
622 
623 	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) {
624 		if (EMPTYSTRING(certlabel) && interactive)
625 			(void) get_certlabel(&certlabel);
626 
627 		if (EMPTYSTRING(certlabel)) {
628 			cryptoerror(LOG_STDERR, gettext("A label must be "
629 			    "specified to create a certificate request.\n"));
630 			return (PK_ERR_USAGE);
631 		}
632 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
633 		if (EMPTYSTRING(outkey) && interactive)
634 			(void) get_filename("private key", &outkey);
635 
636 		if (EMPTYSTRING(outkey)) {
637 			cryptoerror(LOG_STDERR, gettext("A key filename "
638 			    "must be specified to create a certificate "
639 			    "request.\n"));
640 			return (PK_ERR_USAGE);
641 		}
642 	}
643 
644 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
645 		cryptoerror(LOG_STDERR,
646 		    gettext("Error parsing format string (%s).\n"), format);
647 		return (PK_ERR_USAGE);
648 	}
649 	if (format && fmt != KMF_FORMAT_ASN1 && fmt != KMF_FORMAT_PEM) {
650 		cryptoerror(LOG_STDERR,
651 		    gettext("CSR must be DER or PEM format.\n"));
652 		return (PK_ERR_USAGE);
653 	}
654 
655 	/*
656 	 * Check the subject name.
657 	 * If interactive is true, get it now interactively.
658 	 */
659 	if (interactive) {
660 		if (get_subname(&subname) != KMF_OK) {
661 			cryptoerror(LOG_STDERR, gettext("Failed to get the "
662 			    "subject name interactively.\n"));
663 			return (PK_ERR_USAGE);
664 		}
665 	} else {
666 		if (EMPTYSTRING(subject)) {
667 			cryptoerror(LOG_STDERR, gettext("A subject name or "
668 			    "-i must be specified to create a certificate "
669 			    "request.\n"));
670 			return (PK_ERR_USAGE);
671 		} else {
672 			subname = strdup(subject);
673 			if (subname == NULL) {
674 				cryptoerror(LOG_STDERR,
675 				    gettext("Out of memory.\n"));
676 				return (PK_ERR_SYSTEM);
677 			}
678 		}
679 	}
680 	if (altname != NULL) {
681 		rv = verify_altname(altname, &alttype, &altcrit);
682 		if (rv != KMF_OK) {
683 			cryptoerror(LOG_STDERR, gettext("Subject AltName "
684 			    "must be specified as a name=value pair. "
685 			    "See the man page for details."));
686 			goto end;
687 		} else {
688 			/* advance the altname past the '=' sign */
689 			char *p = strchr(altname, '=');
690 			if (p != NULL)
691 				altname = p + 1;
692 		}
693 	}
694 
695 	if (kustr != NULL) {
696 		rv = verify_keyusage(kustr, &kubits, &kucrit);
697 		if (rv != KMF_OK) {
698 			cryptoerror(LOG_STDERR, gettext("KeyUsage "
699 			    "must be specified as a comma-separated list. "
700 			    "See the man page for details."));
701 			goto end;
702 		}
703 	}
704 	if ((rv = Str2KeyType(keytype, &keyAlg, &sigAlg)) != 0) {
705 		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
706 		    keytype);
707 		goto end;
708 	}
709 
710 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
711 		if (tokenname == NULL || !strlen(tokenname)) {
712 			if (kstype == KMF_KEYSTORE_NSS) {
713 				tokenname = "internal";
714 			} else  {
715 				tokenname = PK_DEFAULT_PK11TOKEN;
716 			}
717 		}
718 
719 		(void) get_token_password(kstype, tokenname, &tokencred);
720 	}
721 
722 	if (kstype == KMF_KEYSTORE_NSS) {
723 		if (dir == NULL)
724 			dir = PK_DEFAULT_DIRECTORY;
725 
726 		rv = gencsr_nss(kmfhandle,
727 		    tokenname, subname, altname, alttype, altcrit,
728 		    certlabel, dir, prefix,
729 		    keyAlg, keylen, kubits, kucrit,
730 		    fmt, outcsr, &tokencred);
731 
732 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
733 		rv = gencsr_pkcs11(kmfhandle,
734 		    tokenname, subname, altname, alttype, altcrit,
735 		    certlabel, keyAlg, keylen,
736 		    kubits, kucrit, fmt, outcsr, &tokencred);
737 
738 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
739 		rv = gencsr_file(kmfhandle,
740 		    keyAlg, keylen, fmt, subname, altname,
741 		    alttype, altcrit, kubits, kucrit,
742 		    dir, outcsr, outkey);
743 	}
744 
745 end:
746 	if (rv != KMF_OK)
747 		display_error(kmfhandle, rv,
748 		    gettext("Error creating CSR or keypair"));
749 
750 	if (subname)
751 		free(subname);
752 
753 	if (tokencred.cred != NULL)
754 		free(tokencred.cred);
755 
756 	(void) kmf_finalize(kmfhandle);
757 	if (rv != KMF_OK)
758 		return (PK_ERR_USAGE);
759 
760 	return (0);
761 }
762