199ebb4caSwyllys /*
2a2d4930dSDan OpenSolaris Anderson  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
399ebb4caSwyllys  * Use is subject to license terms.
499ebb4caSwyllys  */
59a767088Shaimay /*
69a767088Shaimay  * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
79a767088Shaimay  * project 2000.
89a767088Shaimay  */
99a767088Shaimay /*
109a767088Shaimay  * ====================================================================
119a767088Shaimay  * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
129a767088Shaimay  *
139a767088Shaimay  * Redistribution and use in source and binary forms, with or without
149a767088Shaimay  * modification, are permitted provided that the following conditions
159a767088Shaimay  * are met:
169a767088Shaimay  *
179a767088Shaimay  * 1. Redistributions of source code must retain the above copyright
189a767088Shaimay  *    notice, this list of conditions and the following disclaimer.
199a767088Shaimay  *
209a767088Shaimay  * 2. Redistributions in binary form must reproduce the above copyright
219a767088Shaimay  *    notice, this list of conditions and the following disclaimer in
229a767088Shaimay  *    the documentation and/or other materials provided with the
239a767088Shaimay  *    distribution.
249a767088Shaimay  *
259a767088Shaimay  * 3. All advertising materials mentioning features or use of this
269a767088Shaimay  *    software must display the following acknowledgment:
279a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
289a767088Shaimay  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
299a767088Shaimay  *
309a767088Shaimay  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
319a767088Shaimay  *    endorse or promote products derived from this software without
329a767088Shaimay  *    prior written permission. For written permission, please contact
339a767088Shaimay  *    licensing@OpenSSL.org.
349a767088Shaimay  *
359a767088Shaimay  * 5. Products derived from this software may not be called "OpenSSL"
369a767088Shaimay  *    nor may "OpenSSL" appear in their names without prior written
379a767088Shaimay  *    permission of the OpenSSL Project.
389a767088Shaimay  *
399a767088Shaimay  * 6. Redistributions of any form whatsoever must retain the following
409a767088Shaimay  *    acknowledgment:
419a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
429a767088Shaimay  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
439a767088Shaimay  *
449a767088Shaimay  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
459a767088Shaimay  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
469a767088Shaimay  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
479a767088Shaimay  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
489a767088Shaimay  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
499a767088Shaimay  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
509a767088Shaimay  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
519a767088Shaimay  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
529a767088Shaimay  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
539a767088Shaimay  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
549a767088Shaimay  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
559a767088Shaimay  * OF THE POSSIBILITY OF SUCH DAMAGE.
569a767088Shaimay  * ====================================================================
579a767088Shaimay  *
589a767088Shaimay  * This product includes cryptographic software written by Eric Young
599a767088Shaimay  * (eay@cryptsoft.com).  This product includes software written by Tim
609a767088Shaimay  * Hudson (tjh@cryptsoft.com).
619a767088Shaimay  *
629a767088Shaimay  */
6399ebb4caSwyllys 
6471593db2Swyllys #include <stdlib.h>
6599ebb4caSwyllys #include <kmfapiP.h>
6699ebb4caSwyllys #include <ber_der.h>
6799ebb4caSwyllys #include <fcntl.h>
6899ebb4caSwyllys #include <sys/stat.h>
6999ebb4caSwyllys #include <dirent.h>
7099ebb4caSwyllys #include <cryptoutil.h>
7199ebb4caSwyllys #include <synch.h>
7299ebb4caSwyllys #include <thread.h>
7399ebb4caSwyllys 
7499ebb4caSwyllys /* OPENSSL related headers */
7599ebb4caSwyllys #include <openssl/bio.h>
7699ebb4caSwyllys #include <openssl/bn.h>
7799ebb4caSwyllys #include <openssl/asn1.h>
7899ebb4caSwyllys #include <openssl/err.h>
7999ebb4caSwyllys #include <openssl/bn.h>
8099ebb4caSwyllys #include <openssl/x509.h>
8199ebb4caSwyllys #include <openssl/rsa.h>
8299ebb4caSwyllys #include <openssl/dsa.h>
8399ebb4caSwyllys #include <openssl/x509v3.h>
8499ebb4caSwyllys #include <openssl/objects.h>
8599ebb4caSwyllys #include <openssl/pem.h>
8699ebb4caSwyllys #include <openssl/pkcs12.h>
8799ebb4caSwyllys #include <openssl/ocsp.h>
8899ebb4caSwyllys #include <openssl/des.h>
8999ebb4caSwyllys #include <openssl/rand.h>
9099ebb4caSwyllys 
9199ebb4caSwyllys #define	PRINT_ANY_EXTENSION (\
9299ebb4caSwyllys 	KMF_X509_EXT_KEY_USAGE |\
9399ebb4caSwyllys 	KMF_X509_EXT_CERT_POLICIES |\
9499ebb4caSwyllys 	KMF_X509_EXT_SUBJALTNAME |\
9599ebb4caSwyllys 	KMF_X509_EXT_BASIC_CONSTRAINTS |\
9699ebb4caSwyllys 	KMF_X509_EXT_NAME_CONSTRAINTS |\
9799ebb4caSwyllys 	KMF_X509_EXT_POLICY_CONSTRAINTS |\
9899ebb4caSwyllys 	KMF_X509_EXT_EXT_KEY_USAGE |\
9999ebb4caSwyllys 	KMF_X509_EXT_INHIBIT_ANY_POLICY |\
10099ebb4caSwyllys 	KMF_X509_EXT_AUTH_KEY_ID |\
10199ebb4caSwyllys 	KMF_X509_EXT_SUBJ_KEY_ID |\
10299ebb4caSwyllys 	KMF_X509_EXT_POLICY_MAPPING)
10399ebb4caSwyllys 
10499ebb4caSwyllys static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
10599ebb4caSwyllys 	0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
10699ebb4caSwyllys 	0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
10799ebb4caSwyllys 	0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
10899ebb4caSwyllys 	0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
10999ebb4caSwyllys 	0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
11099ebb4caSwyllys 	0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
11199ebb4caSwyllys 	0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
11299ebb4caSwyllys 	0x91 };
11399ebb4caSwyllys 
11499ebb4caSwyllys static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
11599ebb4caSwyllys 	0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
11699ebb4caSwyllys 	0x8e, 0xda, 0xce, 0x91, 0x5f };
11799ebb4caSwyllys 
11899ebb4caSwyllys static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
11999ebb4caSwyllys 	0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
12099ebb4caSwyllys 	0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
12199ebb4caSwyllys 	0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
12299ebb4caSwyllys 	0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
12399ebb4caSwyllys 	0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
12499ebb4caSwyllys 	0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
12599ebb4caSwyllys 	0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
12699ebb4caSwyllys 	0x02 };
12799ebb4caSwyllys 
12899ebb4caSwyllys #define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
12999ebb4caSwyllys 	h->lasterr.errcode = c;
13099ebb4caSwyllys 
13199ebb4caSwyllys #define	SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
13299ebb4caSwyllys 
1335b3e1433Swyllys /*
1345b3e1433Swyllys  * Declare some new macros for managing stacks of EVP_PKEYS, similar to
1355b3e1433Swyllys  * what wanboot did.
1365b3e1433Swyllys  */
1375b3e1433Swyllys DECLARE_STACK_OF(EVP_PKEY)
1385b3e1433Swyllys 
1395b3e1433Swyllys #define	sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
1405b3e1433Swyllys #define	sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
1415b3e1433Swyllys #define	sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
1425b3e1433Swyllys #define	sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
1435b3e1433Swyllys #define	sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
1445b3e1433Swyllys #define	sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
1455b3e1433Swyllys 	(free_func))
1465b3e1433Swyllys 
14799ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX;
14899ebb4caSwyllys static int ssl_initialized = 0;
14930a5e8faSwyllys static BIO *bio_err = NULL;
15030a5e8faSwyllys 
15130a5e8faSwyllys static int
15230a5e8faSwyllys test_for_file(char *, mode_t);
1535b3e1433Swyllys static KMF_RETURN
1545b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *, char *, int,
1555b3e1433Swyllys     STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
1565b3e1433Swyllys 
1575b3e1433Swyllys static KMF_RETURN
1585b3e1433Swyllys local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *,
1595b3e1433Swyllys     int, KMF_KEY_HANDLE *, char *);
1605b3e1433Swyllys 
1615b3e1433Swyllys static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int);
16299ebb4caSwyllys 
16371593db2Swyllys static KMF_RETURN
16430a5e8faSwyllys extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *,
16502744e81Swyllys     CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
16671593db2Swyllys 
16771593db2Swyllys static KMF_RETURN
16830a5e8faSwyllys kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
16930a5e8faSwyllys     char *, KMF_DATA *);
17030a5e8faSwyllys 
17130a5e8faSwyllys static KMF_RETURN
17230a5e8faSwyllys load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
17330a5e8faSwyllys     char *, KMF_DATA **, uint32_t *);
17471593db2Swyllys 
17502744e81Swyllys static KMF_RETURN
17602744e81Swyllys sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
17702744e81Swyllys 
17802744e81Swyllys static EVP_PKEY *
17902744e81Swyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *);
18002744e81Swyllys 
18130a5e8faSwyllys static KMF_RETURN
18230a5e8faSwyllys convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
18330a5e8faSwyllys 
18499ebb4caSwyllys KMF_RETURN
18530a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
18699ebb4caSwyllys 
18799ebb4caSwyllys void
18899ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
18999ebb4caSwyllys 
19099ebb4caSwyllys KMF_RETURN
19130a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
19299ebb4caSwyllys 
19399ebb4caSwyllys KMF_RETURN
19430a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
19599ebb4caSwyllys 
19699ebb4caSwyllys KMF_RETURN
19730a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
19830a5e8faSwyllys 
19930a5e8faSwyllys KMF_RETURN
20030a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20199ebb4caSwyllys 
20299ebb4caSwyllys KMF_RETURN
20399ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T,  KMF_KEY_HANDLE *, KMF_DATA *);
20499ebb4caSwyllys 
20599ebb4caSwyllys KMF_RETURN
20699ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
20799ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
20899ebb4caSwyllys 
20999ebb4caSwyllys KMF_RETURN
21030a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21199ebb4caSwyllys 
21299ebb4caSwyllys KMF_RETURN
21330a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21499ebb4caSwyllys 
21599ebb4caSwyllys KMF_RETURN
21630a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21799ebb4caSwyllys 
21899ebb4caSwyllys KMF_RETURN
21930a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22099ebb4caSwyllys 
22199ebb4caSwyllys KMF_RETURN
22230a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22399ebb4caSwyllys 
22499ebb4caSwyllys KMF_RETURN
22599ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
22699ebb4caSwyllys 	KMF_PRINTABLE_ITEM, char *);
22799ebb4caSwyllys 
22899ebb4caSwyllys KMF_RETURN
22999ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
23099ebb4caSwyllys 
23199ebb4caSwyllys KMF_RETURN
23230a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23399ebb4caSwyllys 
23499ebb4caSwyllys KMF_RETURN
23599ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
23699ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
23799ebb4caSwyllys 
23899ebb4caSwyllys KMF_RETURN
23930a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24099ebb4caSwyllys 
24199ebb4caSwyllys KMF_RETURN
24230a5e8faSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24399ebb4caSwyllys 
24499ebb4caSwyllys KMF_RETURN
24530a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24699ebb4caSwyllys 
24799ebb4caSwyllys KMF_RETURN
24830a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24999ebb4caSwyllys 
25099ebb4caSwyllys KMF_RETURN
25130a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25299ebb4caSwyllys 
25399ebb4caSwyllys KMF_RETURN
25499ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
25599ebb4caSwyllys 
25699ebb4caSwyllys KMF_RETURN
25730a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
25899ebb4caSwyllys 
25999ebb4caSwyllys KMF_RETURN
26030a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
26199ebb4caSwyllys 
26299ebb4caSwyllys static
26399ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table =
26499ebb4caSwyllys {
26599ebb4caSwyllys 	1,				/* Version */
26699ebb4caSwyllys 	NULL, /* ConfigureKeystore */
26799ebb4caSwyllys 	OpenSSL_FindCert,
26899ebb4caSwyllys 	OpenSSL_FreeKMFCert,
26999ebb4caSwyllys 	OpenSSL_StoreCert,
27099ebb4caSwyllys 	NULL, /* ImportCert */
27199ebb4caSwyllys 	OpenSSL_ImportCRL,
27299ebb4caSwyllys 	OpenSSL_DeleteCert,
27399ebb4caSwyllys 	OpenSSL_DeleteCRL,
27499ebb4caSwyllys 	OpenSSL_CreateKeypair,
27599ebb4caSwyllys 	OpenSSL_FindKey,
27699ebb4caSwyllys 	OpenSSL_EncodePubKeyData,
27799ebb4caSwyllys 	OpenSSL_SignData,
27899ebb4caSwyllys 	OpenSSL_DeleteKey,
27999ebb4caSwyllys 	OpenSSL_ListCRL,
28099ebb4caSwyllys 	NULL,	/* FindCRL */
28199ebb4caSwyllys 	OpenSSL_FindCertInCRL,
28299ebb4caSwyllys 	OpenSSL_GetErrorString,
28330a5e8faSwyllys 	OpenSSL_FindPrikeyByCert,
28499ebb4caSwyllys 	OpenSSL_DecryptData,
28530a5e8faSwyllys 	OpenSSL_ExportPK12,
28699ebb4caSwyllys 	OpenSSL_CreateSymKey,
28799ebb4caSwyllys 	OpenSSL_GetSymKeyValue,
28899ebb4caSwyllys 	NULL,	/* SetTokenPin */
28930a5e8faSwyllys 	OpenSSL_StoreKey,
29099ebb4caSwyllys 	NULL	/* Finalize */
29199ebb4caSwyllys };
29299ebb4caSwyllys 
29399ebb4caSwyllys static mutex_t *lock_cs;
29499ebb4caSwyllys static long *lock_count;
29599ebb4caSwyllys 
29699ebb4caSwyllys static void
297a2d4930dSDan OpenSolaris Anderson /* ARGSUSED1 */
29899ebb4caSwyllys locking_cb(int mode, int type, char *file, int line)
29999ebb4caSwyllys {
30099ebb4caSwyllys 	if (mode & CRYPTO_LOCK) {
30199ebb4caSwyllys 		(void) mutex_lock(&(lock_cs[type]));
30299ebb4caSwyllys 		lock_count[type]++;
30399ebb4caSwyllys 	} else {
30499ebb4caSwyllys 		(void) mutex_unlock(&(lock_cs[type]));
30599ebb4caSwyllys 	}
30699ebb4caSwyllys }
30799ebb4caSwyllys 
30899ebb4caSwyllys static unsigned long
30999ebb4caSwyllys thread_id()
31099ebb4caSwyllys {
31199ebb4caSwyllys 	return ((unsigned long)thr_self());
31299ebb4caSwyllys }
31399ebb4caSwyllys 
31499ebb4caSwyllys KMF_PLUGIN_FUNCLIST *
31599ebb4caSwyllys KMF_Plugin_Initialize()
31699ebb4caSwyllys {
31799ebb4caSwyllys 	int i;
31899ebb4caSwyllys 
31999ebb4caSwyllys 	(void) mutex_lock(&init_lock);
32099ebb4caSwyllys 	if (!ssl_initialized) {
32199ebb4caSwyllys 		OpenSSL_add_all_algorithms();
32299ebb4caSwyllys 
32399ebb4caSwyllys 		/* Enable error strings for reporting */
32499ebb4caSwyllys 		ERR_load_crypto_strings();
32599ebb4caSwyllys 
32699ebb4caSwyllys 		/*
32799ebb4caSwyllys 		 * Add support for extension OIDs that are not yet in the
32899ebb4caSwyllys 		 * openssl default set.
32999ebb4caSwyllys 		 */
33099ebb4caSwyllys 		(void) OBJ_create("2.5.29.30", "nameConstraints",
33199ebb4caSwyllys 		    "X509v3 Name Constraints");
33299ebb4caSwyllys 		(void) OBJ_create("2.5.29.33", "policyMappings",
33399ebb4caSwyllys 		    "X509v3 Policy Mappings");
33499ebb4caSwyllys 		(void) OBJ_create("2.5.29.36", "policyConstraints",
33599ebb4caSwyllys 		    "X509v3 Policy Constraints");
33699ebb4caSwyllys 		(void) OBJ_create("2.5.29.46", "freshestCRL",
33799ebb4caSwyllys 		    "X509v3 Freshest CRL");
33899ebb4caSwyllys 		(void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
33999ebb4caSwyllys 		    "X509v3 Inhibit Any-Policy");
34099ebb4caSwyllys 		/*
34199ebb4caSwyllys 		 * Set up for thread-safe operation.
34299ebb4caSwyllys 		 */
34399ebb4caSwyllys 		lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
34499ebb4caSwyllys 		if (lock_cs == NULL) {
34599ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
34699ebb4caSwyllys 			return (NULL);
34799ebb4caSwyllys 		}
34899ebb4caSwyllys 
34999ebb4caSwyllys 		lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
35099ebb4caSwyllys 		if (lock_count == NULL) {
35199ebb4caSwyllys 			OPENSSL_free(lock_cs);
35299ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
35399ebb4caSwyllys 			return (NULL);
35499ebb4caSwyllys 		}
35599ebb4caSwyllys 
35699ebb4caSwyllys 		for (i = 0; i < CRYPTO_num_locks(); i++) {
35799ebb4caSwyllys 			lock_count[i] = 0;
35899ebb4caSwyllys 			(void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
35999ebb4caSwyllys 		}
36099ebb4caSwyllys 
36199ebb4caSwyllys 		CRYPTO_set_id_callback((unsigned long (*)())thread_id);
36299ebb4caSwyllys 		CRYPTO_set_locking_callback((void (*)())locking_cb);
36399ebb4caSwyllys 		ssl_initialized = 1;
36499ebb4caSwyllys 	}
36599ebb4caSwyllys 	(void) mutex_unlock(&init_lock);
36699ebb4caSwyllys 
36799ebb4caSwyllys 	return (&openssl_plugin_table);
36899ebb4caSwyllys }
36999ebb4caSwyllys /*
37099ebb4caSwyllys  * Convert an SSL DN to a KMF DN.
37199ebb4caSwyllys  */
37299ebb4caSwyllys static KMF_RETURN
37399ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
37499ebb4caSwyllys {
37599ebb4caSwyllys 	KMF_DATA derdata;
37699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
37799ebb4caSwyllys 	uchar_t *tmp;
37899ebb4caSwyllys 
37999ebb4caSwyllys 	/* Convert to raw DER format */
38099ebb4caSwyllys 	derdata.Length = i2d_X509_NAME(sslDN, NULL);
38199ebb4caSwyllys 	if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
38299ebb4caSwyllys 	    == NULL) {
38399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
38499ebb4caSwyllys 	}
38599ebb4caSwyllys 	(void) i2d_X509_NAME(sslDN, &tmp);
38699ebb4caSwyllys 
38799ebb4caSwyllys 	/* Decode to KMF format */
38899ebb4caSwyllys 	rv = DerDecodeName(&derdata, kmfDN);
38999ebb4caSwyllys 	if (rv != KMF_OK) {
39099ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
39199ebb4caSwyllys 	}
39299ebb4caSwyllys 	OPENSSL_free(derdata.Data);
39399ebb4caSwyllys 
39499ebb4caSwyllys 	return (rv);
39599ebb4caSwyllys }
39699ebb4caSwyllys 
39730a5e8faSwyllys int
39899ebb4caSwyllys isdir(char *path)
39999ebb4caSwyllys {
40099ebb4caSwyllys 	struct stat s;
40199ebb4caSwyllys 
40299ebb4caSwyllys 	if (stat(path, &s) == -1)
40399ebb4caSwyllys 		return (0);
40499ebb4caSwyllys 
40530a5e8faSwyllys 	return ((s.st_mode & S_IFMT) == S_IFDIR);
40699ebb4caSwyllys }
40799ebb4caSwyllys 
40899ebb4caSwyllys static KMF_RETURN
40999ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
41099ebb4caSwyllys {
41199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
41299ebb4caSwyllys 	unsigned char *buf = NULL, *p;
41399ebb4caSwyllys 	int len;
41499ebb4caSwyllys 
41599ebb4caSwyllys 	/*
41699ebb4caSwyllys 	 * Convert the X509 internal struct to DER encoded data
41799ebb4caSwyllys 	 */
41899ebb4caSwyllys 	if ((len = i2d_X509(x509cert, NULL)) < 0) {
41999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
42099ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
42199ebb4caSwyllys 		goto cleanup;
42299ebb4caSwyllys 	}
42399ebb4caSwyllys 	if ((buf = malloc(len)) == NULL) {
42499ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
42599ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
42699ebb4caSwyllys 		goto cleanup;
42799ebb4caSwyllys 	}
42899ebb4caSwyllys 
42999ebb4caSwyllys 	/*
43099ebb4caSwyllys 	 * i2d_X509 will increment the buf pointer so that we need to
43199ebb4caSwyllys 	 * save it.
43299ebb4caSwyllys 	 */
43399ebb4caSwyllys 	p = buf;
43499ebb4caSwyllys 	if ((len = i2d_X509(x509cert, &p)) < 0) {
43599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
43699ebb4caSwyllys 		free(buf);
43799ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
43899ebb4caSwyllys 		goto cleanup;
43999ebb4caSwyllys 	}
44099ebb4caSwyllys 
44199ebb4caSwyllys 	/* caller's responsibility to free it */
44299ebb4caSwyllys 	cert->Data = buf;
44399ebb4caSwyllys 	cert->Length = len;
44499ebb4caSwyllys 
44599ebb4caSwyllys cleanup:
44699ebb4caSwyllys 	if (rv != KMF_OK) {
44799ebb4caSwyllys 		if (buf)
44899ebb4caSwyllys 			free(buf);
44999ebb4caSwyllys 		cert->Data = NULL;
45099ebb4caSwyllys 		cert->Length = 0;
45199ebb4caSwyllys 	}
45299ebb4caSwyllys 
45399ebb4caSwyllys 	return (rv);
45499ebb4caSwyllys }
45599ebb4caSwyllys 
45630a5e8faSwyllys 
45799ebb4caSwyllys static KMF_RETURN
45830a5e8faSwyllys check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
45930a5e8faSwyllys     boolean_t *match)
46099ebb4caSwyllys {
46199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
46299ebb4caSwyllys 	boolean_t findIssuer = FALSE;
46399ebb4caSwyllys 	boolean_t findSubject = FALSE;
46499ebb4caSwyllys 	boolean_t findSerial = FALSE;
46599ebb4caSwyllys 	KMF_X509_NAME issuerDN, subjectDN;
46699ebb4caSwyllys 	KMF_X509_NAME certIssuerDN, certSubjectDN;
46799ebb4caSwyllys 
46899ebb4caSwyllys 	*match = FALSE;
46999ebb4caSwyllys 	if (xcert == NULL) {
47099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
47199ebb4caSwyllys 	}
47299ebb4caSwyllys 
47399ebb4caSwyllys 	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
47499ebb4caSwyllys 	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
47599ebb4caSwyllys 	(void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
47699ebb4caSwyllys 	(void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
47799ebb4caSwyllys 
47830a5e8faSwyllys 	if (issuer != NULL && strlen(issuer)) {
47930a5e8faSwyllys 		rv = kmf_dn_parser(issuer, &issuerDN);
48099ebb4caSwyllys 		if (rv != KMF_OK)
48199ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
48299ebb4caSwyllys 
48399ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->issuer, &certIssuerDN);
48499ebb4caSwyllys 		if (rv != KMF_OK) {
48530a5e8faSwyllys 			kmf_free_dn(&issuerDN);
48699ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
48799ebb4caSwyllys 		}
48899ebb4caSwyllys 
48999ebb4caSwyllys 		findIssuer = TRUE;
49099ebb4caSwyllys 	}
49130a5e8faSwyllys 	if (subject != NULL && strlen(subject)) {
49230a5e8faSwyllys 		rv = kmf_dn_parser(subject, &subjectDN);
49399ebb4caSwyllys 		if (rv != KMF_OK) {
49499ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
49599ebb4caSwyllys 			goto cleanup;
49699ebb4caSwyllys 		}
49799ebb4caSwyllys 
49899ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->subject, &certSubjectDN);
49999ebb4caSwyllys 		if (rv != KMF_OK) {
50099ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
50199ebb4caSwyllys 			goto cleanup;
50299ebb4caSwyllys 		}
50399ebb4caSwyllys 		findSubject = TRUE;
50499ebb4caSwyllys 	}
50530a5e8faSwyllys 	if (serial != NULL && serial->val != NULL)
50699ebb4caSwyllys 		findSerial = TRUE;
50799ebb4caSwyllys 
50899ebb4caSwyllys 	if (findSerial) {
50999ebb4caSwyllys 		BIGNUM *bn;
51099ebb4caSwyllys 
51199ebb4caSwyllys 		/* Comparing BIGNUMs is a pain! */
51299ebb4caSwyllys 		bn = ASN1_INTEGER_to_BN(xcert->cert_info->serialNumber, NULL);
51399ebb4caSwyllys 		if (bn != NULL) {
51499ebb4caSwyllys 			int bnlen = BN_num_bytes(bn);
51599ebb4caSwyllys 
51630a5e8faSwyllys 			if (bnlen == serial->len) {
51799ebb4caSwyllys 				uchar_t *a = malloc(bnlen);
51899ebb4caSwyllys 				if (a == NULL) {
51999ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
52099ebb4caSwyllys 					BN_free(bn);
52199ebb4caSwyllys 					goto cleanup;
52299ebb4caSwyllys 				}
52399ebb4caSwyllys 				bnlen = BN_bn2bin(bn, a);
52430a5e8faSwyllys 				*match = (memcmp(a, serial->val, serial->len) ==
52530a5e8faSwyllys 				    0);
52699ebb4caSwyllys 				rv = KMF_OK;
52799ebb4caSwyllys 				free(a);
52899ebb4caSwyllys 			}
52999ebb4caSwyllys 			BN_free(bn);
53099ebb4caSwyllys 			if (!(*match))
53199ebb4caSwyllys 				goto cleanup;
53299ebb4caSwyllys 		} else {
53399ebb4caSwyllys 			rv = KMF_OK;
53499ebb4caSwyllys 			goto cleanup;
53599ebb4caSwyllys 		}
53699ebb4caSwyllys 	}
53799ebb4caSwyllys 	if (findIssuer) {
53830a5e8faSwyllys 		*match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
53930a5e8faSwyllys 		if ((*match) == B_FALSE) {
54030a5e8faSwyllys 			/* stop checking and bail */
54199ebb4caSwyllys 			rv = KMF_OK;
54299ebb4caSwyllys 			goto cleanup;
54399ebb4caSwyllys 		}
54499ebb4caSwyllys 	}
54599ebb4caSwyllys 	if (findSubject) {
54630a5e8faSwyllys 		*match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
54730a5e8faSwyllys 		if ((*match) == B_FALSE) {
54830a5e8faSwyllys 			/* stop checking and bail */
54999ebb4caSwyllys 			rv = KMF_OK;
55099ebb4caSwyllys 			goto cleanup;
55199ebb4caSwyllys 		}
55299ebb4caSwyllys 	}
55399ebb4caSwyllys 
55499ebb4caSwyllys 	*match = TRUE;
55599ebb4caSwyllys cleanup:
55699ebb4caSwyllys 	if (findIssuer) {
55730a5e8faSwyllys 		kmf_free_dn(&issuerDN);
55830a5e8faSwyllys 		kmf_free_dn(&certIssuerDN);
55999ebb4caSwyllys 	}
56099ebb4caSwyllys 	if (findSubject) {
56130a5e8faSwyllys 		kmf_free_dn(&subjectDN);
56230a5e8faSwyllys 		kmf_free_dn(&certSubjectDN);
56399ebb4caSwyllys 	}
56499ebb4caSwyllys 
56599ebb4caSwyllys 	return (rv);
56699ebb4caSwyllys }
56799ebb4caSwyllys 
56830a5e8faSwyllys 
56930a5e8faSwyllys /*
57030a5e8faSwyllys  * This function loads a certificate file into an X509 data structure, and
57130a5e8faSwyllys  * checks if its issuer, subject or the serial number matches with those
57230a5e8faSwyllys  * values.  If it matches, then return the X509 data structure.
57330a5e8faSwyllys  */
57499ebb4caSwyllys static KMF_RETURN
57599ebb4caSwyllys load_X509cert(KMF_HANDLE *kmfh,
57630a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
57730a5e8faSwyllys     char *pathname, X509 **outcert)
57899ebb4caSwyllys {
57999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
58099ebb4caSwyllys 	X509 *xcert = NULL;
58199ebb4caSwyllys 	BIO *bcert = NULL;
58299ebb4caSwyllys 	boolean_t  match = FALSE;
58399ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
58499ebb4caSwyllys 
58599ebb4caSwyllys 	/*
58699ebb4caSwyllys 	 * auto-detect the file format, regardless of what
58799ebb4caSwyllys 	 * the 'format' parameters in the params say.
58899ebb4caSwyllys 	 */
58930a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
59099ebb4caSwyllys 	if (rv != KMF_OK) {
59199ebb4caSwyllys 		if (rv == KMF_ERR_OPEN_FILE)
59299ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
59399ebb4caSwyllys 		return (rv);
59499ebb4caSwyllys 	}
59599ebb4caSwyllys 
59699ebb4caSwyllys 	/* Not ASN1(DER) format */
59799ebb4caSwyllys 	if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
59899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
59999ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
60099ebb4caSwyllys 		goto cleanup;
60199ebb4caSwyllys 	}
60299ebb4caSwyllys 
60399ebb4caSwyllys 	if (format == KMF_FORMAT_PEM)
60499ebb4caSwyllys 		xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
60599ebb4caSwyllys 	else if (format == KMF_FORMAT_ASN1)
60699ebb4caSwyllys 		xcert = d2i_X509_bio(bcert, NULL);
60799ebb4caSwyllys 	else if (format == KMF_FORMAT_PKCS12) {
60899ebb4caSwyllys 		PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
60999ebb4caSwyllys 		if (p12 != NULL) {
61099ebb4caSwyllys 			(void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
61199ebb4caSwyllys 			PKCS12_free(p12);
61299ebb4caSwyllys 			p12 = NULL;
61399ebb4caSwyllys 		} else {
61499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
61599ebb4caSwyllys 			rv = KMF_ERR_BAD_CERT_FORMAT;
61699ebb4caSwyllys 		}
61799ebb4caSwyllys 	} else {
61899ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
61999ebb4caSwyllys 		goto cleanup;
62099ebb4caSwyllys 	}
62199ebb4caSwyllys 
62299ebb4caSwyllys 	if (xcert == NULL) {
62399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
62499ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
62599ebb4caSwyllys 		goto cleanup;
62699ebb4caSwyllys 	}
62799ebb4caSwyllys 
62830a5e8faSwyllys 	if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
62930a5e8faSwyllys 	    match == FALSE) {
63099ebb4caSwyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
63199ebb4caSwyllys 		goto cleanup;
63299ebb4caSwyllys 	}
63399ebb4caSwyllys 
63499ebb4caSwyllys 	if (outcert != NULL) {
63599ebb4caSwyllys 		*outcert = xcert;
63699ebb4caSwyllys 	}
63799ebb4caSwyllys 
63899ebb4caSwyllys cleanup:
63999ebb4caSwyllys 	if (bcert != NULL) (void) BIO_free(bcert);
64099ebb4caSwyllys 	if (rv != KMF_OK && xcert != NULL)
64199ebb4caSwyllys 		X509_free(xcert);
64299ebb4caSwyllys 
64399ebb4caSwyllys 	return (rv);
64499ebb4caSwyllys }
64599ebb4caSwyllys 
64671593db2Swyllys static int
64771593db2Swyllys datacmp(const void *a, const void *b)
64871593db2Swyllys {
64971593db2Swyllys 	KMF_DATA *adata = (KMF_DATA *)a;
65071593db2Swyllys 	KMF_DATA *bdata = (KMF_DATA *)b;
65171593db2Swyllys 	if (adata->Length > bdata->Length)
65271593db2Swyllys 		return (-1);
65371593db2Swyllys 	if (adata->Length < bdata->Length)
65471593db2Swyllys 		return (1);
65571593db2Swyllys 	return (0);
65671593db2Swyllys }
65771593db2Swyllys 
65871593db2Swyllys static KMF_RETURN
65930a5e8faSwyllys load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
66030a5e8faSwyllys     KMF_CERT_VALIDITY validity, char *pathname,
66171593db2Swyllys     KMF_DATA **certlist, uint32_t *numcerts)
66271593db2Swyllys {
66371593db2Swyllys 	KMF_RETURN rv = KMF_OK;
66471593db2Swyllys 	int i;
66571593db2Swyllys 	KMF_DATA *certs = NULL;
66671593db2Swyllys 	int nc = 0;
66771593db2Swyllys 	int hits = 0;
66871593db2Swyllys 	KMF_ENCODE_FORMAT format;
66971593db2Swyllys 
67030a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
67171593db2Swyllys 	if (rv != KMF_OK) {
67271593db2Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
67371593db2Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
67471593db2Swyllys 		return (rv);
67571593db2Swyllys 	}
67671593db2Swyllys 	if (format == KMF_FORMAT_ASN1) {
67771593db2Swyllys 		/* load a single certificate */
67871593db2Swyllys 		certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
67971593db2Swyllys 		if (certs == NULL)
68071593db2Swyllys 			return (KMF_ERR_MEMORY);
68171593db2Swyllys 		certs->Data = NULL;
68271593db2Swyllys 		certs->Length = 0;
68330a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
68430a5e8faSwyllys 		    pathname, certs);
68571593db2Swyllys 		if (rv == KMF_OK) {
68671593db2Swyllys 			*certlist = certs;
68771593db2Swyllys 			*numcerts = 1;
688a2d4930dSDan OpenSolaris Anderson 		} else {
689a2d4930dSDan OpenSolaris Anderson 			kmf_free_data(certs);
690a2d4930dSDan OpenSolaris Anderson 			free(certs);
691a2d4930dSDan OpenSolaris Anderson 			certs = NULL;
69271593db2Swyllys 		}
69371593db2Swyllys 		return (rv);
69471593db2Swyllys 	} else if (format == KMF_FORMAT_PKCS12) {
69571593db2Swyllys 		/* We need a credential to access a PKCS#12 file */
69671593db2Swyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
69771593db2Swyllys 	} else if (format == KMF_FORMAT_PEM ||
69871593db2Swyllys 	    format != KMF_FORMAT_PEM_KEYPAIR) {
699*e65e5c2dSWyllys Ingersoll 
70071593db2Swyllys 		/* This function only works on PEM files */
70130a5e8faSwyllys 		rv = extract_pem(kmfh, issuer, subject, serial, pathname,
70234acef67Swyllys 		    (uchar_t *)NULL, 0, NULL, &certs, &nc);
70371593db2Swyllys 	} else {
70471593db2Swyllys 		return (KMF_ERR_ENCODING);
70571593db2Swyllys 	}
70671593db2Swyllys 
70771593db2Swyllys 	if (rv != KMF_OK)
70871593db2Swyllys 		return (rv);
70971593db2Swyllys 
71071593db2Swyllys 	for (i = 0; i < nc; i++) {
71130a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
71230a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
71330a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
71430a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
71571593db2Swyllys 			if (rv == KMF_OK)
71671593db2Swyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
71771593db2Swyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD)
71871593db2Swyllys 				rv = KMF_OK;
71971593db2Swyllys 		}
72071593db2Swyllys 		if (rv != KMF_OK) {
72171593db2Swyllys 			/* Remove this cert from the list by clearing it. */
72230a5e8faSwyllys 			kmf_free_data(&certs[i]);
72371593db2Swyllys 		} else {
72471593db2Swyllys 			hits++; /* count valid certs found */
72571593db2Swyllys 		}
72671593db2Swyllys 		rv = KMF_OK;
72771593db2Swyllys 	}
728a2d4930dSDan OpenSolaris Anderson 	if (rv == KMF_OK && hits > 0) {
72971593db2Swyllys 		/*
73071593db2Swyllys 		 * Sort the list of certs by length to put the cleared ones
73171593db2Swyllys 		 * at the end so they don't get accessed by the caller.
73271593db2Swyllys 		 */
73371593db2Swyllys 		qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
73471593db2Swyllys 		*certlist = certs;
73571593db2Swyllys 
73671593db2Swyllys 		/* since we sorted the list, just return the number of hits */
73771593db2Swyllys 		*numcerts = hits;
738a2d4930dSDan OpenSolaris Anderson 	} else {
739*e65e5c2dSWyllys Ingersoll 		if (rv == KMF_OK && hits == 0)
740a2d4930dSDan OpenSolaris Anderson 			rv = KMF_ERR_CERT_NOT_FOUND;
741a2d4930dSDan OpenSolaris Anderson 		if (certs != NULL) {
742a2d4930dSDan OpenSolaris Anderson 			free(certs);
743a2d4930dSDan OpenSolaris Anderson 			certs = NULL;
744a2d4930dSDan OpenSolaris Anderson 		}
745a2d4930dSDan OpenSolaris Anderson 	}
74671593db2Swyllys 	return (rv);
74771593db2Swyllys }
74871593db2Swyllys 
74999ebb4caSwyllys static KMF_RETURN
75099ebb4caSwyllys kmf_load_cert(KMF_HANDLE *kmfh,
75130a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
75230a5e8faSwyllys     KMF_CERT_VALIDITY validity,
75399ebb4caSwyllys     char *pathname,
75499ebb4caSwyllys     KMF_DATA *cert)
75599ebb4caSwyllys {
75699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
75799ebb4caSwyllys 	X509 *x509cert = NULL;
75899ebb4caSwyllys 
75930a5e8faSwyllys 	rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
76099ebb4caSwyllys 	if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
76199ebb4caSwyllys 		rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
76299ebb4caSwyllys 		if (rv != KMF_OK) {
76399ebb4caSwyllys 			goto cleanup;
76499ebb4caSwyllys 		}
76530a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
76630a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
76730a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
76830a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
76999ebb4caSwyllys 			if (rv == KMF_OK)  {
77099ebb4caSwyllys 				/*
77199ebb4caSwyllys 				 * This is a valid cert so skip it.
77299ebb4caSwyllys 				 */
77399ebb4caSwyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
77499ebb4caSwyllys 			}
77599ebb4caSwyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD) {
77699ebb4caSwyllys 				/*
77799ebb4caSwyllys 				 * We want to return success when we
77899ebb4caSwyllys 				 * find an invalid cert.
77999ebb4caSwyllys 				 */
78099ebb4caSwyllys 				rv = KMF_OK;
78199ebb4caSwyllys 				goto cleanup;
78299ebb4caSwyllys 			}
78399ebb4caSwyllys 		}
78499ebb4caSwyllys 	}
78599ebb4caSwyllys cleanup:
78699ebb4caSwyllys 	if (x509cert != NULL)
78799ebb4caSwyllys 		X509_free(x509cert);
78899ebb4caSwyllys 
78999ebb4caSwyllys 	return (rv);
79099ebb4caSwyllys }
79199ebb4caSwyllys 
79202744e81Swyllys static KMF_RETURN
79302744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
79402744e81Swyllys {
79502744e81Swyllys 	KMF_RETURN ret = KMF_OK;
79602744e81Swyllys 	KMF_RAW_RSA_KEY rsa;
79702744e81Swyllys 	BerElement *asn1 = NULL;
79802744e81Swyllys 	BerValue filebuf;
79902744e81Swyllys 	BerValue OID = { NULL, 0 };
80002744e81Swyllys 	BerValue *Mod = NULL, *PubExp = NULL;
80102744e81Swyllys 	BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
80202744e81Swyllys 	BerValue *Coef = NULL;
80302744e81Swyllys 	BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
80402744e81Swyllys 	BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
80502744e81Swyllys 	BIGNUM *qminus1 = NULL;
80602744e81Swyllys 	BN_CTX *ctx = NULL;
80702744e81Swyllys 
80802744e81Swyllys 	*pkey = NULL;
80902744e81Swyllys 
81002744e81Swyllys 	filebuf.bv_val = (char *)filedata->Data;
81102744e81Swyllys 	filebuf.bv_len = filedata->Length;
81202744e81Swyllys 
81302744e81Swyllys 	asn1 = kmfder_init(&filebuf);
81402744e81Swyllys 	if (asn1 == NULL) {
81502744e81Swyllys 		ret = KMF_ERR_MEMORY;
81602744e81Swyllys 		goto out;
81702744e81Swyllys 	}
81802744e81Swyllys 
81902744e81Swyllys 	if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
82002744e81Swyllys 	    &OID, &Mod, &PubExp, &PriExp, &Prime1,
82102744e81Swyllys 	    &Prime2, &Coef) == -1)  {
82202744e81Swyllys 		ret = KMF_ERR_ENCODING;
82302744e81Swyllys 		goto out;
82402744e81Swyllys 	}
82502744e81Swyllys 
82602744e81Swyllys 	/*
82702744e81Swyllys 	 * We have to derive the 2 Exponents using Bignumber math.
82802744e81Swyllys 	 * Exp1 = PriExp mod (Prime1 - 1)
82902744e81Swyllys 	 * Exp2 = PriExp mod (Prime2 - 1)
83002744e81Swyllys 	 */
83102744e81Swyllys 
83202744e81Swyllys 	/* D = PrivateExponent */
83302744e81Swyllys 	D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
83402744e81Swyllys 	if (D == NULL) {
83502744e81Swyllys 		ret = KMF_ERR_MEMORY;
83602744e81Swyllys 		goto out;
83702744e81Swyllys 	}
83802744e81Swyllys 
83902744e81Swyllys 	/* P = Prime1 (first prime factor of Modulus) */
84002744e81Swyllys 	P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
84102744e81Swyllys 	if (D == NULL) {
84202744e81Swyllys 		ret = KMF_ERR_MEMORY;
84302744e81Swyllys 		goto out;
84402744e81Swyllys 	}
84502744e81Swyllys 
84602744e81Swyllys 	/* Q = Prime2 (second prime factor of Modulus) */
84702744e81Swyllys 	Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
84802744e81Swyllys 
84902744e81Swyllys 	if ((ctx = BN_CTX_new()) == NULL) {
85002744e81Swyllys 		ret = KMF_ERR_MEMORY;
85102744e81Swyllys 		goto out;
85202744e81Swyllys 	}
85302744e81Swyllys 
85402744e81Swyllys 	/* Compute (P - 1) */
85502744e81Swyllys 	pminus1 = BN_new();
85602744e81Swyllys 	(void) BN_sub(pminus1, P, BN_value_one());
85702744e81Swyllys 
85802744e81Swyllys 	/* Exponent1 = D mod (P - 1) */
85902744e81Swyllys 	Exp1 = BN_new();
86002744e81Swyllys 	(void) BN_mod(Exp1, D, pminus1, ctx);
86102744e81Swyllys 
86202744e81Swyllys 	/* Compute (Q - 1) */
86302744e81Swyllys 	qminus1 = BN_new();
86402744e81Swyllys 	(void) BN_sub(qminus1, Q, BN_value_one());
86502744e81Swyllys 
86602744e81Swyllys 	/* Exponent2 = D mod (Q - 1) */
86702744e81Swyllys 	Exp2 = BN_new();
86802744e81Swyllys 	(void) BN_mod(Exp2, D, qminus1, ctx);
86902744e81Swyllys 
87002744e81Swyllys 	/* Coef = (Inverse Q) mod P */
87102744e81Swyllys 	COEF = BN_new();
87202744e81Swyllys 	(void) BN_mod_inverse(COEF, Q, P, ctx);
87302744e81Swyllys 
87402744e81Swyllys 	/* Convert back to KMF format */
87502744e81Swyllys 	(void) memset(&rsa, 0, sizeof (rsa));
87602744e81Swyllys 
87702744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
87802744e81Swyllys 		goto out;
87902744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
88002744e81Swyllys 		goto out;
88102744e81Swyllys 	if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
88202744e81Swyllys 		goto out;
88302744e81Swyllys 
88402744e81Swyllys 	rsa.mod.val = (uchar_t *)Mod->bv_val;
88502744e81Swyllys 	rsa.mod.len = Mod->bv_len;
88602744e81Swyllys 
88702744e81Swyllys 	rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
88802744e81Swyllys 	rsa.pubexp.len = PubExp->bv_len;
88902744e81Swyllys 
89002744e81Swyllys 	rsa.priexp.val = (uchar_t *)PriExp->bv_val;
89102744e81Swyllys 	rsa.priexp.len = PriExp->bv_len;
89202744e81Swyllys 
89302744e81Swyllys 	rsa.prime1.val = (uchar_t *)Prime1->bv_val;
89402744e81Swyllys 	rsa.prime1.len = Prime1->bv_len;
89502744e81Swyllys 
89602744e81Swyllys 	rsa.prime2.val = (uchar_t *)Prime2->bv_val;
89702744e81Swyllys 	rsa.prime2.len = Prime2->bv_len;
89802744e81Swyllys 
89902744e81Swyllys 	*pkey = ImportRawRSAKey(&rsa);
90002744e81Swyllys out:
90102744e81Swyllys 	if (asn1 != NULL)
90202744e81Swyllys 		kmfber_free(asn1, 1);
90302744e81Swyllys 
90402744e81Swyllys 	if (OID.bv_val) {
90502744e81Swyllys 		free(OID.bv_val);
90602744e81Swyllys 	}
90702744e81Swyllys 	if (PriExp)
90802744e81Swyllys 		free(PriExp);
90902744e81Swyllys 
91002744e81Swyllys 	if (Mod)
91102744e81Swyllys 		free(Mod);
91202744e81Swyllys 
91302744e81Swyllys 	if (PubExp)
91402744e81Swyllys 		free(PubExp);
91502744e81Swyllys 
91602744e81Swyllys 	if (Coef) {
91702744e81Swyllys 		(void) memset(Coef->bv_val, 0, Coef->bv_len);
91802744e81Swyllys 		free(Coef->bv_val);
91902744e81Swyllys 		free(Coef);
92002744e81Swyllys 	}
92102744e81Swyllys 	if (Prime1)
92202744e81Swyllys 		free(Prime1);
92302744e81Swyllys 	if (Prime2)
92402744e81Swyllys 		free(Prime2);
92502744e81Swyllys 
92602744e81Swyllys 	if (ctx != NULL)
92702744e81Swyllys 		BN_CTX_free(ctx);
92802744e81Swyllys 
92902744e81Swyllys 	if (D)
93002744e81Swyllys 		BN_clear_free(D);
93102744e81Swyllys 	if (P)
93202744e81Swyllys 		BN_clear_free(P);
93302744e81Swyllys 	if (Q)
93402744e81Swyllys 		BN_clear_free(Q);
93502744e81Swyllys 	if (pminus1)
93602744e81Swyllys 		BN_clear_free(pminus1);
93702744e81Swyllys 	if (qminus1)
93802744e81Swyllys 		BN_clear_free(qminus1);
93902744e81Swyllys 	if (Exp1)
94002744e81Swyllys 		BN_clear_free(Exp1);
94102744e81Swyllys 	if (Exp2)
94202744e81Swyllys 		BN_clear_free(Exp2);
94302744e81Swyllys 
94402744e81Swyllys 	return (ret);
94502744e81Swyllys 
94602744e81Swyllys }
94702744e81Swyllys 
94899ebb4caSwyllys static EVP_PKEY *
94999ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file)
95099ebb4caSwyllys {
95199ebb4caSwyllys 	BIO *keyfile = NULL;
95299ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
95399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
95499ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
95502744e81Swyllys 	KMF_RETURN rv;
95602744e81Swyllys 	KMF_DATA filedata;
95799ebb4caSwyllys 
95899ebb4caSwyllys 	if (file == NULL) {
95999ebb4caSwyllys 		return (NULL);
96099ebb4caSwyllys 	}
96199ebb4caSwyllys 
96230a5e8faSwyllys 	if (kmf_get_file_format((char *)file, &format) != KMF_OK)
96399ebb4caSwyllys 		return (NULL);
96499ebb4caSwyllys 
96599ebb4caSwyllys 	keyfile = BIO_new_file(file, "rb");
96699ebb4caSwyllys 	if (keyfile == NULL) {
96799ebb4caSwyllys 		goto end;
96899ebb4caSwyllys 	}
96999ebb4caSwyllys 
97002744e81Swyllys 	if (format == KMF_FORMAT_ASN1) {
97199ebb4caSwyllys 		pkey = d2i_PrivateKey_bio(keyfile, NULL);
97202744e81Swyllys 		if (pkey == NULL) {
97302744e81Swyllys 
97402744e81Swyllys 			(void) BIO_free(keyfile);
97502744e81Swyllys 			keyfile = NULL;
97602744e81Swyllys 			/* Try odd ASN.1 variations */
97730a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
97802744e81Swyllys 			    &filedata);
97902744e81Swyllys 			if (rv == KMF_OK) {
98002744e81Swyllys 				(void) readAltFormatPrivateKey(&filedata,
98102744e81Swyllys 				    &pkey);
98230a5e8faSwyllys 				kmf_free_data(&filedata);
98302744e81Swyllys 			}
98402744e81Swyllys 		}
98502744e81Swyllys 	} else if (format == KMF_FORMAT_PEM ||
98602744e81Swyllys 	    format == KMF_FORMAT_PEM_KEYPAIR) {
98799ebb4caSwyllys 		pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
98802744e81Swyllys 		if (pkey == NULL) {
98902744e81Swyllys 			KMF_DATA derdata;
99002744e81Swyllys 			/*
99102744e81Swyllys 			 * Check if this is the alt. format
99202744e81Swyllys 			 * RSA private key file.
99302744e81Swyllys 			 */
99430a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
99502744e81Swyllys 			    &filedata);
99602744e81Swyllys 			if (rv == KMF_OK) {
99702744e81Swyllys 				uchar_t *d = NULL;
99802744e81Swyllys 				int len;
99930a5e8faSwyllys 				rv = kmf_pem_to_der(filedata.Data,
100002744e81Swyllys 				    filedata.Length, &d, &len);
100102744e81Swyllys 				if (rv == KMF_OK && d != NULL) {
100202744e81Swyllys 					derdata.Data = d;
100302744e81Swyllys 					derdata.Length = (size_t)len;
100402744e81Swyllys 					(void) readAltFormatPrivateKey(
100502744e81Swyllys 					    &derdata, &pkey);
100602744e81Swyllys 					free(d);
100702744e81Swyllys 				}
100830a5e8faSwyllys 				kmf_free_data(&filedata);
100902744e81Swyllys 			}
101002744e81Swyllys 		}
101102744e81Swyllys 	}
101299ebb4caSwyllys 
101399ebb4caSwyllys end:
101499ebb4caSwyllys 	if (pkey == NULL)
101599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
101699ebb4caSwyllys 
101799ebb4caSwyllys 	if (keyfile != NULL)
101899ebb4caSwyllys 		(void) BIO_free(keyfile);
101999ebb4caSwyllys 
102099ebb4caSwyllys 	return (pkey);
102199ebb4caSwyllys }
102299ebb4caSwyllys 
102399ebb4caSwyllys KMF_RETURN
102430a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
102599ebb4caSwyllys {
102699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
102799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1028f482c776Swyllys 	int i, n;
1029f482c776Swyllys 	uint32_t maxcerts = 0;
103030a5e8faSwyllys 	uint32_t *num_certs;
103130a5e8faSwyllys 	KMF_X509_DER_CERT *kmf_cert = NULL;
103230a5e8faSwyllys 	char *dirpath = NULL;
103330a5e8faSwyllys 	char *filename = NULL;
103430a5e8faSwyllys 	char *fullpath = NULL;
103530a5e8faSwyllys 	char *issuer = NULL;
103630a5e8faSwyllys 	char *subject = NULL;
103730a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
103830a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
103999ebb4caSwyllys 
104030a5e8faSwyllys 	num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
104130a5e8faSwyllys 	if (num_certs == NULL)
104299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
104399ebb4caSwyllys 
104430a5e8faSwyllys 	/* num_certs should reference the size of kmf_cert */
1045f482c776Swyllys 	maxcerts = *num_certs;
1046f482c776Swyllys 	if (maxcerts == 0)
1047f482c776Swyllys 		maxcerts = 0xFFFFFFFF;
104899ebb4caSwyllys 	*num_certs = 0;
104999ebb4caSwyllys 
105030a5e8faSwyllys 	/* Get the optional returned certificate list  */
105130a5e8faSwyllys 	kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
105230a5e8faSwyllys 	    numattr);
105399ebb4caSwyllys 
105430a5e8faSwyllys 	/*
105530a5e8faSwyllys 	 * The dirpath attribute and the filename attribute can not be NULL
105630a5e8faSwyllys 	 * at the same time.
105730a5e8faSwyllys 	 */
105830a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
105930a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
106030a5e8faSwyllys 	    numattr);
106130a5e8faSwyllys 
106230a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
106399ebb4caSwyllys 	if (fullpath == NULL)
106499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
106599ebb4caSwyllys 
106630a5e8faSwyllys 	/* Get optional search criteria attributes */
106730a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
106830a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
106930a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
107030a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
107130a5e8faSwyllys 	    &validity, NULL);
107230a5e8faSwyllys 	if (rv != KMF_OK) {
107330a5e8faSwyllys 		validity = KMF_ALL_CERTS;
107430a5e8faSwyllys 		rv = KMF_OK;
107530a5e8faSwyllys 	}
107630a5e8faSwyllys 
107799ebb4caSwyllys 	if (isdir(fullpath)) {
107899ebb4caSwyllys 		DIR *dirp;
107999ebb4caSwyllys 		struct dirent *dp;
108099ebb4caSwyllys 
1081f482c776Swyllys 		n = 0;
108299ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
108399ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
108499ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
108599ebb4caSwyllys 		}
108699ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
108799ebb4caSwyllys 			char *fname;
108871593db2Swyllys 			KMF_DATA *certlist = NULL;
1089f482c776Swyllys 			uint32_t loaded_certs = 0;
109071593db2Swyllys 
109199ebb4caSwyllys 			if (strcmp(dp->d_name, ".") == 0 ||
109299ebb4caSwyllys 			    strcmp(dp->d_name, "..") == 0)
109399ebb4caSwyllys 				continue;
109499ebb4caSwyllys 
109534acef67Swyllys 			fname = get_fullpath(fullpath, (char *)&dp->d_name);
109699ebb4caSwyllys 
109730a5e8faSwyllys 			rv = load_certs(kmfh, issuer, subject, serial,
109830a5e8faSwyllys 			    validity, fname, &certlist,	&loaded_certs);
109999ebb4caSwyllys 
110099ebb4caSwyllys 			if (rv != KMF_OK) {
110199ebb4caSwyllys 				free(fname);
110271593db2Swyllys 				if (certlist != NULL) {
1103f482c776Swyllys 					for (i = 0; i < loaded_certs; i++)
110430a5e8faSwyllys 						kmf_free_data(&certlist[i]);
110571593db2Swyllys 					free(certlist);
110671593db2Swyllys 				}
110799ebb4caSwyllys 				continue;
110899ebb4caSwyllys 			}
110999ebb4caSwyllys 
111099ebb4caSwyllys 			/* If load succeeds, add certdata to the list */
111199ebb4caSwyllys 			if (kmf_cert != NULL) {
1112f482c776Swyllys 				for (i = 0; i < loaded_certs &&
1113b4058258Swyllys 				    n < maxcerts; i++) {
111471593db2Swyllys 					kmf_cert[n].certificate.Data =
111571593db2Swyllys 					    certlist[i].Data;
111699ebb4caSwyllys 					kmf_cert[n].certificate.Length =
111771593db2Swyllys 					    certlist[i].Length;
111899ebb4caSwyllys 
111999ebb4caSwyllys 					kmf_cert[n].kmf_private.keystore_type =
112099ebb4caSwyllys 					    KMF_KEYSTORE_OPENSSL;
112199ebb4caSwyllys 					kmf_cert[n].kmf_private.flags =
112299ebb4caSwyllys 					    KMF_FLAG_CERT_VALID;
112371593db2Swyllys 					kmf_cert[n].kmf_private.label =
112471593db2Swyllys 					    strdup(fname);
112599ebb4caSwyllys 					n++;
112699ebb4caSwyllys 				}
1127b4058258Swyllys 				/*
1128b4058258Swyllys 				 * If maxcerts < loaded_certs, clean up the
1129b4058258Swyllys 				 * certs that were not used.
1130b4058258Swyllys 				 */
1131f482c776Swyllys 				for (; i < loaded_certs; i++)
113230a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1133f482c776Swyllys 			} else {
1134f482c776Swyllys 				for (i = 0; i < loaded_certs; i++)
113530a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1136f482c776Swyllys 				n += loaded_certs;
113771593db2Swyllys 			}
1138f482c776Swyllys 			free(certlist);
113971593db2Swyllys 			free(fname);
114071593db2Swyllys 		}
114199ebb4caSwyllys 		(*num_certs) = n;
114299ebb4caSwyllys 		if (*num_certs == 0)
114399ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
114430a5e8faSwyllys 		if (*num_certs > 0)
114599ebb4caSwyllys 			rv = KMF_OK;
114699ebb4caSwyllys exit:
114799ebb4caSwyllys 		(void) closedir(dirp);
114899ebb4caSwyllys 	} else {
114971593db2Swyllys 		KMF_DATA *certlist = NULL;
1150f482c776Swyllys 		uint32_t loaded_certs = 0;
115171593db2Swyllys 
115230a5e8faSwyllys 		rv = load_certs(kmfh, issuer, subject, serial, validity,
115330a5e8faSwyllys 		    fullpath, &certlist, &loaded_certs);
115499ebb4caSwyllys 		if (rv != KMF_OK) {
115599ebb4caSwyllys 			free(fullpath);
115699ebb4caSwyllys 			return (rv);
115799ebb4caSwyllys 		}
115899ebb4caSwyllys 
1159f482c776Swyllys 		n = 0;
116071593db2Swyllys 		if (kmf_cert != NULL && certlist != NULL) {
1161f482c776Swyllys 			for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1162f482c776Swyllys 				kmf_cert[n].certificate.Data =
116371593db2Swyllys 				    certlist[i].Data;
1164f482c776Swyllys 				kmf_cert[n].certificate.Length =
116571593db2Swyllys 				    certlist[i].Length;
1166f482c776Swyllys 				kmf_cert[n].kmf_private.keystore_type =
116799ebb4caSwyllys 				    KMF_KEYSTORE_OPENSSL;
1168f482c776Swyllys 				kmf_cert[n].kmf_private.flags =
116971593db2Swyllys 				    KMF_FLAG_CERT_VALID;
1170f482c776Swyllys 				kmf_cert[n].kmf_private.label =
117171593db2Swyllys 				    strdup(fullpath);
1172f482c776Swyllys 				n++;
117371593db2Swyllys 			}
1174f482c776Swyllys 			/* If maxcerts < loaded_certs, clean up */
1175f482c776Swyllys 			for (; i < loaded_certs; i++)
117630a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1177f482c776Swyllys 		} else if (certlist != NULL) {
1178f482c776Swyllys 			for (i = 0; i < loaded_certs; i++)
117930a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1180f482c776Swyllys 			n = loaded_certs;
1181f482c776Swyllys 		}
118230a5e8faSwyllys 		if (certlist != NULL)
118371593db2Swyllys 			free(certlist);
1184f482c776Swyllys 		*num_certs = n;
118599ebb4caSwyllys 	}
118699ebb4caSwyllys 
118799ebb4caSwyllys 	free(fullpath);
118899ebb4caSwyllys 
118999ebb4caSwyllys 	return (rv);
119099ebb4caSwyllys }
119199ebb4caSwyllys 
119299ebb4caSwyllys void
119399ebb4caSwyllys /*ARGSUSED*/
119499ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
119599ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert)
119699ebb4caSwyllys {
119799ebb4caSwyllys 	if (kmf_cert != NULL) {
119899ebb4caSwyllys 		if (kmf_cert->certificate.Data != NULL) {
1199*e65e5c2dSWyllys Ingersoll 			kmf_free_data(&kmf_cert->certificate);
120099ebb4caSwyllys 		}
120199ebb4caSwyllys 		if (kmf_cert->kmf_private.label)
120299ebb4caSwyllys 			free(kmf_cert->kmf_private.label);
120399ebb4caSwyllys 	}
120499ebb4caSwyllys }
120599ebb4caSwyllys 
120630a5e8faSwyllys /*ARGSUSED*/
120799ebb4caSwyllys KMF_RETURN
120830a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
120999ebb4caSwyllys {
121099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
121130a5e8faSwyllys 	KMF_DATA *cert = NULL;
121230a5e8faSwyllys 	char *outfilename = NULL;
121330a5e8faSwyllys 	char *dirpath = NULL;
121430a5e8faSwyllys 	char *fullpath = NULL;
121599ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
121699ebb4caSwyllys 
121730a5e8faSwyllys 	/* Get the cert data */
121830a5e8faSwyllys 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
121930a5e8faSwyllys 	if (cert == NULL || cert->Data == NULL)
122099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
122199ebb4caSwyllys 
122230a5e8faSwyllys 	/* Check the output filename and directory attributes. */
122330a5e8faSwyllys 	outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
122430a5e8faSwyllys 	    numattr);
122530a5e8faSwyllys 	if (outfilename == NULL)
122630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
122799ebb4caSwyllys 
122830a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
122930a5e8faSwyllys 	fullpath = get_fullpath(dirpath, outfilename);
123099ebb4caSwyllys 	if (fullpath == NULL)
123130a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
123299ebb4caSwyllys 
123330a5e8faSwyllys 	/* Check the optional format attribute */
123430a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
123530a5e8faSwyllys 	    &format, NULL);
123630a5e8faSwyllys 	if (ret != KMF_OK) {
123730a5e8faSwyllys 		/* If there is no format attribute, then default to PEM */
123830a5e8faSwyllys 		format = KMF_FORMAT_PEM;
123999ebb4caSwyllys 		ret = KMF_OK;
124030a5e8faSwyllys 	} else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
124130a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
124299ebb4caSwyllys 		goto out;
124399ebb4caSwyllys 	}
124499ebb4caSwyllys 
124530a5e8faSwyllys 	/* Store the certificate in the file with the specified format */
124630a5e8faSwyllys 	ret = kmf_create_cert_file(cert, format, fullpath);
124799ebb4caSwyllys 
124899ebb4caSwyllys out:
124999ebb4caSwyllys 	if (fullpath != NULL)
125099ebb4caSwyllys 		free(fullpath);
125199ebb4caSwyllys 
125299ebb4caSwyllys 	return (ret);
125399ebb4caSwyllys }
125499ebb4caSwyllys 
125530a5e8faSwyllys 
125699ebb4caSwyllys KMF_RETURN
125730a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
125899ebb4caSwyllys {
125999ebb4caSwyllys 	KMF_RETURN rv;
126099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
126199ebb4caSwyllys 	KMF_DATA certdata = {NULL, 0};
126230a5e8faSwyllys 	char *dirpath = NULL;
126330a5e8faSwyllys 	char *filename = NULL;
126430a5e8faSwyllys 	char *fullpath = NULL;
126530a5e8faSwyllys 	char *issuer = NULL;
126630a5e8faSwyllys 	char *subject = NULL;
126730a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
126830a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
126999ebb4caSwyllys 
127030a5e8faSwyllys 	/*
127130a5e8faSwyllys 	 * Get the DIRPATH and CERT_FILENAME attributes.  They can not be
127230a5e8faSwyllys 	 * NULL at the same time.
127330a5e8faSwyllys 	 */
127430a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
127530a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
127630a5e8faSwyllys 	    numattr);
127730a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
127899ebb4caSwyllys 	if (fullpath == NULL)
127999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
128099ebb4caSwyllys 
128130a5e8faSwyllys 	/* Get optional search criteria attributes */
128230a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
128330a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
128430a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
128530a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
128630a5e8faSwyllys 	    &validity, NULL);
128730a5e8faSwyllys 	if (rv != KMF_OK) {
128830a5e8faSwyllys 		validity = KMF_ALL_CERTS;
128930a5e8faSwyllys 		rv = KMF_OK;
129030a5e8faSwyllys 	}
129130a5e8faSwyllys 
129299ebb4caSwyllys 	if (isdir(fullpath)) {
129399ebb4caSwyllys 		DIR *dirp;
129499ebb4caSwyllys 		struct dirent *dp;
129599ebb4caSwyllys 
129699ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
129799ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
129899ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
129999ebb4caSwyllys 		}
130099ebb4caSwyllys 
130199ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
130299ebb4caSwyllys 			if (strcmp(dp->d_name, ".") != 0 &&
130399ebb4caSwyllys 			    strcmp(dp->d_name, "..") != 0) {
130499ebb4caSwyllys 				char *fname;
130599ebb4caSwyllys 
130699ebb4caSwyllys 				fname = get_fullpath(fullpath,
130799ebb4caSwyllys 				    (char *)&dp->d_name);
130899ebb4caSwyllys 
130999ebb4caSwyllys 				if (fname == NULL) {
131099ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
131199ebb4caSwyllys 					break;
131299ebb4caSwyllys 				}
131399ebb4caSwyllys 
131430a5e8faSwyllys 				rv = kmf_load_cert(kmfh, issuer, subject,
131530a5e8faSwyllys 				    serial, validity, fname, &certdata);
131699ebb4caSwyllys 
131799ebb4caSwyllys 				if (rv == KMF_ERR_CERT_NOT_FOUND) {
131899ebb4caSwyllys 					free(fname);
1319*e65e5c2dSWyllys Ingersoll 					kmf_free_data(&certdata);
132099ebb4caSwyllys 					rv = KMF_OK;
132199ebb4caSwyllys 					continue;
132299ebb4caSwyllys 				} else if (rv != KMF_OK) {
132399ebb4caSwyllys 					free(fname);
132499ebb4caSwyllys 					break;
132599ebb4caSwyllys 				}
132699ebb4caSwyllys 
132799ebb4caSwyllys 				if (unlink(fname) != 0) {
132899ebb4caSwyllys 					SET_SYS_ERROR(kmfh, errno);
132999ebb4caSwyllys 					rv = KMF_ERR_INTERNAL;
133099ebb4caSwyllys 					free(fname);
133199ebb4caSwyllys 					break;
133299ebb4caSwyllys 				}
133399ebb4caSwyllys 				free(fname);
1334*e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certdata);
133599ebb4caSwyllys 			}
133699ebb4caSwyllys 		}
133799ebb4caSwyllys 		(void) closedir(dirp);
133899ebb4caSwyllys 	} else {
133999ebb4caSwyllys 		/* Just try to load a single certificate */
134030a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
134130a5e8faSwyllys 		    fullpath, &certdata);
134299ebb4caSwyllys 		if (rv == KMF_OK) {
134399ebb4caSwyllys 			if (unlink(fullpath) != 0) {
134499ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
134599ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
134699ebb4caSwyllys 			}
134799ebb4caSwyllys 		}
134899ebb4caSwyllys 	}
134999ebb4caSwyllys 
135099ebb4caSwyllys out:
135199ebb4caSwyllys 	if (fullpath != NULL)
135299ebb4caSwyllys 		free(fullpath);
135399ebb4caSwyllys 
1354*e65e5c2dSWyllys Ingersoll 	kmf_free_data(&certdata);
135599ebb4caSwyllys 
135699ebb4caSwyllys 	return (rv);
135799ebb4caSwyllys }
135899ebb4caSwyllys 
135999ebb4caSwyllys KMF_RETURN
136099ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
136199ebb4caSwyllys 	KMF_DATA *keydata)
136299ebb4caSwyllys {
136399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
136499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
136599ebb4caSwyllys 	int n;
136699ebb4caSwyllys 
136799ebb4caSwyllys 	if (key == NULL || keydata == NULL ||
136899ebb4caSwyllys 	    key->keyp == NULL)
136999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
137099ebb4caSwyllys 
137199ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
137299ebb4caSwyllys 		RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
137399ebb4caSwyllys 
137499ebb4caSwyllys 		if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
137599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
137699ebb4caSwyllys 			return (KMF_ERR_ENCODING);
137799ebb4caSwyllys 		}
137899ebb4caSwyllys 		RSA_free(pubkey);
137999ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
138099ebb4caSwyllys 		DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
138199ebb4caSwyllys 
138299ebb4caSwyllys 		if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
138399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
138499ebb4caSwyllys 			return (KMF_ERR_ENCODING);
138599ebb4caSwyllys 		}
138699ebb4caSwyllys 		DSA_free(pubkey);
138799ebb4caSwyllys 	} else {
138899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
138999ebb4caSwyllys 	}
139099ebb4caSwyllys 	keydata->Length = n;
139199ebb4caSwyllys 
139299ebb4caSwyllys cleanup:
139399ebb4caSwyllys 	if (rv != KMF_OK) {
139499ebb4caSwyllys 		if (keydata->Data)
139599ebb4caSwyllys 			free(keydata->Data);
139699ebb4caSwyllys 		keydata->Data = NULL;
139799ebb4caSwyllys 		keydata->Length = 0;
139899ebb4caSwyllys 	}
139999ebb4caSwyllys 
140099ebb4caSwyllys 	return (rv);
140199ebb4caSwyllys }
140299ebb4caSwyllys 
140399ebb4caSwyllys static KMF_RETURN
140430a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
140530a5e8faSwyllys 	KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
140699ebb4caSwyllys {
140799ebb4caSwyllys 	int rv = 0;
140899ebb4caSwyllys 	RSA *rsa;
140999ebb4caSwyllys 	DSA *dsa;
141099ebb4caSwyllys 
14115b3e1433Swyllys 	if (pkey == NULL || out == NULL)
14125b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
14135b3e1433Swyllys 
141499ebb4caSwyllys 	switch (format) {
141573cc0e02Swyllys 		case KMF_FORMAT_RAWKEY:
141673cc0e02Swyllys 			/* same as ASN.1 */
141799ebb4caSwyllys 		case KMF_FORMAT_ASN1:
141899ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
141999ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
142030a5e8faSwyllys 				if (private)
142199ebb4caSwyllys 					rv = i2d_RSAPrivateKey_bio(out, rsa);
142230a5e8faSwyllys 				else
142330a5e8faSwyllys 					rv = i2d_RSAPublicKey_bio(out, rsa);
142499ebb4caSwyllys 				RSA_free(rsa);
142599ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
142699ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
142799ebb4caSwyllys 				rv = i2d_DSAPrivateKey_bio(out, dsa);
142899ebb4caSwyllys 				DSA_free(dsa);
142999ebb4caSwyllys 			}
143099ebb4caSwyllys 			if (rv == 1) {
143199ebb4caSwyllys 				rv = KMF_OK;
143299ebb4caSwyllys 			} else {
143399ebb4caSwyllys 				SET_ERROR(kmfh, rv);
143499ebb4caSwyllys 			}
143599ebb4caSwyllys 			break;
143699ebb4caSwyllys 		case KMF_FORMAT_PEM:
143799ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
143899ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
143930a5e8faSwyllys 				if (private)
144099ebb4caSwyllys 					rv = PEM_write_bio_RSAPrivateKey(out,
144130a5e8faSwyllys 					    rsa, NULL, NULL, 0, NULL,
144230a5e8faSwyllys 					    (cred != NULL ? cred->cred : NULL));
144330a5e8faSwyllys 				else
144430a5e8faSwyllys 					rv = PEM_write_bio_RSAPublicKey(out,
144530a5e8faSwyllys 					    rsa);
144699ebb4caSwyllys 				RSA_free(rsa);
144799ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
144899ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
144999ebb4caSwyllys 				rv = PEM_write_bio_DSAPrivateKey(out,
145030a5e8faSwyllys 				    dsa, NULL, NULL, 0, NULL,
145130a5e8faSwyllys 				    (cred != NULL ? cred->cred : NULL));
145299ebb4caSwyllys 				DSA_free(dsa);
145399ebb4caSwyllys 			}
145499ebb4caSwyllys 
145599ebb4caSwyllys 			if (rv == 1) {
145699ebb4caSwyllys 				rv = KMF_OK;
145799ebb4caSwyllys 			} else {
145899ebb4caSwyllys 				SET_ERROR(kmfh, rv);
145999ebb4caSwyllys 			}
146099ebb4caSwyllys 			break;
146199ebb4caSwyllys 
146299ebb4caSwyllys 		default:
146399ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
146499ebb4caSwyllys 	}
146599ebb4caSwyllys 
146699ebb4caSwyllys 	return (rv);
146799ebb4caSwyllys }
146899ebb4caSwyllys 
146999ebb4caSwyllys KMF_RETURN
147030a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
147130a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
147299ebb4caSwyllys {
147399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
147499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
147599ebb4caSwyllys 	uint32_t eValue = 0x010001;
147699ebb4caSwyllys 	RSA *sslPrivKey = NULL;
147799ebb4caSwyllys 	DSA *sslDSAKey = NULL;
147899ebb4caSwyllys 	EVP_PKEY *eprikey = NULL;
147999ebb4caSwyllys 	EVP_PKEY *epubkey = NULL;
148099ebb4caSwyllys 	BIO *out = NULL;
148130a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
148230a5e8faSwyllys 	uint32_t keylen = 1024;
148330a5e8faSwyllys 	uint32_t keylen_size = sizeof (uint32_t);
148430a5e8faSwyllys 	boolean_t storekey = TRUE;
148530a5e8faSwyllys 	KMF_KEY_ALG keytype = KMF_RSA;
148699ebb4caSwyllys 
148730a5e8faSwyllys 	rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
148830a5e8faSwyllys 	    &storekey, NULL);
148930a5e8faSwyllys 	if (rv != KMF_OK) {
149030a5e8faSwyllys 		/* "storekey" is optional. Default is TRUE */
149130a5e8faSwyllys 		rv = KMF_OK;
149299ebb4caSwyllys 	}
149399ebb4caSwyllys 
149430a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
149530a5e8faSwyllys 	    (void *)&keytype, NULL);
149630a5e8faSwyllys 	if (rv != KMF_OK)
149730a5e8faSwyllys 		/* keytype is optional.  KMF_RSA is default */
149830a5e8faSwyllys 		rv = KMF_OK;
149999ebb4caSwyllys 
150030a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
150130a5e8faSwyllys 	if (pubkey == NULL)
150299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
150399ebb4caSwyllys 
150430a5e8faSwyllys 	privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
150530a5e8faSwyllys 	if (privkey == NULL)
150630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
150730a5e8faSwyllys 
150830a5e8faSwyllys 	(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
150930a5e8faSwyllys 	(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
151099ebb4caSwyllys 
151199ebb4caSwyllys 	eprikey = EVP_PKEY_new();
151299ebb4caSwyllys 	if (eprikey == NULL) {
151399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
151499ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
151599ebb4caSwyllys 		goto cleanup;
151699ebb4caSwyllys 	}
151799ebb4caSwyllys 	epubkey = EVP_PKEY_new();
151899ebb4caSwyllys 	if (epubkey == NULL) {
151999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
152099ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
152199ebb4caSwyllys 		goto cleanup;
152299ebb4caSwyllys 	}
152330a5e8faSwyllys 	if (keytype == KMF_RSA) {
152430a5e8faSwyllys 		KMF_BIGINT *rsaexp = NULL;
152599ebb4caSwyllys 
152630a5e8faSwyllys 		rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
152730a5e8faSwyllys 		if (rsaexp != NULL) {
152830a5e8faSwyllys 			if (rsaexp->len > 0 &&
152930a5e8faSwyllys 			    rsaexp->len <= sizeof (eValue) &&
153030a5e8faSwyllys 			    rsaexp->val != NULL) {
1531a2d4930dSDan OpenSolaris Anderson 				/* LINTED E_BAD_PTR_CAST_ALIGN */
153230a5e8faSwyllys 				eValue = *(uint32_t *)rsaexp->val;
153330a5e8faSwyllys 			} else {
153430a5e8faSwyllys 				rv = KMF_ERR_BAD_PARAMETER;
153530a5e8faSwyllys 				goto cleanup;
153630a5e8faSwyllys 			}
153730a5e8faSwyllys 		} else {
153830a5e8faSwyllys 			/* RSA Exponent is optional. Default is 0x10001 */
153930a5e8faSwyllys 			rv = KMF_OK;
154030a5e8faSwyllys 		}
154130a5e8faSwyllys 
154230a5e8faSwyllys 		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
154330a5e8faSwyllys 		    &keylen, &keylen_size);
154430a5e8faSwyllys 		if (rv == KMF_ERR_ATTR_NOT_FOUND)
154530a5e8faSwyllys 			/* keylen is optional, default is 1024 */
154630a5e8faSwyllys 			rv = KMF_OK;
154730a5e8faSwyllys 		if (rv != KMF_OK) {
154830a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
154930a5e8faSwyllys 			goto cleanup;
155030a5e8faSwyllys 		}
155130a5e8faSwyllys 
155230a5e8faSwyllys 		sslPrivKey = RSA_generate_key(keylen, eValue, NULL, NULL);
155399ebb4caSwyllys 		if (sslPrivKey == NULL) {
155499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
155599ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
155699ebb4caSwyllys 		} else {
155730a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
155899ebb4caSwyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
155999ebb4caSwyllys 			privkey->keyalg = KMF_RSA;
156099ebb4caSwyllys 			privkey->keyclass = KMF_ASYM_PRI;
156199ebb4caSwyllys 			privkey->israw = FALSE;
156299ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
156330a5e8faSwyllys 
156499ebb4caSwyllys 			/* OpenSSL derives the public key from the private */
156530a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
156699ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
156799ebb4caSwyllys 			pubkey->keyalg = KMF_RSA;
156899ebb4caSwyllys 			pubkey->israw = FALSE;
156999ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
157099ebb4caSwyllys 			pubkey->keyp = (void *)epubkey;
157199ebb4caSwyllys 		}
157230a5e8faSwyllys 	} else if (keytype == KMF_DSA) {
157330a5e8faSwyllys 		DSA *dp;
157499ebb4caSwyllys 		sslDSAKey = DSA_new();
157599ebb4caSwyllys 		if (sslDSAKey == NULL) {
157699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
157799ebb4caSwyllys 			return (KMF_ERR_MEMORY);
157899ebb4caSwyllys 		}
157999ebb4caSwyllys 
158099ebb4caSwyllys 		if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) ==
158199ebb4caSwyllys 		    NULL) {
158299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
158399ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
158499ebb4caSwyllys 			goto cleanup;
158599ebb4caSwyllys 		}
158699ebb4caSwyllys 		if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) ==
158799ebb4caSwyllys 		    NULL) {
158899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
158999ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
159099ebb4caSwyllys 			goto cleanup;
159199ebb4caSwyllys 		}
159299ebb4caSwyllys 		if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) ==
159399ebb4caSwyllys 		    NULL) {
159499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
159599ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
159699ebb4caSwyllys 			goto cleanup;
159799ebb4caSwyllys 		}
159899ebb4caSwyllys 
159999ebb4caSwyllys 		if (!DSA_generate_key(sslDSAKey)) {
160099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
160199ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
160299ebb4caSwyllys 			goto cleanup;
160399ebb4caSwyllys 		}
160499ebb4caSwyllys 
160599ebb4caSwyllys 		privkey->kstype = KMF_KEYSTORE_OPENSSL;
160699ebb4caSwyllys 		privkey->keyalg = KMF_DSA;
160799ebb4caSwyllys 		privkey->keyclass = KMF_ASYM_PRI;
160899ebb4caSwyllys 		privkey->israw = FALSE;
160999ebb4caSwyllys 		if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
161099ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
161199ebb4caSwyllys 		} else {
161299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
161399ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
161499ebb4caSwyllys 			goto cleanup;
161599ebb4caSwyllys 		}
161630a5e8faSwyllys 		dp = DSA_new();
161799ebb4caSwyllys 		/* Make a copy for the public key */
161899ebb4caSwyllys 		if (dp != NULL) {
161999ebb4caSwyllys 			if ((dp->p = BN_new()) == NULL) {
162099ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
162199ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
162299ebb4caSwyllys 				DSA_free(dp);
162399ebb4caSwyllys 				goto cleanup;
162499ebb4caSwyllys 			}
162599ebb4caSwyllys 			if ((dp->q = BN_new()) == NULL) {
162699ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
162799ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
162899ebb4caSwyllys 				BN_free(dp->p);
162999ebb4caSwyllys 				DSA_free(dp);
163099ebb4caSwyllys 				goto cleanup;
163199ebb4caSwyllys 			}
163299ebb4caSwyllys 			if ((dp->g = BN_new()) == NULL) {
163399ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
163499ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
163599ebb4caSwyllys 				BN_free(dp->q);
163699ebb4caSwyllys 				BN_free(dp->p);
163799ebb4caSwyllys 				DSA_free(dp);
163899ebb4caSwyllys 				goto cleanup;
163999ebb4caSwyllys 			}
164099ebb4caSwyllys 			if ((dp->pub_key = BN_new()) == NULL) {
164199ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
164299ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
164399ebb4caSwyllys 				BN_free(dp->q);
164499ebb4caSwyllys 				BN_free(dp->p);
164599ebb4caSwyllys 				BN_free(dp->g);
164699ebb4caSwyllys 				DSA_free(dp);
164799ebb4caSwyllys 				goto cleanup;
164899ebb4caSwyllys 			}
164999ebb4caSwyllys 			(void) BN_copy(dp->p, sslDSAKey->p);
165099ebb4caSwyllys 			(void) BN_copy(dp->q, sslDSAKey->q);
165199ebb4caSwyllys 			(void) BN_copy(dp->g, sslDSAKey->g);
165299ebb4caSwyllys 			(void) BN_copy(dp->pub_key, sslDSAKey->pub_key);
165399ebb4caSwyllys 
165499ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
165599ebb4caSwyllys 			pubkey->keyalg = KMF_DSA;
165699ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
165799ebb4caSwyllys 			pubkey->israw = FALSE;
165899ebb4caSwyllys 
165999ebb4caSwyllys 			if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
166099ebb4caSwyllys 				pubkey->keyp = (void *)epubkey;
166199ebb4caSwyllys 			} else {
166299ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
166399ebb4caSwyllys 				rv = KMF_ERR_KEYGEN_FAILED;
166499ebb4caSwyllys 				goto cleanup;
166599ebb4caSwyllys 			}
166699ebb4caSwyllys 		}
166799ebb4caSwyllys 	}
166899ebb4caSwyllys 
166999ebb4caSwyllys 	if (rv != KMF_OK) {
167099ebb4caSwyllys 		goto cleanup;
167199ebb4caSwyllys 	}
167299ebb4caSwyllys 
167330a5e8faSwyllys 	if (storekey) {
167430a5e8faSwyllys 		KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
167530a5e8faSwyllys 		int i = 0;
167630a5e8faSwyllys 		char *keyfile = NULL, *dirpath = NULL;
167730a5e8faSwyllys 		KMF_ENCODE_FORMAT format;
167830a5e8faSwyllys 		/*
167930a5e8faSwyllys 		 * Construct a new attribute arrray and call openssl_store_key
168030a5e8faSwyllys 		 */
168130a5e8faSwyllys 		kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
168230a5e8faSwyllys 		    privkey, sizeof (privkey));
168330a5e8faSwyllys 		i++;
168430a5e8faSwyllys 
168530a5e8faSwyllys 		dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
168630a5e8faSwyllys 		if (dirpath != NULL) {
168730a5e8faSwyllys 			storeattrs[i].type = KMF_DIRPATH_ATTR;
168830a5e8faSwyllys 			storeattrs[i].pValue = dirpath;
168930a5e8faSwyllys 			storeattrs[i].valueLen = strlen(dirpath);
169030a5e8faSwyllys 			i++;
169130a5e8faSwyllys 		} else {
169230a5e8faSwyllys 			rv = KMF_OK; /* DIRPATH is optional */
169399ebb4caSwyllys 		}
169430a5e8faSwyllys 		keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
169530a5e8faSwyllys 		    attrlist, numattr);
169630a5e8faSwyllys 		if (keyfile != NULL) {
169730a5e8faSwyllys 			storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
169830a5e8faSwyllys 			storeattrs[i].pValue = keyfile;
169930a5e8faSwyllys 			storeattrs[i].valueLen = strlen(keyfile);
170030a5e8faSwyllys 			i++;
170130a5e8faSwyllys 		} else {
170230a5e8faSwyllys 			goto cleanup; /* KEYFILE is required */
170330a5e8faSwyllys 		}
170430a5e8faSwyllys 		rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
170530a5e8faSwyllys 		    (void *)&format, NULL);
170630a5e8faSwyllys 		if (rv == KMF_OK) {
170730a5e8faSwyllys 			storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
170830a5e8faSwyllys 			storeattrs[i].pValue = &format;
170930a5e8faSwyllys 			storeattrs[i].valueLen = sizeof (format);
171030a5e8faSwyllys 			i++;
171130a5e8faSwyllys 		}
171230a5e8faSwyllys 
171330a5e8faSwyllys 		rv = OpenSSL_StoreKey(handle, i, storeattrs);
171430a5e8faSwyllys 	}
171599ebb4caSwyllys 
171699ebb4caSwyllys cleanup:
171799ebb4caSwyllys 	if (rv != KMF_OK) {
171899ebb4caSwyllys 		if (eprikey != NULL)
171999ebb4caSwyllys 			EVP_PKEY_free(eprikey);
172099ebb4caSwyllys 
172199ebb4caSwyllys 		if (epubkey != NULL)
172299ebb4caSwyllys 			EVP_PKEY_free(epubkey);
172399ebb4caSwyllys 
172499ebb4caSwyllys 		if (pubkey->keylabel) {
172599ebb4caSwyllys 			free(pubkey->keylabel);
172699ebb4caSwyllys 			pubkey->keylabel = NULL;
172799ebb4caSwyllys 		}
172899ebb4caSwyllys 
172999ebb4caSwyllys 		if (privkey->keylabel) {
173099ebb4caSwyllys 			free(privkey->keylabel);
173199ebb4caSwyllys 			privkey->keylabel = NULL;
173299ebb4caSwyllys 		}
173399ebb4caSwyllys 
173499ebb4caSwyllys 		pubkey->keyp = NULL;
173599ebb4caSwyllys 		privkey->keyp = NULL;
173699ebb4caSwyllys 	}
173799ebb4caSwyllys 
173899ebb4caSwyllys 	if (sslPrivKey)
173999ebb4caSwyllys 		RSA_free(sslPrivKey);
174099ebb4caSwyllys 
174199ebb4caSwyllys 	if (sslDSAKey)
174299ebb4caSwyllys 		DSA_free(sslDSAKey);
174399ebb4caSwyllys 
174499ebb4caSwyllys 	if (out != NULL)
174599ebb4caSwyllys 		(void) BIO_free(out);
174699ebb4caSwyllys 
174799ebb4caSwyllys 	return (rv);
174899ebb4caSwyllys }
174999ebb4caSwyllys 
1750*e65e5c2dSWyllys Ingersoll /*
1751*e65e5c2dSWyllys Ingersoll  * Make sure the BN conversion is properly padded with 0x00
1752*e65e5c2dSWyllys Ingersoll  * bytes.  If not, signature verification for DSA signatures
1753*e65e5c2dSWyllys Ingersoll  * may fail in the case where the bignum value does not use
1754*e65e5c2dSWyllys Ingersoll  * all of the bits.
1755*e65e5c2dSWyllys Ingersoll  */
1756*e65e5c2dSWyllys Ingersoll static int
1757*e65e5c2dSWyllys Ingersoll fixbnlen(BIGNUM *bn, unsigned char *buf, int len) {
1758*e65e5c2dSWyllys Ingersoll 	int bytes = len - BN_num_bytes(bn);
1759*e65e5c2dSWyllys Ingersoll 	while (bytes-- > 0)
1760*e65e5c2dSWyllys Ingersoll 		*buf++ = 0;
1761*e65e5c2dSWyllys Ingersoll 
1762*e65e5c2dSWyllys Ingersoll 	return (BN_bn2bin(bn, buf));
1763*e65e5c2dSWyllys Ingersoll }
1764*e65e5c2dSWyllys Ingersoll 
176599ebb4caSwyllys KMF_RETURN
176699ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
176799ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
176899ebb4caSwyllys {
176999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
177099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
177199ebb4caSwyllys 	KMF_ALGORITHM_INDEX		AlgId;
177299ebb4caSwyllys 	EVP_MD_CTX ctx;
177399ebb4caSwyllys 	const EVP_MD *md;
177402744e81Swyllys 
177599ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
177699ebb4caSwyllys 	    tobesigned == NULL || output == NULL ||
177799ebb4caSwyllys 	    tobesigned->Data == NULL ||
177899ebb4caSwyllys 	    output->Data == NULL)
177999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
178099ebb4caSwyllys 
178199ebb4caSwyllys 	/* Map the OID to an OpenSSL algorithm */
178230a5e8faSwyllys 	AlgId = x509_algoid_to_algid(AlgOID);
178399ebb4caSwyllys 	if (AlgId == KMF_ALGID_NONE)
1784*e65e5c2dSWyllys Ingersoll 		return (KMF_ERR_BAD_ALGORITHM);
178599ebb4caSwyllys 
178699ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
178799ebb4caSwyllys 		EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
178899ebb4caSwyllys 		uchar_t *p;
178902744e81Swyllys 		int len;
179099ebb4caSwyllys 		if (AlgId == KMF_ALGID_MD5WithRSA)
179199ebb4caSwyllys 			md = EVP_md5();
179299ebb4caSwyllys 		else if (AlgId == KMF_ALGID_MD2WithRSA)
179399ebb4caSwyllys 			md = EVP_md2();
179499ebb4caSwyllys 		else if (AlgId == KMF_ALGID_SHA1WithRSA)
179599ebb4caSwyllys 			md = EVP_sha1();
1796*e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA256WithRSA)
1797*e65e5c2dSWyllys Ingersoll 			md = EVP_sha256();
1798*e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA384WithRSA)
1799*e65e5c2dSWyllys Ingersoll 			md = EVP_sha384();
1800*e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA512WithRSA)
1801*e65e5c2dSWyllys Ingersoll 			md = EVP_sha512();
180202744e81Swyllys 		else if (AlgId == KMF_ALGID_RSA)
180302744e81Swyllys 			md = NULL;
180499ebb4caSwyllys 		else
1805*e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_ALGORITHM);
180699ebb4caSwyllys 
180702744e81Swyllys 		if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
180802744e81Swyllys 			RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
180999ebb4caSwyllys 
181002744e81Swyllys 			p = output->Data;
181102744e81Swyllys 			if ((len = RSA_private_encrypt(tobesigned->Length,
181202744e81Swyllys 			    tobesigned->Data, p, rsa,
181302744e81Swyllys 			    RSA_PKCS1_PADDING)) <= 0) {
181402744e81Swyllys 				SET_ERROR(kmfh, ERR_get_error());
181502744e81Swyllys 				ret = KMF_ERR_INTERNAL;
181602744e81Swyllys 			}
181702744e81Swyllys 			output->Length = len;
181802744e81Swyllys 		} else {
181999ebb4caSwyllys 			(void) EVP_MD_CTX_init(&ctx);
182099ebb4caSwyllys 			(void) EVP_SignInit_ex(&ctx, md, NULL);
182199ebb4caSwyllys 			(void) EVP_SignUpdate(&ctx, tobesigned->Data,
182299ebb4caSwyllys 			    (uint32_t)tobesigned->Length);
182399ebb4caSwyllys 			len = (uint32_t)output->Length;
182499ebb4caSwyllys 			p = output->Data;
182502744e81Swyllys 			if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) {
182699ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
182702744e81Swyllys 				len = 0;
182802744e81Swyllys 				ret = KMF_ERR_INTERNAL;
182999ebb4caSwyllys 			}
183099ebb4caSwyllys 			output->Length = len;
183199ebb4caSwyllys 			(void) EVP_MD_CTX_cleanup(&ctx);
183202744e81Swyllys 		}
183399ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
183499ebb4caSwyllys 		DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
183599ebb4caSwyllys 
183699ebb4caSwyllys 		uchar_t hash[EVP_MAX_MD_SIZE];
183799ebb4caSwyllys 		uint32_t hashlen;
183899ebb4caSwyllys 		DSA_SIG *dsasig;
183999ebb4caSwyllys 
1840*e65e5c2dSWyllys Ingersoll 		if (AlgId == KMF_ALGID_DSA ||
1841*e65e5c2dSWyllys Ingersoll 		    AlgId == KMF_ALGID_SHA1WithDSA)
1842*e65e5c2dSWyllys Ingersoll 			md = EVP_sha1();
1843*e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA256WithDSA)
1844*e65e5c2dSWyllys Ingersoll 			md = EVP_sha256();
1845*e65e5c2dSWyllys Ingersoll 		else /* Bad algorithm */
1846*e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_ALGORITHM);
1847*e65e5c2dSWyllys Ingersoll 
184899ebb4caSwyllys 		/*
184999ebb4caSwyllys 		 * OpenSSL EVP_Sign operation automatically converts to
185099ebb4caSwyllys 		 * ASN.1 output so we do the operations separately so we
185199ebb4caSwyllys 		 * are assured of NOT getting ASN.1 output returned.
185299ebb4caSwyllys 		 * KMF does not want ASN.1 encoded results because
185399ebb4caSwyllys 		 * not all mechanisms return ASN.1 encodings (PKCS#11
185499ebb4caSwyllys 		 * and NSS return raw signature data).
185599ebb4caSwyllys 		 */
185699ebb4caSwyllys 		EVP_MD_CTX_init(&ctx);
185799ebb4caSwyllys 		(void) EVP_DigestInit_ex(&ctx, md, NULL);
185899ebb4caSwyllys 		(void) EVP_DigestUpdate(&ctx, tobesigned->Data,
185999ebb4caSwyllys 		    tobesigned->Length);
186099ebb4caSwyllys 		(void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
186199ebb4caSwyllys 
1862*e65e5c2dSWyllys Ingersoll 		/* Only sign first 20 bytes for SHA2 */
1863*e65e5c2dSWyllys Ingersoll 		if (AlgId == KMF_ALGID_SHA256WithDSA)
1864*e65e5c2dSWyllys Ingersoll 			hashlen = 20;
186599ebb4caSwyllys 		dsasig = DSA_do_sign(hash, hashlen, dsa);
186699ebb4caSwyllys 		if (dsasig != NULL) {
186799ebb4caSwyllys 			int i;
1868*e65e5c2dSWyllys Ingersoll 			output->Length = i = fixbnlen(dsasig->r, output->Data,
1869*e65e5c2dSWyllys Ingersoll 			    hashlen);
1870*e65e5c2dSWyllys Ingersoll 			output->Length += fixbnlen(dsasig->s, &output->Data[i],
1871*e65e5c2dSWyllys Ingersoll 			    hashlen);
187299ebb4caSwyllys 			DSA_SIG_free(dsasig);
187399ebb4caSwyllys 		} else {
187499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
187599ebb4caSwyllys 		}
1876*e65e5c2dSWyllys Ingersoll 		(void) EVP_MD_CTX_cleanup(&ctx);
187799ebb4caSwyllys 	} else {
187899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
187999ebb4caSwyllys 	}
188099ebb4caSwyllys cleanup:
188199ebb4caSwyllys 	return (ret);
188299ebb4caSwyllys }
188399ebb4caSwyllys 
188499ebb4caSwyllys KMF_RETURN
188599ebb4caSwyllys /*ARGSUSED*/
188630a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle,
188730a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
188899ebb4caSwyllys {
188999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
189030a5e8faSwyllys 	KMF_KEY_HANDLE *key;
189130a5e8faSwyllys 	boolean_t destroy = B_TRUE;
189230a5e8faSwyllys 
189330a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
189499ebb4caSwyllys 	if (key == NULL || key->keyp == NULL)
189599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
189699ebb4caSwyllys 
189730a5e8faSwyllys 	rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
189830a5e8faSwyllys 	    (void *)&destroy, NULL);
189930a5e8faSwyllys 	if (rv != KMF_OK) {
190030a5e8faSwyllys 		/* "destroy" is optional. Default is TRUE */
190130a5e8faSwyllys 		rv = KMF_OK;
190230a5e8faSwyllys 	}
190330a5e8faSwyllys 
190499ebb4caSwyllys 	if (key->keyclass != KMF_ASYM_PUB &&
190599ebb4caSwyllys 	    key->keyclass != KMF_ASYM_PRI &&
190699ebb4caSwyllys 	    key->keyclass != KMF_SYMMETRIC)
190799ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
190899ebb4caSwyllys 
190999ebb4caSwyllys 	if (key->keyclass == KMF_SYMMETRIC) {
191030a5e8faSwyllys 		kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
191199ebb4caSwyllys 		key->keyp = NULL;
191299ebb4caSwyllys 	} else {
191399ebb4caSwyllys 		if (key->keyp != NULL) {
191499ebb4caSwyllys 			EVP_PKEY_free(key->keyp);
191599ebb4caSwyllys 			key->keyp = NULL;
191699ebb4caSwyllys 		}
191799ebb4caSwyllys 	}
191899ebb4caSwyllys 
191999ebb4caSwyllys 	if (key->keylabel != NULL) {
192099ebb4caSwyllys 		EVP_PKEY *pkey = NULL;
192199ebb4caSwyllys 		/* If the file exists, make sure it is a proper key. */
192299ebb4caSwyllys 		pkey = openssl_load_key(handle, key->keylabel);
192399ebb4caSwyllys 		if (pkey == NULL) {
19245b3e1433Swyllys 			if (key->keylabel != NULL) {
192599ebb4caSwyllys 				free(key->keylabel);
192699ebb4caSwyllys 				key->keylabel = NULL;
19275b3e1433Swyllys 			}
192899ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
192999ebb4caSwyllys 		}
193099ebb4caSwyllys 		EVP_PKEY_free(pkey);
193199ebb4caSwyllys 
193299ebb4caSwyllys 		if (destroy) {
193399ebb4caSwyllys 			if (unlink(key->keylabel) != 0) {
193499ebb4caSwyllys 				KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
193599ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
193699ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
193799ebb4caSwyllys 			}
193899ebb4caSwyllys 		}
193999ebb4caSwyllys 		if (key->keylabel != NULL) {
194099ebb4caSwyllys 			free(key->keylabel);
194199ebb4caSwyllys 			key->keylabel = NULL;
194299ebb4caSwyllys 		}
194399ebb4caSwyllys 	}
194499ebb4caSwyllys 	return (rv);
194599ebb4caSwyllys }
194699ebb4caSwyllys 
194799ebb4caSwyllys KMF_RETURN
194899ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
194999ebb4caSwyllys {
195099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
195199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
195299ebb4caSwyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
195399ebb4caSwyllys 
195499ebb4caSwyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
195599ebb4caSwyllys 	if (strlen(str)) {
195699ebb4caSwyllys 		*msgstr = (char *)strdup(str);
195799ebb4caSwyllys 		if ((*msgstr) == NULL)
195899ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
195999ebb4caSwyllys 	} else {
196099ebb4caSwyllys 		*msgstr = NULL;
196199ebb4caSwyllys 	}
196299ebb4caSwyllys 
196399ebb4caSwyllys 	return (ret);
196499ebb4caSwyllys }
196599ebb4caSwyllys 
196699ebb4caSwyllys static int
196799ebb4caSwyllys ext2NID(int kmfext)
196899ebb4caSwyllys {
196999ebb4caSwyllys 	switch (kmfext) {
197099ebb4caSwyllys 		case KMF_X509_EXT_KEY_USAGE:
197199ebb4caSwyllys 			return (NID_key_usage);
197299ebb4caSwyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
197399ebb4caSwyllys 			return (NID_private_key_usage_period);
197499ebb4caSwyllys 		case KMF_X509_EXT_CERT_POLICIES:
197599ebb4caSwyllys 			return (NID_certificate_policies);
197699ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
197799ebb4caSwyllys 			return (NID_subject_alt_name);
197899ebb4caSwyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
197999ebb4caSwyllys 			return (NID_issuer_alt_name);
198099ebb4caSwyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
198199ebb4caSwyllys 			return (NID_basic_constraints);
198299ebb4caSwyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
198399ebb4caSwyllys 			return (NID_ext_key_usage);
198499ebb4caSwyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
198599ebb4caSwyllys 			return (NID_authority_key_identifier);
198699ebb4caSwyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
198799ebb4caSwyllys 			return (NID_crl_distribution_points);
198899ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
198999ebb4caSwyllys 			return (NID_subject_key_identifier);
199099ebb4caSwyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
199199ebb4caSwyllys 			return (OBJ_sn2nid("policyMappings"));
199299ebb4caSwyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
199399ebb4caSwyllys 			return (OBJ_sn2nid("nameConstraints"));
199499ebb4caSwyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
199599ebb4caSwyllys 			return (OBJ_sn2nid("policyConstraints"));
199699ebb4caSwyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
199799ebb4caSwyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
199899ebb4caSwyllys 		case KMF_X509_EXT_FRESHEST_CRL:
199999ebb4caSwyllys 			return (OBJ_sn2nid("freshestCRL"));
200099ebb4caSwyllys 		default:
200199ebb4caSwyllys 			return (NID_undef);
200299ebb4caSwyllys 	}
200399ebb4caSwyllys }
200499ebb4caSwyllys 
200599ebb4caSwyllys KMF_RETURN
200699ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
200799ebb4caSwyllys 	KMF_PRINTABLE_ITEM flag, char *resultStr)
200899ebb4caSwyllys {
200999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
201099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
201199ebb4caSwyllys 	X509 *xcert = NULL;
201299ebb4caSwyllys 	unsigned char *outbuf = NULL;
201399ebb4caSwyllys 	unsigned char *outbuf_p;
201499ebb4caSwyllys 	char *tmpstr = NULL;
201599ebb4caSwyllys 	int j;
201699ebb4caSwyllys 	int ext_index, nid, len;
201799ebb4caSwyllys 	BIO *mem = NULL;
201899ebb4caSwyllys 	STACK *emlst = NULL;
201999ebb4caSwyllys 	X509_EXTENSION *ex;
202099ebb4caSwyllys 	X509_CINF *ci;
202199ebb4caSwyllys 
202299ebb4caSwyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
202399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
202499ebb4caSwyllys 	}
202599ebb4caSwyllys 
202699ebb4caSwyllys 	/* copy cert data to outbuf */
202799ebb4caSwyllys 	outbuf = malloc(pcert->Length);
202899ebb4caSwyllys 	if (outbuf == NULL) {
202999ebb4caSwyllys 		return (KMF_ERR_MEMORY);
203099ebb4caSwyllys 	}
203199ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
203299ebb4caSwyllys 
203399ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
203499ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
203599ebb4caSwyllys 	if (xcert == NULL) {
203699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
203799ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
203899ebb4caSwyllys 		goto out;
203999ebb4caSwyllys 	}
204099ebb4caSwyllys 
204199ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
204299ebb4caSwyllys 	if (mem == NULL) {
204399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
204499ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
204599ebb4caSwyllys 		goto out;
204699ebb4caSwyllys 	}
204799ebb4caSwyllys 
204899ebb4caSwyllys 	switch (flag) {
204999ebb4caSwyllys 	case KMF_CERT_ISSUER:
205099ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
205199ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
205299ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
205399ebb4caSwyllys 		break;
205499ebb4caSwyllys 
205599ebb4caSwyllys 	case KMF_CERT_SUBJECT:
205699ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
205799ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
205899ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
205999ebb4caSwyllys 		break;
206099ebb4caSwyllys 
206199ebb4caSwyllys 	case KMF_CERT_VERSION:
206299ebb4caSwyllys 		tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version);
206399ebb4caSwyllys 		(void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN);
206499ebb4caSwyllys 		OPENSSL_free(tmpstr);
206599ebb4caSwyllys 		len = strlen(resultStr);
206699ebb4caSwyllys 		break;
206799ebb4caSwyllys 
206899ebb4caSwyllys 	case KMF_CERT_SERIALNUM:
206999ebb4caSwyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
207099ebb4caSwyllys 			(void) strcpy(resultStr, "0x");
207199ebb4caSwyllys 			len = BIO_gets(mem, &resultStr[2],
207299ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN - 2);
207399ebb4caSwyllys 		}
207499ebb4caSwyllys 		break;
207599ebb4caSwyllys 
207699ebb4caSwyllys 	case KMF_CERT_NOTBEFORE:
207799ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notBefore(xcert));
207899ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
207999ebb4caSwyllys 		break;
208099ebb4caSwyllys 
208199ebb4caSwyllys 	case KMF_CERT_NOTAFTER:
208299ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notAfter(xcert));
208399ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
208499ebb4caSwyllys 		break;
208599ebb4caSwyllys 
208699ebb4caSwyllys 	case KMF_CERT_PUBKEY_DATA:
208799ebb4caSwyllys 		{
208899ebb4caSwyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
208999ebb4caSwyllys 			if (pkey == NULL) {
209099ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
209199ebb4caSwyllys 				ret = KMF_ERR_ENCODING;
209299ebb4caSwyllys 				goto out;
209399ebb4caSwyllys 			}
209499ebb4caSwyllys 
209599ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
209699ebb4caSwyllys 				(void) BIO_printf(mem,
209799ebb4caSwyllys 				    "RSA Public Key: (%d bit)\n",
209899ebb4caSwyllys 				    BN_num_bits(pkey->pkey.rsa->n));
209999ebb4caSwyllys 				(void) RSA_print(mem, pkey->pkey.rsa, 0);
210099ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
210199ebb4caSwyllys 				(void) BIO_printf(mem,
210299ebb4caSwyllys 				    "%12sDSA Public Key:\n", "");
210399ebb4caSwyllys 				(void) DSA_print(mem, pkey->pkey.dsa, 0);
210499ebb4caSwyllys 			} else {
210599ebb4caSwyllys 				(void) BIO_printf(mem,
210699ebb4caSwyllys 				    "%12sUnknown Public Key:\n", "");
210799ebb4caSwyllys 			}
210899ebb4caSwyllys 			(void) BIO_printf(mem, "\n");
210999ebb4caSwyllys 			EVP_PKEY_free(pkey);
211099ebb4caSwyllys 		}
211199ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
211299ebb4caSwyllys 		break;
211399ebb4caSwyllys 	case KMF_CERT_SIGNATURE_ALG:
211499ebb4caSwyllys 	case KMF_CERT_PUBKEY_ALG:
211599ebb4caSwyllys 		if (flag == KMF_CERT_SIGNATURE_ALG) {
211699ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
211799ebb4caSwyllys 			    xcert->sig_alg->algorithm);
211899ebb4caSwyllys 		} else {
211999ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
212099ebb4caSwyllys 			    xcert->cert_info->key->algor->algorithm);
212199ebb4caSwyllys 		}
212299ebb4caSwyllys 
212399ebb4caSwyllys 		if (len > 0) {
212499ebb4caSwyllys 			len = BIO_read(mem, resultStr,
212599ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN);
212699ebb4caSwyllys 		}
212799ebb4caSwyllys 		break;
212899ebb4caSwyllys 
212999ebb4caSwyllys 	case KMF_CERT_EMAIL:
213099ebb4caSwyllys 		emlst = X509_get1_email(xcert);
213199ebb4caSwyllys 		for (j = 0; j < sk_num(emlst); j++)
213299ebb4caSwyllys 			(void) BIO_printf(mem, "%s\n", sk_value(emlst, j));
213399ebb4caSwyllys 
213499ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
213599ebb4caSwyllys 		X509_email_free(emlst);
213699ebb4caSwyllys 		break;
213799ebb4caSwyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
213899ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
213999ebb4caSwyllys 	case KMF_X509_EXT_KEY_USAGE:
214099ebb4caSwyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
214199ebb4caSwyllys 	case KMF_X509_EXT_CERT_POLICIES:
214299ebb4caSwyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
214399ebb4caSwyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
214499ebb4caSwyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
214599ebb4caSwyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
214699ebb4caSwyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
214799ebb4caSwyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
214899ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
214999ebb4caSwyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
215099ebb4caSwyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
215199ebb4caSwyllys 	case KMF_X509_EXT_FRESHEST_CRL:
215299ebb4caSwyllys 		nid = ext2NID(flag);
215399ebb4caSwyllys 		if (nid == NID_undef) {
215499ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
215599ebb4caSwyllys 			goto out;
215699ebb4caSwyllys 		}
215799ebb4caSwyllys 		ci = xcert->cert_info;
215899ebb4caSwyllys 
215999ebb4caSwyllys 		ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1);
216099ebb4caSwyllys 		if (ext_index == -1) {
216199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
216299ebb4caSwyllys 
216399ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
216499ebb4caSwyllys 			goto out;
216599ebb4caSwyllys 		}
216699ebb4caSwyllys 		ex = X509v3_get_ext(ci->extensions, ext_index);
216799ebb4caSwyllys 
216899ebb4caSwyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
216999ebb4caSwyllys 
217099ebb4caSwyllys 		if (BIO_printf(mem, ": %s\n",
217130a5e8faSwyllys 		    X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
217299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
217399ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
217499ebb4caSwyllys 			goto out;
217599ebb4caSwyllys 		}
217699ebb4caSwyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
217799ebb4caSwyllys 			(void) BIO_printf(mem, "%*s", 4, "");
217899ebb4caSwyllys 			(void) M_ASN1_OCTET_STRING_print(mem, ex->value);
217999ebb4caSwyllys 		}
218099ebb4caSwyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
218199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
218299ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
218399ebb4caSwyllys 			goto out;
218499ebb4caSwyllys 		}
218599ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
218699ebb4caSwyllys 	}
218799ebb4caSwyllys 	if (len <= 0) {
218899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
218999ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
219099ebb4caSwyllys 	}
219199ebb4caSwyllys 
219299ebb4caSwyllys out:
219399ebb4caSwyllys 	if (outbuf != NULL) {
219499ebb4caSwyllys 		free(outbuf);
219599ebb4caSwyllys 	}
219699ebb4caSwyllys 
219799ebb4caSwyllys 	if (xcert != NULL) {
219899ebb4caSwyllys 		X509_free(xcert);
219999ebb4caSwyllys 	}
220099ebb4caSwyllys 
220199ebb4caSwyllys 	if (mem != NULL) {
220299ebb4caSwyllys 		(void) BIO_free(mem);
220399ebb4caSwyllys 	}
220499ebb4caSwyllys 
220599ebb4caSwyllys 	return (ret);
220699ebb4caSwyllys }
220730a5e8faSwyllys 
220899ebb4caSwyllys KMF_RETURN
220999ebb4caSwyllys /*ARGSUSED*/
221030a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
221130a5e8faSwyllys     KMF_ATTRIBUTE *attrlist)
221299ebb4caSwyllys {
221399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
221430a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
221530a5e8faSwyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
221630a5e8faSwyllys 	KMF_KEY_HANDLE *key = NULL;
221730a5e8faSwyllys 	uint32_t numkeys = 1; /* 1 key only */
221830a5e8faSwyllys 	char *dirpath = NULL;
221930a5e8faSwyllys 	char *keyfile = NULL;
222030a5e8faSwyllys 	KMF_ATTRIBUTE new_attrlist[16];
222130a5e8faSwyllys 	int i = 0;
222299ebb4caSwyllys 
222399ebb4caSwyllys 	/*
222499ebb4caSwyllys 	 * This is really just a FindKey operation, reuse the
222599ebb4caSwyllys 	 * FindKey function.
222699ebb4caSwyllys 	 */
222730a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
222830a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
222930a5e8faSwyllys 	i++;
223099ebb4caSwyllys 
223130a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
223230a5e8faSwyllys 	    KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
223330a5e8faSwyllys 	i++;
223499ebb4caSwyllys 
223530a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
223630a5e8faSwyllys 	    KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
223730a5e8faSwyllys 	i++;
223830a5e8faSwyllys 
223930a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
224030a5e8faSwyllys 	if (key == NULL) {
224130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
224230a5e8faSwyllys 	} else {
224330a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
224430a5e8faSwyllys 		    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
224530a5e8faSwyllys 		i++;
224630a5e8faSwyllys 	}
224730a5e8faSwyllys 
224830a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
224930a5e8faSwyllys 	if (dirpath != NULL) {
225030a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
225130a5e8faSwyllys 		    KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
225230a5e8faSwyllys 		i++;
225330a5e8faSwyllys 	}
225430a5e8faSwyllys 
225530a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
225630a5e8faSwyllys 	if (keyfile == NULL)
225730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
225830a5e8faSwyllys 	else {
225930a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
226030a5e8faSwyllys 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
226130a5e8faSwyllys 		i++;
226230a5e8faSwyllys 	}
226330a5e8faSwyllys 
226430a5e8faSwyllys 	rv = OpenSSL_FindKey(handle, i, new_attrlist);
226599ebb4caSwyllys 	return (rv);
226699ebb4caSwyllys }
226799ebb4caSwyllys 
226899ebb4caSwyllys KMF_RETURN
226999ebb4caSwyllys /*ARGSUSED*/
227099ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
227199ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
227299ebb4caSwyllys 	KMF_DATA *output)
227399ebb4caSwyllys {
227499ebb4caSwyllys 	KMF_RETURN		ret = KMF_OK;
227599ebb4caSwyllys 	RSA *rsa = NULL;
227699ebb4caSwyllys 	unsigned int in_len = 0, out_len = 0;
227799ebb4caSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
227899ebb4caSwyllys 	uint8_t *in_data, *out_data;
227999ebb4caSwyllys 	int i, blocks;
228099ebb4caSwyllys 
228199ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
228299ebb4caSwyllys 	    ciphertext == NULL || output == NULL ||
228399ebb4caSwyllys 	    ciphertext->Data == NULL ||
228499ebb4caSwyllys 	    output->Data == NULL)
228599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
228699ebb4caSwyllys 
228799ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
228899ebb4caSwyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
228999ebb4caSwyllys 		modulus_len = RSA_size(rsa);
229099ebb4caSwyllys 	} else {
229199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
229299ebb4caSwyllys 	}
229399ebb4caSwyllys 
229499ebb4caSwyllys 	blocks = ciphertext->Length/modulus_len;
229599ebb4caSwyllys 	out_data = output->Data;
229699ebb4caSwyllys 	in_data = ciphertext->Data;
229799ebb4caSwyllys 	out_len = modulus_len - 11;
229899ebb4caSwyllys 	in_len = modulus_len;
229999ebb4caSwyllys 
230099ebb4caSwyllys 	for (i = 0; i < blocks; i++) {
230199ebb4caSwyllys 		out_len  = RSA_private_decrypt(in_len,
230299ebb4caSwyllys 		    in_data, out_data, rsa, RSA_PKCS1_PADDING);
230399ebb4caSwyllys 
230499ebb4caSwyllys 		if (out_len == 0) {
230599ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
230699ebb4caSwyllys 			goto cleanup;
230799ebb4caSwyllys 		}
230899ebb4caSwyllys 
230999ebb4caSwyllys 		out_data += out_len;
231099ebb4caSwyllys 		total_decrypted += out_len;
231199ebb4caSwyllys 		in_data += in_len;
231299ebb4caSwyllys 	}
231399ebb4caSwyllys 
231499ebb4caSwyllys 	output->Length = total_decrypted;
231599ebb4caSwyllys 
231699ebb4caSwyllys cleanup:
231799ebb4caSwyllys 	RSA_free(rsa);
231899ebb4caSwyllys 	if (ret != KMF_OK)
231999ebb4caSwyllys 		output->Length = 0;
232099ebb4caSwyllys 
232199ebb4caSwyllys 	return (ret);
232299ebb4caSwyllys 
232399ebb4caSwyllys }
232499ebb4caSwyllys 
232599ebb4caSwyllys /*
232699ebb4caSwyllys  *  This function will create a certid from issuer_cert and user_cert.
232799ebb4caSwyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
232899ebb4caSwyllys  *  certid memory after use.
232999ebb4caSwyllys  */
233099ebb4caSwyllys static KMF_RETURN
233199ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
233299ebb4caSwyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
233399ebb4caSwyllys {
233499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
233599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
233699ebb4caSwyllys 	X509   *issuer = NULL;
233799ebb4caSwyllys 	X509   *cert = NULL;
233899ebb4caSwyllys 	unsigned char *ptmp;
233999ebb4caSwyllys 
234099ebb4caSwyllys 	if (issuer_cert == NULL || user_cert == NULL) {
234199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
234299ebb4caSwyllys 	}
234399ebb4caSwyllys 
234499ebb4caSwyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
234599ebb4caSwyllys 	ptmp = issuer_cert->Data;
234699ebb4caSwyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
234799ebb4caSwyllys 	    issuer_cert->Length);
234899ebb4caSwyllys 	if (issuer == NULL) {
234999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
235099ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
235199ebb4caSwyllys 		goto end;
235299ebb4caSwyllys 	}
235399ebb4caSwyllys 
235499ebb4caSwyllys 	/* convert the DER-encoded user cert to an internal X509 */
235599ebb4caSwyllys 	ptmp = user_cert->Data;
235699ebb4caSwyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
235799ebb4caSwyllys 	    user_cert->Length);
235899ebb4caSwyllys 	if (cert == NULL) {
235999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
236099ebb4caSwyllys 
236199ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
236299ebb4caSwyllys 		goto end;
236399ebb4caSwyllys 	}
236499ebb4caSwyllys 
236599ebb4caSwyllys 	/* create a CERTID */
236699ebb4caSwyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
236799ebb4caSwyllys 	if (*certid == NULL) {
236899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
236999ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
237099ebb4caSwyllys 		goto end;
237199ebb4caSwyllys 	}
237299ebb4caSwyllys 
237399ebb4caSwyllys end:
237499ebb4caSwyllys 	if (issuer != NULL) {
237599ebb4caSwyllys 		X509_free(issuer);
237699ebb4caSwyllys 	}
237799ebb4caSwyllys 
237899ebb4caSwyllys 	if (cert != NULL) {
237999ebb4caSwyllys 		X509_free(cert);
238099ebb4caSwyllys 	}
238199ebb4caSwyllys 
238299ebb4caSwyllys 	return (ret);
238399ebb4caSwyllys }
238499ebb4caSwyllys 
238599ebb4caSwyllys KMF_RETURN
238630a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
238730a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
238899ebb4caSwyllys {
238999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
239099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
239199ebb4caSwyllys 	OCSP_CERTID *id = NULL;
239299ebb4caSwyllys 	OCSP_REQUEST *req = NULL;
239399ebb4caSwyllys 	BIO *derbio = NULL;
239430a5e8faSwyllys 	char *reqfile;
239530a5e8faSwyllys 	KMF_DATA *issuer_cert;
239630a5e8faSwyllys 	KMF_DATA *user_cert;
239799ebb4caSwyllys 
239830a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
239930a5e8faSwyllys 	    attrlist, numattr);
240030a5e8faSwyllys 	if (user_cert == NULL)
240199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
240299ebb4caSwyllys 
240330a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
240430a5e8faSwyllys 	    attrlist, numattr);
240530a5e8faSwyllys 	if (issuer_cert == NULL)
240630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
240730a5e8faSwyllys 
240830a5e8faSwyllys 	reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
240930a5e8faSwyllys 	    attrlist, numattr);
241030a5e8faSwyllys 	if (reqfile == NULL)
241130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
241230a5e8faSwyllys 
241330a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
241499ebb4caSwyllys 	if (ret != KMF_OK) {
241599ebb4caSwyllys 		return (ret);
241699ebb4caSwyllys 	}
241799ebb4caSwyllys 
241899ebb4caSwyllys 	/* Create an OCSP request */
241999ebb4caSwyllys 	req = OCSP_REQUEST_new();
242099ebb4caSwyllys 	if (req == NULL) {
242199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
242299ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
242399ebb4caSwyllys 		goto end;
242499ebb4caSwyllys 	}
242599ebb4caSwyllys 
242699ebb4caSwyllys 	if (!OCSP_request_add0_id(req, id)) {
242799ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
242899ebb4caSwyllys 		goto end;
242999ebb4caSwyllys 	}
243099ebb4caSwyllys 
243199ebb4caSwyllys 	/* Write the request to the output file with DER encoding */
243299ebb4caSwyllys 	derbio = BIO_new_file(reqfile, "wb");
243399ebb4caSwyllys 	if (!derbio) {
243499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
243599ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
243699ebb4caSwyllys 		goto end;
243799ebb4caSwyllys 	}
243899ebb4caSwyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
243999ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
244099ebb4caSwyllys 	}
244199ebb4caSwyllys 
244299ebb4caSwyllys end:
244399ebb4caSwyllys 	/*
2444*e65e5c2dSWyllys Ingersoll 	 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2445a2d4930dSDan OpenSolaris Anderson 	 * will also deallocate certid's space.
244699ebb4caSwyllys 	 */
244799ebb4caSwyllys 	if (req != NULL) {
244899ebb4caSwyllys 		OCSP_REQUEST_free(req);
244999ebb4caSwyllys 	}
245099ebb4caSwyllys 
245199ebb4caSwyllys 	if (derbio != NULL) {
245299ebb4caSwyllys 		(void) BIO_free(derbio);
245399ebb4caSwyllys 	}
245499ebb4caSwyllys 
245599ebb4caSwyllys 	return (ret);
245699ebb4caSwyllys }
245799ebb4caSwyllys 
245899ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */
245999ebb4caSwyllys static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
246099ebb4caSwyllys {
246199ebb4caSwyllys 	int i;
246299ebb4caSwyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
246399ebb4caSwyllys 
246499ebb4caSwyllys 	/* Easy if lookup by name */
246599ebb4caSwyllys 	if (id->type == V_OCSP_RESPID_NAME)
246699ebb4caSwyllys 		return (X509_find_by_subject(certs, id->value.byName));
246799ebb4caSwyllys 
246899ebb4caSwyllys 	/* Lookup by key hash */
246999ebb4caSwyllys 
247099ebb4caSwyllys 	/* If key hash isn't SHA1 length then forget it */
247199ebb4caSwyllys 	if (id->value.byKey->length != SHA_DIGEST_LENGTH)
247299ebb4caSwyllys 		return (NULL);
247399ebb4caSwyllys 
247499ebb4caSwyllys 	keyhash = id->value.byKey->data;
247599ebb4caSwyllys 	/* Calculate hash of each key and compare */
247699ebb4caSwyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
2477a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
247899ebb4caSwyllys 		X509 *x = sk_X509_value(certs, i);
24795b3e1433Swyllys 		/* Use pubkey_digest to get the key ID value */
248099ebb4caSwyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
248199ebb4caSwyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
248299ebb4caSwyllys 			return (x);
248399ebb4caSwyllys 	}
248499ebb4caSwyllys 	return (NULL);
248599ebb4caSwyllys }
248699ebb4caSwyllys 
248799ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */
2488a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */
248999ebb4caSwyllys static int
249099ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
249199ebb4caSwyllys     X509_STORE *st, unsigned long flags)
249299ebb4caSwyllys {
249399ebb4caSwyllys 	X509 *signer;
249499ebb4caSwyllys 	OCSP_RESPID *rid = bs->tbsResponseData->responderId;
249599ebb4caSwyllys 	if ((signer = ocsp_find_signer_sk(certs, rid)))	{
249699ebb4caSwyllys 		*psigner = signer;
249799ebb4caSwyllys 		return (2);
249899ebb4caSwyllys 	}
249999ebb4caSwyllys 	if (!(flags & OCSP_NOINTERN) &&
250099ebb4caSwyllys 	    (signer = ocsp_find_signer_sk(bs->certs, rid))) {
250199ebb4caSwyllys 		*psigner = signer;
250299ebb4caSwyllys 		return (1);
250399ebb4caSwyllys 	}
250499ebb4caSwyllys 	/* Maybe lookup from store if by subject name */
250599ebb4caSwyllys 
250699ebb4caSwyllys 	*psigner = NULL;
250799ebb4caSwyllys 	return (0);
250899ebb4caSwyllys }
250999ebb4caSwyllys 
251099ebb4caSwyllys /*
251199ebb4caSwyllys  * This function will verify the signature of a basic response, using
251299ebb4caSwyllys  * the public key from the OCSP responder certificate.
251399ebb4caSwyllys  */
251499ebb4caSwyllys static KMF_RETURN
251599ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
251699ebb4caSwyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
251799ebb4caSwyllys {
251899ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
251999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
252099ebb4caSwyllys 	STACK_OF(X509) *cert_stack = NULL;
252199ebb4caSwyllys 	X509 *signer = NULL;
252299ebb4caSwyllys 	X509 *issuer = NULL;
252399ebb4caSwyllys 	EVP_PKEY *skey = NULL;
252499ebb4caSwyllys 	unsigned char *ptmp;
252599ebb4caSwyllys 
252699ebb4caSwyllys 
252799ebb4caSwyllys 	if (bs == NULL || issuer_cert == NULL)
252899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
252999ebb4caSwyllys 
253099ebb4caSwyllys 	/*
253199ebb4caSwyllys 	 * Find the certificate that signed the basic response.
253299ebb4caSwyllys 	 *
253399ebb4caSwyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
253499ebb4caSwyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
253599ebb4caSwyllys 	 * If we still do not find a signer, we will look for it from the
253699ebb4caSwyllys 	 * certificate list came with the response file.
253799ebb4caSwyllys 	 */
253899ebb4caSwyllys 	if (signer_cert != NULL) {
253999ebb4caSwyllys 		ptmp = signer_cert->Data;
254099ebb4caSwyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
254199ebb4caSwyllys 		    signer_cert->Length);
254299ebb4caSwyllys 		if (signer == NULL) {
254399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
254499ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
254599ebb4caSwyllys 			goto end;
254699ebb4caSwyllys 		}
254799ebb4caSwyllys 	} else {
254899ebb4caSwyllys 		/*
254999ebb4caSwyllys 		 * Convert the issuer cert into X509 and push it into a
255099ebb4caSwyllys 		 * stack to be used by ocsp_find_signer().
255199ebb4caSwyllys 		 */
255299ebb4caSwyllys 		ptmp = issuer_cert->Data;
255399ebb4caSwyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
255499ebb4caSwyllys 		    issuer_cert->Length);
255599ebb4caSwyllys 		if (issuer == NULL) {
255699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
255799ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
255899ebb4caSwyllys 			goto end;
255999ebb4caSwyllys 		}
256099ebb4caSwyllys 
256199ebb4caSwyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
256299ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
256399ebb4caSwyllys 			goto end;
256499ebb4caSwyllys 		}
256599ebb4caSwyllys 
256699ebb4caSwyllys 		if (sk_X509_push(cert_stack, issuer) == NULL) {
256799ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
256899ebb4caSwyllys 			goto end;
256999ebb4caSwyllys 		}
257099ebb4caSwyllys 
257199ebb4caSwyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
257299ebb4caSwyllys 		if (!ret) {
257399ebb4caSwyllys 			/* can not find the signer */
257499ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
257599ebb4caSwyllys 			goto end;
257699ebb4caSwyllys 		}
257799ebb4caSwyllys 	}
257899ebb4caSwyllys 
257999ebb4caSwyllys 	/* Verify the signature of the response */
258099ebb4caSwyllys 	skey = X509_get_pubkey(signer);
258199ebb4caSwyllys 	if (skey == NULL) {
258299ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
258399ebb4caSwyllys 		goto end;
258499ebb4caSwyllys 	}
258599ebb4caSwyllys 
258699ebb4caSwyllys 	ret = OCSP_BASICRESP_verify(bs, skey, 0);
258799ebb4caSwyllys 	if (ret == 0) {
258899ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
258999ebb4caSwyllys 		goto end;
259099ebb4caSwyllys 	}
259199ebb4caSwyllys 
259299ebb4caSwyllys end:
259399ebb4caSwyllys 	if (issuer != NULL) {
259499ebb4caSwyllys 		X509_free(issuer);
259599ebb4caSwyllys 	}
259699ebb4caSwyllys 
259799ebb4caSwyllys 	if (signer != NULL) {
259899ebb4caSwyllys 		X509_free(signer);
259999ebb4caSwyllys 	}
260099ebb4caSwyllys 
260199ebb4caSwyllys 	if (skey != NULL) {
260299ebb4caSwyllys 		EVP_PKEY_free(skey);
260399ebb4caSwyllys 	}
260499ebb4caSwyllys 
260599ebb4caSwyllys 	if (cert_stack != NULL) {
260699ebb4caSwyllys 		sk_X509_free(cert_stack);
260799ebb4caSwyllys 	}
260899ebb4caSwyllys 
260999ebb4caSwyllys 	return (ret);
261099ebb4caSwyllys }
261199ebb4caSwyllys 
261299ebb4caSwyllys 
261399ebb4caSwyllys 
261499ebb4caSwyllys KMF_RETURN
261599ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
261630a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
261799ebb4caSwyllys {
261899ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
261999ebb4caSwyllys 	BIO *derbio = NULL;
262099ebb4caSwyllys 	OCSP_RESPONSE *resp = NULL;
262199ebb4caSwyllys 	OCSP_BASICRESP *bs = NULL;
262299ebb4caSwyllys 	OCSP_CERTID *id = NULL;
262399ebb4caSwyllys 	OCSP_SINGLERESP *single = NULL;
262499ebb4caSwyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
262599ebb4caSwyllys 	int index, status, reason;
262630a5e8faSwyllys 	KMF_DATA *issuer_cert;
262730a5e8faSwyllys 	KMF_DATA *user_cert;
262830a5e8faSwyllys 	KMF_DATA *signer_cert;
262930a5e8faSwyllys 	KMF_DATA *response;
263030a5e8faSwyllys 	int *response_reason, *response_status, *cert_status;
263130a5e8faSwyllys 	boolean_t ignore_response_sign = B_FALSE;	/* default is FALSE */
263230a5e8faSwyllys 	uint32_t response_lifetime;
263399ebb4caSwyllys 
263430a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
263530a5e8faSwyllys 	    attrlist, numattr);
263630a5e8faSwyllys 	if (issuer_cert == NULL)
263799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
263899ebb4caSwyllys 
263930a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
264030a5e8faSwyllys 	    attrlist, numattr);
264130a5e8faSwyllys 	if (user_cert == NULL)
264299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
264330a5e8faSwyllys 
264430a5e8faSwyllys 	response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
264530a5e8faSwyllys 	    attrlist, numattr);
264630a5e8faSwyllys 	if (response == NULL)
264730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
264830a5e8faSwyllys 
264930a5e8faSwyllys 	response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
265030a5e8faSwyllys 	    attrlist, numattr);
265130a5e8faSwyllys 	if (response_status == NULL)
265230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
265330a5e8faSwyllys 
265430a5e8faSwyllys 	response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
265530a5e8faSwyllys 	    attrlist, numattr);
265630a5e8faSwyllys 	if (response_reason == NULL)
265730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
265830a5e8faSwyllys 
265930a5e8faSwyllys 	cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
266030a5e8faSwyllys 	    attrlist, numattr);
266130a5e8faSwyllys 	if (cert_status == NULL)
266230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
266399ebb4caSwyllys 
266499ebb4caSwyllys 	/* Read in the response */
266530a5e8faSwyllys 	derbio = BIO_new_mem_buf(response->Data, response->Length);
266699ebb4caSwyllys 	if (!derbio) {
266799ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
266899ebb4caSwyllys 		return (ret);
266999ebb4caSwyllys 	}
267099ebb4caSwyllys 
267199ebb4caSwyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
267299ebb4caSwyllys 	if (resp == NULL) {
267399ebb4caSwyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
267499ebb4caSwyllys 		goto end;
267599ebb4caSwyllys 	}
267699ebb4caSwyllys 
267799ebb4caSwyllys 	/* Check the response status */
267899ebb4caSwyllys 	status = OCSP_response_status(resp);
267930a5e8faSwyllys 	*response_status = status;
268099ebb4caSwyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
268199ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
268299ebb4caSwyllys 		goto end;
268399ebb4caSwyllys 	}
268499ebb4caSwyllys 
268599ebb4caSwyllys #ifdef DEBUG
268699ebb4caSwyllys 	printf("Successfully checked the response file status.\n");
268799ebb4caSwyllys #endif /* DEBUG */
268899ebb4caSwyllys 
268999ebb4caSwyllys 	/* Extract basic response */
269099ebb4caSwyllys 	bs = OCSP_response_get1_basic(resp);
269199ebb4caSwyllys 	if (bs == NULL) {
269299ebb4caSwyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
269399ebb4caSwyllys 		goto end;
269499ebb4caSwyllys 	}
269599ebb4caSwyllys 
269699ebb4caSwyllys #ifdef DEBUG
269799ebb4caSwyllys 	printf("Successfully retrieved the basic response.\n");
269899ebb4caSwyllys #endif /* DEBUG */
269999ebb4caSwyllys 
270099ebb4caSwyllys 	/* Check the basic response signature if required */
270130a5e8faSwyllys 	ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
270230a5e8faSwyllys 	    (void *)&ignore_response_sign, NULL);
270330a5e8faSwyllys 	if (ret != KMF_OK)
270430a5e8faSwyllys 		ret = KMF_OK;
270530a5e8faSwyllys 
270630a5e8faSwyllys 	signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
270730a5e8faSwyllys 	    attrlist, numattr);
270830a5e8faSwyllys 
270930a5e8faSwyllys 	if (ignore_response_sign == B_FALSE) {
271099ebb4caSwyllys 		ret = check_response_signature(handle, bs,
271130a5e8faSwyllys 		    signer_cert, issuer_cert);
271299ebb4caSwyllys 		if (ret != KMF_OK)
271399ebb4caSwyllys 			goto end;
271499ebb4caSwyllys 	}
271599ebb4caSwyllys 
271699ebb4caSwyllys #ifdef DEBUG
271799ebb4caSwyllys 	printf("Successfully verified the response signature.\n");
271899ebb4caSwyllys #endif /* DEBUG */
271999ebb4caSwyllys 
272099ebb4caSwyllys 	/* Create a certid for the certificate in question */
272130a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
272299ebb4caSwyllys 	if (ret != KMF_OK) {
272399ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
272499ebb4caSwyllys 		goto end;
272599ebb4caSwyllys 	}
272699ebb4caSwyllys 
272799ebb4caSwyllys #ifdef DEBUG
272899ebb4caSwyllys 	printf("successfully created a certid for the cert.\n");
272999ebb4caSwyllys #endif /* DEBUG */
273099ebb4caSwyllys 
273199ebb4caSwyllys 	/* Find the index of the single response for the certid */
273299ebb4caSwyllys 	index = OCSP_resp_find(bs, id, -1);
273399ebb4caSwyllys 	if (index < 0) {
273499ebb4caSwyllys 		/* cound not find this certificate in the response */
273599ebb4caSwyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
273699ebb4caSwyllys 		goto end;
273799ebb4caSwyllys 	}
273899ebb4caSwyllys 
273999ebb4caSwyllys #ifdef DEBUG
274099ebb4caSwyllys 	printf("Successfully found the single response index for the cert.\n");
274199ebb4caSwyllys #endif /* DEBUG */
274299ebb4caSwyllys 
274399ebb4caSwyllys 	/* Retrieve the single response and get the cert status */
274499ebb4caSwyllys 	single = OCSP_resp_get0(bs, index);
274599ebb4caSwyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
274699ebb4caSwyllys 	    &nextupd);
274799ebb4caSwyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
274830a5e8faSwyllys 		*cert_status = OCSP_GOOD;
274999ebb4caSwyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
275030a5e8faSwyllys 		*cert_status = OCSP_UNKNOWN;
275199ebb4caSwyllys 	} else { /* revoked */
275230a5e8faSwyllys 		*cert_status = OCSP_REVOKED;
275330a5e8faSwyllys 		*response_reason = reason;
275499ebb4caSwyllys 	}
275599ebb4caSwyllys 	ret = KMF_OK;
275699ebb4caSwyllys 
275730a5e8faSwyllys 	/* resp. time is optional, so we don't care about the return code. */
275830a5e8faSwyllys 	(void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
275930a5e8faSwyllys 	    (void *)&response_lifetime, NULL);
276030a5e8faSwyllys 
276199ebb4caSwyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
276230a5e8faSwyllys 	    response_lifetime)) {
276399ebb4caSwyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
276499ebb4caSwyllys 		goto end;
276599ebb4caSwyllys 	}
276699ebb4caSwyllys 
276799ebb4caSwyllys #ifdef DEBUG
276899ebb4caSwyllys 	printf("Successfully verify the time.\n");
276999ebb4caSwyllys #endif /* DEBUG */
277099ebb4caSwyllys 
277199ebb4caSwyllys end:
277299ebb4caSwyllys 	if (derbio != NULL)
277399ebb4caSwyllys 		(void) BIO_free(derbio);
277499ebb4caSwyllys 
277599ebb4caSwyllys 	if (resp != NULL)
277699ebb4caSwyllys 		OCSP_RESPONSE_free(resp);
277799ebb4caSwyllys 
277899ebb4caSwyllys 	if (bs != NULL)
277999ebb4caSwyllys 		OCSP_BASICRESP_free(bs);
278099ebb4caSwyllys 
278199ebb4caSwyllys 	if (id != NULL)
278299ebb4caSwyllys 		OCSP_CERTID_free(id);
278399ebb4caSwyllys 
278499ebb4caSwyllys 	return (ret);
278599ebb4caSwyllys }
278699ebb4caSwyllys 
278799ebb4caSwyllys static KMF_RETURN
278899ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path,
278999ebb4caSwyllys 	KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
279099ebb4caSwyllys {
279199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
279230a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
279399ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
279499ebb4caSwyllys 
279599ebb4caSwyllys 	if (keyclass == KMF_ASYM_PRI ||
279699ebb4caSwyllys 	    keyclass == KMF_ASYM_PUB) {
279799ebb4caSwyllys 		pkey = openssl_load_key(handle, path);
279899ebb4caSwyllys 		if (pkey == NULL) {
279999ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
280099ebb4caSwyllys 		}
280199ebb4caSwyllys 		if (key != NULL) {
280299ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA)
280399ebb4caSwyllys 				key->keyalg = KMF_RSA;
280499ebb4caSwyllys 			else if (pkey->type == EVP_PKEY_DSA)
280599ebb4caSwyllys 				key->keyalg = KMF_DSA;
280699ebb4caSwyllys 
280799ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
280899ebb4caSwyllys 			key->keyclass = keyclass;
280999ebb4caSwyllys 			key->keyp = (void *)pkey;
281099ebb4caSwyllys 			key->israw = FALSE;
28115b3e1433Swyllys 			if (path != NULL &&
28125b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
28135b3e1433Swyllys 				EVP_PKEY_free(pkey);
28145b3e1433Swyllys 				return (KMF_ERR_MEMORY);
28155b3e1433Swyllys 			}
281699ebb4caSwyllys 		} else {
281799ebb4caSwyllys 			EVP_PKEY_free(pkey);
281899ebb4caSwyllys 			pkey = NULL;
281999ebb4caSwyllys 		}
282099ebb4caSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
282199ebb4caSwyllys 		KMF_ENCODE_FORMAT fmt;
282299ebb4caSwyllys 		/*
282399ebb4caSwyllys 		 * If the file is a recognized format,
282499ebb4caSwyllys 		 * then it is NOT a symmetric key.
282599ebb4caSwyllys 		 */
282630a5e8faSwyllys 		rv = kmf_get_file_format(path, &fmt);
282799ebb4caSwyllys 		if (rv == KMF_OK || fmt != 0) {
282899ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
282999ebb4caSwyllys 		} else if (rv == KMF_ERR_ENCODING) {
283099ebb4caSwyllys 			/*
283199ebb4caSwyllys 			 * If we don't know the encoding,
283299ebb4caSwyllys 			 * it is probably  a symmetric key.
283399ebb4caSwyllys 			 */
283499ebb4caSwyllys 			rv = KMF_OK;
283530a5e8faSwyllys 		} else if (rv == KMF_ERR_OPEN_FILE) {
283630a5e8faSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
283799ebb4caSwyllys 		}
283899ebb4caSwyllys 
283999ebb4caSwyllys 		if (key != NULL) {
284099ebb4caSwyllys 			KMF_DATA keyvalue;
284199ebb4caSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
284299ebb4caSwyllys 			if (rkey == NULL) {
284399ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
284499ebb4caSwyllys 				goto out;
284599ebb4caSwyllys 			}
284699ebb4caSwyllys 
284799ebb4caSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
284830a5e8faSwyllys 			rv = kmf_read_input_file(handle, path, &keyvalue);
284999ebb4caSwyllys 			if (rv != KMF_OK)
285099ebb4caSwyllys 				goto out;
285199ebb4caSwyllys 
285299ebb4caSwyllys 			rkey->keydata.len = keyvalue.Length;
285399ebb4caSwyllys 			rkey->keydata.val = keyvalue.Data;
285499ebb4caSwyllys 
285599ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
285699ebb4caSwyllys 			key->keyclass = keyclass;
285799ebb4caSwyllys 			key->israw = TRUE;
285899ebb4caSwyllys 			key->keyp = (void *)rkey;
28595b3e1433Swyllys 			if (path != NULL &&
28605b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
28615b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
28625b3e1433Swyllys 			}
286399ebb4caSwyllys 		}
286499ebb4caSwyllys 	}
286599ebb4caSwyllys out:
286699ebb4caSwyllys 	if (rv != KMF_OK) {
286799ebb4caSwyllys 		if (rkey != NULL) {
286830a5e8faSwyllys 			kmf_free_raw_sym_key(rkey);
286999ebb4caSwyllys 		}
287099ebb4caSwyllys 		if (pkey != NULL)
287199ebb4caSwyllys 			EVP_PKEY_free(pkey);
287299ebb4caSwyllys 
287399ebb4caSwyllys 		if (key != NULL) {
287499ebb4caSwyllys 			key->keyalg = KMF_KEYALG_NONE;
287599ebb4caSwyllys 			key->keyclass = KMF_KEYCLASS_NONE;
287699ebb4caSwyllys 			key->keyp = NULL;
287799ebb4caSwyllys 		}
287899ebb4caSwyllys 	}
287999ebb4caSwyllys 
288099ebb4caSwyllys 	return (rv);
288199ebb4caSwyllys }
288299ebb4caSwyllys 
288399ebb4caSwyllys KMF_RETURN
288430a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle,
288530a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
288699ebb4caSwyllys {
288799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
288899ebb4caSwyllys 	char *fullpath = NULL;
2889f482c776Swyllys 	uint32_t maxkeys;
289030a5e8faSwyllys 	KMF_KEY_HANDLE *key;
289130a5e8faSwyllys 	uint32_t *numkeys;
289230a5e8faSwyllys 	KMF_KEY_CLASS keyclass;
289330a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
289430a5e8faSwyllys 	char *dirpath;
289530a5e8faSwyllys 	char *keyfile;
289699ebb4caSwyllys 
289730a5e8faSwyllys 	if (handle == NULL)
289899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
289999ebb4caSwyllys 
290030a5e8faSwyllys 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
290130a5e8faSwyllys 	if (numkeys == NULL)
290230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
290330a5e8faSwyllys 
290430a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
290530a5e8faSwyllys 	    (void *)&keyclass, NULL);
290630a5e8faSwyllys 	if (rv != KMF_OK)
290730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
290830a5e8faSwyllys 
290930a5e8faSwyllys 	if (keyclass != KMF_ASYM_PUB &&
291030a5e8faSwyllys 	    keyclass != KMF_ASYM_PRI &&
291130a5e8faSwyllys 	    keyclass != KMF_SYMMETRIC)
291299ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
291399ebb4caSwyllys 
291430a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
291530a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
291630a5e8faSwyllys 
291730a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
291899ebb4caSwyllys 
291999ebb4caSwyllys 	if (fullpath == NULL)
292099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
292199ebb4caSwyllys 
2922f482c776Swyllys 	maxkeys = *numkeys;
2923f482c776Swyllys 	if (maxkeys == 0)
2924f482c776Swyllys 		maxkeys = 0xFFFFFFFF;
292599ebb4caSwyllys 	*numkeys = 0;
292699ebb4caSwyllys 
292730a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
292830a5e8faSwyllys 	/* it is okay to have "keys" contains NULL */
292930a5e8faSwyllys 
293030a5e8faSwyllys 	/*
293130a5e8faSwyllys 	 * The caller may want a list of the raw key data as well.
293230a5e8faSwyllys 	 * Useful for importing keys from a file into other keystores.
293330a5e8faSwyllys 	 */
293430a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
293530a5e8faSwyllys 
293699ebb4caSwyllys 	if (isdir(fullpath)) {
293799ebb4caSwyllys 		DIR *dirp;
293899ebb4caSwyllys 		struct dirent *dp;
293999ebb4caSwyllys 		int n = 0;
294099ebb4caSwyllys 
294199ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
294299ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
294399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
294499ebb4caSwyllys 		}
294599ebb4caSwyllys 		rewinddir(dirp);
2946f482c776Swyllys 		while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
294799ebb4caSwyllys 			if (strcmp(dp->d_name, ".") &&
294899ebb4caSwyllys 			    strcmp(dp->d_name, "..")) {
294999ebb4caSwyllys 				char *fname;
295099ebb4caSwyllys 
295199ebb4caSwyllys 				fname = get_fullpath(fullpath,
295299ebb4caSwyllys 				    (char *)&dp->d_name);
295399ebb4caSwyllys 
295499ebb4caSwyllys 				rv = fetch_key(handle, fname,
295530a5e8faSwyllys 				    keyclass, key ? &key[n] : NULL);
295699ebb4caSwyllys 
295730a5e8faSwyllys 				if (rv == KMF_OK) {
295830a5e8faSwyllys 					if (key != NULL && rawkey != NULL)
295930a5e8faSwyllys 						rv = convertToRawKey(
296030a5e8faSwyllys 						    key[n].keyp, &rawkey[n]);
296199ebb4caSwyllys 					n++;
296230a5e8faSwyllys 				}
296399ebb4caSwyllys 
296499ebb4caSwyllys 				if (rv != KMF_OK || key == NULL)
296599ebb4caSwyllys 					free(fname);
296699ebb4caSwyllys 			}
296799ebb4caSwyllys 		}
296899ebb4caSwyllys 		(void) closedir(dirp);
296999ebb4caSwyllys 		free(fullpath);
297099ebb4caSwyllys 		(*numkeys) = n;
297199ebb4caSwyllys 	} else {
297230a5e8faSwyllys 		rv = fetch_key(handle, fullpath, keyclass, key);
297399ebb4caSwyllys 		if (rv == KMF_OK)
297499ebb4caSwyllys 			(*numkeys) = 1;
297599ebb4caSwyllys 
297699ebb4caSwyllys 		if (rv != KMF_OK || key == NULL)
297799ebb4caSwyllys 			free(fullpath);
297830a5e8faSwyllys 
297930a5e8faSwyllys 		if (rv == KMF_OK && key != NULL && rawkey != NULL) {
298030a5e8faSwyllys 			rv = convertToRawKey(key->keyp, rawkey);
298130a5e8faSwyllys 		}
298299ebb4caSwyllys 	}
298399ebb4caSwyllys 
2984f482c776Swyllys 	if (rv == KMF_OK && (*numkeys) == 0)
298599ebb4caSwyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
298673cc0e02Swyllys 	else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
298773cc0e02Swyllys 		rv = KMF_OK;
298899ebb4caSwyllys 
298999ebb4caSwyllys 	return (rv);
299099ebb4caSwyllys }
299199ebb4caSwyllys 
299299ebb4caSwyllys #define	HANDLE_PK12_ERROR { \
299399ebb4caSwyllys 	SET_ERROR(kmfh, ERR_get_error()); \
299499ebb4caSwyllys 	rv = KMF_ERR_ENCODING; \
299599ebb4caSwyllys 	goto out; \
299699ebb4caSwyllys }
299799ebb4caSwyllys 
29985b3e1433Swyllys static int
29995b3e1433Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
300099ebb4caSwyllys {
30015b3e1433Swyllys 	if (xcert != NULL && xcert->aux != NULL &&
30025b3e1433Swyllys 	    xcert->aux->alias != NULL) {
30035b3e1433Swyllys 		if (PKCS12_add_friendlyname_asc(bag,
30045b3e1433Swyllys 		    (const char *)xcert->aux->alias->data,
30055b3e1433Swyllys 		    xcert->aux->alias->length) == 0)
30065b3e1433Swyllys 			return (0);
30075b3e1433Swyllys 	}
30085b3e1433Swyllys 	return (1);
30095b3e1433Swyllys }
30105b3e1433Swyllys 
30115b3e1433Swyllys static PKCS7 *
30125b3e1433Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
30135b3e1433Swyllys 	uchar_t *keyid, unsigned int keyidlen)
30145b3e1433Swyllys {
301599ebb4caSwyllys 	PKCS12_SAFEBAG *bag = NULL;
301699ebb4caSwyllys 	PKCS7 *cert_authsafe = NULL;
30175b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack;
301899ebb4caSwyllys 
301999ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
302099ebb4caSwyllys 	if (bag_stack == NULL)
30215b3e1433Swyllys 		return (NULL);
302299ebb4caSwyllys 
302399ebb4caSwyllys 	/* Convert cert from X509 struct to PKCS#12 bag */
302499ebb4caSwyllys 	bag = PKCS12_x5092certbag(sslcert);
302599ebb4caSwyllys 	if (bag == NULL) {
30265b3e1433Swyllys 		goto out;
302799ebb4caSwyllys 	}
302899ebb4caSwyllys 
302999ebb4caSwyllys 	/* Add the key id to the certificate bag. */
30305b3e1433Swyllys 	if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
30315b3e1433Swyllys 		goto out;
303299ebb4caSwyllys 	}
303399ebb4caSwyllys 
30345b3e1433Swyllys 	if (!add_alias_to_bag(bag, sslcert))
30355b3e1433Swyllys 		goto out;
30365b3e1433Swyllys 
303799ebb4caSwyllys 	/* Pile it on the bag_stack. */
303899ebb4caSwyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
30395b3e1433Swyllys 		goto out;
304099ebb4caSwyllys 	}
304199ebb4caSwyllys 	/* Turn bag_stack of certs into encrypted authsafe. */
304299ebb4caSwyllys 	cert_authsafe = PKCS12_pack_p7encdata(
304399ebb4caSwyllys 	    NID_pbe_WithSHA1And40BitRC2_CBC,
304434acef67Swyllys 	    cred->cred, cred->credlen, NULL, 0,
304534acef67Swyllys 	    PKCS12_DEFAULT_ITER, bag_stack);
304699ebb4caSwyllys 
30475b3e1433Swyllys out:
30485b3e1433Swyllys 	if (bag_stack != NULL)
304999ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
305099ebb4caSwyllys 
30515b3e1433Swyllys 	return (cert_authsafe);
305299ebb4caSwyllys }
30535b3e1433Swyllys 
30545b3e1433Swyllys static PKCS7 *
30555b3e1433Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
30565b3e1433Swyllys 	uchar_t *keyid,  unsigned int keyidlen,
30575b3e1433Swyllys 	char *label, int label_len)
30585b3e1433Swyllys {
30595b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
30605b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
30615b3e1433Swyllys 	PKCS12_SAFEBAG *bag = NULL;
30625b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
30635b3e1433Swyllys 
306499ebb4caSwyllys 	p8 = EVP_PKEY2PKCS8(pkey);
306599ebb4caSwyllys 	if (p8 == NULL) {
30665b3e1433Swyllys 		return (NULL);
306799ebb4caSwyllys 	}
306899ebb4caSwyllys 	/* Put the shrouded key into a PKCS#12 bag. */
306999ebb4caSwyllys 	bag = PKCS12_MAKE_SHKEYBAG(
307099ebb4caSwyllys 	    NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
307199ebb4caSwyllys 	    cred->cred, cred->credlen,
307299ebb4caSwyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, p8);
307399ebb4caSwyllys 
307499ebb4caSwyllys 	/* Clean up the PKCS#8 shrouded key, don't need it now. */
307599ebb4caSwyllys 	PKCS8_PRIV_KEY_INFO_free(p8);
307699ebb4caSwyllys 	p8 = NULL;
307799ebb4caSwyllys 
307899ebb4caSwyllys 	if (bag == NULL) {
30795b3e1433Swyllys 		return (NULL);
308099ebb4caSwyllys 	}
30815b3e1433Swyllys 	if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
30825b3e1433Swyllys 		goto out;
30835b3e1433Swyllys 	if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
30845b3e1433Swyllys 		goto out;
30855b3e1433Swyllys 
308699ebb4caSwyllys 	/* Start a PKCS#12 safebag container for the private key. */
308799ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
30885b3e1433Swyllys 	if (bag_stack == NULL)
30895b3e1433Swyllys 		goto out;
309099ebb4caSwyllys 
309199ebb4caSwyllys 	/* Pile on the private key on the bag_stack. */
30925b3e1433Swyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
30935b3e1433Swyllys 		goto out;
30945b3e1433Swyllys 
309599ebb4caSwyllys 	key_authsafe = PKCS12_pack_p7data(bag_stack);
309699ebb4caSwyllys 
30975b3e1433Swyllys out:
30985b3e1433Swyllys 	if (bag_stack != NULL)
309999ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
310099ebb4caSwyllys 	bag_stack = NULL;
31015b3e1433Swyllys 	return (key_authsafe);
310299ebb4caSwyllys }
310399ebb4caSwyllys 
310499ebb4caSwyllys static EVP_PKEY *
310599ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
310699ebb4caSwyllys {
310799ebb4caSwyllys 	RSA		*rsa = NULL;
310899ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
310999ebb4caSwyllys 
311099ebb4caSwyllys 	if ((rsa = RSA_new()) == NULL)
311199ebb4caSwyllys 		return (NULL);
311299ebb4caSwyllys 
311399ebb4caSwyllys 	if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL)
311499ebb4caSwyllys 		return (NULL);
311599ebb4caSwyllys 
311699ebb4caSwyllys 	if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) ==
311799ebb4caSwyllys 	    NULL)
311899ebb4caSwyllys 		return (NULL);
311999ebb4caSwyllys 
312099ebb4caSwyllys 	if (key->priexp.val != NULL)
312199ebb4caSwyllys 		if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len,
312299ebb4caSwyllys 		    rsa->d)) == NULL)
312399ebb4caSwyllys 			return (NULL);
312499ebb4caSwyllys 
312599ebb4caSwyllys 	if (key->prime1.val != NULL)
312699ebb4caSwyllys 		if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len,
312799ebb4caSwyllys 		    rsa->p)) == NULL)
312899ebb4caSwyllys 			return (NULL);
312999ebb4caSwyllys 
313099ebb4caSwyllys 	if (key->prime2.val != NULL)
313199ebb4caSwyllys 		if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len,
313299ebb4caSwyllys 		    rsa->q)) == NULL)
313399ebb4caSwyllys 			return (NULL);
313499ebb4caSwyllys 
313599ebb4caSwyllys 	if (key->exp1.val != NULL)
313699ebb4caSwyllys 		if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len,
313799ebb4caSwyllys 		    rsa->dmp1)) == NULL)
313899ebb4caSwyllys 			return (NULL);
313999ebb4caSwyllys 
314099ebb4caSwyllys 	if (key->exp2.val != NULL)
314199ebb4caSwyllys 		if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len,
314299ebb4caSwyllys 		    rsa->dmq1)) == NULL)
314399ebb4caSwyllys 			return (NULL);
314499ebb4caSwyllys 
314599ebb4caSwyllys 	if (key->coef.val != NULL)
314699ebb4caSwyllys 		if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len,
314799ebb4caSwyllys 		    rsa->iqmp)) == NULL)
314899ebb4caSwyllys 			return (NULL);
314999ebb4caSwyllys 
315099ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
315199ebb4caSwyllys 		return (NULL);
315299ebb4caSwyllys 
315399ebb4caSwyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
315499ebb4caSwyllys 
315599ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
315699ebb4caSwyllys 	RSA_free(rsa);
315799ebb4caSwyllys 
315899ebb4caSwyllys 	return (newkey);
315999ebb4caSwyllys }
316099ebb4caSwyllys 
316199ebb4caSwyllys static EVP_PKEY *
316299ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
316399ebb4caSwyllys {
316499ebb4caSwyllys 	DSA		*dsa = NULL;
316599ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
316699ebb4caSwyllys 
316799ebb4caSwyllys 	if ((dsa = DSA_new()) == NULL)
316899ebb4caSwyllys 		return (NULL);
316999ebb4caSwyllys 
317099ebb4caSwyllys 	if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len,
317199ebb4caSwyllys 	    dsa->p)) == NULL)
317299ebb4caSwyllys 		return (NULL);
317399ebb4caSwyllys 
317499ebb4caSwyllys 	if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len,
317599ebb4caSwyllys 	    dsa->q)) == NULL)
317699ebb4caSwyllys 		return (NULL);
317799ebb4caSwyllys 
317899ebb4caSwyllys 	if ((dsa->g = BN_bin2bn(key->base.val, key->base.len,
317999ebb4caSwyllys 	    dsa->g)) == NULL)
318099ebb4caSwyllys 		return (NULL);
318199ebb4caSwyllys 
318299ebb4caSwyllys 	if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len,
318399ebb4caSwyllys 	    dsa->priv_key)) == NULL)
318499ebb4caSwyllys 		return (NULL);
318599ebb4caSwyllys 
318630a5e8faSwyllys 	if (key->pubvalue.val != NULL) {
318730a5e8faSwyllys 		if ((dsa->pub_key = BN_bin2bn(key->pubvalue.val,
318830a5e8faSwyllys 		    key->pubvalue.len, dsa->pub_key)) == NULL)
318930a5e8faSwyllys 			return (NULL);
319030a5e8faSwyllys 	}
319130a5e8faSwyllys 
319299ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
319399ebb4caSwyllys 		return (NULL);
319499ebb4caSwyllys 
319599ebb4caSwyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
319699ebb4caSwyllys 
319799ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
319899ebb4caSwyllys 	DSA_free(dsa);
319999ebb4caSwyllys 	return (newkey);
320099ebb4caSwyllys }
320199ebb4caSwyllys 
32025b3e1433Swyllys static EVP_PKEY *
32035b3e1433Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key)
32045b3e1433Swyllys {
32055b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
32065b3e1433Swyllys 	KMF_RAW_KEY_DATA *rawkey;
32075b3e1433Swyllys 	ASN1_TYPE *attr = NULL;
32085b3e1433Swyllys 	KMF_RETURN ret;
32095b3e1433Swyllys 
32105b3e1433Swyllys 	if (key == NULL || !key->israw)
32115b3e1433Swyllys 		return (NULL);
32125b3e1433Swyllys 
32135b3e1433Swyllys 	rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
32145b3e1433Swyllys 	if (rawkey->keytype == KMF_RSA) {
32155b3e1433Swyllys 		pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
32165b3e1433Swyllys 	} else if (rawkey->keytype == KMF_DSA) {
32175b3e1433Swyllys 		pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
3218*e65e5c2dSWyllys Ingersoll 	} else if (rawkey->keytype == KMF_ECDSA) {
3219*e65e5c2dSWyllys Ingersoll 		/*
3220*e65e5c2dSWyllys Ingersoll 		 * OpenSSL in Solaris does not support EC for
3221*e65e5c2dSWyllys Ingersoll 		 * legal reasons
3222*e65e5c2dSWyllys Ingersoll 		 */
3223*e65e5c2dSWyllys Ingersoll 		return (NULL);
32245b3e1433Swyllys 	} else {
32255b3e1433Swyllys 		/* wrong kind of key */
32265b3e1433Swyllys 		return (NULL);
32275b3e1433Swyllys 	}
32285b3e1433Swyllys 
32295b3e1433Swyllys 	if (rawkey->label != NULL) {
32305b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
32315b3e1433Swyllys 			EVP_PKEY_free(pkey);
32325b3e1433Swyllys 			return (NULL);
32335b3e1433Swyllys 		}
32345b3e1433Swyllys 		attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
32355b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
32365b3e1433Swyllys 		    strlen(rawkey->label));
32375b3e1433Swyllys 		attr->type = V_ASN1_BMPSTRING;
32385b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.bmpstring;
32395b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
32405b3e1433Swyllys 		if (ret != KMF_OK) {
32415b3e1433Swyllys 			EVP_PKEY_free(pkey);
32425b3e1433Swyllys 			ASN1_TYPE_free(attr);
32435b3e1433Swyllys 			return (NULL);
32445b3e1433Swyllys 		}
32455b3e1433Swyllys 	}
32465b3e1433Swyllys 	if (rawkey->id.Data != NULL) {
32475b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
32485b3e1433Swyllys 			EVP_PKEY_free(pkey);
32495b3e1433Swyllys 			return (NULL);
32505b3e1433Swyllys 		}
32515b3e1433Swyllys 		attr->value.octet_string =
32525b3e1433Swyllys 		    ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
32535b3e1433Swyllys 		attr->type = V_ASN1_OCTET_STRING;
32545b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.octet_string,
32555b3e1433Swyllys 		    rawkey->id.Data, rawkey->id.Length);
32565b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.octet_string;
32575b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
32585b3e1433Swyllys 		if (ret != KMF_OK) {
32595b3e1433Swyllys 			EVP_PKEY_free(pkey);
32605b3e1433Swyllys 			ASN1_TYPE_free(attr);
32615b3e1433Swyllys 			return (NULL);
32625b3e1433Swyllys 		}
32635b3e1433Swyllys 	}
32645b3e1433Swyllys 	return (pkey);
32655b3e1433Swyllys }
32665b3e1433Swyllys 
32675b3e1433Swyllys /*
32685b3e1433Swyllys  * Search a list of private keys to find one that goes with the certificate.
32695b3e1433Swyllys  */
32705b3e1433Swyllys static EVP_PKEY *
32715b3e1433Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
32725b3e1433Swyllys {
32735b3e1433Swyllys 	int i;
32745b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
32755b3e1433Swyllys 
32765b3e1433Swyllys 	if (numkeys == 0 || keylist == NULL || xcert == NULL)
32775b3e1433Swyllys 		return (NULL);
32785b3e1433Swyllys 	for (i = 0; i < numkeys; i++) {
32795b3e1433Swyllys 		if (keylist[i].israw)
32805b3e1433Swyllys 			pkey = raw_key_to_pkey(&keylist[i]);
32815b3e1433Swyllys 		else
32825b3e1433Swyllys 			pkey = (EVP_PKEY *)keylist[i].keyp;
32835b3e1433Swyllys 		if (pkey != NULL) {
32845b3e1433Swyllys 			if (X509_check_private_key(xcert, pkey)) {
32855b3e1433Swyllys 				return (pkey);
32865b3e1433Swyllys 			} else {
32875b3e1433Swyllys 				EVP_PKEY_free(pkey);
32885b3e1433Swyllys 				pkey = NULL;
32895b3e1433Swyllys 			}
32905b3e1433Swyllys 		}
32915b3e1433Swyllys 	}
32925b3e1433Swyllys 	return (pkey);
32935b3e1433Swyllys }
32945b3e1433Swyllys 
329599ebb4caSwyllys static KMF_RETURN
32965b3e1433Swyllys local_export_pk12(KMF_HANDLE_T handle,
329799ebb4caSwyllys 	KMF_CREDENTIAL *cred,
329899ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
329999ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
330099ebb4caSwyllys 	char *filename)
330199ebb4caSwyllys {
330299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
330399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
330499ebb4caSwyllys 	BIO *bio = NULL;
33055b3e1433Swyllys 	PKCS7 *cert_authsafe = NULL;
33065b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
33075b3e1433Swyllys 	STACK_OF(PKCS7) *authsafe_stack = NULL;
33085b3e1433Swyllys 	PKCS12 *p12_elem = NULL;
330999ebb4caSwyllys 	int i;
331099ebb4caSwyllys 
33115b3e1433Swyllys 	if (numcerts == 0 && numkeys == 0)
33125b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
33135b3e1433Swyllys 
331499ebb4caSwyllys 	/*
331599ebb4caSwyllys 	 * Open the output file.
331699ebb4caSwyllys 	 */
331799ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
331899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
331999ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
332099ebb4caSwyllys 		goto cleanup;
332199ebb4caSwyllys 	}
332299ebb4caSwyllys 
33235b3e1433Swyllys 	/* Start a PKCS#7 stack. */
33245b3e1433Swyllys 	authsafe_stack = sk_PKCS7_new_null();
33255b3e1433Swyllys 	if (authsafe_stack == NULL) {
33265b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
33275b3e1433Swyllys 		goto cleanup;
33285b3e1433Swyllys 	}
33295b3e1433Swyllys 	if (numcerts > 0) {
333099ebb4caSwyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
333199ebb4caSwyllys 			const uchar_t *p = certlist[i].certificate.Data;
333299ebb4caSwyllys 			long len = certlist[i].certificate.Length;
33335b3e1433Swyllys 			X509 *xcert = NULL;
33345b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
33355b3e1433Swyllys 			unsigned char keyid[EVP_MAX_MD_SIZE];
33365b3e1433Swyllys 			unsigned int keyidlen = 0;
333799ebb4caSwyllys 
333899ebb4caSwyllys 			xcert = d2i_X509(NULL, &p, len);
333999ebb4caSwyllys 			if (xcert == NULL) {
334099ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
334199ebb4caSwyllys 				rv = KMF_ERR_ENCODING;
334299ebb4caSwyllys 			}
33435b3e1433Swyllys 			if (certlist[i].kmf_private.label != NULL) {
33445b3e1433Swyllys 				/* Set alias attribute */
33455b3e1433Swyllys 				(void) X509_alias_set1(xcert,
33465b3e1433Swyllys 				    (uchar_t *)certlist[i].kmf_private.label,
33475b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label));
33485b3e1433Swyllys 			}
33495b3e1433Swyllys 			/* Check if there is a key corresponding to this cert */
33505b3e1433Swyllys 			pkey = find_matching_key(xcert, numkeys, keylist);
33515b3e1433Swyllys 
33525b3e1433Swyllys 			/*
33535b3e1433Swyllys 			 * If key is found, get fingerprint and create a
33545b3e1433Swyllys 			 * safebag.
33555b3e1433Swyllys 			 */
33565b3e1433Swyllys 			if (pkey != NULL) {
33575b3e1433Swyllys 				(void) X509_digest(xcert, EVP_sha1(),
33585b3e1433Swyllys 				    keyid, &keyidlen);
33595b3e1433Swyllys 				key_authsafe = add_key_to_safe(pkey, cred,
33605b3e1433Swyllys 				    keyid, keyidlen,
33615b3e1433Swyllys 				    certlist[i].kmf_private.label,
33625b3e1433Swyllys 				    (certlist[i].kmf_private.label ?
33635b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label) : 0));
33645b3e1433Swyllys 
33655b3e1433Swyllys 				if (key_authsafe == NULL) {
33665b3e1433Swyllys 					X509_free(xcert);
33675b3e1433Swyllys 					EVP_PKEY_free(pkey);
33685b3e1433Swyllys 					goto cleanup;
33695b3e1433Swyllys 				}
33705b3e1433Swyllys 				/* Put the key safe into the Auth Safe */
33715b3e1433Swyllys 				if (!sk_PKCS7_push(authsafe_stack,
33725b3e1433Swyllys 				    key_authsafe)) {
33735b3e1433Swyllys 					X509_free(xcert);
33745b3e1433Swyllys 					EVP_PKEY_free(pkey);
33755b3e1433Swyllys 					goto cleanup;
33765b3e1433Swyllys 				}
33775b3e1433Swyllys 			}
33785b3e1433Swyllys 
33795b3e1433Swyllys 			/* create a certificate safebag */
33805b3e1433Swyllys 			cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
33815b3e1433Swyllys 			    keyidlen);
33825b3e1433Swyllys 			if (cert_authsafe == NULL) {
33835b3e1433Swyllys 				X509_free(xcert);
33845b3e1433Swyllys 				EVP_PKEY_free(pkey);
33855b3e1433Swyllys 				goto cleanup;
33865b3e1433Swyllys 			}
33875b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
33885b3e1433Swyllys 				X509_free(xcert);
33895b3e1433Swyllys 				EVP_PKEY_free(pkey);
33905b3e1433Swyllys 				goto cleanup;
33915b3e1433Swyllys 			}
33925b3e1433Swyllys 
339399ebb4caSwyllys 			X509_free(xcert);
339499ebb4caSwyllys 			if (pkey)
339599ebb4caSwyllys 				EVP_PKEY_free(pkey);
339699ebb4caSwyllys 		}
33975b3e1433Swyllys 	} else if (numcerts == 0 && numkeys > 0) {
33985b3e1433Swyllys 		/*
33995b3e1433Swyllys 		 * If only adding keys to the file.
34005b3e1433Swyllys 		 */
34015b3e1433Swyllys 		for (i = 0; i < numkeys; i++) {
34025b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
34035b3e1433Swyllys 
34045b3e1433Swyllys 			if (keylist[i].israw)
34055b3e1433Swyllys 				pkey = raw_key_to_pkey(&keylist[i]);
34065b3e1433Swyllys 			else
34075b3e1433Swyllys 				pkey = (EVP_PKEY *)keylist[i].keyp;
34085b3e1433Swyllys 
34095b3e1433Swyllys 			if (pkey == NULL)
34105b3e1433Swyllys 				continue;
34115b3e1433Swyllys 
34125b3e1433Swyllys 			key_authsafe = add_key_to_safe(pkey, cred,
34135b3e1433Swyllys 			    NULL, 0, NULL, 0);
34145b3e1433Swyllys 
34155b3e1433Swyllys 			if (key_authsafe == NULL) {
34165b3e1433Swyllys 				EVP_PKEY_free(pkey);
34175b3e1433Swyllys 				goto cleanup;
34185b3e1433Swyllys 			}
34195b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
34205b3e1433Swyllys 				EVP_PKEY_free(pkey);
34215b3e1433Swyllys 				goto cleanup;
34225b3e1433Swyllys 			}
34235b3e1433Swyllys 		}
34245b3e1433Swyllys 	}
34255b3e1433Swyllys 	p12_elem = PKCS12_init(NID_pkcs7_data);
34265b3e1433Swyllys 	if (p12_elem == NULL) {
34275b3e1433Swyllys 		goto cleanup;
342899ebb4caSwyllys 	}
342999ebb4caSwyllys 
34305b3e1433Swyllys 	/* Put the PKCS#7 stack into the PKCS#12 element. */
34315b3e1433Swyllys 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
34325b3e1433Swyllys 		goto cleanup;
34335b3e1433Swyllys 	}
34345b3e1433Swyllys 
34355b3e1433Swyllys 	/* Set the integrity MAC on the PKCS#12 element. */
34365b3e1433Swyllys 	if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
34375b3e1433Swyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
34385b3e1433Swyllys 		goto cleanup;
34395b3e1433Swyllys 	}
34405b3e1433Swyllys 
34415b3e1433Swyllys 	/* Write the PKCS#12 element to the export file. */
34425b3e1433Swyllys 	if (!i2d_PKCS12_bio(bio, p12_elem)) {
34435b3e1433Swyllys 		goto cleanup;
34445b3e1433Swyllys 	}
34455b3e1433Swyllys 	PKCS12_free(p12_elem);
34465b3e1433Swyllys 
344799ebb4caSwyllys cleanup:
34485b3e1433Swyllys 	/* Clear away the PKCS#7 stack, we're done with it. */
34495b3e1433Swyllys 	if (authsafe_stack)
34505b3e1433Swyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
345199ebb4caSwyllys 
345299ebb4caSwyllys 	if (bio != NULL)
345399ebb4caSwyllys 		(void) BIO_free_all(bio);
345499ebb4caSwyllys 
345599ebb4caSwyllys 	return (rv);
345699ebb4caSwyllys }
345799ebb4caSwyllys 
345899ebb4caSwyllys KMF_RETURN
345930a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
346030a5e8faSwyllys     KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
346130a5e8faSwyllys     KMF_CREDENTIAL *p12cred, char *filename)
346230a5e8faSwyllys {
346330a5e8faSwyllys 	KMF_RETURN rv;
346430a5e8faSwyllys 
346530a5e8faSwyllys 	if (certlist == NULL && keylist == NULL)
346630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
346730a5e8faSwyllys 
34685b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, numcerts, certlist,
346930a5e8faSwyllys 	    numkeys, keylist, filename);
347030a5e8faSwyllys 
347130a5e8faSwyllys 	return (rv);
347230a5e8faSwyllys }
347330a5e8faSwyllys 
347430a5e8faSwyllys KMF_RETURN
347530a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
347699ebb4caSwyllys {
347799ebb4caSwyllys 	KMF_RETURN rv;
347899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
347999ebb4caSwyllys 	char *fullpath = NULL;
348030a5e8faSwyllys 	char *dirpath = NULL;
348130a5e8faSwyllys 	char *certfile = NULL;
348230a5e8faSwyllys 	char *keyfile = NULL;
348330a5e8faSwyllys 	char *filename = NULL;
348430a5e8faSwyllys 	KMF_CREDENTIAL *p12cred = NULL;
34855b3e1433Swyllys 	KMF_X509_DER_CERT certdata;
34865b3e1433Swyllys 	KMF_KEY_HANDLE key;
34875b3e1433Swyllys 	int gotkey = 0;
34885b3e1433Swyllys 	int gotcert = 0;
348930a5e8faSwyllys 
349030a5e8faSwyllys 	if (handle == NULL)
349130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
349299ebb4caSwyllys 
349399ebb4caSwyllys 	/*
349499ebb4caSwyllys 	 *  First, find the certificate.
349599ebb4caSwyllys 	 */
349630a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
349730a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
349830a5e8faSwyllys 	if (certfile != NULL) {
349930a5e8faSwyllys 		fullpath = get_fullpath(dirpath, certfile);
350099ebb4caSwyllys 		if (fullpath == NULL)
350199ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
350299ebb4caSwyllys 
350399ebb4caSwyllys 		if (isdir(fullpath)) {
350499ebb4caSwyllys 			free(fullpath);
350599ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
350699ebb4caSwyllys 		}
350799ebb4caSwyllys 
35085b3e1433Swyllys 		(void) memset(&certdata, 0, sizeof (certdata));
35095b3e1433Swyllys 		rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL,
35105b3e1433Swyllys 		    fullpath, &certdata.certificate);
351199ebb4caSwyllys 		if (rv != KMF_OK)
351299ebb4caSwyllys 			goto end;
351330a5e8faSwyllys 
35145b3e1433Swyllys 		gotcert++;
35155b3e1433Swyllys 		certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
351630a5e8faSwyllys 		free(fullpath);
351799ebb4caSwyllys 	}
351899ebb4caSwyllys 
351999ebb4caSwyllys 	/*
352099ebb4caSwyllys 	 * Now find the private key.
352199ebb4caSwyllys 	 */
352230a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
352330a5e8faSwyllys 	if (keyfile != NULL) {
352430a5e8faSwyllys 		fullpath = get_fullpath(dirpath, keyfile);
352599ebb4caSwyllys 		if (fullpath == NULL)
352699ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
352799ebb4caSwyllys 
352899ebb4caSwyllys 		if (isdir(fullpath)) {
352999ebb4caSwyllys 			free(fullpath);
353099ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
353199ebb4caSwyllys 		}
353299ebb4caSwyllys 
35335b3e1433Swyllys 		(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
35345b3e1433Swyllys 		rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
35355b3e1433Swyllys 		if (rv != KMF_OK)
353699ebb4caSwyllys 			goto end;
35375b3e1433Swyllys 		gotkey++;
353899ebb4caSwyllys 	}
353999ebb4caSwyllys 
354099ebb4caSwyllys 	/*
354199ebb4caSwyllys 	 * Open the output file.
354299ebb4caSwyllys 	 */
354330a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
354430a5e8faSwyllys 	    numattr);
354530a5e8faSwyllys 	if (filename == NULL) {
354630a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
354730a5e8faSwyllys 		goto end;
354830a5e8faSwyllys 	}
354930a5e8faSwyllys 
355099ebb4caSwyllys 	/* Stick the key and the cert into a PKCS#12 file */
355130a5e8faSwyllys 	p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
355230a5e8faSwyllys 	if (p12cred == NULL) {
355330a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
355430a5e8faSwyllys 		goto end;
355530a5e8faSwyllys 	}
355630a5e8faSwyllys 
35575b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, 1, &certdata,
35585b3e1433Swyllys 	    1, &key, filename);
355999ebb4caSwyllys 
356099ebb4caSwyllys end:
356199ebb4caSwyllys 	if (fullpath)
356299ebb4caSwyllys 		free(fullpath);
356399ebb4caSwyllys 
35645b3e1433Swyllys 	if (gotcert)
35655b3e1433Swyllys 		kmf_free_kmf_cert(handle, &certdata);
35665b3e1433Swyllys 	if (gotkey)
35675b3e1433Swyllys 		kmf_free_kmf_key(handle, &key);
356899ebb4caSwyllys 	return (rv);
356999ebb4caSwyllys }
357099ebb4caSwyllys 
357171593db2Swyllys /*
357271593db2Swyllys  * Helper function to extract keys and certificates from
357371593db2Swyllys  * a single PEM file.  Typically the file should contain a
357471593db2Swyllys  * private key and an associated public key wrapped in an x509 cert.
357571593db2Swyllys  * However, the file may be just a list of X509 certs with no keys.
357671593db2Swyllys  */
357771593db2Swyllys static KMF_RETURN
357830a5e8faSwyllys extract_pem(KMF_HANDLE *kmfh,
357930a5e8faSwyllys 	char *issuer, char *subject, KMF_BIGINT *serial,
358002744e81Swyllys 	char *filename, CK_UTF8CHAR *pin,
358171593db2Swyllys 	CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
358271593db2Swyllys 	int *numcerts)
3583a2d4930dSDan OpenSolaris Anderson /* ARGSUSED6 */
358471593db2Swyllys {
358571593db2Swyllys 	KMF_RETURN rv = KMF_OK;
358671593db2Swyllys 	FILE *fp;
358734acef67Swyllys 	STACK_OF(X509_INFO) *x509_info_stack = NULL;
358802744e81Swyllys 	int i, ncerts = 0, matchcerts = 0;
358971593db2Swyllys 	EVP_PKEY *pkey = NULL;
359071593db2Swyllys 	X509_INFO *info;
359171593db2Swyllys 	X509 *x;
35925b3e1433Swyllys 	X509_INFO **cert_infos = NULL;
359371593db2Swyllys 	KMF_DATA *certlist = NULL;
359471593db2Swyllys 
359571593db2Swyllys 	if (priv_key)
359671593db2Swyllys 		*priv_key = NULL;
359771593db2Swyllys 	if (certs)
359871593db2Swyllys 		*certs = NULL;
359971593db2Swyllys 	fp = fopen(filename, "r");
36005b3e1433Swyllys 	if (fp == NULL)
360171593db2Swyllys 		return (KMF_ERR_OPEN_FILE);
36025b3e1433Swyllys 
360371593db2Swyllys 	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
360471593db2Swyllys 	if (x509_info_stack == NULL) {
360571593db2Swyllys 		(void) fclose(fp);
360671593db2Swyllys 		return (KMF_ERR_ENCODING);
360771593db2Swyllys 	}
36085b3e1433Swyllys 	cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
36095b3e1433Swyllys 	    sizeof (X509_INFO *));
36105b3e1433Swyllys 	if (cert_infos == NULL) {
36115b3e1433Swyllys 		(void) fclose(fp);
36125b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
36135b3e1433Swyllys 		goto err;
36145b3e1433Swyllys 	}
361571593db2Swyllys 
36165b3e1433Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3617a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
361834acef67Swyllys 		cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
361971593db2Swyllys 		ncerts++;
362071593db2Swyllys 	}
362171593db2Swyllys 
362271593db2Swyllys 	if (ncerts == 0) {
362371593db2Swyllys 		(void) fclose(fp);
362434acef67Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
362534acef67Swyllys 		goto err;
362671593db2Swyllys 	}
362771593db2Swyllys 
362871593db2Swyllys 	if (priv_key != NULL) {
362971593db2Swyllys 		rewind(fp);
363071593db2Swyllys 		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
363171593db2Swyllys 	}
363271593db2Swyllys 	(void) fclose(fp);
363371593db2Swyllys 
363471593db2Swyllys 	x = cert_infos[ncerts - 1]->x509;
363571593db2Swyllys 	/*
363671593db2Swyllys 	 * Make sure the private key matchs the last cert in the file.
363771593db2Swyllys 	 */
363871593db2Swyllys 	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
363971593db2Swyllys 		EVP_PKEY_free(pkey);
364034acef67Swyllys 		rv = KMF_ERR_KEY_MISMATCH;
364134acef67Swyllys 		goto err;
364271593db2Swyllys 	}
364371593db2Swyllys 
3644a2d4930dSDan OpenSolaris Anderson 	certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
364571593db2Swyllys 	if (certlist == NULL) {
364671593db2Swyllys 		if (pkey != NULL)
364771593db2Swyllys 			EVP_PKEY_free(pkey);
364834acef67Swyllys 		rv = KMF_ERR_MEMORY;
364934acef67Swyllys 		goto err;
365071593db2Swyllys 	}
365171593db2Swyllys 
365271593db2Swyllys 	/*
365371593db2Swyllys 	 * Convert all of the certs to DER format.
365471593db2Swyllys 	 */
365502744e81Swyllys 	matchcerts = 0;
365671593db2Swyllys 	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
365702744e81Swyllys 		boolean_t match = FALSE;
365871593db2Swyllys 		info =  cert_infos[ncerts - 1 - i];
365971593db2Swyllys 
366030a5e8faSwyllys 		rv = check_cert(info->x509, issuer, subject, serial, &match);
366102744e81Swyllys 		if (rv != KMF_OK || match != TRUE) {
366202744e81Swyllys 			rv = KMF_OK;
366302744e81Swyllys 			continue;
366402744e81Swyllys 		}
366502744e81Swyllys 
366602744e81Swyllys 		rv = ssl_cert2KMFDATA(kmfh, info->x509,
366702744e81Swyllys 			&certlist[matchcerts++]);
366871593db2Swyllys 
366971593db2Swyllys 		if (rv != KMF_OK) {
3670*e65e5c2dSWyllys Ingersoll 			int j;
3671*e65e5c2dSWyllys Ingersoll 			for (j = 0; j < matchcerts; j++)
3672*e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certlist[j]);
367371593db2Swyllys 			free(certlist);
367471593db2Swyllys 			certlist = NULL;
367502744e81Swyllys 			ncerts = matchcerts = 0;
367671593db2Swyllys 		}
367771593db2Swyllys 	}
367871593db2Swyllys 
367971593db2Swyllys 	if (numcerts != NULL)
368002744e81Swyllys 		*numcerts = matchcerts;
3681a2d4930dSDan OpenSolaris Anderson 
3682*e65e5c2dSWyllys Ingersoll 	if (certs != NULL)
368371593db2Swyllys 		*certs = certlist;
3684*e65e5c2dSWyllys Ingersoll 	else if (certlist != NULL) {
3685*e65e5c2dSWyllys Ingersoll 		for (i = 0; i < ncerts; i++)
3686*e65e5c2dSWyllys Ingersoll 			kmf_free_data(&certlist[i]);
3687a2d4930dSDan OpenSolaris Anderson 		free(certlist);
3688a2d4930dSDan OpenSolaris Anderson 		certlist = NULL;
3689a2d4930dSDan OpenSolaris Anderson 	}
369071593db2Swyllys 
369171593db2Swyllys 	if (priv_key == NULL && pkey != NULL)
369271593db2Swyllys 		EVP_PKEY_free(pkey);
369371593db2Swyllys 	else if (priv_key != NULL && pkey != NULL)
369471593db2Swyllys 		*priv_key = pkey;
369571593db2Swyllys 
369634acef67Swyllys err:
369734acef67Swyllys 	/* Cleanup the stack of X509 info records */
369834acef67Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3699a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
370034acef67Swyllys 		info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
370134acef67Swyllys 		X509_INFO_free(info);
370234acef67Swyllys 	}
370334acef67Swyllys 	if (x509_info_stack)
370434acef67Swyllys 		sk_X509_INFO_free(x509_info_stack);
370534acef67Swyllys 
37065b3e1433Swyllys 	if (cert_infos != NULL)
37075b3e1433Swyllys 		free(cert_infos);
37085b3e1433Swyllys 
370971593db2Swyllys 	return (rv);
371071593db2Swyllys }
371171593db2Swyllys 
37125b3e1433Swyllys static KMF_RETURN
37135b3e1433Swyllys openssl_parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
37145b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
37155b3e1433Swyllys {
37165b3e1433Swyllys 	KMF_RETURN ret;
37175b3e1433Swyllys 	int i;
37185b3e1433Swyllys 
37195b3e1433Swyllys 	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
3720a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
37215b3e1433Swyllys 		PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
37225b3e1433Swyllys 		ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
37235b3e1433Swyllys 		    keys, certs);
37245b3e1433Swyllys 
37255b3e1433Swyllys 		if (ret != KMF_OK)
37265b3e1433Swyllys 			return (ret);
37275b3e1433Swyllys 	}
37285b3e1433Swyllys 
37295b3e1433Swyllys 	return (ret);
37305b3e1433Swyllys }
37315b3e1433Swyllys 
37325b3e1433Swyllys static KMF_RETURN
37335b3e1433Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
37345b3e1433Swyllys {
37355b3e1433Swyllys 	X509_ATTRIBUTE *attr = NULL;
37365b3e1433Swyllys 
37375b3e1433Swyllys 	if (pkey == NULL || attrib == NULL)
37385b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
37395b3e1433Swyllys 
37405b3e1433Swyllys 	if (pkey->attributes == NULL) {
37415b3e1433Swyllys 		pkey->attributes = sk_X509_ATTRIBUTE_new_null();
37425b3e1433Swyllys 		if (pkey->attributes == NULL)
37435b3e1433Swyllys 			return (KMF_ERR_MEMORY);
37445b3e1433Swyllys 	}
37455b3e1433Swyllys 	attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
37465b3e1433Swyllys 	if (attr != NULL) {
37475b3e1433Swyllys 		int i;
37485b3e1433Swyllys 		X509_ATTRIBUTE *a;
37495b3e1433Swyllys 		for (i = 0;
37505b3e1433Swyllys 		    i < sk_X509_ATTRIBUTE_num(pkey->attributes); i++) {
3751*e65e5c2dSWyllys Ingersoll 			/* LINTED E_BAD_PTR_CASE_ALIGN */
37525b3e1433Swyllys 			a = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
37535b3e1433Swyllys 			if (OBJ_obj2nid(a->object) == nid) {
37545b3e1433Swyllys 				X509_ATTRIBUTE_free(a);
3755a2d4930dSDan OpenSolaris Anderson 				/* LINTED E_BAD_PTR_CAST_ALIGN */
37565b3e1433Swyllys 				sk_X509_ATTRIBUTE_set(pkey->attributes,
37575b3e1433Swyllys 				    i, attr);
37585b3e1433Swyllys 				return (KMF_OK);
37595b3e1433Swyllys 			}
37605b3e1433Swyllys 		}
37615b3e1433Swyllys 		if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == NULL) {
37625b3e1433Swyllys 			X509_ATTRIBUTE_free(attr);
37635b3e1433Swyllys 			return (KMF_ERR_MEMORY);
37645b3e1433Swyllys 		}
37655b3e1433Swyllys 	} else {
37665b3e1433Swyllys 		return (KMF_ERR_MEMORY);
37675b3e1433Swyllys 	}
37685b3e1433Swyllys 
37695b3e1433Swyllys 	return (KMF_OK);
37705b3e1433Swyllys }
37715b3e1433Swyllys 
37725b3e1433Swyllys static KMF_RETURN
37735b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
37745b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
37755b3e1433Swyllys {
37765b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
37775b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
37785b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
37795b3e1433Swyllys 	X509 *xcert = NULL;
37805b3e1433Swyllys 	ASN1_TYPE *keyid = NULL;
37815b3e1433Swyllys 	ASN1_TYPE *fname = NULL;
37825b3e1433Swyllys 	uchar_t *data = NULL;
37835b3e1433Swyllys 
37845b3e1433Swyllys 	keyid = PKCS12_get_attr(bag, NID_localKeyID);
37855b3e1433Swyllys 	fname = PKCS12_get_attr(bag, NID_friendlyName);
37865b3e1433Swyllys 
37875b3e1433Swyllys 	switch (M_PKCS12_bag_type(bag)) {
37885b3e1433Swyllys 		case NID_keyBag:
37895b3e1433Swyllys 			if (keylist == NULL)
37905b3e1433Swyllys 				goto end;
37915b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(bag->value.keybag);
37925b3e1433Swyllys 			if (pkey == NULL)
37935b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
37945b3e1433Swyllys 
37955b3e1433Swyllys 			break;
37965b3e1433Swyllys 		case NID_pkcs8ShroudedKeyBag:
37975b3e1433Swyllys 			if (keylist == NULL)
37985b3e1433Swyllys 				goto end;
37995b3e1433Swyllys 			p8 = M_PKCS12_decrypt_skey(bag, pass, passlen);
38005b3e1433Swyllys 			if (p8 == NULL)
38015b3e1433Swyllys 				return (KMF_ERR_AUTH_FAILED);
38025b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(p8);
38035b3e1433Swyllys 			PKCS8_PRIV_KEY_INFO_free(p8);
38045b3e1433Swyllys 			if (pkey == NULL)
38055b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38065b3e1433Swyllys 			break;
38075b3e1433Swyllys 		case NID_certBag:
38085b3e1433Swyllys 			if (certlist == NULL)
38095b3e1433Swyllys 				goto end;
38105b3e1433Swyllys 			if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate)
38115b3e1433Swyllys 				return (KMF_ERR_PKCS12_FORMAT);
38125b3e1433Swyllys 			xcert = M_PKCS12_certbag2x509(bag);
38135b3e1433Swyllys 			if (xcert == NULL) {
38145b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38155b3e1433Swyllys 				goto end;
38165b3e1433Swyllys 			}
38175b3e1433Swyllys 			if (keyid != NULL) {
38185b3e1433Swyllys 				if (X509_keyid_set1(xcert,
38195b3e1433Swyllys 				    keyid->value.octet_string->data,
38205b3e1433Swyllys 				    keyid->value.octet_string->length) == 0) {
38215b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
38225b3e1433Swyllys 					goto end;
38235b3e1433Swyllys 				}
38245b3e1433Swyllys 			}
38255b3e1433Swyllys 			if (fname != NULL) {
38265b3e1433Swyllys 				int len, r;
38275b3e1433Swyllys 				len = ASN1_STRING_to_UTF8(&data,
38285b3e1433Swyllys 				    fname->value.asn1_string);
38295b3e1433Swyllys 				if (len > 0 && data != NULL) {
38305b3e1433Swyllys 					r = X509_alias_set1(xcert, data, len);
38315b3e1433Swyllys 					if (r == NULL) {
38325b3e1433Swyllys 						ret = KMF_ERR_PKCS12_FORMAT;
38335b3e1433Swyllys 						goto end;
38345b3e1433Swyllys 					}
38355b3e1433Swyllys 				} else {
38365b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
38375b3e1433Swyllys 					goto end;
38385b3e1433Swyllys 				}
38395b3e1433Swyllys 			}
38405b3e1433Swyllys 			if (sk_X509_push(certlist, xcert) == 0)
38415b3e1433Swyllys 				ret = KMF_ERR_MEMORY;
38425b3e1433Swyllys 			else
38435b3e1433Swyllys 				xcert = NULL;
38445b3e1433Swyllys 			break;
38455b3e1433Swyllys 		case NID_safeContentsBag:
38465b3e1433Swyllys 			return (openssl_parse_bags(bag->value.safes, pass,
38475b3e1433Swyllys 			    keylist, certlist));
38485b3e1433Swyllys 		default:
38495b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
38505b3e1433Swyllys 			break;
38515b3e1433Swyllys 	}
38525b3e1433Swyllys 
38535b3e1433Swyllys 	/*
38545b3e1433Swyllys 	 * Set the ID and/or FriendlyName attributes on the key.
38555b3e1433Swyllys 	 * If converting to PKCS11 objects, these can translate to CKA_ID
38565b3e1433Swyllys 	 * and CKA_LABEL values.
38575b3e1433Swyllys 	 */
38585b3e1433Swyllys 	if (pkey != NULL && ret == KMF_OK) {
38595b3e1433Swyllys 		ASN1_TYPE *attr = NULL;
38605b3e1433Swyllys 		if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
38615b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
38625b3e1433Swyllys 				return (KMF_ERR_MEMORY);
38635b3e1433Swyllys 			attr->value.octet_string =
38645b3e1433Swyllys 			    ASN1_STRING_dup(keyid->value.octet_string);
38655b3e1433Swyllys 			attr->type = V_ASN1_OCTET_STRING;
38665b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.octet_string;
38675b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
38685b3e1433Swyllys 			OPENSSL_free(attr);
38695b3e1433Swyllys 		}
38705b3e1433Swyllys 
38715b3e1433Swyllys 		if (ret == KMF_OK && fname != NULL &&
38725b3e1433Swyllys 		    fname->type == V_ASN1_BMPSTRING) {
38735b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
38745b3e1433Swyllys 				return (KMF_ERR_MEMORY);
38755b3e1433Swyllys 			attr->value.bmpstring =
38765b3e1433Swyllys 			    ASN1_STRING_dup(fname->value.bmpstring);
38775b3e1433Swyllys 			attr->type = V_ASN1_BMPSTRING;
38785b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.bmpstring;
38795b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
38805b3e1433Swyllys 			OPENSSL_free(attr);
38815b3e1433Swyllys 		}
38825b3e1433Swyllys 
38835b3e1433Swyllys 		if (ret == KMF_OK && keylist != NULL &&
38845b3e1433Swyllys 		    sk_EVP_PKEY_push(keylist, pkey) == 0)
38855b3e1433Swyllys 			ret = KMF_ERR_MEMORY;
38865b3e1433Swyllys 	}
38875b3e1433Swyllys 	if (ret == KMF_OK && keylist != NULL)
38885b3e1433Swyllys 		pkey = NULL;
38895b3e1433Swyllys end:
38905b3e1433Swyllys 	if (pkey != NULL)
38915b3e1433Swyllys 		EVP_PKEY_free(pkey);
38925b3e1433Swyllys 	if (xcert != NULL)
38935b3e1433Swyllys 		X509_free(xcert);
38945b3e1433Swyllys 	if (data != NULL)
38955b3e1433Swyllys 		OPENSSL_free(data);
38965b3e1433Swyllys 
38975b3e1433Swyllys 	return (ret);
38985b3e1433Swyllys }
38995b3e1433Swyllys 
39005b3e1433Swyllys static KMF_RETURN
39015b3e1433Swyllys openssl_pkcs12_parse(PKCS12 *p12, char *pin,
39025b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys,
39035b3e1433Swyllys 	STACK_OF(X509) *certs,
39045b3e1433Swyllys 	STACK_OF(X509) *ca)
3905a2d4930dSDan OpenSolaris Anderson /* ARGSUSED3 */
39065b3e1433Swyllys {
39075b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
39085b3e1433Swyllys 	STACK_OF(PKCS7) *asafes = NULL;
39095b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
39105b3e1433Swyllys 	int i, bagnid;
39115b3e1433Swyllys 	PKCS7 *p7;
39125b3e1433Swyllys 
39135b3e1433Swyllys 	if (p12 == NULL || (keys == NULL && certs == NULL))
39145b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
39155b3e1433Swyllys 
39165b3e1433Swyllys 	if (pin == NULL || *pin == NULL) {
39175b3e1433Swyllys 		if (PKCS12_verify_mac(p12, NULL, 0)) {
39185b3e1433Swyllys 			pin = NULL;
39195b3e1433Swyllys 		} else if (PKCS12_verify_mac(p12, "", 0)) {
39205b3e1433Swyllys 			pin = "";
39215b3e1433Swyllys 		} else {
39225b3e1433Swyllys 			return (KMF_ERR_AUTH_FAILED);
39235b3e1433Swyllys 		}
39245b3e1433Swyllys 	} else if (!PKCS12_verify_mac(p12, pin, -1)) {
39255b3e1433Swyllys 		return (KMF_ERR_AUTH_FAILED);
39265b3e1433Swyllys 	}
39275b3e1433Swyllys 
39285b3e1433Swyllys 	if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
39295b3e1433Swyllys 		return (KMF_ERR_PKCS12_FORMAT);
39305b3e1433Swyllys 
39315b3e1433Swyllys 	for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
39325b3e1433Swyllys 		bags = NULL;
3933a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
39345b3e1433Swyllys 		p7 = sk_PKCS7_value(asafes, i);
39355b3e1433Swyllys 		bagnid = OBJ_obj2nid(p7->type);
39365b3e1433Swyllys 
39375b3e1433Swyllys 		if (bagnid == NID_pkcs7_data) {
39385b3e1433Swyllys 			bags = PKCS12_unpack_p7data(p7);
39395b3e1433Swyllys 		} else if (bagnid == NID_pkcs7_encrypted) {
39405b3e1433Swyllys 			bags = PKCS12_unpack_p7encdata(p7, pin,
39415b3e1433Swyllys 			    (pin ? strlen(pin) : 0));
39425b3e1433Swyllys 		} else {
39435b3e1433Swyllys 			continue;
39445b3e1433Swyllys 		}
39455b3e1433Swyllys 		if (bags == NULL) {
39465b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39475b3e1433Swyllys 			goto out;
39485b3e1433Swyllys 		}
39495b3e1433Swyllys 
39505b3e1433Swyllys 		if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
39515b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39525b3e1433Swyllys 
39535b3e1433Swyllys 		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
39545b3e1433Swyllys 	}
39555b3e1433Swyllys out:
39565b3e1433Swyllys 	if (asafes != NULL)
39575b3e1433Swyllys 		sk_PKCS7_pop_free(asafes, PKCS7_free);
39585b3e1433Swyllys 
39595b3e1433Swyllys 	return (ret);
39605b3e1433Swyllys }
39615b3e1433Swyllys 
396299ebb4caSwyllys /*
396399ebb4caSwyllys  * Helper function to decrypt and parse PKCS#12 import file.
396499ebb4caSwyllys  */
396599ebb4caSwyllys static KMF_RETURN
396699ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
39675b3e1433Swyllys 	STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs,
39685b3e1433Swyllys 	STACK_OF(X509) **ca)
3969a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */
397099ebb4caSwyllys {
397199ebb4caSwyllys 	PKCS12			*pk12, *pk12_tmp;
39725b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*pkeylist = NULL;
39735b3e1433Swyllys 	STACK_OF(X509)		*xcertlist = NULL;
39745b3e1433Swyllys 	STACK_OF(X509)		*cacertlist = NULL;
397599ebb4caSwyllys 
397699ebb4caSwyllys 	if ((pk12 = PKCS12_new()) == NULL) {
397799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
397899ebb4caSwyllys 	}
397999ebb4caSwyllys 
398099ebb4caSwyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
398199ebb4caSwyllys 		/* This is ok; it seems to mean there is no more to read. */
398299ebb4caSwyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
398399ebb4caSwyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
398499ebb4caSwyllys 			goto end_extract_pkcs12;
398599ebb4caSwyllys 
398699ebb4caSwyllys 		PKCS12_free(pk12);
398799ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
398899ebb4caSwyllys 	}
398999ebb4caSwyllys 	pk12 = pk12_tmp;
399099ebb4caSwyllys 
39915b3e1433Swyllys 	xcertlist = sk_X509_new_null();
39925b3e1433Swyllys 	if (xcertlist == NULL) {
39935b3e1433Swyllys 		PKCS12_free(pk12);
39945b3e1433Swyllys 		return (KMF_ERR_MEMORY);
39955b3e1433Swyllys 	}
39965b3e1433Swyllys 	pkeylist = sk_EVP_PKEY_new_null();
39975b3e1433Swyllys 	if (pkeylist == NULL) {
39985b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
39995b3e1433Swyllys 		PKCS12_free(pk12);
40005b3e1433Swyllys 		return (KMF_ERR_MEMORY);
40015b3e1433Swyllys 	}
40025b3e1433Swyllys 
40035b3e1433Swyllys 	if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
40045b3e1433Swyllys 	    cacertlist) != KMF_OK) {
40055b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40065b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
400799ebb4caSwyllys 		PKCS12_free(pk12);
400899ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
400999ebb4caSwyllys 	}
401099ebb4caSwyllys 
40115b3e1433Swyllys 	if (priv_key && pkeylist)
40125b3e1433Swyllys 		*priv_key = pkeylist;
40135b3e1433Swyllys 	else if (pkeylist)
40145b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
40155b3e1433Swyllys 	if (certs && xcertlist)
40165b3e1433Swyllys 		*certs = xcertlist;
40175b3e1433Swyllys 	else if (xcertlist)
40185b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40195b3e1433Swyllys 	if (ca && cacertlist)
40205b3e1433Swyllys 		*ca = cacertlist;
40215b3e1433Swyllys 	else if (cacertlist)
40225b3e1433Swyllys 		sk_X509_pop_free(cacertlist, X509_free);
402399ebb4caSwyllys 
40245b3e1433Swyllys end_extract_pkcs12:
402599ebb4caSwyllys 
402699ebb4caSwyllys 	PKCS12_free(pk12);
402799ebb4caSwyllys 	return (KMF_OK);
402899ebb4caSwyllys }
402999ebb4caSwyllys 
403099ebb4caSwyllys static KMF_RETURN
403199ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
403299ebb4caSwyllys {
403399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
403499ebb4caSwyllys 	uint32_t sz;
403599ebb4caSwyllys 
403699ebb4caSwyllys 	sz = BN_num_bytes(from);
403799ebb4caSwyllys 	to->val = (uchar_t *)malloc(sz);
403899ebb4caSwyllys 	if (to->val == NULL)
403999ebb4caSwyllys 		return (KMF_ERR_MEMORY);
404099ebb4caSwyllys 
404199ebb4caSwyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
404299ebb4caSwyllys 		free(to->val);
404399ebb4caSwyllys 		to->val = NULL;
404499ebb4caSwyllys 		to->len = 0;
404599ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
404699ebb4caSwyllys 	}
404799ebb4caSwyllys 
404899ebb4caSwyllys 	return (rv);
404999ebb4caSwyllys }
405099ebb4caSwyllys 
405199ebb4caSwyllys static KMF_RETURN
405299ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
405399ebb4caSwyllys {
405499ebb4caSwyllys 	KMF_RETURN rv;
405599ebb4caSwyllys 	KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
405699ebb4caSwyllys 
405799ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
405899ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK)
405999ebb4caSwyllys 		goto cleanup;
406099ebb4caSwyllys 
406199ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK)
406299ebb4caSwyllys 		goto cleanup;
406399ebb4caSwyllys 
406499ebb4caSwyllys 	if (rsa->d != NULL)
406599ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK)
406699ebb4caSwyllys 			goto cleanup;
406799ebb4caSwyllys 
406899ebb4caSwyllys 	if (rsa->p != NULL)
406999ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK)
407099ebb4caSwyllys 			goto cleanup;
407199ebb4caSwyllys 
407299ebb4caSwyllys 	if (rsa->q != NULL)
407399ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK)
407499ebb4caSwyllys 			goto cleanup;
407599ebb4caSwyllys 
407699ebb4caSwyllys 	if (rsa->dmp1 != NULL)
407799ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK)
407899ebb4caSwyllys 			goto cleanup;
407999ebb4caSwyllys 
408099ebb4caSwyllys 	if (rsa->dmq1 != NULL)
408199ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK)
408299ebb4caSwyllys 			goto cleanup;
408399ebb4caSwyllys 
408499ebb4caSwyllys 	if (rsa->iqmp != NULL)
408599ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK)
408699ebb4caSwyllys 			goto cleanup;
408799ebb4caSwyllys cleanup:
408899ebb4caSwyllys 	if (rv != KMF_OK)
408930a5e8faSwyllys 		kmf_free_raw_key(key);
409099ebb4caSwyllys 	else
409199ebb4caSwyllys 		key->keytype = KMF_RSA;
409299ebb4caSwyllys 
409399ebb4caSwyllys 	/*
409499ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
409599ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
409699ebb4caSwyllys 	 */
409799ebb4caSwyllys 	RSA_free(rsa);
409899ebb4caSwyllys 
409999ebb4caSwyllys 	return (rv);
410099ebb4caSwyllys }
410199ebb4caSwyllys 
410299ebb4caSwyllys static KMF_RETURN
410399ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
410499ebb4caSwyllys {
410599ebb4caSwyllys 	KMF_RETURN rv;
410699ebb4caSwyllys 	KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
410799ebb4caSwyllys 
410899ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
410999ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK)
411099ebb4caSwyllys 		goto cleanup;
411199ebb4caSwyllys 
411299ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK)
411399ebb4caSwyllys 		goto cleanup;
411499ebb4caSwyllys 
411599ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK)
411699ebb4caSwyllys 		goto cleanup;
411799ebb4caSwyllys 
411899ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK)
411999ebb4caSwyllys 		goto cleanup;
412099ebb4caSwyllys 
412199ebb4caSwyllys cleanup:
412299ebb4caSwyllys 	if (rv != KMF_OK)
412330a5e8faSwyllys 		kmf_free_raw_key(key);
412499ebb4caSwyllys 	else
412599ebb4caSwyllys 		key->keytype = KMF_DSA;
412699ebb4caSwyllys 
412799ebb4caSwyllys 	/*
412899ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
412999ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
413099ebb4caSwyllys 	 */
413199ebb4caSwyllys 	DSA_free(dsa);
413299ebb4caSwyllys 
413399ebb4caSwyllys 	return (rv);
413499ebb4caSwyllys }
413599ebb4caSwyllys 
413699ebb4caSwyllys static KMF_RETURN
413799ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
41385b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
413999ebb4caSwyllys {
414099ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
41415b3e1433Swyllys 	KMF_X509_DER_CERT *list = (*certlist);
41425b3e1433Swyllys 	KMF_X509_DER_CERT cert;
414399ebb4caSwyllys 	int n = (*ncerts);
414499ebb4caSwyllys 
414599ebb4caSwyllys 	if (list == NULL) {
41465b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
414799ebb4caSwyllys 	} else {
41485b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)realloc(list,
41495b3e1433Swyllys 		    sizeof (KMF_X509_DER_CERT) * (n + 1));
415099ebb4caSwyllys 	}
415199ebb4caSwyllys 
415299ebb4caSwyllys 	if (list == NULL)
415399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
415499ebb4caSwyllys 
41555b3e1433Swyllys 	(void) memset(&cert, 0, sizeof (cert));
41565b3e1433Swyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
415799ebb4caSwyllys 	if (rv == KMF_OK) {
41585b3e1433Swyllys 		int len = 0;
41595b3e1433Swyllys 		/* Get the alias name for the cert if there is one */
41605b3e1433Swyllys 		char *a = (char *)X509_alias_get0(sslcert, &len);
41615b3e1433Swyllys 		if (a != NULL)
41625b3e1433Swyllys 			cert.kmf_private.label = strdup(a);
41635b3e1433Swyllys 		cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
41645b3e1433Swyllys 
416599ebb4caSwyllys 		list[n] = cert;
416699ebb4caSwyllys 		(*ncerts) = n + 1;
416799ebb4caSwyllys 
416899ebb4caSwyllys 		*certlist = list;
416999ebb4caSwyllys 	} else {
417099ebb4caSwyllys 		free(list);
417199ebb4caSwyllys 	}
417299ebb4caSwyllys 
417399ebb4caSwyllys 	return (rv);
417499ebb4caSwyllys }
417599ebb4caSwyllys 
417699ebb4caSwyllys static KMF_RETURN
417799ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
417899ebb4caSwyllys 	KMF_RAW_KEY_DATA *newkey, int *nkeys)
417999ebb4caSwyllys {
418099ebb4caSwyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
418199ebb4caSwyllys 	int n = (*nkeys);
418299ebb4caSwyllys 
418399ebb4caSwyllys 	if (list == NULL) {
418499ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
418599ebb4caSwyllys 	} else {
418699ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
418799ebb4caSwyllys 		    sizeof (KMF_RAW_KEY_DATA) * (n + 1));
418899ebb4caSwyllys 	}
418999ebb4caSwyllys 
419099ebb4caSwyllys 	if (list == NULL)
419199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
419299ebb4caSwyllys 
419399ebb4caSwyllys 	list[n] = *newkey;
419499ebb4caSwyllys 	(*nkeys) = n + 1;
419599ebb4caSwyllys 
419699ebb4caSwyllys 	*keylist = list;
419799ebb4caSwyllys 
419899ebb4caSwyllys 	return (KMF_OK);
419999ebb4caSwyllys }
420099ebb4caSwyllys 
42015b3e1433Swyllys static X509_ATTRIBUTE *
42025b3e1433Swyllys find_attr(STACK_OF(X509_ATTRIBUTE) *attrs, int nid)
42035b3e1433Swyllys {
42045b3e1433Swyllys 	X509_ATTRIBUTE *a;
42055b3e1433Swyllys 	int i;
42065b3e1433Swyllys 
42075b3e1433Swyllys 	if (attrs == NULL)
42085b3e1433Swyllys 		return (NULL);
42095b3e1433Swyllys 
42105b3e1433Swyllys 	for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
4211a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
42125b3e1433Swyllys 		a = sk_X509_ATTRIBUTE_value(attrs, i);
42135b3e1433Swyllys 		if (OBJ_obj2nid(a->object) == nid)
42145b3e1433Swyllys 			return (a);
42155b3e1433Swyllys 	}
42165b3e1433Swyllys 	return (NULL);
42175b3e1433Swyllys }
42185b3e1433Swyllys 
421930a5e8faSwyllys static KMF_RETURN
422030a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
422130a5e8faSwyllys {
422230a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
42235b3e1433Swyllys 	X509_ATTRIBUTE *attr;
422430a5e8faSwyllys 
422530a5e8faSwyllys 	if (pkey == NULL || key == NULL)
422630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
422730a5e8faSwyllys 	/* Convert SSL key to raw key */
422830a5e8faSwyllys 	switch (pkey->type) {
422930a5e8faSwyllys 		case EVP_PKEY_RSA:
423030a5e8faSwyllys 			rv = exportRawRSAKey(EVP_PKEY_get1_RSA(pkey),
423130a5e8faSwyllys 			    key);
423230a5e8faSwyllys 			if (rv != KMF_OK)
423330a5e8faSwyllys 				return (rv);
423430a5e8faSwyllys 			break;
423530a5e8faSwyllys 		case EVP_PKEY_DSA:
423630a5e8faSwyllys 			rv = exportRawDSAKey(EVP_PKEY_get1_DSA(pkey),
423730a5e8faSwyllys 			    key);
423830a5e8faSwyllys 			if (rv != KMF_OK)
423930a5e8faSwyllys 				return (rv);
424030a5e8faSwyllys 			break;
424130a5e8faSwyllys 		default:
424230a5e8faSwyllys 			return (KMF_ERR_BAD_PARAMETER);
424330a5e8faSwyllys 	}
42445b3e1433Swyllys 	/*
42455b3e1433Swyllys 	 * If friendlyName, add it to record.
42465b3e1433Swyllys 	 */
42475b3e1433Swyllys 	attr = find_attr(pkey->attributes, NID_friendlyName);
42485b3e1433Swyllys 	if (attr != NULL) {
42495b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
42505b3e1433Swyllys 		int numattr = sk_ASN1_TYPE_num(attr->value.set);
42515b3e1433Swyllys 		if (attr->single == 0 && numattr > 0) {
4252a2d4930dSDan OpenSolaris Anderson 			/* LINTED E_BAD_PTR_CAST_ALIGN */
42535b3e1433Swyllys 			ty = sk_ASN1_TYPE_value(attr->value.set, 0);
42545b3e1433Swyllys 		}
42555b3e1433Swyllys 		if (ty != NULL) {
42565b3e1433Swyllys 			key->label = uni2asc(ty->value.bmpstring->data,
42575b3e1433Swyllys 			    ty->value.bmpstring->length);
42585b3e1433Swyllys 		}
42595b3e1433Swyllys 	} else {
42605b3e1433Swyllys 		key->label = NULL;
42615b3e1433Swyllys 	}
42625b3e1433Swyllys 
42635b3e1433Swyllys 	/*
42645b3e1433Swyllys 	 * If KeyID, add it to record as a KMF_DATA object.
42655b3e1433Swyllys 	 */
42665b3e1433Swyllys 	attr = find_attr(pkey->attributes, NID_localKeyID);
42675b3e1433Swyllys 	if (attr != NULL) {
42685b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
42695b3e1433Swyllys 		int numattr = sk_ASN1_TYPE_num(attr->value.set);
42705b3e1433Swyllys 		if (attr->single == 0 && numattr > 0) {
4271a2d4930dSDan OpenSolaris Anderson 			/* LINTED E_BAD_PTR_CAST_ALIGN */
42725b3e1433Swyllys 			ty = sk_ASN1_TYPE_value(attr->value.set, 0);
42735b3e1433Swyllys 		}
42745b3e1433Swyllys 		key->id.Data = (uchar_t *)malloc(
42755b3e1433Swyllys 		    ty->value.octet_string->length);
42765b3e1433Swyllys 		if (key->id.Data == NULL)
42775b3e1433Swyllys 			return (KMF_ERR_MEMORY);
42785b3e1433Swyllys 		(void) memcpy(key->id.Data, ty->value.octet_string->data,
42795b3e1433Swyllys 		    ty->value.octet_string->length);
42805b3e1433Swyllys 		key->id.Length = ty->value.octet_string->length;
42815b3e1433Swyllys 	} else {
42825b3e1433Swyllys 		(void) memset(&key->id, 0, sizeof (KMF_DATA));
42835b3e1433Swyllys 	}
428430a5e8faSwyllys 
428530a5e8faSwyllys 	return (rv);
428630a5e8faSwyllys }
428799ebb4caSwyllys 
428899ebb4caSwyllys static KMF_RETURN
428999ebb4caSwyllys convertPK12Objects(
429099ebb4caSwyllys 	KMF_HANDLE *kmfh,
42915b3e1433Swyllys 	STACK_OF(EVP_PKEY) *sslkeys,
42925b3e1433Swyllys 	STACK_OF(X509) *sslcert,
42935b3e1433Swyllys 	STACK_OF(X509) *sslcacerts,
429499ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
42955b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
429699ebb4caSwyllys {
429799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
429899ebb4caSwyllys 	KMF_RAW_KEY_DATA key;
429999ebb4caSwyllys 	int i;
430099ebb4caSwyllys 
43015b3e1433Swyllys 	for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
4302a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
43035b3e1433Swyllys 		EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
43045b3e1433Swyllys 		rv = convertToRawKey(pkey, &key);
430530a5e8faSwyllys 		if (rv == KMF_OK)
430699ebb4caSwyllys 			rv = add_key_to_list(keylist, &key, nkeys);
430730a5e8faSwyllys 
430899ebb4caSwyllys 		if (rv != KMF_OK)
430999ebb4caSwyllys 			return (rv);
431099ebb4caSwyllys 	}
431199ebb4caSwyllys 
431299ebb4caSwyllys 	/* Now add the certificate to the certlist */
43135b3e1433Swyllys 	for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
4314a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
43155b3e1433Swyllys 		X509 *cert = sk_X509_value(sslcert, i);
43165b3e1433Swyllys 		rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
431799ebb4caSwyllys 		if (rv != KMF_OK)
431899ebb4caSwyllys 			return (rv);
431999ebb4caSwyllys 	}
432099ebb4caSwyllys 
432199ebb4caSwyllys 	/* Also add any included CA certs to the list */
432271593db2Swyllys 	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
432399ebb4caSwyllys 		X509 *c;
432499ebb4caSwyllys 		/*
432599ebb4caSwyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
432699ebb4caSwyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
432799ebb4caSwyllys 		 * Lint is complaining about the embedded casting, and
432899ebb4caSwyllys 		 * to fix it, you need to fix openssl header files.
432999ebb4caSwyllys 		 */
433099ebb4caSwyllys 		/* LINTED E_BAD_PTR_CAST_ALIGN */
433199ebb4caSwyllys 		c = sk_X509_value(sslcacerts, i);
433299ebb4caSwyllys 
433399ebb4caSwyllys 		/* Now add the ca cert to the certlist */
433499ebb4caSwyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
433599ebb4caSwyllys 		if (rv != KMF_OK)
433699ebb4caSwyllys 			return (rv);
433799ebb4caSwyllys 	}
433899ebb4caSwyllys 	return (rv);
433999ebb4caSwyllys }
434099ebb4caSwyllys 
434199ebb4caSwyllys KMF_RETURN
434230a5e8faSwyllys openssl_import_objects(KMF_HANDLE *kmfh,
434399ebb4caSwyllys 	char *filename, KMF_CREDENTIAL *cred,
43445b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts,
434599ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
434699ebb4caSwyllys {
434799ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
434830a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
434930a5e8faSwyllys 	BIO		*bio = NULL;
43505b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*privkeys = NULL;
43515b3e1433Swyllys 	STACK_OF(X509)		*certs = NULL;
435299ebb4caSwyllys 	STACK_OF(X509)		*cacerts = NULL;
435399ebb4caSwyllys 
435430a5e8faSwyllys 	/*
435530a5e8faSwyllys 	 * auto-detect the file format, regardless of what
435630a5e8faSwyllys 	 * the 'format' parameters in the params say.
435730a5e8faSwyllys 	 */
435830a5e8faSwyllys 	rv = kmf_get_file_format(filename, &format);
435930a5e8faSwyllys 	if (rv != KMF_OK) {
436030a5e8faSwyllys 		return (rv);
436130a5e8faSwyllys 	}
436230a5e8faSwyllys 
436330a5e8faSwyllys 	/* This function only works for PEM or PKCS#12 files */
436430a5e8faSwyllys 	if (format != KMF_FORMAT_PEM &&
436530a5e8faSwyllys 	    format != KMF_FORMAT_PEM_KEYPAIR &&
436630a5e8faSwyllys 	    format != KMF_FORMAT_PKCS12)
436730a5e8faSwyllys 		return (KMF_ERR_ENCODING);
436830a5e8faSwyllys 
436930a5e8faSwyllys 	*certlist = NULL;
437030a5e8faSwyllys 	*keylist = NULL;
437130a5e8faSwyllys 	*ncerts = 0;
437230a5e8faSwyllys 	*nkeys = 0;
437330a5e8faSwyllys 
437430a5e8faSwyllys 	if (format == KMF_FORMAT_PKCS12) {
437599ebb4caSwyllys 		bio = BIO_new_file(filename, "rb");
437699ebb4caSwyllys 		if (bio == NULL) {
437799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
437899ebb4caSwyllys 			rv = KMF_ERR_OPEN_FILE;
437999ebb4caSwyllys 			goto end;
438099ebb4caSwyllys 		}
438199ebb4caSwyllys 
438234acef67Swyllys 		rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
43835b3e1433Swyllys 		    (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
438499ebb4caSwyllys 
438599ebb4caSwyllys 		if (rv  == KMF_OK)
438699ebb4caSwyllys 			/* Convert keys and certs to exportable format */
43875b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
438899ebb4caSwyllys 			    keylist, nkeys, certlist, ncerts);
438930a5e8faSwyllys 	} else {
43905b3e1433Swyllys 		EVP_PKEY *pkey;
43915b3e1433Swyllys 		KMF_DATA *certdata = NULL;
43925b3e1433Swyllys 		KMF_X509_DER_CERT *kmfcerts = NULL;
43935b3e1433Swyllys 		int i;
439430a5e8faSwyllys 		rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
439534acef67Swyllys 		    (uchar_t *)cred->cred, (uint32_t)cred->credlen,
43965b3e1433Swyllys 		    &pkey, &certdata, ncerts);
439771593db2Swyllys 
439871593db2Swyllys 		/* Reached end of import file? */
43995b3e1433Swyllys 		if (rv == KMF_OK && pkey != NULL) {
44005b3e1433Swyllys 			privkeys = sk_EVP_PKEY_new_null();
44015b3e1433Swyllys 			if (privkeys == NULL) {
44025b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
44035b3e1433Swyllys 				goto end;
44045b3e1433Swyllys 			}
44055b3e1433Swyllys 			(void) sk_EVP_PKEY_push(privkeys, pkey);
44065b3e1433Swyllys 			/* convert the certificate list here */
44075b3e1433Swyllys 			if (*ncerts > 0 && certlist != NULL) {
4408*e65e5c2dSWyllys Ingersoll 				kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
44095b3e1433Swyllys 				    sizeof (KMF_X509_DER_CERT));
44105b3e1433Swyllys 				if (kmfcerts == NULL) {
44115b3e1433Swyllys 					rv = KMF_ERR_MEMORY;
44125b3e1433Swyllys 					goto end;
44135b3e1433Swyllys 				}
44145b3e1433Swyllys 				for (i = 0; i < *ncerts; i++) {
44155b3e1433Swyllys 					kmfcerts[i].certificate = certdata[i];
44165b3e1433Swyllys 					kmfcerts[i].kmf_private.keystore_type =
44175b3e1433Swyllys 					    KMF_KEYSTORE_OPENSSL;
44185b3e1433Swyllys 				}
44195b3e1433Swyllys 				*certlist = kmfcerts;
44205b3e1433Swyllys 			}
44215b3e1433Swyllys 			/*
44225b3e1433Swyllys 			 * Convert keys to exportable format, the certs
44235b3e1433Swyllys 			 * are already OK.
44245b3e1433Swyllys 			 */
44255b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
442671593db2Swyllys 			    keylist, nkeys, NULL, NULL);
442730a5e8faSwyllys 		}
44285b3e1433Swyllys 	}
442971593db2Swyllys end:
443030a5e8faSwyllys 	if (bio != NULL)
443199ebb4caSwyllys 		(void) BIO_free(bio);
443299ebb4caSwyllys 
44335b3e1433Swyllys 	if (privkeys)
44345b3e1433Swyllys 		sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
44355b3e1433Swyllys 	if (certs)
44365b3e1433Swyllys 		sk_X509_pop_free(certs, X509_free);
443730a5e8faSwyllys 	if (cacerts)
44385b3e1433Swyllys 		sk_X509_pop_free(cacerts, X509_free);
443930a5e8faSwyllys 
444099ebb4caSwyllys 	return (rv);
444199ebb4caSwyllys }
444299ebb4caSwyllys 
444399ebb4caSwyllys static KMF_RETURN
444499ebb4caSwyllys create_deskey(DES_cblock **deskey)
444599ebb4caSwyllys {
444699ebb4caSwyllys 	DES_cblock *key;
444799ebb4caSwyllys 
444899ebb4caSwyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
444999ebb4caSwyllys 	if (key == NULL) {
445099ebb4caSwyllys 		return (KMF_ERR_MEMORY);
445199ebb4caSwyllys 	}
445299ebb4caSwyllys 
445399ebb4caSwyllys 	if (DES_random_key(key) == 0) {
445499ebb4caSwyllys 		free(key);
445599ebb4caSwyllys 		return (KMF_ERR_KEYGEN_FAILED);
445699ebb4caSwyllys 	}
445799ebb4caSwyllys 
445899ebb4caSwyllys 	*deskey = key;
445999ebb4caSwyllys 	return (KMF_OK);
446099ebb4caSwyllys }
446199ebb4caSwyllys 
446299ebb4caSwyllys #define	KEYGEN_RETRY 3
446399ebb4caSwyllys #define	DES3_KEY_SIZE 24
446499ebb4caSwyllys 
446599ebb4caSwyllys static KMF_RETURN
446699ebb4caSwyllys create_des3key(unsigned char **des3key)
446799ebb4caSwyllys {
446899ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
446999ebb4caSwyllys 	DES_cblock *deskey1 = NULL;
447099ebb4caSwyllys 	DES_cblock *deskey2 = NULL;
447199ebb4caSwyllys 	DES_cblock *deskey3 = NULL;
447299ebb4caSwyllys 	unsigned char *newkey = NULL;
447399ebb4caSwyllys 	int retry;
447499ebb4caSwyllys 
447599ebb4caSwyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
447699ebb4caSwyllys 		return (KMF_ERR_MEMORY);
447799ebb4caSwyllys 	}
447899ebb4caSwyllys 
447999ebb4caSwyllys 	/* create the 1st DES key */
448099ebb4caSwyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
448199ebb4caSwyllys 		goto out;
448299ebb4caSwyllys 	}
448399ebb4caSwyllys 
448499ebb4caSwyllys 	/*
448599ebb4caSwyllys 	 * Create the 2nd DES key and make sure its value is different
448699ebb4caSwyllys 	 * from the 1st DES key.
448799ebb4caSwyllys 	 */
448899ebb4caSwyllys 	retry = 0;
448999ebb4caSwyllys 	do {
449099ebb4caSwyllys 		if (deskey2 != NULL) {
449199ebb4caSwyllys 			free(deskey2);
449299ebb4caSwyllys 			deskey2 = NULL;
449399ebb4caSwyllys 		}
449499ebb4caSwyllys 
449599ebb4caSwyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
449699ebb4caSwyllys 			goto out;
449799ebb4caSwyllys 		}
449899ebb4caSwyllys 
449999ebb4caSwyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
450099ebb4caSwyllys 		    == 0) {
450199ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
450299ebb4caSwyllys 			retry++;
450399ebb4caSwyllys 		}
450499ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
450599ebb4caSwyllys 
450699ebb4caSwyllys 	if (ret != KMF_OK) {
450799ebb4caSwyllys 		goto out;
450899ebb4caSwyllys 	}
450999ebb4caSwyllys 
451099ebb4caSwyllys 	/*
451199ebb4caSwyllys 	 * Create the 3rd DES key and make sure its value is different
451299ebb4caSwyllys 	 * from the 2nd DES key.
451399ebb4caSwyllys 	 */
451499ebb4caSwyllys 	retry = 0;
451599ebb4caSwyllys 	do {
451699ebb4caSwyllys 		if (deskey3 != NULL) {
451799ebb4caSwyllys 			free(deskey3);
451899ebb4caSwyllys 			deskey3 = NULL;
451999ebb4caSwyllys 		}
452099ebb4caSwyllys 
452199ebb4caSwyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
452299ebb4caSwyllys 			goto out;
452399ebb4caSwyllys 		}
452499ebb4caSwyllys 
452599ebb4caSwyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
452699ebb4caSwyllys 		    == 0) {
452799ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
452899ebb4caSwyllys 			retry++;
452999ebb4caSwyllys 		}
453099ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
453199ebb4caSwyllys 
453299ebb4caSwyllys 	if (ret != KMF_OK) {
453399ebb4caSwyllys 		goto out;
453499ebb4caSwyllys 	}
453599ebb4caSwyllys 
453699ebb4caSwyllys 	/* Concatenate 3 DES keys into a DES3 key */
453799ebb4caSwyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
453899ebb4caSwyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
453999ebb4caSwyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
454099ebb4caSwyllys 	*des3key = newkey;
454199ebb4caSwyllys 
454299ebb4caSwyllys out:
454399ebb4caSwyllys 	if (deskey1 != NULL)
454499ebb4caSwyllys 		free(deskey1);
454599ebb4caSwyllys 
454699ebb4caSwyllys 	if (deskey2 != NULL)
454799ebb4caSwyllys 		free(deskey2);
454899ebb4caSwyllys 
454999ebb4caSwyllys 	if (deskey3 != NULL)
455099ebb4caSwyllys 		free(deskey3);
455199ebb4caSwyllys 
455299ebb4caSwyllys 	if (ret != KMF_OK && newkey != NULL)
455399ebb4caSwyllys 		free(newkey);
455499ebb4caSwyllys 
455599ebb4caSwyllys 	return (ret);
455699ebb4caSwyllys }
455799ebb4caSwyllys 
455899ebb4caSwyllys KMF_RETURN
455930a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
456030a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
456199ebb4caSwyllys {
456299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
456399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
456499ebb4caSwyllys 	char *fullpath = NULL;
456599ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
456699ebb4caSwyllys 	DES_cblock *deskey = NULL;
456799ebb4caSwyllys 	unsigned char *des3key = NULL;
456899ebb4caSwyllys 	unsigned char *random = NULL;
456999ebb4caSwyllys 	int fd = -1;
457030a5e8faSwyllys 	KMF_KEY_HANDLE *symkey;
457130a5e8faSwyllys 	KMF_KEY_ALG keytype;
457230a5e8faSwyllys 	uint32_t keylen;
457330a5e8faSwyllys 	uint32_t keylen_size = sizeof (keylen);
457430a5e8faSwyllys 	char *dirpath;
457530a5e8faSwyllys 	char *keyfile;
457699ebb4caSwyllys 
457799ebb4caSwyllys 	if (kmfh == NULL)
457899ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
457999ebb4caSwyllys 
458030a5e8faSwyllys 	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
458130a5e8faSwyllys 	if (symkey == NULL)
458299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
458399ebb4caSwyllys 
458430a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
458530a5e8faSwyllys 
458630a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
458730a5e8faSwyllys 	if (keyfile == NULL)
458830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
458930a5e8faSwyllys 
459030a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
459130a5e8faSwyllys 	    (void *)&keytype, NULL);
459230a5e8faSwyllys 	if (ret != KMF_OK)
459330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
459430a5e8faSwyllys 
459530a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
459630a5e8faSwyllys 	    &keylen, &keylen_size);
459730a5e8faSwyllys 	if (ret == KMF_ERR_ATTR_NOT_FOUND &&
459830a5e8faSwyllys 	    (keytype == KMF_DES || keytype == KMF_DES3))
459930a5e8faSwyllys 		/* keylength is not required for DES and 3DES */
460030a5e8faSwyllys 		ret = KMF_OK;
460130a5e8faSwyllys 	if (ret != KMF_OK)
460230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
460330a5e8faSwyllys 
460430a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
460599ebb4caSwyllys 	if (fullpath == NULL)
460699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
460799ebb4caSwyllys 
460899ebb4caSwyllys 	/* If the requested file exists, return an error */
460930a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
461099ebb4caSwyllys 		free(fullpath);
461199ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
461299ebb4caSwyllys 	}
461399ebb4caSwyllys 
461499ebb4caSwyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
461599ebb4caSwyllys 	if (fd == -1) {
461699ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
461799ebb4caSwyllys 		goto out;
461899ebb4caSwyllys 	}
461999ebb4caSwyllys 
462099ebb4caSwyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
462199ebb4caSwyllys 	if (rkey == NULL) {
462299ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
462399ebb4caSwyllys 		goto out;
462499ebb4caSwyllys 	}
462599ebb4caSwyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
462699ebb4caSwyllys 
462730a5e8faSwyllys 	if (keytype == KMF_DES) {
462899ebb4caSwyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
462999ebb4caSwyllys 			goto out;
463099ebb4caSwyllys 		}
463199ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)deskey;
463299ebb4caSwyllys 		rkey->keydata.len = 8;
463399ebb4caSwyllys 
463499ebb4caSwyllys 		symkey->keyalg = KMF_DES;
463599ebb4caSwyllys 
463630a5e8faSwyllys 	} else if (keytype == KMF_DES3) {
463799ebb4caSwyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
463899ebb4caSwyllys 			goto out;
463999ebb4caSwyllys 		}
464099ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)des3key;
464199ebb4caSwyllys 		rkey->keydata.len = DES3_KEY_SIZE;
464299ebb4caSwyllys 		symkey->keyalg = KMF_DES3;
46439b37d296Swyllys 
464430a5e8faSwyllys 	} else if (keytype == KMF_AES || keytype == KMF_RC4 ||
464530a5e8faSwyllys 	    keytype == KMF_GENERIC_SECRET) {
464699ebb4caSwyllys 		int bytes;
464799ebb4caSwyllys 
464830a5e8faSwyllys 		if (keylen % 8 != 0) {
464999ebb4caSwyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
465099ebb4caSwyllys 			goto out;
465199ebb4caSwyllys 		}
465299ebb4caSwyllys 
465330a5e8faSwyllys 		if (keytype == KMF_AES) {
465430a5e8faSwyllys 			if (keylen != 128 &&
465530a5e8faSwyllys 			    keylen != 192 &&
465630a5e8faSwyllys 			    keylen != 256) {
465799ebb4caSwyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
465899ebb4caSwyllys 				goto out;
465999ebb4caSwyllys 			}
466099ebb4caSwyllys 		}
466199ebb4caSwyllys 
466230a5e8faSwyllys 		bytes = keylen/8;
466399ebb4caSwyllys 		random = malloc(bytes);
466499ebb4caSwyllys 		if (random == NULL) {
466599ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
466699ebb4caSwyllys 			goto out;
466799ebb4caSwyllys 		}
466899ebb4caSwyllys 		if (RAND_bytes(random, bytes) != 1) {
466999ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
467099ebb4caSwyllys 			goto out;
467199ebb4caSwyllys 		}
467299ebb4caSwyllys 
467399ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)random;
467499ebb4caSwyllys 		rkey->keydata.len = bytes;
467530a5e8faSwyllys 		symkey->keyalg = keytype;
467699ebb4caSwyllys 
467799ebb4caSwyllys 	} else {
467899ebb4caSwyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
467999ebb4caSwyllys 		goto out;
468099ebb4caSwyllys 	}
468199ebb4caSwyllys 
468299ebb4caSwyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
468399ebb4caSwyllys 
468499ebb4caSwyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
468599ebb4caSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
468699ebb4caSwyllys 	symkey->keylabel = (char *)fullpath;
468799ebb4caSwyllys 	symkey->israw = TRUE;
468899ebb4caSwyllys 	symkey->keyp = rkey;
468999ebb4caSwyllys 
469099ebb4caSwyllys out:
469199ebb4caSwyllys 	if (fd != -1)
469299ebb4caSwyllys 		(void) close(fd);
469399ebb4caSwyllys 
469499ebb4caSwyllys 	if (ret != KMF_OK && fullpath != NULL) {
469599ebb4caSwyllys 		free(fullpath);
469699ebb4caSwyllys 	}
469799ebb4caSwyllys 	if (ret != KMF_OK) {
469830a5e8faSwyllys 		kmf_free_raw_sym_key(rkey);
469999ebb4caSwyllys 		symkey->keyp = NULL;
470099ebb4caSwyllys 		symkey->keyalg = KMF_KEYALG_NONE;
470199ebb4caSwyllys 	}
470299ebb4caSwyllys 
470399ebb4caSwyllys 	return (ret);
470499ebb4caSwyllys }
470599ebb4caSwyllys 
470699ebb4caSwyllys /*
470799ebb4caSwyllys  * Check a file to see if it is a CRL file with PEM or DER format.
470899ebb4caSwyllys  * If success, return its format in the "pformat" argument.
470999ebb4caSwyllys  */
471099ebb4caSwyllys KMF_RETURN
471199ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
471299ebb4caSwyllys {
471399ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
471499ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
471599ebb4caSwyllys 	BIO		*bio = NULL;
471699ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
471799ebb4caSwyllys 
471899ebb4caSwyllys 	if (filename == NULL) {
471999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
472099ebb4caSwyllys 	}
472199ebb4caSwyllys 
472299ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
472399ebb4caSwyllys 	if (bio == NULL)	{
472499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
472599ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
472699ebb4caSwyllys 		goto out;
472799ebb4caSwyllys 	}
472899ebb4caSwyllys 
472999ebb4caSwyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
473099ebb4caSwyllys 		*pformat = KMF_FORMAT_PEM;
473199ebb4caSwyllys 		goto out;
473299ebb4caSwyllys 	}
473399ebb4caSwyllys 	(void) BIO_free(bio);
473499ebb4caSwyllys 
473599ebb4caSwyllys 	/*
473699ebb4caSwyllys 	 * Now try to read it as raw DER data.
473799ebb4caSwyllys 	 */
473899ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
473999ebb4caSwyllys 	if (bio == NULL)	{
474099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
474199ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
474299ebb4caSwyllys 		goto out;
474399ebb4caSwyllys 	}
474499ebb4caSwyllys 
474599ebb4caSwyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
474699ebb4caSwyllys 		*pformat = KMF_FORMAT_ASN1;
474799ebb4caSwyllys 	} else {
474899ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
474999ebb4caSwyllys 	}
475099ebb4caSwyllys 
475199ebb4caSwyllys out:
475299ebb4caSwyllys 	if (bio != NULL)
475399ebb4caSwyllys 		(void) BIO_free(bio);
475499ebb4caSwyllys 
475599ebb4caSwyllys 	if (xcrl != NULL)
475699ebb4caSwyllys 		X509_CRL_free(xcrl);
475799ebb4caSwyllys 
475899ebb4caSwyllys 	return (ret);
475999ebb4caSwyllys }
476099ebb4caSwyllys 
476199ebb4caSwyllys KMF_RETURN
476299ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
476399ebb4caSwyllys     KMF_RAW_SYM_KEY *rkey)
476499ebb4caSwyllys {
476599ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
476699ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
476799ebb4caSwyllys 	KMF_DATA	keyvalue;
476899ebb4caSwyllys 
476999ebb4caSwyllys 	if (kmfh == NULL)
477099ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
477199ebb4caSwyllys 
477299ebb4caSwyllys 	if (symkey == NULL || rkey == NULL)
477399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
477499ebb4caSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
477599ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
477699ebb4caSwyllys 
477799ebb4caSwyllys 	if (symkey->israw) {
477899ebb4caSwyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
477999ebb4caSwyllys 
478099ebb4caSwyllys 		if (rawkey == NULL ||
478199ebb4caSwyllys 		    rawkey->keydata.val == NULL ||
478299ebb4caSwyllys 		    rawkey->keydata.len == 0)
478399ebb4caSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
478499ebb4caSwyllys 
478599ebb4caSwyllys 		rkey->keydata.len = rawkey->keydata.len;
478699ebb4caSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
478799ebb4caSwyllys 			return (KMF_ERR_MEMORY);
478899ebb4caSwyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
478999ebb4caSwyllys 		    rkey->keydata.len);
479099ebb4caSwyllys 	} else {
479130a5e8faSwyllys 		rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
479299ebb4caSwyllys 		if (rv != KMF_OK)
479399ebb4caSwyllys 			return (rv);
479499ebb4caSwyllys 		rkey->keydata.len = keyvalue.Length;
479599ebb4caSwyllys 		rkey->keydata.val = keyvalue.Data;
479699ebb4caSwyllys 	}
479799ebb4caSwyllys 
479899ebb4caSwyllys 	return (rv);
479999ebb4caSwyllys }
480002744e81Swyllys 
480102744e81Swyllys /*
480230a5e8faSwyllys  * substitute for the unsafe access(2) function.
480330a5e8faSwyllys  * If the file in question already exists, return 1.
480430a5e8faSwyllys  * else 0.  If an error occurs during testing (other
480530a5e8faSwyllys  * than EEXIST), return -1.
480630a5e8faSwyllys  */
480730a5e8faSwyllys static int
480830a5e8faSwyllys test_for_file(char *filename, mode_t mode)
480930a5e8faSwyllys {
481030a5e8faSwyllys 	int fd;
481130a5e8faSwyllys 
481230a5e8faSwyllys 	/*
481330a5e8faSwyllys 	 * Try to create the file with the EXCL flag.
481430a5e8faSwyllys 	 * The call should fail if the file exists.
481530a5e8faSwyllys 	 */
481630a5e8faSwyllys 	fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
481730a5e8faSwyllys 	if (fd == -1 && errno == EEXIST)
481830a5e8faSwyllys 		return (1);
481930a5e8faSwyllys 	else if (fd == -1) /* some other error */
482030a5e8faSwyllys 		return (-1);
482130a5e8faSwyllys 
482230a5e8faSwyllys 	/* The file did NOT exist.  Delete the testcase. */
482330a5e8faSwyllys 	(void) close(fd);
482430a5e8faSwyllys 	(void) unlink(filename);
482530a5e8faSwyllys 	return (0);
482630a5e8faSwyllys }
482730a5e8faSwyllys 
482830a5e8faSwyllys KMF_RETURN
482930a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
483030a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
483130a5e8faSwyllys {
483230a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
483330a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
483430a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
483530a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
483630a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
483730a5e8faSwyllys 	KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
483830a5e8faSwyllys 	KMF_CREDENTIAL cred = {NULL, 0};
483930a5e8faSwyllys 	BIO *out = NULL;
484030a5e8faSwyllys 	int keys = 0;
484130a5e8faSwyllys 	char *fullpath = NULL;
484230a5e8faSwyllys 	char *keyfile = NULL;
484330a5e8faSwyllys 	char *dirpath = NULL;
484430a5e8faSwyllys 
484530a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
484630a5e8faSwyllys 	if (pubkey != NULL)
484730a5e8faSwyllys 		keys++;
484830a5e8faSwyllys 
484930a5e8faSwyllys 	prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
485030a5e8faSwyllys 	if (prikey != NULL)
485130a5e8faSwyllys 		keys++;
485230a5e8faSwyllys 
485330a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
485430a5e8faSwyllys 	if (rawkey != NULL)
485530a5e8faSwyllys 		keys++;
485630a5e8faSwyllys 
485730a5e8faSwyllys 	/*
485830a5e8faSwyllys 	 * Exactly 1 type of key must be passed to this function.
485930a5e8faSwyllys 	 */
486030a5e8faSwyllys 	if (keys != 1)
486130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
486230a5e8faSwyllys 
486330a5e8faSwyllys 	keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
486430a5e8faSwyllys 	    numattr);
486530a5e8faSwyllys 	if (keyfile == NULL)
486630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
486730a5e8faSwyllys 
486830a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
486930a5e8faSwyllys 
487030a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
487130a5e8faSwyllys 
487230a5e8faSwyllys 	/* Once we have the full path, we don't need the pieces */
487330a5e8faSwyllys 	if (fullpath == NULL)
487430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
487530a5e8faSwyllys 
487630a5e8faSwyllys 	/* If the requested file exists, return an error */
487730a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
487830a5e8faSwyllys 		free(fullpath);
487930a5e8faSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
488030a5e8faSwyllys 	}
488130a5e8faSwyllys 
488230a5e8faSwyllys 	rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
488330a5e8faSwyllys 	    &format, NULL);
488430a5e8faSwyllys 	if (rv != KMF_OK)
488530a5e8faSwyllys 		/* format is optional. */
488630a5e8faSwyllys 		rv = KMF_OK;
488730a5e8faSwyllys 
488830a5e8faSwyllys 	/* CRED is not required for OpenSSL files */
488930a5e8faSwyllys 	(void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
489030a5e8faSwyllys 	    &cred, NULL);
489130a5e8faSwyllys 
489230a5e8faSwyllys 	/* Store the private key to the keyfile */
489330a5e8faSwyllys 	out = BIO_new_file(fullpath, "wb");
489430a5e8faSwyllys 	if (out == NULL) {
489530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
489630a5e8faSwyllys 		rv = KMF_ERR_OPEN_FILE;
489730a5e8faSwyllys 		goto end;
489830a5e8faSwyllys 	}
489930a5e8faSwyllys 
490030a5e8faSwyllys 	if (prikey != NULL && prikey->keyp != NULL) {
490130a5e8faSwyllys 		if (prikey->keyalg == KMF_RSA ||
490230a5e8faSwyllys 		    prikey->keyalg == KMF_DSA) {
490330a5e8faSwyllys 			pkey = (EVP_PKEY *)prikey->keyp;
490430a5e8faSwyllys 
490530a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
490630a5e8faSwyllys 			    out, &cred, pkey, TRUE);
490730a5e8faSwyllys 
490830a5e8faSwyllys 			if (rv == KMF_OK && prikey->keylabel == NULL) {
490930a5e8faSwyllys 				prikey->keylabel = strdup(fullpath);
491030a5e8faSwyllys 				if (prikey->keylabel == NULL)
491130a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
491230a5e8faSwyllys 			}
491330a5e8faSwyllys 		}
491430a5e8faSwyllys 	} else if (pubkey != NULL && pubkey->keyp != NULL) {
491530a5e8faSwyllys 		if (pubkey->keyalg == KMF_RSA ||
491630a5e8faSwyllys 		    pubkey->keyalg == KMF_DSA) {
491730a5e8faSwyllys 			pkey = (EVP_PKEY *)pubkey->keyp;
491830a5e8faSwyllys 
491930a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
492030a5e8faSwyllys 			    out, &cred, pkey, FALSE);
492130a5e8faSwyllys 
492230a5e8faSwyllys 			if (rv == KMF_OK && pubkey->keylabel == NULL) {
492330a5e8faSwyllys 				pubkey->keylabel = strdup(fullpath);
492430a5e8faSwyllys 				if (pubkey->keylabel == NULL)
492530a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
492630a5e8faSwyllys 			}
492730a5e8faSwyllys 		}
492830a5e8faSwyllys 	} else if (rawkey != NULL) {
492930a5e8faSwyllys 		if (rawkey->keytype == KMF_RSA) {
493030a5e8faSwyllys 			pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
493130a5e8faSwyllys 		} else if (rawkey->keytype == KMF_DSA) {
493230a5e8faSwyllys 			pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
493330a5e8faSwyllys 		} else {
493430a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
493530a5e8faSwyllys 		}
49365b3e1433Swyllys 		if (pkey != NULL) {
493773cc0e02Swyllys 			KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
493873cc0e02Swyllys 
493973cc0e02Swyllys 			rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
494073cc0e02Swyllys 			    (void *)&kclass, NULL);
494173cc0e02Swyllys 			if (rv != KMF_OK)
494273cc0e02Swyllys 				rv = KMF_OK;
49435b3e1433Swyllys 			rv = ssl_write_key(kmfh, format, out,
494473cc0e02Swyllys 			    &cred, pkey, (kclass == KMF_ASYM_PRI));
49455b3e1433Swyllys 			EVP_PKEY_free(pkey);
49465b3e1433Swyllys 		}
494730a5e8faSwyllys 	}
494830a5e8faSwyllys 
494930a5e8faSwyllys end:
495030a5e8faSwyllys 
495130a5e8faSwyllys 	if (out)
495230a5e8faSwyllys 		(void) BIO_free(out);
495330a5e8faSwyllys 
49545b3e1433Swyllys 
495530a5e8faSwyllys 	if (rv == KMF_OK)
495630a5e8faSwyllys 		(void) chmod(fullpath, 0400);
495730a5e8faSwyllys 
495830a5e8faSwyllys 	free(fullpath);
495930a5e8faSwyllys 	return (rv);
496030a5e8faSwyllys }
496130a5e8faSwyllys 
496230a5e8faSwyllys KMF_RETURN
496330a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
496430a5e8faSwyllys {
496530a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
496630a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
496730a5e8faSwyllys 	X509_CRL *xcrl = NULL;
496830a5e8faSwyllys 	X509 *xcert = NULL;
496930a5e8faSwyllys 	EVP_PKEY *pkey;
497030a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
497130a5e8faSwyllys 	BIO *in = NULL, *out = NULL;
497230a5e8faSwyllys 	int openssl_ret = 0;
497330a5e8faSwyllys 	KMF_ENCODE_FORMAT outformat;
497430a5e8faSwyllys 	boolean_t crlcheck = FALSE;
497530a5e8faSwyllys 	char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
497630a5e8faSwyllys 
497730a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
497830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
497930a5e8faSwyllys 	}
498030a5e8faSwyllys 
498130a5e8faSwyllys 	/* CRL check is optional */
498230a5e8faSwyllys 	(void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
498330a5e8faSwyllys 	    &crlcheck, NULL);
498430a5e8faSwyllys 
498530a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
498630a5e8faSwyllys 	if (crlcheck == B_TRUE && certfile == NULL) {
498730a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
498830a5e8faSwyllys 	}
498930a5e8faSwyllys 
499030a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
499130a5e8faSwyllys 	incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
499230a5e8faSwyllys 	outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
499330a5e8faSwyllys 
499430a5e8faSwyllys 	crlfile = get_fullpath(dirpath, incrl);
499530a5e8faSwyllys 
499630a5e8faSwyllys 	if (crlfile == NULL)
499730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
499830a5e8faSwyllys 
499930a5e8faSwyllys 	outcrlfile = get_fullpath(dirpath, outcrl);
500030a5e8faSwyllys 	if (outcrlfile == NULL)
500130a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
500230a5e8faSwyllys 
500330a5e8faSwyllys 	if (isdir(outcrlfile)) {
500430a5e8faSwyllys 		free(outcrlfile);
500530a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
500630a5e8faSwyllys 	}
500730a5e8faSwyllys 
500830a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
500930a5e8faSwyllys 	if (ret != KMF_OK) {
501030a5e8faSwyllys 		free(outcrlfile);
501130a5e8faSwyllys 		return (ret);
501230a5e8faSwyllys 	}
501330a5e8faSwyllys 
501430a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
501530a5e8faSwyllys 	if (in == NULL)	{
501630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
501730a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
501830a5e8faSwyllys 		goto end;
501930a5e8faSwyllys 	}
502030a5e8faSwyllys 
502130a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
502230a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
502330a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
502430a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
502530a5e8faSwyllys 	}
502630a5e8faSwyllys 
502730a5e8faSwyllys 	if (xcrl == NULL) {
502830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
502930a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
503030a5e8faSwyllys 		goto end;
503130a5e8faSwyllys 	}
503230a5e8faSwyllys 
503330a5e8faSwyllys 	/* If bypasscheck is specified, no need to verify. */
503430a5e8faSwyllys 	if (crlcheck == B_FALSE)
503530a5e8faSwyllys 		goto output;
503630a5e8faSwyllys 
503730a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
503830a5e8faSwyllys 	if (ret != KMF_OK)
503930a5e8faSwyllys 		goto end;
504030a5e8faSwyllys 
504130a5e8faSwyllys 	/* Read in the CA cert file and convert to X509 */
504230a5e8faSwyllys 	if (BIO_read_filename(in, certfile) <= 0) {
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 		xcert = d2i_X509_bio(in, NULL);
505030a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
505130a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
505230a5e8faSwyllys 	} else {
505330a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
505430a5e8faSwyllys 		goto end;
505530a5e8faSwyllys 	}
505630a5e8faSwyllys 
505730a5e8faSwyllys 	if (xcert == NULL) {
505830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
505930a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
506030a5e8faSwyllys 		goto end;
506130a5e8faSwyllys 	}
506230a5e8faSwyllys 	/* Now get the public key from the CA cert */
506330a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
506430a5e8faSwyllys 	if (pkey == NULL) {
506530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
506630a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
506730a5e8faSwyllys 		goto end;
506830a5e8faSwyllys 	}
506930a5e8faSwyllys 
507030a5e8faSwyllys 	/* Verify the CRL with the CA's public key */
507130a5e8faSwyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
507230a5e8faSwyllys 	EVP_PKEY_free(pkey);
507330a5e8faSwyllys 	if (openssl_ret > 0) {
507430a5e8faSwyllys 		ret = KMF_OK;  /* verify succeed */
507530a5e8faSwyllys 	} else {
507630a5e8faSwyllys 		SET_ERROR(kmfh, openssl_ret);
507730a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
507830a5e8faSwyllys 	}
507930a5e8faSwyllys 
508030a5e8faSwyllys output:
508130a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
508230a5e8faSwyllys 	    &outformat, NULL);
508330a5e8faSwyllys 	if (ret != KMF_OK) {
508430a5e8faSwyllys 		ret = KMF_OK;
508530a5e8faSwyllys 		outformat = KMF_FORMAT_PEM;
508630a5e8faSwyllys 	}
508730a5e8faSwyllys 
508830a5e8faSwyllys 	out = BIO_new_file(outcrlfile, "wb");
508930a5e8faSwyllys 	if (out == NULL) {
509030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
509130a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
509230a5e8faSwyllys 		goto end;
509330a5e8faSwyllys 	}
509430a5e8faSwyllys 
509530a5e8faSwyllys 	if (outformat == KMF_FORMAT_ASN1) {
509630a5e8faSwyllys 		openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
509730a5e8faSwyllys 	} else if (outformat == KMF_FORMAT_PEM) {
509830a5e8faSwyllys 		openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
509930a5e8faSwyllys 	} else {
510030a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
510130a5e8faSwyllys 		goto end;
510230a5e8faSwyllys 	}
510330a5e8faSwyllys 
510430a5e8faSwyllys 	if (openssl_ret <= 0) {
510530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
510630a5e8faSwyllys 		ret = KMF_ERR_WRITE_FILE;
510730a5e8faSwyllys 	} else {
510830a5e8faSwyllys 		ret = KMF_OK;
510930a5e8faSwyllys 	}
511030a5e8faSwyllys 
511130a5e8faSwyllys end:
511230a5e8faSwyllys 	if (xcrl != NULL)
511330a5e8faSwyllys 		X509_CRL_free(xcrl);
511430a5e8faSwyllys 
511530a5e8faSwyllys 	if (xcert != NULL)
511630a5e8faSwyllys 		X509_free(xcert);
511730a5e8faSwyllys 
511830a5e8faSwyllys 	if (in != NULL)
511930a5e8faSwyllys 		(void) BIO_free(in);
512030a5e8faSwyllys 
512130a5e8faSwyllys 	if (out != NULL)
512230a5e8faSwyllys 		(void) BIO_free(out);
512330a5e8faSwyllys 
512430a5e8faSwyllys 	if (outcrlfile != NULL)
512530a5e8faSwyllys 		free(outcrlfile);
512630a5e8faSwyllys 
512730a5e8faSwyllys 	return (ret);
512830a5e8faSwyllys }
512930a5e8faSwyllys 
513030a5e8faSwyllys KMF_RETURN
513130a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
513230a5e8faSwyllys {
513330a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
513430a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
513530a5e8faSwyllys 	X509_CRL   *x = NULL;
513630a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
513730a5e8faSwyllys 	char *crlfile = NULL;
513830a5e8faSwyllys 	BIO *in = NULL;
513930a5e8faSwyllys 	BIO *mem = NULL;
514030a5e8faSwyllys 	long len;
514130a5e8faSwyllys 	char *memptr;
514230a5e8faSwyllys 	char *data = NULL;
514330a5e8faSwyllys 	char **crldata;
514430a5e8faSwyllys 	char *crlfilename, *dirpath;
514530a5e8faSwyllys 
514630a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
514730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
514830a5e8faSwyllys 	}
514930a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
515030a5e8faSwyllys 	    attrlist, numattr);
515130a5e8faSwyllys 	if (crlfilename == NULL)
515230a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
515330a5e8faSwyllys 
515430a5e8faSwyllys 	crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
515530a5e8faSwyllys 	    attrlist, numattr);
515630a5e8faSwyllys 
515730a5e8faSwyllys 	if (crldata == NULL)
515830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
515930a5e8faSwyllys 
516030a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
516130a5e8faSwyllys 
516230a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
516330a5e8faSwyllys 
516430a5e8faSwyllys 	if (crlfile == NULL)
516530a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
516630a5e8faSwyllys 
516730a5e8faSwyllys 	if (isdir(crlfile)) {
516830a5e8faSwyllys 		free(crlfile);
516930a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
517030a5e8faSwyllys 	}
517130a5e8faSwyllys 
517230a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
517330a5e8faSwyllys 	if (ret != KMF_OK) {
517430a5e8faSwyllys 		free(crlfile);
517530a5e8faSwyllys 		return (ret);
517630a5e8faSwyllys 	}
517730a5e8faSwyllys 
517830a5e8faSwyllys 	if (bio_err == NULL)
517930a5e8faSwyllys 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
518030a5e8faSwyllys 
518130a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
518230a5e8faSwyllys 	if (in == NULL)	{
518330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
518430a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
518530a5e8faSwyllys 		goto end;
518630a5e8faSwyllys 	}
518730a5e8faSwyllys 
518830a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
518930a5e8faSwyllys 		x = d2i_X509_CRL_bio(in, NULL);
519030a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
519130a5e8faSwyllys 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
519230a5e8faSwyllys 	}
519330a5e8faSwyllys 
519430a5e8faSwyllys 	if (x == NULL) { /* should not happen */
519530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
519630a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
519730a5e8faSwyllys 		goto end;
519830a5e8faSwyllys 	}
519930a5e8faSwyllys 
520030a5e8faSwyllys 	mem = BIO_new(BIO_s_mem());
520130a5e8faSwyllys 	if (mem == NULL) {
520230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
520330a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
520430a5e8faSwyllys 		goto end;
520530a5e8faSwyllys 	}
520630a5e8faSwyllys 
520730a5e8faSwyllys 	(void) X509_CRL_print(mem, x);
520830a5e8faSwyllys 	len = BIO_get_mem_data(mem, &memptr);
520930a5e8faSwyllys 	if (len <= 0) {
521030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
521130a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
521230a5e8faSwyllys 		goto end;
521330a5e8faSwyllys 	}
521430a5e8faSwyllys 
521530a5e8faSwyllys 	data = malloc(len + 1);
521630a5e8faSwyllys 	if (data == NULL) {
521730a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
521830a5e8faSwyllys 		goto end;
521930a5e8faSwyllys 	}
522030a5e8faSwyllys 
522130a5e8faSwyllys 	(void) memcpy(data, memptr, len);
522230a5e8faSwyllys 	data[len] = '\0';
522330a5e8faSwyllys 	*crldata = data;
522430a5e8faSwyllys 
522530a5e8faSwyllys end:
522630a5e8faSwyllys 	if (x != NULL)
522730a5e8faSwyllys 		X509_CRL_free(x);
522830a5e8faSwyllys 
522930a5e8faSwyllys 	if (crlfile != NULL)
523030a5e8faSwyllys 		free(crlfile);
523130a5e8faSwyllys 
523230a5e8faSwyllys 	if (in != NULL)
523330a5e8faSwyllys 		(void) BIO_free(in);
523430a5e8faSwyllys 
523530a5e8faSwyllys 	if (mem != NULL)
523630a5e8faSwyllys 		(void) BIO_free(mem);
523730a5e8faSwyllys 
523830a5e8faSwyllys 	return (ret);
523930a5e8faSwyllys }
524030a5e8faSwyllys 
524130a5e8faSwyllys KMF_RETURN
524230a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
524330a5e8faSwyllys {
524430a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
524530a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
524630a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
524730a5e8faSwyllys 	char *crlfile = NULL;
524830a5e8faSwyllys 	BIO *in = NULL;
524930a5e8faSwyllys 	char *crlfilename, *dirpath;
525030a5e8faSwyllys 
525130a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
525230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
525330a5e8faSwyllys 	}
525430a5e8faSwyllys 
525530a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
525630a5e8faSwyllys 	    attrlist, numattr);
525730a5e8faSwyllys 
525830a5e8faSwyllys 	if (crlfilename == NULL)
525930a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
526030a5e8faSwyllys 
526130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
526230a5e8faSwyllys 
526330a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
526430a5e8faSwyllys 
526530a5e8faSwyllys 	if (crlfile == NULL)
526630a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
526730a5e8faSwyllys 
526830a5e8faSwyllys 	if (isdir(crlfile)) {
526930a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
527030a5e8faSwyllys 		goto end;
527130a5e8faSwyllys 	}
527230a5e8faSwyllys 
527330a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
527430a5e8faSwyllys 	if (ret != KMF_OK)
527530a5e8faSwyllys 		goto end;
527630a5e8faSwyllys 
527730a5e8faSwyllys 	if (unlink(crlfile) != 0) {
527830a5e8faSwyllys 		SET_SYS_ERROR(kmfh, errno);
527930a5e8faSwyllys 		ret = KMF_ERR_INTERNAL;
528030a5e8faSwyllys 		goto end;
528130a5e8faSwyllys 	}
528230a5e8faSwyllys 
528330a5e8faSwyllys end:
528430a5e8faSwyllys 	if (in != NULL)
528530a5e8faSwyllys 		(void) BIO_free(in);
528630a5e8faSwyllys 	if (crlfile != NULL)
528730a5e8faSwyllys 		free(crlfile);
528830a5e8faSwyllys 
528930a5e8faSwyllys 	return (ret);
529030a5e8faSwyllys }
529130a5e8faSwyllys 
529230a5e8faSwyllys KMF_RETURN
529330a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
529430a5e8faSwyllys {
529530a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
529630a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
529730a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
529830a5e8faSwyllys 	BIO *in = NULL;
529930a5e8faSwyllys 	X509   *xcert = NULL;
530030a5e8faSwyllys 	X509_CRL   *xcrl = NULL;
530130a5e8faSwyllys 	STACK_OF(X509_REVOKED) *revoke_stack = NULL;
530230a5e8faSwyllys 	X509_REVOKED *revoke;
530330a5e8faSwyllys 	int i;
530430a5e8faSwyllys 	char *crlfilename, *crlfile, *dirpath, *certfile;
530530a5e8faSwyllys 
530630a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
530730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
530830a5e8faSwyllys 	}
530930a5e8faSwyllys 
531030a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
531130a5e8faSwyllys 	    attrlist, numattr);
531230a5e8faSwyllys 
531330a5e8faSwyllys 	if (crlfilename == NULL)
531430a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
531530a5e8faSwyllys 
531630a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
531730a5e8faSwyllys 	if (certfile == NULL)
531830a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
531930a5e8faSwyllys 
532030a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
532130a5e8faSwyllys 
532230a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
532330a5e8faSwyllys 
532430a5e8faSwyllys 	if (crlfile == NULL)
532530a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
532630a5e8faSwyllys 
532730a5e8faSwyllys 	if (isdir(crlfile)) {
532830a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
532930a5e8faSwyllys 		goto end;
533030a5e8faSwyllys 	}
533130a5e8faSwyllys 
533230a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
533330a5e8faSwyllys 	if (ret != KMF_OK)
533430a5e8faSwyllys 		goto end;
533530a5e8faSwyllys 
533630a5e8faSwyllys 	/* Read the CRL file and load it into a X509_CRL structure */
533730a5e8faSwyllys 	in = BIO_new_file(crlfilename, "rb");
533830a5e8faSwyllys 	if (in == NULL)	{
533930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
534030a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
534130a5e8faSwyllys 		goto end;
534230a5e8faSwyllys 	}
534330a5e8faSwyllys 
534430a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
534530a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
534630a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
534730a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
534830a5e8faSwyllys 	}
534930a5e8faSwyllys 
535030a5e8faSwyllys 	if (xcrl == NULL) {
535130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
535230a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
535330a5e8faSwyllys 		goto end;
535430a5e8faSwyllys 	}
535530a5e8faSwyllys 	(void) BIO_free(in);
535630a5e8faSwyllys 
535730a5e8faSwyllys 	/* Read the Certificate file and load it into a X509 structure */
535830a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
535930a5e8faSwyllys 	if (ret != KMF_OK)
536030a5e8faSwyllys 		goto end;
536130a5e8faSwyllys 
536230a5e8faSwyllys 	in = BIO_new_file(certfile, "rb");
536330a5e8faSwyllys 	if (in == NULL)	{
536430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
536530a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
536630a5e8faSwyllys 		goto end;
536730a5e8faSwyllys 	}
536830a5e8faSwyllys 
536930a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
537030a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
537130a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
537230a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
537330a5e8faSwyllys 	}
537430a5e8faSwyllys 
537530a5e8faSwyllys 	if (xcert == NULL) {
537630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
537730a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
537830a5e8faSwyllys 		goto end;
537930a5e8faSwyllys 	}
538030a5e8faSwyllys 
538130a5e8faSwyllys 	/* Check if the certificate and the CRL have same issuer */
538230a5e8faSwyllys 	if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) {
538330a5e8faSwyllys 		ret = KMF_ERR_ISSUER;
538430a5e8faSwyllys 		goto end;
538530a5e8faSwyllys 	}
538630a5e8faSwyllys 
538730a5e8faSwyllys 	/* Check to see if the certificate serial number is revoked */
538830a5e8faSwyllys 	revoke_stack = X509_CRL_get_REVOKED(xcrl);
538930a5e8faSwyllys 	if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
539030a5e8faSwyllys 		/* No revoked certificates in the CRL file */
539130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
539230a5e8faSwyllys 		ret = KMF_ERR_EMPTY_CRL;
539330a5e8faSwyllys 		goto end;
539430a5e8faSwyllys 	}
539530a5e8faSwyllys 
539630a5e8faSwyllys 	for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
5397a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
539830a5e8faSwyllys 		revoke = sk_X509_REVOKED_value(revoke_stack, i);
539930a5e8faSwyllys 		if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber,
540030a5e8faSwyllys 		    revoke->serialNumber) == 0) {
540130a5e8faSwyllys 			break;
540230a5e8faSwyllys 		}
540330a5e8faSwyllys 	}
540430a5e8faSwyllys 
540530a5e8faSwyllys 	if (i < sk_X509_REVOKED_num(revoke_stack)) {
540630a5e8faSwyllys 		ret = KMF_OK;
540730a5e8faSwyllys 	} else {
540830a5e8faSwyllys 		ret = KMF_ERR_NOT_REVOKED;
540930a5e8faSwyllys 	}
541030a5e8faSwyllys 
541130a5e8faSwyllys end:
541230a5e8faSwyllys 	if (in != NULL)
541330a5e8faSwyllys 		(void) BIO_free(in);
541430a5e8faSwyllys 	if (xcrl != NULL)
541530a5e8faSwyllys 		X509_CRL_free(xcrl);
541630a5e8faSwyllys 	if (xcert != NULL)
541730a5e8faSwyllys 		X509_free(xcert);
541830a5e8faSwyllys 
541930a5e8faSwyllys 	return (ret);
542030a5e8faSwyllys }
542130a5e8faSwyllys 
542230a5e8faSwyllys KMF_RETURN
542330a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
542430a5e8faSwyllys {
542530a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
542630a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
542730a5e8faSwyllys 	BIO		*bcrl = NULL;
542830a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
542930a5e8faSwyllys 	X509		*xcert = NULL;
543030a5e8faSwyllys 	EVP_PKEY	*pkey;
543130a5e8faSwyllys 	int		sslret;
543230a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
543330a5e8faSwyllys 	unsigned char	*p;
543430a5e8faSwyllys 	long		len;
543530a5e8faSwyllys 
543630a5e8faSwyllys 	if (handle == NULL || crlname == NULL || tacert == NULL) {
543730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
543830a5e8faSwyllys 	}
543930a5e8faSwyllys 
544030a5e8faSwyllys 	ret = kmf_get_file_format(crlname, &crl_format);
544130a5e8faSwyllys 	if (ret != KMF_OK)
544230a5e8faSwyllys 		return (ret);
544330a5e8faSwyllys 
544430a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
544530a5e8faSwyllys 	if (bcrl == NULL)	{
544630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
544730a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
544830a5e8faSwyllys 		goto cleanup;
544930a5e8faSwyllys 	}
545030a5e8faSwyllys 
545130a5e8faSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
545230a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
545330a5e8faSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
545430a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
545530a5e8faSwyllys 	} else {
545630a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
545730a5e8faSwyllys 		goto cleanup;
545830a5e8faSwyllys 	}
545930a5e8faSwyllys 
546030a5e8faSwyllys 	if (xcrl == NULL) {
546130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
546230a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
546330a5e8faSwyllys 		goto cleanup;
546430a5e8faSwyllys 	}
546530a5e8faSwyllys 
546630a5e8faSwyllys 	p = tacert->Data;
546730a5e8faSwyllys 	len = tacert->Length;
546830a5e8faSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
546930a5e8faSwyllys 
547030a5e8faSwyllys 	if (xcert == NULL) {
547130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
547230a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
547330a5e8faSwyllys 		goto cleanup;
547430a5e8faSwyllys 	}
547530a5e8faSwyllys 
547630a5e8faSwyllys 	/* Get issuer certificate public key */
547730a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
547830a5e8faSwyllys 	if (pkey == NULL) {
547930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
548030a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
548130a5e8faSwyllys 		goto cleanup;
548230a5e8faSwyllys 	}
548330a5e8faSwyllys 
548430a5e8faSwyllys 	/* Verify CRL signature */
548530a5e8faSwyllys 	sslret = X509_CRL_verify(xcrl, pkey);
548630a5e8faSwyllys 	EVP_PKEY_free(pkey);
548730a5e8faSwyllys 	if (sslret > 0) {
548830a5e8faSwyllys 		ret = KMF_OK;
548930a5e8faSwyllys 	} else {
549030a5e8faSwyllys 		SET_ERROR(kmfh, sslret);
549130a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
549230a5e8faSwyllys 	}
549330a5e8faSwyllys 
549430a5e8faSwyllys cleanup:
549530a5e8faSwyllys 	if (bcrl != NULL)
549630a5e8faSwyllys 		(void) BIO_free(bcrl);
549730a5e8faSwyllys 
549830a5e8faSwyllys 	if (xcrl != NULL)
549930a5e8faSwyllys 		X509_CRL_free(xcrl);
550030a5e8faSwyllys 
550130a5e8faSwyllys 	if (xcert != NULL)
550230a5e8faSwyllys 		X509_free(xcert);
550330a5e8faSwyllys 
550430a5e8faSwyllys 	return (ret);
550530a5e8faSwyllys 
550630a5e8faSwyllys }
550730a5e8faSwyllys 
550830a5e8faSwyllys KMF_RETURN
550930a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
551030a5e8faSwyllys {
551130a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
551230a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
551330a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
551430a5e8faSwyllys 	BIO		*bcrl = NULL;
551530a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
551630a5e8faSwyllys 	int		i;
551730a5e8faSwyllys 
551830a5e8faSwyllys 	if (handle == NULL || crlname == NULL) {
551930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
552030a5e8faSwyllys 	}
552130a5e8faSwyllys 
552230a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlname, &crl_format);
552330a5e8faSwyllys 	if (ret != KMF_OK)
552430a5e8faSwyllys 		return (ret);
552530a5e8faSwyllys 
552630a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
552730a5e8faSwyllys 	if (bcrl == NULL) {
552830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
552930a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
553030a5e8faSwyllys 		goto cleanup;
553130a5e8faSwyllys 	}
553230a5e8faSwyllys 
55335b3e1433Swyllys 	if (crl_format == KMF_FORMAT_ASN1)
553430a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
55355b3e1433Swyllys 	else if (crl_format == KMF_FORMAT_PEM)
553630a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
553730a5e8faSwyllys 
553830a5e8faSwyllys 	if (xcrl == NULL) {
553930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
554030a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
554130a5e8faSwyllys 		goto cleanup;
554230a5e8faSwyllys 	}
554330a5e8faSwyllys 	i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL);
554430a5e8faSwyllys 	if (i >= 0) {
554530a5e8faSwyllys 		ret = KMF_ERR_VALIDITY_PERIOD;
554630a5e8faSwyllys 		goto cleanup;
554730a5e8faSwyllys 	}
554830a5e8faSwyllys 	if (X509_CRL_get_nextUpdate(xcrl)) {
554930a5e8faSwyllys 		i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL);
555030a5e8faSwyllys 
555130a5e8faSwyllys 		if (i <= 0) {
555230a5e8faSwyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
555330a5e8faSwyllys 			goto cleanup;
555430a5e8faSwyllys 		}
555530a5e8faSwyllys 	}
555630a5e8faSwyllys 
555730a5e8faSwyllys 	ret = KMF_OK;
555830a5e8faSwyllys 
555930a5e8faSwyllys cleanup:
556030a5e8faSwyllys 	if (bcrl != NULL)
556130a5e8faSwyllys 		(void) BIO_free(bcrl);
556230a5e8faSwyllys 
556330a5e8faSwyllys 	if (xcrl != NULL)
556430a5e8faSwyllys 		X509_CRL_free(xcrl);
556530a5e8faSwyllys 
556630a5e8faSwyllys 	return (ret);
556730a5e8faSwyllys }
5568