199ebb4caSwyllys /*
22c9a247fSWyllys Ingersoll  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
32c9a247fSWyllys Ingersoll  *
499ebb4caSwyllys  * Use is subject to license terms.
599ebb4caSwyllys  */
69a767088Shaimay /*
7*70f9559bSTheo Schlossnagle  * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
8*70f9559bSTheo Schlossnagle  */
9*70f9559bSTheo Schlossnagle /*
109a767088Shaimay  * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
119a767088Shaimay  * project 2000.
129a767088Shaimay  */
139a767088Shaimay /*
149a767088Shaimay  * ====================================================================
159a767088Shaimay  * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
169a767088Shaimay  *
179a767088Shaimay  * Redistribution and use in source and binary forms, with or without
189a767088Shaimay  * modification, are permitted provided that the following conditions
199a767088Shaimay  * are met:
209a767088Shaimay  *
219a767088Shaimay  * 1. Redistributions of source code must retain the above copyright
229a767088Shaimay  *    notice, this list of conditions and the following disclaimer.
239a767088Shaimay  *
249a767088Shaimay  * 2. Redistributions in binary form must reproduce the above copyright
259a767088Shaimay  *    notice, this list of conditions and the following disclaimer in
269a767088Shaimay  *    the documentation and/or other materials provided with the
279a767088Shaimay  *    distribution.
289a767088Shaimay  *
299a767088Shaimay  * 3. All advertising materials mentioning features or use of this
309a767088Shaimay  *    software must display the following acknowledgment:
319a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
329a767088Shaimay  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
339a767088Shaimay  *
349a767088Shaimay  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
359a767088Shaimay  *    endorse or promote products derived from this software without
369a767088Shaimay  *    prior written permission. For written permission, please contact
379a767088Shaimay  *    licensing@OpenSSL.org.
389a767088Shaimay  *
399a767088Shaimay  * 5. Products derived from this software may not be called "OpenSSL"
409a767088Shaimay  *    nor may "OpenSSL" appear in their names without prior written
419a767088Shaimay  *    permission of the OpenSSL Project.
429a767088Shaimay  *
439a767088Shaimay  * 6. Redistributions of any form whatsoever must retain the following
449a767088Shaimay  *    acknowledgment:
459a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
469a767088Shaimay  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
479a767088Shaimay  *
489a767088Shaimay  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
499a767088Shaimay  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
509a767088Shaimay  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
519a767088Shaimay  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
529a767088Shaimay  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
539a767088Shaimay  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
549a767088Shaimay  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
559a767088Shaimay  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
569a767088Shaimay  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
579a767088Shaimay  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
589a767088Shaimay  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
599a767088Shaimay  * OF THE POSSIBILITY OF SUCH DAMAGE.
609a767088Shaimay  * ====================================================================
619a767088Shaimay  *
629a767088Shaimay  * This product includes cryptographic software written by Eric Young
639a767088Shaimay  * (eay@cryptsoft.com).  This product includes software written by Tim
649a767088Shaimay  * Hudson (tjh@cryptsoft.com).
659a767088Shaimay  *
669a767088Shaimay  */
6799ebb4caSwyllys 
6871593db2Swyllys #include <stdlib.h>
6999ebb4caSwyllys #include <kmfapiP.h>
7099ebb4caSwyllys #include <ber_der.h>
7199ebb4caSwyllys #include <fcntl.h>
7299ebb4caSwyllys #include <sys/stat.h>
7399ebb4caSwyllys #include <dirent.h>
7499ebb4caSwyllys #include <cryptoutil.h>
7599ebb4caSwyllys #include <synch.h>
7699ebb4caSwyllys #include <thread.h>
7799ebb4caSwyllys 
7899ebb4caSwyllys /* OPENSSL related headers */
7999ebb4caSwyllys #include <openssl/bio.h>
8099ebb4caSwyllys #include <openssl/bn.h>
8199ebb4caSwyllys #include <openssl/asn1.h>
8299ebb4caSwyllys #include <openssl/err.h>
8399ebb4caSwyllys #include <openssl/bn.h>
8499ebb4caSwyllys #include <openssl/x509.h>
8599ebb4caSwyllys #include <openssl/rsa.h>
8699ebb4caSwyllys #include <openssl/dsa.h>
8799ebb4caSwyllys #include <openssl/x509v3.h>
8899ebb4caSwyllys #include <openssl/objects.h>
8999ebb4caSwyllys #include <openssl/pem.h>
9099ebb4caSwyllys #include <openssl/pkcs12.h>
9199ebb4caSwyllys #include <openssl/ocsp.h>
9299ebb4caSwyllys #include <openssl/des.h>
9399ebb4caSwyllys #include <openssl/rand.h>
9499ebb4caSwyllys 
9599ebb4caSwyllys #define	PRINT_ANY_EXTENSION (\
9699ebb4caSwyllys 	KMF_X509_EXT_KEY_USAGE |\
9799ebb4caSwyllys 	KMF_X509_EXT_CERT_POLICIES |\
9899ebb4caSwyllys 	KMF_X509_EXT_SUBJALTNAME |\
9999ebb4caSwyllys 	KMF_X509_EXT_BASIC_CONSTRAINTS |\
10099ebb4caSwyllys 	KMF_X509_EXT_NAME_CONSTRAINTS |\
10199ebb4caSwyllys 	KMF_X509_EXT_POLICY_CONSTRAINTS |\
10299ebb4caSwyllys 	KMF_X509_EXT_EXT_KEY_USAGE |\
10399ebb4caSwyllys 	KMF_X509_EXT_INHIBIT_ANY_POLICY |\
10499ebb4caSwyllys 	KMF_X509_EXT_AUTH_KEY_ID |\
10599ebb4caSwyllys 	KMF_X509_EXT_SUBJ_KEY_ID |\
10699ebb4caSwyllys 	KMF_X509_EXT_POLICY_MAPPING)
10799ebb4caSwyllys 
10899ebb4caSwyllys static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
10999ebb4caSwyllys 	0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
11099ebb4caSwyllys 	0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
11199ebb4caSwyllys 	0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
11299ebb4caSwyllys 	0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
11399ebb4caSwyllys 	0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
11499ebb4caSwyllys 	0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
11599ebb4caSwyllys 	0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
11699ebb4caSwyllys 	0x91 };
11799ebb4caSwyllys 
11899ebb4caSwyllys static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
11999ebb4caSwyllys 	0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
12099ebb4caSwyllys 	0x8e, 0xda, 0xce, 0x91, 0x5f };
12199ebb4caSwyllys 
12299ebb4caSwyllys static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
12399ebb4caSwyllys 	0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
12499ebb4caSwyllys 	0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
12599ebb4caSwyllys 	0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
12699ebb4caSwyllys 	0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
12799ebb4caSwyllys 	0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
12899ebb4caSwyllys 	0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
12999ebb4caSwyllys 	0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
13099ebb4caSwyllys 	0x02 };
13199ebb4caSwyllys 
13299ebb4caSwyllys #define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
13399ebb4caSwyllys 	h->lasterr.errcode = c;
13499ebb4caSwyllys 
13599ebb4caSwyllys #define	SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
13699ebb4caSwyllys 
1375b3e1433Swyllys /*
1385b3e1433Swyllys  * Declare some new macros for managing stacks of EVP_PKEYS, similar to
1395b3e1433Swyllys  * what wanboot did.
1405b3e1433Swyllys  */
1415b3e1433Swyllys DECLARE_STACK_OF(EVP_PKEY)
1425b3e1433Swyllys 
1435b3e1433Swyllys #define	sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
1445b3e1433Swyllys #define	sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
1455b3e1433Swyllys #define	sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
1465b3e1433Swyllys #define	sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
1475b3e1433Swyllys #define	sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
1485b3e1433Swyllys #define	sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
1495b3e1433Swyllys 	(free_func))
1505b3e1433Swyllys 
15199ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX;
15299ebb4caSwyllys static int ssl_initialized = 0;
15330a5e8faSwyllys static BIO *bio_err = NULL;
15430a5e8faSwyllys 
15530a5e8faSwyllys static int
15630a5e8faSwyllys test_for_file(char *, mode_t);
1575b3e1433Swyllys static KMF_RETURN
1585b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *, char *, int,
1595b3e1433Swyllys     STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
1605b3e1433Swyllys 
1615b3e1433Swyllys static KMF_RETURN
1625b3e1433Swyllys local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *,
1635b3e1433Swyllys     int, KMF_KEY_HANDLE *, char *);
1645b3e1433Swyllys 
1655b3e1433Swyllys static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int);
16699ebb4caSwyllys 
16771593db2Swyllys static KMF_RETURN
16830a5e8faSwyllys extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *,
16902744e81Swyllys     CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
17071593db2Swyllys 
17171593db2Swyllys static KMF_RETURN
17230a5e8faSwyllys kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
17330a5e8faSwyllys     char *, KMF_DATA *);
17430a5e8faSwyllys 
17530a5e8faSwyllys static KMF_RETURN
17630a5e8faSwyllys load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
17730a5e8faSwyllys     char *, KMF_DATA **, uint32_t *);
17871593db2Swyllys 
17902744e81Swyllys static KMF_RETURN
18002744e81Swyllys sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
18102744e81Swyllys 
18202744e81Swyllys static EVP_PKEY *
18302744e81Swyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *);
18402744e81Swyllys 
18530a5e8faSwyllys static KMF_RETURN
18630a5e8faSwyllys convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
18730a5e8faSwyllys 
18899ebb4caSwyllys KMF_RETURN
18930a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
19099ebb4caSwyllys 
19199ebb4caSwyllys void
19299ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
19399ebb4caSwyllys 
19499ebb4caSwyllys KMF_RETURN
19530a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
19699ebb4caSwyllys 
19799ebb4caSwyllys KMF_RETURN
19830a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
19999ebb4caSwyllys 
20099ebb4caSwyllys KMF_RETURN
20130a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20230a5e8faSwyllys 
20330a5e8faSwyllys KMF_RETURN
20430a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20599ebb4caSwyllys 
20699ebb4caSwyllys KMF_RETURN
20799ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T,  KMF_KEY_HANDLE *, KMF_DATA *);
20899ebb4caSwyllys 
20999ebb4caSwyllys KMF_RETURN
21099ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
21199ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
21299ebb4caSwyllys 
21399ebb4caSwyllys KMF_RETURN
21430a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21599ebb4caSwyllys 
21699ebb4caSwyllys KMF_RETURN
21730a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21899ebb4caSwyllys 
21999ebb4caSwyllys KMF_RETURN
22030a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22199ebb4caSwyllys 
22299ebb4caSwyllys KMF_RETURN
22330a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22499ebb4caSwyllys 
22599ebb4caSwyllys KMF_RETURN
22630a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22799ebb4caSwyllys 
22899ebb4caSwyllys KMF_RETURN
22999ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
23099ebb4caSwyllys 	KMF_PRINTABLE_ITEM, char *);
23199ebb4caSwyllys 
23299ebb4caSwyllys KMF_RETURN
23399ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
23499ebb4caSwyllys 
23599ebb4caSwyllys KMF_RETURN
23630a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23799ebb4caSwyllys 
23899ebb4caSwyllys KMF_RETURN
23999ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
24099ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
24199ebb4caSwyllys 
24299ebb4caSwyllys KMF_RETURN
24330a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24499ebb4caSwyllys 
24599ebb4caSwyllys KMF_RETURN
24630a5e8faSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24799ebb4caSwyllys 
24899ebb4caSwyllys KMF_RETURN
24930a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25099ebb4caSwyllys 
25199ebb4caSwyllys KMF_RETURN
25230a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25399ebb4caSwyllys 
25499ebb4caSwyllys KMF_RETURN
25530a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25699ebb4caSwyllys 
25799ebb4caSwyllys KMF_RETURN
25899ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
25999ebb4caSwyllys 
26099ebb4caSwyllys KMF_RETURN
26130a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
26299ebb4caSwyllys 
26399ebb4caSwyllys KMF_RETURN
26430a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
26599ebb4caSwyllys 
26699ebb4caSwyllys static
26799ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table =
26899ebb4caSwyllys {
26999ebb4caSwyllys 	1,				/* Version */
27099ebb4caSwyllys 	NULL, /* ConfigureKeystore */
27199ebb4caSwyllys 	OpenSSL_FindCert,
27299ebb4caSwyllys 	OpenSSL_FreeKMFCert,
27399ebb4caSwyllys 	OpenSSL_StoreCert,
27499ebb4caSwyllys 	NULL, /* ImportCert */
27599ebb4caSwyllys 	OpenSSL_ImportCRL,
27699ebb4caSwyllys 	OpenSSL_DeleteCert,
27799ebb4caSwyllys 	OpenSSL_DeleteCRL,
27899ebb4caSwyllys 	OpenSSL_CreateKeypair,
27999ebb4caSwyllys 	OpenSSL_FindKey,
28099ebb4caSwyllys 	OpenSSL_EncodePubKeyData,
28199ebb4caSwyllys 	OpenSSL_SignData,
28299ebb4caSwyllys 	OpenSSL_DeleteKey,
28399ebb4caSwyllys 	OpenSSL_ListCRL,
28499ebb4caSwyllys 	NULL,	/* FindCRL */
28599ebb4caSwyllys 	OpenSSL_FindCertInCRL,
28699ebb4caSwyllys 	OpenSSL_GetErrorString,
28730a5e8faSwyllys 	OpenSSL_FindPrikeyByCert,
28899ebb4caSwyllys 	OpenSSL_DecryptData,
28930a5e8faSwyllys 	OpenSSL_ExportPK12,
29099ebb4caSwyllys 	OpenSSL_CreateSymKey,
29199ebb4caSwyllys 	OpenSSL_GetSymKeyValue,
29299ebb4caSwyllys 	NULL,	/* SetTokenPin */
29330a5e8faSwyllys 	OpenSSL_StoreKey,
29499ebb4caSwyllys 	NULL	/* Finalize */
29599ebb4caSwyllys };
29699ebb4caSwyllys 
29799ebb4caSwyllys static mutex_t *lock_cs;
29899ebb4caSwyllys static long *lock_count;
29999ebb4caSwyllys 
30099ebb4caSwyllys static void
301a2d4930dSDan OpenSolaris Anderson /* ARGSUSED1 */
30299ebb4caSwyllys locking_cb(int mode, int type, char *file, int line)
30399ebb4caSwyllys {
30499ebb4caSwyllys 	if (mode & CRYPTO_LOCK) {
30599ebb4caSwyllys 		(void) mutex_lock(&(lock_cs[type]));
30699ebb4caSwyllys 		lock_count[type]++;
30799ebb4caSwyllys 	} else {
30899ebb4caSwyllys 		(void) mutex_unlock(&(lock_cs[type]));
30999ebb4caSwyllys 	}
31099ebb4caSwyllys }
31199ebb4caSwyllys 
31299ebb4caSwyllys static unsigned long
31399ebb4caSwyllys thread_id()
31499ebb4caSwyllys {
31599ebb4caSwyllys 	return ((unsigned long)thr_self());
31699ebb4caSwyllys }
31799ebb4caSwyllys 
31899ebb4caSwyllys KMF_PLUGIN_FUNCLIST *
31999ebb4caSwyllys KMF_Plugin_Initialize()
32099ebb4caSwyllys {
32199ebb4caSwyllys 	int i;
32299ebb4caSwyllys 
32399ebb4caSwyllys 	(void) mutex_lock(&init_lock);
32499ebb4caSwyllys 	if (!ssl_initialized) {
32599ebb4caSwyllys 		/*
32699ebb4caSwyllys 		 * Add support for extension OIDs that are not yet in the
32799ebb4caSwyllys 		 * openssl default set.
32899ebb4caSwyllys 		 */
32999ebb4caSwyllys 		(void) OBJ_create("2.5.29.30", "nameConstraints",
33099ebb4caSwyllys 		    "X509v3 Name Constraints");
33199ebb4caSwyllys 		(void) OBJ_create("2.5.29.33", "policyMappings",
33299ebb4caSwyllys 		    "X509v3 Policy Mappings");
33399ebb4caSwyllys 		(void) OBJ_create("2.5.29.36", "policyConstraints",
33499ebb4caSwyllys 		    "X509v3 Policy Constraints");
33599ebb4caSwyllys 		(void) OBJ_create("2.5.29.46", "freshestCRL",
33699ebb4caSwyllys 		    "X509v3 Freshest CRL");
33799ebb4caSwyllys 		(void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
33899ebb4caSwyllys 		    "X509v3 Inhibit Any-Policy");
33999ebb4caSwyllys 		/*
34099ebb4caSwyllys 		 * Set up for thread-safe operation.
34199ebb4caSwyllys 		 */
34299ebb4caSwyllys 		lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
34399ebb4caSwyllys 		if (lock_cs == NULL) {
34499ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
34599ebb4caSwyllys 			return (NULL);
34699ebb4caSwyllys 		}
34799ebb4caSwyllys 
34899ebb4caSwyllys 		lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
34999ebb4caSwyllys 		if (lock_count == NULL) {
35099ebb4caSwyllys 			OPENSSL_free(lock_cs);
35199ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
35299ebb4caSwyllys 			return (NULL);
35399ebb4caSwyllys 		}
35499ebb4caSwyllys 
35599ebb4caSwyllys 		for (i = 0; i < CRYPTO_num_locks(); i++) {
35699ebb4caSwyllys 			lock_count[i] = 0;
35799ebb4caSwyllys 			(void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
35899ebb4caSwyllys 		}
35999ebb4caSwyllys 
36099ebb4caSwyllys 		CRYPTO_set_id_callback((unsigned long (*)())thread_id);
3612c9a247fSWyllys Ingersoll 		if (CRYPTO_get_locking_callback() == NULL)
36299ebb4caSwyllys 			CRYPTO_set_locking_callback((void (*)())locking_cb);
3632c9a247fSWyllys Ingersoll 
3642c9a247fSWyllys Ingersoll 		OpenSSL_add_all_algorithms();
3652c9a247fSWyllys Ingersoll 
3662c9a247fSWyllys Ingersoll 		/* Enable error strings for reporting */
3672c9a247fSWyllys Ingersoll 		ERR_load_crypto_strings();
3682c9a247fSWyllys Ingersoll 
36999ebb4caSwyllys 		ssl_initialized = 1;
37099ebb4caSwyllys 	}
37199ebb4caSwyllys 	(void) mutex_unlock(&init_lock);
37299ebb4caSwyllys 
37399ebb4caSwyllys 	return (&openssl_plugin_table);
37499ebb4caSwyllys }
37599ebb4caSwyllys /*
37699ebb4caSwyllys  * Convert an SSL DN to a KMF DN.
37799ebb4caSwyllys  */
37899ebb4caSwyllys static KMF_RETURN
37999ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
38099ebb4caSwyllys {
38199ebb4caSwyllys 	KMF_DATA derdata;
38299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
38399ebb4caSwyllys 	uchar_t *tmp;
38499ebb4caSwyllys 
38599ebb4caSwyllys 	/* Convert to raw DER format */
38699ebb4caSwyllys 	derdata.Length = i2d_X509_NAME(sslDN, NULL);
38799ebb4caSwyllys 	if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
38899ebb4caSwyllys 	    == NULL) {
38999ebb4caSwyllys 		return (KMF_ERR_MEMORY);
39099ebb4caSwyllys 	}
39199ebb4caSwyllys 	(void) i2d_X509_NAME(sslDN, &tmp);
39299ebb4caSwyllys 
39399ebb4caSwyllys 	/* Decode to KMF format */
39499ebb4caSwyllys 	rv = DerDecodeName(&derdata, kmfDN);
39599ebb4caSwyllys 	if (rv != KMF_OK) {
39699ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
39799ebb4caSwyllys 	}
39899ebb4caSwyllys 	OPENSSL_free(derdata.Data);
39999ebb4caSwyllys 
40099ebb4caSwyllys 	return (rv);
40199ebb4caSwyllys }
40299ebb4caSwyllys 
40330a5e8faSwyllys int
40499ebb4caSwyllys isdir(char *path)
40599ebb4caSwyllys {
40699ebb4caSwyllys 	struct stat s;
40799ebb4caSwyllys 
40899ebb4caSwyllys 	if (stat(path, &s) == -1)
40999ebb4caSwyllys 		return (0);
41099ebb4caSwyllys 
41130a5e8faSwyllys 	return ((s.st_mode & S_IFMT) == S_IFDIR);
41299ebb4caSwyllys }
41399ebb4caSwyllys 
41499ebb4caSwyllys static KMF_RETURN
41599ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
41699ebb4caSwyllys {
41799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
41899ebb4caSwyllys 	unsigned char *buf = NULL, *p;
41999ebb4caSwyllys 	int len;
42099ebb4caSwyllys 
42199ebb4caSwyllys 	/*
42299ebb4caSwyllys 	 * Convert the X509 internal struct to DER encoded data
42399ebb4caSwyllys 	 */
42499ebb4caSwyllys 	if ((len = i2d_X509(x509cert, NULL)) < 0) {
42599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
42699ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
42799ebb4caSwyllys 		goto cleanup;
42899ebb4caSwyllys 	}
42999ebb4caSwyllys 	if ((buf = malloc(len)) == NULL) {
43099ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
43199ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
43299ebb4caSwyllys 		goto cleanup;
43399ebb4caSwyllys 	}
43499ebb4caSwyllys 
43599ebb4caSwyllys 	/*
43699ebb4caSwyllys 	 * i2d_X509 will increment the buf pointer so that we need to
43799ebb4caSwyllys 	 * save it.
43899ebb4caSwyllys 	 */
43999ebb4caSwyllys 	p = buf;
44099ebb4caSwyllys 	if ((len = i2d_X509(x509cert, &p)) < 0) {
44199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
44299ebb4caSwyllys 		free(buf);
44399ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
44499ebb4caSwyllys 		goto cleanup;
44599ebb4caSwyllys 	}
44699ebb4caSwyllys 
44799ebb4caSwyllys 	/* caller's responsibility to free it */
44899ebb4caSwyllys 	cert->Data = buf;
44999ebb4caSwyllys 	cert->Length = len;
45099ebb4caSwyllys 
45199ebb4caSwyllys cleanup:
45299ebb4caSwyllys 	if (rv != KMF_OK) {
45399ebb4caSwyllys 		if (buf)
45499ebb4caSwyllys 			free(buf);
45599ebb4caSwyllys 		cert->Data = NULL;
45699ebb4caSwyllys 		cert->Length = 0;
45799ebb4caSwyllys 	}
45899ebb4caSwyllys 
45999ebb4caSwyllys 	return (rv);
46099ebb4caSwyllys }
46199ebb4caSwyllys 
46230a5e8faSwyllys 
46399ebb4caSwyllys static KMF_RETURN
46430a5e8faSwyllys check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
46530a5e8faSwyllys     boolean_t *match)
46699ebb4caSwyllys {
46799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
46899ebb4caSwyllys 	boolean_t findIssuer = FALSE;
46999ebb4caSwyllys 	boolean_t findSubject = FALSE;
47099ebb4caSwyllys 	boolean_t findSerial = FALSE;
47199ebb4caSwyllys 	KMF_X509_NAME issuerDN, subjectDN;
47299ebb4caSwyllys 	KMF_X509_NAME certIssuerDN, certSubjectDN;
47399ebb4caSwyllys 
47499ebb4caSwyllys 	*match = FALSE;
47599ebb4caSwyllys 	if (xcert == NULL) {
47699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
47799ebb4caSwyllys 	}
47899ebb4caSwyllys 
47999ebb4caSwyllys 	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
48099ebb4caSwyllys 	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
48199ebb4caSwyllys 	(void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
48299ebb4caSwyllys 	(void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
48399ebb4caSwyllys 
48430a5e8faSwyllys 	if (issuer != NULL && strlen(issuer)) {
48530a5e8faSwyllys 		rv = kmf_dn_parser(issuer, &issuerDN);
48699ebb4caSwyllys 		if (rv != KMF_OK)
48799ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
48899ebb4caSwyllys 
48999ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->issuer, &certIssuerDN);
49099ebb4caSwyllys 		if (rv != KMF_OK) {
49130a5e8faSwyllys 			kmf_free_dn(&issuerDN);
49299ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
49399ebb4caSwyllys 		}
49499ebb4caSwyllys 
49599ebb4caSwyllys 		findIssuer = TRUE;
49699ebb4caSwyllys 	}
49730a5e8faSwyllys 	if (subject != NULL && strlen(subject)) {
49830a5e8faSwyllys 		rv = kmf_dn_parser(subject, &subjectDN);
49999ebb4caSwyllys 		if (rv != KMF_OK) {
50099ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
50199ebb4caSwyllys 			goto cleanup;
50299ebb4caSwyllys 		}
50399ebb4caSwyllys 
50499ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->subject, &certSubjectDN);
50599ebb4caSwyllys 		if (rv != KMF_OK) {
50699ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
50799ebb4caSwyllys 			goto cleanup;
50899ebb4caSwyllys 		}
50999ebb4caSwyllys 		findSubject = TRUE;
51099ebb4caSwyllys 	}
51130a5e8faSwyllys 	if (serial != NULL && serial->val != NULL)
51299ebb4caSwyllys 		findSerial = TRUE;
51399ebb4caSwyllys 
51499ebb4caSwyllys 	if (findSerial) {
51599ebb4caSwyllys 		BIGNUM *bn;
51699ebb4caSwyllys 
51799ebb4caSwyllys 		/* Comparing BIGNUMs is a pain! */
51899ebb4caSwyllys 		bn = ASN1_INTEGER_to_BN(xcert->cert_info->serialNumber, NULL);
51999ebb4caSwyllys 		if (bn != NULL) {
52099ebb4caSwyllys 			int bnlen = BN_num_bytes(bn);
52199ebb4caSwyllys 
52230a5e8faSwyllys 			if (bnlen == serial->len) {
52399ebb4caSwyllys 				uchar_t *a = malloc(bnlen);
52499ebb4caSwyllys 				if (a == NULL) {
52599ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
52699ebb4caSwyllys 					BN_free(bn);
52799ebb4caSwyllys 					goto cleanup;
52899ebb4caSwyllys 				}
52999ebb4caSwyllys 				bnlen = BN_bn2bin(bn, a);
53030a5e8faSwyllys 				*match = (memcmp(a, serial->val, serial->len) ==
53130a5e8faSwyllys 				    0);
53299ebb4caSwyllys 				rv = KMF_OK;
53399ebb4caSwyllys 				free(a);
53499ebb4caSwyllys 			}
53599ebb4caSwyllys 			BN_free(bn);
53699ebb4caSwyllys 			if (!(*match))
53799ebb4caSwyllys 				goto cleanup;
53899ebb4caSwyllys 		} else {
53999ebb4caSwyllys 			rv = KMF_OK;
54099ebb4caSwyllys 			goto cleanup;
54199ebb4caSwyllys 		}
54299ebb4caSwyllys 	}
54399ebb4caSwyllys 	if (findIssuer) {
54430a5e8faSwyllys 		*match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
54530a5e8faSwyllys 		if ((*match) == B_FALSE) {
54630a5e8faSwyllys 			/* stop checking and bail */
54799ebb4caSwyllys 			rv = KMF_OK;
54899ebb4caSwyllys 			goto cleanup;
54999ebb4caSwyllys 		}
55099ebb4caSwyllys 	}
55199ebb4caSwyllys 	if (findSubject) {
55230a5e8faSwyllys 		*match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
55330a5e8faSwyllys 		if ((*match) == B_FALSE) {
55430a5e8faSwyllys 			/* stop checking and bail */
55599ebb4caSwyllys 			rv = KMF_OK;
55699ebb4caSwyllys 			goto cleanup;
55799ebb4caSwyllys 		}
55899ebb4caSwyllys 	}
55999ebb4caSwyllys 
56099ebb4caSwyllys 	*match = TRUE;
56199ebb4caSwyllys cleanup:
56299ebb4caSwyllys 	if (findIssuer) {
56330a5e8faSwyllys 		kmf_free_dn(&issuerDN);
56430a5e8faSwyllys 		kmf_free_dn(&certIssuerDN);
56599ebb4caSwyllys 	}
56699ebb4caSwyllys 	if (findSubject) {
56730a5e8faSwyllys 		kmf_free_dn(&subjectDN);
56830a5e8faSwyllys 		kmf_free_dn(&certSubjectDN);
56999ebb4caSwyllys 	}
57099ebb4caSwyllys 
57199ebb4caSwyllys 	return (rv);
57299ebb4caSwyllys }
57399ebb4caSwyllys 
57430a5e8faSwyllys 
57530a5e8faSwyllys /*
57630a5e8faSwyllys  * This function loads a certificate file into an X509 data structure, and
57730a5e8faSwyllys  * checks if its issuer, subject or the serial number matches with those
57830a5e8faSwyllys  * values.  If it matches, then return the X509 data structure.
57930a5e8faSwyllys  */
58099ebb4caSwyllys static KMF_RETURN
58199ebb4caSwyllys load_X509cert(KMF_HANDLE *kmfh,
58230a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
58330a5e8faSwyllys     char *pathname, X509 **outcert)
58499ebb4caSwyllys {
58599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
58699ebb4caSwyllys 	X509 *xcert = NULL;
58799ebb4caSwyllys 	BIO *bcert = NULL;
58899ebb4caSwyllys 	boolean_t  match = FALSE;
58999ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
59099ebb4caSwyllys 
59199ebb4caSwyllys 	/*
59299ebb4caSwyllys 	 * auto-detect the file format, regardless of what
59399ebb4caSwyllys 	 * the 'format' parameters in the params say.
59499ebb4caSwyllys 	 */
59530a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
59699ebb4caSwyllys 	if (rv != KMF_OK) {
59799ebb4caSwyllys 		if (rv == KMF_ERR_OPEN_FILE)
59899ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
59999ebb4caSwyllys 		return (rv);
60099ebb4caSwyllys 	}
60199ebb4caSwyllys 
60299ebb4caSwyllys 	/* Not ASN1(DER) format */
60399ebb4caSwyllys 	if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
60499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
60599ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
60699ebb4caSwyllys 		goto cleanup;
60799ebb4caSwyllys 	}
60899ebb4caSwyllys 
60999ebb4caSwyllys 	if (format == KMF_FORMAT_PEM)
61099ebb4caSwyllys 		xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
61199ebb4caSwyllys 	else if (format == KMF_FORMAT_ASN1)
61299ebb4caSwyllys 		xcert = d2i_X509_bio(bcert, NULL);
61399ebb4caSwyllys 	else if (format == KMF_FORMAT_PKCS12) {
61499ebb4caSwyllys 		PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
61599ebb4caSwyllys 		if (p12 != NULL) {
61699ebb4caSwyllys 			(void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
61799ebb4caSwyllys 			PKCS12_free(p12);
61899ebb4caSwyllys 			p12 = NULL;
61999ebb4caSwyllys 		} else {
62099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
62199ebb4caSwyllys 			rv = KMF_ERR_BAD_CERT_FORMAT;
62299ebb4caSwyllys 		}
62399ebb4caSwyllys 	} else {
62499ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
62599ebb4caSwyllys 		goto cleanup;
62699ebb4caSwyllys 	}
62799ebb4caSwyllys 
62899ebb4caSwyllys 	if (xcert == NULL) {
62999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
63099ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
63199ebb4caSwyllys 		goto cleanup;
63299ebb4caSwyllys 	}
63399ebb4caSwyllys 
63430a5e8faSwyllys 	if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
63530a5e8faSwyllys 	    match == FALSE) {
63699ebb4caSwyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
63799ebb4caSwyllys 		goto cleanup;
63899ebb4caSwyllys 	}
63999ebb4caSwyllys 
64099ebb4caSwyllys 	if (outcert != NULL) {
64199ebb4caSwyllys 		*outcert = xcert;
64299ebb4caSwyllys 	}
64399ebb4caSwyllys 
64499ebb4caSwyllys cleanup:
64599ebb4caSwyllys 	if (bcert != NULL) (void) BIO_free(bcert);
64699ebb4caSwyllys 	if (rv != KMF_OK && xcert != NULL)
64799ebb4caSwyllys 		X509_free(xcert);
64899ebb4caSwyllys 
64999ebb4caSwyllys 	return (rv);
65099ebb4caSwyllys }
65199ebb4caSwyllys 
65271593db2Swyllys static int
65371593db2Swyllys datacmp(const void *a, const void *b)
65471593db2Swyllys {
65571593db2Swyllys 	KMF_DATA *adata = (KMF_DATA *)a;
65671593db2Swyllys 	KMF_DATA *bdata = (KMF_DATA *)b;
65771593db2Swyllys 	if (adata->Length > bdata->Length)
65871593db2Swyllys 		return (-1);
65971593db2Swyllys 	if (adata->Length < bdata->Length)
66071593db2Swyllys 		return (1);
66171593db2Swyllys 	return (0);
66271593db2Swyllys }
66371593db2Swyllys 
66471593db2Swyllys static KMF_RETURN
66530a5e8faSwyllys load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
66630a5e8faSwyllys     KMF_CERT_VALIDITY validity, char *pathname,
66771593db2Swyllys     KMF_DATA **certlist, uint32_t *numcerts)
66871593db2Swyllys {
66971593db2Swyllys 	KMF_RETURN rv = KMF_OK;
67071593db2Swyllys 	int i;
67171593db2Swyllys 	KMF_DATA *certs = NULL;
67271593db2Swyllys 	int nc = 0;
67371593db2Swyllys 	int hits = 0;
67471593db2Swyllys 	KMF_ENCODE_FORMAT format;
67571593db2Swyllys 
67630a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
67771593db2Swyllys 	if (rv != KMF_OK) {
67871593db2Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
67971593db2Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
68071593db2Swyllys 		return (rv);
68171593db2Swyllys 	}
68271593db2Swyllys 	if (format == KMF_FORMAT_ASN1) {
68371593db2Swyllys 		/* load a single certificate */
68471593db2Swyllys 		certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
68571593db2Swyllys 		if (certs == NULL)
68671593db2Swyllys 			return (KMF_ERR_MEMORY);
68771593db2Swyllys 		certs->Data = NULL;
68871593db2Swyllys 		certs->Length = 0;
68930a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
69030a5e8faSwyllys 		    pathname, certs);
69171593db2Swyllys 		if (rv == KMF_OK) {
69271593db2Swyllys 			*certlist = certs;
69371593db2Swyllys 			*numcerts = 1;
694a2d4930dSDan OpenSolaris Anderson 		} else {
695a2d4930dSDan OpenSolaris Anderson 			kmf_free_data(certs);
696a2d4930dSDan OpenSolaris Anderson 			free(certs);
697a2d4930dSDan OpenSolaris Anderson 			certs = NULL;
69871593db2Swyllys 		}
69971593db2Swyllys 		return (rv);
70071593db2Swyllys 	} else if (format == KMF_FORMAT_PKCS12) {
70171593db2Swyllys 		/* We need a credential to access a PKCS#12 file */
70271593db2Swyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
70371593db2Swyllys 	} else if (format == KMF_FORMAT_PEM ||
70471593db2Swyllys 	    format != KMF_FORMAT_PEM_KEYPAIR) {
705e65e5c2dSWyllys Ingersoll 
70671593db2Swyllys 		/* This function only works on PEM files */
70730a5e8faSwyllys 		rv = extract_pem(kmfh, issuer, subject, serial, pathname,
70834acef67Swyllys 		    (uchar_t *)NULL, 0, NULL, &certs, &nc);
70971593db2Swyllys 	} else {
71071593db2Swyllys 		return (KMF_ERR_ENCODING);
71171593db2Swyllys 	}
71271593db2Swyllys 
71371593db2Swyllys 	if (rv != KMF_OK)
71471593db2Swyllys 		return (rv);
71571593db2Swyllys 
71671593db2Swyllys 	for (i = 0; i < nc; i++) {
71730a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
71830a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
71930a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
72030a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
72171593db2Swyllys 			if (rv == KMF_OK)
72271593db2Swyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
72371593db2Swyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD)
72471593db2Swyllys 				rv = KMF_OK;
72571593db2Swyllys 		}
72671593db2Swyllys 		if (rv != KMF_OK) {
72771593db2Swyllys 			/* Remove this cert from the list by clearing it. */
72830a5e8faSwyllys 			kmf_free_data(&certs[i]);
72971593db2Swyllys 		} else {
73071593db2Swyllys 			hits++; /* count valid certs found */
73171593db2Swyllys 		}
73271593db2Swyllys 		rv = KMF_OK;
73371593db2Swyllys 	}
734a2d4930dSDan OpenSolaris Anderson 	if (rv == KMF_OK && hits > 0) {
73571593db2Swyllys 		/*
73671593db2Swyllys 		 * Sort the list of certs by length to put the cleared ones
73771593db2Swyllys 		 * at the end so they don't get accessed by the caller.
73871593db2Swyllys 		 */
73971593db2Swyllys 		qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
74071593db2Swyllys 		*certlist = certs;
74171593db2Swyllys 
74271593db2Swyllys 		/* since we sorted the list, just return the number of hits */
74371593db2Swyllys 		*numcerts = hits;
744a2d4930dSDan OpenSolaris Anderson 	} else {
745e65e5c2dSWyllys Ingersoll 		if (rv == KMF_OK && hits == 0)
746a2d4930dSDan OpenSolaris Anderson 			rv = KMF_ERR_CERT_NOT_FOUND;
747a2d4930dSDan OpenSolaris Anderson 		if (certs != NULL) {
748a2d4930dSDan OpenSolaris Anderson 			free(certs);
749a2d4930dSDan OpenSolaris Anderson 			certs = NULL;
750a2d4930dSDan OpenSolaris Anderson 		}
751a2d4930dSDan OpenSolaris Anderson 	}
75271593db2Swyllys 	return (rv);
75371593db2Swyllys }
75471593db2Swyllys 
75599ebb4caSwyllys static KMF_RETURN
75699ebb4caSwyllys kmf_load_cert(KMF_HANDLE *kmfh,
75730a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
75830a5e8faSwyllys     KMF_CERT_VALIDITY validity,
75999ebb4caSwyllys     char *pathname,
76099ebb4caSwyllys     KMF_DATA *cert)
76199ebb4caSwyllys {
76299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
76399ebb4caSwyllys 	X509 *x509cert = NULL;
76499ebb4caSwyllys 
76530a5e8faSwyllys 	rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
76699ebb4caSwyllys 	if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
76799ebb4caSwyllys 		rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
76899ebb4caSwyllys 		if (rv != KMF_OK) {
76999ebb4caSwyllys 			goto cleanup;
77099ebb4caSwyllys 		}
77130a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
77230a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
77330a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
77430a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
77599ebb4caSwyllys 			if (rv == KMF_OK)  {
77699ebb4caSwyllys 				/*
77799ebb4caSwyllys 				 * This is a valid cert so skip it.
77899ebb4caSwyllys 				 */
77999ebb4caSwyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
78099ebb4caSwyllys 			}
78199ebb4caSwyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD) {
78299ebb4caSwyllys 				/*
78399ebb4caSwyllys 				 * We want to return success when we
78499ebb4caSwyllys 				 * find an invalid cert.
78599ebb4caSwyllys 				 */
78699ebb4caSwyllys 				rv = KMF_OK;
78799ebb4caSwyllys 				goto cleanup;
78899ebb4caSwyllys 			}
78999ebb4caSwyllys 		}
79099ebb4caSwyllys 	}
79199ebb4caSwyllys cleanup:
79299ebb4caSwyllys 	if (x509cert != NULL)
79399ebb4caSwyllys 		X509_free(x509cert);
79499ebb4caSwyllys 
79599ebb4caSwyllys 	return (rv);
79699ebb4caSwyllys }
79799ebb4caSwyllys 
79802744e81Swyllys static KMF_RETURN
79902744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
80002744e81Swyllys {
80102744e81Swyllys 	KMF_RETURN ret = KMF_OK;
80202744e81Swyllys 	KMF_RAW_RSA_KEY rsa;
80302744e81Swyllys 	BerElement *asn1 = NULL;
80402744e81Swyllys 	BerValue filebuf;
80502744e81Swyllys 	BerValue OID = { NULL, 0 };
80602744e81Swyllys 	BerValue *Mod = NULL, *PubExp = NULL;
80702744e81Swyllys 	BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
80802744e81Swyllys 	BerValue *Coef = NULL;
80902744e81Swyllys 	BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
81002744e81Swyllys 	BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
81102744e81Swyllys 	BIGNUM *qminus1 = NULL;
81202744e81Swyllys 	BN_CTX *ctx = NULL;
81302744e81Swyllys 
81402744e81Swyllys 	*pkey = NULL;
81502744e81Swyllys 
81602744e81Swyllys 	filebuf.bv_val = (char *)filedata->Data;
81702744e81Swyllys 	filebuf.bv_len = filedata->Length;
81802744e81Swyllys 
81902744e81Swyllys 	asn1 = kmfder_init(&filebuf);
82002744e81Swyllys 	if (asn1 == NULL) {
82102744e81Swyllys 		ret = KMF_ERR_MEMORY;
82202744e81Swyllys 		goto out;
82302744e81Swyllys 	}
82402744e81Swyllys 
82502744e81Swyllys 	if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
82602744e81Swyllys 	    &OID, &Mod, &PubExp, &PriExp, &Prime1,
82702744e81Swyllys 	    &Prime2, &Coef) == -1)  {
82802744e81Swyllys 		ret = KMF_ERR_ENCODING;
82902744e81Swyllys 		goto out;
83002744e81Swyllys 	}
83102744e81Swyllys 
83202744e81Swyllys 	/*
83302744e81Swyllys 	 * We have to derive the 2 Exponents using Bignumber math.
83402744e81Swyllys 	 * Exp1 = PriExp mod (Prime1 - 1)
83502744e81Swyllys 	 * Exp2 = PriExp mod (Prime2 - 1)
83602744e81Swyllys 	 */
83702744e81Swyllys 
83802744e81Swyllys 	/* D = PrivateExponent */
83902744e81Swyllys 	D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
84002744e81Swyllys 	if (D == NULL) {
84102744e81Swyllys 		ret = KMF_ERR_MEMORY;
84202744e81Swyllys 		goto out;
84302744e81Swyllys 	}
84402744e81Swyllys 
84502744e81Swyllys 	/* P = Prime1 (first prime factor of Modulus) */
84602744e81Swyllys 	P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
84702744e81Swyllys 	if (D == NULL) {
84802744e81Swyllys 		ret = KMF_ERR_MEMORY;
84902744e81Swyllys 		goto out;
85002744e81Swyllys 	}
85102744e81Swyllys 
85202744e81Swyllys 	/* Q = Prime2 (second prime factor of Modulus) */
85302744e81Swyllys 	Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
85402744e81Swyllys 
85502744e81Swyllys 	if ((ctx = BN_CTX_new()) == NULL) {
85602744e81Swyllys 		ret = KMF_ERR_MEMORY;
85702744e81Swyllys 		goto out;
85802744e81Swyllys 	}
85902744e81Swyllys 
86002744e81Swyllys 	/* Compute (P - 1) */
86102744e81Swyllys 	pminus1 = BN_new();
86202744e81Swyllys 	(void) BN_sub(pminus1, P, BN_value_one());
86302744e81Swyllys 
86402744e81Swyllys 	/* Exponent1 = D mod (P - 1) */
86502744e81Swyllys 	Exp1 = BN_new();
86602744e81Swyllys 	(void) BN_mod(Exp1, D, pminus1, ctx);
86702744e81Swyllys 
86802744e81Swyllys 	/* Compute (Q - 1) */
86902744e81Swyllys 	qminus1 = BN_new();
87002744e81Swyllys 	(void) BN_sub(qminus1, Q, BN_value_one());
87102744e81Swyllys 
87202744e81Swyllys 	/* Exponent2 = D mod (Q - 1) */
87302744e81Swyllys 	Exp2 = BN_new();
87402744e81Swyllys 	(void) BN_mod(Exp2, D, qminus1, ctx);
87502744e81Swyllys 
87602744e81Swyllys 	/* Coef = (Inverse Q) mod P */
87702744e81Swyllys 	COEF = BN_new();
87802744e81Swyllys 	(void) BN_mod_inverse(COEF, Q, P, ctx);
87902744e81Swyllys 
88002744e81Swyllys 	/* Convert back to KMF format */
88102744e81Swyllys 	(void) memset(&rsa, 0, sizeof (rsa));
88202744e81Swyllys 
88302744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
88402744e81Swyllys 		goto out;
88502744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
88602744e81Swyllys 		goto out;
88702744e81Swyllys 	if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
88802744e81Swyllys 		goto out;
88902744e81Swyllys 
89002744e81Swyllys 	rsa.mod.val = (uchar_t *)Mod->bv_val;
89102744e81Swyllys 	rsa.mod.len = Mod->bv_len;
89202744e81Swyllys 
89302744e81Swyllys 	rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
89402744e81Swyllys 	rsa.pubexp.len = PubExp->bv_len;
89502744e81Swyllys 
89602744e81Swyllys 	rsa.priexp.val = (uchar_t *)PriExp->bv_val;
89702744e81Swyllys 	rsa.priexp.len = PriExp->bv_len;
89802744e81Swyllys 
89902744e81Swyllys 	rsa.prime1.val = (uchar_t *)Prime1->bv_val;
90002744e81Swyllys 	rsa.prime1.len = Prime1->bv_len;
90102744e81Swyllys 
90202744e81Swyllys 	rsa.prime2.val = (uchar_t *)Prime2->bv_val;
90302744e81Swyllys 	rsa.prime2.len = Prime2->bv_len;
90402744e81Swyllys 
90502744e81Swyllys 	*pkey = ImportRawRSAKey(&rsa);
90602744e81Swyllys out:
90702744e81Swyllys 	if (asn1 != NULL)
90802744e81Swyllys 		kmfber_free(asn1, 1);
90902744e81Swyllys 
91002744e81Swyllys 	if (OID.bv_val) {
91102744e81Swyllys 		free(OID.bv_val);
91202744e81Swyllys 	}
91302744e81Swyllys 	if (PriExp)
91402744e81Swyllys 		free(PriExp);
91502744e81Swyllys 
91602744e81Swyllys 	if (Mod)
91702744e81Swyllys 		free(Mod);
91802744e81Swyllys 
91902744e81Swyllys 	if (PubExp)
92002744e81Swyllys 		free(PubExp);
92102744e81Swyllys 
92202744e81Swyllys 	if (Coef) {
92302744e81Swyllys 		(void) memset(Coef->bv_val, 0, Coef->bv_len);
92402744e81Swyllys 		free(Coef->bv_val);
92502744e81Swyllys 		free(Coef);
92602744e81Swyllys 	}
92702744e81Swyllys 	if (Prime1)
92802744e81Swyllys 		free(Prime1);
92902744e81Swyllys 	if (Prime2)
93002744e81Swyllys 		free(Prime2);
93102744e81Swyllys 
93202744e81Swyllys 	if (ctx != NULL)
93302744e81Swyllys 		BN_CTX_free(ctx);
93402744e81Swyllys 
93502744e81Swyllys 	if (D)
93602744e81Swyllys 		BN_clear_free(D);
93702744e81Swyllys 	if (P)
93802744e81Swyllys 		BN_clear_free(P);
93902744e81Swyllys 	if (Q)
94002744e81Swyllys 		BN_clear_free(Q);
94102744e81Swyllys 	if (pminus1)
94202744e81Swyllys 		BN_clear_free(pminus1);
94302744e81Swyllys 	if (qminus1)
94402744e81Swyllys 		BN_clear_free(qminus1);
94502744e81Swyllys 	if (Exp1)
94602744e81Swyllys 		BN_clear_free(Exp1);
94702744e81Swyllys 	if (Exp2)
94802744e81Swyllys 		BN_clear_free(Exp2);
94902744e81Swyllys 
95002744e81Swyllys 	return (ret);
95102744e81Swyllys 
95202744e81Swyllys }
95302744e81Swyllys 
95499ebb4caSwyllys static EVP_PKEY *
95599ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file)
95699ebb4caSwyllys {
95799ebb4caSwyllys 	BIO *keyfile = NULL;
95899ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
95999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
96099ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
96102744e81Swyllys 	KMF_RETURN rv;
96202744e81Swyllys 	KMF_DATA filedata;
96399ebb4caSwyllys 
96499ebb4caSwyllys 	if (file == NULL) {
96599ebb4caSwyllys 		return (NULL);
96699ebb4caSwyllys 	}
96799ebb4caSwyllys 
96830a5e8faSwyllys 	if (kmf_get_file_format((char *)file, &format) != KMF_OK)
96999ebb4caSwyllys 		return (NULL);
97099ebb4caSwyllys 
97199ebb4caSwyllys 	keyfile = BIO_new_file(file, "rb");
97299ebb4caSwyllys 	if (keyfile == NULL) {
97399ebb4caSwyllys 		goto end;
97499ebb4caSwyllys 	}
97599ebb4caSwyllys 
97602744e81Swyllys 	if (format == KMF_FORMAT_ASN1) {
97799ebb4caSwyllys 		pkey = d2i_PrivateKey_bio(keyfile, NULL);
97802744e81Swyllys 		if (pkey == NULL) {
97902744e81Swyllys 
98002744e81Swyllys 			(void) BIO_free(keyfile);
98102744e81Swyllys 			keyfile = NULL;
98202744e81Swyllys 			/* Try odd ASN.1 variations */
98330a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
98402744e81Swyllys 			    &filedata);
98502744e81Swyllys 			if (rv == KMF_OK) {
98602744e81Swyllys 				(void) readAltFormatPrivateKey(&filedata,
98702744e81Swyllys 				    &pkey);
98830a5e8faSwyllys 				kmf_free_data(&filedata);
98902744e81Swyllys 			}
99002744e81Swyllys 		}
99102744e81Swyllys 	} else if (format == KMF_FORMAT_PEM ||
99202744e81Swyllys 	    format == KMF_FORMAT_PEM_KEYPAIR) {
99399ebb4caSwyllys 		pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
99402744e81Swyllys 		if (pkey == NULL) {
99502744e81Swyllys 			KMF_DATA derdata;
99602744e81Swyllys 			/*
99702744e81Swyllys 			 * Check if this is the alt. format
99802744e81Swyllys 			 * RSA private key file.
99902744e81Swyllys 			 */
100030a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
100102744e81Swyllys 			    &filedata);
100202744e81Swyllys 			if (rv == KMF_OK) {
100302744e81Swyllys 				uchar_t *d = NULL;
100402744e81Swyllys 				int len;
100530a5e8faSwyllys 				rv = kmf_pem_to_der(filedata.Data,
100602744e81Swyllys 				    filedata.Length, &d, &len);
100702744e81Swyllys 				if (rv == KMF_OK && d != NULL) {
100802744e81Swyllys 					derdata.Data = d;
100902744e81Swyllys 					derdata.Length = (size_t)len;
101002744e81Swyllys 					(void) readAltFormatPrivateKey(
101102744e81Swyllys 					    &derdata, &pkey);
101202744e81Swyllys 					free(d);
101302744e81Swyllys 				}
101430a5e8faSwyllys 				kmf_free_data(&filedata);
101502744e81Swyllys 			}
101602744e81Swyllys 		}
101702744e81Swyllys 	}
101899ebb4caSwyllys 
101999ebb4caSwyllys end:
102099ebb4caSwyllys 	if (pkey == NULL)
102199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
102299ebb4caSwyllys 
102399ebb4caSwyllys 	if (keyfile != NULL)
102499ebb4caSwyllys 		(void) BIO_free(keyfile);
102599ebb4caSwyllys 
102699ebb4caSwyllys 	return (pkey);
102799ebb4caSwyllys }
102899ebb4caSwyllys 
102999ebb4caSwyllys KMF_RETURN
103030a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
103199ebb4caSwyllys {
103299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
103399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1034f482c776Swyllys 	int i, n;
1035f482c776Swyllys 	uint32_t maxcerts = 0;
103630a5e8faSwyllys 	uint32_t *num_certs;
103730a5e8faSwyllys 	KMF_X509_DER_CERT *kmf_cert = NULL;
103830a5e8faSwyllys 	char *dirpath = NULL;
103930a5e8faSwyllys 	char *filename = NULL;
104030a5e8faSwyllys 	char *fullpath = NULL;
104130a5e8faSwyllys 	char *issuer = NULL;
104230a5e8faSwyllys 	char *subject = NULL;
104330a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
104430a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
104599ebb4caSwyllys 
104630a5e8faSwyllys 	num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
104730a5e8faSwyllys 	if (num_certs == NULL)
104899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
104999ebb4caSwyllys 
105030a5e8faSwyllys 	/* num_certs should reference the size of kmf_cert */
1051f482c776Swyllys 	maxcerts = *num_certs;
1052f482c776Swyllys 	if (maxcerts == 0)
1053f482c776Swyllys 		maxcerts = 0xFFFFFFFF;
105499ebb4caSwyllys 	*num_certs = 0;
105599ebb4caSwyllys 
105630a5e8faSwyllys 	/* Get the optional returned certificate list  */
105730a5e8faSwyllys 	kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
105830a5e8faSwyllys 	    numattr);
105999ebb4caSwyllys 
106030a5e8faSwyllys 	/*
106130a5e8faSwyllys 	 * The dirpath attribute and the filename attribute can not be NULL
106230a5e8faSwyllys 	 * at the same time.
106330a5e8faSwyllys 	 */
106430a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
106530a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
106630a5e8faSwyllys 	    numattr);
106730a5e8faSwyllys 
106830a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
106999ebb4caSwyllys 	if (fullpath == NULL)
107099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
107199ebb4caSwyllys 
107230a5e8faSwyllys 	/* Get optional search criteria attributes */
107330a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
107430a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
107530a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
107630a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
107730a5e8faSwyllys 	    &validity, NULL);
107830a5e8faSwyllys 	if (rv != KMF_OK) {
107930a5e8faSwyllys 		validity = KMF_ALL_CERTS;
108030a5e8faSwyllys 		rv = KMF_OK;
108130a5e8faSwyllys 	}
108230a5e8faSwyllys 
108399ebb4caSwyllys 	if (isdir(fullpath)) {
108499ebb4caSwyllys 		DIR *dirp;
108599ebb4caSwyllys 		struct dirent *dp;
108699ebb4caSwyllys 
1087f482c776Swyllys 		n = 0;
108899ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
108999ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
109099ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
109199ebb4caSwyllys 		}
109299ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
109399ebb4caSwyllys 			char *fname;
109471593db2Swyllys 			KMF_DATA *certlist = NULL;
1095f482c776Swyllys 			uint32_t loaded_certs = 0;
109671593db2Swyllys 
109799ebb4caSwyllys 			if (strcmp(dp->d_name, ".") == 0 ||
109899ebb4caSwyllys 			    strcmp(dp->d_name, "..") == 0)
109999ebb4caSwyllys 				continue;
110099ebb4caSwyllys 
110134acef67Swyllys 			fname = get_fullpath(fullpath, (char *)&dp->d_name);
110299ebb4caSwyllys 
110330a5e8faSwyllys 			rv = load_certs(kmfh, issuer, subject, serial,
110430a5e8faSwyllys 			    validity, fname, &certlist,	&loaded_certs);
110599ebb4caSwyllys 
110699ebb4caSwyllys 			if (rv != KMF_OK) {
110799ebb4caSwyllys 				free(fname);
110871593db2Swyllys 				if (certlist != NULL) {
1109f482c776Swyllys 					for (i = 0; i < loaded_certs; i++)
111030a5e8faSwyllys 						kmf_free_data(&certlist[i]);
111171593db2Swyllys 					free(certlist);
111271593db2Swyllys 				}
111399ebb4caSwyllys 				continue;
111499ebb4caSwyllys 			}
111599ebb4caSwyllys 
111699ebb4caSwyllys 			/* If load succeeds, add certdata to the list */
111799ebb4caSwyllys 			if (kmf_cert != NULL) {
1118f482c776Swyllys 				for (i = 0; i < loaded_certs &&
1119b4058258Swyllys 				    n < maxcerts; i++) {
112071593db2Swyllys 					kmf_cert[n].certificate.Data =
112171593db2Swyllys 					    certlist[i].Data;
112299ebb4caSwyllys 					kmf_cert[n].certificate.Length =
112371593db2Swyllys 					    certlist[i].Length;
112499ebb4caSwyllys 
112599ebb4caSwyllys 					kmf_cert[n].kmf_private.keystore_type =
112699ebb4caSwyllys 					    KMF_KEYSTORE_OPENSSL;
112799ebb4caSwyllys 					kmf_cert[n].kmf_private.flags =
112899ebb4caSwyllys 					    KMF_FLAG_CERT_VALID;
112971593db2Swyllys 					kmf_cert[n].kmf_private.label =
113071593db2Swyllys 					    strdup(fname);
113199ebb4caSwyllys 					n++;
113299ebb4caSwyllys 				}
1133b4058258Swyllys 				/*
1134b4058258Swyllys 				 * If maxcerts < loaded_certs, clean up the
1135b4058258Swyllys 				 * certs that were not used.
1136b4058258Swyllys 				 */
1137f482c776Swyllys 				for (; i < loaded_certs; i++)
113830a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1139f482c776Swyllys 			} else {
1140f482c776Swyllys 				for (i = 0; i < loaded_certs; i++)
114130a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1142f482c776Swyllys 				n += loaded_certs;
114371593db2Swyllys 			}
1144f482c776Swyllys 			free(certlist);
114571593db2Swyllys 			free(fname);
114671593db2Swyllys 		}
114799ebb4caSwyllys 		(*num_certs) = n;
114899ebb4caSwyllys 		if (*num_certs == 0)
114999ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
115030a5e8faSwyllys 		if (*num_certs > 0)
115199ebb4caSwyllys 			rv = KMF_OK;
115299ebb4caSwyllys exit:
115399ebb4caSwyllys 		(void) closedir(dirp);
115499ebb4caSwyllys 	} else {
115571593db2Swyllys 		KMF_DATA *certlist = NULL;
1156f482c776Swyllys 		uint32_t loaded_certs = 0;
115771593db2Swyllys 
115830a5e8faSwyllys 		rv = load_certs(kmfh, issuer, subject, serial, validity,
115930a5e8faSwyllys 		    fullpath, &certlist, &loaded_certs);
116099ebb4caSwyllys 		if (rv != KMF_OK) {
116199ebb4caSwyllys 			free(fullpath);
116299ebb4caSwyllys 			return (rv);
116399ebb4caSwyllys 		}
116499ebb4caSwyllys 
1165f482c776Swyllys 		n = 0;
116671593db2Swyllys 		if (kmf_cert != NULL && certlist != NULL) {
1167f482c776Swyllys 			for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1168f482c776Swyllys 				kmf_cert[n].certificate.Data =
116971593db2Swyllys 				    certlist[i].Data;
1170f482c776Swyllys 				kmf_cert[n].certificate.Length =
117171593db2Swyllys 				    certlist[i].Length;
1172f482c776Swyllys 				kmf_cert[n].kmf_private.keystore_type =
117399ebb4caSwyllys 				    KMF_KEYSTORE_OPENSSL;
1174f482c776Swyllys 				kmf_cert[n].kmf_private.flags =
117571593db2Swyllys 				    KMF_FLAG_CERT_VALID;
1176f482c776Swyllys 				kmf_cert[n].kmf_private.label =
117771593db2Swyllys 				    strdup(fullpath);
1178f482c776Swyllys 				n++;
117971593db2Swyllys 			}
1180f482c776Swyllys 			/* If maxcerts < loaded_certs, clean up */
1181f482c776Swyllys 			for (; i < loaded_certs; i++)
118230a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1183f482c776Swyllys 		} else if (certlist != NULL) {
1184f482c776Swyllys 			for (i = 0; i < loaded_certs; i++)
118530a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1186f482c776Swyllys 			n = loaded_certs;
1187f482c776Swyllys 		}
118830a5e8faSwyllys 		if (certlist != NULL)
118971593db2Swyllys 			free(certlist);
1190f482c776Swyllys 		*num_certs = n;
119199ebb4caSwyllys 	}
119299ebb4caSwyllys 
119399ebb4caSwyllys 	free(fullpath);
119499ebb4caSwyllys 
119599ebb4caSwyllys 	return (rv);
119699ebb4caSwyllys }
119799ebb4caSwyllys 
119899ebb4caSwyllys void
119999ebb4caSwyllys /*ARGSUSED*/
120099ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
120199ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert)
120299ebb4caSwyllys {
120399ebb4caSwyllys 	if (kmf_cert != NULL) {
120499ebb4caSwyllys 		if (kmf_cert->certificate.Data != NULL) {
1205e65e5c2dSWyllys Ingersoll 			kmf_free_data(&kmf_cert->certificate);
120699ebb4caSwyllys 		}
120799ebb4caSwyllys 		if (kmf_cert->kmf_private.label)
120899ebb4caSwyllys 			free(kmf_cert->kmf_private.label);
120999ebb4caSwyllys 	}
121099ebb4caSwyllys }
121199ebb4caSwyllys 
121230a5e8faSwyllys /*ARGSUSED*/
121399ebb4caSwyllys KMF_RETURN
121430a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
121599ebb4caSwyllys {
121699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
121730a5e8faSwyllys 	KMF_DATA *cert = NULL;
121830a5e8faSwyllys 	char *outfilename = NULL;
121930a5e8faSwyllys 	char *dirpath = NULL;
122030a5e8faSwyllys 	char *fullpath = NULL;
122199ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
122299ebb4caSwyllys 
122330a5e8faSwyllys 	/* Get the cert data */
122430a5e8faSwyllys 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
122530a5e8faSwyllys 	if (cert == NULL || cert->Data == NULL)
122699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
122799ebb4caSwyllys 
122830a5e8faSwyllys 	/* Check the output filename and directory attributes. */
122930a5e8faSwyllys 	outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
123030a5e8faSwyllys 	    numattr);
123130a5e8faSwyllys 	if (outfilename == NULL)
123230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
123399ebb4caSwyllys 
123430a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
123530a5e8faSwyllys 	fullpath = get_fullpath(dirpath, outfilename);
123699ebb4caSwyllys 	if (fullpath == NULL)
123730a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
123899ebb4caSwyllys 
123930a5e8faSwyllys 	/* Check the optional format attribute */
124030a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
124130a5e8faSwyllys 	    &format, NULL);
124230a5e8faSwyllys 	if (ret != KMF_OK) {
124330a5e8faSwyllys 		/* If there is no format attribute, then default to PEM */
124430a5e8faSwyllys 		format = KMF_FORMAT_PEM;
124599ebb4caSwyllys 		ret = KMF_OK;
124630a5e8faSwyllys 	} else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
124730a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
124899ebb4caSwyllys 		goto out;
124999ebb4caSwyllys 	}
125099ebb4caSwyllys 
125130a5e8faSwyllys 	/* Store the certificate in the file with the specified format */
125230a5e8faSwyllys 	ret = kmf_create_cert_file(cert, format, fullpath);
125399ebb4caSwyllys 
125499ebb4caSwyllys out:
125599ebb4caSwyllys 	if (fullpath != NULL)
125699ebb4caSwyllys 		free(fullpath);
125799ebb4caSwyllys 
125899ebb4caSwyllys 	return (ret);
125999ebb4caSwyllys }
126099ebb4caSwyllys 
126130a5e8faSwyllys 
126299ebb4caSwyllys KMF_RETURN
126330a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
126499ebb4caSwyllys {
126599ebb4caSwyllys 	KMF_RETURN rv;
126699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
126799ebb4caSwyllys 	KMF_DATA certdata = {NULL, 0};
126830a5e8faSwyllys 	char *dirpath = NULL;
126930a5e8faSwyllys 	char *filename = NULL;
127030a5e8faSwyllys 	char *fullpath = NULL;
127130a5e8faSwyllys 	char *issuer = NULL;
127230a5e8faSwyllys 	char *subject = NULL;
127330a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
127430a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
127599ebb4caSwyllys 
127630a5e8faSwyllys 	/*
127730a5e8faSwyllys 	 * Get the DIRPATH and CERT_FILENAME attributes.  They can not be
127830a5e8faSwyllys 	 * NULL at the same time.
127930a5e8faSwyllys 	 */
128030a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
128130a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
128230a5e8faSwyllys 	    numattr);
128330a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
128499ebb4caSwyllys 	if (fullpath == NULL)
128599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
128699ebb4caSwyllys 
128730a5e8faSwyllys 	/* Get optional search criteria attributes */
128830a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
128930a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
129030a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
129130a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
129230a5e8faSwyllys 	    &validity, NULL);
129330a5e8faSwyllys 	if (rv != KMF_OK) {
129430a5e8faSwyllys 		validity = KMF_ALL_CERTS;
129530a5e8faSwyllys 		rv = KMF_OK;
129630a5e8faSwyllys 	}
129730a5e8faSwyllys 
129899ebb4caSwyllys 	if (isdir(fullpath)) {
129999ebb4caSwyllys 		DIR *dirp;
130099ebb4caSwyllys 		struct dirent *dp;
130199ebb4caSwyllys 
130299ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
130399ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
130499ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
130599ebb4caSwyllys 		}
130699ebb4caSwyllys 
130799ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
130899ebb4caSwyllys 			if (strcmp(dp->d_name, ".") != 0 &&
130999ebb4caSwyllys 			    strcmp(dp->d_name, "..") != 0) {
131099ebb4caSwyllys 				char *fname;
131199ebb4caSwyllys 
131299ebb4caSwyllys 				fname = get_fullpath(fullpath,
131399ebb4caSwyllys 				    (char *)&dp->d_name);
131499ebb4caSwyllys 
131599ebb4caSwyllys 				if (fname == NULL) {
131699ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
131799ebb4caSwyllys 					break;
131899ebb4caSwyllys 				}
131999ebb4caSwyllys 
132030a5e8faSwyllys 				rv = kmf_load_cert(kmfh, issuer, subject,
132130a5e8faSwyllys 				    serial, validity, fname, &certdata);
132299ebb4caSwyllys 
132399ebb4caSwyllys 				if (rv == KMF_ERR_CERT_NOT_FOUND) {
132499ebb4caSwyllys 					free(fname);
1325e65e5c2dSWyllys Ingersoll 					kmf_free_data(&certdata);
132699ebb4caSwyllys 					rv = KMF_OK;
132799ebb4caSwyllys 					continue;
132899ebb4caSwyllys 				} else if (rv != KMF_OK) {
132999ebb4caSwyllys 					free(fname);
133099ebb4caSwyllys 					break;
133199ebb4caSwyllys 				}
133299ebb4caSwyllys 
133399ebb4caSwyllys 				if (unlink(fname) != 0) {
133499ebb4caSwyllys 					SET_SYS_ERROR(kmfh, errno);
133599ebb4caSwyllys 					rv = KMF_ERR_INTERNAL;
133699ebb4caSwyllys 					free(fname);
133799ebb4caSwyllys 					break;
133899ebb4caSwyllys 				}
133999ebb4caSwyllys 				free(fname);
1340e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certdata);
134199ebb4caSwyllys 			}
134299ebb4caSwyllys 		}
134399ebb4caSwyllys 		(void) closedir(dirp);
134499ebb4caSwyllys 	} else {
134599ebb4caSwyllys 		/* Just try to load a single certificate */
134630a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
134730a5e8faSwyllys 		    fullpath, &certdata);
134899ebb4caSwyllys 		if (rv == KMF_OK) {
134999ebb4caSwyllys 			if (unlink(fullpath) != 0) {
135099ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
135199ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
135299ebb4caSwyllys 			}
135399ebb4caSwyllys 		}
135499ebb4caSwyllys 	}
135599ebb4caSwyllys 
135699ebb4caSwyllys out:
135799ebb4caSwyllys 	if (fullpath != NULL)
135899ebb4caSwyllys 		free(fullpath);
135999ebb4caSwyllys 
1360e65e5c2dSWyllys Ingersoll 	kmf_free_data(&certdata);
136199ebb4caSwyllys 
136299ebb4caSwyllys 	return (rv);
136399ebb4caSwyllys }
136499ebb4caSwyllys 
136599ebb4caSwyllys KMF_RETURN
136699ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
136799ebb4caSwyllys 	KMF_DATA *keydata)
136899ebb4caSwyllys {
136999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
137099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
137199ebb4caSwyllys 	int n;
137299ebb4caSwyllys 
137399ebb4caSwyllys 	if (key == NULL || keydata == NULL ||
137499ebb4caSwyllys 	    key->keyp == NULL)
137599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
137699ebb4caSwyllys 
137799ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
137899ebb4caSwyllys 		RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
137999ebb4caSwyllys 
138099ebb4caSwyllys 		if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
138199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
138299ebb4caSwyllys 			return (KMF_ERR_ENCODING);
138399ebb4caSwyllys 		}
138499ebb4caSwyllys 		RSA_free(pubkey);
138599ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
138699ebb4caSwyllys 		DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
138799ebb4caSwyllys 
138899ebb4caSwyllys 		if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
138999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
139099ebb4caSwyllys 			return (KMF_ERR_ENCODING);
139199ebb4caSwyllys 		}
139299ebb4caSwyllys 		DSA_free(pubkey);
139399ebb4caSwyllys 	} else {
139499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
139599ebb4caSwyllys 	}
139699ebb4caSwyllys 	keydata->Length = n;
139799ebb4caSwyllys 
139899ebb4caSwyllys cleanup:
139999ebb4caSwyllys 	if (rv != KMF_OK) {
140099ebb4caSwyllys 		if (keydata->Data)
140199ebb4caSwyllys 			free(keydata->Data);
140299ebb4caSwyllys 		keydata->Data = NULL;
140399ebb4caSwyllys 		keydata->Length = 0;
140499ebb4caSwyllys 	}
140599ebb4caSwyllys 
140699ebb4caSwyllys 	return (rv);
140799ebb4caSwyllys }
140899ebb4caSwyllys 
140999ebb4caSwyllys static KMF_RETURN
141030a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
141130a5e8faSwyllys 	KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
141299ebb4caSwyllys {
141399ebb4caSwyllys 	int rv = 0;
141499ebb4caSwyllys 	RSA *rsa;
141599ebb4caSwyllys 	DSA *dsa;
141699ebb4caSwyllys 
14175b3e1433Swyllys 	if (pkey == NULL || out == NULL)
14185b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
14195b3e1433Swyllys 
142099ebb4caSwyllys 	switch (format) {
142173cc0e02Swyllys 		case KMF_FORMAT_RAWKEY:
142273cc0e02Swyllys 			/* same as ASN.1 */
142399ebb4caSwyllys 		case KMF_FORMAT_ASN1:
142499ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
142599ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
142630a5e8faSwyllys 				if (private)
142799ebb4caSwyllys 					rv = i2d_RSAPrivateKey_bio(out, rsa);
142830a5e8faSwyllys 				else
142930a5e8faSwyllys 					rv = i2d_RSAPublicKey_bio(out, rsa);
143099ebb4caSwyllys 				RSA_free(rsa);
143199ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
143299ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
143399ebb4caSwyllys 				rv = i2d_DSAPrivateKey_bio(out, dsa);
143499ebb4caSwyllys 				DSA_free(dsa);
143599ebb4caSwyllys 			}
143699ebb4caSwyllys 			if (rv == 1) {
143799ebb4caSwyllys 				rv = KMF_OK;
143899ebb4caSwyllys 			} else {
143999ebb4caSwyllys 				SET_ERROR(kmfh, rv);
144099ebb4caSwyllys 			}
144199ebb4caSwyllys 			break;
144299ebb4caSwyllys 		case KMF_FORMAT_PEM:
144399ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
144499ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
144530a5e8faSwyllys 				if (private)
144699ebb4caSwyllys 					rv = PEM_write_bio_RSAPrivateKey(out,
144730a5e8faSwyllys 					    rsa, NULL, NULL, 0, NULL,
144830a5e8faSwyllys 					    (cred != NULL ? cred->cred : NULL));
144930a5e8faSwyllys 				else
145030a5e8faSwyllys 					rv = PEM_write_bio_RSAPublicKey(out,
145130a5e8faSwyllys 					    rsa);
145299ebb4caSwyllys 				RSA_free(rsa);
145399ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
145499ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
145599ebb4caSwyllys 				rv = PEM_write_bio_DSAPrivateKey(out,
145630a5e8faSwyllys 				    dsa, NULL, NULL, 0, NULL,
145730a5e8faSwyllys 				    (cred != NULL ? cred->cred : NULL));
145899ebb4caSwyllys 				DSA_free(dsa);
145999ebb4caSwyllys 			}
146099ebb4caSwyllys 
146199ebb4caSwyllys 			if (rv == 1) {
146299ebb4caSwyllys 				rv = KMF_OK;
146399ebb4caSwyllys 			} else {
146499ebb4caSwyllys 				SET_ERROR(kmfh, rv);
146599ebb4caSwyllys 			}
146699ebb4caSwyllys 			break;
146799ebb4caSwyllys 
146899ebb4caSwyllys 		default:
146999ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
147099ebb4caSwyllys 	}
147199ebb4caSwyllys 
147299ebb4caSwyllys 	return (rv);
147399ebb4caSwyllys }
147499ebb4caSwyllys 
147599ebb4caSwyllys KMF_RETURN
147630a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
147730a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
147899ebb4caSwyllys {
147999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
148099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
148199ebb4caSwyllys 	uint32_t eValue = 0x010001;
148299ebb4caSwyllys 	RSA *sslPrivKey = NULL;
148399ebb4caSwyllys 	DSA *sslDSAKey = NULL;
148499ebb4caSwyllys 	EVP_PKEY *eprikey = NULL;
148599ebb4caSwyllys 	EVP_PKEY *epubkey = NULL;
148699ebb4caSwyllys 	BIO *out = NULL;
148730a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
148830a5e8faSwyllys 	uint32_t keylen = 1024;
148930a5e8faSwyllys 	uint32_t keylen_size = sizeof (uint32_t);
149030a5e8faSwyllys 	boolean_t storekey = TRUE;
149130a5e8faSwyllys 	KMF_KEY_ALG keytype = KMF_RSA;
149299ebb4caSwyllys 
149330a5e8faSwyllys 	rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
149430a5e8faSwyllys 	    &storekey, NULL);
149530a5e8faSwyllys 	if (rv != KMF_OK) {
149630a5e8faSwyllys 		/* "storekey" is optional. Default is TRUE */
149730a5e8faSwyllys 		rv = KMF_OK;
149899ebb4caSwyllys 	}
149999ebb4caSwyllys 
150030a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
150130a5e8faSwyllys 	    (void *)&keytype, NULL);
150230a5e8faSwyllys 	if (rv != KMF_OK)
150330a5e8faSwyllys 		/* keytype is optional.  KMF_RSA is default */
150430a5e8faSwyllys 		rv = KMF_OK;
150599ebb4caSwyllys 
150630a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
150730a5e8faSwyllys 	if (pubkey == NULL)
150899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
150999ebb4caSwyllys 
151030a5e8faSwyllys 	privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
151130a5e8faSwyllys 	if (privkey == NULL)
151230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
151330a5e8faSwyllys 
151430a5e8faSwyllys 	(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
151530a5e8faSwyllys 	(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
151699ebb4caSwyllys 
151799ebb4caSwyllys 	eprikey = EVP_PKEY_new();
151899ebb4caSwyllys 	if (eprikey == NULL) {
151999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
152099ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
152199ebb4caSwyllys 		goto cleanup;
152299ebb4caSwyllys 	}
152399ebb4caSwyllys 	epubkey = EVP_PKEY_new();
152499ebb4caSwyllys 	if (epubkey == NULL) {
152599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
152699ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
152799ebb4caSwyllys 		goto cleanup;
152899ebb4caSwyllys 	}
152930a5e8faSwyllys 	if (keytype == KMF_RSA) {
153030a5e8faSwyllys 		KMF_BIGINT *rsaexp = NULL;
153199ebb4caSwyllys 
153230a5e8faSwyllys 		rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
153330a5e8faSwyllys 		if (rsaexp != NULL) {
153430a5e8faSwyllys 			if (rsaexp->len > 0 &&
153530a5e8faSwyllys 			    rsaexp->len <= sizeof (eValue) &&
153630a5e8faSwyllys 			    rsaexp->val != NULL) {
1537a2d4930dSDan OpenSolaris Anderson 				/* LINTED E_BAD_PTR_CAST_ALIGN */
153830a5e8faSwyllys 				eValue = *(uint32_t *)rsaexp->val;
153930a5e8faSwyllys 			} else {
154030a5e8faSwyllys 				rv = KMF_ERR_BAD_PARAMETER;
154130a5e8faSwyllys 				goto cleanup;
154230a5e8faSwyllys 			}
154330a5e8faSwyllys 		} else {
154430a5e8faSwyllys 			/* RSA Exponent is optional. Default is 0x10001 */
154530a5e8faSwyllys 			rv = KMF_OK;
154630a5e8faSwyllys 		}
154730a5e8faSwyllys 
154830a5e8faSwyllys 		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
154930a5e8faSwyllys 		    &keylen, &keylen_size);
155030a5e8faSwyllys 		if (rv == KMF_ERR_ATTR_NOT_FOUND)
155130a5e8faSwyllys 			/* keylen is optional, default is 1024 */
155230a5e8faSwyllys 			rv = KMF_OK;
155330a5e8faSwyllys 		if (rv != KMF_OK) {
155430a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
155530a5e8faSwyllys 			goto cleanup;
155630a5e8faSwyllys 		}
155730a5e8faSwyllys 
155830a5e8faSwyllys 		sslPrivKey = RSA_generate_key(keylen, eValue, NULL, NULL);
155999ebb4caSwyllys 		if (sslPrivKey == NULL) {
156099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
156199ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
156299ebb4caSwyllys 		} else {
156330a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
156499ebb4caSwyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
156599ebb4caSwyllys 			privkey->keyalg = KMF_RSA;
156699ebb4caSwyllys 			privkey->keyclass = KMF_ASYM_PRI;
156799ebb4caSwyllys 			privkey->israw = FALSE;
156899ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
156930a5e8faSwyllys 
157099ebb4caSwyllys 			/* OpenSSL derives the public key from the private */
157130a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
157299ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
157399ebb4caSwyllys 			pubkey->keyalg = KMF_RSA;
157499ebb4caSwyllys 			pubkey->israw = FALSE;
157599ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
157699ebb4caSwyllys 			pubkey->keyp = (void *)epubkey;
157799ebb4caSwyllys 		}
157830a5e8faSwyllys 	} else if (keytype == KMF_DSA) {
157930a5e8faSwyllys 		DSA *dp;
158099ebb4caSwyllys 		sslDSAKey = DSA_new();
158199ebb4caSwyllys 		if (sslDSAKey == NULL) {
158299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
158399ebb4caSwyllys 			return (KMF_ERR_MEMORY);
158499ebb4caSwyllys 		}
158599ebb4caSwyllys 
158699ebb4caSwyllys 		if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) ==
158799ebb4caSwyllys 		    NULL) {
158899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
158999ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
159099ebb4caSwyllys 			goto cleanup;
159199ebb4caSwyllys 		}
159299ebb4caSwyllys 		if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) ==
159399ebb4caSwyllys 		    NULL) {
159499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
159599ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
159699ebb4caSwyllys 			goto cleanup;
159799ebb4caSwyllys 		}
159899ebb4caSwyllys 		if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) ==
159999ebb4caSwyllys 		    NULL) {
160099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
160199ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
160299ebb4caSwyllys 			goto cleanup;
160399ebb4caSwyllys 		}
160499ebb4caSwyllys 
160599ebb4caSwyllys 		if (!DSA_generate_key(sslDSAKey)) {
160699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
160799ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
160899ebb4caSwyllys 			goto cleanup;
160999ebb4caSwyllys 		}
161099ebb4caSwyllys 
161199ebb4caSwyllys 		privkey->kstype = KMF_KEYSTORE_OPENSSL;
161299ebb4caSwyllys 		privkey->keyalg = KMF_DSA;
161399ebb4caSwyllys 		privkey->keyclass = KMF_ASYM_PRI;
161499ebb4caSwyllys 		privkey->israw = FALSE;
161599ebb4caSwyllys 		if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
161699ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
161799ebb4caSwyllys 		} else {
161899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
161999ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
162099ebb4caSwyllys 			goto cleanup;
162199ebb4caSwyllys 		}
162230a5e8faSwyllys 		dp = DSA_new();
162399ebb4caSwyllys 		/* Make a copy for the public key */
162499ebb4caSwyllys 		if (dp != NULL) {
162599ebb4caSwyllys 			if ((dp->p = BN_new()) == NULL) {
162699ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
162799ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
162899ebb4caSwyllys 				DSA_free(dp);
162999ebb4caSwyllys 				goto cleanup;
163099ebb4caSwyllys 			}
163199ebb4caSwyllys 			if ((dp->q = BN_new()) == NULL) {
163299ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
163399ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
163499ebb4caSwyllys 				BN_free(dp->p);
163599ebb4caSwyllys 				DSA_free(dp);
163699ebb4caSwyllys 				goto cleanup;
163799ebb4caSwyllys 			}
163899ebb4caSwyllys 			if ((dp->g = BN_new()) == NULL) {
163999ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
164099ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
164199ebb4caSwyllys 				BN_free(dp->q);
164299ebb4caSwyllys 				BN_free(dp->p);
164399ebb4caSwyllys 				DSA_free(dp);
164499ebb4caSwyllys 				goto cleanup;
164599ebb4caSwyllys 			}
164699ebb4caSwyllys 			if ((dp->pub_key = BN_new()) == NULL) {
164799ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
164899ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
164999ebb4caSwyllys 				BN_free(dp->q);
165099ebb4caSwyllys 				BN_free(dp->p);
165199ebb4caSwyllys 				BN_free(dp->g);
165299ebb4caSwyllys 				DSA_free(dp);
165399ebb4caSwyllys 				goto cleanup;
165499ebb4caSwyllys 			}
165599ebb4caSwyllys 			(void) BN_copy(dp->p, sslDSAKey->p);
165699ebb4caSwyllys 			(void) BN_copy(dp->q, sslDSAKey->q);
165799ebb4caSwyllys 			(void) BN_copy(dp->g, sslDSAKey->g);
165899ebb4caSwyllys 			(void) BN_copy(dp->pub_key, sslDSAKey->pub_key);
165999ebb4caSwyllys 
166099ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
166199ebb4caSwyllys 			pubkey->keyalg = KMF_DSA;
166299ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
166399ebb4caSwyllys 			pubkey->israw = FALSE;
166499ebb4caSwyllys 
166599ebb4caSwyllys 			if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
166699ebb4caSwyllys 				pubkey->keyp = (void *)epubkey;
166799ebb4caSwyllys 			} else {
166899ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
166999ebb4caSwyllys 				rv = KMF_ERR_KEYGEN_FAILED;
167099ebb4caSwyllys 				goto cleanup;
167199ebb4caSwyllys 			}
167299ebb4caSwyllys 		}
167399ebb4caSwyllys 	}
167499ebb4caSwyllys 
167599ebb4caSwyllys 	if (rv != KMF_OK) {
167699ebb4caSwyllys 		goto cleanup;
167799ebb4caSwyllys 	}
167899ebb4caSwyllys 
167930a5e8faSwyllys 	if (storekey) {
168030a5e8faSwyllys 		KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
168130a5e8faSwyllys 		int i = 0;
168230a5e8faSwyllys 		char *keyfile = NULL, *dirpath = NULL;
168330a5e8faSwyllys 		KMF_ENCODE_FORMAT format;
168430a5e8faSwyllys 		/*
168530a5e8faSwyllys 		 * Construct a new attribute arrray and call openssl_store_key
168630a5e8faSwyllys 		 */
168730a5e8faSwyllys 		kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
168830a5e8faSwyllys 		    privkey, sizeof (privkey));
168930a5e8faSwyllys 		i++;
169030a5e8faSwyllys 
169130a5e8faSwyllys 		dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
169230a5e8faSwyllys 		if (dirpath != NULL) {
169330a5e8faSwyllys 			storeattrs[i].type = KMF_DIRPATH_ATTR;
169430a5e8faSwyllys 			storeattrs[i].pValue = dirpath;
169530a5e8faSwyllys 			storeattrs[i].valueLen = strlen(dirpath);
169630a5e8faSwyllys 			i++;
169730a5e8faSwyllys 		} else {
169830a5e8faSwyllys 			rv = KMF_OK; /* DIRPATH is optional */
169999ebb4caSwyllys 		}
170030a5e8faSwyllys 		keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
170130a5e8faSwyllys 		    attrlist, numattr);
170230a5e8faSwyllys 		if (keyfile != NULL) {
170330a5e8faSwyllys 			storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
170430a5e8faSwyllys 			storeattrs[i].pValue = keyfile;
170530a5e8faSwyllys 			storeattrs[i].valueLen = strlen(keyfile);
170630a5e8faSwyllys 			i++;
170730a5e8faSwyllys 		} else {
170830a5e8faSwyllys 			goto cleanup; /* KEYFILE is required */
170930a5e8faSwyllys 		}
171030a5e8faSwyllys 		rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
171130a5e8faSwyllys 		    (void *)&format, NULL);
171230a5e8faSwyllys 		if (rv == KMF_OK) {
171330a5e8faSwyllys 			storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
171430a5e8faSwyllys 			storeattrs[i].pValue = &format;
171530a5e8faSwyllys 			storeattrs[i].valueLen = sizeof (format);
171630a5e8faSwyllys 			i++;
171730a5e8faSwyllys 		}
171830a5e8faSwyllys 
171930a5e8faSwyllys 		rv = OpenSSL_StoreKey(handle, i, storeattrs);
172030a5e8faSwyllys 	}
172199ebb4caSwyllys 
172299ebb4caSwyllys cleanup:
172399ebb4caSwyllys 	if (rv != KMF_OK) {
172499ebb4caSwyllys 		if (eprikey != NULL)
172599ebb4caSwyllys 			EVP_PKEY_free(eprikey);
172699ebb4caSwyllys 
172799ebb4caSwyllys 		if (epubkey != NULL)
172899ebb4caSwyllys 			EVP_PKEY_free(epubkey);
172999ebb4caSwyllys 
173099ebb4caSwyllys 		if (pubkey->keylabel) {
173199ebb4caSwyllys 			free(pubkey->keylabel);
173299ebb4caSwyllys 			pubkey->keylabel = NULL;
173399ebb4caSwyllys 		}
173499ebb4caSwyllys 
173599ebb4caSwyllys 		if (privkey->keylabel) {
173699ebb4caSwyllys 			free(privkey->keylabel);
173799ebb4caSwyllys 			privkey->keylabel = NULL;
173899ebb4caSwyllys 		}
173999ebb4caSwyllys 
174099ebb4caSwyllys 		pubkey->keyp = NULL;
174199ebb4caSwyllys 		privkey->keyp = NULL;
174299ebb4caSwyllys 	}
174399ebb4caSwyllys 
174499ebb4caSwyllys 	if (sslPrivKey)
174599ebb4caSwyllys 		RSA_free(sslPrivKey);
174699ebb4caSwyllys 
174799ebb4caSwyllys 	if (sslDSAKey)
174899ebb4caSwyllys 		DSA_free(sslDSAKey);
174999ebb4caSwyllys 
175099ebb4caSwyllys 	if (out != NULL)
175199ebb4caSwyllys 		(void) BIO_free(out);
175299ebb4caSwyllys 
175399ebb4caSwyllys 	return (rv);
175499ebb4caSwyllys }
175599ebb4caSwyllys 
1756e65e5c2dSWyllys Ingersoll /*
1757e65e5c2dSWyllys Ingersoll  * Make sure the BN conversion is properly padded with 0x00
1758e65e5c2dSWyllys Ingersoll  * bytes.  If not, signature verification for DSA signatures
1759e65e5c2dSWyllys Ingersoll  * may fail in the case where the bignum value does not use
1760e65e5c2dSWyllys Ingersoll  * all of the bits.
1761e65e5c2dSWyllys Ingersoll  */
1762e65e5c2dSWyllys Ingersoll static int
1763e65e5c2dSWyllys Ingersoll fixbnlen(BIGNUM *bn, unsigned char *buf, int len) {
1764e65e5c2dSWyllys Ingersoll 	int bytes = len - BN_num_bytes(bn);
17652c9a247fSWyllys Ingersoll 
17662c9a247fSWyllys Ingersoll 	/* prepend with leading 0x00 if necessary */
1767e65e5c2dSWyllys Ingersoll 	while (bytes-- > 0)
1768e65e5c2dSWyllys Ingersoll 		*buf++ = 0;
1769e65e5c2dSWyllys Ingersoll 
17702c9a247fSWyllys Ingersoll 	(void) BN_bn2bin(bn, buf);
17712c9a247fSWyllys Ingersoll 	/*
17722c9a247fSWyllys Ingersoll 	 * Return the desired length since we prepended it
17732c9a247fSWyllys Ingersoll 	 * with the necessary 0x00 padding.
17742c9a247fSWyllys Ingersoll 	 */
17752c9a247fSWyllys Ingersoll 	return (len);
1776e65e5c2dSWyllys Ingersoll }
1777e65e5c2dSWyllys Ingersoll 
177899ebb4caSwyllys KMF_RETURN
177999ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
178099ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
178199ebb4caSwyllys {
178299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
178399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
178499ebb4caSwyllys 	KMF_ALGORITHM_INDEX		AlgId;
178599ebb4caSwyllys 	EVP_MD_CTX ctx;
178699ebb4caSwyllys 	const EVP_MD *md;
178702744e81Swyllys 
178899ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
178999ebb4caSwyllys 	    tobesigned == NULL || output == NULL ||
179099ebb4caSwyllys 	    tobesigned->Data == NULL ||
179199ebb4caSwyllys 	    output->Data == NULL)
179299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
179399ebb4caSwyllys 
179499ebb4caSwyllys 	/* Map the OID to an OpenSSL algorithm */
179530a5e8faSwyllys 	AlgId = x509_algoid_to_algid(AlgOID);
179699ebb4caSwyllys 	if (AlgId == KMF_ALGID_NONE)
1797e65e5c2dSWyllys Ingersoll 		return (KMF_ERR_BAD_ALGORITHM);
179899ebb4caSwyllys 
179999ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
180099ebb4caSwyllys 		EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
180199ebb4caSwyllys 		uchar_t *p;
180202744e81Swyllys 		int len;
180399ebb4caSwyllys 		if (AlgId == KMF_ALGID_MD5WithRSA)
180499ebb4caSwyllys 			md = EVP_md5();
180599ebb4caSwyllys 		else if (AlgId == KMF_ALGID_MD2WithRSA)
180699ebb4caSwyllys 			md = EVP_md2();
180799ebb4caSwyllys 		else if (AlgId == KMF_ALGID_SHA1WithRSA)
180899ebb4caSwyllys 			md = EVP_sha1();
1809e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA256WithRSA)
1810e65e5c2dSWyllys Ingersoll 			md = EVP_sha256();
1811e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA384WithRSA)
1812e65e5c2dSWyllys Ingersoll 			md = EVP_sha384();
1813e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA512WithRSA)
1814e65e5c2dSWyllys Ingersoll 			md = EVP_sha512();
181502744e81Swyllys 		else if (AlgId == KMF_ALGID_RSA)
181602744e81Swyllys 			md = NULL;
181799ebb4caSwyllys 		else
1818e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_ALGORITHM);
181999ebb4caSwyllys 
182002744e81Swyllys 		if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
182102744e81Swyllys 			RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
182299ebb4caSwyllys 
182302744e81Swyllys 			p = output->Data;
182402744e81Swyllys 			if ((len = RSA_private_encrypt(tobesigned->Length,
182502744e81Swyllys 			    tobesigned->Data, p, rsa,
182602744e81Swyllys 			    RSA_PKCS1_PADDING)) <= 0) {
182702744e81Swyllys 				SET_ERROR(kmfh, ERR_get_error());
182802744e81Swyllys 				ret = KMF_ERR_INTERNAL;
182902744e81Swyllys 			}
183002744e81Swyllys 			output->Length = len;
183102744e81Swyllys 		} else {
183299ebb4caSwyllys 			(void) EVP_MD_CTX_init(&ctx);
183399ebb4caSwyllys 			(void) EVP_SignInit_ex(&ctx, md, NULL);
183499ebb4caSwyllys 			(void) EVP_SignUpdate(&ctx, tobesigned->Data,
183599ebb4caSwyllys 			    (uint32_t)tobesigned->Length);
183699ebb4caSwyllys 			len = (uint32_t)output->Length;
183799ebb4caSwyllys 			p = output->Data;
183802744e81Swyllys 			if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) {
183999ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
184002744e81Swyllys 				len = 0;
184102744e81Swyllys 				ret = KMF_ERR_INTERNAL;
184299ebb4caSwyllys 			}
184399ebb4caSwyllys 			output->Length = len;
184499ebb4caSwyllys 			(void) EVP_MD_CTX_cleanup(&ctx);
184502744e81Swyllys 		}
184699ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
184799ebb4caSwyllys 		DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
184899ebb4caSwyllys 
184999ebb4caSwyllys 		uchar_t hash[EVP_MAX_MD_SIZE];
185099ebb4caSwyllys 		uint32_t hashlen;
185199ebb4caSwyllys 		DSA_SIG *dsasig;
185299ebb4caSwyllys 
1853e65e5c2dSWyllys Ingersoll 		if (AlgId == KMF_ALGID_DSA ||
1854e65e5c2dSWyllys Ingersoll 		    AlgId == KMF_ALGID_SHA1WithDSA)
1855e65e5c2dSWyllys Ingersoll 			md = EVP_sha1();
1856e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA256WithDSA)
1857e65e5c2dSWyllys Ingersoll 			md = EVP_sha256();
1858e65e5c2dSWyllys Ingersoll 		else /* Bad algorithm */
1859e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_ALGORITHM);
1860e65e5c2dSWyllys Ingersoll 
186199ebb4caSwyllys 		/*
186299ebb4caSwyllys 		 * OpenSSL EVP_Sign operation automatically converts to
186399ebb4caSwyllys 		 * ASN.1 output so we do the operations separately so we
186499ebb4caSwyllys 		 * are assured of NOT getting ASN.1 output returned.
186599ebb4caSwyllys 		 * KMF does not want ASN.1 encoded results because
186699ebb4caSwyllys 		 * not all mechanisms return ASN.1 encodings (PKCS#11
186799ebb4caSwyllys 		 * and NSS return raw signature data).
186899ebb4caSwyllys 		 */
186999ebb4caSwyllys 		EVP_MD_CTX_init(&ctx);
187099ebb4caSwyllys 		(void) EVP_DigestInit_ex(&ctx, md, NULL);
187199ebb4caSwyllys 		(void) EVP_DigestUpdate(&ctx, tobesigned->Data,
187299ebb4caSwyllys 		    tobesigned->Length);
187399ebb4caSwyllys 		(void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
187499ebb4caSwyllys 
1875e65e5c2dSWyllys Ingersoll 		/* Only sign first 20 bytes for SHA2 */
1876e65e5c2dSWyllys Ingersoll 		if (AlgId == KMF_ALGID_SHA256WithDSA)
1877e65e5c2dSWyllys Ingersoll 			hashlen = 20;
187899ebb4caSwyllys 		dsasig = DSA_do_sign(hash, hashlen, dsa);
187999ebb4caSwyllys 		if (dsasig != NULL) {
188099ebb4caSwyllys 			int i;
1881e65e5c2dSWyllys Ingersoll 			output->Length = i = fixbnlen(dsasig->r, output->Data,
1882e65e5c2dSWyllys Ingersoll 			    hashlen);
18832c9a247fSWyllys Ingersoll 
1884e65e5c2dSWyllys Ingersoll 			output->Length += fixbnlen(dsasig->s, &output->Data[i],
1885e65e5c2dSWyllys Ingersoll 			    hashlen);
18862c9a247fSWyllys Ingersoll 
188799ebb4caSwyllys 			DSA_SIG_free(dsasig);
188899ebb4caSwyllys 		} else {
188999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
189099ebb4caSwyllys 		}
1891e65e5c2dSWyllys Ingersoll 		(void) EVP_MD_CTX_cleanup(&ctx);
189299ebb4caSwyllys 	} else {
189399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
189499ebb4caSwyllys 	}
189599ebb4caSwyllys cleanup:
189699ebb4caSwyllys 	return (ret);
189799ebb4caSwyllys }
189899ebb4caSwyllys 
189999ebb4caSwyllys KMF_RETURN
190099ebb4caSwyllys /*ARGSUSED*/
190130a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle,
190230a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
190399ebb4caSwyllys {
190499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
190530a5e8faSwyllys 	KMF_KEY_HANDLE *key;
190630a5e8faSwyllys 	boolean_t destroy = B_TRUE;
190730a5e8faSwyllys 
190830a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
190999ebb4caSwyllys 	if (key == NULL || key->keyp == NULL)
191099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
191199ebb4caSwyllys 
191230a5e8faSwyllys 	rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
191330a5e8faSwyllys 	    (void *)&destroy, NULL);
191430a5e8faSwyllys 	if (rv != KMF_OK) {
191530a5e8faSwyllys 		/* "destroy" is optional. Default is TRUE */
191630a5e8faSwyllys 		rv = KMF_OK;
191730a5e8faSwyllys 	}
191830a5e8faSwyllys 
191999ebb4caSwyllys 	if (key->keyclass != KMF_ASYM_PUB &&
192099ebb4caSwyllys 	    key->keyclass != KMF_ASYM_PRI &&
192199ebb4caSwyllys 	    key->keyclass != KMF_SYMMETRIC)
192299ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
192399ebb4caSwyllys 
192499ebb4caSwyllys 	if (key->keyclass == KMF_SYMMETRIC) {
192530a5e8faSwyllys 		kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
192699ebb4caSwyllys 		key->keyp = NULL;
192799ebb4caSwyllys 	} else {
192899ebb4caSwyllys 		if (key->keyp != NULL) {
192999ebb4caSwyllys 			EVP_PKEY_free(key->keyp);
193099ebb4caSwyllys 			key->keyp = NULL;
193199ebb4caSwyllys 		}
193299ebb4caSwyllys 	}
193399ebb4caSwyllys 
193499ebb4caSwyllys 	if (key->keylabel != NULL) {
193599ebb4caSwyllys 		EVP_PKEY *pkey = NULL;
193699ebb4caSwyllys 		/* If the file exists, make sure it is a proper key. */
193799ebb4caSwyllys 		pkey = openssl_load_key(handle, key->keylabel);
193899ebb4caSwyllys 		if (pkey == NULL) {
19395b3e1433Swyllys 			if (key->keylabel != NULL) {
194099ebb4caSwyllys 				free(key->keylabel);
194199ebb4caSwyllys 				key->keylabel = NULL;
19425b3e1433Swyllys 			}
194399ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
194499ebb4caSwyllys 		}
194599ebb4caSwyllys 		EVP_PKEY_free(pkey);
194699ebb4caSwyllys 
194799ebb4caSwyllys 		if (destroy) {
194899ebb4caSwyllys 			if (unlink(key->keylabel) != 0) {
194999ebb4caSwyllys 				KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
195099ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
195199ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
195299ebb4caSwyllys 			}
195399ebb4caSwyllys 		}
195499ebb4caSwyllys 		if (key->keylabel != NULL) {
195599ebb4caSwyllys 			free(key->keylabel);
195699ebb4caSwyllys 			key->keylabel = NULL;
195799ebb4caSwyllys 		}
195899ebb4caSwyllys 	}
195999ebb4caSwyllys 	return (rv);
196099ebb4caSwyllys }
196199ebb4caSwyllys 
196299ebb4caSwyllys KMF_RETURN
196399ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
196499ebb4caSwyllys {
196599ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
196699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
196799ebb4caSwyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
196899ebb4caSwyllys 
196999ebb4caSwyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
197099ebb4caSwyllys 	if (strlen(str)) {
197199ebb4caSwyllys 		*msgstr = (char *)strdup(str);
197299ebb4caSwyllys 		if ((*msgstr) == NULL)
197399ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
197499ebb4caSwyllys 	} else {
197599ebb4caSwyllys 		*msgstr = NULL;
197699ebb4caSwyllys 	}
197799ebb4caSwyllys 
197899ebb4caSwyllys 	return (ret);
197999ebb4caSwyllys }
198099ebb4caSwyllys 
198199ebb4caSwyllys static int
198299ebb4caSwyllys ext2NID(int kmfext)
198399ebb4caSwyllys {
198499ebb4caSwyllys 	switch (kmfext) {
198599ebb4caSwyllys 		case KMF_X509_EXT_KEY_USAGE:
198699ebb4caSwyllys 			return (NID_key_usage);
198799ebb4caSwyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
198899ebb4caSwyllys 			return (NID_private_key_usage_period);
198999ebb4caSwyllys 		case KMF_X509_EXT_CERT_POLICIES:
199099ebb4caSwyllys 			return (NID_certificate_policies);
199199ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
199299ebb4caSwyllys 			return (NID_subject_alt_name);
199399ebb4caSwyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
199499ebb4caSwyllys 			return (NID_issuer_alt_name);
199599ebb4caSwyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
199699ebb4caSwyllys 			return (NID_basic_constraints);
199799ebb4caSwyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
199899ebb4caSwyllys 			return (NID_ext_key_usage);
199999ebb4caSwyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
200099ebb4caSwyllys 			return (NID_authority_key_identifier);
200199ebb4caSwyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
200299ebb4caSwyllys 			return (NID_crl_distribution_points);
200399ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
200499ebb4caSwyllys 			return (NID_subject_key_identifier);
200599ebb4caSwyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
200699ebb4caSwyllys 			return (OBJ_sn2nid("policyMappings"));
200799ebb4caSwyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
200899ebb4caSwyllys 			return (OBJ_sn2nid("nameConstraints"));
200999ebb4caSwyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
201099ebb4caSwyllys 			return (OBJ_sn2nid("policyConstraints"));
201199ebb4caSwyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
201299ebb4caSwyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
201399ebb4caSwyllys 		case KMF_X509_EXT_FRESHEST_CRL:
201499ebb4caSwyllys 			return (OBJ_sn2nid("freshestCRL"));
201599ebb4caSwyllys 		default:
201699ebb4caSwyllys 			return (NID_undef);
201799ebb4caSwyllys 	}
201899ebb4caSwyllys }
201999ebb4caSwyllys 
202099ebb4caSwyllys KMF_RETURN
202199ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
202299ebb4caSwyllys 	KMF_PRINTABLE_ITEM flag, char *resultStr)
202399ebb4caSwyllys {
202499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
202599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
202699ebb4caSwyllys 	X509 *xcert = NULL;
202799ebb4caSwyllys 	unsigned char *outbuf = NULL;
202899ebb4caSwyllys 	unsigned char *outbuf_p;
202999ebb4caSwyllys 	char *tmpstr = NULL;
203099ebb4caSwyllys 	int j;
203199ebb4caSwyllys 	int ext_index, nid, len;
203299ebb4caSwyllys 	BIO *mem = NULL;
2033*70f9559bSTheo Schlossnagle #if OPENSSL_VERSION_NUMBER < 0x10000000L
203499ebb4caSwyllys 	STACK *emlst = NULL;
2035*70f9559bSTheo Schlossnagle #else
2036*70f9559bSTheo Schlossnagle         STACK_OF(OPENSSL_STRING) *emlst = NULL;
2037*70f9559bSTheo Schlossnagle #endif
203899ebb4caSwyllys 	X509_EXTENSION *ex;
203999ebb4caSwyllys 	X509_CINF *ci;
204099ebb4caSwyllys 
204199ebb4caSwyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
204299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
204399ebb4caSwyllys 	}
204499ebb4caSwyllys 
204599ebb4caSwyllys 	/* copy cert data to outbuf */
204699ebb4caSwyllys 	outbuf = malloc(pcert->Length);
204799ebb4caSwyllys 	if (outbuf == NULL) {
204899ebb4caSwyllys 		return (KMF_ERR_MEMORY);
204999ebb4caSwyllys 	}
205099ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
205199ebb4caSwyllys 
205299ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
205399ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
205499ebb4caSwyllys 	if (xcert == NULL) {
205599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
205699ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
205799ebb4caSwyllys 		goto out;
205899ebb4caSwyllys 	}
205999ebb4caSwyllys 
206099ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
206199ebb4caSwyllys 	if (mem == NULL) {
206299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
206399ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
206499ebb4caSwyllys 		goto out;
206599ebb4caSwyllys 	}
206699ebb4caSwyllys 
206799ebb4caSwyllys 	switch (flag) {
206899ebb4caSwyllys 	case KMF_CERT_ISSUER:
206999ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
207099ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
207199ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
207299ebb4caSwyllys 		break;
207399ebb4caSwyllys 
207499ebb4caSwyllys 	case KMF_CERT_SUBJECT:
207599ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
207699ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
207799ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
207899ebb4caSwyllys 		break;
207999ebb4caSwyllys 
208099ebb4caSwyllys 	case KMF_CERT_VERSION:
208199ebb4caSwyllys 		tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version);
208299ebb4caSwyllys 		(void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN);
208399ebb4caSwyllys 		OPENSSL_free(tmpstr);
208499ebb4caSwyllys 		len = strlen(resultStr);
208599ebb4caSwyllys 		break;
208699ebb4caSwyllys 
208799ebb4caSwyllys 	case KMF_CERT_SERIALNUM:
208899ebb4caSwyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
208999ebb4caSwyllys 			(void) strcpy(resultStr, "0x");
209099ebb4caSwyllys 			len = BIO_gets(mem, &resultStr[2],
209199ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN - 2);
209299ebb4caSwyllys 		}
209399ebb4caSwyllys 		break;
209499ebb4caSwyllys 
209599ebb4caSwyllys 	case KMF_CERT_NOTBEFORE:
209699ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notBefore(xcert));
209799ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
209899ebb4caSwyllys 		break;
209999ebb4caSwyllys 
210099ebb4caSwyllys 	case KMF_CERT_NOTAFTER:
210199ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notAfter(xcert));
210299ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
210399ebb4caSwyllys 		break;
210499ebb4caSwyllys 
210599ebb4caSwyllys 	case KMF_CERT_PUBKEY_DATA:
210699ebb4caSwyllys 		{
210799ebb4caSwyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
210899ebb4caSwyllys 			if (pkey == NULL) {
210999ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
211099ebb4caSwyllys 				ret = KMF_ERR_ENCODING;
211199ebb4caSwyllys 				goto out;
211299ebb4caSwyllys 			}
211399ebb4caSwyllys 
211499ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
211599ebb4caSwyllys 				(void) BIO_printf(mem,
211699ebb4caSwyllys 				    "RSA Public Key: (%d bit)\n",
211799ebb4caSwyllys 				    BN_num_bits(pkey->pkey.rsa->n));
211899ebb4caSwyllys 				(void) RSA_print(mem, pkey->pkey.rsa, 0);
211999ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
212099ebb4caSwyllys 				(void) BIO_printf(mem,
212199ebb4caSwyllys 				    "%12sDSA Public Key:\n", "");
212299ebb4caSwyllys 				(void) DSA_print(mem, pkey->pkey.dsa, 0);
212399ebb4caSwyllys 			} else {
212499ebb4caSwyllys 				(void) BIO_printf(mem,
212599ebb4caSwyllys 				    "%12sUnknown Public Key:\n", "");
212699ebb4caSwyllys 			}
212799ebb4caSwyllys 			(void) BIO_printf(mem, "\n");
212899ebb4caSwyllys 			EVP_PKEY_free(pkey);
212999ebb4caSwyllys 		}
213099ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
213199ebb4caSwyllys 		break;
213299ebb4caSwyllys 	case KMF_CERT_SIGNATURE_ALG:
213399ebb4caSwyllys 	case KMF_CERT_PUBKEY_ALG:
213499ebb4caSwyllys 		if (flag == KMF_CERT_SIGNATURE_ALG) {
213599ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
213699ebb4caSwyllys 			    xcert->sig_alg->algorithm);
213799ebb4caSwyllys 		} else {
213899ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
213999ebb4caSwyllys 			    xcert->cert_info->key->algor->algorithm);
214099ebb4caSwyllys 		}
214199ebb4caSwyllys 
214299ebb4caSwyllys 		if (len > 0) {
214399ebb4caSwyllys 			len = BIO_read(mem, resultStr,
214499ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN);
214599ebb4caSwyllys 		}
214699ebb4caSwyllys 		break;
214799ebb4caSwyllys 
214899ebb4caSwyllys 	case KMF_CERT_EMAIL:
214999ebb4caSwyllys 		emlst = X509_get1_email(xcert);
2150*70f9559bSTheo Schlossnagle #if OPENSSL_VERSION_NUMBER < 0x10000000L
215199ebb4caSwyllys 		for (j = 0; j < sk_num(emlst); j++)
215299ebb4caSwyllys 			(void) BIO_printf(mem, "%s\n", sk_value(emlst, j));
2153*70f9559bSTheo Schlossnagle #else
2154*70f9559bSTheo Schlossnagle 		for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
2155*70f9559bSTheo Schlossnagle 			(void) BIO_printf(mem, "%s\n",
2156*70f9559bSTheo Schlossnagle                             sk_OPENSSL_STRING_value(emlst, j));
2157*70f9559bSTheo Schlossnagle #endif
215899ebb4caSwyllys 
215999ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
216099ebb4caSwyllys 		X509_email_free(emlst);
216199ebb4caSwyllys 		break;
216299ebb4caSwyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
216399ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
216499ebb4caSwyllys 	case KMF_X509_EXT_KEY_USAGE:
216599ebb4caSwyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
216699ebb4caSwyllys 	case KMF_X509_EXT_CERT_POLICIES:
216799ebb4caSwyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
216899ebb4caSwyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
216999ebb4caSwyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
217099ebb4caSwyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
217199ebb4caSwyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
217299ebb4caSwyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
217399ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
217499ebb4caSwyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
217599ebb4caSwyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
217699ebb4caSwyllys 	case KMF_X509_EXT_FRESHEST_CRL:
217799ebb4caSwyllys 		nid = ext2NID(flag);
217899ebb4caSwyllys 		if (nid == NID_undef) {
217999ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
218099ebb4caSwyllys 			goto out;
218199ebb4caSwyllys 		}
218299ebb4caSwyllys 		ci = xcert->cert_info;
218399ebb4caSwyllys 
218499ebb4caSwyllys 		ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1);
218599ebb4caSwyllys 		if (ext_index == -1) {
218699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
218799ebb4caSwyllys 
218899ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
218999ebb4caSwyllys 			goto out;
219099ebb4caSwyllys 		}
219199ebb4caSwyllys 		ex = X509v3_get_ext(ci->extensions, ext_index);
219299ebb4caSwyllys 
219399ebb4caSwyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
219499ebb4caSwyllys 
219599ebb4caSwyllys 		if (BIO_printf(mem, ": %s\n",
219630a5e8faSwyllys 		    X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
219799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
219899ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
219999ebb4caSwyllys 			goto out;
220099ebb4caSwyllys 		}
220199ebb4caSwyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
220299ebb4caSwyllys 			(void) BIO_printf(mem, "%*s", 4, "");
220399ebb4caSwyllys 			(void) M_ASN1_OCTET_STRING_print(mem, ex->value);
220499ebb4caSwyllys 		}
220599ebb4caSwyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
220699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
220799ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
220899ebb4caSwyllys 			goto out;
220999ebb4caSwyllys 		}
221099ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
221199ebb4caSwyllys 	}
221299ebb4caSwyllys 	if (len <= 0) {
221399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
221499ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
221599ebb4caSwyllys 	}
221699ebb4caSwyllys 
221799ebb4caSwyllys out:
221899ebb4caSwyllys 	if (outbuf != NULL) {
221999ebb4caSwyllys 		free(outbuf);
222099ebb4caSwyllys 	}
222199ebb4caSwyllys 
222299ebb4caSwyllys 	if (xcert != NULL) {
222399ebb4caSwyllys 		X509_free(xcert);
222499ebb4caSwyllys 	}
222599ebb4caSwyllys 
222699ebb4caSwyllys 	if (mem != NULL) {
222799ebb4caSwyllys 		(void) BIO_free(mem);
222899ebb4caSwyllys 	}
222999ebb4caSwyllys 
223099ebb4caSwyllys 	return (ret);
223199ebb4caSwyllys }
223230a5e8faSwyllys 
223399ebb4caSwyllys KMF_RETURN
223499ebb4caSwyllys /*ARGSUSED*/
223530a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
223630a5e8faSwyllys     KMF_ATTRIBUTE *attrlist)
223799ebb4caSwyllys {
223899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
223930a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
224030a5e8faSwyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
224130a5e8faSwyllys 	KMF_KEY_HANDLE *key = NULL;
224230a5e8faSwyllys 	uint32_t numkeys = 1; /* 1 key only */
224330a5e8faSwyllys 	char *dirpath = NULL;
224430a5e8faSwyllys 	char *keyfile = NULL;
224530a5e8faSwyllys 	KMF_ATTRIBUTE new_attrlist[16];
224630a5e8faSwyllys 	int i = 0;
224799ebb4caSwyllys 
224899ebb4caSwyllys 	/*
224999ebb4caSwyllys 	 * This is really just a FindKey operation, reuse the
225099ebb4caSwyllys 	 * FindKey function.
225199ebb4caSwyllys 	 */
225230a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
225330a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
225430a5e8faSwyllys 	i++;
225599ebb4caSwyllys 
225630a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
225730a5e8faSwyllys 	    KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
225830a5e8faSwyllys 	i++;
225999ebb4caSwyllys 
226030a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
226130a5e8faSwyllys 	    KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
226230a5e8faSwyllys 	i++;
226330a5e8faSwyllys 
226430a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
226530a5e8faSwyllys 	if (key == NULL) {
226630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
226730a5e8faSwyllys 	} else {
226830a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
226930a5e8faSwyllys 		    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
227030a5e8faSwyllys 		i++;
227130a5e8faSwyllys 	}
227230a5e8faSwyllys 
227330a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
227430a5e8faSwyllys 	if (dirpath != NULL) {
227530a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
227630a5e8faSwyllys 		    KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
227730a5e8faSwyllys 		i++;
227830a5e8faSwyllys 	}
227930a5e8faSwyllys 
228030a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
228130a5e8faSwyllys 	if (keyfile == NULL)
228230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
228330a5e8faSwyllys 	else {
228430a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
228530a5e8faSwyllys 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
228630a5e8faSwyllys 		i++;
228730a5e8faSwyllys 	}
228830a5e8faSwyllys 
228930a5e8faSwyllys 	rv = OpenSSL_FindKey(handle, i, new_attrlist);
229099ebb4caSwyllys 	return (rv);
229199ebb4caSwyllys }
229299ebb4caSwyllys 
229399ebb4caSwyllys KMF_RETURN
229499ebb4caSwyllys /*ARGSUSED*/
229599ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
229699ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
229799ebb4caSwyllys 	KMF_DATA *output)
229899ebb4caSwyllys {
229999ebb4caSwyllys 	KMF_RETURN		ret = KMF_OK;
230099ebb4caSwyllys 	RSA *rsa = NULL;
230199ebb4caSwyllys 	unsigned int in_len = 0, out_len = 0;
230299ebb4caSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
230399ebb4caSwyllys 	uint8_t *in_data, *out_data;
230499ebb4caSwyllys 	int i, blocks;
230599ebb4caSwyllys 
230699ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
230799ebb4caSwyllys 	    ciphertext == NULL || output == NULL ||
230899ebb4caSwyllys 	    ciphertext->Data == NULL ||
230999ebb4caSwyllys 	    output->Data == NULL)
231099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
231199ebb4caSwyllys 
231299ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
231399ebb4caSwyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
231499ebb4caSwyllys 		modulus_len = RSA_size(rsa);
231599ebb4caSwyllys 	} else {
231699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
231799ebb4caSwyllys 	}
231899ebb4caSwyllys 
231999ebb4caSwyllys 	blocks = ciphertext->Length/modulus_len;
232099ebb4caSwyllys 	out_data = output->Data;
232199ebb4caSwyllys 	in_data = ciphertext->Data;
232299ebb4caSwyllys 	out_len = modulus_len - 11;
232399ebb4caSwyllys 	in_len = modulus_len;
232499ebb4caSwyllys 
232599ebb4caSwyllys 	for (i = 0; i < blocks; i++) {
232699ebb4caSwyllys 		out_len  = RSA_private_decrypt(in_len,
232799ebb4caSwyllys 		    in_data, out_data, rsa, RSA_PKCS1_PADDING);
232899ebb4caSwyllys 
232999ebb4caSwyllys 		if (out_len == 0) {
233099ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
233199ebb4caSwyllys 			goto cleanup;
233299ebb4caSwyllys 		}
233399ebb4caSwyllys 
233499ebb4caSwyllys 		out_data += out_len;
233599ebb4caSwyllys 		total_decrypted += out_len;
233699ebb4caSwyllys 		in_data += in_len;
233799ebb4caSwyllys 	}
233899ebb4caSwyllys 
233999ebb4caSwyllys 	output->Length = total_decrypted;
234099ebb4caSwyllys 
234199ebb4caSwyllys cleanup:
234299ebb4caSwyllys 	RSA_free(rsa);
234399ebb4caSwyllys 	if (ret != KMF_OK)
234499ebb4caSwyllys 		output->Length = 0;
234599ebb4caSwyllys 
234699ebb4caSwyllys 	return (ret);
234799ebb4caSwyllys 
234899ebb4caSwyllys }
234999ebb4caSwyllys 
235099ebb4caSwyllys /*
235199ebb4caSwyllys  *  This function will create a certid from issuer_cert and user_cert.
235299ebb4caSwyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
235399ebb4caSwyllys  *  certid memory after use.
235499ebb4caSwyllys  */
235599ebb4caSwyllys static KMF_RETURN
235699ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
235799ebb4caSwyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
235899ebb4caSwyllys {
235999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
236099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
236199ebb4caSwyllys 	X509   *issuer = NULL;
236299ebb4caSwyllys 	X509   *cert = NULL;
236399ebb4caSwyllys 	unsigned char *ptmp;
236499ebb4caSwyllys 
236599ebb4caSwyllys 	if (issuer_cert == NULL || user_cert == NULL) {
236699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
236799ebb4caSwyllys 	}
236899ebb4caSwyllys 
236999ebb4caSwyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
237099ebb4caSwyllys 	ptmp = issuer_cert->Data;
237199ebb4caSwyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
237299ebb4caSwyllys 	    issuer_cert->Length);
237399ebb4caSwyllys 	if (issuer == NULL) {
237499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
237599ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
237699ebb4caSwyllys 		goto end;
237799ebb4caSwyllys 	}
237899ebb4caSwyllys 
237999ebb4caSwyllys 	/* convert the DER-encoded user cert to an internal X509 */
238099ebb4caSwyllys 	ptmp = user_cert->Data;
238199ebb4caSwyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
238299ebb4caSwyllys 	    user_cert->Length);
238399ebb4caSwyllys 	if (cert == NULL) {
238499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
238599ebb4caSwyllys 
238699ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
238799ebb4caSwyllys 		goto end;
238899ebb4caSwyllys 	}
238999ebb4caSwyllys 
239099ebb4caSwyllys 	/* create a CERTID */
239199ebb4caSwyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
239299ebb4caSwyllys 	if (*certid == NULL) {
239399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
239499ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
239599ebb4caSwyllys 		goto end;
239699ebb4caSwyllys 	}
239799ebb4caSwyllys 
239899ebb4caSwyllys end:
239999ebb4caSwyllys 	if (issuer != NULL) {
240099ebb4caSwyllys 		X509_free(issuer);
240199ebb4caSwyllys 	}
240299ebb4caSwyllys 
240399ebb4caSwyllys 	if (cert != NULL) {
240499ebb4caSwyllys 		X509_free(cert);
240599ebb4caSwyllys 	}
240699ebb4caSwyllys 
240799ebb4caSwyllys 	return (ret);
240899ebb4caSwyllys }
240999ebb4caSwyllys 
241099ebb4caSwyllys KMF_RETURN
241130a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
241230a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
241399ebb4caSwyllys {
241499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
241599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
241699ebb4caSwyllys 	OCSP_CERTID *id = NULL;
241799ebb4caSwyllys 	OCSP_REQUEST *req = NULL;
241899ebb4caSwyllys 	BIO *derbio = NULL;
241930a5e8faSwyllys 	char *reqfile;
242030a5e8faSwyllys 	KMF_DATA *issuer_cert;
242130a5e8faSwyllys 	KMF_DATA *user_cert;
242299ebb4caSwyllys 
242330a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
242430a5e8faSwyllys 	    attrlist, numattr);
242530a5e8faSwyllys 	if (user_cert == NULL)
242699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
242799ebb4caSwyllys 
242830a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
242930a5e8faSwyllys 	    attrlist, numattr);
243030a5e8faSwyllys 	if (issuer_cert == NULL)
243130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
243230a5e8faSwyllys 
243330a5e8faSwyllys 	reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
243430a5e8faSwyllys 	    attrlist, numattr);
243530a5e8faSwyllys 	if (reqfile == NULL)
243630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
243730a5e8faSwyllys 
243830a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
243999ebb4caSwyllys 	if (ret != KMF_OK) {
244099ebb4caSwyllys 		return (ret);
244199ebb4caSwyllys 	}
244299ebb4caSwyllys 
244399ebb4caSwyllys 	/* Create an OCSP request */
244499ebb4caSwyllys 	req = OCSP_REQUEST_new();
244599ebb4caSwyllys 	if (req == NULL) {
244699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
244799ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
244899ebb4caSwyllys 		goto end;
244999ebb4caSwyllys 	}
245099ebb4caSwyllys 
245199ebb4caSwyllys 	if (!OCSP_request_add0_id(req, id)) {
245299ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
245399ebb4caSwyllys 		goto end;
245499ebb4caSwyllys 	}
245599ebb4caSwyllys 
245699ebb4caSwyllys 	/* Write the request to the output file with DER encoding */
245799ebb4caSwyllys 	derbio = BIO_new_file(reqfile, "wb");
245899ebb4caSwyllys 	if (!derbio) {
245999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
246099ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
246199ebb4caSwyllys 		goto end;
246299ebb4caSwyllys 	}
246399ebb4caSwyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
246499ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
246599ebb4caSwyllys 	}
246699ebb4caSwyllys 
246799ebb4caSwyllys end:
246899ebb4caSwyllys 	/*
2469e65e5c2dSWyllys Ingersoll 	 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2470a2d4930dSDan OpenSolaris Anderson 	 * will also deallocate certid's space.
247199ebb4caSwyllys 	 */
247299ebb4caSwyllys 	if (req != NULL) {
247399ebb4caSwyllys 		OCSP_REQUEST_free(req);
247499ebb4caSwyllys 	}
247599ebb4caSwyllys 
247699ebb4caSwyllys 	if (derbio != NULL) {
247799ebb4caSwyllys 		(void) BIO_free(derbio);
247899ebb4caSwyllys 	}
247999ebb4caSwyllys 
248099ebb4caSwyllys 	return (ret);
248199ebb4caSwyllys }
248299ebb4caSwyllys 
248399ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */
248499ebb4caSwyllys static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
248599ebb4caSwyllys {
248699ebb4caSwyllys 	int i;
248799ebb4caSwyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
248899ebb4caSwyllys 
248999ebb4caSwyllys 	/* Easy if lookup by name */
249099ebb4caSwyllys 	if (id->type == V_OCSP_RESPID_NAME)
249199ebb4caSwyllys 		return (X509_find_by_subject(certs, id->value.byName));
249299ebb4caSwyllys 
249399ebb4caSwyllys 	/* Lookup by key hash */
249499ebb4caSwyllys 
249599ebb4caSwyllys 	/* If key hash isn't SHA1 length then forget it */
249699ebb4caSwyllys 	if (id->value.byKey->length != SHA_DIGEST_LENGTH)
249799ebb4caSwyllys 		return (NULL);
249899ebb4caSwyllys 
249999ebb4caSwyllys 	keyhash = id->value.byKey->data;
250099ebb4caSwyllys 	/* Calculate hash of each key and compare */
250199ebb4caSwyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
2502a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
250399ebb4caSwyllys 		X509 *x = sk_X509_value(certs, i);
25045b3e1433Swyllys 		/* Use pubkey_digest to get the key ID value */
250599ebb4caSwyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
250699ebb4caSwyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
250799ebb4caSwyllys 			return (x);
250899ebb4caSwyllys 	}
250999ebb4caSwyllys 	return (NULL);
251099ebb4caSwyllys }
251199ebb4caSwyllys 
251299ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */
2513a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */
251499ebb4caSwyllys static int
251599ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
251699ebb4caSwyllys     X509_STORE *st, unsigned long flags)
251799ebb4caSwyllys {
251899ebb4caSwyllys 	X509 *signer;
251999ebb4caSwyllys 	OCSP_RESPID *rid = bs->tbsResponseData->responderId;
252099ebb4caSwyllys 	if ((signer = ocsp_find_signer_sk(certs, rid)))	{
252199ebb4caSwyllys 		*psigner = signer;
252299ebb4caSwyllys 		return (2);
252399ebb4caSwyllys 	}
252499ebb4caSwyllys 	if (!(flags & OCSP_NOINTERN) &&
252599ebb4caSwyllys 	    (signer = ocsp_find_signer_sk(bs->certs, rid))) {
252699ebb4caSwyllys 		*psigner = signer;
252799ebb4caSwyllys 		return (1);
252899ebb4caSwyllys 	}
252999ebb4caSwyllys 	/* Maybe lookup from store if by subject name */
253099ebb4caSwyllys 
253199ebb4caSwyllys 	*psigner = NULL;
253299ebb4caSwyllys 	return (0);
253399ebb4caSwyllys }
253499ebb4caSwyllys 
253599ebb4caSwyllys /*
253699ebb4caSwyllys  * This function will verify the signature of a basic response, using
253799ebb4caSwyllys  * the public key from the OCSP responder certificate.
253899ebb4caSwyllys  */
253999ebb4caSwyllys static KMF_RETURN
254099ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
254199ebb4caSwyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
254299ebb4caSwyllys {
254399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
254499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
254599ebb4caSwyllys 	STACK_OF(X509) *cert_stack = NULL;
254699ebb4caSwyllys 	X509 *signer = NULL;
254799ebb4caSwyllys 	X509 *issuer = NULL;
254899ebb4caSwyllys 	EVP_PKEY *skey = NULL;
254999ebb4caSwyllys 	unsigned char *ptmp;
255099ebb4caSwyllys 
255199ebb4caSwyllys 
255299ebb4caSwyllys 	if (bs == NULL || issuer_cert == NULL)
255399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
255499ebb4caSwyllys 
255599ebb4caSwyllys 	/*
255699ebb4caSwyllys 	 * Find the certificate that signed the basic response.
255799ebb4caSwyllys 	 *
255899ebb4caSwyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
255999ebb4caSwyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
256099ebb4caSwyllys 	 * If we still do not find a signer, we will look for it from the
256199ebb4caSwyllys 	 * certificate list came with the response file.
256299ebb4caSwyllys 	 */
256399ebb4caSwyllys 	if (signer_cert != NULL) {
256499ebb4caSwyllys 		ptmp = signer_cert->Data;
256599ebb4caSwyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
256699ebb4caSwyllys 		    signer_cert->Length);
256799ebb4caSwyllys 		if (signer == NULL) {
256899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
256999ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
257099ebb4caSwyllys 			goto end;
257199ebb4caSwyllys 		}
257299ebb4caSwyllys 	} else {
257399ebb4caSwyllys 		/*
257499ebb4caSwyllys 		 * Convert the issuer cert into X509 and push it into a
257599ebb4caSwyllys 		 * stack to be used by ocsp_find_signer().
257699ebb4caSwyllys 		 */
257799ebb4caSwyllys 		ptmp = issuer_cert->Data;
257899ebb4caSwyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
257999ebb4caSwyllys 		    issuer_cert->Length);
258099ebb4caSwyllys 		if (issuer == NULL) {
258199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
258299ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
258399ebb4caSwyllys 			goto end;
258499ebb4caSwyllys 		}
258599ebb4caSwyllys 
258699ebb4caSwyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
258799ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
258899ebb4caSwyllys 			goto end;
258999ebb4caSwyllys 		}
259099ebb4caSwyllys 
259199ebb4caSwyllys 		if (sk_X509_push(cert_stack, issuer) == NULL) {
259299ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
259399ebb4caSwyllys 			goto end;
259499ebb4caSwyllys 		}
259599ebb4caSwyllys 
259699ebb4caSwyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
259799ebb4caSwyllys 		if (!ret) {
259899ebb4caSwyllys 			/* can not find the signer */
259999ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
260099ebb4caSwyllys 			goto end;
260199ebb4caSwyllys 		}
260299ebb4caSwyllys 	}
260399ebb4caSwyllys 
260499ebb4caSwyllys 	/* Verify the signature of the response */
260599ebb4caSwyllys 	skey = X509_get_pubkey(signer);
260699ebb4caSwyllys 	if (skey == NULL) {
260799ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
260899ebb4caSwyllys 		goto end;
260999ebb4caSwyllys 	}
261099ebb4caSwyllys 
261199ebb4caSwyllys 	ret = OCSP_BASICRESP_verify(bs, skey, 0);
261299ebb4caSwyllys 	if (ret == 0) {
261399ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
261499ebb4caSwyllys 		goto end;
261599ebb4caSwyllys 	}
261699ebb4caSwyllys 
261799ebb4caSwyllys end:
261899ebb4caSwyllys 	if (issuer != NULL) {
261999ebb4caSwyllys 		X509_free(issuer);
262099ebb4caSwyllys 	}
262199ebb4caSwyllys 
262299ebb4caSwyllys 	if (signer != NULL) {
262399ebb4caSwyllys 		X509_free(signer);
262499ebb4caSwyllys 	}
262599ebb4caSwyllys 
262699ebb4caSwyllys 	if (skey != NULL) {
262799ebb4caSwyllys 		EVP_PKEY_free(skey);
262899ebb4caSwyllys 	}
262999ebb4caSwyllys 
263099ebb4caSwyllys 	if (cert_stack != NULL) {
263199ebb4caSwyllys 		sk_X509_free(cert_stack);
263299ebb4caSwyllys 	}
263399ebb4caSwyllys 
263499ebb4caSwyllys 	return (ret);
263599ebb4caSwyllys }
263699ebb4caSwyllys 
263799ebb4caSwyllys 
263899ebb4caSwyllys 
263999ebb4caSwyllys KMF_RETURN
264099ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
264130a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
264299ebb4caSwyllys {
264399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
264499ebb4caSwyllys 	BIO *derbio = NULL;
264599ebb4caSwyllys 	OCSP_RESPONSE *resp = NULL;
264699ebb4caSwyllys 	OCSP_BASICRESP *bs = NULL;
264799ebb4caSwyllys 	OCSP_CERTID *id = NULL;
264899ebb4caSwyllys 	OCSP_SINGLERESP *single = NULL;
264999ebb4caSwyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
265099ebb4caSwyllys 	int index, status, reason;
265130a5e8faSwyllys 	KMF_DATA *issuer_cert;
265230a5e8faSwyllys 	KMF_DATA *user_cert;
265330a5e8faSwyllys 	KMF_DATA *signer_cert;
265430a5e8faSwyllys 	KMF_DATA *response;
265530a5e8faSwyllys 	int *response_reason, *response_status, *cert_status;
265630a5e8faSwyllys 	boolean_t ignore_response_sign = B_FALSE;	/* default is FALSE */
265730a5e8faSwyllys 	uint32_t response_lifetime;
265899ebb4caSwyllys 
265930a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
266030a5e8faSwyllys 	    attrlist, numattr);
266130a5e8faSwyllys 	if (issuer_cert == NULL)
266299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
266399ebb4caSwyllys 
266430a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
266530a5e8faSwyllys 	    attrlist, numattr);
266630a5e8faSwyllys 	if (user_cert == NULL)
266799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
266830a5e8faSwyllys 
266930a5e8faSwyllys 	response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
267030a5e8faSwyllys 	    attrlist, numattr);
267130a5e8faSwyllys 	if (response == NULL)
267230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
267330a5e8faSwyllys 
267430a5e8faSwyllys 	response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
267530a5e8faSwyllys 	    attrlist, numattr);
267630a5e8faSwyllys 	if (response_status == NULL)
267730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
267830a5e8faSwyllys 
267930a5e8faSwyllys 	response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
268030a5e8faSwyllys 	    attrlist, numattr);
268130a5e8faSwyllys 	if (response_reason == NULL)
268230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
268330a5e8faSwyllys 
268430a5e8faSwyllys 	cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
268530a5e8faSwyllys 	    attrlist, numattr);
268630a5e8faSwyllys 	if (cert_status == NULL)
268730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
268899ebb4caSwyllys 
268999ebb4caSwyllys 	/* Read in the response */
269030a5e8faSwyllys 	derbio = BIO_new_mem_buf(response->Data, response->Length);
269199ebb4caSwyllys 	if (!derbio) {
269299ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
269399ebb4caSwyllys 		return (ret);
269499ebb4caSwyllys 	}
269599ebb4caSwyllys 
269699ebb4caSwyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
269799ebb4caSwyllys 	if (resp == NULL) {
269899ebb4caSwyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
269999ebb4caSwyllys 		goto end;
270099ebb4caSwyllys 	}
270199ebb4caSwyllys 
270299ebb4caSwyllys 	/* Check the response status */
270399ebb4caSwyllys 	status = OCSP_response_status(resp);
270430a5e8faSwyllys 	*response_status = status;
270599ebb4caSwyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
270699ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
270799ebb4caSwyllys 		goto end;
270899ebb4caSwyllys 	}
270999ebb4caSwyllys 
271099ebb4caSwyllys #ifdef DEBUG
271199ebb4caSwyllys 	printf("Successfully checked the response file status.\n");
271299ebb4caSwyllys #endif /* DEBUG */
271399ebb4caSwyllys 
271499ebb4caSwyllys 	/* Extract basic response */
271599ebb4caSwyllys 	bs = OCSP_response_get1_basic(resp);
271699ebb4caSwyllys 	if (bs == NULL) {
271799ebb4caSwyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
271899ebb4caSwyllys 		goto end;
271999ebb4caSwyllys 	}
272099ebb4caSwyllys 
272199ebb4caSwyllys #ifdef DEBUG
272299ebb4caSwyllys 	printf("Successfully retrieved the basic response.\n");
272399ebb4caSwyllys #endif /* DEBUG */
272499ebb4caSwyllys 
272599ebb4caSwyllys 	/* Check the basic response signature if required */
272630a5e8faSwyllys 	ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
272730a5e8faSwyllys 	    (void *)&ignore_response_sign, NULL);
272830a5e8faSwyllys 	if (ret != KMF_OK)
272930a5e8faSwyllys 		ret = KMF_OK;
273030a5e8faSwyllys 
273130a5e8faSwyllys 	signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
273230a5e8faSwyllys 	    attrlist, numattr);
273330a5e8faSwyllys 
273430a5e8faSwyllys 	if (ignore_response_sign == B_FALSE) {
273599ebb4caSwyllys 		ret = check_response_signature(handle, bs,
273630a5e8faSwyllys 		    signer_cert, issuer_cert);
273799ebb4caSwyllys 		if (ret != KMF_OK)
273899ebb4caSwyllys 			goto end;
273999ebb4caSwyllys 	}
274099ebb4caSwyllys 
274199ebb4caSwyllys #ifdef DEBUG
274299ebb4caSwyllys 	printf("Successfully verified the response signature.\n");
274399ebb4caSwyllys #endif /* DEBUG */
274499ebb4caSwyllys 
274599ebb4caSwyllys 	/* Create a certid for the certificate in question */
274630a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
274799ebb4caSwyllys 	if (ret != KMF_OK) {
274899ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
274999ebb4caSwyllys 		goto end;
275099ebb4caSwyllys 	}
275199ebb4caSwyllys 
275299ebb4caSwyllys #ifdef DEBUG
275399ebb4caSwyllys 	printf("successfully created a certid for the cert.\n");
275499ebb4caSwyllys #endif /* DEBUG */
275599ebb4caSwyllys 
275699ebb4caSwyllys 	/* Find the index of the single response for the certid */
275799ebb4caSwyllys 	index = OCSP_resp_find(bs, id, -1);
275899ebb4caSwyllys 	if (index < 0) {
275999ebb4caSwyllys 		/* cound not find this certificate in the response */
276099ebb4caSwyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
276199ebb4caSwyllys 		goto end;
276299ebb4caSwyllys 	}
276399ebb4caSwyllys 
276499ebb4caSwyllys #ifdef DEBUG
276599ebb4caSwyllys 	printf("Successfully found the single response index for the cert.\n");
276699ebb4caSwyllys #endif /* DEBUG */
276799ebb4caSwyllys 
276899ebb4caSwyllys 	/* Retrieve the single response and get the cert status */
276999ebb4caSwyllys 	single = OCSP_resp_get0(bs, index);
277099ebb4caSwyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
277199ebb4caSwyllys 	    &nextupd);
277299ebb4caSwyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
277330a5e8faSwyllys 		*cert_status = OCSP_GOOD;
277499ebb4caSwyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
277530a5e8faSwyllys 		*cert_status = OCSP_UNKNOWN;
277699ebb4caSwyllys 	} else { /* revoked */
277730a5e8faSwyllys 		*cert_status = OCSP_REVOKED;
277830a5e8faSwyllys 		*response_reason = reason;
277999ebb4caSwyllys 	}
278099ebb4caSwyllys 	ret = KMF_OK;
278199ebb4caSwyllys 
278230a5e8faSwyllys 	/* resp. time is optional, so we don't care about the return code. */
278330a5e8faSwyllys 	(void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
278430a5e8faSwyllys 	    (void *)&response_lifetime, NULL);
278530a5e8faSwyllys 
278699ebb4caSwyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
278730a5e8faSwyllys 	    response_lifetime)) {
278899ebb4caSwyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
278999ebb4caSwyllys 		goto end;
279099ebb4caSwyllys 	}
279199ebb4caSwyllys 
279299ebb4caSwyllys #ifdef DEBUG
279399ebb4caSwyllys 	printf("Successfully verify the time.\n");
279499ebb4caSwyllys #endif /* DEBUG */
279599ebb4caSwyllys 
279699ebb4caSwyllys end:
279799ebb4caSwyllys 	if (derbio != NULL)
279899ebb4caSwyllys 		(void) BIO_free(derbio);
279999ebb4caSwyllys 
280099ebb4caSwyllys 	if (resp != NULL)
280199ebb4caSwyllys 		OCSP_RESPONSE_free(resp);
280299ebb4caSwyllys 
280399ebb4caSwyllys 	if (bs != NULL)
280499ebb4caSwyllys 		OCSP_BASICRESP_free(bs);
280599ebb4caSwyllys 
280699ebb4caSwyllys 	if (id != NULL)
280799ebb4caSwyllys 		OCSP_CERTID_free(id);
280899ebb4caSwyllys 
280999ebb4caSwyllys 	return (ret);
281099ebb4caSwyllys }
281199ebb4caSwyllys 
281299ebb4caSwyllys static KMF_RETURN
281399ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path,
281499ebb4caSwyllys 	KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
281599ebb4caSwyllys {
281699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
281730a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
281899ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
281999ebb4caSwyllys 
282099ebb4caSwyllys 	if (keyclass == KMF_ASYM_PRI ||
282199ebb4caSwyllys 	    keyclass == KMF_ASYM_PUB) {
282299ebb4caSwyllys 		pkey = openssl_load_key(handle, path);
282399ebb4caSwyllys 		if (pkey == NULL) {
282499ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
282599ebb4caSwyllys 		}
282699ebb4caSwyllys 		if (key != NULL) {
282799ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA)
282899ebb4caSwyllys 				key->keyalg = KMF_RSA;
282999ebb4caSwyllys 			else if (pkey->type == EVP_PKEY_DSA)
283099ebb4caSwyllys 				key->keyalg = KMF_DSA;
283199ebb4caSwyllys 
283299ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
283399ebb4caSwyllys 			key->keyclass = keyclass;
283499ebb4caSwyllys 			key->keyp = (void *)pkey;
283599ebb4caSwyllys 			key->israw = FALSE;
28365b3e1433Swyllys 			if (path != NULL &&
28375b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
28385b3e1433Swyllys 				EVP_PKEY_free(pkey);
28395b3e1433Swyllys 				return (KMF_ERR_MEMORY);
28405b3e1433Swyllys 			}
284199ebb4caSwyllys 		} else {
284299ebb4caSwyllys 			EVP_PKEY_free(pkey);
284399ebb4caSwyllys 			pkey = NULL;
284499ebb4caSwyllys 		}
284599ebb4caSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
284699ebb4caSwyllys 		KMF_ENCODE_FORMAT fmt;
284799ebb4caSwyllys 		/*
284899ebb4caSwyllys 		 * If the file is a recognized format,
284999ebb4caSwyllys 		 * then it is NOT a symmetric key.
285099ebb4caSwyllys 		 */
285130a5e8faSwyllys 		rv = kmf_get_file_format(path, &fmt);
285299ebb4caSwyllys 		if (rv == KMF_OK || fmt != 0) {
285399ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
285499ebb4caSwyllys 		} else if (rv == KMF_ERR_ENCODING) {
285599ebb4caSwyllys 			/*
285699ebb4caSwyllys 			 * If we don't know the encoding,
285799ebb4caSwyllys 			 * it is probably  a symmetric key.
285899ebb4caSwyllys 			 */
285999ebb4caSwyllys 			rv = KMF_OK;
286030a5e8faSwyllys 		} else if (rv == KMF_ERR_OPEN_FILE) {
286130a5e8faSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
286299ebb4caSwyllys 		}
286399ebb4caSwyllys 
286499ebb4caSwyllys 		if (key != NULL) {
286599ebb4caSwyllys 			KMF_DATA keyvalue;
286699ebb4caSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
286799ebb4caSwyllys 			if (rkey == NULL) {
286899ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
286999ebb4caSwyllys 				goto out;
287099ebb4caSwyllys 			}
287199ebb4caSwyllys 
287299ebb4caSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
287330a5e8faSwyllys 			rv = kmf_read_input_file(handle, path, &keyvalue);
287499ebb4caSwyllys 			if (rv != KMF_OK)
287599ebb4caSwyllys 				goto out;
287699ebb4caSwyllys 
287799ebb4caSwyllys 			rkey->keydata.len = keyvalue.Length;
287899ebb4caSwyllys 			rkey->keydata.val = keyvalue.Data;
287999ebb4caSwyllys 
288099ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
288199ebb4caSwyllys 			key->keyclass = keyclass;
288299ebb4caSwyllys 			key->israw = TRUE;
288399ebb4caSwyllys 			key->keyp = (void *)rkey;
28845b3e1433Swyllys 			if (path != NULL &&
28855b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
28865b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
28875b3e1433Swyllys 			}
288899ebb4caSwyllys 		}
288999ebb4caSwyllys 	}
289099ebb4caSwyllys out:
289199ebb4caSwyllys 	if (rv != KMF_OK) {
289299ebb4caSwyllys 		if (rkey != NULL) {
289330a5e8faSwyllys 			kmf_free_raw_sym_key(rkey);
289499ebb4caSwyllys 		}
289599ebb4caSwyllys 		if (pkey != NULL)
289699ebb4caSwyllys 			EVP_PKEY_free(pkey);
289799ebb4caSwyllys 
289899ebb4caSwyllys 		if (key != NULL) {
289999ebb4caSwyllys 			key->keyalg = KMF_KEYALG_NONE;
290099ebb4caSwyllys 			key->keyclass = KMF_KEYCLASS_NONE;
290199ebb4caSwyllys 			key->keyp = NULL;
290299ebb4caSwyllys 		}
290399ebb4caSwyllys 	}
290499ebb4caSwyllys 
290599ebb4caSwyllys 	return (rv);
290699ebb4caSwyllys }
290799ebb4caSwyllys 
290899ebb4caSwyllys KMF_RETURN
290930a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle,
291030a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
291199ebb4caSwyllys {
291299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
291399ebb4caSwyllys 	char *fullpath = NULL;
2914f482c776Swyllys 	uint32_t maxkeys;
291530a5e8faSwyllys 	KMF_KEY_HANDLE *key;
291630a5e8faSwyllys 	uint32_t *numkeys;
291730a5e8faSwyllys 	KMF_KEY_CLASS keyclass;
291830a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
291930a5e8faSwyllys 	char *dirpath;
292030a5e8faSwyllys 	char *keyfile;
292199ebb4caSwyllys 
292230a5e8faSwyllys 	if (handle == NULL)
292399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
292499ebb4caSwyllys 
292530a5e8faSwyllys 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
292630a5e8faSwyllys 	if (numkeys == NULL)
292730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
292830a5e8faSwyllys 
292930a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
293030a5e8faSwyllys 	    (void *)&keyclass, NULL);
293130a5e8faSwyllys 	if (rv != KMF_OK)
293230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
293330a5e8faSwyllys 
293430a5e8faSwyllys 	if (keyclass != KMF_ASYM_PUB &&
293530a5e8faSwyllys 	    keyclass != KMF_ASYM_PRI &&
293630a5e8faSwyllys 	    keyclass != KMF_SYMMETRIC)
293799ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
293899ebb4caSwyllys 
293930a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
294030a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
294130a5e8faSwyllys 
294230a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
294399ebb4caSwyllys 
294499ebb4caSwyllys 	if (fullpath == NULL)
294599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
294699ebb4caSwyllys 
2947f482c776Swyllys 	maxkeys = *numkeys;
2948f482c776Swyllys 	if (maxkeys == 0)
2949f482c776Swyllys 		maxkeys = 0xFFFFFFFF;
295099ebb4caSwyllys 	*numkeys = 0;
295199ebb4caSwyllys 
295230a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
295330a5e8faSwyllys 	/* it is okay to have "keys" contains NULL */
295430a5e8faSwyllys 
295530a5e8faSwyllys 	/*
295630a5e8faSwyllys 	 * The caller may want a list of the raw key data as well.
295730a5e8faSwyllys 	 * Useful for importing keys from a file into other keystores.
295830a5e8faSwyllys 	 */
295930a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
296030a5e8faSwyllys 
296199ebb4caSwyllys 	if (isdir(fullpath)) {
296299ebb4caSwyllys 		DIR *dirp;
296399ebb4caSwyllys 		struct dirent *dp;
296499ebb4caSwyllys 		int n = 0;
296599ebb4caSwyllys 
296699ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
296799ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
296899ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
296999ebb4caSwyllys 		}
297099ebb4caSwyllys 		rewinddir(dirp);
2971f482c776Swyllys 		while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
297299ebb4caSwyllys 			if (strcmp(dp->d_name, ".") &&
297399ebb4caSwyllys 			    strcmp(dp->d_name, "..")) {
297499ebb4caSwyllys 				char *fname;
297599ebb4caSwyllys 
297699ebb4caSwyllys 				fname = get_fullpath(fullpath,
297799ebb4caSwyllys 				    (char *)&dp->d_name);
297899ebb4caSwyllys 
297999ebb4caSwyllys 				rv = fetch_key(handle, fname,
298030a5e8faSwyllys 				    keyclass, key ? &key[n] : NULL);
298199ebb4caSwyllys 
298230a5e8faSwyllys 				if (rv == KMF_OK) {
298330a5e8faSwyllys 					if (key != NULL && rawkey != NULL)
298430a5e8faSwyllys 						rv = convertToRawKey(
298530a5e8faSwyllys 						    key[n].keyp, &rawkey[n]);
298699ebb4caSwyllys 					n++;
298730a5e8faSwyllys 				}
298899ebb4caSwyllys 
298999ebb4caSwyllys 				if (rv != KMF_OK || key == NULL)
299099ebb4caSwyllys 					free(fname);
299199ebb4caSwyllys 			}
299299ebb4caSwyllys 		}
299399ebb4caSwyllys 		(void) closedir(dirp);
299499ebb4caSwyllys 		free(fullpath);
299599ebb4caSwyllys 		(*numkeys) = n;
299699ebb4caSwyllys 	} else {
299730a5e8faSwyllys 		rv = fetch_key(handle, fullpath, keyclass, key);
299899ebb4caSwyllys 		if (rv == KMF_OK)
299999ebb4caSwyllys 			(*numkeys) = 1;
300099ebb4caSwyllys 
300199ebb4caSwyllys 		if (rv != KMF_OK || key == NULL)
300299ebb4caSwyllys 			free(fullpath);
300330a5e8faSwyllys 
300430a5e8faSwyllys 		if (rv == KMF_OK && key != NULL && rawkey != NULL) {
300530a5e8faSwyllys 			rv = convertToRawKey(key->keyp, rawkey);
300630a5e8faSwyllys 		}
300799ebb4caSwyllys 	}
300899ebb4caSwyllys 
3009f482c776Swyllys 	if (rv == KMF_OK && (*numkeys) == 0)
301099ebb4caSwyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
301173cc0e02Swyllys 	else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
301273cc0e02Swyllys 		rv = KMF_OK;
301399ebb4caSwyllys 
301499ebb4caSwyllys 	return (rv);
301599ebb4caSwyllys }
301699ebb4caSwyllys 
301799ebb4caSwyllys #define	HANDLE_PK12_ERROR { \
301899ebb4caSwyllys 	SET_ERROR(kmfh, ERR_get_error()); \
301999ebb4caSwyllys 	rv = KMF_ERR_ENCODING; \
302099ebb4caSwyllys 	goto out; \
302199ebb4caSwyllys }
302299ebb4caSwyllys 
30235b3e1433Swyllys static int
30245b3e1433Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
302599ebb4caSwyllys {
30265b3e1433Swyllys 	if (xcert != NULL && xcert->aux != NULL &&
30275b3e1433Swyllys 	    xcert->aux->alias != NULL) {
30285b3e1433Swyllys 		if (PKCS12_add_friendlyname_asc(bag,
30295b3e1433Swyllys 		    (const char *)xcert->aux->alias->data,
30305b3e1433Swyllys 		    xcert->aux->alias->length) == 0)
30315b3e1433Swyllys 			return (0);
30325b3e1433Swyllys 	}
30335b3e1433Swyllys 	return (1);
30345b3e1433Swyllys }
30355b3e1433Swyllys 
30365b3e1433Swyllys static PKCS7 *
30375b3e1433Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
30385b3e1433Swyllys 	uchar_t *keyid, unsigned int keyidlen)
30395b3e1433Swyllys {
304099ebb4caSwyllys 	PKCS12_SAFEBAG *bag = NULL;
304199ebb4caSwyllys 	PKCS7 *cert_authsafe = NULL;
30425b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack;
304399ebb4caSwyllys 
304499ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
304599ebb4caSwyllys 	if (bag_stack == NULL)
30465b3e1433Swyllys 		return (NULL);
304799ebb4caSwyllys 
304899ebb4caSwyllys 	/* Convert cert from X509 struct to PKCS#12 bag */
304999ebb4caSwyllys 	bag = PKCS12_x5092certbag(sslcert);
305099ebb4caSwyllys 	if (bag == NULL) {
30515b3e1433Swyllys 		goto out;
305299ebb4caSwyllys 	}
305399ebb4caSwyllys 
305499ebb4caSwyllys 	/* Add the key id to the certificate bag. */
30555b3e1433Swyllys 	if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
30565b3e1433Swyllys 		goto out;
305799ebb4caSwyllys 	}
305899ebb4caSwyllys 
30595b3e1433Swyllys 	if (!add_alias_to_bag(bag, sslcert))
30605b3e1433Swyllys 		goto out;
30615b3e1433Swyllys 
306299ebb4caSwyllys 	/* Pile it on the bag_stack. */
306399ebb4caSwyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
30645b3e1433Swyllys 		goto out;
306599ebb4caSwyllys 	}
306699ebb4caSwyllys 	/* Turn bag_stack of certs into encrypted authsafe. */
306799ebb4caSwyllys 	cert_authsafe = PKCS12_pack_p7encdata(
306899ebb4caSwyllys 	    NID_pbe_WithSHA1And40BitRC2_CBC,
306934acef67Swyllys 	    cred->cred, cred->credlen, NULL, 0,
307034acef67Swyllys 	    PKCS12_DEFAULT_ITER, bag_stack);
307199ebb4caSwyllys 
30725b3e1433Swyllys out:
30735b3e1433Swyllys 	if (bag_stack != NULL)
307499ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
307599ebb4caSwyllys 
30765b3e1433Swyllys 	return (cert_authsafe);
307799ebb4caSwyllys }
30785b3e1433Swyllys 
30795b3e1433Swyllys static PKCS7 *
30805b3e1433Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
30815b3e1433Swyllys 	uchar_t *keyid,  unsigned int keyidlen,
30825b3e1433Swyllys 	char *label, int label_len)
30835b3e1433Swyllys {
30845b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
30855b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
30865b3e1433Swyllys 	PKCS12_SAFEBAG *bag = NULL;
30875b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
30885b3e1433Swyllys 
308999ebb4caSwyllys 	p8 = EVP_PKEY2PKCS8(pkey);
309099ebb4caSwyllys 	if (p8 == NULL) {
30915b3e1433Swyllys 		return (NULL);
309299ebb4caSwyllys 	}
309399ebb4caSwyllys 	/* Put the shrouded key into a PKCS#12 bag. */
309499ebb4caSwyllys 	bag = PKCS12_MAKE_SHKEYBAG(
309599ebb4caSwyllys 	    NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
309699ebb4caSwyllys 	    cred->cred, cred->credlen,
309799ebb4caSwyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, p8);
309899ebb4caSwyllys 
309999ebb4caSwyllys 	/* Clean up the PKCS#8 shrouded key, don't need it now. */
310099ebb4caSwyllys 	PKCS8_PRIV_KEY_INFO_free(p8);
310199ebb4caSwyllys 	p8 = NULL;
310299ebb4caSwyllys 
310399ebb4caSwyllys 	if (bag == NULL) {
31045b3e1433Swyllys 		return (NULL);
310599ebb4caSwyllys 	}
31065b3e1433Swyllys 	if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
31075b3e1433Swyllys 		goto out;
31085b3e1433Swyllys 	if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
31095b3e1433Swyllys 		goto out;
31105b3e1433Swyllys 
311199ebb4caSwyllys 	/* Start a PKCS#12 safebag container for the private key. */
311299ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
31135b3e1433Swyllys 	if (bag_stack == NULL)
31145b3e1433Swyllys 		goto out;
311599ebb4caSwyllys 
311699ebb4caSwyllys 	/* Pile on the private key on the bag_stack. */
31175b3e1433Swyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
31185b3e1433Swyllys 		goto out;
31195b3e1433Swyllys 
312099ebb4caSwyllys 	key_authsafe = PKCS12_pack_p7data(bag_stack);
312199ebb4caSwyllys 
31225b3e1433Swyllys out:
31235b3e1433Swyllys 	if (bag_stack != NULL)
312499ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
312599ebb4caSwyllys 	bag_stack = NULL;
31265b3e1433Swyllys 	return (key_authsafe);
312799ebb4caSwyllys }
312899ebb4caSwyllys 
312999ebb4caSwyllys static EVP_PKEY *
313099ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
313199ebb4caSwyllys {
313299ebb4caSwyllys 	RSA		*rsa = NULL;
313399ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
313499ebb4caSwyllys 
313599ebb4caSwyllys 	if ((rsa = RSA_new()) == NULL)
313699ebb4caSwyllys 		return (NULL);
313799ebb4caSwyllys 
313899ebb4caSwyllys 	if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL)
313999ebb4caSwyllys 		return (NULL);
314099ebb4caSwyllys 
314199ebb4caSwyllys 	if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) ==
314299ebb4caSwyllys 	    NULL)
314399ebb4caSwyllys 		return (NULL);
314499ebb4caSwyllys 
314599ebb4caSwyllys 	if (key->priexp.val != NULL)
314699ebb4caSwyllys 		if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len,
314799ebb4caSwyllys 		    rsa->d)) == NULL)
314899ebb4caSwyllys 			return (NULL);
314999ebb4caSwyllys 
315099ebb4caSwyllys 	if (key->prime1.val != NULL)
315199ebb4caSwyllys 		if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len,
315299ebb4caSwyllys 		    rsa->p)) == NULL)
315399ebb4caSwyllys 			return (NULL);
315499ebb4caSwyllys 
315599ebb4caSwyllys 	if (key->prime2.val != NULL)
315699ebb4caSwyllys 		if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len,
315799ebb4caSwyllys 		    rsa->q)) == NULL)
315899ebb4caSwyllys 			return (NULL);
315999ebb4caSwyllys 
316099ebb4caSwyllys 	if (key->exp1.val != NULL)
316199ebb4caSwyllys 		if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len,
316299ebb4caSwyllys 		    rsa->dmp1)) == NULL)
316399ebb4caSwyllys 			return (NULL);
316499ebb4caSwyllys 
316599ebb4caSwyllys 	if (key->exp2.val != NULL)
316699ebb4caSwyllys 		if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len,
316799ebb4caSwyllys 		    rsa->dmq1)) == NULL)
316899ebb4caSwyllys 			return (NULL);
316999ebb4caSwyllys 
317099ebb4caSwyllys 	if (key->coef.val != NULL)
317199ebb4caSwyllys 		if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len,
317299ebb4caSwyllys 		    rsa->iqmp)) == NULL)
317399ebb4caSwyllys 			return (NULL);
317499ebb4caSwyllys 
317599ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
317699ebb4caSwyllys 		return (NULL);
317799ebb4caSwyllys 
317899ebb4caSwyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
317999ebb4caSwyllys 
318099ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
318199ebb4caSwyllys 	RSA_free(rsa);
318299ebb4caSwyllys 
318399ebb4caSwyllys 	return (newkey);
318499ebb4caSwyllys }
318599ebb4caSwyllys 
318699ebb4caSwyllys static EVP_PKEY *
318799ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
318899ebb4caSwyllys {
318999ebb4caSwyllys 	DSA		*dsa = NULL;
319099ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
319199ebb4caSwyllys 
319299ebb4caSwyllys 	if ((dsa = DSA_new()) == NULL)
319399ebb4caSwyllys 		return (NULL);
319499ebb4caSwyllys 
319599ebb4caSwyllys 	if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len,
319699ebb4caSwyllys 	    dsa->p)) == NULL)
319799ebb4caSwyllys 		return (NULL);
319899ebb4caSwyllys 
319999ebb4caSwyllys 	if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len,
320099ebb4caSwyllys 	    dsa->q)) == NULL)
320199ebb4caSwyllys 		return (NULL);
320299ebb4caSwyllys 
320399ebb4caSwyllys 	if ((dsa->g = BN_bin2bn(key->base.val, key->base.len,
320499ebb4caSwyllys 	    dsa->g)) == NULL)
320599ebb4caSwyllys 		return (NULL);
320699ebb4caSwyllys 
320799ebb4caSwyllys 	if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len,
320899ebb4caSwyllys 	    dsa->priv_key)) == NULL)
320999ebb4caSwyllys 		return (NULL);
321099ebb4caSwyllys 
321130a5e8faSwyllys 	if (key->pubvalue.val != NULL) {
321230a5e8faSwyllys 		if ((dsa->pub_key = BN_bin2bn(key->pubvalue.val,
321330a5e8faSwyllys 		    key->pubvalue.len, dsa->pub_key)) == NULL)
321430a5e8faSwyllys 			return (NULL);
321530a5e8faSwyllys 	}
321630a5e8faSwyllys 
321799ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
321899ebb4caSwyllys 		return (NULL);
321999ebb4caSwyllys 
322099ebb4caSwyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
322199ebb4caSwyllys 
322299ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
322399ebb4caSwyllys 	DSA_free(dsa);
322499ebb4caSwyllys 	return (newkey);
322599ebb4caSwyllys }
322699ebb4caSwyllys 
32275b3e1433Swyllys static EVP_PKEY *
32285b3e1433Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key)
32295b3e1433Swyllys {
32305b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
32315b3e1433Swyllys 	KMF_RAW_KEY_DATA *rawkey;
32325b3e1433Swyllys 	ASN1_TYPE *attr = NULL;
32335b3e1433Swyllys 	KMF_RETURN ret;
32345b3e1433Swyllys 
32355b3e1433Swyllys 	if (key == NULL || !key->israw)
32365b3e1433Swyllys 		return (NULL);
32375b3e1433Swyllys 
32385b3e1433Swyllys 	rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
32395b3e1433Swyllys 	if (rawkey->keytype == KMF_RSA) {
32405b3e1433Swyllys 		pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
32415b3e1433Swyllys 	} else if (rawkey->keytype == KMF_DSA) {
32425b3e1433Swyllys 		pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
3243e65e5c2dSWyllys Ingersoll 	} else if (rawkey->keytype == KMF_ECDSA) {
3244e65e5c2dSWyllys Ingersoll 		/*
3245e65e5c2dSWyllys Ingersoll 		 * OpenSSL in Solaris does not support EC for
3246e65e5c2dSWyllys Ingersoll 		 * legal reasons
3247e65e5c2dSWyllys Ingersoll 		 */
3248e65e5c2dSWyllys Ingersoll 		return (NULL);
32495b3e1433Swyllys 	} else {
32505b3e1433Swyllys 		/* wrong kind of key */
32515b3e1433Swyllys 		return (NULL);
32525b3e1433Swyllys 	}
32535b3e1433Swyllys 
32545b3e1433Swyllys 	if (rawkey->label != NULL) {
32555b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
32565b3e1433Swyllys 			EVP_PKEY_free(pkey);
32575b3e1433Swyllys 			return (NULL);
32585b3e1433Swyllys 		}
32595b3e1433Swyllys 		attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
32605b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
32615b3e1433Swyllys 		    strlen(rawkey->label));
32625b3e1433Swyllys 		attr->type = V_ASN1_BMPSTRING;
32635b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.bmpstring;
32645b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
32655b3e1433Swyllys 		if (ret != KMF_OK) {
32665b3e1433Swyllys 			EVP_PKEY_free(pkey);
32675b3e1433Swyllys 			ASN1_TYPE_free(attr);
32685b3e1433Swyllys 			return (NULL);
32695b3e1433Swyllys 		}
32705b3e1433Swyllys 	}
32715b3e1433Swyllys 	if (rawkey->id.Data != NULL) {
32725b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
32735b3e1433Swyllys 			EVP_PKEY_free(pkey);
32745b3e1433Swyllys 			return (NULL);
32755b3e1433Swyllys 		}
32765b3e1433Swyllys 		attr->value.octet_string =
32775b3e1433Swyllys 		    ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
32785b3e1433Swyllys 		attr->type = V_ASN1_OCTET_STRING;
32795b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.octet_string,
32805b3e1433Swyllys 		    rawkey->id.Data, rawkey->id.Length);
32815b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.octet_string;
32825b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
32835b3e1433Swyllys 		if (ret != KMF_OK) {
32845b3e1433Swyllys 			EVP_PKEY_free(pkey);
32855b3e1433Swyllys 			ASN1_TYPE_free(attr);
32865b3e1433Swyllys 			return (NULL);
32875b3e1433Swyllys 		}
32885b3e1433Swyllys 	}
32895b3e1433Swyllys 	return (pkey);
32905b3e1433Swyllys }
32915b3e1433Swyllys 
32925b3e1433Swyllys /*
32935b3e1433Swyllys  * Search a list of private keys to find one that goes with the certificate.
32945b3e1433Swyllys  */
32955b3e1433Swyllys static EVP_PKEY *
32965b3e1433Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
32975b3e1433Swyllys {
32985b3e1433Swyllys 	int i;
32995b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
33005b3e1433Swyllys 
33015b3e1433Swyllys 	if (numkeys == 0 || keylist == NULL || xcert == NULL)
33025b3e1433Swyllys 		return (NULL);
33035b3e1433Swyllys 	for (i = 0; i < numkeys; i++) {
33045b3e1433Swyllys 		if (keylist[i].israw)
33055b3e1433Swyllys 			pkey = raw_key_to_pkey(&keylist[i]);
33065b3e1433Swyllys 		else
33075b3e1433Swyllys 			pkey = (EVP_PKEY *)keylist[i].keyp;
33085b3e1433Swyllys 		if (pkey != NULL) {
33095b3e1433Swyllys 			if (X509_check_private_key(xcert, pkey)) {
33105b3e1433Swyllys 				return (pkey);
33115b3e1433Swyllys 			} else {
33125b3e1433Swyllys 				EVP_PKEY_free(pkey);
33135b3e1433Swyllys 				pkey = NULL;
33145b3e1433Swyllys 			}
33155b3e1433Swyllys 		}
33165b3e1433Swyllys 	}
33175b3e1433Swyllys 	return (pkey);
33185b3e1433Swyllys }
33195b3e1433Swyllys 
332099ebb4caSwyllys static KMF_RETURN
33215b3e1433Swyllys local_export_pk12(KMF_HANDLE_T handle,
332299ebb4caSwyllys 	KMF_CREDENTIAL *cred,
332399ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
332499ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
332599ebb4caSwyllys 	char *filename)
332699ebb4caSwyllys {
332799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
332899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
332999ebb4caSwyllys 	BIO *bio = NULL;
33305b3e1433Swyllys 	PKCS7 *cert_authsafe = NULL;
33315b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
33325b3e1433Swyllys 	STACK_OF(PKCS7) *authsafe_stack = NULL;
33335b3e1433Swyllys 	PKCS12 *p12_elem = NULL;
333499ebb4caSwyllys 	int i;
333599ebb4caSwyllys 
33365b3e1433Swyllys 	if (numcerts == 0 && numkeys == 0)
33375b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
33385b3e1433Swyllys 
333999ebb4caSwyllys 	/*
334099ebb4caSwyllys 	 * Open the output file.
334199ebb4caSwyllys 	 */
334299ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
334399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
334499ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
334599ebb4caSwyllys 		goto cleanup;
334699ebb4caSwyllys 	}
334799ebb4caSwyllys 
33485b3e1433Swyllys 	/* Start a PKCS#7 stack. */
33495b3e1433Swyllys 	authsafe_stack = sk_PKCS7_new_null();
33505b3e1433Swyllys 	if (authsafe_stack == NULL) {
33515b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
33525b3e1433Swyllys 		goto cleanup;
33535b3e1433Swyllys 	}
33545b3e1433Swyllys 	if (numcerts > 0) {
335599ebb4caSwyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
335699ebb4caSwyllys 			const uchar_t *p = certlist[i].certificate.Data;
335799ebb4caSwyllys 			long len = certlist[i].certificate.Length;
33585b3e1433Swyllys 			X509 *xcert = NULL;
33595b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
33605b3e1433Swyllys 			unsigned char keyid[EVP_MAX_MD_SIZE];
33615b3e1433Swyllys 			unsigned int keyidlen = 0;
336299ebb4caSwyllys 
336399ebb4caSwyllys 			xcert = d2i_X509(NULL, &p, len);
336499ebb4caSwyllys 			if (xcert == NULL) {
336599ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
336699ebb4caSwyllys 				rv = KMF_ERR_ENCODING;
336799ebb4caSwyllys 			}
33685b3e1433Swyllys 			if (certlist[i].kmf_private.label != NULL) {
33695b3e1433Swyllys 				/* Set alias attribute */
33705b3e1433Swyllys 				(void) X509_alias_set1(xcert,
33715b3e1433Swyllys 				    (uchar_t *)certlist[i].kmf_private.label,
33725b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label));
33735b3e1433Swyllys 			}
33745b3e1433Swyllys 			/* Check if there is a key corresponding to this cert */
33755b3e1433Swyllys 			pkey = find_matching_key(xcert, numkeys, keylist);
33765b3e1433Swyllys 
33775b3e1433Swyllys 			/*
33785b3e1433Swyllys 			 * If key is found, get fingerprint and create a
33795b3e1433Swyllys 			 * safebag.
33805b3e1433Swyllys 			 */
33815b3e1433Swyllys 			if (pkey != NULL) {
33825b3e1433Swyllys 				(void) X509_digest(xcert, EVP_sha1(),
33835b3e1433Swyllys 				    keyid, &keyidlen);
33845b3e1433Swyllys 				key_authsafe = add_key_to_safe(pkey, cred,
33855b3e1433Swyllys 				    keyid, keyidlen,
33865b3e1433Swyllys 				    certlist[i].kmf_private.label,
33875b3e1433Swyllys 				    (certlist[i].kmf_private.label ?
33885b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label) : 0));
33895b3e1433Swyllys 
33905b3e1433Swyllys 				if (key_authsafe == NULL) {
33915b3e1433Swyllys 					X509_free(xcert);
33925b3e1433Swyllys 					EVP_PKEY_free(pkey);
33935b3e1433Swyllys 					goto cleanup;
33945b3e1433Swyllys 				}
33955b3e1433Swyllys 				/* Put the key safe into the Auth Safe */
33965b3e1433Swyllys 				if (!sk_PKCS7_push(authsafe_stack,
33975b3e1433Swyllys 				    key_authsafe)) {
33985b3e1433Swyllys 					X509_free(xcert);
33995b3e1433Swyllys 					EVP_PKEY_free(pkey);
34005b3e1433Swyllys 					goto cleanup;
34015b3e1433Swyllys 				}
34025b3e1433Swyllys 			}
34035b3e1433Swyllys 
34045b3e1433Swyllys 			/* create a certificate safebag */
34055b3e1433Swyllys 			cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
34065b3e1433Swyllys 			    keyidlen);
34075b3e1433Swyllys 			if (cert_authsafe == NULL) {
34085b3e1433Swyllys 				X509_free(xcert);
34095b3e1433Swyllys 				EVP_PKEY_free(pkey);
34105b3e1433Swyllys 				goto cleanup;
34115b3e1433Swyllys 			}
34125b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
34135b3e1433Swyllys 				X509_free(xcert);
34145b3e1433Swyllys 				EVP_PKEY_free(pkey);
34155b3e1433Swyllys 				goto cleanup;
34165b3e1433Swyllys 			}
34175b3e1433Swyllys 
341899ebb4caSwyllys 			X509_free(xcert);
341999ebb4caSwyllys 			if (pkey)
342099ebb4caSwyllys 				EVP_PKEY_free(pkey);
342199ebb4caSwyllys 		}
34225b3e1433Swyllys 	} else if (numcerts == 0 && numkeys > 0) {
34235b3e1433Swyllys 		/*
34245b3e1433Swyllys 		 * If only adding keys to the file.
34255b3e1433Swyllys 		 */
34265b3e1433Swyllys 		for (i = 0; i < numkeys; i++) {
34275b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
34285b3e1433Swyllys 
34295b3e1433Swyllys 			if (keylist[i].israw)
34305b3e1433Swyllys 				pkey = raw_key_to_pkey(&keylist[i]);
34315b3e1433Swyllys 			else
34325b3e1433Swyllys 				pkey = (EVP_PKEY *)keylist[i].keyp;
34335b3e1433Swyllys 
34345b3e1433Swyllys 			if (pkey == NULL)
34355b3e1433Swyllys 				continue;
34365b3e1433Swyllys 
34375b3e1433Swyllys 			key_authsafe = add_key_to_safe(pkey, cred,
34385b3e1433Swyllys 			    NULL, 0, NULL, 0);
34395b3e1433Swyllys 
34405b3e1433Swyllys 			if (key_authsafe == NULL) {
34415b3e1433Swyllys 				EVP_PKEY_free(pkey);
34425b3e1433Swyllys 				goto cleanup;
34435b3e1433Swyllys 			}
34445b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
34455b3e1433Swyllys 				EVP_PKEY_free(pkey);
34465b3e1433Swyllys 				goto cleanup;
34475b3e1433Swyllys 			}
34485b3e1433Swyllys 		}
34495b3e1433Swyllys 	}
34505b3e1433Swyllys 	p12_elem = PKCS12_init(NID_pkcs7_data);
34515b3e1433Swyllys 	if (p12_elem == NULL) {
34525b3e1433Swyllys 		goto cleanup;
345399ebb4caSwyllys 	}
345499ebb4caSwyllys 
34555b3e1433Swyllys 	/* Put the PKCS#7 stack into the PKCS#12 element. */
34565b3e1433Swyllys 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
34575b3e1433Swyllys 		goto cleanup;
34585b3e1433Swyllys 	}
34595b3e1433Swyllys 
34605b3e1433Swyllys 	/* Set the integrity MAC on the PKCS#12 element. */
34615b3e1433Swyllys 	if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
34625b3e1433Swyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
34635b3e1433Swyllys 		goto cleanup;
34645b3e1433Swyllys 	}
34655b3e1433Swyllys 
34665b3e1433Swyllys 	/* Write the PKCS#12 element to the export file. */
34675b3e1433Swyllys 	if (!i2d_PKCS12_bio(bio, p12_elem)) {
34685b3e1433Swyllys 		goto cleanup;
34695b3e1433Swyllys 	}
34705b3e1433Swyllys 	PKCS12_free(p12_elem);
34715b3e1433Swyllys 
347299ebb4caSwyllys cleanup:
34735b3e1433Swyllys 	/* Clear away the PKCS#7 stack, we're done with it. */
34745b3e1433Swyllys 	if (authsafe_stack)
34755b3e1433Swyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
347699ebb4caSwyllys 
347799ebb4caSwyllys 	if (bio != NULL)
347899ebb4caSwyllys 		(void) BIO_free_all(bio);
347999ebb4caSwyllys 
348099ebb4caSwyllys 	return (rv);
348199ebb4caSwyllys }
348299ebb4caSwyllys 
348399ebb4caSwyllys KMF_RETURN
348430a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
348530a5e8faSwyllys     KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
348630a5e8faSwyllys     KMF_CREDENTIAL *p12cred, char *filename)
348730a5e8faSwyllys {
348830a5e8faSwyllys 	KMF_RETURN rv;
348930a5e8faSwyllys 
349030a5e8faSwyllys 	if (certlist == NULL && keylist == NULL)
349130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
349230a5e8faSwyllys 
34935b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, numcerts, certlist,
349430a5e8faSwyllys 	    numkeys, keylist, filename);
349530a5e8faSwyllys 
349630a5e8faSwyllys 	return (rv);
349730a5e8faSwyllys }
349830a5e8faSwyllys 
349930a5e8faSwyllys KMF_RETURN
350030a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
350199ebb4caSwyllys {
350299ebb4caSwyllys 	KMF_RETURN rv;
350399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
350499ebb4caSwyllys 	char *fullpath = NULL;
350530a5e8faSwyllys 	char *dirpath = NULL;
350630a5e8faSwyllys 	char *certfile = NULL;
350730a5e8faSwyllys 	char *keyfile = NULL;
350830a5e8faSwyllys 	char *filename = NULL;
350930a5e8faSwyllys 	KMF_CREDENTIAL *p12cred = NULL;
35105b3e1433Swyllys 	KMF_X509_DER_CERT certdata;
35115b3e1433Swyllys 	KMF_KEY_HANDLE key;
35125b3e1433Swyllys 	int gotkey = 0;
35135b3e1433Swyllys 	int gotcert = 0;
351430a5e8faSwyllys 
351530a5e8faSwyllys 	if (handle == NULL)
351630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
351799ebb4caSwyllys 
351899ebb4caSwyllys 	/*
351999ebb4caSwyllys 	 *  First, find the certificate.
352099ebb4caSwyllys 	 */
352130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
352230a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
352330a5e8faSwyllys 	if (certfile != NULL) {
352430a5e8faSwyllys 		fullpath = get_fullpath(dirpath, certfile);
352599ebb4caSwyllys 		if (fullpath == NULL)
352699ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
352799ebb4caSwyllys 
352899ebb4caSwyllys 		if (isdir(fullpath)) {
352999ebb4caSwyllys 			free(fullpath);
353099ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
353199ebb4caSwyllys 		}
353299ebb4caSwyllys 
35335b3e1433Swyllys 		(void) memset(&certdata, 0, sizeof (certdata));
35345b3e1433Swyllys 		rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL,
35355b3e1433Swyllys 		    fullpath, &certdata.certificate);
353699ebb4caSwyllys 		if (rv != KMF_OK)
353799ebb4caSwyllys 			goto end;
353830a5e8faSwyllys 
35395b3e1433Swyllys 		gotcert++;
35405b3e1433Swyllys 		certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
354130a5e8faSwyllys 		free(fullpath);
354299ebb4caSwyllys 	}
354399ebb4caSwyllys 
354499ebb4caSwyllys 	/*
354599ebb4caSwyllys 	 * Now find the private key.
354699ebb4caSwyllys 	 */
354730a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
354830a5e8faSwyllys 	if (keyfile != NULL) {
354930a5e8faSwyllys 		fullpath = get_fullpath(dirpath, keyfile);
355099ebb4caSwyllys 		if (fullpath == NULL)
355199ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
355299ebb4caSwyllys 
355399ebb4caSwyllys 		if (isdir(fullpath)) {
355499ebb4caSwyllys 			free(fullpath);
355599ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
355699ebb4caSwyllys 		}
355799ebb4caSwyllys 
35585b3e1433Swyllys 		(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
35595b3e1433Swyllys 		rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
35605b3e1433Swyllys 		if (rv != KMF_OK)
356199ebb4caSwyllys 			goto end;
35625b3e1433Swyllys 		gotkey++;
356399ebb4caSwyllys 	}
356499ebb4caSwyllys 
356599ebb4caSwyllys 	/*
356699ebb4caSwyllys 	 * Open the output file.
356799ebb4caSwyllys 	 */
356830a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
356930a5e8faSwyllys 	    numattr);
357030a5e8faSwyllys 	if (filename == NULL) {
357130a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
357230a5e8faSwyllys 		goto end;
357330a5e8faSwyllys 	}
357430a5e8faSwyllys 
357599ebb4caSwyllys 	/* Stick the key and the cert into a PKCS#12 file */
357630a5e8faSwyllys 	p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
357730a5e8faSwyllys 	if (p12cred == NULL) {
357830a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
357930a5e8faSwyllys 		goto end;
358030a5e8faSwyllys 	}
358130a5e8faSwyllys 
35825b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, 1, &certdata,
35835b3e1433Swyllys 	    1, &key, filename);
358499ebb4caSwyllys 
358599ebb4caSwyllys end:
358699ebb4caSwyllys 	if (fullpath)
358799ebb4caSwyllys 		free(fullpath);
358899ebb4caSwyllys 
35895b3e1433Swyllys 	if (gotcert)
35905b3e1433Swyllys 		kmf_free_kmf_cert(handle, &certdata);
35915b3e1433Swyllys 	if (gotkey)
35925b3e1433Swyllys 		kmf_free_kmf_key(handle, &key);
359399ebb4caSwyllys 	return (rv);
359499ebb4caSwyllys }
359599ebb4caSwyllys 
359671593db2Swyllys /*
359771593db2Swyllys  * Helper function to extract keys and certificates from
359871593db2Swyllys  * a single PEM file.  Typically the file should contain a
359971593db2Swyllys  * private key and an associated public key wrapped in an x509 cert.
360071593db2Swyllys  * However, the file may be just a list of X509 certs with no keys.
360171593db2Swyllys  */
360271593db2Swyllys static KMF_RETURN
360330a5e8faSwyllys extract_pem(KMF_HANDLE *kmfh,
360430a5e8faSwyllys 	char *issuer, char *subject, KMF_BIGINT *serial,
360502744e81Swyllys 	char *filename, CK_UTF8CHAR *pin,
360671593db2Swyllys 	CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
360771593db2Swyllys 	int *numcerts)
3608a2d4930dSDan OpenSolaris Anderson /* ARGSUSED6 */
360971593db2Swyllys {
361071593db2Swyllys 	KMF_RETURN rv = KMF_OK;
361171593db2Swyllys 	FILE *fp;
361234acef67Swyllys 	STACK_OF(X509_INFO) *x509_info_stack = NULL;
361302744e81Swyllys 	int i, ncerts = 0, matchcerts = 0;
361471593db2Swyllys 	EVP_PKEY *pkey = NULL;
361571593db2Swyllys 	X509_INFO *info;
361671593db2Swyllys 	X509 *x;
36175b3e1433Swyllys 	X509_INFO **cert_infos = NULL;
361871593db2Swyllys 	KMF_DATA *certlist = NULL;
361971593db2Swyllys 
362071593db2Swyllys 	if (priv_key)
362171593db2Swyllys 		*priv_key = NULL;
362271593db2Swyllys 	if (certs)
362371593db2Swyllys 		*certs = NULL;
362471593db2Swyllys 	fp = fopen(filename, "r");
36255b3e1433Swyllys 	if (fp == NULL)
362671593db2Swyllys 		return (KMF_ERR_OPEN_FILE);
36275b3e1433Swyllys 
362871593db2Swyllys 	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
362971593db2Swyllys 	if (x509_info_stack == NULL) {
363071593db2Swyllys 		(void) fclose(fp);
363171593db2Swyllys 		return (KMF_ERR_ENCODING);
363271593db2Swyllys 	}
36335b3e1433Swyllys 	cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
36345b3e1433Swyllys 	    sizeof (X509_INFO *));
36355b3e1433Swyllys 	if (cert_infos == NULL) {
36365b3e1433Swyllys 		(void) fclose(fp);
36375b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
36385b3e1433Swyllys 		goto err;
36395b3e1433Swyllys 	}
364071593db2Swyllys 
36415b3e1433Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3642a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
364334acef67Swyllys 		cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
364471593db2Swyllys 		ncerts++;
364571593db2Swyllys 	}
364671593db2Swyllys 
364771593db2Swyllys 	if (ncerts == 0) {
364871593db2Swyllys 		(void) fclose(fp);
364934acef67Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
365034acef67Swyllys 		goto err;
365171593db2Swyllys 	}
365271593db2Swyllys 
365371593db2Swyllys 	if (priv_key != NULL) {
365471593db2Swyllys 		rewind(fp);
365571593db2Swyllys 		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
365671593db2Swyllys 	}
365771593db2Swyllys 	(void) fclose(fp);
365871593db2Swyllys 
365971593db2Swyllys 	x = cert_infos[ncerts - 1]->x509;
366071593db2Swyllys 	/*
366171593db2Swyllys 	 * Make sure the private key matchs the last cert in the file.
366271593db2Swyllys 	 */
366371593db2Swyllys 	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
366471593db2Swyllys 		EVP_PKEY_free(pkey);
366534acef67Swyllys 		rv = KMF_ERR_KEY_MISMATCH;
366634acef67Swyllys 		goto err;
366771593db2Swyllys 	}
366871593db2Swyllys 
3669a2d4930dSDan OpenSolaris Anderson 	certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
367071593db2Swyllys 	if (certlist == NULL) {
367171593db2Swyllys 		if (pkey != NULL)
367271593db2Swyllys 			EVP_PKEY_free(pkey);
367334acef67Swyllys 		rv = KMF_ERR_MEMORY;
367434acef67Swyllys 		goto err;
367571593db2Swyllys 	}
367671593db2Swyllys 
367771593db2Swyllys 	/*
367871593db2Swyllys 	 * Convert all of the certs to DER format.
367971593db2Swyllys 	 */
368002744e81Swyllys 	matchcerts = 0;
368171593db2Swyllys 	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
368202744e81Swyllys 		boolean_t match = FALSE;
368371593db2Swyllys 		info =  cert_infos[ncerts - 1 - i];
368471593db2Swyllys 
368530a5e8faSwyllys 		rv = check_cert(info->x509, issuer, subject, serial, &match);
368602744e81Swyllys 		if (rv != KMF_OK || match != TRUE) {
368702744e81Swyllys 			rv = KMF_OK;
368802744e81Swyllys 			continue;
368902744e81Swyllys 		}
369002744e81Swyllys 
369102744e81Swyllys 		rv = ssl_cert2KMFDATA(kmfh, info->x509,
369202744e81Swyllys 			&certlist[matchcerts++]);
369371593db2Swyllys 
369471593db2Swyllys 		if (rv != KMF_OK) {
3695e65e5c2dSWyllys Ingersoll 			int j;
3696e65e5c2dSWyllys Ingersoll 			for (j = 0; j < matchcerts; j++)
3697e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certlist[j]);
369871593db2Swyllys 			free(certlist);
369971593db2Swyllys 			certlist = NULL;
370002744e81Swyllys 			ncerts = matchcerts = 0;
370171593db2Swyllys 		}
370271593db2Swyllys 	}
370371593db2Swyllys 
370471593db2Swyllys 	if (numcerts != NULL)
370502744e81Swyllys 		*numcerts = matchcerts;
3706a2d4930dSDan OpenSolaris Anderson 
3707e65e5c2dSWyllys Ingersoll 	if (certs != NULL)
370871593db2Swyllys 		*certs = certlist;
3709e65e5c2dSWyllys Ingersoll 	else if (certlist != NULL) {
3710e65e5c2dSWyllys Ingersoll 		for (i = 0; i < ncerts; i++)
3711e65e5c2dSWyllys Ingersoll 			kmf_free_data(&certlist[i]);
3712a2d4930dSDan OpenSolaris Anderson 		free(certlist);
3713a2d4930dSDan OpenSolaris Anderson 		certlist = NULL;
3714a2d4930dSDan OpenSolaris Anderson 	}
371571593db2Swyllys 
371671593db2Swyllys 	if (priv_key == NULL && pkey != NULL)
371771593db2Swyllys 		EVP_PKEY_free(pkey);
371871593db2Swyllys 	else if (priv_key != NULL && pkey != NULL)
371971593db2Swyllys 		*priv_key = pkey;
372071593db2Swyllys 
372134acef67Swyllys err:
372234acef67Swyllys 	/* Cleanup the stack of X509 info records */
372334acef67Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3724a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
372534acef67Swyllys 		info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
372634acef67Swyllys 		X509_INFO_free(info);
372734acef67Swyllys 	}
372834acef67Swyllys 	if (x509_info_stack)
372934acef67Swyllys 		sk_X509_INFO_free(x509_info_stack);
373034acef67Swyllys 
37315b3e1433Swyllys 	if (cert_infos != NULL)
37325b3e1433Swyllys 		free(cert_infos);
37335b3e1433Swyllys 
373471593db2Swyllys 	return (rv);
373571593db2Swyllys }
373671593db2Swyllys 
37375b3e1433Swyllys static KMF_RETURN
37385b3e1433Swyllys openssl_parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
37395b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
37405b3e1433Swyllys {
37415b3e1433Swyllys 	KMF_RETURN ret;
37425b3e1433Swyllys 	int i;
37435b3e1433Swyllys 
37445b3e1433Swyllys 	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
3745a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
37465b3e1433Swyllys 		PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
37475b3e1433Swyllys 		ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
37485b3e1433Swyllys 		    keys, certs);
37495b3e1433Swyllys 
37505b3e1433Swyllys 		if (ret != KMF_OK)
37515b3e1433Swyllys 			return (ret);
37525b3e1433Swyllys 	}
37535b3e1433Swyllys 
37545b3e1433Swyllys 	return (ret);
37555b3e1433Swyllys }
37565b3e1433Swyllys 
37575b3e1433Swyllys static KMF_RETURN
37585b3e1433Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
37595b3e1433Swyllys {
37605b3e1433Swyllys 	X509_ATTRIBUTE *attr = NULL;
37615b3e1433Swyllys 
37625b3e1433Swyllys 	if (pkey == NULL || attrib == NULL)
37635b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
37645b3e1433Swyllys 
37655b3e1433Swyllys 	if (pkey->attributes == NULL) {
37665b3e1433Swyllys 		pkey->attributes = sk_X509_ATTRIBUTE_new_null();
37675b3e1433Swyllys 		if (pkey->attributes == NULL)
37685b3e1433Swyllys 			return (KMF_ERR_MEMORY);
37695b3e1433Swyllys 	}
37705b3e1433Swyllys 	attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
37715b3e1433Swyllys 	if (attr != NULL) {
37725b3e1433Swyllys 		int i;
37735b3e1433Swyllys 		X509_ATTRIBUTE *a;
37745b3e1433Swyllys 		for (i = 0;
37755b3e1433Swyllys 		    i < sk_X509_ATTRIBUTE_num(pkey->attributes); i++) {
3776e65e5c2dSWyllys Ingersoll 			/* LINTED E_BAD_PTR_CASE_ALIGN */
37775b3e1433Swyllys 			a = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
37785b3e1433Swyllys 			if (OBJ_obj2nid(a->object) == nid) {
37795b3e1433Swyllys 				X509_ATTRIBUTE_free(a);
3780a2d4930dSDan OpenSolaris Anderson 				/* LINTED E_BAD_PTR_CAST_ALIGN */
37815b3e1433Swyllys 				sk_X509_ATTRIBUTE_set(pkey->attributes,
37825b3e1433Swyllys 				    i, attr);
37835b3e1433Swyllys 				return (KMF_OK);
37845b3e1433Swyllys 			}
37855b3e1433Swyllys 		}
37865b3e1433Swyllys 		if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == NULL) {
37875b3e1433Swyllys 			X509_ATTRIBUTE_free(attr);
37885b3e1433Swyllys 			return (KMF_ERR_MEMORY);
37895b3e1433Swyllys 		}
37905b3e1433Swyllys 	} else {
37915b3e1433Swyllys 		return (KMF_ERR_MEMORY);
37925b3e1433Swyllys 	}
37935b3e1433Swyllys 
37945b3e1433Swyllys 	return (KMF_OK);
37955b3e1433Swyllys }
37965b3e1433Swyllys 
37975b3e1433Swyllys static KMF_RETURN
37985b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
37995b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
38005b3e1433Swyllys {
38015b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
38025b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
38035b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
38045b3e1433Swyllys 	X509 *xcert = NULL;
38055b3e1433Swyllys 	ASN1_TYPE *keyid = NULL;
38065b3e1433Swyllys 	ASN1_TYPE *fname = NULL;
38075b3e1433Swyllys 	uchar_t *data = NULL;
38085b3e1433Swyllys 
38095b3e1433Swyllys 	keyid = PKCS12_get_attr(bag, NID_localKeyID);
38105b3e1433Swyllys 	fname = PKCS12_get_attr(bag, NID_friendlyName);
38115b3e1433Swyllys 
38125b3e1433Swyllys 	switch (M_PKCS12_bag_type(bag)) {
38135b3e1433Swyllys 		case NID_keyBag:
38145b3e1433Swyllys 			if (keylist == NULL)
38155b3e1433Swyllys 				goto end;
38165b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(bag->value.keybag);
38175b3e1433Swyllys 			if (pkey == NULL)
38185b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38195b3e1433Swyllys 
38205b3e1433Swyllys 			break;
38215b3e1433Swyllys 		case NID_pkcs8ShroudedKeyBag:
38225b3e1433Swyllys 			if (keylist == NULL)
38235b3e1433Swyllys 				goto end;
38245b3e1433Swyllys 			p8 = M_PKCS12_decrypt_skey(bag, pass, passlen);
38255b3e1433Swyllys 			if (p8 == NULL)
38265b3e1433Swyllys 				return (KMF_ERR_AUTH_FAILED);
38275b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(p8);
38285b3e1433Swyllys 			PKCS8_PRIV_KEY_INFO_free(p8);
38295b3e1433Swyllys 			if (pkey == NULL)
38305b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38315b3e1433Swyllys 			break;
38325b3e1433Swyllys 		case NID_certBag:
38335b3e1433Swyllys 			if (certlist == NULL)
38345b3e1433Swyllys 				goto end;
38355b3e1433Swyllys 			if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate)
38365b3e1433Swyllys 				return (KMF_ERR_PKCS12_FORMAT);
38375b3e1433Swyllys 			xcert = M_PKCS12_certbag2x509(bag);
38385b3e1433Swyllys 			if (xcert == NULL) {
38395b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38405b3e1433Swyllys 				goto end;
38415b3e1433Swyllys 			}
38425b3e1433Swyllys 			if (keyid != NULL) {
38435b3e1433Swyllys 				if (X509_keyid_set1(xcert,
38445b3e1433Swyllys 				    keyid->value.octet_string->data,
38455b3e1433Swyllys 				    keyid->value.octet_string->length) == 0) {
38465b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
38475b3e1433Swyllys 					goto end;
38485b3e1433Swyllys 				}
38495b3e1433Swyllys 			}
38505b3e1433Swyllys 			if (fname != NULL) {
38515b3e1433Swyllys 				int len, r;
38525b3e1433Swyllys 				len = ASN1_STRING_to_UTF8(&data,
38535b3e1433Swyllys 				    fname->value.asn1_string);
38545b3e1433Swyllys 				if (len > 0 && data != NULL) {
38555b3e1433Swyllys 					r = X509_alias_set1(xcert, data, len);
38565b3e1433Swyllys 					if (r == NULL) {
38575b3e1433Swyllys 						ret = KMF_ERR_PKCS12_FORMAT;
38585b3e1433Swyllys 						goto end;
38595b3e1433Swyllys 					}
38605b3e1433Swyllys 				} else {
38615b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
38625b3e1433Swyllys 					goto end;
38635b3e1433Swyllys 				}
38645b3e1433Swyllys 			}
38655b3e1433Swyllys 			if (sk_X509_push(certlist, xcert) == 0)
38665b3e1433Swyllys 				ret = KMF_ERR_MEMORY;
38675b3e1433Swyllys 			else
38685b3e1433Swyllys 				xcert = NULL;
38695b3e1433Swyllys 			break;
38705b3e1433Swyllys 		case NID_safeContentsBag:
38715b3e1433Swyllys 			return (openssl_parse_bags(bag->value.safes, pass,
38725b3e1433Swyllys 			    keylist, certlist));
38735b3e1433Swyllys 		default:
38745b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
38755b3e1433Swyllys 			break;
38765b3e1433Swyllys 	}
38775b3e1433Swyllys 
38785b3e1433Swyllys 	/*
38795b3e1433Swyllys 	 * Set the ID and/or FriendlyName attributes on the key.
38805b3e1433Swyllys 	 * If converting to PKCS11 objects, these can translate to CKA_ID
38815b3e1433Swyllys 	 * and CKA_LABEL values.
38825b3e1433Swyllys 	 */
38835b3e1433Swyllys 	if (pkey != NULL && ret == KMF_OK) {
38845b3e1433Swyllys 		ASN1_TYPE *attr = NULL;
38855b3e1433Swyllys 		if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
38865b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
38875b3e1433Swyllys 				return (KMF_ERR_MEMORY);
38885b3e1433Swyllys 			attr->value.octet_string =
38895b3e1433Swyllys 			    ASN1_STRING_dup(keyid->value.octet_string);
38905b3e1433Swyllys 			attr->type = V_ASN1_OCTET_STRING;
38915b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.octet_string;
38925b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
38935b3e1433Swyllys 			OPENSSL_free(attr);
38945b3e1433Swyllys 		}
38955b3e1433Swyllys 
38965b3e1433Swyllys 		if (ret == KMF_OK && fname != NULL &&
38975b3e1433Swyllys 		    fname->type == V_ASN1_BMPSTRING) {
38985b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
38995b3e1433Swyllys 				return (KMF_ERR_MEMORY);
39005b3e1433Swyllys 			attr->value.bmpstring =
39015b3e1433Swyllys 			    ASN1_STRING_dup(fname->value.bmpstring);
39025b3e1433Swyllys 			attr->type = V_ASN1_BMPSTRING;
39035b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.bmpstring;
39045b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
39055b3e1433Swyllys 			OPENSSL_free(attr);
39065b3e1433Swyllys 		}
39075b3e1433Swyllys 
39085b3e1433Swyllys 		if (ret == KMF_OK && keylist != NULL &&
39095b3e1433Swyllys 		    sk_EVP_PKEY_push(keylist, pkey) == 0)
39105b3e1433Swyllys 			ret = KMF_ERR_MEMORY;
39115b3e1433Swyllys 	}
39125b3e1433Swyllys 	if (ret == KMF_OK && keylist != NULL)
39135b3e1433Swyllys 		pkey = NULL;
39145b3e1433Swyllys end:
39155b3e1433Swyllys 	if (pkey != NULL)
39165b3e1433Swyllys 		EVP_PKEY_free(pkey);
39175b3e1433Swyllys 	if (xcert != NULL)
39185b3e1433Swyllys 		X509_free(xcert);
39195b3e1433Swyllys 	if (data != NULL)
39205b3e1433Swyllys 		OPENSSL_free(data);
39215b3e1433Swyllys 
39225b3e1433Swyllys 	return (ret);
39235b3e1433Swyllys }
39245b3e1433Swyllys 
39255b3e1433Swyllys static KMF_RETURN
39265b3e1433Swyllys openssl_pkcs12_parse(PKCS12 *p12, char *pin,
39275b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys,
39285b3e1433Swyllys 	STACK_OF(X509) *certs,
39295b3e1433Swyllys 	STACK_OF(X509) *ca)
3930a2d4930dSDan OpenSolaris Anderson /* ARGSUSED3 */
39315b3e1433Swyllys {
39325b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
39335b3e1433Swyllys 	STACK_OF(PKCS7) *asafes = NULL;
39345b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
39355b3e1433Swyllys 	int i, bagnid;
39365b3e1433Swyllys 	PKCS7 *p7;
39375b3e1433Swyllys 
39385b3e1433Swyllys 	if (p12 == NULL || (keys == NULL && certs == NULL))
39395b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
39405b3e1433Swyllys 
39415b3e1433Swyllys 	if (pin == NULL || *pin == NULL) {
39425b3e1433Swyllys 		if (PKCS12_verify_mac(p12, NULL, 0)) {
39435b3e1433Swyllys 			pin = NULL;
39445b3e1433Swyllys 		} else if (PKCS12_verify_mac(p12, "", 0)) {
39455b3e1433Swyllys 			pin = "";
39465b3e1433Swyllys 		} else {
39475b3e1433Swyllys 			return (KMF_ERR_AUTH_FAILED);
39485b3e1433Swyllys 		}
39495b3e1433Swyllys 	} else if (!PKCS12_verify_mac(p12, pin, -1)) {
39505b3e1433Swyllys 		return (KMF_ERR_AUTH_FAILED);
39515b3e1433Swyllys 	}
39525b3e1433Swyllys 
39535b3e1433Swyllys 	if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
39545b3e1433Swyllys 		return (KMF_ERR_PKCS12_FORMAT);
39555b3e1433Swyllys 
39565b3e1433Swyllys 	for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
39575b3e1433Swyllys 		bags = NULL;
3958a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
39595b3e1433Swyllys 		p7 = sk_PKCS7_value(asafes, i);
39605b3e1433Swyllys 		bagnid = OBJ_obj2nid(p7->type);
39615b3e1433Swyllys 
39625b3e1433Swyllys 		if (bagnid == NID_pkcs7_data) {
39635b3e1433Swyllys 			bags = PKCS12_unpack_p7data(p7);
39645b3e1433Swyllys 		} else if (bagnid == NID_pkcs7_encrypted) {
39655b3e1433Swyllys 			bags = PKCS12_unpack_p7encdata(p7, pin,
39665b3e1433Swyllys 			    (pin ? strlen(pin) : 0));
39675b3e1433Swyllys 		} else {
39685b3e1433Swyllys 			continue;
39695b3e1433Swyllys 		}
39705b3e1433Swyllys 		if (bags == NULL) {
39715b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39725b3e1433Swyllys 			goto out;
39735b3e1433Swyllys 		}
39745b3e1433Swyllys 
39755b3e1433Swyllys 		if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
39765b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39775b3e1433Swyllys 
39785b3e1433Swyllys 		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
39795b3e1433Swyllys 	}
39805b3e1433Swyllys out:
39815b3e1433Swyllys 	if (asafes != NULL)
39825b3e1433Swyllys 		sk_PKCS7_pop_free(asafes, PKCS7_free);
39835b3e1433Swyllys 
39845b3e1433Swyllys 	return (ret);
39855b3e1433Swyllys }
39865b3e1433Swyllys 
398799ebb4caSwyllys /*
398899ebb4caSwyllys  * Helper function to decrypt and parse PKCS#12 import file.
398999ebb4caSwyllys  */
399099ebb4caSwyllys static KMF_RETURN
399199ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
39925b3e1433Swyllys 	STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs,
39935b3e1433Swyllys 	STACK_OF(X509) **ca)
3994a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */
399599ebb4caSwyllys {
399699ebb4caSwyllys 	PKCS12			*pk12, *pk12_tmp;
39975b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*pkeylist = NULL;
39985b3e1433Swyllys 	STACK_OF(X509)		*xcertlist = NULL;
39995b3e1433Swyllys 	STACK_OF(X509)		*cacertlist = NULL;
400099ebb4caSwyllys 
400199ebb4caSwyllys 	if ((pk12 = PKCS12_new()) == NULL) {
400299ebb4caSwyllys 		return (KMF_ERR_MEMORY);
400399ebb4caSwyllys 	}
400499ebb4caSwyllys 
400599ebb4caSwyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
400699ebb4caSwyllys 		/* This is ok; it seems to mean there is no more to read. */
400799ebb4caSwyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
400899ebb4caSwyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
400999ebb4caSwyllys 			goto end_extract_pkcs12;
401099ebb4caSwyllys 
401199ebb4caSwyllys 		PKCS12_free(pk12);
401299ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
401399ebb4caSwyllys 	}
401499ebb4caSwyllys 	pk12 = pk12_tmp;
401599ebb4caSwyllys 
40165b3e1433Swyllys 	xcertlist = sk_X509_new_null();
40175b3e1433Swyllys 	if (xcertlist == NULL) {
40185b3e1433Swyllys 		PKCS12_free(pk12);
40195b3e1433Swyllys 		return (KMF_ERR_MEMORY);
40205b3e1433Swyllys 	}
40215b3e1433Swyllys 	pkeylist = sk_EVP_PKEY_new_null();
40225b3e1433Swyllys 	if (pkeylist == NULL) {
40235b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40245b3e1433Swyllys 		PKCS12_free(pk12);
40255b3e1433Swyllys 		return (KMF_ERR_MEMORY);
40265b3e1433Swyllys 	}
40275b3e1433Swyllys 
40285b3e1433Swyllys 	if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
40295b3e1433Swyllys 	    cacertlist) != KMF_OK) {
40305b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40315b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
403299ebb4caSwyllys 		PKCS12_free(pk12);
403399ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
403499ebb4caSwyllys 	}
403599ebb4caSwyllys 
40365b3e1433Swyllys 	if (priv_key && pkeylist)
40375b3e1433Swyllys 		*priv_key = pkeylist;
40385b3e1433Swyllys 	else if (pkeylist)
40395b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
40405b3e1433Swyllys 	if (certs && xcertlist)
40415b3e1433Swyllys 		*certs = xcertlist;
40425b3e1433Swyllys 	else if (xcertlist)
40435b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40445b3e1433Swyllys 	if (ca && cacertlist)
40455b3e1433Swyllys 		*ca = cacertlist;
40465b3e1433Swyllys 	else if (cacertlist)
40475b3e1433Swyllys 		sk_X509_pop_free(cacertlist, X509_free);
404899ebb4caSwyllys 
40495b3e1433Swyllys end_extract_pkcs12:
405099ebb4caSwyllys 
405199ebb4caSwyllys 	PKCS12_free(pk12);
405299ebb4caSwyllys 	return (KMF_OK);
405399ebb4caSwyllys }
405499ebb4caSwyllys 
405599ebb4caSwyllys static KMF_RETURN
405699ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
405799ebb4caSwyllys {
405899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
405999ebb4caSwyllys 	uint32_t sz;
406099ebb4caSwyllys 
406199ebb4caSwyllys 	sz = BN_num_bytes(from);
406299ebb4caSwyllys 	to->val = (uchar_t *)malloc(sz);
406399ebb4caSwyllys 	if (to->val == NULL)
406499ebb4caSwyllys 		return (KMF_ERR_MEMORY);
406599ebb4caSwyllys 
406699ebb4caSwyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
406799ebb4caSwyllys 		free(to->val);
406899ebb4caSwyllys 		to->val = NULL;
406999ebb4caSwyllys 		to->len = 0;
407099ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
407199ebb4caSwyllys 	}
407299ebb4caSwyllys 
407399ebb4caSwyllys 	return (rv);
407499ebb4caSwyllys }
407599ebb4caSwyllys 
407699ebb4caSwyllys static KMF_RETURN
407799ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
407899ebb4caSwyllys {
407999ebb4caSwyllys 	KMF_RETURN rv;
408099ebb4caSwyllys 	KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
408199ebb4caSwyllys 
408299ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
408399ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK)
408499ebb4caSwyllys 		goto cleanup;
408599ebb4caSwyllys 
408699ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK)
408799ebb4caSwyllys 		goto cleanup;
408899ebb4caSwyllys 
408999ebb4caSwyllys 	if (rsa->d != NULL)
409099ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK)
409199ebb4caSwyllys 			goto cleanup;
409299ebb4caSwyllys 
409399ebb4caSwyllys 	if (rsa->p != NULL)
409499ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK)
409599ebb4caSwyllys 			goto cleanup;
409699ebb4caSwyllys 
409799ebb4caSwyllys 	if (rsa->q != NULL)
409899ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK)
409999ebb4caSwyllys 			goto cleanup;
410099ebb4caSwyllys 
410199ebb4caSwyllys 	if (rsa->dmp1 != NULL)
410299ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK)
410399ebb4caSwyllys 			goto cleanup;
410499ebb4caSwyllys 
410599ebb4caSwyllys 	if (rsa->dmq1 != NULL)
410699ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK)
410799ebb4caSwyllys 			goto cleanup;
410899ebb4caSwyllys 
410999ebb4caSwyllys 	if (rsa->iqmp != NULL)
411099ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK)
411199ebb4caSwyllys 			goto cleanup;
411299ebb4caSwyllys cleanup:
411399ebb4caSwyllys 	if (rv != KMF_OK)
411430a5e8faSwyllys 		kmf_free_raw_key(key);
411599ebb4caSwyllys 	else
411699ebb4caSwyllys 		key->keytype = KMF_RSA;
411799ebb4caSwyllys 
411899ebb4caSwyllys 	/*
411999ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
412099ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
412199ebb4caSwyllys 	 */
412299ebb4caSwyllys 	RSA_free(rsa);
412399ebb4caSwyllys 
412499ebb4caSwyllys 	return (rv);
412599ebb4caSwyllys }
412699ebb4caSwyllys 
412799ebb4caSwyllys static KMF_RETURN
412899ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
412999ebb4caSwyllys {
413099ebb4caSwyllys 	KMF_RETURN rv;
413199ebb4caSwyllys 	KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
413299ebb4caSwyllys 
413399ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
413499ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK)
413599ebb4caSwyllys 		goto cleanup;
413699ebb4caSwyllys 
413799ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK)
413899ebb4caSwyllys 		goto cleanup;
413999ebb4caSwyllys 
414099ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK)
414199ebb4caSwyllys 		goto cleanup;
414299ebb4caSwyllys 
414399ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK)
414499ebb4caSwyllys 		goto cleanup;
414599ebb4caSwyllys 
414699ebb4caSwyllys cleanup:
414799ebb4caSwyllys 	if (rv != KMF_OK)
414830a5e8faSwyllys 		kmf_free_raw_key(key);
414999ebb4caSwyllys 	else
415099ebb4caSwyllys 		key->keytype = KMF_DSA;
415199ebb4caSwyllys 
415299ebb4caSwyllys 	/*
415399ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
415499ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
415599ebb4caSwyllys 	 */
415699ebb4caSwyllys 	DSA_free(dsa);
415799ebb4caSwyllys 
415899ebb4caSwyllys 	return (rv);
415999ebb4caSwyllys }
416099ebb4caSwyllys 
416199ebb4caSwyllys static KMF_RETURN
416299ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
41635b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
416499ebb4caSwyllys {
416599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
41665b3e1433Swyllys 	KMF_X509_DER_CERT *list = (*certlist);
41675b3e1433Swyllys 	KMF_X509_DER_CERT cert;
416899ebb4caSwyllys 	int n = (*ncerts);
416999ebb4caSwyllys 
417099ebb4caSwyllys 	if (list == NULL) {
41715b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
417299ebb4caSwyllys 	} else {
41735b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)realloc(list,
41745b3e1433Swyllys 		    sizeof (KMF_X509_DER_CERT) * (n + 1));
417599ebb4caSwyllys 	}
417699ebb4caSwyllys 
417799ebb4caSwyllys 	if (list == NULL)
417899ebb4caSwyllys 		return (KMF_ERR_MEMORY);
417999ebb4caSwyllys 
41805b3e1433Swyllys 	(void) memset(&cert, 0, sizeof (cert));
41815b3e1433Swyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
418299ebb4caSwyllys 	if (rv == KMF_OK) {
41835b3e1433Swyllys 		int len = 0;
41845b3e1433Swyllys 		/* Get the alias name for the cert if there is one */
41855b3e1433Swyllys 		char *a = (char *)X509_alias_get0(sslcert, &len);
41865b3e1433Swyllys 		if (a != NULL)
41875b3e1433Swyllys 			cert.kmf_private.label = strdup(a);
41885b3e1433Swyllys 		cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
41895b3e1433Swyllys 
419099ebb4caSwyllys 		list[n] = cert;
419199ebb4caSwyllys 		(*ncerts) = n + 1;
419299ebb4caSwyllys 
419399ebb4caSwyllys 		*certlist = list;
419499ebb4caSwyllys 	} else {
419599ebb4caSwyllys 		free(list);
419699ebb4caSwyllys 	}
419799ebb4caSwyllys 
419899ebb4caSwyllys 	return (rv);
419999ebb4caSwyllys }
420099ebb4caSwyllys 
420199ebb4caSwyllys static KMF_RETURN
420299ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
420399ebb4caSwyllys 	KMF_RAW_KEY_DATA *newkey, int *nkeys)
420499ebb4caSwyllys {
420599ebb4caSwyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
420699ebb4caSwyllys 	int n = (*nkeys);
420799ebb4caSwyllys 
420899ebb4caSwyllys 	if (list == NULL) {
420999ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
421099ebb4caSwyllys 	} else {
421199ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
421299ebb4caSwyllys 		    sizeof (KMF_RAW_KEY_DATA) * (n + 1));
421399ebb4caSwyllys 	}
421499ebb4caSwyllys 
421599ebb4caSwyllys 	if (list == NULL)
421699ebb4caSwyllys 		return (KMF_ERR_MEMORY);
421799ebb4caSwyllys 
421899ebb4caSwyllys 	list[n] = *newkey;
421999ebb4caSwyllys 	(*nkeys) = n + 1;
422099ebb4caSwyllys 
422199ebb4caSwyllys 	*keylist = list;
422299ebb4caSwyllys 
422399ebb4caSwyllys 	return (KMF_OK);
422499ebb4caSwyllys }
422599ebb4caSwyllys 
42265b3e1433Swyllys static X509_ATTRIBUTE *
42275b3e1433Swyllys find_attr(STACK_OF(X509_ATTRIBUTE) *attrs, int nid)
42285b3e1433Swyllys {
42295b3e1433Swyllys 	X509_ATTRIBUTE *a;
42305b3e1433Swyllys 	int i;
42315b3e1433Swyllys 
42325b3e1433Swyllys 	if (attrs == NULL)
42335b3e1433Swyllys 		return (NULL);
42345b3e1433Swyllys 
42355b3e1433Swyllys 	for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
4236a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
42375b3e1433Swyllys 		a = sk_X509_ATTRIBUTE_value(attrs, i);
42385b3e1433Swyllys 		if (OBJ_obj2nid(a->object) == nid)
42395b3e1433Swyllys 			return (a);
42405b3e1433Swyllys 	}
42415b3e1433Swyllys 	return (NULL);
42425b3e1433Swyllys }
42435b3e1433Swyllys 
424430a5e8faSwyllys static KMF_RETURN
424530a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
424630a5e8faSwyllys {
424730a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
42485b3e1433Swyllys 	X509_ATTRIBUTE *attr;
424930a5e8faSwyllys 
425030a5e8faSwyllys 	if (pkey == NULL || key == NULL)
425130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
425230a5e8faSwyllys 	/* Convert SSL key to raw key */
425330a5e8faSwyllys 	switch (pkey->type) {
425430a5e8faSwyllys 		case EVP_PKEY_RSA:
425530a5e8faSwyllys 			rv = exportRawRSAKey(EVP_PKEY_get1_RSA(pkey),
425630a5e8faSwyllys 			    key);
425730a5e8faSwyllys 			if (rv != KMF_OK)
425830a5e8faSwyllys 				return (rv);
425930a5e8faSwyllys 			break;
426030a5e8faSwyllys 		case EVP_PKEY_DSA:
426130a5e8faSwyllys 			rv = exportRawDSAKey(EVP_PKEY_get1_DSA(pkey),
426230a5e8faSwyllys 			    key);
426330a5e8faSwyllys 			if (rv != KMF_OK)
426430a5e8faSwyllys 				return (rv);
426530a5e8faSwyllys 			break;
426630a5e8faSwyllys 		default:
426730a5e8faSwyllys 			return (KMF_ERR_BAD_PARAMETER);
426830a5e8faSwyllys 	}
42695b3e1433Swyllys 	/*
42705b3e1433Swyllys 	 * If friendlyName, add it to record.
42715b3e1433Swyllys 	 */
42725b3e1433Swyllys 	attr = find_attr(pkey->attributes, NID_friendlyName);
42735b3e1433Swyllys 	if (attr != NULL) {
42745b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
42755b3e1433Swyllys 		int numattr = sk_ASN1_TYPE_num(attr->value.set);
42765b3e1433Swyllys 		if (attr->single == 0 && numattr > 0) {
4277a2d4930dSDan OpenSolaris Anderson 			/* LINTED E_BAD_PTR_CAST_ALIGN */
42785b3e1433Swyllys 			ty = sk_ASN1_TYPE_value(attr->value.set, 0);
42795b3e1433Swyllys 		}
42805b3e1433Swyllys 		if (ty != NULL) {
4281*70f9559bSTheo Schlossnagle #if OPENSSL_VERSION_NUMBER < 0x10000000L
42825b3e1433Swyllys 			key->label = uni2asc(ty->value.bmpstring->data,
42835b3e1433Swyllys 			    ty->value.bmpstring->length);
4284*70f9559bSTheo Schlossnagle #else
4285*70f9559bSTheo Schlossnagle 			key->label = OPENSSL_uni2asc(ty->value.bmpstring->data,
4286*70f9559bSTheo Schlossnagle 			    ty->value.bmpstring->length);
4287*70f9559bSTheo Schlossnagle #endif
42885b3e1433Swyllys 		}
42895b3e1433Swyllys 	} else {
42905b3e1433Swyllys 		key->label = NULL;
42915b3e1433Swyllys 	}
42925b3e1433Swyllys 
42935b3e1433Swyllys 	/*
42945b3e1433Swyllys 	 * If KeyID, add it to record as a KMF_DATA object.
42955b3e1433Swyllys 	 */
42965b3e1433Swyllys 	attr = find_attr(pkey->attributes, NID_localKeyID);
42975b3e1433Swyllys 	if (attr != NULL) {
42985b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
42995b3e1433Swyllys 		int numattr = sk_ASN1_TYPE_num(attr->value.set);
43005b3e1433Swyllys 		if (attr->single == 0 && numattr > 0) {
4301a2d4930dSDan OpenSolaris Anderson 			/* LINTED E_BAD_PTR_CAST_ALIGN */
43025b3e1433Swyllys 			ty = sk_ASN1_TYPE_value(attr->value.set, 0);
43035b3e1433Swyllys 		}
43045b3e1433Swyllys 		key->id.Data = (uchar_t *)malloc(
43055b3e1433Swyllys 		    ty->value.octet_string->length);
43065b3e1433Swyllys 		if (key->id.Data == NULL)
43075b3e1433Swyllys 			return (KMF_ERR_MEMORY);
43085b3e1433Swyllys 		(void) memcpy(key->id.Data, ty->value.octet_string->data,
43095b3e1433Swyllys 		    ty->value.octet_string->length);
43105b3e1433Swyllys 		key->id.Length = ty->value.octet_string->length;
43115b3e1433Swyllys 	} else {
43125b3e1433Swyllys 		(void) memset(&key->id, 0, sizeof (KMF_DATA));
43135b3e1433Swyllys 	}
431430a5e8faSwyllys 
431530a5e8faSwyllys 	return (rv);
431630a5e8faSwyllys }
431799ebb4caSwyllys 
431899ebb4caSwyllys static KMF_RETURN
431999ebb4caSwyllys convertPK12Objects(
432099ebb4caSwyllys 	KMF_HANDLE *kmfh,
43215b3e1433Swyllys 	STACK_OF(EVP_PKEY) *sslkeys,
43225b3e1433Swyllys 	STACK_OF(X509) *sslcert,
43235b3e1433Swyllys 	STACK_OF(X509) *sslcacerts,
432499ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
43255b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
432699ebb4caSwyllys {
432799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
432899ebb4caSwyllys 	KMF_RAW_KEY_DATA key;
432999ebb4caSwyllys 	int i;
433099ebb4caSwyllys 
43315b3e1433Swyllys 	for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
4332a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
43335b3e1433Swyllys 		EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
43345b3e1433Swyllys 		rv = convertToRawKey(pkey, &key);
433530a5e8faSwyllys 		if (rv == KMF_OK)
433699ebb4caSwyllys 			rv = add_key_to_list(keylist, &key, nkeys);
433730a5e8faSwyllys 
433899ebb4caSwyllys 		if (rv != KMF_OK)
433999ebb4caSwyllys 			return (rv);
434099ebb4caSwyllys 	}
434199ebb4caSwyllys 
434299ebb4caSwyllys 	/* Now add the certificate to the certlist */
43435b3e1433Swyllys 	for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
4344a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
43455b3e1433Swyllys 		X509 *cert = sk_X509_value(sslcert, i);
43465b3e1433Swyllys 		rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
434799ebb4caSwyllys 		if (rv != KMF_OK)
434899ebb4caSwyllys 			return (rv);
434999ebb4caSwyllys 	}
435099ebb4caSwyllys 
435199ebb4caSwyllys 	/* Also add any included CA certs to the list */
435271593db2Swyllys 	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
435399ebb4caSwyllys 		X509 *c;
435499ebb4caSwyllys 		/*
435599ebb4caSwyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
435699ebb4caSwyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
435799ebb4caSwyllys 		 * Lint is complaining about the embedded casting, and
435899ebb4caSwyllys 		 * to fix it, you need to fix openssl header files.
435999ebb4caSwyllys 		 */
436099ebb4caSwyllys 		/* LINTED E_BAD_PTR_CAST_ALIGN */
436199ebb4caSwyllys 		c = sk_X509_value(sslcacerts, i);
436299ebb4caSwyllys 
436399ebb4caSwyllys 		/* Now add the ca cert to the certlist */
436499ebb4caSwyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
436599ebb4caSwyllys 		if (rv != KMF_OK)
436699ebb4caSwyllys 			return (rv);
436799ebb4caSwyllys 	}
436899ebb4caSwyllys 	return (rv);
436999ebb4caSwyllys }
437099ebb4caSwyllys 
437199ebb4caSwyllys KMF_RETURN
437230a5e8faSwyllys openssl_import_objects(KMF_HANDLE *kmfh,
437399ebb4caSwyllys 	char *filename, KMF_CREDENTIAL *cred,
43745b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts,
437599ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
437699ebb4caSwyllys {
437799ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
437830a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
437930a5e8faSwyllys 	BIO		*bio = NULL;
43805b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*privkeys = NULL;
43815b3e1433Swyllys 	STACK_OF(X509)		*certs = NULL;
438299ebb4caSwyllys 	STACK_OF(X509)		*cacerts = NULL;
438399ebb4caSwyllys 
438430a5e8faSwyllys 	/*
438530a5e8faSwyllys 	 * auto-detect the file format, regardless of what
438630a5e8faSwyllys 	 * the 'format' parameters in the params say.
438730a5e8faSwyllys 	 */
438830a5e8faSwyllys 	rv = kmf_get_file_format(filename, &format);
438930a5e8faSwyllys 	if (rv != KMF_OK) {
439030a5e8faSwyllys 		return (rv);
439130a5e8faSwyllys 	}
439230a5e8faSwyllys 
439330a5e8faSwyllys 	/* This function only works for PEM or PKCS#12 files */
439430a5e8faSwyllys 	if (format != KMF_FORMAT_PEM &&
439530a5e8faSwyllys 	    format != KMF_FORMAT_PEM_KEYPAIR &&
439630a5e8faSwyllys 	    format != KMF_FORMAT_PKCS12)
439730a5e8faSwyllys 		return (KMF_ERR_ENCODING);
439830a5e8faSwyllys 
439930a5e8faSwyllys 	*certlist = NULL;
440030a5e8faSwyllys 	*keylist = NULL;
440130a5e8faSwyllys 	*ncerts = 0;
440230a5e8faSwyllys 	*nkeys = 0;
440330a5e8faSwyllys 
440430a5e8faSwyllys 	if (format == KMF_FORMAT_PKCS12) {
440599ebb4caSwyllys 		bio = BIO_new_file(filename, "rb");
440699ebb4caSwyllys 		if (bio == NULL) {
440799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
440899ebb4caSwyllys 			rv = KMF_ERR_OPEN_FILE;
440999ebb4caSwyllys 			goto end;
441099ebb4caSwyllys 		}
441199ebb4caSwyllys 
441234acef67Swyllys 		rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
44135b3e1433Swyllys 		    (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
441499ebb4caSwyllys 
441599ebb4caSwyllys 		if (rv  == KMF_OK)
441699ebb4caSwyllys 			/* Convert keys and certs to exportable format */
44175b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
441899ebb4caSwyllys 			    keylist, nkeys, certlist, ncerts);
441930a5e8faSwyllys 	} else {
44205b3e1433Swyllys 		EVP_PKEY *pkey;
44215b3e1433Swyllys 		KMF_DATA *certdata = NULL;
44225b3e1433Swyllys 		KMF_X509_DER_CERT *kmfcerts = NULL;
44235b3e1433Swyllys 		int i;
442430a5e8faSwyllys 		rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
442534acef67Swyllys 		    (uchar_t *)cred->cred, (uint32_t)cred->credlen,
44265b3e1433Swyllys 		    &pkey, &certdata, ncerts);
442771593db2Swyllys 
442871593db2Swyllys 		/* Reached end of import file? */
44295b3e1433Swyllys 		if (rv == KMF_OK && pkey != NULL) {
44305b3e1433Swyllys 			privkeys = sk_EVP_PKEY_new_null();
44315b3e1433Swyllys 			if (privkeys == NULL) {
44325b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
44335b3e1433Swyllys 				goto end;
44345b3e1433Swyllys 			}
44355b3e1433Swyllys 			(void) sk_EVP_PKEY_push(privkeys, pkey);
44365b3e1433Swyllys 			/* convert the certificate list here */
44375b3e1433Swyllys 			if (*ncerts > 0 && certlist != NULL) {
4438e65e5c2dSWyllys Ingersoll 				kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
44395b3e1433Swyllys 				    sizeof (KMF_X509_DER_CERT));
44405b3e1433Swyllys 				if (kmfcerts == NULL) {
44415b3e1433Swyllys 					rv = KMF_ERR_MEMORY;
44425b3e1433Swyllys 					goto end;
44435b3e1433Swyllys 				}
44445b3e1433Swyllys 				for (i = 0; i < *ncerts; i++) {
44455b3e1433Swyllys 					kmfcerts[i].certificate = certdata[i];
44465b3e1433Swyllys 					kmfcerts[i].kmf_private.keystore_type =
44475b3e1433Swyllys 					    KMF_KEYSTORE_OPENSSL;
44485b3e1433Swyllys 				}
44495b3e1433Swyllys 				*certlist = kmfcerts;
44505b3e1433Swyllys 			}
44515b3e1433Swyllys 			/*
44525b3e1433Swyllys 			 * Convert keys to exportable format, the certs
44535b3e1433Swyllys 			 * are already OK.
44545b3e1433Swyllys 			 */
44555b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
445671593db2Swyllys 			    keylist, nkeys, NULL, NULL);
445730a5e8faSwyllys 		}
44585b3e1433Swyllys 	}
445971593db2Swyllys end:
446030a5e8faSwyllys 	if (bio != NULL)
446199ebb4caSwyllys 		(void) BIO_free(bio);
446299ebb4caSwyllys 
44635b3e1433Swyllys 	if (privkeys)
44645b3e1433Swyllys 		sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
44655b3e1433Swyllys 	if (certs)
44665b3e1433Swyllys 		sk_X509_pop_free(certs, X509_free);
446730a5e8faSwyllys 	if (cacerts)
44685b3e1433Swyllys 		sk_X509_pop_free(cacerts, X509_free);
446930a5e8faSwyllys 
447099ebb4caSwyllys 	return (rv);
447199ebb4caSwyllys }
447299ebb4caSwyllys 
447399ebb4caSwyllys static KMF_RETURN
447499ebb4caSwyllys create_deskey(DES_cblock **deskey)
447599ebb4caSwyllys {
447699ebb4caSwyllys 	DES_cblock *key;
447799ebb4caSwyllys 
447899ebb4caSwyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
447999ebb4caSwyllys 	if (key == NULL) {
448099ebb4caSwyllys 		return (KMF_ERR_MEMORY);
448199ebb4caSwyllys 	}
448299ebb4caSwyllys 
448399ebb4caSwyllys 	if (DES_random_key(key) == 0) {
448499ebb4caSwyllys 		free(key);
448599ebb4caSwyllys 		return (KMF_ERR_KEYGEN_FAILED);
448699ebb4caSwyllys 	}
448799ebb4caSwyllys 
448899ebb4caSwyllys 	*deskey = key;
448999ebb4caSwyllys 	return (KMF_OK);
449099ebb4caSwyllys }
449199ebb4caSwyllys 
449299ebb4caSwyllys #define	KEYGEN_RETRY 3
449399ebb4caSwyllys #define	DES3_KEY_SIZE 24
449499ebb4caSwyllys 
449599ebb4caSwyllys static KMF_RETURN
449699ebb4caSwyllys create_des3key(unsigned char **des3key)
449799ebb4caSwyllys {
449899ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
449999ebb4caSwyllys 	DES_cblock *deskey1 = NULL;
450099ebb4caSwyllys 	DES_cblock *deskey2 = NULL;
450199ebb4caSwyllys 	DES_cblock *deskey3 = NULL;
450299ebb4caSwyllys 	unsigned char *newkey = NULL;
450399ebb4caSwyllys 	int retry;
450499ebb4caSwyllys 
450599ebb4caSwyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
450699ebb4caSwyllys 		return (KMF_ERR_MEMORY);
450799ebb4caSwyllys 	}
450899ebb4caSwyllys 
450999ebb4caSwyllys 	/* create the 1st DES key */
451099ebb4caSwyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
451199ebb4caSwyllys 		goto out;
451299ebb4caSwyllys 	}
451399ebb4caSwyllys 
451499ebb4caSwyllys 	/*
451599ebb4caSwyllys 	 * Create the 2nd DES key and make sure its value is different
451699ebb4caSwyllys 	 * from the 1st DES key.
451799ebb4caSwyllys 	 */
451899ebb4caSwyllys 	retry = 0;
451999ebb4caSwyllys 	do {
452099ebb4caSwyllys 		if (deskey2 != NULL) {
452199ebb4caSwyllys 			free(deskey2);
452299ebb4caSwyllys 			deskey2 = NULL;
452399ebb4caSwyllys 		}
452499ebb4caSwyllys 
452599ebb4caSwyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
452699ebb4caSwyllys 			goto out;
452799ebb4caSwyllys 		}
452899ebb4caSwyllys 
452999ebb4caSwyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
453099ebb4caSwyllys 		    == 0) {
453199ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
453299ebb4caSwyllys 			retry++;
453399ebb4caSwyllys 		}
453499ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
453599ebb4caSwyllys 
453699ebb4caSwyllys 	if (ret != KMF_OK) {
453799ebb4caSwyllys 		goto out;
453899ebb4caSwyllys 	}
453999ebb4caSwyllys 
454099ebb4caSwyllys 	/*
454199ebb4caSwyllys 	 * Create the 3rd DES key and make sure its value is different
454299ebb4caSwyllys 	 * from the 2nd DES key.
454399ebb4caSwyllys 	 */
454499ebb4caSwyllys 	retry = 0;
454599ebb4caSwyllys 	do {
454699ebb4caSwyllys 		if (deskey3 != NULL) {
454799ebb4caSwyllys 			free(deskey3);
454899ebb4caSwyllys 			deskey3 = NULL;
454999ebb4caSwyllys 		}
455099ebb4caSwyllys 
455199ebb4caSwyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
455299ebb4caSwyllys 			goto out;
455399ebb4caSwyllys 		}
455499ebb4caSwyllys 
455599ebb4caSwyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
455699ebb4caSwyllys 		    == 0) {
455799ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
455899ebb4caSwyllys 			retry++;
455999ebb4caSwyllys 		}
456099ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
456199ebb4caSwyllys 
456299ebb4caSwyllys 	if (ret != KMF_OK) {
456399ebb4caSwyllys 		goto out;
456499ebb4caSwyllys 	}
456599ebb4caSwyllys 
456699ebb4caSwyllys 	/* Concatenate 3 DES keys into a DES3 key */
456799ebb4caSwyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
456899ebb4caSwyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
456999ebb4caSwyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
457099ebb4caSwyllys 	*des3key = newkey;
457199ebb4caSwyllys 
457299ebb4caSwyllys out:
457399ebb4caSwyllys 	if (deskey1 != NULL)
457499ebb4caSwyllys 		free(deskey1);
457599ebb4caSwyllys 
457699ebb4caSwyllys 	if (deskey2 != NULL)
457799ebb4caSwyllys 		free(deskey2);
457899ebb4caSwyllys 
457999ebb4caSwyllys 	if (deskey3 != NULL)
458099ebb4caSwyllys 		free(deskey3);
458199ebb4caSwyllys 
458299ebb4caSwyllys 	if (ret != KMF_OK && newkey != NULL)
458399ebb4caSwyllys 		free(newkey);
458499ebb4caSwyllys 
458599ebb4caSwyllys 	return (ret);
458699ebb4caSwyllys }
458799ebb4caSwyllys 
458899ebb4caSwyllys KMF_RETURN
458930a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
459030a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
459199ebb4caSwyllys {
459299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
459399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
459499ebb4caSwyllys 	char *fullpath = NULL;
459599ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
459699ebb4caSwyllys 	DES_cblock *deskey = NULL;
459799ebb4caSwyllys 	unsigned char *des3key = NULL;
459899ebb4caSwyllys 	unsigned char *random = NULL;
459999ebb4caSwyllys 	int fd = -1;
460030a5e8faSwyllys 	KMF_KEY_HANDLE *symkey;
460130a5e8faSwyllys 	KMF_KEY_ALG keytype;
460230a5e8faSwyllys 	uint32_t keylen;
460330a5e8faSwyllys 	uint32_t keylen_size = sizeof (keylen);
460430a5e8faSwyllys 	char *dirpath;
460530a5e8faSwyllys 	char *keyfile;
460699ebb4caSwyllys 
460799ebb4caSwyllys 	if (kmfh == NULL)
460899ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
460999ebb4caSwyllys 
461030a5e8faSwyllys 	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
461130a5e8faSwyllys 	if (symkey == NULL)
461299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
461399ebb4caSwyllys 
461430a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
461530a5e8faSwyllys 
461630a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
461730a5e8faSwyllys 	if (keyfile == NULL)
461830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
461930a5e8faSwyllys 
462030a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
462130a5e8faSwyllys 	    (void *)&keytype, NULL);
462230a5e8faSwyllys 	if (ret != KMF_OK)
462330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
462430a5e8faSwyllys 
462530a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
462630a5e8faSwyllys 	    &keylen, &keylen_size);
462730a5e8faSwyllys 	if (ret == KMF_ERR_ATTR_NOT_FOUND &&
462830a5e8faSwyllys 	    (keytype == KMF_DES || keytype == KMF_DES3))
462930a5e8faSwyllys 		/* keylength is not required for DES and 3DES */
463030a5e8faSwyllys 		ret = KMF_OK;
463130a5e8faSwyllys 	if (ret != KMF_OK)
463230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
463330a5e8faSwyllys 
463430a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
463599ebb4caSwyllys 	if (fullpath == NULL)
463699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
463799ebb4caSwyllys 
463899ebb4caSwyllys 	/* If the requested file exists, return an error */
463930a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
464099ebb4caSwyllys 		free(fullpath);
464199ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
464299ebb4caSwyllys 	}
464399ebb4caSwyllys 
464499ebb4caSwyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
464599ebb4caSwyllys 	if (fd == -1) {
464699ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
464799ebb4caSwyllys 		goto out;
464899ebb4caSwyllys 	}
464999ebb4caSwyllys 
465099ebb4caSwyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
465199ebb4caSwyllys 	if (rkey == NULL) {
465299ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
465399ebb4caSwyllys 		goto out;
465499ebb4caSwyllys 	}
465599ebb4caSwyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
465699ebb4caSwyllys 
465730a5e8faSwyllys 	if (keytype == KMF_DES) {
465899ebb4caSwyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
465999ebb4caSwyllys 			goto out;
466099ebb4caSwyllys 		}
466199ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)deskey;
466299ebb4caSwyllys 		rkey->keydata.len = 8;
466399ebb4caSwyllys 
466499ebb4caSwyllys 		symkey->keyalg = KMF_DES;
466599ebb4caSwyllys 
466630a5e8faSwyllys 	} else if (keytype == KMF_DES3) {
466799ebb4caSwyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
466899ebb4caSwyllys 			goto out;
466999ebb4caSwyllys 		}
467099ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)des3key;
467199ebb4caSwyllys 		rkey->keydata.len = DES3_KEY_SIZE;
467299ebb4caSwyllys 		symkey->keyalg = KMF_DES3;
46739b37d296Swyllys 
467430a5e8faSwyllys 	} else if (keytype == KMF_AES || keytype == KMF_RC4 ||
467530a5e8faSwyllys 	    keytype == KMF_GENERIC_SECRET) {
467699ebb4caSwyllys 		int bytes;
467799ebb4caSwyllys 
467830a5e8faSwyllys 		if (keylen % 8 != 0) {
467999ebb4caSwyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
468099ebb4caSwyllys 			goto out;
468199ebb4caSwyllys 		}
468299ebb4caSwyllys 
468330a5e8faSwyllys 		if (keytype == KMF_AES) {
468430a5e8faSwyllys 			if (keylen != 128 &&
468530a5e8faSwyllys 			    keylen != 192 &&
468630a5e8faSwyllys 			    keylen != 256) {
468799ebb4caSwyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
468899ebb4caSwyllys 				goto out;
468999ebb4caSwyllys 			}
469099ebb4caSwyllys 		}
469199ebb4caSwyllys 
469230a5e8faSwyllys 		bytes = keylen/8;
469399ebb4caSwyllys 		random = malloc(bytes);
469499ebb4caSwyllys 		if (random == NULL) {
469599ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
469699ebb4caSwyllys 			goto out;
469799ebb4caSwyllys 		}
469899ebb4caSwyllys 		if (RAND_bytes(random, bytes) != 1) {
469999ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
470099ebb4caSwyllys 			goto out;
470199ebb4caSwyllys 		}
470299ebb4caSwyllys 
470399ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)random;
470499ebb4caSwyllys 		rkey->keydata.len = bytes;
470530a5e8faSwyllys 		symkey->keyalg = keytype;
470699ebb4caSwyllys 
470799ebb4caSwyllys 	} else {
470899ebb4caSwyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
470999ebb4caSwyllys 		goto out;
471099ebb4caSwyllys 	}
471199ebb4caSwyllys 
471299ebb4caSwyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
471399ebb4caSwyllys 
471499ebb4caSwyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
471599ebb4caSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
471699ebb4caSwyllys 	symkey->keylabel = (char *)fullpath;
471799ebb4caSwyllys 	symkey->israw = TRUE;
471899ebb4caSwyllys 	symkey->keyp = rkey;
471999ebb4caSwyllys 
472099ebb4caSwyllys out:
472199ebb4caSwyllys 	if (fd != -1)
472299ebb4caSwyllys 		(void) close(fd);
472399ebb4caSwyllys 
472499ebb4caSwyllys 	if (ret != KMF_OK && fullpath != NULL) {
472599ebb4caSwyllys 		free(fullpath);
472699ebb4caSwyllys 	}
472799ebb4caSwyllys 	if (ret != KMF_OK) {
472830a5e8faSwyllys 		kmf_free_raw_sym_key(rkey);
472999ebb4caSwyllys 		symkey->keyp = NULL;
473099ebb4caSwyllys 		symkey->keyalg = KMF_KEYALG_NONE;
473199ebb4caSwyllys 	}
473299ebb4caSwyllys 
473399ebb4caSwyllys 	return (ret);
473499ebb4caSwyllys }
473599ebb4caSwyllys 
473699ebb4caSwyllys /*
473799ebb4caSwyllys  * Check a file to see if it is a CRL file with PEM or DER format.
473899ebb4caSwyllys  * If success, return its format in the "pformat" argument.
473999ebb4caSwyllys  */
474099ebb4caSwyllys KMF_RETURN
474199ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
474299ebb4caSwyllys {
474399ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
474499ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
474599ebb4caSwyllys 	BIO		*bio = NULL;
474699ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
474799ebb4caSwyllys 
474899ebb4caSwyllys 	if (filename == NULL) {
474999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
475099ebb4caSwyllys 	}
475199ebb4caSwyllys 
475299ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
475399ebb4caSwyllys 	if (bio == NULL)	{
475499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
475599ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
475699ebb4caSwyllys 		goto out;
475799ebb4caSwyllys 	}
475899ebb4caSwyllys 
475999ebb4caSwyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
476099ebb4caSwyllys 		*pformat = KMF_FORMAT_PEM;
476199ebb4caSwyllys 		goto out;
476299ebb4caSwyllys 	}
476399ebb4caSwyllys 	(void) BIO_free(bio);
476499ebb4caSwyllys 
476599ebb4caSwyllys 	/*
476699ebb4caSwyllys 	 * Now try to read it as raw DER data.
476799ebb4caSwyllys 	 */
476899ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
476999ebb4caSwyllys 	if (bio == NULL)	{
477099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
477199ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
477299ebb4caSwyllys 		goto out;
477399ebb4caSwyllys 	}
477499ebb4caSwyllys 
477599ebb4caSwyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
477699ebb4caSwyllys 		*pformat = KMF_FORMAT_ASN1;
477799ebb4caSwyllys 	} else {
477899ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
477999ebb4caSwyllys 	}
478099ebb4caSwyllys 
478199ebb4caSwyllys out:
478299ebb4caSwyllys 	if (bio != NULL)
478399ebb4caSwyllys 		(void) BIO_free(bio);
478499ebb4caSwyllys 
478599ebb4caSwyllys 	if (xcrl != NULL)
478699ebb4caSwyllys 		X509_CRL_free(xcrl);
478799ebb4caSwyllys 
478899ebb4caSwyllys 	return (ret);
478999ebb4caSwyllys }
479099ebb4caSwyllys 
479199ebb4caSwyllys KMF_RETURN
479299ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
479399ebb4caSwyllys     KMF_RAW_SYM_KEY *rkey)
479499ebb4caSwyllys {
479599ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
479699ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
479799ebb4caSwyllys 	KMF_DATA	keyvalue;
479899ebb4caSwyllys 
479999ebb4caSwyllys 	if (kmfh == NULL)
480099ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
480199ebb4caSwyllys 
480299ebb4caSwyllys 	if (symkey == NULL || rkey == NULL)
480399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
480499ebb4caSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
480599ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
480699ebb4caSwyllys 
480799ebb4caSwyllys 	if (symkey->israw) {
480899ebb4caSwyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
480999ebb4caSwyllys 
481099ebb4caSwyllys 		if (rawkey == NULL ||
481199ebb4caSwyllys 		    rawkey->keydata.val == NULL ||
481299ebb4caSwyllys 		    rawkey->keydata.len == 0)
481399ebb4caSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
481499ebb4caSwyllys 
481599ebb4caSwyllys 		rkey->keydata.len = rawkey->keydata.len;
481699ebb4caSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
481799ebb4caSwyllys 			return (KMF_ERR_MEMORY);
481899ebb4caSwyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
481999ebb4caSwyllys 		    rkey->keydata.len);
482099ebb4caSwyllys 	} else {
482130a5e8faSwyllys 		rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
482299ebb4caSwyllys 		if (rv != KMF_OK)
482399ebb4caSwyllys 			return (rv);
482499ebb4caSwyllys 		rkey->keydata.len = keyvalue.Length;
482599ebb4caSwyllys 		rkey->keydata.val = keyvalue.Data;
482699ebb4caSwyllys 	}
482799ebb4caSwyllys 
482899ebb4caSwyllys 	return (rv);
482999ebb4caSwyllys }
483002744e81Swyllys 
483102744e81Swyllys /*
483230a5e8faSwyllys  * substitute for the unsafe access(2) function.
483330a5e8faSwyllys  * If the file in question already exists, return 1.
483430a5e8faSwyllys  * else 0.  If an error occurs during testing (other
483530a5e8faSwyllys  * than EEXIST), return -1.
483630a5e8faSwyllys  */
483730a5e8faSwyllys static int
483830a5e8faSwyllys test_for_file(char *filename, mode_t mode)
483930a5e8faSwyllys {
484030a5e8faSwyllys 	int fd;
484130a5e8faSwyllys 
484230a5e8faSwyllys 	/*
484330a5e8faSwyllys 	 * Try to create the file with the EXCL flag.
484430a5e8faSwyllys 	 * The call should fail if the file exists.
484530a5e8faSwyllys 	 */
484630a5e8faSwyllys 	fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
484730a5e8faSwyllys 	if (fd == -1 && errno == EEXIST)
484830a5e8faSwyllys 		return (1);
484930a5e8faSwyllys 	else if (fd == -1) /* some other error */
485030a5e8faSwyllys 		return (-1);
485130a5e8faSwyllys 
485230a5e8faSwyllys 	/* The file did NOT exist.  Delete the testcase. */
485330a5e8faSwyllys 	(void) close(fd);
485430a5e8faSwyllys 	(void) unlink(filename);
485530a5e8faSwyllys 	return (0);
485630a5e8faSwyllys }
485730a5e8faSwyllys 
485830a5e8faSwyllys KMF_RETURN
485930a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
486030a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
486130a5e8faSwyllys {
486230a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
486330a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
486430a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
486530a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
486630a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
486730a5e8faSwyllys 	KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
486830a5e8faSwyllys 	KMF_CREDENTIAL cred = {NULL, 0};
486930a5e8faSwyllys 	BIO *out = NULL;
487030a5e8faSwyllys 	int keys = 0;
487130a5e8faSwyllys 	char *fullpath = NULL;
487230a5e8faSwyllys 	char *keyfile = NULL;
487330a5e8faSwyllys 	char *dirpath = NULL;
487430a5e8faSwyllys 
487530a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
487630a5e8faSwyllys 	if (pubkey != NULL)
487730a5e8faSwyllys 		keys++;
487830a5e8faSwyllys 
487930a5e8faSwyllys 	prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
488030a5e8faSwyllys 	if (prikey != NULL)
488130a5e8faSwyllys 		keys++;
488230a5e8faSwyllys 
488330a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
488430a5e8faSwyllys 	if (rawkey != NULL)
488530a5e8faSwyllys 		keys++;
488630a5e8faSwyllys 
488730a5e8faSwyllys 	/*
488830a5e8faSwyllys 	 * Exactly 1 type of key must be passed to this function.
488930a5e8faSwyllys 	 */
489030a5e8faSwyllys 	if (keys != 1)
489130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
489230a5e8faSwyllys 
489330a5e8faSwyllys 	keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
489430a5e8faSwyllys 	    numattr);
489530a5e8faSwyllys 	if (keyfile == NULL)
489630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
489730a5e8faSwyllys 
489830a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
489930a5e8faSwyllys 
490030a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
490130a5e8faSwyllys 
490230a5e8faSwyllys 	/* Once we have the full path, we don't need the pieces */
490330a5e8faSwyllys 	if (fullpath == NULL)
490430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
490530a5e8faSwyllys 
490630a5e8faSwyllys 	/* If the requested file exists, return an error */
490730a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
490830a5e8faSwyllys 		free(fullpath);
490930a5e8faSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
491030a5e8faSwyllys 	}
491130a5e8faSwyllys 
491230a5e8faSwyllys 	rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
491330a5e8faSwyllys 	    &format, NULL);
491430a5e8faSwyllys 	if (rv != KMF_OK)
491530a5e8faSwyllys 		/* format is optional. */
491630a5e8faSwyllys 		rv = KMF_OK;
491730a5e8faSwyllys 
491830a5e8faSwyllys 	/* CRED is not required for OpenSSL files */
491930a5e8faSwyllys 	(void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
492030a5e8faSwyllys 	    &cred, NULL);
492130a5e8faSwyllys 
492230a5e8faSwyllys 	/* Store the private key to the keyfile */
492330a5e8faSwyllys 	out = BIO_new_file(fullpath, "wb");
492430a5e8faSwyllys 	if (out == NULL) {
492530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
492630a5e8faSwyllys 		rv = KMF_ERR_OPEN_FILE;
492730a5e8faSwyllys 		goto end;
492830a5e8faSwyllys 	}
492930a5e8faSwyllys 
493030a5e8faSwyllys 	if (prikey != NULL && prikey->keyp != NULL) {
493130a5e8faSwyllys 		if (prikey->keyalg == KMF_RSA ||
493230a5e8faSwyllys 		    prikey->keyalg == KMF_DSA) {
493330a5e8faSwyllys 			pkey = (EVP_PKEY *)prikey->keyp;
493430a5e8faSwyllys 
493530a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
493630a5e8faSwyllys 			    out, &cred, pkey, TRUE);
493730a5e8faSwyllys 
493830a5e8faSwyllys 			if (rv == KMF_OK && prikey->keylabel == NULL) {
493930a5e8faSwyllys 				prikey->keylabel = strdup(fullpath);
494030a5e8faSwyllys 				if (prikey->keylabel == NULL)
494130a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
494230a5e8faSwyllys 			}
494330a5e8faSwyllys 		}
494430a5e8faSwyllys 	} else if (pubkey != NULL && pubkey->keyp != NULL) {
494530a5e8faSwyllys 		if (pubkey->keyalg == KMF_RSA ||
494630a5e8faSwyllys 		    pubkey->keyalg == KMF_DSA) {
494730a5e8faSwyllys 			pkey = (EVP_PKEY *)pubkey->keyp;
494830a5e8faSwyllys 
494930a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
495030a5e8faSwyllys 			    out, &cred, pkey, FALSE);
495130a5e8faSwyllys 
495230a5e8faSwyllys 			if (rv == KMF_OK && pubkey->keylabel == NULL) {
495330a5e8faSwyllys 				pubkey->keylabel = strdup(fullpath);
495430a5e8faSwyllys 				if (pubkey->keylabel == NULL)
495530a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
495630a5e8faSwyllys 			}
495730a5e8faSwyllys 		}
495830a5e8faSwyllys 	} else if (rawkey != NULL) {
495930a5e8faSwyllys 		if (rawkey->keytype == KMF_RSA) {
496030a5e8faSwyllys 			pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
496130a5e8faSwyllys 		} else if (rawkey->keytype == KMF_DSA) {
496230a5e8faSwyllys 			pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
496330a5e8faSwyllys 		} else {
496430a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
496530a5e8faSwyllys 		}
49665b3e1433Swyllys 		if (pkey != NULL) {
496773cc0e02Swyllys 			KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
496873cc0e02Swyllys 
496973cc0e02Swyllys 			rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
497073cc0e02Swyllys 			    (void *)&kclass, NULL);
497173cc0e02Swyllys 			if (rv != KMF_OK)
497273cc0e02Swyllys 				rv = KMF_OK;
49735b3e1433Swyllys 			rv = ssl_write_key(kmfh, format, out,
497473cc0e02Swyllys 			    &cred, pkey, (kclass == KMF_ASYM_PRI));
49755b3e1433Swyllys 			EVP_PKEY_free(pkey);
49765b3e1433Swyllys 		}
497730a5e8faSwyllys 	}
497830a5e8faSwyllys 
497930a5e8faSwyllys end:
498030a5e8faSwyllys 
498130a5e8faSwyllys 	if (out)
498230a5e8faSwyllys 		(void) BIO_free(out);
498330a5e8faSwyllys 
49845b3e1433Swyllys 
498530a5e8faSwyllys 	if (rv == KMF_OK)
498630a5e8faSwyllys 		(void) chmod(fullpath, 0400);
498730a5e8faSwyllys 
498830a5e8faSwyllys 	free(fullpath);
498930a5e8faSwyllys 	return (rv);
499030a5e8faSwyllys }
499130a5e8faSwyllys 
499230a5e8faSwyllys KMF_RETURN
499330a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
499430a5e8faSwyllys {
499530a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
499630a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
499730a5e8faSwyllys 	X509_CRL *xcrl = NULL;
499830a5e8faSwyllys 	X509 *xcert = NULL;
499930a5e8faSwyllys 	EVP_PKEY *pkey;
500030a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
500130a5e8faSwyllys 	BIO *in = NULL, *out = NULL;
500230a5e8faSwyllys 	int openssl_ret = 0;
500330a5e8faSwyllys 	KMF_ENCODE_FORMAT outformat;
500430a5e8faSwyllys 	boolean_t crlcheck = FALSE;
500530a5e8faSwyllys 	char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
500630a5e8faSwyllys 
500730a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
500830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
500930a5e8faSwyllys 	}
501030a5e8faSwyllys 
501130a5e8faSwyllys 	/* CRL check is optional */
501230a5e8faSwyllys 	(void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
501330a5e8faSwyllys 	    &crlcheck, NULL);
501430a5e8faSwyllys 
501530a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
501630a5e8faSwyllys 	if (crlcheck == B_TRUE && certfile == NULL) {
501730a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
501830a5e8faSwyllys 	}
501930a5e8faSwyllys 
502030a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
502130a5e8faSwyllys 	incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
502230a5e8faSwyllys 	outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
502330a5e8faSwyllys 
502430a5e8faSwyllys 	crlfile = get_fullpath(dirpath, incrl);
502530a5e8faSwyllys 
502630a5e8faSwyllys 	if (crlfile == NULL)
502730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
502830a5e8faSwyllys 
502930a5e8faSwyllys 	outcrlfile = get_fullpath(dirpath, outcrl);
503030a5e8faSwyllys 	if (outcrlfile == NULL)
503130a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
503230a5e8faSwyllys 
503330a5e8faSwyllys 	if (isdir(outcrlfile)) {
503430a5e8faSwyllys 		free(outcrlfile);
503530a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
503630a5e8faSwyllys 	}
503730a5e8faSwyllys 
503830a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
503930a5e8faSwyllys 	if (ret != KMF_OK) {
504030a5e8faSwyllys 		free(outcrlfile);
504130a5e8faSwyllys 		return (ret);
504230a5e8faSwyllys 	}
504330a5e8faSwyllys 
504430a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
504530a5e8faSwyllys 	if (in == NULL)	{
504630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
504730a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
504830a5e8faSwyllys 		goto end;
504930a5e8faSwyllys 	}
505030a5e8faSwyllys 
505130a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
505230a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
505330a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
505430a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
505530a5e8faSwyllys 	}
505630a5e8faSwyllys 
505730a5e8faSwyllys 	if (xcrl == NULL) {
505830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
505930a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
506030a5e8faSwyllys 		goto end;
506130a5e8faSwyllys 	}
506230a5e8faSwyllys 
506330a5e8faSwyllys 	/* If bypasscheck is specified, no need to verify. */
506430a5e8faSwyllys 	if (crlcheck == B_FALSE)
506530a5e8faSwyllys 		goto output;
506630a5e8faSwyllys 
506730a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
506830a5e8faSwyllys 	if (ret != KMF_OK)
506930a5e8faSwyllys 		goto end;
507030a5e8faSwyllys 
507130a5e8faSwyllys 	/* Read in the CA cert file and convert to X509 */
507230a5e8faSwyllys 	if (BIO_read_filename(in, certfile) <= 0) {
507330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
507430a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
507530a5e8faSwyllys 		goto end;
507630a5e8faSwyllys 	}
507730a5e8faSwyllys 
507830a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
507930a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
508030a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
508130a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
508230a5e8faSwyllys 	} else {
508330a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
508430a5e8faSwyllys 		goto end;
508530a5e8faSwyllys 	}
508630a5e8faSwyllys 
508730a5e8faSwyllys 	if (xcert == NULL) {
508830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
508930a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
509030a5e8faSwyllys 		goto end;
509130a5e8faSwyllys 	}
509230a5e8faSwyllys 	/* Now get the public key from the CA cert */
509330a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
509430a5e8faSwyllys 	if (pkey == NULL) {
509530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
509630a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
509730a5e8faSwyllys 		goto end;
509830a5e8faSwyllys 	}
509930a5e8faSwyllys 
510030a5e8faSwyllys 	/* Verify the CRL with the CA's public key */
510130a5e8faSwyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
510230a5e8faSwyllys 	EVP_PKEY_free(pkey);
510330a5e8faSwyllys 	if (openssl_ret > 0) {
510430a5e8faSwyllys 		ret = KMF_OK;  /* verify succeed */
510530a5e8faSwyllys 	} else {
510630a5e8faSwyllys 		SET_ERROR(kmfh, openssl_ret);
510730a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
510830a5e8faSwyllys 	}
510930a5e8faSwyllys 
511030a5e8faSwyllys output:
511130a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
511230a5e8faSwyllys 	    &outformat, NULL);
511330a5e8faSwyllys 	if (ret != KMF_OK) {
511430a5e8faSwyllys 		ret = KMF_OK;
511530a5e8faSwyllys 		outformat = KMF_FORMAT_PEM;
511630a5e8faSwyllys 	}
511730a5e8faSwyllys 
511830a5e8faSwyllys 	out = BIO_new_file(outcrlfile, "wb");
511930a5e8faSwyllys 	if (out == NULL) {
512030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
512130a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
512230a5e8faSwyllys 		goto end;
512330a5e8faSwyllys 	}
512430a5e8faSwyllys 
512530a5e8faSwyllys 	if (outformat == KMF_FORMAT_ASN1) {
512630a5e8faSwyllys 		openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
512730a5e8faSwyllys 	} else if (outformat == KMF_FORMAT_PEM) {
512830a5e8faSwyllys 		openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
512930a5e8faSwyllys 	} else {
513030a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
513130a5e8faSwyllys 		goto end;
513230a5e8faSwyllys 	}
513330a5e8faSwyllys 
513430a5e8faSwyllys 	if (openssl_ret <= 0) {
513530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
513630a5e8faSwyllys 		ret = KMF_ERR_WRITE_FILE;
513730a5e8faSwyllys 	} else {
513830a5e8faSwyllys 		ret = KMF_OK;
513930a5e8faSwyllys 	}
514030a5e8faSwyllys 
514130a5e8faSwyllys end:
514230a5e8faSwyllys 	if (xcrl != NULL)
514330a5e8faSwyllys 		X509_CRL_free(xcrl);
514430a5e8faSwyllys 
514530a5e8faSwyllys 	if (xcert != NULL)
514630a5e8faSwyllys 		X509_free(xcert);
514730a5e8faSwyllys 
514830a5e8faSwyllys 	if (in != NULL)
514930a5e8faSwyllys 		(void) BIO_free(in);
515030a5e8faSwyllys 
515130a5e8faSwyllys 	if (out != NULL)
515230a5e8faSwyllys 		(void) BIO_free(out);
515330a5e8faSwyllys 
515430a5e8faSwyllys 	if (outcrlfile != NULL)
515530a5e8faSwyllys 		free(outcrlfile);
515630a5e8faSwyllys 
515730a5e8faSwyllys 	return (ret);
515830a5e8faSwyllys }
515930a5e8faSwyllys 
516030a5e8faSwyllys KMF_RETURN
516130a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
516230a5e8faSwyllys {
516330a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
516430a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
516530a5e8faSwyllys 	X509_CRL   *x = NULL;
516630a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
516730a5e8faSwyllys 	char *crlfile = NULL;
516830a5e8faSwyllys 	BIO *in = NULL;
516930a5e8faSwyllys 	BIO *mem = NULL;
517030a5e8faSwyllys 	long len;
517130a5e8faSwyllys 	char *memptr;
517230a5e8faSwyllys 	char *data = NULL;
517330a5e8faSwyllys 	char **crldata;
517430a5e8faSwyllys 	char *crlfilename, *dirpath;
517530a5e8faSwyllys 
517630a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
517730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
517830a5e8faSwyllys 	}
517930a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
518030a5e8faSwyllys 	    attrlist, numattr);
518130a5e8faSwyllys 	if (crlfilename == NULL)
518230a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
518330a5e8faSwyllys 
518430a5e8faSwyllys 	crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
518530a5e8faSwyllys 	    attrlist, numattr);
518630a5e8faSwyllys 
518730a5e8faSwyllys 	if (crldata == NULL)
518830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
518930a5e8faSwyllys 
519030a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
519130a5e8faSwyllys 
519230a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
519330a5e8faSwyllys 
519430a5e8faSwyllys 	if (crlfile == NULL)
519530a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
519630a5e8faSwyllys 
519730a5e8faSwyllys 	if (isdir(crlfile)) {
519830a5e8faSwyllys 		free(crlfile);
519930a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
520030a5e8faSwyllys 	}
520130a5e8faSwyllys 
520230a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
520330a5e8faSwyllys 	if (ret != KMF_OK) {
520430a5e8faSwyllys 		free(crlfile);
520530a5e8faSwyllys 		return (ret);
520630a5e8faSwyllys 	}
520730a5e8faSwyllys 
520830a5e8faSwyllys 	if (bio_err == NULL)
520930a5e8faSwyllys 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
521030a5e8faSwyllys 
521130a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
521230a5e8faSwyllys 	if (in == NULL)	{
521330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
521430a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
521530a5e8faSwyllys 		goto end;
521630a5e8faSwyllys 	}
521730a5e8faSwyllys 
521830a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
521930a5e8faSwyllys 		x = d2i_X509_CRL_bio(in, NULL);
522030a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
522130a5e8faSwyllys 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
522230a5e8faSwyllys 	}
522330a5e8faSwyllys 
522430a5e8faSwyllys 	if (x == NULL) { /* should not happen */
522530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
522630a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
522730a5e8faSwyllys 		goto end;
522830a5e8faSwyllys 	}
522930a5e8faSwyllys 
523030a5e8faSwyllys 	mem = BIO_new(BIO_s_mem());
523130a5e8faSwyllys 	if (mem == NULL) {
523230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
523330a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
523430a5e8faSwyllys 		goto end;
523530a5e8faSwyllys 	}
523630a5e8faSwyllys 
523730a5e8faSwyllys 	(void) X509_CRL_print(mem, x);
523830a5e8faSwyllys 	len = BIO_get_mem_data(mem, &memptr);
523930a5e8faSwyllys 	if (len <= 0) {
524030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
524130a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
524230a5e8faSwyllys 		goto end;
524330a5e8faSwyllys 	}
524430a5e8faSwyllys 
524530a5e8faSwyllys 	data = malloc(len + 1);
524630a5e8faSwyllys 	if (data == NULL) {
524730a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
524830a5e8faSwyllys 		goto end;
524930a5e8faSwyllys 	}
525030a5e8faSwyllys 
525130a5e8faSwyllys 	(void) memcpy(data, memptr, len);
525230a5e8faSwyllys 	data[len] = '\0';
525330a5e8faSwyllys 	*crldata = data;
525430a5e8faSwyllys 
525530a5e8faSwyllys end:
525630a5e8faSwyllys 	if (x != NULL)
525730a5e8faSwyllys 		X509_CRL_free(x);
525830a5e8faSwyllys 
525930a5e8faSwyllys 	if (crlfile != NULL)
526030a5e8faSwyllys 		free(crlfile);
526130a5e8faSwyllys 
526230a5e8faSwyllys 	if (in != NULL)
526330a5e8faSwyllys 		(void) BIO_free(in);
526430a5e8faSwyllys 
526530a5e8faSwyllys 	if (mem != NULL)
526630a5e8faSwyllys 		(void) BIO_free(mem);
526730a5e8faSwyllys 
526830a5e8faSwyllys 	return (ret);
526930a5e8faSwyllys }
527030a5e8faSwyllys 
527130a5e8faSwyllys KMF_RETURN
527230a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
527330a5e8faSwyllys {
527430a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
527530a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
527630a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
527730a5e8faSwyllys 	char *crlfile = NULL;
527830a5e8faSwyllys 	BIO *in = NULL;
527930a5e8faSwyllys 	char *crlfilename, *dirpath;
528030a5e8faSwyllys 
528130a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
528230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
528330a5e8faSwyllys 	}
528430a5e8faSwyllys 
528530a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
528630a5e8faSwyllys 	    attrlist, numattr);
528730a5e8faSwyllys 
528830a5e8faSwyllys 	if (crlfilename == NULL)
528930a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
529030a5e8faSwyllys 
529130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
529230a5e8faSwyllys 
529330a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
529430a5e8faSwyllys 
529530a5e8faSwyllys 	if (crlfile == NULL)
529630a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
529730a5e8faSwyllys 
529830a5e8faSwyllys 	if (isdir(crlfile)) {
529930a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
530030a5e8faSwyllys 		goto end;
530130a5e8faSwyllys 	}
530230a5e8faSwyllys 
530330a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
530430a5e8faSwyllys 	if (ret != KMF_OK)
530530a5e8faSwyllys 		goto end;
530630a5e8faSwyllys 
530730a5e8faSwyllys 	if (unlink(crlfile) != 0) {
530830a5e8faSwyllys 		SET_SYS_ERROR(kmfh, errno);
530930a5e8faSwyllys 		ret = KMF_ERR_INTERNAL;
531030a5e8faSwyllys 		goto end;
531130a5e8faSwyllys 	}
531230a5e8faSwyllys 
531330a5e8faSwyllys end:
531430a5e8faSwyllys 	if (in != NULL)
531530a5e8faSwyllys 		(void) BIO_free(in);
531630a5e8faSwyllys 	if (crlfile != NULL)
531730a5e8faSwyllys 		free(crlfile);
531830a5e8faSwyllys 
531930a5e8faSwyllys 	return (ret);
532030a5e8faSwyllys }
532130a5e8faSwyllys 
532230a5e8faSwyllys KMF_RETURN
532330a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
532430a5e8faSwyllys {
532530a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
532630a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
532730a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
532830a5e8faSwyllys 	BIO *in = NULL;
532930a5e8faSwyllys 	X509   *xcert = NULL;
533030a5e8faSwyllys 	X509_CRL   *xcrl = NULL;
533130a5e8faSwyllys 	STACK_OF(X509_REVOKED) *revoke_stack = NULL;
533230a5e8faSwyllys 	X509_REVOKED *revoke;
533330a5e8faSwyllys 	int i;
533430a5e8faSwyllys 	char *crlfilename, *crlfile, *dirpath, *certfile;
533530a5e8faSwyllys 
533630a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
533730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
533830a5e8faSwyllys 	}
533930a5e8faSwyllys 
534030a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
534130a5e8faSwyllys 	    attrlist, numattr);
534230a5e8faSwyllys 
534330a5e8faSwyllys 	if (crlfilename == NULL)
534430a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
534530a5e8faSwyllys 
534630a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
534730a5e8faSwyllys 	if (certfile == NULL)
534830a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
534930a5e8faSwyllys 
535030a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
535130a5e8faSwyllys 
535230a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
535330a5e8faSwyllys 
535430a5e8faSwyllys 	if (crlfile == NULL)
535530a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
535630a5e8faSwyllys 
535730a5e8faSwyllys 	if (isdir(crlfile)) {
535830a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
535930a5e8faSwyllys 		goto end;
536030a5e8faSwyllys 	}
536130a5e8faSwyllys 
536230a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
536330a5e8faSwyllys 	if (ret != KMF_OK)
536430a5e8faSwyllys 		goto end;
536530a5e8faSwyllys 
536630a5e8faSwyllys 	/* Read the CRL file and load it into a X509_CRL structure */
536730a5e8faSwyllys 	in = BIO_new_file(crlfilename, "rb");
536830a5e8faSwyllys 	if (in == NULL)	{
536930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
537030a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
537130a5e8faSwyllys 		goto end;
537230a5e8faSwyllys 	}
537330a5e8faSwyllys 
537430a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
537530a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
537630a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
537730a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
537830a5e8faSwyllys 	}
537930a5e8faSwyllys 
538030a5e8faSwyllys 	if (xcrl == NULL) {
538130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
538230a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
538330a5e8faSwyllys 		goto end;
538430a5e8faSwyllys 	}
538530a5e8faSwyllys 	(void) BIO_free(in);
538630a5e8faSwyllys 
538730a5e8faSwyllys 	/* Read the Certificate file and load it into a X509 structure */
538830a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
538930a5e8faSwyllys 	if (ret != KMF_OK)
539030a5e8faSwyllys 		goto end;
539130a5e8faSwyllys 
539230a5e8faSwyllys 	in = BIO_new_file(certfile, "rb");
539330a5e8faSwyllys 	if (in == NULL)	{
539430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
539530a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
539630a5e8faSwyllys 		goto end;
539730a5e8faSwyllys 	}
539830a5e8faSwyllys 
539930a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
540030a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
540130a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
540230a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
540330a5e8faSwyllys 	}
540430a5e8faSwyllys 
540530a5e8faSwyllys 	if (xcert == NULL) {
540630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
540730a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
540830a5e8faSwyllys 		goto end;
540930a5e8faSwyllys 	}
541030a5e8faSwyllys 
541130a5e8faSwyllys 	/* Check if the certificate and the CRL have same issuer */
541230a5e8faSwyllys 	if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) {
541330a5e8faSwyllys 		ret = KMF_ERR_ISSUER;
541430a5e8faSwyllys 		goto end;
541530a5e8faSwyllys 	}
541630a5e8faSwyllys 
541730a5e8faSwyllys 	/* Check to see if the certificate serial number is revoked */
541830a5e8faSwyllys 	revoke_stack = X509_CRL_get_REVOKED(xcrl);
541930a5e8faSwyllys 	if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
542030a5e8faSwyllys 		/* No revoked certificates in the CRL file */
542130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
542230a5e8faSwyllys 		ret = KMF_ERR_EMPTY_CRL;
542330a5e8faSwyllys 		goto end;
542430a5e8faSwyllys 	}
542530a5e8faSwyllys 
542630a5e8faSwyllys 	for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
5427a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
542830a5e8faSwyllys 		revoke = sk_X509_REVOKED_value(revoke_stack, i);
542930a5e8faSwyllys 		if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber,
543030a5e8faSwyllys 		    revoke->serialNumber) == 0) {
543130a5e8faSwyllys 			break;
543230a5e8faSwyllys 		}
543330a5e8faSwyllys 	}
543430a5e8faSwyllys 
543530a5e8faSwyllys 	if (i < sk_X509_REVOKED_num(revoke_stack)) {
543630a5e8faSwyllys 		ret = KMF_OK;
543730a5e8faSwyllys 	} else {
543830a5e8faSwyllys 		ret = KMF_ERR_NOT_REVOKED;
543930a5e8faSwyllys 	}
544030a5e8faSwyllys 
544130a5e8faSwyllys end:
544230a5e8faSwyllys 	if (in != NULL)
544330a5e8faSwyllys 		(void) BIO_free(in);
544430a5e8faSwyllys 	if (xcrl != NULL)
544530a5e8faSwyllys 		X509_CRL_free(xcrl);
544630a5e8faSwyllys 	if (xcert != NULL)
544730a5e8faSwyllys 		X509_free(xcert);
544830a5e8faSwyllys 
544930a5e8faSwyllys 	return (ret);
545030a5e8faSwyllys }
545130a5e8faSwyllys 
545230a5e8faSwyllys KMF_RETURN
545330a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
545430a5e8faSwyllys {
545530a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
545630a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
545730a5e8faSwyllys 	BIO		*bcrl = NULL;
545830a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
545930a5e8faSwyllys 	X509		*xcert = NULL;
546030a5e8faSwyllys 	EVP_PKEY	*pkey;
546130a5e8faSwyllys 	int		sslret;
546230a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
546330a5e8faSwyllys 	unsigned char	*p;
546430a5e8faSwyllys 	long		len;
546530a5e8faSwyllys 
546630a5e8faSwyllys 	if (handle == NULL || crlname == NULL || tacert == NULL) {
546730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
546830a5e8faSwyllys 	}
546930a5e8faSwyllys 
547030a5e8faSwyllys 	ret = kmf_get_file_format(crlname, &crl_format);
547130a5e8faSwyllys 	if (ret != KMF_OK)
547230a5e8faSwyllys 		return (ret);
547330a5e8faSwyllys 
547430a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
547530a5e8faSwyllys 	if (bcrl == NULL)	{
547630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
547730a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
547830a5e8faSwyllys 		goto cleanup;
547930a5e8faSwyllys 	}
548030a5e8faSwyllys 
548130a5e8faSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
548230a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
548330a5e8faSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
548430a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
548530a5e8faSwyllys 	} else {
548630a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
548730a5e8faSwyllys 		goto cleanup;
548830a5e8faSwyllys 	}
548930a5e8faSwyllys 
549030a5e8faSwyllys 	if (xcrl == NULL) {
549130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
549230a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
549330a5e8faSwyllys 		goto cleanup;
549430a5e8faSwyllys 	}
549530a5e8faSwyllys 
549630a5e8faSwyllys 	p = tacert->Data;
549730a5e8faSwyllys 	len = tacert->Length;
549830a5e8faSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
549930a5e8faSwyllys 
550030a5e8faSwyllys 	if (xcert == NULL) {
550130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
550230a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
550330a5e8faSwyllys 		goto cleanup;
550430a5e8faSwyllys 	}
550530a5e8faSwyllys 
550630a5e8faSwyllys 	/* Get issuer certificate public key */
550730a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
550830a5e8faSwyllys 	if (pkey == NULL) {
550930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
551030a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
551130a5e8faSwyllys 		goto cleanup;
551230a5e8faSwyllys 	}
551330a5e8faSwyllys 
551430a5e8faSwyllys 	/* Verify CRL signature */
551530a5e8faSwyllys 	sslret = X509_CRL_verify(xcrl, pkey);
551630a5e8faSwyllys 	EVP_PKEY_free(pkey);
551730a5e8faSwyllys 	if (sslret > 0) {
551830a5e8faSwyllys 		ret = KMF_OK;
551930a5e8faSwyllys 	} else {
552030a5e8faSwyllys 		SET_ERROR(kmfh, sslret);
552130a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
552230a5e8faSwyllys 	}
552330a5e8faSwyllys 
552430a5e8faSwyllys cleanup:
552530a5e8faSwyllys 	if (bcrl != NULL)
552630a5e8faSwyllys 		(void) BIO_free(bcrl);
552730a5e8faSwyllys 
552830a5e8faSwyllys 	if (xcrl != NULL)
552930a5e8faSwyllys 		X509_CRL_free(xcrl);
553030a5e8faSwyllys 
553130a5e8faSwyllys 	if (xcert != NULL)
553230a5e8faSwyllys 		X509_free(xcert);
553330a5e8faSwyllys 
553430a5e8faSwyllys 	return (ret);
553530a5e8faSwyllys 
553630a5e8faSwyllys }
553730a5e8faSwyllys 
553830a5e8faSwyllys KMF_RETURN
553930a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
554030a5e8faSwyllys {
554130a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
554230a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
554330a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
554430a5e8faSwyllys 	BIO		*bcrl = NULL;
554530a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
554630a5e8faSwyllys 	int		i;
554730a5e8faSwyllys 
554830a5e8faSwyllys 	if (handle == NULL || crlname == NULL) {
554930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
555030a5e8faSwyllys 	}
555130a5e8faSwyllys 
555230a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlname, &crl_format);
555330a5e8faSwyllys 	if (ret != KMF_OK)
555430a5e8faSwyllys 		return (ret);
555530a5e8faSwyllys 
555630a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
555730a5e8faSwyllys 	if (bcrl == NULL) {
555830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
555930a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
556030a5e8faSwyllys 		goto cleanup;
556130a5e8faSwyllys 	}
556230a5e8faSwyllys 
55635b3e1433Swyllys 	if (crl_format == KMF_FORMAT_ASN1)
556430a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
55655b3e1433Swyllys 	else if (crl_format == KMF_FORMAT_PEM)
556630a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
556730a5e8faSwyllys 
556830a5e8faSwyllys 	if (xcrl == NULL) {
556930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
557030a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
557130a5e8faSwyllys 		goto cleanup;
557230a5e8faSwyllys 	}
557330a5e8faSwyllys 	i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL);
557430a5e8faSwyllys 	if (i >= 0) {
557530a5e8faSwyllys 		ret = KMF_ERR_VALIDITY_PERIOD;
557630a5e8faSwyllys 		goto cleanup;
557730a5e8faSwyllys 	}
557830a5e8faSwyllys 	if (X509_CRL_get_nextUpdate(xcrl)) {
557930a5e8faSwyllys 		i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL);
558030a5e8faSwyllys 
558130a5e8faSwyllys 		if (i <= 0) {
558230a5e8faSwyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
558330a5e8faSwyllys 			goto cleanup;
558430a5e8faSwyllys 		}
558530a5e8faSwyllys 	}
558630a5e8faSwyllys 
558730a5e8faSwyllys 	ret = KMF_OK;
558830a5e8faSwyllys 
558930a5e8faSwyllys cleanup:
559030a5e8faSwyllys 	if (bcrl != NULL)
559130a5e8faSwyllys 		(void) BIO_free(bcrl);
559230a5e8faSwyllys 
559330a5e8faSwyllys 	if (xcrl != NULL)
559430a5e8faSwyllys 		X509_CRL_free(xcrl);
559530a5e8faSwyllys 
559630a5e8faSwyllys 	return (ret);
559730a5e8faSwyllys }
5598