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