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