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  * OpenSSL keystore wrapper
22*99ebb4caSwyllys  *
23*99ebb4caSwyllys  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24*99ebb4caSwyllys  * Use is subject to license terms.
25*99ebb4caSwyllys  */
26*99ebb4caSwyllys 
27*99ebb4caSwyllys #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*99ebb4caSwyllys 
29*99ebb4caSwyllys #include <kmfapiP.h>
30*99ebb4caSwyllys #include <ber_der.h>
31*99ebb4caSwyllys #include <oidsalg.h>
32*99ebb4caSwyllys #include <fcntl.h>
33*99ebb4caSwyllys #include <sys/stat.h>
34*99ebb4caSwyllys #include <dirent.h>
35*99ebb4caSwyllys #include <cryptoutil.h>
36*99ebb4caSwyllys #include <synch.h>
37*99ebb4caSwyllys #include <thread.h>
38*99ebb4caSwyllys 
39*99ebb4caSwyllys /* OPENSSL related headers */
40*99ebb4caSwyllys #include <openssl/bio.h>
41*99ebb4caSwyllys #include <openssl/bn.h>
42*99ebb4caSwyllys #include <openssl/asn1.h>
43*99ebb4caSwyllys #include <openssl/err.h>
44*99ebb4caSwyllys #include <openssl/bn.h>
45*99ebb4caSwyllys #include <openssl/x509.h>
46*99ebb4caSwyllys #include <openssl/rsa.h>
47*99ebb4caSwyllys #include <openssl/dsa.h>
48*99ebb4caSwyllys #include <openssl/x509v3.h>
49*99ebb4caSwyllys #include <openssl/objects.h>
50*99ebb4caSwyllys #include <openssl/pem.h>
51*99ebb4caSwyllys #include <openssl/pkcs12.h>
52*99ebb4caSwyllys #include <openssl/ocsp.h>
53*99ebb4caSwyllys #include <openssl/des.h>
54*99ebb4caSwyllys #include <openssl/rand.h>
55*99ebb4caSwyllys 
56*99ebb4caSwyllys #define	PRINT_ANY_EXTENSION (\
57*99ebb4caSwyllys 	KMF_X509_EXT_KEY_USAGE |\
58*99ebb4caSwyllys 	KMF_X509_EXT_CERT_POLICIES |\
59*99ebb4caSwyllys 	KMF_X509_EXT_SUBJALTNAME |\
60*99ebb4caSwyllys 	KMF_X509_EXT_BASIC_CONSTRAINTS |\
61*99ebb4caSwyllys 	KMF_X509_EXT_NAME_CONSTRAINTS |\
62*99ebb4caSwyllys 	KMF_X509_EXT_POLICY_CONSTRAINTS |\
63*99ebb4caSwyllys 	KMF_X509_EXT_EXT_KEY_USAGE |\
64*99ebb4caSwyllys 	KMF_X509_EXT_INHIBIT_ANY_POLICY |\
65*99ebb4caSwyllys 	KMF_X509_EXT_AUTH_KEY_ID |\
66*99ebb4caSwyllys 	KMF_X509_EXT_SUBJ_KEY_ID |\
67*99ebb4caSwyllys 	KMF_X509_EXT_POLICY_MAPPING)
68*99ebb4caSwyllys 
69*99ebb4caSwyllys static BIO *bio_err = NULL;
70*99ebb4caSwyllys static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
71*99ebb4caSwyllys 	0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
72*99ebb4caSwyllys 	0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
73*99ebb4caSwyllys 	0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
74*99ebb4caSwyllys 	0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
75*99ebb4caSwyllys 	0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
76*99ebb4caSwyllys 	0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
77*99ebb4caSwyllys 	0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
78*99ebb4caSwyllys 	0x91 };
79*99ebb4caSwyllys 
80*99ebb4caSwyllys static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
81*99ebb4caSwyllys 	0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
82*99ebb4caSwyllys 	0x8e, 0xda, 0xce, 0x91, 0x5f };
83*99ebb4caSwyllys 
84*99ebb4caSwyllys static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
85*99ebb4caSwyllys 	0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
86*99ebb4caSwyllys 	0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
87*99ebb4caSwyllys 	0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
88*99ebb4caSwyllys 	0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
89*99ebb4caSwyllys 	0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
90*99ebb4caSwyllys 	0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
91*99ebb4caSwyllys 	0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
92*99ebb4caSwyllys 	0x02 };
93*99ebb4caSwyllys 
94*99ebb4caSwyllys #define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
95*99ebb4caSwyllys 	h->lasterr.errcode = c;
96*99ebb4caSwyllys 
97*99ebb4caSwyllys #define	SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
98*99ebb4caSwyllys 
99*99ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX;
100*99ebb4caSwyllys static int ssl_initialized = 0;
101*99ebb4caSwyllys 
102*99ebb4caSwyllys KMF_RETURN
103*99ebb4caSwyllys OpenSSL_FindCert(KMF_HANDLE_T,
104*99ebb4caSwyllys 	KMF_FINDCERT_PARAMS *,
105*99ebb4caSwyllys 	KMF_X509_DER_CERT *,
106*99ebb4caSwyllys 	uint32_t *);
107*99ebb4caSwyllys 
108*99ebb4caSwyllys void
109*99ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
110*99ebb4caSwyllys 
111*99ebb4caSwyllys KMF_RETURN
112*99ebb4caSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, KMF_STORECERT_PARAMS *, KMF_DATA *);
113*99ebb4caSwyllys 
114*99ebb4caSwyllys KMF_RETURN
115*99ebb4caSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, KMF_DELETECERT_PARAMS *);
116*99ebb4caSwyllys 
117*99ebb4caSwyllys KMF_RETURN
118*99ebb4caSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T, KMF_CREATEKEYPAIR_PARAMS *,
119*99ebb4caSwyllys 	KMF_KEY_HANDLE *, KMF_KEY_HANDLE *);
120*99ebb4caSwyllys 
121*99ebb4caSwyllys KMF_RETURN
122*99ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T,  KMF_KEY_HANDLE *, KMF_DATA *);
123*99ebb4caSwyllys 
124*99ebb4caSwyllys KMF_RETURN
125*99ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
126*99ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
127*99ebb4caSwyllys 
128*99ebb4caSwyllys KMF_RETURN
129*99ebb4caSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T, KMF_DELETEKEY_PARAMS *,
130*99ebb4caSwyllys 	KMF_KEY_HANDLE *, boolean_t);
131*99ebb4caSwyllys 
132*99ebb4caSwyllys KMF_RETURN
133*99ebb4caSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T, KMF_IMPORTCRL_PARAMS *);
134*99ebb4caSwyllys 
135*99ebb4caSwyllys KMF_RETURN
136*99ebb4caSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T, KMF_DELETECRL_PARAMS *);
137*99ebb4caSwyllys 
138*99ebb4caSwyllys KMF_RETURN
139*99ebb4caSwyllys OpenSSL_ListCRL(KMF_HANDLE_T, KMF_LISTCRL_PARAMS *, char **);
140*99ebb4caSwyllys 
141*99ebb4caSwyllys KMF_RETURN
142*99ebb4caSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T, KMF_FINDCERTINCRL_PARAMS *);
143*99ebb4caSwyllys 
144*99ebb4caSwyllys KMF_RETURN
145*99ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
146*99ebb4caSwyllys 	KMF_PRINTABLE_ITEM, char *);
147*99ebb4caSwyllys 
148*99ebb4caSwyllys KMF_RETURN
149*99ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
150*99ebb4caSwyllys 
151*99ebb4caSwyllys KMF_RETURN
152*99ebb4caSwyllys OpenSSL_GetPrikeyByCert(KMF_HANDLE_T, KMF_CRYPTOWITHCERT_PARAMS *, KMF_DATA *,
153*99ebb4caSwyllys 	KMF_KEY_HANDLE *, KMF_KEY_ALG);
154*99ebb4caSwyllys 
155*99ebb4caSwyllys KMF_RETURN
156*99ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
157*99ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
158*99ebb4caSwyllys 
159*99ebb4caSwyllys KMF_RETURN
160*99ebb4caSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, KMF_OCSPREQUEST_PARAMS *,
161*99ebb4caSwyllys 	char *reqfile);
162*99ebb4caSwyllys 
163*99ebb4caSwyllys KMF_RETURN
164*99ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, KMF_OCSPRESPONSE_PARAMS_INPUT *,
165*99ebb4caSwyllys     KMF_OCSPRESPONSE_PARAMS_OUTPUT *);
166*99ebb4caSwyllys 
167*99ebb4caSwyllys KMF_RETURN
168*99ebb4caSwyllys OpenSSL_FindKey(KMF_HANDLE_T, KMF_FINDKEY_PARAMS *,
169*99ebb4caSwyllys 	KMF_KEY_HANDLE *, uint32_t *);
170*99ebb4caSwyllys 
171*99ebb4caSwyllys KMF_RETURN
172*99ebb4caSwyllys OpenSSL_ExportP12(KMF_HANDLE_T,
173*99ebb4caSwyllys 	KMF_EXPORTP12_PARAMS *,
174*99ebb4caSwyllys 	int, KMF_X509_DER_CERT *,
175*99ebb4caSwyllys 	int, KMF_KEY_HANDLE *,
176*99ebb4caSwyllys 	char *);
177*99ebb4caSwyllys 
178*99ebb4caSwyllys KMF_RETURN
179*99ebb4caSwyllys OpenSSL_StorePrivateKey(KMF_HANDLE_T, KMF_STOREKEY_PARAMS *,
180*99ebb4caSwyllys 	KMF_RAW_KEY_DATA *);
181*99ebb4caSwyllys 
182*99ebb4caSwyllys KMF_RETURN
183*99ebb4caSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T, KMF_CREATESYMKEY_PARAMS *,
184*99ebb4caSwyllys 	KMF_KEY_HANDLE *);
185*99ebb4caSwyllys 
186*99ebb4caSwyllys KMF_RETURN
187*99ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
188*99ebb4caSwyllys 
189*99ebb4caSwyllys KMF_RETURN
190*99ebb4caSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T, KMF_VERIFYCRL_PARAMS *);
191*99ebb4caSwyllys 
192*99ebb4caSwyllys KMF_RETURN
193*99ebb4caSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T, KMF_CHECKCRLDATE_PARAMS *);
194*99ebb4caSwyllys 
195*99ebb4caSwyllys static
196*99ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table =
197*99ebb4caSwyllys {
198*99ebb4caSwyllys 	1,				/* Version */
199*99ebb4caSwyllys 	NULL, /* ConfigureKeystore */
200*99ebb4caSwyllys 	OpenSSL_FindCert,
201*99ebb4caSwyllys 	OpenSSL_FreeKMFCert,
202*99ebb4caSwyllys 	OpenSSL_StoreCert,
203*99ebb4caSwyllys 	NULL, /* ImportCert */
204*99ebb4caSwyllys 	OpenSSL_ImportCRL,
205*99ebb4caSwyllys 	OpenSSL_DeleteCert,
206*99ebb4caSwyllys 	OpenSSL_DeleteCRL,
207*99ebb4caSwyllys 	OpenSSL_CreateKeypair,
208*99ebb4caSwyllys 	OpenSSL_FindKey,
209*99ebb4caSwyllys 	OpenSSL_EncodePubKeyData,
210*99ebb4caSwyllys 	OpenSSL_SignData,
211*99ebb4caSwyllys 	OpenSSL_DeleteKey,
212*99ebb4caSwyllys 	OpenSSL_ListCRL,
213*99ebb4caSwyllys 	NULL,	/* FindCRL */
214*99ebb4caSwyllys 	OpenSSL_FindCertInCRL,
215*99ebb4caSwyllys 	OpenSSL_GetErrorString,
216*99ebb4caSwyllys 	OpenSSL_GetPrikeyByCert,
217*99ebb4caSwyllys 	OpenSSL_DecryptData,
218*99ebb4caSwyllys 	OpenSSL_ExportP12,
219*99ebb4caSwyllys 	OpenSSL_StorePrivateKey,
220*99ebb4caSwyllys 	OpenSSL_CreateSymKey,
221*99ebb4caSwyllys 	OpenSSL_GetSymKeyValue,
222*99ebb4caSwyllys 	NULL,	/* SetTokenPin */
223*99ebb4caSwyllys 	NULL	/* Finalize */
224*99ebb4caSwyllys };
225*99ebb4caSwyllys 
226*99ebb4caSwyllys static mutex_t *lock_cs;
227*99ebb4caSwyllys static long *lock_count;
228*99ebb4caSwyllys 
229*99ebb4caSwyllys static void
230*99ebb4caSwyllys /*ARGSUSED*/
231*99ebb4caSwyllys locking_cb(int mode, int type, char *file, int line)
232*99ebb4caSwyllys {
233*99ebb4caSwyllys 	if (mode & CRYPTO_LOCK) {
234*99ebb4caSwyllys 		(void) mutex_lock(&(lock_cs[type]));
235*99ebb4caSwyllys 		lock_count[type]++;
236*99ebb4caSwyllys 	} else {
237*99ebb4caSwyllys 		(void) mutex_unlock(&(lock_cs[type]));
238*99ebb4caSwyllys 	}
239*99ebb4caSwyllys }
240*99ebb4caSwyllys 
241*99ebb4caSwyllys static unsigned long
242*99ebb4caSwyllys thread_id()
243*99ebb4caSwyllys {
244*99ebb4caSwyllys 	return ((unsigned long)thr_self());
245*99ebb4caSwyllys }
246*99ebb4caSwyllys 
247*99ebb4caSwyllys KMF_PLUGIN_FUNCLIST *
248*99ebb4caSwyllys KMF_Plugin_Initialize()
249*99ebb4caSwyllys {
250*99ebb4caSwyllys 	int i;
251*99ebb4caSwyllys 
252*99ebb4caSwyllys 	(void) mutex_lock(&init_lock);
253*99ebb4caSwyllys 	if (!ssl_initialized) {
254*99ebb4caSwyllys 		OpenSSL_add_all_algorithms();
255*99ebb4caSwyllys 
256*99ebb4caSwyllys 		/* Enable error strings for reporting */
257*99ebb4caSwyllys 		ERR_load_crypto_strings();
258*99ebb4caSwyllys 
259*99ebb4caSwyllys 		/*
260*99ebb4caSwyllys 		 * Add support for extension OIDs that are not yet in the
261*99ebb4caSwyllys 		 * openssl default set.
262*99ebb4caSwyllys 		 */
263*99ebb4caSwyllys 		(void) OBJ_create("2.5.29.30", "nameConstraints",
264*99ebb4caSwyllys 				"X509v3 Name Constraints");
265*99ebb4caSwyllys 		(void) OBJ_create("2.5.29.33", "policyMappings",
266*99ebb4caSwyllys 				"X509v3 Policy Mappings");
267*99ebb4caSwyllys 		(void) OBJ_create("2.5.29.36", "policyConstraints",
268*99ebb4caSwyllys 			"X509v3 Policy Constraints");
269*99ebb4caSwyllys 		(void) OBJ_create("2.5.29.46", "freshestCRL",
270*99ebb4caSwyllys 			"X509v3 Freshest CRL");
271*99ebb4caSwyllys 		(void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
272*99ebb4caSwyllys 			"X509v3 Inhibit Any-Policy");
273*99ebb4caSwyllys 		/*
274*99ebb4caSwyllys 		 * Set up for thread-safe operation.
275*99ebb4caSwyllys 		 */
276*99ebb4caSwyllys 		lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
277*99ebb4caSwyllys 		if (lock_cs == NULL) {
278*99ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
279*99ebb4caSwyllys 			return (NULL);
280*99ebb4caSwyllys 		}
281*99ebb4caSwyllys 
282*99ebb4caSwyllys 		lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
283*99ebb4caSwyllys 		if (lock_count == NULL) {
284*99ebb4caSwyllys 			OPENSSL_free(lock_cs);
285*99ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
286*99ebb4caSwyllys 			return (NULL);
287*99ebb4caSwyllys 		}
288*99ebb4caSwyllys 
289*99ebb4caSwyllys 		for (i = 0; i < CRYPTO_num_locks(); i++) {
290*99ebb4caSwyllys 			lock_count[i] = 0;
291*99ebb4caSwyllys 			(void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
292*99ebb4caSwyllys 		}
293*99ebb4caSwyllys 
294*99ebb4caSwyllys 		CRYPTO_set_id_callback((unsigned long (*)())thread_id);
295*99ebb4caSwyllys 		CRYPTO_set_locking_callback((void (*)())locking_cb);
296*99ebb4caSwyllys 		ssl_initialized = 1;
297*99ebb4caSwyllys 	}
298*99ebb4caSwyllys 	(void) mutex_unlock(&init_lock);
299*99ebb4caSwyllys 
300*99ebb4caSwyllys 	return (&openssl_plugin_table);
301*99ebb4caSwyllys }
302*99ebb4caSwyllys /*
303*99ebb4caSwyllys  * Convert an SSL DN to a KMF DN.
304*99ebb4caSwyllys  */
305*99ebb4caSwyllys static KMF_RETURN
306*99ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
307*99ebb4caSwyllys {
308*99ebb4caSwyllys 	KMF_DATA derdata;
309*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
310*99ebb4caSwyllys 	uchar_t *tmp;
311*99ebb4caSwyllys 
312*99ebb4caSwyllys 	/* Convert to raw DER format */
313*99ebb4caSwyllys 	derdata.Length = i2d_X509_NAME(sslDN, NULL);
314*99ebb4caSwyllys 	if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
315*99ebb4caSwyllys 		== NULL) {
316*99ebb4caSwyllys 		return (KMF_ERR_MEMORY);
317*99ebb4caSwyllys 	}
318*99ebb4caSwyllys 	(void) i2d_X509_NAME(sslDN, &tmp);
319*99ebb4caSwyllys 
320*99ebb4caSwyllys 	/* Decode to KMF format */
321*99ebb4caSwyllys 	rv = DerDecodeName(&derdata, kmfDN);
322*99ebb4caSwyllys 	if (rv != KMF_OK) {
323*99ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
324*99ebb4caSwyllys 	}
325*99ebb4caSwyllys 	OPENSSL_free(derdata.Data);
326*99ebb4caSwyllys 
327*99ebb4caSwyllys 	return (rv);
328*99ebb4caSwyllys }
329*99ebb4caSwyllys 
330*99ebb4caSwyllys static int
331*99ebb4caSwyllys isdir(char *path)
332*99ebb4caSwyllys {
333*99ebb4caSwyllys 	struct stat s;
334*99ebb4caSwyllys 
335*99ebb4caSwyllys 	if (stat(path, &s) == -1)
336*99ebb4caSwyllys 		return (0);
337*99ebb4caSwyllys 
338*99ebb4caSwyllys 	return (s.st_mode & S_IFDIR);
339*99ebb4caSwyllys }
340*99ebb4caSwyllys 
341*99ebb4caSwyllys static KMF_RETURN
342*99ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
343*99ebb4caSwyllys {
344*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
345*99ebb4caSwyllys 	unsigned char *buf = NULL, *p;
346*99ebb4caSwyllys 	int len;
347*99ebb4caSwyllys 
348*99ebb4caSwyllys 	/*
349*99ebb4caSwyllys 	 * Convert the X509 internal struct to DER encoded data
350*99ebb4caSwyllys 	 */
351*99ebb4caSwyllys 	if ((len = i2d_X509(x509cert, NULL)) < 0) {
352*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
353*99ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
354*99ebb4caSwyllys 		goto cleanup;
355*99ebb4caSwyllys 	}
356*99ebb4caSwyllys 	if ((buf = malloc(len)) == NULL) {
357*99ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
358*99ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
359*99ebb4caSwyllys 		goto cleanup;
360*99ebb4caSwyllys 	}
361*99ebb4caSwyllys 
362*99ebb4caSwyllys 	/*
363*99ebb4caSwyllys 	 * i2d_X509 will increment the buf pointer so that we need to
364*99ebb4caSwyllys 	 * save it.
365*99ebb4caSwyllys 	 */
366*99ebb4caSwyllys 	p = buf;
367*99ebb4caSwyllys 	if ((len = i2d_X509(x509cert, &p)) < 0) {
368*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
369*99ebb4caSwyllys 		free(buf);
370*99ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
371*99ebb4caSwyllys 		goto cleanup;
372*99ebb4caSwyllys 	}
373*99ebb4caSwyllys 
374*99ebb4caSwyllys 	/* caller's responsibility to free it */
375*99ebb4caSwyllys 	cert->Data = buf;
376*99ebb4caSwyllys 	cert->Length = len;
377*99ebb4caSwyllys 
378*99ebb4caSwyllys cleanup:
379*99ebb4caSwyllys 	if (rv != KMF_OK) {
380*99ebb4caSwyllys 		if (buf)
381*99ebb4caSwyllys 			free(buf);
382*99ebb4caSwyllys 		cert->Data = NULL;
383*99ebb4caSwyllys 		cert->Length = 0;
384*99ebb4caSwyllys 	}
385*99ebb4caSwyllys 
386*99ebb4caSwyllys 	return (rv);
387*99ebb4caSwyllys }
388*99ebb4caSwyllys 
389*99ebb4caSwyllys static KMF_RETURN
390*99ebb4caSwyllys check_cert(X509 *xcert, KMF_FINDCERT_PARAMS *params, boolean_t *match)
391*99ebb4caSwyllys {
392*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
393*99ebb4caSwyllys 	boolean_t findIssuer = FALSE;
394*99ebb4caSwyllys 	boolean_t findSubject = FALSE;
395*99ebb4caSwyllys 	boolean_t findSerial = FALSE;
396*99ebb4caSwyllys 	KMF_X509_NAME issuerDN, subjectDN;
397*99ebb4caSwyllys 	KMF_X509_NAME certIssuerDN, certSubjectDN;
398*99ebb4caSwyllys 
399*99ebb4caSwyllys 	*match = FALSE;
400*99ebb4caSwyllys 	if (xcert == NULL) {
401*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
402*99ebb4caSwyllys 	}
403*99ebb4caSwyllys 
404*99ebb4caSwyllys 	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
405*99ebb4caSwyllys 	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
406*99ebb4caSwyllys 	(void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
407*99ebb4caSwyllys 	(void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
408*99ebb4caSwyllys 
409*99ebb4caSwyllys 	if (params->issuer != NULL && strlen(params->issuer)) {
410*99ebb4caSwyllys 		rv = KMF_DNParser(params->issuer, &issuerDN);
411*99ebb4caSwyllys 		if (rv != KMF_OK)
412*99ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
413*99ebb4caSwyllys 
414*99ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->issuer, &certIssuerDN);
415*99ebb4caSwyllys 		if (rv != KMF_OK) {
416*99ebb4caSwyllys 			KMF_FreeDN(&issuerDN);
417*99ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
418*99ebb4caSwyllys 		}
419*99ebb4caSwyllys 
420*99ebb4caSwyllys 		findIssuer = TRUE;
421*99ebb4caSwyllys 	}
422*99ebb4caSwyllys 	if (params->subject != NULL && strlen(params->subject)) {
423*99ebb4caSwyllys 		rv = KMF_DNParser(params->subject, &subjectDN);
424*99ebb4caSwyllys 		if (rv != KMF_OK) {
425*99ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
426*99ebb4caSwyllys 			goto cleanup;
427*99ebb4caSwyllys 		}
428*99ebb4caSwyllys 
429*99ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->subject, &certSubjectDN);
430*99ebb4caSwyllys 		if (rv != KMF_OK) {
431*99ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
432*99ebb4caSwyllys 			goto cleanup;
433*99ebb4caSwyllys 		}
434*99ebb4caSwyllys 		findSubject = TRUE;
435*99ebb4caSwyllys 	}
436*99ebb4caSwyllys 	if (params->serial != NULL && params->serial->val != NULL)
437*99ebb4caSwyllys 		findSerial = TRUE;
438*99ebb4caSwyllys 
439*99ebb4caSwyllys 	if (findSerial) {
440*99ebb4caSwyllys 		BIGNUM *bn;
441*99ebb4caSwyllys 
442*99ebb4caSwyllys 		/* Comparing BIGNUMs is a pain! */
443*99ebb4caSwyllys 		bn = ASN1_INTEGER_to_BN(xcert->cert_info->serialNumber, NULL);
444*99ebb4caSwyllys 		if (bn != NULL) {
445*99ebb4caSwyllys 			int bnlen = BN_num_bytes(bn);
446*99ebb4caSwyllys 
447*99ebb4caSwyllys 			if (bnlen == params->serial->len) {
448*99ebb4caSwyllys 				uchar_t *a = malloc(bnlen);
449*99ebb4caSwyllys 				if (a == NULL) {
450*99ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
451*99ebb4caSwyllys 					BN_free(bn);
452*99ebb4caSwyllys 					goto cleanup;
453*99ebb4caSwyllys 				}
454*99ebb4caSwyllys 				bnlen = BN_bn2bin(bn, a);
455*99ebb4caSwyllys 				*match = !memcmp(a,
456*99ebb4caSwyllys 					params->serial->val,
457*99ebb4caSwyllys 					params->serial->len);
458*99ebb4caSwyllys 				rv = KMF_OK;
459*99ebb4caSwyllys 				free(a);
460*99ebb4caSwyllys 			}
461*99ebb4caSwyllys 			BN_free(bn);
462*99ebb4caSwyllys 			if (!(*match))
463*99ebb4caSwyllys 				goto cleanup;
464*99ebb4caSwyllys 		} else {
465*99ebb4caSwyllys 			rv = KMF_OK;
466*99ebb4caSwyllys 			goto cleanup;
467*99ebb4caSwyllys 		}
468*99ebb4caSwyllys 	}
469*99ebb4caSwyllys 	if (findIssuer) {
470*99ebb4caSwyllys 		*match = !KMF_CompareRDNs(&issuerDN, &certIssuerDN);
471*99ebb4caSwyllys 		if (!(*match)) {
472*99ebb4caSwyllys 			rv = KMF_OK;
473*99ebb4caSwyllys 			goto cleanup;
474*99ebb4caSwyllys 		}
475*99ebb4caSwyllys 	}
476*99ebb4caSwyllys 	if (findSubject) {
477*99ebb4caSwyllys 		*match = !KMF_CompareRDNs(&subjectDN, &certSubjectDN);
478*99ebb4caSwyllys 		if (!(*match)) {
479*99ebb4caSwyllys 			rv = KMF_OK;
480*99ebb4caSwyllys 			goto cleanup;
481*99ebb4caSwyllys 		}
482*99ebb4caSwyllys 	}
483*99ebb4caSwyllys 
484*99ebb4caSwyllys 	*match = TRUE;
485*99ebb4caSwyllys cleanup:
486*99ebb4caSwyllys 	if (findIssuer) {
487*99ebb4caSwyllys 		KMF_FreeDN(&issuerDN);
488*99ebb4caSwyllys 		KMF_FreeDN(&certIssuerDN);
489*99ebb4caSwyllys 	}
490*99ebb4caSwyllys 	if (findSubject) {
491*99ebb4caSwyllys 		KMF_FreeDN(&subjectDN);
492*99ebb4caSwyllys 		KMF_FreeDN(&certSubjectDN);
493*99ebb4caSwyllys 	}
494*99ebb4caSwyllys 
495*99ebb4caSwyllys 	return (rv);
496*99ebb4caSwyllys }
497*99ebb4caSwyllys 
498*99ebb4caSwyllys static KMF_RETURN
499*99ebb4caSwyllys load_X509cert(KMF_HANDLE *kmfh,
500*99ebb4caSwyllys 	KMF_FINDCERT_PARAMS *params,
501*99ebb4caSwyllys 	char *pathname,
502*99ebb4caSwyllys 	X509 **outcert)
503*99ebb4caSwyllys {
504*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
505*99ebb4caSwyllys 	X509 *xcert = NULL;
506*99ebb4caSwyllys 	BIO *bcert = NULL;
507*99ebb4caSwyllys 	boolean_t  match = FALSE;
508*99ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
509*99ebb4caSwyllys 
510*99ebb4caSwyllys 	/*
511*99ebb4caSwyllys 	 * auto-detect the file format, regardless of what
512*99ebb4caSwyllys 	 * the 'format' parameters in the params say.
513*99ebb4caSwyllys 	 */
514*99ebb4caSwyllys 	rv = KMF_GetFileFormat(pathname, &format);
515*99ebb4caSwyllys 	if (rv != KMF_OK) {
516*99ebb4caSwyllys 		if (rv == KMF_ERR_OPEN_FILE)
517*99ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
518*99ebb4caSwyllys 		return (rv);
519*99ebb4caSwyllys 	}
520*99ebb4caSwyllys 
521*99ebb4caSwyllys 	/* Not ASN1(DER) format */
522*99ebb4caSwyllys 	if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
523*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
524*99ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
525*99ebb4caSwyllys 		goto cleanup;
526*99ebb4caSwyllys 	}
527*99ebb4caSwyllys 
528*99ebb4caSwyllys 	if (format == KMF_FORMAT_PEM)
529*99ebb4caSwyllys 		xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
530*99ebb4caSwyllys 	else if (format == KMF_FORMAT_ASN1)
531*99ebb4caSwyllys 		xcert = d2i_X509_bio(bcert, NULL);
532*99ebb4caSwyllys 	else if (format == KMF_FORMAT_PKCS12) {
533*99ebb4caSwyllys 		PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
534*99ebb4caSwyllys 		if (p12 != NULL) {
535*99ebb4caSwyllys 			(void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
536*99ebb4caSwyllys 			PKCS12_free(p12);
537*99ebb4caSwyllys 			p12 = NULL;
538*99ebb4caSwyllys 		} else {
539*99ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
540*99ebb4caSwyllys 			rv = KMF_ERR_BAD_CERT_FORMAT;
541*99ebb4caSwyllys 		}
542*99ebb4caSwyllys 	} else {
543*99ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
544*99ebb4caSwyllys 		goto cleanup;
545*99ebb4caSwyllys 	}
546*99ebb4caSwyllys 
547*99ebb4caSwyllys 	if (xcert == NULL) {
548*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
549*99ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
550*99ebb4caSwyllys 		goto cleanup;
551*99ebb4caSwyllys 	}
552*99ebb4caSwyllys 
553*99ebb4caSwyllys 	if (check_cert(xcert, params, &match) != KMF_OK || match == FALSE) {
554*99ebb4caSwyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
555*99ebb4caSwyllys 		goto cleanup;
556*99ebb4caSwyllys 	}
557*99ebb4caSwyllys 
558*99ebb4caSwyllys 	if (outcert != NULL) {
559*99ebb4caSwyllys 		*outcert = xcert;
560*99ebb4caSwyllys 	}
561*99ebb4caSwyllys 
562*99ebb4caSwyllys cleanup:
563*99ebb4caSwyllys 	if (bcert != NULL) (void) BIO_free(bcert);
564*99ebb4caSwyllys 	if (rv != KMF_OK && xcert != NULL)
565*99ebb4caSwyllys 		X509_free(xcert);
566*99ebb4caSwyllys 
567*99ebb4caSwyllys 	return (rv);
568*99ebb4caSwyllys }
569*99ebb4caSwyllys 
570*99ebb4caSwyllys static KMF_RETURN
571*99ebb4caSwyllys kmf_load_cert(KMF_HANDLE *kmfh,
572*99ebb4caSwyllys 	KMF_FINDCERT_PARAMS *params,
573*99ebb4caSwyllys 	char *pathname,
574*99ebb4caSwyllys 	KMF_DATA *cert)
575*99ebb4caSwyllys {
576*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
577*99ebb4caSwyllys 	X509 *x509cert = NULL;
578*99ebb4caSwyllys 
579*99ebb4caSwyllys 	rv = load_X509cert(kmfh, params, pathname, &x509cert);
580*99ebb4caSwyllys 	if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
581*99ebb4caSwyllys 		rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
582*99ebb4caSwyllys 		if (rv != KMF_OK) {
583*99ebb4caSwyllys 			goto cleanup;
584*99ebb4caSwyllys 		}
585*99ebb4caSwyllys 		if (params->find_cert_validity == KMF_NONEXPIRED_CERTS) {
586*99ebb4caSwyllys 			rv = KMF_CheckCertDate(kmfh, cert);
587*99ebb4caSwyllys 		} else if (params->find_cert_validity == KMF_EXPIRED_CERTS) {
588*99ebb4caSwyllys 			rv = KMF_CheckCertDate(kmfh, cert);
589*99ebb4caSwyllys 			if (rv == KMF_OK)  {
590*99ebb4caSwyllys 				/*
591*99ebb4caSwyllys 				 * This is a valid cert so skip it.
592*99ebb4caSwyllys 				 */
593*99ebb4caSwyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
594*99ebb4caSwyllys 			}
595*99ebb4caSwyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD) {
596*99ebb4caSwyllys 				/*
597*99ebb4caSwyllys 				 * We want to return success when we
598*99ebb4caSwyllys 				 * find an invalid cert.
599*99ebb4caSwyllys 				 */
600*99ebb4caSwyllys 				rv = KMF_OK;
601*99ebb4caSwyllys 				goto cleanup;
602*99ebb4caSwyllys 			}
603*99ebb4caSwyllys 		}
604*99ebb4caSwyllys 	}
605*99ebb4caSwyllys cleanup:
606*99ebb4caSwyllys 	if (x509cert != NULL)
607*99ebb4caSwyllys 		X509_free(x509cert);
608*99ebb4caSwyllys 
609*99ebb4caSwyllys 	return (rv);
610*99ebb4caSwyllys }
611*99ebb4caSwyllys 
612*99ebb4caSwyllys static EVP_PKEY *
613*99ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file)
614*99ebb4caSwyllys {
615*99ebb4caSwyllys 	BIO *keyfile = NULL;
616*99ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
617*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
618*99ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
619*99ebb4caSwyllys 
620*99ebb4caSwyllys 	if (file == NULL) {
621*99ebb4caSwyllys 		return (NULL);
622*99ebb4caSwyllys 	}
623*99ebb4caSwyllys 
624*99ebb4caSwyllys 	if (KMF_GetFileFormat((char *)file, &format) != KMF_OK)
625*99ebb4caSwyllys 		return (NULL);
626*99ebb4caSwyllys 
627*99ebb4caSwyllys 	keyfile = BIO_new_file(file, "rb");
628*99ebb4caSwyllys 	if (keyfile == NULL) {
629*99ebb4caSwyllys 		goto end;
630*99ebb4caSwyllys 	}
631*99ebb4caSwyllys 
632*99ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1)
633*99ebb4caSwyllys 		pkey = d2i_PrivateKey_bio(keyfile, NULL);
634*99ebb4caSwyllys 	else if (format == KMF_FORMAT_PEM)
635*99ebb4caSwyllys 		pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
636*99ebb4caSwyllys 
637*99ebb4caSwyllys end:
638*99ebb4caSwyllys 	if (pkey == NULL)
639*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
640*99ebb4caSwyllys 
641*99ebb4caSwyllys 	if (keyfile != NULL)
642*99ebb4caSwyllys 		(void) BIO_free(keyfile);
643*99ebb4caSwyllys 
644*99ebb4caSwyllys 	return (pkey);
645*99ebb4caSwyllys }
646*99ebb4caSwyllys 
647*99ebb4caSwyllys KMF_RETURN
648*99ebb4caSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle,
649*99ebb4caSwyllys 	KMF_FINDCERT_PARAMS *params,
650*99ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert,
651*99ebb4caSwyllys 	uint32_t *num_certs)
652*99ebb4caSwyllys {
653*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
654*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
655*99ebb4caSwyllys 	KMF_DATA certdata = {NULL, 0};
656*99ebb4caSwyllys 	char *fullpath;
657*99ebb4caSwyllys 
658*99ebb4caSwyllys 	if (num_certs == NULL || params == NULL)
659*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
660*99ebb4caSwyllys 
661*99ebb4caSwyllys 	*num_certs = 0;
662*99ebb4caSwyllys 
663*99ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
664*99ebb4caSwyllys 		params->sslparms.certfile);
665*99ebb4caSwyllys 
666*99ebb4caSwyllys 	if (fullpath == NULL)
667*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
668*99ebb4caSwyllys 
669*99ebb4caSwyllys 	if (isdir(fullpath)) {
670*99ebb4caSwyllys 		DIR *dirp;
671*99ebb4caSwyllys 		struct dirent *dp;
672*99ebb4caSwyllys 		int n = 0;
673*99ebb4caSwyllys 
674*99ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
675*99ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
676*99ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
677*99ebb4caSwyllys 		}
678*99ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
679*99ebb4caSwyllys 			char *fname;
680*99ebb4caSwyllys 			if (strcmp(dp->d_name, ".") == 0 ||
681*99ebb4caSwyllys 			    strcmp(dp->d_name, "..") == 0)
682*99ebb4caSwyllys 				continue;
683*99ebb4caSwyllys 
684*99ebb4caSwyllys 			fname = get_fullpath(fullpath,
685*99ebb4caSwyllys 				(char *)&dp->d_name);
686*99ebb4caSwyllys 
687*99ebb4caSwyllys 			rv = kmf_load_cert(kmfh, params, fname,
688*99ebb4caSwyllys 				&certdata);
689*99ebb4caSwyllys 
690*99ebb4caSwyllys 			if (rv != KMF_OK) {
691*99ebb4caSwyllys 				free(fname);
692*99ebb4caSwyllys 				KMF_FreeData(&certdata);
693*99ebb4caSwyllys 				continue;
694*99ebb4caSwyllys 			}
695*99ebb4caSwyllys 
696*99ebb4caSwyllys 			/* If load succeeds, add certdata to the list */
697*99ebb4caSwyllys 			if (kmf_cert != NULL) {
698*99ebb4caSwyllys 				kmf_cert[n].certificate.Data = certdata.Data;
699*99ebb4caSwyllys 				kmf_cert[n].certificate.Length =
700*99ebb4caSwyllys 					certdata.Length;
701*99ebb4caSwyllys 
702*99ebb4caSwyllys 				kmf_cert[n].kmf_private.keystore_type =
703*99ebb4caSwyllys 					KMF_KEYSTORE_OPENSSL;
704*99ebb4caSwyllys 				kmf_cert[n].kmf_private.flags =
705*99ebb4caSwyllys 					KMF_FLAG_CERT_VALID;
706*99ebb4caSwyllys 				kmf_cert[n].kmf_private.label = fname;
707*99ebb4caSwyllys 			} else {
708*99ebb4caSwyllys 				free(fname);
709*99ebb4caSwyllys 				KMF_FreeData(&certdata);
710*99ebb4caSwyllys 			}
711*99ebb4caSwyllys 			n++;
712*99ebb4caSwyllys 		}
713*99ebb4caSwyllys 		(*num_certs) = n;
714*99ebb4caSwyllys 		if (*num_certs == 0)
715*99ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
716*99ebb4caSwyllys 		if (*num_certs > 0)
717*99ebb4caSwyllys 			rv = KMF_OK;
718*99ebb4caSwyllys exit:
719*99ebb4caSwyllys 		(void) closedir(dirp);
720*99ebb4caSwyllys 	} else {
721*99ebb4caSwyllys 		/* Just try to load a single certificate */
722*99ebb4caSwyllys 		rv = kmf_load_cert(kmfh, params, fullpath, &certdata);
723*99ebb4caSwyllys 		if (rv != KMF_OK) {
724*99ebb4caSwyllys 			free(fullpath);
725*99ebb4caSwyllys 			KMF_FreeData(&certdata);
726*99ebb4caSwyllys 			return (rv);
727*99ebb4caSwyllys 		}
728*99ebb4caSwyllys 
729*99ebb4caSwyllys 		if (kmf_cert != NULL) {
730*99ebb4caSwyllys 			kmf_cert->certificate.Data = certdata.Data;
731*99ebb4caSwyllys 			kmf_cert->certificate.Length = certdata.Length;
732*99ebb4caSwyllys 			kmf_cert->kmf_private.keystore_type =
733*99ebb4caSwyllys 				KMF_KEYSTORE_OPENSSL;
734*99ebb4caSwyllys 			kmf_cert->kmf_private.flags = KMF_FLAG_CERT_VALID;
735*99ebb4caSwyllys 			kmf_cert->kmf_private.label = fullpath;
736*99ebb4caSwyllys 		} else {
737*99ebb4caSwyllys 			KMF_FreeData(&certdata);
738*99ebb4caSwyllys 		}
739*99ebb4caSwyllys 
740*99ebb4caSwyllys 		*num_certs = 1;
741*99ebb4caSwyllys 	}
742*99ebb4caSwyllys 
743*99ebb4caSwyllys 	if (kmf_cert == NULL || rv != KMF_OK)
744*99ebb4caSwyllys 		free(fullpath);
745*99ebb4caSwyllys 
746*99ebb4caSwyllys 	return (rv);
747*99ebb4caSwyllys 
748*99ebb4caSwyllys }
749*99ebb4caSwyllys 
750*99ebb4caSwyllys void
751*99ebb4caSwyllys /*ARGSUSED*/
752*99ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
753*99ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert)
754*99ebb4caSwyllys {
755*99ebb4caSwyllys 	if (kmf_cert != NULL) {
756*99ebb4caSwyllys 		if (kmf_cert->certificate.Data != NULL) {
757*99ebb4caSwyllys 			free(kmf_cert->certificate.Data);
758*99ebb4caSwyllys 			kmf_cert->certificate.Data = NULL;
759*99ebb4caSwyllys 			kmf_cert->certificate.Length = 0;
760*99ebb4caSwyllys 		}
761*99ebb4caSwyllys 		if (kmf_cert->kmf_private.label)
762*99ebb4caSwyllys 			free(kmf_cert->kmf_private.label);
763*99ebb4caSwyllys 	}
764*99ebb4caSwyllys }
765*99ebb4caSwyllys 
766*99ebb4caSwyllys KMF_RETURN
767*99ebb4caSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, KMF_STORECERT_PARAMS *params,
768*99ebb4caSwyllys     KMF_DATA * pcert)
769*99ebb4caSwyllys {
770*99ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
771*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
772*99ebb4caSwyllys 	X509 *xcert = NULL;
773*99ebb4caSwyllys 	FILE *fp;
774*99ebb4caSwyllys 	unsigned char *outbuf;
775*99ebb4caSwyllys 	unsigned char *outbuf_p;
776*99ebb4caSwyllys 	char *fullpath;
777*99ebb4caSwyllys 	int outbuflen;
778*99ebb4caSwyllys 	int len;
779*99ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
780*99ebb4caSwyllys 
781*99ebb4caSwyllys 	if (params == NULL || params->ks_opt_u.openssl_opts.certfile == NULL) {
782*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
783*99ebb4caSwyllys 	}
784*99ebb4caSwyllys 
785*99ebb4caSwyllys 	/*
786*99ebb4caSwyllys 	 * check if the cert output format is supported by OPENSSL.
787*99ebb4caSwyllys 	 * however, since the keystore for OPENSSL is just a file, we have
788*99ebb4caSwyllys 	 * no way to store the format along with the file.
789*99ebb4caSwyllys 	 */
790*99ebb4caSwyllys 	format = params->sslparms.format;
791*99ebb4caSwyllys 	if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM)
792*99ebb4caSwyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
793*99ebb4caSwyllys 
794*99ebb4caSwyllys 
795*99ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
796*99ebb4caSwyllys 		params->sslparms.certfile);
797*99ebb4caSwyllys 	if (fullpath == NULL)
798*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
799*99ebb4caSwyllys 
800*99ebb4caSwyllys 	/*
801*99ebb4caSwyllys 	 * When storing a certificate, you must specify a filename.
802*99ebb4caSwyllys 	 */
803*99ebb4caSwyllys 	if (isdir(fullpath)) {
804*99ebb4caSwyllys 		free(fullpath);
805*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
806*99ebb4caSwyllys 	}
807*99ebb4caSwyllys 
808*99ebb4caSwyllys 	/* copy cert data to outbuf */
809*99ebb4caSwyllys 	outbuflen = pcert->Length;
810*99ebb4caSwyllys 	outbuf = malloc(outbuflen);
811*99ebb4caSwyllys 	if (outbuf == NULL) {
812*99ebb4caSwyllys 		free(fullpath);
813*99ebb4caSwyllys 		return (KMF_ERR_MEMORY);
814*99ebb4caSwyllys 	}
815*99ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
816*99ebb4caSwyllys 
817*99ebb4caSwyllys 	if ((fp = fopen(fullpath, "w")) ==
818*99ebb4caSwyllys 		NULL) {
819*99ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
820*99ebb4caSwyllys 		ret = KMF_ERR_INTERNAL;
821*99ebb4caSwyllys 		goto out;
822*99ebb4caSwyllys 	}
823*99ebb4caSwyllys 
824*99ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
825*99ebb4caSwyllys 		len = fwrite(outbuf, 1, outbuflen, fp);
826*99ebb4caSwyllys 		if (len != outbuflen) {
827*99ebb4caSwyllys 			SET_SYS_ERROR(kmfh, errno);
828*99ebb4caSwyllys 			ret = KMF_ERR_WRITE_FILE;
829*99ebb4caSwyllys 		} else {
830*99ebb4caSwyllys 			ret = KMF_OK;
831*99ebb4caSwyllys 		}
832*99ebb4caSwyllys 		goto out;
833*99ebb4caSwyllys 	}
834*99ebb4caSwyllys 
835*99ebb4caSwyllys 	/*
836*99ebb4caSwyllys 	 * The output format is not KMF_FORMAT_ASN1, so we will
837*99ebb4caSwyllys 	 * Convert the cert data to OpenSSL internal X509 first.
838*99ebb4caSwyllys 	 */
839*99ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
840*99ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, outbuflen);
841*99ebb4caSwyllys 	if (xcert == NULL) {
842*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
843*99ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
844*99ebb4caSwyllys 		goto out;
845*99ebb4caSwyllys 	}
846*99ebb4caSwyllys 
847*99ebb4caSwyllys 	if (format == KMF_FORMAT_PEM) {
848*99ebb4caSwyllys 		/* Convert to the PEM format and write it out */
849*99ebb4caSwyllys 		if (!PEM_write_X509(fp, xcert)) {
850*99ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
851*99ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
852*99ebb4caSwyllys 		} else {
853*99ebb4caSwyllys 			ret = KMF_OK;
854*99ebb4caSwyllys 		}
855*99ebb4caSwyllys 		goto out;
856*99ebb4caSwyllys 	}
857*99ebb4caSwyllys 
858*99ebb4caSwyllys out:
859*99ebb4caSwyllys 	if (fullpath != NULL)
860*99ebb4caSwyllys 		free(fullpath);
861*99ebb4caSwyllys 
862*99ebb4caSwyllys 	if (outbuf != NULL) {
863*99ebb4caSwyllys 		free(outbuf);
864*99ebb4caSwyllys 	}
865*99ebb4caSwyllys 	if (fp != NULL) {
866*99ebb4caSwyllys 		(void) fclose(fp);
867*99ebb4caSwyllys 	}
868*99ebb4caSwyllys 
869*99ebb4caSwyllys 	if (xcert != NULL) {
870*99ebb4caSwyllys 		X509_free(xcert);
871*99ebb4caSwyllys 	}
872*99ebb4caSwyllys 
873*99ebb4caSwyllys 	return (ret);
874*99ebb4caSwyllys }
875*99ebb4caSwyllys 
876*99ebb4caSwyllys KMF_RETURN
877*99ebb4caSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, KMF_DELETECERT_PARAMS *params)
878*99ebb4caSwyllys {
879*99ebb4caSwyllys 	KMF_RETURN rv;
880*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
881*99ebb4caSwyllys 	char *fullpath = NULL;
882*99ebb4caSwyllys 	KMF_DATA certdata = {NULL, 0};
883*99ebb4caSwyllys 
884*99ebb4caSwyllys 	if (params == NULL) {
885*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
886*99ebb4caSwyllys 	}
887*99ebb4caSwyllys 
888*99ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
889*99ebb4caSwyllys 		params->sslparms.certfile);
890*99ebb4caSwyllys 
891*99ebb4caSwyllys 	if (fullpath == NULL)
892*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
893*99ebb4caSwyllys 
894*99ebb4caSwyllys 	if (isdir(fullpath)) {
895*99ebb4caSwyllys 		DIR *dirp;
896*99ebb4caSwyllys 		struct dirent *dp;
897*99ebb4caSwyllys 
898*99ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
899*99ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
900*99ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
901*99ebb4caSwyllys 		}
902*99ebb4caSwyllys 
903*99ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
904*99ebb4caSwyllys 			if (strcmp(dp->d_name, ".") != 0 &&
905*99ebb4caSwyllys 			    strcmp(dp->d_name, "..") != 0) {
906*99ebb4caSwyllys 				char *fname;
907*99ebb4caSwyllys 
908*99ebb4caSwyllys 				fname = get_fullpath(fullpath,
909*99ebb4caSwyllys 					(char *)&dp->d_name);
910*99ebb4caSwyllys 
911*99ebb4caSwyllys 				if (fname == NULL) {
912*99ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
913*99ebb4caSwyllys 					break;
914*99ebb4caSwyllys 				}
915*99ebb4caSwyllys 
916*99ebb4caSwyllys 				rv = kmf_load_cert(kmfh, params, fname,
917*99ebb4caSwyllys 				    &certdata);
918*99ebb4caSwyllys 
919*99ebb4caSwyllys 				if (rv == KMF_ERR_CERT_NOT_FOUND) {
920*99ebb4caSwyllys 					free(fname);
921*99ebb4caSwyllys 					if (certdata.Data)
922*99ebb4caSwyllys 						free(certdata.Data);
923*99ebb4caSwyllys 					rv = KMF_OK;
924*99ebb4caSwyllys 					continue;
925*99ebb4caSwyllys 				} else if (rv != KMF_OK) {
926*99ebb4caSwyllys 					free(fname);
927*99ebb4caSwyllys 					break;
928*99ebb4caSwyllys 				}
929*99ebb4caSwyllys 
930*99ebb4caSwyllys 				if (unlink(fname) != 0) {
931*99ebb4caSwyllys 					SET_SYS_ERROR(kmfh, errno);
932*99ebb4caSwyllys 					rv = KMF_ERR_INTERNAL;
933*99ebb4caSwyllys 					free(fname);
934*99ebb4caSwyllys 					break;
935*99ebb4caSwyllys 				}
936*99ebb4caSwyllys 				free(fname);
937*99ebb4caSwyllys 				if (certdata.Data)
938*99ebb4caSwyllys 					free(certdata.Data);
939*99ebb4caSwyllys 			}
940*99ebb4caSwyllys 		}
941*99ebb4caSwyllys 		(void) closedir(dirp);
942*99ebb4caSwyllys 	} else {
943*99ebb4caSwyllys 		/* Just try to load a single certificate */
944*99ebb4caSwyllys 		rv = kmf_load_cert(kmfh, params, fullpath, &certdata);
945*99ebb4caSwyllys 		if (rv == KMF_OK) {
946*99ebb4caSwyllys 			if (unlink(fullpath) != 0) {
947*99ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
948*99ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
949*99ebb4caSwyllys 			}
950*99ebb4caSwyllys 		}
951*99ebb4caSwyllys 	}
952*99ebb4caSwyllys 
953*99ebb4caSwyllys out:
954*99ebb4caSwyllys 	if (fullpath != NULL)
955*99ebb4caSwyllys 		free(fullpath);
956*99ebb4caSwyllys 
957*99ebb4caSwyllys 	if (certdata.Data)
958*99ebb4caSwyllys 		free(certdata.Data);
959*99ebb4caSwyllys 
960*99ebb4caSwyllys 	return (rv);
961*99ebb4caSwyllys }
962*99ebb4caSwyllys 
963*99ebb4caSwyllys KMF_RETURN
964*99ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
965*99ebb4caSwyllys 	KMF_DATA *keydata)
966*99ebb4caSwyllys {
967*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
968*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
969*99ebb4caSwyllys 	int n;
970*99ebb4caSwyllys 
971*99ebb4caSwyllys 	if (key == NULL || keydata == NULL ||
972*99ebb4caSwyllys 	    key->keyp == NULL)
973*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
974*99ebb4caSwyllys 
975*99ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
976*99ebb4caSwyllys 		RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
977*99ebb4caSwyllys 
978*99ebb4caSwyllys 		if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
979*99ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
980*99ebb4caSwyllys 			return (KMF_ERR_ENCODING);
981*99ebb4caSwyllys 		}
982*99ebb4caSwyllys 		RSA_free(pubkey);
983*99ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
984*99ebb4caSwyllys 		DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
985*99ebb4caSwyllys 
986*99ebb4caSwyllys 		if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
987*99ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
988*99ebb4caSwyllys 			return (KMF_ERR_ENCODING);
989*99ebb4caSwyllys 		}
990*99ebb4caSwyllys 		DSA_free(pubkey);
991*99ebb4caSwyllys 	} else {
992*99ebb4caSwyllys 	    return (KMF_ERR_BAD_PARAMETER);
993*99ebb4caSwyllys 	}
994*99ebb4caSwyllys 	keydata->Length = n;
995*99ebb4caSwyllys 
996*99ebb4caSwyllys cleanup:
997*99ebb4caSwyllys 	if (rv != KMF_OK) {
998*99ebb4caSwyllys 		if (keydata->Data)
999*99ebb4caSwyllys 			free(keydata->Data);
1000*99ebb4caSwyllys 		keydata->Data = NULL;
1001*99ebb4caSwyllys 		keydata->Length = 0;
1002*99ebb4caSwyllys 	}
1003*99ebb4caSwyllys 
1004*99ebb4caSwyllys 	return (rv);
1005*99ebb4caSwyllys }
1006*99ebb4caSwyllys 
1007*99ebb4caSwyllys static KMF_RETURN
1008*99ebb4caSwyllys ssl_write_private_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
1009*99ebb4caSwyllys 	KMF_CREDENTIAL *cred, EVP_PKEY *pkey)
1010*99ebb4caSwyllys {
1011*99ebb4caSwyllys 	int rv = 0;
1012*99ebb4caSwyllys 	RSA *rsa;
1013*99ebb4caSwyllys 	DSA *dsa;
1014*99ebb4caSwyllys 
1015*99ebb4caSwyllys 	switch (format) {
1016*99ebb4caSwyllys 		case KMF_FORMAT_ASN1:
1017*99ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
1018*99ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
1019*99ebb4caSwyllys 				rv = i2d_RSAPrivateKey_bio(out, rsa);
1020*99ebb4caSwyllys 				RSA_free(rsa);
1021*99ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
1022*99ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
1023*99ebb4caSwyllys 				rv = i2d_DSAPrivateKey_bio(out, dsa);
1024*99ebb4caSwyllys 				DSA_free(dsa);
1025*99ebb4caSwyllys 			}
1026*99ebb4caSwyllys 			if (rv == 1) {
1027*99ebb4caSwyllys 				rv = KMF_OK;
1028*99ebb4caSwyllys 			} else {
1029*99ebb4caSwyllys 				SET_ERROR(kmfh, rv);
1030*99ebb4caSwyllys 			}
1031*99ebb4caSwyllys 			break;
1032*99ebb4caSwyllys 		case KMF_FORMAT_PEM:
1033*99ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
1034*99ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
1035*99ebb4caSwyllys 				rv = PEM_write_bio_RSAPrivateKey(out,
1036*99ebb4caSwyllys 					rsa,
1037*99ebb4caSwyllys 					NULL /* encryption type */,
1038*99ebb4caSwyllys 					NULL, 0, NULL,
1039*99ebb4caSwyllys 					cred->cred);
1040*99ebb4caSwyllys 				RSA_free(rsa);
1041*99ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
1042*99ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
1043*99ebb4caSwyllys 				rv = PEM_write_bio_DSAPrivateKey(out,
1044*99ebb4caSwyllys 					dsa,
1045*99ebb4caSwyllys 					NULL /* encryption type */,
1046*99ebb4caSwyllys 					NULL, 0, NULL,
1047*99ebb4caSwyllys 					cred->cred);
1048*99ebb4caSwyllys 				DSA_free(dsa);
1049*99ebb4caSwyllys 			}
1050*99ebb4caSwyllys 
1051*99ebb4caSwyllys 			if (rv == 1) {
1052*99ebb4caSwyllys 				rv = KMF_OK;
1053*99ebb4caSwyllys 			} else {
1054*99ebb4caSwyllys 				SET_ERROR(kmfh, rv);
1055*99ebb4caSwyllys 			}
1056*99ebb4caSwyllys 			break;
1057*99ebb4caSwyllys 
1058*99ebb4caSwyllys 		default:
1059*99ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
1060*99ebb4caSwyllys 	}
1061*99ebb4caSwyllys 
1062*99ebb4caSwyllys 	return (rv);
1063*99ebb4caSwyllys }
1064*99ebb4caSwyllys 
1065*99ebb4caSwyllys KMF_RETURN
1066*99ebb4caSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, KMF_CREATEKEYPAIR_PARAMS *params,
1067*99ebb4caSwyllys 	KMF_KEY_HANDLE *privkey, KMF_KEY_HANDLE *pubkey)
1068*99ebb4caSwyllys {
1069*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
1070*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1071*99ebb4caSwyllys 	int format;
1072*99ebb4caSwyllys 	uint32_t eValue = 0x010001;
1073*99ebb4caSwyllys 	RSA *sslPrivKey = NULL;
1074*99ebb4caSwyllys 	DSA *sslDSAKey = NULL;
1075*99ebb4caSwyllys 	EVP_PKEY *eprikey = NULL;
1076*99ebb4caSwyllys 	EVP_PKEY *epubkey = NULL;
1077*99ebb4caSwyllys 	BIO *out = NULL;
1078*99ebb4caSwyllys 	char *fullpath = NULL;
1079*99ebb4caSwyllys 
1080*99ebb4caSwyllys 	if (params == NULL || params->sslparms.keyfile == NULL) {
1081*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1082*99ebb4caSwyllys 	}
1083*99ebb4caSwyllys 
1084*99ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
1085*99ebb4caSwyllys 			params->sslparms.keyfile);
1086*99ebb4caSwyllys 
1087*99ebb4caSwyllys 	if (fullpath == NULL)
1088*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1089*99ebb4caSwyllys 
1090*99ebb4caSwyllys 	/* If the requested file exists, return an error */
1091*99ebb4caSwyllys 	if (access(fullpath, F_OK) == 0) {
1092*99ebb4caSwyllys 		free(fullpath);
1093*99ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
1094*99ebb4caSwyllys 	}
1095*99ebb4caSwyllys 
1096*99ebb4caSwyllys 	eprikey = EVP_PKEY_new();
1097*99ebb4caSwyllys 	if (eprikey == NULL) {
1098*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1099*99ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
1100*99ebb4caSwyllys 		goto cleanup;
1101*99ebb4caSwyllys 	}
1102*99ebb4caSwyllys 	epubkey = EVP_PKEY_new();
1103*99ebb4caSwyllys 	if (epubkey == NULL) {
1104*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1105*99ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
1106*99ebb4caSwyllys 		goto cleanup;
1107*99ebb4caSwyllys 	}
1108*99ebb4caSwyllys 	if (params->keytype == KMF_RSA) {
1109*99ebb4caSwyllys 		if (params->rsa_exponent.len > 0 &&
1110*99ebb4caSwyllys 		    params->rsa_exponent.len <= sizeof (eValue) &&
1111*99ebb4caSwyllys 		    params->rsa_exponent.val != NULL)
1112*99ebb4caSwyllys 			/*LINTED*/
1113*99ebb4caSwyllys 			eValue = *(uint32_t *)params->rsa_exponent.val;
1114*99ebb4caSwyllys 
1115*99ebb4caSwyllys 		sslPrivKey = RSA_generate_key(params->keylength, eValue,
1116*99ebb4caSwyllys 			NULL, NULL);
1117*99ebb4caSwyllys 		if (sslPrivKey == NULL) {
1118*99ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
1119*99ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
1120*99ebb4caSwyllys 		} else {
1121*99ebb4caSwyllys 			if (privkey != NULL &&
1122*99ebb4caSwyllys 				EVP_PKEY_set1_RSA(eprikey, sslPrivKey)) {
1123*99ebb4caSwyllys 				privkey->kstype = KMF_KEYSTORE_OPENSSL;
1124*99ebb4caSwyllys 				privkey->keyalg = KMF_RSA;
1125*99ebb4caSwyllys 				privkey->keyclass = KMF_ASYM_PRI;
1126*99ebb4caSwyllys 				privkey->israw = FALSE;
1127*99ebb4caSwyllys 				privkey->keylabel = (char *)strdup(fullpath);
1128*99ebb4caSwyllys 				privkey->keyp = (void *)eprikey;
1129*99ebb4caSwyllys 			}
1130*99ebb4caSwyllys 			/* OpenSSL derives the public key from the private */
1131*99ebb4caSwyllys 			if (pubkey != NULL &&
1132*99ebb4caSwyllys 				EVP_PKEY_set1_RSA(epubkey, sslPrivKey)) {
1133*99ebb4caSwyllys 				pubkey->kstype = KMF_KEYSTORE_OPENSSL;
1134*99ebb4caSwyllys 				pubkey->keyalg = KMF_RSA;
1135*99ebb4caSwyllys 				pubkey->israw = FALSE;
1136*99ebb4caSwyllys 				pubkey->keyclass = KMF_ASYM_PUB;
1137*99ebb4caSwyllys 				pubkey->keylabel = (char *)strdup(fullpath);
1138*99ebb4caSwyllys 				pubkey->keyp = (void *)epubkey;
1139*99ebb4caSwyllys 			}
1140*99ebb4caSwyllys 		}
1141*99ebb4caSwyllys 	} else if (params->keytype == KMF_DSA) {
1142*99ebb4caSwyllys 		sslDSAKey = DSA_new();
1143*99ebb4caSwyllys 		if (sslDSAKey == NULL) {
1144*99ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
1145*99ebb4caSwyllys 			return (KMF_ERR_MEMORY);
1146*99ebb4caSwyllys 		}
1147*99ebb4caSwyllys 
1148*99ebb4caSwyllys 		if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) ==
1149*99ebb4caSwyllys 			NULL) {
1150*99ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
1151*99ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
1152*99ebb4caSwyllys 			goto cleanup;
1153*99ebb4caSwyllys 		}
1154*99ebb4caSwyllys 		if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) ==
1155*99ebb4caSwyllys 			NULL) {
1156*99ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
1157*99ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
1158*99ebb4caSwyllys 			goto cleanup;
1159*99ebb4caSwyllys 		}
1160*99ebb4caSwyllys 		if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) ==
1161*99ebb4caSwyllys 			NULL) {
1162*99ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
1163*99ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
1164*99ebb4caSwyllys 			goto cleanup;
1165*99ebb4caSwyllys 		}
1166*99ebb4caSwyllys 
1167*99ebb4caSwyllys 		if (!DSA_generate_key(sslDSAKey)) {
1168*99ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
1169*99ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
1170*99ebb4caSwyllys 			goto cleanup;
1171*99ebb4caSwyllys 		}
1172*99ebb4caSwyllys 
1173*99ebb4caSwyllys 		if (privkey != NULL) {
1174*99ebb4caSwyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
1175*99ebb4caSwyllys 			privkey->keyalg = KMF_DSA;
1176*99ebb4caSwyllys 			privkey->keyclass = KMF_ASYM_PRI;
1177*99ebb4caSwyllys 			privkey->israw = FALSE;
1178*99ebb4caSwyllys 			privkey->keylabel = (char *)strdup(fullpath);
1179*99ebb4caSwyllys 			if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
1180*99ebb4caSwyllys 				privkey->keyp = (void *)eprikey;
1181*99ebb4caSwyllys 			} else {
1182*99ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
1183*99ebb4caSwyllys 				rv = KMF_ERR_KEYGEN_FAILED;
1184*99ebb4caSwyllys 				goto cleanup;
1185*99ebb4caSwyllys 			}
1186*99ebb4caSwyllys 		}
1187*99ebb4caSwyllys 		if (pubkey != NULL) {
1188*99ebb4caSwyllys 			DSA *dp = DSA_new();
1189*99ebb4caSwyllys 			/* Make a copy for the public key */
1190*99ebb4caSwyllys 			if (dp != NULL) {
1191*99ebb4caSwyllys 				if ((dp->p = BN_new()) == NULL) {
1192*99ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
1193*99ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
1194*99ebb4caSwyllys 					DSA_free(dp);
1195*99ebb4caSwyllys 					goto cleanup;
1196*99ebb4caSwyllys 				}
1197*99ebb4caSwyllys 				if ((dp->q = BN_new()) == NULL) {
1198*99ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
1199*99ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
1200*99ebb4caSwyllys 					BN_free(dp->p);
1201*99ebb4caSwyllys 					DSA_free(dp);
1202*99ebb4caSwyllys 					goto cleanup;
1203*99ebb4caSwyllys 				}
1204*99ebb4caSwyllys 				if ((dp->g = BN_new()) == NULL) {
1205*99ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
1206*99ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
1207*99ebb4caSwyllys 					BN_free(dp->q);
1208*99ebb4caSwyllys 					BN_free(dp->p);
1209*99ebb4caSwyllys 					DSA_free(dp);
1210*99ebb4caSwyllys 					goto cleanup;
1211*99ebb4caSwyllys 				}
1212*99ebb4caSwyllys 				if ((dp->pub_key = BN_new()) == NULL) {
1213*99ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
1214*99ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
1215*99ebb4caSwyllys 					BN_free(dp->q);
1216*99ebb4caSwyllys 					BN_free(dp->p);
1217*99ebb4caSwyllys 					BN_free(dp->g);
1218*99ebb4caSwyllys 					DSA_free(dp);
1219*99ebb4caSwyllys 					goto cleanup;
1220*99ebb4caSwyllys 				}
1221*99ebb4caSwyllys 				(void) BN_copy(dp->p, sslDSAKey->p);
1222*99ebb4caSwyllys 				(void) BN_copy(dp->q, sslDSAKey->q);
1223*99ebb4caSwyllys 				(void) BN_copy(dp->g, sslDSAKey->g);
1224*99ebb4caSwyllys 				(void) BN_copy(dp->pub_key, sslDSAKey->pub_key);
1225*99ebb4caSwyllys 
1226*99ebb4caSwyllys 				pubkey->kstype = KMF_KEYSTORE_OPENSSL;
1227*99ebb4caSwyllys 				pubkey->keyalg = KMF_DSA;
1228*99ebb4caSwyllys 				pubkey->keyclass = KMF_ASYM_PUB;
1229*99ebb4caSwyllys 				pubkey->israw = FALSE;
1230*99ebb4caSwyllys 				pubkey->keylabel = (char *)strdup(fullpath);
1231*99ebb4caSwyllys 
1232*99ebb4caSwyllys 				if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
1233*99ebb4caSwyllys 					pubkey->keyp = (void *)epubkey;
1234*99ebb4caSwyllys 				} else {
1235*99ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
1236*99ebb4caSwyllys 					rv = KMF_ERR_KEYGEN_FAILED;
1237*99ebb4caSwyllys 					goto cleanup;
1238*99ebb4caSwyllys 				}
1239*99ebb4caSwyllys 			}
1240*99ebb4caSwyllys 		}
1241*99ebb4caSwyllys 	}
1242*99ebb4caSwyllys 
1243*99ebb4caSwyllys 	if (rv != KMF_OK) {
1244*99ebb4caSwyllys 		goto cleanup;
1245*99ebb4caSwyllys 	}
1246*99ebb4caSwyllys 
1247*99ebb4caSwyllys 	/* Store the private key to the keyfile */
1248*99ebb4caSwyllys 	format = params->sslparms.format;
1249*99ebb4caSwyllys 	out = BIO_new_file(fullpath, "wb");
1250*99ebb4caSwyllys 	if (out == NULL) {
1251*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1252*99ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
1253*99ebb4caSwyllys 		goto cleanup;
1254*99ebb4caSwyllys 	}
1255*99ebb4caSwyllys 	rv = ssl_write_private_key(kmfh, format, out, &params->cred, eprikey);
1256*99ebb4caSwyllys 
1257*99ebb4caSwyllys cleanup:
1258*99ebb4caSwyllys 	if (rv != KMF_OK) {
1259*99ebb4caSwyllys 		if (eprikey != NULL)
1260*99ebb4caSwyllys 			EVP_PKEY_free(eprikey);
1261*99ebb4caSwyllys 
1262*99ebb4caSwyllys 		if (epubkey != NULL)
1263*99ebb4caSwyllys 			EVP_PKEY_free(epubkey);
1264*99ebb4caSwyllys 
1265*99ebb4caSwyllys 		if (pubkey->keylabel) {
1266*99ebb4caSwyllys 			free(pubkey->keylabel);
1267*99ebb4caSwyllys 			pubkey->keylabel = NULL;
1268*99ebb4caSwyllys 		}
1269*99ebb4caSwyllys 
1270*99ebb4caSwyllys 		if (privkey->keylabel) {
1271*99ebb4caSwyllys 			free(privkey->keylabel);
1272*99ebb4caSwyllys 			privkey->keylabel = NULL;
1273*99ebb4caSwyllys 		}
1274*99ebb4caSwyllys 
1275*99ebb4caSwyllys 		pubkey->keyp = NULL;
1276*99ebb4caSwyllys 		privkey->keyp = NULL;
1277*99ebb4caSwyllys 	}
1278*99ebb4caSwyllys 
1279*99ebb4caSwyllys 	if (sslPrivKey)
1280*99ebb4caSwyllys 		RSA_free(sslPrivKey);
1281*99ebb4caSwyllys 
1282*99ebb4caSwyllys 	if (sslDSAKey)
1283*99ebb4caSwyllys 		DSA_free(sslDSAKey);
1284*99ebb4caSwyllys 
1285*99ebb4caSwyllys 
1286*99ebb4caSwyllys 	if (out != NULL)
1287*99ebb4caSwyllys 		(void) BIO_free(out);
1288*99ebb4caSwyllys 
1289*99ebb4caSwyllys 	if (fullpath)
1290*99ebb4caSwyllys 		free(fullpath);
1291*99ebb4caSwyllys 
1292*99ebb4caSwyllys 	/* Protect the file by making it read-only */
1293*99ebb4caSwyllys 	if (rv == KMF_OK) {
1294*99ebb4caSwyllys 		(void) chmod(fullpath, 0400);
1295*99ebb4caSwyllys 	}
1296*99ebb4caSwyllys 	return (rv);
1297*99ebb4caSwyllys }
1298*99ebb4caSwyllys 
1299*99ebb4caSwyllys KMF_RETURN
1300*99ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1301*99ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
1302*99ebb4caSwyllys {
1303*99ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
1304*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1305*99ebb4caSwyllys 	KMF_ALGORITHM_INDEX		AlgId;
1306*99ebb4caSwyllys 	EVP_MD_CTX ctx;
1307*99ebb4caSwyllys 	const EVP_MD *md;
1308*99ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
1309*99ebb4caSwyllys 		tobesigned == NULL || output == NULL ||
1310*99ebb4caSwyllys 		tobesigned->Data == NULL ||
1311*99ebb4caSwyllys 		output->Data == NULL)
1312*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1313*99ebb4caSwyllys 
1314*99ebb4caSwyllys 	/* Map the OID to an OpenSSL algorithm */
1315*99ebb4caSwyllys 	AlgId = X509_AlgorithmOidToAlgId(AlgOID);
1316*99ebb4caSwyllys 	if (AlgId == KMF_ALGID_NONE)
1317*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1318*99ebb4caSwyllys 
1319*99ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
1320*99ebb4caSwyllys 		EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
1321*99ebb4caSwyllys 		uchar_t *p;
1322*99ebb4caSwyllys 		uint32_t len;
1323*99ebb4caSwyllys 		if (AlgId == KMF_ALGID_MD5WithRSA)
1324*99ebb4caSwyllys 			md = EVP_md5();
1325*99ebb4caSwyllys 		else if (AlgId == KMF_ALGID_MD2WithRSA)
1326*99ebb4caSwyllys 			md = EVP_md2();
1327*99ebb4caSwyllys 		else if (AlgId == KMF_ALGID_SHA1WithRSA)
1328*99ebb4caSwyllys 			md = EVP_sha1();
1329*99ebb4caSwyllys 		else
1330*99ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
1331*99ebb4caSwyllys 
1332*99ebb4caSwyllys 		if (md == NULL) {
1333*99ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
1334*99ebb4caSwyllys 			return (KMF_ERR_MEMORY);
1335*99ebb4caSwyllys 		}
1336*99ebb4caSwyllys 
1337*99ebb4caSwyllys 		(void) EVP_MD_CTX_init(&ctx);
1338*99ebb4caSwyllys 		(void) EVP_SignInit_ex(&ctx, md, NULL);
1339*99ebb4caSwyllys 		(void) EVP_SignUpdate(&ctx, tobesigned->Data,
1340*99ebb4caSwyllys 			(uint32_t)tobesigned->Length);
1341*99ebb4caSwyllys 		len = (uint32_t)output->Length;
1342*99ebb4caSwyllys 		p = output->Data;
1343*99ebb4caSwyllys 		if (!EVP_SignFinal(&ctx, p, &len, pkey)) {
1344*99ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
1345*99ebb4caSwyllys 			output->Length = 0;
1346*99ebb4caSwyllys 		}
1347*99ebb4caSwyllys 		output->Length = len;
1348*99ebb4caSwyllys 		(void) EVP_MD_CTX_cleanup(&ctx);
1349*99ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
1350*99ebb4caSwyllys 		DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
1351*99ebb4caSwyllys 
1352*99ebb4caSwyllys 		uchar_t hash[EVP_MAX_MD_SIZE];
1353*99ebb4caSwyllys 		uint32_t hashlen;
1354*99ebb4caSwyllys 		DSA_SIG *dsasig;
1355*99ebb4caSwyllys 
1356*99ebb4caSwyllys 		/*
1357*99ebb4caSwyllys 		 * OpenSSL EVP_Sign operation automatically converts to
1358*99ebb4caSwyllys 		 * ASN.1 output so we do the operations separately so we
1359*99ebb4caSwyllys 		 * are assured of NOT getting ASN.1 output returned.
1360*99ebb4caSwyllys 		 * KMF does not want ASN.1 encoded results because
1361*99ebb4caSwyllys 		 * not all mechanisms return ASN.1 encodings (PKCS#11
1362*99ebb4caSwyllys 		 * and NSS return raw signature data).
1363*99ebb4caSwyllys 		 */
1364*99ebb4caSwyllys 		md = EVP_sha1();
1365*99ebb4caSwyllys 		EVP_MD_CTX_init(&ctx);
1366*99ebb4caSwyllys 		(void) EVP_DigestInit_ex(&ctx, md, NULL);
1367*99ebb4caSwyllys 		(void) EVP_DigestUpdate(&ctx, tobesigned->Data,
1368*99ebb4caSwyllys 			tobesigned->Length);
1369*99ebb4caSwyllys 		(void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
1370*99ebb4caSwyllys 		(void) EVP_MD_CTX_cleanup(&ctx);
1371*99ebb4caSwyllys 
1372*99ebb4caSwyllys 		dsasig = DSA_do_sign(hash, hashlen, dsa);
1373*99ebb4caSwyllys 		if (dsasig != NULL) {
1374*99ebb4caSwyllys 			int i;
1375*99ebb4caSwyllys 			output->Length = i = BN_bn2bin(dsasig->r, output->Data);
1376*99ebb4caSwyllys 			output->Length += BN_bn2bin(dsasig->s,
1377*99ebb4caSwyllys 				&output->Data[i]);
1378*99ebb4caSwyllys 			DSA_SIG_free(dsasig);
1379*99ebb4caSwyllys 		} else {
1380*99ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
1381*99ebb4caSwyllys 		}
1382*99ebb4caSwyllys 	} else {
1383*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1384*99ebb4caSwyllys 	}
1385*99ebb4caSwyllys cleanup:
1386*99ebb4caSwyllys 	return (ret);
1387*99ebb4caSwyllys }
1388*99ebb4caSwyllys 
1389*99ebb4caSwyllys KMF_RETURN
1390*99ebb4caSwyllys /*ARGSUSED*/
1391*99ebb4caSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle, KMF_DELETEKEY_PARAMS *params,
1392*99ebb4caSwyllys 	KMF_KEY_HANDLE *key, boolean_t destroy)
1393*99ebb4caSwyllys {
1394*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
1395*99ebb4caSwyllys 	if (key == NULL || key->keyp == NULL)
1396*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1397*99ebb4caSwyllys 
1398*99ebb4caSwyllys 	if (key->keyclass != KMF_ASYM_PUB &&
1399*99ebb4caSwyllys 		key->keyclass != KMF_ASYM_PRI &&
1400*99ebb4caSwyllys 		key->keyclass != KMF_SYMMETRIC)
1401*99ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
1402*99ebb4caSwyllys 
1403*99ebb4caSwyllys 	if (key->keyclass == KMF_SYMMETRIC) {
1404*99ebb4caSwyllys 		KMF_FreeRawSymKey((KMF_RAW_SYM_KEY *)key->keyp);
1405*99ebb4caSwyllys 		key->keyp = NULL;
1406*99ebb4caSwyllys 	} else {
1407*99ebb4caSwyllys 		if (key->keyp != NULL) {
1408*99ebb4caSwyllys 			EVP_PKEY_free(key->keyp);
1409*99ebb4caSwyllys 			key->keyp = NULL;
1410*99ebb4caSwyllys 		}
1411*99ebb4caSwyllys 	}
1412*99ebb4caSwyllys 
1413*99ebb4caSwyllys 	if (key->keylabel != NULL) {
1414*99ebb4caSwyllys 		EVP_PKEY *pkey = NULL;
1415*99ebb4caSwyllys 		/* If the file exists, make sure it is a proper key. */
1416*99ebb4caSwyllys 		pkey = openssl_load_key(handle, key->keylabel);
1417*99ebb4caSwyllys 		if (pkey == NULL) {
1418*99ebb4caSwyllys 			free(key->keylabel);
1419*99ebb4caSwyllys 			key->keylabel = NULL;
1420*99ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
1421*99ebb4caSwyllys 		}
1422*99ebb4caSwyllys 		EVP_PKEY_free(pkey);
1423*99ebb4caSwyllys 
1424*99ebb4caSwyllys 		if (destroy) {
1425*99ebb4caSwyllys 			if (unlink(key->keylabel) != 0) {
1426*99ebb4caSwyllys 				KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1427*99ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
1428*99ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
1429*99ebb4caSwyllys 			}
1430*99ebb4caSwyllys 		}
1431*99ebb4caSwyllys 		if (key->keylabel != NULL) {
1432*99ebb4caSwyllys 			free(key->keylabel);
1433*99ebb4caSwyllys 			key->keylabel = NULL;
1434*99ebb4caSwyllys 		}
1435*99ebb4caSwyllys 	}
1436*99ebb4caSwyllys 	return (rv);
1437*99ebb4caSwyllys }
1438*99ebb4caSwyllys 
1439*99ebb4caSwyllys KMF_RETURN
1440*99ebb4caSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, KMF_IMPORTCRL_PARAMS *params)
1441*99ebb4caSwyllys {
1442*99ebb4caSwyllys 	KMF_RETURN 	ret = KMF_OK;
1443*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1444*99ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
1445*99ebb4caSwyllys 	X509		*xcert = NULL;
1446*99ebb4caSwyllys 	EVP_PKEY	*pkey;
1447*99ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
1448*99ebb4caSwyllys 	BIO *in = NULL, *out = NULL;
1449*99ebb4caSwyllys 	int openssl_ret = 0;
1450*99ebb4caSwyllys 	char *outcrlfile = NULL;
1451*99ebb4caSwyllys 	KMF_ENCODE_FORMAT outformat;
1452*99ebb4caSwyllys 
1453*99ebb4caSwyllys 	if (params == NULL || params->sslparms.crlfile == NULL) {
1454*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1455*99ebb4caSwyllys 	}
1456*99ebb4caSwyllys 
1457*99ebb4caSwyllys 	if (params->sslparms.crl_check == B_TRUE &&
1458*99ebb4caSwyllys 	    params->sslparms.certfile == NULL) {
1459*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1460*99ebb4caSwyllys 	}
1461*99ebb4caSwyllys 
1462*99ebb4caSwyllys 	outcrlfile = get_fullpath(params->sslparms.dirpath,
1463*99ebb4caSwyllys 		params->sslparms.outcrlfile);
1464*99ebb4caSwyllys 
1465*99ebb4caSwyllys 	if (outcrlfile == NULL)
1466*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1467*99ebb4caSwyllys 
1468*99ebb4caSwyllys 	if (isdir(outcrlfile)) {
1469*99ebb4caSwyllys 		free(outcrlfile);
1470*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1471*99ebb4caSwyllys 	}
1472*99ebb4caSwyllys 
1473*99ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, params->sslparms.crlfile, &format);
1474*99ebb4caSwyllys 	if (ret != KMF_OK) {
1475*99ebb4caSwyllys 		free(outcrlfile);
1476*99ebb4caSwyllys 		return (ret);
1477*99ebb4caSwyllys 	}
1478*99ebb4caSwyllys 
1479*99ebb4caSwyllys 	in = BIO_new_file(params->sslparms.crlfile, "rb");
1480*99ebb4caSwyllys 	if (in == NULL)	{
1481*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1482*99ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
1483*99ebb4caSwyllys 		goto end;
1484*99ebb4caSwyllys 	}
1485*99ebb4caSwyllys 
1486*99ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
1487*99ebb4caSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
1488*99ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
1489*99ebb4caSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
1490*99ebb4caSwyllys 	}
1491*99ebb4caSwyllys 
1492*99ebb4caSwyllys 	if (xcrl == NULL) {
1493*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1494*99ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
1495*99ebb4caSwyllys 		goto end;
1496*99ebb4caSwyllys 	}
1497*99ebb4caSwyllys 
1498*99ebb4caSwyllys 	/* If bypasscheck is specified, no need to verify. */
1499*99ebb4caSwyllys 	if (params->sslparms.crl_check == B_FALSE) {
1500*99ebb4caSwyllys 		goto output;
1501*99ebb4caSwyllys 	}
1502*99ebb4caSwyllys 
1503*99ebb4caSwyllys 	ret = KMF_IsCertFile(handle, params->sslparms.certfile, &format);
1504*99ebb4caSwyllys 	if (ret != KMF_OK)
1505*99ebb4caSwyllys 		goto end;
1506*99ebb4caSwyllys 
1507*99ebb4caSwyllys 	/* Read in the CA cert file and convert to X509 */
1508*99ebb4caSwyllys 	if (BIO_read_filename(in, params->sslparms.certfile) <= 0) {
1509*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1510*99ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
1511*99ebb4caSwyllys 		goto end;
1512*99ebb4caSwyllys 	}
1513*99ebb4caSwyllys 
1514*99ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
1515*99ebb4caSwyllys 		xcert = d2i_X509_bio(in, NULL);
1516*99ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
1517*99ebb4caSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
1518*99ebb4caSwyllys 	} else {
1519*99ebb4caSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
1520*99ebb4caSwyllys 		goto end;
1521*99ebb4caSwyllys 	}
1522*99ebb4caSwyllys 
1523*99ebb4caSwyllys 	if (xcert == NULL) {
1524*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1525*99ebb4caSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
1526*99ebb4caSwyllys 		goto end;
1527*99ebb4caSwyllys 	}
1528*99ebb4caSwyllys 	/* Now get the public key from the CA cert */
1529*99ebb4caSwyllys 	pkey = X509_get_pubkey(xcert);
1530*99ebb4caSwyllys 	if (!pkey) {
1531*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1532*99ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
1533*99ebb4caSwyllys 		goto end;
1534*99ebb4caSwyllys 	}
1535*99ebb4caSwyllys 
1536*99ebb4caSwyllys 	/* Verify the CRL with the CA's public key */
1537*99ebb4caSwyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
1538*99ebb4caSwyllys 	EVP_PKEY_free(pkey);
1539*99ebb4caSwyllys 	if (openssl_ret > 0) {
1540*99ebb4caSwyllys 		ret = KMF_OK;  /* verify succeed */
1541*99ebb4caSwyllys 	} else {
1542*99ebb4caSwyllys 		SET_ERROR(kmfh, openssl_ret);
1543*99ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
1544*99ebb4caSwyllys 	}
1545*99ebb4caSwyllys 
1546*99ebb4caSwyllys output:
1547*99ebb4caSwyllys 	outformat = params->sslparms.format;
1548*99ebb4caSwyllys 
1549*99ebb4caSwyllys 	out = BIO_new_file(outcrlfile, "wb");
1550*99ebb4caSwyllys 	if (out == NULL) {
1551*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1552*99ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
1553*99ebb4caSwyllys 		goto end;
1554*99ebb4caSwyllys 	}
1555*99ebb4caSwyllys 
1556*99ebb4caSwyllys 	if (outformat == KMF_FORMAT_ASN1) {
1557*99ebb4caSwyllys 		openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
1558*99ebb4caSwyllys 	} else if (outformat == KMF_FORMAT_PEM) {
1559*99ebb4caSwyllys 		openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
1560*99ebb4caSwyllys 	} else {
1561*99ebb4caSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
1562*99ebb4caSwyllys 		goto end;
1563*99ebb4caSwyllys 	}
1564*99ebb4caSwyllys 
1565*99ebb4caSwyllys 	if (openssl_ret <= 0) {
1566*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1567*99ebb4caSwyllys 		ret = KMF_ERR_WRITE_FILE;
1568*99ebb4caSwyllys 	} else {
1569*99ebb4caSwyllys 		ret = KMF_OK;
1570*99ebb4caSwyllys 	}
1571*99ebb4caSwyllys 
1572*99ebb4caSwyllys end:
1573*99ebb4caSwyllys 	if (xcrl != NULL)
1574*99ebb4caSwyllys 		X509_CRL_free(xcrl);
1575*99ebb4caSwyllys 
1576*99ebb4caSwyllys 	if (xcert != NULL)
1577*99ebb4caSwyllys 		X509_free(xcert);
1578*99ebb4caSwyllys 
1579*99ebb4caSwyllys 	if (in != NULL)
1580*99ebb4caSwyllys 		(void) BIO_free(in);
1581*99ebb4caSwyllys 
1582*99ebb4caSwyllys 	if (out != NULL)
1583*99ebb4caSwyllys 		(void) BIO_free(out);
1584*99ebb4caSwyllys 
1585*99ebb4caSwyllys 	if (outcrlfile != NULL)
1586*99ebb4caSwyllys 		free(outcrlfile);
1587*99ebb4caSwyllys 
1588*99ebb4caSwyllys 	return (ret);
1589*99ebb4caSwyllys }
1590*99ebb4caSwyllys 
1591*99ebb4caSwyllys KMF_RETURN
1592*99ebb4caSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, KMF_LISTCRL_PARAMS *params,
1593*99ebb4caSwyllys     char **crldata)
1594*99ebb4caSwyllys {
1595*99ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
1596*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1597*99ebb4caSwyllys 	X509_CRL   *x = NULL;
1598*99ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
1599*99ebb4caSwyllys 	char *crlfile = NULL;
1600*99ebb4caSwyllys 	BIO *in = NULL;
1601*99ebb4caSwyllys 	BIO *mem = NULL;
1602*99ebb4caSwyllys 	long len;
1603*99ebb4caSwyllys 	char *memptr;
1604*99ebb4caSwyllys 	char *data = NULL;
1605*99ebb4caSwyllys 
1606*99ebb4caSwyllys 	if (params == NULL || params->sslparms.crlfile == NULL) {
1607*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1608*99ebb4caSwyllys 	}
1609*99ebb4caSwyllys 
1610*99ebb4caSwyllys 	crlfile = get_fullpath(params->sslparms.dirpath,
1611*99ebb4caSwyllys 		params->sslparms.crlfile);
1612*99ebb4caSwyllys 
1613*99ebb4caSwyllys 	if (crlfile == NULL)
1614*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1615*99ebb4caSwyllys 
1616*99ebb4caSwyllys 	if (isdir(crlfile)) {
1617*99ebb4caSwyllys 		free(crlfile);
1618*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1619*99ebb4caSwyllys 	}
1620*99ebb4caSwyllys 
1621*99ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, crlfile, &format);
1622*99ebb4caSwyllys 	if (ret != KMF_OK) {
1623*99ebb4caSwyllys 		free(crlfile);
1624*99ebb4caSwyllys 		return (ret);
1625*99ebb4caSwyllys 	}
1626*99ebb4caSwyllys 
1627*99ebb4caSwyllys 	if (bio_err == NULL)
1628*99ebb4caSwyllys 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
1629*99ebb4caSwyllys 
1630*99ebb4caSwyllys 	in = BIO_new_file(crlfile, "rb");
1631*99ebb4caSwyllys 	if (in == NULL)	{
1632*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1633*99ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
1634*99ebb4caSwyllys 		goto end;
1635*99ebb4caSwyllys 	}
1636*99ebb4caSwyllys 
1637*99ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
1638*99ebb4caSwyllys 		x = d2i_X509_CRL_bio(in, NULL);
1639*99ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
1640*99ebb4caSwyllys 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
1641*99ebb4caSwyllys 	}
1642*99ebb4caSwyllys 
1643*99ebb4caSwyllys 	if (x == NULL) { /* should not happen */
1644*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1645*99ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
1646*99ebb4caSwyllys 		goto end;
1647*99ebb4caSwyllys 	}
1648*99ebb4caSwyllys 
1649*99ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
1650*99ebb4caSwyllys 	if (mem == NULL) {
1651*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1652*99ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
1653*99ebb4caSwyllys 		goto end;
1654*99ebb4caSwyllys 	}
1655*99ebb4caSwyllys 
1656*99ebb4caSwyllys 	(void) X509_CRL_print(mem, x);
1657*99ebb4caSwyllys 	len = BIO_get_mem_data(mem, &memptr);
1658*99ebb4caSwyllys 	if (len <= 0) {
1659*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1660*99ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
1661*99ebb4caSwyllys 		goto end;
1662*99ebb4caSwyllys 	}
1663*99ebb4caSwyllys 
1664*99ebb4caSwyllys 	data = malloc(len + 1);
1665*99ebb4caSwyllys 	if (data == NULL) {
1666*99ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
1667*99ebb4caSwyllys 		goto end;
1668*99ebb4caSwyllys 	}
1669*99ebb4caSwyllys 
1670*99ebb4caSwyllys 	(void) memcpy(data, memptr, len);
1671*99ebb4caSwyllys 	data[len] = '\0';
1672*99ebb4caSwyllys 	*crldata = data;
1673*99ebb4caSwyllys 
1674*99ebb4caSwyllys end:
1675*99ebb4caSwyllys 	if (x != NULL)
1676*99ebb4caSwyllys 		X509_CRL_free(x);
1677*99ebb4caSwyllys 
1678*99ebb4caSwyllys 	if (crlfile != NULL)
1679*99ebb4caSwyllys 		free(crlfile);
1680*99ebb4caSwyllys 
1681*99ebb4caSwyllys 	if (in != NULL)
1682*99ebb4caSwyllys 		(void) BIO_free(in);
1683*99ebb4caSwyllys 
1684*99ebb4caSwyllys 	if (mem != NULL)
1685*99ebb4caSwyllys 		(void) BIO_free(mem);
1686*99ebb4caSwyllys 
1687*99ebb4caSwyllys 	return (ret);
1688*99ebb4caSwyllys }
1689*99ebb4caSwyllys 
1690*99ebb4caSwyllys KMF_RETURN
1691*99ebb4caSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, KMF_DELETECRL_PARAMS *params)
1692*99ebb4caSwyllys {
1693*99ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
1694*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1695*99ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
1696*99ebb4caSwyllys 	char *crlfile = NULL;
1697*99ebb4caSwyllys 	BIO *in = NULL;
1698*99ebb4caSwyllys 
1699*99ebb4caSwyllys 	if (params == NULL || params->sslparms.crlfile == NULL) {
1700*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1701*99ebb4caSwyllys 	}
1702*99ebb4caSwyllys 
1703*99ebb4caSwyllys 	crlfile = get_fullpath(params->sslparms.dirpath,
1704*99ebb4caSwyllys 		params->sslparms.crlfile);
1705*99ebb4caSwyllys 
1706*99ebb4caSwyllys 	if (crlfile == NULL)
1707*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1708*99ebb4caSwyllys 
1709*99ebb4caSwyllys 	if (isdir(crlfile)) {
1710*99ebb4caSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
1711*99ebb4caSwyllys 		goto end;
1712*99ebb4caSwyllys 	}
1713*99ebb4caSwyllys 
1714*99ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, crlfile, &format);
1715*99ebb4caSwyllys 	if (ret != KMF_OK)
1716*99ebb4caSwyllys 		goto end;
1717*99ebb4caSwyllys 
1718*99ebb4caSwyllys 	if (unlink(crlfile) != 0) {
1719*99ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
1720*99ebb4caSwyllys 		ret = KMF_ERR_INTERNAL;
1721*99ebb4caSwyllys 		goto end;
1722*99ebb4caSwyllys 	}
1723*99ebb4caSwyllys 
1724*99ebb4caSwyllys end:
1725*99ebb4caSwyllys 	if (in != NULL)
1726*99ebb4caSwyllys 		(void) BIO_free(in);
1727*99ebb4caSwyllys 	if (crlfile != NULL)
1728*99ebb4caSwyllys 		free(crlfile);
1729*99ebb4caSwyllys 
1730*99ebb4caSwyllys 	return (ret);
1731*99ebb4caSwyllys }
1732*99ebb4caSwyllys 
1733*99ebb4caSwyllys 
1734*99ebb4caSwyllys KMF_RETURN
1735*99ebb4caSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, KMF_FINDCERTINCRL_PARAMS *params)
1736*99ebb4caSwyllys {
1737*99ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
1738*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1739*99ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
1740*99ebb4caSwyllys 	BIO *in = NULL;
1741*99ebb4caSwyllys 	X509   *xcert = NULL;
1742*99ebb4caSwyllys 	X509_CRL   *xcrl = NULL;
1743*99ebb4caSwyllys 	STACK_OF(X509_REVOKED) *revoke_stack = NULL;
1744*99ebb4caSwyllys 	X509_REVOKED *revoke;
1745*99ebb4caSwyllys 	int i;
1746*99ebb4caSwyllys 
1747*99ebb4caSwyllys 	if (params == NULL || params->sslparms.crlfile == NULL ||
1748*99ebb4caSwyllys 	    params->sslparms.certfile == NULL) {
1749*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1750*99ebb4caSwyllys 	}
1751*99ebb4caSwyllys 
1752*99ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, params->sslparms.crlfile, &format);
1753*99ebb4caSwyllys 	if (ret != KMF_OK)
1754*99ebb4caSwyllys 		return (ret);
1755*99ebb4caSwyllys 
1756*99ebb4caSwyllys 	/* Read the CRL file and load it into a X509_CRL structure */
1757*99ebb4caSwyllys 	in = BIO_new_file(params->sslparms.crlfile, "rb");
1758*99ebb4caSwyllys 	if (in == NULL)	{
1759*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1760*99ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
1761*99ebb4caSwyllys 		goto end;
1762*99ebb4caSwyllys 	}
1763*99ebb4caSwyllys 
1764*99ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
1765*99ebb4caSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
1766*99ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
1767*99ebb4caSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
1768*99ebb4caSwyllys 	}
1769*99ebb4caSwyllys 
1770*99ebb4caSwyllys 	if (xcrl == NULL) {
1771*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1772*99ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
1773*99ebb4caSwyllys 		goto end;
1774*99ebb4caSwyllys 	}
1775*99ebb4caSwyllys 	(void) BIO_free(in);
1776*99ebb4caSwyllys 
1777*99ebb4caSwyllys 	/* Read the Certificate file and load it into a X509 structure */
1778*99ebb4caSwyllys 	ret = KMF_IsCertFile(handle, params->sslparms.certfile, &format);
1779*99ebb4caSwyllys 	if (ret != KMF_OK)
1780*99ebb4caSwyllys 		goto end;
1781*99ebb4caSwyllys 
1782*99ebb4caSwyllys 	in = BIO_new_file(params->sslparms.certfile, "rb");
1783*99ebb4caSwyllys 	if (in == NULL)	{
1784*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1785*99ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
1786*99ebb4caSwyllys 		goto end;
1787*99ebb4caSwyllys 	}
1788*99ebb4caSwyllys 
1789*99ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
1790*99ebb4caSwyllys 		xcert = d2i_X509_bio(in, NULL);
1791*99ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
1792*99ebb4caSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
1793*99ebb4caSwyllys 	}
1794*99ebb4caSwyllys 
1795*99ebb4caSwyllys 	if (xcert == NULL) {
1796*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1797*99ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
1798*99ebb4caSwyllys 		goto end;
1799*99ebb4caSwyllys 	}
1800*99ebb4caSwyllys 
1801*99ebb4caSwyllys 	/* Check if the certificate and the CRL have same issuer */
1802*99ebb4caSwyllys 	if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) {
1803*99ebb4caSwyllys 		ret = KMF_ERR_ISSUER;
1804*99ebb4caSwyllys 		goto end;
1805*99ebb4caSwyllys 	}
1806*99ebb4caSwyllys 
1807*99ebb4caSwyllys 	/* Check to see if the certificate serial number is revoked */
1808*99ebb4caSwyllys 	revoke_stack = X509_CRL_get_REVOKED(xcrl);
1809*99ebb4caSwyllys 	if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
1810*99ebb4caSwyllys 		/* No revoked certificates in the CRL file */
1811*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1812*99ebb4caSwyllys 		ret = KMF_ERR_EMPTY_CRL;
1813*99ebb4caSwyllys 		goto end;
1814*99ebb4caSwyllys 	}
1815*99ebb4caSwyllys 
1816*99ebb4caSwyllys 	for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
1817*99ebb4caSwyllys 		/*LINTED*/
1818*99ebb4caSwyllys 		revoke = sk_X509_REVOKED_value(revoke_stack, i);
1819*99ebb4caSwyllys 		if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber,
1820*99ebb4caSwyllys 		    revoke->serialNumber) == 0) {
1821*99ebb4caSwyllys 			break;
1822*99ebb4caSwyllys 		}
1823*99ebb4caSwyllys 	}
1824*99ebb4caSwyllys 
1825*99ebb4caSwyllys 	if (i < sk_X509_REVOKED_num(revoke_stack)) {
1826*99ebb4caSwyllys 		ret = KMF_OK;
1827*99ebb4caSwyllys 	} else {
1828*99ebb4caSwyllys 		ret = KMF_ERR_NOT_REVOKED;
1829*99ebb4caSwyllys 	}
1830*99ebb4caSwyllys 
1831*99ebb4caSwyllys end:
1832*99ebb4caSwyllys 	if (in != NULL)
1833*99ebb4caSwyllys 		(void) BIO_free(in);
1834*99ebb4caSwyllys 	if (xcrl != NULL)
1835*99ebb4caSwyllys 		X509_CRL_free(xcrl);
1836*99ebb4caSwyllys 	if (xcert != NULL)
1837*99ebb4caSwyllys 		X509_free(xcert);
1838*99ebb4caSwyllys 
1839*99ebb4caSwyllys 	return (ret);
1840*99ebb4caSwyllys }
1841*99ebb4caSwyllys 
1842*99ebb4caSwyllys KMF_RETURN
1843*99ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
1844*99ebb4caSwyllys {
1845*99ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
1846*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1847*99ebb4caSwyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
1848*99ebb4caSwyllys 
1849*99ebb4caSwyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
1850*99ebb4caSwyllys 	if (strlen(str)) {
1851*99ebb4caSwyllys 		*msgstr = (char *)strdup(str);
1852*99ebb4caSwyllys 		if ((*msgstr) == NULL)
1853*99ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
1854*99ebb4caSwyllys 	} else {
1855*99ebb4caSwyllys 		*msgstr = NULL;
1856*99ebb4caSwyllys 	}
1857*99ebb4caSwyllys 
1858*99ebb4caSwyllys 	return (ret);
1859*99ebb4caSwyllys }
1860*99ebb4caSwyllys 
1861*99ebb4caSwyllys static int
1862*99ebb4caSwyllys ext2NID(int kmfext)
1863*99ebb4caSwyllys {
1864*99ebb4caSwyllys 	switch (kmfext) {
1865*99ebb4caSwyllys 		case KMF_X509_EXT_KEY_USAGE:
1866*99ebb4caSwyllys 			return (NID_key_usage);
1867*99ebb4caSwyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
1868*99ebb4caSwyllys 			return (NID_private_key_usage_period);
1869*99ebb4caSwyllys 		case KMF_X509_EXT_CERT_POLICIES:
1870*99ebb4caSwyllys 			return (NID_certificate_policies);
1871*99ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
1872*99ebb4caSwyllys 			return (NID_subject_alt_name);
1873*99ebb4caSwyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
1874*99ebb4caSwyllys 			return (NID_issuer_alt_name);
1875*99ebb4caSwyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
1876*99ebb4caSwyllys 			return (NID_basic_constraints);
1877*99ebb4caSwyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
1878*99ebb4caSwyllys 			return (NID_ext_key_usage);
1879*99ebb4caSwyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
1880*99ebb4caSwyllys 			return (NID_authority_key_identifier);
1881*99ebb4caSwyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
1882*99ebb4caSwyllys 			return (NID_crl_distribution_points);
1883*99ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
1884*99ebb4caSwyllys 			return (NID_subject_key_identifier);
1885*99ebb4caSwyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
1886*99ebb4caSwyllys 			return (OBJ_sn2nid("policyMappings"));
1887*99ebb4caSwyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
1888*99ebb4caSwyllys 			return (OBJ_sn2nid("nameConstraints"));
1889*99ebb4caSwyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
1890*99ebb4caSwyllys 			return (OBJ_sn2nid("policyConstraints"));
1891*99ebb4caSwyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
1892*99ebb4caSwyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
1893*99ebb4caSwyllys 		case KMF_X509_EXT_FRESHEST_CRL:
1894*99ebb4caSwyllys 			return (OBJ_sn2nid("freshestCRL"));
1895*99ebb4caSwyllys 		default:
1896*99ebb4caSwyllys 			return (NID_undef);
1897*99ebb4caSwyllys 	}
1898*99ebb4caSwyllys }
1899*99ebb4caSwyllys 
1900*99ebb4caSwyllys KMF_RETURN
1901*99ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
1902*99ebb4caSwyllys 	KMF_PRINTABLE_ITEM flag, char *resultStr)
1903*99ebb4caSwyllys {
1904*99ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
1905*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1906*99ebb4caSwyllys 	X509 *xcert = NULL;
1907*99ebb4caSwyllys 	unsigned char *outbuf = NULL;
1908*99ebb4caSwyllys 	unsigned char *outbuf_p;
1909*99ebb4caSwyllys 	char *tmpstr = NULL;
1910*99ebb4caSwyllys 	int j;
1911*99ebb4caSwyllys 	int ext_index, nid, len;
1912*99ebb4caSwyllys 	BIO *mem = NULL;
1913*99ebb4caSwyllys 	STACK *emlst = NULL;
1914*99ebb4caSwyllys 	X509_EXTENSION *ex;
1915*99ebb4caSwyllys 	X509_CINF *ci;
1916*99ebb4caSwyllys 
1917*99ebb4caSwyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
1918*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1919*99ebb4caSwyllys 	}
1920*99ebb4caSwyllys 
1921*99ebb4caSwyllys 	/* copy cert data to outbuf */
1922*99ebb4caSwyllys 	outbuf = malloc(pcert->Length);
1923*99ebb4caSwyllys 	if (outbuf == NULL) {
1924*99ebb4caSwyllys 		return (KMF_ERR_MEMORY);
1925*99ebb4caSwyllys 	}
1926*99ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
1927*99ebb4caSwyllys 
1928*99ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
1929*99ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
1930*99ebb4caSwyllys 	if (xcert == NULL) {
1931*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1932*99ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
1933*99ebb4caSwyllys 		goto out;
1934*99ebb4caSwyllys 	}
1935*99ebb4caSwyllys 
1936*99ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
1937*99ebb4caSwyllys 	if (mem == NULL) {
1938*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1939*99ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
1940*99ebb4caSwyllys 		goto out;
1941*99ebb4caSwyllys 	}
1942*99ebb4caSwyllys 
1943*99ebb4caSwyllys 	switch (flag) {
1944*99ebb4caSwyllys 	case KMF_CERT_ISSUER:
1945*99ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
1946*99ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
1947*99ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
1948*99ebb4caSwyllys 		break;
1949*99ebb4caSwyllys 
1950*99ebb4caSwyllys 	case KMF_CERT_SUBJECT:
1951*99ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
1952*99ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
1953*99ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
1954*99ebb4caSwyllys 		break;
1955*99ebb4caSwyllys 
1956*99ebb4caSwyllys 	case KMF_CERT_VERSION:
1957*99ebb4caSwyllys 		tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version);
1958*99ebb4caSwyllys 		(void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN);
1959*99ebb4caSwyllys 		OPENSSL_free(tmpstr);
1960*99ebb4caSwyllys 		len = strlen(resultStr);
1961*99ebb4caSwyllys 		break;
1962*99ebb4caSwyllys 
1963*99ebb4caSwyllys 	case KMF_CERT_SERIALNUM:
1964*99ebb4caSwyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
1965*99ebb4caSwyllys 			(void) strcpy(resultStr, "0x");
1966*99ebb4caSwyllys 			len = BIO_gets(mem, &resultStr[2],
1967*99ebb4caSwyllys 				KMF_CERT_PRINTABLE_LEN - 2);
1968*99ebb4caSwyllys 		}
1969*99ebb4caSwyllys 		break;
1970*99ebb4caSwyllys 
1971*99ebb4caSwyllys 	case KMF_CERT_NOTBEFORE:
1972*99ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notBefore(xcert));
1973*99ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
1974*99ebb4caSwyllys 		break;
1975*99ebb4caSwyllys 
1976*99ebb4caSwyllys 	case KMF_CERT_NOTAFTER:
1977*99ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notAfter(xcert));
1978*99ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
1979*99ebb4caSwyllys 		break;
1980*99ebb4caSwyllys 
1981*99ebb4caSwyllys 	case KMF_CERT_PUBKEY_DATA:
1982*99ebb4caSwyllys 		{
1983*99ebb4caSwyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
1984*99ebb4caSwyllys 			if (pkey == NULL) {
1985*99ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
1986*99ebb4caSwyllys 				ret = KMF_ERR_ENCODING;
1987*99ebb4caSwyllys 				goto out;
1988*99ebb4caSwyllys 			}
1989*99ebb4caSwyllys 
1990*99ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
1991*99ebb4caSwyllys 				(void) BIO_printf(mem,
1992*99ebb4caSwyllys 					"RSA Public Key: (%d bit)\n",
1993*99ebb4caSwyllys 					BN_num_bits(pkey->pkey.rsa->n));
1994*99ebb4caSwyllys 				(void) RSA_print(mem, pkey->pkey.rsa, 0);
1995*99ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
1996*99ebb4caSwyllys 				(void) BIO_printf(mem,
1997*99ebb4caSwyllys 					"%12sDSA Public Key:\n", "");
1998*99ebb4caSwyllys 				(void) DSA_print(mem, pkey->pkey.dsa, 0);
1999*99ebb4caSwyllys 			} else {
2000*99ebb4caSwyllys 				(void) BIO_printf(mem,
2001*99ebb4caSwyllys 					"%12sUnknown Public Key:\n", "");
2002*99ebb4caSwyllys 			}
2003*99ebb4caSwyllys 			(void) BIO_printf(mem, "\n");
2004*99ebb4caSwyllys 			EVP_PKEY_free(pkey);
2005*99ebb4caSwyllys 		}
2006*99ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2007*99ebb4caSwyllys 		break;
2008*99ebb4caSwyllys 	case KMF_CERT_SIGNATURE_ALG:
2009*99ebb4caSwyllys 	case KMF_CERT_PUBKEY_ALG:
2010*99ebb4caSwyllys 		if (flag == KMF_CERT_SIGNATURE_ALG) {
2011*99ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
2012*99ebb4caSwyllys 				xcert->sig_alg->algorithm);
2013*99ebb4caSwyllys 		} else {
2014*99ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
2015*99ebb4caSwyllys 				xcert->cert_info->key->algor->algorithm);
2016*99ebb4caSwyllys 		}
2017*99ebb4caSwyllys 
2018*99ebb4caSwyllys 		if (len > 0) {
2019*99ebb4caSwyllys 			len = BIO_read(mem, resultStr,
2020*99ebb4caSwyllys 				KMF_CERT_PRINTABLE_LEN);
2021*99ebb4caSwyllys 		}
2022*99ebb4caSwyllys 		break;
2023*99ebb4caSwyllys 
2024*99ebb4caSwyllys 	case KMF_CERT_EMAIL:
2025*99ebb4caSwyllys 		emlst = X509_get1_email(xcert);
2026*99ebb4caSwyllys 		for (j = 0; j < sk_num(emlst); j++)
2027*99ebb4caSwyllys 			(void) BIO_printf(mem, "%s\n", sk_value(emlst, j));
2028*99ebb4caSwyllys 
2029*99ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2030*99ebb4caSwyllys 		X509_email_free(emlst);
2031*99ebb4caSwyllys 		break;
2032*99ebb4caSwyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
2033*99ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
2034*99ebb4caSwyllys 	case KMF_X509_EXT_KEY_USAGE:
2035*99ebb4caSwyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
2036*99ebb4caSwyllys 	case KMF_X509_EXT_CERT_POLICIES:
2037*99ebb4caSwyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
2038*99ebb4caSwyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
2039*99ebb4caSwyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
2040*99ebb4caSwyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
2041*99ebb4caSwyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
2042*99ebb4caSwyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
2043*99ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
2044*99ebb4caSwyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
2045*99ebb4caSwyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
2046*99ebb4caSwyllys 	case KMF_X509_EXT_FRESHEST_CRL:
2047*99ebb4caSwyllys 		nid = ext2NID(flag);
2048*99ebb4caSwyllys 		if (nid == NID_undef) {
2049*99ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
2050*99ebb4caSwyllys 			goto out;
2051*99ebb4caSwyllys 		}
2052*99ebb4caSwyllys 		ci = xcert->cert_info;
2053*99ebb4caSwyllys 
2054*99ebb4caSwyllys 		ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1);
2055*99ebb4caSwyllys 		if (ext_index == -1) {
2056*99ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
2057*99ebb4caSwyllys 
2058*99ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
2059*99ebb4caSwyllys 			goto out;
2060*99ebb4caSwyllys 		}
2061*99ebb4caSwyllys 		ex = X509v3_get_ext(ci->extensions, ext_index);
2062*99ebb4caSwyllys 
2063*99ebb4caSwyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
2064*99ebb4caSwyllys 
2065*99ebb4caSwyllys 		if (BIO_printf(mem, ": %s\n",
2066*99ebb4caSwyllys 			X509_EXTENSION_get_critical(ex) ? "critical" : "") <=
2067*99ebb4caSwyllys 			0) {
2068*99ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
2069*99ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
2070*99ebb4caSwyllys 			goto out;
2071*99ebb4caSwyllys 		}
2072*99ebb4caSwyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
2073*99ebb4caSwyllys 			(void) BIO_printf(mem, "%*s", 4, "");
2074*99ebb4caSwyllys 			(void) M_ASN1_OCTET_STRING_print(mem, ex->value);
2075*99ebb4caSwyllys 		}
2076*99ebb4caSwyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
2077*99ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
2078*99ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
2079*99ebb4caSwyllys 			goto out;
2080*99ebb4caSwyllys 		}
2081*99ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2082*99ebb4caSwyllys 	}
2083*99ebb4caSwyllys 	if (len <= 0) {
2084*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
2085*99ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
2086*99ebb4caSwyllys 	}
2087*99ebb4caSwyllys 
2088*99ebb4caSwyllys out:
2089*99ebb4caSwyllys 	if (outbuf != NULL) {
2090*99ebb4caSwyllys 		free(outbuf);
2091*99ebb4caSwyllys 	}
2092*99ebb4caSwyllys 
2093*99ebb4caSwyllys 	if (xcert != NULL) {
2094*99ebb4caSwyllys 		X509_free(xcert);
2095*99ebb4caSwyllys 	}
2096*99ebb4caSwyllys 
2097*99ebb4caSwyllys 	if (mem != NULL) {
2098*99ebb4caSwyllys 		(void) BIO_free(mem);
2099*99ebb4caSwyllys 	}
2100*99ebb4caSwyllys 
2101*99ebb4caSwyllys 	return (ret);
2102*99ebb4caSwyllys }
2103*99ebb4caSwyllys KMF_RETURN
2104*99ebb4caSwyllys /*ARGSUSED*/
2105*99ebb4caSwyllys OpenSSL_GetPrikeyByCert(KMF_HANDLE_T handle,
2106*99ebb4caSwyllys 	KMF_CRYPTOWITHCERT_PARAMS *params,
2107*99ebb4caSwyllys 	KMF_DATA *SignerCertData, KMF_KEY_HANDLE *key,
2108*99ebb4caSwyllys 	KMF_KEY_ALG keytype)
2109*99ebb4caSwyllys {
2110*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
2111*99ebb4caSwyllys 	KMF_FINDKEY_PARAMS fkparms;
2112*99ebb4caSwyllys 	uint32_t numkeys = 0;
2113*99ebb4caSwyllys 
2114*99ebb4caSwyllys 	if (params == NULL && params->sslparms.keyfile == NULL)
2115*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2116*99ebb4caSwyllys 
2117*99ebb4caSwyllys 	/*
2118*99ebb4caSwyllys 	 * This is really just a FindKey operation, reuse the
2119*99ebb4caSwyllys 	 * FindKey function.
2120*99ebb4caSwyllys 	 */
2121*99ebb4caSwyllys 	(void *)memset(&fkparms, 0, sizeof (fkparms));
2122*99ebb4caSwyllys 	fkparms.kstype = KMF_KEYSTORE_OPENSSL;
2123*99ebb4caSwyllys 	fkparms.keyclass = KMF_ASYM_PRI;
2124*99ebb4caSwyllys 	fkparms.keytype = keytype;
2125*99ebb4caSwyllys 	fkparms.format = params->format;
2126*99ebb4caSwyllys 	fkparms.sslparms = params->sslparms;
2127*99ebb4caSwyllys 
2128*99ebb4caSwyllys 	rv = OpenSSL_FindKey(handle, &fkparms, key, &numkeys);
2129*99ebb4caSwyllys 
2130*99ebb4caSwyllys 	return (rv);
2131*99ebb4caSwyllys }
2132*99ebb4caSwyllys 
2133*99ebb4caSwyllys KMF_RETURN
2134*99ebb4caSwyllys /*ARGSUSED*/
2135*99ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
2136*99ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
2137*99ebb4caSwyllys 	KMF_DATA *output)
2138*99ebb4caSwyllys {
2139*99ebb4caSwyllys 	KMF_RETURN		ret = KMF_OK;
2140*99ebb4caSwyllys 	RSA *rsa = NULL;
2141*99ebb4caSwyllys 	unsigned int in_len = 0, out_len = 0;
2142*99ebb4caSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
2143*99ebb4caSwyllys 	uint8_t *in_data, *out_data;
2144*99ebb4caSwyllys 	int i, blocks;
2145*99ebb4caSwyllys 
2146*99ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
2147*99ebb4caSwyllys 	    ciphertext == NULL || output == NULL ||
2148*99ebb4caSwyllys 	    ciphertext->Data == NULL ||
2149*99ebb4caSwyllys 	    output->Data == NULL)
2150*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2151*99ebb4caSwyllys 
2152*99ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
2153*99ebb4caSwyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
2154*99ebb4caSwyllys 		modulus_len = RSA_size(rsa);
2155*99ebb4caSwyllys 	} else {
2156*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2157*99ebb4caSwyllys 	}
2158*99ebb4caSwyllys 
2159*99ebb4caSwyllys 	blocks = ciphertext->Length/modulus_len;
2160*99ebb4caSwyllys 	out_data = output->Data;
2161*99ebb4caSwyllys 	in_data = ciphertext->Data;
2162*99ebb4caSwyllys 	out_len = modulus_len - 11;
2163*99ebb4caSwyllys 	in_len = modulus_len;
2164*99ebb4caSwyllys 
2165*99ebb4caSwyllys 	for (i = 0; i < blocks; i++) {
2166*99ebb4caSwyllys 		out_len  = RSA_private_decrypt(in_len,
2167*99ebb4caSwyllys 			in_data, out_data, rsa, RSA_PKCS1_PADDING);
2168*99ebb4caSwyllys 
2169*99ebb4caSwyllys 		if (out_len == 0) {
2170*99ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
2171*99ebb4caSwyllys 			goto cleanup;
2172*99ebb4caSwyllys 		}
2173*99ebb4caSwyllys 
2174*99ebb4caSwyllys 		out_data += out_len;
2175*99ebb4caSwyllys 		total_decrypted += out_len;
2176*99ebb4caSwyllys 		in_data += in_len;
2177*99ebb4caSwyllys 	}
2178*99ebb4caSwyllys 
2179*99ebb4caSwyllys 	output->Length = total_decrypted;
2180*99ebb4caSwyllys 
2181*99ebb4caSwyllys cleanup:
2182*99ebb4caSwyllys 	RSA_free(rsa);
2183*99ebb4caSwyllys 	if (ret != KMF_OK)
2184*99ebb4caSwyllys 		output->Length = 0;
2185*99ebb4caSwyllys 
2186*99ebb4caSwyllys 	return (ret);
2187*99ebb4caSwyllys 
2188*99ebb4caSwyllys }
2189*99ebb4caSwyllys 
2190*99ebb4caSwyllys /*
2191*99ebb4caSwyllys  *  This function will create a certid from issuer_cert and user_cert.
2192*99ebb4caSwyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
2193*99ebb4caSwyllys  *  certid memory after use.
2194*99ebb4caSwyllys  */
2195*99ebb4caSwyllys static KMF_RETURN
2196*99ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
2197*99ebb4caSwyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
2198*99ebb4caSwyllys {
2199*99ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
2200*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2201*99ebb4caSwyllys 	X509   *issuer = NULL;
2202*99ebb4caSwyllys 	X509   *cert = NULL;
2203*99ebb4caSwyllys 	unsigned char *ptmp;
2204*99ebb4caSwyllys 
2205*99ebb4caSwyllys 	if (issuer_cert == NULL || user_cert == NULL) {
2206*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2207*99ebb4caSwyllys 	}
2208*99ebb4caSwyllys 
2209*99ebb4caSwyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
2210*99ebb4caSwyllys 	ptmp = issuer_cert->Data;
2211*99ebb4caSwyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2212*99ebb4caSwyllys 		issuer_cert->Length);
2213*99ebb4caSwyllys 	if (issuer == NULL) {
2214*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
2215*99ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
2216*99ebb4caSwyllys 		goto end;
2217*99ebb4caSwyllys 	}
2218*99ebb4caSwyllys 
2219*99ebb4caSwyllys 	/* convert the DER-encoded user cert to an internal X509 */
2220*99ebb4caSwyllys 	ptmp = user_cert->Data;
2221*99ebb4caSwyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
2222*99ebb4caSwyllys 		user_cert->Length);
2223*99ebb4caSwyllys 	if (cert == NULL) {
2224*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
2225*99ebb4caSwyllys 
2226*99ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
2227*99ebb4caSwyllys 		goto end;
2228*99ebb4caSwyllys 	}
2229*99ebb4caSwyllys 
2230*99ebb4caSwyllys 	/* create a CERTID */
2231*99ebb4caSwyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
2232*99ebb4caSwyllys 	if (*certid == NULL) {
2233*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
2234*99ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
2235*99ebb4caSwyllys 		goto end;
2236*99ebb4caSwyllys 	}
2237*99ebb4caSwyllys 
2238*99ebb4caSwyllys end:
2239*99ebb4caSwyllys 	if (issuer != NULL) {
2240*99ebb4caSwyllys 		X509_free(issuer);
2241*99ebb4caSwyllys 	}
2242*99ebb4caSwyllys 
2243*99ebb4caSwyllys 	if (cert != NULL) {
2244*99ebb4caSwyllys 		X509_free(cert);
2245*99ebb4caSwyllys 	}
2246*99ebb4caSwyllys 
2247*99ebb4caSwyllys 	return (ret);
2248*99ebb4caSwyllys }
2249*99ebb4caSwyllys 
2250*99ebb4caSwyllys KMF_RETURN
2251*99ebb4caSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle, KMF_OCSPREQUEST_PARAMS *params,
2252*99ebb4caSwyllys     char *reqfile)
2253*99ebb4caSwyllys {
2254*99ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
2255*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2256*99ebb4caSwyllys 	OCSP_CERTID *id = NULL;
2257*99ebb4caSwyllys 	OCSP_REQUEST *req = NULL;
2258*99ebb4caSwyllys 	BIO *derbio = NULL;
2259*99ebb4caSwyllys 
2260*99ebb4caSwyllys 	if (params->user_cert == NULL || params->issuer_cert == NULL ||
2261*99ebb4caSwyllys 	    reqfile == NULL) {
2262*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2263*99ebb4caSwyllys 	}
2264*99ebb4caSwyllys 
2265*99ebb4caSwyllys 	ret = create_certid(handle, params->issuer_cert, params->user_cert,
2266*99ebb4caSwyllys 	    &id);
2267*99ebb4caSwyllys 	if (ret != KMF_OK) {
2268*99ebb4caSwyllys 		return (ret);
2269*99ebb4caSwyllys 	}
2270*99ebb4caSwyllys 
2271*99ebb4caSwyllys 	/* Create an OCSP request */
2272*99ebb4caSwyllys 	req = OCSP_REQUEST_new();
2273*99ebb4caSwyllys 	if (req == NULL) {
2274*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
2275*99ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
2276*99ebb4caSwyllys 		goto end;
2277*99ebb4caSwyllys 	}
2278*99ebb4caSwyllys 
2279*99ebb4caSwyllys 	if (!OCSP_request_add0_id(req, id)) {
2280*99ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
2281*99ebb4caSwyllys 		goto end;
2282*99ebb4caSwyllys 	}
2283*99ebb4caSwyllys 
2284*99ebb4caSwyllys 	/* Write the request to the output file with DER encoding */
2285*99ebb4caSwyllys 	derbio = BIO_new_file(reqfile, "wb");
2286*99ebb4caSwyllys 	if (!derbio) {
2287*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
2288*99ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
2289*99ebb4caSwyllys 		goto end;
2290*99ebb4caSwyllys 	}
2291*99ebb4caSwyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
2292*99ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
2293*99ebb4caSwyllys 	}
2294*99ebb4caSwyllys 
2295*99ebb4caSwyllys end:
2296*99ebb4caSwyllys 	/*
2297*99ebb4caSwyllys 	 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2298*99ebb4caSwyllys 	 * will deallocate certid's space also.
2299*99ebb4caSwyllys 	 */
2300*99ebb4caSwyllys 	if (req != NULL) {
2301*99ebb4caSwyllys 		OCSP_REQUEST_free(req);
2302*99ebb4caSwyllys 	}
2303*99ebb4caSwyllys 
2304*99ebb4caSwyllys 	if (derbio != NULL) {
2305*99ebb4caSwyllys 		(void) BIO_free(derbio);
2306*99ebb4caSwyllys 	}
2307*99ebb4caSwyllys 
2308*99ebb4caSwyllys 	return (ret);
2309*99ebb4caSwyllys }
2310*99ebb4caSwyllys 
2311*99ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */
2312*99ebb4caSwyllys static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
2313*99ebb4caSwyllys {
2314*99ebb4caSwyllys 	int i;
2315*99ebb4caSwyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
2316*99ebb4caSwyllys 
2317*99ebb4caSwyllys 	/* Easy if lookup by name */
2318*99ebb4caSwyllys 	if (id->type == V_OCSP_RESPID_NAME)
2319*99ebb4caSwyllys 		return (X509_find_by_subject(certs, id->value.byName));
2320*99ebb4caSwyllys 
2321*99ebb4caSwyllys 	/* Lookup by key hash */
2322*99ebb4caSwyllys 
2323*99ebb4caSwyllys 	/* If key hash isn't SHA1 length then forget it */
2324*99ebb4caSwyllys 	if (id->value.byKey->length != SHA_DIGEST_LENGTH)
2325*99ebb4caSwyllys 		return (NULL);
2326*99ebb4caSwyllys 
2327*99ebb4caSwyllys 	keyhash = id->value.byKey->data;
2328*99ebb4caSwyllys 	/* Calculate hash of each key and compare */
2329*99ebb4caSwyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
2330*99ebb4caSwyllys 		/*LINTED*/
2331*99ebb4caSwyllys 		X509 *x = sk_X509_value(certs, i);
2332*99ebb4caSwyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
2333*99ebb4caSwyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
2334*99ebb4caSwyllys 			return (x);
2335*99ebb4caSwyllys 	}
2336*99ebb4caSwyllys 	return (NULL);
2337*99ebb4caSwyllys }
2338*99ebb4caSwyllys 
2339*99ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */
2340*99ebb4caSwyllys /*ARGSUSED*/
2341*99ebb4caSwyllys static int
2342*99ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
2343*99ebb4caSwyllys     X509_STORE *st, unsigned long flags)
2344*99ebb4caSwyllys {
2345*99ebb4caSwyllys 	X509 *signer;
2346*99ebb4caSwyllys 	OCSP_RESPID *rid = bs->tbsResponseData->responderId;
2347*99ebb4caSwyllys 	if ((signer = ocsp_find_signer_sk(certs, rid)))	{
2348*99ebb4caSwyllys 		*psigner = signer;
2349*99ebb4caSwyllys 		return (2);
2350*99ebb4caSwyllys 	}
2351*99ebb4caSwyllys 	if (!(flags & OCSP_NOINTERN) &&
2352*99ebb4caSwyllys 	    (signer = ocsp_find_signer_sk(bs->certs, rid))) {
2353*99ebb4caSwyllys 		*psigner = signer;
2354*99ebb4caSwyllys 		return (1);
2355*99ebb4caSwyllys 	}
2356*99ebb4caSwyllys 	/* Maybe lookup from store if by subject name */
2357*99ebb4caSwyllys 
2358*99ebb4caSwyllys 	*psigner = NULL;
2359*99ebb4caSwyllys 	return (0);
2360*99ebb4caSwyllys }
2361*99ebb4caSwyllys 
2362*99ebb4caSwyllys /*
2363*99ebb4caSwyllys  * This function will verify the signature of a basic response, using
2364*99ebb4caSwyllys  * the public key from the OCSP responder certificate.
2365*99ebb4caSwyllys  */
2366*99ebb4caSwyllys static KMF_RETURN
2367*99ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
2368*99ebb4caSwyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
2369*99ebb4caSwyllys {
2370*99ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
2371*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2372*99ebb4caSwyllys 	STACK_OF(X509) *cert_stack = NULL;
2373*99ebb4caSwyllys 	X509 *signer = NULL;
2374*99ebb4caSwyllys 	X509 *issuer = NULL;
2375*99ebb4caSwyllys 	EVP_PKEY *skey = NULL;
2376*99ebb4caSwyllys 	unsigned char *ptmp;
2377*99ebb4caSwyllys 
2378*99ebb4caSwyllys 
2379*99ebb4caSwyllys 	if (bs == NULL || issuer_cert == NULL)
2380*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2381*99ebb4caSwyllys 
2382*99ebb4caSwyllys 	/*
2383*99ebb4caSwyllys 	 * Find the certificate that signed the basic response.
2384*99ebb4caSwyllys 	 *
2385*99ebb4caSwyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
2386*99ebb4caSwyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
2387*99ebb4caSwyllys 	 * If we still do not find a signer, we will look for it from the
2388*99ebb4caSwyllys 	 * certificate list came with the response file.
2389*99ebb4caSwyllys 	 */
2390*99ebb4caSwyllys 	if (signer_cert != NULL) {
2391*99ebb4caSwyllys 		ptmp = signer_cert->Data;
2392*99ebb4caSwyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2393*99ebb4caSwyllys 		    signer_cert->Length);
2394*99ebb4caSwyllys 		if (signer == NULL) {
2395*99ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
2396*99ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
2397*99ebb4caSwyllys 			goto end;
2398*99ebb4caSwyllys 		}
2399*99ebb4caSwyllys 	} else {
2400*99ebb4caSwyllys 		/*
2401*99ebb4caSwyllys 		 * Convert the issuer cert into X509 and push it into a
2402*99ebb4caSwyllys 		 * stack to be used by ocsp_find_signer().
2403*99ebb4caSwyllys 		 */
2404*99ebb4caSwyllys 		ptmp = issuer_cert->Data;
2405*99ebb4caSwyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2406*99ebb4caSwyllys 			issuer_cert->Length);
2407*99ebb4caSwyllys 		if (issuer == NULL) {
2408*99ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
2409*99ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
2410*99ebb4caSwyllys 			goto end;
2411*99ebb4caSwyllys 		}
2412*99ebb4caSwyllys 
2413*99ebb4caSwyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
2414*99ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
2415*99ebb4caSwyllys 			goto end;
2416*99ebb4caSwyllys 		}
2417*99ebb4caSwyllys 
2418*99ebb4caSwyllys 		if (sk_X509_push(cert_stack, issuer) == NULL) {
2419*99ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
2420*99ebb4caSwyllys 			goto end;
2421*99ebb4caSwyllys 		}
2422*99ebb4caSwyllys 
2423*99ebb4caSwyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
2424*99ebb4caSwyllys 		if (!ret) {
2425*99ebb4caSwyllys 			/* can not find the signer */
2426*99ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
2427*99ebb4caSwyllys 			goto end;
2428*99ebb4caSwyllys 		}
2429*99ebb4caSwyllys 	}
2430*99ebb4caSwyllys 
2431*99ebb4caSwyllys 	/* Verify the signature of the response */
2432*99ebb4caSwyllys 	skey = X509_get_pubkey(signer);
2433*99ebb4caSwyllys 	if (skey == NULL) {
2434*99ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
2435*99ebb4caSwyllys 		goto end;
2436*99ebb4caSwyllys 	}
2437*99ebb4caSwyllys 
2438*99ebb4caSwyllys 	ret = OCSP_BASICRESP_verify(bs, skey, 0);
2439*99ebb4caSwyllys 	if (ret == 0) {
2440*99ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
2441*99ebb4caSwyllys 		goto end;
2442*99ebb4caSwyllys 	}
2443*99ebb4caSwyllys 
2444*99ebb4caSwyllys end:
2445*99ebb4caSwyllys 	if (issuer != NULL) {
2446*99ebb4caSwyllys 		X509_free(issuer);
2447*99ebb4caSwyllys 	}
2448*99ebb4caSwyllys 
2449*99ebb4caSwyllys 	if (signer != NULL) {
2450*99ebb4caSwyllys 		X509_free(signer);
2451*99ebb4caSwyllys 	}
2452*99ebb4caSwyllys 
2453*99ebb4caSwyllys 	if (skey != NULL) {
2454*99ebb4caSwyllys 		EVP_PKEY_free(skey);
2455*99ebb4caSwyllys 	}
2456*99ebb4caSwyllys 
2457*99ebb4caSwyllys 	if (cert_stack != NULL) {
2458*99ebb4caSwyllys 		sk_X509_free(cert_stack);
2459*99ebb4caSwyllys 	}
2460*99ebb4caSwyllys 
2461*99ebb4caSwyllys 	return (ret);
2462*99ebb4caSwyllys }
2463*99ebb4caSwyllys 
2464*99ebb4caSwyllys 
2465*99ebb4caSwyllys 
2466*99ebb4caSwyllys KMF_RETURN
2467*99ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
2468*99ebb4caSwyllys     KMF_OCSPRESPONSE_PARAMS_INPUT *params_in,
2469*99ebb4caSwyllys     KMF_OCSPRESPONSE_PARAMS_OUTPUT *params_out)
2470*99ebb4caSwyllys {
2471*99ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
2472*99ebb4caSwyllys 	BIO *derbio = NULL;
2473*99ebb4caSwyllys 	OCSP_RESPONSE *resp = NULL;
2474*99ebb4caSwyllys 	OCSP_BASICRESP *bs = NULL;
2475*99ebb4caSwyllys 	OCSP_CERTID *id = NULL;
2476*99ebb4caSwyllys 	OCSP_SINGLERESP *single = NULL;
2477*99ebb4caSwyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
2478*99ebb4caSwyllys 	int index, status, reason;
2479*99ebb4caSwyllys 
2480*99ebb4caSwyllys 	if (params_in == NULL || params_in->issuer_cert == NULL ||
2481*99ebb4caSwyllys 	    params_in->user_cert == NULL || params_in->response == NULL) {
2482*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2483*99ebb4caSwyllys 	}
2484*99ebb4caSwyllys 
2485*99ebb4caSwyllys 	if (params_out == NULL) {
2486*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2487*99ebb4caSwyllys 	}
2488*99ebb4caSwyllys 
2489*99ebb4caSwyllys 	/* Read in the response */
2490*99ebb4caSwyllys 	derbio = BIO_new_mem_buf(params_in->response->Data,
2491*99ebb4caSwyllys 	    params_in->response->Length);
2492*99ebb4caSwyllys 	if (!derbio) {
2493*99ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
2494*99ebb4caSwyllys 		return (ret);
2495*99ebb4caSwyllys 	}
2496*99ebb4caSwyllys 
2497*99ebb4caSwyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
2498*99ebb4caSwyllys 	if (resp == NULL) {
2499*99ebb4caSwyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
2500*99ebb4caSwyllys 		goto end;
2501*99ebb4caSwyllys 	}
2502*99ebb4caSwyllys 
2503*99ebb4caSwyllys 	/* Check the response status */
2504*99ebb4caSwyllys 	status = OCSP_response_status(resp);
2505*99ebb4caSwyllys 	params_out->response_status = status;
2506*99ebb4caSwyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
2507*99ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
2508*99ebb4caSwyllys 		goto end;
2509*99ebb4caSwyllys 	}
2510*99ebb4caSwyllys 
2511*99ebb4caSwyllys #ifdef DEBUG
2512*99ebb4caSwyllys 	printf("Successfully checked the response file status.\n");
2513*99ebb4caSwyllys #endif /* DEBUG */
2514*99ebb4caSwyllys 
2515*99ebb4caSwyllys 	/* Extract basic response */
2516*99ebb4caSwyllys 	bs = OCSP_response_get1_basic(resp);
2517*99ebb4caSwyllys 	if (bs == NULL) {
2518*99ebb4caSwyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
2519*99ebb4caSwyllys 		goto end;
2520*99ebb4caSwyllys 	}
2521*99ebb4caSwyllys 
2522*99ebb4caSwyllys #ifdef DEBUG
2523*99ebb4caSwyllys 	printf("Successfully retrieved the basic response.\n");
2524*99ebb4caSwyllys #endif /* DEBUG */
2525*99ebb4caSwyllys 
2526*99ebb4caSwyllys 	/* Check the basic response signature if required */
2527*99ebb4caSwyllys 	if (params_in->ignore_response_sign == B_FALSE) {
2528*99ebb4caSwyllys 		ret = check_response_signature(handle, bs,
2529*99ebb4caSwyllys 		    params_in->signer_cert, params_in->issuer_cert);
2530*99ebb4caSwyllys 		if (ret != KMF_OK)
2531*99ebb4caSwyllys 			goto end;
2532*99ebb4caSwyllys 	}
2533*99ebb4caSwyllys 
2534*99ebb4caSwyllys #ifdef DEBUG
2535*99ebb4caSwyllys 	printf("Successfully verified the response signature.\n");
2536*99ebb4caSwyllys #endif /* DEBUG */
2537*99ebb4caSwyllys 
2538*99ebb4caSwyllys 	/* Create a certid for the certificate in question */
2539*99ebb4caSwyllys 	ret = create_certid(handle, params_in->issuer_cert,
2540*99ebb4caSwyllys 	    params_in->user_cert, &id);
2541*99ebb4caSwyllys 	if (ret != KMF_OK) {
2542*99ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
2543*99ebb4caSwyllys 		goto end;
2544*99ebb4caSwyllys 	}
2545*99ebb4caSwyllys 
2546*99ebb4caSwyllys #ifdef DEBUG
2547*99ebb4caSwyllys 	printf("successfully created a certid for the cert.\n");
2548*99ebb4caSwyllys #endif /* DEBUG */
2549*99ebb4caSwyllys 
2550*99ebb4caSwyllys 	/* Find the index of the single response for the certid */
2551*99ebb4caSwyllys 	index = OCSP_resp_find(bs, id, -1);
2552*99ebb4caSwyllys 	if (index < 0) {
2553*99ebb4caSwyllys 		/* cound not find this certificate in the response */
2554*99ebb4caSwyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
2555*99ebb4caSwyllys 		goto end;
2556*99ebb4caSwyllys 	}
2557*99ebb4caSwyllys 
2558*99ebb4caSwyllys #ifdef DEBUG
2559*99ebb4caSwyllys 	printf("Successfully found the single response index for the cert.\n");
2560*99ebb4caSwyllys #endif /* DEBUG */
2561*99ebb4caSwyllys 
2562*99ebb4caSwyllys 	/* Retrieve the single response and get the cert status */
2563*99ebb4caSwyllys 	single = OCSP_resp_get0(bs, index);
2564*99ebb4caSwyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
2565*99ebb4caSwyllys 	    &nextupd);
2566*99ebb4caSwyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
2567*99ebb4caSwyllys 		params_out->cert_status = OCSP_GOOD;
2568*99ebb4caSwyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
2569*99ebb4caSwyllys 		params_out->cert_status = OCSP_UNKNOWN;
2570*99ebb4caSwyllys 	} else { /* revoked */
2571*99ebb4caSwyllys 		params_out->cert_status = OCSP_REVOKED;
2572*99ebb4caSwyllys 		params_out->reason = reason;
2573*99ebb4caSwyllys 	}
2574*99ebb4caSwyllys 	ret = KMF_OK;
2575*99ebb4caSwyllys 
2576*99ebb4caSwyllys 	/* Verify the time */
2577*99ebb4caSwyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
2578*99ebb4caSwyllys 	    params_in->response_lifetime)) {
2579*99ebb4caSwyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
2580*99ebb4caSwyllys 		goto end;
2581*99ebb4caSwyllys 	}
2582*99ebb4caSwyllys 
2583*99ebb4caSwyllys #ifdef DEBUG
2584*99ebb4caSwyllys 	printf("Successfully verify the time.\n");
2585*99ebb4caSwyllys #endif /* DEBUG */
2586*99ebb4caSwyllys 
2587*99ebb4caSwyllys end:
2588*99ebb4caSwyllys 	if (derbio != NULL)
2589*99ebb4caSwyllys 		(void) BIO_free(derbio);
2590*99ebb4caSwyllys 
2591*99ebb4caSwyllys 	if (resp != NULL)
2592*99ebb4caSwyllys 		OCSP_RESPONSE_free(resp);
2593*99ebb4caSwyllys 
2594*99ebb4caSwyllys 	if (bs != NULL)
2595*99ebb4caSwyllys 		OCSP_BASICRESP_free(bs);
2596*99ebb4caSwyllys 
2597*99ebb4caSwyllys 	if (id != NULL)
2598*99ebb4caSwyllys 		OCSP_CERTID_free(id);
2599*99ebb4caSwyllys 
2600*99ebb4caSwyllys 	return (ret);
2601*99ebb4caSwyllys }
2602*99ebb4caSwyllys 
2603*99ebb4caSwyllys static KMF_RETURN
2604*99ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path,
2605*99ebb4caSwyllys 	KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
2606*99ebb4caSwyllys {
2607*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
2608*99ebb4caSwyllys 	EVP_PKEY *pkey;
2609*99ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
2610*99ebb4caSwyllys 
2611*99ebb4caSwyllys 	/* Make sure the requested file actually exists. */
2612*99ebb4caSwyllys 	if (access(path, F_OK) != 0) {
2613*99ebb4caSwyllys 		return (KMF_ERR_KEY_NOT_FOUND);
2614*99ebb4caSwyllys 	}
2615*99ebb4caSwyllys 
2616*99ebb4caSwyllys 	if (keyclass == KMF_ASYM_PRI ||
2617*99ebb4caSwyllys 	    keyclass == KMF_ASYM_PUB) {
2618*99ebb4caSwyllys 		pkey = openssl_load_key(handle, path);
2619*99ebb4caSwyllys 		if (pkey == NULL) {
2620*99ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
2621*99ebb4caSwyllys 		}
2622*99ebb4caSwyllys 		if (key != NULL) {
2623*99ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA)
2624*99ebb4caSwyllys 				key->keyalg = KMF_RSA;
2625*99ebb4caSwyllys 			else if (pkey->type == EVP_PKEY_DSA)
2626*99ebb4caSwyllys 				key->keyalg = KMF_DSA;
2627*99ebb4caSwyllys 
2628*99ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
2629*99ebb4caSwyllys 			key->keyclass = keyclass;
2630*99ebb4caSwyllys 			key->keyp = (void *)pkey;
2631*99ebb4caSwyllys 			key->israw = FALSE;
2632*99ebb4caSwyllys 			key->keylabel = path;
2633*99ebb4caSwyllys 		} else {
2634*99ebb4caSwyllys 			EVP_PKEY_free(pkey);
2635*99ebb4caSwyllys 			pkey = NULL;
2636*99ebb4caSwyllys 		}
2637*99ebb4caSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
2638*99ebb4caSwyllys 		KMF_ENCODE_FORMAT fmt;
2639*99ebb4caSwyllys 		/*
2640*99ebb4caSwyllys 		 * If the file is a recognized format,
2641*99ebb4caSwyllys 		 * then it is NOT a symmetric key.
2642*99ebb4caSwyllys 		 */
2643*99ebb4caSwyllys 		rv = KMF_GetFileFormat(path, &fmt);
2644*99ebb4caSwyllys 		if (rv == KMF_OK || fmt != 0) {
2645*99ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
2646*99ebb4caSwyllys 		} else if (rv == KMF_ERR_ENCODING) {
2647*99ebb4caSwyllys 			/*
2648*99ebb4caSwyllys 			 * If we don't know the encoding,
2649*99ebb4caSwyllys 			 * it is probably  a symmetric key.
2650*99ebb4caSwyllys 			 */
2651*99ebb4caSwyllys 			rv = KMF_OK;
2652*99ebb4caSwyllys 		}
2653*99ebb4caSwyllys 
2654*99ebb4caSwyllys 		if (key != NULL) {
2655*99ebb4caSwyllys 			KMF_DATA keyvalue;
2656*99ebb4caSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
2657*99ebb4caSwyllys 			if (rkey == NULL) {
2658*99ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
2659*99ebb4caSwyllys 				goto out;
2660*99ebb4caSwyllys 			}
2661*99ebb4caSwyllys 
2662*99ebb4caSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
2663*99ebb4caSwyllys 			rv = KMF_ReadInputFile(handle, path, &keyvalue);
2664*99ebb4caSwyllys 			if (rv != KMF_OK)
2665*99ebb4caSwyllys 				goto out;
2666*99ebb4caSwyllys 
2667*99ebb4caSwyllys 			rkey->keydata.len = keyvalue.Length;
2668*99ebb4caSwyllys 			rkey->keydata.val = keyvalue.Data;
2669*99ebb4caSwyllys 
2670*99ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
2671*99ebb4caSwyllys 			key->keyclass = keyclass;
2672*99ebb4caSwyllys 			key->israw = TRUE;
2673*99ebb4caSwyllys 			key->keylabel = path;
2674*99ebb4caSwyllys 			key->keyp = (void *)rkey;
2675*99ebb4caSwyllys 		}
2676*99ebb4caSwyllys 	}
2677*99ebb4caSwyllys out:
2678*99ebb4caSwyllys 	if (rv != KMF_OK) {
2679*99ebb4caSwyllys 		if (rkey != NULL) {
2680*99ebb4caSwyllys 			KMF_FreeRawSymKey(rkey);
2681*99ebb4caSwyllys 		}
2682*99ebb4caSwyllys 		if (pkey != NULL)
2683*99ebb4caSwyllys 			EVP_PKEY_free(pkey);
2684*99ebb4caSwyllys 
2685*99ebb4caSwyllys 		if (key != NULL) {
2686*99ebb4caSwyllys 			key->keyalg = KMF_KEYALG_NONE;
2687*99ebb4caSwyllys 			key->keyclass = KMF_KEYCLASS_NONE;
2688*99ebb4caSwyllys 			key->keyp = NULL;
2689*99ebb4caSwyllys 		}
2690*99ebb4caSwyllys 	}
2691*99ebb4caSwyllys 
2692*99ebb4caSwyllys 	return (rv);
2693*99ebb4caSwyllys }
2694*99ebb4caSwyllys 
2695*99ebb4caSwyllys KMF_RETURN
2696*99ebb4caSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle, KMF_FINDKEY_PARAMS *params,
2697*99ebb4caSwyllys 	KMF_KEY_HANDLE *key, uint32_t *numkeys)
2698*99ebb4caSwyllys {
2699*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
2700*99ebb4caSwyllys 	char *fullpath = NULL;
2701*99ebb4caSwyllys 
2702*99ebb4caSwyllys 	if (handle == NULL || params == NULL || numkeys == NULL)
2703*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2704*99ebb4caSwyllys 
2705*99ebb4caSwyllys 	if (params->keyclass != KMF_ASYM_PUB &&
2706*99ebb4caSwyllys 		params->keyclass != KMF_ASYM_PRI &&
2707*99ebb4caSwyllys 		params->keyclass != KMF_SYMMETRIC)
2708*99ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
2709*99ebb4caSwyllys 
2710*99ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
2711*99ebb4caSwyllys 		params->sslparms.keyfile);
2712*99ebb4caSwyllys 
2713*99ebb4caSwyllys 	if (fullpath == NULL)
2714*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2715*99ebb4caSwyllys 
2716*99ebb4caSwyllys 	*numkeys = 0;
2717*99ebb4caSwyllys 
2718*99ebb4caSwyllys 	if (isdir(fullpath)) {
2719*99ebb4caSwyllys 		DIR *dirp;
2720*99ebb4caSwyllys 		struct dirent *dp;
2721*99ebb4caSwyllys 		int n = 0;
2722*99ebb4caSwyllys 
2723*99ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
2724*99ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
2725*99ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
2726*99ebb4caSwyllys 		}
2727*99ebb4caSwyllys 		rewinddir(dirp);
2728*99ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
2729*99ebb4caSwyllys 			if (strcmp(dp->d_name, ".") &&
2730*99ebb4caSwyllys 			    strcmp(dp->d_name, "..")) {
2731*99ebb4caSwyllys 				char *fname;
2732*99ebb4caSwyllys 
2733*99ebb4caSwyllys 				fname = get_fullpath(fullpath,
2734*99ebb4caSwyllys 					(char *)&dp->d_name);
2735*99ebb4caSwyllys 
2736*99ebb4caSwyllys 				rv = fetch_key(handle, fname,
2737*99ebb4caSwyllys 					params->keyclass,
2738*99ebb4caSwyllys 					key ? &key[n] : NULL);
2739*99ebb4caSwyllys 
2740*99ebb4caSwyllys 				if (rv == KMF_OK)
2741*99ebb4caSwyllys 					n++;
2742*99ebb4caSwyllys 
2743*99ebb4caSwyllys 				if (rv != KMF_OK || key == NULL)
2744*99ebb4caSwyllys 					free(fname);
2745*99ebb4caSwyllys 			}
2746*99ebb4caSwyllys 		}
2747*99ebb4caSwyllys 		(void) closedir(dirp);
2748*99ebb4caSwyllys 		free(fullpath);
2749*99ebb4caSwyllys 		(*numkeys) = n;
2750*99ebb4caSwyllys 	} else {
2751*99ebb4caSwyllys 		rv = fetch_key(handle, fullpath, params->keyclass, key);
2752*99ebb4caSwyllys 		if (rv == KMF_OK)
2753*99ebb4caSwyllys 			(*numkeys) = 1;
2754*99ebb4caSwyllys 
2755*99ebb4caSwyllys 		if (rv != KMF_OK || key == NULL)
2756*99ebb4caSwyllys 			free(fullpath);
2757*99ebb4caSwyllys 	}
2758*99ebb4caSwyllys 
2759*99ebb4caSwyllys 	if ((*numkeys) == 0)
2760*99ebb4caSwyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
2761*99ebb4caSwyllys 
2762*99ebb4caSwyllys 	return (rv);
2763*99ebb4caSwyllys }
2764*99ebb4caSwyllys 
2765*99ebb4caSwyllys #define	HANDLE_PK12_ERROR { \
2766*99ebb4caSwyllys 	SET_ERROR(kmfh, ERR_get_error()); \
2767*99ebb4caSwyllys 	rv = KMF_ERR_ENCODING; \
2768*99ebb4caSwyllys 	goto out; \
2769*99ebb4caSwyllys }
2770*99ebb4caSwyllys 
2771*99ebb4caSwyllys static KMF_RETURN
2772*99ebb4caSwyllys write_pkcs12(KMF_HANDLE *kmfh,
2773*99ebb4caSwyllys 	BIO *bio,
2774*99ebb4caSwyllys 	KMF_CREDENTIAL *cred,
2775*99ebb4caSwyllys 	EVP_PKEY *pkey,
2776*99ebb4caSwyllys 	X509 *sslcert)
2777*99ebb4caSwyllys {
2778*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
2779*99ebb4caSwyllys 	STACK_OF(PKCS12_SAFEBAG)	*bag_stack = NULL;
2780*99ebb4caSwyllys 	PKCS12_SAFEBAG			*bag = NULL;
2781*99ebb4caSwyllys 	PKCS7				*cert_authsafe = NULL;
2782*99ebb4caSwyllys 	PKCS8_PRIV_KEY_INFO		*p8 = NULL;
2783*99ebb4caSwyllys 	PKCS7				*key_authsafe = NULL;
2784*99ebb4caSwyllys 	STACK_OF(PKCS7)			*authsafe_stack = NULL;
2785*99ebb4caSwyllys 	PKCS12				*p12_elem = NULL;
2786*99ebb4caSwyllys 	char				*lab = NULL;
2787*99ebb4caSwyllys 	int				lab_len = 0;
2788*99ebb4caSwyllys 	unsigned char keyid[EVP_MAX_MD_SIZE];
2789*99ebb4caSwyllys 	unsigned int keyidlen = 0;
2790*99ebb4caSwyllys 
2791*99ebb4caSwyllys 	/* Must have at least a cert OR a key */
2792*99ebb4caSwyllys 	if (sslcert == NULL && pkey == NULL)
2793*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2794*99ebb4caSwyllys 
2795*99ebb4caSwyllys 	(void) memset(keyid, 0, sizeof (keyid));
2796*99ebb4caSwyllys 	/*
2797*99ebb4caSwyllys 	 * Section 1:
2798*99ebb4caSwyllys 	 *
2799*99ebb4caSwyllys 	 * The first PKCS#12 container (safebag) will hold the certificates
2800*99ebb4caSwyllys 	 * associated with this key.  The result of this section is a
2801*99ebb4caSwyllys 	 * PIN-encrypted PKCS#7 container (authsafe).  If there are no
2802*99ebb4caSwyllys 	 * certificates, there is no point in creating the "safebag" or the
2803*99ebb4caSwyllys 	 * "authsafe" so we go to the next section.
2804*99ebb4caSwyllys 	 */
2805*99ebb4caSwyllys 	if (sslcert != NULL && pkey != NULL) {
2806*99ebb4caSwyllys 		if (X509_check_private_key(sslcert, pkey)) {
2807*99ebb4caSwyllys 			(void) X509_digest(sslcert, EVP_sha1(), keyid,
2808*99ebb4caSwyllys 				&keyidlen);
2809*99ebb4caSwyllys 		} else {
2810*99ebb4caSwyllys 			/* The key doesn't match the cert */
2811*99ebb4caSwyllys 			HANDLE_PK12_ERROR
2812*99ebb4caSwyllys 		}
2813*99ebb4caSwyllys 	}
2814*99ebb4caSwyllys 
2815*99ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
2816*99ebb4caSwyllys 	if (bag_stack == NULL)
2817*99ebb4caSwyllys 		return (KMF_ERR_MEMORY);
2818*99ebb4caSwyllys 
2819*99ebb4caSwyllys 	if (sslcert != NULL) {
2820*99ebb4caSwyllys 		/* Convert cert from X509 struct to PKCS#12 bag */
2821*99ebb4caSwyllys 		bag = PKCS12_x5092certbag(sslcert);
2822*99ebb4caSwyllys 		if (bag == NULL) {
2823*99ebb4caSwyllys 			HANDLE_PK12_ERROR
2824*99ebb4caSwyllys 		}
2825*99ebb4caSwyllys 
2826*99ebb4caSwyllys 		/* Add the key id to the certificate bag. */
2827*99ebb4caSwyllys 		if (keyidlen > 0 &&
2828*99ebb4caSwyllys 			!PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
2829*99ebb4caSwyllys 			HANDLE_PK12_ERROR
2830*99ebb4caSwyllys 		}
2831*99ebb4caSwyllys 
2832*99ebb4caSwyllys 		/* Pile it on the bag_stack. */
2833*99ebb4caSwyllys 		if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
2834*99ebb4caSwyllys 			HANDLE_PK12_ERROR
2835*99ebb4caSwyllys 		}
2836*99ebb4caSwyllys #if 0
2837*99ebb4caSwyllys 		/* No support for CA certs yet */
2838*99ebb4caSwyllys 		if (cacerts != NULL && ncacerts > 0) {
2839*99ebb4caSwyllys 			int i;
2840*99ebb4caSwyllys 			for (i = 0; i < ncacerts; i++) {
2841*99ebb4caSwyllys 				KMF_X509_DER_CERT *c = &cacerts[i];
2842*99ebb4caSwyllys 				X509 *ca = NULL;
2843*99ebb4caSwyllys 
2844*99ebb4caSwyllys 				uchar_t *p = (uchar_t *)c->certificate.Data;
2845*99ebb4caSwyllys 				ca = d2i_X509(NULL, &p,
2846*99ebb4caSwyllys 					c->certificate.Length);
2847*99ebb4caSwyllys 				if (ca == NULL) {
2848*99ebb4caSwyllys 					HANDLE_PK12_ERROR
2849*99ebb4caSwyllys 				}
2850*99ebb4caSwyllys 				/* Convert CA cert to PKCS#12 bag. */
2851*99ebb4caSwyllys 				bag = PKCS12_x5092certbag(ca);
2852*99ebb4caSwyllys 				if (bag == NULL) {
2853*99ebb4caSwyllys 					sk_PKCS12_SAFEBAG_pop_free(bag_stack,
2854*99ebb4caSwyllys 					    PKCS12_SAFEBAG_free);
2855*99ebb4caSwyllys 					HANDLE_PK12_ERROR
2856*99ebb4caSwyllys 				}
2857*99ebb4caSwyllys 				/* Pile it onto the bag_stack. */
2858*99ebb4caSwyllys 				if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
2859*99ebb4caSwyllys 					HANDLE_PK12_ERROR
2860*99ebb4caSwyllys 				}
2861*99ebb4caSwyllys 			}
2862*99ebb4caSwyllys 		}
2863*99ebb4caSwyllys #endif
2864*99ebb4caSwyllys 		/* Turn bag_stack of certs into encrypted authsafe. */
2865*99ebb4caSwyllys 		cert_authsafe = PKCS12_pack_p7encdata(
2866*99ebb4caSwyllys 			NID_pbe_WithSHA1And40BitRC2_CBC,
2867*99ebb4caSwyllys 			cred->cred,
2868*99ebb4caSwyllys 			cred->credlen, NULL, 0,
2869*99ebb4caSwyllys 			PKCS12_DEFAULT_ITER,
2870*99ebb4caSwyllys 			bag_stack);
2871*99ebb4caSwyllys 
2872*99ebb4caSwyllys 		/* Clear away this bag_stack, we're done with it. */
2873*99ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
2874*99ebb4caSwyllys 		bag_stack = NULL;
2875*99ebb4caSwyllys 
2876*99ebb4caSwyllys 		if (cert_authsafe == NULL) {
2877*99ebb4caSwyllys 			HANDLE_PK12_ERROR
2878*99ebb4caSwyllys 		}
2879*99ebb4caSwyllys 	}
2880*99ebb4caSwyllys 	/*
2881*99ebb4caSwyllys 	 * Section 2:
2882*99ebb4caSwyllys 	 *
2883*99ebb4caSwyllys 	 * The second PKCS#12 container (safebag) will hold the private key
2884*99ebb4caSwyllys 	 * that goes with the certificates above.  The results of this section
2885*99ebb4caSwyllys 	 * is an unencrypted PKCS#7 container (authsafe).  If there is no
2886*99ebb4caSwyllys 	 * private key, there is no point in creating the "safebag" or the
2887*99ebb4caSwyllys 	 * "authsafe" so we go to the next section.
2888*99ebb4caSwyllys 	 */
2889*99ebb4caSwyllys 	if (pkey != NULL) {
2890*99ebb4caSwyllys 		p8 = EVP_PKEY2PKCS8(pkey);
2891*99ebb4caSwyllys 		if (p8 == NULL) {
2892*99ebb4caSwyllys 			HANDLE_PK12_ERROR
2893*99ebb4caSwyllys 		}
2894*99ebb4caSwyllys 		/* Put the shrouded key into a PKCS#12 bag. */
2895*99ebb4caSwyllys 		bag = PKCS12_MAKE_SHKEYBAG(
2896*99ebb4caSwyllys 			NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
2897*99ebb4caSwyllys 			cred->cred, cred->credlen,
2898*99ebb4caSwyllys 			NULL, 0, PKCS12_DEFAULT_ITER, p8);
2899*99ebb4caSwyllys 
2900*99ebb4caSwyllys 		/* Clean up the PKCS#8 shrouded key, don't need it now. */
2901*99ebb4caSwyllys 		PKCS8_PRIV_KEY_INFO_free(p8);
2902*99ebb4caSwyllys 		p8 = NULL;
2903*99ebb4caSwyllys 
2904*99ebb4caSwyllys 		if (bag == NULL) {
2905*99ebb4caSwyllys 			HANDLE_PK12_ERROR
2906*99ebb4caSwyllys 		}
2907*99ebb4caSwyllys 		if (keyidlen &&
2908*99ebb4caSwyllys 			!PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
2909*99ebb4caSwyllys 			HANDLE_PK12_ERROR
2910*99ebb4caSwyllys 		}
2911*99ebb4caSwyllys 		if (lab != NULL) {
2912*99ebb4caSwyllys 			if (!PKCS12_add_friendlyname(bag,
2913*99ebb4caSwyllys 				(char *)lab, lab_len)) {
2914*99ebb4caSwyllys 				HANDLE_PK12_ERROR
2915*99ebb4caSwyllys 			}
2916*99ebb4caSwyllys 		}
2917*99ebb4caSwyllys 		/* Start a PKCS#12 safebag container for the private key. */
2918*99ebb4caSwyllys 		bag_stack = sk_PKCS12_SAFEBAG_new_null();
2919*99ebb4caSwyllys 		if (bag_stack == NULL) {
2920*99ebb4caSwyllys 			HANDLE_PK12_ERROR
2921*99ebb4caSwyllys 		}
2922*99ebb4caSwyllys 
2923*99ebb4caSwyllys 		/* Pile on the private key on the bag_stack. */
2924*99ebb4caSwyllys 		if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
2925*99ebb4caSwyllys 			HANDLE_PK12_ERROR
2926*99ebb4caSwyllys 		}
2927*99ebb4caSwyllys 		key_authsafe = PKCS12_pack_p7data(bag_stack);
2928*99ebb4caSwyllys 
2929*99ebb4caSwyllys 		/* Clear away this bag_stack, we're done with it. */
2930*99ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
2931*99ebb4caSwyllys 		bag_stack = NULL;
2932*99ebb4caSwyllys 
2933*99ebb4caSwyllys 		if (key_authsafe == NULL) {
2934*99ebb4caSwyllys 			HANDLE_PK12_ERROR
2935*99ebb4caSwyllys 		}
2936*99ebb4caSwyllys 	}
2937*99ebb4caSwyllys 	/*
2938*99ebb4caSwyllys 	 * Section 3:
2939*99ebb4caSwyllys 	 *
2940*99ebb4caSwyllys 	 * This is where the two PKCS#7 containers, one for the certificates
2941*99ebb4caSwyllys 	 * and one for the private key, are put together into a PKCS#12
2942*99ebb4caSwyllys 	 * element.  This final PKCS#12 element is written to the export file.
2943*99ebb4caSwyllys 	 */
2944*99ebb4caSwyllys 
2945*99ebb4caSwyllys 	/* Start a PKCS#7 stack. */
2946*99ebb4caSwyllys 	authsafe_stack = sk_PKCS7_new_null();
2947*99ebb4caSwyllys 	if (authsafe_stack == NULL) {
2948*99ebb4caSwyllys 		HANDLE_PK12_ERROR
2949*99ebb4caSwyllys 	}
2950*99ebb4caSwyllys 	if (key_authsafe != NULL) {
2951*99ebb4caSwyllys 		if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
2952*99ebb4caSwyllys 			HANDLE_PK12_ERROR
2953*99ebb4caSwyllys 		}
2954*99ebb4caSwyllys 	}
2955*99ebb4caSwyllys 	if (cert_authsafe != NULL) {
2956*99ebb4caSwyllys 		if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
2957*99ebb4caSwyllys 			HANDLE_PK12_ERROR
2958*99ebb4caSwyllys 		}
2959*99ebb4caSwyllys 	}
2960*99ebb4caSwyllys 	p12_elem = PKCS12_init(NID_pkcs7_data);
2961*99ebb4caSwyllys 	if (p12_elem == NULL) {
2962*99ebb4caSwyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
2963*99ebb4caSwyllys 		HANDLE_PK12_ERROR
2964*99ebb4caSwyllys 	}
2965*99ebb4caSwyllys 
2966*99ebb4caSwyllys 	/* Put the PKCS#7 stack into the PKCS#12 element. */
2967*99ebb4caSwyllys 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
2968*99ebb4caSwyllys 		HANDLE_PK12_ERROR
2969*99ebb4caSwyllys 	}
2970*99ebb4caSwyllys 	/* Clear away the PKCS#7 stack, we're done with it. */
2971*99ebb4caSwyllys 	sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
2972*99ebb4caSwyllys 	authsafe_stack = NULL;
2973*99ebb4caSwyllys 
2974*99ebb4caSwyllys 	/* Set the integrity MAC on the PKCS#12 element. */
2975*99ebb4caSwyllys 	if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
2976*99ebb4caSwyllys 		NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
2977*99ebb4caSwyllys 		HANDLE_PK12_ERROR
2978*99ebb4caSwyllys 	}
2979*99ebb4caSwyllys 
2980*99ebb4caSwyllys 	/* Write the PKCS#12 element to the export file. */
2981*99ebb4caSwyllys 	if (!i2d_PKCS12_bio(bio, p12_elem)) {
2982*99ebb4caSwyllys 		HANDLE_PK12_ERROR
2983*99ebb4caSwyllys 	}
2984*99ebb4caSwyllys 
2985*99ebb4caSwyllys 	PKCS12_free(p12_elem);
2986*99ebb4caSwyllys out:
2987*99ebb4caSwyllys 	if (rv != KMF_OK) {
2988*99ebb4caSwyllys 		/* Clear away this bag_stack, we're done with it. */
2989*99ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
2990*99ebb4caSwyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
2991*99ebb4caSwyllys 	}
2992*99ebb4caSwyllys 	return (rv);
2993*99ebb4caSwyllys }
2994*99ebb4caSwyllys 
2995*99ebb4caSwyllys static EVP_PKEY *
2996*99ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
2997*99ebb4caSwyllys {
2998*99ebb4caSwyllys 	RSA		*rsa = NULL;
2999*99ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
3000*99ebb4caSwyllys 
3001*99ebb4caSwyllys 	if ((rsa = RSA_new()) == NULL)
3002*99ebb4caSwyllys 		return (NULL);
3003*99ebb4caSwyllys 
3004*99ebb4caSwyllys 	if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL)
3005*99ebb4caSwyllys 		return (NULL);
3006*99ebb4caSwyllys 
3007*99ebb4caSwyllys 	if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) ==
3008*99ebb4caSwyllys 		NULL)
3009*99ebb4caSwyllys 		return (NULL);
3010*99ebb4caSwyllys 
3011*99ebb4caSwyllys 	if (key->priexp.val != NULL)
3012*99ebb4caSwyllys 		if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len,
3013*99ebb4caSwyllys 			rsa->d)) == NULL)
3014*99ebb4caSwyllys 			return (NULL);
3015*99ebb4caSwyllys 
3016*99ebb4caSwyllys 	if (key->prime1.val != NULL)
3017*99ebb4caSwyllys 		if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len,
3018*99ebb4caSwyllys 			rsa->p)) == NULL)
3019*99ebb4caSwyllys 			return (NULL);
3020*99ebb4caSwyllys 
3021*99ebb4caSwyllys 	if (key->prime2.val != NULL)
3022*99ebb4caSwyllys 		if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len,
3023*99ebb4caSwyllys 			rsa->q)) == NULL)
3024*99ebb4caSwyllys 			return (NULL);
3025*99ebb4caSwyllys 
3026*99ebb4caSwyllys 	if (key->exp1.val != NULL)
3027*99ebb4caSwyllys 		if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len,
3028*99ebb4caSwyllys 			rsa->dmp1)) == NULL)
3029*99ebb4caSwyllys 			return (NULL);
3030*99ebb4caSwyllys 
3031*99ebb4caSwyllys 	if (key->exp2.val != NULL)
3032*99ebb4caSwyllys 		if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len,
3033*99ebb4caSwyllys 			rsa->dmq1)) == NULL)
3034*99ebb4caSwyllys 			return (NULL);
3035*99ebb4caSwyllys 
3036*99ebb4caSwyllys 	if (key->coef.val != NULL)
3037*99ebb4caSwyllys 		if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len,
3038*99ebb4caSwyllys 			rsa->iqmp)) == NULL)
3039*99ebb4caSwyllys 			return (NULL);
3040*99ebb4caSwyllys 
3041*99ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
3042*99ebb4caSwyllys 		return (NULL);
3043*99ebb4caSwyllys 
3044*99ebb4caSwyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
3045*99ebb4caSwyllys 
3046*99ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
3047*99ebb4caSwyllys 	RSA_free(rsa);
3048*99ebb4caSwyllys 
3049*99ebb4caSwyllys 	return (newkey);
3050*99ebb4caSwyllys }
3051*99ebb4caSwyllys 
3052*99ebb4caSwyllys static EVP_PKEY *
3053*99ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
3054*99ebb4caSwyllys {
3055*99ebb4caSwyllys 	DSA		*dsa = NULL;
3056*99ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
3057*99ebb4caSwyllys 
3058*99ebb4caSwyllys 	if ((dsa = DSA_new()) == NULL)
3059*99ebb4caSwyllys 		return (NULL);
3060*99ebb4caSwyllys 
3061*99ebb4caSwyllys 	if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len,
3062*99ebb4caSwyllys 		dsa->p)) == NULL)
3063*99ebb4caSwyllys 		return (NULL);
3064*99ebb4caSwyllys 
3065*99ebb4caSwyllys 	if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len,
3066*99ebb4caSwyllys 		dsa->q)) == NULL)
3067*99ebb4caSwyllys 		return (NULL);
3068*99ebb4caSwyllys 
3069*99ebb4caSwyllys 	if ((dsa->g = BN_bin2bn(key->base.val, key->base.len,
3070*99ebb4caSwyllys 		dsa->g)) == NULL)
3071*99ebb4caSwyllys 		return (NULL);
3072*99ebb4caSwyllys 
3073*99ebb4caSwyllys 	if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len,
3074*99ebb4caSwyllys 		dsa->priv_key)) == NULL)
3075*99ebb4caSwyllys 		return (NULL);
3076*99ebb4caSwyllys 
3077*99ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
3078*99ebb4caSwyllys 		return (NULL);
3079*99ebb4caSwyllys 
3080*99ebb4caSwyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
3081*99ebb4caSwyllys 
3082*99ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
3083*99ebb4caSwyllys 	DSA_free(dsa);
3084*99ebb4caSwyllys 	return (newkey);
3085*99ebb4caSwyllys }
3086*99ebb4caSwyllys 
3087*99ebb4caSwyllys static KMF_RETURN
3088*99ebb4caSwyllys ExportPK12FromRawData(KMF_HANDLE_T handle,
3089*99ebb4caSwyllys 	KMF_CREDENTIAL *cred,
3090*99ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
3091*99ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
3092*99ebb4caSwyllys 	char *filename)
3093*99ebb4caSwyllys {
3094*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
3095*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3096*99ebb4caSwyllys 	BIO *bio = NULL;
3097*99ebb4caSwyllys 	X509 *xcert = NULL;
3098*99ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
3099*99ebb4caSwyllys 	int i;
3100*99ebb4caSwyllys 
3101*99ebb4caSwyllys 	/*
3102*99ebb4caSwyllys 	 * Open the output file.
3103*99ebb4caSwyllys 	 */
3104*99ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
3105*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
3106*99ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
3107*99ebb4caSwyllys 		goto cleanup;
3108*99ebb4caSwyllys 	}
3109*99ebb4caSwyllys 
3110*99ebb4caSwyllys 	if (numcerts > 0 && numkeys > 0) {
3111*99ebb4caSwyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
3112*99ebb4caSwyllys 			KMF_RAW_KEY_DATA *key = NULL;
3113*99ebb4caSwyllys 			const uchar_t *p = certlist[i].certificate.Data;
3114*99ebb4caSwyllys 			long len = certlist[i].certificate.Length;
3115*99ebb4caSwyllys 
3116*99ebb4caSwyllys 			if (i < numkeys) {
3117*99ebb4caSwyllys 				key = (KMF_RAW_KEY_DATA *)keylist[i].keyp;
3118*99ebb4caSwyllys 
3119*99ebb4caSwyllys 				if (key->keytype == KMF_RSA) {
3120*99ebb4caSwyllys 					pkey = ImportRawRSAKey(
3121*99ebb4caSwyllys 						&key->rawdata.rsa);
3122*99ebb4caSwyllys 				} else if (key->keytype == KMF_DSA) {
3123*99ebb4caSwyllys 					pkey = ImportRawDSAKey(
3124*99ebb4caSwyllys 						&key->rawdata.dsa);
3125*99ebb4caSwyllys 				} else {
3126*99ebb4caSwyllys 					rv = KMF_ERR_BAD_PARAMETER;
3127*99ebb4caSwyllys 				}
3128*99ebb4caSwyllys 			}
3129*99ebb4caSwyllys 
3130*99ebb4caSwyllys 			xcert = d2i_X509(NULL, &p, len);
3131*99ebb4caSwyllys 			if (xcert == NULL) {
3132*99ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
3133*99ebb4caSwyllys 				rv = KMF_ERR_ENCODING;
3134*99ebb4caSwyllys 			}
3135*99ebb4caSwyllys 			/* Stick the key and the cert into a PKCS#12 file */
3136*99ebb4caSwyllys 			rv = write_pkcs12(kmfh, bio, cred, pkey, xcert);
3137*99ebb4caSwyllys 			if (xcert)
3138*99ebb4caSwyllys 				X509_free(xcert);
3139*99ebb4caSwyllys 			if (pkey)
3140*99ebb4caSwyllys 				EVP_PKEY_free(pkey);
3141*99ebb4caSwyllys 		}
3142*99ebb4caSwyllys 	}
3143*99ebb4caSwyllys 
3144*99ebb4caSwyllys cleanup:
3145*99ebb4caSwyllys 
3146*99ebb4caSwyllys 	if (bio != NULL)
3147*99ebb4caSwyllys 		(void) BIO_free_all(bio);
3148*99ebb4caSwyllys 
3149*99ebb4caSwyllys 	return (rv);
3150*99ebb4caSwyllys }
3151*99ebb4caSwyllys 
3152*99ebb4caSwyllys KMF_RETURN
3153*99ebb4caSwyllys OpenSSL_ExportP12(KMF_HANDLE_T handle,
3154*99ebb4caSwyllys 	KMF_EXPORTP12_PARAMS *params,
3155*99ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
3156*99ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
3157*99ebb4caSwyllys 	char *filename)
3158*99ebb4caSwyllys {
3159*99ebb4caSwyllys 	KMF_RETURN rv;
3160*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
3161*99ebb4caSwyllys 	KMF_FINDCERT_PARAMS fcargs;
3162*99ebb4caSwyllys 	BIO *bio = NULL;
3163*99ebb4caSwyllys 	X509 *xcert = NULL;
3164*99ebb4caSwyllys 	char *fullpath = NULL;
3165*99ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
3166*99ebb4caSwyllys 
3167*99ebb4caSwyllys 	/*
3168*99ebb4caSwyllys 	 *  First, find the certificate.
3169*99ebb4caSwyllys 	 */
3170*99ebb4caSwyllys 	if (params == NULL)
3171*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
3172*99ebb4caSwyllys 
3173*99ebb4caSwyllys 	/*
3174*99ebb4caSwyllys 	 * If the caller already sent the raw keys and certs,
3175*99ebb4caSwyllys 	 * shortcut the search and just export that
3176*99ebb4caSwyllys 	 * data.
3177*99ebb4caSwyllys 	 *
3178*99ebb4caSwyllys 	 * One *may* export a key OR a cert by itself.
3179*99ebb4caSwyllys 	 */
3180*99ebb4caSwyllys 	if (certlist != NULL || keylist != NULL) {
3181*99ebb4caSwyllys 		rv = ExportPK12FromRawData(handle,
3182*99ebb4caSwyllys 			&params->p12cred,
3183*99ebb4caSwyllys 			numcerts, certlist,
3184*99ebb4caSwyllys 			numkeys, keylist,
3185*99ebb4caSwyllys 			filename);
3186*99ebb4caSwyllys 		return (rv);
3187*99ebb4caSwyllys 	}
3188*99ebb4caSwyllys 
3189*99ebb4caSwyllys 	if (params->sslparms.certfile != NULL) {
3190*99ebb4caSwyllys 		fullpath = get_fullpath(params->sslparms.dirpath,
3191*99ebb4caSwyllys 			params->sslparms.certfile);
3192*99ebb4caSwyllys 
3193*99ebb4caSwyllys 		if (fullpath == NULL)
3194*99ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
3195*99ebb4caSwyllys 
3196*99ebb4caSwyllys 		if (isdir(fullpath)) {
3197*99ebb4caSwyllys 			free(fullpath);
3198*99ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
3199*99ebb4caSwyllys 		}
3200*99ebb4caSwyllys 
3201*99ebb4caSwyllys 		(void *)memset(&fcargs, 0, sizeof (fcargs));
3202*99ebb4caSwyllys 		fcargs.kstype = params->kstype;
3203*99ebb4caSwyllys 		fcargs.certLabel = params->certLabel;
3204*99ebb4caSwyllys 		fcargs.issuer = params->issuer;
3205*99ebb4caSwyllys 		fcargs.subject = params->subject;
3206*99ebb4caSwyllys 		fcargs.serial = params->serial;
3207*99ebb4caSwyllys 		fcargs.idstr = params->idstr;
3208*99ebb4caSwyllys 		fcargs.sslparms.dirpath = NULL;
3209*99ebb4caSwyllys 		fcargs.sslparms.certfile = fullpath;
3210*99ebb4caSwyllys 		fcargs.sslparms.format = params->sslparms.format;
3211*99ebb4caSwyllys 
3212*99ebb4caSwyllys 		rv = load_X509cert(kmfh, &fcargs, fullpath, &xcert);
3213*99ebb4caSwyllys 		if (rv != KMF_OK)
3214*99ebb4caSwyllys 			goto end;
3215*99ebb4caSwyllys 	}
3216*99ebb4caSwyllys 
3217*99ebb4caSwyllys 	/*
3218*99ebb4caSwyllys 	 * Now find the private key.
3219*99ebb4caSwyllys 	 */
3220*99ebb4caSwyllys 	if (params->sslparms.keyfile != NULL) {
3221*99ebb4caSwyllys 		fullpath = get_fullpath(params->sslparms.dirpath,
3222*99ebb4caSwyllys 			params->sslparms.keyfile);
3223*99ebb4caSwyllys 
3224*99ebb4caSwyllys 		if (fullpath == NULL)
3225*99ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
3226*99ebb4caSwyllys 
3227*99ebb4caSwyllys 		if (isdir(fullpath)) {
3228*99ebb4caSwyllys 			free(fullpath);
3229*99ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
3230*99ebb4caSwyllys 		}
3231*99ebb4caSwyllys 
3232*99ebb4caSwyllys 		pkey = openssl_load_key(handle, fullpath);
3233*99ebb4caSwyllys 		if (pkey == NULL) {
3234*99ebb4caSwyllys 			rv = KMF_ERR_KEY_NOT_FOUND;
3235*99ebb4caSwyllys 			goto end;
3236*99ebb4caSwyllys 		}
3237*99ebb4caSwyllys 	}
3238*99ebb4caSwyllys 
3239*99ebb4caSwyllys 	/*
3240*99ebb4caSwyllys 	 * Open the output file.
3241*99ebb4caSwyllys 	 */
3242*99ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
3243*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
3244*99ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
3245*99ebb4caSwyllys 		goto end;
3246*99ebb4caSwyllys 	}
3247*99ebb4caSwyllys 
3248*99ebb4caSwyllys 	/* Stick the key and the cert into a PKCS#12 file */
3249*99ebb4caSwyllys 	rv = write_pkcs12(kmfh, bio, &params->p12cred,
3250*99ebb4caSwyllys 		pkey, xcert);
3251*99ebb4caSwyllys 
3252*99ebb4caSwyllys end:
3253*99ebb4caSwyllys 	if (fullpath)
3254*99ebb4caSwyllys 		free(fullpath);
3255*99ebb4caSwyllys 	if (xcert)
3256*99ebb4caSwyllys 		X509_free(xcert);
3257*99ebb4caSwyllys 	if (pkey)
3258*99ebb4caSwyllys 		EVP_PKEY_free(pkey);
3259*99ebb4caSwyllys 	if (bio)
3260*99ebb4caSwyllys 		(void) BIO_free(bio);
3261*99ebb4caSwyllys 
3262*99ebb4caSwyllys 	return (rv);
3263*99ebb4caSwyllys }
3264*99ebb4caSwyllys 
3265*99ebb4caSwyllys /*
3266*99ebb4caSwyllys  * Helper function to decrypt and parse PKCS#12 import file.
3267*99ebb4caSwyllys  */
3268*99ebb4caSwyllys static KMF_RETURN
3269*99ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
3270*99ebb4caSwyllys 	EVP_PKEY **priv_key, X509 **cert, STACK_OF(X509) **ca)
3271*99ebb4caSwyllys /* ARGSUSED */
3272*99ebb4caSwyllys {
3273*99ebb4caSwyllys 	PKCS12		*pk12, *pk12_tmp;
3274*99ebb4caSwyllys 	EVP_PKEY	*temp_pkey = NULL;
3275*99ebb4caSwyllys 	X509		*temp_cert = NULL;
3276*99ebb4caSwyllys 	STACK_OF(X509)	*temp_ca = NULL;
3277*99ebb4caSwyllys 
3278*99ebb4caSwyllys 	if ((pk12 = PKCS12_new()) == NULL) {
3279*99ebb4caSwyllys 		return (KMF_ERR_MEMORY);
3280*99ebb4caSwyllys 	}
3281*99ebb4caSwyllys 
3282*99ebb4caSwyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
3283*99ebb4caSwyllys 		/* This is ok; it seems to mean there is no more to read. */
3284*99ebb4caSwyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
3285*99ebb4caSwyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
3286*99ebb4caSwyllys 			goto end_extract_pkcs12;
3287*99ebb4caSwyllys 
3288*99ebb4caSwyllys 		PKCS12_free(pk12);
3289*99ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
3290*99ebb4caSwyllys 	}
3291*99ebb4caSwyllys 	pk12 = pk12_tmp;
3292*99ebb4caSwyllys 
3293*99ebb4caSwyllys 	if (PKCS12_parse(pk12, (char *)pin, &temp_pkey, &temp_cert,
3294*99ebb4caSwyllys 	    &temp_ca) <= 0) {
3295*99ebb4caSwyllys 		PKCS12_free(pk12);
3296*99ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
3297*99ebb4caSwyllys 	}
3298*99ebb4caSwyllys 
3299*99ebb4caSwyllys end_extract_pkcs12:
3300*99ebb4caSwyllys 
3301*99ebb4caSwyllys 	*priv_key = temp_pkey;
3302*99ebb4caSwyllys 	*cert = temp_cert;
3303*99ebb4caSwyllys 	*ca = temp_ca;
3304*99ebb4caSwyllys 
3305*99ebb4caSwyllys 	PKCS12_free(pk12);
3306*99ebb4caSwyllys 	return (KMF_OK);
3307*99ebb4caSwyllys }
3308*99ebb4caSwyllys 
3309*99ebb4caSwyllys static KMF_RETURN
3310*99ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
3311*99ebb4caSwyllys {
3312*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
3313*99ebb4caSwyllys 	uint32_t sz;
3314*99ebb4caSwyllys 
3315*99ebb4caSwyllys 	sz = BN_num_bytes(from);
3316*99ebb4caSwyllys 	to->val = (uchar_t *)malloc(sz);
3317*99ebb4caSwyllys 	if (to->val == NULL)
3318*99ebb4caSwyllys 		return (KMF_ERR_MEMORY);
3319*99ebb4caSwyllys 
3320*99ebb4caSwyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
3321*99ebb4caSwyllys 		free(to->val);
3322*99ebb4caSwyllys 		to->val = NULL;
3323*99ebb4caSwyllys 		to->len = 0;
3324*99ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
3325*99ebb4caSwyllys 	}
3326*99ebb4caSwyllys 
3327*99ebb4caSwyllys 	return (rv);
3328*99ebb4caSwyllys }
3329*99ebb4caSwyllys 
3330*99ebb4caSwyllys static KMF_RETURN
3331*99ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
3332*99ebb4caSwyllys {
3333*99ebb4caSwyllys 	KMF_RETURN rv;
3334*99ebb4caSwyllys 	KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
3335*99ebb4caSwyllys 
3336*99ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
3337*99ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK)
3338*99ebb4caSwyllys 		goto cleanup;
3339*99ebb4caSwyllys 
3340*99ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK)
3341*99ebb4caSwyllys 		goto cleanup;
3342*99ebb4caSwyllys 
3343*99ebb4caSwyllys 	if (rsa->d != NULL)
3344*99ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK)
3345*99ebb4caSwyllys 			goto cleanup;
3346*99ebb4caSwyllys 
3347*99ebb4caSwyllys 	if (rsa->p != NULL)
3348*99ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK)
3349*99ebb4caSwyllys 			goto cleanup;
3350*99ebb4caSwyllys 
3351*99ebb4caSwyllys 	if (rsa->q != NULL)
3352*99ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK)
3353*99ebb4caSwyllys 			goto cleanup;
3354*99ebb4caSwyllys 
3355*99ebb4caSwyllys 	if (rsa->dmp1 != NULL)
3356*99ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK)
3357*99ebb4caSwyllys 			goto cleanup;
3358*99ebb4caSwyllys 
3359*99ebb4caSwyllys 	if (rsa->dmq1 != NULL)
3360*99ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK)
3361*99ebb4caSwyllys 			goto cleanup;
3362*99ebb4caSwyllys 
3363*99ebb4caSwyllys 	if (rsa->iqmp != NULL)
3364*99ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK)
3365*99ebb4caSwyllys 			goto cleanup;
3366*99ebb4caSwyllys cleanup:
3367*99ebb4caSwyllys 	if (rv != KMF_OK)
3368*99ebb4caSwyllys 		KMF_FreeRawKey(key);
3369*99ebb4caSwyllys 	else
3370*99ebb4caSwyllys 		key->keytype = KMF_RSA;
3371*99ebb4caSwyllys 
3372*99ebb4caSwyllys 	/*
3373*99ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
3374*99ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
3375*99ebb4caSwyllys 	 */
3376*99ebb4caSwyllys 	RSA_free(rsa);
3377*99ebb4caSwyllys 
3378*99ebb4caSwyllys 	return (rv);
3379*99ebb4caSwyllys }
3380*99ebb4caSwyllys 
3381*99ebb4caSwyllys static KMF_RETURN
3382*99ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
3383*99ebb4caSwyllys {
3384*99ebb4caSwyllys 	KMF_RETURN rv;
3385*99ebb4caSwyllys 	KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
3386*99ebb4caSwyllys 
3387*99ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
3388*99ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK)
3389*99ebb4caSwyllys 		goto cleanup;
3390*99ebb4caSwyllys 
3391*99ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK)
3392*99ebb4caSwyllys 		goto cleanup;
3393*99ebb4caSwyllys 
3394*99ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK)
3395*99ebb4caSwyllys 		goto cleanup;
3396*99ebb4caSwyllys 
3397*99ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK)
3398*99ebb4caSwyllys 		goto cleanup;
3399*99ebb4caSwyllys 
3400*99ebb4caSwyllys cleanup:
3401*99ebb4caSwyllys 	if (rv != KMF_OK)
3402*99ebb4caSwyllys 		KMF_FreeRawKey(key);
3403*99ebb4caSwyllys 	else
3404*99ebb4caSwyllys 		key->keytype = KMF_DSA;
3405*99ebb4caSwyllys 
3406*99ebb4caSwyllys 	/*
3407*99ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
3408*99ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
3409*99ebb4caSwyllys 	 */
3410*99ebb4caSwyllys 	DSA_free(dsa);
3411*99ebb4caSwyllys 
3412*99ebb4caSwyllys 	return (rv);
3413*99ebb4caSwyllys }
3414*99ebb4caSwyllys 
3415*99ebb4caSwyllys static KMF_RETURN
3416*99ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
3417*99ebb4caSwyllys 	KMF_DATA **certlist, int *ncerts)
3418*99ebb4caSwyllys {
3419*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
3420*99ebb4caSwyllys 	KMF_DATA *list = (*certlist);
3421*99ebb4caSwyllys 	KMF_DATA cert;
3422*99ebb4caSwyllys 	int n = (*ncerts);
3423*99ebb4caSwyllys 
3424*99ebb4caSwyllys 	if (list == NULL) {
3425*99ebb4caSwyllys 		list = (KMF_DATA *)malloc(sizeof (KMF_DATA));
3426*99ebb4caSwyllys 	} else {
3427*99ebb4caSwyllys 		list = (KMF_DATA *)realloc(list, sizeof (KMF_DATA) * (n + 1));
3428*99ebb4caSwyllys 	}
3429*99ebb4caSwyllys 
3430*99ebb4caSwyllys 	if (list == NULL)
3431*99ebb4caSwyllys 		return (KMF_ERR_MEMORY);
3432*99ebb4caSwyllys 
3433*99ebb4caSwyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert);
3434*99ebb4caSwyllys 	if (rv == KMF_OK) {
3435*99ebb4caSwyllys 		list[n] = cert;
3436*99ebb4caSwyllys 		(*ncerts) = n + 1;
3437*99ebb4caSwyllys 
3438*99ebb4caSwyllys 		*certlist = list;
3439*99ebb4caSwyllys 	} else {
3440*99ebb4caSwyllys 		free(list);
3441*99ebb4caSwyllys 	}
3442*99ebb4caSwyllys 
3443*99ebb4caSwyllys 	return (rv);
3444*99ebb4caSwyllys }
3445*99ebb4caSwyllys 
3446*99ebb4caSwyllys static KMF_RETURN
3447*99ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
3448*99ebb4caSwyllys 	KMF_RAW_KEY_DATA *newkey, int *nkeys)
3449*99ebb4caSwyllys {
3450*99ebb4caSwyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
3451*99ebb4caSwyllys 	int n = (*nkeys);
3452*99ebb4caSwyllys 
3453*99ebb4caSwyllys 	if (list == NULL) {
3454*99ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
3455*99ebb4caSwyllys 	} else {
3456*99ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
3457*99ebb4caSwyllys 			sizeof (KMF_RAW_KEY_DATA) * (n + 1));
3458*99ebb4caSwyllys 	}
3459*99ebb4caSwyllys 
3460*99ebb4caSwyllys 	if (list == NULL)
3461*99ebb4caSwyllys 		return (KMF_ERR_MEMORY);
3462*99ebb4caSwyllys 
3463*99ebb4caSwyllys 	list[n] = *newkey;
3464*99ebb4caSwyllys 	(*nkeys) = n + 1;
3465*99ebb4caSwyllys 
3466*99ebb4caSwyllys 	*keylist = list;
3467*99ebb4caSwyllys 
3468*99ebb4caSwyllys 	return (KMF_OK);
3469*99ebb4caSwyllys }
3470*99ebb4caSwyllys 
3471*99ebb4caSwyllys 
3472*99ebb4caSwyllys static KMF_RETURN
3473*99ebb4caSwyllys convertPK12Objects(
3474*99ebb4caSwyllys 	KMF_HANDLE *kmfh,
3475*99ebb4caSwyllys 	EVP_PKEY *sslkey, X509 *sslcert, STACK_OF(X509) *sslcacerts,
3476*99ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
3477*99ebb4caSwyllys 	KMF_DATA **certlist, int *ncerts)
3478*99ebb4caSwyllys {
3479*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
3480*99ebb4caSwyllys 	KMF_RAW_KEY_DATA key;
3481*99ebb4caSwyllys 	int i;
3482*99ebb4caSwyllys 
3483*99ebb4caSwyllys 	if (sslkey != NULL) {
3484*99ebb4caSwyllys 		/* Convert SSL key to raw key */
3485*99ebb4caSwyllys 		switch (sslkey->type) {
3486*99ebb4caSwyllys 			case EVP_PKEY_RSA:
3487*99ebb4caSwyllys 				rv = exportRawRSAKey(EVP_PKEY_get1_RSA(sslkey),
3488*99ebb4caSwyllys 					&key);
3489*99ebb4caSwyllys 				if (rv != KMF_OK)
3490*99ebb4caSwyllys 					return (rv);
3491*99ebb4caSwyllys 
3492*99ebb4caSwyllys 				break;
3493*99ebb4caSwyllys 			case EVP_PKEY_DSA:
3494*99ebb4caSwyllys 				rv = exportRawDSAKey(EVP_PKEY_get1_DSA(sslkey),
3495*99ebb4caSwyllys 					&key);
3496*99ebb4caSwyllys 				if (rv != KMF_OK)
3497*99ebb4caSwyllys 					return (rv);
3498*99ebb4caSwyllys 
3499*99ebb4caSwyllys 				break;
3500*99ebb4caSwyllys 			default:
3501*99ebb4caSwyllys 				return (KMF_ERR_BAD_PARAMETER);
3502*99ebb4caSwyllys 		}
3503*99ebb4caSwyllys 
3504*99ebb4caSwyllys 		rv = add_key_to_list(keylist, &key, nkeys);
3505*99ebb4caSwyllys 		if (rv != KMF_OK)
3506*99ebb4caSwyllys 			return (rv);
3507*99ebb4caSwyllys 	}
3508*99ebb4caSwyllys 
3509*99ebb4caSwyllys 	/* Now add the certificate to the certlist */
3510*99ebb4caSwyllys 	if (sslcert != NULL) {
3511*99ebb4caSwyllys 		rv = add_cert_to_list(kmfh, sslcert, certlist, ncerts);
3512*99ebb4caSwyllys 		if (rv != KMF_OK)
3513*99ebb4caSwyllys 			return (rv);
3514*99ebb4caSwyllys 	}
3515*99ebb4caSwyllys 
3516*99ebb4caSwyllys 	/* Also add any included CA certs to the list */
3517*99ebb4caSwyllys 	for (i = 0; i != sk_X509_num(sslcacerts); i++) {
3518*99ebb4caSwyllys 		X509 *c;
3519*99ebb4caSwyllys 		/*
3520*99ebb4caSwyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
3521*99ebb4caSwyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
3522*99ebb4caSwyllys 		 * Lint is complaining about the embedded casting, and
3523*99ebb4caSwyllys 		 * to fix it, you need to fix openssl header files.
3524*99ebb4caSwyllys 		 */
3525*99ebb4caSwyllys 		/* LINTED E_BAD_PTR_CAST_ALIGN */
3526*99ebb4caSwyllys 		c = sk_X509_value(sslcacerts, i);
3527*99ebb4caSwyllys 
3528*99ebb4caSwyllys 		/* Now add the ca cert to the certlist */
3529*99ebb4caSwyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
3530*99ebb4caSwyllys 		if (rv != KMF_OK)
3531*99ebb4caSwyllys 			return (rv);
3532*99ebb4caSwyllys 	}
3533*99ebb4caSwyllys 	return (rv);
3534*99ebb4caSwyllys }
3535*99ebb4caSwyllys 
3536*99ebb4caSwyllys KMF_RETURN
3537*99ebb4caSwyllys openssl_read_pkcs12(KMF_HANDLE *kmfh,
3538*99ebb4caSwyllys 	char *filename, KMF_CREDENTIAL *cred,
3539*99ebb4caSwyllys 	KMF_DATA **certlist, int *ncerts,
3540*99ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
3541*99ebb4caSwyllys {
3542*99ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
3543*99ebb4caSwyllys 	BIO		*bio = NULL;
3544*99ebb4caSwyllys 	EVP_PKEY	*privkey = NULL;
3545*99ebb4caSwyllys 	X509		*cert = NULL;
3546*99ebb4caSwyllys 	STACK_OF(X509)	*cacerts = NULL;
3547*99ebb4caSwyllys 
3548*99ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
3549*99ebb4caSwyllys 	if (bio == NULL) {
3550*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
3551*99ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
3552*99ebb4caSwyllys 		goto end;
3553*99ebb4caSwyllys 	}
3554*99ebb4caSwyllys 
3555*99ebb4caSwyllys 	*certlist = NULL;
3556*99ebb4caSwyllys 	*keylist = NULL;
3557*99ebb4caSwyllys 	*ncerts = 0;
3558*99ebb4caSwyllys 	*nkeys = 0;
3559*99ebb4caSwyllys 	while (rv == KMF_OK) {
3560*99ebb4caSwyllys 		rv = extract_pkcs12(bio,
3561*99ebb4caSwyllys 			(uchar_t *)cred->cred,
3562*99ebb4caSwyllys 			(uint32_t)cred->credlen,
3563*99ebb4caSwyllys 			&privkey, &cert, &cacerts);
3564*99ebb4caSwyllys 
3565*99ebb4caSwyllys 		/* Reached end of import file? */
3566*99ebb4caSwyllys 		if (rv == KMF_OK && privkey == NULL &&
3567*99ebb4caSwyllys 			cert == NULL && cacerts == NULL)
3568*99ebb4caSwyllys 			break;
3569*99ebb4caSwyllys 
3570*99ebb4caSwyllys 		if (rv == KMF_OK)
3571*99ebb4caSwyllys 			/* Convert keys and certs to exportable format */
3572*99ebb4caSwyllys 			rv = convertPK12Objects(kmfh, privkey, cert, cacerts,
3573*99ebb4caSwyllys 				keylist, nkeys, certlist, ncerts);
3574*99ebb4caSwyllys 
3575*99ebb4caSwyllys 		if (privkey)
3576*99ebb4caSwyllys 			EVP_PKEY_free(privkey);
3577*99ebb4caSwyllys 
3578*99ebb4caSwyllys 		if (cert)
3579*99ebb4caSwyllys 			X509_free(cert);
3580*99ebb4caSwyllys 
3581*99ebb4caSwyllys 		if (cacerts)
3582*99ebb4caSwyllys 			sk_X509_free(cacerts);
3583*99ebb4caSwyllys 	}
3584*99ebb4caSwyllys end:
3585*99ebb4caSwyllys 	if (bio != NULL)
3586*99ebb4caSwyllys 		(void) BIO_free(bio);
3587*99ebb4caSwyllys 
3588*99ebb4caSwyllys 	if (privkey)
3589*99ebb4caSwyllys 		EVP_PKEY_free(privkey);
3590*99ebb4caSwyllys 
3591*99ebb4caSwyllys 	if (cert)
3592*99ebb4caSwyllys 		X509_free(cert);
3593*99ebb4caSwyllys 
3594*99ebb4caSwyllys 	if (cacerts)
3595*99ebb4caSwyllys 		sk_X509_free(cacerts);
3596*99ebb4caSwyllys 
3597*99ebb4caSwyllys 	return (rv);
3598*99ebb4caSwyllys }
3599*99ebb4caSwyllys 
3600*99ebb4caSwyllys KMF_RETURN
3601*99ebb4caSwyllys OpenSSL_StorePrivateKey(KMF_HANDLE_T handle, KMF_STOREKEY_PARAMS *params,
3602*99ebb4caSwyllys 	KMF_RAW_KEY_DATA *key)
3603*99ebb4caSwyllys {
3604*99ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
3605*99ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
3606*99ebb4caSwyllys 	char		*fullpath;
3607*99ebb4caSwyllys 	EVP_PKEY	*pkey = NULL;
3608*99ebb4caSwyllys 	BIO		*bio = NULL;
3609*99ebb4caSwyllys 
3610*99ebb4caSwyllys 	if (key != NULL) {
3611*99ebb4caSwyllys 		if (key->keytype == KMF_RSA) {
3612*99ebb4caSwyllys 			pkey = ImportRawRSAKey(&key->rawdata.rsa);
3613*99ebb4caSwyllys 		} else if (key->keytype == KMF_DSA) {
3614*99ebb4caSwyllys 			pkey = ImportRawDSAKey(&key->rawdata.dsa);
3615*99ebb4caSwyllys 		} else {
3616*99ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
3617*99ebb4caSwyllys 		}
3618*99ebb4caSwyllys 	} else {
3619*99ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
3620*99ebb4caSwyllys 	}
3621*99ebb4caSwyllys 	if (rv != KMF_OK || pkey == NULL)
3622*99ebb4caSwyllys 		return (rv);
3623*99ebb4caSwyllys 
3624*99ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
3625*99ebb4caSwyllys 			params->sslparms.keyfile);
3626*99ebb4caSwyllys 
3627*99ebb4caSwyllys 	if (fullpath == NULL)
3628*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
3629*99ebb4caSwyllys 
3630*99ebb4caSwyllys 	/* If the requested file exists, return an error */
3631*99ebb4caSwyllys 	if (access(fullpath, F_OK) == 0) {
3632*99ebb4caSwyllys 		free(fullpath);
3633*99ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
3634*99ebb4caSwyllys 	}
3635*99ebb4caSwyllys 
3636*99ebb4caSwyllys 	bio = BIO_new_file(fullpath, "wb");
3637*99ebb4caSwyllys 	if (bio == NULL) {
3638*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
3639*99ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
3640*99ebb4caSwyllys 		goto cleanup;
3641*99ebb4caSwyllys 	}
3642*99ebb4caSwyllys 
3643*99ebb4caSwyllys 	rv = ssl_write_private_key(kmfh,
3644*99ebb4caSwyllys 		params->sslparms.format,
3645*99ebb4caSwyllys 		bio, &params->cred, pkey);
3646*99ebb4caSwyllys 
3647*99ebb4caSwyllys cleanup:
3648*99ebb4caSwyllys 	if (fullpath)
3649*99ebb4caSwyllys 		free(fullpath);
3650*99ebb4caSwyllys 
3651*99ebb4caSwyllys 	if (pkey)
3652*99ebb4caSwyllys 		EVP_PKEY_free(pkey);
3653*99ebb4caSwyllys 
3654*99ebb4caSwyllys 	if (bio)
3655*99ebb4caSwyllys 		(void) BIO_free(bio);
3656*99ebb4caSwyllys 
3657*99ebb4caSwyllys 	/* Protect the file by making it read-only */
3658*99ebb4caSwyllys 	if (rv == KMF_OK) {
3659*99ebb4caSwyllys 		(void) chmod(fullpath, 0400);
3660*99ebb4caSwyllys 	}
3661*99ebb4caSwyllys 	return (rv);
3662*99ebb4caSwyllys }
3663*99ebb4caSwyllys 
3664*99ebb4caSwyllys static KMF_RETURN
3665*99ebb4caSwyllys create_deskey(DES_cblock **deskey)
3666*99ebb4caSwyllys {
3667*99ebb4caSwyllys 	DES_cblock *key;
3668*99ebb4caSwyllys 
3669*99ebb4caSwyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
3670*99ebb4caSwyllys 	if (key == NULL) {
3671*99ebb4caSwyllys 		return (KMF_ERR_MEMORY);
3672*99ebb4caSwyllys 	}
3673*99ebb4caSwyllys 
3674*99ebb4caSwyllys 	if (DES_random_key(key) == 0) {
3675*99ebb4caSwyllys 		free(key);
3676*99ebb4caSwyllys 		return (KMF_ERR_KEYGEN_FAILED);
3677*99ebb4caSwyllys 	}
3678*99ebb4caSwyllys 
3679*99ebb4caSwyllys 	*deskey = key;
3680*99ebb4caSwyllys 	return (KMF_OK);
3681*99ebb4caSwyllys }
3682*99ebb4caSwyllys 
3683*99ebb4caSwyllys #define	KEYGEN_RETRY 3
3684*99ebb4caSwyllys #define	DES3_KEY_SIZE 24
3685*99ebb4caSwyllys 
3686*99ebb4caSwyllys static KMF_RETURN
3687*99ebb4caSwyllys create_des3key(unsigned char **des3key)
3688*99ebb4caSwyllys {
3689*99ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
3690*99ebb4caSwyllys 	DES_cblock *deskey1 = NULL;
3691*99ebb4caSwyllys 	DES_cblock *deskey2 = NULL;
3692*99ebb4caSwyllys 	DES_cblock *deskey3 = NULL;
3693*99ebb4caSwyllys 	unsigned char *newkey = NULL;
3694*99ebb4caSwyllys 	int retry;
3695*99ebb4caSwyllys 
3696*99ebb4caSwyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
3697*99ebb4caSwyllys 		return (KMF_ERR_MEMORY);
3698*99ebb4caSwyllys 	}
3699*99ebb4caSwyllys 
3700*99ebb4caSwyllys 	/* create the 1st DES key */
3701*99ebb4caSwyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
3702*99ebb4caSwyllys 		goto out;
3703*99ebb4caSwyllys 	}
3704*99ebb4caSwyllys 
3705*99ebb4caSwyllys 	/*
3706*99ebb4caSwyllys 	 * Create the 2nd DES key and make sure its value is different
3707*99ebb4caSwyllys 	 * from the 1st DES key.
3708*99ebb4caSwyllys 	 */
3709*99ebb4caSwyllys 	retry = 0;
3710*99ebb4caSwyllys 	do {
3711*99ebb4caSwyllys 		if (deskey2 != NULL) {
3712*99ebb4caSwyllys 			free(deskey2);
3713*99ebb4caSwyllys 			deskey2 = NULL;
3714*99ebb4caSwyllys 		}
3715*99ebb4caSwyllys 
3716*99ebb4caSwyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
3717*99ebb4caSwyllys 			goto out;
3718*99ebb4caSwyllys 		}
3719*99ebb4caSwyllys 
3720*99ebb4caSwyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
3721*99ebb4caSwyllys 		    == 0) {
3722*99ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
3723*99ebb4caSwyllys 			retry++;
3724*99ebb4caSwyllys 		}
3725*99ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
3726*99ebb4caSwyllys 
3727*99ebb4caSwyllys 	if (ret != KMF_OK) {
3728*99ebb4caSwyllys 		goto out;
3729*99ebb4caSwyllys 	}
3730*99ebb4caSwyllys 
3731*99ebb4caSwyllys 	/*
3732*99ebb4caSwyllys 	 * Create the 3rd DES key and make sure its value is different
3733*99ebb4caSwyllys 	 * from the 2nd DES key.
3734*99ebb4caSwyllys 	 */
3735*99ebb4caSwyllys 	retry = 0;
3736*99ebb4caSwyllys 	do {
3737*99ebb4caSwyllys 		if (deskey3 != NULL) {
3738*99ebb4caSwyllys 			free(deskey3);
3739*99ebb4caSwyllys 			deskey3 = NULL;
3740*99ebb4caSwyllys 		}
3741*99ebb4caSwyllys 
3742*99ebb4caSwyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
3743*99ebb4caSwyllys 			goto out;
3744*99ebb4caSwyllys 		}
3745*99ebb4caSwyllys 
3746*99ebb4caSwyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
3747*99ebb4caSwyllys 		    == 0) {
3748*99ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
3749*99ebb4caSwyllys 			retry++;
3750*99ebb4caSwyllys 		}
3751*99ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
3752*99ebb4caSwyllys 
3753*99ebb4caSwyllys 	if (ret != KMF_OK) {
3754*99ebb4caSwyllys 		goto out;
3755*99ebb4caSwyllys 	}
3756*99ebb4caSwyllys 
3757*99ebb4caSwyllys 	/* Concatenate 3 DES keys into a DES3 key */
3758*99ebb4caSwyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
3759*99ebb4caSwyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
3760*99ebb4caSwyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
3761*99ebb4caSwyllys 	*des3key = newkey;
3762*99ebb4caSwyllys 
3763*99ebb4caSwyllys out:
3764*99ebb4caSwyllys 	if (deskey1 != NULL)
3765*99ebb4caSwyllys 		free(deskey1);
3766*99ebb4caSwyllys 
3767*99ebb4caSwyllys 	if (deskey2 != NULL)
3768*99ebb4caSwyllys 		free(deskey2);
3769*99ebb4caSwyllys 
3770*99ebb4caSwyllys 	if (deskey3 != NULL)
3771*99ebb4caSwyllys 		free(deskey3);
3772*99ebb4caSwyllys 
3773*99ebb4caSwyllys 	if (ret != KMF_OK && newkey != NULL)
3774*99ebb4caSwyllys 		free(newkey);
3775*99ebb4caSwyllys 
3776*99ebb4caSwyllys 	return (ret);
3777*99ebb4caSwyllys }
3778*99ebb4caSwyllys 
3779*99ebb4caSwyllys KMF_RETURN
3780*99ebb4caSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle, KMF_CREATESYMKEY_PARAMS *params,
3781*99ebb4caSwyllys 	KMF_KEY_HANDLE *symkey)
3782*99ebb4caSwyllys {
3783*99ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
3784*99ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3785*99ebb4caSwyllys 	char *fullpath = NULL;
3786*99ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
3787*99ebb4caSwyllys 	DES_cblock *deskey = NULL;
3788*99ebb4caSwyllys 	unsigned char *des3key = NULL;
3789*99ebb4caSwyllys 	unsigned char *random = NULL;
3790*99ebb4caSwyllys 	int fd = -1;
3791*99ebb4caSwyllys 
3792*99ebb4caSwyllys 	if (kmfh == NULL)
3793*99ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
3794*99ebb4caSwyllys 
3795*99ebb4caSwyllys 	if (params == NULL || params->sslparms.keyfile == NULL) {
3796*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
3797*99ebb4caSwyllys 	}
3798*99ebb4caSwyllys 
3799*99ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
3800*99ebb4caSwyllys 		params->sslparms.keyfile);
3801*99ebb4caSwyllys 	if (fullpath == NULL)
3802*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
3803*99ebb4caSwyllys 
3804*99ebb4caSwyllys 	/* If the requested file exists, return an error */
3805*99ebb4caSwyllys 	if (access(fullpath, F_OK) == 0) {
3806*99ebb4caSwyllys 		free(fullpath);
3807*99ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
3808*99ebb4caSwyllys 	}
3809*99ebb4caSwyllys 
3810*99ebb4caSwyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
3811*99ebb4caSwyllys 	if (fd == -1) {
3812*99ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
3813*99ebb4caSwyllys 		goto out;
3814*99ebb4caSwyllys 	}
3815*99ebb4caSwyllys 
3816*99ebb4caSwyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
3817*99ebb4caSwyllys 	if (rkey == NULL) {
3818*99ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
3819*99ebb4caSwyllys 		goto out;
3820*99ebb4caSwyllys 	}
3821*99ebb4caSwyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
3822*99ebb4caSwyllys 
3823*99ebb4caSwyllys 	if (params->keytype == KMF_DES) {
3824*99ebb4caSwyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
3825*99ebb4caSwyllys 			goto out;
3826*99ebb4caSwyllys 		}
3827*99ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)deskey;
3828*99ebb4caSwyllys 		rkey->keydata.len = 8;
3829*99ebb4caSwyllys 
3830*99ebb4caSwyllys 		symkey->keyalg = KMF_DES;
3831*99ebb4caSwyllys 
3832*99ebb4caSwyllys 	} else if (params->keytype == KMF_DES3) {
3833*99ebb4caSwyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
3834*99ebb4caSwyllys 			goto out;
3835*99ebb4caSwyllys 		}
3836*99ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)des3key;
3837*99ebb4caSwyllys 		rkey->keydata.len = DES3_KEY_SIZE;
3838*99ebb4caSwyllys 		symkey->keyalg = KMF_DES3;
3839*99ebb4caSwyllys 
3840*99ebb4caSwyllys 	} else if (params->keytype == KMF_AES || params->keytype == KMF_RC4) {
3841*99ebb4caSwyllys 		int bytes;
3842*99ebb4caSwyllys 
3843*99ebb4caSwyllys 		if (params->keylength % 8 != 0) {
3844*99ebb4caSwyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
3845*99ebb4caSwyllys 			goto out;
3846*99ebb4caSwyllys 		}
3847*99ebb4caSwyllys 
3848*99ebb4caSwyllys 		if (params->keytype == KMF_AES) {
3849*99ebb4caSwyllys 			if (params->keylength != 128 &&
3850*99ebb4caSwyllys 			    params->keylength != 192 &&
3851*99ebb4caSwyllys 			    params->keylength != 256) {
3852*99ebb4caSwyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
3853*99ebb4caSwyllys 				goto out;
3854*99ebb4caSwyllys 			}
3855*99ebb4caSwyllys 		}
3856*99ebb4caSwyllys 
3857*99ebb4caSwyllys 		bytes = params->keylength/8;
3858*99ebb4caSwyllys 		random = malloc(bytes);
3859*99ebb4caSwyllys 		if (random == NULL) {
3860*99ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
3861*99ebb4caSwyllys 			goto out;
3862*99ebb4caSwyllys 		}
3863*99ebb4caSwyllys 		if (RAND_bytes(random, bytes) != 1) {
3864*99ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
3865*99ebb4caSwyllys 			goto out;
3866*99ebb4caSwyllys 		}
3867*99ebb4caSwyllys 
3868*99ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)random;
3869*99ebb4caSwyllys 		rkey->keydata.len = bytes;
3870*99ebb4caSwyllys 		symkey->keyalg = params->keytype;
3871*99ebb4caSwyllys 
3872*99ebb4caSwyllys 	} else {
3873*99ebb4caSwyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
3874*99ebb4caSwyllys 		goto out;
3875*99ebb4caSwyllys 	}
3876*99ebb4caSwyllys 
3877*99ebb4caSwyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
3878*99ebb4caSwyllys 
3879*99ebb4caSwyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
3880*99ebb4caSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
3881*99ebb4caSwyllys 	symkey->keylabel = (char *)fullpath;
3882*99ebb4caSwyllys 	symkey->israw = TRUE;
3883*99ebb4caSwyllys 	symkey->keyp = rkey;
3884*99ebb4caSwyllys 
3885*99ebb4caSwyllys out:
3886*99ebb4caSwyllys 	if (fd != -1)
3887*99ebb4caSwyllys 		(void) close(fd);
3888*99ebb4caSwyllys 
3889*99ebb4caSwyllys 	if (ret != KMF_OK && fullpath != NULL) {
3890*99ebb4caSwyllys 		free(fullpath);
3891*99ebb4caSwyllys 	}
3892*99ebb4caSwyllys 	if (ret != KMF_OK) {
3893*99ebb4caSwyllys 		KMF_FreeRawSymKey(rkey);
3894*99ebb4caSwyllys 		symkey->keyp = NULL;
3895*99ebb4caSwyllys 		symkey->keyalg = KMF_KEYALG_NONE;
3896*99ebb4caSwyllys 	}
3897*99ebb4caSwyllys 
3898*99ebb4caSwyllys 	return (ret);
3899*99ebb4caSwyllys }
3900*99ebb4caSwyllys 
3901*99ebb4caSwyllys 
3902*99ebb4caSwyllys KMF_RETURN
3903*99ebb4caSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, KMF_VERIFYCRL_PARAMS *params)
3904*99ebb4caSwyllys {
3905*99ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
3906*99ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
3907*99ebb4caSwyllys 	BIO		*bcrl = NULL;
3908*99ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
3909*99ebb4caSwyllys 	X509		*xcert = NULL;
3910*99ebb4caSwyllys 	EVP_PKEY	*pkey;
3911*99ebb4caSwyllys 	int		sslret;
3912*99ebb4caSwyllys 	KMF_ENCODE_FORMAT crl_format;
3913*99ebb4caSwyllys 	unsigned char	*p;
3914*99ebb4caSwyllys 	long		len;
3915*99ebb4caSwyllys 
3916*99ebb4caSwyllys 	if (params->crl_name == NULL || params->tacert == NULL) {
3917*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
3918*99ebb4caSwyllys 	}
3919*99ebb4caSwyllys 
3920*99ebb4caSwyllys 	ret = KMF_GetFileFormat(params->crl_name, &crl_format);
3921*99ebb4caSwyllys 	if (ret != KMF_OK)
3922*99ebb4caSwyllys 		return (ret);
3923*99ebb4caSwyllys 
3924*99ebb4caSwyllys 	bcrl = BIO_new_file(params->crl_name, "rb");
3925*99ebb4caSwyllys 	if (bcrl == NULL)	{
3926*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
3927*99ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
3928*99ebb4caSwyllys 		goto cleanup;
3929*99ebb4caSwyllys 	}
3930*99ebb4caSwyllys 
3931*99ebb4caSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
3932*99ebb4caSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
3933*99ebb4caSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
3934*99ebb4caSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
3935*99ebb4caSwyllys 	} else {
3936*99ebb4caSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
3937*99ebb4caSwyllys 		goto cleanup;
3938*99ebb4caSwyllys 	}
3939*99ebb4caSwyllys 
3940*99ebb4caSwyllys 	if (xcrl == NULL) {
3941*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
3942*99ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
3943*99ebb4caSwyllys 		goto cleanup;
3944*99ebb4caSwyllys 	}
3945*99ebb4caSwyllys 
3946*99ebb4caSwyllys 	p = params->tacert->Data;
3947*99ebb4caSwyllys 	len = params->tacert->Length;
3948*99ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
3949*99ebb4caSwyllys 
3950*99ebb4caSwyllys 	if (xcert == NULL) {
3951*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
3952*99ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
3953*99ebb4caSwyllys 		goto cleanup;
3954*99ebb4caSwyllys 	}
3955*99ebb4caSwyllys 
3956*99ebb4caSwyllys 	/* Get issuer certificate public key */
3957*99ebb4caSwyllys 	pkey = X509_get_pubkey(xcert);
3958*99ebb4caSwyllys 	if (!pkey) {
3959*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
3960*99ebb4caSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
3961*99ebb4caSwyllys 		goto cleanup;
3962*99ebb4caSwyllys 	}
3963*99ebb4caSwyllys 
3964*99ebb4caSwyllys 	/* Verify CRL signature */
3965*99ebb4caSwyllys 	sslret = X509_CRL_verify(xcrl, pkey);
3966*99ebb4caSwyllys 	EVP_PKEY_free(pkey);
3967*99ebb4caSwyllys 	if (sslret > 0) {
3968*99ebb4caSwyllys 		ret = KMF_OK;
3969*99ebb4caSwyllys 	} else {
3970*99ebb4caSwyllys 		SET_ERROR(kmfh, sslret);
3971*99ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
3972*99ebb4caSwyllys 	}
3973*99ebb4caSwyllys 
3974*99ebb4caSwyllys cleanup:
3975*99ebb4caSwyllys 	if (bcrl != NULL)
3976*99ebb4caSwyllys 		(void) BIO_free(bcrl);
3977*99ebb4caSwyllys 
3978*99ebb4caSwyllys 	if (xcrl != NULL)
3979*99ebb4caSwyllys 		X509_CRL_free(xcrl);
3980*99ebb4caSwyllys 
3981*99ebb4caSwyllys 	if (xcert != NULL)
3982*99ebb4caSwyllys 		X509_free(xcert);
3983*99ebb4caSwyllys 
3984*99ebb4caSwyllys 	return (ret);
3985*99ebb4caSwyllys 
3986*99ebb4caSwyllys }
3987*99ebb4caSwyllys 
3988*99ebb4caSwyllys KMF_RETURN
3989*99ebb4caSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle,
3990*99ebb4caSwyllys 	KMF_CHECKCRLDATE_PARAMS *params)
3991*99ebb4caSwyllys {
3992*99ebb4caSwyllys 
3993*99ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
3994*99ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
3995*99ebb4caSwyllys 	KMF_ENCODE_FORMAT crl_format;
3996*99ebb4caSwyllys 	BIO		*bcrl = NULL;
3997*99ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
3998*99ebb4caSwyllys 	int		i;
3999*99ebb4caSwyllys 
4000*99ebb4caSwyllys 	if (params == NULL || params->crl_name == NULL) {
4001*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
4002*99ebb4caSwyllys 	}
4003*99ebb4caSwyllys 
4004*99ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, params->crl_name, &crl_format);
4005*99ebb4caSwyllys 	if (ret != KMF_OK)
4006*99ebb4caSwyllys 		return (ret);
4007*99ebb4caSwyllys 
4008*99ebb4caSwyllys 	bcrl = BIO_new_file(params->crl_name, "rb");
4009*99ebb4caSwyllys 	if (bcrl == NULL)	{
4010*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
4011*99ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
4012*99ebb4caSwyllys 		goto cleanup;
4013*99ebb4caSwyllys 	}
4014*99ebb4caSwyllys 
4015*99ebb4caSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
4016*99ebb4caSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
4017*99ebb4caSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
4018*99ebb4caSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
4019*99ebb4caSwyllys 	}
4020*99ebb4caSwyllys 
4021*99ebb4caSwyllys 	if (xcrl == NULL) {
4022*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
4023*99ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
4024*99ebb4caSwyllys 		goto cleanup;
4025*99ebb4caSwyllys 	}
4026*99ebb4caSwyllys 
4027*99ebb4caSwyllys 	i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL);
4028*99ebb4caSwyllys 	if (i >= 0) {
4029*99ebb4caSwyllys 		ret = KMF_ERR_VALIDITY_PERIOD;
4030*99ebb4caSwyllys 		goto cleanup;
4031*99ebb4caSwyllys 	}
4032*99ebb4caSwyllys 
4033*99ebb4caSwyllys 	if (X509_CRL_get_nextUpdate(xcrl)) {
4034*99ebb4caSwyllys 		i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL);
4035*99ebb4caSwyllys 
4036*99ebb4caSwyllys 		if (i <= 0) {
4037*99ebb4caSwyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
4038*99ebb4caSwyllys 			goto cleanup;
4039*99ebb4caSwyllys 		}
4040*99ebb4caSwyllys 	}
4041*99ebb4caSwyllys 
4042*99ebb4caSwyllys 	ret = KMF_OK;
4043*99ebb4caSwyllys 
4044*99ebb4caSwyllys cleanup:
4045*99ebb4caSwyllys 	if (bcrl != NULL)
4046*99ebb4caSwyllys 		(void) BIO_free(bcrl);
4047*99ebb4caSwyllys 
4048*99ebb4caSwyllys 	if (xcrl != NULL)
4049*99ebb4caSwyllys 		X509_CRL_free(xcrl);
4050*99ebb4caSwyllys 
4051*99ebb4caSwyllys 	return (ret);
4052*99ebb4caSwyllys }
4053*99ebb4caSwyllys 
4054*99ebb4caSwyllys /*
4055*99ebb4caSwyllys  * Check a file to see if it is a CRL file with PEM or DER format.
4056*99ebb4caSwyllys  * If success, return its format in the "pformat" argument.
4057*99ebb4caSwyllys  */
4058*99ebb4caSwyllys KMF_RETURN
4059*99ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
4060*99ebb4caSwyllys {
4061*99ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
4062*99ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
4063*99ebb4caSwyllys 	BIO		*bio = NULL;
4064*99ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
4065*99ebb4caSwyllys 
4066*99ebb4caSwyllys 	if (filename == NULL) {
4067*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
4068*99ebb4caSwyllys 	}
4069*99ebb4caSwyllys 
4070*99ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
4071*99ebb4caSwyllys 	if (bio == NULL)	{
4072*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
4073*99ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
4074*99ebb4caSwyllys 		goto out;
4075*99ebb4caSwyllys 	}
4076*99ebb4caSwyllys 
4077*99ebb4caSwyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
4078*99ebb4caSwyllys 		*pformat = KMF_FORMAT_PEM;
4079*99ebb4caSwyllys 		goto out;
4080*99ebb4caSwyllys 	}
4081*99ebb4caSwyllys 	(void) BIO_free(bio);
4082*99ebb4caSwyllys 
4083*99ebb4caSwyllys 	/*
4084*99ebb4caSwyllys 	 * Now try to read it as raw DER data.
4085*99ebb4caSwyllys 	 */
4086*99ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
4087*99ebb4caSwyllys 	if (bio == NULL)	{
4088*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
4089*99ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
4090*99ebb4caSwyllys 		goto out;
4091*99ebb4caSwyllys 	}
4092*99ebb4caSwyllys 
4093*99ebb4caSwyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
4094*99ebb4caSwyllys 		*pformat = KMF_FORMAT_ASN1;
4095*99ebb4caSwyllys 	} else {
4096*99ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
4097*99ebb4caSwyllys 	}
4098*99ebb4caSwyllys 
4099*99ebb4caSwyllys out:
4100*99ebb4caSwyllys 	if (bio != NULL)
4101*99ebb4caSwyllys 		(void) BIO_free(bio);
4102*99ebb4caSwyllys 
4103*99ebb4caSwyllys 	if (xcrl != NULL)
4104*99ebb4caSwyllys 		X509_CRL_free(xcrl);
4105*99ebb4caSwyllys 
4106*99ebb4caSwyllys 	return (ret);
4107*99ebb4caSwyllys }
4108*99ebb4caSwyllys 
4109*99ebb4caSwyllys /*
4110*99ebb4caSwyllys  * Check a file to see if it is a certficate file with PEM or DER format.
4111*99ebb4caSwyllys  * If success, return its format in the pformat argument.
4112*99ebb4caSwyllys  */
4113*99ebb4caSwyllys KMF_RETURN
4114*99ebb4caSwyllys OpenSSL_IsCertFile(KMF_HANDLE_T handle, char *filename,
4115*99ebb4caSwyllys 	KMF_ENCODE_FORMAT *pformat)
4116*99ebb4caSwyllys {
4117*99ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
4118*99ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
4119*99ebb4caSwyllys 	BIO		*bio = NULL;
4120*99ebb4caSwyllys 	X509		*xcert = NULL;
4121*99ebb4caSwyllys 
4122*99ebb4caSwyllys 	if (filename == NULL) {
4123*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
4124*99ebb4caSwyllys 	}
4125*99ebb4caSwyllys 
4126*99ebb4caSwyllys 	ret = KMF_GetFileFormat(filename, pformat);
4127*99ebb4caSwyllys 	if (ret != KMF_OK)
4128*99ebb4caSwyllys 		return (ret);
4129*99ebb4caSwyllys 
4130*99ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
4131*99ebb4caSwyllys 	if (bio == NULL)	{
4132*99ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
4133*99ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
4134*99ebb4caSwyllys 		goto out;
4135*99ebb4caSwyllys 	}
4136*99ebb4caSwyllys 
4137*99ebb4caSwyllys 	if ((*pformat) == KMF_FORMAT_PEM) {
4138*99ebb4caSwyllys 		if ((xcert = PEM_read_bio_X509(bio, NULL,
4139*99ebb4caSwyllys 			NULL, NULL)) == NULL) {
4140*99ebb4caSwyllys 			ret = KMF_ERR_BAD_CERTFILE;
4141*99ebb4caSwyllys 		}
4142*99ebb4caSwyllys 	} else if ((*pformat) == KMF_FORMAT_ASN1) {
4143*99ebb4caSwyllys 		if ((xcert = d2i_X509_bio(bio, NULL)) == NULL) {
4144*99ebb4caSwyllys 			ret = KMF_ERR_BAD_CERTFILE;
4145*99ebb4caSwyllys 		}
4146*99ebb4caSwyllys 	} else {
4147*99ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
4148*99ebb4caSwyllys 	}
4149*99ebb4caSwyllys 
4150*99ebb4caSwyllys out:
4151*99ebb4caSwyllys 	if (bio != NULL)
4152*99ebb4caSwyllys 		(void) BIO_free(bio);
4153*99ebb4caSwyllys 
4154*99ebb4caSwyllys 	if (xcert != NULL)
4155*99ebb4caSwyllys 		X509_free(xcert);
4156*99ebb4caSwyllys 
4157*99ebb4caSwyllys 	return (ret);
4158*99ebb4caSwyllys }
4159*99ebb4caSwyllys 
4160*99ebb4caSwyllys KMF_RETURN
4161*99ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
4162*99ebb4caSwyllys     KMF_RAW_SYM_KEY *rkey)
4163*99ebb4caSwyllys {
4164*99ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
4165*99ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
4166*99ebb4caSwyllys 	KMF_DATA	keyvalue;
4167*99ebb4caSwyllys 
4168*99ebb4caSwyllys 	if (kmfh == NULL)
4169*99ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
4170*99ebb4caSwyllys 
4171*99ebb4caSwyllys 	if (symkey == NULL || rkey == NULL)
4172*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
4173*99ebb4caSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
4174*99ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
4175*99ebb4caSwyllys 
4176*99ebb4caSwyllys 	if (symkey->israw) {
4177*99ebb4caSwyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
4178*99ebb4caSwyllys 
4179*99ebb4caSwyllys 		if (rawkey == NULL ||
4180*99ebb4caSwyllys 		    rawkey->keydata.val == NULL ||
4181*99ebb4caSwyllys 		    rawkey->keydata.len == 0)
4182*99ebb4caSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
4183*99ebb4caSwyllys 
4184*99ebb4caSwyllys 		rkey->keydata.len = rawkey->keydata.len;
4185*99ebb4caSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
4186*99ebb4caSwyllys 			return (KMF_ERR_MEMORY);
4187*99ebb4caSwyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
4188*99ebb4caSwyllys 		    rkey->keydata.len);
4189*99ebb4caSwyllys 	} else {
4190*99ebb4caSwyllys 		rv = KMF_ReadInputFile(handle, symkey->keylabel, &keyvalue);
4191*99ebb4caSwyllys 		if (rv != KMF_OK)
4192*99ebb4caSwyllys 			return (rv);
4193*99ebb4caSwyllys 		rkey->keydata.len = keyvalue.Length;
4194*99ebb4caSwyllys 		rkey->keydata.val = keyvalue.Data;
4195*99ebb4caSwyllys 	}
4196*99ebb4caSwyllys 
4197*99ebb4caSwyllys 	return (rv);
4198*99ebb4caSwyllys }
4199