199ebb4caSwyllys /*
271593db2Swyllys  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
399ebb4caSwyllys  * Use is subject to license terms.
499ebb4caSwyllys  */
5*9a767088Shaimay /*
6*9a767088Shaimay  * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
7*9a767088Shaimay  * project 2000.
8*9a767088Shaimay  */
9*9a767088Shaimay /*
10*9a767088Shaimay  * ====================================================================
11*9a767088Shaimay  * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
12*9a767088Shaimay  *
13*9a767088Shaimay  * Redistribution and use in source and binary forms, with or without
14*9a767088Shaimay  * modification, are permitted provided that the following conditions
15*9a767088Shaimay  * are met:
16*9a767088Shaimay  *
17*9a767088Shaimay  * 1. Redistributions of source code must retain the above copyright
18*9a767088Shaimay  *    notice, this list of conditions and the following disclaimer.
19*9a767088Shaimay  *
20*9a767088Shaimay  * 2. Redistributions in binary form must reproduce the above copyright
21*9a767088Shaimay  *    notice, this list of conditions and the following disclaimer in
22*9a767088Shaimay  *    the documentation and/or other materials provided with the
23*9a767088Shaimay  *    distribution.
24*9a767088Shaimay  *
25*9a767088Shaimay  * 3. All advertising materials mentioning features or use of this
26*9a767088Shaimay  *    software must display the following acknowledgment:
27*9a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
28*9a767088Shaimay  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
29*9a767088Shaimay  *
30*9a767088Shaimay  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
31*9a767088Shaimay  *    endorse or promote products derived from this software without
32*9a767088Shaimay  *    prior written permission. For written permission, please contact
33*9a767088Shaimay  *    licensing@OpenSSL.org.
34*9a767088Shaimay  *
35*9a767088Shaimay  * 5. Products derived from this software may not be called "OpenSSL"
36*9a767088Shaimay  *    nor may "OpenSSL" appear in their names without prior written
37*9a767088Shaimay  *    permission of the OpenSSL Project.
38*9a767088Shaimay  *
39*9a767088Shaimay  * 6. Redistributions of any form whatsoever must retain the following
40*9a767088Shaimay  *    acknowledgment:
41*9a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
42*9a767088Shaimay  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
43*9a767088Shaimay  *
44*9a767088Shaimay  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
45*9a767088Shaimay  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46*9a767088Shaimay  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
47*9a767088Shaimay  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
48*9a767088Shaimay  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
49*9a767088Shaimay  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50*9a767088Shaimay  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
51*9a767088Shaimay  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52*9a767088Shaimay  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
53*9a767088Shaimay  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54*9a767088Shaimay  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
55*9a767088Shaimay  * OF THE POSSIBILITY OF SUCH DAMAGE.
56*9a767088Shaimay  * ====================================================================
57*9a767088Shaimay  *
58*9a767088Shaimay  * This product includes cryptographic software written by Eric Young
59*9a767088Shaimay  * (eay@cryptsoft.com).  This product includes software written by Tim
60*9a767088Shaimay  * Hudson (tjh@cryptsoft.com).
61*9a767088Shaimay  *
62*9a767088Shaimay  */
6399ebb4caSwyllys 
6499ebb4caSwyllys #pragma ident	"%Z%%M%	%I%	%E% SMI"
6599ebb4caSwyllys 
6671593db2Swyllys #include <stdlib.h>
6799ebb4caSwyllys #include <kmfapiP.h>
6899ebb4caSwyllys #include <ber_der.h>
6999ebb4caSwyllys #include <oidsalg.h>
7099ebb4caSwyllys #include <fcntl.h>
7199ebb4caSwyllys #include <sys/stat.h>
7299ebb4caSwyllys #include <dirent.h>
7399ebb4caSwyllys #include <cryptoutil.h>
7499ebb4caSwyllys #include <synch.h>
7599ebb4caSwyllys #include <thread.h>
7699ebb4caSwyllys 
7799ebb4caSwyllys /* OPENSSL related headers */
7899ebb4caSwyllys #include <openssl/bio.h>
7999ebb4caSwyllys #include <openssl/bn.h>
8099ebb4caSwyllys #include <openssl/asn1.h>
8199ebb4caSwyllys #include <openssl/err.h>
8299ebb4caSwyllys #include <openssl/bn.h>
8399ebb4caSwyllys #include <openssl/x509.h>
8499ebb4caSwyllys #include <openssl/rsa.h>
8599ebb4caSwyllys #include <openssl/dsa.h>
8699ebb4caSwyllys #include <openssl/x509v3.h>
8799ebb4caSwyllys #include <openssl/objects.h>
8899ebb4caSwyllys #include <openssl/pem.h>
8999ebb4caSwyllys #include <openssl/pkcs12.h>
9099ebb4caSwyllys #include <openssl/ocsp.h>
9199ebb4caSwyllys #include <openssl/des.h>
9299ebb4caSwyllys #include <openssl/rand.h>
9399ebb4caSwyllys 
9499ebb4caSwyllys #define	PRINT_ANY_EXTENSION (\
9599ebb4caSwyllys 	KMF_X509_EXT_KEY_USAGE |\
9699ebb4caSwyllys 	KMF_X509_EXT_CERT_POLICIES |\
9799ebb4caSwyllys 	KMF_X509_EXT_SUBJALTNAME |\
9899ebb4caSwyllys 	KMF_X509_EXT_BASIC_CONSTRAINTS |\
9999ebb4caSwyllys 	KMF_X509_EXT_NAME_CONSTRAINTS |\
10099ebb4caSwyllys 	KMF_X509_EXT_POLICY_CONSTRAINTS |\
10199ebb4caSwyllys 	KMF_X509_EXT_EXT_KEY_USAGE |\
10299ebb4caSwyllys 	KMF_X509_EXT_INHIBIT_ANY_POLICY |\
10399ebb4caSwyllys 	KMF_X509_EXT_AUTH_KEY_ID |\
10499ebb4caSwyllys 	KMF_X509_EXT_SUBJ_KEY_ID |\
10599ebb4caSwyllys 	KMF_X509_EXT_POLICY_MAPPING)
10699ebb4caSwyllys 
10799ebb4caSwyllys static BIO *bio_err = NULL;
10899ebb4caSwyllys static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
10999ebb4caSwyllys 	0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
11099ebb4caSwyllys 	0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
11199ebb4caSwyllys 	0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
11299ebb4caSwyllys 	0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
11399ebb4caSwyllys 	0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
11499ebb4caSwyllys 	0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
11599ebb4caSwyllys 	0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
11699ebb4caSwyllys 	0x91 };
11799ebb4caSwyllys 
11899ebb4caSwyllys static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
11999ebb4caSwyllys 	0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
12099ebb4caSwyllys 	0x8e, 0xda, 0xce, 0x91, 0x5f };
12199ebb4caSwyllys 
12299ebb4caSwyllys static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
12399ebb4caSwyllys 	0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
12499ebb4caSwyllys 	0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
12599ebb4caSwyllys 	0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
12699ebb4caSwyllys 	0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
12799ebb4caSwyllys 	0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
12899ebb4caSwyllys 	0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
12999ebb4caSwyllys 	0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
13099ebb4caSwyllys 	0x02 };
13199ebb4caSwyllys 
13299ebb4caSwyllys #define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
13399ebb4caSwyllys 	h->lasterr.errcode = c;
13499ebb4caSwyllys 
13599ebb4caSwyllys #define	SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
13699ebb4caSwyllys 
13799ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX;
13899ebb4caSwyllys static int ssl_initialized = 0;
13999ebb4caSwyllys 
14071593db2Swyllys static KMF_RETURN
14171593db2Swyllys extract_objects(KMF_HANDLE *, char *, CK_UTF8CHAR *, CK_ULONG,
14271593db2Swyllys 	EVP_PKEY **, KMF_DATA **, int *);
14371593db2Swyllys 
14471593db2Swyllys static KMF_RETURN
14571593db2Swyllys kmf_load_cert(KMF_HANDLE *, KMF_FINDCERT_PARAMS *, char *, KMF_DATA *);
14671593db2Swyllys 
14799ebb4caSwyllys KMF_RETURN
14899ebb4caSwyllys OpenSSL_FindCert(KMF_HANDLE_T,
14999ebb4caSwyllys 	KMF_FINDCERT_PARAMS *,
15099ebb4caSwyllys 	KMF_X509_DER_CERT *,
15199ebb4caSwyllys 	uint32_t *);
15299ebb4caSwyllys 
15399ebb4caSwyllys void
15499ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
15599ebb4caSwyllys 
15699ebb4caSwyllys KMF_RETURN
15799ebb4caSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, KMF_STORECERT_PARAMS *, KMF_DATA *);
15899ebb4caSwyllys 
15999ebb4caSwyllys KMF_RETURN
16099ebb4caSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, KMF_DELETECERT_PARAMS *);
16199ebb4caSwyllys 
16299ebb4caSwyllys KMF_RETURN
16399ebb4caSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T, KMF_CREATEKEYPAIR_PARAMS *,
16499ebb4caSwyllys 	KMF_KEY_HANDLE *, KMF_KEY_HANDLE *);
16599ebb4caSwyllys 
16699ebb4caSwyllys KMF_RETURN
16799ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T,  KMF_KEY_HANDLE *, KMF_DATA *);
16899ebb4caSwyllys 
16999ebb4caSwyllys KMF_RETURN
17099ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
17199ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
17299ebb4caSwyllys 
17399ebb4caSwyllys KMF_RETURN
17499ebb4caSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T, KMF_DELETEKEY_PARAMS *,
17599ebb4caSwyllys 	KMF_KEY_HANDLE *, boolean_t);
17699ebb4caSwyllys 
17799ebb4caSwyllys KMF_RETURN
17899ebb4caSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T, KMF_IMPORTCRL_PARAMS *);
17999ebb4caSwyllys 
18099ebb4caSwyllys KMF_RETURN
18199ebb4caSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T, KMF_DELETECRL_PARAMS *);
18299ebb4caSwyllys 
18399ebb4caSwyllys KMF_RETURN
18499ebb4caSwyllys OpenSSL_ListCRL(KMF_HANDLE_T, KMF_LISTCRL_PARAMS *, char **);
18599ebb4caSwyllys 
18699ebb4caSwyllys KMF_RETURN
18799ebb4caSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T, KMF_FINDCERTINCRL_PARAMS *);
18899ebb4caSwyllys 
18999ebb4caSwyllys KMF_RETURN
19099ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
19199ebb4caSwyllys 	KMF_PRINTABLE_ITEM, char *);
19299ebb4caSwyllys 
19399ebb4caSwyllys KMF_RETURN
19499ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
19599ebb4caSwyllys 
19699ebb4caSwyllys KMF_RETURN
19799ebb4caSwyllys OpenSSL_GetPrikeyByCert(KMF_HANDLE_T, KMF_CRYPTOWITHCERT_PARAMS *, KMF_DATA *,
19899ebb4caSwyllys 	KMF_KEY_HANDLE *, KMF_KEY_ALG);
19999ebb4caSwyllys 
20099ebb4caSwyllys KMF_RETURN
20199ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
20299ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
20399ebb4caSwyllys 
20499ebb4caSwyllys KMF_RETURN
20599ebb4caSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, KMF_OCSPREQUEST_PARAMS *,
20699ebb4caSwyllys 	char *reqfile);
20799ebb4caSwyllys 
20899ebb4caSwyllys KMF_RETURN
20999ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, KMF_OCSPRESPONSE_PARAMS_INPUT *,
21099ebb4caSwyllys     KMF_OCSPRESPONSE_PARAMS_OUTPUT *);
21199ebb4caSwyllys 
21299ebb4caSwyllys KMF_RETURN
21399ebb4caSwyllys OpenSSL_FindKey(KMF_HANDLE_T, KMF_FINDKEY_PARAMS *,
21499ebb4caSwyllys 	KMF_KEY_HANDLE *, uint32_t *);
21599ebb4caSwyllys 
21699ebb4caSwyllys KMF_RETURN
21799ebb4caSwyllys OpenSSL_ExportP12(KMF_HANDLE_T,
21899ebb4caSwyllys 	KMF_EXPORTP12_PARAMS *,
21999ebb4caSwyllys 	int, KMF_X509_DER_CERT *,
22099ebb4caSwyllys 	int, KMF_KEY_HANDLE *,
22199ebb4caSwyllys 	char *);
22299ebb4caSwyllys 
22399ebb4caSwyllys KMF_RETURN
22499ebb4caSwyllys OpenSSL_StorePrivateKey(KMF_HANDLE_T, KMF_STOREKEY_PARAMS *,
22599ebb4caSwyllys 	KMF_RAW_KEY_DATA *);
22699ebb4caSwyllys 
22799ebb4caSwyllys KMF_RETURN
22899ebb4caSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T, KMF_CREATESYMKEY_PARAMS *,
22999ebb4caSwyllys 	KMF_KEY_HANDLE *);
23099ebb4caSwyllys 
23199ebb4caSwyllys KMF_RETURN
23299ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
23399ebb4caSwyllys 
23499ebb4caSwyllys KMF_RETURN
23599ebb4caSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T, KMF_VERIFYCRL_PARAMS *);
23699ebb4caSwyllys 
23799ebb4caSwyllys KMF_RETURN
23899ebb4caSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T, KMF_CHECKCRLDATE_PARAMS *);
23999ebb4caSwyllys 
24099ebb4caSwyllys static
24199ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table =
24299ebb4caSwyllys {
24399ebb4caSwyllys 	1,				/* Version */
24499ebb4caSwyllys 	NULL, /* ConfigureKeystore */
24599ebb4caSwyllys 	OpenSSL_FindCert,
24699ebb4caSwyllys 	OpenSSL_FreeKMFCert,
24799ebb4caSwyllys 	OpenSSL_StoreCert,
24899ebb4caSwyllys 	NULL, /* ImportCert */
24999ebb4caSwyllys 	OpenSSL_ImportCRL,
25099ebb4caSwyllys 	OpenSSL_DeleteCert,
25199ebb4caSwyllys 	OpenSSL_DeleteCRL,
25299ebb4caSwyllys 	OpenSSL_CreateKeypair,
25399ebb4caSwyllys 	OpenSSL_FindKey,
25499ebb4caSwyllys 	OpenSSL_EncodePubKeyData,
25599ebb4caSwyllys 	OpenSSL_SignData,
25699ebb4caSwyllys 	OpenSSL_DeleteKey,
25799ebb4caSwyllys 	OpenSSL_ListCRL,
25899ebb4caSwyllys 	NULL,	/* FindCRL */
25999ebb4caSwyllys 	OpenSSL_FindCertInCRL,
26099ebb4caSwyllys 	OpenSSL_GetErrorString,
26199ebb4caSwyllys 	OpenSSL_GetPrikeyByCert,
26299ebb4caSwyllys 	OpenSSL_DecryptData,
26399ebb4caSwyllys 	OpenSSL_ExportP12,
26499ebb4caSwyllys 	OpenSSL_StorePrivateKey,
26599ebb4caSwyllys 	OpenSSL_CreateSymKey,
26699ebb4caSwyllys 	OpenSSL_GetSymKeyValue,
26799ebb4caSwyllys 	NULL,	/* SetTokenPin */
26899ebb4caSwyllys 	NULL	/* Finalize */
26999ebb4caSwyllys };
27099ebb4caSwyllys 
27199ebb4caSwyllys static mutex_t *lock_cs;
27299ebb4caSwyllys static long *lock_count;
27399ebb4caSwyllys 
27499ebb4caSwyllys static void
27599ebb4caSwyllys /*ARGSUSED*/
27699ebb4caSwyllys locking_cb(int mode, int type, char *file, int line)
27799ebb4caSwyllys {
27899ebb4caSwyllys 	if (mode & CRYPTO_LOCK) {
27999ebb4caSwyllys 		(void) mutex_lock(&(lock_cs[type]));
28099ebb4caSwyllys 		lock_count[type]++;
28199ebb4caSwyllys 	} else {
28299ebb4caSwyllys 		(void) mutex_unlock(&(lock_cs[type]));
28399ebb4caSwyllys 	}
28499ebb4caSwyllys }
28599ebb4caSwyllys 
28699ebb4caSwyllys static unsigned long
28799ebb4caSwyllys thread_id()
28899ebb4caSwyllys {
28999ebb4caSwyllys 	return ((unsigned long)thr_self());
29099ebb4caSwyllys }
29199ebb4caSwyllys 
29299ebb4caSwyllys KMF_PLUGIN_FUNCLIST *
29399ebb4caSwyllys KMF_Plugin_Initialize()
29499ebb4caSwyllys {
29599ebb4caSwyllys 	int i;
29699ebb4caSwyllys 
29799ebb4caSwyllys 	(void) mutex_lock(&init_lock);
29899ebb4caSwyllys 	if (!ssl_initialized) {
29999ebb4caSwyllys 		OpenSSL_add_all_algorithms();
30099ebb4caSwyllys 
30199ebb4caSwyllys 		/* Enable error strings for reporting */
30299ebb4caSwyllys 		ERR_load_crypto_strings();
30399ebb4caSwyllys 
30499ebb4caSwyllys 		/*
30599ebb4caSwyllys 		 * Add support for extension OIDs that are not yet in the
30699ebb4caSwyllys 		 * openssl default set.
30799ebb4caSwyllys 		 */
30899ebb4caSwyllys 		(void) OBJ_create("2.5.29.30", "nameConstraints",
30999ebb4caSwyllys 				"X509v3 Name Constraints");
31099ebb4caSwyllys 		(void) OBJ_create("2.5.29.33", "policyMappings",
31199ebb4caSwyllys 				"X509v3 Policy Mappings");
31299ebb4caSwyllys 		(void) OBJ_create("2.5.29.36", "policyConstraints",
31399ebb4caSwyllys 			"X509v3 Policy Constraints");
31499ebb4caSwyllys 		(void) OBJ_create("2.5.29.46", "freshestCRL",
31599ebb4caSwyllys 			"X509v3 Freshest CRL");
31699ebb4caSwyllys 		(void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
31799ebb4caSwyllys 			"X509v3 Inhibit Any-Policy");
31899ebb4caSwyllys 		/*
31999ebb4caSwyllys 		 * Set up for thread-safe operation.
32099ebb4caSwyllys 		 */
32199ebb4caSwyllys 		lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
32299ebb4caSwyllys 		if (lock_cs == NULL) {
32399ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
32499ebb4caSwyllys 			return (NULL);
32599ebb4caSwyllys 		}
32699ebb4caSwyllys 
32799ebb4caSwyllys 		lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
32899ebb4caSwyllys 		if (lock_count == NULL) {
32999ebb4caSwyllys 			OPENSSL_free(lock_cs);
33099ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
33199ebb4caSwyllys 			return (NULL);
33299ebb4caSwyllys 		}
33399ebb4caSwyllys 
33499ebb4caSwyllys 		for (i = 0; i < CRYPTO_num_locks(); i++) {
33599ebb4caSwyllys 			lock_count[i] = 0;
33699ebb4caSwyllys 			(void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
33799ebb4caSwyllys 		}
33899ebb4caSwyllys 
33999ebb4caSwyllys 		CRYPTO_set_id_callback((unsigned long (*)())thread_id);
34099ebb4caSwyllys 		CRYPTO_set_locking_callback((void (*)())locking_cb);
34199ebb4caSwyllys 		ssl_initialized = 1;
34299ebb4caSwyllys 	}
34399ebb4caSwyllys 	(void) mutex_unlock(&init_lock);
34499ebb4caSwyllys 
34599ebb4caSwyllys 	return (&openssl_plugin_table);
34699ebb4caSwyllys }
34799ebb4caSwyllys /*
34899ebb4caSwyllys  * Convert an SSL DN to a KMF DN.
34999ebb4caSwyllys  */
35099ebb4caSwyllys static KMF_RETURN
35199ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
35299ebb4caSwyllys {
35399ebb4caSwyllys 	KMF_DATA derdata;
35499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
35599ebb4caSwyllys 	uchar_t *tmp;
35699ebb4caSwyllys 
35799ebb4caSwyllys 	/* Convert to raw DER format */
35899ebb4caSwyllys 	derdata.Length = i2d_X509_NAME(sslDN, NULL);
35999ebb4caSwyllys 	if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
36099ebb4caSwyllys 		== NULL) {
36199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
36299ebb4caSwyllys 	}
36399ebb4caSwyllys 	(void) i2d_X509_NAME(sslDN, &tmp);
36499ebb4caSwyllys 
36599ebb4caSwyllys 	/* Decode to KMF format */
36699ebb4caSwyllys 	rv = DerDecodeName(&derdata, kmfDN);
36799ebb4caSwyllys 	if (rv != KMF_OK) {
36899ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
36999ebb4caSwyllys 	}
37099ebb4caSwyllys 	OPENSSL_free(derdata.Data);
37199ebb4caSwyllys 
37299ebb4caSwyllys 	return (rv);
37399ebb4caSwyllys }
37499ebb4caSwyllys 
37599ebb4caSwyllys static int
37699ebb4caSwyllys isdir(char *path)
37799ebb4caSwyllys {
37899ebb4caSwyllys 	struct stat s;
37999ebb4caSwyllys 
38099ebb4caSwyllys 	if (stat(path, &s) == -1)
38199ebb4caSwyllys 		return (0);
38299ebb4caSwyllys 
38399ebb4caSwyllys 	return (s.st_mode & S_IFDIR);
38499ebb4caSwyllys }
38599ebb4caSwyllys 
38699ebb4caSwyllys static KMF_RETURN
38799ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
38899ebb4caSwyllys {
38999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
39099ebb4caSwyllys 	unsigned char *buf = NULL, *p;
39199ebb4caSwyllys 	int len;
39299ebb4caSwyllys 
39399ebb4caSwyllys 	/*
39499ebb4caSwyllys 	 * Convert the X509 internal struct to DER encoded data
39599ebb4caSwyllys 	 */
39699ebb4caSwyllys 	if ((len = i2d_X509(x509cert, NULL)) < 0) {
39799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
39899ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
39999ebb4caSwyllys 		goto cleanup;
40099ebb4caSwyllys 	}
40199ebb4caSwyllys 	if ((buf = malloc(len)) == NULL) {
40299ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
40399ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
40499ebb4caSwyllys 		goto cleanup;
40599ebb4caSwyllys 	}
40699ebb4caSwyllys 
40799ebb4caSwyllys 	/*
40899ebb4caSwyllys 	 * i2d_X509 will increment the buf pointer so that we need to
40999ebb4caSwyllys 	 * save it.
41099ebb4caSwyllys 	 */
41199ebb4caSwyllys 	p = buf;
41299ebb4caSwyllys 	if ((len = i2d_X509(x509cert, &p)) < 0) {
41399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
41499ebb4caSwyllys 		free(buf);
41599ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
41699ebb4caSwyllys 		goto cleanup;
41799ebb4caSwyllys 	}
41899ebb4caSwyllys 
41999ebb4caSwyllys 	/* caller's responsibility to free it */
42099ebb4caSwyllys 	cert->Data = buf;
42199ebb4caSwyllys 	cert->Length = len;
42299ebb4caSwyllys 
42399ebb4caSwyllys cleanup:
42499ebb4caSwyllys 	if (rv != KMF_OK) {
42599ebb4caSwyllys 		if (buf)
42699ebb4caSwyllys 			free(buf);
42799ebb4caSwyllys 		cert->Data = NULL;
42899ebb4caSwyllys 		cert->Length = 0;
42999ebb4caSwyllys 	}
43099ebb4caSwyllys 
43199ebb4caSwyllys 	return (rv);
43299ebb4caSwyllys }
43399ebb4caSwyllys 
43499ebb4caSwyllys static KMF_RETURN
43599ebb4caSwyllys check_cert(X509 *xcert, KMF_FINDCERT_PARAMS *params, boolean_t *match)
43699ebb4caSwyllys {
43799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
43899ebb4caSwyllys 	boolean_t findIssuer = FALSE;
43999ebb4caSwyllys 	boolean_t findSubject = FALSE;
44099ebb4caSwyllys 	boolean_t findSerial = FALSE;
44199ebb4caSwyllys 	KMF_X509_NAME issuerDN, subjectDN;
44299ebb4caSwyllys 	KMF_X509_NAME certIssuerDN, certSubjectDN;
44399ebb4caSwyllys 
44499ebb4caSwyllys 	*match = FALSE;
44599ebb4caSwyllys 	if (xcert == NULL) {
44699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
44799ebb4caSwyllys 	}
44899ebb4caSwyllys 
44999ebb4caSwyllys 	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
45099ebb4caSwyllys 	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
45199ebb4caSwyllys 	(void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
45299ebb4caSwyllys 	(void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
45399ebb4caSwyllys 
45499ebb4caSwyllys 	if (params->issuer != NULL && strlen(params->issuer)) {
45599ebb4caSwyllys 		rv = KMF_DNParser(params->issuer, &issuerDN);
45699ebb4caSwyllys 		if (rv != KMF_OK)
45799ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
45899ebb4caSwyllys 
45999ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->issuer, &certIssuerDN);
46099ebb4caSwyllys 		if (rv != KMF_OK) {
46199ebb4caSwyllys 			KMF_FreeDN(&issuerDN);
46299ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
46399ebb4caSwyllys 		}
46499ebb4caSwyllys 
46599ebb4caSwyllys 		findIssuer = TRUE;
46699ebb4caSwyllys 	}
46799ebb4caSwyllys 	if (params->subject != NULL && strlen(params->subject)) {
46899ebb4caSwyllys 		rv = KMF_DNParser(params->subject, &subjectDN);
46999ebb4caSwyllys 		if (rv != KMF_OK) {
47099ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
47199ebb4caSwyllys 			goto cleanup;
47299ebb4caSwyllys 		}
47399ebb4caSwyllys 
47499ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->subject, &certSubjectDN);
47599ebb4caSwyllys 		if (rv != KMF_OK) {
47699ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
47799ebb4caSwyllys 			goto cleanup;
47899ebb4caSwyllys 		}
47999ebb4caSwyllys 		findSubject = TRUE;
48099ebb4caSwyllys 	}
48199ebb4caSwyllys 	if (params->serial != NULL && params->serial->val != NULL)
48299ebb4caSwyllys 		findSerial = TRUE;
48399ebb4caSwyllys 
48499ebb4caSwyllys 	if (findSerial) {
48599ebb4caSwyllys 		BIGNUM *bn;
48699ebb4caSwyllys 
48799ebb4caSwyllys 		/* Comparing BIGNUMs is a pain! */
48899ebb4caSwyllys 		bn = ASN1_INTEGER_to_BN(xcert->cert_info->serialNumber, NULL);
48999ebb4caSwyllys 		if (bn != NULL) {
49099ebb4caSwyllys 			int bnlen = BN_num_bytes(bn);
49199ebb4caSwyllys 
49299ebb4caSwyllys 			if (bnlen == params->serial->len) {
49399ebb4caSwyllys 				uchar_t *a = malloc(bnlen);
49499ebb4caSwyllys 				if (a == NULL) {
49599ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
49699ebb4caSwyllys 					BN_free(bn);
49799ebb4caSwyllys 					goto cleanup;
49899ebb4caSwyllys 				}
49999ebb4caSwyllys 				bnlen = BN_bn2bin(bn, a);
50099ebb4caSwyllys 				*match = !memcmp(a,
50199ebb4caSwyllys 					params->serial->val,
50299ebb4caSwyllys 					params->serial->len);
50399ebb4caSwyllys 				rv = KMF_OK;
50499ebb4caSwyllys 				free(a);
50599ebb4caSwyllys 			}
50699ebb4caSwyllys 			BN_free(bn);
50799ebb4caSwyllys 			if (!(*match))
50899ebb4caSwyllys 				goto cleanup;
50999ebb4caSwyllys 		} else {
51099ebb4caSwyllys 			rv = KMF_OK;
51199ebb4caSwyllys 			goto cleanup;
51299ebb4caSwyllys 		}
51399ebb4caSwyllys 	}
51499ebb4caSwyllys 	if (findIssuer) {
51599ebb4caSwyllys 		*match = !KMF_CompareRDNs(&issuerDN, &certIssuerDN);
51699ebb4caSwyllys 		if (!(*match)) {
51799ebb4caSwyllys 			rv = KMF_OK;
51899ebb4caSwyllys 			goto cleanup;
51999ebb4caSwyllys 		}
52099ebb4caSwyllys 	}
52199ebb4caSwyllys 	if (findSubject) {
52299ebb4caSwyllys 		*match = !KMF_CompareRDNs(&subjectDN, &certSubjectDN);
52399ebb4caSwyllys 		if (!(*match)) {
52499ebb4caSwyllys 			rv = KMF_OK;
52599ebb4caSwyllys 			goto cleanup;
52699ebb4caSwyllys 		}
52799ebb4caSwyllys 	}
52899ebb4caSwyllys 
52999ebb4caSwyllys 	*match = TRUE;
53099ebb4caSwyllys cleanup:
53199ebb4caSwyllys 	if (findIssuer) {
53299ebb4caSwyllys 		KMF_FreeDN(&issuerDN);
53399ebb4caSwyllys 		KMF_FreeDN(&certIssuerDN);
53499ebb4caSwyllys 	}
53599ebb4caSwyllys 	if (findSubject) {
53699ebb4caSwyllys 		KMF_FreeDN(&subjectDN);
53799ebb4caSwyllys 		KMF_FreeDN(&certSubjectDN);
53899ebb4caSwyllys 	}
53999ebb4caSwyllys 
54099ebb4caSwyllys 	return (rv);
54199ebb4caSwyllys }
54299ebb4caSwyllys 
54399ebb4caSwyllys static KMF_RETURN
54499ebb4caSwyllys load_X509cert(KMF_HANDLE *kmfh,
54599ebb4caSwyllys 	KMF_FINDCERT_PARAMS *params,
54699ebb4caSwyllys 	char *pathname,
54799ebb4caSwyllys 	X509 **outcert)
54899ebb4caSwyllys {
54999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
55099ebb4caSwyllys 	X509 *xcert = NULL;
55199ebb4caSwyllys 	BIO *bcert = NULL;
55299ebb4caSwyllys 	boolean_t  match = FALSE;
55399ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
55499ebb4caSwyllys 
55599ebb4caSwyllys 	/*
55699ebb4caSwyllys 	 * auto-detect the file format, regardless of what
55799ebb4caSwyllys 	 * the 'format' parameters in the params say.
55899ebb4caSwyllys 	 */
55999ebb4caSwyllys 	rv = KMF_GetFileFormat(pathname, &format);
56099ebb4caSwyllys 	if (rv != KMF_OK) {
56199ebb4caSwyllys 		if (rv == KMF_ERR_OPEN_FILE)
56299ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
56399ebb4caSwyllys 		return (rv);
56499ebb4caSwyllys 	}
56599ebb4caSwyllys 
56699ebb4caSwyllys 	/* Not ASN1(DER) format */
56799ebb4caSwyllys 	if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
56899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
56999ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
57099ebb4caSwyllys 		goto cleanup;
57199ebb4caSwyllys 	}
57299ebb4caSwyllys 
57399ebb4caSwyllys 	if (format == KMF_FORMAT_PEM)
57499ebb4caSwyllys 		xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
57599ebb4caSwyllys 	else if (format == KMF_FORMAT_ASN1)
57699ebb4caSwyllys 		xcert = d2i_X509_bio(bcert, NULL);
57799ebb4caSwyllys 	else if (format == KMF_FORMAT_PKCS12) {
57899ebb4caSwyllys 		PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
57999ebb4caSwyllys 		if (p12 != NULL) {
58099ebb4caSwyllys 			(void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
58199ebb4caSwyllys 			PKCS12_free(p12);
58299ebb4caSwyllys 			p12 = NULL;
58399ebb4caSwyllys 		} else {
58499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
58599ebb4caSwyllys 			rv = KMF_ERR_BAD_CERT_FORMAT;
58699ebb4caSwyllys 		}
58799ebb4caSwyllys 	} else {
58899ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
58999ebb4caSwyllys 		goto cleanup;
59099ebb4caSwyllys 	}
59199ebb4caSwyllys 
59299ebb4caSwyllys 	if (xcert == NULL) {
59399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
59499ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
59599ebb4caSwyllys 		goto cleanup;
59699ebb4caSwyllys 	}
59799ebb4caSwyllys 
59899ebb4caSwyllys 	if (check_cert(xcert, params, &match) != KMF_OK || match == FALSE) {
59999ebb4caSwyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
60099ebb4caSwyllys 		goto cleanup;
60199ebb4caSwyllys 	}
60299ebb4caSwyllys 
60399ebb4caSwyllys 	if (outcert != NULL) {
60499ebb4caSwyllys 		*outcert = xcert;
60599ebb4caSwyllys 	}
60699ebb4caSwyllys 
60799ebb4caSwyllys cleanup:
60899ebb4caSwyllys 	if (bcert != NULL) (void) BIO_free(bcert);
60999ebb4caSwyllys 	if (rv != KMF_OK && xcert != NULL)
61099ebb4caSwyllys 		X509_free(xcert);
61199ebb4caSwyllys 
61299ebb4caSwyllys 	return (rv);
61399ebb4caSwyllys }
61499ebb4caSwyllys 
61571593db2Swyllys static int
61671593db2Swyllys datacmp(const void *a, const void *b)
61771593db2Swyllys {
61871593db2Swyllys 	KMF_DATA *adata = (KMF_DATA *)a;
61971593db2Swyllys 	KMF_DATA *bdata = (KMF_DATA *)b;
62071593db2Swyllys 	if (adata->Length > bdata->Length)
62171593db2Swyllys 		return (-1);
62271593db2Swyllys 	if (adata->Length < bdata->Length)
62371593db2Swyllys 		return (1);
62471593db2Swyllys 	return (0);
62571593db2Swyllys }
62671593db2Swyllys 
62771593db2Swyllys static KMF_RETURN
62871593db2Swyllys load_certs(KMF_HANDLE *kmfh, KMF_FINDCERT_PARAMS *params, char *pathname,
62971593db2Swyllys 	KMF_DATA **certlist, uint32_t *numcerts)
63071593db2Swyllys {
63171593db2Swyllys 	KMF_RETURN rv = KMF_OK;
63271593db2Swyllys 	int i;
63371593db2Swyllys 	KMF_DATA *certs = NULL;
63471593db2Swyllys 	int nc = 0;
63571593db2Swyllys 	int hits = 0;
63671593db2Swyllys 	KMF_ENCODE_FORMAT format;
63771593db2Swyllys 
63871593db2Swyllys 	rv = KMF_GetFileFormat(pathname, &format);
63971593db2Swyllys 	if (rv != KMF_OK) {
64071593db2Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
64171593db2Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
64271593db2Swyllys 		return (rv);
64371593db2Swyllys 	}
64471593db2Swyllys 	if (format == KMF_FORMAT_ASN1) {
64571593db2Swyllys 		/* load a single certificate */
64671593db2Swyllys 		certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
64771593db2Swyllys 		if (certs == NULL)
64871593db2Swyllys 			return (KMF_ERR_MEMORY);
64971593db2Swyllys 		certs->Data = NULL;
65071593db2Swyllys 		certs->Length = 0;
65171593db2Swyllys 		rv = kmf_load_cert(kmfh, params, pathname, certs);
65271593db2Swyllys 		if (rv == KMF_OK) {
65371593db2Swyllys 			*certlist = certs;
65471593db2Swyllys 			*numcerts = 1;
65571593db2Swyllys 		}
65671593db2Swyllys 		return (rv);
65771593db2Swyllys 	} else if (format == KMF_FORMAT_PKCS12) {
65871593db2Swyllys 		/* We need a credential to access a PKCS#12 file */
65971593db2Swyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
66071593db2Swyllys 	} else if (format == KMF_FORMAT_PEM ||
66171593db2Swyllys 		format != KMF_FORMAT_PEM_KEYPAIR) {
66271593db2Swyllys 
66371593db2Swyllys 		/* This function only works on PEM files */
66471593db2Swyllys 		rv = extract_objects(kmfh, pathname,
66571593db2Swyllys 			(uchar_t *)NULL, 0, NULL,
66671593db2Swyllys 			&certs, &nc);
66771593db2Swyllys 	} else {
66871593db2Swyllys 		return (KMF_ERR_ENCODING);
66971593db2Swyllys 	}
67071593db2Swyllys 
67171593db2Swyllys 	if (rv != KMF_OK)
67271593db2Swyllys 		return (rv);
67371593db2Swyllys 
67471593db2Swyllys 	for (i = 0; i < nc; i++) {
67571593db2Swyllys 		if (params->find_cert_validity == KMF_NONEXPIRED_CERTS) {
67671593db2Swyllys 			rv = KMF_CheckCertDate(kmfh, &certs[i]);
67771593db2Swyllys 		} else if (params->find_cert_validity == KMF_EXPIRED_CERTS) {
67871593db2Swyllys 			rv = KMF_CheckCertDate(kmfh, &certs[i]);
67971593db2Swyllys 			if (rv == KMF_OK)
68071593db2Swyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
68171593db2Swyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD)
68271593db2Swyllys 				rv = KMF_OK;
68371593db2Swyllys 		}
68471593db2Swyllys 		if (rv != KMF_OK) {
68571593db2Swyllys 			/* Remove this cert from the list by clearing it. */
68671593db2Swyllys 			KMF_FreeData(&certs[i]);
68771593db2Swyllys 		} else {
68871593db2Swyllys 			hits++; /* count valid certs found */
68971593db2Swyllys 		}
69071593db2Swyllys 		rv = KMF_OK;
69171593db2Swyllys 	}
69271593db2Swyllys 	if (rv == KMF_OK && hits == 0) {
69371593db2Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
69471593db2Swyllys 	} else if (rv == KMF_OK && hits > 0) {
69571593db2Swyllys 		/*
69671593db2Swyllys 		 * Sort the list of certs by length to put the cleared ones
69771593db2Swyllys 		 * at the end so they don't get accessed by the caller.
69871593db2Swyllys 		 */
69971593db2Swyllys 		qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
70071593db2Swyllys 		*certlist = certs;
70171593db2Swyllys 
70271593db2Swyllys 		/* since we sorted the list, just return the number of hits */
70371593db2Swyllys 		*numcerts = hits;
70471593db2Swyllys 	}
70571593db2Swyllys 	return (rv);
70671593db2Swyllys }
70771593db2Swyllys 
70899ebb4caSwyllys static KMF_RETURN
70999ebb4caSwyllys kmf_load_cert(KMF_HANDLE *kmfh,
71099ebb4caSwyllys 	KMF_FINDCERT_PARAMS *params,
71199ebb4caSwyllys 	char *pathname,
71299ebb4caSwyllys 	KMF_DATA *cert)
71399ebb4caSwyllys {
71499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
71599ebb4caSwyllys 	X509 *x509cert = NULL;
71699ebb4caSwyllys 
71799ebb4caSwyllys 	rv = load_X509cert(kmfh, params, pathname, &x509cert);
71899ebb4caSwyllys 	if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
71999ebb4caSwyllys 		rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
72099ebb4caSwyllys 		if (rv != KMF_OK) {
72199ebb4caSwyllys 			goto cleanup;
72299ebb4caSwyllys 		}
72399ebb4caSwyllys 		if (params->find_cert_validity == KMF_NONEXPIRED_CERTS) {
72499ebb4caSwyllys 			rv = KMF_CheckCertDate(kmfh, cert);
72599ebb4caSwyllys 		} else if (params->find_cert_validity == KMF_EXPIRED_CERTS) {
72699ebb4caSwyllys 			rv = KMF_CheckCertDate(kmfh, cert);
72799ebb4caSwyllys 			if (rv == KMF_OK)  {
72899ebb4caSwyllys 				/*
72999ebb4caSwyllys 				 * This is a valid cert so skip it.
73099ebb4caSwyllys 				 */
73199ebb4caSwyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
73299ebb4caSwyllys 			}
73399ebb4caSwyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD) {
73499ebb4caSwyllys 				/*
73599ebb4caSwyllys 				 * We want to return success when we
73699ebb4caSwyllys 				 * find an invalid cert.
73799ebb4caSwyllys 				 */
73899ebb4caSwyllys 				rv = KMF_OK;
73999ebb4caSwyllys 				goto cleanup;
74099ebb4caSwyllys 			}
74199ebb4caSwyllys 		}
74299ebb4caSwyllys 	}
74399ebb4caSwyllys cleanup:
74499ebb4caSwyllys 	if (x509cert != NULL)
74599ebb4caSwyllys 		X509_free(x509cert);
74699ebb4caSwyllys 
74799ebb4caSwyllys 	return (rv);
74899ebb4caSwyllys }
74999ebb4caSwyllys 
75099ebb4caSwyllys static EVP_PKEY *
75199ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file)
75299ebb4caSwyllys {
75399ebb4caSwyllys 	BIO *keyfile = NULL;
75499ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
75599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
75699ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
75799ebb4caSwyllys 
75899ebb4caSwyllys 	if (file == NULL) {
75999ebb4caSwyllys 		return (NULL);
76099ebb4caSwyllys 	}
76199ebb4caSwyllys 
76299ebb4caSwyllys 	if (KMF_GetFileFormat((char *)file, &format) != KMF_OK)
76399ebb4caSwyllys 		return (NULL);
76499ebb4caSwyllys 
76599ebb4caSwyllys 	keyfile = BIO_new_file(file, "rb");
76699ebb4caSwyllys 	if (keyfile == NULL) {
76799ebb4caSwyllys 		goto end;
76899ebb4caSwyllys 	}
76999ebb4caSwyllys 
77099ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1)
77199ebb4caSwyllys 		pkey = d2i_PrivateKey_bio(keyfile, NULL);
77271593db2Swyllys 	else if (format == KMF_FORMAT_PEM ||
77371593db2Swyllys 		format == KMF_FORMAT_PEM_KEYPAIR)
77499ebb4caSwyllys 		pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
77599ebb4caSwyllys 
77699ebb4caSwyllys end:
77799ebb4caSwyllys 	if (pkey == NULL)
77899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
77999ebb4caSwyllys 
78099ebb4caSwyllys 	if (keyfile != NULL)
78199ebb4caSwyllys 		(void) BIO_free(keyfile);
78299ebb4caSwyllys 
78399ebb4caSwyllys 	return (pkey);
78499ebb4caSwyllys }
78599ebb4caSwyllys 
78699ebb4caSwyllys KMF_RETURN
78799ebb4caSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle,
78899ebb4caSwyllys 	KMF_FINDCERT_PARAMS *params,
78999ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert,
79099ebb4caSwyllys 	uint32_t *num_certs)
79199ebb4caSwyllys {
79299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
79399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
79499ebb4caSwyllys 	char *fullpath;
79571593db2Swyllys 	int i;
79699ebb4caSwyllys 
79799ebb4caSwyllys 	if (num_certs == NULL || params == NULL)
79899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
79999ebb4caSwyllys 
80099ebb4caSwyllys 	*num_certs = 0;
80199ebb4caSwyllys 
80299ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
80399ebb4caSwyllys 		params->sslparms.certfile);
80499ebb4caSwyllys 
80599ebb4caSwyllys 	if (fullpath == NULL)
80699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
80799ebb4caSwyllys 
80899ebb4caSwyllys 	if (isdir(fullpath)) {
80999ebb4caSwyllys 		DIR *dirp;
81099ebb4caSwyllys 		struct dirent *dp;
81199ebb4caSwyllys 		int n = 0;
81299ebb4caSwyllys 
81399ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
81499ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
81599ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
81699ebb4caSwyllys 		}
81799ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
81899ebb4caSwyllys 			char *fname;
81971593db2Swyllys 			KMF_DATA *certlist = NULL;
82071593db2Swyllys 			uint32_t numcerts = 0;
82171593db2Swyllys 
82299ebb4caSwyllys 			if (strcmp(dp->d_name, ".") == 0 ||
82399ebb4caSwyllys 			    strcmp(dp->d_name, "..") == 0)
82499ebb4caSwyllys 				continue;
82599ebb4caSwyllys 
82699ebb4caSwyllys 			fname = get_fullpath(fullpath,
82799ebb4caSwyllys 				(char *)&dp->d_name);
82899ebb4caSwyllys 
82971593db2Swyllys 			rv = load_certs(kmfh, params, fname, &certlist,
83071593db2Swyllys 				&numcerts);
83199ebb4caSwyllys 
83299ebb4caSwyllys 			if (rv != KMF_OK) {
83399ebb4caSwyllys 				free(fname);
83471593db2Swyllys 				if (certlist != NULL) {
83571593db2Swyllys 					for (i = 0; i < numcerts; i++)
83671593db2Swyllys 						KMF_FreeData(&certlist[i]);
83771593db2Swyllys 					free(certlist);
83871593db2Swyllys 				}
83999ebb4caSwyllys 				continue;
84099ebb4caSwyllys 			}
84199ebb4caSwyllys 
84299ebb4caSwyllys 			/* If load succeeds, add certdata to the list */
84399ebb4caSwyllys 			if (kmf_cert != NULL) {
84471593db2Swyllys 				for (i = 0; i < numcerts; i++) {
84571593db2Swyllys 					kmf_cert[n].certificate.Data =
84671593db2Swyllys 						certlist[i].Data;
84799ebb4caSwyllys 					kmf_cert[n].certificate.Length =
84871593db2Swyllys 						certlist[i].Length;
84999ebb4caSwyllys 
85099ebb4caSwyllys 					kmf_cert[n].kmf_private.keystore_type =
85199ebb4caSwyllys 						KMF_KEYSTORE_OPENSSL;
85299ebb4caSwyllys 					kmf_cert[n].kmf_private.flags =
85399ebb4caSwyllys 						KMF_FLAG_CERT_VALID;
85471593db2Swyllys 					kmf_cert[n].kmf_private.label =
85571593db2Swyllys 						strdup(fname);
85699ebb4caSwyllys 					n++;
85799ebb4caSwyllys 				}
85871593db2Swyllys 				free(certlist);
85971593db2Swyllys 			} else {
86071593db2Swyllys 				for (i = 0; i < numcerts; i++)
86171593db2Swyllys 					KMF_FreeData(&certlist[i]);
86271593db2Swyllys 				free(certlist);
86371593db2Swyllys 				n += numcerts;
86471593db2Swyllys 			}
86571593db2Swyllys 			free(fname);
86671593db2Swyllys 		}
86799ebb4caSwyllys 		(*num_certs) = n;
86899ebb4caSwyllys 		if (*num_certs == 0)
86999ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
87099ebb4caSwyllys 		if (*num_certs > 0)
87199ebb4caSwyllys 			rv = KMF_OK;
87299ebb4caSwyllys exit:
87399ebb4caSwyllys 		(void) closedir(dirp);
87499ebb4caSwyllys 	} else {
87571593db2Swyllys 		KMF_DATA *certlist = NULL;
87671593db2Swyllys 		uint32_t numcerts = 0;
87771593db2Swyllys 
87871593db2Swyllys 		rv = load_certs(kmfh, params, fullpath, &certlist, &numcerts);
87999ebb4caSwyllys 		if (rv != KMF_OK) {
88099ebb4caSwyllys 			free(fullpath);
88199ebb4caSwyllys 			return (rv);
88299ebb4caSwyllys 		}
88399ebb4caSwyllys 
88471593db2Swyllys 		if (kmf_cert != NULL && certlist != NULL) {
88571593db2Swyllys 			for (i = 0; i < numcerts; i++) {
88671593db2Swyllys 				kmf_cert[i].certificate.Data =
88771593db2Swyllys 					certlist[i].Data;
88871593db2Swyllys 				kmf_cert[i].certificate.Length =
88971593db2Swyllys 					certlist[i].Length;
89071593db2Swyllys 				kmf_cert[i].kmf_private.keystore_type =
89199ebb4caSwyllys 					KMF_KEYSTORE_OPENSSL;
89271593db2Swyllys 				kmf_cert[i].kmf_private.flags =
89371593db2Swyllys 					KMF_FLAG_CERT_VALID;
89471593db2Swyllys 				kmf_cert[i].kmf_private.label =
89571593db2Swyllys 					strdup(fullpath);
89671593db2Swyllys 			}
89771593db2Swyllys 			free(certlist);
89899ebb4caSwyllys 		} else {
89971593db2Swyllys 			if (certlist != NULL) {
90071593db2Swyllys 				for (i = 0; i < numcerts; i++)
90171593db2Swyllys 					KMF_FreeData(&certlist[i]);
90271593db2Swyllys 				free(certlist);
90371593db2Swyllys 			}
90471593db2Swyllys 		}
90571593db2Swyllys 		*num_certs = numcerts;
90699ebb4caSwyllys 	}
90799ebb4caSwyllys 
90899ebb4caSwyllys 	free(fullpath);
90999ebb4caSwyllys 
91099ebb4caSwyllys 	return (rv);
91199ebb4caSwyllys }
91299ebb4caSwyllys 
91399ebb4caSwyllys void
91499ebb4caSwyllys /*ARGSUSED*/
91599ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
91699ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert)
91799ebb4caSwyllys {
91899ebb4caSwyllys 	if (kmf_cert != NULL) {
91999ebb4caSwyllys 		if (kmf_cert->certificate.Data != NULL) {
92099ebb4caSwyllys 			free(kmf_cert->certificate.Data);
92199ebb4caSwyllys 			kmf_cert->certificate.Data = NULL;
92299ebb4caSwyllys 			kmf_cert->certificate.Length = 0;
92399ebb4caSwyllys 		}
92499ebb4caSwyllys 		if (kmf_cert->kmf_private.label)
92599ebb4caSwyllys 			free(kmf_cert->kmf_private.label);
92699ebb4caSwyllys 	}
92799ebb4caSwyllys }
92899ebb4caSwyllys 
92999ebb4caSwyllys KMF_RETURN
93099ebb4caSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, KMF_STORECERT_PARAMS *params,
93199ebb4caSwyllys     KMF_DATA * pcert)
93299ebb4caSwyllys {
93399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
93499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
93599ebb4caSwyllys 	X509 *xcert = NULL;
93699ebb4caSwyllys 	FILE *fp;
93799ebb4caSwyllys 	unsigned char *outbuf;
93899ebb4caSwyllys 	unsigned char *outbuf_p;
93999ebb4caSwyllys 	char *fullpath;
94099ebb4caSwyllys 	int outbuflen;
94199ebb4caSwyllys 	int len;
94299ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
94399ebb4caSwyllys 
94499ebb4caSwyllys 	if (params == NULL || params->ks_opt_u.openssl_opts.certfile == NULL) {
94599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
94699ebb4caSwyllys 	}
94799ebb4caSwyllys 
94899ebb4caSwyllys 	/*
94999ebb4caSwyllys 	 * check if the cert output format is supported by OPENSSL.
95099ebb4caSwyllys 	 * however, since the keystore for OPENSSL is just a file, we have
95199ebb4caSwyllys 	 * no way to store the format along with the file.
95299ebb4caSwyllys 	 */
95399ebb4caSwyllys 	format = params->sslparms.format;
95499ebb4caSwyllys 	if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM)
95599ebb4caSwyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
95699ebb4caSwyllys 
95799ebb4caSwyllys 
95899ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
95999ebb4caSwyllys 		params->sslparms.certfile);
96099ebb4caSwyllys 	if (fullpath == NULL)
96199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
96299ebb4caSwyllys 
96399ebb4caSwyllys 	/*
96499ebb4caSwyllys 	 * When storing a certificate, you must specify a filename.
96599ebb4caSwyllys 	 */
96699ebb4caSwyllys 	if (isdir(fullpath)) {
96799ebb4caSwyllys 		free(fullpath);
96899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
96999ebb4caSwyllys 	}
97099ebb4caSwyllys 
97199ebb4caSwyllys 	/* copy cert data to outbuf */
97299ebb4caSwyllys 	outbuflen = pcert->Length;
97399ebb4caSwyllys 	outbuf = malloc(outbuflen);
97499ebb4caSwyllys 	if (outbuf == NULL) {
97599ebb4caSwyllys 		free(fullpath);
97699ebb4caSwyllys 		return (KMF_ERR_MEMORY);
97799ebb4caSwyllys 	}
97899ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
97999ebb4caSwyllys 
98099ebb4caSwyllys 	if ((fp = fopen(fullpath, "w")) ==
98199ebb4caSwyllys 		NULL) {
98299ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
98399ebb4caSwyllys 		ret = KMF_ERR_INTERNAL;
98499ebb4caSwyllys 		goto out;
98599ebb4caSwyllys 	}
98699ebb4caSwyllys 
98799ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
98899ebb4caSwyllys 		len = fwrite(outbuf, 1, outbuflen, fp);
98999ebb4caSwyllys 		if (len != outbuflen) {
99099ebb4caSwyllys 			SET_SYS_ERROR(kmfh, errno);
99199ebb4caSwyllys 			ret = KMF_ERR_WRITE_FILE;
99299ebb4caSwyllys 		} else {
99399ebb4caSwyllys 			ret = KMF_OK;
99499ebb4caSwyllys 		}
99599ebb4caSwyllys 		goto out;
99699ebb4caSwyllys 	}
99799ebb4caSwyllys 
99899ebb4caSwyllys 	/*
99999ebb4caSwyllys 	 * The output format is not KMF_FORMAT_ASN1, so we will
100099ebb4caSwyllys 	 * Convert the cert data to OpenSSL internal X509 first.
100199ebb4caSwyllys 	 */
100299ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
100399ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, outbuflen);
100499ebb4caSwyllys 	if (xcert == NULL) {
100599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
100699ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
100799ebb4caSwyllys 		goto out;
100899ebb4caSwyllys 	}
100999ebb4caSwyllys 
101099ebb4caSwyllys 	if (format == KMF_FORMAT_PEM) {
101199ebb4caSwyllys 		/* Convert to the PEM format and write it out */
101299ebb4caSwyllys 		if (!PEM_write_X509(fp, xcert)) {
101399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
101499ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
101599ebb4caSwyllys 		} else {
101699ebb4caSwyllys 			ret = KMF_OK;
101799ebb4caSwyllys 		}
101899ebb4caSwyllys 		goto out;
101999ebb4caSwyllys 	}
102099ebb4caSwyllys 
102199ebb4caSwyllys out:
102299ebb4caSwyllys 	if (fullpath != NULL)
102399ebb4caSwyllys 		free(fullpath);
102499ebb4caSwyllys 
102599ebb4caSwyllys 	if (outbuf != NULL) {
102699ebb4caSwyllys 		free(outbuf);
102799ebb4caSwyllys 	}
102899ebb4caSwyllys 	if (fp != NULL) {
102999ebb4caSwyllys 		(void) fclose(fp);
103099ebb4caSwyllys 	}
103199ebb4caSwyllys 
103299ebb4caSwyllys 	if (xcert != NULL) {
103399ebb4caSwyllys 		X509_free(xcert);
103499ebb4caSwyllys 	}
103599ebb4caSwyllys 
103699ebb4caSwyllys 	return (ret);
103799ebb4caSwyllys }
103899ebb4caSwyllys 
103999ebb4caSwyllys KMF_RETURN
104099ebb4caSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, KMF_DELETECERT_PARAMS *params)
104199ebb4caSwyllys {
104299ebb4caSwyllys 	KMF_RETURN rv;
104399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
104499ebb4caSwyllys 	char *fullpath = NULL;
104599ebb4caSwyllys 	KMF_DATA certdata = {NULL, 0};
104699ebb4caSwyllys 
104799ebb4caSwyllys 	if (params == NULL) {
104899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
104999ebb4caSwyllys 	}
105099ebb4caSwyllys 
105199ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
105299ebb4caSwyllys 		params->sslparms.certfile);
105399ebb4caSwyllys 
105499ebb4caSwyllys 	if (fullpath == NULL)
105599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
105699ebb4caSwyllys 
105799ebb4caSwyllys 	if (isdir(fullpath)) {
105899ebb4caSwyllys 		DIR *dirp;
105999ebb4caSwyllys 		struct dirent *dp;
106099ebb4caSwyllys 
106199ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
106299ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
106399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
106499ebb4caSwyllys 		}
106599ebb4caSwyllys 
106699ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
106799ebb4caSwyllys 			if (strcmp(dp->d_name, ".") != 0 &&
106899ebb4caSwyllys 			    strcmp(dp->d_name, "..") != 0) {
106999ebb4caSwyllys 				char *fname;
107099ebb4caSwyllys 
107199ebb4caSwyllys 				fname = get_fullpath(fullpath,
107299ebb4caSwyllys 					(char *)&dp->d_name);
107399ebb4caSwyllys 
107499ebb4caSwyllys 				if (fname == NULL) {
107599ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
107699ebb4caSwyllys 					break;
107799ebb4caSwyllys 				}
107899ebb4caSwyllys 
107999ebb4caSwyllys 				rv = kmf_load_cert(kmfh, params, fname,
108099ebb4caSwyllys 				    &certdata);
108199ebb4caSwyllys 
108299ebb4caSwyllys 				if (rv == KMF_ERR_CERT_NOT_FOUND) {
108399ebb4caSwyllys 					free(fname);
108499ebb4caSwyllys 					if (certdata.Data)
108599ebb4caSwyllys 						free(certdata.Data);
108699ebb4caSwyllys 					rv = KMF_OK;
108799ebb4caSwyllys 					continue;
108899ebb4caSwyllys 				} else if (rv != KMF_OK) {
108999ebb4caSwyllys 					free(fname);
109099ebb4caSwyllys 					break;
109199ebb4caSwyllys 				}
109299ebb4caSwyllys 
109399ebb4caSwyllys 				if (unlink(fname) != 0) {
109499ebb4caSwyllys 					SET_SYS_ERROR(kmfh, errno);
109599ebb4caSwyllys 					rv = KMF_ERR_INTERNAL;
109699ebb4caSwyllys 					free(fname);
109799ebb4caSwyllys 					break;
109899ebb4caSwyllys 				}
109999ebb4caSwyllys 				free(fname);
110099ebb4caSwyllys 				if (certdata.Data)
110199ebb4caSwyllys 					free(certdata.Data);
110299ebb4caSwyllys 			}
110399ebb4caSwyllys 		}
110499ebb4caSwyllys 		(void) closedir(dirp);
110599ebb4caSwyllys 	} else {
110699ebb4caSwyllys 		/* Just try to load a single certificate */
110799ebb4caSwyllys 		rv = kmf_load_cert(kmfh, params, fullpath, &certdata);
110899ebb4caSwyllys 		if (rv == KMF_OK) {
110999ebb4caSwyllys 			if (unlink(fullpath) != 0) {
111099ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
111199ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
111299ebb4caSwyllys 			}
111399ebb4caSwyllys 		}
111499ebb4caSwyllys 	}
111599ebb4caSwyllys 
111699ebb4caSwyllys out:
111799ebb4caSwyllys 	if (fullpath != NULL)
111899ebb4caSwyllys 		free(fullpath);
111999ebb4caSwyllys 
112099ebb4caSwyllys 	if (certdata.Data)
112199ebb4caSwyllys 		free(certdata.Data);
112299ebb4caSwyllys 
112399ebb4caSwyllys 	return (rv);
112499ebb4caSwyllys }
112599ebb4caSwyllys 
112699ebb4caSwyllys KMF_RETURN
112799ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
112899ebb4caSwyllys 	KMF_DATA *keydata)
112999ebb4caSwyllys {
113099ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
113199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
113299ebb4caSwyllys 	int n;
113399ebb4caSwyllys 
113499ebb4caSwyllys 	if (key == NULL || keydata == NULL ||
113599ebb4caSwyllys 	    key->keyp == NULL)
113699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
113799ebb4caSwyllys 
113899ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
113999ebb4caSwyllys 		RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
114099ebb4caSwyllys 
114199ebb4caSwyllys 		if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
114299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
114399ebb4caSwyllys 			return (KMF_ERR_ENCODING);
114499ebb4caSwyllys 		}
114599ebb4caSwyllys 		RSA_free(pubkey);
114699ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
114799ebb4caSwyllys 		DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
114899ebb4caSwyllys 
114999ebb4caSwyllys 		if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
115099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
115199ebb4caSwyllys 			return (KMF_ERR_ENCODING);
115299ebb4caSwyllys 		}
115399ebb4caSwyllys 		DSA_free(pubkey);
115499ebb4caSwyllys 	} else {
115599ebb4caSwyllys 	    return (KMF_ERR_BAD_PARAMETER);
115699ebb4caSwyllys 	}
115799ebb4caSwyllys 	keydata->Length = n;
115899ebb4caSwyllys 
115999ebb4caSwyllys cleanup:
116099ebb4caSwyllys 	if (rv != KMF_OK) {
116199ebb4caSwyllys 		if (keydata->Data)
116299ebb4caSwyllys 			free(keydata->Data);
116399ebb4caSwyllys 		keydata->Data = NULL;
116499ebb4caSwyllys 		keydata->Length = 0;
116599ebb4caSwyllys 	}
116699ebb4caSwyllys 
116799ebb4caSwyllys 	return (rv);
116899ebb4caSwyllys }
116999ebb4caSwyllys 
117099ebb4caSwyllys static KMF_RETURN
117199ebb4caSwyllys ssl_write_private_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
117299ebb4caSwyllys 	KMF_CREDENTIAL *cred, EVP_PKEY *pkey)
117399ebb4caSwyllys {
117499ebb4caSwyllys 	int rv = 0;
117599ebb4caSwyllys 	RSA *rsa;
117699ebb4caSwyllys 	DSA *dsa;
117799ebb4caSwyllys 
117899ebb4caSwyllys 	switch (format) {
117999ebb4caSwyllys 		case KMF_FORMAT_ASN1:
118099ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
118199ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
118299ebb4caSwyllys 				rv = i2d_RSAPrivateKey_bio(out, rsa);
118399ebb4caSwyllys 				RSA_free(rsa);
118499ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
118599ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
118699ebb4caSwyllys 				rv = i2d_DSAPrivateKey_bio(out, dsa);
118799ebb4caSwyllys 				DSA_free(dsa);
118899ebb4caSwyllys 			}
118999ebb4caSwyllys 			if (rv == 1) {
119099ebb4caSwyllys 				rv = KMF_OK;
119199ebb4caSwyllys 			} else {
119299ebb4caSwyllys 				SET_ERROR(kmfh, rv);
119399ebb4caSwyllys 			}
119499ebb4caSwyllys 			break;
119599ebb4caSwyllys 		case KMF_FORMAT_PEM:
119699ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
119799ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
119899ebb4caSwyllys 				rv = PEM_write_bio_RSAPrivateKey(out,
119999ebb4caSwyllys 					rsa,
120099ebb4caSwyllys 					NULL /* encryption type */,
120199ebb4caSwyllys 					NULL, 0, NULL,
120299ebb4caSwyllys 					cred->cred);
120399ebb4caSwyllys 				RSA_free(rsa);
120499ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
120599ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
120699ebb4caSwyllys 				rv = PEM_write_bio_DSAPrivateKey(out,
120799ebb4caSwyllys 					dsa,
120899ebb4caSwyllys 					NULL /* encryption type */,
120999ebb4caSwyllys 					NULL, 0, NULL,
121099ebb4caSwyllys 					cred->cred);
121199ebb4caSwyllys 				DSA_free(dsa);
121299ebb4caSwyllys 			}
121399ebb4caSwyllys 
121499ebb4caSwyllys 			if (rv == 1) {
121599ebb4caSwyllys 				rv = KMF_OK;
121699ebb4caSwyllys 			} else {
121799ebb4caSwyllys 				SET_ERROR(kmfh, rv);
121899ebb4caSwyllys 			}
121999ebb4caSwyllys 			break;
122099ebb4caSwyllys 
122199ebb4caSwyllys 		default:
122299ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
122399ebb4caSwyllys 	}
122499ebb4caSwyllys 
122599ebb4caSwyllys 	return (rv);
122699ebb4caSwyllys }
122799ebb4caSwyllys 
122899ebb4caSwyllys KMF_RETURN
122999ebb4caSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, KMF_CREATEKEYPAIR_PARAMS *params,
123099ebb4caSwyllys 	KMF_KEY_HANDLE *privkey, KMF_KEY_HANDLE *pubkey)
123199ebb4caSwyllys {
123299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
123399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
123499ebb4caSwyllys 	int format;
123599ebb4caSwyllys 	uint32_t eValue = 0x010001;
123699ebb4caSwyllys 	RSA *sslPrivKey = NULL;
123799ebb4caSwyllys 	DSA *sslDSAKey = NULL;
123899ebb4caSwyllys 	EVP_PKEY *eprikey = NULL;
123999ebb4caSwyllys 	EVP_PKEY *epubkey = NULL;
124099ebb4caSwyllys 	BIO *out = NULL;
124199ebb4caSwyllys 	char *fullpath = NULL;
124299ebb4caSwyllys 
124399ebb4caSwyllys 	if (params == NULL || params->sslparms.keyfile == NULL) {
124499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
124599ebb4caSwyllys 	}
124699ebb4caSwyllys 
124799ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
124899ebb4caSwyllys 			params->sslparms.keyfile);
124999ebb4caSwyllys 
125099ebb4caSwyllys 	if (fullpath == NULL)
125199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
125299ebb4caSwyllys 
125399ebb4caSwyllys 	/* If the requested file exists, return an error */
125499ebb4caSwyllys 	if (access(fullpath, F_OK) == 0) {
125599ebb4caSwyllys 		free(fullpath);
125699ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
125799ebb4caSwyllys 	}
125899ebb4caSwyllys 
125999ebb4caSwyllys 	eprikey = EVP_PKEY_new();
126099ebb4caSwyllys 	if (eprikey == NULL) {
126199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
126299ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
126399ebb4caSwyllys 		goto cleanup;
126499ebb4caSwyllys 	}
126599ebb4caSwyllys 	epubkey = EVP_PKEY_new();
126699ebb4caSwyllys 	if (epubkey == NULL) {
126799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
126899ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
126999ebb4caSwyllys 		goto cleanup;
127099ebb4caSwyllys 	}
127199ebb4caSwyllys 	if (params->keytype == KMF_RSA) {
127299ebb4caSwyllys 		if (params->rsa_exponent.len > 0 &&
127399ebb4caSwyllys 		    params->rsa_exponent.len <= sizeof (eValue) &&
127499ebb4caSwyllys 		    params->rsa_exponent.val != NULL)
127599ebb4caSwyllys 			/*LINTED*/
127699ebb4caSwyllys 			eValue = *(uint32_t *)params->rsa_exponent.val;
127799ebb4caSwyllys 
127899ebb4caSwyllys 		sslPrivKey = RSA_generate_key(params->keylength, eValue,
127999ebb4caSwyllys 			NULL, NULL);
128099ebb4caSwyllys 		if (sslPrivKey == NULL) {
128199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
128299ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
128399ebb4caSwyllys 		} else {
128499ebb4caSwyllys 			if (privkey != NULL &&
128599ebb4caSwyllys 				EVP_PKEY_set1_RSA(eprikey, sslPrivKey)) {
128699ebb4caSwyllys 				privkey->kstype = KMF_KEYSTORE_OPENSSL;
128799ebb4caSwyllys 				privkey->keyalg = KMF_RSA;
128899ebb4caSwyllys 				privkey->keyclass = KMF_ASYM_PRI;
128999ebb4caSwyllys 				privkey->israw = FALSE;
129099ebb4caSwyllys 				privkey->keylabel = (char *)strdup(fullpath);
129199ebb4caSwyllys 				privkey->keyp = (void *)eprikey;
129299ebb4caSwyllys 			}
129399ebb4caSwyllys 			/* OpenSSL derives the public key from the private */
129499ebb4caSwyllys 			if (pubkey != NULL &&
129599ebb4caSwyllys 				EVP_PKEY_set1_RSA(epubkey, sslPrivKey)) {
129699ebb4caSwyllys 				pubkey->kstype = KMF_KEYSTORE_OPENSSL;
129799ebb4caSwyllys 				pubkey->keyalg = KMF_RSA;
129899ebb4caSwyllys 				pubkey->israw = FALSE;
129999ebb4caSwyllys 				pubkey->keyclass = KMF_ASYM_PUB;
130099ebb4caSwyllys 				pubkey->keylabel = (char *)strdup(fullpath);
130199ebb4caSwyllys 				pubkey->keyp = (void *)epubkey;
130299ebb4caSwyllys 			}
130399ebb4caSwyllys 		}
130499ebb4caSwyllys 	} else if (params->keytype == KMF_DSA) {
130599ebb4caSwyllys 		sslDSAKey = DSA_new();
130699ebb4caSwyllys 		if (sslDSAKey == NULL) {
130799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
130899ebb4caSwyllys 			return (KMF_ERR_MEMORY);
130999ebb4caSwyllys 		}
131099ebb4caSwyllys 
131199ebb4caSwyllys 		if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) ==
131299ebb4caSwyllys 			NULL) {
131399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
131499ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
131599ebb4caSwyllys 			goto cleanup;
131699ebb4caSwyllys 		}
131799ebb4caSwyllys 		if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) ==
131899ebb4caSwyllys 			NULL) {
131999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
132099ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
132199ebb4caSwyllys 			goto cleanup;
132299ebb4caSwyllys 		}
132399ebb4caSwyllys 		if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) ==
132499ebb4caSwyllys 			NULL) {
132599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
132699ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
132799ebb4caSwyllys 			goto cleanup;
132899ebb4caSwyllys 		}
132999ebb4caSwyllys 
133099ebb4caSwyllys 		if (!DSA_generate_key(sslDSAKey)) {
133199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
133299ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
133399ebb4caSwyllys 			goto cleanup;
133499ebb4caSwyllys 		}
133599ebb4caSwyllys 
133699ebb4caSwyllys 		if (privkey != NULL) {
133799ebb4caSwyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
133899ebb4caSwyllys 			privkey->keyalg = KMF_DSA;
133999ebb4caSwyllys 			privkey->keyclass = KMF_ASYM_PRI;
134099ebb4caSwyllys 			privkey->israw = FALSE;
134199ebb4caSwyllys 			privkey->keylabel = (char *)strdup(fullpath);
134299ebb4caSwyllys 			if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
134399ebb4caSwyllys 				privkey->keyp = (void *)eprikey;
134499ebb4caSwyllys 			} else {
134599ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
134699ebb4caSwyllys 				rv = KMF_ERR_KEYGEN_FAILED;
134799ebb4caSwyllys 				goto cleanup;
134899ebb4caSwyllys 			}
134999ebb4caSwyllys 		}
135099ebb4caSwyllys 		if (pubkey != NULL) {
135199ebb4caSwyllys 			DSA *dp = DSA_new();
135299ebb4caSwyllys 			/* Make a copy for the public key */
135399ebb4caSwyllys 			if (dp != NULL) {
135499ebb4caSwyllys 				if ((dp->p = BN_new()) == NULL) {
135599ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
135699ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
135799ebb4caSwyllys 					DSA_free(dp);
135899ebb4caSwyllys 					goto cleanup;
135999ebb4caSwyllys 				}
136099ebb4caSwyllys 				if ((dp->q = BN_new()) == NULL) {
136199ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
136299ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
136399ebb4caSwyllys 					BN_free(dp->p);
136499ebb4caSwyllys 					DSA_free(dp);
136599ebb4caSwyllys 					goto cleanup;
136699ebb4caSwyllys 				}
136799ebb4caSwyllys 				if ((dp->g = BN_new()) == NULL) {
136899ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
136999ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
137099ebb4caSwyllys 					BN_free(dp->q);
137199ebb4caSwyllys 					BN_free(dp->p);
137299ebb4caSwyllys 					DSA_free(dp);
137399ebb4caSwyllys 					goto cleanup;
137499ebb4caSwyllys 				}
137599ebb4caSwyllys 				if ((dp->pub_key = BN_new()) == NULL) {
137699ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
137799ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
137899ebb4caSwyllys 					BN_free(dp->q);
137999ebb4caSwyllys 					BN_free(dp->p);
138099ebb4caSwyllys 					BN_free(dp->g);
138199ebb4caSwyllys 					DSA_free(dp);
138299ebb4caSwyllys 					goto cleanup;
138399ebb4caSwyllys 				}
138499ebb4caSwyllys 				(void) BN_copy(dp->p, sslDSAKey->p);
138599ebb4caSwyllys 				(void) BN_copy(dp->q, sslDSAKey->q);
138699ebb4caSwyllys 				(void) BN_copy(dp->g, sslDSAKey->g);
138799ebb4caSwyllys 				(void) BN_copy(dp->pub_key, sslDSAKey->pub_key);
138899ebb4caSwyllys 
138999ebb4caSwyllys 				pubkey->kstype = KMF_KEYSTORE_OPENSSL;
139099ebb4caSwyllys 				pubkey->keyalg = KMF_DSA;
139199ebb4caSwyllys 				pubkey->keyclass = KMF_ASYM_PUB;
139299ebb4caSwyllys 				pubkey->israw = FALSE;
139399ebb4caSwyllys 				pubkey->keylabel = (char *)strdup(fullpath);
139499ebb4caSwyllys 
139599ebb4caSwyllys 				if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
139699ebb4caSwyllys 					pubkey->keyp = (void *)epubkey;
139799ebb4caSwyllys 				} else {
139899ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
139999ebb4caSwyllys 					rv = KMF_ERR_KEYGEN_FAILED;
140099ebb4caSwyllys 					goto cleanup;
140199ebb4caSwyllys 				}
140299ebb4caSwyllys 			}
140399ebb4caSwyllys 		}
140499ebb4caSwyllys 	}
140599ebb4caSwyllys 
140699ebb4caSwyllys 	if (rv != KMF_OK) {
140799ebb4caSwyllys 		goto cleanup;
140899ebb4caSwyllys 	}
140999ebb4caSwyllys 
141099ebb4caSwyllys 	/* Store the private key to the keyfile */
141199ebb4caSwyllys 	format = params->sslparms.format;
141299ebb4caSwyllys 	out = BIO_new_file(fullpath, "wb");
141399ebb4caSwyllys 	if (out == NULL) {
141499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
141599ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
141699ebb4caSwyllys 		goto cleanup;
141799ebb4caSwyllys 	}
141899ebb4caSwyllys 	rv = ssl_write_private_key(kmfh, format, out, &params->cred, eprikey);
141999ebb4caSwyllys 
142099ebb4caSwyllys cleanup:
142199ebb4caSwyllys 	if (rv != KMF_OK) {
142299ebb4caSwyllys 		if (eprikey != NULL)
142399ebb4caSwyllys 			EVP_PKEY_free(eprikey);
142499ebb4caSwyllys 
142599ebb4caSwyllys 		if (epubkey != NULL)
142699ebb4caSwyllys 			EVP_PKEY_free(epubkey);
142799ebb4caSwyllys 
142899ebb4caSwyllys 		if (pubkey->keylabel) {
142999ebb4caSwyllys 			free(pubkey->keylabel);
143099ebb4caSwyllys 			pubkey->keylabel = NULL;
143199ebb4caSwyllys 		}
143299ebb4caSwyllys 
143399ebb4caSwyllys 		if (privkey->keylabel) {
143499ebb4caSwyllys 			free(privkey->keylabel);
143599ebb4caSwyllys 			privkey->keylabel = NULL;
143699ebb4caSwyllys 		}
143799ebb4caSwyllys 
143899ebb4caSwyllys 		pubkey->keyp = NULL;
143999ebb4caSwyllys 		privkey->keyp = NULL;
144099ebb4caSwyllys 	}
144199ebb4caSwyllys 
144299ebb4caSwyllys 	if (sslPrivKey)
144399ebb4caSwyllys 		RSA_free(sslPrivKey);
144499ebb4caSwyllys 
144599ebb4caSwyllys 	if (sslDSAKey)
144699ebb4caSwyllys 		DSA_free(sslDSAKey);
144799ebb4caSwyllys 
144899ebb4caSwyllys 
144999ebb4caSwyllys 	if (out != NULL)
145099ebb4caSwyllys 		(void) BIO_free(out);
145199ebb4caSwyllys 
145299ebb4caSwyllys 	if (fullpath)
145399ebb4caSwyllys 		free(fullpath);
145499ebb4caSwyllys 
145599ebb4caSwyllys 	/* Protect the file by making it read-only */
145699ebb4caSwyllys 	if (rv == KMF_OK) {
145799ebb4caSwyllys 		(void) chmod(fullpath, 0400);
145899ebb4caSwyllys 	}
145999ebb4caSwyllys 	return (rv);
146099ebb4caSwyllys }
146199ebb4caSwyllys 
146299ebb4caSwyllys KMF_RETURN
146399ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
146499ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
146599ebb4caSwyllys {
146699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
146799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
146899ebb4caSwyllys 	KMF_ALGORITHM_INDEX		AlgId;
146999ebb4caSwyllys 	EVP_MD_CTX ctx;
147099ebb4caSwyllys 	const EVP_MD *md;
147199ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
147299ebb4caSwyllys 		tobesigned == NULL || output == NULL ||
147399ebb4caSwyllys 		tobesigned->Data == NULL ||
147499ebb4caSwyllys 		output->Data == NULL)
147599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
147699ebb4caSwyllys 
147799ebb4caSwyllys 	/* Map the OID to an OpenSSL algorithm */
147899ebb4caSwyllys 	AlgId = X509_AlgorithmOidToAlgId(AlgOID);
147999ebb4caSwyllys 	if (AlgId == KMF_ALGID_NONE)
148099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
148199ebb4caSwyllys 
148299ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
148399ebb4caSwyllys 		EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
148499ebb4caSwyllys 		uchar_t *p;
148599ebb4caSwyllys 		uint32_t len;
148699ebb4caSwyllys 		if (AlgId == KMF_ALGID_MD5WithRSA)
148799ebb4caSwyllys 			md = EVP_md5();
148899ebb4caSwyllys 		else if (AlgId == KMF_ALGID_MD2WithRSA)
148999ebb4caSwyllys 			md = EVP_md2();
149099ebb4caSwyllys 		else if (AlgId == KMF_ALGID_SHA1WithRSA)
149199ebb4caSwyllys 			md = EVP_sha1();
149299ebb4caSwyllys 		else
149399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
149499ebb4caSwyllys 
149599ebb4caSwyllys 		if (md == NULL) {
149699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
149799ebb4caSwyllys 			return (KMF_ERR_MEMORY);
149899ebb4caSwyllys 		}
149999ebb4caSwyllys 
150099ebb4caSwyllys 		(void) EVP_MD_CTX_init(&ctx);
150199ebb4caSwyllys 		(void) EVP_SignInit_ex(&ctx, md, NULL);
150299ebb4caSwyllys 		(void) EVP_SignUpdate(&ctx, tobesigned->Data,
150399ebb4caSwyllys 			(uint32_t)tobesigned->Length);
150499ebb4caSwyllys 		len = (uint32_t)output->Length;
150599ebb4caSwyllys 		p = output->Data;
150699ebb4caSwyllys 		if (!EVP_SignFinal(&ctx, p, &len, pkey)) {
150799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
150899ebb4caSwyllys 			output->Length = 0;
150999ebb4caSwyllys 		}
151099ebb4caSwyllys 		output->Length = len;
151199ebb4caSwyllys 		(void) EVP_MD_CTX_cleanup(&ctx);
151299ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
151399ebb4caSwyllys 		DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
151499ebb4caSwyllys 
151599ebb4caSwyllys 		uchar_t hash[EVP_MAX_MD_SIZE];
151699ebb4caSwyllys 		uint32_t hashlen;
151799ebb4caSwyllys 		DSA_SIG *dsasig;
151899ebb4caSwyllys 
151999ebb4caSwyllys 		/*
152099ebb4caSwyllys 		 * OpenSSL EVP_Sign operation automatically converts to
152199ebb4caSwyllys 		 * ASN.1 output so we do the operations separately so we
152299ebb4caSwyllys 		 * are assured of NOT getting ASN.1 output returned.
152399ebb4caSwyllys 		 * KMF does not want ASN.1 encoded results because
152499ebb4caSwyllys 		 * not all mechanisms return ASN.1 encodings (PKCS#11
152599ebb4caSwyllys 		 * and NSS return raw signature data).
152699ebb4caSwyllys 		 */
152799ebb4caSwyllys 		md = EVP_sha1();
152899ebb4caSwyllys 		EVP_MD_CTX_init(&ctx);
152999ebb4caSwyllys 		(void) EVP_DigestInit_ex(&ctx, md, NULL);
153099ebb4caSwyllys 		(void) EVP_DigestUpdate(&ctx, tobesigned->Data,
153199ebb4caSwyllys 			tobesigned->Length);
153299ebb4caSwyllys 		(void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
153399ebb4caSwyllys 		(void) EVP_MD_CTX_cleanup(&ctx);
153499ebb4caSwyllys 
153599ebb4caSwyllys 		dsasig = DSA_do_sign(hash, hashlen, dsa);
153699ebb4caSwyllys 		if (dsasig != NULL) {
153799ebb4caSwyllys 			int i;
153899ebb4caSwyllys 			output->Length = i = BN_bn2bin(dsasig->r, output->Data);
153999ebb4caSwyllys 			output->Length += BN_bn2bin(dsasig->s,
154099ebb4caSwyllys 				&output->Data[i]);
154199ebb4caSwyllys 			DSA_SIG_free(dsasig);
154299ebb4caSwyllys 		} else {
154399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
154499ebb4caSwyllys 		}
154599ebb4caSwyllys 	} else {
154699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
154799ebb4caSwyllys 	}
154899ebb4caSwyllys cleanup:
154999ebb4caSwyllys 	return (ret);
155099ebb4caSwyllys }
155199ebb4caSwyllys 
155299ebb4caSwyllys KMF_RETURN
155399ebb4caSwyllys /*ARGSUSED*/
155499ebb4caSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle, KMF_DELETEKEY_PARAMS *params,
155599ebb4caSwyllys 	KMF_KEY_HANDLE *key, boolean_t destroy)
155699ebb4caSwyllys {
155799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
155899ebb4caSwyllys 	if (key == NULL || key->keyp == NULL)
155999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
156099ebb4caSwyllys 
156199ebb4caSwyllys 	if (key->keyclass != KMF_ASYM_PUB &&
156299ebb4caSwyllys 		key->keyclass != KMF_ASYM_PRI &&
156399ebb4caSwyllys 		key->keyclass != KMF_SYMMETRIC)
156499ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
156599ebb4caSwyllys 
156699ebb4caSwyllys 	if (key->keyclass == KMF_SYMMETRIC) {
156799ebb4caSwyllys 		KMF_FreeRawSymKey((KMF_RAW_SYM_KEY *)key->keyp);
156899ebb4caSwyllys 		key->keyp = NULL;
156999ebb4caSwyllys 	} else {
157099ebb4caSwyllys 		if (key->keyp != NULL) {
157199ebb4caSwyllys 			EVP_PKEY_free(key->keyp);
157299ebb4caSwyllys 			key->keyp = NULL;
157399ebb4caSwyllys 		}
157499ebb4caSwyllys 	}
157599ebb4caSwyllys 
157699ebb4caSwyllys 	if (key->keylabel != NULL) {
157799ebb4caSwyllys 		EVP_PKEY *pkey = NULL;
157899ebb4caSwyllys 		/* If the file exists, make sure it is a proper key. */
157999ebb4caSwyllys 		pkey = openssl_load_key(handle, key->keylabel);
158099ebb4caSwyllys 		if (pkey == NULL) {
158199ebb4caSwyllys 			free(key->keylabel);
158299ebb4caSwyllys 			key->keylabel = NULL;
158399ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
158499ebb4caSwyllys 		}
158599ebb4caSwyllys 		EVP_PKEY_free(pkey);
158699ebb4caSwyllys 
158799ebb4caSwyllys 		if (destroy) {
158899ebb4caSwyllys 			if (unlink(key->keylabel) != 0) {
158999ebb4caSwyllys 				KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
159099ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
159199ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
159299ebb4caSwyllys 			}
159399ebb4caSwyllys 		}
159499ebb4caSwyllys 		if (key->keylabel != NULL) {
159599ebb4caSwyllys 			free(key->keylabel);
159699ebb4caSwyllys 			key->keylabel = NULL;
159799ebb4caSwyllys 		}
159899ebb4caSwyllys 	}
159999ebb4caSwyllys 	return (rv);
160099ebb4caSwyllys }
160199ebb4caSwyllys 
160299ebb4caSwyllys KMF_RETURN
160399ebb4caSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, KMF_IMPORTCRL_PARAMS *params)
160499ebb4caSwyllys {
160599ebb4caSwyllys 	KMF_RETURN 	ret = KMF_OK;
160699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
160799ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
160899ebb4caSwyllys 	X509		*xcert = NULL;
160999ebb4caSwyllys 	EVP_PKEY	*pkey;
161099ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
161199ebb4caSwyllys 	BIO *in = NULL, *out = NULL;
161299ebb4caSwyllys 	int openssl_ret = 0;
161399ebb4caSwyllys 	char *outcrlfile = NULL;
161499ebb4caSwyllys 	KMF_ENCODE_FORMAT outformat;
161599ebb4caSwyllys 
161699ebb4caSwyllys 	if (params == NULL || params->sslparms.crlfile == NULL) {
161799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
161899ebb4caSwyllys 	}
161999ebb4caSwyllys 
162099ebb4caSwyllys 	if (params->sslparms.crl_check == B_TRUE &&
162199ebb4caSwyllys 	    params->sslparms.certfile == NULL) {
162299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
162399ebb4caSwyllys 	}
162499ebb4caSwyllys 
162599ebb4caSwyllys 	outcrlfile = get_fullpath(params->sslparms.dirpath,
162699ebb4caSwyllys 		params->sslparms.outcrlfile);
162799ebb4caSwyllys 
162899ebb4caSwyllys 	if (outcrlfile == NULL)
162999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
163099ebb4caSwyllys 
163199ebb4caSwyllys 	if (isdir(outcrlfile)) {
163299ebb4caSwyllys 		free(outcrlfile);
163399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
163499ebb4caSwyllys 	}
163599ebb4caSwyllys 
163699ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, params->sslparms.crlfile, &format);
163799ebb4caSwyllys 	if (ret != KMF_OK) {
163899ebb4caSwyllys 		free(outcrlfile);
163999ebb4caSwyllys 		return (ret);
164099ebb4caSwyllys 	}
164199ebb4caSwyllys 
164299ebb4caSwyllys 	in = BIO_new_file(params->sslparms.crlfile, "rb");
164399ebb4caSwyllys 	if (in == NULL)	{
164499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
164599ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
164699ebb4caSwyllys 		goto end;
164799ebb4caSwyllys 	}
164899ebb4caSwyllys 
164999ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
165099ebb4caSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
165199ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
165299ebb4caSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
165399ebb4caSwyllys 	}
165499ebb4caSwyllys 
165599ebb4caSwyllys 	if (xcrl == NULL) {
165699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
165799ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
165899ebb4caSwyllys 		goto end;
165999ebb4caSwyllys 	}
166099ebb4caSwyllys 
166199ebb4caSwyllys 	/* If bypasscheck is specified, no need to verify. */
166299ebb4caSwyllys 	if (params->sslparms.crl_check == B_FALSE) {
166399ebb4caSwyllys 		goto output;
166499ebb4caSwyllys 	}
166599ebb4caSwyllys 
166699ebb4caSwyllys 	ret = KMF_IsCertFile(handle, params->sslparms.certfile, &format);
166799ebb4caSwyllys 	if (ret != KMF_OK)
166899ebb4caSwyllys 		goto end;
166999ebb4caSwyllys 
167099ebb4caSwyllys 	/* Read in the CA cert file and convert to X509 */
167199ebb4caSwyllys 	if (BIO_read_filename(in, params->sslparms.certfile) <= 0) {
167299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
167399ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
167499ebb4caSwyllys 		goto end;
167599ebb4caSwyllys 	}
167699ebb4caSwyllys 
167799ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
167899ebb4caSwyllys 		xcert = d2i_X509_bio(in, NULL);
167999ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
168099ebb4caSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
168199ebb4caSwyllys 	} else {
168299ebb4caSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
168399ebb4caSwyllys 		goto end;
168499ebb4caSwyllys 	}
168599ebb4caSwyllys 
168699ebb4caSwyllys 	if (xcert == NULL) {
168799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
168899ebb4caSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
168999ebb4caSwyllys 		goto end;
169099ebb4caSwyllys 	}
169199ebb4caSwyllys 	/* Now get the public key from the CA cert */
169299ebb4caSwyllys 	pkey = X509_get_pubkey(xcert);
169399ebb4caSwyllys 	if (!pkey) {
169499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
169599ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
169699ebb4caSwyllys 		goto end;
169799ebb4caSwyllys 	}
169899ebb4caSwyllys 
169999ebb4caSwyllys 	/* Verify the CRL with the CA's public key */
170099ebb4caSwyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
170199ebb4caSwyllys 	EVP_PKEY_free(pkey);
170299ebb4caSwyllys 	if (openssl_ret > 0) {
170399ebb4caSwyllys 		ret = KMF_OK;  /* verify succeed */
170499ebb4caSwyllys 	} else {
170599ebb4caSwyllys 		SET_ERROR(kmfh, openssl_ret);
170699ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
170799ebb4caSwyllys 	}
170899ebb4caSwyllys 
170999ebb4caSwyllys output:
171099ebb4caSwyllys 	outformat = params->sslparms.format;
171199ebb4caSwyllys 
171299ebb4caSwyllys 	out = BIO_new_file(outcrlfile, "wb");
171399ebb4caSwyllys 	if (out == NULL) {
171499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
171599ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
171699ebb4caSwyllys 		goto end;
171799ebb4caSwyllys 	}
171899ebb4caSwyllys 
171999ebb4caSwyllys 	if (outformat == KMF_FORMAT_ASN1) {
172099ebb4caSwyllys 		openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
172199ebb4caSwyllys 	} else if (outformat == KMF_FORMAT_PEM) {
172299ebb4caSwyllys 		openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
172399ebb4caSwyllys 	} else {
172499ebb4caSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
172599ebb4caSwyllys 		goto end;
172699ebb4caSwyllys 	}
172799ebb4caSwyllys 
172899ebb4caSwyllys 	if (openssl_ret <= 0) {
172999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
173099ebb4caSwyllys 		ret = KMF_ERR_WRITE_FILE;
173199ebb4caSwyllys 	} else {
173299ebb4caSwyllys 		ret = KMF_OK;
173399ebb4caSwyllys 	}
173499ebb4caSwyllys 
173599ebb4caSwyllys end:
173699ebb4caSwyllys 	if (xcrl != NULL)
173799ebb4caSwyllys 		X509_CRL_free(xcrl);
173899ebb4caSwyllys 
173999ebb4caSwyllys 	if (xcert != NULL)
174099ebb4caSwyllys 		X509_free(xcert);
174199ebb4caSwyllys 
174299ebb4caSwyllys 	if (in != NULL)
174399ebb4caSwyllys 		(void) BIO_free(in);
174499ebb4caSwyllys 
174599ebb4caSwyllys 	if (out != NULL)
174699ebb4caSwyllys 		(void) BIO_free(out);
174799ebb4caSwyllys 
174899ebb4caSwyllys 	if (outcrlfile != NULL)
174999ebb4caSwyllys 		free(outcrlfile);
175099ebb4caSwyllys 
175199ebb4caSwyllys 	return (ret);
175299ebb4caSwyllys }
175399ebb4caSwyllys 
175499ebb4caSwyllys KMF_RETURN
175599ebb4caSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, KMF_LISTCRL_PARAMS *params,
175699ebb4caSwyllys     char **crldata)
175799ebb4caSwyllys {
175899ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
175999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
176099ebb4caSwyllys 	X509_CRL   *x = NULL;
176199ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
176299ebb4caSwyllys 	char *crlfile = NULL;
176399ebb4caSwyllys 	BIO *in = NULL;
176499ebb4caSwyllys 	BIO *mem = NULL;
176599ebb4caSwyllys 	long len;
176699ebb4caSwyllys 	char *memptr;
176799ebb4caSwyllys 	char *data = NULL;
176899ebb4caSwyllys 
176999ebb4caSwyllys 	if (params == NULL || params->sslparms.crlfile == NULL) {
177099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
177199ebb4caSwyllys 	}
177299ebb4caSwyllys 
177399ebb4caSwyllys 	crlfile = get_fullpath(params->sslparms.dirpath,
177499ebb4caSwyllys 		params->sslparms.crlfile);
177599ebb4caSwyllys 
177699ebb4caSwyllys 	if (crlfile == NULL)
177799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
177899ebb4caSwyllys 
177999ebb4caSwyllys 	if (isdir(crlfile)) {
178099ebb4caSwyllys 		free(crlfile);
178199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
178299ebb4caSwyllys 	}
178399ebb4caSwyllys 
178499ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, crlfile, &format);
178599ebb4caSwyllys 	if (ret != KMF_OK) {
178699ebb4caSwyllys 		free(crlfile);
178799ebb4caSwyllys 		return (ret);
178899ebb4caSwyllys 	}
178999ebb4caSwyllys 
179099ebb4caSwyllys 	if (bio_err == NULL)
179199ebb4caSwyllys 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
179299ebb4caSwyllys 
179399ebb4caSwyllys 	in = BIO_new_file(crlfile, "rb");
179499ebb4caSwyllys 	if (in == NULL)	{
179599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
179699ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
179799ebb4caSwyllys 		goto end;
179899ebb4caSwyllys 	}
179999ebb4caSwyllys 
180099ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
180199ebb4caSwyllys 		x = d2i_X509_CRL_bio(in, NULL);
180299ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
180399ebb4caSwyllys 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
180499ebb4caSwyllys 	}
180599ebb4caSwyllys 
180699ebb4caSwyllys 	if (x == NULL) { /* should not happen */
180799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
180899ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
180999ebb4caSwyllys 		goto end;
181099ebb4caSwyllys 	}
181199ebb4caSwyllys 
181299ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
181399ebb4caSwyllys 	if (mem == NULL) {
181499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
181599ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
181699ebb4caSwyllys 		goto end;
181799ebb4caSwyllys 	}
181899ebb4caSwyllys 
181999ebb4caSwyllys 	(void) X509_CRL_print(mem, x);
182099ebb4caSwyllys 	len = BIO_get_mem_data(mem, &memptr);
182199ebb4caSwyllys 	if (len <= 0) {
182299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
182399ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
182499ebb4caSwyllys 		goto end;
182599ebb4caSwyllys 	}
182699ebb4caSwyllys 
182799ebb4caSwyllys 	data = malloc(len + 1);
182899ebb4caSwyllys 	if (data == NULL) {
182999ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
183099ebb4caSwyllys 		goto end;
183199ebb4caSwyllys 	}
183299ebb4caSwyllys 
183399ebb4caSwyllys 	(void) memcpy(data, memptr, len);
183499ebb4caSwyllys 	data[len] = '\0';
183599ebb4caSwyllys 	*crldata = data;
183699ebb4caSwyllys 
183799ebb4caSwyllys end:
183899ebb4caSwyllys 	if (x != NULL)
183999ebb4caSwyllys 		X509_CRL_free(x);
184099ebb4caSwyllys 
184199ebb4caSwyllys 	if (crlfile != NULL)
184299ebb4caSwyllys 		free(crlfile);
184399ebb4caSwyllys 
184499ebb4caSwyllys 	if (in != NULL)
184599ebb4caSwyllys 		(void) BIO_free(in);
184699ebb4caSwyllys 
184799ebb4caSwyllys 	if (mem != NULL)
184899ebb4caSwyllys 		(void) BIO_free(mem);
184999ebb4caSwyllys 
185099ebb4caSwyllys 	return (ret);
185199ebb4caSwyllys }
185299ebb4caSwyllys 
185399ebb4caSwyllys KMF_RETURN
185499ebb4caSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, KMF_DELETECRL_PARAMS *params)
185599ebb4caSwyllys {
185699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
185799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
185899ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
185999ebb4caSwyllys 	char *crlfile = NULL;
186099ebb4caSwyllys 	BIO *in = NULL;
186199ebb4caSwyllys 
186299ebb4caSwyllys 	if (params == NULL || params->sslparms.crlfile == NULL) {
186399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
186499ebb4caSwyllys 	}
186599ebb4caSwyllys 
186699ebb4caSwyllys 	crlfile = get_fullpath(params->sslparms.dirpath,
186799ebb4caSwyllys 		params->sslparms.crlfile);
186899ebb4caSwyllys 
186999ebb4caSwyllys 	if (crlfile == NULL)
187099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
187199ebb4caSwyllys 
187299ebb4caSwyllys 	if (isdir(crlfile)) {
187399ebb4caSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
187499ebb4caSwyllys 		goto end;
187599ebb4caSwyllys 	}
187699ebb4caSwyllys 
187799ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, crlfile, &format);
187899ebb4caSwyllys 	if (ret != KMF_OK)
187999ebb4caSwyllys 		goto end;
188099ebb4caSwyllys 
188199ebb4caSwyllys 	if (unlink(crlfile) != 0) {
188299ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
188399ebb4caSwyllys 		ret = KMF_ERR_INTERNAL;
188499ebb4caSwyllys 		goto end;
188599ebb4caSwyllys 	}
188699ebb4caSwyllys 
188799ebb4caSwyllys end:
188899ebb4caSwyllys 	if (in != NULL)
188999ebb4caSwyllys 		(void) BIO_free(in);
189099ebb4caSwyllys 	if (crlfile != NULL)
189199ebb4caSwyllys 		free(crlfile);
189299ebb4caSwyllys 
189399ebb4caSwyllys 	return (ret);
189499ebb4caSwyllys }
189599ebb4caSwyllys 
189699ebb4caSwyllys 
189799ebb4caSwyllys KMF_RETURN
189899ebb4caSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, KMF_FINDCERTINCRL_PARAMS *params)
189999ebb4caSwyllys {
190099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
190199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
190299ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
190399ebb4caSwyllys 	BIO *in = NULL;
190499ebb4caSwyllys 	X509   *xcert = NULL;
190599ebb4caSwyllys 	X509_CRL   *xcrl = NULL;
190699ebb4caSwyllys 	STACK_OF(X509_REVOKED) *revoke_stack = NULL;
190799ebb4caSwyllys 	X509_REVOKED *revoke;
190899ebb4caSwyllys 	int i;
190999ebb4caSwyllys 
191099ebb4caSwyllys 	if (params == NULL || params->sslparms.crlfile == NULL ||
191199ebb4caSwyllys 	    params->sslparms.certfile == NULL) {
191299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
191399ebb4caSwyllys 	}
191499ebb4caSwyllys 
191599ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, params->sslparms.crlfile, &format);
191699ebb4caSwyllys 	if (ret != KMF_OK)
191799ebb4caSwyllys 		return (ret);
191899ebb4caSwyllys 
191999ebb4caSwyllys 	/* Read the CRL file and load it into a X509_CRL structure */
192099ebb4caSwyllys 	in = BIO_new_file(params->sslparms.crlfile, "rb");
192199ebb4caSwyllys 	if (in == NULL)	{
192299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
192399ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
192499ebb4caSwyllys 		goto end;
192599ebb4caSwyllys 	}
192699ebb4caSwyllys 
192799ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
192899ebb4caSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
192999ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
193099ebb4caSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
193199ebb4caSwyllys 	}
193299ebb4caSwyllys 
193399ebb4caSwyllys 	if (xcrl == NULL) {
193499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
193599ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
193699ebb4caSwyllys 		goto end;
193799ebb4caSwyllys 	}
193899ebb4caSwyllys 	(void) BIO_free(in);
193999ebb4caSwyllys 
194099ebb4caSwyllys 	/* Read the Certificate file and load it into a X509 structure */
194199ebb4caSwyllys 	ret = KMF_IsCertFile(handle, params->sslparms.certfile, &format);
194299ebb4caSwyllys 	if (ret != KMF_OK)
194399ebb4caSwyllys 		goto end;
194499ebb4caSwyllys 
194599ebb4caSwyllys 	in = BIO_new_file(params->sslparms.certfile, "rb");
194699ebb4caSwyllys 	if (in == NULL)	{
194799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
194899ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
194999ebb4caSwyllys 		goto end;
195099ebb4caSwyllys 	}
195199ebb4caSwyllys 
195299ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
195399ebb4caSwyllys 		xcert = d2i_X509_bio(in, NULL);
195499ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
195599ebb4caSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
195699ebb4caSwyllys 	}
195799ebb4caSwyllys 
195899ebb4caSwyllys 	if (xcert == NULL) {
195999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
196099ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
196199ebb4caSwyllys 		goto end;
196299ebb4caSwyllys 	}
196399ebb4caSwyllys 
196499ebb4caSwyllys 	/* Check if the certificate and the CRL have same issuer */
196599ebb4caSwyllys 	if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) {
196699ebb4caSwyllys 		ret = KMF_ERR_ISSUER;
196799ebb4caSwyllys 		goto end;
196899ebb4caSwyllys 	}
196999ebb4caSwyllys 
197099ebb4caSwyllys 	/* Check to see if the certificate serial number is revoked */
197199ebb4caSwyllys 	revoke_stack = X509_CRL_get_REVOKED(xcrl);
197299ebb4caSwyllys 	if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
197399ebb4caSwyllys 		/* No revoked certificates in the CRL file */
197499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
197599ebb4caSwyllys 		ret = KMF_ERR_EMPTY_CRL;
197699ebb4caSwyllys 		goto end;
197799ebb4caSwyllys 	}
197899ebb4caSwyllys 
197999ebb4caSwyllys 	for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
198099ebb4caSwyllys 		/*LINTED*/
198199ebb4caSwyllys 		revoke = sk_X509_REVOKED_value(revoke_stack, i);
198299ebb4caSwyllys 		if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber,
198399ebb4caSwyllys 		    revoke->serialNumber) == 0) {
198499ebb4caSwyllys 			break;
198599ebb4caSwyllys 		}
198699ebb4caSwyllys 	}
198799ebb4caSwyllys 
198899ebb4caSwyllys 	if (i < sk_X509_REVOKED_num(revoke_stack)) {
198999ebb4caSwyllys 		ret = KMF_OK;
199099ebb4caSwyllys 	} else {
199199ebb4caSwyllys 		ret = KMF_ERR_NOT_REVOKED;
199299ebb4caSwyllys 	}
199399ebb4caSwyllys 
199499ebb4caSwyllys end:
199599ebb4caSwyllys 	if (in != NULL)
199699ebb4caSwyllys 		(void) BIO_free(in);
199799ebb4caSwyllys 	if (xcrl != NULL)
199899ebb4caSwyllys 		X509_CRL_free(xcrl);
199999ebb4caSwyllys 	if (xcert != NULL)
200099ebb4caSwyllys 		X509_free(xcert);
200199ebb4caSwyllys 
200299ebb4caSwyllys 	return (ret);
200399ebb4caSwyllys }
200499ebb4caSwyllys 
200599ebb4caSwyllys KMF_RETURN
200699ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
200799ebb4caSwyllys {
200899ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
200999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
201099ebb4caSwyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
201199ebb4caSwyllys 
201299ebb4caSwyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
201399ebb4caSwyllys 	if (strlen(str)) {
201499ebb4caSwyllys 		*msgstr = (char *)strdup(str);
201599ebb4caSwyllys 		if ((*msgstr) == NULL)
201699ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
201799ebb4caSwyllys 	} else {
201899ebb4caSwyllys 		*msgstr = NULL;
201999ebb4caSwyllys 	}
202099ebb4caSwyllys 
202199ebb4caSwyllys 	return (ret);
202299ebb4caSwyllys }
202399ebb4caSwyllys 
202499ebb4caSwyllys static int
202599ebb4caSwyllys ext2NID(int kmfext)
202699ebb4caSwyllys {
202799ebb4caSwyllys 	switch (kmfext) {
202899ebb4caSwyllys 		case KMF_X509_EXT_KEY_USAGE:
202999ebb4caSwyllys 			return (NID_key_usage);
203099ebb4caSwyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
203199ebb4caSwyllys 			return (NID_private_key_usage_period);
203299ebb4caSwyllys 		case KMF_X509_EXT_CERT_POLICIES:
203399ebb4caSwyllys 			return (NID_certificate_policies);
203499ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
203599ebb4caSwyllys 			return (NID_subject_alt_name);
203699ebb4caSwyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
203799ebb4caSwyllys 			return (NID_issuer_alt_name);
203899ebb4caSwyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
203999ebb4caSwyllys 			return (NID_basic_constraints);
204099ebb4caSwyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
204199ebb4caSwyllys 			return (NID_ext_key_usage);
204299ebb4caSwyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
204399ebb4caSwyllys 			return (NID_authority_key_identifier);
204499ebb4caSwyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
204599ebb4caSwyllys 			return (NID_crl_distribution_points);
204699ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
204799ebb4caSwyllys 			return (NID_subject_key_identifier);
204899ebb4caSwyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
204999ebb4caSwyllys 			return (OBJ_sn2nid("policyMappings"));
205099ebb4caSwyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
205199ebb4caSwyllys 			return (OBJ_sn2nid("nameConstraints"));
205299ebb4caSwyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
205399ebb4caSwyllys 			return (OBJ_sn2nid("policyConstraints"));
205499ebb4caSwyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
205599ebb4caSwyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
205699ebb4caSwyllys 		case KMF_X509_EXT_FRESHEST_CRL:
205799ebb4caSwyllys 			return (OBJ_sn2nid("freshestCRL"));
205899ebb4caSwyllys 		default:
205999ebb4caSwyllys 			return (NID_undef);
206099ebb4caSwyllys 	}
206199ebb4caSwyllys }
206299ebb4caSwyllys 
206399ebb4caSwyllys KMF_RETURN
206499ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
206599ebb4caSwyllys 	KMF_PRINTABLE_ITEM flag, char *resultStr)
206699ebb4caSwyllys {
206799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
206899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
206999ebb4caSwyllys 	X509 *xcert = NULL;
207099ebb4caSwyllys 	unsigned char *outbuf = NULL;
207199ebb4caSwyllys 	unsigned char *outbuf_p;
207299ebb4caSwyllys 	char *tmpstr = NULL;
207399ebb4caSwyllys 	int j;
207499ebb4caSwyllys 	int ext_index, nid, len;
207599ebb4caSwyllys 	BIO *mem = NULL;
207699ebb4caSwyllys 	STACK *emlst = NULL;
207799ebb4caSwyllys 	X509_EXTENSION *ex;
207899ebb4caSwyllys 	X509_CINF *ci;
207999ebb4caSwyllys 
208099ebb4caSwyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
208199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
208299ebb4caSwyllys 	}
208399ebb4caSwyllys 
208499ebb4caSwyllys 	/* copy cert data to outbuf */
208599ebb4caSwyllys 	outbuf = malloc(pcert->Length);
208699ebb4caSwyllys 	if (outbuf == NULL) {
208799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
208899ebb4caSwyllys 	}
208999ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
209099ebb4caSwyllys 
209199ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
209299ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
209399ebb4caSwyllys 	if (xcert == NULL) {
209499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
209599ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
209699ebb4caSwyllys 		goto out;
209799ebb4caSwyllys 	}
209899ebb4caSwyllys 
209999ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
210099ebb4caSwyllys 	if (mem == NULL) {
210199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
210299ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
210399ebb4caSwyllys 		goto out;
210499ebb4caSwyllys 	}
210599ebb4caSwyllys 
210699ebb4caSwyllys 	switch (flag) {
210799ebb4caSwyllys 	case KMF_CERT_ISSUER:
210899ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
210999ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
211099ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
211199ebb4caSwyllys 		break;
211299ebb4caSwyllys 
211399ebb4caSwyllys 	case KMF_CERT_SUBJECT:
211499ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
211599ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
211699ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
211799ebb4caSwyllys 		break;
211899ebb4caSwyllys 
211999ebb4caSwyllys 	case KMF_CERT_VERSION:
212099ebb4caSwyllys 		tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version);
212199ebb4caSwyllys 		(void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN);
212299ebb4caSwyllys 		OPENSSL_free(tmpstr);
212399ebb4caSwyllys 		len = strlen(resultStr);
212499ebb4caSwyllys 		break;
212599ebb4caSwyllys 
212699ebb4caSwyllys 	case KMF_CERT_SERIALNUM:
212799ebb4caSwyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
212899ebb4caSwyllys 			(void) strcpy(resultStr, "0x");
212999ebb4caSwyllys 			len = BIO_gets(mem, &resultStr[2],
213099ebb4caSwyllys 				KMF_CERT_PRINTABLE_LEN - 2);
213199ebb4caSwyllys 		}
213299ebb4caSwyllys 		break;
213399ebb4caSwyllys 
213499ebb4caSwyllys 	case KMF_CERT_NOTBEFORE:
213599ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notBefore(xcert));
213699ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
213799ebb4caSwyllys 		break;
213899ebb4caSwyllys 
213999ebb4caSwyllys 	case KMF_CERT_NOTAFTER:
214099ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notAfter(xcert));
214199ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
214299ebb4caSwyllys 		break;
214399ebb4caSwyllys 
214499ebb4caSwyllys 	case KMF_CERT_PUBKEY_DATA:
214599ebb4caSwyllys 		{
214699ebb4caSwyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
214799ebb4caSwyllys 			if (pkey == NULL) {
214899ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
214999ebb4caSwyllys 				ret = KMF_ERR_ENCODING;
215099ebb4caSwyllys 				goto out;
215199ebb4caSwyllys 			}
215299ebb4caSwyllys 
215399ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
215499ebb4caSwyllys 				(void) BIO_printf(mem,
215599ebb4caSwyllys 					"RSA Public Key: (%d bit)\n",
215699ebb4caSwyllys 					BN_num_bits(pkey->pkey.rsa->n));
215799ebb4caSwyllys 				(void) RSA_print(mem, pkey->pkey.rsa, 0);
215899ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
215999ebb4caSwyllys 				(void) BIO_printf(mem,
216099ebb4caSwyllys 					"%12sDSA Public Key:\n", "");
216199ebb4caSwyllys 				(void) DSA_print(mem, pkey->pkey.dsa, 0);
216299ebb4caSwyllys 			} else {
216399ebb4caSwyllys 				(void) BIO_printf(mem,
216499ebb4caSwyllys 					"%12sUnknown Public Key:\n", "");
216599ebb4caSwyllys 			}
216699ebb4caSwyllys 			(void) BIO_printf(mem, "\n");
216799ebb4caSwyllys 			EVP_PKEY_free(pkey);
216899ebb4caSwyllys 		}
216999ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
217099ebb4caSwyllys 		break;
217199ebb4caSwyllys 	case KMF_CERT_SIGNATURE_ALG:
217299ebb4caSwyllys 	case KMF_CERT_PUBKEY_ALG:
217399ebb4caSwyllys 		if (flag == KMF_CERT_SIGNATURE_ALG) {
217499ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
217599ebb4caSwyllys 				xcert->sig_alg->algorithm);
217699ebb4caSwyllys 		} else {
217799ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
217899ebb4caSwyllys 				xcert->cert_info->key->algor->algorithm);
217999ebb4caSwyllys 		}
218099ebb4caSwyllys 
218199ebb4caSwyllys 		if (len > 0) {
218299ebb4caSwyllys 			len = BIO_read(mem, resultStr,
218399ebb4caSwyllys 				KMF_CERT_PRINTABLE_LEN);
218499ebb4caSwyllys 		}
218599ebb4caSwyllys 		break;
218699ebb4caSwyllys 
218799ebb4caSwyllys 	case KMF_CERT_EMAIL:
218899ebb4caSwyllys 		emlst = X509_get1_email(xcert);
218999ebb4caSwyllys 		for (j = 0; j < sk_num(emlst); j++)
219099ebb4caSwyllys 			(void) BIO_printf(mem, "%s\n", sk_value(emlst, j));
219199ebb4caSwyllys 
219299ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
219399ebb4caSwyllys 		X509_email_free(emlst);
219499ebb4caSwyllys 		break;
219599ebb4caSwyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
219699ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
219799ebb4caSwyllys 	case KMF_X509_EXT_KEY_USAGE:
219899ebb4caSwyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
219999ebb4caSwyllys 	case KMF_X509_EXT_CERT_POLICIES:
220099ebb4caSwyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
220199ebb4caSwyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
220299ebb4caSwyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
220399ebb4caSwyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
220499ebb4caSwyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
220599ebb4caSwyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
220699ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
220799ebb4caSwyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
220899ebb4caSwyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
220999ebb4caSwyllys 	case KMF_X509_EXT_FRESHEST_CRL:
221099ebb4caSwyllys 		nid = ext2NID(flag);
221199ebb4caSwyllys 		if (nid == NID_undef) {
221299ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
221399ebb4caSwyllys 			goto out;
221499ebb4caSwyllys 		}
221599ebb4caSwyllys 		ci = xcert->cert_info;
221699ebb4caSwyllys 
221799ebb4caSwyllys 		ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1);
221899ebb4caSwyllys 		if (ext_index == -1) {
221999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
222099ebb4caSwyllys 
222199ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
222299ebb4caSwyllys 			goto out;
222399ebb4caSwyllys 		}
222499ebb4caSwyllys 		ex = X509v3_get_ext(ci->extensions, ext_index);
222599ebb4caSwyllys 
222699ebb4caSwyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
222799ebb4caSwyllys 
222899ebb4caSwyllys 		if (BIO_printf(mem, ": %s\n",
222999ebb4caSwyllys 			X509_EXTENSION_get_critical(ex) ? "critical" : "") <=
223099ebb4caSwyllys 			0) {
223199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
223299ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
223399ebb4caSwyllys 			goto out;
223499ebb4caSwyllys 		}
223599ebb4caSwyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
223699ebb4caSwyllys 			(void) BIO_printf(mem, "%*s", 4, "");
223799ebb4caSwyllys 			(void) M_ASN1_OCTET_STRING_print(mem, ex->value);
223899ebb4caSwyllys 		}
223999ebb4caSwyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
224099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
224199ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
224299ebb4caSwyllys 			goto out;
224399ebb4caSwyllys 		}
224499ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
224599ebb4caSwyllys 	}
224699ebb4caSwyllys 	if (len <= 0) {
224799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
224899ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
224999ebb4caSwyllys 	}
225099ebb4caSwyllys 
225199ebb4caSwyllys out:
225299ebb4caSwyllys 	if (outbuf != NULL) {
225399ebb4caSwyllys 		free(outbuf);
225499ebb4caSwyllys 	}
225599ebb4caSwyllys 
225699ebb4caSwyllys 	if (xcert != NULL) {
225799ebb4caSwyllys 		X509_free(xcert);
225899ebb4caSwyllys 	}
225999ebb4caSwyllys 
226099ebb4caSwyllys 	if (mem != NULL) {
226199ebb4caSwyllys 		(void) BIO_free(mem);
226299ebb4caSwyllys 	}
226399ebb4caSwyllys 
226499ebb4caSwyllys 	return (ret);
226599ebb4caSwyllys }
226699ebb4caSwyllys KMF_RETURN
226799ebb4caSwyllys /*ARGSUSED*/
226899ebb4caSwyllys OpenSSL_GetPrikeyByCert(KMF_HANDLE_T handle,
226999ebb4caSwyllys 	KMF_CRYPTOWITHCERT_PARAMS *params,
227099ebb4caSwyllys 	KMF_DATA *SignerCertData, KMF_KEY_HANDLE *key,
227199ebb4caSwyllys 	KMF_KEY_ALG keytype)
227299ebb4caSwyllys {
227399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
227499ebb4caSwyllys 	KMF_FINDKEY_PARAMS fkparms;
227599ebb4caSwyllys 	uint32_t numkeys = 0;
227699ebb4caSwyllys 
227799ebb4caSwyllys 	if (params == NULL && params->sslparms.keyfile == NULL)
227899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
227999ebb4caSwyllys 
228099ebb4caSwyllys 	/*
228199ebb4caSwyllys 	 * This is really just a FindKey operation, reuse the
228299ebb4caSwyllys 	 * FindKey function.
228399ebb4caSwyllys 	 */
228499ebb4caSwyllys 	(void *)memset(&fkparms, 0, sizeof (fkparms));
228599ebb4caSwyllys 	fkparms.kstype = KMF_KEYSTORE_OPENSSL;
228699ebb4caSwyllys 	fkparms.keyclass = KMF_ASYM_PRI;
228799ebb4caSwyllys 	fkparms.keytype = keytype;
228899ebb4caSwyllys 	fkparms.format = params->format;
228999ebb4caSwyllys 	fkparms.sslparms = params->sslparms;
229099ebb4caSwyllys 
229199ebb4caSwyllys 	rv = OpenSSL_FindKey(handle, &fkparms, key, &numkeys);
229299ebb4caSwyllys 
229399ebb4caSwyllys 	return (rv);
229499ebb4caSwyllys }
229599ebb4caSwyllys 
229699ebb4caSwyllys KMF_RETURN
229799ebb4caSwyllys /*ARGSUSED*/
229899ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
229999ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
230099ebb4caSwyllys 	KMF_DATA *output)
230199ebb4caSwyllys {
230299ebb4caSwyllys 	KMF_RETURN		ret = KMF_OK;
230399ebb4caSwyllys 	RSA *rsa = NULL;
230499ebb4caSwyllys 	unsigned int in_len = 0, out_len = 0;
230599ebb4caSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
230699ebb4caSwyllys 	uint8_t *in_data, *out_data;
230799ebb4caSwyllys 	int i, blocks;
230899ebb4caSwyllys 
230999ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
231099ebb4caSwyllys 	    ciphertext == NULL || output == NULL ||
231199ebb4caSwyllys 	    ciphertext->Data == NULL ||
231299ebb4caSwyllys 	    output->Data == NULL)
231399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
231499ebb4caSwyllys 
231599ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
231699ebb4caSwyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
231799ebb4caSwyllys 		modulus_len = RSA_size(rsa);
231899ebb4caSwyllys 	} else {
231999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
232099ebb4caSwyllys 	}
232199ebb4caSwyllys 
232299ebb4caSwyllys 	blocks = ciphertext->Length/modulus_len;
232399ebb4caSwyllys 	out_data = output->Data;
232499ebb4caSwyllys 	in_data = ciphertext->Data;
232599ebb4caSwyllys 	out_len = modulus_len - 11;
232699ebb4caSwyllys 	in_len = modulus_len;
232799ebb4caSwyllys 
232899ebb4caSwyllys 	for (i = 0; i < blocks; i++) {
232999ebb4caSwyllys 		out_len  = RSA_private_decrypt(in_len,
233099ebb4caSwyllys 			in_data, out_data, rsa, RSA_PKCS1_PADDING);
233199ebb4caSwyllys 
233299ebb4caSwyllys 		if (out_len == 0) {
233399ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
233499ebb4caSwyllys 			goto cleanup;
233599ebb4caSwyllys 		}
233699ebb4caSwyllys 
233799ebb4caSwyllys 		out_data += out_len;
233899ebb4caSwyllys 		total_decrypted += out_len;
233999ebb4caSwyllys 		in_data += in_len;
234099ebb4caSwyllys 	}
234199ebb4caSwyllys 
234299ebb4caSwyllys 	output->Length = total_decrypted;
234399ebb4caSwyllys 
234499ebb4caSwyllys cleanup:
234599ebb4caSwyllys 	RSA_free(rsa);
234699ebb4caSwyllys 	if (ret != KMF_OK)
234799ebb4caSwyllys 		output->Length = 0;
234899ebb4caSwyllys 
234999ebb4caSwyllys 	return (ret);
235099ebb4caSwyllys 
235199ebb4caSwyllys }
235299ebb4caSwyllys 
235399ebb4caSwyllys /*
235499ebb4caSwyllys  *  This function will create a certid from issuer_cert and user_cert.
235599ebb4caSwyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
235699ebb4caSwyllys  *  certid memory after use.
235799ebb4caSwyllys  */
235899ebb4caSwyllys static KMF_RETURN
235999ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
236099ebb4caSwyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
236199ebb4caSwyllys {
236299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
236399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
236499ebb4caSwyllys 	X509   *issuer = NULL;
236599ebb4caSwyllys 	X509   *cert = NULL;
236699ebb4caSwyllys 	unsigned char *ptmp;
236799ebb4caSwyllys 
236899ebb4caSwyllys 	if (issuer_cert == NULL || user_cert == NULL) {
236999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
237099ebb4caSwyllys 	}
237199ebb4caSwyllys 
237299ebb4caSwyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
237399ebb4caSwyllys 	ptmp = issuer_cert->Data;
237499ebb4caSwyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
237599ebb4caSwyllys 		issuer_cert->Length);
237699ebb4caSwyllys 	if (issuer == NULL) {
237799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
237899ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
237999ebb4caSwyllys 		goto end;
238099ebb4caSwyllys 	}
238199ebb4caSwyllys 
238299ebb4caSwyllys 	/* convert the DER-encoded user cert to an internal X509 */
238399ebb4caSwyllys 	ptmp = user_cert->Data;
238499ebb4caSwyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
238599ebb4caSwyllys 		user_cert->Length);
238699ebb4caSwyllys 	if (cert == NULL) {
238799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
238899ebb4caSwyllys 
238999ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
239099ebb4caSwyllys 		goto end;
239199ebb4caSwyllys 	}
239299ebb4caSwyllys 
239399ebb4caSwyllys 	/* create a CERTID */
239499ebb4caSwyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
239599ebb4caSwyllys 	if (*certid == NULL) {
239699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
239799ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
239899ebb4caSwyllys 		goto end;
239999ebb4caSwyllys 	}
240099ebb4caSwyllys 
240199ebb4caSwyllys end:
240299ebb4caSwyllys 	if (issuer != NULL) {
240399ebb4caSwyllys 		X509_free(issuer);
240499ebb4caSwyllys 	}
240599ebb4caSwyllys 
240699ebb4caSwyllys 	if (cert != NULL) {
240799ebb4caSwyllys 		X509_free(cert);
240899ebb4caSwyllys 	}
240999ebb4caSwyllys 
241099ebb4caSwyllys 	return (ret);
241199ebb4caSwyllys }
241299ebb4caSwyllys 
241399ebb4caSwyllys KMF_RETURN
241499ebb4caSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle, KMF_OCSPREQUEST_PARAMS *params,
241599ebb4caSwyllys     char *reqfile)
241699ebb4caSwyllys {
241799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
241899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
241999ebb4caSwyllys 	OCSP_CERTID *id = NULL;
242099ebb4caSwyllys 	OCSP_REQUEST *req = NULL;
242199ebb4caSwyllys 	BIO *derbio = NULL;
242299ebb4caSwyllys 
242399ebb4caSwyllys 	if (params->user_cert == NULL || params->issuer_cert == NULL ||
242499ebb4caSwyllys 	    reqfile == NULL) {
242599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
242699ebb4caSwyllys 	}
242799ebb4caSwyllys 
242899ebb4caSwyllys 	ret = create_certid(handle, params->issuer_cert, params->user_cert,
242999ebb4caSwyllys 	    &id);
243099ebb4caSwyllys 	if (ret != KMF_OK) {
243199ebb4caSwyllys 		return (ret);
243299ebb4caSwyllys 	}
243399ebb4caSwyllys 
243499ebb4caSwyllys 	/* Create an OCSP request */
243599ebb4caSwyllys 	req = OCSP_REQUEST_new();
243699ebb4caSwyllys 	if (req == NULL) {
243799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
243899ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
243999ebb4caSwyllys 		goto end;
244099ebb4caSwyllys 	}
244199ebb4caSwyllys 
244299ebb4caSwyllys 	if (!OCSP_request_add0_id(req, id)) {
244399ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
244499ebb4caSwyllys 		goto end;
244599ebb4caSwyllys 	}
244699ebb4caSwyllys 
244799ebb4caSwyllys 	/* Write the request to the output file with DER encoding */
244899ebb4caSwyllys 	derbio = BIO_new_file(reqfile, "wb");
244999ebb4caSwyllys 	if (!derbio) {
245099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
245199ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
245299ebb4caSwyllys 		goto end;
245399ebb4caSwyllys 	}
245499ebb4caSwyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
245599ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
245699ebb4caSwyllys 	}
245799ebb4caSwyllys 
245899ebb4caSwyllys end:
245999ebb4caSwyllys 	/*
246099ebb4caSwyllys 	 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
246199ebb4caSwyllys 	 * will deallocate certid's space also.
246299ebb4caSwyllys 	 */
246399ebb4caSwyllys 	if (req != NULL) {
246499ebb4caSwyllys 		OCSP_REQUEST_free(req);
246599ebb4caSwyllys 	}
246699ebb4caSwyllys 
246799ebb4caSwyllys 	if (derbio != NULL) {
246899ebb4caSwyllys 		(void) BIO_free(derbio);
246999ebb4caSwyllys 	}
247099ebb4caSwyllys 
247199ebb4caSwyllys 	return (ret);
247299ebb4caSwyllys }
247399ebb4caSwyllys 
247499ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */
247599ebb4caSwyllys static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
247699ebb4caSwyllys {
247799ebb4caSwyllys 	int i;
247899ebb4caSwyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
247999ebb4caSwyllys 
248099ebb4caSwyllys 	/* Easy if lookup by name */
248199ebb4caSwyllys 	if (id->type == V_OCSP_RESPID_NAME)
248299ebb4caSwyllys 		return (X509_find_by_subject(certs, id->value.byName));
248399ebb4caSwyllys 
248499ebb4caSwyllys 	/* Lookup by key hash */
248599ebb4caSwyllys 
248699ebb4caSwyllys 	/* If key hash isn't SHA1 length then forget it */
248799ebb4caSwyllys 	if (id->value.byKey->length != SHA_DIGEST_LENGTH)
248899ebb4caSwyllys 		return (NULL);
248999ebb4caSwyllys 
249099ebb4caSwyllys 	keyhash = id->value.byKey->data;
249199ebb4caSwyllys 	/* Calculate hash of each key and compare */
249299ebb4caSwyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
249399ebb4caSwyllys 		/*LINTED*/
249499ebb4caSwyllys 		X509 *x = sk_X509_value(certs, i);
249599ebb4caSwyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
249699ebb4caSwyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
249799ebb4caSwyllys 			return (x);
249899ebb4caSwyllys 	}
249999ebb4caSwyllys 	return (NULL);
250099ebb4caSwyllys }
250199ebb4caSwyllys 
250299ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */
250399ebb4caSwyllys /*ARGSUSED*/
250499ebb4caSwyllys static int
250599ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
250699ebb4caSwyllys     X509_STORE *st, unsigned long flags)
250799ebb4caSwyllys {
250899ebb4caSwyllys 	X509 *signer;
250999ebb4caSwyllys 	OCSP_RESPID *rid = bs->tbsResponseData->responderId;
251099ebb4caSwyllys 	if ((signer = ocsp_find_signer_sk(certs, rid)))	{
251199ebb4caSwyllys 		*psigner = signer;
251299ebb4caSwyllys 		return (2);
251399ebb4caSwyllys 	}
251499ebb4caSwyllys 	if (!(flags & OCSP_NOINTERN) &&
251599ebb4caSwyllys 	    (signer = ocsp_find_signer_sk(bs->certs, rid))) {
251699ebb4caSwyllys 		*psigner = signer;
251799ebb4caSwyllys 		return (1);
251899ebb4caSwyllys 	}
251999ebb4caSwyllys 	/* Maybe lookup from store if by subject name */
252099ebb4caSwyllys 
252199ebb4caSwyllys 	*psigner = NULL;
252299ebb4caSwyllys 	return (0);
252399ebb4caSwyllys }
252499ebb4caSwyllys 
252599ebb4caSwyllys /*
252699ebb4caSwyllys  * This function will verify the signature of a basic response, using
252799ebb4caSwyllys  * the public key from the OCSP responder certificate.
252899ebb4caSwyllys  */
252999ebb4caSwyllys static KMF_RETURN
253099ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
253199ebb4caSwyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
253299ebb4caSwyllys {
253399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
253499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
253599ebb4caSwyllys 	STACK_OF(X509) *cert_stack = NULL;
253699ebb4caSwyllys 	X509 *signer = NULL;
253799ebb4caSwyllys 	X509 *issuer = NULL;
253899ebb4caSwyllys 	EVP_PKEY *skey = NULL;
253999ebb4caSwyllys 	unsigned char *ptmp;
254099ebb4caSwyllys 
254199ebb4caSwyllys 
254299ebb4caSwyllys 	if (bs == NULL || issuer_cert == NULL)
254399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
254499ebb4caSwyllys 
254599ebb4caSwyllys 	/*
254699ebb4caSwyllys 	 * Find the certificate that signed the basic response.
254799ebb4caSwyllys 	 *
254899ebb4caSwyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
254999ebb4caSwyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
255099ebb4caSwyllys 	 * If we still do not find a signer, we will look for it from the
255199ebb4caSwyllys 	 * certificate list came with the response file.
255299ebb4caSwyllys 	 */
255399ebb4caSwyllys 	if (signer_cert != NULL) {
255499ebb4caSwyllys 		ptmp = signer_cert->Data;
255599ebb4caSwyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
255699ebb4caSwyllys 		    signer_cert->Length);
255799ebb4caSwyllys 		if (signer == NULL) {
255899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
255999ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
256099ebb4caSwyllys 			goto end;
256199ebb4caSwyllys 		}
256299ebb4caSwyllys 	} else {
256399ebb4caSwyllys 		/*
256499ebb4caSwyllys 		 * Convert the issuer cert into X509 and push it into a
256599ebb4caSwyllys 		 * stack to be used by ocsp_find_signer().
256699ebb4caSwyllys 		 */
256799ebb4caSwyllys 		ptmp = issuer_cert->Data;
256899ebb4caSwyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
256999ebb4caSwyllys 			issuer_cert->Length);
257099ebb4caSwyllys 		if (issuer == NULL) {
257199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
257299ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
257399ebb4caSwyllys 			goto end;
257499ebb4caSwyllys 		}
257599ebb4caSwyllys 
257699ebb4caSwyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
257799ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
257899ebb4caSwyllys 			goto end;
257999ebb4caSwyllys 		}
258099ebb4caSwyllys 
258199ebb4caSwyllys 		if (sk_X509_push(cert_stack, issuer) == NULL) {
258299ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
258399ebb4caSwyllys 			goto end;
258499ebb4caSwyllys 		}
258599ebb4caSwyllys 
258699ebb4caSwyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
258799ebb4caSwyllys 		if (!ret) {
258899ebb4caSwyllys 			/* can not find the signer */
258999ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
259099ebb4caSwyllys 			goto end;
259199ebb4caSwyllys 		}
259299ebb4caSwyllys 	}
259399ebb4caSwyllys 
259499ebb4caSwyllys 	/* Verify the signature of the response */
259599ebb4caSwyllys 	skey = X509_get_pubkey(signer);
259699ebb4caSwyllys 	if (skey == NULL) {
259799ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
259899ebb4caSwyllys 		goto end;
259999ebb4caSwyllys 	}
260099ebb4caSwyllys 
260199ebb4caSwyllys 	ret = OCSP_BASICRESP_verify(bs, skey, 0);
260299ebb4caSwyllys 	if (ret == 0) {
260399ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
260499ebb4caSwyllys 		goto end;
260599ebb4caSwyllys 	}
260699ebb4caSwyllys 
260799ebb4caSwyllys end:
260899ebb4caSwyllys 	if (issuer != NULL) {
260999ebb4caSwyllys 		X509_free(issuer);
261099ebb4caSwyllys 	}
261199ebb4caSwyllys 
261299ebb4caSwyllys 	if (signer != NULL) {
261399ebb4caSwyllys 		X509_free(signer);
261499ebb4caSwyllys 	}
261599ebb4caSwyllys 
261699ebb4caSwyllys 	if (skey != NULL) {
261799ebb4caSwyllys 		EVP_PKEY_free(skey);
261899ebb4caSwyllys 	}
261999ebb4caSwyllys 
262099ebb4caSwyllys 	if (cert_stack != NULL) {
262199ebb4caSwyllys 		sk_X509_free(cert_stack);
262299ebb4caSwyllys 	}
262399ebb4caSwyllys 
262499ebb4caSwyllys 	return (ret);
262599ebb4caSwyllys }
262699ebb4caSwyllys 
262799ebb4caSwyllys 
262899ebb4caSwyllys 
262999ebb4caSwyllys KMF_RETURN
263099ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
263199ebb4caSwyllys     KMF_OCSPRESPONSE_PARAMS_INPUT *params_in,
263299ebb4caSwyllys     KMF_OCSPRESPONSE_PARAMS_OUTPUT *params_out)
263399ebb4caSwyllys {
263499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
263599ebb4caSwyllys 	BIO *derbio = NULL;
263699ebb4caSwyllys 	OCSP_RESPONSE *resp = NULL;
263799ebb4caSwyllys 	OCSP_BASICRESP *bs = NULL;
263899ebb4caSwyllys 	OCSP_CERTID *id = NULL;
263999ebb4caSwyllys 	OCSP_SINGLERESP *single = NULL;
264099ebb4caSwyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
264199ebb4caSwyllys 	int index, status, reason;
264299ebb4caSwyllys 
264399ebb4caSwyllys 	if (params_in == NULL || params_in->issuer_cert == NULL ||
264499ebb4caSwyllys 	    params_in->user_cert == NULL || params_in->response == NULL) {
264599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
264699ebb4caSwyllys 	}
264799ebb4caSwyllys 
264899ebb4caSwyllys 	if (params_out == NULL) {
264999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
265099ebb4caSwyllys 	}
265199ebb4caSwyllys 
265299ebb4caSwyllys 	/* Read in the response */
265399ebb4caSwyllys 	derbio = BIO_new_mem_buf(params_in->response->Data,
265499ebb4caSwyllys 	    params_in->response->Length);
265599ebb4caSwyllys 	if (!derbio) {
265699ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
265799ebb4caSwyllys 		return (ret);
265899ebb4caSwyllys 	}
265999ebb4caSwyllys 
266099ebb4caSwyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
266199ebb4caSwyllys 	if (resp == NULL) {
266299ebb4caSwyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
266399ebb4caSwyllys 		goto end;
266499ebb4caSwyllys 	}
266599ebb4caSwyllys 
266699ebb4caSwyllys 	/* Check the response status */
266799ebb4caSwyllys 	status = OCSP_response_status(resp);
266899ebb4caSwyllys 	params_out->response_status = status;
266999ebb4caSwyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
267099ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
267199ebb4caSwyllys 		goto end;
267299ebb4caSwyllys 	}
267399ebb4caSwyllys 
267499ebb4caSwyllys #ifdef DEBUG
267599ebb4caSwyllys 	printf("Successfully checked the response file status.\n");
267699ebb4caSwyllys #endif /* DEBUG */
267799ebb4caSwyllys 
267899ebb4caSwyllys 	/* Extract basic response */
267999ebb4caSwyllys 	bs = OCSP_response_get1_basic(resp);
268099ebb4caSwyllys 	if (bs == NULL) {
268199ebb4caSwyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
268299ebb4caSwyllys 		goto end;
268399ebb4caSwyllys 	}
268499ebb4caSwyllys 
268599ebb4caSwyllys #ifdef DEBUG
268699ebb4caSwyllys 	printf("Successfully retrieved the basic response.\n");
268799ebb4caSwyllys #endif /* DEBUG */
268899ebb4caSwyllys 
268999ebb4caSwyllys 	/* Check the basic response signature if required */
269099ebb4caSwyllys 	if (params_in->ignore_response_sign == B_FALSE) {
269199ebb4caSwyllys 		ret = check_response_signature(handle, bs,
269299ebb4caSwyllys 		    params_in->signer_cert, params_in->issuer_cert);
269399ebb4caSwyllys 		if (ret != KMF_OK)
269499ebb4caSwyllys 			goto end;
269599ebb4caSwyllys 	}
269699ebb4caSwyllys 
269799ebb4caSwyllys #ifdef DEBUG
269899ebb4caSwyllys 	printf("Successfully verified the response signature.\n");
269999ebb4caSwyllys #endif /* DEBUG */
270099ebb4caSwyllys 
270199ebb4caSwyllys 	/* Create a certid for the certificate in question */
270299ebb4caSwyllys 	ret = create_certid(handle, params_in->issuer_cert,
270399ebb4caSwyllys 	    params_in->user_cert, &id);
270499ebb4caSwyllys 	if (ret != KMF_OK) {
270599ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
270699ebb4caSwyllys 		goto end;
270799ebb4caSwyllys 	}
270899ebb4caSwyllys 
270999ebb4caSwyllys #ifdef DEBUG
271099ebb4caSwyllys 	printf("successfully created a certid for the cert.\n");
271199ebb4caSwyllys #endif /* DEBUG */
271299ebb4caSwyllys 
271399ebb4caSwyllys 	/* Find the index of the single response for the certid */
271499ebb4caSwyllys 	index = OCSP_resp_find(bs, id, -1);
271599ebb4caSwyllys 	if (index < 0) {
271699ebb4caSwyllys 		/* cound not find this certificate in the response */
271799ebb4caSwyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
271899ebb4caSwyllys 		goto end;
271999ebb4caSwyllys 	}
272099ebb4caSwyllys 
272199ebb4caSwyllys #ifdef DEBUG
272299ebb4caSwyllys 	printf("Successfully found the single response index for the cert.\n");
272399ebb4caSwyllys #endif /* DEBUG */
272499ebb4caSwyllys 
272599ebb4caSwyllys 	/* Retrieve the single response and get the cert status */
272699ebb4caSwyllys 	single = OCSP_resp_get0(bs, index);
272799ebb4caSwyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
272899ebb4caSwyllys 	    &nextupd);
272999ebb4caSwyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
273099ebb4caSwyllys 		params_out->cert_status = OCSP_GOOD;
273199ebb4caSwyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
273299ebb4caSwyllys 		params_out->cert_status = OCSP_UNKNOWN;
273399ebb4caSwyllys 	} else { /* revoked */
273499ebb4caSwyllys 		params_out->cert_status = OCSP_REVOKED;
273599ebb4caSwyllys 		params_out->reason = reason;
273699ebb4caSwyllys 	}
273799ebb4caSwyllys 	ret = KMF_OK;
273899ebb4caSwyllys 
273999ebb4caSwyllys 	/* Verify the time */
274099ebb4caSwyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
274199ebb4caSwyllys 	    params_in->response_lifetime)) {
274299ebb4caSwyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
274399ebb4caSwyllys 		goto end;
274499ebb4caSwyllys 	}
274599ebb4caSwyllys 
274699ebb4caSwyllys #ifdef DEBUG
274799ebb4caSwyllys 	printf("Successfully verify the time.\n");
274899ebb4caSwyllys #endif /* DEBUG */
274999ebb4caSwyllys 
275099ebb4caSwyllys end:
275199ebb4caSwyllys 	if (derbio != NULL)
275299ebb4caSwyllys 		(void) BIO_free(derbio);
275399ebb4caSwyllys 
275499ebb4caSwyllys 	if (resp != NULL)
275599ebb4caSwyllys 		OCSP_RESPONSE_free(resp);
275699ebb4caSwyllys 
275799ebb4caSwyllys 	if (bs != NULL)
275899ebb4caSwyllys 		OCSP_BASICRESP_free(bs);
275999ebb4caSwyllys 
276099ebb4caSwyllys 	if (id != NULL)
276199ebb4caSwyllys 		OCSP_CERTID_free(id);
276299ebb4caSwyllys 
276399ebb4caSwyllys 	return (ret);
276499ebb4caSwyllys }
276599ebb4caSwyllys 
276699ebb4caSwyllys static KMF_RETURN
276799ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path,
276899ebb4caSwyllys 	KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
276999ebb4caSwyllys {
277099ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
277199ebb4caSwyllys 	EVP_PKEY *pkey;
277299ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
277399ebb4caSwyllys 
277499ebb4caSwyllys 	/* Make sure the requested file actually exists. */
277599ebb4caSwyllys 	if (access(path, F_OK) != 0) {
277699ebb4caSwyllys 		return (KMF_ERR_KEY_NOT_FOUND);
277799ebb4caSwyllys 	}
277899ebb4caSwyllys 
277999ebb4caSwyllys 	if (keyclass == KMF_ASYM_PRI ||
278099ebb4caSwyllys 	    keyclass == KMF_ASYM_PUB) {
278199ebb4caSwyllys 		pkey = openssl_load_key(handle, path);
278299ebb4caSwyllys 		if (pkey == NULL) {
278399ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
278499ebb4caSwyllys 		}
278599ebb4caSwyllys 		if (key != NULL) {
278699ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA)
278799ebb4caSwyllys 				key->keyalg = KMF_RSA;
278899ebb4caSwyllys 			else if (pkey->type == EVP_PKEY_DSA)
278999ebb4caSwyllys 				key->keyalg = KMF_DSA;
279099ebb4caSwyllys 
279199ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
279299ebb4caSwyllys 			key->keyclass = keyclass;
279399ebb4caSwyllys 			key->keyp = (void *)pkey;
279499ebb4caSwyllys 			key->israw = FALSE;
279599ebb4caSwyllys 			key->keylabel = path;
279699ebb4caSwyllys 		} else {
279799ebb4caSwyllys 			EVP_PKEY_free(pkey);
279899ebb4caSwyllys 			pkey = NULL;
279999ebb4caSwyllys 		}
280099ebb4caSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
280199ebb4caSwyllys 		KMF_ENCODE_FORMAT fmt;
280299ebb4caSwyllys 		/*
280399ebb4caSwyllys 		 * If the file is a recognized format,
280499ebb4caSwyllys 		 * then it is NOT a symmetric key.
280599ebb4caSwyllys 		 */
280699ebb4caSwyllys 		rv = KMF_GetFileFormat(path, &fmt);
280799ebb4caSwyllys 		if (rv == KMF_OK || fmt != 0) {
280899ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
280999ebb4caSwyllys 		} else if (rv == KMF_ERR_ENCODING) {
281099ebb4caSwyllys 			/*
281199ebb4caSwyllys 			 * If we don't know the encoding,
281299ebb4caSwyllys 			 * it is probably  a symmetric key.
281399ebb4caSwyllys 			 */
281499ebb4caSwyllys 			rv = KMF_OK;
281599ebb4caSwyllys 		}
281699ebb4caSwyllys 
281799ebb4caSwyllys 		if (key != NULL) {
281899ebb4caSwyllys 			KMF_DATA keyvalue;
281999ebb4caSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
282099ebb4caSwyllys 			if (rkey == NULL) {
282199ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
282299ebb4caSwyllys 				goto out;
282399ebb4caSwyllys 			}
282499ebb4caSwyllys 
282599ebb4caSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
282699ebb4caSwyllys 			rv = KMF_ReadInputFile(handle, path, &keyvalue);
282799ebb4caSwyllys 			if (rv != KMF_OK)
282899ebb4caSwyllys 				goto out;
282999ebb4caSwyllys 
283099ebb4caSwyllys 			rkey->keydata.len = keyvalue.Length;
283199ebb4caSwyllys 			rkey->keydata.val = keyvalue.Data;
283299ebb4caSwyllys 
283399ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
283499ebb4caSwyllys 			key->keyclass = keyclass;
283599ebb4caSwyllys 			key->israw = TRUE;
283699ebb4caSwyllys 			key->keylabel = path;
283799ebb4caSwyllys 			key->keyp = (void *)rkey;
283899ebb4caSwyllys 		}
283999ebb4caSwyllys 	}
284099ebb4caSwyllys out:
284199ebb4caSwyllys 	if (rv != KMF_OK) {
284299ebb4caSwyllys 		if (rkey != NULL) {
284399ebb4caSwyllys 			KMF_FreeRawSymKey(rkey);
284499ebb4caSwyllys 		}
284599ebb4caSwyllys 		if (pkey != NULL)
284699ebb4caSwyllys 			EVP_PKEY_free(pkey);
284799ebb4caSwyllys 
284899ebb4caSwyllys 		if (key != NULL) {
284999ebb4caSwyllys 			key->keyalg = KMF_KEYALG_NONE;
285099ebb4caSwyllys 			key->keyclass = KMF_KEYCLASS_NONE;
285199ebb4caSwyllys 			key->keyp = NULL;
285299ebb4caSwyllys 		}
285399ebb4caSwyllys 	}
285499ebb4caSwyllys 
285599ebb4caSwyllys 	return (rv);
285699ebb4caSwyllys }
285799ebb4caSwyllys 
285899ebb4caSwyllys KMF_RETURN
285999ebb4caSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle, KMF_FINDKEY_PARAMS *params,
286099ebb4caSwyllys 	KMF_KEY_HANDLE *key, uint32_t *numkeys)
286199ebb4caSwyllys {
286299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
286399ebb4caSwyllys 	char *fullpath = NULL;
286499ebb4caSwyllys 
286599ebb4caSwyllys 	if (handle == NULL || params == NULL || numkeys == NULL)
286699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
286799ebb4caSwyllys 
286899ebb4caSwyllys 	if (params->keyclass != KMF_ASYM_PUB &&
286999ebb4caSwyllys 		params->keyclass != KMF_ASYM_PRI &&
287099ebb4caSwyllys 		params->keyclass != KMF_SYMMETRIC)
287199ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
287299ebb4caSwyllys 
287399ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
287499ebb4caSwyllys 		params->sslparms.keyfile);
287599ebb4caSwyllys 
287699ebb4caSwyllys 	if (fullpath == NULL)
287799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
287899ebb4caSwyllys 
287999ebb4caSwyllys 	*numkeys = 0;
288099ebb4caSwyllys 
288199ebb4caSwyllys 	if (isdir(fullpath)) {
288299ebb4caSwyllys 		DIR *dirp;
288399ebb4caSwyllys 		struct dirent *dp;
288499ebb4caSwyllys 		int n = 0;
288599ebb4caSwyllys 
288699ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
288799ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
288899ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
288999ebb4caSwyllys 		}
289099ebb4caSwyllys 		rewinddir(dirp);
289199ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
289299ebb4caSwyllys 			if (strcmp(dp->d_name, ".") &&
289399ebb4caSwyllys 			    strcmp(dp->d_name, "..")) {
289499ebb4caSwyllys 				char *fname;
289599ebb4caSwyllys 
289699ebb4caSwyllys 				fname = get_fullpath(fullpath,
289799ebb4caSwyllys 					(char *)&dp->d_name);
289899ebb4caSwyllys 
289999ebb4caSwyllys 				rv = fetch_key(handle, fname,
290099ebb4caSwyllys 					params->keyclass,
290199ebb4caSwyllys 					key ? &key[n] : NULL);
290299ebb4caSwyllys 
290399ebb4caSwyllys 				if (rv == KMF_OK)
290499ebb4caSwyllys 					n++;
290599ebb4caSwyllys 
290699ebb4caSwyllys 				if (rv != KMF_OK || key == NULL)
290799ebb4caSwyllys 					free(fname);
290899ebb4caSwyllys 			}
290999ebb4caSwyllys 		}
291099ebb4caSwyllys 		(void) closedir(dirp);
291199ebb4caSwyllys 		free(fullpath);
291299ebb4caSwyllys 		(*numkeys) = n;
291399ebb4caSwyllys 	} else {
291499ebb4caSwyllys 		rv = fetch_key(handle, fullpath, params->keyclass, key);
291599ebb4caSwyllys 		if (rv == KMF_OK)
291699ebb4caSwyllys 			(*numkeys) = 1;
291799ebb4caSwyllys 
291899ebb4caSwyllys 		if (rv != KMF_OK || key == NULL)
291999ebb4caSwyllys 			free(fullpath);
292099ebb4caSwyllys 	}
292199ebb4caSwyllys 
292299ebb4caSwyllys 	if ((*numkeys) == 0)
292399ebb4caSwyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
292499ebb4caSwyllys 
292599ebb4caSwyllys 	return (rv);
292699ebb4caSwyllys }
292799ebb4caSwyllys 
292899ebb4caSwyllys #define	HANDLE_PK12_ERROR { \
292999ebb4caSwyllys 	SET_ERROR(kmfh, ERR_get_error()); \
293099ebb4caSwyllys 	rv = KMF_ERR_ENCODING; \
293199ebb4caSwyllys 	goto out; \
293299ebb4caSwyllys }
293399ebb4caSwyllys 
293499ebb4caSwyllys static KMF_RETURN
293599ebb4caSwyllys write_pkcs12(KMF_HANDLE *kmfh,
293699ebb4caSwyllys 	BIO *bio,
293799ebb4caSwyllys 	KMF_CREDENTIAL *cred,
293899ebb4caSwyllys 	EVP_PKEY *pkey,
293999ebb4caSwyllys 	X509 *sslcert)
294099ebb4caSwyllys {
294199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
294299ebb4caSwyllys 	STACK_OF(PKCS12_SAFEBAG)	*bag_stack = NULL;
294399ebb4caSwyllys 	PKCS12_SAFEBAG			*bag = NULL;
294499ebb4caSwyllys 	PKCS7				*cert_authsafe = NULL;
294599ebb4caSwyllys 	PKCS8_PRIV_KEY_INFO		*p8 = NULL;
294699ebb4caSwyllys 	PKCS7				*key_authsafe = NULL;
294799ebb4caSwyllys 	STACK_OF(PKCS7)			*authsafe_stack = NULL;
294899ebb4caSwyllys 	PKCS12				*p12_elem = NULL;
294999ebb4caSwyllys 	char				*lab = NULL;
295099ebb4caSwyllys 	int				lab_len = 0;
295199ebb4caSwyllys 	unsigned char keyid[EVP_MAX_MD_SIZE];
295299ebb4caSwyllys 	unsigned int keyidlen = 0;
295399ebb4caSwyllys 
295499ebb4caSwyllys 	/* Must have at least a cert OR a key */
295599ebb4caSwyllys 	if (sslcert == NULL && pkey == NULL)
295699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
295799ebb4caSwyllys 
295899ebb4caSwyllys 	(void) memset(keyid, 0, sizeof (keyid));
295999ebb4caSwyllys 	/*
296099ebb4caSwyllys 	 * Section 1:
296199ebb4caSwyllys 	 *
296299ebb4caSwyllys 	 * The first PKCS#12 container (safebag) will hold the certificates
296399ebb4caSwyllys 	 * associated with this key.  The result of this section is a
296499ebb4caSwyllys 	 * PIN-encrypted PKCS#7 container (authsafe).  If there are no
296599ebb4caSwyllys 	 * certificates, there is no point in creating the "safebag" or the
296699ebb4caSwyllys 	 * "authsafe" so we go to the next section.
296799ebb4caSwyllys 	 */
296899ebb4caSwyllys 	if (sslcert != NULL && pkey != NULL) {
296999ebb4caSwyllys 		if (X509_check_private_key(sslcert, pkey)) {
297099ebb4caSwyllys 			(void) X509_digest(sslcert, EVP_sha1(), keyid,
297199ebb4caSwyllys 				&keyidlen);
297299ebb4caSwyllys 		} else {
297399ebb4caSwyllys 			/* The key doesn't match the cert */
297499ebb4caSwyllys 			HANDLE_PK12_ERROR
297599ebb4caSwyllys 		}
297699ebb4caSwyllys 	}
297799ebb4caSwyllys 
297899ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
297999ebb4caSwyllys 	if (bag_stack == NULL)
298099ebb4caSwyllys 		return (KMF_ERR_MEMORY);
298199ebb4caSwyllys 
298299ebb4caSwyllys 	if (sslcert != NULL) {
298399ebb4caSwyllys 		/* Convert cert from X509 struct to PKCS#12 bag */
298499ebb4caSwyllys 		bag = PKCS12_x5092certbag(sslcert);
298599ebb4caSwyllys 		if (bag == NULL) {
298699ebb4caSwyllys 			HANDLE_PK12_ERROR
298799ebb4caSwyllys 		}
298899ebb4caSwyllys 
298999ebb4caSwyllys 		/* Add the key id to the certificate bag. */
299099ebb4caSwyllys 		if (keyidlen > 0 &&
299199ebb4caSwyllys 			!PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
299299ebb4caSwyllys 			HANDLE_PK12_ERROR
299399ebb4caSwyllys 		}
299499ebb4caSwyllys 
299599ebb4caSwyllys 		/* Pile it on the bag_stack. */
299699ebb4caSwyllys 		if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
299799ebb4caSwyllys 			HANDLE_PK12_ERROR
299899ebb4caSwyllys 		}
299999ebb4caSwyllys #if 0
300099ebb4caSwyllys 		/* No support for CA certs yet */
300199ebb4caSwyllys 		if (cacerts != NULL && ncacerts > 0) {
300299ebb4caSwyllys 			int i;
300399ebb4caSwyllys 			for (i = 0; i < ncacerts; i++) {
300499ebb4caSwyllys 				KMF_X509_DER_CERT *c = &cacerts[i];
300599ebb4caSwyllys 				X509 *ca = NULL;
300699ebb4caSwyllys 
300799ebb4caSwyllys 				uchar_t *p = (uchar_t *)c->certificate.Data;
300899ebb4caSwyllys 				ca = d2i_X509(NULL, &p,
300999ebb4caSwyllys 					c->certificate.Length);
301099ebb4caSwyllys 				if (ca == NULL) {
301199ebb4caSwyllys 					HANDLE_PK12_ERROR
301299ebb4caSwyllys 				}
301399ebb4caSwyllys 				/* Convert CA cert to PKCS#12 bag. */
301499ebb4caSwyllys 				bag = PKCS12_x5092certbag(ca);
301599ebb4caSwyllys 				if (bag == NULL) {
301699ebb4caSwyllys 					sk_PKCS12_SAFEBAG_pop_free(bag_stack,
301799ebb4caSwyllys 					    PKCS12_SAFEBAG_free);
301899ebb4caSwyllys 					HANDLE_PK12_ERROR
301999ebb4caSwyllys 				}
302099ebb4caSwyllys 				/* Pile it onto the bag_stack. */
302199ebb4caSwyllys 				if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
302299ebb4caSwyllys 					HANDLE_PK12_ERROR
302399ebb4caSwyllys 				}
302499ebb4caSwyllys 			}
302599ebb4caSwyllys 		}
302699ebb4caSwyllys #endif
302799ebb4caSwyllys 		/* Turn bag_stack of certs into encrypted authsafe. */
302899ebb4caSwyllys 		cert_authsafe = PKCS12_pack_p7encdata(
302999ebb4caSwyllys 			NID_pbe_WithSHA1And40BitRC2_CBC,
303099ebb4caSwyllys 			cred->cred,
303199ebb4caSwyllys 			cred->credlen, NULL, 0,
303299ebb4caSwyllys 			PKCS12_DEFAULT_ITER,
303399ebb4caSwyllys 			bag_stack);
303499ebb4caSwyllys 
303599ebb4caSwyllys 		/* Clear away this bag_stack, we're done with it. */
303699ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
303799ebb4caSwyllys 		bag_stack = NULL;
303899ebb4caSwyllys 
303999ebb4caSwyllys 		if (cert_authsafe == NULL) {
304099ebb4caSwyllys 			HANDLE_PK12_ERROR
304199ebb4caSwyllys 		}
304299ebb4caSwyllys 	}
304399ebb4caSwyllys 	/*
304499ebb4caSwyllys 	 * Section 2:
304599ebb4caSwyllys 	 *
304699ebb4caSwyllys 	 * The second PKCS#12 container (safebag) will hold the private key
304799ebb4caSwyllys 	 * that goes with the certificates above.  The results of this section
304899ebb4caSwyllys 	 * is an unencrypted PKCS#7 container (authsafe).  If there is no
304999ebb4caSwyllys 	 * private key, there is no point in creating the "safebag" or the
305099ebb4caSwyllys 	 * "authsafe" so we go to the next section.
305199ebb4caSwyllys 	 */
305299ebb4caSwyllys 	if (pkey != NULL) {
305399ebb4caSwyllys 		p8 = EVP_PKEY2PKCS8(pkey);
305499ebb4caSwyllys 		if (p8 == NULL) {
305599ebb4caSwyllys 			HANDLE_PK12_ERROR
305699ebb4caSwyllys 		}
305799ebb4caSwyllys 		/* Put the shrouded key into a PKCS#12 bag. */
305899ebb4caSwyllys 		bag = PKCS12_MAKE_SHKEYBAG(
305999ebb4caSwyllys 			NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
306099ebb4caSwyllys 			cred->cred, cred->credlen,
306199ebb4caSwyllys 			NULL, 0, PKCS12_DEFAULT_ITER, p8);
306299ebb4caSwyllys 
306399ebb4caSwyllys 		/* Clean up the PKCS#8 shrouded key, don't need it now. */
306499ebb4caSwyllys 		PKCS8_PRIV_KEY_INFO_free(p8);
306599ebb4caSwyllys 		p8 = NULL;
306699ebb4caSwyllys 
306799ebb4caSwyllys 		if (bag == NULL) {
306899ebb4caSwyllys 			HANDLE_PK12_ERROR
306999ebb4caSwyllys 		}
307099ebb4caSwyllys 		if (keyidlen &&
307199ebb4caSwyllys 			!PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
307299ebb4caSwyllys 			HANDLE_PK12_ERROR
307399ebb4caSwyllys 		}
307499ebb4caSwyllys 		if (lab != NULL) {
307599ebb4caSwyllys 			if (!PKCS12_add_friendlyname(bag,
307699ebb4caSwyllys 				(char *)lab, lab_len)) {
307799ebb4caSwyllys 				HANDLE_PK12_ERROR
307899ebb4caSwyllys 			}
307999ebb4caSwyllys 		}
308099ebb4caSwyllys 		/* Start a PKCS#12 safebag container for the private key. */
308199ebb4caSwyllys 		bag_stack = sk_PKCS12_SAFEBAG_new_null();
308299ebb4caSwyllys 		if (bag_stack == NULL) {
308399ebb4caSwyllys 			HANDLE_PK12_ERROR
308499ebb4caSwyllys 		}
308599ebb4caSwyllys 
308699ebb4caSwyllys 		/* Pile on the private key on the bag_stack. */
308799ebb4caSwyllys 		if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
308899ebb4caSwyllys 			HANDLE_PK12_ERROR
308999ebb4caSwyllys 		}
309099ebb4caSwyllys 		key_authsafe = PKCS12_pack_p7data(bag_stack);
309199ebb4caSwyllys 
309299ebb4caSwyllys 		/* Clear away this bag_stack, we're done with it. */
309399ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
309499ebb4caSwyllys 		bag_stack = NULL;
309599ebb4caSwyllys 
309699ebb4caSwyllys 		if (key_authsafe == NULL) {
309799ebb4caSwyllys 			HANDLE_PK12_ERROR
309899ebb4caSwyllys 		}
309999ebb4caSwyllys 	}
310099ebb4caSwyllys 	/*
310199ebb4caSwyllys 	 * Section 3:
310299ebb4caSwyllys 	 *
310399ebb4caSwyllys 	 * This is where the two PKCS#7 containers, one for the certificates
310499ebb4caSwyllys 	 * and one for the private key, are put together into a PKCS#12
310599ebb4caSwyllys 	 * element.  This final PKCS#12 element is written to the export file.
310699ebb4caSwyllys 	 */
310799ebb4caSwyllys 
310899ebb4caSwyllys 	/* Start a PKCS#7 stack. */
310999ebb4caSwyllys 	authsafe_stack = sk_PKCS7_new_null();
311099ebb4caSwyllys 	if (authsafe_stack == NULL) {
311199ebb4caSwyllys 		HANDLE_PK12_ERROR
311299ebb4caSwyllys 	}
311399ebb4caSwyllys 	if (key_authsafe != NULL) {
311499ebb4caSwyllys 		if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
311599ebb4caSwyllys 			HANDLE_PK12_ERROR
311699ebb4caSwyllys 		}
311799ebb4caSwyllys 	}
311899ebb4caSwyllys 	if (cert_authsafe != NULL) {
311999ebb4caSwyllys 		if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
312099ebb4caSwyllys 			HANDLE_PK12_ERROR
312199ebb4caSwyllys 		}
312299ebb4caSwyllys 	}
312399ebb4caSwyllys 	p12_elem = PKCS12_init(NID_pkcs7_data);
312499ebb4caSwyllys 	if (p12_elem == NULL) {
312599ebb4caSwyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
312699ebb4caSwyllys 		HANDLE_PK12_ERROR
312799ebb4caSwyllys 	}
312899ebb4caSwyllys 
312999ebb4caSwyllys 	/* Put the PKCS#7 stack into the PKCS#12 element. */
313099ebb4caSwyllys 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
313199ebb4caSwyllys 		HANDLE_PK12_ERROR
313299ebb4caSwyllys 	}
313399ebb4caSwyllys 	/* Clear away the PKCS#7 stack, we're done with it. */
313499ebb4caSwyllys 	sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
313599ebb4caSwyllys 	authsafe_stack = NULL;
313699ebb4caSwyllys 
313799ebb4caSwyllys 	/* Set the integrity MAC on the PKCS#12 element. */
313899ebb4caSwyllys 	if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
313999ebb4caSwyllys 		NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
314099ebb4caSwyllys 		HANDLE_PK12_ERROR
314199ebb4caSwyllys 	}
314299ebb4caSwyllys 
314399ebb4caSwyllys 	/* Write the PKCS#12 element to the export file. */
314499ebb4caSwyllys 	if (!i2d_PKCS12_bio(bio, p12_elem)) {
314599ebb4caSwyllys 		HANDLE_PK12_ERROR
314699ebb4caSwyllys 	}
314799ebb4caSwyllys 
314899ebb4caSwyllys 	PKCS12_free(p12_elem);
314999ebb4caSwyllys out:
315099ebb4caSwyllys 	if (rv != KMF_OK) {
315199ebb4caSwyllys 		/* Clear away this bag_stack, we're done with it. */
315299ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
315399ebb4caSwyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
315499ebb4caSwyllys 	}
315599ebb4caSwyllys 	return (rv);
315699ebb4caSwyllys }
315799ebb4caSwyllys 
315899ebb4caSwyllys static EVP_PKEY *
315999ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
316099ebb4caSwyllys {
316199ebb4caSwyllys 	RSA		*rsa = NULL;
316299ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
316399ebb4caSwyllys 
316499ebb4caSwyllys 	if ((rsa = RSA_new()) == NULL)
316599ebb4caSwyllys 		return (NULL);
316699ebb4caSwyllys 
316799ebb4caSwyllys 	if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL)
316899ebb4caSwyllys 		return (NULL);
316999ebb4caSwyllys 
317099ebb4caSwyllys 	if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) ==
317199ebb4caSwyllys 		NULL)
317299ebb4caSwyllys 		return (NULL);
317399ebb4caSwyllys 
317499ebb4caSwyllys 	if (key->priexp.val != NULL)
317599ebb4caSwyllys 		if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len,
317699ebb4caSwyllys 			rsa->d)) == NULL)
317799ebb4caSwyllys 			return (NULL);
317899ebb4caSwyllys 
317999ebb4caSwyllys 	if (key->prime1.val != NULL)
318099ebb4caSwyllys 		if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len,
318199ebb4caSwyllys 			rsa->p)) == NULL)
318299ebb4caSwyllys 			return (NULL);
318399ebb4caSwyllys 
318499ebb4caSwyllys 	if (key->prime2.val != NULL)
318599ebb4caSwyllys 		if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len,
318699ebb4caSwyllys 			rsa->q)) == NULL)
318799ebb4caSwyllys 			return (NULL);
318899ebb4caSwyllys 
318999ebb4caSwyllys 	if (key->exp1.val != NULL)
319099ebb4caSwyllys 		if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len,
319199ebb4caSwyllys 			rsa->dmp1)) == NULL)
319299ebb4caSwyllys 			return (NULL);
319399ebb4caSwyllys 
319499ebb4caSwyllys 	if (key->exp2.val != NULL)
319599ebb4caSwyllys 		if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len,
319699ebb4caSwyllys 			rsa->dmq1)) == NULL)
319799ebb4caSwyllys 			return (NULL);
319899ebb4caSwyllys 
319999ebb4caSwyllys 	if (key->coef.val != NULL)
320099ebb4caSwyllys 		if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len,
320199ebb4caSwyllys 			rsa->iqmp)) == NULL)
320299ebb4caSwyllys 			return (NULL);
320399ebb4caSwyllys 
320499ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
320599ebb4caSwyllys 		return (NULL);
320699ebb4caSwyllys 
320799ebb4caSwyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
320899ebb4caSwyllys 
320999ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
321099ebb4caSwyllys 	RSA_free(rsa);
321199ebb4caSwyllys 
321299ebb4caSwyllys 	return (newkey);
321399ebb4caSwyllys }
321499ebb4caSwyllys 
321599ebb4caSwyllys static EVP_PKEY *
321699ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
321799ebb4caSwyllys {
321899ebb4caSwyllys 	DSA		*dsa = NULL;
321999ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
322099ebb4caSwyllys 
322199ebb4caSwyllys 	if ((dsa = DSA_new()) == NULL)
322299ebb4caSwyllys 		return (NULL);
322399ebb4caSwyllys 
322499ebb4caSwyllys 	if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len,
322599ebb4caSwyllys 		dsa->p)) == NULL)
322699ebb4caSwyllys 		return (NULL);
322799ebb4caSwyllys 
322899ebb4caSwyllys 	if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len,
322999ebb4caSwyllys 		dsa->q)) == NULL)
323099ebb4caSwyllys 		return (NULL);
323199ebb4caSwyllys 
323299ebb4caSwyllys 	if ((dsa->g = BN_bin2bn(key->base.val, key->base.len,
323399ebb4caSwyllys 		dsa->g)) == NULL)
323499ebb4caSwyllys 		return (NULL);
323599ebb4caSwyllys 
323699ebb4caSwyllys 	if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len,
323799ebb4caSwyllys 		dsa->priv_key)) == NULL)
323899ebb4caSwyllys 		return (NULL);
323999ebb4caSwyllys 
324099ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
324199ebb4caSwyllys 		return (NULL);
324299ebb4caSwyllys 
324399ebb4caSwyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
324499ebb4caSwyllys 
324599ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
324699ebb4caSwyllys 	DSA_free(dsa);
324799ebb4caSwyllys 	return (newkey);
324899ebb4caSwyllys }
324999ebb4caSwyllys 
325099ebb4caSwyllys static KMF_RETURN
325199ebb4caSwyllys ExportPK12FromRawData(KMF_HANDLE_T handle,
325299ebb4caSwyllys 	KMF_CREDENTIAL *cred,
325399ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
325499ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
325599ebb4caSwyllys 	char *filename)
325699ebb4caSwyllys {
325799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
325899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
325999ebb4caSwyllys 	BIO *bio = NULL;
326099ebb4caSwyllys 	X509 *xcert = NULL;
326199ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
326299ebb4caSwyllys 	int i;
326399ebb4caSwyllys 
326499ebb4caSwyllys 	/*
326599ebb4caSwyllys 	 * Open the output file.
326699ebb4caSwyllys 	 */
326799ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
326899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
326999ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
327099ebb4caSwyllys 		goto cleanup;
327199ebb4caSwyllys 	}
327299ebb4caSwyllys 
327399ebb4caSwyllys 	if (numcerts > 0 && numkeys > 0) {
327499ebb4caSwyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
327599ebb4caSwyllys 			KMF_RAW_KEY_DATA *key = NULL;
327699ebb4caSwyllys 			const uchar_t *p = certlist[i].certificate.Data;
327799ebb4caSwyllys 			long len = certlist[i].certificate.Length;
327899ebb4caSwyllys 
327999ebb4caSwyllys 			if (i < numkeys) {
328099ebb4caSwyllys 				key = (KMF_RAW_KEY_DATA *)keylist[i].keyp;
328199ebb4caSwyllys 
328299ebb4caSwyllys 				if (key->keytype == KMF_RSA) {
328399ebb4caSwyllys 					pkey = ImportRawRSAKey(
328499ebb4caSwyllys 						&key->rawdata.rsa);
328599ebb4caSwyllys 				} else if (key->keytype == KMF_DSA) {
328699ebb4caSwyllys 					pkey = ImportRawDSAKey(
328799ebb4caSwyllys 						&key->rawdata.dsa);
328899ebb4caSwyllys 				} else {
328999ebb4caSwyllys 					rv = KMF_ERR_BAD_PARAMETER;
329099ebb4caSwyllys 				}
329199ebb4caSwyllys 			}
329299ebb4caSwyllys 
329399ebb4caSwyllys 			xcert = d2i_X509(NULL, &p, len);
329499ebb4caSwyllys 			if (xcert == NULL) {
329599ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
329699ebb4caSwyllys 				rv = KMF_ERR_ENCODING;
329799ebb4caSwyllys 			}
329899ebb4caSwyllys 			/* Stick the key and the cert into a PKCS#12 file */
329999ebb4caSwyllys 			rv = write_pkcs12(kmfh, bio, cred, pkey, xcert);
330099ebb4caSwyllys 			if (xcert)
330199ebb4caSwyllys 				X509_free(xcert);
330299ebb4caSwyllys 			if (pkey)
330399ebb4caSwyllys 				EVP_PKEY_free(pkey);
330499ebb4caSwyllys 		}
330599ebb4caSwyllys 	}
330699ebb4caSwyllys 
330799ebb4caSwyllys cleanup:
330899ebb4caSwyllys 
330999ebb4caSwyllys 	if (bio != NULL)
331099ebb4caSwyllys 		(void) BIO_free_all(bio);
331199ebb4caSwyllys 
331299ebb4caSwyllys 	return (rv);
331399ebb4caSwyllys }
331499ebb4caSwyllys 
331599ebb4caSwyllys KMF_RETURN
331699ebb4caSwyllys OpenSSL_ExportP12(KMF_HANDLE_T handle,
331799ebb4caSwyllys 	KMF_EXPORTP12_PARAMS *params,
331899ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
331999ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
332099ebb4caSwyllys 	char *filename)
332199ebb4caSwyllys {
332299ebb4caSwyllys 	KMF_RETURN rv;
332399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
332499ebb4caSwyllys 	KMF_FINDCERT_PARAMS fcargs;
332599ebb4caSwyllys 	BIO *bio = NULL;
332699ebb4caSwyllys 	X509 *xcert = NULL;
332799ebb4caSwyllys 	char *fullpath = NULL;
332899ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
332999ebb4caSwyllys 
333099ebb4caSwyllys 	/*
333199ebb4caSwyllys 	 *  First, find the certificate.
333299ebb4caSwyllys 	 */
333399ebb4caSwyllys 	if (params == NULL)
333499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
333599ebb4caSwyllys 
333699ebb4caSwyllys 	/*
333799ebb4caSwyllys 	 * If the caller already sent the raw keys and certs,
333899ebb4caSwyllys 	 * shortcut the search and just export that
333999ebb4caSwyllys 	 * data.
334099ebb4caSwyllys 	 *
334199ebb4caSwyllys 	 * One *may* export a key OR a cert by itself.
334299ebb4caSwyllys 	 */
334399ebb4caSwyllys 	if (certlist != NULL || keylist != NULL) {
334499ebb4caSwyllys 		rv = ExportPK12FromRawData(handle,
334599ebb4caSwyllys 			&params->p12cred,
334699ebb4caSwyllys 			numcerts, certlist,
334799ebb4caSwyllys 			numkeys, keylist,
334899ebb4caSwyllys 			filename);
334999ebb4caSwyllys 		return (rv);
335099ebb4caSwyllys 	}
335199ebb4caSwyllys 
335299ebb4caSwyllys 	if (params->sslparms.certfile != NULL) {
335399ebb4caSwyllys 		fullpath = get_fullpath(params->sslparms.dirpath,
335499ebb4caSwyllys 			params->sslparms.certfile);
335599ebb4caSwyllys 
335699ebb4caSwyllys 		if (fullpath == NULL)
335799ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
335899ebb4caSwyllys 
335999ebb4caSwyllys 		if (isdir(fullpath)) {
336099ebb4caSwyllys 			free(fullpath);
336199ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
336299ebb4caSwyllys 		}
336399ebb4caSwyllys 
336499ebb4caSwyllys 		(void *)memset(&fcargs, 0, sizeof (fcargs));
336599ebb4caSwyllys 		fcargs.kstype = params->kstype;
336699ebb4caSwyllys 		fcargs.certLabel = params->certLabel;
336799ebb4caSwyllys 		fcargs.issuer = params->issuer;
336899ebb4caSwyllys 		fcargs.subject = params->subject;
336999ebb4caSwyllys 		fcargs.serial = params->serial;
337099ebb4caSwyllys 		fcargs.idstr = params->idstr;
337199ebb4caSwyllys 		fcargs.sslparms.dirpath = NULL;
337299ebb4caSwyllys 		fcargs.sslparms.certfile = fullpath;
337399ebb4caSwyllys 		fcargs.sslparms.format = params->sslparms.format;
337499ebb4caSwyllys 
337599ebb4caSwyllys 		rv = load_X509cert(kmfh, &fcargs, fullpath, &xcert);
337699ebb4caSwyllys 		if (rv != KMF_OK)
337799ebb4caSwyllys 			goto end;
337899ebb4caSwyllys 	}
337999ebb4caSwyllys 
338099ebb4caSwyllys 	/*
338199ebb4caSwyllys 	 * Now find the private key.
338299ebb4caSwyllys 	 */
338399ebb4caSwyllys 	if (params->sslparms.keyfile != NULL) {
338499ebb4caSwyllys 		fullpath = get_fullpath(params->sslparms.dirpath,
338599ebb4caSwyllys 			params->sslparms.keyfile);
338699ebb4caSwyllys 
338799ebb4caSwyllys 		if (fullpath == NULL)
338899ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
338999ebb4caSwyllys 
339099ebb4caSwyllys 		if (isdir(fullpath)) {
339199ebb4caSwyllys 			free(fullpath);
339299ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
339399ebb4caSwyllys 		}
339499ebb4caSwyllys 
339599ebb4caSwyllys 		pkey = openssl_load_key(handle, fullpath);
339699ebb4caSwyllys 		if (pkey == NULL) {
339799ebb4caSwyllys 			rv = KMF_ERR_KEY_NOT_FOUND;
339899ebb4caSwyllys 			goto end;
339999ebb4caSwyllys 		}
340099ebb4caSwyllys 	}
340199ebb4caSwyllys 
340299ebb4caSwyllys 	/*
340399ebb4caSwyllys 	 * Open the output file.
340499ebb4caSwyllys 	 */
340599ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
340699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
340799ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
340899ebb4caSwyllys 		goto end;
340999ebb4caSwyllys 	}
341099ebb4caSwyllys 
341199ebb4caSwyllys 	/* Stick the key and the cert into a PKCS#12 file */
341299ebb4caSwyllys 	rv = write_pkcs12(kmfh, bio, &params->p12cred,
341399ebb4caSwyllys 		pkey, xcert);
341499ebb4caSwyllys 
341599ebb4caSwyllys end:
341699ebb4caSwyllys 	if (fullpath)
341799ebb4caSwyllys 		free(fullpath);
341899ebb4caSwyllys 	if (xcert)
341999ebb4caSwyllys 		X509_free(xcert);
342099ebb4caSwyllys 	if (pkey)
342199ebb4caSwyllys 		EVP_PKEY_free(pkey);
342299ebb4caSwyllys 	if (bio)
342399ebb4caSwyllys 		(void) BIO_free(bio);
342499ebb4caSwyllys 
342599ebb4caSwyllys 	return (rv);
342699ebb4caSwyllys }
342799ebb4caSwyllys 
342871593db2Swyllys #define	MAX_CHAIN_LENGTH 100
342971593db2Swyllys /*
343071593db2Swyllys  * Helper function to extract keys and certificates from
343171593db2Swyllys  * a single PEM file.  Typically the file should contain a
343271593db2Swyllys  * private key and an associated public key wrapped in an x509 cert.
343371593db2Swyllys  * However, the file may be just a list of X509 certs with no keys.
343471593db2Swyllys  */
343571593db2Swyllys static KMF_RETURN
343671593db2Swyllys extract_objects(KMF_HANDLE *kmfh, char *filename, CK_UTF8CHAR *pin,
343771593db2Swyllys 	CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
343871593db2Swyllys 	int *numcerts)
343971593db2Swyllys /* ARGSUSED */
344071593db2Swyllys {
344171593db2Swyllys 	KMF_RETURN rv = KMF_OK;
344271593db2Swyllys 	FILE *fp;
344371593db2Swyllys 	STACK_OF(X509_INFO) *x509_info_stack;
344471593db2Swyllys 	int i, ncerts = 0;
344571593db2Swyllys 	EVP_PKEY *pkey = NULL;
344671593db2Swyllys 	X509_INFO *info;
344771593db2Swyllys 	X509 *x;
344871593db2Swyllys 	X509_INFO *cert_infos[MAX_CHAIN_LENGTH];
344971593db2Swyllys 	KMF_DATA *certlist = NULL;
345071593db2Swyllys 
345171593db2Swyllys 	if (priv_key)
345271593db2Swyllys 		*priv_key = NULL;
345371593db2Swyllys 	if (certs)
345471593db2Swyllys 		*certs = NULL;
345571593db2Swyllys 	fp = fopen(filename, "r");
345671593db2Swyllys 	if (fp == NULL) {
345771593db2Swyllys 		return (KMF_ERR_OPEN_FILE);
345871593db2Swyllys 	}
345971593db2Swyllys 	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
346071593db2Swyllys 	if (x509_info_stack == NULL) {
346171593db2Swyllys 		(void) fclose(fp);
346271593db2Swyllys 		return (KMF_ERR_ENCODING);
346371593db2Swyllys 	}
346471593db2Swyllys 
346571593db2Swyllys 	/*LINTED*/
346671593db2Swyllys 	while ((info = sk_X509_INFO_pop(x509_info_stack)) != NULL &&
346771593db2Swyllys 		ncerts < MAX_CHAIN_LENGTH) {
346871593db2Swyllys 		cert_infos[ncerts] = info;
346971593db2Swyllys 		ncerts++;
347071593db2Swyllys 	}
347171593db2Swyllys 
347271593db2Swyllys 	if (ncerts == 0) {
347371593db2Swyllys 		(void) fclose(fp);
347471593db2Swyllys 		return (KMF_ERR_CERT_NOT_FOUND);
347571593db2Swyllys 	}
347671593db2Swyllys 
347771593db2Swyllys 	if (priv_key != NULL) {
347871593db2Swyllys 		rewind(fp);
347971593db2Swyllys 		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
348071593db2Swyllys 	}
348171593db2Swyllys 	(void) fclose(fp);
348271593db2Swyllys 
348371593db2Swyllys 	x = cert_infos[ncerts - 1]->x509;
348471593db2Swyllys 	/*
348571593db2Swyllys 	 * Make sure the private key matchs the last cert in the file.
348671593db2Swyllys 	 */
348771593db2Swyllys 	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
348871593db2Swyllys 		EVP_PKEY_free(pkey);
348971593db2Swyllys 		return (KMF_ERR_KEY_MISMATCH);
349071593db2Swyllys 	}
349171593db2Swyllys 
349271593db2Swyllys 	certlist = (KMF_DATA *)malloc(ncerts * sizeof (KMF_DATA));
349371593db2Swyllys 	if (certlist == NULL) {
349471593db2Swyllys 		if (pkey != NULL)
349571593db2Swyllys 			EVP_PKEY_free(pkey);
349671593db2Swyllys 		X509_INFO_free(info);
349771593db2Swyllys 		return (KMF_ERR_MEMORY);
349871593db2Swyllys 	}
349971593db2Swyllys 
350071593db2Swyllys 	/*
350171593db2Swyllys 	 * Convert all of the certs to DER format.
350271593db2Swyllys 	 */
350371593db2Swyllys 	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
350471593db2Swyllys 		info =  cert_infos[ncerts - 1 - i];
350571593db2Swyllys 
350671593db2Swyllys 		rv = ssl_cert2KMFDATA(kmfh, info->x509, &certlist[i]);
350771593db2Swyllys 
350871593db2Swyllys 		if (rv != KMF_OK) {
350971593db2Swyllys 			free(certlist);
351071593db2Swyllys 			certlist = NULL;
351171593db2Swyllys 			ncerts = 0;
351271593db2Swyllys 		}
351371593db2Swyllys 		X509_INFO_free(info);
351471593db2Swyllys 	}
351571593db2Swyllys 
351671593db2Swyllys 	if (numcerts != NULL)
351771593db2Swyllys 		*numcerts = ncerts;
351871593db2Swyllys 	if (certs != NULL)
351971593db2Swyllys 		*certs = certlist;
352071593db2Swyllys 
352171593db2Swyllys 	if (priv_key == NULL && pkey != NULL)
352271593db2Swyllys 		EVP_PKEY_free(pkey);
352371593db2Swyllys 	else if (priv_key != NULL && pkey != NULL)
352471593db2Swyllys 		*priv_key = pkey;
352571593db2Swyllys 
352671593db2Swyllys 	return (rv);
352771593db2Swyllys }
352871593db2Swyllys 
352999ebb4caSwyllys /*
353099ebb4caSwyllys  * Helper function to decrypt and parse PKCS#12 import file.
353199ebb4caSwyllys  */
353299ebb4caSwyllys static KMF_RETURN
353399ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
353499ebb4caSwyllys 	EVP_PKEY **priv_key, X509 **cert, STACK_OF(X509) **ca)
353599ebb4caSwyllys /* ARGSUSED */
353699ebb4caSwyllys {
353799ebb4caSwyllys 	PKCS12		*pk12, *pk12_tmp;
353899ebb4caSwyllys 	EVP_PKEY	*temp_pkey = NULL;
353999ebb4caSwyllys 	X509		*temp_cert = NULL;
354099ebb4caSwyllys 	STACK_OF(X509)	*temp_ca = NULL;
354199ebb4caSwyllys 
354299ebb4caSwyllys 	if ((pk12 = PKCS12_new()) == NULL) {
354399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
354499ebb4caSwyllys 	}
354599ebb4caSwyllys 
354699ebb4caSwyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
354799ebb4caSwyllys 		/* This is ok; it seems to mean there is no more to read. */
354899ebb4caSwyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
354999ebb4caSwyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
355099ebb4caSwyllys 			goto end_extract_pkcs12;
355199ebb4caSwyllys 
355299ebb4caSwyllys 		PKCS12_free(pk12);
355399ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
355499ebb4caSwyllys 	}
355599ebb4caSwyllys 	pk12 = pk12_tmp;
355699ebb4caSwyllys 
355799ebb4caSwyllys 	if (PKCS12_parse(pk12, (char *)pin, &temp_pkey, &temp_cert,
355899ebb4caSwyllys 	    &temp_ca) <= 0) {
355999ebb4caSwyllys 		PKCS12_free(pk12);
356099ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
356199ebb4caSwyllys 	}
356299ebb4caSwyllys 
356399ebb4caSwyllys end_extract_pkcs12:
356499ebb4caSwyllys 
356599ebb4caSwyllys 	*priv_key = temp_pkey;
356699ebb4caSwyllys 	*cert = temp_cert;
356799ebb4caSwyllys 	*ca = temp_ca;
356899ebb4caSwyllys 
356999ebb4caSwyllys 	PKCS12_free(pk12);
357099ebb4caSwyllys 	return (KMF_OK);
357199ebb4caSwyllys }
357299ebb4caSwyllys 
357399ebb4caSwyllys static KMF_RETURN
357499ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
357599ebb4caSwyllys {
357699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
357799ebb4caSwyllys 	uint32_t sz;
357899ebb4caSwyllys 
357999ebb4caSwyllys 	sz = BN_num_bytes(from);
358099ebb4caSwyllys 	to->val = (uchar_t *)malloc(sz);
358199ebb4caSwyllys 	if (to->val == NULL)
358299ebb4caSwyllys 		return (KMF_ERR_MEMORY);
358399ebb4caSwyllys 
358499ebb4caSwyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
358599ebb4caSwyllys 		free(to->val);
358699ebb4caSwyllys 		to->val = NULL;
358799ebb4caSwyllys 		to->len = 0;
358899ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
358999ebb4caSwyllys 	}
359099ebb4caSwyllys 
359199ebb4caSwyllys 	return (rv);
359299ebb4caSwyllys }
359399ebb4caSwyllys 
359499ebb4caSwyllys static KMF_RETURN
359599ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
359699ebb4caSwyllys {
359799ebb4caSwyllys 	KMF_RETURN rv;
359899ebb4caSwyllys 	KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
359999ebb4caSwyllys 
360099ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
360199ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK)
360299ebb4caSwyllys 		goto cleanup;
360399ebb4caSwyllys 
360499ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK)
360599ebb4caSwyllys 		goto cleanup;
360699ebb4caSwyllys 
360799ebb4caSwyllys 	if (rsa->d != NULL)
360899ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK)
360999ebb4caSwyllys 			goto cleanup;
361099ebb4caSwyllys 
361199ebb4caSwyllys 	if (rsa->p != NULL)
361299ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK)
361399ebb4caSwyllys 			goto cleanup;
361499ebb4caSwyllys 
361599ebb4caSwyllys 	if (rsa->q != NULL)
361699ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK)
361799ebb4caSwyllys 			goto cleanup;
361899ebb4caSwyllys 
361999ebb4caSwyllys 	if (rsa->dmp1 != NULL)
362099ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK)
362199ebb4caSwyllys 			goto cleanup;
362299ebb4caSwyllys 
362399ebb4caSwyllys 	if (rsa->dmq1 != NULL)
362499ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK)
362599ebb4caSwyllys 			goto cleanup;
362699ebb4caSwyllys 
362799ebb4caSwyllys 	if (rsa->iqmp != NULL)
362899ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK)
362999ebb4caSwyllys 			goto cleanup;
363099ebb4caSwyllys cleanup:
363199ebb4caSwyllys 	if (rv != KMF_OK)
363299ebb4caSwyllys 		KMF_FreeRawKey(key);
363399ebb4caSwyllys 	else
363499ebb4caSwyllys 		key->keytype = KMF_RSA;
363599ebb4caSwyllys 
363699ebb4caSwyllys 	/*
363799ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
363899ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
363999ebb4caSwyllys 	 */
364099ebb4caSwyllys 	RSA_free(rsa);
364199ebb4caSwyllys 
364299ebb4caSwyllys 	return (rv);
364399ebb4caSwyllys }
364499ebb4caSwyllys 
364599ebb4caSwyllys static KMF_RETURN
364699ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
364799ebb4caSwyllys {
364899ebb4caSwyllys 	KMF_RETURN rv;
364999ebb4caSwyllys 	KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
365099ebb4caSwyllys 
365199ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
365299ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK)
365399ebb4caSwyllys 		goto cleanup;
365499ebb4caSwyllys 
365599ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK)
365699ebb4caSwyllys 		goto cleanup;
365799ebb4caSwyllys 
365899ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK)
365999ebb4caSwyllys 		goto cleanup;
366099ebb4caSwyllys 
366199ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK)
366299ebb4caSwyllys 		goto cleanup;
366399ebb4caSwyllys 
366499ebb4caSwyllys cleanup:
366599ebb4caSwyllys 	if (rv != KMF_OK)
366699ebb4caSwyllys 		KMF_FreeRawKey(key);
366799ebb4caSwyllys 	else
366899ebb4caSwyllys 		key->keytype = KMF_DSA;
366999ebb4caSwyllys 
367099ebb4caSwyllys 	/*
367199ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
367299ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
367399ebb4caSwyllys 	 */
367499ebb4caSwyllys 	DSA_free(dsa);
367599ebb4caSwyllys 
367699ebb4caSwyllys 	return (rv);
367799ebb4caSwyllys }
367899ebb4caSwyllys 
367999ebb4caSwyllys static KMF_RETURN
368099ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
368199ebb4caSwyllys 	KMF_DATA **certlist, int *ncerts)
368299ebb4caSwyllys {
368399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
368499ebb4caSwyllys 	KMF_DATA *list = (*certlist);
368599ebb4caSwyllys 	KMF_DATA cert;
368699ebb4caSwyllys 	int n = (*ncerts);
368799ebb4caSwyllys 
368899ebb4caSwyllys 	if (list == NULL) {
368999ebb4caSwyllys 		list = (KMF_DATA *)malloc(sizeof (KMF_DATA));
369099ebb4caSwyllys 	} else {
369199ebb4caSwyllys 		list = (KMF_DATA *)realloc(list, sizeof (KMF_DATA) * (n + 1));
369299ebb4caSwyllys 	}
369399ebb4caSwyllys 
369499ebb4caSwyllys 	if (list == NULL)
369599ebb4caSwyllys 		return (KMF_ERR_MEMORY);
369699ebb4caSwyllys 
369799ebb4caSwyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert);
369899ebb4caSwyllys 	if (rv == KMF_OK) {
369999ebb4caSwyllys 		list[n] = cert;
370099ebb4caSwyllys 		(*ncerts) = n + 1;
370199ebb4caSwyllys 
370299ebb4caSwyllys 		*certlist = list;
370399ebb4caSwyllys 	} else {
370499ebb4caSwyllys 		free(list);
370599ebb4caSwyllys 	}
370699ebb4caSwyllys 
370799ebb4caSwyllys 	return (rv);
370899ebb4caSwyllys }
370999ebb4caSwyllys 
371099ebb4caSwyllys static KMF_RETURN
371199ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
371299ebb4caSwyllys 	KMF_RAW_KEY_DATA *newkey, int *nkeys)
371399ebb4caSwyllys {
371499ebb4caSwyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
371599ebb4caSwyllys 	int n = (*nkeys);
371699ebb4caSwyllys 
371799ebb4caSwyllys 	if (list == NULL) {
371899ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
371999ebb4caSwyllys 	} else {
372099ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
372199ebb4caSwyllys 			sizeof (KMF_RAW_KEY_DATA) * (n + 1));
372299ebb4caSwyllys 	}
372399ebb4caSwyllys 
372499ebb4caSwyllys 	if (list == NULL)
372599ebb4caSwyllys 		return (KMF_ERR_MEMORY);
372699ebb4caSwyllys 
372799ebb4caSwyllys 	list[n] = *newkey;
372899ebb4caSwyllys 	(*nkeys) = n + 1;
372999ebb4caSwyllys 
373099ebb4caSwyllys 	*keylist = list;
373199ebb4caSwyllys 
373299ebb4caSwyllys 	return (KMF_OK);
373399ebb4caSwyllys }
373499ebb4caSwyllys 
373599ebb4caSwyllys 
373699ebb4caSwyllys static KMF_RETURN
373799ebb4caSwyllys convertPK12Objects(
373899ebb4caSwyllys 	KMF_HANDLE *kmfh,
373999ebb4caSwyllys 	EVP_PKEY *sslkey, X509 *sslcert, STACK_OF(X509) *sslcacerts,
374099ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
374199ebb4caSwyllys 	KMF_DATA **certlist, int *ncerts)
374299ebb4caSwyllys {
374399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
374499ebb4caSwyllys 	KMF_RAW_KEY_DATA key;
374599ebb4caSwyllys 	int i;
374699ebb4caSwyllys 
374799ebb4caSwyllys 	if (sslkey != NULL) {
374899ebb4caSwyllys 		/* Convert SSL key to raw key */
374999ebb4caSwyllys 		switch (sslkey->type) {
375099ebb4caSwyllys 			case EVP_PKEY_RSA:
375199ebb4caSwyllys 				rv = exportRawRSAKey(EVP_PKEY_get1_RSA(sslkey),
375299ebb4caSwyllys 					&key);
375399ebb4caSwyllys 				if (rv != KMF_OK)
375499ebb4caSwyllys 					return (rv);
375599ebb4caSwyllys 
375699ebb4caSwyllys 				break;
375799ebb4caSwyllys 			case EVP_PKEY_DSA:
375899ebb4caSwyllys 				rv = exportRawDSAKey(EVP_PKEY_get1_DSA(sslkey),
375999ebb4caSwyllys 					&key);
376099ebb4caSwyllys 				if (rv != KMF_OK)
376199ebb4caSwyllys 					return (rv);
376299ebb4caSwyllys 
376399ebb4caSwyllys 				break;
376499ebb4caSwyllys 			default:
376599ebb4caSwyllys 				return (KMF_ERR_BAD_PARAMETER);
376699ebb4caSwyllys 		}
376799ebb4caSwyllys 
376899ebb4caSwyllys 		rv = add_key_to_list(keylist, &key, nkeys);
376999ebb4caSwyllys 		if (rv != KMF_OK)
377099ebb4caSwyllys 			return (rv);
377199ebb4caSwyllys 	}
377299ebb4caSwyllys 
377399ebb4caSwyllys 	/* Now add the certificate to the certlist */
377499ebb4caSwyllys 	if (sslcert != NULL) {
377599ebb4caSwyllys 		rv = add_cert_to_list(kmfh, sslcert, certlist, ncerts);
377699ebb4caSwyllys 		if (rv != KMF_OK)
377799ebb4caSwyllys 			return (rv);
377899ebb4caSwyllys 	}
377999ebb4caSwyllys 
378099ebb4caSwyllys 	/* Also add any included CA certs to the list */
378171593db2Swyllys 	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
378299ebb4caSwyllys 		X509 *c;
378399ebb4caSwyllys 		/*
378499ebb4caSwyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
378599ebb4caSwyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
378699ebb4caSwyllys 		 * Lint is complaining about the embedded casting, and
378799ebb4caSwyllys 		 * to fix it, you need to fix openssl header files.
378899ebb4caSwyllys 		 */
378999ebb4caSwyllys 		/* LINTED E_BAD_PTR_CAST_ALIGN */
379099ebb4caSwyllys 		c = sk_X509_value(sslcacerts, i);
379199ebb4caSwyllys 
379299ebb4caSwyllys 		/* Now add the ca cert to the certlist */
379399ebb4caSwyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
379499ebb4caSwyllys 		if (rv != KMF_OK)
379599ebb4caSwyllys 			return (rv);
379699ebb4caSwyllys 	}
379799ebb4caSwyllys 	return (rv);
379899ebb4caSwyllys }
379999ebb4caSwyllys 
380099ebb4caSwyllys KMF_RETURN
380199ebb4caSwyllys openssl_read_pkcs12(KMF_HANDLE *kmfh,
380299ebb4caSwyllys 	char *filename, KMF_CREDENTIAL *cred,
380399ebb4caSwyllys 	KMF_DATA **certlist, int *ncerts,
380499ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
380599ebb4caSwyllys {
380699ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
380799ebb4caSwyllys 	BIO		*bio = NULL;
380899ebb4caSwyllys 	EVP_PKEY	*privkey = NULL;
380999ebb4caSwyllys 	X509		*cert = NULL;
381099ebb4caSwyllys 	STACK_OF(X509)	*cacerts = NULL;
381199ebb4caSwyllys 
381299ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
381399ebb4caSwyllys 	if (bio == NULL) {
381499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
381599ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
381699ebb4caSwyllys 		goto end;
381799ebb4caSwyllys 	}
381899ebb4caSwyllys 
381999ebb4caSwyllys 	*certlist = NULL;
382099ebb4caSwyllys 	*keylist = NULL;
382199ebb4caSwyllys 	*ncerts = 0;
382299ebb4caSwyllys 	*nkeys = 0;
382399ebb4caSwyllys 	while (rv == KMF_OK) {
382499ebb4caSwyllys 		rv = extract_pkcs12(bio,
382599ebb4caSwyllys 			(uchar_t *)cred->cred,
382699ebb4caSwyllys 			(uint32_t)cred->credlen,
382799ebb4caSwyllys 			&privkey, &cert, &cacerts);
382899ebb4caSwyllys 
382999ebb4caSwyllys 		/* Reached end of import file? */
383099ebb4caSwyllys 		if (rv == KMF_OK && privkey == NULL &&
383199ebb4caSwyllys 			cert == NULL && cacerts == NULL)
383299ebb4caSwyllys 			break;
383399ebb4caSwyllys 
383499ebb4caSwyllys 		if (rv == KMF_OK)
383599ebb4caSwyllys 			/* Convert keys and certs to exportable format */
383699ebb4caSwyllys 			rv = convertPK12Objects(kmfh, privkey, cert, cacerts,
383799ebb4caSwyllys 				keylist, nkeys, certlist, ncerts);
383899ebb4caSwyllys 
383999ebb4caSwyllys 		if (privkey)
384099ebb4caSwyllys 			EVP_PKEY_free(privkey);
384199ebb4caSwyllys 
384299ebb4caSwyllys 		if (cert)
384399ebb4caSwyllys 			X509_free(cert);
384499ebb4caSwyllys 
384599ebb4caSwyllys 		if (cacerts)
384699ebb4caSwyllys 			sk_X509_free(cacerts);
384799ebb4caSwyllys 	}
384899ebb4caSwyllys end:
384999ebb4caSwyllys 	if (bio != NULL)
385099ebb4caSwyllys 		(void) BIO_free(bio);
385199ebb4caSwyllys 
385299ebb4caSwyllys 	if (privkey)
385399ebb4caSwyllys 		EVP_PKEY_free(privkey);
385499ebb4caSwyllys 
385599ebb4caSwyllys 	if (cert)
385699ebb4caSwyllys 		X509_free(cert);
385799ebb4caSwyllys 
385899ebb4caSwyllys 	if (cacerts)
385999ebb4caSwyllys 		sk_X509_free(cacerts);
386099ebb4caSwyllys 
386199ebb4caSwyllys 	return (rv);
386299ebb4caSwyllys }
386399ebb4caSwyllys 
386499ebb4caSwyllys KMF_RETURN
386571593db2Swyllys openssl_import_keypair(KMF_HANDLE *kmfh,
386671593db2Swyllys 	char *filename, KMF_CREDENTIAL *cred,
386771593db2Swyllys 	KMF_DATA **certlist, int *ncerts,
386871593db2Swyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
386971593db2Swyllys {
387071593db2Swyllys 	KMF_RETURN	rv = KMF_OK;
387171593db2Swyllys 	EVP_PKEY	*privkey = NULL;
387271593db2Swyllys 	KMF_ENCODE_FORMAT format;
387371593db2Swyllys 
387471593db2Swyllys 	/*
387571593db2Swyllys 	 * auto-detect the file format, regardless of what
387671593db2Swyllys 	 * the 'format' parameters in the params say.
387771593db2Swyllys 	 */
387871593db2Swyllys 	rv = KMF_GetFileFormat(filename, &format);
387971593db2Swyllys 	if (rv != KMF_OK) {
388071593db2Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
388171593db2Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
388271593db2Swyllys 		return (rv);
388371593db2Swyllys 	}
388471593db2Swyllys 
388571593db2Swyllys 	/* This function only works on PEM files */
388671593db2Swyllys 	if (format != KMF_FORMAT_PEM &&
388771593db2Swyllys 		format != KMF_FORMAT_PEM_KEYPAIR)
388871593db2Swyllys 		return (KMF_ERR_ENCODING);
388971593db2Swyllys 
389071593db2Swyllys 	*certlist = NULL;
389171593db2Swyllys 	*keylist = NULL;
389271593db2Swyllys 	*ncerts = 0;
389371593db2Swyllys 	*nkeys = 0;
389471593db2Swyllys 	rv = extract_objects(kmfh, filename,
389571593db2Swyllys 		(uchar_t *)cred->cred,
389671593db2Swyllys 		(uint32_t)cred->credlen,
389771593db2Swyllys 		&privkey, certlist, ncerts);
389871593db2Swyllys 
389971593db2Swyllys 	/* Reached end of import file? */
390071593db2Swyllys 	if (rv == KMF_OK)
390171593db2Swyllys 		/* Convert keys and certs to exportable format */
390271593db2Swyllys 		rv = convertPK12Objects(kmfh, privkey, NULL, NULL,
390371593db2Swyllys 			keylist, nkeys, NULL, NULL);
390471593db2Swyllys 
390571593db2Swyllys end:
390671593db2Swyllys 	if (privkey)
390771593db2Swyllys 		EVP_PKEY_free(privkey);
390871593db2Swyllys 
390971593db2Swyllys 	return (rv);
391071593db2Swyllys }
391171593db2Swyllys 
391271593db2Swyllys KMF_RETURN
391399ebb4caSwyllys OpenSSL_StorePrivateKey(KMF_HANDLE_T handle, KMF_STOREKEY_PARAMS *params,
391499ebb4caSwyllys 	KMF_RAW_KEY_DATA *key)
391599ebb4caSwyllys {
391699ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
391799ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
391899ebb4caSwyllys 	char		*fullpath;
391999ebb4caSwyllys 	EVP_PKEY	*pkey = NULL;
392099ebb4caSwyllys 	BIO		*bio = NULL;
392199ebb4caSwyllys 
392299ebb4caSwyllys 	if (key != NULL) {
392399ebb4caSwyllys 		if (key->keytype == KMF_RSA) {
392499ebb4caSwyllys 			pkey = ImportRawRSAKey(&key->rawdata.rsa);
392599ebb4caSwyllys 		} else if (key->keytype == KMF_DSA) {
392699ebb4caSwyllys 			pkey = ImportRawDSAKey(&key->rawdata.dsa);
392799ebb4caSwyllys 		} else {
392899ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
392999ebb4caSwyllys 		}
393099ebb4caSwyllys 	} else {
393199ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
393299ebb4caSwyllys 	}
393399ebb4caSwyllys 	if (rv != KMF_OK || pkey == NULL)
393499ebb4caSwyllys 		return (rv);
393599ebb4caSwyllys 
393699ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
393799ebb4caSwyllys 			params->sslparms.keyfile);
393899ebb4caSwyllys 
393999ebb4caSwyllys 	if (fullpath == NULL)
394099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
394199ebb4caSwyllys 
394299ebb4caSwyllys 	/* If the requested file exists, return an error */
394399ebb4caSwyllys 	if (access(fullpath, F_OK) == 0) {
394499ebb4caSwyllys 		free(fullpath);
394599ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
394699ebb4caSwyllys 	}
394799ebb4caSwyllys 
394899ebb4caSwyllys 	bio = BIO_new_file(fullpath, "wb");
394999ebb4caSwyllys 	if (bio == NULL) {
395099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
395199ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
395299ebb4caSwyllys 		goto cleanup;
395399ebb4caSwyllys 	}
395499ebb4caSwyllys 
395599ebb4caSwyllys 	rv = ssl_write_private_key(kmfh,
395699ebb4caSwyllys 		params->sslparms.format,
395799ebb4caSwyllys 		bio, &params->cred, pkey);
395899ebb4caSwyllys 
395999ebb4caSwyllys cleanup:
396099ebb4caSwyllys 	if (fullpath)
396199ebb4caSwyllys 		free(fullpath);
396299ebb4caSwyllys 
396399ebb4caSwyllys 	if (pkey)
396499ebb4caSwyllys 		EVP_PKEY_free(pkey);
396599ebb4caSwyllys 
396699ebb4caSwyllys 	if (bio)
396799ebb4caSwyllys 		(void) BIO_free(bio);
396899ebb4caSwyllys 
396999ebb4caSwyllys 	/* Protect the file by making it read-only */
397099ebb4caSwyllys 	if (rv == KMF_OK) {
397199ebb4caSwyllys 		(void) chmod(fullpath, 0400);
397299ebb4caSwyllys 	}
397399ebb4caSwyllys 	return (rv);
397499ebb4caSwyllys }
397599ebb4caSwyllys 
397699ebb4caSwyllys static KMF_RETURN
397799ebb4caSwyllys create_deskey(DES_cblock **deskey)
397899ebb4caSwyllys {
397999ebb4caSwyllys 	DES_cblock *key;
398099ebb4caSwyllys 
398199ebb4caSwyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
398299ebb4caSwyllys 	if (key == NULL) {
398399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
398499ebb4caSwyllys 	}
398599ebb4caSwyllys 
398699ebb4caSwyllys 	if (DES_random_key(key) == 0) {
398799ebb4caSwyllys 		free(key);
398899ebb4caSwyllys 		return (KMF_ERR_KEYGEN_FAILED);
398999ebb4caSwyllys 	}
399099ebb4caSwyllys 
399199ebb4caSwyllys 	*deskey = key;
399299ebb4caSwyllys 	return (KMF_OK);
399399ebb4caSwyllys }
399499ebb4caSwyllys 
399599ebb4caSwyllys #define	KEYGEN_RETRY 3
399699ebb4caSwyllys #define	DES3_KEY_SIZE 24
399799ebb4caSwyllys 
399899ebb4caSwyllys static KMF_RETURN
399999ebb4caSwyllys create_des3key(unsigned char **des3key)
400099ebb4caSwyllys {
400199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
400299ebb4caSwyllys 	DES_cblock *deskey1 = NULL;
400399ebb4caSwyllys 	DES_cblock *deskey2 = NULL;
400499ebb4caSwyllys 	DES_cblock *deskey3 = NULL;
400599ebb4caSwyllys 	unsigned char *newkey = NULL;
400699ebb4caSwyllys 	int retry;
400799ebb4caSwyllys 
400899ebb4caSwyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
400999ebb4caSwyllys 		return (KMF_ERR_MEMORY);
401099ebb4caSwyllys 	}
401199ebb4caSwyllys 
401299ebb4caSwyllys 	/* create the 1st DES key */
401399ebb4caSwyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
401499ebb4caSwyllys 		goto out;
401599ebb4caSwyllys 	}
401699ebb4caSwyllys 
401799ebb4caSwyllys 	/*
401899ebb4caSwyllys 	 * Create the 2nd DES key and make sure its value is different
401999ebb4caSwyllys 	 * from the 1st DES key.
402099ebb4caSwyllys 	 */
402199ebb4caSwyllys 	retry = 0;
402299ebb4caSwyllys 	do {
402399ebb4caSwyllys 		if (deskey2 != NULL) {
402499ebb4caSwyllys 			free(deskey2);
402599ebb4caSwyllys 			deskey2 = NULL;
402699ebb4caSwyllys 		}
402799ebb4caSwyllys 
402899ebb4caSwyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
402999ebb4caSwyllys 			goto out;
403099ebb4caSwyllys 		}
403199ebb4caSwyllys 
403299ebb4caSwyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
403399ebb4caSwyllys 		    == 0) {
403499ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
403599ebb4caSwyllys 			retry++;
403699ebb4caSwyllys 		}
403799ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
403899ebb4caSwyllys 
403999ebb4caSwyllys 	if (ret != KMF_OK) {
404099ebb4caSwyllys 		goto out;
404199ebb4caSwyllys 	}
404299ebb4caSwyllys 
404399ebb4caSwyllys 	/*
404499ebb4caSwyllys 	 * Create the 3rd DES key and make sure its value is different
404599ebb4caSwyllys 	 * from the 2nd DES key.
404699ebb4caSwyllys 	 */
404799ebb4caSwyllys 	retry = 0;
404899ebb4caSwyllys 	do {
404999ebb4caSwyllys 		if (deskey3 != NULL) {
405099ebb4caSwyllys 			free(deskey3);
405199ebb4caSwyllys 			deskey3 = NULL;
405299ebb4caSwyllys 		}
405399ebb4caSwyllys 
405499ebb4caSwyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
405599ebb4caSwyllys 			goto out;
405699ebb4caSwyllys 		}
405799ebb4caSwyllys 
405899ebb4caSwyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
405999ebb4caSwyllys 		    == 0) {
406099ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
406199ebb4caSwyllys 			retry++;
406299ebb4caSwyllys 		}
406399ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
406499ebb4caSwyllys 
406599ebb4caSwyllys 	if (ret != KMF_OK) {
406699ebb4caSwyllys 		goto out;
406799ebb4caSwyllys 	}
406899ebb4caSwyllys 
406999ebb4caSwyllys 	/* Concatenate 3 DES keys into a DES3 key */
407099ebb4caSwyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
407199ebb4caSwyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
407299ebb4caSwyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
407399ebb4caSwyllys 	*des3key = newkey;
407499ebb4caSwyllys 
407599ebb4caSwyllys out:
407699ebb4caSwyllys 	if (deskey1 != NULL)
407799ebb4caSwyllys 		free(deskey1);
407899ebb4caSwyllys 
407999ebb4caSwyllys 	if (deskey2 != NULL)
408099ebb4caSwyllys 		free(deskey2);
408199ebb4caSwyllys 
408299ebb4caSwyllys 	if (deskey3 != NULL)
408399ebb4caSwyllys 		free(deskey3);
408499ebb4caSwyllys 
408599ebb4caSwyllys 	if (ret != KMF_OK && newkey != NULL)
408699ebb4caSwyllys 		free(newkey);
408799ebb4caSwyllys 
408899ebb4caSwyllys 	return (ret);
408999ebb4caSwyllys }
409099ebb4caSwyllys 
409199ebb4caSwyllys KMF_RETURN
409299ebb4caSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle, KMF_CREATESYMKEY_PARAMS *params,
409399ebb4caSwyllys 	KMF_KEY_HANDLE *symkey)
409499ebb4caSwyllys {
409599ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
409699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
409799ebb4caSwyllys 	char *fullpath = NULL;
409899ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
409999ebb4caSwyllys 	DES_cblock *deskey = NULL;
410099ebb4caSwyllys 	unsigned char *des3key = NULL;
410199ebb4caSwyllys 	unsigned char *random = NULL;
410299ebb4caSwyllys 	int fd = -1;
410399ebb4caSwyllys 
410499ebb4caSwyllys 	if (kmfh == NULL)
410599ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
410699ebb4caSwyllys 
410799ebb4caSwyllys 	if (params == NULL || params->sslparms.keyfile == NULL) {
410899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
410999ebb4caSwyllys 	}
411099ebb4caSwyllys 
411199ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
411299ebb4caSwyllys 		params->sslparms.keyfile);
411399ebb4caSwyllys 	if (fullpath == NULL)
411499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
411599ebb4caSwyllys 
411699ebb4caSwyllys 	/* If the requested file exists, return an error */
411799ebb4caSwyllys 	if (access(fullpath, F_OK) == 0) {
411899ebb4caSwyllys 		free(fullpath);
411999ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
412099ebb4caSwyllys 	}
412199ebb4caSwyllys 
412299ebb4caSwyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
412399ebb4caSwyllys 	if (fd == -1) {
412499ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
412599ebb4caSwyllys 		goto out;
412699ebb4caSwyllys 	}
412799ebb4caSwyllys 
412899ebb4caSwyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
412999ebb4caSwyllys 	if (rkey == NULL) {
413099ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
413199ebb4caSwyllys 		goto out;
413299ebb4caSwyllys 	}
413399ebb4caSwyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
413499ebb4caSwyllys 
413599ebb4caSwyllys 	if (params->keytype == KMF_DES) {
413699ebb4caSwyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
413799ebb4caSwyllys 			goto out;
413899ebb4caSwyllys 		}
413999ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)deskey;
414099ebb4caSwyllys 		rkey->keydata.len = 8;
414199ebb4caSwyllys 
414299ebb4caSwyllys 		symkey->keyalg = KMF_DES;
414399ebb4caSwyllys 
414499ebb4caSwyllys 	} else if (params->keytype == KMF_DES3) {
414599ebb4caSwyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
414699ebb4caSwyllys 			goto out;
414799ebb4caSwyllys 		}
414899ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)des3key;
414999ebb4caSwyllys 		rkey->keydata.len = DES3_KEY_SIZE;
415099ebb4caSwyllys 		symkey->keyalg = KMF_DES3;
415199ebb4caSwyllys 
415299ebb4caSwyllys 	} else if (params->keytype == KMF_AES || params->keytype == KMF_RC4) {
415399ebb4caSwyllys 		int bytes;
415499ebb4caSwyllys 
415599ebb4caSwyllys 		if (params->keylength % 8 != 0) {
415699ebb4caSwyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
415799ebb4caSwyllys 			goto out;
415899ebb4caSwyllys 		}
415999ebb4caSwyllys 
416099ebb4caSwyllys 		if (params->keytype == KMF_AES) {
416199ebb4caSwyllys 			if (params->keylength != 128 &&
416299ebb4caSwyllys 			    params->keylength != 192 &&
416399ebb4caSwyllys 			    params->keylength != 256) {
416499ebb4caSwyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
416599ebb4caSwyllys 				goto out;
416699ebb4caSwyllys 			}
416799ebb4caSwyllys 		}
416899ebb4caSwyllys 
416999ebb4caSwyllys 		bytes = params->keylength/8;
417099ebb4caSwyllys 		random = malloc(bytes);
417199ebb4caSwyllys 		if (random == NULL) {
417299ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
417399ebb4caSwyllys 			goto out;
417499ebb4caSwyllys 		}
417599ebb4caSwyllys 		if (RAND_bytes(random, bytes) != 1) {
417699ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
417799ebb4caSwyllys 			goto out;
417899ebb4caSwyllys 		}
417999ebb4caSwyllys 
418099ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)random;
418199ebb4caSwyllys 		rkey->keydata.len = bytes;
418299ebb4caSwyllys 		symkey->keyalg = params->keytype;
418399ebb4caSwyllys 
418499ebb4caSwyllys 	} else {
418599ebb4caSwyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
418699ebb4caSwyllys 		goto out;
418799ebb4caSwyllys 	}
418899ebb4caSwyllys 
418999ebb4caSwyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
419099ebb4caSwyllys 
419199ebb4caSwyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
419299ebb4caSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
419399ebb4caSwyllys 	symkey->keylabel = (char *)fullpath;
419499ebb4caSwyllys 	symkey->israw = TRUE;
419599ebb4caSwyllys 	symkey->keyp = rkey;
419699ebb4caSwyllys 
419799ebb4caSwyllys out:
419899ebb4caSwyllys 	if (fd != -1)
419999ebb4caSwyllys 		(void) close(fd);
420099ebb4caSwyllys 
420199ebb4caSwyllys 	if (ret != KMF_OK && fullpath != NULL) {
420299ebb4caSwyllys 		free(fullpath);
420399ebb4caSwyllys 	}
420499ebb4caSwyllys 	if (ret != KMF_OK) {
420599ebb4caSwyllys 		KMF_FreeRawSymKey(rkey);
420699ebb4caSwyllys 		symkey->keyp = NULL;
420799ebb4caSwyllys 		symkey->keyalg = KMF_KEYALG_NONE;
420899ebb4caSwyllys 	}
420999ebb4caSwyllys 
421099ebb4caSwyllys 	return (ret);
421199ebb4caSwyllys }
421299ebb4caSwyllys 
421399ebb4caSwyllys 
421499ebb4caSwyllys KMF_RETURN
421599ebb4caSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, KMF_VERIFYCRL_PARAMS *params)
421699ebb4caSwyllys {
421799ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
421899ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
421999ebb4caSwyllys 	BIO		*bcrl = NULL;
422099ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
422199ebb4caSwyllys 	X509		*xcert = NULL;
422299ebb4caSwyllys 	EVP_PKEY	*pkey;
422399ebb4caSwyllys 	int		sslret;
422499ebb4caSwyllys 	KMF_ENCODE_FORMAT crl_format;
422599ebb4caSwyllys 	unsigned char	*p;
422699ebb4caSwyllys 	long		len;
422799ebb4caSwyllys 
422899ebb4caSwyllys 	if (params->crl_name == NULL || params->tacert == NULL) {
422999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
423099ebb4caSwyllys 	}
423199ebb4caSwyllys 
423299ebb4caSwyllys 	ret = KMF_GetFileFormat(params->crl_name, &crl_format);
423399ebb4caSwyllys 	if (ret != KMF_OK)
423499ebb4caSwyllys 		return (ret);
423599ebb4caSwyllys 
423699ebb4caSwyllys 	bcrl = BIO_new_file(params->crl_name, "rb");
423799ebb4caSwyllys 	if (bcrl == NULL)	{
423899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
423999ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
424099ebb4caSwyllys 		goto cleanup;
424199ebb4caSwyllys 	}
424299ebb4caSwyllys 
424399ebb4caSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
424499ebb4caSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
424599ebb4caSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
424699ebb4caSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
424799ebb4caSwyllys 	} else {
424899ebb4caSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
424999ebb4caSwyllys 		goto cleanup;
425099ebb4caSwyllys 	}
425199ebb4caSwyllys 
425299ebb4caSwyllys 	if (xcrl == NULL) {
425399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
425499ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
425599ebb4caSwyllys 		goto cleanup;
425699ebb4caSwyllys 	}
425799ebb4caSwyllys 
425899ebb4caSwyllys 	p = params->tacert->Data;
425999ebb4caSwyllys 	len = params->tacert->Length;
426099ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
426199ebb4caSwyllys 
426299ebb4caSwyllys 	if (xcert == NULL) {
426399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
426499ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
426599ebb4caSwyllys 		goto cleanup;
426699ebb4caSwyllys 	}
426799ebb4caSwyllys 
426899ebb4caSwyllys 	/* Get issuer certificate public key */
426999ebb4caSwyllys 	pkey = X509_get_pubkey(xcert);
427099ebb4caSwyllys 	if (!pkey) {
427199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
427299ebb4caSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
427399ebb4caSwyllys 		goto cleanup;
427499ebb4caSwyllys 	}
427599ebb4caSwyllys 
427699ebb4caSwyllys 	/* Verify CRL signature */
427799ebb4caSwyllys 	sslret = X509_CRL_verify(xcrl, pkey);
427899ebb4caSwyllys 	EVP_PKEY_free(pkey);
427999ebb4caSwyllys 	if (sslret > 0) {
428099ebb4caSwyllys 		ret = KMF_OK;
428199ebb4caSwyllys 	} else {
428299ebb4caSwyllys 		SET_ERROR(kmfh, sslret);
428399ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
428499ebb4caSwyllys 	}
428599ebb4caSwyllys 
428699ebb4caSwyllys cleanup:
428799ebb4caSwyllys 	if (bcrl != NULL)
428899ebb4caSwyllys 		(void) BIO_free(bcrl);
428999ebb4caSwyllys 
429099ebb4caSwyllys 	if (xcrl != NULL)
429199ebb4caSwyllys 		X509_CRL_free(xcrl);
429299ebb4caSwyllys 
429399ebb4caSwyllys 	if (xcert != NULL)
429499ebb4caSwyllys 		X509_free(xcert);
429599ebb4caSwyllys 
429699ebb4caSwyllys 	return (ret);
429799ebb4caSwyllys 
429899ebb4caSwyllys }
429999ebb4caSwyllys 
430099ebb4caSwyllys KMF_RETURN
430199ebb4caSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle,
430299ebb4caSwyllys 	KMF_CHECKCRLDATE_PARAMS *params)
430399ebb4caSwyllys {
430499ebb4caSwyllys 
430599ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
430699ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
430799ebb4caSwyllys 	KMF_ENCODE_FORMAT crl_format;
430899ebb4caSwyllys 	BIO		*bcrl = NULL;
430999ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
431099ebb4caSwyllys 	int		i;
431199ebb4caSwyllys 
431299ebb4caSwyllys 	if (params == NULL || params->crl_name == NULL) {
431399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
431499ebb4caSwyllys 	}
431599ebb4caSwyllys 
431699ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, params->crl_name, &crl_format);
431799ebb4caSwyllys 	if (ret != KMF_OK)
431899ebb4caSwyllys 		return (ret);
431999ebb4caSwyllys 
432099ebb4caSwyllys 	bcrl = BIO_new_file(params->crl_name, "rb");
432199ebb4caSwyllys 	if (bcrl == NULL)	{
432299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
432399ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
432499ebb4caSwyllys 		goto cleanup;
432599ebb4caSwyllys 	}
432699ebb4caSwyllys 
432799ebb4caSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
432899ebb4caSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
432999ebb4caSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
433099ebb4caSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
433199ebb4caSwyllys 	}
433299ebb4caSwyllys 
433399ebb4caSwyllys 	if (xcrl == NULL) {
433499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
433599ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
433699ebb4caSwyllys 		goto cleanup;
433799ebb4caSwyllys 	}
433899ebb4caSwyllys 
433999ebb4caSwyllys 	i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL);
434099ebb4caSwyllys 	if (i >= 0) {
434199ebb4caSwyllys 		ret = KMF_ERR_VALIDITY_PERIOD;
434299ebb4caSwyllys 		goto cleanup;
434399ebb4caSwyllys 	}
434499ebb4caSwyllys 
434599ebb4caSwyllys 	if (X509_CRL_get_nextUpdate(xcrl)) {
434699ebb4caSwyllys 		i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL);
434799ebb4caSwyllys 
434899ebb4caSwyllys 		if (i <= 0) {
434999ebb4caSwyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
435099ebb4caSwyllys 			goto cleanup;
435199ebb4caSwyllys 		}
435299ebb4caSwyllys 	}
435399ebb4caSwyllys 
435499ebb4caSwyllys 	ret = KMF_OK;
435599ebb4caSwyllys 
435699ebb4caSwyllys cleanup:
435799ebb4caSwyllys 	if (bcrl != NULL)
435899ebb4caSwyllys 		(void) BIO_free(bcrl);
435999ebb4caSwyllys 
436099ebb4caSwyllys 	if (xcrl != NULL)
436199ebb4caSwyllys 		X509_CRL_free(xcrl);
436299ebb4caSwyllys 
436399ebb4caSwyllys 	return (ret);
436499ebb4caSwyllys }
436599ebb4caSwyllys 
436699ebb4caSwyllys /*
436799ebb4caSwyllys  * Check a file to see if it is a CRL file with PEM or DER format.
436899ebb4caSwyllys  * If success, return its format in the "pformat" argument.
436999ebb4caSwyllys  */
437099ebb4caSwyllys KMF_RETURN
437199ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
437299ebb4caSwyllys {
437399ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
437499ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
437599ebb4caSwyllys 	BIO		*bio = NULL;
437699ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
437799ebb4caSwyllys 
437899ebb4caSwyllys 	if (filename == NULL) {
437999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
438099ebb4caSwyllys 	}
438199ebb4caSwyllys 
438299ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
438399ebb4caSwyllys 	if (bio == NULL)	{
438499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
438599ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
438699ebb4caSwyllys 		goto out;
438799ebb4caSwyllys 	}
438899ebb4caSwyllys 
438999ebb4caSwyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
439099ebb4caSwyllys 		*pformat = KMF_FORMAT_PEM;
439199ebb4caSwyllys 		goto out;
439299ebb4caSwyllys 	}
439399ebb4caSwyllys 	(void) BIO_free(bio);
439499ebb4caSwyllys 
439599ebb4caSwyllys 	/*
439699ebb4caSwyllys 	 * Now try to read it as raw DER data.
439799ebb4caSwyllys 	 */
439899ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
439999ebb4caSwyllys 	if (bio == NULL)	{
440099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
440199ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
440299ebb4caSwyllys 		goto out;
440399ebb4caSwyllys 	}
440499ebb4caSwyllys 
440599ebb4caSwyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
440699ebb4caSwyllys 		*pformat = KMF_FORMAT_ASN1;
440799ebb4caSwyllys 	} else {
440899ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
440999ebb4caSwyllys 	}
441099ebb4caSwyllys 
441199ebb4caSwyllys out:
441299ebb4caSwyllys 	if (bio != NULL)
441399ebb4caSwyllys 		(void) BIO_free(bio);
441499ebb4caSwyllys 
441599ebb4caSwyllys 	if (xcrl != NULL)
441699ebb4caSwyllys 		X509_CRL_free(xcrl);
441799ebb4caSwyllys 
441899ebb4caSwyllys 	return (ret);
441999ebb4caSwyllys }
442099ebb4caSwyllys 
442199ebb4caSwyllys /*
442299ebb4caSwyllys  * Check a file to see if it is a certficate file with PEM or DER format.
442399ebb4caSwyllys  * If success, return its format in the pformat argument.
442499ebb4caSwyllys  */
442599ebb4caSwyllys KMF_RETURN
442699ebb4caSwyllys OpenSSL_IsCertFile(KMF_HANDLE_T handle, char *filename,
442799ebb4caSwyllys 	KMF_ENCODE_FORMAT *pformat)
442899ebb4caSwyllys {
442999ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
443099ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
443199ebb4caSwyllys 	BIO		*bio = NULL;
443299ebb4caSwyllys 	X509		*xcert = NULL;
443399ebb4caSwyllys 
443499ebb4caSwyllys 	if (filename == NULL) {
443599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
443699ebb4caSwyllys 	}
443799ebb4caSwyllys 
443899ebb4caSwyllys 	ret = KMF_GetFileFormat(filename, pformat);
443999ebb4caSwyllys 	if (ret != KMF_OK)
444099ebb4caSwyllys 		return (ret);
444199ebb4caSwyllys 
444299ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
444399ebb4caSwyllys 	if (bio == NULL)	{
444499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
444599ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
444699ebb4caSwyllys 		goto out;
444799ebb4caSwyllys 	}
444899ebb4caSwyllys 
444999ebb4caSwyllys 	if ((*pformat) == KMF_FORMAT_PEM) {
445099ebb4caSwyllys 		if ((xcert = PEM_read_bio_X509(bio, NULL,
445199ebb4caSwyllys 			NULL, NULL)) == NULL) {
445299ebb4caSwyllys 			ret = KMF_ERR_BAD_CERTFILE;
445399ebb4caSwyllys 		}
445499ebb4caSwyllys 	} else if ((*pformat) == KMF_FORMAT_ASN1) {
445599ebb4caSwyllys 		if ((xcert = d2i_X509_bio(bio, NULL)) == NULL) {
445699ebb4caSwyllys 			ret = KMF_ERR_BAD_CERTFILE;
445799ebb4caSwyllys 		}
445899ebb4caSwyllys 	} else {
445999ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
446099ebb4caSwyllys 	}
446199ebb4caSwyllys 
446299ebb4caSwyllys out:
446399ebb4caSwyllys 	if (bio != NULL)
446499ebb4caSwyllys 		(void) BIO_free(bio);
446599ebb4caSwyllys 
446699ebb4caSwyllys 	if (xcert != NULL)
446799ebb4caSwyllys 		X509_free(xcert);
446899ebb4caSwyllys 
446999ebb4caSwyllys 	return (ret);
447099ebb4caSwyllys }
447199ebb4caSwyllys 
447299ebb4caSwyllys KMF_RETURN
447399ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
447499ebb4caSwyllys     KMF_RAW_SYM_KEY *rkey)
447599ebb4caSwyllys {
447699ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
447799ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
447899ebb4caSwyllys 	KMF_DATA	keyvalue;
447999ebb4caSwyllys 
448099ebb4caSwyllys 	if (kmfh == NULL)
448199ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
448299ebb4caSwyllys 
448399ebb4caSwyllys 	if (symkey == NULL || rkey == NULL)
448499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
448599ebb4caSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
448699ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
448799ebb4caSwyllys 
448899ebb4caSwyllys 	if (symkey->israw) {
448999ebb4caSwyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
449099ebb4caSwyllys 
449199ebb4caSwyllys 		if (rawkey == NULL ||
449299ebb4caSwyllys 		    rawkey->keydata.val == NULL ||
449399ebb4caSwyllys 		    rawkey->keydata.len == 0)
449499ebb4caSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
449599ebb4caSwyllys 
449699ebb4caSwyllys 		rkey->keydata.len = rawkey->keydata.len;
449799ebb4caSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
449899ebb4caSwyllys 			return (KMF_ERR_MEMORY);
449999ebb4caSwyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
450099ebb4caSwyllys 		    rkey->keydata.len);
450199ebb4caSwyllys 	} else {
450299ebb4caSwyllys 		rv = KMF_ReadInputFile(handle, symkey->keylabel, &keyvalue);
450399ebb4caSwyllys 		if (rv != KMF_OK)
450499ebb4caSwyllys 			return (rv);
450599ebb4caSwyllys 		rkey->keydata.len = keyvalue.Length;
450699ebb4caSwyllys 		rkey->keydata.val = keyvalue.Data;
450799ebb4caSwyllys 	}
450899ebb4caSwyllys 
450999ebb4caSwyllys 	return (rv);
451099ebb4caSwyllys }
4511