xref: /illumos-gate/usr/src/cmd/cmd-crypto/pktool/gencsr.c (revision 6d1d45ee7157107ef92303ea769d6d3fcf5dfcc8)
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 *dir, 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 	if (dir != NULL) {
217 		fullcsrpath = get_fullpath(dir, outcsr);
218 		if (fullcsrpath == NULL) {
219 			cryptoerror(LOG_STDERR,
220 			    gettext("Cannot create file %s in "
221 			    "directory %s\n"), dir, outcsr);
222 			return (PK_ERR_USAGE);
223 		}
224 	} else {
225 		fullcsrpath = strdup(outcsr);
226 	}
227 	if (verify_file(fullcsrpath)) {
228 		cryptoerror(LOG_STDERR,
229 		    gettext("Cannot write the indicated output "
230 		    "certificate file (%s).\n"), fullcsrpath);
231 		free(fullcsrpath);
232 		return (PK_ERR_USAGE);
233 	}
234 	if (dir != NULL) {
235 		fullkeypath = get_fullpath(dir, outkey);
236 		if (fullkeypath == NULL) {
237 			cryptoerror(LOG_STDERR,
238 			    gettext("Cannot create file %s in "
239 			    "directory %s\n"), dir, outkey);
240 			free(fullcsrpath);
241 			return (PK_ERR_USAGE);
242 		}
243 	} else {
244 		fullkeypath = strdup(outkey);
245 	}
246 	if (verify_file(fullcsrpath)) {
247 		cryptoerror(LOG_STDERR,
248 		    gettext("Cannot write the indicated output "
249 		    "key file (%s).\n"), fullkeypath);
250 		free(fullcsrpath);
251 		return (PK_ERR_USAGE);
252 	}
253 
254 	if (keyAlg == KMF_DSA)
255 		sigAlg = KMF_ALGID_SHA1WithDSA;
256 	else
257 		sigAlg = KMF_ALGID_MD5WithRSA;
258 
259 	/* If the subject name cannot be parsed, flag it now and exit */
260 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
261 		return (kmfrv);
262 	}
263 
264 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
265 	    &kstype, sizeof (kstype));
266 	numattr++;
267 
268 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
269 	    fullkeypath, strlen(fullkeypath));
270 	numattr++;
271 
272 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR,
273 	    &keylen, sizeof (keylen));
274 	numattr++;
275 
276 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR,
277 	    &keyAlg, sizeof (keyAlg));
278 	numattr++;
279 
280 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
281 	    &fmt, sizeof (fmt));
282 	numattr++;
283 
284 	(void) memset(&prik, 0, sizeof (prik));
285 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR,
286 	    &prik, sizeof (KMF_KEY_HANDLE));
287 	numattr++;
288 
289 	(void) memset(&pubk, 0, sizeof (pubk));
290 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
291 	    &pubk, sizeof (KMF_KEY_HANDLE));
292 	numattr++;
293 
294 	kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR,
295 	    &storekey, sizeof (storekey));
296 	numattr++;
297 
298 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
299 	if (kmfrv != KMF_OK) {
300 		goto cleanup;
301 	}
302 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
303 	    "SetCSRPubKey");
304 
305 	SET_VALUE(kmf_set_csr_version(&csr, 2), "SetCSRVersion");
306 
307 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
308 	    "kmf_set_csr_subject");
309 
310 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");
311 
312 	if (altname != NULL) {
313 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
314 		    alttype), "kmf_set_csr_subject_altname");
315 	}
316 	if (kubits != NULL) {
317 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
318 		    "kmf_set_csr_ku");
319 	}
320 	if (ekulist != NULL) {
321 		int i;
322 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
323 			SET_VALUE(kmf_add_csr_eku(&csr,
324 			    &ekulist->ekulist[i],
325 			    ekulist->critlist[i]),
326 			    "Extended Key Usage");
327 		}
328 	}
329 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
330 	    KMF_OK) {
331 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, fullcsrpath);
332 	}
333 
334 cleanup:
335 	if (fullkeypath)
336 		free(fullkeypath);
337 	if (fullcsrpath)
338 		free(fullcsrpath);
339 
340 	kmf_free_data(&signedCsr);
341 	kmf_free_kmf_key(kmfhandle, &prik);
342 	kmf_free_signed_csr(&csr);
343 
344 	return (kmfrv);
345 }
346 
347 static KMF_RETURN
348 gencsr_nss(KMF_HANDLE_T kmfhandle,
349 	char *token, char *subject, char *altname,
350 	KMF_GENERALNAMECHOICES alttype, int altcrit,
351 	char *nickname, char *dir, char *prefix,
352 	KMF_KEY_ALG keyAlg, int keylen,
353 	uint16_t kubits, int kucrit,
354 	KMF_ENCODE_FORMAT fmt, char *csrfile,
355 	KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist)
356 {
357 	KMF_RETURN kmfrv;
358 	KMF_KEY_HANDLE pubk, prik;
359 	KMF_X509_NAME	csrSubject;
360 	KMF_CSR_DATA	csr;
361 	KMF_ALGORITHM_INDEX sigAlg;
362 	KMF_DATA signedCsr = {NULL, 0};
363 
364 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
365 	int numattr = 0;
366 	KMF_ATTRIBUTE attrlist[16];
367 	boolean_t storekey = TRUE;
368 
369 	if (token == NULL)
370 		token = DEFAULT_NSS_TOKEN;
371 
372 	if (keyAlg == KMF_DSA)
373 		sigAlg = KMF_ALGID_SHA1WithDSA;
374 	else
375 		sigAlg = KMF_ALGID_MD5WithRSA;
376 
377 	kmfrv = configure_nss(kmfhandle, dir, prefix);
378 	if (kmfrv != KMF_OK)
379 		return (kmfrv);
380 
381 	(void) memset(&csr, 0, sizeof (csr));
382 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
383 
384 	/* If the subject name cannot be parsed, flag it now and exit */
385 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
386 		return (kmfrv);
387 	}
388 
389 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
390 	    &kstype, sizeof (kstype));
391 	numattr++;
392 
393 	if (nickname != NULL && strlen(nickname)) {
394 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
395 		    nickname, strlen(nickname));
396 		numattr++;
397 	}
398 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR,
399 	    &keylen, sizeof (keylen));
400 	numattr++;
401 
402 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR,
403 	    &keyAlg, sizeof (keyAlg));
404 	numattr++;
405 
406 	if (tokencred != NULL && tokencred->credlen > 0) {
407 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
408 		    tokencred, sizeof (KMF_CREDENTIAL));
409 		numattr++;
410 	}
411 
412 	if (token && strlen(token)) {
413 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
414 		    token, strlen(token));
415 		numattr++;
416 	}
417 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
418 	    &pubk, sizeof (KMF_KEY_HANDLE));
419 	numattr++;
420 
421 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR,
422 	    &prik, sizeof (KMF_KEY_HANDLE));
423 	numattr++;
424 
425 	kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR,
426 	    &storekey, sizeof (storekey));
427 	numattr++;
428 
429 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
430 	if (kmfrv != KMF_OK) {
431 		goto cleanup;
432 	}
433 
434 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
435 	    "kmf_set_csr_pubkey");
436 	SET_VALUE(kmf_set_csr_version(&csr, 2), "kmf_set_csr_version");
437 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
438 	    "kmf_set_csr_subject");
439 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");
440 
441 	if (altname != NULL) {
442 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
443 		    alttype), "kmf_set_csr_subject_altname");
444 	}
445 	if (kubits != NULL) {
446 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
447 		    "kmf_set_csr_ku");
448 	}
449 	if (ekulist != NULL) {
450 		int i;
451 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
452 			SET_VALUE(kmf_add_csr_eku(&csr,
453 			    &ekulist->ekulist[i],
454 			    ekulist->critlist[i]),
455 			    "Extended Key Usage");
456 		}
457 	}
458 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
459 	    KMF_OK) {
460 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile);
461 	}
462 
463 cleanup:
464 	(void) kmf_free_data(&signedCsr);
465 	(void) kmf_free_kmf_key(kmfhandle, &prik);
466 
467 	/* delete the key */
468 	numattr = 0;
469 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
470 	    &kstype, sizeof (kstype));
471 	numattr++;
472 
473 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
474 	    &pubk, sizeof (KMF_KEY_HANDLE));
475 	numattr++;
476 
477 	if (tokencred != NULL && tokencred->credlen > 0) {
478 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
479 		    tokencred, sizeof (KMF_CREDENTIAL));
480 		numattr++;
481 	}
482 
483 	if (token && strlen(token)) {
484 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
485 		    token, strlen(token));
486 		numattr++;
487 	}
488 
489 	(void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist);
490 
491 	(void) kmf_free_signed_csr(&csr);
492 
493 	return (kmfrv);
494 }
495 
496 int
497 pk_gencsr(int argc, char *argv[])
498 {
499 	KMF_RETURN rv;
500 	int opt;
501 	extern int	optind_av;
502 	extern char	*optarg_av;
503 	KMF_KEYSTORE_TYPE kstype = 0;
504 	char *subject = NULL;
505 	char *tokenname = NULL;
506 	char *dir = NULL;
507 	char *prefix = NULL;
508 	int keylen = PK_DEFAULT_KEYLENGTH;
509 	char *certlabel = NULL;
510 	char *outcsr = NULL;
511 	char *outkey = NULL;
512 	char *format = NULL;
513 	char *altname = NULL;
514 	char *kustr = NULL;
515 	char *ekustr = NULL;
516 	uint16_t kubits = 0;
517 	char *keytype = PK_DEFAULT_KEYTYPE;
518 	KMF_HANDLE_T kmfhandle = NULL;
519 	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
520 	KMF_KEY_ALG keyAlg = KMF_RSA;
521 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA;
522 	boolean_t interactive = B_FALSE;
523 	char *subname = NULL;
524 	KMF_CREDENTIAL tokencred = {NULL, 0};
525 	KMF_GENERALNAMECHOICES alttype = 0;
526 	int altcrit = 0, kucrit = 0;
527 	EKU_LIST *ekulist = NULL;
528 
529 	while ((opt = getopt_av(argc, argv,
530 	    "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
531 	    "u:(keyusage)T:(token)d:(dir)p:(prefix)t:(keytype)"
532 	    "y:(keylen)l:(label)c:(outcsr)e:(eku)"
533 	    "K:(outkey)F:(format)")) != EOF) {
534 
535 		if (opt != 'i' && EMPTYSTRING(optarg_av))
536 			return (PK_ERR_USAGE);
537 
538 		switch (opt) {
539 			case 'A':
540 				altname = optarg_av;
541 				break;
542 			case 'i':
543 				if (interactive || subject)
544 					return (PK_ERR_USAGE);
545 				else
546 					interactive = B_TRUE;
547 				break;
548 			case 'k':
549 				kstype = KS2Int(optarg_av);
550 				if (kstype == 0)
551 					return (PK_ERR_USAGE);
552 				break;
553 			case 's':
554 				if (interactive || subject)
555 					return (PK_ERR_USAGE);
556 				else
557 					subject = optarg_av;
558 				break;
559 			case 'l':
560 			case 'n':
561 				if (certlabel)
562 					return (PK_ERR_USAGE);
563 				certlabel = optarg_av;
564 				break;
565 			case 'T':
566 				if (tokenname)
567 					return (PK_ERR_USAGE);
568 				tokenname = optarg_av;
569 				break;
570 			case 'd':
571 				dir = optarg_av;
572 				break;
573 			case 'p':
574 				if (prefix)
575 					return (PK_ERR_USAGE);
576 				prefix = optarg_av;
577 				break;
578 			case 't':
579 				keytype = optarg_av;
580 				break;
581 			case 'u':
582 				kustr = optarg_av;
583 				break;
584 			case 'y':
585 				if (sscanf(optarg_av, "%d",
586 				    &keylen) != 1) {
587 					cryptoerror(LOG_STDERR,
588 					    gettext("Unrecognized "
589 					    "key length (%s)\n"), optarg_av);
590 					return (PK_ERR_USAGE);
591 				}
592 				break;
593 			case 'c':
594 				if (outcsr)
595 					return (PK_ERR_USAGE);
596 				outcsr = optarg_av;
597 				break;
598 			case 'K':
599 				if (outkey)
600 					return (PK_ERR_USAGE);
601 				outkey = optarg_av;
602 				break;
603 			case 'F':
604 				if (format)
605 					return (PK_ERR_USAGE);
606 				format = optarg_av;
607 				break;
608 			case 'e':
609 				ekustr = optarg_av;
610 				break;
611 			default:
612 				cryptoerror(LOG_STDERR, gettext(
613 				    "unrecognized gencsr option '%s'\n"),
614 				    argv[optind_av]);
615 				return (PK_ERR_USAGE);
616 		}
617 	}
618 	/* No additional args allowed. */
619 	argc -= optind_av;
620 	argv += optind_av;
621 	if (argc) {
622 		return (PK_ERR_USAGE);
623 	}
624 
625 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
626 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
627 		return (PK_ERR_USAGE);
628 	}
629 
630 	/* Assume keystore = PKCS#11 if not specified. */
631 	if (kstype == 0)
632 		kstype = KMF_KEYSTORE_PK11TOKEN;
633 
634 	if (EMPTYSTRING(outcsr) && interactive) {
635 		(void) get_filename("CSR", &outcsr);
636 	}
637 	if (EMPTYSTRING(outcsr)) {
638 		(void) printf(gettext("A filename must be specified to hold"
639 		    "the final certificate request data.\n"));
640 		return (PK_ERR_USAGE);
641 	}
642 	/*
643 	 * verify that the outcsr file does not already exist
644 	 * and that it can be created.
645 	 */
646 	rv = verify_file(outcsr);
647 	if (rv != KMF_OK) {
648 		cryptoerror(LOG_STDERR, gettext("output file (%s) "
649 		    "cannot be created.\n"), outcsr);
650 		return (PK_ERR_USAGE);
651 	}
652 
653 	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) {
654 		if (EMPTYSTRING(certlabel) && interactive)
655 			(void) get_certlabel(&certlabel);
656 
657 		if (EMPTYSTRING(certlabel)) {
658 			cryptoerror(LOG_STDERR, gettext("A label must be "
659 			    "specified to create a certificate request.\n"));
660 			return (PK_ERR_USAGE);
661 		}
662 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
663 		if (EMPTYSTRING(outkey) && interactive)
664 			(void) get_filename("private key", &outkey);
665 
666 		if (EMPTYSTRING(outkey)) {
667 			cryptoerror(LOG_STDERR, gettext("A key filename "
668 			    "must be specified to create a certificate "
669 			    "request.\n"));
670 			return (PK_ERR_USAGE);
671 		}
672 	}
673 
674 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
675 		cryptoerror(LOG_STDERR,
676 		    gettext("Error parsing format string (%s).\n"), format);
677 		return (PK_ERR_USAGE);
678 	}
679 	if (format && fmt != KMF_FORMAT_ASN1 && fmt != KMF_FORMAT_PEM) {
680 		cryptoerror(LOG_STDERR,
681 		    gettext("CSR must be DER or PEM format.\n"));
682 		return (PK_ERR_USAGE);
683 	}
684 
685 	/*
686 	 * Check the subject name.
687 	 * If interactive is true, get it now interactively.
688 	 */
689 	if (interactive) {
690 		if (get_subname(&subname) != KMF_OK) {
691 			cryptoerror(LOG_STDERR, gettext("Failed to get the "
692 			    "subject name interactively.\n"));
693 			return (PK_ERR_USAGE);
694 		}
695 	} else {
696 		if (EMPTYSTRING(subject)) {
697 			cryptoerror(LOG_STDERR, gettext("A subject name or "
698 			    "-i must be specified to create a certificate "
699 			    "request.\n"));
700 			return (PK_ERR_USAGE);
701 		} else {
702 			subname = strdup(subject);
703 			if (subname == NULL) {
704 				cryptoerror(LOG_STDERR,
705 				    gettext("Out of memory.\n"));
706 				return (PK_ERR_SYSTEM);
707 			}
708 		}
709 	}
710 	if (altname != NULL) {
711 		rv = verify_altname(altname, &alttype, &altcrit);
712 		if (rv != KMF_OK) {
713 			cryptoerror(LOG_STDERR, gettext("Subject AltName "
714 			    "must be specified as a name=value pair. "
715 			    "See the man page for details."));
716 			goto end;
717 		} else {
718 			/* advance the altname past the '=' sign */
719 			char *p = strchr(altname, '=');
720 			if (p != NULL)
721 				altname = p + 1;
722 		}
723 	}
724 
725 	if (kustr != NULL) {
726 		rv = verify_keyusage(kustr, &kubits, &kucrit);
727 		if (rv != KMF_OK) {
728 			cryptoerror(LOG_STDERR, gettext("KeyUsage "
729 			    "must be specified as a comma-separated list. "
730 			    "See the man page for details."));
731 			goto end;
732 		}
733 	}
734 	if (ekustr != NULL) {
735 		rv = verify_ekunames(ekustr, &ekulist);
736 		if (rv != KMF_OK) {
737 			(void) fprintf(stderr, gettext("EKUs must "
738 			    "be specified as a comma-separated list. "
739 			    "See the man page for details.\n"));
740 			rv = PK_ERR_USAGE;
741 			goto end;
742 		}
743 	}
744 
745 
746 	if ((rv = Str2KeyType(keytype, &keyAlg, &sigAlg)) != 0) {
747 		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
748 		    keytype);
749 		goto end;
750 	}
751 
752 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
753 		if (tokenname == NULL || !strlen(tokenname)) {
754 			if (kstype == KMF_KEYSTORE_NSS) {
755 				tokenname = "internal";
756 			} else  {
757 				tokenname = PK_DEFAULT_PK11TOKEN;
758 			}
759 		}
760 
761 		(void) get_token_password(kstype, tokenname, &tokencred);
762 	}
763 
764 	if (kstype == KMF_KEYSTORE_NSS) {
765 		if (dir == NULL)
766 			dir = PK_DEFAULT_DIRECTORY;
767 
768 		rv = gencsr_nss(kmfhandle,
769 		    tokenname, subname, altname, alttype, altcrit,
770 		    certlabel, dir, prefix,
771 		    keyAlg, keylen, kubits, kucrit,
772 		    fmt, outcsr, &tokencred, ekulist);
773 
774 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
775 		rv = gencsr_pkcs11(kmfhandle,
776 		    tokenname, subname, altname, alttype, altcrit,
777 		    certlabel, keyAlg, keylen,
778 		    kubits, kucrit, fmt, outcsr, &tokencred, ekulist);
779 
780 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
781 		rv = gencsr_file(kmfhandle,
782 		    keyAlg, keylen, fmt, subname, altname,
783 		    alttype, altcrit, kubits, kucrit,
784 		    dir, outcsr, outkey, ekulist);
785 	}
786 
787 end:
788 	if (rv != KMF_OK)
789 		display_error(kmfhandle, rv,
790 		    gettext("Error creating CSR or keypair"));
791 
792 	if (ekulist != NULL)
793 		free_eku_list(ekulist);
794 
795 	if (subname)
796 		free(subname);
797 
798 	if (tokencred.cred != NULL)
799 		free(tokencred.cred);
800 
801 	(void) kmf_finalize(kmfhandle);
802 	if (rv != KMF_OK)
803 		return (PK_ERR_USAGE);
804 
805 	return (0);
806 }
807