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