199ebb4caSwyllys /*
2*2c9a247fSWyllys Ingersoll  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
3*2c9a247fSWyllys Ingersoll  *
499ebb4caSwyllys  * Use is subject to license terms.
599ebb4caSwyllys  */
69a767088Shaimay /*
79a767088Shaimay  * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
89a767088Shaimay  * project 2000.
99a767088Shaimay  */
109a767088Shaimay /*
119a767088Shaimay  * ====================================================================
129a767088Shaimay  * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
139a767088Shaimay  *
149a767088Shaimay  * Redistribution and use in source and binary forms, with or without
159a767088Shaimay  * modification, are permitted provided that the following conditions
169a767088Shaimay  * are met:
179a767088Shaimay  *
189a767088Shaimay  * 1. Redistributions of source code must retain the above copyright
199a767088Shaimay  *    notice, this list of conditions and the following disclaimer.
209a767088Shaimay  *
219a767088Shaimay  * 2. Redistributions in binary form must reproduce the above copyright
229a767088Shaimay  *    notice, this list of conditions and the following disclaimer in
239a767088Shaimay  *    the documentation and/or other materials provided with the
249a767088Shaimay  *    distribution.
259a767088Shaimay  *
269a767088Shaimay  * 3. All advertising materials mentioning features or use of this
279a767088Shaimay  *    software must display the following acknowledgment:
289a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
299a767088Shaimay  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
309a767088Shaimay  *
319a767088Shaimay  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
329a767088Shaimay  *    endorse or promote products derived from this software without
339a767088Shaimay  *    prior written permission. For written permission, please contact
349a767088Shaimay  *    licensing@OpenSSL.org.
359a767088Shaimay  *
369a767088Shaimay  * 5. Products derived from this software may not be called "OpenSSL"
379a767088Shaimay  *    nor may "OpenSSL" appear in their names without prior written
389a767088Shaimay  *    permission of the OpenSSL Project.
399a767088Shaimay  *
409a767088Shaimay  * 6. Redistributions of any form whatsoever must retain the following
419a767088Shaimay  *    acknowledgment:
429a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
439a767088Shaimay  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
449a767088Shaimay  *
459a767088Shaimay  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
469a767088Shaimay  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
479a767088Shaimay  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
489a767088Shaimay  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
499a767088Shaimay  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
509a767088Shaimay  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
519a767088Shaimay  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
529a767088Shaimay  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
539a767088Shaimay  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
549a767088Shaimay  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
559a767088Shaimay  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
569a767088Shaimay  * OF THE POSSIBILITY OF SUCH DAMAGE.
579a767088Shaimay  * ====================================================================
589a767088Shaimay  *
599a767088Shaimay  * This product includes cryptographic software written by Eric Young
609a767088Shaimay  * (eay@cryptsoft.com).  This product includes software written by Tim
619a767088Shaimay  * Hudson (tjh@cryptsoft.com).
629a767088Shaimay  *
639a767088Shaimay  */
6499ebb4caSwyllys 
6571593db2Swyllys #include <stdlib.h>
6699ebb4caSwyllys #include <kmfapiP.h>
6799ebb4caSwyllys #include <ber_der.h>
6899ebb4caSwyllys #include <fcntl.h>
6999ebb4caSwyllys #include <sys/stat.h>
7099ebb4caSwyllys #include <dirent.h>
7199ebb4caSwyllys #include <cryptoutil.h>
7299ebb4caSwyllys #include <synch.h>
7399ebb4caSwyllys #include <thread.h>
7499ebb4caSwyllys 
7599ebb4caSwyllys /* OPENSSL related headers */
7699ebb4caSwyllys #include <openssl/bio.h>
7799ebb4caSwyllys #include <openssl/bn.h>
7899ebb4caSwyllys #include <openssl/asn1.h>
7999ebb4caSwyllys #include <openssl/err.h>
8099ebb4caSwyllys #include <openssl/bn.h>
8199ebb4caSwyllys #include <openssl/x509.h>
8299ebb4caSwyllys #include <openssl/rsa.h>
8399ebb4caSwyllys #include <openssl/dsa.h>
8499ebb4caSwyllys #include <openssl/x509v3.h>
8599ebb4caSwyllys #include <openssl/objects.h>
8699ebb4caSwyllys #include <openssl/pem.h>
8799ebb4caSwyllys #include <openssl/pkcs12.h>
8899ebb4caSwyllys #include <openssl/ocsp.h>
8999ebb4caSwyllys #include <openssl/des.h>
9099ebb4caSwyllys #include <openssl/rand.h>
9199ebb4caSwyllys 
9299ebb4caSwyllys #define	PRINT_ANY_EXTENSION (\
9399ebb4caSwyllys 	KMF_X509_EXT_KEY_USAGE |\
9499ebb4caSwyllys 	KMF_X509_EXT_CERT_POLICIES |\
9599ebb4caSwyllys 	KMF_X509_EXT_SUBJALTNAME |\
9699ebb4caSwyllys 	KMF_X509_EXT_BASIC_CONSTRAINTS |\
9799ebb4caSwyllys 	KMF_X509_EXT_NAME_CONSTRAINTS |\
9899ebb4caSwyllys 	KMF_X509_EXT_POLICY_CONSTRAINTS |\
9999ebb4caSwyllys 	KMF_X509_EXT_EXT_KEY_USAGE |\
10099ebb4caSwyllys 	KMF_X509_EXT_INHIBIT_ANY_POLICY |\
10199ebb4caSwyllys 	KMF_X509_EXT_AUTH_KEY_ID |\
10299ebb4caSwyllys 	KMF_X509_EXT_SUBJ_KEY_ID |\
10399ebb4caSwyllys 	KMF_X509_EXT_POLICY_MAPPING)
10499ebb4caSwyllys 
10599ebb4caSwyllys static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
10699ebb4caSwyllys 	0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
10799ebb4caSwyllys 	0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
10899ebb4caSwyllys 	0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
10999ebb4caSwyllys 	0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
11099ebb4caSwyllys 	0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
11199ebb4caSwyllys 	0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
11299ebb4caSwyllys 	0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
11399ebb4caSwyllys 	0x91 };
11499ebb4caSwyllys 
11599ebb4caSwyllys static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
11699ebb4caSwyllys 	0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
11799ebb4caSwyllys 	0x8e, 0xda, 0xce, 0x91, 0x5f };
11899ebb4caSwyllys 
11999ebb4caSwyllys static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
12099ebb4caSwyllys 	0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
12199ebb4caSwyllys 	0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
12299ebb4caSwyllys 	0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
12399ebb4caSwyllys 	0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
12499ebb4caSwyllys 	0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
12599ebb4caSwyllys 	0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
12699ebb4caSwyllys 	0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
12799ebb4caSwyllys 	0x02 };
12899ebb4caSwyllys 
12999ebb4caSwyllys #define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
13099ebb4caSwyllys 	h->lasterr.errcode = c;
13199ebb4caSwyllys 
13299ebb4caSwyllys #define	SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
13399ebb4caSwyllys 
1345b3e1433Swyllys /*
1355b3e1433Swyllys  * Declare some new macros for managing stacks of EVP_PKEYS, similar to
1365b3e1433Swyllys  * what wanboot did.
1375b3e1433Swyllys  */
1385b3e1433Swyllys DECLARE_STACK_OF(EVP_PKEY)
1395b3e1433Swyllys 
1405b3e1433Swyllys #define	sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
1415b3e1433Swyllys #define	sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
1425b3e1433Swyllys #define	sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
1435b3e1433Swyllys #define	sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
1445b3e1433Swyllys #define	sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
1455b3e1433Swyllys #define	sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
1465b3e1433Swyllys 	(free_func))
1475b3e1433Swyllys 
14899ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX;
14999ebb4caSwyllys static int ssl_initialized = 0;
15030a5e8faSwyllys static BIO *bio_err = NULL;
15130a5e8faSwyllys 
15230a5e8faSwyllys static int
15330a5e8faSwyllys test_for_file(char *, mode_t);
1545b3e1433Swyllys static KMF_RETURN
1555b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *, char *, int,
1565b3e1433Swyllys     STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
1575b3e1433Swyllys 
1585b3e1433Swyllys static KMF_RETURN
1595b3e1433Swyllys local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *,
1605b3e1433Swyllys     int, KMF_KEY_HANDLE *, char *);
1615b3e1433Swyllys 
1625b3e1433Swyllys static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int);
16399ebb4caSwyllys 
16471593db2Swyllys static KMF_RETURN
16530a5e8faSwyllys extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *,
16602744e81Swyllys     CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
16771593db2Swyllys 
16871593db2Swyllys static KMF_RETURN
16930a5e8faSwyllys kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
17030a5e8faSwyllys     char *, KMF_DATA *);
17130a5e8faSwyllys 
17230a5e8faSwyllys static KMF_RETURN
17330a5e8faSwyllys load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
17430a5e8faSwyllys     char *, KMF_DATA **, uint32_t *);
17571593db2Swyllys 
17602744e81Swyllys static KMF_RETURN
17702744e81Swyllys sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
17802744e81Swyllys 
17902744e81Swyllys static EVP_PKEY *
18002744e81Swyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *);
18102744e81Swyllys 
18230a5e8faSwyllys static KMF_RETURN
18330a5e8faSwyllys convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
18430a5e8faSwyllys 
18599ebb4caSwyllys KMF_RETURN
18630a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
18799ebb4caSwyllys 
18899ebb4caSwyllys void
18999ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
19099ebb4caSwyllys 
19199ebb4caSwyllys KMF_RETURN
19230a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
19399ebb4caSwyllys 
19499ebb4caSwyllys KMF_RETURN
19530a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
19699ebb4caSwyllys 
19799ebb4caSwyllys KMF_RETURN
19830a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
19930a5e8faSwyllys 
20030a5e8faSwyllys KMF_RETURN
20130a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20299ebb4caSwyllys 
20399ebb4caSwyllys KMF_RETURN
20499ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T,  KMF_KEY_HANDLE *, KMF_DATA *);
20599ebb4caSwyllys 
20699ebb4caSwyllys KMF_RETURN
20799ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
20899ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
20999ebb4caSwyllys 
21099ebb4caSwyllys KMF_RETURN
21130a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21299ebb4caSwyllys 
21399ebb4caSwyllys KMF_RETURN
21430a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21599ebb4caSwyllys 
21699ebb4caSwyllys KMF_RETURN
21730a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21899ebb4caSwyllys 
21999ebb4caSwyllys KMF_RETURN
22030a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22199ebb4caSwyllys 
22299ebb4caSwyllys KMF_RETURN
22330a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22499ebb4caSwyllys 
22599ebb4caSwyllys KMF_RETURN
22699ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
22799ebb4caSwyllys 	KMF_PRINTABLE_ITEM, char *);
22899ebb4caSwyllys 
22999ebb4caSwyllys KMF_RETURN
23099ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
23199ebb4caSwyllys 
23299ebb4caSwyllys KMF_RETURN
23330a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23499ebb4caSwyllys 
23599ebb4caSwyllys KMF_RETURN
23699ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
23799ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
23899ebb4caSwyllys 
23999ebb4caSwyllys KMF_RETURN
24030a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24199ebb4caSwyllys 
24299ebb4caSwyllys KMF_RETURN
24330a5e8faSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24499ebb4caSwyllys 
24599ebb4caSwyllys KMF_RETURN
24630a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24799ebb4caSwyllys 
24899ebb4caSwyllys KMF_RETURN
24930a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25099ebb4caSwyllys 
25199ebb4caSwyllys KMF_RETURN
25230a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25399ebb4caSwyllys 
25499ebb4caSwyllys KMF_RETURN
25599ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
25699ebb4caSwyllys 
25799ebb4caSwyllys KMF_RETURN
25830a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
25999ebb4caSwyllys 
26099ebb4caSwyllys KMF_RETURN
26130a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
26299ebb4caSwyllys 
26399ebb4caSwyllys static
26499ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table =
26599ebb4caSwyllys {
26699ebb4caSwyllys 	1,				/* Version */
26799ebb4caSwyllys 	NULL, /* ConfigureKeystore */
26899ebb4caSwyllys 	OpenSSL_FindCert,
26999ebb4caSwyllys 	OpenSSL_FreeKMFCert,
27099ebb4caSwyllys 	OpenSSL_StoreCert,
27199ebb4caSwyllys 	NULL, /* ImportCert */
27299ebb4caSwyllys 	OpenSSL_ImportCRL,
27399ebb4caSwyllys 	OpenSSL_DeleteCert,
27499ebb4caSwyllys 	OpenSSL_DeleteCRL,
27599ebb4caSwyllys 	OpenSSL_CreateKeypair,
27699ebb4caSwyllys 	OpenSSL_FindKey,
27799ebb4caSwyllys 	OpenSSL_EncodePubKeyData,
27899ebb4caSwyllys 	OpenSSL_SignData,
27999ebb4caSwyllys 	OpenSSL_DeleteKey,
28099ebb4caSwyllys 	OpenSSL_ListCRL,
28199ebb4caSwyllys 	NULL,	/* FindCRL */
28299ebb4caSwyllys 	OpenSSL_FindCertInCRL,
28399ebb4caSwyllys 	OpenSSL_GetErrorString,
28430a5e8faSwyllys 	OpenSSL_FindPrikeyByCert,
28599ebb4caSwyllys 	OpenSSL_DecryptData,
28630a5e8faSwyllys 	OpenSSL_ExportPK12,
28799ebb4caSwyllys 	OpenSSL_CreateSymKey,
28899ebb4caSwyllys 	OpenSSL_GetSymKeyValue,
28999ebb4caSwyllys 	NULL,	/* SetTokenPin */
29030a5e8faSwyllys 	OpenSSL_StoreKey,
29199ebb4caSwyllys 	NULL	/* Finalize */
29299ebb4caSwyllys };
29399ebb4caSwyllys 
29499ebb4caSwyllys static mutex_t *lock_cs;
29599ebb4caSwyllys static long *lock_count;
29699ebb4caSwyllys 
29799ebb4caSwyllys static void
298a2d4930dSDan OpenSolaris Anderson /* ARGSUSED1 */
29999ebb4caSwyllys locking_cb(int mode, int type, char *file, int line)
30099ebb4caSwyllys {
30199ebb4caSwyllys 	if (mode & CRYPTO_LOCK) {
30299ebb4caSwyllys 		(void) mutex_lock(&(lock_cs[type]));
30399ebb4caSwyllys 		lock_count[type]++;
30499ebb4caSwyllys 	} else {
30599ebb4caSwyllys 		(void) mutex_unlock(&(lock_cs[type]));
30699ebb4caSwyllys 	}
30799ebb4caSwyllys }
30899ebb4caSwyllys 
30999ebb4caSwyllys static unsigned long
31099ebb4caSwyllys thread_id()
31199ebb4caSwyllys {
31299ebb4caSwyllys 	return ((unsigned long)thr_self());
31399ebb4caSwyllys }
31499ebb4caSwyllys 
31599ebb4caSwyllys KMF_PLUGIN_FUNCLIST *
31699ebb4caSwyllys KMF_Plugin_Initialize()
31799ebb4caSwyllys {
31899ebb4caSwyllys 	int i;
31999ebb4caSwyllys 
32099ebb4caSwyllys 	(void) mutex_lock(&init_lock);
32199ebb4caSwyllys 	if (!ssl_initialized) {
32299ebb4caSwyllys 		/*
32399ebb4caSwyllys 		 * Add support for extension OIDs that are not yet in the
32499ebb4caSwyllys 		 * openssl default set.
32599ebb4caSwyllys 		 */
32699ebb4caSwyllys 		(void) OBJ_create("2.5.29.30", "nameConstraints",
32799ebb4caSwyllys 		    "X509v3 Name Constraints");
32899ebb4caSwyllys 		(void) OBJ_create("2.5.29.33", "policyMappings",
32999ebb4caSwyllys 		    "X509v3 Policy Mappings");
33099ebb4caSwyllys 		(void) OBJ_create("2.5.29.36", "policyConstraints",
33199ebb4caSwyllys 		    "X509v3 Policy Constraints");
33299ebb4caSwyllys 		(void) OBJ_create("2.5.29.46", "freshestCRL",
33399ebb4caSwyllys 		    "X509v3 Freshest CRL");
33499ebb4caSwyllys 		(void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
33599ebb4caSwyllys 		    "X509v3 Inhibit Any-Policy");
33699ebb4caSwyllys 		/*
33799ebb4caSwyllys 		 * Set up for thread-safe operation.
33899ebb4caSwyllys 		 */
33999ebb4caSwyllys 		lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
34099ebb4caSwyllys 		if (lock_cs == NULL) {
34199ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
34299ebb4caSwyllys 			return (NULL);
34399ebb4caSwyllys 		}
34499ebb4caSwyllys 
34599ebb4caSwyllys 		lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
34699ebb4caSwyllys 		if (lock_count == NULL) {
34799ebb4caSwyllys 			OPENSSL_free(lock_cs);
34899ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
34999ebb4caSwyllys 			return (NULL);
35099ebb4caSwyllys 		}
35199ebb4caSwyllys 
35299ebb4caSwyllys 		for (i = 0; i < CRYPTO_num_locks(); i++) {
35399ebb4caSwyllys 			lock_count[i] = 0;
35499ebb4caSwyllys 			(void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
35599ebb4caSwyllys 		}
35699ebb4caSwyllys 
35799ebb4caSwyllys 		CRYPTO_set_id_callback((unsigned long (*)())thread_id);
358*2c9a247fSWyllys Ingersoll 		if (CRYPTO_get_locking_callback() == NULL)
35999ebb4caSwyllys 			CRYPTO_set_locking_callback((void (*)())locking_cb);
360*2c9a247fSWyllys Ingersoll 
361*2c9a247fSWyllys Ingersoll 		OpenSSL_add_all_algorithms();
362*2c9a247fSWyllys Ingersoll 
363*2c9a247fSWyllys Ingersoll 		/* Enable error strings for reporting */
364*2c9a247fSWyllys Ingersoll 		ERR_load_crypto_strings();
365*2c9a247fSWyllys Ingersoll 
36699ebb4caSwyllys 		ssl_initialized = 1;
36799ebb4caSwyllys 	}
36899ebb4caSwyllys 	(void) mutex_unlock(&init_lock);
36999ebb4caSwyllys 
37099ebb4caSwyllys 	return (&openssl_plugin_table);
37199ebb4caSwyllys }
37299ebb4caSwyllys /*
37399ebb4caSwyllys  * Convert an SSL DN to a KMF DN.
37499ebb4caSwyllys  */
37599ebb4caSwyllys static KMF_RETURN
37699ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
37799ebb4caSwyllys {
37899ebb4caSwyllys 	KMF_DATA derdata;
37999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
38099ebb4caSwyllys 	uchar_t *tmp;
38199ebb4caSwyllys 
38299ebb4caSwyllys 	/* Convert to raw DER format */
38399ebb4caSwyllys 	derdata.Length = i2d_X509_NAME(sslDN, NULL);
38499ebb4caSwyllys 	if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
38599ebb4caSwyllys 	    == NULL) {
38699ebb4caSwyllys 		return (KMF_ERR_MEMORY);
38799ebb4caSwyllys 	}
38899ebb4caSwyllys 	(void) i2d_X509_NAME(sslDN, &tmp);
38999ebb4caSwyllys 
39099ebb4caSwyllys 	/* Decode to KMF format */
39199ebb4caSwyllys 	rv = DerDecodeName(&derdata, kmfDN);
39299ebb4caSwyllys 	if (rv != KMF_OK) {
39399ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
39499ebb4caSwyllys 	}
39599ebb4caSwyllys 	OPENSSL_free(derdata.Data);
39699ebb4caSwyllys 
39799ebb4caSwyllys 	return (rv);
39899ebb4caSwyllys }
39999ebb4caSwyllys 
40030a5e8faSwyllys int
40199ebb4caSwyllys isdir(char *path)
40299ebb4caSwyllys {
40399ebb4caSwyllys 	struct stat s;
40499ebb4caSwyllys 
40599ebb4caSwyllys 	if (stat(path, &s) == -1)
40699ebb4caSwyllys 		return (0);
40799ebb4caSwyllys 
40830a5e8faSwyllys 	return ((s.st_mode & S_IFMT) == S_IFDIR);
40999ebb4caSwyllys }
41099ebb4caSwyllys 
41199ebb4caSwyllys static KMF_RETURN
41299ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
41399ebb4caSwyllys {
41499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
41599ebb4caSwyllys 	unsigned char *buf = NULL, *p;
41699ebb4caSwyllys 	int len;
41799ebb4caSwyllys 
41899ebb4caSwyllys 	/*
41999ebb4caSwyllys 	 * Convert the X509 internal struct to DER encoded data
42099ebb4caSwyllys 	 */
42199ebb4caSwyllys 	if ((len = i2d_X509(x509cert, NULL)) < 0) {
42299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
42399ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
42499ebb4caSwyllys 		goto cleanup;
42599ebb4caSwyllys 	}
42699ebb4caSwyllys 	if ((buf = malloc(len)) == NULL) {
42799ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
42899ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
42999ebb4caSwyllys 		goto cleanup;
43099ebb4caSwyllys 	}
43199ebb4caSwyllys 
43299ebb4caSwyllys 	/*
43399ebb4caSwyllys 	 * i2d_X509 will increment the buf pointer so that we need to
43499ebb4caSwyllys 	 * save it.
43599ebb4caSwyllys 	 */
43699ebb4caSwyllys 	p = buf;
43799ebb4caSwyllys 	if ((len = i2d_X509(x509cert, &p)) < 0) {
43899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
43999ebb4caSwyllys 		free(buf);
44099ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
44199ebb4caSwyllys 		goto cleanup;
44299ebb4caSwyllys 	}
44399ebb4caSwyllys 
44499ebb4caSwyllys 	/* caller's responsibility to free it */
44599ebb4caSwyllys 	cert->Data = buf;
44699ebb4caSwyllys 	cert->Length = len;
44799ebb4caSwyllys 
44899ebb4caSwyllys cleanup:
44999ebb4caSwyllys 	if (rv != KMF_OK) {
45099ebb4caSwyllys 		if (buf)
45199ebb4caSwyllys 			free(buf);
45299ebb4caSwyllys 		cert->Data = NULL;
45399ebb4caSwyllys 		cert->Length = 0;
45499ebb4caSwyllys 	}
45599ebb4caSwyllys 
45699ebb4caSwyllys 	return (rv);
45799ebb4caSwyllys }
45899ebb4caSwyllys 
45930a5e8faSwyllys 
46099ebb4caSwyllys static KMF_RETURN
46130a5e8faSwyllys check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
46230a5e8faSwyllys     boolean_t *match)
46399ebb4caSwyllys {
46499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
46599ebb4caSwyllys 	boolean_t findIssuer = FALSE;
46699ebb4caSwyllys 	boolean_t findSubject = FALSE;
46799ebb4caSwyllys 	boolean_t findSerial = FALSE;
46899ebb4caSwyllys 	KMF_X509_NAME issuerDN, subjectDN;
46999ebb4caSwyllys 	KMF_X509_NAME certIssuerDN, certSubjectDN;
47099ebb4caSwyllys 
47199ebb4caSwyllys 	*match = FALSE;
47299ebb4caSwyllys 	if (xcert == NULL) {
47399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
47499ebb4caSwyllys 	}
47599ebb4caSwyllys 
47699ebb4caSwyllys 	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
47799ebb4caSwyllys 	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
47899ebb4caSwyllys 	(void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
47999ebb4caSwyllys 	(void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
48099ebb4caSwyllys 
48130a5e8faSwyllys 	if (issuer != NULL && strlen(issuer)) {
48230a5e8faSwyllys 		rv = kmf_dn_parser(issuer, &issuerDN);
48399ebb4caSwyllys 		if (rv != KMF_OK)
48499ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
48599ebb4caSwyllys 
48699ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->issuer, &certIssuerDN);
48799ebb4caSwyllys 		if (rv != KMF_OK) {
48830a5e8faSwyllys 			kmf_free_dn(&issuerDN);
48999ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
49099ebb4caSwyllys 		}
49199ebb4caSwyllys 
49299ebb4caSwyllys 		findIssuer = TRUE;
49399ebb4caSwyllys 	}
49430a5e8faSwyllys 	if (subject != NULL && strlen(subject)) {
49530a5e8faSwyllys 		rv = kmf_dn_parser(subject, &subjectDN);
49699ebb4caSwyllys 		if (rv != KMF_OK) {
49799ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
49899ebb4caSwyllys 			goto cleanup;
49999ebb4caSwyllys 		}
50099ebb4caSwyllys 
50199ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->subject, &certSubjectDN);
50299ebb4caSwyllys 		if (rv != KMF_OK) {
50399ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
50499ebb4caSwyllys 			goto cleanup;
50599ebb4caSwyllys 		}
50699ebb4caSwyllys 		findSubject = TRUE;
50799ebb4caSwyllys 	}
50830a5e8faSwyllys 	if (serial != NULL && serial->val != NULL)
50999ebb4caSwyllys 		findSerial = TRUE;
51099ebb4caSwyllys 
51199ebb4caSwyllys 	if (findSerial) {
51299ebb4caSwyllys 		BIGNUM *bn;
51399ebb4caSwyllys 
51499ebb4caSwyllys 		/* Comparing BIGNUMs is a pain! */
51599ebb4caSwyllys 		bn = ASN1_INTEGER_to_BN(xcert->cert_info->serialNumber, NULL);
51699ebb4caSwyllys 		if (bn != NULL) {
51799ebb4caSwyllys 			int bnlen = BN_num_bytes(bn);
51899ebb4caSwyllys 
51930a5e8faSwyllys 			if (bnlen == serial->len) {
52099ebb4caSwyllys 				uchar_t *a = malloc(bnlen);
52199ebb4caSwyllys 				if (a == NULL) {
52299ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
52399ebb4caSwyllys 					BN_free(bn);
52499ebb4caSwyllys 					goto cleanup;
52599ebb4caSwyllys 				}
52699ebb4caSwyllys 				bnlen = BN_bn2bin(bn, a);
52730a5e8faSwyllys 				*match = (memcmp(a, serial->val, serial->len) ==
52830a5e8faSwyllys 				    0);
52999ebb4caSwyllys 				rv = KMF_OK;
53099ebb4caSwyllys 				free(a);
53199ebb4caSwyllys 			}
53299ebb4caSwyllys 			BN_free(bn);
53399ebb4caSwyllys 			if (!(*match))
53499ebb4caSwyllys 				goto cleanup;
53599ebb4caSwyllys 		} else {
53699ebb4caSwyllys 			rv = KMF_OK;
53799ebb4caSwyllys 			goto cleanup;
53899ebb4caSwyllys 		}
53999ebb4caSwyllys 	}
54099ebb4caSwyllys 	if (findIssuer) {
54130a5e8faSwyllys 		*match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
54230a5e8faSwyllys 		if ((*match) == B_FALSE) {
54330a5e8faSwyllys 			/* stop checking and bail */
54499ebb4caSwyllys 			rv = KMF_OK;
54599ebb4caSwyllys 			goto cleanup;
54699ebb4caSwyllys 		}
54799ebb4caSwyllys 	}
54899ebb4caSwyllys 	if (findSubject) {
54930a5e8faSwyllys 		*match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
55030a5e8faSwyllys 		if ((*match) == B_FALSE) {
55130a5e8faSwyllys 			/* stop checking and bail */
55299ebb4caSwyllys 			rv = KMF_OK;
55399ebb4caSwyllys 			goto cleanup;
55499ebb4caSwyllys 		}
55599ebb4caSwyllys 	}
55699ebb4caSwyllys 
55799ebb4caSwyllys 	*match = TRUE;
55899ebb4caSwyllys cleanup:
55999ebb4caSwyllys 	if (findIssuer) {
56030a5e8faSwyllys 		kmf_free_dn(&issuerDN);
56130a5e8faSwyllys 		kmf_free_dn(&certIssuerDN);
56299ebb4caSwyllys 	}
56399ebb4caSwyllys 	if (findSubject) {
56430a5e8faSwyllys 		kmf_free_dn(&subjectDN);
56530a5e8faSwyllys 		kmf_free_dn(&certSubjectDN);
56699ebb4caSwyllys 	}
56799ebb4caSwyllys 
56899ebb4caSwyllys 	return (rv);
56999ebb4caSwyllys }
57099ebb4caSwyllys 
57130a5e8faSwyllys 
57230a5e8faSwyllys /*
57330a5e8faSwyllys  * This function loads a certificate file into an X509 data structure, and
57430a5e8faSwyllys  * checks if its issuer, subject or the serial number matches with those
57530a5e8faSwyllys  * values.  If it matches, then return the X509 data structure.
57630a5e8faSwyllys  */
57799ebb4caSwyllys static KMF_RETURN
57899ebb4caSwyllys load_X509cert(KMF_HANDLE *kmfh,
57930a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
58030a5e8faSwyllys     char *pathname, X509 **outcert)
58199ebb4caSwyllys {
58299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
58399ebb4caSwyllys 	X509 *xcert = NULL;
58499ebb4caSwyllys 	BIO *bcert = NULL;
58599ebb4caSwyllys 	boolean_t  match = FALSE;
58699ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
58799ebb4caSwyllys 
58899ebb4caSwyllys 	/*
58999ebb4caSwyllys 	 * auto-detect the file format, regardless of what
59099ebb4caSwyllys 	 * the 'format' parameters in the params say.
59199ebb4caSwyllys 	 */
59230a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
59399ebb4caSwyllys 	if (rv != KMF_OK) {
59499ebb4caSwyllys 		if (rv == KMF_ERR_OPEN_FILE)
59599ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
59699ebb4caSwyllys 		return (rv);
59799ebb4caSwyllys 	}
59899ebb4caSwyllys 
59999ebb4caSwyllys 	/* Not ASN1(DER) format */
60099ebb4caSwyllys 	if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
60199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
60299ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
60399ebb4caSwyllys 		goto cleanup;
60499ebb4caSwyllys 	}
60599ebb4caSwyllys 
60699ebb4caSwyllys 	if (format == KMF_FORMAT_PEM)
60799ebb4caSwyllys 		xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
60899ebb4caSwyllys 	else if (format == KMF_FORMAT_ASN1)
60999ebb4caSwyllys 		xcert = d2i_X509_bio(bcert, NULL);
61099ebb4caSwyllys 	else if (format == KMF_FORMAT_PKCS12) {
61199ebb4caSwyllys 		PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
61299ebb4caSwyllys 		if (p12 != NULL) {
61399ebb4caSwyllys 			(void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
61499ebb4caSwyllys 			PKCS12_free(p12);
61599ebb4caSwyllys 			p12 = NULL;
61699ebb4caSwyllys 		} else {
61799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
61899ebb4caSwyllys 			rv = KMF_ERR_BAD_CERT_FORMAT;
61999ebb4caSwyllys 		}
62099ebb4caSwyllys 	} else {
62199ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
62299ebb4caSwyllys 		goto cleanup;
62399ebb4caSwyllys 	}
62499ebb4caSwyllys 
62599ebb4caSwyllys 	if (xcert == NULL) {
62699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
62799ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
62899ebb4caSwyllys 		goto cleanup;
62999ebb4caSwyllys 	}
63099ebb4caSwyllys 
63130a5e8faSwyllys 	if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
63230a5e8faSwyllys 	    match == FALSE) {
63399ebb4caSwyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
63499ebb4caSwyllys 		goto cleanup;
63599ebb4caSwyllys 	}
63699ebb4caSwyllys 
63799ebb4caSwyllys 	if (outcert != NULL) {
63899ebb4caSwyllys 		*outcert = xcert;
63999ebb4caSwyllys 	}
64099ebb4caSwyllys 
64199ebb4caSwyllys cleanup:
64299ebb4caSwyllys 	if (bcert != NULL) (void) BIO_free(bcert);
64399ebb4caSwyllys 	if (rv != KMF_OK && xcert != NULL)
64499ebb4caSwyllys 		X509_free(xcert);
64599ebb4caSwyllys 
64699ebb4caSwyllys 	return (rv);
64799ebb4caSwyllys }
64899ebb4caSwyllys 
64971593db2Swyllys static int
65071593db2Swyllys datacmp(const void *a, const void *b)
65171593db2Swyllys {
65271593db2Swyllys 	KMF_DATA *adata = (KMF_DATA *)a;
65371593db2Swyllys 	KMF_DATA *bdata = (KMF_DATA *)b;
65471593db2Swyllys 	if (adata->Length > bdata->Length)
65571593db2Swyllys 		return (-1);
65671593db2Swyllys 	if (adata->Length < bdata->Length)
65771593db2Swyllys 		return (1);
65871593db2Swyllys 	return (0);
65971593db2Swyllys }
66071593db2Swyllys 
66171593db2Swyllys static KMF_RETURN
66230a5e8faSwyllys load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
66330a5e8faSwyllys     KMF_CERT_VALIDITY validity, char *pathname,
66471593db2Swyllys     KMF_DATA **certlist, uint32_t *numcerts)
66571593db2Swyllys {
66671593db2Swyllys 	KMF_RETURN rv = KMF_OK;
66771593db2Swyllys 	int i;
66871593db2Swyllys 	KMF_DATA *certs = NULL;
66971593db2Swyllys 	int nc = 0;
67071593db2Swyllys 	int hits = 0;
67171593db2Swyllys 	KMF_ENCODE_FORMAT format;
67271593db2Swyllys 
67330a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
67471593db2Swyllys 	if (rv != KMF_OK) {
67571593db2Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
67671593db2Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
67771593db2Swyllys 		return (rv);
67871593db2Swyllys 	}
67971593db2Swyllys 	if (format == KMF_FORMAT_ASN1) {
68071593db2Swyllys 		/* load a single certificate */
68171593db2Swyllys 		certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
68271593db2Swyllys 		if (certs == NULL)
68371593db2Swyllys 			return (KMF_ERR_MEMORY);
68471593db2Swyllys 		certs->Data = NULL;
68571593db2Swyllys 		certs->Length = 0;
68630a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
68730a5e8faSwyllys 		    pathname, certs);
68871593db2Swyllys 		if (rv == KMF_OK) {
68971593db2Swyllys 			*certlist = certs;
69071593db2Swyllys 			*numcerts = 1;
691a2d4930dSDan OpenSolaris Anderson 		} else {
692a2d4930dSDan OpenSolaris Anderson 			kmf_free_data(certs);
693a2d4930dSDan OpenSolaris Anderson 			free(certs);
694a2d4930dSDan OpenSolaris Anderson 			certs = NULL;
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) {
702e65e5c2dSWyllys Ingersoll 
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 	}
731a2d4930dSDan OpenSolaris Anderson 	if (rv == KMF_OK && hits > 0) {
73271593db2Swyllys 		/*
73371593db2Swyllys 		 * Sort the list of certs by length to put the cleared ones
73471593db2Swyllys 		 * at the end so they don't get accessed by the caller.
73571593db2Swyllys 		 */
73671593db2Swyllys 		qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
73771593db2Swyllys 		*certlist = certs;
73871593db2Swyllys 
73971593db2Swyllys 		/* since we sorted the list, just return the number of hits */
74071593db2Swyllys 		*numcerts = hits;
741a2d4930dSDan OpenSolaris Anderson 	} else {
742e65e5c2dSWyllys Ingersoll 		if (rv == KMF_OK && hits == 0)
743a2d4930dSDan OpenSolaris Anderson 			rv = KMF_ERR_CERT_NOT_FOUND;
744a2d4930dSDan OpenSolaris Anderson 		if (certs != NULL) {
745a2d4930dSDan OpenSolaris Anderson 			free(certs);
746a2d4930dSDan OpenSolaris Anderson 			certs = NULL;
747a2d4930dSDan OpenSolaris Anderson 		}
748a2d4930dSDan OpenSolaris Anderson 	}
74971593db2Swyllys 	return (rv);
75071593db2Swyllys }
75171593db2Swyllys 
75299ebb4caSwyllys static KMF_RETURN
75399ebb4caSwyllys kmf_load_cert(KMF_HANDLE *kmfh,
75430a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
75530a5e8faSwyllys     KMF_CERT_VALIDITY validity,
75699ebb4caSwyllys     char *pathname,
75799ebb4caSwyllys     KMF_DATA *cert)
75899ebb4caSwyllys {
75999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
76099ebb4caSwyllys 	X509 *x509cert = NULL;
76199ebb4caSwyllys 
76230a5e8faSwyllys 	rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
76399ebb4caSwyllys 	if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
76499ebb4caSwyllys 		rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
76599ebb4caSwyllys 		if (rv != KMF_OK) {
76699ebb4caSwyllys 			goto cleanup;
76799ebb4caSwyllys 		}
76830a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
76930a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
77030a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
77130a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
77299ebb4caSwyllys 			if (rv == KMF_OK)  {
77399ebb4caSwyllys 				/*
77499ebb4caSwyllys 				 * This is a valid cert so skip it.
77599ebb4caSwyllys 				 */
77699ebb4caSwyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
77799ebb4caSwyllys 			}
77899ebb4caSwyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD) {
77999ebb4caSwyllys 				/*
78099ebb4caSwyllys 				 * We want to return success when we
78199ebb4caSwyllys 				 * find an invalid cert.
78299ebb4caSwyllys 				 */
78399ebb4caSwyllys 				rv = KMF_OK;
78499ebb4caSwyllys 				goto cleanup;
78599ebb4caSwyllys 			}
78699ebb4caSwyllys 		}
78799ebb4caSwyllys 	}
78899ebb4caSwyllys cleanup:
78999ebb4caSwyllys 	if (x509cert != NULL)
79099ebb4caSwyllys 		X509_free(x509cert);
79199ebb4caSwyllys 
79299ebb4caSwyllys 	return (rv);
79399ebb4caSwyllys }
79499ebb4caSwyllys 
79502744e81Swyllys static KMF_RETURN
79602744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
79702744e81Swyllys {
79802744e81Swyllys 	KMF_RETURN ret = KMF_OK;
79902744e81Swyllys 	KMF_RAW_RSA_KEY rsa;
80002744e81Swyllys 	BerElement *asn1 = NULL;
80102744e81Swyllys 	BerValue filebuf;
80202744e81Swyllys 	BerValue OID = { NULL, 0 };
80302744e81Swyllys 	BerValue *Mod = NULL, *PubExp = NULL;
80402744e81Swyllys 	BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
80502744e81Swyllys 	BerValue *Coef = NULL;
80602744e81Swyllys 	BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
80702744e81Swyllys 	BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
80802744e81Swyllys 	BIGNUM *qminus1 = NULL;
80902744e81Swyllys 	BN_CTX *ctx = NULL;
81002744e81Swyllys 
81102744e81Swyllys 	*pkey = NULL;
81202744e81Swyllys 
81302744e81Swyllys 	filebuf.bv_val = (char *)filedata->Data;
81402744e81Swyllys 	filebuf.bv_len = filedata->Length;
81502744e81Swyllys 
81602744e81Swyllys 	asn1 = kmfder_init(&filebuf);
81702744e81Swyllys 	if (asn1 == NULL) {
81802744e81Swyllys 		ret = KMF_ERR_MEMORY;
81902744e81Swyllys 		goto out;
82002744e81Swyllys 	}
82102744e81Swyllys 
82202744e81Swyllys 	if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
82302744e81Swyllys 	    &OID, &Mod, &PubExp, &PriExp, &Prime1,
82402744e81Swyllys 	    &Prime2, &Coef) == -1)  {
82502744e81Swyllys 		ret = KMF_ERR_ENCODING;
82602744e81Swyllys 		goto out;
82702744e81Swyllys 	}
82802744e81Swyllys 
82902744e81Swyllys 	/*
83002744e81Swyllys 	 * We have to derive the 2 Exponents using Bignumber math.
83102744e81Swyllys 	 * Exp1 = PriExp mod (Prime1 - 1)
83202744e81Swyllys 	 * Exp2 = PriExp mod (Prime2 - 1)
83302744e81Swyllys 	 */
83402744e81Swyllys 
83502744e81Swyllys 	/* D = PrivateExponent */
83602744e81Swyllys 	D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
83702744e81Swyllys 	if (D == NULL) {
83802744e81Swyllys 		ret = KMF_ERR_MEMORY;
83902744e81Swyllys 		goto out;
84002744e81Swyllys 	}
84102744e81Swyllys 
84202744e81Swyllys 	/* P = Prime1 (first prime factor of Modulus) */
84302744e81Swyllys 	P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
84402744e81Swyllys 	if (D == NULL) {
84502744e81Swyllys 		ret = KMF_ERR_MEMORY;
84602744e81Swyllys 		goto out;
84702744e81Swyllys 	}
84802744e81Swyllys 
84902744e81Swyllys 	/* Q = Prime2 (second prime factor of Modulus) */
85002744e81Swyllys 	Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
85102744e81Swyllys 
85202744e81Swyllys 	if ((ctx = BN_CTX_new()) == NULL) {
85302744e81Swyllys 		ret = KMF_ERR_MEMORY;
85402744e81Swyllys 		goto out;
85502744e81Swyllys 	}
85602744e81Swyllys 
85702744e81Swyllys 	/* Compute (P - 1) */
85802744e81Swyllys 	pminus1 = BN_new();
85902744e81Swyllys 	(void) BN_sub(pminus1, P, BN_value_one());
86002744e81Swyllys 
86102744e81Swyllys 	/* Exponent1 = D mod (P - 1) */
86202744e81Swyllys 	Exp1 = BN_new();
86302744e81Swyllys 	(void) BN_mod(Exp1, D, pminus1, ctx);
86402744e81Swyllys 
86502744e81Swyllys 	/* Compute (Q - 1) */
86602744e81Swyllys 	qminus1 = BN_new();
86702744e81Swyllys 	(void) BN_sub(qminus1, Q, BN_value_one());
86802744e81Swyllys 
86902744e81Swyllys 	/* Exponent2 = D mod (Q - 1) */
87002744e81Swyllys 	Exp2 = BN_new();
87102744e81Swyllys 	(void) BN_mod(Exp2, D, qminus1, ctx);
87202744e81Swyllys 
87302744e81Swyllys 	/* Coef = (Inverse Q) mod P */
87402744e81Swyllys 	COEF = BN_new();
87502744e81Swyllys 	(void) BN_mod_inverse(COEF, Q, P, ctx);
87602744e81Swyllys 
87702744e81Swyllys 	/* Convert back to KMF format */
87802744e81Swyllys 	(void) memset(&rsa, 0, sizeof (rsa));
87902744e81Swyllys 
88002744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
88102744e81Swyllys 		goto out;
88202744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
88302744e81Swyllys 		goto out;
88402744e81Swyllys 	if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
88502744e81Swyllys 		goto out;
88602744e81Swyllys 
88702744e81Swyllys 	rsa.mod.val = (uchar_t *)Mod->bv_val;
88802744e81Swyllys 	rsa.mod.len = Mod->bv_len;
88902744e81Swyllys 
89002744e81Swyllys 	rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
89102744e81Swyllys 	rsa.pubexp.len = PubExp->bv_len;
89202744e81Swyllys 
89302744e81Swyllys 	rsa.priexp.val = (uchar_t *)PriExp->bv_val;
89402744e81Swyllys 	rsa.priexp.len = PriExp->bv_len;
89502744e81Swyllys 
89602744e81Swyllys 	rsa.prime1.val = (uchar_t *)Prime1->bv_val;
89702744e81Swyllys 	rsa.prime1.len = Prime1->bv_len;
89802744e81Swyllys 
89902744e81Swyllys 	rsa.prime2.val = (uchar_t *)Prime2->bv_val;
90002744e81Swyllys 	rsa.prime2.len = Prime2->bv_len;
90102744e81Swyllys 
90202744e81Swyllys 	*pkey = ImportRawRSAKey(&rsa);
90302744e81Swyllys out:
90402744e81Swyllys 	if (asn1 != NULL)
90502744e81Swyllys 		kmfber_free(asn1, 1);
90602744e81Swyllys 
90702744e81Swyllys 	if (OID.bv_val) {
90802744e81Swyllys 		free(OID.bv_val);
90902744e81Swyllys 	}
91002744e81Swyllys 	if (PriExp)
91102744e81Swyllys 		free(PriExp);
91202744e81Swyllys 
91302744e81Swyllys 	if (Mod)
91402744e81Swyllys 		free(Mod);
91502744e81Swyllys 
91602744e81Swyllys 	if (PubExp)
91702744e81Swyllys 		free(PubExp);
91802744e81Swyllys 
91902744e81Swyllys 	if (Coef) {
92002744e81Swyllys 		(void) memset(Coef->bv_val, 0, Coef->bv_len);
92102744e81Swyllys 		free(Coef->bv_val);
92202744e81Swyllys 		free(Coef);
92302744e81Swyllys 	}
92402744e81Swyllys 	if (Prime1)
92502744e81Swyllys 		free(Prime1);
92602744e81Swyllys 	if (Prime2)
92702744e81Swyllys 		free(Prime2);
92802744e81Swyllys 
92902744e81Swyllys 	if (ctx != NULL)
93002744e81Swyllys 		BN_CTX_free(ctx);
93102744e81Swyllys 
93202744e81Swyllys 	if (D)
93302744e81Swyllys 		BN_clear_free(D);
93402744e81Swyllys 	if (P)
93502744e81Swyllys 		BN_clear_free(P);
93602744e81Swyllys 	if (Q)
93702744e81Swyllys 		BN_clear_free(Q);
93802744e81Swyllys 	if (pminus1)
93902744e81Swyllys 		BN_clear_free(pminus1);
94002744e81Swyllys 	if (qminus1)
94102744e81Swyllys 		BN_clear_free(qminus1);
94202744e81Swyllys 	if (Exp1)
94302744e81Swyllys 		BN_clear_free(Exp1);
94402744e81Swyllys 	if (Exp2)
94502744e81Swyllys 		BN_clear_free(Exp2);
94602744e81Swyllys 
94702744e81Swyllys 	return (ret);
94802744e81Swyllys 
94902744e81Swyllys }
95002744e81Swyllys 
95199ebb4caSwyllys static EVP_PKEY *
95299ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file)
95399ebb4caSwyllys {
95499ebb4caSwyllys 	BIO *keyfile = NULL;
95599ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
95699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
95799ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
95802744e81Swyllys 	KMF_RETURN rv;
95902744e81Swyllys 	KMF_DATA filedata;
96099ebb4caSwyllys 
96199ebb4caSwyllys 	if (file == NULL) {
96299ebb4caSwyllys 		return (NULL);
96399ebb4caSwyllys 	}
96499ebb4caSwyllys 
96530a5e8faSwyllys 	if (kmf_get_file_format((char *)file, &format) != KMF_OK)
96699ebb4caSwyllys 		return (NULL);
96799ebb4caSwyllys 
96899ebb4caSwyllys 	keyfile = BIO_new_file(file, "rb");
96999ebb4caSwyllys 	if (keyfile == NULL) {
97099ebb4caSwyllys 		goto end;
97199ebb4caSwyllys 	}
97299ebb4caSwyllys 
97302744e81Swyllys 	if (format == KMF_FORMAT_ASN1) {
97499ebb4caSwyllys 		pkey = d2i_PrivateKey_bio(keyfile, NULL);
97502744e81Swyllys 		if (pkey == NULL) {
97602744e81Swyllys 
97702744e81Swyllys 			(void) BIO_free(keyfile);
97802744e81Swyllys 			keyfile = NULL;
97902744e81Swyllys 			/* Try odd ASN.1 variations */
98030a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
98102744e81Swyllys 			    &filedata);
98202744e81Swyllys 			if (rv == KMF_OK) {
98302744e81Swyllys 				(void) readAltFormatPrivateKey(&filedata,
98402744e81Swyllys 				    &pkey);
98530a5e8faSwyllys 				kmf_free_data(&filedata);
98602744e81Swyllys 			}
98702744e81Swyllys 		}
98802744e81Swyllys 	} else if (format == KMF_FORMAT_PEM ||
98902744e81Swyllys 	    format == KMF_FORMAT_PEM_KEYPAIR) {
99099ebb4caSwyllys 		pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
99102744e81Swyllys 		if (pkey == NULL) {
99202744e81Swyllys 			KMF_DATA derdata;
99302744e81Swyllys 			/*
99402744e81Swyllys 			 * Check if this is the alt. format
99502744e81Swyllys 			 * RSA private key file.
99602744e81Swyllys 			 */
99730a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
99802744e81Swyllys 			    &filedata);
99902744e81Swyllys 			if (rv == KMF_OK) {
100002744e81Swyllys 				uchar_t *d = NULL;
100102744e81Swyllys 				int len;
100230a5e8faSwyllys 				rv = kmf_pem_to_der(filedata.Data,
100302744e81Swyllys 				    filedata.Length, &d, &len);
100402744e81Swyllys 				if (rv == KMF_OK && d != NULL) {
100502744e81Swyllys 					derdata.Data = d;
100602744e81Swyllys 					derdata.Length = (size_t)len;
100702744e81Swyllys 					(void) readAltFormatPrivateKey(
100802744e81Swyllys 					    &derdata, &pkey);
100902744e81Swyllys 					free(d);
101002744e81Swyllys 				}
101130a5e8faSwyllys 				kmf_free_data(&filedata);
101202744e81Swyllys 			}
101302744e81Swyllys 		}
101402744e81Swyllys 	}
101599ebb4caSwyllys 
101699ebb4caSwyllys end:
101799ebb4caSwyllys 	if (pkey == NULL)
101899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
101999ebb4caSwyllys 
102099ebb4caSwyllys 	if (keyfile != NULL)
102199ebb4caSwyllys 		(void) BIO_free(keyfile);
102299ebb4caSwyllys 
102399ebb4caSwyllys 	return (pkey);
102499ebb4caSwyllys }
102599ebb4caSwyllys 
102699ebb4caSwyllys KMF_RETURN
102730a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
102899ebb4caSwyllys {
102999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
103099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1031f482c776Swyllys 	int i, n;
1032f482c776Swyllys 	uint32_t maxcerts = 0;
103330a5e8faSwyllys 	uint32_t *num_certs;
103430a5e8faSwyllys 	KMF_X509_DER_CERT *kmf_cert = NULL;
103530a5e8faSwyllys 	char *dirpath = NULL;
103630a5e8faSwyllys 	char *filename = NULL;
103730a5e8faSwyllys 	char *fullpath = NULL;
103830a5e8faSwyllys 	char *issuer = NULL;
103930a5e8faSwyllys 	char *subject = NULL;
104030a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
104130a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
104299ebb4caSwyllys 
104330a5e8faSwyllys 	num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
104430a5e8faSwyllys 	if (num_certs == NULL)
104599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
104699ebb4caSwyllys 
104730a5e8faSwyllys 	/* num_certs should reference the size of kmf_cert */
1048f482c776Swyllys 	maxcerts = *num_certs;
1049f482c776Swyllys 	if (maxcerts == 0)
1050f482c776Swyllys 		maxcerts = 0xFFFFFFFF;
105199ebb4caSwyllys 	*num_certs = 0;
105299ebb4caSwyllys 
105330a5e8faSwyllys 	/* Get the optional returned certificate list  */
105430a5e8faSwyllys 	kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
105530a5e8faSwyllys 	    numattr);
105699ebb4caSwyllys 
105730a5e8faSwyllys 	/*
105830a5e8faSwyllys 	 * The dirpath attribute and the filename attribute can not be NULL
105930a5e8faSwyllys 	 * at the same time.
106030a5e8faSwyllys 	 */
106130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
106230a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
106330a5e8faSwyllys 	    numattr);
106430a5e8faSwyllys 
106530a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
106699ebb4caSwyllys 	if (fullpath == NULL)
106799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
106899ebb4caSwyllys 
106930a5e8faSwyllys 	/* Get optional search criteria attributes */
107030a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
107130a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
107230a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
107330a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
107430a5e8faSwyllys 	    &validity, NULL);
107530a5e8faSwyllys 	if (rv != KMF_OK) {
107630a5e8faSwyllys 		validity = KMF_ALL_CERTS;
107730a5e8faSwyllys 		rv = KMF_OK;
107830a5e8faSwyllys 	}
107930a5e8faSwyllys 
108099ebb4caSwyllys 	if (isdir(fullpath)) {
108199ebb4caSwyllys 		DIR *dirp;
108299ebb4caSwyllys 		struct dirent *dp;
108399ebb4caSwyllys 
1084f482c776Swyllys 		n = 0;
108599ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
108699ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
108799ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
108899ebb4caSwyllys 		}
108999ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
109099ebb4caSwyllys 			char *fname;
109171593db2Swyllys 			KMF_DATA *certlist = NULL;
1092f482c776Swyllys 			uint32_t loaded_certs = 0;
109371593db2Swyllys 
109499ebb4caSwyllys 			if (strcmp(dp->d_name, ".") == 0 ||
109599ebb4caSwyllys 			    strcmp(dp->d_name, "..") == 0)
109699ebb4caSwyllys 				continue;
109799ebb4caSwyllys 
109834acef67Swyllys 			fname = get_fullpath(fullpath, (char *)&dp->d_name);
109999ebb4caSwyllys 
110030a5e8faSwyllys 			rv = load_certs(kmfh, issuer, subject, serial,
110130a5e8faSwyllys 			    validity, fname, &certlist,	&loaded_certs);
110299ebb4caSwyllys 
110399ebb4caSwyllys 			if (rv != KMF_OK) {
110499ebb4caSwyllys 				free(fname);
110571593db2Swyllys 				if (certlist != NULL) {
1106f482c776Swyllys 					for (i = 0; i < loaded_certs; i++)
110730a5e8faSwyllys 						kmf_free_data(&certlist[i]);
110871593db2Swyllys 					free(certlist);
110971593db2Swyllys 				}
111099ebb4caSwyllys 				continue;
111199ebb4caSwyllys 			}
111299ebb4caSwyllys 
111399ebb4caSwyllys 			/* If load succeeds, add certdata to the list */
111499ebb4caSwyllys 			if (kmf_cert != NULL) {
1115f482c776Swyllys 				for (i = 0; i < loaded_certs &&
1116b4058258Swyllys 				    n < maxcerts; i++) {
111771593db2Swyllys 					kmf_cert[n].certificate.Data =
111871593db2Swyllys 					    certlist[i].Data;
111999ebb4caSwyllys 					kmf_cert[n].certificate.Length =
112071593db2Swyllys 					    certlist[i].Length;
112199ebb4caSwyllys 
112299ebb4caSwyllys 					kmf_cert[n].kmf_private.keystore_type =
112399ebb4caSwyllys 					    KMF_KEYSTORE_OPENSSL;
112499ebb4caSwyllys 					kmf_cert[n].kmf_private.flags =
112599ebb4caSwyllys 					    KMF_FLAG_CERT_VALID;
112671593db2Swyllys 					kmf_cert[n].kmf_private.label =
112771593db2Swyllys 					    strdup(fname);
112899ebb4caSwyllys 					n++;
112999ebb4caSwyllys 				}
1130b4058258Swyllys 				/*
1131b4058258Swyllys 				 * If maxcerts < loaded_certs, clean up the
1132b4058258Swyllys 				 * certs that were not used.
1133b4058258Swyllys 				 */
1134f482c776Swyllys 				for (; i < loaded_certs; i++)
113530a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1136f482c776Swyllys 			} else {
1137f482c776Swyllys 				for (i = 0; i < loaded_certs; i++)
113830a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1139f482c776Swyllys 				n += loaded_certs;
114071593db2Swyllys 			}
1141f482c776Swyllys 			free(certlist);
114271593db2Swyllys 			free(fname);
114371593db2Swyllys 		}
114499ebb4caSwyllys 		(*num_certs) = n;
114599ebb4caSwyllys 		if (*num_certs == 0)
114699ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
114730a5e8faSwyllys 		if (*num_certs > 0)
114899ebb4caSwyllys 			rv = KMF_OK;
114999ebb4caSwyllys exit:
115099ebb4caSwyllys 		(void) closedir(dirp);
115199ebb4caSwyllys 	} else {
115271593db2Swyllys 		KMF_DATA *certlist = NULL;
1153f482c776Swyllys 		uint32_t loaded_certs = 0;
115471593db2Swyllys 
115530a5e8faSwyllys 		rv = load_certs(kmfh, issuer, subject, serial, validity,
115630a5e8faSwyllys 		    fullpath, &certlist, &loaded_certs);
115799ebb4caSwyllys 		if (rv != KMF_OK) {
115899ebb4caSwyllys 			free(fullpath);
115999ebb4caSwyllys 			return (rv);
116099ebb4caSwyllys 		}
116199ebb4caSwyllys 
1162f482c776Swyllys 		n = 0;
116371593db2Swyllys 		if (kmf_cert != NULL && certlist != NULL) {
1164f482c776Swyllys 			for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1165f482c776Swyllys 				kmf_cert[n].certificate.Data =
116671593db2Swyllys 				    certlist[i].Data;
1167f482c776Swyllys 				kmf_cert[n].certificate.Length =
116871593db2Swyllys 				    certlist[i].Length;
1169f482c776Swyllys 				kmf_cert[n].kmf_private.keystore_type =
117099ebb4caSwyllys 				    KMF_KEYSTORE_OPENSSL;
1171f482c776Swyllys 				kmf_cert[n].kmf_private.flags =
117271593db2Swyllys 				    KMF_FLAG_CERT_VALID;
1173f482c776Swyllys 				kmf_cert[n].kmf_private.label =
117471593db2Swyllys 				    strdup(fullpath);
1175f482c776Swyllys 				n++;
117671593db2Swyllys 			}
1177f482c776Swyllys 			/* If maxcerts < loaded_certs, clean up */
1178f482c776Swyllys 			for (; i < loaded_certs; i++)
117930a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1180f482c776Swyllys 		} else if (certlist != NULL) {
1181f482c776Swyllys 			for (i = 0; i < loaded_certs; i++)
118230a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1183f482c776Swyllys 			n = loaded_certs;
1184f482c776Swyllys 		}
118530a5e8faSwyllys 		if (certlist != NULL)
118671593db2Swyllys 			free(certlist);
1187f482c776Swyllys 		*num_certs = n;
118899ebb4caSwyllys 	}
118999ebb4caSwyllys 
119099ebb4caSwyllys 	free(fullpath);
119199ebb4caSwyllys 
119299ebb4caSwyllys 	return (rv);
119399ebb4caSwyllys }
119499ebb4caSwyllys 
119599ebb4caSwyllys void
119699ebb4caSwyllys /*ARGSUSED*/
119799ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
119899ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert)
119999ebb4caSwyllys {
120099ebb4caSwyllys 	if (kmf_cert != NULL) {
120199ebb4caSwyllys 		if (kmf_cert->certificate.Data != NULL) {
1202e65e5c2dSWyllys Ingersoll 			kmf_free_data(&kmf_cert->certificate);
120399ebb4caSwyllys 		}
120499ebb4caSwyllys 		if (kmf_cert->kmf_private.label)
120599ebb4caSwyllys 			free(kmf_cert->kmf_private.label);
120699ebb4caSwyllys 	}
120799ebb4caSwyllys }
120899ebb4caSwyllys 
120930a5e8faSwyllys /*ARGSUSED*/
121099ebb4caSwyllys KMF_RETURN
121130a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
121299ebb4caSwyllys {
121399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
121430a5e8faSwyllys 	KMF_DATA *cert = NULL;
121530a5e8faSwyllys 	char *outfilename = NULL;
121630a5e8faSwyllys 	char *dirpath = NULL;
121730a5e8faSwyllys 	char *fullpath = NULL;
121899ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
121999ebb4caSwyllys 
122030a5e8faSwyllys 	/* Get the cert data */
122130a5e8faSwyllys 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
122230a5e8faSwyllys 	if (cert == NULL || cert->Data == NULL)
122399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
122499ebb4caSwyllys 
122530a5e8faSwyllys 	/* Check the output filename and directory attributes. */
122630a5e8faSwyllys 	outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
122730a5e8faSwyllys 	    numattr);
122830a5e8faSwyllys 	if (outfilename == NULL)
122930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
123099ebb4caSwyllys 
123130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
123230a5e8faSwyllys 	fullpath = get_fullpath(dirpath, outfilename);
123399ebb4caSwyllys 	if (fullpath == NULL)
123430a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
123599ebb4caSwyllys 
123630a5e8faSwyllys 	/* Check the optional format attribute */
123730a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
123830a5e8faSwyllys 	    &format, NULL);
123930a5e8faSwyllys 	if (ret != KMF_OK) {
124030a5e8faSwyllys 		/* If there is no format attribute, then default to PEM */
124130a5e8faSwyllys 		format = KMF_FORMAT_PEM;
124299ebb4caSwyllys 		ret = KMF_OK;
124330a5e8faSwyllys 	} else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
124430a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
124599ebb4caSwyllys 		goto out;
124699ebb4caSwyllys 	}
124799ebb4caSwyllys 
124830a5e8faSwyllys 	/* Store the certificate in the file with the specified format */
124930a5e8faSwyllys 	ret = kmf_create_cert_file(cert, format, fullpath);
125099ebb4caSwyllys 
125199ebb4caSwyllys out:
125299ebb4caSwyllys 	if (fullpath != NULL)
125399ebb4caSwyllys 		free(fullpath);
125499ebb4caSwyllys 
125599ebb4caSwyllys 	return (ret);
125699ebb4caSwyllys }
125799ebb4caSwyllys 
125830a5e8faSwyllys 
125999ebb4caSwyllys KMF_RETURN
126030a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
126199ebb4caSwyllys {
126299ebb4caSwyllys 	KMF_RETURN rv;
126399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
126499ebb4caSwyllys 	KMF_DATA certdata = {NULL, 0};
126530a5e8faSwyllys 	char *dirpath = NULL;
126630a5e8faSwyllys 	char *filename = NULL;
126730a5e8faSwyllys 	char *fullpath = NULL;
126830a5e8faSwyllys 	char *issuer = NULL;
126930a5e8faSwyllys 	char *subject = NULL;
127030a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
127130a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
127299ebb4caSwyllys 
127330a5e8faSwyllys 	/*
127430a5e8faSwyllys 	 * Get the DIRPATH and CERT_FILENAME attributes.  They can not be
127530a5e8faSwyllys 	 * NULL at the same time.
127630a5e8faSwyllys 	 */
127730a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
127830a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
127930a5e8faSwyllys 	    numattr);
128030a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
128199ebb4caSwyllys 	if (fullpath == NULL)
128299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
128399ebb4caSwyllys 
128430a5e8faSwyllys 	/* Get optional search criteria attributes */
128530a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
128630a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
128730a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
128830a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
128930a5e8faSwyllys 	    &validity, NULL);
129030a5e8faSwyllys 	if (rv != KMF_OK) {
129130a5e8faSwyllys 		validity = KMF_ALL_CERTS;
129230a5e8faSwyllys 		rv = KMF_OK;
129330a5e8faSwyllys 	}
129430a5e8faSwyllys 
129599ebb4caSwyllys 	if (isdir(fullpath)) {
129699ebb4caSwyllys 		DIR *dirp;
129799ebb4caSwyllys 		struct dirent *dp;
129899ebb4caSwyllys 
129999ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
130099ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
130199ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
130299ebb4caSwyllys 		}
130399ebb4caSwyllys 
130499ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
130599ebb4caSwyllys 			if (strcmp(dp->d_name, ".") != 0 &&
130699ebb4caSwyllys 			    strcmp(dp->d_name, "..") != 0) {
130799ebb4caSwyllys 				char *fname;
130899ebb4caSwyllys 
130999ebb4caSwyllys 				fname = get_fullpath(fullpath,
131099ebb4caSwyllys 				    (char *)&dp->d_name);
131199ebb4caSwyllys 
131299ebb4caSwyllys 				if (fname == NULL) {
131399ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
131499ebb4caSwyllys 					break;
131599ebb4caSwyllys 				}
131699ebb4caSwyllys 
131730a5e8faSwyllys 				rv = kmf_load_cert(kmfh, issuer, subject,
131830a5e8faSwyllys 				    serial, validity, fname, &certdata);
131999ebb4caSwyllys 
132099ebb4caSwyllys 				if (rv == KMF_ERR_CERT_NOT_FOUND) {
132199ebb4caSwyllys 					free(fname);
1322e65e5c2dSWyllys Ingersoll 					kmf_free_data(&certdata);
132399ebb4caSwyllys 					rv = KMF_OK;
132499ebb4caSwyllys 					continue;
132599ebb4caSwyllys 				} else if (rv != KMF_OK) {
132699ebb4caSwyllys 					free(fname);
132799ebb4caSwyllys 					break;
132899ebb4caSwyllys 				}
132999ebb4caSwyllys 
133099ebb4caSwyllys 				if (unlink(fname) != 0) {
133199ebb4caSwyllys 					SET_SYS_ERROR(kmfh, errno);
133299ebb4caSwyllys 					rv = KMF_ERR_INTERNAL;
133399ebb4caSwyllys 					free(fname);
133499ebb4caSwyllys 					break;
133599ebb4caSwyllys 				}
133699ebb4caSwyllys 				free(fname);
1337e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certdata);
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 
1357e65e5c2dSWyllys Ingersoll 	kmf_free_data(&certdata);
135899ebb4caSwyllys 
135999ebb4caSwyllys 	return (rv);
136099ebb4caSwyllys }
136199ebb4caSwyllys 
136299ebb4caSwyllys KMF_RETURN
136399ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
136499ebb4caSwyllys 	KMF_DATA *keydata)
136599ebb4caSwyllys {
136699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
136799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
136899ebb4caSwyllys 	int n;
136999ebb4caSwyllys 
137099ebb4caSwyllys 	if (key == NULL || keydata == NULL ||
137199ebb4caSwyllys 	    key->keyp == NULL)
137299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
137399ebb4caSwyllys 
137499ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
137599ebb4caSwyllys 		RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
137699ebb4caSwyllys 
137799ebb4caSwyllys 		if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
137899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
137999ebb4caSwyllys 			return (KMF_ERR_ENCODING);
138099ebb4caSwyllys 		}
138199ebb4caSwyllys 		RSA_free(pubkey);
138299ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
138399ebb4caSwyllys 		DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
138499ebb4caSwyllys 
138599ebb4caSwyllys 		if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
138699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
138799ebb4caSwyllys 			return (KMF_ERR_ENCODING);
138899ebb4caSwyllys 		}
138999ebb4caSwyllys 		DSA_free(pubkey);
139099ebb4caSwyllys 	} else {
139199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
139299ebb4caSwyllys 	}
139399ebb4caSwyllys 	keydata->Length = n;
139499ebb4caSwyllys 
139599ebb4caSwyllys cleanup:
139699ebb4caSwyllys 	if (rv != KMF_OK) {
139799ebb4caSwyllys 		if (keydata->Data)
139899ebb4caSwyllys 			free(keydata->Data);
139999ebb4caSwyllys 		keydata->Data = NULL;
140099ebb4caSwyllys 		keydata->Length = 0;
140199ebb4caSwyllys 	}
140299ebb4caSwyllys 
140399ebb4caSwyllys 	return (rv);
140499ebb4caSwyllys }
140599ebb4caSwyllys 
140699ebb4caSwyllys static KMF_RETURN
140730a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
140830a5e8faSwyllys 	KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
140999ebb4caSwyllys {
141099ebb4caSwyllys 	int rv = 0;
141199ebb4caSwyllys 	RSA *rsa;
141299ebb4caSwyllys 	DSA *dsa;
141399ebb4caSwyllys 
14145b3e1433Swyllys 	if (pkey == NULL || out == NULL)
14155b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
14165b3e1433Swyllys 
141799ebb4caSwyllys 	switch (format) {
141873cc0e02Swyllys 		case KMF_FORMAT_RAWKEY:
141973cc0e02Swyllys 			/* same as ASN.1 */
142099ebb4caSwyllys 		case KMF_FORMAT_ASN1:
142199ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
142299ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
142330a5e8faSwyllys 				if (private)
142499ebb4caSwyllys 					rv = i2d_RSAPrivateKey_bio(out, rsa);
142530a5e8faSwyllys 				else
142630a5e8faSwyllys 					rv = i2d_RSAPublicKey_bio(out, rsa);
142799ebb4caSwyllys 				RSA_free(rsa);
142899ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
142999ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
143099ebb4caSwyllys 				rv = i2d_DSAPrivateKey_bio(out, dsa);
143199ebb4caSwyllys 				DSA_free(dsa);
143299ebb4caSwyllys 			}
143399ebb4caSwyllys 			if (rv == 1) {
143499ebb4caSwyllys 				rv = KMF_OK;
143599ebb4caSwyllys 			} else {
143699ebb4caSwyllys 				SET_ERROR(kmfh, rv);
143799ebb4caSwyllys 			}
143899ebb4caSwyllys 			break;
143999ebb4caSwyllys 		case KMF_FORMAT_PEM:
144099ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
144199ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
144230a5e8faSwyllys 				if (private)
144399ebb4caSwyllys 					rv = PEM_write_bio_RSAPrivateKey(out,
144430a5e8faSwyllys 					    rsa, NULL, NULL, 0, NULL,
144530a5e8faSwyllys 					    (cred != NULL ? cred->cred : NULL));
144630a5e8faSwyllys 				else
144730a5e8faSwyllys 					rv = PEM_write_bio_RSAPublicKey(out,
144830a5e8faSwyllys 					    rsa);
144999ebb4caSwyllys 				RSA_free(rsa);
145099ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
145199ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
145299ebb4caSwyllys 				rv = PEM_write_bio_DSAPrivateKey(out,
145330a5e8faSwyllys 				    dsa, NULL, NULL, 0, NULL,
145430a5e8faSwyllys 				    (cred != NULL ? cred->cred : NULL));
145599ebb4caSwyllys 				DSA_free(dsa);
145699ebb4caSwyllys 			}
145799ebb4caSwyllys 
145899ebb4caSwyllys 			if (rv == 1) {
145999ebb4caSwyllys 				rv = KMF_OK;
146099ebb4caSwyllys 			} else {
146199ebb4caSwyllys 				SET_ERROR(kmfh, rv);
146299ebb4caSwyllys 			}
146399ebb4caSwyllys 			break;
146499ebb4caSwyllys 
146599ebb4caSwyllys 		default:
146699ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
146799ebb4caSwyllys 	}
146899ebb4caSwyllys 
146999ebb4caSwyllys 	return (rv);
147099ebb4caSwyllys }
147199ebb4caSwyllys 
147299ebb4caSwyllys KMF_RETURN
147330a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
147430a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
147599ebb4caSwyllys {
147699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
147799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
147899ebb4caSwyllys 	uint32_t eValue = 0x010001;
147999ebb4caSwyllys 	RSA *sslPrivKey = NULL;
148099ebb4caSwyllys 	DSA *sslDSAKey = NULL;
148199ebb4caSwyllys 	EVP_PKEY *eprikey = NULL;
148299ebb4caSwyllys 	EVP_PKEY *epubkey = NULL;
148399ebb4caSwyllys 	BIO *out = NULL;
148430a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
148530a5e8faSwyllys 	uint32_t keylen = 1024;
148630a5e8faSwyllys 	uint32_t keylen_size = sizeof (uint32_t);
148730a5e8faSwyllys 	boolean_t storekey = TRUE;
148830a5e8faSwyllys 	KMF_KEY_ALG keytype = KMF_RSA;
148999ebb4caSwyllys 
149030a5e8faSwyllys 	rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
149130a5e8faSwyllys 	    &storekey, NULL);
149230a5e8faSwyllys 	if (rv != KMF_OK) {
149330a5e8faSwyllys 		/* "storekey" is optional. Default is TRUE */
149430a5e8faSwyllys 		rv = KMF_OK;
149599ebb4caSwyllys 	}
149699ebb4caSwyllys 
149730a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
149830a5e8faSwyllys 	    (void *)&keytype, NULL);
149930a5e8faSwyllys 	if (rv != KMF_OK)
150030a5e8faSwyllys 		/* keytype is optional.  KMF_RSA is default */
150130a5e8faSwyllys 		rv = KMF_OK;
150299ebb4caSwyllys 
150330a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
150430a5e8faSwyllys 	if (pubkey == NULL)
150599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
150699ebb4caSwyllys 
150730a5e8faSwyllys 	privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
150830a5e8faSwyllys 	if (privkey == NULL)
150930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
151030a5e8faSwyllys 
151130a5e8faSwyllys 	(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
151230a5e8faSwyllys 	(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
151399ebb4caSwyllys 
151499ebb4caSwyllys 	eprikey = EVP_PKEY_new();
151599ebb4caSwyllys 	if (eprikey == NULL) {
151699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
151799ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
151899ebb4caSwyllys 		goto cleanup;
151999ebb4caSwyllys 	}
152099ebb4caSwyllys 	epubkey = EVP_PKEY_new();
152199ebb4caSwyllys 	if (epubkey == NULL) {
152299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
152399ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
152499ebb4caSwyllys 		goto cleanup;
152599ebb4caSwyllys 	}
152630a5e8faSwyllys 	if (keytype == KMF_RSA) {
152730a5e8faSwyllys 		KMF_BIGINT *rsaexp = NULL;
152899ebb4caSwyllys 
152930a5e8faSwyllys 		rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
153030a5e8faSwyllys 		if (rsaexp != NULL) {
153130a5e8faSwyllys 			if (rsaexp->len > 0 &&
153230a5e8faSwyllys 			    rsaexp->len <= sizeof (eValue) &&
153330a5e8faSwyllys 			    rsaexp->val != NULL) {
1534a2d4930dSDan OpenSolaris Anderson 				/* LINTED E_BAD_PTR_CAST_ALIGN */
153530a5e8faSwyllys 				eValue = *(uint32_t *)rsaexp->val;
153630a5e8faSwyllys 			} else {
153730a5e8faSwyllys 				rv = KMF_ERR_BAD_PARAMETER;
153830a5e8faSwyllys 				goto cleanup;
153930a5e8faSwyllys 			}
154030a5e8faSwyllys 		} else {
154130a5e8faSwyllys 			/* RSA Exponent is optional. Default is 0x10001 */
154230a5e8faSwyllys 			rv = KMF_OK;
154330a5e8faSwyllys 		}
154430a5e8faSwyllys 
154530a5e8faSwyllys 		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
154630a5e8faSwyllys 		    &keylen, &keylen_size);
154730a5e8faSwyllys 		if (rv == KMF_ERR_ATTR_NOT_FOUND)
154830a5e8faSwyllys 			/* keylen is optional, default is 1024 */
154930a5e8faSwyllys 			rv = KMF_OK;
155030a5e8faSwyllys 		if (rv != KMF_OK) {
155130a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
155230a5e8faSwyllys 			goto cleanup;
155330a5e8faSwyllys 		}
155430a5e8faSwyllys 
155530a5e8faSwyllys 		sslPrivKey = RSA_generate_key(keylen, eValue, NULL, NULL);
155699ebb4caSwyllys 		if (sslPrivKey == NULL) {
155799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
155899ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
155999ebb4caSwyllys 		} else {
156030a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
156199ebb4caSwyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
156299ebb4caSwyllys 			privkey->keyalg = KMF_RSA;
156399ebb4caSwyllys 			privkey->keyclass = KMF_ASYM_PRI;
156499ebb4caSwyllys 			privkey->israw = FALSE;
156599ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
156630a5e8faSwyllys 
156799ebb4caSwyllys 			/* OpenSSL derives the public key from the private */
156830a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
156999ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
157099ebb4caSwyllys 			pubkey->keyalg = KMF_RSA;
157199ebb4caSwyllys 			pubkey->israw = FALSE;
157299ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
157399ebb4caSwyllys 			pubkey->keyp = (void *)epubkey;
157499ebb4caSwyllys 		}
157530a5e8faSwyllys 	} else if (keytype == KMF_DSA) {
157630a5e8faSwyllys 		DSA *dp;
157799ebb4caSwyllys 		sslDSAKey = DSA_new();
157899ebb4caSwyllys 		if (sslDSAKey == NULL) {
157999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
158099ebb4caSwyllys 			return (KMF_ERR_MEMORY);
158199ebb4caSwyllys 		}
158299ebb4caSwyllys 
158399ebb4caSwyllys 		if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) ==
158499ebb4caSwyllys 		    NULL) {
158599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
158699ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
158799ebb4caSwyllys 			goto cleanup;
158899ebb4caSwyllys 		}
158999ebb4caSwyllys 		if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) ==
159099ebb4caSwyllys 		    NULL) {
159199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
159299ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
159399ebb4caSwyllys 			goto cleanup;
159499ebb4caSwyllys 		}
159599ebb4caSwyllys 		if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) ==
159699ebb4caSwyllys 		    NULL) {
159799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
159899ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
159999ebb4caSwyllys 			goto cleanup;
160099ebb4caSwyllys 		}
160199ebb4caSwyllys 
160299ebb4caSwyllys 		if (!DSA_generate_key(sslDSAKey)) {
160399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
160499ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
160599ebb4caSwyllys 			goto cleanup;
160699ebb4caSwyllys 		}
160799ebb4caSwyllys 
160899ebb4caSwyllys 		privkey->kstype = KMF_KEYSTORE_OPENSSL;
160999ebb4caSwyllys 		privkey->keyalg = KMF_DSA;
161099ebb4caSwyllys 		privkey->keyclass = KMF_ASYM_PRI;
161199ebb4caSwyllys 		privkey->israw = FALSE;
161299ebb4caSwyllys 		if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
161399ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
161499ebb4caSwyllys 		} else {
161599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
161699ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
161799ebb4caSwyllys 			goto cleanup;
161899ebb4caSwyllys 		}
161930a5e8faSwyllys 		dp = DSA_new();
162099ebb4caSwyllys 		/* Make a copy for the public key */
162199ebb4caSwyllys 		if (dp != NULL) {
162299ebb4caSwyllys 			if ((dp->p = BN_new()) == NULL) {
162399ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
162499ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
162599ebb4caSwyllys 				DSA_free(dp);
162699ebb4caSwyllys 				goto cleanup;
162799ebb4caSwyllys 			}
162899ebb4caSwyllys 			if ((dp->q = BN_new()) == NULL) {
162999ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
163099ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
163199ebb4caSwyllys 				BN_free(dp->p);
163299ebb4caSwyllys 				DSA_free(dp);
163399ebb4caSwyllys 				goto cleanup;
163499ebb4caSwyllys 			}
163599ebb4caSwyllys 			if ((dp->g = BN_new()) == NULL) {
163699ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
163799ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
163899ebb4caSwyllys 				BN_free(dp->q);
163999ebb4caSwyllys 				BN_free(dp->p);
164099ebb4caSwyllys 				DSA_free(dp);
164199ebb4caSwyllys 				goto cleanup;
164299ebb4caSwyllys 			}
164399ebb4caSwyllys 			if ((dp->pub_key = BN_new()) == NULL) {
164499ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
164599ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
164699ebb4caSwyllys 				BN_free(dp->q);
164799ebb4caSwyllys 				BN_free(dp->p);
164899ebb4caSwyllys 				BN_free(dp->g);
164999ebb4caSwyllys 				DSA_free(dp);
165099ebb4caSwyllys 				goto cleanup;
165199ebb4caSwyllys 			}
165299ebb4caSwyllys 			(void) BN_copy(dp->p, sslDSAKey->p);
165399ebb4caSwyllys 			(void) BN_copy(dp->q, sslDSAKey->q);
165499ebb4caSwyllys 			(void) BN_copy(dp->g, sslDSAKey->g);
165599ebb4caSwyllys 			(void) BN_copy(dp->pub_key, sslDSAKey->pub_key);
165699ebb4caSwyllys 
165799ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
165899ebb4caSwyllys 			pubkey->keyalg = KMF_DSA;
165999ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
166099ebb4caSwyllys 			pubkey->israw = FALSE;
166199ebb4caSwyllys 
166299ebb4caSwyllys 			if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
166399ebb4caSwyllys 				pubkey->keyp = (void *)epubkey;
166499ebb4caSwyllys 			} else {
166599ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
166699ebb4caSwyllys 				rv = KMF_ERR_KEYGEN_FAILED;
166799ebb4caSwyllys 				goto cleanup;
166899ebb4caSwyllys 			}
166999ebb4caSwyllys 		}
167099ebb4caSwyllys 	}
167199ebb4caSwyllys 
167299ebb4caSwyllys 	if (rv != KMF_OK) {
167399ebb4caSwyllys 		goto cleanup;
167499ebb4caSwyllys 	}
167599ebb4caSwyllys 
167630a5e8faSwyllys 	if (storekey) {
167730a5e8faSwyllys 		KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
167830a5e8faSwyllys 		int i = 0;
167930a5e8faSwyllys 		char *keyfile = NULL, *dirpath = NULL;
168030a5e8faSwyllys 		KMF_ENCODE_FORMAT format;
168130a5e8faSwyllys 		/*
168230a5e8faSwyllys 		 * Construct a new attribute arrray and call openssl_store_key
168330a5e8faSwyllys 		 */
168430a5e8faSwyllys 		kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
168530a5e8faSwyllys 		    privkey, sizeof (privkey));
168630a5e8faSwyllys 		i++;
168730a5e8faSwyllys 
168830a5e8faSwyllys 		dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
168930a5e8faSwyllys 		if (dirpath != NULL) {
169030a5e8faSwyllys 			storeattrs[i].type = KMF_DIRPATH_ATTR;
169130a5e8faSwyllys 			storeattrs[i].pValue = dirpath;
169230a5e8faSwyllys 			storeattrs[i].valueLen = strlen(dirpath);
169330a5e8faSwyllys 			i++;
169430a5e8faSwyllys 		} else {
169530a5e8faSwyllys 			rv = KMF_OK; /* DIRPATH is optional */
169699ebb4caSwyllys 		}
169730a5e8faSwyllys 		keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
169830a5e8faSwyllys 		    attrlist, numattr);
169930a5e8faSwyllys 		if (keyfile != NULL) {
170030a5e8faSwyllys 			storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
170130a5e8faSwyllys 			storeattrs[i].pValue = keyfile;
170230a5e8faSwyllys 			storeattrs[i].valueLen = strlen(keyfile);
170330a5e8faSwyllys 			i++;
170430a5e8faSwyllys 		} else {
170530a5e8faSwyllys 			goto cleanup; /* KEYFILE is required */
170630a5e8faSwyllys 		}
170730a5e8faSwyllys 		rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
170830a5e8faSwyllys 		    (void *)&format, NULL);
170930a5e8faSwyllys 		if (rv == KMF_OK) {
171030a5e8faSwyllys 			storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
171130a5e8faSwyllys 			storeattrs[i].pValue = &format;
171230a5e8faSwyllys 			storeattrs[i].valueLen = sizeof (format);
171330a5e8faSwyllys 			i++;
171430a5e8faSwyllys 		}
171530a5e8faSwyllys 
171630a5e8faSwyllys 		rv = OpenSSL_StoreKey(handle, i, storeattrs);
171730a5e8faSwyllys 	}
171899ebb4caSwyllys 
171999ebb4caSwyllys cleanup:
172099ebb4caSwyllys 	if (rv != KMF_OK) {
172199ebb4caSwyllys 		if (eprikey != NULL)
172299ebb4caSwyllys 			EVP_PKEY_free(eprikey);
172399ebb4caSwyllys 
172499ebb4caSwyllys 		if (epubkey != NULL)
172599ebb4caSwyllys 			EVP_PKEY_free(epubkey);
172699ebb4caSwyllys 
172799ebb4caSwyllys 		if (pubkey->keylabel) {
172899ebb4caSwyllys 			free(pubkey->keylabel);
172999ebb4caSwyllys 			pubkey->keylabel = NULL;
173099ebb4caSwyllys 		}
173199ebb4caSwyllys 
173299ebb4caSwyllys 		if (privkey->keylabel) {
173399ebb4caSwyllys 			free(privkey->keylabel);
173499ebb4caSwyllys 			privkey->keylabel = NULL;
173599ebb4caSwyllys 		}
173699ebb4caSwyllys 
173799ebb4caSwyllys 		pubkey->keyp = NULL;
173899ebb4caSwyllys 		privkey->keyp = NULL;
173999ebb4caSwyllys 	}
174099ebb4caSwyllys 
174199ebb4caSwyllys 	if (sslPrivKey)
174299ebb4caSwyllys 		RSA_free(sslPrivKey);
174399ebb4caSwyllys 
174499ebb4caSwyllys 	if (sslDSAKey)
174599ebb4caSwyllys 		DSA_free(sslDSAKey);
174699ebb4caSwyllys 
174799ebb4caSwyllys 	if (out != NULL)
174899ebb4caSwyllys 		(void) BIO_free(out);
174999ebb4caSwyllys 
175099ebb4caSwyllys 	return (rv);
175199ebb4caSwyllys }
175299ebb4caSwyllys 
1753e65e5c2dSWyllys Ingersoll /*
1754e65e5c2dSWyllys Ingersoll  * Make sure the BN conversion is properly padded with 0x00
1755e65e5c2dSWyllys Ingersoll  * bytes.  If not, signature verification for DSA signatures
1756e65e5c2dSWyllys Ingersoll  * may fail in the case where the bignum value does not use
1757e65e5c2dSWyllys Ingersoll  * all of the bits.
1758e65e5c2dSWyllys Ingersoll  */
1759e65e5c2dSWyllys Ingersoll static int
1760e65e5c2dSWyllys Ingersoll fixbnlen(BIGNUM *bn, unsigned char *buf, int len) {
1761e65e5c2dSWyllys Ingersoll 	int bytes = len - BN_num_bytes(bn);
1762*2c9a247fSWyllys Ingersoll 
1763*2c9a247fSWyllys Ingersoll 	/* prepend with leading 0x00 if necessary */
1764e65e5c2dSWyllys Ingersoll 	while (bytes-- > 0)
1765e65e5c2dSWyllys Ingersoll 		*buf++ = 0;
1766e65e5c2dSWyllys Ingersoll 
1767*2c9a247fSWyllys Ingersoll 	(void) BN_bn2bin(bn, buf);
1768*2c9a247fSWyllys Ingersoll 	/*
1769*2c9a247fSWyllys Ingersoll 	 * Return the desired length since we prepended it
1770*2c9a247fSWyllys Ingersoll 	 * with the necessary 0x00 padding.
1771*2c9a247fSWyllys Ingersoll 	 */
1772*2c9a247fSWyllys Ingersoll 	return (len);
1773e65e5c2dSWyllys Ingersoll }
1774e65e5c2dSWyllys Ingersoll 
177599ebb4caSwyllys KMF_RETURN
177699ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
177799ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
177899ebb4caSwyllys {
177999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
178099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
178199ebb4caSwyllys 	KMF_ALGORITHM_INDEX		AlgId;
178299ebb4caSwyllys 	EVP_MD_CTX ctx;
178399ebb4caSwyllys 	const EVP_MD *md;
178402744e81Swyllys 
178599ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
178699ebb4caSwyllys 	    tobesigned == NULL || output == NULL ||
178799ebb4caSwyllys 	    tobesigned->Data == NULL ||
178899ebb4caSwyllys 	    output->Data == NULL)
178999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
179099ebb4caSwyllys 
179199ebb4caSwyllys 	/* Map the OID to an OpenSSL algorithm */
179230a5e8faSwyllys 	AlgId = x509_algoid_to_algid(AlgOID);
179399ebb4caSwyllys 	if (AlgId == KMF_ALGID_NONE)
1794e65e5c2dSWyllys Ingersoll 		return (KMF_ERR_BAD_ALGORITHM);
179599ebb4caSwyllys 
179699ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
179799ebb4caSwyllys 		EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
179899ebb4caSwyllys 		uchar_t *p;
179902744e81Swyllys 		int len;
180099ebb4caSwyllys 		if (AlgId == KMF_ALGID_MD5WithRSA)
180199ebb4caSwyllys 			md = EVP_md5();
180299ebb4caSwyllys 		else if (AlgId == KMF_ALGID_MD2WithRSA)
180399ebb4caSwyllys 			md = EVP_md2();
180499ebb4caSwyllys 		else if (AlgId == KMF_ALGID_SHA1WithRSA)
180599ebb4caSwyllys 			md = EVP_sha1();
1806e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA256WithRSA)
1807e65e5c2dSWyllys Ingersoll 			md = EVP_sha256();
1808e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA384WithRSA)
1809e65e5c2dSWyllys Ingersoll 			md = EVP_sha384();
1810e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA512WithRSA)
1811e65e5c2dSWyllys Ingersoll 			md = EVP_sha512();
181202744e81Swyllys 		else if (AlgId == KMF_ALGID_RSA)
181302744e81Swyllys 			md = NULL;
181499ebb4caSwyllys 		else
1815e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_ALGORITHM);
181699ebb4caSwyllys 
181702744e81Swyllys 		if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
181802744e81Swyllys 			RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
181999ebb4caSwyllys 
182002744e81Swyllys 			p = output->Data;
182102744e81Swyllys 			if ((len = RSA_private_encrypt(tobesigned->Length,
182202744e81Swyllys 			    tobesigned->Data, p, rsa,
182302744e81Swyllys 			    RSA_PKCS1_PADDING)) <= 0) {
182402744e81Swyllys 				SET_ERROR(kmfh, ERR_get_error());
182502744e81Swyllys 				ret = KMF_ERR_INTERNAL;
182602744e81Swyllys 			}
182702744e81Swyllys 			output->Length = len;
182802744e81Swyllys 		} else {
182999ebb4caSwyllys 			(void) EVP_MD_CTX_init(&ctx);
183099ebb4caSwyllys 			(void) EVP_SignInit_ex(&ctx, md, NULL);
183199ebb4caSwyllys 			(void) EVP_SignUpdate(&ctx, tobesigned->Data,
183299ebb4caSwyllys 			    (uint32_t)tobesigned->Length);
183399ebb4caSwyllys 			len = (uint32_t)output->Length;
183499ebb4caSwyllys 			p = output->Data;
183502744e81Swyllys 			if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) {
183699ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
183702744e81Swyllys 				len = 0;
183802744e81Swyllys 				ret = KMF_ERR_INTERNAL;
183999ebb4caSwyllys 			}
184099ebb4caSwyllys 			output->Length = len;
184199ebb4caSwyllys 			(void) EVP_MD_CTX_cleanup(&ctx);
184202744e81Swyllys 		}
184399ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
184499ebb4caSwyllys 		DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
184599ebb4caSwyllys 
184699ebb4caSwyllys 		uchar_t hash[EVP_MAX_MD_SIZE];
184799ebb4caSwyllys 		uint32_t hashlen;
184899ebb4caSwyllys 		DSA_SIG *dsasig;
184999ebb4caSwyllys 
1850e65e5c2dSWyllys Ingersoll 		if (AlgId == KMF_ALGID_DSA ||
1851e65e5c2dSWyllys Ingersoll 		    AlgId == KMF_ALGID_SHA1WithDSA)
1852e65e5c2dSWyllys Ingersoll 			md = EVP_sha1();
1853e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA256WithDSA)
1854e65e5c2dSWyllys Ingersoll 			md = EVP_sha256();
1855e65e5c2dSWyllys Ingersoll 		else /* Bad algorithm */
1856e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_ALGORITHM);
1857e65e5c2dSWyllys Ingersoll 
185899ebb4caSwyllys 		/*
185999ebb4caSwyllys 		 * OpenSSL EVP_Sign operation automatically converts to
186099ebb4caSwyllys 		 * ASN.1 output so we do the operations separately so we
186199ebb4caSwyllys 		 * are assured of NOT getting ASN.1 output returned.
186299ebb4caSwyllys 		 * KMF does not want ASN.1 encoded results because
186399ebb4caSwyllys 		 * not all mechanisms return ASN.1 encodings (PKCS#11
186499ebb4caSwyllys 		 * and NSS return raw signature data).
186599ebb4caSwyllys 		 */
186699ebb4caSwyllys 		EVP_MD_CTX_init(&ctx);
186799ebb4caSwyllys 		(void) EVP_DigestInit_ex(&ctx, md, NULL);
186899ebb4caSwyllys 		(void) EVP_DigestUpdate(&ctx, tobesigned->Data,
186999ebb4caSwyllys 		    tobesigned->Length);
187099ebb4caSwyllys 		(void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
187199ebb4caSwyllys 
1872e65e5c2dSWyllys Ingersoll 		/* Only sign first 20 bytes for SHA2 */
1873e65e5c2dSWyllys Ingersoll 		if (AlgId == KMF_ALGID_SHA256WithDSA)
1874e65e5c2dSWyllys Ingersoll 			hashlen = 20;
187599ebb4caSwyllys 		dsasig = DSA_do_sign(hash, hashlen, dsa);
187699ebb4caSwyllys 		if (dsasig != NULL) {
187799ebb4caSwyllys 			int i;
1878e65e5c2dSWyllys Ingersoll 			output->Length = i = fixbnlen(dsasig->r, output->Data,
1879e65e5c2dSWyllys Ingersoll 			    hashlen);
1880*2c9a247fSWyllys Ingersoll 
1881e65e5c2dSWyllys Ingersoll 			output->Length += fixbnlen(dsasig->s, &output->Data[i],
1882e65e5c2dSWyllys Ingersoll 			    hashlen);
1883*2c9a247fSWyllys Ingersoll 
188499ebb4caSwyllys 			DSA_SIG_free(dsasig);
188599ebb4caSwyllys 		} else {
188699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
188799ebb4caSwyllys 		}
1888e65e5c2dSWyllys Ingersoll 		(void) EVP_MD_CTX_cleanup(&ctx);
188999ebb4caSwyllys 	} else {
189099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
189199ebb4caSwyllys 	}
189299ebb4caSwyllys cleanup:
189399ebb4caSwyllys 	return (ret);
189499ebb4caSwyllys }
189599ebb4caSwyllys 
189699ebb4caSwyllys KMF_RETURN
189799ebb4caSwyllys /*ARGSUSED*/
189830a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle,
189930a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
190099ebb4caSwyllys {
190199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
190230a5e8faSwyllys 	KMF_KEY_HANDLE *key;
190330a5e8faSwyllys 	boolean_t destroy = B_TRUE;
190430a5e8faSwyllys 
190530a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
190699ebb4caSwyllys 	if (key == NULL || key->keyp == NULL)
190799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
190899ebb4caSwyllys 
190930a5e8faSwyllys 	rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
191030a5e8faSwyllys 	    (void *)&destroy, NULL);
191130a5e8faSwyllys 	if (rv != KMF_OK) {
191230a5e8faSwyllys 		/* "destroy" is optional. Default is TRUE */
191330a5e8faSwyllys 		rv = KMF_OK;
191430a5e8faSwyllys 	}
191530a5e8faSwyllys 
191699ebb4caSwyllys 	if (key->keyclass != KMF_ASYM_PUB &&
191799ebb4caSwyllys 	    key->keyclass != KMF_ASYM_PRI &&
191899ebb4caSwyllys 	    key->keyclass != KMF_SYMMETRIC)
191999ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
192099ebb4caSwyllys 
192199ebb4caSwyllys 	if (key->keyclass == KMF_SYMMETRIC) {
192230a5e8faSwyllys 		kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
192399ebb4caSwyllys 		key->keyp = NULL;
192499ebb4caSwyllys 	} else {
192599ebb4caSwyllys 		if (key->keyp != NULL) {
192699ebb4caSwyllys 			EVP_PKEY_free(key->keyp);
192799ebb4caSwyllys 			key->keyp = NULL;
192899ebb4caSwyllys 		}
192999ebb4caSwyllys 	}
193099ebb4caSwyllys 
193199ebb4caSwyllys 	if (key->keylabel != NULL) {
193299ebb4caSwyllys 		EVP_PKEY *pkey = NULL;
193399ebb4caSwyllys 		/* If the file exists, make sure it is a proper key. */
193499ebb4caSwyllys 		pkey = openssl_load_key(handle, key->keylabel);
193599ebb4caSwyllys 		if (pkey == NULL) {
19365b3e1433Swyllys 			if (key->keylabel != NULL) {
193799ebb4caSwyllys 				free(key->keylabel);
193899ebb4caSwyllys 				key->keylabel = NULL;
19395b3e1433Swyllys 			}
194099ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
194199ebb4caSwyllys 		}
194299ebb4caSwyllys 		EVP_PKEY_free(pkey);
194399ebb4caSwyllys 
194499ebb4caSwyllys 		if (destroy) {
194599ebb4caSwyllys 			if (unlink(key->keylabel) != 0) {
194699ebb4caSwyllys 				KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
194799ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
194899ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
194999ebb4caSwyllys 			}
195099ebb4caSwyllys 		}
195199ebb4caSwyllys 		if (key->keylabel != NULL) {
195299ebb4caSwyllys 			free(key->keylabel);
195399ebb4caSwyllys 			key->keylabel = NULL;
195499ebb4caSwyllys 		}
195599ebb4caSwyllys 	}
195699ebb4caSwyllys 	return (rv);
195799ebb4caSwyllys }
195899ebb4caSwyllys 
195999ebb4caSwyllys KMF_RETURN
196099ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
196199ebb4caSwyllys {
196299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
196399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
196499ebb4caSwyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
196599ebb4caSwyllys 
196699ebb4caSwyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
196799ebb4caSwyllys 	if (strlen(str)) {
196899ebb4caSwyllys 		*msgstr = (char *)strdup(str);
196999ebb4caSwyllys 		if ((*msgstr) == NULL)
197099ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
197199ebb4caSwyllys 	} else {
197299ebb4caSwyllys 		*msgstr = NULL;
197399ebb4caSwyllys 	}
197499ebb4caSwyllys 
197599ebb4caSwyllys 	return (ret);
197699ebb4caSwyllys }
197799ebb4caSwyllys 
197899ebb4caSwyllys static int
197999ebb4caSwyllys ext2NID(int kmfext)
198099ebb4caSwyllys {
198199ebb4caSwyllys 	switch (kmfext) {
198299ebb4caSwyllys 		case KMF_X509_EXT_KEY_USAGE:
198399ebb4caSwyllys 			return (NID_key_usage);
198499ebb4caSwyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
198599ebb4caSwyllys 			return (NID_private_key_usage_period);
198699ebb4caSwyllys 		case KMF_X509_EXT_CERT_POLICIES:
198799ebb4caSwyllys 			return (NID_certificate_policies);
198899ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
198999ebb4caSwyllys 			return (NID_subject_alt_name);
199099ebb4caSwyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
199199ebb4caSwyllys 			return (NID_issuer_alt_name);
199299ebb4caSwyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
199399ebb4caSwyllys 			return (NID_basic_constraints);
199499ebb4caSwyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
199599ebb4caSwyllys 			return (NID_ext_key_usage);
199699ebb4caSwyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
199799ebb4caSwyllys 			return (NID_authority_key_identifier);
199899ebb4caSwyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
199999ebb4caSwyllys 			return (NID_crl_distribution_points);
200099ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
200199ebb4caSwyllys 			return (NID_subject_key_identifier);
200299ebb4caSwyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
200399ebb4caSwyllys 			return (OBJ_sn2nid("policyMappings"));
200499ebb4caSwyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
200599ebb4caSwyllys 			return (OBJ_sn2nid("nameConstraints"));
200699ebb4caSwyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
200799ebb4caSwyllys 			return (OBJ_sn2nid("policyConstraints"));
200899ebb4caSwyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
200999ebb4caSwyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
201099ebb4caSwyllys 		case KMF_X509_EXT_FRESHEST_CRL:
201199ebb4caSwyllys 			return (OBJ_sn2nid("freshestCRL"));
201299ebb4caSwyllys 		default:
201399ebb4caSwyllys 			return (NID_undef);
201499ebb4caSwyllys 	}
201599ebb4caSwyllys }
201699ebb4caSwyllys 
201799ebb4caSwyllys KMF_RETURN
201899ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
201999ebb4caSwyllys 	KMF_PRINTABLE_ITEM flag, char *resultStr)
202099ebb4caSwyllys {
202199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
202299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
202399ebb4caSwyllys 	X509 *xcert = NULL;
202499ebb4caSwyllys 	unsigned char *outbuf = NULL;
202599ebb4caSwyllys 	unsigned char *outbuf_p;
202699ebb4caSwyllys 	char *tmpstr = NULL;
202799ebb4caSwyllys 	int j;
202899ebb4caSwyllys 	int ext_index, nid, len;
202999ebb4caSwyllys 	BIO *mem = NULL;
203099ebb4caSwyllys 	STACK *emlst = NULL;
203199ebb4caSwyllys 	X509_EXTENSION *ex;
203299ebb4caSwyllys 	X509_CINF *ci;
203399ebb4caSwyllys 
203499ebb4caSwyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
203599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
203699ebb4caSwyllys 	}
203799ebb4caSwyllys 
203899ebb4caSwyllys 	/* copy cert data to outbuf */
203999ebb4caSwyllys 	outbuf = malloc(pcert->Length);
204099ebb4caSwyllys 	if (outbuf == NULL) {
204199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
204299ebb4caSwyllys 	}
204399ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
204499ebb4caSwyllys 
204599ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
204699ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
204799ebb4caSwyllys 	if (xcert == NULL) {
204899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
204999ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
205099ebb4caSwyllys 		goto out;
205199ebb4caSwyllys 	}
205299ebb4caSwyllys 
205399ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
205499ebb4caSwyllys 	if (mem == NULL) {
205599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
205699ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
205799ebb4caSwyllys 		goto out;
205899ebb4caSwyllys 	}
205999ebb4caSwyllys 
206099ebb4caSwyllys 	switch (flag) {
206199ebb4caSwyllys 	case KMF_CERT_ISSUER:
206299ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
206399ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
206499ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
206599ebb4caSwyllys 		break;
206699ebb4caSwyllys 
206799ebb4caSwyllys 	case KMF_CERT_SUBJECT:
206899ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
206999ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
207099ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
207199ebb4caSwyllys 		break;
207299ebb4caSwyllys 
207399ebb4caSwyllys 	case KMF_CERT_VERSION:
207499ebb4caSwyllys 		tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version);
207599ebb4caSwyllys 		(void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN);
207699ebb4caSwyllys 		OPENSSL_free(tmpstr);
207799ebb4caSwyllys 		len = strlen(resultStr);
207899ebb4caSwyllys 		break;
207999ebb4caSwyllys 
208099ebb4caSwyllys 	case KMF_CERT_SERIALNUM:
208199ebb4caSwyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
208299ebb4caSwyllys 			(void) strcpy(resultStr, "0x");
208399ebb4caSwyllys 			len = BIO_gets(mem, &resultStr[2],
208499ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN - 2);
208599ebb4caSwyllys 		}
208699ebb4caSwyllys 		break;
208799ebb4caSwyllys 
208899ebb4caSwyllys 	case KMF_CERT_NOTBEFORE:
208999ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notBefore(xcert));
209099ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
209199ebb4caSwyllys 		break;
209299ebb4caSwyllys 
209399ebb4caSwyllys 	case KMF_CERT_NOTAFTER:
209499ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notAfter(xcert));
209599ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
209699ebb4caSwyllys 		break;
209799ebb4caSwyllys 
209899ebb4caSwyllys 	case KMF_CERT_PUBKEY_DATA:
209999ebb4caSwyllys 		{
210099ebb4caSwyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
210199ebb4caSwyllys 			if (pkey == NULL) {
210299ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
210399ebb4caSwyllys 				ret = KMF_ERR_ENCODING;
210499ebb4caSwyllys 				goto out;
210599ebb4caSwyllys 			}
210699ebb4caSwyllys 
210799ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
210899ebb4caSwyllys 				(void) BIO_printf(mem,
210999ebb4caSwyllys 				    "RSA Public Key: (%d bit)\n",
211099ebb4caSwyllys 				    BN_num_bits(pkey->pkey.rsa->n));
211199ebb4caSwyllys 				(void) RSA_print(mem, pkey->pkey.rsa, 0);
211299ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
211399ebb4caSwyllys 				(void) BIO_printf(mem,
211499ebb4caSwyllys 				    "%12sDSA Public Key:\n", "");
211599ebb4caSwyllys 				(void) DSA_print(mem, pkey->pkey.dsa, 0);
211699ebb4caSwyllys 			} else {
211799ebb4caSwyllys 				(void) BIO_printf(mem,
211899ebb4caSwyllys 				    "%12sUnknown Public Key:\n", "");
211999ebb4caSwyllys 			}
212099ebb4caSwyllys 			(void) BIO_printf(mem, "\n");
212199ebb4caSwyllys 			EVP_PKEY_free(pkey);
212299ebb4caSwyllys 		}
212399ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
212499ebb4caSwyllys 		break;
212599ebb4caSwyllys 	case KMF_CERT_SIGNATURE_ALG:
212699ebb4caSwyllys 	case KMF_CERT_PUBKEY_ALG:
212799ebb4caSwyllys 		if (flag == KMF_CERT_SIGNATURE_ALG) {
212899ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
212999ebb4caSwyllys 			    xcert->sig_alg->algorithm);
213099ebb4caSwyllys 		} else {
213199ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
213299ebb4caSwyllys 			    xcert->cert_info->key->algor->algorithm);
213399ebb4caSwyllys 		}
213499ebb4caSwyllys 
213599ebb4caSwyllys 		if (len > 0) {
213699ebb4caSwyllys 			len = BIO_read(mem, resultStr,
213799ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN);
213899ebb4caSwyllys 		}
213999ebb4caSwyllys 		break;
214099ebb4caSwyllys 
214199ebb4caSwyllys 	case KMF_CERT_EMAIL:
214299ebb4caSwyllys 		emlst = X509_get1_email(xcert);
214399ebb4caSwyllys 		for (j = 0; j < sk_num(emlst); j++)
214499ebb4caSwyllys 			(void) BIO_printf(mem, "%s\n", sk_value(emlst, j));
214599ebb4caSwyllys 
214699ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
214799ebb4caSwyllys 		X509_email_free(emlst);
214899ebb4caSwyllys 		break;
214999ebb4caSwyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
215099ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
215199ebb4caSwyllys 	case KMF_X509_EXT_KEY_USAGE:
215299ebb4caSwyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
215399ebb4caSwyllys 	case KMF_X509_EXT_CERT_POLICIES:
215499ebb4caSwyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
215599ebb4caSwyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
215699ebb4caSwyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
215799ebb4caSwyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
215899ebb4caSwyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
215999ebb4caSwyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
216099ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
216199ebb4caSwyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
216299ebb4caSwyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
216399ebb4caSwyllys 	case KMF_X509_EXT_FRESHEST_CRL:
216499ebb4caSwyllys 		nid = ext2NID(flag);
216599ebb4caSwyllys 		if (nid == NID_undef) {
216699ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
216799ebb4caSwyllys 			goto out;
216899ebb4caSwyllys 		}
216999ebb4caSwyllys 		ci = xcert->cert_info;
217099ebb4caSwyllys 
217199ebb4caSwyllys 		ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1);
217299ebb4caSwyllys 		if (ext_index == -1) {
217399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
217499ebb4caSwyllys 
217599ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
217699ebb4caSwyllys 			goto out;
217799ebb4caSwyllys 		}
217899ebb4caSwyllys 		ex = X509v3_get_ext(ci->extensions, ext_index);
217999ebb4caSwyllys 
218099ebb4caSwyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
218199ebb4caSwyllys 
218299ebb4caSwyllys 		if (BIO_printf(mem, ": %s\n",
218330a5e8faSwyllys 		    X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
218499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
218599ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
218699ebb4caSwyllys 			goto out;
218799ebb4caSwyllys 		}
218899ebb4caSwyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
218999ebb4caSwyllys 			(void) BIO_printf(mem, "%*s", 4, "");
219099ebb4caSwyllys 			(void) M_ASN1_OCTET_STRING_print(mem, ex->value);
219199ebb4caSwyllys 		}
219299ebb4caSwyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
219399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
219499ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
219599ebb4caSwyllys 			goto out;
219699ebb4caSwyllys 		}
219799ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
219899ebb4caSwyllys 	}
219999ebb4caSwyllys 	if (len <= 0) {
220099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
220199ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
220299ebb4caSwyllys 	}
220399ebb4caSwyllys 
220499ebb4caSwyllys out:
220599ebb4caSwyllys 	if (outbuf != NULL) {
220699ebb4caSwyllys 		free(outbuf);
220799ebb4caSwyllys 	}
220899ebb4caSwyllys 
220999ebb4caSwyllys 	if (xcert != NULL) {
221099ebb4caSwyllys 		X509_free(xcert);
221199ebb4caSwyllys 	}
221299ebb4caSwyllys 
221399ebb4caSwyllys 	if (mem != NULL) {
221499ebb4caSwyllys 		(void) BIO_free(mem);
221599ebb4caSwyllys 	}
221699ebb4caSwyllys 
221799ebb4caSwyllys 	return (ret);
221899ebb4caSwyllys }
221930a5e8faSwyllys 
222099ebb4caSwyllys KMF_RETURN
222199ebb4caSwyllys /*ARGSUSED*/
222230a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
222330a5e8faSwyllys     KMF_ATTRIBUTE *attrlist)
222499ebb4caSwyllys {
222599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
222630a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
222730a5e8faSwyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
222830a5e8faSwyllys 	KMF_KEY_HANDLE *key = NULL;
222930a5e8faSwyllys 	uint32_t numkeys = 1; /* 1 key only */
223030a5e8faSwyllys 	char *dirpath = NULL;
223130a5e8faSwyllys 	char *keyfile = NULL;
223230a5e8faSwyllys 	KMF_ATTRIBUTE new_attrlist[16];
223330a5e8faSwyllys 	int i = 0;
223499ebb4caSwyllys 
223599ebb4caSwyllys 	/*
223699ebb4caSwyllys 	 * This is really just a FindKey operation, reuse the
223799ebb4caSwyllys 	 * FindKey function.
223899ebb4caSwyllys 	 */
223930a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
224030a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
224130a5e8faSwyllys 	i++;
224299ebb4caSwyllys 
224330a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
224430a5e8faSwyllys 	    KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
224530a5e8faSwyllys 	i++;
224699ebb4caSwyllys 
224730a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
224830a5e8faSwyllys 	    KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
224930a5e8faSwyllys 	i++;
225030a5e8faSwyllys 
225130a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
225230a5e8faSwyllys 	if (key == NULL) {
225330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
225430a5e8faSwyllys 	} else {
225530a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
225630a5e8faSwyllys 		    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
225730a5e8faSwyllys 		i++;
225830a5e8faSwyllys 	}
225930a5e8faSwyllys 
226030a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
226130a5e8faSwyllys 	if (dirpath != NULL) {
226230a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
226330a5e8faSwyllys 		    KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
226430a5e8faSwyllys 		i++;
226530a5e8faSwyllys 	}
226630a5e8faSwyllys 
226730a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
226830a5e8faSwyllys 	if (keyfile == NULL)
226930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
227030a5e8faSwyllys 	else {
227130a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
227230a5e8faSwyllys 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
227330a5e8faSwyllys 		i++;
227430a5e8faSwyllys 	}
227530a5e8faSwyllys 
227630a5e8faSwyllys 	rv = OpenSSL_FindKey(handle, i, new_attrlist);
227799ebb4caSwyllys 	return (rv);
227899ebb4caSwyllys }
227999ebb4caSwyllys 
228099ebb4caSwyllys KMF_RETURN
228199ebb4caSwyllys /*ARGSUSED*/
228299ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
228399ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
228499ebb4caSwyllys 	KMF_DATA *output)
228599ebb4caSwyllys {
228699ebb4caSwyllys 	KMF_RETURN		ret = KMF_OK;
228799ebb4caSwyllys 	RSA *rsa = NULL;
228899ebb4caSwyllys 	unsigned int in_len = 0, out_len = 0;
228999ebb4caSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
229099ebb4caSwyllys 	uint8_t *in_data, *out_data;
229199ebb4caSwyllys 	int i, blocks;
229299ebb4caSwyllys 
229399ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
229499ebb4caSwyllys 	    ciphertext == NULL || output == NULL ||
229599ebb4caSwyllys 	    ciphertext->Data == NULL ||
229699ebb4caSwyllys 	    output->Data == NULL)
229799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
229899ebb4caSwyllys 
229999ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
230099ebb4caSwyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
230199ebb4caSwyllys 		modulus_len = RSA_size(rsa);
230299ebb4caSwyllys 	} else {
230399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
230499ebb4caSwyllys 	}
230599ebb4caSwyllys 
230699ebb4caSwyllys 	blocks = ciphertext->Length/modulus_len;
230799ebb4caSwyllys 	out_data = output->Data;
230899ebb4caSwyllys 	in_data = ciphertext->Data;
230999ebb4caSwyllys 	out_len = modulus_len - 11;
231099ebb4caSwyllys 	in_len = modulus_len;
231199ebb4caSwyllys 
231299ebb4caSwyllys 	for (i = 0; i < blocks; i++) {
231399ebb4caSwyllys 		out_len  = RSA_private_decrypt(in_len,
231499ebb4caSwyllys 		    in_data, out_data, rsa, RSA_PKCS1_PADDING);
231599ebb4caSwyllys 
231699ebb4caSwyllys 		if (out_len == 0) {
231799ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
231899ebb4caSwyllys 			goto cleanup;
231999ebb4caSwyllys 		}
232099ebb4caSwyllys 
232199ebb4caSwyllys 		out_data += out_len;
232299ebb4caSwyllys 		total_decrypted += out_len;
232399ebb4caSwyllys 		in_data += in_len;
232499ebb4caSwyllys 	}
232599ebb4caSwyllys 
232699ebb4caSwyllys 	output->Length = total_decrypted;
232799ebb4caSwyllys 
232899ebb4caSwyllys cleanup:
232999ebb4caSwyllys 	RSA_free(rsa);
233099ebb4caSwyllys 	if (ret != KMF_OK)
233199ebb4caSwyllys 		output->Length = 0;
233299ebb4caSwyllys 
233399ebb4caSwyllys 	return (ret);
233499ebb4caSwyllys 
233599ebb4caSwyllys }
233699ebb4caSwyllys 
233799ebb4caSwyllys /*
233899ebb4caSwyllys  *  This function will create a certid from issuer_cert and user_cert.
233999ebb4caSwyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
234099ebb4caSwyllys  *  certid memory after use.
234199ebb4caSwyllys  */
234299ebb4caSwyllys static KMF_RETURN
234399ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
234499ebb4caSwyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
234599ebb4caSwyllys {
234699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
234799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
234899ebb4caSwyllys 	X509   *issuer = NULL;
234999ebb4caSwyllys 	X509   *cert = NULL;
235099ebb4caSwyllys 	unsigned char *ptmp;
235199ebb4caSwyllys 
235299ebb4caSwyllys 	if (issuer_cert == NULL || user_cert == NULL) {
235399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
235499ebb4caSwyllys 	}
235599ebb4caSwyllys 
235699ebb4caSwyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
235799ebb4caSwyllys 	ptmp = issuer_cert->Data;
235899ebb4caSwyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
235999ebb4caSwyllys 	    issuer_cert->Length);
236099ebb4caSwyllys 	if (issuer == NULL) {
236199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
236299ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
236399ebb4caSwyllys 		goto end;
236499ebb4caSwyllys 	}
236599ebb4caSwyllys 
236699ebb4caSwyllys 	/* convert the DER-encoded user cert to an internal X509 */
236799ebb4caSwyllys 	ptmp = user_cert->Data;
236899ebb4caSwyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
236999ebb4caSwyllys 	    user_cert->Length);
237099ebb4caSwyllys 	if (cert == NULL) {
237199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
237299ebb4caSwyllys 
237399ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
237499ebb4caSwyllys 		goto end;
237599ebb4caSwyllys 	}
237699ebb4caSwyllys 
237799ebb4caSwyllys 	/* create a CERTID */
237899ebb4caSwyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
237999ebb4caSwyllys 	if (*certid == NULL) {
238099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
238199ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
238299ebb4caSwyllys 		goto end;
238399ebb4caSwyllys 	}
238499ebb4caSwyllys 
238599ebb4caSwyllys end:
238699ebb4caSwyllys 	if (issuer != NULL) {
238799ebb4caSwyllys 		X509_free(issuer);
238899ebb4caSwyllys 	}
238999ebb4caSwyllys 
239099ebb4caSwyllys 	if (cert != NULL) {
239199ebb4caSwyllys 		X509_free(cert);
239299ebb4caSwyllys 	}
239399ebb4caSwyllys 
239499ebb4caSwyllys 	return (ret);
239599ebb4caSwyllys }
239699ebb4caSwyllys 
239799ebb4caSwyllys KMF_RETURN
239830a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
239930a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
240099ebb4caSwyllys {
240199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
240299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
240399ebb4caSwyllys 	OCSP_CERTID *id = NULL;
240499ebb4caSwyllys 	OCSP_REQUEST *req = NULL;
240599ebb4caSwyllys 	BIO *derbio = NULL;
240630a5e8faSwyllys 	char *reqfile;
240730a5e8faSwyllys 	KMF_DATA *issuer_cert;
240830a5e8faSwyllys 	KMF_DATA *user_cert;
240999ebb4caSwyllys 
241030a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
241130a5e8faSwyllys 	    attrlist, numattr);
241230a5e8faSwyllys 	if (user_cert == NULL)
241399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
241499ebb4caSwyllys 
241530a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
241630a5e8faSwyllys 	    attrlist, numattr);
241730a5e8faSwyllys 	if (issuer_cert == NULL)
241830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
241930a5e8faSwyllys 
242030a5e8faSwyllys 	reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
242130a5e8faSwyllys 	    attrlist, numattr);
242230a5e8faSwyllys 	if (reqfile == NULL)
242330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
242430a5e8faSwyllys 
242530a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
242699ebb4caSwyllys 	if (ret != KMF_OK) {
242799ebb4caSwyllys 		return (ret);
242899ebb4caSwyllys 	}
242999ebb4caSwyllys 
243099ebb4caSwyllys 	/* Create an OCSP request */
243199ebb4caSwyllys 	req = OCSP_REQUEST_new();
243299ebb4caSwyllys 	if (req == NULL) {
243399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
243499ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
243599ebb4caSwyllys 		goto end;
243699ebb4caSwyllys 	}
243799ebb4caSwyllys 
243899ebb4caSwyllys 	if (!OCSP_request_add0_id(req, id)) {
243999ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
244099ebb4caSwyllys 		goto end;
244199ebb4caSwyllys 	}
244299ebb4caSwyllys 
244399ebb4caSwyllys 	/* Write the request to the output file with DER encoding */
244499ebb4caSwyllys 	derbio = BIO_new_file(reqfile, "wb");
244599ebb4caSwyllys 	if (!derbio) {
244699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
244799ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
244899ebb4caSwyllys 		goto end;
244999ebb4caSwyllys 	}
245099ebb4caSwyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
245199ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
245299ebb4caSwyllys 	}
245399ebb4caSwyllys 
245499ebb4caSwyllys end:
245599ebb4caSwyllys 	/*
2456e65e5c2dSWyllys Ingersoll 	 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2457a2d4930dSDan OpenSolaris Anderson 	 * will also deallocate certid's space.
245899ebb4caSwyllys 	 */
245999ebb4caSwyllys 	if (req != NULL) {
246099ebb4caSwyllys 		OCSP_REQUEST_free(req);
246199ebb4caSwyllys 	}
246299ebb4caSwyllys 
246399ebb4caSwyllys 	if (derbio != NULL) {
246499ebb4caSwyllys 		(void) BIO_free(derbio);
246599ebb4caSwyllys 	}
246699ebb4caSwyllys 
246799ebb4caSwyllys 	return (ret);
246899ebb4caSwyllys }
246999ebb4caSwyllys 
247099ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */
247199ebb4caSwyllys static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
247299ebb4caSwyllys {
247399ebb4caSwyllys 	int i;
247499ebb4caSwyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
247599ebb4caSwyllys 
247699ebb4caSwyllys 	/* Easy if lookup by name */
247799ebb4caSwyllys 	if (id->type == V_OCSP_RESPID_NAME)
247899ebb4caSwyllys 		return (X509_find_by_subject(certs, id->value.byName));
247999ebb4caSwyllys 
248099ebb4caSwyllys 	/* Lookup by key hash */
248199ebb4caSwyllys 
248299ebb4caSwyllys 	/* If key hash isn't SHA1 length then forget it */
248399ebb4caSwyllys 	if (id->value.byKey->length != SHA_DIGEST_LENGTH)
248499ebb4caSwyllys 		return (NULL);
248599ebb4caSwyllys 
248699ebb4caSwyllys 	keyhash = id->value.byKey->data;
248799ebb4caSwyllys 	/* Calculate hash of each key and compare */
248899ebb4caSwyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
2489a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
249099ebb4caSwyllys 		X509 *x = sk_X509_value(certs, i);
24915b3e1433Swyllys 		/* Use pubkey_digest to get the key ID value */
249299ebb4caSwyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
249399ebb4caSwyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
249499ebb4caSwyllys 			return (x);
249599ebb4caSwyllys 	}
249699ebb4caSwyllys 	return (NULL);
249799ebb4caSwyllys }
249899ebb4caSwyllys 
249999ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */
2500a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */
250199ebb4caSwyllys static int
250299ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
250399ebb4caSwyllys     X509_STORE *st, unsigned long flags)
250499ebb4caSwyllys {
250599ebb4caSwyllys 	X509 *signer;
250699ebb4caSwyllys 	OCSP_RESPID *rid = bs->tbsResponseData->responderId;
250799ebb4caSwyllys 	if ((signer = ocsp_find_signer_sk(certs, rid)))	{
250899ebb4caSwyllys 		*psigner = signer;
250999ebb4caSwyllys 		return (2);
251099ebb4caSwyllys 	}
251199ebb4caSwyllys 	if (!(flags & OCSP_NOINTERN) &&
251299ebb4caSwyllys 	    (signer = ocsp_find_signer_sk(bs->certs, rid))) {
251399ebb4caSwyllys 		*psigner = signer;
251499ebb4caSwyllys 		return (1);
251599ebb4caSwyllys 	}
251699ebb4caSwyllys 	/* Maybe lookup from store if by subject name */
251799ebb4caSwyllys 
251899ebb4caSwyllys 	*psigner = NULL;
251999ebb4caSwyllys 	return (0);
252099ebb4caSwyllys }
252199ebb4caSwyllys 
252299ebb4caSwyllys /*
252399ebb4caSwyllys  * This function will verify the signature of a basic response, using
252499ebb4caSwyllys  * the public key from the OCSP responder certificate.
252599ebb4caSwyllys  */
252699ebb4caSwyllys static KMF_RETURN
252799ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
252899ebb4caSwyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
252999ebb4caSwyllys {
253099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
253199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
253299ebb4caSwyllys 	STACK_OF(X509) *cert_stack = NULL;
253399ebb4caSwyllys 	X509 *signer = NULL;
253499ebb4caSwyllys 	X509 *issuer = NULL;
253599ebb4caSwyllys 	EVP_PKEY *skey = NULL;
253699ebb4caSwyllys 	unsigned char *ptmp;
253799ebb4caSwyllys 
253899ebb4caSwyllys 
253999ebb4caSwyllys 	if (bs == NULL || issuer_cert == NULL)
254099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
254199ebb4caSwyllys 
254299ebb4caSwyllys 	/*
254399ebb4caSwyllys 	 * Find the certificate that signed the basic response.
254499ebb4caSwyllys 	 *
254599ebb4caSwyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
254699ebb4caSwyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
254799ebb4caSwyllys 	 * If we still do not find a signer, we will look for it from the
254899ebb4caSwyllys 	 * certificate list came with the response file.
254999ebb4caSwyllys 	 */
255099ebb4caSwyllys 	if (signer_cert != NULL) {
255199ebb4caSwyllys 		ptmp = signer_cert->Data;
255299ebb4caSwyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
255399ebb4caSwyllys 		    signer_cert->Length);
255499ebb4caSwyllys 		if (signer == NULL) {
255599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
255699ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
255799ebb4caSwyllys 			goto end;
255899ebb4caSwyllys 		}
255999ebb4caSwyllys 	} else {
256099ebb4caSwyllys 		/*
256199ebb4caSwyllys 		 * Convert the issuer cert into X509 and push it into a
256299ebb4caSwyllys 		 * stack to be used by ocsp_find_signer().
256399ebb4caSwyllys 		 */
256499ebb4caSwyllys 		ptmp = issuer_cert->Data;
256599ebb4caSwyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
256699ebb4caSwyllys 		    issuer_cert->Length);
256799ebb4caSwyllys 		if (issuer == NULL) {
256899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
256999ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
257099ebb4caSwyllys 			goto end;
257199ebb4caSwyllys 		}
257299ebb4caSwyllys 
257399ebb4caSwyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
257499ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
257599ebb4caSwyllys 			goto end;
257699ebb4caSwyllys 		}
257799ebb4caSwyllys 
257899ebb4caSwyllys 		if (sk_X509_push(cert_stack, issuer) == NULL) {
257999ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
258099ebb4caSwyllys 			goto end;
258199ebb4caSwyllys 		}
258299ebb4caSwyllys 
258399ebb4caSwyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
258499ebb4caSwyllys 		if (!ret) {
258599ebb4caSwyllys 			/* can not find the signer */
258699ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
258799ebb4caSwyllys 			goto end;
258899ebb4caSwyllys 		}
258999ebb4caSwyllys 	}
259099ebb4caSwyllys 
259199ebb4caSwyllys 	/* Verify the signature of the response */
259299ebb4caSwyllys 	skey = X509_get_pubkey(signer);
259399ebb4caSwyllys 	if (skey == NULL) {
259499ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
259599ebb4caSwyllys 		goto end;
259699ebb4caSwyllys 	}
259799ebb4caSwyllys 
259899ebb4caSwyllys 	ret = OCSP_BASICRESP_verify(bs, skey, 0);
259999ebb4caSwyllys 	if (ret == 0) {
260099ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
260199ebb4caSwyllys 		goto end;
260299ebb4caSwyllys 	}
260399ebb4caSwyllys 
260499ebb4caSwyllys end:
260599ebb4caSwyllys 	if (issuer != NULL) {
260699ebb4caSwyllys 		X509_free(issuer);
260799ebb4caSwyllys 	}
260899ebb4caSwyllys 
260999ebb4caSwyllys 	if (signer != NULL) {
261099ebb4caSwyllys 		X509_free(signer);
261199ebb4caSwyllys 	}
261299ebb4caSwyllys 
261399ebb4caSwyllys 	if (skey != NULL) {
261499ebb4caSwyllys 		EVP_PKEY_free(skey);
261599ebb4caSwyllys 	}
261699ebb4caSwyllys 
261799ebb4caSwyllys 	if (cert_stack != NULL) {
261899ebb4caSwyllys 		sk_X509_free(cert_stack);
261999ebb4caSwyllys 	}
262099ebb4caSwyllys 
262199ebb4caSwyllys 	return (ret);
262299ebb4caSwyllys }
262399ebb4caSwyllys 
262499ebb4caSwyllys 
262599ebb4caSwyllys 
262699ebb4caSwyllys KMF_RETURN
262799ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
262830a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
262999ebb4caSwyllys {
263099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
263199ebb4caSwyllys 	BIO *derbio = NULL;
263299ebb4caSwyllys 	OCSP_RESPONSE *resp = NULL;
263399ebb4caSwyllys 	OCSP_BASICRESP *bs = NULL;
263499ebb4caSwyllys 	OCSP_CERTID *id = NULL;
263599ebb4caSwyllys 	OCSP_SINGLERESP *single = NULL;
263699ebb4caSwyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
263799ebb4caSwyllys 	int index, status, reason;
263830a5e8faSwyllys 	KMF_DATA *issuer_cert;
263930a5e8faSwyllys 	KMF_DATA *user_cert;
264030a5e8faSwyllys 	KMF_DATA *signer_cert;
264130a5e8faSwyllys 	KMF_DATA *response;
264230a5e8faSwyllys 	int *response_reason, *response_status, *cert_status;
264330a5e8faSwyllys 	boolean_t ignore_response_sign = B_FALSE;	/* default is FALSE */
264430a5e8faSwyllys 	uint32_t response_lifetime;
264599ebb4caSwyllys 
264630a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
264730a5e8faSwyllys 	    attrlist, numattr);
264830a5e8faSwyllys 	if (issuer_cert == NULL)
264999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
265099ebb4caSwyllys 
265130a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
265230a5e8faSwyllys 	    attrlist, numattr);
265330a5e8faSwyllys 	if (user_cert == NULL)
265499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
265530a5e8faSwyllys 
265630a5e8faSwyllys 	response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
265730a5e8faSwyllys 	    attrlist, numattr);
265830a5e8faSwyllys 	if (response == NULL)
265930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
266030a5e8faSwyllys 
266130a5e8faSwyllys 	response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
266230a5e8faSwyllys 	    attrlist, numattr);
266330a5e8faSwyllys 	if (response_status == NULL)
266430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
266530a5e8faSwyllys 
266630a5e8faSwyllys 	response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
266730a5e8faSwyllys 	    attrlist, numattr);
266830a5e8faSwyllys 	if (response_reason == NULL)
266930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
267030a5e8faSwyllys 
267130a5e8faSwyllys 	cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
267230a5e8faSwyllys 	    attrlist, numattr);
267330a5e8faSwyllys 	if (cert_status == NULL)
267430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
267599ebb4caSwyllys 
267699ebb4caSwyllys 	/* Read in the response */
267730a5e8faSwyllys 	derbio = BIO_new_mem_buf(response->Data, response->Length);
267899ebb4caSwyllys 	if (!derbio) {
267999ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
268099ebb4caSwyllys 		return (ret);
268199ebb4caSwyllys 	}
268299ebb4caSwyllys 
268399ebb4caSwyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
268499ebb4caSwyllys 	if (resp == NULL) {
268599ebb4caSwyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
268699ebb4caSwyllys 		goto end;
268799ebb4caSwyllys 	}
268899ebb4caSwyllys 
268999ebb4caSwyllys 	/* Check the response status */
269099ebb4caSwyllys 	status = OCSP_response_status(resp);
269130a5e8faSwyllys 	*response_status = status;
269299ebb4caSwyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
269399ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
269499ebb4caSwyllys 		goto end;
269599ebb4caSwyllys 	}
269699ebb4caSwyllys 
269799ebb4caSwyllys #ifdef DEBUG
269899ebb4caSwyllys 	printf("Successfully checked the response file status.\n");
269999ebb4caSwyllys #endif /* DEBUG */
270099ebb4caSwyllys 
270199ebb4caSwyllys 	/* Extract basic response */
270299ebb4caSwyllys 	bs = OCSP_response_get1_basic(resp);
270399ebb4caSwyllys 	if (bs == NULL) {
270499ebb4caSwyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
270599ebb4caSwyllys 		goto end;
270699ebb4caSwyllys 	}
270799ebb4caSwyllys 
270899ebb4caSwyllys #ifdef DEBUG
270999ebb4caSwyllys 	printf("Successfully retrieved the basic response.\n");
271099ebb4caSwyllys #endif /* DEBUG */
271199ebb4caSwyllys 
271299ebb4caSwyllys 	/* Check the basic response signature if required */
271330a5e8faSwyllys 	ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
271430a5e8faSwyllys 	    (void *)&ignore_response_sign, NULL);
271530a5e8faSwyllys 	if (ret != KMF_OK)
271630a5e8faSwyllys 		ret = KMF_OK;
271730a5e8faSwyllys 
271830a5e8faSwyllys 	signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
271930a5e8faSwyllys 	    attrlist, numattr);
272030a5e8faSwyllys 
272130a5e8faSwyllys 	if (ignore_response_sign == B_FALSE) {
272299ebb4caSwyllys 		ret = check_response_signature(handle, bs,
272330a5e8faSwyllys 		    signer_cert, issuer_cert);
272499ebb4caSwyllys 		if (ret != KMF_OK)
272599ebb4caSwyllys 			goto end;
272699ebb4caSwyllys 	}
272799ebb4caSwyllys 
272899ebb4caSwyllys #ifdef DEBUG
272999ebb4caSwyllys 	printf("Successfully verified the response signature.\n");
273099ebb4caSwyllys #endif /* DEBUG */
273199ebb4caSwyllys 
273299ebb4caSwyllys 	/* Create a certid for the certificate in question */
273330a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
273499ebb4caSwyllys 	if (ret != KMF_OK) {
273599ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
273699ebb4caSwyllys 		goto end;
273799ebb4caSwyllys 	}
273899ebb4caSwyllys 
273999ebb4caSwyllys #ifdef DEBUG
274099ebb4caSwyllys 	printf("successfully created a certid for the cert.\n");
274199ebb4caSwyllys #endif /* DEBUG */
274299ebb4caSwyllys 
274399ebb4caSwyllys 	/* Find the index of the single response for the certid */
274499ebb4caSwyllys 	index = OCSP_resp_find(bs, id, -1);
274599ebb4caSwyllys 	if (index < 0) {
274699ebb4caSwyllys 		/* cound not find this certificate in the response */
274799ebb4caSwyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
274899ebb4caSwyllys 		goto end;
274999ebb4caSwyllys 	}
275099ebb4caSwyllys 
275199ebb4caSwyllys #ifdef DEBUG
275299ebb4caSwyllys 	printf("Successfully found the single response index for the cert.\n");
275399ebb4caSwyllys #endif /* DEBUG */
275499ebb4caSwyllys 
275599ebb4caSwyllys 	/* Retrieve the single response and get the cert status */
275699ebb4caSwyllys 	single = OCSP_resp_get0(bs, index);
275799ebb4caSwyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
275899ebb4caSwyllys 	    &nextupd);
275999ebb4caSwyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
276030a5e8faSwyllys 		*cert_status = OCSP_GOOD;
276199ebb4caSwyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
276230a5e8faSwyllys 		*cert_status = OCSP_UNKNOWN;
276399ebb4caSwyllys 	} else { /* revoked */
276430a5e8faSwyllys 		*cert_status = OCSP_REVOKED;
276530a5e8faSwyllys 		*response_reason = reason;
276699ebb4caSwyllys 	}
276799ebb4caSwyllys 	ret = KMF_OK;
276899ebb4caSwyllys 
276930a5e8faSwyllys 	/* resp. time is optional, so we don't care about the return code. */
277030a5e8faSwyllys 	(void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
277130a5e8faSwyllys 	    (void *)&response_lifetime, NULL);
277230a5e8faSwyllys 
277399ebb4caSwyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
277430a5e8faSwyllys 	    response_lifetime)) {
277599ebb4caSwyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
277699ebb4caSwyllys 		goto end;
277799ebb4caSwyllys 	}
277899ebb4caSwyllys 
277999ebb4caSwyllys #ifdef DEBUG
278099ebb4caSwyllys 	printf("Successfully verify the time.\n");
278199ebb4caSwyllys #endif /* DEBUG */
278299ebb4caSwyllys 
278399ebb4caSwyllys end:
278499ebb4caSwyllys 	if (derbio != NULL)
278599ebb4caSwyllys 		(void) BIO_free(derbio);
278699ebb4caSwyllys 
278799ebb4caSwyllys 	if (resp != NULL)
278899ebb4caSwyllys 		OCSP_RESPONSE_free(resp);
278999ebb4caSwyllys 
279099ebb4caSwyllys 	if (bs != NULL)
279199ebb4caSwyllys 		OCSP_BASICRESP_free(bs);
279299ebb4caSwyllys 
279399ebb4caSwyllys 	if (id != NULL)
279499ebb4caSwyllys 		OCSP_CERTID_free(id);
279599ebb4caSwyllys 
279699ebb4caSwyllys 	return (ret);
279799ebb4caSwyllys }
279899ebb4caSwyllys 
279999ebb4caSwyllys static KMF_RETURN
280099ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path,
280199ebb4caSwyllys 	KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
280299ebb4caSwyllys {
280399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
280430a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
280599ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
280699ebb4caSwyllys 
280799ebb4caSwyllys 	if (keyclass == KMF_ASYM_PRI ||
280899ebb4caSwyllys 	    keyclass == KMF_ASYM_PUB) {
280999ebb4caSwyllys 		pkey = openssl_load_key(handle, path);
281099ebb4caSwyllys 		if (pkey == NULL) {
281199ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
281299ebb4caSwyllys 		}
281399ebb4caSwyllys 		if (key != NULL) {
281499ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA)
281599ebb4caSwyllys 				key->keyalg = KMF_RSA;
281699ebb4caSwyllys 			else if (pkey->type == EVP_PKEY_DSA)
281799ebb4caSwyllys 				key->keyalg = KMF_DSA;
281899ebb4caSwyllys 
281999ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
282099ebb4caSwyllys 			key->keyclass = keyclass;
282199ebb4caSwyllys 			key->keyp = (void *)pkey;
282299ebb4caSwyllys 			key->israw = FALSE;
28235b3e1433Swyllys 			if (path != NULL &&
28245b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
28255b3e1433Swyllys 				EVP_PKEY_free(pkey);
28265b3e1433Swyllys 				return (KMF_ERR_MEMORY);
28275b3e1433Swyllys 			}
282899ebb4caSwyllys 		} else {
282999ebb4caSwyllys 			EVP_PKEY_free(pkey);
283099ebb4caSwyllys 			pkey = NULL;
283199ebb4caSwyllys 		}
283299ebb4caSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
283399ebb4caSwyllys 		KMF_ENCODE_FORMAT fmt;
283499ebb4caSwyllys 		/*
283599ebb4caSwyllys 		 * If the file is a recognized format,
283699ebb4caSwyllys 		 * then it is NOT a symmetric key.
283799ebb4caSwyllys 		 */
283830a5e8faSwyllys 		rv = kmf_get_file_format(path, &fmt);
283999ebb4caSwyllys 		if (rv == KMF_OK || fmt != 0) {
284099ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
284199ebb4caSwyllys 		} else if (rv == KMF_ERR_ENCODING) {
284299ebb4caSwyllys 			/*
284399ebb4caSwyllys 			 * If we don't know the encoding,
284499ebb4caSwyllys 			 * it is probably  a symmetric key.
284599ebb4caSwyllys 			 */
284699ebb4caSwyllys 			rv = KMF_OK;
284730a5e8faSwyllys 		} else if (rv == KMF_ERR_OPEN_FILE) {
284830a5e8faSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
284999ebb4caSwyllys 		}
285099ebb4caSwyllys 
285199ebb4caSwyllys 		if (key != NULL) {
285299ebb4caSwyllys 			KMF_DATA keyvalue;
285399ebb4caSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
285499ebb4caSwyllys 			if (rkey == NULL) {
285599ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
285699ebb4caSwyllys 				goto out;
285799ebb4caSwyllys 			}
285899ebb4caSwyllys 
285999ebb4caSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
286030a5e8faSwyllys 			rv = kmf_read_input_file(handle, path, &keyvalue);
286199ebb4caSwyllys 			if (rv != KMF_OK)
286299ebb4caSwyllys 				goto out;
286399ebb4caSwyllys 
286499ebb4caSwyllys 			rkey->keydata.len = keyvalue.Length;
286599ebb4caSwyllys 			rkey->keydata.val = keyvalue.Data;
286699ebb4caSwyllys 
286799ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
286899ebb4caSwyllys 			key->keyclass = keyclass;
286999ebb4caSwyllys 			key->israw = TRUE;
287099ebb4caSwyllys 			key->keyp = (void *)rkey;
28715b3e1433Swyllys 			if (path != NULL &&
28725b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
28735b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
28745b3e1433Swyllys 			}
287599ebb4caSwyllys 		}
287699ebb4caSwyllys 	}
287799ebb4caSwyllys out:
287899ebb4caSwyllys 	if (rv != KMF_OK) {
287999ebb4caSwyllys 		if (rkey != NULL) {
288030a5e8faSwyllys 			kmf_free_raw_sym_key(rkey);
288199ebb4caSwyllys 		}
288299ebb4caSwyllys 		if (pkey != NULL)
288399ebb4caSwyllys 			EVP_PKEY_free(pkey);
288499ebb4caSwyllys 
288599ebb4caSwyllys 		if (key != NULL) {
288699ebb4caSwyllys 			key->keyalg = KMF_KEYALG_NONE;
288799ebb4caSwyllys 			key->keyclass = KMF_KEYCLASS_NONE;
288899ebb4caSwyllys 			key->keyp = NULL;
288999ebb4caSwyllys 		}
289099ebb4caSwyllys 	}
289199ebb4caSwyllys 
289299ebb4caSwyllys 	return (rv);
289399ebb4caSwyllys }
289499ebb4caSwyllys 
289599ebb4caSwyllys KMF_RETURN
289630a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle,
289730a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
289899ebb4caSwyllys {
289999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
290099ebb4caSwyllys 	char *fullpath = NULL;
2901f482c776Swyllys 	uint32_t maxkeys;
290230a5e8faSwyllys 	KMF_KEY_HANDLE *key;
290330a5e8faSwyllys 	uint32_t *numkeys;
290430a5e8faSwyllys 	KMF_KEY_CLASS keyclass;
290530a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
290630a5e8faSwyllys 	char *dirpath;
290730a5e8faSwyllys 	char *keyfile;
290899ebb4caSwyllys 
290930a5e8faSwyllys 	if (handle == NULL)
291099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
291199ebb4caSwyllys 
291230a5e8faSwyllys 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
291330a5e8faSwyllys 	if (numkeys == NULL)
291430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
291530a5e8faSwyllys 
291630a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
291730a5e8faSwyllys 	    (void *)&keyclass, NULL);
291830a5e8faSwyllys 	if (rv != KMF_OK)
291930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
292030a5e8faSwyllys 
292130a5e8faSwyllys 	if (keyclass != KMF_ASYM_PUB &&
292230a5e8faSwyllys 	    keyclass != KMF_ASYM_PRI &&
292330a5e8faSwyllys 	    keyclass != KMF_SYMMETRIC)
292499ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
292599ebb4caSwyllys 
292630a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
292730a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
292830a5e8faSwyllys 
292930a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
293099ebb4caSwyllys 
293199ebb4caSwyllys 	if (fullpath == NULL)
293299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
293399ebb4caSwyllys 
2934f482c776Swyllys 	maxkeys = *numkeys;
2935f482c776Swyllys 	if (maxkeys == 0)
2936f482c776Swyllys 		maxkeys = 0xFFFFFFFF;
293799ebb4caSwyllys 	*numkeys = 0;
293899ebb4caSwyllys 
293930a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
294030a5e8faSwyllys 	/* it is okay to have "keys" contains NULL */
294130a5e8faSwyllys 
294230a5e8faSwyllys 	/*
294330a5e8faSwyllys 	 * The caller may want a list of the raw key data as well.
294430a5e8faSwyllys 	 * Useful for importing keys from a file into other keystores.
294530a5e8faSwyllys 	 */
294630a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
294730a5e8faSwyllys 
294899ebb4caSwyllys 	if (isdir(fullpath)) {
294999ebb4caSwyllys 		DIR *dirp;
295099ebb4caSwyllys 		struct dirent *dp;
295199ebb4caSwyllys 		int n = 0;
295299ebb4caSwyllys 
295399ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
295499ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
295599ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
295699ebb4caSwyllys 		}
295799ebb4caSwyllys 		rewinddir(dirp);
2958f482c776Swyllys 		while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
295999ebb4caSwyllys 			if (strcmp(dp->d_name, ".") &&
296099ebb4caSwyllys 			    strcmp(dp->d_name, "..")) {
296199ebb4caSwyllys 				char *fname;
296299ebb4caSwyllys 
296399ebb4caSwyllys 				fname = get_fullpath(fullpath,
296499ebb4caSwyllys 				    (char *)&dp->d_name);
296599ebb4caSwyllys 
296699ebb4caSwyllys 				rv = fetch_key(handle, fname,
296730a5e8faSwyllys 				    keyclass, key ? &key[n] : NULL);
296899ebb4caSwyllys 
296930a5e8faSwyllys 				if (rv == KMF_OK) {
297030a5e8faSwyllys 					if (key != NULL && rawkey != NULL)
297130a5e8faSwyllys 						rv = convertToRawKey(
297230a5e8faSwyllys 						    key[n].keyp, &rawkey[n]);
297399ebb4caSwyllys 					n++;
297430a5e8faSwyllys 				}
297599ebb4caSwyllys 
297699ebb4caSwyllys 				if (rv != KMF_OK || key == NULL)
297799ebb4caSwyllys 					free(fname);
297899ebb4caSwyllys 			}
297999ebb4caSwyllys 		}
298099ebb4caSwyllys 		(void) closedir(dirp);
298199ebb4caSwyllys 		free(fullpath);
298299ebb4caSwyllys 		(*numkeys) = n;
298399ebb4caSwyllys 	} else {
298430a5e8faSwyllys 		rv = fetch_key(handle, fullpath, keyclass, key);
298599ebb4caSwyllys 		if (rv == KMF_OK)
298699ebb4caSwyllys 			(*numkeys) = 1;
298799ebb4caSwyllys 
298899ebb4caSwyllys 		if (rv != KMF_OK || key == NULL)
298999ebb4caSwyllys 			free(fullpath);
299030a5e8faSwyllys 
299130a5e8faSwyllys 		if (rv == KMF_OK && key != NULL && rawkey != NULL) {
299230a5e8faSwyllys 			rv = convertToRawKey(key->keyp, rawkey);
299330a5e8faSwyllys 		}
299499ebb4caSwyllys 	}
299599ebb4caSwyllys 
2996f482c776Swyllys 	if (rv == KMF_OK && (*numkeys) == 0)
299799ebb4caSwyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
299873cc0e02Swyllys 	else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
299973cc0e02Swyllys 		rv = KMF_OK;
300099ebb4caSwyllys 
300199ebb4caSwyllys 	return (rv);
300299ebb4caSwyllys }
300399ebb4caSwyllys 
300499ebb4caSwyllys #define	HANDLE_PK12_ERROR { \
300599ebb4caSwyllys 	SET_ERROR(kmfh, ERR_get_error()); \
300699ebb4caSwyllys 	rv = KMF_ERR_ENCODING; \
300799ebb4caSwyllys 	goto out; \
300899ebb4caSwyllys }
300999ebb4caSwyllys 
30105b3e1433Swyllys static int
30115b3e1433Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
301299ebb4caSwyllys {
30135b3e1433Swyllys 	if (xcert != NULL && xcert->aux != NULL &&
30145b3e1433Swyllys 	    xcert->aux->alias != NULL) {
30155b3e1433Swyllys 		if (PKCS12_add_friendlyname_asc(bag,
30165b3e1433Swyllys 		    (const char *)xcert->aux->alias->data,
30175b3e1433Swyllys 		    xcert->aux->alias->length) == 0)
30185b3e1433Swyllys 			return (0);
30195b3e1433Swyllys 	}
30205b3e1433Swyllys 	return (1);
30215b3e1433Swyllys }
30225b3e1433Swyllys 
30235b3e1433Swyllys static PKCS7 *
30245b3e1433Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
30255b3e1433Swyllys 	uchar_t *keyid, unsigned int keyidlen)
30265b3e1433Swyllys {
302799ebb4caSwyllys 	PKCS12_SAFEBAG *bag = NULL;
302899ebb4caSwyllys 	PKCS7 *cert_authsafe = NULL;
30295b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack;
303099ebb4caSwyllys 
303199ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
303299ebb4caSwyllys 	if (bag_stack == NULL)
30335b3e1433Swyllys 		return (NULL);
303499ebb4caSwyllys 
303599ebb4caSwyllys 	/* Convert cert from X509 struct to PKCS#12 bag */
303699ebb4caSwyllys 	bag = PKCS12_x5092certbag(sslcert);
303799ebb4caSwyllys 	if (bag == NULL) {
30385b3e1433Swyllys 		goto out;
303999ebb4caSwyllys 	}
304099ebb4caSwyllys 
304199ebb4caSwyllys 	/* Add the key id to the certificate bag. */
30425b3e1433Swyllys 	if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
30435b3e1433Swyllys 		goto out;
304499ebb4caSwyllys 	}
304599ebb4caSwyllys 
30465b3e1433Swyllys 	if (!add_alias_to_bag(bag, sslcert))
30475b3e1433Swyllys 		goto out;
30485b3e1433Swyllys 
304999ebb4caSwyllys 	/* Pile it on the bag_stack. */
305099ebb4caSwyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
30515b3e1433Swyllys 		goto out;
305299ebb4caSwyllys 	}
305399ebb4caSwyllys 	/* Turn bag_stack of certs into encrypted authsafe. */
305499ebb4caSwyllys 	cert_authsafe = PKCS12_pack_p7encdata(
305599ebb4caSwyllys 	    NID_pbe_WithSHA1And40BitRC2_CBC,
305634acef67Swyllys 	    cred->cred, cred->credlen, NULL, 0,
305734acef67Swyllys 	    PKCS12_DEFAULT_ITER, bag_stack);
305899ebb4caSwyllys 
30595b3e1433Swyllys out:
30605b3e1433Swyllys 	if (bag_stack != NULL)
306199ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
306299ebb4caSwyllys 
30635b3e1433Swyllys 	return (cert_authsafe);
306499ebb4caSwyllys }
30655b3e1433Swyllys 
30665b3e1433Swyllys static PKCS7 *
30675b3e1433Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
30685b3e1433Swyllys 	uchar_t *keyid,  unsigned int keyidlen,
30695b3e1433Swyllys 	char *label, int label_len)
30705b3e1433Swyllys {
30715b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
30725b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
30735b3e1433Swyllys 	PKCS12_SAFEBAG *bag = NULL;
30745b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
30755b3e1433Swyllys 
307699ebb4caSwyllys 	p8 = EVP_PKEY2PKCS8(pkey);
307799ebb4caSwyllys 	if (p8 == NULL) {
30785b3e1433Swyllys 		return (NULL);
307999ebb4caSwyllys 	}
308099ebb4caSwyllys 	/* Put the shrouded key into a PKCS#12 bag. */
308199ebb4caSwyllys 	bag = PKCS12_MAKE_SHKEYBAG(
308299ebb4caSwyllys 	    NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
308399ebb4caSwyllys 	    cred->cred, cred->credlen,
308499ebb4caSwyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, p8);
308599ebb4caSwyllys 
308699ebb4caSwyllys 	/* Clean up the PKCS#8 shrouded key, don't need it now. */
308799ebb4caSwyllys 	PKCS8_PRIV_KEY_INFO_free(p8);
308899ebb4caSwyllys 	p8 = NULL;
308999ebb4caSwyllys 
309099ebb4caSwyllys 	if (bag == NULL) {
30915b3e1433Swyllys 		return (NULL);
309299ebb4caSwyllys 	}
30935b3e1433Swyllys 	if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
30945b3e1433Swyllys 		goto out;
30955b3e1433Swyllys 	if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
30965b3e1433Swyllys 		goto out;
30975b3e1433Swyllys 
309899ebb4caSwyllys 	/* Start a PKCS#12 safebag container for the private key. */
309999ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
31005b3e1433Swyllys 	if (bag_stack == NULL)
31015b3e1433Swyllys 		goto out;
310299ebb4caSwyllys 
310399ebb4caSwyllys 	/* Pile on the private key on the bag_stack. */
31045b3e1433Swyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
31055b3e1433Swyllys 		goto out;
31065b3e1433Swyllys 
310799ebb4caSwyllys 	key_authsafe = PKCS12_pack_p7data(bag_stack);
310899ebb4caSwyllys 
31095b3e1433Swyllys out:
31105b3e1433Swyllys 	if (bag_stack != NULL)
311199ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
311299ebb4caSwyllys 	bag_stack = NULL;
31135b3e1433Swyllys 	return (key_authsafe);
311499ebb4caSwyllys }
311599ebb4caSwyllys 
311699ebb4caSwyllys static EVP_PKEY *
311799ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
311899ebb4caSwyllys {
311999ebb4caSwyllys 	RSA		*rsa = NULL;
312099ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
312199ebb4caSwyllys 
312299ebb4caSwyllys 	if ((rsa = RSA_new()) == NULL)
312399ebb4caSwyllys 		return (NULL);
312499ebb4caSwyllys 
312599ebb4caSwyllys 	if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL)
312699ebb4caSwyllys 		return (NULL);
312799ebb4caSwyllys 
312899ebb4caSwyllys 	if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) ==
312999ebb4caSwyllys 	    NULL)
313099ebb4caSwyllys 		return (NULL);
313199ebb4caSwyllys 
313299ebb4caSwyllys 	if (key->priexp.val != NULL)
313399ebb4caSwyllys 		if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len,
313499ebb4caSwyllys 		    rsa->d)) == NULL)
313599ebb4caSwyllys 			return (NULL);
313699ebb4caSwyllys 
313799ebb4caSwyllys 	if (key->prime1.val != NULL)
313899ebb4caSwyllys 		if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len,
313999ebb4caSwyllys 		    rsa->p)) == NULL)
314099ebb4caSwyllys 			return (NULL);
314199ebb4caSwyllys 
314299ebb4caSwyllys 	if (key->prime2.val != NULL)
314399ebb4caSwyllys 		if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len,
314499ebb4caSwyllys 		    rsa->q)) == NULL)
314599ebb4caSwyllys 			return (NULL);
314699ebb4caSwyllys 
314799ebb4caSwyllys 	if (key->exp1.val != NULL)
314899ebb4caSwyllys 		if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len,
314999ebb4caSwyllys 		    rsa->dmp1)) == NULL)
315099ebb4caSwyllys 			return (NULL);
315199ebb4caSwyllys 
315299ebb4caSwyllys 	if (key->exp2.val != NULL)
315399ebb4caSwyllys 		if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len,
315499ebb4caSwyllys 		    rsa->dmq1)) == NULL)
315599ebb4caSwyllys 			return (NULL);
315699ebb4caSwyllys 
315799ebb4caSwyllys 	if (key->coef.val != NULL)
315899ebb4caSwyllys 		if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len,
315999ebb4caSwyllys 		    rsa->iqmp)) == NULL)
316099ebb4caSwyllys 			return (NULL);
316199ebb4caSwyllys 
316299ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
316399ebb4caSwyllys 		return (NULL);
316499ebb4caSwyllys 
316599ebb4caSwyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
316699ebb4caSwyllys 
316799ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
316899ebb4caSwyllys 	RSA_free(rsa);
316999ebb4caSwyllys 
317099ebb4caSwyllys 	return (newkey);
317199ebb4caSwyllys }
317299ebb4caSwyllys 
317399ebb4caSwyllys static EVP_PKEY *
317499ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
317599ebb4caSwyllys {
317699ebb4caSwyllys 	DSA		*dsa = NULL;
317799ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
317899ebb4caSwyllys 
317999ebb4caSwyllys 	if ((dsa = DSA_new()) == NULL)
318099ebb4caSwyllys 		return (NULL);
318199ebb4caSwyllys 
318299ebb4caSwyllys 	if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len,
318399ebb4caSwyllys 	    dsa->p)) == NULL)
318499ebb4caSwyllys 		return (NULL);
318599ebb4caSwyllys 
318699ebb4caSwyllys 	if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len,
318799ebb4caSwyllys 	    dsa->q)) == NULL)
318899ebb4caSwyllys 		return (NULL);
318999ebb4caSwyllys 
319099ebb4caSwyllys 	if ((dsa->g = BN_bin2bn(key->base.val, key->base.len,
319199ebb4caSwyllys 	    dsa->g)) == NULL)
319299ebb4caSwyllys 		return (NULL);
319399ebb4caSwyllys 
319499ebb4caSwyllys 	if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len,
319599ebb4caSwyllys 	    dsa->priv_key)) == NULL)
319699ebb4caSwyllys 		return (NULL);
319799ebb4caSwyllys 
319830a5e8faSwyllys 	if (key->pubvalue.val != NULL) {
319930a5e8faSwyllys 		if ((dsa->pub_key = BN_bin2bn(key->pubvalue.val,
320030a5e8faSwyllys 		    key->pubvalue.len, dsa->pub_key)) == NULL)
320130a5e8faSwyllys 			return (NULL);
320230a5e8faSwyllys 	}
320330a5e8faSwyllys 
320499ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
320599ebb4caSwyllys 		return (NULL);
320699ebb4caSwyllys 
320799ebb4caSwyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
320899ebb4caSwyllys 
320999ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
321099ebb4caSwyllys 	DSA_free(dsa);
321199ebb4caSwyllys 	return (newkey);
321299ebb4caSwyllys }
321399ebb4caSwyllys 
32145b3e1433Swyllys static EVP_PKEY *
32155b3e1433Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key)
32165b3e1433Swyllys {
32175b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
32185b3e1433Swyllys 	KMF_RAW_KEY_DATA *rawkey;
32195b3e1433Swyllys 	ASN1_TYPE *attr = NULL;
32205b3e1433Swyllys 	KMF_RETURN ret;
32215b3e1433Swyllys 
32225b3e1433Swyllys 	if (key == NULL || !key->israw)
32235b3e1433Swyllys 		return (NULL);
32245b3e1433Swyllys 
32255b3e1433Swyllys 	rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
32265b3e1433Swyllys 	if (rawkey->keytype == KMF_RSA) {
32275b3e1433Swyllys 		pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
32285b3e1433Swyllys 	} else if (rawkey->keytype == KMF_DSA) {
32295b3e1433Swyllys 		pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
3230e65e5c2dSWyllys Ingersoll 	} else if (rawkey->keytype == KMF_ECDSA) {
3231e65e5c2dSWyllys Ingersoll 		/*
3232e65e5c2dSWyllys Ingersoll 		 * OpenSSL in Solaris does not support EC for
3233e65e5c2dSWyllys Ingersoll 		 * legal reasons
3234e65e5c2dSWyllys Ingersoll 		 */
3235e65e5c2dSWyllys Ingersoll 		return (NULL);
32365b3e1433Swyllys 	} else {
32375b3e1433Swyllys 		/* wrong kind of key */
32385b3e1433Swyllys 		return (NULL);
32395b3e1433Swyllys 	}
32405b3e1433Swyllys 
32415b3e1433Swyllys 	if (rawkey->label != NULL) {
32425b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
32435b3e1433Swyllys 			EVP_PKEY_free(pkey);
32445b3e1433Swyllys 			return (NULL);
32455b3e1433Swyllys 		}
32465b3e1433Swyllys 		attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
32475b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
32485b3e1433Swyllys 		    strlen(rawkey->label));
32495b3e1433Swyllys 		attr->type = V_ASN1_BMPSTRING;
32505b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.bmpstring;
32515b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
32525b3e1433Swyllys 		if (ret != KMF_OK) {
32535b3e1433Swyllys 			EVP_PKEY_free(pkey);
32545b3e1433Swyllys 			ASN1_TYPE_free(attr);
32555b3e1433Swyllys 			return (NULL);
32565b3e1433Swyllys 		}
32575b3e1433Swyllys 	}
32585b3e1433Swyllys 	if (rawkey->id.Data != NULL) {
32595b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
32605b3e1433Swyllys 			EVP_PKEY_free(pkey);
32615b3e1433Swyllys 			return (NULL);
32625b3e1433Swyllys 		}
32635b3e1433Swyllys 		attr->value.octet_string =
32645b3e1433Swyllys 		    ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
32655b3e1433Swyllys 		attr->type = V_ASN1_OCTET_STRING;
32665b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.octet_string,
32675b3e1433Swyllys 		    rawkey->id.Data, rawkey->id.Length);
32685b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.octet_string;
32695b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
32705b3e1433Swyllys 		if (ret != KMF_OK) {
32715b3e1433Swyllys 			EVP_PKEY_free(pkey);
32725b3e1433Swyllys 			ASN1_TYPE_free(attr);
32735b3e1433Swyllys 			return (NULL);
32745b3e1433Swyllys 		}
32755b3e1433Swyllys 	}
32765b3e1433Swyllys 	return (pkey);
32775b3e1433Swyllys }
32785b3e1433Swyllys 
32795b3e1433Swyllys /*
32805b3e1433Swyllys  * Search a list of private keys to find one that goes with the certificate.
32815b3e1433Swyllys  */
32825b3e1433Swyllys static EVP_PKEY *
32835b3e1433Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
32845b3e1433Swyllys {
32855b3e1433Swyllys 	int i;
32865b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
32875b3e1433Swyllys 
32885b3e1433Swyllys 	if (numkeys == 0 || keylist == NULL || xcert == NULL)
32895b3e1433Swyllys 		return (NULL);
32905b3e1433Swyllys 	for (i = 0; i < numkeys; i++) {
32915b3e1433Swyllys 		if (keylist[i].israw)
32925b3e1433Swyllys 			pkey = raw_key_to_pkey(&keylist[i]);
32935b3e1433Swyllys 		else
32945b3e1433Swyllys 			pkey = (EVP_PKEY *)keylist[i].keyp;
32955b3e1433Swyllys 		if (pkey != NULL) {
32965b3e1433Swyllys 			if (X509_check_private_key(xcert, pkey)) {
32975b3e1433Swyllys 				return (pkey);
32985b3e1433Swyllys 			} else {
32995b3e1433Swyllys 				EVP_PKEY_free(pkey);
33005b3e1433Swyllys 				pkey = NULL;
33015b3e1433Swyllys 			}
33025b3e1433Swyllys 		}
33035b3e1433Swyllys 	}
33045b3e1433Swyllys 	return (pkey);
33055b3e1433Swyllys }
33065b3e1433Swyllys 
330799ebb4caSwyllys static KMF_RETURN
33085b3e1433Swyllys local_export_pk12(KMF_HANDLE_T handle,
330999ebb4caSwyllys 	KMF_CREDENTIAL *cred,
331099ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
331199ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
331299ebb4caSwyllys 	char *filename)
331399ebb4caSwyllys {
331499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
331599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
331699ebb4caSwyllys 	BIO *bio = NULL;
33175b3e1433Swyllys 	PKCS7 *cert_authsafe = NULL;
33185b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
33195b3e1433Swyllys 	STACK_OF(PKCS7) *authsafe_stack = NULL;
33205b3e1433Swyllys 	PKCS12 *p12_elem = NULL;
332199ebb4caSwyllys 	int i;
332299ebb4caSwyllys 
33235b3e1433Swyllys 	if (numcerts == 0 && numkeys == 0)
33245b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
33255b3e1433Swyllys 
332699ebb4caSwyllys 	/*
332799ebb4caSwyllys 	 * Open the output file.
332899ebb4caSwyllys 	 */
332999ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
333099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
333199ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
333299ebb4caSwyllys 		goto cleanup;
333399ebb4caSwyllys 	}
333499ebb4caSwyllys 
33355b3e1433Swyllys 	/* Start a PKCS#7 stack. */
33365b3e1433Swyllys 	authsafe_stack = sk_PKCS7_new_null();
33375b3e1433Swyllys 	if (authsafe_stack == NULL) {
33385b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
33395b3e1433Swyllys 		goto cleanup;
33405b3e1433Swyllys 	}
33415b3e1433Swyllys 	if (numcerts > 0) {
334299ebb4caSwyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
334399ebb4caSwyllys 			const uchar_t *p = certlist[i].certificate.Data;
334499ebb4caSwyllys 			long len = certlist[i].certificate.Length;
33455b3e1433Swyllys 			X509 *xcert = NULL;
33465b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
33475b3e1433Swyllys 			unsigned char keyid[EVP_MAX_MD_SIZE];
33485b3e1433Swyllys 			unsigned int keyidlen = 0;
334999ebb4caSwyllys 
335099ebb4caSwyllys 			xcert = d2i_X509(NULL, &p, len);
335199ebb4caSwyllys 			if (xcert == NULL) {
335299ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
335399ebb4caSwyllys 				rv = KMF_ERR_ENCODING;
335499ebb4caSwyllys 			}
33555b3e1433Swyllys 			if (certlist[i].kmf_private.label != NULL) {
33565b3e1433Swyllys 				/* Set alias attribute */
33575b3e1433Swyllys 				(void) X509_alias_set1(xcert,
33585b3e1433Swyllys 				    (uchar_t *)certlist[i].kmf_private.label,
33595b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label));
33605b3e1433Swyllys 			}
33615b3e1433Swyllys 			/* Check if there is a key corresponding to this cert */
33625b3e1433Swyllys 			pkey = find_matching_key(xcert, numkeys, keylist);
33635b3e1433Swyllys 
33645b3e1433Swyllys 			/*
33655b3e1433Swyllys 			 * If key is found, get fingerprint and create a
33665b3e1433Swyllys 			 * safebag.
33675b3e1433Swyllys 			 */
33685b3e1433Swyllys 			if (pkey != NULL) {
33695b3e1433Swyllys 				(void) X509_digest(xcert, EVP_sha1(),
33705b3e1433Swyllys 				    keyid, &keyidlen);
33715b3e1433Swyllys 				key_authsafe = add_key_to_safe(pkey, cred,
33725b3e1433Swyllys 				    keyid, keyidlen,
33735b3e1433Swyllys 				    certlist[i].kmf_private.label,
33745b3e1433Swyllys 				    (certlist[i].kmf_private.label ?
33755b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label) : 0));
33765b3e1433Swyllys 
33775b3e1433Swyllys 				if (key_authsafe == NULL) {
33785b3e1433Swyllys 					X509_free(xcert);
33795b3e1433Swyllys 					EVP_PKEY_free(pkey);
33805b3e1433Swyllys 					goto cleanup;
33815b3e1433Swyllys 				}
33825b3e1433Swyllys 				/* Put the key safe into the Auth Safe */
33835b3e1433Swyllys 				if (!sk_PKCS7_push(authsafe_stack,
33845b3e1433Swyllys 				    key_authsafe)) {
33855b3e1433Swyllys 					X509_free(xcert);
33865b3e1433Swyllys 					EVP_PKEY_free(pkey);
33875b3e1433Swyllys 					goto cleanup;
33885b3e1433Swyllys 				}
33895b3e1433Swyllys 			}
33905b3e1433Swyllys 
33915b3e1433Swyllys 			/* create a certificate safebag */
33925b3e1433Swyllys 			cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
33935b3e1433Swyllys 			    keyidlen);
33945b3e1433Swyllys 			if (cert_authsafe == NULL) {
33955b3e1433Swyllys 				X509_free(xcert);
33965b3e1433Swyllys 				EVP_PKEY_free(pkey);
33975b3e1433Swyllys 				goto cleanup;
33985b3e1433Swyllys 			}
33995b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
34005b3e1433Swyllys 				X509_free(xcert);
34015b3e1433Swyllys 				EVP_PKEY_free(pkey);
34025b3e1433Swyllys 				goto cleanup;
34035b3e1433Swyllys 			}
34045b3e1433Swyllys 
340599ebb4caSwyllys 			X509_free(xcert);
340699ebb4caSwyllys 			if (pkey)
340799ebb4caSwyllys 				EVP_PKEY_free(pkey);
340899ebb4caSwyllys 		}
34095b3e1433Swyllys 	} else if (numcerts == 0 && numkeys > 0) {
34105b3e1433Swyllys 		/*
34115b3e1433Swyllys 		 * If only adding keys to the file.
34125b3e1433Swyllys 		 */
34135b3e1433Swyllys 		for (i = 0; i < numkeys; i++) {
34145b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
34155b3e1433Swyllys 
34165b3e1433Swyllys 			if (keylist[i].israw)
34175b3e1433Swyllys 				pkey = raw_key_to_pkey(&keylist[i]);
34185b3e1433Swyllys 			else
34195b3e1433Swyllys 				pkey = (EVP_PKEY *)keylist[i].keyp;
34205b3e1433Swyllys 
34215b3e1433Swyllys 			if (pkey == NULL)
34225b3e1433Swyllys 				continue;
34235b3e1433Swyllys 
34245b3e1433Swyllys 			key_authsafe = add_key_to_safe(pkey, cred,
34255b3e1433Swyllys 			    NULL, 0, NULL, 0);
34265b3e1433Swyllys 
34275b3e1433Swyllys 			if (key_authsafe == NULL) {
34285b3e1433Swyllys 				EVP_PKEY_free(pkey);
34295b3e1433Swyllys 				goto cleanup;
34305b3e1433Swyllys 			}
34315b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
34325b3e1433Swyllys 				EVP_PKEY_free(pkey);
34335b3e1433Swyllys 				goto cleanup;
34345b3e1433Swyllys 			}
34355b3e1433Swyllys 		}
34365b3e1433Swyllys 	}
34375b3e1433Swyllys 	p12_elem = PKCS12_init(NID_pkcs7_data);
34385b3e1433Swyllys 	if (p12_elem == NULL) {
34395b3e1433Swyllys 		goto cleanup;
344099ebb4caSwyllys 	}
344199ebb4caSwyllys 
34425b3e1433Swyllys 	/* Put the PKCS#7 stack into the PKCS#12 element. */
34435b3e1433Swyllys 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
34445b3e1433Swyllys 		goto cleanup;
34455b3e1433Swyllys 	}
34465b3e1433Swyllys 
34475b3e1433Swyllys 	/* Set the integrity MAC on the PKCS#12 element. */
34485b3e1433Swyllys 	if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
34495b3e1433Swyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
34505b3e1433Swyllys 		goto cleanup;
34515b3e1433Swyllys 	}
34525b3e1433Swyllys 
34535b3e1433Swyllys 	/* Write the PKCS#12 element to the export file. */
34545b3e1433Swyllys 	if (!i2d_PKCS12_bio(bio, p12_elem)) {
34555b3e1433Swyllys 		goto cleanup;
34565b3e1433Swyllys 	}
34575b3e1433Swyllys 	PKCS12_free(p12_elem);
34585b3e1433Swyllys 
345999ebb4caSwyllys cleanup:
34605b3e1433Swyllys 	/* Clear away the PKCS#7 stack, we're done with it. */
34615b3e1433Swyllys 	if (authsafe_stack)
34625b3e1433Swyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
346399ebb4caSwyllys 
346499ebb4caSwyllys 	if (bio != NULL)
346599ebb4caSwyllys 		(void) BIO_free_all(bio);
346699ebb4caSwyllys 
346799ebb4caSwyllys 	return (rv);
346899ebb4caSwyllys }
346999ebb4caSwyllys 
347099ebb4caSwyllys KMF_RETURN
347130a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
347230a5e8faSwyllys     KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
347330a5e8faSwyllys     KMF_CREDENTIAL *p12cred, char *filename)
347430a5e8faSwyllys {
347530a5e8faSwyllys 	KMF_RETURN rv;
347630a5e8faSwyllys 
347730a5e8faSwyllys 	if (certlist == NULL && keylist == NULL)
347830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
347930a5e8faSwyllys 
34805b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, numcerts, certlist,
348130a5e8faSwyllys 	    numkeys, keylist, filename);
348230a5e8faSwyllys 
348330a5e8faSwyllys 	return (rv);
348430a5e8faSwyllys }
348530a5e8faSwyllys 
348630a5e8faSwyllys KMF_RETURN
348730a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
348899ebb4caSwyllys {
348999ebb4caSwyllys 	KMF_RETURN rv;
349099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
349199ebb4caSwyllys 	char *fullpath = NULL;
349230a5e8faSwyllys 	char *dirpath = NULL;
349330a5e8faSwyllys 	char *certfile = NULL;
349430a5e8faSwyllys 	char *keyfile = NULL;
349530a5e8faSwyllys 	char *filename = NULL;
349630a5e8faSwyllys 	KMF_CREDENTIAL *p12cred = NULL;
34975b3e1433Swyllys 	KMF_X509_DER_CERT certdata;
34985b3e1433Swyllys 	KMF_KEY_HANDLE key;
34995b3e1433Swyllys 	int gotkey = 0;
35005b3e1433Swyllys 	int gotcert = 0;
350130a5e8faSwyllys 
350230a5e8faSwyllys 	if (handle == NULL)
350330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
350499ebb4caSwyllys 
350599ebb4caSwyllys 	/*
350699ebb4caSwyllys 	 *  First, find the certificate.
350799ebb4caSwyllys 	 */
350830a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
350930a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
351030a5e8faSwyllys 	if (certfile != NULL) {
351130a5e8faSwyllys 		fullpath = get_fullpath(dirpath, certfile);
351299ebb4caSwyllys 		if (fullpath == NULL)
351399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
351499ebb4caSwyllys 
351599ebb4caSwyllys 		if (isdir(fullpath)) {
351699ebb4caSwyllys 			free(fullpath);
351799ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
351899ebb4caSwyllys 		}
351999ebb4caSwyllys 
35205b3e1433Swyllys 		(void) memset(&certdata, 0, sizeof (certdata));
35215b3e1433Swyllys 		rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL,
35225b3e1433Swyllys 		    fullpath, &certdata.certificate);
352399ebb4caSwyllys 		if (rv != KMF_OK)
352499ebb4caSwyllys 			goto end;
352530a5e8faSwyllys 
35265b3e1433Swyllys 		gotcert++;
35275b3e1433Swyllys 		certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
352830a5e8faSwyllys 		free(fullpath);
352999ebb4caSwyllys 	}
353099ebb4caSwyllys 
353199ebb4caSwyllys 	/*
353299ebb4caSwyllys 	 * Now find the private key.
353399ebb4caSwyllys 	 */
353430a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
353530a5e8faSwyllys 	if (keyfile != NULL) {
353630a5e8faSwyllys 		fullpath = get_fullpath(dirpath, keyfile);
353799ebb4caSwyllys 		if (fullpath == NULL)
353899ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
353999ebb4caSwyllys 
354099ebb4caSwyllys 		if (isdir(fullpath)) {
354199ebb4caSwyllys 			free(fullpath);
354299ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
354399ebb4caSwyllys 		}
354499ebb4caSwyllys 
35455b3e1433Swyllys 		(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
35465b3e1433Swyllys 		rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
35475b3e1433Swyllys 		if (rv != KMF_OK)
354899ebb4caSwyllys 			goto end;
35495b3e1433Swyllys 		gotkey++;
355099ebb4caSwyllys 	}
355199ebb4caSwyllys 
355299ebb4caSwyllys 	/*
355399ebb4caSwyllys 	 * Open the output file.
355499ebb4caSwyllys 	 */
355530a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
355630a5e8faSwyllys 	    numattr);
355730a5e8faSwyllys 	if (filename == NULL) {
355830a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
355930a5e8faSwyllys 		goto end;
356030a5e8faSwyllys 	}
356130a5e8faSwyllys 
356299ebb4caSwyllys 	/* Stick the key and the cert into a PKCS#12 file */
356330a5e8faSwyllys 	p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
356430a5e8faSwyllys 	if (p12cred == NULL) {
356530a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
356630a5e8faSwyllys 		goto end;
356730a5e8faSwyllys 	}
356830a5e8faSwyllys 
35695b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, 1, &certdata,
35705b3e1433Swyllys 	    1, &key, filename);
357199ebb4caSwyllys 
357299ebb4caSwyllys end:
357399ebb4caSwyllys 	if (fullpath)
357499ebb4caSwyllys 		free(fullpath);
357599ebb4caSwyllys 
35765b3e1433Swyllys 	if (gotcert)
35775b3e1433Swyllys 		kmf_free_kmf_cert(handle, &certdata);
35785b3e1433Swyllys 	if (gotkey)
35795b3e1433Swyllys 		kmf_free_kmf_key(handle, &key);
358099ebb4caSwyllys 	return (rv);
358199ebb4caSwyllys }
358299ebb4caSwyllys 
358371593db2Swyllys /*
358471593db2Swyllys  * Helper function to extract keys and certificates from
358571593db2Swyllys  * a single PEM file.  Typically the file should contain a
358671593db2Swyllys  * private key and an associated public key wrapped in an x509 cert.
358771593db2Swyllys  * However, the file may be just a list of X509 certs with no keys.
358871593db2Swyllys  */
358971593db2Swyllys static KMF_RETURN
359030a5e8faSwyllys extract_pem(KMF_HANDLE *kmfh,
359130a5e8faSwyllys 	char *issuer, char *subject, KMF_BIGINT *serial,
359202744e81Swyllys 	char *filename, CK_UTF8CHAR *pin,
359371593db2Swyllys 	CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
359471593db2Swyllys 	int *numcerts)
3595a2d4930dSDan OpenSolaris Anderson /* ARGSUSED6 */
359671593db2Swyllys {
359771593db2Swyllys 	KMF_RETURN rv = KMF_OK;
359871593db2Swyllys 	FILE *fp;
359934acef67Swyllys 	STACK_OF(X509_INFO) *x509_info_stack = NULL;
360002744e81Swyllys 	int i, ncerts = 0, matchcerts = 0;
360171593db2Swyllys 	EVP_PKEY *pkey = NULL;
360271593db2Swyllys 	X509_INFO *info;
360371593db2Swyllys 	X509 *x;
36045b3e1433Swyllys 	X509_INFO **cert_infos = NULL;
360571593db2Swyllys 	KMF_DATA *certlist = NULL;
360671593db2Swyllys 
360771593db2Swyllys 	if (priv_key)
360871593db2Swyllys 		*priv_key = NULL;
360971593db2Swyllys 	if (certs)
361071593db2Swyllys 		*certs = NULL;
361171593db2Swyllys 	fp = fopen(filename, "r");
36125b3e1433Swyllys 	if (fp == NULL)
361371593db2Swyllys 		return (KMF_ERR_OPEN_FILE);
36145b3e1433Swyllys 
361571593db2Swyllys 	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
361671593db2Swyllys 	if (x509_info_stack == NULL) {
361771593db2Swyllys 		(void) fclose(fp);
361871593db2Swyllys 		return (KMF_ERR_ENCODING);
361971593db2Swyllys 	}
36205b3e1433Swyllys 	cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
36215b3e1433Swyllys 	    sizeof (X509_INFO *));
36225b3e1433Swyllys 	if (cert_infos == NULL) {
36235b3e1433Swyllys 		(void) fclose(fp);
36245b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
36255b3e1433Swyllys 		goto err;
36265b3e1433Swyllys 	}
362771593db2Swyllys 
36285b3e1433Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3629a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
363034acef67Swyllys 		cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
363171593db2Swyllys 		ncerts++;
363271593db2Swyllys 	}
363371593db2Swyllys 
363471593db2Swyllys 	if (ncerts == 0) {
363571593db2Swyllys 		(void) fclose(fp);
363634acef67Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
363734acef67Swyllys 		goto err;
363871593db2Swyllys 	}
363971593db2Swyllys 
364071593db2Swyllys 	if (priv_key != NULL) {
364171593db2Swyllys 		rewind(fp);
364271593db2Swyllys 		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
364371593db2Swyllys 	}
364471593db2Swyllys 	(void) fclose(fp);
364571593db2Swyllys 
364671593db2Swyllys 	x = cert_infos[ncerts - 1]->x509;
364771593db2Swyllys 	/*
364871593db2Swyllys 	 * Make sure the private key matchs the last cert in the file.
364971593db2Swyllys 	 */
365071593db2Swyllys 	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
365171593db2Swyllys 		EVP_PKEY_free(pkey);
365234acef67Swyllys 		rv = KMF_ERR_KEY_MISMATCH;
365334acef67Swyllys 		goto err;
365471593db2Swyllys 	}
365571593db2Swyllys 
3656a2d4930dSDan OpenSolaris Anderson 	certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
365771593db2Swyllys 	if (certlist == NULL) {
365871593db2Swyllys 		if (pkey != NULL)
365971593db2Swyllys 			EVP_PKEY_free(pkey);
366034acef67Swyllys 		rv = KMF_ERR_MEMORY;
366134acef67Swyllys 		goto err;
366271593db2Swyllys 	}
366371593db2Swyllys 
366471593db2Swyllys 	/*
366571593db2Swyllys 	 * Convert all of the certs to DER format.
366671593db2Swyllys 	 */
366702744e81Swyllys 	matchcerts = 0;
366871593db2Swyllys 	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
366902744e81Swyllys 		boolean_t match = FALSE;
367071593db2Swyllys 		info =  cert_infos[ncerts - 1 - i];
367171593db2Swyllys 
367230a5e8faSwyllys 		rv = check_cert(info->x509, issuer, subject, serial, &match);
367302744e81Swyllys 		if (rv != KMF_OK || match != TRUE) {
367402744e81Swyllys 			rv = KMF_OK;
367502744e81Swyllys 			continue;
367602744e81Swyllys 		}
367702744e81Swyllys 
367802744e81Swyllys 		rv = ssl_cert2KMFDATA(kmfh, info->x509,
367902744e81Swyllys 			&certlist[matchcerts++]);
368071593db2Swyllys 
368171593db2Swyllys 		if (rv != KMF_OK) {
3682e65e5c2dSWyllys Ingersoll 			int j;
3683e65e5c2dSWyllys Ingersoll 			for (j = 0; j < matchcerts; j++)
3684e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certlist[j]);
368571593db2Swyllys 			free(certlist);
368671593db2Swyllys 			certlist = NULL;
368702744e81Swyllys 			ncerts = matchcerts = 0;
368871593db2Swyllys 		}
368971593db2Swyllys 	}
369071593db2Swyllys 
369171593db2Swyllys 	if (numcerts != NULL)
369202744e81Swyllys 		*numcerts = matchcerts;
3693a2d4930dSDan OpenSolaris Anderson 
3694e65e5c2dSWyllys Ingersoll 	if (certs != NULL)
369571593db2Swyllys 		*certs = certlist;
3696e65e5c2dSWyllys Ingersoll 	else if (certlist != NULL) {
3697e65e5c2dSWyllys Ingersoll 		for (i = 0; i < ncerts; i++)
3698e65e5c2dSWyllys Ingersoll 			kmf_free_data(&certlist[i]);
3699a2d4930dSDan OpenSolaris Anderson 		free(certlist);
3700a2d4930dSDan OpenSolaris Anderson 		certlist = NULL;
3701a2d4930dSDan OpenSolaris Anderson 	}
370271593db2Swyllys 
370371593db2Swyllys 	if (priv_key == NULL && pkey != NULL)
370471593db2Swyllys 		EVP_PKEY_free(pkey);
370571593db2Swyllys 	else if (priv_key != NULL && pkey != NULL)
370671593db2Swyllys 		*priv_key = pkey;
370771593db2Swyllys 
370834acef67Swyllys err:
370934acef67Swyllys 	/* Cleanup the stack of X509 info records */
371034acef67Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3711a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
371234acef67Swyllys 		info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
371334acef67Swyllys 		X509_INFO_free(info);
371434acef67Swyllys 	}
371534acef67Swyllys 	if (x509_info_stack)
371634acef67Swyllys 		sk_X509_INFO_free(x509_info_stack);
371734acef67Swyllys 
37185b3e1433Swyllys 	if (cert_infos != NULL)
37195b3e1433Swyllys 		free(cert_infos);
37205b3e1433Swyllys 
372171593db2Swyllys 	return (rv);
372271593db2Swyllys }
372371593db2Swyllys 
37245b3e1433Swyllys static KMF_RETURN
37255b3e1433Swyllys openssl_parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
37265b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
37275b3e1433Swyllys {
37285b3e1433Swyllys 	KMF_RETURN ret;
37295b3e1433Swyllys 	int i;
37305b3e1433Swyllys 
37315b3e1433Swyllys 	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
3732a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
37335b3e1433Swyllys 		PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
37345b3e1433Swyllys 		ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
37355b3e1433Swyllys 		    keys, certs);
37365b3e1433Swyllys 
37375b3e1433Swyllys 		if (ret != KMF_OK)
37385b3e1433Swyllys 			return (ret);
37395b3e1433Swyllys 	}
37405b3e1433Swyllys 
37415b3e1433Swyllys 	return (ret);
37425b3e1433Swyllys }
37435b3e1433Swyllys 
37445b3e1433Swyllys static KMF_RETURN
37455b3e1433Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
37465b3e1433Swyllys {
37475b3e1433Swyllys 	X509_ATTRIBUTE *attr = NULL;
37485b3e1433Swyllys 
37495b3e1433Swyllys 	if (pkey == NULL || attrib == NULL)
37505b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
37515b3e1433Swyllys 
37525b3e1433Swyllys 	if (pkey->attributes == NULL) {
37535b3e1433Swyllys 		pkey->attributes = sk_X509_ATTRIBUTE_new_null();
37545b3e1433Swyllys 		if (pkey->attributes == NULL)
37555b3e1433Swyllys 			return (KMF_ERR_MEMORY);
37565b3e1433Swyllys 	}
37575b3e1433Swyllys 	attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
37585b3e1433Swyllys 	if (attr != NULL) {
37595b3e1433Swyllys 		int i;
37605b3e1433Swyllys 		X509_ATTRIBUTE *a;
37615b3e1433Swyllys 		for (i = 0;
37625b3e1433Swyllys 		    i < sk_X509_ATTRIBUTE_num(pkey->attributes); i++) {
3763e65e5c2dSWyllys Ingersoll 			/* LINTED E_BAD_PTR_CASE_ALIGN */
37645b3e1433Swyllys 			a = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
37655b3e1433Swyllys 			if (OBJ_obj2nid(a->object) == nid) {
37665b3e1433Swyllys 				X509_ATTRIBUTE_free(a);
3767a2d4930dSDan OpenSolaris Anderson 				/* LINTED E_BAD_PTR_CAST_ALIGN */
37685b3e1433Swyllys 				sk_X509_ATTRIBUTE_set(pkey->attributes,
37695b3e1433Swyllys 				    i, attr);
37705b3e1433Swyllys 				return (KMF_OK);
37715b3e1433Swyllys 			}
37725b3e1433Swyllys 		}
37735b3e1433Swyllys 		if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == NULL) {
37745b3e1433Swyllys 			X509_ATTRIBUTE_free(attr);
37755b3e1433Swyllys 			return (KMF_ERR_MEMORY);
37765b3e1433Swyllys 		}
37775b3e1433Swyllys 	} else {
37785b3e1433Swyllys 		return (KMF_ERR_MEMORY);
37795b3e1433Swyllys 	}
37805b3e1433Swyllys 
37815b3e1433Swyllys 	return (KMF_OK);
37825b3e1433Swyllys }
37835b3e1433Swyllys 
37845b3e1433Swyllys static KMF_RETURN
37855b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
37865b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
37875b3e1433Swyllys {
37885b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
37895b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
37905b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
37915b3e1433Swyllys 	X509 *xcert = NULL;
37925b3e1433Swyllys 	ASN1_TYPE *keyid = NULL;
37935b3e1433Swyllys 	ASN1_TYPE *fname = NULL;
37945b3e1433Swyllys 	uchar_t *data = NULL;
37955b3e1433Swyllys 
37965b3e1433Swyllys 	keyid = PKCS12_get_attr(bag, NID_localKeyID);
37975b3e1433Swyllys 	fname = PKCS12_get_attr(bag, NID_friendlyName);
37985b3e1433Swyllys 
37995b3e1433Swyllys 	switch (M_PKCS12_bag_type(bag)) {
38005b3e1433Swyllys 		case NID_keyBag:
38015b3e1433Swyllys 			if (keylist == NULL)
38025b3e1433Swyllys 				goto end;
38035b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(bag->value.keybag);
38045b3e1433Swyllys 			if (pkey == NULL)
38055b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38065b3e1433Swyllys 
38075b3e1433Swyllys 			break;
38085b3e1433Swyllys 		case NID_pkcs8ShroudedKeyBag:
38095b3e1433Swyllys 			if (keylist == NULL)
38105b3e1433Swyllys 				goto end;
38115b3e1433Swyllys 			p8 = M_PKCS12_decrypt_skey(bag, pass, passlen);
38125b3e1433Swyllys 			if (p8 == NULL)
38135b3e1433Swyllys 				return (KMF_ERR_AUTH_FAILED);
38145b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(p8);
38155b3e1433Swyllys 			PKCS8_PRIV_KEY_INFO_free(p8);
38165b3e1433Swyllys 			if (pkey == NULL)
38175b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38185b3e1433Swyllys 			break;
38195b3e1433Swyllys 		case NID_certBag:
38205b3e1433Swyllys 			if (certlist == NULL)
38215b3e1433Swyllys 				goto end;
38225b3e1433Swyllys 			if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate)
38235b3e1433Swyllys 				return (KMF_ERR_PKCS12_FORMAT);
38245b3e1433Swyllys 			xcert = M_PKCS12_certbag2x509(bag);
38255b3e1433Swyllys 			if (xcert == NULL) {
38265b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38275b3e1433Swyllys 				goto end;
38285b3e1433Swyllys 			}
38295b3e1433Swyllys 			if (keyid != NULL) {
38305b3e1433Swyllys 				if (X509_keyid_set1(xcert,
38315b3e1433Swyllys 				    keyid->value.octet_string->data,
38325b3e1433Swyllys 				    keyid->value.octet_string->length) == 0) {
38335b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
38345b3e1433Swyllys 					goto end;
38355b3e1433Swyllys 				}
38365b3e1433Swyllys 			}
38375b3e1433Swyllys 			if (fname != NULL) {
38385b3e1433Swyllys 				int len, r;
38395b3e1433Swyllys 				len = ASN1_STRING_to_UTF8(&data,
38405b3e1433Swyllys 				    fname->value.asn1_string);
38415b3e1433Swyllys 				if (len > 0 && data != NULL) {
38425b3e1433Swyllys 					r = X509_alias_set1(xcert, data, len);
38435b3e1433Swyllys 					if (r == NULL) {
38445b3e1433Swyllys 						ret = KMF_ERR_PKCS12_FORMAT;
38455b3e1433Swyllys 						goto end;
38465b3e1433Swyllys 					}
38475b3e1433Swyllys 				} else {
38485b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
38495b3e1433Swyllys 					goto end;
38505b3e1433Swyllys 				}
38515b3e1433Swyllys 			}
38525b3e1433Swyllys 			if (sk_X509_push(certlist, xcert) == 0)
38535b3e1433Swyllys 				ret = KMF_ERR_MEMORY;
38545b3e1433Swyllys 			else
38555b3e1433Swyllys 				xcert = NULL;
38565b3e1433Swyllys 			break;
38575b3e1433Swyllys 		case NID_safeContentsBag:
38585b3e1433Swyllys 			return (openssl_parse_bags(bag->value.safes, pass,
38595b3e1433Swyllys 			    keylist, certlist));
38605b3e1433Swyllys 		default:
38615b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
38625b3e1433Swyllys 			break;
38635b3e1433Swyllys 	}
38645b3e1433Swyllys 
38655b3e1433Swyllys 	/*
38665b3e1433Swyllys 	 * Set the ID and/or FriendlyName attributes on the key.
38675b3e1433Swyllys 	 * If converting to PKCS11 objects, these can translate to CKA_ID
38685b3e1433Swyllys 	 * and CKA_LABEL values.
38695b3e1433Swyllys 	 */
38705b3e1433Swyllys 	if (pkey != NULL && ret == KMF_OK) {
38715b3e1433Swyllys 		ASN1_TYPE *attr = NULL;
38725b3e1433Swyllys 		if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
38735b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
38745b3e1433Swyllys 				return (KMF_ERR_MEMORY);
38755b3e1433Swyllys 			attr->value.octet_string =
38765b3e1433Swyllys 			    ASN1_STRING_dup(keyid->value.octet_string);
38775b3e1433Swyllys 			attr->type = V_ASN1_OCTET_STRING;
38785b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.octet_string;
38795b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
38805b3e1433Swyllys 			OPENSSL_free(attr);
38815b3e1433Swyllys 		}
38825b3e1433Swyllys 
38835b3e1433Swyllys 		if (ret == KMF_OK && fname != NULL &&
38845b3e1433Swyllys 		    fname->type == V_ASN1_BMPSTRING) {
38855b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
38865b3e1433Swyllys 				return (KMF_ERR_MEMORY);
38875b3e1433Swyllys 			attr->value.bmpstring =
38885b3e1433Swyllys 			    ASN1_STRING_dup(fname->value.bmpstring);
38895b3e1433Swyllys 			attr->type = V_ASN1_BMPSTRING;
38905b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.bmpstring;
38915b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
38925b3e1433Swyllys 			OPENSSL_free(attr);
38935b3e1433Swyllys 		}
38945b3e1433Swyllys 
38955b3e1433Swyllys 		if (ret == KMF_OK && keylist != NULL &&
38965b3e1433Swyllys 		    sk_EVP_PKEY_push(keylist, pkey) == 0)
38975b3e1433Swyllys 			ret = KMF_ERR_MEMORY;
38985b3e1433Swyllys 	}
38995b3e1433Swyllys 	if (ret == KMF_OK && keylist != NULL)
39005b3e1433Swyllys 		pkey = NULL;
39015b3e1433Swyllys end:
39025b3e1433Swyllys 	if (pkey != NULL)
39035b3e1433Swyllys 		EVP_PKEY_free(pkey);
39045b3e1433Swyllys 	if (xcert != NULL)
39055b3e1433Swyllys 		X509_free(xcert);
39065b3e1433Swyllys 	if (data != NULL)
39075b3e1433Swyllys 		OPENSSL_free(data);
39085b3e1433Swyllys 
39095b3e1433Swyllys 	return (ret);
39105b3e1433Swyllys }
39115b3e1433Swyllys 
39125b3e1433Swyllys static KMF_RETURN
39135b3e1433Swyllys openssl_pkcs12_parse(PKCS12 *p12, char *pin,
39145b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys,
39155b3e1433Swyllys 	STACK_OF(X509) *certs,
39165b3e1433Swyllys 	STACK_OF(X509) *ca)
3917a2d4930dSDan OpenSolaris Anderson /* ARGSUSED3 */
39185b3e1433Swyllys {
39195b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
39205b3e1433Swyllys 	STACK_OF(PKCS7) *asafes = NULL;
39215b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
39225b3e1433Swyllys 	int i, bagnid;
39235b3e1433Swyllys 	PKCS7 *p7;
39245b3e1433Swyllys 
39255b3e1433Swyllys 	if (p12 == NULL || (keys == NULL && certs == NULL))
39265b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
39275b3e1433Swyllys 
39285b3e1433Swyllys 	if (pin == NULL || *pin == NULL) {
39295b3e1433Swyllys 		if (PKCS12_verify_mac(p12, NULL, 0)) {
39305b3e1433Swyllys 			pin = NULL;
39315b3e1433Swyllys 		} else if (PKCS12_verify_mac(p12, "", 0)) {
39325b3e1433Swyllys 			pin = "";
39335b3e1433Swyllys 		} else {
39345b3e1433Swyllys 			return (KMF_ERR_AUTH_FAILED);
39355b3e1433Swyllys 		}
39365b3e1433Swyllys 	} else if (!PKCS12_verify_mac(p12, pin, -1)) {
39375b3e1433Swyllys 		return (KMF_ERR_AUTH_FAILED);
39385b3e1433Swyllys 	}
39395b3e1433Swyllys 
39405b3e1433Swyllys 	if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
39415b3e1433Swyllys 		return (KMF_ERR_PKCS12_FORMAT);
39425b3e1433Swyllys 
39435b3e1433Swyllys 	for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
39445b3e1433Swyllys 		bags = NULL;
3945a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
39465b3e1433Swyllys 		p7 = sk_PKCS7_value(asafes, i);
39475b3e1433Swyllys 		bagnid = OBJ_obj2nid(p7->type);
39485b3e1433Swyllys 
39495b3e1433Swyllys 		if (bagnid == NID_pkcs7_data) {
39505b3e1433Swyllys 			bags = PKCS12_unpack_p7data(p7);
39515b3e1433Swyllys 		} else if (bagnid == NID_pkcs7_encrypted) {
39525b3e1433Swyllys 			bags = PKCS12_unpack_p7encdata(p7, pin,
39535b3e1433Swyllys 			    (pin ? strlen(pin) : 0));
39545b3e1433Swyllys 		} else {
39555b3e1433Swyllys 			continue;
39565b3e1433Swyllys 		}
39575b3e1433Swyllys 		if (bags == NULL) {
39585b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39595b3e1433Swyllys 			goto out;
39605b3e1433Swyllys 		}
39615b3e1433Swyllys 
39625b3e1433Swyllys 		if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
39635b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39645b3e1433Swyllys 
39655b3e1433Swyllys 		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
39665b3e1433Swyllys 	}
39675b3e1433Swyllys out:
39685b3e1433Swyllys 	if (asafes != NULL)
39695b3e1433Swyllys 		sk_PKCS7_pop_free(asafes, PKCS7_free);
39705b3e1433Swyllys 
39715b3e1433Swyllys 	return (ret);
39725b3e1433Swyllys }
39735b3e1433Swyllys 
397499ebb4caSwyllys /*
397599ebb4caSwyllys  * Helper function to decrypt and parse PKCS#12 import file.
397699ebb4caSwyllys  */
397799ebb4caSwyllys static KMF_RETURN
397899ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
39795b3e1433Swyllys 	STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs,
39805b3e1433Swyllys 	STACK_OF(X509) **ca)
3981a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */
398299ebb4caSwyllys {
398399ebb4caSwyllys 	PKCS12			*pk12, *pk12_tmp;
39845b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*pkeylist = NULL;
39855b3e1433Swyllys 	STACK_OF(X509)		*xcertlist = NULL;
39865b3e1433Swyllys 	STACK_OF(X509)		*cacertlist = NULL;
398799ebb4caSwyllys 
398899ebb4caSwyllys 	if ((pk12 = PKCS12_new()) == NULL) {
398999ebb4caSwyllys 		return (KMF_ERR_MEMORY);
399099ebb4caSwyllys 	}
399199ebb4caSwyllys 
399299ebb4caSwyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
399399ebb4caSwyllys 		/* This is ok; it seems to mean there is no more to read. */
399499ebb4caSwyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
399599ebb4caSwyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
399699ebb4caSwyllys 			goto end_extract_pkcs12;
399799ebb4caSwyllys 
399899ebb4caSwyllys 		PKCS12_free(pk12);
399999ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
400099ebb4caSwyllys 	}
400199ebb4caSwyllys 	pk12 = pk12_tmp;
400299ebb4caSwyllys 
40035b3e1433Swyllys 	xcertlist = sk_X509_new_null();
40045b3e1433Swyllys 	if (xcertlist == NULL) {
40055b3e1433Swyllys 		PKCS12_free(pk12);
40065b3e1433Swyllys 		return (KMF_ERR_MEMORY);
40075b3e1433Swyllys 	}
40085b3e1433Swyllys 	pkeylist = sk_EVP_PKEY_new_null();
40095b3e1433Swyllys 	if (pkeylist == NULL) {
40105b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40115b3e1433Swyllys 		PKCS12_free(pk12);
40125b3e1433Swyllys 		return (KMF_ERR_MEMORY);
40135b3e1433Swyllys 	}
40145b3e1433Swyllys 
40155b3e1433Swyllys 	if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
40165b3e1433Swyllys 	    cacertlist) != KMF_OK) {
40175b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40185b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
401999ebb4caSwyllys 		PKCS12_free(pk12);
402099ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
402199ebb4caSwyllys 	}
402299ebb4caSwyllys 
40235b3e1433Swyllys 	if (priv_key && pkeylist)
40245b3e1433Swyllys 		*priv_key = pkeylist;
40255b3e1433Swyllys 	else if (pkeylist)
40265b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
40275b3e1433Swyllys 	if (certs && xcertlist)
40285b3e1433Swyllys 		*certs = xcertlist;
40295b3e1433Swyllys 	else if (xcertlist)
40305b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40315b3e1433Swyllys 	if (ca && cacertlist)
40325b3e1433Swyllys 		*ca = cacertlist;
40335b3e1433Swyllys 	else if (cacertlist)
40345b3e1433Swyllys 		sk_X509_pop_free(cacertlist, X509_free);
403599ebb4caSwyllys 
40365b3e1433Swyllys end_extract_pkcs12:
403799ebb4caSwyllys 
403899ebb4caSwyllys 	PKCS12_free(pk12);
403999ebb4caSwyllys 	return (KMF_OK);
404099ebb4caSwyllys }
404199ebb4caSwyllys 
404299ebb4caSwyllys static KMF_RETURN
404399ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
404499ebb4caSwyllys {
404599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
404699ebb4caSwyllys 	uint32_t sz;
404799ebb4caSwyllys 
404899ebb4caSwyllys 	sz = BN_num_bytes(from);
404999ebb4caSwyllys 	to->val = (uchar_t *)malloc(sz);
405099ebb4caSwyllys 	if (to->val == NULL)
405199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
405299ebb4caSwyllys 
405399ebb4caSwyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
405499ebb4caSwyllys 		free(to->val);
405599ebb4caSwyllys 		to->val = NULL;
405699ebb4caSwyllys 		to->len = 0;
405799ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
405899ebb4caSwyllys 	}
405999ebb4caSwyllys 
406099ebb4caSwyllys 	return (rv);
406199ebb4caSwyllys }
406299ebb4caSwyllys 
406399ebb4caSwyllys static KMF_RETURN
406499ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
406599ebb4caSwyllys {
406699ebb4caSwyllys 	KMF_RETURN rv;
406799ebb4caSwyllys 	KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
406899ebb4caSwyllys 
406999ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
407099ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK)
407199ebb4caSwyllys 		goto cleanup;
407299ebb4caSwyllys 
407399ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK)
407499ebb4caSwyllys 		goto cleanup;
407599ebb4caSwyllys 
407699ebb4caSwyllys 	if (rsa->d != NULL)
407799ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK)
407899ebb4caSwyllys 			goto cleanup;
407999ebb4caSwyllys 
408099ebb4caSwyllys 	if (rsa->p != NULL)
408199ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK)
408299ebb4caSwyllys 			goto cleanup;
408399ebb4caSwyllys 
408499ebb4caSwyllys 	if (rsa->q != NULL)
408599ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK)
408699ebb4caSwyllys 			goto cleanup;
408799ebb4caSwyllys 
408899ebb4caSwyllys 	if (rsa->dmp1 != NULL)
408999ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK)
409099ebb4caSwyllys 			goto cleanup;
409199ebb4caSwyllys 
409299ebb4caSwyllys 	if (rsa->dmq1 != NULL)
409399ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK)
409499ebb4caSwyllys 			goto cleanup;
409599ebb4caSwyllys 
409699ebb4caSwyllys 	if (rsa->iqmp != NULL)
409799ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK)
409899ebb4caSwyllys 			goto cleanup;
409999ebb4caSwyllys cleanup:
410099ebb4caSwyllys 	if (rv != KMF_OK)
410130a5e8faSwyllys 		kmf_free_raw_key(key);
410299ebb4caSwyllys 	else
410399ebb4caSwyllys 		key->keytype = KMF_RSA;
410499ebb4caSwyllys 
410599ebb4caSwyllys 	/*
410699ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
410799ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
410899ebb4caSwyllys 	 */
410999ebb4caSwyllys 	RSA_free(rsa);
411099ebb4caSwyllys 
411199ebb4caSwyllys 	return (rv);
411299ebb4caSwyllys }
411399ebb4caSwyllys 
411499ebb4caSwyllys static KMF_RETURN
411599ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
411699ebb4caSwyllys {
411799ebb4caSwyllys 	KMF_RETURN rv;
411899ebb4caSwyllys 	KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
411999ebb4caSwyllys 
412099ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
412199ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK)
412299ebb4caSwyllys 		goto cleanup;
412399ebb4caSwyllys 
412499ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK)
412599ebb4caSwyllys 		goto cleanup;
412699ebb4caSwyllys 
412799ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK)
412899ebb4caSwyllys 		goto cleanup;
412999ebb4caSwyllys 
413099ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK)
413199ebb4caSwyllys 		goto cleanup;
413299ebb4caSwyllys 
413399ebb4caSwyllys cleanup:
413499ebb4caSwyllys 	if (rv != KMF_OK)
413530a5e8faSwyllys 		kmf_free_raw_key(key);
413699ebb4caSwyllys 	else
413799ebb4caSwyllys 		key->keytype = KMF_DSA;
413899ebb4caSwyllys 
413999ebb4caSwyllys 	/*
414099ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
414199ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
414299ebb4caSwyllys 	 */
414399ebb4caSwyllys 	DSA_free(dsa);
414499ebb4caSwyllys 
414599ebb4caSwyllys 	return (rv);
414699ebb4caSwyllys }
414799ebb4caSwyllys 
414899ebb4caSwyllys static KMF_RETURN
414999ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
41505b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
415199ebb4caSwyllys {
415299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
41535b3e1433Swyllys 	KMF_X509_DER_CERT *list = (*certlist);
41545b3e1433Swyllys 	KMF_X509_DER_CERT cert;
415599ebb4caSwyllys 	int n = (*ncerts);
415699ebb4caSwyllys 
415799ebb4caSwyllys 	if (list == NULL) {
41585b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
415999ebb4caSwyllys 	} else {
41605b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)realloc(list,
41615b3e1433Swyllys 		    sizeof (KMF_X509_DER_CERT) * (n + 1));
416299ebb4caSwyllys 	}
416399ebb4caSwyllys 
416499ebb4caSwyllys 	if (list == NULL)
416599ebb4caSwyllys 		return (KMF_ERR_MEMORY);
416699ebb4caSwyllys 
41675b3e1433Swyllys 	(void) memset(&cert, 0, sizeof (cert));
41685b3e1433Swyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
416999ebb4caSwyllys 	if (rv == KMF_OK) {
41705b3e1433Swyllys 		int len = 0;
41715b3e1433Swyllys 		/* Get the alias name for the cert if there is one */
41725b3e1433Swyllys 		char *a = (char *)X509_alias_get0(sslcert, &len);
41735b3e1433Swyllys 		if (a != NULL)
41745b3e1433Swyllys 			cert.kmf_private.label = strdup(a);
41755b3e1433Swyllys 		cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
41765b3e1433Swyllys 
417799ebb4caSwyllys 		list[n] = cert;
417899ebb4caSwyllys 		(*ncerts) = n + 1;
417999ebb4caSwyllys 
418099ebb4caSwyllys 		*certlist = list;
418199ebb4caSwyllys 	} else {
418299ebb4caSwyllys 		free(list);
418399ebb4caSwyllys 	}
418499ebb4caSwyllys 
418599ebb4caSwyllys 	return (rv);
418699ebb4caSwyllys }
418799ebb4caSwyllys 
418899ebb4caSwyllys static KMF_RETURN
418999ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
419099ebb4caSwyllys 	KMF_RAW_KEY_DATA *newkey, int *nkeys)
419199ebb4caSwyllys {
419299ebb4caSwyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
419399ebb4caSwyllys 	int n = (*nkeys);
419499ebb4caSwyllys 
419599ebb4caSwyllys 	if (list == NULL) {
419699ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
419799ebb4caSwyllys 	} else {
419899ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
419999ebb4caSwyllys 		    sizeof (KMF_RAW_KEY_DATA) * (n + 1));
420099ebb4caSwyllys 	}
420199ebb4caSwyllys 
420299ebb4caSwyllys 	if (list == NULL)
420399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
420499ebb4caSwyllys 
420599ebb4caSwyllys 	list[n] = *newkey;
420699ebb4caSwyllys 	(*nkeys) = n + 1;
420799ebb4caSwyllys 
420899ebb4caSwyllys 	*keylist = list;
420999ebb4caSwyllys 
421099ebb4caSwyllys 	return (KMF_OK);
421199ebb4caSwyllys }
421299ebb4caSwyllys 
42135b3e1433Swyllys static X509_ATTRIBUTE *
42145b3e1433Swyllys find_attr(STACK_OF(X509_ATTRIBUTE) *attrs, int nid)
42155b3e1433Swyllys {
42165b3e1433Swyllys 	X509_ATTRIBUTE *a;
42175b3e1433Swyllys 	int i;
42185b3e1433Swyllys 
42195b3e1433Swyllys 	if (attrs == NULL)
42205b3e1433Swyllys 		return (NULL);
42215b3e1433Swyllys 
42225b3e1433Swyllys 	for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
4223a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
42245b3e1433Swyllys 		a = sk_X509_ATTRIBUTE_value(attrs, i);
42255b3e1433Swyllys 		if (OBJ_obj2nid(a->object) == nid)
42265b3e1433Swyllys 			return (a);
42275b3e1433Swyllys 	}
42285b3e1433Swyllys 	return (NULL);
42295b3e1433Swyllys }
42305b3e1433Swyllys 
423130a5e8faSwyllys static KMF_RETURN
423230a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
423330a5e8faSwyllys {
423430a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
42355b3e1433Swyllys 	X509_ATTRIBUTE *attr;
423630a5e8faSwyllys 
423730a5e8faSwyllys 	if (pkey == NULL || key == NULL)
423830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
423930a5e8faSwyllys 	/* Convert SSL key to raw key */
424030a5e8faSwyllys 	switch (pkey->type) {
424130a5e8faSwyllys 		case EVP_PKEY_RSA:
424230a5e8faSwyllys 			rv = exportRawRSAKey(EVP_PKEY_get1_RSA(pkey),
424330a5e8faSwyllys 			    key);
424430a5e8faSwyllys 			if (rv != KMF_OK)
424530a5e8faSwyllys 				return (rv);
424630a5e8faSwyllys 			break;
424730a5e8faSwyllys 		case EVP_PKEY_DSA:
424830a5e8faSwyllys 			rv = exportRawDSAKey(EVP_PKEY_get1_DSA(pkey),
424930a5e8faSwyllys 			    key);
425030a5e8faSwyllys 			if (rv != KMF_OK)
425130a5e8faSwyllys 				return (rv);
425230a5e8faSwyllys 			break;
425330a5e8faSwyllys 		default:
425430a5e8faSwyllys 			return (KMF_ERR_BAD_PARAMETER);
425530a5e8faSwyllys 	}
42565b3e1433Swyllys 	/*
42575b3e1433Swyllys 	 * If friendlyName, add it to record.
42585b3e1433Swyllys 	 */
42595b3e1433Swyllys 	attr = find_attr(pkey->attributes, NID_friendlyName);
42605b3e1433Swyllys 	if (attr != NULL) {
42615b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
42625b3e1433Swyllys 		int numattr = sk_ASN1_TYPE_num(attr->value.set);
42635b3e1433Swyllys 		if (attr->single == 0 && numattr > 0) {
4264a2d4930dSDan OpenSolaris Anderson 			/* LINTED E_BAD_PTR_CAST_ALIGN */
42655b3e1433Swyllys 			ty = sk_ASN1_TYPE_value(attr->value.set, 0);
42665b3e1433Swyllys 		}
42675b3e1433Swyllys 		if (ty != NULL) {
42685b3e1433Swyllys 			key->label = uni2asc(ty->value.bmpstring->data,
42695b3e1433Swyllys 			    ty->value.bmpstring->length);
42705b3e1433Swyllys 		}
42715b3e1433Swyllys 	} else {
42725b3e1433Swyllys 		key->label = NULL;
42735b3e1433Swyllys 	}
42745b3e1433Swyllys 
42755b3e1433Swyllys 	/*
42765b3e1433Swyllys 	 * If KeyID, add it to record as a KMF_DATA object.
42775b3e1433Swyllys 	 */
42785b3e1433Swyllys 	attr = find_attr(pkey->attributes, NID_localKeyID);
42795b3e1433Swyllys 	if (attr != NULL) {
42805b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
42815b3e1433Swyllys 		int numattr = sk_ASN1_TYPE_num(attr->value.set);
42825b3e1433Swyllys 		if (attr->single == 0 && numattr > 0) {
4283a2d4930dSDan OpenSolaris Anderson 			/* LINTED E_BAD_PTR_CAST_ALIGN */
42845b3e1433Swyllys 			ty = sk_ASN1_TYPE_value(attr->value.set, 0);
42855b3e1433Swyllys 		}
42865b3e1433Swyllys 		key->id.Data = (uchar_t *)malloc(
42875b3e1433Swyllys 		    ty->value.octet_string->length);
42885b3e1433Swyllys 		if (key->id.Data == NULL)
42895b3e1433Swyllys 			return (KMF_ERR_MEMORY);
42905b3e1433Swyllys 		(void) memcpy(key->id.Data, ty->value.octet_string->data,
42915b3e1433Swyllys 		    ty->value.octet_string->length);
42925b3e1433Swyllys 		key->id.Length = ty->value.octet_string->length;
42935b3e1433Swyllys 	} else {
42945b3e1433Swyllys 		(void) memset(&key->id, 0, sizeof (KMF_DATA));
42955b3e1433Swyllys 	}
429630a5e8faSwyllys 
429730a5e8faSwyllys 	return (rv);
429830a5e8faSwyllys }
429999ebb4caSwyllys 
430099ebb4caSwyllys static KMF_RETURN
430199ebb4caSwyllys convertPK12Objects(
430299ebb4caSwyllys 	KMF_HANDLE *kmfh,
43035b3e1433Swyllys 	STACK_OF(EVP_PKEY) *sslkeys,
43045b3e1433Swyllys 	STACK_OF(X509) *sslcert,
43055b3e1433Swyllys 	STACK_OF(X509) *sslcacerts,
430699ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
43075b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
430899ebb4caSwyllys {
430999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
431099ebb4caSwyllys 	KMF_RAW_KEY_DATA key;
431199ebb4caSwyllys 	int i;
431299ebb4caSwyllys 
43135b3e1433Swyllys 	for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
4314a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
43155b3e1433Swyllys 		EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
43165b3e1433Swyllys 		rv = convertToRawKey(pkey, &key);
431730a5e8faSwyllys 		if (rv == KMF_OK)
431899ebb4caSwyllys 			rv = add_key_to_list(keylist, &key, nkeys);
431930a5e8faSwyllys 
432099ebb4caSwyllys 		if (rv != KMF_OK)
432199ebb4caSwyllys 			return (rv);
432299ebb4caSwyllys 	}
432399ebb4caSwyllys 
432499ebb4caSwyllys 	/* Now add the certificate to the certlist */
43255b3e1433Swyllys 	for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
4326a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
43275b3e1433Swyllys 		X509 *cert = sk_X509_value(sslcert, i);
43285b3e1433Swyllys 		rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
432999ebb4caSwyllys 		if (rv != KMF_OK)
433099ebb4caSwyllys 			return (rv);
433199ebb4caSwyllys 	}
433299ebb4caSwyllys 
433399ebb4caSwyllys 	/* Also add any included CA certs to the list */
433471593db2Swyllys 	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
433599ebb4caSwyllys 		X509 *c;
433699ebb4caSwyllys 		/*
433799ebb4caSwyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
433899ebb4caSwyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
433999ebb4caSwyllys 		 * Lint is complaining about the embedded casting, and
434099ebb4caSwyllys 		 * to fix it, you need to fix openssl header files.
434199ebb4caSwyllys 		 */
434299ebb4caSwyllys 		/* LINTED E_BAD_PTR_CAST_ALIGN */
434399ebb4caSwyllys 		c = sk_X509_value(sslcacerts, i);
434499ebb4caSwyllys 
434599ebb4caSwyllys 		/* Now add the ca cert to the certlist */
434699ebb4caSwyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
434799ebb4caSwyllys 		if (rv != KMF_OK)
434899ebb4caSwyllys 			return (rv);
434999ebb4caSwyllys 	}
435099ebb4caSwyllys 	return (rv);
435199ebb4caSwyllys }
435299ebb4caSwyllys 
435399ebb4caSwyllys KMF_RETURN
435430a5e8faSwyllys openssl_import_objects(KMF_HANDLE *kmfh,
435599ebb4caSwyllys 	char *filename, KMF_CREDENTIAL *cred,
43565b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts,
435799ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
435899ebb4caSwyllys {
435999ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
436030a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
436130a5e8faSwyllys 	BIO		*bio = NULL;
43625b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*privkeys = NULL;
43635b3e1433Swyllys 	STACK_OF(X509)		*certs = NULL;
436499ebb4caSwyllys 	STACK_OF(X509)		*cacerts = NULL;
436599ebb4caSwyllys 
436630a5e8faSwyllys 	/*
436730a5e8faSwyllys 	 * auto-detect the file format, regardless of what
436830a5e8faSwyllys 	 * the 'format' parameters in the params say.
436930a5e8faSwyllys 	 */
437030a5e8faSwyllys 	rv = kmf_get_file_format(filename, &format);
437130a5e8faSwyllys 	if (rv != KMF_OK) {
437230a5e8faSwyllys 		return (rv);
437330a5e8faSwyllys 	}
437430a5e8faSwyllys 
437530a5e8faSwyllys 	/* This function only works for PEM or PKCS#12 files */
437630a5e8faSwyllys 	if (format != KMF_FORMAT_PEM &&
437730a5e8faSwyllys 	    format != KMF_FORMAT_PEM_KEYPAIR &&
437830a5e8faSwyllys 	    format != KMF_FORMAT_PKCS12)
437930a5e8faSwyllys 		return (KMF_ERR_ENCODING);
438030a5e8faSwyllys 
438130a5e8faSwyllys 	*certlist = NULL;
438230a5e8faSwyllys 	*keylist = NULL;
438330a5e8faSwyllys 	*ncerts = 0;
438430a5e8faSwyllys 	*nkeys = 0;
438530a5e8faSwyllys 
438630a5e8faSwyllys 	if (format == KMF_FORMAT_PKCS12) {
438799ebb4caSwyllys 		bio = BIO_new_file(filename, "rb");
438899ebb4caSwyllys 		if (bio == NULL) {
438999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
439099ebb4caSwyllys 			rv = KMF_ERR_OPEN_FILE;
439199ebb4caSwyllys 			goto end;
439299ebb4caSwyllys 		}
439399ebb4caSwyllys 
439434acef67Swyllys 		rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
43955b3e1433Swyllys 		    (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
439699ebb4caSwyllys 
439799ebb4caSwyllys 		if (rv  == KMF_OK)
439899ebb4caSwyllys 			/* Convert keys and certs to exportable format */
43995b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
440099ebb4caSwyllys 			    keylist, nkeys, certlist, ncerts);
440130a5e8faSwyllys 	} else {
44025b3e1433Swyllys 		EVP_PKEY *pkey;
44035b3e1433Swyllys 		KMF_DATA *certdata = NULL;
44045b3e1433Swyllys 		KMF_X509_DER_CERT *kmfcerts = NULL;
44055b3e1433Swyllys 		int i;
440630a5e8faSwyllys 		rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
440734acef67Swyllys 		    (uchar_t *)cred->cred, (uint32_t)cred->credlen,
44085b3e1433Swyllys 		    &pkey, &certdata, ncerts);
440971593db2Swyllys 
441071593db2Swyllys 		/* Reached end of import file? */
44115b3e1433Swyllys 		if (rv == KMF_OK && pkey != NULL) {
44125b3e1433Swyllys 			privkeys = sk_EVP_PKEY_new_null();
44135b3e1433Swyllys 			if (privkeys == NULL) {
44145b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
44155b3e1433Swyllys 				goto end;
44165b3e1433Swyllys 			}
44175b3e1433Swyllys 			(void) sk_EVP_PKEY_push(privkeys, pkey);
44185b3e1433Swyllys 			/* convert the certificate list here */
44195b3e1433Swyllys 			if (*ncerts > 0 && certlist != NULL) {
4420e65e5c2dSWyllys Ingersoll 				kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
44215b3e1433Swyllys 				    sizeof (KMF_X509_DER_CERT));
44225b3e1433Swyllys 				if (kmfcerts == NULL) {
44235b3e1433Swyllys 					rv = KMF_ERR_MEMORY;
44245b3e1433Swyllys 					goto end;
44255b3e1433Swyllys 				}
44265b3e1433Swyllys 				for (i = 0; i < *ncerts; i++) {
44275b3e1433Swyllys 					kmfcerts[i].certificate = certdata[i];
44285b3e1433Swyllys 					kmfcerts[i].kmf_private.keystore_type =
44295b3e1433Swyllys 					    KMF_KEYSTORE_OPENSSL;
44305b3e1433Swyllys 				}
44315b3e1433Swyllys 				*certlist = kmfcerts;
44325b3e1433Swyllys 			}
44335b3e1433Swyllys 			/*
44345b3e1433Swyllys 			 * Convert keys to exportable format, the certs
44355b3e1433Swyllys 			 * are already OK.
44365b3e1433Swyllys 			 */
44375b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
443871593db2Swyllys 			    keylist, nkeys, NULL, NULL);
443930a5e8faSwyllys 		}
44405b3e1433Swyllys 	}
444171593db2Swyllys end:
444230a5e8faSwyllys 	if (bio != NULL)
444399ebb4caSwyllys 		(void) BIO_free(bio);
444499ebb4caSwyllys 
44455b3e1433Swyllys 	if (privkeys)
44465b3e1433Swyllys 		sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
44475b3e1433Swyllys 	if (certs)
44485b3e1433Swyllys 		sk_X509_pop_free(certs, X509_free);
444930a5e8faSwyllys 	if (cacerts)
44505b3e1433Swyllys 		sk_X509_pop_free(cacerts, X509_free);
445130a5e8faSwyllys 
445299ebb4caSwyllys 	return (rv);
445399ebb4caSwyllys }
445499ebb4caSwyllys 
445599ebb4caSwyllys static KMF_RETURN
445699ebb4caSwyllys create_deskey(DES_cblock **deskey)
445799ebb4caSwyllys {
445899ebb4caSwyllys 	DES_cblock *key;
445999ebb4caSwyllys 
446099ebb4caSwyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
446199ebb4caSwyllys 	if (key == NULL) {
446299ebb4caSwyllys 		return (KMF_ERR_MEMORY);
446399ebb4caSwyllys 	}
446499ebb4caSwyllys 
446599ebb4caSwyllys 	if (DES_random_key(key) == 0) {
446699ebb4caSwyllys 		free(key);
446799ebb4caSwyllys 		return (KMF_ERR_KEYGEN_FAILED);
446899ebb4caSwyllys 	}
446999ebb4caSwyllys 
447099ebb4caSwyllys 	*deskey = key;
447199ebb4caSwyllys 	return (KMF_OK);
447299ebb4caSwyllys }
447399ebb4caSwyllys 
447499ebb4caSwyllys #define	KEYGEN_RETRY 3
447599ebb4caSwyllys #define	DES3_KEY_SIZE 24
447699ebb4caSwyllys 
447799ebb4caSwyllys static KMF_RETURN
447899ebb4caSwyllys create_des3key(unsigned char **des3key)
447999ebb4caSwyllys {
448099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
448199ebb4caSwyllys 	DES_cblock *deskey1 = NULL;
448299ebb4caSwyllys 	DES_cblock *deskey2 = NULL;
448399ebb4caSwyllys 	DES_cblock *deskey3 = NULL;
448499ebb4caSwyllys 	unsigned char *newkey = NULL;
448599ebb4caSwyllys 	int retry;
448699ebb4caSwyllys 
448799ebb4caSwyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
448899ebb4caSwyllys 		return (KMF_ERR_MEMORY);
448999ebb4caSwyllys 	}
449099ebb4caSwyllys 
449199ebb4caSwyllys 	/* create the 1st DES key */
449299ebb4caSwyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
449399ebb4caSwyllys 		goto out;
449499ebb4caSwyllys 	}
449599ebb4caSwyllys 
449699ebb4caSwyllys 	/*
449799ebb4caSwyllys 	 * Create the 2nd DES key and make sure its value is different
449899ebb4caSwyllys 	 * from the 1st DES key.
449999ebb4caSwyllys 	 */
450099ebb4caSwyllys 	retry = 0;
450199ebb4caSwyllys 	do {
450299ebb4caSwyllys 		if (deskey2 != NULL) {
450399ebb4caSwyllys 			free(deskey2);
450499ebb4caSwyllys 			deskey2 = NULL;
450599ebb4caSwyllys 		}
450699ebb4caSwyllys 
450799ebb4caSwyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
450899ebb4caSwyllys 			goto out;
450999ebb4caSwyllys 		}
451099ebb4caSwyllys 
451199ebb4caSwyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
451299ebb4caSwyllys 		    == 0) {
451399ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
451499ebb4caSwyllys 			retry++;
451599ebb4caSwyllys 		}
451699ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
451799ebb4caSwyllys 
451899ebb4caSwyllys 	if (ret != KMF_OK) {
451999ebb4caSwyllys 		goto out;
452099ebb4caSwyllys 	}
452199ebb4caSwyllys 
452299ebb4caSwyllys 	/*
452399ebb4caSwyllys 	 * Create the 3rd DES key and make sure its value is different
452499ebb4caSwyllys 	 * from the 2nd DES key.
452599ebb4caSwyllys 	 */
452699ebb4caSwyllys 	retry = 0;
452799ebb4caSwyllys 	do {
452899ebb4caSwyllys 		if (deskey3 != NULL) {
452999ebb4caSwyllys 			free(deskey3);
453099ebb4caSwyllys 			deskey3 = NULL;
453199ebb4caSwyllys 		}
453299ebb4caSwyllys 
453399ebb4caSwyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
453499ebb4caSwyllys 			goto out;
453599ebb4caSwyllys 		}
453699ebb4caSwyllys 
453799ebb4caSwyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
453899ebb4caSwyllys 		    == 0) {
453999ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
454099ebb4caSwyllys 			retry++;
454199ebb4caSwyllys 		}
454299ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
454399ebb4caSwyllys 
454499ebb4caSwyllys 	if (ret != KMF_OK) {
454599ebb4caSwyllys 		goto out;
454699ebb4caSwyllys 	}
454799ebb4caSwyllys 
454899ebb4caSwyllys 	/* Concatenate 3 DES keys into a DES3 key */
454999ebb4caSwyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
455099ebb4caSwyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
455199ebb4caSwyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
455299ebb4caSwyllys 	*des3key = newkey;
455399ebb4caSwyllys 
455499ebb4caSwyllys out:
455599ebb4caSwyllys 	if (deskey1 != NULL)
455699ebb4caSwyllys 		free(deskey1);
455799ebb4caSwyllys 
455899ebb4caSwyllys 	if (deskey2 != NULL)
455999ebb4caSwyllys 		free(deskey2);
456099ebb4caSwyllys 
456199ebb4caSwyllys 	if (deskey3 != NULL)
456299ebb4caSwyllys 		free(deskey3);
456399ebb4caSwyllys 
456499ebb4caSwyllys 	if (ret != KMF_OK && newkey != NULL)
456599ebb4caSwyllys 		free(newkey);
456699ebb4caSwyllys 
456799ebb4caSwyllys 	return (ret);
456899ebb4caSwyllys }
456999ebb4caSwyllys 
457099ebb4caSwyllys KMF_RETURN
457130a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
457230a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
457399ebb4caSwyllys {
457499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
457599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
457699ebb4caSwyllys 	char *fullpath = NULL;
457799ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
457899ebb4caSwyllys 	DES_cblock *deskey = NULL;
457999ebb4caSwyllys 	unsigned char *des3key = NULL;
458099ebb4caSwyllys 	unsigned char *random = NULL;
458199ebb4caSwyllys 	int fd = -1;
458230a5e8faSwyllys 	KMF_KEY_HANDLE *symkey;
458330a5e8faSwyllys 	KMF_KEY_ALG keytype;
458430a5e8faSwyllys 	uint32_t keylen;
458530a5e8faSwyllys 	uint32_t keylen_size = sizeof (keylen);
458630a5e8faSwyllys 	char *dirpath;
458730a5e8faSwyllys 	char *keyfile;
458899ebb4caSwyllys 
458999ebb4caSwyllys 	if (kmfh == NULL)
459099ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
459199ebb4caSwyllys 
459230a5e8faSwyllys 	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
459330a5e8faSwyllys 	if (symkey == NULL)
459499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
459599ebb4caSwyllys 
459630a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
459730a5e8faSwyllys 
459830a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
459930a5e8faSwyllys 	if (keyfile == NULL)
460030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
460130a5e8faSwyllys 
460230a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
460330a5e8faSwyllys 	    (void *)&keytype, NULL);
460430a5e8faSwyllys 	if (ret != KMF_OK)
460530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
460630a5e8faSwyllys 
460730a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
460830a5e8faSwyllys 	    &keylen, &keylen_size);
460930a5e8faSwyllys 	if (ret == KMF_ERR_ATTR_NOT_FOUND &&
461030a5e8faSwyllys 	    (keytype == KMF_DES || keytype == KMF_DES3))
461130a5e8faSwyllys 		/* keylength is not required for DES and 3DES */
461230a5e8faSwyllys 		ret = KMF_OK;
461330a5e8faSwyllys 	if (ret != KMF_OK)
461430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
461530a5e8faSwyllys 
461630a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
461799ebb4caSwyllys 	if (fullpath == NULL)
461899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
461999ebb4caSwyllys 
462099ebb4caSwyllys 	/* If the requested file exists, return an error */
462130a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
462299ebb4caSwyllys 		free(fullpath);
462399ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
462499ebb4caSwyllys 	}
462599ebb4caSwyllys 
462699ebb4caSwyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
462799ebb4caSwyllys 	if (fd == -1) {
462899ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
462999ebb4caSwyllys 		goto out;
463099ebb4caSwyllys 	}
463199ebb4caSwyllys 
463299ebb4caSwyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
463399ebb4caSwyllys 	if (rkey == NULL) {
463499ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
463599ebb4caSwyllys 		goto out;
463699ebb4caSwyllys 	}
463799ebb4caSwyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
463899ebb4caSwyllys 
463930a5e8faSwyllys 	if (keytype == KMF_DES) {
464099ebb4caSwyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
464199ebb4caSwyllys 			goto out;
464299ebb4caSwyllys 		}
464399ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)deskey;
464499ebb4caSwyllys 		rkey->keydata.len = 8;
464599ebb4caSwyllys 
464699ebb4caSwyllys 		symkey->keyalg = KMF_DES;
464799ebb4caSwyllys 
464830a5e8faSwyllys 	} else if (keytype == KMF_DES3) {
464999ebb4caSwyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
465099ebb4caSwyllys 			goto out;
465199ebb4caSwyllys 		}
465299ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)des3key;
465399ebb4caSwyllys 		rkey->keydata.len = DES3_KEY_SIZE;
465499ebb4caSwyllys 		symkey->keyalg = KMF_DES3;
46559b37d296Swyllys 
465630a5e8faSwyllys 	} else if (keytype == KMF_AES || keytype == KMF_RC4 ||
465730a5e8faSwyllys 	    keytype == KMF_GENERIC_SECRET) {
465899ebb4caSwyllys 		int bytes;
465999ebb4caSwyllys 
466030a5e8faSwyllys 		if (keylen % 8 != 0) {
466199ebb4caSwyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
466299ebb4caSwyllys 			goto out;
466399ebb4caSwyllys 		}
466499ebb4caSwyllys 
466530a5e8faSwyllys 		if (keytype == KMF_AES) {
466630a5e8faSwyllys 			if (keylen != 128 &&
466730a5e8faSwyllys 			    keylen != 192 &&
466830a5e8faSwyllys 			    keylen != 256) {
466999ebb4caSwyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
467099ebb4caSwyllys 				goto out;
467199ebb4caSwyllys 			}
467299ebb4caSwyllys 		}
467399ebb4caSwyllys 
467430a5e8faSwyllys 		bytes = keylen/8;
467599ebb4caSwyllys 		random = malloc(bytes);
467699ebb4caSwyllys 		if (random == NULL) {
467799ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
467899ebb4caSwyllys 			goto out;
467999ebb4caSwyllys 		}
468099ebb4caSwyllys 		if (RAND_bytes(random, bytes) != 1) {
468199ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
468299ebb4caSwyllys 			goto out;
468399ebb4caSwyllys 		}
468499ebb4caSwyllys 
468599ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)random;
468699ebb4caSwyllys 		rkey->keydata.len = bytes;
468730a5e8faSwyllys 		symkey->keyalg = keytype;
468899ebb4caSwyllys 
468999ebb4caSwyllys 	} else {
469099ebb4caSwyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
469199ebb4caSwyllys 		goto out;
469299ebb4caSwyllys 	}
469399ebb4caSwyllys 
469499ebb4caSwyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
469599ebb4caSwyllys 
469699ebb4caSwyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
469799ebb4caSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
469899ebb4caSwyllys 	symkey->keylabel = (char *)fullpath;
469999ebb4caSwyllys 	symkey->israw = TRUE;
470099ebb4caSwyllys 	symkey->keyp = rkey;
470199ebb4caSwyllys 
470299ebb4caSwyllys out:
470399ebb4caSwyllys 	if (fd != -1)
470499ebb4caSwyllys 		(void) close(fd);
470599ebb4caSwyllys 
470699ebb4caSwyllys 	if (ret != KMF_OK && fullpath != NULL) {
470799ebb4caSwyllys 		free(fullpath);
470899ebb4caSwyllys 	}
470999ebb4caSwyllys 	if (ret != KMF_OK) {
471030a5e8faSwyllys 		kmf_free_raw_sym_key(rkey);
471199ebb4caSwyllys 		symkey->keyp = NULL;
471299ebb4caSwyllys 		symkey->keyalg = KMF_KEYALG_NONE;
471399ebb4caSwyllys 	}
471499ebb4caSwyllys 
471599ebb4caSwyllys 	return (ret);
471699ebb4caSwyllys }
471799ebb4caSwyllys 
471899ebb4caSwyllys /*
471999ebb4caSwyllys  * Check a file to see if it is a CRL file with PEM or DER format.
472099ebb4caSwyllys  * If success, return its format in the "pformat" argument.
472199ebb4caSwyllys  */
472299ebb4caSwyllys KMF_RETURN
472399ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
472499ebb4caSwyllys {
472599ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
472699ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
472799ebb4caSwyllys 	BIO		*bio = NULL;
472899ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
472999ebb4caSwyllys 
473099ebb4caSwyllys 	if (filename == NULL) {
473199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
473299ebb4caSwyllys 	}
473399ebb4caSwyllys 
473499ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
473599ebb4caSwyllys 	if (bio == NULL)	{
473699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
473799ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
473899ebb4caSwyllys 		goto out;
473999ebb4caSwyllys 	}
474099ebb4caSwyllys 
474199ebb4caSwyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
474299ebb4caSwyllys 		*pformat = KMF_FORMAT_PEM;
474399ebb4caSwyllys 		goto out;
474499ebb4caSwyllys 	}
474599ebb4caSwyllys 	(void) BIO_free(bio);
474699ebb4caSwyllys 
474799ebb4caSwyllys 	/*
474899ebb4caSwyllys 	 * Now try to read it as raw DER data.
474999ebb4caSwyllys 	 */
475099ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
475199ebb4caSwyllys 	if (bio == NULL)	{
475299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
475399ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
475499ebb4caSwyllys 		goto out;
475599ebb4caSwyllys 	}
475699ebb4caSwyllys 
475799ebb4caSwyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
475899ebb4caSwyllys 		*pformat = KMF_FORMAT_ASN1;
475999ebb4caSwyllys 	} else {
476099ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
476199ebb4caSwyllys 	}
476299ebb4caSwyllys 
476399ebb4caSwyllys out:
476499ebb4caSwyllys 	if (bio != NULL)
476599ebb4caSwyllys 		(void) BIO_free(bio);
476699ebb4caSwyllys 
476799ebb4caSwyllys 	if (xcrl != NULL)
476899ebb4caSwyllys 		X509_CRL_free(xcrl);
476999ebb4caSwyllys 
477099ebb4caSwyllys 	return (ret);
477199ebb4caSwyllys }
477299ebb4caSwyllys 
477399ebb4caSwyllys KMF_RETURN
477499ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
477599ebb4caSwyllys     KMF_RAW_SYM_KEY *rkey)
477699ebb4caSwyllys {
477799ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
477899ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
477999ebb4caSwyllys 	KMF_DATA	keyvalue;
478099ebb4caSwyllys 
478199ebb4caSwyllys 	if (kmfh == NULL)
478299ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
478399ebb4caSwyllys 
478499ebb4caSwyllys 	if (symkey == NULL || rkey == NULL)
478599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
478699ebb4caSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
478799ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
478899ebb4caSwyllys 
478999ebb4caSwyllys 	if (symkey->israw) {
479099ebb4caSwyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
479199ebb4caSwyllys 
479299ebb4caSwyllys 		if (rawkey == NULL ||
479399ebb4caSwyllys 		    rawkey->keydata.val == NULL ||
479499ebb4caSwyllys 		    rawkey->keydata.len == 0)
479599ebb4caSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
479699ebb4caSwyllys 
479799ebb4caSwyllys 		rkey->keydata.len = rawkey->keydata.len;
479899ebb4caSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
479999ebb4caSwyllys 			return (KMF_ERR_MEMORY);
480099ebb4caSwyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
480199ebb4caSwyllys 		    rkey->keydata.len);
480299ebb4caSwyllys 	} else {
480330a5e8faSwyllys 		rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
480499ebb4caSwyllys 		if (rv != KMF_OK)
480599ebb4caSwyllys 			return (rv);
480699ebb4caSwyllys 		rkey->keydata.len = keyvalue.Length;
480799ebb4caSwyllys 		rkey->keydata.val = keyvalue.Data;
480899ebb4caSwyllys 	}
480999ebb4caSwyllys 
481099ebb4caSwyllys 	return (rv);
481199ebb4caSwyllys }
481202744e81Swyllys 
481302744e81Swyllys /*
481430a5e8faSwyllys  * substitute for the unsafe access(2) function.
481530a5e8faSwyllys  * If the file in question already exists, return 1.
481630a5e8faSwyllys  * else 0.  If an error occurs during testing (other
481730a5e8faSwyllys  * than EEXIST), return -1.
481830a5e8faSwyllys  */
481930a5e8faSwyllys static int
482030a5e8faSwyllys test_for_file(char *filename, mode_t mode)
482130a5e8faSwyllys {
482230a5e8faSwyllys 	int fd;
482330a5e8faSwyllys 
482430a5e8faSwyllys 	/*
482530a5e8faSwyllys 	 * Try to create the file with the EXCL flag.
482630a5e8faSwyllys 	 * The call should fail if the file exists.
482730a5e8faSwyllys 	 */
482830a5e8faSwyllys 	fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
482930a5e8faSwyllys 	if (fd == -1 && errno == EEXIST)
483030a5e8faSwyllys 		return (1);
483130a5e8faSwyllys 	else if (fd == -1) /* some other error */
483230a5e8faSwyllys 		return (-1);
483330a5e8faSwyllys 
483430a5e8faSwyllys 	/* The file did NOT exist.  Delete the testcase. */
483530a5e8faSwyllys 	(void) close(fd);
483630a5e8faSwyllys 	(void) unlink(filename);
483730a5e8faSwyllys 	return (0);
483830a5e8faSwyllys }
483930a5e8faSwyllys 
484030a5e8faSwyllys KMF_RETURN
484130a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
484230a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
484330a5e8faSwyllys {
484430a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
484530a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
484630a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
484730a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
484830a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
484930a5e8faSwyllys 	KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
485030a5e8faSwyllys 	KMF_CREDENTIAL cred = {NULL, 0};
485130a5e8faSwyllys 	BIO *out = NULL;
485230a5e8faSwyllys 	int keys = 0;
485330a5e8faSwyllys 	char *fullpath = NULL;
485430a5e8faSwyllys 	char *keyfile = NULL;
485530a5e8faSwyllys 	char *dirpath = NULL;
485630a5e8faSwyllys 
485730a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
485830a5e8faSwyllys 	if (pubkey != NULL)
485930a5e8faSwyllys 		keys++;
486030a5e8faSwyllys 
486130a5e8faSwyllys 	prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
486230a5e8faSwyllys 	if (prikey != NULL)
486330a5e8faSwyllys 		keys++;
486430a5e8faSwyllys 
486530a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
486630a5e8faSwyllys 	if (rawkey != NULL)
486730a5e8faSwyllys 		keys++;
486830a5e8faSwyllys 
486930a5e8faSwyllys 	/*
487030a5e8faSwyllys 	 * Exactly 1 type of key must be passed to this function.
487130a5e8faSwyllys 	 */
487230a5e8faSwyllys 	if (keys != 1)
487330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
487430a5e8faSwyllys 
487530a5e8faSwyllys 	keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
487630a5e8faSwyllys 	    numattr);
487730a5e8faSwyllys 	if (keyfile == NULL)
487830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
487930a5e8faSwyllys 
488030a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
488130a5e8faSwyllys 
488230a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
488330a5e8faSwyllys 
488430a5e8faSwyllys 	/* Once we have the full path, we don't need the pieces */
488530a5e8faSwyllys 	if (fullpath == NULL)
488630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
488730a5e8faSwyllys 
488830a5e8faSwyllys 	/* If the requested file exists, return an error */
488930a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
489030a5e8faSwyllys 		free(fullpath);
489130a5e8faSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
489230a5e8faSwyllys 	}
489330a5e8faSwyllys 
489430a5e8faSwyllys 	rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
489530a5e8faSwyllys 	    &format, NULL);
489630a5e8faSwyllys 	if (rv != KMF_OK)
489730a5e8faSwyllys 		/* format is optional. */
489830a5e8faSwyllys 		rv = KMF_OK;
489930a5e8faSwyllys 
490030a5e8faSwyllys 	/* CRED is not required for OpenSSL files */
490130a5e8faSwyllys 	(void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
490230a5e8faSwyllys 	    &cred, NULL);
490330a5e8faSwyllys 
490430a5e8faSwyllys 	/* Store the private key to the keyfile */
490530a5e8faSwyllys 	out = BIO_new_file(fullpath, "wb");
490630a5e8faSwyllys 	if (out == NULL) {
490730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
490830a5e8faSwyllys 		rv = KMF_ERR_OPEN_FILE;
490930a5e8faSwyllys 		goto end;
491030a5e8faSwyllys 	}
491130a5e8faSwyllys 
491230a5e8faSwyllys 	if (prikey != NULL && prikey->keyp != NULL) {
491330a5e8faSwyllys 		if (prikey->keyalg == KMF_RSA ||
491430a5e8faSwyllys 		    prikey->keyalg == KMF_DSA) {
491530a5e8faSwyllys 			pkey = (EVP_PKEY *)prikey->keyp;
491630a5e8faSwyllys 
491730a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
491830a5e8faSwyllys 			    out, &cred, pkey, TRUE);
491930a5e8faSwyllys 
492030a5e8faSwyllys 			if (rv == KMF_OK && prikey->keylabel == NULL) {
492130a5e8faSwyllys 				prikey->keylabel = strdup(fullpath);
492230a5e8faSwyllys 				if (prikey->keylabel == NULL)
492330a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
492430a5e8faSwyllys 			}
492530a5e8faSwyllys 		}
492630a5e8faSwyllys 	} else if (pubkey != NULL && pubkey->keyp != NULL) {
492730a5e8faSwyllys 		if (pubkey->keyalg == KMF_RSA ||
492830a5e8faSwyllys 		    pubkey->keyalg == KMF_DSA) {
492930a5e8faSwyllys 			pkey = (EVP_PKEY *)pubkey->keyp;
493030a5e8faSwyllys 
493130a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
493230a5e8faSwyllys 			    out, &cred, pkey, FALSE);
493330a5e8faSwyllys 
493430a5e8faSwyllys 			if (rv == KMF_OK && pubkey->keylabel == NULL) {
493530a5e8faSwyllys 				pubkey->keylabel = strdup(fullpath);
493630a5e8faSwyllys 				if (pubkey->keylabel == NULL)
493730a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
493830a5e8faSwyllys 			}
493930a5e8faSwyllys 		}
494030a5e8faSwyllys 	} else if (rawkey != NULL) {
494130a5e8faSwyllys 		if (rawkey->keytype == KMF_RSA) {
494230a5e8faSwyllys 			pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
494330a5e8faSwyllys 		} else if (rawkey->keytype == KMF_DSA) {
494430a5e8faSwyllys 			pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
494530a5e8faSwyllys 		} else {
494630a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
494730a5e8faSwyllys 		}
49485b3e1433Swyllys 		if (pkey != NULL) {
494973cc0e02Swyllys 			KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
495073cc0e02Swyllys 
495173cc0e02Swyllys 			rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
495273cc0e02Swyllys 			    (void *)&kclass, NULL);
495373cc0e02Swyllys 			if (rv != KMF_OK)
495473cc0e02Swyllys 				rv = KMF_OK;
49555b3e1433Swyllys 			rv = ssl_write_key(kmfh, format, out,
495673cc0e02Swyllys 			    &cred, pkey, (kclass == KMF_ASYM_PRI));
49575b3e1433Swyllys 			EVP_PKEY_free(pkey);
49585b3e1433Swyllys 		}
495930a5e8faSwyllys 	}
496030a5e8faSwyllys 
496130a5e8faSwyllys end:
496230a5e8faSwyllys 
496330a5e8faSwyllys 	if (out)
496430a5e8faSwyllys 		(void) BIO_free(out);
496530a5e8faSwyllys 
49665b3e1433Swyllys 
496730a5e8faSwyllys 	if (rv == KMF_OK)
496830a5e8faSwyllys 		(void) chmod(fullpath, 0400);
496930a5e8faSwyllys 
497030a5e8faSwyllys 	free(fullpath);
497130a5e8faSwyllys 	return (rv);
497230a5e8faSwyllys }
497330a5e8faSwyllys 
497430a5e8faSwyllys KMF_RETURN
497530a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
497630a5e8faSwyllys {
497730a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
497830a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
497930a5e8faSwyllys 	X509_CRL *xcrl = NULL;
498030a5e8faSwyllys 	X509 *xcert = NULL;
498130a5e8faSwyllys 	EVP_PKEY *pkey;
498230a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
498330a5e8faSwyllys 	BIO *in = NULL, *out = NULL;
498430a5e8faSwyllys 	int openssl_ret = 0;
498530a5e8faSwyllys 	KMF_ENCODE_FORMAT outformat;
498630a5e8faSwyllys 	boolean_t crlcheck = FALSE;
498730a5e8faSwyllys 	char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
498830a5e8faSwyllys 
498930a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
499030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
499130a5e8faSwyllys 	}
499230a5e8faSwyllys 
499330a5e8faSwyllys 	/* CRL check is optional */
499430a5e8faSwyllys 	(void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
499530a5e8faSwyllys 	    &crlcheck, NULL);
499630a5e8faSwyllys 
499730a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
499830a5e8faSwyllys 	if (crlcheck == B_TRUE && certfile == NULL) {
499930a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
500030a5e8faSwyllys 	}
500130a5e8faSwyllys 
500230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
500330a5e8faSwyllys 	incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
500430a5e8faSwyllys 	outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
500530a5e8faSwyllys 
500630a5e8faSwyllys 	crlfile = get_fullpath(dirpath, incrl);
500730a5e8faSwyllys 
500830a5e8faSwyllys 	if (crlfile == NULL)
500930a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
501030a5e8faSwyllys 
501130a5e8faSwyllys 	outcrlfile = get_fullpath(dirpath, outcrl);
501230a5e8faSwyllys 	if (outcrlfile == NULL)
501330a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
501430a5e8faSwyllys 
501530a5e8faSwyllys 	if (isdir(outcrlfile)) {
501630a5e8faSwyllys 		free(outcrlfile);
501730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
501830a5e8faSwyllys 	}
501930a5e8faSwyllys 
502030a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
502130a5e8faSwyllys 	if (ret != KMF_OK) {
502230a5e8faSwyllys 		free(outcrlfile);
502330a5e8faSwyllys 		return (ret);
502430a5e8faSwyllys 	}
502530a5e8faSwyllys 
502630a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
502730a5e8faSwyllys 	if (in == NULL)	{
502830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
502930a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
503030a5e8faSwyllys 		goto end;
503130a5e8faSwyllys 	}
503230a5e8faSwyllys 
503330a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
503430a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
503530a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
503630a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
503730a5e8faSwyllys 	}
503830a5e8faSwyllys 
503930a5e8faSwyllys 	if (xcrl == NULL) {
504030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
504130a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
504230a5e8faSwyllys 		goto end;
504330a5e8faSwyllys 	}
504430a5e8faSwyllys 
504530a5e8faSwyllys 	/* If bypasscheck is specified, no need to verify. */
504630a5e8faSwyllys 	if (crlcheck == B_FALSE)
504730a5e8faSwyllys 		goto output;
504830a5e8faSwyllys 
504930a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
505030a5e8faSwyllys 	if (ret != KMF_OK)
505130a5e8faSwyllys 		goto end;
505230a5e8faSwyllys 
505330a5e8faSwyllys 	/* Read in the CA cert file and convert to X509 */
505430a5e8faSwyllys 	if (BIO_read_filename(in, certfile) <= 0) {
505530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
505630a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
505730a5e8faSwyllys 		goto end;
505830a5e8faSwyllys 	}
505930a5e8faSwyllys 
506030a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
506130a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
506230a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
506330a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
506430a5e8faSwyllys 	} else {
506530a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
506630a5e8faSwyllys 		goto end;
506730a5e8faSwyllys 	}
506830a5e8faSwyllys 
506930a5e8faSwyllys 	if (xcert == NULL) {
507030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
507130a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
507230a5e8faSwyllys 		goto end;
507330a5e8faSwyllys 	}
507430a5e8faSwyllys 	/* Now get the public key from the CA cert */
507530a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
507630a5e8faSwyllys 	if (pkey == NULL) {
507730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
507830a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
507930a5e8faSwyllys 		goto end;
508030a5e8faSwyllys 	}
508130a5e8faSwyllys 
508230a5e8faSwyllys 	/* Verify the CRL with the CA's public key */
508330a5e8faSwyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
508430a5e8faSwyllys 	EVP_PKEY_free(pkey);
508530a5e8faSwyllys 	if (openssl_ret > 0) {
508630a5e8faSwyllys 		ret = KMF_OK;  /* verify succeed */
508730a5e8faSwyllys 	} else {
508830a5e8faSwyllys 		SET_ERROR(kmfh, openssl_ret);
508930a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
509030a5e8faSwyllys 	}
509130a5e8faSwyllys 
509230a5e8faSwyllys output:
509330a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
509430a5e8faSwyllys 	    &outformat, NULL);
509530a5e8faSwyllys 	if (ret != KMF_OK) {
509630a5e8faSwyllys 		ret = KMF_OK;
509730a5e8faSwyllys 		outformat = KMF_FORMAT_PEM;
509830a5e8faSwyllys 	}
509930a5e8faSwyllys 
510030a5e8faSwyllys 	out = BIO_new_file(outcrlfile, "wb");
510130a5e8faSwyllys 	if (out == NULL) {
510230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
510330a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
510430a5e8faSwyllys 		goto end;
510530a5e8faSwyllys 	}
510630a5e8faSwyllys 
510730a5e8faSwyllys 	if (outformat == KMF_FORMAT_ASN1) {
510830a5e8faSwyllys 		openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
510930a5e8faSwyllys 	} else if (outformat == KMF_FORMAT_PEM) {
511030a5e8faSwyllys 		openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
511130a5e8faSwyllys 	} else {
511230a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
511330a5e8faSwyllys 		goto end;
511430a5e8faSwyllys 	}
511530a5e8faSwyllys 
511630a5e8faSwyllys 	if (openssl_ret <= 0) {
511730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
511830a5e8faSwyllys 		ret = KMF_ERR_WRITE_FILE;
511930a5e8faSwyllys 	} else {
512030a5e8faSwyllys 		ret = KMF_OK;
512130a5e8faSwyllys 	}
512230a5e8faSwyllys 
512330a5e8faSwyllys end:
512430a5e8faSwyllys 	if (xcrl != NULL)
512530a5e8faSwyllys 		X509_CRL_free(xcrl);
512630a5e8faSwyllys 
512730a5e8faSwyllys 	if (xcert != NULL)
512830a5e8faSwyllys 		X509_free(xcert);
512930a5e8faSwyllys 
513030a5e8faSwyllys 	if (in != NULL)
513130a5e8faSwyllys 		(void) BIO_free(in);
513230a5e8faSwyllys 
513330a5e8faSwyllys 	if (out != NULL)
513430a5e8faSwyllys 		(void) BIO_free(out);
513530a5e8faSwyllys 
513630a5e8faSwyllys 	if (outcrlfile != NULL)
513730a5e8faSwyllys 		free(outcrlfile);
513830a5e8faSwyllys 
513930a5e8faSwyllys 	return (ret);
514030a5e8faSwyllys }
514130a5e8faSwyllys 
514230a5e8faSwyllys KMF_RETURN
514330a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
514430a5e8faSwyllys {
514530a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
514630a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
514730a5e8faSwyllys 	X509_CRL   *x = NULL;
514830a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
514930a5e8faSwyllys 	char *crlfile = NULL;
515030a5e8faSwyllys 	BIO *in = NULL;
515130a5e8faSwyllys 	BIO *mem = NULL;
515230a5e8faSwyllys 	long len;
515330a5e8faSwyllys 	char *memptr;
515430a5e8faSwyllys 	char *data = NULL;
515530a5e8faSwyllys 	char **crldata;
515630a5e8faSwyllys 	char *crlfilename, *dirpath;
515730a5e8faSwyllys 
515830a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
515930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
516030a5e8faSwyllys 	}
516130a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
516230a5e8faSwyllys 	    attrlist, numattr);
516330a5e8faSwyllys 	if (crlfilename == NULL)
516430a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
516530a5e8faSwyllys 
516630a5e8faSwyllys 	crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
516730a5e8faSwyllys 	    attrlist, numattr);
516830a5e8faSwyllys 
516930a5e8faSwyllys 	if (crldata == NULL)
517030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
517130a5e8faSwyllys 
517230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
517330a5e8faSwyllys 
517430a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
517530a5e8faSwyllys 
517630a5e8faSwyllys 	if (crlfile == NULL)
517730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
517830a5e8faSwyllys 
517930a5e8faSwyllys 	if (isdir(crlfile)) {
518030a5e8faSwyllys 		free(crlfile);
518130a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
518230a5e8faSwyllys 	}
518330a5e8faSwyllys 
518430a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
518530a5e8faSwyllys 	if (ret != KMF_OK) {
518630a5e8faSwyllys 		free(crlfile);
518730a5e8faSwyllys 		return (ret);
518830a5e8faSwyllys 	}
518930a5e8faSwyllys 
519030a5e8faSwyllys 	if (bio_err == NULL)
519130a5e8faSwyllys 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
519230a5e8faSwyllys 
519330a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
519430a5e8faSwyllys 	if (in == NULL)	{
519530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
519630a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
519730a5e8faSwyllys 		goto end;
519830a5e8faSwyllys 	}
519930a5e8faSwyllys 
520030a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
520130a5e8faSwyllys 		x = d2i_X509_CRL_bio(in, NULL);
520230a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
520330a5e8faSwyllys 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
520430a5e8faSwyllys 	}
520530a5e8faSwyllys 
520630a5e8faSwyllys 	if (x == NULL) { /* should not happen */
520730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
520830a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
520930a5e8faSwyllys 		goto end;
521030a5e8faSwyllys 	}
521130a5e8faSwyllys 
521230a5e8faSwyllys 	mem = BIO_new(BIO_s_mem());
521330a5e8faSwyllys 	if (mem == NULL) {
521430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
521530a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
521630a5e8faSwyllys 		goto end;
521730a5e8faSwyllys 	}
521830a5e8faSwyllys 
521930a5e8faSwyllys 	(void) X509_CRL_print(mem, x);
522030a5e8faSwyllys 	len = BIO_get_mem_data(mem, &memptr);
522130a5e8faSwyllys 	if (len <= 0) {
522230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
522330a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
522430a5e8faSwyllys 		goto end;
522530a5e8faSwyllys 	}
522630a5e8faSwyllys 
522730a5e8faSwyllys 	data = malloc(len + 1);
522830a5e8faSwyllys 	if (data == NULL) {
522930a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
523030a5e8faSwyllys 		goto end;
523130a5e8faSwyllys 	}
523230a5e8faSwyllys 
523330a5e8faSwyllys 	(void) memcpy(data, memptr, len);
523430a5e8faSwyllys 	data[len] = '\0';
523530a5e8faSwyllys 	*crldata = data;
523630a5e8faSwyllys 
523730a5e8faSwyllys end:
523830a5e8faSwyllys 	if (x != NULL)
523930a5e8faSwyllys 		X509_CRL_free(x);
524030a5e8faSwyllys 
524130a5e8faSwyllys 	if (crlfile != NULL)
524230a5e8faSwyllys 		free(crlfile);
524330a5e8faSwyllys 
524430a5e8faSwyllys 	if (in != NULL)
524530a5e8faSwyllys 		(void) BIO_free(in);
524630a5e8faSwyllys 
524730a5e8faSwyllys 	if (mem != NULL)
524830a5e8faSwyllys 		(void) BIO_free(mem);
524930a5e8faSwyllys 
525030a5e8faSwyllys 	return (ret);
525130a5e8faSwyllys }
525230a5e8faSwyllys 
525330a5e8faSwyllys KMF_RETURN
525430a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
525530a5e8faSwyllys {
525630a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
525730a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
525830a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
525930a5e8faSwyllys 	char *crlfile = NULL;
526030a5e8faSwyllys 	BIO *in = NULL;
526130a5e8faSwyllys 	char *crlfilename, *dirpath;
526230a5e8faSwyllys 
526330a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
526430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
526530a5e8faSwyllys 	}
526630a5e8faSwyllys 
526730a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
526830a5e8faSwyllys 	    attrlist, numattr);
526930a5e8faSwyllys 
527030a5e8faSwyllys 	if (crlfilename == NULL)
527130a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
527230a5e8faSwyllys 
527330a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
527430a5e8faSwyllys 
527530a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
527630a5e8faSwyllys 
527730a5e8faSwyllys 	if (crlfile == NULL)
527830a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
527930a5e8faSwyllys 
528030a5e8faSwyllys 	if (isdir(crlfile)) {
528130a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
528230a5e8faSwyllys 		goto end;
528330a5e8faSwyllys 	}
528430a5e8faSwyllys 
528530a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
528630a5e8faSwyllys 	if (ret != KMF_OK)
528730a5e8faSwyllys 		goto end;
528830a5e8faSwyllys 
528930a5e8faSwyllys 	if (unlink(crlfile) != 0) {
529030a5e8faSwyllys 		SET_SYS_ERROR(kmfh, errno);
529130a5e8faSwyllys 		ret = KMF_ERR_INTERNAL;
529230a5e8faSwyllys 		goto end;
529330a5e8faSwyllys 	}
529430a5e8faSwyllys 
529530a5e8faSwyllys end:
529630a5e8faSwyllys 	if (in != NULL)
529730a5e8faSwyllys 		(void) BIO_free(in);
529830a5e8faSwyllys 	if (crlfile != NULL)
529930a5e8faSwyllys 		free(crlfile);
530030a5e8faSwyllys 
530130a5e8faSwyllys 	return (ret);
530230a5e8faSwyllys }
530330a5e8faSwyllys 
530430a5e8faSwyllys KMF_RETURN
530530a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
530630a5e8faSwyllys {
530730a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
530830a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
530930a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
531030a5e8faSwyllys 	BIO *in = NULL;
531130a5e8faSwyllys 	X509   *xcert = NULL;
531230a5e8faSwyllys 	X509_CRL   *xcrl = NULL;
531330a5e8faSwyllys 	STACK_OF(X509_REVOKED) *revoke_stack = NULL;
531430a5e8faSwyllys 	X509_REVOKED *revoke;
531530a5e8faSwyllys 	int i;
531630a5e8faSwyllys 	char *crlfilename, *crlfile, *dirpath, *certfile;
531730a5e8faSwyllys 
531830a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
531930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
532030a5e8faSwyllys 	}
532130a5e8faSwyllys 
532230a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
532330a5e8faSwyllys 	    attrlist, numattr);
532430a5e8faSwyllys 
532530a5e8faSwyllys 	if (crlfilename == NULL)
532630a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
532730a5e8faSwyllys 
532830a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
532930a5e8faSwyllys 	if (certfile == NULL)
533030a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
533130a5e8faSwyllys 
533230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
533330a5e8faSwyllys 
533430a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
533530a5e8faSwyllys 
533630a5e8faSwyllys 	if (crlfile == NULL)
533730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
533830a5e8faSwyllys 
533930a5e8faSwyllys 	if (isdir(crlfile)) {
534030a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
534130a5e8faSwyllys 		goto end;
534230a5e8faSwyllys 	}
534330a5e8faSwyllys 
534430a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
534530a5e8faSwyllys 	if (ret != KMF_OK)
534630a5e8faSwyllys 		goto end;
534730a5e8faSwyllys 
534830a5e8faSwyllys 	/* Read the CRL file and load it into a X509_CRL structure */
534930a5e8faSwyllys 	in = BIO_new_file(crlfilename, "rb");
535030a5e8faSwyllys 	if (in == NULL)	{
535130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
535230a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
535330a5e8faSwyllys 		goto end;
535430a5e8faSwyllys 	}
535530a5e8faSwyllys 
535630a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
535730a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
535830a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
535930a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
536030a5e8faSwyllys 	}
536130a5e8faSwyllys 
536230a5e8faSwyllys 	if (xcrl == NULL) {
536330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
536430a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
536530a5e8faSwyllys 		goto end;
536630a5e8faSwyllys 	}
536730a5e8faSwyllys 	(void) BIO_free(in);
536830a5e8faSwyllys 
536930a5e8faSwyllys 	/* Read the Certificate file and load it into a X509 structure */
537030a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
537130a5e8faSwyllys 	if (ret != KMF_OK)
537230a5e8faSwyllys 		goto end;
537330a5e8faSwyllys 
537430a5e8faSwyllys 	in = BIO_new_file(certfile, "rb");
537530a5e8faSwyllys 	if (in == NULL)	{
537630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
537730a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
537830a5e8faSwyllys 		goto end;
537930a5e8faSwyllys 	}
538030a5e8faSwyllys 
538130a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
538230a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
538330a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
538430a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
538530a5e8faSwyllys 	}
538630a5e8faSwyllys 
538730a5e8faSwyllys 	if (xcert == NULL) {
538830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
538930a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
539030a5e8faSwyllys 		goto end;
539130a5e8faSwyllys 	}
539230a5e8faSwyllys 
539330a5e8faSwyllys 	/* Check if the certificate and the CRL have same issuer */
539430a5e8faSwyllys 	if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) {
539530a5e8faSwyllys 		ret = KMF_ERR_ISSUER;
539630a5e8faSwyllys 		goto end;
539730a5e8faSwyllys 	}
539830a5e8faSwyllys 
539930a5e8faSwyllys 	/* Check to see if the certificate serial number is revoked */
540030a5e8faSwyllys 	revoke_stack = X509_CRL_get_REVOKED(xcrl);
540130a5e8faSwyllys 	if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
540230a5e8faSwyllys 		/* No revoked certificates in the CRL file */
540330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
540430a5e8faSwyllys 		ret = KMF_ERR_EMPTY_CRL;
540530a5e8faSwyllys 		goto end;
540630a5e8faSwyllys 	}
540730a5e8faSwyllys 
540830a5e8faSwyllys 	for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
5409a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
541030a5e8faSwyllys 		revoke = sk_X509_REVOKED_value(revoke_stack, i);
541130a5e8faSwyllys 		if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber,
541230a5e8faSwyllys 		    revoke->serialNumber) == 0) {
541330a5e8faSwyllys 			break;
541430a5e8faSwyllys 		}
541530a5e8faSwyllys 	}
541630a5e8faSwyllys 
541730a5e8faSwyllys 	if (i < sk_X509_REVOKED_num(revoke_stack)) {
541830a5e8faSwyllys 		ret = KMF_OK;
541930a5e8faSwyllys 	} else {
542030a5e8faSwyllys 		ret = KMF_ERR_NOT_REVOKED;
542130a5e8faSwyllys 	}
542230a5e8faSwyllys 
542330a5e8faSwyllys end:
542430a5e8faSwyllys 	if (in != NULL)
542530a5e8faSwyllys 		(void) BIO_free(in);
542630a5e8faSwyllys 	if (xcrl != NULL)
542730a5e8faSwyllys 		X509_CRL_free(xcrl);
542830a5e8faSwyllys 	if (xcert != NULL)
542930a5e8faSwyllys 		X509_free(xcert);
543030a5e8faSwyllys 
543130a5e8faSwyllys 	return (ret);
543230a5e8faSwyllys }
543330a5e8faSwyllys 
543430a5e8faSwyllys KMF_RETURN
543530a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
543630a5e8faSwyllys {
543730a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
543830a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
543930a5e8faSwyllys 	BIO		*bcrl = NULL;
544030a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
544130a5e8faSwyllys 	X509		*xcert = NULL;
544230a5e8faSwyllys 	EVP_PKEY	*pkey;
544330a5e8faSwyllys 	int		sslret;
544430a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
544530a5e8faSwyllys 	unsigned char	*p;
544630a5e8faSwyllys 	long		len;
544730a5e8faSwyllys 
544830a5e8faSwyllys 	if (handle == NULL || crlname == NULL || tacert == NULL) {
544930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
545030a5e8faSwyllys 	}
545130a5e8faSwyllys 
545230a5e8faSwyllys 	ret = kmf_get_file_format(crlname, &crl_format);
545330a5e8faSwyllys 	if (ret != KMF_OK)
545430a5e8faSwyllys 		return (ret);
545530a5e8faSwyllys 
545630a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
545730a5e8faSwyllys 	if (bcrl == NULL)	{
545830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
545930a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
546030a5e8faSwyllys 		goto cleanup;
546130a5e8faSwyllys 	}
546230a5e8faSwyllys 
546330a5e8faSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
546430a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
546530a5e8faSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
546630a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
546730a5e8faSwyllys 	} else {
546830a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
546930a5e8faSwyllys 		goto cleanup;
547030a5e8faSwyllys 	}
547130a5e8faSwyllys 
547230a5e8faSwyllys 	if (xcrl == NULL) {
547330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
547430a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
547530a5e8faSwyllys 		goto cleanup;
547630a5e8faSwyllys 	}
547730a5e8faSwyllys 
547830a5e8faSwyllys 	p = tacert->Data;
547930a5e8faSwyllys 	len = tacert->Length;
548030a5e8faSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
548130a5e8faSwyllys 
548230a5e8faSwyllys 	if (xcert == NULL) {
548330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
548430a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
548530a5e8faSwyllys 		goto cleanup;
548630a5e8faSwyllys 	}
548730a5e8faSwyllys 
548830a5e8faSwyllys 	/* Get issuer certificate public key */
548930a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
549030a5e8faSwyllys 	if (pkey == NULL) {
549130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
549230a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
549330a5e8faSwyllys 		goto cleanup;
549430a5e8faSwyllys 	}
549530a5e8faSwyllys 
549630a5e8faSwyllys 	/* Verify CRL signature */
549730a5e8faSwyllys 	sslret = X509_CRL_verify(xcrl, pkey);
549830a5e8faSwyllys 	EVP_PKEY_free(pkey);
549930a5e8faSwyllys 	if (sslret > 0) {
550030a5e8faSwyllys 		ret = KMF_OK;
550130a5e8faSwyllys 	} else {
550230a5e8faSwyllys 		SET_ERROR(kmfh, sslret);
550330a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
550430a5e8faSwyllys 	}
550530a5e8faSwyllys 
550630a5e8faSwyllys cleanup:
550730a5e8faSwyllys 	if (bcrl != NULL)
550830a5e8faSwyllys 		(void) BIO_free(bcrl);
550930a5e8faSwyllys 
551030a5e8faSwyllys 	if (xcrl != NULL)
551130a5e8faSwyllys 		X509_CRL_free(xcrl);
551230a5e8faSwyllys 
551330a5e8faSwyllys 	if (xcert != NULL)
551430a5e8faSwyllys 		X509_free(xcert);
551530a5e8faSwyllys 
551630a5e8faSwyllys 	return (ret);
551730a5e8faSwyllys 
551830a5e8faSwyllys }
551930a5e8faSwyllys 
552030a5e8faSwyllys KMF_RETURN
552130a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
552230a5e8faSwyllys {
552330a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
552430a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
552530a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
552630a5e8faSwyllys 	BIO		*bcrl = NULL;
552730a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
552830a5e8faSwyllys 	int		i;
552930a5e8faSwyllys 
553030a5e8faSwyllys 	if (handle == NULL || crlname == NULL) {
553130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
553230a5e8faSwyllys 	}
553330a5e8faSwyllys 
553430a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlname, &crl_format);
553530a5e8faSwyllys 	if (ret != KMF_OK)
553630a5e8faSwyllys 		return (ret);
553730a5e8faSwyllys 
553830a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
553930a5e8faSwyllys 	if (bcrl == NULL) {
554030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
554130a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
554230a5e8faSwyllys 		goto cleanup;
554330a5e8faSwyllys 	}
554430a5e8faSwyllys 
55455b3e1433Swyllys 	if (crl_format == KMF_FORMAT_ASN1)
554630a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
55475b3e1433Swyllys 	else if (crl_format == KMF_FORMAT_PEM)
554830a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
554930a5e8faSwyllys 
555030a5e8faSwyllys 	if (xcrl == NULL) {
555130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
555230a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
555330a5e8faSwyllys 		goto cleanup;
555430a5e8faSwyllys 	}
555530a5e8faSwyllys 	i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL);
555630a5e8faSwyllys 	if (i >= 0) {
555730a5e8faSwyllys 		ret = KMF_ERR_VALIDITY_PERIOD;
555830a5e8faSwyllys 		goto cleanup;
555930a5e8faSwyllys 	}
556030a5e8faSwyllys 	if (X509_CRL_get_nextUpdate(xcrl)) {
556130a5e8faSwyllys 		i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL);
556230a5e8faSwyllys 
556330a5e8faSwyllys 		if (i <= 0) {
556430a5e8faSwyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
556530a5e8faSwyllys 			goto cleanup;
556630a5e8faSwyllys 		}
556730a5e8faSwyllys 	}
556830a5e8faSwyllys 
556930a5e8faSwyllys 	ret = KMF_OK;
557030a5e8faSwyllys 
557130a5e8faSwyllys cleanup:
557230a5e8faSwyllys 	if (bcrl != NULL)
557330a5e8faSwyllys 		(void) BIO_free(bcrl);
557430a5e8faSwyllys 
557530a5e8faSwyllys 	if (xcrl != NULL)
557630a5e8faSwyllys 		X509_CRL_free(xcrl);
557730a5e8faSwyllys 
557830a5e8faSwyllys 	return (ret);
557930a5e8faSwyllys }
5580