199ebb4caSwyllys /*
271593db2Swyllys  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
399ebb4caSwyllys  * Use is subject to license terms.
499ebb4caSwyllys  */
59a767088Shaimay /*
69a767088Shaimay  * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
79a767088Shaimay  * project 2000.
89a767088Shaimay  */
99a767088Shaimay /*
109a767088Shaimay  * ====================================================================
119a767088Shaimay  * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
129a767088Shaimay  *
139a767088Shaimay  * Redistribution and use in source and binary forms, with or without
149a767088Shaimay  * modification, are permitted provided that the following conditions
159a767088Shaimay  * are met:
169a767088Shaimay  *
179a767088Shaimay  * 1. Redistributions of source code must retain the above copyright
189a767088Shaimay  *    notice, this list of conditions and the following disclaimer.
199a767088Shaimay  *
209a767088Shaimay  * 2. Redistributions in binary form must reproduce the above copyright
219a767088Shaimay  *    notice, this list of conditions and the following disclaimer in
229a767088Shaimay  *    the documentation and/or other materials provided with the
239a767088Shaimay  *    distribution.
249a767088Shaimay  *
259a767088Shaimay  * 3. All advertising materials mentioning features or use of this
269a767088Shaimay  *    software must display the following acknowledgment:
279a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
289a767088Shaimay  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
299a767088Shaimay  *
309a767088Shaimay  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
319a767088Shaimay  *    endorse or promote products derived from this software without
329a767088Shaimay  *    prior written permission. For written permission, please contact
339a767088Shaimay  *    licensing@OpenSSL.org.
349a767088Shaimay  *
359a767088Shaimay  * 5. Products derived from this software may not be called "OpenSSL"
369a767088Shaimay  *    nor may "OpenSSL" appear in their names without prior written
379a767088Shaimay  *    permission of the OpenSSL Project.
389a767088Shaimay  *
399a767088Shaimay  * 6. Redistributions of any form whatsoever must retain the following
409a767088Shaimay  *    acknowledgment:
419a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
429a767088Shaimay  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
439a767088Shaimay  *
449a767088Shaimay  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
459a767088Shaimay  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
469a767088Shaimay  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
479a767088Shaimay  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
489a767088Shaimay  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
499a767088Shaimay  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
509a767088Shaimay  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
519a767088Shaimay  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
529a767088Shaimay  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
539a767088Shaimay  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
549a767088Shaimay  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
559a767088Shaimay  * OF THE POSSIBILITY OF SUCH DAMAGE.
569a767088Shaimay  * ====================================================================
579a767088Shaimay  *
589a767088Shaimay  * This product includes cryptographic software written by Eric Young
599a767088Shaimay  * (eay@cryptsoft.com).  This product includes software written by Tim
609a767088Shaimay  * Hudson (tjh@cryptsoft.com).
619a767088Shaimay  *
629a767088Shaimay  */
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 <fcntl.h>
7099ebb4caSwyllys #include <sys/stat.h>
7199ebb4caSwyllys #include <dirent.h>
7299ebb4caSwyllys #include <cryptoutil.h>
7399ebb4caSwyllys #include <synch.h>
7499ebb4caSwyllys #include <thread.h>
7599ebb4caSwyllys 
7699ebb4caSwyllys /* OPENSSL related headers */
7799ebb4caSwyllys #include <openssl/bio.h>
7899ebb4caSwyllys #include <openssl/bn.h>
7999ebb4caSwyllys #include <openssl/asn1.h>
8099ebb4caSwyllys #include <openssl/err.h>
8199ebb4caSwyllys #include <openssl/bn.h>
8299ebb4caSwyllys #include <openssl/x509.h>
8399ebb4caSwyllys #include <openssl/rsa.h>
8499ebb4caSwyllys #include <openssl/dsa.h>
8599ebb4caSwyllys #include <openssl/x509v3.h>
8699ebb4caSwyllys #include <openssl/objects.h>
8799ebb4caSwyllys #include <openssl/pem.h>
8899ebb4caSwyllys #include <openssl/pkcs12.h>
8999ebb4caSwyllys #include <openssl/ocsp.h>
9099ebb4caSwyllys #include <openssl/des.h>
9199ebb4caSwyllys #include <openssl/rand.h>
9299ebb4caSwyllys 
9399ebb4caSwyllys #define	PRINT_ANY_EXTENSION (\
9499ebb4caSwyllys 	KMF_X509_EXT_KEY_USAGE |\
9599ebb4caSwyllys 	KMF_X509_EXT_CERT_POLICIES |\
9699ebb4caSwyllys 	KMF_X509_EXT_SUBJALTNAME |\
9799ebb4caSwyllys 	KMF_X509_EXT_BASIC_CONSTRAINTS |\
9899ebb4caSwyllys 	KMF_X509_EXT_NAME_CONSTRAINTS |\
9999ebb4caSwyllys 	KMF_X509_EXT_POLICY_CONSTRAINTS |\
10099ebb4caSwyllys 	KMF_X509_EXT_EXT_KEY_USAGE |\
10199ebb4caSwyllys 	KMF_X509_EXT_INHIBIT_ANY_POLICY |\
10299ebb4caSwyllys 	KMF_X509_EXT_AUTH_KEY_ID |\
10399ebb4caSwyllys 	KMF_X509_EXT_SUBJ_KEY_ID |\
10499ebb4caSwyllys 	KMF_X509_EXT_POLICY_MAPPING)
10599ebb4caSwyllys 
10699ebb4caSwyllys static BIO *bio_err = NULL;
10799ebb4caSwyllys static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
10899ebb4caSwyllys 	0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
10999ebb4caSwyllys 	0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
11099ebb4caSwyllys 	0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
11199ebb4caSwyllys 	0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
11299ebb4caSwyllys 	0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
11399ebb4caSwyllys 	0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
11499ebb4caSwyllys 	0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
11599ebb4caSwyllys 	0x91 };
11699ebb4caSwyllys 
11799ebb4caSwyllys static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
11899ebb4caSwyllys 	0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
11999ebb4caSwyllys 	0x8e, 0xda, 0xce, 0x91, 0x5f };
12099ebb4caSwyllys 
12199ebb4caSwyllys static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
12299ebb4caSwyllys 	0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
12399ebb4caSwyllys 	0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
12499ebb4caSwyllys 	0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
12599ebb4caSwyllys 	0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
12699ebb4caSwyllys 	0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
12799ebb4caSwyllys 	0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
12899ebb4caSwyllys 	0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
12999ebb4caSwyllys 	0x02 };
13099ebb4caSwyllys 
13199ebb4caSwyllys #define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
13299ebb4caSwyllys 	h->lasterr.errcode = c;
13399ebb4caSwyllys 
13499ebb4caSwyllys #define	SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
13599ebb4caSwyllys 
13699ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX;
13799ebb4caSwyllys static int ssl_initialized = 0;
13899ebb4caSwyllys 
13971593db2Swyllys static KMF_RETURN
14002744e81Swyllys extract_objects(KMF_HANDLE *, KMF_FINDCERT_PARAMS *, char *,
14102744e81Swyllys 	CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
14271593db2Swyllys 
14371593db2Swyllys static KMF_RETURN
14471593db2Swyllys kmf_load_cert(KMF_HANDLE *, KMF_FINDCERT_PARAMS *, char *, KMF_DATA *);
14571593db2Swyllys 
14602744e81Swyllys static KMF_RETURN
14702744e81Swyllys sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
14802744e81Swyllys 
14902744e81Swyllys static EVP_PKEY *
15002744e81Swyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *);
15102744e81Swyllys 
15299ebb4caSwyllys KMF_RETURN
15399ebb4caSwyllys OpenSSL_FindCert(KMF_HANDLE_T,
15499ebb4caSwyllys 	KMF_FINDCERT_PARAMS *,
15599ebb4caSwyllys 	KMF_X509_DER_CERT *,
15699ebb4caSwyllys 	uint32_t *);
15799ebb4caSwyllys 
15899ebb4caSwyllys void
15999ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
16099ebb4caSwyllys 
16199ebb4caSwyllys KMF_RETURN
16299ebb4caSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, KMF_STORECERT_PARAMS *, KMF_DATA *);
16399ebb4caSwyllys 
16499ebb4caSwyllys KMF_RETURN
16599ebb4caSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, KMF_DELETECERT_PARAMS *);
16699ebb4caSwyllys 
16799ebb4caSwyllys KMF_RETURN
16899ebb4caSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T, KMF_CREATEKEYPAIR_PARAMS *,
16999ebb4caSwyllys 	KMF_KEY_HANDLE *, KMF_KEY_HANDLE *);
17099ebb4caSwyllys 
17199ebb4caSwyllys KMF_RETURN
17299ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T,  KMF_KEY_HANDLE *, KMF_DATA *);
17399ebb4caSwyllys 
17499ebb4caSwyllys KMF_RETURN
17599ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
17699ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
17799ebb4caSwyllys 
17899ebb4caSwyllys KMF_RETURN
17999ebb4caSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T, KMF_DELETEKEY_PARAMS *,
18099ebb4caSwyllys 	KMF_KEY_HANDLE *, boolean_t);
18199ebb4caSwyllys 
18299ebb4caSwyllys KMF_RETURN
18399ebb4caSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T, KMF_IMPORTCRL_PARAMS *);
18499ebb4caSwyllys 
18599ebb4caSwyllys KMF_RETURN
18699ebb4caSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T, KMF_DELETECRL_PARAMS *);
18799ebb4caSwyllys 
18899ebb4caSwyllys KMF_RETURN
18999ebb4caSwyllys OpenSSL_ListCRL(KMF_HANDLE_T, KMF_LISTCRL_PARAMS *, char **);
19099ebb4caSwyllys 
19199ebb4caSwyllys KMF_RETURN
19299ebb4caSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T, KMF_FINDCERTINCRL_PARAMS *);
19399ebb4caSwyllys 
19499ebb4caSwyllys KMF_RETURN
19599ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
19699ebb4caSwyllys 	KMF_PRINTABLE_ITEM, char *);
19799ebb4caSwyllys 
19899ebb4caSwyllys KMF_RETURN
19999ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
20099ebb4caSwyllys 
20199ebb4caSwyllys KMF_RETURN
20299ebb4caSwyllys OpenSSL_GetPrikeyByCert(KMF_HANDLE_T, KMF_CRYPTOWITHCERT_PARAMS *, KMF_DATA *,
20399ebb4caSwyllys 	KMF_KEY_HANDLE *, KMF_KEY_ALG);
20499ebb4caSwyllys 
20599ebb4caSwyllys KMF_RETURN
20699ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
20799ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
20899ebb4caSwyllys 
20999ebb4caSwyllys KMF_RETURN
21099ebb4caSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, KMF_OCSPREQUEST_PARAMS *,
21199ebb4caSwyllys 	char *reqfile);
21299ebb4caSwyllys 
21399ebb4caSwyllys KMF_RETURN
21499ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, KMF_OCSPRESPONSE_PARAMS_INPUT *,
21599ebb4caSwyllys     KMF_OCSPRESPONSE_PARAMS_OUTPUT *);
21699ebb4caSwyllys 
21799ebb4caSwyllys KMF_RETURN
21899ebb4caSwyllys OpenSSL_FindKey(KMF_HANDLE_T, KMF_FINDKEY_PARAMS *,
21999ebb4caSwyllys 	KMF_KEY_HANDLE *, uint32_t *);
22099ebb4caSwyllys 
22199ebb4caSwyllys KMF_RETURN
22299ebb4caSwyllys OpenSSL_ExportP12(KMF_HANDLE_T,
22399ebb4caSwyllys 	KMF_EXPORTP12_PARAMS *,
22499ebb4caSwyllys 	int, KMF_X509_DER_CERT *,
22599ebb4caSwyllys 	int, KMF_KEY_HANDLE *,
22699ebb4caSwyllys 	char *);
22799ebb4caSwyllys 
22899ebb4caSwyllys KMF_RETURN
22999ebb4caSwyllys OpenSSL_StorePrivateKey(KMF_HANDLE_T, KMF_STOREKEY_PARAMS *,
23099ebb4caSwyllys 	KMF_RAW_KEY_DATA *);
23199ebb4caSwyllys 
23299ebb4caSwyllys KMF_RETURN
23399ebb4caSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T, KMF_CREATESYMKEY_PARAMS *,
23499ebb4caSwyllys 	KMF_KEY_HANDLE *);
23599ebb4caSwyllys 
23699ebb4caSwyllys KMF_RETURN
23799ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
23899ebb4caSwyllys 
23999ebb4caSwyllys KMF_RETURN
24099ebb4caSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T, KMF_VERIFYCRL_PARAMS *);
24199ebb4caSwyllys 
24299ebb4caSwyllys KMF_RETURN
24399ebb4caSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T, KMF_CHECKCRLDATE_PARAMS *);
24499ebb4caSwyllys 
24502744e81Swyllys KMF_RETURN
24602744e81Swyllys OpenSSL_VerifyDataWithCert(KMF_HANDLE_T, KMF_ALGORITHM_INDEX,
24702744e81Swyllys 	KMF_DATA *, KMF_DATA *, KMF_DATA *);
24802744e81Swyllys 
24999ebb4caSwyllys static
25099ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table =
25199ebb4caSwyllys {
25299ebb4caSwyllys 	1,				/* Version */
25399ebb4caSwyllys 	NULL, /* ConfigureKeystore */
25499ebb4caSwyllys 	OpenSSL_FindCert,
25599ebb4caSwyllys 	OpenSSL_FreeKMFCert,
25699ebb4caSwyllys 	OpenSSL_StoreCert,
25799ebb4caSwyllys 	NULL, /* ImportCert */
25899ebb4caSwyllys 	OpenSSL_ImportCRL,
25999ebb4caSwyllys 	OpenSSL_DeleteCert,
26099ebb4caSwyllys 	OpenSSL_DeleteCRL,
26199ebb4caSwyllys 	OpenSSL_CreateKeypair,
26299ebb4caSwyllys 	OpenSSL_FindKey,
26399ebb4caSwyllys 	OpenSSL_EncodePubKeyData,
26499ebb4caSwyllys 	OpenSSL_SignData,
26599ebb4caSwyllys 	OpenSSL_DeleteKey,
26699ebb4caSwyllys 	OpenSSL_ListCRL,
26799ebb4caSwyllys 	NULL,	/* FindCRL */
26899ebb4caSwyllys 	OpenSSL_FindCertInCRL,
26999ebb4caSwyllys 	OpenSSL_GetErrorString,
27099ebb4caSwyllys 	OpenSSL_GetPrikeyByCert,
27199ebb4caSwyllys 	OpenSSL_DecryptData,
27299ebb4caSwyllys 	OpenSSL_ExportP12,
27399ebb4caSwyllys 	OpenSSL_StorePrivateKey,
27499ebb4caSwyllys 	OpenSSL_CreateSymKey,
27599ebb4caSwyllys 	OpenSSL_GetSymKeyValue,
27699ebb4caSwyllys 	NULL,	/* SetTokenPin */
27702744e81Swyllys 	OpenSSL_VerifyDataWithCert,
27899ebb4caSwyllys 	NULL	/* Finalize */
27999ebb4caSwyllys };
28099ebb4caSwyllys 
28199ebb4caSwyllys static mutex_t *lock_cs;
28299ebb4caSwyllys static long *lock_count;
28399ebb4caSwyllys 
28499ebb4caSwyllys static void
28599ebb4caSwyllys /*ARGSUSED*/
28699ebb4caSwyllys locking_cb(int mode, int type, char *file, int line)
28799ebb4caSwyllys {
28899ebb4caSwyllys 	if (mode & CRYPTO_LOCK) {
28999ebb4caSwyllys 		(void) mutex_lock(&(lock_cs[type]));
29099ebb4caSwyllys 		lock_count[type]++;
29199ebb4caSwyllys 	} else {
29299ebb4caSwyllys 		(void) mutex_unlock(&(lock_cs[type]));
29399ebb4caSwyllys 	}
29499ebb4caSwyllys }
29599ebb4caSwyllys 
29699ebb4caSwyllys static unsigned long
29799ebb4caSwyllys thread_id()
29899ebb4caSwyllys {
29999ebb4caSwyllys 	return ((unsigned long)thr_self());
30099ebb4caSwyllys }
30199ebb4caSwyllys 
30299ebb4caSwyllys KMF_PLUGIN_FUNCLIST *
30399ebb4caSwyllys KMF_Plugin_Initialize()
30499ebb4caSwyllys {
30599ebb4caSwyllys 	int i;
30699ebb4caSwyllys 
30799ebb4caSwyllys 	(void) mutex_lock(&init_lock);
30899ebb4caSwyllys 	if (!ssl_initialized) {
30999ebb4caSwyllys 		OpenSSL_add_all_algorithms();
31099ebb4caSwyllys 
31199ebb4caSwyllys 		/* Enable error strings for reporting */
31299ebb4caSwyllys 		ERR_load_crypto_strings();
31399ebb4caSwyllys 
31499ebb4caSwyllys 		/*
31599ebb4caSwyllys 		 * Add support for extension OIDs that are not yet in the
31699ebb4caSwyllys 		 * openssl default set.
31799ebb4caSwyllys 		 */
31899ebb4caSwyllys 		(void) OBJ_create("2.5.29.30", "nameConstraints",
31999ebb4caSwyllys 		    "X509v3 Name Constraints");
32099ebb4caSwyllys 		(void) OBJ_create("2.5.29.33", "policyMappings",
32199ebb4caSwyllys 		    "X509v3 Policy Mappings");
32299ebb4caSwyllys 		(void) OBJ_create("2.5.29.36", "policyConstraints",
32399ebb4caSwyllys 		    "X509v3 Policy Constraints");
32499ebb4caSwyllys 		(void) OBJ_create("2.5.29.46", "freshestCRL",
32599ebb4caSwyllys 		    "X509v3 Freshest CRL");
32699ebb4caSwyllys 		(void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
32799ebb4caSwyllys 		    "X509v3 Inhibit Any-Policy");
32899ebb4caSwyllys 		/*
32999ebb4caSwyllys 		 * Set up for thread-safe operation.
33099ebb4caSwyllys 		 */
33199ebb4caSwyllys 		lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
33299ebb4caSwyllys 		if (lock_cs == NULL) {
33399ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
33499ebb4caSwyllys 			return (NULL);
33599ebb4caSwyllys 		}
33699ebb4caSwyllys 
33799ebb4caSwyllys 		lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
33899ebb4caSwyllys 		if (lock_count == NULL) {
33999ebb4caSwyllys 			OPENSSL_free(lock_cs);
34099ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
34199ebb4caSwyllys 			return (NULL);
34299ebb4caSwyllys 		}
34399ebb4caSwyllys 
34499ebb4caSwyllys 		for (i = 0; i < CRYPTO_num_locks(); i++) {
34599ebb4caSwyllys 			lock_count[i] = 0;
34699ebb4caSwyllys 			(void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
34799ebb4caSwyllys 		}
34899ebb4caSwyllys 
34999ebb4caSwyllys 		CRYPTO_set_id_callback((unsigned long (*)())thread_id);
35099ebb4caSwyllys 		CRYPTO_set_locking_callback((void (*)())locking_cb);
35199ebb4caSwyllys 		ssl_initialized = 1;
35299ebb4caSwyllys 	}
35399ebb4caSwyllys 	(void) mutex_unlock(&init_lock);
35499ebb4caSwyllys 
35599ebb4caSwyllys 	return (&openssl_plugin_table);
35699ebb4caSwyllys }
35799ebb4caSwyllys /*
35899ebb4caSwyllys  * Convert an SSL DN to a KMF DN.
35999ebb4caSwyllys  */
36099ebb4caSwyllys static KMF_RETURN
36199ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
36299ebb4caSwyllys {
36399ebb4caSwyllys 	KMF_DATA derdata;
36499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
36599ebb4caSwyllys 	uchar_t *tmp;
36699ebb4caSwyllys 
36799ebb4caSwyllys 	/* Convert to raw DER format */
36899ebb4caSwyllys 	derdata.Length = i2d_X509_NAME(sslDN, NULL);
36999ebb4caSwyllys 	if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
37099ebb4caSwyllys 	    == NULL) {
37199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
37299ebb4caSwyllys 	}
37399ebb4caSwyllys 	(void) i2d_X509_NAME(sslDN, &tmp);
37499ebb4caSwyllys 
37599ebb4caSwyllys 	/* Decode to KMF format */
37699ebb4caSwyllys 	rv = DerDecodeName(&derdata, kmfDN);
37799ebb4caSwyllys 	if (rv != KMF_OK) {
37899ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
37999ebb4caSwyllys 	}
38099ebb4caSwyllys 	OPENSSL_free(derdata.Data);
38199ebb4caSwyllys 
38299ebb4caSwyllys 	return (rv);
38399ebb4caSwyllys }
38499ebb4caSwyllys 
38599ebb4caSwyllys static int
38699ebb4caSwyllys isdir(char *path)
38799ebb4caSwyllys {
38899ebb4caSwyllys 	struct stat s;
38999ebb4caSwyllys 
39099ebb4caSwyllys 	if (stat(path, &s) == -1)
39199ebb4caSwyllys 		return (0);
39299ebb4caSwyllys 
39399ebb4caSwyllys 	return (s.st_mode & S_IFDIR);
39499ebb4caSwyllys }
39599ebb4caSwyllys 
39699ebb4caSwyllys static KMF_RETURN
39799ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
39899ebb4caSwyllys {
39999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
40099ebb4caSwyllys 	unsigned char *buf = NULL, *p;
40199ebb4caSwyllys 	int len;
40299ebb4caSwyllys 
40399ebb4caSwyllys 	/*
40499ebb4caSwyllys 	 * Convert the X509 internal struct to DER encoded data
40599ebb4caSwyllys 	 */
40699ebb4caSwyllys 	if ((len = i2d_X509(x509cert, NULL)) < 0) {
40799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
40899ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
40999ebb4caSwyllys 		goto cleanup;
41099ebb4caSwyllys 	}
41199ebb4caSwyllys 	if ((buf = malloc(len)) == NULL) {
41299ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
41399ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
41499ebb4caSwyllys 		goto cleanup;
41599ebb4caSwyllys 	}
41699ebb4caSwyllys 
41799ebb4caSwyllys 	/*
41899ebb4caSwyllys 	 * i2d_X509 will increment the buf pointer so that we need to
41999ebb4caSwyllys 	 * save it.
42099ebb4caSwyllys 	 */
42199ebb4caSwyllys 	p = buf;
42299ebb4caSwyllys 	if ((len = i2d_X509(x509cert, &p)) < 0) {
42399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
42499ebb4caSwyllys 		free(buf);
42599ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
42699ebb4caSwyllys 		goto cleanup;
42799ebb4caSwyllys 	}
42899ebb4caSwyllys 
42999ebb4caSwyllys 	/* caller's responsibility to free it */
43099ebb4caSwyllys 	cert->Data = buf;
43199ebb4caSwyllys 	cert->Length = len;
43299ebb4caSwyllys 
43399ebb4caSwyllys cleanup:
43499ebb4caSwyllys 	if (rv != KMF_OK) {
43599ebb4caSwyllys 		if (buf)
43699ebb4caSwyllys 			free(buf);
43799ebb4caSwyllys 		cert->Data = NULL;
43899ebb4caSwyllys 		cert->Length = 0;
43999ebb4caSwyllys 	}
44099ebb4caSwyllys 
44199ebb4caSwyllys 	return (rv);
44299ebb4caSwyllys }
44399ebb4caSwyllys 
44499ebb4caSwyllys static KMF_RETURN
44599ebb4caSwyllys check_cert(X509 *xcert, KMF_FINDCERT_PARAMS *params, boolean_t *match)
44699ebb4caSwyllys {
44799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
44899ebb4caSwyllys 	boolean_t findIssuer = FALSE;
44999ebb4caSwyllys 	boolean_t findSubject = FALSE;
45099ebb4caSwyllys 	boolean_t findSerial = FALSE;
45199ebb4caSwyllys 	KMF_X509_NAME issuerDN, subjectDN;
45299ebb4caSwyllys 	KMF_X509_NAME certIssuerDN, certSubjectDN;
45399ebb4caSwyllys 
45499ebb4caSwyllys 	*match = FALSE;
45599ebb4caSwyllys 	if (xcert == NULL) {
45699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
45799ebb4caSwyllys 	}
45899ebb4caSwyllys 
45999ebb4caSwyllys 	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
46099ebb4caSwyllys 	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
46199ebb4caSwyllys 	(void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
46299ebb4caSwyllys 	(void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
46399ebb4caSwyllys 
46499ebb4caSwyllys 	if (params->issuer != NULL && strlen(params->issuer)) {
46599ebb4caSwyllys 		rv = KMF_DNParser(params->issuer, &issuerDN);
46699ebb4caSwyllys 		if (rv != KMF_OK)
46799ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
46899ebb4caSwyllys 
46999ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->issuer, &certIssuerDN);
47099ebb4caSwyllys 		if (rv != KMF_OK) {
47199ebb4caSwyllys 			KMF_FreeDN(&issuerDN);
47299ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
47399ebb4caSwyllys 		}
47499ebb4caSwyllys 
47599ebb4caSwyllys 		findIssuer = TRUE;
47699ebb4caSwyllys 	}
47799ebb4caSwyllys 	if (params->subject != NULL && strlen(params->subject)) {
47899ebb4caSwyllys 		rv = KMF_DNParser(params->subject, &subjectDN);
47999ebb4caSwyllys 		if (rv != KMF_OK) {
48099ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
48199ebb4caSwyllys 			goto cleanup;
48299ebb4caSwyllys 		}
48399ebb4caSwyllys 
48499ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->subject, &certSubjectDN);
48599ebb4caSwyllys 		if (rv != KMF_OK) {
48699ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
48799ebb4caSwyllys 			goto cleanup;
48899ebb4caSwyllys 		}
48999ebb4caSwyllys 		findSubject = TRUE;
49099ebb4caSwyllys 	}
49199ebb4caSwyllys 	if (params->serial != NULL && params->serial->val != NULL)
49299ebb4caSwyllys 		findSerial = TRUE;
49399ebb4caSwyllys 
49499ebb4caSwyllys 	if (findSerial) {
49599ebb4caSwyllys 		BIGNUM *bn;
49699ebb4caSwyllys 
49799ebb4caSwyllys 		/* Comparing BIGNUMs is a pain! */
49899ebb4caSwyllys 		bn = ASN1_INTEGER_to_BN(xcert->cert_info->serialNumber, NULL);
49999ebb4caSwyllys 		if (bn != NULL) {
50099ebb4caSwyllys 			int bnlen = BN_num_bytes(bn);
50199ebb4caSwyllys 
50299ebb4caSwyllys 			if (bnlen == params->serial->len) {
50399ebb4caSwyllys 				uchar_t *a = malloc(bnlen);
50499ebb4caSwyllys 				if (a == NULL) {
50599ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
50699ebb4caSwyllys 					BN_free(bn);
50799ebb4caSwyllys 					goto cleanup;
50899ebb4caSwyllys 				}
50999ebb4caSwyllys 				bnlen = BN_bn2bin(bn, a);
51099ebb4caSwyllys 				*match = !memcmp(a,
51199ebb4caSwyllys 				    params->serial->val,
51299ebb4caSwyllys 				    params->serial->len);
51399ebb4caSwyllys 				rv = KMF_OK;
51499ebb4caSwyllys 				free(a);
51599ebb4caSwyllys 			}
51699ebb4caSwyllys 			BN_free(bn);
51799ebb4caSwyllys 			if (!(*match))
51899ebb4caSwyllys 				goto cleanup;
51999ebb4caSwyllys 		} else {
52099ebb4caSwyllys 			rv = KMF_OK;
52199ebb4caSwyllys 			goto cleanup;
52299ebb4caSwyllys 		}
52399ebb4caSwyllys 	}
52499ebb4caSwyllys 	if (findIssuer) {
52599ebb4caSwyllys 		*match = !KMF_CompareRDNs(&issuerDN, &certIssuerDN);
52699ebb4caSwyllys 		if (!(*match)) {
52799ebb4caSwyllys 			rv = KMF_OK;
52899ebb4caSwyllys 			goto cleanup;
52999ebb4caSwyllys 		}
53099ebb4caSwyllys 	}
53199ebb4caSwyllys 	if (findSubject) {
53299ebb4caSwyllys 		*match = !KMF_CompareRDNs(&subjectDN, &certSubjectDN);
53399ebb4caSwyllys 		if (!(*match)) {
53499ebb4caSwyllys 			rv = KMF_OK;
53599ebb4caSwyllys 			goto cleanup;
53699ebb4caSwyllys 		}
53799ebb4caSwyllys 	}
53899ebb4caSwyllys 
53999ebb4caSwyllys 	*match = TRUE;
54099ebb4caSwyllys cleanup:
54199ebb4caSwyllys 	if (findIssuer) {
54299ebb4caSwyllys 		KMF_FreeDN(&issuerDN);
54399ebb4caSwyllys 		KMF_FreeDN(&certIssuerDN);
54499ebb4caSwyllys 	}
54599ebb4caSwyllys 	if (findSubject) {
54699ebb4caSwyllys 		KMF_FreeDN(&subjectDN);
54799ebb4caSwyllys 		KMF_FreeDN(&certSubjectDN);
54899ebb4caSwyllys 	}
54999ebb4caSwyllys 
55099ebb4caSwyllys 	return (rv);
55199ebb4caSwyllys }
55299ebb4caSwyllys 
55399ebb4caSwyllys static KMF_RETURN
55499ebb4caSwyllys load_X509cert(KMF_HANDLE *kmfh,
55599ebb4caSwyllys 	KMF_FINDCERT_PARAMS *params,
55699ebb4caSwyllys 	char *pathname,
55799ebb4caSwyllys 	X509 **outcert)
55899ebb4caSwyllys {
55999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
56099ebb4caSwyllys 	X509 *xcert = NULL;
56199ebb4caSwyllys 	BIO *bcert = NULL;
56299ebb4caSwyllys 	boolean_t  match = FALSE;
56399ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
56499ebb4caSwyllys 
56599ebb4caSwyllys 	/*
56699ebb4caSwyllys 	 * auto-detect the file format, regardless of what
56799ebb4caSwyllys 	 * the 'format' parameters in the params say.
56899ebb4caSwyllys 	 */
56999ebb4caSwyllys 	rv = KMF_GetFileFormat(pathname, &format);
57099ebb4caSwyllys 	if (rv != KMF_OK) {
57199ebb4caSwyllys 		if (rv == KMF_ERR_OPEN_FILE)
57299ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
57399ebb4caSwyllys 		return (rv);
57499ebb4caSwyllys 	}
57599ebb4caSwyllys 
57699ebb4caSwyllys 	/* Not ASN1(DER) format */
57799ebb4caSwyllys 	if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
57899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
57999ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
58099ebb4caSwyllys 		goto cleanup;
58199ebb4caSwyllys 	}
58299ebb4caSwyllys 
58399ebb4caSwyllys 	if (format == KMF_FORMAT_PEM)
58499ebb4caSwyllys 		xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
58599ebb4caSwyllys 	else if (format == KMF_FORMAT_ASN1)
58699ebb4caSwyllys 		xcert = d2i_X509_bio(bcert, NULL);
58799ebb4caSwyllys 	else if (format == KMF_FORMAT_PKCS12) {
58899ebb4caSwyllys 		PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
58999ebb4caSwyllys 		if (p12 != NULL) {
59099ebb4caSwyllys 			(void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
59199ebb4caSwyllys 			PKCS12_free(p12);
59299ebb4caSwyllys 			p12 = NULL;
59399ebb4caSwyllys 		} else {
59499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
59599ebb4caSwyllys 			rv = KMF_ERR_BAD_CERT_FORMAT;
59699ebb4caSwyllys 		}
59799ebb4caSwyllys 	} else {
59899ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
59999ebb4caSwyllys 		goto cleanup;
60099ebb4caSwyllys 	}
60199ebb4caSwyllys 
60299ebb4caSwyllys 	if (xcert == NULL) {
60399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
60499ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
60599ebb4caSwyllys 		goto cleanup;
60699ebb4caSwyllys 	}
60799ebb4caSwyllys 
60899ebb4caSwyllys 	if (check_cert(xcert, params, &match) != KMF_OK || match == FALSE) {
60999ebb4caSwyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
61099ebb4caSwyllys 		goto cleanup;
61199ebb4caSwyllys 	}
61299ebb4caSwyllys 
61399ebb4caSwyllys 	if (outcert != NULL) {
61499ebb4caSwyllys 		*outcert = xcert;
61599ebb4caSwyllys 	}
61699ebb4caSwyllys 
61799ebb4caSwyllys cleanup:
61899ebb4caSwyllys 	if (bcert != NULL) (void) BIO_free(bcert);
61999ebb4caSwyllys 	if (rv != KMF_OK && xcert != NULL)
62099ebb4caSwyllys 		X509_free(xcert);
62199ebb4caSwyllys 
62299ebb4caSwyllys 	return (rv);
62399ebb4caSwyllys }
62499ebb4caSwyllys 
62571593db2Swyllys static int
62671593db2Swyllys datacmp(const void *a, const void *b)
62771593db2Swyllys {
62871593db2Swyllys 	KMF_DATA *adata = (KMF_DATA *)a;
62971593db2Swyllys 	KMF_DATA *bdata = (KMF_DATA *)b;
63071593db2Swyllys 	if (adata->Length > bdata->Length)
63171593db2Swyllys 		return (-1);
63271593db2Swyllys 	if (adata->Length < bdata->Length)
63371593db2Swyllys 		return (1);
63471593db2Swyllys 	return (0);
63571593db2Swyllys }
63671593db2Swyllys 
63771593db2Swyllys static KMF_RETURN
63871593db2Swyllys load_certs(KMF_HANDLE *kmfh, KMF_FINDCERT_PARAMS *params, char *pathname,
63971593db2Swyllys 	KMF_DATA **certlist, uint32_t *numcerts)
64071593db2Swyllys {
64171593db2Swyllys 	KMF_RETURN rv = KMF_OK;
64271593db2Swyllys 	int i;
64371593db2Swyllys 	KMF_DATA *certs = NULL;
64471593db2Swyllys 	int nc = 0;
64571593db2Swyllys 	int hits = 0;
64671593db2Swyllys 	KMF_ENCODE_FORMAT format;
64771593db2Swyllys 
64871593db2Swyllys 	rv = KMF_GetFileFormat(pathname, &format);
64971593db2Swyllys 	if (rv != KMF_OK) {
65071593db2Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
65171593db2Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
65271593db2Swyllys 		return (rv);
65371593db2Swyllys 	}
65471593db2Swyllys 	if (format == KMF_FORMAT_ASN1) {
65571593db2Swyllys 		/* load a single certificate */
65671593db2Swyllys 		certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
65771593db2Swyllys 		if (certs == NULL)
65871593db2Swyllys 			return (KMF_ERR_MEMORY);
65971593db2Swyllys 		certs->Data = NULL;
66071593db2Swyllys 		certs->Length = 0;
66171593db2Swyllys 		rv = kmf_load_cert(kmfh, params, pathname, certs);
66271593db2Swyllys 		if (rv == KMF_OK) {
66371593db2Swyllys 			*certlist = certs;
66471593db2Swyllys 			*numcerts = 1;
66571593db2Swyllys 		}
66671593db2Swyllys 		return (rv);
66771593db2Swyllys 	} else if (format == KMF_FORMAT_PKCS12) {
66871593db2Swyllys 		/* We need a credential to access a PKCS#12 file */
66971593db2Swyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
67071593db2Swyllys 	} else if (format == KMF_FORMAT_PEM ||
67171593db2Swyllys 	    format != KMF_FORMAT_PEM_KEYPAIR) {
67271593db2Swyllys 
67371593db2Swyllys 		/* This function only works on PEM files */
67402744e81Swyllys 		rv = extract_objects(kmfh, params, pathname,
675*34acef67Swyllys 		    (uchar_t *)NULL, 0, NULL, &certs, &nc);
67671593db2Swyllys 	} else {
67771593db2Swyllys 		return (KMF_ERR_ENCODING);
67871593db2Swyllys 	}
67971593db2Swyllys 
68071593db2Swyllys 	if (rv != KMF_OK)
68171593db2Swyllys 		return (rv);
68271593db2Swyllys 
68371593db2Swyllys 	for (i = 0; i < nc; i++) {
68471593db2Swyllys 		if (params->find_cert_validity == KMF_NONEXPIRED_CERTS) {
68571593db2Swyllys 			rv = KMF_CheckCertDate(kmfh, &certs[i]);
68671593db2Swyllys 		} else if (params->find_cert_validity == KMF_EXPIRED_CERTS) {
68771593db2Swyllys 			rv = KMF_CheckCertDate(kmfh, &certs[i]);
68871593db2Swyllys 			if (rv == KMF_OK)
68971593db2Swyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
69071593db2Swyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD)
69171593db2Swyllys 				rv = KMF_OK;
69271593db2Swyllys 		}
69371593db2Swyllys 		if (rv != KMF_OK) {
69471593db2Swyllys 			/* Remove this cert from the list by clearing it. */
69571593db2Swyllys 			KMF_FreeData(&certs[i]);
69671593db2Swyllys 		} else {
69771593db2Swyllys 			hits++; /* count valid certs found */
69871593db2Swyllys 		}
69971593db2Swyllys 		rv = KMF_OK;
70071593db2Swyllys 	}
70171593db2Swyllys 	if (rv == KMF_OK && hits == 0) {
70271593db2Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
70371593db2Swyllys 	} else if (rv == KMF_OK && hits > 0) {
70471593db2Swyllys 		/*
70571593db2Swyllys 		 * Sort the list of certs by length to put the cleared ones
70671593db2Swyllys 		 * at the end so they don't get accessed by the caller.
70771593db2Swyllys 		 */
70871593db2Swyllys 		qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
70971593db2Swyllys 		*certlist = certs;
71071593db2Swyllys 
71171593db2Swyllys 		/* since we sorted the list, just return the number of hits */
71271593db2Swyllys 		*numcerts = hits;
71371593db2Swyllys 	}
71471593db2Swyllys 	return (rv);
71571593db2Swyllys }
71671593db2Swyllys 
71799ebb4caSwyllys static KMF_RETURN
71899ebb4caSwyllys kmf_load_cert(KMF_HANDLE *kmfh,
71999ebb4caSwyllys 	KMF_FINDCERT_PARAMS *params,
72099ebb4caSwyllys 	char *pathname,
72199ebb4caSwyllys 	KMF_DATA *cert)
72299ebb4caSwyllys {
72399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
72499ebb4caSwyllys 	X509 *x509cert = NULL;
72599ebb4caSwyllys 
72699ebb4caSwyllys 	rv = load_X509cert(kmfh, params, pathname, &x509cert);
72799ebb4caSwyllys 	if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
72899ebb4caSwyllys 		rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
72999ebb4caSwyllys 		if (rv != KMF_OK) {
73099ebb4caSwyllys 			goto cleanup;
73199ebb4caSwyllys 		}
73299ebb4caSwyllys 		if (params->find_cert_validity == KMF_NONEXPIRED_CERTS) {
73399ebb4caSwyllys 			rv = KMF_CheckCertDate(kmfh, cert);
73499ebb4caSwyllys 		} else if (params->find_cert_validity == KMF_EXPIRED_CERTS) {
73599ebb4caSwyllys 			rv = KMF_CheckCertDate(kmfh, cert);
73699ebb4caSwyllys 			if (rv == KMF_OK)  {
73799ebb4caSwyllys 				/*
73899ebb4caSwyllys 				 * This is a valid cert so skip it.
73999ebb4caSwyllys 				 */
74099ebb4caSwyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
74199ebb4caSwyllys 			}
74299ebb4caSwyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD) {
74399ebb4caSwyllys 				/*
74499ebb4caSwyllys 				 * We want to return success when we
74599ebb4caSwyllys 				 * find an invalid cert.
74699ebb4caSwyllys 				 */
74799ebb4caSwyllys 				rv = KMF_OK;
74899ebb4caSwyllys 				goto cleanup;
74999ebb4caSwyllys 			}
75099ebb4caSwyllys 		}
75199ebb4caSwyllys 	}
75299ebb4caSwyllys cleanup:
75399ebb4caSwyllys 	if (x509cert != NULL)
75499ebb4caSwyllys 		X509_free(x509cert);
75599ebb4caSwyllys 
75699ebb4caSwyllys 	return (rv);
75799ebb4caSwyllys }
75899ebb4caSwyllys 
75902744e81Swyllys static KMF_RETURN
76002744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
76102744e81Swyllys {
76202744e81Swyllys 	KMF_RETURN ret = KMF_OK;
76302744e81Swyllys 	KMF_RAW_RSA_KEY rsa;
76402744e81Swyllys 	BerElement *asn1 = NULL;
76502744e81Swyllys 	BerValue filebuf;
76602744e81Swyllys 	BerValue OID = { NULL, 0 };
76702744e81Swyllys 	BerValue *Mod = NULL, *PubExp = NULL;
76802744e81Swyllys 	BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
76902744e81Swyllys 	BerValue *Coef = NULL;
77002744e81Swyllys 	BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
77102744e81Swyllys 	BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
77202744e81Swyllys 	BIGNUM *qminus1 = NULL;
77302744e81Swyllys 	BN_CTX *ctx = NULL;
77402744e81Swyllys 
77502744e81Swyllys 	*pkey = NULL;
77602744e81Swyllys 
77702744e81Swyllys 	filebuf.bv_val = (char *)filedata->Data;
77802744e81Swyllys 	filebuf.bv_len = filedata->Length;
77902744e81Swyllys 
78002744e81Swyllys 	asn1 = kmfder_init(&filebuf);
78102744e81Swyllys 	if (asn1 == NULL) {
78202744e81Swyllys 		ret = KMF_ERR_MEMORY;
78302744e81Swyllys 		goto out;
78402744e81Swyllys 	}
78502744e81Swyllys 
78602744e81Swyllys 	if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
78702744e81Swyllys 	    &OID, &Mod, &PubExp, &PriExp, &Prime1,
78802744e81Swyllys 	    &Prime2, &Coef) == -1)  {
78902744e81Swyllys 		ret = KMF_ERR_ENCODING;
79002744e81Swyllys 		goto out;
79102744e81Swyllys 	}
79202744e81Swyllys 
79302744e81Swyllys 	/*
79402744e81Swyllys 	 * We have to derive the 2 Exponents using Bignumber math.
79502744e81Swyllys 	 * Exp1 = PriExp mod (Prime1 - 1)
79602744e81Swyllys 	 * Exp2 = PriExp mod (Prime2 - 1)
79702744e81Swyllys 	 */
79802744e81Swyllys 
79902744e81Swyllys 	/* D = PrivateExponent */
80002744e81Swyllys 	D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
80102744e81Swyllys 	if (D == NULL) {
80202744e81Swyllys 		ret = KMF_ERR_MEMORY;
80302744e81Swyllys 		goto out;
80402744e81Swyllys 	}
80502744e81Swyllys 
80602744e81Swyllys 	/* P = Prime1 (first prime factor of Modulus) */
80702744e81Swyllys 	P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
80802744e81Swyllys 	if (D == NULL) {
80902744e81Swyllys 		ret = KMF_ERR_MEMORY;
81002744e81Swyllys 		goto out;
81102744e81Swyllys 	}
81202744e81Swyllys 
81302744e81Swyllys 	/* Q = Prime2 (second prime factor of Modulus) */
81402744e81Swyllys 	Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
81502744e81Swyllys 
81602744e81Swyllys 	if ((ctx = BN_CTX_new()) == NULL) {
81702744e81Swyllys 		ret = KMF_ERR_MEMORY;
81802744e81Swyllys 		goto out;
81902744e81Swyllys 	}
82002744e81Swyllys 
82102744e81Swyllys 	/* Compute (P - 1) */
82202744e81Swyllys 	pminus1 = BN_new();
82302744e81Swyllys 	(void) BN_sub(pminus1, P, BN_value_one());
82402744e81Swyllys 
82502744e81Swyllys 	/* Exponent1 = D mod (P - 1) */
82602744e81Swyllys 	Exp1 = BN_new();
82702744e81Swyllys 	(void) BN_mod(Exp1, D, pminus1, ctx);
82802744e81Swyllys 
82902744e81Swyllys 	/* Compute (Q - 1) */
83002744e81Swyllys 	qminus1 = BN_new();
83102744e81Swyllys 	(void) BN_sub(qminus1, Q, BN_value_one());
83202744e81Swyllys 
83302744e81Swyllys 	/* Exponent2 = D mod (Q - 1) */
83402744e81Swyllys 	Exp2 = BN_new();
83502744e81Swyllys 	(void) BN_mod(Exp2, D, qminus1, ctx);
83602744e81Swyllys 
83702744e81Swyllys 	/* Coef = (Inverse Q) mod P */
83802744e81Swyllys 	COEF = BN_new();
83902744e81Swyllys 	(void) BN_mod_inverse(COEF, Q, P, ctx);
84002744e81Swyllys 
84102744e81Swyllys 	/* Convert back to KMF format */
84202744e81Swyllys 	(void) memset(&rsa, 0, sizeof (rsa));
84302744e81Swyllys 
84402744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
84502744e81Swyllys 		goto out;
84602744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
84702744e81Swyllys 		goto out;
84802744e81Swyllys 	if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
84902744e81Swyllys 		goto out;
85002744e81Swyllys 
85102744e81Swyllys 	rsa.mod.val = (uchar_t *)Mod->bv_val;
85202744e81Swyllys 	rsa.mod.len = Mod->bv_len;
85302744e81Swyllys 
85402744e81Swyllys 	rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
85502744e81Swyllys 	rsa.pubexp.len = PubExp->bv_len;
85602744e81Swyllys 
85702744e81Swyllys 	rsa.priexp.val = (uchar_t *)PriExp->bv_val;
85802744e81Swyllys 	rsa.priexp.len = PriExp->bv_len;
85902744e81Swyllys 
86002744e81Swyllys 	rsa.prime1.val = (uchar_t *)Prime1->bv_val;
86102744e81Swyllys 	rsa.prime1.len = Prime1->bv_len;
86202744e81Swyllys 
86302744e81Swyllys 	rsa.prime2.val = (uchar_t *)Prime2->bv_val;
86402744e81Swyllys 	rsa.prime2.len = Prime2->bv_len;
86502744e81Swyllys 
86602744e81Swyllys 	*pkey = ImportRawRSAKey(&rsa);
86702744e81Swyllys out:
86802744e81Swyllys 	if (asn1 != NULL)
86902744e81Swyllys 		kmfber_free(asn1, 1);
87002744e81Swyllys 
87102744e81Swyllys 	if (OID.bv_val) {
87202744e81Swyllys 		free(OID.bv_val);
87302744e81Swyllys 	}
87402744e81Swyllys 	if (PriExp)
87502744e81Swyllys 		free(PriExp);
87602744e81Swyllys 
87702744e81Swyllys 	if (Mod)
87802744e81Swyllys 		free(Mod);
87902744e81Swyllys 
88002744e81Swyllys 	if (PubExp)
88102744e81Swyllys 		free(PubExp);
88202744e81Swyllys 
88302744e81Swyllys 	if (Coef) {
88402744e81Swyllys 		(void) memset(Coef->bv_val, 0, Coef->bv_len);
88502744e81Swyllys 		free(Coef->bv_val);
88602744e81Swyllys 		free(Coef);
88702744e81Swyllys 	}
88802744e81Swyllys 	if (Prime1)
88902744e81Swyllys 		free(Prime1);
89002744e81Swyllys 	if (Prime2)
89102744e81Swyllys 		free(Prime2);
89202744e81Swyllys 
89302744e81Swyllys 	if (ctx != NULL)
89402744e81Swyllys 		BN_CTX_free(ctx);
89502744e81Swyllys 
89602744e81Swyllys 	if (D)
89702744e81Swyllys 		BN_clear_free(D);
89802744e81Swyllys 	if (P)
89902744e81Swyllys 		BN_clear_free(P);
90002744e81Swyllys 	if (Q)
90102744e81Swyllys 		BN_clear_free(Q);
90202744e81Swyllys 	if (pminus1)
90302744e81Swyllys 		BN_clear_free(pminus1);
90402744e81Swyllys 	if (qminus1)
90502744e81Swyllys 		BN_clear_free(qminus1);
90602744e81Swyllys 	if (Exp1)
90702744e81Swyllys 		BN_clear_free(Exp1);
90802744e81Swyllys 	if (Exp2)
90902744e81Swyllys 		BN_clear_free(Exp2);
91002744e81Swyllys 
91102744e81Swyllys 	return (ret);
91202744e81Swyllys 
91302744e81Swyllys }
91402744e81Swyllys 
91599ebb4caSwyllys static EVP_PKEY *
91699ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file)
91799ebb4caSwyllys {
91899ebb4caSwyllys 	BIO *keyfile = NULL;
91999ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
92099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
92199ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
92202744e81Swyllys 	KMF_RETURN rv;
92302744e81Swyllys 	KMF_DATA filedata;
92499ebb4caSwyllys 
92599ebb4caSwyllys 	if (file == NULL) {
92699ebb4caSwyllys 		return (NULL);
92799ebb4caSwyllys 	}
92899ebb4caSwyllys 
92999ebb4caSwyllys 	if (KMF_GetFileFormat((char *)file, &format) != KMF_OK)
93099ebb4caSwyllys 		return (NULL);
93199ebb4caSwyllys 
93299ebb4caSwyllys 	keyfile = BIO_new_file(file, "rb");
93399ebb4caSwyllys 	if (keyfile == NULL) {
93499ebb4caSwyllys 		goto end;
93599ebb4caSwyllys 	}
93699ebb4caSwyllys 
93702744e81Swyllys 	if (format == KMF_FORMAT_ASN1) {
93899ebb4caSwyllys 		pkey = d2i_PrivateKey_bio(keyfile, NULL);
93902744e81Swyllys 		if (pkey == NULL) {
94002744e81Swyllys 
94102744e81Swyllys 			(void) BIO_free(keyfile);
94202744e81Swyllys 			keyfile = NULL;
94302744e81Swyllys 			/* Try odd ASN.1 variations */
94402744e81Swyllys 			rv = KMF_ReadInputFile(kmfh, (char *)file,
94502744e81Swyllys 			    &filedata);
94602744e81Swyllys 			if (rv == KMF_OK) {
94702744e81Swyllys 				(void) readAltFormatPrivateKey(&filedata,
94802744e81Swyllys 				    &pkey);
94902744e81Swyllys 				KMF_FreeData(&filedata);
95002744e81Swyllys 			}
95102744e81Swyllys 		}
95202744e81Swyllys 	} else if (format == KMF_FORMAT_PEM ||
95302744e81Swyllys 	    format == KMF_FORMAT_PEM_KEYPAIR) {
95499ebb4caSwyllys 		pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
95502744e81Swyllys 		if (pkey == NULL) {
95602744e81Swyllys 			KMF_DATA derdata;
95702744e81Swyllys 			/*
95802744e81Swyllys 			 * Check if this is the alt. format
95902744e81Swyllys 			 * RSA private key file.
96002744e81Swyllys 			 */
96102744e81Swyllys 			rv = KMF_ReadInputFile(kmfh, (char *)file,
96202744e81Swyllys 			    &filedata);
96302744e81Swyllys 			if (rv == KMF_OK) {
96402744e81Swyllys 				uchar_t *d = NULL;
96502744e81Swyllys 				int len;
96602744e81Swyllys 				rv = KMF_Pem2Der(filedata.Data,
96702744e81Swyllys 				    filedata.Length, &d, &len);
96802744e81Swyllys 				if (rv == KMF_OK && d != NULL) {
96902744e81Swyllys 					derdata.Data = d;
97002744e81Swyllys 					derdata.Length = (size_t)len;
97102744e81Swyllys 					(void) readAltFormatPrivateKey(
97202744e81Swyllys 					    &derdata, &pkey);
97302744e81Swyllys 					free(d);
97402744e81Swyllys 				}
97502744e81Swyllys 				KMF_FreeData(&filedata);
97602744e81Swyllys 			}
97702744e81Swyllys 		}
97802744e81Swyllys 	}
97999ebb4caSwyllys 
98099ebb4caSwyllys end:
98199ebb4caSwyllys 	if (pkey == NULL)
98299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
98399ebb4caSwyllys 
98499ebb4caSwyllys 	if (keyfile != NULL)
98599ebb4caSwyllys 		(void) BIO_free(keyfile);
98699ebb4caSwyllys 
98799ebb4caSwyllys 	return (pkey);
98899ebb4caSwyllys }
98999ebb4caSwyllys 
99099ebb4caSwyllys KMF_RETURN
99199ebb4caSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle,
99299ebb4caSwyllys 	KMF_FINDCERT_PARAMS *params,
99399ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert,
99499ebb4caSwyllys 	uint32_t *num_certs)
99599ebb4caSwyllys {
99699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
99799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
99899ebb4caSwyllys 	char *fullpath;
999f482c776Swyllys 	int i, n;
1000f482c776Swyllys 	uint32_t maxcerts = 0;
100199ebb4caSwyllys 
100299ebb4caSwyllys 	if (num_certs == NULL || params == NULL)
100399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
100499ebb4caSwyllys 
1005f482c776Swyllys 	maxcerts = *num_certs;
1006f482c776Swyllys 	if (maxcerts == 0)
1007f482c776Swyllys 		maxcerts = 0xFFFFFFFF;
100899ebb4caSwyllys 	*num_certs = 0;
100999ebb4caSwyllys 
101099ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
101199ebb4caSwyllys 	    params->sslparms.certfile);
101299ebb4caSwyllys 
101399ebb4caSwyllys 	if (fullpath == NULL)
101499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
101599ebb4caSwyllys 
101699ebb4caSwyllys 	if (isdir(fullpath)) {
101799ebb4caSwyllys 		DIR *dirp;
101899ebb4caSwyllys 		struct dirent *dp;
101999ebb4caSwyllys 
1020f482c776Swyllys 		n = 0;
102199ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
102299ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
102399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
102499ebb4caSwyllys 		}
102599ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
102699ebb4caSwyllys 			char *fname;
102771593db2Swyllys 			KMF_DATA *certlist = NULL;
1028f482c776Swyllys 			uint32_t loaded_certs = 0;
102971593db2Swyllys 
103099ebb4caSwyllys 			if (strcmp(dp->d_name, ".") == 0 ||
103199ebb4caSwyllys 			    strcmp(dp->d_name, "..") == 0)
103299ebb4caSwyllys 				continue;
103399ebb4caSwyllys 
1034*34acef67Swyllys 			fname = get_fullpath(fullpath, (char *)&dp->d_name);
103599ebb4caSwyllys 
103671593db2Swyllys 			rv = load_certs(kmfh, params, fname, &certlist,
1037f482c776Swyllys 			    &loaded_certs);
103899ebb4caSwyllys 
103999ebb4caSwyllys 			if (rv != KMF_OK) {
104099ebb4caSwyllys 				free(fname);
104171593db2Swyllys 				if (certlist != NULL) {
1042f482c776Swyllys 					for (i = 0; i < loaded_certs; i++)
104371593db2Swyllys 						KMF_FreeData(&certlist[i]);
104471593db2Swyllys 					free(certlist);
104571593db2Swyllys 				}
104699ebb4caSwyllys 				continue;
104799ebb4caSwyllys 			}
104899ebb4caSwyllys 
104999ebb4caSwyllys 			/* If load succeeds, add certdata to the list */
105099ebb4caSwyllys 			if (kmf_cert != NULL) {
1051f482c776Swyllys 				for (i = 0; i < loaded_certs &&
1052b4058258Swyllys 				    n < maxcerts; i++) {
105371593db2Swyllys 					kmf_cert[n].certificate.Data =
105471593db2Swyllys 					    certlist[i].Data;
105599ebb4caSwyllys 					kmf_cert[n].certificate.Length =
105671593db2Swyllys 					    certlist[i].Length;
105799ebb4caSwyllys 
105899ebb4caSwyllys 					kmf_cert[n].kmf_private.keystore_type =
105999ebb4caSwyllys 					    KMF_KEYSTORE_OPENSSL;
106099ebb4caSwyllys 					kmf_cert[n].kmf_private.flags =
106199ebb4caSwyllys 					    KMF_FLAG_CERT_VALID;
106271593db2Swyllys 					kmf_cert[n].kmf_private.label =
106371593db2Swyllys 					    strdup(fname);
106499ebb4caSwyllys 					n++;
106599ebb4caSwyllys 				}
1066b4058258Swyllys 				/*
1067b4058258Swyllys 				 * If maxcerts < loaded_certs, clean up the
1068b4058258Swyllys 				 * certs that were not used.
1069b4058258Swyllys 				 */
1070f482c776Swyllys 				for (; i < loaded_certs; i++)
107171593db2Swyllys 					KMF_FreeData(&certlist[i]);
1072f482c776Swyllys 			} else {
1073f482c776Swyllys 				for (i = 0; i < loaded_certs; i++)
1074f482c776Swyllys 					KMF_FreeData(&certlist[i]);
1075f482c776Swyllys 				n += loaded_certs;
107671593db2Swyllys 			}
1077f482c776Swyllys 			free(certlist);
107871593db2Swyllys 			free(fname);
107971593db2Swyllys 		}
108099ebb4caSwyllys 		(*num_certs) = n;
108199ebb4caSwyllys 		if (*num_certs == 0)
108299ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
1083f482c776Swyllys 		else
108499ebb4caSwyllys 			rv = KMF_OK;
108599ebb4caSwyllys exit:
108699ebb4caSwyllys 		(void) closedir(dirp);
108799ebb4caSwyllys 	} else {
108871593db2Swyllys 		KMF_DATA *certlist = NULL;
1089f482c776Swyllys 		uint32_t loaded_certs = 0;
109071593db2Swyllys 
1091f482c776Swyllys 		rv = load_certs(kmfh, params, fullpath,
1092f482c776Swyllys 		    &certlist, &loaded_certs);
109399ebb4caSwyllys 		if (rv != KMF_OK) {
109499ebb4caSwyllys 			free(fullpath);
109599ebb4caSwyllys 			return (rv);
109699ebb4caSwyllys 		}
109799ebb4caSwyllys 
1098f482c776Swyllys 		n = 0;
109971593db2Swyllys 		if (kmf_cert != NULL && certlist != NULL) {
1100f482c776Swyllys 			for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1101f482c776Swyllys 				kmf_cert[n].certificate.Data =
110271593db2Swyllys 				    certlist[i].Data;
1103f482c776Swyllys 				kmf_cert[n].certificate.Length =
110471593db2Swyllys 				    certlist[i].Length;
1105f482c776Swyllys 				kmf_cert[n].kmf_private.keystore_type =
110699ebb4caSwyllys 				    KMF_KEYSTORE_OPENSSL;
1107f482c776Swyllys 				kmf_cert[n].kmf_private.flags =
110871593db2Swyllys 				    KMF_FLAG_CERT_VALID;
1109f482c776Swyllys 				kmf_cert[n].kmf_private.label =
111071593db2Swyllys 				    strdup(fullpath);
1111f482c776Swyllys 				n++;
111271593db2Swyllys 			}
1113f482c776Swyllys 			/* If maxcerts < loaded_certs, clean up */
1114f482c776Swyllys 			for (; i < loaded_certs; i++)
111571593db2Swyllys 				KMF_FreeData(&certlist[i]);
1116f482c776Swyllys 		} else if (certlist != NULL) {
1117f482c776Swyllys 			for (i = 0; i < loaded_certs; i++)
1118f482c776Swyllys 				KMF_FreeData(&certlist[i]);
1119f482c776Swyllys 			n = loaded_certs;
1120f482c776Swyllys 		}
1121f482c776Swyllys 		if (certlist)
112271593db2Swyllys 			free(certlist);
1123f482c776Swyllys 
1124f482c776Swyllys 		*num_certs = n;
112599ebb4caSwyllys 	}
112699ebb4caSwyllys 
112799ebb4caSwyllys 	free(fullpath);
112899ebb4caSwyllys 
112999ebb4caSwyllys 	return (rv);
113099ebb4caSwyllys }
113199ebb4caSwyllys 
113299ebb4caSwyllys void
113399ebb4caSwyllys /*ARGSUSED*/
113499ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
113599ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert)
113699ebb4caSwyllys {
113799ebb4caSwyllys 	if (kmf_cert != NULL) {
113899ebb4caSwyllys 		if (kmf_cert->certificate.Data != NULL) {
113999ebb4caSwyllys 			free(kmf_cert->certificate.Data);
114099ebb4caSwyllys 			kmf_cert->certificate.Data = NULL;
114199ebb4caSwyllys 			kmf_cert->certificate.Length = 0;
114299ebb4caSwyllys 		}
114399ebb4caSwyllys 		if (kmf_cert->kmf_private.label)
114499ebb4caSwyllys 			free(kmf_cert->kmf_private.label);
114599ebb4caSwyllys 	}
114699ebb4caSwyllys }
114799ebb4caSwyllys 
114899ebb4caSwyllys KMF_RETURN
114999ebb4caSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, KMF_STORECERT_PARAMS *params,
115099ebb4caSwyllys     KMF_DATA * pcert)
115199ebb4caSwyllys {
115299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
115399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
115499ebb4caSwyllys 	X509 *xcert = NULL;
115599ebb4caSwyllys 	FILE *fp;
115699ebb4caSwyllys 	unsigned char *outbuf;
115799ebb4caSwyllys 	unsigned char *outbuf_p;
115899ebb4caSwyllys 	char *fullpath;
115999ebb4caSwyllys 	int outbuflen;
116099ebb4caSwyllys 	int len;
116199ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
116299ebb4caSwyllys 
116399ebb4caSwyllys 	if (params == NULL || params->ks_opt_u.openssl_opts.certfile == NULL) {
116499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
116599ebb4caSwyllys 	}
116699ebb4caSwyllys 
116799ebb4caSwyllys 	/*
116899ebb4caSwyllys 	 * check if the cert output format is supported by OPENSSL.
116999ebb4caSwyllys 	 * however, since the keystore for OPENSSL is just a file, we have
117099ebb4caSwyllys 	 * no way to store the format along with the file.
117199ebb4caSwyllys 	 */
117299ebb4caSwyllys 	format = params->sslparms.format;
117399ebb4caSwyllys 	if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM)
117499ebb4caSwyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
117599ebb4caSwyllys 
117699ebb4caSwyllys 
117799ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
117899ebb4caSwyllys 	    params->sslparms.certfile);
117999ebb4caSwyllys 	if (fullpath == NULL)
118099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
118199ebb4caSwyllys 
118299ebb4caSwyllys 	/*
118399ebb4caSwyllys 	 * When storing a certificate, you must specify a filename.
118499ebb4caSwyllys 	 */
118599ebb4caSwyllys 	if (isdir(fullpath)) {
118699ebb4caSwyllys 		free(fullpath);
118799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
118899ebb4caSwyllys 	}
118999ebb4caSwyllys 
119099ebb4caSwyllys 	/* copy cert data to outbuf */
119199ebb4caSwyllys 	outbuflen = pcert->Length;
119299ebb4caSwyllys 	outbuf = malloc(outbuflen);
119399ebb4caSwyllys 	if (outbuf == NULL) {
119499ebb4caSwyllys 		free(fullpath);
119599ebb4caSwyllys 		return (KMF_ERR_MEMORY);
119699ebb4caSwyllys 	}
119799ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
119899ebb4caSwyllys 
1199*34acef67Swyllys 	if ((fp = fopen(fullpath, "w")) == NULL) {
120099ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
120199ebb4caSwyllys 		ret = KMF_ERR_INTERNAL;
120299ebb4caSwyllys 		goto out;
120399ebb4caSwyllys 	}
120499ebb4caSwyllys 
120599ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
120699ebb4caSwyllys 		len = fwrite(outbuf, 1, outbuflen, fp);
120799ebb4caSwyllys 		if (len != outbuflen) {
120899ebb4caSwyllys 			SET_SYS_ERROR(kmfh, errno);
120999ebb4caSwyllys 			ret = KMF_ERR_WRITE_FILE;
121099ebb4caSwyllys 		} else {
121199ebb4caSwyllys 			ret = KMF_OK;
121299ebb4caSwyllys 		}
121399ebb4caSwyllys 		goto out;
121499ebb4caSwyllys 	}
121599ebb4caSwyllys 
121699ebb4caSwyllys 	/*
121799ebb4caSwyllys 	 * The output format is not KMF_FORMAT_ASN1, so we will
121899ebb4caSwyllys 	 * Convert the cert data to OpenSSL internal X509 first.
121999ebb4caSwyllys 	 */
122099ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
122199ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, outbuflen);
122299ebb4caSwyllys 	if (xcert == NULL) {
122399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
122499ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
122599ebb4caSwyllys 		goto out;
122699ebb4caSwyllys 	}
122799ebb4caSwyllys 
122899ebb4caSwyllys 	if (format == KMF_FORMAT_PEM) {
122999ebb4caSwyllys 		/* Convert to the PEM format and write it out */
123099ebb4caSwyllys 		if (!PEM_write_X509(fp, xcert)) {
123199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
123299ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
123399ebb4caSwyllys 		} else {
123499ebb4caSwyllys 			ret = KMF_OK;
123599ebb4caSwyllys 		}
123699ebb4caSwyllys 		goto out;
123799ebb4caSwyllys 	}
123899ebb4caSwyllys 
123999ebb4caSwyllys out:
124099ebb4caSwyllys 	if (fullpath != NULL)
124199ebb4caSwyllys 		free(fullpath);
124299ebb4caSwyllys 
124399ebb4caSwyllys 	if (outbuf != NULL) {
124499ebb4caSwyllys 		free(outbuf);
124599ebb4caSwyllys 	}
124699ebb4caSwyllys 	if (fp != NULL) {
124799ebb4caSwyllys 		(void) fclose(fp);
124899ebb4caSwyllys 	}
124999ebb4caSwyllys 
125099ebb4caSwyllys 	if (xcert != NULL) {
125199ebb4caSwyllys 		X509_free(xcert);
125299ebb4caSwyllys 	}
125399ebb4caSwyllys 
125499ebb4caSwyllys 	return (ret);
125599ebb4caSwyllys }
125699ebb4caSwyllys 
125799ebb4caSwyllys KMF_RETURN
125899ebb4caSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, KMF_DELETECERT_PARAMS *params)
125999ebb4caSwyllys {
126099ebb4caSwyllys 	KMF_RETURN rv;
126199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
126299ebb4caSwyllys 	char *fullpath = NULL;
126399ebb4caSwyllys 	KMF_DATA certdata = {NULL, 0};
126499ebb4caSwyllys 
126599ebb4caSwyllys 	if (params == NULL) {
126699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
126799ebb4caSwyllys 	}
126899ebb4caSwyllys 
126999ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
127099ebb4caSwyllys 	    params->sslparms.certfile);
127199ebb4caSwyllys 
127299ebb4caSwyllys 	if (fullpath == NULL)
127399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
127499ebb4caSwyllys 
127599ebb4caSwyllys 	if (isdir(fullpath)) {
127699ebb4caSwyllys 		DIR *dirp;
127799ebb4caSwyllys 		struct dirent *dp;
127899ebb4caSwyllys 
127999ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
128099ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
128199ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
128299ebb4caSwyllys 		}
128399ebb4caSwyllys 
128499ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
128599ebb4caSwyllys 			if (strcmp(dp->d_name, ".") != 0 &&
128699ebb4caSwyllys 			    strcmp(dp->d_name, "..") != 0) {
128799ebb4caSwyllys 				char *fname;
128899ebb4caSwyllys 
128999ebb4caSwyllys 				fname = get_fullpath(fullpath,
129099ebb4caSwyllys 				    (char *)&dp->d_name);
129199ebb4caSwyllys 
129299ebb4caSwyllys 				if (fname == NULL) {
129399ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
129499ebb4caSwyllys 					break;
129599ebb4caSwyllys 				}
129699ebb4caSwyllys 
129799ebb4caSwyllys 				rv = kmf_load_cert(kmfh, params, fname,
129899ebb4caSwyllys 				    &certdata);
129999ebb4caSwyllys 
130099ebb4caSwyllys 				if (rv == KMF_ERR_CERT_NOT_FOUND) {
130199ebb4caSwyllys 					free(fname);
130299ebb4caSwyllys 					if (certdata.Data)
130399ebb4caSwyllys 						free(certdata.Data);
130499ebb4caSwyllys 					rv = KMF_OK;
130599ebb4caSwyllys 					continue;
130699ebb4caSwyllys 				} else if (rv != KMF_OK) {
130799ebb4caSwyllys 					free(fname);
130899ebb4caSwyllys 					break;
130999ebb4caSwyllys 				}
131099ebb4caSwyllys 
131199ebb4caSwyllys 				if (unlink(fname) != 0) {
131299ebb4caSwyllys 					SET_SYS_ERROR(kmfh, errno);
131399ebb4caSwyllys 					rv = KMF_ERR_INTERNAL;
131499ebb4caSwyllys 					free(fname);
131599ebb4caSwyllys 					break;
131699ebb4caSwyllys 				}
131799ebb4caSwyllys 				free(fname);
131899ebb4caSwyllys 				if (certdata.Data)
131999ebb4caSwyllys 					free(certdata.Data);
132099ebb4caSwyllys 			}
132199ebb4caSwyllys 		}
132299ebb4caSwyllys 		(void) closedir(dirp);
132399ebb4caSwyllys 	} else {
132499ebb4caSwyllys 		/* Just try to load a single certificate */
132599ebb4caSwyllys 		rv = kmf_load_cert(kmfh, params, fullpath, &certdata);
132699ebb4caSwyllys 		if (rv == KMF_OK) {
132799ebb4caSwyllys 			if (unlink(fullpath) != 0) {
132899ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
132999ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
133099ebb4caSwyllys 			}
133199ebb4caSwyllys 		}
133299ebb4caSwyllys 	}
133399ebb4caSwyllys 
133499ebb4caSwyllys out:
133599ebb4caSwyllys 	if (fullpath != NULL)
133699ebb4caSwyllys 		free(fullpath);
133799ebb4caSwyllys 
133899ebb4caSwyllys 	if (certdata.Data)
133999ebb4caSwyllys 		free(certdata.Data);
134099ebb4caSwyllys 
134199ebb4caSwyllys 	return (rv);
134299ebb4caSwyllys }
134399ebb4caSwyllys 
134499ebb4caSwyllys KMF_RETURN
134599ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
134699ebb4caSwyllys 	KMF_DATA *keydata)
134799ebb4caSwyllys {
134899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
134999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
135099ebb4caSwyllys 	int n;
135199ebb4caSwyllys 
135299ebb4caSwyllys 	if (key == NULL || keydata == NULL ||
135399ebb4caSwyllys 	    key->keyp == NULL)
135499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
135599ebb4caSwyllys 
135699ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
135799ebb4caSwyllys 		RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
135899ebb4caSwyllys 
135999ebb4caSwyllys 		if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
136099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
136199ebb4caSwyllys 			return (KMF_ERR_ENCODING);
136299ebb4caSwyllys 		}
136399ebb4caSwyllys 		RSA_free(pubkey);
136499ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
136599ebb4caSwyllys 		DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
136699ebb4caSwyllys 
136799ebb4caSwyllys 		if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
136899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
136999ebb4caSwyllys 			return (KMF_ERR_ENCODING);
137099ebb4caSwyllys 		}
137199ebb4caSwyllys 		DSA_free(pubkey);
137299ebb4caSwyllys 	} else {
137399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
137499ebb4caSwyllys 	}
137599ebb4caSwyllys 	keydata->Length = n;
137699ebb4caSwyllys 
137799ebb4caSwyllys cleanup:
137899ebb4caSwyllys 	if (rv != KMF_OK) {
137999ebb4caSwyllys 		if (keydata->Data)
138099ebb4caSwyllys 			free(keydata->Data);
138199ebb4caSwyllys 		keydata->Data = NULL;
138299ebb4caSwyllys 		keydata->Length = 0;
138399ebb4caSwyllys 	}
138499ebb4caSwyllys 
138599ebb4caSwyllys 	return (rv);
138699ebb4caSwyllys }
138799ebb4caSwyllys 
138899ebb4caSwyllys static KMF_RETURN
138999ebb4caSwyllys ssl_write_private_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
139099ebb4caSwyllys 	KMF_CREDENTIAL *cred, EVP_PKEY *pkey)
139199ebb4caSwyllys {
139299ebb4caSwyllys 	int rv = 0;
139399ebb4caSwyllys 	RSA *rsa;
139499ebb4caSwyllys 	DSA *dsa;
139599ebb4caSwyllys 
139699ebb4caSwyllys 	switch (format) {
139799ebb4caSwyllys 		case KMF_FORMAT_ASN1:
139899ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
139999ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
140099ebb4caSwyllys 				rv = i2d_RSAPrivateKey_bio(out, rsa);
140199ebb4caSwyllys 				RSA_free(rsa);
140299ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
140399ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
140499ebb4caSwyllys 				rv = i2d_DSAPrivateKey_bio(out, dsa);
140599ebb4caSwyllys 				DSA_free(dsa);
140699ebb4caSwyllys 			}
140799ebb4caSwyllys 			if (rv == 1) {
140899ebb4caSwyllys 				rv = KMF_OK;
140999ebb4caSwyllys 			} else {
141099ebb4caSwyllys 				SET_ERROR(kmfh, rv);
141199ebb4caSwyllys 			}
141299ebb4caSwyllys 			break;
141399ebb4caSwyllys 		case KMF_FORMAT_PEM:
141499ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
141599ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
141699ebb4caSwyllys 				rv = PEM_write_bio_RSAPrivateKey(out,
1417*34acef67Swyllys 				    rsa, NULL /* encryption type */,
1418*34acef67Swyllys 				    NULL, 0, NULL, cred->cred);
141999ebb4caSwyllys 				RSA_free(rsa);
142099ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
142199ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
142299ebb4caSwyllys 				rv = PEM_write_bio_DSAPrivateKey(out,
1423*34acef67Swyllys 				    dsa, NULL /* encryption type */,
1424*34acef67Swyllys 				    NULL, 0, NULL, cred->cred);
142599ebb4caSwyllys 				DSA_free(dsa);
142699ebb4caSwyllys 			}
142799ebb4caSwyllys 
142899ebb4caSwyllys 			if (rv == 1) {
142999ebb4caSwyllys 				rv = KMF_OK;
143099ebb4caSwyllys 			} else {
143199ebb4caSwyllys 				SET_ERROR(kmfh, rv);
143299ebb4caSwyllys 			}
143399ebb4caSwyllys 			break;
143499ebb4caSwyllys 
143599ebb4caSwyllys 		default:
143699ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
143799ebb4caSwyllys 	}
143899ebb4caSwyllys 
143999ebb4caSwyllys 	return (rv);
144099ebb4caSwyllys }
144199ebb4caSwyllys 
144299ebb4caSwyllys KMF_RETURN
144399ebb4caSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, KMF_CREATEKEYPAIR_PARAMS *params,
144499ebb4caSwyllys 	KMF_KEY_HANDLE *privkey, KMF_KEY_HANDLE *pubkey)
144599ebb4caSwyllys {
144699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
144799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
144899ebb4caSwyllys 	int format;
144999ebb4caSwyllys 	uint32_t eValue = 0x010001;
145099ebb4caSwyllys 	RSA *sslPrivKey = NULL;
145199ebb4caSwyllys 	DSA *sslDSAKey = NULL;
145299ebb4caSwyllys 	EVP_PKEY *eprikey = NULL;
145399ebb4caSwyllys 	EVP_PKEY *epubkey = NULL;
145499ebb4caSwyllys 	BIO *out = NULL;
145599ebb4caSwyllys 	char *fullpath = NULL;
145699ebb4caSwyllys 
145799ebb4caSwyllys 	if (params == NULL || params->sslparms.keyfile == NULL) {
145899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
145999ebb4caSwyllys 	}
146099ebb4caSwyllys 
146199ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
146299ebb4caSwyllys 	    params->sslparms.keyfile);
146399ebb4caSwyllys 
146499ebb4caSwyllys 	if (fullpath == NULL)
146599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
146699ebb4caSwyllys 
146799ebb4caSwyllys 	/* If the requested file exists, return an error */
146899ebb4caSwyllys 	if (access(fullpath, F_OK) == 0) {
146999ebb4caSwyllys 		free(fullpath);
147099ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
147199ebb4caSwyllys 	}
147299ebb4caSwyllys 
147399ebb4caSwyllys 	eprikey = EVP_PKEY_new();
147499ebb4caSwyllys 	if (eprikey == NULL) {
147599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
147699ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
147799ebb4caSwyllys 		goto cleanup;
147899ebb4caSwyllys 	}
147999ebb4caSwyllys 	epubkey = EVP_PKEY_new();
148099ebb4caSwyllys 	if (epubkey == NULL) {
148199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
148299ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
148399ebb4caSwyllys 		goto cleanup;
148499ebb4caSwyllys 	}
148599ebb4caSwyllys 	if (params->keytype == KMF_RSA) {
148699ebb4caSwyllys 		if (params->rsa_exponent.len > 0 &&
148799ebb4caSwyllys 		    params->rsa_exponent.len <= sizeof (eValue) &&
148899ebb4caSwyllys 		    params->rsa_exponent.val != NULL)
148999ebb4caSwyllys 			/*LINTED*/
149099ebb4caSwyllys 			eValue = *(uint32_t *)params->rsa_exponent.val;
149199ebb4caSwyllys 
149299ebb4caSwyllys 		sslPrivKey = RSA_generate_key(params->keylength, eValue,
149399ebb4caSwyllys 		    NULL, NULL);
149499ebb4caSwyllys 		if (sslPrivKey == NULL) {
149599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
149699ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
149799ebb4caSwyllys 		} else {
149899ebb4caSwyllys 			if (privkey != NULL &&
149999ebb4caSwyllys 			    EVP_PKEY_set1_RSA(eprikey, sslPrivKey)) {
150099ebb4caSwyllys 				privkey->kstype = KMF_KEYSTORE_OPENSSL;
150199ebb4caSwyllys 				privkey->keyalg = KMF_RSA;
150299ebb4caSwyllys 				privkey->keyclass = KMF_ASYM_PRI;
150399ebb4caSwyllys 				privkey->israw = FALSE;
150499ebb4caSwyllys 				privkey->keylabel = (char *)strdup(fullpath);
150599ebb4caSwyllys 				privkey->keyp = (void *)eprikey;
150699ebb4caSwyllys 			}
150799ebb4caSwyllys 			/* OpenSSL derives the public key from the private */
150899ebb4caSwyllys 			if (pubkey != NULL &&
150999ebb4caSwyllys 			    EVP_PKEY_set1_RSA(epubkey, sslPrivKey)) {
151099ebb4caSwyllys 				pubkey->kstype = KMF_KEYSTORE_OPENSSL;
151199ebb4caSwyllys 				pubkey->keyalg = KMF_RSA;
151299ebb4caSwyllys 				pubkey->israw = FALSE;
151399ebb4caSwyllys 				pubkey->keyclass = KMF_ASYM_PUB;
151499ebb4caSwyllys 				pubkey->keylabel = (char *)strdup(fullpath);
151599ebb4caSwyllys 				pubkey->keyp = (void *)epubkey;
151699ebb4caSwyllys 			}
151799ebb4caSwyllys 		}
151899ebb4caSwyllys 	} else if (params->keytype == KMF_DSA) {
151999ebb4caSwyllys 		sslDSAKey = DSA_new();
152099ebb4caSwyllys 		if (sslDSAKey == NULL) {
152199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
152299ebb4caSwyllys 			return (KMF_ERR_MEMORY);
152399ebb4caSwyllys 		}
152499ebb4caSwyllys 
152599ebb4caSwyllys 		if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) ==
152699ebb4caSwyllys 		    NULL) {
152799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
152899ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
152999ebb4caSwyllys 			goto cleanup;
153099ebb4caSwyllys 		}
153199ebb4caSwyllys 		if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) ==
153299ebb4caSwyllys 		    NULL) {
153399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
153499ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
153599ebb4caSwyllys 			goto cleanup;
153699ebb4caSwyllys 		}
153799ebb4caSwyllys 		if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) ==
153899ebb4caSwyllys 		    NULL) {
153999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
154099ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
154199ebb4caSwyllys 			goto cleanup;
154299ebb4caSwyllys 		}
154399ebb4caSwyllys 
154499ebb4caSwyllys 		if (!DSA_generate_key(sslDSAKey)) {
154599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
154699ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
154799ebb4caSwyllys 			goto cleanup;
154899ebb4caSwyllys 		}
154999ebb4caSwyllys 
155099ebb4caSwyllys 		if (privkey != NULL) {
155199ebb4caSwyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
155299ebb4caSwyllys 			privkey->keyalg = KMF_DSA;
155399ebb4caSwyllys 			privkey->keyclass = KMF_ASYM_PRI;
155499ebb4caSwyllys 			privkey->israw = FALSE;
155599ebb4caSwyllys 			privkey->keylabel = (char *)strdup(fullpath);
155699ebb4caSwyllys 			if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
155799ebb4caSwyllys 				privkey->keyp = (void *)eprikey;
155899ebb4caSwyllys 			} else {
155999ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
156099ebb4caSwyllys 				rv = KMF_ERR_KEYGEN_FAILED;
156199ebb4caSwyllys 				goto cleanup;
156299ebb4caSwyllys 			}
156399ebb4caSwyllys 		}
156499ebb4caSwyllys 		if (pubkey != NULL) {
156599ebb4caSwyllys 			DSA *dp = DSA_new();
156699ebb4caSwyllys 			/* Make a copy for the public key */
156799ebb4caSwyllys 			if (dp != NULL) {
156899ebb4caSwyllys 				if ((dp->p = BN_new()) == NULL) {
156999ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
157099ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
157199ebb4caSwyllys 					DSA_free(dp);
157299ebb4caSwyllys 					goto cleanup;
157399ebb4caSwyllys 				}
157499ebb4caSwyllys 				if ((dp->q = BN_new()) == NULL) {
157599ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
157699ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
157799ebb4caSwyllys 					BN_free(dp->p);
157899ebb4caSwyllys 					DSA_free(dp);
157999ebb4caSwyllys 					goto cleanup;
158099ebb4caSwyllys 				}
158199ebb4caSwyllys 				if ((dp->g = BN_new()) == NULL) {
158299ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
158399ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
158499ebb4caSwyllys 					BN_free(dp->q);
158599ebb4caSwyllys 					BN_free(dp->p);
158699ebb4caSwyllys 					DSA_free(dp);
158799ebb4caSwyllys 					goto cleanup;
158899ebb4caSwyllys 				}
158999ebb4caSwyllys 				if ((dp->pub_key = BN_new()) == NULL) {
159099ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
159199ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
159299ebb4caSwyllys 					BN_free(dp->q);
159399ebb4caSwyllys 					BN_free(dp->p);
159499ebb4caSwyllys 					BN_free(dp->g);
159599ebb4caSwyllys 					DSA_free(dp);
159699ebb4caSwyllys 					goto cleanup;
159799ebb4caSwyllys 				}
159899ebb4caSwyllys 				(void) BN_copy(dp->p, sslDSAKey->p);
159999ebb4caSwyllys 				(void) BN_copy(dp->q, sslDSAKey->q);
160099ebb4caSwyllys 				(void) BN_copy(dp->g, sslDSAKey->g);
160199ebb4caSwyllys 				(void) BN_copy(dp->pub_key, sslDSAKey->pub_key);
160299ebb4caSwyllys 
160399ebb4caSwyllys 				pubkey->kstype = KMF_KEYSTORE_OPENSSL;
160499ebb4caSwyllys 				pubkey->keyalg = KMF_DSA;
160599ebb4caSwyllys 				pubkey->keyclass = KMF_ASYM_PUB;
160699ebb4caSwyllys 				pubkey->israw = FALSE;
160799ebb4caSwyllys 				pubkey->keylabel = (char *)strdup(fullpath);
160899ebb4caSwyllys 
160999ebb4caSwyllys 				if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
161099ebb4caSwyllys 					pubkey->keyp = (void *)epubkey;
161199ebb4caSwyllys 				} else {
161299ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
161399ebb4caSwyllys 					rv = KMF_ERR_KEYGEN_FAILED;
161499ebb4caSwyllys 					goto cleanup;
161599ebb4caSwyllys 				}
161699ebb4caSwyllys 			}
161799ebb4caSwyllys 		}
161899ebb4caSwyllys 	}
161999ebb4caSwyllys 
162099ebb4caSwyllys 	if (rv != KMF_OK) {
162199ebb4caSwyllys 		goto cleanup;
162299ebb4caSwyllys 	}
162399ebb4caSwyllys 
162499ebb4caSwyllys 	/* Store the private key to the keyfile */
162599ebb4caSwyllys 	format = params->sslparms.format;
162699ebb4caSwyllys 	out = BIO_new_file(fullpath, "wb");
162799ebb4caSwyllys 	if (out == NULL) {
162899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
162999ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
163099ebb4caSwyllys 		goto cleanup;
163199ebb4caSwyllys 	}
163299ebb4caSwyllys 	rv = ssl_write_private_key(kmfh, format, out, &params->cred, eprikey);
163399ebb4caSwyllys 
163499ebb4caSwyllys cleanup:
163599ebb4caSwyllys 	if (rv != KMF_OK) {
163699ebb4caSwyllys 		if (eprikey != NULL)
163799ebb4caSwyllys 			EVP_PKEY_free(eprikey);
163899ebb4caSwyllys 
163999ebb4caSwyllys 		if (epubkey != NULL)
164099ebb4caSwyllys 			EVP_PKEY_free(epubkey);
164199ebb4caSwyllys 
164299ebb4caSwyllys 		if (pubkey->keylabel) {
164399ebb4caSwyllys 			free(pubkey->keylabel);
164499ebb4caSwyllys 			pubkey->keylabel = NULL;
164599ebb4caSwyllys 		}
164699ebb4caSwyllys 
164799ebb4caSwyllys 		if (privkey->keylabel) {
164899ebb4caSwyllys 			free(privkey->keylabel);
164999ebb4caSwyllys 			privkey->keylabel = NULL;
165099ebb4caSwyllys 		}
165199ebb4caSwyllys 
165299ebb4caSwyllys 		pubkey->keyp = NULL;
165399ebb4caSwyllys 		privkey->keyp = NULL;
165499ebb4caSwyllys 	}
165599ebb4caSwyllys 
165699ebb4caSwyllys 	if (sslPrivKey)
165799ebb4caSwyllys 		RSA_free(sslPrivKey);
165899ebb4caSwyllys 
165999ebb4caSwyllys 	if (sslDSAKey)
166099ebb4caSwyllys 		DSA_free(sslDSAKey);
166199ebb4caSwyllys 
166299ebb4caSwyllys 
166399ebb4caSwyllys 	if (out != NULL)
166499ebb4caSwyllys 		(void) BIO_free(out);
166599ebb4caSwyllys 
166699ebb4caSwyllys 	if (fullpath)
166799ebb4caSwyllys 		free(fullpath);
166899ebb4caSwyllys 
166999ebb4caSwyllys 	/* Protect the file by making it read-only */
167099ebb4caSwyllys 	if (rv == KMF_OK) {
167199ebb4caSwyllys 		(void) chmod(fullpath, 0400);
167299ebb4caSwyllys 	}
167399ebb4caSwyllys 	return (rv);
167499ebb4caSwyllys }
167599ebb4caSwyllys 
167699ebb4caSwyllys KMF_RETURN
167799ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
167899ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
167999ebb4caSwyllys {
168099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
168199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
168299ebb4caSwyllys 	KMF_ALGORITHM_INDEX		AlgId;
168399ebb4caSwyllys 	EVP_MD_CTX ctx;
168499ebb4caSwyllys 	const EVP_MD *md;
168502744e81Swyllys 
168699ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
168799ebb4caSwyllys 	    tobesigned == NULL || output == NULL ||
168899ebb4caSwyllys 	    tobesigned->Data == NULL ||
168999ebb4caSwyllys 	    output->Data == NULL)
169099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
169199ebb4caSwyllys 
169299ebb4caSwyllys 	/* Map the OID to an OpenSSL algorithm */
169399ebb4caSwyllys 	AlgId = X509_AlgorithmOidToAlgId(AlgOID);
169499ebb4caSwyllys 	if (AlgId == KMF_ALGID_NONE)
169599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
169699ebb4caSwyllys 
169799ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
169899ebb4caSwyllys 		EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
169999ebb4caSwyllys 		uchar_t *p;
170002744e81Swyllys 		int len;
170199ebb4caSwyllys 		if (AlgId == KMF_ALGID_MD5WithRSA)
170299ebb4caSwyllys 			md = EVP_md5();
170399ebb4caSwyllys 		else if (AlgId == KMF_ALGID_MD2WithRSA)
170499ebb4caSwyllys 			md = EVP_md2();
170599ebb4caSwyllys 		else if (AlgId == KMF_ALGID_SHA1WithRSA)
170699ebb4caSwyllys 			md = EVP_sha1();
170702744e81Swyllys 		else if (AlgId == KMF_ALGID_RSA)
170802744e81Swyllys 			md = NULL;
170999ebb4caSwyllys 		else
171099ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
171199ebb4caSwyllys 
171202744e81Swyllys 		if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
171302744e81Swyllys 			RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
171499ebb4caSwyllys 
171502744e81Swyllys 			p = output->Data;
171602744e81Swyllys 			if ((len = RSA_private_encrypt(tobesigned->Length,
171702744e81Swyllys 			    tobesigned->Data, p, rsa,
171802744e81Swyllys 			    RSA_PKCS1_PADDING)) <= 0) {
171902744e81Swyllys 				SET_ERROR(kmfh, ERR_get_error());
172002744e81Swyllys 				ret = KMF_ERR_INTERNAL;
172102744e81Swyllys 			}
172202744e81Swyllys 			output->Length = len;
172302744e81Swyllys 		} else {
172499ebb4caSwyllys 			(void) EVP_MD_CTX_init(&ctx);
172599ebb4caSwyllys 			(void) EVP_SignInit_ex(&ctx, md, NULL);
172699ebb4caSwyllys 			(void) EVP_SignUpdate(&ctx, tobesigned->Data,
172799ebb4caSwyllys 			    (uint32_t)tobesigned->Length);
172899ebb4caSwyllys 			len = (uint32_t)output->Length;
172999ebb4caSwyllys 			p = output->Data;
173002744e81Swyllys 			if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) {
173199ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
173202744e81Swyllys 				len = 0;
173302744e81Swyllys 				ret = KMF_ERR_INTERNAL;
173499ebb4caSwyllys 			}
173599ebb4caSwyllys 			output->Length = len;
173699ebb4caSwyllys 			(void) EVP_MD_CTX_cleanup(&ctx);
173702744e81Swyllys 		}
173899ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
173999ebb4caSwyllys 		DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
174099ebb4caSwyllys 
174199ebb4caSwyllys 		uchar_t hash[EVP_MAX_MD_SIZE];
174299ebb4caSwyllys 		uint32_t hashlen;
174399ebb4caSwyllys 		DSA_SIG *dsasig;
174499ebb4caSwyllys 
174599ebb4caSwyllys 		/*
174699ebb4caSwyllys 		 * OpenSSL EVP_Sign operation automatically converts to
174799ebb4caSwyllys 		 * ASN.1 output so we do the operations separately so we
174899ebb4caSwyllys 		 * are assured of NOT getting ASN.1 output returned.
174999ebb4caSwyllys 		 * KMF does not want ASN.1 encoded results because
175099ebb4caSwyllys 		 * not all mechanisms return ASN.1 encodings (PKCS#11
175199ebb4caSwyllys 		 * and NSS return raw signature data).
175299ebb4caSwyllys 		 */
175399ebb4caSwyllys 		md = EVP_sha1();
175499ebb4caSwyllys 		EVP_MD_CTX_init(&ctx);
175599ebb4caSwyllys 		(void) EVP_DigestInit_ex(&ctx, md, NULL);
175699ebb4caSwyllys 		(void) EVP_DigestUpdate(&ctx, tobesigned->Data,
175799ebb4caSwyllys 		    tobesigned->Length);
175899ebb4caSwyllys 		(void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
175999ebb4caSwyllys 		(void) EVP_MD_CTX_cleanup(&ctx);
176099ebb4caSwyllys 
176199ebb4caSwyllys 		dsasig = DSA_do_sign(hash, hashlen, dsa);
176299ebb4caSwyllys 		if (dsasig != NULL) {
176399ebb4caSwyllys 			int i;
176499ebb4caSwyllys 			output->Length = i = BN_bn2bin(dsasig->r, output->Data);
176599ebb4caSwyllys 			output->Length += BN_bn2bin(dsasig->s,
176699ebb4caSwyllys 			    &output->Data[i]);
176799ebb4caSwyllys 			DSA_SIG_free(dsasig);
176899ebb4caSwyllys 		} else {
176999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
177099ebb4caSwyllys 		}
177199ebb4caSwyllys 	} else {
177299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
177399ebb4caSwyllys 	}
177499ebb4caSwyllys cleanup:
177599ebb4caSwyllys 	return (ret);
177699ebb4caSwyllys }
177799ebb4caSwyllys 
177899ebb4caSwyllys KMF_RETURN
177999ebb4caSwyllys /*ARGSUSED*/
178099ebb4caSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle, KMF_DELETEKEY_PARAMS *params,
178199ebb4caSwyllys 	KMF_KEY_HANDLE *key, boolean_t destroy)
178299ebb4caSwyllys {
178399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
178499ebb4caSwyllys 	if (key == NULL || key->keyp == NULL)
178599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
178699ebb4caSwyllys 
178799ebb4caSwyllys 	if (key->keyclass != KMF_ASYM_PUB &&
178899ebb4caSwyllys 	    key->keyclass != KMF_ASYM_PRI &&
178999ebb4caSwyllys 	    key->keyclass != KMF_SYMMETRIC)
179099ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
179199ebb4caSwyllys 
179299ebb4caSwyllys 	if (key->keyclass == KMF_SYMMETRIC) {
179399ebb4caSwyllys 		KMF_FreeRawSymKey((KMF_RAW_SYM_KEY *)key->keyp);
179499ebb4caSwyllys 		key->keyp = NULL;
179599ebb4caSwyllys 	} else {
179699ebb4caSwyllys 		if (key->keyp != NULL) {
179799ebb4caSwyllys 			EVP_PKEY_free(key->keyp);
179899ebb4caSwyllys 			key->keyp = NULL;
179999ebb4caSwyllys 		}
180099ebb4caSwyllys 	}
180199ebb4caSwyllys 
180299ebb4caSwyllys 	if (key->keylabel != NULL) {
180399ebb4caSwyllys 		EVP_PKEY *pkey = NULL;
180499ebb4caSwyllys 		/* If the file exists, make sure it is a proper key. */
180599ebb4caSwyllys 		pkey = openssl_load_key(handle, key->keylabel);
180699ebb4caSwyllys 		if (pkey == NULL) {
180799ebb4caSwyllys 			free(key->keylabel);
180899ebb4caSwyllys 			key->keylabel = NULL;
180999ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
181099ebb4caSwyllys 		}
181199ebb4caSwyllys 		EVP_PKEY_free(pkey);
181299ebb4caSwyllys 
181399ebb4caSwyllys 		if (destroy) {
181499ebb4caSwyllys 			if (unlink(key->keylabel) != 0) {
181599ebb4caSwyllys 				KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
181699ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
181799ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
181899ebb4caSwyllys 			}
181999ebb4caSwyllys 		}
182099ebb4caSwyllys 		if (key->keylabel != NULL) {
182199ebb4caSwyllys 			free(key->keylabel);
182299ebb4caSwyllys 			key->keylabel = NULL;
182399ebb4caSwyllys 		}
182499ebb4caSwyllys 	}
182599ebb4caSwyllys 	return (rv);
182699ebb4caSwyllys }
182799ebb4caSwyllys 
182899ebb4caSwyllys KMF_RETURN
182999ebb4caSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, KMF_IMPORTCRL_PARAMS *params)
183099ebb4caSwyllys {
183199ebb4caSwyllys 	KMF_RETURN 	ret = KMF_OK;
183299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
183399ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
183499ebb4caSwyllys 	X509		*xcert = NULL;
183599ebb4caSwyllys 	EVP_PKEY	*pkey;
183699ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
183799ebb4caSwyllys 	BIO *in = NULL, *out = NULL;
183899ebb4caSwyllys 	int openssl_ret = 0;
183999ebb4caSwyllys 	char *outcrlfile = NULL;
184099ebb4caSwyllys 	KMF_ENCODE_FORMAT outformat;
184199ebb4caSwyllys 
184299ebb4caSwyllys 	if (params == NULL || params->sslparms.crlfile == NULL) {
184399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
184499ebb4caSwyllys 	}
184599ebb4caSwyllys 
184699ebb4caSwyllys 	if (params->sslparms.crl_check == B_TRUE &&
184799ebb4caSwyllys 	    params->sslparms.certfile == NULL) {
184899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
184999ebb4caSwyllys 	}
185099ebb4caSwyllys 
185199ebb4caSwyllys 	outcrlfile = get_fullpath(params->sslparms.dirpath,
185299ebb4caSwyllys 	    params->sslparms.outcrlfile);
185399ebb4caSwyllys 
185499ebb4caSwyllys 	if (outcrlfile == NULL)
185599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
185699ebb4caSwyllys 
185799ebb4caSwyllys 	if (isdir(outcrlfile)) {
185899ebb4caSwyllys 		free(outcrlfile);
185999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
186099ebb4caSwyllys 	}
186199ebb4caSwyllys 
186299ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, params->sslparms.crlfile, &format);
186399ebb4caSwyllys 	if (ret != KMF_OK) {
186499ebb4caSwyllys 		free(outcrlfile);
186599ebb4caSwyllys 		return (ret);
186699ebb4caSwyllys 	}
186799ebb4caSwyllys 
186899ebb4caSwyllys 	in = BIO_new_file(params->sslparms.crlfile, "rb");
186999ebb4caSwyllys 	if (in == NULL)	{
187099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
187199ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
187299ebb4caSwyllys 		goto end;
187399ebb4caSwyllys 	}
187499ebb4caSwyllys 
187599ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
187699ebb4caSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
187799ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
187899ebb4caSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
187999ebb4caSwyllys 	}
188099ebb4caSwyllys 
188199ebb4caSwyllys 	if (xcrl == NULL) {
188299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
188399ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
188499ebb4caSwyllys 		goto end;
188599ebb4caSwyllys 	}
188699ebb4caSwyllys 
188799ebb4caSwyllys 	/* If bypasscheck is specified, no need to verify. */
188899ebb4caSwyllys 	if (params->sslparms.crl_check == B_FALSE) {
188999ebb4caSwyllys 		goto output;
189099ebb4caSwyllys 	}
189199ebb4caSwyllys 
189299ebb4caSwyllys 	ret = KMF_IsCertFile(handle, params->sslparms.certfile, &format);
189399ebb4caSwyllys 	if (ret != KMF_OK)
189499ebb4caSwyllys 		goto end;
189599ebb4caSwyllys 
189699ebb4caSwyllys 	/* Read in the CA cert file and convert to X509 */
189799ebb4caSwyllys 	if (BIO_read_filename(in, params->sslparms.certfile) <= 0) {
189899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
189999ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
190099ebb4caSwyllys 		goto end;
190199ebb4caSwyllys 	}
190299ebb4caSwyllys 
190399ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
190499ebb4caSwyllys 		xcert = d2i_X509_bio(in, NULL);
190599ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
190699ebb4caSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
190799ebb4caSwyllys 	} else {
190899ebb4caSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
190999ebb4caSwyllys 		goto end;
191099ebb4caSwyllys 	}
191199ebb4caSwyllys 
191299ebb4caSwyllys 	if (xcert == NULL) {
191399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
191499ebb4caSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
191599ebb4caSwyllys 		goto end;
191699ebb4caSwyllys 	}
191799ebb4caSwyllys 	/* Now get the public key from the CA cert */
191899ebb4caSwyllys 	pkey = X509_get_pubkey(xcert);
191999ebb4caSwyllys 	if (!pkey) {
192099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
192199ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
192299ebb4caSwyllys 		goto end;
192399ebb4caSwyllys 	}
192499ebb4caSwyllys 
192599ebb4caSwyllys 	/* Verify the CRL with the CA's public key */
192699ebb4caSwyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
192799ebb4caSwyllys 	EVP_PKEY_free(pkey);
192899ebb4caSwyllys 	if (openssl_ret > 0) {
192999ebb4caSwyllys 		ret = KMF_OK;  /* verify succeed */
193099ebb4caSwyllys 	} else {
193199ebb4caSwyllys 		SET_ERROR(kmfh, openssl_ret);
193299ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
193399ebb4caSwyllys 	}
193499ebb4caSwyllys 
193599ebb4caSwyllys output:
193699ebb4caSwyllys 	outformat = params->sslparms.format;
193799ebb4caSwyllys 
193899ebb4caSwyllys 	out = BIO_new_file(outcrlfile, "wb");
193999ebb4caSwyllys 	if (out == NULL) {
194099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
194199ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
194299ebb4caSwyllys 		goto end;
194399ebb4caSwyllys 	}
194499ebb4caSwyllys 
194599ebb4caSwyllys 	if (outformat == KMF_FORMAT_ASN1) {
194699ebb4caSwyllys 		openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
194799ebb4caSwyllys 	} else if (outformat == KMF_FORMAT_PEM) {
194899ebb4caSwyllys 		openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
194999ebb4caSwyllys 	} else {
195099ebb4caSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
195199ebb4caSwyllys 		goto end;
195299ebb4caSwyllys 	}
195399ebb4caSwyllys 
195499ebb4caSwyllys 	if (openssl_ret <= 0) {
195599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
195699ebb4caSwyllys 		ret = KMF_ERR_WRITE_FILE;
195799ebb4caSwyllys 	} else {
195899ebb4caSwyllys 		ret = KMF_OK;
195999ebb4caSwyllys 	}
196099ebb4caSwyllys 
196199ebb4caSwyllys end:
196299ebb4caSwyllys 	if (xcrl != NULL)
196399ebb4caSwyllys 		X509_CRL_free(xcrl);
196499ebb4caSwyllys 
196599ebb4caSwyllys 	if (xcert != NULL)
196699ebb4caSwyllys 		X509_free(xcert);
196799ebb4caSwyllys 
196899ebb4caSwyllys 	if (in != NULL)
196999ebb4caSwyllys 		(void) BIO_free(in);
197099ebb4caSwyllys 
197199ebb4caSwyllys 	if (out != NULL)
197299ebb4caSwyllys 		(void) BIO_free(out);
197399ebb4caSwyllys 
197499ebb4caSwyllys 	if (outcrlfile != NULL)
197599ebb4caSwyllys 		free(outcrlfile);
197699ebb4caSwyllys 
197799ebb4caSwyllys 	return (ret);
197899ebb4caSwyllys }
197999ebb4caSwyllys 
198099ebb4caSwyllys KMF_RETURN
198199ebb4caSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, KMF_LISTCRL_PARAMS *params,
198299ebb4caSwyllys     char **crldata)
198399ebb4caSwyllys {
198499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
198599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
198699ebb4caSwyllys 	X509_CRL   *x = NULL;
198799ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
198899ebb4caSwyllys 	char *crlfile = NULL;
198999ebb4caSwyllys 	BIO *in = NULL;
199099ebb4caSwyllys 	BIO *mem = NULL;
199199ebb4caSwyllys 	long len;
199299ebb4caSwyllys 	char *memptr;
199399ebb4caSwyllys 	char *data = NULL;
199499ebb4caSwyllys 
199599ebb4caSwyllys 	if (params == NULL || params->sslparms.crlfile == NULL) {
199699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
199799ebb4caSwyllys 	}
199899ebb4caSwyllys 
199999ebb4caSwyllys 	crlfile = get_fullpath(params->sslparms.dirpath,
200099ebb4caSwyllys 	    params->sslparms.crlfile);
200199ebb4caSwyllys 
200299ebb4caSwyllys 	if (crlfile == NULL)
200399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
200499ebb4caSwyllys 
200599ebb4caSwyllys 	if (isdir(crlfile)) {
200699ebb4caSwyllys 		free(crlfile);
200799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
200899ebb4caSwyllys 	}
200999ebb4caSwyllys 
201099ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, crlfile, &format);
201199ebb4caSwyllys 	if (ret != KMF_OK) {
201299ebb4caSwyllys 		free(crlfile);
201399ebb4caSwyllys 		return (ret);
201499ebb4caSwyllys 	}
201599ebb4caSwyllys 
201699ebb4caSwyllys 	if (bio_err == NULL)
201799ebb4caSwyllys 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
201899ebb4caSwyllys 
201999ebb4caSwyllys 	in = BIO_new_file(crlfile, "rb");
202099ebb4caSwyllys 	if (in == NULL)	{
202199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
202299ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
202399ebb4caSwyllys 		goto end;
202499ebb4caSwyllys 	}
202599ebb4caSwyllys 
202699ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
202799ebb4caSwyllys 		x = d2i_X509_CRL_bio(in, NULL);
202899ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
202999ebb4caSwyllys 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
203099ebb4caSwyllys 	}
203199ebb4caSwyllys 
203299ebb4caSwyllys 	if (x == NULL) { /* should not happen */
203399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
203499ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
203599ebb4caSwyllys 		goto end;
203699ebb4caSwyllys 	}
203799ebb4caSwyllys 
203899ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
203999ebb4caSwyllys 	if (mem == NULL) {
204099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
204199ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
204299ebb4caSwyllys 		goto end;
204399ebb4caSwyllys 	}
204499ebb4caSwyllys 
204599ebb4caSwyllys 	(void) X509_CRL_print(mem, x);
204699ebb4caSwyllys 	len = BIO_get_mem_data(mem, &memptr);
204799ebb4caSwyllys 	if (len <= 0) {
204899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
204999ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
205099ebb4caSwyllys 		goto end;
205199ebb4caSwyllys 	}
205299ebb4caSwyllys 
205399ebb4caSwyllys 	data = malloc(len + 1);
205499ebb4caSwyllys 	if (data == NULL) {
205599ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
205699ebb4caSwyllys 		goto end;
205799ebb4caSwyllys 	}
205899ebb4caSwyllys 
205999ebb4caSwyllys 	(void) memcpy(data, memptr, len);
206099ebb4caSwyllys 	data[len] = '\0';
206199ebb4caSwyllys 	*crldata = data;
206299ebb4caSwyllys 
206399ebb4caSwyllys end:
206499ebb4caSwyllys 	if (x != NULL)
206599ebb4caSwyllys 		X509_CRL_free(x);
206699ebb4caSwyllys 
206799ebb4caSwyllys 	if (crlfile != NULL)
206899ebb4caSwyllys 		free(crlfile);
206999ebb4caSwyllys 
207099ebb4caSwyllys 	if (in != NULL)
207199ebb4caSwyllys 		(void) BIO_free(in);
207299ebb4caSwyllys 
207399ebb4caSwyllys 	if (mem != NULL)
207499ebb4caSwyllys 		(void) BIO_free(mem);
207599ebb4caSwyllys 
207699ebb4caSwyllys 	return (ret);
207799ebb4caSwyllys }
207899ebb4caSwyllys 
207999ebb4caSwyllys KMF_RETURN
208099ebb4caSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, KMF_DELETECRL_PARAMS *params)
208199ebb4caSwyllys {
208299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
208399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
208499ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
208599ebb4caSwyllys 	char *crlfile = NULL;
208699ebb4caSwyllys 	BIO *in = NULL;
208799ebb4caSwyllys 
208899ebb4caSwyllys 	if (params == NULL || params->sslparms.crlfile == NULL) {
208999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
209099ebb4caSwyllys 	}
209199ebb4caSwyllys 
209299ebb4caSwyllys 	crlfile = get_fullpath(params->sslparms.dirpath,
209399ebb4caSwyllys 	    params->sslparms.crlfile);
209499ebb4caSwyllys 
209599ebb4caSwyllys 	if (crlfile == NULL)
209699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
209799ebb4caSwyllys 
209899ebb4caSwyllys 	if (isdir(crlfile)) {
209999ebb4caSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
210099ebb4caSwyllys 		goto end;
210199ebb4caSwyllys 	}
210299ebb4caSwyllys 
210399ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, crlfile, &format);
210499ebb4caSwyllys 	if (ret != KMF_OK)
210599ebb4caSwyllys 		goto end;
210699ebb4caSwyllys 
210799ebb4caSwyllys 	if (unlink(crlfile) != 0) {
210899ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
210999ebb4caSwyllys 		ret = KMF_ERR_INTERNAL;
211099ebb4caSwyllys 		goto end;
211199ebb4caSwyllys 	}
211299ebb4caSwyllys 
211399ebb4caSwyllys end:
211499ebb4caSwyllys 	if (in != NULL)
211599ebb4caSwyllys 		(void) BIO_free(in);
211699ebb4caSwyllys 	if (crlfile != NULL)
211799ebb4caSwyllys 		free(crlfile);
211899ebb4caSwyllys 
211999ebb4caSwyllys 	return (ret);
212099ebb4caSwyllys }
212199ebb4caSwyllys 
212299ebb4caSwyllys 
212399ebb4caSwyllys KMF_RETURN
212499ebb4caSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, KMF_FINDCERTINCRL_PARAMS *params)
212599ebb4caSwyllys {
212699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
212799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
212899ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
212999ebb4caSwyllys 	BIO *in = NULL;
213099ebb4caSwyllys 	X509   *xcert = NULL;
213199ebb4caSwyllys 	X509_CRL   *xcrl = NULL;
213299ebb4caSwyllys 	STACK_OF(X509_REVOKED) *revoke_stack = NULL;
213399ebb4caSwyllys 	X509_REVOKED *revoke;
213499ebb4caSwyllys 	int i;
213599ebb4caSwyllys 
213699ebb4caSwyllys 	if (params == NULL || params->sslparms.crlfile == NULL ||
213799ebb4caSwyllys 	    params->sslparms.certfile == NULL) {
213899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
213999ebb4caSwyllys 	}
214099ebb4caSwyllys 
214199ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, params->sslparms.crlfile, &format);
214299ebb4caSwyllys 	if (ret != KMF_OK)
214399ebb4caSwyllys 		return (ret);
214499ebb4caSwyllys 
214599ebb4caSwyllys 	/* Read the CRL file and load it into a X509_CRL structure */
214699ebb4caSwyllys 	in = BIO_new_file(params->sslparms.crlfile, "rb");
214799ebb4caSwyllys 	if (in == NULL)	{
214899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
214999ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
215099ebb4caSwyllys 		goto end;
215199ebb4caSwyllys 	}
215299ebb4caSwyllys 
215399ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
215499ebb4caSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
215599ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
215699ebb4caSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
215799ebb4caSwyllys 	}
215899ebb4caSwyllys 
215999ebb4caSwyllys 	if (xcrl == NULL) {
216099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
216199ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
216299ebb4caSwyllys 		goto end;
216399ebb4caSwyllys 	}
216499ebb4caSwyllys 	(void) BIO_free(in);
216599ebb4caSwyllys 
216699ebb4caSwyllys 	/* Read the Certificate file and load it into a X509 structure */
216799ebb4caSwyllys 	ret = KMF_IsCertFile(handle, params->sslparms.certfile, &format);
216899ebb4caSwyllys 	if (ret != KMF_OK)
216999ebb4caSwyllys 		goto end;
217099ebb4caSwyllys 
217199ebb4caSwyllys 	in = BIO_new_file(params->sslparms.certfile, "rb");
217299ebb4caSwyllys 	if (in == NULL)	{
217399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
217499ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
217599ebb4caSwyllys 		goto end;
217699ebb4caSwyllys 	}
217799ebb4caSwyllys 
217899ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
217999ebb4caSwyllys 		xcert = d2i_X509_bio(in, NULL);
218099ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
218199ebb4caSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
218299ebb4caSwyllys 	}
218399ebb4caSwyllys 
218499ebb4caSwyllys 	if (xcert == NULL) {
218599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
218699ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
218799ebb4caSwyllys 		goto end;
218899ebb4caSwyllys 	}
218999ebb4caSwyllys 
219099ebb4caSwyllys 	/* Check if the certificate and the CRL have same issuer */
219199ebb4caSwyllys 	if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) {
219299ebb4caSwyllys 		ret = KMF_ERR_ISSUER;
219399ebb4caSwyllys 		goto end;
219499ebb4caSwyllys 	}
219599ebb4caSwyllys 
219699ebb4caSwyllys 	/* Check to see if the certificate serial number is revoked */
219799ebb4caSwyllys 	revoke_stack = X509_CRL_get_REVOKED(xcrl);
219899ebb4caSwyllys 	if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
219999ebb4caSwyllys 		/* No revoked certificates in the CRL file */
220099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
220199ebb4caSwyllys 		ret = KMF_ERR_EMPTY_CRL;
220299ebb4caSwyllys 		goto end;
220399ebb4caSwyllys 	}
220499ebb4caSwyllys 
220599ebb4caSwyllys 	for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
220699ebb4caSwyllys 		/*LINTED*/
220799ebb4caSwyllys 		revoke = sk_X509_REVOKED_value(revoke_stack, i);
220899ebb4caSwyllys 		if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber,
220999ebb4caSwyllys 		    revoke->serialNumber) == 0) {
221099ebb4caSwyllys 			break;
221199ebb4caSwyllys 		}
221299ebb4caSwyllys 	}
221399ebb4caSwyllys 
221499ebb4caSwyllys 	if (i < sk_X509_REVOKED_num(revoke_stack)) {
221599ebb4caSwyllys 		ret = KMF_OK;
221699ebb4caSwyllys 	} else {
221799ebb4caSwyllys 		ret = KMF_ERR_NOT_REVOKED;
221899ebb4caSwyllys 	}
221999ebb4caSwyllys 
222099ebb4caSwyllys end:
222199ebb4caSwyllys 	if (in != NULL)
222299ebb4caSwyllys 		(void) BIO_free(in);
222399ebb4caSwyllys 	if (xcrl != NULL)
222499ebb4caSwyllys 		X509_CRL_free(xcrl);
222599ebb4caSwyllys 	if (xcert != NULL)
222699ebb4caSwyllys 		X509_free(xcert);
222799ebb4caSwyllys 
222899ebb4caSwyllys 	return (ret);
222999ebb4caSwyllys }
223099ebb4caSwyllys 
223199ebb4caSwyllys KMF_RETURN
223299ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
223399ebb4caSwyllys {
223499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
223599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
223699ebb4caSwyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
223799ebb4caSwyllys 
223899ebb4caSwyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
223999ebb4caSwyllys 	if (strlen(str)) {
224099ebb4caSwyllys 		*msgstr = (char *)strdup(str);
224199ebb4caSwyllys 		if ((*msgstr) == NULL)
224299ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
224399ebb4caSwyllys 	} else {
224499ebb4caSwyllys 		*msgstr = NULL;
224599ebb4caSwyllys 	}
224699ebb4caSwyllys 
224799ebb4caSwyllys 	return (ret);
224899ebb4caSwyllys }
224999ebb4caSwyllys 
225099ebb4caSwyllys static int
225199ebb4caSwyllys ext2NID(int kmfext)
225299ebb4caSwyllys {
225399ebb4caSwyllys 	switch (kmfext) {
225499ebb4caSwyllys 		case KMF_X509_EXT_KEY_USAGE:
225599ebb4caSwyllys 			return (NID_key_usage);
225699ebb4caSwyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
225799ebb4caSwyllys 			return (NID_private_key_usage_period);
225899ebb4caSwyllys 		case KMF_X509_EXT_CERT_POLICIES:
225999ebb4caSwyllys 			return (NID_certificate_policies);
226099ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
226199ebb4caSwyllys 			return (NID_subject_alt_name);
226299ebb4caSwyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
226399ebb4caSwyllys 			return (NID_issuer_alt_name);
226499ebb4caSwyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
226599ebb4caSwyllys 			return (NID_basic_constraints);
226699ebb4caSwyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
226799ebb4caSwyllys 			return (NID_ext_key_usage);
226899ebb4caSwyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
226999ebb4caSwyllys 			return (NID_authority_key_identifier);
227099ebb4caSwyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
227199ebb4caSwyllys 			return (NID_crl_distribution_points);
227299ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
227399ebb4caSwyllys 			return (NID_subject_key_identifier);
227499ebb4caSwyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
227599ebb4caSwyllys 			return (OBJ_sn2nid("policyMappings"));
227699ebb4caSwyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
227799ebb4caSwyllys 			return (OBJ_sn2nid("nameConstraints"));
227899ebb4caSwyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
227999ebb4caSwyllys 			return (OBJ_sn2nid("policyConstraints"));
228099ebb4caSwyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
228199ebb4caSwyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
228299ebb4caSwyllys 		case KMF_X509_EXT_FRESHEST_CRL:
228399ebb4caSwyllys 			return (OBJ_sn2nid("freshestCRL"));
228499ebb4caSwyllys 		default:
228599ebb4caSwyllys 			return (NID_undef);
228699ebb4caSwyllys 	}
228799ebb4caSwyllys }
228899ebb4caSwyllys 
228999ebb4caSwyllys KMF_RETURN
229099ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
229199ebb4caSwyllys 	KMF_PRINTABLE_ITEM flag, char *resultStr)
229299ebb4caSwyllys {
229399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
229499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
229599ebb4caSwyllys 	X509 *xcert = NULL;
229699ebb4caSwyllys 	unsigned char *outbuf = NULL;
229799ebb4caSwyllys 	unsigned char *outbuf_p;
229899ebb4caSwyllys 	char *tmpstr = NULL;
229999ebb4caSwyllys 	int j;
230099ebb4caSwyllys 	int ext_index, nid, len;
230199ebb4caSwyllys 	BIO *mem = NULL;
230299ebb4caSwyllys 	STACK *emlst = NULL;
230399ebb4caSwyllys 	X509_EXTENSION *ex;
230499ebb4caSwyllys 	X509_CINF *ci;
230599ebb4caSwyllys 
230699ebb4caSwyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
230799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
230899ebb4caSwyllys 	}
230999ebb4caSwyllys 
231099ebb4caSwyllys 	/* copy cert data to outbuf */
231199ebb4caSwyllys 	outbuf = malloc(pcert->Length);
231299ebb4caSwyllys 	if (outbuf == NULL) {
231399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
231499ebb4caSwyllys 	}
231599ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
231699ebb4caSwyllys 
231799ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
231899ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
231999ebb4caSwyllys 	if (xcert == NULL) {
232099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
232199ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
232299ebb4caSwyllys 		goto out;
232399ebb4caSwyllys 	}
232499ebb4caSwyllys 
232599ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
232699ebb4caSwyllys 	if (mem == NULL) {
232799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
232899ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
232999ebb4caSwyllys 		goto out;
233099ebb4caSwyllys 	}
233199ebb4caSwyllys 
233299ebb4caSwyllys 	switch (flag) {
233399ebb4caSwyllys 	case KMF_CERT_ISSUER:
233499ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
233599ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
233699ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
233799ebb4caSwyllys 		break;
233899ebb4caSwyllys 
233999ebb4caSwyllys 	case KMF_CERT_SUBJECT:
234099ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
234199ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
234299ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
234399ebb4caSwyllys 		break;
234499ebb4caSwyllys 
234599ebb4caSwyllys 	case KMF_CERT_VERSION:
234699ebb4caSwyllys 		tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version);
234799ebb4caSwyllys 		(void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN);
234899ebb4caSwyllys 		OPENSSL_free(tmpstr);
234999ebb4caSwyllys 		len = strlen(resultStr);
235099ebb4caSwyllys 		break;
235199ebb4caSwyllys 
235299ebb4caSwyllys 	case KMF_CERT_SERIALNUM:
235399ebb4caSwyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
235499ebb4caSwyllys 			(void) strcpy(resultStr, "0x");
235599ebb4caSwyllys 			len = BIO_gets(mem, &resultStr[2],
235699ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN - 2);
235799ebb4caSwyllys 		}
235899ebb4caSwyllys 		break;
235999ebb4caSwyllys 
236099ebb4caSwyllys 	case KMF_CERT_NOTBEFORE:
236199ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notBefore(xcert));
236299ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
236399ebb4caSwyllys 		break;
236499ebb4caSwyllys 
236599ebb4caSwyllys 	case KMF_CERT_NOTAFTER:
236699ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notAfter(xcert));
236799ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
236899ebb4caSwyllys 		break;
236999ebb4caSwyllys 
237099ebb4caSwyllys 	case KMF_CERT_PUBKEY_DATA:
237199ebb4caSwyllys 		{
237299ebb4caSwyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
237399ebb4caSwyllys 			if (pkey == NULL) {
237499ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
237599ebb4caSwyllys 				ret = KMF_ERR_ENCODING;
237699ebb4caSwyllys 				goto out;
237799ebb4caSwyllys 			}
237899ebb4caSwyllys 
237999ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
238099ebb4caSwyllys 				(void) BIO_printf(mem,
238199ebb4caSwyllys 				    "RSA Public Key: (%d bit)\n",
238299ebb4caSwyllys 				    BN_num_bits(pkey->pkey.rsa->n));
238399ebb4caSwyllys 				(void) RSA_print(mem, pkey->pkey.rsa, 0);
238499ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
238599ebb4caSwyllys 				(void) BIO_printf(mem,
238699ebb4caSwyllys 				    "%12sDSA Public Key:\n", "");
238799ebb4caSwyllys 				(void) DSA_print(mem, pkey->pkey.dsa, 0);
238899ebb4caSwyllys 			} else {
238999ebb4caSwyllys 				(void) BIO_printf(mem,
239099ebb4caSwyllys 				    "%12sUnknown Public Key:\n", "");
239199ebb4caSwyllys 			}
239299ebb4caSwyllys 			(void) BIO_printf(mem, "\n");
239399ebb4caSwyllys 			EVP_PKEY_free(pkey);
239499ebb4caSwyllys 		}
239599ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
239699ebb4caSwyllys 		break;
239799ebb4caSwyllys 	case KMF_CERT_SIGNATURE_ALG:
239899ebb4caSwyllys 	case KMF_CERT_PUBKEY_ALG:
239999ebb4caSwyllys 		if (flag == KMF_CERT_SIGNATURE_ALG) {
240099ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
240199ebb4caSwyllys 			    xcert->sig_alg->algorithm);
240299ebb4caSwyllys 		} else {
240399ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
240499ebb4caSwyllys 			    xcert->cert_info->key->algor->algorithm);
240599ebb4caSwyllys 		}
240699ebb4caSwyllys 
240799ebb4caSwyllys 		if (len > 0) {
240899ebb4caSwyllys 			len = BIO_read(mem, resultStr,
240999ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN);
241099ebb4caSwyllys 		}
241199ebb4caSwyllys 		break;
241299ebb4caSwyllys 
241399ebb4caSwyllys 	case KMF_CERT_EMAIL:
241499ebb4caSwyllys 		emlst = X509_get1_email(xcert);
241599ebb4caSwyllys 		for (j = 0; j < sk_num(emlst); j++)
241699ebb4caSwyllys 			(void) BIO_printf(mem, "%s\n", sk_value(emlst, j));
241799ebb4caSwyllys 
241899ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
241999ebb4caSwyllys 		X509_email_free(emlst);
242099ebb4caSwyllys 		break;
242199ebb4caSwyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
242299ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
242399ebb4caSwyllys 	case KMF_X509_EXT_KEY_USAGE:
242499ebb4caSwyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
242599ebb4caSwyllys 	case KMF_X509_EXT_CERT_POLICIES:
242699ebb4caSwyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
242799ebb4caSwyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
242899ebb4caSwyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
242999ebb4caSwyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
243099ebb4caSwyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
243199ebb4caSwyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
243299ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
243399ebb4caSwyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
243499ebb4caSwyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
243599ebb4caSwyllys 	case KMF_X509_EXT_FRESHEST_CRL:
243699ebb4caSwyllys 		nid = ext2NID(flag);
243799ebb4caSwyllys 		if (nid == NID_undef) {
243899ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
243999ebb4caSwyllys 			goto out;
244099ebb4caSwyllys 		}
244199ebb4caSwyllys 		ci = xcert->cert_info;
244299ebb4caSwyllys 
244399ebb4caSwyllys 		ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1);
244499ebb4caSwyllys 		if (ext_index == -1) {
244599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
244699ebb4caSwyllys 
244799ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
244899ebb4caSwyllys 			goto out;
244999ebb4caSwyllys 		}
245099ebb4caSwyllys 		ex = X509v3_get_ext(ci->extensions, ext_index);
245199ebb4caSwyllys 
245299ebb4caSwyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
245399ebb4caSwyllys 
245499ebb4caSwyllys 		if (BIO_printf(mem, ": %s\n",
245599ebb4caSwyllys 		    X509_EXTENSION_get_critical(ex) ? "critical" : "") <=
245699ebb4caSwyllys 		    0) {
245799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
245899ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
245999ebb4caSwyllys 			goto out;
246099ebb4caSwyllys 		}
246199ebb4caSwyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
246299ebb4caSwyllys 			(void) BIO_printf(mem, "%*s", 4, "");
246399ebb4caSwyllys 			(void) M_ASN1_OCTET_STRING_print(mem, ex->value);
246499ebb4caSwyllys 		}
246599ebb4caSwyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
246699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
246799ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
246899ebb4caSwyllys 			goto out;
246999ebb4caSwyllys 		}
247099ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
247199ebb4caSwyllys 	}
247299ebb4caSwyllys 	if (len <= 0) {
247399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
247499ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
247599ebb4caSwyllys 	}
247699ebb4caSwyllys 
247799ebb4caSwyllys out:
247899ebb4caSwyllys 	if (outbuf != NULL) {
247999ebb4caSwyllys 		free(outbuf);
248099ebb4caSwyllys 	}
248199ebb4caSwyllys 
248299ebb4caSwyllys 	if (xcert != NULL) {
248399ebb4caSwyllys 		X509_free(xcert);
248499ebb4caSwyllys 	}
248599ebb4caSwyllys 
248699ebb4caSwyllys 	if (mem != NULL) {
248799ebb4caSwyllys 		(void) BIO_free(mem);
248899ebb4caSwyllys 	}
248999ebb4caSwyllys 
249099ebb4caSwyllys 	return (ret);
249199ebb4caSwyllys }
249299ebb4caSwyllys KMF_RETURN
249399ebb4caSwyllys /*ARGSUSED*/
249499ebb4caSwyllys OpenSSL_GetPrikeyByCert(KMF_HANDLE_T handle,
249599ebb4caSwyllys 	KMF_CRYPTOWITHCERT_PARAMS *params,
249699ebb4caSwyllys 	KMF_DATA *SignerCertData, KMF_KEY_HANDLE *key,
249799ebb4caSwyllys 	KMF_KEY_ALG keytype)
249899ebb4caSwyllys {
249999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
250099ebb4caSwyllys 	KMF_FINDKEY_PARAMS fkparms;
250199ebb4caSwyllys 	uint32_t numkeys = 0;
250299ebb4caSwyllys 
250302744e81Swyllys 	if (params == NULL || params->sslparms.keyfile == NULL)
250499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
250599ebb4caSwyllys 
250699ebb4caSwyllys 	/*
250799ebb4caSwyllys 	 * This is really just a FindKey operation, reuse the
250899ebb4caSwyllys 	 * FindKey function.
250999ebb4caSwyllys 	 */
251099ebb4caSwyllys 	(void *)memset(&fkparms, 0, sizeof (fkparms));
251199ebb4caSwyllys 	fkparms.kstype = KMF_KEYSTORE_OPENSSL;
251299ebb4caSwyllys 	fkparms.keyclass = KMF_ASYM_PRI;
251399ebb4caSwyllys 	fkparms.keytype = keytype;
251499ebb4caSwyllys 	fkparms.format = params->format;
251599ebb4caSwyllys 	fkparms.sslparms = params->sslparms;
251699ebb4caSwyllys 
251799ebb4caSwyllys 	rv = OpenSSL_FindKey(handle, &fkparms, key, &numkeys);
251899ebb4caSwyllys 
251999ebb4caSwyllys 	return (rv);
252099ebb4caSwyllys }
252199ebb4caSwyllys 
252299ebb4caSwyllys KMF_RETURN
252399ebb4caSwyllys /*ARGSUSED*/
252499ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
252599ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
252699ebb4caSwyllys 	KMF_DATA *output)
252799ebb4caSwyllys {
252899ebb4caSwyllys 	KMF_RETURN		ret = KMF_OK;
252999ebb4caSwyllys 	RSA *rsa = NULL;
253099ebb4caSwyllys 	unsigned int in_len = 0, out_len = 0;
253199ebb4caSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
253299ebb4caSwyllys 	uint8_t *in_data, *out_data;
253399ebb4caSwyllys 	int i, blocks;
253499ebb4caSwyllys 
253599ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
253699ebb4caSwyllys 	    ciphertext == NULL || output == NULL ||
253799ebb4caSwyllys 	    ciphertext->Data == NULL ||
253899ebb4caSwyllys 	    output->Data == NULL)
253999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
254099ebb4caSwyllys 
254199ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
254299ebb4caSwyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
254399ebb4caSwyllys 		modulus_len = RSA_size(rsa);
254499ebb4caSwyllys 	} else {
254599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
254699ebb4caSwyllys 	}
254799ebb4caSwyllys 
254899ebb4caSwyllys 	blocks = ciphertext->Length/modulus_len;
254999ebb4caSwyllys 	out_data = output->Data;
255099ebb4caSwyllys 	in_data = ciphertext->Data;
255199ebb4caSwyllys 	out_len = modulus_len - 11;
255299ebb4caSwyllys 	in_len = modulus_len;
255399ebb4caSwyllys 
255499ebb4caSwyllys 	for (i = 0; i < blocks; i++) {
255599ebb4caSwyllys 		out_len  = RSA_private_decrypt(in_len,
255699ebb4caSwyllys 		    in_data, out_data, rsa, RSA_PKCS1_PADDING);
255799ebb4caSwyllys 
255899ebb4caSwyllys 		if (out_len == 0) {
255999ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
256099ebb4caSwyllys 			goto cleanup;
256199ebb4caSwyllys 		}
256299ebb4caSwyllys 
256399ebb4caSwyllys 		out_data += out_len;
256499ebb4caSwyllys 		total_decrypted += out_len;
256599ebb4caSwyllys 		in_data += in_len;
256699ebb4caSwyllys 	}
256799ebb4caSwyllys 
256899ebb4caSwyllys 	output->Length = total_decrypted;
256999ebb4caSwyllys 
257099ebb4caSwyllys cleanup:
257199ebb4caSwyllys 	RSA_free(rsa);
257299ebb4caSwyllys 	if (ret != KMF_OK)
257399ebb4caSwyllys 		output->Length = 0;
257499ebb4caSwyllys 
257599ebb4caSwyllys 	return (ret);
257699ebb4caSwyllys 
257799ebb4caSwyllys }
257899ebb4caSwyllys 
257999ebb4caSwyllys /*
258099ebb4caSwyllys  *  This function will create a certid from issuer_cert and user_cert.
258199ebb4caSwyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
258299ebb4caSwyllys  *  certid memory after use.
258399ebb4caSwyllys  */
258499ebb4caSwyllys static KMF_RETURN
258599ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
258699ebb4caSwyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
258799ebb4caSwyllys {
258899ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
258999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
259099ebb4caSwyllys 	X509   *issuer = NULL;
259199ebb4caSwyllys 	X509   *cert = NULL;
259299ebb4caSwyllys 	unsigned char *ptmp;
259399ebb4caSwyllys 
259499ebb4caSwyllys 	if (issuer_cert == NULL || user_cert == NULL) {
259599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
259699ebb4caSwyllys 	}
259799ebb4caSwyllys 
259899ebb4caSwyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
259999ebb4caSwyllys 	ptmp = issuer_cert->Data;
260099ebb4caSwyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
260199ebb4caSwyllys 	    issuer_cert->Length);
260299ebb4caSwyllys 	if (issuer == NULL) {
260399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
260499ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
260599ebb4caSwyllys 		goto end;
260699ebb4caSwyllys 	}
260799ebb4caSwyllys 
260899ebb4caSwyllys 	/* convert the DER-encoded user cert to an internal X509 */
260999ebb4caSwyllys 	ptmp = user_cert->Data;
261099ebb4caSwyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
261199ebb4caSwyllys 	    user_cert->Length);
261299ebb4caSwyllys 	if (cert == NULL) {
261399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
261499ebb4caSwyllys 
261599ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
261699ebb4caSwyllys 		goto end;
261799ebb4caSwyllys 	}
261899ebb4caSwyllys 
261999ebb4caSwyllys 	/* create a CERTID */
262099ebb4caSwyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
262199ebb4caSwyllys 	if (*certid == NULL) {
262299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
262399ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
262499ebb4caSwyllys 		goto end;
262599ebb4caSwyllys 	}
262699ebb4caSwyllys 
262799ebb4caSwyllys end:
262899ebb4caSwyllys 	if (issuer != NULL) {
262999ebb4caSwyllys 		X509_free(issuer);
263099ebb4caSwyllys 	}
263199ebb4caSwyllys 
263299ebb4caSwyllys 	if (cert != NULL) {
263399ebb4caSwyllys 		X509_free(cert);
263499ebb4caSwyllys 	}
263599ebb4caSwyllys 
263699ebb4caSwyllys 	return (ret);
263799ebb4caSwyllys }
263899ebb4caSwyllys 
263999ebb4caSwyllys KMF_RETURN
264099ebb4caSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle, KMF_OCSPREQUEST_PARAMS *params,
264199ebb4caSwyllys     char *reqfile)
264299ebb4caSwyllys {
264399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
264499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
264599ebb4caSwyllys 	OCSP_CERTID *id = NULL;
264699ebb4caSwyllys 	OCSP_REQUEST *req = NULL;
264799ebb4caSwyllys 	BIO *derbio = NULL;
264899ebb4caSwyllys 
264999ebb4caSwyllys 	if (params->user_cert == NULL || params->issuer_cert == NULL ||
265099ebb4caSwyllys 	    reqfile == NULL) {
265199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
265299ebb4caSwyllys 	}
265399ebb4caSwyllys 
265499ebb4caSwyllys 	ret = create_certid(handle, params->issuer_cert, params->user_cert,
265599ebb4caSwyllys 	    &id);
265699ebb4caSwyllys 	if (ret != KMF_OK) {
265799ebb4caSwyllys 		return (ret);
265899ebb4caSwyllys 	}
265999ebb4caSwyllys 
266099ebb4caSwyllys 	/* Create an OCSP request */
266199ebb4caSwyllys 	req = OCSP_REQUEST_new();
266299ebb4caSwyllys 	if (req == NULL) {
266399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
266499ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
266599ebb4caSwyllys 		goto end;
266699ebb4caSwyllys 	}
266799ebb4caSwyllys 
266899ebb4caSwyllys 	if (!OCSP_request_add0_id(req, id)) {
266999ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
267099ebb4caSwyllys 		goto end;
267199ebb4caSwyllys 	}
267299ebb4caSwyllys 
267399ebb4caSwyllys 	/* Write the request to the output file with DER encoding */
267499ebb4caSwyllys 	derbio = BIO_new_file(reqfile, "wb");
267599ebb4caSwyllys 	if (!derbio) {
267699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
267799ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
267899ebb4caSwyllys 		goto end;
267999ebb4caSwyllys 	}
268099ebb4caSwyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
268199ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
268299ebb4caSwyllys 	}
268399ebb4caSwyllys 
268499ebb4caSwyllys end:
268599ebb4caSwyllys 	/*
268699ebb4caSwyllys 	 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
268799ebb4caSwyllys 	 * will deallocate certid's space also.
268899ebb4caSwyllys 	 */
268999ebb4caSwyllys 	if (req != NULL) {
269099ebb4caSwyllys 		OCSP_REQUEST_free(req);
269199ebb4caSwyllys 	}
269299ebb4caSwyllys 
269399ebb4caSwyllys 	if (derbio != NULL) {
269499ebb4caSwyllys 		(void) BIO_free(derbio);
269599ebb4caSwyllys 	}
269699ebb4caSwyllys 
269799ebb4caSwyllys 	return (ret);
269899ebb4caSwyllys }
269999ebb4caSwyllys 
270099ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */
270199ebb4caSwyllys static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
270299ebb4caSwyllys {
270399ebb4caSwyllys 	int i;
270499ebb4caSwyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
270599ebb4caSwyllys 
270699ebb4caSwyllys 	/* Easy if lookup by name */
270799ebb4caSwyllys 	if (id->type == V_OCSP_RESPID_NAME)
270899ebb4caSwyllys 		return (X509_find_by_subject(certs, id->value.byName));
270999ebb4caSwyllys 
271099ebb4caSwyllys 	/* Lookup by key hash */
271199ebb4caSwyllys 
271299ebb4caSwyllys 	/* If key hash isn't SHA1 length then forget it */
271399ebb4caSwyllys 	if (id->value.byKey->length != SHA_DIGEST_LENGTH)
271499ebb4caSwyllys 		return (NULL);
271599ebb4caSwyllys 
271699ebb4caSwyllys 	keyhash = id->value.byKey->data;
271799ebb4caSwyllys 	/* Calculate hash of each key and compare */
271899ebb4caSwyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
271999ebb4caSwyllys 		/*LINTED*/
272099ebb4caSwyllys 		X509 *x = sk_X509_value(certs, i);
272199ebb4caSwyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
272299ebb4caSwyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
272399ebb4caSwyllys 			return (x);
272499ebb4caSwyllys 	}
272599ebb4caSwyllys 	return (NULL);
272699ebb4caSwyllys }
272799ebb4caSwyllys 
272899ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */
272999ebb4caSwyllys /*ARGSUSED*/
273099ebb4caSwyllys static int
273199ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
273299ebb4caSwyllys     X509_STORE *st, unsigned long flags)
273399ebb4caSwyllys {
273499ebb4caSwyllys 	X509 *signer;
273599ebb4caSwyllys 	OCSP_RESPID *rid = bs->tbsResponseData->responderId;
273699ebb4caSwyllys 	if ((signer = ocsp_find_signer_sk(certs, rid)))	{
273799ebb4caSwyllys 		*psigner = signer;
273899ebb4caSwyllys 		return (2);
273999ebb4caSwyllys 	}
274099ebb4caSwyllys 	if (!(flags & OCSP_NOINTERN) &&
274199ebb4caSwyllys 	    (signer = ocsp_find_signer_sk(bs->certs, rid))) {
274299ebb4caSwyllys 		*psigner = signer;
274399ebb4caSwyllys 		return (1);
274499ebb4caSwyllys 	}
274599ebb4caSwyllys 	/* Maybe lookup from store if by subject name */
274699ebb4caSwyllys 
274799ebb4caSwyllys 	*psigner = NULL;
274899ebb4caSwyllys 	return (0);
274999ebb4caSwyllys }
275099ebb4caSwyllys 
275199ebb4caSwyllys /*
275299ebb4caSwyllys  * This function will verify the signature of a basic response, using
275399ebb4caSwyllys  * the public key from the OCSP responder certificate.
275499ebb4caSwyllys  */
275599ebb4caSwyllys static KMF_RETURN
275699ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
275799ebb4caSwyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
275899ebb4caSwyllys {
275999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
276099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
276199ebb4caSwyllys 	STACK_OF(X509) *cert_stack = NULL;
276299ebb4caSwyllys 	X509 *signer = NULL;
276399ebb4caSwyllys 	X509 *issuer = NULL;
276499ebb4caSwyllys 	EVP_PKEY *skey = NULL;
276599ebb4caSwyllys 	unsigned char *ptmp;
276699ebb4caSwyllys 
276799ebb4caSwyllys 
276899ebb4caSwyllys 	if (bs == NULL || issuer_cert == NULL)
276999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
277099ebb4caSwyllys 
277199ebb4caSwyllys 	/*
277299ebb4caSwyllys 	 * Find the certificate that signed the basic response.
277399ebb4caSwyllys 	 *
277499ebb4caSwyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
277599ebb4caSwyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
277699ebb4caSwyllys 	 * If we still do not find a signer, we will look for it from the
277799ebb4caSwyllys 	 * certificate list came with the response file.
277899ebb4caSwyllys 	 */
277999ebb4caSwyllys 	if (signer_cert != NULL) {
278099ebb4caSwyllys 		ptmp = signer_cert->Data;
278199ebb4caSwyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
278299ebb4caSwyllys 		    signer_cert->Length);
278399ebb4caSwyllys 		if (signer == NULL) {
278499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
278599ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
278699ebb4caSwyllys 			goto end;
278799ebb4caSwyllys 		}
278899ebb4caSwyllys 	} else {
278999ebb4caSwyllys 		/*
279099ebb4caSwyllys 		 * Convert the issuer cert into X509 and push it into a
279199ebb4caSwyllys 		 * stack to be used by ocsp_find_signer().
279299ebb4caSwyllys 		 */
279399ebb4caSwyllys 		ptmp = issuer_cert->Data;
279499ebb4caSwyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
279599ebb4caSwyllys 		    issuer_cert->Length);
279699ebb4caSwyllys 		if (issuer == NULL) {
279799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
279899ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
279999ebb4caSwyllys 			goto end;
280099ebb4caSwyllys 		}
280199ebb4caSwyllys 
280299ebb4caSwyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
280399ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
280499ebb4caSwyllys 			goto end;
280599ebb4caSwyllys 		}
280699ebb4caSwyllys 
280799ebb4caSwyllys 		if (sk_X509_push(cert_stack, issuer) == NULL) {
280899ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
280999ebb4caSwyllys 			goto end;
281099ebb4caSwyllys 		}
281199ebb4caSwyllys 
281299ebb4caSwyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
281399ebb4caSwyllys 		if (!ret) {
281499ebb4caSwyllys 			/* can not find the signer */
281599ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
281699ebb4caSwyllys 			goto end;
281799ebb4caSwyllys 		}
281899ebb4caSwyllys 	}
281999ebb4caSwyllys 
282099ebb4caSwyllys 	/* Verify the signature of the response */
282199ebb4caSwyllys 	skey = X509_get_pubkey(signer);
282299ebb4caSwyllys 	if (skey == NULL) {
282399ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
282499ebb4caSwyllys 		goto end;
282599ebb4caSwyllys 	}
282699ebb4caSwyllys 
282799ebb4caSwyllys 	ret = OCSP_BASICRESP_verify(bs, skey, 0);
282899ebb4caSwyllys 	if (ret == 0) {
282999ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
283099ebb4caSwyllys 		goto end;
283199ebb4caSwyllys 	}
283299ebb4caSwyllys 
283399ebb4caSwyllys end:
283499ebb4caSwyllys 	if (issuer != NULL) {
283599ebb4caSwyllys 		X509_free(issuer);
283699ebb4caSwyllys 	}
283799ebb4caSwyllys 
283899ebb4caSwyllys 	if (signer != NULL) {
283999ebb4caSwyllys 		X509_free(signer);
284099ebb4caSwyllys 	}
284199ebb4caSwyllys 
284299ebb4caSwyllys 	if (skey != NULL) {
284399ebb4caSwyllys 		EVP_PKEY_free(skey);
284499ebb4caSwyllys 	}
284599ebb4caSwyllys 
284699ebb4caSwyllys 	if (cert_stack != NULL) {
284799ebb4caSwyllys 		sk_X509_free(cert_stack);
284899ebb4caSwyllys 	}
284999ebb4caSwyllys 
285099ebb4caSwyllys 	return (ret);
285199ebb4caSwyllys }
285299ebb4caSwyllys 
285399ebb4caSwyllys 
285499ebb4caSwyllys 
285599ebb4caSwyllys KMF_RETURN
285699ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
285799ebb4caSwyllys     KMF_OCSPRESPONSE_PARAMS_INPUT *params_in,
285899ebb4caSwyllys     KMF_OCSPRESPONSE_PARAMS_OUTPUT *params_out)
285999ebb4caSwyllys {
286099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
286199ebb4caSwyllys 	BIO *derbio = NULL;
286299ebb4caSwyllys 	OCSP_RESPONSE *resp = NULL;
286399ebb4caSwyllys 	OCSP_BASICRESP *bs = NULL;
286499ebb4caSwyllys 	OCSP_CERTID *id = NULL;
286599ebb4caSwyllys 	OCSP_SINGLERESP *single = NULL;
286699ebb4caSwyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
286799ebb4caSwyllys 	int index, status, reason;
286899ebb4caSwyllys 
286999ebb4caSwyllys 	if (params_in == NULL || params_in->issuer_cert == NULL ||
287099ebb4caSwyllys 	    params_in->user_cert == NULL || params_in->response == NULL) {
287199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
287299ebb4caSwyllys 	}
287399ebb4caSwyllys 
287499ebb4caSwyllys 	if (params_out == NULL) {
287599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
287699ebb4caSwyllys 	}
287799ebb4caSwyllys 
287899ebb4caSwyllys 	/* Read in the response */
287999ebb4caSwyllys 	derbio = BIO_new_mem_buf(params_in->response->Data,
288099ebb4caSwyllys 	    params_in->response->Length);
288199ebb4caSwyllys 	if (!derbio) {
288299ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
288399ebb4caSwyllys 		return (ret);
288499ebb4caSwyllys 	}
288599ebb4caSwyllys 
288699ebb4caSwyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
288799ebb4caSwyllys 	if (resp == NULL) {
288899ebb4caSwyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
288999ebb4caSwyllys 		goto end;
289099ebb4caSwyllys 	}
289199ebb4caSwyllys 
289299ebb4caSwyllys 	/* Check the response status */
289399ebb4caSwyllys 	status = OCSP_response_status(resp);
289499ebb4caSwyllys 	params_out->response_status = status;
289599ebb4caSwyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
289699ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
289799ebb4caSwyllys 		goto end;
289899ebb4caSwyllys 	}
289999ebb4caSwyllys 
290099ebb4caSwyllys #ifdef DEBUG
290199ebb4caSwyllys 	printf("Successfully checked the response file status.\n");
290299ebb4caSwyllys #endif /* DEBUG */
290399ebb4caSwyllys 
290499ebb4caSwyllys 	/* Extract basic response */
290599ebb4caSwyllys 	bs = OCSP_response_get1_basic(resp);
290699ebb4caSwyllys 	if (bs == NULL) {
290799ebb4caSwyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
290899ebb4caSwyllys 		goto end;
290999ebb4caSwyllys 	}
291099ebb4caSwyllys 
291199ebb4caSwyllys #ifdef DEBUG
291299ebb4caSwyllys 	printf("Successfully retrieved the basic response.\n");
291399ebb4caSwyllys #endif /* DEBUG */
291499ebb4caSwyllys 
291599ebb4caSwyllys 	/* Check the basic response signature if required */
291699ebb4caSwyllys 	if (params_in->ignore_response_sign == B_FALSE) {
291799ebb4caSwyllys 		ret = check_response_signature(handle, bs,
291899ebb4caSwyllys 		    params_in->signer_cert, params_in->issuer_cert);
291999ebb4caSwyllys 		if (ret != KMF_OK)
292099ebb4caSwyllys 			goto end;
292199ebb4caSwyllys 	}
292299ebb4caSwyllys 
292399ebb4caSwyllys #ifdef DEBUG
292499ebb4caSwyllys 	printf("Successfully verified the response signature.\n");
292599ebb4caSwyllys #endif /* DEBUG */
292699ebb4caSwyllys 
292799ebb4caSwyllys 	/* Create a certid for the certificate in question */
292899ebb4caSwyllys 	ret = create_certid(handle, params_in->issuer_cert,
292999ebb4caSwyllys 	    params_in->user_cert, &id);
293099ebb4caSwyllys 	if (ret != KMF_OK) {
293199ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
293299ebb4caSwyllys 		goto end;
293399ebb4caSwyllys 	}
293499ebb4caSwyllys 
293599ebb4caSwyllys #ifdef DEBUG
293699ebb4caSwyllys 	printf("successfully created a certid for the cert.\n");
293799ebb4caSwyllys #endif /* DEBUG */
293899ebb4caSwyllys 
293999ebb4caSwyllys 	/* Find the index of the single response for the certid */
294099ebb4caSwyllys 	index = OCSP_resp_find(bs, id, -1);
294199ebb4caSwyllys 	if (index < 0) {
294299ebb4caSwyllys 		/* cound not find this certificate in the response */
294399ebb4caSwyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
294499ebb4caSwyllys 		goto end;
294599ebb4caSwyllys 	}
294699ebb4caSwyllys 
294799ebb4caSwyllys #ifdef DEBUG
294899ebb4caSwyllys 	printf("Successfully found the single response index for the cert.\n");
294999ebb4caSwyllys #endif /* DEBUG */
295099ebb4caSwyllys 
295199ebb4caSwyllys 	/* Retrieve the single response and get the cert status */
295299ebb4caSwyllys 	single = OCSP_resp_get0(bs, index);
295399ebb4caSwyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
295499ebb4caSwyllys 	    &nextupd);
295599ebb4caSwyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
295699ebb4caSwyllys 		params_out->cert_status = OCSP_GOOD;
295799ebb4caSwyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
295899ebb4caSwyllys 		params_out->cert_status = OCSP_UNKNOWN;
295999ebb4caSwyllys 	} else { /* revoked */
296099ebb4caSwyllys 		params_out->cert_status = OCSP_REVOKED;
296199ebb4caSwyllys 		params_out->reason = reason;
296299ebb4caSwyllys 	}
296399ebb4caSwyllys 	ret = KMF_OK;
296499ebb4caSwyllys 
296599ebb4caSwyllys 	/* Verify the time */
296699ebb4caSwyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
296799ebb4caSwyllys 	    params_in->response_lifetime)) {
296899ebb4caSwyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
296999ebb4caSwyllys 		goto end;
297099ebb4caSwyllys 	}
297199ebb4caSwyllys 
297299ebb4caSwyllys #ifdef DEBUG
297399ebb4caSwyllys 	printf("Successfully verify the time.\n");
297499ebb4caSwyllys #endif /* DEBUG */
297599ebb4caSwyllys 
297699ebb4caSwyllys end:
297799ebb4caSwyllys 	if (derbio != NULL)
297899ebb4caSwyllys 		(void) BIO_free(derbio);
297999ebb4caSwyllys 
298099ebb4caSwyllys 	if (resp != NULL)
298199ebb4caSwyllys 		OCSP_RESPONSE_free(resp);
298299ebb4caSwyllys 
298399ebb4caSwyllys 	if (bs != NULL)
298499ebb4caSwyllys 		OCSP_BASICRESP_free(bs);
298599ebb4caSwyllys 
298699ebb4caSwyllys 	if (id != NULL)
298799ebb4caSwyllys 		OCSP_CERTID_free(id);
298899ebb4caSwyllys 
298999ebb4caSwyllys 	return (ret);
299099ebb4caSwyllys }
299199ebb4caSwyllys 
299299ebb4caSwyllys static KMF_RETURN
299399ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path,
299499ebb4caSwyllys 	KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
299599ebb4caSwyllys {
299699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
299799ebb4caSwyllys 	EVP_PKEY *pkey;
299899ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
299999ebb4caSwyllys 
300099ebb4caSwyllys 	/* Make sure the requested file actually exists. */
300199ebb4caSwyllys 	if (access(path, F_OK) != 0) {
300299ebb4caSwyllys 		return (KMF_ERR_KEY_NOT_FOUND);
300399ebb4caSwyllys 	}
300499ebb4caSwyllys 
300599ebb4caSwyllys 	if (keyclass == KMF_ASYM_PRI ||
300699ebb4caSwyllys 	    keyclass == KMF_ASYM_PUB) {
300799ebb4caSwyllys 		pkey = openssl_load_key(handle, path);
300899ebb4caSwyllys 		if (pkey == NULL) {
300999ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
301099ebb4caSwyllys 		}
301199ebb4caSwyllys 		if (key != NULL) {
301299ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA)
301399ebb4caSwyllys 				key->keyalg = KMF_RSA;
301499ebb4caSwyllys 			else if (pkey->type == EVP_PKEY_DSA)
301599ebb4caSwyllys 				key->keyalg = KMF_DSA;
301699ebb4caSwyllys 
301799ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
301899ebb4caSwyllys 			key->keyclass = keyclass;
301999ebb4caSwyllys 			key->keyp = (void *)pkey;
302099ebb4caSwyllys 			key->israw = FALSE;
302199ebb4caSwyllys 			key->keylabel = path;
302299ebb4caSwyllys 		} else {
302399ebb4caSwyllys 			EVP_PKEY_free(pkey);
302499ebb4caSwyllys 			pkey = NULL;
302599ebb4caSwyllys 		}
302699ebb4caSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
302799ebb4caSwyllys 		KMF_ENCODE_FORMAT fmt;
302899ebb4caSwyllys 		/*
302999ebb4caSwyllys 		 * If the file is a recognized format,
303099ebb4caSwyllys 		 * then it is NOT a symmetric key.
303199ebb4caSwyllys 		 */
303299ebb4caSwyllys 		rv = KMF_GetFileFormat(path, &fmt);
303399ebb4caSwyllys 		if (rv == KMF_OK || fmt != 0) {
303499ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
303599ebb4caSwyllys 		} else if (rv == KMF_ERR_ENCODING) {
303699ebb4caSwyllys 			/*
303799ebb4caSwyllys 			 * If we don't know the encoding,
303899ebb4caSwyllys 			 * it is probably  a symmetric key.
303999ebb4caSwyllys 			 */
304099ebb4caSwyllys 			rv = KMF_OK;
304199ebb4caSwyllys 		}
304299ebb4caSwyllys 
304399ebb4caSwyllys 		if (key != NULL) {
304499ebb4caSwyllys 			KMF_DATA keyvalue;
304599ebb4caSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
304699ebb4caSwyllys 			if (rkey == NULL) {
304799ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
304899ebb4caSwyllys 				goto out;
304999ebb4caSwyllys 			}
305099ebb4caSwyllys 
305199ebb4caSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
305299ebb4caSwyllys 			rv = KMF_ReadInputFile(handle, path, &keyvalue);
305399ebb4caSwyllys 			if (rv != KMF_OK)
305499ebb4caSwyllys 				goto out;
305599ebb4caSwyllys 
305699ebb4caSwyllys 			rkey->keydata.len = keyvalue.Length;
305799ebb4caSwyllys 			rkey->keydata.val = keyvalue.Data;
305899ebb4caSwyllys 
305999ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
306099ebb4caSwyllys 			key->keyclass = keyclass;
306199ebb4caSwyllys 			key->israw = TRUE;
306299ebb4caSwyllys 			key->keylabel = path;
306399ebb4caSwyllys 			key->keyp = (void *)rkey;
306499ebb4caSwyllys 		}
306599ebb4caSwyllys 	}
306699ebb4caSwyllys out:
306799ebb4caSwyllys 	if (rv != KMF_OK) {
306899ebb4caSwyllys 		if (rkey != NULL) {
306999ebb4caSwyllys 			KMF_FreeRawSymKey(rkey);
307099ebb4caSwyllys 		}
307199ebb4caSwyllys 		if (pkey != NULL)
307299ebb4caSwyllys 			EVP_PKEY_free(pkey);
307399ebb4caSwyllys 
307499ebb4caSwyllys 		if (key != NULL) {
307599ebb4caSwyllys 			key->keyalg = KMF_KEYALG_NONE;
307699ebb4caSwyllys 			key->keyclass = KMF_KEYCLASS_NONE;
307799ebb4caSwyllys 			key->keyp = NULL;
307899ebb4caSwyllys 		}
307999ebb4caSwyllys 	}
308099ebb4caSwyllys 
308199ebb4caSwyllys 	return (rv);
308299ebb4caSwyllys }
308399ebb4caSwyllys 
308499ebb4caSwyllys KMF_RETURN
308599ebb4caSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle, KMF_FINDKEY_PARAMS *params,
308699ebb4caSwyllys 	KMF_KEY_HANDLE *key, uint32_t *numkeys)
308799ebb4caSwyllys {
308899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
308999ebb4caSwyllys 	char *fullpath = NULL;
3090f482c776Swyllys 	uint32_t maxkeys;
309199ebb4caSwyllys 
309299ebb4caSwyllys 	if (handle == NULL || params == NULL || numkeys == NULL)
309399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
309499ebb4caSwyllys 
309599ebb4caSwyllys 	if (params->keyclass != KMF_ASYM_PUB &&
309699ebb4caSwyllys 	    params->keyclass != KMF_ASYM_PRI &&
309799ebb4caSwyllys 	    params->keyclass != KMF_SYMMETRIC)
309899ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
309999ebb4caSwyllys 
310099ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
310199ebb4caSwyllys 	    params->sslparms.keyfile);
310299ebb4caSwyllys 
310399ebb4caSwyllys 	if (fullpath == NULL)
310499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
310599ebb4caSwyllys 
3106f482c776Swyllys 	maxkeys = *numkeys;
3107f482c776Swyllys 	if (maxkeys == 0)
3108f482c776Swyllys 		maxkeys = 0xFFFFFFFF;
3109f482c776Swyllys 
311099ebb4caSwyllys 	*numkeys = 0;
311199ebb4caSwyllys 
311299ebb4caSwyllys 	if (isdir(fullpath)) {
311399ebb4caSwyllys 		DIR *dirp;
311499ebb4caSwyllys 		struct dirent *dp;
311599ebb4caSwyllys 		int n = 0;
311699ebb4caSwyllys 
311799ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
311899ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
311999ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
312099ebb4caSwyllys 		}
312199ebb4caSwyllys 		rewinddir(dirp);
3122f482c776Swyllys 		while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
312399ebb4caSwyllys 			if (strcmp(dp->d_name, ".") &&
312499ebb4caSwyllys 			    strcmp(dp->d_name, "..")) {
312599ebb4caSwyllys 				char *fname;
312699ebb4caSwyllys 
312799ebb4caSwyllys 				fname = get_fullpath(fullpath,
312899ebb4caSwyllys 				    (char *)&dp->d_name);
312999ebb4caSwyllys 
313099ebb4caSwyllys 				rv = fetch_key(handle, fname,
313199ebb4caSwyllys 				    params->keyclass,
313299ebb4caSwyllys 				    key ? &key[n] : NULL);
313399ebb4caSwyllys 
313499ebb4caSwyllys 				if (rv == KMF_OK)
313599ebb4caSwyllys 					n++;
313699ebb4caSwyllys 
313799ebb4caSwyllys 				if (rv != KMF_OK || key == NULL)
313899ebb4caSwyllys 					free(fname);
313999ebb4caSwyllys 			}
314099ebb4caSwyllys 		}
314199ebb4caSwyllys 		(void) closedir(dirp);
314299ebb4caSwyllys 		free(fullpath);
314399ebb4caSwyllys 		(*numkeys) = n;
314499ebb4caSwyllys 	} else {
314599ebb4caSwyllys 		rv = fetch_key(handle, fullpath, params->keyclass, key);
314699ebb4caSwyllys 		if (rv == KMF_OK)
314799ebb4caSwyllys 			(*numkeys) = 1;
314899ebb4caSwyllys 
314999ebb4caSwyllys 		if (rv != KMF_OK || key == NULL)
315099ebb4caSwyllys 			free(fullpath);
315199ebb4caSwyllys 	}
315299ebb4caSwyllys 
3153f482c776Swyllys 	if (rv == KMF_OK && (*numkeys) == 0)
315499ebb4caSwyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
315599ebb4caSwyllys 
315699ebb4caSwyllys 	return (rv);
315799ebb4caSwyllys }
315899ebb4caSwyllys 
315999ebb4caSwyllys #define	HANDLE_PK12_ERROR { \
316099ebb4caSwyllys 	SET_ERROR(kmfh, ERR_get_error()); \
316199ebb4caSwyllys 	rv = KMF_ERR_ENCODING; \
316299ebb4caSwyllys 	goto out; \
316399ebb4caSwyllys }
316499ebb4caSwyllys 
316599ebb4caSwyllys static KMF_RETURN
316699ebb4caSwyllys write_pkcs12(KMF_HANDLE *kmfh,
316799ebb4caSwyllys 	BIO *bio,
316899ebb4caSwyllys 	KMF_CREDENTIAL *cred,
316999ebb4caSwyllys 	EVP_PKEY *pkey,
317099ebb4caSwyllys 	X509 *sslcert)
317199ebb4caSwyllys {
317299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
317399ebb4caSwyllys 	STACK_OF(PKCS12_SAFEBAG)	*bag_stack = NULL;
317499ebb4caSwyllys 	PKCS12_SAFEBAG			*bag = NULL;
317599ebb4caSwyllys 	PKCS7				*cert_authsafe = NULL;
317699ebb4caSwyllys 	PKCS8_PRIV_KEY_INFO		*p8 = NULL;
317799ebb4caSwyllys 	PKCS7				*key_authsafe = NULL;
317899ebb4caSwyllys 	STACK_OF(PKCS7)			*authsafe_stack = NULL;
317999ebb4caSwyllys 	PKCS12				*p12_elem = NULL;
318099ebb4caSwyllys 	char				*lab = NULL;
318199ebb4caSwyllys 	int				lab_len = 0;
318299ebb4caSwyllys 	unsigned char keyid[EVP_MAX_MD_SIZE];
318399ebb4caSwyllys 	unsigned int keyidlen = 0;
318499ebb4caSwyllys 
318599ebb4caSwyllys 	/* Must have at least a cert OR a key */
318699ebb4caSwyllys 	if (sslcert == NULL && pkey == NULL)
318799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
318899ebb4caSwyllys 
318999ebb4caSwyllys 	(void) memset(keyid, 0, sizeof (keyid));
319099ebb4caSwyllys 	/*
319199ebb4caSwyllys 	 * Section 1:
319299ebb4caSwyllys 	 *
319399ebb4caSwyllys 	 * The first PKCS#12 container (safebag) will hold the certificates
319499ebb4caSwyllys 	 * associated with this key.  The result of this section is a
319599ebb4caSwyllys 	 * PIN-encrypted PKCS#7 container (authsafe).  If there are no
319699ebb4caSwyllys 	 * certificates, there is no point in creating the "safebag" or the
319799ebb4caSwyllys 	 * "authsafe" so we go to the next section.
319899ebb4caSwyllys 	 */
319999ebb4caSwyllys 	if (sslcert != NULL && pkey != NULL) {
320099ebb4caSwyllys 		if (X509_check_private_key(sslcert, pkey)) {
320199ebb4caSwyllys 			(void) X509_digest(sslcert, EVP_sha1(), keyid,
320299ebb4caSwyllys 			    &keyidlen);
320399ebb4caSwyllys 		} else {
320499ebb4caSwyllys 			/* The key doesn't match the cert */
320599ebb4caSwyllys 			HANDLE_PK12_ERROR
320699ebb4caSwyllys 		}
320799ebb4caSwyllys 	}
320899ebb4caSwyllys 
320999ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
321099ebb4caSwyllys 	if (bag_stack == NULL)
321199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
321299ebb4caSwyllys 
321399ebb4caSwyllys 	if (sslcert != NULL) {
321499ebb4caSwyllys 		/* Convert cert from X509 struct to PKCS#12 bag */
321599ebb4caSwyllys 		bag = PKCS12_x5092certbag(sslcert);
321699ebb4caSwyllys 		if (bag == NULL) {
321799ebb4caSwyllys 			HANDLE_PK12_ERROR
321899ebb4caSwyllys 		}
321999ebb4caSwyllys 
322099ebb4caSwyllys 		/* Add the key id to the certificate bag. */
322199ebb4caSwyllys 		if (keyidlen > 0 &&
322299ebb4caSwyllys 		    !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
322399ebb4caSwyllys 			HANDLE_PK12_ERROR
322499ebb4caSwyllys 		}
322599ebb4caSwyllys 
322699ebb4caSwyllys 		/* Pile it on the bag_stack. */
322799ebb4caSwyllys 		if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
322899ebb4caSwyllys 			HANDLE_PK12_ERROR
322999ebb4caSwyllys 		}
323099ebb4caSwyllys #if 0
323199ebb4caSwyllys 		/* No support for CA certs yet */
323299ebb4caSwyllys 		if (cacerts != NULL && ncacerts > 0) {
323399ebb4caSwyllys 			int i;
323499ebb4caSwyllys 			for (i = 0; i < ncacerts; i++) {
323599ebb4caSwyllys 				KMF_X509_DER_CERT *c = &cacerts[i];
323699ebb4caSwyllys 				X509 *ca = NULL;
323799ebb4caSwyllys 
323899ebb4caSwyllys 				uchar_t *p = (uchar_t *)c->certificate.Data;
323999ebb4caSwyllys 				ca = d2i_X509(NULL, &p,
324099ebb4caSwyllys 				    c->certificate.Length);
324199ebb4caSwyllys 				if (ca == NULL) {
324299ebb4caSwyllys 					HANDLE_PK12_ERROR
324399ebb4caSwyllys 				}
324499ebb4caSwyllys 				/* Convert CA cert to PKCS#12 bag. */
324599ebb4caSwyllys 				bag = PKCS12_x5092certbag(ca);
324699ebb4caSwyllys 				if (bag == NULL) {
324799ebb4caSwyllys 					sk_PKCS12_SAFEBAG_pop_free(bag_stack,
324899ebb4caSwyllys 					    PKCS12_SAFEBAG_free);
324999ebb4caSwyllys 					HANDLE_PK12_ERROR
325099ebb4caSwyllys 				}
325199ebb4caSwyllys 				/* Pile it onto the bag_stack. */
325299ebb4caSwyllys 				if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
325399ebb4caSwyllys 					HANDLE_PK12_ERROR
325499ebb4caSwyllys 				}
325599ebb4caSwyllys 			}
325699ebb4caSwyllys 		}
325799ebb4caSwyllys #endif
325899ebb4caSwyllys 		/* Turn bag_stack of certs into encrypted authsafe. */
325999ebb4caSwyllys 		cert_authsafe = PKCS12_pack_p7encdata(
326099ebb4caSwyllys 		    NID_pbe_WithSHA1And40BitRC2_CBC,
3261*34acef67Swyllys 		    cred->cred, cred->credlen, NULL, 0,
3262*34acef67Swyllys 		    PKCS12_DEFAULT_ITER, bag_stack);
326399ebb4caSwyllys 
326499ebb4caSwyllys 		/* Clear away this bag_stack, we're done with it. */
326599ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
326699ebb4caSwyllys 		bag_stack = NULL;
326799ebb4caSwyllys 
326899ebb4caSwyllys 		if (cert_authsafe == NULL) {
326999ebb4caSwyllys 			HANDLE_PK12_ERROR
327099ebb4caSwyllys 		}
327199ebb4caSwyllys 	}
327299ebb4caSwyllys 	/*
327399ebb4caSwyllys 	 * Section 2:
327499ebb4caSwyllys 	 *
327599ebb4caSwyllys 	 * The second PKCS#12 container (safebag) will hold the private key
327699ebb4caSwyllys 	 * that goes with the certificates above.  The results of this section
327799ebb4caSwyllys 	 * is an unencrypted PKCS#7 container (authsafe).  If there is no
327899ebb4caSwyllys 	 * private key, there is no point in creating the "safebag" or the
327999ebb4caSwyllys 	 * "authsafe" so we go to the next section.
328099ebb4caSwyllys 	 */
328199ebb4caSwyllys 	if (pkey != NULL) {
328299ebb4caSwyllys 		p8 = EVP_PKEY2PKCS8(pkey);
328399ebb4caSwyllys 		if (p8 == NULL) {
328499ebb4caSwyllys 			HANDLE_PK12_ERROR
328599ebb4caSwyllys 		}
328699ebb4caSwyllys 		/* Put the shrouded key into a PKCS#12 bag. */
328799ebb4caSwyllys 		bag = PKCS12_MAKE_SHKEYBAG(
328899ebb4caSwyllys 		    NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
328999ebb4caSwyllys 		    cred->cred, cred->credlen,
329099ebb4caSwyllys 		    NULL, 0, PKCS12_DEFAULT_ITER, p8);
329199ebb4caSwyllys 
329299ebb4caSwyllys 		/* Clean up the PKCS#8 shrouded key, don't need it now. */
329399ebb4caSwyllys 		PKCS8_PRIV_KEY_INFO_free(p8);
329499ebb4caSwyllys 		p8 = NULL;
329599ebb4caSwyllys 
329699ebb4caSwyllys 		if (bag == NULL) {
329799ebb4caSwyllys 			HANDLE_PK12_ERROR
329899ebb4caSwyllys 		}
329999ebb4caSwyllys 		if (keyidlen &&
330099ebb4caSwyllys 		    !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
330199ebb4caSwyllys 			HANDLE_PK12_ERROR
330299ebb4caSwyllys 		}
330399ebb4caSwyllys 		if (lab != NULL) {
330499ebb4caSwyllys 			if (!PKCS12_add_friendlyname(bag,
330599ebb4caSwyllys 			    (char *)lab, lab_len)) {
330699ebb4caSwyllys 				HANDLE_PK12_ERROR
330799ebb4caSwyllys 			}
330899ebb4caSwyllys 		}
330999ebb4caSwyllys 		/* Start a PKCS#12 safebag container for the private key. */
331099ebb4caSwyllys 		bag_stack = sk_PKCS12_SAFEBAG_new_null();
331199ebb4caSwyllys 		if (bag_stack == NULL) {
331299ebb4caSwyllys 			HANDLE_PK12_ERROR
331399ebb4caSwyllys 		}
331499ebb4caSwyllys 
331599ebb4caSwyllys 		/* Pile on the private key on the bag_stack. */
331699ebb4caSwyllys 		if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
331799ebb4caSwyllys 			HANDLE_PK12_ERROR
331899ebb4caSwyllys 		}
331999ebb4caSwyllys 		key_authsafe = PKCS12_pack_p7data(bag_stack);
332099ebb4caSwyllys 
332199ebb4caSwyllys 		/* Clear away this bag_stack, we're done with it. */
332299ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
332399ebb4caSwyllys 		bag_stack = NULL;
332499ebb4caSwyllys 
332599ebb4caSwyllys 		if (key_authsafe == NULL) {
332699ebb4caSwyllys 			HANDLE_PK12_ERROR
332799ebb4caSwyllys 		}
332899ebb4caSwyllys 	}
332999ebb4caSwyllys 	/*
333099ebb4caSwyllys 	 * Section 3:
333199ebb4caSwyllys 	 *
333299ebb4caSwyllys 	 * This is where the two PKCS#7 containers, one for the certificates
333399ebb4caSwyllys 	 * and one for the private key, are put together into a PKCS#12
333499ebb4caSwyllys 	 * element.  This final PKCS#12 element is written to the export file.
333599ebb4caSwyllys 	 */
333699ebb4caSwyllys 
333799ebb4caSwyllys 	/* Start a PKCS#7 stack. */
333899ebb4caSwyllys 	authsafe_stack = sk_PKCS7_new_null();
333999ebb4caSwyllys 	if (authsafe_stack == NULL) {
334099ebb4caSwyllys 		HANDLE_PK12_ERROR
334199ebb4caSwyllys 	}
334299ebb4caSwyllys 	if (key_authsafe != NULL) {
334399ebb4caSwyllys 		if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
334499ebb4caSwyllys 			HANDLE_PK12_ERROR
334599ebb4caSwyllys 		}
334699ebb4caSwyllys 	}
334799ebb4caSwyllys 	if (cert_authsafe != NULL) {
334899ebb4caSwyllys 		if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
334999ebb4caSwyllys 			HANDLE_PK12_ERROR
335099ebb4caSwyllys 		}
335199ebb4caSwyllys 	}
335299ebb4caSwyllys 	p12_elem = PKCS12_init(NID_pkcs7_data);
335399ebb4caSwyllys 	if (p12_elem == NULL) {
335499ebb4caSwyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
335599ebb4caSwyllys 		HANDLE_PK12_ERROR
335699ebb4caSwyllys 	}
335799ebb4caSwyllys 
335899ebb4caSwyllys 	/* Put the PKCS#7 stack into the PKCS#12 element. */
335999ebb4caSwyllys 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
336099ebb4caSwyllys 		HANDLE_PK12_ERROR
336199ebb4caSwyllys 	}
336299ebb4caSwyllys 	/* Clear away the PKCS#7 stack, we're done with it. */
336399ebb4caSwyllys 	sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
336499ebb4caSwyllys 	authsafe_stack = NULL;
336599ebb4caSwyllys 
336699ebb4caSwyllys 	/* Set the integrity MAC on the PKCS#12 element. */
336799ebb4caSwyllys 	if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
336899ebb4caSwyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
336999ebb4caSwyllys 		HANDLE_PK12_ERROR
337099ebb4caSwyllys 	}
337199ebb4caSwyllys 
337299ebb4caSwyllys 	/* Write the PKCS#12 element to the export file. */
337399ebb4caSwyllys 	if (!i2d_PKCS12_bio(bio, p12_elem)) {
337499ebb4caSwyllys 		HANDLE_PK12_ERROR
337599ebb4caSwyllys 	}
337699ebb4caSwyllys 
337799ebb4caSwyllys 	PKCS12_free(p12_elem);
337899ebb4caSwyllys out:
337999ebb4caSwyllys 	if (rv != KMF_OK) {
338099ebb4caSwyllys 		/* Clear away this bag_stack, we're done with it. */
338199ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
338299ebb4caSwyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
338399ebb4caSwyllys 	}
338499ebb4caSwyllys 	return (rv);
338599ebb4caSwyllys }
338699ebb4caSwyllys 
338799ebb4caSwyllys static EVP_PKEY *
338899ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
338999ebb4caSwyllys {
339099ebb4caSwyllys 	RSA		*rsa = NULL;
339199ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
339299ebb4caSwyllys 
339399ebb4caSwyllys 	if ((rsa = RSA_new()) == NULL)
339499ebb4caSwyllys 		return (NULL);
339599ebb4caSwyllys 
339699ebb4caSwyllys 	if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL)
339799ebb4caSwyllys 		return (NULL);
339899ebb4caSwyllys 
339999ebb4caSwyllys 	if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) ==
340099ebb4caSwyllys 	    NULL)
340199ebb4caSwyllys 		return (NULL);
340299ebb4caSwyllys 
340399ebb4caSwyllys 	if (key->priexp.val != NULL)
340499ebb4caSwyllys 		if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len,
340599ebb4caSwyllys 		    rsa->d)) == NULL)
340699ebb4caSwyllys 			return (NULL);
340799ebb4caSwyllys 
340899ebb4caSwyllys 	if (key->prime1.val != NULL)
340999ebb4caSwyllys 		if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len,
341099ebb4caSwyllys 		    rsa->p)) == NULL)
341199ebb4caSwyllys 			return (NULL);
341299ebb4caSwyllys 
341399ebb4caSwyllys 	if (key->prime2.val != NULL)
341499ebb4caSwyllys 		if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len,
341599ebb4caSwyllys 		    rsa->q)) == NULL)
341699ebb4caSwyllys 			return (NULL);
341799ebb4caSwyllys 
341899ebb4caSwyllys 	if (key->exp1.val != NULL)
341999ebb4caSwyllys 		if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len,
342099ebb4caSwyllys 		    rsa->dmp1)) == NULL)
342199ebb4caSwyllys 			return (NULL);
342299ebb4caSwyllys 
342399ebb4caSwyllys 	if (key->exp2.val != NULL)
342499ebb4caSwyllys 		if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len,
342599ebb4caSwyllys 		    rsa->dmq1)) == NULL)
342699ebb4caSwyllys 			return (NULL);
342799ebb4caSwyllys 
342899ebb4caSwyllys 	if (key->coef.val != NULL)
342999ebb4caSwyllys 		if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len,
343099ebb4caSwyllys 		    rsa->iqmp)) == NULL)
343199ebb4caSwyllys 			return (NULL);
343299ebb4caSwyllys 
343399ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
343499ebb4caSwyllys 		return (NULL);
343599ebb4caSwyllys 
343699ebb4caSwyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
343799ebb4caSwyllys 
343899ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
343999ebb4caSwyllys 	RSA_free(rsa);
344099ebb4caSwyllys 
344199ebb4caSwyllys 	return (newkey);
344299ebb4caSwyllys }
344399ebb4caSwyllys 
344499ebb4caSwyllys static EVP_PKEY *
344599ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
344699ebb4caSwyllys {
344799ebb4caSwyllys 	DSA		*dsa = NULL;
344899ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
344999ebb4caSwyllys 
345099ebb4caSwyllys 	if ((dsa = DSA_new()) == NULL)
345199ebb4caSwyllys 		return (NULL);
345299ebb4caSwyllys 
345399ebb4caSwyllys 	if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len,
345499ebb4caSwyllys 	    dsa->p)) == NULL)
345599ebb4caSwyllys 		return (NULL);
345699ebb4caSwyllys 
345799ebb4caSwyllys 	if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len,
345899ebb4caSwyllys 	    dsa->q)) == NULL)
345999ebb4caSwyllys 		return (NULL);
346099ebb4caSwyllys 
346199ebb4caSwyllys 	if ((dsa->g = BN_bin2bn(key->base.val, key->base.len,
346299ebb4caSwyllys 	    dsa->g)) == NULL)
346399ebb4caSwyllys 		return (NULL);
346499ebb4caSwyllys 
346599ebb4caSwyllys 	if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len,
346699ebb4caSwyllys 	    dsa->priv_key)) == NULL)
346799ebb4caSwyllys 		return (NULL);
346899ebb4caSwyllys 
346999ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
347099ebb4caSwyllys 		return (NULL);
347199ebb4caSwyllys 
347299ebb4caSwyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
347399ebb4caSwyllys 
347499ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
347599ebb4caSwyllys 	DSA_free(dsa);
347699ebb4caSwyllys 	return (newkey);
347799ebb4caSwyllys }
347899ebb4caSwyllys 
347999ebb4caSwyllys static KMF_RETURN
348099ebb4caSwyllys ExportPK12FromRawData(KMF_HANDLE_T handle,
348199ebb4caSwyllys 	KMF_CREDENTIAL *cred,
348299ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
348399ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
348499ebb4caSwyllys 	char *filename)
348599ebb4caSwyllys {
348699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
348799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
348899ebb4caSwyllys 	BIO *bio = NULL;
348999ebb4caSwyllys 	X509 *xcert = NULL;
349099ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
349199ebb4caSwyllys 	int i;
349299ebb4caSwyllys 
349399ebb4caSwyllys 	/*
349499ebb4caSwyllys 	 * Open the output file.
349599ebb4caSwyllys 	 */
349699ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
349799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
349899ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
349999ebb4caSwyllys 		goto cleanup;
350099ebb4caSwyllys 	}
350199ebb4caSwyllys 
350299ebb4caSwyllys 	if (numcerts > 0 && numkeys > 0) {
350399ebb4caSwyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
350499ebb4caSwyllys 			KMF_RAW_KEY_DATA *key = NULL;
350599ebb4caSwyllys 			const uchar_t *p = certlist[i].certificate.Data;
350699ebb4caSwyllys 			long len = certlist[i].certificate.Length;
350799ebb4caSwyllys 
350899ebb4caSwyllys 			if (i < numkeys) {
350999ebb4caSwyllys 				key = (KMF_RAW_KEY_DATA *)keylist[i].keyp;
351099ebb4caSwyllys 
351199ebb4caSwyllys 				if (key->keytype == KMF_RSA) {
351299ebb4caSwyllys 					pkey = ImportRawRSAKey(
351399ebb4caSwyllys 					    &key->rawdata.rsa);
351499ebb4caSwyllys 				} else if (key->keytype == KMF_DSA) {
351599ebb4caSwyllys 					pkey = ImportRawDSAKey(
351699ebb4caSwyllys 					    &key->rawdata.dsa);
351799ebb4caSwyllys 				} else {
351899ebb4caSwyllys 					rv = KMF_ERR_BAD_PARAMETER;
351999ebb4caSwyllys 				}
352099ebb4caSwyllys 			}
352199ebb4caSwyllys 
352299ebb4caSwyllys 			xcert = d2i_X509(NULL, &p, len);
352399ebb4caSwyllys 			if (xcert == NULL) {
352499ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
352599ebb4caSwyllys 				rv = KMF_ERR_ENCODING;
352699ebb4caSwyllys 			}
352799ebb4caSwyllys 			/* Stick the key and the cert into a PKCS#12 file */
352899ebb4caSwyllys 			rv = write_pkcs12(kmfh, bio, cred, pkey, xcert);
352999ebb4caSwyllys 			if (xcert)
353099ebb4caSwyllys 				X509_free(xcert);
353199ebb4caSwyllys 			if (pkey)
353299ebb4caSwyllys 				EVP_PKEY_free(pkey);
353399ebb4caSwyllys 		}
353499ebb4caSwyllys 	}
353599ebb4caSwyllys 
353699ebb4caSwyllys cleanup:
353799ebb4caSwyllys 
353899ebb4caSwyllys 	if (bio != NULL)
353999ebb4caSwyllys 		(void) BIO_free_all(bio);
354099ebb4caSwyllys 
354199ebb4caSwyllys 	return (rv);
354299ebb4caSwyllys }
354399ebb4caSwyllys 
354499ebb4caSwyllys KMF_RETURN
354599ebb4caSwyllys OpenSSL_ExportP12(KMF_HANDLE_T handle,
354699ebb4caSwyllys 	KMF_EXPORTP12_PARAMS *params,
354799ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
354899ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
354999ebb4caSwyllys 	char *filename)
355099ebb4caSwyllys {
355199ebb4caSwyllys 	KMF_RETURN rv;
355299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
355399ebb4caSwyllys 	KMF_FINDCERT_PARAMS fcargs;
355499ebb4caSwyllys 	BIO *bio = NULL;
355599ebb4caSwyllys 	X509 *xcert = NULL;
355699ebb4caSwyllys 	char *fullpath = NULL;
355799ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
355899ebb4caSwyllys 
355999ebb4caSwyllys 	/*
356099ebb4caSwyllys 	 *  First, find the certificate.
356199ebb4caSwyllys 	 */
356299ebb4caSwyllys 	if (params == NULL)
356399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
356499ebb4caSwyllys 
356599ebb4caSwyllys 	/*
356699ebb4caSwyllys 	 * If the caller already sent the raw keys and certs,
356799ebb4caSwyllys 	 * shortcut the search and just export that
356899ebb4caSwyllys 	 * data.
356999ebb4caSwyllys 	 *
357099ebb4caSwyllys 	 * One *may* export a key OR a cert by itself.
357199ebb4caSwyllys 	 */
357299ebb4caSwyllys 	if (certlist != NULL || keylist != NULL) {
357399ebb4caSwyllys 		rv = ExportPK12FromRawData(handle,
3574*34acef67Swyllys 		    &params->p12cred, numcerts, certlist,
3575*34acef67Swyllys 		    numkeys, keylist, filename);
357699ebb4caSwyllys 		return (rv);
357799ebb4caSwyllys 	}
357899ebb4caSwyllys 
357999ebb4caSwyllys 	if (params->sslparms.certfile != NULL) {
358099ebb4caSwyllys 		fullpath = get_fullpath(params->sslparms.dirpath,
358199ebb4caSwyllys 		    params->sslparms.certfile);
358299ebb4caSwyllys 
358399ebb4caSwyllys 		if (fullpath == NULL)
358499ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
358599ebb4caSwyllys 
358699ebb4caSwyllys 		if (isdir(fullpath)) {
358799ebb4caSwyllys 			free(fullpath);
358899ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
358999ebb4caSwyllys 		}
359099ebb4caSwyllys 
359199ebb4caSwyllys 		(void *)memset(&fcargs, 0, sizeof (fcargs));
359299ebb4caSwyllys 		fcargs.kstype = params->kstype;
359399ebb4caSwyllys 		fcargs.certLabel = params->certLabel;
359499ebb4caSwyllys 		fcargs.issuer = params->issuer;
359599ebb4caSwyllys 		fcargs.subject = params->subject;
359699ebb4caSwyllys 		fcargs.serial = params->serial;
359799ebb4caSwyllys 		fcargs.idstr = params->idstr;
359899ebb4caSwyllys 		fcargs.sslparms.dirpath = NULL;
359999ebb4caSwyllys 		fcargs.sslparms.certfile = fullpath;
360099ebb4caSwyllys 		fcargs.sslparms.format = params->sslparms.format;
360199ebb4caSwyllys 
360299ebb4caSwyllys 		rv = load_X509cert(kmfh, &fcargs, fullpath, &xcert);
360399ebb4caSwyllys 		if (rv != KMF_OK)
360499ebb4caSwyllys 			goto end;
360599ebb4caSwyllys 	}
360699ebb4caSwyllys 
360799ebb4caSwyllys 	/*
360899ebb4caSwyllys 	 * Now find the private key.
360999ebb4caSwyllys 	 */
361099ebb4caSwyllys 	if (params->sslparms.keyfile != NULL) {
361199ebb4caSwyllys 		fullpath = get_fullpath(params->sslparms.dirpath,
361299ebb4caSwyllys 		    params->sslparms.keyfile);
361399ebb4caSwyllys 
361499ebb4caSwyllys 		if (fullpath == NULL)
361599ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
361699ebb4caSwyllys 
361799ebb4caSwyllys 		if (isdir(fullpath)) {
361899ebb4caSwyllys 			free(fullpath);
361999ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
362099ebb4caSwyllys 		}
362199ebb4caSwyllys 
362299ebb4caSwyllys 		pkey = openssl_load_key(handle, fullpath);
362399ebb4caSwyllys 		if (pkey == NULL) {
362499ebb4caSwyllys 			rv = KMF_ERR_KEY_NOT_FOUND;
362599ebb4caSwyllys 			goto end;
362699ebb4caSwyllys 		}
362799ebb4caSwyllys 	}
362899ebb4caSwyllys 
362999ebb4caSwyllys 	/*
363099ebb4caSwyllys 	 * Open the output file.
363199ebb4caSwyllys 	 */
363299ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
363399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
363499ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
363599ebb4caSwyllys 		goto end;
363699ebb4caSwyllys 	}
363799ebb4caSwyllys 
363899ebb4caSwyllys 	/* Stick the key and the cert into a PKCS#12 file */
363999ebb4caSwyllys 	rv = write_pkcs12(kmfh, bio, &params->p12cred,
364099ebb4caSwyllys 	    pkey, xcert);
364199ebb4caSwyllys 
364299ebb4caSwyllys end:
364399ebb4caSwyllys 	if (fullpath)
364499ebb4caSwyllys 		free(fullpath);
364599ebb4caSwyllys 	if (xcert)
364699ebb4caSwyllys 		X509_free(xcert);
364799ebb4caSwyllys 	if (pkey)
364899ebb4caSwyllys 		EVP_PKEY_free(pkey);
364999ebb4caSwyllys 	if (bio)
365099ebb4caSwyllys 		(void) BIO_free(bio);
365199ebb4caSwyllys 
365299ebb4caSwyllys 	return (rv);
365399ebb4caSwyllys }
365499ebb4caSwyllys 
365571593db2Swyllys #define	MAX_CHAIN_LENGTH 100
365671593db2Swyllys /*
365771593db2Swyllys  * Helper function to extract keys and certificates from
365871593db2Swyllys  * a single PEM file.  Typically the file should contain a
365971593db2Swyllys  * private key and an associated public key wrapped in an x509 cert.
366071593db2Swyllys  * However, the file may be just a list of X509 certs with no keys.
366171593db2Swyllys  */
366271593db2Swyllys static KMF_RETURN
366302744e81Swyllys extract_objects(KMF_HANDLE *kmfh, KMF_FINDCERT_PARAMS *params,
366402744e81Swyllys 	char *filename, CK_UTF8CHAR *pin,
366571593db2Swyllys 	CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
366671593db2Swyllys 	int *numcerts)
366771593db2Swyllys /* ARGSUSED */
366871593db2Swyllys {
366971593db2Swyllys 	KMF_RETURN rv = KMF_OK;
367071593db2Swyllys 	FILE *fp;
3671*34acef67Swyllys 	STACK_OF(X509_INFO) *x509_info_stack = NULL;
367202744e81Swyllys 	int i, ncerts = 0, matchcerts = 0;
367371593db2Swyllys 	EVP_PKEY *pkey = NULL;
367471593db2Swyllys 	X509_INFO *info;
367571593db2Swyllys 	X509 *x;
367671593db2Swyllys 	X509_INFO *cert_infos[MAX_CHAIN_LENGTH];
367771593db2Swyllys 	KMF_DATA *certlist = NULL;
367871593db2Swyllys 
367971593db2Swyllys 	if (priv_key)
368071593db2Swyllys 		*priv_key = NULL;
368171593db2Swyllys 	if (certs)
368271593db2Swyllys 		*certs = NULL;
368371593db2Swyllys 	fp = fopen(filename, "r");
368471593db2Swyllys 	if (fp == NULL) {
368571593db2Swyllys 		return (KMF_ERR_OPEN_FILE);
368671593db2Swyllys 	}
368771593db2Swyllys 	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
368871593db2Swyllys 	if (x509_info_stack == NULL) {
368971593db2Swyllys 		(void) fclose(fp);
369071593db2Swyllys 		return (KMF_ERR_ENCODING);
369171593db2Swyllys 	}
369271593db2Swyllys 
3693*34acef67Swyllys 	for (i = 0;
3694*34acef67Swyllys 	    i < sk_X509_INFO_num(x509_info_stack) && i < MAX_CHAIN_LENGTH;
3695*34acef67Swyllys 	    i++) {
369671593db2Swyllys 		/*LINTED*/
3697*34acef67Swyllys 		cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
369871593db2Swyllys 		ncerts++;
369971593db2Swyllys 	}
370071593db2Swyllys 
370171593db2Swyllys 	if (ncerts == 0) {
370271593db2Swyllys 		(void) fclose(fp);
3703*34acef67Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
3704*34acef67Swyllys 		goto err;
370571593db2Swyllys 	}
370671593db2Swyllys 
370771593db2Swyllys 	if (priv_key != NULL) {
370871593db2Swyllys 		rewind(fp);
370971593db2Swyllys 		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
371071593db2Swyllys 	}
371171593db2Swyllys 	(void) fclose(fp);
371271593db2Swyllys 
371371593db2Swyllys 	x = cert_infos[ncerts - 1]->x509;
371471593db2Swyllys 	/*
371571593db2Swyllys 	 * Make sure the private key matchs the last cert in the file.
371671593db2Swyllys 	 */
371771593db2Swyllys 	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
371871593db2Swyllys 		EVP_PKEY_free(pkey);
3719*34acef67Swyllys 		rv = KMF_ERR_KEY_MISMATCH;
3720*34acef67Swyllys 		goto err;
372171593db2Swyllys 	}
372271593db2Swyllys 
372371593db2Swyllys 	certlist = (KMF_DATA *)malloc(ncerts * sizeof (KMF_DATA));
372471593db2Swyllys 	if (certlist == NULL) {
372571593db2Swyllys 		if (pkey != NULL)
372671593db2Swyllys 			EVP_PKEY_free(pkey);
3727*34acef67Swyllys 		rv = KMF_ERR_MEMORY;
3728*34acef67Swyllys 		goto err;
372971593db2Swyllys 	}
373071593db2Swyllys 
373171593db2Swyllys 	/*
373271593db2Swyllys 	 * Convert all of the certs to DER format.
373371593db2Swyllys 	 */
373402744e81Swyllys 	matchcerts = 0;
373571593db2Swyllys 	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
373602744e81Swyllys 		boolean_t match = FALSE;
373771593db2Swyllys 		info =  cert_infos[ncerts - 1 - i];
373871593db2Swyllys 
373902744e81Swyllys 		if (params != NULL) {
374002744e81Swyllys 			rv = check_cert(info->x509, params, &match);
374102744e81Swyllys 			if (rv != KMF_OK || match != TRUE) {
374202744e81Swyllys 				rv = KMF_OK;
374302744e81Swyllys 				continue;
374402744e81Swyllys 			}
374502744e81Swyllys 		}
374602744e81Swyllys 
374702744e81Swyllys 		rv = ssl_cert2KMFDATA(kmfh, info->x509,
374802744e81Swyllys 			&certlist[matchcerts++]);
374971593db2Swyllys 
375071593db2Swyllys 		if (rv != KMF_OK) {
375171593db2Swyllys 			free(certlist);
375271593db2Swyllys 			certlist = NULL;
375302744e81Swyllys 			ncerts = matchcerts = 0;
375471593db2Swyllys 		}
375571593db2Swyllys 	}
375671593db2Swyllys 
375771593db2Swyllys 	if (numcerts != NULL)
375802744e81Swyllys 		*numcerts = matchcerts;
375971593db2Swyllys 	if (certs != NULL)
376071593db2Swyllys 		*certs = certlist;
376171593db2Swyllys 
376271593db2Swyllys 	if (priv_key == NULL && pkey != NULL)
376371593db2Swyllys 		EVP_PKEY_free(pkey);
376471593db2Swyllys 	else if (priv_key != NULL && pkey != NULL)
376571593db2Swyllys 		*priv_key = pkey;
376671593db2Swyllys 
3767*34acef67Swyllys err:
3768*34acef67Swyllys 	/* Cleanup the stack of X509 info records */
3769*34acef67Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3770*34acef67Swyllys 		/*LINTED*/
3771*34acef67Swyllys 		info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
3772*34acef67Swyllys 		X509_INFO_free(info);
3773*34acef67Swyllys 	}
3774*34acef67Swyllys 	if (x509_info_stack)
3775*34acef67Swyllys 		sk_X509_INFO_free(x509_info_stack);
3776*34acef67Swyllys 
377771593db2Swyllys 	return (rv);
377871593db2Swyllys }
377971593db2Swyllys 
378099ebb4caSwyllys /*
378199ebb4caSwyllys  * Helper function to decrypt and parse PKCS#12 import file.
378299ebb4caSwyllys  */
378399ebb4caSwyllys static KMF_RETURN
378499ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
378599ebb4caSwyllys 	EVP_PKEY **priv_key, X509 **cert, STACK_OF(X509) **ca)
378699ebb4caSwyllys /* ARGSUSED */
378799ebb4caSwyllys {
378899ebb4caSwyllys 	PKCS12		*pk12, *pk12_tmp;
378999ebb4caSwyllys 	EVP_PKEY	*temp_pkey = NULL;
379099ebb4caSwyllys 	X509		*temp_cert = NULL;
379199ebb4caSwyllys 	STACK_OF(X509)	*temp_ca = NULL;
379299ebb4caSwyllys 
379399ebb4caSwyllys 	if ((pk12 = PKCS12_new()) == NULL) {
379499ebb4caSwyllys 		return (KMF_ERR_MEMORY);
379599ebb4caSwyllys 	}
379699ebb4caSwyllys 
379799ebb4caSwyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
379899ebb4caSwyllys 		/* This is ok; it seems to mean there is no more to read. */
379999ebb4caSwyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
380099ebb4caSwyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
380199ebb4caSwyllys 			goto end_extract_pkcs12;
380299ebb4caSwyllys 
380399ebb4caSwyllys 		PKCS12_free(pk12);
380499ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
380599ebb4caSwyllys 	}
380699ebb4caSwyllys 	pk12 = pk12_tmp;
380799ebb4caSwyllys 
380899ebb4caSwyllys 	if (PKCS12_parse(pk12, (char *)pin, &temp_pkey, &temp_cert,
380999ebb4caSwyllys 	    &temp_ca) <= 0) {
381099ebb4caSwyllys 		PKCS12_free(pk12);
381199ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
381299ebb4caSwyllys 	}
381399ebb4caSwyllys 
381499ebb4caSwyllys end_extract_pkcs12:
381599ebb4caSwyllys 
381699ebb4caSwyllys 	*priv_key = temp_pkey;
381799ebb4caSwyllys 	*cert = temp_cert;
381899ebb4caSwyllys 	*ca = temp_ca;
381999ebb4caSwyllys 
382099ebb4caSwyllys 	PKCS12_free(pk12);
382199ebb4caSwyllys 	return (KMF_OK);
382299ebb4caSwyllys }
382399ebb4caSwyllys 
382499ebb4caSwyllys static KMF_RETURN
382599ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
382699ebb4caSwyllys {
382799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
382899ebb4caSwyllys 	uint32_t sz;
382999ebb4caSwyllys 
383099ebb4caSwyllys 	sz = BN_num_bytes(from);
383199ebb4caSwyllys 	to->val = (uchar_t *)malloc(sz);
383299ebb4caSwyllys 	if (to->val == NULL)
383399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
383499ebb4caSwyllys 
383599ebb4caSwyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
383699ebb4caSwyllys 		free(to->val);
383799ebb4caSwyllys 		to->val = NULL;
383899ebb4caSwyllys 		to->len = 0;
383999ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
384099ebb4caSwyllys 	}
384199ebb4caSwyllys 
384299ebb4caSwyllys 	return (rv);
384399ebb4caSwyllys }
384499ebb4caSwyllys 
384599ebb4caSwyllys static KMF_RETURN
384699ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
384799ebb4caSwyllys {
384899ebb4caSwyllys 	KMF_RETURN rv;
384999ebb4caSwyllys 	KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
385099ebb4caSwyllys 
385199ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
385299ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK)
385399ebb4caSwyllys 		goto cleanup;
385499ebb4caSwyllys 
385599ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK)
385699ebb4caSwyllys 		goto cleanup;
385799ebb4caSwyllys 
385899ebb4caSwyllys 	if (rsa->d != NULL)
385999ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK)
386099ebb4caSwyllys 			goto cleanup;
386199ebb4caSwyllys 
386299ebb4caSwyllys 	if (rsa->p != NULL)
386399ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK)
386499ebb4caSwyllys 			goto cleanup;
386599ebb4caSwyllys 
386699ebb4caSwyllys 	if (rsa->q != NULL)
386799ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK)
386899ebb4caSwyllys 			goto cleanup;
386999ebb4caSwyllys 
387099ebb4caSwyllys 	if (rsa->dmp1 != NULL)
387199ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK)
387299ebb4caSwyllys 			goto cleanup;
387399ebb4caSwyllys 
387499ebb4caSwyllys 	if (rsa->dmq1 != NULL)
387599ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK)
387699ebb4caSwyllys 			goto cleanup;
387799ebb4caSwyllys 
387899ebb4caSwyllys 	if (rsa->iqmp != NULL)
387999ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK)
388099ebb4caSwyllys 			goto cleanup;
388199ebb4caSwyllys cleanup:
388299ebb4caSwyllys 	if (rv != KMF_OK)
388399ebb4caSwyllys 		KMF_FreeRawKey(key);
388499ebb4caSwyllys 	else
388599ebb4caSwyllys 		key->keytype = KMF_RSA;
388699ebb4caSwyllys 
388799ebb4caSwyllys 	/*
388899ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
388999ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
389099ebb4caSwyllys 	 */
389199ebb4caSwyllys 	RSA_free(rsa);
389299ebb4caSwyllys 
389399ebb4caSwyllys 	return (rv);
389499ebb4caSwyllys }
389599ebb4caSwyllys 
389699ebb4caSwyllys static KMF_RETURN
389799ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
389899ebb4caSwyllys {
389999ebb4caSwyllys 	KMF_RETURN rv;
390099ebb4caSwyllys 	KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
390199ebb4caSwyllys 
390299ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
390399ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK)
390499ebb4caSwyllys 		goto cleanup;
390599ebb4caSwyllys 
390699ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK)
390799ebb4caSwyllys 		goto cleanup;
390899ebb4caSwyllys 
390999ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK)
391099ebb4caSwyllys 		goto cleanup;
391199ebb4caSwyllys 
391299ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK)
391399ebb4caSwyllys 		goto cleanup;
391499ebb4caSwyllys 
391599ebb4caSwyllys cleanup:
391699ebb4caSwyllys 	if (rv != KMF_OK)
391799ebb4caSwyllys 		KMF_FreeRawKey(key);
391899ebb4caSwyllys 	else
391999ebb4caSwyllys 		key->keytype = KMF_DSA;
392099ebb4caSwyllys 
392199ebb4caSwyllys 	/*
392299ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
392399ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
392499ebb4caSwyllys 	 */
392599ebb4caSwyllys 	DSA_free(dsa);
392699ebb4caSwyllys 
392799ebb4caSwyllys 	return (rv);
392899ebb4caSwyllys }
392999ebb4caSwyllys 
393099ebb4caSwyllys static KMF_RETURN
393199ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
393299ebb4caSwyllys 	KMF_DATA **certlist, int *ncerts)
393399ebb4caSwyllys {
393499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
393599ebb4caSwyllys 	KMF_DATA *list = (*certlist);
393699ebb4caSwyllys 	KMF_DATA cert;
393799ebb4caSwyllys 	int n = (*ncerts);
393899ebb4caSwyllys 
393999ebb4caSwyllys 	if (list == NULL) {
394099ebb4caSwyllys 		list = (KMF_DATA *)malloc(sizeof (KMF_DATA));
394199ebb4caSwyllys 	} else {
394299ebb4caSwyllys 		list = (KMF_DATA *)realloc(list, sizeof (KMF_DATA) * (n + 1));
394399ebb4caSwyllys 	}
394499ebb4caSwyllys 
394599ebb4caSwyllys 	if (list == NULL)
394699ebb4caSwyllys 		return (KMF_ERR_MEMORY);
394799ebb4caSwyllys 
394899ebb4caSwyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert);
394999ebb4caSwyllys 	if (rv == KMF_OK) {
395099ebb4caSwyllys 		list[n] = cert;
395199ebb4caSwyllys 		(*ncerts) = n + 1;
395299ebb4caSwyllys 
395399ebb4caSwyllys 		*certlist = list;
395499ebb4caSwyllys 	} else {
395599ebb4caSwyllys 		free(list);
395699ebb4caSwyllys 	}
395799ebb4caSwyllys 
395899ebb4caSwyllys 	return (rv);
395999ebb4caSwyllys }
396099ebb4caSwyllys 
396199ebb4caSwyllys static KMF_RETURN
396299ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
396399ebb4caSwyllys 	KMF_RAW_KEY_DATA *newkey, int *nkeys)
396499ebb4caSwyllys {
396599ebb4caSwyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
396699ebb4caSwyllys 	int n = (*nkeys);
396799ebb4caSwyllys 
396899ebb4caSwyllys 	if (list == NULL) {
396999ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
397099ebb4caSwyllys 	} else {
397199ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
397299ebb4caSwyllys 		    sizeof (KMF_RAW_KEY_DATA) * (n + 1));
397399ebb4caSwyllys 	}
397499ebb4caSwyllys 
397599ebb4caSwyllys 	if (list == NULL)
397699ebb4caSwyllys 		return (KMF_ERR_MEMORY);
397799ebb4caSwyllys 
397899ebb4caSwyllys 	list[n] = *newkey;
397999ebb4caSwyllys 	(*nkeys) = n + 1;
398099ebb4caSwyllys 
398199ebb4caSwyllys 	*keylist = list;
398299ebb4caSwyllys 
398399ebb4caSwyllys 	return (KMF_OK);
398499ebb4caSwyllys }
398599ebb4caSwyllys 
398699ebb4caSwyllys 
398799ebb4caSwyllys static KMF_RETURN
398899ebb4caSwyllys convertPK12Objects(
398999ebb4caSwyllys 	KMF_HANDLE *kmfh,
399099ebb4caSwyllys 	EVP_PKEY *sslkey, X509 *sslcert, STACK_OF(X509) *sslcacerts,
399199ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
399299ebb4caSwyllys 	KMF_DATA **certlist, int *ncerts)
399399ebb4caSwyllys {
399499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
399599ebb4caSwyllys 	KMF_RAW_KEY_DATA key;
399699ebb4caSwyllys 	int i;
399799ebb4caSwyllys 
399899ebb4caSwyllys 	if (sslkey != NULL) {
399999ebb4caSwyllys 		/* Convert SSL key to raw key */
400099ebb4caSwyllys 		switch (sslkey->type) {
400199ebb4caSwyllys 			case EVP_PKEY_RSA:
400299ebb4caSwyllys 				rv = exportRawRSAKey(EVP_PKEY_get1_RSA(sslkey),
400399ebb4caSwyllys 				    &key);
400499ebb4caSwyllys 				if (rv != KMF_OK)
400599ebb4caSwyllys 					return (rv);
400699ebb4caSwyllys 
400799ebb4caSwyllys 				break;
400899ebb4caSwyllys 			case EVP_PKEY_DSA:
400999ebb4caSwyllys 				rv = exportRawDSAKey(EVP_PKEY_get1_DSA(sslkey),
401099ebb4caSwyllys 				    &key);
401199ebb4caSwyllys 				if (rv != KMF_OK)
401299ebb4caSwyllys 					return (rv);
401399ebb4caSwyllys 
401499ebb4caSwyllys 				break;
401599ebb4caSwyllys 			default:
401699ebb4caSwyllys 				return (KMF_ERR_BAD_PARAMETER);
401799ebb4caSwyllys 		}
401899ebb4caSwyllys 
401999ebb4caSwyllys 		rv = add_key_to_list(keylist, &key, nkeys);
402099ebb4caSwyllys 		if (rv != KMF_OK)
402199ebb4caSwyllys 			return (rv);
402299ebb4caSwyllys 	}
402399ebb4caSwyllys 
402499ebb4caSwyllys 	/* Now add the certificate to the certlist */
402599ebb4caSwyllys 	if (sslcert != NULL) {
402699ebb4caSwyllys 		rv = add_cert_to_list(kmfh, sslcert, certlist, ncerts);
402799ebb4caSwyllys 		if (rv != KMF_OK)
402899ebb4caSwyllys 			return (rv);
402999ebb4caSwyllys 	}
403099ebb4caSwyllys 
403199ebb4caSwyllys 	/* Also add any included CA certs to the list */
403271593db2Swyllys 	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
403399ebb4caSwyllys 		X509 *c;
403499ebb4caSwyllys 		/*
403599ebb4caSwyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
403699ebb4caSwyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
403799ebb4caSwyllys 		 * Lint is complaining about the embedded casting, and
403899ebb4caSwyllys 		 * to fix it, you need to fix openssl header files.
403999ebb4caSwyllys 		 */
404099ebb4caSwyllys 		/* LINTED E_BAD_PTR_CAST_ALIGN */
404199ebb4caSwyllys 		c = sk_X509_value(sslcacerts, i);
404299ebb4caSwyllys 
404399ebb4caSwyllys 		/* Now add the ca cert to the certlist */
404499ebb4caSwyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
404599ebb4caSwyllys 		if (rv != KMF_OK)
404699ebb4caSwyllys 			return (rv);
404799ebb4caSwyllys 	}
404899ebb4caSwyllys 	return (rv);
404999ebb4caSwyllys }
405099ebb4caSwyllys 
405199ebb4caSwyllys KMF_RETURN
405299ebb4caSwyllys openssl_read_pkcs12(KMF_HANDLE *kmfh,
405399ebb4caSwyllys 	char *filename, KMF_CREDENTIAL *cred,
405499ebb4caSwyllys 	KMF_DATA **certlist, int *ncerts,
405599ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
405699ebb4caSwyllys {
405799ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
405899ebb4caSwyllys 	BIO		*bio = NULL;
405999ebb4caSwyllys 	EVP_PKEY	*privkey = NULL;
406099ebb4caSwyllys 	X509		*cert = NULL;
406199ebb4caSwyllys 	STACK_OF(X509)	*cacerts = NULL;
406299ebb4caSwyllys 
406399ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
406499ebb4caSwyllys 	if (bio == NULL) {
406599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
406699ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
406799ebb4caSwyllys 		goto end;
406899ebb4caSwyllys 	}
406999ebb4caSwyllys 
407099ebb4caSwyllys 	*certlist = NULL;
407199ebb4caSwyllys 	*keylist = NULL;
407299ebb4caSwyllys 	*ncerts = 0;
407399ebb4caSwyllys 	*nkeys = 0;
40746adaf03eSwyllys 
4075*34acef67Swyllys 	rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
4076*34acef67Swyllys 	    (uint32_t)cred->credlen, &privkey, &cert, &cacerts);
407799ebb4caSwyllys 
407899ebb4caSwyllys 	if (rv == KMF_OK)
407999ebb4caSwyllys 		/* Convert keys and certs to exportable format */
408099ebb4caSwyllys 		rv = convertPK12Objects(kmfh, privkey, cert, cacerts,
408199ebb4caSwyllys 		    keylist, nkeys, certlist, ncerts);
408299ebb4caSwyllys 
408399ebb4caSwyllys end:
408499ebb4caSwyllys 	if (bio != NULL)
408599ebb4caSwyllys 		(void) BIO_free(bio);
408699ebb4caSwyllys 
408799ebb4caSwyllys 	if (privkey)
408899ebb4caSwyllys 		EVP_PKEY_free(privkey);
408999ebb4caSwyllys 
409099ebb4caSwyllys 	if (cert)
409199ebb4caSwyllys 		X509_free(cert);
409299ebb4caSwyllys 
409399ebb4caSwyllys 	if (cacerts)
409499ebb4caSwyllys 		sk_X509_free(cacerts);
409599ebb4caSwyllys 
409699ebb4caSwyllys 	return (rv);
409799ebb4caSwyllys }
409899ebb4caSwyllys 
409999ebb4caSwyllys KMF_RETURN
410071593db2Swyllys openssl_import_keypair(KMF_HANDLE *kmfh,
410171593db2Swyllys 	char *filename, KMF_CREDENTIAL *cred,
410271593db2Swyllys 	KMF_DATA **certlist, int *ncerts,
410371593db2Swyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
410471593db2Swyllys {
410571593db2Swyllys 	KMF_RETURN	rv = KMF_OK;
410671593db2Swyllys 	EVP_PKEY	*privkey = NULL;
410771593db2Swyllys 	KMF_ENCODE_FORMAT format;
410871593db2Swyllys 
410971593db2Swyllys 	/*
411071593db2Swyllys 	 * auto-detect the file format, regardless of what
411171593db2Swyllys 	 * the 'format' parameters in the params say.
411271593db2Swyllys 	 */
411371593db2Swyllys 	rv = KMF_GetFileFormat(filename, &format);
411471593db2Swyllys 	if (rv != KMF_OK) {
411571593db2Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
411671593db2Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
411771593db2Swyllys 		return (rv);
411871593db2Swyllys 	}
411971593db2Swyllys 
412071593db2Swyllys 	/* This function only works on PEM files */
412171593db2Swyllys 	if (format != KMF_FORMAT_PEM &&
412271593db2Swyllys 	    format != KMF_FORMAT_PEM_KEYPAIR)
412371593db2Swyllys 		return (KMF_ERR_ENCODING);
412471593db2Swyllys 
412571593db2Swyllys 	*certlist = NULL;
412671593db2Swyllys 	*keylist = NULL;
412771593db2Swyllys 	*ncerts = 0;
412871593db2Swyllys 	*nkeys = 0;
412902744e81Swyllys 	rv = extract_objects(kmfh, NULL, filename,
4130*34acef67Swyllys 	    (uchar_t *)cred->cred, (uint32_t)cred->credlen,
413171593db2Swyllys 	    &privkey, certlist, ncerts);
413271593db2Swyllys 
413371593db2Swyllys 	/* Reached end of import file? */
413471593db2Swyllys 	if (rv == KMF_OK)
413571593db2Swyllys 		/* Convert keys and certs to exportable format */
413671593db2Swyllys 		rv = convertPK12Objects(kmfh, privkey, NULL, NULL,
413771593db2Swyllys 		    keylist, nkeys, NULL, NULL);
413871593db2Swyllys 
413971593db2Swyllys end:
414071593db2Swyllys 	if (privkey)
414171593db2Swyllys 		EVP_PKEY_free(privkey);
414271593db2Swyllys 
414371593db2Swyllys 	return (rv);
414471593db2Swyllys }
414571593db2Swyllys 
414671593db2Swyllys KMF_RETURN
414799ebb4caSwyllys OpenSSL_StorePrivateKey(KMF_HANDLE_T handle, KMF_STOREKEY_PARAMS *params,
414899ebb4caSwyllys 	KMF_RAW_KEY_DATA *key)
414999ebb4caSwyllys {
415099ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
415199ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
415299ebb4caSwyllys 	char		*fullpath;
415399ebb4caSwyllys 	EVP_PKEY	*pkey = NULL;
415499ebb4caSwyllys 	BIO		*bio = NULL;
415599ebb4caSwyllys 
415699ebb4caSwyllys 	if (key != NULL) {
415799ebb4caSwyllys 		if (key->keytype == KMF_RSA) {
415899ebb4caSwyllys 			pkey = ImportRawRSAKey(&key->rawdata.rsa);
415999ebb4caSwyllys 		} else if (key->keytype == KMF_DSA) {
416099ebb4caSwyllys 			pkey = ImportRawDSAKey(&key->rawdata.dsa);
416199ebb4caSwyllys 		} else {
416299ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
416399ebb4caSwyllys 		}
416499ebb4caSwyllys 	} else {
416599ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
416699ebb4caSwyllys 	}
416799ebb4caSwyllys 	if (rv != KMF_OK || pkey == NULL)
416899ebb4caSwyllys 		return (rv);
416999ebb4caSwyllys 
417099ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
417199ebb4caSwyllys 	    params->sslparms.keyfile);
417299ebb4caSwyllys 
417399ebb4caSwyllys 	if (fullpath == NULL)
417499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
417599ebb4caSwyllys 
417699ebb4caSwyllys 	/* If the requested file exists, return an error */
417799ebb4caSwyllys 	if (access(fullpath, F_OK) == 0) {
417899ebb4caSwyllys 		free(fullpath);
417999ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
418099ebb4caSwyllys 	}
418199ebb4caSwyllys 
418299ebb4caSwyllys 	bio = BIO_new_file(fullpath, "wb");
418399ebb4caSwyllys 	if (bio == NULL) {
418499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
418599ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
418699ebb4caSwyllys 		goto cleanup;
418799ebb4caSwyllys 	}
418899ebb4caSwyllys 
4189*34acef67Swyllys 	rv = ssl_write_private_key(kmfh, params->sslparms.format,
419099ebb4caSwyllys 	    bio, &params->cred, pkey);
419199ebb4caSwyllys 
419299ebb4caSwyllys cleanup:
419399ebb4caSwyllys 	if (fullpath)
419499ebb4caSwyllys 		free(fullpath);
419599ebb4caSwyllys 
419699ebb4caSwyllys 	if (pkey)
419799ebb4caSwyllys 		EVP_PKEY_free(pkey);
419899ebb4caSwyllys 
419999ebb4caSwyllys 	if (bio)
420099ebb4caSwyllys 		(void) BIO_free(bio);
420199ebb4caSwyllys 
420299ebb4caSwyllys 	/* Protect the file by making it read-only */
420399ebb4caSwyllys 	if (rv == KMF_OK) {
420499ebb4caSwyllys 		(void) chmod(fullpath, 0400);
420599ebb4caSwyllys 	}
420699ebb4caSwyllys 	return (rv);
420799ebb4caSwyllys }
420899ebb4caSwyllys 
420999ebb4caSwyllys static KMF_RETURN
421099ebb4caSwyllys create_deskey(DES_cblock **deskey)
421199ebb4caSwyllys {
421299ebb4caSwyllys 	DES_cblock *key;
421399ebb4caSwyllys 
421499ebb4caSwyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
421599ebb4caSwyllys 	if (key == NULL) {
421699ebb4caSwyllys 		return (KMF_ERR_MEMORY);
421799ebb4caSwyllys 	}
421899ebb4caSwyllys 
421999ebb4caSwyllys 	if (DES_random_key(key) == 0) {
422099ebb4caSwyllys 		free(key);
422199ebb4caSwyllys 		return (KMF_ERR_KEYGEN_FAILED);
422299ebb4caSwyllys 	}
422399ebb4caSwyllys 
422499ebb4caSwyllys 	*deskey = key;
422599ebb4caSwyllys 	return (KMF_OK);
422699ebb4caSwyllys }
422799ebb4caSwyllys 
422899ebb4caSwyllys #define	KEYGEN_RETRY 3
422999ebb4caSwyllys #define	DES3_KEY_SIZE 24
423099ebb4caSwyllys 
423199ebb4caSwyllys static KMF_RETURN
423299ebb4caSwyllys create_des3key(unsigned char **des3key)
423399ebb4caSwyllys {
423499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
423599ebb4caSwyllys 	DES_cblock *deskey1 = NULL;
423699ebb4caSwyllys 	DES_cblock *deskey2 = NULL;
423799ebb4caSwyllys 	DES_cblock *deskey3 = NULL;
423899ebb4caSwyllys 	unsigned char *newkey = NULL;
423999ebb4caSwyllys 	int retry;
424099ebb4caSwyllys 
424199ebb4caSwyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
424299ebb4caSwyllys 		return (KMF_ERR_MEMORY);
424399ebb4caSwyllys 	}
424499ebb4caSwyllys 
424599ebb4caSwyllys 	/* create the 1st DES key */
424699ebb4caSwyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
424799ebb4caSwyllys 		goto out;
424899ebb4caSwyllys 	}
424999ebb4caSwyllys 
425099ebb4caSwyllys 	/*
425199ebb4caSwyllys 	 * Create the 2nd DES key and make sure its value is different
425299ebb4caSwyllys 	 * from the 1st DES key.
425399ebb4caSwyllys 	 */
425499ebb4caSwyllys 	retry = 0;
425599ebb4caSwyllys 	do {
425699ebb4caSwyllys 		if (deskey2 != NULL) {
425799ebb4caSwyllys 			free(deskey2);
425899ebb4caSwyllys 			deskey2 = NULL;
425999ebb4caSwyllys 		}
426099ebb4caSwyllys 
426199ebb4caSwyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
426299ebb4caSwyllys 			goto out;
426399ebb4caSwyllys 		}
426499ebb4caSwyllys 
426599ebb4caSwyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
426699ebb4caSwyllys 		    == 0) {
426799ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
426899ebb4caSwyllys 			retry++;
426999ebb4caSwyllys 		}
427099ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
427199ebb4caSwyllys 
427299ebb4caSwyllys 	if (ret != KMF_OK) {
427399ebb4caSwyllys 		goto out;
427499ebb4caSwyllys 	}
427599ebb4caSwyllys 
427699ebb4caSwyllys 	/*
427799ebb4caSwyllys 	 * Create the 3rd DES key and make sure its value is different
427899ebb4caSwyllys 	 * from the 2nd DES key.
427999ebb4caSwyllys 	 */
428099ebb4caSwyllys 	retry = 0;
428199ebb4caSwyllys 	do {
428299ebb4caSwyllys 		if (deskey3 != NULL) {
428399ebb4caSwyllys 			free(deskey3);
428499ebb4caSwyllys 			deskey3 = NULL;
428599ebb4caSwyllys 		}
428699ebb4caSwyllys 
428799ebb4caSwyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
428899ebb4caSwyllys 			goto out;
428999ebb4caSwyllys 		}
429099ebb4caSwyllys 
429199ebb4caSwyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
429299ebb4caSwyllys 		    == 0) {
429399ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
429499ebb4caSwyllys 			retry++;
429599ebb4caSwyllys 		}
429699ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
429799ebb4caSwyllys 
429899ebb4caSwyllys 	if (ret != KMF_OK) {
429999ebb4caSwyllys 		goto out;
430099ebb4caSwyllys 	}
430199ebb4caSwyllys 
430299ebb4caSwyllys 	/* Concatenate 3 DES keys into a DES3 key */
430399ebb4caSwyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
430499ebb4caSwyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
430599ebb4caSwyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
430699ebb4caSwyllys 	*des3key = newkey;
430799ebb4caSwyllys 
430899ebb4caSwyllys out:
430999ebb4caSwyllys 	if (deskey1 != NULL)
431099ebb4caSwyllys 		free(deskey1);
431199ebb4caSwyllys 
431299ebb4caSwyllys 	if (deskey2 != NULL)
431399ebb4caSwyllys 		free(deskey2);
431499ebb4caSwyllys 
431599ebb4caSwyllys 	if (deskey3 != NULL)
431699ebb4caSwyllys 		free(deskey3);
431799ebb4caSwyllys 
431899ebb4caSwyllys 	if (ret != KMF_OK && newkey != NULL)
431999ebb4caSwyllys 		free(newkey);
432099ebb4caSwyllys 
432199ebb4caSwyllys 	return (ret);
432299ebb4caSwyllys }
432399ebb4caSwyllys 
432499ebb4caSwyllys KMF_RETURN
432599ebb4caSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle, KMF_CREATESYMKEY_PARAMS *params,
432699ebb4caSwyllys 	KMF_KEY_HANDLE *symkey)
432799ebb4caSwyllys {
432899ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
432999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
433099ebb4caSwyllys 	char *fullpath = NULL;
433199ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
433299ebb4caSwyllys 	DES_cblock *deskey = NULL;
433399ebb4caSwyllys 	unsigned char *des3key = NULL;
433499ebb4caSwyllys 	unsigned char *random = NULL;
433599ebb4caSwyllys 	int fd = -1;
433699ebb4caSwyllys 
433799ebb4caSwyllys 	if (kmfh == NULL)
433899ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
433999ebb4caSwyllys 
434099ebb4caSwyllys 	if (params == NULL || params->sslparms.keyfile == NULL) {
434199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
434299ebb4caSwyllys 	}
434399ebb4caSwyllys 
434499ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
434599ebb4caSwyllys 	    params->sslparms.keyfile);
434699ebb4caSwyllys 	if (fullpath == NULL)
434799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
434899ebb4caSwyllys 
434999ebb4caSwyllys 	/* If the requested file exists, return an error */
435099ebb4caSwyllys 	if (access(fullpath, F_OK) == 0) {
435199ebb4caSwyllys 		free(fullpath);
435299ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
435399ebb4caSwyllys 	}
435499ebb4caSwyllys 
435599ebb4caSwyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
435699ebb4caSwyllys 	if (fd == -1) {
435799ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
435899ebb4caSwyllys 		goto out;
435999ebb4caSwyllys 	}
436099ebb4caSwyllys 
436199ebb4caSwyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
436299ebb4caSwyllys 	if (rkey == NULL) {
436399ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
436499ebb4caSwyllys 		goto out;
436599ebb4caSwyllys 	}
436699ebb4caSwyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
436799ebb4caSwyllys 
436899ebb4caSwyllys 	if (params->keytype == KMF_DES) {
436999ebb4caSwyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
437099ebb4caSwyllys 			goto out;
437199ebb4caSwyllys 		}
437299ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)deskey;
437399ebb4caSwyllys 		rkey->keydata.len = 8;
437499ebb4caSwyllys 
437599ebb4caSwyllys 		symkey->keyalg = KMF_DES;
437699ebb4caSwyllys 
437799ebb4caSwyllys 	} else if (params->keytype == KMF_DES3) {
437899ebb4caSwyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
437999ebb4caSwyllys 			goto out;
438099ebb4caSwyllys 		}
438199ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)des3key;
438299ebb4caSwyllys 		rkey->keydata.len = DES3_KEY_SIZE;
438399ebb4caSwyllys 		symkey->keyalg = KMF_DES3;
43849b37d296Swyllys 
4385c197cb9dShylee 	} else if (params->keytype == KMF_AES || params->keytype == KMF_RC4 ||
4386c197cb9dShylee 	    params->keytype == KMF_GENERIC_SECRET) {
438799ebb4caSwyllys 		int bytes;
438899ebb4caSwyllys 
438999ebb4caSwyllys 		if (params->keylength % 8 != 0) {
439099ebb4caSwyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
439199ebb4caSwyllys 			goto out;
439299ebb4caSwyllys 		}
439399ebb4caSwyllys 
439499ebb4caSwyllys 		if (params->keytype == KMF_AES) {
439599ebb4caSwyllys 			if (params->keylength != 128 &&
439699ebb4caSwyllys 			    params->keylength != 192 &&
439799ebb4caSwyllys 			    params->keylength != 256) {
439899ebb4caSwyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
439999ebb4caSwyllys 				goto out;
440099ebb4caSwyllys 			}
440199ebb4caSwyllys 		}
440299ebb4caSwyllys 
440399ebb4caSwyllys 		bytes = params->keylength/8;
440499ebb4caSwyllys 		random = malloc(bytes);
440599ebb4caSwyllys 		if (random == NULL) {
440699ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
440799ebb4caSwyllys 			goto out;
440899ebb4caSwyllys 		}
440999ebb4caSwyllys 		if (RAND_bytes(random, bytes) != 1) {
441099ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
441199ebb4caSwyllys 			goto out;
441299ebb4caSwyllys 		}
441399ebb4caSwyllys 
441499ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)random;
441599ebb4caSwyllys 		rkey->keydata.len = bytes;
441699ebb4caSwyllys 		symkey->keyalg = params->keytype;
441799ebb4caSwyllys 
441899ebb4caSwyllys 	} else {
441999ebb4caSwyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
442099ebb4caSwyllys 		goto out;
442199ebb4caSwyllys 	}
442299ebb4caSwyllys 
442399ebb4caSwyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
442499ebb4caSwyllys 
442599ebb4caSwyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
442699ebb4caSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
442799ebb4caSwyllys 	symkey->keylabel = (char *)fullpath;
442899ebb4caSwyllys 	symkey->israw = TRUE;
442999ebb4caSwyllys 	symkey->keyp = rkey;
443099ebb4caSwyllys 
443199ebb4caSwyllys out:
443299ebb4caSwyllys 	if (fd != -1)
443399ebb4caSwyllys 		(void) close(fd);
443499ebb4caSwyllys 
443599ebb4caSwyllys 	if (ret != KMF_OK && fullpath != NULL) {
443699ebb4caSwyllys 		free(fullpath);
443799ebb4caSwyllys 	}
443899ebb4caSwyllys 	if (ret != KMF_OK) {
443999ebb4caSwyllys 		KMF_FreeRawSymKey(rkey);
444099ebb4caSwyllys 		symkey->keyp = NULL;
444199ebb4caSwyllys 		symkey->keyalg = KMF_KEYALG_NONE;
444299ebb4caSwyllys 	}
444399ebb4caSwyllys 
444499ebb4caSwyllys 	return (ret);
444599ebb4caSwyllys }
444699ebb4caSwyllys 
444799ebb4caSwyllys 
444899ebb4caSwyllys KMF_RETURN
444999ebb4caSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, KMF_VERIFYCRL_PARAMS *params)
445099ebb4caSwyllys {
445199ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
445299ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
445399ebb4caSwyllys 	BIO		*bcrl = NULL;
445499ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
445599ebb4caSwyllys 	X509		*xcert = NULL;
445699ebb4caSwyllys 	EVP_PKEY	*pkey;
445799ebb4caSwyllys 	int		sslret;
445899ebb4caSwyllys 	KMF_ENCODE_FORMAT crl_format;
445999ebb4caSwyllys 	unsigned char	*p;
446099ebb4caSwyllys 	long		len;
446199ebb4caSwyllys 
446299ebb4caSwyllys 	if (params->crl_name == NULL || params->tacert == NULL) {
446399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
446499ebb4caSwyllys 	}
446599ebb4caSwyllys 
446699ebb4caSwyllys 	ret = KMF_GetFileFormat(params->crl_name, &crl_format);
446799ebb4caSwyllys 	if (ret != KMF_OK)
446899ebb4caSwyllys 		return (ret);
446999ebb4caSwyllys 
447099ebb4caSwyllys 	bcrl = BIO_new_file(params->crl_name, "rb");
447199ebb4caSwyllys 	if (bcrl == NULL)	{
447299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
447399ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
447499ebb4caSwyllys 		goto cleanup;
447599ebb4caSwyllys 	}
447699ebb4caSwyllys 
447799ebb4caSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
447899ebb4caSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
447999ebb4caSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
448099ebb4caSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
448199ebb4caSwyllys 	} else {
448299ebb4caSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
448399ebb4caSwyllys 		goto cleanup;
448499ebb4caSwyllys 	}
448599ebb4caSwyllys 
448699ebb4caSwyllys 	if (xcrl == NULL) {
448799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
448899ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
448999ebb4caSwyllys 		goto cleanup;
449099ebb4caSwyllys 	}
449199ebb4caSwyllys 
449299ebb4caSwyllys 	p = params->tacert->Data;
449399ebb4caSwyllys 	len = params->tacert->Length;
449499ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
449599ebb4caSwyllys 
449699ebb4caSwyllys 	if (xcert == NULL) {
449799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
449899ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
449999ebb4caSwyllys 		goto cleanup;
450099ebb4caSwyllys 	}
450199ebb4caSwyllys 
450299ebb4caSwyllys 	/* Get issuer certificate public key */
450399ebb4caSwyllys 	pkey = X509_get_pubkey(xcert);
450499ebb4caSwyllys 	if (!pkey) {
450599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
450699ebb4caSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
450799ebb4caSwyllys 		goto cleanup;
450899ebb4caSwyllys 	}
450999ebb4caSwyllys 
451099ebb4caSwyllys 	/* Verify CRL signature */
451199ebb4caSwyllys 	sslret = X509_CRL_verify(xcrl, pkey);
451299ebb4caSwyllys 	EVP_PKEY_free(pkey);
451399ebb4caSwyllys 	if (sslret > 0) {
451499ebb4caSwyllys 		ret = KMF_OK;
451599ebb4caSwyllys 	} else {
451699ebb4caSwyllys 		SET_ERROR(kmfh, sslret);
451799ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
451899ebb4caSwyllys 	}
451999ebb4caSwyllys 
452099ebb4caSwyllys cleanup:
452199ebb4caSwyllys 	if (bcrl != NULL)
452299ebb4caSwyllys 		(void) BIO_free(bcrl);
452399ebb4caSwyllys 
452499ebb4caSwyllys 	if (xcrl != NULL)
452599ebb4caSwyllys 		X509_CRL_free(xcrl);
452699ebb4caSwyllys 
452799ebb4caSwyllys 	if (xcert != NULL)
452899ebb4caSwyllys 		X509_free(xcert);
452999ebb4caSwyllys 
453099ebb4caSwyllys 	return (ret);
453199ebb4caSwyllys 
453299ebb4caSwyllys }
453399ebb4caSwyllys 
453499ebb4caSwyllys KMF_RETURN
453599ebb4caSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle,
453699ebb4caSwyllys 	KMF_CHECKCRLDATE_PARAMS *params)
453799ebb4caSwyllys {
453899ebb4caSwyllys 
453999ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
454099ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
454199ebb4caSwyllys 	KMF_ENCODE_FORMAT crl_format;
454299ebb4caSwyllys 	BIO		*bcrl = NULL;
454399ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
454499ebb4caSwyllys 	int		i;
454599ebb4caSwyllys 
454699ebb4caSwyllys 	if (params == NULL || params->crl_name == NULL) {
454799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
454899ebb4caSwyllys 	}
454999ebb4caSwyllys 
455099ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, params->crl_name, &crl_format);
455199ebb4caSwyllys 	if (ret != KMF_OK)
455299ebb4caSwyllys 		return (ret);
455399ebb4caSwyllys 
455499ebb4caSwyllys 	bcrl = BIO_new_file(params->crl_name, "rb");
455599ebb4caSwyllys 	if (bcrl == NULL)	{
455699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
455799ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
455899ebb4caSwyllys 		goto cleanup;
455999ebb4caSwyllys 	}
456099ebb4caSwyllys 
456199ebb4caSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
456299ebb4caSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
456399ebb4caSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
456499ebb4caSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
456599ebb4caSwyllys 	}
456699ebb4caSwyllys 
456799ebb4caSwyllys 	if (xcrl == NULL) {
456899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
456999ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
457099ebb4caSwyllys 		goto cleanup;
457199ebb4caSwyllys 	}
457299ebb4caSwyllys 
457399ebb4caSwyllys 	i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL);
457499ebb4caSwyllys 	if (i >= 0) {
457599ebb4caSwyllys 		ret = KMF_ERR_VALIDITY_PERIOD;
457699ebb4caSwyllys 		goto cleanup;
457799ebb4caSwyllys 	}
457899ebb4caSwyllys 
457999ebb4caSwyllys 	if (X509_CRL_get_nextUpdate(xcrl)) {
458099ebb4caSwyllys 		i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL);
458199ebb4caSwyllys 
458299ebb4caSwyllys 		if (i <= 0) {
458399ebb4caSwyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
458499ebb4caSwyllys 			goto cleanup;
458599ebb4caSwyllys 		}
458699ebb4caSwyllys 	}
458799ebb4caSwyllys 
458899ebb4caSwyllys 	ret = KMF_OK;
458999ebb4caSwyllys 
459099ebb4caSwyllys cleanup:
459199ebb4caSwyllys 	if (bcrl != NULL)
459299ebb4caSwyllys 		(void) BIO_free(bcrl);
459399ebb4caSwyllys 
459499ebb4caSwyllys 	if (xcrl != NULL)
459599ebb4caSwyllys 		X509_CRL_free(xcrl);
459699ebb4caSwyllys 
459799ebb4caSwyllys 	return (ret);
459899ebb4caSwyllys }
459999ebb4caSwyllys 
460099ebb4caSwyllys /*
460199ebb4caSwyllys  * Check a file to see if it is a CRL file with PEM or DER format.
460299ebb4caSwyllys  * If success, return its format in the "pformat" argument.
460399ebb4caSwyllys  */
460499ebb4caSwyllys KMF_RETURN
460599ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
460699ebb4caSwyllys {
460799ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
460899ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
460999ebb4caSwyllys 	BIO		*bio = NULL;
461099ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
461199ebb4caSwyllys 
461299ebb4caSwyllys 	if (filename == NULL) {
461399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
461499ebb4caSwyllys 	}
461599ebb4caSwyllys 
461699ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
461799ebb4caSwyllys 	if (bio == NULL)	{
461899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
461999ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
462099ebb4caSwyllys 		goto out;
462199ebb4caSwyllys 	}
462299ebb4caSwyllys 
462399ebb4caSwyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
462499ebb4caSwyllys 		*pformat = KMF_FORMAT_PEM;
462599ebb4caSwyllys 		goto out;
462699ebb4caSwyllys 	}
462799ebb4caSwyllys 	(void) BIO_free(bio);
462899ebb4caSwyllys 
462999ebb4caSwyllys 	/*
463099ebb4caSwyllys 	 * Now try to read it as raw DER data.
463199ebb4caSwyllys 	 */
463299ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
463399ebb4caSwyllys 	if (bio == NULL)	{
463499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
463599ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
463699ebb4caSwyllys 		goto out;
463799ebb4caSwyllys 	}
463899ebb4caSwyllys 
463999ebb4caSwyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
464099ebb4caSwyllys 		*pformat = KMF_FORMAT_ASN1;
464199ebb4caSwyllys 	} else {
464299ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
464399ebb4caSwyllys 	}
464499ebb4caSwyllys 
464599ebb4caSwyllys out:
464699ebb4caSwyllys 	if (bio != NULL)
464799ebb4caSwyllys 		(void) BIO_free(bio);
464899ebb4caSwyllys 
464999ebb4caSwyllys 	if (xcrl != NULL)
465099ebb4caSwyllys 		X509_CRL_free(xcrl);
465199ebb4caSwyllys 
465299ebb4caSwyllys 	return (ret);
465399ebb4caSwyllys }
465499ebb4caSwyllys 
465599ebb4caSwyllys /*
465699ebb4caSwyllys  * Check a file to see if it is a certficate file with PEM or DER format.
465799ebb4caSwyllys  * If success, return its format in the pformat argument.
465899ebb4caSwyllys  */
465999ebb4caSwyllys KMF_RETURN
466099ebb4caSwyllys OpenSSL_IsCertFile(KMF_HANDLE_T handle, char *filename,
466199ebb4caSwyllys 	KMF_ENCODE_FORMAT *pformat)
466299ebb4caSwyllys {
466399ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
466499ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
466599ebb4caSwyllys 	BIO		*bio = NULL;
466699ebb4caSwyllys 	X509		*xcert = NULL;
466799ebb4caSwyllys 
466899ebb4caSwyllys 	if (filename == NULL) {
466999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
467099ebb4caSwyllys 	}
467199ebb4caSwyllys 
467299ebb4caSwyllys 	ret = KMF_GetFileFormat(filename, pformat);
467399ebb4caSwyllys 	if (ret != KMF_OK)
467499ebb4caSwyllys 		return (ret);
467599ebb4caSwyllys 
467699ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
467799ebb4caSwyllys 	if (bio == NULL)	{
467899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
467999ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
468099ebb4caSwyllys 		goto out;
468199ebb4caSwyllys 	}
468299ebb4caSwyllys 
468399ebb4caSwyllys 	if ((*pformat) == KMF_FORMAT_PEM) {
468499ebb4caSwyllys 		if ((xcert = PEM_read_bio_X509(bio, NULL,
468599ebb4caSwyllys 		    NULL, NULL)) == NULL) {
468699ebb4caSwyllys 			ret = KMF_ERR_BAD_CERTFILE;
468799ebb4caSwyllys 		}
468899ebb4caSwyllys 	} else if ((*pformat) == KMF_FORMAT_ASN1) {
468999ebb4caSwyllys 		if ((xcert = d2i_X509_bio(bio, NULL)) == NULL) {
469099ebb4caSwyllys 			ret = KMF_ERR_BAD_CERTFILE;
469199ebb4caSwyllys 		}
469299ebb4caSwyllys 	} else {
469399ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
469499ebb4caSwyllys 	}
469599ebb4caSwyllys 
469699ebb4caSwyllys out:
469799ebb4caSwyllys 	if (bio != NULL)
469899ebb4caSwyllys 		(void) BIO_free(bio);
469999ebb4caSwyllys 
470099ebb4caSwyllys 	if (xcert != NULL)
470199ebb4caSwyllys 		X509_free(xcert);
470299ebb4caSwyllys 
470399ebb4caSwyllys 	return (ret);
470499ebb4caSwyllys }
470599ebb4caSwyllys 
470699ebb4caSwyllys KMF_RETURN
470799ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
470899ebb4caSwyllys     KMF_RAW_SYM_KEY *rkey)
470999ebb4caSwyllys {
471099ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
471199ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
471299ebb4caSwyllys 	KMF_DATA	keyvalue;
471399ebb4caSwyllys 
471499ebb4caSwyllys 	if (kmfh == NULL)
471599ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
471699ebb4caSwyllys 
471799ebb4caSwyllys 	if (symkey == NULL || rkey == NULL)
471899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
471999ebb4caSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
472099ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
472199ebb4caSwyllys 
472299ebb4caSwyllys 	if (symkey->israw) {
472399ebb4caSwyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
472499ebb4caSwyllys 
472599ebb4caSwyllys 		if (rawkey == NULL ||
472699ebb4caSwyllys 		    rawkey->keydata.val == NULL ||
472799ebb4caSwyllys 		    rawkey->keydata.len == 0)
472899ebb4caSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
472999ebb4caSwyllys 
473099ebb4caSwyllys 		rkey->keydata.len = rawkey->keydata.len;
473199ebb4caSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
473299ebb4caSwyllys 			return (KMF_ERR_MEMORY);
473399ebb4caSwyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
473499ebb4caSwyllys 		    rkey->keydata.len);
473599ebb4caSwyllys 	} else {
473699ebb4caSwyllys 		rv = KMF_ReadInputFile(handle, symkey->keylabel, &keyvalue);
473799ebb4caSwyllys 		if (rv != KMF_OK)
473899ebb4caSwyllys 			return (rv);
473999ebb4caSwyllys 		rkey->keydata.len = keyvalue.Length;
474099ebb4caSwyllys 		rkey->keydata.val = keyvalue.Data;
474199ebb4caSwyllys 	}
474299ebb4caSwyllys 
474399ebb4caSwyllys 	return (rv);
474499ebb4caSwyllys }
474502744e81Swyllys 
474602744e81Swyllys /*
474702744e81Swyllys  * id-sha1    OBJECT IDENTIFIER ::= {
474802744e81Swyllys  *     iso(1) identified-organization(3) oiw(14) secsig(3)
474902744e81Swyllys  *     algorithms(2) 26
475002744e81Swyllys  * }
475102744e81Swyllys  */
475202744e81Swyllys #define	ASN1_SHA1_OID_PREFIX_LEN 15
475302744e81Swyllys static uchar_t SHA1_DER_PREFIX[ASN1_SHA1_OID_PREFIX_LEN] = {
475402744e81Swyllys 	0x30, 0x21, 0x30, 0x09,
475502744e81Swyllys 	0x06, 0x05, 0x2b, 0x0e,
475602744e81Swyllys 	0x03, 0x02, 0x1a, 0x05,
475702744e81Swyllys 	0x00, 0x04, 0x14
475802744e81Swyllys };
475902744e81Swyllys 
476002744e81Swyllys /*
476102744e81Swyllys  * id-md2 OBJECT IDENTIFIER ::= {
476202744e81Swyllys  *     iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2
476302744e81Swyllys  * }
476402744e81Swyllys  */
476502744e81Swyllys #define	ASN1_MD2_OID_PREFIX_LEN 18
476602744e81Swyllys static uchar_t MD2_DER_PREFIX[ASN1_MD2_OID_PREFIX_LEN] = {
476702744e81Swyllys 	0x30, 0x20, 0x30, 0x0c,
476802744e81Swyllys 	0x06, 0x08, 0x2a, 0x86,
476902744e81Swyllys 	0x48, 0x86, 0xf7, 0x0d,
477002744e81Swyllys 	0x02, 0x02, 0x05, 0x00,
477102744e81Swyllys 	0x04, 0x10
477202744e81Swyllys };
477302744e81Swyllys 
477402744e81Swyllys /*
477502744e81Swyllys  * id-md5 OBJECT IDENTIFIER ::= {
477602744e81Swyllys  *     iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5
477702744e81Swyllys  * }
477802744e81Swyllys  */
477902744e81Swyllys #define	ASN1_MD5_OID_PREFIX_LEN 18
478002744e81Swyllys static uchar_t MD5_DER_PREFIX[ASN1_MD5_OID_PREFIX_LEN] = {
478102744e81Swyllys 	0x30, 0x20, 0x30, 0x0c,
478202744e81Swyllys 	0x06, 0x08, 0x2a, 0x86,
478302744e81Swyllys 	0x48, 0x86, 0xf7, 0x0d,
478402744e81Swyllys 	0x02, 0x05, 0x05, 0x00,
478502744e81Swyllys 	0x04, 0x10
478602744e81Swyllys };
478702744e81Swyllys 
478802744e81Swyllys KMF_RETURN
478902744e81Swyllys OpenSSL_VerifyDataWithCert(KMF_HANDLE_T handle,
479002744e81Swyllys 	KMF_ALGORITHM_INDEX algid, KMF_DATA *indata,
479102744e81Swyllys 	KMF_DATA *insig, KMF_DATA *cert)
479202744e81Swyllys {
479302744e81Swyllys 	KMF_RETURN ret = KMF_OK;
479402744e81Swyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
479502744e81Swyllys 	X509	*xcert = NULL;
479602744e81Swyllys 	EVP_PKEY *pkey = NULL;
479702744e81Swyllys 	uchar_t *p;
479802744e81Swyllys 	uchar_t *rsaout = NULL;
479902744e81Swyllys 	uchar_t *pfx = NULL;
480002744e81Swyllys 	const EVP_MD *md;
480102744e81Swyllys 	int pfxlen = 0, len;
480202744e81Swyllys 
480302744e81Swyllys 	if (handle == NULL || indata == NULL ||
480402744e81Swyllys 	    indata->Data == NULL || indata->Length == 0 ||
480502744e81Swyllys 	    insig == NULL|| insig->Data == NULL || insig->Length == 0 ||
480602744e81Swyllys 	    cert == NULL || cert->Data == NULL || cert->Length == 0)
480702744e81Swyllys 		return (KMF_ERR_BAD_PARAMETER);
480802744e81Swyllys 
480902744e81Swyllys 	p = cert->Data;
481002744e81Swyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, cert->Length);
481102744e81Swyllys 	if (xcert == NULL) {
481202744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
481302744e81Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
481402744e81Swyllys 		goto cleanup;
481502744e81Swyllys 	}
481602744e81Swyllys 
481702744e81Swyllys 	pkey = X509_get_pubkey(xcert);
481802744e81Swyllys 	if (!pkey) {
481902744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
482002744e81Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
482102744e81Swyllys 		goto cleanup;
482202744e81Swyllys 	}
482302744e81Swyllys 
482402744e81Swyllys 	if (algid != KMF_ALGID_NONE) {
482502744e81Swyllys 		switch (algid) {
482602744e81Swyllys 			case KMF_ALGID_MD5WithRSA:
482702744e81Swyllys 				md = EVP_md5();
482802744e81Swyllys 				break;
482902744e81Swyllys 			case KMF_ALGID_MD2WithRSA:
483002744e81Swyllys 				md = EVP_md2();
483102744e81Swyllys 				break;
483202744e81Swyllys 			case KMF_ALGID_SHA1WithRSA:
483302744e81Swyllys 				md = EVP_sha1();
483402744e81Swyllys 				break;
483502744e81Swyllys 			case KMF_ALGID_RSA:
483602744e81Swyllys 				md = NULL;
483702744e81Swyllys 				break;
483802744e81Swyllys 			default:
483902744e81Swyllys 				ret = KMF_ERR_BAD_PARAMETER;
484002744e81Swyllys 				goto cleanup;
484102744e81Swyllys 		}
484202744e81Swyllys 	} else {
484302744e81Swyllys 		/* Get the hash type from the cert signature */
484402744e81Swyllys 		md = EVP_get_digestbyobj(xcert->sig_alg->algorithm);
484502744e81Swyllys 		if (md == NULL) {
484602744e81Swyllys 			SET_ERROR(kmfh, ERR_get_error());
484702744e81Swyllys 			ret = KMF_ERR_BAD_PARAMETER;
484802744e81Swyllys 			goto cleanup;
484902744e81Swyllys 		}
485002744e81Swyllys 	}
48519b37d296Swyllys 	if (md != NULL) {
485202744e81Swyllys 		switch (EVP_MD_type(md)) {
485302744e81Swyllys 		case NID_md2:
485402744e81Swyllys 		case NID_md2WithRSAEncryption:
485502744e81Swyllys 			pfxlen = ASN1_MD2_OID_PREFIX_LEN;
485602744e81Swyllys 			pfx = MD2_DER_PREFIX;
485702744e81Swyllys 			break;
485802744e81Swyllys 		case NID_md5:
485902744e81Swyllys 		case NID_md5WithRSAEncryption:
486002744e81Swyllys 			pfxlen = ASN1_MD5_OID_PREFIX_LEN;
486102744e81Swyllys 			pfx = MD5_DER_PREFIX;
486202744e81Swyllys 			break;
486302744e81Swyllys 		case NID_sha1:
486402744e81Swyllys 		case NID_sha1WithRSAEncryption:
486502744e81Swyllys 			pfxlen = ASN1_SHA1_OID_PREFIX_LEN;
486602744e81Swyllys 			pfx = SHA1_DER_PREFIX;
486702744e81Swyllys 			break;
486802744e81Swyllys 		default: /* Unsupported */
486902744e81Swyllys 			pfxlen = 0;
487002744e81Swyllys 			pfx = NULL;
487102744e81Swyllys 			break;
487202744e81Swyllys 		}
48739b37d296Swyllys 	}
487402744e81Swyllys 
487502744e81Swyllys 	/* RSA with no hash is a special case */
487602744e81Swyllys 	rsaout = malloc(RSA_size(pkey->pkey.rsa));
487702744e81Swyllys 	if (rsaout == NULL)
487802744e81Swyllys 		return (KMF_ERR_MEMORY);
487902744e81Swyllys 
488002744e81Swyllys 	/* Decrypt the input signature */
488102744e81Swyllys 	len = RSA_public_decrypt(insig->Length,
488202744e81Swyllys 	    insig->Data, rsaout, pkey->pkey.rsa, RSA_PKCS1_PADDING);
488302744e81Swyllys 	if (len < 1) {
488402744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
488502744e81Swyllys 		ret = KMF_ERR_BAD_PARAMETER;
488602744e81Swyllys 	} else {
488702744e81Swyllys 		size_t hashlen = 0;
488802744e81Swyllys 		uint32_t dlen;
488902744e81Swyllys 		char *digest = NULL;
489002744e81Swyllys 
489102744e81Swyllys 		/*
489202744e81Swyllys 		 * If the AlgId requires it, hash the input data before
489302744e81Swyllys 		 * comparing it to the decrypted signature.
489402744e81Swyllys 		 */
489502744e81Swyllys 		if (md) {
489602744e81Swyllys 			EVP_MD_CTX ctx;
489702744e81Swyllys 
489802744e81Swyllys 			hashlen = md->md_size;
489902744e81Swyllys 
490002744e81Swyllys 			digest = malloc(hashlen + pfxlen);
490102744e81Swyllys 			if (digest == NULL)
490202744e81Swyllys 				return (KMF_ERR_MEMORY);
490302744e81Swyllys 			/* Add the prefix to the comparison buffer. */
490402744e81Swyllys 			if (pfx && pfxlen > 0) {
490502744e81Swyllys 				(void) memcpy(digest, pfx, pfxlen);
490602744e81Swyllys 			}
490702744e81Swyllys 			(void) EVP_DigestInit(&ctx, md);
490802744e81Swyllys 			(void) EVP_DigestUpdate(&ctx, indata->Data,
490902744e81Swyllys 			    indata->Length);
491002744e81Swyllys 
491102744e81Swyllys 			/* Add the digest AFTER the ASN1 prefix */
491202744e81Swyllys 			(void) EVP_DigestFinal(&ctx,
491302744e81Swyllys 			    (uchar_t *)digest + pfxlen, &dlen);
491402744e81Swyllys 
491502744e81Swyllys 			dlen += pfxlen;
491602744e81Swyllys 		} else {
491702744e81Swyllys 			digest = (char *)indata->Data;
491802744e81Swyllys 			dlen = indata->Length;
491902744e81Swyllys 		}
492002744e81Swyllys 
492102744e81Swyllys 		/*
492202744e81Swyllys 		 * The result of the RSA decryption should be ASN1(OID | Hash).
492302744e81Swyllys 		 * Compare the output hash to the input data for the final
492402744e81Swyllys 		 * result.
492502744e81Swyllys 		 */
492602744e81Swyllys 		if (memcmp(rsaout, digest, dlen))
492702744e81Swyllys 			ret = KMF_ERR_INTERNAL;
492802744e81Swyllys 		else
492902744e81Swyllys 			ret = KMF_OK;
493002744e81Swyllys 
493102744e81Swyllys 		/* If we had to allocate space for the digest, free it now */
493202744e81Swyllys 		if (hashlen)
493302744e81Swyllys 			free(digest);
493402744e81Swyllys 	}
493502744e81Swyllys cleanup:
493602744e81Swyllys 	if (pkey)
493702744e81Swyllys 		EVP_PKEY_free(pkey);
493802744e81Swyllys 
493902744e81Swyllys 	if (xcert)
494002744e81Swyllys 		X509_free(xcert);
494102744e81Swyllys 
494202744e81Swyllys 	if (rsaout)
494302744e81Swyllys 		free(rsaout);
494402744e81Swyllys 
494502744e81Swyllys 	return (ret);
494602744e81Swyllys }
4947