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