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,
67571593db2Swyllys 			(uchar_t *)NULL, 0, NULL,
67671593db2Swyllys 			&certs, &nc);
67771593db2Swyllys 	} else {
67871593db2Swyllys 		return (KMF_ERR_ENCODING);
67971593db2Swyllys 	}
68071593db2Swyllys 
68171593db2Swyllys 	if (rv != KMF_OK)
68271593db2Swyllys 		return (rv);
68371593db2Swyllys 
68471593db2Swyllys 	for (i = 0; i < nc; i++) {
68571593db2Swyllys 		if (params->find_cert_validity == KMF_NONEXPIRED_CERTS) {
68671593db2Swyllys 			rv = KMF_CheckCertDate(kmfh, &certs[i]);
68771593db2Swyllys 		} else if (params->find_cert_validity == KMF_EXPIRED_CERTS) {
68871593db2Swyllys 			rv = KMF_CheckCertDate(kmfh, &certs[i]);
68971593db2Swyllys 			if (rv == KMF_OK)
69071593db2Swyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
69171593db2Swyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD)
69271593db2Swyllys 				rv = KMF_OK;
69371593db2Swyllys 		}
69471593db2Swyllys 		if (rv != KMF_OK) {
69571593db2Swyllys 			/* Remove this cert from the list by clearing it. */
69671593db2Swyllys 			KMF_FreeData(&certs[i]);
69771593db2Swyllys 		} else {
69871593db2Swyllys 			hits++; /* count valid certs found */
69971593db2Swyllys 		}
70071593db2Swyllys 		rv = KMF_OK;
70171593db2Swyllys 	}
70271593db2Swyllys 	if (rv == KMF_OK && hits == 0) {
70371593db2Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
70471593db2Swyllys 	} else if (rv == KMF_OK && hits > 0) {
70571593db2Swyllys 		/*
70671593db2Swyllys 		 * Sort the list of certs by length to put the cleared ones
70771593db2Swyllys 		 * at the end so they don't get accessed by the caller.
70871593db2Swyllys 		 */
70971593db2Swyllys 		qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
71071593db2Swyllys 		*certlist = certs;
71171593db2Swyllys 
71271593db2Swyllys 		/* since we sorted the list, just return the number of hits */
71371593db2Swyllys 		*numcerts = hits;
71471593db2Swyllys 	}
71571593db2Swyllys 	return (rv);
71671593db2Swyllys }
71771593db2Swyllys 
71899ebb4caSwyllys static KMF_RETURN
71999ebb4caSwyllys kmf_load_cert(KMF_HANDLE *kmfh,
72099ebb4caSwyllys 	KMF_FINDCERT_PARAMS *params,
72199ebb4caSwyllys 	char *pathname,
72299ebb4caSwyllys 	KMF_DATA *cert)
72399ebb4caSwyllys {
72499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
72599ebb4caSwyllys 	X509 *x509cert = NULL;
72699ebb4caSwyllys 
72799ebb4caSwyllys 	rv = load_X509cert(kmfh, params, pathname, &x509cert);
72899ebb4caSwyllys 	if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
72999ebb4caSwyllys 		rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
73099ebb4caSwyllys 		if (rv != KMF_OK) {
73199ebb4caSwyllys 			goto cleanup;
73299ebb4caSwyllys 		}
73399ebb4caSwyllys 		if (params->find_cert_validity == KMF_NONEXPIRED_CERTS) {
73499ebb4caSwyllys 			rv = KMF_CheckCertDate(kmfh, cert);
73599ebb4caSwyllys 		} else if (params->find_cert_validity == KMF_EXPIRED_CERTS) {
73699ebb4caSwyllys 			rv = KMF_CheckCertDate(kmfh, cert);
73799ebb4caSwyllys 			if (rv == KMF_OK)  {
73899ebb4caSwyllys 				/*
73999ebb4caSwyllys 				 * This is a valid cert so skip it.
74099ebb4caSwyllys 				 */
74199ebb4caSwyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
74299ebb4caSwyllys 			}
74399ebb4caSwyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD) {
74499ebb4caSwyllys 				/*
74599ebb4caSwyllys 				 * We want to return success when we
74699ebb4caSwyllys 				 * find an invalid cert.
74799ebb4caSwyllys 				 */
74899ebb4caSwyllys 				rv = KMF_OK;
74999ebb4caSwyllys 				goto cleanup;
75099ebb4caSwyllys 			}
75199ebb4caSwyllys 		}
75299ebb4caSwyllys 	}
75399ebb4caSwyllys cleanup:
75499ebb4caSwyllys 	if (x509cert != NULL)
75599ebb4caSwyllys 		X509_free(x509cert);
75699ebb4caSwyllys 
75799ebb4caSwyllys 	return (rv);
75899ebb4caSwyllys }
75999ebb4caSwyllys 
76002744e81Swyllys static KMF_RETURN
76102744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
76202744e81Swyllys {
76302744e81Swyllys 	KMF_RETURN ret = KMF_OK;
76402744e81Swyllys 	KMF_RAW_RSA_KEY rsa;
76502744e81Swyllys 	BerElement *asn1 = NULL;
76602744e81Swyllys 	BerValue filebuf;
76702744e81Swyllys 	BerValue OID = { NULL, 0 };
76802744e81Swyllys 	BerValue *Mod = NULL, *PubExp = NULL;
76902744e81Swyllys 	BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
77002744e81Swyllys 	BerValue *Coef = NULL;
77102744e81Swyllys 	BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
77202744e81Swyllys 	BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
77302744e81Swyllys 	BIGNUM *qminus1 = NULL;
77402744e81Swyllys 	BN_CTX *ctx = NULL;
77502744e81Swyllys 
77602744e81Swyllys 	*pkey = NULL;
77702744e81Swyllys 
77802744e81Swyllys 	filebuf.bv_val = (char *)filedata->Data;
77902744e81Swyllys 	filebuf.bv_len = filedata->Length;
78002744e81Swyllys 
78102744e81Swyllys 	asn1 = kmfder_init(&filebuf);
78202744e81Swyllys 	if (asn1 == NULL) {
78302744e81Swyllys 		ret = KMF_ERR_MEMORY;
78402744e81Swyllys 		goto out;
78502744e81Swyllys 	}
78602744e81Swyllys 
78702744e81Swyllys 	if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
78802744e81Swyllys 		&OID, &Mod, &PubExp, &PriExp, &Prime1,
78902744e81Swyllys 		&Prime2, &Coef) == -1)  {
79002744e81Swyllys 		ret = KMF_ERR_ENCODING;
79102744e81Swyllys 		goto out;
79202744e81Swyllys 	}
79302744e81Swyllys 
79402744e81Swyllys 	/*
79502744e81Swyllys 	 * We have to derive the 2 Exponents using Bignumber math.
79602744e81Swyllys 	 * Exp1 = PriExp mod (Prime1 - 1)
79702744e81Swyllys 	 * Exp2 = PriExp mod (Prime2 - 1)
79802744e81Swyllys 	 */
79902744e81Swyllys 
80002744e81Swyllys 	/* D = PrivateExponent */
80102744e81Swyllys 	D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
80202744e81Swyllys 	if (D == NULL) {
80302744e81Swyllys 		ret = KMF_ERR_MEMORY;
80402744e81Swyllys 		goto out;
80502744e81Swyllys 	}
80602744e81Swyllys 
80702744e81Swyllys 	/* P = Prime1 (first prime factor of Modulus) */
80802744e81Swyllys 	P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
80902744e81Swyllys 	if (D == NULL) {
81002744e81Swyllys 		ret = KMF_ERR_MEMORY;
81102744e81Swyllys 		goto out;
81202744e81Swyllys 	}
81302744e81Swyllys 
81402744e81Swyllys 	/* Q = Prime2 (second prime factor of Modulus) */
81502744e81Swyllys 	Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
81602744e81Swyllys 
81702744e81Swyllys 	if ((ctx = BN_CTX_new()) == NULL) {
81802744e81Swyllys 		ret = KMF_ERR_MEMORY;
81902744e81Swyllys 		goto out;
82002744e81Swyllys 	}
82102744e81Swyllys 
82202744e81Swyllys 	/* Compute (P - 1) */
82302744e81Swyllys 	pminus1 = BN_new();
82402744e81Swyllys 	(void) BN_sub(pminus1, P, BN_value_one());
82502744e81Swyllys 
82602744e81Swyllys 	/* Exponent1 = D mod (P - 1) */
82702744e81Swyllys 	Exp1 = BN_new();
82802744e81Swyllys 	(void) BN_mod(Exp1, D, pminus1, ctx);
82902744e81Swyllys 
83002744e81Swyllys 	/* Compute (Q - 1) */
83102744e81Swyllys 	qminus1 = BN_new();
83202744e81Swyllys 	(void) BN_sub(qminus1, Q, BN_value_one());
83302744e81Swyllys 
83402744e81Swyllys 	/* Exponent2 = D mod (Q - 1) */
83502744e81Swyllys 	Exp2 = BN_new();
83602744e81Swyllys 	(void) BN_mod(Exp2, D, qminus1, ctx);
83702744e81Swyllys 
83802744e81Swyllys 	/* Coef = (Inverse Q) mod P */
83902744e81Swyllys 	COEF = BN_new();
84002744e81Swyllys 	(void) BN_mod_inverse(COEF, Q, P, ctx);
84102744e81Swyllys 
84202744e81Swyllys 	/* Convert back to KMF format */
84302744e81Swyllys 	(void) memset(&rsa, 0, sizeof (rsa));
84402744e81Swyllys 
84502744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
84602744e81Swyllys 		goto out;
84702744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
84802744e81Swyllys 		goto out;
84902744e81Swyllys 	if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
85002744e81Swyllys 		goto out;
85102744e81Swyllys 
85202744e81Swyllys 	rsa.mod.val = (uchar_t *)Mod->bv_val;
85302744e81Swyllys 	rsa.mod.len = Mod->bv_len;
85402744e81Swyllys 
85502744e81Swyllys 	rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
85602744e81Swyllys 	rsa.pubexp.len = PubExp->bv_len;
85702744e81Swyllys 
85802744e81Swyllys 	rsa.priexp.val = (uchar_t *)PriExp->bv_val;
85902744e81Swyllys 	rsa.priexp.len = PriExp->bv_len;
86002744e81Swyllys 
86102744e81Swyllys 	rsa.prime1.val = (uchar_t *)Prime1->bv_val;
86202744e81Swyllys 	rsa.prime1.len = Prime1->bv_len;
86302744e81Swyllys 
86402744e81Swyllys 	rsa.prime2.val = (uchar_t *)Prime2->bv_val;
86502744e81Swyllys 	rsa.prime2.len = Prime2->bv_len;
86602744e81Swyllys 
86702744e81Swyllys 	*pkey = ImportRawRSAKey(&rsa);
86802744e81Swyllys out:
86902744e81Swyllys 	if (asn1 != NULL)
87002744e81Swyllys 		kmfber_free(asn1, 1);
87102744e81Swyllys 
87202744e81Swyllys 	if (OID.bv_val) {
87302744e81Swyllys 		free(OID.bv_val);
87402744e81Swyllys 	}
87502744e81Swyllys 	if (PriExp)
87602744e81Swyllys 		free(PriExp);
87702744e81Swyllys 
87802744e81Swyllys 	if (Mod)
87902744e81Swyllys 		free(Mod);
88002744e81Swyllys 
88102744e81Swyllys 	if (PubExp)
88202744e81Swyllys 		free(PubExp);
88302744e81Swyllys 
88402744e81Swyllys 	if (Coef) {
88502744e81Swyllys 		(void) memset(Coef->bv_val, 0, Coef->bv_len);
88602744e81Swyllys 		free(Coef->bv_val);
88702744e81Swyllys 		free(Coef);
88802744e81Swyllys 	}
88902744e81Swyllys 	if (Prime1)
89002744e81Swyllys 		free(Prime1);
89102744e81Swyllys 	if (Prime2)
89202744e81Swyllys 		free(Prime2);
89302744e81Swyllys 
89402744e81Swyllys 	if (ctx != NULL)
89502744e81Swyllys 		BN_CTX_free(ctx);
89602744e81Swyllys 
89702744e81Swyllys 	if (D)
89802744e81Swyllys 		BN_clear_free(D);
89902744e81Swyllys 	if (P)
90002744e81Swyllys 		BN_clear_free(P);
90102744e81Swyllys 	if (Q)
90202744e81Swyllys 		BN_clear_free(Q);
90302744e81Swyllys 	if (pminus1)
90402744e81Swyllys 		BN_clear_free(pminus1);
90502744e81Swyllys 	if (qminus1)
90602744e81Swyllys 		BN_clear_free(qminus1);
90702744e81Swyllys 	if (Exp1)
90802744e81Swyllys 		BN_clear_free(Exp1);
90902744e81Swyllys 	if (Exp2)
91002744e81Swyllys 		BN_clear_free(Exp2);
91102744e81Swyllys 
91202744e81Swyllys 	return (ret);
91302744e81Swyllys 
91402744e81Swyllys }
91502744e81Swyllys 
91699ebb4caSwyllys static EVP_PKEY *
91799ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file)
91899ebb4caSwyllys {
91999ebb4caSwyllys 	BIO *keyfile = NULL;
92099ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
92199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
92299ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
92302744e81Swyllys 	KMF_RETURN rv;
92402744e81Swyllys 	KMF_DATA filedata;
92599ebb4caSwyllys 
92699ebb4caSwyllys 	if (file == NULL) {
92799ebb4caSwyllys 		return (NULL);
92899ebb4caSwyllys 	}
92999ebb4caSwyllys 
93099ebb4caSwyllys 	if (KMF_GetFileFormat((char *)file, &format) != KMF_OK)
93199ebb4caSwyllys 		return (NULL);
93299ebb4caSwyllys 
93399ebb4caSwyllys 	keyfile = BIO_new_file(file, "rb");
93499ebb4caSwyllys 	if (keyfile == NULL) {
93599ebb4caSwyllys 		goto end;
93699ebb4caSwyllys 	}
93799ebb4caSwyllys 
93802744e81Swyllys 	if (format == KMF_FORMAT_ASN1) {
93999ebb4caSwyllys 		pkey = d2i_PrivateKey_bio(keyfile, NULL);
94002744e81Swyllys 		if (pkey == NULL) {
94102744e81Swyllys 
94202744e81Swyllys 			(void) BIO_free(keyfile);
94302744e81Swyllys 			keyfile = NULL;
94402744e81Swyllys 			/* Try odd ASN.1 variations */
94502744e81Swyllys 			rv = KMF_ReadInputFile(kmfh, (char *)file,
94602744e81Swyllys 				&filedata);
94702744e81Swyllys 			if (rv == KMF_OK) {
94802744e81Swyllys 				(void) readAltFormatPrivateKey(&filedata,
94902744e81Swyllys 					&pkey);
95002744e81Swyllys 				KMF_FreeData(&filedata);
95102744e81Swyllys 			}
95202744e81Swyllys 		}
95302744e81Swyllys 	} else if (format == KMF_FORMAT_PEM ||
95402744e81Swyllys 		format == KMF_FORMAT_PEM_KEYPAIR) {
95599ebb4caSwyllys 		pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
95602744e81Swyllys 		if (pkey == NULL) {
95702744e81Swyllys 			KMF_DATA derdata;
95802744e81Swyllys 			/*
95902744e81Swyllys 			 * Check if this is the alt. format
96002744e81Swyllys 			 * RSA private key file.
96102744e81Swyllys 			 */
96202744e81Swyllys 			rv = KMF_ReadInputFile(kmfh, (char *)file,
96302744e81Swyllys 				&filedata);
96402744e81Swyllys 			if (rv == KMF_OK) {
96502744e81Swyllys 				uchar_t *d = NULL;
96602744e81Swyllys 				int len;
96702744e81Swyllys 				rv = KMF_Pem2Der(filedata.Data,
96802744e81Swyllys 					filedata.Length, &d, &len);
96902744e81Swyllys 				if (rv == KMF_OK && d != NULL) {
97002744e81Swyllys 					derdata.Data = d;
97102744e81Swyllys 					derdata.Length = (size_t)len;
97202744e81Swyllys 					(void) readAltFormatPrivateKey(
97302744e81Swyllys 						&derdata, &pkey);
97402744e81Swyllys 					free(d);
97502744e81Swyllys 				}
97602744e81Swyllys 				KMF_FreeData(&filedata);
97702744e81Swyllys 			}
97802744e81Swyllys 		}
97902744e81Swyllys 	}
98099ebb4caSwyllys 
98199ebb4caSwyllys end:
98299ebb4caSwyllys 	if (pkey == NULL)
98399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
98499ebb4caSwyllys 
98599ebb4caSwyllys 	if (keyfile != NULL)
98699ebb4caSwyllys 		(void) BIO_free(keyfile);
98799ebb4caSwyllys 
98899ebb4caSwyllys 	return (pkey);
98999ebb4caSwyllys }
99099ebb4caSwyllys 
99199ebb4caSwyllys KMF_RETURN
99299ebb4caSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle,
99399ebb4caSwyllys 	KMF_FINDCERT_PARAMS *params,
99499ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert,
99599ebb4caSwyllys 	uint32_t *num_certs)
99699ebb4caSwyllys {
99799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
99899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
99999ebb4caSwyllys 	char *fullpath;
1000f482c776Swyllys 	int i, n;
1001f482c776Swyllys 	uint32_t maxcerts = 0;
100299ebb4caSwyllys 
100399ebb4caSwyllys 	if (num_certs == NULL || params == NULL)
100499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
100599ebb4caSwyllys 
1006f482c776Swyllys 	maxcerts = *num_certs;
1007f482c776Swyllys 	if (maxcerts == 0)
1008f482c776Swyllys 		maxcerts = 0xFFFFFFFF;
100999ebb4caSwyllys 	*num_certs = 0;
101099ebb4caSwyllys 
101199ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
101299ebb4caSwyllys 		params->sslparms.certfile);
101399ebb4caSwyllys 
101499ebb4caSwyllys 	if (fullpath == NULL)
101599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
101699ebb4caSwyllys 
101799ebb4caSwyllys 	if (isdir(fullpath)) {
101899ebb4caSwyllys 		DIR *dirp;
101999ebb4caSwyllys 		struct dirent *dp;
102099ebb4caSwyllys 
1021f482c776Swyllys 		n = 0;
102299ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
102399ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
102499ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
102599ebb4caSwyllys 		}
102699ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
102799ebb4caSwyllys 			char *fname;
102871593db2Swyllys 			KMF_DATA *certlist = NULL;
1029f482c776Swyllys 			uint32_t loaded_certs = 0;
103071593db2Swyllys 
103199ebb4caSwyllys 			if (strcmp(dp->d_name, ".") == 0 ||
103299ebb4caSwyllys 			    strcmp(dp->d_name, "..") == 0)
103399ebb4caSwyllys 				continue;
103499ebb4caSwyllys 
103599ebb4caSwyllys 			fname = get_fullpath(fullpath,
103699ebb4caSwyllys 				(char *)&dp->d_name);
103799ebb4caSwyllys 
103871593db2Swyllys 			rv = load_certs(kmfh, params, fname, &certlist,
1039f482c776Swyllys 				&loaded_certs);
104099ebb4caSwyllys 
104199ebb4caSwyllys 			if (rv != KMF_OK) {
104299ebb4caSwyllys 				free(fname);
104371593db2Swyllys 				if (certlist != NULL) {
1044f482c776Swyllys 					for (i = 0; i < loaded_certs; i++)
104571593db2Swyllys 						KMF_FreeData(&certlist[i]);
104671593db2Swyllys 					free(certlist);
104771593db2Swyllys 				}
104899ebb4caSwyllys 				continue;
104999ebb4caSwyllys 			}
105099ebb4caSwyllys 
105199ebb4caSwyllys 			/* If load succeeds, add certdata to the list */
105299ebb4caSwyllys 			if (kmf_cert != NULL) {
1053f482c776Swyllys 				for (i = 0; i < loaded_certs &&
1054*b4058258Swyllys 				    n < maxcerts; i++) {
105571593db2Swyllys 					kmf_cert[n].certificate.Data =
105671593db2Swyllys 						certlist[i].Data;
105799ebb4caSwyllys 					kmf_cert[n].certificate.Length =
105871593db2Swyllys 						certlist[i].Length;
105999ebb4caSwyllys 
106099ebb4caSwyllys 					kmf_cert[n].kmf_private.keystore_type =
106199ebb4caSwyllys 						KMF_KEYSTORE_OPENSSL;
106299ebb4caSwyllys 					kmf_cert[n].kmf_private.flags =
106399ebb4caSwyllys 						KMF_FLAG_CERT_VALID;
106471593db2Swyllys 					kmf_cert[n].kmf_private.label =
106571593db2Swyllys 						strdup(fname);
106699ebb4caSwyllys 					n++;
106799ebb4caSwyllys 				}
1068*b4058258Swyllys 				/*
1069*b4058258Swyllys 				 * If maxcerts < loaded_certs, clean up the
1070*b4058258Swyllys 				 * certs that were not used.
1071*b4058258Swyllys 				 */
1072f482c776Swyllys 				for (; i < loaded_certs; i++)
107371593db2Swyllys 					KMF_FreeData(&certlist[i]);
1074f482c776Swyllys 			} else {
1075f482c776Swyllys 				for (i = 0; i < loaded_certs; i++)
1076f482c776Swyllys 					KMF_FreeData(&certlist[i]);
1077f482c776Swyllys 				n += loaded_certs;
107871593db2Swyllys 			}
1079f482c776Swyllys 			free(certlist);
108071593db2Swyllys 			free(fname);
108171593db2Swyllys 		}
108299ebb4caSwyllys 		(*num_certs) = n;
108399ebb4caSwyllys 		if (*num_certs == 0)
108499ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
1085f482c776Swyllys 		else
108699ebb4caSwyllys 			rv = KMF_OK;
108799ebb4caSwyllys exit:
108899ebb4caSwyllys 		(void) closedir(dirp);
108999ebb4caSwyllys 	} else {
109071593db2Swyllys 		KMF_DATA *certlist = NULL;
1091f482c776Swyllys 		uint32_t loaded_certs = 0;
109271593db2Swyllys 
1093f482c776Swyllys 		rv = load_certs(kmfh, params, fullpath,
1094f482c776Swyllys 			&certlist, &loaded_certs);
109599ebb4caSwyllys 		if (rv != KMF_OK) {
109699ebb4caSwyllys 			free(fullpath);
109799ebb4caSwyllys 			return (rv);
109899ebb4caSwyllys 		}
109999ebb4caSwyllys 
1100f482c776Swyllys 		n = 0;
110171593db2Swyllys 		if (kmf_cert != NULL && certlist != NULL) {
1102f482c776Swyllys 			for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1103f482c776Swyllys 				kmf_cert[n].certificate.Data =
110471593db2Swyllys 					certlist[i].Data;
1105f482c776Swyllys 				kmf_cert[n].certificate.Length =
110671593db2Swyllys 					certlist[i].Length;
1107f482c776Swyllys 				kmf_cert[n].kmf_private.keystore_type =
110899ebb4caSwyllys 					KMF_KEYSTORE_OPENSSL;
1109f482c776Swyllys 				kmf_cert[n].kmf_private.flags =
111071593db2Swyllys 					KMF_FLAG_CERT_VALID;
1111f482c776Swyllys 				kmf_cert[n].kmf_private.label =
111271593db2Swyllys 					strdup(fullpath);
1113f482c776Swyllys 				n++;
111471593db2Swyllys 			}
1115f482c776Swyllys 			/* If maxcerts < loaded_certs, clean up */
1116f482c776Swyllys 			for (; i < loaded_certs; i++)
111771593db2Swyllys 				KMF_FreeData(&certlist[i]);
1118f482c776Swyllys 		} else if (certlist != NULL) {
1119f482c776Swyllys 			for (i = 0; i < loaded_certs; i++)
1120f482c776Swyllys 				KMF_FreeData(&certlist[i]);
1121f482c776Swyllys 			n = loaded_certs;
1122f482c776Swyllys 		}
1123f482c776Swyllys 		if (certlist)
112471593db2Swyllys 			free(certlist);
1125f482c776Swyllys 
1126f482c776Swyllys 		*num_certs = n;
112799ebb4caSwyllys 	}
112899ebb4caSwyllys 
112999ebb4caSwyllys 	free(fullpath);
113099ebb4caSwyllys 
113199ebb4caSwyllys 	return (rv);
113299ebb4caSwyllys }
113399ebb4caSwyllys 
113499ebb4caSwyllys void
113599ebb4caSwyllys /*ARGSUSED*/
113699ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
113799ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert)
113899ebb4caSwyllys {
113999ebb4caSwyllys 	if (kmf_cert != NULL) {
114099ebb4caSwyllys 		if (kmf_cert->certificate.Data != NULL) {
114199ebb4caSwyllys 			free(kmf_cert->certificate.Data);
114299ebb4caSwyllys 			kmf_cert->certificate.Data = NULL;
114399ebb4caSwyllys 			kmf_cert->certificate.Length = 0;
114499ebb4caSwyllys 		}
114599ebb4caSwyllys 		if (kmf_cert->kmf_private.label)
114699ebb4caSwyllys 			free(kmf_cert->kmf_private.label);
114799ebb4caSwyllys 	}
114899ebb4caSwyllys }
114999ebb4caSwyllys 
115099ebb4caSwyllys KMF_RETURN
115199ebb4caSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, KMF_STORECERT_PARAMS *params,
115299ebb4caSwyllys     KMF_DATA * pcert)
115399ebb4caSwyllys {
115499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
115599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
115699ebb4caSwyllys 	X509 *xcert = NULL;
115799ebb4caSwyllys 	FILE *fp;
115899ebb4caSwyllys 	unsigned char *outbuf;
115999ebb4caSwyllys 	unsigned char *outbuf_p;
116099ebb4caSwyllys 	char *fullpath;
116199ebb4caSwyllys 	int outbuflen;
116299ebb4caSwyllys 	int len;
116399ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
116499ebb4caSwyllys 
116599ebb4caSwyllys 	if (params == NULL || params->ks_opt_u.openssl_opts.certfile == NULL) {
116699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
116799ebb4caSwyllys 	}
116899ebb4caSwyllys 
116999ebb4caSwyllys 	/*
117099ebb4caSwyllys 	 * check if the cert output format is supported by OPENSSL.
117199ebb4caSwyllys 	 * however, since the keystore for OPENSSL is just a file, we have
117299ebb4caSwyllys 	 * no way to store the format along with the file.
117399ebb4caSwyllys 	 */
117499ebb4caSwyllys 	format = params->sslparms.format;
117599ebb4caSwyllys 	if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM)
117699ebb4caSwyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
117799ebb4caSwyllys 
117899ebb4caSwyllys 
117999ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
118099ebb4caSwyllys 		params->sslparms.certfile);
118199ebb4caSwyllys 	if (fullpath == NULL)
118299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
118399ebb4caSwyllys 
118499ebb4caSwyllys 	/*
118599ebb4caSwyllys 	 * When storing a certificate, you must specify a filename.
118699ebb4caSwyllys 	 */
118799ebb4caSwyllys 	if (isdir(fullpath)) {
118899ebb4caSwyllys 		free(fullpath);
118999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
119099ebb4caSwyllys 	}
119199ebb4caSwyllys 
119299ebb4caSwyllys 	/* copy cert data to outbuf */
119399ebb4caSwyllys 	outbuflen = pcert->Length;
119499ebb4caSwyllys 	outbuf = malloc(outbuflen);
119599ebb4caSwyllys 	if (outbuf == NULL) {
119699ebb4caSwyllys 		free(fullpath);
119799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
119899ebb4caSwyllys 	}
119999ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
120099ebb4caSwyllys 
120199ebb4caSwyllys 	if ((fp = fopen(fullpath, "w")) ==
120299ebb4caSwyllys 		NULL) {
120399ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
120499ebb4caSwyllys 		ret = KMF_ERR_INTERNAL;
120599ebb4caSwyllys 		goto out;
120699ebb4caSwyllys 	}
120799ebb4caSwyllys 
120899ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
120999ebb4caSwyllys 		len = fwrite(outbuf, 1, outbuflen, fp);
121099ebb4caSwyllys 		if (len != outbuflen) {
121199ebb4caSwyllys 			SET_SYS_ERROR(kmfh, errno);
121299ebb4caSwyllys 			ret = KMF_ERR_WRITE_FILE;
121399ebb4caSwyllys 		} else {
121499ebb4caSwyllys 			ret = KMF_OK;
121599ebb4caSwyllys 		}
121699ebb4caSwyllys 		goto out;
121799ebb4caSwyllys 	}
121899ebb4caSwyllys 
121999ebb4caSwyllys 	/*
122099ebb4caSwyllys 	 * The output format is not KMF_FORMAT_ASN1, so we will
122199ebb4caSwyllys 	 * Convert the cert data to OpenSSL internal X509 first.
122299ebb4caSwyllys 	 */
122399ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
122499ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, outbuflen);
122599ebb4caSwyllys 	if (xcert == NULL) {
122699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
122799ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
122899ebb4caSwyllys 		goto out;
122999ebb4caSwyllys 	}
123099ebb4caSwyllys 
123199ebb4caSwyllys 	if (format == KMF_FORMAT_PEM) {
123299ebb4caSwyllys 		/* Convert to the PEM format and write it out */
123399ebb4caSwyllys 		if (!PEM_write_X509(fp, xcert)) {
123499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
123599ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
123699ebb4caSwyllys 		} else {
123799ebb4caSwyllys 			ret = KMF_OK;
123899ebb4caSwyllys 		}
123999ebb4caSwyllys 		goto out;
124099ebb4caSwyllys 	}
124199ebb4caSwyllys 
124299ebb4caSwyllys out:
124399ebb4caSwyllys 	if (fullpath != NULL)
124499ebb4caSwyllys 		free(fullpath);
124599ebb4caSwyllys 
124699ebb4caSwyllys 	if (outbuf != NULL) {
124799ebb4caSwyllys 		free(outbuf);
124899ebb4caSwyllys 	}
124999ebb4caSwyllys 	if (fp != NULL) {
125099ebb4caSwyllys 		(void) fclose(fp);
125199ebb4caSwyllys 	}
125299ebb4caSwyllys 
125399ebb4caSwyllys 	if (xcert != NULL) {
125499ebb4caSwyllys 		X509_free(xcert);
125599ebb4caSwyllys 	}
125699ebb4caSwyllys 
125799ebb4caSwyllys 	return (ret);
125899ebb4caSwyllys }
125999ebb4caSwyllys 
126099ebb4caSwyllys KMF_RETURN
126199ebb4caSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, KMF_DELETECERT_PARAMS *params)
126299ebb4caSwyllys {
126399ebb4caSwyllys 	KMF_RETURN rv;
126499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
126599ebb4caSwyllys 	char *fullpath = NULL;
126699ebb4caSwyllys 	KMF_DATA certdata = {NULL, 0};
126799ebb4caSwyllys 
126899ebb4caSwyllys 	if (params == NULL) {
126999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
127099ebb4caSwyllys 	}
127199ebb4caSwyllys 
127299ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
127399ebb4caSwyllys 		params->sslparms.certfile);
127499ebb4caSwyllys 
127599ebb4caSwyllys 	if (fullpath == NULL)
127699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
127799ebb4caSwyllys 
127899ebb4caSwyllys 	if (isdir(fullpath)) {
127999ebb4caSwyllys 		DIR *dirp;
128099ebb4caSwyllys 		struct dirent *dp;
128199ebb4caSwyllys 
128299ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
128399ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
128499ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
128599ebb4caSwyllys 		}
128699ebb4caSwyllys 
128799ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
128899ebb4caSwyllys 			if (strcmp(dp->d_name, ".") != 0 &&
128999ebb4caSwyllys 			    strcmp(dp->d_name, "..") != 0) {
129099ebb4caSwyllys 				char *fname;
129199ebb4caSwyllys 
129299ebb4caSwyllys 				fname = get_fullpath(fullpath,
129399ebb4caSwyllys 					(char *)&dp->d_name);
129499ebb4caSwyllys 
129599ebb4caSwyllys 				if (fname == NULL) {
129699ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
129799ebb4caSwyllys 					break;
129899ebb4caSwyllys 				}
129999ebb4caSwyllys 
130099ebb4caSwyllys 				rv = kmf_load_cert(kmfh, params, fname,
130199ebb4caSwyllys 				    &certdata);
130299ebb4caSwyllys 
130399ebb4caSwyllys 				if (rv == KMF_ERR_CERT_NOT_FOUND) {
130499ebb4caSwyllys 					free(fname);
130599ebb4caSwyllys 					if (certdata.Data)
130699ebb4caSwyllys 						free(certdata.Data);
130799ebb4caSwyllys 					rv = KMF_OK;
130899ebb4caSwyllys 					continue;
130999ebb4caSwyllys 				} else if (rv != KMF_OK) {
131099ebb4caSwyllys 					free(fname);
131199ebb4caSwyllys 					break;
131299ebb4caSwyllys 				}
131399ebb4caSwyllys 
131499ebb4caSwyllys 				if (unlink(fname) != 0) {
131599ebb4caSwyllys 					SET_SYS_ERROR(kmfh, errno);
131699ebb4caSwyllys 					rv = KMF_ERR_INTERNAL;
131799ebb4caSwyllys 					free(fname);
131899ebb4caSwyllys 					break;
131999ebb4caSwyllys 				}
132099ebb4caSwyllys 				free(fname);
132199ebb4caSwyllys 				if (certdata.Data)
132299ebb4caSwyllys 					free(certdata.Data);
132399ebb4caSwyllys 			}
132499ebb4caSwyllys 		}
132599ebb4caSwyllys 		(void) closedir(dirp);
132699ebb4caSwyllys 	} else {
132799ebb4caSwyllys 		/* Just try to load a single certificate */
132899ebb4caSwyllys 		rv = kmf_load_cert(kmfh, params, fullpath, &certdata);
132999ebb4caSwyllys 		if (rv == KMF_OK) {
133099ebb4caSwyllys 			if (unlink(fullpath) != 0) {
133199ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
133299ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
133399ebb4caSwyllys 			}
133499ebb4caSwyllys 		}
133599ebb4caSwyllys 	}
133699ebb4caSwyllys 
133799ebb4caSwyllys out:
133899ebb4caSwyllys 	if (fullpath != NULL)
133999ebb4caSwyllys 		free(fullpath);
134099ebb4caSwyllys 
134199ebb4caSwyllys 	if (certdata.Data)
134299ebb4caSwyllys 		free(certdata.Data);
134399ebb4caSwyllys 
134499ebb4caSwyllys 	return (rv);
134599ebb4caSwyllys }
134699ebb4caSwyllys 
134799ebb4caSwyllys KMF_RETURN
134899ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
134999ebb4caSwyllys 	KMF_DATA *keydata)
135099ebb4caSwyllys {
135199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
135299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
135399ebb4caSwyllys 	int n;
135499ebb4caSwyllys 
135599ebb4caSwyllys 	if (key == NULL || keydata == NULL ||
135699ebb4caSwyllys 	    key->keyp == NULL)
135799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
135899ebb4caSwyllys 
135999ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
136099ebb4caSwyllys 		RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
136199ebb4caSwyllys 
136299ebb4caSwyllys 		if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
136399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
136499ebb4caSwyllys 			return (KMF_ERR_ENCODING);
136599ebb4caSwyllys 		}
136699ebb4caSwyllys 		RSA_free(pubkey);
136799ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
136899ebb4caSwyllys 		DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
136999ebb4caSwyllys 
137099ebb4caSwyllys 		if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
137199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
137299ebb4caSwyllys 			return (KMF_ERR_ENCODING);
137399ebb4caSwyllys 		}
137499ebb4caSwyllys 		DSA_free(pubkey);
137599ebb4caSwyllys 	} else {
137699ebb4caSwyllys 	    return (KMF_ERR_BAD_PARAMETER);
137799ebb4caSwyllys 	}
137899ebb4caSwyllys 	keydata->Length = n;
137999ebb4caSwyllys 
138099ebb4caSwyllys cleanup:
138199ebb4caSwyllys 	if (rv != KMF_OK) {
138299ebb4caSwyllys 		if (keydata->Data)
138399ebb4caSwyllys 			free(keydata->Data);
138499ebb4caSwyllys 		keydata->Data = NULL;
138599ebb4caSwyllys 		keydata->Length = 0;
138699ebb4caSwyllys 	}
138799ebb4caSwyllys 
138899ebb4caSwyllys 	return (rv);
138999ebb4caSwyllys }
139099ebb4caSwyllys 
139199ebb4caSwyllys static KMF_RETURN
139299ebb4caSwyllys ssl_write_private_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
139399ebb4caSwyllys 	KMF_CREDENTIAL *cred, EVP_PKEY *pkey)
139499ebb4caSwyllys {
139599ebb4caSwyllys 	int rv = 0;
139699ebb4caSwyllys 	RSA *rsa;
139799ebb4caSwyllys 	DSA *dsa;
139899ebb4caSwyllys 
139999ebb4caSwyllys 	switch (format) {
140099ebb4caSwyllys 		case KMF_FORMAT_ASN1:
140199ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
140299ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
140399ebb4caSwyllys 				rv = i2d_RSAPrivateKey_bio(out, rsa);
140499ebb4caSwyllys 				RSA_free(rsa);
140599ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
140699ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
140799ebb4caSwyllys 				rv = i2d_DSAPrivateKey_bio(out, dsa);
140899ebb4caSwyllys 				DSA_free(dsa);
140999ebb4caSwyllys 			}
141099ebb4caSwyllys 			if (rv == 1) {
141199ebb4caSwyllys 				rv = KMF_OK;
141299ebb4caSwyllys 			} else {
141399ebb4caSwyllys 				SET_ERROR(kmfh, rv);
141499ebb4caSwyllys 			}
141599ebb4caSwyllys 			break;
141699ebb4caSwyllys 		case KMF_FORMAT_PEM:
141799ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
141899ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
141999ebb4caSwyllys 				rv = PEM_write_bio_RSAPrivateKey(out,
142099ebb4caSwyllys 					rsa,
142199ebb4caSwyllys 					NULL /* encryption type */,
142299ebb4caSwyllys 					NULL, 0, NULL,
142399ebb4caSwyllys 					cred->cred);
142499ebb4caSwyllys 				RSA_free(rsa);
142599ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
142699ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
142799ebb4caSwyllys 				rv = PEM_write_bio_DSAPrivateKey(out,
142899ebb4caSwyllys 					dsa,
142999ebb4caSwyllys 					NULL /* encryption type */,
143099ebb4caSwyllys 					NULL, 0, NULL,
143199ebb4caSwyllys 					cred->cred);
143299ebb4caSwyllys 				DSA_free(dsa);
143399ebb4caSwyllys 			}
143499ebb4caSwyllys 
143599ebb4caSwyllys 			if (rv == 1) {
143699ebb4caSwyllys 				rv = KMF_OK;
143799ebb4caSwyllys 			} else {
143899ebb4caSwyllys 				SET_ERROR(kmfh, rv);
143999ebb4caSwyllys 			}
144099ebb4caSwyllys 			break;
144199ebb4caSwyllys 
144299ebb4caSwyllys 		default:
144399ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
144499ebb4caSwyllys 	}
144599ebb4caSwyllys 
144699ebb4caSwyllys 	return (rv);
144799ebb4caSwyllys }
144899ebb4caSwyllys 
144999ebb4caSwyllys KMF_RETURN
145099ebb4caSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, KMF_CREATEKEYPAIR_PARAMS *params,
145199ebb4caSwyllys 	KMF_KEY_HANDLE *privkey, KMF_KEY_HANDLE *pubkey)
145299ebb4caSwyllys {
145399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
145499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
145599ebb4caSwyllys 	int format;
145699ebb4caSwyllys 	uint32_t eValue = 0x010001;
145799ebb4caSwyllys 	RSA *sslPrivKey = NULL;
145899ebb4caSwyllys 	DSA *sslDSAKey = NULL;
145999ebb4caSwyllys 	EVP_PKEY *eprikey = NULL;
146099ebb4caSwyllys 	EVP_PKEY *epubkey = NULL;
146199ebb4caSwyllys 	BIO *out = NULL;
146299ebb4caSwyllys 	char *fullpath = NULL;
146399ebb4caSwyllys 
146499ebb4caSwyllys 	if (params == NULL || params->sslparms.keyfile == NULL) {
146599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
146699ebb4caSwyllys 	}
146799ebb4caSwyllys 
146899ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
146999ebb4caSwyllys 			params->sslparms.keyfile);
147099ebb4caSwyllys 
147199ebb4caSwyllys 	if (fullpath == NULL)
147299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
147399ebb4caSwyllys 
147499ebb4caSwyllys 	/* If the requested file exists, return an error */
147599ebb4caSwyllys 	if (access(fullpath, F_OK) == 0) {
147699ebb4caSwyllys 		free(fullpath);
147799ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
147899ebb4caSwyllys 	}
147999ebb4caSwyllys 
148099ebb4caSwyllys 	eprikey = EVP_PKEY_new();
148199ebb4caSwyllys 	if (eprikey == NULL) {
148299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
148399ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
148499ebb4caSwyllys 		goto cleanup;
148599ebb4caSwyllys 	}
148699ebb4caSwyllys 	epubkey = EVP_PKEY_new();
148799ebb4caSwyllys 	if (epubkey == NULL) {
148899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
148999ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
149099ebb4caSwyllys 		goto cleanup;
149199ebb4caSwyllys 	}
149299ebb4caSwyllys 	if (params->keytype == KMF_RSA) {
149399ebb4caSwyllys 		if (params->rsa_exponent.len > 0 &&
149499ebb4caSwyllys 		    params->rsa_exponent.len <= sizeof (eValue) &&
149599ebb4caSwyllys 		    params->rsa_exponent.val != NULL)
149699ebb4caSwyllys 			/*LINTED*/
149799ebb4caSwyllys 			eValue = *(uint32_t *)params->rsa_exponent.val;
149899ebb4caSwyllys 
149999ebb4caSwyllys 		sslPrivKey = RSA_generate_key(params->keylength, eValue,
150099ebb4caSwyllys 			NULL, NULL);
150199ebb4caSwyllys 		if (sslPrivKey == NULL) {
150299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
150399ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
150499ebb4caSwyllys 		} else {
150599ebb4caSwyllys 			if (privkey != NULL &&
150699ebb4caSwyllys 				EVP_PKEY_set1_RSA(eprikey, sslPrivKey)) {
150799ebb4caSwyllys 				privkey->kstype = KMF_KEYSTORE_OPENSSL;
150899ebb4caSwyllys 				privkey->keyalg = KMF_RSA;
150999ebb4caSwyllys 				privkey->keyclass = KMF_ASYM_PRI;
151099ebb4caSwyllys 				privkey->israw = FALSE;
151199ebb4caSwyllys 				privkey->keylabel = (char *)strdup(fullpath);
151299ebb4caSwyllys 				privkey->keyp = (void *)eprikey;
151399ebb4caSwyllys 			}
151499ebb4caSwyllys 			/* OpenSSL derives the public key from the private */
151599ebb4caSwyllys 			if (pubkey != NULL &&
151699ebb4caSwyllys 				EVP_PKEY_set1_RSA(epubkey, sslPrivKey)) {
151799ebb4caSwyllys 				pubkey->kstype = KMF_KEYSTORE_OPENSSL;
151899ebb4caSwyllys 				pubkey->keyalg = KMF_RSA;
151999ebb4caSwyllys 				pubkey->israw = FALSE;
152099ebb4caSwyllys 				pubkey->keyclass = KMF_ASYM_PUB;
152199ebb4caSwyllys 				pubkey->keylabel = (char *)strdup(fullpath);
152299ebb4caSwyllys 				pubkey->keyp = (void *)epubkey;
152399ebb4caSwyllys 			}
152499ebb4caSwyllys 		}
152599ebb4caSwyllys 	} else if (params->keytype == KMF_DSA) {
152699ebb4caSwyllys 		sslDSAKey = DSA_new();
152799ebb4caSwyllys 		if (sslDSAKey == NULL) {
152899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
152999ebb4caSwyllys 			return (KMF_ERR_MEMORY);
153099ebb4caSwyllys 		}
153199ebb4caSwyllys 
153299ebb4caSwyllys 		if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) ==
153399ebb4caSwyllys 			NULL) {
153499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
153599ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
153699ebb4caSwyllys 			goto cleanup;
153799ebb4caSwyllys 		}
153899ebb4caSwyllys 		if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) ==
153999ebb4caSwyllys 			NULL) {
154099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
154199ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
154299ebb4caSwyllys 			goto cleanup;
154399ebb4caSwyllys 		}
154499ebb4caSwyllys 		if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) ==
154599ebb4caSwyllys 			NULL) {
154699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
154799ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
154899ebb4caSwyllys 			goto cleanup;
154999ebb4caSwyllys 		}
155099ebb4caSwyllys 
155199ebb4caSwyllys 		if (!DSA_generate_key(sslDSAKey)) {
155299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
155399ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
155499ebb4caSwyllys 			goto cleanup;
155599ebb4caSwyllys 		}
155699ebb4caSwyllys 
155799ebb4caSwyllys 		if (privkey != NULL) {
155899ebb4caSwyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
155999ebb4caSwyllys 			privkey->keyalg = KMF_DSA;
156099ebb4caSwyllys 			privkey->keyclass = KMF_ASYM_PRI;
156199ebb4caSwyllys 			privkey->israw = FALSE;
156299ebb4caSwyllys 			privkey->keylabel = (char *)strdup(fullpath);
156399ebb4caSwyllys 			if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
156499ebb4caSwyllys 				privkey->keyp = (void *)eprikey;
156599ebb4caSwyllys 			} else {
156699ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
156799ebb4caSwyllys 				rv = KMF_ERR_KEYGEN_FAILED;
156899ebb4caSwyllys 				goto cleanup;
156999ebb4caSwyllys 			}
157099ebb4caSwyllys 		}
157199ebb4caSwyllys 		if (pubkey != NULL) {
157299ebb4caSwyllys 			DSA *dp = DSA_new();
157399ebb4caSwyllys 			/* Make a copy for the public key */
157499ebb4caSwyllys 			if (dp != NULL) {
157599ebb4caSwyllys 				if ((dp->p = BN_new()) == NULL) {
157699ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
157799ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
157899ebb4caSwyllys 					DSA_free(dp);
157999ebb4caSwyllys 					goto cleanup;
158099ebb4caSwyllys 				}
158199ebb4caSwyllys 				if ((dp->q = BN_new()) == NULL) {
158299ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
158399ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
158499ebb4caSwyllys 					BN_free(dp->p);
158599ebb4caSwyllys 					DSA_free(dp);
158699ebb4caSwyllys 					goto cleanup;
158799ebb4caSwyllys 				}
158899ebb4caSwyllys 				if ((dp->g = BN_new()) == NULL) {
158999ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
159099ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
159199ebb4caSwyllys 					BN_free(dp->q);
159299ebb4caSwyllys 					BN_free(dp->p);
159399ebb4caSwyllys 					DSA_free(dp);
159499ebb4caSwyllys 					goto cleanup;
159599ebb4caSwyllys 				}
159699ebb4caSwyllys 				if ((dp->pub_key = BN_new()) == NULL) {
159799ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
159899ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
159999ebb4caSwyllys 					BN_free(dp->q);
160099ebb4caSwyllys 					BN_free(dp->p);
160199ebb4caSwyllys 					BN_free(dp->g);
160299ebb4caSwyllys 					DSA_free(dp);
160399ebb4caSwyllys 					goto cleanup;
160499ebb4caSwyllys 				}
160599ebb4caSwyllys 				(void) BN_copy(dp->p, sslDSAKey->p);
160699ebb4caSwyllys 				(void) BN_copy(dp->q, sslDSAKey->q);
160799ebb4caSwyllys 				(void) BN_copy(dp->g, sslDSAKey->g);
160899ebb4caSwyllys 				(void) BN_copy(dp->pub_key, sslDSAKey->pub_key);
160999ebb4caSwyllys 
161099ebb4caSwyllys 				pubkey->kstype = KMF_KEYSTORE_OPENSSL;
161199ebb4caSwyllys 				pubkey->keyalg = KMF_DSA;
161299ebb4caSwyllys 				pubkey->keyclass = KMF_ASYM_PUB;
161399ebb4caSwyllys 				pubkey->israw = FALSE;
161499ebb4caSwyllys 				pubkey->keylabel = (char *)strdup(fullpath);
161599ebb4caSwyllys 
161699ebb4caSwyllys 				if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
161799ebb4caSwyllys 					pubkey->keyp = (void *)epubkey;
161899ebb4caSwyllys 				} else {
161999ebb4caSwyllys 					SET_ERROR(kmfh, ERR_get_error());
162099ebb4caSwyllys 					rv = KMF_ERR_KEYGEN_FAILED;
162199ebb4caSwyllys 					goto cleanup;
162299ebb4caSwyllys 				}
162399ebb4caSwyllys 			}
162499ebb4caSwyllys 		}
162599ebb4caSwyllys 	}
162699ebb4caSwyllys 
162799ebb4caSwyllys 	if (rv != KMF_OK) {
162899ebb4caSwyllys 		goto cleanup;
162999ebb4caSwyllys 	}
163099ebb4caSwyllys 
163199ebb4caSwyllys 	/* Store the private key to the keyfile */
163299ebb4caSwyllys 	format = params->sslparms.format;
163399ebb4caSwyllys 	out = BIO_new_file(fullpath, "wb");
163499ebb4caSwyllys 	if (out == NULL) {
163599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
163699ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
163799ebb4caSwyllys 		goto cleanup;
163899ebb4caSwyllys 	}
163999ebb4caSwyllys 	rv = ssl_write_private_key(kmfh, format, out, &params->cred, eprikey);
164099ebb4caSwyllys 
164199ebb4caSwyllys cleanup:
164299ebb4caSwyllys 	if (rv != KMF_OK) {
164399ebb4caSwyllys 		if (eprikey != NULL)
164499ebb4caSwyllys 			EVP_PKEY_free(eprikey);
164599ebb4caSwyllys 
164699ebb4caSwyllys 		if (epubkey != NULL)
164799ebb4caSwyllys 			EVP_PKEY_free(epubkey);
164899ebb4caSwyllys 
164999ebb4caSwyllys 		if (pubkey->keylabel) {
165099ebb4caSwyllys 			free(pubkey->keylabel);
165199ebb4caSwyllys 			pubkey->keylabel = NULL;
165299ebb4caSwyllys 		}
165399ebb4caSwyllys 
165499ebb4caSwyllys 		if (privkey->keylabel) {
165599ebb4caSwyllys 			free(privkey->keylabel);
165699ebb4caSwyllys 			privkey->keylabel = NULL;
165799ebb4caSwyllys 		}
165899ebb4caSwyllys 
165999ebb4caSwyllys 		pubkey->keyp = NULL;
166099ebb4caSwyllys 		privkey->keyp = NULL;
166199ebb4caSwyllys 	}
166299ebb4caSwyllys 
166399ebb4caSwyllys 	if (sslPrivKey)
166499ebb4caSwyllys 		RSA_free(sslPrivKey);
166599ebb4caSwyllys 
166699ebb4caSwyllys 	if (sslDSAKey)
166799ebb4caSwyllys 		DSA_free(sslDSAKey);
166899ebb4caSwyllys 
166999ebb4caSwyllys 
167099ebb4caSwyllys 	if (out != NULL)
167199ebb4caSwyllys 		(void) BIO_free(out);
167299ebb4caSwyllys 
167399ebb4caSwyllys 	if (fullpath)
167499ebb4caSwyllys 		free(fullpath);
167599ebb4caSwyllys 
167699ebb4caSwyllys 	/* Protect the file by making it read-only */
167799ebb4caSwyllys 	if (rv == KMF_OK) {
167899ebb4caSwyllys 		(void) chmod(fullpath, 0400);
167999ebb4caSwyllys 	}
168099ebb4caSwyllys 	return (rv);
168199ebb4caSwyllys }
168299ebb4caSwyllys 
168399ebb4caSwyllys KMF_RETURN
168499ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
168599ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
168699ebb4caSwyllys {
168799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
168899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
168999ebb4caSwyllys 	KMF_ALGORITHM_INDEX		AlgId;
169099ebb4caSwyllys 	EVP_MD_CTX ctx;
169199ebb4caSwyllys 	const EVP_MD *md;
169202744e81Swyllys 
169399ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
169499ebb4caSwyllys 		tobesigned == NULL || output == NULL ||
169599ebb4caSwyllys 		tobesigned->Data == NULL ||
169699ebb4caSwyllys 		output->Data == NULL)
169799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
169899ebb4caSwyllys 
169999ebb4caSwyllys 	/* Map the OID to an OpenSSL algorithm */
170099ebb4caSwyllys 	AlgId = X509_AlgorithmOidToAlgId(AlgOID);
170199ebb4caSwyllys 	if (AlgId == KMF_ALGID_NONE)
170299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
170399ebb4caSwyllys 
170499ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
170599ebb4caSwyllys 		EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
170699ebb4caSwyllys 		uchar_t *p;
170702744e81Swyllys 		int len;
170899ebb4caSwyllys 		if (AlgId == KMF_ALGID_MD5WithRSA)
170999ebb4caSwyllys 			md = EVP_md5();
171099ebb4caSwyllys 		else if (AlgId == KMF_ALGID_MD2WithRSA)
171199ebb4caSwyllys 			md = EVP_md2();
171299ebb4caSwyllys 		else if (AlgId == KMF_ALGID_SHA1WithRSA)
171399ebb4caSwyllys 			md = EVP_sha1();
171402744e81Swyllys 		else if (AlgId == KMF_ALGID_RSA)
171502744e81Swyllys 			md = NULL;
171699ebb4caSwyllys 		else
171799ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
171899ebb4caSwyllys 
171902744e81Swyllys 		if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
172002744e81Swyllys 			RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
172199ebb4caSwyllys 
172202744e81Swyllys 			p = output->Data;
172302744e81Swyllys 			if ((len = RSA_private_encrypt(tobesigned->Length,
172402744e81Swyllys 				tobesigned->Data, p, rsa,
172502744e81Swyllys 				RSA_PKCS1_PADDING)) <= 0) {
172602744e81Swyllys 				SET_ERROR(kmfh, ERR_get_error());
172702744e81Swyllys 				ret = KMF_ERR_INTERNAL;
172802744e81Swyllys 			}
172902744e81Swyllys 			output->Length = len;
173002744e81Swyllys 		} else {
173199ebb4caSwyllys 			(void) EVP_MD_CTX_init(&ctx);
173299ebb4caSwyllys 			(void) EVP_SignInit_ex(&ctx, md, NULL);
173399ebb4caSwyllys 			(void) EVP_SignUpdate(&ctx, tobesigned->Data,
173499ebb4caSwyllys 				(uint32_t)tobesigned->Length);
173599ebb4caSwyllys 			len = (uint32_t)output->Length;
173699ebb4caSwyllys 			p = output->Data;
173702744e81Swyllys 			if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) {
173899ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
173902744e81Swyllys 				len = 0;
174002744e81Swyllys 				ret = KMF_ERR_INTERNAL;
174199ebb4caSwyllys 			}
174299ebb4caSwyllys 			output->Length = len;
174399ebb4caSwyllys 			(void) EVP_MD_CTX_cleanup(&ctx);
174402744e81Swyllys 		}
174599ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
174699ebb4caSwyllys 		DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
174799ebb4caSwyllys 
174899ebb4caSwyllys 		uchar_t hash[EVP_MAX_MD_SIZE];
174999ebb4caSwyllys 		uint32_t hashlen;
175099ebb4caSwyllys 		DSA_SIG *dsasig;
175199ebb4caSwyllys 
175299ebb4caSwyllys 		/*
175399ebb4caSwyllys 		 * OpenSSL EVP_Sign operation automatically converts to
175499ebb4caSwyllys 		 * ASN.1 output so we do the operations separately so we
175599ebb4caSwyllys 		 * are assured of NOT getting ASN.1 output returned.
175699ebb4caSwyllys 		 * KMF does not want ASN.1 encoded results because
175799ebb4caSwyllys 		 * not all mechanisms return ASN.1 encodings (PKCS#11
175899ebb4caSwyllys 		 * and NSS return raw signature data).
175999ebb4caSwyllys 		 */
176099ebb4caSwyllys 		md = EVP_sha1();
176199ebb4caSwyllys 		EVP_MD_CTX_init(&ctx);
176299ebb4caSwyllys 		(void) EVP_DigestInit_ex(&ctx, md, NULL);
176399ebb4caSwyllys 		(void) EVP_DigestUpdate(&ctx, tobesigned->Data,
176499ebb4caSwyllys 			tobesigned->Length);
176599ebb4caSwyllys 		(void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
176699ebb4caSwyllys 		(void) EVP_MD_CTX_cleanup(&ctx);
176799ebb4caSwyllys 
176899ebb4caSwyllys 		dsasig = DSA_do_sign(hash, hashlen, dsa);
176999ebb4caSwyllys 		if (dsasig != NULL) {
177099ebb4caSwyllys 			int i;
177199ebb4caSwyllys 			output->Length = i = BN_bn2bin(dsasig->r, output->Data);
177299ebb4caSwyllys 			output->Length += BN_bn2bin(dsasig->s,
177399ebb4caSwyllys 				&output->Data[i]);
177499ebb4caSwyllys 			DSA_SIG_free(dsasig);
177599ebb4caSwyllys 		} else {
177699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
177799ebb4caSwyllys 		}
177899ebb4caSwyllys 	} else {
177999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
178099ebb4caSwyllys 	}
178199ebb4caSwyllys cleanup:
178299ebb4caSwyllys 	return (ret);
178399ebb4caSwyllys }
178499ebb4caSwyllys 
178599ebb4caSwyllys KMF_RETURN
178699ebb4caSwyllys /*ARGSUSED*/
178799ebb4caSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle, KMF_DELETEKEY_PARAMS *params,
178899ebb4caSwyllys 	KMF_KEY_HANDLE *key, boolean_t destroy)
178999ebb4caSwyllys {
179099ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
179199ebb4caSwyllys 	if (key == NULL || key->keyp == NULL)
179299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
179399ebb4caSwyllys 
179499ebb4caSwyllys 	if (key->keyclass != KMF_ASYM_PUB &&
179599ebb4caSwyllys 		key->keyclass != KMF_ASYM_PRI &&
179699ebb4caSwyllys 		key->keyclass != KMF_SYMMETRIC)
179799ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
179899ebb4caSwyllys 
179999ebb4caSwyllys 	if (key->keyclass == KMF_SYMMETRIC) {
180099ebb4caSwyllys 		KMF_FreeRawSymKey((KMF_RAW_SYM_KEY *)key->keyp);
180199ebb4caSwyllys 		key->keyp = NULL;
180299ebb4caSwyllys 	} else {
180399ebb4caSwyllys 		if (key->keyp != NULL) {
180499ebb4caSwyllys 			EVP_PKEY_free(key->keyp);
180599ebb4caSwyllys 			key->keyp = NULL;
180699ebb4caSwyllys 		}
180799ebb4caSwyllys 	}
180899ebb4caSwyllys 
180999ebb4caSwyllys 	if (key->keylabel != NULL) {
181099ebb4caSwyllys 		EVP_PKEY *pkey = NULL;
181199ebb4caSwyllys 		/* If the file exists, make sure it is a proper key. */
181299ebb4caSwyllys 		pkey = openssl_load_key(handle, key->keylabel);
181399ebb4caSwyllys 		if (pkey == NULL) {
181499ebb4caSwyllys 			free(key->keylabel);
181599ebb4caSwyllys 			key->keylabel = NULL;
181699ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
181799ebb4caSwyllys 		}
181899ebb4caSwyllys 		EVP_PKEY_free(pkey);
181999ebb4caSwyllys 
182099ebb4caSwyllys 		if (destroy) {
182199ebb4caSwyllys 			if (unlink(key->keylabel) != 0) {
182299ebb4caSwyllys 				KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
182399ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
182499ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
182599ebb4caSwyllys 			}
182699ebb4caSwyllys 		}
182799ebb4caSwyllys 		if (key->keylabel != NULL) {
182899ebb4caSwyllys 			free(key->keylabel);
182999ebb4caSwyllys 			key->keylabel = NULL;
183099ebb4caSwyllys 		}
183199ebb4caSwyllys 	}
183299ebb4caSwyllys 	return (rv);
183399ebb4caSwyllys }
183499ebb4caSwyllys 
183599ebb4caSwyllys KMF_RETURN
183699ebb4caSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, KMF_IMPORTCRL_PARAMS *params)
183799ebb4caSwyllys {
183899ebb4caSwyllys 	KMF_RETURN 	ret = KMF_OK;
183999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
184099ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
184199ebb4caSwyllys 	X509		*xcert = NULL;
184299ebb4caSwyllys 	EVP_PKEY	*pkey;
184399ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
184499ebb4caSwyllys 	BIO *in = NULL, *out = NULL;
184599ebb4caSwyllys 	int openssl_ret = 0;
184699ebb4caSwyllys 	char *outcrlfile = NULL;
184799ebb4caSwyllys 	KMF_ENCODE_FORMAT outformat;
184899ebb4caSwyllys 
184999ebb4caSwyllys 	if (params == NULL || params->sslparms.crlfile == NULL) {
185099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
185199ebb4caSwyllys 	}
185299ebb4caSwyllys 
185399ebb4caSwyllys 	if (params->sslparms.crl_check == B_TRUE &&
185499ebb4caSwyllys 	    params->sslparms.certfile == NULL) {
185599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
185699ebb4caSwyllys 	}
185799ebb4caSwyllys 
185899ebb4caSwyllys 	outcrlfile = get_fullpath(params->sslparms.dirpath,
185999ebb4caSwyllys 		params->sslparms.outcrlfile);
186099ebb4caSwyllys 
186199ebb4caSwyllys 	if (outcrlfile == NULL)
186299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
186399ebb4caSwyllys 
186499ebb4caSwyllys 	if (isdir(outcrlfile)) {
186599ebb4caSwyllys 		free(outcrlfile);
186699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
186799ebb4caSwyllys 	}
186899ebb4caSwyllys 
186999ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, params->sslparms.crlfile, &format);
187099ebb4caSwyllys 	if (ret != KMF_OK) {
187199ebb4caSwyllys 		free(outcrlfile);
187299ebb4caSwyllys 		return (ret);
187399ebb4caSwyllys 	}
187499ebb4caSwyllys 
187599ebb4caSwyllys 	in = BIO_new_file(params->sslparms.crlfile, "rb");
187699ebb4caSwyllys 	if (in == NULL)	{
187799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
187899ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
187999ebb4caSwyllys 		goto end;
188099ebb4caSwyllys 	}
188199ebb4caSwyllys 
188299ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
188399ebb4caSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
188499ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
188599ebb4caSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
188699ebb4caSwyllys 	}
188799ebb4caSwyllys 
188899ebb4caSwyllys 	if (xcrl == NULL) {
188999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
189099ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
189199ebb4caSwyllys 		goto end;
189299ebb4caSwyllys 	}
189399ebb4caSwyllys 
189499ebb4caSwyllys 	/* If bypasscheck is specified, no need to verify. */
189599ebb4caSwyllys 	if (params->sslparms.crl_check == B_FALSE) {
189699ebb4caSwyllys 		goto output;
189799ebb4caSwyllys 	}
189899ebb4caSwyllys 
189999ebb4caSwyllys 	ret = KMF_IsCertFile(handle, params->sslparms.certfile, &format);
190099ebb4caSwyllys 	if (ret != KMF_OK)
190199ebb4caSwyllys 		goto end;
190299ebb4caSwyllys 
190399ebb4caSwyllys 	/* Read in the CA cert file and convert to X509 */
190499ebb4caSwyllys 	if (BIO_read_filename(in, params->sslparms.certfile) <= 0) {
190599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
190699ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
190799ebb4caSwyllys 		goto end;
190899ebb4caSwyllys 	}
190999ebb4caSwyllys 
191099ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
191199ebb4caSwyllys 		xcert = d2i_X509_bio(in, NULL);
191299ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
191399ebb4caSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
191499ebb4caSwyllys 	} else {
191599ebb4caSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
191699ebb4caSwyllys 		goto end;
191799ebb4caSwyllys 	}
191899ebb4caSwyllys 
191999ebb4caSwyllys 	if (xcert == NULL) {
192099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
192199ebb4caSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
192299ebb4caSwyllys 		goto end;
192399ebb4caSwyllys 	}
192499ebb4caSwyllys 	/* Now get the public key from the CA cert */
192599ebb4caSwyllys 	pkey = X509_get_pubkey(xcert);
192699ebb4caSwyllys 	if (!pkey) {
192799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
192899ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
192999ebb4caSwyllys 		goto end;
193099ebb4caSwyllys 	}
193199ebb4caSwyllys 
193299ebb4caSwyllys 	/* Verify the CRL with the CA's public key */
193399ebb4caSwyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
193499ebb4caSwyllys 	EVP_PKEY_free(pkey);
193599ebb4caSwyllys 	if (openssl_ret > 0) {
193699ebb4caSwyllys 		ret = KMF_OK;  /* verify succeed */
193799ebb4caSwyllys 	} else {
193899ebb4caSwyllys 		SET_ERROR(kmfh, openssl_ret);
193999ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
194099ebb4caSwyllys 	}
194199ebb4caSwyllys 
194299ebb4caSwyllys output:
194399ebb4caSwyllys 	outformat = params->sslparms.format;
194499ebb4caSwyllys 
194599ebb4caSwyllys 	out = BIO_new_file(outcrlfile, "wb");
194699ebb4caSwyllys 	if (out == NULL) {
194799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
194899ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
194999ebb4caSwyllys 		goto end;
195099ebb4caSwyllys 	}
195199ebb4caSwyllys 
195299ebb4caSwyllys 	if (outformat == KMF_FORMAT_ASN1) {
195399ebb4caSwyllys 		openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
195499ebb4caSwyllys 	} else if (outformat == KMF_FORMAT_PEM) {
195599ebb4caSwyllys 		openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
195699ebb4caSwyllys 	} else {
195799ebb4caSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
195899ebb4caSwyllys 		goto end;
195999ebb4caSwyllys 	}
196099ebb4caSwyllys 
196199ebb4caSwyllys 	if (openssl_ret <= 0) {
196299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
196399ebb4caSwyllys 		ret = KMF_ERR_WRITE_FILE;
196499ebb4caSwyllys 	} else {
196599ebb4caSwyllys 		ret = KMF_OK;
196699ebb4caSwyllys 	}
196799ebb4caSwyllys 
196899ebb4caSwyllys end:
196999ebb4caSwyllys 	if (xcrl != NULL)
197099ebb4caSwyllys 		X509_CRL_free(xcrl);
197199ebb4caSwyllys 
197299ebb4caSwyllys 	if (xcert != NULL)
197399ebb4caSwyllys 		X509_free(xcert);
197499ebb4caSwyllys 
197599ebb4caSwyllys 	if (in != NULL)
197699ebb4caSwyllys 		(void) BIO_free(in);
197799ebb4caSwyllys 
197899ebb4caSwyllys 	if (out != NULL)
197999ebb4caSwyllys 		(void) BIO_free(out);
198099ebb4caSwyllys 
198199ebb4caSwyllys 	if (outcrlfile != NULL)
198299ebb4caSwyllys 		free(outcrlfile);
198399ebb4caSwyllys 
198499ebb4caSwyllys 	return (ret);
198599ebb4caSwyllys }
198699ebb4caSwyllys 
198799ebb4caSwyllys KMF_RETURN
198899ebb4caSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, KMF_LISTCRL_PARAMS *params,
198999ebb4caSwyllys     char **crldata)
199099ebb4caSwyllys {
199199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
199299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
199399ebb4caSwyllys 	X509_CRL   *x = NULL;
199499ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
199599ebb4caSwyllys 	char *crlfile = NULL;
199699ebb4caSwyllys 	BIO *in = NULL;
199799ebb4caSwyllys 	BIO *mem = NULL;
199899ebb4caSwyllys 	long len;
199999ebb4caSwyllys 	char *memptr;
200099ebb4caSwyllys 	char *data = NULL;
200199ebb4caSwyllys 
200299ebb4caSwyllys 	if (params == NULL || params->sslparms.crlfile == NULL) {
200399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
200499ebb4caSwyllys 	}
200599ebb4caSwyllys 
200699ebb4caSwyllys 	crlfile = get_fullpath(params->sslparms.dirpath,
200799ebb4caSwyllys 		params->sslparms.crlfile);
200899ebb4caSwyllys 
200999ebb4caSwyllys 	if (crlfile == NULL)
201099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
201199ebb4caSwyllys 
201299ebb4caSwyllys 	if (isdir(crlfile)) {
201399ebb4caSwyllys 		free(crlfile);
201499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
201599ebb4caSwyllys 	}
201699ebb4caSwyllys 
201799ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, crlfile, &format);
201899ebb4caSwyllys 	if (ret != KMF_OK) {
201999ebb4caSwyllys 		free(crlfile);
202099ebb4caSwyllys 		return (ret);
202199ebb4caSwyllys 	}
202299ebb4caSwyllys 
202399ebb4caSwyllys 	if (bio_err == NULL)
202499ebb4caSwyllys 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
202599ebb4caSwyllys 
202699ebb4caSwyllys 	in = BIO_new_file(crlfile, "rb");
202799ebb4caSwyllys 	if (in == NULL)	{
202899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
202999ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
203099ebb4caSwyllys 		goto end;
203199ebb4caSwyllys 	}
203299ebb4caSwyllys 
203399ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
203499ebb4caSwyllys 		x = d2i_X509_CRL_bio(in, NULL);
203599ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
203699ebb4caSwyllys 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
203799ebb4caSwyllys 	}
203899ebb4caSwyllys 
203999ebb4caSwyllys 	if (x == NULL) { /* should not happen */
204099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
204199ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
204299ebb4caSwyllys 		goto end;
204399ebb4caSwyllys 	}
204499ebb4caSwyllys 
204599ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
204699ebb4caSwyllys 	if (mem == NULL) {
204799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
204899ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
204999ebb4caSwyllys 		goto end;
205099ebb4caSwyllys 	}
205199ebb4caSwyllys 
205299ebb4caSwyllys 	(void) X509_CRL_print(mem, x);
205399ebb4caSwyllys 	len = BIO_get_mem_data(mem, &memptr);
205499ebb4caSwyllys 	if (len <= 0) {
205599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
205699ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
205799ebb4caSwyllys 		goto end;
205899ebb4caSwyllys 	}
205999ebb4caSwyllys 
206099ebb4caSwyllys 	data = malloc(len + 1);
206199ebb4caSwyllys 	if (data == NULL) {
206299ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
206399ebb4caSwyllys 		goto end;
206499ebb4caSwyllys 	}
206599ebb4caSwyllys 
206699ebb4caSwyllys 	(void) memcpy(data, memptr, len);
206799ebb4caSwyllys 	data[len] = '\0';
206899ebb4caSwyllys 	*crldata = data;
206999ebb4caSwyllys 
207099ebb4caSwyllys end:
207199ebb4caSwyllys 	if (x != NULL)
207299ebb4caSwyllys 		X509_CRL_free(x);
207399ebb4caSwyllys 
207499ebb4caSwyllys 	if (crlfile != NULL)
207599ebb4caSwyllys 		free(crlfile);
207699ebb4caSwyllys 
207799ebb4caSwyllys 	if (in != NULL)
207899ebb4caSwyllys 		(void) BIO_free(in);
207999ebb4caSwyllys 
208099ebb4caSwyllys 	if (mem != NULL)
208199ebb4caSwyllys 		(void) BIO_free(mem);
208299ebb4caSwyllys 
208399ebb4caSwyllys 	return (ret);
208499ebb4caSwyllys }
208599ebb4caSwyllys 
208699ebb4caSwyllys KMF_RETURN
208799ebb4caSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, KMF_DELETECRL_PARAMS *params)
208899ebb4caSwyllys {
208999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
209099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
209199ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
209299ebb4caSwyllys 	char *crlfile = NULL;
209399ebb4caSwyllys 	BIO *in = NULL;
209499ebb4caSwyllys 
209599ebb4caSwyllys 	if (params == NULL || params->sslparms.crlfile == NULL) {
209699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
209799ebb4caSwyllys 	}
209899ebb4caSwyllys 
209999ebb4caSwyllys 	crlfile = get_fullpath(params->sslparms.dirpath,
210099ebb4caSwyllys 		params->sslparms.crlfile);
210199ebb4caSwyllys 
210299ebb4caSwyllys 	if (crlfile == NULL)
210399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
210499ebb4caSwyllys 
210599ebb4caSwyllys 	if (isdir(crlfile)) {
210699ebb4caSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
210799ebb4caSwyllys 		goto end;
210899ebb4caSwyllys 	}
210999ebb4caSwyllys 
211099ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, crlfile, &format);
211199ebb4caSwyllys 	if (ret != KMF_OK)
211299ebb4caSwyllys 		goto end;
211399ebb4caSwyllys 
211499ebb4caSwyllys 	if (unlink(crlfile) != 0) {
211599ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
211699ebb4caSwyllys 		ret = KMF_ERR_INTERNAL;
211799ebb4caSwyllys 		goto end;
211899ebb4caSwyllys 	}
211999ebb4caSwyllys 
212099ebb4caSwyllys end:
212199ebb4caSwyllys 	if (in != NULL)
212299ebb4caSwyllys 		(void) BIO_free(in);
212399ebb4caSwyllys 	if (crlfile != NULL)
212499ebb4caSwyllys 		free(crlfile);
212599ebb4caSwyllys 
212699ebb4caSwyllys 	return (ret);
212799ebb4caSwyllys }
212899ebb4caSwyllys 
212999ebb4caSwyllys 
213099ebb4caSwyllys KMF_RETURN
213199ebb4caSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, KMF_FINDCERTINCRL_PARAMS *params)
213299ebb4caSwyllys {
213399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
213499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
213599ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
213699ebb4caSwyllys 	BIO *in = NULL;
213799ebb4caSwyllys 	X509   *xcert = NULL;
213899ebb4caSwyllys 	X509_CRL   *xcrl = NULL;
213999ebb4caSwyllys 	STACK_OF(X509_REVOKED) *revoke_stack = NULL;
214099ebb4caSwyllys 	X509_REVOKED *revoke;
214199ebb4caSwyllys 	int i;
214299ebb4caSwyllys 
214399ebb4caSwyllys 	if (params == NULL || params->sslparms.crlfile == NULL ||
214499ebb4caSwyllys 	    params->sslparms.certfile == NULL) {
214599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
214699ebb4caSwyllys 	}
214799ebb4caSwyllys 
214899ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, params->sslparms.crlfile, &format);
214999ebb4caSwyllys 	if (ret != KMF_OK)
215099ebb4caSwyllys 		return (ret);
215199ebb4caSwyllys 
215299ebb4caSwyllys 	/* Read the CRL file and load it into a X509_CRL structure */
215399ebb4caSwyllys 	in = BIO_new_file(params->sslparms.crlfile, "rb");
215499ebb4caSwyllys 	if (in == NULL)	{
215599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
215699ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
215799ebb4caSwyllys 		goto end;
215899ebb4caSwyllys 	}
215999ebb4caSwyllys 
216099ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
216199ebb4caSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
216299ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
216399ebb4caSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
216499ebb4caSwyllys 	}
216599ebb4caSwyllys 
216699ebb4caSwyllys 	if (xcrl == NULL) {
216799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
216899ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
216999ebb4caSwyllys 		goto end;
217099ebb4caSwyllys 	}
217199ebb4caSwyllys 	(void) BIO_free(in);
217299ebb4caSwyllys 
217399ebb4caSwyllys 	/* Read the Certificate file and load it into a X509 structure */
217499ebb4caSwyllys 	ret = KMF_IsCertFile(handle, params->sslparms.certfile, &format);
217599ebb4caSwyllys 	if (ret != KMF_OK)
217699ebb4caSwyllys 		goto end;
217799ebb4caSwyllys 
217899ebb4caSwyllys 	in = BIO_new_file(params->sslparms.certfile, "rb");
217999ebb4caSwyllys 	if (in == NULL)	{
218099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
218199ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
218299ebb4caSwyllys 		goto end;
218399ebb4caSwyllys 	}
218499ebb4caSwyllys 
218599ebb4caSwyllys 	if (format == KMF_FORMAT_ASN1) {
218699ebb4caSwyllys 		xcert = d2i_X509_bio(in, NULL);
218799ebb4caSwyllys 	} else if (format == KMF_FORMAT_PEM) {
218899ebb4caSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
218999ebb4caSwyllys 	}
219099ebb4caSwyllys 
219199ebb4caSwyllys 	if (xcert == NULL) {
219299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
219399ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
219499ebb4caSwyllys 		goto end;
219599ebb4caSwyllys 	}
219699ebb4caSwyllys 
219799ebb4caSwyllys 	/* Check if the certificate and the CRL have same issuer */
219899ebb4caSwyllys 	if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) {
219999ebb4caSwyllys 		ret = KMF_ERR_ISSUER;
220099ebb4caSwyllys 		goto end;
220199ebb4caSwyllys 	}
220299ebb4caSwyllys 
220399ebb4caSwyllys 	/* Check to see if the certificate serial number is revoked */
220499ebb4caSwyllys 	revoke_stack = X509_CRL_get_REVOKED(xcrl);
220599ebb4caSwyllys 	if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
220699ebb4caSwyllys 		/* No revoked certificates in the CRL file */
220799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
220899ebb4caSwyllys 		ret = KMF_ERR_EMPTY_CRL;
220999ebb4caSwyllys 		goto end;
221099ebb4caSwyllys 	}
221199ebb4caSwyllys 
221299ebb4caSwyllys 	for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
221399ebb4caSwyllys 		/*LINTED*/
221499ebb4caSwyllys 		revoke = sk_X509_REVOKED_value(revoke_stack, i);
221599ebb4caSwyllys 		if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber,
221699ebb4caSwyllys 		    revoke->serialNumber) == 0) {
221799ebb4caSwyllys 			break;
221899ebb4caSwyllys 		}
221999ebb4caSwyllys 	}
222099ebb4caSwyllys 
222199ebb4caSwyllys 	if (i < sk_X509_REVOKED_num(revoke_stack)) {
222299ebb4caSwyllys 		ret = KMF_OK;
222399ebb4caSwyllys 	} else {
222499ebb4caSwyllys 		ret = KMF_ERR_NOT_REVOKED;
222599ebb4caSwyllys 	}
222699ebb4caSwyllys 
222799ebb4caSwyllys end:
222899ebb4caSwyllys 	if (in != NULL)
222999ebb4caSwyllys 		(void) BIO_free(in);
223099ebb4caSwyllys 	if (xcrl != NULL)
223199ebb4caSwyllys 		X509_CRL_free(xcrl);
223299ebb4caSwyllys 	if (xcert != NULL)
223399ebb4caSwyllys 		X509_free(xcert);
223499ebb4caSwyllys 
223599ebb4caSwyllys 	return (ret);
223699ebb4caSwyllys }
223799ebb4caSwyllys 
223899ebb4caSwyllys KMF_RETURN
223999ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
224099ebb4caSwyllys {
224199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
224299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
224399ebb4caSwyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
224499ebb4caSwyllys 
224599ebb4caSwyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
224699ebb4caSwyllys 	if (strlen(str)) {
224799ebb4caSwyllys 		*msgstr = (char *)strdup(str);
224899ebb4caSwyllys 		if ((*msgstr) == NULL)
224999ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
225099ebb4caSwyllys 	} else {
225199ebb4caSwyllys 		*msgstr = NULL;
225299ebb4caSwyllys 	}
225399ebb4caSwyllys 
225499ebb4caSwyllys 	return (ret);
225599ebb4caSwyllys }
225699ebb4caSwyllys 
225799ebb4caSwyllys static int
225899ebb4caSwyllys ext2NID(int kmfext)
225999ebb4caSwyllys {
226099ebb4caSwyllys 	switch (kmfext) {
226199ebb4caSwyllys 		case KMF_X509_EXT_KEY_USAGE:
226299ebb4caSwyllys 			return (NID_key_usage);
226399ebb4caSwyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
226499ebb4caSwyllys 			return (NID_private_key_usage_period);
226599ebb4caSwyllys 		case KMF_X509_EXT_CERT_POLICIES:
226699ebb4caSwyllys 			return (NID_certificate_policies);
226799ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
226899ebb4caSwyllys 			return (NID_subject_alt_name);
226999ebb4caSwyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
227099ebb4caSwyllys 			return (NID_issuer_alt_name);
227199ebb4caSwyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
227299ebb4caSwyllys 			return (NID_basic_constraints);
227399ebb4caSwyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
227499ebb4caSwyllys 			return (NID_ext_key_usage);
227599ebb4caSwyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
227699ebb4caSwyllys 			return (NID_authority_key_identifier);
227799ebb4caSwyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
227899ebb4caSwyllys 			return (NID_crl_distribution_points);
227999ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
228099ebb4caSwyllys 			return (NID_subject_key_identifier);
228199ebb4caSwyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
228299ebb4caSwyllys 			return (OBJ_sn2nid("policyMappings"));
228399ebb4caSwyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
228499ebb4caSwyllys 			return (OBJ_sn2nid("nameConstraints"));
228599ebb4caSwyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
228699ebb4caSwyllys 			return (OBJ_sn2nid("policyConstraints"));
228799ebb4caSwyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
228899ebb4caSwyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
228999ebb4caSwyllys 		case KMF_X509_EXT_FRESHEST_CRL:
229099ebb4caSwyllys 			return (OBJ_sn2nid("freshestCRL"));
229199ebb4caSwyllys 		default:
229299ebb4caSwyllys 			return (NID_undef);
229399ebb4caSwyllys 	}
229499ebb4caSwyllys }
229599ebb4caSwyllys 
229699ebb4caSwyllys KMF_RETURN
229799ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
229899ebb4caSwyllys 	KMF_PRINTABLE_ITEM flag, char *resultStr)
229999ebb4caSwyllys {
230099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
230199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
230299ebb4caSwyllys 	X509 *xcert = NULL;
230399ebb4caSwyllys 	unsigned char *outbuf = NULL;
230499ebb4caSwyllys 	unsigned char *outbuf_p;
230599ebb4caSwyllys 	char *tmpstr = NULL;
230699ebb4caSwyllys 	int j;
230799ebb4caSwyllys 	int ext_index, nid, len;
230899ebb4caSwyllys 	BIO *mem = NULL;
230999ebb4caSwyllys 	STACK *emlst = NULL;
231099ebb4caSwyllys 	X509_EXTENSION *ex;
231199ebb4caSwyllys 	X509_CINF *ci;
231299ebb4caSwyllys 
231399ebb4caSwyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
231499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
231599ebb4caSwyllys 	}
231699ebb4caSwyllys 
231799ebb4caSwyllys 	/* copy cert data to outbuf */
231899ebb4caSwyllys 	outbuf = malloc(pcert->Length);
231999ebb4caSwyllys 	if (outbuf == NULL) {
232099ebb4caSwyllys 		return (KMF_ERR_MEMORY);
232199ebb4caSwyllys 	}
232299ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
232399ebb4caSwyllys 
232499ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
232599ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
232699ebb4caSwyllys 	if (xcert == NULL) {
232799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
232899ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
232999ebb4caSwyllys 		goto out;
233099ebb4caSwyllys 	}
233199ebb4caSwyllys 
233299ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
233399ebb4caSwyllys 	if (mem == NULL) {
233499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
233599ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
233699ebb4caSwyllys 		goto out;
233799ebb4caSwyllys 	}
233899ebb4caSwyllys 
233999ebb4caSwyllys 	switch (flag) {
234099ebb4caSwyllys 	case KMF_CERT_ISSUER:
234199ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
234299ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
234399ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
234499ebb4caSwyllys 		break;
234599ebb4caSwyllys 
234699ebb4caSwyllys 	case KMF_CERT_SUBJECT:
234799ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
234899ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
234999ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
235099ebb4caSwyllys 		break;
235199ebb4caSwyllys 
235299ebb4caSwyllys 	case KMF_CERT_VERSION:
235399ebb4caSwyllys 		tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version);
235499ebb4caSwyllys 		(void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN);
235599ebb4caSwyllys 		OPENSSL_free(tmpstr);
235699ebb4caSwyllys 		len = strlen(resultStr);
235799ebb4caSwyllys 		break;
235899ebb4caSwyllys 
235999ebb4caSwyllys 	case KMF_CERT_SERIALNUM:
236099ebb4caSwyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
236199ebb4caSwyllys 			(void) strcpy(resultStr, "0x");
236299ebb4caSwyllys 			len = BIO_gets(mem, &resultStr[2],
236399ebb4caSwyllys 				KMF_CERT_PRINTABLE_LEN - 2);
236499ebb4caSwyllys 		}
236599ebb4caSwyllys 		break;
236699ebb4caSwyllys 
236799ebb4caSwyllys 	case KMF_CERT_NOTBEFORE:
236899ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notBefore(xcert));
236999ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
237099ebb4caSwyllys 		break;
237199ebb4caSwyllys 
237299ebb4caSwyllys 	case KMF_CERT_NOTAFTER:
237399ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notAfter(xcert));
237499ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
237599ebb4caSwyllys 		break;
237699ebb4caSwyllys 
237799ebb4caSwyllys 	case KMF_CERT_PUBKEY_DATA:
237899ebb4caSwyllys 		{
237999ebb4caSwyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
238099ebb4caSwyllys 			if (pkey == NULL) {
238199ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
238299ebb4caSwyllys 				ret = KMF_ERR_ENCODING;
238399ebb4caSwyllys 				goto out;
238499ebb4caSwyllys 			}
238599ebb4caSwyllys 
238699ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
238799ebb4caSwyllys 				(void) BIO_printf(mem,
238899ebb4caSwyllys 					"RSA Public Key: (%d bit)\n",
238999ebb4caSwyllys 					BN_num_bits(pkey->pkey.rsa->n));
239099ebb4caSwyllys 				(void) RSA_print(mem, pkey->pkey.rsa, 0);
239199ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
239299ebb4caSwyllys 				(void) BIO_printf(mem,
239399ebb4caSwyllys 					"%12sDSA Public Key:\n", "");
239499ebb4caSwyllys 				(void) DSA_print(mem, pkey->pkey.dsa, 0);
239599ebb4caSwyllys 			} else {
239699ebb4caSwyllys 				(void) BIO_printf(mem,
239799ebb4caSwyllys 					"%12sUnknown Public Key:\n", "");
239899ebb4caSwyllys 			}
239999ebb4caSwyllys 			(void) BIO_printf(mem, "\n");
240099ebb4caSwyllys 			EVP_PKEY_free(pkey);
240199ebb4caSwyllys 		}
240299ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
240399ebb4caSwyllys 		break;
240499ebb4caSwyllys 	case KMF_CERT_SIGNATURE_ALG:
240599ebb4caSwyllys 	case KMF_CERT_PUBKEY_ALG:
240699ebb4caSwyllys 		if (flag == KMF_CERT_SIGNATURE_ALG) {
240799ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
240899ebb4caSwyllys 				xcert->sig_alg->algorithm);
240999ebb4caSwyllys 		} else {
241099ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
241199ebb4caSwyllys 				xcert->cert_info->key->algor->algorithm);
241299ebb4caSwyllys 		}
241399ebb4caSwyllys 
241499ebb4caSwyllys 		if (len > 0) {
241599ebb4caSwyllys 			len = BIO_read(mem, resultStr,
241699ebb4caSwyllys 				KMF_CERT_PRINTABLE_LEN);
241799ebb4caSwyllys 		}
241899ebb4caSwyllys 		break;
241999ebb4caSwyllys 
242099ebb4caSwyllys 	case KMF_CERT_EMAIL:
242199ebb4caSwyllys 		emlst = X509_get1_email(xcert);
242299ebb4caSwyllys 		for (j = 0; j < sk_num(emlst); j++)
242399ebb4caSwyllys 			(void) BIO_printf(mem, "%s\n", sk_value(emlst, j));
242499ebb4caSwyllys 
242599ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
242699ebb4caSwyllys 		X509_email_free(emlst);
242799ebb4caSwyllys 		break;
242899ebb4caSwyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
242999ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
243099ebb4caSwyllys 	case KMF_X509_EXT_KEY_USAGE:
243199ebb4caSwyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
243299ebb4caSwyllys 	case KMF_X509_EXT_CERT_POLICIES:
243399ebb4caSwyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
243499ebb4caSwyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
243599ebb4caSwyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
243699ebb4caSwyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
243799ebb4caSwyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
243899ebb4caSwyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
243999ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
244099ebb4caSwyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
244199ebb4caSwyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
244299ebb4caSwyllys 	case KMF_X509_EXT_FRESHEST_CRL:
244399ebb4caSwyllys 		nid = ext2NID(flag);
244499ebb4caSwyllys 		if (nid == NID_undef) {
244599ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
244699ebb4caSwyllys 			goto out;
244799ebb4caSwyllys 		}
244899ebb4caSwyllys 		ci = xcert->cert_info;
244999ebb4caSwyllys 
245099ebb4caSwyllys 		ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1);
245199ebb4caSwyllys 		if (ext_index == -1) {
245299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
245399ebb4caSwyllys 
245499ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
245599ebb4caSwyllys 			goto out;
245699ebb4caSwyllys 		}
245799ebb4caSwyllys 		ex = X509v3_get_ext(ci->extensions, ext_index);
245899ebb4caSwyllys 
245999ebb4caSwyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
246099ebb4caSwyllys 
246199ebb4caSwyllys 		if (BIO_printf(mem, ": %s\n",
246299ebb4caSwyllys 			X509_EXTENSION_get_critical(ex) ? "critical" : "") <=
246399ebb4caSwyllys 			0) {
246499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
246599ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
246699ebb4caSwyllys 			goto out;
246799ebb4caSwyllys 		}
246899ebb4caSwyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
246999ebb4caSwyllys 			(void) BIO_printf(mem, "%*s", 4, "");
247099ebb4caSwyllys 			(void) M_ASN1_OCTET_STRING_print(mem, ex->value);
247199ebb4caSwyllys 		}
247299ebb4caSwyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
247399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
247499ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
247599ebb4caSwyllys 			goto out;
247699ebb4caSwyllys 		}
247799ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
247899ebb4caSwyllys 	}
247999ebb4caSwyllys 	if (len <= 0) {
248099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
248199ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
248299ebb4caSwyllys 	}
248399ebb4caSwyllys 
248499ebb4caSwyllys out:
248599ebb4caSwyllys 	if (outbuf != NULL) {
248699ebb4caSwyllys 		free(outbuf);
248799ebb4caSwyllys 	}
248899ebb4caSwyllys 
248999ebb4caSwyllys 	if (xcert != NULL) {
249099ebb4caSwyllys 		X509_free(xcert);
249199ebb4caSwyllys 	}
249299ebb4caSwyllys 
249399ebb4caSwyllys 	if (mem != NULL) {
249499ebb4caSwyllys 		(void) BIO_free(mem);
249599ebb4caSwyllys 	}
249699ebb4caSwyllys 
249799ebb4caSwyllys 	return (ret);
249899ebb4caSwyllys }
249999ebb4caSwyllys KMF_RETURN
250099ebb4caSwyllys /*ARGSUSED*/
250199ebb4caSwyllys OpenSSL_GetPrikeyByCert(KMF_HANDLE_T handle,
250299ebb4caSwyllys 	KMF_CRYPTOWITHCERT_PARAMS *params,
250399ebb4caSwyllys 	KMF_DATA *SignerCertData, KMF_KEY_HANDLE *key,
250499ebb4caSwyllys 	KMF_KEY_ALG keytype)
250599ebb4caSwyllys {
250699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
250799ebb4caSwyllys 	KMF_FINDKEY_PARAMS fkparms;
250899ebb4caSwyllys 	uint32_t numkeys = 0;
250999ebb4caSwyllys 
251002744e81Swyllys 	if (params == NULL || params->sslparms.keyfile == NULL)
251199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
251299ebb4caSwyllys 
251399ebb4caSwyllys 	/*
251499ebb4caSwyllys 	 * This is really just a FindKey operation, reuse the
251599ebb4caSwyllys 	 * FindKey function.
251699ebb4caSwyllys 	 */
251799ebb4caSwyllys 	(void *)memset(&fkparms, 0, sizeof (fkparms));
251899ebb4caSwyllys 	fkparms.kstype = KMF_KEYSTORE_OPENSSL;
251999ebb4caSwyllys 	fkparms.keyclass = KMF_ASYM_PRI;
252099ebb4caSwyllys 	fkparms.keytype = keytype;
252199ebb4caSwyllys 	fkparms.format = params->format;
252299ebb4caSwyllys 	fkparms.sslparms = params->sslparms;
252399ebb4caSwyllys 
252499ebb4caSwyllys 	rv = OpenSSL_FindKey(handle, &fkparms, key, &numkeys);
252599ebb4caSwyllys 
252699ebb4caSwyllys 	return (rv);
252799ebb4caSwyllys }
252899ebb4caSwyllys 
252999ebb4caSwyllys KMF_RETURN
253099ebb4caSwyllys /*ARGSUSED*/
253199ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
253299ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
253399ebb4caSwyllys 	KMF_DATA *output)
253499ebb4caSwyllys {
253599ebb4caSwyllys 	KMF_RETURN		ret = KMF_OK;
253699ebb4caSwyllys 	RSA *rsa = NULL;
253799ebb4caSwyllys 	unsigned int in_len = 0, out_len = 0;
253899ebb4caSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
253999ebb4caSwyllys 	uint8_t *in_data, *out_data;
254099ebb4caSwyllys 	int i, blocks;
254199ebb4caSwyllys 
254299ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
254399ebb4caSwyllys 	    ciphertext == NULL || output == NULL ||
254499ebb4caSwyllys 	    ciphertext->Data == NULL ||
254599ebb4caSwyllys 	    output->Data == NULL)
254699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
254799ebb4caSwyllys 
254899ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
254999ebb4caSwyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
255099ebb4caSwyllys 		modulus_len = RSA_size(rsa);
255199ebb4caSwyllys 	} else {
255299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
255399ebb4caSwyllys 	}
255499ebb4caSwyllys 
255599ebb4caSwyllys 	blocks = ciphertext->Length/modulus_len;
255699ebb4caSwyllys 	out_data = output->Data;
255799ebb4caSwyllys 	in_data = ciphertext->Data;
255899ebb4caSwyllys 	out_len = modulus_len - 11;
255999ebb4caSwyllys 	in_len = modulus_len;
256099ebb4caSwyllys 
256199ebb4caSwyllys 	for (i = 0; i < blocks; i++) {
256299ebb4caSwyllys 		out_len  = RSA_private_decrypt(in_len,
256399ebb4caSwyllys 			in_data, out_data, rsa, RSA_PKCS1_PADDING);
256499ebb4caSwyllys 
256599ebb4caSwyllys 		if (out_len == 0) {
256699ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
256799ebb4caSwyllys 			goto cleanup;
256899ebb4caSwyllys 		}
256999ebb4caSwyllys 
257099ebb4caSwyllys 		out_data += out_len;
257199ebb4caSwyllys 		total_decrypted += out_len;
257299ebb4caSwyllys 		in_data += in_len;
257399ebb4caSwyllys 	}
257499ebb4caSwyllys 
257599ebb4caSwyllys 	output->Length = total_decrypted;
257699ebb4caSwyllys 
257799ebb4caSwyllys cleanup:
257899ebb4caSwyllys 	RSA_free(rsa);
257999ebb4caSwyllys 	if (ret != KMF_OK)
258099ebb4caSwyllys 		output->Length = 0;
258199ebb4caSwyllys 
258299ebb4caSwyllys 	return (ret);
258399ebb4caSwyllys 
258499ebb4caSwyllys }
258599ebb4caSwyllys 
258699ebb4caSwyllys /*
258799ebb4caSwyllys  *  This function will create a certid from issuer_cert and user_cert.
258899ebb4caSwyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
258999ebb4caSwyllys  *  certid memory after use.
259099ebb4caSwyllys  */
259199ebb4caSwyllys static KMF_RETURN
259299ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
259399ebb4caSwyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
259499ebb4caSwyllys {
259599ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
259699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
259799ebb4caSwyllys 	X509   *issuer = NULL;
259899ebb4caSwyllys 	X509   *cert = NULL;
259999ebb4caSwyllys 	unsigned char *ptmp;
260099ebb4caSwyllys 
260199ebb4caSwyllys 	if (issuer_cert == NULL || user_cert == NULL) {
260299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
260399ebb4caSwyllys 	}
260499ebb4caSwyllys 
260599ebb4caSwyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
260699ebb4caSwyllys 	ptmp = issuer_cert->Data;
260799ebb4caSwyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
260899ebb4caSwyllys 		issuer_cert->Length);
260999ebb4caSwyllys 	if (issuer == NULL) {
261099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
261199ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
261299ebb4caSwyllys 		goto end;
261399ebb4caSwyllys 	}
261499ebb4caSwyllys 
261599ebb4caSwyllys 	/* convert the DER-encoded user cert to an internal X509 */
261699ebb4caSwyllys 	ptmp = user_cert->Data;
261799ebb4caSwyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
261899ebb4caSwyllys 		user_cert->Length);
261999ebb4caSwyllys 	if (cert == NULL) {
262099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
262199ebb4caSwyllys 
262299ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
262399ebb4caSwyllys 		goto end;
262499ebb4caSwyllys 	}
262599ebb4caSwyllys 
262699ebb4caSwyllys 	/* create a CERTID */
262799ebb4caSwyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
262899ebb4caSwyllys 	if (*certid == NULL) {
262999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
263099ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
263199ebb4caSwyllys 		goto end;
263299ebb4caSwyllys 	}
263399ebb4caSwyllys 
263499ebb4caSwyllys end:
263599ebb4caSwyllys 	if (issuer != NULL) {
263699ebb4caSwyllys 		X509_free(issuer);
263799ebb4caSwyllys 	}
263899ebb4caSwyllys 
263999ebb4caSwyllys 	if (cert != NULL) {
264099ebb4caSwyllys 		X509_free(cert);
264199ebb4caSwyllys 	}
264299ebb4caSwyllys 
264399ebb4caSwyllys 	return (ret);
264499ebb4caSwyllys }
264599ebb4caSwyllys 
264699ebb4caSwyllys KMF_RETURN
264799ebb4caSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle, KMF_OCSPREQUEST_PARAMS *params,
264899ebb4caSwyllys     char *reqfile)
264999ebb4caSwyllys {
265099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
265199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
265299ebb4caSwyllys 	OCSP_CERTID *id = NULL;
265399ebb4caSwyllys 	OCSP_REQUEST *req = NULL;
265499ebb4caSwyllys 	BIO *derbio = NULL;
265599ebb4caSwyllys 
265699ebb4caSwyllys 	if (params->user_cert == NULL || params->issuer_cert == NULL ||
265799ebb4caSwyllys 	    reqfile == NULL) {
265899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
265999ebb4caSwyllys 	}
266099ebb4caSwyllys 
266199ebb4caSwyllys 	ret = create_certid(handle, params->issuer_cert, params->user_cert,
266299ebb4caSwyllys 	    &id);
266399ebb4caSwyllys 	if (ret != KMF_OK) {
266499ebb4caSwyllys 		return (ret);
266599ebb4caSwyllys 	}
266699ebb4caSwyllys 
266799ebb4caSwyllys 	/* Create an OCSP request */
266899ebb4caSwyllys 	req = OCSP_REQUEST_new();
266999ebb4caSwyllys 	if (req == NULL) {
267099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
267199ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
267299ebb4caSwyllys 		goto end;
267399ebb4caSwyllys 	}
267499ebb4caSwyllys 
267599ebb4caSwyllys 	if (!OCSP_request_add0_id(req, id)) {
267699ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
267799ebb4caSwyllys 		goto end;
267899ebb4caSwyllys 	}
267999ebb4caSwyllys 
268099ebb4caSwyllys 	/* Write the request to the output file with DER encoding */
268199ebb4caSwyllys 	derbio = BIO_new_file(reqfile, "wb");
268299ebb4caSwyllys 	if (!derbio) {
268399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
268499ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
268599ebb4caSwyllys 		goto end;
268699ebb4caSwyllys 	}
268799ebb4caSwyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
268899ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
268999ebb4caSwyllys 	}
269099ebb4caSwyllys 
269199ebb4caSwyllys end:
269299ebb4caSwyllys 	/*
269399ebb4caSwyllys 	 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
269499ebb4caSwyllys 	 * will deallocate certid's space also.
269599ebb4caSwyllys 	 */
269699ebb4caSwyllys 	if (req != NULL) {
269799ebb4caSwyllys 		OCSP_REQUEST_free(req);
269899ebb4caSwyllys 	}
269999ebb4caSwyllys 
270099ebb4caSwyllys 	if (derbio != NULL) {
270199ebb4caSwyllys 		(void) BIO_free(derbio);
270299ebb4caSwyllys 	}
270399ebb4caSwyllys 
270499ebb4caSwyllys 	return (ret);
270599ebb4caSwyllys }
270699ebb4caSwyllys 
270799ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */
270899ebb4caSwyllys static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
270999ebb4caSwyllys {
271099ebb4caSwyllys 	int i;
271199ebb4caSwyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
271299ebb4caSwyllys 
271399ebb4caSwyllys 	/* Easy if lookup by name */
271499ebb4caSwyllys 	if (id->type == V_OCSP_RESPID_NAME)
271599ebb4caSwyllys 		return (X509_find_by_subject(certs, id->value.byName));
271699ebb4caSwyllys 
271799ebb4caSwyllys 	/* Lookup by key hash */
271899ebb4caSwyllys 
271999ebb4caSwyllys 	/* If key hash isn't SHA1 length then forget it */
272099ebb4caSwyllys 	if (id->value.byKey->length != SHA_DIGEST_LENGTH)
272199ebb4caSwyllys 		return (NULL);
272299ebb4caSwyllys 
272399ebb4caSwyllys 	keyhash = id->value.byKey->data;
272499ebb4caSwyllys 	/* Calculate hash of each key and compare */
272599ebb4caSwyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
272699ebb4caSwyllys 		/*LINTED*/
272799ebb4caSwyllys 		X509 *x = sk_X509_value(certs, i);
272899ebb4caSwyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
272999ebb4caSwyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
273099ebb4caSwyllys 			return (x);
273199ebb4caSwyllys 	}
273299ebb4caSwyllys 	return (NULL);
273399ebb4caSwyllys }
273499ebb4caSwyllys 
273599ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */
273699ebb4caSwyllys /*ARGSUSED*/
273799ebb4caSwyllys static int
273899ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
273999ebb4caSwyllys     X509_STORE *st, unsigned long flags)
274099ebb4caSwyllys {
274199ebb4caSwyllys 	X509 *signer;
274299ebb4caSwyllys 	OCSP_RESPID *rid = bs->tbsResponseData->responderId;
274399ebb4caSwyllys 	if ((signer = ocsp_find_signer_sk(certs, rid)))	{
274499ebb4caSwyllys 		*psigner = signer;
274599ebb4caSwyllys 		return (2);
274699ebb4caSwyllys 	}
274799ebb4caSwyllys 	if (!(flags & OCSP_NOINTERN) &&
274899ebb4caSwyllys 	    (signer = ocsp_find_signer_sk(bs->certs, rid))) {
274999ebb4caSwyllys 		*psigner = signer;
275099ebb4caSwyllys 		return (1);
275199ebb4caSwyllys 	}
275299ebb4caSwyllys 	/* Maybe lookup from store if by subject name */
275399ebb4caSwyllys 
275499ebb4caSwyllys 	*psigner = NULL;
275599ebb4caSwyllys 	return (0);
275699ebb4caSwyllys }
275799ebb4caSwyllys 
275899ebb4caSwyllys /*
275999ebb4caSwyllys  * This function will verify the signature of a basic response, using
276099ebb4caSwyllys  * the public key from the OCSP responder certificate.
276199ebb4caSwyllys  */
276299ebb4caSwyllys static KMF_RETURN
276399ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
276499ebb4caSwyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
276599ebb4caSwyllys {
276699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
276799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
276899ebb4caSwyllys 	STACK_OF(X509) *cert_stack = NULL;
276999ebb4caSwyllys 	X509 *signer = NULL;
277099ebb4caSwyllys 	X509 *issuer = NULL;
277199ebb4caSwyllys 	EVP_PKEY *skey = NULL;
277299ebb4caSwyllys 	unsigned char *ptmp;
277399ebb4caSwyllys 
277499ebb4caSwyllys 
277599ebb4caSwyllys 	if (bs == NULL || issuer_cert == NULL)
277699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
277799ebb4caSwyllys 
277899ebb4caSwyllys 	/*
277999ebb4caSwyllys 	 * Find the certificate that signed the basic response.
278099ebb4caSwyllys 	 *
278199ebb4caSwyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
278299ebb4caSwyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
278399ebb4caSwyllys 	 * If we still do not find a signer, we will look for it from the
278499ebb4caSwyllys 	 * certificate list came with the response file.
278599ebb4caSwyllys 	 */
278699ebb4caSwyllys 	if (signer_cert != NULL) {
278799ebb4caSwyllys 		ptmp = signer_cert->Data;
278899ebb4caSwyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
278999ebb4caSwyllys 		    signer_cert->Length);
279099ebb4caSwyllys 		if (signer == NULL) {
279199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
279299ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
279399ebb4caSwyllys 			goto end;
279499ebb4caSwyllys 		}
279599ebb4caSwyllys 	} else {
279699ebb4caSwyllys 		/*
279799ebb4caSwyllys 		 * Convert the issuer cert into X509 and push it into a
279899ebb4caSwyllys 		 * stack to be used by ocsp_find_signer().
279999ebb4caSwyllys 		 */
280099ebb4caSwyllys 		ptmp = issuer_cert->Data;
280199ebb4caSwyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
280299ebb4caSwyllys 			issuer_cert->Length);
280399ebb4caSwyllys 		if (issuer == NULL) {
280499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
280599ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
280699ebb4caSwyllys 			goto end;
280799ebb4caSwyllys 		}
280899ebb4caSwyllys 
280999ebb4caSwyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
281099ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
281199ebb4caSwyllys 			goto end;
281299ebb4caSwyllys 		}
281399ebb4caSwyllys 
281499ebb4caSwyllys 		if (sk_X509_push(cert_stack, issuer) == NULL) {
281599ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
281699ebb4caSwyllys 			goto end;
281799ebb4caSwyllys 		}
281899ebb4caSwyllys 
281999ebb4caSwyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
282099ebb4caSwyllys 		if (!ret) {
282199ebb4caSwyllys 			/* can not find the signer */
282299ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
282399ebb4caSwyllys 			goto end;
282499ebb4caSwyllys 		}
282599ebb4caSwyllys 	}
282699ebb4caSwyllys 
282799ebb4caSwyllys 	/* Verify the signature of the response */
282899ebb4caSwyllys 	skey = X509_get_pubkey(signer);
282999ebb4caSwyllys 	if (skey == NULL) {
283099ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
283199ebb4caSwyllys 		goto end;
283299ebb4caSwyllys 	}
283399ebb4caSwyllys 
283499ebb4caSwyllys 	ret = OCSP_BASICRESP_verify(bs, skey, 0);
283599ebb4caSwyllys 	if (ret == 0) {
283699ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
283799ebb4caSwyllys 		goto end;
283899ebb4caSwyllys 	}
283999ebb4caSwyllys 
284099ebb4caSwyllys end:
284199ebb4caSwyllys 	if (issuer != NULL) {
284299ebb4caSwyllys 		X509_free(issuer);
284399ebb4caSwyllys 	}
284499ebb4caSwyllys 
284599ebb4caSwyllys 	if (signer != NULL) {
284699ebb4caSwyllys 		X509_free(signer);
284799ebb4caSwyllys 	}
284899ebb4caSwyllys 
284999ebb4caSwyllys 	if (skey != NULL) {
285099ebb4caSwyllys 		EVP_PKEY_free(skey);
285199ebb4caSwyllys 	}
285299ebb4caSwyllys 
285399ebb4caSwyllys 	if (cert_stack != NULL) {
285499ebb4caSwyllys 		sk_X509_free(cert_stack);
285599ebb4caSwyllys 	}
285699ebb4caSwyllys 
285799ebb4caSwyllys 	return (ret);
285899ebb4caSwyllys }
285999ebb4caSwyllys 
286099ebb4caSwyllys 
286199ebb4caSwyllys 
286299ebb4caSwyllys KMF_RETURN
286399ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
286499ebb4caSwyllys     KMF_OCSPRESPONSE_PARAMS_INPUT *params_in,
286599ebb4caSwyllys     KMF_OCSPRESPONSE_PARAMS_OUTPUT *params_out)
286699ebb4caSwyllys {
286799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
286899ebb4caSwyllys 	BIO *derbio = NULL;
286999ebb4caSwyllys 	OCSP_RESPONSE *resp = NULL;
287099ebb4caSwyllys 	OCSP_BASICRESP *bs = NULL;
287199ebb4caSwyllys 	OCSP_CERTID *id = NULL;
287299ebb4caSwyllys 	OCSP_SINGLERESP *single = NULL;
287399ebb4caSwyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
287499ebb4caSwyllys 	int index, status, reason;
287599ebb4caSwyllys 
287699ebb4caSwyllys 	if (params_in == NULL || params_in->issuer_cert == NULL ||
287799ebb4caSwyllys 	    params_in->user_cert == NULL || params_in->response == NULL) {
287899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
287999ebb4caSwyllys 	}
288099ebb4caSwyllys 
288199ebb4caSwyllys 	if (params_out == NULL) {
288299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
288399ebb4caSwyllys 	}
288499ebb4caSwyllys 
288599ebb4caSwyllys 	/* Read in the response */
288699ebb4caSwyllys 	derbio = BIO_new_mem_buf(params_in->response->Data,
288799ebb4caSwyllys 	    params_in->response->Length);
288899ebb4caSwyllys 	if (!derbio) {
288999ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
289099ebb4caSwyllys 		return (ret);
289199ebb4caSwyllys 	}
289299ebb4caSwyllys 
289399ebb4caSwyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
289499ebb4caSwyllys 	if (resp == NULL) {
289599ebb4caSwyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
289699ebb4caSwyllys 		goto end;
289799ebb4caSwyllys 	}
289899ebb4caSwyllys 
289999ebb4caSwyllys 	/* Check the response status */
290099ebb4caSwyllys 	status = OCSP_response_status(resp);
290199ebb4caSwyllys 	params_out->response_status = status;
290299ebb4caSwyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
290399ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
290499ebb4caSwyllys 		goto end;
290599ebb4caSwyllys 	}
290699ebb4caSwyllys 
290799ebb4caSwyllys #ifdef DEBUG
290899ebb4caSwyllys 	printf("Successfully checked the response file status.\n");
290999ebb4caSwyllys #endif /* DEBUG */
291099ebb4caSwyllys 
291199ebb4caSwyllys 	/* Extract basic response */
291299ebb4caSwyllys 	bs = OCSP_response_get1_basic(resp);
291399ebb4caSwyllys 	if (bs == NULL) {
291499ebb4caSwyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
291599ebb4caSwyllys 		goto end;
291699ebb4caSwyllys 	}
291799ebb4caSwyllys 
291899ebb4caSwyllys #ifdef DEBUG
291999ebb4caSwyllys 	printf("Successfully retrieved the basic response.\n");
292099ebb4caSwyllys #endif /* DEBUG */
292199ebb4caSwyllys 
292299ebb4caSwyllys 	/* Check the basic response signature if required */
292399ebb4caSwyllys 	if (params_in->ignore_response_sign == B_FALSE) {
292499ebb4caSwyllys 		ret = check_response_signature(handle, bs,
292599ebb4caSwyllys 		    params_in->signer_cert, params_in->issuer_cert);
292699ebb4caSwyllys 		if (ret != KMF_OK)
292799ebb4caSwyllys 			goto end;
292899ebb4caSwyllys 	}
292999ebb4caSwyllys 
293099ebb4caSwyllys #ifdef DEBUG
293199ebb4caSwyllys 	printf("Successfully verified the response signature.\n");
293299ebb4caSwyllys #endif /* DEBUG */
293399ebb4caSwyllys 
293499ebb4caSwyllys 	/* Create a certid for the certificate in question */
293599ebb4caSwyllys 	ret = create_certid(handle, params_in->issuer_cert,
293699ebb4caSwyllys 	    params_in->user_cert, &id);
293799ebb4caSwyllys 	if (ret != KMF_OK) {
293899ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
293999ebb4caSwyllys 		goto end;
294099ebb4caSwyllys 	}
294199ebb4caSwyllys 
294299ebb4caSwyllys #ifdef DEBUG
294399ebb4caSwyllys 	printf("successfully created a certid for the cert.\n");
294499ebb4caSwyllys #endif /* DEBUG */
294599ebb4caSwyllys 
294699ebb4caSwyllys 	/* Find the index of the single response for the certid */
294799ebb4caSwyllys 	index = OCSP_resp_find(bs, id, -1);
294899ebb4caSwyllys 	if (index < 0) {
294999ebb4caSwyllys 		/* cound not find this certificate in the response */
295099ebb4caSwyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
295199ebb4caSwyllys 		goto end;
295299ebb4caSwyllys 	}
295399ebb4caSwyllys 
295499ebb4caSwyllys #ifdef DEBUG
295599ebb4caSwyllys 	printf("Successfully found the single response index for the cert.\n");
295699ebb4caSwyllys #endif /* DEBUG */
295799ebb4caSwyllys 
295899ebb4caSwyllys 	/* Retrieve the single response and get the cert status */
295999ebb4caSwyllys 	single = OCSP_resp_get0(bs, index);
296099ebb4caSwyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
296199ebb4caSwyllys 	    &nextupd);
296299ebb4caSwyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
296399ebb4caSwyllys 		params_out->cert_status = OCSP_GOOD;
296499ebb4caSwyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
296599ebb4caSwyllys 		params_out->cert_status = OCSP_UNKNOWN;
296699ebb4caSwyllys 	} else { /* revoked */
296799ebb4caSwyllys 		params_out->cert_status = OCSP_REVOKED;
296899ebb4caSwyllys 		params_out->reason = reason;
296999ebb4caSwyllys 	}
297099ebb4caSwyllys 	ret = KMF_OK;
297199ebb4caSwyllys 
297299ebb4caSwyllys 	/* Verify the time */
297399ebb4caSwyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
297499ebb4caSwyllys 	    params_in->response_lifetime)) {
297599ebb4caSwyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
297699ebb4caSwyllys 		goto end;
297799ebb4caSwyllys 	}
297899ebb4caSwyllys 
297999ebb4caSwyllys #ifdef DEBUG
298099ebb4caSwyllys 	printf("Successfully verify the time.\n");
298199ebb4caSwyllys #endif /* DEBUG */
298299ebb4caSwyllys 
298399ebb4caSwyllys end:
298499ebb4caSwyllys 	if (derbio != NULL)
298599ebb4caSwyllys 		(void) BIO_free(derbio);
298699ebb4caSwyllys 
298799ebb4caSwyllys 	if (resp != NULL)
298899ebb4caSwyllys 		OCSP_RESPONSE_free(resp);
298999ebb4caSwyllys 
299099ebb4caSwyllys 	if (bs != NULL)
299199ebb4caSwyllys 		OCSP_BASICRESP_free(bs);
299299ebb4caSwyllys 
299399ebb4caSwyllys 	if (id != NULL)
299499ebb4caSwyllys 		OCSP_CERTID_free(id);
299599ebb4caSwyllys 
299699ebb4caSwyllys 	return (ret);
299799ebb4caSwyllys }
299899ebb4caSwyllys 
299999ebb4caSwyllys static KMF_RETURN
300099ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path,
300199ebb4caSwyllys 	KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
300299ebb4caSwyllys {
300399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
300499ebb4caSwyllys 	EVP_PKEY *pkey;
300599ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
300699ebb4caSwyllys 
300799ebb4caSwyllys 	/* Make sure the requested file actually exists. */
300899ebb4caSwyllys 	if (access(path, F_OK) != 0) {
300999ebb4caSwyllys 		return (KMF_ERR_KEY_NOT_FOUND);
301099ebb4caSwyllys 	}
301199ebb4caSwyllys 
301299ebb4caSwyllys 	if (keyclass == KMF_ASYM_PRI ||
301399ebb4caSwyllys 	    keyclass == KMF_ASYM_PUB) {
301499ebb4caSwyllys 		pkey = openssl_load_key(handle, path);
301599ebb4caSwyllys 		if (pkey == NULL) {
301699ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
301799ebb4caSwyllys 		}
301899ebb4caSwyllys 		if (key != NULL) {
301999ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA)
302099ebb4caSwyllys 				key->keyalg = KMF_RSA;
302199ebb4caSwyllys 			else if (pkey->type == EVP_PKEY_DSA)
302299ebb4caSwyllys 				key->keyalg = KMF_DSA;
302399ebb4caSwyllys 
302499ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
302599ebb4caSwyllys 			key->keyclass = keyclass;
302699ebb4caSwyllys 			key->keyp = (void *)pkey;
302799ebb4caSwyllys 			key->israw = FALSE;
302899ebb4caSwyllys 			key->keylabel = path;
302999ebb4caSwyllys 		} else {
303099ebb4caSwyllys 			EVP_PKEY_free(pkey);
303199ebb4caSwyllys 			pkey = NULL;
303299ebb4caSwyllys 		}
303399ebb4caSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
303499ebb4caSwyllys 		KMF_ENCODE_FORMAT fmt;
303599ebb4caSwyllys 		/*
303699ebb4caSwyllys 		 * If the file is a recognized format,
303799ebb4caSwyllys 		 * then it is NOT a symmetric key.
303899ebb4caSwyllys 		 */
303999ebb4caSwyllys 		rv = KMF_GetFileFormat(path, &fmt);
304099ebb4caSwyllys 		if (rv == KMF_OK || fmt != 0) {
304199ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
304299ebb4caSwyllys 		} else if (rv == KMF_ERR_ENCODING) {
304399ebb4caSwyllys 			/*
304499ebb4caSwyllys 			 * If we don't know the encoding,
304599ebb4caSwyllys 			 * it is probably  a symmetric key.
304699ebb4caSwyllys 			 */
304799ebb4caSwyllys 			rv = KMF_OK;
304899ebb4caSwyllys 		}
304999ebb4caSwyllys 
305099ebb4caSwyllys 		if (key != NULL) {
305199ebb4caSwyllys 			KMF_DATA keyvalue;
305299ebb4caSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
305399ebb4caSwyllys 			if (rkey == NULL) {
305499ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
305599ebb4caSwyllys 				goto out;
305699ebb4caSwyllys 			}
305799ebb4caSwyllys 
305899ebb4caSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
305999ebb4caSwyllys 			rv = KMF_ReadInputFile(handle, path, &keyvalue);
306099ebb4caSwyllys 			if (rv != KMF_OK)
306199ebb4caSwyllys 				goto out;
306299ebb4caSwyllys 
306399ebb4caSwyllys 			rkey->keydata.len = keyvalue.Length;
306499ebb4caSwyllys 			rkey->keydata.val = keyvalue.Data;
306599ebb4caSwyllys 
306699ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
306799ebb4caSwyllys 			key->keyclass = keyclass;
306899ebb4caSwyllys 			key->israw = TRUE;
306999ebb4caSwyllys 			key->keylabel = path;
307099ebb4caSwyllys 			key->keyp = (void *)rkey;
307199ebb4caSwyllys 		}
307299ebb4caSwyllys 	}
307399ebb4caSwyllys out:
307499ebb4caSwyllys 	if (rv != KMF_OK) {
307599ebb4caSwyllys 		if (rkey != NULL) {
307699ebb4caSwyllys 			KMF_FreeRawSymKey(rkey);
307799ebb4caSwyllys 		}
307899ebb4caSwyllys 		if (pkey != NULL)
307999ebb4caSwyllys 			EVP_PKEY_free(pkey);
308099ebb4caSwyllys 
308199ebb4caSwyllys 		if (key != NULL) {
308299ebb4caSwyllys 			key->keyalg = KMF_KEYALG_NONE;
308399ebb4caSwyllys 			key->keyclass = KMF_KEYCLASS_NONE;
308499ebb4caSwyllys 			key->keyp = NULL;
308599ebb4caSwyllys 		}
308699ebb4caSwyllys 	}
308799ebb4caSwyllys 
308899ebb4caSwyllys 	return (rv);
308999ebb4caSwyllys }
309099ebb4caSwyllys 
309199ebb4caSwyllys KMF_RETURN
309299ebb4caSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle, KMF_FINDKEY_PARAMS *params,
309399ebb4caSwyllys 	KMF_KEY_HANDLE *key, uint32_t *numkeys)
309499ebb4caSwyllys {
309599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
309699ebb4caSwyllys 	char *fullpath = NULL;
3097f482c776Swyllys 	uint32_t maxkeys;
309899ebb4caSwyllys 
309999ebb4caSwyllys 	if (handle == NULL || params == NULL || numkeys == NULL)
310099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
310199ebb4caSwyllys 
310299ebb4caSwyllys 	if (params->keyclass != KMF_ASYM_PUB &&
310399ebb4caSwyllys 		params->keyclass != KMF_ASYM_PRI &&
310499ebb4caSwyllys 		params->keyclass != KMF_SYMMETRIC)
310599ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
310699ebb4caSwyllys 
310799ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
310899ebb4caSwyllys 		params->sslparms.keyfile);
310999ebb4caSwyllys 
311099ebb4caSwyllys 	if (fullpath == NULL)
311199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
311299ebb4caSwyllys 
3113f482c776Swyllys 	maxkeys = *numkeys;
3114f482c776Swyllys 	if (maxkeys == 0)
3115f482c776Swyllys 		maxkeys = 0xFFFFFFFF;
3116f482c776Swyllys 
311799ebb4caSwyllys 	*numkeys = 0;
311899ebb4caSwyllys 
311999ebb4caSwyllys 	if (isdir(fullpath)) {
312099ebb4caSwyllys 		DIR *dirp;
312199ebb4caSwyllys 		struct dirent *dp;
312299ebb4caSwyllys 		int n = 0;
312399ebb4caSwyllys 
312499ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
312599ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
312699ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
312799ebb4caSwyllys 		}
312899ebb4caSwyllys 		rewinddir(dirp);
3129f482c776Swyllys 		while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
313099ebb4caSwyllys 			if (strcmp(dp->d_name, ".") &&
313199ebb4caSwyllys 			    strcmp(dp->d_name, "..")) {
313299ebb4caSwyllys 				char *fname;
313399ebb4caSwyllys 
313499ebb4caSwyllys 				fname = get_fullpath(fullpath,
313599ebb4caSwyllys 					(char *)&dp->d_name);
313699ebb4caSwyllys 
313799ebb4caSwyllys 				rv = fetch_key(handle, fname,
313899ebb4caSwyllys 					params->keyclass,
313999ebb4caSwyllys 					key ? &key[n] : NULL);
314099ebb4caSwyllys 
314199ebb4caSwyllys 				if (rv == KMF_OK)
314299ebb4caSwyllys 					n++;
314399ebb4caSwyllys 
314499ebb4caSwyllys 				if (rv != KMF_OK || key == NULL)
314599ebb4caSwyllys 					free(fname);
314699ebb4caSwyllys 			}
314799ebb4caSwyllys 		}
314899ebb4caSwyllys 		(void) closedir(dirp);
314999ebb4caSwyllys 		free(fullpath);
315099ebb4caSwyllys 		(*numkeys) = n;
315199ebb4caSwyllys 	} else {
315299ebb4caSwyllys 		rv = fetch_key(handle, fullpath, params->keyclass, key);
315399ebb4caSwyllys 		if (rv == KMF_OK)
315499ebb4caSwyllys 			(*numkeys) = 1;
315599ebb4caSwyllys 
315699ebb4caSwyllys 		if (rv != KMF_OK || key == NULL)
315799ebb4caSwyllys 			free(fullpath);
315899ebb4caSwyllys 	}
315999ebb4caSwyllys 
3160f482c776Swyllys 	if (rv == KMF_OK && (*numkeys) == 0)
316199ebb4caSwyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
316299ebb4caSwyllys 
316399ebb4caSwyllys 	return (rv);
316499ebb4caSwyllys }
316599ebb4caSwyllys 
316699ebb4caSwyllys #define	HANDLE_PK12_ERROR { \
316799ebb4caSwyllys 	SET_ERROR(kmfh, ERR_get_error()); \
316899ebb4caSwyllys 	rv = KMF_ERR_ENCODING; \
316999ebb4caSwyllys 	goto out; \
317099ebb4caSwyllys }
317199ebb4caSwyllys 
317299ebb4caSwyllys static KMF_RETURN
317399ebb4caSwyllys write_pkcs12(KMF_HANDLE *kmfh,
317499ebb4caSwyllys 	BIO *bio,
317599ebb4caSwyllys 	KMF_CREDENTIAL *cred,
317699ebb4caSwyllys 	EVP_PKEY *pkey,
317799ebb4caSwyllys 	X509 *sslcert)
317899ebb4caSwyllys {
317999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
318099ebb4caSwyllys 	STACK_OF(PKCS12_SAFEBAG)	*bag_stack = NULL;
318199ebb4caSwyllys 	PKCS12_SAFEBAG			*bag = NULL;
318299ebb4caSwyllys 	PKCS7				*cert_authsafe = NULL;
318399ebb4caSwyllys 	PKCS8_PRIV_KEY_INFO		*p8 = NULL;
318499ebb4caSwyllys 	PKCS7				*key_authsafe = NULL;
318599ebb4caSwyllys 	STACK_OF(PKCS7)			*authsafe_stack = NULL;
318699ebb4caSwyllys 	PKCS12				*p12_elem = NULL;
318799ebb4caSwyllys 	char				*lab = NULL;
318899ebb4caSwyllys 	int				lab_len = 0;
318999ebb4caSwyllys 	unsigned char keyid[EVP_MAX_MD_SIZE];
319099ebb4caSwyllys 	unsigned int keyidlen = 0;
319199ebb4caSwyllys 
319299ebb4caSwyllys 	/* Must have at least a cert OR a key */
319399ebb4caSwyllys 	if (sslcert == NULL && pkey == NULL)
319499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
319599ebb4caSwyllys 
319699ebb4caSwyllys 	(void) memset(keyid, 0, sizeof (keyid));
319799ebb4caSwyllys 	/*
319899ebb4caSwyllys 	 * Section 1:
319999ebb4caSwyllys 	 *
320099ebb4caSwyllys 	 * The first PKCS#12 container (safebag) will hold the certificates
320199ebb4caSwyllys 	 * associated with this key.  The result of this section is a
320299ebb4caSwyllys 	 * PIN-encrypted PKCS#7 container (authsafe).  If there are no
320399ebb4caSwyllys 	 * certificates, there is no point in creating the "safebag" or the
320499ebb4caSwyllys 	 * "authsafe" so we go to the next section.
320599ebb4caSwyllys 	 */
320699ebb4caSwyllys 	if (sslcert != NULL && pkey != NULL) {
320799ebb4caSwyllys 		if (X509_check_private_key(sslcert, pkey)) {
320899ebb4caSwyllys 			(void) X509_digest(sslcert, EVP_sha1(), keyid,
320999ebb4caSwyllys 				&keyidlen);
321099ebb4caSwyllys 		} else {
321199ebb4caSwyllys 			/* The key doesn't match the cert */
321299ebb4caSwyllys 			HANDLE_PK12_ERROR
321399ebb4caSwyllys 		}
321499ebb4caSwyllys 	}
321599ebb4caSwyllys 
321699ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
321799ebb4caSwyllys 	if (bag_stack == NULL)
321899ebb4caSwyllys 		return (KMF_ERR_MEMORY);
321999ebb4caSwyllys 
322099ebb4caSwyllys 	if (sslcert != NULL) {
322199ebb4caSwyllys 		/* Convert cert from X509 struct to PKCS#12 bag */
322299ebb4caSwyllys 		bag = PKCS12_x5092certbag(sslcert);
322399ebb4caSwyllys 		if (bag == NULL) {
322499ebb4caSwyllys 			HANDLE_PK12_ERROR
322599ebb4caSwyllys 		}
322699ebb4caSwyllys 
322799ebb4caSwyllys 		/* Add the key id to the certificate bag. */
322899ebb4caSwyllys 		if (keyidlen > 0 &&
322999ebb4caSwyllys 			!PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
323099ebb4caSwyllys 			HANDLE_PK12_ERROR
323199ebb4caSwyllys 		}
323299ebb4caSwyllys 
323399ebb4caSwyllys 		/* Pile it on the bag_stack. */
323499ebb4caSwyllys 		if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
323599ebb4caSwyllys 			HANDLE_PK12_ERROR
323699ebb4caSwyllys 		}
323799ebb4caSwyllys #if 0
323899ebb4caSwyllys 		/* No support for CA certs yet */
323999ebb4caSwyllys 		if (cacerts != NULL && ncacerts > 0) {
324099ebb4caSwyllys 			int i;
324199ebb4caSwyllys 			for (i = 0; i < ncacerts; i++) {
324299ebb4caSwyllys 				KMF_X509_DER_CERT *c = &cacerts[i];
324399ebb4caSwyllys 				X509 *ca = NULL;
324499ebb4caSwyllys 
324599ebb4caSwyllys 				uchar_t *p = (uchar_t *)c->certificate.Data;
324699ebb4caSwyllys 				ca = d2i_X509(NULL, &p,
324799ebb4caSwyllys 					c->certificate.Length);
324899ebb4caSwyllys 				if (ca == NULL) {
324999ebb4caSwyllys 					HANDLE_PK12_ERROR
325099ebb4caSwyllys 				}
325199ebb4caSwyllys 				/* Convert CA cert to PKCS#12 bag. */
325299ebb4caSwyllys 				bag = PKCS12_x5092certbag(ca);
325399ebb4caSwyllys 				if (bag == NULL) {
325499ebb4caSwyllys 					sk_PKCS12_SAFEBAG_pop_free(bag_stack,
325599ebb4caSwyllys 					    PKCS12_SAFEBAG_free);
325699ebb4caSwyllys 					HANDLE_PK12_ERROR
325799ebb4caSwyllys 				}
325899ebb4caSwyllys 				/* Pile it onto the bag_stack. */
325999ebb4caSwyllys 				if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
326099ebb4caSwyllys 					HANDLE_PK12_ERROR
326199ebb4caSwyllys 				}
326299ebb4caSwyllys 			}
326399ebb4caSwyllys 		}
326499ebb4caSwyllys #endif
326599ebb4caSwyllys 		/* Turn bag_stack of certs into encrypted authsafe. */
326699ebb4caSwyllys 		cert_authsafe = PKCS12_pack_p7encdata(
326799ebb4caSwyllys 			NID_pbe_WithSHA1And40BitRC2_CBC,
326899ebb4caSwyllys 			cred->cred,
326999ebb4caSwyllys 			cred->credlen, NULL, 0,
327099ebb4caSwyllys 			PKCS12_DEFAULT_ITER,
327199ebb4caSwyllys 			bag_stack);
327299ebb4caSwyllys 
327399ebb4caSwyllys 		/* Clear away this bag_stack, we're done with it. */
327499ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
327599ebb4caSwyllys 		bag_stack = NULL;
327699ebb4caSwyllys 
327799ebb4caSwyllys 		if (cert_authsafe == NULL) {
327899ebb4caSwyllys 			HANDLE_PK12_ERROR
327999ebb4caSwyllys 		}
328099ebb4caSwyllys 	}
328199ebb4caSwyllys 	/*
328299ebb4caSwyllys 	 * Section 2:
328399ebb4caSwyllys 	 *
328499ebb4caSwyllys 	 * The second PKCS#12 container (safebag) will hold the private key
328599ebb4caSwyllys 	 * that goes with the certificates above.  The results of this section
328699ebb4caSwyllys 	 * is an unencrypted PKCS#7 container (authsafe).  If there is no
328799ebb4caSwyllys 	 * private key, there is no point in creating the "safebag" or the
328899ebb4caSwyllys 	 * "authsafe" so we go to the next section.
328999ebb4caSwyllys 	 */
329099ebb4caSwyllys 	if (pkey != NULL) {
329199ebb4caSwyllys 		p8 = EVP_PKEY2PKCS8(pkey);
329299ebb4caSwyllys 		if (p8 == NULL) {
329399ebb4caSwyllys 			HANDLE_PK12_ERROR
329499ebb4caSwyllys 		}
329599ebb4caSwyllys 		/* Put the shrouded key into a PKCS#12 bag. */
329699ebb4caSwyllys 		bag = PKCS12_MAKE_SHKEYBAG(
329799ebb4caSwyllys 			NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
329899ebb4caSwyllys 			cred->cred, cred->credlen,
329999ebb4caSwyllys 			NULL, 0, PKCS12_DEFAULT_ITER, p8);
330099ebb4caSwyllys 
330199ebb4caSwyllys 		/* Clean up the PKCS#8 shrouded key, don't need it now. */
330299ebb4caSwyllys 		PKCS8_PRIV_KEY_INFO_free(p8);
330399ebb4caSwyllys 		p8 = NULL;
330499ebb4caSwyllys 
330599ebb4caSwyllys 		if (bag == NULL) {
330699ebb4caSwyllys 			HANDLE_PK12_ERROR
330799ebb4caSwyllys 		}
330899ebb4caSwyllys 		if (keyidlen &&
330999ebb4caSwyllys 			!PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
331099ebb4caSwyllys 			HANDLE_PK12_ERROR
331199ebb4caSwyllys 		}
331299ebb4caSwyllys 		if (lab != NULL) {
331399ebb4caSwyllys 			if (!PKCS12_add_friendlyname(bag,
331499ebb4caSwyllys 				(char *)lab, lab_len)) {
331599ebb4caSwyllys 				HANDLE_PK12_ERROR
331699ebb4caSwyllys 			}
331799ebb4caSwyllys 		}
331899ebb4caSwyllys 		/* Start a PKCS#12 safebag container for the private key. */
331999ebb4caSwyllys 		bag_stack = sk_PKCS12_SAFEBAG_new_null();
332099ebb4caSwyllys 		if (bag_stack == NULL) {
332199ebb4caSwyllys 			HANDLE_PK12_ERROR
332299ebb4caSwyllys 		}
332399ebb4caSwyllys 
332499ebb4caSwyllys 		/* Pile on the private key on the bag_stack. */
332599ebb4caSwyllys 		if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
332699ebb4caSwyllys 			HANDLE_PK12_ERROR
332799ebb4caSwyllys 		}
332899ebb4caSwyllys 		key_authsafe = PKCS12_pack_p7data(bag_stack);
332999ebb4caSwyllys 
333099ebb4caSwyllys 		/* Clear away this bag_stack, we're done with it. */
333199ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
333299ebb4caSwyllys 		bag_stack = NULL;
333399ebb4caSwyllys 
333499ebb4caSwyllys 		if (key_authsafe == NULL) {
333599ebb4caSwyllys 			HANDLE_PK12_ERROR
333699ebb4caSwyllys 		}
333799ebb4caSwyllys 	}
333899ebb4caSwyllys 	/*
333999ebb4caSwyllys 	 * Section 3:
334099ebb4caSwyllys 	 *
334199ebb4caSwyllys 	 * This is where the two PKCS#7 containers, one for the certificates
334299ebb4caSwyllys 	 * and one for the private key, are put together into a PKCS#12
334399ebb4caSwyllys 	 * element.  This final PKCS#12 element is written to the export file.
334499ebb4caSwyllys 	 */
334599ebb4caSwyllys 
334699ebb4caSwyllys 	/* Start a PKCS#7 stack. */
334799ebb4caSwyllys 	authsafe_stack = sk_PKCS7_new_null();
334899ebb4caSwyllys 	if (authsafe_stack == NULL) {
334999ebb4caSwyllys 		HANDLE_PK12_ERROR
335099ebb4caSwyllys 	}
335199ebb4caSwyllys 	if (key_authsafe != NULL) {
335299ebb4caSwyllys 		if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
335399ebb4caSwyllys 			HANDLE_PK12_ERROR
335499ebb4caSwyllys 		}
335599ebb4caSwyllys 	}
335699ebb4caSwyllys 	if (cert_authsafe != NULL) {
335799ebb4caSwyllys 		if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
335899ebb4caSwyllys 			HANDLE_PK12_ERROR
335999ebb4caSwyllys 		}
336099ebb4caSwyllys 	}
336199ebb4caSwyllys 	p12_elem = PKCS12_init(NID_pkcs7_data);
336299ebb4caSwyllys 	if (p12_elem == NULL) {
336399ebb4caSwyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
336499ebb4caSwyllys 		HANDLE_PK12_ERROR
336599ebb4caSwyllys 	}
336699ebb4caSwyllys 
336799ebb4caSwyllys 	/* Put the PKCS#7 stack into the PKCS#12 element. */
336899ebb4caSwyllys 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
336999ebb4caSwyllys 		HANDLE_PK12_ERROR
337099ebb4caSwyllys 	}
337199ebb4caSwyllys 	/* Clear away the PKCS#7 stack, we're done with it. */
337299ebb4caSwyllys 	sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
337399ebb4caSwyllys 	authsafe_stack = NULL;
337499ebb4caSwyllys 
337599ebb4caSwyllys 	/* Set the integrity MAC on the PKCS#12 element. */
337699ebb4caSwyllys 	if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
337799ebb4caSwyllys 		NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
337899ebb4caSwyllys 		HANDLE_PK12_ERROR
337999ebb4caSwyllys 	}
338099ebb4caSwyllys 
338199ebb4caSwyllys 	/* Write the PKCS#12 element to the export file. */
338299ebb4caSwyllys 	if (!i2d_PKCS12_bio(bio, p12_elem)) {
338399ebb4caSwyllys 		HANDLE_PK12_ERROR
338499ebb4caSwyllys 	}
338599ebb4caSwyllys 
338699ebb4caSwyllys 	PKCS12_free(p12_elem);
338799ebb4caSwyllys out:
338899ebb4caSwyllys 	if (rv != KMF_OK) {
338999ebb4caSwyllys 		/* Clear away this bag_stack, we're done with it. */
339099ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
339199ebb4caSwyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
339299ebb4caSwyllys 	}
339399ebb4caSwyllys 	return (rv);
339499ebb4caSwyllys }
339599ebb4caSwyllys 
339699ebb4caSwyllys static EVP_PKEY *
339799ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
339899ebb4caSwyllys {
339999ebb4caSwyllys 	RSA		*rsa = NULL;
340099ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
340199ebb4caSwyllys 
340299ebb4caSwyllys 	if ((rsa = RSA_new()) == NULL)
340399ebb4caSwyllys 		return (NULL);
340499ebb4caSwyllys 
340599ebb4caSwyllys 	if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL)
340699ebb4caSwyllys 		return (NULL);
340799ebb4caSwyllys 
340899ebb4caSwyllys 	if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) ==
340999ebb4caSwyllys 		NULL)
341099ebb4caSwyllys 		return (NULL);
341199ebb4caSwyllys 
341299ebb4caSwyllys 	if (key->priexp.val != NULL)
341399ebb4caSwyllys 		if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len,
341499ebb4caSwyllys 			rsa->d)) == NULL)
341599ebb4caSwyllys 			return (NULL);
341699ebb4caSwyllys 
341799ebb4caSwyllys 	if (key->prime1.val != NULL)
341899ebb4caSwyllys 		if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len,
341999ebb4caSwyllys 			rsa->p)) == NULL)
342099ebb4caSwyllys 			return (NULL);
342199ebb4caSwyllys 
342299ebb4caSwyllys 	if (key->prime2.val != NULL)
342399ebb4caSwyllys 		if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len,
342499ebb4caSwyllys 			rsa->q)) == NULL)
342599ebb4caSwyllys 			return (NULL);
342699ebb4caSwyllys 
342799ebb4caSwyllys 	if (key->exp1.val != NULL)
342899ebb4caSwyllys 		if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len,
342999ebb4caSwyllys 			rsa->dmp1)) == NULL)
343099ebb4caSwyllys 			return (NULL);
343199ebb4caSwyllys 
343299ebb4caSwyllys 	if (key->exp2.val != NULL)
343399ebb4caSwyllys 		if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len,
343499ebb4caSwyllys 			rsa->dmq1)) == NULL)
343599ebb4caSwyllys 			return (NULL);
343699ebb4caSwyllys 
343799ebb4caSwyllys 	if (key->coef.val != NULL)
343899ebb4caSwyllys 		if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len,
343999ebb4caSwyllys 			rsa->iqmp)) == NULL)
344099ebb4caSwyllys 			return (NULL);
344199ebb4caSwyllys 
344299ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
344399ebb4caSwyllys 		return (NULL);
344499ebb4caSwyllys 
344599ebb4caSwyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
344699ebb4caSwyllys 
344799ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
344899ebb4caSwyllys 	RSA_free(rsa);
344999ebb4caSwyllys 
345099ebb4caSwyllys 	return (newkey);
345199ebb4caSwyllys }
345299ebb4caSwyllys 
345399ebb4caSwyllys static EVP_PKEY *
345499ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
345599ebb4caSwyllys {
345699ebb4caSwyllys 	DSA		*dsa = NULL;
345799ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
345899ebb4caSwyllys 
345999ebb4caSwyllys 	if ((dsa = DSA_new()) == NULL)
346099ebb4caSwyllys 		return (NULL);
346199ebb4caSwyllys 
346299ebb4caSwyllys 	if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len,
346399ebb4caSwyllys 		dsa->p)) == NULL)
346499ebb4caSwyllys 		return (NULL);
346599ebb4caSwyllys 
346699ebb4caSwyllys 	if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len,
346799ebb4caSwyllys 		dsa->q)) == NULL)
346899ebb4caSwyllys 		return (NULL);
346999ebb4caSwyllys 
347099ebb4caSwyllys 	if ((dsa->g = BN_bin2bn(key->base.val, key->base.len,
347199ebb4caSwyllys 		dsa->g)) == NULL)
347299ebb4caSwyllys 		return (NULL);
347399ebb4caSwyllys 
347499ebb4caSwyllys 	if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len,
347599ebb4caSwyllys 		dsa->priv_key)) == NULL)
347699ebb4caSwyllys 		return (NULL);
347799ebb4caSwyllys 
347899ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
347999ebb4caSwyllys 		return (NULL);
348099ebb4caSwyllys 
348199ebb4caSwyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
348299ebb4caSwyllys 
348399ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
348499ebb4caSwyllys 	DSA_free(dsa);
348599ebb4caSwyllys 	return (newkey);
348699ebb4caSwyllys }
348799ebb4caSwyllys 
348899ebb4caSwyllys static KMF_RETURN
348999ebb4caSwyllys ExportPK12FromRawData(KMF_HANDLE_T handle,
349099ebb4caSwyllys 	KMF_CREDENTIAL *cred,
349199ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
349299ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
349399ebb4caSwyllys 	char *filename)
349499ebb4caSwyllys {
349599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
349699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
349799ebb4caSwyllys 	BIO *bio = NULL;
349899ebb4caSwyllys 	X509 *xcert = NULL;
349999ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
350099ebb4caSwyllys 	int i;
350199ebb4caSwyllys 
350299ebb4caSwyllys 	/*
350399ebb4caSwyllys 	 * Open the output file.
350499ebb4caSwyllys 	 */
350599ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
350699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
350799ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
350899ebb4caSwyllys 		goto cleanup;
350999ebb4caSwyllys 	}
351099ebb4caSwyllys 
351199ebb4caSwyllys 	if (numcerts > 0 && numkeys > 0) {
351299ebb4caSwyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
351399ebb4caSwyllys 			KMF_RAW_KEY_DATA *key = NULL;
351499ebb4caSwyllys 			const uchar_t *p = certlist[i].certificate.Data;
351599ebb4caSwyllys 			long len = certlist[i].certificate.Length;
351699ebb4caSwyllys 
351799ebb4caSwyllys 			if (i < numkeys) {
351899ebb4caSwyllys 				key = (KMF_RAW_KEY_DATA *)keylist[i].keyp;
351999ebb4caSwyllys 
352099ebb4caSwyllys 				if (key->keytype == KMF_RSA) {
352199ebb4caSwyllys 					pkey = ImportRawRSAKey(
352299ebb4caSwyllys 						&key->rawdata.rsa);
352399ebb4caSwyllys 				} else if (key->keytype == KMF_DSA) {
352499ebb4caSwyllys 					pkey = ImportRawDSAKey(
352599ebb4caSwyllys 						&key->rawdata.dsa);
352699ebb4caSwyllys 				} else {
352799ebb4caSwyllys 					rv = KMF_ERR_BAD_PARAMETER;
352899ebb4caSwyllys 				}
352999ebb4caSwyllys 			}
353099ebb4caSwyllys 
353199ebb4caSwyllys 			xcert = d2i_X509(NULL, &p, len);
353299ebb4caSwyllys 			if (xcert == NULL) {
353399ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
353499ebb4caSwyllys 				rv = KMF_ERR_ENCODING;
353599ebb4caSwyllys 			}
353699ebb4caSwyllys 			/* Stick the key and the cert into a PKCS#12 file */
353799ebb4caSwyllys 			rv = write_pkcs12(kmfh, bio, cred, pkey, xcert);
353899ebb4caSwyllys 			if (xcert)
353999ebb4caSwyllys 				X509_free(xcert);
354099ebb4caSwyllys 			if (pkey)
354199ebb4caSwyllys 				EVP_PKEY_free(pkey);
354299ebb4caSwyllys 		}
354399ebb4caSwyllys 	}
354499ebb4caSwyllys 
354599ebb4caSwyllys cleanup:
354699ebb4caSwyllys 
354799ebb4caSwyllys 	if (bio != NULL)
354899ebb4caSwyllys 		(void) BIO_free_all(bio);
354999ebb4caSwyllys 
355099ebb4caSwyllys 	return (rv);
355199ebb4caSwyllys }
355299ebb4caSwyllys 
355399ebb4caSwyllys KMF_RETURN
355499ebb4caSwyllys OpenSSL_ExportP12(KMF_HANDLE_T handle,
355599ebb4caSwyllys 	KMF_EXPORTP12_PARAMS *params,
355699ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
355799ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
355899ebb4caSwyllys 	char *filename)
355999ebb4caSwyllys {
356099ebb4caSwyllys 	KMF_RETURN rv;
356199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
356299ebb4caSwyllys 	KMF_FINDCERT_PARAMS fcargs;
356399ebb4caSwyllys 	BIO *bio = NULL;
356499ebb4caSwyllys 	X509 *xcert = NULL;
356599ebb4caSwyllys 	char *fullpath = NULL;
356699ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
356799ebb4caSwyllys 
356899ebb4caSwyllys 	/*
356999ebb4caSwyllys 	 *  First, find the certificate.
357099ebb4caSwyllys 	 */
357199ebb4caSwyllys 	if (params == NULL)
357299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
357399ebb4caSwyllys 
357499ebb4caSwyllys 	/*
357599ebb4caSwyllys 	 * If the caller already sent the raw keys and certs,
357699ebb4caSwyllys 	 * shortcut the search and just export that
357799ebb4caSwyllys 	 * data.
357899ebb4caSwyllys 	 *
357999ebb4caSwyllys 	 * One *may* export a key OR a cert by itself.
358099ebb4caSwyllys 	 */
358199ebb4caSwyllys 	if (certlist != NULL || keylist != NULL) {
358299ebb4caSwyllys 		rv = ExportPK12FromRawData(handle,
358399ebb4caSwyllys 			&params->p12cred,
358499ebb4caSwyllys 			numcerts, certlist,
358599ebb4caSwyllys 			numkeys, keylist,
358699ebb4caSwyllys 			filename);
358799ebb4caSwyllys 		return (rv);
358899ebb4caSwyllys 	}
358999ebb4caSwyllys 
359099ebb4caSwyllys 	if (params->sslparms.certfile != NULL) {
359199ebb4caSwyllys 		fullpath = get_fullpath(params->sslparms.dirpath,
359299ebb4caSwyllys 			params->sslparms.certfile);
359399ebb4caSwyllys 
359499ebb4caSwyllys 		if (fullpath == NULL)
359599ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
359699ebb4caSwyllys 
359799ebb4caSwyllys 		if (isdir(fullpath)) {
359899ebb4caSwyllys 			free(fullpath);
359999ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
360099ebb4caSwyllys 		}
360199ebb4caSwyllys 
360299ebb4caSwyllys 		(void *)memset(&fcargs, 0, sizeof (fcargs));
360399ebb4caSwyllys 		fcargs.kstype = params->kstype;
360499ebb4caSwyllys 		fcargs.certLabel = params->certLabel;
360599ebb4caSwyllys 		fcargs.issuer = params->issuer;
360699ebb4caSwyllys 		fcargs.subject = params->subject;
360799ebb4caSwyllys 		fcargs.serial = params->serial;
360899ebb4caSwyllys 		fcargs.idstr = params->idstr;
360999ebb4caSwyllys 		fcargs.sslparms.dirpath = NULL;
361099ebb4caSwyllys 		fcargs.sslparms.certfile = fullpath;
361199ebb4caSwyllys 		fcargs.sslparms.format = params->sslparms.format;
361299ebb4caSwyllys 
361399ebb4caSwyllys 		rv = load_X509cert(kmfh, &fcargs, fullpath, &xcert);
361499ebb4caSwyllys 		if (rv != KMF_OK)
361599ebb4caSwyllys 			goto end;
361699ebb4caSwyllys 	}
361799ebb4caSwyllys 
361899ebb4caSwyllys 	/*
361999ebb4caSwyllys 	 * Now find the private key.
362099ebb4caSwyllys 	 */
362199ebb4caSwyllys 	if (params->sslparms.keyfile != NULL) {
362299ebb4caSwyllys 		fullpath = get_fullpath(params->sslparms.dirpath,
362399ebb4caSwyllys 			params->sslparms.keyfile);
362499ebb4caSwyllys 
362599ebb4caSwyllys 		if (fullpath == NULL)
362699ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
362799ebb4caSwyllys 
362899ebb4caSwyllys 		if (isdir(fullpath)) {
362999ebb4caSwyllys 			free(fullpath);
363099ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
363199ebb4caSwyllys 		}
363299ebb4caSwyllys 
363399ebb4caSwyllys 		pkey = openssl_load_key(handle, fullpath);
363499ebb4caSwyllys 		if (pkey == NULL) {
363599ebb4caSwyllys 			rv = KMF_ERR_KEY_NOT_FOUND;
363699ebb4caSwyllys 			goto end;
363799ebb4caSwyllys 		}
363899ebb4caSwyllys 	}
363999ebb4caSwyllys 
364099ebb4caSwyllys 	/*
364199ebb4caSwyllys 	 * Open the output file.
364299ebb4caSwyllys 	 */
364399ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
364499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
364599ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
364699ebb4caSwyllys 		goto end;
364799ebb4caSwyllys 	}
364899ebb4caSwyllys 
364999ebb4caSwyllys 	/* Stick the key and the cert into a PKCS#12 file */
365099ebb4caSwyllys 	rv = write_pkcs12(kmfh, bio, &params->p12cred,
365199ebb4caSwyllys 		pkey, xcert);
365299ebb4caSwyllys 
365399ebb4caSwyllys end:
365499ebb4caSwyllys 	if (fullpath)
365599ebb4caSwyllys 		free(fullpath);
365699ebb4caSwyllys 	if (xcert)
365799ebb4caSwyllys 		X509_free(xcert);
365899ebb4caSwyllys 	if (pkey)
365999ebb4caSwyllys 		EVP_PKEY_free(pkey);
366099ebb4caSwyllys 	if (bio)
366199ebb4caSwyllys 		(void) BIO_free(bio);
366299ebb4caSwyllys 
366399ebb4caSwyllys 	return (rv);
366499ebb4caSwyllys }
366599ebb4caSwyllys 
366671593db2Swyllys #define	MAX_CHAIN_LENGTH 100
366771593db2Swyllys /*
366871593db2Swyllys  * Helper function to extract keys and certificates from
366971593db2Swyllys  * a single PEM file.  Typically the file should contain a
367071593db2Swyllys  * private key and an associated public key wrapped in an x509 cert.
367171593db2Swyllys  * However, the file may be just a list of X509 certs with no keys.
367271593db2Swyllys  */
367371593db2Swyllys static KMF_RETURN
367402744e81Swyllys extract_objects(KMF_HANDLE *kmfh, KMF_FINDCERT_PARAMS *params,
367502744e81Swyllys 	char *filename, CK_UTF8CHAR *pin,
367671593db2Swyllys 	CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
367771593db2Swyllys 	int *numcerts)
367871593db2Swyllys /* ARGSUSED */
367971593db2Swyllys {
368071593db2Swyllys 	KMF_RETURN rv = KMF_OK;
368171593db2Swyllys 	FILE *fp;
368271593db2Swyllys 	STACK_OF(X509_INFO) *x509_info_stack;
368302744e81Swyllys 	int i, ncerts = 0, matchcerts = 0;
368471593db2Swyllys 	EVP_PKEY *pkey = NULL;
368571593db2Swyllys 	X509_INFO *info;
368671593db2Swyllys 	X509 *x;
368771593db2Swyllys 	X509_INFO *cert_infos[MAX_CHAIN_LENGTH];
368871593db2Swyllys 	KMF_DATA *certlist = NULL;
368971593db2Swyllys 
369071593db2Swyllys 	if (priv_key)
369171593db2Swyllys 		*priv_key = NULL;
369271593db2Swyllys 	if (certs)
369371593db2Swyllys 		*certs = NULL;
369471593db2Swyllys 	fp = fopen(filename, "r");
369571593db2Swyllys 	if (fp == NULL) {
369671593db2Swyllys 		return (KMF_ERR_OPEN_FILE);
369771593db2Swyllys 	}
369871593db2Swyllys 	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
369971593db2Swyllys 	if (x509_info_stack == NULL) {
370071593db2Swyllys 		(void) fclose(fp);
370171593db2Swyllys 		return (KMF_ERR_ENCODING);
370271593db2Swyllys 	}
370371593db2Swyllys 
370471593db2Swyllys 	/*LINTED*/
370571593db2Swyllys 	while ((info = sk_X509_INFO_pop(x509_info_stack)) != NULL &&
37066567ca1aSkrishna 		info->x509 != NULL && ncerts < MAX_CHAIN_LENGTH) {
370771593db2Swyllys 		cert_infos[ncerts] = info;
370871593db2Swyllys 		ncerts++;
370971593db2Swyllys 	}
371071593db2Swyllys 
371171593db2Swyllys 	if (ncerts == 0) {
371271593db2Swyllys 		(void) fclose(fp);
371371593db2Swyllys 		return (KMF_ERR_CERT_NOT_FOUND);
371471593db2Swyllys 	}
371571593db2Swyllys 
371671593db2Swyllys 	if (priv_key != NULL) {
371771593db2Swyllys 		rewind(fp);
371871593db2Swyllys 		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
371971593db2Swyllys 	}
372071593db2Swyllys 	(void) fclose(fp);
372171593db2Swyllys 
372271593db2Swyllys 	x = cert_infos[ncerts - 1]->x509;
372371593db2Swyllys 	/*
372471593db2Swyllys 	 * Make sure the private key matchs the last cert in the file.
372571593db2Swyllys 	 */
372671593db2Swyllys 	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
372771593db2Swyllys 		EVP_PKEY_free(pkey);
372871593db2Swyllys 		return (KMF_ERR_KEY_MISMATCH);
372971593db2Swyllys 	}
373071593db2Swyllys 
373171593db2Swyllys 	certlist = (KMF_DATA *)malloc(ncerts * sizeof (KMF_DATA));
373271593db2Swyllys 	if (certlist == NULL) {
373371593db2Swyllys 		if (pkey != NULL)
373471593db2Swyllys 			EVP_PKEY_free(pkey);
373571593db2Swyllys 		X509_INFO_free(info);
373671593db2Swyllys 		return (KMF_ERR_MEMORY);
373771593db2Swyllys 	}
373871593db2Swyllys 
373971593db2Swyllys 	/*
374071593db2Swyllys 	 * Convert all of the certs to DER format.
374171593db2Swyllys 	 */
374202744e81Swyllys 	matchcerts = 0;
374371593db2Swyllys 	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
374402744e81Swyllys 		boolean_t match = FALSE;
374571593db2Swyllys 		info =  cert_infos[ncerts - 1 - i];
374671593db2Swyllys 
374702744e81Swyllys 		if (params != NULL) {
374802744e81Swyllys 			rv = check_cert(info->x509, params, &match);
374902744e81Swyllys 			if (rv != KMF_OK || match != TRUE) {
375002744e81Swyllys 				X509_INFO_free(info);
375102744e81Swyllys 				rv = KMF_OK;
375202744e81Swyllys 				continue;
375302744e81Swyllys 			}
375402744e81Swyllys 		}
375502744e81Swyllys 
375602744e81Swyllys 		rv = ssl_cert2KMFDATA(kmfh, info->x509,
375702744e81Swyllys 			&certlist[matchcerts++]);
375871593db2Swyllys 
375971593db2Swyllys 		if (rv != KMF_OK) {
376071593db2Swyllys 			free(certlist);
376171593db2Swyllys 			certlist = NULL;
376202744e81Swyllys 			ncerts = matchcerts = 0;
376371593db2Swyllys 		}
376402744e81Swyllys 
376571593db2Swyllys 		X509_INFO_free(info);
376671593db2Swyllys 	}
376771593db2Swyllys 
376871593db2Swyllys 	if (numcerts != NULL)
376902744e81Swyllys 		*numcerts = matchcerts;
377071593db2Swyllys 	if (certs != NULL)
377171593db2Swyllys 		*certs = certlist;
377271593db2Swyllys 
377371593db2Swyllys 	if (priv_key == NULL && pkey != NULL)
377471593db2Swyllys 		EVP_PKEY_free(pkey);
377571593db2Swyllys 	else if (priv_key != NULL && pkey != NULL)
377671593db2Swyllys 		*priv_key = pkey;
377771593db2Swyllys 
377871593db2Swyllys 	return (rv);
377971593db2Swyllys }
378071593db2Swyllys 
378199ebb4caSwyllys /*
378299ebb4caSwyllys  * Helper function to decrypt and parse PKCS#12 import file.
378399ebb4caSwyllys  */
378499ebb4caSwyllys static KMF_RETURN
378599ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
378699ebb4caSwyllys 	EVP_PKEY **priv_key, X509 **cert, STACK_OF(X509) **ca)
378799ebb4caSwyllys /* ARGSUSED */
378899ebb4caSwyllys {
378999ebb4caSwyllys 	PKCS12		*pk12, *pk12_tmp;
379099ebb4caSwyllys 	EVP_PKEY	*temp_pkey = NULL;
379199ebb4caSwyllys 	X509		*temp_cert = NULL;
379299ebb4caSwyllys 	STACK_OF(X509)	*temp_ca = NULL;
379399ebb4caSwyllys 
379499ebb4caSwyllys 	if ((pk12 = PKCS12_new()) == NULL) {
379599ebb4caSwyllys 		return (KMF_ERR_MEMORY);
379699ebb4caSwyllys 	}
379799ebb4caSwyllys 
379899ebb4caSwyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
379999ebb4caSwyllys 		/* This is ok; it seems to mean there is no more to read. */
380099ebb4caSwyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
380199ebb4caSwyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
380299ebb4caSwyllys 			goto end_extract_pkcs12;
380399ebb4caSwyllys 
380499ebb4caSwyllys 		PKCS12_free(pk12);
380599ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
380699ebb4caSwyllys 	}
380799ebb4caSwyllys 	pk12 = pk12_tmp;
380899ebb4caSwyllys 
380999ebb4caSwyllys 	if (PKCS12_parse(pk12, (char *)pin, &temp_pkey, &temp_cert,
381099ebb4caSwyllys 	    &temp_ca) <= 0) {
381199ebb4caSwyllys 		PKCS12_free(pk12);
381299ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
381399ebb4caSwyllys 	}
381499ebb4caSwyllys 
381599ebb4caSwyllys end_extract_pkcs12:
381699ebb4caSwyllys 
381799ebb4caSwyllys 	*priv_key = temp_pkey;
381899ebb4caSwyllys 	*cert = temp_cert;
381999ebb4caSwyllys 	*ca = temp_ca;
382099ebb4caSwyllys 
382199ebb4caSwyllys 	PKCS12_free(pk12);
382299ebb4caSwyllys 	return (KMF_OK);
382399ebb4caSwyllys }
382499ebb4caSwyllys 
382599ebb4caSwyllys static KMF_RETURN
382699ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
382799ebb4caSwyllys {
382899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
382999ebb4caSwyllys 	uint32_t sz;
383099ebb4caSwyllys 
383199ebb4caSwyllys 	sz = BN_num_bytes(from);
383299ebb4caSwyllys 	to->val = (uchar_t *)malloc(sz);
383399ebb4caSwyllys 	if (to->val == NULL)
383499ebb4caSwyllys 		return (KMF_ERR_MEMORY);
383599ebb4caSwyllys 
383699ebb4caSwyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
383799ebb4caSwyllys 		free(to->val);
383899ebb4caSwyllys 		to->val = NULL;
383999ebb4caSwyllys 		to->len = 0;
384099ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
384199ebb4caSwyllys 	}
384299ebb4caSwyllys 
384399ebb4caSwyllys 	return (rv);
384499ebb4caSwyllys }
384599ebb4caSwyllys 
384699ebb4caSwyllys static KMF_RETURN
384799ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
384899ebb4caSwyllys {
384999ebb4caSwyllys 	KMF_RETURN rv;
385099ebb4caSwyllys 	KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
385199ebb4caSwyllys 
385299ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
385399ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK)
385499ebb4caSwyllys 		goto cleanup;
385599ebb4caSwyllys 
385699ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK)
385799ebb4caSwyllys 		goto cleanup;
385899ebb4caSwyllys 
385999ebb4caSwyllys 	if (rsa->d != NULL)
386099ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK)
386199ebb4caSwyllys 			goto cleanup;
386299ebb4caSwyllys 
386399ebb4caSwyllys 	if (rsa->p != NULL)
386499ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK)
386599ebb4caSwyllys 			goto cleanup;
386699ebb4caSwyllys 
386799ebb4caSwyllys 	if (rsa->q != NULL)
386899ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK)
386999ebb4caSwyllys 			goto cleanup;
387099ebb4caSwyllys 
387199ebb4caSwyllys 	if (rsa->dmp1 != NULL)
387299ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK)
387399ebb4caSwyllys 			goto cleanup;
387499ebb4caSwyllys 
387599ebb4caSwyllys 	if (rsa->dmq1 != NULL)
387699ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK)
387799ebb4caSwyllys 			goto cleanup;
387899ebb4caSwyllys 
387999ebb4caSwyllys 	if (rsa->iqmp != NULL)
388099ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK)
388199ebb4caSwyllys 			goto cleanup;
388299ebb4caSwyllys cleanup:
388399ebb4caSwyllys 	if (rv != KMF_OK)
388499ebb4caSwyllys 		KMF_FreeRawKey(key);
388599ebb4caSwyllys 	else
388699ebb4caSwyllys 		key->keytype = KMF_RSA;
388799ebb4caSwyllys 
388899ebb4caSwyllys 	/*
388999ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
389099ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
389199ebb4caSwyllys 	 */
389299ebb4caSwyllys 	RSA_free(rsa);
389399ebb4caSwyllys 
389499ebb4caSwyllys 	return (rv);
389599ebb4caSwyllys }
389699ebb4caSwyllys 
389799ebb4caSwyllys static KMF_RETURN
389899ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
389999ebb4caSwyllys {
390099ebb4caSwyllys 	KMF_RETURN rv;
390199ebb4caSwyllys 	KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
390299ebb4caSwyllys 
390399ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
390499ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK)
390599ebb4caSwyllys 		goto cleanup;
390699ebb4caSwyllys 
390799ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK)
390899ebb4caSwyllys 		goto cleanup;
390999ebb4caSwyllys 
391099ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK)
391199ebb4caSwyllys 		goto cleanup;
391299ebb4caSwyllys 
391399ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK)
391499ebb4caSwyllys 		goto cleanup;
391599ebb4caSwyllys 
391699ebb4caSwyllys cleanup:
391799ebb4caSwyllys 	if (rv != KMF_OK)
391899ebb4caSwyllys 		KMF_FreeRawKey(key);
391999ebb4caSwyllys 	else
392099ebb4caSwyllys 		key->keytype = KMF_DSA;
392199ebb4caSwyllys 
392299ebb4caSwyllys 	/*
392399ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
392499ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
392599ebb4caSwyllys 	 */
392699ebb4caSwyllys 	DSA_free(dsa);
392799ebb4caSwyllys 
392899ebb4caSwyllys 	return (rv);
392999ebb4caSwyllys }
393099ebb4caSwyllys 
393199ebb4caSwyllys static KMF_RETURN
393299ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
393399ebb4caSwyllys 	KMF_DATA **certlist, int *ncerts)
393499ebb4caSwyllys {
393599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
393699ebb4caSwyllys 	KMF_DATA *list = (*certlist);
393799ebb4caSwyllys 	KMF_DATA cert;
393899ebb4caSwyllys 	int n = (*ncerts);
393999ebb4caSwyllys 
394099ebb4caSwyllys 	if (list == NULL) {
394199ebb4caSwyllys 		list = (KMF_DATA *)malloc(sizeof (KMF_DATA));
394299ebb4caSwyllys 	} else {
394399ebb4caSwyllys 		list = (KMF_DATA *)realloc(list, sizeof (KMF_DATA) * (n + 1));
394499ebb4caSwyllys 	}
394599ebb4caSwyllys 
394699ebb4caSwyllys 	if (list == NULL)
394799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
394899ebb4caSwyllys 
394999ebb4caSwyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert);
395099ebb4caSwyllys 	if (rv == KMF_OK) {
395199ebb4caSwyllys 		list[n] = cert;
395299ebb4caSwyllys 		(*ncerts) = n + 1;
395399ebb4caSwyllys 
395499ebb4caSwyllys 		*certlist = list;
395599ebb4caSwyllys 	} else {
395699ebb4caSwyllys 		free(list);
395799ebb4caSwyllys 	}
395899ebb4caSwyllys 
395999ebb4caSwyllys 	return (rv);
396099ebb4caSwyllys }
396199ebb4caSwyllys 
396299ebb4caSwyllys static KMF_RETURN
396399ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
396499ebb4caSwyllys 	KMF_RAW_KEY_DATA *newkey, int *nkeys)
396599ebb4caSwyllys {
396699ebb4caSwyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
396799ebb4caSwyllys 	int n = (*nkeys);
396899ebb4caSwyllys 
396999ebb4caSwyllys 	if (list == NULL) {
397099ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
397199ebb4caSwyllys 	} else {
397299ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
397399ebb4caSwyllys 			sizeof (KMF_RAW_KEY_DATA) * (n + 1));
397499ebb4caSwyllys 	}
397599ebb4caSwyllys 
397699ebb4caSwyllys 	if (list == NULL)
397799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
397899ebb4caSwyllys 
397999ebb4caSwyllys 	list[n] = *newkey;
398099ebb4caSwyllys 	(*nkeys) = n + 1;
398199ebb4caSwyllys 
398299ebb4caSwyllys 	*keylist = list;
398399ebb4caSwyllys 
398499ebb4caSwyllys 	return (KMF_OK);
398599ebb4caSwyllys }
398699ebb4caSwyllys 
398799ebb4caSwyllys 
398899ebb4caSwyllys static KMF_RETURN
398999ebb4caSwyllys convertPK12Objects(
399099ebb4caSwyllys 	KMF_HANDLE *kmfh,
399199ebb4caSwyllys 	EVP_PKEY *sslkey, X509 *sslcert, STACK_OF(X509) *sslcacerts,
399299ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
399399ebb4caSwyllys 	KMF_DATA **certlist, int *ncerts)
399499ebb4caSwyllys {
399599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
399699ebb4caSwyllys 	KMF_RAW_KEY_DATA key;
399799ebb4caSwyllys 	int i;
399899ebb4caSwyllys 
399999ebb4caSwyllys 	if (sslkey != NULL) {
400099ebb4caSwyllys 		/* Convert SSL key to raw key */
400199ebb4caSwyllys 		switch (sslkey->type) {
400299ebb4caSwyllys 			case EVP_PKEY_RSA:
400399ebb4caSwyllys 				rv = exportRawRSAKey(EVP_PKEY_get1_RSA(sslkey),
400499ebb4caSwyllys 					&key);
400599ebb4caSwyllys 				if (rv != KMF_OK)
400699ebb4caSwyllys 					return (rv);
400799ebb4caSwyllys 
400899ebb4caSwyllys 				break;
400999ebb4caSwyllys 			case EVP_PKEY_DSA:
401099ebb4caSwyllys 				rv = exportRawDSAKey(EVP_PKEY_get1_DSA(sslkey),
401199ebb4caSwyllys 					&key);
401299ebb4caSwyllys 				if (rv != KMF_OK)
401399ebb4caSwyllys 					return (rv);
401499ebb4caSwyllys 
401599ebb4caSwyllys 				break;
401699ebb4caSwyllys 			default:
401799ebb4caSwyllys 				return (KMF_ERR_BAD_PARAMETER);
401899ebb4caSwyllys 		}
401999ebb4caSwyllys 
402099ebb4caSwyllys 		rv = add_key_to_list(keylist, &key, nkeys);
402199ebb4caSwyllys 		if (rv != KMF_OK)
402299ebb4caSwyllys 			return (rv);
402399ebb4caSwyllys 	}
402499ebb4caSwyllys 
402599ebb4caSwyllys 	/* Now add the certificate to the certlist */
402699ebb4caSwyllys 	if (sslcert != NULL) {
402799ebb4caSwyllys 		rv = add_cert_to_list(kmfh, sslcert, certlist, ncerts);
402899ebb4caSwyllys 		if (rv != KMF_OK)
402999ebb4caSwyllys 			return (rv);
403099ebb4caSwyllys 	}
403199ebb4caSwyllys 
403299ebb4caSwyllys 	/* Also add any included CA certs to the list */
403371593db2Swyllys 	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
403499ebb4caSwyllys 		X509 *c;
403599ebb4caSwyllys 		/*
403699ebb4caSwyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
403799ebb4caSwyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
403899ebb4caSwyllys 		 * Lint is complaining about the embedded casting, and
403999ebb4caSwyllys 		 * to fix it, you need to fix openssl header files.
404099ebb4caSwyllys 		 */
404199ebb4caSwyllys 		/* LINTED E_BAD_PTR_CAST_ALIGN */
404299ebb4caSwyllys 		c = sk_X509_value(sslcacerts, i);
404399ebb4caSwyllys 
404499ebb4caSwyllys 		/* Now add the ca cert to the certlist */
404599ebb4caSwyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
404699ebb4caSwyllys 		if (rv != KMF_OK)
404799ebb4caSwyllys 			return (rv);
404899ebb4caSwyllys 	}
404999ebb4caSwyllys 	return (rv);
405099ebb4caSwyllys }
405199ebb4caSwyllys 
405299ebb4caSwyllys KMF_RETURN
405399ebb4caSwyllys openssl_read_pkcs12(KMF_HANDLE *kmfh,
405499ebb4caSwyllys 	char *filename, KMF_CREDENTIAL *cred,
405599ebb4caSwyllys 	KMF_DATA **certlist, int *ncerts,
405699ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
405799ebb4caSwyllys {
405899ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
405999ebb4caSwyllys 	BIO		*bio = NULL;
406099ebb4caSwyllys 	EVP_PKEY	*privkey = NULL;
406199ebb4caSwyllys 	X509		*cert = NULL;
406299ebb4caSwyllys 	STACK_OF(X509)	*cacerts = NULL;
406399ebb4caSwyllys 
406499ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
406599ebb4caSwyllys 	if (bio == NULL) {
406699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
406799ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
406899ebb4caSwyllys 		goto end;
406999ebb4caSwyllys 	}
407099ebb4caSwyllys 
407199ebb4caSwyllys 	*certlist = NULL;
407299ebb4caSwyllys 	*keylist = NULL;
407399ebb4caSwyllys 	*ncerts = 0;
407499ebb4caSwyllys 	*nkeys = 0;
40756adaf03eSwyllys 
407699ebb4caSwyllys 	rv = extract_pkcs12(bio,
407799ebb4caSwyllys 		(uchar_t *)cred->cred,
407899ebb4caSwyllys 		(uint32_t)cred->credlen,
407999ebb4caSwyllys 		&privkey, &cert, &cacerts);
408099ebb4caSwyllys 
408199ebb4caSwyllys 	if (rv == KMF_OK)
408299ebb4caSwyllys 		/* Convert keys and certs to exportable format */
408399ebb4caSwyllys 		rv = convertPK12Objects(kmfh, privkey, cert, cacerts,
408499ebb4caSwyllys 			keylist, nkeys, certlist, ncerts);
408599ebb4caSwyllys 
408699ebb4caSwyllys end:
408799ebb4caSwyllys 	if (bio != NULL)
408899ebb4caSwyllys 		(void) BIO_free(bio);
408999ebb4caSwyllys 
409099ebb4caSwyllys 	if (privkey)
409199ebb4caSwyllys 		EVP_PKEY_free(privkey);
409299ebb4caSwyllys 
409399ebb4caSwyllys 	if (cert)
409499ebb4caSwyllys 		X509_free(cert);
409599ebb4caSwyllys 
409699ebb4caSwyllys 	if (cacerts)
409799ebb4caSwyllys 		sk_X509_free(cacerts);
409899ebb4caSwyllys 
409999ebb4caSwyllys 	return (rv);
410099ebb4caSwyllys }
410199ebb4caSwyllys 
410299ebb4caSwyllys KMF_RETURN
410371593db2Swyllys openssl_import_keypair(KMF_HANDLE *kmfh,
410471593db2Swyllys 	char *filename, KMF_CREDENTIAL *cred,
410571593db2Swyllys 	KMF_DATA **certlist, int *ncerts,
410671593db2Swyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
410771593db2Swyllys {
410871593db2Swyllys 	KMF_RETURN	rv = KMF_OK;
410971593db2Swyllys 	EVP_PKEY	*privkey = NULL;
411071593db2Swyllys 	KMF_ENCODE_FORMAT format;
411171593db2Swyllys 
411271593db2Swyllys 	/*
411371593db2Swyllys 	 * auto-detect the file format, regardless of what
411471593db2Swyllys 	 * the 'format' parameters in the params say.
411571593db2Swyllys 	 */
411671593db2Swyllys 	rv = KMF_GetFileFormat(filename, &format);
411771593db2Swyllys 	if (rv != KMF_OK) {
411871593db2Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
411971593db2Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
412071593db2Swyllys 		return (rv);
412171593db2Swyllys 	}
412271593db2Swyllys 
412371593db2Swyllys 	/* This function only works on PEM files */
412471593db2Swyllys 	if (format != KMF_FORMAT_PEM &&
412571593db2Swyllys 		format != KMF_FORMAT_PEM_KEYPAIR)
412671593db2Swyllys 		return (KMF_ERR_ENCODING);
412771593db2Swyllys 
412871593db2Swyllys 	*certlist = NULL;
412971593db2Swyllys 	*keylist = NULL;
413071593db2Swyllys 	*ncerts = 0;
413171593db2Swyllys 	*nkeys = 0;
413202744e81Swyllys 	rv = extract_objects(kmfh, NULL, filename,
413371593db2Swyllys 		(uchar_t *)cred->cred,
413471593db2Swyllys 		(uint32_t)cred->credlen,
413571593db2Swyllys 		&privkey, certlist, ncerts);
413671593db2Swyllys 
413771593db2Swyllys 	/* Reached end of import file? */
413871593db2Swyllys 	if (rv == KMF_OK)
413971593db2Swyllys 		/* Convert keys and certs to exportable format */
414071593db2Swyllys 		rv = convertPK12Objects(kmfh, privkey, NULL, NULL,
414171593db2Swyllys 			keylist, nkeys, NULL, NULL);
414271593db2Swyllys 
414371593db2Swyllys end:
414471593db2Swyllys 	if (privkey)
414571593db2Swyllys 		EVP_PKEY_free(privkey);
414671593db2Swyllys 
414771593db2Swyllys 	return (rv);
414871593db2Swyllys }
414971593db2Swyllys 
415071593db2Swyllys KMF_RETURN
415199ebb4caSwyllys OpenSSL_StorePrivateKey(KMF_HANDLE_T handle, KMF_STOREKEY_PARAMS *params,
415299ebb4caSwyllys 	KMF_RAW_KEY_DATA *key)
415399ebb4caSwyllys {
415499ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
415599ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
415699ebb4caSwyllys 	char		*fullpath;
415799ebb4caSwyllys 	EVP_PKEY	*pkey = NULL;
415899ebb4caSwyllys 	BIO		*bio = NULL;
415999ebb4caSwyllys 
416099ebb4caSwyllys 	if (key != NULL) {
416199ebb4caSwyllys 		if (key->keytype == KMF_RSA) {
416299ebb4caSwyllys 			pkey = ImportRawRSAKey(&key->rawdata.rsa);
416399ebb4caSwyllys 		} else if (key->keytype == KMF_DSA) {
416499ebb4caSwyllys 			pkey = ImportRawDSAKey(&key->rawdata.dsa);
416599ebb4caSwyllys 		} else {
416699ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
416799ebb4caSwyllys 		}
416899ebb4caSwyllys 	} else {
416999ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
417099ebb4caSwyllys 	}
417199ebb4caSwyllys 	if (rv != KMF_OK || pkey == NULL)
417299ebb4caSwyllys 		return (rv);
417399ebb4caSwyllys 
417499ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
417599ebb4caSwyllys 			params->sslparms.keyfile);
417699ebb4caSwyllys 
417799ebb4caSwyllys 	if (fullpath == NULL)
417899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
417999ebb4caSwyllys 
418099ebb4caSwyllys 	/* If the requested file exists, return an error */
418199ebb4caSwyllys 	if (access(fullpath, F_OK) == 0) {
418299ebb4caSwyllys 		free(fullpath);
418399ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
418499ebb4caSwyllys 	}
418599ebb4caSwyllys 
418699ebb4caSwyllys 	bio = BIO_new_file(fullpath, "wb");
418799ebb4caSwyllys 	if (bio == NULL) {
418899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
418999ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
419099ebb4caSwyllys 		goto cleanup;
419199ebb4caSwyllys 	}
419299ebb4caSwyllys 
419399ebb4caSwyllys 	rv = ssl_write_private_key(kmfh,
419499ebb4caSwyllys 		params->sslparms.format,
419599ebb4caSwyllys 		bio, &params->cred, pkey);
419699ebb4caSwyllys 
419799ebb4caSwyllys cleanup:
419899ebb4caSwyllys 	if (fullpath)
419999ebb4caSwyllys 		free(fullpath);
420099ebb4caSwyllys 
420199ebb4caSwyllys 	if (pkey)
420299ebb4caSwyllys 		EVP_PKEY_free(pkey);
420399ebb4caSwyllys 
420499ebb4caSwyllys 	if (bio)
420599ebb4caSwyllys 		(void) BIO_free(bio);
420699ebb4caSwyllys 
420799ebb4caSwyllys 	/* Protect the file by making it read-only */
420899ebb4caSwyllys 	if (rv == KMF_OK) {
420999ebb4caSwyllys 		(void) chmod(fullpath, 0400);
421099ebb4caSwyllys 	}
421199ebb4caSwyllys 	return (rv);
421299ebb4caSwyllys }
421399ebb4caSwyllys 
421499ebb4caSwyllys static KMF_RETURN
421599ebb4caSwyllys create_deskey(DES_cblock **deskey)
421699ebb4caSwyllys {
421799ebb4caSwyllys 	DES_cblock *key;
421899ebb4caSwyllys 
421999ebb4caSwyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
422099ebb4caSwyllys 	if (key == NULL) {
422199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
422299ebb4caSwyllys 	}
422399ebb4caSwyllys 
422499ebb4caSwyllys 	if (DES_random_key(key) == 0) {
422599ebb4caSwyllys 		free(key);
422699ebb4caSwyllys 		return (KMF_ERR_KEYGEN_FAILED);
422799ebb4caSwyllys 	}
422899ebb4caSwyllys 
422999ebb4caSwyllys 	*deskey = key;
423099ebb4caSwyllys 	return (KMF_OK);
423199ebb4caSwyllys }
423299ebb4caSwyllys 
423399ebb4caSwyllys #define	KEYGEN_RETRY 3
423499ebb4caSwyllys #define	DES3_KEY_SIZE 24
423599ebb4caSwyllys 
423699ebb4caSwyllys static KMF_RETURN
423799ebb4caSwyllys create_des3key(unsigned char **des3key)
423899ebb4caSwyllys {
423999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
424099ebb4caSwyllys 	DES_cblock *deskey1 = NULL;
424199ebb4caSwyllys 	DES_cblock *deskey2 = NULL;
424299ebb4caSwyllys 	DES_cblock *deskey3 = NULL;
424399ebb4caSwyllys 	unsigned char *newkey = NULL;
424499ebb4caSwyllys 	int retry;
424599ebb4caSwyllys 
424699ebb4caSwyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
424799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
424899ebb4caSwyllys 	}
424999ebb4caSwyllys 
425099ebb4caSwyllys 	/* create the 1st DES key */
425199ebb4caSwyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
425299ebb4caSwyllys 		goto out;
425399ebb4caSwyllys 	}
425499ebb4caSwyllys 
425599ebb4caSwyllys 	/*
425699ebb4caSwyllys 	 * Create the 2nd DES key and make sure its value is different
425799ebb4caSwyllys 	 * from the 1st DES key.
425899ebb4caSwyllys 	 */
425999ebb4caSwyllys 	retry = 0;
426099ebb4caSwyllys 	do {
426199ebb4caSwyllys 		if (deskey2 != NULL) {
426299ebb4caSwyllys 			free(deskey2);
426399ebb4caSwyllys 			deskey2 = NULL;
426499ebb4caSwyllys 		}
426599ebb4caSwyllys 
426699ebb4caSwyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
426799ebb4caSwyllys 			goto out;
426899ebb4caSwyllys 		}
426999ebb4caSwyllys 
427099ebb4caSwyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
427199ebb4caSwyllys 		    == 0) {
427299ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
427399ebb4caSwyllys 			retry++;
427499ebb4caSwyllys 		}
427599ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
427699ebb4caSwyllys 
427799ebb4caSwyllys 	if (ret != KMF_OK) {
427899ebb4caSwyllys 		goto out;
427999ebb4caSwyllys 	}
428099ebb4caSwyllys 
428199ebb4caSwyllys 	/*
428299ebb4caSwyllys 	 * Create the 3rd DES key and make sure its value is different
428399ebb4caSwyllys 	 * from the 2nd DES key.
428499ebb4caSwyllys 	 */
428599ebb4caSwyllys 	retry = 0;
428699ebb4caSwyllys 	do {
428799ebb4caSwyllys 		if (deskey3 != NULL) {
428899ebb4caSwyllys 			free(deskey3);
428999ebb4caSwyllys 			deskey3 = NULL;
429099ebb4caSwyllys 		}
429199ebb4caSwyllys 
429299ebb4caSwyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
429399ebb4caSwyllys 			goto out;
429499ebb4caSwyllys 		}
429599ebb4caSwyllys 
429699ebb4caSwyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
429799ebb4caSwyllys 		    == 0) {
429899ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
429999ebb4caSwyllys 			retry++;
430099ebb4caSwyllys 		}
430199ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
430299ebb4caSwyllys 
430399ebb4caSwyllys 	if (ret != KMF_OK) {
430499ebb4caSwyllys 		goto out;
430599ebb4caSwyllys 	}
430699ebb4caSwyllys 
430799ebb4caSwyllys 	/* Concatenate 3 DES keys into a DES3 key */
430899ebb4caSwyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
430999ebb4caSwyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
431099ebb4caSwyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
431199ebb4caSwyllys 	*des3key = newkey;
431299ebb4caSwyllys 
431399ebb4caSwyllys out:
431499ebb4caSwyllys 	if (deskey1 != NULL)
431599ebb4caSwyllys 		free(deskey1);
431699ebb4caSwyllys 
431799ebb4caSwyllys 	if (deskey2 != NULL)
431899ebb4caSwyllys 		free(deskey2);
431999ebb4caSwyllys 
432099ebb4caSwyllys 	if (deskey3 != NULL)
432199ebb4caSwyllys 		free(deskey3);
432299ebb4caSwyllys 
432399ebb4caSwyllys 	if (ret != KMF_OK && newkey != NULL)
432499ebb4caSwyllys 		free(newkey);
432599ebb4caSwyllys 
432699ebb4caSwyllys 	return (ret);
432799ebb4caSwyllys }
432899ebb4caSwyllys 
432999ebb4caSwyllys KMF_RETURN
433099ebb4caSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle, KMF_CREATESYMKEY_PARAMS *params,
433199ebb4caSwyllys 	KMF_KEY_HANDLE *symkey)
433299ebb4caSwyllys {
433399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
433499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
433599ebb4caSwyllys 	char *fullpath = NULL;
433699ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
433799ebb4caSwyllys 	DES_cblock *deskey = NULL;
433899ebb4caSwyllys 	unsigned char *des3key = NULL;
433999ebb4caSwyllys 	unsigned char *random = NULL;
434099ebb4caSwyllys 	int fd = -1;
434199ebb4caSwyllys 
434299ebb4caSwyllys 	if (kmfh == NULL)
434399ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
434499ebb4caSwyllys 
434599ebb4caSwyllys 	if (params == NULL || params->sslparms.keyfile == NULL) {
434699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
434799ebb4caSwyllys 	}
434899ebb4caSwyllys 
434999ebb4caSwyllys 	fullpath = get_fullpath(params->sslparms.dirpath,
435099ebb4caSwyllys 		params->sslparms.keyfile);
435199ebb4caSwyllys 	if (fullpath == NULL)
435299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
435399ebb4caSwyllys 
435499ebb4caSwyllys 	/* If the requested file exists, return an error */
435599ebb4caSwyllys 	if (access(fullpath, F_OK) == 0) {
435699ebb4caSwyllys 		free(fullpath);
435799ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
435899ebb4caSwyllys 	}
435999ebb4caSwyllys 
436099ebb4caSwyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
436199ebb4caSwyllys 	if (fd == -1) {
436299ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
436399ebb4caSwyllys 		goto out;
436499ebb4caSwyllys 	}
436599ebb4caSwyllys 
436699ebb4caSwyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
436799ebb4caSwyllys 	if (rkey == NULL) {
436899ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
436999ebb4caSwyllys 		goto out;
437099ebb4caSwyllys 	}
437199ebb4caSwyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
437299ebb4caSwyllys 
437399ebb4caSwyllys 	if (params->keytype == KMF_DES) {
437499ebb4caSwyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
437599ebb4caSwyllys 			goto out;
437699ebb4caSwyllys 		}
437799ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)deskey;
437899ebb4caSwyllys 		rkey->keydata.len = 8;
437999ebb4caSwyllys 
438099ebb4caSwyllys 		symkey->keyalg = KMF_DES;
438199ebb4caSwyllys 
438299ebb4caSwyllys 	} else if (params->keytype == KMF_DES3) {
438399ebb4caSwyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
438499ebb4caSwyllys 			goto out;
438599ebb4caSwyllys 		}
438699ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)des3key;
438799ebb4caSwyllys 		rkey->keydata.len = DES3_KEY_SIZE;
438899ebb4caSwyllys 		symkey->keyalg = KMF_DES3;
43899b37d296Swyllys 
4390c197cb9dShylee 	} else if (params->keytype == KMF_AES || params->keytype == KMF_RC4 ||
4391c197cb9dShylee 	    params->keytype == KMF_GENERIC_SECRET) {
439299ebb4caSwyllys 		int bytes;
439399ebb4caSwyllys 
439499ebb4caSwyllys 		if (params->keylength % 8 != 0) {
439599ebb4caSwyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
439699ebb4caSwyllys 			goto out;
439799ebb4caSwyllys 		}
439899ebb4caSwyllys 
439999ebb4caSwyllys 		if (params->keytype == KMF_AES) {
440099ebb4caSwyllys 			if (params->keylength != 128 &&
440199ebb4caSwyllys 			    params->keylength != 192 &&
440299ebb4caSwyllys 			    params->keylength != 256) {
440399ebb4caSwyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
440499ebb4caSwyllys 				goto out;
440599ebb4caSwyllys 			}
440699ebb4caSwyllys 		}
440799ebb4caSwyllys 
440899ebb4caSwyllys 		bytes = params->keylength/8;
440999ebb4caSwyllys 		random = malloc(bytes);
441099ebb4caSwyllys 		if (random == NULL) {
441199ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
441299ebb4caSwyllys 			goto out;
441399ebb4caSwyllys 		}
441499ebb4caSwyllys 		if (RAND_bytes(random, bytes) != 1) {
441599ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
441699ebb4caSwyllys 			goto out;
441799ebb4caSwyllys 		}
441899ebb4caSwyllys 
441999ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)random;
442099ebb4caSwyllys 		rkey->keydata.len = bytes;
442199ebb4caSwyllys 		symkey->keyalg = params->keytype;
442299ebb4caSwyllys 
442399ebb4caSwyllys 	} else {
442499ebb4caSwyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
442599ebb4caSwyllys 		goto out;
442699ebb4caSwyllys 	}
442799ebb4caSwyllys 
442899ebb4caSwyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
442999ebb4caSwyllys 
443099ebb4caSwyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
443199ebb4caSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
443299ebb4caSwyllys 	symkey->keylabel = (char *)fullpath;
443399ebb4caSwyllys 	symkey->israw = TRUE;
443499ebb4caSwyllys 	symkey->keyp = rkey;
443599ebb4caSwyllys 
443699ebb4caSwyllys out:
443799ebb4caSwyllys 	if (fd != -1)
443899ebb4caSwyllys 		(void) close(fd);
443999ebb4caSwyllys 
444099ebb4caSwyllys 	if (ret != KMF_OK && fullpath != NULL) {
444199ebb4caSwyllys 		free(fullpath);
444299ebb4caSwyllys 	}
444399ebb4caSwyllys 	if (ret != KMF_OK) {
444499ebb4caSwyllys 		KMF_FreeRawSymKey(rkey);
444599ebb4caSwyllys 		symkey->keyp = NULL;
444699ebb4caSwyllys 		symkey->keyalg = KMF_KEYALG_NONE;
444799ebb4caSwyllys 	}
444899ebb4caSwyllys 
444999ebb4caSwyllys 	return (ret);
445099ebb4caSwyllys }
445199ebb4caSwyllys 
445299ebb4caSwyllys 
445399ebb4caSwyllys KMF_RETURN
445499ebb4caSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, KMF_VERIFYCRL_PARAMS *params)
445599ebb4caSwyllys {
445699ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
445799ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
445899ebb4caSwyllys 	BIO		*bcrl = NULL;
445999ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
446099ebb4caSwyllys 	X509		*xcert = NULL;
446199ebb4caSwyllys 	EVP_PKEY	*pkey;
446299ebb4caSwyllys 	int		sslret;
446399ebb4caSwyllys 	KMF_ENCODE_FORMAT crl_format;
446499ebb4caSwyllys 	unsigned char	*p;
446599ebb4caSwyllys 	long		len;
446699ebb4caSwyllys 
446799ebb4caSwyllys 	if (params->crl_name == NULL || params->tacert == NULL) {
446899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
446999ebb4caSwyllys 	}
447099ebb4caSwyllys 
447199ebb4caSwyllys 	ret = KMF_GetFileFormat(params->crl_name, &crl_format);
447299ebb4caSwyllys 	if (ret != KMF_OK)
447399ebb4caSwyllys 		return (ret);
447499ebb4caSwyllys 
447599ebb4caSwyllys 	bcrl = BIO_new_file(params->crl_name, "rb");
447699ebb4caSwyllys 	if (bcrl == NULL)	{
447799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
447899ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
447999ebb4caSwyllys 		goto cleanup;
448099ebb4caSwyllys 	}
448199ebb4caSwyllys 
448299ebb4caSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
448399ebb4caSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
448499ebb4caSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
448599ebb4caSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
448699ebb4caSwyllys 	} else {
448799ebb4caSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
448899ebb4caSwyllys 		goto cleanup;
448999ebb4caSwyllys 	}
449099ebb4caSwyllys 
449199ebb4caSwyllys 	if (xcrl == NULL) {
449299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
449399ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
449499ebb4caSwyllys 		goto cleanup;
449599ebb4caSwyllys 	}
449699ebb4caSwyllys 
449799ebb4caSwyllys 	p = params->tacert->Data;
449899ebb4caSwyllys 	len = params->tacert->Length;
449999ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
450099ebb4caSwyllys 
450199ebb4caSwyllys 	if (xcert == NULL) {
450299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
450399ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
450499ebb4caSwyllys 		goto cleanup;
450599ebb4caSwyllys 	}
450699ebb4caSwyllys 
450799ebb4caSwyllys 	/* Get issuer certificate public key */
450899ebb4caSwyllys 	pkey = X509_get_pubkey(xcert);
450999ebb4caSwyllys 	if (!pkey) {
451099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
451199ebb4caSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
451299ebb4caSwyllys 		goto cleanup;
451399ebb4caSwyllys 	}
451499ebb4caSwyllys 
451599ebb4caSwyllys 	/* Verify CRL signature */
451699ebb4caSwyllys 	sslret = X509_CRL_verify(xcrl, pkey);
451799ebb4caSwyllys 	EVP_PKEY_free(pkey);
451899ebb4caSwyllys 	if (sslret > 0) {
451999ebb4caSwyllys 		ret = KMF_OK;
452099ebb4caSwyllys 	} else {
452199ebb4caSwyllys 		SET_ERROR(kmfh, sslret);
452299ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
452399ebb4caSwyllys 	}
452499ebb4caSwyllys 
452599ebb4caSwyllys cleanup:
452699ebb4caSwyllys 	if (bcrl != NULL)
452799ebb4caSwyllys 		(void) BIO_free(bcrl);
452899ebb4caSwyllys 
452999ebb4caSwyllys 	if (xcrl != NULL)
453099ebb4caSwyllys 		X509_CRL_free(xcrl);
453199ebb4caSwyllys 
453299ebb4caSwyllys 	if (xcert != NULL)
453399ebb4caSwyllys 		X509_free(xcert);
453499ebb4caSwyllys 
453599ebb4caSwyllys 	return (ret);
453699ebb4caSwyllys 
453799ebb4caSwyllys }
453899ebb4caSwyllys 
453999ebb4caSwyllys KMF_RETURN
454099ebb4caSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle,
454199ebb4caSwyllys 	KMF_CHECKCRLDATE_PARAMS *params)
454299ebb4caSwyllys {
454399ebb4caSwyllys 
454499ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
454599ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
454699ebb4caSwyllys 	KMF_ENCODE_FORMAT crl_format;
454799ebb4caSwyllys 	BIO		*bcrl = NULL;
454899ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
454999ebb4caSwyllys 	int		i;
455099ebb4caSwyllys 
455199ebb4caSwyllys 	if (params == NULL || params->crl_name == NULL) {
455299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
455399ebb4caSwyllys 	}
455499ebb4caSwyllys 
455599ebb4caSwyllys 	ret = KMF_IsCRLFile(handle, params->crl_name, &crl_format);
455699ebb4caSwyllys 	if (ret != KMF_OK)
455799ebb4caSwyllys 		return (ret);
455899ebb4caSwyllys 
455999ebb4caSwyllys 	bcrl = BIO_new_file(params->crl_name, "rb");
456099ebb4caSwyllys 	if (bcrl == NULL)	{
456199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
456299ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
456399ebb4caSwyllys 		goto cleanup;
456499ebb4caSwyllys 	}
456599ebb4caSwyllys 
456699ebb4caSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
456799ebb4caSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
456899ebb4caSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
456999ebb4caSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
457099ebb4caSwyllys 	}
457199ebb4caSwyllys 
457299ebb4caSwyllys 	if (xcrl == NULL) {
457399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
457499ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
457599ebb4caSwyllys 		goto cleanup;
457699ebb4caSwyllys 	}
457799ebb4caSwyllys 
457899ebb4caSwyllys 	i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL);
457999ebb4caSwyllys 	if (i >= 0) {
458099ebb4caSwyllys 		ret = KMF_ERR_VALIDITY_PERIOD;
458199ebb4caSwyllys 		goto cleanup;
458299ebb4caSwyllys 	}
458399ebb4caSwyllys 
458499ebb4caSwyllys 	if (X509_CRL_get_nextUpdate(xcrl)) {
458599ebb4caSwyllys 		i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL);
458699ebb4caSwyllys 
458799ebb4caSwyllys 		if (i <= 0) {
458899ebb4caSwyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
458999ebb4caSwyllys 			goto cleanup;
459099ebb4caSwyllys 		}
459199ebb4caSwyllys 	}
459299ebb4caSwyllys 
459399ebb4caSwyllys 	ret = KMF_OK;
459499ebb4caSwyllys 
459599ebb4caSwyllys cleanup:
459699ebb4caSwyllys 	if (bcrl != NULL)
459799ebb4caSwyllys 		(void) BIO_free(bcrl);
459899ebb4caSwyllys 
459999ebb4caSwyllys 	if (xcrl != NULL)
460099ebb4caSwyllys 		X509_CRL_free(xcrl);
460199ebb4caSwyllys 
460299ebb4caSwyllys 	return (ret);
460399ebb4caSwyllys }
460499ebb4caSwyllys 
460599ebb4caSwyllys /*
460699ebb4caSwyllys  * Check a file to see if it is a CRL file with PEM or DER format.
460799ebb4caSwyllys  * If success, return its format in the "pformat" argument.
460899ebb4caSwyllys  */
460999ebb4caSwyllys KMF_RETURN
461099ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
461199ebb4caSwyllys {
461299ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
461399ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
461499ebb4caSwyllys 	BIO		*bio = NULL;
461599ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
461699ebb4caSwyllys 
461799ebb4caSwyllys 	if (filename == NULL) {
461899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
461999ebb4caSwyllys 	}
462099ebb4caSwyllys 
462199ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
462299ebb4caSwyllys 	if (bio == NULL)	{
462399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
462499ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
462599ebb4caSwyllys 		goto out;
462699ebb4caSwyllys 	}
462799ebb4caSwyllys 
462899ebb4caSwyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
462999ebb4caSwyllys 		*pformat = KMF_FORMAT_PEM;
463099ebb4caSwyllys 		goto out;
463199ebb4caSwyllys 	}
463299ebb4caSwyllys 	(void) BIO_free(bio);
463399ebb4caSwyllys 
463499ebb4caSwyllys 	/*
463599ebb4caSwyllys 	 * Now try to read it as raw DER data.
463699ebb4caSwyllys 	 */
463799ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
463899ebb4caSwyllys 	if (bio == NULL)	{
463999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
464099ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
464199ebb4caSwyllys 		goto out;
464299ebb4caSwyllys 	}
464399ebb4caSwyllys 
464499ebb4caSwyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
464599ebb4caSwyllys 		*pformat = KMF_FORMAT_ASN1;
464699ebb4caSwyllys 	} else {
464799ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
464899ebb4caSwyllys 	}
464999ebb4caSwyllys 
465099ebb4caSwyllys out:
465199ebb4caSwyllys 	if (bio != NULL)
465299ebb4caSwyllys 		(void) BIO_free(bio);
465399ebb4caSwyllys 
465499ebb4caSwyllys 	if (xcrl != NULL)
465599ebb4caSwyllys 		X509_CRL_free(xcrl);
465699ebb4caSwyllys 
465799ebb4caSwyllys 	return (ret);
465899ebb4caSwyllys }
465999ebb4caSwyllys 
466099ebb4caSwyllys /*
466199ebb4caSwyllys  * Check a file to see if it is a certficate file with PEM or DER format.
466299ebb4caSwyllys  * If success, return its format in the pformat argument.
466399ebb4caSwyllys  */
466499ebb4caSwyllys KMF_RETURN
466599ebb4caSwyllys OpenSSL_IsCertFile(KMF_HANDLE_T handle, char *filename,
466699ebb4caSwyllys 	KMF_ENCODE_FORMAT *pformat)
466799ebb4caSwyllys {
466899ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
466999ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
467099ebb4caSwyllys 	BIO		*bio = NULL;
467199ebb4caSwyllys 	X509		*xcert = NULL;
467299ebb4caSwyllys 
467399ebb4caSwyllys 	if (filename == NULL) {
467499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
467599ebb4caSwyllys 	}
467699ebb4caSwyllys 
467799ebb4caSwyllys 	ret = KMF_GetFileFormat(filename, pformat);
467899ebb4caSwyllys 	if (ret != KMF_OK)
467999ebb4caSwyllys 		return (ret);
468099ebb4caSwyllys 
468199ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
468299ebb4caSwyllys 	if (bio == NULL)	{
468399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
468499ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
468599ebb4caSwyllys 		goto out;
468699ebb4caSwyllys 	}
468799ebb4caSwyllys 
468899ebb4caSwyllys 	if ((*pformat) == KMF_FORMAT_PEM) {
468999ebb4caSwyllys 		if ((xcert = PEM_read_bio_X509(bio, NULL,
469099ebb4caSwyllys 			NULL, NULL)) == NULL) {
469199ebb4caSwyllys 			ret = KMF_ERR_BAD_CERTFILE;
469299ebb4caSwyllys 		}
469399ebb4caSwyllys 	} else if ((*pformat) == KMF_FORMAT_ASN1) {
469499ebb4caSwyllys 		if ((xcert = d2i_X509_bio(bio, NULL)) == NULL) {
469599ebb4caSwyllys 			ret = KMF_ERR_BAD_CERTFILE;
469699ebb4caSwyllys 		}
469799ebb4caSwyllys 	} else {
469899ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
469999ebb4caSwyllys 	}
470099ebb4caSwyllys 
470199ebb4caSwyllys out:
470299ebb4caSwyllys 	if (bio != NULL)
470399ebb4caSwyllys 		(void) BIO_free(bio);
470499ebb4caSwyllys 
470599ebb4caSwyllys 	if (xcert != NULL)
470699ebb4caSwyllys 		X509_free(xcert);
470799ebb4caSwyllys 
470899ebb4caSwyllys 	return (ret);
470999ebb4caSwyllys }
471099ebb4caSwyllys 
471199ebb4caSwyllys KMF_RETURN
471299ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
471399ebb4caSwyllys     KMF_RAW_SYM_KEY *rkey)
471499ebb4caSwyllys {
471599ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
471699ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
471799ebb4caSwyllys 	KMF_DATA	keyvalue;
471899ebb4caSwyllys 
471999ebb4caSwyllys 	if (kmfh == NULL)
472099ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
472199ebb4caSwyllys 
472299ebb4caSwyllys 	if (symkey == NULL || rkey == NULL)
472399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
472499ebb4caSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
472599ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
472699ebb4caSwyllys 
472799ebb4caSwyllys 	if (symkey->israw) {
472899ebb4caSwyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
472999ebb4caSwyllys 
473099ebb4caSwyllys 		if (rawkey == NULL ||
473199ebb4caSwyllys 		    rawkey->keydata.val == NULL ||
473299ebb4caSwyllys 		    rawkey->keydata.len == 0)
473399ebb4caSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
473499ebb4caSwyllys 
473599ebb4caSwyllys 		rkey->keydata.len = rawkey->keydata.len;
473699ebb4caSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
473799ebb4caSwyllys 			return (KMF_ERR_MEMORY);
473899ebb4caSwyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
473999ebb4caSwyllys 		    rkey->keydata.len);
474099ebb4caSwyllys 	} else {
474199ebb4caSwyllys 		rv = KMF_ReadInputFile(handle, symkey->keylabel, &keyvalue);
474299ebb4caSwyllys 		if (rv != KMF_OK)
474399ebb4caSwyllys 			return (rv);
474499ebb4caSwyllys 		rkey->keydata.len = keyvalue.Length;
474599ebb4caSwyllys 		rkey->keydata.val = keyvalue.Data;
474699ebb4caSwyllys 	}
474799ebb4caSwyllys 
474899ebb4caSwyllys 	return (rv);
474999ebb4caSwyllys }
475002744e81Swyllys 
475102744e81Swyllys /*
475202744e81Swyllys  * id-sha1    OBJECT IDENTIFIER ::= {
475302744e81Swyllys  *     iso(1) identified-organization(3) oiw(14) secsig(3)
475402744e81Swyllys  *     algorithms(2) 26
475502744e81Swyllys  * }
475602744e81Swyllys  */
475702744e81Swyllys #define	ASN1_SHA1_OID_PREFIX_LEN 15
475802744e81Swyllys static uchar_t SHA1_DER_PREFIX[ASN1_SHA1_OID_PREFIX_LEN] = {
475902744e81Swyllys 	0x30, 0x21, 0x30, 0x09,
476002744e81Swyllys 	0x06, 0x05, 0x2b, 0x0e,
476102744e81Swyllys 	0x03, 0x02, 0x1a, 0x05,
476202744e81Swyllys 	0x00, 0x04, 0x14
476302744e81Swyllys };
476402744e81Swyllys 
476502744e81Swyllys /*
476602744e81Swyllys  * id-md2 OBJECT IDENTIFIER ::= {
476702744e81Swyllys  *     iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2
476802744e81Swyllys  * }
476902744e81Swyllys  */
477002744e81Swyllys #define	ASN1_MD2_OID_PREFIX_LEN 18
477102744e81Swyllys static uchar_t MD2_DER_PREFIX[ASN1_MD2_OID_PREFIX_LEN] = {
477202744e81Swyllys 	0x30, 0x20, 0x30, 0x0c,
477302744e81Swyllys 	0x06, 0x08, 0x2a, 0x86,
477402744e81Swyllys 	0x48, 0x86, 0xf7, 0x0d,
477502744e81Swyllys 	0x02, 0x02, 0x05, 0x00,
477602744e81Swyllys 	0x04, 0x10
477702744e81Swyllys };
477802744e81Swyllys 
477902744e81Swyllys /*
478002744e81Swyllys  * id-md5 OBJECT IDENTIFIER ::= {
478102744e81Swyllys  *     iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5
478202744e81Swyllys  * }
478302744e81Swyllys  */
478402744e81Swyllys #define	ASN1_MD5_OID_PREFIX_LEN 18
478502744e81Swyllys static uchar_t MD5_DER_PREFIX[ASN1_MD5_OID_PREFIX_LEN] = {
478602744e81Swyllys 	0x30, 0x20, 0x30, 0x0c,
478702744e81Swyllys 	0x06, 0x08, 0x2a, 0x86,
478802744e81Swyllys 	0x48, 0x86, 0xf7, 0x0d,
478902744e81Swyllys 	0x02, 0x05, 0x05, 0x00,
479002744e81Swyllys 	0x04, 0x10
479102744e81Swyllys };
479202744e81Swyllys 
479302744e81Swyllys KMF_RETURN
479402744e81Swyllys OpenSSL_VerifyDataWithCert(KMF_HANDLE_T handle,
479502744e81Swyllys 	KMF_ALGORITHM_INDEX algid, KMF_DATA *indata,
479602744e81Swyllys 	KMF_DATA *insig, KMF_DATA *cert)
479702744e81Swyllys {
479802744e81Swyllys 	KMF_RETURN ret = KMF_OK;
479902744e81Swyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
480002744e81Swyllys 	X509	*xcert = NULL;
480102744e81Swyllys 	EVP_PKEY *pkey = NULL;
480202744e81Swyllys 	uchar_t *p;
480302744e81Swyllys 	uchar_t *rsaout = NULL;
480402744e81Swyllys 	uchar_t *pfx = NULL;
480502744e81Swyllys 	const EVP_MD *md;
480602744e81Swyllys 	int pfxlen = 0, len;
480702744e81Swyllys 
480802744e81Swyllys 	if (handle == NULL || indata == NULL ||
480902744e81Swyllys 	    indata->Data == NULL || indata->Length == 0 ||
481002744e81Swyllys 	    insig == NULL|| insig->Data == NULL || insig->Length == 0 ||
481102744e81Swyllys 	    cert == NULL || cert->Data == NULL || cert->Length == 0)
481202744e81Swyllys 		return (KMF_ERR_BAD_PARAMETER);
481302744e81Swyllys 
481402744e81Swyllys 	p = cert->Data;
481502744e81Swyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, cert->Length);
481602744e81Swyllys 	if (xcert == NULL) {
481702744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
481802744e81Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
481902744e81Swyllys 		goto cleanup;
482002744e81Swyllys 	}
482102744e81Swyllys 
482202744e81Swyllys 	pkey = X509_get_pubkey(xcert);
482302744e81Swyllys 	if (!pkey) {
482402744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
482502744e81Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
482602744e81Swyllys 		goto cleanup;
482702744e81Swyllys 	}
482802744e81Swyllys 
482902744e81Swyllys 	if (algid != KMF_ALGID_NONE) {
483002744e81Swyllys 		switch (algid) {
483102744e81Swyllys 			case KMF_ALGID_MD5WithRSA:
483202744e81Swyllys 				md = EVP_md5();
483302744e81Swyllys 				break;
483402744e81Swyllys 			case KMF_ALGID_MD2WithRSA:
483502744e81Swyllys 				md = EVP_md2();
483602744e81Swyllys 				break;
483702744e81Swyllys 			case KMF_ALGID_SHA1WithRSA:
483802744e81Swyllys 				md = EVP_sha1();
483902744e81Swyllys 				break;
484002744e81Swyllys 			case KMF_ALGID_RSA:
484102744e81Swyllys 				md = NULL;
484202744e81Swyllys 				break;
484302744e81Swyllys 			default:
484402744e81Swyllys 				ret = KMF_ERR_BAD_PARAMETER;
484502744e81Swyllys 				goto cleanup;
484602744e81Swyllys 		}
484702744e81Swyllys 	} else {
484802744e81Swyllys 		/* Get the hash type from the cert signature */
484902744e81Swyllys 		md = EVP_get_digestbyobj(xcert->sig_alg->algorithm);
485002744e81Swyllys 		if (md == NULL) {
485102744e81Swyllys 			SET_ERROR(kmfh, ERR_get_error());
485202744e81Swyllys 			ret = KMF_ERR_BAD_PARAMETER;
485302744e81Swyllys 			goto cleanup;
485402744e81Swyllys 		}
485502744e81Swyllys 	}
48569b37d296Swyllys 	if (md != NULL) {
485702744e81Swyllys 		switch (EVP_MD_type(md)) {
485802744e81Swyllys 		case NID_md2:
485902744e81Swyllys 		case NID_md2WithRSAEncryption:
486002744e81Swyllys 			pfxlen = ASN1_MD2_OID_PREFIX_LEN;
486102744e81Swyllys 			pfx = MD2_DER_PREFIX;
486202744e81Swyllys 			break;
486302744e81Swyllys 		case NID_md5:
486402744e81Swyllys 		case NID_md5WithRSAEncryption:
486502744e81Swyllys 			pfxlen = ASN1_MD5_OID_PREFIX_LEN;
486602744e81Swyllys 			pfx = MD5_DER_PREFIX;
486702744e81Swyllys 			break;
486802744e81Swyllys 		case NID_sha1:
486902744e81Swyllys 		case NID_sha1WithRSAEncryption:
487002744e81Swyllys 			pfxlen = ASN1_SHA1_OID_PREFIX_LEN;
487102744e81Swyllys 			pfx = SHA1_DER_PREFIX;
487202744e81Swyllys 			break;
487302744e81Swyllys 		default: /* Unsupported */
487402744e81Swyllys 			pfxlen = 0;
487502744e81Swyllys 			pfx = NULL;
487602744e81Swyllys 			break;
487702744e81Swyllys 		}
48789b37d296Swyllys 	}
487902744e81Swyllys 
488002744e81Swyllys 	/* RSA with no hash is a special case */
488102744e81Swyllys 	rsaout = malloc(RSA_size(pkey->pkey.rsa));
488202744e81Swyllys 	if (rsaout == NULL)
488302744e81Swyllys 		return (KMF_ERR_MEMORY);
488402744e81Swyllys 
488502744e81Swyllys 	/* Decrypt the input signature */
488602744e81Swyllys 	len = RSA_public_decrypt(insig->Length,
488702744e81Swyllys 		insig->Data, rsaout, pkey->pkey.rsa, RSA_PKCS1_PADDING);
488802744e81Swyllys 	if (len < 1) {
488902744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
489002744e81Swyllys 		ret = KMF_ERR_BAD_PARAMETER;
489102744e81Swyllys 	} else {
489202744e81Swyllys 		size_t hashlen = 0;
489302744e81Swyllys 		uint32_t dlen;
489402744e81Swyllys 		char *digest = NULL;
489502744e81Swyllys 
489602744e81Swyllys 		/*
489702744e81Swyllys 		 * If the AlgId requires it, hash the input data before
489802744e81Swyllys 		 * comparing it to the decrypted signature.
489902744e81Swyllys 		 */
490002744e81Swyllys 		if (md) {
490102744e81Swyllys 			EVP_MD_CTX ctx;
490202744e81Swyllys 
490302744e81Swyllys 			hashlen = md->md_size;
490402744e81Swyllys 
490502744e81Swyllys 			digest = malloc(hashlen + pfxlen);
490602744e81Swyllys 			if (digest == NULL)
490702744e81Swyllys 				return (KMF_ERR_MEMORY);
490802744e81Swyllys 			/* Add the prefix to the comparison buffer. */
490902744e81Swyllys 			if (pfx && pfxlen > 0) {
491002744e81Swyllys 				(void) memcpy(digest, pfx, pfxlen);
491102744e81Swyllys 			}
491202744e81Swyllys 			(void) EVP_DigestInit(&ctx, md);
491302744e81Swyllys 			(void) EVP_DigestUpdate(&ctx, indata->Data,
491402744e81Swyllys 				indata->Length);
491502744e81Swyllys 
491602744e81Swyllys 			/* Add the digest AFTER the ASN1 prefix */
491702744e81Swyllys 			(void) EVP_DigestFinal(&ctx,
491802744e81Swyllys 				(uchar_t *)digest + pfxlen, &dlen);
491902744e81Swyllys 
492002744e81Swyllys 			dlen += pfxlen;
492102744e81Swyllys 		} else {
492202744e81Swyllys 			digest = (char *)indata->Data;
492302744e81Swyllys 			dlen = indata->Length;
492402744e81Swyllys 		}
492502744e81Swyllys 
492602744e81Swyllys 		/*
492702744e81Swyllys 		 * The result of the RSA decryption should be ASN1(OID | Hash).
492802744e81Swyllys 		 * Compare the output hash to the input data for the final
492902744e81Swyllys 		 * result.
493002744e81Swyllys 		 */
493102744e81Swyllys 		if (memcmp(rsaout, digest, dlen))
493202744e81Swyllys 			ret = KMF_ERR_INTERNAL;
493302744e81Swyllys 		else
493402744e81Swyllys 			ret = KMF_OK;
493502744e81Swyllys 
493602744e81Swyllys 		/* If we had to allocate space for the digest, free it now */
493702744e81Swyllys 		if (hashlen)
493802744e81Swyllys 			free(digest);
493902744e81Swyllys 	}
494002744e81Swyllys cleanup:
494102744e81Swyllys 	if (pkey)
494202744e81Swyllys 		EVP_PKEY_free(pkey);
494302744e81Swyllys 
494402744e81Swyllys 	if (xcert)
494502744e81Swyllys 		X509_free(xcert);
494602744e81Swyllys 
494702744e81Swyllys 	if (rsaout)
494802744e81Swyllys 		free(rsaout);
494902744e81Swyllys 
495002744e81Swyllys 	return (ret);
495102744e81Swyllys }
4952