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 /*
770f9559bSTheo Schlossnagle  * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
870f9559bSTheo Schlossnagle  */
970f9559bSTheo 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 /*
138*bf5d9f18SAndy Fiddaman  * Declare some new macros for managing stacks of EVP_PKEYS.
1395b3e1433Swyllys  */
1405b3e1433Swyllys DECLARE_STACK_OF(EVP_PKEY)
1415b3e1433Swyllys 
1425b3e1433Swyllys #define	sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
1435b3e1433Swyllys #define	sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
1445b3e1433Swyllys #define	sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
1455b3e1433Swyllys #define	sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
1465b3e1433Swyllys #define	sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
1475b3e1433Swyllys #define	sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
1485b3e1433Swyllys 	(free_func))
1495b3e1433Swyllys 
15099ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX;
15199ebb4caSwyllys static int ssl_initialized = 0;
15230a5e8faSwyllys static BIO *bio_err = NULL;
15330a5e8faSwyllys 
15430a5e8faSwyllys static int
15530a5e8faSwyllys test_for_file(char *, mode_t);
1565b3e1433Swyllys static KMF_RETURN
1575b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *, char *, int,
1585b3e1433Swyllys     STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
1595b3e1433Swyllys 
1605b3e1433Swyllys static KMF_RETURN
1615b3e1433Swyllys local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *,
1625b3e1433Swyllys     int, KMF_KEY_HANDLE *, char *);
1635b3e1433Swyllys 
1645b3e1433Swyllys static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int);
16599ebb4caSwyllys 
16671593db2Swyllys static KMF_RETURN
16730a5e8faSwyllys extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *,
16802744e81Swyllys     CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
16971593db2Swyllys 
17071593db2Swyllys static KMF_RETURN
17130a5e8faSwyllys kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
17230a5e8faSwyllys     char *, KMF_DATA *);
17330a5e8faSwyllys 
17430a5e8faSwyllys static KMF_RETURN
17530a5e8faSwyllys load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
17630a5e8faSwyllys     char *, KMF_DATA **, uint32_t *);
17771593db2Swyllys 
17802744e81Swyllys static KMF_RETURN
17902744e81Swyllys sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
18002744e81Swyllys 
18102744e81Swyllys static EVP_PKEY *
18202744e81Swyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *);
18302744e81Swyllys 
18430a5e8faSwyllys static KMF_RETURN
18530a5e8faSwyllys convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
18630a5e8faSwyllys 
18799ebb4caSwyllys KMF_RETURN
18830a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
18999ebb4caSwyllys 
19099ebb4caSwyllys void
19199ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
19299ebb4caSwyllys 
19399ebb4caSwyllys KMF_RETURN
19430a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
19599ebb4caSwyllys 
19699ebb4caSwyllys KMF_RETURN
19730a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
19899ebb4caSwyllys 
19999ebb4caSwyllys KMF_RETURN
20030a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20130a5e8faSwyllys 
20230a5e8faSwyllys KMF_RETURN
20330a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20499ebb4caSwyllys 
20599ebb4caSwyllys KMF_RETURN
20699ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T,  KMF_KEY_HANDLE *, KMF_DATA *);
20799ebb4caSwyllys 
20899ebb4caSwyllys KMF_RETURN
20999ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
21099ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
21199ebb4caSwyllys 
21299ebb4caSwyllys KMF_RETURN
21330a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21499ebb4caSwyllys 
21599ebb4caSwyllys KMF_RETURN
21630a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21799ebb4caSwyllys 
21899ebb4caSwyllys KMF_RETURN
21930a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22099ebb4caSwyllys 
22199ebb4caSwyllys KMF_RETURN
22230a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22399ebb4caSwyllys 
22499ebb4caSwyllys KMF_RETURN
22530a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22699ebb4caSwyllys 
22799ebb4caSwyllys KMF_RETURN
22899ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
22999ebb4caSwyllys 	KMF_PRINTABLE_ITEM, char *);
23099ebb4caSwyllys 
23199ebb4caSwyllys KMF_RETURN
23299ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
23399ebb4caSwyllys 
23499ebb4caSwyllys KMF_RETURN
23530a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23699ebb4caSwyllys 
23799ebb4caSwyllys KMF_RETURN
23899ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
23999ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
24099ebb4caSwyllys 
24199ebb4caSwyllys KMF_RETURN
24230a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24399ebb4caSwyllys 
24499ebb4caSwyllys KMF_RETURN
24530a5e8faSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24699ebb4caSwyllys 
24799ebb4caSwyllys KMF_RETURN
24830a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24999ebb4caSwyllys 
25099ebb4caSwyllys KMF_RETURN
25130a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25299ebb4caSwyllys 
25399ebb4caSwyllys KMF_RETURN
25430a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25599ebb4caSwyllys 
25699ebb4caSwyllys KMF_RETURN
25799ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
25899ebb4caSwyllys 
25999ebb4caSwyllys KMF_RETURN
26030a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
26199ebb4caSwyllys 
26299ebb4caSwyllys KMF_RETURN
26330a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
26499ebb4caSwyllys 
26599ebb4caSwyllys static
26699ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table =
26799ebb4caSwyllys {
26899ebb4caSwyllys 	1,				/* Version */
26999ebb4caSwyllys 	NULL, /* ConfigureKeystore */
27099ebb4caSwyllys 	OpenSSL_FindCert,
27199ebb4caSwyllys 	OpenSSL_FreeKMFCert,
27299ebb4caSwyllys 	OpenSSL_StoreCert,
27399ebb4caSwyllys 	NULL, /* ImportCert */
27499ebb4caSwyllys 	OpenSSL_ImportCRL,
27599ebb4caSwyllys 	OpenSSL_DeleteCert,
27699ebb4caSwyllys 	OpenSSL_DeleteCRL,
27799ebb4caSwyllys 	OpenSSL_CreateKeypair,
27899ebb4caSwyllys 	OpenSSL_FindKey,
27999ebb4caSwyllys 	OpenSSL_EncodePubKeyData,
28099ebb4caSwyllys 	OpenSSL_SignData,
28199ebb4caSwyllys 	OpenSSL_DeleteKey,
28299ebb4caSwyllys 	OpenSSL_ListCRL,
28399ebb4caSwyllys 	NULL,	/* FindCRL */
28499ebb4caSwyllys 	OpenSSL_FindCertInCRL,
28599ebb4caSwyllys 	OpenSSL_GetErrorString,
28630a5e8faSwyllys 	OpenSSL_FindPrikeyByCert,
28799ebb4caSwyllys 	OpenSSL_DecryptData,
28830a5e8faSwyllys 	OpenSSL_ExportPK12,
28999ebb4caSwyllys 	OpenSSL_CreateSymKey,
29099ebb4caSwyllys 	OpenSSL_GetSymKeyValue,
29199ebb4caSwyllys 	NULL,	/* SetTokenPin */
29230a5e8faSwyllys 	OpenSSL_StoreKey,
29399ebb4caSwyllys 	NULL	/* Finalize */
29499ebb4caSwyllys };
29599ebb4caSwyllys 
29699ebb4caSwyllys static mutex_t *lock_cs;
29799ebb4caSwyllys static long *lock_count;
29899ebb4caSwyllys 
29999ebb4caSwyllys static void
300a2d4930dSDan OpenSolaris Anderson /* ARGSUSED1 */
30199ebb4caSwyllys locking_cb(int mode, int type, char *file, int line)
30299ebb4caSwyllys {
30399ebb4caSwyllys 	if (mode & CRYPTO_LOCK) {
30499ebb4caSwyllys 		(void) mutex_lock(&(lock_cs[type]));
30599ebb4caSwyllys 		lock_count[type]++;
30699ebb4caSwyllys 	} else {
30799ebb4caSwyllys 		(void) mutex_unlock(&(lock_cs[type]));
30899ebb4caSwyllys 	}
30999ebb4caSwyllys }
31099ebb4caSwyllys 
31199ebb4caSwyllys static unsigned long
31299ebb4caSwyllys thread_id()
31399ebb4caSwyllys {
31499ebb4caSwyllys 	return ((unsigned long)thr_self());
31599ebb4caSwyllys }
31699ebb4caSwyllys 
31799ebb4caSwyllys KMF_PLUGIN_FUNCLIST *
31899ebb4caSwyllys KMF_Plugin_Initialize()
31999ebb4caSwyllys {
32099ebb4caSwyllys 	int i;
32199ebb4caSwyllys 
32299ebb4caSwyllys 	(void) mutex_lock(&init_lock);
32399ebb4caSwyllys 	if (!ssl_initialized) {
32499ebb4caSwyllys 		/*
32599ebb4caSwyllys 		 * Add support for extension OIDs that are not yet in the
32699ebb4caSwyllys 		 * openssl default set.
32799ebb4caSwyllys 		 */
32899ebb4caSwyllys 		(void) OBJ_create("2.5.29.30", "nameConstraints",
32999ebb4caSwyllys 		    "X509v3 Name Constraints");
33099ebb4caSwyllys 		(void) OBJ_create("2.5.29.33", "policyMappings",
33199ebb4caSwyllys 		    "X509v3 Policy Mappings");
33299ebb4caSwyllys 		(void) OBJ_create("2.5.29.36", "policyConstraints",
33399ebb4caSwyllys 		    "X509v3 Policy Constraints");
33499ebb4caSwyllys 		(void) OBJ_create("2.5.29.46", "freshestCRL",
33599ebb4caSwyllys 		    "X509v3 Freshest CRL");
33699ebb4caSwyllys 		(void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
33799ebb4caSwyllys 		    "X509v3 Inhibit Any-Policy");
33899ebb4caSwyllys 		/*
33999ebb4caSwyllys 		 * Set up for thread-safe operation.
34099ebb4caSwyllys 		 */
34199ebb4caSwyllys 		lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
34299ebb4caSwyllys 		if (lock_cs == NULL) {
34399ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
34499ebb4caSwyllys 			return (NULL);
34599ebb4caSwyllys 		}
34699ebb4caSwyllys 
34799ebb4caSwyllys 		lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
34899ebb4caSwyllys 		if (lock_count == NULL) {
34999ebb4caSwyllys 			OPENSSL_free(lock_cs);
35099ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
35199ebb4caSwyllys 			return (NULL);
35299ebb4caSwyllys 		}
35399ebb4caSwyllys 
35499ebb4caSwyllys 		for (i = 0; i < CRYPTO_num_locks(); i++) {
35599ebb4caSwyllys 			lock_count[i] = 0;
35699ebb4caSwyllys 			(void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
35799ebb4caSwyllys 		}
35899ebb4caSwyllys 
35999ebb4caSwyllys 		CRYPTO_set_id_callback((unsigned long (*)())thread_id);
3602c9a247fSWyllys Ingersoll 		if (CRYPTO_get_locking_callback() == NULL)
36199ebb4caSwyllys 			CRYPTO_set_locking_callback((void (*)())locking_cb);
3622c9a247fSWyllys Ingersoll 
3632c9a247fSWyllys Ingersoll 		OpenSSL_add_all_algorithms();
3642c9a247fSWyllys Ingersoll 
3652c9a247fSWyllys Ingersoll 		/* Enable error strings for reporting */
3662c9a247fSWyllys Ingersoll 		ERR_load_crypto_strings();
3672c9a247fSWyllys Ingersoll 
36899ebb4caSwyllys 		ssl_initialized = 1;
36999ebb4caSwyllys 	}
37099ebb4caSwyllys 	(void) mutex_unlock(&init_lock);
37199ebb4caSwyllys 
37299ebb4caSwyllys 	return (&openssl_plugin_table);
37399ebb4caSwyllys }
37499ebb4caSwyllys /*
37599ebb4caSwyllys  * Convert an SSL DN to a KMF DN.
37699ebb4caSwyllys  */
37799ebb4caSwyllys static KMF_RETURN
37899ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
37999ebb4caSwyllys {
38099ebb4caSwyllys 	KMF_DATA derdata;
38199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
38299ebb4caSwyllys 	uchar_t *tmp;
38399ebb4caSwyllys 
38499ebb4caSwyllys 	/* Convert to raw DER format */
38599ebb4caSwyllys 	derdata.Length = i2d_X509_NAME(sslDN, NULL);
38699ebb4caSwyllys 	if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
38799ebb4caSwyllys 	    == NULL) {
38899ebb4caSwyllys 		return (KMF_ERR_MEMORY);
38999ebb4caSwyllys 	}
39099ebb4caSwyllys 	(void) i2d_X509_NAME(sslDN, &tmp);
39199ebb4caSwyllys 
39299ebb4caSwyllys 	/* Decode to KMF format */
39399ebb4caSwyllys 	rv = DerDecodeName(&derdata, kmfDN);
39499ebb4caSwyllys 	if (rv != KMF_OK) {
39599ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
39699ebb4caSwyllys 	}
39799ebb4caSwyllys 	OPENSSL_free(derdata.Data);
39899ebb4caSwyllys 
39999ebb4caSwyllys 	return (rv);
40099ebb4caSwyllys }
40199ebb4caSwyllys 
40230a5e8faSwyllys int
40399ebb4caSwyllys isdir(char *path)
40499ebb4caSwyllys {
40599ebb4caSwyllys 	struct stat s;
40699ebb4caSwyllys 
40799ebb4caSwyllys 	if (stat(path, &s) == -1)
40899ebb4caSwyllys 		return (0);
40999ebb4caSwyllys 
41030a5e8faSwyllys 	return ((s.st_mode & S_IFMT) == S_IFDIR);
41199ebb4caSwyllys }
41299ebb4caSwyllys 
41399ebb4caSwyllys static KMF_RETURN
41499ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
41599ebb4caSwyllys {
41699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
41799ebb4caSwyllys 	unsigned char *buf = NULL, *p;
41899ebb4caSwyllys 	int len;
41999ebb4caSwyllys 
42099ebb4caSwyllys 	/*
42199ebb4caSwyllys 	 * Convert the X509 internal struct to DER encoded data
42299ebb4caSwyllys 	 */
42399ebb4caSwyllys 	if ((len = i2d_X509(x509cert, NULL)) < 0) {
42499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
42599ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
42699ebb4caSwyllys 		goto cleanup;
42799ebb4caSwyllys 	}
42899ebb4caSwyllys 	if ((buf = malloc(len)) == NULL) {
42999ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
43099ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
43199ebb4caSwyllys 		goto cleanup;
43299ebb4caSwyllys 	}
43399ebb4caSwyllys 
43499ebb4caSwyllys 	/*
43599ebb4caSwyllys 	 * i2d_X509 will increment the buf pointer so that we need to
43699ebb4caSwyllys 	 * save it.
43799ebb4caSwyllys 	 */
43899ebb4caSwyllys 	p = buf;
43999ebb4caSwyllys 	if ((len = i2d_X509(x509cert, &p)) < 0) {
44099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
44199ebb4caSwyllys 		free(buf);
44299ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
44399ebb4caSwyllys 		goto cleanup;
44499ebb4caSwyllys 	}
44599ebb4caSwyllys 
44699ebb4caSwyllys 	/* caller's responsibility to free it */
44799ebb4caSwyllys 	cert->Data = buf;
44899ebb4caSwyllys 	cert->Length = len;
44999ebb4caSwyllys 
45099ebb4caSwyllys cleanup:
45199ebb4caSwyllys 	if (rv != KMF_OK) {
45299ebb4caSwyllys 		if (buf)
45399ebb4caSwyllys 			free(buf);
45499ebb4caSwyllys 		cert->Data = NULL;
45599ebb4caSwyllys 		cert->Length = 0;
45699ebb4caSwyllys 	}
45799ebb4caSwyllys 
45899ebb4caSwyllys 	return (rv);
45999ebb4caSwyllys }
46099ebb4caSwyllys 
46130a5e8faSwyllys 
46299ebb4caSwyllys static KMF_RETURN
46330a5e8faSwyllys check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
46430a5e8faSwyllys     boolean_t *match)
46599ebb4caSwyllys {
46699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
46799ebb4caSwyllys 	boolean_t findIssuer = FALSE;
46899ebb4caSwyllys 	boolean_t findSubject = FALSE;
46999ebb4caSwyllys 	boolean_t findSerial = FALSE;
47099ebb4caSwyllys 	KMF_X509_NAME issuerDN, subjectDN;
47199ebb4caSwyllys 	KMF_X509_NAME certIssuerDN, certSubjectDN;
47299ebb4caSwyllys 
47399ebb4caSwyllys 	*match = FALSE;
47499ebb4caSwyllys 	if (xcert == NULL) {
47599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
47699ebb4caSwyllys 	}
47799ebb4caSwyllys 
47899ebb4caSwyllys 	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
47999ebb4caSwyllys 	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
48099ebb4caSwyllys 	(void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
48199ebb4caSwyllys 	(void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
48299ebb4caSwyllys 
48330a5e8faSwyllys 	if (issuer != NULL && strlen(issuer)) {
48430a5e8faSwyllys 		rv = kmf_dn_parser(issuer, &issuerDN);
48599ebb4caSwyllys 		if (rv != KMF_OK)
48699ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
48799ebb4caSwyllys 
48899ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->issuer, &certIssuerDN);
48999ebb4caSwyllys 		if (rv != KMF_OK) {
49030a5e8faSwyllys 			kmf_free_dn(&issuerDN);
49199ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
49299ebb4caSwyllys 		}
49399ebb4caSwyllys 
49499ebb4caSwyllys 		findIssuer = TRUE;
49599ebb4caSwyllys 	}
49630a5e8faSwyllys 	if (subject != NULL && strlen(subject)) {
49730a5e8faSwyllys 		rv = kmf_dn_parser(subject, &subjectDN);
49899ebb4caSwyllys 		if (rv != KMF_OK) {
49999ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
50099ebb4caSwyllys 			goto cleanup;
50199ebb4caSwyllys 		}
50299ebb4caSwyllys 
50399ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->subject, &certSubjectDN);
50499ebb4caSwyllys 		if (rv != KMF_OK) {
50599ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
50699ebb4caSwyllys 			goto cleanup;
50799ebb4caSwyllys 		}
50899ebb4caSwyllys 		findSubject = TRUE;
50999ebb4caSwyllys 	}
51030a5e8faSwyllys 	if (serial != NULL && serial->val != NULL)
51199ebb4caSwyllys 		findSerial = TRUE;
51299ebb4caSwyllys 
51399ebb4caSwyllys 	if (findSerial) {
51499ebb4caSwyllys 		BIGNUM *bn;
51599ebb4caSwyllys 
51699ebb4caSwyllys 		/* Comparing BIGNUMs is a pain! */
51799ebb4caSwyllys 		bn = ASN1_INTEGER_to_BN(xcert->cert_info->serialNumber, NULL);
51899ebb4caSwyllys 		if (bn != NULL) {
51999ebb4caSwyllys 			int bnlen = BN_num_bytes(bn);
52099ebb4caSwyllys 
52130a5e8faSwyllys 			if (bnlen == serial->len) {
52299ebb4caSwyllys 				uchar_t *a = malloc(bnlen);
52399ebb4caSwyllys 				if (a == NULL) {
52499ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
52599ebb4caSwyllys 					BN_free(bn);
52699ebb4caSwyllys 					goto cleanup;
52799ebb4caSwyllys 				}
52899ebb4caSwyllys 				bnlen = BN_bn2bin(bn, a);
52930a5e8faSwyllys 				*match = (memcmp(a, serial->val, serial->len) ==
53030a5e8faSwyllys 				    0);
53199ebb4caSwyllys 				rv = KMF_OK;
53299ebb4caSwyllys 				free(a);
53399ebb4caSwyllys 			}
53499ebb4caSwyllys 			BN_free(bn);
53599ebb4caSwyllys 			if (!(*match))
53699ebb4caSwyllys 				goto cleanup;
53799ebb4caSwyllys 		} else {
53899ebb4caSwyllys 			rv = KMF_OK;
53999ebb4caSwyllys 			goto cleanup;
54099ebb4caSwyllys 		}
54199ebb4caSwyllys 	}
54299ebb4caSwyllys 	if (findIssuer) {
54330a5e8faSwyllys 		*match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
54430a5e8faSwyllys 		if ((*match) == B_FALSE) {
54530a5e8faSwyllys 			/* stop checking and bail */
54699ebb4caSwyllys 			rv = KMF_OK;
54799ebb4caSwyllys 			goto cleanup;
54899ebb4caSwyllys 		}
54999ebb4caSwyllys 	}
55099ebb4caSwyllys 	if (findSubject) {
55130a5e8faSwyllys 		*match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
55230a5e8faSwyllys 		if ((*match) == B_FALSE) {
55330a5e8faSwyllys 			/* stop checking and bail */
55499ebb4caSwyllys 			rv = KMF_OK;
55599ebb4caSwyllys 			goto cleanup;
55699ebb4caSwyllys 		}
55799ebb4caSwyllys 	}
55899ebb4caSwyllys 
55999ebb4caSwyllys 	*match = TRUE;
56099ebb4caSwyllys cleanup:
56199ebb4caSwyllys 	if (findIssuer) {
56230a5e8faSwyllys 		kmf_free_dn(&issuerDN);
56330a5e8faSwyllys 		kmf_free_dn(&certIssuerDN);
56499ebb4caSwyllys 	}
56599ebb4caSwyllys 	if (findSubject) {
56630a5e8faSwyllys 		kmf_free_dn(&subjectDN);
56730a5e8faSwyllys 		kmf_free_dn(&certSubjectDN);
56899ebb4caSwyllys 	}
56999ebb4caSwyllys 
57099ebb4caSwyllys 	return (rv);
57199ebb4caSwyllys }
57299ebb4caSwyllys 
57330a5e8faSwyllys 
57430a5e8faSwyllys /*
57530a5e8faSwyllys  * This function loads a certificate file into an X509 data structure, and
57630a5e8faSwyllys  * checks if its issuer, subject or the serial number matches with those
57730a5e8faSwyllys  * values.  If it matches, then return the X509 data structure.
57830a5e8faSwyllys  */
57999ebb4caSwyllys static KMF_RETURN
58099ebb4caSwyllys load_X509cert(KMF_HANDLE *kmfh,
58130a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
58230a5e8faSwyllys     char *pathname, X509 **outcert)
58399ebb4caSwyllys {
58499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
58599ebb4caSwyllys 	X509 *xcert = NULL;
58699ebb4caSwyllys 	BIO *bcert = NULL;
58799ebb4caSwyllys 	boolean_t  match = FALSE;
58899ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
58999ebb4caSwyllys 
59099ebb4caSwyllys 	/*
59199ebb4caSwyllys 	 * auto-detect the file format, regardless of what
59299ebb4caSwyllys 	 * the 'format' parameters in the params say.
59399ebb4caSwyllys 	 */
59430a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
59599ebb4caSwyllys 	if (rv != KMF_OK) {
59699ebb4caSwyllys 		if (rv == KMF_ERR_OPEN_FILE)
59799ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
59899ebb4caSwyllys 		return (rv);
59999ebb4caSwyllys 	}
60099ebb4caSwyllys 
60199ebb4caSwyllys 	/* Not ASN1(DER) format */
60299ebb4caSwyllys 	if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
60399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
60499ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
60599ebb4caSwyllys 		goto cleanup;
60699ebb4caSwyllys 	}
60799ebb4caSwyllys 
60899ebb4caSwyllys 	if (format == KMF_FORMAT_PEM)
60999ebb4caSwyllys 		xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
61099ebb4caSwyllys 	else if (format == KMF_FORMAT_ASN1)
61199ebb4caSwyllys 		xcert = d2i_X509_bio(bcert, NULL);
61299ebb4caSwyllys 	else if (format == KMF_FORMAT_PKCS12) {
61399ebb4caSwyllys 		PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
61499ebb4caSwyllys 		if (p12 != NULL) {
61599ebb4caSwyllys 			(void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
61699ebb4caSwyllys 			PKCS12_free(p12);
61799ebb4caSwyllys 			p12 = NULL;
61899ebb4caSwyllys 		} else {
61999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
62099ebb4caSwyllys 			rv = KMF_ERR_BAD_CERT_FORMAT;
62199ebb4caSwyllys 		}
62299ebb4caSwyllys 	} else {
62399ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
62499ebb4caSwyllys 		goto cleanup;
62599ebb4caSwyllys 	}
62699ebb4caSwyllys 
62799ebb4caSwyllys 	if (xcert == NULL) {
62899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
62999ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
63099ebb4caSwyllys 		goto cleanup;
63199ebb4caSwyllys 	}
63299ebb4caSwyllys 
63330a5e8faSwyllys 	if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
63430a5e8faSwyllys 	    match == FALSE) {
63599ebb4caSwyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
63699ebb4caSwyllys 		goto cleanup;
63799ebb4caSwyllys 	}
63899ebb4caSwyllys 
63999ebb4caSwyllys 	if (outcert != NULL) {
64099ebb4caSwyllys 		*outcert = xcert;
64199ebb4caSwyllys 	}
64299ebb4caSwyllys 
64399ebb4caSwyllys cleanup:
64499ebb4caSwyllys 	if (bcert != NULL) (void) BIO_free(bcert);
64599ebb4caSwyllys 	if (rv != KMF_OK && xcert != NULL)
64699ebb4caSwyllys 		X509_free(xcert);
64799ebb4caSwyllys 
64899ebb4caSwyllys 	return (rv);
64999ebb4caSwyllys }
65099ebb4caSwyllys 
65171593db2Swyllys static int
65271593db2Swyllys datacmp(const void *a, const void *b)
65371593db2Swyllys {
65471593db2Swyllys 	KMF_DATA *adata = (KMF_DATA *)a;
65571593db2Swyllys 	KMF_DATA *bdata = (KMF_DATA *)b;
65671593db2Swyllys 	if (adata->Length > bdata->Length)
65771593db2Swyllys 		return (-1);
65871593db2Swyllys 	if (adata->Length < bdata->Length)
65971593db2Swyllys 		return (1);
66071593db2Swyllys 	return (0);
66171593db2Swyllys }
66271593db2Swyllys 
66371593db2Swyllys static KMF_RETURN
66430a5e8faSwyllys load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
66530a5e8faSwyllys     KMF_CERT_VALIDITY validity, char *pathname,
66671593db2Swyllys     KMF_DATA **certlist, uint32_t *numcerts)
66771593db2Swyllys {
66871593db2Swyllys 	KMF_RETURN rv = KMF_OK;
66971593db2Swyllys 	int i;
67071593db2Swyllys 	KMF_DATA *certs = NULL;
67171593db2Swyllys 	int nc = 0;
67271593db2Swyllys 	int hits = 0;
67371593db2Swyllys 	KMF_ENCODE_FORMAT format;
67471593db2Swyllys 
67530a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
67671593db2Swyllys 	if (rv != KMF_OK) {
67771593db2Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
67871593db2Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
67971593db2Swyllys 		return (rv);
68071593db2Swyllys 	}
68171593db2Swyllys 	if (format == KMF_FORMAT_ASN1) {
68271593db2Swyllys 		/* load a single certificate */
68371593db2Swyllys 		certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
68471593db2Swyllys 		if (certs == NULL)
68571593db2Swyllys 			return (KMF_ERR_MEMORY);
68671593db2Swyllys 		certs->Data = NULL;
68771593db2Swyllys 		certs->Length = 0;
68830a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
68930a5e8faSwyllys 		    pathname, certs);
69071593db2Swyllys 		if (rv == KMF_OK) {
69171593db2Swyllys 			*certlist = certs;
69271593db2Swyllys 			*numcerts = 1;
693a2d4930dSDan OpenSolaris Anderson 		} else {
694a2d4930dSDan OpenSolaris Anderson 			kmf_free_data(certs);
695a2d4930dSDan OpenSolaris Anderson 			free(certs);
696a2d4930dSDan OpenSolaris Anderson 			certs = NULL;
69771593db2Swyllys 		}
69871593db2Swyllys 		return (rv);
69971593db2Swyllys 	} else if (format == KMF_FORMAT_PKCS12) {
70071593db2Swyllys 		/* We need a credential to access a PKCS#12 file */
70171593db2Swyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
70271593db2Swyllys 	} else if (format == KMF_FORMAT_PEM ||
70371593db2Swyllys 	    format != KMF_FORMAT_PEM_KEYPAIR) {
704e65e5c2dSWyllys Ingersoll 
70571593db2Swyllys 		/* This function only works on PEM files */
70630a5e8faSwyllys 		rv = extract_pem(kmfh, issuer, subject, serial, pathname,
70734acef67Swyllys 		    (uchar_t *)NULL, 0, NULL, &certs, &nc);
70871593db2Swyllys 	} else {
70971593db2Swyllys 		return (KMF_ERR_ENCODING);
71071593db2Swyllys 	}
71171593db2Swyllys 
71271593db2Swyllys 	if (rv != KMF_OK)
71371593db2Swyllys 		return (rv);
71471593db2Swyllys 
71571593db2Swyllys 	for (i = 0; i < nc; i++) {
71630a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
71730a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
71830a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
71930a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
72071593db2Swyllys 			if (rv == KMF_OK)
72171593db2Swyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
72271593db2Swyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD)
72371593db2Swyllys 				rv = KMF_OK;
72471593db2Swyllys 		}
72571593db2Swyllys 		if (rv != KMF_OK) {
72671593db2Swyllys 			/* Remove this cert from the list by clearing it. */
72730a5e8faSwyllys 			kmf_free_data(&certs[i]);
72871593db2Swyllys 		} else {
72971593db2Swyllys 			hits++; /* count valid certs found */
73071593db2Swyllys 		}
73171593db2Swyllys 		rv = KMF_OK;
73271593db2Swyllys 	}
733a2d4930dSDan OpenSolaris Anderson 	if (rv == KMF_OK && hits > 0) {
73471593db2Swyllys 		/*
73571593db2Swyllys 		 * Sort the list of certs by length to put the cleared ones
73671593db2Swyllys 		 * at the end so they don't get accessed by the caller.
73771593db2Swyllys 		 */
73871593db2Swyllys 		qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
73971593db2Swyllys 		*certlist = certs;
74071593db2Swyllys 
74171593db2Swyllys 		/* since we sorted the list, just return the number of hits */
74271593db2Swyllys 		*numcerts = hits;
743a2d4930dSDan OpenSolaris Anderson 	} else {
744e65e5c2dSWyllys Ingersoll 		if (rv == KMF_OK && hits == 0)
745a2d4930dSDan OpenSolaris Anderson 			rv = KMF_ERR_CERT_NOT_FOUND;
746a2d4930dSDan OpenSolaris Anderson 		if (certs != NULL) {
747a2d4930dSDan OpenSolaris Anderson 			free(certs);
748a2d4930dSDan OpenSolaris Anderson 			certs = NULL;
749a2d4930dSDan OpenSolaris Anderson 		}
750a2d4930dSDan OpenSolaris Anderson 	}
75171593db2Swyllys 	return (rv);
75271593db2Swyllys }
75371593db2Swyllys 
75499ebb4caSwyllys static KMF_RETURN
75599ebb4caSwyllys kmf_load_cert(KMF_HANDLE *kmfh,
75630a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
75730a5e8faSwyllys     KMF_CERT_VALIDITY validity,
75899ebb4caSwyllys     char *pathname,
75999ebb4caSwyllys     KMF_DATA *cert)
76099ebb4caSwyllys {
76199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
76299ebb4caSwyllys 	X509 *x509cert = NULL;
76399ebb4caSwyllys 
76430a5e8faSwyllys 	rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
76599ebb4caSwyllys 	if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
76699ebb4caSwyllys 		rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
76799ebb4caSwyllys 		if (rv != KMF_OK) {
76899ebb4caSwyllys 			goto cleanup;
76999ebb4caSwyllys 		}
77030a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
77130a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
77230a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
77330a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
77499ebb4caSwyllys 			if (rv == KMF_OK)  {
77599ebb4caSwyllys 				/*
77699ebb4caSwyllys 				 * This is a valid cert so skip it.
77799ebb4caSwyllys 				 */
77899ebb4caSwyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
77999ebb4caSwyllys 			}
78099ebb4caSwyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD) {
78199ebb4caSwyllys 				/*
78299ebb4caSwyllys 				 * We want to return success when we
78399ebb4caSwyllys 				 * find an invalid cert.
78499ebb4caSwyllys 				 */
78599ebb4caSwyllys 				rv = KMF_OK;
78699ebb4caSwyllys 				goto cleanup;
78799ebb4caSwyllys 			}
78899ebb4caSwyllys 		}
78999ebb4caSwyllys 	}
79099ebb4caSwyllys cleanup:
79199ebb4caSwyllys 	if (x509cert != NULL)
79299ebb4caSwyllys 		X509_free(x509cert);
79399ebb4caSwyllys 
79499ebb4caSwyllys 	return (rv);
79599ebb4caSwyllys }
79699ebb4caSwyllys 
79702744e81Swyllys static KMF_RETURN
79802744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
79902744e81Swyllys {
80002744e81Swyllys 	KMF_RETURN ret = KMF_OK;
80102744e81Swyllys 	KMF_RAW_RSA_KEY rsa;
80202744e81Swyllys 	BerElement *asn1 = NULL;
80302744e81Swyllys 	BerValue filebuf;
80402744e81Swyllys 	BerValue OID = { NULL, 0 };
80502744e81Swyllys 	BerValue *Mod = NULL, *PubExp = NULL;
80602744e81Swyllys 	BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
80702744e81Swyllys 	BerValue *Coef = NULL;
80802744e81Swyllys 	BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
80902744e81Swyllys 	BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
81002744e81Swyllys 	BIGNUM *qminus1 = NULL;
81102744e81Swyllys 	BN_CTX *ctx = NULL;
81202744e81Swyllys 
81302744e81Swyllys 	*pkey = NULL;
81402744e81Swyllys 
81502744e81Swyllys 	filebuf.bv_val = (char *)filedata->Data;
81602744e81Swyllys 	filebuf.bv_len = filedata->Length;
81702744e81Swyllys 
81802744e81Swyllys 	asn1 = kmfder_init(&filebuf);
81902744e81Swyllys 	if (asn1 == NULL) {
82002744e81Swyllys 		ret = KMF_ERR_MEMORY;
82102744e81Swyllys 		goto out;
82202744e81Swyllys 	}
82302744e81Swyllys 
82402744e81Swyllys 	if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
82502744e81Swyllys 	    &OID, &Mod, &PubExp, &PriExp, &Prime1,
82602744e81Swyllys 	    &Prime2, &Coef) == -1)  {
82702744e81Swyllys 		ret = KMF_ERR_ENCODING;
82802744e81Swyllys 		goto out;
82902744e81Swyllys 	}
83002744e81Swyllys 
83102744e81Swyllys 	/*
83202744e81Swyllys 	 * We have to derive the 2 Exponents using Bignumber math.
83302744e81Swyllys 	 * Exp1 = PriExp mod (Prime1 - 1)
83402744e81Swyllys 	 * Exp2 = PriExp mod (Prime2 - 1)
83502744e81Swyllys 	 */
83602744e81Swyllys 
83702744e81Swyllys 	/* D = PrivateExponent */
83802744e81Swyllys 	D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
83902744e81Swyllys 	if (D == NULL) {
84002744e81Swyllys 		ret = KMF_ERR_MEMORY;
84102744e81Swyllys 		goto out;
84202744e81Swyllys 	}
84302744e81Swyllys 
84402744e81Swyllys 	/* P = Prime1 (first prime factor of Modulus) */
84502744e81Swyllys 	P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
84602744e81Swyllys 	if (D == NULL) {
84702744e81Swyllys 		ret = KMF_ERR_MEMORY;
84802744e81Swyllys 		goto out;
84902744e81Swyllys 	}
85002744e81Swyllys 
85102744e81Swyllys 	/* Q = Prime2 (second prime factor of Modulus) */
85202744e81Swyllys 	Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
85302744e81Swyllys 
85402744e81Swyllys 	if ((ctx = BN_CTX_new()) == NULL) {
85502744e81Swyllys 		ret = KMF_ERR_MEMORY;
85602744e81Swyllys 		goto out;
85702744e81Swyllys 	}
85802744e81Swyllys 
85902744e81Swyllys 	/* Compute (P - 1) */
86002744e81Swyllys 	pminus1 = BN_new();
86102744e81Swyllys 	(void) BN_sub(pminus1, P, BN_value_one());
86202744e81Swyllys 
86302744e81Swyllys 	/* Exponent1 = D mod (P - 1) */
86402744e81Swyllys 	Exp1 = BN_new();
86502744e81Swyllys 	(void) BN_mod(Exp1, D, pminus1, ctx);
86602744e81Swyllys 
86702744e81Swyllys 	/* Compute (Q - 1) */
86802744e81Swyllys 	qminus1 = BN_new();
86902744e81Swyllys 	(void) BN_sub(qminus1, Q, BN_value_one());
87002744e81Swyllys 
87102744e81Swyllys 	/* Exponent2 = D mod (Q - 1) */
87202744e81Swyllys 	Exp2 = BN_new();
87302744e81Swyllys 	(void) BN_mod(Exp2, D, qminus1, ctx);
87402744e81Swyllys 
87502744e81Swyllys 	/* Coef = (Inverse Q) mod P */
87602744e81Swyllys 	COEF = BN_new();
87702744e81Swyllys 	(void) BN_mod_inverse(COEF, Q, P, ctx);
87802744e81Swyllys 
87902744e81Swyllys 	/* Convert back to KMF format */
88002744e81Swyllys 	(void) memset(&rsa, 0, sizeof (rsa));
88102744e81Swyllys 
88202744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
88302744e81Swyllys 		goto out;
88402744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
88502744e81Swyllys 		goto out;
88602744e81Swyllys 	if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
88702744e81Swyllys 		goto out;
88802744e81Swyllys 
88902744e81Swyllys 	rsa.mod.val = (uchar_t *)Mod->bv_val;
89002744e81Swyllys 	rsa.mod.len = Mod->bv_len;
89102744e81Swyllys 
89202744e81Swyllys 	rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
89302744e81Swyllys 	rsa.pubexp.len = PubExp->bv_len;
89402744e81Swyllys 
89502744e81Swyllys 	rsa.priexp.val = (uchar_t *)PriExp->bv_val;
89602744e81Swyllys 	rsa.priexp.len = PriExp->bv_len;
89702744e81Swyllys 
89802744e81Swyllys 	rsa.prime1.val = (uchar_t *)Prime1->bv_val;
89902744e81Swyllys 	rsa.prime1.len = Prime1->bv_len;
90002744e81Swyllys 
90102744e81Swyllys 	rsa.prime2.val = (uchar_t *)Prime2->bv_val;
90202744e81Swyllys 	rsa.prime2.len = Prime2->bv_len;
90302744e81Swyllys 
90402744e81Swyllys 	*pkey = ImportRawRSAKey(&rsa);
90502744e81Swyllys out:
90602744e81Swyllys 	if (asn1 != NULL)
90702744e81Swyllys 		kmfber_free(asn1, 1);
90802744e81Swyllys 
90902744e81Swyllys 	if (OID.bv_val) {
91002744e81Swyllys 		free(OID.bv_val);
91102744e81Swyllys 	}
91202744e81Swyllys 	if (PriExp)
91302744e81Swyllys 		free(PriExp);
91402744e81Swyllys 
91502744e81Swyllys 	if (Mod)
91602744e81Swyllys 		free(Mod);
91702744e81Swyllys 
91802744e81Swyllys 	if (PubExp)
91902744e81Swyllys 		free(PubExp);
92002744e81Swyllys 
92102744e81Swyllys 	if (Coef) {
92202744e81Swyllys 		(void) memset(Coef->bv_val, 0, Coef->bv_len);
92302744e81Swyllys 		free(Coef->bv_val);
92402744e81Swyllys 		free(Coef);
92502744e81Swyllys 	}
92602744e81Swyllys 	if (Prime1)
92702744e81Swyllys 		free(Prime1);
92802744e81Swyllys 	if (Prime2)
92902744e81Swyllys 		free(Prime2);
93002744e81Swyllys 
93102744e81Swyllys 	if (ctx != NULL)
93202744e81Swyllys 		BN_CTX_free(ctx);
93302744e81Swyllys 
93402744e81Swyllys 	if (D)
93502744e81Swyllys 		BN_clear_free(D);
93602744e81Swyllys 	if (P)
93702744e81Swyllys 		BN_clear_free(P);
93802744e81Swyllys 	if (Q)
93902744e81Swyllys 		BN_clear_free(Q);
94002744e81Swyllys 	if (pminus1)
94102744e81Swyllys 		BN_clear_free(pminus1);
94202744e81Swyllys 	if (qminus1)
94302744e81Swyllys 		BN_clear_free(qminus1);
94402744e81Swyllys 	if (Exp1)
94502744e81Swyllys 		BN_clear_free(Exp1);
94602744e81Swyllys 	if (Exp2)
94702744e81Swyllys 		BN_clear_free(Exp2);
94802744e81Swyllys 
94902744e81Swyllys 	return (ret);
95002744e81Swyllys 
95102744e81Swyllys }
95202744e81Swyllys 
95399ebb4caSwyllys static EVP_PKEY *
95499ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file)
95599ebb4caSwyllys {
95699ebb4caSwyllys 	BIO *keyfile = NULL;
95799ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
95899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
95999ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
96002744e81Swyllys 	KMF_RETURN rv;
96102744e81Swyllys 	KMF_DATA filedata;
96299ebb4caSwyllys 
96399ebb4caSwyllys 	if (file == NULL) {
96499ebb4caSwyllys 		return (NULL);
96599ebb4caSwyllys 	}
96699ebb4caSwyllys 
96730a5e8faSwyllys 	if (kmf_get_file_format((char *)file, &format) != KMF_OK)
96899ebb4caSwyllys 		return (NULL);
96999ebb4caSwyllys 
97099ebb4caSwyllys 	keyfile = BIO_new_file(file, "rb");
97199ebb4caSwyllys 	if (keyfile == NULL) {
97299ebb4caSwyllys 		goto end;
97399ebb4caSwyllys 	}
97499ebb4caSwyllys 
97502744e81Swyllys 	if (format == KMF_FORMAT_ASN1) {
97699ebb4caSwyllys 		pkey = d2i_PrivateKey_bio(keyfile, NULL);
97702744e81Swyllys 		if (pkey == NULL) {
97802744e81Swyllys 
97902744e81Swyllys 			(void) BIO_free(keyfile);
98002744e81Swyllys 			keyfile = NULL;
98102744e81Swyllys 			/* Try odd ASN.1 variations */
98230a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
98302744e81Swyllys 			    &filedata);
98402744e81Swyllys 			if (rv == KMF_OK) {
98502744e81Swyllys 				(void) readAltFormatPrivateKey(&filedata,
98602744e81Swyllys 				    &pkey);
98730a5e8faSwyllys 				kmf_free_data(&filedata);
98802744e81Swyllys 			}
98902744e81Swyllys 		}
99002744e81Swyllys 	} else if (format == KMF_FORMAT_PEM ||
99102744e81Swyllys 	    format == KMF_FORMAT_PEM_KEYPAIR) {
99299ebb4caSwyllys 		pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
99302744e81Swyllys 		if (pkey == NULL) {
99402744e81Swyllys 			KMF_DATA derdata;
99502744e81Swyllys 			/*
99602744e81Swyllys 			 * Check if this is the alt. format
99702744e81Swyllys 			 * RSA private key file.
99802744e81Swyllys 			 */
99930a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
100002744e81Swyllys 			    &filedata);
100102744e81Swyllys 			if (rv == KMF_OK) {
100202744e81Swyllys 				uchar_t *d = NULL;
100302744e81Swyllys 				int len;
100430a5e8faSwyllys 				rv = kmf_pem_to_der(filedata.Data,
100502744e81Swyllys 				    filedata.Length, &d, &len);
100602744e81Swyllys 				if (rv == KMF_OK && d != NULL) {
100702744e81Swyllys 					derdata.Data = d;
100802744e81Swyllys 					derdata.Length = (size_t)len;
100902744e81Swyllys 					(void) readAltFormatPrivateKey(
101002744e81Swyllys 					    &derdata, &pkey);
101102744e81Swyllys 					free(d);
101202744e81Swyllys 				}
101330a5e8faSwyllys 				kmf_free_data(&filedata);
101402744e81Swyllys 			}
101502744e81Swyllys 		}
101602744e81Swyllys 	}
101799ebb4caSwyllys 
101899ebb4caSwyllys end:
101999ebb4caSwyllys 	if (pkey == NULL)
102099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
102199ebb4caSwyllys 
102299ebb4caSwyllys 	if (keyfile != NULL)
102399ebb4caSwyllys 		(void) BIO_free(keyfile);
102499ebb4caSwyllys 
102599ebb4caSwyllys 	return (pkey);
102699ebb4caSwyllys }
102799ebb4caSwyllys 
102899ebb4caSwyllys KMF_RETURN
102930a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
103099ebb4caSwyllys {
103199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
103299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1033f482c776Swyllys 	int i, n;
1034f482c776Swyllys 	uint32_t maxcerts = 0;
103530a5e8faSwyllys 	uint32_t *num_certs;
103630a5e8faSwyllys 	KMF_X509_DER_CERT *kmf_cert = NULL;
103730a5e8faSwyllys 	char *dirpath = NULL;
103830a5e8faSwyllys 	char *filename = NULL;
103930a5e8faSwyllys 	char *fullpath = NULL;
104030a5e8faSwyllys 	char *issuer = NULL;
104130a5e8faSwyllys 	char *subject = NULL;
104230a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
104330a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
104499ebb4caSwyllys 
104530a5e8faSwyllys 	num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
104630a5e8faSwyllys 	if (num_certs == NULL)
104799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
104899ebb4caSwyllys 
104930a5e8faSwyllys 	/* num_certs should reference the size of kmf_cert */
1050f482c776Swyllys 	maxcerts = *num_certs;
1051f482c776Swyllys 	if (maxcerts == 0)
1052f482c776Swyllys 		maxcerts = 0xFFFFFFFF;
105399ebb4caSwyllys 	*num_certs = 0;
105499ebb4caSwyllys 
105530a5e8faSwyllys 	/* Get the optional returned certificate list  */
105630a5e8faSwyllys 	kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
105730a5e8faSwyllys 	    numattr);
105899ebb4caSwyllys 
105930a5e8faSwyllys 	/*
106030a5e8faSwyllys 	 * The dirpath attribute and the filename attribute can not be NULL
106130a5e8faSwyllys 	 * at the same time.
106230a5e8faSwyllys 	 */
106330a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
106430a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
106530a5e8faSwyllys 	    numattr);
106630a5e8faSwyllys 
106730a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
106899ebb4caSwyllys 	if (fullpath == NULL)
106999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
107099ebb4caSwyllys 
107130a5e8faSwyllys 	/* Get optional search criteria attributes */
107230a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
107330a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
107430a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
107530a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
107630a5e8faSwyllys 	    &validity, NULL);
107730a5e8faSwyllys 	if (rv != KMF_OK) {
107830a5e8faSwyllys 		validity = KMF_ALL_CERTS;
107930a5e8faSwyllys 		rv = KMF_OK;
108030a5e8faSwyllys 	}
108130a5e8faSwyllys 
108299ebb4caSwyllys 	if (isdir(fullpath)) {
108399ebb4caSwyllys 		DIR *dirp;
108499ebb4caSwyllys 		struct dirent *dp;
108599ebb4caSwyllys 
1086f482c776Swyllys 		n = 0;
108799ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
108899ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
108999ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
109099ebb4caSwyllys 		}
109199ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
109299ebb4caSwyllys 			char *fname;
109371593db2Swyllys 			KMF_DATA *certlist = NULL;
1094f482c776Swyllys 			uint32_t loaded_certs = 0;
109571593db2Swyllys 
109699ebb4caSwyllys 			if (strcmp(dp->d_name, ".") == 0 ||
109799ebb4caSwyllys 			    strcmp(dp->d_name, "..") == 0)
109899ebb4caSwyllys 				continue;
109999ebb4caSwyllys 
110034acef67Swyllys 			fname = get_fullpath(fullpath, (char *)&dp->d_name);
110199ebb4caSwyllys 
110230a5e8faSwyllys 			rv = load_certs(kmfh, issuer, subject, serial,
110330a5e8faSwyllys 			    validity, fname, &certlist,	&loaded_certs);
110499ebb4caSwyllys 
110599ebb4caSwyllys 			if (rv != KMF_OK) {
110699ebb4caSwyllys 				free(fname);
110771593db2Swyllys 				if (certlist != NULL) {
1108f482c776Swyllys 					for (i = 0; i < loaded_certs; i++)
110930a5e8faSwyllys 						kmf_free_data(&certlist[i]);
111071593db2Swyllys 					free(certlist);
111171593db2Swyllys 				}
111299ebb4caSwyllys 				continue;
111399ebb4caSwyllys 			}
111499ebb4caSwyllys 
111599ebb4caSwyllys 			/* If load succeeds, add certdata to the list */
111699ebb4caSwyllys 			if (kmf_cert != NULL) {
1117f482c776Swyllys 				for (i = 0; i < loaded_certs &&
1118b4058258Swyllys 				    n < maxcerts; i++) {
111971593db2Swyllys 					kmf_cert[n].certificate.Data =
112071593db2Swyllys 					    certlist[i].Data;
112199ebb4caSwyllys 					kmf_cert[n].certificate.Length =
112271593db2Swyllys 					    certlist[i].Length;
112399ebb4caSwyllys 
112499ebb4caSwyllys 					kmf_cert[n].kmf_private.keystore_type =
112599ebb4caSwyllys 					    KMF_KEYSTORE_OPENSSL;
112699ebb4caSwyllys 					kmf_cert[n].kmf_private.flags =
112799ebb4caSwyllys 					    KMF_FLAG_CERT_VALID;
112871593db2Swyllys 					kmf_cert[n].kmf_private.label =
112971593db2Swyllys 					    strdup(fname);
113099ebb4caSwyllys 					n++;
113199ebb4caSwyllys 				}
1132b4058258Swyllys 				/*
1133b4058258Swyllys 				 * If maxcerts < loaded_certs, clean up the
1134b4058258Swyllys 				 * certs that were not used.
1135b4058258Swyllys 				 */
1136f482c776Swyllys 				for (; i < loaded_certs; i++)
113730a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1138f482c776Swyllys 			} else {
1139f482c776Swyllys 				for (i = 0; i < loaded_certs; i++)
114030a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1141f482c776Swyllys 				n += loaded_certs;
114271593db2Swyllys 			}
1143f482c776Swyllys 			free(certlist);
114471593db2Swyllys 			free(fname);
114571593db2Swyllys 		}
114699ebb4caSwyllys 		(*num_certs) = n;
114799ebb4caSwyllys 		if (*num_certs == 0)
114899ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
114930a5e8faSwyllys 		if (*num_certs > 0)
115099ebb4caSwyllys 			rv = KMF_OK;
115199ebb4caSwyllys exit:
115299ebb4caSwyllys 		(void) closedir(dirp);
115399ebb4caSwyllys 	} else {
115471593db2Swyllys 		KMF_DATA *certlist = NULL;
1155f482c776Swyllys 		uint32_t loaded_certs = 0;
115671593db2Swyllys 
115730a5e8faSwyllys 		rv = load_certs(kmfh, issuer, subject, serial, validity,
115830a5e8faSwyllys 		    fullpath, &certlist, &loaded_certs);
115999ebb4caSwyllys 		if (rv != KMF_OK) {
116099ebb4caSwyllys 			free(fullpath);
116199ebb4caSwyllys 			return (rv);
116299ebb4caSwyllys 		}
116399ebb4caSwyllys 
1164f482c776Swyllys 		n = 0;
116571593db2Swyllys 		if (kmf_cert != NULL && certlist != NULL) {
1166f482c776Swyllys 			for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1167f482c776Swyllys 				kmf_cert[n].certificate.Data =
116871593db2Swyllys 				    certlist[i].Data;
1169f482c776Swyllys 				kmf_cert[n].certificate.Length =
117071593db2Swyllys 				    certlist[i].Length;
1171f482c776Swyllys 				kmf_cert[n].kmf_private.keystore_type =
117299ebb4caSwyllys 				    KMF_KEYSTORE_OPENSSL;
1173f482c776Swyllys 				kmf_cert[n].kmf_private.flags =
117471593db2Swyllys 				    KMF_FLAG_CERT_VALID;
1175f482c776Swyllys 				kmf_cert[n].kmf_private.label =
117671593db2Swyllys 				    strdup(fullpath);
1177f482c776Swyllys 				n++;
117871593db2Swyllys 			}
1179f482c776Swyllys 			/* If maxcerts < loaded_certs, clean up */
1180f482c776Swyllys 			for (; i < loaded_certs; i++)
118130a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1182f482c776Swyllys 		} else if (certlist != NULL) {
1183f482c776Swyllys 			for (i = 0; i < loaded_certs; i++)
118430a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1185f482c776Swyllys 			n = loaded_certs;
1186f482c776Swyllys 		}
118730a5e8faSwyllys 		if (certlist != NULL)
118871593db2Swyllys 			free(certlist);
1189f482c776Swyllys 		*num_certs = n;
119099ebb4caSwyllys 	}
119199ebb4caSwyllys 
119299ebb4caSwyllys 	free(fullpath);
119399ebb4caSwyllys 
119499ebb4caSwyllys 	return (rv);
119599ebb4caSwyllys }
119699ebb4caSwyllys 
119799ebb4caSwyllys void
119899ebb4caSwyllys /*ARGSUSED*/
119999ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
120099ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert)
120199ebb4caSwyllys {
120299ebb4caSwyllys 	if (kmf_cert != NULL) {
120399ebb4caSwyllys 		if (kmf_cert->certificate.Data != NULL) {
1204e65e5c2dSWyllys Ingersoll 			kmf_free_data(&kmf_cert->certificate);
120599ebb4caSwyllys 		}
120699ebb4caSwyllys 		if (kmf_cert->kmf_private.label)
120799ebb4caSwyllys 			free(kmf_cert->kmf_private.label);
120899ebb4caSwyllys 	}
120999ebb4caSwyllys }
121099ebb4caSwyllys 
121130a5e8faSwyllys /*ARGSUSED*/
121299ebb4caSwyllys KMF_RETURN
121330a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
121499ebb4caSwyllys {
121599ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
121630a5e8faSwyllys 	KMF_DATA *cert = NULL;
121730a5e8faSwyllys 	char *outfilename = NULL;
121830a5e8faSwyllys 	char *dirpath = NULL;
121930a5e8faSwyllys 	char *fullpath = NULL;
122099ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
122199ebb4caSwyllys 
122230a5e8faSwyllys 	/* Get the cert data */
122330a5e8faSwyllys 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
122430a5e8faSwyllys 	if (cert == NULL || cert->Data == NULL)
122599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
122699ebb4caSwyllys 
122730a5e8faSwyllys 	/* Check the output filename and directory attributes. */
122830a5e8faSwyllys 	outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
122930a5e8faSwyllys 	    numattr);
123030a5e8faSwyllys 	if (outfilename == NULL)
123130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
123299ebb4caSwyllys 
123330a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
123430a5e8faSwyllys 	fullpath = get_fullpath(dirpath, outfilename);
123599ebb4caSwyllys 	if (fullpath == NULL)
123630a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
123799ebb4caSwyllys 
123830a5e8faSwyllys 	/* Check the optional format attribute */
123930a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
124030a5e8faSwyllys 	    &format, NULL);
124130a5e8faSwyllys 	if (ret != KMF_OK) {
124230a5e8faSwyllys 		/* If there is no format attribute, then default to PEM */
124330a5e8faSwyllys 		format = KMF_FORMAT_PEM;
124499ebb4caSwyllys 		ret = KMF_OK;
124530a5e8faSwyllys 	} else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
124630a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
124799ebb4caSwyllys 		goto out;
124899ebb4caSwyllys 	}
124999ebb4caSwyllys 
125030a5e8faSwyllys 	/* Store the certificate in the file with the specified format */
125130a5e8faSwyllys 	ret = kmf_create_cert_file(cert, format, fullpath);
125299ebb4caSwyllys 
125399ebb4caSwyllys out:
125499ebb4caSwyllys 	if (fullpath != NULL)
125599ebb4caSwyllys 		free(fullpath);
125699ebb4caSwyllys 
125799ebb4caSwyllys 	return (ret);
125899ebb4caSwyllys }
125999ebb4caSwyllys 
126030a5e8faSwyllys 
126199ebb4caSwyllys KMF_RETURN
126230a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
126399ebb4caSwyllys {
126499ebb4caSwyllys 	KMF_RETURN rv;
126599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
12666b35cb3cSRichard PALO 	KMF_DATA certdata = { 0, NULL };
126730a5e8faSwyllys 	char *dirpath = NULL;
126830a5e8faSwyllys 	char *filename = NULL;
126930a5e8faSwyllys 	char *fullpath = NULL;
127030a5e8faSwyllys 	char *issuer = NULL;
127130a5e8faSwyllys 	char *subject = NULL;
127230a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
127330a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
127499ebb4caSwyllys 
127530a5e8faSwyllys 	/*
127630a5e8faSwyllys 	 * Get the DIRPATH and CERT_FILENAME attributes.  They can not be
127730a5e8faSwyllys 	 * NULL at the same time.
127830a5e8faSwyllys 	 */
127930a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
128030a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
128130a5e8faSwyllys 	    numattr);
128230a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
128399ebb4caSwyllys 	if (fullpath == NULL)
128499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
128599ebb4caSwyllys 
128630a5e8faSwyllys 	/* Get optional search criteria attributes */
128730a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
128830a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
128930a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
129030a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
129130a5e8faSwyllys 	    &validity, NULL);
129230a5e8faSwyllys 	if (rv != KMF_OK) {
129330a5e8faSwyllys 		validity = KMF_ALL_CERTS;
129430a5e8faSwyllys 		rv = KMF_OK;
129530a5e8faSwyllys 	}
129630a5e8faSwyllys 
129799ebb4caSwyllys 	if (isdir(fullpath)) {
129899ebb4caSwyllys 		DIR *dirp;
129999ebb4caSwyllys 		struct dirent *dp;
130099ebb4caSwyllys 
130199ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
130299ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
130399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
130499ebb4caSwyllys 		}
130599ebb4caSwyllys 
130699ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
130799ebb4caSwyllys 			if (strcmp(dp->d_name, ".") != 0 &&
130899ebb4caSwyllys 			    strcmp(dp->d_name, "..") != 0) {
130999ebb4caSwyllys 				char *fname;
131099ebb4caSwyllys 
131199ebb4caSwyllys 				fname = get_fullpath(fullpath,
131299ebb4caSwyllys 				    (char *)&dp->d_name);
131399ebb4caSwyllys 
131499ebb4caSwyllys 				if (fname == NULL) {
131599ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
131699ebb4caSwyllys 					break;
131799ebb4caSwyllys 				}
131899ebb4caSwyllys 
131930a5e8faSwyllys 				rv = kmf_load_cert(kmfh, issuer, subject,
132030a5e8faSwyllys 				    serial, validity, fname, &certdata);
132199ebb4caSwyllys 
132299ebb4caSwyllys 				if (rv == KMF_ERR_CERT_NOT_FOUND) {
132399ebb4caSwyllys 					free(fname);
1324e65e5c2dSWyllys Ingersoll 					kmf_free_data(&certdata);
132599ebb4caSwyllys 					rv = KMF_OK;
132699ebb4caSwyllys 					continue;
132799ebb4caSwyllys 				} else if (rv != KMF_OK) {
132899ebb4caSwyllys 					free(fname);
132999ebb4caSwyllys 					break;
133099ebb4caSwyllys 				}
133199ebb4caSwyllys 
133299ebb4caSwyllys 				if (unlink(fname) != 0) {
133399ebb4caSwyllys 					SET_SYS_ERROR(kmfh, errno);
133499ebb4caSwyllys 					rv = KMF_ERR_INTERNAL;
133599ebb4caSwyllys 					free(fname);
133699ebb4caSwyllys 					break;
133799ebb4caSwyllys 				}
133899ebb4caSwyllys 				free(fname);
1339e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certdata);
134099ebb4caSwyllys 			}
134199ebb4caSwyllys 		}
134299ebb4caSwyllys 		(void) closedir(dirp);
134399ebb4caSwyllys 	} else {
134499ebb4caSwyllys 		/* Just try to load a single certificate */
134530a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
134630a5e8faSwyllys 		    fullpath, &certdata);
134799ebb4caSwyllys 		if (rv == KMF_OK) {
134899ebb4caSwyllys 			if (unlink(fullpath) != 0) {
134999ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
135099ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
135199ebb4caSwyllys 			}
135299ebb4caSwyllys 		}
135399ebb4caSwyllys 	}
135499ebb4caSwyllys 
135599ebb4caSwyllys out:
135699ebb4caSwyllys 	if (fullpath != NULL)
135799ebb4caSwyllys 		free(fullpath);
135899ebb4caSwyllys 
1359e65e5c2dSWyllys Ingersoll 	kmf_free_data(&certdata);
136099ebb4caSwyllys 
136199ebb4caSwyllys 	return (rv);
136299ebb4caSwyllys }
136399ebb4caSwyllys 
136499ebb4caSwyllys KMF_RETURN
136599ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
136699ebb4caSwyllys 	KMF_DATA *keydata)
136799ebb4caSwyllys {
136899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
136999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
137099ebb4caSwyllys 	int n;
137199ebb4caSwyllys 
137299ebb4caSwyllys 	if (key == NULL || keydata == NULL ||
137399ebb4caSwyllys 	    key->keyp == NULL)
137499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
137599ebb4caSwyllys 
137699ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
137799ebb4caSwyllys 		RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
137899ebb4caSwyllys 
137999ebb4caSwyllys 		if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
138099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
138199ebb4caSwyllys 			return (KMF_ERR_ENCODING);
138299ebb4caSwyllys 		}
138399ebb4caSwyllys 		RSA_free(pubkey);
138499ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
138599ebb4caSwyllys 		DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
138699ebb4caSwyllys 
138799ebb4caSwyllys 		if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
138899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
138999ebb4caSwyllys 			return (KMF_ERR_ENCODING);
139099ebb4caSwyllys 		}
139199ebb4caSwyllys 		DSA_free(pubkey);
139299ebb4caSwyllys 	} else {
139399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
139499ebb4caSwyllys 	}
139599ebb4caSwyllys 	keydata->Length = n;
139699ebb4caSwyllys 
139799ebb4caSwyllys cleanup:
139899ebb4caSwyllys 	if (rv != KMF_OK) {
139999ebb4caSwyllys 		if (keydata->Data)
140099ebb4caSwyllys 			free(keydata->Data);
140199ebb4caSwyllys 		keydata->Data = NULL;
140299ebb4caSwyllys 		keydata->Length = 0;
140399ebb4caSwyllys 	}
140499ebb4caSwyllys 
140599ebb4caSwyllys 	return (rv);
140699ebb4caSwyllys }
140799ebb4caSwyllys 
140899ebb4caSwyllys static KMF_RETURN
140930a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
141030a5e8faSwyllys 	KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
141199ebb4caSwyllys {
141299ebb4caSwyllys 	int rv = 0;
141399ebb4caSwyllys 	RSA *rsa;
141499ebb4caSwyllys 	DSA *dsa;
141599ebb4caSwyllys 
14165b3e1433Swyllys 	if (pkey == NULL || out == NULL)
14175b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
14185b3e1433Swyllys 
141999ebb4caSwyllys 	switch (format) {
142073cc0e02Swyllys 		case KMF_FORMAT_RAWKEY:
142173cc0e02Swyllys 			/* same as ASN.1 */
142299ebb4caSwyllys 		case KMF_FORMAT_ASN1:
142399ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
142499ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
142530a5e8faSwyllys 				if (private)
142699ebb4caSwyllys 					rv = i2d_RSAPrivateKey_bio(out, rsa);
142730a5e8faSwyllys 				else
142830a5e8faSwyllys 					rv = i2d_RSAPublicKey_bio(out, rsa);
142999ebb4caSwyllys 				RSA_free(rsa);
143099ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
143199ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
143299ebb4caSwyllys 				rv = i2d_DSAPrivateKey_bio(out, dsa);
143399ebb4caSwyllys 				DSA_free(dsa);
143499ebb4caSwyllys 			}
143599ebb4caSwyllys 			if (rv == 1) {
143699ebb4caSwyllys 				rv = KMF_OK;
143799ebb4caSwyllys 			} else {
143899ebb4caSwyllys 				SET_ERROR(kmfh, rv);
143999ebb4caSwyllys 			}
144099ebb4caSwyllys 			break;
144199ebb4caSwyllys 		case KMF_FORMAT_PEM:
144299ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
144399ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
144430a5e8faSwyllys 				if (private)
144599ebb4caSwyllys 					rv = PEM_write_bio_RSAPrivateKey(out,
144630a5e8faSwyllys 					    rsa, NULL, NULL, 0, NULL,
144730a5e8faSwyllys 					    (cred != NULL ? cred->cred : NULL));
144830a5e8faSwyllys 				else
144930a5e8faSwyllys 					rv = PEM_write_bio_RSAPublicKey(out,
145030a5e8faSwyllys 					    rsa);
145199ebb4caSwyllys 				RSA_free(rsa);
145299ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
145399ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
145499ebb4caSwyllys 				rv = PEM_write_bio_DSAPrivateKey(out,
145530a5e8faSwyllys 				    dsa, NULL, NULL, 0, NULL,
145630a5e8faSwyllys 				    (cred != NULL ? cred->cred : NULL));
145799ebb4caSwyllys 				DSA_free(dsa);
145899ebb4caSwyllys 			}
145999ebb4caSwyllys 
146099ebb4caSwyllys 			if (rv == 1) {
146199ebb4caSwyllys 				rv = KMF_OK;
146299ebb4caSwyllys 			} else {
146399ebb4caSwyllys 				SET_ERROR(kmfh, rv);
146499ebb4caSwyllys 			}
146599ebb4caSwyllys 			break;
146699ebb4caSwyllys 
146799ebb4caSwyllys 		default:
146899ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
146999ebb4caSwyllys 	}
147099ebb4caSwyllys 
147199ebb4caSwyllys 	return (rv);
147299ebb4caSwyllys }
147399ebb4caSwyllys 
147499ebb4caSwyllys KMF_RETURN
147530a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
147630a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
147799ebb4caSwyllys {
147899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
147999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
148099ebb4caSwyllys 	uint32_t eValue = 0x010001;
148199ebb4caSwyllys 	RSA *sslPrivKey = NULL;
148299ebb4caSwyllys 	DSA *sslDSAKey = NULL;
148399ebb4caSwyllys 	EVP_PKEY *eprikey = NULL;
148499ebb4caSwyllys 	EVP_PKEY *epubkey = NULL;
148599ebb4caSwyllys 	BIO *out = NULL;
148630a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
148730a5e8faSwyllys 	uint32_t keylen = 1024;
148830a5e8faSwyllys 	uint32_t keylen_size = sizeof (uint32_t);
148930a5e8faSwyllys 	boolean_t storekey = TRUE;
149030a5e8faSwyllys 	KMF_KEY_ALG keytype = KMF_RSA;
149199ebb4caSwyllys 
149230a5e8faSwyllys 	rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
149330a5e8faSwyllys 	    &storekey, NULL);
149430a5e8faSwyllys 	if (rv != KMF_OK) {
149530a5e8faSwyllys 		/* "storekey" is optional. Default is TRUE */
149630a5e8faSwyllys 		rv = KMF_OK;
149799ebb4caSwyllys 	}
149899ebb4caSwyllys 
149930a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
150030a5e8faSwyllys 	    (void *)&keytype, NULL);
150130a5e8faSwyllys 	if (rv != KMF_OK)
150230a5e8faSwyllys 		/* keytype is optional.  KMF_RSA is default */
150330a5e8faSwyllys 		rv = KMF_OK;
150499ebb4caSwyllys 
150530a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
150630a5e8faSwyllys 	if (pubkey == NULL)
150799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
150899ebb4caSwyllys 
150930a5e8faSwyllys 	privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
151030a5e8faSwyllys 	if (privkey == NULL)
151130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
151230a5e8faSwyllys 
151330a5e8faSwyllys 	(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
151430a5e8faSwyllys 	(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
151599ebb4caSwyllys 
151699ebb4caSwyllys 	eprikey = EVP_PKEY_new();
151799ebb4caSwyllys 	if (eprikey == NULL) {
151899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
151999ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
152099ebb4caSwyllys 		goto cleanup;
152199ebb4caSwyllys 	}
152299ebb4caSwyllys 	epubkey = EVP_PKEY_new();
152399ebb4caSwyllys 	if (epubkey == NULL) {
152499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
152599ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
152699ebb4caSwyllys 		goto cleanup;
152799ebb4caSwyllys 	}
152830a5e8faSwyllys 	if (keytype == KMF_RSA) {
152930a5e8faSwyllys 		KMF_BIGINT *rsaexp = NULL;
153099ebb4caSwyllys 
153130a5e8faSwyllys 		rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
153230a5e8faSwyllys 		if (rsaexp != NULL) {
153330a5e8faSwyllys 			if (rsaexp->len > 0 &&
153430a5e8faSwyllys 			    rsaexp->len <= sizeof (eValue) &&
153530a5e8faSwyllys 			    rsaexp->val != NULL) {
1536a2d4930dSDan OpenSolaris Anderson 				/* LINTED E_BAD_PTR_CAST_ALIGN */
153730a5e8faSwyllys 				eValue = *(uint32_t *)rsaexp->val;
153830a5e8faSwyllys 			} else {
153930a5e8faSwyllys 				rv = KMF_ERR_BAD_PARAMETER;
154030a5e8faSwyllys 				goto cleanup;
154130a5e8faSwyllys 			}
154230a5e8faSwyllys 		} else {
154330a5e8faSwyllys 			/* RSA Exponent is optional. Default is 0x10001 */
154430a5e8faSwyllys 			rv = KMF_OK;
154530a5e8faSwyllys 		}
154630a5e8faSwyllys 
154730a5e8faSwyllys 		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
154830a5e8faSwyllys 		    &keylen, &keylen_size);
154930a5e8faSwyllys 		if (rv == KMF_ERR_ATTR_NOT_FOUND)
155030a5e8faSwyllys 			/* keylen is optional, default is 1024 */
155130a5e8faSwyllys 			rv = KMF_OK;
155230a5e8faSwyllys 		if (rv != KMF_OK) {
155330a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
155430a5e8faSwyllys 			goto cleanup;
155530a5e8faSwyllys 		}
155630a5e8faSwyllys 
155730a5e8faSwyllys 		sslPrivKey = RSA_generate_key(keylen, eValue, NULL, NULL);
155899ebb4caSwyllys 		if (sslPrivKey == NULL) {
155999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
156099ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
156199ebb4caSwyllys 		} else {
156230a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
156399ebb4caSwyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
156499ebb4caSwyllys 			privkey->keyalg = KMF_RSA;
156599ebb4caSwyllys 			privkey->keyclass = KMF_ASYM_PRI;
156699ebb4caSwyllys 			privkey->israw = FALSE;
156799ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
156830a5e8faSwyllys 
156999ebb4caSwyllys 			/* OpenSSL derives the public key from the private */
157030a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
157199ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
157299ebb4caSwyllys 			pubkey->keyalg = KMF_RSA;
157399ebb4caSwyllys 			pubkey->israw = FALSE;
157499ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
157599ebb4caSwyllys 			pubkey->keyp = (void *)epubkey;
157699ebb4caSwyllys 		}
157730a5e8faSwyllys 	} else if (keytype == KMF_DSA) {
157830a5e8faSwyllys 		DSA *dp;
157999ebb4caSwyllys 		sslDSAKey = DSA_new();
158099ebb4caSwyllys 		if (sslDSAKey == NULL) {
158199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
158299ebb4caSwyllys 			return (KMF_ERR_MEMORY);
158399ebb4caSwyllys 		}
158499ebb4caSwyllys 
158599ebb4caSwyllys 		if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) ==
158699ebb4caSwyllys 		    NULL) {
158799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
158899ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
158999ebb4caSwyllys 			goto cleanup;
159099ebb4caSwyllys 		}
159199ebb4caSwyllys 		if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) ==
159299ebb4caSwyllys 		    NULL) {
159399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
159499ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
159599ebb4caSwyllys 			goto cleanup;
159699ebb4caSwyllys 		}
159799ebb4caSwyllys 		if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) ==
159899ebb4caSwyllys 		    NULL) {
159999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
160099ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
160199ebb4caSwyllys 			goto cleanup;
160299ebb4caSwyllys 		}
160399ebb4caSwyllys 
160499ebb4caSwyllys 		if (!DSA_generate_key(sslDSAKey)) {
160599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
160699ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
160799ebb4caSwyllys 			goto cleanup;
160899ebb4caSwyllys 		}
160999ebb4caSwyllys 
161099ebb4caSwyllys 		privkey->kstype = KMF_KEYSTORE_OPENSSL;
161199ebb4caSwyllys 		privkey->keyalg = KMF_DSA;
161299ebb4caSwyllys 		privkey->keyclass = KMF_ASYM_PRI;
161399ebb4caSwyllys 		privkey->israw = FALSE;
161499ebb4caSwyllys 		if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
161599ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
161699ebb4caSwyllys 		} else {
161799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
161899ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
161999ebb4caSwyllys 			goto cleanup;
162099ebb4caSwyllys 		}
162130a5e8faSwyllys 		dp = DSA_new();
162299ebb4caSwyllys 		/* Make a copy for the public key */
162399ebb4caSwyllys 		if (dp != NULL) {
162499ebb4caSwyllys 			if ((dp->p = BN_new()) == NULL) {
162599ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
162699ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
162799ebb4caSwyllys 				DSA_free(dp);
162899ebb4caSwyllys 				goto cleanup;
162999ebb4caSwyllys 			}
163099ebb4caSwyllys 			if ((dp->q = BN_new()) == NULL) {
163199ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
163299ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
163399ebb4caSwyllys 				BN_free(dp->p);
163499ebb4caSwyllys 				DSA_free(dp);
163599ebb4caSwyllys 				goto cleanup;
163699ebb4caSwyllys 			}
163799ebb4caSwyllys 			if ((dp->g = BN_new()) == NULL) {
163899ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
163999ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
164099ebb4caSwyllys 				BN_free(dp->q);
164199ebb4caSwyllys 				BN_free(dp->p);
164299ebb4caSwyllys 				DSA_free(dp);
164399ebb4caSwyllys 				goto cleanup;
164499ebb4caSwyllys 			}
164599ebb4caSwyllys 			if ((dp->pub_key = BN_new()) == NULL) {
164699ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
164799ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
164899ebb4caSwyllys 				BN_free(dp->q);
164999ebb4caSwyllys 				BN_free(dp->p);
165099ebb4caSwyllys 				BN_free(dp->g);
165199ebb4caSwyllys 				DSA_free(dp);
165299ebb4caSwyllys 				goto cleanup;
165399ebb4caSwyllys 			}
165499ebb4caSwyllys 			(void) BN_copy(dp->p, sslDSAKey->p);
165599ebb4caSwyllys 			(void) BN_copy(dp->q, sslDSAKey->q);
165699ebb4caSwyllys 			(void) BN_copy(dp->g, sslDSAKey->g);
165799ebb4caSwyllys 			(void) BN_copy(dp->pub_key, sslDSAKey->pub_key);
165899ebb4caSwyllys 
165999ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
166099ebb4caSwyllys 			pubkey->keyalg = KMF_DSA;
166199ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
166299ebb4caSwyllys 			pubkey->israw = FALSE;
166399ebb4caSwyllys 
166499ebb4caSwyllys 			if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
166599ebb4caSwyllys 				pubkey->keyp = (void *)epubkey;
166699ebb4caSwyllys 			} else {
166799ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
166899ebb4caSwyllys 				rv = KMF_ERR_KEYGEN_FAILED;
166999ebb4caSwyllys 				goto cleanup;
167099ebb4caSwyllys 			}
167199ebb4caSwyllys 		}
167299ebb4caSwyllys 	}
167399ebb4caSwyllys 
167499ebb4caSwyllys 	if (rv != KMF_OK) {
167599ebb4caSwyllys 		goto cleanup;
167699ebb4caSwyllys 	}
167799ebb4caSwyllys 
167830a5e8faSwyllys 	if (storekey) {
167930a5e8faSwyllys 		KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
168030a5e8faSwyllys 		int i = 0;
168130a5e8faSwyllys 		char *keyfile = NULL, *dirpath = NULL;
168230a5e8faSwyllys 		KMF_ENCODE_FORMAT format;
168330a5e8faSwyllys 		/*
168430a5e8faSwyllys 		 * Construct a new attribute arrray and call openssl_store_key
168530a5e8faSwyllys 		 */
168630a5e8faSwyllys 		kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
168730a5e8faSwyllys 		    privkey, sizeof (privkey));
168830a5e8faSwyllys 		i++;
168930a5e8faSwyllys 
169030a5e8faSwyllys 		dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
169130a5e8faSwyllys 		if (dirpath != NULL) {
169230a5e8faSwyllys 			storeattrs[i].type = KMF_DIRPATH_ATTR;
169330a5e8faSwyllys 			storeattrs[i].pValue = dirpath;
169430a5e8faSwyllys 			storeattrs[i].valueLen = strlen(dirpath);
169530a5e8faSwyllys 			i++;
169630a5e8faSwyllys 		} else {
169730a5e8faSwyllys 			rv = KMF_OK; /* DIRPATH is optional */
169899ebb4caSwyllys 		}
169930a5e8faSwyllys 		keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
170030a5e8faSwyllys 		    attrlist, numattr);
170130a5e8faSwyllys 		if (keyfile != NULL) {
170230a5e8faSwyllys 			storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
170330a5e8faSwyllys 			storeattrs[i].pValue = keyfile;
170430a5e8faSwyllys 			storeattrs[i].valueLen = strlen(keyfile);
170530a5e8faSwyllys 			i++;
170630a5e8faSwyllys 		} else {
170730a5e8faSwyllys 			goto cleanup; /* KEYFILE is required */
170830a5e8faSwyllys 		}
170930a5e8faSwyllys 		rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
171030a5e8faSwyllys 		    (void *)&format, NULL);
171130a5e8faSwyllys 		if (rv == KMF_OK) {
171230a5e8faSwyllys 			storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
171330a5e8faSwyllys 			storeattrs[i].pValue = &format;
171430a5e8faSwyllys 			storeattrs[i].valueLen = sizeof (format);
171530a5e8faSwyllys 			i++;
171630a5e8faSwyllys 		}
171730a5e8faSwyllys 
171830a5e8faSwyllys 		rv = OpenSSL_StoreKey(handle, i, storeattrs);
171930a5e8faSwyllys 	}
172099ebb4caSwyllys 
172199ebb4caSwyllys cleanup:
172299ebb4caSwyllys 	if (rv != KMF_OK) {
172399ebb4caSwyllys 		if (eprikey != NULL)
172499ebb4caSwyllys 			EVP_PKEY_free(eprikey);
172599ebb4caSwyllys 
172699ebb4caSwyllys 		if (epubkey != NULL)
172799ebb4caSwyllys 			EVP_PKEY_free(epubkey);
172899ebb4caSwyllys 
172999ebb4caSwyllys 		if (pubkey->keylabel) {
173099ebb4caSwyllys 			free(pubkey->keylabel);
173199ebb4caSwyllys 			pubkey->keylabel = NULL;
173299ebb4caSwyllys 		}
173399ebb4caSwyllys 
173499ebb4caSwyllys 		if (privkey->keylabel) {
173599ebb4caSwyllys 			free(privkey->keylabel);
173699ebb4caSwyllys 			privkey->keylabel = NULL;
173799ebb4caSwyllys 		}
173899ebb4caSwyllys 
173999ebb4caSwyllys 		pubkey->keyp = NULL;
174099ebb4caSwyllys 		privkey->keyp = NULL;
174199ebb4caSwyllys 	}
174299ebb4caSwyllys 
174399ebb4caSwyllys 	if (sslPrivKey)
174499ebb4caSwyllys 		RSA_free(sslPrivKey);
174599ebb4caSwyllys 
174699ebb4caSwyllys 	if (sslDSAKey)
174799ebb4caSwyllys 		DSA_free(sslDSAKey);
174899ebb4caSwyllys 
174999ebb4caSwyllys 	if (out != NULL)
175099ebb4caSwyllys 		(void) BIO_free(out);
175199ebb4caSwyllys 
175299ebb4caSwyllys 	return (rv);
175399ebb4caSwyllys }
175499ebb4caSwyllys 
1755e65e5c2dSWyllys Ingersoll /*
1756e65e5c2dSWyllys Ingersoll  * Make sure the BN conversion is properly padded with 0x00
1757e65e5c2dSWyllys Ingersoll  * bytes.  If not, signature verification for DSA signatures
1758e65e5c2dSWyllys Ingersoll  * may fail in the case where the bignum value does not use
1759e65e5c2dSWyllys Ingersoll  * all of the bits.
1760e65e5c2dSWyllys Ingersoll  */
1761e65e5c2dSWyllys Ingersoll static int
1762e65e5c2dSWyllys Ingersoll fixbnlen(BIGNUM *bn, unsigned char *buf, int len) {
1763e65e5c2dSWyllys Ingersoll 	int bytes = len - BN_num_bytes(bn);
17642c9a247fSWyllys Ingersoll 
17652c9a247fSWyllys Ingersoll 	/* prepend with leading 0x00 if necessary */
1766e65e5c2dSWyllys Ingersoll 	while (bytes-- > 0)
1767e65e5c2dSWyllys Ingersoll 		*buf++ = 0;
1768e65e5c2dSWyllys Ingersoll 
17692c9a247fSWyllys Ingersoll 	(void) BN_bn2bin(bn, buf);
17702c9a247fSWyllys Ingersoll 	/*
17712c9a247fSWyllys Ingersoll 	 * Return the desired length since we prepended it
17722c9a247fSWyllys Ingersoll 	 * with the necessary 0x00 padding.
17732c9a247fSWyllys Ingersoll 	 */
17742c9a247fSWyllys Ingersoll 	return (len);
1775e65e5c2dSWyllys Ingersoll }
1776e65e5c2dSWyllys Ingersoll 
177799ebb4caSwyllys KMF_RETURN
177899ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
177999ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
178099ebb4caSwyllys {
178199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
178299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
178399ebb4caSwyllys 	KMF_ALGORITHM_INDEX		AlgId;
178499ebb4caSwyllys 	EVP_MD_CTX ctx;
178599ebb4caSwyllys 	const EVP_MD *md;
178602744e81Swyllys 
178799ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
178899ebb4caSwyllys 	    tobesigned == NULL || output == NULL ||
178999ebb4caSwyllys 	    tobesigned->Data == NULL ||
179099ebb4caSwyllys 	    output->Data == NULL)
179199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
179299ebb4caSwyllys 
179399ebb4caSwyllys 	/* Map the OID to an OpenSSL algorithm */
179430a5e8faSwyllys 	AlgId = x509_algoid_to_algid(AlgOID);
179599ebb4caSwyllys 	if (AlgId == KMF_ALGID_NONE)
1796e65e5c2dSWyllys Ingersoll 		return (KMF_ERR_BAD_ALGORITHM);
179799ebb4caSwyllys 
179899ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
179999ebb4caSwyllys 		EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
180099ebb4caSwyllys 		uchar_t *p;
180102744e81Swyllys 		int len;
180299ebb4caSwyllys 		if (AlgId == KMF_ALGID_MD5WithRSA)
180399ebb4caSwyllys 			md = EVP_md5();
180499ebb4caSwyllys 		else if (AlgId == KMF_ALGID_SHA1WithRSA)
180599ebb4caSwyllys 			md = EVP_sha1();
1806e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA256WithRSA)
1807e65e5c2dSWyllys Ingersoll 			md = EVP_sha256();
1808e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA384WithRSA)
1809e65e5c2dSWyllys Ingersoll 			md = EVP_sha384();
1810e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA512WithRSA)
1811e65e5c2dSWyllys Ingersoll 			md = EVP_sha512();
181202744e81Swyllys 		else if (AlgId == KMF_ALGID_RSA)
181302744e81Swyllys 			md = NULL;
181499ebb4caSwyllys 		else
1815e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_ALGORITHM);
181699ebb4caSwyllys 
181702744e81Swyllys 		if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
181802744e81Swyllys 			RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
181999ebb4caSwyllys 
182002744e81Swyllys 			p = output->Data;
182102744e81Swyllys 			if ((len = RSA_private_encrypt(tobesigned->Length,
182202744e81Swyllys 			    tobesigned->Data, p, rsa,
182302744e81Swyllys 			    RSA_PKCS1_PADDING)) <= 0) {
182402744e81Swyllys 				SET_ERROR(kmfh, ERR_get_error());
182502744e81Swyllys 				ret = KMF_ERR_INTERNAL;
182602744e81Swyllys 			}
182702744e81Swyllys 			output->Length = len;
182802744e81Swyllys 		} else {
182999ebb4caSwyllys 			(void) EVP_MD_CTX_init(&ctx);
183099ebb4caSwyllys 			(void) EVP_SignInit_ex(&ctx, md, NULL);
183199ebb4caSwyllys 			(void) EVP_SignUpdate(&ctx, tobesigned->Data,
183299ebb4caSwyllys 			    (uint32_t)tobesigned->Length);
183399ebb4caSwyllys 			len = (uint32_t)output->Length;
183499ebb4caSwyllys 			p = output->Data;
183502744e81Swyllys 			if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) {
183699ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
183702744e81Swyllys 				len = 0;
183802744e81Swyllys 				ret = KMF_ERR_INTERNAL;
183999ebb4caSwyllys 			}
184099ebb4caSwyllys 			output->Length = len;
184199ebb4caSwyllys 			(void) EVP_MD_CTX_cleanup(&ctx);
184202744e81Swyllys 		}
184399ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
184499ebb4caSwyllys 		DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
184599ebb4caSwyllys 
184699ebb4caSwyllys 		uchar_t hash[EVP_MAX_MD_SIZE];
184799ebb4caSwyllys 		uint32_t hashlen;
184899ebb4caSwyllys 		DSA_SIG *dsasig;
184999ebb4caSwyllys 
1850e65e5c2dSWyllys Ingersoll 		if (AlgId == KMF_ALGID_DSA ||
1851e65e5c2dSWyllys Ingersoll 		    AlgId == KMF_ALGID_SHA1WithDSA)
1852e65e5c2dSWyllys Ingersoll 			md = EVP_sha1();
1853e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA256WithDSA)
1854e65e5c2dSWyllys Ingersoll 			md = EVP_sha256();
1855e65e5c2dSWyllys Ingersoll 		else /* Bad algorithm */
1856e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_ALGORITHM);
1857e65e5c2dSWyllys Ingersoll 
185899ebb4caSwyllys 		/*
185999ebb4caSwyllys 		 * OpenSSL EVP_Sign operation automatically converts to
186099ebb4caSwyllys 		 * ASN.1 output so we do the operations separately so we
186199ebb4caSwyllys 		 * are assured of NOT getting ASN.1 output returned.
186299ebb4caSwyllys 		 * KMF does not want ASN.1 encoded results because
186399ebb4caSwyllys 		 * not all mechanisms return ASN.1 encodings (PKCS#11
186499ebb4caSwyllys 		 * and NSS return raw signature data).
186599ebb4caSwyllys 		 */
186699ebb4caSwyllys 		EVP_MD_CTX_init(&ctx);
186799ebb4caSwyllys 		(void) EVP_DigestInit_ex(&ctx, md, NULL);
186899ebb4caSwyllys 		(void) EVP_DigestUpdate(&ctx, tobesigned->Data,
186999ebb4caSwyllys 		    tobesigned->Length);
187099ebb4caSwyllys 		(void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
187199ebb4caSwyllys 
1872e65e5c2dSWyllys Ingersoll 		/* Only sign first 20 bytes for SHA2 */
1873e65e5c2dSWyllys Ingersoll 		if (AlgId == KMF_ALGID_SHA256WithDSA)
1874e65e5c2dSWyllys Ingersoll 			hashlen = 20;
187599ebb4caSwyllys 		dsasig = DSA_do_sign(hash, hashlen, dsa);
187699ebb4caSwyllys 		if (dsasig != NULL) {
187799ebb4caSwyllys 			int i;
1878e65e5c2dSWyllys Ingersoll 			output->Length = i = fixbnlen(dsasig->r, output->Data,
1879e65e5c2dSWyllys Ingersoll 			    hashlen);
18802c9a247fSWyllys Ingersoll 
1881e65e5c2dSWyllys Ingersoll 			output->Length += fixbnlen(dsasig->s, &output->Data[i],
1882e65e5c2dSWyllys Ingersoll 			    hashlen);
18832c9a247fSWyllys Ingersoll 
188499ebb4caSwyllys 			DSA_SIG_free(dsasig);
188599ebb4caSwyllys 		} else {
188699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
188799ebb4caSwyllys 		}
1888e65e5c2dSWyllys Ingersoll 		(void) EVP_MD_CTX_cleanup(&ctx);
188999ebb4caSwyllys 	} else {
189099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
189199ebb4caSwyllys 	}
189299ebb4caSwyllys cleanup:
189399ebb4caSwyllys 	return (ret);
189499ebb4caSwyllys }
189599ebb4caSwyllys 
189699ebb4caSwyllys KMF_RETURN
189799ebb4caSwyllys /*ARGSUSED*/
189830a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle,
189930a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
190099ebb4caSwyllys {
190199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
190230a5e8faSwyllys 	KMF_KEY_HANDLE *key;
190330a5e8faSwyllys 	boolean_t destroy = B_TRUE;
190430a5e8faSwyllys 
190530a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
190699ebb4caSwyllys 	if (key == NULL || key->keyp == NULL)
190799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
190899ebb4caSwyllys 
190930a5e8faSwyllys 	rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
191030a5e8faSwyllys 	    (void *)&destroy, NULL);
191130a5e8faSwyllys 	if (rv != KMF_OK) {
191230a5e8faSwyllys 		/* "destroy" is optional. Default is TRUE */
191330a5e8faSwyllys 		rv = KMF_OK;
191430a5e8faSwyllys 	}
191530a5e8faSwyllys 
191699ebb4caSwyllys 	if (key->keyclass != KMF_ASYM_PUB &&
191799ebb4caSwyllys 	    key->keyclass != KMF_ASYM_PRI &&
191899ebb4caSwyllys 	    key->keyclass != KMF_SYMMETRIC)
191999ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
192099ebb4caSwyllys 
192199ebb4caSwyllys 	if (key->keyclass == KMF_SYMMETRIC) {
192230a5e8faSwyllys 		kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
192399ebb4caSwyllys 		key->keyp = NULL;
192499ebb4caSwyllys 	} else {
192599ebb4caSwyllys 		if (key->keyp != NULL) {
192699ebb4caSwyllys 			EVP_PKEY_free(key->keyp);
192799ebb4caSwyllys 			key->keyp = NULL;
192899ebb4caSwyllys 		}
192999ebb4caSwyllys 	}
193099ebb4caSwyllys 
193199ebb4caSwyllys 	if (key->keylabel != NULL) {
193299ebb4caSwyllys 		EVP_PKEY *pkey = NULL;
193399ebb4caSwyllys 		/* If the file exists, make sure it is a proper key. */
193499ebb4caSwyllys 		pkey = openssl_load_key(handle, key->keylabel);
193599ebb4caSwyllys 		if (pkey == NULL) {
19365b3e1433Swyllys 			if (key->keylabel != NULL) {
193799ebb4caSwyllys 				free(key->keylabel);
193899ebb4caSwyllys 				key->keylabel = NULL;
19395b3e1433Swyllys 			}
194099ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
194199ebb4caSwyllys 		}
194299ebb4caSwyllys 		EVP_PKEY_free(pkey);
194399ebb4caSwyllys 
194499ebb4caSwyllys 		if (destroy) {
194599ebb4caSwyllys 			if (unlink(key->keylabel) != 0) {
194699ebb4caSwyllys 				KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
194799ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
194899ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
194999ebb4caSwyllys 			}
195099ebb4caSwyllys 		}
195199ebb4caSwyllys 		if (key->keylabel != NULL) {
195299ebb4caSwyllys 			free(key->keylabel);
195399ebb4caSwyllys 			key->keylabel = NULL;
195499ebb4caSwyllys 		}
195599ebb4caSwyllys 	}
195699ebb4caSwyllys 	return (rv);
195799ebb4caSwyllys }
195899ebb4caSwyllys 
195999ebb4caSwyllys KMF_RETURN
196099ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
196199ebb4caSwyllys {
196299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
196399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
196499ebb4caSwyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
196599ebb4caSwyllys 
196699ebb4caSwyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
196799ebb4caSwyllys 	if (strlen(str)) {
196899ebb4caSwyllys 		*msgstr = (char *)strdup(str);
196999ebb4caSwyllys 		if ((*msgstr) == NULL)
197099ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
197199ebb4caSwyllys 	} else {
197299ebb4caSwyllys 		*msgstr = NULL;
197399ebb4caSwyllys 	}
197499ebb4caSwyllys 
197599ebb4caSwyllys 	return (ret);
197699ebb4caSwyllys }
197799ebb4caSwyllys 
197899ebb4caSwyllys static int
197999ebb4caSwyllys ext2NID(int kmfext)
198099ebb4caSwyllys {
198199ebb4caSwyllys 	switch (kmfext) {
198299ebb4caSwyllys 		case KMF_X509_EXT_KEY_USAGE:
198399ebb4caSwyllys 			return (NID_key_usage);
198499ebb4caSwyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
198599ebb4caSwyllys 			return (NID_private_key_usage_period);
198699ebb4caSwyllys 		case KMF_X509_EXT_CERT_POLICIES:
198799ebb4caSwyllys 			return (NID_certificate_policies);
198899ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
198999ebb4caSwyllys 			return (NID_subject_alt_name);
199099ebb4caSwyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
199199ebb4caSwyllys 			return (NID_issuer_alt_name);
199299ebb4caSwyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
199399ebb4caSwyllys 			return (NID_basic_constraints);
199499ebb4caSwyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
199599ebb4caSwyllys 			return (NID_ext_key_usage);
199699ebb4caSwyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
199799ebb4caSwyllys 			return (NID_authority_key_identifier);
199899ebb4caSwyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
199999ebb4caSwyllys 			return (NID_crl_distribution_points);
200099ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
200199ebb4caSwyllys 			return (NID_subject_key_identifier);
200299ebb4caSwyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
200399ebb4caSwyllys 			return (OBJ_sn2nid("policyMappings"));
200499ebb4caSwyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
200599ebb4caSwyllys 			return (OBJ_sn2nid("nameConstraints"));
200699ebb4caSwyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
200799ebb4caSwyllys 			return (OBJ_sn2nid("policyConstraints"));
200899ebb4caSwyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
200999ebb4caSwyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
201099ebb4caSwyllys 		case KMF_X509_EXT_FRESHEST_CRL:
201199ebb4caSwyllys 			return (OBJ_sn2nid("freshestCRL"));
201299ebb4caSwyllys 		default:
201399ebb4caSwyllys 			return (NID_undef);
201499ebb4caSwyllys 	}
201599ebb4caSwyllys }
201699ebb4caSwyllys 
201799ebb4caSwyllys KMF_RETURN
201899ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
201999ebb4caSwyllys 	KMF_PRINTABLE_ITEM flag, char *resultStr)
202099ebb4caSwyllys {
202199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
202299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
202399ebb4caSwyllys 	X509 *xcert = NULL;
202499ebb4caSwyllys 	unsigned char *outbuf = NULL;
202599ebb4caSwyllys 	unsigned char *outbuf_p;
202699ebb4caSwyllys 	char *tmpstr = NULL;
202799ebb4caSwyllys 	int j;
202899ebb4caSwyllys 	int ext_index, nid, len;
202999ebb4caSwyllys 	BIO *mem = NULL;
203070f9559bSTheo Schlossnagle #if OPENSSL_VERSION_NUMBER < 0x10000000L
203199ebb4caSwyllys 	STACK *emlst = NULL;
203270f9559bSTheo Schlossnagle #else
203370f9559bSTheo Schlossnagle 	STACK_OF(OPENSSL_STRING) *emlst = NULL;
203470f9559bSTheo Schlossnagle #endif
203599ebb4caSwyllys 	X509_EXTENSION *ex;
203699ebb4caSwyllys 	X509_CINF *ci;
203799ebb4caSwyllys 
203899ebb4caSwyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
203999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
204099ebb4caSwyllys 	}
204199ebb4caSwyllys 
204299ebb4caSwyllys 	/* copy cert data to outbuf */
204399ebb4caSwyllys 	outbuf = malloc(pcert->Length);
204499ebb4caSwyllys 	if (outbuf == NULL) {
204599ebb4caSwyllys 		return (KMF_ERR_MEMORY);
204699ebb4caSwyllys 	}
204799ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
204899ebb4caSwyllys 
204999ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
205099ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
205199ebb4caSwyllys 	if (xcert == NULL) {
205299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
205399ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
205499ebb4caSwyllys 		goto out;
205599ebb4caSwyllys 	}
205699ebb4caSwyllys 
205799ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
205899ebb4caSwyllys 	if (mem == NULL) {
205999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
206099ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
206199ebb4caSwyllys 		goto out;
206299ebb4caSwyllys 	}
206399ebb4caSwyllys 
206499ebb4caSwyllys 	switch (flag) {
206599ebb4caSwyllys 	case KMF_CERT_ISSUER:
206699ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
206799ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
206899ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
206999ebb4caSwyllys 		break;
207099ebb4caSwyllys 
207199ebb4caSwyllys 	case KMF_CERT_SUBJECT:
207299ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
207399ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
207499ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
207599ebb4caSwyllys 		break;
207699ebb4caSwyllys 
207799ebb4caSwyllys 	case KMF_CERT_VERSION:
207899ebb4caSwyllys 		tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version);
207999ebb4caSwyllys 		(void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN);
208099ebb4caSwyllys 		OPENSSL_free(tmpstr);
208199ebb4caSwyllys 		len = strlen(resultStr);
208299ebb4caSwyllys 		break;
208399ebb4caSwyllys 
208499ebb4caSwyllys 	case KMF_CERT_SERIALNUM:
208599ebb4caSwyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
208699ebb4caSwyllys 			(void) strcpy(resultStr, "0x");
208799ebb4caSwyllys 			len = BIO_gets(mem, &resultStr[2],
208899ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN - 2);
208999ebb4caSwyllys 		}
209099ebb4caSwyllys 		break;
209199ebb4caSwyllys 
209299ebb4caSwyllys 	case KMF_CERT_NOTBEFORE:
209399ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notBefore(xcert));
209499ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
209599ebb4caSwyllys 		break;
209699ebb4caSwyllys 
209799ebb4caSwyllys 	case KMF_CERT_NOTAFTER:
209899ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notAfter(xcert));
209999ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
210099ebb4caSwyllys 		break;
210199ebb4caSwyllys 
210299ebb4caSwyllys 	case KMF_CERT_PUBKEY_DATA:
210399ebb4caSwyllys 		{
210499ebb4caSwyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
210599ebb4caSwyllys 			if (pkey == NULL) {
210699ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
210799ebb4caSwyllys 				ret = KMF_ERR_ENCODING;
210899ebb4caSwyllys 				goto out;
210999ebb4caSwyllys 			}
211099ebb4caSwyllys 
211199ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
211299ebb4caSwyllys 				(void) BIO_printf(mem,
211399ebb4caSwyllys 				    "RSA Public Key: (%d bit)\n",
211499ebb4caSwyllys 				    BN_num_bits(pkey->pkey.rsa->n));
211599ebb4caSwyllys 				(void) RSA_print(mem, pkey->pkey.rsa, 0);
211699ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
211799ebb4caSwyllys 				(void) BIO_printf(mem,
211899ebb4caSwyllys 				    "%12sDSA Public Key:\n", "");
211999ebb4caSwyllys 				(void) DSA_print(mem, pkey->pkey.dsa, 0);
212099ebb4caSwyllys 			} else {
212199ebb4caSwyllys 				(void) BIO_printf(mem,
212299ebb4caSwyllys 				    "%12sUnknown Public Key:\n", "");
212399ebb4caSwyllys 			}
212499ebb4caSwyllys 			(void) BIO_printf(mem, "\n");
212599ebb4caSwyllys 			EVP_PKEY_free(pkey);
212699ebb4caSwyllys 		}
212799ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
212899ebb4caSwyllys 		break;
212999ebb4caSwyllys 	case KMF_CERT_SIGNATURE_ALG:
213099ebb4caSwyllys 	case KMF_CERT_PUBKEY_ALG:
213199ebb4caSwyllys 		if (flag == KMF_CERT_SIGNATURE_ALG) {
213299ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
213399ebb4caSwyllys 			    xcert->sig_alg->algorithm);
213499ebb4caSwyllys 		} else {
213599ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
213699ebb4caSwyllys 			    xcert->cert_info->key->algor->algorithm);
213799ebb4caSwyllys 		}
213899ebb4caSwyllys 
213999ebb4caSwyllys 		if (len > 0) {
214099ebb4caSwyllys 			len = BIO_read(mem, resultStr,
214199ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN);
214299ebb4caSwyllys 		}
214399ebb4caSwyllys 		break;
214499ebb4caSwyllys 
214599ebb4caSwyllys 	case KMF_CERT_EMAIL:
214699ebb4caSwyllys 		emlst = X509_get1_email(xcert);
214770f9559bSTheo Schlossnagle #if OPENSSL_VERSION_NUMBER < 0x10000000L
214899ebb4caSwyllys 		for (j = 0; j < sk_num(emlst); j++)
214999ebb4caSwyllys 			(void) BIO_printf(mem, "%s\n", sk_value(emlst, j));
215070f9559bSTheo Schlossnagle #else
215170f9559bSTheo Schlossnagle 		for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
215270f9559bSTheo Schlossnagle 			(void) BIO_printf(mem, "%s\n",
215370f9559bSTheo Schlossnagle 			    sk_OPENSSL_STRING_value(emlst, j));
215470f9559bSTheo Schlossnagle #endif
215599ebb4caSwyllys 
215699ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
215799ebb4caSwyllys 		X509_email_free(emlst);
215899ebb4caSwyllys 		break;
215999ebb4caSwyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
216099ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
216199ebb4caSwyllys 	case KMF_X509_EXT_KEY_USAGE:
216299ebb4caSwyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
216399ebb4caSwyllys 	case KMF_X509_EXT_CERT_POLICIES:
216499ebb4caSwyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
216599ebb4caSwyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
216699ebb4caSwyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
216799ebb4caSwyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
216899ebb4caSwyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
216999ebb4caSwyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
217099ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
217199ebb4caSwyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
217299ebb4caSwyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
217399ebb4caSwyllys 	case KMF_X509_EXT_FRESHEST_CRL:
217499ebb4caSwyllys 		nid = ext2NID(flag);
217599ebb4caSwyllys 		if (nid == NID_undef) {
217699ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
217799ebb4caSwyllys 			goto out;
217899ebb4caSwyllys 		}
217999ebb4caSwyllys 		ci = xcert->cert_info;
218099ebb4caSwyllys 
218199ebb4caSwyllys 		ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1);
218299ebb4caSwyllys 		if (ext_index == -1) {
218399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
218499ebb4caSwyllys 
218599ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
218699ebb4caSwyllys 			goto out;
218799ebb4caSwyllys 		}
218899ebb4caSwyllys 		ex = X509v3_get_ext(ci->extensions, ext_index);
218999ebb4caSwyllys 
219099ebb4caSwyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
219199ebb4caSwyllys 
219299ebb4caSwyllys 		if (BIO_printf(mem, ": %s\n",
219330a5e8faSwyllys 		    X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
219499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
219599ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
219699ebb4caSwyllys 			goto out;
219799ebb4caSwyllys 		}
219899ebb4caSwyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
219999ebb4caSwyllys 			(void) BIO_printf(mem, "%*s", 4, "");
220099ebb4caSwyllys 			(void) M_ASN1_OCTET_STRING_print(mem, ex->value);
220199ebb4caSwyllys 		}
220299ebb4caSwyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
220399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
220499ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
220599ebb4caSwyllys 			goto out;
220699ebb4caSwyllys 		}
220799ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
220899ebb4caSwyllys 	}
220999ebb4caSwyllys 	if (len <= 0) {
221099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
221199ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
221299ebb4caSwyllys 	}
221399ebb4caSwyllys 
221499ebb4caSwyllys out:
221599ebb4caSwyllys 	if (outbuf != NULL) {
221699ebb4caSwyllys 		free(outbuf);
221799ebb4caSwyllys 	}
221899ebb4caSwyllys 
221999ebb4caSwyllys 	if (xcert != NULL) {
222099ebb4caSwyllys 		X509_free(xcert);
222199ebb4caSwyllys 	}
222299ebb4caSwyllys 
222399ebb4caSwyllys 	if (mem != NULL) {
222499ebb4caSwyllys 		(void) BIO_free(mem);
222599ebb4caSwyllys 	}
222699ebb4caSwyllys 
222799ebb4caSwyllys 	return (ret);
222899ebb4caSwyllys }
222930a5e8faSwyllys 
223099ebb4caSwyllys KMF_RETURN
223199ebb4caSwyllys /*ARGSUSED*/
223230a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
223330a5e8faSwyllys     KMF_ATTRIBUTE *attrlist)
223499ebb4caSwyllys {
223599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
223630a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
223730a5e8faSwyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
223830a5e8faSwyllys 	KMF_KEY_HANDLE *key = NULL;
223930a5e8faSwyllys 	uint32_t numkeys = 1; /* 1 key only */
224030a5e8faSwyllys 	char *dirpath = NULL;
224130a5e8faSwyllys 	char *keyfile = NULL;
224230a5e8faSwyllys 	KMF_ATTRIBUTE new_attrlist[16];
224330a5e8faSwyllys 	int i = 0;
224499ebb4caSwyllys 
224599ebb4caSwyllys 	/*
224699ebb4caSwyllys 	 * This is really just a FindKey operation, reuse the
224799ebb4caSwyllys 	 * FindKey function.
224899ebb4caSwyllys 	 */
224930a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
225030a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
225130a5e8faSwyllys 	i++;
225299ebb4caSwyllys 
225330a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
225430a5e8faSwyllys 	    KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
225530a5e8faSwyllys 	i++;
225699ebb4caSwyllys 
225730a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
225830a5e8faSwyllys 	    KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
225930a5e8faSwyllys 	i++;
226030a5e8faSwyllys 
226130a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
226230a5e8faSwyllys 	if (key == NULL) {
226330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
226430a5e8faSwyllys 	} else {
226530a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
226630a5e8faSwyllys 		    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
226730a5e8faSwyllys 		i++;
226830a5e8faSwyllys 	}
226930a5e8faSwyllys 
227030a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
227130a5e8faSwyllys 	if (dirpath != NULL) {
227230a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
227330a5e8faSwyllys 		    KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
227430a5e8faSwyllys 		i++;
227530a5e8faSwyllys 	}
227630a5e8faSwyllys 
227730a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
227830a5e8faSwyllys 	if (keyfile == NULL)
227930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
228030a5e8faSwyllys 	else {
228130a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
228230a5e8faSwyllys 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
228330a5e8faSwyllys 		i++;
228430a5e8faSwyllys 	}
228530a5e8faSwyllys 
228630a5e8faSwyllys 	rv = OpenSSL_FindKey(handle, i, new_attrlist);
228799ebb4caSwyllys 	return (rv);
228899ebb4caSwyllys }
228999ebb4caSwyllys 
229099ebb4caSwyllys KMF_RETURN
229199ebb4caSwyllys /*ARGSUSED*/
229299ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
229399ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
229499ebb4caSwyllys 	KMF_DATA *output)
229599ebb4caSwyllys {
229699ebb4caSwyllys 	KMF_RETURN		ret = KMF_OK;
229799ebb4caSwyllys 	RSA *rsa = NULL;
229899ebb4caSwyllys 	unsigned int in_len = 0, out_len = 0;
229999ebb4caSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
230099ebb4caSwyllys 	uint8_t *in_data, *out_data;
230199ebb4caSwyllys 	int i, blocks;
230299ebb4caSwyllys 
230399ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
230499ebb4caSwyllys 	    ciphertext == NULL || output == NULL ||
230599ebb4caSwyllys 	    ciphertext->Data == NULL ||
230699ebb4caSwyllys 	    output->Data == NULL)
230799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
230899ebb4caSwyllys 
230999ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
231099ebb4caSwyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
231199ebb4caSwyllys 		modulus_len = RSA_size(rsa);
231299ebb4caSwyllys 	} else {
231399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
231499ebb4caSwyllys 	}
231599ebb4caSwyllys 
231699ebb4caSwyllys 	blocks = ciphertext->Length/modulus_len;
231799ebb4caSwyllys 	out_data = output->Data;
231899ebb4caSwyllys 	in_data = ciphertext->Data;
231999ebb4caSwyllys 	out_len = modulus_len - 11;
232099ebb4caSwyllys 	in_len = modulus_len;
232199ebb4caSwyllys 
232299ebb4caSwyllys 	for (i = 0; i < blocks; i++) {
232399ebb4caSwyllys 		out_len  = RSA_private_decrypt(in_len,
232499ebb4caSwyllys 		    in_data, out_data, rsa, RSA_PKCS1_PADDING);
232599ebb4caSwyllys 
232699ebb4caSwyllys 		if (out_len == 0) {
232799ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
232899ebb4caSwyllys 			goto cleanup;
232999ebb4caSwyllys 		}
233099ebb4caSwyllys 
233199ebb4caSwyllys 		out_data += out_len;
233299ebb4caSwyllys 		total_decrypted += out_len;
233399ebb4caSwyllys 		in_data += in_len;
233499ebb4caSwyllys 	}
233599ebb4caSwyllys 
233699ebb4caSwyllys 	output->Length = total_decrypted;
233799ebb4caSwyllys 
233899ebb4caSwyllys cleanup:
233999ebb4caSwyllys 	RSA_free(rsa);
234099ebb4caSwyllys 	if (ret != KMF_OK)
234199ebb4caSwyllys 		output->Length = 0;
234299ebb4caSwyllys 
234399ebb4caSwyllys 	return (ret);
234499ebb4caSwyllys 
234599ebb4caSwyllys }
234699ebb4caSwyllys 
234799ebb4caSwyllys /*
234899ebb4caSwyllys  *  This function will create a certid from issuer_cert and user_cert.
234999ebb4caSwyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
235099ebb4caSwyllys  *  certid memory after use.
235199ebb4caSwyllys  */
235299ebb4caSwyllys static KMF_RETURN
235399ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
235499ebb4caSwyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
235599ebb4caSwyllys {
235699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
235799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
235899ebb4caSwyllys 	X509   *issuer = NULL;
235999ebb4caSwyllys 	X509   *cert = NULL;
236099ebb4caSwyllys 	unsigned char *ptmp;
236199ebb4caSwyllys 
236299ebb4caSwyllys 	if (issuer_cert == NULL || user_cert == NULL) {
236399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
236499ebb4caSwyllys 	}
236599ebb4caSwyllys 
236699ebb4caSwyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
236799ebb4caSwyllys 	ptmp = issuer_cert->Data;
236899ebb4caSwyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
236999ebb4caSwyllys 	    issuer_cert->Length);
237099ebb4caSwyllys 	if (issuer == NULL) {
237199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
237299ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
237399ebb4caSwyllys 		goto end;
237499ebb4caSwyllys 	}
237599ebb4caSwyllys 
237699ebb4caSwyllys 	/* convert the DER-encoded user cert to an internal X509 */
237799ebb4caSwyllys 	ptmp = user_cert->Data;
237899ebb4caSwyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
237999ebb4caSwyllys 	    user_cert->Length);
238099ebb4caSwyllys 	if (cert == NULL) {
238199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
238299ebb4caSwyllys 
238399ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
238499ebb4caSwyllys 		goto end;
238599ebb4caSwyllys 	}
238699ebb4caSwyllys 
238799ebb4caSwyllys 	/* create a CERTID */
238899ebb4caSwyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
238999ebb4caSwyllys 	if (*certid == NULL) {
239099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
239199ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
239299ebb4caSwyllys 		goto end;
239399ebb4caSwyllys 	}
239499ebb4caSwyllys 
239599ebb4caSwyllys end:
239699ebb4caSwyllys 	if (issuer != NULL) {
239799ebb4caSwyllys 		X509_free(issuer);
239899ebb4caSwyllys 	}
239999ebb4caSwyllys 
240099ebb4caSwyllys 	if (cert != NULL) {
240199ebb4caSwyllys 		X509_free(cert);
240299ebb4caSwyllys 	}
240399ebb4caSwyllys 
240499ebb4caSwyllys 	return (ret);
240599ebb4caSwyllys }
240699ebb4caSwyllys 
240799ebb4caSwyllys KMF_RETURN
240830a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
240930a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
241099ebb4caSwyllys {
241199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
241299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
241399ebb4caSwyllys 	OCSP_CERTID *id = NULL;
241499ebb4caSwyllys 	OCSP_REQUEST *req = NULL;
241599ebb4caSwyllys 	BIO *derbio = NULL;
241630a5e8faSwyllys 	char *reqfile;
241730a5e8faSwyllys 	KMF_DATA *issuer_cert;
241830a5e8faSwyllys 	KMF_DATA *user_cert;
241999ebb4caSwyllys 
242030a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
242130a5e8faSwyllys 	    attrlist, numattr);
242230a5e8faSwyllys 	if (user_cert == NULL)
242399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
242499ebb4caSwyllys 
242530a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
242630a5e8faSwyllys 	    attrlist, numattr);
242730a5e8faSwyllys 	if (issuer_cert == NULL)
242830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
242930a5e8faSwyllys 
243030a5e8faSwyllys 	reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
243130a5e8faSwyllys 	    attrlist, numattr);
243230a5e8faSwyllys 	if (reqfile == NULL)
243330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
243430a5e8faSwyllys 
243530a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
243699ebb4caSwyllys 	if (ret != KMF_OK) {
243799ebb4caSwyllys 		return (ret);
243899ebb4caSwyllys 	}
243999ebb4caSwyllys 
244099ebb4caSwyllys 	/* Create an OCSP request */
244199ebb4caSwyllys 	req = OCSP_REQUEST_new();
244299ebb4caSwyllys 	if (req == NULL) {
244399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
244499ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
244599ebb4caSwyllys 		goto end;
244699ebb4caSwyllys 	}
244799ebb4caSwyllys 
244899ebb4caSwyllys 	if (!OCSP_request_add0_id(req, id)) {
244999ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
245099ebb4caSwyllys 		goto end;
245199ebb4caSwyllys 	}
245299ebb4caSwyllys 
245399ebb4caSwyllys 	/* Write the request to the output file with DER encoding */
245499ebb4caSwyllys 	derbio = BIO_new_file(reqfile, "wb");
245599ebb4caSwyllys 	if (!derbio) {
245699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
245799ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
245899ebb4caSwyllys 		goto end;
245999ebb4caSwyllys 	}
246099ebb4caSwyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
246199ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
246299ebb4caSwyllys 	}
246399ebb4caSwyllys 
246499ebb4caSwyllys end:
246599ebb4caSwyllys 	/*
2466e65e5c2dSWyllys Ingersoll 	 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2467a2d4930dSDan OpenSolaris Anderson 	 * will also deallocate certid's space.
246899ebb4caSwyllys 	 */
246999ebb4caSwyllys 	if (req != NULL) {
247099ebb4caSwyllys 		OCSP_REQUEST_free(req);
247199ebb4caSwyllys 	}
247299ebb4caSwyllys 
247399ebb4caSwyllys 	if (derbio != NULL) {
247499ebb4caSwyllys 		(void) BIO_free(derbio);
247599ebb4caSwyllys 	}
247699ebb4caSwyllys 
247799ebb4caSwyllys 	return (ret);
247899ebb4caSwyllys }
247999ebb4caSwyllys 
248099ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */
248199ebb4caSwyllys static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
248299ebb4caSwyllys {
248399ebb4caSwyllys 	int i;
248499ebb4caSwyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
248599ebb4caSwyllys 
248699ebb4caSwyllys 	/* Easy if lookup by name */
248799ebb4caSwyllys 	if (id->type == V_OCSP_RESPID_NAME)
248899ebb4caSwyllys 		return (X509_find_by_subject(certs, id->value.byName));
248999ebb4caSwyllys 
249099ebb4caSwyllys 	/* Lookup by key hash */
249199ebb4caSwyllys 
249299ebb4caSwyllys 	/* If key hash isn't SHA1 length then forget it */
249399ebb4caSwyllys 	if (id->value.byKey->length != SHA_DIGEST_LENGTH)
249499ebb4caSwyllys 		return (NULL);
249599ebb4caSwyllys 
249699ebb4caSwyllys 	keyhash = id->value.byKey->data;
249799ebb4caSwyllys 	/* Calculate hash of each key and compare */
249899ebb4caSwyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
2499d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
250099ebb4caSwyllys 		X509 *x = sk_X509_value(certs, i);
25015b3e1433Swyllys 		/* Use pubkey_digest to get the key ID value */
250299ebb4caSwyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
250399ebb4caSwyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
250499ebb4caSwyllys 			return (x);
250599ebb4caSwyllys 	}
250699ebb4caSwyllys 	return (NULL);
250799ebb4caSwyllys }
250899ebb4caSwyllys 
250999ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */
2510a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */
251199ebb4caSwyllys static int
251299ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
251399ebb4caSwyllys     X509_STORE *st, unsigned long flags)
251499ebb4caSwyllys {
251599ebb4caSwyllys 	X509 *signer;
251699ebb4caSwyllys 	OCSP_RESPID *rid = bs->tbsResponseData->responderId;
251799ebb4caSwyllys 	if ((signer = ocsp_find_signer_sk(certs, rid)))	{
251899ebb4caSwyllys 		*psigner = signer;
251999ebb4caSwyllys 		return (2);
252099ebb4caSwyllys 	}
252199ebb4caSwyllys 	if (!(flags & OCSP_NOINTERN) &&
252299ebb4caSwyllys 	    (signer = ocsp_find_signer_sk(bs->certs, rid))) {
252399ebb4caSwyllys 		*psigner = signer;
252499ebb4caSwyllys 		return (1);
252599ebb4caSwyllys 	}
252699ebb4caSwyllys 	/* Maybe lookup from store if by subject name */
252799ebb4caSwyllys 
252899ebb4caSwyllys 	*psigner = NULL;
252999ebb4caSwyllys 	return (0);
253099ebb4caSwyllys }
253199ebb4caSwyllys 
253299ebb4caSwyllys /*
253399ebb4caSwyllys  * This function will verify the signature of a basic response, using
253499ebb4caSwyllys  * the public key from the OCSP responder certificate.
253599ebb4caSwyllys  */
253699ebb4caSwyllys static KMF_RETURN
253799ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
253899ebb4caSwyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
253999ebb4caSwyllys {
254099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
254199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
254299ebb4caSwyllys 	STACK_OF(X509) *cert_stack = NULL;
254399ebb4caSwyllys 	X509 *signer = NULL;
254499ebb4caSwyllys 	X509 *issuer = NULL;
254599ebb4caSwyllys 	EVP_PKEY *skey = NULL;
254699ebb4caSwyllys 	unsigned char *ptmp;
254799ebb4caSwyllys 
254899ebb4caSwyllys 
254999ebb4caSwyllys 	if (bs == NULL || issuer_cert == NULL)
255099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
255199ebb4caSwyllys 
255299ebb4caSwyllys 	/*
255399ebb4caSwyllys 	 * Find the certificate that signed the basic response.
255499ebb4caSwyllys 	 *
255599ebb4caSwyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
255699ebb4caSwyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
255799ebb4caSwyllys 	 * If we still do not find a signer, we will look for it from the
255899ebb4caSwyllys 	 * certificate list came with the response file.
255999ebb4caSwyllys 	 */
256099ebb4caSwyllys 	if (signer_cert != NULL) {
256199ebb4caSwyllys 		ptmp = signer_cert->Data;
256299ebb4caSwyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
256399ebb4caSwyllys 		    signer_cert->Length);
256499ebb4caSwyllys 		if (signer == NULL) {
256599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
256699ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
256799ebb4caSwyllys 			goto end;
256899ebb4caSwyllys 		}
256999ebb4caSwyllys 	} else {
257099ebb4caSwyllys 		/*
257199ebb4caSwyllys 		 * Convert the issuer cert into X509 and push it into a
257299ebb4caSwyllys 		 * stack to be used by ocsp_find_signer().
257399ebb4caSwyllys 		 */
257499ebb4caSwyllys 		ptmp = issuer_cert->Data;
257599ebb4caSwyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
257699ebb4caSwyllys 		    issuer_cert->Length);
257799ebb4caSwyllys 		if (issuer == NULL) {
257899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
257999ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
258099ebb4caSwyllys 			goto end;
258199ebb4caSwyllys 		}
258299ebb4caSwyllys 
258399ebb4caSwyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
258499ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
258599ebb4caSwyllys 			goto end;
258699ebb4caSwyllys 		}
258799ebb4caSwyllys 
258899ebb4caSwyllys 		if (sk_X509_push(cert_stack, issuer) == NULL) {
258999ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
259099ebb4caSwyllys 			goto end;
259199ebb4caSwyllys 		}
259299ebb4caSwyllys 
259399ebb4caSwyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
259499ebb4caSwyllys 		if (!ret) {
259599ebb4caSwyllys 			/* can not find the signer */
259699ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
259799ebb4caSwyllys 			goto end;
259899ebb4caSwyllys 		}
259999ebb4caSwyllys 	}
260099ebb4caSwyllys 
260199ebb4caSwyllys 	/* Verify the signature of the response */
260299ebb4caSwyllys 	skey = X509_get_pubkey(signer);
260399ebb4caSwyllys 	if (skey == NULL) {
260499ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
260599ebb4caSwyllys 		goto end;
260699ebb4caSwyllys 	}
260799ebb4caSwyllys 
260899ebb4caSwyllys 	ret = OCSP_BASICRESP_verify(bs, skey, 0);
260999ebb4caSwyllys 	if (ret == 0) {
261099ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
261199ebb4caSwyllys 		goto end;
261299ebb4caSwyllys 	}
261399ebb4caSwyllys 
261499ebb4caSwyllys end:
261599ebb4caSwyllys 	if (issuer != NULL) {
261699ebb4caSwyllys 		X509_free(issuer);
261799ebb4caSwyllys 	}
261899ebb4caSwyllys 
261999ebb4caSwyllys 	if (signer != NULL) {
262099ebb4caSwyllys 		X509_free(signer);
262199ebb4caSwyllys 	}
262299ebb4caSwyllys 
262399ebb4caSwyllys 	if (skey != NULL) {
262499ebb4caSwyllys 		EVP_PKEY_free(skey);
262599ebb4caSwyllys 	}
262699ebb4caSwyllys 
262799ebb4caSwyllys 	if (cert_stack != NULL) {
262899ebb4caSwyllys 		sk_X509_free(cert_stack);
262999ebb4caSwyllys 	}
263099ebb4caSwyllys 
263199ebb4caSwyllys 	return (ret);
263299ebb4caSwyllys }
263399ebb4caSwyllys 
263499ebb4caSwyllys 
263599ebb4caSwyllys 
263699ebb4caSwyllys KMF_RETURN
263799ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
263830a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
263999ebb4caSwyllys {
264099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
264199ebb4caSwyllys 	BIO *derbio = NULL;
264299ebb4caSwyllys 	OCSP_RESPONSE *resp = NULL;
264399ebb4caSwyllys 	OCSP_BASICRESP *bs = NULL;
264499ebb4caSwyllys 	OCSP_CERTID *id = NULL;
264599ebb4caSwyllys 	OCSP_SINGLERESP *single = NULL;
264699ebb4caSwyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
264799ebb4caSwyllys 	int index, status, reason;
264830a5e8faSwyllys 	KMF_DATA *issuer_cert;
264930a5e8faSwyllys 	KMF_DATA *user_cert;
265030a5e8faSwyllys 	KMF_DATA *signer_cert;
265130a5e8faSwyllys 	KMF_DATA *response;
265230a5e8faSwyllys 	int *response_reason, *response_status, *cert_status;
265330a5e8faSwyllys 	boolean_t ignore_response_sign = B_FALSE;	/* default is FALSE */
265430a5e8faSwyllys 	uint32_t response_lifetime;
265599ebb4caSwyllys 
265630a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
265730a5e8faSwyllys 	    attrlist, numattr);
265830a5e8faSwyllys 	if (issuer_cert == NULL)
265999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
266099ebb4caSwyllys 
266130a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
266230a5e8faSwyllys 	    attrlist, numattr);
266330a5e8faSwyllys 	if (user_cert == NULL)
266499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
266530a5e8faSwyllys 
266630a5e8faSwyllys 	response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
266730a5e8faSwyllys 	    attrlist, numattr);
266830a5e8faSwyllys 	if (response == NULL)
266930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
267030a5e8faSwyllys 
267130a5e8faSwyllys 	response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
267230a5e8faSwyllys 	    attrlist, numattr);
267330a5e8faSwyllys 	if (response_status == NULL)
267430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
267530a5e8faSwyllys 
267630a5e8faSwyllys 	response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
267730a5e8faSwyllys 	    attrlist, numattr);
267830a5e8faSwyllys 	if (response_reason == NULL)
267930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
268030a5e8faSwyllys 
268130a5e8faSwyllys 	cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
268230a5e8faSwyllys 	    attrlist, numattr);
268330a5e8faSwyllys 	if (cert_status == NULL)
268430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
268599ebb4caSwyllys 
268699ebb4caSwyllys 	/* Read in the response */
268730a5e8faSwyllys 	derbio = BIO_new_mem_buf(response->Data, response->Length);
268899ebb4caSwyllys 	if (!derbio) {
268999ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
269099ebb4caSwyllys 		return (ret);
269199ebb4caSwyllys 	}
269299ebb4caSwyllys 
269399ebb4caSwyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
269499ebb4caSwyllys 	if (resp == NULL) {
269599ebb4caSwyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
269699ebb4caSwyllys 		goto end;
269799ebb4caSwyllys 	}
269899ebb4caSwyllys 
269999ebb4caSwyllys 	/* Check the response status */
270099ebb4caSwyllys 	status = OCSP_response_status(resp);
270130a5e8faSwyllys 	*response_status = status;
270299ebb4caSwyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
270399ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
270499ebb4caSwyllys 		goto end;
270599ebb4caSwyllys 	}
270699ebb4caSwyllys 
270799ebb4caSwyllys #ifdef DEBUG
270899ebb4caSwyllys 	printf("Successfully checked the response file status.\n");
270999ebb4caSwyllys #endif /* DEBUG */
271099ebb4caSwyllys 
271199ebb4caSwyllys 	/* Extract basic response */
271299ebb4caSwyllys 	bs = OCSP_response_get1_basic(resp);
271399ebb4caSwyllys 	if (bs == NULL) {
271499ebb4caSwyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
271599ebb4caSwyllys 		goto end;
271699ebb4caSwyllys 	}
271799ebb4caSwyllys 
271899ebb4caSwyllys #ifdef DEBUG
271999ebb4caSwyllys 	printf("Successfully retrieved the basic response.\n");
272099ebb4caSwyllys #endif /* DEBUG */
272199ebb4caSwyllys 
272299ebb4caSwyllys 	/* Check the basic response signature if required */
272330a5e8faSwyllys 	ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
272430a5e8faSwyllys 	    (void *)&ignore_response_sign, NULL);
272530a5e8faSwyllys 	if (ret != KMF_OK)
272630a5e8faSwyllys 		ret = KMF_OK;
272730a5e8faSwyllys 
272830a5e8faSwyllys 	signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
272930a5e8faSwyllys 	    attrlist, numattr);
273030a5e8faSwyllys 
273130a5e8faSwyllys 	if (ignore_response_sign == B_FALSE) {
273299ebb4caSwyllys 		ret = check_response_signature(handle, bs,
273330a5e8faSwyllys 		    signer_cert, issuer_cert);
273499ebb4caSwyllys 		if (ret != KMF_OK)
273599ebb4caSwyllys 			goto end;
273699ebb4caSwyllys 	}
273799ebb4caSwyllys 
273899ebb4caSwyllys #ifdef DEBUG
273999ebb4caSwyllys 	printf("Successfully verified the response signature.\n");
274099ebb4caSwyllys #endif /* DEBUG */
274199ebb4caSwyllys 
274299ebb4caSwyllys 	/* Create a certid for the certificate in question */
274330a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
274499ebb4caSwyllys 	if (ret != KMF_OK) {
274599ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
274699ebb4caSwyllys 		goto end;
274799ebb4caSwyllys 	}
274899ebb4caSwyllys 
274999ebb4caSwyllys #ifdef DEBUG
275099ebb4caSwyllys 	printf("successfully created a certid for the cert.\n");
275199ebb4caSwyllys #endif /* DEBUG */
275299ebb4caSwyllys 
275399ebb4caSwyllys 	/* Find the index of the single response for the certid */
275499ebb4caSwyllys 	index = OCSP_resp_find(bs, id, -1);
275599ebb4caSwyllys 	if (index < 0) {
275699ebb4caSwyllys 		/* cound not find this certificate in the response */
275799ebb4caSwyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
275899ebb4caSwyllys 		goto end;
275999ebb4caSwyllys 	}
276099ebb4caSwyllys 
276199ebb4caSwyllys #ifdef DEBUG
276299ebb4caSwyllys 	printf("Successfully found the single response index for the cert.\n");
276399ebb4caSwyllys #endif /* DEBUG */
276499ebb4caSwyllys 
276599ebb4caSwyllys 	/* Retrieve the single response and get the cert status */
276699ebb4caSwyllys 	single = OCSP_resp_get0(bs, index);
276799ebb4caSwyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
276899ebb4caSwyllys 	    &nextupd);
276999ebb4caSwyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
277030a5e8faSwyllys 		*cert_status = OCSP_GOOD;
277199ebb4caSwyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
277230a5e8faSwyllys 		*cert_status = OCSP_UNKNOWN;
277399ebb4caSwyllys 	} else { /* revoked */
277430a5e8faSwyllys 		*cert_status = OCSP_REVOKED;
277530a5e8faSwyllys 		*response_reason = reason;
277699ebb4caSwyllys 	}
277799ebb4caSwyllys 	ret = KMF_OK;
277899ebb4caSwyllys 
277930a5e8faSwyllys 	/* resp. time is optional, so we don't care about the return code. */
278030a5e8faSwyllys 	(void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
278130a5e8faSwyllys 	    (void *)&response_lifetime, NULL);
278230a5e8faSwyllys 
278399ebb4caSwyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
278430a5e8faSwyllys 	    response_lifetime)) {
278599ebb4caSwyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
278699ebb4caSwyllys 		goto end;
278799ebb4caSwyllys 	}
278899ebb4caSwyllys 
278999ebb4caSwyllys #ifdef DEBUG
279099ebb4caSwyllys 	printf("Successfully verify the time.\n");
279199ebb4caSwyllys #endif /* DEBUG */
279299ebb4caSwyllys 
279399ebb4caSwyllys end:
279499ebb4caSwyllys 	if (derbio != NULL)
279599ebb4caSwyllys 		(void) BIO_free(derbio);
279699ebb4caSwyllys 
279799ebb4caSwyllys 	if (resp != NULL)
279899ebb4caSwyllys 		OCSP_RESPONSE_free(resp);
279999ebb4caSwyllys 
280099ebb4caSwyllys 	if (bs != NULL)
280199ebb4caSwyllys 		OCSP_BASICRESP_free(bs);
280299ebb4caSwyllys 
280399ebb4caSwyllys 	if (id != NULL)
280499ebb4caSwyllys 		OCSP_CERTID_free(id);
280599ebb4caSwyllys 
280699ebb4caSwyllys 	return (ret);
280799ebb4caSwyllys }
280899ebb4caSwyllys 
280999ebb4caSwyllys static KMF_RETURN
281099ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path,
281199ebb4caSwyllys 	KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
281299ebb4caSwyllys {
281399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
281430a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
281599ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
281699ebb4caSwyllys 
281799ebb4caSwyllys 	if (keyclass == KMF_ASYM_PRI ||
281899ebb4caSwyllys 	    keyclass == KMF_ASYM_PUB) {
281999ebb4caSwyllys 		pkey = openssl_load_key(handle, path);
282099ebb4caSwyllys 		if (pkey == NULL) {
282199ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
282299ebb4caSwyllys 		}
282399ebb4caSwyllys 		if (key != NULL) {
282499ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA)
282599ebb4caSwyllys 				key->keyalg = KMF_RSA;
282699ebb4caSwyllys 			else if (pkey->type == EVP_PKEY_DSA)
282799ebb4caSwyllys 				key->keyalg = KMF_DSA;
282899ebb4caSwyllys 
282999ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
283099ebb4caSwyllys 			key->keyclass = keyclass;
283199ebb4caSwyllys 			key->keyp = (void *)pkey;
283299ebb4caSwyllys 			key->israw = FALSE;
28335b3e1433Swyllys 			if (path != NULL &&
28345b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
28355b3e1433Swyllys 				EVP_PKEY_free(pkey);
28365b3e1433Swyllys 				return (KMF_ERR_MEMORY);
28375b3e1433Swyllys 			}
283899ebb4caSwyllys 		} else {
283999ebb4caSwyllys 			EVP_PKEY_free(pkey);
284099ebb4caSwyllys 			pkey = NULL;
284199ebb4caSwyllys 		}
284299ebb4caSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
284399ebb4caSwyllys 		KMF_ENCODE_FORMAT fmt;
284499ebb4caSwyllys 		/*
284599ebb4caSwyllys 		 * If the file is a recognized format,
284699ebb4caSwyllys 		 * then it is NOT a symmetric key.
284799ebb4caSwyllys 		 */
284830a5e8faSwyllys 		rv = kmf_get_file_format(path, &fmt);
284999ebb4caSwyllys 		if (rv == KMF_OK || fmt != 0) {
285099ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
285199ebb4caSwyllys 		} else if (rv == KMF_ERR_ENCODING) {
285299ebb4caSwyllys 			/*
285399ebb4caSwyllys 			 * If we don't know the encoding,
285499ebb4caSwyllys 			 * it is probably  a symmetric key.
285599ebb4caSwyllys 			 */
285699ebb4caSwyllys 			rv = KMF_OK;
285730a5e8faSwyllys 		} else if (rv == KMF_ERR_OPEN_FILE) {
285830a5e8faSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
285999ebb4caSwyllys 		}
286099ebb4caSwyllys 
286199ebb4caSwyllys 		if (key != NULL) {
286299ebb4caSwyllys 			KMF_DATA keyvalue;
286399ebb4caSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
286499ebb4caSwyllys 			if (rkey == NULL) {
286599ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
286699ebb4caSwyllys 				goto out;
286799ebb4caSwyllys 			}
286899ebb4caSwyllys 
286999ebb4caSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
287030a5e8faSwyllys 			rv = kmf_read_input_file(handle, path, &keyvalue);
287199ebb4caSwyllys 			if (rv != KMF_OK)
287299ebb4caSwyllys 				goto out;
287399ebb4caSwyllys 
287499ebb4caSwyllys 			rkey->keydata.len = keyvalue.Length;
287599ebb4caSwyllys 			rkey->keydata.val = keyvalue.Data;
287699ebb4caSwyllys 
287799ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
287899ebb4caSwyllys 			key->keyclass = keyclass;
287999ebb4caSwyllys 			key->israw = TRUE;
288099ebb4caSwyllys 			key->keyp = (void *)rkey;
28815b3e1433Swyllys 			if (path != NULL &&
28825b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
28835b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
28845b3e1433Swyllys 			}
288599ebb4caSwyllys 		}
288699ebb4caSwyllys 	}
288799ebb4caSwyllys out:
288899ebb4caSwyllys 	if (rv != KMF_OK) {
288999ebb4caSwyllys 		if (rkey != NULL) {
289030a5e8faSwyllys 			kmf_free_raw_sym_key(rkey);
289199ebb4caSwyllys 		}
289299ebb4caSwyllys 		if (pkey != NULL)
289399ebb4caSwyllys 			EVP_PKEY_free(pkey);
289499ebb4caSwyllys 
289599ebb4caSwyllys 		if (key != NULL) {
289699ebb4caSwyllys 			key->keyalg = KMF_KEYALG_NONE;
289799ebb4caSwyllys 			key->keyclass = KMF_KEYCLASS_NONE;
289899ebb4caSwyllys 			key->keyp = NULL;
289999ebb4caSwyllys 		}
290099ebb4caSwyllys 	}
290199ebb4caSwyllys 
290299ebb4caSwyllys 	return (rv);
290399ebb4caSwyllys }
290499ebb4caSwyllys 
290599ebb4caSwyllys KMF_RETURN
290630a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle,
290730a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
290899ebb4caSwyllys {
290999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
291099ebb4caSwyllys 	char *fullpath = NULL;
2911f482c776Swyllys 	uint32_t maxkeys;
291230a5e8faSwyllys 	KMF_KEY_HANDLE *key;
291330a5e8faSwyllys 	uint32_t *numkeys;
291430a5e8faSwyllys 	KMF_KEY_CLASS keyclass;
291530a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
291630a5e8faSwyllys 	char *dirpath;
291730a5e8faSwyllys 	char *keyfile;
291899ebb4caSwyllys 
291930a5e8faSwyllys 	if (handle == NULL)
292099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
292199ebb4caSwyllys 
292230a5e8faSwyllys 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
292330a5e8faSwyllys 	if (numkeys == NULL)
292430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
292530a5e8faSwyllys 
292630a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
292730a5e8faSwyllys 	    (void *)&keyclass, NULL);
292830a5e8faSwyllys 	if (rv != KMF_OK)
292930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
293030a5e8faSwyllys 
293130a5e8faSwyllys 	if (keyclass != KMF_ASYM_PUB &&
293230a5e8faSwyllys 	    keyclass != KMF_ASYM_PRI &&
293330a5e8faSwyllys 	    keyclass != KMF_SYMMETRIC)
293499ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
293599ebb4caSwyllys 
293630a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
293730a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
293830a5e8faSwyllys 
293930a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
294099ebb4caSwyllys 
294199ebb4caSwyllys 	if (fullpath == NULL)
294299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
294399ebb4caSwyllys 
2944f482c776Swyllys 	maxkeys = *numkeys;
2945f482c776Swyllys 	if (maxkeys == 0)
2946f482c776Swyllys 		maxkeys = 0xFFFFFFFF;
294799ebb4caSwyllys 	*numkeys = 0;
294899ebb4caSwyllys 
294930a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
295030a5e8faSwyllys 	/* it is okay to have "keys" contains NULL */
295130a5e8faSwyllys 
295230a5e8faSwyllys 	/*
295330a5e8faSwyllys 	 * The caller may want a list of the raw key data as well.
295430a5e8faSwyllys 	 * Useful for importing keys from a file into other keystores.
295530a5e8faSwyllys 	 */
295630a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
295730a5e8faSwyllys 
295899ebb4caSwyllys 	if (isdir(fullpath)) {
295999ebb4caSwyllys 		DIR *dirp;
296099ebb4caSwyllys 		struct dirent *dp;
296199ebb4caSwyllys 		int n = 0;
296299ebb4caSwyllys 
296399ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
296499ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
296599ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
296699ebb4caSwyllys 		}
296799ebb4caSwyllys 		rewinddir(dirp);
2968f482c776Swyllys 		while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
296999ebb4caSwyllys 			if (strcmp(dp->d_name, ".") &&
297099ebb4caSwyllys 			    strcmp(dp->d_name, "..")) {
297199ebb4caSwyllys 				char *fname;
297299ebb4caSwyllys 
297399ebb4caSwyllys 				fname = get_fullpath(fullpath,
297499ebb4caSwyllys 				    (char *)&dp->d_name);
297599ebb4caSwyllys 
297699ebb4caSwyllys 				rv = fetch_key(handle, fname,
297730a5e8faSwyllys 				    keyclass, key ? &key[n] : NULL);
297899ebb4caSwyllys 
297930a5e8faSwyllys 				if (rv == KMF_OK) {
298030a5e8faSwyllys 					if (key != NULL && rawkey != NULL)
298130a5e8faSwyllys 						rv = convertToRawKey(
298230a5e8faSwyllys 						    key[n].keyp, &rawkey[n]);
298399ebb4caSwyllys 					n++;
298430a5e8faSwyllys 				}
298599ebb4caSwyllys 
298699ebb4caSwyllys 				if (rv != KMF_OK || key == NULL)
298799ebb4caSwyllys 					free(fname);
298899ebb4caSwyllys 			}
298999ebb4caSwyllys 		}
299099ebb4caSwyllys 		(void) closedir(dirp);
299199ebb4caSwyllys 		free(fullpath);
299299ebb4caSwyllys 		(*numkeys) = n;
299399ebb4caSwyllys 	} else {
299430a5e8faSwyllys 		rv = fetch_key(handle, fullpath, keyclass, key);
299599ebb4caSwyllys 		if (rv == KMF_OK)
299699ebb4caSwyllys 			(*numkeys) = 1;
299799ebb4caSwyllys 
299899ebb4caSwyllys 		if (rv != KMF_OK || key == NULL)
299999ebb4caSwyllys 			free(fullpath);
300030a5e8faSwyllys 
300130a5e8faSwyllys 		if (rv == KMF_OK && key != NULL && rawkey != NULL) {
300230a5e8faSwyllys 			rv = convertToRawKey(key->keyp, rawkey);
300330a5e8faSwyllys 		}
300499ebb4caSwyllys 	}
300599ebb4caSwyllys 
3006f482c776Swyllys 	if (rv == KMF_OK && (*numkeys) == 0)
300799ebb4caSwyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
300873cc0e02Swyllys 	else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
300973cc0e02Swyllys 		rv = KMF_OK;
301099ebb4caSwyllys 
301199ebb4caSwyllys 	return (rv);
301299ebb4caSwyllys }
301399ebb4caSwyllys 
301499ebb4caSwyllys #define	HANDLE_PK12_ERROR { \
301599ebb4caSwyllys 	SET_ERROR(kmfh, ERR_get_error()); \
301699ebb4caSwyllys 	rv = KMF_ERR_ENCODING; \
301799ebb4caSwyllys 	goto out; \
301899ebb4caSwyllys }
301999ebb4caSwyllys 
30205b3e1433Swyllys static int
30215b3e1433Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
302299ebb4caSwyllys {
30235b3e1433Swyllys 	if (xcert != NULL && xcert->aux != NULL &&
30245b3e1433Swyllys 	    xcert->aux->alias != NULL) {
30255b3e1433Swyllys 		if (PKCS12_add_friendlyname_asc(bag,
30265b3e1433Swyllys 		    (const char *)xcert->aux->alias->data,
30275b3e1433Swyllys 		    xcert->aux->alias->length) == 0)
30285b3e1433Swyllys 			return (0);
30295b3e1433Swyllys 	}
30305b3e1433Swyllys 	return (1);
30315b3e1433Swyllys }
30325b3e1433Swyllys 
30335b3e1433Swyllys static PKCS7 *
30345b3e1433Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
30355b3e1433Swyllys 	uchar_t *keyid, unsigned int keyidlen)
30365b3e1433Swyllys {
303799ebb4caSwyllys 	PKCS12_SAFEBAG *bag = NULL;
303899ebb4caSwyllys 	PKCS7 *cert_authsafe = NULL;
30395b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack;
304099ebb4caSwyllys 
304199ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
304299ebb4caSwyllys 	if (bag_stack == NULL)
30435b3e1433Swyllys 		return (NULL);
304499ebb4caSwyllys 
304599ebb4caSwyllys 	/* Convert cert from X509 struct to PKCS#12 bag */
304699ebb4caSwyllys 	bag = PKCS12_x5092certbag(sslcert);
304799ebb4caSwyllys 	if (bag == NULL) {
30485b3e1433Swyllys 		goto out;
304999ebb4caSwyllys 	}
305099ebb4caSwyllys 
305199ebb4caSwyllys 	/* Add the key id to the certificate bag. */
30525b3e1433Swyllys 	if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
30535b3e1433Swyllys 		goto out;
305499ebb4caSwyllys 	}
305599ebb4caSwyllys 
30565b3e1433Swyllys 	if (!add_alias_to_bag(bag, sslcert))
30575b3e1433Swyllys 		goto out;
30585b3e1433Swyllys 
305999ebb4caSwyllys 	/* Pile it on the bag_stack. */
306099ebb4caSwyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
30615b3e1433Swyllys 		goto out;
306299ebb4caSwyllys 	}
306399ebb4caSwyllys 	/* Turn bag_stack of certs into encrypted authsafe. */
306499ebb4caSwyllys 	cert_authsafe = PKCS12_pack_p7encdata(
306599ebb4caSwyllys 	    NID_pbe_WithSHA1And40BitRC2_CBC,
306634acef67Swyllys 	    cred->cred, cred->credlen, NULL, 0,
306734acef67Swyllys 	    PKCS12_DEFAULT_ITER, bag_stack);
306899ebb4caSwyllys 
30695b3e1433Swyllys out:
30705b3e1433Swyllys 	if (bag_stack != NULL)
307199ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
307299ebb4caSwyllys 
30735b3e1433Swyllys 	return (cert_authsafe);
307499ebb4caSwyllys }
30755b3e1433Swyllys 
30765b3e1433Swyllys static PKCS7 *
30775b3e1433Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
30785b3e1433Swyllys 	uchar_t *keyid,  unsigned int keyidlen,
30795b3e1433Swyllys 	char *label, int label_len)
30805b3e1433Swyllys {
30815b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
30825b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
30835b3e1433Swyllys 	PKCS12_SAFEBAG *bag = NULL;
30845b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
30855b3e1433Swyllys 
308699ebb4caSwyllys 	p8 = EVP_PKEY2PKCS8(pkey);
308799ebb4caSwyllys 	if (p8 == NULL) {
30885b3e1433Swyllys 		return (NULL);
308999ebb4caSwyllys 	}
309099ebb4caSwyllys 	/* Put the shrouded key into a PKCS#12 bag. */
309199ebb4caSwyllys 	bag = PKCS12_MAKE_SHKEYBAG(
309299ebb4caSwyllys 	    NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
309399ebb4caSwyllys 	    cred->cred, cred->credlen,
309499ebb4caSwyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, p8);
309599ebb4caSwyllys 
309699ebb4caSwyllys 	/* Clean up the PKCS#8 shrouded key, don't need it now. */
309799ebb4caSwyllys 	PKCS8_PRIV_KEY_INFO_free(p8);
309899ebb4caSwyllys 	p8 = NULL;
309999ebb4caSwyllys 
310099ebb4caSwyllys 	if (bag == NULL) {
31015b3e1433Swyllys 		return (NULL);
310299ebb4caSwyllys 	}
31035b3e1433Swyllys 	if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
31045b3e1433Swyllys 		goto out;
31055b3e1433Swyllys 	if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
31065b3e1433Swyllys 		goto out;
31075b3e1433Swyllys 
310899ebb4caSwyllys 	/* Start a PKCS#12 safebag container for the private key. */
310999ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
31105b3e1433Swyllys 	if (bag_stack == NULL)
31115b3e1433Swyllys 		goto out;
311299ebb4caSwyllys 
311399ebb4caSwyllys 	/* Pile on the private key on the bag_stack. */
31145b3e1433Swyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
31155b3e1433Swyllys 		goto out;
31165b3e1433Swyllys 
311799ebb4caSwyllys 	key_authsafe = PKCS12_pack_p7data(bag_stack);
311899ebb4caSwyllys 
31195b3e1433Swyllys out:
31205b3e1433Swyllys 	if (bag_stack != NULL)
312199ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
312299ebb4caSwyllys 	bag_stack = NULL;
31235b3e1433Swyllys 	return (key_authsafe);
312499ebb4caSwyllys }
312599ebb4caSwyllys 
312699ebb4caSwyllys static EVP_PKEY *
312799ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
312899ebb4caSwyllys {
312999ebb4caSwyllys 	RSA		*rsa = NULL;
313099ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
313199ebb4caSwyllys 
313299ebb4caSwyllys 	if ((rsa = RSA_new()) == NULL)
313399ebb4caSwyllys 		return (NULL);
313499ebb4caSwyllys 
313599ebb4caSwyllys 	if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL)
313699ebb4caSwyllys 		return (NULL);
313799ebb4caSwyllys 
313899ebb4caSwyllys 	if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) ==
313999ebb4caSwyllys 	    NULL)
314099ebb4caSwyllys 		return (NULL);
314199ebb4caSwyllys 
314299ebb4caSwyllys 	if (key->priexp.val != NULL)
314399ebb4caSwyllys 		if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len,
314499ebb4caSwyllys 		    rsa->d)) == NULL)
314599ebb4caSwyllys 			return (NULL);
314699ebb4caSwyllys 
314799ebb4caSwyllys 	if (key->prime1.val != NULL)
314899ebb4caSwyllys 		if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len,
314999ebb4caSwyllys 		    rsa->p)) == NULL)
315099ebb4caSwyllys 			return (NULL);
315199ebb4caSwyllys 
315299ebb4caSwyllys 	if (key->prime2.val != NULL)
315399ebb4caSwyllys 		if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len,
315499ebb4caSwyllys 		    rsa->q)) == NULL)
315599ebb4caSwyllys 			return (NULL);
315699ebb4caSwyllys 
315799ebb4caSwyllys 	if (key->exp1.val != NULL)
315899ebb4caSwyllys 		if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len,
315999ebb4caSwyllys 		    rsa->dmp1)) == NULL)
316099ebb4caSwyllys 			return (NULL);
316199ebb4caSwyllys 
316299ebb4caSwyllys 	if (key->exp2.val != NULL)
316399ebb4caSwyllys 		if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len,
316499ebb4caSwyllys 		    rsa->dmq1)) == NULL)
316599ebb4caSwyllys 			return (NULL);
316699ebb4caSwyllys 
316799ebb4caSwyllys 	if (key->coef.val != NULL)
316899ebb4caSwyllys 		if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len,
316999ebb4caSwyllys 		    rsa->iqmp)) == NULL)
317099ebb4caSwyllys 			return (NULL);
317199ebb4caSwyllys 
317299ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
317399ebb4caSwyllys 		return (NULL);
317499ebb4caSwyllys 
317599ebb4caSwyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
317699ebb4caSwyllys 
317799ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
317899ebb4caSwyllys 	RSA_free(rsa);
317999ebb4caSwyllys 
318099ebb4caSwyllys 	return (newkey);
318199ebb4caSwyllys }
318299ebb4caSwyllys 
318399ebb4caSwyllys static EVP_PKEY *
318499ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
318599ebb4caSwyllys {
318699ebb4caSwyllys 	DSA		*dsa = NULL;
318799ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
318899ebb4caSwyllys 
318999ebb4caSwyllys 	if ((dsa = DSA_new()) == NULL)
319099ebb4caSwyllys 		return (NULL);
319199ebb4caSwyllys 
319299ebb4caSwyllys 	if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len,
319399ebb4caSwyllys 	    dsa->p)) == NULL)
319499ebb4caSwyllys 		return (NULL);
319599ebb4caSwyllys 
319699ebb4caSwyllys 	if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len,
319799ebb4caSwyllys 	    dsa->q)) == NULL)
319899ebb4caSwyllys 		return (NULL);
319999ebb4caSwyllys 
320099ebb4caSwyllys 	if ((dsa->g = BN_bin2bn(key->base.val, key->base.len,
320199ebb4caSwyllys 	    dsa->g)) == NULL)
320299ebb4caSwyllys 		return (NULL);
320399ebb4caSwyllys 
320499ebb4caSwyllys 	if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len,
320599ebb4caSwyllys 	    dsa->priv_key)) == NULL)
320699ebb4caSwyllys 		return (NULL);
320799ebb4caSwyllys 
320830a5e8faSwyllys 	if (key->pubvalue.val != NULL) {
320930a5e8faSwyllys 		if ((dsa->pub_key = BN_bin2bn(key->pubvalue.val,
321030a5e8faSwyllys 		    key->pubvalue.len, dsa->pub_key)) == NULL)
321130a5e8faSwyllys 			return (NULL);
321230a5e8faSwyllys 	}
321330a5e8faSwyllys 
321499ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
321599ebb4caSwyllys 		return (NULL);
321699ebb4caSwyllys 
321799ebb4caSwyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
321899ebb4caSwyllys 
321999ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
322099ebb4caSwyllys 	DSA_free(dsa);
322199ebb4caSwyllys 	return (newkey);
322299ebb4caSwyllys }
322399ebb4caSwyllys 
32245b3e1433Swyllys static EVP_PKEY *
32255b3e1433Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key)
32265b3e1433Swyllys {
32275b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
32285b3e1433Swyllys 	KMF_RAW_KEY_DATA *rawkey;
32295b3e1433Swyllys 	ASN1_TYPE *attr = NULL;
32305b3e1433Swyllys 	KMF_RETURN ret;
32315b3e1433Swyllys 
32325b3e1433Swyllys 	if (key == NULL || !key->israw)
32335b3e1433Swyllys 		return (NULL);
32345b3e1433Swyllys 
32355b3e1433Swyllys 	rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
32365b3e1433Swyllys 	if (rawkey->keytype == KMF_RSA) {
32375b3e1433Swyllys 		pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
32385b3e1433Swyllys 	} else if (rawkey->keytype == KMF_DSA) {
32395b3e1433Swyllys 		pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
3240e65e5c2dSWyllys Ingersoll 	} else if (rawkey->keytype == KMF_ECDSA) {
3241e65e5c2dSWyllys Ingersoll 		/*
3242e65e5c2dSWyllys Ingersoll 		 * OpenSSL in Solaris does not support EC for
3243e65e5c2dSWyllys Ingersoll 		 * legal reasons
3244e65e5c2dSWyllys Ingersoll 		 */
3245e65e5c2dSWyllys Ingersoll 		return (NULL);
32465b3e1433Swyllys 	} else {
32475b3e1433Swyllys 		/* wrong kind of key */
32485b3e1433Swyllys 		return (NULL);
32495b3e1433Swyllys 	}
32505b3e1433Swyllys 
32515b3e1433Swyllys 	if (rawkey->label != NULL) {
32525b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
32535b3e1433Swyllys 			EVP_PKEY_free(pkey);
32545b3e1433Swyllys 			return (NULL);
32555b3e1433Swyllys 		}
32565b3e1433Swyllys 		attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
32575b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
32585b3e1433Swyllys 		    strlen(rawkey->label));
32595b3e1433Swyllys 		attr->type = V_ASN1_BMPSTRING;
32605b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.bmpstring;
32615b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
32625b3e1433Swyllys 		if (ret != KMF_OK) {
32635b3e1433Swyllys 			EVP_PKEY_free(pkey);
32645b3e1433Swyllys 			ASN1_TYPE_free(attr);
32655b3e1433Swyllys 			return (NULL);
32665b3e1433Swyllys 		}
32675b3e1433Swyllys 	}
32685b3e1433Swyllys 	if (rawkey->id.Data != NULL) {
32695b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
32705b3e1433Swyllys 			EVP_PKEY_free(pkey);
32715b3e1433Swyllys 			return (NULL);
32725b3e1433Swyllys 		}
32735b3e1433Swyllys 		attr->value.octet_string =
32745b3e1433Swyllys 		    ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
32755b3e1433Swyllys 		attr->type = V_ASN1_OCTET_STRING;
32765b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.octet_string,
32775b3e1433Swyllys 		    rawkey->id.Data, rawkey->id.Length);
32785b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.octet_string;
32795b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
32805b3e1433Swyllys 		if (ret != KMF_OK) {
32815b3e1433Swyllys 			EVP_PKEY_free(pkey);
32825b3e1433Swyllys 			ASN1_TYPE_free(attr);
32835b3e1433Swyllys 			return (NULL);
32845b3e1433Swyllys 		}
32855b3e1433Swyllys 	}
32865b3e1433Swyllys 	return (pkey);
32875b3e1433Swyllys }
32885b3e1433Swyllys 
32895b3e1433Swyllys /*
32905b3e1433Swyllys  * Search a list of private keys to find one that goes with the certificate.
32915b3e1433Swyllys  */
32925b3e1433Swyllys static EVP_PKEY *
32935b3e1433Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
32945b3e1433Swyllys {
32955b3e1433Swyllys 	int i;
32965b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
32975b3e1433Swyllys 
32985b3e1433Swyllys 	if (numkeys == 0 || keylist == NULL || xcert == NULL)
32995b3e1433Swyllys 		return (NULL);
33005b3e1433Swyllys 	for (i = 0; i < numkeys; i++) {
33015b3e1433Swyllys 		if (keylist[i].israw)
33025b3e1433Swyllys 			pkey = raw_key_to_pkey(&keylist[i]);
33035b3e1433Swyllys 		else
33045b3e1433Swyllys 			pkey = (EVP_PKEY *)keylist[i].keyp;
33055b3e1433Swyllys 		if (pkey != NULL) {
33065b3e1433Swyllys 			if (X509_check_private_key(xcert, pkey)) {
33075b3e1433Swyllys 				return (pkey);
33085b3e1433Swyllys 			} else {
33095b3e1433Swyllys 				EVP_PKEY_free(pkey);
33105b3e1433Swyllys 				pkey = NULL;
33115b3e1433Swyllys 			}
33125b3e1433Swyllys 		}
33135b3e1433Swyllys 	}
33145b3e1433Swyllys 	return (pkey);
33155b3e1433Swyllys }
33165b3e1433Swyllys 
331799ebb4caSwyllys static KMF_RETURN
33185b3e1433Swyllys local_export_pk12(KMF_HANDLE_T handle,
331999ebb4caSwyllys 	KMF_CREDENTIAL *cred,
332099ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
332199ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
332299ebb4caSwyllys 	char *filename)
332399ebb4caSwyllys {
332499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
332599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
332699ebb4caSwyllys 	BIO *bio = NULL;
33275b3e1433Swyllys 	PKCS7 *cert_authsafe = NULL;
33285b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
33295b3e1433Swyllys 	STACK_OF(PKCS7) *authsafe_stack = NULL;
33305b3e1433Swyllys 	PKCS12 *p12_elem = NULL;
333199ebb4caSwyllys 	int i;
333299ebb4caSwyllys 
33335b3e1433Swyllys 	if (numcerts == 0 && numkeys == 0)
33345b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
33355b3e1433Swyllys 
333699ebb4caSwyllys 	/*
333799ebb4caSwyllys 	 * Open the output file.
333899ebb4caSwyllys 	 */
333999ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
334099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
334199ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
334299ebb4caSwyllys 		goto cleanup;
334399ebb4caSwyllys 	}
334499ebb4caSwyllys 
33455b3e1433Swyllys 	/* Start a PKCS#7 stack. */
33465b3e1433Swyllys 	authsafe_stack = sk_PKCS7_new_null();
33475b3e1433Swyllys 	if (authsafe_stack == NULL) {
33485b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
33495b3e1433Swyllys 		goto cleanup;
33505b3e1433Swyllys 	}
33515b3e1433Swyllys 	if (numcerts > 0) {
335299ebb4caSwyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
335399ebb4caSwyllys 			const uchar_t *p = certlist[i].certificate.Data;
335499ebb4caSwyllys 			long len = certlist[i].certificate.Length;
33555b3e1433Swyllys 			X509 *xcert = NULL;
33565b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
33575b3e1433Swyllys 			unsigned char keyid[EVP_MAX_MD_SIZE];
33585b3e1433Swyllys 			unsigned int keyidlen = 0;
335999ebb4caSwyllys 
336099ebb4caSwyllys 			xcert = d2i_X509(NULL, &p, len);
336199ebb4caSwyllys 			if (xcert == NULL) {
336299ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
336399ebb4caSwyllys 				rv = KMF_ERR_ENCODING;
336499ebb4caSwyllys 			}
33655b3e1433Swyllys 			if (certlist[i].kmf_private.label != NULL) {
33665b3e1433Swyllys 				/* Set alias attribute */
33675b3e1433Swyllys 				(void) X509_alias_set1(xcert,
33685b3e1433Swyllys 				    (uchar_t *)certlist[i].kmf_private.label,
33695b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label));
33705b3e1433Swyllys 			}
33715b3e1433Swyllys 			/* Check if there is a key corresponding to this cert */
33725b3e1433Swyllys 			pkey = find_matching_key(xcert, numkeys, keylist);
33735b3e1433Swyllys 
33745b3e1433Swyllys 			/*
33755b3e1433Swyllys 			 * If key is found, get fingerprint and create a
33765b3e1433Swyllys 			 * safebag.
33775b3e1433Swyllys 			 */
33785b3e1433Swyllys 			if (pkey != NULL) {
33795b3e1433Swyllys 				(void) X509_digest(xcert, EVP_sha1(),
33805b3e1433Swyllys 				    keyid, &keyidlen);
33815b3e1433Swyllys 				key_authsafe = add_key_to_safe(pkey, cred,
33825b3e1433Swyllys 				    keyid, keyidlen,
33835b3e1433Swyllys 				    certlist[i].kmf_private.label,
33845b3e1433Swyllys 				    (certlist[i].kmf_private.label ?
33855b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label) : 0));
33865b3e1433Swyllys 
33875b3e1433Swyllys 				if (key_authsafe == NULL) {
33885b3e1433Swyllys 					X509_free(xcert);
33895b3e1433Swyllys 					EVP_PKEY_free(pkey);
33905b3e1433Swyllys 					goto cleanup;
33915b3e1433Swyllys 				}
33925b3e1433Swyllys 				/* Put the key safe into the Auth Safe */
33935b3e1433Swyllys 				if (!sk_PKCS7_push(authsafe_stack,
33945b3e1433Swyllys 				    key_authsafe)) {
33955b3e1433Swyllys 					X509_free(xcert);
33965b3e1433Swyllys 					EVP_PKEY_free(pkey);
33975b3e1433Swyllys 					goto cleanup;
33985b3e1433Swyllys 				}
33995b3e1433Swyllys 			}
34005b3e1433Swyllys 
34015b3e1433Swyllys 			/* create a certificate safebag */
34025b3e1433Swyllys 			cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
34035b3e1433Swyllys 			    keyidlen);
34045b3e1433Swyllys 			if (cert_authsafe == NULL) {
34055b3e1433Swyllys 				X509_free(xcert);
34065b3e1433Swyllys 				EVP_PKEY_free(pkey);
34075b3e1433Swyllys 				goto cleanup;
34085b3e1433Swyllys 			}
34095b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
34105b3e1433Swyllys 				X509_free(xcert);
34115b3e1433Swyllys 				EVP_PKEY_free(pkey);
34125b3e1433Swyllys 				goto cleanup;
34135b3e1433Swyllys 			}
34145b3e1433Swyllys 
341599ebb4caSwyllys 			X509_free(xcert);
341699ebb4caSwyllys 			if (pkey)
341799ebb4caSwyllys 				EVP_PKEY_free(pkey);
341899ebb4caSwyllys 		}
34195b3e1433Swyllys 	} else if (numcerts == 0 && numkeys > 0) {
34205b3e1433Swyllys 		/*
34215b3e1433Swyllys 		 * If only adding keys to the file.
34225b3e1433Swyllys 		 */
34235b3e1433Swyllys 		for (i = 0; i < numkeys; i++) {
34245b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
34255b3e1433Swyllys 
34265b3e1433Swyllys 			if (keylist[i].israw)
34275b3e1433Swyllys 				pkey = raw_key_to_pkey(&keylist[i]);
34285b3e1433Swyllys 			else
34295b3e1433Swyllys 				pkey = (EVP_PKEY *)keylist[i].keyp;
34305b3e1433Swyllys 
34315b3e1433Swyllys 			if (pkey == NULL)
34325b3e1433Swyllys 				continue;
34335b3e1433Swyllys 
34345b3e1433Swyllys 			key_authsafe = add_key_to_safe(pkey, cred,
34355b3e1433Swyllys 			    NULL, 0, NULL, 0);
34365b3e1433Swyllys 
34375b3e1433Swyllys 			if (key_authsafe == NULL) {
34385b3e1433Swyllys 				EVP_PKEY_free(pkey);
34395b3e1433Swyllys 				goto cleanup;
34405b3e1433Swyllys 			}
34415b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
34425b3e1433Swyllys 				EVP_PKEY_free(pkey);
34435b3e1433Swyllys 				goto cleanup;
34445b3e1433Swyllys 			}
34455b3e1433Swyllys 		}
34465b3e1433Swyllys 	}
34475b3e1433Swyllys 	p12_elem = PKCS12_init(NID_pkcs7_data);
34485b3e1433Swyllys 	if (p12_elem == NULL) {
34495b3e1433Swyllys 		goto cleanup;
345099ebb4caSwyllys 	}
345199ebb4caSwyllys 
34525b3e1433Swyllys 	/* Put the PKCS#7 stack into the PKCS#12 element. */
34535b3e1433Swyllys 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
34545b3e1433Swyllys 		goto cleanup;
34555b3e1433Swyllys 	}
34565b3e1433Swyllys 
34575b3e1433Swyllys 	/* Set the integrity MAC on the PKCS#12 element. */
34585b3e1433Swyllys 	if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
34595b3e1433Swyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
34605b3e1433Swyllys 		goto cleanup;
34615b3e1433Swyllys 	}
34625b3e1433Swyllys 
34635b3e1433Swyllys 	/* Write the PKCS#12 element to the export file. */
34645b3e1433Swyllys 	if (!i2d_PKCS12_bio(bio, p12_elem)) {
34655b3e1433Swyllys 		goto cleanup;
34665b3e1433Swyllys 	}
34675b3e1433Swyllys 	PKCS12_free(p12_elem);
34685b3e1433Swyllys 
346999ebb4caSwyllys cleanup:
34705b3e1433Swyllys 	/* Clear away the PKCS#7 stack, we're done with it. */
34715b3e1433Swyllys 	if (authsafe_stack)
34725b3e1433Swyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
347399ebb4caSwyllys 
347499ebb4caSwyllys 	if (bio != NULL)
347599ebb4caSwyllys 		(void) BIO_free_all(bio);
347699ebb4caSwyllys 
347799ebb4caSwyllys 	return (rv);
347899ebb4caSwyllys }
347999ebb4caSwyllys 
348099ebb4caSwyllys KMF_RETURN
348130a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
348230a5e8faSwyllys     KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
348330a5e8faSwyllys     KMF_CREDENTIAL *p12cred, char *filename)
348430a5e8faSwyllys {
348530a5e8faSwyllys 	KMF_RETURN rv;
348630a5e8faSwyllys 
348730a5e8faSwyllys 	if (certlist == NULL && keylist == NULL)
348830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
348930a5e8faSwyllys 
34905b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, numcerts, certlist,
349130a5e8faSwyllys 	    numkeys, keylist, filename);
349230a5e8faSwyllys 
349330a5e8faSwyllys 	return (rv);
349430a5e8faSwyllys }
349530a5e8faSwyllys 
349630a5e8faSwyllys KMF_RETURN
349730a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
349899ebb4caSwyllys {
349999ebb4caSwyllys 	KMF_RETURN rv;
350099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
350199ebb4caSwyllys 	char *fullpath = NULL;
350230a5e8faSwyllys 	char *dirpath = NULL;
350330a5e8faSwyllys 	char *certfile = NULL;
350430a5e8faSwyllys 	char *keyfile = NULL;
350530a5e8faSwyllys 	char *filename = NULL;
350630a5e8faSwyllys 	KMF_CREDENTIAL *p12cred = NULL;
35075b3e1433Swyllys 	KMF_X509_DER_CERT certdata;
35085b3e1433Swyllys 	KMF_KEY_HANDLE key;
35095b3e1433Swyllys 	int gotkey = 0;
35105b3e1433Swyllys 	int gotcert = 0;
351130a5e8faSwyllys 
351230a5e8faSwyllys 	if (handle == NULL)
351330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
351499ebb4caSwyllys 
351599ebb4caSwyllys 	/*
351699ebb4caSwyllys 	 *  First, find the certificate.
351799ebb4caSwyllys 	 */
351830a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
351930a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
352030a5e8faSwyllys 	if (certfile != NULL) {
352130a5e8faSwyllys 		fullpath = get_fullpath(dirpath, certfile);
352299ebb4caSwyllys 		if (fullpath == NULL)
352399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
352499ebb4caSwyllys 
352599ebb4caSwyllys 		if (isdir(fullpath)) {
352699ebb4caSwyllys 			free(fullpath);
352799ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
352899ebb4caSwyllys 		}
352999ebb4caSwyllys 
35305b3e1433Swyllys 		(void) memset(&certdata, 0, sizeof (certdata));
35315b3e1433Swyllys 		rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL,
35325b3e1433Swyllys 		    fullpath, &certdata.certificate);
353399ebb4caSwyllys 		if (rv != KMF_OK)
353499ebb4caSwyllys 			goto end;
353530a5e8faSwyllys 
35365b3e1433Swyllys 		gotcert++;
35375b3e1433Swyllys 		certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
353830a5e8faSwyllys 		free(fullpath);
353999ebb4caSwyllys 	}
354099ebb4caSwyllys 
354199ebb4caSwyllys 	/*
354299ebb4caSwyllys 	 * Now find the private key.
354399ebb4caSwyllys 	 */
354430a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
354530a5e8faSwyllys 	if (keyfile != NULL) {
354630a5e8faSwyllys 		fullpath = get_fullpath(dirpath, keyfile);
354799ebb4caSwyllys 		if (fullpath == NULL)
354899ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
354999ebb4caSwyllys 
355099ebb4caSwyllys 		if (isdir(fullpath)) {
355199ebb4caSwyllys 			free(fullpath);
355299ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
355399ebb4caSwyllys 		}
355499ebb4caSwyllys 
35555b3e1433Swyllys 		(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
35565b3e1433Swyllys 		rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
35575b3e1433Swyllys 		if (rv != KMF_OK)
355899ebb4caSwyllys 			goto end;
35595b3e1433Swyllys 		gotkey++;
356099ebb4caSwyllys 	}
356199ebb4caSwyllys 
356299ebb4caSwyllys 	/*
356399ebb4caSwyllys 	 * Open the output file.
356499ebb4caSwyllys 	 */
356530a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
356630a5e8faSwyllys 	    numattr);
356730a5e8faSwyllys 	if (filename == NULL) {
356830a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
356930a5e8faSwyllys 		goto end;
357030a5e8faSwyllys 	}
357130a5e8faSwyllys 
357299ebb4caSwyllys 	/* Stick the key and the cert into a PKCS#12 file */
357330a5e8faSwyllys 	p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
357430a5e8faSwyllys 	if (p12cred == NULL) {
357530a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
357630a5e8faSwyllys 		goto end;
357730a5e8faSwyllys 	}
357830a5e8faSwyllys 
35795b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, 1, &certdata,
35805b3e1433Swyllys 	    1, &key, filename);
358199ebb4caSwyllys 
358299ebb4caSwyllys end:
358399ebb4caSwyllys 	if (fullpath)
358499ebb4caSwyllys 		free(fullpath);
358599ebb4caSwyllys 
35865b3e1433Swyllys 	if (gotcert)
35875b3e1433Swyllys 		kmf_free_kmf_cert(handle, &certdata);
35885b3e1433Swyllys 	if (gotkey)
35895b3e1433Swyllys 		kmf_free_kmf_key(handle, &key);
359099ebb4caSwyllys 	return (rv);
359199ebb4caSwyllys }
359299ebb4caSwyllys 
359371593db2Swyllys /*
359471593db2Swyllys  * Helper function to extract keys and certificates from
359571593db2Swyllys  * a single PEM file.  Typically the file should contain a
359671593db2Swyllys  * private key and an associated public key wrapped in an x509 cert.
359771593db2Swyllys  * However, the file may be just a list of X509 certs with no keys.
359871593db2Swyllys  */
359971593db2Swyllys static KMF_RETURN
360030a5e8faSwyllys extract_pem(KMF_HANDLE *kmfh,
360130a5e8faSwyllys 	char *issuer, char *subject, KMF_BIGINT *serial,
360202744e81Swyllys 	char *filename, CK_UTF8CHAR *pin,
360371593db2Swyllys 	CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
360471593db2Swyllys 	int *numcerts)
3605a2d4930dSDan OpenSolaris Anderson /* ARGSUSED6 */
360671593db2Swyllys {
360771593db2Swyllys 	KMF_RETURN rv = KMF_OK;
360871593db2Swyllys 	FILE *fp;
360934acef67Swyllys 	STACK_OF(X509_INFO) *x509_info_stack = NULL;
361002744e81Swyllys 	int i, ncerts = 0, matchcerts = 0;
361171593db2Swyllys 	EVP_PKEY *pkey = NULL;
361271593db2Swyllys 	X509_INFO *info;
361371593db2Swyllys 	X509 *x;
36145b3e1433Swyllys 	X509_INFO **cert_infos = NULL;
361571593db2Swyllys 	KMF_DATA *certlist = NULL;
361671593db2Swyllys 
361771593db2Swyllys 	if (priv_key)
361871593db2Swyllys 		*priv_key = NULL;
361971593db2Swyllys 	if (certs)
362071593db2Swyllys 		*certs = NULL;
362171593db2Swyllys 	fp = fopen(filename, "r");
36225b3e1433Swyllys 	if (fp == NULL)
362371593db2Swyllys 		return (KMF_ERR_OPEN_FILE);
36245b3e1433Swyllys 
362571593db2Swyllys 	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
362671593db2Swyllys 	if (x509_info_stack == NULL) {
362771593db2Swyllys 		(void) fclose(fp);
362871593db2Swyllys 		return (KMF_ERR_ENCODING);
362971593db2Swyllys 	}
36305b3e1433Swyllys 	cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
36315b3e1433Swyllys 	    sizeof (X509_INFO *));
36325b3e1433Swyllys 	if (cert_infos == NULL) {
36335b3e1433Swyllys 		(void) fclose(fp);
36345b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
36355b3e1433Swyllys 		goto err;
36365b3e1433Swyllys 	}
363771593db2Swyllys 
36385b3e1433Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3639d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
364034acef67Swyllys 		cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
364171593db2Swyllys 		ncerts++;
364271593db2Swyllys 	}
364371593db2Swyllys 
364471593db2Swyllys 	if (ncerts == 0) {
364571593db2Swyllys 		(void) fclose(fp);
364634acef67Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
364734acef67Swyllys 		goto err;
364871593db2Swyllys 	}
364971593db2Swyllys 
365071593db2Swyllys 	if (priv_key != NULL) {
365171593db2Swyllys 		rewind(fp);
365271593db2Swyllys 		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
365371593db2Swyllys 	}
365471593db2Swyllys 	(void) fclose(fp);
365571593db2Swyllys 
365671593db2Swyllys 	x = cert_infos[ncerts - 1]->x509;
365771593db2Swyllys 	/*
365871593db2Swyllys 	 * Make sure the private key matchs the last cert in the file.
365971593db2Swyllys 	 */
366071593db2Swyllys 	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
366171593db2Swyllys 		EVP_PKEY_free(pkey);
366234acef67Swyllys 		rv = KMF_ERR_KEY_MISMATCH;
366334acef67Swyllys 		goto err;
366471593db2Swyllys 	}
366571593db2Swyllys 
3666a2d4930dSDan OpenSolaris Anderson 	certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
366771593db2Swyllys 	if (certlist == NULL) {
366871593db2Swyllys 		if (pkey != NULL)
366971593db2Swyllys 			EVP_PKEY_free(pkey);
367034acef67Swyllys 		rv = KMF_ERR_MEMORY;
367134acef67Swyllys 		goto err;
367271593db2Swyllys 	}
367371593db2Swyllys 
367471593db2Swyllys 	/*
367571593db2Swyllys 	 * Convert all of the certs to DER format.
367671593db2Swyllys 	 */
367702744e81Swyllys 	matchcerts = 0;
367871593db2Swyllys 	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
367902744e81Swyllys 		boolean_t match = FALSE;
368071593db2Swyllys 		info =  cert_infos[ncerts - 1 - i];
368171593db2Swyllys 
368230a5e8faSwyllys 		rv = check_cert(info->x509, issuer, subject, serial, &match);
368302744e81Swyllys 		if (rv != KMF_OK || match != TRUE) {
368402744e81Swyllys 			rv = KMF_OK;
368502744e81Swyllys 			continue;
368602744e81Swyllys 		}
368702744e81Swyllys 
368802744e81Swyllys 		rv = ssl_cert2KMFDATA(kmfh, info->x509,
368902744e81Swyllys 			&certlist[matchcerts++]);
369071593db2Swyllys 
369171593db2Swyllys 		if (rv != KMF_OK) {
3692e65e5c2dSWyllys Ingersoll 			int j;
3693e65e5c2dSWyllys Ingersoll 			for (j = 0; j < matchcerts; j++)
3694e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certlist[j]);
369571593db2Swyllys 			free(certlist);
369671593db2Swyllys 			certlist = NULL;
369702744e81Swyllys 			ncerts = matchcerts = 0;
369871593db2Swyllys 		}
369971593db2Swyllys 	}
370071593db2Swyllys 
370171593db2Swyllys 	if (numcerts != NULL)
370202744e81Swyllys 		*numcerts = matchcerts;
3703a2d4930dSDan OpenSolaris Anderson 
3704e65e5c2dSWyllys Ingersoll 	if (certs != NULL)
370571593db2Swyllys 		*certs = certlist;
3706e65e5c2dSWyllys Ingersoll 	else if (certlist != NULL) {
3707e65e5c2dSWyllys Ingersoll 		for (i = 0; i < ncerts; i++)
3708e65e5c2dSWyllys Ingersoll 			kmf_free_data(&certlist[i]);
3709a2d4930dSDan OpenSolaris Anderson 		free(certlist);
3710a2d4930dSDan OpenSolaris Anderson 		certlist = NULL;
3711a2d4930dSDan OpenSolaris Anderson 	}
371271593db2Swyllys 
371371593db2Swyllys 	if (priv_key == NULL && pkey != NULL)
371471593db2Swyllys 		EVP_PKEY_free(pkey);
371571593db2Swyllys 	else if (priv_key != NULL && pkey != NULL)
371671593db2Swyllys 		*priv_key = pkey;
371771593db2Swyllys 
371834acef67Swyllys err:
371934acef67Swyllys 	/* Cleanup the stack of X509 info records */
372034acef67Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3721d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
372234acef67Swyllys 		info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
372334acef67Swyllys 		X509_INFO_free(info);
372434acef67Swyllys 	}
372534acef67Swyllys 	if (x509_info_stack)
372634acef67Swyllys 		sk_X509_INFO_free(x509_info_stack);
372734acef67Swyllys 
37285b3e1433Swyllys 	if (cert_infos != NULL)
37295b3e1433Swyllys 		free(cert_infos);
37305b3e1433Swyllys 
373171593db2Swyllys 	return (rv);
373271593db2Swyllys }
373371593db2Swyllys 
37345b3e1433Swyllys static KMF_RETURN
37355b3e1433Swyllys openssl_parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
37365b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
37375b3e1433Swyllys {
37385b3e1433Swyllys 	KMF_RETURN ret;
37395b3e1433Swyllys 	int i;
37405b3e1433Swyllys 
37415b3e1433Swyllys 	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
3742d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
37435b3e1433Swyllys 		PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
37445b3e1433Swyllys 		ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
37455b3e1433Swyllys 		    keys, certs);
37465b3e1433Swyllys 
37475b3e1433Swyllys 		if (ret != KMF_OK)
37485b3e1433Swyllys 			return (ret);
37495b3e1433Swyllys 	}
37505b3e1433Swyllys 
37515b3e1433Swyllys 	return (ret);
37525b3e1433Swyllys }
37535b3e1433Swyllys 
37545b3e1433Swyllys static KMF_RETURN
37555b3e1433Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
37565b3e1433Swyllys {
37575b3e1433Swyllys 	X509_ATTRIBUTE *attr = NULL;
37585b3e1433Swyllys 
37595b3e1433Swyllys 	if (pkey == NULL || attrib == NULL)
37605b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
37615b3e1433Swyllys 
37625b3e1433Swyllys 	if (pkey->attributes == NULL) {
37635b3e1433Swyllys 		pkey->attributes = sk_X509_ATTRIBUTE_new_null();
37645b3e1433Swyllys 		if (pkey->attributes == NULL)
37655b3e1433Swyllys 			return (KMF_ERR_MEMORY);
37665b3e1433Swyllys 	}
37675b3e1433Swyllys 	attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
37685b3e1433Swyllys 	if (attr != NULL) {
37695b3e1433Swyllys 		int i;
37705b3e1433Swyllys 		X509_ATTRIBUTE *a;
37715b3e1433Swyllys 		for (i = 0;
37725b3e1433Swyllys 		    i < sk_X509_ATTRIBUTE_num(pkey->attributes); i++) {
3773d7141854SRobert Mustacchi 			/* LINTED E_BAD_PTR_CASE_ALIGN */
37745b3e1433Swyllys 			a = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
37755b3e1433Swyllys 			if (OBJ_obj2nid(a->object) == nid) {
37765b3e1433Swyllys 				X509_ATTRIBUTE_free(a);
3777d7141854SRobert Mustacchi 				/* LINTED E_BAD_PTR_CAST_ALIGN */
377837bbd7ccSRichard Lowe 				(void) sk_X509_ATTRIBUTE_set(pkey->attributes,
37795b3e1433Swyllys 				    i, attr);
37805b3e1433Swyllys 				return (KMF_OK);
37815b3e1433Swyllys 			}
37825b3e1433Swyllys 		}
37835b3e1433Swyllys 		if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == NULL) {
37845b3e1433Swyllys 			X509_ATTRIBUTE_free(attr);
37855b3e1433Swyllys 			return (KMF_ERR_MEMORY);
37865b3e1433Swyllys 		}
37875b3e1433Swyllys 	} else {
37885b3e1433Swyllys 		return (KMF_ERR_MEMORY);
37895b3e1433Swyllys 	}
37905b3e1433Swyllys 
37915b3e1433Swyllys 	return (KMF_OK);
37925b3e1433Swyllys }
37935b3e1433Swyllys 
37945b3e1433Swyllys static KMF_RETURN
37955b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
37965b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
37975b3e1433Swyllys {
37985b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
37995b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
38005b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
38015b3e1433Swyllys 	X509 *xcert = NULL;
38025b3e1433Swyllys 	ASN1_TYPE *keyid = NULL;
38035b3e1433Swyllys 	ASN1_TYPE *fname = NULL;
38045b3e1433Swyllys 	uchar_t *data = NULL;
38055b3e1433Swyllys 
38065b3e1433Swyllys 	keyid = PKCS12_get_attr(bag, NID_localKeyID);
38075b3e1433Swyllys 	fname = PKCS12_get_attr(bag, NID_friendlyName);
38085b3e1433Swyllys 
38095b3e1433Swyllys 	switch (M_PKCS12_bag_type(bag)) {
38105b3e1433Swyllys 		case NID_keyBag:
38115b3e1433Swyllys 			if (keylist == NULL)
38125b3e1433Swyllys 				goto end;
38135b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(bag->value.keybag);
38145b3e1433Swyllys 			if (pkey == NULL)
38155b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38165b3e1433Swyllys 
38175b3e1433Swyllys 			break;
38185b3e1433Swyllys 		case NID_pkcs8ShroudedKeyBag:
38195b3e1433Swyllys 			if (keylist == NULL)
38205b3e1433Swyllys 				goto end;
38215b3e1433Swyllys 			p8 = M_PKCS12_decrypt_skey(bag, pass, passlen);
38225b3e1433Swyllys 			if (p8 == NULL)
38235b3e1433Swyllys 				return (KMF_ERR_AUTH_FAILED);
38245b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(p8);
38255b3e1433Swyllys 			PKCS8_PRIV_KEY_INFO_free(p8);
38265b3e1433Swyllys 			if (pkey == NULL)
38275b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38285b3e1433Swyllys 			break;
38295b3e1433Swyllys 		case NID_certBag:
38305b3e1433Swyllys 			if (certlist == NULL)
38315b3e1433Swyllys 				goto end;
38325b3e1433Swyllys 			if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate)
38335b3e1433Swyllys 				return (KMF_ERR_PKCS12_FORMAT);
38345b3e1433Swyllys 			xcert = M_PKCS12_certbag2x509(bag);
38355b3e1433Swyllys 			if (xcert == NULL) {
38365b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38375b3e1433Swyllys 				goto end;
38385b3e1433Swyllys 			}
38395b3e1433Swyllys 			if (keyid != NULL) {
38405b3e1433Swyllys 				if (X509_keyid_set1(xcert,
38415b3e1433Swyllys 				    keyid->value.octet_string->data,
38425b3e1433Swyllys 				    keyid->value.octet_string->length) == 0) {
38435b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
38445b3e1433Swyllys 					goto end;
38455b3e1433Swyllys 				}
38465b3e1433Swyllys 			}
38475b3e1433Swyllys 			if (fname != NULL) {
38485b3e1433Swyllys 				int len, r;
38495b3e1433Swyllys 				len = ASN1_STRING_to_UTF8(&data,
38505b3e1433Swyllys 				    fname->value.asn1_string);
38515b3e1433Swyllys 				if (len > 0 && data != NULL) {
38525b3e1433Swyllys 					r = X509_alias_set1(xcert, data, len);
38535b3e1433Swyllys 					if (r == NULL) {
38545b3e1433Swyllys 						ret = KMF_ERR_PKCS12_FORMAT;
38555b3e1433Swyllys 						goto end;
38565b3e1433Swyllys 					}
38575b3e1433Swyllys 				} else {
38585b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
38595b3e1433Swyllys 					goto end;
38605b3e1433Swyllys 				}
38615b3e1433Swyllys 			}
38625b3e1433Swyllys 			if (sk_X509_push(certlist, xcert) == 0)
38635b3e1433Swyllys 				ret = KMF_ERR_MEMORY;
38645b3e1433Swyllys 			else
38655b3e1433Swyllys 				xcert = NULL;
38665b3e1433Swyllys 			break;
38675b3e1433Swyllys 		case NID_safeContentsBag:
38685b3e1433Swyllys 			return (openssl_parse_bags(bag->value.safes, pass,
38695b3e1433Swyllys 			    keylist, certlist));
38705b3e1433Swyllys 		default:
38715b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
38725b3e1433Swyllys 			break;
38735b3e1433Swyllys 	}
38745b3e1433Swyllys 
38755b3e1433Swyllys 	/*
38765b3e1433Swyllys 	 * Set the ID and/or FriendlyName attributes on the key.
38775b3e1433Swyllys 	 * If converting to PKCS11 objects, these can translate to CKA_ID
38785b3e1433Swyllys 	 * and CKA_LABEL values.
38795b3e1433Swyllys 	 */
38805b3e1433Swyllys 	if (pkey != NULL && ret == KMF_OK) {
38815b3e1433Swyllys 		ASN1_TYPE *attr = NULL;
38825b3e1433Swyllys 		if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
38835b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
38845b3e1433Swyllys 				return (KMF_ERR_MEMORY);
38855b3e1433Swyllys 			attr->value.octet_string =
38865b3e1433Swyllys 			    ASN1_STRING_dup(keyid->value.octet_string);
38875b3e1433Swyllys 			attr->type = V_ASN1_OCTET_STRING;
38885b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.octet_string;
38895b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
38905b3e1433Swyllys 			OPENSSL_free(attr);
38915b3e1433Swyllys 		}
38925b3e1433Swyllys 
38935b3e1433Swyllys 		if (ret == KMF_OK && fname != NULL &&
38945b3e1433Swyllys 		    fname->type == V_ASN1_BMPSTRING) {
38955b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
38965b3e1433Swyllys 				return (KMF_ERR_MEMORY);
38975b3e1433Swyllys 			attr->value.bmpstring =
38985b3e1433Swyllys 			    ASN1_STRING_dup(fname->value.bmpstring);
38995b3e1433Swyllys 			attr->type = V_ASN1_BMPSTRING;
39005b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.bmpstring;
39015b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
39025b3e1433Swyllys 			OPENSSL_free(attr);
39035b3e1433Swyllys 		}
39045b3e1433Swyllys 
39055b3e1433Swyllys 		if (ret == KMF_OK && keylist != NULL &&
39065b3e1433Swyllys 		    sk_EVP_PKEY_push(keylist, pkey) == 0)
39075b3e1433Swyllys 			ret = KMF_ERR_MEMORY;
39085b3e1433Swyllys 	}
39095b3e1433Swyllys 	if (ret == KMF_OK && keylist != NULL)
39105b3e1433Swyllys 		pkey = NULL;
39115b3e1433Swyllys end:
39125b3e1433Swyllys 	if (pkey != NULL)
39135b3e1433Swyllys 		EVP_PKEY_free(pkey);
39145b3e1433Swyllys 	if (xcert != NULL)
39155b3e1433Swyllys 		X509_free(xcert);
39165b3e1433Swyllys 	if (data != NULL)
39175b3e1433Swyllys 		OPENSSL_free(data);
39185b3e1433Swyllys 
39195b3e1433Swyllys 	return (ret);
39205b3e1433Swyllys }
39215b3e1433Swyllys 
39225b3e1433Swyllys static KMF_RETURN
39235b3e1433Swyllys openssl_pkcs12_parse(PKCS12 *p12, char *pin,
39245b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys,
39255b3e1433Swyllys 	STACK_OF(X509) *certs,
39265b3e1433Swyllys 	STACK_OF(X509) *ca)
3927a2d4930dSDan OpenSolaris Anderson /* ARGSUSED3 */
39285b3e1433Swyllys {
39295b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
39305b3e1433Swyllys 	STACK_OF(PKCS7) *asafes = NULL;
39315b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
39325b3e1433Swyllys 	int i, bagnid;
39335b3e1433Swyllys 	PKCS7 *p7;
39345b3e1433Swyllys 
39355b3e1433Swyllys 	if (p12 == NULL || (keys == NULL && certs == NULL))
39365b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
39375b3e1433Swyllys 
39385b3e1433Swyllys 	if (pin == NULL || *pin == NULL) {
39395b3e1433Swyllys 		if (PKCS12_verify_mac(p12, NULL, 0)) {
39405b3e1433Swyllys 			pin = NULL;
39415b3e1433Swyllys 		} else if (PKCS12_verify_mac(p12, "", 0)) {
39425b3e1433Swyllys 			pin = "";
39435b3e1433Swyllys 		} else {
39445b3e1433Swyllys 			return (KMF_ERR_AUTH_FAILED);
39455b3e1433Swyllys 		}
39465b3e1433Swyllys 	} else if (!PKCS12_verify_mac(p12, pin, -1)) {
39475b3e1433Swyllys 		return (KMF_ERR_AUTH_FAILED);
39485b3e1433Swyllys 	}
39495b3e1433Swyllys 
39505b3e1433Swyllys 	if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
39515b3e1433Swyllys 		return (KMF_ERR_PKCS12_FORMAT);
39525b3e1433Swyllys 
39535b3e1433Swyllys 	for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
39545b3e1433Swyllys 		bags = NULL;
3955d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
39565b3e1433Swyllys 		p7 = sk_PKCS7_value(asafes, i);
39575b3e1433Swyllys 		bagnid = OBJ_obj2nid(p7->type);
39585b3e1433Swyllys 
39595b3e1433Swyllys 		if (bagnid == NID_pkcs7_data) {
39605b3e1433Swyllys 			bags = PKCS12_unpack_p7data(p7);
39615b3e1433Swyllys 		} else if (bagnid == NID_pkcs7_encrypted) {
39625b3e1433Swyllys 			bags = PKCS12_unpack_p7encdata(p7, pin,
39635b3e1433Swyllys 			    (pin ? strlen(pin) : 0));
39645b3e1433Swyllys 		} else {
39655b3e1433Swyllys 			continue;
39665b3e1433Swyllys 		}
39675b3e1433Swyllys 		if (bags == NULL) {
39685b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39695b3e1433Swyllys 			goto out;
39705b3e1433Swyllys 		}
39715b3e1433Swyllys 
39725b3e1433Swyllys 		if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
39735b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39745b3e1433Swyllys 
39755b3e1433Swyllys 		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
39765b3e1433Swyllys 	}
39775b3e1433Swyllys out:
39785b3e1433Swyllys 	if (asafes != NULL)
39795b3e1433Swyllys 		sk_PKCS7_pop_free(asafes, PKCS7_free);
39805b3e1433Swyllys 
39815b3e1433Swyllys 	return (ret);
39825b3e1433Swyllys }
39835b3e1433Swyllys 
398499ebb4caSwyllys /*
398599ebb4caSwyllys  * Helper function to decrypt and parse PKCS#12 import file.
398699ebb4caSwyllys  */
398799ebb4caSwyllys static KMF_RETURN
398899ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
39895b3e1433Swyllys 	STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs,
39905b3e1433Swyllys 	STACK_OF(X509) **ca)
3991a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */
399299ebb4caSwyllys {
399399ebb4caSwyllys 	PKCS12			*pk12, *pk12_tmp;
39945b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*pkeylist = NULL;
39955b3e1433Swyllys 	STACK_OF(X509)		*xcertlist = NULL;
39965b3e1433Swyllys 	STACK_OF(X509)		*cacertlist = NULL;
399799ebb4caSwyllys 
399899ebb4caSwyllys 	if ((pk12 = PKCS12_new()) == NULL) {
399999ebb4caSwyllys 		return (KMF_ERR_MEMORY);
400099ebb4caSwyllys 	}
400199ebb4caSwyllys 
400299ebb4caSwyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
400399ebb4caSwyllys 		/* This is ok; it seems to mean there is no more to read. */
400499ebb4caSwyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
400599ebb4caSwyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
400699ebb4caSwyllys 			goto end_extract_pkcs12;
400799ebb4caSwyllys 
400899ebb4caSwyllys 		PKCS12_free(pk12);
400999ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
401099ebb4caSwyllys 	}
401199ebb4caSwyllys 	pk12 = pk12_tmp;
401299ebb4caSwyllys 
40135b3e1433Swyllys 	xcertlist = sk_X509_new_null();
40145b3e1433Swyllys 	if (xcertlist == NULL) {
40155b3e1433Swyllys 		PKCS12_free(pk12);
40165b3e1433Swyllys 		return (KMF_ERR_MEMORY);
40175b3e1433Swyllys 	}
40185b3e1433Swyllys 	pkeylist = sk_EVP_PKEY_new_null();
40195b3e1433Swyllys 	if (pkeylist == NULL) {
40205b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40215b3e1433Swyllys 		PKCS12_free(pk12);
40225b3e1433Swyllys 		return (KMF_ERR_MEMORY);
40235b3e1433Swyllys 	}
40245b3e1433Swyllys 
40255b3e1433Swyllys 	if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
40265b3e1433Swyllys 	    cacertlist) != KMF_OK) {
40275b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40285b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
402999ebb4caSwyllys 		PKCS12_free(pk12);
403099ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
403199ebb4caSwyllys 	}
403299ebb4caSwyllys 
40335b3e1433Swyllys 	if (priv_key && pkeylist)
40345b3e1433Swyllys 		*priv_key = pkeylist;
40355b3e1433Swyllys 	else if (pkeylist)
40365b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
40375b3e1433Swyllys 	if (certs && xcertlist)
40385b3e1433Swyllys 		*certs = xcertlist;
40395b3e1433Swyllys 	else if (xcertlist)
40405b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40415b3e1433Swyllys 	if (ca && cacertlist)
40425b3e1433Swyllys 		*ca = cacertlist;
40435b3e1433Swyllys 	else if (cacertlist)
40445b3e1433Swyllys 		sk_X509_pop_free(cacertlist, X509_free);
404599ebb4caSwyllys 
40465b3e1433Swyllys end_extract_pkcs12:
404799ebb4caSwyllys 
404899ebb4caSwyllys 	PKCS12_free(pk12);
404999ebb4caSwyllys 	return (KMF_OK);
405099ebb4caSwyllys }
405199ebb4caSwyllys 
405299ebb4caSwyllys static KMF_RETURN
405399ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
405499ebb4caSwyllys {
405599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
405699ebb4caSwyllys 	uint32_t sz;
405799ebb4caSwyllys 
405899ebb4caSwyllys 	sz = BN_num_bytes(from);
405999ebb4caSwyllys 	to->val = (uchar_t *)malloc(sz);
406099ebb4caSwyllys 	if (to->val == NULL)
406199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
406299ebb4caSwyllys 
406399ebb4caSwyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
406499ebb4caSwyllys 		free(to->val);
406599ebb4caSwyllys 		to->val = NULL;
406699ebb4caSwyllys 		to->len = 0;
406799ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
406899ebb4caSwyllys 	}
406999ebb4caSwyllys 
407099ebb4caSwyllys 	return (rv);
407199ebb4caSwyllys }
407299ebb4caSwyllys 
407399ebb4caSwyllys static KMF_RETURN
407499ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
407599ebb4caSwyllys {
407699ebb4caSwyllys 	KMF_RETURN rv;
407799ebb4caSwyllys 	KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
407899ebb4caSwyllys 
407999ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
408099ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK)
408199ebb4caSwyllys 		goto cleanup;
408299ebb4caSwyllys 
408399ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK)
408499ebb4caSwyllys 		goto cleanup;
408599ebb4caSwyllys 
408699ebb4caSwyllys 	if (rsa->d != NULL)
408799ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK)
408899ebb4caSwyllys 			goto cleanup;
408999ebb4caSwyllys 
409099ebb4caSwyllys 	if (rsa->p != NULL)
409199ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK)
409299ebb4caSwyllys 			goto cleanup;
409399ebb4caSwyllys 
409499ebb4caSwyllys 	if (rsa->q != NULL)
409599ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK)
409699ebb4caSwyllys 			goto cleanup;
409799ebb4caSwyllys 
409899ebb4caSwyllys 	if (rsa->dmp1 != NULL)
409999ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK)
410099ebb4caSwyllys 			goto cleanup;
410199ebb4caSwyllys 
410299ebb4caSwyllys 	if (rsa->dmq1 != NULL)
410399ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK)
410499ebb4caSwyllys 			goto cleanup;
410599ebb4caSwyllys 
410699ebb4caSwyllys 	if (rsa->iqmp != NULL)
410799ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK)
410899ebb4caSwyllys 			goto cleanup;
410999ebb4caSwyllys cleanup:
411099ebb4caSwyllys 	if (rv != KMF_OK)
411130a5e8faSwyllys 		kmf_free_raw_key(key);
411299ebb4caSwyllys 	else
411399ebb4caSwyllys 		key->keytype = KMF_RSA;
411499ebb4caSwyllys 
411599ebb4caSwyllys 	/*
411699ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
411799ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
411899ebb4caSwyllys 	 */
411999ebb4caSwyllys 	RSA_free(rsa);
412099ebb4caSwyllys 
412199ebb4caSwyllys 	return (rv);
412299ebb4caSwyllys }
412399ebb4caSwyllys 
412499ebb4caSwyllys static KMF_RETURN
412599ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
412699ebb4caSwyllys {
412799ebb4caSwyllys 	KMF_RETURN rv;
412899ebb4caSwyllys 	KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
412999ebb4caSwyllys 
413099ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
413199ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK)
413299ebb4caSwyllys 		goto cleanup;
413399ebb4caSwyllys 
413499ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK)
413599ebb4caSwyllys 		goto cleanup;
413699ebb4caSwyllys 
413799ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK)
413899ebb4caSwyllys 		goto cleanup;
413999ebb4caSwyllys 
414099ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK)
414199ebb4caSwyllys 		goto cleanup;
414299ebb4caSwyllys 
414399ebb4caSwyllys cleanup:
414499ebb4caSwyllys 	if (rv != KMF_OK)
414530a5e8faSwyllys 		kmf_free_raw_key(key);
414699ebb4caSwyllys 	else
414799ebb4caSwyllys 		key->keytype = KMF_DSA;
414899ebb4caSwyllys 
414999ebb4caSwyllys 	/*
415099ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
415199ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
415299ebb4caSwyllys 	 */
415399ebb4caSwyllys 	DSA_free(dsa);
415499ebb4caSwyllys 
415599ebb4caSwyllys 	return (rv);
415699ebb4caSwyllys }
415799ebb4caSwyllys 
415899ebb4caSwyllys static KMF_RETURN
415999ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
41605b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
416199ebb4caSwyllys {
416299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
41635b3e1433Swyllys 	KMF_X509_DER_CERT *list = (*certlist);
41645b3e1433Swyllys 	KMF_X509_DER_CERT cert;
416599ebb4caSwyllys 	int n = (*ncerts);
416699ebb4caSwyllys 
416799ebb4caSwyllys 	if (list == NULL) {
41685b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
416999ebb4caSwyllys 	} else {
41705b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)realloc(list,
41715b3e1433Swyllys 		    sizeof (KMF_X509_DER_CERT) * (n + 1));
417299ebb4caSwyllys 	}
417399ebb4caSwyllys 
417499ebb4caSwyllys 	if (list == NULL)
417599ebb4caSwyllys 		return (KMF_ERR_MEMORY);
417699ebb4caSwyllys 
41775b3e1433Swyllys 	(void) memset(&cert, 0, sizeof (cert));
41785b3e1433Swyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
417999ebb4caSwyllys 	if (rv == KMF_OK) {
41805b3e1433Swyllys 		int len = 0;
41815b3e1433Swyllys 		/* Get the alias name for the cert if there is one */
41825b3e1433Swyllys 		char *a = (char *)X509_alias_get0(sslcert, &len);
41835b3e1433Swyllys 		if (a != NULL)
41845b3e1433Swyllys 			cert.kmf_private.label = strdup(a);
41855b3e1433Swyllys 		cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
41865b3e1433Swyllys 
418799ebb4caSwyllys 		list[n] = cert;
418899ebb4caSwyllys 		(*ncerts) = n + 1;
418999ebb4caSwyllys 
419099ebb4caSwyllys 		*certlist = list;
419199ebb4caSwyllys 	} else {
419299ebb4caSwyllys 		free(list);
419399ebb4caSwyllys 	}
419499ebb4caSwyllys 
419599ebb4caSwyllys 	return (rv);
419699ebb4caSwyllys }
419799ebb4caSwyllys 
419899ebb4caSwyllys static KMF_RETURN
419999ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
420099ebb4caSwyllys 	KMF_RAW_KEY_DATA *newkey, int *nkeys)
420199ebb4caSwyllys {
420299ebb4caSwyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
420399ebb4caSwyllys 	int n = (*nkeys);
420499ebb4caSwyllys 
420599ebb4caSwyllys 	if (list == NULL) {
420699ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
420799ebb4caSwyllys 	} else {
420899ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
420999ebb4caSwyllys 		    sizeof (KMF_RAW_KEY_DATA) * (n + 1));
421099ebb4caSwyllys 	}
421199ebb4caSwyllys 
421299ebb4caSwyllys 	if (list == NULL)
421399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
421499ebb4caSwyllys 
421599ebb4caSwyllys 	list[n] = *newkey;
421699ebb4caSwyllys 	(*nkeys) = n + 1;
421799ebb4caSwyllys 
421899ebb4caSwyllys 	*keylist = list;
421999ebb4caSwyllys 
422099ebb4caSwyllys 	return (KMF_OK);
422199ebb4caSwyllys }
422299ebb4caSwyllys 
42235b3e1433Swyllys static X509_ATTRIBUTE *
42245b3e1433Swyllys find_attr(STACK_OF(X509_ATTRIBUTE) *attrs, int nid)
42255b3e1433Swyllys {
42265b3e1433Swyllys 	X509_ATTRIBUTE *a;
42275b3e1433Swyllys 	int i;
42285b3e1433Swyllys 
42295b3e1433Swyllys 	if (attrs == NULL)
42305b3e1433Swyllys 		return (NULL);
42315b3e1433Swyllys 
42325b3e1433Swyllys 	for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
4233d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
42345b3e1433Swyllys 		a = sk_X509_ATTRIBUTE_value(attrs, i);
42355b3e1433Swyllys 		if (OBJ_obj2nid(a->object) == nid)
42365b3e1433Swyllys 			return (a);
42375b3e1433Swyllys 	}
42385b3e1433Swyllys 	return (NULL);
42395b3e1433Swyllys }
42405b3e1433Swyllys 
424130a5e8faSwyllys static KMF_RETURN
424230a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
424330a5e8faSwyllys {
424430a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
42455b3e1433Swyllys 	X509_ATTRIBUTE *attr;
424630a5e8faSwyllys 
424730a5e8faSwyllys 	if (pkey == NULL || key == NULL)
424830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
424930a5e8faSwyllys 	/* Convert SSL key to raw key */
425030a5e8faSwyllys 	switch (pkey->type) {
425130a5e8faSwyllys 		case EVP_PKEY_RSA:
425230a5e8faSwyllys 			rv = exportRawRSAKey(EVP_PKEY_get1_RSA(pkey),
425330a5e8faSwyllys 			    key);
425430a5e8faSwyllys 			if (rv != KMF_OK)
425530a5e8faSwyllys 				return (rv);
425630a5e8faSwyllys 			break;
425730a5e8faSwyllys 		case EVP_PKEY_DSA:
425830a5e8faSwyllys 			rv = exportRawDSAKey(EVP_PKEY_get1_DSA(pkey),
425930a5e8faSwyllys 			    key);
426030a5e8faSwyllys 			if (rv != KMF_OK)
426130a5e8faSwyllys 				return (rv);
426230a5e8faSwyllys 			break;
426330a5e8faSwyllys 		default:
426430a5e8faSwyllys 			return (KMF_ERR_BAD_PARAMETER);
426530a5e8faSwyllys 	}
42665b3e1433Swyllys 	/*
42675b3e1433Swyllys 	 * If friendlyName, add it to record.
42685b3e1433Swyllys 	 */
42695b3e1433Swyllys 	attr = find_attr(pkey->attributes, NID_friendlyName);
42705b3e1433Swyllys 	if (attr != NULL) {
42715b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
42725b3e1433Swyllys 		int numattr = sk_ASN1_TYPE_num(attr->value.set);
42735b3e1433Swyllys 		if (attr->single == 0 && numattr > 0) {
4274d7141854SRobert Mustacchi 			/* LINTED E_BAD_PTR_CAST_ALIGN */
42755b3e1433Swyllys 			ty = sk_ASN1_TYPE_value(attr->value.set, 0);
42765b3e1433Swyllys 		}
42775b3e1433Swyllys 		if (ty != NULL) {
427870f9559bSTheo Schlossnagle #if OPENSSL_VERSION_NUMBER < 0x10000000L
42795b3e1433Swyllys 			key->label = uni2asc(ty->value.bmpstring->data,
42805b3e1433Swyllys 			    ty->value.bmpstring->length);
428170f9559bSTheo Schlossnagle #else
428270f9559bSTheo Schlossnagle 			key->label = OPENSSL_uni2asc(ty->value.bmpstring->data,
428370f9559bSTheo Schlossnagle 			    ty->value.bmpstring->length);
428470f9559bSTheo Schlossnagle #endif
42855b3e1433Swyllys 		}
42865b3e1433Swyllys 	} else {
42875b3e1433Swyllys 		key->label = NULL;
42885b3e1433Swyllys 	}
42895b3e1433Swyllys 
42905b3e1433Swyllys 	/*
42915b3e1433Swyllys 	 * If KeyID, add it to record as a KMF_DATA object.
42925b3e1433Swyllys 	 */
42935b3e1433Swyllys 	attr = find_attr(pkey->attributes, NID_localKeyID);
42945b3e1433Swyllys 	if (attr != NULL) {
42955b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
42965b3e1433Swyllys 		int numattr = sk_ASN1_TYPE_num(attr->value.set);
42975b3e1433Swyllys 		if (attr->single == 0 && numattr > 0) {
4298d7141854SRobert Mustacchi 			/* LINTED E_BAD_PTR_CAST_ALIGN */
42995b3e1433Swyllys 			ty = sk_ASN1_TYPE_value(attr->value.set, 0);
43005b3e1433Swyllys 		}
43015b3e1433Swyllys 		key->id.Data = (uchar_t *)malloc(
43025b3e1433Swyllys 		    ty->value.octet_string->length);
43035b3e1433Swyllys 		if (key->id.Data == NULL)
43045b3e1433Swyllys 			return (KMF_ERR_MEMORY);
43055b3e1433Swyllys 		(void) memcpy(key->id.Data, ty->value.octet_string->data,
43065b3e1433Swyllys 		    ty->value.octet_string->length);
43075b3e1433Swyllys 		key->id.Length = ty->value.octet_string->length;
43085b3e1433Swyllys 	} else {
43095b3e1433Swyllys 		(void) memset(&key->id, 0, sizeof (KMF_DATA));
43105b3e1433Swyllys 	}
431130a5e8faSwyllys 
431230a5e8faSwyllys 	return (rv);
431330a5e8faSwyllys }
431499ebb4caSwyllys 
431599ebb4caSwyllys static KMF_RETURN
431699ebb4caSwyllys convertPK12Objects(
431799ebb4caSwyllys 	KMF_HANDLE *kmfh,
43185b3e1433Swyllys 	STACK_OF(EVP_PKEY) *sslkeys,
43195b3e1433Swyllys 	STACK_OF(X509) *sslcert,
43205b3e1433Swyllys 	STACK_OF(X509) *sslcacerts,
432199ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
43225b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
432399ebb4caSwyllys {
432499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
432599ebb4caSwyllys 	KMF_RAW_KEY_DATA key;
432699ebb4caSwyllys 	int i;
432799ebb4caSwyllys 
43285b3e1433Swyllys 	for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
4329d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
43305b3e1433Swyllys 		EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
43315b3e1433Swyllys 		rv = convertToRawKey(pkey, &key);
433230a5e8faSwyllys 		if (rv == KMF_OK)
433399ebb4caSwyllys 			rv = add_key_to_list(keylist, &key, nkeys);
433430a5e8faSwyllys 
433599ebb4caSwyllys 		if (rv != KMF_OK)
433699ebb4caSwyllys 			return (rv);
433799ebb4caSwyllys 	}
433899ebb4caSwyllys 
433999ebb4caSwyllys 	/* Now add the certificate to the certlist */
43405b3e1433Swyllys 	for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
4341d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
43425b3e1433Swyllys 		X509 *cert = sk_X509_value(sslcert, i);
43435b3e1433Swyllys 		rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
434499ebb4caSwyllys 		if (rv != KMF_OK)
434599ebb4caSwyllys 			return (rv);
434699ebb4caSwyllys 	}
434799ebb4caSwyllys 
434899ebb4caSwyllys 	/* Also add any included CA certs to the list */
434971593db2Swyllys 	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
435099ebb4caSwyllys 		X509 *c;
435199ebb4caSwyllys 		/*
435299ebb4caSwyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
435399ebb4caSwyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
435499ebb4caSwyllys 		 * Lint is complaining about the embedded casting, and
435599ebb4caSwyllys 		 * to fix it, you need to fix openssl header files.
435699ebb4caSwyllys 		 */
4357d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
435899ebb4caSwyllys 		c = sk_X509_value(sslcacerts, i);
435999ebb4caSwyllys 
436099ebb4caSwyllys 		/* Now add the ca cert to the certlist */
436199ebb4caSwyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
436299ebb4caSwyllys 		if (rv != KMF_OK)
436399ebb4caSwyllys 			return (rv);
436499ebb4caSwyllys 	}
436599ebb4caSwyllys 	return (rv);
436699ebb4caSwyllys }
436799ebb4caSwyllys 
436899ebb4caSwyllys KMF_RETURN
436930a5e8faSwyllys openssl_import_objects(KMF_HANDLE *kmfh,
437099ebb4caSwyllys 	char *filename, KMF_CREDENTIAL *cred,
43715b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts,
437299ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
437399ebb4caSwyllys {
437499ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
437530a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
437630a5e8faSwyllys 	BIO		*bio = NULL;
43775b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*privkeys = NULL;
43785b3e1433Swyllys 	STACK_OF(X509)		*certs = NULL;
437999ebb4caSwyllys 	STACK_OF(X509)		*cacerts = NULL;
438099ebb4caSwyllys 
438130a5e8faSwyllys 	/*
438230a5e8faSwyllys 	 * auto-detect the file format, regardless of what
438330a5e8faSwyllys 	 * the 'format' parameters in the params say.
438430a5e8faSwyllys 	 */
438530a5e8faSwyllys 	rv = kmf_get_file_format(filename, &format);
438630a5e8faSwyllys 	if (rv != KMF_OK) {
438730a5e8faSwyllys 		return (rv);
438830a5e8faSwyllys 	}
438930a5e8faSwyllys 
439030a5e8faSwyllys 	/* This function only works for PEM or PKCS#12 files */
439130a5e8faSwyllys 	if (format != KMF_FORMAT_PEM &&
439230a5e8faSwyllys 	    format != KMF_FORMAT_PEM_KEYPAIR &&
439330a5e8faSwyllys 	    format != KMF_FORMAT_PKCS12)
439430a5e8faSwyllys 		return (KMF_ERR_ENCODING);
439530a5e8faSwyllys 
439630a5e8faSwyllys 	*certlist = NULL;
439730a5e8faSwyllys 	*keylist = NULL;
439830a5e8faSwyllys 	*ncerts = 0;
439930a5e8faSwyllys 	*nkeys = 0;
440030a5e8faSwyllys 
440130a5e8faSwyllys 	if (format == KMF_FORMAT_PKCS12) {
440299ebb4caSwyllys 		bio = BIO_new_file(filename, "rb");
440399ebb4caSwyllys 		if (bio == NULL) {
440499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
440599ebb4caSwyllys 			rv = KMF_ERR_OPEN_FILE;
440699ebb4caSwyllys 			goto end;
440799ebb4caSwyllys 		}
440899ebb4caSwyllys 
440934acef67Swyllys 		rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
44105b3e1433Swyllys 		    (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
441199ebb4caSwyllys 
441299ebb4caSwyllys 		if (rv  == KMF_OK)
441399ebb4caSwyllys 			/* Convert keys and certs to exportable format */
44145b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
441599ebb4caSwyllys 			    keylist, nkeys, certlist, ncerts);
441630a5e8faSwyllys 	} else {
44175b3e1433Swyllys 		EVP_PKEY *pkey;
44185b3e1433Swyllys 		KMF_DATA *certdata = NULL;
44195b3e1433Swyllys 		KMF_X509_DER_CERT *kmfcerts = NULL;
44205b3e1433Swyllys 		int i;
442130a5e8faSwyllys 		rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
442234acef67Swyllys 		    (uchar_t *)cred->cred, (uint32_t)cred->credlen,
44235b3e1433Swyllys 		    &pkey, &certdata, ncerts);
442471593db2Swyllys 
442571593db2Swyllys 		/* Reached end of import file? */
44265b3e1433Swyllys 		if (rv == KMF_OK && pkey != NULL) {
44275b3e1433Swyllys 			privkeys = sk_EVP_PKEY_new_null();
44285b3e1433Swyllys 			if (privkeys == NULL) {
44295b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
44305b3e1433Swyllys 				goto end;
44315b3e1433Swyllys 			}
44325b3e1433Swyllys 			(void) sk_EVP_PKEY_push(privkeys, pkey);
44335b3e1433Swyllys 			/* convert the certificate list here */
44345b3e1433Swyllys 			if (*ncerts > 0 && certlist != NULL) {
4435e65e5c2dSWyllys Ingersoll 				kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
44365b3e1433Swyllys 				    sizeof (KMF_X509_DER_CERT));
44375b3e1433Swyllys 				if (kmfcerts == NULL) {
44385b3e1433Swyllys 					rv = KMF_ERR_MEMORY;
44395b3e1433Swyllys 					goto end;
44405b3e1433Swyllys 				}
44415b3e1433Swyllys 				for (i = 0; i < *ncerts; i++) {
44425b3e1433Swyllys 					kmfcerts[i].certificate = certdata[i];
44435b3e1433Swyllys 					kmfcerts[i].kmf_private.keystore_type =
44445b3e1433Swyllys 					    KMF_KEYSTORE_OPENSSL;
44455b3e1433Swyllys 				}
44465b3e1433Swyllys 				*certlist = kmfcerts;
44475b3e1433Swyllys 			}
44485b3e1433Swyllys 			/*
44495b3e1433Swyllys 			 * Convert keys to exportable format, the certs
44505b3e1433Swyllys 			 * are already OK.
44515b3e1433Swyllys 			 */
44525b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
445371593db2Swyllys 			    keylist, nkeys, NULL, NULL);
445430a5e8faSwyllys 		}
44555b3e1433Swyllys 	}
445671593db2Swyllys end:
445730a5e8faSwyllys 	if (bio != NULL)
445899ebb4caSwyllys 		(void) BIO_free(bio);
445999ebb4caSwyllys 
44605b3e1433Swyllys 	if (privkeys)
44615b3e1433Swyllys 		sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
44625b3e1433Swyllys 	if (certs)
44635b3e1433Swyllys 		sk_X509_pop_free(certs, X509_free);
446430a5e8faSwyllys 	if (cacerts)
44655b3e1433Swyllys 		sk_X509_pop_free(cacerts, X509_free);
446630a5e8faSwyllys 
446799ebb4caSwyllys 	return (rv);
446899ebb4caSwyllys }
446999ebb4caSwyllys 
447099ebb4caSwyllys static KMF_RETURN
447199ebb4caSwyllys create_deskey(DES_cblock **deskey)
447299ebb4caSwyllys {
447399ebb4caSwyllys 	DES_cblock *key;
447499ebb4caSwyllys 
447599ebb4caSwyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
447699ebb4caSwyllys 	if (key == NULL) {
447799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
447899ebb4caSwyllys 	}
447999ebb4caSwyllys 
448099ebb4caSwyllys 	if (DES_random_key(key) == 0) {
448199ebb4caSwyllys 		free(key);
448299ebb4caSwyllys 		return (KMF_ERR_KEYGEN_FAILED);
448399ebb4caSwyllys 	}
448499ebb4caSwyllys 
448599ebb4caSwyllys 	*deskey = key;
448699ebb4caSwyllys 	return (KMF_OK);
448799ebb4caSwyllys }
448899ebb4caSwyllys 
448999ebb4caSwyllys #define	KEYGEN_RETRY 3
449099ebb4caSwyllys #define	DES3_KEY_SIZE 24
449199ebb4caSwyllys 
449299ebb4caSwyllys static KMF_RETURN
449399ebb4caSwyllys create_des3key(unsigned char **des3key)
449499ebb4caSwyllys {
449599ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
449699ebb4caSwyllys 	DES_cblock *deskey1 = NULL;
449799ebb4caSwyllys 	DES_cblock *deskey2 = NULL;
449899ebb4caSwyllys 	DES_cblock *deskey3 = NULL;
449999ebb4caSwyllys 	unsigned char *newkey = NULL;
450099ebb4caSwyllys 	int retry;
450199ebb4caSwyllys 
450299ebb4caSwyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
450399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
450499ebb4caSwyllys 	}
450599ebb4caSwyllys 
450699ebb4caSwyllys 	/* create the 1st DES key */
450799ebb4caSwyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
450899ebb4caSwyllys 		goto out;
450999ebb4caSwyllys 	}
451099ebb4caSwyllys 
451199ebb4caSwyllys 	/*
451299ebb4caSwyllys 	 * Create the 2nd DES key and make sure its value is different
451399ebb4caSwyllys 	 * from the 1st DES key.
451499ebb4caSwyllys 	 */
451599ebb4caSwyllys 	retry = 0;
451699ebb4caSwyllys 	do {
451799ebb4caSwyllys 		if (deskey2 != NULL) {
451899ebb4caSwyllys 			free(deskey2);
451999ebb4caSwyllys 			deskey2 = NULL;
452099ebb4caSwyllys 		}
452199ebb4caSwyllys 
452299ebb4caSwyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
452399ebb4caSwyllys 			goto out;
452499ebb4caSwyllys 		}
452599ebb4caSwyllys 
452699ebb4caSwyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
452799ebb4caSwyllys 		    == 0) {
452899ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
452999ebb4caSwyllys 			retry++;
453099ebb4caSwyllys 		}
453199ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
453299ebb4caSwyllys 
453399ebb4caSwyllys 	if (ret != KMF_OK) {
453499ebb4caSwyllys 		goto out;
453599ebb4caSwyllys 	}
453699ebb4caSwyllys 
453799ebb4caSwyllys 	/*
453899ebb4caSwyllys 	 * Create the 3rd DES key and make sure its value is different
453999ebb4caSwyllys 	 * from the 2nd DES key.
454099ebb4caSwyllys 	 */
454199ebb4caSwyllys 	retry = 0;
454299ebb4caSwyllys 	do {
454399ebb4caSwyllys 		if (deskey3 != NULL) {
454499ebb4caSwyllys 			free(deskey3);
454599ebb4caSwyllys 			deskey3 = NULL;
454699ebb4caSwyllys 		}
454799ebb4caSwyllys 
454899ebb4caSwyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
454999ebb4caSwyllys 			goto out;
455099ebb4caSwyllys 		}
455199ebb4caSwyllys 
455299ebb4caSwyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
455399ebb4caSwyllys 		    == 0) {
455499ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
455599ebb4caSwyllys 			retry++;
455699ebb4caSwyllys 		}
455799ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
455899ebb4caSwyllys 
455999ebb4caSwyllys 	if (ret != KMF_OK) {
456099ebb4caSwyllys 		goto out;
456199ebb4caSwyllys 	}
456299ebb4caSwyllys 
456399ebb4caSwyllys 	/* Concatenate 3 DES keys into a DES3 key */
456499ebb4caSwyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
456599ebb4caSwyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
456699ebb4caSwyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
456799ebb4caSwyllys 	*des3key = newkey;
456899ebb4caSwyllys 
456999ebb4caSwyllys out:
457099ebb4caSwyllys 	if (deskey1 != NULL)
457199ebb4caSwyllys 		free(deskey1);
457299ebb4caSwyllys 
457399ebb4caSwyllys 	if (deskey2 != NULL)
457499ebb4caSwyllys 		free(deskey2);
457599ebb4caSwyllys 
457699ebb4caSwyllys 	if (deskey3 != NULL)
457799ebb4caSwyllys 		free(deskey3);
457899ebb4caSwyllys 
457999ebb4caSwyllys 	if (ret != KMF_OK && newkey != NULL)
458099ebb4caSwyllys 		free(newkey);
458199ebb4caSwyllys 
458299ebb4caSwyllys 	return (ret);
458399ebb4caSwyllys }
458499ebb4caSwyllys 
458599ebb4caSwyllys KMF_RETURN
458630a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
458730a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
458899ebb4caSwyllys {
458999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
459099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
459199ebb4caSwyllys 	char *fullpath = NULL;
459299ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
459399ebb4caSwyllys 	DES_cblock *deskey = NULL;
459499ebb4caSwyllys 	unsigned char *des3key = NULL;
459599ebb4caSwyllys 	unsigned char *random = NULL;
459699ebb4caSwyllys 	int fd = -1;
459730a5e8faSwyllys 	KMF_KEY_HANDLE *symkey;
459830a5e8faSwyllys 	KMF_KEY_ALG keytype;
459930a5e8faSwyllys 	uint32_t keylen;
460030a5e8faSwyllys 	uint32_t keylen_size = sizeof (keylen);
460130a5e8faSwyllys 	char *dirpath;
460230a5e8faSwyllys 	char *keyfile;
460399ebb4caSwyllys 
460499ebb4caSwyllys 	if (kmfh == NULL)
460599ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
460699ebb4caSwyllys 
460730a5e8faSwyllys 	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
460830a5e8faSwyllys 	if (symkey == NULL)
460999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
461099ebb4caSwyllys 
461130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
461230a5e8faSwyllys 
461330a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
461430a5e8faSwyllys 	if (keyfile == NULL)
461530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
461630a5e8faSwyllys 
461730a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
461830a5e8faSwyllys 	    (void *)&keytype, NULL);
461930a5e8faSwyllys 	if (ret != KMF_OK)
462030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
462130a5e8faSwyllys 
462230a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
462330a5e8faSwyllys 	    &keylen, &keylen_size);
462430a5e8faSwyllys 	if (ret == KMF_ERR_ATTR_NOT_FOUND &&
462530a5e8faSwyllys 	    (keytype == KMF_DES || keytype == KMF_DES3))
462630a5e8faSwyllys 		/* keylength is not required for DES and 3DES */
462730a5e8faSwyllys 		ret = KMF_OK;
462830a5e8faSwyllys 	if (ret != KMF_OK)
462930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
463030a5e8faSwyllys 
463130a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
463299ebb4caSwyllys 	if (fullpath == NULL)
463399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
463499ebb4caSwyllys 
463599ebb4caSwyllys 	/* If the requested file exists, return an error */
463630a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
463799ebb4caSwyllys 		free(fullpath);
463899ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
463999ebb4caSwyllys 	}
464099ebb4caSwyllys 
464199ebb4caSwyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
464299ebb4caSwyllys 	if (fd == -1) {
464399ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
464499ebb4caSwyllys 		goto out;
464599ebb4caSwyllys 	}
464699ebb4caSwyllys 
464799ebb4caSwyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
464899ebb4caSwyllys 	if (rkey == NULL) {
464999ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
465099ebb4caSwyllys 		goto out;
465199ebb4caSwyllys 	}
465299ebb4caSwyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
465399ebb4caSwyllys 
465430a5e8faSwyllys 	if (keytype == KMF_DES) {
465599ebb4caSwyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
465699ebb4caSwyllys 			goto out;
465799ebb4caSwyllys 		}
465899ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)deskey;
465999ebb4caSwyllys 		rkey->keydata.len = 8;
466099ebb4caSwyllys 
466199ebb4caSwyllys 		symkey->keyalg = KMF_DES;
466299ebb4caSwyllys 
466330a5e8faSwyllys 	} else if (keytype == KMF_DES3) {
466499ebb4caSwyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
466599ebb4caSwyllys 			goto out;
466699ebb4caSwyllys 		}
466799ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)des3key;
466899ebb4caSwyllys 		rkey->keydata.len = DES3_KEY_SIZE;
466999ebb4caSwyllys 		symkey->keyalg = KMF_DES3;
46709b37d296Swyllys 
467130a5e8faSwyllys 	} else if (keytype == KMF_AES || keytype == KMF_RC4 ||
467230a5e8faSwyllys 	    keytype == KMF_GENERIC_SECRET) {
467399ebb4caSwyllys 		int bytes;
467499ebb4caSwyllys 
467530a5e8faSwyllys 		if (keylen % 8 != 0) {
467699ebb4caSwyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
467799ebb4caSwyllys 			goto out;
467899ebb4caSwyllys 		}
467999ebb4caSwyllys 
468030a5e8faSwyllys 		if (keytype == KMF_AES) {
468130a5e8faSwyllys 			if (keylen != 128 &&
468230a5e8faSwyllys 			    keylen != 192 &&
468330a5e8faSwyllys 			    keylen != 256) {
468499ebb4caSwyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
468599ebb4caSwyllys 				goto out;
468699ebb4caSwyllys 			}
468799ebb4caSwyllys 		}
468899ebb4caSwyllys 
468930a5e8faSwyllys 		bytes = keylen/8;
469099ebb4caSwyllys 		random = malloc(bytes);
469199ebb4caSwyllys 		if (random == NULL) {
469299ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
469399ebb4caSwyllys 			goto out;
469499ebb4caSwyllys 		}
469599ebb4caSwyllys 		if (RAND_bytes(random, bytes) != 1) {
469699ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
469799ebb4caSwyllys 			goto out;
469899ebb4caSwyllys 		}
469999ebb4caSwyllys 
470099ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)random;
470199ebb4caSwyllys 		rkey->keydata.len = bytes;
470230a5e8faSwyllys 		symkey->keyalg = keytype;
470399ebb4caSwyllys 
470499ebb4caSwyllys 	} else {
470599ebb4caSwyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
470699ebb4caSwyllys 		goto out;
470799ebb4caSwyllys 	}
470899ebb4caSwyllys 
470999ebb4caSwyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
471099ebb4caSwyllys 
471199ebb4caSwyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
471299ebb4caSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
471399ebb4caSwyllys 	symkey->keylabel = (char *)fullpath;
471499ebb4caSwyllys 	symkey->israw = TRUE;
471599ebb4caSwyllys 	symkey->keyp = rkey;
471699ebb4caSwyllys 
471799ebb4caSwyllys out:
471899ebb4caSwyllys 	if (fd != -1)
471999ebb4caSwyllys 		(void) close(fd);
472099ebb4caSwyllys 
472199ebb4caSwyllys 	if (ret != KMF_OK && fullpath != NULL) {
472299ebb4caSwyllys 		free(fullpath);
472399ebb4caSwyllys 	}
472499ebb4caSwyllys 	if (ret != KMF_OK) {
472530a5e8faSwyllys 		kmf_free_raw_sym_key(rkey);
472699ebb4caSwyllys 		symkey->keyp = NULL;
472799ebb4caSwyllys 		symkey->keyalg = KMF_KEYALG_NONE;
472899ebb4caSwyllys 	}
472999ebb4caSwyllys 
473099ebb4caSwyllys 	return (ret);
473199ebb4caSwyllys }
473299ebb4caSwyllys 
473399ebb4caSwyllys /*
473499ebb4caSwyllys  * Check a file to see if it is a CRL file with PEM or DER format.
473599ebb4caSwyllys  * If success, return its format in the "pformat" argument.
473699ebb4caSwyllys  */
473799ebb4caSwyllys KMF_RETURN
473899ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
473999ebb4caSwyllys {
474099ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
474199ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
474299ebb4caSwyllys 	BIO		*bio = NULL;
474399ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
474499ebb4caSwyllys 
474599ebb4caSwyllys 	if (filename == NULL) {
474699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
474799ebb4caSwyllys 	}
474899ebb4caSwyllys 
474999ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
475099ebb4caSwyllys 	if (bio == NULL)	{
475199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
475299ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
475399ebb4caSwyllys 		goto out;
475499ebb4caSwyllys 	}
475599ebb4caSwyllys 
475699ebb4caSwyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
475799ebb4caSwyllys 		*pformat = KMF_FORMAT_PEM;
475899ebb4caSwyllys 		goto out;
475999ebb4caSwyllys 	}
476099ebb4caSwyllys 	(void) BIO_free(bio);
476199ebb4caSwyllys 
476299ebb4caSwyllys 	/*
476399ebb4caSwyllys 	 * Now try to read it as raw DER data.
476499ebb4caSwyllys 	 */
476599ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
476699ebb4caSwyllys 	if (bio == NULL)	{
476799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
476899ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
476999ebb4caSwyllys 		goto out;
477099ebb4caSwyllys 	}
477199ebb4caSwyllys 
477299ebb4caSwyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
477399ebb4caSwyllys 		*pformat = KMF_FORMAT_ASN1;
477499ebb4caSwyllys 	} else {
477599ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
477699ebb4caSwyllys 	}
477799ebb4caSwyllys 
477899ebb4caSwyllys out:
477999ebb4caSwyllys 	if (bio != NULL)
478099ebb4caSwyllys 		(void) BIO_free(bio);
478199ebb4caSwyllys 
478299ebb4caSwyllys 	if (xcrl != NULL)
478399ebb4caSwyllys 		X509_CRL_free(xcrl);
478499ebb4caSwyllys 
478599ebb4caSwyllys 	return (ret);
478699ebb4caSwyllys }
478799ebb4caSwyllys 
478899ebb4caSwyllys KMF_RETURN
478999ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
479099ebb4caSwyllys     KMF_RAW_SYM_KEY *rkey)
479199ebb4caSwyllys {
479299ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
479399ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
479499ebb4caSwyllys 	KMF_DATA	keyvalue;
479599ebb4caSwyllys 
479699ebb4caSwyllys 	if (kmfh == NULL)
479799ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
479899ebb4caSwyllys 
479999ebb4caSwyllys 	if (symkey == NULL || rkey == NULL)
480099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
480199ebb4caSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
480299ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
480399ebb4caSwyllys 
480499ebb4caSwyllys 	if (symkey->israw) {
480599ebb4caSwyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
480699ebb4caSwyllys 
480799ebb4caSwyllys 		if (rawkey == NULL ||
480899ebb4caSwyllys 		    rawkey->keydata.val == NULL ||
480999ebb4caSwyllys 		    rawkey->keydata.len == 0)
481099ebb4caSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
481199ebb4caSwyllys 
481299ebb4caSwyllys 		rkey->keydata.len = rawkey->keydata.len;
481399ebb4caSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
481499ebb4caSwyllys 			return (KMF_ERR_MEMORY);
481599ebb4caSwyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
481699ebb4caSwyllys 		    rkey->keydata.len);
481799ebb4caSwyllys 	} else {
481830a5e8faSwyllys 		rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
481999ebb4caSwyllys 		if (rv != KMF_OK)
482099ebb4caSwyllys 			return (rv);
482199ebb4caSwyllys 		rkey->keydata.len = keyvalue.Length;
482299ebb4caSwyllys 		rkey->keydata.val = keyvalue.Data;
482399ebb4caSwyllys 	}
482499ebb4caSwyllys 
482599ebb4caSwyllys 	return (rv);
482699ebb4caSwyllys }
482702744e81Swyllys 
482802744e81Swyllys /*
482930a5e8faSwyllys  * substitute for the unsafe access(2) function.
483030a5e8faSwyllys  * If the file in question already exists, return 1.
483130a5e8faSwyllys  * else 0.  If an error occurs during testing (other
483230a5e8faSwyllys  * than EEXIST), return -1.
483330a5e8faSwyllys  */
483430a5e8faSwyllys static int
483530a5e8faSwyllys test_for_file(char *filename, mode_t mode)
483630a5e8faSwyllys {
483730a5e8faSwyllys 	int fd;
483830a5e8faSwyllys 
483930a5e8faSwyllys 	/*
484030a5e8faSwyllys 	 * Try to create the file with the EXCL flag.
484130a5e8faSwyllys 	 * The call should fail if the file exists.
484230a5e8faSwyllys 	 */
484330a5e8faSwyllys 	fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
484430a5e8faSwyllys 	if (fd == -1 && errno == EEXIST)
484530a5e8faSwyllys 		return (1);
484630a5e8faSwyllys 	else if (fd == -1) /* some other error */
484730a5e8faSwyllys 		return (-1);
484830a5e8faSwyllys 
484930a5e8faSwyllys 	/* The file did NOT exist.  Delete the testcase. */
485030a5e8faSwyllys 	(void) close(fd);
485130a5e8faSwyllys 	(void) unlink(filename);
485230a5e8faSwyllys 	return (0);
485330a5e8faSwyllys }
485430a5e8faSwyllys 
485530a5e8faSwyllys KMF_RETURN
485630a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
485730a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
485830a5e8faSwyllys {
485930a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
486030a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
486130a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
486230a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
486330a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
486430a5e8faSwyllys 	KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
486530a5e8faSwyllys 	KMF_CREDENTIAL cred = { NULL, 0 };
486630a5e8faSwyllys 	BIO *out = NULL;
486730a5e8faSwyllys 	int keys = 0;
486830a5e8faSwyllys 	char *fullpath = NULL;
486930a5e8faSwyllys 	char *keyfile = NULL;
487030a5e8faSwyllys 	char *dirpath = NULL;
487130a5e8faSwyllys 
487230a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
487330a5e8faSwyllys 	if (pubkey != NULL)
487430a5e8faSwyllys 		keys++;
487530a5e8faSwyllys 
487630a5e8faSwyllys 	prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
487730a5e8faSwyllys 	if (prikey != NULL)
487830a5e8faSwyllys 		keys++;
487930a5e8faSwyllys 
488030a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
488130a5e8faSwyllys 	if (rawkey != NULL)
488230a5e8faSwyllys 		keys++;
488330a5e8faSwyllys 
488430a5e8faSwyllys 	/*
488530a5e8faSwyllys 	 * Exactly 1 type of key must be passed to this function.
488630a5e8faSwyllys 	 */
488730a5e8faSwyllys 	if (keys != 1)
488830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
488930a5e8faSwyllys 
489030a5e8faSwyllys 	keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
489130a5e8faSwyllys 	    numattr);
489230a5e8faSwyllys 	if (keyfile == NULL)
489330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
489430a5e8faSwyllys 
489530a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
489630a5e8faSwyllys 
489730a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
489830a5e8faSwyllys 
489930a5e8faSwyllys 	/* Once we have the full path, we don't need the pieces */
490030a5e8faSwyllys 	if (fullpath == NULL)
490130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
490230a5e8faSwyllys 
490330a5e8faSwyllys 	/* If the requested file exists, return an error */
490430a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
490530a5e8faSwyllys 		free(fullpath);
490630a5e8faSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
490730a5e8faSwyllys 	}
490830a5e8faSwyllys 
490930a5e8faSwyllys 	rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
491030a5e8faSwyllys 	    &format, NULL);
491130a5e8faSwyllys 	if (rv != KMF_OK)
491230a5e8faSwyllys 		/* format is optional. */
491330a5e8faSwyllys 		rv = KMF_OK;
491430a5e8faSwyllys 
491530a5e8faSwyllys 	/* CRED is not required for OpenSSL files */
491630a5e8faSwyllys 	(void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
491730a5e8faSwyllys 	    &cred, NULL);
491830a5e8faSwyllys 
491930a5e8faSwyllys 	/* Store the private key to the keyfile */
492030a5e8faSwyllys 	out = BIO_new_file(fullpath, "wb");
492130a5e8faSwyllys 	if (out == NULL) {
492230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
492330a5e8faSwyllys 		rv = KMF_ERR_OPEN_FILE;
492430a5e8faSwyllys 		goto end;
492530a5e8faSwyllys 	}
492630a5e8faSwyllys 
492730a5e8faSwyllys 	if (prikey != NULL && prikey->keyp != NULL) {
492830a5e8faSwyllys 		if (prikey->keyalg == KMF_RSA ||
492930a5e8faSwyllys 		    prikey->keyalg == KMF_DSA) {
493030a5e8faSwyllys 			pkey = (EVP_PKEY *)prikey->keyp;
493130a5e8faSwyllys 
493230a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
493330a5e8faSwyllys 			    out, &cred, pkey, TRUE);
493430a5e8faSwyllys 
493530a5e8faSwyllys 			if (rv == KMF_OK && prikey->keylabel == NULL) {
493630a5e8faSwyllys 				prikey->keylabel = strdup(fullpath);
493730a5e8faSwyllys 				if (prikey->keylabel == NULL)
493830a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
493930a5e8faSwyllys 			}
494030a5e8faSwyllys 		}
494130a5e8faSwyllys 	} else if (pubkey != NULL && pubkey->keyp != NULL) {
494230a5e8faSwyllys 		if (pubkey->keyalg == KMF_RSA ||
494330a5e8faSwyllys 		    pubkey->keyalg == KMF_DSA) {
494430a5e8faSwyllys 			pkey = (EVP_PKEY *)pubkey->keyp;
494530a5e8faSwyllys 
494630a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
494730a5e8faSwyllys 			    out, &cred, pkey, FALSE);
494830a5e8faSwyllys 
494930a5e8faSwyllys 			if (rv == KMF_OK && pubkey->keylabel == NULL) {
495030a5e8faSwyllys 				pubkey->keylabel = strdup(fullpath);
495130a5e8faSwyllys 				if (pubkey->keylabel == NULL)
495230a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
495330a5e8faSwyllys 			}
495430a5e8faSwyllys 		}
495530a5e8faSwyllys 	} else if (rawkey != NULL) {
495630a5e8faSwyllys 		if (rawkey->keytype == KMF_RSA) {
495730a5e8faSwyllys 			pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
495830a5e8faSwyllys 		} else if (rawkey->keytype == KMF_DSA) {
495930a5e8faSwyllys 			pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
496030a5e8faSwyllys 		} else {
496130a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
496230a5e8faSwyllys 		}
49635b3e1433Swyllys 		if (pkey != NULL) {
496473cc0e02Swyllys 			KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
496573cc0e02Swyllys 
496673cc0e02Swyllys 			rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
496773cc0e02Swyllys 			    (void *)&kclass, NULL);
496873cc0e02Swyllys 			if (rv != KMF_OK)
496973cc0e02Swyllys 				rv = KMF_OK;
49705b3e1433Swyllys 			rv = ssl_write_key(kmfh, format, out,
497173cc0e02Swyllys 			    &cred, pkey, (kclass == KMF_ASYM_PRI));
49725b3e1433Swyllys 			EVP_PKEY_free(pkey);
49735b3e1433Swyllys 		}
497430a5e8faSwyllys 	}
497530a5e8faSwyllys 
497630a5e8faSwyllys end:
497730a5e8faSwyllys 
497830a5e8faSwyllys 	if (out)
497930a5e8faSwyllys 		(void) BIO_free(out);
498030a5e8faSwyllys 
49815b3e1433Swyllys 
498230a5e8faSwyllys 	if (rv == KMF_OK)
498330a5e8faSwyllys 		(void) chmod(fullpath, 0400);
498430a5e8faSwyllys 
498530a5e8faSwyllys 	free(fullpath);
498630a5e8faSwyllys 	return (rv);
498730a5e8faSwyllys }
498830a5e8faSwyllys 
498930a5e8faSwyllys KMF_RETURN
499030a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
499130a5e8faSwyllys {
499230a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
499330a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
499430a5e8faSwyllys 	X509_CRL *xcrl = NULL;
499530a5e8faSwyllys 	X509 *xcert = NULL;
499630a5e8faSwyllys 	EVP_PKEY *pkey;
499730a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
499830a5e8faSwyllys 	BIO *in = NULL, *out = NULL;
499930a5e8faSwyllys 	int openssl_ret = 0;
500030a5e8faSwyllys 	KMF_ENCODE_FORMAT outformat;
500130a5e8faSwyllys 	boolean_t crlcheck = FALSE;
500230a5e8faSwyllys 	char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
500330a5e8faSwyllys 
500430a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
500530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
500630a5e8faSwyllys 	}
500730a5e8faSwyllys 
500830a5e8faSwyllys 	/* CRL check is optional */
500930a5e8faSwyllys 	(void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
501030a5e8faSwyllys 	    &crlcheck, NULL);
501130a5e8faSwyllys 
501230a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
501330a5e8faSwyllys 	if (crlcheck == B_TRUE && certfile == NULL) {
501430a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
501530a5e8faSwyllys 	}
501630a5e8faSwyllys 
501730a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
501830a5e8faSwyllys 	incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
501930a5e8faSwyllys 	outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
502030a5e8faSwyllys 
502130a5e8faSwyllys 	crlfile = get_fullpath(dirpath, incrl);
502230a5e8faSwyllys 
502330a5e8faSwyllys 	if (crlfile == NULL)
502430a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
502530a5e8faSwyllys 
502630a5e8faSwyllys 	outcrlfile = get_fullpath(dirpath, outcrl);
502730a5e8faSwyllys 	if (outcrlfile == NULL)
502830a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
502930a5e8faSwyllys 
503030a5e8faSwyllys 	if (isdir(outcrlfile)) {
503130a5e8faSwyllys 		free(outcrlfile);
503230a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
503330a5e8faSwyllys 	}
503430a5e8faSwyllys 
503530a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
503630a5e8faSwyllys 	if (ret != KMF_OK) {
503730a5e8faSwyllys 		free(outcrlfile);
503830a5e8faSwyllys 		return (ret);
503930a5e8faSwyllys 	}
504030a5e8faSwyllys 
504130a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
504230a5e8faSwyllys 	if (in == NULL)	{
504330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
504430a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
504530a5e8faSwyllys 		goto end;
504630a5e8faSwyllys 	}
504730a5e8faSwyllys 
504830a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
504930a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
505030a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
505130a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
505230a5e8faSwyllys 	}
505330a5e8faSwyllys 
505430a5e8faSwyllys 	if (xcrl == NULL) {
505530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
505630a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
505730a5e8faSwyllys 		goto end;
505830a5e8faSwyllys 	}
505930a5e8faSwyllys 
506030a5e8faSwyllys 	/* If bypasscheck is specified, no need to verify. */
506130a5e8faSwyllys 	if (crlcheck == B_FALSE)
506230a5e8faSwyllys 		goto output;
506330a5e8faSwyllys 
506430a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
506530a5e8faSwyllys 	if (ret != KMF_OK)
506630a5e8faSwyllys 		goto end;
506730a5e8faSwyllys 
506830a5e8faSwyllys 	/* Read in the CA cert file and convert to X509 */
506930a5e8faSwyllys 	if (BIO_read_filename(in, certfile) <= 0) {
507030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
507130a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
507230a5e8faSwyllys 		goto end;
507330a5e8faSwyllys 	}
507430a5e8faSwyllys 
507530a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
507630a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
507730a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
507830a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
507930a5e8faSwyllys 	} else {
508030a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
508130a5e8faSwyllys 		goto end;
508230a5e8faSwyllys 	}
508330a5e8faSwyllys 
508430a5e8faSwyllys 	if (xcert == NULL) {
508530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
508630a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
508730a5e8faSwyllys 		goto end;
508830a5e8faSwyllys 	}
508930a5e8faSwyllys 	/* Now get the public key from the CA cert */
509030a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
509130a5e8faSwyllys 	if (pkey == NULL) {
509230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
509330a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
509430a5e8faSwyllys 		goto end;
509530a5e8faSwyllys 	}
509630a5e8faSwyllys 
509730a5e8faSwyllys 	/* Verify the CRL with the CA's public key */
509830a5e8faSwyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
509930a5e8faSwyllys 	EVP_PKEY_free(pkey);
510030a5e8faSwyllys 	if (openssl_ret > 0) {
510130a5e8faSwyllys 		ret = KMF_OK;  /* verify succeed */
510230a5e8faSwyllys 	} else {
510330a5e8faSwyllys 		SET_ERROR(kmfh, openssl_ret);
510430a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
510530a5e8faSwyllys 	}
510630a5e8faSwyllys 
510730a5e8faSwyllys output:
510830a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
510930a5e8faSwyllys 	    &outformat, NULL);
511030a5e8faSwyllys 	if (ret != KMF_OK) {
511130a5e8faSwyllys 		ret = KMF_OK;
511230a5e8faSwyllys 		outformat = KMF_FORMAT_PEM;
511330a5e8faSwyllys 	}
511430a5e8faSwyllys 
511530a5e8faSwyllys 	out = BIO_new_file(outcrlfile, "wb");
511630a5e8faSwyllys 	if (out == NULL) {
511730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
511830a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
511930a5e8faSwyllys 		goto end;
512030a5e8faSwyllys 	}
512130a5e8faSwyllys 
512230a5e8faSwyllys 	if (outformat == KMF_FORMAT_ASN1) {
512330a5e8faSwyllys 		openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
512430a5e8faSwyllys 	} else if (outformat == KMF_FORMAT_PEM) {
512530a5e8faSwyllys 		openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
512630a5e8faSwyllys 	} else {
512730a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
512830a5e8faSwyllys 		goto end;
512930a5e8faSwyllys 	}
513030a5e8faSwyllys 
513130a5e8faSwyllys 	if (openssl_ret <= 0) {
513230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
513330a5e8faSwyllys 		ret = KMF_ERR_WRITE_FILE;
513430a5e8faSwyllys 	} else {
513530a5e8faSwyllys 		ret = KMF_OK;
513630a5e8faSwyllys 	}
513730a5e8faSwyllys 
513830a5e8faSwyllys end:
513930a5e8faSwyllys 	if (xcrl != NULL)
514030a5e8faSwyllys 		X509_CRL_free(xcrl);
514130a5e8faSwyllys 
514230a5e8faSwyllys 	if (xcert != NULL)
514330a5e8faSwyllys 		X509_free(xcert);
514430a5e8faSwyllys 
514530a5e8faSwyllys 	if (in != NULL)
514630a5e8faSwyllys 		(void) BIO_free(in);
514730a5e8faSwyllys 
514830a5e8faSwyllys 	if (out != NULL)
514930a5e8faSwyllys 		(void) BIO_free(out);
515030a5e8faSwyllys 
515130a5e8faSwyllys 	if (outcrlfile != NULL)
515230a5e8faSwyllys 		free(outcrlfile);
515330a5e8faSwyllys 
515430a5e8faSwyllys 	return (ret);
515530a5e8faSwyllys }
515630a5e8faSwyllys 
515730a5e8faSwyllys KMF_RETURN
515830a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
515930a5e8faSwyllys {
516030a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
516130a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
516230a5e8faSwyllys 	X509_CRL   *x = NULL;
516330a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
516430a5e8faSwyllys 	char *crlfile = NULL;
516530a5e8faSwyllys 	BIO *in = NULL;
516630a5e8faSwyllys 	BIO *mem = NULL;
516730a5e8faSwyllys 	long len;
516830a5e8faSwyllys 	char *memptr;
516930a5e8faSwyllys 	char *data = NULL;
517030a5e8faSwyllys 	char **crldata;
517130a5e8faSwyllys 	char *crlfilename, *dirpath;
517230a5e8faSwyllys 
517330a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
517430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
517530a5e8faSwyllys 	}
517630a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
517730a5e8faSwyllys 	    attrlist, numattr);
517830a5e8faSwyllys 	if (crlfilename == NULL)
517930a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
518030a5e8faSwyllys 
518130a5e8faSwyllys 	crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
518230a5e8faSwyllys 	    attrlist, numattr);
518330a5e8faSwyllys 
518430a5e8faSwyllys 	if (crldata == NULL)
518530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
518630a5e8faSwyllys 
518730a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
518830a5e8faSwyllys 
518930a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
519030a5e8faSwyllys 
519130a5e8faSwyllys 	if (crlfile == NULL)
519230a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
519330a5e8faSwyllys 
519430a5e8faSwyllys 	if (isdir(crlfile)) {
519530a5e8faSwyllys 		free(crlfile);
519630a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
519730a5e8faSwyllys 	}
519830a5e8faSwyllys 
519930a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
520030a5e8faSwyllys 	if (ret != KMF_OK) {
520130a5e8faSwyllys 		free(crlfile);
520230a5e8faSwyllys 		return (ret);
520330a5e8faSwyllys 	}
520430a5e8faSwyllys 
520530a5e8faSwyllys 	if (bio_err == NULL)
520630a5e8faSwyllys 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
520730a5e8faSwyllys 
520830a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
520930a5e8faSwyllys 	if (in == NULL)	{
521030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
521130a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
521230a5e8faSwyllys 		goto end;
521330a5e8faSwyllys 	}
521430a5e8faSwyllys 
521530a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
521630a5e8faSwyllys 		x = d2i_X509_CRL_bio(in, NULL);
521730a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
521830a5e8faSwyllys 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
521930a5e8faSwyllys 	}
522030a5e8faSwyllys 
522130a5e8faSwyllys 	if (x == NULL) { /* should not happen */
522230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
522330a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
522430a5e8faSwyllys 		goto end;
522530a5e8faSwyllys 	}
522630a5e8faSwyllys 
522730a5e8faSwyllys 	mem = BIO_new(BIO_s_mem());
522830a5e8faSwyllys 	if (mem == NULL) {
522930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
523030a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
523130a5e8faSwyllys 		goto end;
523230a5e8faSwyllys 	}
523330a5e8faSwyllys 
523430a5e8faSwyllys 	(void) X509_CRL_print(mem, x);
523530a5e8faSwyllys 	len = BIO_get_mem_data(mem, &memptr);
523630a5e8faSwyllys 	if (len <= 0) {
523730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
523830a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
523930a5e8faSwyllys 		goto end;
524030a5e8faSwyllys 	}
524130a5e8faSwyllys 
524230a5e8faSwyllys 	data = malloc(len + 1);
524330a5e8faSwyllys 	if (data == NULL) {
524430a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
524530a5e8faSwyllys 		goto end;
524630a5e8faSwyllys 	}
524730a5e8faSwyllys 
524830a5e8faSwyllys 	(void) memcpy(data, memptr, len);
524930a5e8faSwyllys 	data[len] = '\0';
525030a5e8faSwyllys 	*crldata = data;
525130a5e8faSwyllys 
525230a5e8faSwyllys end:
525330a5e8faSwyllys 	if (x != NULL)
525430a5e8faSwyllys 		X509_CRL_free(x);
525530a5e8faSwyllys 
525630a5e8faSwyllys 	if (crlfile != NULL)
525730a5e8faSwyllys 		free(crlfile);
525830a5e8faSwyllys 
525930a5e8faSwyllys 	if (in != NULL)
526030a5e8faSwyllys 		(void) BIO_free(in);
526130a5e8faSwyllys 
526230a5e8faSwyllys 	if (mem != NULL)
526330a5e8faSwyllys 		(void) BIO_free(mem);
526430a5e8faSwyllys 
526530a5e8faSwyllys 	return (ret);
526630a5e8faSwyllys }
526730a5e8faSwyllys 
526830a5e8faSwyllys KMF_RETURN
526930a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
527030a5e8faSwyllys {
527130a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
527230a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
527330a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
527430a5e8faSwyllys 	char *crlfile = NULL;
527530a5e8faSwyllys 	BIO *in = NULL;
527630a5e8faSwyllys 	char *crlfilename, *dirpath;
527730a5e8faSwyllys 
527830a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
527930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
528030a5e8faSwyllys 	}
528130a5e8faSwyllys 
528230a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
528330a5e8faSwyllys 	    attrlist, numattr);
528430a5e8faSwyllys 
528530a5e8faSwyllys 	if (crlfilename == NULL)
528630a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
528730a5e8faSwyllys 
528830a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
528930a5e8faSwyllys 
529030a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
529130a5e8faSwyllys 
529230a5e8faSwyllys 	if (crlfile == NULL)
529330a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
529430a5e8faSwyllys 
529530a5e8faSwyllys 	if (isdir(crlfile)) {
529630a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
529730a5e8faSwyllys 		goto end;
529830a5e8faSwyllys 	}
529930a5e8faSwyllys 
530030a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
530130a5e8faSwyllys 	if (ret != KMF_OK)
530230a5e8faSwyllys 		goto end;
530330a5e8faSwyllys 
530430a5e8faSwyllys 	if (unlink(crlfile) != 0) {
530530a5e8faSwyllys 		SET_SYS_ERROR(kmfh, errno);
530630a5e8faSwyllys 		ret = KMF_ERR_INTERNAL;
530730a5e8faSwyllys 		goto end;
530830a5e8faSwyllys 	}
530930a5e8faSwyllys 
531030a5e8faSwyllys end:
531130a5e8faSwyllys 	if (in != NULL)
531230a5e8faSwyllys 		(void) BIO_free(in);
531330a5e8faSwyllys 	if (crlfile != NULL)
531430a5e8faSwyllys 		free(crlfile);
531530a5e8faSwyllys 
531630a5e8faSwyllys 	return (ret);
531730a5e8faSwyllys }
531830a5e8faSwyllys 
531930a5e8faSwyllys KMF_RETURN
532030a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
532130a5e8faSwyllys {
532230a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
532330a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
532430a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
532530a5e8faSwyllys 	BIO *in = NULL;
532630a5e8faSwyllys 	X509   *xcert = NULL;
532730a5e8faSwyllys 	X509_CRL   *xcrl = NULL;
532830a5e8faSwyllys 	STACK_OF(X509_REVOKED) *revoke_stack = NULL;
532930a5e8faSwyllys 	X509_REVOKED *revoke;
533030a5e8faSwyllys 	int i;
533130a5e8faSwyllys 	char *crlfilename, *crlfile, *dirpath, *certfile;
533230a5e8faSwyllys 
533330a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
533430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
533530a5e8faSwyllys 	}
533630a5e8faSwyllys 
533730a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
533830a5e8faSwyllys 	    attrlist, numattr);
533930a5e8faSwyllys 
534030a5e8faSwyllys 	if (crlfilename == NULL)
534130a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
534230a5e8faSwyllys 
534330a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
534430a5e8faSwyllys 	if (certfile == NULL)
534530a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
534630a5e8faSwyllys 
534730a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
534830a5e8faSwyllys 
534930a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
535030a5e8faSwyllys 
535130a5e8faSwyllys 	if (crlfile == NULL)
535230a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
535330a5e8faSwyllys 
535430a5e8faSwyllys 	if (isdir(crlfile)) {
535530a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
535630a5e8faSwyllys 		goto end;
535730a5e8faSwyllys 	}
535830a5e8faSwyllys 
535930a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
536030a5e8faSwyllys 	if (ret != KMF_OK)
536130a5e8faSwyllys 		goto end;
536230a5e8faSwyllys 
536330a5e8faSwyllys 	/* Read the CRL file and load it into a X509_CRL structure */
536430a5e8faSwyllys 	in = BIO_new_file(crlfilename, "rb");
536530a5e8faSwyllys 	if (in == NULL)	{
536630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
536730a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
536830a5e8faSwyllys 		goto end;
536930a5e8faSwyllys 	}
537030a5e8faSwyllys 
537130a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
537230a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
537330a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
537430a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
537530a5e8faSwyllys 	}
537630a5e8faSwyllys 
537730a5e8faSwyllys 	if (xcrl == NULL) {
537830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
537930a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
538030a5e8faSwyllys 		goto end;
538130a5e8faSwyllys 	}
538230a5e8faSwyllys 	(void) BIO_free(in);
538330a5e8faSwyllys 
538430a5e8faSwyllys 	/* Read the Certificate file and load it into a X509 structure */
538530a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
538630a5e8faSwyllys 	if (ret != KMF_OK)
538730a5e8faSwyllys 		goto end;
538830a5e8faSwyllys 
538930a5e8faSwyllys 	in = BIO_new_file(certfile, "rb");
539030a5e8faSwyllys 	if (in == NULL)	{
539130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
539230a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
539330a5e8faSwyllys 		goto end;
539430a5e8faSwyllys 	}
539530a5e8faSwyllys 
539630a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
539730a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
539830a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
539930a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
540030a5e8faSwyllys 	}
540130a5e8faSwyllys 
540230a5e8faSwyllys 	if (xcert == NULL) {
540330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
540430a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
540530a5e8faSwyllys 		goto end;
540630a5e8faSwyllys 	}
540730a5e8faSwyllys 
540830a5e8faSwyllys 	/* Check if the certificate and the CRL have same issuer */
540930a5e8faSwyllys 	if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) {
541030a5e8faSwyllys 		ret = KMF_ERR_ISSUER;
541130a5e8faSwyllys 		goto end;
541230a5e8faSwyllys 	}
541330a5e8faSwyllys 
541430a5e8faSwyllys 	/* Check to see if the certificate serial number is revoked */
541530a5e8faSwyllys 	revoke_stack = X509_CRL_get_REVOKED(xcrl);
541630a5e8faSwyllys 	if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
541730a5e8faSwyllys 		/* No revoked certificates in the CRL file */
541830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
541930a5e8faSwyllys 		ret = KMF_ERR_EMPTY_CRL;
542030a5e8faSwyllys 		goto end;
542130a5e8faSwyllys 	}
542230a5e8faSwyllys 
542330a5e8faSwyllys 	for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
5424d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
542530a5e8faSwyllys 		revoke = sk_X509_REVOKED_value(revoke_stack, i);
542630a5e8faSwyllys 		if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber,
542730a5e8faSwyllys 		    revoke->serialNumber) == 0) {
542830a5e8faSwyllys 			break;
542930a5e8faSwyllys 		}
543030a5e8faSwyllys 	}
543130a5e8faSwyllys 
543230a5e8faSwyllys 	if (i < sk_X509_REVOKED_num(revoke_stack)) {
543330a5e8faSwyllys 		ret = KMF_OK;
543430a5e8faSwyllys 	} else {
543530a5e8faSwyllys 		ret = KMF_ERR_NOT_REVOKED;
543630a5e8faSwyllys 	}
543730a5e8faSwyllys 
543830a5e8faSwyllys end:
543930a5e8faSwyllys 	if (in != NULL)
544030a5e8faSwyllys 		(void) BIO_free(in);
544130a5e8faSwyllys 	if (xcrl != NULL)
544230a5e8faSwyllys 		X509_CRL_free(xcrl);
544330a5e8faSwyllys 	if (xcert != NULL)
544430a5e8faSwyllys 		X509_free(xcert);
544530a5e8faSwyllys 
544630a5e8faSwyllys 	return (ret);
544730a5e8faSwyllys }
544830a5e8faSwyllys 
544930a5e8faSwyllys KMF_RETURN
545030a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
545130a5e8faSwyllys {
545230a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
545330a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
545430a5e8faSwyllys 	BIO		*bcrl = NULL;
545530a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
545630a5e8faSwyllys 	X509		*xcert = NULL;
545730a5e8faSwyllys 	EVP_PKEY	*pkey;
545830a5e8faSwyllys 	int		sslret;
545930a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
546030a5e8faSwyllys 	unsigned char	*p;
546130a5e8faSwyllys 	long		len;
546230a5e8faSwyllys 
546330a5e8faSwyllys 	if (handle == NULL || crlname == NULL || tacert == NULL) {
546430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
546530a5e8faSwyllys 	}
546630a5e8faSwyllys 
546730a5e8faSwyllys 	ret = kmf_get_file_format(crlname, &crl_format);
546830a5e8faSwyllys 	if (ret != KMF_OK)
546930a5e8faSwyllys 		return (ret);
547030a5e8faSwyllys 
547130a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
547230a5e8faSwyllys 	if (bcrl == NULL)	{
547330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
547430a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
547530a5e8faSwyllys 		goto cleanup;
547630a5e8faSwyllys 	}
547730a5e8faSwyllys 
547830a5e8faSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
547930a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
548030a5e8faSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
548130a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
548230a5e8faSwyllys 	} else {
548330a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
548430a5e8faSwyllys 		goto cleanup;
548530a5e8faSwyllys 	}
548630a5e8faSwyllys 
548730a5e8faSwyllys 	if (xcrl == NULL) {
548830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
548930a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
549030a5e8faSwyllys 		goto cleanup;
549130a5e8faSwyllys 	}
549230a5e8faSwyllys 
549330a5e8faSwyllys 	p = tacert->Data;
549430a5e8faSwyllys 	len = tacert->Length;
549530a5e8faSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
549630a5e8faSwyllys 
549730a5e8faSwyllys 	if (xcert == NULL) {
549830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
549930a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
550030a5e8faSwyllys 		goto cleanup;
550130a5e8faSwyllys 	}
550230a5e8faSwyllys 
550330a5e8faSwyllys 	/* Get issuer certificate public key */
550430a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
550530a5e8faSwyllys 	if (pkey == NULL) {
550630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
550730a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
550830a5e8faSwyllys 		goto cleanup;
550930a5e8faSwyllys 	}
551030a5e8faSwyllys 
551130a5e8faSwyllys 	/* Verify CRL signature */
551230a5e8faSwyllys 	sslret = X509_CRL_verify(xcrl, pkey);
551330a5e8faSwyllys 	EVP_PKEY_free(pkey);
551430a5e8faSwyllys 	if (sslret > 0) {
551530a5e8faSwyllys 		ret = KMF_OK;
551630a5e8faSwyllys 	} else {
551730a5e8faSwyllys 		SET_ERROR(kmfh, sslret);
551830a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
551930a5e8faSwyllys 	}
552030a5e8faSwyllys 
552130a5e8faSwyllys cleanup:
552230a5e8faSwyllys 	if (bcrl != NULL)
552330a5e8faSwyllys 		(void) BIO_free(bcrl);
552430a5e8faSwyllys 
552530a5e8faSwyllys 	if (xcrl != NULL)
552630a5e8faSwyllys 		X509_CRL_free(xcrl);
552730a5e8faSwyllys 
552830a5e8faSwyllys 	if (xcert != NULL)
552930a5e8faSwyllys 		X509_free(xcert);
553030a5e8faSwyllys 
553130a5e8faSwyllys 	return (ret);
553230a5e8faSwyllys 
553330a5e8faSwyllys }
553430a5e8faSwyllys 
553530a5e8faSwyllys KMF_RETURN
553630a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
553730a5e8faSwyllys {
553830a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
553930a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
554030a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
554130a5e8faSwyllys 	BIO		*bcrl = NULL;
554230a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
554330a5e8faSwyllys 	int		i;
554430a5e8faSwyllys 
554530a5e8faSwyllys 	if (handle == NULL || crlname == NULL) {
554630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
554730a5e8faSwyllys 	}
554830a5e8faSwyllys 
554930a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlname, &crl_format);
555030a5e8faSwyllys 	if (ret != KMF_OK)
555130a5e8faSwyllys 		return (ret);
555230a5e8faSwyllys 
555330a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
555430a5e8faSwyllys 	if (bcrl == NULL) {
555530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
555630a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
555730a5e8faSwyllys 		goto cleanup;
555830a5e8faSwyllys 	}
555930a5e8faSwyllys 
55605b3e1433Swyllys 	if (crl_format == KMF_FORMAT_ASN1)
556130a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
55625b3e1433Swyllys 	else if (crl_format == KMF_FORMAT_PEM)
556330a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
556430a5e8faSwyllys 
556530a5e8faSwyllys 	if (xcrl == NULL) {
556630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
556730a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
556830a5e8faSwyllys 		goto cleanup;
556930a5e8faSwyllys 	}
557030a5e8faSwyllys 	i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL);
557130a5e8faSwyllys 	if (i >= 0) {
557230a5e8faSwyllys 		ret = KMF_ERR_VALIDITY_PERIOD;
557330a5e8faSwyllys 		goto cleanup;
557430a5e8faSwyllys 	}
557530a5e8faSwyllys 	if (X509_CRL_get_nextUpdate(xcrl)) {
557630a5e8faSwyllys 		i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL);
557730a5e8faSwyllys 
557830a5e8faSwyllys 		if (i <= 0) {
557930a5e8faSwyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
558030a5e8faSwyllys 			goto cleanup;
558130a5e8faSwyllys 		}
558230a5e8faSwyllys 	}
558330a5e8faSwyllys 
558430a5e8faSwyllys 	ret = KMF_OK;
558530a5e8faSwyllys 
558630a5e8faSwyllys cleanup:
558730a5e8faSwyllys 	if (bcrl != NULL)
558830a5e8faSwyllys 		(void) BIO_free(bcrl);
558930a5e8faSwyllys 
559030a5e8faSwyllys 	if (xcrl != NULL)
559130a5e8faSwyllys 		X509_CRL_free(xcrl);
559230a5e8faSwyllys 
559330a5e8faSwyllys 	return (ret);
559430a5e8faSwyllys }
5595