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 uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
10799ebb4caSwyllys 	0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
10899ebb4caSwyllys 	0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
10999ebb4caSwyllys 	0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
11099ebb4caSwyllys 	0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
11199ebb4caSwyllys 	0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
11299ebb4caSwyllys 	0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
11399ebb4caSwyllys 	0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
11499ebb4caSwyllys 	0x91 };
11599ebb4caSwyllys 
11699ebb4caSwyllys static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
11799ebb4caSwyllys 	0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
11899ebb4caSwyllys 	0x8e, 0xda, 0xce, 0x91, 0x5f };
11999ebb4caSwyllys 
12099ebb4caSwyllys static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
12199ebb4caSwyllys 	0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
12299ebb4caSwyllys 	0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
12399ebb4caSwyllys 	0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
12499ebb4caSwyllys 	0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
12599ebb4caSwyllys 	0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
12699ebb4caSwyllys 	0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
12799ebb4caSwyllys 	0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
12899ebb4caSwyllys 	0x02 };
12999ebb4caSwyllys 
13099ebb4caSwyllys #define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
13199ebb4caSwyllys 	h->lasterr.errcode = c;
13299ebb4caSwyllys 
13399ebb4caSwyllys #define	SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
13499ebb4caSwyllys 
13599ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX;
13699ebb4caSwyllys static int ssl_initialized = 0;
137*30a5e8faSwyllys static BIO *bio_err = NULL;
138*30a5e8faSwyllys 
139*30a5e8faSwyllys static int
140*30a5e8faSwyllys test_for_file(char *, mode_t);
14199ebb4caSwyllys 
14271593db2Swyllys static KMF_RETURN
143*30a5e8faSwyllys extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *,
14402744e81Swyllys     CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
14571593db2Swyllys 
14671593db2Swyllys static KMF_RETURN
147*30a5e8faSwyllys kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
148*30a5e8faSwyllys     char *, KMF_DATA *);
149*30a5e8faSwyllys 
150*30a5e8faSwyllys static KMF_RETURN
151*30a5e8faSwyllys load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
152*30a5e8faSwyllys     char *, KMF_DATA **, uint32_t *);
15371593db2Swyllys 
15402744e81Swyllys static KMF_RETURN
15502744e81Swyllys sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
15602744e81Swyllys 
15702744e81Swyllys static EVP_PKEY *
15802744e81Swyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *);
15902744e81Swyllys 
160*30a5e8faSwyllys static KMF_RETURN
161*30a5e8faSwyllys convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
162*30a5e8faSwyllys 
16399ebb4caSwyllys KMF_RETURN
164*30a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
16599ebb4caSwyllys 
16699ebb4caSwyllys void
16799ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
16899ebb4caSwyllys 
16999ebb4caSwyllys KMF_RETURN
170*30a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
17199ebb4caSwyllys 
17299ebb4caSwyllys KMF_RETURN
173*30a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
17499ebb4caSwyllys 
17599ebb4caSwyllys KMF_RETURN
176*30a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
177*30a5e8faSwyllys 
178*30a5e8faSwyllys KMF_RETURN
179*30a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
18099ebb4caSwyllys 
18199ebb4caSwyllys KMF_RETURN
18299ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T,  KMF_KEY_HANDLE *, KMF_DATA *);
18399ebb4caSwyllys 
18499ebb4caSwyllys KMF_RETURN
18599ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
18699ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
18799ebb4caSwyllys 
18899ebb4caSwyllys KMF_RETURN
189*30a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
19099ebb4caSwyllys 
19199ebb4caSwyllys KMF_RETURN
192*30a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
19399ebb4caSwyllys 
19499ebb4caSwyllys KMF_RETURN
195*30a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
19699ebb4caSwyllys 
19799ebb4caSwyllys KMF_RETURN
198*30a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
19999ebb4caSwyllys 
20099ebb4caSwyllys KMF_RETURN
201*30a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20299ebb4caSwyllys 
20399ebb4caSwyllys KMF_RETURN
20499ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
20599ebb4caSwyllys 	KMF_PRINTABLE_ITEM, char *);
20699ebb4caSwyllys 
20799ebb4caSwyllys KMF_RETURN
20899ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
20999ebb4caSwyllys 
21099ebb4caSwyllys KMF_RETURN
211*30a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21299ebb4caSwyllys 
21399ebb4caSwyllys KMF_RETURN
21499ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
21599ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
21699ebb4caSwyllys 
21799ebb4caSwyllys KMF_RETURN
218*30a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21999ebb4caSwyllys 
22099ebb4caSwyllys KMF_RETURN
221*30a5e8faSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22299ebb4caSwyllys 
22399ebb4caSwyllys KMF_RETURN
224*30a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22599ebb4caSwyllys 
22699ebb4caSwyllys KMF_RETURN
227*30a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22899ebb4caSwyllys 
22999ebb4caSwyllys KMF_RETURN
230*30a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23199ebb4caSwyllys 
23299ebb4caSwyllys KMF_RETURN
23399ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
23499ebb4caSwyllys 
23599ebb4caSwyllys KMF_RETURN
236*30a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
23799ebb4caSwyllys 
23899ebb4caSwyllys KMF_RETURN
239*30a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
24099ebb4caSwyllys 
24102744e81Swyllys KMF_RETURN
24202744e81Swyllys OpenSSL_VerifyDataWithCert(KMF_HANDLE_T, KMF_ALGORITHM_INDEX,
24302744e81Swyllys 	KMF_DATA *, KMF_DATA *, KMF_DATA *);
24402744e81Swyllys 
24599ebb4caSwyllys static
24699ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table =
24799ebb4caSwyllys {
24899ebb4caSwyllys 	1,				/* Version */
24999ebb4caSwyllys 	NULL, /* ConfigureKeystore */
25099ebb4caSwyllys 	OpenSSL_FindCert,
25199ebb4caSwyllys 	OpenSSL_FreeKMFCert,
25299ebb4caSwyllys 	OpenSSL_StoreCert,
25399ebb4caSwyllys 	NULL, /* ImportCert */
25499ebb4caSwyllys 	OpenSSL_ImportCRL,
25599ebb4caSwyllys 	OpenSSL_DeleteCert,
25699ebb4caSwyllys 	OpenSSL_DeleteCRL,
25799ebb4caSwyllys 	OpenSSL_CreateKeypair,
25899ebb4caSwyllys 	OpenSSL_FindKey,
25999ebb4caSwyllys 	OpenSSL_EncodePubKeyData,
26099ebb4caSwyllys 	OpenSSL_SignData,
26199ebb4caSwyllys 	OpenSSL_DeleteKey,
26299ebb4caSwyllys 	OpenSSL_ListCRL,
26399ebb4caSwyllys 	NULL,	/* FindCRL */
26499ebb4caSwyllys 	OpenSSL_FindCertInCRL,
26599ebb4caSwyllys 	OpenSSL_GetErrorString,
266*30a5e8faSwyllys 	OpenSSL_FindPrikeyByCert,
26799ebb4caSwyllys 	OpenSSL_DecryptData,
268*30a5e8faSwyllys 	OpenSSL_ExportPK12,
26999ebb4caSwyllys 	OpenSSL_CreateSymKey,
27099ebb4caSwyllys 	OpenSSL_GetSymKeyValue,
27199ebb4caSwyllys 	NULL,	/* SetTokenPin */
27202744e81Swyllys 	OpenSSL_VerifyDataWithCert,
273*30a5e8faSwyllys 	OpenSSL_StoreKey,
27499ebb4caSwyllys 	NULL	/* Finalize */
27599ebb4caSwyllys };
27699ebb4caSwyllys 
27799ebb4caSwyllys static mutex_t *lock_cs;
27899ebb4caSwyllys static long *lock_count;
27999ebb4caSwyllys 
28099ebb4caSwyllys static void
28199ebb4caSwyllys /*ARGSUSED*/
28299ebb4caSwyllys locking_cb(int mode, int type, char *file, int line)
28399ebb4caSwyllys {
28499ebb4caSwyllys 	if (mode & CRYPTO_LOCK) {
28599ebb4caSwyllys 		(void) mutex_lock(&(lock_cs[type]));
28699ebb4caSwyllys 		lock_count[type]++;
28799ebb4caSwyllys 	} else {
28899ebb4caSwyllys 		(void) mutex_unlock(&(lock_cs[type]));
28999ebb4caSwyllys 	}
29099ebb4caSwyllys }
29199ebb4caSwyllys 
29299ebb4caSwyllys static unsigned long
29399ebb4caSwyllys thread_id()
29499ebb4caSwyllys {
29599ebb4caSwyllys 	return ((unsigned long)thr_self());
29699ebb4caSwyllys }
29799ebb4caSwyllys 
29899ebb4caSwyllys KMF_PLUGIN_FUNCLIST *
29999ebb4caSwyllys KMF_Plugin_Initialize()
30099ebb4caSwyllys {
30199ebb4caSwyllys 	int i;
30299ebb4caSwyllys 
30399ebb4caSwyllys 	(void) mutex_lock(&init_lock);
30499ebb4caSwyllys 	if (!ssl_initialized) {
30599ebb4caSwyllys 		OpenSSL_add_all_algorithms();
30699ebb4caSwyllys 
30799ebb4caSwyllys 		/* Enable error strings for reporting */
30899ebb4caSwyllys 		ERR_load_crypto_strings();
30999ebb4caSwyllys 
31099ebb4caSwyllys 		/*
31199ebb4caSwyllys 		 * Add support for extension OIDs that are not yet in the
31299ebb4caSwyllys 		 * openssl default set.
31399ebb4caSwyllys 		 */
31499ebb4caSwyllys 		(void) OBJ_create("2.5.29.30", "nameConstraints",
31599ebb4caSwyllys 		    "X509v3 Name Constraints");
31699ebb4caSwyllys 		(void) OBJ_create("2.5.29.33", "policyMappings",
31799ebb4caSwyllys 		    "X509v3 Policy Mappings");
31899ebb4caSwyllys 		(void) OBJ_create("2.5.29.36", "policyConstraints",
31999ebb4caSwyllys 		    "X509v3 Policy Constraints");
32099ebb4caSwyllys 		(void) OBJ_create("2.5.29.46", "freshestCRL",
32199ebb4caSwyllys 		    "X509v3 Freshest CRL");
32299ebb4caSwyllys 		(void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
32399ebb4caSwyllys 		    "X509v3 Inhibit Any-Policy");
32499ebb4caSwyllys 		/*
32599ebb4caSwyllys 		 * Set up for thread-safe operation.
32699ebb4caSwyllys 		 */
32799ebb4caSwyllys 		lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
32899ebb4caSwyllys 		if (lock_cs == NULL) {
32999ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
33099ebb4caSwyllys 			return (NULL);
33199ebb4caSwyllys 		}
33299ebb4caSwyllys 
33399ebb4caSwyllys 		lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
33499ebb4caSwyllys 		if (lock_count == NULL) {
33599ebb4caSwyllys 			OPENSSL_free(lock_cs);
33699ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
33799ebb4caSwyllys 			return (NULL);
33899ebb4caSwyllys 		}
33999ebb4caSwyllys 
34099ebb4caSwyllys 		for (i = 0; i < CRYPTO_num_locks(); i++) {
34199ebb4caSwyllys 			lock_count[i] = 0;
34299ebb4caSwyllys 			(void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
34399ebb4caSwyllys 		}
34499ebb4caSwyllys 
34599ebb4caSwyllys 		CRYPTO_set_id_callback((unsigned long (*)())thread_id);
34699ebb4caSwyllys 		CRYPTO_set_locking_callback((void (*)())locking_cb);
34799ebb4caSwyllys 		ssl_initialized = 1;
34899ebb4caSwyllys 	}
34999ebb4caSwyllys 	(void) mutex_unlock(&init_lock);
35099ebb4caSwyllys 
35199ebb4caSwyllys 	return (&openssl_plugin_table);
35299ebb4caSwyllys }
35399ebb4caSwyllys /*
35499ebb4caSwyllys  * Convert an SSL DN to a KMF DN.
35599ebb4caSwyllys  */
35699ebb4caSwyllys static KMF_RETURN
35799ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
35899ebb4caSwyllys {
35999ebb4caSwyllys 	KMF_DATA derdata;
36099ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
36199ebb4caSwyllys 	uchar_t *tmp;
36299ebb4caSwyllys 
36399ebb4caSwyllys 	/* Convert to raw DER format */
36499ebb4caSwyllys 	derdata.Length = i2d_X509_NAME(sslDN, NULL);
36599ebb4caSwyllys 	if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
36699ebb4caSwyllys 	    == NULL) {
36799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
36899ebb4caSwyllys 	}
36999ebb4caSwyllys 	(void) i2d_X509_NAME(sslDN, &tmp);
37099ebb4caSwyllys 
37199ebb4caSwyllys 	/* Decode to KMF format */
37299ebb4caSwyllys 	rv = DerDecodeName(&derdata, kmfDN);
37399ebb4caSwyllys 	if (rv != KMF_OK) {
37499ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
37599ebb4caSwyllys 	}
37699ebb4caSwyllys 	OPENSSL_free(derdata.Data);
37799ebb4caSwyllys 
37899ebb4caSwyllys 	return (rv);
37999ebb4caSwyllys }
38099ebb4caSwyllys 
381*30a5e8faSwyllys int
38299ebb4caSwyllys isdir(char *path)
38399ebb4caSwyllys {
38499ebb4caSwyllys 	struct stat s;
38599ebb4caSwyllys 
38699ebb4caSwyllys 	if (stat(path, &s) == -1)
38799ebb4caSwyllys 		return (0);
38899ebb4caSwyllys 
389*30a5e8faSwyllys 	return ((s.st_mode & S_IFMT) == S_IFDIR);
39099ebb4caSwyllys }
39199ebb4caSwyllys 
39299ebb4caSwyllys static KMF_RETURN
39399ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
39499ebb4caSwyllys {
39599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
39699ebb4caSwyllys 	unsigned char *buf = NULL, *p;
39799ebb4caSwyllys 	int len;
39899ebb4caSwyllys 
39999ebb4caSwyllys 	/*
40099ebb4caSwyllys 	 * Convert the X509 internal struct to DER encoded data
40199ebb4caSwyllys 	 */
40299ebb4caSwyllys 	if ((len = i2d_X509(x509cert, NULL)) < 0) {
40399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
40499ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
40599ebb4caSwyllys 		goto cleanup;
40699ebb4caSwyllys 	}
40799ebb4caSwyllys 	if ((buf = malloc(len)) == NULL) {
40899ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
40999ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
41099ebb4caSwyllys 		goto cleanup;
41199ebb4caSwyllys 	}
41299ebb4caSwyllys 
41399ebb4caSwyllys 	/*
41499ebb4caSwyllys 	 * i2d_X509 will increment the buf pointer so that we need to
41599ebb4caSwyllys 	 * save it.
41699ebb4caSwyllys 	 */
41799ebb4caSwyllys 	p = buf;
41899ebb4caSwyllys 	if ((len = i2d_X509(x509cert, &p)) < 0) {
41999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
42099ebb4caSwyllys 		free(buf);
42199ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
42299ebb4caSwyllys 		goto cleanup;
42399ebb4caSwyllys 	}
42499ebb4caSwyllys 
42599ebb4caSwyllys 	/* caller's responsibility to free it */
42699ebb4caSwyllys 	cert->Data = buf;
42799ebb4caSwyllys 	cert->Length = len;
42899ebb4caSwyllys 
42999ebb4caSwyllys cleanup:
43099ebb4caSwyllys 	if (rv != KMF_OK) {
43199ebb4caSwyllys 		if (buf)
43299ebb4caSwyllys 			free(buf);
43399ebb4caSwyllys 		cert->Data = NULL;
43499ebb4caSwyllys 		cert->Length = 0;
43599ebb4caSwyllys 	}
43699ebb4caSwyllys 
43799ebb4caSwyllys 	return (rv);
43899ebb4caSwyllys }
43999ebb4caSwyllys 
440*30a5e8faSwyllys 
44199ebb4caSwyllys static KMF_RETURN
442*30a5e8faSwyllys check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
443*30a5e8faSwyllys     boolean_t *match)
44499ebb4caSwyllys {
44599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
44699ebb4caSwyllys 	boolean_t findIssuer = FALSE;
44799ebb4caSwyllys 	boolean_t findSubject = FALSE;
44899ebb4caSwyllys 	boolean_t findSerial = FALSE;
44999ebb4caSwyllys 	KMF_X509_NAME issuerDN, subjectDN;
45099ebb4caSwyllys 	KMF_X509_NAME certIssuerDN, certSubjectDN;
45199ebb4caSwyllys 
45299ebb4caSwyllys 	*match = FALSE;
45399ebb4caSwyllys 	if (xcert == NULL) {
45499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
45599ebb4caSwyllys 	}
45699ebb4caSwyllys 
45799ebb4caSwyllys 	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
45899ebb4caSwyllys 	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
45999ebb4caSwyllys 	(void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
46099ebb4caSwyllys 	(void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
46199ebb4caSwyllys 
462*30a5e8faSwyllys 	if (issuer != NULL && strlen(issuer)) {
463*30a5e8faSwyllys 		rv = kmf_dn_parser(issuer, &issuerDN);
46499ebb4caSwyllys 		if (rv != KMF_OK)
46599ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
46699ebb4caSwyllys 
46799ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->issuer, &certIssuerDN);
46899ebb4caSwyllys 		if (rv != KMF_OK) {
469*30a5e8faSwyllys 			kmf_free_dn(&issuerDN);
47099ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
47199ebb4caSwyllys 		}
47299ebb4caSwyllys 
47399ebb4caSwyllys 		findIssuer = TRUE;
47499ebb4caSwyllys 	}
475*30a5e8faSwyllys 	if (subject != NULL && strlen(subject)) {
476*30a5e8faSwyllys 		rv = kmf_dn_parser(subject, &subjectDN);
47799ebb4caSwyllys 		if (rv != KMF_OK) {
47899ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
47999ebb4caSwyllys 			goto cleanup;
48099ebb4caSwyllys 		}
48199ebb4caSwyllys 
48299ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->subject, &certSubjectDN);
48399ebb4caSwyllys 		if (rv != KMF_OK) {
48499ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
48599ebb4caSwyllys 			goto cleanup;
48699ebb4caSwyllys 		}
48799ebb4caSwyllys 		findSubject = TRUE;
48899ebb4caSwyllys 	}
489*30a5e8faSwyllys 	if (serial != NULL && serial->val != NULL)
49099ebb4caSwyllys 		findSerial = TRUE;
49199ebb4caSwyllys 
49299ebb4caSwyllys 	if (findSerial) {
49399ebb4caSwyllys 		BIGNUM *bn;
49499ebb4caSwyllys 
49599ebb4caSwyllys 		/* Comparing BIGNUMs is a pain! */
49699ebb4caSwyllys 		bn = ASN1_INTEGER_to_BN(xcert->cert_info->serialNumber, NULL);
49799ebb4caSwyllys 		if (bn != NULL) {
49899ebb4caSwyllys 			int bnlen = BN_num_bytes(bn);
49999ebb4caSwyllys 
500*30a5e8faSwyllys 			if (bnlen == serial->len) {
50199ebb4caSwyllys 				uchar_t *a = malloc(bnlen);
50299ebb4caSwyllys 				if (a == NULL) {
50399ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
50499ebb4caSwyllys 					BN_free(bn);
50599ebb4caSwyllys 					goto cleanup;
50699ebb4caSwyllys 				}
50799ebb4caSwyllys 				bnlen = BN_bn2bin(bn, a);
508*30a5e8faSwyllys 				*match = (memcmp(a, serial->val, serial->len) ==
509*30a5e8faSwyllys 				    0);
51099ebb4caSwyllys 				rv = KMF_OK;
51199ebb4caSwyllys 				free(a);
51299ebb4caSwyllys 			}
51399ebb4caSwyllys 			BN_free(bn);
51499ebb4caSwyllys 			if (!(*match))
51599ebb4caSwyllys 				goto cleanup;
51699ebb4caSwyllys 		} else {
51799ebb4caSwyllys 			rv = KMF_OK;
51899ebb4caSwyllys 			goto cleanup;
51999ebb4caSwyllys 		}
52099ebb4caSwyllys 	}
52199ebb4caSwyllys 	if (findIssuer) {
522*30a5e8faSwyllys 		*match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
523*30a5e8faSwyllys 		if ((*match) == B_FALSE) {
524*30a5e8faSwyllys 			/* stop checking and bail */
52599ebb4caSwyllys 			rv = KMF_OK;
52699ebb4caSwyllys 			goto cleanup;
52799ebb4caSwyllys 		}
52899ebb4caSwyllys 	}
52999ebb4caSwyllys 	if (findSubject) {
530*30a5e8faSwyllys 		*match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
531*30a5e8faSwyllys 		if ((*match) == B_FALSE) {
532*30a5e8faSwyllys 			/* stop checking and bail */
53399ebb4caSwyllys 			rv = KMF_OK;
53499ebb4caSwyllys 			goto cleanup;
53599ebb4caSwyllys 		}
53699ebb4caSwyllys 	}
53799ebb4caSwyllys 
53899ebb4caSwyllys 	*match = TRUE;
53999ebb4caSwyllys cleanup:
54099ebb4caSwyllys 	if (findIssuer) {
541*30a5e8faSwyllys 		kmf_free_dn(&issuerDN);
542*30a5e8faSwyllys 		kmf_free_dn(&certIssuerDN);
54399ebb4caSwyllys 	}
54499ebb4caSwyllys 	if (findSubject) {
545*30a5e8faSwyllys 		kmf_free_dn(&subjectDN);
546*30a5e8faSwyllys 		kmf_free_dn(&certSubjectDN);
54799ebb4caSwyllys 	}
54899ebb4caSwyllys 
54999ebb4caSwyllys 	return (rv);
55099ebb4caSwyllys }
55199ebb4caSwyllys 
552*30a5e8faSwyllys 
553*30a5e8faSwyllys /*
554*30a5e8faSwyllys  * This function loads a certificate file into an X509 data structure, and
555*30a5e8faSwyllys  * checks if its issuer, subject or the serial number matches with those
556*30a5e8faSwyllys  * values.  If it matches, then return the X509 data structure.
557*30a5e8faSwyllys  */
55899ebb4caSwyllys static KMF_RETURN
55999ebb4caSwyllys load_X509cert(KMF_HANDLE *kmfh,
560*30a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
561*30a5e8faSwyllys     char *pathname, X509 **outcert)
56299ebb4caSwyllys {
56399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
56499ebb4caSwyllys 	X509 *xcert = NULL;
56599ebb4caSwyllys 	BIO *bcert = NULL;
56699ebb4caSwyllys 	boolean_t  match = FALSE;
56799ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
56899ebb4caSwyllys 
56999ebb4caSwyllys 	/*
57099ebb4caSwyllys 	 * auto-detect the file format, regardless of what
57199ebb4caSwyllys 	 * the 'format' parameters in the params say.
57299ebb4caSwyllys 	 */
573*30a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
57499ebb4caSwyllys 	if (rv != KMF_OK) {
57599ebb4caSwyllys 		if (rv == KMF_ERR_OPEN_FILE)
57699ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
57799ebb4caSwyllys 		return (rv);
57899ebb4caSwyllys 	}
57999ebb4caSwyllys 
58099ebb4caSwyllys 	/* Not ASN1(DER) format */
58199ebb4caSwyllys 	if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
58299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
58399ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
58499ebb4caSwyllys 		goto cleanup;
58599ebb4caSwyllys 	}
58699ebb4caSwyllys 
58799ebb4caSwyllys 	if (format == KMF_FORMAT_PEM)
58899ebb4caSwyllys 		xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
58999ebb4caSwyllys 	else if (format == KMF_FORMAT_ASN1)
59099ebb4caSwyllys 		xcert = d2i_X509_bio(bcert, NULL);
59199ebb4caSwyllys 	else if (format == KMF_FORMAT_PKCS12) {
59299ebb4caSwyllys 		PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
59399ebb4caSwyllys 		if (p12 != NULL) {
59499ebb4caSwyllys 			(void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
59599ebb4caSwyllys 			PKCS12_free(p12);
59699ebb4caSwyllys 			p12 = NULL;
59799ebb4caSwyllys 		} else {
59899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
59999ebb4caSwyllys 			rv = KMF_ERR_BAD_CERT_FORMAT;
60099ebb4caSwyllys 		}
60199ebb4caSwyllys 	} else {
60299ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
60399ebb4caSwyllys 		goto cleanup;
60499ebb4caSwyllys 	}
60599ebb4caSwyllys 
60699ebb4caSwyllys 	if (xcert == NULL) {
60799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
60899ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
60999ebb4caSwyllys 		goto cleanup;
61099ebb4caSwyllys 	}
61199ebb4caSwyllys 
612*30a5e8faSwyllys 	if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
613*30a5e8faSwyllys 	    match == FALSE) {
61499ebb4caSwyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
61599ebb4caSwyllys 		goto cleanup;
61699ebb4caSwyllys 	}
61799ebb4caSwyllys 
61899ebb4caSwyllys 	if (outcert != NULL) {
61999ebb4caSwyllys 		*outcert = xcert;
62099ebb4caSwyllys 	}
62199ebb4caSwyllys 
62299ebb4caSwyllys cleanup:
62399ebb4caSwyllys 	if (bcert != NULL) (void) BIO_free(bcert);
62499ebb4caSwyllys 	if (rv != KMF_OK && xcert != NULL)
62599ebb4caSwyllys 		X509_free(xcert);
62699ebb4caSwyllys 
62799ebb4caSwyllys 	return (rv);
62899ebb4caSwyllys }
62999ebb4caSwyllys 
63071593db2Swyllys static int
63171593db2Swyllys datacmp(const void *a, const void *b)
63271593db2Swyllys {
63371593db2Swyllys 	KMF_DATA *adata = (KMF_DATA *)a;
63471593db2Swyllys 	KMF_DATA *bdata = (KMF_DATA *)b;
63571593db2Swyllys 	if (adata->Length > bdata->Length)
63671593db2Swyllys 		return (-1);
63771593db2Swyllys 	if (adata->Length < bdata->Length)
63871593db2Swyllys 		return (1);
63971593db2Swyllys 	return (0);
64071593db2Swyllys }
64171593db2Swyllys 
64271593db2Swyllys static KMF_RETURN
643*30a5e8faSwyllys load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
644*30a5e8faSwyllys     KMF_CERT_VALIDITY validity, char *pathname,
64571593db2Swyllys     KMF_DATA **certlist, uint32_t *numcerts)
64671593db2Swyllys {
64771593db2Swyllys 	KMF_RETURN rv = KMF_OK;
64871593db2Swyllys 	int i;
64971593db2Swyllys 	KMF_DATA *certs = NULL;
65071593db2Swyllys 	int nc = 0;
65171593db2Swyllys 	int hits = 0;
65271593db2Swyllys 	KMF_ENCODE_FORMAT format;
65371593db2Swyllys 
654*30a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
65571593db2Swyllys 	if (rv != KMF_OK) {
65671593db2Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
65771593db2Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
65871593db2Swyllys 		return (rv);
65971593db2Swyllys 	}
66071593db2Swyllys 	if (format == KMF_FORMAT_ASN1) {
66171593db2Swyllys 		/* load a single certificate */
66271593db2Swyllys 		certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
66371593db2Swyllys 		if (certs == NULL)
66471593db2Swyllys 			return (KMF_ERR_MEMORY);
66571593db2Swyllys 		certs->Data = NULL;
66671593db2Swyllys 		certs->Length = 0;
667*30a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
668*30a5e8faSwyllys 		    pathname, certs);
66971593db2Swyllys 		if (rv == KMF_OK) {
67071593db2Swyllys 			*certlist = certs;
67171593db2Swyllys 			*numcerts = 1;
67271593db2Swyllys 		}
67371593db2Swyllys 		return (rv);
67471593db2Swyllys 	} else if (format == KMF_FORMAT_PKCS12) {
67571593db2Swyllys 		/* We need a credential to access a PKCS#12 file */
67671593db2Swyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
67771593db2Swyllys 	} else if (format == KMF_FORMAT_PEM ||
67871593db2Swyllys 	    format != KMF_FORMAT_PEM_KEYPAIR) {
67971593db2Swyllys 
68071593db2Swyllys 		/* This function only works on PEM files */
681*30a5e8faSwyllys 		rv = extract_pem(kmfh, issuer, subject, serial, pathname,
68234acef67Swyllys 		    (uchar_t *)NULL, 0, NULL, &certs, &nc);
68371593db2Swyllys 	} else {
68471593db2Swyllys 		return (KMF_ERR_ENCODING);
68571593db2Swyllys 	}
68671593db2Swyllys 
68771593db2Swyllys 	if (rv != KMF_OK)
68871593db2Swyllys 		return (rv);
68971593db2Swyllys 
69071593db2Swyllys 	for (i = 0; i < nc; i++) {
691*30a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
692*30a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
693*30a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
694*30a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
69571593db2Swyllys 			if (rv == KMF_OK)
69671593db2Swyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
69771593db2Swyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD)
69871593db2Swyllys 				rv = KMF_OK;
69971593db2Swyllys 		}
70071593db2Swyllys 		if (rv != KMF_OK) {
70171593db2Swyllys 			/* Remove this cert from the list by clearing it. */
702*30a5e8faSwyllys 			kmf_free_data(&certs[i]);
70371593db2Swyllys 		} else {
70471593db2Swyllys 			hits++; /* count valid certs found */
70571593db2Swyllys 		}
70671593db2Swyllys 		rv = KMF_OK;
70771593db2Swyllys 	}
70871593db2Swyllys 	if (rv == KMF_OK && hits == 0) {
70971593db2Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
71071593db2Swyllys 	} else if (rv == KMF_OK && hits > 0) {
71171593db2Swyllys 		/*
71271593db2Swyllys 		 * Sort the list of certs by length to put the cleared ones
71371593db2Swyllys 		 * at the end so they don't get accessed by the caller.
71471593db2Swyllys 		 */
71571593db2Swyllys 		qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
71671593db2Swyllys 		*certlist = certs;
71771593db2Swyllys 
71871593db2Swyllys 		/* since we sorted the list, just return the number of hits */
71971593db2Swyllys 		*numcerts = hits;
72071593db2Swyllys 	}
72171593db2Swyllys 	return (rv);
72271593db2Swyllys }
72371593db2Swyllys 
724*30a5e8faSwyllys 
72599ebb4caSwyllys static KMF_RETURN
72699ebb4caSwyllys kmf_load_cert(KMF_HANDLE *kmfh,
727*30a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
728*30a5e8faSwyllys     KMF_CERT_VALIDITY validity,
72999ebb4caSwyllys     char *pathname,
73099ebb4caSwyllys     KMF_DATA *cert)
73199ebb4caSwyllys {
73299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
73399ebb4caSwyllys 	X509 *x509cert = NULL;
73499ebb4caSwyllys 
735*30a5e8faSwyllys 	rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
73699ebb4caSwyllys 	if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
73799ebb4caSwyllys 		rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
73899ebb4caSwyllys 		if (rv != KMF_OK) {
73999ebb4caSwyllys 			goto cleanup;
74099ebb4caSwyllys 		}
741*30a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
742*30a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
743*30a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
744*30a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
74599ebb4caSwyllys 			if (rv == KMF_OK)  {
74699ebb4caSwyllys 				/*
74799ebb4caSwyllys 				 * This is a valid cert so skip it.
74899ebb4caSwyllys 				 */
74999ebb4caSwyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
75099ebb4caSwyllys 			}
75199ebb4caSwyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD) {
75299ebb4caSwyllys 				/*
75399ebb4caSwyllys 				 * We want to return success when we
75499ebb4caSwyllys 				 * find an invalid cert.
75599ebb4caSwyllys 				 */
75699ebb4caSwyllys 				rv = KMF_OK;
75799ebb4caSwyllys 				goto cleanup;
75899ebb4caSwyllys 			}
75999ebb4caSwyllys 		}
76099ebb4caSwyllys 	}
76199ebb4caSwyllys cleanup:
76299ebb4caSwyllys 	if (x509cert != NULL)
76399ebb4caSwyllys 		X509_free(x509cert);
76499ebb4caSwyllys 
76599ebb4caSwyllys 	return (rv);
76699ebb4caSwyllys }
76799ebb4caSwyllys 
76802744e81Swyllys static KMF_RETURN
76902744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
77002744e81Swyllys {
77102744e81Swyllys 	KMF_RETURN ret = KMF_OK;
77202744e81Swyllys 	KMF_RAW_RSA_KEY rsa;
77302744e81Swyllys 	BerElement *asn1 = NULL;
77402744e81Swyllys 	BerValue filebuf;
77502744e81Swyllys 	BerValue OID = { NULL, 0 };
77602744e81Swyllys 	BerValue *Mod = NULL, *PubExp = NULL;
77702744e81Swyllys 	BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
77802744e81Swyllys 	BerValue *Coef = NULL;
77902744e81Swyllys 	BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
78002744e81Swyllys 	BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
78102744e81Swyllys 	BIGNUM *qminus1 = NULL;
78202744e81Swyllys 	BN_CTX *ctx = NULL;
78302744e81Swyllys 
78402744e81Swyllys 	*pkey = NULL;
78502744e81Swyllys 
78602744e81Swyllys 	filebuf.bv_val = (char *)filedata->Data;
78702744e81Swyllys 	filebuf.bv_len = filedata->Length;
78802744e81Swyllys 
78902744e81Swyllys 	asn1 = kmfder_init(&filebuf);
79002744e81Swyllys 	if (asn1 == NULL) {
79102744e81Swyllys 		ret = KMF_ERR_MEMORY;
79202744e81Swyllys 		goto out;
79302744e81Swyllys 	}
79402744e81Swyllys 
79502744e81Swyllys 	if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
79602744e81Swyllys 	    &OID, &Mod, &PubExp, &PriExp, &Prime1,
79702744e81Swyllys 	    &Prime2, &Coef) == -1)  {
79802744e81Swyllys 		ret = KMF_ERR_ENCODING;
79902744e81Swyllys 		goto out;
80002744e81Swyllys 	}
80102744e81Swyllys 
80202744e81Swyllys 	/*
80302744e81Swyllys 	 * We have to derive the 2 Exponents using Bignumber math.
80402744e81Swyllys 	 * Exp1 = PriExp mod (Prime1 - 1)
80502744e81Swyllys 	 * Exp2 = PriExp mod (Prime2 - 1)
80602744e81Swyllys 	 */
80702744e81Swyllys 
80802744e81Swyllys 	/* D = PrivateExponent */
80902744e81Swyllys 	D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
81002744e81Swyllys 	if (D == NULL) {
81102744e81Swyllys 		ret = KMF_ERR_MEMORY;
81202744e81Swyllys 		goto out;
81302744e81Swyllys 	}
81402744e81Swyllys 
81502744e81Swyllys 	/* P = Prime1 (first prime factor of Modulus) */
81602744e81Swyllys 	P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
81702744e81Swyllys 	if (D == NULL) {
81802744e81Swyllys 		ret = KMF_ERR_MEMORY;
81902744e81Swyllys 		goto out;
82002744e81Swyllys 	}
82102744e81Swyllys 
82202744e81Swyllys 	/* Q = Prime2 (second prime factor of Modulus) */
82302744e81Swyllys 	Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
82402744e81Swyllys 
82502744e81Swyllys 	if ((ctx = BN_CTX_new()) == NULL) {
82602744e81Swyllys 		ret = KMF_ERR_MEMORY;
82702744e81Swyllys 		goto out;
82802744e81Swyllys 	}
82902744e81Swyllys 
83002744e81Swyllys 	/* Compute (P - 1) */
83102744e81Swyllys 	pminus1 = BN_new();
83202744e81Swyllys 	(void) BN_sub(pminus1, P, BN_value_one());
83302744e81Swyllys 
83402744e81Swyllys 	/* Exponent1 = D mod (P - 1) */
83502744e81Swyllys 	Exp1 = BN_new();
83602744e81Swyllys 	(void) BN_mod(Exp1, D, pminus1, ctx);
83702744e81Swyllys 
83802744e81Swyllys 	/* Compute (Q - 1) */
83902744e81Swyllys 	qminus1 = BN_new();
84002744e81Swyllys 	(void) BN_sub(qminus1, Q, BN_value_one());
84102744e81Swyllys 
84202744e81Swyllys 	/* Exponent2 = D mod (Q - 1) */
84302744e81Swyllys 	Exp2 = BN_new();
84402744e81Swyllys 	(void) BN_mod(Exp2, D, qminus1, ctx);
84502744e81Swyllys 
84602744e81Swyllys 	/* Coef = (Inverse Q) mod P */
84702744e81Swyllys 	COEF = BN_new();
84802744e81Swyllys 	(void) BN_mod_inverse(COEF, Q, P, ctx);
84902744e81Swyllys 
85002744e81Swyllys 	/* Convert back to KMF format */
85102744e81Swyllys 	(void) memset(&rsa, 0, sizeof (rsa));
85202744e81Swyllys 
85302744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
85402744e81Swyllys 		goto out;
85502744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
85602744e81Swyllys 		goto out;
85702744e81Swyllys 	if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
85802744e81Swyllys 		goto out;
85902744e81Swyllys 
86002744e81Swyllys 	rsa.mod.val = (uchar_t *)Mod->bv_val;
86102744e81Swyllys 	rsa.mod.len = Mod->bv_len;
86202744e81Swyllys 
86302744e81Swyllys 	rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
86402744e81Swyllys 	rsa.pubexp.len = PubExp->bv_len;
86502744e81Swyllys 
86602744e81Swyllys 	rsa.priexp.val = (uchar_t *)PriExp->bv_val;
86702744e81Swyllys 	rsa.priexp.len = PriExp->bv_len;
86802744e81Swyllys 
86902744e81Swyllys 	rsa.prime1.val = (uchar_t *)Prime1->bv_val;
87002744e81Swyllys 	rsa.prime1.len = Prime1->bv_len;
87102744e81Swyllys 
87202744e81Swyllys 	rsa.prime2.val = (uchar_t *)Prime2->bv_val;
87302744e81Swyllys 	rsa.prime2.len = Prime2->bv_len;
87402744e81Swyllys 
87502744e81Swyllys 	*pkey = ImportRawRSAKey(&rsa);
87602744e81Swyllys out:
87702744e81Swyllys 	if (asn1 != NULL)
87802744e81Swyllys 		kmfber_free(asn1, 1);
87902744e81Swyllys 
88002744e81Swyllys 	if (OID.bv_val) {
88102744e81Swyllys 		free(OID.bv_val);
88202744e81Swyllys 	}
88302744e81Swyllys 	if (PriExp)
88402744e81Swyllys 		free(PriExp);
88502744e81Swyllys 
88602744e81Swyllys 	if (Mod)
88702744e81Swyllys 		free(Mod);
88802744e81Swyllys 
88902744e81Swyllys 	if (PubExp)
89002744e81Swyllys 		free(PubExp);
89102744e81Swyllys 
89202744e81Swyllys 	if (Coef) {
89302744e81Swyllys 		(void) memset(Coef->bv_val, 0, Coef->bv_len);
89402744e81Swyllys 		free(Coef->bv_val);
89502744e81Swyllys 		free(Coef);
89602744e81Swyllys 	}
89702744e81Swyllys 	if (Prime1)
89802744e81Swyllys 		free(Prime1);
89902744e81Swyllys 	if (Prime2)
90002744e81Swyllys 		free(Prime2);
90102744e81Swyllys 
90202744e81Swyllys 	if (ctx != NULL)
90302744e81Swyllys 		BN_CTX_free(ctx);
90402744e81Swyllys 
90502744e81Swyllys 	if (D)
90602744e81Swyllys 		BN_clear_free(D);
90702744e81Swyllys 	if (P)
90802744e81Swyllys 		BN_clear_free(P);
90902744e81Swyllys 	if (Q)
91002744e81Swyllys 		BN_clear_free(Q);
91102744e81Swyllys 	if (pminus1)
91202744e81Swyllys 		BN_clear_free(pminus1);
91302744e81Swyllys 	if (qminus1)
91402744e81Swyllys 		BN_clear_free(qminus1);
91502744e81Swyllys 	if (Exp1)
91602744e81Swyllys 		BN_clear_free(Exp1);
91702744e81Swyllys 	if (Exp2)
91802744e81Swyllys 		BN_clear_free(Exp2);
91902744e81Swyllys 
92002744e81Swyllys 	return (ret);
92102744e81Swyllys 
92202744e81Swyllys }
92302744e81Swyllys 
92499ebb4caSwyllys static EVP_PKEY *
92599ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file)
92699ebb4caSwyllys {
92799ebb4caSwyllys 	BIO *keyfile = NULL;
92899ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
92999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
93099ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
93102744e81Swyllys 	KMF_RETURN rv;
93202744e81Swyllys 	KMF_DATA filedata;
93399ebb4caSwyllys 
93499ebb4caSwyllys 	if (file == NULL) {
93599ebb4caSwyllys 		return (NULL);
93699ebb4caSwyllys 	}
93799ebb4caSwyllys 
938*30a5e8faSwyllys 	if (kmf_get_file_format((char *)file, &format) != KMF_OK)
93999ebb4caSwyllys 		return (NULL);
94099ebb4caSwyllys 
94199ebb4caSwyllys 	keyfile = BIO_new_file(file, "rb");
94299ebb4caSwyllys 	if (keyfile == NULL) {
94399ebb4caSwyllys 		goto end;
94499ebb4caSwyllys 	}
94599ebb4caSwyllys 
94602744e81Swyllys 	if (format == KMF_FORMAT_ASN1) {
94799ebb4caSwyllys 		pkey = d2i_PrivateKey_bio(keyfile, NULL);
94802744e81Swyllys 		if (pkey == NULL) {
94902744e81Swyllys 
95002744e81Swyllys 			(void) BIO_free(keyfile);
95102744e81Swyllys 			keyfile = NULL;
95202744e81Swyllys 			/* Try odd ASN.1 variations */
953*30a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
95402744e81Swyllys 			    &filedata);
95502744e81Swyllys 			if (rv == KMF_OK) {
95602744e81Swyllys 				(void) readAltFormatPrivateKey(&filedata,
95702744e81Swyllys 				    &pkey);
958*30a5e8faSwyllys 				kmf_free_data(&filedata);
95902744e81Swyllys 			}
96002744e81Swyllys 		}
96102744e81Swyllys 	} else if (format == KMF_FORMAT_PEM ||
96202744e81Swyllys 	    format == KMF_FORMAT_PEM_KEYPAIR) {
96399ebb4caSwyllys 		pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
96402744e81Swyllys 		if (pkey == NULL) {
96502744e81Swyllys 			KMF_DATA derdata;
96602744e81Swyllys 			/*
96702744e81Swyllys 			 * Check if this is the alt. format
96802744e81Swyllys 			 * RSA private key file.
96902744e81Swyllys 			 */
970*30a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
97102744e81Swyllys 			    &filedata);
97202744e81Swyllys 			if (rv == KMF_OK) {
97302744e81Swyllys 				uchar_t *d = NULL;
97402744e81Swyllys 				int len;
975*30a5e8faSwyllys 				rv = kmf_pem_to_der(filedata.Data,
97602744e81Swyllys 				    filedata.Length, &d, &len);
97702744e81Swyllys 				if (rv == KMF_OK && d != NULL) {
97802744e81Swyllys 					derdata.Data = d;
97902744e81Swyllys 					derdata.Length = (size_t)len;
98002744e81Swyllys 					(void) readAltFormatPrivateKey(
98102744e81Swyllys 					    &derdata, &pkey);
98202744e81Swyllys 					free(d);
98302744e81Swyllys 				}
984*30a5e8faSwyllys 				kmf_free_data(&filedata);
98502744e81Swyllys 			}
98602744e81Swyllys 		}
98702744e81Swyllys 	}
98899ebb4caSwyllys 
98999ebb4caSwyllys end:
99099ebb4caSwyllys 	if (pkey == NULL)
99199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
99299ebb4caSwyllys 
99399ebb4caSwyllys 	if (keyfile != NULL)
99499ebb4caSwyllys 		(void) BIO_free(keyfile);
99599ebb4caSwyllys 
99699ebb4caSwyllys 	return (pkey);
99799ebb4caSwyllys }
99899ebb4caSwyllys 
99999ebb4caSwyllys KMF_RETURN
1000*30a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
100199ebb4caSwyllys {
100299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
100399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1004f482c776Swyllys 	int i, n;
1005f482c776Swyllys 	uint32_t maxcerts = 0;
1006*30a5e8faSwyllys 	uint32_t *num_certs;
1007*30a5e8faSwyllys 	KMF_X509_DER_CERT *kmf_cert = NULL;
1008*30a5e8faSwyllys 	char *dirpath = NULL;
1009*30a5e8faSwyllys 	char *filename = NULL;
1010*30a5e8faSwyllys 	char *fullpath = NULL;
1011*30a5e8faSwyllys 	char *issuer = NULL;
1012*30a5e8faSwyllys 	char *subject = NULL;
1013*30a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
1014*30a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
101599ebb4caSwyllys 
1016*30a5e8faSwyllys 	num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
1017*30a5e8faSwyllys 	if (num_certs == NULL)
101899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
101999ebb4caSwyllys 
1020*30a5e8faSwyllys 	/* num_certs should reference the size of kmf_cert */
1021f482c776Swyllys 	maxcerts = *num_certs;
1022f482c776Swyllys 	if (maxcerts == 0)
1023f482c776Swyllys 		maxcerts = 0xFFFFFFFF;
102499ebb4caSwyllys 	*num_certs = 0;
102599ebb4caSwyllys 
1026*30a5e8faSwyllys 	/* Get the optional returned certificate list  */
1027*30a5e8faSwyllys 	kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
1028*30a5e8faSwyllys 	    numattr);
102999ebb4caSwyllys 
1030*30a5e8faSwyllys 	/*
1031*30a5e8faSwyllys 	 * The dirpath attribute and the filename attribute can not be NULL
1032*30a5e8faSwyllys 	 * at the same time.
1033*30a5e8faSwyllys 	 */
1034*30a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1035*30a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1036*30a5e8faSwyllys 	    numattr);
1037*30a5e8faSwyllys 
1038*30a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
103999ebb4caSwyllys 	if (fullpath == NULL)
104099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
104199ebb4caSwyllys 
1042*30a5e8faSwyllys 	/* Get optional search criteria attributes */
1043*30a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1044*30a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1045*30a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1046*30a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
1047*30a5e8faSwyllys 	    &validity, NULL);
1048*30a5e8faSwyllys 	if (rv != KMF_OK) {
1049*30a5e8faSwyllys 		validity = KMF_ALL_CERTS;
1050*30a5e8faSwyllys 		rv = KMF_OK;
1051*30a5e8faSwyllys 	}
1052*30a5e8faSwyllys 
105399ebb4caSwyllys 	if (isdir(fullpath)) {
105499ebb4caSwyllys 		DIR *dirp;
105599ebb4caSwyllys 		struct dirent *dp;
105699ebb4caSwyllys 
1057f482c776Swyllys 		n = 0;
105899ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
105999ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
106099ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
106199ebb4caSwyllys 		}
106299ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
106399ebb4caSwyllys 			char *fname;
106471593db2Swyllys 			KMF_DATA *certlist = NULL;
1065f482c776Swyllys 			uint32_t loaded_certs = 0;
106671593db2Swyllys 
106799ebb4caSwyllys 			if (strcmp(dp->d_name, ".") == 0 ||
106899ebb4caSwyllys 			    strcmp(dp->d_name, "..") == 0)
106999ebb4caSwyllys 				continue;
107099ebb4caSwyllys 
107134acef67Swyllys 			fname = get_fullpath(fullpath, (char *)&dp->d_name);
107299ebb4caSwyllys 
1073*30a5e8faSwyllys 			rv = load_certs(kmfh, issuer, subject, serial,
1074*30a5e8faSwyllys 			    validity, fname, &certlist,	&loaded_certs);
107599ebb4caSwyllys 
107699ebb4caSwyllys 			if (rv != KMF_OK) {
107799ebb4caSwyllys 				free(fname);
107871593db2Swyllys 				if (certlist != NULL) {
1079f482c776Swyllys 					for (i = 0; i < loaded_certs; i++)
1080*30a5e8faSwyllys 						kmf_free_data(&certlist[i]);
108171593db2Swyllys 					free(certlist);
108271593db2Swyllys 				}
108399ebb4caSwyllys 				continue;
108499ebb4caSwyllys 			}
108599ebb4caSwyllys 
108699ebb4caSwyllys 			/* If load succeeds, add certdata to the list */
108799ebb4caSwyllys 			if (kmf_cert != NULL) {
1088f482c776Swyllys 				for (i = 0; i < loaded_certs &&
1089b4058258Swyllys 				    n < maxcerts; i++) {
109071593db2Swyllys 					kmf_cert[n].certificate.Data =
109171593db2Swyllys 					    certlist[i].Data;
109299ebb4caSwyllys 					kmf_cert[n].certificate.Length =
109371593db2Swyllys 					    certlist[i].Length;
109499ebb4caSwyllys 
109599ebb4caSwyllys 					kmf_cert[n].kmf_private.keystore_type =
109699ebb4caSwyllys 					    KMF_KEYSTORE_OPENSSL;
109799ebb4caSwyllys 					kmf_cert[n].kmf_private.flags =
109899ebb4caSwyllys 					    KMF_FLAG_CERT_VALID;
109971593db2Swyllys 					kmf_cert[n].kmf_private.label =
110071593db2Swyllys 					    strdup(fname);
110199ebb4caSwyllys 					n++;
110299ebb4caSwyllys 				}
1103b4058258Swyllys 				/*
1104b4058258Swyllys 				 * If maxcerts < loaded_certs, clean up the
1105b4058258Swyllys 				 * certs that were not used.
1106b4058258Swyllys 				 */
1107f482c776Swyllys 				for (; i < loaded_certs; i++)
1108*30a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1109f482c776Swyllys 			} else {
1110f482c776Swyllys 				for (i = 0; i < loaded_certs; i++)
1111*30a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1112f482c776Swyllys 				n += loaded_certs;
111371593db2Swyllys 			}
1114f482c776Swyllys 			free(certlist);
111571593db2Swyllys 			free(fname);
111671593db2Swyllys 		}
111799ebb4caSwyllys 		(*num_certs) = n;
111899ebb4caSwyllys 		if (*num_certs == 0)
111999ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
1120*30a5e8faSwyllys 		if (*num_certs > 0)
112199ebb4caSwyllys 			rv = KMF_OK;
112299ebb4caSwyllys exit:
112399ebb4caSwyllys 		(void) closedir(dirp);
112499ebb4caSwyllys 	} else {
112571593db2Swyllys 		KMF_DATA *certlist = NULL;
1126f482c776Swyllys 		uint32_t loaded_certs = 0;
112771593db2Swyllys 
1128*30a5e8faSwyllys 		rv = load_certs(kmfh, issuer, subject, serial, validity,
1129*30a5e8faSwyllys 		    fullpath, &certlist, &loaded_certs);
113099ebb4caSwyllys 		if (rv != KMF_OK) {
113199ebb4caSwyllys 			free(fullpath);
113299ebb4caSwyllys 			return (rv);
113399ebb4caSwyllys 		}
113499ebb4caSwyllys 
1135f482c776Swyllys 		n = 0;
113671593db2Swyllys 		if (kmf_cert != NULL && certlist != NULL) {
1137f482c776Swyllys 			for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1138f482c776Swyllys 				kmf_cert[n].certificate.Data =
113971593db2Swyllys 				    certlist[i].Data;
1140f482c776Swyllys 				kmf_cert[n].certificate.Length =
114171593db2Swyllys 				    certlist[i].Length;
1142f482c776Swyllys 				kmf_cert[n].kmf_private.keystore_type =
114399ebb4caSwyllys 				    KMF_KEYSTORE_OPENSSL;
1144f482c776Swyllys 				kmf_cert[n].kmf_private.flags =
114571593db2Swyllys 				    KMF_FLAG_CERT_VALID;
1146f482c776Swyllys 				kmf_cert[n].kmf_private.label =
114771593db2Swyllys 				    strdup(fullpath);
1148f482c776Swyllys 				n++;
114971593db2Swyllys 			}
1150f482c776Swyllys 			/* If maxcerts < loaded_certs, clean up */
1151f482c776Swyllys 			for (; i < loaded_certs; i++)
1152*30a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1153f482c776Swyllys 		} else if (certlist != NULL) {
1154f482c776Swyllys 			for (i = 0; i < loaded_certs; i++)
1155*30a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1156f482c776Swyllys 			n = loaded_certs;
1157f482c776Swyllys 		}
1158*30a5e8faSwyllys 		if (certlist != NULL)
115971593db2Swyllys 			free(certlist);
1160f482c776Swyllys 		*num_certs = n;
116199ebb4caSwyllys 	}
116299ebb4caSwyllys 
116399ebb4caSwyllys 	free(fullpath);
116499ebb4caSwyllys 
116599ebb4caSwyllys 	return (rv);
116699ebb4caSwyllys }
116799ebb4caSwyllys 
116899ebb4caSwyllys void
116999ebb4caSwyllys /*ARGSUSED*/
117099ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
117199ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert)
117299ebb4caSwyllys {
117399ebb4caSwyllys 	if (kmf_cert != NULL) {
117499ebb4caSwyllys 		if (kmf_cert->certificate.Data != NULL) {
117599ebb4caSwyllys 			free(kmf_cert->certificate.Data);
117699ebb4caSwyllys 			kmf_cert->certificate.Data = NULL;
117799ebb4caSwyllys 			kmf_cert->certificate.Length = 0;
117899ebb4caSwyllys 		}
117999ebb4caSwyllys 		if (kmf_cert->kmf_private.label)
118099ebb4caSwyllys 			free(kmf_cert->kmf_private.label);
118199ebb4caSwyllys 	}
118299ebb4caSwyllys }
118399ebb4caSwyllys 
1184*30a5e8faSwyllys /*ARGSUSED*/
118599ebb4caSwyllys KMF_RETURN
1186*30a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
118799ebb4caSwyllys {
118899ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
1189*30a5e8faSwyllys 	KMF_DATA *cert = NULL;
1190*30a5e8faSwyllys 	char *outfilename = NULL;
1191*30a5e8faSwyllys 	char *dirpath = NULL;
1192*30a5e8faSwyllys 	char *fullpath = NULL;
119399ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
119499ebb4caSwyllys 
1195*30a5e8faSwyllys 	/* Get the cert data */
1196*30a5e8faSwyllys 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
1197*30a5e8faSwyllys 	if (cert == NULL || cert->Data == NULL)
119899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
119999ebb4caSwyllys 
1200*30a5e8faSwyllys 	/* Check the output filename and directory attributes. */
1201*30a5e8faSwyllys 	outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1202*30a5e8faSwyllys 	    numattr);
1203*30a5e8faSwyllys 	if (outfilename == NULL)
1204*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
120599ebb4caSwyllys 
1206*30a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1207*30a5e8faSwyllys 	fullpath = get_fullpath(dirpath, outfilename);
120899ebb4caSwyllys 	if (fullpath == NULL)
1209*30a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
121099ebb4caSwyllys 
1211*30a5e8faSwyllys 	/* Check the optional format attribute */
1212*30a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
1213*30a5e8faSwyllys 	    &format, NULL);
1214*30a5e8faSwyllys 	if (ret != KMF_OK) {
1215*30a5e8faSwyllys 		/* If there is no format attribute, then default to PEM */
1216*30a5e8faSwyllys 		format = KMF_FORMAT_PEM;
121799ebb4caSwyllys 		ret = KMF_OK;
1218*30a5e8faSwyllys 	} else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
1219*30a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
122099ebb4caSwyllys 		goto out;
122199ebb4caSwyllys 	}
122299ebb4caSwyllys 
1223*30a5e8faSwyllys 	/* Store the certificate in the file with the specified format */
1224*30a5e8faSwyllys 	ret = kmf_create_cert_file(cert, format, fullpath);
122599ebb4caSwyllys 
122699ebb4caSwyllys out:
122799ebb4caSwyllys 	if (fullpath != NULL)
122899ebb4caSwyllys 		free(fullpath);
122999ebb4caSwyllys 
123099ebb4caSwyllys 	return (ret);
123199ebb4caSwyllys }
123299ebb4caSwyllys 
1233*30a5e8faSwyllys 
123499ebb4caSwyllys KMF_RETURN
1235*30a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
123699ebb4caSwyllys {
123799ebb4caSwyllys 	KMF_RETURN rv;
123899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
123999ebb4caSwyllys 	KMF_DATA certdata = {NULL, 0};
1240*30a5e8faSwyllys 	char *dirpath = NULL;
1241*30a5e8faSwyllys 	char *filename = NULL;
1242*30a5e8faSwyllys 	char *fullpath = NULL;
1243*30a5e8faSwyllys 	char *issuer = NULL;
1244*30a5e8faSwyllys 	char *subject = NULL;
1245*30a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
1246*30a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
124799ebb4caSwyllys 
1248*30a5e8faSwyllys 	/*
1249*30a5e8faSwyllys 	 * Get the DIRPATH and CERT_FILENAME attributes.  They can not be
1250*30a5e8faSwyllys 	 * NULL at the same time.
1251*30a5e8faSwyllys 	 */
1252*30a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1253*30a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1254*30a5e8faSwyllys 	    numattr);
1255*30a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
125699ebb4caSwyllys 	if (fullpath == NULL)
125799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
125899ebb4caSwyllys 
1259*30a5e8faSwyllys 	/* Get optional search criteria attributes */
1260*30a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1261*30a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1262*30a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1263*30a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
1264*30a5e8faSwyllys 	    &validity, NULL);
1265*30a5e8faSwyllys 	if (rv != KMF_OK) {
1266*30a5e8faSwyllys 		validity = KMF_ALL_CERTS;
1267*30a5e8faSwyllys 		rv = KMF_OK;
1268*30a5e8faSwyllys 	}
1269*30a5e8faSwyllys 
127099ebb4caSwyllys 	if (isdir(fullpath)) {
127199ebb4caSwyllys 		DIR *dirp;
127299ebb4caSwyllys 		struct dirent *dp;
127399ebb4caSwyllys 
127499ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
127599ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
127699ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
127799ebb4caSwyllys 		}
127899ebb4caSwyllys 
127999ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
128099ebb4caSwyllys 			if (strcmp(dp->d_name, ".") != 0 &&
128199ebb4caSwyllys 			    strcmp(dp->d_name, "..") != 0) {
128299ebb4caSwyllys 				char *fname;
128399ebb4caSwyllys 
128499ebb4caSwyllys 				fname = get_fullpath(fullpath,
128599ebb4caSwyllys 				    (char *)&dp->d_name);
128699ebb4caSwyllys 
128799ebb4caSwyllys 				if (fname == NULL) {
128899ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
128999ebb4caSwyllys 					break;
129099ebb4caSwyllys 				}
129199ebb4caSwyllys 
1292*30a5e8faSwyllys 				rv = kmf_load_cert(kmfh, issuer, subject,
1293*30a5e8faSwyllys 				    serial, validity, fname, &certdata);
129499ebb4caSwyllys 
129599ebb4caSwyllys 				if (rv == KMF_ERR_CERT_NOT_FOUND) {
129699ebb4caSwyllys 					free(fname);
129799ebb4caSwyllys 					if (certdata.Data)
129899ebb4caSwyllys 						free(certdata.Data);
129999ebb4caSwyllys 					rv = KMF_OK;
130099ebb4caSwyllys 					continue;
130199ebb4caSwyllys 				} else if (rv != KMF_OK) {
130299ebb4caSwyllys 					free(fname);
130399ebb4caSwyllys 					break;
130499ebb4caSwyllys 				}
130599ebb4caSwyllys 
130699ebb4caSwyllys 				if (unlink(fname) != 0) {
130799ebb4caSwyllys 					SET_SYS_ERROR(kmfh, errno);
130899ebb4caSwyllys 					rv = KMF_ERR_INTERNAL;
130999ebb4caSwyllys 					free(fname);
131099ebb4caSwyllys 					break;
131199ebb4caSwyllys 				}
131299ebb4caSwyllys 				free(fname);
131399ebb4caSwyllys 				if (certdata.Data)
131499ebb4caSwyllys 					free(certdata.Data);
131599ebb4caSwyllys 			}
131699ebb4caSwyllys 		}
131799ebb4caSwyllys 		(void) closedir(dirp);
131899ebb4caSwyllys 	} else {
131999ebb4caSwyllys 		/* Just try to load a single certificate */
1320*30a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
1321*30a5e8faSwyllys 		    fullpath, &certdata);
132299ebb4caSwyllys 		if (rv == KMF_OK) {
132399ebb4caSwyllys 			if (unlink(fullpath) != 0) {
132499ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
132599ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
132699ebb4caSwyllys 			}
132799ebb4caSwyllys 		}
132899ebb4caSwyllys 	}
132999ebb4caSwyllys 
133099ebb4caSwyllys out:
133199ebb4caSwyllys 	if (fullpath != NULL)
133299ebb4caSwyllys 		free(fullpath);
133399ebb4caSwyllys 
133499ebb4caSwyllys 	if (certdata.Data)
133599ebb4caSwyllys 		free(certdata.Data);
133699ebb4caSwyllys 
133799ebb4caSwyllys 	return (rv);
133899ebb4caSwyllys }
133999ebb4caSwyllys 
134099ebb4caSwyllys KMF_RETURN
134199ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
134299ebb4caSwyllys 	KMF_DATA *keydata)
134399ebb4caSwyllys {
134499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
134599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
134699ebb4caSwyllys 	int n;
134799ebb4caSwyllys 
134899ebb4caSwyllys 	if (key == NULL || keydata == NULL ||
134999ebb4caSwyllys 	    key->keyp == NULL)
135099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
135199ebb4caSwyllys 
135299ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
135399ebb4caSwyllys 		RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
135499ebb4caSwyllys 
135599ebb4caSwyllys 		if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
135699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
135799ebb4caSwyllys 			return (KMF_ERR_ENCODING);
135899ebb4caSwyllys 		}
135999ebb4caSwyllys 		RSA_free(pubkey);
136099ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
136199ebb4caSwyllys 		DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
136299ebb4caSwyllys 
136399ebb4caSwyllys 		if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
136499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
136599ebb4caSwyllys 			return (KMF_ERR_ENCODING);
136699ebb4caSwyllys 		}
136799ebb4caSwyllys 		DSA_free(pubkey);
136899ebb4caSwyllys 	} else {
136999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
137099ebb4caSwyllys 	}
137199ebb4caSwyllys 	keydata->Length = n;
137299ebb4caSwyllys 
137399ebb4caSwyllys cleanup:
137499ebb4caSwyllys 	if (rv != KMF_OK) {
137599ebb4caSwyllys 		if (keydata->Data)
137699ebb4caSwyllys 			free(keydata->Data);
137799ebb4caSwyllys 		keydata->Data = NULL;
137899ebb4caSwyllys 		keydata->Length = 0;
137999ebb4caSwyllys 	}
138099ebb4caSwyllys 
138199ebb4caSwyllys 	return (rv);
138299ebb4caSwyllys }
138399ebb4caSwyllys 
138499ebb4caSwyllys static KMF_RETURN
1385*30a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
1386*30a5e8faSwyllys 	KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
138799ebb4caSwyllys {
138899ebb4caSwyllys 	int rv = 0;
138999ebb4caSwyllys 	RSA *rsa;
139099ebb4caSwyllys 	DSA *dsa;
139199ebb4caSwyllys 
139299ebb4caSwyllys 	switch (format) {
139399ebb4caSwyllys 		case KMF_FORMAT_ASN1:
139499ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
139599ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
1396*30a5e8faSwyllys 				if (private)
139799ebb4caSwyllys 					rv = i2d_RSAPrivateKey_bio(out, rsa);
1398*30a5e8faSwyllys 				else
1399*30a5e8faSwyllys 					rv = i2d_RSAPublicKey_bio(out, rsa);
140099ebb4caSwyllys 				RSA_free(rsa);
140199ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
140299ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
140399ebb4caSwyllys 				rv = i2d_DSAPrivateKey_bio(out, dsa);
140499ebb4caSwyllys 				DSA_free(dsa);
140599ebb4caSwyllys 			}
140699ebb4caSwyllys 			if (rv == 1) {
140799ebb4caSwyllys 				rv = KMF_OK;
140899ebb4caSwyllys 			} else {
140999ebb4caSwyllys 				SET_ERROR(kmfh, rv);
141099ebb4caSwyllys 			}
141199ebb4caSwyllys 			break;
141299ebb4caSwyllys 		case KMF_FORMAT_PEM:
141399ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
141499ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
1415*30a5e8faSwyllys 				if (private)
141699ebb4caSwyllys 					rv = PEM_write_bio_RSAPrivateKey(out,
1417*30a5e8faSwyllys 					    rsa, NULL, NULL, 0, NULL,
1418*30a5e8faSwyllys 					    (cred != NULL ? cred->cred : NULL));
1419*30a5e8faSwyllys 				else
1420*30a5e8faSwyllys 					rv = PEM_write_bio_RSAPublicKey(out,
1421*30a5e8faSwyllys 					    rsa);
142299ebb4caSwyllys 				RSA_free(rsa);
142399ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
142499ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
142599ebb4caSwyllys 				rv = PEM_write_bio_DSAPrivateKey(out,
1426*30a5e8faSwyllys 				    dsa, NULL, NULL, 0, NULL,
1427*30a5e8faSwyllys 				    (cred != NULL ? cred->cred : NULL));
142899ebb4caSwyllys 				DSA_free(dsa);
142999ebb4caSwyllys 			}
143099ebb4caSwyllys 
143199ebb4caSwyllys 			if (rv == 1) {
143299ebb4caSwyllys 				rv = KMF_OK;
143399ebb4caSwyllys 			} else {
143499ebb4caSwyllys 				SET_ERROR(kmfh, rv);
143599ebb4caSwyllys 			}
143699ebb4caSwyllys 			break;
143799ebb4caSwyllys 
143899ebb4caSwyllys 		default:
143999ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
144099ebb4caSwyllys 	}
144199ebb4caSwyllys 
144299ebb4caSwyllys 	return (rv);
144399ebb4caSwyllys }
144499ebb4caSwyllys 
144599ebb4caSwyllys KMF_RETURN
1446*30a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
1447*30a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
144899ebb4caSwyllys {
144999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
145099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
145199ebb4caSwyllys 	uint32_t eValue = 0x010001;
145299ebb4caSwyllys 	RSA *sslPrivKey = NULL;
145399ebb4caSwyllys 	DSA *sslDSAKey = NULL;
145499ebb4caSwyllys 	EVP_PKEY *eprikey = NULL;
145599ebb4caSwyllys 	EVP_PKEY *epubkey = NULL;
145699ebb4caSwyllys 	BIO *out = NULL;
1457*30a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
1458*30a5e8faSwyllys 	uint32_t keylen = 1024;
1459*30a5e8faSwyllys 	uint32_t keylen_size = sizeof (uint32_t);
1460*30a5e8faSwyllys 	boolean_t storekey = TRUE;
1461*30a5e8faSwyllys 	KMF_KEY_ALG keytype = KMF_RSA;
146299ebb4caSwyllys 
1463*30a5e8faSwyllys 	rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
1464*30a5e8faSwyllys 	    &storekey, NULL);
1465*30a5e8faSwyllys 	if (rv != KMF_OK) {
1466*30a5e8faSwyllys 		/* "storekey" is optional. Default is TRUE */
1467*30a5e8faSwyllys 		rv = KMF_OK;
146899ebb4caSwyllys 	}
146999ebb4caSwyllys 
1470*30a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
1471*30a5e8faSwyllys 	    (void *)&keytype, NULL);
1472*30a5e8faSwyllys 	if (rv != KMF_OK)
1473*30a5e8faSwyllys 		/* keytype is optional.  KMF_RSA is default */
1474*30a5e8faSwyllys 		rv = KMF_OK;
147599ebb4caSwyllys 
1476*30a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
1477*30a5e8faSwyllys 	if (pubkey == NULL)
147899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
147999ebb4caSwyllys 
1480*30a5e8faSwyllys 	privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
1481*30a5e8faSwyllys 	if (privkey == NULL)
1482*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1483*30a5e8faSwyllys 
1484*30a5e8faSwyllys 	(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
1485*30a5e8faSwyllys 	(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
148699ebb4caSwyllys 
148799ebb4caSwyllys 	eprikey = EVP_PKEY_new();
148899ebb4caSwyllys 	if (eprikey == NULL) {
148999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
149099ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
149199ebb4caSwyllys 		goto cleanup;
149299ebb4caSwyllys 	}
149399ebb4caSwyllys 	epubkey = EVP_PKEY_new();
149499ebb4caSwyllys 	if (epubkey == NULL) {
149599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
149699ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
149799ebb4caSwyllys 		goto cleanup;
149899ebb4caSwyllys 	}
1499*30a5e8faSwyllys 	if (keytype == KMF_RSA) {
1500*30a5e8faSwyllys 		KMF_BIGINT *rsaexp = NULL;
150199ebb4caSwyllys 
1502*30a5e8faSwyllys 		rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
1503*30a5e8faSwyllys 		if (rsaexp != NULL) {
1504*30a5e8faSwyllys 			if (rsaexp->len > 0 &&
1505*30a5e8faSwyllys 			    rsaexp->len <= sizeof (eValue) &&
1506*30a5e8faSwyllys 			    rsaexp->val != NULL) {
1507*30a5e8faSwyllys 				/*LINTED*/
1508*30a5e8faSwyllys 				eValue = *(uint32_t *)rsaexp->val;
1509*30a5e8faSwyllys 			} else {
1510*30a5e8faSwyllys 				rv = KMF_ERR_BAD_PARAMETER;
1511*30a5e8faSwyllys 				goto cleanup;
1512*30a5e8faSwyllys 			}
1513*30a5e8faSwyllys 		} else {
1514*30a5e8faSwyllys 			/* RSA Exponent is optional. Default is 0x10001 */
1515*30a5e8faSwyllys 			rv = KMF_OK;
1516*30a5e8faSwyllys 		}
1517*30a5e8faSwyllys 
1518*30a5e8faSwyllys 		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
1519*30a5e8faSwyllys 		    &keylen, &keylen_size);
1520*30a5e8faSwyllys 		if (rv == KMF_ERR_ATTR_NOT_FOUND)
1521*30a5e8faSwyllys 			/* keylen is optional, default is 1024 */
1522*30a5e8faSwyllys 			rv = KMF_OK;
1523*30a5e8faSwyllys 		if (rv != KMF_OK) {
1524*30a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
1525*30a5e8faSwyllys 			goto cleanup;
1526*30a5e8faSwyllys 		}
1527*30a5e8faSwyllys 
1528*30a5e8faSwyllys 		sslPrivKey = RSA_generate_key(keylen, eValue, NULL, NULL);
152999ebb4caSwyllys 		if (sslPrivKey == NULL) {
153099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
153199ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
153299ebb4caSwyllys 		} else {
1533*30a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
153499ebb4caSwyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
153599ebb4caSwyllys 			privkey->keyalg = KMF_RSA;
153699ebb4caSwyllys 			privkey->keyclass = KMF_ASYM_PRI;
153799ebb4caSwyllys 			privkey->israw = FALSE;
153899ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
1539*30a5e8faSwyllys 
154099ebb4caSwyllys 			/* OpenSSL derives the public key from the private */
1541*30a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
154299ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
154399ebb4caSwyllys 			pubkey->keyalg = KMF_RSA;
154499ebb4caSwyllys 			pubkey->israw = FALSE;
154599ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
154699ebb4caSwyllys 			pubkey->keyp = (void *)epubkey;
154799ebb4caSwyllys 		}
1548*30a5e8faSwyllys 	} else if (keytype == KMF_DSA) {
1549*30a5e8faSwyllys 		DSA *dp;
155099ebb4caSwyllys 		sslDSAKey = DSA_new();
155199ebb4caSwyllys 		if (sslDSAKey == NULL) {
155299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
155399ebb4caSwyllys 			return (KMF_ERR_MEMORY);
155499ebb4caSwyllys 		}
155599ebb4caSwyllys 
155699ebb4caSwyllys 		if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) ==
155799ebb4caSwyllys 		    NULL) {
155899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
155999ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
156099ebb4caSwyllys 			goto cleanup;
156199ebb4caSwyllys 		}
156299ebb4caSwyllys 		if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) ==
156399ebb4caSwyllys 		    NULL) {
156499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
156599ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
156699ebb4caSwyllys 			goto cleanup;
156799ebb4caSwyllys 		}
156899ebb4caSwyllys 		if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) ==
156999ebb4caSwyllys 		    NULL) {
157099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
157199ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
157299ebb4caSwyllys 			goto cleanup;
157399ebb4caSwyllys 		}
157499ebb4caSwyllys 
157599ebb4caSwyllys 		if (!DSA_generate_key(sslDSAKey)) {
157699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
157799ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
157899ebb4caSwyllys 			goto cleanup;
157999ebb4caSwyllys 		}
158099ebb4caSwyllys 
158199ebb4caSwyllys 		privkey->kstype = KMF_KEYSTORE_OPENSSL;
158299ebb4caSwyllys 		privkey->keyalg = KMF_DSA;
158399ebb4caSwyllys 		privkey->keyclass = KMF_ASYM_PRI;
158499ebb4caSwyllys 		privkey->israw = FALSE;
158599ebb4caSwyllys 		if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
158699ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
158799ebb4caSwyllys 		} else {
158899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
158999ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
159099ebb4caSwyllys 			goto cleanup;
159199ebb4caSwyllys 		}
1592*30a5e8faSwyllys 		dp = DSA_new();
159399ebb4caSwyllys 		/* Make a copy for the public key */
159499ebb4caSwyllys 		if (dp != NULL) {
159599ebb4caSwyllys 			if ((dp->p = BN_new()) == NULL) {
159699ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
159799ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
159899ebb4caSwyllys 				DSA_free(dp);
159999ebb4caSwyllys 				goto cleanup;
160099ebb4caSwyllys 			}
160199ebb4caSwyllys 			if ((dp->q = BN_new()) == NULL) {
160299ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
160399ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
160499ebb4caSwyllys 				BN_free(dp->p);
160599ebb4caSwyllys 				DSA_free(dp);
160699ebb4caSwyllys 				goto cleanup;
160799ebb4caSwyllys 			}
160899ebb4caSwyllys 			if ((dp->g = BN_new()) == NULL) {
160999ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
161099ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
161199ebb4caSwyllys 				BN_free(dp->q);
161299ebb4caSwyllys 				BN_free(dp->p);
161399ebb4caSwyllys 				DSA_free(dp);
161499ebb4caSwyllys 				goto cleanup;
161599ebb4caSwyllys 			}
161699ebb4caSwyllys 			if ((dp->pub_key = BN_new()) == NULL) {
161799ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
161899ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
161999ebb4caSwyllys 				BN_free(dp->q);
162099ebb4caSwyllys 				BN_free(dp->p);
162199ebb4caSwyllys 				BN_free(dp->g);
162299ebb4caSwyllys 				DSA_free(dp);
162399ebb4caSwyllys 				goto cleanup;
162499ebb4caSwyllys 			}
162599ebb4caSwyllys 			(void) BN_copy(dp->p, sslDSAKey->p);
162699ebb4caSwyllys 			(void) BN_copy(dp->q, sslDSAKey->q);
162799ebb4caSwyllys 			(void) BN_copy(dp->g, sslDSAKey->g);
162899ebb4caSwyllys 			(void) BN_copy(dp->pub_key, sslDSAKey->pub_key);
162999ebb4caSwyllys 
163099ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
163199ebb4caSwyllys 			pubkey->keyalg = KMF_DSA;
163299ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
163399ebb4caSwyllys 			pubkey->israw = FALSE;
163499ebb4caSwyllys 
163599ebb4caSwyllys 			if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
163699ebb4caSwyllys 				pubkey->keyp = (void *)epubkey;
163799ebb4caSwyllys 			} else {
163899ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
163999ebb4caSwyllys 				rv = KMF_ERR_KEYGEN_FAILED;
164099ebb4caSwyllys 				goto cleanup;
164199ebb4caSwyllys 			}
164299ebb4caSwyllys 		}
164399ebb4caSwyllys 	}
164499ebb4caSwyllys 
164599ebb4caSwyllys 	if (rv != KMF_OK) {
164699ebb4caSwyllys 		goto cleanup;
164799ebb4caSwyllys 	}
164899ebb4caSwyllys 
1649*30a5e8faSwyllys 	if (storekey) {
1650*30a5e8faSwyllys 		KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
1651*30a5e8faSwyllys 		int i = 0;
1652*30a5e8faSwyllys 		char *keyfile = NULL, *dirpath = NULL;
1653*30a5e8faSwyllys 		KMF_ENCODE_FORMAT format;
1654*30a5e8faSwyllys 		/*
1655*30a5e8faSwyllys 		 * Construct a new attribute arrray and call openssl_store_key
1656*30a5e8faSwyllys 		 */
1657*30a5e8faSwyllys 		kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
1658*30a5e8faSwyllys 		    privkey, sizeof (privkey));
1659*30a5e8faSwyllys 		i++;
1660*30a5e8faSwyllys 
1661*30a5e8faSwyllys 		dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1662*30a5e8faSwyllys 		if (dirpath != NULL) {
1663*30a5e8faSwyllys 			storeattrs[i].type = KMF_DIRPATH_ATTR;
1664*30a5e8faSwyllys 			storeattrs[i].pValue = dirpath;
1665*30a5e8faSwyllys 			storeattrs[i].valueLen = strlen(dirpath);
1666*30a5e8faSwyllys 			i++;
1667*30a5e8faSwyllys 		} else {
1668*30a5e8faSwyllys 			rv = KMF_OK; /* DIRPATH is optional */
166999ebb4caSwyllys 		}
1670*30a5e8faSwyllys 		keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
1671*30a5e8faSwyllys 		    attrlist, numattr);
1672*30a5e8faSwyllys 		if (keyfile != NULL) {
1673*30a5e8faSwyllys 			storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
1674*30a5e8faSwyllys 			storeattrs[i].pValue = keyfile;
1675*30a5e8faSwyllys 			storeattrs[i].valueLen = strlen(keyfile);
1676*30a5e8faSwyllys 			i++;
1677*30a5e8faSwyllys 		} else {
1678*30a5e8faSwyllys 			goto cleanup; /* KEYFILE is required */
1679*30a5e8faSwyllys 		}
1680*30a5e8faSwyllys 		rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
1681*30a5e8faSwyllys 		    (void *)&format, NULL);
1682*30a5e8faSwyllys 		if (rv == KMF_OK) {
1683*30a5e8faSwyllys 			storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
1684*30a5e8faSwyllys 			storeattrs[i].pValue = &format;
1685*30a5e8faSwyllys 			storeattrs[i].valueLen = sizeof (format);
1686*30a5e8faSwyllys 			i++;
1687*30a5e8faSwyllys 		}
1688*30a5e8faSwyllys 
1689*30a5e8faSwyllys 		rv = OpenSSL_StoreKey(handle, i, storeattrs);
1690*30a5e8faSwyllys 	}
169199ebb4caSwyllys 
169299ebb4caSwyllys cleanup:
169399ebb4caSwyllys 	if (rv != KMF_OK) {
169499ebb4caSwyllys 		if (eprikey != NULL)
169599ebb4caSwyllys 			EVP_PKEY_free(eprikey);
169699ebb4caSwyllys 
169799ebb4caSwyllys 		if (epubkey != NULL)
169899ebb4caSwyllys 			EVP_PKEY_free(epubkey);
169999ebb4caSwyllys 
170099ebb4caSwyllys 		if (pubkey->keylabel) {
170199ebb4caSwyllys 			free(pubkey->keylabel);
170299ebb4caSwyllys 			pubkey->keylabel = NULL;
170399ebb4caSwyllys 		}
170499ebb4caSwyllys 
170599ebb4caSwyllys 		if (privkey->keylabel) {
170699ebb4caSwyllys 			free(privkey->keylabel);
170799ebb4caSwyllys 			privkey->keylabel = NULL;
170899ebb4caSwyllys 		}
170999ebb4caSwyllys 
171099ebb4caSwyllys 		pubkey->keyp = NULL;
171199ebb4caSwyllys 		privkey->keyp = NULL;
171299ebb4caSwyllys 	}
171399ebb4caSwyllys 
171499ebb4caSwyllys 	if (sslPrivKey)
171599ebb4caSwyllys 		RSA_free(sslPrivKey);
171699ebb4caSwyllys 
171799ebb4caSwyllys 	if (sslDSAKey)
171899ebb4caSwyllys 		DSA_free(sslDSAKey);
171999ebb4caSwyllys 
172099ebb4caSwyllys 	if (out != NULL)
172199ebb4caSwyllys 		(void) BIO_free(out);
172299ebb4caSwyllys 
172399ebb4caSwyllys 	return (rv);
172499ebb4caSwyllys }
172599ebb4caSwyllys 
172699ebb4caSwyllys KMF_RETURN
172799ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
172899ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
172999ebb4caSwyllys {
173099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
173199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
173299ebb4caSwyllys 	KMF_ALGORITHM_INDEX		AlgId;
173399ebb4caSwyllys 	EVP_MD_CTX ctx;
173499ebb4caSwyllys 	const EVP_MD *md;
173502744e81Swyllys 
173699ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
173799ebb4caSwyllys 	    tobesigned == NULL || output == NULL ||
173899ebb4caSwyllys 	    tobesigned->Data == NULL ||
173999ebb4caSwyllys 	    output->Data == NULL)
174099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
174199ebb4caSwyllys 
174299ebb4caSwyllys 	/* Map the OID to an OpenSSL algorithm */
1743*30a5e8faSwyllys 	AlgId = x509_algoid_to_algid(AlgOID);
174499ebb4caSwyllys 	if (AlgId == KMF_ALGID_NONE)
174599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
174699ebb4caSwyllys 
174799ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
174899ebb4caSwyllys 		EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
174999ebb4caSwyllys 		uchar_t *p;
175002744e81Swyllys 		int len;
175199ebb4caSwyllys 		if (AlgId == KMF_ALGID_MD5WithRSA)
175299ebb4caSwyllys 			md = EVP_md5();
175399ebb4caSwyllys 		else if (AlgId == KMF_ALGID_MD2WithRSA)
175499ebb4caSwyllys 			md = EVP_md2();
175599ebb4caSwyllys 		else if (AlgId == KMF_ALGID_SHA1WithRSA)
175699ebb4caSwyllys 			md = EVP_sha1();
175702744e81Swyllys 		else if (AlgId == KMF_ALGID_RSA)
175802744e81Swyllys 			md = NULL;
175999ebb4caSwyllys 		else
176099ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
176199ebb4caSwyllys 
176202744e81Swyllys 		if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
176302744e81Swyllys 			RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
176499ebb4caSwyllys 
176502744e81Swyllys 			p = output->Data;
176602744e81Swyllys 			if ((len = RSA_private_encrypt(tobesigned->Length,
176702744e81Swyllys 			    tobesigned->Data, p, rsa,
176802744e81Swyllys 			    RSA_PKCS1_PADDING)) <= 0) {
176902744e81Swyllys 				SET_ERROR(kmfh, ERR_get_error());
177002744e81Swyllys 				ret = KMF_ERR_INTERNAL;
177102744e81Swyllys 			}
177202744e81Swyllys 			output->Length = len;
177302744e81Swyllys 		} else {
177499ebb4caSwyllys 			(void) EVP_MD_CTX_init(&ctx);
177599ebb4caSwyllys 			(void) EVP_SignInit_ex(&ctx, md, NULL);
177699ebb4caSwyllys 			(void) EVP_SignUpdate(&ctx, tobesigned->Data,
177799ebb4caSwyllys 			    (uint32_t)tobesigned->Length);
177899ebb4caSwyllys 			len = (uint32_t)output->Length;
177999ebb4caSwyllys 			p = output->Data;
178002744e81Swyllys 			if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) {
178199ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
178202744e81Swyllys 				len = 0;
178302744e81Swyllys 				ret = KMF_ERR_INTERNAL;
178499ebb4caSwyllys 			}
178599ebb4caSwyllys 			output->Length = len;
178699ebb4caSwyllys 			(void) EVP_MD_CTX_cleanup(&ctx);
178702744e81Swyllys 		}
178899ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
178999ebb4caSwyllys 		DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
179099ebb4caSwyllys 
179199ebb4caSwyllys 		uchar_t hash[EVP_MAX_MD_SIZE];
179299ebb4caSwyllys 		uint32_t hashlen;
179399ebb4caSwyllys 		DSA_SIG *dsasig;
179499ebb4caSwyllys 
179599ebb4caSwyllys 		/*
179699ebb4caSwyllys 		 * OpenSSL EVP_Sign operation automatically converts to
179799ebb4caSwyllys 		 * ASN.1 output so we do the operations separately so we
179899ebb4caSwyllys 		 * are assured of NOT getting ASN.1 output returned.
179999ebb4caSwyllys 		 * KMF does not want ASN.1 encoded results because
180099ebb4caSwyllys 		 * not all mechanisms return ASN.1 encodings (PKCS#11
180199ebb4caSwyllys 		 * and NSS return raw signature data).
180299ebb4caSwyllys 		 */
180399ebb4caSwyllys 		md = EVP_sha1();
180499ebb4caSwyllys 		EVP_MD_CTX_init(&ctx);
180599ebb4caSwyllys 		(void) EVP_DigestInit_ex(&ctx, md, NULL);
180699ebb4caSwyllys 		(void) EVP_DigestUpdate(&ctx, tobesigned->Data,
180799ebb4caSwyllys 		    tobesigned->Length);
180899ebb4caSwyllys 		(void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
180999ebb4caSwyllys 		(void) EVP_MD_CTX_cleanup(&ctx);
181099ebb4caSwyllys 
181199ebb4caSwyllys 		dsasig = DSA_do_sign(hash, hashlen, dsa);
181299ebb4caSwyllys 		if (dsasig != NULL) {
181399ebb4caSwyllys 			int i;
181499ebb4caSwyllys 			output->Length = i = BN_bn2bin(dsasig->r, output->Data);
181599ebb4caSwyllys 			output->Length += BN_bn2bin(dsasig->s,
181699ebb4caSwyllys 			    &output->Data[i]);
181799ebb4caSwyllys 			DSA_SIG_free(dsasig);
181899ebb4caSwyllys 		} else {
181999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
182099ebb4caSwyllys 		}
182199ebb4caSwyllys 	} else {
182299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
182399ebb4caSwyllys 	}
182499ebb4caSwyllys cleanup:
182599ebb4caSwyllys 	return (ret);
182699ebb4caSwyllys }
182799ebb4caSwyllys 
182899ebb4caSwyllys KMF_RETURN
182999ebb4caSwyllys /*ARGSUSED*/
1830*30a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle,
1831*30a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
183299ebb4caSwyllys {
183399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
1834*30a5e8faSwyllys 	KMF_KEY_HANDLE *key;
1835*30a5e8faSwyllys 	boolean_t destroy = B_TRUE;
1836*30a5e8faSwyllys 
1837*30a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
183899ebb4caSwyllys 	if (key == NULL || key->keyp == NULL)
183999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
184099ebb4caSwyllys 
1841*30a5e8faSwyllys 	rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
1842*30a5e8faSwyllys 	    (void *)&destroy, NULL);
1843*30a5e8faSwyllys 	if (rv != KMF_OK) {
1844*30a5e8faSwyllys 		/* "destroy" is optional. Default is TRUE */
1845*30a5e8faSwyllys 		rv = KMF_OK;
1846*30a5e8faSwyllys 	}
1847*30a5e8faSwyllys 
184899ebb4caSwyllys 	if (key->keyclass != KMF_ASYM_PUB &&
184999ebb4caSwyllys 	    key->keyclass != KMF_ASYM_PRI &&
185099ebb4caSwyllys 	    key->keyclass != KMF_SYMMETRIC)
185199ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
185299ebb4caSwyllys 
185399ebb4caSwyllys 	if (key->keyclass == KMF_SYMMETRIC) {
1854*30a5e8faSwyllys 		kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
185599ebb4caSwyllys 		key->keyp = NULL;
185699ebb4caSwyllys 	} else {
185799ebb4caSwyllys 		if (key->keyp != NULL) {
185899ebb4caSwyllys 			EVP_PKEY_free(key->keyp);
185999ebb4caSwyllys 			key->keyp = NULL;
186099ebb4caSwyllys 		}
186199ebb4caSwyllys 	}
186299ebb4caSwyllys 
186399ebb4caSwyllys 	if (key->keylabel != NULL) {
186499ebb4caSwyllys 		EVP_PKEY *pkey = NULL;
186599ebb4caSwyllys 		/* If the file exists, make sure it is a proper key. */
186699ebb4caSwyllys 		pkey = openssl_load_key(handle, key->keylabel);
186799ebb4caSwyllys 		if (pkey == NULL) {
186899ebb4caSwyllys 			free(key->keylabel);
186999ebb4caSwyllys 			key->keylabel = NULL;
187099ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
187199ebb4caSwyllys 		}
187299ebb4caSwyllys 		EVP_PKEY_free(pkey);
187399ebb4caSwyllys 
187499ebb4caSwyllys 		if (destroy) {
187599ebb4caSwyllys 			if (unlink(key->keylabel) != 0) {
187699ebb4caSwyllys 				KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
187799ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
187899ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
187999ebb4caSwyllys 			}
188099ebb4caSwyllys 		}
188199ebb4caSwyllys 		if (key->keylabel != NULL) {
188299ebb4caSwyllys 			free(key->keylabel);
188399ebb4caSwyllys 			key->keylabel = NULL;
188499ebb4caSwyllys 		}
188599ebb4caSwyllys 	}
188699ebb4caSwyllys 	return (rv);
188799ebb4caSwyllys }
188899ebb4caSwyllys 
188999ebb4caSwyllys KMF_RETURN
189099ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
189199ebb4caSwyllys {
189299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
189399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
189499ebb4caSwyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
189599ebb4caSwyllys 
189699ebb4caSwyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
189799ebb4caSwyllys 	if (strlen(str)) {
189899ebb4caSwyllys 		*msgstr = (char *)strdup(str);
189999ebb4caSwyllys 		if ((*msgstr) == NULL)
190099ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
190199ebb4caSwyllys 	} else {
190299ebb4caSwyllys 		*msgstr = NULL;
190399ebb4caSwyllys 	}
190499ebb4caSwyllys 
190599ebb4caSwyllys 	return (ret);
190699ebb4caSwyllys }
190799ebb4caSwyllys 
190899ebb4caSwyllys static int
190999ebb4caSwyllys ext2NID(int kmfext)
191099ebb4caSwyllys {
191199ebb4caSwyllys 	switch (kmfext) {
191299ebb4caSwyllys 		case KMF_X509_EXT_KEY_USAGE:
191399ebb4caSwyllys 			return (NID_key_usage);
191499ebb4caSwyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
191599ebb4caSwyllys 			return (NID_private_key_usage_period);
191699ebb4caSwyllys 		case KMF_X509_EXT_CERT_POLICIES:
191799ebb4caSwyllys 			return (NID_certificate_policies);
191899ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
191999ebb4caSwyllys 			return (NID_subject_alt_name);
192099ebb4caSwyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
192199ebb4caSwyllys 			return (NID_issuer_alt_name);
192299ebb4caSwyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
192399ebb4caSwyllys 			return (NID_basic_constraints);
192499ebb4caSwyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
192599ebb4caSwyllys 			return (NID_ext_key_usage);
192699ebb4caSwyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
192799ebb4caSwyllys 			return (NID_authority_key_identifier);
192899ebb4caSwyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
192999ebb4caSwyllys 			return (NID_crl_distribution_points);
193099ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
193199ebb4caSwyllys 			return (NID_subject_key_identifier);
193299ebb4caSwyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
193399ebb4caSwyllys 			return (OBJ_sn2nid("policyMappings"));
193499ebb4caSwyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
193599ebb4caSwyllys 			return (OBJ_sn2nid("nameConstraints"));
193699ebb4caSwyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
193799ebb4caSwyllys 			return (OBJ_sn2nid("policyConstraints"));
193899ebb4caSwyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
193999ebb4caSwyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
194099ebb4caSwyllys 		case KMF_X509_EXT_FRESHEST_CRL:
194199ebb4caSwyllys 			return (OBJ_sn2nid("freshestCRL"));
194299ebb4caSwyllys 		default:
194399ebb4caSwyllys 			return (NID_undef);
194499ebb4caSwyllys 	}
194599ebb4caSwyllys }
194699ebb4caSwyllys 
194799ebb4caSwyllys KMF_RETURN
194899ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
194999ebb4caSwyllys 	KMF_PRINTABLE_ITEM flag, char *resultStr)
195099ebb4caSwyllys {
195199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
195299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
195399ebb4caSwyllys 	X509 *xcert = NULL;
195499ebb4caSwyllys 	unsigned char *outbuf = NULL;
195599ebb4caSwyllys 	unsigned char *outbuf_p;
195699ebb4caSwyllys 	char *tmpstr = NULL;
195799ebb4caSwyllys 	int j;
195899ebb4caSwyllys 	int ext_index, nid, len;
195999ebb4caSwyllys 	BIO *mem = NULL;
196099ebb4caSwyllys 	STACK *emlst = NULL;
196199ebb4caSwyllys 	X509_EXTENSION *ex;
196299ebb4caSwyllys 	X509_CINF *ci;
196399ebb4caSwyllys 
196499ebb4caSwyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
196599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
196699ebb4caSwyllys 	}
196799ebb4caSwyllys 
196899ebb4caSwyllys 	/* copy cert data to outbuf */
196999ebb4caSwyllys 	outbuf = malloc(pcert->Length);
197099ebb4caSwyllys 	if (outbuf == NULL) {
197199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
197299ebb4caSwyllys 	}
197399ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
197499ebb4caSwyllys 
197599ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
197699ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
197799ebb4caSwyllys 	if (xcert == NULL) {
197899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
197999ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
198099ebb4caSwyllys 		goto out;
198199ebb4caSwyllys 	}
198299ebb4caSwyllys 
198399ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
198499ebb4caSwyllys 	if (mem == NULL) {
198599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
198699ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
198799ebb4caSwyllys 		goto out;
198899ebb4caSwyllys 	}
198999ebb4caSwyllys 
199099ebb4caSwyllys 	switch (flag) {
199199ebb4caSwyllys 	case KMF_CERT_ISSUER:
199299ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
199399ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
199499ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
199599ebb4caSwyllys 		break;
199699ebb4caSwyllys 
199799ebb4caSwyllys 	case KMF_CERT_SUBJECT:
199899ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
199999ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
200099ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
200199ebb4caSwyllys 		break;
200299ebb4caSwyllys 
200399ebb4caSwyllys 	case KMF_CERT_VERSION:
200499ebb4caSwyllys 		tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version);
200599ebb4caSwyllys 		(void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN);
200699ebb4caSwyllys 		OPENSSL_free(tmpstr);
200799ebb4caSwyllys 		len = strlen(resultStr);
200899ebb4caSwyllys 		break;
200999ebb4caSwyllys 
201099ebb4caSwyllys 	case KMF_CERT_SERIALNUM:
201199ebb4caSwyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
201299ebb4caSwyllys 			(void) strcpy(resultStr, "0x");
201399ebb4caSwyllys 			len = BIO_gets(mem, &resultStr[2],
201499ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN - 2);
201599ebb4caSwyllys 		}
201699ebb4caSwyllys 		break;
201799ebb4caSwyllys 
201899ebb4caSwyllys 	case KMF_CERT_NOTBEFORE:
201999ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notBefore(xcert));
202099ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
202199ebb4caSwyllys 		break;
202299ebb4caSwyllys 
202399ebb4caSwyllys 	case KMF_CERT_NOTAFTER:
202499ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notAfter(xcert));
202599ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
202699ebb4caSwyllys 		break;
202799ebb4caSwyllys 
202899ebb4caSwyllys 	case KMF_CERT_PUBKEY_DATA:
202999ebb4caSwyllys 		{
203099ebb4caSwyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
203199ebb4caSwyllys 			if (pkey == NULL) {
203299ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
203399ebb4caSwyllys 				ret = KMF_ERR_ENCODING;
203499ebb4caSwyllys 				goto out;
203599ebb4caSwyllys 			}
203699ebb4caSwyllys 
203799ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
203899ebb4caSwyllys 				(void) BIO_printf(mem,
203999ebb4caSwyllys 				    "RSA Public Key: (%d bit)\n",
204099ebb4caSwyllys 				    BN_num_bits(pkey->pkey.rsa->n));
204199ebb4caSwyllys 				(void) RSA_print(mem, pkey->pkey.rsa, 0);
204299ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
204399ebb4caSwyllys 				(void) BIO_printf(mem,
204499ebb4caSwyllys 				    "%12sDSA Public Key:\n", "");
204599ebb4caSwyllys 				(void) DSA_print(mem, pkey->pkey.dsa, 0);
204699ebb4caSwyllys 			} else {
204799ebb4caSwyllys 				(void) BIO_printf(mem,
204899ebb4caSwyllys 				    "%12sUnknown Public Key:\n", "");
204999ebb4caSwyllys 			}
205099ebb4caSwyllys 			(void) BIO_printf(mem, "\n");
205199ebb4caSwyllys 			EVP_PKEY_free(pkey);
205299ebb4caSwyllys 		}
205399ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
205499ebb4caSwyllys 		break;
205599ebb4caSwyllys 	case KMF_CERT_SIGNATURE_ALG:
205699ebb4caSwyllys 	case KMF_CERT_PUBKEY_ALG:
205799ebb4caSwyllys 		if (flag == KMF_CERT_SIGNATURE_ALG) {
205899ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
205999ebb4caSwyllys 			    xcert->sig_alg->algorithm);
206099ebb4caSwyllys 		} else {
206199ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
206299ebb4caSwyllys 			    xcert->cert_info->key->algor->algorithm);
206399ebb4caSwyllys 		}
206499ebb4caSwyllys 
206599ebb4caSwyllys 		if (len > 0) {
206699ebb4caSwyllys 			len = BIO_read(mem, resultStr,
206799ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN);
206899ebb4caSwyllys 		}
206999ebb4caSwyllys 		break;
207099ebb4caSwyllys 
207199ebb4caSwyllys 	case KMF_CERT_EMAIL:
207299ebb4caSwyllys 		emlst = X509_get1_email(xcert);
207399ebb4caSwyllys 		for (j = 0; j < sk_num(emlst); j++)
207499ebb4caSwyllys 			(void) BIO_printf(mem, "%s\n", sk_value(emlst, j));
207599ebb4caSwyllys 
207699ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
207799ebb4caSwyllys 		X509_email_free(emlst);
207899ebb4caSwyllys 		break;
207999ebb4caSwyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
208099ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
208199ebb4caSwyllys 	case KMF_X509_EXT_KEY_USAGE:
208299ebb4caSwyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
208399ebb4caSwyllys 	case KMF_X509_EXT_CERT_POLICIES:
208499ebb4caSwyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
208599ebb4caSwyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
208699ebb4caSwyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
208799ebb4caSwyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
208899ebb4caSwyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
208999ebb4caSwyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
209099ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
209199ebb4caSwyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
209299ebb4caSwyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
209399ebb4caSwyllys 	case KMF_X509_EXT_FRESHEST_CRL:
209499ebb4caSwyllys 		nid = ext2NID(flag);
209599ebb4caSwyllys 		if (nid == NID_undef) {
209699ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
209799ebb4caSwyllys 			goto out;
209899ebb4caSwyllys 		}
209999ebb4caSwyllys 		ci = xcert->cert_info;
210099ebb4caSwyllys 
210199ebb4caSwyllys 		ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1);
210299ebb4caSwyllys 		if (ext_index == -1) {
210399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
210499ebb4caSwyllys 
210599ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
210699ebb4caSwyllys 			goto out;
210799ebb4caSwyllys 		}
210899ebb4caSwyllys 		ex = X509v3_get_ext(ci->extensions, ext_index);
210999ebb4caSwyllys 
211099ebb4caSwyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
211199ebb4caSwyllys 
211299ebb4caSwyllys 		if (BIO_printf(mem, ": %s\n",
2113*30a5e8faSwyllys 		    X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
211499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
211599ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
211699ebb4caSwyllys 			goto out;
211799ebb4caSwyllys 		}
211899ebb4caSwyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
211999ebb4caSwyllys 			(void) BIO_printf(mem, "%*s", 4, "");
212099ebb4caSwyllys 			(void) M_ASN1_OCTET_STRING_print(mem, ex->value);
212199ebb4caSwyllys 		}
212299ebb4caSwyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
212399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
212499ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
212599ebb4caSwyllys 			goto out;
212699ebb4caSwyllys 		}
212799ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
212899ebb4caSwyllys 	}
212999ebb4caSwyllys 	if (len <= 0) {
213099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
213199ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
213299ebb4caSwyllys 	}
213399ebb4caSwyllys 
213499ebb4caSwyllys out:
213599ebb4caSwyllys 	if (outbuf != NULL) {
213699ebb4caSwyllys 		free(outbuf);
213799ebb4caSwyllys 	}
213899ebb4caSwyllys 
213999ebb4caSwyllys 	if (xcert != NULL) {
214099ebb4caSwyllys 		X509_free(xcert);
214199ebb4caSwyllys 	}
214299ebb4caSwyllys 
214399ebb4caSwyllys 	if (mem != NULL) {
214499ebb4caSwyllys 		(void) BIO_free(mem);
214599ebb4caSwyllys 	}
214699ebb4caSwyllys 
214799ebb4caSwyllys 	return (ret);
214899ebb4caSwyllys }
2149*30a5e8faSwyllys 
215099ebb4caSwyllys KMF_RETURN
215199ebb4caSwyllys /*ARGSUSED*/
2152*30a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
2153*30a5e8faSwyllys     KMF_ATTRIBUTE *attrlist)
215499ebb4caSwyllys {
215599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
2156*30a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
2157*30a5e8faSwyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
2158*30a5e8faSwyllys 	KMF_KEY_HANDLE *key = NULL;
2159*30a5e8faSwyllys 	uint32_t numkeys = 1; /* 1 key only */
2160*30a5e8faSwyllys 	char *dirpath = NULL;
2161*30a5e8faSwyllys 	char *keyfile = NULL;
2162*30a5e8faSwyllys 	KMF_ATTRIBUTE new_attrlist[16];
2163*30a5e8faSwyllys 	int i = 0;
216499ebb4caSwyllys 
216599ebb4caSwyllys 	/*
216699ebb4caSwyllys 	 * This is really just a FindKey operation, reuse the
216799ebb4caSwyllys 	 * FindKey function.
216899ebb4caSwyllys 	 */
2169*30a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
2170*30a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
2171*30a5e8faSwyllys 	i++;
217299ebb4caSwyllys 
2173*30a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
2174*30a5e8faSwyllys 	    KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
2175*30a5e8faSwyllys 	i++;
217699ebb4caSwyllys 
2177*30a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
2178*30a5e8faSwyllys 	    KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
2179*30a5e8faSwyllys 	i++;
2180*30a5e8faSwyllys 
2181*30a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2182*30a5e8faSwyllys 	if (key == NULL) {
2183*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2184*30a5e8faSwyllys 	} else {
2185*30a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
2186*30a5e8faSwyllys 		    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
2187*30a5e8faSwyllys 		i++;
2188*30a5e8faSwyllys 	}
2189*30a5e8faSwyllys 
2190*30a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
2191*30a5e8faSwyllys 	if (dirpath != NULL) {
2192*30a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
2193*30a5e8faSwyllys 		    KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
2194*30a5e8faSwyllys 		i++;
2195*30a5e8faSwyllys 	}
2196*30a5e8faSwyllys 
2197*30a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
2198*30a5e8faSwyllys 	if (keyfile == NULL)
2199*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2200*30a5e8faSwyllys 	else {
2201*30a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
2202*30a5e8faSwyllys 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
2203*30a5e8faSwyllys 		i++;
2204*30a5e8faSwyllys 	}
2205*30a5e8faSwyllys 
2206*30a5e8faSwyllys 	rv = OpenSSL_FindKey(handle, i, new_attrlist);
220799ebb4caSwyllys 	return (rv);
220899ebb4caSwyllys }
220999ebb4caSwyllys 
221099ebb4caSwyllys KMF_RETURN
221199ebb4caSwyllys /*ARGSUSED*/
221299ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
221399ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
221499ebb4caSwyllys 	KMF_DATA *output)
221599ebb4caSwyllys {
221699ebb4caSwyllys 	KMF_RETURN		ret = KMF_OK;
221799ebb4caSwyllys 	RSA *rsa = NULL;
221899ebb4caSwyllys 	unsigned int in_len = 0, out_len = 0;
221999ebb4caSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
222099ebb4caSwyllys 	uint8_t *in_data, *out_data;
222199ebb4caSwyllys 	int i, blocks;
222299ebb4caSwyllys 
222399ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
222499ebb4caSwyllys 	    ciphertext == NULL || output == NULL ||
222599ebb4caSwyllys 	    ciphertext->Data == NULL ||
222699ebb4caSwyllys 	    output->Data == NULL)
222799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
222899ebb4caSwyllys 
222999ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
223099ebb4caSwyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
223199ebb4caSwyllys 		modulus_len = RSA_size(rsa);
223299ebb4caSwyllys 	} else {
223399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
223499ebb4caSwyllys 	}
223599ebb4caSwyllys 
223699ebb4caSwyllys 	blocks = ciphertext->Length/modulus_len;
223799ebb4caSwyllys 	out_data = output->Data;
223899ebb4caSwyllys 	in_data = ciphertext->Data;
223999ebb4caSwyllys 	out_len = modulus_len - 11;
224099ebb4caSwyllys 	in_len = modulus_len;
224199ebb4caSwyllys 
224299ebb4caSwyllys 	for (i = 0; i < blocks; i++) {
224399ebb4caSwyllys 		out_len  = RSA_private_decrypt(in_len,
224499ebb4caSwyllys 		    in_data, out_data, rsa, RSA_PKCS1_PADDING);
224599ebb4caSwyllys 
224699ebb4caSwyllys 		if (out_len == 0) {
224799ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
224899ebb4caSwyllys 			goto cleanup;
224999ebb4caSwyllys 		}
225099ebb4caSwyllys 
225199ebb4caSwyllys 		out_data += out_len;
225299ebb4caSwyllys 		total_decrypted += out_len;
225399ebb4caSwyllys 		in_data += in_len;
225499ebb4caSwyllys 	}
225599ebb4caSwyllys 
225699ebb4caSwyllys 	output->Length = total_decrypted;
225799ebb4caSwyllys 
225899ebb4caSwyllys cleanup:
225999ebb4caSwyllys 	RSA_free(rsa);
226099ebb4caSwyllys 	if (ret != KMF_OK)
226199ebb4caSwyllys 		output->Length = 0;
226299ebb4caSwyllys 
226399ebb4caSwyllys 	return (ret);
226499ebb4caSwyllys 
226599ebb4caSwyllys }
226699ebb4caSwyllys 
226799ebb4caSwyllys /*
226899ebb4caSwyllys  *  This function will create a certid from issuer_cert and user_cert.
226999ebb4caSwyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
227099ebb4caSwyllys  *  certid memory after use.
227199ebb4caSwyllys  */
227299ebb4caSwyllys static KMF_RETURN
227399ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
227499ebb4caSwyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
227599ebb4caSwyllys {
227699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
227799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
227899ebb4caSwyllys 	X509   *issuer = NULL;
227999ebb4caSwyllys 	X509   *cert = NULL;
228099ebb4caSwyllys 	unsigned char *ptmp;
228199ebb4caSwyllys 
228299ebb4caSwyllys 	if (issuer_cert == NULL || user_cert == NULL) {
228399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
228499ebb4caSwyllys 	}
228599ebb4caSwyllys 
228699ebb4caSwyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
228799ebb4caSwyllys 	ptmp = issuer_cert->Data;
228899ebb4caSwyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
228999ebb4caSwyllys 	    issuer_cert->Length);
229099ebb4caSwyllys 	if (issuer == NULL) {
229199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
229299ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
229399ebb4caSwyllys 		goto end;
229499ebb4caSwyllys 	}
229599ebb4caSwyllys 
229699ebb4caSwyllys 	/* convert the DER-encoded user cert to an internal X509 */
229799ebb4caSwyllys 	ptmp = user_cert->Data;
229899ebb4caSwyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
229999ebb4caSwyllys 	    user_cert->Length);
230099ebb4caSwyllys 	if (cert == NULL) {
230199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
230299ebb4caSwyllys 
230399ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
230499ebb4caSwyllys 		goto end;
230599ebb4caSwyllys 	}
230699ebb4caSwyllys 
230799ebb4caSwyllys 	/* create a CERTID */
230899ebb4caSwyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
230999ebb4caSwyllys 	if (*certid == NULL) {
231099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
231199ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
231299ebb4caSwyllys 		goto end;
231399ebb4caSwyllys 	}
231499ebb4caSwyllys 
231599ebb4caSwyllys end:
231699ebb4caSwyllys 	if (issuer != NULL) {
231799ebb4caSwyllys 		X509_free(issuer);
231899ebb4caSwyllys 	}
231999ebb4caSwyllys 
232099ebb4caSwyllys 	if (cert != NULL) {
232199ebb4caSwyllys 		X509_free(cert);
232299ebb4caSwyllys 	}
232399ebb4caSwyllys 
232499ebb4caSwyllys 	return (ret);
232599ebb4caSwyllys }
232699ebb4caSwyllys 
232799ebb4caSwyllys KMF_RETURN
2328*30a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
2329*30a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
233099ebb4caSwyllys {
233199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
233299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
233399ebb4caSwyllys 	OCSP_CERTID *id = NULL;
233499ebb4caSwyllys 	OCSP_REQUEST *req = NULL;
233599ebb4caSwyllys 	BIO *derbio = NULL;
2336*30a5e8faSwyllys 	char *reqfile;
2337*30a5e8faSwyllys 	KMF_DATA *issuer_cert;
2338*30a5e8faSwyllys 	KMF_DATA *user_cert;
233999ebb4caSwyllys 
2340*30a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
2341*30a5e8faSwyllys 	    attrlist, numattr);
2342*30a5e8faSwyllys 	if (user_cert == NULL)
234399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
234499ebb4caSwyllys 
2345*30a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
2346*30a5e8faSwyllys 	    attrlist, numattr);
2347*30a5e8faSwyllys 	if (issuer_cert == NULL)
2348*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2349*30a5e8faSwyllys 
2350*30a5e8faSwyllys 	reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
2351*30a5e8faSwyllys 	    attrlist, numattr);
2352*30a5e8faSwyllys 	if (reqfile == NULL)
2353*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2354*30a5e8faSwyllys 
2355*30a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
235699ebb4caSwyllys 	if (ret != KMF_OK) {
235799ebb4caSwyllys 		return (ret);
235899ebb4caSwyllys 	}
235999ebb4caSwyllys 
236099ebb4caSwyllys 	/* Create an OCSP request */
236199ebb4caSwyllys 	req = OCSP_REQUEST_new();
236299ebb4caSwyllys 	if (req == NULL) {
236399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
236499ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
236599ebb4caSwyllys 		goto end;
236699ebb4caSwyllys 	}
236799ebb4caSwyllys 
236899ebb4caSwyllys 	if (!OCSP_request_add0_id(req, id)) {
236999ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
237099ebb4caSwyllys 		goto end;
237199ebb4caSwyllys 	}
237299ebb4caSwyllys 
237399ebb4caSwyllys 	/* Write the request to the output file with DER encoding */
237499ebb4caSwyllys 	derbio = BIO_new_file(reqfile, "wb");
237599ebb4caSwyllys 	if (!derbio) {
237699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
237799ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
237899ebb4caSwyllys 		goto end;
237999ebb4caSwyllys 	}
238099ebb4caSwyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
238199ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
238299ebb4caSwyllys 	}
238399ebb4caSwyllys 
238499ebb4caSwyllys end:
238599ebb4caSwyllys 	/*
238699ebb4caSwyllys 	 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
238799ebb4caSwyllys 	 * will deallocate certid's space also.
238899ebb4caSwyllys 	 */
238999ebb4caSwyllys 	if (req != NULL) {
239099ebb4caSwyllys 		OCSP_REQUEST_free(req);
239199ebb4caSwyllys 	}
239299ebb4caSwyllys 
239399ebb4caSwyllys 	if (derbio != NULL) {
239499ebb4caSwyllys 		(void) BIO_free(derbio);
239599ebb4caSwyllys 	}
239699ebb4caSwyllys 
239799ebb4caSwyllys 	return (ret);
239899ebb4caSwyllys }
239999ebb4caSwyllys 
240099ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */
240199ebb4caSwyllys static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
240299ebb4caSwyllys {
240399ebb4caSwyllys 	int i;
240499ebb4caSwyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
240599ebb4caSwyllys 
240699ebb4caSwyllys 	/* Easy if lookup by name */
240799ebb4caSwyllys 	if (id->type == V_OCSP_RESPID_NAME)
240899ebb4caSwyllys 		return (X509_find_by_subject(certs, id->value.byName));
240999ebb4caSwyllys 
241099ebb4caSwyllys 	/* Lookup by key hash */
241199ebb4caSwyllys 
241299ebb4caSwyllys 	/* If key hash isn't SHA1 length then forget it */
241399ebb4caSwyllys 	if (id->value.byKey->length != SHA_DIGEST_LENGTH)
241499ebb4caSwyllys 		return (NULL);
241599ebb4caSwyllys 
241699ebb4caSwyllys 	keyhash = id->value.byKey->data;
241799ebb4caSwyllys 	/* Calculate hash of each key and compare */
241899ebb4caSwyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
241999ebb4caSwyllys 		/*LINTED*/
242099ebb4caSwyllys 		X509 *x = sk_X509_value(certs, i);
242199ebb4caSwyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
242299ebb4caSwyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
242399ebb4caSwyllys 			return (x);
242499ebb4caSwyllys 	}
242599ebb4caSwyllys 	return (NULL);
242699ebb4caSwyllys }
242799ebb4caSwyllys 
242899ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */
242999ebb4caSwyllys /*ARGSUSED*/
243099ebb4caSwyllys static int
243199ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
243299ebb4caSwyllys     X509_STORE *st, unsigned long flags)
243399ebb4caSwyllys {
243499ebb4caSwyllys 	X509 *signer;
243599ebb4caSwyllys 	OCSP_RESPID *rid = bs->tbsResponseData->responderId;
243699ebb4caSwyllys 	if ((signer = ocsp_find_signer_sk(certs, rid)))	{
243799ebb4caSwyllys 		*psigner = signer;
243899ebb4caSwyllys 		return (2);
243999ebb4caSwyllys 	}
244099ebb4caSwyllys 	if (!(flags & OCSP_NOINTERN) &&
244199ebb4caSwyllys 	    (signer = ocsp_find_signer_sk(bs->certs, rid))) {
244299ebb4caSwyllys 		*psigner = signer;
244399ebb4caSwyllys 		return (1);
244499ebb4caSwyllys 	}
244599ebb4caSwyllys 	/* Maybe lookup from store if by subject name */
244699ebb4caSwyllys 
244799ebb4caSwyllys 	*psigner = NULL;
244899ebb4caSwyllys 	return (0);
244999ebb4caSwyllys }
245099ebb4caSwyllys 
245199ebb4caSwyllys /*
245299ebb4caSwyllys  * This function will verify the signature of a basic response, using
245399ebb4caSwyllys  * the public key from the OCSP responder certificate.
245499ebb4caSwyllys  */
245599ebb4caSwyllys static KMF_RETURN
245699ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
245799ebb4caSwyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
245899ebb4caSwyllys {
245999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
246099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
246199ebb4caSwyllys 	STACK_OF(X509) *cert_stack = NULL;
246299ebb4caSwyllys 	X509 *signer = NULL;
246399ebb4caSwyllys 	X509 *issuer = NULL;
246499ebb4caSwyllys 	EVP_PKEY *skey = NULL;
246599ebb4caSwyllys 	unsigned char *ptmp;
246699ebb4caSwyllys 
246799ebb4caSwyllys 
246899ebb4caSwyllys 	if (bs == NULL || issuer_cert == NULL)
246999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
247099ebb4caSwyllys 
247199ebb4caSwyllys 	/*
247299ebb4caSwyllys 	 * Find the certificate that signed the basic response.
247399ebb4caSwyllys 	 *
247499ebb4caSwyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
247599ebb4caSwyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
247699ebb4caSwyllys 	 * If we still do not find a signer, we will look for it from the
247799ebb4caSwyllys 	 * certificate list came with the response file.
247899ebb4caSwyllys 	 */
247999ebb4caSwyllys 	if (signer_cert != NULL) {
248099ebb4caSwyllys 		ptmp = signer_cert->Data;
248199ebb4caSwyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
248299ebb4caSwyllys 		    signer_cert->Length);
248399ebb4caSwyllys 		if (signer == NULL) {
248499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
248599ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
248699ebb4caSwyllys 			goto end;
248799ebb4caSwyllys 		}
248899ebb4caSwyllys 	} else {
248999ebb4caSwyllys 		/*
249099ebb4caSwyllys 		 * Convert the issuer cert into X509 and push it into a
249199ebb4caSwyllys 		 * stack to be used by ocsp_find_signer().
249299ebb4caSwyllys 		 */
249399ebb4caSwyllys 		ptmp = issuer_cert->Data;
249499ebb4caSwyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
249599ebb4caSwyllys 		    issuer_cert->Length);
249699ebb4caSwyllys 		if (issuer == NULL) {
249799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
249899ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
249999ebb4caSwyllys 			goto end;
250099ebb4caSwyllys 		}
250199ebb4caSwyllys 
250299ebb4caSwyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
250399ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
250499ebb4caSwyllys 			goto end;
250599ebb4caSwyllys 		}
250699ebb4caSwyllys 
250799ebb4caSwyllys 		if (sk_X509_push(cert_stack, issuer) == NULL) {
250899ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
250999ebb4caSwyllys 			goto end;
251099ebb4caSwyllys 		}
251199ebb4caSwyllys 
251299ebb4caSwyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
251399ebb4caSwyllys 		if (!ret) {
251499ebb4caSwyllys 			/* can not find the signer */
251599ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
251699ebb4caSwyllys 			goto end;
251799ebb4caSwyllys 		}
251899ebb4caSwyllys 	}
251999ebb4caSwyllys 
252099ebb4caSwyllys 	/* Verify the signature of the response */
252199ebb4caSwyllys 	skey = X509_get_pubkey(signer);
252299ebb4caSwyllys 	if (skey == NULL) {
252399ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
252499ebb4caSwyllys 		goto end;
252599ebb4caSwyllys 	}
252699ebb4caSwyllys 
252799ebb4caSwyllys 	ret = OCSP_BASICRESP_verify(bs, skey, 0);
252899ebb4caSwyllys 	if (ret == 0) {
252999ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
253099ebb4caSwyllys 		goto end;
253199ebb4caSwyllys 	}
253299ebb4caSwyllys 
253399ebb4caSwyllys end:
253499ebb4caSwyllys 	if (issuer != NULL) {
253599ebb4caSwyllys 		X509_free(issuer);
253699ebb4caSwyllys 	}
253799ebb4caSwyllys 
253899ebb4caSwyllys 	if (signer != NULL) {
253999ebb4caSwyllys 		X509_free(signer);
254099ebb4caSwyllys 	}
254199ebb4caSwyllys 
254299ebb4caSwyllys 	if (skey != NULL) {
254399ebb4caSwyllys 		EVP_PKEY_free(skey);
254499ebb4caSwyllys 	}
254599ebb4caSwyllys 
254699ebb4caSwyllys 	if (cert_stack != NULL) {
254799ebb4caSwyllys 		sk_X509_free(cert_stack);
254899ebb4caSwyllys 	}
254999ebb4caSwyllys 
255099ebb4caSwyllys 	return (ret);
255199ebb4caSwyllys }
255299ebb4caSwyllys 
255399ebb4caSwyllys 
255499ebb4caSwyllys 
255599ebb4caSwyllys KMF_RETURN
255699ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
2557*30a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
255899ebb4caSwyllys {
255999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
256099ebb4caSwyllys 	BIO *derbio = NULL;
256199ebb4caSwyllys 	OCSP_RESPONSE *resp = NULL;
256299ebb4caSwyllys 	OCSP_BASICRESP *bs = NULL;
256399ebb4caSwyllys 	OCSP_CERTID *id = NULL;
256499ebb4caSwyllys 	OCSP_SINGLERESP *single = NULL;
256599ebb4caSwyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
256699ebb4caSwyllys 	int index, status, reason;
2567*30a5e8faSwyllys 	KMF_DATA *issuer_cert;
2568*30a5e8faSwyllys 	KMF_DATA *user_cert;
2569*30a5e8faSwyllys 	KMF_DATA *signer_cert;
2570*30a5e8faSwyllys 	KMF_DATA *response;
2571*30a5e8faSwyllys 	int *response_reason, *response_status, *cert_status;
2572*30a5e8faSwyllys 	boolean_t ignore_response_sign = B_FALSE;	/* default is FALSE */
2573*30a5e8faSwyllys 	uint32_t response_lifetime;
257499ebb4caSwyllys 
2575*30a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
2576*30a5e8faSwyllys 	    attrlist, numattr);
2577*30a5e8faSwyllys 	if (issuer_cert == NULL)
257899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
257999ebb4caSwyllys 
2580*30a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
2581*30a5e8faSwyllys 	    attrlist, numattr);
2582*30a5e8faSwyllys 	if (user_cert == NULL)
258399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2584*30a5e8faSwyllys 
2585*30a5e8faSwyllys 	response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
2586*30a5e8faSwyllys 	    attrlist, numattr);
2587*30a5e8faSwyllys 	if (response == NULL)
2588*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2589*30a5e8faSwyllys 
2590*30a5e8faSwyllys 	response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
2591*30a5e8faSwyllys 	    attrlist, numattr);
2592*30a5e8faSwyllys 	if (response_status == NULL)
2593*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2594*30a5e8faSwyllys 
2595*30a5e8faSwyllys 	response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
2596*30a5e8faSwyllys 	    attrlist, numattr);
2597*30a5e8faSwyllys 	if (response_reason == NULL)
2598*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2599*30a5e8faSwyllys 
2600*30a5e8faSwyllys 	cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
2601*30a5e8faSwyllys 	    attrlist, numattr);
2602*30a5e8faSwyllys 	if (cert_status == NULL)
2603*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
260499ebb4caSwyllys 
260599ebb4caSwyllys 	/* Read in the response */
2606*30a5e8faSwyllys 	derbio = BIO_new_mem_buf(response->Data, response->Length);
260799ebb4caSwyllys 	if (!derbio) {
260899ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
260999ebb4caSwyllys 		return (ret);
261099ebb4caSwyllys 	}
261199ebb4caSwyllys 
261299ebb4caSwyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
261399ebb4caSwyllys 	if (resp == NULL) {
261499ebb4caSwyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
261599ebb4caSwyllys 		goto end;
261699ebb4caSwyllys 	}
261799ebb4caSwyllys 
261899ebb4caSwyllys 	/* Check the response status */
261999ebb4caSwyllys 	status = OCSP_response_status(resp);
2620*30a5e8faSwyllys 	*response_status = status;
262199ebb4caSwyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
262299ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
262399ebb4caSwyllys 		goto end;
262499ebb4caSwyllys 	}
262599ebb4caSwyllys 
262699ebb4caSwyllys #ifdef DEBUG
262799ebb4caSwyllys 	printf("Successfully checked the response file status.\n");
262899ebb4caSwyllys #endif /* DEBUG */
262999ebb4caSwyllys 
263099ebb4caSwyllys 	/* Extract basic response */
263199ebb4caSwyllys 	bs = OCSP_response_get1_basic(resp);
263299ebb4caSwyllys 	if (bs == NULL) {
263399ebb4caSwyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
263499ebb4caSwyllys 		goto end;
263599ebb4caSwyllys 	}
263699ebb4caSwyllys 
263799ebb4caSwyllys #ifdef DEBUG
263899ebb4caSwyllys 	printf("Successfully retrieved the basic response.\n");
263999ebb4caSwyllys #endif /* DEBUG */
264099ebb4caSwyllys 
264199ebb4caSwyllys 	/* Check the basic response signature if required */
2642*30a5e8faSwyllys 	ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
2643*30a5e8faSwyllys 	    (void *)&ignore_response_sign, NULL);
2644*30a5e8faSwyllys 	if (ret != KMF_OK)
2645*30a5e8faSwyllys 		ret = KMF_OK;
2646*30a5e8faSwyllys 
2647*30a5e8faSwyllys 	signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
2648*30a5e8faSwyllys 	    attrlist, numattr);
2649*30a5e8faSwyllys 
2650*30a5e8faSwyllys 	if (ignore_response_sign == B_FALSE) {
265199ebb4caSwyllys 		ret = check_response_signature(handle, bs,
2652*30a5e8faSwyllys 		    signer_cert, issuer_cert);
265399ebb4caSwyllys 		if (ret != KMF_OK)
265499ebb4caSwyllys 			goto end;
265599ebb4caSwyllys 	}
265699ebb4caSwyllys 
265799ebb4caSwyllys #ifdef DEBUG
265899ebb4caSwyllys 	printf("Successfully verified the response signature.\n");
265999ebb4caSwyllys #endif /* DEBUG */
266099ebb4caSwyllys 
266199ebb4caSwyllys 	/* Create a certid for the certificate in question */
2662*30a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
266399ebb4caSwyllys 	if (ret != KMF_OK) {
266499ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
266599ebb4caSwyllys 		goto end;
266699ebb4caSwyllys 	}
266799ebb4caSwyllys 
266899ebb4caSwyllys #ifdef DEBUG
266999ebb4caSwyllys 	printf("successfully created a certid for the cert.\n");
267099ebb4caSwyllys #endif /* DEBUG */
267199ebb4caSwyllys 
267299ebb4caSwyllys 	/* Find the index of the single response for the certid */
267399ebb4caSwyllys 	index = OCSP_resp_find(bs, id, -1);
267499ebb4caSwyllys 	if (index < 0) {
267599ebb4caSwyllys 		/* cound not find this certificate in the response */
267699ebb4caSwyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
267799ebb4caSwyllys 		goto end;
267899ebb4caSwyllys 	}
267999ebb4caSwyllys 
268099ebb4caSwyllys #ifdef DEBUG
268199ebb4caSwyllys 	printf("Successfully found the single response index for the cert.\n");
268299ebb4caSwyllys #endif /* DEBUG */
268399ebb4caSwyllys 
268499ebb4caSwyllys 	/* Retrieve the single response and get the cert status */
268599ebb4caSwyllys 	single = OCSP_resp_get0(bs, index);
268699ebb4caSwyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
268799ebb4caSwyllys 	    &nextupd);
268899ebb4caSwyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
2689*30a5e8faSwyllys 		*cert_status = OCSP_GOOD;
269099ebb4caSwyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
2691*30a5e8faSwyllys 		*cert_status = OCSP_UNKNOWN;
269299ebb4caSwyllys 	} else { /* revoked */
2693*30a5e8faSwyllys 		*cert_status = OCSP_REVOKED;
2694*30a5e8faSwyllys 		*response_reason = reason;
269599ebb4caSwyllys 	}
269699ebb4caSwyllys 	ret = KMF_OK;
269799ebb4caSwyllys 
2698*30a5e8faSwyllys 	/* resp. time is optional, so we don't care about the return code. */
2699*30a5e8faSwyllys 	(void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
2700*30a5e8faSwyllys 	    (void *)&response_lifetime, NULL);
2701*30a5e8faSwyllys 
270299ebb4caSwyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
2703*30a5e8faSwyllys 	    response_lifetime)) {
270499ebb4caSwyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
270599ebb4caSwyllys 		goto end;
270699ebb4caSwyllys 	}
270799ebb4caSwyllys 
270899ebb4caSwyllys #ifdef DEBUG
270999ebb4caSwyllys 	printf("Successfully verify the time.\n");
271099ebb4caSwyllys #endif /* DEBUG */
271199ebb4caSwyllys 
271299ebb4caSwyllys end:
271399ebb4caSwyllys 	if (derbio != NULL)
271499ebb4caSwyllys 		(void) BIO_free(derbio);
271599ebb4caSwyllys 
271699ebb4caSwyllys 	if (resp != NULL)
271799ebb4caSwyllys 		OCSP_RESPONSE_free(resp);
271899ebb4caSwyllys 
271999ebb4caSwyllys 	if (bs != NULL)
272099ebb4caSwyllys 		OCSP_BASICRESP_free(bs);
272199ebb4caSwyllys 
272299ebb4caSwyllys 	if (id != NULL)
272399ebb4caSwyllys 		OCSP_CERTID_free(id);
272499ebb4caSwyllys 
272599ebb4caSwyllys 	return (ret);
272699ebb4caSwyllys }
272799ebb4caSwyllys 
272899ebb4caSwyllys static KMF_RETURN
272999ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path,
273099ebb4caSwyllys 	KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
273199ebb4caSwyllys {
273299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
2733*30a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
273499ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
273599ebb4caSwyllys 
273699ebb4caSwyllys 	if (keyclass == KMF_ASYM_PRI ||
273799ebb4caSwyllys 	    keyclass == KMF_ASYM_PUB) {
273899ebb4caSwyllys 		pkey = openssl_load_key(handle, path);
273999ebb4caSwyllys 		if (pkey == NULL) {
274099ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
274199ebb4caSwyllys 		}
274299ebb4caSwyllys 		if (key != NULL) {
274399ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA)
274499ebb4caSwyllys 				key->keyalg = KMF_RSA;
274599ebb4caSwyllys 			else if (pkey->type == EVP_PKEY_DSA)
274699ebb4caSwyllys 				key->keyalg = KMF_DSA;
274799ebb4caSwyllys 
274899ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
274999ebb4caSwyllys 			key->keyclass = keyclass;
275099ebb4caSwyllys 			key->keyp = (void *)pkey;
275199ebb4caSwyllys 			key->israw = FALSE;
275299ebb4caSwyllys 			key->keylabel = path;
275399ebb4caSwyllys 		} else {
275499ebb4caSwyllys 			EVP_PKEY_free(pkey);
275599ebb4caSwyllys 			pkey = NULL;
275699ebb4caSwyllys 		}
275799ebb4caSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
275899ebb4caSwyllys 		KMF_ENCODE_FORMAT fmt;
275999ebb4caSwyllys 		/*
276099ebb4caSwyllys 		 * If the file is a recognized format,
276199ebb4caSwyllys 		 * then it is NOT a symmetric key.
276299ebb4caSwyllys 		 */
2763*30a5e8faSwyllys 		rv = kmf_get_file_format(path, &fmt);
276499ebb4caSwyllys 		if (rv == KMF_OK || fmt != 0) {
276599ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
276699ebb4caSwyllys 		} else if (rv == KMF_ERR_ENCODING) {
276799ebb4caSwyllys 			/*
276899ebb4caSwyllys 			 * If we don't know the encoding,
276999ebb4caSwyllys 			 * it is probably  a symmetric key.
277099ebb4caSwyllys 			 */
277199ebb4caSwyllys 			rv = KMF_OK;
2772*30a5e8faSwyllys 		} else if (rv == KMF_ERR_OPEN_FILE) {
2773*30a5e8faSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
277499ebb4caSwyllys 		}
277599ebb4caSwyllys 
277699ebb4caSwyllys 		if (key != NULL) {
277799ebb4caSwyllys 			KMF_DATA keyvalue;
277899ebb4caSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
277999ebb4caSwyllys 			if (rkey == NULL) {
278099ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
278199ebb4caSwyllys 				goto out;
278299ebb4caSwyllys 			}
278399ebb4caSwyllys 
278499ebb4caSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
2785*30a5e8faSwyllys 			rv = kmf_read_input_file(handle, path, &keyvalue);
278699ebb4caSwyllys 			if (rv != KMF_OK)
278799ebb4caSwyllys 				goto out;
278899ebb4caSwyllys 
278999ebb4caSwyllys 			rkey->keydata.len = keyvalue.Length;
279099ebb4caSwyllys 			rkey->keydata.val = keyvalue.Data;
279199ebb4caSwyllys 
279299ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
279399ebb4caSwyllys 			key->keyclass = keyclass;
279499ebb4caSwyllys 			key->israw = TRUE;
279599ebb4caSwyllys 			key->keylabel = path;
279699ebb4caSwyllys 			key->keyp = (void *)rkey;
279799ebb4caSwyllys 		}
279899ebb4caSwyllys 	}
279999ebb4caSwyllys out:
280099ebb4caSwyllys 	if (rv != KMF_OK) {
280199ebb4caSwyllys 		if (rkey != NULL) {
2802*30a5e8faSwyllys 			kmf_free_raw_sym_key(rkey);
280399ebb4caSwyllys 		}
280499ebb4caSwyllys 		if (pkey != NULL)
280599ebb4caSwyllys 			EVP_PKEY_free(pkey);
280699ebb4caSwyllys 
280799ebb4caSwyllys 		if (key != NULL) {
280899ebb4caSwyllys 			key->keyalg = KMF_KEYALG_NONE;
280999ebb4caSwyllys 			key->keyclass = KMF_KEYCLASS_NONE;
281099ebb4caSwyllys 			key->keyp = NULL;
281199ebb4caSwyllys 		}
281299ebb4caSwyllys 	}
281399ebb4caSwyllys 
281499ebb4caSwyllys 	return (rv);
281599ebb4caSwyllys }
281699ebb4caSwyllys 
281799ebb4caSwyllys KMF_RETURN
2818*30a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle,
2819*30a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
282099ebb4caSwyllys {
282199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
282299ebb4caSwyllys 	char *fullpath = NULL;
2823f482c776Swyllys 	uint32_t maxkeys;
2824*30a5e8faSwyllys 	KMF_KEY_HANDLE *key;
2825*30a5e8faSwyllys 	uint32_t *numkeys;
2826*30a5e8faSwyllys 	KMF_KEY_CLASS keyclass;
2827*30a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
2828*30a5e8faSwyllys 	char *dirpath;
2829*30a5e8faSwyllys 	char *keyfile;
283099ebb4caSwyllys 
2831*30a5e8faSwyllys 	if (handle == NULL)
283299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
283399ebb4caSwyllys 
2834*30a5e8faSwyllys 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
2835*30a5e8faSwyllys 	if (numkeys == NULL)
2836*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2837*30a5e8faSwyllys 
2838*30a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
2839*30a5e8faSwyllys 	    (void *)&keyclass, NULL);
2840*30a5e8faSwyllys 	if (rv != KMF_OK)
2841*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2842*30a5e8faSwyllys 
2843*30a5e8faSwyllys 	if (keyclass != KMF_ASYM_PUB &&
2844*30a5e8faSwyllys 	    keyclass != KMF_ASYM_PRI &&
2845*30a5e8faSwyllys 	    keyclass != KMF_SYMMETRIC)
284699ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
284799ebb4caSwyllys 
2848*30a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
2849*30a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
2850*30a5e8faSwyllys 
2851*30a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
285299ebb4caSwyllys 
285399ebb4caSwyllys 	if (fullpath == NULL)
285499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
285599ebb4caSwyllys 
2856f482c776Swyllys 	maxkeys = *numkeys;
2857f482c776Swyllys 	if (maxkeys == 0)
2858f482c776Swyllys 		maxkeys = 0xFFFFFFFF;
285999ebb4caSwyllys 	*numkeys = 0;
286099ebb4caSwyllys 
2861*30a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2862*30a5e8faSwyllys 	/* it is okay to have "keys" contains NULL */
2863*30a5e8faSwyllys 
2864*30a5e8faSwyllys 	/*
2865*30a5e8faSwyllys 	 * The caller may want a list of the raw key data as well.
2866*30a5e8faSwyllys 	 * Useful for importing keys from a file into other keystores.
2867*30a5e8faSwyllys 	 */
2868*30a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
2869*30a5e8faSwyllys 
287099ebb4caSwyllys 	if (isdir(fullpath)) {
287199ebb4caSwyllys 		DIR *dirp;
287299ebb4caSwyllys 		struct dirent *dp;
287399ebb4caSwyllys 		int n = 0;
287499ebb4caSwyllys 
287599ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
287699ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
287799ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
287899ebb4caSwyllys 		}
287999ebb4caSwyllys 		rewinddir(dirp);
2880f482c776Swyllys 		while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
288199ebb4caSwyllys 			if (strcmp(dp->d_name, ".") &&
288299ebb4caSwyllys 			    strcmp(dp->d_name, "..")) {
288399ebb4caSwyllys 				char *fname;
288499ebb4caSwyllys 
288599ebb4caSwyllys 				fname = get_fullpath(fullpath,
288699ebb4caSwyllys 				    (char *)&dp->d_name);
288799ebb4caSwyllys 
288899ebb4caSwyllys 				rv = fetch_key(handle, fname,
2889*30a5e8faSwyllys 				    keyclass, key ? &key[n] : NULL);
289099ebb4caSwyllys 
2891*30a5e8faSwyllys 				if (rv == KMF_OK) {
2892*30a5e8faSwyllys 					if (key != NULL && rawkey != NULL)
2893*30a5e8faSwyllys 						rv = convertToRawKey(
2894*30a5e8faSwyllys 						    key[n].keyp, &rawkey[n]);
289599ebb4caSwyllys 					n++;
2896*30a5e8faSwyllys 				}
289799ebb4caSwyllys 
289899ebb4caSwyllys 				if (rv != KMF_OK || key == NULL)
289999ebb4caSwyllys 					free(fname);
290099ebb4caSwyllys 			}
290199ebb4caSwyllys 		}
290299ebb4caSwyllys 		(void) closedir(dirp);
290399ebb4caSwyllys 		free(fullpath);
290499ebb4caSwyllys 		(*numkeys) = n;
290599ebb4caSwyllys 	} else {
2906*30a5e8faSwyllys 		rv = fetch_key(handle, fullpath, keyclass, key);
290799ebb4caSwyllys 		if (rv == KMF_OK)
290899ebb4caSwyllys 			(*numkeys) = 1;
290999ebb4caSwyllys 
291099ebb4caSwyllys 		if (rv != KMF_OK || key == NULL)
291199ebb4caSwyllys 			free(fullpath);
2912*30a5e8faSwyllys 
2913*30a5e8faSwyllys 		if (rv == KMF_OK && key != NULL && rawkey != NULL) {
2914*30a5e8faSwyllys 			rv = convertToRawKey(key->keyp, rawkey);
2915*30a5e8faSwyllys 		}
291699ebb4caSwyllys 	}
291799ebb4caSwyllys 
2918f482c776Swyllys 	if (rv == KMF_OK && (*numkeys) == 0)
291999ebb4caSwyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
292099ebb4caSwyllys 
292199ebb4caSwyllys 	return (rv);
292299ebb4caSwyllys }
292399ebb4caSwyllys 
292499ebb4caSwyllys #define	HANDLE_PK12_ERROR { \
292599ebb4caSwyllys 	SET_ERROR(kmfh, ERR_get_error()); \
292699ebb4caSwyllys 	rv = KMF_ERR_ENCODING; \
292799ebb4caSwyllys 	goto out; \
292899ebb4caSwyllys }
292999ebb4caSwyllys 
293099ebb4caSwyllys static KMF_RETURN
293199ebb4caSwyllys write_pkcs12(KMF_HANDLE *kmfh,
293299ebb4caSwyllys 	BIO *bio,
293399ebb4caSwyllys 	KMF_CREDENTIAL *cred,
293499ebb4caSwyllys 	EVP_PKEY *pkey,
293599ebb4caSwyllys 	X509 *sslcert)
293699ebb4caSwyllys {
293799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
293899ebb4caSwyllys 	STACK_OF(PKCS12_SAFEBAG)	*bag_stack = NULL;
293999ebb4caSwyllys 	PKCS12_SAFEBAG			*bag = NULL;
294099ebb4caSwyllys 	PKCS7				*cert_authsafe = NULL;
294199ebb4caSwyllys 	PKCS8_PRIV_KEY_INFO		*p8 = NULL;
294299ebb4caSwyllys 	PKCS7				*key_authsafe = NULL;
294399ebb4caSwyllys 	STACK_OF(PKCS7)			*authsafe_stack = NULL;
294499ebb4caSwyllys 	PKCS12				*p12_elem = NULL;
294599ebb4caSwyllys 	char				*lab = NULL;
294699ebb4caSwyllys 	int				lab_len = 0;
294799ebb4caSwyllys 	unsigned char keyid[EVP_MAX_MD_SIZE];
294899ebb4caSwyllys 	unsigned int keyidlen = 0;
294999ebb4caSwyllys 
295099ebb4caSwyllys 	/* Must have at least a cert OR a key */
295199ebb4caSwyllys 	if (sslcert == NULL && pkey == NULL)
295299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
295399ebb4caSwyllys 
295499ebb4caSwyllys 	(void) memset(keyid, 0, sizeof (keyid));
295599ebb4caSwyllys 	/*
295699ebb4caSwyllys 	 * Section 1:
295799ebb4caSwyllys 	 *
295899ebb4caSwyllys 	 * The first PKCS#12 container (safebag) will hold the certificates
295999ebb4caSwyllys 	 * associated with this key.  The result of this section is a
296099ebb4caSwyllys 	 * PIN-encrypted PKCS#7 container (authsafe).  If there are no
296199ebb4caSwyllys 	 * certificates, there is no point in creating the "safebag" or the
296299ebb4caSwyllys 	 * "authsafe" so we go to the next section.
296399ebb4caSwyllys 	 */
296499ebb4caSwyllys 	if (sslcert != NULL && pkey != NULL) {
296599ebb4caSwyllys 		if (X509_check_private_key(sslcert, pkey)) {
296699ebb4caSwyllys 			(void) X509_digest(sslcert, EVP_sha1(), keyid,
296799ebb4caSwyllys 			    &keyidlen);
296899ebb4caSwyllys 		} else {
296999ebb4caSwyllys 			/* The key doesn't match the cert */
297099ebb4caSwyllys 			HANDLE_PK12_ERROR
297199ebb4caSwyllys 		}
297299ebb4caSwyllys 	}
297399ebb4caSwyllys 
297499ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
297599ebb4caSwyllys 	if (bag_stack == NULL)
297699ebb4caSwyllys 		return (KMF_ERR_MEMORY);
297799ebb4caSwyllys 
297899ebb4caSwyllys 	if (sslcert != NULL) {
297999ebb4caSwyllys 		/* Convert cert from X509 struct to PKCS#12 bag */
298099ebb4caSwyllys 		bag = PKCS12_x5092certbag(sslcert);
298199ebb4caSwyllys 		if (bag == NULL) {
298299ebb4caSwyllys 			HANDLE_PK12_ERROR
298399ebb4caSwyllys 		}
298499ebb4caSwyllys 
298599ebb4caSwyllys 		/* Add the key id to the certificate bag. */
298699ebb4caSwyllys 		if (keyidlen > 0 &&
298799ebb4caSwyllys 		    !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
298899ebb4caSwyllys 			HANDLE_PK12_ERROR
298999ebb4caSwyllys 		}
299099ebb4caSwyllys 
299199ebb4caSwyllys 		/* Pile it on the bag_stack. */
299299ebb4caSwyllys 		if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
299399ebb4caSwyllys 			HANDLE_PK12_ERROR
299499ebb4caSwyllys 		}
299599ebb4caSwyllys #if 0
299699ebb4caSwyllys 		/* No support for CA certs yet */
299799ebb4caSwyllys 		if (cacerts != NULL && ncacerts > 0) {
299899ebb4caSwyllys 			int i;
299999ebb4caSwyllys 			for (i = 0; i < ncacerts; i++) {
300099ebb4caSwyllys 				KMF_X509_DER_CERT *c = &cacerts[i];
300199ebb4caSwyllys 				X509 *ca = NULL;
300299ebb4caSwyllys 
300399ebb4caSwyllys 				uchar_t *p = (uchar_t *)c->certificate.Data;
3004*30a5e8faSwyllys 				ca = d2i_X509(NULL, &p, c->certificate.Length);
300599ebb4caSwyllys 				if (ca == NULL) {
300699ebb4caSwyllys 					HANDLE_PK12_ERROR
300799ebb4caSwyllys 				}
300899ebb4caSwyllys 				/* Convert CA cert to PKCS#12 bag. */
300999ebb4caSwyllys 				bag = PKCS12_x5092certbag(ca);
301099ebb4caSwyllys 				if (bag == NULL) {
301199ebb4caSwyllys 					sk_PKCS12_SAFEBAG_pop_free(bag_stack,
301299ebb4caSwyllys 					    PKCS12_SAFEBAG_free);
301399ebb4caSwyllys 					HANDLE_PK12_ERROR
301499ebb4caSwyllys 				}
301599ebb4caSwyllys 				/* Pile it onto the bag_stack. */
301699ebb4caSwyllys 				if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
301799ebb4caSwyllys 					HANDLE_PK12_ERROR
301899ebb4caSwyllys 				}
301999ebb4caSwyllys 			}
302099ebb4caSwyllys 		}
302199ebb4caSwyllys #endif
302299ebb4caSwyllys 		/* Turn bag_stack of certs into encrypted authsafe. */
302399ebb4caSwyllys 		cert_authsafe = PKCS12_pack_p7encdata(
302499ebb4caSwyllys 		    NID_pbe_WithSHA1And40BitRC2_CBC,
302534acef67Swyllys 		    cred->cred, cred->credlen, NULL, 0,
302634acef67Swyllys 		    PKCS12_DEFAULT_ITER, bag_stack);
302799ebb4caSwyllys 
302899ebb4caSwyllys 		/* Clear away this bag_stack, we're done with it. */
302999ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
303099ebb4caSwyllys 		bag_stack = NULL;
303199ebb4caSwyllys 
303299ebb4caSwyllys 		if (cert_authsafe == NULL) {
303399ebb4caSwyllys 			HANDLE_PK12_ERROR
303499ebb4caSwyllys 		}
303599ebb4caSwyllys 	}
303699ebb4caSwyllys 	/*
303799ebb4caSwyllys 	 * Section 2:
303899ebb4caSwyllys 	 *
303999ebb4caSwyllys 	 * The second PKCS#12 container (safebag) will hold the private key
304099ebb4caSwyllys 	 * that goes with the certificates above.  The results of this section
304199ebb4caSwyllys 	 * is an unencrypted PKCS#7 container (authsafe).  If there is no
304299ebb4caSwyllys 	 * private key, there is no point in creating the "safebag" or the
304399ebb4caSwyllys 	 * "authsafe" so we go to the next section.
304499ebb4caSwyllys 	 */
304599ebb4caSwyllys 	if (pkey != NULL) {
304699ebb4caSwyllys 		p8 = EVP_PKEY2PKCS8(pkey);
304799ebb4caSwyllys 		if (p8 == NULL) {
304899ebb4caSwyllys 			HANDLE_PK12_ERROR
304999ebb4caSwyllys 		}
305099ebb4caSwyllys 		/* Put the shrouded key into a PKCS#12 bag. */
305199ebb4caSwyllys 		bag = PKCS12_MAKE_SHKEYBAG(
305299ebb4caSwyllys 		    NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
305399ebb4caSwyllys 		    cred->cred, cred->credlen,
305499ebb4caSwyllys 		    NULL, 0, PKCS12_DEFAULT_ITER, p8);
305599ebb4caSwyllys 
305699ebb4caSwyllys 		/* Clean up the PKCS#8 shrouded key, don't need it now. */
305799ebb4caSwyllys 		PKCS8_PRIV_KEY_INFO_free(p8);
305899ebb4caSwyllys 		p8 = NULL;
305999ebb4caSwyllys 
306099ebb4caSwyllys 		if (bag == NULL) {
306199ebb4caSwyllys 			HANDLE_PK12_ERROR
306299ebb4caSwyllys 		}
306399ebb4caSwyllys 		if (keyidlen &&
306499ebb4caSwyllys 		    !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
306599ebb4caSwyllys 			HANDLE_PK12_ERROR
306699ebb4caSwyllys 		}
306799ebb4caSwyllys 		if (lab != NULL) {
306899ebb4caSwyllys 			if (!PKCS12_add_friendlyname(bag,
306999ebb4caSwyllys 			    (char *)lab, lab_len)) {
307099ebb4caSwyllys 				HANDLE_PK12_ERROR
307199ebb4caSwyllys 			}
307299ebb4caSwyllys 		}
307399ebb4caSwyllys 		/* Start a PKCS#12 safebag container for the private key. */
307499ebb4caSwyllys 		bag_stack = sk_PKCS12_SAFEBAG_new_null();
307599ebb4caSwyllys 		if (bag_stack == NULL) {
307699ebb4caSwyllys 			HANDLE_PK12_ERROR
307799ebb4caSwyllys 		}
307899ebb4caSwyllys 
307999ebb4caSwyllys 		/* Pile on the private key on the bag_stack. */
308099ebb4caSwyllys 		if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
308199ebb4caSwyllys 			HANDLE_PK12_ERROR
308299ebb4caSwyllys 		}
308399ebb4caSwyllys 		key_authsafe = PKCS12_pack_p7data(bag_stack);
308499ebb4caSwyllys 
308599ebb4caSwyllys 		/* Clear away this bag_stack, we're done with it. */
308699ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
308799ebb4caSwyllys 		bag_stack = NULL;
308899ebb4caSwyllys 
308999ebb4caSwyllys 		if (key_authsafe == NULL) {
309099ebb4caSwyllys 			HANDLE_PK12_ERROR
309199ebb4caSwyllys 		}
309299ebb4caSwyllys 	}
309399ebb4caSwyllys 	/*
309499ebb4caSwyllys 	 * Section 3:
309599ebb4caSwyllys 	 *
309699ebb4caSwyllys 	 * This is where the two PKCS#7 containers, one for the certificates
309799ebb4caSwyllys 	 * and one for the private key, are put together into a PKCS#12
309899ebb4caSwyllys 	 * element.  This final PKCS#12 element is written to the export file.
309999ebb4caSwyllys 	 */
310099ebb4caSwyllys 
310199ebb4caSwyllys 	/* Start a PKCS#7 stack. */
310299ebb4caSwyllys 	authsafe_stack = sk_PKCS7_new_null();
310399ebb4caSwyllys 	if (authsafe_stack == NULL) {
310499ebb4caSwyllys 		HANDLE_PK12_ERROR
310599ebb4caSwyllys 	}
310699ebb4caSwyllys 	if (key_authsafe != NULL) {
310799ebb4caSwyllys 		if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
310899ebb4caSwyllys 			HANDLE_PK12_ERROR
310999ebb4caSwyllys 		}
311099ebb4caSwyllys 	}
311199ebb4caSwyllys 	if (cert_authsafe != NULL) {
311299ebb4caSwyllys 		if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
311399ebb4caSwyllys 			HANDLE_PK12_ERROR
311499ebb4caSwyllys 		}
311599ebb4caSwyllys 	}
311699ebb4caSwyllys 	p12_elem = PKCS12_init(NID_pkcs7_data);
311799ebb4caSwyllys 	if (p12_elem == NULL) {
311899ebb4caSwyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
311999ebb4caSwyllys 		HANDLE_PK12_ERROR
312099ebb4caSwyllys 	}
312199ebb4caSwyllys 
312299ebb4caSwyllys 	/* Put the PKCS#7 stack into the PKCS#12 element. */
312399ebb4caSwyllys 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
312499ebb4caSwyllys 		HANDLE_PK12_ERROR
312599ebb4caSwyllys 	}
312699ebb4caSwyllys 	/* Clear away the PKCS#7 stack, we're done with it. */
312799ebb4caSwyllys 	sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
312899ebb4caSwyllys 	authsafe_stack = NULL;
312999ebb4caSwyllys 
313099ebb4caSwyllys 	/* Set the integrity MAC on the PKCS#12 element. */
313199ebb4caSwyllys 	if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
313299ebb4caSwyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
313399ebb4caSwyllys 		HANDLE_PK12_ERROR
313499ebb4caSwyllys 	}
313599ebb4caSwyllys 
313699ebb4caSwyllys 	/* Write the PKCS#12 element to the export file. */
313799ebb4caSwyllys 	if (!i2d_PKCS12_bio(bio, p12_elem)) {
313899ebb4caSwyllys 		HANDLE_PK12_ERROR
313999ebb4caSwyllys 	}
314099ebb4caSwyllys 
314199ebb4caSwyllys 	PKCS12_free(p12_elem);
314299ebb4caSwyllys out:
314399ebb4caSwyllys 	if (rv != KMF_OK) {
314499ebb4caSwyllys 		/* Clear away this bag_stack, we're done with it. */
314599ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
314699ebb4caSwyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
314799ebb4caSwyllys 	}
314899ebb4caSwyllys 	return (rv);
314999ebb4caSwyllys }
315099ebb4caSwyllys 
315199ebb4caSwyllys static EVP_PKEY *
315299ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
315399ebb4caSwyllys {
315499ebb4caSwyllys 	RSA		*rsa = NULL;
315599ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
315699ebb4caSwyllys 
315799ebb4caSwyllys 	if ((rsa = RSA_new()) == NULL)
315899ebb4caSwyllys 		return (NULL);
315999ebb4caSwyllys 
316099ebb4caSwyllys 	if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL)
316199ebb4caSwyllys 		return (NULL);
316299ebb4caSwyllys 
316399ebb4caSwyllys 	if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) ==
316499ebb4caSwyllys 	    NULL)
316599ebb4caSwyllys 		return (NULL);
316699ebb4caSwyllys 
316799ebb4caSwyllys 	if (key->priexp.val != NULL)
316899ebb4caSwyllys 		if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len,
316999ebb4caSwyllys 		    rsa->d)) == NULL)
317099ebb4caSwyllys 			return (NULL);
317199ebb4caSwyllys 
317299ebb4caSwyllys 	if (key->prime1.val != NULL)
317399ebb4caSwyllys 		if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len,
317499ebb4caSwyllys 		    rsa->p)) == NULL)
317599ebb4caSwyllys 			return (NULL);
317699ebb4caSwyllys 
317799ebb4caSwyllys 	if (key->prime2.val != NULL)
317899ebb4caSwyllys 		if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len,
317999ebb4caSwyllys 		    rsa->q)) == NULL)
318099ebb4caSwyllys 			return (NULL);
318199ebb4caSwyllys 
318299ebb4caSwyllys 	if (key->exp1.val != NULL)
318399ebb4caSwyllys 		if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len,
318499ebb4caSwyllys 		    rsa->dmp1)) == NULL)
318599ebb4caSwyllys 			return (NULL);
318699ebb4caSwyllys 
318799ebb4caSwyllys 	if (key->exp2.val != NULL)
318899ebb4caSwyllys 		if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len,
318999ebb4caSwyllys 		    rsa->dmq1)) == NULL)
319099ebb4caSwyllys 			return (NULL);
319199ebb4caSwyllys 
319299ebb4caSwyllys 	if (key->coef.val != NULL)
319399ebb4caSwyllys 		if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len,
319499ebb4caSwyllys 		    rsa->iqmp)) == NULL)
319599ebb4caSwyllys 			return (NULL);
319699ebb4caSwyllys 
319799ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
319899ebb4caSwyllys 		return (NULL);
319999ebb4caSwyllys 
320099ebb4caSwyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
320199ebb4caSwyllys 
320299ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
320399ebb4caSwyllys 	RSA_free(rsa);
320499ebb4caSwyllys 
320599ebb4caSwyllys 	return (newkey);
320699ebb4caSwyllys }
320799ebb4caSwyllys 
320899ebb4caSwyllys static EVP_PKEY *
320999ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
321099ebb4caSwyllys {
321199ebb4caSwyllys 	DSA		*dsa = NULL;
321299ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
321399ebb4caSwyllys 
321499ebb4caSwyllys 	if ((dsa = DSA_new()) == NULL)
321599ebb4caSwyllys 		return (NULL);
321699ebb4caSwyllys 
321799ebb4caSwyllys 	if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len,
321899ebb4caSwyllys 	    dsa->p)) == NULL)
321999ebb4caSwyllys 		return (NULL);
322099ebb4caSwyllys 
322199ebb4caSwyllys 	if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len,
322299ebb4caSwyllys 	    dsa->q)) == NULL)
322399ebb4caSwyllys 		return (NULL);
322499ebb4caSwyllys 
322599ebb4caSwyllys 	if ((dsa->g = BN_bin2bn(key->base.val, key->base.len,
322699ebb4caSwyllys 	    dsa->g)) == NULL)
322799ebb4caSwyllys 		return (NULL);
322899ebb4caSwyllys 
322999ebb4caSwyllys 	if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len,
323099ebb4caSwyllys 	    dsa->priv_key)) == NULL)
323199ebb4caSwyllys 		return (NULL);
323299ebb4caSwyllys 
3233*30a5e8faSwyllys 	if (key->pubvalue.val != NULL) {
3234*30a5e8faSwyllys 		if ((dsa->pub_key = BN_bin2bn(key->pubvalue.val,
3235*30a5e8faSwyllys 		    key->pubvalue.len, dsa->pub_key)) == NULL)
3236*30a5e8faSwyllys 			return (NULL);
3237*30a5e8faSwyllys 	}
3238*30a5e8faSwyllys 
323999ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
324099ebb4caSwyllys 		return (NULL);
324199ebb4caSwyllys 
324299ebb4caSwyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
324399ebb4caSwyllys 
324499ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
324599ebb4caSwyllys 	DSA_free(dsa);
324699ebb4caSwyllys 	return (newkey);
324799ebb4caSwyllys }
324899ebb4caSwyllys 
324999ebb4caSwyllys static KMF_RETURN
325099ebb4caSwyllys ExportPK12FromRawData(KMF_HANDLE_T handle,
325199ebb4caSwyllys 	KMF_CREDENTIAL *cred,
325299ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
325399ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
325499ebb4caSwyllys 	char *filename)
325599ebb4caSwyllys {
325699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
325799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
325899ebb4caSwyllys 	BIO *bio = NULL;
325999ebb4caSwyllys 	X509 *xcert = NULL;
326099ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
326199ebb4caSwyllys 	int i;
326299ebb4caSwyllys 
326399ebb4caSwyllys 	/*
326499ebb4caSwyllys 	 * Open the output file.
326599ebb4caSwyllys 	 */
326699ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
326799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
326899ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
326999ebb4caSwyllys 		goto cleanup;
327099ebb4caSwyllys 	}
327199ebb4caSwyllys 
327299ebb4caSwyllys 	if (numcerts > 0 && numkeys > 0) {
327399ebb4caSwyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
327499ebb4caSwyllys 			KMF_RAW_KEY_DATA *key = NULL;
327599ebb4caSwyllys 			const uchar_t *p = certlist[i].certificate.Data;
327699ebb4caSwyllys 			long len = certlist[i].certificate.Length;
327799ebb4caSwyllys 
327899ebb4caSwyllys 			if (i < numkeys) {
327999ebb4caSwyllys 				key = (KMF_RAW_KEY_DATA *)keylist[i].keyp;
328099ebb4caSwyllys 
328199ebb4caSwyllys 				if (key->keytype == KMF_RSA) {
328299ebb4caSwyllys 					pkey = ImportRawRSAKey(
328399ebb4caSwyllys 					    &key->rawdata.rsa);
328499ebb4caSwyllys 				} else if (key->keytype == KMF_DSA) {
328599ebb4caSwyllys 					pkey = ImportRawDSAKey(
328699ebb4caSwyllys 					    &key->rawdata.dsa);
328799ebb4caSwyllys 				} else {
328899ebb4caSwyllys 					rv = KMF_ERR_BAD_PARAMETER;
328999ebb4caSwyllys 				}
329099ebb4caSwyllys 			}
329199ebb4caSwyllys 
329299ebb4caSwyllys 			xcert = d2i_X509(NULL, &p, len);
329399ebb4caSwyllys 			if (xcert == NULL) {
329499ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
329599ebb4caSwyllys 				rv = KMF_ERR_ENCODING;
329699ebb4caSwyllys 			}
329799ebb4caSwyllys 			/* Stick the key and the cert into a PKCS#12 file */
329899ebb4caSwyllys 			rv = write_pkcs12(kmfh, bio, cred, pkey, xcert);
329999ebb4caSwyllys 			if (xcert)
330099ebb4caSwyllys 				X509_free(xcert);
330199ebb4caSwyllys 			if (pkey)
330299ebb4caSwyllys 				EVP_PKEY_free(pkey);
330399ebb4caSwyllys 		}
330499ebb4caSwyllys 	}
330599ebb4caSwyllys 
330699ebb4caSwyllys cleanup:
330799ebb4caSwyllys 
330899ebb4caSwyllys 	if (bio != NULL)
330999ebb4caSwyllys 		(void) BIO_free_all(bio);
331099ebb4caSwyllys 
331199ebb4caSwyllys 	return (rv);
331299ebb4caSwyllys }
331399ebb4caSwyllys 
3314*30a5e8faSwyllys 
331599ebb4caSwyllys KMF_RETURN
3316*30a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
3317*30a5e8faSwyllys     KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
3318*30a5e8faSwyllys     KMF_CREDENTIAL *p12cred, char *filename)
3319*30a5e8faSwyllys {
3320*30a5e8faSwyllys 	KMF_RETURN rv;
3321*30a5e8faSwyllys 
3322*30a5e8faSwyllys 	if (certlist == NULL && keylist == NULL)
3323*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
3324*30a5e8faSwyllys 
3325*30a5e8faSwyllys 	rv = ExportPK12FromRawData(handle, p12cred, numcerts, certlist,
3326*30a5e8faSwyllys 	    numkeys, keylist, filename);
3327*30a5e8faSwyllys 
3328*30a5e8faSwyllys 	return (rv);
3329*30a5e8faSwyllys }
3330*30a5e8faSwyllys 
3331*30a5e8faSwyllys 
3332*30a5e8faSwyllys KMF_RETURN
3333*30a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
333499ebb4caSwyllys {
333599ebb4caSwyllys 	KMF_RETURN rv;
333699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
333799ebb4caSwyllys 	BIO *bio = NULL;
333899ebb4caSwyllys 	X509 *xcert = NULL;
333999ebb4caSwyllys 	char *fullpath = NULL;
334099ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
3341*30a5e8faSwyllys 	char *dirpath = NULL;
3342*30a5e8faSwyllys 	char *certfile = NULL;
3343*30a5e8faSwyllys 	char *keyfile = NULL;
3344*30a5e8faSwyllys 	char *filename = NULL;
3345*30a5e8faSwyllys 	KMF_CREDENTIAL *p12cred = NULL;
3346*30a5e8faSwyllys 
3347*30a5e8faSwyllys 	if (handle == NULL)
3348*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
334999ebb4caSwyllys 
335099ebb4caSwyllys 	/*
335199ebb4caSwyllys 	 *  First, find the certificate.
335299ebb4caSwyllys 	 */
3353*30a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
3354*30a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
3355*30a5e8faSwyllys 	if (certfile != NULL) {
3356*30a5e8faSwyllys 		fullpath = get_fullpath(dirpath, certfile);
335799ebb4caSwyllys 		if (fullpath == NULL)
335899ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
335999ebb4caSwyllys 
336099ebb4caSwyllys 		if (isdir(fullpath)) {
336199ebb4caSwyllys 			free(fullpath);
336299ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
336399ebb4caSwyllys 		}
336499ebb4caSwyllys 
3365*30a5e8faSwyllys 		rv = load_X509cert(kmfh, NULL, NULL, NULL, fullpath, &xcert);
336699ebb4caSwyllys 		if (rv != KMF_OK)
336799ebb4caSwyllys 			goto end;
3368*30a5e8faSwyllys 
3369*30a5e8faSwyllys 		free(fullpath);
337099ebb4caSwyllys 	}
337199ebb4caSwyllys 
337299ebb4caSwyllys 	/*
337399ebb4caSwyllys 	 * Now find the private key.
337499ebb4caSwyllys 	 */
3375*30a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
3376*30a5e8faSwyllys 	if (keyfile != NULL) {
3377*30a5e8faSwyllys 		fullpath = get_fullpath(dirpath, keyfile);
337899ebb4caSwyllys 		if (fullpath == NULL)
337999ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
338099ebb4caSwyllys 
338199ebb4caSwyllys 		if (isdir(fullpath)) {
338299ebb4caSwyllys 			free(fullpath);
338399ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
338499ebb4caSwyllys 		}
338599ebb4caSwyllys 
338699ebb4caSwyllys 		pkey = openssl_load_key(handle, fullpath);
338799ebb4caSwyllys 		if (pkey == NULL) {
338899ebb4caSwyllys 			rv = KMF_ERR_KEY_NOT_FOUND;
338999ebb4caSwyllys 			goto end;
339099ebb4caSwyllys 		}
339199ebb4caSwyllys 	}
339299ebb4caSwyllys 
339399ebb4caSwyllys 	/*
339499ebb4caSwyllys 	 * Open the output file.
339599ebb4caSwyllys 	 */
3396*30a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
3397*30a5e8faSwyllys 	    numattr);
3398*30a5e8faSwyllys 	if (filename == NULL) {
3399*30a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
3400*30a5e8faSwyllys 		goto end;
3401*30a5e8faSwyllys 	}
3402*30a5e8faSwyllys 
340399ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
340499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
340599ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
340699ebb4caSwyllys 		goto end;
340799ebb4caSwyllys 	}
340899ebb4caSwyllys 
340999ebb4caSwyllys 	/* Stick the key and the cert into a PKCS#12 file */
3410*30a5e8faSwyllys 	p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
3411*30a5e8faSwyllys 	if (p12cred == NULL) {
3412*30a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
3413*30a5e8faSwyllys 		goto end;
3414*30a5e8faSwyllys 	}
3415*30a5e8faSwyllys 
3416*30a5e8faSwyllys 	rv = write_pkcs12(kmfh, bio, p12cred, pkey, xcert);
341799ebb4caSwyllys 
341899ebb4caSwyllys end:
341999ebb4caSwyllys 	if (fullpath)
342099ebb4caSwyllys 		free(fullpath);
342199ebb4caSwyllys 	if (xcert)
342299ebb4caSwyllys 		X509_free(xcert);
342399ebb4caSwyllys 	if (pkey)
342499ebb4caSwyllys 		EVP_PKEY_free(pkey);
342599ebb4caSwyllys 	if (bio)
342699ebb4caSwyllys 		(void) BIO_free(bio);
342799ebb4caSwyllys 
342899ebb4caSwyllys 	return (rv);
342999ebb4caSwyllys }
343099ebb4caSwyllys 
3431*30a5e8faSwyllys 
343271593db2Swyllys #define	MAX_CHAIN_LENGTH 100
343371593db2Swyllys /*
343471593db2Swyllys  * Helper function to extract keys and certificates from
343571593db2Swyllys  * a single PEM file.  Typically the file should contain a
343671593db2Swyllys  * private key and an associated public key wrapped in an x509 cert.
343771593db2Swyllys  * However, the file may be just a list of X509 certs with no keys.
343871593db2Swyllys  */
343971593db2Swyllys static KMF_RETURN
3440*30a5e8faSwyllys extract_pem(KMF_HANDLE *kmfh,
3441*30a5e8faSwyllys 	char *issuer, char *subject, KMF_BIGINT *serial,
344202744e81Swyllys 	char *filename, CK_UTF8CHAR *pin,
344371593db2Swyllys 	CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
344471593db2Swyllys 	int *numcerts)
344571593db2Swyllys /* ARGSUSED */
344671593db2Swyllys {
344771593db2Swyllys 	KMF_RETURN rv = KMF_OK;
344871593db2Swyllys 	FILE *fp;
344934acef67Swyllys 	STACK_OF(X509_INFO) *x509_info_stack = NULL;
345002744e81Swyllys 	int i, ncerts = 0, matchcerts = 0;
345171593db2Swyllys 	EVP_PKEY *pkey = NULL;
345271593db2Swyllys 	X509_INFO *info;
345371593db2Swyllys 	X509 *x;
345471593db2Swyllys 	X509_INFO *cert_infos[MAX_CHAIN_LENGTH];
345571593db2Swyllys 	KMF_DATA *certlist = NULL;
345671593db2Swyllys 
345771593db2Swyllys 	if (priv_key)
345871593db2Swyllys 		*priv_key = NULL;
345971593db2Swyllys 	if (certs)
346071593db2Swyllys 		*certs = NULL;
346171593db2Swyllys 	fp = fopen(filename, "r");
346271593db2Swyllys 	if (fp == NULL) {
346371593db2Swyllys 		return (KMF_ERR_OPEN_FILE);
346471593db2Swyllys 	}
346571593db2Swyllys 	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
346671593db2Swyllys 	if (x509_info_stack == NULL) {
346771593db2Swyllys 		(void) fclose(fp);
346871593db2Swyllys 		return (KMF_ERR_ENCODING);
346971593db2Swyllys 	}
347071593db2Swyllys 
3471*30a5e8faSwyllys 
347234acef67Swyllys 	for (i = 0;
347334acef67Swyllys 	    i < sk_X509_INFO_num(x509_info_stack) && i < MAX_CHAIN_LENGTH;
347434acef67Swyllys 	    i++) {
347571593db2Swyllys 		/* LINTED */
347634acef67Swyllys 		cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
347771593db2Swyllys 		ncerts++;
347871593db2Swyllys 	}
347971593db2Swyllys 
348071593db2Swyllys 	if (ncerts == 0) {
348171593db2Swyllys 		(void) fclose(fp);
348234acef67Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
348334acef67Swyllys 		goto err;
348471593db2Swyllys 	}
348571593db2Swyllys 
348671593db2Swyllys 	if (priv_key != NULL) {
348771593db2Swyllys 		rewind(fp);
348871593db2Swyllys 		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
348971593db2Swyllys 	}
349071593db2Swyllys 	(void) fclose(fp);
349171593db2Swyllys 
349271593db2Swyllys 	x = cert_infos[ncerts - 1]->x509;
349371593db2Swyllys 	/*
349471593db2Swyllys 	 * Make sure the private key matchs the last cert in the file.
349571593db2Swyllys 	 */
349671593db2Swyllys 	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
349771593db2Swyllys 		EVP_PKEY_free(pkey);
349834acef67Swyllys 		rv = KMF_ERR_KEY_MISMATCH;
349934acef67Swyllys 		goto err;
350071593db2Swyllys 	}
350171593db2Swyllys 
350271593db2Swyllys 	certlist = (KMF_DATA *)malloc(ncerts * sizeof (KMF_DATA));
350371593db2Swyllys 	if (certlist == NULL) {
350471593db2Swyllys 		if (pkey != NULL)
350571593db2Swyllys 			EVP_PKEY_free(pkey);
350634acef67Swyllys 		rv = KMF_ERR_MEMORY;
350734acef67Swyllys 		goto err;
350871593db2Swyllys 	}
350971593db2Swyllys 
351071593db2Swyllys 	/*
351171593db2Swyllys 	 * Convert all of the certs to DER format.
351271593db2Swyllys 	 */
351302744e81Swyllys 	matchcerts = 0;
351471593db2Swyllys 	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
351502744e81Swyllys 		boolean_t match = FALSE;
351671593db2Swyllys 		info =  cert_infos[ncerts - 1 - i];
351771593db2Swyllys 
3518*30a5e8faSwyllys 		rv = check_cert(info->x509, issuer, subject, serial, &match);
351902744e81Swyllys 		if (rv != KMF_OK || match != TRUE) {
352002744e81Swyllys 			rv = KMF_OK;
352102744e81Swyllys 			continue;
352202744e81Swyllys 		}
352302744e81Swyllys 
352402744e81Swyllys 		rv = ssl_cert2KMFDATA(kmfh, info->x509,
352502744e81Swyllys 			&certlist[matchcerts++]);
352671593db2Swyllys 
352771593db2Swyllys 		if (rv != KMF_OK) {
352871593db2Swyllys 			free(certlist);
352971593db2Swyllys 			certlist = NULL;
353002744e81Swyllys 			ncerts = matchcerts = 0;
353171593db2Swyllys 		}
353271593db2Swyllys 	}
353371593db2Swyllys 
353471593db2Swyllys 	if (numcerts != NULL)
353502744e81Swyllys 		*numcerts = matchcerts;
353671593db2Swyllys 	if (certs != NULL)
353771593db2Swyllys 		*certs = certlist;
353871593db2Swyllys 
353971593db2Swyllys 	if (priv_key == NULL && pkey != NULL)
354071593db2Swyllys 		EVP_PKEY_free(pkey);
354171593db2Swyllys 	else if (priv_key != NULL && pkey != NULL)
354271593db2Swyllys 		*priv_key = pkey;
354371593db2Swyllys 
354434acef67Swyllys err:
354534acef67Swyllys 	/* Cleanup the stack of X509 info records */
354634acef67Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
354734acef67Swyllys 		/*LINTED*/
354834acef67Swyllys 		info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
354934acef67Swyllys 		X509_INFO_free(info);
355034acef67Swyllys 	}
355134acef67Swyllys 	if (x509_info_stack)
355234acef67Swyllys 		sk_X509_INFO_free(x509_info_stack);
355334acef67Swyllys 
355471593db2Swyllys 	return (rv);
355571593db2Swyllys }
355671593db2Swyllys 
355799ebb4caSwyllys /*
355899ebb4caSwyllys  * Helper function to decrypt and parse PKCS#12 import file.
355999ebb4caSwyllys  */
356099ebb4caSwyllys static KMF_RETURN
356199ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
356299ebb4caSwyllys 	EVP_PKEY **priv_key, X509 **cert, STACK_OF(X509) **ca)
356399ebb4caSwyllys /* ARGSUSED */
356499ebb4caSwyllys {
356599ebb4caSwyllys 	PKCS12		*pk12, *pk12_tmp;
356699ebb4caSwyllys 	EVP_PKEY	*temp_pkey = NULL;
356799ebb4caSwyllys 	X509		*temp_cert = NULL;
356899ebb4caSwyllys 	STACK_OF(X509)	*temp_ca = NULL;
356999ebb4caSwyllys 
357099ebb4caSwyllys 	if ((pk12 = PKCS12_new()) == NULL) {
357199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
357299ebb4caSwyllys 	}
357399ebb4caSwyllys 
357499ebb4caSwyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
357599ebb4caSwyllys 		/* This is ok; it seems to mean there is no more to read. */
357699ebb4caSwyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
357799ebb4caSwyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
357899ebb4caSwyllys 			goto end_extract_pkcs12;
357999ebb4caSwyllys 
358099ebb4caSwyllys 		PKCS12_free(pk12);
358199ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
358299ebb4caSwyllys 	}
358399ebb4caSwyllys 	pk12 = pk12_tmp;
358499ebb4caSwyllys 
358599ebb4caSwyllys 	if (PKCS12_parse(pk12, (char *)pin, &temp_pkey, &temp_cert,
358699ebb4caSwyllys 	    &temp_ca) <= 0) {
358799ebb4caSwyllys 		PKCS12_free(pk12);
358899ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
358999ebb4caSwyllys 	}
359099ebb4caSwyllys 
359199ebb4caSwyllys end_extract_pkcs12:
359299ebb4caSwyllys 
359399ebb4caSwyllys 	*priv_key = temp_pkey;
359499ebb4caSwyllys 	*cert = temp_cert;
359599ebb4caSwyllys 	*ca = temp_ca;
359699ebb4caSwyllys 
359799ebb4caSwyllys 	PKCS12_free(pk12);
359899ebb4caSwyllys 	return (KMF_OK);
359999ebb4caSwyllys }
360099ebb4caSwyllys 
360199ebb4caSwyllys static KMF_RETURN
360299ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
360399ebb4caSwyllys {
360499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
360599ebb4caSwyllys 	uint32_t sz;
360699ebb4caSwyllys 
360799ebb4caSwyllys 	sz = BN_num_bytes(from);
360899ebb4caSwyllys 	to->val = (uchar_t *)malloc(sz);
360999ebb4caSwyllys 	if (to->val == NULL)
361099ebb4caSwyllys 		return (KMF_ERR_MEMORY);
361199ebb4caSwyllys 
361299ebb4caSwyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
361399ebb4caSwyllys 		free(to->val);
361499ebb4caSwyllys 		to->val = NULL;
361599ebb4caSwyllys 		to->len = 0;
361699ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
361799ebb4caSwyllys 	}
361899ebb4caSwyllys 
361999ebb4caSwyllys 	return (rv);
362099ebb4caSwyllys }
362199ebb4caSwyllys 
362299ebb4caSwyllys static KMF_RETURN
362399ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
362499ebb4caSwyllys {
362599ebb4caSwyllys 	KMF_RETURN rv;
362699ebb4caSwyllys 	KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
362799ebb4caSwyllys 
362899ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
362999ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK)
363099ebb4caSwyllys 		goto cleanup;
363199ebb4caSwyllys 
363299ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK)
363399ebb4caSwyllys 		goto cleanup;
363499ebb4caSwyllys 
363599ebb4caSwyllys 	if (rsa->d != NULL)
363699ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK)
363799ebb4caSwyllys 			goto cleanup;
363899ebb4caSwyllys 
363999ebb4caSwyllys 	if (rsa->p != NULL)
364099ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK)
364199ebb4caSwyllys 			goto cleanup;
364299ebb4caSwyllys 
364399ebb4caSwyllys 	if (rsa->q != NULL)
364499ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK)
364599ebb4caSwyllys 			goto cleanup;
364699ebb4caSwyllys 
364799ebb4caSwyllys 	if (rsa->dmp1 != NULL)
364899ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK)
364999ebb4caSwyllys 			goto cleanup;
365099ebb4caSwyllys 
365199ebb4caSwyllys 	if (rsa->dmq1 != NULL)
365299ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK)
365399ebb4caSwyllys 			goto cleanup;
365499ebb4caSwyllys 
365599ebb4caSwyllys 	if (rsa->iqmp != NULL)
365699ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK)
365799ebb4caSwyllys 			goto cleanup;
365899ebb4caSwyllys cleanup:
365999ebb4caSwyllys 	if (rv != KMF_OK)
3660*30a5e8faSwyllys 		kmf_free_raw_key(key);
366199ebb4caSwyllys 	else
366299ebb4caSwyllys 		key->keytype = KMF_RSA;
366399ebb4caSwyllys 
366499ebb4caSwyllys 	/*
366599ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
366699ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
366799ebb4caSwyllys 	 */
366899ebb4caSwyllys 	RSA_free(rsa);
366999ebb4caSwyllys 
367099ebb4caSwyllys 	return (rv);
367199ebb4caSwyllys }
367299ebb4caSwyllys 
367399ebb4caSwyllys static KMF_RETURN
367499ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
367599ebb4caSwyllys {
367699ebb4caSwyllys 	KMF_RETURN rv;
367799ebb4caSwyllys 	KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
367899ebb4caSwyllys 
367999ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
368099ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK)
368199ebb4caSwyllys 		goto cleanup;
368299ebb4caSwyllys 
368399ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK)
368499ebb4caSwyllys 		goto cleanup;
368599ebb4caSwyllys 
368699ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK)
368799ebb4caSwyllys 		goto cleanup;
368899ebb4caSwyllys 
368999ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK)
369099ebb4caSwyllys 		goto cleanup;
369199ebb4caSwyllys 
369299ebb4caSwyllys cleanup:
369399ebb4caSwyllys 	if (rv != KMF_OK)
3694*30a5e8faSwyllys 		kmf_free_raw_key(key);
369599ebb4caSwyllys 	else
369699ebb4caSwyllys 		key->keytype = KMF_DSA;
369799ebb4caSwyllys 
369899ebb4caSwyllys 	/*
369999ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
370099ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
370199ebb4caSwyllys 	 */
370299ebb4caSwyllys 	DSA_free(dsa);
370399ebb4caSwyllys 
370499ebb4caSwyllys 	return (rv);
370599ebb4caSwyllys }
370699ebb4caSwyllys 
370799ebb4caSwyllys static KMF_RETURN
370899ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
370999ebb4caSwyllys 	KMF_DATA **certlist, int *ncerts)
371099ebb4caSwyllys {
371199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
371299ebb4caSwyllys 	KMF_DATA *list = (*certlist);
371399ebb4caSwyllys 	KMF_DATA cert;
371499ebb4caSwyllys 	int n = (*ncerts);
371599ebb4caSwyllys 
371699ebb4caSwyllys 	if (list == NULL) {
371799ebb4caSwyllys 		list = (KMF_DATA *)malloc(sizeof (KMF_DATA));
371899ebb4caSwyllys 	} else {
371999ebb4caSwyllys 		list = (KMF_DATA *)realloc(list, sizeof (KMF_DATA) * (n + 1));
372099ebb4caSwyllys 	}
372199ebb4caSwyllys 
372299ebb4caSwyllys 	if (list == NULL)
372399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
372499ebb4caSwyllys 
372599ebb4caSwyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert);
372699ebb4caSwyllys 	if (rv == KMF_OK) {
372799ebb4caSwyllys 		list[n] = cert;
372899ebb4caSwyllys 		(*ncerts) = n + 1;
372999ebb4caSwyllys 
373099ebb4caSwyllys 		*certlist = list;
373199ebb4caSwyllys 	} else {
373299ebb4caSwyllys 		free(list);
373399ebb4caSwyllys 	}
373499ebb4caSwyllys 
373599ebb4caSwyllys 	return (rv);
373699ebb4caSwyllys }
373799ebb4caSwyllys 
373899ebb4caSwyllys static KMF_RETURN
373999ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
374099ebb4caSwyllys 	KMF_RAW_KEY_DATA *newkey, int *nkeys)
374199ebb4caSwyllys {
374299ebb4caSwyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
374399ebb4caSwyllys 	int n = (*nkeys);
374499ebb4caSwyllys 
374599ebb4caSwyllys 	if (list == NULL) {
374699ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
374799ebb4caSwyllys 	} else {
374899ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
374999ebb4caSwyllys 		    sizeof (KMF_RAW_KEY_DATA) * (n + 1));
375099ebb4caSwyllys 	}
375199ebb4caSwyllys 
375299ebb4caSwyllys 	if (list == NULL)
375399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
375499ebb4caSwyllys 
375599ebb4caSwyllys 	list[n] = *newkey;
375699ebb4caSwyllys 	(*nkeys) = n + 1;
375799ebb4caSwyllys 
375899ebb4caSwyllys 	*keylist = list;
375999ebb4caSwyllys 
376099ebb4caSwyllys 	return (KMF_OK);
376199ebb4caSwyllys }
376299ebb4caSwyllys 
3763*30a5e8faSwyllys static KMF_RETURN
3764*30a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
3765*30a5e8faSwyllys {
3766*30a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
3767*30a5e8faSwyllys 
3768*30a5e8faSwyllys 	if (pkey == NULL || key == NULL)
3769*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
3770*30a5e8faSwyllys 	/* Convert SSL key to raw key */
3771*30a5e8faSwyllys 	switch (pkey->type) {
3772*30a5e8faSwyllys 		case EVP_PKEY_RSA:
3773*30a5e8faSwyllys 			rv = exportRawRSAKey(EVP_PKEY_get1_RSA(pkey),
3774*30a5e8faSwyllys 			    key);
3775*30a5e8faSwyllys 			if (rv != KMF_OK)
3776*30a5e8faSwyllys 				return (rv);
3777*30a5e8faSwyllys 			break;
3778*30a5e8faSwyllys 		case EVP_PKEY_DSA:
3779*30a5e8faSwyllys 			rv = exportRawDSAKey(EVP_PKEY_get1_DSA(pkey),
3780*30a5e8faSwyllys 			    key);
3781*30a5e8faSwyllys 			if (rv != KMF_OK)
3782*30a5e8faSwyllys 				return (rv);
3783*30a5e8faSwyllys 			break;
3784*30a5e8faSwyllys 		default:
3785*30a5e8faSwyllys 			return (KMF_ERR_BAD_PARAMETER);
3786*30a5e8faSwyllys 	}
3787*30a5e8faSwyllys 
3788*30a5e8faSwyllys 	return (rv);
3789*30a5e8faSwyllys }
379099ebb4caSwyllys 
379199ebb4caSwyllys static KMF_RETURN
379299ebb4caSwyllys convertPK12Objects(
379399ebb4caSwyllys 	KMF_HANDLE *kmfh,
379499ebb4caSwyllys 	EVP_PKEY *sslkey, X509 *sslcert, STACK_OF(X509) *sslcacerts,
379599ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
379699ebb4caSwyllys 	KMF_DATA **certlist, int *ncerts)
379799ebb4caSwyllys {
379899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
379999ebb4caSwyllys 	KMF_RAW_KEY_DATA key;
380099ebb4caSwyllys 	int i;
380199ebb4caSwyllys 
380299ebb4caSwyllys 	if (sslkey != NULL) {
3803*30a5e8faSwyllys 		rv = convertToRawKey(sslkey, &key);
3804*30a5e8faSwyllys 		if (rv == KMF_OK)
380599ebb4caSwyllys 			rv = add_key_to_list(keylist, &key, nkeys);
3806*30a5e8faSwyllys 
380799ebb4caSwyllys 		if (rv != KMF_OK)
380899ebb4caSwyllys 			return (rv);
380999ebb4caSwyllys 	}
381099ebb4caSwyllys 
381199ebb4caSwyllys 	/* Now add the certificate to the certlist */
381299ebb4caSwyllys 	if (sslcert != NULL) {
381399ebb4caSwyllys 		rv = add_cert_to_list(kmfh, sslcert, certlist, ncerts);
381499ebb4caSwyllys 		if (rv != KMF_OK)
381599ebb4caSwyllys 			return (rv);
381699ebb4caSwyllys 	}
381799ebb4caSwyllys 
381899ebb4caSwyllys 	/* Also add any included CA certs to the list */
381971593db2Swyllys 	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
382099ebb4caSwyllys 		X509 *c;
382199ebb4caSwyllys 		/*
382299ebb4caSwyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
382399ebb4caSwyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
382499ebb4caSwyllys 		 * Lint is complaining about the embedded casting, and
382599ebb4caSwyllys 		 * to fix it, you need to fix openssl header files.
382699ebb4caSwyllys 		 */
382799ebb4caSwyllys 		/* LINTED E_BAD_PTR_CAST_ALIGN */
382899ebb4caSwyllys 		c = sk_X509_value(sslcacerts, i);
382999ebb4caSwyllys 
383099ebb4caSwyllys 		/* Now add the ca cert to the certlist */
383199ebb4caSwyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
383299ebb4caSwyllys 		if (rv != KMF_OK)
383399ebb4caSwyllys 			return (rv);
383499ebb4caSwyllys 	}
383599ebb4caSwyllys 	return (rv);
383699ebb4caSwyllys }
383799ebb4caSwyllys 
383899ebb4caSwyllys KMF_RETURN
3839*30a5e8faSwyllys openssl_import_objects(KMF_HANDLE *kmfh,
384099ebb4caSwyllys 	char *filename, KMF_CREDENTIAL *cred,
384199ebb4caSwyllys 	KMF_DATA **certlist, int *ncerts,
384299ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
384399ebb4caSwyllys {
384499ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
384599ebb4caSwyllys 	EVP_PKEY	*privkey = NULL;
3846*30a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
3847*30a5e8faSwyllys 	BIO		*bio = NULL;
384899ebb4caSwyllys 	X509		*cert = NULL;
384999ebb4caSwyllys 	STACK_OF(X509)	*cacerts = NULL;
385099ebb4caSwyllys 
3851*30a5e8faSwyllys 	/*
3852*30a5e8faSwyllys 	 * auto-detect the file format, regardless of what
3853*30a5e8faSwyllys 	 * the 'format' parameters in the params say.
3854*30a5e8faSwyllys 	 */
3855*30a5e8faSwyllys 	rv = kmf_get_file_format(filename, &format);
3856*30a5e8faSwyllys 	if (rv != KMF_OK) {
3857*30a5e8faSwyllys 		return (rv);
3858*30a5e8faSwyllys 	}
3859*30a5e8faSwyllys 
3860*30a5e8faSwyllys 	/* This function only works for PEM or PKCS#12 files */
3861*30a5e8faSwyllys 	if (format != KMF_FORMAT_PEM &&
3862*30a5e8faSwyllys 	    format != KMF_FORMAT_PEM_KEYPAIR &&
3863*30a5e8faSwyllys 	    format != KMF_FORMAT_PKCS12)
3864*30a5e8faSwyllys 		return (KMF_ERR_ENCODING);
3865*30a5e8faSwyllys 
3866*30a5e8faSwyllys 	*certlist = NULL;
3867*30a5e8faSwyllys 	*keylist = NULL;
3868*30a5e8faSwyllys 	*ncerts = 0;
3869*30a5e8faSwyllys 	*nkeys = 0;
3870*30a5e8faSwyllys 
3871*30a5e8faSwyllys 	if (format == KMF_FORMAT_PKCS12) {
387299ebb4caSwyllys 		bio = BIO_new_file(filename, "rb");
387399ebb4caSwyllys 		if (bio == NULL) {
387499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
387599ebb4caSwyllys 			rv = KMF_ERR_OPEN_FILE;
387699ebb4caSwyllys 			goto end;
387799ebb4caSwyllys 		}
387899ebb4caSwyllys 
387934acef67Swyllys 		rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
388034acef67Swyllys 		    (uint32_t)cred->credlen, &privkey, &cert, &cacerts);
388199ebb4caSwyllys 
388299ebb4caSwyllys 		if (rv  == KMF_OK)
388399ebb4caSwyllys 			/* Convert keys and certs to exportable format */
388499ebb4caSwyllys 			rv = convertPK12Objects(kmfh, privkey, cert, cacerts,
388599ebb4caSwyllys 			    keylist, nkeys, certlist, ncerts);
388699ebb4caSwyllys 
3887*30a5e8faSwyllys 	} else {
3888*30a5e8faSwyllys 		rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
388934acef67Swyllys 		    (uchar_t *)cred->cred, (uint32_t)cred->credlen,
389071593db2Swyllys 		    &privkey, certlist, ncerts);
389171593db2Swyllys 
389271593db2Swyllys 		/* Reached end of import file? */
389371593db2Swyllys 		if (rv == KMF_OK)
389471593db2Swyllys 			/* Convert keys and certs to exportable format */
389571593db2Swyllys 			rv = convertPK12Objects(kmfh, privkey, NULL, NULL,
389671593db2Swyllys 			    keylist, nkeys, NULL, NULL);
3897*30a5e8faSwyllys 	}
389871593db2Swyllys 
389971593db2Swyllys end:
390071593db2Swyllys 	if (privkey)
390171593db2Swyllys 		EVP_PKEY_free(privkey);
390271593db2Swyllys 
3903*30a5e8faSwyllys 	if (bio != NULL)
390499ebb4caSwyllys 		(void) BIO_free(bio);
390599ebb4caSwyllys 
3906*30a5e8faSwyllys 	if (cert)
3907*30a5e8faSwyllys 		X509_free(cert);
3908*30a5e8faSwyllys 
3909*30a5e8faSwyllys 	if (cacerts)
3910*30a5e8faSwyllys 		sk_X509_free(cacerts);
3911*30a5e8faSwyllys 
391299ebb4caSwyllys 	return (rv);
391399ebb4caSwyllys }
391499ebb4caSwyllys 
391599ebb4caSwyllys static KMF_RETURN
391699ebb4caSwyllys create_deskey(DES_cblock **deskey)
391799ebb4caSwyllys {
391899ebb4caSwyllys 	DES_cblock *key;
391999ebb4caSwyllys 
392099ebb4caSwyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
392199ebb4caSwyllys 	if (key == NULL) {
392299ebb4caSwyllys 		return (KMF_ERR_MEMORY);
392399ebb4caSwyllys 	}
392499ebb4caSwyllys 
392599ebb4caSwyllys 	if (DES_random_key(key) == 0) {
392699ebb4caSwyllys 		free(key);
392799ebb4caSwyllys 		return (KMF_ERR_KEYGEN_FAILED);
392899ebb4caSwyllys 	}
392999ebb4caSwyllys 
393099ebb4caSwyllys 	*deskey = key;
393199ebb4caSwyllys 	return (KMF_OK);
393299ebb4caSwyllys }
393399ebb4caSwyllys 
393499ebb4caSwyllys #define	KEYGEN_RETRY 3
393599ebb4caSwyllys #define	DES3_KEY_SIZE 24
393699ebb4caSwyllys 
393799ebb4caSwyllys static KMF_RETURN
393899ebb4caSwyllys create_des3key(unsigned char **des3key)
393999ebb4caSwyllys {
394099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
394199ebb4caSwyllys 	DES_cblock *deskey1 = NULL;
394299ebb4caSwyllys 	DES_cblock *deskey2 = NULL;
394399ebb4caSwyllys 	DES_cblock *deskey3 = NULL;
394499ebb4caSwyllys 	unsigned char *newkey = NULL;
394599ebb4caSwyllys 	int retry;
394699ebb4caSwyllys 
394799ebb4caSwyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
394899ebb4caSwyllys 		return (KMF_ERR_MEMORY);
394999ebb4caSwyllys 	}
395099ebb4caSwyllys 
395199ebb4caSwyllys 	/* create the 1st DES key */
395299ebb4caSwyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
395399ebb4caSwyllys 		goto out;
395499ebb4caSwyllys 	}
395599ebb4caSwyllys 
395699ebb4caSwyllys 	/*
395799ebb4caSwyllys 	 * Create the 2nd DES key and make sure its value is different
395899ebb4caSwyllys 	 * from the 1st DES key.
395999ebb4caSwyllys 	 */
396099ebb4caSwyllys 	retry = 0;
396199ebb4caSwyllys 	do {
396299ebb4caSwyllys 		if (deskey2 != NULL) {
396399ebb4caSwyllys 			free(deskey2);
396499ebb4caSwyllys 			deskey2 = NULL;
396599ebb4caSwyllys 		}
396699ebb4caSwyllys 
396799ebb4caSwyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
396899ebb4caSwyllys 			goto out;
396999ebb4caSwyllys 		}
397099ebb4caSwyllys 
397199ebb4caSwyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
397299ebb4caSwyllys 		    == 0) {
397399ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
397499ebb4caSwyllys 			retry++;
397599ebb4caSwyllys 		}
397699ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
397799ebb4caSwyllys 
397899ebb4caSwyllys 	if (ret != KMF_OK) {
397999ebb4caSwyllys 		goto out;
398099ebb4caSwyllys 	}
398199ebb4caSwyllys 
398299ebb4caSwyllys 	/*
398399ebb4caSwyllys 	 * Create the 3rd DES key and make sure its value is different
398499ebb4caSwyllys 	 * from the 2nd DES key.
398599ebb4caSwyllys 	 */
398699ebb4caSwyllys 	retry = 0;
398799ebb4caSwyllys 	do {
398899ebb4caSwyllys 		if (deskey3 != NULL) {
398999ebb4caSwyllys 			free(deskey3);
399099ebb4caSwyllys 			deskey3 = NULL;
399199ebb4caSwyllys 		}
399299ebb4caSwyllys 
399399ebb4caSwyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
399499ebb4caSwyllys 			goto out;
399599ebb4caSwyllys 		}
399699ebb4caSwyllys 
399799ebb4caSwyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
399899ebb4caSwyllys 		    == 0) {
399999ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
400099ebb4caSwyllys 			retry++;
400199ebb4caSwyllys 		}
400299ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
400399ebb4caSwyllys 
400499ebb4caSwyllys 	if (ret != KMF_OK) {
400599ebb4caSwyllys 		goto out;
400699ebb4caSwyllys 	}
400799ebb4caSwyllys 
400899ebb4caSwyllys 	/* Concatenate 3 DES keys into a DES3 key */
400999ebb4caSwyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
401099ebb4caSwyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
401199ebb4caSwyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
401299ebb4caSwyllys 	*des3key = newkey;
401399ebb4caSwyllys 
401499ebb4caSwyllys out:
401599ebb4caSwyllys 	if (deskey1 != NULL)
401699ebb4caSwyllys 		free(deskey1);
401799ebb4caSwyllys 
401899ebb4caSwyllys 	if (deskey2 != NULL)
401999ebb4caSwyllys 		free(deskey2);
402099ebb4caSwyllys 
402199ebb4caSwyllys 	if (deskey3 != NULL)
402299ebb4caSwyllys 		free(deskey3);
402399ebb4caSwyllys 
402499ebb4caSwyllys 	if (ret != KMF_OK && newkey != NULL)
402599ebb4caSwyllys 		free(newkey);
402699ebb4caSwyllys 
402799ebb4caSwyllys 	return (ret);
402899ebb4caSwyllys }
402999ebb4caSwyllys 
403099ebb4caSwyllys KMF_RETURN
4031*30a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
4032*30a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
403399ebb4caSwyllys {
403499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
403599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
403699ebb4caSwyllys 	char *fullpath = NULL;
403799ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
403899ebb4caSwyllys 	DES_cblock *deskey = NULL;
403999ebb4caSwyllys 	unsigned char *des3key = NULL;
404099ebb4caSwyllys 	unsigned char *random = NULL;
404199ebb4caSwyllys 	int fd = -1;
4042*30a5e8faSwyllys 	KMF_KEY_HANDLE *symkey;
4043*30a5e8faSwyllys 	KMF_KEY_ALG keytype;
4044*30a5e8faSwyllys 	uint32_t keylen;
4045*30a5e8faSwyllys 	uint32_t keylen_size = sizeof (keylen);
4046*30a5e8faSwyllys 	char *dirpath;
4047*30a5e8faSwyllys 	char *keyfile;
404899ebb4caSwyllys 
404999ebb4caSwyllys 	if (kmfh == NULL)
405099ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
405199ebb4caSwyllys 
4052*30a5e8faSwyllys 	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
4053*30a5e8faSwyllys 	if (symkey == NULL)
405499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
405599ebb4caSwyllys 
4056*30a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4057*30a5e8faSwyllys 
4058*30a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
4059*30a5e8faSwyllys 	if (keyfile == NULL)
4060*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
4061*30a5e8faSwyllys 
4062*30a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
4063*30a5e8faSwyllys 	    (void *)&keytype, NULL);
4064*30a5e8faSwyllys 	if (ret != KMF_OK)
4065*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
4066*30a5e8faSwyllys 
4067*30a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
4068*30a5e8faSwyllys 	    &keylen, &keylen_size);
4069*30a5e8faSwyllys 	if (ret == KMF_ERR_ATTR_NOT_FOUND &&
4070*30a5e8faSwyllys 	    (keytype == KMF_DES || keytype == KMF_DES3))
4071*30a5e8faSwyllys 		/* keylength is not required for DES and 3DES */
4072*30a5e8faSwyllys 		ret = KMF_OK;
4073*30a5e8faSwyllys 	if (ret != KMF_OK)
4074*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
4075*30a5e8faSwyllys 
4076*30a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
407799ebb4caSwyllys 	if (fullpath == NULL)
407899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
407999ebb4caSwyllys 
408099ebb4caSwyllys 	/* If the requested file exists, return an error */
4081*30a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
408299ebb4caSwyllys 		free(fullpath);
408399ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
408499ebb4caSwyllys 	}
408599ebb4caSwyllys 
408699ebb4caSwyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
408799ebb4caSwyllys 	if (fd == -1) {
408899ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
408999ebb4caSwyllys 		goto out;
409099ebb4caSwyllys 	}
409199ebb4caSwyllys 
409299ebb4caSwyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
409399ebb4caSwyllys 	if (rkey == NULL) {
409499ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
409599ebb4caSwyllys 		goto out;
409699ebb4caSwyllys 	}
409799ebb4caSwyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
409899ebb4caSwyllys 
4099*30a5e8faSwyllys 	if (keytype == KMF_DES) {
410099ebb4caSwyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
410199ebb4caSwyllys 			goto out;
410299ebb4caSwyllys 		}
410399ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)deskey;
410499ebb4caSwyllys 		rkey->keydata.len = 8;
410599ebb4caSwyllys 
410699ebb4caSwyllys 		symkey->keyalg = KMF_DES;
410799ebb4caSwyllys 
4108*30a5e8faSwyllys 	} else if (keytype == KMF_DES3) {
410999ebb4caSwyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
411099ebb4caSwyllys 			goto out;
411199ebb4caSwyllys 		}
411299ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)des3key;
411399ebb4caSwyllys 		rkey->keydata.len = DES3_KEY_SIZE;
411499ebb4caSwyllys 		symkey->keyalg = KMF_DES3;
41159b37d296Swyllys 
4116*30a5e8faSwyllys 	} else if (keytype == KMF_AES || keytype == KMF_RC4 ||
4117*30a5e8faSwyllys 	    keytype == KMF_GENERIC_SECRET) {
411899ebb4caSwyllys 		int bytes;
411999ebb4caSwyllys 
4120*30a5e8faSwyllys 		if (keylen % 8 != 0) {
412199ebb4caSwyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
412299ebb4caSwyllys 			goto out;
412399ebb4caSwyllys 		}
412499ebb4caSwyllys 
4125*30a5e8faSwyllys 		if (keytype == KMF_AES) {
4126*30a5e8faSwyllys 			if (keylen != 128 &&
4127*30a5e8faSwyllys 			    keylen != 192 &&
4128*30a5e8faSwyllys 			    keylen != 256) {
412999ebb4caSwyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
413099ebb4caSwyllys 				goto out;
413199ebb4caSwyllys 			}
413299ebb4caSwyllys 		}
413399ebb4caSwyllys 
4134*30a5e8faSwyllys 		bytes = keylen/8;
413599ebb4caSwyllys 		random = malloc(bytes);
413699ebb4caSwyllys 		if (random == NULL) {
413799ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
413899ebb4caSwyllys 			goto out;
413999ebb4caSwyllys 		}
414099ebb4caSwyllys 		if (RAND_bytes(random, bytes) != 1) {
414199ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
414299ebb4caSwyllys 			goto out;
414399ebb4caSwyllys 		}
414499ebb4caSwyllys 
414599ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)random;
414699ebb4caSwyllys 		rkey->keydata.len = bytes;
4147*30a5e8faSwyllys 		symkey->keyalg = keytype;
414899ebb4caSwyllys 
414999ebb4caSwyllys 	} else {
415099ebb4caSwyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
415199ebb4caSwyllys 		goto out;
415299ebb4caSwyllys 	}
415399ebb4caSwyllys 
415499ebb4caSwyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
415599ebb4caSwyllys 
415699ebb4caSwyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
415799ebb4caSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
415899ebb4caSwyllys 	symkey->keylabel = (char *)fullpath;
415999ebb4caSwyllys 	symkey->israw = TRUE;
416099ebb4caSwyllys 	symkey->keyp = rkey;
416199ebb4caSwyllys 
416299ebb4caSwyllys out:
416399ebb4caSwyllys 	if (fd != -1)
416499ebb4caSwyllys 		(void) close(fd);
416599ebb4caSwyllys 
416699ebb4caSwyllys 	if (ret != KMF_OK && fullpath != NULL) {
416799ebb4caSwyllys 		free(fullpath);
416899ebb4caSwyllys 	}
416999ebb4caSwyllys 	if (ret != KMF_OK) {
4170*30a5e8faSwyllys 		kmf_free_raw_sym_key(rkey);
417199ebb4caSwyllys 		symkey->keyp = NULL;
417299ebb4caSwyllys 		symkey->keyalg = KMF_KEYALG_NONE;
417399ebb4caSwyllys 	}
417499ebb4caSwyllys 
417599ebb4caSwyllys 	return (ret);
417699ebb4caSwyllys }
417799ebb4caSwyllys 
417899ebb4caSwyllys /*
417999ebb4caSwyllys  * Check a file to see if it is a CRL file with PEM or DER format.
418099ebb4caSwyllys  * If success, return its format in the "pformat" argument.
418199ebb4caSwyllys  */
418299ebb4caSwyllys KMF_RETURN
418399ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
418499ebb4caSwyllys {
418599ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
418699ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
418799ebb4caSwyllys 	BIO		*bio = NULL;
418899ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
418999ebb4caSwyllys 
419099ebb4caSwyllys 	if (filename == NULL) {
419199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
419299ebb4caSwyllys 	}
419399ebb4caSwyllys 
419499ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
419599ebb4caSwyllys 	if (bio == NULL)	{
419699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
419799ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
419899ebb4caSwyllys 		goto out;
419999ebb4caSwyllys 	}
420099ebb4caSwyllys 
420199ebb4caSwyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
420299ebb4caSwyllys 		*pformat = KMF_FORMAT_PEM;
420399ebb4caSwyllys 		goto out;
420499ebb4caSwyllys 	}
420599ebb4caSwyllys 	(void) BIO_free(bio);
420699ebb4caSwyllys 
420799ebb4caSwyllys 	/*
420899ebb4caSwyllys 	 * Now try to read it as raw DER data.
420999ebb4caSwyllys 	 */
421099ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
421199ebb4caSwyllys 	if (bio == NULL)	{
421299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
421399ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
421499ebb4caSwyllys 		goto out;
421599ebb4caSwyllys 	}
421699ebb4caSwyllys 
421799ebb4caSwyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
421899ebb4caSwyllys 		*pformat = KMF_FORMAT_ASN1;
421999ebb4caSwyllys 	} else {
422099ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
422199ebb4caSwyllys 	}
422299ebb4caSwyllys 
422399ebb4caSwyllys out:
422499ebb4caSwyllys 	if (bio != NULL)
422599ebb4caSwyllys 		(void) BIO_free(bio);
422699ebb4caSwyllys 
422799ebb4caSwyllys 	if (xcrl != NULL)
422899ebb4caSwyllys 		X509_CRL_free(xcrl);
422999ebb4caSwyllys 
423099ebb4caSwyllys 	return (ret);
423199ebb4caSwyllys }
423299ebb4caSwyllys 
423399ebb4caSwyllys /*
423499ebb4caSwyllys  * Check a file to see if it is a certficate file with PEM or DER format.
423599ebb4caSwyllys  * If success, return its format in the pformat argument.
423699ebb4caSwyllys  */
423799ebb4caSwyllys KMF_RETURN
423899ebb4caSwyllys OpenSSL_IsCertFile(KMF_HANDLE_T handle, char *filename,
423999ebb4caSwyllys 	KMF_ENCODE_FORMAT *pformat)
424099ebb4caSwyllys {
424199ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
424299ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
424399ebb4caSwyllys 	BIO		*bio = NULL;
424499ebb4caSwyllys 	X509		*xcert = NULL;
424599ebb4caSwyllys 
424699ebb4caSwyllys 	if (filename == NULL) {
424799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
424899ebb4caSwyllys 	}
424999ebb4caSwyllys 
4250*30a5e8faSwyllys 	ret = kmf_get_file_format(filename, pformat);
425199ebb4caSwyllys 	if (ret != KMF_OK)
425299ebb4caSwyllys 		return (ret);
425399ebb4caSwyllys 
425499ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
425599ebb4caSwyllys 	if (bio == NULL)	{
425699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
425799ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
425899ebb4caSwyllys 		goto out;
425999ebb4caSwyllys 	}
426099ebb4caSwyllys 
426199ebb4caSwyllys 	if ((*pformat) == KMF_FORMAT_PEM) {
426299ebb4caSwyllys 		if ((xcert = PEM_read_bio_X509(bio, NULL,
426399ebb4caSwyllys 		    NULL, NULL)) == NULL) {
426499ebb4caSwyllys 			ret = KMF_ERR_BAD_CERTFILE;
426599ebb4caSwyllys 		}
426699ebb4caSwyllys 	} else if ((*pformat) == KMF_FORMAT_ASN1) {
426799ebb4caSwyllys 		if ((xcert = d2i_X509_bio(bio, NULL)) == NULL) {
426899ebb4caSwyllys 			ret = KMF_ERR_BAD_CERTFILE;
426999ebb4caSwyllys 		}
427099ebb4caSwyllys 	} else {
427199ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
427299ebb4caSwyllys 	}
427399ebb4caSwyllys 
427499ebb4caSwyllys out:
427599ebb4caSwyllys 	if (bio != NULL)
427699ebb4caSwyllys 		(void) BIO_free(bio);
427799ebb4caSwyllys 
427899ebb4caSwyllys 	if (xcert != NULL)
427999ebb4caSwyllys 		X509_free(xcert);
428099ebb4caSwyllys 
428199ebb4caSwyllys 	return (ret);
428299ebb4caSwyllys }
428399ebb4caSwyllys 
428499ebb4caSwyllys KMF_RETURN
428599ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
428699ebb4caSwyllys     KMF_RAW_SYM_KEY *rkey)
428799ebb4caSwyllys {
428899ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
428999ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
429099ebb4caSwyllys 	KMF_DATA	keyvalue;
429199ebb4caSwyllys 
429299ebb4caSwyllys 	if (kmfh == NULL)
429399ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
429499ebb4caSwyllys 
429599ebb4caSwyllys 	if (symkey == NULL || rkey == NULL)
429699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
429799ebb4caSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
429899ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
429999ebb4caSwyllys 
430099ebb4caSwyllys 	if (symkey->israw) {
430199ebb4caSwyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
430299ebb4caSwyllys 
430399ebb4caSwyllys 		if (rawkey == NULL ||
430499ebb4caSwyllys 		    rawkey->keydata.val == NULL ||
430599ebb4caSwyllys 		    rawkey->keydata.len == 0)
430699ebb4caSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
430799ebb4caSwyllys 
430899ebb4caSwyllys 		rkey->keydata.len = rawkey->keydata.len;
430999ebb4caSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
431099ebb4caSwyllys 			return (KMF_ERR_MEMORY);
431199ebb4caSwyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
431299ebb4caSwyllys 		    rkey->keydata.len);
431399ebb4caSwyllys 	} else {
4314*30a5e8faSwyllys 		rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
431599ebb4caSwyllys 		if (rv != KMF_OK)
431699ebb4caSwyllys 			return (rv);
431799ebb4caSwyllys 		rkey->keydata.len = keyvalue.Length;
431899ebb4caSwyllys 		rkey->keydata.val = keyvalue.Data;
431999ebb4caSwyllys 	}
432099ebb4caSwyllys 
432199ebb4caSwyllys 	return (rv);
432299ebb4caSwyllys }
432302744e81Swyllys 
432402744e81Swyllys /*
432502744e81Swyllys  * id-sha1    OBJECT IDENTIFIER ::= {
432602744e81Swyllys  *     iso(1) identified-organization(3) oiw(14) secsig(3)
432702744e81Swyllys  *     algorithms(2) 26
432802744e81Swyllys  * }
432902744e81Swyllys  */
433002744e81Swyllys #define	ASN1_SHA1_OID_PREFIX_LEN 15
433102744e81Swyllys static uchar_t SHA1_DER_PREFIX[ASN1_SHA1_OID_PREFIX_LEN] = {
433202744e81Swyllys 	0x30, 0x21, 0x30, 0x09,
433302744e81Swyllys 	0x06, 0x05, 0x2b, 0x0e,
433402744e81Swyllys 	0x03, 0x02, 0x1a, 0x05,
433502744e81Swyllys 	0x00, 0x04, 0x14
433602744e81Swyllys };
433702744e81Swyllys 
433802744e81Swyllys /*
433902744e81Swyllys  * id-md2 OBJECT IDENTIFIER ::= {
434002744e81Swyllys  *     iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2
434102744e81Swyllys  * }
434202744e81Swyllys  */
434302744e81Swyllys #define	ASN1_MD2_OID_PREFIX_LEN 18
434402744e81Swyllys static uchar_t MD2_DER_PREFIX[ASN1_MD2_OID_PREFIX_LEN] = {
434502744e81Swyllys 	0x30, 0x20, 0x30, 0x0c,
434602744e81Swyllys 	0x06, 0x08, 0x2a, 0x86,
434702744e81Swyllys 	0x48, 0x86, 0xf7, 0x0d,
434802744e81Swyllys 	0x02, 0x02, 0x05, 0x00,
434902744e81Swyllys 	0x04, 0x10
435002744e81Swyllys };
435102744e81Swyllys 
435202744e81Swyllys /*
435302744e81Swyllys  * id-md5 OBJECT IDENTIFIER ::= {
435402744e81Swyllys  *     iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5
435502744e81Swyllys  * }
435602744e81Swyllys  */
435702744e81Swyllys #define	ASN1_MD5_OID_PREFIX_LEN 18
435802744e81Swyllys static uchar_t MD5_DER_PREFIX[ASN1_MD5_OID_PREFIX_LEN] = {
435902744e81Swyllys 	0x30, 0x20, 0x30, 0x0c,
436002744e81Swyllys 	0x06, 0x08, 0x2a, 0x86,
436102744e81Swyllys 	0x48, 0x86, 0xf7, 0x0d,
436202744e81Swyllys 	0x02, 0x05, 0x05, 0x00,
436302744e81Swyllys 	0x04, 0x10
436402744e81Swyllys };
436502744e81Swyllys 
436602744e81Swyllys KMF_RETURN
436702744e81Swyllys OpenSSL_VerifyDataWithCert(KMF_HANDLE_T handle,
436802744e81Swyllys 	KMF_ALGORITHM_INDEX algid, KMF_DATA *indata,
436902744e81Swyllys 	KMF_DATA *insig, KMF_DATA *cert)
437002744e81Swyllys {
437102744e81Swyllys 	KMF_RETURN ret = KMF_OK;
437202744e81Swyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
437302744e81Swyllys 	X509	*xcert = NULL;
437402744e81Swyllys 	EVP_PKEY *pkey = NULL;
437502744e81Swyllys 	uchar_t *p;
437602744e81Swyllys 	uchar_t *rsaout = NULL;
437702744e81Swyllys 	uchar_t *pfx = NULL;
437802744e81Swyllys 	const EVP_MD *md;
437902744e81Swyllys 	int pfxlen = 0, len;
438002744e81Swyllys 
438102744e81Swyllys 	if (handle == NULL || indata == NULL ||
438202744e81Swyllys 	    indata->Data == NULL || indata->Length == 0 ||
438302744e81Swyllys 	    insig == NULL|| insig->Data == NULL || insig->Length == 0 ||
438402744e81Swyllys 	    cert == NULL || cert->Data == NULL || cert->Length == 0)
438502744e81Swyllys 		return (KMF_ERR_BAD_PARAMETER);
438602744e81Swyllys 
438702744e81Swyllys 	p = cert->Data;
438802744e81Swyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, cert->Length);
438902744e81Swyllys 	if (xcert == NULL) {
439002744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
439102744e81Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
439202744e81Swyllys 		goto cleanup;
439302744e81Swyllys 	}
439402744e81Swyllys 
439502744e81Swyllys 	pkey = X509_get_pubkey(xcert);
4396*30a5e8faSwyllys 	if (pkey == NULL) {
439702744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
439802744e81Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
439902744e81Swyllys 		goto cleanup;
440002744e81Swyllys 	}
440102744e81Swyllys 
440202744e81Swyllys 	if (algid != KMF_ALGID_NONE) {
440302744e81Swyllys 		switch (algid) {
440402744e81Swyllys 			case KMF_ALGID_MD5WithRSA:
440502744e81Swyllys 				md = EVP_md5();
440602744e81Swyllys 				break;
440702744e81Swyllys 			case KMF_ALGID_MD2WithRSA:
440802744e81Swyllys 				md = EVP_md2();
440902744e81Swyllys 				break;
441002744e81Swyllys 			case KMF_ALGID_SHA1WithRSA:
441102744e81Swyllys 				md = EVP_sha1();
441202744e81Swyllys 				break;
441302744e81Swyllys 			case KMF_ALGID_RSA:
441402744e81Swyllys 				md = NULL;
441502744e81Swyllys 				break;
441602744e81Swyllys 			default:
441702744e81Swyllys 				ret = KMF_ERR_BAD_PARAMETER;
441802744e81Swyllys 				goto cleanup;
441902744e81Swyllys 		}
442002744e81Swyllys 	} else {
442102744e81Swyllys 		/* Get the hash type from the cert signature */
442202744e81Swyllys 		md = EVP_get_digestbyobj(xcert->sig_alg->algorithm);
442302744e81Swyllys 		if (md == NULL) {
442402744e81Swyllys 			SET_ERROR(kmfh, ERR_get_error());
442502744e81Swyllys 			ret = KMF_ERR_BAD_PARAMETER;
442602744e81Swyllys 			goto cleanup;
442702744e81Swyllys 		}
442802744e81Swyllys 	}
44299b37d296Swyllys 	if (md != NULL) {
443002744e81Swyllys 		switch (EVP_MD_type(md)) {
443102744e81Swyllys 		case NID_md2:
443202744e81Swyllys 		case NID_md2WithRSAEncryption:
443302744e81Swyllys 			pfxlen = ASN1_MD2_OID_PREFIX_LEN;
443402744e81Swyllys 			pfx = MD2_DER_PREFIX;
443502744e81Swyllys 			break;
443602744e81Swyllys 		case NID_md5:
443702744e81Swyllys 		case NID_md5WithRSAEncryption:
443802744e81Swyllys 			pfxlen = ASN1_MD5_OID_PREFIX_LEN;
443902744e81Swyllys 			pfx = MD5_DER_PREFIX;
444002744e81Swyllys 			break;
444102744e81Swyllys 		case NID_sha1:
444202744e81Swyllys 		case NID_sha1WithRSAEncryption:
444302744e81Swyllys 			pfxlen = ASN1_SHA1_OID_PREFIX_LEN;
444402744e81Swyllys 			pfx = SHA1_DER_PREFIX;
444502744e81Swyllys 			break;
444602744e81Swyllys 		default: /* Unsupported */
444702744e81Swyllys 			pfxlen = 0;
444802744e81Swyllys 			pfx = NULL;
444902744e81Swyllys 			break;
445002744e81Swyllys 		}
44519b37d296Swyllys 	}
445202744e81Swyllys 
445302744e81Swyllys 	/* RSA with no hash is a special case */
445402744e81Swyllys 	rsaout = malloc(RSA_size(pkey->pkey.rsa));
445502744e81Swyllys 	if (rsaout == NULL)
445602744e81Swyllys 		return (KMF_ERR_MEMORY);
445702744e81Swyllys 
445802744e81Swyllys 	/* Decrypt the input signature */
445902744e81Swyllys 	len = RSA_public_decrypt(insig->Length,
446002744e81Swyllys 	    insig->Data, rsaout, pkey->pkey.rsa, RSA_PKCS1_PADDING);
446102744e81Swyllys 	if (len < 1) {
446202744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
446302744e81Swyllys 		ret = KMF_ERR_BAD_PARAMETER;
446402744e81Swyllys 	} else {
446502744e81Swyllys 		size_t hashlen = 0;
446602744e81Swyllys 		uint32_t dlen;
446702744e81Swyllys 		char *digest = NULL;
446802744e81Swyllys 
446902744e81Swyllys 		/*
447002744e81Swyllys 		 * If the AlgId requires it, hash the input data before
447102744e81Swyllys 		 * comparing it to the decrypted signature.
447202744e81Swyllys 		 */
447302744e81Swyllys 		if (md) {
447402744e81Swyllys 			EVP_MD_CTX ctx;
447502744e81Swyllys 
447602744e81Swyllys 			hashlen = md->md_size;
447702744e81Swyllys 
447802744e81Swyllys 			digest = malloc(hashlen + pfxlen);
447902744e81Swyllys 			if (digest == NULL)
448002744e81Swyllys 				return (KMF_ERR_MEMORY);
448102744e81Swyllys 			/* Add the prefix to the comparison buffer. */
448202744e81Swyllys 			if (pfx && pfxlen > 0) {
448302744e81Swyllys 				(void) memcpy(digest, pfx, pfxlen);
448402744e81Swyllys 			}
448502744e81Swyllys 			(void) EVP_DigestInit(&ctx, md);
448602744e81Swyllys 			(void) EVP_DigestUpdate(&ctx, indata->Data,
448702744e81Swyllys 			    indata->Length);
448802744e81Swyllys 
448902744e81Swyllys 			/* Add the digest AFTER the ASN1 prefix */
449002744e81Swyllys 			(void) EVP_DigestFinal(&ctx,
449102744e81Swyllys 			    (uchar_t *)digest + pfxlen, &dlen);
449202744e81Swyllys 
449302744e81Swyllys 			dlen += pfxlen;
449402744e81Swyllys 		} else {
449502744e81Swyllys 			digest = (char *)indata->Data;
449602744e81Swyllys 			dlen = indata->Length;
449702744e81Swyllys 		}
449802744e81Swyllys 
449902744e81Swyllys 		/*
450002744e81Swyllys 		 * The result of the RSA decryption should be ASN1(OID | Hash).
450102744e81Swyllys 		 * Compare the output hash to the input data for the final
450202744e81Swyllys 		 * result.
450302744e81Swyllys 		 */
450402744e81Swyllys 		if (memcmp(rsaout, digest, dlen))
450502744e81Swyllys 			ret = KMF_ERR_INTERNAL;
450602744e81Swyllys 		else
450702744e81Swyllys 			ret = KMF_OK;
450802744e81Swyllys 
450902744e81Swyllys 		/* If we had to allocate space for the digest, free it now */
451002744e81Swyllys 		if (hashlen)
451102744e81Swyllys 			free(digest);
451202744e81Swyllys 	}
451302744e81Swyllys cleanup:
451402744e81Swyllys 	if (pkey)
451502744e81Swyllys 		EVP_PKEY_free(pkey);
451602744e81Swyllys 
451702744e81Swyllys 	if (xcert)
451802744e81Swyllys 		X509_free(xcert);
451902744e81Swyllys 
452002744e81Swyllys 	if (rsaout)
452102744e81Swyllys 		free(rsaout);
452202744e81Swyllys 
452302744e81Swyllys 	return (ret);
452402744e81Swyllys }
4525*30a5e8faSwyllys 
4526*30a5e8faSwyllys /*
4527*30a5e8faSwyllys  * substitute for the unsafe access(2) function.
4528*30a5e8faSwyllys  * If the file in question already exists, return 1.
4529*30a5e8faSwyllys  * else 0.  If an error occurs during testing (other
4530*30a5e8faSwyllys  * than EEXIST), return -1.
4531*30a5e8faSwyllys  */
4532*30a5e8faSwyllys static int
4533*30a5e8faSwyllys test_for_file(char *filename, mode_t mode)
4534*30a5e8faSwyllys {
4535*30a5e8faSwyllys 	int fd;
4536*30a5e8faSwyllys 
4537*30a5e8faSwyllys 	/*
4538*30a5e8faSwyllys 	 * Try to create the file with the EXCL flag.
4539*30a5e8faSwyllys 	 * The call should fail if the file exists.
4540*30a5e8faSwyllys 	 */
4541*30a5e8faSwyllys 	fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
4542*30a5e8faSwyllys 	if (fd == -1 && errno == EEXIST)
4543*30a5e8faSwyllys 		return (1);
4544*30a5e8faSwyllys 	else if (fd == -1) /* some other error */
4545*30a5e8faSwyllys 		return (-1);
4546*30a5e8faSwyllys 
4547*30a5e8faSwyllys 	/* The file did NOT exist.  Delete the testcase. */
4548*30a5e8faSwyllys 	(void) close(fd);
4549*30a5e8faSwyllys 	(void) unlink(filename);
4550*30a5e8faSwyllys 	return (0);
4551*30a5e8faSwyllys }
4552*30a5e8faSwyllys 
4553*30a5e8faSwyllys KMF_RETURN
4554*30a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
4555*30a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
4556*30a5e8faSwyllys {
4557*30a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
4558*30a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
4559*30a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
4560*30a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
4561*30a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
4562*30a5e8faSwyllys 	KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
4563*30a5e8faSwyllys 	KMF_CREDENTIAL cred = {NULL, 0};
4564*30a5e8faSwyllys 	BIO *out = NULL;
4565*30a5e8faSwyllys 	int keys = 0;
4566*30a5e8faSwyllys 	char *fullpath = NULL;
4567*30a5e8faSwyllys 	char *keyfile = NULL;
4568*30a5e8faSwyllys 	char *dirpath = NULL;
4569*30a5e8faSwyllys 
4570*30a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
4571*30a5e8faSwyllys 	if (pubkey != NULL)
4572*30a5e8faSwyllys 		keys++;
4573*30a5e8faSwyllys 
4574*30a5e8faSwyllys 	prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
4575*30a5e8faSwyllys 	if (prikey != NULL)
4576*30a5e8faSwyllys 		keys++;
4577*30a5e8faSwyllys 
4578*30a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
4579*30a5e8faSwyllys 	if (rawkey != NULL)
4580*30a5e8faSwyllys 		keys++;
4581*30a5e8faSwyllys 
4582*30a5e8faSwyllys 	/*
4583*30a5e8faSwyllys 	 * Exactly 1 type of key must be passed to this function.
4584*30a5e8faSwyllys 	 */
4585*30a5e8faSwyllys 	if (keys != 1)
4586*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
4587*30a5e8faSwyllys 
4588*30a5e8faSwyllys 	keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
4589*30a5e8faSwyllys 	    numattr);
4590*30a5e8faSwyllys 	if (keyfile == NULL)
4591*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
4592*30a5e8faSwyllys 
4593*30a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4594*30a5e8faSwyllys 
4595*30a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
4596*30a5e8faSwyllys 
4597*30a5e8faSwyllys 	/* Once we have the full path, we don't need the pieces */
4598*30a5e8faSwyllys 	if (fullpath == NULL)
4599*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
4600*30a5e8faSwyllys 
4601*30a5e8faSwyllys 	/* If the requested file exists, return an error */
4602*30a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
4603*30a5e8faSwyllys 		free(fullpath);
4604*30a5e8faSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
4605*30a5e8faSwyllys 	}
4606*30a5e8faSwyllys 
4607*30a5e8faSwyllys 	rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
4608*30a5e8faSwyllys 	    &format, NULL);
4609*30a5e8faSwyllys 	if (rv != KMF_OK)
4610*30a5e8faSwyllys 		/* format is optional. */
4611*30a5e8faSwyllys 		rv = KMF_OK;
4612*30a5e8faSwyllys 
4613*30a5e8faSwyllys 	/* CRED is not required for OpenSSL files */
4614*30a5e8faSwyllys 	(void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
4615*30a5e8faSwyllys 	    &cred, NULL);
4616*30a5e8faSwyllys 
4617*30a5e8faSwyllys 	/* Store the private key to the keyfile */
4618*30a5e8faSwyllys 	out = BIO_new_file(fullpath, "wb");
4619*30a5e8faSwyllys 	if (out == NULL) {
4620*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
4621*30a5e8faSwyllys 		rv = KMF_ERR_OPEN_FILE;
4622*30a5e8faSwyllys 		goto end;
4623*30a5e8faSwyllys 	}
4624*30a5e8faSwyllys 
4625*30a5e8faSwyllys 	if (prikey != NULL && prikey->keyp != NULL) {
4626*30a5e8faSwyllys 		if (prikey->keyalg == KMF_RSA ||
4627*30a5e8faSwyllys 		    prikey->keyalg == KMF_DSA) {
4628*30a5e8faSwyllys 			pkey = (EVP_PKEY *)prikey->keyp;
4629*30a5e8faSwyllys 
4630*30a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
4631*30a5e8faSwyllys 			    out, &cred, pkey, TRUE);
4632*30a5e8faSwyllys 
4633*30a5e8faSwyllys 			if (rv == KMF_OK && prikey->keylabel == NULL) {
4634*30a5e8faSwyllys 				prikey->keylabel = strdup(fullpath);
4635*30a5e8faSwyllys 				if (prikey->keylabel == NULL)
4636*30a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
4637*30a5e8faSwyllys 			}
4638*30a5e8faSwyllys 		}
4639*30a5e8faSwyllys 	} else if (pubkey != NULL && pubkey->keyp != NULL) {
4640*30a5e8faSwyllys 		if (pubkey->keyalg == KMF_RSA ||
4641*30a5e8faSwyllys 		    pubkey->keyalg == KMF_DSA) {
4642*30a5e8faSwyllys 			pkey = (EVP_PKEY *)pubkey->keyp;
4643*30a5e8faSwyllys 
4644*30a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
4645*30a5e8faSwyllys 			    out, &cred, pkey, FALSE);
4646*30a5e8faSwyllys 
4647*30a5e8faSwyllys 			if (rv == KMF_OK && pubkey->keylabel == NULL) {
4648*30a5e8faSwyllys 				pubkey->keylabel = strdup(fullpath);
4649*30a5e8faSwyllys 				if (pubkey->keylabel == NULL)
4650*30a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
4651*30a5e8faSwyllys 			}
4652*30a5e8faSwyllys 		}
4653*30a5e8faSwyllys 	} else if (rawkey != NULL) {
4654*30a5e8faSwyllys 		/* RAW keys are always private */
4655*30a5e8faSwyllys 		if (rawkey->keytype == KMF_RSA) {
4656*30a5e8faSwyllys 			pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
4657*30a5e8faSwyllys 		} else if (rawkey->keytype == KMF_DSA) {
4658*30a5e8faSwyllys 			pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
4659*30a5e8faSwyllys 		} else {
4660*30a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
4661*30a5e8faSwyllys 		}
4662*30a5e8faSwyllys 		rv = ssl_write_key(kmfh, format, out, &cred, pkey, TRUE);
4663*30a5e8faSwyllys 	}
4664*30a5e8faSwyllys 
4665*30a5e8faSwyllys end:
4666*30a5e8faSwyllys 
4667*30a5e8faSwyllys 	if (out)
4668*30a5e8faSwyllys 		(void) BIO_free(out);
4669*30a5e8faSwyllys 
4670*30a5e8faSwyllys 	if (rv == KMF_OK)
4671*30a5e8faSwyllys 		(void) chmod(fullpath, 0400);
4672*30a5e8faSwyllys 
4673*30a5e8faSwyllys 	free(fullpath);
4674*30a5e8faSwyllys 	return (rv);
4675*30a5e8faSwyllys }
4676*30a5e8faSwyllys 
4677*30a5e8faSwyllys KMF_RETURN
4678*30a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
4679*30a5e8faSwyllys {
4680*30a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
4681*30a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4682*30a5e8faSwyllys 	X509_CRL *xcrl = NULL;
4683*30a5e8faSwyllys 	X509 *xcert = NULL;
4684*30a5e8faSwyllys 	EVP_PKEY *pkey;
4685*30a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
4686*30a5e8faSwyllys 	BIO *in = NULL, *out = NULL;
4687*30a5e8faSwyllys 	int openssl_ret = 0;
4688*30a5e8faSwyllys 	KMF_ENCODE_FORMAT outformat;
4689*30a5e8faSwyllys 	boolean_t crlcheck = FALSE;
4690*30a5e8faSwyllys 	char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
4691*30a5e8faSwyllys 
4692*30a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
4693*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
4694*30a5e8faSwyllys 	}
4695*30a5e8faSwyllys 
4696*30a5e8faSwyllys 	/* CRL check is optional */
4697*30a5e8faSwyllys 	(void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
4698*30a5e8faSwyllys 	    &crlcheck, NULL);
4699*30a5e8faSwyllys 
4700*30a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
4701*30a5e8faSwyllys 	if (crlcheck == B_TRUE && certfile == NULL) {
4702*30a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
4703*30a5e8faSwyllys 	}
4704*30a5e8faSwyllys 
4705*30a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4706*30a5e8faSwyllys 	incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
4707*30a5e8faSwyllys 	outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
4708*30a5e8faSwyllys 
4709*30a5e8faSwyllys 	crlfile = get_fullpath(dirpath, incrl);
4710*30a5e8faSwyllys 
4711*30a5e8faSwyllys 	if (crlfile == NULL)
4712*30a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
4713*30a5e8faSwyllys 
4714*30a5e8faSwyllys 	outcrlfile = get_fullpath(dirpath, outcrl);
4715*30a5e8faSwyllys 	if (outcrlfile == NULL)
4716*30a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
4717*30a5e8faSwyllys 
4718*30a5e8faSwyllys 	if (isdir(outcrlfile)) {
4719*30a5e8faSwyllys 		free(outcrlfile);
4720*30a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
4721*30a5e8faSwyllys 	}
4722*30a5e8faSwyllys 
4723*30a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
4724*30a5e8faSwyllys 	if (ret != KMF_OK) {
4725*30a5e8faSwyllys 		free(outcrlfile);
4726*30a5e8faSwyllys 		return (ret);
4727*30a5e8faSwyllys 	}
4728*30a5e8faSwyllys 
4729*30a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
4730*30a5e8faSwyllys 	if (in == NULL)	{
4731*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
4732*30a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
4733*30a5e8faSwyllys 		goto end;
4734*30a5e8faSwyllys 	}
4735*30a5e8faSwyllys 
4736*30a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
4737*30a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
4738*30a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
4739*30a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
4740*30a5e8faSwyllys 	}
4741*30a5e8faSwyllys 
4742*30a5e8faSwyllys 	if (xcrl == NULL) {
4743*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
4744*30a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
4745*30a5e8faSwyllys 		goto end;
4746*30a5e8faSwyllys 	}
4747*30a5e8faSwyllys 
4748*30a5e8faSwyllys 	/* If bypasscheck is specified, no need to verify. */
4749*30a5e8faSwyllys 	if (crlcheck == B_FALSE)
4750*30a5e8faSwyllys 		goto output;
4751*30a5e8faSwyllys 
4752*30a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
4753*30a5e8faSwyllys 	if (ret != KMF_OK)
4754*30a5e8faSwyllys 		goto end;
4755*30a5e8faSwyllys 
4756*30a5e8faSwyllys 	/* Read in the CA cert file and convert to X509 */
4757*30a5e8faSwyllys 	if (BIO_read_filename(in, certfile) <= 0) {
4758*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
4759*30a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
4760*30a5e8faSwyllys 		goto end;
4761*30a5e8faSwyllys 	}
4762*30a5e8faSwyllys 
4763*30a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
4764*30a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
4765*30a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
4766*30a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
4767*30a5e8faSwyllys 	} else {
4768*30a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
4769*30a5e8faSwyllys 		goto end;
4770*30a5e8faSwyllys 	}
4771*30a5e8faSwyllys 
4772*30a5e8faSwyllys 	if (xcert == NULL) {
4773*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
4774*30a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
4775*30a5e8faSwyllys 		goto end;
4776*30a5e8faSwyllys 	}
4777*30a5e8faSwyllys 	/* Now get the public key from the CA cert */
4778*30a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
4779*30a5e8faSwyllys 	if (pkey == NULL) {
4780*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
4781*30a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
4782*30a5e8faSwyllys 		goto end;
4783*30a5e8faSwyllys 	}
4784*30a5e8faSwyllys 
4785*30a5e8faSwyllys 	/* Verify the CRL with the CA's public key */
4786*30a5e8faSwyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
4787*30a5e8faSwyllys 	EVP_PKEY_free(pkey);
4788*30a5e8faSwyllys 	if (openssl_ret > 0) {
4789*30a5e8faSwyllys 		ret = KMF_OK;  /* verify succeed */
4790*30a5e8faSwyllys 	} else {
4791*30a5e8faSwyllys 		SET_ERROR(kmfh, openssl_ret);
4792*30a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
4793*30a5e8faSwyllys 	}
4794*30a5e8faSwyllys 
4795*30a5e8faSwyllys output:
4796*30a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
4797*30a5e8faSwyllys 	    &outformat, NULL);
4798*30a5e8faSwyllys 	if (ret != KMF_OK) {
4799*30a5e8faSwyllys 		ret = KMF_OK;
4800*30a5e8faSwyllys 		outformat = KMF_FORMAT_PEM;
4801*30a5e8faSwyllys 	}
4802*30a5e8faSwyllys 
4803*30a5e8faSwyllys 	out = BIO_new_file(outcrlfile, "wb");
4804*30a5e8faSwyllys 	if (out == NULL) {
4805*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
4806*30a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
4807*30a5e8faSwyllys 		goto end;
4808*30a5e8faSwyllys 	}
4809*30a5e8faSwyllys 
4810*30a5e8faSwyllys 	if (outformat == KMF_FORMAT_ASN1) {
4811*30a5e8faSwyllys 		openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
4812*30a5e8faSwyllys 	} else if (outformat == KMF_FORMAT_PEM) {
4813*30a5e8faSwyllys 		openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
4814*30a5e8faSwyllys 	} else {
4815*30a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
4816*30a5e8faSwyllys 		goto end;
4817*30a5e8faSwyllys 	}
4818*30a5e8faSwyllys 
4819*30a5e8faSwyllys 	if (openssl_ret <= 0) {
4820*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
4821*30a5e8faSwyllys 		ret = KMF_ERR_WRITE_FILE;
4822*30a5e8faSwyllys 	} else {
4823*30a5e8faSwyllys 		ret = KMF_OK;
4824*30a5e8faSwyllys 	}
4825*30a5e8faSwyllys 
4826*30a5e8faSwyllys end:
4827*30a5e8faSwyllys 	if (xcrl != NULL)
4828*30a5e8faSwyllys 		X509_CRL_free(xcrl);
4829*30a5e8faSwyllys 
4830*30a5e8faSwyllys 	if (xcert != NULL)
4831*30a5e8faSwyllys 		X509_free(xcert);
4832*30a5e8faSwyllys 
4833*30a5e8faSwyllys 	if (in != NULL)
4834*30a5e8faSwyllys 		(void) BIO_free(in);
4835*30a5e8faSwyllys 
4836*30a5e8faSwyllys 	if (out != NULL)
4837*30a5e8faSwyllys 		(void) BIO_free(out);
4838*30a5e8faSwyllys 
4839*30a5e8faSwyllys 	if (outcrlfile != NULL)
4840*30a5e8faSwyllys 		free(outcrlfile);
4841*30a5e8faSwyllys 
4842*30a5e8faSwyllys 	return (ret);
4843*30a5e8faSwyllys }
4844*30a5e8faSwyllys 
4845*30a5e8faSwyllys KMF_RETURN
4846*30a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
4847*30a5e8faSwyllys {
4848*30a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
4849*30a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4850*30a5e8faSwyllys 	X509_CRL   *x = NULL;
4851*30a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
4852*30a5e8faSwyllys 	char *crlfile = NULL;
4853*30a5e8faSwyllys 	BIO *in = NULL;
4854*30a5e8faSwyllys 	BIO *mem = NULL;
4855*30a5e8faSwyllys 	long len;
4856*30a5e8faSwyllys 	char *memptr;
4857*30a5e8faSwyllys 	char *data = NULL;
4858*30a5e8faSwyllys 	char **crldata;
4859*30a5e8faSwyllys 	char *crlfilename, *dirpath;
4860*30a5e8faSwyllys 
4861*30a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
4862*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
4863*30a5e8faSwyllys 	}
4864*30a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
4865*30a5e8faSwyllys 	    attrlist, numattr);
4866*30a5e8faSwyllys 	if (crlfilename == NULL)
4867*30a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
4868*30a5e8faSwyllys 
4869*30a5e8faSwyllys 	crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
4870*30a5e8faSwyllys 	    attrlist, numattr);
4871*30a5e8faSwyllys 
4872*30a5e8faSwyllys 	if (crldata == NULL)
4873*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
4874*30a5e8faSwyllys 
4875*30a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4876*30a5e8faSwyllys 
4877*30a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
4878*30a5e8faSwyllys 
4879*30a5e8faSwyllys 	if (crlfile == NULL)
4880*30a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
4881*30a5e8faSwyllys 
4882*30a5e8faSwyllys 	if (isdir(crlfile)) {
4883*30a5e8faSwyllys 		free(crlfile);
4884*30a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
4885*30a5e8faSwyllys 	}
4886*30a5e8faSwyllys 
4887*30a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
4888*30a5e8faSwyllys 	if (ret != KMF_OK) {
4889*30a5e8faSwyllys 		free(crlfile);
4890*30a5e8faSwyllys 		return (ret);
4891*30a5e8faSwyllys 	}
4892*30a5e8faSwyllys 
4893*30a5e8faSwyllys 	if (bio_err == NULL)
4894*30a5e8faSwyllys 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
4895*30a5e8faSwyllys 
4896*30a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
4897*30a5e8faSwyllys 	if (in == NULL)	{
4898*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
4899*30a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
4900*30a5e8faSwyllys 		goto end;
4901*30a5e8faSwyllys 	}
4902*30a5e8faSwyllys 
4903*30a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
4904*30a5e8faSwyllys 		x = d2i_X509_CRL_bio(in, NULL);
4905*30a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
4906*30a5e8faSwyllys 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
4907*30a5e8faSwyllys 	}
4908*30a5e8faSwyllys 
4909*30a5e8faSwyllys 	if (x == NULL) { /* should not happen */
4910*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
4911*30a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
4912*30a5e8faSwyllys 		goto end;
4913*30a5e8faSwyllys 	}
4914*30a5e8faSwyllys 
4915*30a5e8faSwyllys 	mem = BIO_new(BIO_s_mem());
4916*30a5e8faSwyllys 	if (mem == NULL) {
4917*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
4918*30a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
4919*30a5e8faSwyllys 		goto end;
4920*30a5e8faSwyllys 	}
4921*30a5e8faSwyllys 
4922*30a5e8faSwyllys 	(void) X509_CRL_print(mem, x);
4923*30a5e8faSwyllys 	len = BIO_get_mem_data(mem, &memptr);
4924*30a5e8faSwyllys 	if (len <= 0) {
4925*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
4926*30a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
4927*30a5e8faSwyllys 		goto end;
4928*30a5e8faSwyllys 	}
4929*30a5e8faSwyllys 
4930*30a5e8faSwyllys 	data = malloc(len + 1);
4931*30a5e8faSwyllys 	if (data == NULL) {
4932*30a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
4933*30a5e8faSwyllys 		goto end;
4934*30a5e8faSwyllys 	}
4935*30a5e8faSwyllys 
4936*30a5e8faSwyllys 	(void) memcpy(data, memptr, len);
4937*30a5e8faSwyllys 	data[len] = '\0';
4938*30a5e8faSwyllys 	*crldata = data;
4939*30a5e8faSwyllys 
4940*30a5e8faSwyllys end:
4941*30a5e8faSwyllys 	if (x != NULL)
4942*30a5e8faSwyllys 		X509_CRL_free(x);
4943*30a5e8faSwyllys 
4944*30a5e8faSwyllys 	if (crlfile != NULL)
4945*30a5e8faSwyllys 		free(crlfile);
4946*30a5e8faSwyllys 
4947*30a5e8faSwyllys 	if (in != NULL)
4948*30a5e8faSwyllys 		(void) BIO_free(in);
4949*30a5e8faSwyllys 
4950*30a5e8faSwyllys 	if (mem != NULL)
4951*30a5e8faSwyllys 		(void) BIO_free(mem);
4952*30a5e8faSwyllys 
4953*30a5e8faSwyllys 	return (ret);
4954*30a5e8faSwyllys }
4955*30a5e8faSwyllys 
4956*30a5e8faSwyllys KMF_RETURN
4957*30a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
4958*30a5e8faSwyllys {
4959*30a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
4960*30a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4961*30a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
4962*30a5e8faSwyllys 	char *crlfile = NULL;
4963*30a5e8faSwyllys 	BIO *in = NULL;
4964*30a5e8faSwyllys 	char *crlfilename, *dirpath;
4965*30a5e8faSwyllys 
4966*30a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
4967*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
4968*30a5e8faSwyllys 	}
4969*30a5e8faSwyllys 
4970*30a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
4971*30a5e8faSwyllys 	    attrlist, numattr);
4972*30a5e8faSwyllys 
4973*30a5e8faSwyllys 	if (crlfilename == NULL)
4974*30a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
4975*30a5e8faSwyllys 
4976*30a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4977*30a5e8faSwyllys 
4978*30a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
4979*30a5e8faSwyllys 
4980*30a5e8faSwyllys 	if (crlfile == NULL)
4981*30a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
4982*30a5e8faSwyllys 
4983*30a5e8faSwyllys 	if (isdir(crlfile)) {
4984*30a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
4985*30a5e8faSwyllys 		goto end;
4986*30a5e8faSwyllys 	}
4987*30a5e8faSwyllys 
4988*30a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
4989*30a5e8faSwyllys 	if (ret != KMF_OK)
4990*30a5e8faSwyllys 		goto end;
4991*30a5e8faSwyllys 
4992*30a5e8faSwyllys 	if (unlink(crlfile) != 0) {
4993*30a5e8faSwyllys 		SET_SYS_ERROR(kmfh, errno);
4994*30a5e8faSwyllys 		ret = KMF_ERR_INTERNAL;
4995*30a5e8faSwyllys 		goto end;
4996*30a5e8faSwyllys 	}
4997*30a5e8faSwyllys 
4998*30a5e8faSwyllys end:
4999*30a5e8faSwyllys 	if (in != NULL)
5000*30a5e8faSwyllys 		(void) BIO_free(in);
5001*30a5e8faSwyllys 	if (crlfile != NULL)
5002*30a5e8faSwyllys 		free(crlfile);
5003*30a5e8faSwyllys 
5004*30a5e8faSwyllys 	return (ret);
5005*30a5e8faSwyllys }
5006*30a5e8faSwyllys 
5007*30a5e8faSwyllys KMF_RETURN
5008*30a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5009*30a5e8faSwyllys {
5010*30a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
5011*30a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5012*30a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
5013*30a5e8faSwyllys 	BIO *in = NULL;
5014*30a5e8faSwyllys 	X509   *xcert = NULL;
5015*30a5e8faSwyllys 	X509_CRL   *xcrl = NULL;
5016*30a5e8faSwyllys 	STACK_OF(X509_REVOKED) *revoke_stack = NULL;
5017*30a5e8faSwyllys 	X509_REVOKED *revoke;
5018*30a5e8faSwyllys 	int i;
5019*30a5e8faSwyllys 	char *crlfilename, *crlfile, *dirpath, *certfile;
5020*30a5e8faSwyllys 
5021*30a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
5022*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
5023*30a5e8faSwyllys 	}
5024*30a5e8faSwyllys 
5025*30a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5026*30a5e8faSwyllys 	    attrlist, numattr);
5027*30a5e8faSwyllys 
5028*30a5e8faSwyllys 	if (crlfilename == NULL)
5029*30a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
5030*30a5e8faSwyllys 
5031*30a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
5032*30a5e8faSwyllys 	if (certfile == NULL)
5033*30a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
5034*30a5e8faSwyllys 
5035*30a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5036*30a5e8faSwyllys 
5037*30a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
5038*30a5e8faSwyllys 
5039*30a5e8faSwyllys 	if (crlfile == NULL)
5040*30a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
5041*30a5e8faSwyllys 
5042*30a5e8faSwyllys 	if (isdir(crlfile)) {
5043*30a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
5044*30a5e8faSwyllys 		goto end;
5045*30a5e8faSwyllys 	}
5046*30a5e8faSwyllys 
5047*30a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
5048*30a5e8faSwyllys 	if (ret != KMF_OK)
5049*30a5e8faSwyllys 		goto end;
5050*30a5e8faSwyllys 
5051*30a5e8faSwyllys 	/* Read the CRL file and load it into a X509_CRL structure */
5052*30a5e8faSwyllys 	in = BIO_new_file(crlfilename, "rb");
5053*30a5e8faSwyllys 	if (in == NULL)	{
5054*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
5055*30a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
5056*30a5e8faSwyllys 		goto end;
5057*30a5e8faSwyllys 	}
5058*30a5e8faSwyllys 
5059*30a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
5060*30a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
5061*30a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
5062*30a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5063*30a5e8faSwyllys 	}
5064*30a5e8faSwyllys 
5065*30a5e8faSwyllys 	if (xcrl == NULL) {
5066*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
5067*30a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
5068*30a5e8faSwyllys 		goto end;
5069*30a5e8faSwyllys 	}
5070*30a5e8faSwyllys 	(void) BIO_free(in);
5071*30a5e8faSwyllys 
5072*30a5e8faSwyllys 	/* Read the Certificate file and load it into a X509 structure */
5073*30a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
5074*30a5e8faSwyllys 	if (ret != KMF_OK)
5075*30a5e8faSwyllys 		goto end;
5076*30a5e8faSwyllys 
5077*30a5e8faSwyllys 	in = BIO_new_file(certfile, "rb");
5078*30a5e8faSwyllys 	if (in == NULL)	{
5079*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
5080*30a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
5081*30a5e8faSwyllys 		goto end;
5082*30a5e8faSwyllys 	}
5083*30a5e8faSwyllys 
5084*30a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
5085*30a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
5086*30a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
5087*30a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
5088*30a5e8faSwyllys 	}
5089*30a5e8faSwyllys 
5090*30a5e8faSwyllys 	if (xcert == NULL) {
5091*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
5092*30a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
5093*30a5e8faSwyllys 		goto end;
5094*30a5e8faSwyllys 	}
5095*30a5e8faSwyllys 
5096*30a5e8faSwyllys 	/* Check if the certificate and the CRL have same issuer */
5097*30a5e8faSwyllys 	if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) {
5098*30a5e8faSwyllys 		ret = KMF_ERR_ISSUER;
5099*30a5e8faSwyllys 		goto end;
5100*30a5e8faSwyllys 	}
5101*30a5e8faSwyllys 
5102*30a5e8faSwyllys 	/* Check to see if the certificate serial number is revoked */
5103*30a5e8faSwyllys 	revoke_stack = X509_CRL_get_REVOKED(xcrl);
5104*30a5e8faSwyllys 	if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
5105*30a5e8faSwyllys 		/* No revoked certificates in the CRL file */
5106*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
5107*30a5e8faSwyllys 		ret = KMF_ERR_EMPTY_CRL;
5108*30a5e8faSwyllys 		goto end;
5109*30a5e8faSwyllys 	}
5110*30a5e8faSwyllys 
5111*30a5e8faSwyllys 	for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
5112*30a5e8faSwyllys 		/*LINTED*/
5113*30a5e8faSwyllys 		revoke = sk_X509_REVOKED_value(revoke_stack, i);
5114*30a5e8faSwyllys 		if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber,
5115*30a5e8faSwyllys 		    revoke->serialNumber) == 0) {
5116*30a5e8faSwyllys 			break;
5117*30a5e8faSwyllys 		}
5118*30a5e8faSwyllys 	}
5119*30a5e8faSwyllys 
5120*30a5e8faSwyllys 	if (i < sk_X509_REVOKED_num(revoke_stack)) {
5121*30a5e8faSwyllys 		ret = KMF_OK;
5122*30a5e8faSwyllys 	} else {
5123*30a5e8faSwyllys 		ret = KMF_ERR_NOT_REVOKED;
5124*30a5e8faSwyllys 	}
5125*30a5e8faSwyllys 
5126*30a5e8faSwyllys end:
5127*30a5e8faSwyllys 	if (in != NULL)
5128*30a5e8faSwyllys 		(void) BIO_free(in);
5129*30a5e8faSwyllys 	if (xcrl != NULL)
5130*30a5e8faSwyllys 		X509_CRL_free(xcrl);
5131*30a5e8faSwyllys 	if (xcert != NULL)
5132*30a5e8faSwyllys 		X509_free(xcert);
5133*30a5e8faSwyllys 
5134*30a5e8faSwyllys 	return (ret);
5135*30a5e8faSwyllys }
5136*30a5e8faSwyllys 
5137*30a5e8faSwyllys KMF_RETURN
5138*30a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
5139*30a5e8faSwyllys {
5140*30a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
5141*30a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
5142*30a5e8faSwyllys 	BIO		*bcrl = NULL;
5143*30a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
5144*30a5e8faSwyllys 	X509		*xcert = NULL;
5145*30a5e8faSwyllys 	EVP_PKEY	*pkey;
5146*30a5e8faSwyllys 	int		sslret;
5147*30a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
5148*30a5e8faSwyllys 	unsigned char	*p;
5149*30a5e8faSwyllys 	long		len;
5150*30a5e8faSwyllys 
5151*30a5e8faSwyllys 	if (handle == NULL || crlname == NULL || tacert == NULL) {
5152*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
5153*30a5e8faSwyllys 	}
5154*30a5e8faSwyllys 
5155*30a5e8faSwyllys 	ret = kmf_get_file_format(crlname, &crl_format);
5156*30a5e8faSwyllys 	if (ret != KMF_OK)
5157*30a5e8faSwyllys 		return (ret);
5158*30a5e8faSwyllys 
5159*30a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
5160*30a5e8faSwyllys 	if (bcrl == NULL)	{
5161*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
5162*30a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
5163*30a5e8faSwyllys 		goto cleanup;
5164*30a5e8faSwyllys 	}
5165*30a5e8faSwyllys 
5166*30a5e8faSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
5167*30a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
5168*30a5e8faSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
5169*30a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
5170*30a5e8faSwyllys 	} else {
5171*30a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
5172*30a5e8faSwyllys 		goto cleanup;
5173*30a5e8faSwyllys 	}
5174*30a5e8faSwyllys 
5175*30a5e8faSwyllys 	if (xcrl == NULL) {
5176*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
5177*30a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
5178*30a5e8faSwyllys 		goto cleanup;
5179*30a5e8faSwyllys 	}
5180*30a5e8faSwyllys 
5181*30a5e8faSwyllys 	p = tacert->Data;
5182*30a5e8faSwyllys 	len = tacert->Length;
5183*30a5e8faSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
5184*30a5e8faSwyllys 
5185*30a5e8faSwyllys 	if (xcert == NULL) {
5186*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
5187*30a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
5188*30a5e8faSwyllys 		goto cleanup;
5189*30a5e8faSwyllys 	}
5190*30a5e8faSwyllys 
5191*30a5e8faSwyllys 	/* Get issuer certificate public key */
5192*30a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
5193*30a5e8faSwyllys 	if (pkey == NULL) {
5194*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
5195*30a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
5196*30a5e8faSwyllys 		goto cleanup;
5197*30a5e8faSwyllys 	}
5198*30a5e8faSwyllys 
5199*30a5e8faSwyllys 	/* Verify CRL signature */
5200*30a5e8faSwyllys 	sslret = X509_CRL_verify(xcrl, pkey);
5201*30a5e8faSwyllys 	EVP_PKEY_free(pkey);
5202*30a5e8faSwyllys 	if (sslret > 0) {
5203*30a5e8faSwyllys 		ret = KMF_OK;
5204*30a5e8faSwyllys 	} else {
5205*30a5e8faSwyllys 		SET_ERROR(kmfh, sslret);
5206*30a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
5207*30a5e8faSwyllys 	}
5208*30a5e8faSwyllys 
5209*30a5e8faSwyllys cleanup:
5210*30a5e8faSwyllys 	if (bcrl != NULL)
5211*30a5e8faSwyllys 		(void) BIO_free(bcrl);
5212*30a5e8faSwyllys 
5213*30a5e8faSwyllys 	if (xcrl != NULL)
5214*30a5e8faSwyllys 		X509_CRL_free(xcrl);
5215*30a5e8faSwyllys 
5216*30a5e8faSwyllys 	if (xcert != NULL)
5217*30a5e8faSwyllys 		X509_free(xcert);
5218*30a5e8faSwyllys 
5219*30a5e8faSwyllys 	return (ret);
5220*30a5e8faSwyllys 
5221*30a5e8faSwyllys }
5222*30a5e8faSwyllys 
5223*30a5e8faSwyllys KMF_RETURN
5224*30a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
5225*30a5e8faSwyllys {
5226*30a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
5227*30a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
5228*30a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
5229*30a5e8faSwyllys 	BIO		*bcrl = NULL;
5230*30a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
5231*30a5e8faSwyllys 	int		i;
5232*30a5e8faSwyllys 
5233*30a5e8faSwyllys 	if (handle == NULL || crlname == NULL) {
5234*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
5235*30a5e8faSwyllys 	}
5236*30a5e8faSwyllys 
5237*30a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlname, &crl_format);
5238*30a5e8faSwyllys 	if (ret != KMF_OK)
5239*30a5e8faSwyllys 		return (ret);
5240*30a5e8faSwyllys 
5241*30a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
5242*30a5e8faSwyllys 	if (bcrl == NULL)	{
5243*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
5244*30a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
5245*30a5e8faSwyllys 		goto cleanup;
5246*30a5e8faSwyllys 	}
5247*30a5e8faSwyllys 
5248*30a5e8faSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
5249*30a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
5250*30a5e8faSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
5251*30a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
5252*30a5e8faSwyllys 	}
5253*30a5e8faSwyllys 
5254*30a5e8faSwyllys 	if (xcrl == NULL) {
5255*30a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
5256*30a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
5257*30a5e8faSwyllys 		goto cleanup;
5258*30a5e8faSwyllys 	}
5259*30a5e8faSwyllys 
5260*30a5e8faSwyllys 	i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL);
5261*30a5e8faSwyllys 	if (i >= 0) {
5262*30a5e8faSwyllys 		ret = KMF_ERR_VALIDITY_PERIOD;
5263*30a5e8faSwyllys 		goto cleanup;
5264*30a5e8faSwyllys 	}
5265*30a5e8faSwyllys 
5266*30a5e8faSwyllys 	if (X509_CRL_get_nextUpdate(xcrl)) {
5267*30a5e8faSwyllys 		i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL);
5268*30a5e8faSwyllys 
5269*30a5e8faSwyllys 		if (i <= 0) {
5270*30a5e8faSwyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
5271*30a5e8faSwyllys 			goto cleanup;
5272*30a5e8faSwyllys 		}
5273*30a5e8faSwyllys 	}
5274*30a5e8faSwyllys 
5275*30a5e8faSwyllys 	ret = KMF_OK;
5276*30a5e8faSwyllys 
5277*30a5e8faSwyllys cleanup:
5278*30a5e8faSwyllys 	if (bcrl != NULL)
5279*30a5e8faSwyllys 		(void) BIO_free(bcrl);
5280*30a5e8faSwyllys 
5281*30a5e8faSwyllys 	if (xcrl != NULL)
5282*30a5e8faSwyllys 		X509_CRL_free(xcrl);
5283*30a5e8faSwyllys 
5284*30a5e8faSwyllys 	return (ret);
5285*30a5e8faSwyllys }
5286