199ebb4caSwyllys /*
2*a2d4930dSDan 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 
26202744e81Swyllys KMF_RETURN
26302744e81Swyllys OpenSSL_VerifyDataWithCert(KMF_HANDLE_T, KMF_ALGORITHM_INDEX,
26402744e81Swyllys 	KMF_DATA *, KMF_DATA *, KMF_DATA *);
26502744e81Swyllys 
26699ebb4caSwyllys static
26799ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table =
26899ebb4caSwyllys {
26999ebb4caSwyllys 	1,				/* Version */
27099ebb4caSwyllys 	NULL, /* ConfigureKeystore */
27199ebb4caSwyllys 	OpenSSL_FindCert,
27299ebb4caSwyllys 	OpenSSL_FreeKMFCert,
27399ebb4caSwyllys 	OpenSSL_StoreCert,
27499ebb4caSwyllys 	NULL, /* ImportCert */
27599ebb4caSwyllys 	OpenSSL_ImportCRL,
27699ebb4caSwyllys 	OpenSSL_DeleteCert,
27799ebb4caSwyllys 	OpenSSL_DeleteCRL,
27899ebb4caSwyllys 	OpenSSL_CreateKeypair,
27999ebb4caSwyllys 	OpenSSL_FindKey,
28099ebb4caSwyllys 	OpenSSL_EncodePubKeyData,
28199ebb4caSwyllys 	OpenSSL_SignData,
28299ebb4caSwyllys 	OpenSSL_DeleteKey,
28399ebb4caSwyllys 	OpenSSL_ListCRL,
28499ebb4caSwyllys 	NULL,	/* FindCRL */
28599ebb4caSwyllys 	OpenSSL_FindCertInCRL,
28699ebb4caSwyllys 	OpenSSL_GetErrorString,
28730a5e8faSwyllys 	OpenSSL_FindPrikeyByCert,
28899ebb4caSwyllys 	OpenSSL_DecryptData,
28930a5e8faSwyllys 	OpenSSL_ExportPK12,
29099ebb4caSwyllys 	OpenSSL_CreateSymKey,
29199ebb4caSwyllys 	OpenSSL_GetSymKeyValue,
29299ebb4caSwyllys 	NULL,	/* SetTokenPin */
29302744e81Swyllys 	OpenSSL_VerifyDataWithCert,
29430a5e8faSwyllys 	OpenSSL_StoreKey,
29599ebb4caSwyllys 	NULL	/* Finalize */
29699ebb4caSwyllys };
29799ebb4caSwyllys 
29899ebb4caSwyllys static mutex_t *lock_cs;
29999ebb4caSwyllys static long *lock_count;
30099ebb4caSwyllys 
30199ebb4caSwyllys static void
302*a2d4930dSDan OpenSolaris Anderson /* ARGSUSED1 */
30399ebb4caSwyllys locking_cb(int mode, int type, char *file, int line)
30499ebb4caSwyllys {
30599ebb4caSwyllys 	if (mode & CRYPTO_LOCK) {
30699ebb4caSwyllys 		(void) mutex_lock(&(lock_cs[type]));
30799ebb4caSwyllys 		lock_count[type]++;
30899ebb4caSwyllys 	} else {
30999ebb4caSwyllys 		(void) mutex_unlock(&(lock_cs[type]));
31099ebb4caSwyllys 	}
31199ebb4caSwyllys }
31299ebb4caSwyllys 
31399ebb4caSwyllys static unsigned long
31499ebb4caSwyllys thread_id()
31599ebb4caSwyllys {
31699ebb4caSwyllys 	return ((unsigned long)thr_self());
31799ebb4caSwyllys }
31899ebb4caSwyllys 
31999ebb4caSwyllys KMF_PLUGIN_FUNCLIST *
32099ebb4caSwyllys KMF_Plugin_Initialize()
32199ebb4caSwyllys {
32299ebb4caSwyllys 	int i;
32399ebb4caSwyllys 
32499ebb4caSwyllys 	(void) mutex_lock(&init_lock);
32599ebb4caSwyllys 	if (!ssl_initialized) {
32699ebb4caSwyllys 		OpenSSL_add_all_algorithms();
32799ebb4caSwyllys 
32899ebb4caSwyllys 		/* Enable error strings for reporting */
32999ebb4caSwyllys 		ERR_load_crypto_strings();
33099ebb4caSwyllys 
33199ebb4caSwyllys 		/*
33299ebb4caSwyllys 		 * Add support for extension OIDs that are not yet in the
33399ebb4caSwyllys 		 * openssl default set.
33499ebb4caSwyllys 		 */
33599ebb4caSwyllys 		(void) OBJ_create("2.5.29.30", "nameConstraints",
33699ebb4caSwyllys 		    "X509v3 Name Constraints");
33799ebb4caSwyllys 		(void) OBJ_create("2.5.29.33", "policyMappings",
33899ebb4caSwyllys 		    "X509v3 Policy Mappings");
33999ebb4caSwyllys 		(void) OBJ_create("2.5.29.36", "policyConstraints",
34099ebb4caSwyllys 		    "X509v3 Policy Constraints");
34199ebb4caSwyllys 		(void) OBJ_create("2.5.29.46", "freshestCRL",
34299ebb4caSwyllys 		    "X509v3 Freshest CRL");
34399ebb4caSwyllys 		(void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
34499ebb4caSwyllys 		    "X509v3 Inhibit Any-Policy");
34599ebb4caSwyllys 		/*
34699ebb4caSwyllys 		 * Set up for thread-safe operation.
34799ebb4caSwyllys 		 */
34899ebb4caSwyllys 		lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
34999ebb4caSwyllys 		if (lock_cs == NULL) {
35099ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
35199ebb4caSwyllys 			return (NULL);
35299ebb4caSwyllys 		}
35399ebb4caSwyllys 
35499ebb4caSwyllys 		lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
35599ebb4caSwyllys 		if (lock_count == NULL) {
35699ebb4caSwyllys 			OPENSSL_free(lock_cs);
35799ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
35899ebb4caSwyllys 			return (NULL);
35999ebb4caSwyllys 		}
36099ebb4caSwyllys 
36199ebb4caSwyllys 		for (i = 0; i < CRYPTO_num_locks(); i++) {
36299ebb4caSwyllys 			lock_count[i] = 0;
36399ebb4caSwyllys 			(void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
36499ebb4caSwyllys 		}
36599ebb4caSwyllys 
36699ebb4caSwyllys 		CRYPTO_set_id_callback((unsigned long (*)())thread_id);
36799ebb4caSwyllys 		CRYPTO_set_locking_callback((void (*)())locking_cb);
36899ebb4caSwyllys 		ssl_initialized = 1;
36999ebb4caSwyllys 	}
37099ebb4caSwyllys 	(void) mutex_unlock(&init_lock);
37199ebb4caSwyllys 
37299ebb4caSwyllys 	return (&openssl_plugin_table);
37399ebb4caSwyllys }
37499ebb4caSwyllys /*
37599ebb4caSwyllys  * Convert an SSL DN to a KMF DN.
37699ebb4caSwyllys  */
37799ebb4caSwyllys static KMF_RETURN
37899ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
37999ebb4caSwyllys {
38099ebb4caSwyllys 	KMF_DATA derdata;
38199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
38299ebb4caSwyllys 	uchar_t *tmp;
38399ebb4caSwyllys 
38499ebb4caSwyllys 	/* Convert to raw DER format */
38599ebb4caSwyllys 	derdata.Length = i2d_X509_NAME(sslDN, NULL);
38699ebb4caSwyllys 	if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
38799ebb4caSwyllys 	    == NULL) {
38899ebb4caSwyllys 		return (KMF_ERR_MEMORY);
38999ebb4caSwyllys 	}
39099ebb4caSwyllys 	(void) i2d_X509_NAME(sslDN, &tmp);
39199ebb4caSwyllys 
39299ebb4caSwyllys 	/* Decode to KMF format */
39399ebb4caSwyllys 	rv = DerDecodeName(&derdata, kmfDN);
39499ebb4caSwyllys 	if (rv != KMF_OK) {
39599ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
39699ebb4caSwyllys 	}
39799ebb4caSwyllys 	OPENSSL_free(derdata.Data);
39899ebb4caSwyllys 
39999ebb4caSwyllys 	return (rv);
40099ebb4caSwyllys }
40199ebb4caSwyllys 
40230a5e8faSwyllys int
40399ebb4caSwyllys isdir(char *path)
40499ebb4caSwyllys {
40599ebb4caSwyllys 	struct stat s;
40699ebb4caSwyllys 
40799ebb4caSwyllys 	if (stat(path, &s) == -1)
40899ebb4caSwyllys 		return (0);
40999ebb4caSwyllys 
41030a5e8faSwyllys 	return ((s.st_mode & S_IFMT) == S_IFDIR);
41199ebb4caSwyllys }
41299ebb4caSwyllys 
41399ebb4caSwyllys static KMF_RETURN
41499ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
41599ebb4caSwyllys {
41699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
41799ebb4caSwyllys 	unsigned char *buf = NULL, *p;
41899ebb4caSwyllys 	int len;
41999ebb4caSwyllys 
42099ebb4caSwyllys 	/*
42199ebb4caSwyllys 	 * Convert the X509 internal struct to DER encoded data
42299ebb4caSwyllys 	 */
42399ebb4caSwyllys 	if ((len = i2d_X509(x509cert, NULL)) < 0) {
42499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
42599ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
42699ebb4caSwyllys 		goto cleanup;
42799ebb4caSwyllys 	}
42899ebb4caSwyllys 	if ((buf = malloc(len)) == NULL) {
42999ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
43099ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
43199ebb4caSwyllys 		goto cleanup;
43299ebb4caSwyllys 	}
43399ebb4caSwyllys 
43499ebb4caSwyllys 	/*
43599ebb4caSwyllys 	 * i2d_X509 will increment the buf pointer so that we need to
43699ebb4caSwyllys 	 * save it.
43799ebb4caSwyllys 	 */
43899ebb4caSwyllys 	p = buf;
43999ebb4caSwyllys 	if ((len = i2d_X509(x509cert, &p)) < 0) {
44099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
44199ebb4caSwyllys 		free(buf);
44299ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
44399ebb4caSwyllys 		goto cleanup;
44499ebb4caSwyllys 	}
44599ebb4caSwyllys 
44699ebb4caSwyllys 	/* caller's responsibility to free it */
44799ebb4caSwyllys 	cert->Data = buf;
44899ebb4caSwyllys 	cert->Length = len;
44999ebb4caSwyllys 
45099ebb4caSwyllys cleanup:
45199ebb4caSwyllys 	if (rv != KMF_OK) {
45299ebb4caSwyllys 		if (buf)
45399ebb4caSwyllys 			free(buf);
45499ebb4caSwyllys 		cert->Data = NULL;
45599ebb4caSwyllys 		cert->Length = 0;
45699ebb4caSwyllys 	}
45799ebb4caSwyllys 
45899ebb4caSwyllys 	return (rv);
45999ebb4caSwyllys }
46099ebb4caSwyllys 
46130a5e8faSwyllys 
46299ebb4caSwyllys static KMF_RETURN
46330a5e8faSwyllys check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
46430a5e8faSwyllys     boolean_t *match)
46599ebb4caSwyllys {
46699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
46799ebb4caSwyllys 	boolean_t findIssuer = FALSE;
46899ebb4caSwyllys 	boolean_t findSubject = FALSE;
46999ebb4caSwyllys 	boolean_t findSerial = FALSE;
47099ebb4caSwyllys 	KMF_X509_NAME issuerDN, subjectDN;
47199ebb4caSwyllys 	KMF_X509_NAME certIssuerDN, certSubjectDN;
47299ebb4caSwyllys 
47399ebb4caSwyllys 	*match = FALSE;
47499ebb4caSwyllys 	if (xcert == NULL) {
47599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
47699ebb4caSwyllys 	}
47799ebb4caSwyllys 
47899ebb4caSwyllys 	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
47999ebb4caSwyllys 	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
48099ebb4caSwyllys 	(void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
48199ebb4caSwyllys 	(void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
48299ebb4caSwyllys 
48330a5e8faSwyllys 	if (issuer != NULL && strlen(issuer)) {
48430a5e8faSwyllys 		rv = kmf_dn_parser(issuer, &issuerDN);
48599ebb4caSwyllys 		if (rv != KMF_OK)
48699ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
48799ebb4caSwyllys 
48899ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->issuer, &certIssuerDN);
48999ebb4caSwyllys 		if (rv != KMF_OK) {
49030a5e8faSwyllys 			kmf_free_dn(&issuerDN);
49199ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
49299ebb4caSwyllys 		}
49399ebb4caSwyllys 
49499ebb4caSwyllys 		findIssuer = TRUE;
49599ebb4caSwyllys 	}
49630a5e8faSwyllys 	if (subject != NULL && strlen(subject)) {
49730a5e8faSwyllys 		rv = kmf_dn_parser(subject, &subjectDN);
49899ebb4caSwyllys 		if (rv != KMF_OK) {
49999ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
50099ebb4caSwyllys 			goto cleanup;
50199ebb4caSwyllys 		}
50299ebb4caSwyllys 
50399ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->subject, &certSubjectDN);
50499ebb4caSwyllys 		if (rv != KMF_OK) {
50599ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
50699ebb4caSwyllys 			goto cleanup;
50799ebb4caSwyllys 		}
50899ebb4caSwyllys 		findSubject = TRUE;
50999ebb4caSwyllys 	}
51030a5e8faSwyllys 	if (serial != NULL && serial->val != NULL)
51199ebb4caSwyllys 		findSerial = TRUE;
51299ebb4caSwyllys 
51399ebb4caSwyllys 	if (findSerial) {
51499ebb4caSwyllys 		BIGNUM *bn;
51599ebb4caSwyllys 
51699ebb4caSwyllys 		/* Comparing BIGNUMs is a pain! */
51799ebb4caSwyllys 		bn = ASN1_INTEGER_to_BN(xcert->cert_info->serialNumber, NULL);
51899ebb4caSwyllys 		if (bn != NULL) {
51999ebb4caSwyllys 			int bnlen = BN_num_bytes(bn);
52099ebb4caSwyllys 
52130a5e8faSwyllys 			if (bnlen == serial->len) {
52299ebb4caSwyllys 				uchar_t *a = malloc(bnlen);
52399ebb4caSwyllys 				if (a == NULL) {
52499ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
52599ebb4caSwyllys 					BN_free(bn);
52699ebb4caSwyllys 					goto cleanup;
52799ebb4caSwyllys 				}
52899ebb4caSwyllys 				bnlen = BN_bn2bin(bn, a);
52930a5e8faSwyllys 				*match = (memcmp(a, serial->val, serial->len) ==
53030a5e8faSwyllys 				    0);
53199ebb4caSwyllys 				rv = KMF_OK;
53299ebb4caSwyllys 				free(a);
53399ebb4caSwyllys 			}
53499ebb4caSwyllys 			BN_free(bn);
53599ebb4caSwyllys 			if (!(*match))
53699ebb4caSwyllys 				goto cleanup;
53799ebb4caSwyllys 		} else {
53899ebb4caSwyllys 			rv = KMF_OK;
53999ebb4caSwyllys 			goto cleanup;
54099ebb4caSwyllys 		}
54199ebb4caSwyllys 	}
54299ebb4caSwyllys 	if (findIssuer) {
54330a5e8faSwyllys 		*match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
54430a5e8faSwyllys 		if ((*match) == B_FALSE) {
54530a5e8faSwyllys 			/* stop checking and bail */
54699ebb4caSwyllys 			rv = KMF_OK;
54799ebb4caSwyllys 			goto cleanup;
54899ebb4caSwyllys 		}
54999ebb4caSwyllys 	}
55099ebb4caSwyllys 	if (findSubject) {
55130a5e8faSwyllys 		*match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
55230a5e8faSwyllys 		if ((*match) == B_FALSE) {
55330a5e8faSwyllys 			/* stop checking and bail */
55499ebb4caSwyllys 			rv = KMF_OK;
55599ebb4caSwyllys 			goto cleanup;
55699ebb4caSwyllys 		}
55799ebb4caSwyllys 	}
55899ebb4caSwyllys 
55999ebb4caSwyllys 	*match = TRUE;
56099ebb4caSwyllys cleanup:
56199ebb4caSwyllys 	if (findIssuer) {
56230a5e8faSwyllys 		kmf_free_dn(&issuerDN);
56330a5e8faSwyllys 		kmf_free_dn(&certIssuerDN);
56499ebb4caSwyllys 	}
56599ebb4caSwyllys 	if (findSubject) {
56630a5e8faSwyllys 		kmf_free_dn(&subjectDN);
56730a5e8faSwyllys 		kmf_free_dn(&certSubjectDN);
56899ebb4caSwyllys 	}
56999ebb4caSwyllys 
57099ebb4caSwyllys 	return (rv);
57199ebb4caSwyllys }
57299ebb4caSwyllys 
57330a5e8faSwyllys 
57430a5e8faSwyllys /*
57530a5e8faSwyllys  * This function loads a certificate file into an X509 data structure, and
57630a5e8faSwyllys  * checks if its issuer, subject or the serial number matches with those
57730a5e8faSwyllys  * values.  If it matches, then return the X509 data structure.
57830a5e8faSwyllys  */
57999ebb4caSwyllys static KMF_RETURN
58099ebb4caSwyllys load_X509cert(KMF_HANDLE *kmfh,
58130a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
58230a5e8faSwyllys     char *pathname, X509 **outcert)
58399ebb4caSwyllys {
58499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
58599ebb4caSwyllys 	X509 *xcert = NULL;
58699ebb4caSwyllys 	BIO *bcert = NULL;
58799ebb4caSwyllys 	boolean_t  match = FALSE;
58899ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
58999ebb4caSwyllys 
59099ebb4caSwyllys 	/*
59199ebb4caSwyllys 	 * auto-detect the file format, regardless of what
59299ebb4caSwyllys 	 * the 'format' parameters in the params say.
59399ebb4caSwyllys 	 */
59430a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
59599ebb4caSwyllys 	if (rv != KMF_OK) {
59699ebb4caSwyllys 		if (rv == KMF_ERR_OPEN_FILE)
59799ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
59899ebb4caSwyllys 		return (rv);
59999ebb4caSwyllys 	}
60099ebb4caSwyllys 
60199ebb4caSwyllys 	/* Not ASN1(DER) format */
60299ebb4caSwyllys 	if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
60399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
60499ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
60599ebb4caSwyllys 		goto cleanup;
60699ebb4caSwyllys 	}
60799ebb4caSwyllys 
60899ebb4caSwyllys 	if (format == KMF_FORMAT_PEM)
60999ebb4caSwyllys 		xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
61099ebb4caSwyllys 	else if (format == KMF_FORMAT_ASN1)
61199ebb4caSwyllys 		xcert = d2i_X509_bio(bcert, NULL);
61299ebb4caSwyllys 	else if (format == KMF_FORMAT_PKCS12) {
61399ebb4caSwyllys 		PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
61499ebb4caSwyllys 		if (p12 != NULL) {
61599ebb4caSwyllys 			(void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
61699ebb4caSwyllys 			PKCS12_free(p12);
61799ebb4caSwyllys 			p12 = NULL;
61899ebb4caSwyllys 		} else {
61999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
62099ebb4caSwyllys 			rv = KMF_ERR_BAD_CERT_FORMAT;
62199ebb4caSwyllys 		}
62299ebb4caSwyllys 	} else {
62399ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
62499ebb4caSwyllys 		goto cleanup;
62599ebb4caSwyllys 	}
62699ebb4caSwyllys 
62799ebb4caSwyllys 	if (xcert == NULL) {
62899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
62999ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
63099ebb4caSwyllys 		goto cleanup;
63199ebb4caSwyllys 	}
63299ebb4caSwyllys 
63330a5e8faSwyllys 	if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
63430a5e8faSwyllys 	    match == FALSE) {
63599ebb4caSwyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
63699ebb4caSwyllys 		goto cleanup;
63799ebb4caSwyllys 	}
63899ebb4caSwyllys 
63999ebb4caSwyllys 	if (outcert != NULL) {
64099ebb4caSwyllys 		*outcert = xcert;
64199ebb4caSwyllys 	}
64299ebb4caSwyllys 
64399ebb4caSwyllys cleanup:
64499ebb4caSwyllys 	if (bcert != NULL) (void) BIO_free(bcert);
64599ebb4caSwyllys 	if (rv != KMF_OK && xcert != NULL)
64699ebb4caSwyllys 		X509_free(xcert);
64799ebb4caSwyllys 
64899ebb4caSwyllys 	return (rv);
64999ebb4caSwyllys }
65099ebb4caSwyllys 
65171593db2Swyllys static int
65271593db2Swyllys datacmp(const void *a, const void *b)
65371593db2Swyllys {
65471593db2Swyllys 	KMF_DATA *adata = (KMF_DATA *)a;
65571593db2Swyllys 	KMF_DATA *bdata = (KMF_DATA *)b;
65671593db2Swyllys 	if (adata->Length > bdata->Length)
65771593db2Swyllys 		return (-1);
65871593db2Swyllys 	if (adata->Length < bdata->Length)
65971593db2Swyllys 		return (1);
66071593db2Swyllys 	return (0);
66171593db2Swyllys }
66271593db2Swyllys 
66371593db2Swyllys static KMF_RETURN
66430a5e8faSwyllys load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
66530a5e8faSwyllys     KMF_CERT_VALIDITY validity, char *pathname,
66671593db2Swyllys     KMF_DATA **certlist, uint32_t *numcerts)
66771593db2Swyllys {
66871593db2Swyllys 	KMF_RETURN rv = KMF_OK;
66971593db2Swyllys 	int i;
67071593db2Swyllys 	KMF_DATA *certs = NULL;
67171593db2Swyllys 	int nc = 0;
67271593db2Swyllys 	int hits = 0;
67371593db2Swyllys 	KMF_ENCODE_FORMAT format;
67471593db2Swyllys 
67530a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
67671593db2Swyllys 	if (rv != KMF_OK) {
67771593db2Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
67871593db2Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
67971593db2Swyllys 		return (rv);
68071593db2Swyllys 	}
681*a2d4930dSDan OpenSolaris Anderson 
68271593db2Swyllys 	if (format == KMF_FORMAT_ASN1) {
68371593db2Swyllys 		/* load a single certificate */
68471593db2Swyllys 		certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
68571593db2Swyllys 		if (certs == NULL)
68671593db2Swyllys 			return (KMF_ERR_MEMORY);
68771593db2Swyllys 		certs->Data = NULL;
68871593db2Swyllys 		certs->Length = 0;
68930a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
69030a5e8faSwyllys 		    pathname, certs);
69171593db2Swyllys 		if (rv == KMF_OK) {
69271593db2Swyllys 			*certlist = certs;
69371593db2Swyllys 			*numcerts = 1;
694*a2d4930dSDan OpenSolaris Anderson 		} else {
695*a2d4930dSDan OpenSolaris Anderson 			kmf_free_data(certs);
696*a2d4930dSDan OpenSolaris Anderson 			free(certs);
697*a2d4930dSDan OpenSolaris Anderson 			certs = NULL;
69871593db2Swyllys 		}
69971593db2Swyllys 		return (rv);
700*a2d4930dSDan OpenSolaris Anderson 
70171593db2Swyllys 	} else if (format == KMF_FORMAT_PKCS12) {
70271593db2Swyllys 		/* We need a credential to access a PKCS#12 file */
70371593db2Swyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
704*a2d4930dSDan OpenSolaris Anderson 
70571593db2Swyllys 	} else if (format == KMF_FORMAT_PEM ||
70671593db2Swyllys 	    format != KMF_FORMAT_PEM_KEYPAIR) {
70771593db2Swyllys 		/* This function only works on PEM files */
70830a5e8faSwyllys 		rv = extract_pem(kmfh, issuer, subject, serial, pathname,
70934acef67Swyllys 		    (uchar_t *)NULL, 0, NULL, &certs, &nc);
71071593db2Swyllys 	} else {
71171593db2Swyllys 		return (KMF_ERR_ENCODING);
71271593db2Swyllys 	}
71371593db2Swyllys 
71471593db2Swyllys 	if (rv != KMF_OK)
71571593db2Swyllys 		return (rv);
71671593db2Swyllys 
71771593db2Swyllys 	for (i = 0; i < nc; i++) {
71830a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
71930a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
72030a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
72130a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
72271593db2Swyllys 			if (rv == KMF_OK)
72371593db2Swyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
72471593db2Swyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD)
72571593db2Swyllys 				rv = KMF_OK;
72671593db2Swyllys 		}
727*a2d4930dSDan OpenSolaris Anderson 
72871593db2Swyllys 		if (rv != KMF_OK) {
72971593db2Swyllys 			/* Remove this cert from the list by clearing it. */
73030a5e8faSwyllys 			kmf_free_data(&certs[i]);
73171593db2Swyllys 		} else {
73271593db2Swyllys 			hits++; /* count valid certs found */
73371593db2Swyllys 		}
73471593db2Swyllys 		rv = KMF_OK;
73571593db2Swyllys 	}
736*a2d4930dSDan OpenSolaris Anderson 
737*a2d4930dSDan OpenSolaris Anderson 	if (rv == KMF_OK && hits > 0) {
73871593db2Swyllys 		/*
73971593db2Swyllys 		 * Sort the list of certs by length to put the cleared ones
74071593db2Swyllys 		 * at the end so they don't get accessed by the caller.
74171593db2Swyllys 		 */
74271593db2Swyllys 		qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
74371593db2Swyllys 		*certlist = certs;
74471593db2Swyllys 
74571593db2Swyllys 		/* since we sorted the list, just return the number of hits */
74671593db2Swyllys 		*numcerts = hits;
747*a2d4930dSDan OpenSolaris Anderson 
748*a2d4930dSDan OpenSolaris Anderson 	} else {
749*a2d4930dSDan OpenSolaris Anderson 		if (rv == KMF_OK && hits == 0) {
750*a2d4930dSDan OpenSolaris Anderson 			rv = KMF_ERR_CERT_NOT_FOUND;
75171593db2Swyllys 		}
752*a2d4930dSDan OpenSolaris Anderson 
753*a2d4930dSDan OpenSolaris Anderson 		if (certs != NULL) {
754*a2d4930dSDan OpenSolaris Anderson 			kmf_free_data(certs);
755*a2d4930dSDan OpenSolaris Anderson 			free(certs);
756*a2d4930dSDan OpenSolaris Anderson 			certs = NULL;
757*a2d4930dSDan OpenSolaris Anderson 		}
758*a2d4930dSDan OpenSolaris Anderson 	}
759*a2d4930dSDan OpenSolaris Anderson 
76071593db2Swyllys 	return (rv);
76171593db2Swyllys }
76271593db2Swyllys 
76330a5e8faSwyllys 
76499ebb4caSwyllys static KMF_RETURN
76599ebb4caSwyllys kmf_load_cert(KMF_HANDLE *kmfh,
76630a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
76730a5e8faSwyllys     KMF_CERT_VALIDITY validity,
76899ebb4caSwyllys     char *pathname,
76999ebb4caSwyllys     KMF_DATA *cert)
77099ebb4caSwyllys {
77199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
77299ebb4caSwyllys 	X509 *x509cert = NULL;
77399ebb4caSwyllys 
77430a5e8faSwyllys 	rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
77599ebb4caSwyllys 	if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
77699ebb4caSwyllys 		rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
77799ebb4caSwyllys 		if (rv != KMF_OK) {
77899ebb4caSwyllys 			goto cleanup;
77999ebb4caSwyllys 		}
78030a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
78130a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
78230a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
78330a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
78499ebb4caSwyllys 			if (rv == KMF_OK)  {
78599ebb4caSwyllys 				/*
78699ebb4caSwyllys 				 * This is a valid cert so skip it.
78799ebb4caSwyllys 				 */
78899ebb4caSwyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
78999ebb4caSwyllys 			}
79099ebb4caSwyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD) {
79199ebb4caSwyllys 				/*
79299ebb4caSwyllys 				 * We want to return success when we
79399ebb4caSwyllys 				 * find an invalid cert.
79499ebb4caSwyllys 				 */
79599ebb4caSwyllys 				rv = KMF_OK;
79699ebb4caSwyllys 				goto cleanup;
79799ebb4caSwyllys 			}
79899ebb4caSwyllys 		}
79999ebb4caSwyllys 	}
80099ebb4caSwyllys cleanup:
80199ebb4caSwyllys 	if (x509cert != NULL)
80299ebb4caSwyllys 		X509_free(x509cert);
80399ebb4caSwyllys 
80499ebb4caSwyllys 	return (rv);
80599ebb4caSwyllys }
80699ebb4caSwyllys 
80702744e81Swyllys static KMF_RETURN
80802744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
80902744e81Swyllys {
81002744e81Swyllys 	KMF_RETURN ret = KMF_OK;
81102744e81Swyllys 	KMF_RAW_RSA_KEY rsa;
81202744e81Swyllys 	BerElement *asn1 = NULL;
81302744e81Swyllys 	BerValue filebuf;
81402744e81Swyllys 	BerValue OID = { NULL, 0 };
81502744e81Swyllys 	BerValue *Mod = NULL, *PubExp = NULL;
81602744e81Swyllys 	BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
81702744e81Swyllys 	BerValue *Coef = NULL;
81802744e81Swyllys 	BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
81902744e81Swyllys 	BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
82002744e81Swyllys 	BIGNUM *qminus1 = NULL;
82102744e81Swyllys 	BN_CTX *ctx = NULL;
82202744e81Swyllys 
82302744e81Swyllys 	*pkey = NULL;
82402744e81Swyllys 
82502744e81Swyllys 	filebuf.bv_val = (char *)filedata->Data;
82602744e81Swyllys 	filebuf.bv_len = filedata->Length;
82702744e81Swyllys 
82802744e81Swyllys 	asn1 = kmfder_init(&filebuf);
82902744e81Swyllys 	if (asn1 == NULL) {
83002744e81Swyllys 		ret = KMF_ERR_MEMORY;
83102744e81Swyllys 		goto out;
83202744e81Swyllys 	}
83302744e81Swyllys 
83402744e81Swyllys 	if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
83502744e81Swyllys 	    &OID, &Mod, &PubExp, &PriExp, &Prime1,
83602744e81Swyllys 	    &Prime2, &Coef) == -1)  {
83702744e81Swyllys 		ret = KMF_ERR_ENCODING;
83802744e81Swyllys 		goto out;
83902744e81Swyllys 	}
84002744e81Swyllys 
84102744e81Swyllys 	/*
84202744e81Swyllys 	 * We have to derive the 2 Exponents using Bignumber math.
84302744e81Swyllys 	 * Exp1 = PriExp mod (Prime1 - 1)
84402744e81Swyllys 	 * Exp2 = PriExp mod (Prime2 - 1)
84502744e81Swyllys 	 */
84602744e81Swyllys 
84702744e81Swyllys 	/* D = PrivateExponent */
84802744e81Swyllys 	D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
84902744e81Swyllys 	if (D == NULL) {
85002744e81Swyllys 		ret = KMF_ERR_MEMORY;
85102744e81Swyllys 		goto out;
85202744e81Swyllys 	}
85302744e81Swyllys 
85402744e81Swyllys 	/* P = Prime1 (first prime factor of Modulus) */
85502744e81Swyllys 	P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
85602744e81Swyllys 	if (D == NULL) {
85702744e81Swyllys 		ret = KMF_ERR_MEMORY;
85802744e81Swyllys 		goto out;
85902744e81Swyllys 	}
86002744e81Swyllys 
86102744e81Swyllys 	/* Q = Prime2 (second prime factor of Modulus) */
86202744e81Swyllys 	Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
86302744e81Swyllys 
86402744e81Swyllys 	if ((ctx = BN_CTX_new()) == NULL) {
86502744e81Swyllys 		ret = KMF_ERR_MEMORY;
86602744e81Swyllys 		goto out;
86702744e81Swyllys 	}
86802744e81Swyllys 
86902744e81Swyllys 	/* Compute (P - 1) */
87002744e81Swyllys 	pminus1 = BN_new();
87102744e81Swyllys 	(void) BN_sub(pminus1, P, BN_value_one());
87202744e81Swyllys 
87302744e81Swyllys 	/* Exponent1 = D mod (P - 1) */
87402744e81Swyllys 	Exp1 = BN_new();
87502744e81Swyllys 	(void) BN_mod(Exp1, D, pminus1, ctx);
87602744e81Swyllys 
87702744e81Swyllys 	/* Compute (Q - 1) */
87802744e81Swyllys 	qminus1 = BN_new();
87902744e81Swyllys 	(void) BN_sub(qminus1, Q, BN_value_one());
88002744e81Swyllys 
88102744e81Swyllys 	/* Exponent2 = D mod (Q - 1) */
88202744e81Swyllys 	Exp2 = BN_new();
88302744e81Swyllys 	(void) BN_mod(Exp2, D, qminus1, ctx);
88402744e81Swyllys 
88502744e81Swyllys 	/* Coef = (Inverse Q) mod P */
88602744e81Swyllys 	COEF = BN_new();
88702744e81Swyllys 	(void) BN_mod_inverse(COEF, Q, P, ctx);
88802744e81Swyllys 
88902744e81Swyllys 	/* Convert back to KMF format */
89002744e81Swyllys 	(void) memset(&rsa, 0, sizeof (rsa));
89102744e81Swyllys 
89202744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
89302744e81Swyllys 		goto out;
89402744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
89502744e81Swyllys 		goto out;
89602744e81Swyllys 	if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
89702744e81Swyllys 		goto out;
89802744e81Swyllys 
89902744e81Swyllys 	rsa.mod.val = (uchar_t *)Mod->bv_val;
90002744e81Swyllys 	rsa.mod.len = Mod->bv_len;
90102744e81Swyllys 
90202744e81Swyllys 	rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
90302744e81Swyllys 	rsa.pubexp.len = PubExp->bv_len;
90402744e81Swyllys 
90502744e81Swyllys 	rsa.priexp.val = (uchar_t *)PriExp->bv_val;
90602744e81Swyllys 	rsa.priexp.len = PriExp->bv_len;
90702744e81Swyllys 
90802744e81Swyllys 	rsa.prime1.val = (uchar_t *)Prime1->bv_val;
90902744e81Swyllys 	rsa.prime1.len = Prime1->bv_len;
91002744e81Swyllys 
91102744e81Swyllys 	rsa.prime2.val = (uchar_t *)Prime2->bv_val;
91202744e81Swyllys 	rsa.prime2.len = Prime2->bv_len;
91302744e81Swyllys 
91402744e81Swyllys 	*pkey = ImportRawRSAKey(&rsa);
91502744e81Swyllys out:
91602744e81Swyllys 	if (asn1 != NULL)
91702744e81Swyllys 		kmfber_free(asn1, 1);
91802744e81Swyllys 
91902744e81Swyllys 	if (OID.bv_val) {
92002744e81Swyllys 		free(OID.bv_val);
92102744e81Swyllys 	}
92202744e81Swyllys 	if (PriExp)
92302744e81Swyllys 		free(PriExp);
92402744e81Swyllys 
92502744e81Swyllys 	if (Mod)
92602744e81Swyllys 		free(Mod);
92702744e81Swyllys 
92802744e81Swyllys 	if (PubExp)
92902744e81Swyllys 		free(PubExp);
93002744e81Swyllys 
93102744e81Swyllys 	if (Coef) {
93202744e81Swyllys 		(void) memset(Coef->bv_val, 0, Coef->bv_len);
93302744e81Swyllys 		free(Coef->bv_val);
93402744e81Swyllys 		free(Coef);
93502744e81Swyllys 	}
93602744e81Swyllys 	if (Prime1)
93702744e81Swyllys 		free(Prime1);
93802744e81Swyllys 	if (Prime2)
93902744e81Swyllys 		free(Prime2);
94002744e81Swyllys 
94102744e81Swyllys 	if (ctx != NULL)
94202744e81Swyllys 		BN_CTX_free(ctx);
94302744e81Swyllys 
94402744e81Swyllys 	if (D)
94502744e81Swyllys 		BN_clear_free(D);
94602744e81Swyllys 	if (P)
94702744e81Swyllys 		BN_clear_free(P);
94802744e81Swyllys 	if (Q)
94902744e81Swyllys 		BN_clear_free(Q);
95002744e81Swyllys 	if (pminus1)
95102744e81Swyllys 		BN_clear_free(pminus1);
95202744e81Swyllys 	if (qminus1)
95302744e81Swyllys 		BN_clear_free(qminus1);
95402744e81Swyllys 	if (Exp1)
95502744e81Swyllys 		BN_clear_free(Exp1);
95602744e81Swyllys 	if (Exp2)
95702744e81Swyllys 		BN_clear_free(Exp2);
95802744e81Swyllys 
95902744e81Swyllys 	return (ret);
96002744e81Swyllys 
96102744e81Swyllys }
96202744e81Swyllys 
96399ebb4caSwyllys static EVP_PKEY *
96499ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file)
96599ebb4caSwyllys {
96699ebb4caSwyllys 	BIO *keyfile = NULL;
96799ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
96899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
96999ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
97002744e81Swyllys 	KMF_RETURN rv;
97102744e81Swyllys 	KMF_DATA filedata;
97299ebb4caSwyllys 
97399ebb4caSwyllys 	if (file == NULL) {
97499ebb4caSwyllys 		return (NULL);
97599ebb4caSwyllys 	}
97699ebb4caSwyllys 
97730a5e8faSwyllys 	if (kmf_get_file_format((char *)file, &format) != KMF_OK)
97899ebb4caSwyllys 		return (NULL);
97999ebb4caSwyllys 
98099ebb4caSwyllys 	keyfile = BIO_new_file(file, "rb");
98199ebb4caSwyllys 	if (keyfile == NULL) {
98299ebb4caSwyllys 		goto end;
98399ebb4caSwyllys 	}
98499ebb4caSwyllys 
98502744e81Swyllys 	if (format == KMF_FORMAT_ASN1) {
98699ebb4caSwyllys 		pkey = d2i_PrivateKey_bio(keyfile, NULL);
98702744e81Swyllys 		if (pkey == NULL) {
98802744e81Swyllys 
98902744e81Swyllys 			(void) BIO_free(keyfile);
99002744e81Swyllys 			keyfile = NULL;
99102744e81Swyllys 			/* Try odd ASN.1 variations */
99230a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
99302744e81Swyllys 			    &filedata);
99402744e81Swyllys 			if (rv == KMF_OK) {
99502744e81Swyllys 				(void) readAltFormatPrivateKey(&filedata,
99602744e81Swyllys 				    &pkey);
99730a5e8faSwyllys 				kmf_free_data(&filedata);
99802744e81Swyllys 			}
99902744e81Swyllys 		}
100002744e81Swyllys 	} else if (format == KMF_FORMAT_PEM ||
100102744e81Swyllys 	    format == KMF_FORMAT_PEM_KEYPAIR) {
100299ebb4caSwyllys 		pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
100302744e81Swyllys 		if (pkey == NULL) {
100402744e81Swyllys 			KMF_DATA derdata;
100502744e81Swyllys 			/*
100602744e81Swyllys 			 * Check if this is the alt. format
100702744e81Swyllys 			 * RSA private key file.
100802744e81Swyllys 			 */
100930a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
101002744e81Swyllys 			    &filedata);
101102744e81Swyllys 			if (rv == KMF_OK) {
101202744e81Swyllys 				uchar_t *d = NULL;
101302744e81Swyllys 				int len;
101430a5e8faSwyllys 				rv = kmf_pem_to_der(filedata.Data,
101502744e81Swyllys 				    filedata.Length, &d, &len);
101602744e81Swyllys 				if (rv == KMF_OK && d != NULL) {
101702744e81Swyllys 					derdata.Data = d;
101802744e81Swyllys 					derdata.Length = (size_t)len;
101902744e81Swyllys 					(void) readAltFormatPrivateKey(
102002744e81Swyllys 					    &derdata, &pkey);
102102744e81Swyllys 					free(d);
102202744e81Swyllys 				}
102330a5e8faSwyllys 				kmf_free_data(&filedata);
102402744e81Swyllys 			}
102502744e81Swyllys 		}
102602744e81Swyllys 	}
102799ebb4caSwyllys 
102899ebb4caSwyllys end:
102999ebb4caSwyllys 	if (pkey == NULL)
103099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
103199ebb4caSwyllys 
103299ebb4caSwyllys 	if (keyfile != NULL)
103399ebb4caSwyllys 		(void) BIO_free(keyfile);
103499ebb4caSwyllys 
103599ebb4caSwyllys 	return (pkey);
103699ebb4caSwyllys }
103799ebb4caSwyllys 
103899ebb4caSwyllys KMF_RETURN
103930a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
104099ebb4caSwyllys {
104199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
104299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1043f482c776Swyllys 	int i, n;
1044f482c776Swyllys 	uint32_t maxcerts = 0;
104530a5e8faSwyllys 	uint32_t *num_certs;
104630a5e8faSwyllys 	KMF_X509_DER_CERT *kmf_cert = NULL;
104730a5e8faSwyllys 	char *dirpath = NULL;
104830a5e8faSwyllys 	char *filename = NULL;
104930a5e8faSwyllys 	char *fullpath = NULL;
105030a5e8faSwyllys 	char *issuer = NULL;
105130a5e8faSwyllys 	char *subject = NULL;
105230a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
105330a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
105499ebb4caSwyllys 
105530a5e8faSwyllys 	num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
105630a5e8faSwyllys 	if (num_certs == NULL)
105799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
105899ebb4caSwyllys 
105930a5e8faSwyllys 	/* num_certs should reference the size of kmf_cert */
1060f482c776Swyllys 	maxcerts = *num_certs;
1061f482c776Swyllys 	if (maxcerts == 0)
1062f482c776Swyllys 		maxcerts = 0xFFFFFFFF;
106399ebb4caSwyllys 	*num_certs = 0;
106499ebb4caSwyllys 
106530a5e8faSwyllys 	/* Get the optional returned certificate list  */
106630a5e8faSwyllys 	kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
106730a5e8faSwyllys 	    numattr);
106899ebb4caSwyllys 
106930a5e8faSwyllys 	/*
107030a5e8faSwyllys 	 * The dirpath attribute and the filename attribute can not be NULL
107130a5e8faSwyllys 	 * at the same time.
107230a5e8faSwyllys 	 */
107330a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
107430a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
107530a5e8faSwyllys 	    numattr);
107630a5e8faSwyllys 
107730a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
107899ebb4caSwyllys 	if (fullpath == NULL)
107999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
108099ebb4caSwyllys 
108130a5e8faSwyllys 	/* Get optional search criteria attributes */
108230a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
108330a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
108430a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
108530a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
108630a5e8faSwyllys 	    &validity, NULL);
108730a5e8faSwyllys 	if (rv != KMF_OK) {
108830a5e8faSwyllys 		validity = KMF_ALL_CERTS;
108930a5e8faSwyllys 		rv = KMF_OK;
109030a5e8faSwyllys 	}
109130a5e8faSwyllys 
109299ebb4caSwyllys 	if (isdir(fullpath)) {
109399ebb4caSwyllys 		DIR *dirp;
109499ebb4caSwyllys 		struct dirent *dp;
109599ebb4caSwyllys 
1096f482c776Swyllys 		n = 0;
109799ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
109899ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
109999ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
110099ebb4caSwyllys 		}
110199ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
110299ebb4caSwyllys 			char *fname;
110371593db2Swyllys 			KMF_DATA *certlist = NULL;
1104f482c776Swyllys 			uint32_t loaded_certs = 0;
110571593db2Swyllys 
110699ebb4caSwyllys 			if (strcmp(dp->d_name, ".") == 0 ||
110799ebb4caSwyllys 			    strcmp(dp->d_name, "..") == 0)
110899ebb4caSwyllys 				continue;
110999ebb4caSwyllys 
111034acef67Swyllys 			fname = get_fullpath(fullpath, (char *)&dp->d_name);
111199ebb4caSwyllys 
111230a5e8faSwyllys 			rv = load_certs(kmfh, issuer, subject, serial,
111330a5e8faSwyllys 			    validity, fname, &certlist,	&loaded_certs);
111499ebb4caSwyllys 
111599ebb4caSwyllys 			if (rv != KMF_OK) {
111699ebb4caSwyllys 				free(fname);
111771593db2Swyllys 				if (certlist != NULL) {
1118f482c776Swyllys 					for (i = 0; i < loaded_certs; i++)
111930a5e8faSwyllys 						kmf_free_data(&certlist[i]);
112071593db2Swyllys 					free(certlist);
112171593db2Swyllys 				}
112299ebb4caSwyllys 				continue;
112399ebb4caSwyllys 			}
112499ebb4caSwyllys 
112599ebb4caSwyllys 			/* If load succeeds, add certdata to the list */
112699ebb4caSwyllys 			if (kmf_cert != NULL) {
1127f482c776Swyllys 				for (i = 0; i < loaded_certs &&
1128b4058258Swyllys 				    n < maxcerts; i++) {
112971593db2Swyllys 					kmf_cert[n].certificate.Data =
113071593db2Swyllys 					    certlist[i].Data;
113199ebb4caSwyllys 					kmf_cert[n].certificate.Length =
113271593db2Swyllys 					    certlist[i].Length;
113399ebb4caSwyllys 
113499ebb4caSwyllys 					kmf_cert[n].kmf_private.keystore_type =
113599ebb4caSwyllys 					    KMF_KEYSTORE_OPENSSL;
113699ebb4caSwyllys 					kmf_cert[n].kmf_private.flags =
113799ebb4caSwyllys 					    KMF_FLAG_CERT_VALID;
113871593db2Swyllys 					kmf_cert[n].kmf_private.label =
113971593db2Swyllys 					    strdup(fname);
114099ebb4caSwyllys 					n++;
114199ebb4caSwyllys 				}
1142b4058258Swyllys 				/*
1143b4058258Swyllys 				 * If maxcerts < loaded_certs, clean up the
1144b4058258Swyllys 				 * certs that were not used.
1145b4058258Swyllys 				 */
1146f482c776Swyllys 				for (; i < loaded_certs; i++)
114730a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1148f482c776Swyllys 			} else {
1149f482c776Swyllys 				for (i = 0; i < loaded_certs; i++)
115030a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1151f482c776Swyllys 				n += loaded_certs;
115271593db2Swyllys 			}
1153f482c776Swyllys 			free(certlist);
115471593db2Swyllys 			free(fname);
115571593db2Swyllys 		}
115699ebb4caSwyllys 		(*num_certs) = n;
115799ebb4caSwyllys 		if (*num_certs == 0)
115899ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
115930a5e8faSwyllys 		if (*num_certs > 0)
116099ebb4caSwyllys 			rv = KMF_OK;
116199ebb4caSwyllys exit:
116299ebb4caSwyllys 		(void) closedir(dirp);
116399ebb4caSwyllys 	} else {
116471593db2Swyllys 		KMF_DATA *certlist = NULL;
1165f482c776Swyllys 		uint32_t loaded_certs = 0;
116671593db2Swyllys 
116730a5e8faSwyllys 		rv = load_certs(kmfh, issuer, subject, serial, validity,
116830a5e8faSwyllys 		    fullpath, &certlist, &loaded_certs);
116999ebb4caSwyllys 		if (rv != KMF_OK) {
117099ebb4caSwyllys 			free(fullpath);
117199ebb4caSwyllys 			return (rv);
117299ebb4caSwyllys 		}
117399ebb4caSwyllys 
1174f482c776Swyllys 		n = 0;
117571593db2Swyllys 		if (kmf_cert != NULL && certlist != NULL) {
1176f482c776Swyllys 			for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1177f482c776Swyllys 				kmf_cert[n].certificate.Data =
117871593db2Swyllys 				    certlist[i].Data;
1179f482c776Swyllys 				kmf_cert[n].certificate.Length =
118071593db2Swyllys 				    certlist[i].Length;
1181f482c776Swyllys 				kmf_cert[n].kmf_private.keystore_type =
118299ebb4caSwyllys 				    KMF_KEYSTORE_OPENSSL;
1183f482c776Swyllys 				kmf_cert[n].kmf_private.flags =
118471593db2Swyllys 				    KMF_FLAG_CERT_VALID;
1185f482c776Swyllys 				kmf_cert[n].kmf_private.label =
118671593db2Swyllys 				    strdup(fullpath);
1187f482c776Swyllys 				n++;
118871593db2Swyllys 			}
1189f482c776Swyllys 			/* If maxcerts < loaded_certs, clean up */
1190f482c776Swyllys 			for (; i < loaded_certs; i++)
119130a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1192f482c776Swyllys 		} else if (certlist != NULL) {
1193f482c776Swyllys 			for (i = 0; i < loaded_certs; i++)
119430a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1195f482c776Swyllys 			n = loaded_certs;
1196f482c776Swyllys 		}
119730a5e8faSwyllys 		if (certlist != NULL)
119871593db2Swyllys 			free(certlist);
1199f482c776Swyllys 		*num_certs = n;
120099ebb4caSwyllys 	}
120199ebb4caSwyllys 
120299ebb4caSwyllys 	free(fullpath);
120399ebb4caSwyllys 
120499ebb4caSwyllys 	return (rv);
120599ebb4caSwyllys }
120699ebb4caSwyllys 
120799ebb4caSwyllys void
120899ebb4caSwyllys /*ARGSUSED*/
120999ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
121099ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert)
121199ebb4caSwyllys {
121299ebb4caSwyllys 	if (kmf_cert != NULL) {
121399ebb4caSwyllys 		if (kmf_cert->certificate.Data != NULL) {
121499ebb4caSwyllys 			free(kmf_cert->certificate.Data);
121599ebb4caSwyllys 			kmf_cert->certificate.Data = NULL;
121699ebb4caSwyllys 			kmf_cert->certificate.Length = 0;
121799ebb4caSwyllys 		}
121899ebb4caSwyllys 		if (kmf_cert->kmf_private.label)
121999ebb4caSwyllys 			free(kmf_cert->kmf_private.label);
122099ebb4caSwyllys 	}
122199ebb4caSwyllys }
122299ebb4caSwyllys 
122330a5e8faSwyllys /*ARGSUSED*/
122499ebb4caSwyllys KMF_RETURN
122530a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
122699ebb4caSwyllys {
122799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
122830a5e8faSwyllys 	KMF_DATA *cert = NULL;
122930a5e8faSwyllys 	char *outfilename = NULL;
123030a5e8faSwyllys 	char *dirpath = NULL;
123130a5e8faSwyllys 	char *fullpath = NULL;
123299ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
123399ebb4caSwyllys 
123430a5e8faSwyllys 	/* Get the cert data */
123530a5e8faSwyllys 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
123630a5e8faSwyllys 	if (cert == NULL || cert->Data == NULL)
123799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
123899ebb4caSwyllys 
123930a5e8faSwyllys 	/* Check the output filename and directory attributes. */
124030a5e8faSwyllys 	outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
124130a5e8faSwyllys 	    numattr);
124230a5e8faSwyllys 	if (outfilename == NULL)
124330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
124499ebb4caSwyllys 
124530a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
124630a5e8faSwyllys 	fullpath = get_fullpath(dirpath, outfilename);
124799ebb4caSwyllys 	if (fullpath == NULL)
124830a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
124999ebb4caSwyllys 
125030a5e8faSwyllys 	/* Check the optional format attribute */
125130a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
125230a5e8faSwyllys 	    &format, NULL);
125330a5e8faSwyllys 	if (ret != KMF_OK) {
125430a5e8faSwyllys 		/* If there is no format attribute, then default to PEM */
125530a5e8faSwyllys 		format = KMF_FORMAT_PEM;
125699ebb4caSwyllys 		ret = KMF_OK;
125730a5e8faSwyllys 	} else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
125830a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
125999ebb4caSwyllys 		goto out;
126099ebb4caSwyllys 	}
126199ebb4caSwyllys 
126230a5e8faSwyllys 	/* Store the certificate in the file with the specified format */
126330a5e8faSwyllys 	ret = kmf_create_cert_file(cert, format, fullpath);
126499ebb4caSwyllys 
126599ebb4caSwyllys out:
126699ebb4caSwyllys 	if (fullpath != NULL)
126799ebb4caSwyllys 		free(fullpath);
126899ebb4caSwyllys 
126999ebb4caSwyllys 	return (ret);
127099ebb4caSwyllys }
127199ebb4caSwyllys 
127230a5e8faSwyllys 
127399ebb4caSwyllys KMF_RETURN
127430a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
127599ebb4caSwyllys {
127699ebb4caSwyllys 	KMF_RETURN rv;
127799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
127899ebb4caSwyllys 	KMF_DATA certdata = {NULL, 0};
127930a5e8faSwyllys 	char *dirpath = NULL;
128030a5e8faSwyllys 	char *filename = NULL;
128130a5e8faSwyllys 	char *fullpath = NULL;
128230a5e8faSwyllys 	char *issuer = NULL;
128330a5e8faSwyllys 	char *subject = NULL;
128430a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
128530a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
128699ebb4caSwyllys 
128730a5e8faSwyllys 	/*
128830a5e8faSwyllys 	 * Get the DIRPATH and CERT_FILENAME attributes.  They can not be
128930a5e8faSwyllys 	 * NULL at the same time.
129030a5e8faSwyllys 	 */
129130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
129230a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
129330a5e8faSwyllys 	    numattr);
129430a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
129599ebb4caSwyllys 	if (fullpath == NULL)
129699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
129799ebb4caSwyllys 
129830a5e8faSwyllys 	/* Get optional search criteria attributes */
129930a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
130030a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
130130a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
130230a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
130330a5e8faSwyllys 	    &validity, NULL);
130430a5e8faSwyllys 	if (rv != KMF_OK) {
130530a5e8faSwyllys 		validity = KMF_ALL_CERTS;
130630a5e8faSwyllys 		rv = KMF_OK;
130730a5e8faSwyllys 	}
130830a5e8faSwyllys 
130999ebb4caSwyllys 	if (isdir(fullpath)) {
131099ebb4caSwyllys 		DIR *dirp;
131199ebb4caSwyllys 		struct dirent *dp;
131299ebb4caSwyllys 
131399ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
131499ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
131599ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
131699ebb4caSwyllys 		}
131799ebb4caSwyllys 
131899ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
131999ebb4caSwyllys 			if (strcmp(dp->d_name, ".") != 0 &&
132099ebb4caSwyllys 			    strcmp(dp->d_name, "..") != 0) {
132199ebb4caSwyllys 				char *fname;
132299ebb4caSwyllys 
132399ebb4caSwyllys 				fname = get_fullpath(fullpath,
132499ebb4caSwyllys 				    (char *)&dp->d_name);
132599ebb4caSwyllys 
132699ebb4caSwyllys 				if (fname == NULL) {
132799ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
132899ebb4caSwyllys 					break;
132999ebb4caSwyllys 				}
133099ebb4caSwyllys 
133130a5e8faSwyllys 				rv = kmf_load_cert(kmfh, issuer, subject,
133230a5e8faSwyllys 				    serial, validity, fname, &certdata);
133399ebb4caSwyllys 
133499ebb4caSwyllys 				if (rv == KMF_ERR_CERT_NOT_FOUND) {
133599ebb4caSwyllys 					free(fname);
133699ebb4caSwyllys 					if (certdata.Data)
133799ebb4caSwyllys 						free(certdata.Data);
133899ebb4caSwyllys 					rv = KMF_OK;
133999ebb4caSwyllys 					continue;
134099ebb4caSwyllys 				} else if (rv != KMF_OK) {
134199ebb4caSwyllys 					free(fname);
134299ebb4caSwyllys 					break;
134399ebb4caSwyllys 				}
134499ebb4caSwyllys 
134599ebb4caSwyllys 				if (unlink(fname) != 0) {
134699ebb4caSwyllys 					SET_SYS_ERROR(kmfh, errno);
134799ebb4caSwyllys 					rv = KMF_ERR_INTERNAL;
134899ebb4caSwyllys 					free(fname);
134999ebb4caSwyllys 					break;
135099ebb4caSwyllys 				}
135199ebb4caSwyllys 				free(fname);
135299ebb4caSwyllys 				if (certdata.Data)
135399ebb4caSwyllys 					free(certdata.Data);
135499ebb4caSwyllys 			}
135599ebb4caSwyllys 		}
135699ebb4caSwyllys 		(void) closedir(dirp);
135799ebb4caSwyllys 	} else {
135899ebb4caSwyllys 		/* Just try to load a single certificate */
135930a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
136030a5e8faSwyllys 		    fullpath, &certdata);
136199ebb4caSwyllys 		if (rv == KMF_OK) {
136299ebb4caSwyllys 			if (unlink(fullpath) != 0) {
136399ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
136499ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
136599ebb4caSwyllys 			}
136699ebb4caSwyllys 		}
136799ebb4caSwyllys 	}
136899ebb4caSwyllys 
136999ebb4caSwyllys out:
137099ebb4caSwyllys 	if (fullpath != NULL)
137199ebb4caSwyllys 		free(fullpath);
137299ebb4caSwyllys 
137399ebb4caSwyllys 	if (certdata.Data)
137499ebb4caSwyllys 		free(certdata.Data);
137599ebb4caSwyllys 
137699ebb4caSwyllys 	return (rv);
137799ebb4caSwyllys }
137899ebb4caSwyllys 
137999ebb4caSwyllys KMF_RETURN
138099ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
138199ebb4caSwyllys 	KMF_DATA *keydata)
138299ebb4caSwyllys {
138399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
138499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
138599ebb4caSwyllys 	int n;
138699ebb4caSwyllys 
138799ebb4caSwyllys 	if (key == NULL || keydata == NULL ||
138899ebb4caSwyllys 	    key->keyp == NULL)
138999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
139099ebb4caSwyllys 
139199ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
139299ebb4caSwyllys 		RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
139399ebb4caSwyllys 
139499ebb4caSwyllys 		if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
139599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
139699ebb4caSwyllys 			return (KMF_ERR_ENCODING);
139799ebb4caSwyllys 		}
139899ebb4caSwyllys 		RSA_free(pubkey);
139999ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
140099ebb4caSwyllys 		DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
140199ebb4caSwyllys 
140299ebb4caSwyllys 		if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
140399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
140499ebb4caSwyllys 			return (KMF_ERR_ENCODING);
140599ebb4caSwyllys 		}
140699ebb4caSwyllys 		DSA_free(pubkey);
140799ebb4caSwyllys 	} else {
140899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
140999ebb4caSwyllys 	}
141099ebb4caSwyllys 	keydata->Length = n;
141199ebb4caSwyllys 
141299ebb4caSwyllys cleanup:
141399ebb4caSwyllys 	if (rv != KMF_OK) {
141499ebb4caSwyllys 		if (keydata->Data)
141599ebb4caSwyllys 			free(keydata->Data);
141699ebb4caSwyllys 		keydata->Data = NULL;
141799ebb4caSwyllys 		keydata->Length = 0;
141899ebb4caSwyllys 	}
141999ebb4caSwyllys 
142099ebb4caSwyllys 	return (rv);
142199ebb4caSwyllys }
142299ebb4caSwyllys 
142399ebb4caSwyllys static KMF_RETURN
142430a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
142530a5e8faSwyllys 	KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
142699ebb4caSwyllys {
142799ebb4caSwyllys 	int rv = 0;
142899ebb4caSwyllys 	RSA *rsa;
142999ebb4caSwyllys 	DSA *dsa;
143099ebb4caSwyllys 
14315b3e1433Swyllys 	if (pkey == NULL || out == NULL)
14325b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
14335b3e1433Swyllys 
143499ebb4caSwyllys 	switch (format) {
143573cc0e02Swyllys 		case KMF_FORMAT_RAWKEY:
143673cc0e02Swyllys 			/* same as ASN.1 */
143799ebb4caSwyllys 		case KMF_FORMAT_ASN1:
143899ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
143999ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
144030a5e8faSwyllys 				if (private)
144199ebb4caSwyllys 					rv = i2d_RSAPrivateKey_bio(out, rsa);
144230a5e8faSwyllys 				else
144330a5e8faSwyllys 					rv = i2d_RSAPublicKey_bio(out, rsa);
144499ebb4caSwyllys 				RSA_free(rsa);
144599ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
144699ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
144799ebb4caSwyllys 				rv = i2d_DSAPrivateKey_bio(out, dsa);
144899ebb4caSwyllys 				DSA_free(dsa);
144999ebb4caSwyllys 			}
145099ebb4caSwyllys 			if (rv == 1) {
145199ebb4caSwyllys 				rv = KMF_OK;
145299ebb4caSwyllys 			} else {
145399ebb4caSwyllys 				SET_ERROR(kmfh, rv);
145499ebb4caSwyllys 			}
145599ebb4caSwyllys 			break;
145699ebb4caSwyllys 		case KMF_FORMAT_PEM:
145799ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
145899ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
145930a5e8faSwyllys 				if (private)
146099ebb4caSwyllys 					rv = PEM_write_bio_RSAPrivateKey(out,
146130a5e8faSwyllys 					    rsa, NULL, NULL, 0, NULL,
146230a5e8faSwyllys 					    (cred != NULL ? cred->cred : NULL));
146330a5e8faSwyllys 				else
146430a5e8faSwyllys 					rv = PEM_write_bio_RSAPublicKey(out,
146530a5e8faSwyllys 					    rsa);
146699ebb4caSwyllys 				RSA_free(rsa);
146799ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
146899ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
146999ebb4caSwyllys 				rv = PEM_write_bio_DSAPrivateKey(out,
147030a5e8faSwyllys 				    dsa, NULL, NULL, 0, NULL,
147130a5e8faSwyllys 				    (cred != NULL ? cred->cred : NULL));
147299ebb4caSwyllys 				DSA_free(dsa);
147399ebb4caSwyllys 			}
147499ebb4caSwyllys 
147599ebb4caSwyllys 			if (rv == 1) {
147699ebb4caSwyllys 				rv = KMF_OK;
147799ebb4caSwyllys 			} else {
147899ebb4caSwyllys 				SET_ERROR(kmfh, rv);
147999ebb4caSwyllys 			}
148099ebb4caSwyllys 			break;
148199ebb4caSwyllys 
148299ebb4caSwyllys 		default:
148399ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
148499ebb4caSwyllys 	}
148599ebb4caSwyllys 
148699ebb4caSwyllys 	return (rv);
148799ebb4caSwyllys }
148899ebb4caSwyllys 
148999ebb4caSwyllys KMF_RETURN
149030a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
149130a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
149299ebb4caSwyllys {
149399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
149499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
149599ebb4caSwyllys 	uint32_t eValue = 0x010001;
149699ebb4caSwyllys 	RSA *sslPrivKey = NULL;
149799ebb4caSwyllys 	DSA *sslDSAKey = NULL;
149899ebb4caSwyllys 	EVP_PKEY *eprikey = NULL;
149999ebb4caSwyllys 	EVP_PKEY *epubkey = NULL;
150099ebb4caSwyllys 	BIO *out = NULL;
150130a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
150230a5e8faSwyllys 	uint32_t keylen = 1024;
150330a5e8faSwyllys 	uint32_t keylen_size = sizeof (uint32_t);
150430a5e8faSwyllys 	boolean_t storekey = TRUE;
150530a5e8faSwyllys 	KMF_KEY_ALG keytype = KMF_RSA;
150699ebb4caSwyllys 
150730a5e8faSwyllys 	rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
150830a5e8faSwyllys 	    &storekey, NULL);
150930a5e8faSwyllys 	if (rv != KMF_OK) {
151030a5e8faSwyllys 		/* "storekey" is optional. Default is TRUE */
151130a5e8faSwyllys 		rv = KMF_OK;
151299ebb4caSwyllys 	}
151399ebb4caSwyllys 
151430a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
151530a5e8faSwyllys 	    (void *)&keytype, NULL);
151630a5e8faSwyllys 	if (rv != KMF_OK)
151730a5e8faSwyllys 		/* keytype is optional.  KMF_RSA is default */
151830a5e8faSwyllys 		rv = KMF_OK;
151999ebb4caSwyllys 
152030a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
152130a5e8faSwyllys 	if (pubkey == NULL)
152299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
152399ebb4caSwyllys 
152430a5e8faSwyllys 	privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
152530a5e8faSwyllys 	if (privkey == NULL)
152630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
152730a5e8faSwyllys 
152830a5e8faSwyllys 	(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
152930a5e8faSwyllys 	(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
153099ebb4caSwyllys 
153199ebb4caSwyllys 	eprikey = EVP_PKEY_new();
153299ebb4caSwyllys 	if (eprikey == NULL) {
153399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
153499ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
153599ebb4caSwyllys 		goto cleanup;
153699ebb4caSwyllys 	}
153799ebb4caSwyllys 	epubkey = EVP_PKEY_new();
153899ebb4caSwyllys 	if (epubkey == NULL) {
153999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
154099ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
154199ebb4caSwyllys 		goto cleanup;
154299ebb4caSwyllys 	}
154330a5e8faSwyllys 	if (keytype == KMF_RSA) {
154430a5e8faSwyllys 		KMF_BIGINT *rsaexp = NULL;
154599ebb4caSwyllys 
154630a5e8faSwyllys 		rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
154730a5e8faSwyllys 		if (rsaexp != NULL) {
154830a5e8faSwyllys 			if (rsaexp->len > 0 &&
154930a5e8faSwyllys 			    rsaexp->len <= sizeof (eValue) &&
155030a5e8faSwyllys 			    rsaexp->val != NULL) {
1551*a2d4930dSDan OpenSolaris Anderson 				/* LINTED E_BAD_PTR_CAST_ALIGN */
155230a5e8faSwyllys 				eValue = *(uint32_t *)rsaexp->val;
155330a5e8faSwyllys 			} else {
155430a5e8faSwyllys 				rv = KMF_ERR_BAD_PARAMETER;
155530a5e8faSwyllys 				goto cleanup;
155630a5e8faSwyllys 			}
155730a5e8faSwyllys 		} else {
155830a5e8faSwyllys 			/* RSA Exponent is optional. Default is 0x10001 */
155930a5e8faSwyllys 			rv = KMF_OK;
156030a5e8faSwyllys 		}
156130a5e8faSwyllys 
156230a5e8faSwyllys 		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
156330a5e8faSwyllys 		    &keylen, &keylen_size);
156430a5e8faSwyllys 		if (rv == KMF_ERR_ATTR_NOT_FOUND)
156530a5e8faSwyllys 			/* keylen is optional, default is 1024 */
156630a5e8faSwyllys 			rv = KMF_OK;
156730a5e8faSwyllys 		if (rv != KMF_OK) {
156830a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
156930a5e8faSwyllys 			goto cleanup;
157030a5e8faSwyllys 		}
157130a5e8faSwyllys 
157230a5e8faSwyllys 		sslPrivKey = RSA_generate_key(keylen, eValue, NULL, NULL);
157399ebb4caSwyllys 		if (sslPrivKey == NULL) {
157499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
157599ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
157699ebb4caSwyllys 		} else {
157730a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
157899ebb4caSwyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
157999ebb4caSwyllys 			privkey->keyalg = KMF_RSA;
158099ebb4caSwyllys 			privkey->keyclass = KMF_ASYM_PRI;
158199ebb4caSwyllys 			privkey->israw = FALSE;
158299ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
158330a5e8faSwyllys 
158499ebb4caSwyllys 			/* OpenSSL derives the public key from the private */
158530a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
158699ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
158799ebb4caSwyllys 			pubkey->keyalg = KMF_RSA;
158899ebb4caSwyllys 			pubkey->israw = FALSE;
158999ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
159099ebb4caSwyllys 			pubkey->keyp = (void *)epubkey;
159199ebb4caSwyllys 		}
159230a5e8faSwyllys 	} else if (keytype == KMF_DSA) {
159330a5e8faSwyllys 		DSA *dp;
159499ebb4caSwyllys 		sslDSAKey = DSA_new();
159599ebb4caSwyllys 		if (sslDSAKey == NULL) {
159699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
159799ebb4caSwyllys 			return (KMF_ERR_MEMORY);
159899ebb4caSwyllys 		}
159999ebb4caSwyllys 
160099ebb4caSwyllys 		if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) ==
160199ebb4caSwyllys 		    NULL) {
160299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
160399ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
160499ebb4caSwyllys 			goto cleanup;
160599ebb4caSwyllys 		}
160699ebb4caSwyllys 		if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) ==
160799ebb4caSwyllys 		    NULL) {
160899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
160999ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
161099ebb4caSwyllys 			goto cleanup;
161199ebb4caSwyllys 		}
161299ebb4caSwyllys 		if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) ==
161399ebb4caSwyllys 		    NULL) {
161499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
161599ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
161699ebb4caSwyllys 			goto cleanup;
161799ebb4caSwyllys 		}
161899ebb4caSwyllys 
161999ebb4caSwyllys 		if (!DSA_generate_key(sslDSAKey)) {
162099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
162199ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
162299ebb4caSwyllys 			goto cleanup;
162399ebb4caSwyllys 		}
162499ebb4caSwyllys 
162599ebb4caSwyllys 		privkey->kstype = KMF_KEYSTORE_OPENSSL;
162699ebb4caSwyllys 		privkey->keyalg = KMF_DSA;
162799ebb4caSwyllys 		privkey->keyclass = KMF_ASYM_PRI;
162899ebb4caSwyllys 		privkey->israw = FALSE;
162999ebb4caSwyllys 		if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
163099ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
163199ebb4caSwyllys 		} else {
163299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
163399ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
163499ebb4caSwyllys 			goto cleanup;
163599ebb4caSwyllys 		}
163630a5e8faSwyllys 		dp = DSA_new();
163799ebb4caSwyllys 		/* Make a copy for the public key */
163899ebb4caSwyllys 		if (dp != NULL) {
163999ebb4caSwyllys 			if ((dp->p = BN_new()) == NULL) {
164099ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
164199ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
164299ebb4caSwyllys 				DSA_free(dp);
164399ebb4caSwyllys 				goto cleanup;
164499ebb4caSwyllys 			}
164599ebb4caSwyllys 			if ((dp->q = BN_new()) == NULL) {
164699ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
164799ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
164899ebb4caSwyllys 				BN_free(dp->p);
164999ebb4caSwyllys 				DSA_free(dp);
165099ebb4caSwyllys 				goto cleanup;
165199ebb4caSwyllys 			}
165299ebb4caSwyllys 			if ((dp->g = BN_new()) == NULL) {
165399ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
165499ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
165599ebb4caSwyllys 				BN_free(dp->q);
165699ebb4caSwyllys 				BN_free(dp->p);
165799ebb4caSwyllys 				DSA_free(dp);
165899ebb4caSwyllys 				goto cleanup;
165999ebb4caSwyllys 			}
166099ebb4caSwyllys 			if ((dp->pub_key = BN_new()) == NULL) {
166199ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
166299ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
166399ebb4caSwyllys 				BN_free(dp->q);
166499ebb4caSwyllys 				BN_free(dp->p);
166599ebb4caSwyllys 				BN_free(dp->g);
166699ebb4caSwyllys 				DSA_free(dp);
166799ebb4caSwyllys 				goto cleanup;
166899ebb4caSwyllys 			}
166999ebb4caSwyllys 			(void) BN_copy(dp->p, sslDSAKey->p);
167099ebb4caSwyllys 			(void) BN_copy(dp->q, sslDSAKey->q);
167199ebb4caSwyllys 			(void) BN_copy(dp->g, sslDSAKey->g);
167299ebb4caSwyllys 			(void) BN_copy(dp->pub_key, sslDSAKey->pub_key);
167399ebb4caSwyllys 
167499ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
167599ebb4caSwyllys 			pubkey->keyalg = KMF_DSA;
167699ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
167799ebb4caSwyllys 			pubkey->israw = FALSE;
167899ebb4caSwyllys 
167999ebb4caSwyllys 			if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
168099ebb4caSwyllys 				pubkey->keyp = (void *)epubkey;
168199ebb4caSwyllys 			} else {
168299ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
168399ebb4caSwyllys 				rv = KMF_ERR_KEYGEN_FAILED;
168499ebb4caSwyllys 				goto cleanup;
168599ebb4caSwyllys 			}
168699ebb4caSwyllys 		}
168799ebb4caSwyllys 	}
168899ebb4caSwyllys 
168999ebb4caSwyllys 	if (rv != KMF_OK) {
169099ebb4caSwyllys 		goto cleanup;
169199ebb4caSwyllys 	}
169299ebb4caSwyllys 
169330a5e8faSwyllys 	if (storekey) {
169430a5e8faSwyllys 		KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
169530a5e8faSwyllys 		int i = 0;
169630a5e8faSwyllys 		char *keyfile = NULL, *dirpath = NULL;
169730a5e8faSwyllys 		KMF_ENCODE_FORMAT format;
169830a5e8faSwyllys 		/*
169930a5e8faSwyllys 		 * Construct a new attribute arrray and call openssl_store_key
170030a5e8faSwyllys 		 */
170130a5e8faSwyllys 		kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
170230a5e8faSwyllys 		    privkey, sizeof (privkey));
170330a5e8faSwyllys 		i++;
170430a5e8faSwyllys 
170530a5e8faSwyllys 		dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
170630a5e8faSwyllys 		if (dirpath != NULL) {
170730a5e8faSwyllys 			storeattrs[i].type = KMF_DIRPATH_ATTR;
170830a5e8faSwyllys 			storeattrs[i].pValue = dirpath;
170930a5e8faSwyllys 			storeattrs[i].valueLen = strlen(dirpath);
171030a5e8faSwyllys 			i++;
171130a5e8faSwyllys 		} else {
171230a5e8faSwyllys 			rv = KMF_OK; /* DIRPATH is optional */
171399ebb4caSwyllys 		}
171430a5e8faSwyllys 		keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
171530a5e8faSwyllys 		    attrlist, numattr);
171630a5e8faSwyllys 		if (keyfile != NULL) {
171730a5e8faSwyllys 			storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
171830a5e8faSwyllys 			storeattrs[i].pValue = keyfile;
171930a5e8faSwyllys 			storeattrs[i].valueLen = strlen(keyfile);
172030a5e8faSwyllys 			i++;
172130a5e8faSwyllys 		} else {
172230a5e8faSwyllys 			goto cleanup; /* KEYFILE is required */
172330a5e8faSwyllys 		}
172430a5e8faSwyllys 		rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
172530a5e8faSwyllys 		    (void *)&format, NULL);
172630a5e8faSwyllys 		if (rv == KMF_OK) {
172730a5e8faSwyllys 			storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
172830a5e8faSwyllys 			storeattrs[i].pValue = &format;
172930a5e8faSwyllys 			storeattrs[i].valueLen = sizeof (format);
173030a5e8faSwyllys 			i++;
173130a5e8faSwyllys 		}
173230a5e8faSwyllys 
173330a5e8faSwyllys 		rv = OpenSSL_StoreKey(handle, i, storeattrs);
173430a5e8faSwyllys 	}
173599ebb4caSwyllys 
173699ebb4caSwyllys cleanup:
173799ebb4caSwyllys 	if (rv != KMF_OK) {
173899ebb4caSwyllys 		if (eprikey != NULL)
173999ebb4caSwyllys 			EVP_PKEY_free(eprikey);
174099ebb4caSwyllys 
174199ebb4caSwyllys 		if (epubkey != NULL)
174299ebb4caSwyllys 			EVP_PKEY_free(epubkey);
174399ebb4caSwyllys 
174499ebb4caSwyllys 		if (pubkey->keylabel) {
174599ebb4caSwyllys 			free(pubkey->keylabel);
174699ebb4caSwyllys 			pubkey->keylabel = NULL;
174799ebb4caSwyllys 		}
174899ebb4caSwyllys 
174999ebb4caSwyllys 		if (privkey->keylabel) {
175099ebb4caSwyllys 			free(privkey->keylabel);
175199ebb4caSwyllys 			privkey->keylabel = NULL;
175299ebb4caSwyllys 		}
175399ebb4caSwyllys 
175499ebb4caSwyllys 		pubkey->keyp = NULL;
175599ebb4caSwyllys 		privkey->keyp = NULL;
175699ebb4caSwyllys 	}
175799ebb4caSwyllys 
175899ebb4caSwyllys 	if (sslPrivKey)
175999ebb4caSwyllys 		RSA_free(sslPrivKey);
176099ebb4caSwyllys 
176199ebb4caSwyllys 	if (sslDSAKey)
176299ebb4caSwyllys 		DSA_free(sslDSAKey);
176399ebb4caSwyllys 
176499ebb4caSwyllys 	if (out != NULL)
176599ebb4caSwyllys 		(void) BIO_free(out);
176699ebb4caSwyllys 
176799ebb4caSwyllys 	return (rv);
176899ebb4caSwyllys }
176999ebb4caSwyllys 
177099ebb4caSwyllys KMF_RETURN
177199ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
177299ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
177399ebb4caSwyllys {
177499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
177599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
177699ebb4caSwyllys 	KMF_ALGORITHM_INDEX		AlgId;
177799ebb4caSwyllys 	EVP_MD_CTX ctx;
177899ebb4caSwyllys 	const EVP_MD *md;
177902744e81Swyllys 
178099ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
178199ebb4caSwyllys 	    tobesigned == NULL || output == NULL ||
178299ebb4caSwyllys 	    tobesigned->Data == NULL ||
178399ebb4caSwyllys 	    output->Data == NULL)
178499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
178599ebb4caSwyllys 
178699ebb4caSwyllys 	/* Map the OID to an OpenSSL algorithm */
178730a5e8faSwyllys 	AlgId = x509_algoid_to_algid(AlgOID);
178899ebb4caSwyllys 	if (AlgId == KMF_ALGID_NONE)
178999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
179099ebb4caSwyllys 
179199ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
179299ebb4caSwyllys 		EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
179399ebb4caSwyllys 		uchar_t *p;
179402744e81Swyllys 		int len;
179599ebb4caSwyllys 		if (AlgId == KMF_ALGID_MD5WithRSA)
179699ebb4caSwyllys 			md = EVP_md5();
179799ebb4caSwyllys 		else if (AlgId == KMF_ALGID_MD2WithRSA)
179899ebb4caSwyllys 			md = EVP_md2();
179999ebb4caSwyllys 		else if (AlgId == KMF_ALGID_SHA1WithRSA)
180099ebb4caSwyllys 			md = EVP_sha1();
180102744e81Swyllys 		else if (AlgId == KMF_ALGID_RSA)
180202744e81Swyllys 			md = NULL;
180399ebb4caSwyllys 		else
180499ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
180599ebb4caSwyllys 
180602744e81Swyllys 		if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
180702744e81Swyllys 			RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
180899ebb4caSwyllys 
180902744e81Swyllys 			p = output->Data;
181002744e81Swyllys 			if ((len = RSA_private_encrypt(tobesigned->Length,
181102744e81Swyllys 			    tobesigned->Data, p, rsa,
181202744e81Swyllys 			    RSA_PKCS1_PADDING)) <= 0) {
181302744e81Swyllys 				SET_ERROR(kmfh, ERR_get_error());
181402744e81Swyllys 				ret = KMF_ERR_INTERNAL;
181502744e81Swyllys 			}
181602744e81Swyllys 			output->Length = len;
181702744e81Swyllys 		} else {
181899ebb4caSwyllys 			(void) EVP_MD_CTX_init(&ctx);
181999ebb4caSwyllys 			(void) EVP_SignInit_ex(&ctx, md, NULL);
182099ebb4caSwyllys 			(void) EVP_SignUpdate(&ctx, tobesigned->Data,
182199ebb4caSwyllys 			    (uint32_t)tobesigned->Length);
182299ebb4caSwyllys 			len = (uint32_t)output->Length;
182399ebb4caSwyllys 			p = output->Data;
182402744e81Swyllys 			if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) {
182599ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
182602744e81Swyllys 				len = 0;
182702744e81Swyllys 				ret = KMF_ERR_INTERNAL;
182899ebb4caSwyllys 			}
182999ebb4caSwyllys 			output->Length = len;
183099ebb4caSwyllys 			(void) EVP_MD_CTX_cleanup(&ctx);
183102744e81Swyllys 		}
183299ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
183399ebb4caSwyllys 		DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
183499ebb4caSwyllys 
183599ebb4caSwyllys 		uchar_t hash[EVP_MAX_MD_SIZE];
183699ebb4caSwyllys 		uint32_t hashlen;
183799ebb4caSwyllys 		DSA_SIG *dsasig;
183899ebb4caSwyllys 
183999ebb4caSwyllys 		/*
184099ebb4caSwyllys 		 * OpenSSL EVP_Sign operation automatically converts to
184199ebb4caSwyllys 		 * ASN.1 output so we do the operations separately so we
184299ebb4caSwyllys 		 * are assured of NOT getting ASN.1 output returned.
184399ebb4caSwyllys 		 * KMF does not want ASN.1 encoded results because
184499ebb4caSwyllys 		 * not all mechanisms return ASN.1 encodings (PKCS#11
184599ebb4caSwyllys 		 * and NSS return raw signature data).
184699ebb4caSwyllys 		 */
184799ebb4caSwyllys 		md = EVP_sha1();
184899ebb4caSwyllys 		EVP_MD_CTX_init(&ctx);
184999ebb4caSwyllys 		(void) EVP_DigestInit_ex(&ctx, md, NULL);
185099ebb4caSwyllys 		(void) EVP_DigestUpdate(&ctx, tobesigned->Data,
185199ebb4caSwyllys 		    tobesigned->Length);
185299ebb4caSwyllys 		(void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
185399ebb4caSwyllys 		(void) EVP_MD_CTX_cleanup(&ctx);
185499ebb4caSwyllys 
185599ebb4caSwyllys 		dsasig = DSA_do_sign(hash, hashlen, dsa);
185699ebb4caSwyllys 		if (dsasig != NULL) {
185799ebb4caSwyllys 			int i;
185899ebb4caSwyllys 			output->Length = i = BN_bn2bin(dsasig->r, output->Data);
185999ebb4caSwyllys 			output->Length += BN_bn2bin(dsasig->s,
186099ebb4caSwyllys 			    &output->Data[i]);
186199ebb4caSwyllys 			DSA_SIG_free(dsasig);
186299ebb4caSwyllys 		} else {
186399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
186499ebb4caSwyllys 		}
186599ebb4caSwyllys 	} else {
186699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
186799ebb4caSwyllys 	}
186899ebb4caSwyllys cleanup:
186999ebb4caSwyllys 	return (ret);
187099ebb4caSwyllys }
187199ebb4caSwyllys 
187299ebb4caSwyllys KMF_RETURN
187399ebb4caSwyllys /*ARGSUSED*/
187430a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle,
187530a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
187699ebb4caSwyllys {
187799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
187830a5e8faSwyllys 	KMF_KEY_HANDLE *key;
187930a5e8faSwyllys 	boolean_t destroy = B_TRUE;
188030a5e8faSwyllys 
188130a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
188299ebb4caSwyllys 	if (key == NULL || key->keyp == NULL)
188399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
188499ebb4caSwyllys 
188530a5e8faSwyllys 	rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
188630a5e8faSwyllys 	    (void *)&destroy, NULL);
188730a5e8faSwyllys 	if (rv != KMF_OK) {
188830a5e8faSwyllys 		/* "destroy" is optional. Default is TRUE */
188930a5e8faSwyllys 		rv = KMF_OK;
189030a5e8faSwyllys 	}
189130a5e8faSwyllys 
189299ebb4caSwyllys 	if (key->keyclass != KMF_ASYM_PUB &&
189399ebb4caSwyllys 	    key->keyclass != KMF_ASYM_PRI &&
189499ebb4caSwyllys 	    key->keyclass != KMF_SYMMETRIC)
189599ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
189699ebb4caSwyllys 
189799ebb4caSwyllys 	if (key->keyclass == KMF_SYMMETRIC) {
189830a5e8faSwyllys 		kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
189999ebb4caSwyllys 		key->keyp = NULL;
190099ebb4caSwyllys 	} else {
190199ebb4caSwyllys 		if (key->keyp != NULL) {
190299ebb4caSwyllys 			EVP_PKEY_free(key->keyp);
190399ebb4caSwyllys 			key->keyp = NULL;
190499ebb4caSwyllys 		}
190599ebb4caSwyllys 	}
190699ebb4caSwyllys 
190799ebb4caSwyllys 	if (key->keylabel != NULL) {
190899ebb4caSwyllys 		EVP_PKEY *pkey = NULL;
190999ebb4caSwyllys 		/* If the file exists, make sure it is a proper key. */
191099ebb4caSwyllys 		pkey = openssl_load_key(handle, key->keylabel);
191199ebb4caSwyllys 		if (pkey == NULL) {
19125b3e1433Swyllys 			if (key->keylabel != NULL) {
191399ebb4caSwyllys 				free(key->keylabel);
191499ebb4caSwyllys 				key->keylabel = NULL;
19155b3e1433Swyllys 			}
191699ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
191799ebb4caSwyllys 		}
191899ebb4caSwyllys 		EVP_PKEY_free(pkey);
191999ebb4caSwyllys 
192099ebb4caSwyllys 		if (destroy) {
192199ebb4caSwyllys 			if (unlink(key->keylabel) != 0) {
192299ebb4caSwyllys 				KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
192399ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
192499ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
192599ebb4caSwyllys 			}
192699ebb4caSwyllys 		}
192799ebb4caSwyllys 		if (key->keylabel != NULL) {
192899ebb4caSwyllys 			free(key->keylabel);
192999ebb4caSwyllys 			key->keylabel = NULL;
193099ebb4caSwyllys 		}
193199ebb4caSwyllys 	}
193299ebb4caSwyllys 	return (rv);
193399ebb4caSwyllys }
193499ebb4caSwyllys 
193599ebb4caSwyllys KMF_RETURN
193699ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
193799ebb4caSwyllys {
193899ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
193999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
194099ebb4caSwyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
194199ebb4caSwyllys 
194299ebb4caSwyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
194399ebb4caSwyllys 	if (strlen(str)) {
194499ebb4caSwyllys 		*msgstr = (char *)strdup(str);
194599ebb4caSwyllys 		if ((*msgstr) == NULL)
194699ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
194799ebb4caSwyllys 	} else {
194899ebb4caSwyllys 		*msgstr = NULL;
194999ebb4caSwyllys 	}
195099ebb4caSwyllys 
195199ebb4caSwyllys 	return (ret);
195299ebb4caSwyllys }
195399ebb4caSwyllys 
195499ebb4caSwyllys static int
195599ebb4caSwyllys ext2NID(int kmfext)
195699ebb4caSwyllys {
195799ebb4caSwyllys 	switch (kmfext) {
195899ebb4caSwyllys 		case KMF_X509_EXT_KEY_USAGE:
195999ebb4caSwyllys 			return (NID_key_usage);
196099ebb4caSwyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
196199ebb4caSwyllys 			return (NID_private_key_usage_period);
196299ebb4caSwyllys 		case KMF_X509_EXT_CERT_POLICIES:
196399ebb4caSwyllys 			return (NID_certificate_policies);
196499ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
196599ebb4caSwyllys 			return (NID_subject_alt_name);
196699ebb4caSwyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
196799ebb4caSwyllys 			return (NID_issuer_alt_name);
196899ebb4caSwyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
196999ebb4caSwyllys 			return (NID_basic_constraints);
197099ebb4caSwyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
197199ebb4caSwyllys 			return (NID_ext_key_usage);
197299ebb4caSwyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
197399ebb4caSwyllys 			return (NID_authority_key_identifier);
197499ebb4caSwyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
197599ebb4caSwyllys 			return (NID_crl_distribution_points);
197699ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
197799ebb4caSwyllys 			return (NID_subject_key_identifier);
197899ebb4caSwyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
197999ebb4caSwyllys 			return (OBJ_sn2nid("policyMappings"));
198099ebb4caSwyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
198199ebb4caSwyllys 			return (OBJ_sn2nid("nameConstraints"));
198299ebb4caSwyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
198399ebb4caSwyllys 			return (OBJ_sn2nid("policyConstraints"));
198499ebb4caSwyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
198599ebb4caSwyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
198699ebb4caSwyllys 		case KMF_X509_EXT_FRESHEST_CRL:
198799ebb4caSwyllys 			return (OBJ_sn2nid("freshestCRL"));
198899ebb4caSwyllys 		default:
198999ebb4caSwyllys 			return (NID_undef);
199099ebb4caSwyllys 	}
199199ebb4caSwyllys }
199299ebb4caSwyllys 
199399ebb4caSwyllys KMF_RETURN
199499ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
199599ebb4caSwyllys 	KMF_PRINTABLE_ITEM flag, char *resultStr)
199699ebb4caSwyllys {
199799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
199899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
199999ebb4caSwyllys 	X509 *xcert = NULL;
200099ebb4caSwyllys 	unsigned char *outbuf = NULL;
200199ebb4caSwyllys 	unsigned char *outbuf_p;
200299ebb4caSwyllys 	char *tmpstr = NULL;
200399ebb4caSwyllys 	int j;
200499ebb4caSwyllys 	int ext_index, nid, len;
200599ebb4caSwyllys 	BIO *mem = NULL;
200699ebb4caSwyllys 	STACK *emlst = NULL;
200799ebb4caSwyllys 	X509_EXTENSION *ex;
200899ebb4caSwyllys 	X509_CINF *ci;
200999ebb4caSwyllys 
201099ebb4caSwyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
201199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
201299ebb4caSwyllys 	}
201399ebb4caSwyllys 
201499ebb4caSwyllys 	/* copy cert data to outbuf */
201599ebb4caSwyllys 	outbuf = malloc(pcert->Length);
201699ebb4caSwyllys 	if (outbuf == NULL) {
201799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
201899ebb4caSwyllys 	}
201999ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
202099ebb4caSwyllys 
202199ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
202299ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
202399ebb4caSwyllys 	if (xcert == NULL) {
202499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
202599ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
202699ebb4caSwyllys 		goto out;
202799ebb4caSwyllys 	}
202899ebb4caSwyllys 
202999ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
203099ebb4caSwyllys 	if (mem == NULL) {
203199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
203299ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
203399ebb4caSwyllys 		goto out;
203499ebb4caSwyllys 	}
203599ebb4caSwyllys 
203699ebb4caSwyllys 	switch (flag) {
203799ebb4caSwyllys 	case KMF_CERT_ISSUER:
203899ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
203999ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
204099ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
204199ebb4caSwyllys 		break;
204299ebb4caSwyllys 
204399ebb4caSwyllys 	case KMF_CERT_SUBJECT:
204499ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
204599ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
204699ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
204799ebb4caSwyllys 		break;
204899ebb4caSwyllys 
204999ebb4caSwyllys 	case KMF_CERT_VERSION:
205099ebb4caSwyllys 		tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version);
205199ebb4caSwyllys 		(void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN);
205299ebb4caSwyllys 		OPENSSL_free(tmpstr);
205399ebb4caSwyllys 		len = strlen(resultStr);
205499ebb4caSwyllys 		break;
205599ebb4caSwyllys 
205699ebb4caSwyllys 	case KMF_CERT_SERIALNUM:
205799ebb4caSwyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
205899ebb4caSwyllys 			(void) strcpy(resultStr, "0x");
205999ebb4caSwyllys 			len = BIO_gets(mem, &resultStr[2],
206099ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN - 2);
206199ebb4caSwyllys 		}
206299ebb4caSwyllys 		break;
206399ebb4caSwyllys 
206499ebb4caSwyllys 	case KMF_CERT_NOTBEFORE:
206599ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notBefore(xcert));
206699ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
206799ebb4caSwyllys 		break;
206899ebb4caSwyllys 
206999ebb4caSwyllys 	case KMF_CERT_NOTAFTER:
207099ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notAfter(xcert));
207199ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
207299ebb4caSwyllys 		break;
207399ebb4caSwyllys 
207499ebb4caSwyllys 	case KMF_CERT_PUBKEY_DATA:
207599ebb4caSwyllys 		{
207699ebb4caSwyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
207799ebb4caSwyllys 			if (pkey == NULL) {
207899ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
207999ebb4caSwyllys 				ret = KMF_ERR_ENCODING;
208099ebb4caSwyllys 				goto out;
208199ebb4caSwyllys 			}
208299ebb4caSwyllys 
208399ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
208499ebb4caSwyllys 				(void) BIO_printf(mem,
208599ebb4caSwyllys 				    "RSA Public Key: (%d bit)\n",
208699ebb4caSwyllys 				    BN_num_bits(pkey->pkey.rsa->n));
208799ebb4caSwyllys 				(void) RSA_print(mem, pkey->pkey.rsa, 0);
208899ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
208999ebb4caSwyllys 				(void) BIO_printf(mem,
209099ebb4caSwyllys 				    "%12sDSA Public Key:\n", "");
209199ebb4caSwyllys 				(void) DSA_print(mem, pkey->pkey.dsa, 0);
209299ebb4caSwyllys 			} else {
209399ebb4caSwyllys 				(void) BIO_printf(mem,
209499ebb4caSwyllys 				    "%12sUnknown Public Key:\n", "");
209599ebb4caSwyllys 			}
209699ebb4caSwyllys 			(void) BIO_printf(mem, "\n");
209799ebb4caSwyllys 			EVP_PKEY_free(pkey);
209899ebb4caSwyllys 		}
209999ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
210099ebb4caSwyllys 		break;
210199ebb4caSwyllys 	case KMF_CERT_SIGNATURE_ALG:
210299ebb4caSwyllys 	case KMF_CERT_PUBKEY_ALG:
210399ebb4caSwyllys 		if (flag == KMF_CERT_SIGNATURE_ALG) {
210499ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
210599ebb4caSwyllys 			    xcert->sig_alg->algorithm);
210699ebb4caSwyllys 		} else {
210799ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
210899ebb4caSwyllys 			    xcert->cert_info->key->algor->algorithm);
210999ebb4caSwyllys 		}
211099ebb4caSwyllys 
211199ebb4caSwyllys 		if (len > 0) {
211299ebb4caSwyllys 			len = BIO_read(mem, resultStr,
211399ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN);
211499ebb4caSwyllys 		}
211599ebb4caSwyllys 		break;
211699ebb4caSwyllys 
211799ebb4caSwyllys 	case KMF_CERT_EMAIL:
211899ebb4caSwyllys 		emlst = X509_get1_email(xcert);
211999ebb4caSwyllys 		for (j = 0; j < sk_num(emlst); j++)
212099ebb4caSwyllys 			(void) BIO_printf(mem, "%s\n", sk_value(emlst, j));
212199ebb4caSwyllys 
212299ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
212399ebb4caSwyllys 		X509_email_free(emlst);
212499ebb4caSwyllys 		break;
212599ebb4caSwyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
212699ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
212799ebb4caSwyllys 	case KMF_X509_EXT_KEY_USAGE:
212899ebb4caSwyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
212999ebb4caSwyllys 	case KMF_X509_EXT_CERT_POLICIES:
213099ebb4caSwyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
213199ebb4caSwyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
213299ebb4caSwyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
213399ebb4caSwyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
213499ebb4caSwyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
213599ebb4caSwyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
213699ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
213799ebb4caSwyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
213899ebb4caSwyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
213999ebb4caSwyllys 	case KMF_X509_EXT_FRESHEST_CRL:
214099ebb4caSwyllys 		nid = ext2NID(flag);
214199ebb4caSwyllys 		if (nid == NID_undef) {
214299ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
214399ebb4caSwyllys 			goto out;
214499ebb4caSwyllys 		}
214599ebb4caSwyllys 		ci = xcert->cert_info;
214699ebb4caSwyllys 
214799ebb4caSwyllys 		ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1);
214899ebb4caSwyllys 		if (ext_index == -1) {
214999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
215099ebb4caSwyllys 
215199ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
215299ebb4caSwyllys 			goto out;
215399ebb4caSwyllys 		}
215499ebb4caSwyllys 		ex = X509v3_get_ext(ci->extensions, ext_index);
215599ebb4caSwyllys 
215699ebb4caSwyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
215799ebb4caSwyllys 
215899ebb4caSwyllys 		if (BIO_printf(mem, ": %s\n",
215930a5e8faSwyllys 		    X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
216099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
216199ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
216299ebb4caSwyllys 			goto out;
216399ebb4caSwyllys 		}
216499ebb4caSwyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
216599ebb4caSwyllys 			(void) BIO_printf(mem, "%*s", 4, "");
216699ebb4caSwyllys 			(void) M_ASN1_OCTET_STRING_print(mem, ex->value);
216799ebb4caSwyllys 		}
216899ebb4caSwyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
216999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
217099ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
217199ebb4caSwyllys 			goto out;
217299ebb4caSwyllys 		}
217399ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
217499ebb4caSwyllys 	}
217599ebb4caSwyllys 	if (len <= 0) {
217699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
217799ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
217899ebb4caSwyllys 	}
217999ebb4caSwyllys 
218099ebb4caSwyllys out:
218199ebb4caSwyllys 	if (outbuf != NULL) {
218299ebb4caSwyllys 		free(outbuf);
218399ebb4caSwyllys 	}
218499ebb4caSwyllys 
218599ebb4caSwyllys 	if (xcert != NULL) {
218699ebb4caSwyllys 		X509_free(xcert);
218799ebb4caSwyllys 	}
218899ebb4caSwyllys 
218999ebb4caSwyllys 	if (mem != NULL) {
219099ebb4caSwyllys 		(void) BIO_free(mem);
219199ebb4caSwyllys 	}
219299ebb4caSwyllys 
219399ebb4caSwyllys 	return (ret);
219499ebb4caSwyllys }
219530a5e8faSwyllys 
219699ebb4caSwyllys KMF_RETURN
219799ebb4caSwyllys /*ARGSUSED*/
219830a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
219930a5e8faSwyllys     KMF_ATTRIBUTE *attrlist)
220099ebb4caSwyllys {
220199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
220230a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
220330a5e8faSwyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
220430a5e8faSwyllys 	KMF_KEY_HANDLE *key = NULL;
220530a5e8faSwyllys 	uint32_t numkeys = 1; /* 1 key only */
220630a5e8faSwyllys 	char *dirpath = NULL;
220730a5e8faSwyllys 	char *keyfile = NULL;
220830a5e8faSwyllys 	KMF_ATTRIBUTE new_attrlist[16];
220930a5e8faSwyllys 	int i = 0;
221099ebb4caSwyllys 
221199ebb4caSwyllys 	/*
221299ebb4caSwyllys 	 * This is really just a FindKey operation, reuse the
221399ebb4caSwyllys 	 * FindKey function.
221499ebb4caSwyllys 	 */
221530a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
221630a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
221730a5e8faSwyllys 	i++;
221899ebb4caSwyllys 
221930a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
222030a5e8faSwyllys 	    KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
222130a5e8faSwyllys 	i++;
222299ebb4caSwyllys 
222330a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
222430a5e8faSwyllys 	    KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
222530a5e8faSwyllys 	i++;
222630a5e8faSwyllys 
222730a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
222830a5e8faSwyllys 	if (key == NULL) {
222930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
223030a5e8faSwyllys 	} else {
223130a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
223230a5e8faSwyllys 		    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
223330a5e8faSwyllys 		i++;
223430a5e8faSwyllys 	}
223530a5e8faSwyllys 
223630a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
223730a5e8faSwyllys 	if (dirpath != NULL) {
223830a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
223930a5e8faSwyllys 		    KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
224030a5e8faSwyllys 		i++;
224130a5e8faSwyllys 	}
224230a5e8faSwyllys 
224330a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
224430a5e8faSwyllys 	if (keyfile == NULL)
224530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
224630a5e8faSwyllys 	else {
224730a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
224830a5e8faSwyllys 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
224930a5e8faSwyllys 		i++;
225030a5e8faSwyllys 	}
225130a5e8faSwyllys 
225230a5e8faSwyllys 	rv = OpenSSL_FindKey(handle, i, new_attrlist);
225399ebb4caSwyllys 	return (rv);
225499ebb4caSwyllys }
225599ebb4caSwyllys 
225699ebb4caSwyllys KMF_RETURN
225799ebb4caSwyllys /*ARGSUSED*/
225899ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
225999ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
226099ebb4caSwyllys 	KMF_DATA *output)
226199ebb4caSwyllys {
226299ebb4caSwyllys 	KMF_RETURN		ret = KMF_OK;
226399ebb4caSwyllys 	RSA *rsa = NULL;
226499ebb4caSwyllys 	unsigned int in_len = 0, out_len = 0;
226599ebb4caSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
226699ebb4caSwyllys 	uint8_t *in_data, *out_data;
226799ebb4caSwyllys 	int i, blocks;
226899ebb4caSwyllys 
226999ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
227099ebb4caSwyllys 	    ciphertext == NULL || output == NULL ||
227199ebb4caSwyllys 	    ciphertext->Data == NULL ||
227299ebb4caSwyllys 	    output->Data == NULL)
227399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
227499ebb4caSwyllys 
227599ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
227699ebb4caSwyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
227799ebb4caSwyllys 		modulus_len = RSA_size(rsa);
227899ebb4caSwyllys 	} else {
227999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
228099ebb4caSwyllys 	}
228199ebb4caSwyllys 
228299ebb4caSwyllys 	blocks = ciphertext->Length/modulus_len;
228399ebb4caSwyllys 	out_data = output->Data;
228499ebb4caSwyllys 	in_data = ciphertext->Data;
228599ebb4caSwyllys 	out_len = modulus_len - 11;
228699ebb4caSwyllys 	in_len = modulus_len;
228799ebb4caSwyllys 
228899ebb4caSwyllys 	for (i = 0; i < blocks; i++) {
228999ebb4caSwyllys 		out_len  = RSA_private_decrypt(in_len,
229099ebb4caSwyllys 		    in_data, out_data, rsa, RSA_PKCS1_PADDING);
229199ebb4caSwyllys 
229299ebb4caSwyllys 		if (out_len == 0) {
229399ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
229499ebb4caSwyllys 			goto cleanup;
229599ebb4caSwyllys 		}
229699ebb4caSwyllys 
229799ebb4caSwyllys 		out_data += out_len;
229899ebb4caSwyllys 		total_decrypted += out_len;
229999ebb4caSwyllys 		in_data += in_len;
230099ebb4caSwyllys 	}
230199ebb4caSwyllys 
230299ebb4caSwyllys 	output->Length = total_decrypted;
230399ebb4caSwyllys 
230499ebb4caSwyllys cleanup:
230599ebb4caSwyllys 	RSA_free(rsa);
230699ebb4caSwyllys 	if (ret != KMF_OK)
230799ebb4caSwyllys 		output->Length = 0;
230899ebb4caSwyllys 
230999ebb4caSwyllys 	return (ret);
231099ebb4caSwyllys 
231199ebb4caSwyllys }
231299ebb4caSwyllys 
231399ebb4caSwyllys /*
231499ebb4caSwyllys  *  This function will create a certid from issuer_cert and user_cert.
231599ebb4caSwyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
231699ebb4caSwyllys  *  certid memory after use.
231799ebb4caSwyllys  */
231899ebb4caSwyllys static KMF_RETURN
231999ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
232099ebb4caSwyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
232199ebb4caSwyllys {
232299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
232399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
232499ebb4caSwyllys 	X509   *issuer = NULL;
232599ebb4caSwyllys 	X509   *cert = NULL;
232699ebb4caSwyllys 	unsigned char *ptmp;
232799ebb4caSwyllys 
232899ebb4caSwyllys 	if (issuer_cert == NULL || user_cert == NULL) {
232999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
233099ebb4caSwyllys 	}
233199ebb4caSwyllys 
233299ebb4caSwyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
233399ebb4caSwyllys 	ptmp = issuer_cert->Data;
233499ebb4caSwyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
233599ebb4caSwyllys 	    issuer_cert->Length);
233699ebb4caSwyllys 	if (issuer == NULL) {
233799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
233899ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
233999ebb4caSwyllys 		goto end;
234099ebb4caSwyllys 	}
234199ebb4caSwyllys 
234299ebb4caSwyllys 	/* convert the DER-encoded user cert to an internal X509 */
234399ebb4caSwyllys 	ptmp = user_cert->Data;
234499ebb4caSwyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
234599ebb4caSwyllys 	    user_cert->Length);
234699ebb4caSwyllys 	if (cert == NULL) {
234799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
234899ebb4caSwyllys 
234999ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
235099ebb4caSwyllys 		goto end;
235199ebb4caSwyllys 	}
235299ebb4caSwyllys 
235399ebb4caSwyllys 	/* create a CERTID */
235499ebb4caSwyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
235599ebb4caSwyllys 	if (*certid == NULL) {
235699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
235799ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
235899ebb4caSwyllys 		goto end;
235999ebb4caSwyllys 	}
236099ebb4caSwyllys 
236199ebb4caSwyllys end:
236299ebb4caSwyllys 	if (issuer != NULL) {
236399ebb4caSwyllys 		X509_free(issuer);
236499ebb4caSwyllys 	}
236599ebb4caSwyllys 
236699ebb4caSwyllys 	if (cert != NULL) {
236799ebb4caSwyllys 		X509_free(cert);
236899ebb4caSwyllys 	}
236999ebb4caSwyllys 
237099ebb4caSwyllys 	return (ret);
237199ebb4caSwyllys }
237299ebb4caSwyllys 
237399ebb4caSwyllys KMF_RETURN
237430a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
237530a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
237699ebb4caSwyllys {
237799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
237899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
237999ebb4caSwyllys 	OCSP_CERTID *id = NULL;
238099ebb4caSwyllys 	OCSP_REQUEST *req = NULL;
238199ebb4caSwyllys 	BIO *derbio = NULL;
238230a5e8faSwyllys 	char *reqfile;
238330a5e8faSwyllys 	KMF_DATA *issuer_cert;
238430a5e8faSwyllys 	KMF_DATA *user_cert;
238599ebb4caSwyllys 
238630a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
238730a5e8faSwyllys 	    attrlist, numattr);
238830a5e8faSwyllys 	if (user_cert == NULL)
238999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
239099ebb4caSwyllys 
239130a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
239230a5e8faSwyllys 	    attrlist, numattr);
239330a5e8faSwyllys 	if (issuer_cert == NULL)
239430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
239530a5e8faSwyllys 
239630a5e8faSwyllys 	reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
239730a5e8faSwyllys 	    attrlist, numattr);
239830a5e8faSwyllys 	if (reqfile == NULL)
239930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
240030a5e8faSwyllys 
240130a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
240299ebb4caSwyllys 	if (ret != KMF_OK) {
240399ebb4caSwyllys 		return (ret);
240499ebb4caSwyllys 	}
240599ebb4caSwyllys 
240699ebb4caSwyllys 	/* Create an OCSP request */
240799ebb4caSwyllys 	req = OCSP_REQUEST_new();
240899ebb4caSwyllys 	if (req == NULL) {
240999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
241099ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
241199ebb4caSwyllys 		goto end;
241299ebb4caSwyllys 	}
241399ebb4caSwyllys 
241499ebb4caSwyllys 	if (!OCSP_request_add0_id(req, id)) {
241599ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
241699ebb4caSwyllys 		goto end;
241799ebb4caSwyllys 	}
241899ebb4caSwyllys 
241999ebb4caSwyllys 	/* Write the request to the output file with DER encoding */
242099ebb4caSwyllys 	derbio = BIO_new_file(reqfile, "wb");
242199ebb4caSwyllys 	if (!derbio) {
242299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
242399ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
242499ebb4caSwyllys 		goto end;
242599ebb4caSwyllys 	}
242699ebb4caSwyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
242799ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
242899ebb4caSwyllys 	}
242999ebb4caSwyllys 
243099ebb4caSwyllys end:
243199ebb4caSwyllys 	/*
2432*a2d4930dSDan OpenSolaris Anderson 	 * We don't need to free "id" explicitly, because OCSP_REQUEST_free()
2433*a2d4930dSDan OpenSolaris Anderson 	 * will also deallocate certid's space.
243499ebb4caSwyllys 	 */
243599ebb4caSwyllys 	if (req != NULL) {
243699ebb4caSwyllys 		OCSP_REQUEST_free(req);
243799ebb4caSwyllys 	}
243899ebb4caSwyllys 
243999ebb4caSwyllys 	if (derbio != NULL) {
244099ebb4caSwyllys 		(void) BIO_free(derbio);
244199ebb4caSwyllys 	}
244299ebb4caSwyllys 
244399ebb4caSwyllys 	return (ret);
244499ebb4caSwyllys }
244599ebb4caSwyllys 
244699ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */
244799ebb4caSwyllys static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
244899ebb4caSwyllys {
244999ebb4caSwyllys 	int i;
245099ebb4caSwyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
245199ebb4caSwyllys 
245299ebb4caSwyllys 	/* Easy if lookup by name */
245399ebb4caSwyllys 	if (id->type == V_OCSP_RESPID_NAME)
245499ebb4caSwyllys 		return (X509_find_by_subject(certs, id->value.byName));
245599ebb4caSwyllys 
245699ebb4caSwyllys 	/* Lookup by key hash */
245799ebb4caSwyllys 
245899ebb4caSwyllys 	/* If key hash isn't SHA1 length then forget it */
245999ebb4caSwyllys 	if (id->value.byKey->length != SHA_DIGEST_LENGTH)
246099ebb4caSwyllys 		return (NULL);
246199ebb4caSwyllys 
246299ebb4caSwyllys 	keyhash = id->value.byKey->data;
246399ebb4caSwyllys 	/* Calculate hash of each key and compare */
246499ebb4caSwyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
2465*a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
246699ebb4caSwyllys 		X509 *x = sk_X509_value(certs, i);
24675b3e1433Swyllys 		/* Use pubkey_digest to get the key ID value */
246899ebb4caSwyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
246999ebb4caSwyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
247099ebb4caSwyllys 			return (x);
247199ebb4caSwyllys 	}
247299ebb4caSwyllys 	return (NULL);
247399ebb4caSwyllys }
247499ebb4caSwyllys 
247599ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */
2476*a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */
247799ebb4caSwyllys static int
247899ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
247999ebb4caSwyllys     X509_STORE *st, unsigned long flags)
248099ebb4caSwyllys {
248199ebb4caSwyllys 	X509 *signer;
248299ebb4caSwyllys 	OCSP_RESPID *rid = bs->tbsResponseData->responderId;
248399ebb4caSwyllys 	if ((signer = ocsp_find_signer_sk(certs, rid)))	{
248499ebb4caSwyllys 		*psigner = signer;
248599ebb4caSwyllys 		return (2);
248699ebb4caSwyllys 	}
248799ebb4caSwyllys 	if (!(flags & OCSP_NOINTERN) &&
248899ebb4caSwyllys 	    (signer = ocsp_find_signer_sk(bs->certs, rid))) {
248999ebb4caSwyllys 		*psigner = signer;
249099ebb4caSwyllys 		return (1);
249199ebb4caSwyllys 	}
249299ebb4caSwyllys 	/* Maybe lookup from store if by subject name */
249399ebb4caSwyllys 
249499ebb4caSwyllys 	*psigner = NULL;
249599ebb4caSwyllys 	return (0);
249699ebb4caSwyllys }
249799ebb4caSwyllys 
249899ebb4caSwyllys /*
249999ebb4caSwyllys  * This function will verify the signature of a basic response, using
250099ebb4caSwyllys  * the public key from the OCSP responder certificate.
250199ebb4caSwyllys  */
250299ebb4caSwyllys static KMF_RETURN
250399ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
250499ebb4caSwyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
250599ebb4caSwyllys {
250699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
250799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
250899ebb4caSwyllys 	STACK_OF(X509) *cert_stack = NULL;
250999ebb4caSwyllys 	X509 *signer = NULL;
251099ebb4caSwyllys 	X509 *issuer = NULL;
251199ebb4caSwyllys 	EVP_PKEY *skey = NULL;
251299ebb4caSwyllys 	unsigned char *ptmp;
251399ebb4caSwyllys 
251499ebb4caSwyllys 
251599ebb4caSwyllys 	if (bs == NULL || issuer_cert == NULL)
251699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
251799ebb4caSwyllys 
251899ebb4caSwyllys 	/*
251999ebb4caSwyllys 	 * Find the certificate that signed the basic response.
252099ebb4caSwyllys 	 *
252199ebb4caSwyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
252299ebb4caSwyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
252399ebb4caSwyllys 	 * If we still do not find a signer, we will look for it from the
252499ebb4caSwyllys 	 * certificate list came with the response file.
252599ebb4caSwyllys 	 */
252699ebb4caSwyllys 	if (signer_cert != NULL) {
252799ebb4caSwyllys 		ptmp = signer_cert->Data;
252899ebb4caSwyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
252999ebb4caSwyllys 		    signer_cert->Length);
253099ebb4caSwyllys 		if (signer == NULL) {
253199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
253299ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
253399ebb4caSwyllys 			goto end;
253499ebb4caSwyllys 		}
253599ebb4caSwyllys 	} else {
253699ebb4caSwyllys 		/*
253799ebb4caSwyllys 		 * Convert the issuer cert into X509 and push it into a
253899ebb4caSwyllys 		 * stack to be used by ocsp_find_signer().
253999ebb4caSwyllys 		 */
254099ebb4caSwyllys 		ptmp = issuer_cert->Data;
254199ebb4caSwyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
254299ebb4caSwyllys 		    issuer_cert->Length);
254399ebb4caSwyllys 		if (issuer == NULL) {
254499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
254599ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
254699ebb4caSwyllys 			goto end;
254799ebb4caSwyllys 		}
254899ebb4caSwyllys 
254999ebb4caSwyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
255099ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
255199ebb4caSwyllys 			goto end;
255299ebb4caSwyllys 		}
255399ebb4caSwyllys 
255499ebb4caSwyllys 		if (sk_X509_push(cert_stack, issuer) == NULL) {
255599ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
255699ebb4caSwyllys 			goto end;
255799ebb4caSwyllys 		}
255899ebb4caSwyllys 
255999ebb4caSwyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
256099ebb4caSwyllys 		if (!ret) {
256199ebb4caSwyllys 			/* can not find the signer */
256299ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
256399ebb4caSwyllys 			goto end;
256499ebb4caSwyllys 		}
256599ebb4caSwyllys 	}
256699ebb4caSwyllys 
256799ebb4caSwyllys 	/* Verify the signature of the response */
256899ebb4caSwyllys 	skey = X509_get_pubkey(signer);
256999ebb4caSwyllys 	if (skey == NULL) {
257099ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
257199ebb4caSwyllys 		goto end;
257299ebb4caSwyllys 	}
257399ebb4caSwyllys 
257499ebb4caSwyllys 	ret = OCSP_BASICRESP_verify(bs, skey, 0);
257599ebb4caSwyllys 	if (ret == 0) {
257699ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
257799ebb4caSwyllys 		goto end;
257899ebb4caSwyllys 	}
257999ebb4caSwyllys 
258099ebb4caSwyllys end:
258199ebb4caSwyllys 	if (issuer != NULL) {
258299ebb4caSwyllys 		X509_free(issuer);
258399ebb4caSwyllys 	}
258499ebb4caSwyllys 
258599ebb4caSwyllys 	if (signer != NULL) {
258699ebb4caSwyllys 		X509_free(signer);
258799ebb4caSwyllys 	}
258899ebb4caSwyllys 
258999ebb4caSwyllys 	if (skey != NULL) {
259099ebb4caSwyllys 		EVP_PKEY_free(skey);
259199ebb4caSwyllys 	}
259299ebb4caSwyllys 
259399ebb4caSwyllys 	if (cert_stack != NULL) {
259499ebb4caSwyllys 		sk_X509_free(cert_stack);
259599ebb4caSwyllys 	}
259699ebb4caSwyllys 
259799ebb4caSwyllys 	return (ret);
259899ebb4caSwyllys }
259999ebb4caSwyllys 
260099ebb4caSwyllys 
260199ebb4caSwyllys 
260299ebb4caSwyllys KMF_RETURN
260399ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
260430a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
260599ebb4caSwyllys {
260699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
260799ebb4caSwyllys 	BIO *derbio = NULL;
260899ebb4caSwyllys 	OCSP_RESPONSE *resp = NULL;
260999ebb4caSwyllys 	OCSP_BASICRESP *bs = NULL;
261099ebb4caSwyllys 	OCSP_CERTID *id = NULL;
261199ebb4caSwyllys 	OCSP_SINGLERESP *single = NULL;
261299ebb4caSwyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
261399ebb4caSwyllys 	int index, status, reason;
261430a5e8faSwyllys 	KMF_DATA *issuer_cert;
261530a5e8faSwyllys 	KMF_DATA *user_cert;
261630a5e8faSwyllys 	KMF_DATA *signer_cert;
261730a5e8faSwyllys 	KMF_DATA *response;
261830a5e8faSwyllys 	int *response_reason, *response_status, *cert_status;
261930a5e8faSwyllys 	boolean_t ignore_response_sign = B_FALSE;	/* default is FALSE */
262030a5e8faSwyllys 	uint32_t response_lifetime;
262199ebb4caSwyllys 
262230a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
262330a5e8faSwyllys 	    attrlist, numattr);
262430a5e8faSwyllys 	if (issuer_cert == NULL)
262599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
262699ebb4caSwyllys 
262730a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
262830a5e8faSwyllys 	    attrlist, numattr);
262930a5e8faSwyllys 	if (user_cert == NULL)
263099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
263130a5e8faSwyllys 
263230a5e8faSwyllys 	response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
263330a5e8faSwyllys 	    attrlist, numattr);
263430a5e8faSwyllys 	if (response == NULL)
263530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
263630a5e8faSwyllys 
263730a5e8faSwyllys 	response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
263830a5e8faSwyllys 	    attrlist, numattr);
263930a5e8faSwyllys 	if (response_status == NULL)
264030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
264130a5e8faSwyllys 
264230a5e8faSwyllys 	response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
264330a5e8faSwyllys 	    attrlist, numattr);
264430a5e8faSwyllys 	if (response_reason == NULL)
264530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
264630a5e8faSwyllys 
264730a5e8faSwyllys 	cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
264830a5e8faSwyllys 	    attrlist, numattr);
264930a5e8faSwyllys 	if (cert_status == NULL)
265030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
265199ebb4caSwyllys 
265299ebb4caSwyllys 	/* Read in the response */
265330a5e8faSwyllys 	derbio = BIO_new_mem_buf(response->Data, response->Length);
265499ebb4caSwyllys 	if (!derbio) {
265599ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
265699ebb4caSwyllys 		return (ret);
265799ebb4caSwyllys 	}
265899ebb4caSwyllys 
265999ebb4caSwyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
266099ebb4caSwyllys 	if (resp == NULL) {
266199ebb4caSwyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
266299ebb4caSwyllys 		goto end;
266399ebb4caSwyllys 	}
266499ebb4caSwyllys 
266599ebb4caSwyllys 	/* Check the response status */
266699ebb4caSwyllys 	status = OCSP_response_status(resp);
266730a5e8faSwyllys 	*response_status = status;
266899ebb4caSwyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
266999ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
267099ebb4caSwyllys 		goto end;
267199ebb4caSwyllys 	}
267299ebb4caSwyllys 
267399ebb4caSwyllys #ifdef DEBUG
267499ebb4caSwyllys 	printf("Successfully checked the response file status.\n");
267599ebb4caSwyllys #endif /* DEBUG */
267699ebb4caSwyllys 
267799ebb4caSwyllys 	/* Extract basic response */
267899ebb4caSwyllys 	bs = OCSP_response_get1_basic(resp);
267999ebb4caSwyllys 	if (bs == NULL) {
268099ebb4caSwyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
268199ebb4caSwyllys 		goto end;
268299ebb4caSwyllys 	}
268399ebb4caSwyllys 
268499ebb4caSwyllys #ifdef DEBUG
268599ebb4caSwyllys 	printf("Successfully retrieved the basic response.\n");
268699ebb4caSwyllys #endif /* DEBUG */
268799ebb4caSwyllys 
268899ebb4caSwyllys 	/* Check the basic response signature if required */
268930a5e8faSwyllys 	ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
269030a5e8faSwyllys 	    (void *)&ignore_response_sign, NULL);
269130a5e8faSwyllys 	if (ret != KMF_OK)
269230a5e8faSwyllys 		ret = KMF_OK;
269330a5e8faSwyllys 
269430a5e8faSwyllys 	signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
269530a5e8faSwyllys 	    attrlist, numattr);
269630a5e8faSwyllys 
269730a5e8faSwyllys 	if (ignore_response_sign == B_FALSE) {
269899ebb4caSwyllys 		ret = check_response_signature(handle, bs,
269930a5e8faSwyllys 		    signer_cert, issuer_cert);
270099ebb4caSwyllys 		if (ret != KMF_OK)
270199ebb4caSwyllys 			goto end;
270299ebb4caSwyllys 	}
270399ebb4caSwyllys 
270499ebb4caSwyllys #ifdef DEBUG
270599ebb4caSwyllys 	printf("Successfully verified the response signature.\n");
270699ebb4caSwyllys #endif /* DEBUG */
270799ebb4caSwyllys 
270899ebb4caSwyllys 	/* Create a certid for the certificate in question */
270930a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
271099ebb4caSwyllys 	if (ret != KMF_OK) {
271199ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
271299ebb4caSwyllys 		goto end;
271399ebb4caSwyllys 	}
271499ebb4caSwyllys 
271599ebb4caSwyllys #ifdef DEBUG
271699ebb4caSwyllys 	printf("successfully created a certid for the cert.\n");
271799ebb4caSwyllys #endif /* DEBUG */
271899ebb4caSwyllys 
271999ebb4caSwyllys 	/* Find the index of the single response for the certid */
272099ebb4caSwyllys 	index = OCSP_resp_find(bs, id, -1);
272199ebb4caSwyllys 	if (index < 0) {
272299ebb4caSwyllys 		/* cound not find this certificate in the response */
272399ebb4caSwyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
272499ebb4caSwyllys 		goto end;
272599ebb4caSwyllys 	}
272699ebb4caSwyllys 
272799ebb4caSwyllys #ifdef DEBUG
272899ebb4caSwyllys 	printf("Successfully found the single response index for the cert.\n");
272999ebb4caSwyllys #endif /* DEBUG */
273099ebb4caSwyllys 
273199ebb4caSwyllys 	/* Retrieve the single response and get the cert status */
273299ebb4caSwyllys 	single = OCSP_resp_get0(bs, index);
273399ebb4caSwyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
273499ebb4caSwyllys 	    &nextupd);
273599ebb4caSwyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
273630a5e8faSwyllys 		*cert_status = OCSP_GOOD;
273799ebb4caSwyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
273830a5e8faSwyllys 		*cert_status = OCSP_UNKNOWN;
273999ebb4caSwyllys 	} else { /* revoked */
274030a5e8faSwyllys 		*cert_status = OCSP_REVOKED;
274130a5e8faSwyllys 		*response_reason = reason;
274299ebb4caSwyllys 	}
274399ebb4caSwyllys 	ret = KMF_OK;
274499ebb4caSwyllys 
274530a5e8faSwyllys 	/* resp. time is optional, so we don't care about the return code. */
274630a5e8faSwyllys 	(void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
274730a5e8faSwyllys 	    (void *)&response_lifetime, NULL);
274830a5e8faSwyllys 
274999ebb4caSwyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
275030a5e8faSwyllys 	    response_lifetime)) {
275199ebb4caSwyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
275299ebb4caSwyllys 		goto end;
275399ebb4caSwyllys 	}
275499ebb4caSwyllys 
275599ebb4caSwyllys #ifdef DEBUG
275699ebb4caSwyllys 	printf("Successfully verify the time.\n");
275799ebb4caSwyllys #endif /* DEBUG */
275899ebb4caSwyllys 
275999ebb4caSwyllys end:
276099ebb4caSwyllys 	if (derbio != NULL)
276199ebb4caSwyllys 		(void) BIO_free(derbio);
276299ebb4caSwyllys 
276399ebb4caSwyllys 	if (resp != NULL)
276499ebb4caSwyllys 		OCSP_RESPONSE_free(resp);
276599ebb4caSwyllys 
276699ebb4caSwyllys 	if (bs != NULL)
276799ebb4caSwyllys 		OCSP_BASICRESP_free(bs);
276899ebb4caSwyllys 
276999ebb4caSwyllys 	if (id != NULL)
277099ebb4caSwyllys 		OCSP_CERTID_free(id);
277199ebb4caSwyllys 
277299ebb4caSwyllys 	return (ret);
277399ebb4caSwyllys }
277499ebb4caSwyllys 
277599ebb4caSwyllys static KMF_RETURN
277699ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path,
277799ebb4caSwyllys 	KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
277899ebb4caSwyllys {
277999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
278030a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
278199ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
278299ebb4caSwyllys 
278399ebb4caSwyllys 	if (keyclass == KMF_ASYM_PRI ||
278499ebb4caSwyllys 	    keyclass == KMF_ASYM_PUB) {
278599ebb4caSwyllys 		pkey = openssl_load_key(handle, path);
278699ebb4caSwyllys 		if (pkey == NULL) {
278799ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
278899ebb4caSwyllys 		}
278999ebb4caSwyllys 		if (key != NULL) {
279099ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA)
279199ebb4caSwyllys 				key->keyalg = KMF_RSA;
279299ebb4caSwyllys 			else if (pkey->type == EVP_PKEY_DSA)
279399ebb4caSwyllys 				key->keyalg = KMF_DSA;
279499ebb4caSwyllys 
279599ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
279699ebb4caSwyllys 			key->keyclass = keyclass;
279799ebb4caSwyllys 			key->keyp = (void *)pkey;
279899ebb4caSwyllys 			key->israw = FALSE;
27995b3e1433Swyllys 			if (path != NULL &&
28005b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
28015b3e1433Swyllys 				EVP_PKEY_free(pkey);
28025b3e1433Swyllys 				return (KMF_ERR_MEMORY);
28035b3e1433Swyllys 			}
280499ebb4caSwyllys 		} else {
280599ebb4caSwyllys 			EVP_PKEY_free(pkey);
280699ebb4caSwyllys 			pkey = NULL;
280799ebb4caSwyllys 		}
280899ebb4caSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
280999ebb4caSwyllys 		KMF_ENCODE_FORMAT fmt;
281099ebb4caSwyllys 		/*
281199ebb4caSwyllys 		 * If the file is a recognized format,
281299ebb4caSwyllys 		 * then it is NOT a symmetric key.
281399ebb4caSwyllys 		 */
281430a5e8faSwyllys 		rv = kmf_get_file_format(path, &fmt);
281599ebb4caSwyllys 		if (rv == KMF_OK || fmt != 0) {
281699ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
281799ebb4caSwyllys 		} else if (rv == KMF_ERR_ENCODING) {
281899ebb4caSwyllys 			/*
281999ebb4caSwyllys 			 * If we don't know the encoding,
282099ebb4caSwyllys 			 * it is probably  a symmetric key.
282199ebb4caSwyllys 			 */
282299ebb4caSwyllys 			rv = KMF_OK;
282330a5e8faSwyllys 		} else if (rv == KMF_ERR_OPEN_FILE) {
282430a5e8faSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
282599ebb4caSwyllys 		}
282699ebb4caSwyllys 
282799ebb4caSwyllys 		if (key != NULL) {
282899ebb4caSwyllys 			KMF_DATA keyvalue;
282999ebb4caSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
283099ebb4caSwyllys 			if (rkey == NULL) {
283199ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
283299ebb4caSwyllys 				goto out;
283399ebb4caSwyllys 			}
283499ebb4caSwyllys 
283599ebb4caSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
283630a5e8faSwyllys 			rv = kmf_read_input_file(handle, path, &keyvalue);
283799ebb4caSwyllys 			if (rv != KMF_OK)
283899ebb4caSwyllys 				goto out;
283999ebb4caSwyllys 
284099ebb4caSwyllys 			rkey->keydata.len = keyvalue.Length;
284199ebb4caSwyllys 			rkey->keydata.val = keyvalue.Data;
284299ebb4caSwyllys 
284399ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
284499ebb4caSwyllys 			key->keyclass = keyclass;
284599ebb4caSwyllys 			key->israw = TRUE;
284699ebb4caSwyllys 			key->keyp = (void *)rkey;
28475b3e1433Swyllys 			if (path != NULL &&
28485b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
28495b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
28505b3e1433Swyllys 			}
285199ebb4caSwyllys 		}
285299ebb4caSwyllys 	}
285399ebb4caSwyllys out:
285499ebb4caSwyllys 	if (rv != KMF_OK) {
285599ebb4caSwyllys 		if (rkey != NULL) {
285630a5e8faSwyllys 			kmf_free_raw_sym_key(rkey);
285799ebb4caSwyllys 		}
285899ebb4caSwyllys 		if (pkey != NULL)
285999ebb4caSwyllys 			EVP_PKEY_free(pkey);
286099ebb4caSwyllys 
286199ebb4caSwyllys 		if (key != NULL) {
286299ebb4caSwyllys 			key->keyalg = KMF_KEYALG_NONE;
286399ebb4caSwyllys 			key->keyclass = KMF_KEYCLASS_NONE;
286499ebb4caSwyllys 			key->keyp = NULL;
286599ebb4caSwyllys 		}
286699ebb4caSwyllys 	}
286799ebb4caSwyllys 
286899ebb4caSwyllys 	return (rv);
286999ebb4caSwyllys }
287099ebb4caSwyllys 
287199ebb4caSwyllys KMF_RETURN
287230a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle,
287330a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
287499ebb4caSwyllys {
287599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
287699ebb4caSwyllys 	char *fullpath = NULL;
2877f482c776Swyllys 	uint32_t maxkeys;
287830a5e8faSwyllys 	KMF_KEY_HANDLE *key;
287930a5e8faSwyllys 	uint32_t *numkeys;
288030a5e8faSwyllys 	KMF_KEY_CLASS keyclass;
288130a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
288230a5e8faSwyllys 	char *dirpath;
288330a5e8faSwyllys 	char *keyfile;
288499ebb4caSwyllys 
288530a5e8faSwyllys 	if (handle == NULL)
288699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
288799ebb4caSwyllys 
288830a5e8faSwyllys 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
288930a5e8faSwyllys 	if (numkeys == NULL)
289030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
289130a5e8faSwyllys 
289230a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
289330a5e8faSwyllys 	    (void *)&keyclass, NULL);
289430a5e8faSwyllys 	if (rv != KMF_OK)
289530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
289630a5e8faSwyllys 
289730a5e8faSwyllys 	if (keyclass != KMF_ASYM_PUB &&
289830a5e8faSwyllys 	    keyclass != KMF_ASYM_PRI &&
289930a5e8faSwyllys 	    keyclass != KMF_SYMMETRIC)
290099ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
290199ebb4caSwyllys 
290230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
290330a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
290430a5e8faSwyllys 
290530a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
290699ebb4caSwyllys 
290799ebb4caSwyllys 	if (fullpath == NULL)
290899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
290999ebb4caSwyllys 
2910f482c776Swyllys 	maxkeys = *numkeys;
2911f482c776Swyllys 	if (maxkeys == 0)
2912f482c776Swyllys 		maxkeys = 0xFFFFFFFF;
291399ebb4caSwyllys 	*numkeys = 0;
291499ebb4caSwyllys 
291530a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
291630a5e8faSwyllys 	/* it is okay to have "keys" contains NULL */
291730a5e8faSwyllys 
291830a5e8faSwyllys 	/*
291930a5e8faSwyllys 	 * The caller may want a list of the raw key data as well.
292030a5e8faSwyllys 	 * Useful for importing keys from a file into other keystores.
292130a5e8faSwyllys 	 */
292230a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
292330a5e8faSwyllys 
292499ebb4caSwyllys 	if (isdir(fullpath)) {
292599ebb4caSwyllys 		DIR *dirp;
292699ebb4caSwyllys 		struct dirent *dp;
292799ebb4caSwyllys 		int n = 0;
292899ebb4caSwyllys 
292999ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
293099ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
293199ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
293299ebb4caSwyllys 		}
293399ebb4caSwyllys 		rewinddir(dirp);
2934f482c776Swyllys 		while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
293599ebb4caSwyllys 			if (strcmp(dp->d_name, ".") &&
293699ebb4caSwyllys 			    strcmp(dp->d_name, "..")) {
293799ebb4caSwyllys 				char *fname;
293899ebb4caSwyllys 
293999ebb4caSwyllys 				fname = get_fullpath(fullpath,
294099ebb4caSwyllys 				    (char *)&dp->d_name);
294199ebb4caSwyllys 
294299ebb4caSwyllys 				rv = fetch_key(handle, fname,
294330a5e8faSwyllys 				    keyclass, key ? &key[n] : NULL);
294499ebb4caSwyllys 
294530a5e8faSwyllys 				if (rv == KMF_OK) {
294630a5e8faSwyllys 					if (key != NULL && rawkey != NULL)
294730a5e8faSwyllys 						rv = convertToRawKey(
294830a5e8faSwyllys 						    key[n].keyp, &rawkey[n]);
294999ebb4caSwyllys 					n++;
295030a5e8faSwyllys 				}
295199ebb4caSwyllys 
295299ebb4caSwyllys 				if (rv != KMF_OK || key == NULL)
295399ebb4caSwyllys 					free(fname);
295499ebb4caSwyllys 			}
295599ebb4caSwyllys 		}
295699ebb4caSwyllys 		(void) closedir(dirp);
295799ebb4caSwyllys 		free(fullpath);
295899ebb4caSwyllys 		(*numkeys) = n;
295999ebb4caSwyllys 	} else {
296030a5e8faSwyllys 		rv = fetch_key(handle, fullpath, keyclass, key);
296199ebb4caSwyllys 		if (rv == KMF_OK)
296299ebb4caSwyllys 			(*numkeys) = 1;
296399ebb4caSwyllys 
296499ebb4caSwyllys 		if (rv != KMF_OK || key == NULL)
296599ebb4caSwyllys 			free(fullpath);
296630a5e8faSwyllys 
296730a5e8faSwyllys 		if (rv == KMF_OK && key != NULL && rawkey != NULL) {
296830a5e8faSwyllys 			rv = convertToRawKey(key->keyp, rawkey);
296930a5e8faSwyllys 		}
297099ebb4caSwyllys 	}
297199ebb4caSwyllys 
2972f482c776Swyllys 	if (rv == KMF_OK && (*numkeys) == 0)
297399ebb4caSwyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
297473cc0e02Swyllys 	else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
297573cc0e02Swyllys 		rv = KMF_OK;
297699ebb4caSwyllys 
297799ebb4caSwyllys 	return (rv);
297899ebb4caSwyllys }
297999ebb4caSwyllys 
298099ebb4caSwyllys #define	HANDLE_PK12_ERROR { \
298199ebb4caSwyllys 	SET_ERROR(kmfh, ERR_get_error()); \
298299ebb4caSwyllys 	rv = KMF_ERR_ENCODING; \
298399ebb4caSwyllys 	goto out; \
298499ebb4caSwyllys }
298599ebb4caSwyllys 
29865b3e1433Swyllys static int
29875b3e1433Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
298899ebb4caSwyllys {
29895b3e1433Swyllys 	if (xcert != NULL && xcert->aux != NULL &&
29905b3e1433Swyllys 	    xcert->aux->alias != NULL) {
29915b3e1433Swyllys 		if (PKCS12_add_friendlyname_asc(bag,
29925b3e1433Swyllys 		    (const char *)xcert->aux->alias->data,
29935b3e1433Swyllys 		    xcert->aux->alias->length) == 0)
29945b3e1433Swyllys 			return (0);
29955b3e1433Swyllys 	}
29965b3e1433Swyllys 	return (1);
29975b3e1433Swyllys }
29985b3e1433Swyllys 
29995b3e1433Swyllys static PKCS7 *
30005b3e1433Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
30015b3e1433Swyllys 	uchar_t *keyid, unsigned int keyidlen)
30025b3e1433Swyllys {
300399ebb4caSwyllys 	PKCS12_SAFEBAG *bag = NULL;
300499ebb4caSwyllys 	PKCS7 *cert_authsafe = NULL;
30055b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack;
300699ebb4caSwyllys 
300799ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
300899ebb4caSwyllys 	if (bag_stack == NULL)
30095b3e1433Swyllys 		return (NULL);
301099ebb4caSwyllys 
301199ebb4caSwyllys 	/* Convert cert from X509 struct to PKCS#12 bag */
301299ebb4caSwyllys 	bag = PKCS12_x5092certbag(sslcert);
301399ebb4caSwyllys 	if (bag == NULL) {
30145b3e1433Swyllys 		goto out;
301599ebb4caSwyllys 	}
301699ebb4caSwyllys 
301799ebb4caSwyllys 	/* Add the key id to the certificate bag. */
30185b3e1433Swyllys 	if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
30195b3e1433Swyllys 		goto out;
302099ebb4caSwyllys 	}
302199ebb4caSwyllys 
30225b3e1433Swyllys 	if (!add_alias_to_bag(bag, sslcert))
30235b3e1433Swyllys 		goto out;
30245b3e1433Swyllys 
302599ebb4caSwyllys 	/* Pile it on the bag_stack. */
302699ebb4caSwyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
30275b3e1433Swyllys 		goto out;
302899ebb4caSwyllys 	}
302999ebb4caSwyllys 	/* Turn bag_stack of certs into encrypted authsafe. */
303099ebb4caSwyllys 	cert_authsafe = PKCS12_pack_p7encdata(
303199ebb4caSwyllys 	    NID_pbe_WithSHA1And40BitRC2_CBC,
303234acef67Swyllys 	    cred->cred, cred->credlen, NULL, 0,
303334acef67Swyllys 	    PKCS12_DEFAULT_ITER, bag_stack);
303499ebb4caSwyllys 
30355b3e1433Swyllys out:
30365b3e1433Swyllys 	if (bag_stack != NULL)
303799ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
303899ebb4caSwyllys 
30395b3e1433Swyllys 	return (cert_authsafe);
304099ebb4caSwyllys }
30415b3e1433Swyllys 
30425b3e1433Swyllys static PKCS7 *
30435b3e1433Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
30445b3e1433Swyllys 	uchar_t *keyid,  unsigned int keyidlen,
30455b3e1433Swyllys 	char *label, int label_len)
30465b3e1433Swyllys {
30475b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
30485b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
30495b3e1433Swyllys 	PKCS12_SAFEBAG *bag = NULL;
30505b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
30515b3e1433Swyllys 
305299ebb4caSwyllys 	p8 = EVP_PKEY2PKCS8(pkey);
305399ebb4caSwyllys 	if (p8 == NULL) {
30545b3e1433Swyllys 		return (NULL);
305599ebb4caSwyllys 	}
305699ebb4caSwyllys 	/* Put the shrouded key into a PKCS#12 bag. */
305799ebb4caSwyllys 	bag = PKCS12_MAKE_SHKEYBAG(
305899ebb4caSwyllys 	    NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
305999ebb4caSwyllys 	    cred->cred, cred->credlen,
306099ebb4caSwyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, p8);
306199ebb4caSwyllys 
306299ebb4caSwyllys 	/* Clean up the PKCS#8 shrouded key, don't need it now. */
306399ebb4caSwyllys 	PKCS8_PRIV_KEY_INFO_free(p8);
306499ebb4caSwyllys 	p8 = NULL;
306599ebb4caSwyllys 
306699ebb4caSwyllys 	if (bag == NULL) {
30675b3e1433Swyllys 		return (NULL);
306899ebb4caSwyllys 	}
30695b3e1433Swyllys 	if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
30705b3e1433Swyllys 		goto out;
30715b3e1433Swyllys 	if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
30725b3e1433Swyllys 		goto out;
30735b3e1433Swyllys 
307499ebb4caSwyllys 	/* Start a PKCS#12 safebag container for the private key. */
307599ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
30765b3e1433Swyllys 	if (bag_stack == NULL)
30775b3e1433Swyllys 		goto out;
307899ebb4caSwyllys 
307999ebb4caSwyllys 	/* Pile on the private key on the bag_stack. */
30805b3e1433Swyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
30815b3e1433Swyllys 		goto out;
30825b3e1433Swyllys 
308399ebb4caSwyllys 	key_authsafe = PKCS12_pack_p7data(bag_stack);
308499ebb4caSwyllys 
30855b3e1433Swyllys out:
30865b3e1433Swyllys 	if (bag_stack != NULL)
308799ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
308899ebb4caSwyllys 	bag_stack = NULL;
30895b3e1433Swyllys 	return (key_authsafe);
309099ebb4caSwyllys }
309199ebb4caSwyllys 
309299ebb4caSwyllys static EVP_PKEY *
309399ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
309499ebb4caSwyllys {
309599ebb4caSwyllys 	RSA		*rsa = NULL;
309699ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
309799ebb4caSwyllys 
309899ebb4caSwyllys 	if ((rsa = RSA_new()) == NULL)
309999ebb4caSwyllys 		return (NULL);
310099ebb4caSwyllys 
310199ebb4caSwyllys 	if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL)
310299ebb4caSwyllys 		return (NULL);
310399ebb4caSwyllys 
310499ebb4caSwyllys 	if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) ==
310599ebb4caSwyllys 	    NULL)
310699ebb4caSwyllys 		return (NULL);
310799ebb4caSwyllys 
310899ebb4caSwyllys 	if (key->priexp.val != NULL)
310999ebb4caSwyllys 		if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len,
311099ebb4caSwyllys 		    rsa->d)) == NULL)
311199ebb4caSwyllys 			return (NULL);
311299ebb4caSwyllys 
311399ebb4caSwyllys 	if (key->prime1.val != NULL)
311499ebb4caSwyllys 		if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len,
311599ebb4caSwyllys 		    rsa->p)) == NULL)
311699ebb4caSwyllys 			return (NULL);
311799ebb4caSwyllys 
311899ebb4caSwyllys 	if (key->prime2.val != NULL)
311999ebb4caSwyllys 		if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len,
312099ebb4caSwyllys 		    rsa->q)) == NULL)
312199ebb4caSwyllys 			return (NULL);
312299ebb4caSwyllys 
312399ebb4caSwyllys 	if (key->exp1.val != NULL)
312499ebb4caSwyllys 		if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len,
312599ebb4caSwyllys 		    rsa->dmp1)) == NULL)
312699ebb4caSwyllys 			return (NULL);
312799ebb4caSwyllys 
312899ebb4caSwyllys 	if (key->exp2.val != NULL)
312999ebb4caSwyllys 		if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len,
313099ebb4caSwyllys 		    rsa->dmq1)) == NULL)
313199ebb4caSwyllys 			return (NULL);
313299ebb4caSwyllys 
313399ebb4caSwyllys 	if (key->coef.val != NULL)
313499ebb4caSwyllys 		if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len,
313599ebb4caSwyllys 		    rsa->iqmp)) == NULL)
313699ebb4caSwyllys 			return (NULL);
313799ebb4caSwyllys 
313899ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
313999ebb4caSwyllys 		return (NULL);
314099ebb4caSwyllys 
314199ebb4caSwyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
314299ebb4caSwyllys 
314399ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
314499ebb4caSwyllys 	RSA_free(rsa);
314599ebb4caSwyllys 
314699ebb4caSwyllys 	return (newkey);
314799ebb4caSwyllys }
314899ebb4caSwyllys 
314999ebb4caSwyllys static EVP_PKEY *
315099ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
315199ebb4caSwyllys {
315299ebb4caSwyllys 	DSA		*dsa = NULL;
315399ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
315499ebb4caSwyllys 
315599ebb4caSwyllys 	if ((dsa = DSA_new()) == NULL)
315699ebb4caSwyllys 		return (NULL);
315799ebb4caSwyllys 
315899ebb4caSwyllys 	if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len,
315999ebb4caSwyllys 	    dsa->p)) == NULL)
316099ebb4caSwyllys 		return (NULL);
316199ebb4caSwyllys 
316299ebb4caSwyllys 	if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len,
316399ebb4caSwyllys 	    dsa->q)) == NULL)
316499ebb4caSwyllys 		return (NULL);
316599ebb4caSwyllys 
316699ebb4caSwyllys 	if ((dsa->g = BN_bin2bn(key->base.val, key->base.len,
316799ebb4caSwyllys 	    dsa->g)) == NULL)
316899ebb4caSwyllys 		return (NULL);
316999ebb4caSwyllys 
317099ebb4caSwyllys 	if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len,
317199ebb4caSwyllys 	    dsa->priv_key)) == NULL)
317299ebb4caSwyllys 		return (NULL);
317399ebb4caSwyllys 
317430a5e8faSwyllys 	if (key->pubvalue.val != NULL) {
317530a5e8faSwyllys 		if ((dsa->pub_key = BN_bin2bn(key->pubvalue.val,
317630a5e8faSwyllys 		    key->pubvalue.len, dsa->pub_key)) == NULL)
317730a5e8faSwyllys 			return (NULL);
317830a5e8faSwyllys 	}
317930a5e8faSwyllys 
318099ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
318199ebb4caSwyllys 		return (NULL);
318299ebb4caSwyllys 
318399ebb4caSwyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
318499ebb4caSwyllys 
318599ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
318699ebb4caSwyllys 	DSA_free(dsa);
318799ebb4caSwyllys 	return (newkey);
318899ebb4caSwyllys }
318999ebb4caSwyllys 
31905b3e1433Swyllys static EVP_PKEY *
31915b3e1433Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key)
31925b3e1433Swyllys {
31935b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
31945b3e1433Swyllys 	KMF_RAW_KEY_DATA *rawkey;
31955b3e1433Swyllys 	ASN1_TYPE *attr = NULL;
31965b3e1433Swyllys 	KMF_RETURN ret;
31975b3e1433Swyllys 
31985b3e1433Swyllys 	if (key == NULL || !key->israw)
31995b3e1433Swyllys 		return (NULL);
32005b3e1433Swyllys 
32015b3e1433Swyllys 	rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
32025b3e1433Swyllys 	if (rawkey->keytype == KMF_RSA) {
32035b3e1433Swyllys 		pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
32045b3e1433Swyllys 	} else if (rawkey->keytype == KMF_DSA) {
32055b3e1433Swyllys 		pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
32065b3e1433Swyllys 	} else {
32075b3e1433Swyllys 		/* wrong kind of key */
32085b3e1433Swyllys 		return (NULL);
32095b3e1433Swyllys 	}
32105b3e1433Swyllys 
32115b3e1433Swyllys 	if (rawkey->label != NULL) {
32125b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
32135b3e1433Swyllys 			EVP_PKEY_free(pkey);
32145b3e1433Swyllys 			return (NULL);
32155b3e1433Swyllys 		}
32165b3e1433Swyllys 		attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
32175b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
32185b3e1433Swyllys 		    strlen(rawkey->label));
32195b3e1433Swyllys 		attr->type = V_ASN1_BMPSTRING;
32205b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.bmpstring;
32215b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
32225b3e1433Swyllys 		if (ret != KMF_OK) {
32235b3e1433Swyllys 			EVP_PKEY_free(pkey);
32245b3e1433Swyllys 			ASN1_TYPE_free(attr);
32255b3e1433Swyllys 			return (NULL);
32265b3e1433Swyllys 		}
32275b3e1433Swyllys 	}
32285b3e1433Swyllys 	if (rawkey->id.Data != NULL) {
32295b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
32305b3e1433Swyllys 			EVP_PKEY_free(pkey);
32315b3e1433Swyllys 			return (NULL);
32325b3e1433Swyllys 		}
32335b3e1433Swyllys 		attr->value.octet_string =
32345b3e1433Swyllys 		    ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
32355b3e1433Swyllys 		attr->type = V_ASN1_OCTET_STRING;
32365b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.octet_string,
32375b3e1433Swyllys 		    rawkey->id.Data, rawkey->id.Length);
32385b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.octet_string;
32395b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
32405b3e1433Swyllys 		if (ret != KMF_OK) {
32415b3e1433Swyllys 			EVP_PKEY_free(pkey);
32425b3e1433Swyllys 			ASN1_TYPE_free(attr);
32435b3e1433Swyllys 			return (NULL);
32445b3e1433Swyllys 		}
32455b3e1433Swyllys 	}
32465b3e1433Swyllys 	return (pkey);
32475b3e1433Swyllys }
32485b3e1433Swyllys 
32495b3e1433Swyllys /*
32505b3e1433Swyllys  * Search a list of private keys to find one that goes with the certificate.
32515b3e1433Swyllys  */
32525b3e1433Swyllys static EVP_PKEY *
32535b3e1433Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
32545b3e1433Swyllys {
32555b3e1433Swyllys 	int i;
32565b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
32575b3e1433Swyllys 
32585b3e1433Swyllys 	if (numkeys == 0 || keylist == NULL || xcert == NULL)
32595b3e1433Swyllys 		return (NULL);
32605b3e1433Swyllys 	for (i = 0; i < numkeys; i++) {
32615b3e1433Swyllys 		if (keylist[i].israw)
32625b3e1433Swyllys 			pkey = raw_key_to_pkey(&keylist[i]);
32635b3e1433Swyllys 		else
32645b3e1433Swyllys 			pkey = (EVP_PKEY *)keylist[i].keyp;
32655b3e1433Swyllys 		if (pkey != NULL) {
32665b3e1433Swyllys 			if (X509_check_private_key(xcert, pkey)) {
32675b3e1433Swyllys 				return (pkey);
32685b3e1433Swyllys 			} else {
32695b3e1433Swyllys 				EVP_PKEY_free(pkey);
32705b3e1433Swyllys 				pkey = NULL;
32715b3e1433Swyllys 			}
32725b3e1433Swyllys 		}
32735b3e1433Swyllys 	}
32745b3e1433Swyllys 	return (pkey);
32755b3e1433Swyllys }
32765b3e1433Swyllys 
327799ebb4caSwyllys static KMF_RETURN
32785b3e1433Swyllys local_export_pk12(KMF_HANDLE_T handle,
327999ebb4caSwyllys 	KMF_CREDENTIAL *cred,
328099ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
328199ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
328299ebb4caSwyllys 	char *filename)
328399ebb4caSwyllys {
328499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
328599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
328699ebb4caSwyllys 	BIO *bio = NULL;
32875b3e1433Swyllys 	PKCS7 *cert_authsafe = NULL;
32885b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
32895b3e1433Swyllys 	STACK_OF(PKCS7) *authsafe_stack = NULL;
32905b3e1433Swyllys 	PKCS12 *p12_elem = NULL;
329199ebb4caSwyllys 	int i;
329299ebb4caSwyllys 
32935b3e1433Swyllys 	if (numcerts == 0 && numkeys == 0)
32945b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
32955b3e1433Swyllys 
329699ebb4caSwyllys 	/*
329799ebb4caSwyllys 	 * Open the output file.
329899ebb4caSwyllys 	 */
329999ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
330099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
330199ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
330299ebb4caSwyllys 		goto cleanup;
330399ebb4caSwyllys 	}
330499ebb4caSwyllys 
33055b3e1433Swyllys 	/* Start a PKCS#7 stack. */
33065b3e1433Swyllys 	authsafe_stack = sk_PKCS7_new_null();
33075b3e1433Swyllys 	if (authsafe_stack == NULL) {
33085b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
33095b3e1433Swyllys 		goto cleanup;
33105b3e1433Swyllys 	}
33115b3e1433Swyllys 	if (numcerts > 0) {
331299ebb4caSwyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
331399ebb4caSwyllys 			const uchar_t *p = certlist[i].certificate.Data;
331499ebb4caSwyllys 			long len = certlist[i].certificate.Length;
33155b3e1433Swyllys 			X509 *xcert = NULL;
33165b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
33175b3e1433Swyllys 			unsigned char keyid[EVP_MAX_MD_SIZE];
33185b3e1433Swyllys 			unsigned int keyidlen = 0;
331999ebb4caSwyllys 
332099ebb4caSwyllys 			xcert = d2i_X509(NULL, &p, len);
332199ebb4caSwyllys 			if (xcert == NULL) {
332299ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
332399ebb4caSwyllys 				rv = KMF_ERR_ENCODING;
332499ebb4caSwyllys 			}
33255b3e1433Swyllys 			if (certlist[i].kmf_private.label != NULL) {
33265b3e1433Swyllys 				/* Set alias attribute */
33275b3e1433Swyllys 				(void) X509_alias_set1(xcert,
33285b3e1433Swyllys 				    (uchar_t *)certlist[i].kmf_private.label,
33295b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label));
33305b3e1433Swyllys 			}
33315b3e1433Swyllys 			/* Check if there is a key corresponding to this cert */
33325b3e1433Swyllys 			pkey = find_matching_key(xcert, numkeys, keylist);
33335b3e1433Swyllys 
33345b3e1433Swyllys 			/*
33355b3e1433Swyllys 			 * If key is found, get fingerprint and create a
33365b3e1433Swyllys 			 * safebag.
33375b3e1433Swyllys 			 */
33385b3e1433Swyllys 			if (pkey != NULL) {
33395b3e1433Swyllys 				(void) X509_digest(xcert, EVP_sha1(),
33405b3e1433Swyllys 				    keyid, &keyidlen);
33415b3e1433Swyllys 				key_authsafe = add_key_to_safe(pkey, cred,
33425b3e1433Swyllys 				    keyid, keyidlen,
33435b3e1433Swyllys 				    certlist[i].kmf_private.label,
33445b3e1433Swyllys 				    (certlist[i].kmf_private.label ?
33455b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label) : 0));
33465b3e1433Swyllys 
33475b3e1433Swyllys 				if (key_authsafe == NULL) {
33485b3e1433Swyllys 					X509_free(xcert);
33495b3e1433Swyllys 					EVP_PKEY_free(pkey);
33505b3e1433Swyllys 					goto cleanup;
33515b3e1433Swyllys 				}
33525b3e1433Swyllys 				/* Put the key safe into the Auth Safe */
33535b3e1433Swyllys 				if (!sk_PKCS7_push(authsafe_stack,
33545b3e1433Swyllys 				    key_authsafe)) {
33555b3e1433Swyllys 					X509_free(xcert);
33565b3e1433Swyllys 					EVP_PKEY_free(pkey);
33575b3e1433Swyllys 					goto cleanup;
33585b3e1433Swyllys 				}
33595b3e1433Swyllys 			}
33605b3e1433Swyllys 
33615b3e1433Swyllys 			/* create a certificate safebag */
33625b3e1433Swyllys 			cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
33635b3e1433Swyllys 			    keyidlen);
33645b3e1433Swyllys 			if (cert_authsafe == NULL) {
33655b3e1433Swyllys 				X509_free(xcert);
33665b3e1433Swyllys 				EVP_PKEY_free(pkey);
33675b3e1433Swyllys 				goto cleanup;
33685b3e1433Swyllys 			}
33695b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
33705b3e1433Swyllys 				X509_free(xcert);
33715b3e1433Swyllys 				EVP_PKEY_free(pkey);
33725b3e1433Swyllys 				goto cleanup;
33735b3e1433Swyllys 			}
33745b3e1433Swyllys 
337599ebb4caSwyllys 			X509_free(xcert);
337699ebb4caSwyllys 			if (pkey)
337799ebb4caSwyllys 				EVP_PKEY_free(pkey);
337899ebb4caSwyllys 		}
33795b3e1433Swyllys 	} else if (numcerts == 0 && numkeys > 0) {
33805b3e1433Swyllys 		/*
33815b3e1433Swyllys 		 * If only adding keys to the file.
33825b3e1433Swyllys 		 */
33835b3e1433Swyllys 		for (i = 0; i < numkeys; i++) {
33845b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
33855b3e1433Swyllys 
33865b3e1433Swyllys 			if (keylist[i].israw)
33875b3e1433Swyllys 				pkey = raw_key_to_pkey(&keylist[i]);
33885b3e1433Swyllys 			else
33895b3e1433Swyllys 				pkey = (EVP_PKEY *)keylist[i].keyp;
33905b3e1433Swyllys 
33915b3e1433Swyllys 			if (pkey == NULL)
33925b3e1433Swyllys 				continue;
33935b3e1433Swyllys 
33945b3e1433Swyllys 			key_authsafe = add_key_to_safe(pkey, cred,
33955b3e1433Swyllys 			    NULL, 0, NULL, 0);
33965b3e1433Swyllys 
33975b3e1433Swyllys 			if (key_authsafe == NULL) {
33985b3e1433Swyllys 				EVP_PKEY_free(pkey);
33995b3e1433Swyllys 				goto cleanup;
34005b3e1433Swyllys 			}
34015b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
34025b3e1433Swyllys 				EVP_PKEY_free(pkey);
34035b3e1433Swyllys 				goto cleanup;
34045b3e1433Swyllys 			}
34055b3e1433Swyllys 		}
34065b3e1433Swyllys 	}
34075b3e1433Swyllys 	p12_elem = PKCS12_init(NID_pkcs7_data);
34085b3e1433Swyllys 	if (p12_elem == NULL) {
34095b3e1433Swyllys 		goto cleanup;
341099ebb4caSwyllys 	}
341199ebb4caSwyllys 
34125b3e1433Swyllys 	/* Put the PKCS#7 stack into the PKCS#12 element. */
34135b3e1433Swyllys 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
34145b3e1433Swyllys 		goto cleanup;
34155b3e1433Swyllys 	}
34165b3e1433Swyllys 
34175b3e1433Swyllys 	/* Set the integrity MAC on the PKCS#12 element. */
34185b3e1433Swyllys 	if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
34195b3e1433Swyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
34205b3e1433Swyllys 		goto cleanup;
34215b3e1433Swyllys 	}
34225b3e1433Swyllys 
34235b3e1433Swyllys 	/* Write the PKCS#12 element to the export file. */
34245b3e1433Swyllys 	if (!i2d_PKCS12_bio(bio, p12_elem)) {
34255b3e1433Swyllys 		goto cleanup;
34265b3e1433Swyllys 	}
34275b3e1433Swyllys 	PKCS12_free(p12_elem);
34285b3e1433Swyllys 
342999ebb4caSwyllys cleanup:
34305b3e1433Swyllys 	/* Clear away the PKCS#7 stack, we're done with it. */
34315b3e1433Swyllys 	if (authsafe_stack)
34325b3e1433Swyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
343399ebb4caSwyllys 
343499ebb4caSwyllys 	if (bio != NULL)
343599ebb4caSwyllys 		(void) BIO_free_all(bio);
343699ebb4caSwyllys 
343799ebb4caSwyllys 	return (rv);
343899ebb4caSwyllys }
343999ebb4caSwyllys 
344099ebb4caSwyllys KMF_RETURN
344130a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
344230a5e8faSwyllys     KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
344330a5e8faSwyllys     KMF_CREDENTIAL *p12cred, char *filename)
344430a5e8faSwyllys {
344530a5e8faSwyllys 	KMF_RETURN rv;
344630a5e8faSwyllys 
344730a5e8faSwyllys 	if (certlist == NULL && keylist == NULL)
344830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
344930a5e8faSwyllys 
34505b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, numcerts, certlist,
345130a5e8faSwyllys 	    numkeys, keylist, filename);
345230a5e8faSwyllys 
345330a5e8faSwyllys 	return (rv);
345430a5e8faSwyllys }
345530a5e8faSwyllys 
345630a5e8faSwyllys KMF_RETURN
345730a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
345899ebb4caSwyllys {
345999ebb4caSwyllys 	KMF_RETURN rv;
346099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
346199ebb4caSwyllys 	char *fullpath = NULL;
346230a5e8faSwyllys 	char *dirpath = NULL;
346330a5e8faSwyllys 	char *certfile = NULL;
346430a5e8faSwyllys 	char *keyfile = NULL;
346530a5e8faSwyllys 	char *filename = NULL;
346630a5e8faSwyllys 	KMF_CREDENTIAL *p12cred = NULL;
34675b3e1433Swyllys 	KMF_X509_DER_CERT certdata;
34685b3e1433Swyllys 	KMF_KEY_HANDLE key;
34695b3e1433Swyllys 	int gotkey = 0;
34705b3e1433Swyllys 	int gotcert = 0;
347130a5e8faSwyllys 
347230a5e8faSwyllys 	if (handle == NULL)
347330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
347499ebb4caSwyllys 
347599ebb4caSwyllys 	/*
347699ebb4caSwyllys 	 *  First, find the certificate.
347799ebb4caSwyllys 	 */
347830a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
347930a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
348030a5e8faSwyllys 	if (certfile != NULL) {
348130a5e8faSwyllys 		fullpath = get_fullpath(dirpath, certfile);
348299ebb4caSwyllys 		if (fullpath == NULL)
348399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
348499ebb4caSwyllys 
348599ebb4caSwyllys 		if (isdir(fullpath)) {
348699ebb4caSwyllys 			free(fullpath);
348799ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
348899ebb4caSwyllys 		}
348999ebb4caSwyllys 
34905b3e1433Swyllys 		(void) memset(&certdata, 0, sizeof (certdata));
34915b3e1433Swyllys 		rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL,
34925b3e1433Swyllys 		    fullpath, &certdata.certificate);
349399ebb4caSwyllys 		if (rv != KMF_OK)
349499ebb4caSwyllys 			goto end;
349530a5e8faSwyllys 
34965b3e1433Swyllys 		gotcert++;
34975b3e1433Swyllys 		certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
349830a5e8faSwyllys 		free(fullpath);
349999ebb4caSwyllys 	}
350099ebb4caSwyllys 
350199ebb4caSwyllys 	/*
350299ebb4caSwyllys 	 * Now find the private key.
350399ebb4caSwyllys 	 */
350430a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
350530a5e8faSwyllys 	if (keyfile != NULL) {
350630a5e8faSwyllys 		fullpath = get_fullpath(dirpath, keyfile);
350799ebb4caSwyllys 		if (fullpath == NULL)
350899ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
350999ebb4caSwyllys 
351099ebb4caSwyllys 		if (isdir(fullpath)) {
351199ebb4caSwyllys 			free(fullpath);
351299ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
351399ebb4caSwyllys 		}
351499ebb4caSwyllys 
35155b3e1433Swyllys 		(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
35165b3e1433Swyllys 		rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
35175b3e1433Swyllys 		if (rv != KMF_OK)
351899ebb4caSwyllys 			goto end;
35195b3e1433Swyllys 		gotkey++;
352099ebb4caSwyllys 	}
352199ebb4caSwyllys 
352299ebb4caSwyllys 	/*
352399ebb4caSwyllys 	 * Open the output file.
352499ebb4caSwyllys 	 */
352530a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
352630a5e8faSwyllys 	    numattr);
352730a5e8faSwyllys 	if (filename == NULL) {
352830a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
352930a5e8faSwyllys 		goto end;
353030a5e8faSwyllys 	}
353130a5e8faSwyllys 
353299ebb4caSwyllys 	/* Stick the key and the cert into a PKCS#12 file */
353330a5e8faSwyllys 	p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
353430a5e8faSwyllys 	if (p12cred == NULL) {
353530a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
353630a5e8faSwyllys 		goto end;
353730a5e8faSwyllys 	}
353830a5e8faSwyllys 
35395b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, 1, &certdata,
35405b3e1433Swyllys 	    1, &key, filename);
354199ebb4caSwyllys 
354299ebb4caSwyllys end:
354399ebb4caSwyllys 	if (fullpath)
354499ebb4caSwyllys 		free(fullpath);
354599ebb4caSwyllys 
35465b3e1433Swyllys 	if (gotcert)
35475b3e1433Swyllys 		kmf_free_kmf_cert(handle, &certdata);
35485b3e1433Swyllys 	if (gotkey)
35495b3e1433Swyllys 		kmf_free_kmf_key(handle, &key);
355099ebb4caSwyllys 	return (rv);
355199ebb4caSwyllys }
355299ebb4caSwyllys 
355371593db2Swyllys /*
355471593db2Swyllys  * Helper function to extract keys and certificates from
355571593db2Swyllys  * a single PEM file.  Typically the file should contain a
355671593db2Swyllys  * private key and an associated public key wrapped in an x509 cert.
355771593db2Swyllys  * However, the file may be just a list of X509 certs with no keys.
355871593db2Swyllys  */
355971593db2Swyllys static KMF_RETURN
356030a5e8faSwyllys extract_pem(KMF_HANDLE *kmfh,
356130a5e8faSwyllys 	char *issuer, char *subject, KMF_BIGINT *serial,
356202744e81Swyllys 	char *filename, CK_UTF8CHAR *pin,
356371593db2Swyllys 	CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
356471593db2Swyllys 	int *numcerts)
3565*a2d4930dSDan OpenSolaris Anderson /* ARGSUSED6 */
356671593db2Swyllys {
356771593db2Swyllys 	KMF_RETURN rv = KMF_OK;
356871593db2Swyllys 	FILE *fp;
356934acef67Swyllys 	STACK_OF(X509_INFO) *x509_info_stack = NULL;
357002744e81Swyllys 	int i, ncerts = 0, matchcerts = 0;
357171593db2Swyllys 	EVP_PKEY *pkey = NULL;
357271593db2Swyllys 	X509_INFO *info;
357371593db2Swyllys 	X509 *x;
35745b3e1433Swyllys 	X509_INFO **cert_infos = NULL;
357571593db2Swyllys 	KMF_DATA *certlist = NULL;
357671593db2Swyllys 
357771593db2Swyllys 	if (priv_key)
357871593db2Swyllys 		*priv_key = NULL;
357971593db2Swyllys 	if (certs)
358071593db2Swyllys 		*certs = NULL;
358171593db2Swyllys 	fp = fopen(filename, "r");
35825b3e1433Swyllys 	if (fp == NULL)
358371593db2Swyllys 		return (KMF_ERR_OPEN_FILE);
35845b3e1433Swyllys 
358571593db2Swyllys 	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
358671593db2Swyllys 	if (x509_info_stack == NULL) {
358771593db2Swyllys 		(void) fclose(fp);
358871593db2Swyllys 		return (KMF_ERR_ENCODING);
358971593db2Swyllys 	}
35905b3e1433Swyllys 	cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
35915b3e1433Swyllys 	    sizeof (X509_INFO *));
35925b3e1433Swyllys 	if (cert_infos == NULL) {
35935b3e1433Swyllys 		(void) fclose(fp);
35945b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
35955b3e1433Swyllys 		goto err;
35965b3e1433Swyllys 	}
359771593db2Swyllys 
35985b3e1433Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3599*a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
360034acef67Swyllys 		cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
360171593db2Swyllys 		ncerts++;
360271593db2Swyllys 	}
360371593db2Swyllys 
360471593db2Swyllys 	if (ncerts == 0) {
360571593db2Swyllys 		(void) fclose(fp);
360634acef67Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
360734acef67Swyllys 		goto err;
360871593db2Swyllys 	}
360971593db2Swyllys 
361071593db2Swyllys 	if (priv_key != NULL) {
361171593db2Swyllys 		rewind(fp);
361271593db2Swyllys 		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
361371593db2Swyllys 	}
361471593db2Swyllys 	(void) fclose(fp);
361571593db2Swyllys 
361671593db2Swyllys 	x = cert_infos[ncerts - 1]->x509;
361771593db2Swyllys 	/*
361871593db2Swyllys 	 * Make sure the private key matchs the last cert in the file.
361971593db2Swyllys 	 */
362071593db2Swyllys 	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
362171593db2Swyllys 		EVP_PKEY_free(pkey);
362234acef67Swyllys 		rv = KMF_ERR_KEY_MISMATCH;
362334acef67Swyllys 		goto err;
362471593db2Swyllys 	}
362571593db2Swyllys 
3626*a2d4930dSDan OpenSolaris Anderson 	certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
362771593db2Swyllys 	if (certlist == NULL) {
362871593db2Swyllys 		if (pkey != NULL)
362971593db2Swyllys 			EVP_PKEY_free(pkey);
363034acef67Swyllys 		rv = KMF_ERR_MEMORY;
363134acef67Swyllys 		goto err;
363271593db2Swyllys 	}
363371593db2Swyllys 
363471593db2Swyllys 	/*
363571593db2Swyllys 	 * Convert all of the certs to DER format.
363671593db2Swyllys 	 */
363702744e81Swyllys 	matchcerts = 0;
363871593db2Swyllys 	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
363902744e81Swyllys 		boolean_t match = FALSE;
364071593db2Swyllys 		info =  cert_infos[ncerts - 1 - i];
364171593db2Swyllys 
364230a5e8faSwyllys 		rv = check_cert(info->x509, issuer, subject, serial, &match);
364302744e81Swyllys 		if (rv != KMF_OK || match != TRUE) {
364402744e81Swyllys 			rv = KMF_OK;
364502744e81Swyllys 			continue;
364602744e81Swyllys 		}
364702744e81Swyllys 
364802744e81Swyllys 		rv = ssl_cert2KMFDATA(kmfh, info->x509,
364902744e81Swyllys 			&certlist[matchcerts++]);
365071593db2Swyllys 
365171593db2Swyllys 		if (rv != KMF_OK) {
3652*a2d4930dSDan OpenSolaris Anderson 			kmf_free_data(certlist);
365371593db2Swyllys 			free(certlist);
365471593db2Swyllys 			certlist = NULL;
365502744e81Swyllys 			ncerts = matchcerts = 0;
365671593db2Swyllys 		}
365771593db2Swyllys 	}
365871593db2Swyllys 
365971593db2Swyllys 	if (numcerts != NULL)
366002744e81Swyllys 		*numcerts = matchcerts;
3661*a2d4930dSDan OpenSolaris Anderson 
3662*a2d4930dSDan OpenSolaris Anderson 	if (certs != NULL) {
366371593db2Swyllys 		*certs = certlist;
3664*a2d4930dSDan OpenSolaris Anderson 	} else if (certlist != NULL) {
3665*a2d4930dSDan OpenSolaris Anderson 		kmf_free_data(certlist);
3666*a2d4930dSDan OpenSolaris Anderson 		free(certlist);
3667*a2d4930dSDan OpenSolaris Anderson 		certlist = NULL;
3668*a2d4930dSDan OpenSolaris Anderson 	}
366971593db2Swyllys 
367071593db2Swyllys 	if (priv_key == NULL && pkey != NULL)
367171593db2Swyllys 		EVP_PKEY_free(pkey);
367271593db2Swyllys 	else if (priv_key != NULL && pkey != NULL)
367371593db2Swyllys 		*priv_key = pkey;
367471593db2Swyllys 
367534acef67Swyllys err:
367634acef67Swyllys 	/* Cleanup the stack of X509 info records */
367734acef67Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3678*a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
367934acef67Swyllys 		info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
368034acef67Swyllys 		X509_INFO_free(info);
368134acef67Swyllys 	}
368234acef67Swyllys 	if (x509_info_stack)
368334acef67Swyllys 		sk_X509_INFO_free(x509_info_stack);
368434acef67Swyllys 
36855b3e1433Swyllys 	if (cert_infos != NULL)
36865b3e1433Swyllys 		free(cert_infos);
36875b3e1433Swyllys 
368871593db2Swyllys 	return (rv);
368971593db2Swyllys }
369071593db2Swyllys 
3691*a2d4930dSDan OpenSolaris Anderson 
36925b3e1433Swyllys static KMF_RETURN
36935b3e1433Swyllys openssl_parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
36945b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
36955b3e1433Swyllys {
36965b3e1433Swyllys 	KMF_RETURN ret;
36975b3e1433Swyllys 	int i;
36985b3e1433Swyllys 
36995b3e1433Swyllys 	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
3700*a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
37015b3e1433Swyllys 		PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
37025b3e1433Swyllys 		ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
37035b3e1433Swyllys 		    keys, certs);
37045b3e1433Swyllys 
37055b3e1433Swyllys 		if (ret != KMF_OK)
37065b3e1433Swyllys 			return (ret);
37075b3e1433Swyllys 	}
37085b3e1433Swyllys 
37095b3e1433Swyllys 	return (ret);
37105b3e1433Swyllys }
37115b3e1433Swyllys 
37125b3e1433Swyllys static KMF_RETURN
37135b3e1433Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
37145b3e1433Swyllys {
37155b3e1433Swyllys 	X509_ATTRIBUTE *attr = NULL;
37165b3e1433Swyllys 
37175b3e1433Swyllys 	if (pkey == NULL || attrib == NULL)
37185b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
37195b3e1433Swyllys 
37205b3e1433Swyllys 	if (pkey->attributes == NULL) {
37215b3e1433Swyllys 		pkey->attributes = sk_X509_ATTRIBUTE_new_null();
37225b3e1433Swyllys 		if (pkey->attributes == NULL)
37235b3e1433Swyllys 			return (KMF_ERR_MEMORY);
37245b3e1433Swyllys 	}
37255b3e1433Swyllys 	attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
37265b3e1433Swyllys 	if (attr != NULL) {
37275b3e1433Swyllys 		int i;
37285b3e1433Swyllys 		X509_ATTRIBUTE *a;
37295b3e1433Swyllys 		for (i = 0;
37305b3e1433Swyllys 		    i < sk_X509_ATTRIBUTE_num(pkey->attributes); i++) {
3731*a2d4930dSDan OpenSolaris Anderson 			/* LINTED E_BAD_PTR_CAST_ALIGN */
37325b3e1433Swyllys 			a = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
37335b3e1433Swyllys 			if (OBJ_obj2nid(a->object) == nid) {
37345b3e1433Swyllys 				X509_ATTRIBUTE_free(a);
3735*a2d4930dSDan OpenSolaris Anderson 				/* LINTED E_BAD_PTR_CAST_ALIGN */
37365b3e1433Swyllys 				sk_X509_ATTRIBUTE_set(pkey->attributes,
37375b3e1433Swyllys 				    i, attr);
37385b3e1433Swyllys 				return (KMF_OK);
37395b3e1433Swyllys 			}
37405b3e1433Swyllys 		}
37415b3e1433Swyllys 		if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == NULL) {
37425b3e1433Swyllys 			X509_ATTRIBUTE_free(attr);
37435b3e1433Swyllys 			return (KMF_ERR_MEMORY);
37445b3e1433Swyllys 		}
37455b3e1433Swyllys 	} else {
37465b3e1433Swyllys 		return (KMF_ERR_MEMORY);
37475b3e1433Swyllys 	}
37485b3e1433Swyllys 
37495b3e1433Swyllys 	return (KMF_OK);
37505b3e1433Swyllys }
37515b3e1433Swyllys 
37525b3e1433Swyllys static KMF_RETURN
37535b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
37545b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
37555b3e1433Swyllys {
37565b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
37575b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
37585b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
37595b3e1433Swyllys 	X509 *xcert = NULL;
37605b3e1433Swyllys 	ASN1_TYPE *keyid = NULL;
37615b3e1433Swyllys 	ASN1_TYPE *fname = NULL;
37625b3e1433Swyllys 	uchar_t *data = NULL;
37635b3e1433Swyllys 
37645b3e1433Swyllys 	keyid = PKCS12_get_attr(bag, NID_localKeyID);
37655b3e1433Swyllys 	fname = PKCS12_get_attr(bag, NID_friendlyName);
37665b3e1433Swyllys 
37675b3e1433Swyllys 	switch (M_PKCS12_bag_type(bag)) {
37685b3e1433Swyllys 		case NID_keyBag:
37695b3e1433Swyllys 			if (keylist == NULL)
37705b3e1433Swyllys 				goto end;
37715b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(bag->value.keybag);
37725b3e1433Swyllys 			if (pkey == NULL)
37735b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
37745b3e1433Swyllys 
37755b3e1433Swyllys 			break;
37765b3e1433Swyllys 		case NID_pkcs8ShroudedKeyBag:
37775b3e1433Swyllys 			if (keylist == NULL)
37785b3e1433Swyllys 				goto end;
37795b3e1433Swyllys 			p8 = M_PKCS12_decrypt_skey(bag, pass, passlen);
37805b3e1433Swyllys 			if (p8 == NULL)
37815b3e1433Swyllys 				return (KMF_ERR_AUTH_FAILED);
37825b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(p8);
37835b3e1433Swyllys 			PKCS8_PRIV_KEY_INFO_free(p8);
37845b3e1433Swyllys 			if (pkey == NULL)
37855b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
37865b3e1433Swyllys 			break;
37875b3e1433Swyllys 		case NID_certBag:
37885b3e1433Swyllys 			if (certlist == NULL)
37895b3e1433Swyllys 				goto end;
37905b3e1433Swyllys 			if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate)
37915b3e1433Swyllys 				return (KMF_ERR_PKCS12_FORMAT);
37925b3e1433Swyllys 			xcert = M_PKCS12_certbag2x509(bag);
37935b3e1433Swyllys 			if (xcert == NULL) {
37945b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
37955b3e1433Swyllys 				goto end;
37965b3e1433Swyllys 			}
37975b3e1433Swyllys 			if (keyid != NULL) {
37985b3e1433Swyllys 				if (X509_keyid_set1(xcert,
37995b3e1433Swyllys 				    keyid->value.octet_string->data,
38005b3e1433Swyllys 				    keyid->value.octet_string->length) == 0) {
38015b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
38025b3e1433Swyllys 					goto end;
38035b3e1433Swyllys 				}
38045b3e1433Swyllys 			}
38055b3e1433Swyllys 			if (fname != NULL) {
38065b3e1433Swyllys 				int len, r;
38075b3e1433Swyllys 				len = ASN1_STRING_to_UTF8(&data,
38085b3e1433Swyllys 				    fname->value.asn1_string);
38095b3e1433Swyllys 				if (len > 0 && data != NULL) {
38105b3e1433Swyllys 					r = X509_alias_set1(xcert, data, len);
38115b3e1433Swyllys 					if (r == NULL) {
38125b3e1433Swyllys 						ret = KMF_ERR_PKCS12_FORMAT;
38135b3e1433Swyllys 						goto end;
38145b3e1433Swyllys 					}
38155b3e1433Swyllys 				} else {
38165b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
38175b3e1433Swyllys 					goto end;
38185b3e1433Swyllys 				}
38195b3e1433Swyllys 			}
38205b3e1433Swyllys 			if (sk_X509_push(certlist, xcert) == 0)
38215b3e1433Swyllys 				ret = KMF_ERR_MEMORY;
38225b3e1433Swyllys 			else
38235b3e1433Swyllys 				xcert = NULL;
38245b3e1433Swyllys 			break;
38255b3e1433Swyllys 		case NID_safeContentsBag:
38265b3e1433Swyllys 			return (openssl_parse_bags(bag->value.safes, pass,
38275b3e1433Swyllys 			    keylist, certlist));
38285b3e1433Swyllys 		default:
38295b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
38305b3e1433Swyllys 			break;
38315b3e1433Swyllys 	}
38325b3e1433Swyllys 
38335b3e1433Swyllys 	/*
38345b3e1433Swyllys 	 * Set the ID and/or FriendlyName attributes on the key.
38355b3e1433Swyllys 	 * If converting to PKCS11 objects, these can translate to CKA_ID
38365b3e1433Swyllys 	 * and CKA_LABEL values.
38375b3e1433Swyllys 	 */
38385b3e1433Swyllys 	if (pkey != NULL && ret == KMF_OK) {
38395b3e1433Swyllys 		ASN1_TYPE *attr = NULL;
38405b3e1433Swyllys 		if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
38415b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
38425b3e1433Swyllys 				return (KMF_ERR_MEMORY);
38435b3e1433Swyllys 			attr->value.octet_string =
38445b3e1433Swyllys 			    ASN1_STRING_dup(keyid->value.octet_string);
38455b3e1433Swyllys 			attr->type = V_ASN1_OCTET_STRING;
38465b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.octet_string;
38475b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
38485b3e1433Swyllys 			OPENSSL_free(attr);
38495b3e1433Swyllys 		}
38505b3e1433Swyllys 
38515b3e1433Swyllys 		if (ret == KMF_OK && fname != NULL &&
38525b3e1433Swyllys 		    fname->type == V_ASN1_BMPSTRING) {
38535b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
38545b3e1433Swyllys 				return (KMF_ERR_MEMORY);
38555b3e1433Swyllys 			attr->value.bmpstring =
38565b3e1433Swyllys 			    ASN1_STRING_dup(fname->value.bmpstring);
38575b3e1433Swyllys 			attr->type = V_ASN1_BMPSTRING;
38585b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.bmpstring;
38595b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
38605b3e1433Swyllys 			OPENSSL_free(attr);
38615b3e1433Swyllys 		}
38625b3e1433Swyllys 
38635b3e1433Swyllys 		if (ret == KMF_OK && keylist != NULL &&
38645b3e1433Swyllys 		    sk_EVP_PKEY_push(keylist, pkey) == 0)
38655b3e1433Swyllys 			ret = KMF_ERR_MEMORY;
38665b3e1433Swyllys 	}
38675b3e1433Swyllys 	if (ret == KMF_OK && keylist != NULL)
38685b3e1433Swyllys 		pkey = NULL;
38695b3e1433Swyllys end:
38705b3e1433Swyllys 	if (pkey != NULL)
38715b3e1433Swyllys 		EVP_PKEY_free(pkey);
38725b3e1433Swyllys 	if (xcert != NULL)
38735b3e1433Swyllys 		X509_free(xcert);
38745b3e1433Swyllys 	if (data != NULL)
38755b3e1433Swyllys 		OPENSSL_free(data);
38765b3e1433Swyllys 
38775b3e1433Swyllys 	return (ret);
38785b3e1433Swyllys }
38795b3e1433Swyllys 
38805b3e1433Swyllys static KMF_RETURN
38815b3e1433Swyllys openssl_pkcs12_parse(PKCS12 *p12, char *pin,
38825b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys,
38835b3e1433Swyllys 	STACK_OF(X509) *certs,
38845b3e1433Swyllys 	STACK_OF(X509) *ca)
3885*a2d4930dSDan OpenSolaris Anderson /* ARGSUSED3 */
38865b3e1433Swyllys {
38875b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
38885b3e1433Swyllys 	STACK_OF(PKCS7) *asafes = NULL;
38895b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
38905b3e1433Swyllys 	int i, bagnid;
38915b3e1433Swyllys 	PKCS7 *p7;
38925b3e1433Swyllys 
38935b3e1433Swyllys 	if (p12 == NULL || (keys == NULL && certs == NULL))
38945b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
38955b3e1433Swyllys 
38965b3e1433Swyllys 	if (pin == NULL || *pin == NULL) {
38975b3e1433Swyllys 		if (PKCS12_verify_mac(p12, NULL, 0)) {
38985b3e1433Swyllys 			pin = NULL;
38995b3e1433Swyllys 		} else if (PKCS12_verify_mac(p12, "", 0)) {
39005b3e1433Swyllys 			pin = "";
39015b3e1433Swyllys 		} else {
39025b3e1433Swyllys 			return (KMF_ERR_AUTH_FAILED);
39035b3e1433Swyllys 		}
39045b3e1433Swyllys 	} else if (!PKCS12_verify_mac(p12, pin, -1)) {
39055b3e1433Swyllys 		return (KMF_ERR_AUTH_FAILED);
39065b3e1433Swyllys 	}
39075b3e1433Swyllys 
39085b3e1433Swyllys 	if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
39095b3e1433Swyllys 		return (KMF_ERR_PKCS12_FORMAT);
39105b3e1433Swyllys 
39115b3e1433Swyllys 	for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
39125b3e1433Swyllys 		bags = NULL;
3913*a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
39145b3e1433Swyllys 		p7 = sk_PKCS7_value(asafes, i);
39155b3e1433Swyllys 		bagnid = OBJ_obj2nid(p7->type);
39165b3e1433Swyllys 
39175b3e1433Swyllys 		if (bagnid == NID_pkcs7_data) {
39185b3e1433Swyllys 			bags = PKCS12_unpack_p7data(p7);
39195b3e1433Swyllys 		} else if (bagnid == NID_pkcs7_encrypted) {
39205b3e1433Swyllys 			bags = PKCS12_unpack_p7encdata(p7, pin,
39215b3e1433Swyllys 			    (pin ? strlen(pin) : 0));
39225b3e1433Swyllys 		} else {
39235b3e1433Swyllys 			continue;
39245b3e1433Swyllys 		}
39255b3e1433Swyllys 		if (bags == NULL) {
39265b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39275b3e1433Swyllys 			goto out;
39285b3e1433Swyllys 		}
39295b3e1433Swyllys 
39305b3e1433Swyllys 		if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
39315b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39325b3e1433Swyllys 
39335b3e1433Swyllys 		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
39345b3e1433Swyllys 	}
39355b3e1433Swyllys out:
39365b3e1433Swyllys 	if (asafes != NULL)
39375b3e1433Swyllys 		sk_PKCS7_pop_free(asafes, PKCS7_free);
39385b3e1433Swyllys 
39395b3e1433Swyllys 	return (ret);
39405b3e1433Swyllys }
39415b3e1433Swyllys 
394299ebb4caSwyllys /*
394399ebb4caSwyllys  * Helper function to decrypt and parse PKCS#12 import file.
394499ebb4caSwyllys  */
394599ebb4caSwyllys static KMF_RETURN
394699ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
39475b3e1433Swyllys 	STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs,
39485b3e1433Swyllys 	STACK_OF(X509) **ca)
3949*a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */
395099ebb4caSwyllys {
395199ebb4caSwyllys 	PKCS12			*pk12, *pk12_tmp;
39525b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*pkeylist = NULL;
39535b3e1433Swyllys 	STACK_OF(X509)		*xcertlist = NULL;
39545b3e1433Swyllys 	STACK_OF(X509)		*cacertlist = NULL;
395599ebb4caSwyllys 
395699ebb4caSwyllys 	if ((pk12 = PKCS12_new()) == NULL) {
395799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
395899ebb4caSwyllys 	}
395999ebb4caSwyllys 
396099ebb4caSwyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
396199ebb4caSwyllys 		/* This is ok; it seems to mean there is no more to read. */
396299ebb4caSwyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
396399ebb4caSwyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
396499ebb4caSwyllys 			goto end_extract_pkcs12;
396599ebb4caSwyllys 
396699ebb4caSwyllys 		PKCS12_free(pk12);
396799ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
396899ebb4caSwyllys 	}
396999ebb4caSwyllys 	pk12 = pk12_tmp;
397099ebb4caSwyllys 
39715b3e1433Swyllys 	xcertlist = sk_X509_new_null();
39725b3e1433Swyllys 	if (xcertlist == NULL) {
39735b3e1433Swyllys 		PKCS12_free(pk12);
39745b3e1433Swyllys 		return (KMF_ERR_MEMORY);
39755b3e1433Swyllys 	}
39765b3e1433Swyllys 	pkeylist = sk_EVP_PKEY_new_null();
39775b3e1433Swyllys 	if (pkeylist == NULL) {
39785b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
39795b3e1433Swyllys 		PKCS12_free(pk12);
39805b3e1433Swyllys 		return (KMF_ERR_MEMORY);
39815b3e1433Swyllys 	}
39825b3e1433Swyllys 
39835b3e1433Swyllys 	if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
39845b3e1433Swyllys 	    cacertlist) != KMF_OK) {
39855b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
39865b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
398799ebb4caSwyllys 		PKCS12_free(pk12);
398899ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
398999ebb4caSwyllys 	}
399099ebb4caSwyllys 
39915b3e1433Swyllys 	if (priv_key && pkeylist)
39925b3e1433Swyllys 		*priv_key = pkeylist;
39935b3e1433Swyllys 	else if (pkeylist)
39945b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
39955b3e1433Swyllys 	if (certs && xcertlist)
39965b3e1433Swyllys 		*certs = xcertlist;
39975b3e1433Swyllys 	else if (xcertlist)
39985b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
39995b3e1433Swyllys 	if (ca && cacertlist)
40005b3e1433Swyllys 		*ca = cacertlist;
40015b3e1433Swyllys 	else if (cacertlist)
40025b3e1433Swyllys 		sk_X509_pop_free(cacertlist, X509_free);
400399ebb4caSwyllys 
40045b3e1433Swyllys end_extract_pkcs12:
400599ebb4caSwyllys 
400699ebb4caSwyllys 	PKCS12_free(pk12);
400799ebb4caSwyllys 	return (KMF_OK);
400899ebb4caSwyllys }
400999ebb4caSwyllys 
401099ebb4caSwyllys static KMF_RETURN
401199ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
401299ebb4caSwyllys {
401399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
401499ebb4caSwyllys 	uint32_t sz;
401599ebb4caSwyllys 
401699ebb4caSwyllys 	sz = BN_num_bytes(from);
401799ebb4caSwyllys 	to->val = (uchar_t *)malloc(sz);
401899ebb4caSwyllys 	if (to->val == NULL)
401999ebb4caSwyllys 		return (KMF_ERR_MEMORY);
402099ebb4caSwyllys 
402199ebb4caSwyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
402299ebb4caSwyllys 		free(to->val);
402399ebb4caSwyllys 		to->val = NULL;
402499ebb4caSwyllys 		to->len = 0;
402599ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
402699ebb4caSwyllys 	}
402799ebb4caSwyllys 
402899ebb4caSwyllys 	return (rv);
402999ebb4caSwyllys }
403099ebb4caSwyllys 
403199ebb4caSwyllys static KMF_RETURN
403299ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
403399ebb4caSwyllys {
403499ebb4caSwyllys 	KMF_RETURN rv;
403599ebb4caSwyllys 	KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
403699ebb4caSwyllys 
403799ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
403899ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK)
403999ebb4caSwyllys 		goto cleanup;
404099ebb4caSwyllys 
404199ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK)
404299ebb4caSwyllys 		goto cleanup;
404399ebb4caSwyllys 
404499ebb4caSwyllys 	if (rsa->d != NULL)
404599ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK)
404699ebb4caSwyllys 			goto cleanup;
404799ebb4caSwyllys 
404899ebb4caSwyllys 	if (rsa->p != NULL)
404999ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK)
405099ebb4caSwyllys 			goto cleanup;
405199ebb4caSwyllys 
405299ebb4caSwyllys 	if (rsa->q != NULL)
405399ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK)
405499ebb4caSwyllys 			goto cleanup;
405599ebb4caSwyllys 
405699ebb4caSwyllys 	if (rsa->dmp1 != NULL)
405799ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK)
405899ebb4caSwyllys 			goto cleanup;
405999ebb4caSwyllys 
406099ebb4caSwyllys 	if (rsa->dmq1 != NULL)
406199ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK)
406299ebb4caSwyllys 			goto cleanup;
406399ebb4caSwyllys 
406499ebb4caSwyllys 	if (rsa->iqmp != NULL)
406599ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK)
406699ebb4caSwyllys 			goto cleanup;
406799ebb4caSwyllys cleanup:
406899ebb4caSwyllys 	if (rv != KMF_OK)
406930a5e8faSwyllys 		kmf_free_raw_key(key);
407099ebb4caSwyllys 	else
407199ebb4caSwyllys 		key->keytype = KMF_RSA;
407299ebb4caSwyllys 
407399ebb4caSwyllys 	/*
407499ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
407599ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
407699ebb4caSwyllys 	 */
407799ebb4caSwyllys 	RSA_free(rsa);
407899ebb4caSwyllys 
407999ebb4caSwyllys 	return (rv);
408099ebb4caSwyllys }
408199ebb4caSwyllys 
408299ebb4caSwyllys static KMF_RETURN
408399ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
408499ebb4caSwyllys {
408599ebb4caSwyllys 	KMF_RETURN rv;
408699ebb4caSwyllys 	KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
408799ebb4caSwyllys 
408899ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
408999ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK)
409099ebb4caSwyllys 		goto cleanup;
409199ebb4caSwyllys 
409299ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK)
409399ebb4caSwyllys 		goto cleanup;
409499ebb4caSwyllys 
409599ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK)
409699ebb4caSwyllys 		goto cleanup;
409799ebb4caSwyllys 
409899ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK)
409999ebb4caSwyllys 		goto cleanup;
410099ebb4caSwyllys 
410199ebb4caSwyllys cleanup:
410299ebb4caSwyllys 	if (rv != KMF_OK)
410330a5e8faSwyllys 		kmf_free_raw_key(key);
410499ebb4caSwyllys 	else
410599ebb4caSwyllys 		key->keytype = KMF_DSA;
410699ebb4caSwyllys 
410799ebb4caSwyllys 	/*
410899ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
410999ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
411099ebb4caSwyllys 	 */
411199ebb4caSwyllys 	DSA_free(dsa);
411299ebb4caSwyllys 
411399ebb4caSwyllys 	return (rv);
411499ebb4caSwyllys }
411599ebb4caSwyllys 
411699ebb4caSwyllys static KMF_RETURN
411799ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
41185b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
411999ebb4caSwyllys {
412099ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
41215b3e1433Swyllys 	KMF_X509_DER_CERT *list = (*certlist);
41225b3e1433Swyllys 	KMF_X509_DER_CERT cert;
412399ebb4caSwyllys 	int n = (*ncerts);
412499ebb4caSwyllys 
412599ebb4caSwyllys 	if (list == NULL) {
41265b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
412799ebb4caSwyllys 	} else {
41285b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)realloc(list,
41295b3e1433Swyllys 		    sizeof (KMF_X509_DER_CERT) * (n + 1));
413099ebb4caSwyllys 	}
413199ebb4caSwyllys 
413299ebb4caSwyllys 	if (list == NULL)
413399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
413499ebb4caSwyllys 
41355b3e1433Swyllys 	(void) memset(&cert, 0, sizeof (cert));
41365b3e1433Swyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
413799ebb4caSwyllys 	if (rv == KMF_OK) {
41385b3e1433Swyllys 		int len = 0;
41395b3e1433Swyllys 		/* Get the alias name for the cert if there is one */
41405b3e1433Swyllys 		char *a = (char *)X509_alias_get0(sslcert, &len);
41415b3e1433Swyllys 		if (a != NULL)
41425b3e1433Swyllys 			cert.kmf_private.label = strdup(a);
41435b3e1433Swyllys 		cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
41445b3e1433Swyllys 
414599ebb4caSwyllys 		list[n] = cert;
414699ebb4caSwyllys 		(*ncerts) = n + 1;
414799ebb4caSwyllys 
414899ebb4caSwyllys 		*certlist = list;
414999ebb4caSwyllys 	} else {
415099ebb4caSwyllys 		free(list);
415199ebb4caSwyllys 	}
415299ebb4caSwyllys 
415399ebb4caSwyllys 	return (rv);
415499ebb4caSwyllys }
415599ebb4caSwyllys 
415699ebb4caSwyllys static KMF_RETURN
415799ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
415899ebb4caSwyllys 	KMF_RAW_KEY_DATA *newkey, int *nkeys)
415999ebb4caSwyllys {
416099ebb4caSwyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
416199ebb4caSwyllys 	int n = (*nkeys);
416299ebb4caSwyllys 
416399ebb4caSwyllys 	if (list == NULL) {
416499ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
416599ebb4caSwyllys 	} else {
416699ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
416799ebb4caSwyllys 		    sizeof (KMF_RAW_KEY_DATA) * (n + 1));
416899ebb4caSwyllys 	}
416999ebb4caSwyllys 
417099ebb4caSwyllys 	if (list == NULL)
417199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
417299ebb4caSwyllys 
417399ebb4caSwyllys 	list[n] = *newkey;
417499ebb4caSwyllys 	(*nkeys) = n + 1;
417599ebb4caSwyllys 
417699ebb4caSwyllys 	*keylist = list;
417799ebb4caSwyllys 
417899ebb4caSwyllys 	return (KMF_OK);
417999ebb4caSwyllys }
418099ebb4caSwyllys 
41815b3e1433Swyllys static X509_ATTRIBUTE *
41825b3e1433Swyllys find_attr(STACK_OF(X509_ATTRIBUTE) *attrs, int nid)
41835b3e1433Swyllys {
41845b3e1433Swyllys 	X509_ATTRIBUTE *a;
41855b3e1433Swyllys 	int i;
41865b3e1433Swyllys 
41875b3e1433Swyllys 	if (attrs == NULL)
41885b3e1433Swyllys 		return (NULL);
41895b3e1433Swyllys 
41905b3e1433Swyllys 	for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
4191*a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
41925b3e1433Swyllys 		a = sk_X509_ATTRIBUTE_value(attrs, i);
41935b3e1433Swyllys 		if (OBJ_obj2nid(a->object) == nid)
41945b3e1433Swyllys 			return (a);
41955b3e1433Swyllys 	}
41965b3e1433Swyllys 	return (NULL);
41975b3e1433Swyllys }
41985b3e1433Swyllys 
419930a5e8faSwyllys static KMF_RETURN
420030a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
420130a5e8faSwyllys {
420230a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
42035b3e1433Swyllys 	X509_ATTRIBUTE *attr;
420430a5e8faSwyllys 
420530a5e8faSwyllys 	if (pkey == NULL || key == NULL)
420630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
420730a5e8faSwyllys 	/* Convert SSL key to raw key */
420830a5e8faSwyllys 	switch (pkey->type) {
420930a5e8faSwyllys 		case EVP_PKEY_RSA:
421030a5e8faSwyllys 			rv = exportRawRSAKey(EVP_PKEY_get1_RSA(pkey),
421130a5e8faSwyllys 			    key);
421230a5e8faSwyllys 			if (rv != KMF_OK)
421330a5e8faSwyllys 				return (rv);
421430a5e8faSwyllys 			break;
421530a5e8faSwyllys 		case EVP_PKEY_DSA:
421630a5e8faSwyllys 			rv = exportRawDSAKey(EVP_PKEY_get1_DSA(pkey),
421730a5e8faSwyllys 			    key);
421830a5e8faSwyllys 			if (rv != KMF_OK)
421930a5e8faSwyllys 				return (rv);
422030a5e8faSwyllys 			break;
422130a5e8faSwyllys 		default:
422230a5e8faSwyllys 			return (KMF_ERR_BAD_PARAMETER);
422330a5e8faSwyllys 	}
42245b3e1433Swyllys 	/*
42255b3e1433Swyllys 	 * If friendlyName, add it to record.
42265b3e1433Swyllys 	 */
42275b3e1433Swyllys 	attr = find_attr(pkey->attributes, NID_friendlyName);
42285b3e1433Swyllys 	if (attr != NULL) {
42295b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
42305b3e1433Swyllys 		int numattr = sk_ASN1_TYPE_num(attr->value.set);
42315b3e1433Swyllys 		if (attr->single == 0 && numattr > 0) {
4232*a2d4930dSDan OpenSolaris Anderson 			/* LINTED E_BAD_PTR_CAST_ALIGN */
42335b3e1433Swyllys 			ty = sk_ASN1_TYPE_value(attr->value.set, 0);
42345b3e1433Swyllys 		}
42355b3e1433Swyllys 		if (ty != NULL) {
42365b3e1433Swyllys 			key->label = uni2asc(ty->value.bmpstring->data,
42375b3e1433Swyllys 			    ty->value.bmpstring->length);
42385b3e1433Swyllys 		}
42395b3e1433Swyllys 	} else {
42405b3e1433Swyllys 		key->label = NULL;
42415b3e1433Swyllys 	}
42425b3e1433Swyllys 
42435b3e1433Swyllys 	/*
42445b3e1433Swyllys 	 * If KeyID, add it to record as a KMF_DATA object.
42455b3e1433Swyllys 	 */
42465b3e1433Swyllys 	attr = find_attr(pkey->attributes, NID_localKeyID);
42475b3e1433Swyllys 	if (attr != NULL) {
42485b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
42495b3e1433Swyllys 		int numattr = sk_ASN1_TYPE_num(attr->value.set);
42505b3e1433Swyllys 		if (attr->single == 0 && numattr > 0) {
4251*a2d4930dSDan OpenSolaris Anderson 			/* LINTED E_BAD_PTR_CAST_ALIGN */
42525b3e1433Swyllys 			ty = sk_ASN1_TYPE_value(attr->value.set, 0);
42535b3e1433Swyllys 		}
42545b3e1433Swyllys 		key->id.Data = (uchar_t *)malloc(
42555b3e1433Swyllys 		    ty->value.octet_string->length);
42565b3e1433Swyllys 		if (key->id.Data == NULL)
42575b3e1433Swyllys 			return (KMF_ERR_MEMORY);
42585b3e1433Swyllys 		(void) memcpy(key->id.Data, ty->value.octet_string->data,
42595b3e1433Swyllys 		    ty->value.octet_string->length);
42605b3e1433Swyllys 		key->id.Length = ty->value.octet_string->length;
42615b3e1433Swyllys 	} else {
42625b3e1433Swyllys 		(void) memset(&key->id, 0, sizeof (KMF_DATA));
42635b3e1433Swyllys 	}
426430a5e8faSwyllys 
426530a5e8faSwyllys 	return (rv);
426630a5e8faSwyllys }
426799ebb4caSwyllys 
426899ebb4caSwyllys static KMF_RETURN
426999ebb4caSwyllys convertPK12Objects(
427099ebb4caSwyllys 	KMF_HANDLE *kmfh,
42715b3e1433Swyllys 	STACK_OF(EVP_PKEY) *sslkeys,
42725b3e1433Swyllys 	STACK_OF(X509) *sslcert,
42735b3e1433Swyllys 	STACK_OF(X509) *sslcacerts,
427499ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
42755b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
427699ebb4caSwyllys {
427799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
427899ebb4caSwyllys 	KMF_RAW_KEY_DATA key;
427999ebb4caSwyllys 	int i;
428099ebb4caSwyllys 
42815b3e1433Swyllys 	for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
4282*a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
42835b3e1433Swyllys 		EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
42845b3e1433Swyllys 		rv = convertToRawKey(pkey, &key);
428530a5e8faSwyllys 		if (rv == KMF_OK)
428699ebb4caSwyllys 			rv = add_key_to_list(keylist, &key, nkeys);
428730a5e8faSwyllys 
428899ebb4caSwyllys 		if (rv != KMF_OK)
428999ebb4caSwyllys 			return (rv);
429099ebb4caSwyllys 	}
429199ebb4caSwyllys 
429299ebb4caSwyllys 	/* Now add the certificate to the certlist */
42935b3e1433Swyllys 	for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
4294*a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
42955b3e1433Swyllys 		X509 *cert = sk_X509_value(sslcert, i);
42965b3e1433Swyllys 		rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
429799ebb4caSwyllys 		if (rv != KMF_OK)
429899ebb4caSwyllys 			return (rv);
429999ebb4caSwyllys 	}
430099ebb4caSwyllys 
430199ebb4caSwyllys 	/* Also add any included CA certs to the list */
430271593db2Swyllys 	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
430399ebb4caSwyllys 		X509 *c;
430499ebb4caSwyllys 		/*
430599ebb4caSwyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
430699ebb4caSwyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
430799ebb4caSwyllys 		 * Lint is complaining about the embedded casting, and
430899ebb4caSwyllys 		 * to fix it, you need to fix openssl header files.
430999ebb4caSwyllys 		 */
431099ebb4caSwyllys 		/* LINTED E_BAD_PTR_CAST_ALIGN */
431199ebb4caSwyllys 		c = sk_X509_value(sslcacerts, i);
431299ebb4caSwyllys 
431399ebb4caSwyllys 		/* Now add the ca cert to the certlist */
431499ebb4caSwyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
431599ebb4caSwyllys 		if (rv != KMF_OK)
431699ebb4caSwyllys 			return (rv);
431799ebb4caSwyllys 	}
431899ebb4caSwyllys 	return (rv);
431999ebb4caSwyllys }
432099ebb4caSwyllys 
432199ebb4caSwyllys KMF_RETURN
432230a5e8faSwyllys openssl_import_objects(KMF_HANDLE *kmfh,
432399ebb4caSwyllys 	char *filename, KMF_CREDENTIAL *cred,
43245b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts,
432599ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
432699ebb4caSwyllys {
432799ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
432830a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
432930a5e8faSwyllys 	BIO		*bio = NULL;
43305b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*privkeys = NULL;
43315b3e1433Swyllys 	STACK_OF(X509)		*certs = NULL;
433299ebb4caSwyllys 	STACK_OF(X509)		*cacerts = NULL;
433399ebb4caSwyllys 
433430a5e8faSwyllys 	/*
433530a5e8faSwyllys 	 * auto-detect the file format, regardless of what
433630a5e8faSwyllys 	 * the 'format' parameters in the params say.
433730a5e8faSwyllys 	 */
433830a5e8faSwyllys 	rv = kmf_get_file_format(filename, &format);
433930a5e8faSwyllys 	if (rv != KMF_OK) {
434030a5e8faSwyllys 		return (rv);
434130a5e8faSwyllys 	}
434230a5e8faSwyllys 
434330a5e8faSwyllys 	/* This function only works for PEM or PKCS#12 files */
434430a5e8faSwyllys 	if (format != KMF_FORMAT_PEM &&
434530a5e8faSwyllys 	    format != KMF_FORMAT_PEM_KEYPAIR &&
434630a5e8faSwyllys 	    format != KMF_FORMAT_PKCS12)
434730a5e8faSwyllys 		return (KMF_ERR_ENCODING);
434830a5e8faSwyllys 
434930a5e8faSwyllys 	*certlist = NULL;
435030a5e8faSwyllys 	*keylist = NULL;
435130a5e8faSwyllys 	*ncerts = 0;
435230a5e8faSwyllys 	*nkeys = 0;
435330a5e8faSwyllys 
435430a5e8faSwyllys 	if (format == KMF_FORMAT_PKCS12) {
435599ebb4caSwyllys 		bio = BIO_new_file(filename, "rb");
435699ebb4caSwyllys 		if (bio == NULL) {
435799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
435899ebb4caSwyllys 			rv = KMF_ERR_OPEN_FILE;
435999ebb4caSwyllys 			goto end;
436099ebb4caSwyllys 		}
436199ebb4caSwyllys 
436234acef67Swyllys 		rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
43635b3e1433Swyllys 		    (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
436499ebb4caSwyllys 
436599ebb4caSwyllys 		if (rv  == KMF_OK)
436699ebb4caSwyllys 			/* Convert keys and certs to exportable format */
43675b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
436899ebb4caSwyllys 			    keylist, nkeys, certlist, ncerts);
436930a5e8faSwyllys 	} else {
43705b3e1433Swyllys 		EVP_PKEY *pkey;
43715b3e1433Swyllys 		KMF_DATA *certdata = NULL;
43725b3e1433Swyllys 		KMF_X509_DER_CERT *kmfcerts = NULL;
43735b3e1433Swyllys 		int i;
437430a5e8faSwyllys 		rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
437534acef67Swyllys 		    (uchar_t *)cred->cred, (uint32_t)cred->credlen,
43765b3e1433Swyllys 		    &pkey, &certdata, ncerts);
437771593db2Swyllys 
437871593db2Swyllys 		/* Reached end of import file? */
43795b3e1433Swyllys 		if (rv == KMF_OK && pkey != NULL) {
43805b3e1433Swyllys 			privkeys = sk_EVP_PKEY_new_null();
43815b3e1433Swyllys 			if (privkeys == NULL) {
43825b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
43835b3e1433Swyllys 				goto end;
43845b3e1433Swyllys 			}
43855b3e1433Swyllys 			(void) sk_EVP_PKEY_push(privkeys, pkey);
43865b3e1433Swyllys 			/* convert the certificate list here */
43875b3e1433Swyllys 			if (*ncerts > 0 && certlist != NULL) {
43885b3e1433Swyllys 				kmfcerts = (KMF_X509_DER_CERT *)malloc(*ncerts *
43895b3e1433Swyllys 				    sizeof (KMF_X509_DER_CERT));
43905b3e1433Swyllys 				if (kmfcerts == NULL) {
43915b3e1433Swyllys 					rv = KMF_ERR_MEMORY;
43925b3e1433Swyllys 					goto end;
43935b3e1433Swyllys 				}
43945b3e1433Swyllys 				(void) memset(kmfcerts, 0, *ncerts *
43955b3e1433Swyllys 				    sizeof (KMF_X509_DER_CERT));
43965b3e1433Swyllys 				for (i = 0; i < *ncerts; i++) {
43975b3e1433Swyllys 					kmfcerts[i].certificate = certdata[i];
43985b3e1433Swyllys 					kmfcerts[i].kmf_private.keystore_type =
43995b3e1433Swyllys 					    KMF_KEYSTORE_OPENSSL;
44005b3e1433Swyllys 				}
44015b3e1433Swyllys 				*certlist = kmfcerts;
44025b3e1433Swyllys 			}
44035b3e1433Swyllys 			/*
44045b3e1433Swyllys 			 * Convert keys to exportable format, the certs
44055b3e1433Swyllys 			 * are already OK.
44065b3e1433Swyllys 			 */
44075b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
440871593db2Swyllys 			    keylist, nkeys, NULL, NULL);
440930a5e8faSwyllys 		}
44105b3e1433Swyllys 	}
441171593db2Swyllys end:
441230a5e8faSwyllys 	if (bio != NULL)
441399ebb4caSwyllys 		(void) BIO_free(bio);
441499ebb4caSwyllys 
44155b3e1433Swyllys 	if (privkeys)
44165b3e1433Swyllys 		sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
44175b3e1433Swyllys 	if (certs)
44185b3e1433Swyllys 		sk_X509_pop_free(certs, X509_free);
441930a5e8faSwyllys 	if (cacerts)
44205b3e1433Swyllys 		sk_X509_pop_free(cacerts, X509_free);
442130a5e8faSwyllys 
442299ebb4caSwyllys 	return (rv);
442399ebb4caSwyllys }
442499ebb4caSwyllys 
442599ebb4caSwyllys static KMF_RETURN
442699ebb4caSwyllys create_deskey(DES_cblock **deskey)
442799ebb4caSwyllys {
442899ebb4caSwyllys 	DES_cblock *key;
442999ebb4caSwyllys 
443099ebb4caSwyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
443199ebb4caSwyllys 	if (key == NULL) {
443299ebb4caSwyllys 		return (KMF_ERR_MEMORY);
443399ebb4caSwyllys 	}
443499ebb4caSwyllys 
443599ebb4caSwyllys 	if (DES_random_key(key) == 0) {
443699ebb4caSwyllys 		free(key);
443799ebb4caSwyllys 		return (KMF_ERR_KEYGEN_FAILED);
443899ebb4caSwyllys 	}
443999ebb4caSwyllys 
444099ebb4caSwyllys 	*deskey = key;
444199ebb4caSwyllys 	return (KMF_OK);
444299ebb4caSwyllys }
444399ebb4caSwyllys 
444499ebb4caSwyllys #define	KEYGEN_RETRY 3
444599ebb4caSwyllys #define	DES3_KEY_SIZE 24
444699ebb4caSwyllys 
444799ebb4caSwyllys static KMF_RETURN
444899ebb4caSwyllys create_des3key(unsigned char **des3key)
444999ebb4caSwyllys {
445099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
445199ebb4caSwyllys 	DES_cblock *deskey1 = NULL;
445299ebb4caSwyllys 	DES_cblock *deskey2 = NULL;
445399ebb4caSwyllys 	DES_cblock *deskey3 = NULL;
445499ebb4caSwyllys 	unsigned char *newkey = NULL;
445599ebb4caSwyllys 	int retry;
445699ebb4caSwyllys 
445799ebb4caSwyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
445899ebb4caSwyllys 		return (KMF_ERR_MEMORY);
445999ebb4caSwyllys 	}
446099ebb4caSwyllys 
446199ebb4caSwyllys 	/* create the 1st DES key */
446299ebb4caSwyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
446399ebb4caSwyllys 		goto out;
446499ebb4caSwyllys 	}
446599ebb4caSwyllys 
446699ebb4caSwyllys 	/*
446799ebb4caSwyllys 	 * Create the 2nd DES key and make sure its value is different
446899ebb4caSwyllys 	 * from the 1st DES key.
446999ebb4caSwyllys 	 */
447099ebb4caSwyllys 	retry = 0;
447199ebb4caSwyllys 	do {
447299ebb4caSwyllys 		if (deskey2 != NULL) {
447399ebb4caSwyllys 			free(deskey2);
447499ebb4caSwyllys 			deskey2 = NULL;
447599ebb4caSwyllys 		}
447699ebb4caSwyllys 
447799ebb4caSwyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
447899ebb4caSwyllys 			goto out;
447999ebb4caSwyllys 		}
448099ebb4caSwyllys 
448199ebb4caSwyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
448299ebb4caSwyllys 		    == 0) {
448399ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
448499ebb4caSwyllys 			retry++;
448599ebb4caSwyllys 		}
448699ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
448799ebb4caSwyllys 
448899ebb4caSwyllys 	if (ret != KMF_OK) {
448999ebb4caSwyllys 		goto out;
449099ebb4caSwyllys 	}
449199ebb4caSwyllys 
449299ebb4caSwyllys 	/*
449399ebb4caSwyllys 	 * Create the 3rd DES key and make sure its value is different
449499ebb4caSwyllys 	 * from the 2nd DES key.
449599ebb4caSwyllys 	 */
449699ebb4caSwyllys 	retry = 0;
449799ebb4caSwyllys 	do {
449899ebb4caSwyllys 		if (deskey3 != NULL) {
449999ebb4caSwyllys 			free(deskey3);
450099ebb4caSwyllys 			deskey3 = NULL;
450199ebb4caSwyllys 		}
450299ebb4caSwyllys 
450399ebb4caSwyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
450499ebb4caSwyllys 			goto out;
450599ebb4caSwyllys 		}
450699ebb4caSwyllys 
450799ebb4caSwyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
450899ebb4caSwyllys 		    == 0) {
450999ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
451099ebb4caSwyllys 			retry++;
451199ebb4caSwyllys 		}
451299ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
451399ebb4caSwyllys 
451499ebb4caSwyllys 	if (ret != KMF_OK) {
451599ebb4caSwyllys 		goto out;
451699ebb4caSwyllys 	}
451799ebb4caSwyllys 
451899ebb4caSwyllys 	/* Concatenate 3 DES keys into a DES3 key */
451999ebb4caSwyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
452099ebb4caSwyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
452199ebb4caSwyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
452299ebb4caSwyllys 	*des3key = newkey;
452399ebb4caSwyllys 
452499ebb4caSwyllys out:
452599ebb4caSwyllys 	if (deskey1 != NULL)
452699ebb4caSwyllys 		free(deskey1);
452799ebb4caSwyllys 
452899ebb4caSwyllys 	if (deskey2 != NULL)
452999ebb4caSwyllys 		free(deskey2);
453099ebb4caSwyllys 
453199ebb4caSwyllys 	if (deskey3 != NULL)
453299ebb4caSwyllys 		free(deskey3);
453399ebb4caSwyllys 
453499ebb4caSwyllys 	if (ret != KMF_OK && newkey != NULL)
453599ebb4caSwyllys 		free(newkey);
453699ebb4caSwyllys 
453799ebb4caSwyllys 	return (ret);
453899ebb4caSwyllys }
453999ebb4caSwyllys 
454099ebb4caSwyllys KMF_RETURN
454130a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
454230a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
454399ebb4caSwyllys {
454499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
454599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
454699ebb4caSwyllys 	char *fullpath = NULL;
454799ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
454899ebb4caSwyllys 	DES_cblock *deskey = NULL;
454999ebb4caSwyllys 	unsigned char *des3key = NULL;
455099ebb4caSwyllys 	unsigned char *random = NULL;
455199ebb4caSwyllys 	int fd = -1;
455230a5e8faSwyllys 	KMF_KEY_HANDLE *symkey;
455330a5e8faSwyllys 	KMF_KEY_ALG keytype;
455430a5e8faSwyllys 	uint32_t keylen;
455530a5e8faSwyllys 	uint32_t keylen_size = sizeof (keylen);
455630a5e8faSwyllys 	char *dirpath;
455730a5e8faSwyllys 	char *keyfile;
455899ebb4caSwyllys 
455999ebb4caSwyllys 	if (kmfh == NULL)
456099ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
456199ebb4caSwyllys 
456230a5e8faSwyllys 	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
456330a5e8faSwyllys 	if (symkey == NULL)
456499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
456599ebb4caSwyllys 
456630a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
456730a5e8faSwyllys 
456830a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
456930a5e8faSwyllys 	if (keyfile == NULL)
457030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
457130a5e8faSwyllys 
457230a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
457330a5e8faSwyllys 	    (void *)&keytype, NULL);
457430a5e8faSwyllys 	if (ret != KMF_OK)
457530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
457630a5e8faSwyllys 
457730a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
457830a5e8faSwyllys 	    &keylen, &keylen_size);
457930a5e8faSwyllys 	if (ret == KMF_ERR_ATTR_NOT_FOUND &&
458030a5e8faSwyllys 	    (keytype == KMF_DES || keytype == KMF_DES3))
458130a5e8faSwyllys 		/* keylength is not required for DES and 3DES */
458230a5e8faSwyllys 		ret = KMF_OK;
458330a5e8faSwyllys 	if (ret != KMF_OK)
458430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
458530a5e8faSwyllys 
458630a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
458799ebb4caSwyllys 	if (fullpath == NULL)
458899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
458999ebb4caSwyllys 
459099ebb4caSwyllys 	/* If the requested file exists, return an error */
459130a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
459299ebb4caSwyllys 		free(fullpath);
459399ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
459499ebb4caSwyllys 	}
459599ebb4caSwyllys 
459699ebb4caSwyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
459799ebb4caSwyllys 	if (fd == -1) {
459899ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
459999ebb4caSwyllys 		goto out;
460099ebb4caSwyllys 	}
460199ebb4caSwyllys 
460299ebb4caSwyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
460399ebb4caSwyllys 	if (rkey == NULL) {
460499ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
460599ebb4caSwyllys 		goto out;
460699ebb4caSwyllys 	}
460799ebb4caSwyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
460899ebb4caSwyllys 
460930a5e8faSwyllys 	if (keytype == KMF_DES) {
461099ebb4caSwyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
461199ebb4caSwyllys 			goto out;
461299ebb4caSwyllys 		}
461399ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)deskey;
461499ebb4caSwyllys 		rkey->keydata.len = 8;
461599ebb4caSwyllys 
461699ebb4caSwyllys 		symkey->keyalg = KMF_DES;
461799ebb4caSwyllys 
461830a5e8faSwyllys 	} else if (keytype == KMF_DES3) {
461999ebb4caSwyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
462099ebb4caSwyllys 			goto out;
462199ebb4caSwyllys 		}
462299ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)des3key;
462399ebb4caSwyllys 		rkey->keydata.len = DES3_KEY_SIZE;
462499ebb4caSwyllys 		symkey->keyalg = KMF_DES3;
46259b37d296Swyllys 
462630a5e8faSwyllys 	} else if (keytype == KMF_AES || keytype == KMF_RC4 ||
462730a5e8faSwyllys 	    keytype == KMF_GENERIC_SECRET) {
462899ebb4caSwyllys 		int bytes;
462999ebb4caSwyllys 
463030a5e8faSwyllys 		if (keylen % 8 != 0) {
463199ebb4caSwyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
463299ebb4caSwyllys 			goto out;
463399ebb4caSwyllys 		}
463499ebb4caSwyllys 
463530a5e8faSwyllys 		if (keytype == KMF_AES) {
463630a5e8faSwyllys 			if (keylen != 128 &&
463730a5e8faSwyllys 			    keylen != 192 &&
463830a5e8faSwyllys 			    keylen != 256) {
463999ebb4caSwyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
464099ebb4caSwyllys 				goto out;
464199ebb4caSwyllys 			}
464299ebb4caSwyllys 		}
464399ebb4caSwyllys 
464430a5e8faSwyllys 		bytes = keylen/8;
464599ebb4caSwyllys 		random = malloc(bytes);
464699ebb4caSwyllys 		if (random == NULL) {
464799ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
464899ebb4caSwyllys 			goto out;
464999ebb4caSwyllys 		}
465099ebb4caSwyllys 		if (RAND_bytes(random, bytes) != 1) {
465199ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
465299ebb4caSwyllys 			goto out;
465399ebb4caSwyllys 		}
465499ebb4caSwyllys 
465599ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)random;
465699ebb4caSwyllys 		rkey->keydata.len = bytes;
465730a5e8faSwyllys 		symkey->keyalg = keytype;
465899ebb4caSwyllys 
465999ebb4caSwyllys 	} else {
466099ebb4caSwyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
466199ebb4caSwyllys 		goto out;
466299ebb4caSwyllys 	}
466399ebb4caSwyllys 
466499ebb4caSwyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
466599ebb4caSwyllys 
466699ebb4caSwyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
466799ebb4caSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
466899ebb4caSwyllys 	symkey->keylabel = (char *)fullpath;
466999ebb4caSwyllys 	symkey->israw = TRUE;
467099ebb4caSwyllys 	symkey->keyp = rkey;
467199ebb4caSwyllys 
467299ebb4caSwyllys out:
467399ebb4caSwyllys 	if (fd != -1)
467499ebb4caSwyllys 		(void) close(fd);
467599ebb4caSwyllys 
467699ebb4caSwyllys 	if (ret != KMF_OK && fullpath != NULL) {
467799ebb4caSwyllys 		free(fullpath);
467899ebb4caSwyllys 	}
467999ebb4caSwyllys 	if (ret != KMF_OK) {
468030a5e8faSwyllys 		kmf_free_raw_sym_key(rkey);
468199ebb4caSwyllys 		symkey->keyp = NULL;
468299ebb4caSwyllys 		symkey->keyalg = KMF_KEYALG_NONE;
468399ebb4caSwyllys 	}
468499ebb4caSwyllys 
468599ebb4caSwyllys 	return (ret);
468699ebb4caSwyllys }
468799ebb4caSwyllys 
468899ebb4caSwyllys /*
468999ebb4caSwyllys  * Check a file to see if it is a CRL file with PEM or DER format.
469099ebb4caSwyllys  * If success, return its format in the "pformat" argument.
469199ebb4caSwyllys  */
469299ebb4caSwyllys KMF_RETURN
469399ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
469499ebb4caSwyllys {
469599ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
469699ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
469799ebb4caSwyllys 	BIO		*bio = NULL;
469899ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
469999ebb4caSwyllys 
470099ebb4caSwyllys 	if (filename == NULL) {
470199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
470299ebb4caSwyllys 	}
470399ebb4caSwyllys 
470499ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
470599ebb4caSwyllys 	if (bio == NULL)	{
470699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
470799ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
470899ebb4caSwyllys 		goto out;
470999ebb4caSwyllys 	}
471099ebb4caSwyllys 
471199ebb4caSwyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
471299ebb4caSwyllys 		*pformat = KMF_FORMAT_PEM;
471399ebb4caSwyllys 		goto out;
471499ebb4caSwyllys 	}
471599ebb4caSwyllys 	(void) BIO_free(bio);
471699ebb4caSwyllys 
471799ebb4caSwyllys 	/*
471899ebb4caSwyllys 	 * Now try to read it as raw DER data.
471999ebb4caSwyllys 	 */
472099ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
472199ebb4caSwyllys 	if (bio == NULL)	{
472299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
472399ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
472499ebb4caSwyllys 		goto out;
472599ebb4caSwyllys 	}
472699ebb4caSwyllys 
472799ebb4caSwyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
472899ebb4caSwyllys 		*pformat = KMF_FORMAT_ASN1;
472999ebb4caSwyllys 	} else {
473099ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
473199ebb4caSwyllys 	}
473299ebb4caSwyllys 
473399ebb4caSwyllys out:
473499ebb4caSwyllys 	if (bio != NULL)
473599ebb4caSwyllys 		(void) BIO_free(bio);
473699ebb4caSwyllys 
473799ebb4caSwyllys 	if (xcrl != NULL)
473899ebb4caSwyllys 		X509_CRL_free(xcrl);
473999ebb4caSwyllys 
474099ebb4caSwyllys 	return (ret);
474199ebb4caSwyllys }
474299ebb4caSwyllys 
474399ebb4caSwyllys KMF_RETURN
474499ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
474599ebb4caSwyllys     KMF_RAW_SYM_KEY *rkey)
474699ebb4caSwyllys {
474799ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
474899ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
474999ebb4caSwyllys 	KMF_DATA	keyvalue;
475099ebb4caSwyllys 
475199ebb4caSwyllys 	if (kmfh == NULL)
475299ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
475399ebb4caSwyllys 
475499ebb4caSwyllys 	if (symkey == NULL || rkey == NULL)
475599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
475699ebb4caSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
475799ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
475899ebb4caSwyllys 
475999ebb4caSwyllys 	if (symkey->israw) {
476099ebb4caSwyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
476199ebb4caSwyllys 
476299ebb4caSwyllys 		if (rawkey == NULL ||
476399ebb4caSwyllys 		    rawkey->keydata.val == NULL ||
476499ebb4caSwyllys 		    rawkey->keydata.len == 0)
476599ebb4caSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
476699ebb4caSwyllys 
476799ebb4caSwyllys 		rkey->keydata.len = rawkey->keydata.len;
476899ebb4caSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
476999ebb4caSwyllys 			return (KMF_ERR_MEMORY);
477099ebb4caSwyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
477199ebb4caSwyllys 		    rkey->keydata.len);
477299ebb4caSwyllys 	} else {
477330a5e8faSwyllys 		rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
477499ebb4caSwyllys 		if (rv != KMF_OK)
477599ebb4caSwyllys 			return (rv);
477699ebb4caSwyllys 		rkey->keydata.len = keyvalue.Length;
477799ebb4caSwyllys 		rkey->keydata.val = keyvalue.Data;
477899ebb4caSwyllys 	}
477999ebb4caSwyllys 
478099ebb4caSwyllys 	return (rv);
478199ebb4caSwyllys }
478202744e81Swyllys 
478302744e81Swyllys /*
478402744e81Swyllys  * id-sha1    OBJECT IDENTIFIER ::= {
478502744e81Swyllys  *     iso(1) identified-organization(3) oiw(14) secsig(3)
478602744e81Swyllys  *     algorithms(2) 26
478702744e81Swyllys  * }
478802744e81Swyllys  */
478902744e81Swyllys #define	ASN1_SHA1_OID_PREFIX_LEN 15
479002744e81Swyllys static uchar_t SHA1_DER_PREFIX[ASN1_SHA1_OID_PREFIX_LEN] = {
479102744e81Swyllys 	0x30, 0x21, 0x30, 0x09,
479202744e81Swyllys 	0x06, 0x05, 0x2b, 0x0e,
479302744e81Swyllys 	0x03, 0x02, 0x1a, 0x05,
479402744e81Swyllys 	0x00, 0x04, 0x14
479502744e81Swyllys };
479602744e81Swyllys 
479702744e81Swyllys /*
479802744e81Swyllys  * id-md2 OBJECT IDENTIFIER ::= {
479902744e81Swyllys  *     iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2
480002744e81Swyllys  * }
480102744e81Swyllys  */
480202744e81Swyllys #define	ASN1_MD2_OID_PREFIX_LEN 18
480302744e81Swyllys static uchar_t MD2_DER_PREFIX[ASN1_MD2_OID_PREFIX_LEN] = {
480402744e81Swyllys 	0x30, 0x20, 0x30, 0x0c,
480502744e81Swyllys 	0x06, 0x08, 0x2a, 0x86,
480602744e81Swyllys 	0x48, 0x86, 0xf7, 0x0d,
480702744e81Swyllys 	0x02, 0x02, 0x05, 0x00,
480802744e81Swyllys 	0x04, 0x10
480902744e81Swyllys };
481002744e81Swyllys 
481102744e81Swyllys /*
481202744e81Swyllys  * id-md5 OBJECT IDENTIFIER ::= {
481302744e81Swyllys  *     iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5
481402744e81Swyllys  * }
481502744e81Swyllys  */
481602744e81Swyllys #define	ASN1_MD5_OID_PREFIX_LEN 18
481702744e81Swyllys static uchar_t MD5_DER_PREFIX[ASN1_MD5_OID_PREFIX_LEN] = {
481802744e81Swyllys 	0x30, 0x20, 0x30, 0x0c,
481902744e81Swyllys 	0x06, 0x08, 0x2a, 0x86,
482002744e81Swyllys 	0x48, 0x86, 0xf7, 0x0d,
482102744e81Swyllys 	0x02, 0x05, 0x05, 0x00,
482202744e81Swyllys 	0x04, 0x10
482302744e81Swyllys };
482402744e81Swyllys 
482502744e81Swyllys KMF_RETURN
482602744e81Swyllys OpenSSL_VerifyDataWithCert(KMF_HANDLE_T handle,
482702744e81Swyllys 	KMF_ALGORITHM_INDEX algid, KMF_DATA *indata,
482802744e81Swyllys 	KMF_DATA *insig, KMF_DATA *cert)
482902744e81Swyllys {
483002744e81Swyllys 	KMF_RETURN ret = KMF_OK;
483102744e81Swyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
483202744e81Swyllys 	X509	*xcert = NULL;
483302744e81Swyllys 	EVP_PKEY *pkey = NULL;
483402744e81Swyllys 	uchar_t *p;
483502744e81Swyllys 	uchar_t *rsaout = NULL;
483602744e81Swyllys 	uchar_t *pfx = NULL;
483702744e81Swyllys 	const EVP_MD *md;
483802744e81Swyllys 	int pfxlen = 0, len;
483902744e81Swyllys 
484002744e81Swyllys 	if (handle == NULL || indata == NULL ||
484102744e81Swyllys 	    indata->Data == NULL || indata->Length == 0 ||
484202744e81Swyllys 	    insig == NULL|| insig->Data == NULL || insig->Length == 0 ||
484302744e81Swyllys 	    cert == NULL || cert->Data == NULL || cert->Length == 0)
484402744e81Swyllys 		return (KMF_ERR_BAD_PARAMETER);
484502744e81Swyllys 
484602744e81Swyllys 	p = cert->Data;
484702744e81Swyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, cert->Length);
484802744e81Swyllys 	if (xcert == NULL) {
484902744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
485002744e81Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
485102744e81Swyllys 		goto cleanup;
485202744e81Swyllys 	}
485302744e81Swyllys 
485402744e81Swyllys 	pkey = X509_get_pubkey(xcert);
485530a5e8faSwyllys 	if (pkey == NULL) {
485602744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
485702744e81Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
485802744e81Swyllys 		goto cleanup;
485902744e81Swyllys 	}
486002744e81Swyllys 
486102744e81Swyllys 	if (algid != KMF_ALGID_NONE) {
486202744e81Swyllys 		switch (algid) {
486302744e81Swyllys 			case KMF_ALGID_MD5WithRSA:
486402744e81Swyllys 				md = EVP_md5();
486502744e81Swyllys 				break;
486602744e81Swyllys 			case KMF_ALGID_MD2WithRSA:
486702744e81Swyllys 				md = EVP_md2();
486802744e81Swyllys 				break;
486902744e81Swyllys 			case KMF_ALGID_SHA1WithRSA:
487002744e81Swyllys 				md = EVP_sha1();
487102744e81Swyllys 				break;
487202744e81Swyllys 			case KMF_ALGID_RSA:
487302744e81Swyllys 				md = NULL;
487402744e81Swyllys 				break;
487502744e81Swyllys 			default:
487602744e81Swyllys 				ret = KMF_ERR_BAD_PARAMETER;
487702744e81Swyllys 				goto cleanup;
487802744e81Swyllys 		}
487902744e81Swyllys 	} else {
488002744e81Swyllys 		/* Get the hash type from the cert signature */
488102744e81Swyllys 		md = EVP_get_digestbyobj(xcert->sig_alg->algorithm);
488202744e81Swyllys 		if (md == NULL) {
488302744e81Swyllys 			SET_ERROR(kmfh, ERR_get_error());
488402744e81Swyllys 			ret = KMF_ERR_BAD_PARAMETER;
488502744e81Swyllys 			goto cleanup;
488602744e81Swyllys 		}
488702744e81Swyllys 	}
48889b37d296Swyllys 	if (md != NULL) {
488902744e81Swyllys 		switch (EVP_MD_type(md)) {
489002744e81Swyllys 		case NID_md2:
489102744e81Swyllys 		case NID_md2WithRSAEncryption:
489202744e81Swyllys 			pfxlen = ASN1_MD2_OID_PREFIX_LEN;
489302744e81Swyllys 			pfx = MD2_DER_PREFIX;
489402744e81Swyllys 			break;
489502744e81Swyllys 		case NID_md5:
489602744e81Swyllys 		case NID_md5WithRSAEncryption:
489702744e81Swyllys 			pfxlen = ASN1_MD5_OID_PREFIX_LEN;
489802744e81Swyllys 			pfx = MD5_DER_PREFIX;
489902744e81Swyllys 			break;
490002744e81Swyllys 		case NID_sha1:
490102744e81Swyllys 		case NID_sha1WithRSAEncryption:
490202744e81Swyllys 			pfxlen = ASN1_SHA1_OID_PREFIX_LEN;
490302744e81Swyllys 			pfx = SHA1_DER_PREFIX;
490402744e81Swyllys 			break;
490502744e81Swyllys 		default: /* Unsupported */
490602744e81Swyllys 			pfxlen = 0;
490702744e81Swyllys 			pfx = NULL;
490802744e81Swyllys 			break;
490902744e81Swyllys 		}
49109b37d296Swyllys 	}
491102744e81Swyllys 
491202744e81Swyllys 	/* RSA with no hash is a special case */
491302744e81Swyllys 	rsaout = malloc(RSA_size(pkey->pkey.rsa));
491402744e81Swyllys 	if (rsaout == NULL)
491502744e81Swyllys 		return (KMF_ERR_MEMORY);
491602744e81Swyllys 
491702744e81Swyllys 	/* Decrypt the input signature */
491802744e81Swyllys 	len = RSA_public_decrypt(insig->Length,
491902744e81Swyllys 	    insig->Data, rsaout, pkey->pkey.rsa, RSA_PKCS1_PADDING);
492002744e81Swyllys 	if (len < 1) {
492102744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
492202744e81Swyllys 		ret = KMF_ERR_BAD_PARAMETER;
492302744e81Swyllys 	} else {
492402744e81Swyllys 		size_t hashlen = 0;
492502744e81Swyllys 		uint32_t dlen;
492602744e81Swyllys 		char *digest = NULL;
492702744e81Swyllys 
492802744e81Swyllys 		/*
492902744e81Swyllys 		 * If the AlgId requires it, hash the input data before
493002744e81Swyllys 		 * comparing it to the decrypted signature.
493102744e81Swyllys 		 */
493202744e81Swyllys 		if (md) {
493302744e81Swyllys 			EVP_MD_CTX ctx;
493402744e81Swyllys 
493502744e81Swyllys 			hashlen = md->md_size;
493602744e81Swyllys 
493702744e81Swyllys 			digest = malloc(hashlen + pfxlen);
493802744e81Swyllys 			if (digest == NULL)
493902744e81Swyllys 				return (KMF_ERR_MEMORY);
494002744e81Swyllys 			/* Add the prefix to the comparison buffer. */
494102744e81Swyllys 			if (pfx && pfxlen > 0) {
494202744e81Swyllys 				(void) memcpy(digest, pfx, pfxlen);
494302744e81Swyllys 			}
494402744e81Swyllys 			(void) EVP_DigestInit(&ctx, md);
494502744e81Swyllys 			(void) EVP_DigestUpdate(&ctx, indata->Data,
494602744e81Swyllys 			    indata->Length);
494702744e81Swyllys 
494802744e81Swyllys 			/* Add the digest AFTER the ASN1 prefix */
494902744e81Swyllys 			(void) EVP_DigestFinal(&ctx,
495002744e81Swyllys 			    (uchar_t *)digest + pfxlen, &dlen);
495102744e81Swyllys 
495202744e81Swyllys 			dlen += pfxlen;
495302744e81Swyllys 		} else {
495402744e81Swyllys 			digest = (char *)indata->Data;
495502744e81Swyllys 			dlen = indata->Length;
495602744e81Swyllys 		}
495702744e81Swyllys 
495802744e81Swyllys 		/*
495902744e81Swyllys 		 * The result of the RSA decryption should be ASN1(OID | Hash).
496002744e81Swyllys 		 * Compare the output hash to the input data for the final
496102744e81Swyllys 		 * result.
496202744e81Swyllys 		 */
496302744e81Swyllys 		if (memcmp(rsaout, digest, dlen))
496402744e81Swyllys 			ret = KMF_ERR_INTERNAL;
496502744e81Swyllys 		else
496602744e81Swyllys 			ret = KMF_OK;
496702744e81Swyllys 
496802744e81Swyllys 		/* If we had to allocate space for the digest, free it now */
496902744e81Swyllys 		if (hashlen)
497002744e81Swyllys 			free(digest);
497102744e81Swyllys 	}
497202744e81Swyllys cleanup:
497302744e81Swyllys 	if (pkey)
497402744e81Swyllys 		EVP_PKEY_free(pkey);
497502744e81Swyllys 
497602744e81Swyllys 	if (xcert)
497702744e81Swyllys 		X509_free(xcert);
497802744e81Swyllys 
497902744e81Swyllys 	if (rsaout)
498002744e81Swyllys 		free(rsaout);
498102744e81Swyllys 
498202744e81Swyllys 	return (ret);
498302744e81Swyllys }
498430a5e8faSwyllys 
498530a5e8faSwyllys /*
498630a5e8faSwyllys  * substitute for the unsafe access(2) function.
498730a5e8faSwyllys  * If the file in question already exists, return 1.
498830a5e8faSwyllys  * else 0.  If an error occurs during testing (other
498930a5e8faSwyllys  * than EEXIST), return -1.
499030a5e8faSwyllys  */
499130a5e8faSwyllys static int
499230a5e8faSwyllys test_for_file(char *filename, mode_t mode)
499330a5e8faSwyllys {
499430a5e8faSwyllys 	int fd;
499530a5e8faSwyllys 
499630a5e8faSwyllys 	/*
499730a5e8faSwyllys 	 * Try to create the file with the EXCL flag.
499830a5e8faSwyllys 	 * The call should fail if the file exists.
499930a5e8faSwyllys 	 */
500030a5e8faSwyllys 	fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
500130a5e8faSwyllys 	if (fd == -1 && errno == EEXIST)
500230a5e8faSwyllys 		return (1);
500330a5e8faSwyllys 	else if (fd == -1) /* some other error */
500430a5e8faSwyllys 		return (-1);
500530a5e8faSwyllys 
500630a5e8faSwyllys 	/* The file did NOT exist.  Delete the testcase. */
500730a5e8faSwyllys 	(void) close(fd);
500830a5e8faSwyllys 	(void) unlink(filename);
500930a5e8faSwyllys 	return (0);
501030a5e8faSwyllys }
501130a5e8faSwyllys 
501230a5e8faSwyllys KMF_RETURN
501330a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
501430a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
501530a5e8faSwyllys {
501630a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
501730a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
501830a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
501930a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
502030a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
502130a5e8faSwyllys 	KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
502230a5e8faSwyllys 	KMF_CREDENTIAL cred = {NULL, 0};
502330a5e8faSwyllys 	BIO *out = NULL;
502430a5e8faSwyllys 	int keys = 0;
502530a5e8faSwyllys 	char *fullpath = NULL;
502630a5e8faSwyllys 	char *keyfile = NULL;
502730a5e8faSwyllys 	char *dirpath = NULL;
502830a5e8faSwyllys 
502930a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
503030a5e8faSwyllys 	if (pubkey != NULL)
503130a5e8faSwyllys 		keys++;
503230a5e8faSwyllys 
503330a5e8faSwyllys 	prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
503430a5e8faSwyllys 	if (prikey != NULL)
503530a5e8faSwyllys 		keys++;
503630a5e8faSwyllys 
503730a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
503830a5e8faSwyllys 	if (rawkey != NULL)
503930a5e8faSwyllys 		keys++;
504030a5e8faSwyllys 
504130a5e8faSwyllys 	/*
504230a5e8faSwyllys 	 * Exactly 1 type of key must be passed to this function.
504330a5e8faSwyllys 	 */
504430a5e8faSwyllys 	if (keys != 1)
504530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
504630a5e8faSwyllys 
504730a5e8faSwyllys 	keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
504830a5e8faSwyllys 	    numattr);
504930a5e8faSwyllys 	if (keyfile == NULL)
505030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
505130a5e8faSwyllys 
505230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
505330a5e8faSwyllys 
505430a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
505530a5e8faSwyllys 
505630a5e8faSwyllys 	/* Once we have the full path, we don't need the pieces */
505730a5e8faSwyllys 	if (fullpath == NULL)
505830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
505930a5e8faSwyllys 
506030a5e8faSwyllys 	/* If the requested file exists, return an error */
506130a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
506230a5e8faSwyllys 		free(fullpath);
506330a5e8faSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
506430a5e8faSwyllys 	}
506530a5e8faSwyllys 
506630a5e8faSwyllys 	rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
506730a5e8faSwyllys 	    &format, NULL);
506830a5e8faSwyllys 	if (rv != KMF_OK)
506930a5e8faSwyllys 		/* format is optional. */
507030a5e8faSwyllys 		rv = KMF_OK;
507130a5e8faSwyllys 
507230a5e8faSwyllys 	/* CRED is not required for OpenSSL files */
507330a5e8faSwyllys 	(void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
507430a5e8faSwyllys 	    &cred, NULL);
507530a5e8faSwyllys 
507630a5e8faSwyllys 	/* Store the private key to the keyfile */
507730a5e8faSwyllys 	out = BIO_new_file(fullpath, "wb");
507830a5e8faSwyllys 	if (out == NULL) {
507930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
508030a5e8faSwyllys 		rv = KMF_ERR_OPEN_FILE;
508130a5e8faSwyllys 		goto end;
508230a5e8faSwyllys 	}
508330a5e8faSwyllys 
508430a5e8faSwyllys 	if (prikey != NULL && prikey->keyp != NULL) {
508530a5e8faSwyllys 		if (prikey->keyalg == KMF_RSA ||
508630a5e8faSwyllys 		    prikey->keyalg == KMF_DSA) {
508730a5e8faSwyllys 			pkey = (EVP_PKEY *)prikey->keyp;
508830a5e8faSwyllys 
508930a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
509030a5e8faSwyllys 			    out, &cred, pkey, TRUE);
509130a5e8faSwyllys 
509230a5e8faSwyllys 			if (rv == KMF_OK && prikey->keylabel == NULL) {
509330a5e8faSwyllys 				prikey->keylabel = strdup(fullpath);
509430a5e8faSwyllys 				if (prikey->keylabel == NULL)
509530a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
509630a5e8faSwyllys 			}
509730a5e8faSwyllys 		}
509830a5e8faSwyllys 	} else if (pubkey != NULL && pubkey->keyp != NULL) {
509930a5e8faSwyllys 		if (pubkey->keyalg == KMF_RSA ||
510030a5e8faSwyllys 		    pubkey->keyalg == KMF_DSA) {
510130a5e8faSwyllys 			pkey = (EVP_PKEY *)pubkey->keyp;
510230a5e8faSwyllys 
510330a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
510430a5e8faSwyllys 			    out, &cred, pkey, FALSE);
510530a5e8faSwyllys 
510630a5e8faSwyllys 			if (rv == KMF_OK && pubkey->keylabel == NULL) {
510730a5e8faSwyllys 				pubkey->keylabel = strdup(fullpath);
510830a5e8faSwyllys 				if (pubkey->keylabel == NULL)
510930a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
511030a5e8faSwyllys 			}
511130a5e8faSwyllys 		}
511230a5e8faSwyllys 	} else if (rawkey != NULL) {
511330a5e8faSwyllys 		if (rawkey->keytype == KMF_RSA) {
511430a5e8faSwyllys 			pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
511530a5e8faSwyllys 		} else if (rawkey->keytype == KMF_DSA) {
511630a5e8faSwyllys 			pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
511730a5e8faSwyllys 		} else {
511830a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
511930a5e8faSwyllys 		}
51205b3e1433Swyllys 		if (pkey != NULL) {
512173cc0e02Swyllys 			KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
512273cc0e02Swyllys 
512373cc0e02Swyllys 			rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
512473cc0e02Swyllys 			    (void *)&kclass, NULL);
512573cc0e02Swyllys 			if (rv != KMF_OK)
512673cc0e02Swyllys 				rv = KMF_OK;
51275b3e1433Swyllys 			rv = ssl_write_key(kmfh, format, out,
512873cc0e02Swyllys 			    &cred, pkey, (kclass == KMF_ASYM_PRI));
51295b3e1433Swyllys 			EVP_PKEY_free(pkey);
51305b3e1433Swyllys 		}
513130a5e8faSwyllys 	}
513230a5e8faSwyllys 
513330a5e8faSwyllys end:
513430a5e8faSwyllys 
513530a5e8faSwyllys 	if (out)
513630a5e8faSwyllys 		(void) BIO_free(out);
513730a5e8faSwyllys 
51385b3e1433Swyllys 
513930a5e8faSwyllys 	if (rv == KMF_OK)
514030a5e8faSwyllys 		(void) chmod(fullpath, 0400);
514130a5e8faSwyllys 
514230a5e8faSwyllys 	free(fullpath);
514330a5e8faSwyllys 	return (rv);
514430a5e8faSwyllys }
514530a5e8faSwyllys 
514630a5e8faSwyllys KMF_RETURN
514730a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
514830a5e8faSwyllys {
514930a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
515030a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
515130a5e8faSwyllys 	X509_CRL *xcrl = NULL;
515230a5e8faSwyllys 	X509 *xcert = NULL;
515330a5e8faSwyllys 	EVP_PKEY *pkey;
515430a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
515530a5e8faSwyllys 	BIO *in = NULL, *out = NULL;
515630a5e8faSwyllys 	int openssl_ret = 0;
515730a5e8faSwyllys 	KMF_ENCODE_FORMAT outformat;
515830a5e8faSwyllys 	boolean_t crlcheck = FALSE;
515930a5e8faSwyllys 	char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
516030a5e8faSwyllys 
516130a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
516230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
516330a5e8faSwyllys 	}
516430a5e8faSwyllys 
516530a5e8faSwyllys 	/* CRL check is optional */
516630a5e8faSwyllys 	(void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
516730a5e8faSwyllys 	    &crlcheck, NULL);
516830a5e8faSwyllys 
516930a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
517030a5e8faSwyllys 	if (crlcheck == B_TRUE && certfile == NULL) {
517130a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
517230a5e8faSwyllys 	}
517330a5e8faSwyllys 
517430a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
517530a5e8faSwyllys 	incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
517630a5e8faSwyllys 	outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
517730a5e8faSwyllys 
517830a5e8faSwyllys 	crlfile = get_fullpath(dirpath, incrl);
517930a5e8faSwyllys 
518030a5e8faSwyllys 	if (crlfile == NULL)
518130a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
518230a5e8faSwyllys 
518330a5e8faSwyllys 	outcrlfile = get_fullpath(dirpath, outcrl);
518430a5e8faSwyllys 	if (outcrlfile == NULL)
518530a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
518630a5e8faSwyllys 
518730a5e8faSwyllys 	if (isdir(outcrlfile)) {
518830a5e8faSwyllys 		free(outcrlfile);
518930a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
519030a5e8faSwyllys 	}
519130a5e8faSwyllys 
519230a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
519330a5e8faSwyllys 	if (ret != KMF_OK) {
519430a5e8faSwyllys 		free(outcrlfile);
519530a5e8faSwyllys 		return (ret);
519630a5e8faSwyllys 	}
519730a5e8faSwyllys 
519830a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
519930a5e8faSwyllys 	if (in == NULL)	{
520030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
520130a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
520230a5e8faSwyllys 		goto end;
520330a5e8faSwyllys 	}
520430a5e8faSwyllys 
520530a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
520630a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
520730a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
520830a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
520930a5e8faSwyllys 	}
521030a5e8faSwyllys 
521130a5e8faSwyllys 	if (xcrl == NULL) {
521230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
521330a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
521430a5e8faSwyllys 		goto end;
521530a5e8faSwyllys 	}
521630a5e8faSwyllys 
521730a5e8faSwyllys 	/* If bypasscheck is specified, no need to verify. */
521830a5e8faSwyllys 	if (crlcheck == B_FALSE)
521930a5e8faSwyllys 		goto output;
522030a5e8faSwyllys 
522130a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
522230a5e8faSwyllys 	if (ret != KMF_OK)
522330a5e8faSwyllys 		goto end;
522430a5e8faSwyllys 
522530a5e8faSwyllys 	/* Read in the CA cert file and convert to X509 */
522630a5e8faSwyllys 	if (BIO_read_filename(in, certfile) <= 0) {
522730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
522830a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
522930a5e8faSwyllys 		goto end;
523030a5e8faSwyllys 	}
523130a5e8faSwyllys 
523230a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
523330a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
523430a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
523530a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
523630a5e8faSwyllys 	} else {
523730a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
523830a5e8faSwyllys 		goto end;
523930a5e8faSwyllys 	}
524030a5e8faSwyllys 
524130a5e8faSwyllys 	if (xcert == NULL) {
524230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
524330a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
524430a5e8faSwyllys 		goto end;
524530a5e8faSwyllys 	}
524630a5e8faSwyllys 	/* Now get the public key from the CA cert */
524730a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
524830a5e8faSwyllys 	if (pkey == NULL) {
524930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
525030a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
525130a5e8faSwyllys 		goto end;
525230a5e8faSwyllys 	}
525330a5e8faSwyllys 
525430a5e8faSwyllys 	/* Verify the CRL with the CA's public key */
525530a5e8faSwyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
525630a5e8faSwyllys 	EVP_PKEY_free(pkey);
525730a5e8faSwyllys 	if (openssl_ret > 0) {
525830a5e8faSwyllys 		ret = KMF_OK;  /* verify succeed */
525930a5e8faSwyllys 	} else {
526030a5e8faSwyllys 		SET_ERROR(kmfh, openssl_ret);
526130a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
526230a5e8faSwyllys 	}
526330a5e8faSwyllys 
526430a5e8faSwyllys output:
526530a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
526630a5e8faSwyllys 	    &outformat, NULL);
526730a5e8faSwyllys 	if (ret != KMF_OK) {
526830a5e8faSwyllys 		ret = KMF_OK;
526930a5e8faSwyllys 		outformat = KMF_FORMAT_PEM;
527030a5e8faSwyllys 	}
527130a5e8faSwyllys 
527230a5e8faSwyllys 	out = BIO_new_file(outcrlfile, "wb");
527330a5e8faSwyllys 	if (out == NULL) {
527430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
527530a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
527630a5e8faSwyllys 		goto end;
527730a5e8faSwyllys 	}
527830a5e8faSwyllys 
527930a5e8faSwyllys 	if (outformat == KMF_FORMAT_ASN1) {
528030a5e8faSwyllys 		openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
528130a5e8faSwyllys 	} else if (outformat == KMF_FORMAT_PEM) {
528230a5e8faSwyllys 		openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
528330a5e8faSwyllys 	} else {
528430a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
528530a5e8faSwyllys 		goto end;
528630a5e8faSwyllys 	}
528730a5e8faSwyllys 
528830a5e8faSwyllys 	if (openssl_ret <= 0) {
528930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
529030a5e8faSwyllys 		ret = KMF_ERR_WRITE_FILE;
529130a5e8faSwyllys 	} else {
529230a5e8faSwyllys 		ret = KMF_OK;
529330a5e8faSwyllys 	}
529430a5e8faSwyllys 
529530a5e8faSwyllys end:
529630a5e8faSwyllys 	if (xcrl != NULL)
529730a5e8faSwyllys 		X509_CRL_free(xcrl);
529830a5e8faSwyllys 
529930a5e8faSwyllys 	if (xcert != NULL)
530030a5e8faSwyllys 		X509_free(xcert);
530130a5e8faSwyllys 
530230a5e8faSwyllys 	if (in != NULL)
530330a5e8faSwyllys 		(void) BIO_free(in);
530430a5e8faSwyllys 
530530a5e8faSwyllys 	if (out != NULL)
530630a5e8faSwyllys 		(void) BIO_free(out);
530730a5e8faSwyllys 
530830a5e8faSwyllys 	if (outcrlfile != NULL)
530930a5e8faSwyllys 		free(outcrlfile);
531030a5e8faSwyllys 
531130a5e8faSwyllys 	return (ret);
531230a5e8faSwyllys }
531330a5e8faSwyllys 
531430a5e8faSwyllys KMF_RETURN
531530a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
531630a5e8faSwyllys {
531730a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
531830a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
531930a5e8faSwyllys 	X509_CRL   *x = NULL;
532030a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
532130a5e8faSwyllys 	char *crlfile = NULL;
532230a5e8faSwyllys 	BIO *in = NULL;
532330a5e8faSwyllys 	BIO *mem = NULL;
532430a5e8faSwyllys 	long len;
532530a5e8faSwyllys 	char *memptr;
532630a5e8faSwyllys 	char *data = NULL;
532730a5e8faSwyllys 	char **crldata;
532830a5e8faSwyllys 	char *crlfilename, *dirpath;
532930a5e8faSwyllys 
533030a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
533130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
533230a5e8faSwyllys 	}
533330a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
533430a5e8faSwyllys 	    attrlist, numattr);
533530a5e8faSwyllys 	if (crlfilename == NULL)
533630a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
533730a5e8faSwyllys 
533830a5e8faSwyllys 	crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
533930a5e8faSwyllys 	    attrlist, numattr);
534030a5e8faSwyllys 
534130a5e8faSwyllys 	if (crldata == NULL)
534230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
534330a5e8faSwyllys 
534430a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
534530a5e8faSwyllys 
534630a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
534730a5e8faSwyllys 
534830a5e8faSwyllys 	if (crlfile == NULL)
534930a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
535030a5e8faSwyllys 
535130a5e8faSwyllys 	if (isdir(crlfile)) {
535230a5e8faSwyllys 		free(crlfile);
535330a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
535430a5e8faSwyllys 	}
535530a5e8faSwyllys 
535630a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
535730a5e8faSwyllys 	if (ret != KMF_OK) {
535830a5e8faSwyllys 		free(crlfile);
535930a5e8faSwyllys 		return (ret);
536030a5e8faSwyllys 	}
536130a5e8faSwyllys 
536230a5e8faSwyllys 	if (bio_err == NULL)
536330a5e8faSwyllys 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
536430a5e8faSwyllys 
536530a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
536630a5e8faSwyllys 	if (in == NULL)	{
536730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
536830a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
536930a5e8faSwyllys 		goto end;
537030a5e8faSwyllys 	}
537130a5e8faSwyllys 
537230a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
537330a5e8faSwyllys 		x = d2i_X509_CRL_bio(in, NULL);
537430a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
537530a5e8faSwyllys 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
537630a5e8faSwyllys 	}
537730a5e8faSwyllys 
537830a5e8faSwyllys 	if (x == NULL) { /* should not happen */
537930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
538030a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
538130a5e8faSwyllys 		goto end;
538230a5e8faSwyllys 	}
538330a5e8faSwyllys 
538430a5e8faSwyllys 	mem = BIO_new(BIO_s_mem());
538530a5e8faSwyllys 	if (mem == NULL) {
538630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
538730a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
538830a5e8faSwyllys 		goto end;
538930a5e8faSwyllys 	}
539030a5e8faSwyllys 
539130a5e8faSwyllys 	(void) X509_CRL_print(mem, x);
539230a5e8faSwyllys 	len = BIO_get_mem_data(mem, &memptr);
539330a5e8faSwyllys 	if (len <= 0) {
539430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
539530a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
539630a5e8faSwyllys 		goto end;
539730a5e8faSwyllys 	}
539830a5e8faSwyllys 
539930a5e8faSwyllys 	data = malloc(len + 1);
540030a5e8faSwyllys 	if (data == NULL) {
540130a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
540230a5e8faSwyllys 		goto end;
540330a5e8faSwyllys 	}
540430a5e8faSwyllys 
540530a5e8faSwyllys 	(void) memcpy(data, memptr, len);
540630a5e8faSwyllys 	data[len] = '\0';
540730a5e8faSwyllys 	*crldata = data;
540830a5e8faSwyllys 
540930a5e8faSwyllys end:
541030a5e8faSwyllys 	if (x != NULL)
541130a5e8faSwyllys 		X509_CRL_free(x);
541230a5e8faSwyllys 
541330a5e8faSwyllys 	if (crlfile != NULL)
541430a5e8faSwyllys 		free(crlfile);
541530a5e8faSwyllys 
541630a5e8faSwyllys 	if (in != NULL)
541730a5e8faSwyllys 		(void) BIO_free(in);
541830a5e8faSwyllys 
541930a5e8faSwyllys 	if (mem != NULL)
542030a5e8faSwyllys 		(void) BIO_free(mem);
542130a5e8faSwyllys 
542230a5e8faSwyllys 	return (ret);
542330a5e8faSwyllys }
542430a5e8faSwyllys 
542530a5e8faSwyllys KMF_RETURN
542630a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
542730a5e8faSwyllys {
542830a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
542930a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
543030a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
543130a5e8faSwyllys 	char *crlfile = NULL;
543230a5e8faSwyllys 	BIO *in = NULL;
543330a5e8faSwyllys 	char *crlfilename, *dirpath;
543430a5e8faSwyllys 
543530a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
543630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
543730a5e8faSwyllys 	}
543830a5e8faSwyllys 
543930a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
544030a5e8faSwyllys 	    attrlist, numattr);
544130a5e8faSwyllys 
544230a5e8faSwyllys 	if (crlfilename == NULL)
544330a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
544430a5e8faSwyllys 
544530a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
544630a5e8faSwyllys 
544730a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
544830a5e8faSwyllys 
544930a5e8faSwyllys 	if (crlfile == NULL)
545030a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
545130a5e8faSwyllys 
545230a5e8faSwyllys 	if (isdir(crlfile)) {
545330a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
545430a5e8faSwyllys 		goto end;
545530a5e8faSwyllys 	}
545630a5e8faSwyllys 
545730a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
545830a5e8faSwyllys 	if (ret != KMF_OK)
545930a5e8faSwyllys 		goto end;
546030a5e8faSwyllys 
546130a5e8faSwyllys 	if (unlink(crlfile) != 0) {
546230a5e8faSwyllys 		SET_SYS_ERROR(kmfh, errno);
546330a5e8faSwyllys 		ret = KMF_ERR_INTERNAL;
546430a5e8faSwyllys 		goto end;
546530a5e8faSwyllys 	}
546630a5e8faSwyllys 
546730a5e8faSwyllys end:
546830a5e8faSwyllys 	if (in != NULL)
546930a5e8faSwyllys 		(void) BIO_free(in);
547030a5e8faSwyllys 	if (crlfile != NULL)
547130a5e8faSwyllys 		free(crlfile);
547230a5e8faSwyllys 
547330a5e8faSwyllys 	return (ret);
547430a5e8faSwyllys }
547530a5e8faSwyllys 
547630a5e8faSwyllys KMF_RETURN
547730a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
547830a5e8faSwyllys {
547930a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
548030a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
548130a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
548230a5e8faSwyllys 	BIO *in = NULL;
548330a5e8faSwyllys 	X509   *xcert = NULL;
548430a5e8faSwyllys 	X509_CRL   *xcrl = NULL;
548530a5e8faSwyllys 	STACK_OF(X509_REVOKED) *revoke_stack = NULL;
548630a5e8faSwyllys 	X509_REVOKED *revoke;
548730a5e8faSwyllys 	int i;
548830a5e8faSwyllys 	char *crlfilename, *crlfile, *dirpath, *certfile;
548930a5e8faSwyllys 
549030a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
549130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
549230a5e8faSwyllys 	}
549330a5e8faSwyllys 
549430a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
549530a5e8faSwyllys 	    attrlist, numattr);
549630a5e8faSwyllys 
549730a5e8faSwyllys 	if (crlfilename == NULL)
549830a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
549930a5e8faSwyllys 
550030a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
550130a5e8faSwyllys 	if (certfile == NULL)
550230a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
550330a5e8faSwyllys 
550430a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
550530a5e8faSwyllys 
550630a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
550730a5e8faSwyllys 
550830a5e8faSwyllys 	if (crlfile == NULL)
550930a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
551030a5e8faSwyllys 
551130a5e8faSwyllys 	if (isdir(crlfile)) {
551230a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
551330a5e8faSwyllys 		goto end;
551430a5e8faSwyllys 	}
551530a5e8faSwyllys 
551630a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
551730a5e8faSwyllys 	if (ret != KMF_OK)
551830a5e8faSwyllys 		goto end;
551930a5e8faSwyllys 
552030a5e8faSwyllys 	/* Read the CRL file and load it into a X509_CRL structure */
552130a5e8faSwyllys 	in = BIO_new_file(crlfilename, "rb");
552230a5e8faSwyllys 	if (in == NULL)	{
552330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
552430a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
552530a5e8faSwyllys 		goto end;
552630a5e8faSwyllys 	}
552730a5e8faSwyllys 
552830a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
552930a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
553030a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
553130a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
553230a5e8faSwyllys 	}
553330a5e8faSwyllys 
553430a5e8faSwyllys 	if (xcrl == NULL) {
553530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
553630a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
553730a5e8faSwyllys 		goto end;
553830a5e8faSwyllys 	}
553930a5e8faSwyllys 	(void) BIO_free(in);
554030a5e8faSwyllys 
554130a5e8faSwyllys 	/* Read the Certificate file and load it into a X509 structure */
554230a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
554330a5e8faSwyllys 	if (ret != KMF_OK)
554430a5e8faSwyllys 		goto end;
554530a5e8faSwyllys 
554630a5e8faSwyllys 	in = BIO_new_file(certfile, "rb");
554730a5e8faSwyllys 	if (in == NULL)	{
554830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
554930a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
555030a5e8faSwyllys 		goto end;
555130a5e8faSwyllys 	}
555230a5e8faSwyllys 
555330a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
555430a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
555530a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
555630a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
555730a5e8faSwyllys 	}
555830a5e8faSwyllys 
555930a5e8faSwyllys 	if (xcert == NULL) {
556030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
556130a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
556230a5e8faSwyllys 		goto end;
556330a5e8faSwyllys 	}
556430a5e8faSwyllys 
556530a5e8faSwyllys 	/* Check if the certificate and the CRL have same issuer */
556630a5e8faSwyllys 	if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) {
556730a5e8faSwyllys 		ret = KMF_ERR_ISSUER;
556830a5e8faSwyllys 		goto end;
556930a5e8faSwyllys 	}
557030a5e8faSwyllys 
557130a5e8faSwyllys 	/* Check to see if the certificate serial number is revoked */
557230a5e8faSwyllys 	revoke_stack = X509_CRL_get_REVOKED(xcrl);
557330a5e8faSwyllys 	if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
557430a5e8faSwyllys 		/* No revoked certificates in the CRL file */
557530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
557630a5e8faSwyllys 		ret = KMF_ERR_EMPTY_CRL;
557730a5e8faSwyllys 		goto end;
557830a5e8faSwyllys 	}
557930a5e8faSwyllys 
558030a5e8faSwyllys 	for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
5581*a2d4930dSDan OpenSolaris Anderson 		/* LINTED E_BAD_PTR_CAST_ALIGN */
558230a5e8faSwyllys 		revoke = sk_X509_REVOKED_value(revoke_stack, i);
558330a5e8faSwyllys 		if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber,
558430a5e8faSwyllys 		    revoke->serialNumber) == 0) {
558530a5e8faSwyllys 			break;
558630a5e8faSwyllys 		}
558730a5e8faSwyllys 	}
558830a5e8faSwyllys 
558930a5e8faSwyllys 	if (i < sk_X509_REVOKED_num(revoke_stack)) {
559030a5e8faSwyllys 		ret = KMF_OK;
559130a5e8faSwyllys 	} else {
559230a5e8faSwyllys 		ret = KMF_ERR_NOT_REVOKED;
559330a5e8faSwyllys 	}
559430a5e8faSwyllys 
559530a5e8faSwyllys end:
559630a5e8faSwyllys 	if (in != NULL)
559730a5e8faSwyllys 		(void) BIO_free(in);
559830a5e8faSwyllys 	if (xcrl != NULL)
559930a5e8faSwyllys 		X509_CRL_free(xcrl);
560030a5e8faSwyllys 	if (xcert != NULL)
560130a5e8faSwyllys 		X509_free(xcert);
560230a5e8faSwyllys 
560330a5e8faSwyllys 	return (ret);
560430a5e8faSwyllys }
560530a5e8faSwyllys 
560630a5e8faSwyllys KMF_RETURN
560730a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
560830a5e8faSwyllys {
560930a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
561030a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
561130a5e8faSwyllys 	BIO		*bcrl = NULL;
561230a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
561330a5e8faSwyllys 	X509		*xcert = NULL;
561430a5e8faSwyllys 	EVP_PKEY	*pkey;
561530a5e8faSwyllys 	int		sslret;
561630a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
561730a5e8faSwyllys 	unsigned char	*p;
561830a5e8faSwyllys 	long		len;
561930a5e8faSwyllys 
562030a5e8faSwyllys 	if (handle == NULL || crlname == NULL || tacert == NULL) {
562130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
562230a5e8faSwyllys 	}
562330a5e8faSwyllys 
562430a5e8faSwyllys 	ret = kmf_get_file_format(crlname, &crl_format);
562530a5e8faSwyllys 	if (ret != KMF_OK)
562630a5e8faSwyllys 		return (ret);
562730a5e8faSwyllys 
562830a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
562930a5e8faSwyllys 	if (bcrl == NULL)	{
563030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
563130a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
563230a5e8faSwyllys 		goto cleanup;
563330a5e8faSwyllys 	}
563430a5e8faSwyllys 
563530a5e8faSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
563630a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
563730a5e8faSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
563830a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
563930a5e8faSwyllys 	} else {
564030a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
564130a5e8faSwyllys 		goto cleanup;
564230a5e8faSwyllys 	}
564330a5e8faSwyllys 
564430a5e8faSwyllys 	if (xcrl == NULL) {
564530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
564630a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
564730a5e8faSwyllys 		goto cleanup;
564830a5e8faSwyllys 	}
564930a5e8faSwyllys 
565030a5e8faSwyllys 	p = tacert->Data;
565130a5e8faSwyllys 	len = tacert->Length;
565230a5e8faSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
565330a5e8faSwyllys 
565430a5e8faSwyllys 	if (xcert == NULL) {
565530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
565630a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
565730a5e8faSwyllys 		goto cleanup;
565830a5e8faSwyllys 	}
565930a5e8faSwyllys 
566030a5e8faSwyllys 	/* Get issuer certificate public key */
566130a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
566230a5e8faSwyllys 	if (pkey == NULL) {
566330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
566430a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
566530a5e8faSwyllys 		goto cleanup;
566630a5e8faSwyllys 	}
566730a5e8faSwyllys 
566830a5e8faSwyllys 	/* Verify CRL signature */
566930a5e8faSwyllys 	sslret = X509_CRL_verify(xcrl, pkey);
567030a5e8faSwyllys 	EVP_PKEY_free(pkey);
567130a5e8faSwyllys 	if (sslret > 0) {
567230a5e8faSwyllys 		ret = KMF_OK;
567330a5e8faSwyllys 	} else {
567430a5e8faSwyllys 		SET_ERROR(kmfh, sslret);
567530a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
567630a5e8faSwyllys 	}
567730a5e8faSwyllys 
567830a5e8faSwyllys cleanup:
567930a5e8faSwyllys 	if (bcrl != NULL)
568030a5e8faSwyllys 		(void) BIO_free(bcrl);
568130a5e8faSwyllys 
568230a5e8faSwyllys 	if (xcrl != NULL)
568330a5e8faSwyllys 		X509_CRL_free(xcrl);
568430a5e8faSwyllys 
568530a5e8faSwyllys 	if (xcert != NULL)
568630a5e8faSwyllys 		X509_free(xcert);
568730a5e8faSwyllys 
568830a5e8faSwyllys 	return (ret);
568930a5e8faSwyllys 
569030a5e8faSwyllys }
569130a5e8faSwyllys 
569230a5e8faSwyllys KMF_RETURN
569330a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
569430a5e8faSwyllys {
569530a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
569630a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
569730a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
569830a5e8faSwyllys 	BIO		*bcrl = NULL;
569930a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
570030a5e8faSwyllys 	int		i;
570130a5e8faSwyllys 
570230a5e8faSwyllys 	if (handle == NULL || crlname == NULL) {
570330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
570430a5e8faSwyllys 	}
570530a5e8faSwyllys 
570630a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlname, &crl_format);
570730a5e8faSwyllys 	if (ret != KMF_OK)
570830a5e8faSwyllys 		return (ret);
570930a5e8faSwyllys 
571030a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
571130a5e8faSwyllys 	if (bcrl == NULL) {
571230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
571330a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
571430a5e8faSwyllys 		goto cleanup;
571530a5e8faSwyllys 	}
571630a5e8faSwyllys 
57175b3e1433Swyllys 	if (crl_format == KMF_FORMAT_ASN1)
571830a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
57195b3e1433Swyllys 	else if (crl_format == KMF_FORMAT_PEM)
572030a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
572130a5e8faSwyllys 
572230a5e8faSwyllys 	if (xcrl == NULL) {
572330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
572430a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
572530a5e8faSwyllys 		goto cleanup;
572630a5e8faSwyllys 	}
572730a5e8faSwyllys 	i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL);
572830a5e8faSwyllys 	if (i >= 0) {
572930a5e8faSwyllys 		ret = KMF_ERR_VALIDITY_PERIOD;
573030a5e8faSwyllys 		goto cleanup;
573130a5e8faSwyllys 	}
573230a5e8faSwyllys 	if (X509_CRL_get_nextUpdate(xcrl)) {
573330a5e8faSwyllys 		i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL);
573430a5e8faSwyllys 
573530a5e8faSwyllys 		if (i <= 0) {
573630a5e8faSwyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
573730a5e8faSwyllys 			goto cleanup;
573830a5e8faSwyllys 		}
573930a5e8faSwyllys 	}
574030a5e8faSwyllys 
574130a5e8faSwyllys 	ret = KMF_OK;
574230a5e8faSwyllys 
574330a5e8faSwyllys cleanup:
574430a5e8faSwyllys 	if (bcrl != NULL)
574530a5e8faSwyllys 		(void) BIO_free(bcrl);
574630a5e8faSwyllys 
574730a5e8faSwyllys 	if (xcrl != NULL)
574830a5e8faSwyllys 		X509_CRL_free(xcrl);
574930a5e8faSwyllys 
575030a5e8faSwyllys 	return (ret);
575130a5e8faSwyllys }
5752