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