xref: /titanic_52/usr/src/cmd/cmd-crypto/pktool/gencert.c (revision 99ebb4ca412cb0a19d77a3899a87c055b9c30fa8)
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 set %s: 0x%02x\n"), \
45*99ebb4caSwyllys 			s, kmfrv); \
46*99ebb4caSwyllys 		goto cleanup; \
47*99ebb4caSwyllys 	}
48*99ebb4caSwyllys 
49*99ebb4caSwyllys static int
50*99ebb4caSwyllys gencert_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 	KMF_ALGORITHM_INDEX sigAlg,
55*99ebb4caSwyllys 	int keylen, uint32_t ltime, KMF_BIGINT *serial,
56*99ebb4caSwyllys 	uint16_t kubits, int kucrit, KMF_CREDENTIAL *tokencred)
57*99ebb4caSwyllys {
58*99ebb4caSwyllys 	KMF_RETURN kmfrv = KMF_OK;
59*99ebb4caSwyllys 	KMF_CREATEKEYPAIR_PARAMS kp_params;
60*99ebb4caSwyllys 	KMF_STORECERT_PARAMS sc_params;
61*99ebb4caSwyllys 	KMF_KEY_HANDLE pubk, prik;
62*99ebb4caSwyllys 	KMF_X509_CERTIFICATE signedCert;
63*99ebb4caSwyllys 	KMF_X509_NAME	certSubject;
64*99ebb4caSwyllys 	KMF_X509_NAME	certIssuer;
65*99ebb4caSwyllys 	KMF_DATA x509DER;
66*99ebb4caSwyllys 
67*99ebb4caSwyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
68*99ebb4caSwyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
69*99ebb4caSwyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
70*99ebb4caSwyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
71*99ebb4caSwyllys 	(void) memset(&kp_params, 0, sizeof (kp_params));
72*99ebb4caSwyllys 
73*99ebb4caSwyllys 	/* If the subject name cannot be parsed, flag it now and exit */
74*99ebb4caSwyllys 	if (KMF_DNParser(subject, &certSubject) != KMF_OK) {
75*99ebb4caSwyllys 		cryptoerror(LOG_STDERR,
76*99ebb4caSwyllys 			gettext("Subject name cannot be parsed.\n"));
77*99ebb4caSwyllys 		return (PK_ERR_USAGE);
78*99ebb4caSwyllys 	}
79*99ebb4caSwyllys 
80*99ebb4caSwyllys 	/* For a self-signed cert, the issuser and subject are the same */
81*99ebb4caSwyllys 	if (KMF_DNParser(subject, &certIssuer) != KMF_OK) {
82*99ebb4caSwyllys 		cryptoerror(LOG_STDERR,
83*99ebb4caSwyllys 			gettext("Subject name cannot be parsed.\n"));
84*99ebb4caSwyllys 		return (PK_ERR_USAGE);
85*99ebb4caSwyllys 	}
86*99ebb4caSwyllys 
87*99ebb4caSwyllys 	kp_params.kstype = KMF_KEYSTORE_PK11TOKEN;
88*99ebb4caSwyllys 	kp_params.keylabel = certlabel;
89*99ebb4caSwyllys 	kp_params.keylength = keylen; /* bits */
90*99ebb4caSwyllys 	kp_params.keytype = keyAlg;
91*99ebb4caSwyllys 	kp_params.cred.cred = tokencred->cred;
92*99ebb4caSwyllys 	kp_params.cred.credlen = tokencred->credlen;
93*99ebb4caSwyllys 
94*99ebb4caSwyllys 	/* Select a PKCS11 token */
95*99ebb4caSwyllys 	kmfrv = select_token(kmfhandle, token, FALSE);
96*99ebb4caSwyllys 
97*99ebb4caSwyllys 	if (kmfrv != KMF_OK) {
98*99ebb4caSwyllys 		return (kmfrv);
99*99ebb4caSwyllys 	}
100*99ebb4caSwyllys 
101*99ebb4caSwyllys 	kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk);
102*99ebb4caSwyllys 	if (kmfrv != KMF_OK) {
103*99ebb4caSwyllys 		return (kmfrv);
104*99ebb4caSwyllys 	}
105*99ebb4caSwyllys 
106*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertPubKey(kmfhandle, &pubk, &signedCert),
107*99ebb4caSwyllys 			"keypair");
108*99ebb4caSwyllys 
109*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertVersion(&signedCert, 2), "version number");
110*99ebb4caSwyllys 
111*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertSerialNumber(&signedCert, serial),
112*99ebb4caSwyllys 			"serial number");
113*99ebb4caSwyllys 
114*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertValidityTimes(&signedCert, NULL, ltime),
115*99ebb4caSwyllys 		"validity time");
116*99ebb4caSwyllys 
117*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertSignatureAlgorithm(&signedCert, sigAlg),
118*99ebb4caSwyllys 		"signature algorithm");
119*99ebb4caSwyllys 
120*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertSubjectName(&signedCert, &certSubject),
121*99ebb4caSwyllys 		"subject name");
122*99ebb4caSwyllys 
123*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertIssuerName(&signedCert, &certIssuer),
124*99ebb4caSwyllys 		"issuer name");
125*99ebb4caSwyllys 
126*99ebb4caSwyllys 	if (altname != NULL)
127*99ebb4caSwyllys 		SET_VALUE(KMF_SetCertSubjectAltName(&signedCert, altcrit,
128*99ebb4caSwyllys 			alttype, altname), "subjectAltName");
129*99ebb4caSwyllys 
130*99ebb4caSwyllys 	if (kubits != 0)
131*99ebb4caSwyllys 		SET_VALUE(KMF_SetCertKeyUsage(&signedCert, kucrit, kubits),
132*99ebb4caSwyllys 			"KeyUsage");
133*99ebb4caSwyllys 
134*99ebb4caSwyllys 	if ((kmfrv = KMF_SignCertRecord(kmfhandle, &prik,
135*99ebb4caSwyllys 		&signedCert, &x509DER)) != KMF_OK) {
136*99ebb4caSwyllys 		goto cleanup;
137*99ebb4caSwyllys 	}
138*99ebb4caSwyllys 
139*99ebb4caSwyllys 	(void) memset(&sc_params, 0, sizeof (sc_params));
140*99ebb4caSwyllys 	sc_params.kstype = KMF_KEYSTORE_PK11TOKEN;
141*99ebb4caSwyllys 	sc_params.certLabel = certlabel;
142*99ebb4caSwyllys 
143*99ebb4caSwyllys 	/*
144*99ebb4caSwyllys 	 * Store the cert in the DB.
145*99ebb4caSwyllys 	 */
146*99ebb4caSwyllys 	kmfrv = KMF_StoreCert(kmfhandle, &sc_params, &x509DER);
147*99ebb4caSwyllys 
148*99ebb4caSwyllys cleanup:
149*99ebb4caSwyllys 	KMF_FreeData(&x509DER);
150*99ebb4caSwyllys 	KMF_FreeDN(&certSubject);
151*99ebb4caSwyllys 	KMF_FreeDN(&certIssuer);
152*99ebb4caSwyllys 	return (kmfrv);
153*99ebb4caSwyllys }
154*99ebb4caSwyllys 
155*99ebb4caSwyllys static int
156*99ebb4caSwyllys gencert_file(KMF_HANDLE_T kmfhandle,
157*99ebb4caSwyllys 	KMF_KEY_ALG keyAlg, KMF_ALGORITHM_INDEX sigAlg,
158*99ebb4caSwyllys 	int keylen, KMF_ENCODE_FORMAT fmt,
159*99ebb4caSwyllys 	uint32_t ltime, char *subject, char *altname,
160*99ebb4caSwyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
161*99ebb4caSwyllys 	KMF_BIGINT *serial, uint16_t kubits, int kucrit,
162*99ebb4caSwyllys 	char *dir, char *outcert, char *outkey)
163*99ebb4caSwyllys {
164*99ebb4caSwyllys 	KMF_RETURN kmfrv;
165*99ebb4caSwyllys 	KMF_CREATEKEYPAIR_PARAMS kp_params;
166*99ebb4caSwyllys 	KMF_STORECERT_PARAMS sc_params;
167*99ebb4caSwyllys 	KMF_KEY_HANDLE pubk, prik;
168*99ebb4caSwyllys 	KMF_X509_CERTIFICATE signedCert;
169*99ebb4caSwyllys 	KMF_X509_NAME	certSubject;
170*99ebb4caSwyllys 	KMF_X509_NAME	certIssuer;
171*99ebb4caSwyllys 	KMF_DATA x509DER;
172*99ebb4caSwyllys 	char *fullcertpath = NULL;
173*99ebb4caSwyllys 	char *fullkeypath = NULL;
174*99ebb4caSwyllys 
175*99ebb4caSwyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
176*99ebb4caSwyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
177*99ebb4caSwyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
178*99ebb4caSwyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
179*99ebb4caSwyllys 	(void) memset(&kp_params, 0, sizeof (kp_params));
180*99ebb4caSwyllys 	(void) memset(&sc_params, 0, sizeof (sc_params));
181*99ebb4caSwyllys 
182*99ebb4caSwyllys 	if (EMPTYSTRING(outcert) || EMPTYSTRING(outkey)) {
183*99ebb4caSwyllys 		cryptoerror(LOG_STDERR,
184*99ebb4caSwyllys 			gettext("No output file was specified for "
185*99ebb4caSwyllys 				"the cert or key\n"));
186*99ebb4caSwyllys 		return (PK_ERR_USAGE);
187*99ebb4caSwyllys 	}
188*99ebb4caSwyllys 	if (dir != NULL) {
189*99ebb4caSwyllys 		fullcertpath = get_fullpath(dir, outcert);
190*99ebb4caSwyllys 		if (fullcertpath == NULL) {
191*99ebb4caSwyllys 			cryptoerror(LOG_STDERR,
192*99ebb4caSwyllys 				gettext("Cannot create file %s in "
193*99ebb4caSwyllys 					"directory %s\n"), dir, outcert);
194*99ebb4caSwyllys 			return (PK_ERR_USAGE);
195*99ebb4caSwyllys 		}
196*99ebb4caSwyllys 	} else {
197*99ebb4caSwyllys 		fullcertpath = strdup(outcert);
198*99ebb4caSwyllys 	}
199*99ebb4caSwyllys 	if (verify_file(fullcertpath)) {
200*99ebb4caSwyllys 		cryptoerror(LOG_STDERR,
201*99ebb4caSwyllys 			gettext("Cannot write the indicated output "
202*99ebb4caSwyllys 				"certificate file (%s).\n"),
203*99ebb4caSwyllys 				fullcertpath);
204*99ebb4caSwyllys 		free(fullcertpath);
205*99ebb4caSwyllys 		return (PK_ERR_USAGE);
206*99ebb4caSwyllys 	}
207*99ebb4caSwyllys 	if (dir != NULL) {
208*99ebb4caSwyllys 		fullkeypath = get_fullpath(dir, outkey);
209*99ebb4caSwyllys 		if (fullkeypath == NULL) {
210*99ebb4caSwyllys 			cryptoerror(LOG_STDERR,
211*99ebb4caSwyllys 				gettext("Cannot create file %s in "
212*99ebb4caSwyllys 					"directory %s\n"), dir, outkey);
213*99ebb4caSwyllys 			free(fullcertpath);
214*99ebb4caSwyllys 			return (PK_ERR_USAGE);
215*99ebb4caSwyllys 		}
216*99ebb4caSwyllys 	} else {
217*99ebb4caSwyllys 		fullkeypath = strdup(outkey);
218*99ebb4caSwyllys 	}
219*99ebb4caSwyllys 	if (verify_file(fullkeypath)) {
220*99ebb4caSwyllys 		cryptoerror(LOG_STDERR,
221*99ebb4caSwyllys 			gettext("Cannot write the indicated output "
222*99ebb4caSwyllys 				"key file (%s).\n"),
223*99ebb4caSwyllys 				fullkeypath);
224*99ebb4caSwyllys 		free(fullkeypath);
225*99ebb4caSwyllys 		free(fullcertpath);
226*99ebb4caSwyllys 		return (PK_ERR_USAGE);
227*99ebb4caSwyllys 	}
228*99ebb4caSwyllys 
229*99ebb4caSwyllys 	/* If the subject name cannot be parsed, flag it now and exit */
230*99ebb4caSwyllys 	if (KMF_DNParser(subject, &certSubject) != KMF_OK) {
231*99ebb4caSwyllys 		cryptoerror(LOG_STDERR,
232*99ebb4caSwyllys 			gettext("Subject name cannot be parsed (%s)\n"),
233*99ebb4caSwyllys 			subject);
234*99ebb4caSwyllys 		return (PK_ERR_USAGE);
235*99ebb4caSwyllys 	}
236*99ebb4caSwyllys 
237*99ebb4caSwyllys 	/* For a self-signed cert, the issuser and subject are the same */
238*99ebb4caSwyllys 	if (KMF_DNParser(subject, &certIssuer) != KMF_OK) {
239*99ebb4caSwyllys 		cryptoerror(LOG_STDERR,
240*99ebb4caSwyllys 			gettext("Subject name cannot be parsed (%s)\n"),
241*99ebb4caSwyllys 			subject);
242*99ebb4caSwyllys 		KMF_FreeDN(&certSubject);
243*99ebb4caSwyllys 		return (PK_ERR_USAGE);
244*99ebb4caSwyllys 	}
245*99ebb4caSwyllys 
246*99ebb4caSwyllys 	kp_params.kstype = KMF_KEYSTORE_OPENSSL;
247*99ebb4caSwyllys 	kp_params.keylength = keylen; /* bits */
248*99ebb4caSwyllys 	kp_params.keytype = keyAlg;
249*99ebb4caSwyllys 
250*99ebb4caSwyllys 	kp_params.sslparms.keyfile = fullkeypath;
251*99ebb4caSwyllys 	kp_params.sslparms.format = fmt;
252*99ebb4caSwyllys 
253*99ebb4caSwyllys 	kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk);
254*99ebb4caSwyllys 	if (kmfrv != KMF_OK) {
255*99ebb4caSwyllys 		goto cleanup;
256*99ebb4caSwyllys 	}
257*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertPubKey(kmfhandle, &pubk, &signedCert),
258*99ebb4caSwyllys 		"keypair");
259*99ebb4caSwyllys 
260*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertVersion(&signedCert, 2), "version number");
261*99ebb4caSwyllys 
262*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertSerialNumber(&signedCert, serial),
263*99ebb4caSwyllys 		"serial number");
264*99ebb4caSwyllys 
265*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertValidityTimes(&signedCert, NULL, ltime),
266*99ebb4caSwyllys 		"validity time");
267*99ebb4caSwyllys 
268*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertSignatureAlgorithm(&signedCert, sigAlg),
269*99ebb4caSwyllys 		"signature algorithm");
270*99ebb4caSwyllys 
271*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertSubjectName(&signedCert, &certSubject),
272*99ebb4caSwyllys 		"subject name");
273*99ebb4caSwyllys 
274*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertIssuerName(&signedCert, &certIssuer),
275*99ebb4caSwyllys 		"issuer name");
276*99ebb4caSwyllys 
277*99ebb4caSwyllys 	if (altname != NULL)
278*99ebb4caSwyllys 		SET_VALUE(KMF_SetCertSubjectAltName(&signedCert, altcrit,
279*99ebb4caSwyllys 			alttype, altname), "subjectAltName");
280*99ebb4caSwyllys 
281*99ebb4caSwyllys 	if (kubits != 0)
282*99ebb4caSwyllys 		SET_VALUE(KMF_SetCertKeyUsage(&signedCert, kucrit, kubits),
283*99ebb4caSwyllys 			"KeyUsage");
284*99ebb4caSwyllys 
285*99ebb4caSwyllys 	if ((kmfrv = KMF_SignCertRecord(kmfhandle, &prik,
286*99ebb4caSwyllys 		&signedCert, &x509DER)) != KMF_OK) {
287*99ebb4caSwyllys 		goto cleanup;
288*99ebb4caSwyllys 	}
289*99ebb4caSwyllys 
290*99ebb4caSwyllys 	sc_params.kstype = KMF_KEYSTORE_OPENSSL;
291*99ebb4caSwyllys 	sc_params.sslparms.certfile = fullcertpath;
292*99ebb4caSwyllys 	sc_params.sslparms.keyfile = fullkeypath;
293*99ebb4caSwyllys 	sc_params.sslparms.format = fmt;
294*99ebb4caSwyllys 	/*
295*99ebb4caSwyllys 	 * Store the cert in the DB.
296*99ebb4caSwyllys 	 */
297*99ebb4caSwyllys 	kmfrv = KMF_StoreCert(kmfhandle, &sc_params, &x509DER);
298*99ebb4caSwyllys 
299*99ebb4caSwyllys cleanup:
300*99ebb4caSwyllys 	if (fullkeypath != NULL)
301*99ebb4caSwyllys 		free(fullkeypath);
302*99ebb4caSwyllys 	if (fullcertpath != NULL)
303*99ebb4caSwyllys 		free(fullcertpath);
304*99ebb4caSwyllys 
305*99ebb4caSwyllys 	KMF_FreeData(&x509DER);
306*99ebb4caSwyllys 	KMF_FreeDN(&certSubject);
307*99ebb4caSwyllys 	KMF_FreeDN(&certIssuer);
308*99ebb4caSwyllys 	return (kmfrv);
309*99ebb4caSwyllys }
310*99ebb4caSwyllys 
311*99ebb4caSwyllys static KMF_RETURN
312*99ebb4caSwyllys gencert_nss(KMF_HANDLE_T kmfhandle,
313*99ebb4caSwyllys 	char *token, char *subject, char *altname,
314*99ebb4caSwyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
315*99ebb4caSwyllys 	char *nickname, char *dir, char *prefix,
316*99ebb4caSwyllys 	KMF_KEY_ALG keyAlg,
317*99ebb4caSwyllys 	KMF_ALGORITHM_INDEX sigAlg,
318*99ebb4caSwyllys 	int keylen, char *trust,
319*99ebb4caSwyllys 	uint32_t ltime, KMF_BIGINT *serial, uint16_t kubits,
320*99ebb4caSwyllys 	int kucrit, KMF_CREDENTIAL *tokencred)
321*99ebb4caSwyllys {
322*99ebb4caSwyllys 	KMF_RETURN kmfrv;
323*99ebb4caSwyllys 	KMF_CREATEKEYPAIR_PARAMS kp_params;
324*99ebb4caSwyllys 	KMF_STORECERT_PARAMS sc_params;
325*99ebb4caSwyllys 	KMF_KEY_HANDLE pubk, prik;
326*99ebb4caSwyllys 	KMF_X509_CERTIFICATE signedCert;
327*99ebb4caSwyllys 	KMF_X509_NAME	certSubject;
328*99ebb4caSwyllys 	KMF_X509_NAME	certIssuer;
329*99ebb4caSwyllys 	KMF_DATA x509DER;
330*99ebb4caSwyllys 
331*99ebb4caSwyllys 	if (token == NULL)
332*99ebb4caSwyllys 		token = DEFAULT_NSS_TOKEN;
333*99ebb4caSwyllys 
334*99ebb4caSwyllys 	kmfrv = configure_nss(kmfhandle, dir, prefix);
335*99ebb4caSwyllys 	if (kmfrv != KMF_OK)
336*99ebb4caSwyllys 		return (kmfrv);
337*99ebb4caSwyllys 
338*99ebb4caSwyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
339*99ebb4caSwyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
340*99ebb4caSwyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
341*99ebb4caSwyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
342*99ebb4caSwyllys 
343*99ebb4caSwyllys 	/* If the subject name cannot be parsed, flag it now and exit */
344*99ebb4caSwyllys 	if (KMF_DNParser(subject, &certSubject) != KMF_OK) {
345*99ebb4caSwyllys 		cryptoerror(LOG_STDERR,
346*99ebb4caSwyllys 			gettext("Subject name cannot be parsed.\n"));
347*99ebb4caSwyllys 		return (PK_ERR_USAGE);
348*99ebb4caSwyllys 	}
349*99ebb4caSwyllys 
350*99ebb4caSwyllys 	/* For a self-signed cert, the issuser and subject are the same */
351*99ebb4caSwyllys 	if (KMF_DNParser(subject, &certIssuer) != KMF_OK) {
352*99ebb4caSwyllys 		cryptoerror(LOG_STDERR,
353*99ebb4caSwyllys 			gettext("Subject name cannot be parsed.\n"));
354*99ebb4caSwyllys 		return (PK_ERR_USAGE);
355*99ebb4caSwyllys 	}
356*99ebb4caSwyllys 
357*99ebb4caSwyllys 	(void) memset(&kp_params, 0, sizeof (kp_params));
358*99ebb4caSwyllys 
359*99ebb4caSwyllys 	kp_params.kstype = KMF_KEYSTORE_NSS;
360*99ebb4caSwyllys 	kp_params.keylabel = nickname;
361*99ebb4caSwyllys 	kp_params.keylength = keylen; /* bits */
362*99ebb4caSwyllys 	kp_params.keytype = keyAlg;
363*99ebb4caSwyllys 	kp_params.cred.cred = tokencred->cred;
364*99ebb4caSwyllys 	kp_params.cred.credlen = tokencred->credlen;
365*99ebb4caSwyllys 	kp_params.nssparms.slotlabel = token;
366*99ebb4caSwyllys 
367*99ebb4caSwyllys 	kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk);
368*99ebb4caSwyllys 	if (kmfrv != KMF_OK) {
369*99ebb4caSwyllys 		return (kmfrv);
370*99ebb4caSwyllys 	}
371*99ebb4caSwyllys 
372*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertPubKey(kmfhandle, &pubk, &signedCert),
373*99ebb4caSwyllys 			"keypair");
374*99ebb4caSwyllys 
375*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertVersion(&signedCert, 2), "version number");
376*99ebb4caSwyllys 
377*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertSerialNumber(&signedCert, serial),
378*99ebb4caSwyllys 			"serial number");
379*99ebb4caSwyllys 
380*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertValidityTimes(&signedCert, NULL, ltime),
381*99ebb4caSwyllys 		"validity time");
382*99ebb4caSwyllys 
383*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertSignatureAlgorithm(&signedCert, sigAlg),
384*99ebb4caSwyllys 		"signature algorithm");
385*99ebb4caSwyllys 
386*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertSubjectName(&signedCert, &certSubject),
387*99ebb4caSwyllys 		"subject name");
388*99ebb4caSwyllys 
389*99ebb4caSwyllys 	SET_VALUE(KMF_SetCertIssuerName(&signedCert, &certIssuer),
390*99ebb4caSwyllys 		"issuer name");
391*99ebb4caSwyllys 
392*99ebb4caSwyllys 	if (altname != NULL)
393*99ebb4caSwyllys 		SET_VALUE(KMF_SetCertSubjectAltName(&signedCert, altcrit,
394*99ebb4caSwyllys 			alttype, altname), "subjectAltName");
395*99ebb4caSwyllys 
396*99ebb4caSwyllys 	if (kubits)
397*99ebb4caSwyllys 		SET_VALUE(KMF_SetCertKeyUsage(&signedCert, kucrit, kubits),
398*99ebb4caSwyllys 			"subjectAltName");
399*99ebb4caSwyllys 
400*99ebb4caSwyllys 	if ((kmfrv = KMF_SignCertRecord(kmfhandle, &prik,
401*99ebb4caSwyllys 		&signedCert, &x509DER)) != KMF_OK) {
402*99ebb4caSwyllys 		goto cleanup;
403*99ebb4caSwyllys 	}
404*99ebb4caSwyllys 
405*99ebb4caSwyllys 	sc_params.kstype = KMF_KEYSTORE_NSS;
406*99ebb4caSwyllys 	sc_params.certLabel = nickname;
407*99ebb4caSwyllys 	sc_params.nssparms.trustflag = trust;
408*99ebb4caSwyllys 	sc_params.nssparms.slotlabel = token;
409*99ebb4caSwyllys 
410*99ebb4caSwyllys 	/*
411*99ebb4caSwyllys 	 * Store the cert in the DB.
412*99ebb4caSwyllys 	 */
413*99ebb4caSwyllys 	kmfrv = KMF_StoreCert(kmfhandle, &sc_params, &x509DER);
414*99ebb4caSwyllys 
415*99ebb4caSwyllys cleanup:
416*99ebb4caSwyllys 	KMF_FreeData(&x509DER);
417*99ebb4caSwyllys 	KMF_FreeDN(&certSubject);
418*99ebb4caSwyllys 	KMF_FreeDN(&certIssuer);
419*99ebb4caSwyllys 	return (kmfrv);
420*99ebb4caSwyllys }
421*99ebb4caSwyllys 
422*99ebb4caSwyllys int
423*99ebb4caSwyllys pk_gencert(int argc, char *argv[])
424*99ebb4caSwyllys {
425*99ebb4caSwyllys 	int rv;
426*99ebb4caSwyllys 	int opt;
427*99ebb4caSwyllys 	extern int	optind_av;
428*99ebb4caSwyllys 	extern char	*optarg_av;
429*99ebb4caSwyllys 	KMF_KEYSTORE_TYPE kstype = 0;
430*99ebb4caSwyllys 	char *subject = NULL;
431*99ebb4caSwyllys 	char *tokenname = NULL;
432*99ebb4caSwyllys 	char *dir = NULL;
433*99ebb4caSwyllys 	char *prefix = NULL;
434*99ebb4caSwyllys 	char *keytype = PK_DEFAULT_KEYTYPE;
435*99ebb4caSwyllys 	int keylen = PK_DEFAULT_KEYLENGTH;
436*99ebb4caSwyllys 	char *trust = NULL;
437*99ebb4caSwyllys 	char *lifetime = NULL;
438*99ebb4caSwyllys 	char *certlabel = NULL;
439*99ebb4caSwyllys 	char *outcert = NULL;
440*99ebb4caSwyllys 	char *outkey = NULL;
441*99ebb4caSwyllys 	char *format = NULL;
442*99ebb4caSwyllys 	char *serstr = NULL;
443*99ebb4caSwyllys 	char *altname = NULL;
444*99ebb4caSwyllys 	char *keyusagestr = NULL;
445*99ebb4caSwyllys 	KMF_GENERALNAMECHOICES alttype = 0;
446*99ebb4caSwyllys 	KMF_BIGINT serial = { NULL, 0 };
447*99ebb4caSwyllys 	uint32_t ltime;
448*99ebb4caSwyllys 	KMF_HANDLE_T kmfhandle = NULL;
449*99ebb4caSwyllys 	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
450*99ebb4caSwyllys 	KMF_KEY_ALG keyAlg = KMF_RSA;
451*99ebb4caSwyllys 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA;
452*99ebb4caSwyllys 	boolean_t interactive = B_FALSE;
453*99ebb4caSwyllys 	char *subname = NULL;
454*99ebb4caSwyllys 	KMF_CREDENTIAL tokencred = {NULL, 0};
455*99ebb4caSwyllys 	uint16_t kubits = 0;
456*99ebb4caSwyllys 	int altcrit = 0, kucrit = 0;
457*99ebb4caSwyllys 
458*99ebb4caSwyllys 	while ((opt = getopt_av(argc, argv,
459*99ebb4caSwyllys 		"ik:(keystore)s:(subject)n:(nickname)A:(altname)"
460*99ebb4caSwyllys 		"T:(token)d:(dir)p:(prefix)t:(keytype)y:(keylen)"
461*99ebb4caSwyllys 		"r:(trust)L:(lifetime)l:(label)c:(outcert)"
462*99ebb4caSwyllys 		"K:(outkey)S:(serial)F:(format)u:(keyusage)")) != EOF) {
463*99ebb4caSwyllys 
464*99ebb4caSwyllys 		if (opt != 'i' && EMPTYSTRING(optarg_av))
465*99ebb4caSwyllys 			return (PK_ERR_USAGE);
466*99ebb4caSwyllys 
467*99ebb4caSwyllys 		switch (opt) {
468*99ebb4caSwyllys 			case 'A':
469*99ebb4caSwyllys 				altname = optarg_av;
470*99ebb4caSwyllys 				break;
471*99ebb4caSwyllys 			case 'i':
472*99ebb4caSwyllys 				if (interactive || subject)
473*99ebb4caSwyllys 					return (PK_ERR_USAGE);
474*99ebb4caSwyllys 				else
475*99ebb4caSwyllys 					interactive = B_TRUE;
476*99ebb4caSwyllys 				break;
477*99ebb4caSwyllys 			case 'k':
478*99ebb4caSwyllys 				kstype = KS2Int(optarg_av);
479*99ebb4caSwyllys 				if (kstype == 0)
480*99ebb4caSwyllys 					return (PK_ERR_USAGE);
481*99ebb4caSwyllys 				break;
482*99ebb4caSwyllys 			case 's':
483*99ebb4caSwyllys 				if (interactive || subject)
484*99ebb4caSwyllys 					return (PK_ERR_USAGE);
485*99ebb4caSwyllys 				else
486*99ebb4caSwyllys 					subject = optarg_av;
487*99ebb4caSwyllys 				break;
488*99ebb4caSwyllys 			case 'l':
489*99ebb4caSwyllys 			case 'n':
490*99ebb4caSwyllys 				if (certlabel)
491*99ebb4caSwyllys 					return (PK_ERR_USAGE);
492*99ebb4caSwyllys 				certlabel = optarg_av;
493*99ebb4caSwyllys 				break;
494*99ebb4caSwyllys 			case 'T':
495*99ebb4caSwyllys 				if (tokenname)
496*99ebb4caSwyllys 					return (PK_ERR_USAGE);
497*99ebb4caSwyllys 				tokenname = optarg_av;
498*99ebb4caSwyllys 				break;
499*99ebb4caSwyllys 			case 'd':
500*99ebb4caSwyllys 				if (dir)
501*99ebb4caSwyllys 					return (PK_ERR_USAGE);
502*99ebb4caSwyllys 				dir = optarg_av;
503*99ebb4caSwyllys 				break;
504*99ebb4caSwyllys 			case 'p':
505*99ebb4caSwyllys 				if (prefix)
506*99ebb4caSwyllys 					return (PK_ERR_USAGE);
507*99ebb4caSwyllys 				prefix = optarg_av;
508*99ebb4caSwyllys 				break;
509*99ebb4caSwyllys 			case 't':
510*99ebb4caSwyllys 				keytype = optarg_av;
511*99ebb4caSwyllys 				break;
512*99ebb4caSwyllys 			case 'u':
513*99ebb4caSwyllys 				keyusagestr = optarg_av;
514*99ebb4caSwyllys 				break;
515*99ebb4caSwyllys 			case 'y':
516*99ebb4caSwyllys 				if (sscanf(optarg_av, "%d",
517*99ebb4caSwyllys 					&keylen) != 1) {
518*99ebb4caSwyllys 					cryptoerror(LOG_STDERR,
519*99ebb4caSwyllys 						gettext("key length must be"
520*99ebb4caSwyllys 						"a numeric value (%s)\n"),
521*99ebb4caSwyllys 						optarg_av);
522*99ebb4caSwyllys 					return (PK_ERR_USAGE);
523*99ebb4caSwyllys 				}
524*99ebb4caSwyllys 				break;
525*99ebb4caSwyllys 			case 'r':
526*99ebb4caSwyllys 				if (trust)
527*99ebb4caSwyllys 					return (PK_ERR_USAGE);
528*99ebb4caSwyllys 				trust = optarg_av;
529*99ebb4caSwyllys 				break;
530*99ebb4caSwyllys 			case 'L':
531*99ebb4caSwyllys 				if (lifetime)
532*99ebb4caSwyllys 					return (PK_ERR_USAGE);
533*99ebb4caSwyllys 				lifetime = optarg_av;
534*99ebb4caSwyllys 				break;
535*99ebb4caSwyllys 			case 'c':
536*99ebb4caSwyllys 				if (outcert)
537*99ebb4caSwyllys 					return (PK_ERR_USAGE);
538*99ebb4caSwyllys 				outcert = optarg_av;
539*99ebb4caSwyllys 				break;
540*99ebb4caSwyllys 			case 'K':
541*99ebb4caSwyllys 				if (outkey)
542*99ebb4caSwyllys 					return (PK_ERR_USAGE);
543*99ebb4caSwyllys 				outkey = optarg_av;
544*99ebb4caSwyllys 				break;
545*99ebb4caSwyllys 			case 'S':
546*99ebb4caSwyllys 				serstr = optarg_av;
547*99ebb4caSwyllys 				break;
548*99ebb4caSwyllys 			case 'F':
549*99ebb4caSwyllys 				if (format)
550*99ebb4caSwyllys 					return (PK_ERR_USAGE);
551*99ebb4caSwyllys 				format = optarg_av;
552*99ebb4caSwyllys 				break;
553*99ebb4caSwyllys 			default:
554*99ebb4caSwyllys 				return (PK_ERR_USAGE);
555*99ebb4caSwyllys 		}
556*99ebb4caSwyllys 	}
557*99ebb4caSwyllys 
558*99ebb4caSwyllys 	/* No additional args allowed. */
559*99ebb4caSwyllys 	argc -= optind_av;
560*99ebb4caSwyllys 	argv += optind_av;
561*99ebb4caSwyllys 	if (argc) {
562*99ebb4caSwyllys 		return (PK_ERR_USAGE);
563*99ebb4caSwyllys 	}
564*99ebb4caSwyllys 
565*99ebb4caSwyllys 	if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
566*99ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
567*99ebb4caSwyllys 		return (PK_ERR_USAGE);
568*99ebb4caSwyllys 	}
569*99ebb4caSwyllys 
570*99ebb4caSwyllys 	/* Assume keystore = PKCS#11 if not specified. */
571*99ebb4caSwyllys 	if (kstype == 0)
572*99ebb4caSwyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
573*99ebb4caSwyllys 
574*99ebb4caSwyllys 	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) &&
575*99ebb4caSwyllys 	    EMPTYSTRING(certlabel)) {
576*99ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("A label must be specified "
577*99ebb4caSwyllys 		    "to create a self-signed certificate.\n"));
578*99ebb4caSwyllys 		return (PK_ERR_USAGE);
579*99ebb4caSwyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL && EMPTYSTRING(outcert)) {
580*99ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("A certificate filename must "
581*99ebb4caSwyllys 		    "be specified to create a self-signed certificate.\n"));
582*99ebb4caSwyllys 		return (PK_ERR_USAGE);
583*99ebb4caSwyllys 	}
584*99ebb4caSwyllys 
585*99ebb4caSwyllys 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
586*99ebb4caSwyllys 		cryptoerror(LOG_STDERR,
587*99ebb4caSwyllys 		    gettext("Error parsing format string (%s).\n"),
588*99ebb4caSwyllys 		    format);
589*99ebb4caSwyllys 		return (PK_ERR_USAGE);
590*99ebb4caSwyllys 	}
591*99ebb4caSwyllys 
592*99ebb4caSwyllys 	if (Str2Lifetime(lifetime, &ltime) != 0) {
593*99ebb4caSwyllys 		cryptoerror(LOG_STDERR,
594*99ebb4caSwyllys 			gettext("Error parsing lifetime string\n"));
595*99ebb4caSwyllys 		return (PK_ERR_USAGE);
596*99ebb4caSwyllys 	}
597*99ebb4caSwyllys 
598*99ebb4caSwyllys 	if (Str2KeyType(keytype, &keyAlg, &sigAlg) != 0) {
599*99ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
600*99ebb4caSwyllys 			keytype);
601*99ebb4caSwyllys 		return (PK_ERR_USAGE);
602*99ebb4caSwyllys 	}
603*99ebb4caSwyllys 
604*99ebb4caSwyllys 
605*99ebb4caSwyllys 	/*
606*99ebb4caSwyllys 	 * Check the subject name.
607*99ebb4caSwyllys 	 * If interactive is true, get it now interactively.
608*99ebb4caSwyllys 	 */
609*99ebb4caSwyllys 	if (interactive) {
610*99ebb4caSwyllys 		if (get_subname(&subname) != KMF_OK) {
611*99ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("Failed to get the "
612*99ebb4caSwyllys 			    "subject name interactively.\n"));
613*99ebb4caSwyllys 			return (PK_ERR_USAGE);
614*99ebb4caSwyllys 		}
615*99ebb4caSwyllys 	} else {
616*99ebb4caSwyllys 		if (EMPTYSTRING(subject)) {
617*99ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("A subject name or "
618*99ebb4caSwyllys 			    "-i must be specified to create a self-signed "
619*99ebb4caSwyllys 			    "certificate.\n"));
620*99ebb4caSwyllys 			return (PK_ERR_USAGE);
621*99ebb4caSwyllys 		} else {
622*99ebb4caSwyllys 			subname = strdup(subject);
623*99ebb4caSwyllys 			if (subname == NULL) {
624*99ebb4caSwyllys 				cryptoerror(LOG_STDERR,
625*99ebb4caSwyllys 				    gettext("Out of memory.\n"));
626*99ebb4caSwyllys 				return (PK_ERR_SYSTEM);
627*99ebb4caSwyllys 			}
628*99ebb4caSwyllys 		}
629*99ebb4caSwyllys 	}
630*99ebb4caSwyllys 
631*99ebb4caSwyllys 	if (serstr == NULL) {
632*99ebb4caSwyllys 		(void) fprintf(stderr, gettext("A serial number "
633*99ebb4caSwyllys 			"must be specified as a hex number when creating"
634*99ebb4caSwyllys 			" a self-signed certificate "
635*99ebb4caSwyllys 			"(ex: serno=0x0102030405feedface)\n"));
636*99ebb4caSwyllys 		rv = PK_ERR_USAGE;
637*99ebb4caSwyllys 		goto end;
638*99ebb4caSwyllys 	} else {
639*99ebb4caSwyllys 		uchar_t *bytes = NULL;
640*99ebb4caSwyllys 		size_t bytelen;
641*99ebb4caSwyllys 
642*99ebb4caSwyllys 		rv = KMF_HexString2Bytes((uchar_t *)serstr, &bytes, &bytelen);
643*99ebb4caSwyllys 		if (rv != KMF_OK || bytes == NULL) {
644*99ebb4caSwyllys 			(void) fprintf(stderr, gettext("serial number "
645*99ebb4caSwyllys 				"must be specified as a hex number "
646*99ebb4caSwyllys 				"(ex: 0x0102030405ffeeddee)\n"));
647*99ebb4caSwyllys 			rv = PK_ERR_USAGE;
648*99ebb4caSwyllys 			goto end;
649*99ebb4caSwyllys 		}
650*99ebb4caSwyllys 		serial.val = bytes;
651*99ebb4caSwyllys 		serial.len = bytelen;
652*99ebb4caSwyllys 	}
653*99ebb4caSwyllys 
654*99ebb4caSwyllys 	if (altname != NULL) {
655*99ebb4caSwyllys 		rv = verify_altname(altname, &alttype, &altcrit);
656*99ebb4caSwyllys 		if (rv != KMF_OK) {
657*99ebb4caSwyllys 			(void) fprintf(stderr, gettext("Subject AltName "
658*99ebb4caSwyllys 				"must be specified as a name=value pair. "
659*99ebb4caSwyllys 				"See the man page for details.\n"));
660*99ebb4caSwyllys 			rv = PK_ERR_USAGE;
661*99ebb4caSwyllys 			goto end;
662*99ebb4caSwyllys 		} else {
663*99ebb4caSwyllys 			/* advance the altname past the '=' sign */
664*99ebb4caSwyllys 			char *p = strchr(altname, '=');
665*99ebb4caSwyllys 			if (p != NULL)
666*99ebb4caSwyllys 				altname = p + 1;
667*99ebb4caSwyllys 		}
668*99ebb4caSwyllys 	}
669*99ebb4caSwyllys 
670*99ebb4caSwyllys 	if (keyusagestr != NULL) {
671*99ebb4caSwyllys 		rv = verify_keyusage(keyusagestr, &kubits, &kucrit);
672*99ebb4caSwyllys 		if (rv != KMF_OK) {
673*99ebb4caSwyllys 			(void) fprintf(stderr, gettext("KeyUsage "
674*99ebb4caSwyllys 				"must be specified as a comma-separated list. "
675*99ebb4caSwyllys 				"See the man page for details.\n"));
676*99ebb4caSwyllys 			rv = PK_ERR_USAGE;
677*99ebb4caSwyllys 			goto end;
678*99ebb4caSwyllys 		}
679*99ebb4caSwyllys 	}
680*99ebb4caSwyllys 
681*99ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
682*99ebb4caSwyllys 		if (tokenname == NULL || !strlen(tokenname)) {
683*99ebb4caSwyllys 			if (kstype == KMF_KEYSTORE_NSS) {
684*99ebb4caSwyllys 				tokenname = "internal";
685*99ebb4caSwyllys 			} else  {
686*99ebb4caSwyllys 				tokenname = PK_DEFAULT_PK11TOKEN;
687*99ebb4caSwyllys 			}
688*99ebb4caSwyllys 		}
689*99ebb4caSwyllys 
690*99ebb4caSwyllys 		(void) get_token_password(kstype, tokenname, &tokencred);
691*99ebb4caSwyllys 	}
692*99ebb4caSwyllys 
693*99ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_NSS) {
694*99ebb4caSwyllys 		if (dir == NULL)
695*99ebb4caSwyllys 			dir = PK_DEFAULT_DIRECTORY;
696*99ebb4caSwyllys 
697*99ebb4caSwyllys 		rv = gencert_nss(kmfhandle,
698*99ebb4caSwyllys 			tokenname, subname, altname, alttype, altcrit,
699*99ebb4caSwyllys 			certlabel, dir, prefix, keyAlg, sigAlg, keylen,
700*99ebb4caSwyllys 			trust, ltime, &serial, kubits, kucrit, &tokencred);
701*99ebb4caSwyllys 
702*99ebb4caSwyllys 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
703*99ebb4caSwyllys 		rv = gencert_pkcs11(kmfhandle,
704*99ebb4caSwyllys 			tokenname, subname, altname, alttype, altcrit,
705*99ebb4caSwyllys 			certlabel, keyAlg, sigAlg, keylen, ltime,
706*99ebb4caSwyllys 			&serial, kubits, kucrit, &tokencred);
707*99ebb4caSwyllys 
708*99ebb4caSwyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
709*99ebb4caSwyllys 		rv = gencert_file(kmfhandle,
710*99ebb4caSwyllys 			keyAlg, sigAlg, keylen, fmt,
711*99ebb4caSwyllys 			ltime, subname, altname, alttype, altcrit,
712*99ebb4caSwyllys 			&serial, kubits, kucrit, dir, outcert, outkey);
713*99ebb4caSwyllys 	}
714*99ebb4caSwyllys 
715*99ebb4caSwyllys 	if (rv != KMF_OK)
716*99ebb4caSwyllys 		display_error(kmfhandle, rv,
717*99ebb4caSwyllys 			gettext("Error creating certificate and keypair"));
718*99ebb4caSwyllys end:
719*99ebb4caSwyllys 	if (subname)
720*99ebb4caSwyllys 		free(subname);
721*99ebb4caSwyllys 	if (tokencred.cred != NULL)
722*99ebb4caSwyllys 		free(tokencred.cred);
723*99ebb4caSwyllys 
724*99ebb4caSwyllys 	if (serial.val != NULL)
725*99ebb4caSwyllys 		free(serial.val);
726*99ebb4caSwyllys 
727*99ebb4caSwyllys 	(void) KMF_Finalize(kmfhandle);
728*99ebb4caSwyllys 	return (rv);
729*99ebb4caSwyllys }
730