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