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