199ebb4caSwyllys /*
271593db2Swyllys  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
399ebb4caSwyllys  * Use is subject to license terms.
499ebb4caSwyllys  */
59a767088Shaimay /*
69a767088Shaimay  * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
79a767088Shaimay  * project 2000.
89a767088Shaimay  */
99a767088Shaimay /*
109a767088Shaimay  * ====================================================================
119a767088Shaimay  * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
129a767088Shaimay  *
139a767088Shaimay  * Redistribution and use in source and binary forms, with or without
149a767088Shaimay  * modification, are permitted provided that the following conditions
159a767088Shaimay  * are met:
169a767088Shaimay  *
179a767088Shaimay  * 1. Redistributions of source code must retain the above copyright
189a767088Shaimay  *    notice, this list of conditions and the following disclaimer.
199a767088Shaimay  *
209a767088Shaimay  * 2. Redistributions in binary form must reproduce the above copyright
219a767088Shaimay  *    notice, this list of conditions and the following disclaimer in
229a767088Shaimay  *    the documentation and/or other materials provided with the
239a767088Shaimay  *    distribution.
249a767088Shaimay  *
259a767088Shaimay  * 3. All advertising materials mentioning features or use of this
269a767088Shaimay  *    software must display the following acknowledgment:
279a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
289a767088Shaimay  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
299a767088Shaimay  *
309a767088Shaimay  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
319a767088Shaimay  *    endorse or promote products derived from this software without
329a767088Shaimay  *    prior written permission. For written permission, please contact
339a767088Shaimay  *    licensing@OpenSSL.org.
349a767088Shaimay  *
359a767088Shaimay  * 5. Products derived from this software may not be called "OpenSSL"
369a767088Shaimay  *    nor may "OpenSSL" appear in their names without prior written
379a767088Shaimay  *    permission of the OpenSSL Project.
389a767088Shaimay  *
399a767088Shaimay  * 6. Redistributions of any form whatsoever must retain the following
409a767088Shaimay  *    acknowledgment:
419a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
429a767088Shaimay  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
439a767088Shaimay  *
449a767088Shaimay  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
459a767088Shaimay  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
469a767088Shaimay  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
479a767088Shaimay  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
489a767088Shaimay  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
499a767088Shaimay  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
509a767088Shaimay  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
519a767088Shaimay  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
529a767088Shaimay  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
539a767088Shaimay  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
549a767088Shaimay  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
559a767088Shaimay  * OF THE POSSIBILITY OF SUCH DAMAGE.
569a767088Shaimay  * ====================================================================
579a767088Shaimay  *
589a767088Shaimay  * This product includes cryptographic software written by Eric Young
599a767088Shaimay  * (eay@cryptsoft.com).  This product includes software written by Tim
609a767088Shaimay  * Hudson (tjh@cryptsoft.com).
619a767088Shaimay  *
629a767088Shaimay  */
6399ebb4caSwyllys 
6499ebb4caSwyllys #pragma ident	"%Z%%M%	%I%	%E% SMI"
6599ebb4caSwyllys 
6671593db2Swyllys #include <stdlib.h>
6799ebb4caSwyllys #include <kmfapiP.h>
6899ebb4caSwyllys #include <ber_der.h>
6999ebb4caSwyllys #include <fcntl.h>
7099ebb4caSwyllys #include <sys/stat.h>
7199ebb4caSwyllys #include <dirent.h>
7299ebb4caSwyllys #include <cryptoutil.h>
7399ebb4caSwyllys #include <synch.h>
7499ebb4caSwyllys #include <thread.h>
7599ebb4caSwyllys 
7699ebb4caSwyllys /* OPENSSL related headers */
7799ebb4caSwyllys #include <openssl/bio.h>
7899ebb4caSwyllys #include <openssl/bn.h>
7999ebb4caSwyllys #include <openssl/asn1.h>
8099ebb4caSwyllys #include <openssl/err.h>
8199ebb4caSwyllys #include <openssl/bn.h>
8299ebb4caSwyllys #include <openssl/x509.h>
8399ebb4caSwyllys #include <openssl/rsa.h>
8499ebb4caSwyllys #include <openssl/dsa.h>
8599ebb4caSwyllys #include <openssl/x509v3.h>
8699ebb4caSwyllys #include <openssl/objects.h>
8799ebb4caSwyllys #include <openssl/pem.h>
8899ebb4caSwyllys #include <openssl/pkcs12.h>
8999ebb4caSwyllys #include <openssl/ocsp.h>
9099ebb4caSwyllys #include <openssl/des.h>
9199ebb4caSwyllys #include <openssl/rand.h>
9299ebb4caSwyllys 
9399ebb4caSwyllys #define	PRINT_ANY_EXTENSION (\
9499ebb4caSwyllys 	KMF_X509_EXT_KEY_USAGE |\
9599ebb4caSwyllys 	KMF_X509_EXT_CERT_POLICIES |\
9699ebb4caSwyllys 	KMF_X509_EXT_SUBJALTNAME |\
9799ebb4caSwyllys 	KMF_X509_EXT_BASIC_CONSTRAINTS |\
9899ebb4caSwyllys 	KMF_X509_EXT_NAME_CONSTRAINTS |\
9999ebb4caSwyllys 	KMF_X509_EXT_POLICY_CONSTRAINTS |\
10099ebb4caSwyllys 	KMF_X509_EXT_EXT_KEY_USAGE |\
10199ebb4caSwyllys 	KMF_X509_EXT_INHIBIT_ANY_POLICY |\
10299ebb4caSwyllys 	KMF_X509_EXT_AUTH_KEY_ID |\
10399ebb4caSwyllys 	KMF_X509_EXT_SUBJ_KEY_ID |\
10499ebb4caSwyllys 	KMF_X509_EXT_POLICY_MAPPING)
10599ebb4caSwyllys 
10699ebb4caSwyllys static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
10799ebb4caSwyllys 	0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
10899ebb4caSwyllys 	0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
10999ebb4caSwyllys 	0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
11099ebb4caSwyllys 	0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
11199ebb4caSwyllys 	0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
11299ebb4caSwyllys 	0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
11399ebb4caSwyllys 	0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
11499ebb4caSwyllys 	0x91 };
11599ebb4caSwyllys 
11699ebb4caSwyllys static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
11799ebb4caSwyllys 	0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
11899ebb4caSwyllys 	0x8e, 0xda, 0xce, 0x91, 0x5f };
11999ebb4caSwyllys 
12099ebb4caSwyllys static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
12199ebb4caSwyllys 	0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
12299ebb4caSwyllys 	0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
12399ebb4caSwyllys 	0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
12499ebb4caSwyllys 	0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
12599ebb4caSwyllys 	0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
12699ebb4caSwyllys 	0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
12799ebb4caSwyllys 	0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
12899ebb4caSwyllys 	0x02 };
12999ebb4caSwyllys 
13099ebb4caSwyllys #define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
13199ebb4caSwyllys 	h->lasterr.errcode = c;
13299ebb4caSwyllys 
13399ebb4caSwyllys #define	SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
13499ebb4caSwyllys 
1355b3e1433Swyllys /*
1365b3e1433Swyllys  * Declare some new macros for managing stacks of EVP_PKEYS, similar to
1375b3e1433Swyllys  * what wanboot did.
1385b3e1433Swyllys  */
1395b3e1433Swyllys DECLARE_STACK_OF(EVP_PKEY)
1405b3e1433Swyllys 
1415b3e1433Swyllys #define	sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
1425b3e1433Swyllys #define	sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
1435b3e1433Swyllys #define	sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
1445b3e1433Swyllys #define	sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
1455b3e1433Swyllys #define	sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
1465b3e1433Swyllys #define	sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
1475b3e1433Swyllys 	(free_func))
1485b3e1433Swyllys 
14999ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX;
15099ebb4caSwyllys static int ssl_initialized = 0;
15130a5e8faSwyllys static BIO *bio_err = NULL;
15230a5e8faSwyllys 
15330a5e8faSwyllys static int
15430a5e8faSwyllys test_for_file(char *, mode_t);
1555b3e1433Swyllys static KMF_RETURN
1565b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *, char *, int,
1575b3e1433Swyllys     STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
1585b3e1433Swyllys 
1595b3e1433Swyllys static KMF_RETURN
1605b3e1433Swyllys local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *,
1615b3e1433Swyllys     int, KMF_KEY_HANDLE *, char *);
1625b3e1433Swyllys 
1635b3e1433Swyllys static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int);
16499ebb4caSwyllys 
16571593db2Swyllys static KMF_RETURN
16630a5e8faSwyllys extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *,
16702744e81Swyllys     CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
16871593db2Swyllys 
16971593db2Swyllys static KMF_RETURN
17030a5e8faSwyllys kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
17130a5e8faSwyllys     char *, KMF_DATA *);
17230a5e8faSwyllys 
17330a5e8faSwyllys static KMF_RETURN
17430a5e8faSwyllys load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
17530a5e8faSwyllys     char *, KMF_DATA **, uint32_t *);
17671593db2Swyllys 
17702744e81Swyllys static KMF_RETURN
17802744e81Swyllys sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
17902744e81Swyllys 
18002744e81Swyllys static EVP_PKEY *
18102744e81Swyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *);
18202744e81Swyllys 
18330a5e8faSwyllys static KMF_RETURN
18430a5e8faSwyllys convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
18530a5e8faSwyllys 
18699ebb4caSwyllys KMF_RETURN
18730a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
18899ebb4caSwyllys 
18999ebb4caSwyllys void
19099ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
19199ebb4caSwyllys 
19299ebb4caSwyllys KMF_RETURN
19330a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
19499ebb4caSwyllys 
19599ebb4caSwyllys KMF_RETURN
19630a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
19799ebb4caSwyllys 
19899ebb4caSwyllys KMF_RETURN
19930a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20030a5e8faSwyllys 
20130a5e8faSwyllys KMF_RETURN
20230a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20399ebb4caSwyllys 
20499ebb4caSwyllys KMF_RETURN
20599ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T,  KMF_KEY_HANDLE *, KMF_DATA *);
20699ebb4caSwyllys 
20799ebb4caSwyllys KMF_RETURN
20899ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
20999ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
21099ebb4caSwyllys 
21199ebb4caSwyllys KMF_RETURN
21230a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21399ebb4caSwyllys 
21499ebb4caSwyllys KMF_RETURN
21530a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21699ebb4caSwyllys 
21799ebb4caSwyllys KMF_RETURN
21830a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21999ebb4caSwyllys 
22099ebb4caSwyllys KMF_RETURN
22130a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22299ebb4caSwyllys 
22399ebb4caSwyllys KMF_RETURN
22430a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22599ebb4caSwyllys 
22699ebb4caSwyllys KMF_RETURN
22799ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
22899ebb4caSwyllys 	KMF_PRINTABLE_ITEM, char *);
22999ebb4caSwyllys 
23099ebb4caSwyllys KMF_RETURN
23199ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
23299ebb4caSwyllys 
23399ebb4caSwyllys KMF_RETURN
23430a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23599ebb4caSwyllys 
23699ebb4caSwyllys KMF_RETURN
23799ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
23899ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
23999ebb4caSwyllys 
24099ebb4caSwyllys KMF_RETURN
24130a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24299ebb4caSwyllys 
24399ebb4caSwyllys KMF_RETURN
24430a5e8faSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24599ebb4caSwyllys 
24699ebb4caSwyllys KMF_RETURN
24730a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24899ebb4caSwyllys 
24999ebb4caSwyllys KMF_RETURN
25030a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25199ebb4caSwyllys 
25299ebb4caSwyllys KMF_RETURN
25330a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25499ebb4caSwyllys 
25599ebb4caSwyllys KMF_RETURN
25699ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
25799ebb4caSwyllys 
25899ebb4caSwyllys KMF_RETURN
25930a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
26099ebb4caSwyllys 
26199ebb4caSwyllys KMF_RETURN
26230a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
26399ebb4caSwyllys 
26402744e81Swyllys KMF_RETURN
26502744e81Swyllys OpenSSL_VerifyDataWithCert(KMF_HANDLE_T, KMF_ALGORITHM_INDEX,
26602744e81Swyllys 	KMF_DATA *, KMF_DATA *, KMF_DATA *);
26702744e81Swyllys 
26899ebb4caSwyllys static
26999ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table =
27099ebb4caSwyllys {
27199ebb4caSwyllys 	1,				/* Version */
27299ebb4caSwyllys 	NULL, /* ConfigureKeystore */
27399ebb4caSwyllys 	OpenSSL_FindCert,
27499ebb4caSwyllys 	OpenSSL_FreeKMFCert,
27599ebb4caSwyllys 	OpenSSL_StoreCert,
27699ebb4caSwyllys 	NULL, /* ImportCert */
27799ebb4caSwyllys 	OpenSSL_ImportCRL,
27899ebb4caSwyllys 	OpenSSL_DeleteCert,
27999ebb4caSwyllys 	OpenSSL_DeleteCRL,
28099ebb4caSwyllys 	OpenSSL_CreateKeypair,
28199ebb4caSwyllys 	OpenSSL_FindKey,
28299ebb4caSwyllys 	OpenSSL_EncodePubKeyData,
28399ebb4caSwyllys 	OpenSSL_SignData,
28499ebb4caSwyllys 	OpenSSL_DeleteKey,
28599ebb4caSwyllys 	OpenSSL_ListCRL,
28699ebb4caSwyllys 	NULL,	/* FindCRL */
28799ebb4caSwyllys 	OpenSSL_FindCertInCRL,
28899ebb4caSwyllys 	OpenSSL_GetErrorString,
28930a5e8faSwyllys 	OpenSSL_FindPrikeyByCert,
29099ebb4caSwyllys 	OpenSSL_DecryptData,
29130a5e8faSwyllys 	OpenSSL_ExportPK12,
29299ebb4caSwyllys 	OpenSSL_CreateSymKey,
29399ebb4caSwyllys 	OpenSSL_GetSymKeyValue,
29499ebb4caSwyllys 	NULL,	/* SetTokenPin */
29502744e81Swyllys 	OpenSSL_VerifyDataWithCert,
29630a5e8faSwyllys 	OpenSSL_StoreKey,
29799ebb4caSwyllys 	NULL	/* Finalize */
29899ebb4caSwyllys };
29999ebb4caSwyllys 
30099ebb4caSwyllys static mutex_t *lock_cs;
30199ebb4caSwyllys static long *lock_count;
30299ebb4caSwyllys 
30399ebb4caSwyllys static void
30499ebb4caSwyllys /*ARGSUSED*/
30599ebb4caSwyllys locking_cb(int mode, int type, char *file, int line)
30699ebb4caSwyllys {
30799ebb4caSwyllys 	if (mode & CRYPTO_LOCK) {
30899ebb4caSwyllys 		(void) mutex_lock(&(lock_cs[type]));
30999ebb4caSwyllys 		lock_count[type]++;
31099ebb4caSwyllys 	} else {
31199ebb4caSwyllys 		(void) mutex_unlock(&(lock_cs[type]));
31299ebb4caSwyllys 	}
31399ebb4caSwyllys }
31499ebb4caSwyllys 
31599ebb4caSwyllys static unsigned long
31699ebb4caSwyllys thread_id()
31799ebb4caSwyllys {
31899ebb4caSwyllys 	return ((unsigned long)thr_self());
31999ebb4caSwyllys }
32099ebb4caSwyllys 
32199ebb4caSwyllys KMF_PLUGIN_FUNCLIST *
32299ebb4caSwyllys KMF_Plugin_Initialize()
32399ebb4caSwyllys {
32499ebb4caSwyllys 	int i;
32599ebb4caSwyllys 
32699ebb4caSwyllys 	(void) mutex_lock(&init_lock);
32799ebb4caSwyllys 	if (!ssl_initialized) {
32899ebb4caSwyllys 		OpenSSL_add_all_algorithms();
32999ebb4caSwyllys 
33099ebb4caSwyllys 		/* Enable error strings for reporting */
33199ebb4caSwyllys 		ERR_load_crypto_strings();
33299ebb4caSwyllys 
33399ebb4caSwyllys 		/*
33499ebb4caSwyllys 		 * Add support for extension OIDs that are not yet in the
33599ebb4caSwyllys 		 * openssl default set.
33699ebb4caSwyllys 		 */
33799ebb4caSwyllys 		(void) OBJ_create("2.5.29.30", "nameConstraints",
33899ebb4caSwyllys 		    "X509v3 Name Constraints");
33999ebb4caSwyllys 		(void) OBJ_create("2.5.29.33", "policyMappings",
34099ebb4caSwyllys 		    "X509v3 Policy Mappings");
34199ebb4caSwyllys 		(void) OBJ_create("2.5.29.36", "policyConstraints",
34299ebb4caSwyllys 		    "X509v3 Policy Constraints");
34399ebb4caSwyllys 		(void) OBJ_create("2.5.29.46", "freshestCRL",
34499ebb4caSwyllys 		    "X509v3 Freshest CRL");
34599ebb4caSwyllys 		(void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
34699ebb4caSwyllys 		    "X509v3 Inhibit Any-Policy");
34799ebb4caSwyllys 		/*
34899ebb4caSwyllys 		 * Set up for thread-safe operation.
34999ebb4caSwyllys 		 */
35099ebb4caSwyllys 		lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
35199ebb4caSwyllys 		if (lock_cs == NULL) {
35299ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
35399ebb4caSwyllys 			return (NULL);
35499ebb4caSwyllys 		}
35599ebb4caSwyllys 
35699ebb4caSwyllys 		lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
35799ebb4caSwyllys 		if (lock_count == NULL) {
35899ebb4caSwyllys 			OPENSSL_free(lock_cs);
35999ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
36099ebb4caSwyllys 			return (NULL);
36199ebb4caSwyllys 		}
36299ebb4caSwyllys 
36399ebb4caSwyllys 		for (i = 0; i < CRYPTO_num_locks(); i++) {
36499ebb4caSwyllys 			lock_count[i] = 0;
36599ebb4caSwyllys 			(void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
36699ebb4caSwyllys 		}
36799ebb4caSwyllys 
36899ebb4caSwyllys 		CRYPTO_set_id_callback((unsigned long (*)())thread_id);
36999ebb4caSwyllys 		CRYPTO_set_locking_callback((void (*)())locking_cb);
37099ebb4caSwyllys 		ssl_initialized = 1;
37199ebb4caSwyllys 	}
37299ebb4caSwyllys 	(void) mutex_unlock(&init_lock);
37399ebb4caSwyllys 
37499ebb4caSwyllys 	return (&openssl_plugin_table);
37599ebb4caSwyllys }
37699ebb4caSwyllys /*
37799ebb4caSwyllys  * Convert an SSL DN to a KMF DN.
37899ebb4caSwyllys  */
37999ebb4caSwyllys static KMF_RETURN
38099ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
38199ebb4caSwyllys {
38299ebb4caSwyllys 	KMF_DATA derdata;
38399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
38499ebb4caSwyllys 	uchar_t *tmp;
38599ebb4caSwyllys 
38699ebb4caSwyllys 	/* Convert to raw DER format */
38799ebb4caSwyllys 	derdata.Length = i2d_X509_NAME(sslDN, NULL);
38899ebb4caSwyllys 	if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
38999ebb4caSwyllys 	    == NULL) {
39099ebb4caSwyllys 		return (KMF_ERR_MEMORY);
39199ebb4caSwyllys 	}
39299ebb4caSwyllys 	(void) i2d_X509_NAME(sslDN, &tmp);
39399ebb4caSwyllys 
39499ebb4caSwyllys 	/* Decode to KMF format */
39599ebb4caSwyllys 	rv = DerDecodeName(&derdata, kmfDN);
39699ebb4caSwyllys 	if (rv != KMF_OK) {
39799ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
39899ebb4caSwyllys 	}
39999ebb4caSwyllys 	OPENSSL_free(derdata.Data);
40099ebb4caSwyllys 
40199ebb4caSwyllys 	return (rv);
40299ebb4caSwyllys }
40399ebb4caSwyllys 
40430a5e8faSwyllys int
40599ebb4caSwyllys isdir(char *path)
40699ebb4caSwyllys {
40799ebb4caSwyllys 	struct stat s;
40899ebb4caSwyllys 
40999ebb4caSwyllys 	if (stat(path, &s) == -1)
41099ebb4caSwyllys 		return (0);
41199ebb4caSwyllys 
41230a5e8faSwyllys 	return ((s.st_mode & S_IFMT) == S_IFDIR);
41399ebb4caSwyllys }
41499ebb4caSwyllys 
41599ebb4caSwyllys static KMF_RETURN
41699ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
41799ebb4caSwyllys {
41899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
41999ebb4caSwyllys 	unsigned char *buf = NULL, *p;
42099ebb4caSwyllys 	int len;
42199ebb4caSwyllys 
42299ebb4caSwyllys 	/*
42399ebb4caSwyllys 	 * Convert the X509 internal struct to DER encoded data
42499ebb4caSwyllys 	 */
42599ebb4caSwyllys 	if ((len = i2d_X509(x509cert, NULL)) < 0) {
42699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
42799ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
42899ebb4caSwyllys 		goto cleanup;
42999ebb4caSwyllys 	}
43099ebb4caSwyllys 	if ((buf = malloc(len)) == NULL) {
43199ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
43299ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
43399ebb4caSwyllys 		goto cleanup;
43499ebb4caSwyllys 	}
43599ebb4caSwyllys 
43699ebb4caSwyllys 	/*
43799ebb4caSwyllys 	 * i2d_X509 will increment the buf pointer so that we need to
43899ebb4caSwyllys 	 * save it.
43999ebb4caSwyllys 	 */
44099ebb4caSwyllys 	p = buf;
44199ebb4caSwyllys 	if ((len = i2d_X509(x509cert, &p)) < 0) {
44299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
44399ebb4caSwyllys 		free(buf);
44499ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
44599ebb4caSwyllys 		goto cleanup;
44699ebb4caSwyllys 	}
44799ebb4caSwyllys 
44899ebb4caSwyllys 	/* caller's responsibility to free it */
44999ebb4caSwyllys 	cert->Data = buf;
45099ebb4caSwyllys 	cert->Length = len;
45199ebb4caSwyllys 
45299ebb4caSwyllys cleanup:
45399ebb4caSwyllys 	if (rv != KMF_OK) {
45499ebb4caSwyllys 		if (buf)
45599ebb4caSwyllys 			free(buf);
45699ebb4caSwyllys 		cert->Data = NULL;
45799ebb4caSwyllys 		cert->Length = 0;
45899ebb4caSwyllys 	}
45999ebb4caSwyllys 
46099ebb4caSwyllys 	return (rv);
46199ebb4caSwyllys }
46299ebb4caSwyllys 
46330a5e8faSwyllys 
46499ebb4caSwyllys static KMF_RETURN
46530a5e8faSwyllys check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
46630a5e8faSwyllys     boolean_t *match)
46799ebb4caSwyllys {
46899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
46999ebb4caSwyllys 	boolean_t findIssuer = FALSE;
47099ebb4caSwyllys 	boolean_t findSubject = FALSE;
47199ebb4caSwyllys 	boolean_t findSerial = FALSE;
47299ebb4caSwyllys 	KMF_X509_NAME issuerDN, subjectDN;
47399ebb4caSwyllys 	KMF_X509_NAME certIssuerDN, certSubjectDN;
47499ebb4caSwyllys 
47599ebb4caSwyllys 	*match = FALSE;
47699ebb4caSwyllys 	if (xcert == NULL) {
47799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
47899ebb4caSwyllys 	}
47999ebb4caSwyllys 
48099ebb4caSwyllys 	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
48199ebb4caSwyllys 	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
48299ebb4caSwyllys 	(void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
48399ebb4caSwyllys 	(void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
48499ebb4caSwyllys 
48530a5e8faSwyllys 	if (issuer != NULL && strlen(issuer)) {
48630a5e8faSwyllys 		rv = kmf_dn_parser(issuer, &issuerDN);
48799ebb4caSwyllys 		if (rv != KMF_OK)
48899ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
48999ebb4caSwyllys 
49099ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->issuer, &certIssuerDN);
49199ebb4caSwyllys 		if (rv != KMF_OK) {
49230a5e8faSwyllys 			kmf_free_dn(&issuerDN);
49399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
49499ebb4caSwyllys 		}
49599ebb4caSwyllys 
49699ebb4caSwyllys 		findIssuer = TRUE;
49799ebb4caSwyllys 	}
49830a5e8faSwyllys 	if (subject != NULL && strlen(subject)) {
49930a5e8faSwyllys 		rv = kmf_dn_parser(subject, &subjectDN);
50099ebb4caSwyllys 		if (rv != KMF_OK) {
50199ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
50299ebb4caSwyllys 			goto cleanup;
50399ebb4caSwyllys 		}
50499ebb4caSwyllys 
50599ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->subject, &certSubjectDN);
50699ebb4caSwyllys 		if (rv != KMF_OK) {
50799ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
50899ebb4caSwyllys 			goto cleanup;
50999ebb4caSwyllys 		}
51099ebb4caSwyllys 		findSubject = TRUE;
51199ebb4caSwyllys 	}
51230a5e8faSwyllys 	if (serial != NULL && serial->val != NULL)
51399ebb4caSwyllys 		findSerial = TRUE;
51499ebb4caSwyllys 
51599ebb4caSwyllys 	if (findSerial) {
51699ebb4caSwyllys 		BIGNUM *bn;
51799ebb4caSwyllys 
51899ebb4caSwyllys 		/* Comparing BIGNUMs is a pain! */
51999ebb4caSwyllys 		bn = ASN1_INTEGER_to_BN(xcert->cert_info->serialNumber, NULL);
52099ebb4caSwyllys 		if (bn != NULL) {
52199ebb4caSwyllys 			int bnlen = BN_num_bytes(bn);
52299ebb4caSwyllys 
52330a5e8faSwyllys 			if (bnlen == serial->len) {
52499ebb4caSwyllys 				uchar_t *a = malloc(bnlen);
52599ebb4caSwyllys 				if (a == NULL) {
52699ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
52799ebb4caSwyllys 					BN_free(bn);
52899ebb4caSwyllys 					goto cleanup;
52999ebb4caSwyllys 				}
53099ebb4caSwyllys 				bnlen = BN_bn2bin(bn, a);
53130a5e8faSwyllys 				*match = (memcmp(a, serial->val, serial->len) ==
53230a5e8faSwyllys 				    0);
53399ebb4caSwyllys 				rv = KMF_OK;
53499ebb4caSwyllys 				free(a);
53599ebb4caSwyllys 			}
53699ebb4caSwyllys 			BN_free(bn);
53799ebb4caSwyllys 			if (!(*match))
53899ebb4caSwyllys 				goto cleanup;
53999ebb4caSwyllys 		} else {
54099ebb4caSwyllys 			rv = KMF_OK;
54199ebb4caSwyllys 			goto cleanup;
54299ebb4caSwyllys 		}
54399ebb4caSwyllys 	}
54499ebb4caSwyllys 	if (findIssuer) {
54530a5e8faSwyllys 		*match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
54630a5e8faSwyllys 		if ((*match) == B_FALSE) {
54730a5e8faSwyllys 			/* stop checking and bail */
54899ebb4caSwyllys 			rv = KMF_OK;
54999ebb4caSwyllys 			goto cleanup;
55099ebb4caSwyllys 		}
55199ebb4caSwyllys 	}
55299ebb4caSwyllys 	if (findSubject) {
55330a5e8faSwyllys 		*match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
55430a5e8faSwyllys 		if ((*match) == B_FALSE) {
55530a5e8faSwyllys 			/* stop checking and bail */
55699ebb4caSwyllys 			rv = KMF_OK;
55799ebb4caSwyllys 			goto cleanup;
55899ebb4caSwyllys 		}
55999ebb4caSwyllys 	}
56099ebb4caSwyllys 
56199ebb4caSwyllys 	*match = TRUE;
56299ebb4caSwyllys cleanup:
56399ebb4caSwyllys 	if (findIssuer) {
56430a5e8faSwyllys 		kmf_free_dn(&issuerDN);
56530a5e8faSwyllys 		kmf_free_dn(&certIssuerDN);
56699ebb4caSwyllys 	}
56799ebb4caSwyllys 	if (findSubject) {
56830a5e8faSwyllys 		kmf_free_dn(&subjectDN);
56930a5e8faSwyllys 		kmf_free_dn(&certSubjectDN);
57099ebb4caSwyllys 	}
57199ebb4caSwyllys 
57299ebb4caSwyllys 	return (rv);
57399ebb4caSwyllys }
57499ebb4caSwyllys 
57530a5e8faSwyllys 
57630a5e8faSwyllys /*
57730a5e8faSwyllys  * This function loads a certificate file into an X509 data structure, and
57830a5e8faSwyllys  * checks if its issuer, subject or the serial number matches with those
57930a5e8faSwyllys  * values.  If it matches, then return the X509 data structure.
58030a5e8faSwyllys  */
58199ebb4caSwyllys static KMF_RETURN
58299ebb4caSwyllys load_X509cert(KMF_HANDLE *kmfh,
58330a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
58430a5e8faSwyllys     char *pathname, X509 **outcert)
58599ebb4caSwyllys {
58699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
58799ebb4caSwyllys 	X509 *xcert = NULL;
58899ebb4caSwyllys 	BIO *bcert = NULL;
58999ebb4caSwyllys 	boolean_t  match = FALSE;
59099ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
59199ebb4caSwyllys 
59299ebb4caSwyllys 	/*
59399ebb4caSwyllys 	 * auto-detect the file format, regardless of what
59499ebb4caSwyllys 	 * the 'format' parameters in the params say.
59599ebb4caSwyllys 	 */
59630a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
59799ebb4caSwyllys 	if (rv != KMF_OK) {
59899ebb4caSwyllys 		if (rv == KMF_ERR_OPEN_FILE)
59999ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
60099ebb4caSwyllys 		return (rv);
60199ebb4caSwyllys 	}
60299ebb4caSwyllys 
60399ebb4caSwyllys 	/* Not ASN1(DER) format */
60499ebb4caSwyllys 	if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
60599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
60699ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
60799ebb4caSwyllys 		goto cleanup;
60899ebb4caSwyllys 	}
60999ebb4caSwyllys 
61099ebb4caSwyllys 	if (format == KMF_FORMAT_PEM)
61199ebb4caSwyllys 		xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
61299ebb4caSwyllys 	else if (format == KMF_FORMAT_ASN1)
61399ebb4caSwyllys 		xcert = d2i_X509_bio(bcert, NULL);
61499ebb4caSwyllys 	else if (format == KMF_FORMAT_PKCS12) {
61599ebb4caSwyllys 		PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
61699ebb4caSwyllys 		if (p12 != NULL) {
61799ebb4caSwyllys 			(void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
61899ebb4caSwyllys 			PKCS12_free(p12);
61999ebb4caSwyllys 			p12 = NULL;
62099ebb4caSwyllys 		} else {
62199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
62299ebb4caSwyllys 			rv = KMF_ERR_BAD_CERT_FORMAT;
62399ebb4caSwyllys 		}
62499ebb4caSwyllys 	} else {
62599ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
62699ebb4caSwyllys 		goto cleanup;
62799ebb4caSwyllys 	}
62899ebb4caSwyllys 
62999ebb4caSwyllys 	if (xcert == NULL) {
63099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
63199ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
63299ebb4caSwyllys 		goto cleanup;
63399ebb4caSwyllys 	}
63499ebb4caSwyllys 
63530a5e8faSwyllys 	if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
63630a5e8faSwyllys 	    match == FALSE) {
63799ebb4caSwyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
63899ebb4caSwyllys 		goto cleanup;
63999ebb4caSwyllys 	}
64099ebb4caSwyllys 
64199ebb4caSwyllys 	if (outcert != NULL) {
64299ebb4caSwyllys 		*outcert = xcert;
64399ebb4caSwyllys 	}
64499ebb4caSwyllys 
64599ebb4caSwyllys cleanup:
64699ebb4caSwyllys 	if (bcert != NULL) (void) BIO_free(bcert);
64799ebb4caSwyllys 	if (rv != KMF_OK && xcert != NULL)
64899ebb4caSwyllys 		X509_free(xcert);
64999ebb4caSwyllys 
65099ebb4caSwyllys 	return (rv);
65199ebb4caSwyllys }
65299ebb4caSwyllys 
65371593db2Swyllys static int
65471593db2Swyllys datacmp(const void *a, const void *b)
65571593db2Swyllys {
65671593db2Swyllys 	KMF_DATA *adata = (KMF_DATA *)a;
65771593db2Swyllys 	KMF_DATA *bdata = (KMF_DATA *)b;
65871593db2Swyllys 	if (adata->Length > bdata->Length)
65971593db2Swyllys 		return (-1);
66071593db2Swyllys 	if (adata->Length < bdata->Length)
66171593db2Swyllys 		return (1);
66271593db2Swyllys 	return (0);
66371593db2Swyllys }
66471593db2Swyllys 
66571593db2Swyllys static KMF_RETURN
66630a5e8faSwyllys load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
66730a5e8faSwyllys     KMF_CERT_VALIDITY validity, char *pathname,
66871593db2Swyllys     KMF_DATA **certlist, uint32_t *numcerts)
66971593db2Swyllys {
67071593db2Swyllys 	KMF_RETURN rv = KMF_OK;
67171593db2Swyllys 	int i;
67271593db2Swyllys 	KMF_DATA *certs = NULL;
67371593db2Swyllys 	int nc = 0;
67471593db2Swyllys 	int hits = 0;
67571593db2Swyllys 	KMF_ENCODE_FORMAT format;
67671593db2Swyllys 
67730a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
67871593db2Swyllys 	if (rv != KMF_OK) {
67971593db2Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
68071593db2Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
68171593db2Swyllys 		return (rv);
68271593db2Swyllys 	}
68371593db2Swyllys 	if (format == KMF_FORMAT_ASN1) {
68471593db2Swyllys 		/* load a single certificate */
68571593db2Swyllys 		certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
68671593db2Swyllys 		if (certs == NULL)
68771593db2Swyllys 			return (KMF_ERR_MEMORY);
68871593db2Swyllys 		certs->Data = NULL;
68971593db2Swyllys 		certs->Length = 0;
69030a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
69130a5e8faSwyllys 		    pathname, certs);
69271593db2Swyllys 		if (rv == KMF_OK) {
69371593db2Swyllys 			*certlist = certs;
69471593db2Swyllys 			*numcerts = 1;
69571593db2Swyllys 		}
69671593db2Swyllys 		return (rv);
69771593db2Swyllys 	} else if (format == KMF_FORMAT_PKCS12) {
69871593db2Swyllys 		/* We need a credential to access a PKCS#12 file */
69971593db2Swyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
70071593db2Swyllys 	} else if (format == KMF_FORMAT_PEM ||
70171593db2Swyllys 	    format != KMF_FORMAT_PEM_KEYPAIR) {
70271593db2Swyllys 
70371593db2Swyllys 		/* This function only works on PEM files */
70430a5e8faSwyllys 		rv = extract_pem(kmfh, issuer, subject, serial, pathname,
70534acef67Swyllys 		    (uchar_t *)NULL, 0, NULL, &certs, &nc);
70671593db2Swyllys 	} else {
70771593db2Swyllys 		return (KMF_ERR_ENCODING);
70871593db2Swyllys 	}
70971593db2Swyllys 
71071593db2Swyllys 	if (rv != KMF_OK)
71171593db2Swyllys 		return (rv);
71271593db2Swyllys 
71371593db2Swyllys 	for (i = 0; i < nc; i++) {
71430a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
71530a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
71630a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
71730a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
71871593db2Swyllys 			if (rv == KMF_OK)
71971593db2Swyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
72071593db2Swyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD)
72171593db2Swyllys 				rv = KMF_OK;
72271593db2Swyllys 		}
72371593db2Swyllys 		if (rv != KMF_OK) {
72471593db2Swyllys 			/* Remove this cert from the list by clearing it. */
72530a5e8faSwyllys 			kmf_free_data(&certs[i]);
72671593db2Swyllys 		} else {
72771593db2Swyllys 			hits++; /* count valid certs found */
72871593db2Swyllys 		}
72971593db2Swyllys 		rv = KMF_OK;
73071593db2Swyllys 	}
73171593db2Swyllys 	if (rv == KMF_OK && hits == 0) {
73271593db2Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
73371593db2Swyllys 	} else if (rv == KMF_OK && hits > 0) {
73471593db2Swyllys 		/*
73571593db2Swyllys 		 * Sort the list of certs by length to put the cleared ones
73671593db2Swyllys 		 * at the end so they don't get accessed by the caller.
73771593db2Swyllys 		 */
73871593db2Swyllys 		qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
73971593db2Swyllys 		*certlist = certs;
74071593db2Swyllys 
74171593db2Swyllys 		/* since we sorted the list, just return the number of hits */
74271593db2Swyllys 		*numcerts = hits;
74371593db2Swyllys 	}
74471593db2Swyllys 	return (rv);
74571593db2Swyllys }
74671593db2Swyllys 
74730a5e8faSwyllys 
74899ebb4caSwyllys static KMF_RETURN
74999ebb4caSwyllys kmf_load_cert(KMF_HANDLE *kmfh,
75030a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
75130a5e8faSwyllys     KMF_CERT_VALIDITY validity,
75299ebb4caSwyllys     char *pathname,
75399ebb4caSwyllys     KMF_DATA *cert)
75499ebb4caSwyllys {
75599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
75699ebb4caSwyllys 	X509 *x509cert = NULL;
75799ebb4caSwyllys 
75830a5e8faSwyllys 	rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
75999ebb4caSwyllys 	if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
76099ebb4caSwyllys 		rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
76199ebb4caSwyllys 		if (rv != KMF_OK) {
76299ebb4caSwyllys 			goto cleanup;
76399ebb4caSwyllys 		}
76430a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
76530a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
76630a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
76730a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
76899ebb4caSwyllys 			if (rv == KMF_OK)  {
76999ebb4caSwyllys 				/*
77099ebb4caSwyllys 				 * This is a valid cert so skip it.
77199ebb4caSwyllys 				 */
77299ebb4caSwyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
77399ebb4caSwyllys 			}
77499ebb4caSwyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD) {
77599ebb4caSwyllys 				/*
77699ebb4caSwyllys 				 * We want to return success when we
77799ebb4caSwyllys 				 * find an invalid cert.
77899ebb4caSwyllys 				 */
77999ebb4caSwyllys 				rv = KMF_OK;
78099ebb4caSwyllys 				goto cleanup;
78199ebb4caSwyllys 			}
78299ebb4caSwyllys 		}
78399ebb4caSwyllys 	}
78499ebb4caSwyllys cleanup:
78599ebb4caSwyllys 	if (x509cert != NULL)
78699ebb4caSwyllys 		X509_free(x509cert);
78799ebb4caSwyllys 
78899ebb4caSwyllys 	return (rv);
78999ebb4caSwyllys }
79099ebb4caSwyllys 
79102744e81Swyllys static KMF_RETURN
79202744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
79302744e81Swyllys {
79402744e81Swyllys 	KMF_RETURN ret = KMF_OK;
79502744e81Swyllys 	KMF_RAW_RSA_KEY rsa;
79602744e81Swyllys 	BerElement *asn1 = NULL;
79702744e81Swyllys 	BerValue filebuf;
79802744e81Swyllys 	BerValue OID = { NULL, 0 };
79902744e81Swyllys 	BerValue *Mod = NULL, *PubExp = NULL;
80002744e81Swyllys 	BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
80102744e81Swyllys 	BerValue *Coef = NULL;
80202744e81Swyllys 	BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
80302744e81Swyllys 	BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
80402744e81Swyllys 	BIGNUM *qminus1 = NULL;
80502744e81Swyllys 	BN_CTX *ctx = NULL;
80602744e81Swyllys 
80702744e81Swyllys 	*pkey = NULL;
80802744e81Swyllys 
80902744e81Swyllys 	filebuf.bv_val = (char *)filedata->Data;
81002744e81Swyllys 	filebuf.bv_len = filedata->Length;
81102744e81Swyllys 
81202744e81Swyllys 	asn1 = kmfder_init(&filebuf);
81302744e81Swyllys 	if (asn1 == NULL) {
81402744e81Swyllys 		ret = KMF_ERR_MEMORY;
81502744e81Swyllys 		goto out;
81602744e81Swyllys 	}
81702744e81Swyllys 
81802744e81Swyllys 	if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
81902744e81Swyllys 	    &OID, &Mod, &PubExp, &PriExp, &Prime1,
82002744e81Swyllys 	    &Prime2, &Coef) == -1)  {
82102744e81Swyllys 		ret = KMF_ERR_ENCODING;
82202744e81Swyllys 		goto out;
82302744e81Swyllys 	}
82402744e81Swyllys 
82502744e81Swyllys 	/*
82602744e81Swyllys 	 * We have to derive the 2 Exponents using Bignumber math.
82702744e81Swyllys 	 * Exp1 = PriExp mod (Prime1 - 1)
82802744e81Swyllys 	 * Exp2 = PriExp mod (Prime2 - 1)
82902744e81Swyllys 	 */
83002744e81Swyllys 
83102744e81Swyllys 	/* D = PrivateExponent */
83202744e81Swyllys 	D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
83302744e81Swyllys 	if (D == NULL) {
83402744e81Swyllys 		ret = KMF_ERR_MEMORY;
83502744e81Swyllys 		goto out;
83602744e81Swyllys 	}
83702744e81Swyllys 
83802744e81Swyllys 	/* P = Prime1 (first prime factor of Modulus) */
83902744e81Swyllys 	P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
84002744e81Swyllys 	if (D == NULL) {
84102744e81Swyllys 		ret = KMF_ERR_MEMORY;
84202744e81Swyllys 		goto out;
84302744e81Swyllys 	}
84402744e81Swyllys 
84502744e81Swyllys 	/* Q = Prime2 (second prime factor of Modulus) */
84602744e81Swyllys 	Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
84702744e81Swyllys 
84802744e81Swyllys 	if ((ctx = BN_CTX_new()) == NULL) {
84902744e81Swyllys 		ret = KMF_ERR_MEMORY;
85002744e81Swyllys 		goto out;
85102744e81Swyllys 	}
85202744e81Swyllys 
85302744e81Swyllys 	/* Compute (P - 1) */
85402744e81Swyllys 	pminus1 = BN_new();
85502744e81Swyllys 	(void) BN_sub(pminus1, P, BN_value_one());
85602744e81Swyllys 
85702744e81Swyllys 	/* Exponent1 = D mod (P - 1) */
85802744e81Swyllys 	Exp1 = BN_new();
85902744e81Swyllys 	(void) BN_mod(Exp1, D, pminus1, ctx);
86002744e81Swyllys 
86102744e81Swyllys 	/* Compute (Q - 1) */
86202744e81Swyllys 	qminus1 = BN_new();
86302744e81Swyllys 	(void) BN_sub(qminus1, Q, BN_value_one());
86402744e81Swyllys 
86502744e81Swyllys 	/* Exponent2 = D mod (Q - 1) */
86602744e81Swyllys 	Exp2 = BN_new();
86702744e81Swyllys 	(void) BN_mod(Exp2, D, qminus1, ctx);
86802744e81Swyllys 
86902744e81Swyllys 	/* Coef = (Inverse Q) mod P */
87002744e81Swyllys 	COEF = BN_new();
87102744e81Swyllys 	(void) BN_mod_inverse(COEF, Q, P, ctx);
87202744e81Swyllys 
87302744e81Swyllys 	/* Convert back to KMF format */
87402744e81Swyllys 	(void) memset(&rsa, 0, sizeof (rsa));
87502744e81Swyllys 
87602744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
87702744e81Swyllys 		goto out;
87802744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
87902744e81Swyllys 		goto out;
88002744e81Swyllys 	if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
88102744e81Swyllys 		goto out;
88202744e81Swyllys 
88302744e81Swyllys 	rsa.mod.val = (uchar_t *)Mod->bv_val;
88402744e81Swyllys 	rsa.mod.len = Mod->bv_len;
88502744e81Swyllys 
88602744e81Swyllys 	rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
88702744e81Swyllys 	rsa.pubexp.len = PubExp->bv_len;
88802744e81Swyllys 
88902744e81Swyllys 	rsa.priexp.val = (uchar_t *)PriExp->bv_val;
89002744e81Swyllys 	rsa.priexp.len = PriExp->bv_len;
89102744e81Swyllys 
89202744e81Swyllys 	rsa.prime1.val = (uchar_t *)Prime1->bv_val;
89302744e81Swyllys 	rsa.prime1.len = Prime1->bv_len;
89402744e81Swyllys 
89502744e81Swyllys 	rsa.prime2.val = (uchar_t *)Prime2->bv_val;
89602744e81Swyllys 	rsa.prime2.len = Prime2->bv_len;
89702744e81Swyllys 
89802744e81Swyllys 	*pkey = ImportRawRSAKey(&rsa);
89902744e81Swyllys out:
90002744e81Swyllys 	if (asn1 != NULL)
90102744e81Swyllys 		kmfber_free(asn1, 1);
90202744e81Swyllys 
90302744e81Swyllys 	if (OID.bv_val) {
90402744e81Swyllys 		free(OID.bv_val);
90502744e81Swyllys 	}
90602744e81Swyllys 	if (PriExp)
90702744e81Swyllys 		free(PriExp);
90802744e81Swyllys 
90902744e81Swyllys 	if (Mod)
91002744e81Swyllys 		free(Mod);
91102744e81Swyllys 
91202744e81Swyllys 	if (PubExp)
91302744e81Swyllys 		free(PubExp);
91402744e81Swyllys 
91502744e81Swyllys 	if (Coef) {
91602744e81Swyllys 		(void) memset(Coef->bv_val, 0, Coef->bv_len);
91702744e81Swyllys 		free(Coef->bv_val);
91802744e81Swyllys 		free(Coef);
91902744e81Swyllys 	}
92002744e81Swyllys 	if (Prime1)
92102744e81Swyllys 		free(Prime1);
92202744e81Swyllys 	if (Prime2)
92302744e81Swyllys 		free(Prime2);
92402744e81Swyllys 
92502744e81Swyllys 	if (ctx != NULL)
92602744e81Swyllys 		BN_CTX_free(ctx);
92702744e81Swyllys 
92802744e81Swyllys 	if (D)
92902744e81Swyllys 		BN_clear_free(D);
93002744e81Swyllys 	if (P)
93102744e81Swyllys 		BN_clear_free(P);
93202744e81Swyllys 	if (Q)
93302744e81Swyllys 		BN_clear_free(Q);
93402744e81Swyllys 	if (pminus1)
93502744e81Swyllys 		BN_clear_free(pminus1);
93602744e81Swyllys 	if (qminus1)
93702744e81Swyllys 		BN_clear_free(qminus1);
93802744e81Swyllys 	if (Exp1)
93902744e81Swyllys 		BN_clear_free(Exp1);
94002744e81Swyllys 	if (Exp2)
94102744e81Swyllys 		BN_clear_free(Exp2);
94202744e81Swyllys 
94302744e81Swyllys 	return (ret);
94402744e81Swyllys 
94502744e81Swyllys }
94602744e81Swyllys 
94799ebb4caSwyllys static EVP_PKEY *
94899ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file)
94999ebb4caSwyllys {
95099ebb4caSwyllys 	BIO *keyfile = NULL;
95199ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
95299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
95399ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
95402744e81Swyllys 	KMF_RETURN rv;
95502744e81Swyllys 	KMF_DATA filedata;
95699ebb4caSwyllys 
95799ebb4caSwyllys 	if (file == NULL) {
95899ebb4caSwyllys 		return (NULL);
95999ebb4caSwyllys 	}
96099ebb4caSwyllys 
96130a5e8faSwyllys 	if (kmf_get_file_format((char *)file, &format) != KMF_OK)
96299ebb4caSwyllys 		return (NULL);
96399ebb4caSwyllys 
96499ebb4caSwyllys 	keyfile = BIO_new_file(file, "rb");
96599ebb4caSwyllys 	if (keyfile == NULL) {
96699ebb4caSwyllys 		goto end;
96799ebb4caSwyllys 	}
96899ebb4caSwyllys 
96902744e81Swyllys 	if (format == KMF_FORMAT_ASN1) {
97099ebb4caSwyllys 		pkey = d2i_PrivateKey_bio(keyfile, NULL);
97102744e81Swyllys 		if (pkey == NULL) {
97202744e81Swyllys 
97302744e81Swyllys 			(void) BIO_free(keyfile);
97402744e81Swyllys 			keyfile = NULL;
97502744e81Swyllys 			/* Try odd ASN.1 variations */
97630a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
97702744e81Swyllys 			    &filedata);
97802744e81Swyllys 			if (rv == KMF_OK) {
97902744e81Swyllys 				(void) readAltFormatPrivateKey(&filedata,
98002744e81Swyllys 				    &pkey);
98130a5e8faSwyllys 				kmf_free_data(&filedata);
98202744e81Swyllys 			}
98302744e81Swyllys 		}
98402744e81Swyllys 	} else if (format == KMF_FORMAT_PEM ||
98502744e81Swyllys 	    format == KMF_FORMAT_PEM_KEYPAIR) {
98699ebb4caSwyllys 		pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
98702744e81Swyllys 		if (pkey == NULL) {
98802744e81Swyllys 			KMF_DATA derdata;
98902744e81Swyllys 			/*
99002744e81Swyllys 			 * Check if this is the alt. format
99102744e81Swyllys 			 * RSA private key file.
99202744e81Swyllys 			 */
99330a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
99402744e81Swyllys 			    &filedata);
99502744e81Swyllys 			if (rv == KMF_OK) {
99602744e81Swyllys 				uchar_t *d = NULL;
99702744e81Swyllys 				int len;
99830a5e8faSwyllys 				rv = kmf_pem_to_der(filedata.Data,
99902744e81Swyllys 				    filedata.Length, &d, &len);
100002744e81Swyllys 				if (rv == KMF_OK && d != NULL) {
100102744e81Swyllys 					derdata.Data = d;
100202744e81Swyllys 					derdata.Length = (size_t)len;
100302744e81Swyllys 					(void) readAltFormatPrivateKey(
100402744e81Swyllys 					    &derdata, &pkey);
100502744e81Swyllys 					free(d);
100602744e81Swyllys 				}
100730a5e8faSwyllys 				kmf_free_data(&filedata);
100802744e81Swyllys 			}
100902744e81Swyllys 		}
101002744e81Swyllys 	}
101199ebb4caSwyllys 
101299ebb4caSwyllys end:
101399ebb4caSwyllys 	if (pkey == NULL)
101499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
101599ebb4caSwyllys 
101699ebb4caSwyllys 	if (keyfile != NULL)
101799ebb4caSwyllys 		(void) BIO_free(keyfile);
101899ebb4caSwyllys 
101999ebb4caSwyllys 	return (pkey);
102099ebb4caSwyllys }
102199ebb4caSwyllys 
102299ebb4caSwyllys KMF_RETURN
102330a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
102499ebb4caSwyllys {
102599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
102699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1027f482c776Swyllys 	int i, n;
1028f482c776Swyllys 	uint32_t maxcerts = 0;
102930a5e8faSwyllys 	uint32_t *num_certs;
103030a5e8faSwyllys 	KMF_X509_DER_CERT *kmf_cert = NULL;
103130a5e8faSwyllys 	char *dirpath = NULL;
103230a5e8faSwyllys 	char *filename = NULL;
103330a5e8faSwyllys 	char *fullpath = NULL;
103430a5e8faSwyllys 	char *issuer = NULL;
103530a5e8faSwyllys 	char *subject = NULL;
103630a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
103730a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
103899ebb4caSwyllys 
103930a5e8faSwyllys 	num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
104030a5e8faSwyllys 	if (num_certs == NULL)
104199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
104299ebb4caSwyllys 
104330a5e8faSwyllys 	/* num_certs should reference the size of kmf_cert */
1044f482c776Swyllys 	maxcerts = *num_certs;
1045f482c776Swyllys 	if (maxcerts == 0)
1046f482c776Swyllys 		maxcerts = 0xFFFFFFFF;
104799ebb4caSwyllys 	*num_certs = 0;
104899ebb4caSwyllys 
104930a5e8faSwyllys 	/* Get the optional returned certificate list  */
105030a5e8faSwyllys 	kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
105130a5e8faSwyllys 	    numattr);
105299ebb4caSwyllys 
105330a5e8faSwyllys 	/*
105430a5e8faSwyllys 	 * The dirpath attribute and the filename attribute can not be NULL
105530a5e8faSwyllys 	 * at the same time.
105630a5e8faSwyllys 	 */
105730a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
105830a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
105930a5e8faSwyllys 	    numattr);
106030a5e8faSwyllys 
106130a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
106299ebb4caSwyllys 	if (fullpath == NULL)
106399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
106499ebb4caSwyllys 
106530a5e8faSwyllys 	/* Get optional search criteria attributes */
106630a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
106730a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
106830a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
106930a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
107030a5e8faSwyllys 	    &validity, NULL);
107130a5e8faSwyllys 	if (rv != KMF_OK) {
107230a5e8faSwyllys 		validity = KMF_ALL_CERTS;
107330a5e8faSwyllys 		rv = KMF_OK;
107430a5e8faSwyllys 	}
107530a5e8faSwyllys 
107699ebb4caSwyllys 	if (isdir(fullpath)) {
107799ebb4caSwyllys 		DIR *dirp;
107899ebb4caSwyllys 		struct dirent *dp;
107999ebb4caSwyllys 
1080f482c776Swyllys 		n = 0;
108199ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
108299ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
108399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
108499ebb4caSwyllys 		}
108599ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
108699ebb4caSwyllys 			char *fname;
108771593db2Swyllys 			KMF_DATA *certlist = NULL;
1088f482c776Swyllys 			uint32_t loaded_certs = 0;
108971593db2Swyllys 
109099ebb4caSwyllys 			if (strcmp(dp->d_name, ".") == 0 ||
109199ebb4caSwyllys 			    strcmp(dp->d_name, "..") == 0)
109299ebb4caSwyllys 				continue;
109399ebb4caSwyllys 
109434acef67Swyllys 			fname = get_fullpath(fullpath, (char *)&dp->d_name);
109599ebb4caSwyllys 
109630a5e8faSwyllys 			rv = load_certs(kmfh, issuer, subject, serial,
109730a5e8faSwyllys 			    validity, fname, &certlist,	&loaded_certs);
109899ebb4caSwyllys 
109999ebb4caSwyllys 			if (rv != KMF_OK) {
110099ebb4caSwyllys 				free(fname);
110171593db2Swyllys 				if (certlist != NULL) {
1102f482c776Swyllys 					for (i = 0; i < loaded_certs; i++)
110330a5e8faSwyllys 						kmf_free_data(&certlist[i]);
110471593db2Swyllys 					free(certlist);
110571593db2Swyllys 				}
110699ebb4caSwyllys 				continue;
110799ebb4caSwyllys 			}
110899ebb4caSwyllys 
110999ebb4caSwyllys 			/* If load succeeds, add certdata to the list */
111099ebb4caSwyllys 			if (kmf_cert != NULL) {
1111f482c776Swyllys 				for (i = 0; i < loaded_certs &&
1112b4058258Swyllys 				    n < maxcerts; i++) {
111371593db2Swyllys 					kmf_cert[n].certificate.Data =
111471593db2Swyllys 					    certlist[i].Data;
111599ebb4caSwyllys 					kmf_cert[n].certificate.Length =
111671593db2Swyllys 					    certlist[i].Length;
111799ebb4caSwyllys 
111899ebb4caSwyllys 					kmf_cert[n].kmf_private.keystore_type =
111999ebb4caSwyllys 					    KMF_KEYSTORE_OPENSSL;
112099ebb4caSwyllys 					kmf_cert[n].kmf_private.flags =
112199ebb4caSwyllys 					    KMF_FLAG_CERT_VALID;
112271593db2Swyllys 					kmf_cert[n].kmf_private.label =
112371593db2Swyllys 					    strdup(fname);
112499ebb4caSwyllys 					n++;
112599ebb4caSwyllys 				}
1126b4058258Swyllys 				/*
1127b4058258Swyllys 				 * If maxcerts < loaded_certs, clean up the
1128b4058258Swyllys 				 * certs that were not used.
1129b4058258Swyllys 				 */
1130f482c776Swyllys 				for (; i < loaded_certs; i++)
113130a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1132f482c776Swyllys 			} else {
1133f482c776Swyllys 				for (i = 0; i < loaded_certs; i++)
113430a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1135f482c776Swyllys 				n += loaded_certs;
113671593db2Swyllys 			}
1137f482c776Swyllys 			free(certlist);
113871593db2Swyllys 			free(fname);
113971593db2Swyllys 		}
114099ebb4caSwyllys 		(*num_certs) = n;
114199ebb4caSwyllys 		if (*num_certs == 0)
114299ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
114330a5e8faSwyllys 		if (*num_certs > 0)
114499ebb4caSwyllys 			rv = KMF_OK;
114599ebb4caSwyllys exit:
114699ebb4caSwyllys 		(void) closedir(dirp);
114799ebb4caSwyllys 	} else {
114871593db2Swyllys 		KMF_DATA *certlist = NULL;
1149f482c776Swyllys 		uint32_t loaded_certs = 0;
115071593db2Swyllys 
115130a5e8faSwyllys 		rv = load_certs(kmfh, issuer, subject, serial, validity,
115230a5e8faSwyllys 		    fullpath, &certlist, &loaded_certs);
115399ebb4caSwyllys 		if (rv != KMF_OK) {
115499ebb4caSwyllys 			free(fullpath);
115599ebb4caSwyllys 			return (rv);
115699ebb4caSwyllys 		}
115799ebb4caSwyllys 
1158f482c776Swyllys 		n = 0;
115971593db2Swyllys 		if (kmf_cert != NULL && certlist != NULL) {
1160f482c776Swyllys 			for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1161f482c776Swyllys 				kmf_cert[n].certificate.Data =
116271593db2Swyllys 				    certlist[i].Data;
1163f482c776Swyllys 				kmf_cert[n].certificate.Length =
116471593db2Swyllys 				    certlist[i].Length;
1165f482c776Swyllys 				kmf_cert[n].kmf_private.keystore_type =
116699ebb4caSwyllys 				    KMF_KEYSTORE_OPENSSL;
1167f482c776Swyllys 				kmf_cert[n].kmf_private.flags =
116871593db2Swyllys 				    KMF_FLAG_CERT_VALID;
1169f482c776Swyllys 				kmf_cert[n].kmf_private.label =
117071593db2Swyllys 				    strdup(fullpath);
1171f482c776Swyllys 				n++;
117271593db2Swyllys 			}
1173f482c776Swyllys 			/* If maxcerts < loaded_certs, clean up */
1174f482c776Swyllys 			for (; i < loaded_certs; i++)
117530a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1176f482c776Swyllys 		} else if (certlist != NULL) {
1177f482c776Swyllys 			for (i = 0; i < loaded_certs; i++)
117830a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1179f482c776Swyllys 			n = loaded_certs;
1180f482c776Swyllys 		}
118130a5e8faSwyllys 		if (certlist != NULL)
118271593db2Swyllys 			free(certlist);
1183f482c776Swyllys 		*num_certs = n;
118499ebb4caSwyllys 	}
118599ebb4caSwyllys 
118699ebb4caSwyllys 	free(fullpath);
118799ebb4caSwyllys 
118899ebb4caSwyllys 	return (rv);
118999ebb4caSwyllys }
119099ebb4caSwyllys 
119199ebb4caSwyllys void
119299ebb4caSwyllys /*ARGSUSED*/
119399ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
119499ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert)
119599ebb4caSwyllys {
119699ebb4caSwyllys 	if (kmf_cert != NULL) {
119799ebb4caSwyllys 		if (kmf_cert->certificate.Data != NULL) {
119899ebb4caSwyllys 			free(kmf_cert->certificate.Data);
119999ebb4caSwyllys 			kmf_cert->certificate.Data = NULL;
120099ebb4caSwyllys 			kmf_cert->certificate.Length = 0;
120199ebb4caSwyllys 		}
120299ebb4caSwyllys 		if (kmf_cert->kmf_private.label)
120399ebb4caSwyllys 			free(kmf_cert->kmf_private.label);
120499ebb4caSwyllys 	}
120599ebb4caSwyllys }
120699ebb4caSwyllys 
120730a5e8faSwyllys /*ARGSUSED*/
120899ebb4caSwyllys KMF_RETURN
120930a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
121099ebb4caSwyllys {
121199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
121230a5e8faSwyllys 	KMF_DATA *cert = NULL;
121330a5e8faSwyllys 	char *outfilename = NULL;
121430a5e8faSwyllys 	char *dirpath = NULL;
121530a5e8faSwyllys 	char *fullpath = NULL;
121699ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
121799ebb4caSwyllys 
121830a5e8faSwyllys 	/* Get the cert data */
121930a5e8faSwyllys 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
122030a5e8faSwyllys 	if (cert == NULL || cert->Data == NULL)
122199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
122299ebb4caSwyllys 
122330a5e8faSwyllys 	/* Check the output filename and directory attributes. */
122430a5e8faSwyllys 	outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
122530a5e8faSwyllys 	    numattr);
122630a5e8faSwyllys 	if (outfilename == NULL)
122730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
122899ebb4caSwyllys 
122930a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
123030a5e8faSwyllys 	fullpath = get_fullpath(dirpath, outfilename);
123199ebb4caSwyllys 	if (fullpath == NULL)
123230a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
123399ebb4caSwyllys 
123430a5e8faSwyllys 	/* Check the optional format attribute */
123530a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
123630a5e8faSwyllys 	    &format, NULL);
123730a5e8faSwyllys 	if (ret != KMF_OK) {
123830a5e8faSwyllys 		/* If there is no format attribute, then default to PEM */
123930a5e8faSwyllys 		format = KMF_FORMAT_PEM;
124099ebb4caSwyllys 		ret = KMF_OK;
124130a5e8faSwyllys 	} else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
124230a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
124399ebb4caSwyllys 		goto out;
124499ebb4caSwyllys 	}
124599ebb4caSwyllys 
124630a5e8faSwyllys 	/* Store the certificate in the file with the specified format */
124730a5e8faSwyllys 	ret = kmf_create_cert_file(cert, format, fullpath);
124899ebb4caSwyllys 
124999ebb4caSwyllys out:
125099ebb4caSwyllys 	if (fullpath != NULL)
125199ebb4caSwyllys 		free(fullpath);
125299ebb4caSwyllys 
125399ebb4caSwyllys 	return (ret);
125499ebb4caSwyllys }
125599ebb4caSwyllys 
125630a5e8faSwyllys 
125799ebb4caSwyllys KMF_RETURN
125830a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
125999ebb4caSwyllys {
126099ebb4caSwyllys 	KMF_RETURN rv;
126199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
126299ebb4caSwyllys 	KMF_DATA certdata = {NULL, 0};
126330a5e8faSwyllys 	char *dirpath = NULL;
126430a5e8faSwyllys 	char *filename = NULL;
126530a5e8faSwyllys 	char *fullpath = NULL;
126630a5e8faSwyllys 	char *issuer = NULL;
126730a5e8faSwyllys 	char *subject = NULL;
126830a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
126930a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
127099ebb4caSwyllys 
127130a5e8faSwyllys 	/*
127230a5e8faSwyllys 	 * Get the DIRPATH and CERT_FILENAME attributes.  They can not be
127330a5e8faSwyllys 	 * NULL at the same time.
127430a5e8faSwyllys 	 */
127530a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
127630a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
127730a5e8faSwyllys 	    numattr);
127830a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
127999ebb4caSwyllys 	if (fullpath == NULL)
128099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
128199ebb4caSwyllys 
128230a5e8faSwyllys 	/* Get optional search criteria attributes */
128330a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
128430a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
128530a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
128630a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
128730a5e8faSwyllys 	    &validity, NULL);
128830a5e8faSwyllys 	if (rv != KMF_OK) {
128930a5e8faSwyllys 		validity = KMF_ALL_CERTS;
129030a5e8faSwyllys 		rv = KMF_OK;
129130a5e8faSwyllys 	}
129230a5e8faSwyllys 
129399ebb4caSwyllys 	if (isdir(fullpath)) {
129499ebb4caSwyllys 		DIR *dirp;
129599ebb4caSwyllys 		struct dirent *dp;
129699ebb4caSwyllys 
129799ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
129899ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
129999ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
130099ebb4caSwyllys 		}
130199ebb4caSwyllys 
130299ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
130399ebb4caSwyllys 			if (strcmp(dp->d_name, ".") != 0 &&
130499ebb4caSwyllys 			    strcmp(dp->d_name, "..") != 0) {
130599ebb4caSwyllys 				char *fname;
130699ebb4caSwyllys 
130799ebb4caSwyllys 				fname = get_fullpath(fullpath,
130899ebb4caSwyllys 				    (char *)&dp->d_name);
130999ebb4caSwyllys 
131099ebb4caSwyllys 				if (fname == NULL) {
131199ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
131299ebb4caSwyllys 					break;
131399ebb4caSwyllys 				}
131499ebb4caSwyllys 
131530a5e8faSwyllys 				rv = kmf_load_cert(kmfh, issuer, subject,
131630a5e8faSwyllys 				    serial, validity, fname, &certdata);
131799ebb4caSwyllys 
131899ebb4caSwyllys 				if (rv == KMF_ERR_CERT_NOT_FOUND) {
131999ebb4caSwyllys 					free(fname);
132099ebb4caSwyllys 					if (certdata.Data)
132199ebb4caSwyllys 						free(certdata.Data);
132299ebb4caSwyllys 					rv = KMF_OK;
132399ebb4caSwyllys 					continue;
132499ebb4caSwyllys 				} else if (rv != KMF_OK) {
132599ebb4caSwyllys 					free(fname);
132699ebb4caSwyllys 					break;
132799ebb4caSwyllys 				}
132899ebb4caSwyllys 
132999ebb4caSwyllys 				if (unlink(fname) != 0) {
133099ebb4caSwyllys 					SET_SYS_ERROR(kmfh, errno);
133199ebb4caSwyllys 					rv = KMF_ERR_INTERNAL;
133299ebb4caSwyllys 					free(fname);
133399ebb4caSwyllys 					break;
133499ebb4caSwyllys 				}
133599ebb4caSwyllys 				free(fname);
133699ebb4caSwyllys 				if (certdata.Data)
133799ebb4caSwyllys 					free(certdata.Data);
133899ebb4caSwyllys 			}
133999ebb4caSwyllys 		}
134099ebb4caSwyllys 		(void) closedir(dirp);
134199ebb4caSwyllys 	} else {
134299ebb4caSwyllys 		/* Just try to load a single certificate */
134330a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
134430a5e8faSwyllys 		    fullpath, &certdata);
134599ebb4caSwyllys 		if (rv == KMF_OK) {
134699ebb4caSwyllys 			if (unlink(fullpath) != 0) {
134799ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
134899ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
134999ebb4caSwyllys 			}
135099ebb4caSwyllys 		}
135199ebb4caSwyllys 	}
135299ebb4caSwyllys 
135399ebb4caSwyllys out:
135499ebb4caSwyllys 	if (fullpath != NULL)
135599ebb4caSwyllys 		free(fullpath);
135699ebb4caSwyllys 
135799ebb4caSwyllys 	if (certdata.Data)
135899ebb4caSwyllys 		free(certdata.Data);
135999ebb4caSwyllys 
136099ebb4caSwyllys 	return (rv);
136199ebb4caSwyllys }
136299ebb4caSwyllys 
136399ebb4caSwyllys KMF_RETURN
136499ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
136599ebb4caSwyllys 	KMF_DATA *keydata)
136699ebb4caSwyllys {
136799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
136899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
136999ebb4caSwyllys 	int n;
137099ebb4caSwyllys 
137199ebb4caSwyllys 	if (key == NULL || keydata == NULL ||
137299ebb4caSwyllys 	    key->keyp == NULL)
137399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
137499ebb4caSwyllys 
137599ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
137699ebb4caSwyllys 		RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
137799ebb4caSwyllys 
137899ebb4caSwyllys 		if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
137999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
138099ebb4caSwyllys 			return (KMF_ERR_ENCODING);
138199ebb4caSwyllys 		}
138299ebb4caSwyllys 		RSA_free(pubkey);
138399ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
138499ebb4caSwyllys 		DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
138599ebb4caSwyllys 
138699ebb4caSwyllys 		if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
138799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
138899ebb4caSwyllys 			return (KMF_ERR_ENCODING);
138999ebb4caSwyllys 		}
139099ebb4caSwyllys 		DSA_free(pubkey);
139199ebb4caSwyllys 	} else {
139299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
139399ebb4caSwyllys 	}
139499ebb4caSwyllys 	keydata->Length = n;
139599ebb4caSwyllys 
139699ebb4caSwyllys cleanup:
139799ebb4caSwyllys 	if (rv != KMF_OK) {
139899ebb4caSwyllys 		if (keydata->Data)
139999ebb4caSwyllys 			free(keydata->Data);
140099ebb4caSwyllys 		keydata->Data = NULL;
140199ebb4caSwyllys 		keydata->Length = 0;
140299ebb4caSwyllys 	}
140399ebb4caSwyllys 
140499ebb4caSwyllys 	return (rv);
140599ebb4caSwyllys }
140699ebb4caSwyllys 
140799ebb4caSwyllys static KMF_RETURN
140830a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
140930a5e8faSwyllys 	KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
141099ebb4caSwyllys {
141199ebb4caSwyllys 	int rv = 0;
141299ebb4caSwyllys 	RSA *rsa;
141399ebb4caSwyllys 	DSA *dsa;
141499ebb4caSwyllys 
14155b3e1433Swyllys 	if (pkey == NULL || out == NULL)
14165b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
14175b3e1433Swyllys 
141899ebb4caSwyllys 	switch (format) {
1419*73cc0e02Swyllys 		case KMF_FORMAT_RAWKEY:
1420*73cc0e02Swyllys 			/* same as ASN.1 */
142199ebb4caSwyllys 		case KMF_FORMAT_ASN1:
142299ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
142399ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
142430a5e8faSwyllys 				if (private)
142599ebb4caSwyllys 					rv = i2d_RSAPrivateKey_bio(out, rsa);
142630a5e8faSwyllys 				else
142730a5e8faSwyllys 					rv = i2d_RSAPublicKey_bio(out, rsa);
142899ebb4caSwyllys 				RSA_free(rsa);
142999ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
143099ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
143199ebb4caSwyllys 				rv = i2d_DSAPrivateKey_bio(out, dsa);
143299ebb4caSwyllys 				DSA_free(dsa);
143399ebb4caSwyllys 			}
143499ebb4caSwyllys 			if (rv == 1) {
143599ebb4caSwyllys 				rv = KMF_OK;
143699ebb4caSwyllys 			} else {
143799ebb4caSwyllys 				SET_ERROR(kmfh, rv);
143899ebb4caSwyllys 			}
143999ebb4caSwyllys 			break;
144099ebb4caSwyllys 		case KMF_FORMAT_PEM:
144199ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
144299ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
144330a5e8faSwyllys 				if (private)
144499ebb4caSwyllys 					rv = PEM_write_bio_RSAPrivateKey(out,
144530a5e8faSwyllys 					    rsa, NULL, NULL, 0, NULL,
144630a5e8faSwyllys 					    (cred != NULL ? cred->cred : NULL));
144730a5e8faSwyllys 				else
144830a5e8faSwyllys 					rv = PEM_write_bio_RSAPublicKey(out,
144930a5e8faSwyllys 					    rsa);
145099ebb4caSwyllys 				RSA_free(rsa);
145199ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
145299ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
145399ebb4caSwyllys 				rv = PEM_write_bio_DSAPrivateKey(out,
145430a5e8faSwyllys 				    dsa, NULL, NULL, 0, NULL,
145530a5e8faSwyllys 				    (cred != NULL ? cred->cred : NULL));
145699ebb4caSwyllys 				DSA_free(dsa);
145799ebb4caSwyllys 			}
145899ebb4caSwyllys 
145999ebb4caSwyllys 			if (rv == 1) {
146099ebb4caSwyllys 				rv = KMF_OK;
146199ebb4caSwyllys 			} else {
146299ebb4caSwyllys 				SET_ERROR(kmfh, rv);
146399ebb4caSwyllys 			}
146499ebb4caSwyllys 			break;
146599ebb4caSwyllys 
146699ebb4caSwyllys 		default:
146799ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
146899ebb4caSwyllys 	}
146999ebb4caSwyllys 
147099ebb4caSwyllys 	return (rv);
147199ebb4caSwyllys }
147299ebb4caSwyllys 
147399ebb4caSwyllys KMF_RETURN
147430a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
147530a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
147699ebb4caSwyllys {
147799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
147899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
147999ebb4caSwyllys 	uint32_t eValue = 0x010001;
148099ebb4caSwyllys 	RSA *sslPrivKey = NULL;
148199ebb4caSwyllys 	DSA *sslDSAKey = NULL;
148299ebb4caSwyllys 	EVP_PKEY *eprikey = NULL;
148399ebb4caSwyllys 	EVP_PKEY *epubkey = NULL;
148499ebb4caSwyllys 	BIO *out = NULL;
148530a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
148630a5e8faSwyllys 	uint32_t keylen = 1024;
148730a5e8faSwyllys 	uint32_t keylen_size = sizeof (uint32_t);
148830a5e8faSwyllys 	boolean_t storekey = TRUE;
148930a5e8faSwyllys 	KMF_KEY_ALG keytype = KMF_RSA;
149099ebb4caSwyllys 
149130a5e8faSwyllys 	rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
149230a5e8faSwyllys 	    &storekey, NULL);
149330a5e8faSwyllys 	if (rv != KMF_OK) {
149430a5e8faSwyllys 		/* "storekey" is optional. Default is TRUE */
149530a5e8faSwyllys 		rv = KMF_OK;
149699ebb4caSwyllys 	}
149799ebb4caSwyllys 
149830a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
149930a5e8faSwyllys 	    (void *)&keytype, NULL);
150030a5e8faSwyllys 	if (rv != KMF_OK)
150130a5e8faSwyllys 		/* keytype is optional.  KMF_RSA is default */
150230a5e8faSwyllys 		rv = KMF_OK;
150399ebb4caSwyllys 
150430a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
150530a5e8faSwyllys 	if (pubkey == NULL)
150699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
150799ebb4caSwyllys 
150830a5e8faSwyllys 	privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
150930a5e8faSwyllys 	if (privkey == NULL)
151030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
151130a5e8faSwyllys 
151230a5e8faSwyllys 	(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
151330a5e8faSwyllys 	(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
151499ebb4caSwyllys 
151599ebb4caSwyllys 	eprikey = EVP_PKEY_new();
151699ebb4caSwyllys 	if (eprikey == NULL) {
151799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
151899ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
151999ebb4caSwyllys 		goto cleanup;
152099ebb4caSwyllys 	}
152199ebb4caSwyllys 	epubkey = EVP_PKEY_new();
152299ebb4caSwyllys 	if (epubkey == NULL) {
152399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
152499ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
152599ebb4caSwyllys 		goto cleanup;
152699ebb4caSwyllys 	}
152730a5e8faSwyllys 	if (keytype == KMF_RSA) {
152830a5e8faSwyllys 		KMF_BIGINT *rsaexp = NULL;
152999ebb4caSwyllys 
153030a5e8faSwyllys 		rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
153130a5e8faSwyllys 		if (rsaexp != NULL) {
153230a5e8faSwyllys 			if (rsaexp->len > 0 &&
153330a5e8faSwyllys 			    rsaexp->len <= sizeof (eValue) &&
153430a5e8faSwyllys 			    rsaexp->val != NULL) {
153530a5e8faSwyllys 				/*LINTED*/
153630a5e8faSwyllys 				eValue = *(uint32_t *)rsaexp->val;
153730a5e8faSwyllys 			} else {
153830a5e8faSwyllys 				rv = KMF_ERR_BAD_PARAMETER;
153930a5e8faSwyllys 				goto cleanup;
154030a5e8faSwyllys 			}
154130a5e8faSwyllys 		} else {
154230a5e8faSwyllys 			/* RSA Exponent is optional. Default is 0x10001 */
154330a5e8faSwyllys 			rv = KMF_OK;
154430a5e8faSwyllys 		}
154530a5e8faSwyllys 
154630a5e8faSwyllys 		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
154730a5e8faSwyllys 		    &keylen, &keylen_size);
154830a5e8faSwyllys 		if (rv == KMF_ERR_ATTR_NOT_FOUND)
154930a5e8faSwyllys 			/* keylen is optional, default is 1024 */
155030a5e8faSwyllys 			rv = KMF_OK;
155130a5e8faSwyllys 		if (rv != KMF_OK) {
155230a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
155330a5e8faSwyllys 			goto cleanup;
155430a5e8faSwyllys 		}
155530a5e8faSwyllys 
155630a5e8faSwyllys 		sslPrivKey = RSA_generate_key(keylen, eValue, NULL, NULL);
155799ebb4caSwyllys 		if (sslPrivKey == NULL) {
155899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
155999ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
156099ebb4caSwyllys 		} else {
156130a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
156299ebb4caSwyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
156399ebb4caSwyllys 			privkey->keyalg = KMF_RSA;
156499ebb4caSwyllys 			privkey->keyclass = KMF_ASYM_PRI;
156599ebb4caSwyllys 			privkey->israw = FALSE;
156699ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
156730a5e8faSwyllys 
156899ebb4caSwyllys 			/* OpenSSL derives the public key from the private */
156930a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
157099ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
157199ebb4caSwyllys 			pubkey->keyalg = KMF_RSA;
157299ebb4caSwyllys 			pubkey->israw = FALSE;
157399ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
157499ebb4caSwyllys 			pubkey->keyp = (void *)epubkey;
157599ebb4caSwyllys 		}
157630a5e8faSwyllys 	} else if (keytype == KMF_DSA) {
157730a5e8faSwyllys 		DSA *dp;
157899ebb4caSwyllys 		sslDSAKey = DSA_new();
157999ebb4caSwyllys 		if (sslDSAKey == NULL) {
158099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
158199ebb4caSwyllys 			return (KMF_ERR_MEMORY);
158299ebb4caSwyllys 		}
158399ebb4caSwyllys 
158499ebb4caSwyllys 		if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) ==
158599ebb4caSwyllys 		    NULL) {
158699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
158799ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
158899ebb4caSwyllys 			goto cleanup;
158999ebb4caSwyllys 		}
159099ebb4caSwyllys 		if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) ==
159199ebb4caSwyllys 		    NULL) {
159299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
159399ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
159499ebb4caSwyllys 			goto cleanup;
159599ebb4caSwyllys 		}
159699ebb4caSwyllys 		if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) ==
159799ebb4caSwyllys 		    NULL) {
159899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
159999ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
160099ebb4caSwyllys 			goto cleanup;
160199ebb4caSwyllys 		}
160299ebb4caSwyllys 
160399ebb4caSwyllys 		if (!DSA_generate_key(sslDSAKey)) {
160499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
160599ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
160699ebb4caSwyllys 			goto cleanup;
160799ebb4caSwyllys 		}
160899ebb4caSwyllys 
160999ebb4caSwyllys 		privkey->kstype = KMF_KEYSTORE_OPENSSL;
161099ebb4caSwyllys 		privkey->keyalg = KMF_DSA;
161199ebb4caSwyllys 		privkey->keyclass = KMF_ASYM_PRI;
161299ebb4caSwyllys 		privkey->israw = FALSE;
161399ebb4caSwyllys 		if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
161499ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
161599ebb4caSwyllys 		} else {
161699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
161799ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
161899ebb4caSwyllys 			goto cleanup;
161999ebb4caSwyllys 		}
162030a5e8faSwyllys 		dp = DSA_new();
162199ebb4caSwyllys 		/* Make a copy for the public key */
162299ebb4caSwyllys 		if (dp != NULL) {
162399ebb4caSwyllys 			if ((dp->p = BN_new()) == NULL) {
162499ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
162599ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
162699ebb4caSwyllys 				DSA_free(dp);
162799ebb4caSwyllys 				goto cleanup;
162899ebb4caSwyllys 			}
162999ebb4caSwyllys 			if ((dp->q = BN_new()) == NULL) {
163099ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
163199ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
163299ebb4caSwyllys 				BN_free(dp->p);
163399ebb4caSwyllys 				DSA_free(dp);
163499ebb4caSwyllys 				goto cleanup;
163599ebb4caSwyllys 			}
163699ebb4caSwyllys 			if ((dp->g = BN_new()) == NULL) {
163799ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
163899ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
163999ebb4caSwyllys 				BN_free(dp->q);
164099ebb4caSwyllys 				BN_free(dp->p);
164199ebb4caSwyllys 				DSA_free(dp);
164299ebb4caSwyllys 				goto cleanup;
164399ebb4caSwyllys 			}
164499ebb4caSwyllys 			if ((dp->pub_key = BN_new()) == NULL) {
164599ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
164699ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
164799ebb4caSwyllys 				BN_free(dp->q);
164899ebb4caSwyllys 				BN_free(dp->p);
164999ebb4caSwyllys 				BN_free(dp->g);
165099ebb4caSwyllys 				DSA_free(dp);
165199ebb4caSwyllys 				goto cleanup;
165299ebb4caSwyllys 			}
165399ebb4caSwyllys 			(void) BN_copy(dp->p, sslDSAKey->p);
165499ebb4caSwyllys 			(void) BN_copy(dp->q, sslDSAKey->q);
165599ebb4caSwyllys 			(void) BN_copy(dp->g, sslDSAKey->g);
165699ebb4caSwyllys 			(void) BN_copy(dp->pub_key, sslDSAKey->pub_key);
165799ebb4caSwyllys 
165899ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
165999ebb4caSwyllys 			pubkey->keyalg = KMF_DSA;
166099ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
166199ebb4caSwyllys 			pubkey->israw = FALSE;
166299ebb4caSwyllys 
166399ebb4caSwyllys 			if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
166499ebb4caSwyllys 				pubkey->keyp = (void *)epubkey;
166599ebb4caSwyllys 			} else {
166699ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
166799ebb4caSwyllys 				rv = KMF_ERR_KEYGEN_FAILED;
166899ebb4caSwyllys 				goto cleanup;
166999ebb4caSwyllys 			}
167099ebb4caSwyllys 		}
167199ebb4caSwyllys 	}
167299ebb4caSwyllys 
167399ebb4caSwyllys 	if (rv != KMF_OK) {
167499ebb4caSwyllys 		goto cleanup;
167599ebb4caSwyllys 	}
167699ebb4caSwyllys 
167730a5e8faSwyllys 	if (storekey) {
167830a5e8faSwyllys 		KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
167930a5e8faSwyllys 		int i = 0;
168030a5e8faSwyllys 		char *keyfile = NULL, *dirpath = NULL;
168130a5e8faSwyllys 		KMF_ENCODE_FORMAT format;
168230a5e8faSwyllys 		/*
168330a5e8faSwyllys 		 * Construct a new attribute arrray and call openssl_store_key
168430a5e8faSwyllys 		 */
168530a5e8faSwyllys 		kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
168630a5e8faSwyllys 		    privkey, sizeof (privkey));
168730a5e8faSwyllys 		i++;
168830a5e8faSwyllys 
168930a5e8faSwyllys 		dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
169030a5e8faSwyllys 		if (dirpath != NULL) {
169130a5e8faSwyllys 			storeattrs[i].type = KMF_DIRPATH_ATTR;
169230a5e8faSwyllys 			storeattrs[i].pValue = dirpath;
169330a5e8faSwyllys 			storeattrs[i].valueLen = strlen(dirpath);
169430a5e8faSwyllys 			i++;
169530a5e8faSwyllys 		} else {
169630a5e8faSwyllys 			rv = KMF_OK; /* DIRPATH is optional */
169799ebb4caSwyllys 		}
169830a5e8faSwyllys 		keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
169930a5e8faSwyllys 		    attrlist, numattr);
170030a5e8faSwyllys 		if (keyfile != NULL) {
170130a5e8faSwyllys 			storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
170230a5e8faSwyllys 			storeattrs[i].pValue = keyfile;
170330a5e8faSwyllys 			storeattrs[i].valueLen = strlen(keyfile);
170430a5e8faSwyllys 			i++;
170530a5e8faSwyllys 		} else {
170630a5e8faSwyllys 			goto cleanup; /* KEYFILE is required */
170730a5e8faSwyllys 		}
170830a5e8faSwyllys 		rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
170930a5e8faSwyllys 		    (void *)&format, NULL);
171030a5e8faSwyllys 		if (rv == KMF_OK) {
171130a5e8faSwyllys 			storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
171230a5e8faSwyllys 			storeattrs[i].pValue = &format;
171330a5e8faSwyllys 			storeattrs[i].valueLen = sizeof (format);
171430a5e8faSwyllys 			i++;
171530a5e8faSwyllys 		}
171630a5e8faSwyllys 
171730a5e8faSwyllys 		rv = OpenSSL_StoreKey(handle, i, storeattrs);
171830a5e8faSwyllys 	}
171999ebb4caSwyllys 
172099ebb4caSwyllys cleanup:
172199ebb4caSwyllys 	if (rv != KMF_OK) {
172299ebb4caSwyllys 		if (eprikey != NULL)
172399ebb4caSwyllys 			EVP_PKEY_free(eprikey);
172499ebb4caSwyllys 
172599ebb4caSwyllys 		if (epubkey != NULL)
172699ebb4caSwyllys 			EVP_PKEY_free(epubkey);
172799ebb4caSwyllys 
172899ebb4caSwyllys 		if (pubkey->keylabel) {
172999ebb4caSwyllys 			free(pubkey->keylabel);
173099ebb4caSwyllys 			pubkey->keylabel = NULL;
173199ebb4caSwyllys 		}
173299ebb4caSwyllys 
173399ebb4caSwyllys 		if (privkey->keylabel) {
173499ebb4caSwyllys 			free(privkey->keylabel);
173599ebb4caSwyllys 			privkey->keylabel = NULL;
173699ebb4caSwyllys 		}
173799ebb4caSwyllys 
173899ebb4caSwyllys 		pubkey->keyp = NULL;
173999ebb4caSwyllys 		privkey->keyp = NULL;
174099ebb4caSwyllys 	}
174199ebb4caSwyllys 
174299ebb4caSwyllys 	if (sslPrivKey)
174399ebb4caSwyllys 		RSA_free(sslPrivKey);
174499ebb4caSwyllys 
174599ebb4caSwyllys 	if (sslDSAKey)
174699ebb4caSwyllys 		DSA_free(sslDSAKey);
174799ebb4caSwyllys 
174899ebb4caSwyllys 	if (out != NULL)
174999ebb4caSwyllys 		(void) BIO_free(out);
175099ebb4caSwyllys 
175199ebb4caSwyllys 	return (rv);
175299ebb4caSwyllys }
175399ebb4caSwyllys 
175499ebb4caSwyllys KMF_RETURN
175599ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
175699ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
175799ebb4caSwyllys {
175899ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
175999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
176099ebb4caSwyllys 	KMF_ALGORITHM_INDEX		AlgId;
176199ebb4caSwyllys 	EVP_MD_CTX ctx;
176299ebb4caSwyllys 	const EVP_MD *md;
176302744e81Swyllys 
176499ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
176599ebb4caSwyllys 	    tobesigned == NULL || output == NULL ||
176699ebb4caSwyllys 	    tobesigned->Data == NULL ||
176799ebb4caSwyllys 	    output->Data == NULL)
176899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
176999ebb4caSwyllys 
177099ebb4caSwyllys 	/* Map the OID to an OpenSSL algorithm */
177130a5e8faSwyllys 	AlgId = x509_algoid_to_algid(AlgOID);
177299ebb4caSwyllys 	if (AlgId == KMF_ALGID_NONE)
177399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
177499ebb4caSwyllys 
177599ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
177699ebb4caSwyllys 		EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
177799ebb4caSwyllys 		uchar_t *p;
177802744e81Swyllys 		int len;
177999ebb4caSwyllys 		if (AlgId == KMF_ALGID_MD5WithRSA)
178099ebb4caSwyllys 			md = EVP_md5();
178199ebb4caSwyllys 		else if (AlgId == KMF_ALGID_MD2WithRSA)
178299ebb4caSwyllys 			md = EVP_md2();
178399ebb4caSwyllys 		else if (AlgId == KMF_ALGID_SHA1WithRSA)
178499ebb4caSwyllys 			md = EVP_sha1();
178502744e81Swyllys 		else if (AlgId == KMF_ALGID_RSA)
178602744e81Swyllys 			md = NULL;
178799ebb4caSwyllys 		else
178899ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
178999ebb4caSwyllys 
179002744e81Swyllys 		if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
179102744e81Swyllys 			RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
179299ebb4caSwyllys 
179302744e81Swyllys 			p = output->Data;
179402744e81Swyllys 			if ((len = RSA_private_encrypt(tobesigned->Length,
179502744e81Swyllys 			    tobesigned->Data, p, rsa,
179602744e81Swyllys 			    RSA_PKCS1_PADDING)) <= 0) {
179702744e81Swyllys 				SET_ERROR(kmfh, ERR_get_error());
179802744e81Swyllys 				ret = KMF_ERR_INTERNAL;
179902744e81Swyllys 			}
180002744e81Swyllys 			output->Length = len;
180102744e81Swyllys 		} else {
180299ebb4caSwyllys 			(void) EVP_MD_CTX_init(&ctx);
180399ebb4caSwyllys 			(void) EVP_SignInit_ex(&ctx, md, NULL);
180499ebb4caSwyllys 			(void) EVP_SignUpdate(&ctx, tobesigned->Data,
180599ebb4caSwyllys 			    (uint32_t)tobesigned->Length);
180699ebb4caSwyllys 			len = (uint32_t)output->Length;
180799ebb4caSwyllys 			p = output->Data;
180802744e81Swyllys 			if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) {
180999ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
181002744e81Swyllys 				len = 0;
181102744e81Swyllys 				ret = KMF_ERR_INTERNAL;
181299ebb4caSwyllys 			}
181399ebb4caSwyllys 			output->Length = len;
181499ebb4caSwyllys 			(void) EVP_MD_CTX_cleanup(&ctx);
181502744e81Swyllys 		}
181699ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
181799ebb4caSwyllys 		DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
181899ebb4caSwyllys 
181999ebb4caSwyllys 		uchar_t hash[EVP_MAX_MD_SIZE];
182099ebb4caSwyllys 		uint32_t hashlen;
182199ebb4caSwyllys 		DSA_SIG *dsasig;
182299ebb4caSwyllys 
182399ebb4caSwyllys 		/*
182499ebb4caSwyllys 		 * OpenSSL EVP_Sign operation automatically converts to
182599ebb4caSwyllys 		 * ASN.1 output so we do the operations separately so we
182699ebb4caSwyllys 		 * are assured of NOT getting ASN.1 output returned.
182799ebb4caSwyllys 		 * KMF does not want ASN.1 encoded results because
182899ebb4caSwyllys 		 * not all mechanisms return ASN.1 encodings (PKCS#11
182999ebb4caSwyllys 		 * and NSS return raw signature data).
183099ebb4caSwyllys 		 */
183199ebb4caSwyllys 		md = EVP_sha1();
183299ebb4caSwyllys 		EVP_MD_CTX_init(&ctx);
183399ebb4caSwyllys 		(void) EVP_DigestInit_ex(&ctx, md, NULL);
183499ebb4caSwyllys 		(void) EVP_DigestUpdate(&ctx, tobesigned->Data,
183599ebb4caSwyllys 		    tobesigned->Length);
183699ebb4caSwyllys 		(void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
183799ebb4caSwyllys 		(void) EVP_MD_CTX_cleanup(&ctx);
183899ebb4caSwyllys 
183999ebb4caSwyllys 		dsasig = DSA_do_sign(hash, hashlen, dsa);
184099ebb4caSwyllys 		if (dsasig != NULL) {
184199ebb4caSwyllys 			int i;
184299ebb4caSwyllys 			output->Length = i = BN_bn2bin(dsasig->r, output->Data);
184399ebb4caSwyllys 			output->Length += BN_bn2bin(dsasig->s,
184499ebb4caSwyllys 			    &output->Data[i]);
184599ebb4caSwyllys 			DSA_SIG_free(dsasig);
184699ebb4caSwyllys 		} else {
184799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
184899ebb4caSwyllys 		}
184999ebb4caSwyllys 	} else {
185099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
185199ebb4caSwyllys 	}
185299ebb4caSwyllys cleanup:
185399ebb4caSwyllys 	return (ret);
185499ebb4caSwyllys }
185599ebb4caSwyllys 
185699ebb4caSwyllys KMF_RETURN
185799ebb4caSwyllys /*ARGSUSED*/
185830a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle,
185930a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
186099ebb4caSwyllys {
186199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
186230a5e8faSwyllys 	KMF_KEY_HANDLE *key;
186330a5e8faSwyllys 	boolean_t destroy = B_TRUE;
186430a5e8faSwyllys 
186530a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
186699ebb4caSwyllys 	if (key == NULL || key->keyp == NULL)
186799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
186899ebb4caSwyllys 
186930a5e8faSwyllys 	rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
187030a5e8faSwyllys 	    (void *)&destroy, NULL);
187130a5e8faSwyllys 	if (rv != KMF_OK) {
187230a5e8faSwyllys 		/* "destroy" is optional. Default is TRUE */
187330a5e8faSwyllys 		rv = KMF_OK;
187430a5e8faSwyllys 	}
187530a5e8faSwyllys 
187699ebb4caSwyllys 	if (key->keyclass != KMF_ASYM_PUB &&
187799ebb4caSwyllys 	    key->keyclass != KMF_ASYM_PRI &&
187899ebb4caSwyllys 	    key->keyclass != KMF_SYMMETRIC)
187999ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
188099ebb4caSwyllys 
188199ebb4caSwyllys 	if (key->keyclass == KMF_SYMMETRIC) {
188230a5e8faSwyllys 		kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
188399ebb4caSwyllys 		key->keyp = NULL;
188499ebb4caSwyllys 	} else {
188599ebb4caSwyllys 		if (key->keyp != NULL) {
188699ebb4caSwyllys 			EVP_PKEY_free(key->keyp);
188799ebb4caSwyllys 			key->keyp = NULL;
188899ebb4caSwyllys 		}
188999ebb4caSwyllys 	}
189099ebb4caSwyllys 
189199ebb4caSwyllys 	if (key->keylabel != NULL) {
189299ebb4caSwyllys 		EVP_PKEY *pkey = NULL;
189399ebb4caSwyllys 		/* If the file exists, make sure it is a proper key. */
189499ebb4caSwyllys 		pkey = openssl_load_key(handle, key->keylabel);
189599ebb4caSwyllys 		if (pkey == NULL) {
18965b3e1433Swyllys 			if (key->keylabel != NULL) {
189799ebb4caSwyllys 				free(key->keylabel);
189899ebb4caSwyllys 				key->keylabel = NULL;
18995b3e1433Swyllys 			}
190099ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
190199ebb4caSwyllys 		}
190299ebb4caSwyllys 		EVP_PKEY_free(pkey);
190399ebb4caSwyllys 
190499ebb4caSwyllys 		if (destroy) {
190599ebb4caSwyllys 			if (unlink(key->keylabel) != 0) {
190699ebb4caSwyllys 				KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
190799ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
190899ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
190999ebb4caSwyllys 			}
191099ebb4caSwyllys 		}
191199ebb4caSwyllys 		if (key->keylabel != NULL) {
191299ebb4caSwyllys 			free(key->keylabel);
191399ebb4caSwyllys 			key->keylabel = NULL;
191499ebb4caSwyllys 		}
191599ebb4caSwyllys 	}
191699ebb4caSwyllys 	return (rv);
191799ebb4caSwyllys }
191899ebb4caSwyllys 
191999ebb4caSwyllys KMF_RETURN
192099ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
192199ebb4caSwyllys {
192299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
192399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
192499ebb4caSwyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
192599ebb4caSwyllys 
192699ebb4caSwyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
192799ebb4caSwyllys 	if (strlen(str)) {
192899ebb4caSwyllys 		*msgstr = (char *)strdup(str);
192999ebb4caSwyllys 		if ((*msgstr) == NULL)
193099ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
193199ebb4caSwyllys 	} else {
193299ebb4caSwyllys 		*msgstr = NULL;
193399ebb4caSwyllys 	}
193499ebb4caSwyllys 
193599ebb4caSwyllys 	return (ret);
193699ebb4caSwyllys }
193799ebb4caSwyllys 
193899ebb4caSwyllys static int
193999ebb4caSwyllys ext2NID(int kmfext)
194099ebb4caSwyllys {
194199ebb4caSwyllys 	switch (kmfext) {
194299ebb4caSwyllys 		case KMF_X509_EXT_KEY_USAGE:
194399ebb4caSwyllys 			return (NID_key_usage);
194499ebb4caSwyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
194599ebb4caSwyllys 			return (NID_private_key_usage_period);
194699ebb4caSwyllys 		case KMF_X509_EXT_CERT_POLICIES:
194799ebb4caSwyllys 			return (NID_certificate_policies);
194899ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
194999ebb4caSwyllys 			return (NID_subject_alt_name);
195099ebb4caSwyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
195199ebb4caSwyllys 			return (NID_issuer_alt_name);
195299ebb4caSwyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
195399ebb4caSwyllys 			return (NID_basic_constraints);
195499ebb4caSwyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
195599ebb4caSwyllys 			return (NID_ext_key_usage);
195699ebb4caSwyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
195799ebb4caSwyllys 			return (NID_authority_key_identifier);
195899ebb4caSwyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
195999ebb4caSwyllys 			return (NID_crl_distribution_points);
196099ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
196199ebb4caSwyllys 			return (NID_subject_key_identifier);
196299ebb4caSwyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
196399ebb4caSwyllys 			return (OBJ_sn2nid("policyMappings"));
196499ebb4caSwyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
196599ebb4caSwyllys 			return (OBJ_sn2nid("nameConstraints"));
196699ebb4caSwyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
196799ebb4caSwyllys 			return (OBJ_sn2nid("policyConstraints"));
196899ebb4caSwyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
196999ebb4caSwyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
197099ebb4caSwyllys 		case KMF_X509_EXT_FRESHEST_CRL:
197199ebb4caSwyllys 			return (OBJ_sn2nid("freshestCRL"));
197299ebb4caSwyllys 		default:
197399ebb4caSwyllys 			return (NID_undef);
197499ebb4caSwyllys 	}
197599ebb4caSwyllys }
197699ebb4caSwyllys 
197799ebb4caSwyllys KMF_RETURN
197899ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
197999ebb4caSwyllys 	KMF_PRINTABLE_ITEM flag, char *resultStr)
198099ebb4caSwyllys {
198199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
198299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
198399ebb4caSwyllys 	X509 *xcert = NULL;
198499ebb4caSwyllys 	unsigned char *outbuf = NULL;
198599ebb4caSwyllys 	unsigned char *outbuf_p;
198699ebb4caSwyllys 	char *tmpstr = NULL;
198799ebb4caSwyllys 	int j;
198899ebb4caSwyllys 	int ext_index, nid, len;
198999ebb4caSwyllys 	BIO *mem = NULL;
199099ebb4caSwyllys 	STACK *emlst = NULL;
199199ebb4caSwyllys 	X509_EXTENSION *ex;
199299ebb4caSwyllys 	X509_CINF *ci;
199399ebb4caSwyllys 
199499ebb4caSwyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
199599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
199699ebb4caSwyllys 	}
199799ebb4caSwyllys 
199899ebb4caSwyllys 	/* copy cert data to outbuf */
199999ebb4caSwyllys 	outbuf = malloc(pcert->Length);
200099ebb4caSwyllys 	if (outbuf == NULL) {
200199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
200299ebb4caSwyllys 	}
200399ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
200499ebb4caSwyllys 
200599ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
200699ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
200799ebb4caSwyllys 	if (xcert == NULL) {
200899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
200999ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
201099ebb4caSwyllys 		goto out;
201199ebb4caSwyllys 	}
201299ebb4caSwyllys 
201399ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
201499ebb4caSwyllys 	if (mem == NULL) {
201599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
201699ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
201799ebb4caSwyllys 		goto out;
201899ebb4caSwyllys 	}
201999ebb4caSwyllys 
202099ebb4caSwyllys 	switch (flag) {
202199ebb4caSwyllys 	case KMF_CERT_ISSUER:
202299ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
202399ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
202499ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
202599ebb4caSwyllys 		break;
202699ebb4caSwyllys 
202799ebb4caSwyllys 	case KMF_CERT_SUBJECT:
202899ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
202999ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
203099ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
203199ebb4caSwyllys 		break;
203299ebb4caSwyllys 
203399ebb4caSwyllys 	case KMF_CERT_VERSION:
203499ebb4caSwyllys 		tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version);
203599ebb4caSwyllys 		(void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN);
203699ebb4caSwyllys 		OPENSSL_free(tmpstr);
203799ebb4caSwyllys 		len = strlen(resultStr);
203899ebb4caSwyllys 		break;
203999ebb4caSwyllys 
204099ebb4caSwyllys 	case KMF_CERT_SERIALNUM:
204199ebb4caSwyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
204299ebb4caSwyllys 			(void) strcpy(resultStr, "0x");
204399ebb4caSwyllys 			len = BIO_gets(mem, &resultStr[2],
204499ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN - 2);
204599ebb4caSwyllys 		}
204699ebb4caSwyllys 		break;
204799ebb4caSwyllys 
204899ebb4caSwyllys 	case KMF_CERT_NOTBEFORE:
204999ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notBefore(xcert));
205099ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
205199ebb4caSwyllys 		break;
205299ebb4caSwyllys 
205399ebb4caSwyllys 	case KMF_CERT_NOTAFTER:
205499ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notAfter(xcert));
205599ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
205699ebb4caSwyllys 		break;
205799ebb4caSwyllys 
205899ebb4caSwyllys 	case KMF_CERT_PUBKEY_DATA:
205999ebb4caSwyllys 		{
206099ebb4caSwyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
206199ebb4caSwyllys 			if (pkey == NULL) {
206299ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
206399ebb4caSwyllys 				ret = KMF_ERR_ENCODING;
206499ebb4caSwyllys 				goto out;
206599ebb4caSwyllys 			}
206699ebb4caSwyllys 
206799ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
206899ebb4caSwyllys 				(void) BIO_printf(mem,
206999ebb4caSwyllys 				    "RSA Public Key: (%d bit)\n",
207099ebb4caSwyllys 				    BN_num_bits(pkey->pkey.rsa->n));
207199ebb4caSwyllys 				(void) RSA_print(mem, pkey->pkey.rsa, 0);
207299ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
207399ebb4caSwyllys 				(void) BIO_printf(mem,
207499ebb4caSwyllys 				    "%12sDSA Public Key:\n", "");
207599ebb4caSwyllys 				(void) DSA_print(mem, pkey->pkey.dsa, 0);
207699ebb4caSwyllys 			} else {
207799ebb4caSwyllys 				(void) BIO_printf(mem,
207899ebb4caSwyllys 				    "%12sUnknown Public Key:\n", "");
207999ebb4caSwyllys 			}
208099ebb4caSwyllys 			(void) BIO_printf(mem, "\n");
208199ebb4caSwyllys 			EVP_PKEY_free(pkey);
208299ebb4caSwyllys 		}
208399ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
208499ebb4caSwyllys 		break;
208599ebb4caSwyllys 	case KMF_CERT_SIGNATURE_ALG:
208699ebb4caSwyllys 	case KMF_CERT_PUBKEY_ALG:
208799ebb4caSwyllys 		if (flag == KMF_CERT_SIGNATURE_ALG) {
208899ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
208999ebb4caSwyllys 			    xcert->sig_alg->algorithm);
209099ebb4caSwyllys 		} else {
209199ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
209299ebb4caSwyllys 			    xcert->cert_info->key->algor->algorithm);
209399ebb4caSwyllys 		}
209499ebb4caSwyllys 
209599ebb4caSwyllys 		if (len > 0) {
209699ebb4caSwyllys 			len = BIO_read(mem, resultStr,
209799ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN);
209899ebb4caSwyllys 		}
209999ebb4caSwyllys 		break;
210099ebb4caSwyllys 
210199ebb4caSwyllys 	case KMF_CERT_EMAIL:
210299ebb4caSwyllys 		emlst = X509_get1_email(xcert);
210399ebb4caSwyllys 		for (j = 0; j < sk_num(emlst); j++)
210499ebb4caSwyllys 			(void) BIO_printf(mem, "%s\n", sk_value(emlst, j));
210599ebb4caSwyllys 
210699ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
210799ebb4caSwyllys 		X509_email_free(emlst);
210899ebb4caSwyllys 		break;
210999ebb4caSwyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
211099ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
211199ebb4caSwyllys 	case KMF_X509_EXT_KEY_USAGE:
211299ebb4caSwyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
211399ebb4caSwyllys 	case KMF_X509_EXT_CERT_POLICIES:
211499ebb4caSwyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
211599ebb4caSwyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
211699ebb4caSwyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
211799ebb4caSwyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
211899ebb4caSwyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
211999ebb4caSwyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
212099ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
212199ebb4caSwyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
212299ebb4caSwyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
212399ebb4caSwyllys 	case KMF_X509_EXT_FRESHEST_CRL:
212499ebb4caSwyllys 		nid = ext2NID(flag);
212599ebb4caSwyllys 		if (nid == NID_undef) {
212699ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
212799ebb4caSwyllys 			goto out;
212899ebb4caSwyllys 		}
212999ebb4caSwyllys 		ci = xcert->cert_info;
213099ebb4caSwyllys 
213199ebb4caSwyllys 		ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1);
213299ebb4caSwyllys 		if (ext_index == -1) {
213399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
213499ebb4caSwyllys 
213599ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
213699ebb4caSwyllys 			goto out;
213799ebb4caSwyllys 		}
213899ebb4caSwyllys 		ex = X509v3_get_ext(ci->extensions, ext_index);
213999ebb4caSwyllys 
214099ebb4caSwyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
214199ebb4caSwyllys 
214299ebb4caSwyllys 		if (BIO_printf(mem, ": %s\n",
214330a5e8faSwyllys 		    X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
214499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
214599ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
214699ebb4caSwyllys 			goto out;
214799ebb4caSwyllys 		}
214899ebb4caSwyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
214999ebb4caSwyllys 			(void) BIO_printf(mem, "%*s", 4, "");
215099ebb4caSwyllys 			(void) M_ASN1_OCTET_STRING_print(mem, ex->value);
215199ebb4caSwyllys 		}
215299ebb4caSwyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
215399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
215499ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
215599ebb4caSwyllys 			goto out;
215699ebb4caSwyllys 		}
215799ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
215899ebb4caSwyllys 	}
215999ebb4caSwyllys 	if (len <= 0) {
216099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
216199ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
216299ebb4caSwyllys 	}
216399ebb4caSwyllys 
216499ebb4caSwyllys out:
216599ebb4caSwyllys 	if (outbuf != NULL) {
216699ebb4caSwyllys 		free(outbuf);
216799ebb4caSwyllys 	}
216899ebb4caSwyllys 
216999ebb4caSwyllys 	if (xcert != NULL) {
217099ebb4caSwyllys 		X509_free(xcert);
217199ebb4caSwyllys 	}
217299ebb4caSwyllys 
217399ebb4caSwyllys 	if (mem != NULL) {
217499ebb4caSwyllys 		(void) BIO_free(mem);
217599ebb4caSwyllys 	}
217699ebb4caSwyllys 
217799ebb4caSwyllys 	return (ret);
217899ebb4caSwyllys }
217930a5e8faSwyllys 
218099ebb4caSwyllys KMF_RETURN
218199ebb4caSwyllys /*ARGSUSED*/
218230a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
218330a5e8faSwyllys     KMF_ATTRIBUTE *attrlist)
218499ebb4caSwyllys {
218599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
218630a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
218730a5e8faSwyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
218830a5e8faSwyllys 	KMF_KEY_HANDLE *key = NULL;
218930a5e8faSwyllys 	uint32_t numkeys = 1; /* 1 key only */
219030a5e8faSwyllys 	char *dirpath = NULL;
219130a5e8faSwyllys 	char *keyfile = NULL;
219230a5e8faSwyllys 	KMF_ATTRIBUTE new_attrlist[16];
219330a5e8faSwyllys 	int i = 0;
219499ebb4caSwyllys 
219599ebb4caSwyllys 	/*
219699ebb4caSwyllys 	 * This is really just a FindKey operation, reuse the
219799ebb4caSwyllys 	 * FindKey function.
219899ebb4caSwyllys 	 */
219930a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
220030a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
220130a5e8faSwyllys 	i++;
220299ebb4caSwyllys 
220330a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
220430a5e8faSwyllys 	    KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
220530a5e8faSwyllys 	i++;
220699ebb4caSwyllys 
220730a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
220830a5e8faSwyllys 	    KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
220930a5e8faSwyllys 	i++;
221030a5e8faSwyllys 
221130a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
221230a5e8faSwyllys 	if (key == NULL) {
221330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
221430a5e8faSwyllys 	} else {
221530a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
221630a5e8faSwyllys 		    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
221730a5e8faSwyllys 		i++;
221830a5e8faSwyllys 	}
221930a5e8faSwyllys 
222030a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
222130a5e8faSwyllys 	if (dirpath != NULL) {
222230a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
222330a5e8faSwyllys 		    KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
222430a5e8faSwyllys 		i++;
222530a5e8faSwyllys 	}
222630a5e8faSwyllys 
222730a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
222830a5e8faSwyllys 	if (keyfile == NULL)
222930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
223030a5e8faSwyllys 	else {
223130a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
223230a5e8faSwyllys 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
223330a5e8faSwyllys 		i++;
223430a5e8faSwyllys 	}
223530a5e8faSwyllys 
223630a5e8faSwyllys 	rv = OpenSSL_FindKey(handle, i, new_attrlist);
223799ebb4caSwyllys 	return (rv);
223899ebb4caSwyllys }
223999ebb4caSwyllys 
224099ebb4caSwyllys KMF_RETURN
224199ebb4caSwyllys /*ARGSUSED*/
224299ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
224399ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
224499ebb4caSwyllys 	KMF_DATA *output)
224599ebb4caSwyllys {
224699ebb4caSwyllys 	KMF_RETURN		ret = KMF_OK;
224799ebb4caSwyllys 	RSA *rsa = NULL;
224899ebb4caSwyllys 	unsigned int in_len = 0, out_len = 0;
224999ebb4caSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
225099ebb4caSwyllys 	uint8_t *in_data, *out_data;
225199ebb4caSwyllys 	int i, blocks;
225299ebb4caSwyllys 
225399ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
225499ebb4caSwyllys 	    ciphertext == NULL || output == NULL ||
225599ebb4caSwyllys 	    ciphertext->Data == NULL ||
225699ebb4caSwyllys 	    output->Data == NULL)
225799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
225899ebb4caSwyllys 
225999ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
226099ebb4caSwyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
226199ebb4caSwyllys 		modulus_len = RSA_size(rsa);
226299ebb4caSwyllys 	} else {
226399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
226499ebb4caSwyllys 	}
226599ebb4caSwyllys 
226699ebb4caSwyllys 	blocks = ciphertext->Length/modulus_len;
226799ebb4caSwyllys 	out_data = output->Data;
226899ebb4caSwyllys 	in_data = ciphertext->Data;
226999ebb4caSwyllys 	out_len = modulus_len - 11;
227099ebb4caSwyllys 	in_len = modulus_len;
227199ebb4caSwyllys 
227299ebb4caSwyllys 	for (i = 0; i < blocks; i++) {
227399ebb4caSwyllys 		out_len  = RSA_private_decrypt(in_len,
227499ebb4caSwyllys 		    in_data, out_data, rsa, RSA_PKCS1_PADDING);
227599ebb4caSwyllys 
227699ebb4caSwyllys 		if (out_len == 0) {
227799ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
227899ebb4caSwyllys 			goto cleanup;
227999ebb4caSwyllys 		}
228099ebb4caSwyllys 
228199ebb4caSwyllys 		out_data += out_len;
228299ebb4caSwyllys 		total_decrypted += out_len;
228399ebb4caSwyllys 		in_data += in_len;
228499ebb4caSwyllys 	}
228599ebb4caSwyllys 
228699ebb4caSwyllys 	output->Length = total_decrypted;
228799ebb4caSwyllys 
228899ebb4caSwyllys cleanup:
228999ebb4caSwyllys 	RSA_free(rsa);
229099ebb4caSwyllys 	if (ret != KMF_OK)
229199ebb4caSwyllys 		output->Length = 0;
229299ebb4caSwyllys 
229399ebb4caSwyllys 	return (ret);
229499ebb4caSwyllys 
229599ebb4caSwyllys }
229699ebb4caSwyllys 
229799ebb4caSwyllys /*
229899ebb4caSwyllys  *  This function will create a certid from issuer_cert and user_cert.
229999ebb4caSwyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
230099ebb4caSwyllys  *  certid memory after use.
230199ebb4caSwyllys  */
230299ebb4caSwyllys static KMF_RETURN
230399ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
230499ebb4caSwyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
230599ebb4caSwyllys {
230699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
230799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
230899ebb4caSwyllys 	X509   *issuer = NULL;
230999ebb4caSwyllys 	X509   *cert = NULL;
231099ebb4caSwyllys 	unsigned char *ptmp;
231199ebb4caSwyllys 
231299ebb4caSwyllys 	if (issuer_cert == NULL || user_cert == NULL) {
231399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
231499ebb4caSwyllys 	}
231599ebb4caSwyllys 
231699ebb4caSwyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
231799ebb4caSwyllys 	ptmp = issuer_cert->Data;
231899ebb4caSwyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
231999ebb4caSwyllys 	    issuer_cert->Length);
232099ebb4caSwyllys 	if (issuer == NULL) {
232199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
232299ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
232399ebb4caSwyllys 		goto end;
232499ebb4caSwyllys 	}
232599ebb4caSwyllys 
232699ebb4caSwyllys 	/* convert the DER-encoded user cert to an internal X509 */
232799ebb4caSwyllys 	ptmp = user_cert->Data;
232899ebb4caSwyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
232999ebb4caSwyllys 	    user_cert->Length);
233099ebb4caSwyllys 	if (cert == NULL) {
233199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
233299ebb4caSwyllys 
233399ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
233499ebb4caSwyllys 		goto end;
233599ebb4caSwyllys 	}
233699ebb4caSwyllys 
233799ebb4caSwyllys 	/* create a CERTID */
233899ebb4caSwyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
233999ebb4caSwyllys 	if (*certid == NULL) {
234099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
234199ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
234299ebb4caSwyllys 		goto end;
234399ebb4caSwyllys 	}
234499ebb4caSwyllys 
234599ebb4caSwyllys end:
234699ebb4caSwyllys 	if (issuer != NULL) {
234799ebb4caSwyllys 		X509_free(issuer);
234899ebb4caSwyllys 	}
234999ebb4caSwyllys 
235099ebb4caSwyllys 	if (cert != NULL) {
235199ebb4caSwyllys 		X509_free(cert);
235299ebb4caSwyllys 	}
235399ebb4caSwyllys 
235499ebb4caSwyllys 	return (ret);
235599ebb4caSwyllys }
235699ebb4caSwyllys 
235799ebb4caSwyllys KMF_RETURN
235830a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
235930a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
236099ebb4caSwyllys {
236199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
236299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
236399ebb4caSwyllys 	OCSP_CERTID *id = NULL;
236499ebb4caSwyllys 	OCSP_REQUEST *req = NULL;
236599ebb4caSwyllys 	BIO *derbio = NULL;
236630a5e8faSwyllys 	char *reqfile;
236730a5e8faSwyllys 	KMF_DATA *issuer_cert;
236830a5e8faSwyllys 	KMF_DATA *user_cert;
236999ebb4caSwyllys 
237030a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
237130a5e8faSwyllys 	    attrlist, numattr);
237230a5e8faSwyllys 	if (user_cert == NULL)
237399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
237499ebb4caSwyllys 
237530a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
237630a5e8faSwyllys 	    attrlist, numattr);
237730a5e8faSwyllys 	if (issuer_cert == NULL)
237830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
237930a5e8faSwyllys 
238030a5e8faSwyllys 	reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
238130a5e8faSwyllys 	    attrlist, numattr);
238230a5e8faSwyllys 	if (reqfile == NULL)
238330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
238430a5e8faSwyllys 
238530a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
238699ebb4caSwyllys 	if (ret != KMF_OK) {
238799ebb4caSwyllys 		return (ret);
238899ebb4caSwyllys 	}
238999ebb4caSwyllys 
239099ebb4caSwyllys 	/* Create an OCSP request */
239199ebb4caSwyllys 	req = OCSP_REQUEST_new();
239299ebb4caSwyllys 	if (req == NULL) {
239399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
239499ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
239599ebb4caSwyllys 		goto end;
239699ebb4caSwyllys 	}
239799ebb4caSwyllys 
239899ebb4caSwyllys 	if (!OCSP_request_add0_id(req, id)) {
239999ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
240099ebb4caSwyllys 		goto end;
240199ebb4caSwyllys 	}
240299ebb4caSwyllys 
240399ebb4caSwyllys 	/* Write the request to the output file with DER encoding */
240499ebb4caSwyllys 	derbio = BIO_new_file(reqfile, "wb");
240599ebb4caSwyllys 	if (!derbio) {
240699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
240799ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
240899ebb4caSwyllys 		goto end;
240999ebb4caSwyllys 	}
241099ebb4caSwyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
241199ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
241299ebb4caSwyllys 	}
241399ebb4caSwyllys 
241499ebb4caSwyllys end:
241599ebb4caSwyllys 	/*
241699ebb4caSwyllys 	 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
241799ebb4caSwyllys 	 * will deallocate certid's space also.
241899ebb4caSwyllys 	 */
241999ebb4caSwyllys 	if (req != NULL) {
242099ebb4caSwyllys 		OCSP_REQUEST_free(req);
242199ebb4caSwyllys 	}
242299ebb4caSwyllys 
242399ebb4caSwyllys 	if (derbio != NULL) {
242499ebb4caSwyllys 		(void) BIO_free(derbio);
242599ebb4caSwyllys 	}
242699ebb4caSwyllys 
242799ebb4caSwyllys 	return (ret);
242899ebb4caSwyllys }
242999ebb4caSwyllys 
243099ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */
243199ebb4caSwyllys static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
243299ebb4caSwyllys {
243399ebb4caSwyllys 	int i;
243499ebb4caSwyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
243599ebb4caSwyllys 
243699ebb4caSwyllys 	/* Easy if lookup by name */
243799ebb4caSwyllys 	if (id->type == V_OCSP_RESPID_NAME)
243899ebb4caSwyllys 		return (X509_find_by_subject(certs, id->value.byName));
243999ebb4caSwyllys 
244099ebb4caSwyllys 	/* Lookup by key hash */
244199ebb4caSwyllys 
244299ebb4caSwyllys 	/* If key hash isn't SHA1 length then forget it */
244399ebb4caSwyllys 	if (id->value.byKey->length != SHA_DIGEST_LENGTH)
244499ebb4caSwyllys 		return (NULL);
244599ebb4caSwyllys 
244699ebb4caSwyllys 	keyhash = id->value.byKey->data;
244799ebb4caSwyllys 	/* Calculate hash of each key and compare */
244899ebb4caSwyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
244999ebb4caSwyllys 		/*LINTED*/
245099ebb4caSwyllys 		X509 *x = sk_X509_value(certs, i);
24515b3e1433Swyllys 		/* Use pubkey_digest to get the key ID value */
245299ebb4caSwyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
245399ebb4caSwyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
245499ebb4caSwyllys 			return (x);
245599ebb4caSwyllys 	}
245699ebb4caSwyllys 	return (NULL);
245799ebb4caSwyllys }
245899ebb4caSwyllys 
245999ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */
246099ebb4caSwyllys /*ARGSUSED*/
246199ebb4caSwyllys static int
246299ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
246399ebb4caSwyllys     X509_STORE *st, unsigned long flags)
246499ebb4caSwyllys {
246599ebb4caSwyllys 	X509 *signer;
246699ebb4caSwyllys 	OCSP_RESPID *rid = bs->tbsResponseData->responderId;
246799ebb4caSwyllys 	if ((signer = ocsp_find_signer_sk(certs, rid)))	{
246899ebb4caSwyllys 		*psigner = signer;
246999ebb4caSwyllys 		return (2);
247099ebb4caSwyllys 	}
247199ebb4caSwyllys 	if (!(flags & OCSP_NOINTERN) &&
247299ebb4caSwyllys 	    (signer = ocsp_find_signer_sk(bs->certs, rid))) {
247399ebb4caSwyllys 		*psigner = signer;
247499ebb4caSwyllys 		return (1);
247599ebb4caSwyllys 	}
247699ebb4caSwyllys 	/* Maybe lookup from store if by subject name */
247799ebb4caSwyllys 
247899ebb4caSwyllys 	*psigner = NULL;
247999ebb4caSwyllys 	return (0);
248099ebb4caSwyllys }
248199ebb4caSwyllys 
248299ebb4caSwyllys /*
248399ebb4caSwyllys  * This function will verify the signature of a basic response, using
248499ebb4caSwyllys  * the public key from the OCSP responder certificate.
248599ebb4caSwyllys  */
248699ebb4caSwyllys static KMF_RETURN
248799ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
248899ebb4caSwyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
248999ebb4caSwyllys {
249099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
249199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
249299ebb4caSwyllys 	STACK_OF(X509) *cert_stack = NULL;
249399ebb4caSwyllys 	X509 *signer = NULL;
249499ebb4caSwyllys 	X509 *issuer = NULL;
249599ebb4caSwyllys 	EVP_PKEY *skey = NULL;
249699ebb4caSwyllys 	unsigned char *ptmp;
249799ebb4caSwyllys 
249899ebb4caSwyllys 
249999ebb4caSwyllys 	if (bs == NULL || issuer_cert == NULL)
250099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
250199ebb4caSwyllys 
250299ebb4caSwyllys 	/*
250399ebb4caSwyllys 	 * Find the certificate that signed the basic response.
250499ebb4caSwyllys 	 *
250599ebb4caSwyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
250699ebb4caSwyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
250799ebb4caSwyllys 	 * If we still do not find a signer, we will look for it from the
250899ebb4caSwyllys 	 * certificate list came with the response file.
250999ebb4caSwyllys 	 */
251099ebb4caSwyllys 	if (signer_cert != NULL) {
251199ebb4caSwyllys 		ptmp = signer_cert->Data;
251299ebb4caSwyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
251399ebb4caSwyllys 		    signer_cert->Length);
251499ebb4caSwyllys 		if (signer == NULL) {
251599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
251699ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
251799ebb4caSwyllys 			goto end;
251899ebb4caSwyllys 		}
251999ebb4caSwyllys 	} else {
252099ebb4caSwyllys 		/*
252199ebb4caSwyllys 		 * Convert the issuer cert into X509 and push it into a
252299ebb4caSwyllys 		 * stack to be used by ocsp_find_signer().
252399ebb4caSwyllys 		 */
252499ebb4caSwyllys 		ptmp = issuer_cert->Data;
252599ebb4caSwyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
252699ebb4caSwyllys 		    issuer_cert->Length);
252799ebb4caSwyllys 		if (issuer == NULL) {
252899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
252999ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
253099ebb4caSwyllys 			goto end;
253199ebb4caSwyllys 		}
253299ebb4caSwyllys 
253399ebb4caSwyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
253499ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
253599ebb4caSwyllys 			goto end;
253699ebb4caSwyllys 		}
253799ebb4caSwyllys 
253899ebb4caSwyllys 		if (sk_X509_push(cert_stack, issuer) == NULL) {
253999ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
254099ebb4caSwyllys 			goto end;
254199ebb4caSwyllys 		}
254299ebb4caSwyllys 
254399ebb4caSwyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
254499ebb4caSwyllys 		if (!ret) {
254599ebb4caSwyllys 			/* can not find the signer */
254699ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
254799ebb4caSwyllys 			goto end;
254899ebb4caSwyllys 		}
254999ebb4caSwyllys 	}
255099ebb4caSwyllys 
255199ebb4caSwyllys 	/* Verify the signature of the response */
255299ebb4caSwyllys 	skey = X509_get_pubkey(signer);
255399ebb4caSwyllys 	if (skey == NULL) {
255499ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
255599ebb4caSwyllys 		goto end;
255699ebb4caSwyllys 	}
255799ebb4caSwyllys 
255899ebb4caSwyllys 	ret = OCSP_BASICRESP_verify(bs, skey, 0);
255999ebb4caSwyllys 	if (ret == 0) {
256099ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
256199ebb4caSwyllys 		goto end;
256299ebb4caSwyllys 	}
256399ebb4caSwyllys 
256499ebb4caSwyllys end:
256599ebb4caSwyllys 	if (issuer != NULL) {
256699ebb4caSwyllys 		X509_free(issuer);
256799ebb4caSwyllys 	}
256899ebb4caSwyllys 
256999ebb4caSwyllys 	if (signer != NULL) {
257099ebb4caSwyllys 		X509_free(signer);
257199ebb4caSwyllys 	}
257299ebb4caSwyllys 
257399ebb4caSwyllys 	if (skey != NULL) {
257499ebb4caSwyllys 		EVP_PKEY_free(skey);
257599ebb4caSwyllys 	}
257699ebb4caSwyllys 
257799ebb4caSwyllys 	if (cert_stack != NULL) {
257899ebb4caSwyllys 		sk_X509_free(cert_stack);
257999ebb4caSwyllys 	}
258099ebb4caSwyllys 
258199ebb4caSwyllys 	return (ret);
258299ebb4caSwyllys }
258399ebb4caSwyllys 
258499ebb4caSwyllys 
258599ebb4caSwyllys 
258699ebb4caSwyllys KMF_RETURN
258799ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
258830a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
258999ebb4caSwyllys {
259099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
259199ebb4caSwyllys 	BIO *derbio = NULL;
259299ebb4caSwyllys 	OCSP_RESPONSE *resp = NULL;
259399ebb4caSwyllys 	OCSP_BASICRESP *bs = NULL;
259499ebb4caSwyllys 	OCSP_CERTID *id = NULL;
259599ebb4caSwyllys 	OCSP_SINGLERESP *single = NULL;
259699ebb4caSwyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
259799ebb4caSwyllys 	int index, status, reason;
259830a5e8faSwyllys 	KMF_DATA *issuer_cert;
259930a5e8faSwyllys 	KMF_DATA *user_cert;
260030a5e8faSwyllys 	KMF_DATA *signer_cert;
260130a5e8faSwyllys 	KMF_DATA *response;
260230a5e8faSwyllys 	int *response_reason, *response_status, *cert_status;
260330a5e8faSwyllys 	boolean_t ignore_response_sign = B_FALSE;	/* default is FALSE */
260430a5e8faSwyllys 	uint32_t response_lifetime;
260599ebb4caSwyllys 
260630a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
260730a5e8faSwyllys 	    attrlist, numattr);
260830a5e8faSwyllys 	if (issuer_cert == NULL)
260999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
261099ebb4caSwyllys 
261130a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
261230a5e8faSwyllys 	    attrlist, numattr);
261330a5e8faSwyllys 	if (user_cert == NULL)
261499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
261530a5e8faSwyllys 
261630a5e8faSwyllys 	response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
261730a5e8faSwyllys 	    attrlist, numattr);
261830a5e8faSwyllys 	if (response == NULL)
261930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
262030a5e8faSwyllys 
262130a5e8faSwyllys 	response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
262230a5e8faSwyllys 	    attrlist, numattr);
262330a5e8faSwyllys 	if (response_status == NULL)
262430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
262530a5e8faSwyllys 
262630a5e8faSwyllys 	response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
262730a5e8faSwyllys 	    attrlist, numattr);
262830a5e8faSwyllys 	if (response_reason == NULL)
262930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
263030a5e8faSwyllys 
263130a5e8faSwyllys 	cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
263230a5e8faSwyllys 	    attrlist, numattr);
263330a5e8faSwyllys 	if (cert_status == NULL)
263430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
263599ebb4caSwyllys 
263699ebb4caSwyllys 	/* Read in the response */
263730a5e8faSwyllys 	derbio = BIO_new_mem_buf(response->Data, response->Length);
263899ebb4caSwyllys 	if (!derbio) {
263999ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
264099ebb4caSwyllys 		return (ret);
264199ebb4caSwyllys 	}
264299ebb4caSwyllys 
264399ebb4caSwyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
264499ebb4caSwyllys 	if (resp == NULL) {
264599ebb4caSwyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
264699ebb4caSwyllys 		goto end;
264799ebb4caSwyllys 	}
264899ebb4caSwyllys 
264999ebb4caSwyllys 	/* Check the response status */
265099ebb4caSwyllys 	status = OCSP_response_status(resp);
265130a5e8faSwyllys 	*response_status = status;
265299ebb4caSwyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
265399ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
265499ebb4caSwyllys 		goto end;
265599ebb4caSwyllys 	}
265699ebb4caSwyllys 
265799ebb4caSwyllys #ifdef DEBUG
265899ebb4caSwyllys 	printf("Successfully checked the response file status.\n");
265999ebb4caSwyllys #endif /* DEBUG */
266099ebb4caSwyllys 
266199ebb4caSwyllys 	/* Extract basic response */
266299ebb4caSwyllys 	bs = OCSP_response_get1_basic(resp);
266399ebb4caSwyllys 	if (bs == NULL) {
266499ebb4caSwyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
266599ebb4caSwyllys 		goto end;
266699ebb4caSwyllys 	}
266799ebb4caSwyllys 
266899ebb4caSwyllys #ifdef DEBUG
266999ebb4caSwyllys 	printf("Successfully retrieved the basic response.\n");
267099ebb4caSwyllys #endif /* DEBUG */
267199ebb4caSwyllys 
267299ebb4caSwyllys 	/* Check the basic response signature if required */
267330a5e8faSwyllys 	ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
267430a5e8faSwyllys 	    (void *)&ignore_response_sign, NULL);
267530a5e8faSwyllys 	if (ret != KMF_OK)
267630a5e8faSwyllys 		ret = KMF_OK;
267730a5e8faSwyllys 
267830a5e8faSwyllys 	signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
267930a5e8faSwyllys 	    attrlist, numattr);
268030a5e8faSwyllys 
268130a5e8faSwyllys 	if (ignore_response_sign == B_FALSE) {
268299ebb4caSwyllys 		ret = check_response_signature(handle, bs,
268330a5e8faSwyllys 		    signer_cert, issuer_cert);
268499ebb4caSwyllys 		if (ret != KMF_OK)
268599ebb4caSwyllys 			goto end;
268699ebb4caSwyllys 	}
268799ebb4caSwyllys 
268899ebb4caSwyllys #ifdef DEBUG
268999ebb4caSwyllys 	printf("Successfully verified the response signature.\n");
269099ebb4caSwyllys #endif /* DEBUG */
269199ebb4caSwyllys 
269299ebb4caSwyllys 	/* Create a certid for the certificate in question */
269330a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
269499ebb4caSwyllys 	if (ret != KMF_OK) {
269599ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
269699ebb4caSwyllys 		goto end;
269799ebb4caSwyllys 	}
269899ebb4caSwyllys 
269999ebb4caSwyllys #ifdef DEBUG
270099ebb4caSwyllys 	printf("successfully created a certid for the cert.\n");
270199ebb4caSwyllys #endif /* DEBUG */
270299ebb4caSwyllys 
270399ebb4caSwyllys 	/* Find the index of the single response for the certid */
270499ebb4caSwyllys 	index = OCSP_resp_find(bs, id, -1);
270599ebb4caSwyllys 	if (index < 0) {
270699ebb4caSwyllys 		/* cound not find this certificate in the response */
270799ebb4caSwyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
270899ebb4caSwyllys 		goto end;
270999ebb4caSwyllys 	}
271099ebb4caSwyllys 
271199ebb4caSwyllys #ifdef DEBUG
271299ebb4caSwyllys 	printf("Successfully found the single response index for the cert.\n");
271399ebb4caSwyllys #endif /* DEBUG */
271499ebb4caSwyllys 
271599ebb4caSwyllys 	/* Retrieve the single response and get the cert status */
271699ebb4caSwyllys 	single = OCSP_resp_get0(bs, index);
271799ebb4caSwyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
271899ebb4caSwyllys 	    &nextupd);
271999ebb4caSwyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
272030a5e8faSwyllys 		*cert_status = OCSP_GOOD;
272199ebb4caSwyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
272230a5e8faSwyllys 		*cert_status = OCSP_UNKNOWN;
272399ebb4caSwyllys 	} else { /* revoked */
272430a5e8faSwyllys 		*cert_status = OCSP_REVOKED;
272530a5e8faSwyllys 		*response_reason = reason;
272699ebb4caSwyllys 	}
272799ebb4caSwyllys 	ret = KMF_OK;
272899ebb4caSwyllys 
272930a5e8faSwyllys 	/* resp. time is optional, so we don't care about the return code. */
273030a5e8faSwyllys 	(void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
273130a5e8faSwyllys 	    (void *)&response_lifetime, NULL);
273230a5e8faSwyllys 
273399ebb4caSwyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
273430a5e8faSwyllys 	    response_lifetime)) {
273599ebb4caSwyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
273699ebb4caSwyllys 		goto end;
273799ebb4caSwyllys 	}
273899ebb4caSwyllys 
273999ebb4caSwyllys #ifdef DEBUG
274099ebb4caSwyllys 	printf("Successfully verify the time.\n");
274199ebb4caSwyllys #endif /* DEBUG */
274299ebb4caSwyllys 
274399ebb4caSwyllys end:
274499ebb4caSwyllys 	if (derbio != NULL)
274599ebb4caSwyllys 		(void) BIO_free(derbio);
274699ebb4caSwyllys 
274799ebb4caSwyllys 	if (resp != NULL)
274899ebb4caSwyllys 		OCSP_RESPONSE_free(resp);
274999ebb4caSwyllys 
275099ebb4caSwyllys 	if (bs != NULL)
275199ebb4caSwyllys 		OCSP_BASICRESP_free(bs);
275299ebb4caSwyllys 
275399ebb4caSwyllys 	if (id != NULL)
275499ebb4caSwyllys 		OCSP_CERTID_free(id);
275599ebb4caSwyllys 
275699ebb4caSwyllys 	return (ret);
275799ebb4caSwyllys }
275899ebb4caSwyllys 
275999ebb4caSwyllys static KMF_RETURN
276099ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path,
276199ebb4caSwyllys 	KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
276299ebb4caSwyllys {
276399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
276430a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
276599ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
276699ebb4caSwyllys 
276799ebb4caSwyllys 	if (keyclass == KMF_ASYM_PRI ||
276899ebb4caSwyllys 	    keyclass == KMF_ASYM_PUB) {
276999ebb4caSwyllys 		pkey = openssl_load_key(handle, path);
277099ebb4caSwyllys 		if (pkey == NULL) {
277199ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
277299ebb4caSwyllys 		}
277399ebb4caSwyllys 		if (key != NULL) {
277499ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA)
277599ebb4caSwyllys 				key->keyalg = KMF_RSA;
277699ebb4caSwyllys 			else if (pkey->type == EVP_PKEY_DSA)
277799ebb4caSwyllys 				key->keyalg = KMF_DSA;
277899ebb4caSwyllys 
277999ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
278099ebb4caSwyllys 			key->keyclass = keyclass;
278199ebb4caSwyllys 			key->keyp = (void *)pkey;
278299ebb4caSwyllys 			key->israw = FALSE;
27835b3e1433Swyllys 			if (path != NULL &&
27845b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
27855b3e1433Swyllys 				EVP_PKEY_free(pkey);
27865b3e1433Swyllys 				return (KMF_ERR_MEMORY);
27875b3e1433Swyllys 			}
278899ebb4caSwyllys 		} else {
278999ebb4caSwyllys 			EVP_PKEY_free(pkey);
279099ebb4caSwyllys 			pkey = NULL;
279199ebb4caSwyllys 		}
279299ebb4caSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
279399ebb4caSwyllys 		KMF_ENCODE_FORMAT fmt;
279499ebb4caSwyllys 		/*
279599ebb4caSwyllys 		 * If the file is a recognized format,
279699ebb4caSwyllys 		 * then it is NOT a symmetric key.
279799ebb4caSwyllys 		 */
279830a5e8faSwyllys 		rv = kmf_get_file_format(path, &fmt);
279999ebb4caSwyllys 		if (rv == KMF_OK || fmt != 0) {
280099ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
280199ebb4caSwyllys 		} else if (rv == KMF_ERR_ENCODING) {
280299ebb4caSwyllys 			/*
280399ebb4caSwyllys 			 * If we don't know the encoding,
280499ebb4caSwyllys 			 * it is probably  a symmetric key.
280599ebb4caSwyllys 			 */
280699ebb4caSwyllys 			rv = KMF_OK;
280730a5e8faSwyllys 		} else if (rv == KMF_ERR_OPEN_FILE) {
280830a5e8faSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
280999ebb4caSwyllys 		}
281099ebb4caSwyllys 
281199ebb4caSwyllys 		if (key != NULL) {
281299ebb4caSwyllys 			KMF_DATA keyvalue;
281399ebb4caSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
281499ebb4caSwyllys 			if (rkey == NULL) {
281599ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
281699ebb4caSwyllys 				goto out;
281799ebb4caSwyllys 			}
281899ebb4caSwyllys 
281999ebb4caSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
282030a5e8faSwyllys 			rv = kmf_read_input_file(handle, path, &keyvalue);
282199ebb4caSwyllys 			if (rv != KMF_OK)
282299ebb4caSwyllys 				goto out;
282399ebb4caSwyllys 
282499ebb4caSwyllys 			rkey->keydata.len = keyvalue.Length;
282599ebb4caSwyllys 			rkey->keydata.val = keyvalue.Data;
282699ebb4caSwyllys 
282799ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
282899ebb4caSwyllys 			key->keyclass = keyclass;
282999ebb4caSwyllys 			key->israw = TRUE;
283099ebb4caSwyllys 			key->keyp = (void *)rkey;
28315b3e1433Swyllys 			if (path != NULL &&
28325b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
28335b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
28345b3e1433Swyllys 			}
283599ebb4caSwyllys 		}
283699ebb4caSwyllys 	}
283799ebb4caSwyllys out:
283899ebb4caSwyllys 	if (rv != KMF_OK) {
283999ebb4caSwyllys 		if (rkey != NULL) {
284030a5e8faSwyllys 			kmf_free_raw_sym_key(rkey);
284199ebb4caSwyllys 		}
284299ebb4caSwyllys 		if (pkey != NULL)
284399ebb4caSwyllys 			EVP_PKEY_free(pkey);
284499ebb4caSwyllys 
284599ebb4caSwyllys 		if (key != NULL) {
284699ebb4caSwyllys 			key->keyalg = KMF_KEYALG_NONE;
284799ebb4caSwyllys 			key->keyclass = KMF_KEYCLASS_NONE;
284899ebb4caSwyllys 			key->keyp = NULL;
284999ebb4caSwyllys 		}
285099ebb4caSwyllys 	}
285199ebb4caSwyllys 
285299ebb4caSwyllys 	return (rv);
285399ebb4caSwyllys }
285499ebb4caSwyllys 
285599ebb4caSwyllys KMF_RETURN
285630a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle,
285730a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
285899ebb4caSwyllys {
285999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
286099ebb4caSwyllys 	char *fullpath = NULL;
2861f482c776Swyllys 	uint32_t maxkeys;
286230a5e8faSwyllys 	KMF_KEY_HANDLE *key;
286330a5e8faSwyllys 	uint32_t *numkeys;
286430a5e8faSwyllys 	KMF_KEY_CLASS keyclass;
286530a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
286630a5e8faSwyllys 	char *dirpath;
286730a5e8faSwyllys 	char *keyfile;
286899ebb4caSwyllys 
286930a5e8faSwyllys 	if (handle == NULL)
287099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
287199ebb4caSwyllys 
287230a5e8faSwyllys 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
287330a5e8faSwyllys 	if (numkeys == NULL)
287430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
287530a5e8faSwyllys 
287630a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
287730a5e8faSwyllys 	    (void *)&keyclass, NULL);
287830a5e8faSwyllys 	if (rv != KMF_OK)
287930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
288030a5e8faSwyllys 
288130a5e8faSwyllys 	if (keyclass != KMF_ASYM_PUB &&
288230a5e8faSwyllys 	    keyclass != KMF_ASYM_PRI &&
288330a5e8faSwyllys 	    keyclass != KMF_SYMMETRIC)
288499ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
288599ebb4caSwyllys 
288630a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
288730a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
288830a5e8faSwyllys 
288930a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
289099ebb4caSwyllys 
289199ebb4caSwyllys 	if (fullpath == NULL)
289299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
289399ebb4caSwyllys 
2894f482c776Swyllys 	maxkeys = *numkeys;
2895f482c776Swyllys 	if (maxkeys == 0)
2896f482c776Swyllys 		maxkeys = 0xFFFFFFFF;
289799ebb4caSwyllys 	*numkeys = 0;
289899ebb4caSwyllys 
289930a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
290030a5e8faSwyllys 	/* it is okay to have "keys" contains NULL */
290130a5e8faSwyllys 
290230a5e8faSwyllys 	/*
290330a5e8faSwyllys 	 * The caller may want a list of the raw key data as well.
290430a5e8faSwyllys 	 * Useful for importing keys from a file into other keystores.
290530a5e8faSwyllys 	 */
290630a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
290730a5e8faSwyllys 
290899ebb4caSwyllys 	if (isdir(fullpath)) {
290999ebb4caSwyllys 		DIR *dirp;
291099ebb4caSwyllys 		struct dirent *dp;
291199ebb4caSwyllys 		int n = 0;
291299ebb4caSwyllys 
291399ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
291499ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
291599ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
291699ebb4caSwyllys 		}
291799ebb4caSwyllys 		rewinddir(dirp);
2918f482c776Swyllys 		while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
291999ebb4caSwyllys 			if (strcmp(dp->d_name, ".") &&
292099ebb4caSwyllys 			    strcmp(dp->d_name, "..")) {
292199ebb4caSwyllys 				char *fname;
292299ebb4caSwyllys 
292399ebb4caSwyllys 				fname = get_fullpath(fullpath,
292499ebb4caSwyllys 				    (char *)&dp->d_name);
292599ebb4caSwyllys 
292699ebb4caSwyllys 				rv = fetch_key(handle, fname,
292730a5e8faSwyllys 				    keyclass, key ? &key[n] : NULL);
292899ebb4caSwyllys 
292930a5e8faSwyllys 				if (rv == KMF_OK) {
293030a5e8faSwyllys 					if (key != NULL && rawkey != NULL)
293130a5e8faSwyllys 						rv = convertToRawKey(
293230a5e8faSwyllys 						    key[n].keyp, &rawkey[n]);
293399ebb4caSwyllys 					n++;
293430a5e8faSwyllys 				}
293599ebb4caSwyllys 
293699ebb4caSwyllys 				if (rv != KMF_OK || key == NULL)
293799ebb4caSwyllys 					free(fname);
293899ebb4caSwyllys 			}
293999ebb4caSwyllys 		}
294099ebb4caSwyllys 		(void) closedir(dirp);
294199ebb4caSwyllys 		free(fullpath);
294299ebb4caSwyllys 		(*numkeys) = n;
294399ebb4caSwyllys 	} else {
294430a5e8faSwyllys 		rv = fetch_key(handle, fullpath, keyclass, key);
294599ebb4caSwyllys 		if (rv == KMF_OK)
294699ebb4caSwyllys 			(*numkeys) = 1;
294799ebb4caSwyllys 
294899ebb4caSwyllys 		if (rv != KMF_OK || key == NULL)
294999ebb4caSwyllys 			free(fullpath);
295030a5e8faSwyllys 
295130a5e8faSwyllys 		if (rv == KMF_OK && key != NULL && rawkey != NULL) {
295230a5e8faSwyllys 			rv = convertToRawKey(key->keyp, rawkey);
295330a5e8faSwyllys 		}
295499ebb4caSwyllys 	}
295599ebb4caSwyllys 
2956f482c776Swyllys 	if (rv == KMF_OK && (*numkeys) == 0)
295799ebb4caSwyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
2958*73cc0e02Swyllys 	else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
2959*73cc0e02Swyllys 		rv = KMF_OK;
296099ebb4caSwyllys 
296199ebb4caSwyllys 	return (rv);
296299ebb4caSwyllys }
296399ebb4caSwyllys 
296499ebb4caSwyllys #define	HANDLE_PK12_ERROR { \
296599ebb4caSwyllys 	SET_ERROR(kmfh, ERR_get_error()); \
296699ebb4caSwyllys 	rv = KMF_ERR_ENCODING; \
296799ebb4caSwyllys 	goto out; \
296899ebb4caSwyllys }
296999ebb4caSwyllys 
29705b3e1433Swyllys static int
29715b3e1433Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
297299ebb4caSwyllys {
29735b3e1433Swyllys 	if (xcert != NULL && xcert->aux != NULL &&
29745b3e1433Swyllys 	    xcert->aux->alias != NULL) {
29755b3e1433Swyllys 		if (PKCS12_add_friendlyname_asc(bag,
29765b3e1433Swyllys 		    (const char *)xcert->aux->alias->data,
29775b3e1433Swyllys 		    xcert->aux->alias->length) == 0)
29785b3e1433Swyllys 			return (0);
29795b3e1433Swyllys 	}
29805b3e1433Swyllys 	return (1);
29815b3e1433Swyllys }
29825b3e1433Swyllys 
29835b3e1433Swyllys static PKCS7 *
29845b3e1433Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
29855b3e1433Swyllys 	uchar_t *keyid, unsigned int keyidlen)
29865b3e1433Swyllys {
298799ebb4caSwyllys 	PKCS12_SAFEBAG *bag = NULL;
298899ebb4caSwyllys 	PKCS7 *cert_authsafe = NULL;
29895b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack;
299099ebb4caSwyllys 
299199ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
299299ebb4caSwyllys 	if (bag_stack == NULL)
29935b3e1433Swyllys 		return (NULL);
299499ebb4caSwyllys 
299599ebb4caSwyllys 	/* Convert cert from X509 struct to PKCS#12 bag */
299699ebb4caSwyllys 	bag = PKCS12_x5092certbag(sslcert);
299799ebb4caSwyllys 	if (bag == NULL) {
29985b3e1433Swyllys 		goto out;
299999ebb4caSwyllys 	}
300099ebb4caSwyllys 
300199ebb4caSwyllys 	/* Add the key id to the certificate bag. */
30025b3e1433Swyllys 	if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
30035b3e1433Swyllys 		goto out;
300499ebb4caSwyllys 	}
300599ebb4caSwyllys 
30065b3e1433Swyllys 	if (!add_alias_to_bag(bag, sslcert))
30075b3e1433Swyllys 		goto out;
30085b3e1433Swyllys 
300999ebb4caSwyllys 	/* Pile it on the bag_stack. */
301099ebb4caSwyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
30115b3e1433Swyllys 		goto out;
301299ebb4caSwyllys 	}
301399ebb4caSwyllys 	/* Turn bag_stack of certs into encrypted authsafe. */
301499ebb4caSwyllys 	cert_authsafe = PKCS12_pack_p7encdata(
301599ebb4caSwyllys 	    NID_pbe_WithSHA1And40BitRC2_CBC,
301634acef67Swyllys 	    cred->cred, cred->credlen, NULL, 0,
301734acef67Swyllys 	    PKCS12_DEFAULT_ITER, bag_stack);
301899ebb4caSwyllys 
30195b3e1433Swyllys out:
30205b3e1433Swyllys 	if (bag_stack != NULL)
302199ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
302299ebb4caSwyllys 
30235b3e1433Swyllys 	return (cert_authsafe);
302499ebb4caSwyllys }
30255b3e1433Swyllys 
30265b3e1433Swyllys static PKCS7 *
30275b3e1433Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
30285b3e1433Swyllys 	uchar_t *keyid,  unsigned int keyidlen,
30295b3e1433Swyllys 	char *label, int label_len)
30305b3e1433Swyllys {
30315b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
30325b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
30335b3e1433Swyllys 	PKCS12_SAFEBAG *bag = NULL;
30345b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
30355b3e1433Swyllys 
303699ebb4caSwyllys 	p8 = EVP_PKEY2PKCS8(pkey);
303799ebb4caSwyllys 	if (p8 == NULL) {
30385b3e1433Swyllys 		return (NULL);
303999ebb4caSwyllys 	}
304099ebb4caSwyllys 	/* Put the shrouded key into a PKCS#12 bag. */
304199ebb4caSwyllys 	bag = PKCS12_MAKE_SHKEYBAG(
304299ebb4caSwyllys 	    NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
304399ebb4caSwyllys 	    cred->cred, cred->credlen,
304499ebb4caSwyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, p8);
304599ebb4caSwyllys 
304699ebb4caSwyllys 	/* Clean up the PKCS#8 shrouded key, don't need it now. */
304799ebb4caSwyllys 	PKCS8_PRIV_KEY_INFO_free(p8);
304899ebb4caSwyllys 	p8 = NULL;
304999ebb4caSwyllys 
305099ebb4caSwyllys 	if (bag == NULL) {
30515b3e1433Swyllys 		return (NULL);
305299ebb4caSwyllys 	}
30535b3e1433Swyllys 	if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
30545b3e1433Swyllys 		goto out;
30555b3e1433Swyllys 	if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
30565b3e1433Swyllys 		goto out;
30575b3e1433Swyllys 
305899ebb4caSwyllys 	/* Start a PKCS#12 safebag container for the private key. */
305999ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
30605b3e1433Swyllys 	if (bag_stack == NULL)
30615b3e1433Swyllys 		goto out;
306299ebb4caSwyllys 
306399ebb4caSwyllys 	/* Pile on the private key on the bag_stack. */
30645b3e1433Swyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
30655b3e1433Swyllys 		goto out;
30665b3e1433Swyllys 
306799ebb4caSwyllys 	key_authsafe = PKCS12_pack_p7data(bag_stack);
306899ebb4caSwyllys 
30695b3e1433Swyllys out:
30705b3e1433Swyllys 	if (bag_stack != NULL)
307199ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
307299ebb4caSwyllys 	bag_stack = NULL;
30735b3e1433Swyllys 	return (key_authsafe);
307499ebb4caSwyllys }
307599ebb4caSwyllys 
307699ebb4caSwyllys static EVP_PKEY *
307799ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
307899ebb4caSwyllys {
307999ebb4caSwyllys 	RSA		*rsa = NULL;
308099ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
308199ebb4caSwyllys 
308299ebb4caSwyllys 	if ((rsa = RSA_new()) == NULL)
308399ebb4caSwyllys 		return (NULL);
308499ebb4caSwyllys 
308599ebb4caSwyllys 	if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL)
308699ebb4caSwyllys 		return (NULL);
308799ebb4caSwyllys 
308899ebb4caSwyllys 	if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) ==
308999ebb4caSwyllys 	    NULL)
309099ebb4caSwyllys 		return (NULL);
309199ebb4caSwyllys 
309299ebb4caSwyllys 	if (key->priexp.val != NULL)
309399ebb4caSwyllys 		if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len,
309499ebb4caSwyllys 		    rsa->d)) == NULL)
309599ebb4caSwyllys 			return (NULL);
309699ebb4caSwyllys 
309799ebb4caSwyllys 	if (key->prime1.val != NULL)
309899ebb4caSwyllys 		if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len,
309999ebb4caSwyllys 		    rsa->p)) == NULL)
310099ebb4caSwyllys 			return (NULL);
310199ebb4caSwyllys 
310299ebb4caSwyllys 	if (key->prime2.val != NULL)
310399ebb4caSwyllys 		if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len,
310499ebb4caSwyllys 		    rsa->q)) == NULL)
310599ebb4caSwyllys 			return (NULL);
310699ebb4caSwyllys 
310799ebb4caSwyllys 	if (key->exp1.val != NULL)
310899ebb4caSwyllys 		if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len,
310999ebb4caSwyllys 		    rsa->dmp1)) == NULL)
311099ebb4caSwyllys 			return (NULL);
311199ebb4caSwyllys 
311299ebb4caSwyllys 	if (key->exp2.val != NULL)
311399ebb4caSwyllys 		if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len,
311499ebb4caSwyllys 		    rsa->dmq1)) == NULL)
311599ebb4caSwyllys 			return (NULL);
311699ebb4caSwyllys 
311799ebb4caSwyllys 	if (key->coef.val != NULL)
311899ebb4caSwyllys 		if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len,
311999ebb4caSwyllys 		    rsa->iqmp)) == NULL)
312099ebb4caSwyllys 			return (NULL);
312199ebb4caSwyllys 
312299ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
312399ebb4caSwyllys 		return (NULL);
312499ebb4caSwyllys 
312599ebb4caSwyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
312699ebb4caSwyllys 
312799ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
312899ebb4caSwyllys 	RSA_free(rsa);
312999ebb4caSwyllys 
313099ebb4caSwyllys 	return (newkey);
313199ebb4caSwyllys }
313299ebb4caSwyllys 
313399ebb4caSwyllys static EVP_PKEY *
313499ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
313599ebb4caSwyllys {
313699ebb4caSwyllys 	DSA		*dsa = NULL;
313799ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
313899ebb4caSwyllys 
313999ebb4caSwyllys 	if ((dsa = DSA_new()) == NULL)
314099ebb4caSwyllys 		return (NULL);
314199ebb4caSwyllys 
314299ebb4caSwyllys 	if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len,
314399ebb4caSwyllys 	    dsa->p)) == NULL)
314499ebb4caSwyllys 		return (NULL);
314599ebb4caSwyllys 
314699ebb4caSwyllys 	if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len,
314799ebb4caSwyllys 	    dsa->q)) == NULL)
314899ebb4caSwyllys 		return (NULL);
314999ebb4caSwyllys 
315099ebb4caSwyllys 	if ((dsa->g = BN_bin2bn(key->base.val, key->base.len,
315199ebb4caSwyllys 	    dsa->g)) == NULL)
315299ebb4caSwyllys 		return (NULL);
315399ebb4caSwyllys 
315499ebb4caSwyllys 	if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len,
315599ebb4caSwyllys 	    dsa->priv_key)) == NULL)
315699ebb4caSwyllys 		return (NULL);
315799ebb4caSwyllys 
315830a5e8faSwyllys 	if (key->pubvalue.val != NULL) {
315930a5e8faSwyllys 		if ((dsa->pub_key = BN_bin2bn(key->pubvalue.val,
316030a5e8faSwyllys 		    key->pubvalue.len, dsa->pub_key)) == NULL)
316130a5e8faSwyllys 			return (NULL);
316230a5e8faSwyllys 	}
316330a5e8faSwyllys 
316499ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
316599ebb4caSwyllys 		return (NULL);
316699ebb4caSwyllys 
316799ebb4caSwyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
316899ebb4caSwyllys 
316999ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
317099ebb4caSwyllys 	DSA_free(dsa);
317199ebb4caSwyllys 	return (newkey);
317299ebb4caSwyllys }
317399ebb4caSwyllys 
31745b3e1433Swyllys static EVP_PKEY *
31755b3e1433Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key)
31765b3e1433Swyllys {
31775b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
31785b3e1433Swyllys 	KMF_RAW_KEY_DATA *rawkey;
31795b3e1433Swyllys 	ASN1_TYPE *attr = NULL;
31805b3e1433Swyllys 	KMF_RETURN ret;
31815b3e1433Swyllys 
31825b3e1433Swyllys 	if (key == NULL || !key->israw)
31835b3e1433Swyllys 		return (NULL);
31845b3e1433Swyllys 
31855b3e1433Swyllys 	rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
31865b3e1433Swyllys 	if (rawkey->keytype == KMF_RSA) {
31875b3e1433Swyllys 		pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
31885b3e1433Swyllys 	} else if (rawkey->keytype == KMF_DSA) {
31895b3e1433Swyllys 		pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
31905b3e1433Swyllys 	} else {
31915b3e1433Swyllys 		/* wrong kind of key */
31925b3e1433Swyllys 		return (NULL);
31935b3e1433Swyllys 	}
31945b3e1433Swyllys 
31955b3e1433Swyllys 	if (rawkey->label != NULL) {
31965b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
31975b3e1433Swyllys 			EVP_PKEY_free(pkey);
31985b3e1433Swyllys 			return (NULL);
31995b3e1433Swyllys 		}
32005b3e1433Swyllys 		attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
32015b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
32025b3e1433Swyllys 		    strlen(rawkey->label));
32035b3e1433Swyllys 		attr->type = V_ASN1_BMPSTRING;
32045b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.bmpstring;
32055b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
32065b3e1433Swyllys 		if (ret != KMF_OK) {
32075b3e1433Swyllys 			EVP_PKEY_free(pkey);
32085b3e1433Swyllys 			ASN1_TYPE_free(attr);
32095b3e1433Swyllys 			return (NULL);
32105b3e1433Swyllys 		}
32115b3e1433Swyllys 	}
32125b3e1433Swyllys 	if (rawkey->id.Data != NULL) {
32135b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
32145b3e1433Swyllys 			EVP_PKEY_free(pkey);
32155b3e1433Swyllys 			return (NULL);
32165b3e1433Swyllys 		}
32175b3e1433Swyllys 		attr->value.octet_string =
32185b3e1433Swyllys 		    ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
32195b3e1433Swyllys 		attr->type = V_ASN1_OCTET_STRING;
32205b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.octet_string,
32215b3e1433Swyllys 		    rawkey->id.Data, rawkey->id.Length);
32225b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.octet_string;
32235b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
32245b3e1433Swyllys 		if (ret != KMF_OK) {
32255b3e1433Swyllys 			EVP_PKEY_free(pkey);
32265b3e1433Swyllys 			ASN1_TYPE_free(attr);
32275b3e1433Swyllys 			return (NULL);
32285b3e1433Swyllys 		}
32295b3e1433Swyllys 	}
32305b3e1433Swyllys 	return (pkey);
32315b3e1433Swyllys }
32325b3e1433Swyllys 
32335b3e1433Swyllys /*
32345b3e1433Swyllys  * Search a list of private keys to find one that goes with the certificate.
32355b3e1433Swyllys  */
32365b3e1433Swyllys static EVP_PKEY *
32375b3e1433Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
32385b3e1433Swyllys {
32395b3e1433Swyllys 	int i;
32405b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
32415b3e1433Swyllys 
32425b3e1433Swyllys 	if (numkeys == 0 || keylist == NULL || xcert == NULL)
32435b3e1433Swyllys 		return (NULL);
32445b3e1433Swyllys 	for (i = 0; i < numkeys; i++) {
32455b3e1433Swyllys 		if (keylist[i].israw)
32465b3e1433Swyllys 			pkey = raw_key_to_pkey(&keylist[i]);
32475b3e1433Swyllys 		else
32485b3e1433Swyllys 			pkey = (EVP_PKEY *)keylist[i].keyp;
32495b3e1433Swyllys 		if (pkey != NULL) {
32505b3e1433Swyllys 			if (X509_check_private_key(xcert, pkey)) {
32515b3e1433Swyllys 				return (pkey);
32525b3e1433Swyllys 			} else {
32535b3e1433Swyllys 				EVP_PKEY_free(pkey);
32545b3e1433Swyllys 				pkey = NULL;
32555b3e1433Swyllys 			}
32565b3e1433Swyllys 		}
32575b3e1433Swyllys 	}
32585b3e1433Swyllys 	return (pkey);
32595b3e1433Swyllys }
32605b3e1433Swyllys 
326199ebb4caSwyllys static KMF_RETURN
32625b3e1433Swyllys local_export_pk12(KMF_HANDLE_T handle,
326399ebb4caSwyllys 	KMF_CREDENTIAL *cred,
326499ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
326599ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
326699ebb4caSwyllys 	char *filename)
326799ebb4caSwyllys {
326899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
326999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
327099ebb4caSwyllys 	BIO *bio = NULL;
32715b3e1433Swyllys 	PKCS7 *cert_authsafe = NULL;
32725b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
32735b3e1433Swyllys 	STACK_OF(PKCS7) *authsafe_stack = NULL;
32745b3e1433Swyllys 	PKCS12 *p12_elem = NULL;
327599ebb4caSwyllys 	int i;
327699ebb4caSwyllys 
32775b3e1433Swyllys 	if (numcerts == 0 && numkeys == 0)
32785b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
32795b3e1433Swyllys 
328099ebb4caSwyllys 	/*
328199ebb4caSwyllys 	 * Open the output file.
328299ebb4caSwyllys 	 */
328399ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
328499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
328599ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
328699ebb4caSwyllys 		goto cleanup;
328799ebb4caSwyllys 	}
328899ebb4caSwyllys 
32895b3e1433Swyllys 	/* Start a PKCS#7 stack. */
32905b3e1433Swyllys 	authsafe_stack = sk_PKCS7_new_null();
32915b3e1433Swyllys 	if (authsafe_stack == NULL) {
32925b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
32935b3e1433Swyllys 		goto cleanup;
32945b3e1433Swyllys 	}
32955b3e1433Swyllys 	if (numcerts > 0) {
329699ebb4caSwyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
329799ebb4caSwyllys 			const uchar_t *p = certlist[i].certificate.Data;
329899ebb4caSwyllys 			long len = certlist[i].certificate.Length;
32995b3e1433Swyllys 			X509 *xcert = NULL;
33005b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
33015b3e1433Swyllys 			unsigned char keyid[EVP_MAX_MD_SIZE];
33025b3e1433Swyllys 			unsigned int keyidlen = 0;
330399ebb4caSwyllys 
330499ebb4caSwyllys 			xcert = d2i_X509(NULL, &p, len);
330599ebb4caSwyllys 			if (xcert == NULL) {
330699ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
330799ebb4caSwyllys 				rv = KMF_ERR_ENCODING;
330899ebb4caSwyllys 			}
33095b3e1433Swyllys 			if (certlist[i].kmf_private.label != NULL) {
33105b3e1433Swyllys 				/* Set alias attribute */
33115b3e1433Swyllys 				(void) X509_alias_set1(xcert,
33125b3e1433Swyllys 				    (uchar_t *)certlist[i].kmf_private.label,
33135b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label));
33145b3e1433Swyllys 			}
33155b3e1433Swyllys 			/* Check if there is a key corresponding to this cert */
33165b3e1433Swyllys 			pkey = find_matching_key(xcert, numkeys, keylist);
33175b3e1433Swyllys 
33185b3e1433Swyllys 			/*
33195b3e1433Swyllys 			 * If key is found, get fingerprint and create a
33205b3e1433Swyllys 			 * safebag.
33215b3e1433Swyllys 			 */
33225b3e1433Swyllys 			if (pkey != NULL) {
33235b3e1433Swyllys 				(void) X509_digest(xcert, EVP_sha1(),
33245b3e1433Swyllys 				    keyid, &keyidlen);
33255b3e1433Swyllys 				key_authsafe = add_key_to_safe(pkey, cred,
33265b3e1433Swyllys 				    keyid, keyidlen,
33275b3e1433Swyllys 				    certlist[i].kmf_private.label,
33285b3e1433Swyllys 				    (certlist[i].kmf_private.label ?
33295b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label) : 0));
33305b3e1433Swyllys 
33315b3e1433Swyllys 				if (key_authsafe == NULL) {
33325b3e1433Swyllys 					X509_free(xcert);
33335b3e1433Swyllys 					EVP_PKEY_free(pkey);
33345b3e1433Swyllys 					goto cleanup;
33355b3e1433Swyllys 				}
33365b3e1433Swyllys 				/* Put the key safe into the Auth Safe */
33375b3e1433Swyllys 				if (!sk_PKCS7_push(authsafe_stack,
33385b3e1433Swyllys 				    key_authsafe)) {
33395b3e1433Swyllys 					X509_free(xcert);
33405b3e1433Swyllys 					EVP_PKEY_free(pkey);
33415b3e1433Swyllys 					goto cleanup;
33425b3e1433Swyllys 				}
33435b3e1433Swyllys 			}
33445b3e1433Swyllys 
33455b3e1433Swyllys 			/* create a certificate safebag */
33465b3e1433Swyllys 			cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
33475b3e1433Swyllys 			    keyidlen);
33485b3e1433Swyllys 			if (cert_authsafe == NULL) {
33495b3e1433Swyllys 				X509_free(xcert);
33505b3e1433Swyllys 				EVP_PKEY_free(pkey);
33515b3e1433Swyllys 				goto cleanup;
33525b3e1433Swyllys 			}
33535b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
33545b3e1433Swyllys 				X509_free(xcert);
33555b3e1433Swyllys 				EVP_PKEY_free(pkey);
33565b3e1433Swyllys 				goto cleanup;
33575b3e1433Swyllys 			}
33585b3e1433Swyllys 
335999ebb4caSwyllys 			X509_free(xcert);
336099ebb4caSwyllys 			if (pkey)
336199ebb4caSwyllys 				EVP_PKEY_free(pkey);
336299ebb4caSwyllys 		}
33635b3e1433Swyllys 	} else if (numcerts == 0 && numkeys > 0) {
33645b3e1433Swyllys 		/*
33655b3e1433Swyllys 		 * If only adding keys to the file.
33665b3e1433Swyllys 		 */
33675b3e1433Swyllys 		for (i = 0; i < numkeys; i++) {
33685b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
33695b3e1433Swyllys 
33705b3e1433Swyllys 			if (keylist[i].israw)
33715b3e1433Swyllys 				pkey = raw_key_to_pkey(&keylist[i]);
33725b3e1433Swyllys 			else
33735b3e1433Swyllys 				pkey = (EVP_PKEY *)keylist[i].keyp;
33745b3e1433Swyllys 
33755b3e1433Swyllys 			if (pkey == NULL)
33765b3e1433Swyllys 				continue;
33775b3e1433Swyllys 
33785b3e1433Swyllys 			key_authsafe = add_key_to_safe(pkey, cred,
33795b3e1433Swyllys 			    NULL, 0, NULL, 0);
33805b3e1433Swyllys 
33815b3e1433Swyllys 			if (key_authsafe == NULL) {
33825b3e1433Swyllys 				EVP_PKEY_free(pkey);
33835b3e1433Swyllys 				goto cleanup;
33845b3e1433Swyllys 			}
33855b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
33865b3e1433Swyllys 				EVP_PKEY_free(pkey);
33875b3e1433Swyllys 				goto cleanup;
33885b3e1433Swyllys 			}
33895b3e1433Swyllys 		}
33905b3e1433Swyllys 	}
33915b3e1433Swyllys 	p12_elem = PKCS12_init(NID_pkcs7_data);
33925b3e1433Swyllys 	if (p12_elem == NULL) {
33935b3e1433Swyllys 		goto cleanup;
339499ebb4caSwyllys 	}
339599ebb4caSwyllys 
33965b3e1433Swyllys 	/* Put the PKCS#7 stack into the PKCS#12 element. */
33975b3e1433Swyllys 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
33985b3e1433Swyllys 		goto cleanup;
33995b3e1433Swyllys 	}
34005b3e1433Swyllys 
34015b3e1433Swyllys 	/* Set the integrity MAC on the PKCS#12 element. */
34025b3e1433Swyllys 	if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
34035b3e1433Swyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
34045b3e1433Swyllys 		goto cleanup;
34055b3e1433Swyllys 	}
34065b3e1433Swyllys 
34075b3e1433Swyllys 	/* Write the PKCS#12 element to the export file. */
34085b3e1433Swyllys 	if (!i2d_PKCS12_bio(bio, p12_elem)) {
34095b3e1433Swyllys 		goto cleanup;
34105b3e1433Swyllys 	}
34115b3e1433Swyllys 	PKCS12_free(p12_elem);
34125b3e1433Swyllys 
341399ebb4caSwyllys cleanup:
34145b3e1433Swyllys 	/* Clear away the PKCS#7 stack, we're done with it. */
34155b3e1433Swyllys 	if (authsafe_stack)
34165b3e1433Swyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
341799ebb4caSwyllys 
341899ebb4caSwyllys 	if (bio != NULL)
341999ebb4caSwyllys 		(void) BIO_free_all(bio);
342099ebb4caSwyllys 
342199ebb4caSwyllys 	return (rv);
342299ebb4caSwyllys }
342399ebb4caSwyllys 
342499ebb4caSwyllys KMF_RETURN
342530a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
342630a5e8faSwyllys     KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
342730a5e8faSwyllys     KMF_CREDENTIAL *p12cred, char *filename)
342830a5e8faSwyllys {
342930a5e8faSwyllys 	KMF_RETURN rv;
343030a5e8faSwyllys 
343130a5e8faSwyllys 	if (certlist == NULL && keylist == NULL)
343230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
343330a5e8faSwyllys 
34345b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, numcerts, certlist,
343530a5e8faSwyllys 	    numkeys, keylist, filename);
343630a5e8faSwyllys 
343730a5e8faSwyllys 	return (rv);
343830a5e8faSwyllys }
343930a5e8faSwyllys 
344030a5e8faSwyllys KMF_RETURN
344130a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
344299ebb4caSwyllys {
344399ebb4caSwyllys 	KMF_RETURN rv;
344499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
344599ebb4caSwyllys 	char *fullpath = NULL;
344630a5e8faSwyllys 	char *dirpath = NULL;
344730a5e8faSwyllys 	char *certfile = NULL;
344830a5e8faSwyllys 	char *keyfile = NULL;
344930a5e8faSwyllys 	char *filename = NULL;
345030a5e8faSwyllys 	KMF_CREDENTIAL *p12cred = NULL;
34515b3e1433Swyllys 	KMF_X509_DER_CERT certdata;
34525b3e1433Swyllys 	KMF_KEY_HANDLE key;
34535b3e1433Swyllys 	int gotkey = 0;
34545b3e1433Swyllys 	int gotcert = 0;
345530a5e8faSwyllys 
345630a5e8faSwyllys 	if (handle == NULL)
345730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
345899ebb4caSwyllys 
345999ebb4caSwyllys 	/*
346099ebb4caSwyllys 	 *  First, find the certificate.
346199ebb4caSwyllys 	 */
346230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
346330a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
346430a5e8faSwyllys 	if (certfile != NULL) {
346530a5e8faSwyllys 		fullpath = get_fullpath(dirpath, certfile);
346699ebb4caSwyllys 		if (fullpath == NULL)
346799ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
346899ebb4caSwyllys 
346999ebb4caSwyllys 		if (isdir(fullpath)) {
347099ebb4caSwyllys 			free(fullpath);
347199ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
347299ebb4caSwyllys 		}
347399ebb4caSwyllys 
34745b3e1433Swyllys 		(void) memset(&certdata, 0, sizeof (certdata));
34755b3e1433Swyllys 		rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL,
34765b3e1433Swyllys 		    fullpath, &certdata.certificate);
347799ebb4caSwyllys 		if (rv != KMF_OK)
347899ebb4caSwyllys 			goto end;
347930a5e8faSwyllys 
34805b3e1433Swyllys 		gotcert++;
34815b3e1433Swyllys 		certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
348230a5e8faSwyllys 		free(fullpath);
348399ebb4caSwyllys 	}
348499ebb4caSwyllys 
348599ebb4caSwyllys 	/*
348699ebb4caSwyllys 	 * Now find the private key.
348799ebb4caSwyllys 	 */
348830a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
348930a5e8faSwyllys 	if (keyfile != NULL) {
349030a5e8faSwyllys 		fullpath = get_fullpath(dirpath, keyfile);
349199ebb4caSwyllys 		if (fullpath == NULL)
349299ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
349399ebb4caSwyllys 
349499ebb4caSwyllys 		if (isdir(fullpath)) {
349599ebb4caSwyllys 			free(fullpath);
349699ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
349799ebb4caSwyllys 		}
349899ebb4caSwyllys 
34995b3e1433Swyllys 		(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
35005b3e1433Swyllys 		rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
35015b3e1433Swyllys 		if (rv != KMF_OK)
350299ebb4caSwyllys 			goto end;
35035b3e1433Swyllys 		gotkey++;
350499ebb4caSwyllys 	}
350599ebb4caSwyllys 
350699ebb4caSwyllys 	/*
350799ebb4caSwyllys 	 * Open the output file.
350899ebb4caSwyllys 	 */
350930a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
351030a5e8faSwyllys 	    numattr);
351130a5e8faSwyllys 	if (filename == NULL) {
351230a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
351330a5e8faSwyllys 		goto end;
351430a5e8faSwyllys 	}
351530a5e8faSwyllys 
351699ebb4caSwyllys 	/* Stick the key and the cert into a PKCS#12 file */
351730a5e8faSwyllys 	p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
351830a5e8faSwyllys 	if (p12cred == NULL) {
351930a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
352030a5e8faSwyllys 		goto end;
352130a5e8faSwyllys 	}
352230a5e8faSwyllys 
35235b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, 1, &certdata,
35245b3e1433Swyllys 	    1, &key, filename);
352599ebb4caSwyllys 
352699ebb4caSwyllys end:
352799ebb4caSwyllys 	if (fullpath)
352899ebb4caSwyllys 		free(fullpath);
352999ebb4caSwyllys 
35305b3e1433Swyllys 	if (gotcert)
35315b3e1433Swyllys 		kmf_free_kmf_cert(handle, &certdata);
35325b3e1433Swyllys 	if (gotkey)
35335b3e1433Swyllys 		kmf_free_kmf_key(handle, &key);
353499ebb4caSwyllys 	return (rv);
353599ebb4caSwyllys }
353699ebb4caSwyllys 
353771593db2Swyllys /*
353871593db2Swyllys  * Helper function to extract keys and certificates from
353971593db2Swyllys  * a single PEM file.  Typically the file should contain a
354071593db2Swyllys  * private key and an associated public key wrapped in an x509 cert.
354171593db2Swyllys  * However, the file may be just a list of X509 certs with no keys.
354271593db2Swyllys  */
354371593db2Swyllys static KMF_RETURN
354430a5e8faSwyllys extract_pem(KMF_HANDLE *kmfh,
354530a5e8faSwyllys 	char *issuer, char *subject, KMF_BIGINT *serial,
354602744e81Swyllys 	char *filename, CK_UTF8CHAR *pin,
354771593db2Swyllys 	CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
354871593db2Swyllys 	int *numcerts)
354971593db2Swyllys /* ARGSUSED */
355071593db2Swyllys {
355171593db2Swyllys 	KMF_RETURN rv = KMF_OK;
355271593db2Swyllys 	FILE *fp;
355334acef67Swyllys 	STACK_OF(X509_INFO) *x509_info_stack = NULL;
355402744e81Swyllys 	int i, ncerts = 0, matchcerts = 0;
355571593db2Swyllys 	EVP_PKEY *pkey = NULL;
355671593db2Swyllys 	X509_INFO *info;
355771593db2Swyllys 	X509 *x;
35585b3e1433Swyllys 	X509_INFO **cert_infos = NULL;
355971593db2Swyllys 	KMF_DATA *certlist = NULL;
356071593db2Swyllys 
356171593db2Swyllys 	if (priv_key)
356271593db2Swyllys 		*priv_key = NULL;
356371593db2Swyllys 	if (certs)
356471593db2Swyllys 		*certs = NULL;
356571593db2Swyllys 	fp = fopen(filename, "r");
35665b3e1433Swyllys 	if (fp == NULL)
356771593db2Swyllys 		return (KMF_ERR_OPEN_FILE);
35685b3e1433Swyllys 
356971593db2Swyllys 	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
357071593db2Swyllys 	if (x509_info_stack == NULL) {
357171593db2Swyllys 		(void) fclose(fp);
357271593db2Swyllys 		return (KMF_ERR_ENCODING);
357371593db2Swyllys 	}
35745b3e1433Swyllys 	cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
35755b3e1433Swyllys 	    sizeof (X509_INFO *));
35765b3e1433Swyllys 	if (cert_infos == NULL) {
35775b3e1433Swyllys 		(void) fclose(fp);
35785b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
35795b3e1433Swyllys 		goto err;
35805b3e1433Swyllys 	}
358171593db2Swyllys 
35825b3e1433Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
358371593db2Swyllys 		/* LINTED */
358434acef67Swyllys 		cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
358571593db2Swyllys 		ncerts++;
358671593db2Swyllys 	}
358771593db2Swyllys 
358871593db2Swyllys 	if (ncerts == 0) {
358971593db2Swyllys 		(void) fclose(fp);
359034acef67Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
359134acef67Swyllys 		goto err;
359271593db2Swyllys 	}
359371593db2Swyllys 
359471593db2Swyllys 	if (priv_key != NULL) {
359571593db2Swyllys 		rewind(fp);
359671593db2Swyllys 		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
359771593db2Swyllys 	}
359871593db2Swyllys 	(void) fclose(fp);
359971593db2Swyllys 
360071593db2Swyllys 	x = cert_infos[ncerts - 1]->x509;
360171593db2Swyllys 	/*
360271593db2Swyllys 	 * Make sure the private key matchs the last cert in the file.
360371593db2Swyllys 	 */
360471593db2Swyllys 	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
360571593db2Swyllys 		EVP_PKEY_free(pkey);
360634acef67Swyllys 		rv = KMF_ERR_KEY_MISMATCH;
360734acef67Swyllys 		goto err;
360871593db2Swyllys 	}
360971593db2Swyllys 
361071593db2Swyllys 	certlist = (KMF_DATA *)malloc(ncerts * sizeof (KMF_DATA));
361171593db2Swyllys 	if (certlist == NULL) {
361271593db2Swyllys 		if (pkey != NULL)
361371593db2Swyllys 			EVP_PKEY_free(pkey);
361434acef67Swyllys 		rv = KMF_ERR_MEMORY;
361534acef67Swyllys 		goto err;
361671593db2Swyllys 	}
361771593db2Swyllys 
361871593db2Swyllys 	/*
361971593db2Swyllys 	 * Convert all of the certs to DER format.
362071593db2Swyllys 	 */
362102744e81Swyllys 	matchcerts = 0;
362271593db2Swyllys 	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
362302744e81Swyllys 		boolean_t match = FALSE;
362471593db2Swyllys 		info =  cert_infos[ncerts - 1 - i];
362571593db2Swyllys 
362630a5e8faSwyllys 		rv = check_cert(info->x509, issuer, subject, serial, &match);
362702744e81Swyllys 		if (rv != KMF_OK || match != TRUE) {
362802744e81Swyllys 			rv = KMF_OK;
362902744e81Swyllys 			continue;
363002744e81Swyllys 		}
363102744e81Swyllys 
363202744e81Swyllys 		rv = ssl_cert2KMFDATA(kmfh, info->x509,
363302744e81Swyllys 			&certlist[matchcerts++]);
363471593db2Swyllys 
363571593db2Swyllys 		if (rv != KMF_OK) {
363671593db2Swyllys 			free(certlist);
363771593db2Swyllys 			certlist = NULL;
363802744e81Swyllys 			ncerts = matchcerts = 0;
363971593db2Swyllys 		}
364071593db2Swyllys 	}
364171593db2Swyllys 
364271593db2Swyllys 	if (numcerts != NULL)
364302744e81Swyllys 		*numcerts = matchcerts;
364471593db2Swyllys 	if (certs != NULL)
364571593db2Swyllys 		*certs = certlist;
364671593db2Swyllys 
364771593db2Swyllys 	if (priv_key == NULL && pkey != NULL)
364871593db2Swyllys 		EVP_PKEY_free(pkey);
364971593db2Swyllys 	else if (priv_key != NULL && pkey != NULL)
365071593db2Swyllys 		*priv_key = pkey;
365171593db2Swyllys 
365234acef67Swyllys err:
365334acef67Swyllys 	/* Cleanup the stack of X509 info records */
365434acef67Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
365534acef67Swyllys 		/*LINTED*/
365634acef67Swyllys 		info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
365734acef67Swyllys 		X509_INFO_free(info);
365834acef67Swyllys 	}
365934acef67Swyllys 	if (x509_info_stack)
366034acef67Swyllys 		sk_X509_INFO_free(x509_info_stack);
366134acef67Swyllys 
36625b3e1433Swyllys 	if (cert_infos != NULL)
36635b3e1433Swyllys 		free(cert_infos);
36645b3e1433Swyllys 
366571593db2Swyllys 	return (rv);
366671593db2Swyllys }
366771593db2Swyllys 
36685b3e1433Swyllys static KMF_RETURN
36695b3e1433Swyllys openssl_parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
36705b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
36715b3e1433Swyllys {
36725b3e1433Swyllys 	KMF_RETURN ret;
36735b3e1433Swyllys 	int i;
36745b3e1433Swyllys 
36755b3e1433Swyllys 	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
36765b3e1433Swyllys 		/*LINTED*/
36775b3e1433Swyllys 		PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
36785b3e1433Swyllys 		ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
36795b3e1433Swyllys 		    keys, certs);
36805b3e1433Swyllys 
36815b3e1433Swyllys 		if (ret != KMF_OK)
36825b3e1433Swyllys 			return (ret);
36835b3e1433Swyllys 	}
36845b3e1433Swyllys 
36855b3e1433Swyllys 	return (ret);
36865b3e1433Swyllys }
36875b3e1433Swyllys 
36885b3e1433Swyllys static KMF_RETURN
36895b3e1433Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
36905b3e1433Swyllys {
36915b3e1433Swyllys 	X509_ATTRIBUTE *attr = NULL;
36925b3e1433Swyllys 
36935b3e1433Swyllys 	if (pkey == NULL || attrib == NULL)
36945b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
36955b3e1433Swyllys 
36965b3e1433Swyllys 	if (pkey->attributes == NULL) {
36975b3e1433Swyllys 		pkey->attributes = sk_X509_ATTRIBUTE_new_null();
36985b3e1433Swyllys 		if (pkey->attributes == NULL)
36995b3e1433Swyllys 			return (KMF_ERR_MEMORY);
37005b3e1433Swyllys 	}
37015b3e1433Swyllys 	attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
37025b3e1433Swyllys 	if (attr != NULL) {
37035b3e1433Swyllys 		int i;
37045b3e1433Swyllys 		X509_ATTRIBUTE *a;
37055b3e1433Swyllys 		for (i = 0;
37065b3e1433Swyllys 		    i < sk_X509_ATTRIBUTE_num(pkey->attributes); i++) {
37075b3e1433Swyllys 			/*LINTED*/
37085b3e1433Swyllys 			a = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
37095b3e1433Swyllys 			if (OBJ_obj2nid(a->object) == nid) {
37105b3e1433Swyllys 				X509_ATTRIBUTE_free(a);
37115b3e1433Swyllys 				/*LINTED*/
37125b3e1433Swyllys 				sk_X509_ATTRIBUTE_set(pkey->attributes,
37135b3e1433Swyllys 				    i, attr);
37145b3e1433Swyllys 				return (KMF_OK);
37155b3e1433Swyllys 			}
37165b3e1433Swyllys 		}
37175b3e1433Swyllys 		if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == NULL) {
37185b3e1433Swyllys 			X509_ATTRIBUTE_free(attr);
37195b3e1433Swyllys 			return (KMF_ERR_MEMORY);
37205b3e1433Swyllys 		}
37215b3e1433Swyllys 	} else {
37225b3e1433Swyllys 		return (KMF_ERR_MEMORY);
37235b3e1433Swyllys 	}
37245b3e1433Swyllys 
37255b3e1433Swyllys 	return (KMF_OK);
37265b3e1433Swyllys }
37275b3e1433Swyllys 
37285b3e1433Swyllys static KMF_RETURN
37295b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
37305b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
37315b3e1433Swyllys {
37325b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
37335b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
37345b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
37355b3e1433Swyllys 	X509 *xcert = NULL;
37365b3e1433Swyllys 	ASN1_TYPE *keyid = NULL;
37375b3e1433Swyllys 	ASN1_TYPE *fname = NULL;
37385b3e1433Swyllys 	uchar_t *data = NULL;
37395b3e1433Swyllys 
37405b3e1433Swyllys 	keyid = PKCS12_get_attr(bag, NID_localKeyID);
37415b3e1433Swyllys 	fname = PKCS12_get_attr(bag, NID_friendlyName);
37425b3e1433Swyllys 
37435b3e1433Swyllys 	switch (M_PKCS12_bag_type(bag)) {
37445b3e1433Swyllys 		case NID_keyBag:
37455b3e1433Swyllys 			if (keylist == NULL)
37465b3e1433Swyllys 				goto end;
37475b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(bag->value.keybag);
37485b3e1433Swyllys 			if (pkey == NULL)
37495b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
37505b3e1433Swyllys 
37515b3e1433Swyllys 			break;
37525b3e1433Swyllys 		case NID_pkcs8ShroudedKeyBag:
37535b3e1433Swyllys 			if (keylist == NULL)
37545b3e1433Swyllys 				goto end;
37555b3e1433Swyllys 			p8 = M_PKCS12_decrypt_skey(bag, pass, passlen);
37565b3e1433Swyllys 			if (p8 == NULL)
37575b3e1433Swyllys 				return (KMF_ERR_AUTH_FAILED);
37585b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(p8);
37595b3e1433Swyllys 			PKCS8_PRIV_KEY_INFO_free(p8);
37605b3e1433Swyllys 			if (pkey == NULL)
37615b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
37625b3e1433Swyllys 			break;
37635b3e1433Swyllys 		case NID_certBag:
37645b3e1433Swyllys 			if (certlist == NULL)
37655b3e1433Swyllys 				goto end;
37665b3e1433Swyllys 			if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate)
37675b3e1433Swyllys 				return (KMF_ERR_PKCS12_FORMAT);
37685b3e1433Swyllys 			xcert = M_PKCS12_certbag2x509(bag);
37695b3e1433Swyllys 			if (xcert == NULL) {
37705b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
37715b3e1433Swyllys 				goto end;
37725b3e1433Swyllys 			}
37735b3e1433Swyllys 			if (keyid != NULL) {
37745b3e1433Swyllys 				if (X509_keyid_set1(xcert,
37755b3e1433Swyllys 				    keyid->value.octet_string->data,
37765b3e1433Swyllys 				    keyid->value.octet_string->length) == 0) {
37775b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
37785b3e1433Swyllys 					goto end;
37795b3e1433Swyllys 				}
37805b3e1433Swyllys 			}
37815b3e1433Swyllys 			if (fname != NULL) {
37825b3e1433Swyllys 				int len, r;
37835b3e1433Swyllys 				len = ASN1_STRING_to_UTF8(&data,
37845b3e1433Swyllys 				    fname->value.asn1_string);
37855b3e1433Swyllys 				if (len > 0 && data != NULL) {
37865b3e1433Swyllys 					r = X509_alias_set1(xcert, data, len);
37875b3e1433Swyllys 					if (r == NULL) {
37885b3e1433Swyllys 						ret = KMF_ERR_PKCS12_FORMAT;
37895b3e1433Swyllys 						goto end;
37905b3e1433Swyllys 					}
37915b3e1433Swyllys 				} else {
37925b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
37935b3e1433Swyllys 					goto end;
37945b3e1433Swyllys 				}
37955b3e1433Swyllys 			}
37965b3e1433Swyllys 			if (sk_X509_push(certlist, xcert) == 0)
37975b3e1433Swyllys 				ret = KMF_ERR_MEMORY;
37985b3e1433Swyllys 			else
37995b3e1433Swyllys 				xcert = NULL;
38005b3e1433Swyllys 			break;
38015b3e1433Swyllys 		case NID_safeContentsBag:
38025b3e1433Swyllys 			return (openssl_parse_bags(bag->value.safes, pass,
38035b3e1433Swyllys 			    keylist, certlist));
38045b3e1433Swyllys 		default:
38055b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
38065b3e1433Swyllys 			break;
38075b3e1433Swyllys 	}
38085b3e1433Swyllys 
38095b3e1433Swyllys 	/*
38105b3e1433Swyllys 	 * Set the ID and/or FriendlyName attributes on the key.
38115b3e1433Swyllys 	 * If converting to PKCS11 objects, these can translate to CKA_ID
38125b3e1433Swyllys 	 * and CKA_LABEL values.
38135b3e1433Swyllys 	 */
38145b3e1433Swyllys 	if (pkey != NULL && ret == KMF_OK) {
38155b3e1433Swyllys 		ASN1_TYPE *attr = NULL;
38165b3e1433Swyllys 		if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
38175b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
38185b3e1433Swyllys 				return (KMF_ERR_MEMORY);
38195b3e1433Swyllys 			attr->value.octet_string =
38205b3e1433Swyllys 			    ASN1_STRING_dup(keyid->value.octet_string);
38215b3e1433Swyllys 			attr->type = V_ASN1_OCTET_STRING;
38225b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.octet_string;
38235b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
38245b3e1433Swyllys 			OPENSSL_free(attr);
38255b3e1433Swyllys 		}
38265b3e1433Swyllys 
38275b3e1433Swyllys 		if (ret == KMF_OK && fname != NULL &&
38285b3e1433Swyllys 		    fname->type == V_ASN1_BMPSTRING) {
38295b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
38305b3e1433Swyllys 				return (KMF_ERR_MEMORY);
38315b3e1433Swyllys 			attr->value.bmpstring =
38325b3e1433Swyllys 			    ASN1_STRING_dup(fname->value.bmpstring);
38335b3e1433Swyllys 			attr->type = V_ASN1_BMPSTRING;
38345b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.bmpstring;
38355b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
38365b3e1433Swyllys 			OPENSSL_free(attr);
38375b3e1433Swyllys 		}
38385b3e1433Swyllys 
38395b3e1433Swyllys 		if (ret == KMF_OK && keylist != NULL &&
38405b3e1433Swyllys 		    sk_EVP_PKEY_push(keylist, pkey) == 0)
38415b3e1433Swyllys 			ret = KMF_ERR_MEMORY;
38425b3e1433Swyllys 	}
38435b3e1433Swyllys 	if (ret == KMF_OK && keylist != NULL)
38445b3e1433Swyllys 		pkey = NULL;
38455b3e1433Swyllys end:
38465b3e1433Swyllys 	if (pkey != NULL)
38475b3e1433Swyllys 		EVP_PKEY_free(pkey);
38485b3e1433Swyllys 	if (xcert != NULL)
38495b3e1433Swyllys 		X509_free(xcert);
38505b3e1433Swyllys 	if (data != NULL)
38515b3e1433Swyllys 		OPENSSL_free(data);
38525b3e1433Swyllys 
38535b3e1433Swyllys 	return (ret);
38545b3e1433Swyllys }
38555b3e1433Swyllys 
38565b3e1433Swyllys static KMF_RETURN
38575b3e1433Swyllys openssl_pkcs12_parse(PKCS12 *p12, char *pin,
38585b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys,
38595b3e1433Swyllys 	STACK_OF(X509) *certs,
38605b3e1433Swyllys 	STACK_OF(X509) *ca)
38615b3e1433Swyllys /*ARGSUSED*/
38625b3e1433Swyllys {
38635b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
38645b3e1433Swyllys 	STACK_OF(PKCS7) *asafes = NULL;
38655b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
38665b3e1433Swyllys 	int i, bagnid;
38675b3e1433Swyllys 	PKCS7 *p7;
38685b3e1433Swyllys 
38695b3e1433Swyllys 	if (p12 == NULL || (keys == NULL && certs == NULL))
38705b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
38715b3e1433Swyllys 
38725b3e1433Swyllys 	if (pin == NULL || *pin == NULL) {
38735b3e1433Swyllys 		if (PKCS12_verify_mac(p12, NULL, 0)) {
38745b3e1433Swyllys 			pin = NULL;
38755b3e1433Swyllys 		} else if (PKCS12_verify_mac(p12, "", 0)) {
38765b3e1433Swyllys 			pin = "";
38775b3e1433Swyllys 		} else {
38785b3e1433Swyllys 			return (KMF_ERR_AUTH_FAILED);
38795b3e1433Swyllys 		}
38805b3e1433Swyllys 	} else if (!PKCS12_verify_mac(p12, pin, -1)) {
38815b3e1433Swyllys 		return (KMF_ERR_AUTH_FAILED);
38825b3e1433Swyllys 	}
38835b3e1433Swyllys 
38845b3e1433Swyllys 	if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
38855b3e1433Swyllys 		return (KMF_ERR_PKCS12_FORMAT);
38865b3e1433Swyllys 
38875b3e1433Swyllys 	for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
38885b3e1433Swyllys 		bags = NULL;
38895b3e1433Swyllys 		/*LINTED*/
38905b3e1433Swyllys 		p7 = sk_PKCS7_value(asafes, i);
38915b3e1433Swyllys 		bagnid = OBJ_obj2nid(p7->type);
38925b3e1433Swyllys 
38935b3e1433Swyllys 		if (bagnid == NID_pkcs7_data) {
38945b3e1433Swyllys 			bags = PKCS12_unpack_p7data(p7);
38955b3e1433Swyllys 		} else if (bagnid == NID_pkcs7_encrypted) {
38965b3e1433Swyllys 			bags = PKCS12_unpack_p7encdata(p7, pin,
38975b3e1433Swyllys 			    (pin ? strlen(pin) : 0));
38985b3e1433Swyllys 		} else {
38995b3e1433Swyllys 			continue;
39005b3e1433Swyllys 		}
39015b3e1433Swyllys 		if (bags == NULL) {
39025b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39035b3e1433Swyllys 			goto out;
39045b3e1433Swyllys 		}
39055b3e1433Swyllys 
39065b3e1433Swyllys 		if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
39075b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39085b3e1433Swyllys 
39095b3e1433Swyllys 		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
39105b3e1433Swyllys 	}
39115b3e1433Swyllys out:
39125b3e1433Swyllys 	if (asafes != NULL)
39135b3e1433Swyllys 		sk_PKCS7_pop_free(asafes, PKCS7_free);
39145b3e1433Swyllys 
39155b3e1433Swyllys 	return (ret);
39165b3e1433Swyllys }
39175b3e1433Swyllys 
391899ebb4caSwyllys /*
391999ebb4caSwyllys  * Helper function to decrypt and parse PKCS#12 import file.
392099ebb4caSwyllys  */
392199ebb4caSwyllys static KMF_RETURN
392299ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
39235b3e1433Swyllys 	STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs,
39245b3e1433Swyllys 	STACK_OF(X509) **ca)
392599ebb4caSwyllys /* ARGSUSED */
392699ebb4caSwyllys {
392799ebb4caSwyllys 	PKCS12			*pk12, *pk12_tmp;
39285b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*pkeylist = NULL;
39295b3e1433Swyllys 	STACK_OF(X509)		*xcertlist = NULL;
39305b3e1433Swyllys 	STACK_OF(X509)		*cacertlist = NULL;
393199ebb4caSwyllys 
393299ebb4caSwyllys 	if ((pk12 = PKCS12_new()) == NULL) {
393399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
393499ebb4caSwyllys 	}
393599ebb4caSwyllys 
393699ebb4caSwyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
393799ebb4caSwyllys 		/* This is ok; it seems to mean there is no more to read. */
393899ebb4caSwyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
393999ebb4caSwyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
394099ebb4caSwyllys 			goto end_extract_pkcs12;
394199ebb4caSwyllys 
394299ebb4caSwyllys 		PKCS12_free(pk12);
394399ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
394499ebb4caSwyllys 	}
394599ebb4caSwyllys 	pk12 = pk12_tmp;
394699ebb4caSwyllys 
39475b3e1433Swyllys 	xcertlist = sk_X509_new_null();
39485b3e1433Swyllys 	if (xcertlist == NULL) {
39495b3e1433Swyllys 		PKCS12_free(pk12);
39505b3e1433Swyllys 		return (KMF_ERR_MEMORY);
39515b3e1433Swyllys 	}
39525b3e1433Swyllys 	pkeylist = sk_EVP_PKEY_new_null();
39535b3e1433Swyllys 	if (pkeylist == NULL) {
39545b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
39555b3e1433Swyllys 		PKCS12_free(pk12);
39565b3e1433Swyllys 		return (KMF_ERR_MEMORY);
39575b3e1433Swyllys 	}
39585b3e1433Swyllys 
39595b3e1433Swyllys 	if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
39605b3e1433Swyllys 	    cacertlist) != KMF_OK) {
39615b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
39625b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
396399ebb4caSwyllys 		PKCS12_free(pk12);
396499ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
396599ebb4caSwyllys 	}
396699ebb4caSwyllys 
39675b3e1433Swyllys 	if (priv_key && pkeylist)
39685b3e1433Swyllys 		*priv_key = pkeylist;
39695b3e1433Swyllys 	else if (pkeylist)
39705b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
39715b3e1433Swyllys 	if (certs && xcertlist)
39725b3e1433Swyllys 		*certs = xcertlist;
39735b3e1433Swyllys 	else if (xcertlist)
39745b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
39755b3e1433Swyllys 	if (ca && cacertlist)
39765b3e1433Swyllys 		*ca = cacertlist;
39775b3e1433Swyllys 	else if (cacertlist)
39785b3e1433Swyllys 		sk_X509_pop_free(cacertlist, X509_free);
397999ebb4caSwyllys 
39805b3e1433Swyllys end_extract_pkcs12:
398199ebb4caSwyllys 
398299ebb4caSwyllys 	PKCS12_free(pk12);
398399ebb4caSwyllys 	return (KMF_OK);
398499ebb4caSwyllys }
398599ebb4caSwyllys 
398699ebb4caSwyllys static KMF_RETURN
398799ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
398899ebb4caSwyllys {
398999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
399099ebb4caSwyllys 	uint32_t sz;
399199ebb4caSwyllys 
399299ebb4caSwyllys 	sz = BN_num_bytes(from);
399399ebb4caSwyllys 	to->val = (uchar_t *)malloc(sz);
399499ebb4caSwyllys 	if (to->val == NULL)
399599ebb4caSwyllys 		return (KMF_ERR_MEMORY);
399699ebb4caSwyllys 
399799ebb4caSwyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
399899ebb4caSwyllys 		free(to->val);
399999ebb4caSwyllys 		to->val = NULL;
400099ebb4caSwyllys 		to->len = 0;
400199ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
400299ebb4caSwyllys 	}
400399ebb4caSwyllys 
400499ebb4caSwyllys 	return (rv);
400599ebb4caSwyllys }
400699ebb4caSwyllys 
400799ebb4caSwyllys static KMF_RETURN
400899ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
400999ebb4caSwyllys {
401099ebb4caSwyllys 	KMF_RETURN rv;
401199ebb4caSwyllys 	KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
401299ebb4caSwyllys 
401399ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
401499ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK)
401599ebb4caSwyllys 		goto cleanup;
401699ebb4caSwyllys 
401799ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK)
401899ebb4caSwyllys 		goto cleanup;
401999ebb4caSwyllys 
402099ebb4caSwyllys 	if (rsa->d != NULL)
402199ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK)
402299ebb4caSwyllys 			goto cleanup;
402399ebb4caSwyllys 
402499ebb4caSwyllys 	if (rsa->p != NULL)
402599ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK)
402699ebb4caSwyllys 			goto cleanup;
402799ebb4caSwyllys 
402899ebb4caSwyllys 	if (rsa->q != NULL)
402999ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK)
403099ebb4caSwyllys 			goto cleanup;
403199ebb4caSwyllys 
403299ebb4caSwyllys 	if (rsa->dmp1 != NULL)
403399ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK)
403499ebb4caSwyllys 			goto cleanup;
403599ebb4caSwyllys 
403699ebb4caSwyllys 	if (rsa->dmq1 != NULL)
403799ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK)
403899ebb4caSwyllys 			goto cleanup;
403999ebb4caSwyllys 
404099ebb4caSwyllys 	if (rsa->iqmp != NULL)
404199ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK)
404299ebb4caSwyllys 			goto cleanup;
404399ebb4caSwyllys cleanup:
404499ebb4caSwyllys 	if (rv != KMF_OK)
404530a5e8faSwyllys 		kmf_free_raw_key(key);
404699ebb4caSwyllys 	else
404799ebb4caSwyllys 		key->keytype = KMF_RSA;
404899ebb4caSwyllys 
404999ebb4caSwyllys 	/*
405099ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
405199ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
405299ebb4caSwyllys 	 */
405399ebb4caSwyllys 	RSA_free(rsa);
405499ebb4caSwyllys 
405599ebb4caSwyllys 	return (rv);
405699ebb4caSwyllys }
405799ebb4caSwyllys 
405899ebb4caSwyllys static KMF_RETURN
405999ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
406099ebb4caSwyllys {
406199ebb4caSwyllys 	KMF_RETURN rv;
406299ebb4caSwyllys 	KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
406399ebb4caSwyllys 
406499ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
406599ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK)
406699ebb4caSwyllys 		goto cleanup;
406799ebb4caSwyllys 
406899ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK)
406999ebb4caSwyllys 		goto cleanup;
407099ebb4caSwyllys 
407199ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK)
407299ebb4caSwyllys 		goto cleanup;
407399ebb4caSwyllys 
407499ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK)
407599ebb4caSwyllys 		goto cleanup;
407699ebb4caSwyllys 
407799ebb4caSwyllys cleanup:
407899ebb4caSwyllys 	if (rv != KMF_OK)
407930a5e8faSwyllys 		kmf_free_raw_key(key);
408099ebb4caSwyllys 	else
408199ebb4caSwyllys 		key->keytype = KMF_DSA;
408299ebb4caSwyllys 
408399ebb4caSwyllys 	/*
408499ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
408599ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
408699ebb4caSwyllys 	 */
408799ebb4caSwyllys 	DSA_free(dsa);
408899ebb4caSwyllys 
408999ebb4caSwyllys 	return (rv);
409099ebb4caSwyllys }
409199ebb4caSwyllys 
409299ebb4caSwyllys static KMF_RETURN
409399ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
40945b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
409599ebb4caSwyllys {
409699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
40975b3e1433Swyllys 	KMF_X509_DER_CERT *list = (*certlist);
40985b3e1433Swyllys 	KMF_X509_DER_CERT cert;
409999ebb4caSwyllys 	int n = (*ncerts);
410099ebb4caSwyllys 
410199ebb4caSwyllys 	if (list == NULL) {
41025b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
410399ebb4caSwyllys 	} else {
41045b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)realloc(list,
41055b3e1433Swyllys 		    sizeof (KMF_X509_DER_CERT) * (n + 1));
410699ebb4caSwyllys 	}
410799ebb4caSwyllys 
410899ebb4caSwyllys 	if (list == NULL)
410999ebb4caSwyllys 		return (KMF_ERR_MEMORY);
411099ebb4caSwyllys 
41115b3e1433Swyllys 	(void) memset(&cert, 0, sizeof (cert));
41125b3e1433Swyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
411399ebb4caSwyllys 	if (rv == KMF_OK) {
41145b3e1433Swyllys 		int len = 0;
41155b3e1433Swyllys 		/* Get the alias name for the cert if there is one */
41165b3e1433Swyllys 		char *a = (char *)X509_alias_get0(sslcert, &len);
41175b3e1433Swyllys 		if (a != NULL)
41185b3e1433Swyllys 			cert.kmf_private.label = strdup(a);
41195b3e1433Swyllys 		cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
41205b3e1433Swyllys 
412199ebb4caSwyllys 		list[n] = cert;
412299ebb4caSwyllys 		(*ncerts) = n + 1;
412399ebb4caSwyllys 
412499ebb4caSwyllys 		*certlist = list;
412599ebb4caSwyllys 	} else {
412699ebb4caSwyllys 		free(list);
412799ebb4caSwyllys 	}
412899ebb4caSwyllys 
412999ebb4caSwyllys 	return (rv);
413099ebb4caSwyllys }
413199ebb4caSwyllys 
413299ebb4caSwyllys static KMF_RETURN
413399ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
413499ebb4caSwyllys 	KMF_RAW_KEY_DATA *newkey, int *nkeys)
413599ebb4caSwyllys {
413699ebb4caSwyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
413799ebb4caSwyllys 	int n = (*nkeys);
413899ebb4caSwyllys 
413999ebb4caSwyllys 	if (list == NULL) {
414099ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
414199ebb4caSwyllys 	} else {
414299ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
414399ebb4caSwyllys 		    sizeof (KMF_RAW_KEY_DATA) * (n + 1));
414499ebb4caSwyllys 	}
414599ebb4caSwyllys 
414699ebb4caSwyllys 	if (list == NULL)
414799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
414899ebb4caSwyllys 
414999ebb4caSwyllys 	list[n] = *newkey;
415099ebb4caSwyllys 	(*nkeys) = n + 1;
415199ebb4caSwyllys 
415299ebb4caSwyllys 	*keylist = list;
415399ebb4caSwyllys 
415499ebb4caSwyllys 	return (KMF_OK);
415599ebb4caSwyllys }
415699ebb4caSwyllys 
41575b3e1433Swyllys static X509_ATTRIBUTE *
41585b3e1433Swyllys find_attr(STACK_OF(X509_ATTRIBUTE) *attrs, int nid)
41595b3e1433Swyllys {
41605b3e1433Swyllys 	X509_ATTRIBUTE *a;
41615b3e1433Swyllys 	int i;
41625b3e1433Swyllys 
41635b3e1433Swyllys 	if (attrs == NULL)
41645b3e1433Swyllys 		return (NULL);
41655b3e1433Swyllys 
41665b3e1433Swyllys 	for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
41675b3e1433Swyllys 		/*LINTED*/
41685b3e1433Swyllys 		a = sk_X509_ATTRIBUTE_value(attrs, i);
41695b3e1433Swyllys 		if (OBJ_obj2nid(a->object) == nid)
41705b3e1433Swyllys 			return (a);
41715b3e1433Swyllys 	}
41725b3e1433Swyllys 	return (NULL);
41735b3e1433Swyllys }
41745b3e1433Swyllys 
417530a5e8faSwyllys static KMF_RETURN
417630a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
417730a5e8faSwyllys {
417830a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
41795b3e1433Swyllys 	X509_ATTRIBUTE *attr;
418030a5e8faSwyllys 
418130a5e8faSwyllys 	if (pkey == NULL || key == NULL)
418230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
418330a5e8faSwyllys 	/* Convert SSL key to raw key */
418430a5e8faSwyllys 	switch (pkey->type) {
418530a5e8faSwyllys 		case EVP_PKEY_RSA:
418630a5e8faSwyllys 			rv = exportRawRSAKey(EVP_PKEY_get1_RSA(pkey),
418730a5e8faSwyllys 			    key);
418830a5e8faSwyllys 			if (rv != KMF_OK)
418930a5e8faSwyllys 				return (rv);
419030a5e8faSwyllys 			break;
419130a5e8faSwyllys 		case EVP_PKEY_DSA:
419230a5e8faSwyllys 			rv = exportRawDSAKey(EVP_PKEY_get1_DSA(pkey),
419330a5e8faSwyllys 			    key);
419430a5e8faSwyllys 			if (rv != KMF_OK)
419530a5e8faSwyllys 				return (rv);
419630a5e8faSwyllys 			break;
419730a5e8faSwyllys 		default:
419830a5e8faSwyllys 			return (KMF_ERR_BAD_PARAMETER);
419930a5e8faSwyllys 	}
42005b3e1433Swyllys 	/*
42015b3e1433Swyllys 	 * If friendlyName, add it to record.
42025b3e1433Swyllys 	 */
42035b3e1433Swyllys 	attr = find_attr(pkey->attributes, NID_friendlyName);
42045b3e1433Swyllys 	if (attr != NULL) {
42055b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
42065b3e1433Swyllys 		int numattr = sk_ASN1_TYPE_num(attr->value.set);
42075b3e1433Swyllys 		if (attr->single == 0 && numattr > 0) {
42085b3e1433Swyllys 			/*LINTED*/
42095b3e1433Swyllys 			ty = sk_ASN1_TYPE_value(attr->value.set, 0);
42105b3e1433Swyllys 		}
42115b3e1433Swyllys 		if (ty != NULL) {
42125b3e1433Swyllys 			key->label = uni2asc(ty->value.bmpstring->data,
42135b3e1433Swyllys 			    ty->value.bmpstring->length);
42145b3e1433Swyllys 		}
42155b3e1433Swyllys 	} else {
42165b3e1433Swyllys 		key->label = NULL;
42175b3e1433Swyllys 	}
42185b3e1433Swyllys 
42195b3e1433Swyllys 	/*
42205b3e1433Swyllys 	 * If KeyID, add it to record as a KMF_DATA object.
42215b3e1433Swyllys 	 */
42225b3e1433Swyllys 	attr = find_attr(pkey->attributes, NID_localKeyID);
42235b3e1433Swyllys 	if (attr != NULL) {
42245b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
42255b3e1433Swyllys 		int numattr = sk_ASN1_TYPE_num(attr->value.set);
42265b3e1433Swyllys 		if (attr->single == 0 && numattr > 0) {
42275b3e1433Swyllys 			/*LINTED*/
42285b3e1433Swyllys 			ty = sk_ASN1_TYPE_value(attr->value.set, 0);
42295b3e1433Swyllys 		}
42305b3e1433Swyllys 		key->id.Data = (uchar_t *)malloc(
42315b3e1433Swyllys 		    ty->value.octet_string->length);
42325b3e1433Swyllys 		if (key->id.Data == NULL)
42335b3e1433Swyllys 			return (KMF_ERR_MEMORY);
42345b3e1433Swyllys 		(void) memcpy(key->id.Data, ty->value.octet_string->data,
42355b3e1433Swyllys 		    ty->value.octet_string->length);
42365b3e1433Swyllys 		key->id.Length = ty->value.octet_string->length;
42375b3e1433Swyllys 	} else {
42385b3e1433Swyllys 		(void) memset(&key->id, 0, sizeof (KMF_DATA));
42395b3e1433Swyllys 	}
424030a5e8faSwyllys 
424130a5e8faSwyllys 	return (rv);
424230a5e8faSwyllys }
424399ebb4caSwyllys 
424499ebb4caSwyllys static KMF_RETURN
424599ebb4caSwyllys convertPK12Objects(
424699ebb4caSwyllys 	KMF_HANDLE *kmfh,
42475b3e1433Swyllys 	STACK_OF(EVP_PKEY) *sslkeys,
42485b3e1433Swyllys 	STACK_OF(X509) *sslcert,
42495b3e1433Swyllys 	STACK_OF(X509) *sslcacerts,
425099ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
42515b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
425299ebb4caSwyllys {
425399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
425499ebb4caSwyllys 	KMF_RAW_KEY_DATA key;
425599ebb4caSwyllys 	int i;
425699ebb4caSwyllys 
42575b3e1433Swyllys 	for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
42585b3e1433Swyllys 		/*LINTED*/
42595b3e1433Swyllys 		EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
42605b3e1433Swyllys 		rv = convertToRawKey(pkey, &key);
426130a5e8faSwyllys 		if (rv == KMF_OK)
426299ebb4caSwyllys 			rv = add_key_to_list(keylist, &key, nkeys);
426330a5e8faSwyllys 
426499ebb4caSwyllys 		if (rv != KMF_OK)
426599ebb4caSwyllys 			return (rv);
426699ebb4caSwyllys 	}
426799ebb4caSwyllys 
426899ebb4caSwyllys 	/* Now add the certificate to the certlist */
42695b3e1433Swyllys 	for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
42705b3e1433Swyllys 		/*LINTED*/
42715b3e1433Swyllys 		X509 *cert = sk_X509_value(sslcert, i);
42725b3e1433Swyllys 		rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
427399ebb4caSwyllys 		if (rv != KMF_OK)
427499ebb4caSwyllys 			return (rv);
427599ebb4caSwyllys 	}
427699ebb4caSwyllys 
427799ebb4caSwyllys 	/* Also add any included CA certs to the list */
427871593db2Swyllys 	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
427999ebb4caSwyllys 		X509 *c;
428099ebb4caSwyllys 		/*
428199ebb4caSwyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
428299ebb4caSwyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
428399ebb4caSwyllys 		 * Lint is complaining about the embedded casting, and
428499ebb4caSwyllys 		 * to fix it, you need to fix openssl header files.
428599ebb4caSwyllys 		 */
428699ebb4caSwyllys 		/* LINTED E_BAD_PTR_CAST_ALIGN */
428799ebb4caSwyllys 		c = sk_X509_value(sslcacerts, i);
428899ebb4caSwyllys 
428999ebb4caSwyllys 		/* Now add the ca cert to the certlist */
429099ebb4caSwyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
429199ebb4caSwyllys 		if (rv != KMF_OK)
429299ebb4caSwyllys 			return (rv);
429399ebb4caSwyllys 	}
429499ebb4caSwyllys 	return (rv);
429599ebb4caSwyllys }
429699ebb4caSwyllys 
429799ebb4caSwyllys KMF_RETURN
429830a5e8faSwyllys openssl_import_objects(KMF_HANDLE *kmfh,
429999ebb4caSwyllys 	char *filename, KMF_CREDENTIAL *cred,
43005b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts,
430199ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
430299ebb4caSwyllys {
430399ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
430430a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
430530a5e8faSwyllys 	BIO		*bio = NULL;
43065b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*privkeys = NULL;
43075b3e1433Swyllys 	STACK_OF(X509)		*certs = NULL;
430899ebb4caSwyllys 	STACK_OF(X509)		*cacerts = NULL;
430999ebb4caSwyllys 
431030a5e8faSwyllys 	/*
431130a5e8faSwyllys 	 * auto-detect the file format, regardless of what
431230a5e8faSwyllys 	 * the 'format' parameters in the params say.
431330a5e8faSwyllys 	 */
431430a5e8faSwyllys 	rv = kmf_get_file_format(filename, &format);
431530a5e8faSwyllys 	if (rv != KMF_OK) {
431630a5e8faSwyllys 		return (rv);
431730a5e8faSwyllys 	}
431830a5e8faSwyllys 
431930a5e8faSwyllys 	/* This function only works for PEM or PKCS#12 files */
432030a5e8faSwyllys 	if (format != KMF_FORMAT_PEM &&
432130a5e8faSwyllys 	    format != KMF_FORMAT_PEM_KEYPAIR &&
432230a5e8faSwyllys 	    format != KMF_FORMAT_PKCS12)
432330a5e8faSwyllys 		return (KMF_ERR_ENCODING);
432430a5e8faSwyllys 
432530a5e8faSwyllys 	*certlist = NULL;
432630a5e8faSwyllys 	*keylist = NULL;
432730a5e8faSwyllys 	*ncerts = 0;
432830a5e8faSwyllys 	*nkeys = 0;
432930a5e8faSwyllys 
433030a5e8faSwyllys 	if (format == KMF_FORMAT_PKCS12) {
433199ebb4caSwyllys 		bio = BIO_new_file(filename, "rb");
433299ebb4caSwyllys 		if (bio == NULL) {
433399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
433499ebb4caSwyllys 			rv = KMF_ERR_OPEN_FILE;
433599ebb4caSwyllys 			goto end;
433699ebb4caSwyllys 		}
433799ebb4caSwyllys 
433834acef67Swyllys 		rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
43395b3e1433Swyllys 		    (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
434099ebb4caSwyllys 
434199ebb4caSwyllys 		if (rv  == KMF_OK)
434299ebb4caSwyllys 			/* Convert keys and certs to exportable format */
43435b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
434499ebb4caSwyllys 			    keylist, nkeys, certlist, ncerts);
434530a5e8faSwyllys 	} else {
43465b3e1433Swyllys 		EVP_PKEY *pkey;
43475b3e1433Swyllys 		KMF_DATA *certdata = NULL;
43485b3e1433Swyllys 		KMF_X509_DER_CERT *kmfcerts = NULL;
43495b3e1433Swyllys 		int i;
435030a5e8faSwyllys 		rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
435134acef67Swyllys 		    (uchar_t *)cred->cred, (uint32_t)cred->credlen,
43525b3e1433Swyllys 		    &pkey, &certdata, ncerts);
435371593db2Swyllys 
435471593db2Swyllys 		/* Reached end of import file? */
43555b3e1433Swyllys 		if (rv == KMF_OK && pkey != NULL) {
43565b3e1433Swyllys 			privkeys = sk_EVP_PKEY_new_null();
43575b3e1433Swyllys 			if (privkeys == NULL) {
43585b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
43595b3e1433Swyllys 				goto end;
43605b3e1433Swyllys 			}
43615b3e1433Swyllys 			(void) sk_EVP_PKEY_push(privkeys, pkey);
43625b3e1433Swyllys 			/* convert the certificate list here */
43635b3e1433Swyllys 			if (*ncerts > 0 && certlist != NULL) {
43645b3e1433Swyllys 				kmfcerts = (KMF_X509_DER_CERT *)malloc(*ncerts *
43655b3e1433Swyllys 				    sizeof (KMF_X509_DER_CERT));
43665b3e1433Swyllys 				if (kmfcerts == NULL) {
43675b3e1433Swyllys 					rv = KMF_ERR_MEMORY;
43685b3e1433Swyllys 					goto end;
43695b3e1433Swyllys 				}
43705b3e1433Swyllys 				(void) memset(kmfcerts, 0, *ncerts *
43715b3e1433Swyllys 				    sizeof (KMF_X509_DER_CERT));
43725b3e1433Swyllys 				for (i = 0; i < *ncerts; i++) {
43735b3e1433Swyllys 					kmfcerts[i].certificate = certdata[i];
43745b3e1433Swyllys 					kmfcerts[i].kmf_private.keystore_type =
43755b3e1433Swyllys 					    KMF_KEYSTORE_OPENSSL;
43765b3e1433Swyllys 				}
43775b3e1433Swyllys 				*certlist = kmfcerts;
43785b3e1433Swyllys 			}
43795b3e1433Swyllys 			/*
43805b3e1433Swyllys 			 * Convert keys to exportable format, the certs
43815b3e1433Swyllys 			 * are already OK.
43825b3e1433Swyllys 			 */
43835b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
438471593db2Swyllys 			    keylist, nkeys, NULL, NULL);
438530a5e8faSwyllys 		}
43865b3e1433Swyllys 	}
438771593db2Swyllys end:
438830a5e8faSwyllys 	if (bio != NULL)
438999ebb4caSwyllys 		(void) BIO_free(bio);
439099ebb4caSwyllys 
43915b3e1433Swyllys 	if (privkeys)
43925b3e1433Swyllys 		sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
43935b3e1433Swyllys 	if (certs)
43945b3e1433Swyllys 		sk_X509_pop_free(certs, X509_free);
439530a5e8faSwyllys 	if (cacerts)
43965b3e1433Swyllys 		sk_X509_pop_free(cacerts, X509_free);
439730a5e8faSwyllys 
439899ebb4caSwyllys 	return (rv);
439999ebb4caSwyllys }
440099ebb4caSwyllys 
440199ebb4caSwyllys static KMF_RETURN
440299ebb4caSwyllys create_deskey(DES_cblock **deskey)
440399ebb4caSwyllys {
440499ebb4caSwyllys 	DES_cblock *key;
440599ebb4caSwyllys 
440699ebb4caSwyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
440799ebb4caSwyllys 	if (key == NULL) {
440899ebb4caSwyllys 		return (KMF_ERR_MEMORY);
440999ebb4caSwyllys 	}
441099ebb4caSwyllys 
441199ebb4caSwyllys 	if (DES_random_key(key) == 0) {
441299ebb4caSwyllys 		free(key);
441399ebb4caSwyllys 		return (KMF_ERR_KEYGEN_FAILED);
441499ebb4caSwyllys 	}
441599ebb4caSwyllys 
441699ebb4caSwyllys 	*deskey = key;
441799ebb4caSwyllys 	return (KMF_OK);
441899ebb4caSwyllys }
441999ebb4caSwyllys 
442099ebb4caSwyllys #define	KEYGEN_RETRY 3
442199ebb4caSwyllys #define	DES3_KEY_SIZE 24
442299ebb4caSwyllys 
442399ebb4caSwyllys static KMF_RETURN
442499ebb4caSwyllys create_des3key(unsigned char **des3key)
442599ebb4caSwyllys {
442699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
442799ebb4caSwyllys 	DES_cblock *deskey1 = NULL;
442899ebb4caSwyllys 	DES_cblock *deskey2 = NULL;
442999ebb4caSwyllys 	DES_cblock *deskey3 = NULL;
443099ebb4caSwyllys 	unsigned char *newkey = NULL;
443199ebb4caSwyllys 	int retry;
443299ebb4caSwyllys 
443399ebb4caSwyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
443499ebb4caSwyllys 		return (KMF_ERR_MEMORY);
443599ebb4caSwyllys 	}
443699ebb4caSwyllys 
443799ebb4caSwyllys 	/* create the 1st DES key */
443899ebb4caSwyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
443999ebb4caSwyllys 		goto out;
444099ebb4caSwyllys 	}
444199ebb4caSwyllys 
444299ebb4caSwyllys 	/*
444399ebb4caSwyllys 	 * Create the 2nd DES key and make sure its value is different
444499ebb4caSwyllys 	 * from the 1st DES key.
444599ebb4caSwyllys 	 */
444699ebb4caSwyllys 	retry = 0;
444799ebb4caSwyllys 	do {
444899ebb4caSwyllys 		if (deskey2 != NULL) {
444999ebb4caSwyllys 			free(deskey2);
445099ebb4caSwyllys 			deskey2 = NULL;
445199ebb4caSwyllys 		}
445299ebb4caSwyllys 
445399ebb4caSwyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
445499ebb4caSwyllys 			goto out;
445599ebb4caSwyllys 		}
445699ebb4caSwyllys 
445799ebb4caSwyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
445899ebb4caSwyllys 		    == 0) {
445999ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
446099ebb4caSwyllys 			retry++;
446199ebb4caSwyllys 		}
446299ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
446399ebb4caSwyllys 
446499ebb4caSwyllys 	if (ret != KMF_OK) {
446599ebb4caSwyllys 		goto out;
446699ebb4caSwyllys 	}
446799ebb4caSwyllys 
446899ebb4caSwyllys 	/*
446999ebb4caSwyllys 	 * Create the 3rd DES key and make sure its value is different
447099ebb4caSwyllys 	 * from the 2nd DES key.
447199ebb4caSwyllys 	 */
447299ebb4caSwyllys 	retry = 0;
447399ebb4caSwyllys 	do {
447499ebb4caSwyllys 		if (deskey3 != NULL) {
447599ebb4caSwyllys 			free(deskey3);
447699ebb4caSwyllys 			deskey3 = NULL;
447799ebb4caSwyllys 		}
447899ebb4caSwyllys 
447999ebb4caSwyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
448099ebb4caSwyllys 			goto out;
448199ebb4caSwyllys 		}
448299ebb4caSwyllys 
448399ebb4caSwyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
448499ebb4caSwyllys 		    == 0) {
448599ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
448699ebb4caSwyllys 			retry++;
448799ebb4caSwyllys 		}
448899ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
448999ebb4caSwyllys 
449099ebb4caSwyllys 	if (ret != KMF_OK) {
449199ebb4caSwyllys 		goto out;
449299ebb4caSwyllys 	}
449399ebb4caSwyllys 
449499ebb4caSwyllys 	/* Concatenate 3 DES keys into a DES3 key */
449599ebb4caSwyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
449699ebb4caSwyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
449799ebb4caSwyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
449899ebb4caSwyllys 	*des3key = newkey;
449999ebb4caSwyllys 
450099ebb4caSwyllys out:
450199ebb4caSwyllys 	if (deskey1 != NULL)
450299ebb4caSwyllys 		free(deskey1);
450399ebb4caSwyllys 
450499ebb4caSwyllys 	if (deskey2 != NULL)
450599ebb4caSwyllys 		free(deskey2);
450699ebb4caSwyllys 
450799ebb4caSwyllys 	if (deskey3 != NULL)
450899ebb4caSwyllys 		free(deskey3);
450999ebb4caSwyllys 
451099ebb4caSwyllys 	if (ret != KMF_OK && newkey != NULL)
451199ebb4caSwyllys 		free(newkey);
451299ebb4caSwyllys 
451399ebb4caSwyllys 	return (ret);
451499ebb4caSwyllys }
451599ebb4caSwyllys 
451699ebb4caSwyllys KMF_RETURN
451730a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
451830a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
451999ebb4caSwyllys {
452099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
452199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
452299ebb4caSwyllys 	char *fullpath = NULL;
452399ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
452499ebb4caSwyllys 	DES_cblock *deskey = NULL;
452599ebb4caSwyllys 	unsigned char *des3key = NULL;
452699ebb4caSwyllys 	unsigned char *random = NULL;
452799ebb4caSwyllys 	int fd = -1;
452830a5e8faSwyllys 	KMF_KEY_HANDLE *symkey;
452930a5e8faSwyllys 	KMF_KEY_ALG keytype;
453030a5e8faSwyllys 	uint32_t keylen;
453130a5e8faSwyllys 	uint32_t keylen_size = sizeof (keylen);
453230a5e8faSwyllys 	char *dirpath;
453330a5e8faSwyllys 	char *keyfile;
453499ebb4caSwyllys 
453599ebb4caSwyllys 	if (kmfh == NULL)
453699ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
453799ebb4caSwyllys 
453830a5e8faSwyllys 	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
453930a5e8faSwyllys 	if (symkey == NULL)
454099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
454199ebb4caSwyllys 
454230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
454330a5e8faSwyllys 
454430a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
454530a5e8faSwyllys 	if (keyfile == NULL)
454630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
454730a5e8faSwyllys 
454830a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
454930a5e8faSwyllys 	    (void *)&keytype, NULL);
455030a5e8faSwyllys 	if (ret != KMF_OK)
455130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
455230a5e8faSwyllys 
455330a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
455430a5e8faSwyllys 	    &keylen, &keylen_size);
455530a5e8faSwyllys 	if (ret == KMF_ERR_ATTR_NOT_FOUND &&
455630a5e8faSwyllys 	    (keytype == KMF_DES || keytype == KMF_DES3))
455730a5e8faSwyllys 		/* keylength is not required for DES and 3DES */
455830a5e8faSwyllys 		ret = KMF_OK;
455930a5e8faSwyllys 	if (ret != KMF_OK)
456030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
456130a5e8faSwyllys 
456230a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
456399ebb4caSwyllys 	if (fullpath == NULL)
456499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
456599ebb4caSwyllys 
456699ebb4caSwyllys 	/* If the requested file exists, return an error */
456730a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
456899ebb4caSwyllys 		free(fullpath);
456999ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
457099ebb4caSwyllys 	}
457199ebb4caSwyllys 
457299ebb4caSwyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
457399ebb4caSwyllys 	if (fd == -1) {
457499ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
457599ebb4caSwyllys 		goto out;
457699ebb4caSwyllys 	}
457799ebb4caSwyllys 
457899ebb4caSwyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
457999ebb4caSwyllys 	if (rkey == NULL) {
458099ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
458199ebb4caSwyllys 		goto out;
458299ebb4caSwyllys 	}
458399ebb4caSwyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
458499ebb4caSwyllys 
458530a5e8faSwyllys 	if (keytype == KMF_DES) {
458699ebb4caSwyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
458799ebb4caSwyllys 			goto out;
458899ebb4caSwyllys 		}
458999ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)deskey;
459099ebb4caSwyllys 		rkey->keydata.len = 8;
459199ebb4caSwyllys 
459299ebb4caSwyllys 		symkey->keyalg = KMF_DES;
459399ebb4caSwyllys 
459430a5e8faSwyllys 	} else if (keytype == KMF_DES3) {
459599ebb4caSwyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
459699ebb4caSwyllys 			goto out;
459799ebb4caSwyllys 		}
459899ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)des3key;
459999ebb4caSwyllys 		rkey->keydata.len = DES3_KEY_SIZE;
460099ebb4caSwyllys 		symkey->keyalg = KMF_DES3;
46019b37d296Swyllys 
460230a5e8faSwyllys 	} else if (keytype == KMF_AES || keytype == KMF_RC4 ||
460330a5e8faSwyllys 	    keytype == KMF_GENERIC_SECRET) {
460499ebb4caSwyllys 		int bytes;
460599ebb4caSwyllys 
460630a5e8faSwyllys 		if (keylen % 8 != 0) {
460799ebb4caSwyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
460899ebb4caSwyllys 			goto out;
460999ebb4caSwyllys 		}
461099ebb4caSwyllys 
461130a5e8faSwyllys 		if (keytype == KMF_AES) {
461230a5e8faSwyllys 			if (keylen != 128 &&
461330a5e8faSwyllys 			    keylen != 192 &&
461430a5e8faSwyllys 			    keylen != 256) {
461599ebb4caSwyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
461699ebb4caSwyllys 				goto out;
461799ebb4caSwyllys 			}
461899ebb4caSwyllys 		}
461999ebb4caSwyllys 
462030a5e8faSwyllys 		bytes = keylen/8;
462199ebb4caSwyllys 		random = malloc(bytes);
462299ebb4caSwyllys 		if (random == NULL) {
462399ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
462499ebb4caSwyllys 			goto out;
462599ebb4caSwyllys 		}
462699ebb4caSwyllys 		if (RAND_bytes(random, bytes) != 1) {
462799ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
462899ebb4caSwyllys 			goto out;
462999ebb4caSwyllys 		}
463099ebb4caSwyllys 
463199ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)random;
463299ebb4caSwyllys 		rkey->keydata.len = bytes;
463330a5e8faSwyllys 		symkey->keyalg = keytype;
463499ebb4caSwyllys 
463599ebb4caSwyllys 	} else {
463699ebb4caSwyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
463799ebb4caSwyllys 		goto out;
463899ebb4caSwyllys 	}
463999ebb4caSwyllys 
464099ebb4caSwyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
464199ebb4caSwyllys 
464299ebb4caSwyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
464399ebb4caSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
464499ebb4caSwyllys 	symkey->keylabel = (char *)fullpath;
464599ebb4caSwyllys 	symkey->israw = TRUE;
464699ebb4caSwyllys 	symkey->keyp = rkey;
464799ebb4caSwyllys 
464899ebb4caSwyllys out:
464999ebb4caSwyllys 	if (fd != -1)
465099ebb4caSwyllys 		(void) close(fd);
465199ebb4caSwyllys 
465299ebb4caSwyllys 	if (ret != KMF_OK && fullpath != NULL) {
465399ebb4caSwyllys 		free(fullpath);
465499ebb4caSwyllys 	}
465599ebb4caSwyllys 	if (ret != KMF_OK) {
465630a5e8faSwyllys 		kmf_free_raw_sym_key(rkey);
465799ebb4caSwyllys 		symkey->keyp = NULL;
465899ebb4caSwyllys 		symkey->keyalg = KMF_KEYALG_NONE;
465999ebb4caSwyllys 	}
466099ebb4caSwyllys 
466199ebb4caSwyllys 	return (ret);
466299ebb4caSwyllys }
466399ebb4caSwyllys 
466499ebb4caSwyllys /*
466599ebb4caSwyllys  * Check a file to see if it is a CRL file with PEM or DER format.
466699ebb4caSwyllys  * If success, return its format in the "pformat" argument.
466799ebb4caSwyllys  */
466899ebb4caSwyllys KMF_RETURN
466999ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
467099ebb4caSwyllys {
467199ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
467299ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
467399ebb4caSwyllys 	BIO		*bio = NULL;
467499ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
467599ebb4caSwyllys 
467699ebb4caSwyllys 	if (filename == NULL) {
467799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
467899ebb4caSwyllys 	}
467999ebb4caSwyllys 
468099ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
468199ebb4caSwyllys 	if (bio == NULL)	{
468299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
468399ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
468499ebb4caSwyllys 		goto out;
468599ebb4caSwyllys 	}
468699ebb4caSwyllys 
468799ebb4caSwyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
468899ebb4caSwyllys 		*pformat = KMF_FORMAT_PEM;
468999ebb4caSwyllys 		goto out;
469099ebb4caSwyllys 	}
469199ebb4caSwyllys 	(void) BIO_free(bio);
469299ebb4caSwyllys 
469399ebb4caSwyllys 	/*
469499ebb4caSwyllys 	 * Now try to read it as raw DER data.
469599ebb4caSwyllys 	 */
469699ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
469799ebb4caSwyllys 	if (bio == NULL)	{
469899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
469999ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
470099ebb4caSwyllys 		goto out;
470199ebb4caSwyllys 	}
470299ebb4caSwyllys 
470399ebb4caSwyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
470499ebb4caSwyllys 		*pformat = KMF_FORMAT_ASN1;
470599ebb4caSwyllys 	} else {
470699ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
470799ebb4caSwyllys 	}
470899ebb4caSwyllys 
470999ebb4caSwyllys out:
471099ebb4caSwyllys 	if (bio != NULL)
471199ebb4caSwyllys 		(void) BIO_free(bio);
471299ebb4caSwyllys 
471399ebb4caSwyllys 	if (xcrl != NULL)
471499ebb4caSwyllys 		X509_CRL_free(xcrl);
471599ebb4caSwyllys 
471699ebb4caSwyllys 	return (ret);
471799ebb4caSwyllys }
471899ebb4caSwyllys 
471999ebb4caSwyllys /*
472099ebb4caSwyllys  * Check a file to see if it is a certficate file with PEM or DER format.
472199ebb4caSwyllys  * If success, return its format in the pformat argument.
472299ebb4caSwyllys  */
472399ebb4caSwyllys KMF_RETURN
472499ebb4caSwyllys OpenSSL_IsCertFile(KMF_HANDLE_T handle, char *filename,
472599ebb4caSwyllys 	KMF_ENCODE_FORMAT *pformat)
472699ebb4caSwyllys {
472799ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
472899ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
472999ebb4caSwyllys 	BIO		*bio = NULL;
473099ebb4caSwyllys 	X509		*xcert = NULL;
473199ebb4caSwyllys 
473299ebb4caSwyllys 	if (filename == NULL) {
473399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
473499ebb4caSwyllys 	}
473599ebb4caSwyllys 
473630a5e8faSwyllys 	ret = kmf_get_file_format(filename, pformat);
473799ebb4caSwyllys 	if (ret != KMF_OK)
473899ebb4caSwyllys 		return (ret);
473999ebb4caSwyllys 
474099ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
474199ebb4caSwyllys 	if (bio == NULL)	{
474299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
474399ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
474499ebb4caSwyllys 		goto out;
474599ebb4caSwyllys 	}
474699ebb4caSwyllys 
474799ebb4caSwyllys 	if ((*pformat) == KMF_FORMAT_PEM) {
474899ebb4caSwyllys 		if ((xcert = PEM_read_bio_X509(bio, NULL,
474999ebb4caSwyllys 		    NULL, NULL)) == NULL) {
475099ebb4caSwyllys 			ret = KMF_ERR_BAD_CERTFILE;
475199ebb4caSwyllys 		}
475299ebb4caSwyllys 	} else if ((*pformat) == KMF_FORMAT_ASN1) {
475399ebb4caSwyllys 		if ((xcert = d2i_X509_bio(bio, NULL)) == NULL) {
475499ebb4caSwyllys 			ret = KMF_ERR_BAD_CERTFILE;
475599ebb4caSwyllys 		}
475699ebb4caSwyllys 	} else {
475799ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
475899ebb4caSwyllys 	}
475999ebb4caSwyllys 
476099ebb4caSwyllys out:
476199ebb4caSwyllys 	if (bio != NULL)
476299ebb4caSwyllys 		(void) BIO_free(bio);
476399ebb4caSwyllys 
476499ebb4caSwyllys 	if (xcert != NULL)
476599ebb4caSwyllys 		X509_free(xcert);
476699ebb4caSwyllys 
476799ebb4caSwyllys 	return (ret);
476899ebb4caSwyllys }
476999ebb4caSwyllys 
477099ebb4caSwyllys KMF_RETURN
477199ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
477299ebb4caSwyllys     KMF_RAW_SYM_KEY *rkey)
477399ebb4caSwyllys {
477499ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
477599ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
477699ebb4caSwyllys 	KMF_DATA	keyvalue;
477799ebb4caSwyllys 
477899ebb4caSwyllys 	if (kmfh == NULL)
477999ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
478099ebb4caSwyllys 
478199ebb4caSwyllys 	if (symkey == NULL || rkey == NULL)
478299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
478399ebb4caSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
478499ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
478599ebb4caSwyllys 
478699ebb4caSwyllys 	if (symkey->israw) {
478799ebb4caSwyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
478899ebb4caSwyllys 
478999ebb4caSwyllys 		if (rawkey == NULL ||
479099ebb4caSwyllys 		    rawkey->keydata.val == NULL ||
479199ebb4caSwyllys 		    rawkey->keydata.len == 0)
479299ebb4caSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
479399ebb4caSwyllys 
479499ebb4caSwyllys 		rkey->keydata.len = rawkey->keydata.len;
479599ebb4caSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
479699ebb4caSwyllys 			return (KMF_ERR_MEMORY);
479799ebb4caSwyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
479899ebb4caSwyllys 		    rkey->keydata.len);
479999ebb4caSwyllys 	} else {
480030a5e8faSwyllys 		rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
480199ebb4caSwyllys 		if (rv != KMF_OK)
480299ebb4caSwyllys 			return (rv);
480399ebb4caSwyllys 		rkey->keydata.len = keyvalue.Length;
480499ebb4caSwyllys 		rkey->keydata.val = keyvalue.Data;
480599ebb4caSwyllys 	}
480699ebb4caSwyllys 
480799ebb4caSwyllys 	return (rv);
480899ebb4caSwyllys }
480902744e81Swyllys 
481002744e81Swyllys /*
481102744e81Swyllys  * id-sha1    OBJECT IDENTIFIER ::= {
481202744e81Swyllys  *     iso(1) identified-organization(3) oiw(14) secsig(3)
481302744e81Swyllys  *     algorithms(2) 26
481402744e81Swyllys  * }
481502744e81Swyllys  */
481602744e81Swyllys #define	ASN1_SHA1_OID_PREFIX_LEN 15
481702744e81Swyllys static uchar_t SHA1_DER_PREFIX[ASN1_SHA1_OID_PREFIX_LEN] = {
481802744e81Swyllys 	0x30, 0x21, 0x30, 0x09,
481902744e81Swyllys 	0x06, 0x05, 0x2b, 0x0e,
482002744e81Swyllys 	0x03, 0x02, 0x1a, 0x05,
482102744e81Swyllys 	0x00, 0x04, 0x14
482202744e81Swyllys };
482302744e81Swyllys 
482402744e81Swyllys /*
482502744e81Swyllys  * id-md2 OBJECT IDENTIFIER ::= {
482602744e81Swyllys  *     iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2
482702744e81Swyllys  * }
482802744e81Swyllys  */
482902744e81Swyllys #define	ASN1_MD2_OID_PREFIX_LEN 18
483002744e81Swyllys static uchar_t MD2_DER_PREFIX[ASN1_MD2_OID_PREFIX_LEN] = {
483102744e81Swyllys 	0x30, 0x20, 0x30, 0x0c,
483202744e81Swyllys 	0x06, 0x08, 0x2a, 0x86,
483302744e81Swyllys 	0x48, 0x86, 0xf7, 0x0d,
483402744e81Swyllys 	0x02, 0x02, 0x05, 0x00,
483502744e81Swyllys 	0x04, 0x10
483602744e81Swyllys };
483702744e81Swyllys 
483802744e81Swyllys /*
483902744e81Swyllys  * id-md5 OBJECT IDENTIFIER ::= {
484002744e81Swyllys  *     iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5
484102744e81Swyllys  * }
484202744e81Swyllys  */
484302744e81Swyllys #define	ASN1_MD5_OID_PREFIX_LEN 18
484402744e81Swyllys static uchar_t MD5_DER_PREFIX[ASN1_MD5_OID_PREFIX_LEN] = {
484502744e81Swyllys 	0x30, 0x20, 0x30, 0x0c,
484602744e81Swyllys 	0x06, 0x08, 0x2a, 0x86,
484702744e81Swyllys 	0x48, 0x86, 0xf7, 0x0d,
484802744e81Swyllys 	0x02, 0x05, 0x05, 0x00,
484902744e81Swyllys 	0x04, 0x10
485002744e81Swyllys };
485102744e81Swyllys 
485202744e81Swyllys KMF_RETURN
485302744e81Swyllys OpenSSL_VerifyDataWithCert(KMF_HANDLE_T handle,
485402744e81Swyllys 	KMF_ALGORITHM_INDEX algid, KMF_DATA *indata,
485502744e81Swyllys 	KMF_DATA *insig, KMF_DATA *cert)
485602744e81Swyllys {
485702744e81Swyllys 	KMF_RETURN ret = KMF_OK;
485802744e81Swyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
485902744e81Swyllys 	X509	*xcert = NULL;
486002744e81Swyllys 	EVP_PKEY *pkey = NULL;
486102744e81Swyllys 	uchar_t *p;
486202744e81Swyllys 	uchar_t *rsaout = NULL;
486302744e81Swyllys 	uchar_t *pfx = NULL;
486402744e81Swyllys 	const EVP_MD *md;
486502744e81Swyllys 	int pfxlen = 0, len;
486602744e81Swyllys 
486702744e81Swyllys 	if (handle == NULL || indata == NULL ||
486802744e81Swyllys 	    indata->Data == NULL || indata->Length == 0 ||
486902744e81Swyllys 	    insig == NULL|| insig->Data == NULL || insig->Length == 0 ||
487002744e81Swyllys 	    cert == NULL || cert->Data == NULL || cert->Length == 0)
487102744e81Swyllys 		return (KMF_ERR_BAD_PARAMETER);
487202744e81Swyllys 
487302744e81Swyllys 	p = cert->Data;
487402744e81Swyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, cert->Length);
487502744e81Swyllys 	if (xcert == NULL) {
487602744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
487702744e81Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
487802744e81Swyllys 		goto cleanup;
487902744e81Swyllys 	}
488002744e81Swyllys 
488102744e81Swyllys 	pkey = X509_get_pubkey(xcert);
488230a5e8faSwyllys 	if (pkey == NULL) {
488302744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
488402744e81Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
488502744e81Swyllys 		goto cleanup;
488602744e81Swyllys 	}
488702744e81Swyllys 
488802744e81Swyllys 	if (algid != KMF_ALGID_NONE) {
488902744e81Swyllys 		switch (algid) {
489002744e81Swyllys 			case KMF_ALGID_MD5WithRSA:
489102744e81Swyllys 				md = EVP_md5();
489202744e81Swyllys 				break;
489302744e81Swyllys 			case KMF_ALGID_MD2WithRSA:
489402744e81Swyllys 				md = EVP_md2();
489502744e81Swyllys 				break;
489602744e81Swyllys 			case KMF_ALGID_SHA1WithRSA:
489702744e81Swyllys 				md = EVP_sha1();
489802744e81Swyllys 				break;
489902744e81Swyllys 			case KMF_ALGID_RSA:
490002744e81Swyllys 				md = NULL;
490102744e81Swyllys 				break;
490202744e81Swyllys 			default:
490302744e81Swyllys 				ret = KMF_ERR_BAD_PARAMETER;
490402744e81Swyllys 				goto cleanup;
490502744e81Swyllys 		}
490602744e81Swyllys 	} else {
490702744e81Swyllys 		/* Get the hash type from the cert signature */
490802744e81Swyllys 		md = EVP_get_digestbyobj(xcert->sig_alg->algorithm);
490902744e81Swyllys 		if (md == NULL) {
491002744e81Swyllys 			SET_ERROR(kmfh, ERR_get_error());
491102744e81Swyllys 			ret = KMF_ERR_BAD_PARAMETER;
491202744e81Swyllys 			goto cleanup;
491302744e81Swyllys 		}
491402744e81Swyllys 	}
49159b37d296Swyllys 	if (md != NULL) {
491602744e81Swyllys 		switch (EVP_MD_type(md)) {
491702744e81Swyllys 		case NID_md2:
491802744e81Swyllys 		case NID_md2WithRSAEncryption:
491902744e81Swyllys 			pfxlen = ASN1_MD2_OID_PREFIX_LEN;
492002744e81Swyllys 			pfx = MD2_DER_PREFIX;
492102744e81Swyllys 			break;
492202744e81Swyllys 		case NID_md5:
492302744e81Swyllys 		case NID_md5WithRSAEncryption:
492402744e81Swyllys 			pfxlen = ASN1_MD5_OID_PREFIX_LEN;
492502744e81Swyllys 			pfx = MD5_DER_PREFIX;
492602744e81Swyllys 			break;
492702744e81Swyllys 		case NID_sha1:
492802744e81Swyllys 		case NID_sha1WithRSAEncryption:
492902744e81Swyllys 			pfxlen = ASN1_SHA1_OID_PREFIX_LEN;
493002744e81Swyllys 			pfx = SHA1_DER_PREFIX;
493102744e81Swyllys 			break;
493202744e81Swyllys 		default: /* Unsupported */
493302744e81Swyllys 			pfxlen = 0;
493402744e81Swyllys 			pfx = NULL;
493502744e81Swyllys 			break;
493602744e81Swyllys 		}
49379b37d296Swyllys 	}
493802744e81Swyllys 
493902744e81Swyllys 	/* RSA with no hash is a special case */
494002744e81Swyllys 	rsaout = malloc(RSA_size(pkey->pkey.rsa));
494102744e81Swyllys 	if (rsaout == NULL)
494202744e81Swyllys 		return (KMF_ERR_MEMORY);
494302744e81Swyllys 
494402744e81Swyllys 	/* Decrypt the input signature */
494502744e81Swyllys 	len = RSA_public_decrypt(insig->Length,
494602744e81Swyllys 	    insig->Data, rsaout, pkey->pkey.rsa, RSA_PKCS1_PADDING);
494702744e81Swyllys 	if (len < 1) {
494802744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
494902744e81Swyllys 		ret = KMF_ERR_BAD_PARAMETER;
495002744e81Swyllys 	} else {
495102744e81Swyllys 		size_t hashlen = 0;
495202744e81Swyllys 		uint32_t dlen;
495302744e81Swyllys 		char *digest = NULL;
495402744e81Swyllys 
495502744e81Swyllys 		/*
495602744e81Swyllys 		 * If the AlgId requires it, hash the input data before
495702744e81Swyllys 		 * comparing it to the decrypted signature.
495802744e81Swyllys 		 */
495902744e81Swyllys 		if (md) {
496002744e81Swyllys 			EVP_MD_CTX ctx;
496102744e81Swyllys 
496202744e81Swyllys 			hashlen = md->md_size;
496302744e81Swyllys 
496402744e81Swyllys 			digest = malloc(hashlen + pfxlen);
496502744e81Swyllys 			if (digest == NULL)
496602744e81Swyllys 				return (KMF_ERR_MEMORY);
496702744e81Swyllys 			/* Add the prefix to the comparison buffer. */
496802744e81Swyllys 			if (pfx && pfxlen > 0) {
496902744e81Swyllys 				(void) memcpy(digest, pfx, pfxlen);
497002744e81Swyllys 			}
497102744e81Swyllys 			(void) EVP_DigestInit(&ctx, md);
497202744e81Swyllys 			(void) EVP_DigestUpdate(&ctx, indata->Data,
497302744e81Swyllys 			    indata->Length);
497402744e81Swyllys 
497502744e81Swyllys 			/* Add the digest AFTER the ASN1 prefix */
497602744e81Swyllys 			(void) EVP_DigestFinal(&ctx,
497702744e81Swyllys 			    (uchar_t *)digest + pfxlen, &dlen);
497802744e81Swyllys 
497902744e81Swyllys 			dlen += pfxlen;
498002744e81Swyllys 		} else {
498102744e81Swyllys 			digest = (char *)indata->Data;
498202744e81Swyllys 			dlen = indata->Length;
498302744e81Swyllys 		}
498402744e81Swyllys 
498502744e81Swyllys 		/*
498602744e81Swyllys 		 * The result of the RSA decryption should be ASN1(OID | Hash).
498702744e81Swyllys 		 * Compare the output hash to the input data for the final
498802744e81Swyllys 		 * result.
498902744e81Swyllys 		 */
499002744e81Swyllys 		if (memcmp(rsaout, digest, dlen))
499102744e81Swyllys 			ret = KMF_ERR_INTERNAL;
499202744e81Swyllys 		else
499302744e81Swyllys 			ret = KMF_OK;
499402744e81Swyllys 
499502744e81Swyllys 		/* If we had to allocate space for the digest, free it now */
499602744e81Swyllys 		if (hashlen)
499702744e81Swyllys 			free(digest);
499802744e81Swyllys 	}
499902744e81Swyllys cleanup:
500002744e81Swyllys 	if (pkey)
500102744e81Swyllys 		EVP_PKEY_free(pkey);
500202744e81Swyllys 
500302744e81Swyllys 	if (xcert)
500402744e81Swyllys 		X509_free(xcert);
500502744e81Swyllys 
500602744e81Swyllys 	if (rsaout)
500702744e81Swyllys 		free(rsaout);
500802744e81Swyllys 
500902744e81Swyllys 	return (ret);
501002744e81Swyllys }
501130a5e8faSwyllys 
501230a5e8faSwyllys /*
501330a5e8faSwyllys  * substitute for the unsafe access(2) function.
501430a5e8faSwyllys  * If the file in question already exists, return 1.
501530a5e8faSwyllys  * else 0.  If an error occurs during testing (other
501630a5e8faSwyllys  * than EEXIST), return -1.
501730a5e8faSwyllys  */
501830a5e8faSwyllys static int
501930a5e8faSwyllys test_for_file(char *filename, mode_t mode)
502030a5e8faSwyllys {
502130a5e8faSwyllys 	int fd;
502230a5e8faSwyllys 
502330a5e8faSwyllys 	/*
502430a5e8faSwyllys 	 * Try to create the file with the EXCL flag.
502530a5e8faSwyllys 	 * The call should fail if the file exists.
502630a5e8faSwyllys 	 */
502730a5e8faSwyllys 	fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
502830a5e8faSwyllys 	if (fd == -1 && errno == EEXIST)
502930a5e8faSwyllys 		return (1);
503030a5e8faSwyllys 	else if (fd == -1) /* some other error */
503130a5e8faSwyllys 		return (-1);
503230a5e8faSwyllys 
503330a5e8faSwyllys 	/* The file did NOT exist.  Delete the testcase. */
503430a5e8faSwyllys 	(void) close(fd);
503530a5e8faSwyllys 	(void) unlink(filename);
503630a5e8faSwyllys 	return (0);
503730a5e8faSwyllys }
503830a5e8faSwyllys 
503930a5e8faSwyllys KMF_RETURN
504030a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
504130a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
504230a5e8faSwyllys {
504330a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
504430a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
504530a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
504630a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
504730a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
504830a5e8faSwyllys 	KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
504930a5e8faSwyllys 	KMF_CREDENTIAL cred = {NULL, 0};
505030a5e8faSwyllys 	BIO *out = NULL;
505130a5e8faSwyllys 	int keys = 0;
505230a5e8faSwyllys 	char *fullpath = NULL;
505330a5e8faSwyllys 	char *keyfile = NULL;
505430a5e8faSwyllys 	char *dirpath = NULL;
505530a5e8faSwyllys 
505630a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
505730a5e8faSwyllys 	if (pubkey != NULL)
505830a5e8faSwyllys 		keys++;
505930a5e8faSwyllys 
506030a5e8faSwyllys 	prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
506130a5e8faSwyllys 	if (prikey != NULL)
506230a5e8faSwyllys 		keys++;
506330a5e8faSwyllys 
506430a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
506530a5e8faSwyllys 	if (rawkey != NULL)
506630a5e8faSwyllys 		keys++;
506730a5e8faSwyllys 
506830a5e8faSwyllys 	/*
506930a5e8faSwyllys 	 * Exactly 1 type of key must be passed to this function.
507030a5e8faSwyllys 	 */
507130a5e8faSwyllys 	if (keys != 1)
507230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
507330a5e8faSwyllys 
507430a5e8faSwyllys 	keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
507530a5e8faSwyllys 	    numattr);
507630a5e8faSwyllys 	if (keyfile == NULL)
507730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
507830a5e8faSwyllys 
507930a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
508030a5e8faSwyllys 
508130a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
508230a5e8faSwyllys 
508330a5e8faSwyllys 	/* Once we have the full path, we don't need the pieces */
508430a5e8faSwyllys 	if (fullpath == NULL)
508530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
508630a5e8faSwyllys 
508730a5e8faSwyllys 	/* If the requested file exists, return an error */
508830a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
508930a5e8faSwyllys 		free(fullpath);
509030a5e8faSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
509130a5e8faSwyllys 	}
509230a5e8faSwyllys 
509330a5e8faSwyllys 	rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
509430a5e8faSwyllys 	    &format, NULL);
509530a5e8faSwyllys 	if (rv != KMF_OK)
509630a5e8faSwyllys 		/* format is optional. */
509730a5e8faSwyllys 		rv = KMF_OK;
509830a5e8faSwyllys 
509930a5e8faSwyllys 	/* CRED is not required for OpenSSL files */
510030a5e8faSwyllys 	(void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
510130a5e8faSwyllys 	    &cred, NULL);
510230a5e8faSwyllys 
510330a5e8faSwyllys 	/* Store the private key to the keyfile */
510430a5e8faSwyllys 	out = BIO_new_file(fullpath, "wb");
510530a5e8faSwyllys 	if (out == NULL) {
510630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
510730a5e8faSwyllys 		rv = KMF_ERR_OPEN_FILE;
510830a5e8faSwyllys 		goto end;
510930a5e8faSwyllys 	}
511030a5e8faSwyllys 
511130a5e8faSwyllys 	if (prikey != NULL && prikey->keyp != NULL) {
511230a5e8faSwyllys 		if (prikey->keyalg == KMF_RSA ||
511330a5e8faSwyllys 		    prikey->keyalg == KMF_DSA) {
511430a5e8faSwyllys 			pkey = (EVP_PKEY *)prikey->keyp;
511530a5e8faSwyllys 
511630a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
511730a5e8faSwyllys 			    out, &cred, pkey, TRUE);
511830a5e8faSwyllys 
511930a5e8faSwyllys 			if (rv == KMF_OK && prikey->keylabel == NULL) {
512030a5e8faSwyllys 				prikey->keylabel = strdup(fullpath);
512130a5e8faSwyllys 				if (prikey->keylabel == NULL)
512230a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
512330a5e8faSwyllys 			}
512430a5e8faSwyllys 		}
512530a5e8faSwyllys 	} else if (pubkey != NULL && pubkey->keyp != NULL) {
512630a5e8faSwyllys 		if (pubkey->keyalg == KMF_RSA ||
512730a5e8faSwyllys 		    pubkey->keyalg == KMF_DSA) {
512830a5e8faSwyllys 			pkey = (EVP_PKEY *)pubkey->keyp;
512930a5e8faSwyllys 
513030a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
513130a5e8faSwyllys 			    out, &cred, pkey, FALSE);
513230a5e8faSwyllys 
513330a5e8faSwyllys 			if (rv == KMF_OK && pubkey->keylabel == NULL) {
513430a5e8faSwyllys 				pubkey->keylabel = strdup(fullpath);
513530a5e8faSwyllys 				if (pubkey->keylabel == NULL)
513630a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
513730a5e8faSwyllys 			}
513830a5e8faSwyllys 		}
513930a5e8faSwyllys 	} else if (rawkey != NULL) {
514030a5e8faSwyllys 		if (rawkey->keytype == KMF_RSA) {
514130a5e8faSwyllys 			pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
514230a5e8faSwyllys 		} else if (rawkey->keytype == KMF_DSA) {
514330a5e8faSwyllys 			pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
514430a5e8faSwyllys 		} else {
514530a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
514630a5e8faSwyllys 		}
51475b3e1433Swyllys 		if (pkey != NULL) {
5148*73cc0e02Swyllys 			KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
5149*73cc0e02Swyllys 
5150*73cc0e02Swyllys 			rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
5151*73cc0e02Swyllys 			    (void *)&kclass, NULL);
5152*73cc0e02Swyllys 			if (rv != KMF_OK)
5153*73cc0e02Swyllys 				rv = KMF_OK;
51545b3e1433Swyllys 			rv = ssl_write_key(kmfh, format, out,
5155*73cc0e02Swyllys 			    &cred, pkey, (kclass == KMF_ASYM_PRI));
51565b3e1433Swyllys 			EVP_PKEY_free(pkey);
51575b3e1433Swyllys 		}
515830a5e8faSwyllys 	}
515930a5e8faSwyllys 
516030a5e8faSwyllys end:
516130a5e8faSwyllys 
516230a5e8faSwyllys 	if (out)
516330a5e8faSwyllys 		(void) BIO_free(out);
516430a5e8faSwyllys 
51655b3e1433Swyllys 
516630a5e8faSwyllys 	if (rv == KMF_OK)
516730a5e8faSwyllys 		(void) chmod(fullpath, 0400);
516830a5e8faSwyllys 
516930a5e8faSwyllys 	free(fullpath);
517030a5e8faSwyllys 	return (rv);
517130a5e8faSwyllys }
517230a5e8faSwyllys 
517330a5e8faSwyllys KMF_RETURN
517430a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
517530a5e8faSwyllys {
517630a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
517730a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
517830a5e8faSwyllys 	X509_CRL *xcrl = NULL;
517930a5e8faSwyllys 	X509 *xcert = NULL;
518030a5e8faSwyllys 	EVP_PKEY *pkey;
518130a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
518230a5e8faSwyllys 	BIO *in = NULL, *out = NULL;
518330a5e8faSwyllys 	int openssl_ret = 0;
518430a5e8faSwyllys 	KMF_ENCODE_FORMAT outformat;
518530a5e8faSwyllys 	boolean_t crlcheck = FALSE;
518630a5e8faSwyllys 	char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
518730a5e8faSwyllys 
518830a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
518930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
519030a5e8faSwyllys 	}
519130a5e8faSwyllys 
519230a5e8faSwyllys 	/* CRL check is optional */
519330a5e8faSwyllys 	(void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
519430a5e8faSwyllys 	    &crlcheck, NULL);
519530a5e8faSwyllys 
519630a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
519730a5e8faSwyllys 	if (crlcheck == B_TRUE && certfile == NULL) {
519830a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
519930a5e8faSwyllys 	}
520030a5e8faSwyllys 
520130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
520230a5e8faSwyllys 	incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
520330a5e8faSwyllys 	outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
520430a5e8faSwyllys 
520530a5e8faSwyllys 	crlfile = get_fullpath(dirpath, incrl);
520630a5e8faSwyllys 
520730a5e8faSwyllys 	if (crlfile == NULL)
520830a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
520930a5e8faSwyllys 
521030a5e8faSwyllys 	outcrlfile = get_fullpath(dirpath, outcrl);
521130a5e8faSwyllys 	if (outcrlfile == NULL)
521230a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
521330a5e8faSwyllys 
521430a5e8faSwyllys 	if (isdir(outcrlfile)) {
521530a5e8faSwyllys 		free(outcrlfile);
521630a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
521730a5e8faSwyllys 	}
521830a5e8faSwyllys 
521930a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
522030a5e8faSwyllys 	if (ret != KMF_OK) {
522130a5e8faSwyllys 		free(outcrlfile);
522230a5e8faSwyllys 		return (ret);
522330a5e8faSwyllys 	}
522430a5e8faSwyllys 
522530a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
522630a5e8faSwyllys 	if (in == NULL)	{
522730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
522830a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
522930a5e8faSwyllys 		goto end;
523030a5e8faSwyllys 	}
523130a5e8faSwyllys 
523230a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
523330a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
523430a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
523530a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
523630a5e8faSwyllys 	}
523730a5e8faSwyllys 
523830a5e8faSwyllys 	if (xcrl == NULL) {
523930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
524030a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
524130a5e8faSwyllys 		goto end;
524230a5e8faSwyllys 	}
524330a5e8faSwyllys 
524430a5e8faSwyllys 	/* If bypasscheck is specified, no need to verify. */
524530a5e8faSwyllys 	if (crlcheck == B_FALSE)
524630a5e8faSwyllys 		goto output;
524730a5e8faSwyllys 
524830a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
524930a5e8faSwyllys 	if (ret != KMF_OK)
525030a5e8faSwyllys 		goto end;
525130a5e8faSwyllys 
525230a5e8faSwyllys 	/* Read in the CA cert file and convert to X509 */
525330a5e8faSwyllys 	if (BIO_read_filename(in, certfile) <= 0) {
525430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
525530a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
525630a5e8faSwyllys 		goto end;
525730a5e8faSwyllys 	}
525830a5e8faSwyllys 
525930a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
526030a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
526130a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
526230a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
526330a5e8faSwyllys 	} else {
526430a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
526530a5e8faSwyllys 		goto end;
526630a5e8faSwyllys 	}
526730a5e8faSwyllys 
526830a5e8faSwyllys 	if (xcert == NULL) {
526930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
527030a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
527130a5e8faSwyllys 		goto end;
527230a5e8faSwyllys 	}
527330a5e8faSwyllys 	/* Now get the public key from the CA cert */
527430a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
527530a5e8faSwyllys 	if (pkey == NULL) {
527630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
527730a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
527830a5e8faSwyllys 		goto end;
527930a5e8faSwyllys 	}
528030a5e8faSwyllys 
528130a5e8faSwyllys 	/* Verify the CRL with the CA's public key */
528230a5e8faSwyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
528330a5e8faSwyllys 	EVP_PKEY_free(pkey);
528430a5e8faSwyllys 	if (openssl_ret > 0) {
528530a5e8faSwyllys 		ret = KMF_OK;  /* verify succeed */
528630a5e8faSwyllys 	} else {
528730a5e8faSwyllys 		SET_ERROR(kmfh, openssl_ret);
528830a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
528930a5e8faSwyllys 	}
529030a5e8faSwyllys 
529130a5e8faSwyllys output:
529230a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
529330a5e8faSwyllys 	    &outformat, NULL);
529430a5e8faSwyllys 	if (ret != KMF_OK) {
529530a5e8faSwyllys 		ret = KMF_OK;
529630a5e8faSwyllys 		outformat = KMF_FORMAT_PEM;
529730a5e8faSwyllys 	}
529830a5e8faSwyllys 
529930a5e8faSwyllys 	out = BIO_new_file(outcrlfile, "wb");
530030a5e8faSwyllys 	if (out == NULL) {
530130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
530230a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
530330a5e8faSwyllys 		goto end;
530430a5e8faSwyllys 	}
530530a5e8faSwyllys 
530630a5e8faSwyllys 	if (outformat == KMF_FORMAT_ASN1) {
530730a5e8faSwyllys 		openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
530830a5e8faSwyllys 	} else if (outformat == KMF_FORMAT_PEM) {
530930a5e8faSwyllys 		openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
531030a5e8faSwyllys 	} else {
531130a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
531230a5e8faSwyllys 		goto end;
531330a5e8faSwyllys 	}
531430a5e8faSwyllys 
531530a5e8faSwyllys 	if (openssl_ret <= 0) {
531630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
531730a5e8faSwyllys 		ret = KMF_ERR_WRITE_FILE;
531830a5e8faSwyllys 	} else {
531930a5e8faSwyllys 		ret = KMF_OK;
532030a5e8faSwyllys 	}
532130a5e8faSwyllys 
532230a5e8faSwyllys end:
532330a5e8faSwyllys 	if (xcrl != NULL)
532430a5e8faSwyllys 		X509_CRL_free(xcrl);
532530a5e8faSwyllys 
532630a5e8faSwyllys 	if (xcert != NULL)
532730a5e8faSwyllys 		X509_free(xcert);
532830a5e8faSwyllys 
532930a5e8faSwyllys 	if (in != NULL)
533030a5e8faSwyllys 		(void) BIO_free(in);
533130a5e8faSwyllys 
533230a5e8faSwyllys 	if (out != NULL)
533330a5e8faSwyllys 		(void) BIO_free(out);
533430a5e8faSwyllys 
533530a5e8faSwyllys 	if (outcrlfile != NULL)
533630a5e8faSwyllys 		free(outcrlfile);
533730a5e8faSwyllys 
533830a5e8faSwyllys 	return (ret);
533930a5e8faSwyllys }
534030a5e8faSwyllys 
534130a5e8faSwyllys KMF_RETURN
534230a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
534330a5e8faSwyllys {
534430a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
534530a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
534630a5e8faSwyllys 	X509_CRL   *x = NULL;
534730a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
534830a5e8faSwyllys 	char *crlfile = NULL;
534930a5e8faSwyllys 	BIO *in = NULL;
535030a5e8faSwyllys 	BIO *mem = NULL;
535130a5e8faSwyllys 	long len;
535230a5e8faSwyllys 	char *memptr;
535330a5e8faSwyllys 	char *data = NULL;
535430a5e8faSwyllys 	char **crldata;
535530a5e8faSwyllys 	char *crlfilename, *dirpath;
535630a5e8faSwyllys 
535730a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
535830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
535930a5e8faSwyllys 	}
536030a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
536130a5e8faSwyllys 	    attrlist, numattr);
536230a5e8faSwyllys 	if (crlfilename == NULL)
536330a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
536430a5e8faSwyllys 
536530a5e8faSwyllys 	crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
536630a5e8faSwyllys 	    attrlist, numattr);
536730a5e8faSwyllys 
536830a5e8faSwyllys 	if (crldata == NULL)
536930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
537030a5e8faSwyllys 
537130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
537230a5e8faSwyllys 
537330a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
537430a5e8faSwyllys 
537530a5e8faSwyllys 	if (crlfile == NULL)
537630a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
537730a5e8faSwyllys 
537830a5e8faSwyllys 	if (isdir(crlfile)) {
537930a5e8faSwyllys 		free(crlfile);
538030a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
538130a5e8faSwyllys 	}
538230a5e8faSwyllys 
538330a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
538430a5e8faSwyllys 	if (ret != KMF_OK) {
538530a5e8faSwyllys 		free(crlfile);
538630a5e8faSwyllys 		return (ret);
538730a5e8faSwyllys 	}
538830a5e8faSwyllys 
538930a5e8faSwyllys 	if (bio_err == NULL)
539030a5e8faSwyllys 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
539130a5e8faSwyllys 
539230a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
539330a5e8faSwyllys 	if (in == NULL)	{
539430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
539530a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
539630a5e8faSwyllys 		goto end;
539730a5e8faSwyllys 	}
539830a5e8faSwyllys 
539930a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
540030a5e8faSwyllys 		x = d2i_X509_CRL_bio(in, NULL);
540130a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
540230a5e8faSwyllys 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
540330a5e8faSwyllys 	}
540430a5e8faSwyllys 
540530a5e8faSwyllys 	if (x == NULL) { /* should not happen */
540630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
540730a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
540830a5e8faSwyllys 		goto end;
540930a5e8faSwyllys 	}
541030a5e8faSwyllys 
541130a5e8faSwyllys 	mem = BIO_new(BIO_s_mem());
541230a5e8faSwyllys 	if (mem == NULL) {
541330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
541430a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
541530a5e8faSwyllys 		goto end;
541630a5e8faSwyllys 	}
541730a5e8faSwyllys 
541830a5e8faSwyllys 	(void) X509_CRL_print(mem, x);
541930a5e8faSwyllys 	len = BIO_get_mem_data(mem, &memptr);
542030a5e8faSwyllys 	if (len <= 0) {
542130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
542230a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
542330a5e8faSwyllys 		goto end;
542430a5e8faSwyllys 	}
542530a5e8faSwyllys 
542630a5e8faSwyllys 	data = malloc(len + 1);
542730a5e8faSwyllys 	if (data == NULL) {
542830a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
542930a5e8faSwyllys 		goto end;
543030a5e8faSwyllys 	}
543130a5e8faSwyllys 
543230a5e8faSwyllys 	(void) memcpy(data, memptr, len);
543330a5e8faSwyllys 	data[len] = '\0';
543430a5e8faSwyllys 	*crldata = data;
543530a5e8faSwyllys 
543630a5e8faSwyllys end:
543730a5e8faSwyllys 	if (x != NULL)
543830a5e8faSwyllys 		X509_CRL_free(x);
543930a5e8faSwyllys 
544030a5e8faSwyllys 	if (crlfile != NULL)
544130a5e8faSwyllys 		free(crlfile);
544230a5e8faSwyllys 
544330a5e8faSwyllys 	if (in != NULL)
544430a5e8faSwyllys 		(void) BIO_free(in);
544530a5e8faSwyllys 
544630a5e8faSwyllys 	if (mem != NULL)
544730a5e8faSwyllys 		(void) BIO_free(mem);
544830a5e8faSwyllys 
544930a5e8faSwyllys 	return (ret);
545030a5e8faSwyllys }
545130a5e8faSwyllys 
545230a5e8faSwyllys KMF_RETURN
545330a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
545430a5e8faSwyllys {
545530a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
545630a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
545730a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
545830a5e8faSwyllys 	char *crlfile = NULL;
545930a5e8faSwyllys 	BIO *in = NULL;
546030a5e8faSwyllys 	char *crlfilename, *dirpath;
546130a5e8faSwyllys 
546230a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
546330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
546430a5e8faSwyllys 	}
546530a5e8faSwyllys 
546630a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
546730a5e8faSwyllys 	    attrlist, numattr);
546830a5e8faSwyllys 
546930a5e8faSwyllys 	if (crlfilename == NULL)
547030a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
547130a5e8faSwyllys 
547230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
547330a5e8faSwyllys 
547430a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
547530a5e8faSwyllys 
547630a5e8faSwyllys 	if (crlfile == NULL)
547730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
547830a5e8faSwyllys 
547930a5e8faSwyllys 	if (isdir(crlfile)) {
548030a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
548130a5e8faSwyllys 		goto end;
548230a5e8faSwyllys 	}
548330a5e8faSwyllys 
548430a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
548530a5e8faSwyllys 	if (ret != KMF_OK)
548630a5e8faSwyllys 		goto end;
548730a5e8faSwyllys 
548830a5e8faSwyllys 	if (unlink(crlfile) != 0) {
548930a5e8faSwyllys 		SET_SYS_ERROR(kmfh, errno);
549030a5e8faSwyllys 		ret = KMF_ERR_INTERNAL;
549130a5e8faSwyllys 		goto end;
549230a5e8faSwyllys 	}
549330a5e8faSwyllys 
549430a5e8faSwyllys end:
549530a5e8faSwyllys 	if (in != NULL)
549630a5e8faSwyllys 		(void) BIO_free(in);
549730a5e8faSwyllys 	if (crlfile != NULL)
549830a5e8faSwyllys 		free(crlfile);
549930a5e8faSwyllys 
550030a5e8faSwyllys 	return (ret);
550130a5e8faSwyllys }
550230a5e8faSwyllys 
550330a5e8faSwyllys KMF_RETURN
550430a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
550530a5e8faSwyllys {
550630a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
550730a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
550830a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
550930a5e8faSwyllys 	BIO *in = NULL;
551030a5e8faSwyllys 	X509   *xcert = NULL;
551130a5e8faSwyllys 	X509_CRL   *xcrl = NULL;
551230a5e8faSwyllys 	STACK_OF(X509_REVOKED) *revoke_stack = NULL;
551330a5e8faSwyllys 	X509_REVOKED *revoke;
551430a5e8faSwyllys 	int i;
551530a5e8faSwyllys 	char *crlfilename, *crlfile, *dirpath, *certfile;
551630a5e8faSwyllys 
551730a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
551830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
551930a5e8faSwyllys 	}
552030a5e8faSwyllys 
552130a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
552230a5e8faSwyllys 	    attrlist, numattr);
552330a5e8faSwyllys 
552430a5e8faSwyllys 	if (crlfilename == NULL)
552530a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
552630a5e8faSwyllys 
552730a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
552830a5e8faSwyllys 	if (certfile == NULL)
552930a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
553030a5e8faSwyllys 
553130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
553230a5e8faSwyllys 
553330a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
553430a5e8faSwyllys 
553530a5e8faSwyllys 	if (crlfile == NULL)
553630a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
553730a5e8faSwyllys 
553830a5e8faSwyllys 	if (isdir(crlfile)) {
553930a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
554030a5e8faSwyllys 		goto end;
554130a5e8faSwyllys 	}
554230a5e8faSwyllys 
554330a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
554430a5e8faSwyllys 	if (ret != KMF_OK)
554530a5e8faSwyllys 		goto end;
554630a5e8faSwyllys 
554730a5e8faSwyllys 	/* Read the CRL file and load it into a X509_CRL structure */
554830a5e8faSwyllys 	in = BIO_new_file(crlfilename, "rb");
554930a5e8faSwyllys 	if (in == NULL)	{
555030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
555130a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
555230a5e8faSwyllys 		goto end;
555330a5e8faSwyllys 	}
555430a5e8faSwyllys 
555530a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
555630a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
555730a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
555830a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
555930a5e8faSwyllys 	}
556030a5e8faSwyllys 
556130a5e8faSwyllys 	if (xcrl == NULL) {
556230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
556330a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
556430a5e8faSwyllys 		goto end;
556530a5e8faSwyllys 	}
556630a5e8faSwyllys 	(void) BIO_free(in);
556730a5e8faSwyllys 
556830a5e8faSwyllys 	/* Read the Certificate file and load it into a X509 structure */
556930a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
557030a5e8faSwyllys 	if (ret != KMF_OK)
557130a5e8faSwyllys 		goto end;
557230a5e8faSwyllys 
557330a5e8faSwyllys 	in = BIO_new_file(certfile, "rb");
557430a5e8faSwyllys 	if (in == NULL)	{
557530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
557630a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
557730a5e8faSwyllys 		goto end;
557830a5e8faSwyllys 	}
557930a5e8faSwyllys 
558030a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
558130a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
558230a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
558330a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
558430a5e8faSwyllys 	}
558530a5e8faSwyllys 
558630a5e8faSwyllys 	if (xcert == NULL) {
558730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
558830a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
558930a5e8faSwyllys 		goto end;
559030a5e8faSwyllys 	}
559130a5e8faSwyllys 
559230a5e8faSwyllys 	/* Check if the certificate and the CRL have same issuer */
559330a5e8faSwyllys 	if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) {
559430a5e8faSwyllys 		ret = KMF_ERR_ISSUER;
559530a5e8faSwyllys 		goto end;
559630a5e8faSwyllys 	}
559730a5e8faSwyllys 
559830a5e8faSwyllys 	/* Check to see if the certificate serial number is revoked */
559930a5e8faSwyllys 	revoke_stack = X509_CRL_get_REVOKED(xcrl);
560030a5e8faSwyllys 	if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
560130a5e8faSwyllys 		/* No revoked certificates in the CRL file */
560230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
560330a5e8faSwyllys 		ret = KMF_ERR_EMPTY_CRL;
560430a5e8faSwyllys 		goto end;
560530a5e8faSwyllys 	}
560630a5e8faSwyllys 
560730a5e8faSwyllys 	for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
560830a5e8faSwyllys 		/*LINTED*/
560930a5e8faSwyllys 		revoke = sk_X509_REVOKED_value(revoke_stack, i);
561030a5e8faSwyllys 		if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber,
561130a5e8faSwyllys 		    revoke->serialNumber) == 0) {
561230a5e8faSwyllys 			break;
561330a5e8faSwyllys 		}
561430a5e8faSwyllys 	}
561530a5e8faSwyllys 
561630a5e8faSwyllys 	if (i < sk_X509_REVOKED_num(revoke_stack)) {
561730a5e8faSwyllys 		ret = KMF_OK;
561830a5e8faSwyllys 	} else {
561930a5e8faSwyllys 		ret = KMF_ERR_NOT_REVOKED;
562030a5e8faSwyllys 	}
562130a5e8faSwyllys 
562230a5e8faSwyllys end:
562330a5e8faSwyllys 	if (in != NULL)
562430a5e8faSwyllys 		(void) BIO_free(in);
562530a5e8faSwyllys 	if (xcrl != NULL)
562630a5e8faSwyllys 		X509_CRL_free(xcrl);
562730a5e8faSwyllys 	if (xcert != NULL)
562830a5e8faSwyllys 		X509_free(xcert);
562930a5e8faSwyllys 
563030a5e8faSwyllys 	return (ret);
563130a5e8faSwyllys }
563230a5e8faSwyllys 
563330a5e8faSwyllys KMF_RETURN
563430a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
563530a5e8faSwyllys {
563630a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
563730a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
563830a5e8faSwyllys 	BIO		*bcrl = NULL;
563930a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
564030a5e8faSwyllys 	X509		*xcert = NULL;
564130a5e8faSwyllys 	EVP_PKEY	*pkey;
564230a5e8faSwyllys 	int		sslret;
564330a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
564430a5e8faSwyllys 	unsigned char	*p;
564530a5e8faSwyllys 	long		len;
564630a5e8faSwyllys 
564730a5e8faSwyllys 	if (handle == NULL || crlname == NULL || tacert == NULL) {
564830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
564930a5e8faSwyllys 	}
565030a5e8faSwyllys 
565130a5e8faSwyllys 	ret = kmf_get_file_format(crlname, &crl_format);
565230a5e8faSwyllys 	if (ret != KMF_OK)
565330a5e8faSwyllys 		return (ret);
565430a5e8faSwyllys 
565530a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
565630a5e8faSwyllys 	if (bcrl == NULL)	{
565730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
565830a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
565930a5e8faSwyllys 		goto cleanup;
566030a5e8faSwyllys 	}
566130a5e8faSwyllys 
566230a5e8faSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
566330a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
566430a5e8faSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
566530a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
566630a5e8faSwyllys 	} else {
566730a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
566830a5e8faSwyllys 		goto cleanup;
566930a5e8faSwyllys 	}
567030a5e8faSwyllys 
567130a5e8faSwyllys 	if (xcrl == NULL) {
567230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
567330a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
567430a5e8faSwyllys 		goto cleanup;
567530a5e8faSwyllys 	}
567630a5e8faSwyllys 
567730a5e8faSwyllys 	p = tacert->Data;
567830a5e8faSwyllys 	len = tacert->Length;
567930a5e8faSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
568030a5e8faSwyllys 
568130a5e8faSwyllys 	if (xcert == NULL) {
568230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
568330a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
568430a5e8faSwyllys 		goto cleanup;
568530a5e8faSwyllys 	}
568630a5e8faSwyllys 
568730a5e8faSwyllys 	/* Get issuer certificate public key */
568830a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
568930a5e8faSwyllys 	if (pkey == NULL) {
569030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
569130a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
569230a5e8faSwyllys 		goto cleanup;
569330a5e8faSwyllys 	}
569430a5e8faSwyllys 
569530a5e8faSwyllys 	/* Verify CRL signature */
569630a5e8faSwyllys 	sslret = X509_CRL_verify(xcrl, pkey);
569730a5e8faSwyllys 	EVP_PKEY_free(pkey);
569830a5e8faSwyllys 	if (sslret > 0) {
569930a5e8faSwyllys 		ret = KMF_OK;
570030a5e8faSwyllys 	} else {
570130a5e8faSwyllys 		SET_ERROR(kmfh, sslret);
570230a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
570330a5e8faSwyllys 	}
570430a5e8faSwyllys 
570530a5e8faSwyllys cleanup:
570630a5e8faSwyllys 	if (bcrl != NULL)
570730a5e8faSwyllys 		(void) BIO_free(bcrl);
570830a5e8faSwyllys 
570930a5e8faSwyllys 	if (xcrl != NULL)
571030a5e8faSwyllys 		X509_CRL_free(xcrl);
571130a5e8faSwyllys 
571230a5e8faSwyllys 	if (xcert != NULL)
571330a5e8faSwyllys 		X509_free(xcert);
571430a5e8faSwyllys 
571530a5e8faSwyllys 	return (ret);
571630a5e8faSwyllys 
571730a5e8faSwyllys }
571830a5e8faSwyllys 
571930a5e8faSwyllys KMF_RETURN
572030a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
572130a5e8faSwyllys {
572230a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
572330a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
572430a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
572530a5e8faSwyllys 	BIO		*bcrl = NULL;
572630a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
572730a5e8faSwyllys 	int		i;
572830a5e8faSwyllys 
572930a5e8faSwyllys 	if (handle == NULL || crlname == NULL) {
573030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
573130a5e8faSwyllys 	}
573230a5e8faSwyllys 
573330a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlname, &crl_format);
573430a5e8faSwyllys 	if (ret != KMF_OK)
573530a5e8faSwyllys 		return (ret);
573630a5e8faSwyllys 
573730a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
573830a5e8faSwyllys 	if (bcrl == NULL) {
573930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
574030a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
574130a5e8faSwyllys 		goto cleanup;
574230a5e8faSwyllys 	}
574330a5e8faSwyllys 
57445b3e1433Swyllys 	if (crl_format == KMF_FORMAT_ASN1)
574530a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
57465b3e1433Swyllys 	else if (crl_format == KMF_FORMAT_PEM)
574730a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
574830a5e8faSwyllys 
574930a5e8faSwyllys 	if (xcrl == NULL) {
575030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
575130a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
575230a5e8faSwyllys 		goto cleanup;
575330a5e8faSwyllys 	}
575430a5e8faSwyllys 	i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL);
575530a5e8faSwyllys 	if (i >= 0) {
575630a5e8faSwyllys 		ret = KMF_ERR_VALIDITY_PERIOD;
575730a5e8faSwyllys 		goto cleanup;
575830a5e8faSwyllys 	}
575930a5e8faSwyllys 	if (X509_CRL_get_nextUpdate(xcrl)) {
576030a5e8faSwyllys 		i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL);
576130a5e8faSwyllys 
576230a5e8faSwyllys 		if (i <= 0) {
576330a5e8faSwyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
576430a5e8faSwyllys 			goto cleanup;
576530a5e8faSwyllys 		}
576630a5e8faSwyllys 	}
576730a5e8faSwyllys 
576830a5e8faSwyllys 	ret = KMF_OK;
576930a5e8faSwyllys 
577030a5e8faSwyllys cleanup:
577130a5e8faSwyllys 	if (bcrl != NULL)
577230a5e8faSwyllys 		(void) BIO_free(bcrl);
577330a5e8faSwyllys 
577430a5e8faSwyllys 	if (xcrl != NULL)
577530a5e8faSwyllys 		X509_CRL_free(xcrl);
577630a5e8faSwyllys 
577730a5e8faSwyllys 	return (ret);
577830a5e8faSwyllys }
5779