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