199ebb4caSwyllys /*
271593db2Swyllys  * Copyright 2007 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 
6499ebb4caSwyllys #pragma ident	"%Z%%M%	%I%	%E% SMI"
6599ebb4caSwyllys 
6671593db2Swyllys #include <stdlib.h>
6799ebb4caSwyllys #include <kmfapiP.h>
6899ebb4caSwyllys #include <ber_der.h>
6999ebb4caSwyllys #include <fcntl.h>
7099ebb4caSwyllys #include <sys/stat.h>
7199ebb4caSwyllys #include <dirent.h>
7299ebb4caSwyllys #include <cryptoutil.h>
7399ebb4caSwyllys #include <synch.h>
7499ebb4caSwyllys #include <thread.h>
7599ebb4caSwyllys 
7699ebb4caSwyllys /* OPENSSL related headers */
7799ebb4caSwyllys #include <openssl/bio.h>
7899ebb4caSwyllys #include <openssl/bn.h>
7999ebb4caSwyllys #include <openssl/asn1.h>
8099ebb4caSwyllys #include <openssl/err.h>
8199ebb4caSwyllys #include <openssl/bn.h>
8299ebb4caSwyllys #include <openssl/x509.h>
8399ebb4caSwyllys #include <openssl/rsa.h>
8499ebb4caSwyllys #include <openssl/dsa.h>
8599ebb4caSwyllys #include <openssl/x509v3.h>
8699ebb4caSwyllys #include <openssl/objects.h>
8799ebb4caSwyllys #include <openssl/pem.h>
8899ebb4caSwyllys #include <openssl/pkcs12.h>
8999ebb4caSwyllys #include <openssl/ocsp.h>
9099ebb4caSwyllys #include <openssl/des.h>
9199ebb4caSwyllys #include <openssl/rand.h>
9299ebb4caSwyllys 
9399ebb4caSwyllys #define	PRINT_ANY_EXTENSION (\
9499ebb4caSwyllys 	KMF_X509_EXT_KEY_USAGE |\
9599ebb4caSwyllys 	KMF_X509_EXT_CERT_POLICIES |\
9699ebb4caSwyllys 	KMF_X509_EXT_SUBJALTNAME |\
9799ebb4caSwyllys 	KMF_X509_EXT_BASIC_CONSTRAINTS |\
9899ebb4caSwyllys 	KMF_X509_EXT_NAME_CONSTRAINTS |\
9999ebb4caSwyllys 	KMF_X509_EXT_POLICY_CONSTRAINTS |\
10099ebb4caSwyllys 	KMF_X509_EXT_EXT_KEY_USAGE |\
10199ebb4caSwyllys 	KMF_X509_EXT_INHIBIT_ANY_POLICY |\
10299ebb4caSwyllys 	KMF_X509_EXT_AUTH_KEY_ID |\
10399ebb4caSwyllys 	KMF_X509_EXT_SUBJ_KEY_ID |\
10499ebb4caSwyllys 	KMF_X509_EXT_POLICY_MAPPING)
10599ebb4caSwyllys 
10699ebb4caSwyllys static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
10799ebb4caSwyllys 	0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
10899ebb4caSwyllys 	0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
10999ebb4caSwyllys 	0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
11099ebb4caSwyllys 	0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
11199ebb4caSwyllys 	0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
11299ebb4caSwyllys 	0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
11399ebb4caSwyllys 	0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
11499ebb4caSwyllys 	0x91 };
11599ebb4caSwyllys 
11699ebb4caSwyllys static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
11799ebb4caSwyllys 	0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
11899ebb4caSwyllys 	0x8e, 0xda, 0xce, 0x91, 0x5f };
11999ebb4caSwyllys 
12099ebb4caSwyllys static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
12199ebb4caSwyllys 	0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
12299ebb4caSwyllys 	0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
12399ebb4caSwyllys 	0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
12499ebb4caSwyllys 	0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
12599ebb4caSwyllys 	0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
12699ebb4caSwyllys 	0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
12799ebb4caSwyllys 	0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
12899ebb4caSwyllys 	0x02 };
12999ebb4caSwyllys 
13099ebb4caSwyllys #define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
13199ebb4caSwyllys 	h->lasterr.errcode = c;
13299ebb4caSwyllys 
13399ebb4caSwyllys #define	SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
13499ebb4caSwyllys 
135*5b3e1433Swyllys /*
136*5b3e1433Swyllys  * Declare some new macros for managing stacks of EVP_PKEYS, similar to
137*5b3e1433Swyllys  * what wanboot did.
138*5b3e1433Swyllys  */
139*5b3e1433Swyllys DECLARE_STACK_OF(EVP_PKEY)
140*5b3e1433Swyllys 
141*5b3e1433Swyllys #define	sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
142*5b3e1433Swyllys #define	sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
143*5b3e1433Swyllys #define	sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
144*5b3e1433Swyllys #define	sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
145*5b3e1433Swyllys #define	sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
146*5b3e1433Swyllys #define	sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
147*5b3e1433Swyllys 	(free_func))
148*5b3e1433Swyllys 
14999ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX;
15099ebb4caSwyllys static int ssl_initialized = 0;
15130a5e8faSwyllys static BIO *bio_err = NULL;
15230a5e8faSwyllys 
15330a5e8faSwyllys static int
15430a5e8faSwyllys test_for_file(char *, mode_t);
155*5b3e1433Swyllys static KMF_RETURN
156*5b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *, char *, int,
157*5b3e1433Swyllys     STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
158*5b3e1433Swyllys 
159*5b3e1433Swyllys static KMF_RETURN
160*5b3e1433Swyllys local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *,
161*5b3e1433Swyllys     int, KMF_KEY_HANDLE *, char *);
162*5b3e1433Swyllys 
163*5b3e1433Swyllys static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int);
16499ebb4caSwyllys 
16571593db2Swyllys static KMF_RETURN
16630a5e8faSwyllys extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *,
16702744e81Swyllys     CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
16871593db2Swyllys 
16971593db2Swyllys static KMF_RETURN
17030a5e8faSwyllys kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
17130a5e8faSwyllys     char *, KMF_DATA *);
17230a5e8faSwyllys 
17330a5e8faSwyllys static KMF_RETURN
17430a5e8faSwyllys load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
17530a5e8faSwyllys     char *, KMF_DATA **, uint32_t *);
17671593db2Swyllys 
17702744e81Swyllys static KMF_RETURN
17802744e81Swyllys sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
17902744e81Swyllys 
18002744e81Swyllys static EVP_PKEY *
18102744e81Swyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *);
18202744e81Swyllys 
18330a5e8faSwyllys static KMF_RETURN
18430a5e8faSwyllys convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
18530a5e8faSwyllys 
18699ebb4caSwyllys KMF_RETURN
18730a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
18899ebb4caSwyllys 
18999ebb4caSwyllys void
19099ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
19199ebb4caSwyllys 
19299ebb4caSwyllys KMF_RETURN
19330a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
19499ebb4caSwyllys 
19599ebb4caSwyllys KMF_RETURN
19630a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
19799ebb4caSwyllys 
19899ebb4caSwyllys KMF_RETURN
19930a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20030a5e8faSwyllys 
20130a5e8faSwyllys KMF_RETURN
20230a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20399ebb4caSwyllys 
20499ebb4caSwyllys KMF_RETURN
20599ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T,  KMF_KEY_HANDLE *, KMF_DATA *);
20699ebb4caSwyllys 
20799ebb4caSwyllys KMF_RETURN
20899ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
20999ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
21099ebb4caSwyllys 
21199ebb4caSwyllys KMF_RETURN
21230a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21399ebb4caSwyllys 
21499ebb4caSwyllys KMF_RETURN
21530a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21699ebb4caSwyllys 
21799ebb4caSwyllys KMF_RETURN
21830a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21999ebb4caSwyllys 
22099ebb4caSwyllys KMF_RETURN
22130a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22299ebb4caSwyllys 
22399ebb4caSwyllys KMF_RETURN
22430a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22599ebb4caSwyllys 
22699ebb4caSwyllys KMF_RETURN
22799ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
22899ebb4caSwyllys 	KMF_PRINTABLE_ITEM, char *);
22999ebb4caSwyllys 
23099ebb4caSwyllys KMF_RETURN
23199ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
23299ebb4caSwyllys 
23399ebb4caSwyllys KMF_RETURN
23430a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23599ebb4caSwyllys 
23699ebb4caSwyllys KMF_RETURN
23799ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
23899ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
23999ebb4caSwyllys 
24099ebb4caSwyllys KMF_RETURN
24130a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24299ebb4caSwyllys 
24399ebb4caSwyllys KMF_RETURN
24430a5e8faSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24599ebb4caSwyllys 
24699ebb4caSwyllys KMF_RETURN
24730a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24899ebb4caSwyllys 
24999ebb4caSwyllys KMF_RETURN
25030a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25199ebb4caSwyllys 
25299ebb4caSwyllys KMF_RETURN
25330a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25499ebb4caSwyllys 
25599ebb4caSwyllys KMF_RETURN
25699ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
25799ebb4caSwyllys 
25899ebb4caSwyllys KMF_RETURN
25930a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
26099ebb4caSwyllys 
26199ebb4caSwyllys KMF_RETURN
26230a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
26399ebb4caSwyllys 
26402744e81Swyllys KMF_RETURN
26502744e81Swyllys OpenSSL_VerifyDataWithCert(KMF_HANDLE_T, KMF_ALGORITHM_INDEX,
26602744e81Swyllys 	KMF_DATA *, KMF_DATA *, KMF_DATA *);
26702744e81Swyllys 
26899ebb4caSwyllys static
26999ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table =
27099ebb4caSwyllys {
27199ebb4caSwyllys 	1,				/* Version */
27299ebb4caSwyllys 	NULL, /* ConfigureKeystore */
27399ebb4caSwyllys 	OpenSSL_FindCert,
27499ebb4caSwyllys 	OpenSSL_FreeKMFCert,
27599ebb4caSwyllys 	OpenSSL_StoreCert,
27699ebb4caSwyllys 	NULL, /* ImportCert */
27799ebb4caSwyllys 	OpenSSL_ImportCRL,
27899ebb4caSwyllys 	OpenSSL_DeleteCert,
27999ebb4caSwyllys 	OpenSSL_DeleteCRL,
28099ebb4caSwyllys 	OpenSSL_CreateKeypair,
28199ebb4caSwyllys 	OpenSSL_FindKey,
28299ebb4caSwyllys 	OpenSSL_EncodePubKeyData,
28399ebb4caSwyllys 	OpenSSL_SignData,
28499ebb4caSwyllys 	OpenSSL_DeleteKey,
28599ebb4caSwyllys 	OpenSSL_ListCRL,
28699ebb4caSwyllys 	NULL,	/* FindCRL */
28799ebb4caSwyllys 	OpenSSL_FindCertInCRL,
28899ebb4caSwyllys 	OpenSSL_GetErrorString,
28930a5e8faSwyllys 	OpenSSL_FindPrikeyByCert,
29099ebb4caSwyllys 	OpenSSL_DecryptData,
29130a5e8faSwyllys 	OpenSSL_ExportPK12,
29299ebb4caSwyllys 	OpenSSL_CreateSymKey,
29399ebb4caSwyllys 	OpenSSL_GetSymKeyValue,
29499ebb4caSwyllys 	NULL,	/* SetTokenPin */
29502744e81Swyllys 	OpenSSL_VerifyDataWithCert,
29630a5e8faSwyllys 	OpenSSL_StoreKey,
29799ebb4caSwyllys 	NULL	/* Finalize */
29899ebb4caSwyllys };
29999ebb4caSwyllys 
30099ebb4caSwyllys static mutex_t *lock_cs;
30199ebb4caSwyllys static long *lock_count;
30299ebb4caSwyllys 
30399ebb4caSwyllys static void
30499ebb4caSwyllys /*ARGSUSED*/
30599ebb4caSwyllys locking_cb(int mode, int type, char *file, int line)
30699ebb4caSwyllys {
30799ebb4caSwyllys 	if (mode & CRYPTO_LOCK) {
30899ebb4caSwyllys 		(void) mutex_lock(&(lock_cs[type]));
30999ebb4caSwyllys 		lock_count[type]++;
31099ebb4caSwyllys 	} else {
31199ebb4caSwyllys 		(void) mutex_unlock(&(lock_cs[type]));
31299ebb4caSwyllys 	}
31399ebb4caSwyllys }
31499ebb4caSwyllys 
31599ebb4caSwyllys static unsigned long
31699ebb4caSwyllys thread_id()
31799ebb4caSwyllys {
31899ebb4caSwyllys 	return ((unsigned long)thr_self());
31999ebb4caSwyllys }
32099ebb4caSwyllys 
32199ebb4caSwyllys KMF_PLUGIN_FUNCLIST *
32299ebb4caSwyllys KMF_Plugin_Initialize()
32399ebb4caSwyllys {
32499ebb4caSwyllys 	int i;
32599ebb4caSwyllys 
32699ebb4caSwyllys 	(void) mutex_lock(&init_lock);
32799ebb4caSwyllys 	if (!ssl_initialized) {
32899ebb4caSwyllys 		OpenSSL_add_all_algorithms();
32999ebb4caSwyllys 
33099ebb4caSwyllys 		/* Enable error strings for reporting */
33199ebb4caSwyllys 		ERR_load_crypto_strings();
33299ebb4caSwyllys 
33399ebb4caSwyllys 		/*
33499ebb4caSwyllys 		 * Add support for extension OIDs that are not yet in the
33599ebb4caSwyllys 		 * openssl default set.
33699ebb4caSwyllys 		 */
33799ebb4caSwyllys 		(void) OBJ_create("2.5.29.30", "nameConstraints",
33899ebb4caSwyllys 		    "X509v3 Name Constraints");
33999ebb4caSwyllys 		(void) OBJ_create("2.5.29.33", "policyMappings",
34099ebb4caSwyllys 		    "X509v3 Policy Mappings");
34199ebb4caSwyllys 		(void) OBJ_create("2.5.29.36", "policyConstraints",
34299ebb4caSwyllys 		    "X509v3 Policy Constraints");
34399ebb4caSwyllys 		(void) OBJ_create("2.5.29.46", "freshestCRL",
34499ebb4caSwyllys 		    "X509v3 Freshest CRL");
34599ebb4caSwyllys 		(void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
34699ebb4caSwyllys 		    "X509v3 Inhibit Any-Policy");
34799ebb4caSwyllys 		/*
34899ebb4caSwyllys 		 * Set up for thread-safe operation.
34999ebb4caSwyllys 		 */
35099ebb4caSwyllys 		lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
35199ebb4caSwyllys 		if (lock_cs == NULL) {
35299ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
35399ebb4caSwyllys 			return (NULL);
35499ebb4caSwyllys 		}
35599ebb4caSwyllys 
35699ebb4caSwyllys 		lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
35799ebb4caSwyllys 		if (lock_count == NULL) {
35899ebb4caSwyllys 			OPENSSL_free(lock_cs);
35999ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
36099ebb4caSwyllys 			return (NULL);
36199ebb4caSwyllys 		}
36299ebb4caSwyllys 
36399ebb4caSwyllys 		for (i = 0; i < CRYPTO_num_locks(); i++) {
36499ebb4caSwyllys 			lock_count[i] = 0;
36599ebb4caSwyllys 			(void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
36699ebb4caSwyllys 		}
36799ebb4caSwyllys 
36899ebb4caSwyllys 		CRYPTO_set_id_callback((unsigned long (*)())thread_id);
36999ebb4caSwyllys 		CRYPTO_set_locking_callback((void (*)())locking_cb);
37099ebb4caSwyllys 		ssl_initialized = 1;
37199ebb4caSwyllys 	}
37299ebb4caSwyllys 	(void) mutex_unlock(&init_lock);
37399ebb4caSwyllys 
37499ebb4caSwyllys 	return (&openssl_plugin_table);
37599ebb4caSwyllys }
37699ebb4caSwyllys /*
37799ebb4caSwyllys  * Convert an SSL DN to a KMF DN.
37899ebb4caSwyllys  */
37999ebb4caSwyllys static KMF_RETURN
38099ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
38199ebb4caSwyllys {
38299ebb4caSwyllys 	KMF_DATA derdata;
38399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
38499ebb4caSwyllys 	uchar_t *tmp;
38599ebb4caSwyllys 
38699ebb4caSwyllys 	/* Convert to raw DER format */
38799ebb4caSwyllys 	derdata.Length = i2d_X509_NAME(sslDN, NULL);
38899ebb4caSwyllys 	if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
38999ebb4caSwyllys 	    == NULL) {
39099ebb4caSwyllys 		return (KMF_ERR_MEMORY);
39199ebb4caSwyllys 	}
39299ebb4caSwyllys 	(void) i2d_X509_NAME(sslDN, &tmp);
39399ebb4caSwyllys 
39499ebb4caSwyllys 	/* Decode to KMF format */
39599ebb4caSwyllys 	rv = DerDecodeName(&derdata, kmfDN);
39699ebb4caSwyllys 	if (rv != KMF_OK) {
39799ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
39899ebb4caSwyllys 	}
39999ebb4caSwyllys 	OPENSSL_free(derdata.Data);
40099ebb4caSwyllys 
40199ebb4caSwyllys 	return (rv);
40299ebb4caSwyllys }
40399ebb4caSwyllys 
40430a5e8faSwyllys int
40599ebb4caSwyllys isdir(char *path)
40699ebb4caSwyllys {
40799ebb4caSwyllys 	struct stat s;
40899ebb4caSwyllys 
40999ebb4caSwyllys 	if (stat(path, &s) == -1)
41099ebb4caSwyllys 		return (0);
41199ebb4caSwyllys 
41230a5e8faSwyllys 	return ((s.st_mode & S_IFMT) == S_IFDIR);
41399ebb4caSwyllys }
41499ebb4caSwyllys 
41599ebb4caSwyllys static KMF_RETURN
41699ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
41799ebb4caSwyllys {
41899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
41999ebb4caSwyllys 	unsigned char *buf = NULL, *p;
42099ebb4caSwyllys 	int len;
42199ebb4caSwyllys 
42299ebb4caSwyllys 	/*
42399ebb4caSwyllys 	 * Convert the X509 internal struct to DER encoded data
42499ebb4caSwyllys 	 */
42599ebb4caSwyllys 	if ((len = i2d_X509(x509cert, NULL)) < 0) {
42699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
42799ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
42899ebb4caSwyllys 		goto cleanup;
42999ebb4caSwyllys 	}
43099ebb4caSwyllys 	if ((buf = malloc(len)) == NULL) {
43199ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
43299ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
43399ebb4caSwyllys 		goto cleanup;
43499ebb4caSwyllys 	}
43599ebb4caSwyllys 
43699ebb4caSwyllys 	/*
43799ebb4caSwyllys 	 * i2d_X509 will increment the buf pointer so that we need to
43899ebb4caSwyllys 	 * save it.
43999ebb4caSwyllys 	 */
44099ebb4caSwyllys 	p = buf;
44199ebb4caSwyllys 	if ((len = i2d_X509(x509cert, &p)) < 0) {
44299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
44399ebb4caSwyllys 		free(buf);
44499ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
44599ebb4caSwyllys 		goto cleanup;
44699ebb4caSwyllys 	}
44799ebb4caSwyllys 
44899ebb4caSwyllys 	/* caller's responsibility to free it */
44999ebb4caSwyllys 	cert->Data = buf;
45099ebb4caSwyllys 	cert->Length = len;
45199ebb4caSwyllys 
45299ebb4caSwyllys cleanup:
45399ebb4caSwyllys 	if (rv != KMF_OK) {
45499ebb4caSwyllys 		if (buf)
45599ebb4caSwyllys 			free(buf);
45699ebb4caSwyllys 		cert->Data = NULL;
45799ebb4caSwyllys 		cert->Length = 0;
45899ebb4caSwyllys 	}
45999ebb4caSwyllys 
46099ebb4caSwyllys 	return (rv);
46199ebb4caSwyllys }
46299ebb4caSwyllys 
46330a5e8faSwyllys 
46499ebb4caSwyllys static KMF_RETURN
46530a5e8faSwyllys check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
46630a5e8faSwyllys     boolean_t *match)
46799ebb4caSwyllys {
46899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
46999ebb4caSwyllys 	boolean_t findIssuer = FALSE;
47099ebb4caSwyllys 	boolean_t findSubject = FALSE;
47199ebb4caSwyllys 	boolean_t findSerial = FALSE;
47299ebb4caSwyllys 	KMF_X509_NAME issuerDN, subjectDN;
47399ebb4caSwyllys 	KMF_X509_NAME certIssuerDN, certSubjectDN;
47499ebb4caSwyllys 
47599ebb4caSwyllys 	*match = FALSE;
47699ebb4caSwyllys 	if (xcert == NULL) {
47799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
47899ebb4caSwyllys 	}
47999ebb4caSwyllys 
48099ebb4caSwyllys 	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
48199ebb4caSwyllys 	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
48299ebb4caSwyllys 	(void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
48399ebb4caSwyllys 	(void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
48499ebb4caSwyllys 
48530a5e8faSwyllys 	if (issuer != NULL && strlen(issuer)) {
48630a5e8faSwyllys 		rv = kmf_dn_parser(issuer, &issuerDN);
48799ebb4caSwyllys 		if (rv != KMF_OK)
48899ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
48999ebb4caSwyllys 
49099ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->issuer, &certIssuerDN);
49199ebb4caSwyllys 		if (rv != KMF_OK) {
49230a5e8faSwyllys 			kmf_free_dn(&issuerDN);
49399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
49499ebb4caSwyllys 		}
49599ebb4caSwyllys 
49699ebb4caSwyllys 		findIssuer = TRUE;
49799ebb4caSwyllys 	}
49830a5e8faSwyllys 	if (subject != NULL && strlen(subject)) {
49930a5e8faSwyllys 		rv = kmf_dn_parser(subject, &subjectDN);
50099ebb4caSwyllys 		if (rv != KMF_OK) {
50199ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
50299ebb4caSwyllys 			goto cleanup;
50399ebb4caSwyllys 		}
50499ebb4caSwyllys 
50599ebb4caSwyllys 		rv = get_x509_dn(xcert->cert_info->subject, &certSubjectDN);
50699ebb4caSwyllys 		if (rv != KMF_OK) {
50799ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
50899ebb4caSwyllys 			goto cleanup;
50999ebb4caSwyllys 		}
51099ebb4caSwyllys 		findSubject = TRUE;
51199ebb4caSwyllys 	}
51230a5e8faSwyllys 	if (serial != NULL && serial->val != NULL)
51399ebb4caSwyllys 		findSerial = TRUE;
51499ebb4caSwyllys 
51599ebb4caSwyllys 	if (findSerial) {
51699ebb4caSwyllys 		BIGNUM *bn;
51799ebb4caSwyllys 
51899ebb4caSwyllys 		/* Comparing BIGNUMs is a pain! */
51999ebb4caSwyllys 		bn = ASN1_INTEGER_to_BN(xcert->cert_info->serialNumber, NULL);
52099ebb4caSwyllys 		if (bn != NULL) {
52199ebb4caSwyllys 			int bnlen = BN_num_bytes(bn);
52299ebb4caSwyllys 
52330a5e8faSwyllys 			if (bnlen == serial->len) {
52499ebb4caSwyllys 				uchar_t *a = malloc(bnlen);
52599ebb4caSwyllys 				if (a == NULL) {
52699ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
52799ebb4caSwyllys 					BN_free(bn);
52899ebb4caSwyllys 					goto cleanup;
52999ebb4caSwyllys 				}
53099ebb4caSwyllys 				bnlen = BN_bn2bin(bn, a);
53130a5e8faSwyllys 				*match = (memcmp(a, serial->val, serial->len) ==
53230a5e8faSwyllys 				    0);
53399ebb4caSwyllys 				rv = KMF_OK;
53499ebb4caSwyllys 				free(a);
53599ebb4caSwyllys 			}
53699ebb4caSwyllys 			BN_free(bn);
53799ebb4caSwyllys 			if (!(*match))
53899ebb4caSwyllys 				goto cleanup;
53999ebb4caSwyllys 		} else {
54099ebb4caSwyllys 			rv = KMF_OK;
54199ebb4caSwyllys 			goto cleanup;
54299ebb4caSwyllys 		}
54399ebb4caSwyllys 	}
54499ebb4caSwyllys 	if (findIssuer) {
54530a5e8faSwyllys 		*match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
54630a5e8faSwyllys 		if ((*match) == B_FALSE) {
54730a5e8faSwyllys 			/* stop checking and bail */
54899ebb4caSwyllys 			rv = KMF_OK;
54999ebb4caSwyllys 			goto cleanup;
55099ebb4caSwyllys 		}
55199ebb4caSwyllys 	}
55299ebb4caSwyllys 	if (findSubject) {
55330a5e8faSwyllys 		*match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
55430a5e8faSwyllys 		if ((*match) == B_FALSE) {
55530a5e8faSwyllys 			/* stop checking and bail */
55699ebb4caSwyllys 			rv = KMF_OK;
55799ebb4caSwyllys 			goto cleanup;
55899ebb4caSwyllys 		}
55999ebb4caSwyllys 	}
56099ebb4caSwyllys 
56199ebb4caSwyllys 	*match = TRUE;
56299ebb4caSwyllys cleanup:
56399ebb4caSwyllys 	if (findIssuer) {
56430a5e8faSwyllys 		kmf_free_dn(&issuerDN);
56530a5e8faSwyllys 		kmf_free_dn(&certIssuerDN);
56699ebb4caSwyllys 	}
56799ebb4caSwyllys 	if (findSubject) {
56830a5e8faSwyllys 		kmf_free_dn(&subjectDN);
56930a5e8faSwyllys 		kmf_free_dn(&certSubjectDN);
57099ebb4caSwyllys 	}
57199ebb4caSwyllys 
57299ebb4caSwyllys 	return (rv);
57399ebb4caSwyllys }
57499ebb4caSwyllys 
57530a5e8faSwyllys 
57630a5e8faSwyllys /*
57730a5e8faSwyllys  * This function loads a certificate file into an X509 data structure, and
57830a5e8faSwyllys  * checks if its issuer, subject or the serial number matches with those
57930a5e8faSwyllys  * values.  If it matches, then return the X509 data structure.
58030a5e8faSwyllys  */
58199ebb4caSwyllys static KMF_RETURN
58299ebb4caSwyllys load_X509cert(KMF_HANDLE *kmfh,
58330a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
58430a5e8faSwyllys     char *pathname, X509 **outcert)
58599ebb4caSwyllys {
58699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
58799ebb4caSwyllys 	X509 *xcert = NULL;
58899ebb4caSwyllys 	BIO *bcert = NULL;
58999ebb4caSwyllys 	boolean_t  match = FALSE;
59099ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
59199ebb4caSwyllys 
59299ebb4caSwyllys 	/*
59399ebb4caSwyllys 	 * auto-detect the file format, regardless of what
59499ebb4caSwyllys 	 * the 'format' parameters in the params say.
59599ebb4caSwyllys 	 */
59630a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
59799ebb4caSwyllys 	if (rv != KMF_OK) {
59899ebb4caSwyllys 		if (rv == KMF_ERR_OPEN_FILE)
59999ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
60099ebb4caSwyllys 		return (rv);
60199ebb4caSwyllys 	}
60299ebb4caSwyllys 
60399ebb4caSwyllys 	/* Not ASN1(DER) format */
60499ebb4caSwyllys 	if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
60599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
60699ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
60799ebb4caSwyllys 		goto cleanup;
60899ebb4caSwyllys 	}
60999ebb4caSwyllys 
61099ebb4caSwyllys 	if (format == KMF_FORMAT_PEM)
61199ebb4caSwyllys 		xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
61299ebb4caSwyllys 	else if (format == KMF_FORMAT_ASN1)
61399ebb4caSwyllys 		xcert = d2i_X509_bio(bcert, NULL);
61499ebb4caSwyllys 	else if (format == KMF_FORMAT_PKCS12) {
61599ebb4caSwyllys 		PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
61699ebb4caSwyllys 		if (p12 != NULL) {
61799ebb4caSwyllys 			(void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
61899ebb4caSwyllys 			PKCS12_free(p12);
61999ebb4caSwyllys 			p12 = NULL;
62099ebb4caSwyllys 		} else {
62199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
62299ebb4caSwyllys 			rv = KMF_ERR_BAD_CERT_FORMAT;
62399ebb4caSwyllys 		}
62499ebb4caSwyllys 	} else {
62599ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
62699ebb4caSwyllys 		goto cleanup;
62799ebb4caSwyllys 	}
62899ebb4caSwyllys 
62999ebb4caSwyllys 	if (xcert == NULL) {
63099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
63199ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
63299ebb4caSwyllys 		goto cleanup;
63399ebb4caSwyllys 	}
63499ebb4caSwyllys 
63530a5e8faSwyllys 	if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
63630a5e8faSwyllys 	    match == FALSE) {
63799ebb4caSwyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
63899ebb4caSwyllys 		goto cleanup;
63999ebb4caSwyllys 	}
64099ebb4caSwyllys 
64199ebb4caSwyllys 	if (outcert != NULL) {
64299ebb4caSwyllys 		*outcert = xcert;
64399ebb4caSwyllys 	}
64499ebb4caSwyllys 
64599ebb4caSwyllys cleanup:
64699ebb4caSwyllys 	if (bcert != NULL) (void) BIO_free(bcert);
64799ebb4caSwyllys 	if (rv != KMF_OK && xcert != NULL)
64899ebb4caSwyllys 		X509_free(xcert);
64999ebb4caSwyllys 
65099ebb4caSwyllys 	return (rv);
65199ebb4caSwyllys }
65299ebb4caSwyllys 
65371593db2Swyllys static int
65471593db2Swyllys datacmp(const void *a, const void *b)
65571593db2Swyllys {
65671593db2Swyllys 	KMF_DATA *adata = (KMF_DATA *)a;
65771593db2Swyllys 	KMF_DATA *bdata = (KMF_DATA *)b;
65871593db2Swyllys 	if (adata->Length > bdata->Length)
65971593db2Swyllys 		return (-1);
66071593db2Swyllys 	if (adata->Length < bdata->Length)
66171593db2Swyllys 		return (1);
66271593db2Swyllys 	return (0);
66371593db2Swyllys }
66471593db2Swyllys 
66571593db2Swyllys static KMF_RETURN
66630a5e8faSwyllys load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
66730a5e8faSwyllys     KMF_CERT_VALIDITY validity, char *pathname,
66871593db2Swyllys     KMF_DATA **certlist, uint32_t *numcerts)
66971593db2Swyllys {
67071593db2Swyllys 	KMF_RETURN rv = KMF_OK;
67171593db2Swyllys 	int i;
67271593db2Swyllys 	KMF_DATA *certs = NULL;
67371593db2Swyllys 	int nc = 0;
67471593db2Swyllys 	int hits = 0;
67571593db2Swyllys 	KMF_ENCODE_FORMAT format;
67671593db2Swyllys 
67730a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
67871593db2Swyllys 	if (rv != KMF_OK) {
67971593db2Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
68071593db2Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
68171593db2Swyllys 		return (rv);
68271593db2Swyllys 	}
68371593db2Swyllys 	if (format == KMF_FORMAT_ASN1) {
68471593db2Swyllys 		/* load a single certificate */
68571593db2Swyllys 		certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
68671593db2Swyllys 		if (certs == NULL)
68771593db2Swyllys 			return (KMF_ERR_MEMORY);
68871593db2Swyllys 		certs->Data = NULL;
68971593db2Swyllys 		certs->Length = 0;
69030a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
69130a5e8faSwyllys 		    pathname, certs);
69271593db2Swyllys 		if (rv == KMF_OK) {
69371593db2Swyllys 			*certlist = certs;
69471593db2Swyllys 			*numcerts = 1;
69571593db2Swyllys 		}
69671593db2Swyllys 		return (rv);
69771593db2Swyllys 	} else if (format == KMF_FORMAT_PKCS12) {
69871593db2Swyllys 		/* We need a credential to access a PKCS#12 file */
69971593db2Swyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
70071593db2Swyllys 	} else if (format == KMF_FORMAT_PEM ||
70171593db2Swyllys 	    format != KMF_FORMAT_PEM_KEYPAIR) {
70271593db2Swyllys 
70371593db2Swyllys 		/* This function only works on PEM files */
70430a5e8faSwyllys 		rv = extract_pem(kmfh, issuer, subject, serial, pathname,
70534acef67Swyllys 		    (uchar_t *)NULL, 0, NULL, &certs, &nc);
70671593db2Swyllys 	} else {
70771593db2Swyllys 		return (KMF_ERR_ENCODING);
70871593db2Swyllys 	}
70971593db2Swyllys 
71071593db2Swyllys 	if (rv != KMF_OK)
71171593db2Swyllys 		return (rv);
71271593db2Swyllys 
71371593db2Swyllys 	for (i = 0; i < nc; i++) {
71430a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
71530a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
71630a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
71730a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
71871593db2Swyllys 			if (rv == KMF_OK)
71971593db2Swyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
72071593db2Swyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD)
72171593db2Swyllys 				rv = KMF_OK;
72271593db2Swyllys 		}
72371593db2Swyllys 		if (rv != KMF_OK) {
72471593db2Swyllys 			/* Remove this cert from the list by clearing it. */
72530a5e8faSwyllys 			kmf_free_data(&certs[i]);
72671593db2Swyllys 		} else {
72771593db2Swyllys 			hits++; /* count valid certs found */
72871593db2Swyllys 		}
72971593db2Swyllys 		rv = KMF_OK;
73071593db2Swyllys 	}
73171593db2Swyllys 	if (rv == KMF_OK && hits == 0) {
73271593db2Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
73371593db2Swyllys 	} else if (rv == KMF_OK && hits > 0) {
73471593db2Swyllys 		/*
73571593db2Swyllys 		 * Sort the list of certs by length to put the cleared ones
73671593db2Swyllys 		 * at the end so they don't get accessed by the caller.
73771593db2Swyllys 		 */
73871593db2Swyllys 		qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
73971593db2Swyllys 		*certlist = certs;
74071593db2Swyllys 
74171593db2Swyllys 		/* since we sorted the list, just return the number of hits */
74271593db2Swyllys 		*numcerts = hits;
74371593db2Swyllys 	}
74471593db2Swyllys 	return (rv);
74571593db2Swyllys }
74671593db2Swyllys 
74730a5e8faSwyllys 
74899ebb4caSwyllys static KMF_RETURN
74999ebb4caSwyllys kmf_load_cert(KMF_HANDLE *kmfh,
75030a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
75130a5e8faSwyllys     KMF_CERT_VALIDITY validity,
75299ebb4caSwyllys     char *pathname,
75399ebb4caSwyllys     KMF_DATA *cert)
75499ebb4caSwyllys {
75599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
75699ebb4caSwyllys 	X509 *x509cert = NULL;
75799ebb4caSwyllys 
75830a5e8faSwyllys 	rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
75999ebb4caSwyllys 	if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
76099ebb4caSwyllys 		rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
76199ebb4caSwyllys 		if (rv != KMF_OK) {
76299ebb4caSwyllys 			goto cleanup;
76399ebb4caSwyllys 		}
76430a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
76530a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
76630a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
76730a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
76899ebb4caSwyllys 			if (rv == KMF_OK)  {
76999ebb4caSwyllys 				/*
77099ebb4caSwyllys 				 * This is a valid cert so skip it.
77199ebb4caSwyllys 				 */
77299ebb4caSwyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
77399ebb4caSwyllys 			}
77499ebb4caSwyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD) {
77599ebb4caSwyllys 				/*
77699ebb4caSwyllys 				 * We want to return success when we
77799ebb4caSwyllys 				 * find an invalid cert.
77899ebb4caSwyllys 				 */
77999ebb4caSwyllys 				rv = KMF_OK;
78099ebb4caSwyllys 				goto cleanup;
78199ebb4caSwyllys 			}
78299ebb4caSwyllys 		}
78399ebb4caSwyllys 	}
78499ebb4caSwyllys cleanup:
78599ebb4caSwyllys 	if (x509cert != NULL)
78699ebb4caSwyllys 		X509_free(x509cert);
78799ebb4caSwyllys 
78899ebb4caSwyllys 	return (rv);
78999ebb4caSwyllys }
79099ebb4caSwyllys 
79102744e81Swyllys static KMF_RETURN
79202744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
79302744e81Swyllys {
79402744e81Swyllys 	KMF_RETURN ret = KMF_OK;
79502744e81Swyllys 	KMF_RAW_RSA_KEY rsa;
79602744e81Swyllys 	BerElement *asn1 = NULL;
79702744e81Swyllys 	BerValue filebuf;
79802744e81Swyllys 	BerValue OID = { NULL, 0 };
79902744e81Swyllys 	BerValue *Mod = NULL, *PubExp = NULL;
80002744e81Swyllys 	BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
80102744e81Swyllys 	BerValue *Coef = NULL;
80202744e81Swyllys 	BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
80302744e81Swyllys 	BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
80402744e81Swyllys 	BIGNUM *qminus1 = NULL;
80502744e81Swyllys 	BN_CTX *ctx = NULL;
80602744e81Swyllys 
80702744e81Swyllys 	*pkey = NULL;
80802744e81Swyllys 
80902744e81Swyllys 	filebuf.bv_val = (char *)filedata->Data;
81002744e81Swyllys 	filebuf.bv_len = filedata->Length;
81102744e81Swyllys 
81202744e81Swyllys 	asn1 = kmfder_init(&filebuf);
81302744e81Swyllys 	if (asn1 == NULL) {
81402744e81Swyllys 		ret = KMF_ERR_MEMORY;
81502744e81Swyllys 		goto out;
81602744e81Swyllys 	}
81702744e81Swyllys 
81802744e81Swyllys 	if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
81902744e81Swyllys 	    &OID, &Mod, &PubExp, &PriExp, &Prime1,
82002744e81Swyllys 	    &Prime2, &Coef) == -1)  {
82102744e81Swyllys 		ret = KMF_ERR_ENCODING;
82202744e81Swyllys 		goto out;
82302744e81Swyllys 	}
82402744e81Swyllys 
82502744e81Swyllys 	/*
82602744e81Swyllys 	 * We have to derive the 2 Exponents using Bignumber math.
82702744e81Swyllys 	 * Exp1 = PriExp mod (Prime1 - 1)
82802744e81Swyllys 	 * Exp2 = PriExp mod (Prime2 - 1)
82902744e81Swyllys 	 */
83002744e81Swyllys 
83102744e81Swyllys 	/* D = PrivateExponent */
83202744e81Swyllys 	D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
83302744e81Swyllys 	if (D == NULL) {
83402744e81Swyllys 		ret = KMF_ERR_MEMORY;
83502744e81Swyllys 		goto out;
83602744e81Swyllys 	}
83702744e81Swyllys 
83802744e81Swyllys 	/* P = Prime1 (first prime factor of Modulus) */
83902744e81Swyllys 	P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
84002744e81Swyllys 	if (D == NULL) {
84102744e81Swyllys 		ret = KMF_ERR_MEMORY;
84202744e81Swyllys 		goto out;
84302744e81Swyllys 	}
84402744e81Swyllys 
84502744e81Swyllys 	/* Q = Prime2 (second prime factor of Modulus) */
84602744e81Swyllys 	Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
84702744e81Swyllys 
84802744e81Swyllys 	if ((ctx = BN_CTX_new()) == NULL) {
84902744e81Swyllys 		ret = KMF_ERR_MEMORY;
85002744e81Swyllys 		goto out;
85102744e81Swyllys 	}
85202744e81Swyllys 
85302744e81Swyllys 	/* Compute (P - 1) */
85402744e81Swyllys 	pminus1 = BN_new();
85502744e81Swyllys 	(void) BN_sub(pminus1, P, BN_value_one());
85602744e81Swyllys 
85702744e81Swyllys 	/* Exponent1 = D mod (P - 1) */
85802744e81Swyllys 	Exp1 = BN_new();
85902744e81Swyllys 	(void) BN_mod(Exp1, D, pminus1, ctx);
86002744e81Swyllys 
86102744e81Swyllys 	/* Compute (Q - 1) */
86202744e81Swyllys 	qminus1 = BN_new();
86302744e81Swyllys 	(void) BN_sub(qminus1, Q, BN_value_one());
86402744e81Swyllys 
86502744e81Swyllys 	/* Exponent2 = D mod (Q - 1) */
86602744e81Swyllys 	Exp2 = BN_new();
86702744e81Swyllys 	(void) BN_mod(Exp2, D, qminus1, ctx);
86802744e81Swyllys 
86902744e81Swyllys 	/* Coef = (Inverse Q) mod P */
87002744e81Swyllys 	COEF = BN_new();
87102744e81Swyllys 	(void) BN_mod_inverse(COEF, Q, P, ctx);
87202744e81Swyllys 
87302744e81Swyllys 	/* Convert back to KMF format */
87402744e81Swyllys 	(void) memset(&rsa, 0, sizeof (rsa));
87502744e81Swyllys 
87602744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
87702744e81Swyllys 		goto out;
87802744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
87902744e81Swyllys 		goto out;
88002744e81Swyllys 	if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
88102744e81Swyllys 		goto out;
88202744e81Swyllys 
88302744e81Swyllys 	rsa.mod.val = (uchar_t *)Mod->bv_val;
88402744e81Swyllys 	rsa.mod.len = Mod->bv_len;
88502744e81Swyllys 
88602744e81Swyllys 	rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
88702744e81Swyllys 	rsa.pubexp.len = PubExp->bv_len;
88802744e81Swyllys 
88902744e81Swyllys 	rsa.priexp.val = (uchar_t *)PriExp->bv_val;
89002744e81Swyllys 	rsa.priexp.len = PriExp->bv_len;
89102744e81Swyllys 
89202744e81Swyllys 	rsa.prime1.val = (uchar_t *)Prime1->bv_val;
89302744e81Swyllys 	rsa.prime1.len = Prime1->bv_len;
89402744e81Swyllys 
89502744e81Swyllys 	rsa.prime2.val = (uchar_t *)Prime2->bv_val;
89602744e81Swyllys 	rsa.prime2.len = Prime2->bv_len;
89702744e81Swyllys 
89802744e81Swyllys 	*pkey = ImportRawRSAKey(&rsa);
89902744e81Swyllys out:
90002744e81Swyllys 	if (asn1 != NULL)
90102744e81Swyllys 		kmfber_free(asn1, 1);
90202744e81Swyllys 
90302744e81Swyllys 	if (OID.bv_val) {
90402744e81Swyllys 		free(OID.bv_val);
90502744e81Swyllys 	}
90602744e81Swyllys 	if (PriExp)
90702744e81Swyllys 		free(PriExp);
90802744e81Swyllys 
90902744e81Swyllys 	if (Mod)
91002744e81Swyllys 		free(Mod);
91102744e81Swyllys 
91202744e81Swyllys 	if (PubExp)
91302744e81Swyllys 		free(PubExp);
91402744e81Swyllys 
91502744e81Swyllys 	if (Coef) {
91602744e81Swyllys 		(void) memset(Coef->bv_val, 0, Coef->bv_len);
91702744e81Swyllys 		free(Coef->bv_val);
91802744e81Swyllys 		free(Coef);
91902744e81Swyllys 	}
92002744e81Swyllys 	if (Prime1)
92102744e81Swyllys 		free(Prime1);
92202744e81Swyllys 	if (Prime2)
92302744e81Swyllys 		free(Prime2);
92402744e81Swyllys 
92502744e81Swyllys 	if (ctx != NULL)
92602744e81Swyllys 		BN_CTX_free(ctx);
92702744e81Swyllys 
92802744e81Swyllys 	if (D)
92902744e81Swyllys 		BN_clear_free(D);
93002744e81Swyllys 	if (P)
93102744e81Swyllys 		BN_clear_free(P);
93202744e81Swyllys 	if (Q)
93302744e81Swyllys 		BN_clear_free(Q);
93402744e81Swyllys 	if (pminus1)
93502744e81Swyllys 		BN_clear_free(pminus1);
93602744e81Swyllys 	if (qminus1)
93702744e81Swyllys 		BN_clear_free(qminus1);
93802744e81Swyllys 	if (Exp1)
93902744e81Swyllys 		BN_clear_free(Exp1);
94002744e81Swyllys 	if (Exp2)
94102744e81Swyllys 		BN_clear_free(Exp2);
94202744e81Swyllys 
94302744e81Swyllys 	return (ret);
94402744e81Swyllys 
94502744e81Swyllys }
94602744e81Swyllys 
94799ebb4caSwyllys static EVP_PKEY *
94899ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file)
94999ebb4caSwyllys {
95099ebb4caSwyllys 	BIO *keyfile = NULL;
95199ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
95299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
95399ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
95402744e81Swyllys 	KMF_RETURN rv;
95502744e81Swyllys 	KMF_DATA filedata;
95699ebb4caSwyllys 
95799ebb4caSwyllys 	if (file == NULL) {
95899ebb4caSwyllys 		return (NULL);
95999ebb4caSwyllys 	}
96099ebb4caSwyllys 
96130a5e8faSwyllys 	if (kmf_get_file_format((char *)file, &format) != KMF_OK)
96299ebb4caSwyllys 		return (NULL);
96399ebb4caSwyllys 
96499ebb4caSwyllys 	keyfile = BIO_new_file(file, "rb");
96599ebb4caSwyllys 	if (keyfile == NULL) {
96699ebb4caSwyllys 		goto end;
96799ebb4caSwyllys 	}
96899ebb4caSwyllys 
96902744e81Swyllys 	if (format == KMF_FORMAT_ASN1) {
97099ebb4caSwyllys 		pkey = d2i_PrivateKey_bio(keyfile, NULL);
97102744e81Swyllys 		if (pkey == NULL) {
97202744e81Swyllys 
97302744e81Swyllys 			(void) BIO_free(keyfile);
97402744e81Swyllys 			keyfile = NULL;
97502744e81Swyllys 			/* Try odd ASN.1 variations */
97630a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
97702744e81Swyllys 			    &filedata);
97802744e81Swyllys 			if (rv == KMF_OK) {
97902744e81Swyllys 				(void) readAltFormatPrivateKey(&filedata,
98002744e81Swyllys 				    &pkey);
98130a5e8faSwyllys 				kmf_free_data(&filedata);
98202744e81Swyllys 			}
98302744e81Swyllys 		}
98402744e81Swyllys 	} else if (format == KMF_FORMAT_PEM ||
98502744e81Swyllys 	    format == KMF_FORMAT_PEM_KEYPAIR) {
98699ebb4caSwyllys 		pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
98702744e81Swyllys 		if (pkey == NULL) {
98802744e81Swyllys 			KMF_DATA derdata;
98902744e81Swyllys 			/*
99002744e81Swyllys 			 * Check if this is the alt. format
99102744e81Swyllys 			 * RSA private key file.
99202744e81Swyllys 			 */
99330a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
99402744e81Swyllys 			    &filedata);
99502744e81Swyllys 			if (rv == KMF_OK) {
99602744e81Swyllys 				uchar_t *d = NULL;
99702744e81Swyllys 				int len;
99830a5e8faSwyllys 				rv = kmf_pem_to_der(filedata.Data,
99902744e81Swyllys 				    filedata.Length, &d, &len);
100002744e81Swyllys 				if (rv == KMF_OK && d != NULL) {
100102744e81Swyllys 					derdata.Data = d;
100202744e81Swyllys 					derdata.Length = (size_t)len;
100302744e81Swyllys 					(void) readAltFormatPrivateKey(
100402744e81Swyllys 					    &derdata, &pkey);
100502744e81Swyllys 					free(d);
100602744e81Swyllys 				}
100730a5e8faSwyllys 				kmf_free_data(&filedata);
100802744e81Swyllys 			}
100902744e81Swyllys 		}
101002744e81Swyllys 	}
101199ebb4caSwyllys 
101299ebb4caSwyllys end:
101399ebb4caSwyllys 	if (pkey == NULL)
101499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
101599ebb4caSwyllys 
101699ebb4caSwyllys 	if (keyfile != NULL)
101799ebb4caSwyllys 		(void) BIO_free(keyfile);
101899ebb4caSwyllys 
101999ebb4caSwyllys 	return (pkey);
102099ebb4caSwyllys }
102199ebb4caSwyllys 
102299ebb4caSwyllys KMF_RETURN
102330a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
102499ebb4caSwyllys {
102599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
102699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1027f482c776Swyllys 	int i, n;
1028f482c776Swyllys 	uint32_t maxcerts = 0;
102930a5e8faSwyllys 	uint32_t *num_certs;
103030a5e8faSwyllys 	KMF_X509_DER_CERT *kmf_cert = NULL;
103130a5e8faSwyllys 	char *dirpath = NULL;
103230a5e8faSwyllys 	char *filename = NULL;
103330a5e8faSwyllys 	char *fullpath = NULL;
103430a5e8faSwyllys 	char *issuer = NULL;
103530a5e8faSwyllys 	char *subject = NULL;
103630a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
103730a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
103899ebb4caSwyllys 
103930a5e8faSwyllys 	num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
104030a5e8faSwyllys 	if (num_certs == NULL)
104199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
104299ebb4caSwyllys 
104330a5e8faSwyllys 	/* num_certs should reference the size of kmf_cert */
1044f482c776Swyllys 	maxcerts = *num_certs;
1045f482c776Swyllys 	if (maxcerts == 0)
1046f482c776Swyllys 		maxcerts = 0xFFFFFFFF;
104799ebb4caSwyllys 	*num_certs = 0;
104899ebb4caSwyllys 
104930a5e8faSwyllys 	/* Get the optional returned certificate list  */
105030a5e8faSwyllys 	kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
105130a5e8faSwyllys 	    numattr);
105299ebb4caSwyllys 
105330a5e8faSwyllys 	/*
105430a5e8faSwyllys 	 * The dirpath attribute and the filename attribute can not be NULL
105530a5e8faSwyllys 	 * at the same time.
105630a5e8faSwyllys 	 */
105730a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
105830a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
105930a5e8faSwyllys 	    numattr);
106030a5e8faSwyllys 
106130a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
106299ebb4caSwyllys 	if (fullpath == NULL)
106399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
106499ebb4caSwyllys 
106530a5e8faSwyllys 	/* Get optional search criteria attributes */
106630a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
106730a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
106830a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
106930a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
107030a5e8faSwyllys 	    &validity, NULL);
107130a5e8faSwyllys 	if (rv != KMF_OK) {
107230a5e8faSwyllys 		validity = KMF_ALL_CERTS;
107330a5e8faSwyllys 		rv = KMF_OK;
107430a5e8faSwyllys 	}
107530a5e8faSwyllys 
107699ebb4caSwyllys 	if (isdir(fullpath)) {
107799ebb4caSwyllys 		DIR *dirp;
107899ebb4caSwyllys 		struct dirent *dp;
107999ebb4caSwyllys 
1080f482c776Swyllys 		n = 0;
108199ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
108299ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
108399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
108499ebb4caSwyllys 		}
108599ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
108699ebb4caSwyllys 			char *fname;
108771593db2Swyllys 			KMF_DATA *certlist = NULL;
1088f482c776Swyllys 			uint32_t loaded_certs = 0;
108971593db2Swyllys 
109099ebb4caSwyllys 			if (strcmp(dp->d_name, ".") == 0 ||
109199ebb4caSwyllys 			    strcmp(dp->d_name, "..") == 0)
109299ebb4caSwyllys 				continue;
109399ebb4caSwyllys 
109434acef67Swyllys 			fname = get_fullpath(fullpath, (char *)&dp->d_name);
109599ebb4caSwyllys 
109630a5e8faSwyllys 			rv = load_certs(kmfh, issuer, subject, serial,
109730a5e8faSwyllys 			    validity, fname, &certlist,	&loaded_certs);
109899ebb4caSwyllys 
109999ebb4caSwyllys 			if (rv != KMF_OK) {
110099ebb4caSwyllys 				free(fname);
110171593db2Swyllys 				if (certlist != NULL) {
1102f482c776Swyllys 					for (i = 0; i < loaded_certs; i++)
110330a5e8faSwyllys 						kmf_free_data(&certlist[i]);
110471593db2Swyllys 					free(certlist);
110571593db2Swyllys 				}
110699ebb4caSwyllys 				continue;
110799ebb4caSwyllys 			}
110899ebb4caSwyllys 
110999ebb4caSwyllys 			/* If load succeeds, add certdata to the list */
111099ebb4caSwyllys 			if (kmf_cert != NULL) {
1111f482c776Swyllys 				for (i = 0; i < loaded_certs &&
1112b4058258Swyllys 				    n < maxcerts; i++) {
111371593db2Swyllys 					kmf_cert[n].certificate.Data =
111471593db2Swyllys 					    certlist[i].Data;
111599ebb4caSwyllys 					kmf_cert[n].certificate.Length =
111671593db2Swyllys 					    certlist[i].Length;
111799ebb4caSwyllys 
111899ebb4caSwyllys 					kmf_cert[n].kmf_private.keystore_type =
111999ebb4caSwyllys 					    KMF_KEYSTORE_OPENSSL;
112099ebb4caSwyllys 					kmf_cert[n].kmf_private.flags =
112199ebb4caSwyllys 					    KMF_FLAG_CERT_VALID;
112271593db2Swyllys 					kmf_cert[n].kmf_private.label =
112371593db2Swyllys 					    strdup(fname);
112499ebb4caSwyllys 					n++;
112599ebb4caSwyllys 				}
1126b4058258Swyllys 				/*
1127b4058258Swyllys 				 * If maxcerts < loaded_certs, clean up the
1128b4058258Swyllys 				 * certs that were not used.
1129b4058258Swyllys 				 */
1130f482c776Swyllys 				for (; i < loaded_certs; i++)
113130a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1132f482c776Swyllys 			} else {
1133f482c776Swyllys 				for (i = 0; i < loaded_certs; i++)
113430a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1135f482c776Swyllys 				n += loaded_certs;
113671593db2Swyllys 			}
1137f482c776Swyllys 			free(certlist);
113871593db2Swyllys 			free(fname);
113971593db2Swyllys 		}
114099ebb4caSwyllys 		(*num_certs) = n;
114199ebb4caSwyllys 		if (*num_certs == 0)
114299ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
114330a5e8faSwyllys 		if (*num_certs > 0)
114499ebb4caSwyllys 			rv = KMF_OK;
114599ebb4caSwyllys exit:
114699ebb4caSwyllys 		(void) closedir(dirp);
114799ebb4caSwyllys 	} else {
114871593db2Swyllys 		KMF_DATA *certlist = NULL;
1149f482c776Swyllys 		uint32_t loaded_certs = 0;
115071593db2Swyllys 
115130a5e8faSwyllys 		rv = load_certs(kmfh, issuer, subject, serial, validity,
115230a5e8faSwyllys 		    fullpath, &certlist, &loaded_certs);
115399ebb4caSwyllys 		if (rv != KMF_OK) {
115499ebb4caSwyllys 			free(fullpath);
115599ebb4caSwyllys 			return (rv);
115699ebb4caSwyllys 		}
115799ebb4caSwyllys 
1158f482c776Swyllys 		n = 0;
115971593db2Swyllys 		if (kmf_cert != NULL && certlist != NULL) {
1160f482c776Swyllys 			for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1161f482c776Swyllys 				kmf_cert[n].certificate.Data =
116271593db2Swyllys 				    certlist[i].Data;
1163f482c776Swyllys 				kmf_cert[n].certificate.Length =
116471593db2Swyllys 				    certlist[i].Length;
1165f482c776Swyllys 				kmf_cert[n].kmf_private.keystore_type =
116699ebb4caSwyllys 				    KMF_KEYSTORE_OPENSSL;
1167f482c776Swyllys 				kmf_cert[n].kmf_private.flags =
116871593db2Swyllys 				    KMF_FLAG_CERT_VALID;
1169f482c776Swyllys 				kmf_cert[n].kmf_private.label =
117071593db2Swyllys 				    strdup(fullpath);
1171f482c776Swyllys 				n++;
117271593db2Swyllys 			}
1173f482c776Swyllys 			/* If maxcerts < loaded_certs, clean up */
1174f482c776Swyllys 			for (; i < loaded_certs; i++)
117530a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1176f482c776Swyllys 		} else if (certlist != NULL) {
1177f482c776Swyllys 			for (i = 0; i < loaded_certs; i++)
117830a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1179f482c776Swyllys 			n = loaded_certs;
1180f482c776Swyllys 		}
118130a5e8faSwyllys 		if (certlist != NULL)
118271593db2Swyllys 			free(certlist);
1183f482c776Swyllys 		*num_certs = n;
118499ebb4caSwyllys 	}
118599ebb4caSwyllys 
118699ebb4caSwyllys 	free(fullpath);
118799ebb4caSwyllys 
118899ebb4caSwyllys 	return (rv);
118999ebb4caSwyllys }
119099ebb4caSwyllys 
119199ebb4caSwyllys void
119299ebb4caSwyllys /*ARGSUSED*/
119399ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
119499ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert)
119599ebb4caSwyllys {
119699ebb4caSwyllys 	if (kmf_cert != NULL) {
119799ebb4caSwyllys 		if (kmf_cert->certificate.Data != NULL) {
119899ebb4caSwyllys 			free(kmf_cert->certificate.Data);
119999ebb4caSwyllys 			kmf_cert->certificate.Data = NULL;
120099ebb4caSwyllys 			kmf_cert->certificate.Length = 0;
120199ebb4caSwyllys 		}
120299ebb4caSwyllys 		if (kmf_cert->kmf_private.label)
120399ebb4caSwyllys 			free(kmf_cert->kmf_private.label);
120499ebb4caSwyllys 	}
120599ebb4caSwyllys }
120699ebb4caSwyllys 
120730a5e8faSwyllys /*ARGSUSED*/
120899ebb4caSwyllys KMF_RETURN
120930a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
121099ebb4caSwyllys {
121199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
121230a5e8faSwyllys 	KMF_DATA *cert = NULL;
121330a5e8faSwyllys 	char *outfilename = NULL;
121430a5e8faSwyllys 	char *dirpath = NULL;
121530a5e8faSwyllys 	char *fullpath = NULL;
121699ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
121799ebb4caSwyllys 
121830a5e8faSwyllys 	/* Get the cert data */
121930a5e8faSwyllys 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
122030a5e8faSwyllys 	if (cert == NULL || cert->Data == NULL)
122199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
122299ebb4caSwyllys 
122330a5e8faSwyllys 	/* Check the output filename and directory attributes. */
122430a5e8faSwyllys 	outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
122530a5e8faSwyllys 	    numattr);
122630a5e8faSwyllys 	if (outfilename == NULL)
122730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
122899ebb4caSwyllys 
122930a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
123030a5e8faSwyllys 	fullpath = get_fullpath(dirpath, outfilename);
123199ebb4caSwyllys 	if (fullpath == NULL)
123230a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
123399ebb4caSwyllys 
123430a5e8faSwyllys 	/* Check the optional format attribute */
123530a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
123630a5e8faSwyllys 	    &format, NULL);
123730a5e8faSwyllys 	if (ret != KMF_OK) {
123830a5e8faSwyllys 		/* If there is no format attribute, then default to PEM */
123930a5e8faSwyllys 		format = KMF_FORMAT_PEM;
124099ebb4caSwyllys 		ret = KMF_OK;
124130a5e8faSwyllys 	} else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
124230a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
124399ebb4caSwyllys 		goto out;
124499ebb4caSwyllys 	}
124599ebb4caSwyllys 
124630a5e8faSwyllys 	/* Store the certificate in the file with the specified format */
124730a5e8faSwyllys 	ret = kmf_create_cert_file(cert, format, fullpath);
124899ebb4caSwyllys 
124999ebb4caSwyllys out:
125099ebb4caSwyllys 	if (fullpath != NULL)
125199ebb4caSwyllys 		free(fullpath);
125299ebb4caSwyllys 
125399ebb4caSwyllys 	return (ret);
125499ebb4caSwyllys }
125599ebb4caSwyllys 
125630a5e8faSwyllys 
125799ebb4caSwyllys KMF_RETURN
125830a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
125999ebb4caSwyllys {
126099ebb4caSwyllys 	KMF_RETURN rv;
126199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
126299ebb4caSwyllys 	KMF_DATA certdata = {NULL, 0};
126330a5e8faSwyllys 	char *dirpath = NULL;
126430a5e8faSwyllys 	char *filename = NULL;
126530a5e8faSwyllys 	char *fullpath = NULL;
126630a5e8faSwyllys 	char *issuer = NULL;
126730a5e8faSwyllys 	char *subject = NULL;
126830a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
126930a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
127099ebb4caSwyllys 
127130a5e8faSwyllys 	/*
127230a5e8faSwyllys 	 * Get the DIRPATH and CERT_FILENAME attributes.  They can not be
127330a5e8faSwyllys 	 * NULL at the same time.
127430a5e8faSwyllys 	 */
127530a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
127630a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
127730a5e8faSwyllys 	    numattr);
127830a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
127999ebb4caSwyllys 	if (fullpath == NULL)
128099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
128199ebb4caSwyllys 
128230a5e8faSwyllys 	/* Get optional search criteria attributes */
128330a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
128430a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
128530a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
128630a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
128730a5e8faSwyllys 	    &validity, NULL);
128830a5e8faSwyllys 	if (rv != KMF_OK) {
128930a5e8faSwyllys 		validity = KMF_ALL_CERTS;
129030a5e8faSwyllys 		rv = KMF_OK;
129130a5e8faSwyllys 	}
129230a5e8faSwyllys 
129399ebb4caSwyllys 	if (isdir(fullpath)) {
129499ebb4caSwyllys 		DIR *dirp;
129599ebb4caSwyllys 		struct dirent *dp;
129699ebb4caSwyllys 
129799ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
129899ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
129999ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
130099ebb4caSwyllys 		}
130199ebb4caSwyllys 
130299ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
130399ebb4caSwyllys 			if (strcmp(dp->d_name, ".") != 0 &&
130499ebb4caSwyllys 			    strcmp(dp->d_name, "..") != 0) {
130599ebb4caSwyllys 				char *fname;
130699ebb4caSwyllys 
130799ebb4caSwyllys 				fname = get_fullpath(fullpath,
130899ebb4caSwyllys 				    (char *)&dp->d_name);
130999ebb4caSwyllys 
131099ebb4caSwyllys 				if (fname == NULL) {
131199ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
131299ebb4caSwyllys 					break;
131399ebb4caSwyllys 				}
131499ebb4caSwyllys 
131530a5e8faSwyllys 				rv = kmf_load_cert(kmfh, issuer, subject,
131630a5e8faSwyllys 				    serial, validity, fname, &certdata);
131799ebb4caSwyllys 
131899ebb4caSwyllys 				if (rv == KMF_ERR_CERT_NOT_FOUND) {
131999ebb4caSwyllys 					free(fname);
132099ebb4caSwyllys 					if (certdata.Data)
132199ebb4caSwyllys 						free(certdata.Data);
132299ebb4caSwyllys 					rv = KMF_OK;
132399ebb4caSwyllys 					continue;
132499ebb4caSwyllys 				} else if (rv != KMF_OK) {
132599ebb4caSwyllys 					free(fname);
132699ebb4caSwyllys 					break;
132799ebb4caSwyllys 				}
132899ebb4caSwyllys 
132999ebb4caSwyllys 				if (unlink(fname) != 0) {
133099ebb4caSwyllys 					SET_SYS_ERROR(kmfh, errno);
133199ebb4caSwyllys 					rv = KMF_ERR_INTERNAL;
133299ebb4caSwyllys 					free(fname);
133399ebb4caSwyllys 					break;
133499ebb4caSwyllys 				}
133599ebb4caSwyllys 				free(fname);
133699ebb4caSwyllys 				if (certdata.Data)
133799ebb4caSwyllys 					free(certdata.Data);
133899ebb4caSwyllys 			}
133999ebb4caSwyllys 		}
134099ebb4caSwyllys 		(void) closedir(dirp);
134199ebb4caSwyllys 	} else {
134299ebb4caSwyllys 		/* Just try to load a single certificate */
134330a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
134430a5e8faSwyllys 		    fullpath, &certdata);
134599ebb4caSwyllys 		if (rv == KMF_OK) {
134699ebb4caSwyllys 			if (unlink(fullpath) != 0) {
134799ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
134899ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
134999ebb4caSwyllys 			}
135099ebb4caSwyllys 		}
135199ebb4caSwyllys 	}
135299ebb4caSwyllys 
135399ebb4caSwyllys out:
135499ebb4caSwyllys 	if (fullpath != NULL)
135599ebb4caSwyllys 		free(fullpath);
135699ebb4caSwyllys 
135799ebb4caSwyllys 	if (certdata.Data)
135899ebb4caSwyllys 		free(certdata.Data);
135999ebb4caSwyllys 
136099ebb4caSwyllys 	return (rv);
136199ebb4caSwyllys }
136299ebb4caSwyllys 
136399ebb4caSwyllys KMF_RETURN
136499ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
136599ebb4caSwyllys 	KMF_DATA *keydata)
136699ebb4caSwyllys {
136799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
136899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
136999ebb4caSwyllys 	int n;
137099ebb4caSwyllys 
137199ebb4caSwyllys 	if (key == NULL || keydata == NULL ||
137299ebb4caSwyllys 	    key->keyp == NULL)
137399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
137499ebb4caSwyllys 
137599ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
137699ebb4caSwyllys 		RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
137799ebb4caSwyllys 
137899ebb4caSwyllys 		if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
137999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
138099ebb4caSwyllys 			return (KMF_ERR_ENCODING);
138199ebb4caSwyllys 		}
138299ebb4caSwyllys 		RSA_free(pubkey);
138399ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
138499ebb4caSwyllys 		DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
138599ebb4caSwyllys 
138699ebb4caSwyllys 		if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
138799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
138899ebb4caSwyllys 			return (KMF_ERR_ENCODING);
138999ebb4caSwyllys 		}
139099ebb4caSwyllys 		DSA_free(pubkey);
139199ebb4caSwyllys 	} else {
139299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
139399ebb4caSwyllys 	}
139499ebb4caSwyllys 	keydata->Length = n;
139599ebb4caSwyllys 
139699ebb4caSwyllys cleanup:
139799ebb4caSwyllys 	if (rv != KMF_OK) {
139899ebb4caSwyllys 		if (keydata->Data)
139999ebb4caSwyllys 			free(keydata->Data);
140099ebb4caSwyllys 		keydata->Data = NULL;
140199ebb4caSwyllys 		keydata->Length = 0;
140299ebb4caSwyllys 	}
140399ebb4caSwyllys 
140499ebb4caSwyllys 	return (rv);
140599ebb4caSwyllys }
140699ebb4caSwyllys 
140799ebb4caSwyllys static KMF_RETURN
140830a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
140930a5e8faSwyllys 	KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
141099ebb4caSwyllys {
141199ebb4caSwyllys 	int rv = 0;
141299ebb4caSwyllys 	RSA *rsa;
141399ebb4caSwyllys 	DSA *dsa;
141499ebb4caSwyllys 
1415*5b3e1433Swyllys 	if (pkey == NULL || out == NULL)
1416*5b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
1417*5b3e1433Swyllys 
141899ebb4caSwyllys 	switch (format) {
141999ebb4caSwyllys 		case KMF_FORMAT_ASN1:
142099ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
142199ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
142230a5e8faSwyllys 				if (private)
142399ebb4caSwyllys 					rv = i2d_RSAPrivateKey_bio(out, rsa);
142430a5e8faSwyllys 				else
142530a5e8faSwyllys 					rv = i2d_RSAPublicKey_bio(out, rsa);
142699ebb4caSwyllys 				RSA_free(rsa);
142799ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
142899ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
142999ebb4caSwyllys 				rv = i2d_DSAPrivateKey_bio(out, dsa);
143099ebb4caSwyllys 				DSA_free(dsa);
143199ebb4caSwyllys 			}
143299ebb4caSwyllys 			if (rv == 1) {
143399ebb4caSwyllys 				rv = KMF_OK;
143499ebb4caSwyllys 			} else {
143599ebb4caSwyllys 				SET_ERROR(kmfh, rv);
143699ebb4caSwyllys 			}
143799ebb4caSwyllys 			break;
143899ebb4caSwyllys 		case KMF_FORMAT_PEM:
143999ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
144099ebb4caSwyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
144130a5e8faSwyllys 				if (private)
144299ebb4caSwyllys 					rv = PEM_write_bio_RSAPrivateKey(out,
144330a5e8faSwyllys 					    rsa, NULL, NULL, 0, NULL,
144430a5e8faSwyllys 					    (cred != NULL ? cred->cred : NULL));
144530a5e8faSwyllys 				else
144630a5e8faSwyllys 					rv = PEM_write_bio_RSAPublicKey(out,
144730a5e8faSwyllys 					    rsa);
144899ebb4caSwyllys 				RSA_free(rsa);
144999ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
145099ebb4caSwyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
145199ebb4caSwyllys 				rv = PEM_write_bio_DSAPrivateKey(out,
145230a5e8faSwyllys 				    dsa, NULL, NULL, 0, NULL,
145330a5e8faSwyllys 				    (cred != NULL ? cred->cred : NULL));
145499ebb4caSwyllys 				DSA_free(dsa);
145599ebb4caSwyllys 			}
145699ebb4caSwyllys 
145799ebb4caSwyllys 			if (rv == 1) {
145899ebb4caSwyllys 				rv = KMF_OK;
145999ebb4caSwyllys 			} else {
146099ebb4caSwyllys 				SET_ERROR(kmfh, rv);
146199ebb4caSwyllys 			}
146299ebb4caSwyllys 			break;
146399ebb4caSwyllys 
146499ebb4caSwyllys 		default:
146599ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
146699ebb4caSwyllys 	}
146799ebb4caSwyllys 
146899ebb4caSwyllys 	return (rv);
146999ebb4caSwyllys }
147099ebb4caSwyllys 
147199ebb4caSwyllys KMF_RETURN
147230a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
147330a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
147499ebb4caSwyllys {
147599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
147699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
147799ebb4caSwyllys 	uint32_t eValue = 0x010001;
147899ebb4caSwyllys 	RSA *sslPrivKey = NULL;
147999ebb4caSwyllys 	DSA *sslDSAKey = NULL;
148099ebb4caSwyllys 	EVP_PKEY *eprikey = NULL;
148199ebb4caSwyllys 	EVP_PKEY *epubkey = NULL;
148299ebb4caSwyllys 	BIO *out = NULL;
148330a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
148430a5e8faSwyllys 	uint32_t keylen = 1024;
148530a5e8faSwyllys 	uint32_t keylen_size = sizeof (uint32_t);
148630a5e8faSwyllys 	boolean_t storekey = TRUE;
148730a5e8faSwyllys 	KMF_KEY_ALG keytype = KMF_RSA;
148899ebb4caSwyllys 
148930a5e8faSwyllys 	rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
149030a5e8faSwyllys 	    &storekey, NULL);
149130a5e8faSwyllys 	if (rv != KMF_OK) {
149230a5e8faSwyllys 		/* "storekey" is optional. Default is TRUE */
149330a5e8faSwyllys 		rv = KMF_OK;
149499ebb4caSwyllys 	}
149599ebb4caSwyllys 
149630a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
149730a5e8faSwyllys 	    (void *)&keytype, NULL);
149830a5e8faSwyllys 	if (rv != KMF_OK)
149930a5e8faSwyllys 		/* keytype is optional.  KMF_RSA is default */
150030a5e8faSwyllys 		rv = KMF_OK;
150199ebb4caSwyllys 
150230a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
150330a5e8faSwyllys 	if (pubkey == NULL)
150499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
150599ebb4caSwyllys 
150630a5e8faSwyllys 	privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
150730a5e8faSwyllys 	if (privkey == NULL)
150830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
150930a5e8faSwyllys 
151030a5e8faSwyllys 	(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
151130a5e8faSwyllys 	(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
151299ebb4caSwyllys 
151399ebb4caSwyllys 	eprikey = EVP_PKEY_new();
151499ebb4caSwyllys 	if (eprikey == NULL) {
151599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
151699ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
151799ebb4caSwyllys 		goto cleanup;
151899ebb4caSwyllys 	}
151999ebb4caSwyllys 	epubkey = EVP_PKEY_new();
152099ebb4caSwyllys 	if (epubkey == NULL) {
152199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
152299ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
152399ebb4caSwyllys 		goto cleanup;
152499ebb4caSwyllys 	}
152530a5e8faSwyllys 	if (keytype == KMF_RSA) {
152630a5e8faSwyllys 		KMF_BIGINT *rsaexp = NULL;
152799ebb4caSwyllys 
152830a5e8faSwyllys 		rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
152930a5e8faSwyllys 		if (rsaexp != NULL) {
153030a5e8faSwyllys 			if (rsaexp->len > 0 &&
153130a5e8faSwyllys 			    rsaexp->len <= sizeof (eValue) &&
153230a5e8faSwyllys 			    rsaexp->val != NULL) {
153330a5e8faSwyllys 				/*LINTED*/
153430a5e8faSwyllys 				eValue = *(uint32_t *)rsaexp->val;
153530a5e8faSwyllys 			} else {
153630a5e8faSwyllys 				rv = KMF_ERR_BAD_PARAMETER;
153730a5e8faSwyllys 				goto cleanup;
153830a5e8faSwyllys 			}
153930a5e8faSwyllys 		} else {
154030a5e8faSwyllys 			/* RSA Exponent is optional. Default is 0x10001 */
154130a5e8faSwyllys 			rv = KMF_OK;
154230a5e8faSwyllys 		}
154330a5e8faSwyllys 
154430a5e8faSwyllys 		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
154530a5e8faSwyllys 		    &keylen, &keylen_size);
154630a5e8faSwyllys 		if (rv == KMF_ERR_ATTR_NOT_FOUND)
154730a5e8faSwyllys 			/* keylen is optional, default is 1024 */
154830a5e8faSwyllys 			rv = KMF_OK;
154930a5e8faSwyllys 		if (rv != KMF_OK) {
155030a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
155130a5e8faSwyllys 			goto cleanup;
155230a5e8faSwyllys 		}
155330a5e8faSwyllys 
155430a5e8faSwyllys 		sslPrivKey = RSA_generate_key(keylen, eValue, NULL, NULL);
155599ebb4caSwyllys 		if (sslPrivKey == NULL) {
155699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
155799ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
155899ebb4caSwyllys 		} else {
155930a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
156099ebb4caSwyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
156199ebb4caSwyllys 			privkey->keyalg = KMF_RSA;
156299ebb4caSwyllys 			privkey->keyclass = KMF_ASYM_PRI;
156399ebb4caSwyllys 			privkey->israw = FALSE;
156499ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
156530a5e8faSwyllys 
156699ebb4caSwyllys 			/* OpenSSL derives the public key from the private */
156730a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
156899ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
156999ebb4caSwyllys 			pubkey->keyalg = KMF_RSA;
157099ebb4caSwyllys 			pubkey->israw = FALSE;
157199ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
157299ebb4caSwyllys 			pubkey->keyp = (void *)epubkey;
157399ebb4caSwyllys 		}
157430a5e8faSwyllys 	} else if (keytype == KMF_DSA) {
157530a5e8faSwyllys 		DSA *dp;
157699ebb4caSwyllys 		sslDSAKey = DSA_new();
157799ebb4caSwyllys 		if (sslDSAKey == NULL) {
157899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
157999ebb4caSwyllys 			return (KMF_ERR_MEMORY);
158099ebb4caSwyllys 		}
158199ebb4caSwyllys 
158299ebb4caSwyllys 		if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) ==
158399ebb4caSwyllys 		    NULL) {
158499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
158599ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
158699ebb4caSwyllys 			goto cleanup;
158799ebb4caSwyllys 		}
158899ebb4caSwyllys 		if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) ==
158999ebb4caSwyllys 		    NULL) {
159099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
159199ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
159299ebb4caSwyllys 			goto cleanup;
159399ebb4caSwyllys 		}
159499ebb4caSwyllys 		if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) ==
159599ebb4caSwyllys 		    NULL) {
159699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
159799ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
159899ebb4caSwyllys 			goto cleanup;
159999ebb4caSwyllys 		}
160099ebb4caSwyllys 
160199ebb4caSwyllys 		if (!DSA_generate_key(sslDSAKey)) {
160299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
160399ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
160499ebb4caSwyllys 			goto cleanup;
160599ebb4caSwyllys 		}
160699ebb4caSwyllys 
160799ebb4caSwyllys 		privkey->kstype = KMF_KEYSTORE_OPENSSL;
160899ebb4caSwyllys 		privkey->keyalg = KMF_DSA;
160999ebb4caSwyllys 		privkey->keyclass = KMF_ASYM_PRI;
161099ebb4caSwyllys 		privkey->israw = FALSE;
161199ebb4caSwyllys 		if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
161299ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
161399ebb4caSwyllys 		} else {
161499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
161599ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
161699ebb4caSwyllys 			goto cleanup;
161799ebb4caSwyllys 		}
161830a5e8faSwyllys 		dp = DSA_new();
161999ebb4caSwyllys 		/* Make a copy for the public key */
162099ebb4caSwyllys 		if (dp != NULL) {
162199ebb4caSwyllys 			if ((dp->p = BN_new()) == NULL) {
162299ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
162399ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
162499ebb4caSwyllys 				DSA_free(dp);
162599ebb4caSwyllys 				goto cleanup;
162699ebb4caSwyllys 			}
162799ebb4caSwyllys 			if ((dp->q = BN_new()) == NULL) {
162899ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
162999ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
163099ebb4caSwyllys 				BN_free(dp->p);
163199ebb4caSwyllys 				DSA_free(dp);
163299ebb4caSwyllys 				goto cleanup;
163399ebb4caSwyllys 			}
163499ebb4caSwyllys 			if ((dp->g = BN_new()) == NULL) {
163599ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
163699ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
163799ebb4caSwyllys 				BN_free(dp->q);
163899ebb4caSwyllys 				BN_free(dp->p);
163999ebb4caSwyllys 				DSA_free(dp);
164099ebb4caSwyllys 				goto cleanup;
164199ebb4caSwyllys 			}
164299ebb4caSwyllys 			if ((dp->pub_key = BN_new()) == NULL) {
164399ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
164499ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
164599ebb4caSwyllys 				BN_free(dp->q);
164699ebb4caSwyllys 				BN_free(dp->p);
164799ebb4caSwyllys 				BN_free(dp->g);
164899ebb4caSwyllys 				DSA_free(dp);
164999ebb4caSwyllys 				goto cleanup;
165099ebb4caSwyllys 			}
165199ebb4caSwyllys 			(void) BN_copy(dp->p, sslDSAKey->p);
165299ebb4caSwyllys 			(void) BN_copy(dp->q, sslDSAKey->q);
165399ebb4caSwyllys 			(void) BN_copy(dp->g, sslDSAKey->g);
165499ebb4caSwyllys 			(void) BN_copy(dp->pub_key, sslDSAKey->pub_key);
165599ebb4caSwyllys 
165699ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
165799ebb4caSwyllys 			pubkey->keyalg = KMF_DSA;
165899ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
165999ebb4caSwyllys 			pubkey->israw = FALSE;
166099ebb4caSwyllys 
166199ebb4caSwyllys 			if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
166299ebb4caSwyllys 				pubkey->keyp = (void *)epubkey;
166399ebb4caSwyllys 			} else {
166499ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
166599ebb4caSwyllys 				rv = KMF_ERR_KEYGEN_FAILED;
166699ebb4caSwyllys 				goto cleanup;
166799ebb4caSwyllys 			}
166899ebb4caSwyllys 		}
166999ebb4caSwyllys 	}
167099ebb4caSwyllys 
167199ebb4caSwyllys 	if (rv != KMF_OK) {
167299ebb4caSwyllys 		goto cleanup;
167399ebb4caSwyllys 	}
167499ebb4caSwyllys 
167530a5e8faSwyllys 	if (storekey) {
167630a5e8faSwyllys 		KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
167730a5e8faSwyllys 		int i = 0;
167830a5e8faSwyllys 		char *keyfile = NULL, *dirpath = NULL;
167930a5e8faSwyllys 		KMF_ENCODE_FORMAT format;
168030a5e8faSwyllys 		/*
168130a5e8faSwyllys 		 * Construct a new attribute arrray and call openssl_store_key
168230a5e8faSwyllys 		 */
168330a5e8faSwyllys 		kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
168430a5e8faSwyllys 		    privkey, sizeof (privkey));
168530a5e8faSwyllys 		i++;
168630a5e8faSwyllys 
168730a5e8faSwyllys 		dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
168830a5e8faSwyllys 		if (dirpath != NULL) {
168930a5e8faSwyllys 			storeattrs[i].type = KMF_DIRPATH_ATTR;
169030a5e8faSwyllys 			storeattrs[i].pValue = dirpath;
169130a5e8faSwyllys 			storeattrs[i].valueLen = strlen(dirpath);
169230a5e8faSwyllys 			i++;
169330a5e8faSwyllys 		} else {
169430a5e8faSwyllys 			rv = KMF_OK; /* DIRPATH is optional */
169599ebb4caSwyllys 		}
169630a5e8faSwyllys 		keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
169730a5e8faSwyllys 		    attrlist, numattr);
169830a5e8faSwyllys 		if (keyfile != NULL) {
169930a5e8faSwyllys 			storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
170030a5e8faSwyllys 			storeattrs[i].pValue = keyfile;
170130a5e8faSwyllys 			storeattrs[i].valueLen = strlen(keyfile);
170230a5e8faSwyllys 			i++;
170330a5e8faSwyllys 		} else {
170430a5e8faSwyllys 			goto cleanup; /* KEYFILE is required */
170530a5e8faSwyllys 		}
170630a5e8faSwyllys 		rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
170730a5e8faSwyllys 		    (void *)&format, NULL);
170830a5e8faSwyllys 		if (rv == KMF_OK) {
170930a5e8faSwyllys 			storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
171030a5e8faSwyllys 			storeattrs[i].pValue = &format;
171130a5e8faSwyllys 			storeattrs[i].valueLen = sizeof (format);
171230a5e8faSwyllys 			i++;
171330a5e8faSwyllys 		}
171430a5e8faSwyllys 
171530a5e8faSwyllys 		rv = OpenSSL_StoreKey(handle, i, storeattrs);
171630a5e8faSwyllys 	}
171799ebb4caSwyllys 
171899ebb4caSwyllys cleanup:
171999ebb4caSwyllys 	if (rv != KMF_OK) {
172099ebb4caSwyllys 		if (eprikey != NULL)
172199ebb4caSwyllys 			EVP_PKEY_free(eprikey);
172299ebb4caSwyllys 
172399ebb4caSwyllys 		if (epubkey != NULL)
172499ebb4caSwyllys 			EVP_PKEY_free(epubkey);
172599ebb4caSwyllys 
172699ebb4caSwyllys 		if (pubkey->keylabel) {
172799ebb4caSwyllys 			free(pubkey->keylabel);
172899ebb4caSwyllys 			pubkey->keylabel = NULL;
172999ebb4caSwyllys 		}
173099ebb4caSwyllys 
173199ebb4caSwyllys 		if (privkey->keylabel) {
173299ebb4caSwyllys 			free(privkey->keylabel);
173399ebb4caSwyllys 			privkey->keylabel = NULL;
173499ebb4caSwyllys 		}
173599ebb4caSwyllys 
173699ebb4caSwyllys 		pubkey->keyp = NULL;
173799ebb4caSwyllys 		privkey->keyp = NULL;
173899ebb4caSwyllys 	}
173999ebb4caSwyllys 
174099ebb4caSwyllys 	if (sslPrivKey)
174199ebb4caSwyllys 		RSA_free(sslPrivKey);
174299ebb4caSwyllys 
174399ebb4caSwyllys 	if (sslDSAKey)
174499ebb4caSwyllys 		DSA_free(sslDSAKey);
174599ebb4caSwyllys 
174699ebb4caSwyllys 	if (out != NULL)
174799ebb4caSwyllys 		(void) BIO_free(out);
174899ebb4caSwyllys 
174999ebb4caSwyllys 	return (rv);
175099ebb4caSwyllys }
175199ebb4caSwyllys 
175299ebb4caSwyllys KMF_RETURN
175399ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
175499ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
175599ebb4caSwyllys {
175699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
175799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
175899ebb4caSwyllys 	KMF_ALGORITHM_INDEX		AlgId;
175999ebb4caSwyllys 	EVP_MD_CTX ctx;
176099ebb4caSwyllys 	const EVP_MD *md;
176102744e81Swyllys 
176299ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
176399ebb4caSwyllys 	    tobesigned == NULL || output == NULL ||
176499ebb4caSwyllys 	    tobesigned->Data == NULL ||
176599ebb4caSwyllys 	    output->Data == NULL)
176699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
176799ebb4caSwyllys 
176899ebb4caSwyllys 	/* Map the OID to an OpenSSL algorithm */
176930a5e8faSwyllys 	AlgId = x509_algoid_to_algid(AlgOID);
177099ebb4caSwyllys 	if (AlgId == KMF_ALGID_NONE)
177199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
177299ebb4caSwyllys 
177399ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
177499ebb4caSwyllys 		EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
177599ebb4caSwyllys 		uchar_t *p;
177602744e81Swyllys 		int len;
177799ebb4caSwyllys 		if (AlgId == KMF_ALGID_MD5WithRSA)
177899ebb4caSwyllys 			md = EVP_md5();
177999ebb4caSwyllys 		else if (AlgId == KMF_ALGID_MD2WithRSA)
178099ebb4caSwyllys 			md = EVP_md2();
178199ebb4caSwyllys 		else if (AlgId == KMF_ALGID_SHA1WithRSA)
178299ebb4caSwyllys 			md = EVP_sha1();
178302744e81Swyllys 		else if (AlgId == KMF_ALGID_RSA)
178402744e81Swyllys 			md = NULL;
178599ebb4caSwyllys 		else
178699ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
178799ebb4caSwyllys 
178802744e81Swyllys 		if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
178902744e81Swyllys 			RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
179099ebb4caSwyllys 
179102744e81Swyllys 			p = output->Data;
179202744e81Swyllys 			if ((len = RSA_private_encrypt(tobesigned->Length,
179302744e81Swyllys 			    tobesigned->Data, p, rsa,
179402744e81Swyllys 			    RSA_PKCS1_PADDING)) <= 0) {
179502744e81Swyllys 				SET_ERROR(kmfh, ERR_get_error());
179602744e81Swyllys 				ret = KMF_ERR_INTERNAL;
179702744e81Swyllys 			}
179802744e81Swyllys 			output->Length = len;
179902744e81Swyllys 		} else {
180099ebb4caSwyllys 			(void) EVP_MD_CTX_init(&ctx);
180199ebb4caSwyllys 			(void) EVP_SignInit_ex(&ctx, md, NULL);
180299ebb4caSwyllys 			(void) EVP_SignUpdate(&ctx, tobesigned->Data,
180399ebb4caSwyllys 			    (uint32_t)tobesigned->Length);
180499ebb4caSwyllys 			len = (uint32_t)output->Length;
180599ebb4caSwyllys 			p = output->Data;
180602744e81Swyllys 			if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) {
180799ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
180802744e81Swyllys 				len = 0;
180902744e81Swyllys 				ret = KMF_ERR_INTERNAL;
181099ebb4caSwyllys 			}
181199ebb4caSwyllys 			output->Length = len;
181299ebb4caSwyllys 			(void) EVP_MD_CTX_cleanup(&ctx);
181302744e81Swyllys 		}
181499ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
181599ebb4caSwyllys 		DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
181699ebb4caSwyllys 
181799ebb4caSwyllys 		uchar_t hash[EVP_MAX_MD_SIZE];
181899ebb4caSwyllys 		uint32_t hashlen;
181999ebb4caSwyllys 		DSA_SIG *dsasig;
182099ebb4caSwyllys 
182199ebb4caSwyllys 		/*
182299ebb4caSwyllys 		 * OpenSSL EVP_Sign operation automatically converts to
182399ebb4caSwyllys 		 * ASN.1 output so we do the operations separately so we
182499ebb4caSwyllys 		 * are assured of NOT getting ASN.1 output returned.
182599ebb4caSwyllys 		 * KMF does not want ASN.1 encoded results because
182699ebb4caSwyllys 		 * not all mechanisms return ASN.1 encodings (PKCS#11
182799ebb4caSwyllys 		 * and NSS return raw signature data).
182899ebb4caSwyllys 		 */
182999ebb4caSwyllys 		md = EVP_sha1();
183099ebb4caSwyllys 		EVP_MD_CTX_init(&ctx);
183199ebb4caSwyllys 		(void) EVP_DigestInit_ex(&ctx, md, NULL);
183299ebb4caSwyllys 		(void) EVP_DigestUpdate(&ctx, tobesigned->Data,
183399ebb4caSwyllys 		    tobesigned->Length);
183499ebb4caSwyllys 		(void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
183599ebb4caSwyllys 		(void) EVP_MD_CTX_cleanup(&ctx);
183699ebb4caSwyllys 
183799ebb4caSwyllys 		dsasig = DSA_do_sign(hash, hashlen, dsa);
183899ebb4caSwyllys 		if (dsasig != NULL) {
183999ebb4caSwyllys 			int i;
184099ebb4caSwyllys 			output->Length = i = BN_bn2bin(dsasig->r, output->Data);
184199ebb4caSwyllys 			output->Length += BN_bn2bin(dsasig->s,
184299ebb4caSwyllys 			    &output->Data[i]);
184399ebb4caSwyllys 			DSA_SIG_free(dsasig);
184499ebb4caSwyllys 		} else {
184599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
184699ebb4caSwyllys 		}
184799ebb4caSwyllys 	} else {
184899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
184999ebb4caSwyllys 	}
185099ebb4caSwyllys cleanup:
185199ebb4caSwyllys 	return (ret);
185299ebb4caSwyllys }
185399ebb4caSwyllys 
185499ebb4caSwyllys KMF_RETURN
185599ebb4caSwyllys /*ARGSUSED*/
185630a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle,
185730a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
185899ebb4caSwyllys {
185999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
186030a5e8faSwyllys 	KMF_KEY_HANDLE *key;
186130a5e8faSwyllys 	boolean_t destroy = B_TRUE;
186230a5e8faSwyllys 
186330a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
186499ebb4caSwyllys 	if (key == NULL || key->keyp == NULL)
186599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
186699ebb4caSwyllys 
186730a5e8faSwyllys 	rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
186830a5e8faSwyllys 	    (void *)&destroy, NULL);
186930a5e8faSwyllys 	if (rv != KMF_OK) {
187030a5e8faSwyllys 		/* "destroy" is optional. Default is TRUE */
187130a5e8faSwyllys 		rv = KMF_OK;
187230a5e8faSwyllys 	}
187330a5e8faSwyllys 
187499ebb4caSwyllys 	if (key->keyclass != KMF_ASYM_PUB &&
187599ebb4caSwyllys 	    key->keyclass != KMF_ASYM_PRI &&
187699ebb4caSwyllys 	    key->keyclass != KMF_SYMMETRIC)
187799ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
187899ebb4caSwyllys 
187999ebb4caSwyllys 	if (key->keyclass == KMF_SYMMETRIC) {
188030a5e8faSwyllys 		kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
188199ebb4caSwyllys 		key->keyp = NULL;
188299ebb4caSwyllys 	} else {
188399ebb4caSwyllys 		if (key->keyp != NULL) {
188499ebb4caSwyllys 			EVP_PKEY_free(key->keyp);
188599ebb4caSwyllys 			key->keyp = NULL;
188699ebb4caSwyllys 		}
188799ebb4caSwyllys 	}
188899ebb4caSwyllys 
188999ebb4caSwyllys 	if (key->keylabel != NULL) {
189099ebb4caSwyllys 		EVP_PKEY *pkey = NULL;
189199ebb4caSwyllys 		/* If the file exists, make sure it is a proper key. */
189299ebb4caSwyllys 		pkey = openssl_load_key(handle, key->keylabel);
189399ebb4caSwyllys 		if (pkey == NULL) {
1894*5b3e1433Swyllys 			if (key->keylabel != NULL) {
189599ebb4caSwyllys 				free(key->keylabel);
189699ebb4caSwyllys 				key->keylabel = NULL;
1897*5b3e1433Swyllys 			}
189899ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
189999ebb4caSwyllys 		}
190099ebb4caSwyllys 		EVP_PKEY_free(pkey);
190199ebb4caSwyllys 
190299ebb4caSwyllys 		if (destroy) {
190399ebb4caSwyllys 			if (unlink(key->keylabel) != 0) {
190499ebb4caSwyllys 				KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
190599ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
190699ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
190799ebb4caSwyllys 			}
190899ebb4caSwyllys 		}
190999ebb4caSwyllys 		if (key->keylabel != NULL) {
191099ebb4caSwyllys 			free(key->keylabel);
191199ebb4caSwyllys 			key->keylabel = NULL;
191299ebb4caSwyllys 		}
191399ebb4caSwyllys 	}
191499ebb4caSwyllys 	return (rv);
191599ebb4caSwyllys }
191699ebb4caSwyllys 
191799ebb4caSwyllys KMF_RETURN
191899ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
191999ebb4caSwyllys {
192099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
192199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
192299ebb4caSwyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
192399ebb4caSwyllys 
192499ebb4caSwyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
192599ebb4caSwyllys 	if (strlen(str)) {
192699ebb4caSwyllys 		*msgstr = (char *)strdup(str);
192799ebb4caSwyllys 		if ((*msgstr) == NULL)
192899ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
192999ebb4caSwyllys 	} else {
193099ebb4caSwyllys 		*msgstr = NULL;
193199ebb4caSwyllys 	}
193299ebb4caSwyllys 
193399ebb4caSwyllys 	return (ret);
193499ebb4caSwyllys }
193599ebb4caSwyllys 
193699ebb4caSwyllys static int
193799ebb4caSwyllys ext2NID(int kmfext)
193899ebb4caSwyllys {
193999ebb4caSwyllys 	switch (kmfext) {
194099ebb4caSwyllys 		case KMF_X509_EXT_KEY_USAGE:
194199ebb4caSwyllys 			return (NID_key_usage);
194299ebb4caSwyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
194399ebb4caSwyllys 			return (NID_private_key_usage_period);
194499ebb4caSwyllys 		case KMF_X509_EXT_CERT_POLICIES:
194599ebb4caSwyllys 			return (NID_certificate_policies);
194699ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
194799ebb4caSwyllys 			return (NID_subject_alt_name);
194899ebb4caSwyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
194999ebb4caSwyllys 			return (NID_issuer_alt_name);
195099ebb4caSwyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
195199ebb4caSwyllys 			return (NID_basic_constraints);
195299ebb4caSwyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
195399ebb4caSwyllys 			return (NID_ext_key_usage);
195499ebb4caSwyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
195599ebb4caSwyllys 			return (NID_authority_key_identifier);
195699ebb4caSwyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
195799ebb4caSwyllys 			return (NID_crl_distribution_points);
195899ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
195999ebb4caSwyllys 			return (NID_subject_key_identifier);
196099ebb4caSwyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
196199ebb4caSwyllys 			return (OBJ_sn2nid("policyMappings"));
196299ebb4caSwyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
196399ebb4caSwyllys 			return (OBJ_sn2nid("nameConstraints"));
196499ebb4caSwyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
196599ebb4caSwyllys 			return (OBJ_sn2nid("policyConstraints"));
196699ebb4caSwyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
196799ebb4caSwyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
196899ebb4caSwyllys 		case KMF_X509_EXT_FRESHEST_CRL:
196999ebb4caSwyllys 			return (OBJ_sn2nid("freshestCRL"));
197099ebb4caSwyllys 		default:
197199ebb4caSwyllys 			return (NID_undef);
197299ebb4caSwyllys 	}
197399ebb4caSwyllys }
197499ebb4caSwyllys 
197599ebb4caSwyllys KMF_RETURN
197699ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
197799ebb4caSwyllys 	KMF_PRINTABLE_ITEM flag, char *resultStr)
197899ebb4caSwyllys {
197999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
198099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
198199ebb4caSwyllys 	X509 *xcert = NULL;
198299ebb4caSwyllys 	unsigned char *outbuf = NULL;
198399ebb4caSwyllys 	unsigned char *outbuf_p;
198499ebb4caSwyllys 	char *tmpstr = NULL;
198599ebb4caSwyllys 	int j;
198699ebb4caSwyllys 	int ext_index, nid, len;
198799ebb4caSwyllys 	BIO *mem = NULL;
198899ebb4caSwyllys 	STACK *emlst = NULL;
198999ebb4caSwyllys 	X509_EXTENSION *ex;
199099ebb4caSwyllys 	X509_CINF *ci;
199199ebb4caSwyllys 
199299ebb4caSwyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
199399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
199499ebb4caSwyllys 	}
199599ebb4caSwyllys 
199699ebb4caSwyllys 	/* copy cert data to outbuf */
199799ebb4caSwyllys 	outbuf = malloc(pcert->Length);
199899ebb4caSwyllys 	if (outbuf == NULL) {
199999ebb4caSwyllys 		return (KMF_ERR_MEMORY);
200099ebb4caSwyllys 	}
200199ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
200299ebb4caSwyllys 
200399ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
200499ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
200599ebb4caSwyllys 	if (xcert == NULL) {
200699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
200799ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
200899ebb4caSwyllys 		goto out;
200999ebb4caSwyllys 	}
201099ebb4caSwyllys 
201199ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
201299ebb4caSwyllys 	if (mem == NULL) {
201399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
201499ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
201599ebb4caSwyllys 		goto out;
201699ebb4caSwyllys 	}
201799ebb4caSwyllys 
201899ebb4caSwyllys 	switch (flag) {
201999ebb4caSwyllys 	case KMF_CERT_ISSUER:
202099ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
202199ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
202299ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
202399ebb4caSwyllys 		break;
202499ebb4caSwyllys 
202599ebb4caSwyllys 	case KMF_CERT_SUBJECT:
202699ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
202799ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
202899ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
202999ebb4caSwyllys 		break;
203099ebb4caSwyllys 
203199ebb4caSwyllys 	case KMF_CERT_VERSION:
203299ebb4caSwyllys 		tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version);
203399ebb4caSwyllys 		(void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN);
203499ebb4caSwyllys 		OPENSSL_free(tmpstr);
203599ebb4caSwyllys 		len = strlen(resultStr);
203699ebb4caSwyllys 		break;
203799ebb4caSwyllys 
203899ebb4caSwyllys 	case KMF_CERT_SERIALNUM:
203999ebb4caSwyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
204099ebb4caSwyllys 			(void) strcpy(resultStr, "0x");
204199ebb4caSwyllys 			len = BIO_gets(mem, &resultStr[2],
204299ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN - 2);
204399ebb4caSwyllys 		}
204499ebb4caSwyllys 		break;
204599ebb4caSwyllys 
204699ebb4caSwyllys 	case KMF_CERT_NOTBEFORE:
204799ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notBefore(xcert));
204899ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
204999ebb4caSwyllys 		break;
205099ebb4caSwyllys 
205199ebb4caSwyllys 	case KMF_CERT_NOTAFTER:
205299ebb4caSwyllys 		(void) ASN1_TIME_print(mem, X509_get_notAfter(xcert));
205399ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
205499ebb4caSwyllys 		break;
205599ebb4caSwyllys 
205699ebb4caSwyllys 	case KMF_CERT_PUBKEY_DATA:
205799ebb4caSwyllys 		{
205899ebb4caSwyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
205999ebb4caSwyllys 			if (pkey == NULL) {
206099ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
206199ebb4caSwyllys 				ret = KMF_ERR_ENCODING;
206299ebb4caSwyllys 				goto out;
206399ebb4caSwyllys 			}
206499ebb4caSwyllys 
206599ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA) {
206699ebb4caSwyllys 				(void) BIO_printf(mem,
206799ebb4caSwyllys 				    "RSA Public Key: (%d bit)\n",
206899ebb4caSwyllys 				    BN_num_bits(pkey->pkey.rsa->n));
206999ebb4caSwyllys 				(void) RSA_print(mem, pkey->pkey.rsa, 0);
207099ebb4caSwyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
207199ebb4caSwyllys 				(void) BIO_printf(mem,
207299ebb4caSwyllys 				    "%12sDSA Public Key:\n", "");
207399ebb4caSwyllys 				(void) DSA_print(mem, pkey->pkey.dsa, 0);
207499ebb4caSwyllys 			} else {
207599ebb4caSwyllys 				(void) BIO_printf(mem,
207699ebb4caSwyllys 				    "%12sUnknown Public Key:\n", "");
207799ebb4caSwyllys 			}
207899ebb4caSwyllys 			(void) BIO_printf(mem, "\n");
207999ebb4caSwyllys 			EVP_PKEY_free(pkey);
208099ebb4caSwyllys 		}
208199ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
208299ebb4caSwyllys 		break;
208399ebb4caSwyllys 	case KMF_CERT_SIGNATURE_ALG:
208499ebb4caSwyllys 	case KMF_CERT_PUBKEY_ALG:
208599ebb4caSwyllys 		if (flag == KMF_CERT_SIGNATURE_ALG) {
208699ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
208799ebb4caSwyllys 			    xcert->sig_alg->algorithm);
208899ebb4caSwyllys 		} else {
208999ebb4caSwyllys 			len = i2a_ASN1_OBJECT(mem,
209099ebb4caSwyllys 			    xcert->cert_info->key->algor->algorithm);
209199ebb4caSwyllys 		}
209299ebb4caSwyllys 
209399ebb4caSwyllys 		if (len > 0) {
209499ebb4caSwyllys 			len = BIO_read(mem, resultStr,
209599ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN);
209699ebb4caSwyllys 		}
209799ebb4caSwyllys 		break;
209899ebb4caSwyllys 
209999ebb4caSwyllys 	case KMF_CERT_EMAIL:
210099ebb4caSwyllys 		emlst = X509_get1_email(xcert);
210199ebb4caSwyllys 		for (j = 0; j < sk_num(emlst); j++)
210299ebb4caSwyllys 			(void) BIO_printf(mem, "%s\n", sk_value(emlst, j));
210399ebb4caSwyllys 
210499ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
210599ebb4caSwyllys 		X509_email_free(emlst);
210699ebb4caSwyllys 		break;
210799ebb4caSwyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
210899ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
210999ebb4caSwyllys 	case KMF_X509_EXT_KEY_USAGE:
211099ebb4caSwyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
211199ebb4caSwyllys 	case KMF_X509_EXT_CERT_POLICIES:
211299ebb4caSwyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
211399ebb4caSwyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
211499ebb4caSwyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
211599ebb4caSwyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
211699ebb4caSwyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
211799ebb4caSwyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
211899ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
211999ebb4caSwyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
212099ebb4caSwyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
212199ebb4caSwyllys 	case KMF_X509_EXT_FRESHEST_CRL:
212299ebb4caSwyllys 		nid = ext2NID(flag);
212399ebb4caSwyllys 		if (nid == NID_undef) {
212499ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
212599ebb4caSwyllys 			goto out;
212699ebb4caSwyllys 		}
212799ebb4caSwyllys 		ci = xcert->cert_info;
212899ebb4caSwyllys 
212999ebb4caSwyllys 		ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1);
213099ebb4caSwyllys 		if (ext_index == -1) {
213199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
213299ebb4caSwyllys 
213399ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
213499ebb4caSwyllys 			goto out;
213599ebb4caSwyllys 		}
213699ebb4caSwyllys 		ex = X509v3_get_ext(ci->extensions, ext_index);
213799ebb4caSwyllys 
213899ebb4caSwyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
213999ebb4caSwyllys 
214099ebb4caSwyllys 		if (BIO_printf(mem, ": %s\n",
214130a5e8faSwyllys 		    X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
214299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
214399ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
214499ebb4caSwyllys 			goto out;
214599ebb4caSwyllys 		}
214699ebb4caSwyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
214799ebb4caSwyllys 			(void) BIO_printf(mem, "%*s", 4, "");
214899ebb4caSwyllys 			(void) M_ASN1_OCTET_STRING_print(mem, ex->value);
214999ebb4caSwyllys 		}
215099ebb4caSwyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
215199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
215299ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
215399ebb4caSwyllys 			goto out;
215499ebb4caSwyllys 		}
215599ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
215699ebb4caSwyllys 	}
215799ebb4caSwyllys 	if (len <= 0) {
215899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
215999ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
216099ebb4caSwyllys 	}
216199ebb4caSwyllys 
216299ebb4caSwyllys out:
216399ebb4caSwyllys 	if (outbuf != NULL) {
216499ebb4caSwyllys 		free(outbuf);
216599ebb4caSwyllys 	}
216699ebb4caSwyllys 
216799ebb4caSwyllys 	if (xcert != NULL) {
216899ebb4caSwyllys 		X509_free(xcert);
216999ebb4caSwyllys 	}
217099ebb4caSwyllys 
217199ebb4caSwyllys 	if (mem != NULL) {
217299ebb4caSwyllys 		(void) BIO_free(mem);
217399ebb4caSwyllys 	}
217499ebb4caSwyllys 
217599ebb4caSwyllys 	return (ret);
217699ebb4caSwyllys }
217730a5e8faSwyllys 
217899ebb4caSwyllys KMF_RETURN
217999ebb4caSwyllys /*ARGSUSED*/
218030a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
218130a5e8faSwyllys     KMF_ATTRIBUTE *attrlist)
218299ebb4caSwyllys {
218399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
218430a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
218530a5e8faSwyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
218630a5e8faSwyllys 	KMF_KEY_HANDLE *key = NULL;
218730a5e8faSwyllys 	uint32_t numkeys = 1; /* 1 key only */
218830a5e8faSwyllys 	char *dirpath = NULL;
218930a5e8faSwyllys 	char *keyfile = NULL;
219030a5e8faSwyllys 	KMF_ATTRIBUTE new_attrlist[16];
219130a5e8faSwyllys 	int i = 0;
219299ebb4caSwyllys 
219399ebb4caSwyllys 	/*
219499ebb4caSwyllys 	 * This is really just a FindKey operation, reuse the
219599ebb4caSwyllys 	 * FindKey function.
219699ebb4caSwyllys 	 */
219730a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
219830a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
219930a5e8faSwyllys 	i++;
220099ebb4caSwyllys 
220130a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
220230a5e8faSwyllys 	    KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
220330a5e8faSwyllys 	i++;
220499ebb4caSwyllys 
220530a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
220630a5e8faSwyllys 	    KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
220730a5e8faSwyllys 	i++;
220830a5e8faSwyllys 
220930a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
221030a5e8faSwyllys 	if (key == NULL) {
221130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
221230a5e8faSwyllys 	} else {
221330a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
221430a5e8faSwyllys 		    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
221530a5e8faSwyllys 		i++;
221630a5e8faSwyllys 	}
221730a5e8faSwyllys 
221830a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
221930a5e8faSwyllys 	if (dirpath != NULL) {
222030a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
222130a5e8faSwyllys 		    KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
222230a5e8faSwyllys 		i++;
222330a5e8faSwyllys 	}
222430a5e8faSwyllys 
222530a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
222630a5e8faSwyllys 	if (keyfile == NULL)
222730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
222830a5e8faSwyllys 	else {
222930a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
223030a5e8faSwyllys 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
223130a5e8faSwyllys 		i++;
223230a5e8faSwyllys 	}
223330a5e8faSwyllys 
223430a5e8faSwyllys 	rv = OpenSSL_FindKey(handle, i, new_attrlist);
223599ebb4caSwyllys 	return (rv);
223699ebb4caSwyllys }
223799ebb4caSwyllys 
223899ebb4caSwyllys KMF_RETURN
223999ebb4caSwyllys /*ARGSUSED*/
224099ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
224199ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
224299ebb4caSwyllys 	KMF_DATA *output)
224399ebb4caSwyllys {
224499ebb4caSwyllys 	KMF_RETURN		ret = KMF_OK;
224599ebb4caSwyllys 	RSA *rsa = NULL;
224699ebb4caSwyllys 	unsigned int in_len = 0, out_len = 0;
224799ebb4caSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
224899ebb4caSwyllys 	uint8_t *in_data, *out_data;
224999ebb4caSwyllys 	int i, blocks;
225099ebb4caSwyllys 
225199ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
225299ebb4caSwyllys 	    ciphertext == NULL || output == NULL ||
225399ebb4caSwyllys 	    ciphertext->Data == NULL ||
225499ebb4caSwyllys 	    output->Data == NULL)
225599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
225699ebb4caSwyllys 
225799ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
225899ebb4caSwyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
225999ebb4caSwyllys 		modulus_len = RSA_size(rsa);
226099ebb4caSwyllys 	} else {
226199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
226299ebb4caSwyllys 	}
226399ebb4caSwyllys 
226499ebb4caSwyllys 	blocks = ciphertext->Length/modulus_len;
226599ebb4caSwyllys 	out_data = output->Data;
226699ebb4caSwyllys 	in_data = ciphertext->Data;
226799ebb4caSwyllys 	out_len = modulus_len - 11;
226899ebb4caSwyllys 	in_len = modulus_len;
226999ebb4caSwyllys 
227099ebb4caSwyllys 	for (i = 0; i < blocks; i++) {
227199ebb4caSwyllys 		out_len  = RSA_private_decrypt(in_len,
227299ebb4caSwyllys 		    in_data, out_data, rsa, RSA_PKCS1_PADDING);
227399ebb4caSwyllys 
227499ebb4caSwyllys 		if (out_len == 0) {
227599ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
227699ebb4caSwyllys 			goto cleanup;
227799ebb4caSwyllys 		}
227899ebb4caSwyllys 
227999ebb4caSwyllys 		out_data += out_len;
228099ebb4caSwyllys 		total_decrypted += out_len;
228199ebb4caSwyllys 		in_data += in_len;
228299ebb4caSwyllys 	}
228399ebb4caSwyllys 
228499ebb4caSwyllys 	output->Length = total_decrypted;
228599ebb4caSwyllys 
228699ebb4caSwyllys cleanup:
228799ebb4caSwyllys 	RSA_free(rsa);
228899ebb4caSwyllys 	if (ret != KMF_OK)
228999ebb4caSwyllys 		output->Length = 0;
229099ebb4caSwyllys 
229199ebb4caSwyllys 	return (ret);
229299ebb4caSwyllys 
229399ebb4caSwyllys }
229499ebb4caSwyllys 
229599ebb4caSwyllys /*
229699ebb4caSwyllys  *  This function will create a certid from issuer_cert and user_cert.
229799ebb4caSwyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
229899ebb4caSwyllys  *  certid memory after use.
229999ebb4caSwyllys  */
230099ebb4caSwyllys static KMF_RETURN
230199ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
230299ebb4caSwyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
230399ebb4caSwyllys {
230499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
230599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
230699ebb4caSwyllys 	X509   *issuer = NULL;
230799ebb4caSwyllys 	X509   *cert = NULL;
230899ebb4caSwyllys 	unsigned char *ptmp;
230999ebb4caSwyllys 
231099ebb4caSwyllys 	if (issuer_cert == NULL || user_cert == NULL) {
231199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
231299ebb4caSwyllys 	}
231399ebb4caSwyllys 
231499ebb4caSwyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
231599ebb4caSwyllys 	ptmp = issuer_cert->Data;
231699ebb4caSwyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
231799ebb4caSwyllys 	    issuer_cert->Length);
231899ebb4caSwyllys 	if (issuer == NULL) {
231999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
232099ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
232199ebb4caSwyllys 		goto end;
232299ebb4caSwyllys 	}
232399ebb4caSwyllys 
232499ebb4caSwyllys 	/* convert the DER-encoded user cert to an internal X509 */
232599ebb4caSwyllys 	ptmp = user_cert->Data;
232699ebb4caSwyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
232799ebb4caSwyllys 	    user_cert->Length);
232899ebb4caSwyllys 	if (cert == NULL) {
232999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
233099ebb4caSwyllys 
233199ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
233299ebb4caSwyllys 		goto end;
233399ebb4caSwyllys 	}
233499ebb4caSwyllys 
233599ebb4caSwyllys 	/* create a CERTID */
233699ebb4caSwyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
233799ebb4caSwyllys 	if (*certid == NULL) {
233899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
233999ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
234099ebb4caSwyllys 		goto end;
234199ebb4caSwyllys 	}
234299ebb4caSwyllys 
234399ebb4caSwyllys end:
234499ebb4caSwyllys 	if (issuer != NULL) {
234599ebb4caSwyllys 		X509_free(issuer);
234699ebb4caSwyllys 	}
234799ebb4caSwyllys 
234899ebb4caSwyllys 	if (cert != NULL) {
234999ebb4caSwyllys 		X509_free(cert);
235099ebb4caSwyllys 	}
235199ebb4caSwyllys 
235299ebb4caSwyllys 	return (ret);
235399ebb4caSwyllys }
235499ebb4caSwyllys 
235599ebb4caSwyllys KMF_RETURN
235630a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
235730a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
235899ebb4caSwyllys {
235999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
236099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
236199ebb4caSwyllys 	OCSP_CERTID *id = NULL;
236299ebb4caSwyllys 	OCSP_REQUEST *req = NULL;
236399ebb4caSwyllys 	BIO *derbio = NULL;
236430a5e8faSwyllys 	char *reqfile;
236530a5e8faSwyllys 	KMF_DATA *issuer_cert;
236630a5e8faSwyllys 	KMF_DATA *user_cert;
236799ebb4caSwyllys 
236830a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
236930a5e8faSwyllys 	    attrlist, numattr);
237030a5e8faSwyllys 	if (user_cert == NULL)
237199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
237299ebb4caSwyllys 
237330a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
237430a5e8faSwyllys 	    attrlist, numattr);
237530a5e8faSwyllys 	if (issuer_cert == NULL)
237630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
237730a5e8faSwyllys 
237830a5e8faSwyllys 	reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
237930a5e8faSwyllys 	    attrlist, numattr);
238030a5e8faSwyllys 	if (reqfile == NULL)
238130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
238230a5e8faSwyllys 
238330a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
238499ebb4caSwyllys 	if (ret != KMF_OK) {
238599ebb4caSwyllys 		return (ret);
238699ebb4caSwyllys 	}
238799ebb4caSwyllys 
238899ebb4caSwyllys 	/* Create an OCSP request */
238999ebb4caSwyllys 	req = OCSP_REQUEST_new();
239099ebb4caSwyllys 	if (req == NULL) {
239199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
239299ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
239399ebb4caSwyllys 		goto end;
239499ebb4caSwyllys 	}
239599ebb4caSwyllys 
239699ebb4caSwyllys 	if (!OCSP_request_add0_id(req, id)) {
239799ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
239899ebb4caSwyllys 		goto end;
239999ebb4caSwyllys 	}
240099ebb4caSwyllys 
240199ebb4caSwyllys 	/* Write the request to the output file with DER encoding */
240299ebb4caSwyllys 	derbio = BIO_new_file(reqfile, "wb");
240399ebb4caSwyllys 	if (!derbio) {
240499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
240599ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
240699ebb4caSwyllys 		goto end;
240799ebb4caSwyllys 	}
240899ebb4caSwyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
240999ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
241099ebb4caSwyllys 	}
241199ebb4caSwyllys 
241299ebb4caSwyllys end:
241399ebb4caSwyllys 	/*
241499ebb4caSwyllys 	 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
241599ebb4caSwyllys 	 * will deallocate certid's space also.
241699ebb4caSwyllys 	 */
241799ebb4caSwyllys 	if (req != NULL) {
241899ebb4caSwyllys 		OCSP_REQUEST_free(req);
241999ebb4caSwyllys 	}
242099ebb4caSwyllys 
242199ebb4caSwyllys 	if (derbio != NULL) {
242299ebb4caSwyllys 		(void) BIO_free(derbio);
242399ebb4caSwyllys 	}
242499ebb4caSwyllys 
242599ebb4caSwyllys 	return (ret);
242699ebb4caSwyllys }
242799ebb4caSwyllys 
242899ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */
242999ebb4caSwyllys static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
243099ebb4caSwyllys {
243199ebb4caSwyllys 	int i;
243299ebb4caSwyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
243399ebb4caSwyllys 
243499ebb4caSwyllys 	/* Easy if lookup by name */
243599ebb4caSwyllys 	if (id->type == V_OCSP_RESPID_NAME)
243699ebb4caSwyllys 		return (X509_find_by_subject(certs, id->value.byName));
243799ebb4caSwyllys 
243899ebb4caSwyllys 	/* Lookup by key hash */
243999ebb4caSwyllys 
244099ebb4caSwyllys 	/* If key hash isn't SHA1 length then forget it */
244199ebb4caSwyllys 	if (id->value.byKey->length != SHA_DIGEST_LENGTH)
244299ebb4caSwyllys 		return (NULL);
244399ebb4caSwyllys 
244499ebb4caSwyllys 	keyhash = id->value.byKey->data;
244599ebb4caSwyllys 	/* Calculate hash of each key and compare */
244699ebb4caSwyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
244799ebb4caSwyllys 		/*LINTED*/
244899ebb4caSwyllys 		X509 *x = sk_X509_value(certs, i);
2449*5b3e1433Swyllys 		/* Use pubkey_digest to get the key ID value */
245099ebb4caSwyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
245199ebb4caSwyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
245299ebb4caSwyllys 			return (x);
245399ebb4caSwyllys 	}
245499ebb4caSwyllys 	return (NULL);
245599ebb4caSwyllys }
245699ebb4caSwyllys 
245799ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */
245899ebb4caSwyllys /*ARGSUSED*/
245999ebb4caSwyllys static int
246099ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
246199ebb4caSwyllys     X509_STORE *st, unsigned long flags)
246299ebb4caSwyllys {
246399ebb4caSwyllys 	X509 *signer;
246499ebb4caSwyllys 	OCSP_RESPID *rid = bs->tbsResponseData->responderId;
246599ebb4caSwyllys 	if ((signer = ocsp_find_signer_sk(certs, rid)))	{
246699ebb4caSwyllys 		*psigner = signer;
246799ebb4caSwyllys 		return (2);
246899ebb4caSwyllys 	}
246999ebb4caSwyllys 	if (!(flags & OCSP_NOINTERN) &&
247099ebb4caSwyllys 	    (signer = ocsp_find_signer_sk(bs->certs, rid))) {
247199ebb4caSwyllys 		*psigner = signer;
247299ebb4caSwyllys 		return (1);
247399ebb4caSwyllys 	}
247499ebb4caSwyllys 	/* Maybe lookup from store if by subject name */
247599ebb4caSwyllys 
247699ebb4caSwyllys 	*psigner = NULL;
247799ebb4caSwyllys 	return (0);
247899ebb4caSwyllys }
247999ebb4caSwyllys 
248099ebb4caSwyllys /*
248199ebb4caSwyllys  * This function will verify the signature of a basic response, using
248299ebb4caSwyllys  * the public key from the OCSP responder certificate.
248399ebb4caSwyllys  */
248499ebb4caSwyllys static KMF_RETURN
248599ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
248699ebb4caSwyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
248799ebb4caSwyllys {
248899ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
248999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
249099ebb4caSwyllys 	STACK_OF(X509) *cert_stack = NULL;
249199ebb4caSwyllys 	X509 *signer = NULL;
249299ebb4caSwyllys 	X509 *issuer = NULL;
249399ebb4caSwyllys 	EVP_PKEY *skey = NULL;
249499ebb4caSwyllys 	unsigned char *ptmp;
249599ebb4caSwyllys 
249699ebb4caSwyllys 
249799ebb4caSwyllys 	if (bs == NULL || issuer_cert == NULL)
249899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
249999ebb4caSwyllys 
250099ebb4caSwyllys 	/*
250199ebb4caSwyllys 	 * Find the certificate that signed the basic response.
250299ebb4caSwyllys 	 *
250399ebb4caSwyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
250499ebb4caSwyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
250599ebb4caSwyllys 	 * If we still do not find a signer, we will look for it from the
250699ebb4caSwyllys 	 * certificate list came with the response file.
250799ebb4caSwyllys 	 */
250899ebb4caSwyllys 	if (signer_cert != NULL) {
250999ebb4caSwyllys 		ptmp = signer_cert->Data;
251099ebb4caSwyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
251199ebb4caSwyllys 		    signer_cert->Length);
251299ebb4caSwyllys 		if (signer == NULL) {
251399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
251499ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
251599ebb4caSwyllys 			goto end;
251699ebb4caSwyllys 		}
251799ebb4caSwyllys 	} else {
251899ebb4caSwyllys 		/*
251999ebb4caSwyllys 		 * Convert the issuer cert into X509 and push it into a
252099ebb4caSwyllys 		 * stack to be used by ocsp_find_signer().
252199ebb4caSwyllys 		 */
252299ebb4caSwyllys 		ptmp = issuer_cert->Data;
252399ebb4caSwyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
252499ebb4caSwyllys 		    issuer_cert->Length);
252599ebb4caSwyllys 		if (issuer == NULL) {
252699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
252799ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
252899ebb4caSwyllys 			goto end;
252999ebb4caSwyllys 		}
253099ebb4caSwyllys 
253199ebb4caSwyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
253299ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
253399ebb4caSwyllys 			goto end;
253499ebb4caSwyllys 		}
253599ebb4caSwyllys 
253699ebb4caSwyllys 		if (sk_X509_push(cert_stack, issuer) == NULL) {
253799ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
253899ebb4caSwyllys 			goto end;
253999ebb4caSwyllys 		}
254099ebb4caSwyllys 
254199ebb4caSwyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
254299ebb4caSwyllys 		if (!ret) {
254399ebb4caSwyllys 			/* can not find the signer */
254499ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
254599ebb4caSwyllys 			goto end;
254699ebb4caSwyllys 		}
254799ebb4caSwyllys 	}
254899ebb4caSwyllys 
254999ebb4caSwyllys 	/* Verify the signature of the response */
255099ebb4caSwyllys 	skey = X509_get_pubkey(signer);
255199ebb4caSwyllys 	if (skey == NULL) {
255299ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
255399ebb4caSwyllys 		goto end;
255499ebb4caSwyllys 	}
255599ebb4caSwyllys 
255699ebb4caSwyllys 	ret = OCSP_BASICRESP_verify(bs, skey, 0);
255799ebb4caSwyllys 	if (ret == 0) {
255899ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
255999ebb4caSwyllys 		goto end;
256099ebb4caSwyllys 	}
256199ebb4caSwyllys 
256299ebb4caSwyllys end:
256399ebb4caSwyllys 	if (issuer != NULL) {
256499ebb4caSwyllys 		X509_free(issuer);
256599ebb4caSwyllys 	}
256699ebb4caSwyllys 
256799ebb4caSwyllys 	if (signer != NULL) {
256899ebb4caSwyllys 		X509_free(signer);
256999ebb4caSwyllys 	}
257099ebb4caSwyllys 
257199ebb4caSwyllys 	if (skey != NULL) {
257299ebb4caSwyllys 		EVP_PKEY_free(skey);
257399ebb4caSwyllys 	}
257499ebb4caSwyllys 
257599ebb4caSwyllys 	if (cert_stack != NULL) {
257699ebb4caSwyllys 		sk_X509_free(cert_stack);
257799ebb4caSwyllys 	}
257899ebb4caSwyllys 
257999ebb4caSwyllys 	return (ret);
258099ebb4caSwyllys }
258199ebb4caSwyllys 
258299ebb4caSwyllys 
258399ebb4caSwyllys 
258499ebb4caSwyllys KMF_RETURN
258599ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
258630a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
258799ebb4caSwyllys {
258899ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
258999ebb4caSwyllys 	BIO *derbio = NULL;
259099ebb4caSwyllys 	OCSP_RESPONSE *resp = NULL;
259199ebb4caSwyllys 	OCSP_BASICRESP *bs = NULL;
259299ebb4caSwyllys 	OCSP_CERTID *id = NULL;
259399ebb4caSwyllys 	OCSP_SINGLERESP *single = NULL;
259499ebb4caSwyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
259599ebb4caSwyllys 	int index, status, reason;
259630a5e8faSwyllys 	KMF_DATA *issuer_cert;
259730a5e8faSwyllys 	KMF_DATA *user_cert;
259830a5e8faSwyllys 	KMF_DATA *signer_cert;
259930a5e8faSwyllys 	KMF_DATA *response;
260030a5e8faSwyllys 	int *response_reason, *response_status, *cert_status;
260130a5e8faSwyllys 	boolean_t ignore_response_sign = B_FALSE;	/* default is FALSE */
260230a5e8faSwyllys 	uint32_t response_lifetime;
260399ebb4caSwyllys 
260430a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
260530a5e8faSwyllys 	    attrlist, numattr);
260630a5e8faSwyllys 	if (issuer_cert == NULL)
260799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
260899ebb4caSwyllys 
260930a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
261030a5e8faSwyllys 	    attrlist, numattr);
261130a5e8faSwyllys 	if (user_cert == NULL)
261299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
261330a5e8faSwyllys 
261430a5e8faSwyllys 	response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
261530a5e8faSwyllys 	    attrlist, numattr);
261630a5e8faSwyllys 	if (response == NULL)
261730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
261830a5e8faSwyllys 
261930a5e8faSwyllys 	response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
262030a5e8faSwyllys 	    attrlist, numattr);
262130a5e8faSwyllys 	if (response_status == NULL)
262230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
262330a5e8faSwyllys 
262430a5e8faSwyllys 	response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
262530a5e8faSwyllys 	    attrlist, numattr);
262630a5e8faSwyllys 	if (response_reason == NULL)
262730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
262830a5e8faSwyllys 
262930a5e8faSwyllys 	cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
263030a5e8faSwyllys 	    attrlist, numattr);
263130a5e8faSwyllys 	if (cert_status == NULL)
263230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
263399ebb4caSwyllys 
263499ebb4caSwyllys 	/* Read in the response */
263530a5e8faSwyllys 	derbio = BIO_new_mem_buf(response->Data, response->Length);
263699ebb4caSwyllys 	if (!derbio) {
263799ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
263899ebb4caSwyllys 		return (ret);
263999ebb4caSwyllys 	}
264099ebb4caSwyllys 
264199ebb4caSwyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
264299ebb4caSwyllys 	if (resp == NULL) {
264399ebb4caSwyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
264499ebb4caSwyllys 		goto end;
264599ebb4caSwyllys 	}
264699ebb4caSwyllys 
264799ebb4caSwyllys 	/* Check the response status */
264899ebb4caSwyllys 	status = OCSP_response_status(resp);
264930a5e8faSwyllys 	*response_status = status;
265099ebb4caSwyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
265199ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
265299ebb4caSwyllys 		goto end;
265399ebb4caSwyllys 	}
265499ebb4caSwyllys 
265599ebb4caSwyllys #ifdef DEBUG
265699ebb4caSwyllys 	printf("Successfully checked the response file status.\n");
265799ebb4caSwyllys #endif /* DEBUG */
265899ebb4caSwyllys 
265999ebb4caSwyllys 	/* Extract basic response */
266099ebb4caSwyllys 	bs = OCSP_response_get1_basic(resp);
266199ebb4caSwyllys 	if (bs == NULL) {
266299ebb4caSwyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
266399ebb4caSwyllys 		goto end;
266499ebb4caSwyllys 	}
266599ebb4caSwyllys 
266699ebb4caSwyllys #ifdef DEBUG
266799ebb4caSwyllys 	printf("Successfully retrieved the basic response.\n");
266899ebb4caSwyllys #endif /* DEBUG */
266999ebb4caSwyllys 
267099ebb4caSwyllys 	/* Check the basic response signature if required */
267130a5e8faSwyllys 	ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
267230a5e8faSwyllys 	    (void *)&ignore_response_sign, NULL);
267330a5e8faSwyllys 	if (ret != KMF_OK)
267430a5e8faSwyllys 		ret = KMF_OK;
267530a5e8faSwyllys 
267630a5e8faSwyllys 	signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
267730a5e8faSwyllys 	    attrlist, numattr);
267830a5e8faSwyllys 
267930a5e8faSwyllys 	if (ignore_response_sign == B_FALSE) {
268099ebb4caSwyllys 		ret = check_response_signature(handle, bs,
268130a5e8faSwyllys 		    signer_cert, issuer_cert);
268299ebb4caSwyllys 		if (ret != KMF_OK)
268399ebb4caSwyllys 			goto end;
268499ebb4caSwyllys 	}
268599ebb4caSwyllys 
268699ebb4caSwyllys #ifdef DEBUG
268799ebb4caSwyllys 	printf("Successfully verified the response signature.\n");
268899ebb4caSwyllys #endif /* DEBUG */
268999ebb4caSwyllys 
269099ebb4caSwyllys 	/* Create a certid for the certificate in question */
269130a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
269299ebb4caSwyllys 	if (ret != KMF_OK) {
269399ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
269499ebb4caSwyllys 		goto end;
269599ebb4caSwyllys 	}
269699ebb4caSwyllys 
269799ebb4caSwyllys #ifdef DEBUG
269899ebb4caSwyllys 	printf("successfully created a certid for the cert.\n");
269999ebb4caSwyllys #endif /* DEBUG */
270099ebb4caSwyllys 
270199ebb4caSwyllys 	/* Find the index of the single response for the certid */
270299ebb4caSwyllys 	index = OCSP_resp_find(bs, id, -1);
270399ebb4caSwyllys 	if (index < 0) {
270499ebb4caSwyllys 		/* cound not find this certificate in the response */
270599ebb4caSwyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
270699ebb4caSwyllys 		goto end;
270799ebb4caSwyllys 	}
270899ebb4caSwyllys 
270999ebb4caSwyllys #ifdef DEBUG
271099ebb4caSwyllys 	printf("Successfully found the single response index for the cert.\n");
271199ebb4caSwyllys #endif /* DEBUG */
271299ebb4caSwyllys 
271399ebb4caSwyllys 	/* Retrieve the single response and get the cert status */
271499ebb4caSwyllys 	single = OCSP_resp_get0(bs, index);
271599ebb4caSwyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
271699ebb4caSwyllys 	    &nextupd);
271799ebb4caSwyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
271830a5e8faSwyllys 		*cert_status = OCSP_GOOD;
271999ebb4caSwyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
272030a5e8faSwyllys 		*cert_status = OCSP_UNKNOWN;
272199ebb4caSwyllys 	} else { /* revoked */
272230a5e8faSwyllys 		*cert_status = OCSP_REVOKED;
272330a5e8faSwyllys 		*response_reason = reason;
272499ebb4caSwyllys 	}
272599ebb4caSwyllys 	ret = KMF_OK;
272699ebb4caSwyllys 
272730a5e8faSwyllys 	/* resp. time is optional, so we don't care about the return code. */
272830a5e8faSwyllys 	(void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
272930a5e8faSwyllys 	    (void *)&response_lifetime, NULL);
273030a5e8faSwyllys 
273199ebb4caSwyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
273230a5e8faSwyllys 	    response_lifetime)) {
273399ebb4caSwyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
273499ebb4caSwyllys 		goto end;
273599ebb4caSwyllys 	}
273699ebb4caSwyllys 
273799ebb4caSwyllys #ifdef DEBUG
273899ebb4caSwyllys 	printf("Successfully verify the time.\n");
273999ebb4caSwyllys #endif /* DEBUG */
274099ebb4caSwyllys 
274199ebb4caSwyllys end:
274299ebb4caSwyllys 	if (derbio != NULL)
274399ebb4caSwyllys 		(void) BIO_free(derbio);
274499ebb4caSwyllys 
274599ebb4caSwyllys 	if (resp != NULL)
274699ebb4caSwyllys 		OCSP_RESPONSE_free(resp);
274799ebb4caSwyllys 
274899ebb4caSwyllys 	if (bs != NULL)
274999ebb4caSwyllys 		OCSP_BASICRESP_free(bs);
275099ebb4caSwyllys 
275199ebb4caSwyllys 	if (id != NULL)
275299ebb4caSwyllys 		OCSP_CERTID_free(id);
275399ebb4caSwyllys 
275499ebb4caSwyllys 	return (ret);
275599ebb4caSwyllys }
275699ebb4caSwyllys 
275799ebb4caSwyllys static KMF_RETURN
275899ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path,
275999ebb4caSwyllys 	KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
276099ebb4caSwyllys {
276199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
276230a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
276399ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
276499ebb4caSwyllys 
276599ebb4caSwyllys 	if (keyclass == KMF_ASYM_PRI ||
276699ebb4caSwyllys 	    keyclass == KMF_ASYM_PUB) {
276799ebb4caSwyllys 		pkey = openssl_load_key(handle, path);
276899ebb4caSwyllys 		if (pkey == NULL) {
276999ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
277099ebb4caSwyllys 		}
277199ebb4caSwyllys 		if (key != NULL) {
277299ebb4caSwyllys 			if (pkey->type == EVP_PKEY_RSA)
277399ebb4caSwyllys 				key->keyalg = KMF_RSA;
277499ebb4caSwyllys 			else if (pkey->type == EVP_PKEY_DSA)
277599ebb4caSwyllys 				key->keyalg = KMF_DSA;
277699ebb4caSwyllys 
277799ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
277899ebb4caSwyllys 			key->keyclass = keyclass;
277999ebb4caSwyllys 			key->keyp = (void *)pkey;
278099ebb4caSwyllys 			key->israw = FALSE;
2781*5b3e1433Swyllys 			if (path != NULL &&
2782*5b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
2783*5b3e1433Swyllys 				EVP_PKEY_free(pkey);
2784*5b3e1433Swyllys 				return (KMF_ERR_MEMORY);
2785*5b3e1433Swyllys 			}
278699ebb4caSwyllys 		} else {
278799ebb4caSwyllys 			EVP_PKEY_free(pkey);
278899ebb4caSwyllys 			pkey = NULL;
278999ebb4caSwyllys 		}
279099ebb4caSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
279199ebb4caSwyllys 		KMF_ENCODE_FORMAT fmt;
279299ebb4caSwyllys 		/*
279399ebb4caSwyllys 		 * If the file is a recognized format,
279499ebb4caSwyllys 		 * then it is NOT a symmetric key.
279599ebb4caSwyllys 		 */
279630a5e8faSwyllys 		rv = kmf_get_file_format(path, &fmt);
279799ebb4caSwyllys 		if (rv == KMF_OK || fmt != 0) {
279899ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
279999ebb4caSwyllys 		} else if (rv == KMF_ERR_ENCODING) {
280099ebb4caSwyllys 			/*
280199ebb4caSwyllys 			 * If we don't know the encoding,
280299ebb4caSwyllys 			 * it is probably  a symmetric key.
280399ebb4caSwyllys 			 */
280499ebb4caSwyllys 			rv = KMF_OK;
280530a5e8faSwyllys 		} else if (rv == KMF_ERR_OPEN_FILE) {
280630a5e8faSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
280799ebb4caSwyllys 		}
280899ebb4caSwyllys 
280999ebb4caSwyllys 		if (key != NULL) {
281099ebb4caSwyllys 			KMF_DATA keyvalue;
281199ebb4caSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
281299ebb4caSwyllys 			if (rkey == NULL) {
281399ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
281499ebb4caSwyllys 				goto out;
281599ebb4caSwyllys 			}
281699ebb4caSwyllys 
281799ebb4caSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
281830a5e8faSwyllys 			rv = kmf_read_input_file(handle, path, &keyvalue);
281999ebb4caSwyllys 			if (rv != KMF_OK)
282099ebb4caSwyllys 				goto out;
282199ebb4caSwyllys 
282299ebb4caSwyllys 			rkey->keydata.len = keyvalue.Length;
282399ebb4caSwyllys 			rkey->keydata.val = keyvalue.Data;
282499ebb4caSwyllys 
282599ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
282699ebb4caSwyllys 			key->keyclass = keyclass;
282799ebb4caSwyllys 			key->israw = TRUE;
282899ebb4caSwyllys 			key->keyp = (void *)rkey;
2829*5b3e1433Swyllys 			if (path != NULL &&
2830*5b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
2831*5b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
2832*5b3e1433Swyllys 			}
283399ebb4caSwyllys 		}
283499ebb4caSwyllys 	}
283599ebb4caSwyllys out:
283699ebb4caSwyllys 	if (rv != KMF_OK) {
283799ebb4caSwyllys 		if (rkey != NULL) {
283830a5e8faSwyllys 			kmf_free_raw_sym_key(rkey);
283999ebb4caSwyllys 		}
284099ebb4caSwyllys 		if (pkey != NULL)
284199ebb4caSwyllys 			EVP_PKEY_free(pkey);
284299ebb4caSwyllys 
284399ebb4caSwyllys 		if (key != NULL) {
284499ebb4caSwyllys 			key->keyalg = KMF_KEYALG_NONE;
284599ebb4caSwyllys 			key->keyclass = KMF_KEYCLASS_NONE;
284699ebb4caSwyllys 			key->keyp = NULL;
284799ebb4caSwyllys 		}
284899ebb4caSwyllys 	}
284999ebb4caSwyllys 
285099ebb4caSwyllys 	return (rv);
285199ebb4caSwyllys }
285299ebb4caSwyllys 
285399ebb4caSwyllys KMF_RETURN
285430a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle,
285530a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
285699ebb4caSwyllys {
285799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
285899ebb4caSwyllys 	char *fullpath = NULL;
2859f482c776Swyllys 	uint32_t maxkeys;
286030a5e8faSwyllys 	KMF_KEY_HANDLE *key;
286130a5e8faSwyllys 	uint32_t *numkeys;
286230a5e8faSwyllys 	KMF_KEY_CLASS keyclass;
286330a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
286430a5e8faSwyllys 	char *dirpath;
286530a5e8faSwyllys 	char *keyfile;
286699ebb4caSwyllys 
286730a5e8faSwyllys 	if (handle == NULL)
286899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
286999ebb4caSwyllys 
287030a5e8faSwyllys 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
287130a5e8faSwyllys 	if (numkeys == NULL)
287230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
287330a5e8faSwyllys 
287430a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
287530a5e8faSwyllys 	    (void *)&keyclass, NULL);
287630a5e8faSwyllys 	if (rv != KMF_OK)
287730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
287830a5e8faSwyllys 
287930a5e8faSwyllys 	if (keyclass != KMF_ASYM_PUB &&
288030a5e8faSwyllys 	    keyclass != KMF_ASYM_PRI &&
288130a5e8faSwyllys 	    keyclass != KMF_SYMMETRIC)
288299ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
288399ebb4caSwyllys 
288430a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
288530a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
288630a5e8faSwyllys 
288730a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
288899ebb4caSwyllys 
288999ebb4caSwyllys 	if (fullpath == NULL)
289099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
289199ebb4caSwyllys 
2892f482c776Swyllys 	maxkeys = *numkeys;
2893f482c776Swyllys 	if (maxkeys == 0)
2894f482c776Swyllys 		maxkeys = 0xFFFFFFFF;
289599ebb4caSwyllys 	*numkeys = 0;
289699ebb4caSwyllys 
289730a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
289830a5e8faSwyllys 	/* it is okay to have "keys" contains NULL */
289930a5e8faSwyllys 
290030a5e8faSwyllys 	/*
290130a5e8faSwyllys 	 * The caller may want a list of the raw key data as well.
290230a5e8faSwyllys 	 * Useful for importing keys from a file into other keystores.
290330a5e8faSwyllys 	 */
290430a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
290530a5e8faSwyllys 
290699ebb4caSwyllys 	if (isdir(fullpath)) {
290799ebb4caSwyllys 		DIR *dirp;
290899ebb4caSwyllys 		struct dirent *dp;
290999ebb4caSwyllys 		int n = 0;
291099ebb4caSwyllys 
291199ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
291299ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
291399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
291499ebb4caSwyllys 		}
291599ebb4caSwyllys 		rewinddir(dirp);
2916f482c776Swyllys 		while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
291799ebb4caSwyllys 			if (strcmp(dp->d_name, ".") &&
291899ebb4caSwyllys 			    strcmp(dp->d_name, "..")) {
291999ebb4caSwyllys 				char *fname;
292099ebb4caSwyllys 
292199ebb4caSwyllys 				fname = get_fullpath(fullpath,
292299ebb4caSwyllys 				    (char *)&dp->d_name);
292399ebb4caSwyllys 
292499ebb4caSwyllys 				rv = fetch_key(handle, fname,
292530a5e8faSwyllys 				    keyclass, key ? &key[n] : NULL);
292699ebb4caSwyllys 
292730a5e8faSwyllys 				if (rv == KMF_OK) {
292830a5e8faSwyllys 					if (key != NULL && rawkey != NULL)
292930a5e8faSwyllys 						rv = convertToRawKey(
293030a5e8faSwyllys 						    key[n].keyp, &rawkey[n]);
293199ebb4caSwyllys 					n++;
293230a5e8faSwyllys 				}
293399ebb4caSwyllys 
293499ebb4caSwyllys 				if (rv != KMF_OK || key == NULL)
293599ebb4caSwyllys 					free(fname);
293699ebb4caSwyllys 			}
293799ebb4caSwyllys 		}
293899ebb4caSwyllys 		(void) closedir(dirp);
293999ebb4caSwyllys 		free(fullpath);
294099ebb4caSwyllys 		(*numkeys) = n;
294199ebb4caSwyllys 	} else {
294230a5e8faSwyllys 		rv = fetch_key(handle, fullpath, keyclass, key);
294399ebb4caSwyllys 		if (rv == KMF_OK)
294499ebb4caSwyllys 			(*numkeys) = 1;
294599ebb4caSwyllys 
294699ebb4caSwyllys 		if (rv != KMF_OK || key == NULL)
294799ebb4caSwyllys 			free(fullpath);
294830a5e8faSwyllys 
294930a5e8faSwyllys 		if (rv == KMF_OK && key != NULL && rawkey != NULL) {
295030a5e8faSwyllys 			rv = convertToRawKey(key->keyp, rawkey);
295130a5e8faSwyllys 		}
295299ebb4caSwyllys 	}
295399ebb4caSwyllys 
2954f482c776Swyllys 	if (rv == KMF_OK && (*numkeys) == 0)
295599ebb4caSwyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
295699ebb4caSwyllys 
295799ebb4caSwyllys 	return (rv);
295899ebb4caSwyllys }
295999ebb4caSwyllys 
296099ebb4caSwyllys #define	HANDLE_PK12_ERROR { \
296199ebb4caSwyllys 	SET_ERROR(kmfh, ERR_get_error()); \
296299ebb4caSwyllys 	rv = KMF_ERR_ENCODING; \
296399ebb4caSwyllys 	goto out; \
296499ebb4caSwyllys }
296599ebb4caSwyllys 
2966*5b3e1433Swyllys static int
2967*5b3e1433Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
296899ebb4caSwyllys {
2969*5b3e1433Swyllys 	if (xcert != NULL && xcert->aux != NULL &&
2970*5b3e1433Swyllys 	    xcert->aux->alias != NULL) {
2971*5b3e1433Swyllys 		if (PKCS12_add_friendlyname_asc(bag,
2972*5b3e1433Swyllys 		    (const char *)xcert->aux->alias->data,
2973*5b3e1433Swyllys 		    xcert->aux->alias->length) == 0)
2974*5b3e1433Swyllys 			return (0);
2975*5b3e1433Swyllys 	}
2976*5b3e1433Swyllys 	return (1);
2977*5b3e1433Swyllys }
2978*5b3e1433Swyllys 
2979*5b3e1433Swyllys static PKCS7 *
2980*5b3e1433Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
2981*5b3e1433Swyllys 	uchar_t *keyid, unsigned int keyidlen)
2982*5b3e1433Swyllys {
298399ebb4caSwyllys 	PKCS12_SAFEBAG *bag = NULL;
298499ebb4caSwyllys 	PKCS7 *cert_authsafe = NULL;
2985*5b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack;
298699ebb4caSwyllys 
298799ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
298899ebb4caSwyllys 	if (bag_stack == NULL)
2989*5b3e1433Swyllys 		return (NULL);
299099ebb4caSwyllys 
299199ebb4caSwyllys 	/* Convert cert from X509 struct to PKCS#12 bag */
299299ebb4caSwyllys 	bag = PKCS12_x5092certbag(sslcert);
299399ebb4caSwyllys 	if (bag == NULL) {
2994*5b3e1433Swyllys 		goto out;
299599ebb4caSwyllys 	}
299699ebb4caSwyllys 
299799ebb4caSwyllys 	/* Add the key id to the certificate bag. */
2998*5b3e1433Swyllys 	if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
2999*5b3e1433Swyllys 		goto out;
300099ebb4caSwyllys 	}
300199ebb4caSwyllys 
3002*5b3e1433Swyllys 	if (!add_alias_to_bag(bag, sslcert))
3003*5b3e1433Swyllys 		goto out;
3004*5b3e1433Swyllys 
300599ebb4caSwyllys 	/* Pile it on the bag_stack. */
300699ebb4caSwyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
3007*5b3e1433Swyllys 		goto out;
300899ebb4caSwyllys 	}
300999ebb4caSwyllys 	/* Turn bag_stack of certs into encrypted authsafe. */
301099ebb4caSwyllys 	cert_authsafe = PKCS12_pack_p7encdata(
301199ebb4caSwyllys 	    NID_pbe_WithSHA1And40BitRC2_CBC,
301234acef67Swyllys 	    cred->cred, cred->credlen, NULL, 0,
301334acef67Swyllys 	    PKCS12_DEFAULT_ITER, bag_stack);
301499ebb4caSwyllys 
3015*5b3e1433Swyllys out:
3016*5b3e1433Swyllys 	if (bag_stack != NULL)
301799ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
301899ebb4caSwyllys 
3019*5b3e1433Swyllys 	return (cert_authsafe);
302099ebb4caSwyllys }
3021*5b3e1433Swyllys 
3022*5b3e1433Swyllys static PKCS7 *
3023*5b3e1433Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
3024*5b3e1433Swyllys 	uchar_t *keyid,  unsigned int keyidlen,
3025*5b3e1433Swyllys 	char *label, int label_len)
3026*5b3e1433Swyllys {
3027*5b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
3028*5b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
3029*5b3e1433Swyllys 	PKCS12_SAFEBAG *bag = NULL;
3030*5b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
3031*5b3e1433Swyllys 
303299ebb4caSwyllys 	p8 = EVP_PKEY2PKCS8(pkey);
303399ebb4caSwyllys 	if (p8 == NULL) {
3034*5b3e1433Swyllys 		return (NULL);
303599ebb4caSwyllys 	}
303699ebb4caSwyllys 	/* Put the shrouded key into a PKCS#12 bag. */
303799ebb4caSwyllys 	bag = PKCS12_MAKE_SHKEYBAG(
303899ebb4caSwyllys 	    NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
303999ebb4caSwyllys 	    cred->cred, cred->credlen,
304099ebb4caSwyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, p8);
304199ebb4caSwyllys 
304299ebb4caSwyllys 	/* Clean up the PKCS#8 shrouded key, don't need it now. */
304399ebb4caSwyllys 	PKCS8_PRIV_KEY_INFO_free(p8);
304499ebb4caSwyllys 	p8 = NULL;
304599ebb4caSwyllys 
304699ebb4caSwyllys 	if (bag == NULL) {
3047*5b3e1433Swyllys 		return (NULL);
304899ebb4caSwyllys 	}
3049*5b3e1433Swyllys 	if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
3050*5b3e1433Swyllys 		goto out;
3051*5b3e1433Swyllys 	if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
3052*5b3e1433Swyllys 		goto out;
3053*5b3e1433Swyllys 
305499ebb4caSwyllys 	/* Start a PKCS#12 safebag container for the private key. */
305599ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
3056*5b3e1433Swyllys 	if (bag_stack == NULL)
3057*5b3e1433Swyllys 		goto out;
305899ebb4caSwyllys 
305999ebb4caSwyllys 	/* Pile on the private key on the bag_stack. */
3060*5b3e1433Swyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
3061*5b3e1433Swyllys 		goto out;
3062*5b3e1433Swyllys 
306399ebb4caSwyllys 	key_authsafe = PKCS12_pack_p7data(bag_stack);
306499ebb4caSwyllys 
3065*5b3e1433Swyllys out:
3066*5b3e1433Swyllys 	if (bag_stack != NULL)
306799ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
306899ebb4caSwyllys 	bag_stack = NULL;
3069*5b3e1433Swyllys 	return (key_authsafe);
307099ebb4caSwyllys }
307199ebb4caSwyllys 
307299ebb4caSwyllys static EVP_PKEY *
307399ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
307499ebb4caSwyllys {
307599ebb4caSwyllys 	RSA		*rsa = NULL;
307699ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
307799ebb4caSwyllys 
307899ebb4caSwyllys 	if ((rsa = RSA_new()) == NULL)
307999ebb4caSwyllys 		return (NULL);
308099ebb4caSwyllys 
308199ebb4caSwyllys 	if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL)
308299ebb4caSwyllys 		return (NULL);
308399ebb4caSwyllys 
308499ebb4caSwyllys 	if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) ==
308599ebb4caSwyllys 	    NULL)
308699ebb4caSwyllys 		return (NULL);
308799ebb4caSwyllys 
308899ebb4caSwyllys 	if (key->priexp.val != NULL)
308999ebb4caSwyllys 		if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len,
309099ebb4caSwyllys 		    rsa->d)) == NULL)
309199ebb4caSwyllys 			return (NULL);
309299ebb4caSwyllys 
309399ebb4caSwyllys 	if (key->prime1.val != NULL)
309499ebb4caSwyllys 		if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len,
309599ebb4caSwyllys 		    rsa->p)) == NULL)
309699ebb4caSwyllys 			return (NULL);
309799ebb4caSwyllys 
309899ebb4caSwyllys 	if (key->prime2.val != NULL)
309999ebb4caSwyllys 		if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len,
310099ebb4caSwyllys 		    rsa->q)) == NULL)
310199ebb4caSwyllys 			return (NULL);
310299ebb4caSwyllys 
310399ebb4caSwyllys 	if (key->exp1.val != NULL)
310499ebb4caSwyllys 		if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len,
310599ebb4caSwyllys 		    rsa->dmp1)) == NULL)
310699ebb4caSwyllys 			return (NULL);
310799ebb4caSwyllys 
310899ebb4caSwyllys 	if (key->exp2.val != NULL)
310999ebb4caSwyllys 		if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len,
311099ebb4caSwyllys 		    rsa->dmq1)) == NULL)
311199ebb4caSwyllys 			return (NULL);
311299ebb4caSwyllys 
311399ebb4caSwyllys 	if (key->coef.val != NULL)
311499ebb4caSwyllys 		if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len,
311599ebb4caSwyllys 		    rsa->iqmp)) == NULL)
311699ebb4caSwyllys 			return (NULL);
311799ebb4caSwyllys 
311899ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
311999ebb4caSwyllys 		return (NULL);
312099ebb4caSwyllys 
312199ebb4caSwyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
312299ebb4caSwyllys 
312399ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
312499ebb4caSwyllys 	RSA_free(rsa);
312599ebb4caSwyllys 
312699ebb4caSwyllys 	return (newkey);
312799ebb4caSwyllys }
312899ebb4caSwyllys 
312999ebb4caSwyllys static EVP_PKEY *
313099ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
313199ebb4caSwyllys {
313299ebb4caSwyllys 	DSA		*dsa = NULL;
313399ebb4caSwyllys 	EVP_PKEY 	*newkey = NULL;
313499ebb4caSwyllys 
313599ebb4caSwyllys 	if ((dsa = DSA_new()) == NULL)
313699ebb4caSwyllys 		return (NULL);
313799ebb4caSwyllys 
313899ebb4caSwyllys 	if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len,
313999ebb4caSwyllys 	    dsa->p)) == NULL)
314099ebb4caSwyllys 		return (NULL);
314199ebb4caSwyllys 
314299ebb4caSwyllys 	if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len,
314399ebb4caSwyllys 	    dsa->q)) == NULL)
314499ebb4caSwyllys 		return (NULL);
314599ebb4caSwyllys 
314699ebb4caSwyllys 	if ((dsa->g = BN_bin2bn(key->base.val, key->base.len,
314799ebb4caSwyllys 	    dsa->g)) == NULL)
314899ebb4caSwyllys 		return (NULL);
314999ebb4caSwyllys 
315099ebb4caSwyllys 	if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len,
315199ebb4caSwyllys 	    dsa->priv_key)) == NULL)
315299ebb4caSwyllys 		return (NULL);
315399ebb4caSwyllys 
315430a5e8faSwyllys 	if (key->pubvalue.val != NULL) {
315530a5e8faSwyllys 		if ((dsa->pub_key = BN_bin2bn(key->pubvalue.val,
315630a5e8faSwyllys 		    key->pubvalue.len, dsa->pub_key)) == NULL)
315730a5e8faSwyllys 			return (NULL);
315830a5e8faSwyllys 	}
315930a5e8faSwyllys 
316099ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
316199ebb4caSwyllys 		return (NULL);
316299ebb4caSwyllys 
316399ebb4caSwyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
316499ebb4caSwyllys 
316599ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
316699ebb4caSwyllys 	DSA_free(dsa);
316799ebb4caSwyllys 	return (newkey);
316899ebb4caSwyllys }
316999ebb4caSwyllys 
3170*5b3e1433Swyllys static EVP_PKEY *
3171*5b3e1433Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key)
3172*5b3e1433Swyllys {
3173*5b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
3174*5b3e1433Swyllys 	KMF_RAW_KEY_DATA *rawkey;
3175*5b3e1433Swyllys 	ASN1_TYPE *attr = NULL;
3176*5b3e1433Swyllys 	KMF_RETURN ret;
3177*5b3e1433Swyllys 
3178*5b3e1433Swyllys 	if (key == NULL || !key->israw)
3179*5b3e1433Swyllys 		return (NULL);
3180*5b3e1433Swyllys 
3181*5b3e1433Swyllys 	rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
3182*5b3e1433Swyllys 	if (rawkey->keytype == KMF_RSA) {
3183*5b3e1433Swyllys 		pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
3184*5b3e1433Swyllys 	} else if (rawkey->keytype == KMF_DSA) {
3185*5b3e1433Swyllys 		pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
3186*5b3e1433Swyllys 	} else {
3187*5b3e1433Swyllys 		/* wrong kind of key */
3188*5b3e1433Swyllys 		return (NULL);
3189*5b3e1433Swyllys 	}
3190*5b3e1433Swyllys 
3191*5b3e1433Swyllys 	if (rawkey->label != NULL) {
3192*5b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
3193*5b3e1433Swyllys 			EVP_PKEY_free(pkey);
3194*5b3e1433Swyllys 			return (NULL);
3195*5b3e1433Swyllys 		}
3196*5b3e1433Swyllys 		attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
3197*5b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
3198*5b3e1433Swyllys 		    strlen(rawkey->label));
3199*5b3e1433Swyllys 		attr->type = V_ASN1_BMPSTRING;
3200*5b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.bmpstring;
3201*5b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
3202*5b3e1433Swyllys 		if (ret != KMF_OK) {
3203*5b3e1433Swyllys 			EVP_PKEY_free(pkey);
3204*5b3e1433Swyllys 			ASN1_TYPE_free(attr);
3205*5b3e1433Swyllys 			return (NULL);
3206*5b3e1433Swyllys 		}
3207*5b3e1433Swyllys 	}
3208*5b3e1433Swyllys 	if (rawkey->id.Data != NULL) {
3209*5b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
3210*5b3e1433Swyllys 			EVP_PKEY_free(pkey);
3211*5b3e1433Swyllys 			return (NULL);
3212*5b3e1433Swyllys 		}
3213*5b3e1433Swyllys 		attr->value.octet_string =
3214*5b3e1433Swyllys 		    ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
3215*5b3e1433Swyllys 		attr->type = V_ASN1_OCTET_STRING;
3216*5b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.octet_string,
3217*5b3e1433Swyllys 		    rawkey->id.Data, rawkey->id.Length);
3218*5b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.octet_string;
3219*5b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
3220*5b3e1433Swyllys 		if (ret != KMF_OK) {
3221*5b3e1433Swyllys 			EVP_PKEY_free(pkey);
3222*5b3e1433Swyllys 			ASN1_TYPE_free(attr);
3223*5b3e1433Swyllys 			return (NULL);
3224*5b3e1433Swyllys 		}
3225*5b3e1433Swyllys 	}
3226*5b3e1433Swyllys 	return (pkey);
3227*5b3e1433Swyllys }
3228*5b3e1433Swyllys 
3229*5b3e1433Swyllys /*
3230*5b3e1433Swyllys  * Search a list of private keys to find one that goes with the certificate.
3231*5b3e1433Swyllys  */
3232*5b3e1433Swyllys static EVP_PKEY *
3233*5b3e1433Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
3234*5b3e1433Swyllys {
3235*5b3e1433Swyllys 	int i;
3236*5b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
3237*5b3e1433Swyllys 
3238*5b3e1433Swyllys 	if (numkeys == 0 || keylist == NULL || xcert == NULL)
3239*5b3e1433Swyllys 		return (NULL);
3240*5b3e1433Swyllys 	for (i = 0; i < numkeys; i++) {
3241*5b3e1433Swyllys 		if (keylist[i].israw)
3242*5b3e1433Swyllys 			pkey = raw_key_to_pkey(&keylist[i]);
3243*5b3e1433Swyllys 		else
3244*5b3e1433Swyllys 			pkey = (EVP_PKEY *)keylist[i].keyp;
3245*5b3e1433Swyllys 		if (pkey != NULL) {
3246*5b3e1433Swyllys 			if (X509_check_private_key(xcert, pkey)) {
3247*5b3e1433Swyllys 				return (pkey);
3248*5b3e1433Swyllys 			} else {
3249*5b3e1433Swyllys 				EVP_PKEY_free(pkey);
3250*5b3e1433Swyllys 				pkey = NULL;
3251*5b3e1433Swyllys 			}
3252*5b3e1433Swyllys 		}
3253*5b3e1433Swyllys 	}
3254*5b3e1433Swyllys 	return (pkey);
3255*5b3e1433Swyllys }
3256*5b3e1433Swyllys 
325799ebb4caSwyllys static KMF_RETURN
3258*5b3e1433Swyllys local_export_pk12(KMF_HANDLE_T handle,
325999ebb4caSwyllys 	KMF_CREDENTIAL *cred,
326099ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
326199ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
326299ebb4caSwyllys 	char *filename)
326399ebb4caSwyllys {
326499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
326599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
326699ebb4caSwyllys 	BIO *bio = NULL;
3267*5b3e1433Swyllys 	PKCS7 *cert_authsafe = NULL;
3268*5b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
3269*5b3e1433Swyllys 	STACK_OF(PKCS7) *authsafe_stack = NULL;
3270*5b3e1433Swyllys 	PKCS12 *p12_elem = NULL;
327199ebb4caSwyllys 	int i;
327299ebb4caSwyllys 
3273*5b3e1433Swyllys 	if (numcerts == 0 && numkeys == 0)
3274*5b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
3275*5b3e1433Swyllys 
327699ebb4caSwyllys 	/*
327799ebb4caSwyllys 	 * Open the output file.
327899ebb4caSwyllys 	 */
327999ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
328099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
328199ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
328299ebb4caSwyllys 		goto cleanup;
328399ebb4caSwyllys 	}
328499ebb4caSwyllys 
3285*5b3e1433Swyllys 	/* Start a PKCS#7 stack. */
3286*5b3e1433Swyllys 	authsafe_stack = sk_PKCS7_new_null();
3287*5b3e1433Swyllys 	if (authsafe_stack == NULL) {
3288*5b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
3289*5b3e1433Swyllys 		goto cleanup;
3290*5b3e1433Swyllys 	}
3291*5b3e1433Swyllys 	if (numcerts > 0) {
329299ebb4caSwyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
329399ebb4caSwyllys 			const uchar_t *p = certlist[i].certificate.Data;
329499ebb4caSwyllys 			long len = certlist[i].certificate.Length;
3295*5b3e1433Swyllys 			X509 *xcert = NULL;
3296*5b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
3297*5b3e1433Swyllys 			unsigned char keyid[EVP_MAX_MD_SIZE];
3298*5b3e1433Swyllys 			unsigned int keyidlen = 0;
329999ebb4caSwyllys 
330099ebb4caSwyllys 			xcert = d2i_X509(NULL, &p, len);
330199ebb4caSwyllys 			if (xcert == NULL) {
330299ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
330399ebb4caSwyllys 				rv = KMF_ERR_ENCODING;
330499ebb4caSwyllys 			}
3305*5b3e1433Swyllys 			if (certlist[i].kmf_private.label != NULL) {
3306*5b3e1433Swyllys 				/* Set alias attribute */
3307*5b3e1433Swyllys 				(void) X509_alias_set1(xcert,
3308*5b3e1433Swyllys 				    (uchar_t *)certlist[i].kmf_private.label,
3309*5b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label));
3310*5b3e1433Swyllys 			}
3311*5b3e1433Swyllys 			/* Check if there is a key corresponding to this cert */
3312*5b3e1433Swyllys 			pkey = find_matching_key(xcert, numkeys, keylist);
3313*5b3e1433Swyllys 
3314*5b3e1433Swyllys 			/*
3315*5b3e1433Swyllys 			 * If key is found, get fingerprint and create a
3316*5b3e1433Swyllys 			 * safebag.
3317*5b3e1433Swyllys 			 */
3318*5b3e1433Swyllys 			if (pkey != NULL) {
3319*5b3e1433Swyllys 				(void) X509_digest(xcert, EVP_sha1(),
3320*5b3e1433Swyllys 				    keyid, &keyidlen);
3321*5b3e1433Swyllys 				key_authsafe = add_key_to_safe(pkey, cred,
3322*5b3e1433Swyllys 				    keyid, keyidlen,
3323*5b3e1433Swyllys 				    certlist[i].kmf_private.label,
3324*5b3e1433Swyllys 				    (certlist[i].kmf_private.label ?
3325*5b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label) : 0));
3326*5b3e1433Swyllys 
3327*5b3e1433Swyllys 				if (key_authsafe == NULL) {
3328*5b3e1433Swyllys 					X509_free(xcert);
3329*5b3e1433Swyllys 					EVP_PKEY_free(pkey);
3330*5b3e1433Swyllys 					goto cleanup;
3331*5b3e1433Swyllys 				}
3332*5b3e1433Swyllys 				/* Put the key safe into the Auth Safe */
3333*5b3e1433Swyllys 				if (!sk_PKCS7_push(authsafe_stack,
3334*5b3e1433Swyllys 				    key_authsafe)) {
3335*5b3e1433Swyllys 					X509_free(xcert);
3336*5b3e1433Swyllys 					EVP_PKEY_free(pkey);
3337*5b3e1433Swyllys 					goto cleanup;
3338*5b3e1433Swyllys 				}
3339*5b3e1433Swyllys 			}
3340*5b3e1433Swyllys 
3341*5b3e1433Swyllys 			/* create a certificate safebag */
3342*5b3e1433Swyllys 			cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
3343*5b3e1433Swyllys 			    keyidlen);
3344*5b3e1433Swyllys 			if (cert_authsafe == NULL) {
3345*5b3e1433Swyllys 				X509_free(xcert);
3346*5b3e1433Swyllys 				EVP_PKEY_free(pkey);
3347*5b3e1433Swyllys 				goto cleanup;
3348*5b3e1433Swyllys 			}
3349*5b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
3350*5b3e1433Swyllys 				X509_free(xcert);
3351*5b3e1433Swyllys 				EVP_PKEY_free(pkey);
3352*5b3e1433Swyllys 				goto cleanup;
3353*5b3e1433Swyllys 			}
3354*5b3e1433Swyllys 
335599ebb4caSwyllys 			X509_free(xcert);
335699ebb4caSwyllys 			if (pkey)
335799ebb4caSwyllys 				EVP_PKEY_free(pkey);
335899ebb4caSwyllys 		}
3359*5b3e1433Swyllys 	} else if (numcerts == 0 && numkeys > 0) {
3360*5b3e1433Swyllys 		/*
3361*5b3e1433Swyllys 		 * If only adding keys to the file.
3362*5b3e1433Swyllys 		 */
3363*5b3e1433Swyllys 		for (i = 0; i < numkeys; i++) {
3364*5b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
3365*5b3e1433Swyllys 
3366*5b3e1433Swyllys 			if (keylist[i].israw)
3367*5b3e1433Swyllys 				pkey = raw_key_to_pkey(&keylist[i]);
3368*5b3e1433Swyllys 			else
3369*5b3e1433Swyllys 				pkey = (EVP_PKEY *)keylist[i].keyp;
3370*5b3e1433Swyllys 
3371*5b3e1433Swyllys 			if (pkey == NULL)
3372*5b3e1433Swyllys 				continue;
3373*5b3e1433Swyllys 
3374*5b3e1433Swyllys 			key_authsafe = add_key_to_safe(pkey, cred,
3375*5b3e1433Swyllys 			    NULL, 0, NULL, 0);
3376*5b3e1433Swyllys 
3377*5b3e1433Swyllys 			if (key_authsafe == NULL) {
3378*5b3e1433Swyllys 				EVP_PKEY_free(pkey);
3379*5b3e1433Swyllys 				goto cleanup;
3380*5b3e1433Swyllys 			}
3381*5b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
3382*5b3e1433Swyllys 				EVP_PKEY_free(pkey);
3383*5b3e1433Swyllys 				goto cleanup;
3384*5b3e1433Swyllys 			}
3385*5b3e1433Swyllys 		}
3386*5b3e1433Swyllys 	}
3387*5b3e1433Swyllys 	p12_elem = PKCS12_init(NID_pkcs7_data);
3388*5b3e1433Swyllys 	if (p12_elem == NULL) {
3389*5b3e1433Swyllys 		goto cleanup;
339099ebb4caSwyllys 	}
339199ebb4caSwyllys 
3392*5b3e1433Swyllys 	/* Put the PKCS#7 stack into the PKCS#12 element. */
3393*5b3e1433Swyllys 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
3394*5b3e1433Swyllys 		goto cleanup;
3395*5b3e1433Swyllys 	}
3396*5b3e1433Swyllys 
3397*5b3e1433Swyllys 	/* Set the integrity MAC on the PKCS#12 element. */
3398*5b3e1433Swyllys 	if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
3399*5b3e1433Swyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
3400*5b3e1433Swyllys 		goto cleanup;
3401*5b3e1433Swyllys 	}
3402*5b3e1433Swyllys 
3403*5b3e1433Swyllys 	/* Write the PKCS#12 element to the export file. */
3404*5b3e1433Swyllys 	if (!i2d_PKCS12_bio(bio, p12_elem)) {
3405*5b3e1433Swyllys 		goto cleanup;
3406*5b3e1433Swyllys 	}
3407*5b3e1433Swyllys 	PKCS12_free(p12_elem);
3408*5b3e1433Swyllys 
340999ebb4caSwyllys cleanup:
3410*5b3e1433Swyllys 	/* Clear away the PKCS#7 stack, we're done with it. */
3411*5b3e1433Swyllys 	if (authsafe_stack)
3412*5b3e1433Swyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
341399ebb4caSwyllys 
341499ebb4caSwyllys 	if (bio != NULL)
341599ebb4caSwyllys 		(void) BIO_free_all(bio);
341699ebb4caSwyllys 
341799ebb4caSwyllys 	return (rv);
341899ebb4caSwyllys }
341999ebb4caSwyllys 
342099ebb4caSwyllys KMF_RETURN
342130a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
342230a5e8faSwyllys     KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
342330a5e8faSwyllys     KMF_CREDENTIAL *p12cred, char *filename)
342430a5e8faSwyllys {
342530a5e8faSwyllys 	KMF_RETURN rv;
342630a5e8faSwyllys 
342730a5e8faSwyllys 	if (certlist == NULL && keylist == NULL)
342830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
342930a5e8faSwyllys 
3430*5b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, numcerts, certlist,
343130a5e8faSwyllys 	    numkeys, keylist, filename);
343230a5e8faSwyllys 
343330a5e8faSwyllys 	return (rv);
343430a5e8faSwyllys }
343530a5e8faSwyllys 
343630a5e8faSwyllys KMF_RETURN
343730a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
343899ebb4caSwyllys {
343999ebb4caSwyllys 	KMF_RETURN rv;
344099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
344199ebb4caSwyllys 	char *fullpath = NULL;
344230a5e8faSwyllys 	char *dirpath = NULL;
344330a5e8faSwyllys 	char *certfile = NULL;
344430a5e8faSwyllys 	char *keyfile = NULL;
344530a5e8faSwyllys 	char *filename = NULL;
344630a5e8faSwyllys 	KMF_CREDENTIAL *p12cred = NULL;
3447*5b3e1433Swyllys 	KMF_X509_DER_CERT certdata;
3448*5b3e1433Swyllys 	KMF_KEY_HANDLE key;
3449*5b3e1433Swyllys 	int gotkey = 0;
3450*5b3e1433Swyllys 	int gotcert = 0;
345130a5e8faSwyllys 
345230a5e8faSwyllys 	if (handle == NULL)
345330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
345499ebb4caSwyllys 
345599ebb4caSwyllys 	/*
345699ebb4caSwyllys 	 *  First, find the certificate.
345799ebb4caSwyllys 	 */
345830a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
345930a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
346030a5e8faSwyllys 	if (certfile != NULL) {
346130a5e8faSwyllys 		fullpath = get_fullpath(dirpath, certfile);
346299ebb4caSwyllys 		if (fullpath == NULL)
346399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
346499ebb4caSwyllys 
346599ebb4caSwyllys 		if (isdir(fullpath)) {
346699ebb4caSwyllys 			free(fullpath);
346799ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
346899ebb4caSwyllys 		}
346999ebb4caSwyllys 
3470*5b3e1433Swyllys 		(void) memset(&certdata, 0, sizeof (certdata));
3471*5b3e1433Swyllys 		rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL,
3472*5b3e1433Swyllys 		    fullpath, &certdata.certificate);
347399ebb4caSwyllys 		if (rv != KMF_OK)
347499ebb4caSwyllys 			goto end;
347530a5e8faSwyllys 
3476*5b3e1433Swyllys 		gotcert++;
3477*5b3e1433Swyllys 		certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
347830a5e8faSwyllys 		free(fullpath);
347999ebb4caSwyllys 	}
348099ebb4caSwyllys 
348199ebb4caSwyllys 	/*
348299ebb4caSwyllys 	 * Now find the private key.
348399ebb4caSwyllys 	 */
348430a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
348530a5e8faSwyllys 	if (keyfile != NULL) {
348630a5e8faSwyllys 		fullpath = get_fullpath(dirpath, keyfile);
348799ebb4caSwyllys 		if (fullpath == NULL)
348899ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
348999ebb4caSwyllys 
349099ebb4caSwyllys 		if (isdir(fullpath)) {
349199ebb4caSwyllys 			free(fullpath);
349299ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
349399ebb4caSwyllys 		}
349499ebb4caSwyllys 
3495*5b3e1433Swyllys 		(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
3496*5b3e1433Swyllys 		rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
3497*5b3e1433Swyllys 		if (rv != KMF_OK)
349899ebb4caSwyllys 			goto end;
3499*5b3e1433Swyllys 		gotkey++;
350099ebb4caSwyllys 	}
350199ebb4caSwyllys 
350299ebb4caSwyllys 	/*
350399ebb4caSwyllys 	 * Open the output file.
350499ebb4caSwyllys 	 */
350530a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
350630a5e8faSwyllys 	    numattr);
350730a5e8faSwyllys 	if (filename == NULL) {
350830a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
350930a5e8faSwyllys 		goto end;
351030a5e8faSwyllys 	}
351130a5e8faSwyllys 
351299ebb4caSwyllys 	/* Stick the key and the cert into a PKCS#12 file */
351330a5e8faSwyllys 	p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
351430a5e8faSwyllys 	if (p12cred == NULL) {
351530a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
351630a5e8faSwyllys 		goto end;
351730a5e8faSwyllys 	}
351830a5e8faSwyllys 
3519*5b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, 1, &certdata,
3520*5b3e1433Swyllys 	    1, &key, filename);
352199ebb4caSwyllys 
352299ebb4caSwyllys end:
352399ebb4caSwyllys 	if (fullpath)
352499ebb4caSwyllys 		free(fullpath);
352599ebb4caSwyllys 
3526*5b3e1433Swyllys 	if (gotcert)
3527*5b3e1433Swyllys 		kmf_free_kmf_cert(handle, &certdata);
3528*5b3e1433Swyllys 	if (gotkey)
3529*5b3e1433Swyllys 		kmf_free_kmf_key(handle, &key);
353099ebb4caSwyllys 	return (rv);
353199ebb4caSwyllys }
353299ebb4caSwyllys 
353371593db2Swyllys /*
353471593db2Swyllys  * Helper function to extract keys and certificates from
353571593db2Swyllys  * a single PEM file.  Typically the file should contain a
353671593db2Swyllys  * private key and an associated public key wrapped in an x509 cert.
353771593db2Swyllys  * However, the file may be just a list of X509 certs with no keys.
353871593db2Swyllys  */
353971593db2Swyllys static KMF_RETURN
354030a5e8faSwyllys extract_pem(KMF_HANDLE *kmfh,
354130a5e8faSwyllys 	char *issuer, char *subject, KMF_BIGINT *serial,
354202744e81Swyllys 	char *filename, CK_UTF8CHAR *pin,
354371593db2Swyllys 	CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
354471593db2Swyllys 	int *numcerts)
354571593db2Swyllys /* ARGSUSED */
354671593db2Swyllys {
354771593db2Swyllys 	KMF_RETURN rv = KMF_OK;
354871593db2Swyllys 	FILE *fp;
354934acef67Swyllys 	STACK_OF(X509_INFO) *x509_info_stack = NULL;
355002744e81Swyllys 	int i, ncerts = 0, matchcerts = 0;
355171593db2Swyllys 	EVP_PKEY *pkey = NULL;
355271593db2Swyllys 	X509_INFO *info;
355371593db2Swyllys 	X509 *x;
3554*5b3e1433Swyllys 	X509_INFO **cert_infos = NULL;
355571593db2Swyllys 	KMF_DATA *certlist = NULL;
355671593db2Swyllys 
355771593db2Swyllys 	if (priv_key)
355871593db2Swyllys 		*priv_key = NULL;
355971593db2Swyllys 	if (certs)
356071593db2Swyllys 		*certs = NULL;
356171593db2Swyllys 	fp = fopen(filename, "r");
3562*5b3e1433Swyllys 	if (fp == NULL)
356371593db2Swyllys 		return (KMF_ERR_OPEN_FILE);
3564*5b3e1433Swyllys 
356571593db2Swyllys 	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
356671593db2Swyllys 	if (x509_info_stack == NULL) {
356771593db2Swyllys 		(void) fclose(fp);
356871593db2Swyllys 		return (KMF_ERR_ENCODING);
356971593db2Swyllys 	}
3570*5b3e1433Swyllys 	cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
3571*5b3e1433Swyllys 	    sizeof (X509_INFO *));
3572*5b3e1433Swyllys 	if (cert_infos == NULL) {
3573*5b3e1433Swyllys 		(void) fclose(fp);
3574*5b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
3575*5b3e1433Swyllys 		goto err;
3576*5b3e1433Swyllys 	}
357771593db2Swyllys 
3578*5b3e1433Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
357971593db2Swyllys 		/* LINTED */
358034acef67Swyllys 		cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
358171593db2Swyllys 		ncerts++;
358271593db2Swyllys 	}
358371593db2Swyllys 
358471593db2Swyllys 	if (ncerts == 0) {
358571593db2Swyllys 		(void) fclose(fp);
358634acef67Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
358734acef67Swyllys 		goto err;
358871593db2Swyllys 	}
358971593db2Swyllys 
359071593db2Swyllys 	if (priv_key != NULL) {
359171593db2Swyllys 		rewind(fp);
359271593db2Swyllys 		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
359371593db2Swyllys 	}
359471593db2Swyllys 	(void) fclose(fp);
359571593db2Swyllys 
359671593db2Swyllys 	x = cert_infos[ncerts - 1]->x509;
359771593db2Swyllys 	/*
359871593db2Swyllys 	 * Make sure the private key matchs the last cert in the file.
359971593db2Swyllys 	 */
360071593db2Swyllys 	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
360171593db2Swyllys 		EVP_PKEY_free(pkey);
360234acef67Swyllys 		rv = KMF_ERR_KEY_MISMATCH;
360334acef67Swyllys 		goto err;
360471593db2Swyllys 	}
360571593db2Swyllys 
360671593db2Swyllys 	certlist = (KMF_DATA *)malloc(ncerts * sizeof (KMF_DATA));
360771593db2Swyllys 	if (certlist == NULL) {
360871593db2Swyllys 		if (pkey != NULL)
360971593db2Swyllys 			EVP_PKEY_free(pkey);
361034acef67Swyllys 		rv = KMF_ERR_MEMORY;
361134acef67Swyllys 		goto err;
361271593db2Swyllys 	}
361371593db2Swyllys 
361471593db2Swyllys 	/*
361571593db2Swyllys 	 * Convert all of the certs to DER format.
361671593db2Swyllys 	 */
361702744e81Swyllys 	matchcerts = 0;
361871593db2Swyllys 	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
361902744e81Swyllys 		boolean_t match = FALSE;
362071593db2Swyllys 		info =  cert_infos[ncerts - 1 - i];
362171593db2Swyllys 
362230a5e8faSwyllys 		rv = check_cert(info->x509, issuer, subject, serial, &match);
362302744e81Swyllys 		if (rv != KMF_OK || match != TRUE) {
362402744e81Swyllys 			rv = KMF_OK;
362502744e81Swyllys 			continue;
362602744e81Swyllys 		}
362702744e81Swyllys 
362802744e81Swyllys 		rv = ssl_cert2KMFDATA(kmfh, info->x509,
362902744e81Swyllys 			&certlist[matchcerts++]);
363071593db2Swyllys 
363171593db2Swyllys 		if (rv != KMF_OK) {
363271593db2Swyllys 			free(certlist);
363371593db2Swyllys 			certlist = NULL;
363402744e81Swyllys 			ncerts = matchcerts = 0;
363571593db2Swyllys 		}
363671593db2Swyllys 	}
363771593db2Swyllys 
363871593db2Swyllys 	if (numcerts != NULL)
363902744e81Swyllys 		*numcerts = matchcerts;
364071593db2Swyllys 	if (certs != NULL)
364171593db2Swyllys 		*certs = certlist;
364271593db2Swyllys 
364371593db2Swyllys 	if (priv_key == NULL && pkey != NULL)
364471593db2Swyllys 		EVP_PKEY_free(pkey);
364571593db2Swyllys 	else if (priv_key != NULL && pkey != NULL)
364671593db2Swyllys 		*priv_key = pkey;
364771593db2Swyllys 
364834acef67Swyllys err:
364934acef67Swyllys 	/* Cleanup the stack of X509 info records */
365034acef67Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
365134acef67Swyllys 		/*LINTED*/
365234acef67Swyllys 		info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
365334acef67Swyllys 		X509_INFO_free(info);
365434acef67Swyllys 	}
365534acef67Swyllys 	if (x509_info_stack)
365634acef67Swyllys 		sk_X509_INFO_free(x509_info_stack);
365734acef67Swyllys 
3658*5b3e1433Swyllys 	if (cert_infos != NULL)
3659*5b3e1433Swyllys 		free(cert_infos);
3660*5b3e1433Swyllys 
366171593db2Swyllys 	return (rv);
366271593db2Swyllys }
366371593db2Swyllys 
3664*5b3e1433Swyllys static KMF_RETURN
3665*5b3e1433Swyllys openssl_parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
3666*5b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
3667*5b3e1433Swyllys {
3668*5b3e1433Swyllys 	KMF_RETURN ret;
3669*5b3e1433Swyllys 	int i;
3670*5b3e1433Swyllys 
3671*5b3e1433Swyllys 	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
3672*5b3e1433Swyllys 		/*LINTED*/
3673*5b3e1433Swyllys 		PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
3674*5b3e1433Swyllys 		ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
3675*5b3e1433Swyllys 		    keys, certs);
3676*5b3e1433Swyllys 
3677*5b3e1433Swyllys 		if (ret != KMF_OK)
3678*5b3e1433Swyllys 			return (ret);
3679*5b3e1433Swyllys 	}
3680*5b3e1433Swyllys 
3681*5b3e1433Swyllys 	return (ret);
3682*5b3e1433Swyllys }
3683*5b3e1433Swyllys 
3684*5b3e1433Swyllys static KMF_RETURN
3685*5b3e1433Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
3686*5b3e1433Swyllys {
3687*5b3e1433Swyllys 	X509_ATTRIBUTE *attr = NULL;
3688*5b3e1433Swyllys 
3689*5b3e1433Swyllys 	if (pkey == NULL || attrib == NULL)
3690*5b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
3691*5b3e1433Swyllys 
3692*5b3e1433Swyllys 	if (pkey->attributes == NULL) {
3693*5b3e1433Swyllys 		pkey->attributes = sk_X509_ATTRIBUTE_new_null();
3694*5b3e1433Swyllys 		if (pkey->attributes == NULL)
3695*5b3e1433Swyllys 			return (KMF_ERR_MEMORY);
3696*5b3e1433Swyllys 	}
3697*5b3e1433Swyllys 	attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
3698*5b3e1433Swyllys 	if (attr != NULL) {
3699*5b3e1433Swyllys 		int i;
3700*5b3e1433Swyllys 		X509_ATTRIBUTE *a;
3701*5b3e1433Swyllys 		for (i = 0;
3702*5b3e1433Swyllys 		    i < sk_X509_ATTRIBUTE_num(pkey->attributes); i++) {
3703*5b3e1433Swyllys 			/*LINTED*/
3704*5b3e1433Swyllys 			a = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
3705*5b3e1433Swyllys 			if (OBJ_obj2nid(a->object) == nid) {
3706*5b3e1433Swyllys 				X509_ATTRIBUTE_free(a);
3707*5b3e1433Swyllys 				/*LINTED*/
3708*5b3e1433Swyllys 				sk_X509_ATTRIBUTE_set(pkey->attributes,
3709*5b3e1433Swyllys 				    i, attr);
3710*5b3e1433Swyllys 				return (KMF_OK);
3711*5b3e1433Swyllys 			}
3712*5b3e1433Swyllys 		}
3713*5b3e1433Swyllys 		if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == NULL) {
3714*5b3e1433Swyllys 			X509_ATTRIBUTE_free(attr);
3715*5b3e1433Swyllys 			return (KMF_ERR_MEMORY);
3716*5b3e1433Swyllys 		}
3717*5b3e1433Swyllys 	} else {
3718*5b3e1433Swyllys 		return (KMF_ERR_MEMORY);
3719*5b3e1433Swyllys 	}
3720*5b3e1433Swyllys 
3721*5b3e1433Swyllys 	return (KMF_OK);
3722*5b3e1433Swyllys }
3723*5b3e1433Swyllys 
3724*5b3e1433Swyllys static KMF_RETURN
3725*5b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
3726*5b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
3727*5b3e1433Swyllys {
3728*5b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
3729*5b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
3730*5b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
3731*5b3e1433Swyllys 	X509 *xcert = NULL;
3732*5b3e1433Swyllys 	ASN1_TYPE *keyid = NULL;
3733*5b3e1433Swyllys 	ASN1_TYPE *fname = NULL;
3734*5b3e1433Swyllys 	uchar_t *data = NULL;
3735*5b3e1433Swyllys 
3736*5b3e1433Swyllys 	keyid = PKCS12_get_attr(bag, NID_localKeyID);
3737*5b3e1433Swyllys 	fname = PKCS12_get_attr(bag, NID_friendlyName);
3738*5b3e1433Swyllys 
3739*5b3e1433Swyllys 	switch (M_PKCS12_bag_type(bag)) {
3740*5b3e1433Swyllys 		case NID_keyBag:
3741*5b3e1433Swyllys 			if (keylist == NULL)
3742*5b3e1433Swyllys 				goto end;
3743*5b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(bag->value.keybag);
3744*5b3e1433Swyllys 			if (pkey == NULL)
3745*5b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
3746*5b3e1433Swyllys 
3747*5b3e1433Swyllys 			break;
3748*5b3e1433Swyllys 		case NID_pkcs8ShroudedKeyBag:
3749*5b3e1433Swyllys 			if (keylist == NULL)
3750*5b3e1433Swyllys 				goto end;
3751*5b3e1433Swyllys 			p8 = M_PKCS12_decrypt_skey(bag, pass, passlen);
3752*5b3e1433Swyllys 			if (p8 == NULL)
3753*5b3e1433Swyllys 				return (KMF_ERR_AUTH_FAILED);
3754*5b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(p8);
3755*5b3e1433Swyllys 			PKCS8_PRIV_KEY_INFO_free(p8);
3756*5b3e1433Swyllys 			if (pkey == NULL)
3757*5b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
3758*5b3e1433Swyllys 			break;
3759*5b3e1433Swyllys 		case NID_certBag:
3760*5b3e1433Swyllys 			if (certlist == NULL)
3761*5b3e1433Swyllys 				goto end;
3762*5b3e1433Swyllys 			if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate)
3763*5b3e1433Swyllys 				return (KMF_ERR_PKCS12_FORMAT);
3764*5b3e1433Swyllys 			xcert = M_PKCS12_certbag2x509(bag);
3765*5b3e1433Swyllys 			if (xcert == NULL) {
3766*5b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
3767*5b3e1433Swyllys 				goto end;
3768*5b3e1433Swyllys 			}
3769*5b3e1433Swyllys 			if (keyid != NULL) {
3770*5b3e1433Swyllys 				if (X509_keyid_set1(xcert,
3771*5b3e1433Swyllys 				    keyid->value.octet_string->data,
3772*5b3e1433Swyllys 				    keyid->value.octet_string->length) == 0) {
3773*5b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
3774*5b3e1433Swyllys 					goto end;
3775*5b3e1433Swyllys 				}
3776*5b3e1433Swyllys 			}
3777*5b3e1433Swyllys 			if (fname != NULL) {
3778*5b3e1433Swyllys 				int len, r;
3779*5b3e1433Swyllys 				len = ASN1_STRING_to_UTF8(&data,
3780*5b3e1433Swyllys 				    fname->value.asn1_string);
3781*5b3e1433Swyllys 				if (len > 0 && data != NULL) {
3782*5b3e1433Swyllys 					r = X509_alias_set1(xcert, data, len);
3783*5b3e1433Swyllys 					if (r == NULL) {
3784*5b3e1433Swyllys 						ret = KMF_ERR_PKCS12_FORMAT;
3785*5b3e1433Swyllys 						goto end;
3786*5b3e1433Swyllys 					}
3787*5b3e1433Swyllys 				} else {
3788*5b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
3789*5b3e1433Swyllys 					goto end;
3790*5b3e1433Swyllys 				}
3791*5b3e1433Swyllys 			}
3792*5b3e1433Swyllys 			if (sk_X509_push(certlist, xcert) == 0)
3793*5b3e1433Swyllys 				ret = KMF_ERR_MEMORY;
3794*5b3e1433Swyllys 			else
3795*5b3e1433Swyllys 				xcert = NULL;
3796*5b3e1433Swyllys 			break;
3797*5b3e1433Swyllys 		case NID_safeContentsBag:
3798*5b3e1433Swyllys 			return (openssl_parse_bags(bag->value.safes, pass,
3799*5b3e1433Swyllys 			    keylist, certlist));
3800*5b3e1433Swyllys 		default:
3801*5b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
3802*5b3e1433Swyllys 			break;
3803*5b3e1433Swyllys 	}
3804*5b3e1433Swyllys 
3805*5b3e1433Swyllys 	/*
3806*5b3e1433Swyllys 	 * Set the ID and/or FriendlyName attributes on the key.
3807*5b3e1433Swyllys 	 * If converting to PKCS11 objects, these can translate to CKA_ID
3808*5b3e1433Swyllys 	 * and CKA_LABEL values.
3809*5b3e1433Swyllys 	 */
3810*5b3e1433Swyllys 	if (pkey != NULL && ret == KMF_OK) {
3811*5b3e1433Swyllys 		ASN1_TYPE *attr = NULL;
3812*5b3e1433Swyllys 		if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
3813*5b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
3814*5b3e1433Swyllys 				return (KMF_ERR_MEMORY);
3815*5b3e1433Swyllys 			attr->value.octet_string =
3816*5b3e1433Swyllys 			    ASN1_STRING_dup(keyid->value.octet_string);
3817*5b3e1433Swyllys 			attr->type = V_ASN1_OCTET_STRING;
3818*5b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.octet_string;
3819*5b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
3820*5b3e1433Swyllys 			OPENSSL_free(attr);
3821*5b3e1433Swyllys 		}
3822*5b3e1433Swyllys 
3823*5b3e1433Swyllys 		if (ret == KMF_OK && fname != NULL &&
3824*5b3e1433Swyllys 		    fname->type == V_ASN1_BMPSTRING) {
3825*5b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
3826*5b3e1433Swyllys 				return (KMF_ERR_MEMORY);
3827*5b3e1433Swyllys 			attr->value.bmpstring =
3828*5b3e1433Swyllys 			    ASN1_STRING_dup(fname->value.bmpstring);
3829*5b3e1433Swyllys 			attr->type = V_ASN1_BMPSTRING;
3830*5b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.bmpstring;
3831*5b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
3832*5b3e1433Swyllys 			OPENSSL_free(attr);
3833*5b3e1433Swyllys 		}
3834*5b3e1433Swyllys 
3835*5b3e1433Swyllys 		if (ret == KMF_OK && keylist != NULL &&
3836*5b3e1433Swyllys 		    sk_EVP_PKEY_push(keylist, pkey) == 0)
3837*5b3e1433Swyllys 			ret = KMF_ERR_MEMORY;
3838*5b3e1433Swyllys 	}
3839*5b3e1433Swyllys 	if (ret == KMF_OK && keylist != NULL)
3840*5b3e1433Swyllys 		pkey = NULL;
3841*5b3e1433Swyllys end:
3842*5b3e1433Swyllys 	if (pkey != NULL)
3843*5b3e1433Swyllys 		EVP_PKEY_free(pkey);
3844*5b3e1433Swyllys 	if (xcert != NULL)
3845*5b3e1433Swyllys 		X509_free(xcert);
3846*5b3e1433Swyllys 	if (data != NULL)
3847*5b3e1433Swyllys 		OPENSSL_free(data);
3848*5b3e1433Swyllys 
3849*5b3e1433Swyllys 	return (ret);
3850*5b3e1433Swyllys }
3851*5b3e1433Swyllys 
3852*5b3e1433Swyllys static KMF_RETURN
3853*5b3e1433Swyllys openssl_pkcs12_parse(PKCS12 *p12, char *pin,
3854*5b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys,
3855*5b3e1433Swyllys 	STACK_OF(X509) *certs,
3856*5b3e1433Swyllys 	STACK_OF(X509) *ca)
3857*5b3e1433Swyllys /*ARGSUSED*/
3858*5b3e1433Swyllys {
3859*5b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
3860*5b3e1433Swyllys 	STACK_OF(PKCS7) *asafes = NULL;
3861*5b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
3862*5b3e1433Swyllys 	int i, bagnid;
3863*5b3e1433Swyllys 	PKCS7 *p7;
3864*5b3e1433Swyllys 
3865*5b3e1433Swyllys 	if (p12 == NULL || (keys == NULL && certs == NULL))
3866*5b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
3867*5b3e1433Swyllys 
3868*5b3e1433Swyllys 	if (pin == NULL || *pin == NULL) {
3869*5b3e1433Swyllys 		if (PKCS12_verify_mac(p12, NULL, 0)) {
3870*5b3e1433Swyllys 			pin = NULL;
3871*5b3e1433Swyllys 		} else if (PKCS12_verify_mac(p12, "", 0)) {
3872*5b3e1433Swyllys 			pin = "";
3873*5b3e1433Swyllys 		} else {
3874*5b3e1433Swyllys 			return (KMF_ERR_AUTH_FAILED);
3875*5b3e1433Swyllys 		}
3876*5b3e1433Swyllys 	} else if (!PKCS12_verify_mac(p12, pin, -1)) {
3877*5b3e1433Swyllys 		return (KMF_ERR_AUTH_FAILED);
3878*5b3e1433Swyllys 	}
3879*5b3e1433Swyllys 
3880*5b3e1433Swyllys 	if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
3881*5b3e1433Swyllys 		return (KMF_ERR_PKCS12_FORMAT);
3882*5b3e1433Swyllys 
3883*5b3e1433Swyllys 	for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
3884*5b3e1433Swyllys 		bags = NULL;
3885*5b3e1433Swyllys 		/*LINTED*/
3886*5b3e1433Swyllys 		p7 = sk_PKCS7_value(asafes, i);
3887*5b3e1433Swyllys 		bagnid = OBJ_obj2nid(p7->type);
3888*5b3e1433Swyllys 
3889*5b3e1433Swyllys 		if (bagnid == NID_pkcs7_data) {
3890*5b3e1433Swyllys 			bags = PKCS12_unpack_p7data(p7);
3891*5b3e1433Swyllys 		} else if (bagnid == NID_pkcs7_encrypted) {
3892*5b3e1433Swyllys 			bags = PKCS12_unpack_p7encdata(p7, pin,
3893*5b3e1433Swyllys 			    (pin ? strlen(pin) : 0));
3894*5b3e1433Swyllys 		} else {
3895*5b3e1433Swyllys 			continue;
3896*5b3e1433Swyllys 		}
3897*5b3e1433Swyllys 		if (bags == NULL) {
3898*5b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
3899*5b3e1433Swyllys 			goto out;
3900*5b3e1433Swyllys 		}
3901*5b3e1433Swyllys 
3902*5b3e1433Swyllys 		if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
3903*5b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
3904*5b3e1433Swyllys 
3905*5b3e1433Swyllys 		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
3906*5b3e1433Swyllys 	}
3907*5b3e1433Swyllys out:
3908*5b3e1433Swyllys 	if (asafes != NULL)
3909*5b3e1433Swyllys 		sk_PKCS7_pop_free(asafes, PKCS7_free);
3910*5b3e1433Swyllys 
3911*5b3e1433Swyllys 	return (ret);
3912*5b3e1433Swyllys }
3913*5b3e1433Swyllys 
391499ebb4caSwyllys /*
391599ebb4caSwyllys  * Helper function to decrypt and parse PKCS#12 import file.
391699ebb4caSwyllys  */
391799ebb4caSwyllys static KMF_RETURN
391899ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
3919*5b3e1433Swyllys 	STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs,
3920*5b3e1433Swyllys 	STACK_OF(X509) **ca)
392199ebb4caSwyllys /* ARGSUSED */
392299ebb4caSwyllys {
392399ebb4caSwyllys 	PKCS12			*pk12, *pk12_tmp;
3924*5b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*pkeylist = NULL;
3925*5b3e1433Swyllys 	STACK_OF(X509)		*xcertlist = NULL;
3926*5b3e1433Swyllys 	STACK_OF(X509)		*cacertlist = NULL;
392799ebb4caSwyllys 
392899ebb4caSwyllys 	if ((pk12 = PKCS12_new()) == NULL) {
392999ebb4caSwyllys 		return (KMF_ERR_MEMORY);
393099ebb4caSwyllys 	}
393199ebb4caSwyllys 
393299ebb4caSwyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
393399ebb4caSwyllys 		/* This is ok; it seems to mean there is no more to read. */
393499ebb4caSwyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
393599ebb4caSwyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
393699ebb4caSwyllys 			goto end_extract_pkcs12;
393799ebb4caSwyllys 
393899ebb4caSwyllys 		PKCS12_free(pk12);
393999ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
394099ebb4caSwyllys 	}
394199ebb4caSwyllys 	pk12 = pk12_tmp;
394299ebb4caSwyllys 
3943*5b3e1433Swyllys 	xcertlist = sk_X509_new_null();
3944*5b3e1433Swyllys 	if (xcertlist == NULL) {
3945*5b3e1433Swyllys 		PKCS12_free(pk12);
3946*5b3e1433Swyllys 		return (KMF_ERR_MEMORY);
3947*5b3e1433Swyllys 	}
3948*5b3e1433Swyllys 	pkeylist = sk_EVP_PKEY_new_null();
3949*5b3e1433Swyllys 	if (pkeylist == NULL) {
3950*5b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
3951*5b3e1433Swyllys 		PKCS12_free(pk12);
3952*5b3e1433Swyllys 		return (KMF_ERR_MEMORY);
3953*5b3e1433Swyllys 	}
3954*5b3e1433Swyllys 
3955*5b3e1433Swyllys 	if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
3956*5b3e1433Swyllys 	    cacertlist) != KMF_OK) {
3957*5b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
3958*5b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
395999ebb4caSwyllys 		PKCS12_free(pk12);
396099ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
396199ebb4caSwyllys 	}
396299ebb4caSwyllys 
3963*5b3e1433Swyllys 	if (priv_key && pkeylist)
3964*5b3e1433Swyllys 		*priv_key = pkeylist;
3965*5b3e1433Swyllys 	else if (pkeylist)
3966*5b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
3967*5b3e1433Swyllys 	if (certs && xcertlist)
3968*5b3e1433Swyllys 		*certs = xcertlist;
3969*5b3e1433Swyllys 	else if (xcertlist)
3970*5b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
3971*5b3e1433Swyllys 	if (ca && cacertlist)
3972*5b3e1433Swyllys 		*ca = cacertlist;
3973*5b3e1433Swyllys 	else if (cacertlist)
3974*5b3e1433Swyllys 		sk_X509_pop_free(cacertlist, X509_free);
397599ebb4caSwyllys 
3976*5b3e1433Swyllys end_extract_pkcs12:
397799ebb4caSwyllys 
397899ebb4caSwyllys 	PKCS12_free(pk12);
397999ebb4caSwyllys 	return (KMF_OK);
398099ebb4caSwyllys }
398199ebb4caSwyllys 
398299ebb4caSwyllys static KMF_RETURN
398399ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
398499ebb4caSwyllys {
398599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
398699ebb4caSwyllys 	uint32_t sz;
398799ebb4caSwyllys 
398899ebb4caSwyllys 	sz = BN_num_bytes(from);
398999ebb4caSwyllys 	to->val = (uchar_t *)malloc(sz);
399099ebb4caSwyllys 	if (to->val == NULL)
399199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
399299ebb4caSwyllys 
399399ebb4caSwyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
399499ebb4caSwyllys 		free(to->val);
399599ebb4caSwyllys 		to->val = NULL;
399699ebb4caSwyllys 		to->len = 0;
399799ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
399899ebb4caSwyllys 	}
399999ebb4caSwyllys 
400099ebb4caSwyllys 	return (rv);
400199ebb4caSwyllys }
400299ebb4caSwyllys 
400399ebb4caSwyllys static KMF_RETURN
400499ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
400599ebb4caSwyllys {
400699ebb4caSwyllys 	KMF_RETURN rv;
400799ebb4caSwyllys 	KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
400899ebb4caSwyllys 
400999ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
401099ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK)
401199ebb4caSwyllys 		goto cleanup;
401299ebb4caSwyllys 
401399ebb4caSwyllys 	if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK)
401499ebb4caSwyllys 		goto cleanup;
401599ebb4caSwyllys 
401699ebb4caSwyllys 	if (rsa->d != NULL)
401799ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK)
401899ebb4caSwyllys 			goto cleanup;
401999ebb4caSwyllys 
402099ebb4caSwyllys 	if (rsa->p != NULL)
402199ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK)
402299ebb4caSwyllys 			goto cleanup;
402399ebb4caSwyllys 
402499ebb4caSwyllys 	if (rsa->q != NULL)
402599ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK)
402699ebb4caSwyllys 			goto cleanup;
402799ebb4caSwyllys 
402899ebb4caSwyllys 	if (rsa->dmp1 != NULL)
402999ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK)
403099ebb4caSwyllys 			goto cleanup;
403199ebb4caSwyllys 
403299ebb4caSwyllys 	if (rsa->dmq1 != NULL)
403399ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK)
403499ebb4caSwyllys 			goto cleanup;
403599ebb4caSwyllys 
403699ebb4caSwyllys 	if (rsa->iqmp != NULL)
403799ebb4caSwyllys 		if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK)
403899ebb4caSwyllys 			goto cleanup;
403999ebb4caSwyllys cleanup:
404099ebb4caSwyllys 	if (rv != KMF_OK)
404130a5e8faSwyllys 		kmf_free_raw_key(key);
404299ebb4caSwyllys 	else
404399ebb4caSwyllys 		key->keytype = KMF_RSA;
404499ebb4caSwyllys 
404599ebb4caSwyllys 	/*
404699ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
404799ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
404899ebb4caSwyllys 	 */
404999ebb4caSwyllys 	RSA_free(rsa);
405099ebb4caSwyllys 
405199ebb4caSwyllys 	return (rv);
405299ebb4caSwyllys }
405399ebb4caSwyllys 
405499ebb4caSwyllys static KMF_RETURN
405599ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
405699ebb4caSwyllys {
405799ebb4caSwyllys 	KMF_RETURN rv;
405899ebb4caSwyllys 	KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
405999ebb4caSwyllys 
406099ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
406199ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK)
406299ebb4caSwyllys 		goto cleanup;
406399ebb4caSwyllys 
406499ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK)
406599ebb4caSwyllys 		goto cleanup;
406699ebb4caSwyllys 
406799ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK)
406899ebb4caSwyllys 		goto cleanup;
406999ebb4caSwyllys 
407099ebb4caSwyllys 	if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK)
407199ebb4caSwyllys 		goto cleanup;
407299ebb4caSwyllys 
407399ebb4caSwyllys cleanup:
407499ebb4caSwyllys 	if (rv != KMF_OK)
407530a5e8faSwyllys 		kmf_free_raw_key(key);
407699ebb4caSwyllys 	else
407799ebb4caSwyllys 		key->keytype = KMF_DSA;
407899ebb4caSwyllys 
407999ebb4caSwyllys 	/*
408099ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
408199ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
408299ebb4caSwyllys 	 */
408399ebb4caSwyllys 	DSA_free(dsa);
408499ebb4caSwyllys 
408599ebb4caSwyllys 	return (rv);
408699ebb4caSwyllys }
408799ebb4caSwyllys 
408899ebb4caSwyllys static KMF_RETURN
408999ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
4090*5b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
409199ebb4caSwyllys {
409299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
4093*5b3e1433Swyllys 	KMF_X509_DER_CERT *list = (*certlist);
4094*5b3e1433Swyllys 	KMF_X509_DER_CERT cert;
409599ebb4caSwyllys 	int n = (*ncerts);
409699ebb4caSwyllys 
409799ebb4caSwyllys 	if (list == NULL) {
4098*5b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
409999ebb4caSwyllys 	} else {
4100*5b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)realloc(list,
4101*5b3e1433Swyllys 		    sizeof (KMF_X509_DER_CERT) * (n + 1));
410299ebb4caSwyllys 	}
410399ebb4caSwyllys 
410499ebb4caSwyllys 	if (list == NULL)
410599ebb4caSwyllys 		return (KMF_ERR_MEMORY);
410699ebb4caSwyllys 
4107*5b3e1433Swyllys 	(void) memset(&cert, 0, sizeof (cert));
4108*5b3e1433Swyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
410999ebb4caSwyllys 	if (rv == KMF_OK) {
4110*5b3e1433Swyllys 		int len = 0;
4111*5b3e1433Swyllys 		/* Get the alias name for the cert if there is one */
4112*5b3e1433Swyllys 		char *a = (char *)X509_alias_get0(sslcert, &len);
4113*5b3e1433Swyllys 		if (a != NULL)
4114*5b3e1433Swyllys 			cert.kmf_private.label = strdup(a);
4115*5b3e1433Swyllys 		cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
4116*5b3e1433Swyllys 
411799ebb4caSwyllys 		list[n] = cert;
411899ebb4caSwyllys 		(*ncerts) = n + 1;
411999ebb4caSwyllys 
412099ebb4caSwyllys 		*certlist = list;
412199ebb4caSwyllys 	} else {
412299ebb4caSwyllys 		free(list);
412399ebb4caSwyllys 	}
412499ebb4caSwyllys 
412599ebb4caSwyllys 	return (rv);
412699ebb4caSwyllys }
412799ebb4caSwyllys 
412899ebb4caSwyllys static KMF_RETURN
412999ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
413099ebb4caSwyllys 	KMF_RAW_KEY_DATA *newkey, int *nkeys)
413199ebb4caSwyllys {
413299ebb4caSwyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
413399ebb4caSwyllys 	int n = (*nkeys);
413499ebb4caSwyllys 
413599ebb4caSwyllys 	if (list == NULL) {
413699ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
413799ebb4caSwyllys 	} else {
413899ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
413999ebb4caSwyllys 		    sizeof (KMF_RAW_KEY_DATA) * (n + 1));
414099ebb4caSwyllys 	}
414199ebb4caSwyllys 
414299ebb4caSwyllys 	if (list == NULL)
414399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
414499ebb4caSwyllys 
414599ebb4caSwyllys 	list[n] = *newkey;
414699ebb4caSwyllys 	(*nkeys) = n + 1;
414799ebb4caSwyllys 
414899ebb4caSwyllys 	*keylist = list;
414999ebb4caSwyllys 
415099ebb4caSwyllys 	return (KMF_OK);
415199ebb4caSwyllys }
415299ebb4caSwyllys 
4153*5b3e1433Swyllys static X509_ATTRIBUTE *
4154*5b3e1433Swyllys find_attr(STACK_OF(X509_ATTRIBUTE) *attrs, int nid)
4155*5b3e1433Swyllys {
4156*5b3e1433Swyllys 	X509_ATTRIBUTE *a;
4157*5b3e1433Swyllys 	int i;
4158*5b3e1433Swyllys 
4159*5b3e1433Swyllys 	if (attrs == NULL)
4160*5b3e1433Swyllys 		return (NULL);
4161*5b3e1433Swyllys 
4162*5b3e1433Swyllys 	for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
4163*5b3e1433Swyllys 		/*LINTED*/
4164*5b3e1433Swyllys 		a = sk_X509_ATTRIBUTE_value(attrs, i);
4165*5b3e1433Swyllys 		if (OBJ_obj2nid(a->object) == nid)
4166*5b3e1433Swyllys 			return (a);
4167*5b3e1433Swyllys 	}
4168*5b3e1433Swyllys 	return (NULL);
4169*5b3e1433Swyllys }
4170*5b3e1433Swyllys 
417130a5e8faSwyllys static KMF_RETURN
417230a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
417330a5e8faSwyllys {
417430a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
4175*5b3e1433Swyllys 	X509_ATTRIBUTE *attr;
417630a5e8faSwyllys 
417730a5e8faSwyllys 	if (pkey == NULL || key == NULL)
417830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
417930a5e8faSwyllys 	/* Convert SSL key to raw key */
418030a5e8faSwyllys 	switch (pkey->type) {
418130a5e8faSwyllys 		case EVP_PKEY_RSA:
418230a5e8faSwyllys 			rv = exportRawRSAKey(EVP_PKEY_get1_RSA(pkey),
418330a5e8faSwyllys 			    key);
418430a5e8faSwyllys 			if (rv != KMF_OK)
418530a5e8faSwyllys 				return (rv);
418630a5e8faSwyllys 			break;
418730a5e8faSwyllys 		case EVP_PKEY_DSA:
418830a5e8faSwyllys 			rv = exportRawDSAKey(EVP_PKEY_get1_DSA(pkey),
418930a5e8faSwyllys 			    key);
419030a5e8faSwyllys 			if (rv != KMF_OK)
419130a5e8faSwyllys 				return (rv);
419230a5e8faSwyllys 			break;
419330a5e8faSwyllys 		default:
419430a5e8faSwyllys 			return (KMF_ERR_BAD_PARAMETER);
419530a5e8faSwyllys 	}
4196*5b3e1433Swyllys 	/*
4197*5b3e1433Swyllys 	 * If friendlyName, add it to record.
4198*5b3e1433Swyllys 	 */
4199*5b3e1433Swyllys 	attr = find_attr(pkey->attributes, NID_friendlyName);
4200*5b3e1433Swyllys 	if (attr != NULL) {
4201*5b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
4202*5b3e1433Swyllys 		int numattr = sk_ASN1_TYPE_num(attr->value.set);
4203*5b3e1433Swyllys 		if (attr->single == 0 && numattr > 0) {
4204*5b3e1433Swyllys 			/*LINTED*/
4205*5b3e1433Swyllys 			ty = sk_ASN1_TYPE_value(attr->value.set, 0);
4206*5b3e1433Swyllys 		}
4207*5b3e1433Swyllys 		if (ty != NULL) {
4208*5b3e1433Swyllys 			key->label = uni2asc(ty->value.bmpstring->data,
4209*5b3e1433Swyllys 			    ty->value.bmpstring->length);
4210*5b3e1433Swyllys 		}
4211*5b3e1433Swyllys 	} else {
4212*5b3e1433Swyllys 		key->label = NULL;
4213*5b3e1433Swyllys 	}
4214*5b3e1433Swyllys 
4215*5b3e1433Swyllys 	/*
4216*5b3e1433Swyllys 	 * If KeyID, add it to record as a KMF_DATA object.
4217*5b3e1433Swyllys 	 */
4218*5b3e1433Swyllys 	attr = find_attr(pkey->attributes, NID_localKeyID);
4219*5b3e1433Swyllys 	if (attr != NULL) {
4220*5b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
4221*5b3e1433Swyllys 		int numattr = sk_ASN1_TYPE_num(attr->value.set);
4222*5b3e1433Swyllys 		if (attr->single == 0 && numattr > 0) {
4223*5b3e1433Swyllys 			/*LINTED*/
4224*5b3e1433Swyllys 			ty = sk_ASN1_TYPE_value(attr->value.set, 0);
4225*5b3e1433Swyllys 		}
4226*5b3e1433Swyllys 		key->id.Data = (uchar_t *)malloc(
4227*5b3e1433Swyllys 		    ty->value.octet_string->length);
4228*5b3e1433Swyllys 		if (key->id.Data == NULL)
4229*5b3e1433Swyllys 			return (KMF_ERR_MEMORY);
4230*5b3e1433Swyllys 		(void) memcpy(key->id.Data, ty->value.octet_string->data,
4231*5b3e1433Swyllys 		    ty->value.octet_string->length);
4232*5b3e1433Swyllys 		key->id.Length = ty->value.octet_string->length;
4233*5b3e1433Swyllys 	} else {
4234*5b3e1433Swyllys 		(void) memset(&key->id, 0, sizeof (KMF_DATA));
4235*5b3e1433Swyllys 	}
423630a5e8faSwyllys 
423730a5e8faSwyllys 	return (rv);
423830a5e8faSwyllys }
423999ebb4caSwyllys 
424099ebb4caSwyllys static KMF_RETURN
424199ebb4caSwyllys convertPK12Objects(
424299ebb4caSwyllys 	KMF_HANDLE *kmfh,
4243*5b3e1433Swyllys 	STACK_OF(EVP_PKEY) *sslkeys,
4244*5b3e1433Swyllys 	STACK_OF(X509) *sslcert,
4245*5b3e1433Swyllys 	STACK_OF(X509) *sslcacerts,
424699ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
4247*5b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
424899ebb4caSwyllys {
424999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
425099ebb4caSwyllys 	KMF_RAW_KEY_DATA key;
425199ebb4caSwyllys 	int i;
425299ebb4caSwyllys 
4253*5b3e1433Swyllys 	for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
4254*5b3e1433Swyllys 		/*LINTED*/
4255*5b3e1433Swyllys 		EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
4256*5b3e1433Swyllys 		rv = convertToRawKey(pkey, &key);
425730a5e8faSwyllys 		if (rv == KMF_OK)
425899ebb4caSwyllys 			rv = add_key_to_list(keylist, &key, nkeys);
425930a5e8faSwyllys 
426099ebb4caSwyllys 		if (rv != KMF_OK)
426199ebb4caSwyllys 			return (rv);
426299ebb4caSwyllys 	}
426399ebb4caSwyllys 
426499ebb4caSwyllys 	/* Now add the certificate to the certlist */
4265*5b3e1433Swyllys 	for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
4266*5b3e1433Swyllys 		/*LINTED*/
4267*5b3e1433Swyllys 		X509 *cert = sk_X509_value(sslcert, i);
4268*5b3e1433Swyllys 		rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
426999ebb4caSwyllys 		if (rv != KMF_OK)
427099ebb4caSwyllys 			return (rv);
427199ebb4caSwyllys 	}
427299ebb4caSwyllys 
427399ebb4caSwyllys 	/* Also add any included CA certs to the list */
427471593db2Swyllys 	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
427599ebb4caSwyllys 		X509 *c;
427699ebb4caSwyllys 		/*
427799ebb4caSwyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
427899ebb4caSwyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
427999ebb4caSwyllys 		 * Lint is complaining about the embedded casting, and
428099ebb4caSwyllys 		 * to fix it, you need to fix openssl header files.
428199ebb4caSwyllys 		 */
428299ebb4caSwyllys 		/* LINTED E_BAD_PTR_CAST_ALIGN */
428399ebb4caSwyllys 		c = sk_X509_value(sslcacerts, i);
428499ebb4caSwyllys 
428599ebb4caSwyllys 		/* Now add the ca cert to the certlist */
428699ebb4caSwyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
428799ebb4caSwyllys 		if (rv != KMF_OK)
428899ebb4caSwyllys 			return (rv);
428999ebb4caSwyllys 	}
429099ebb4caSwyllys 	return (rv);
429199ebb4caSwyllys }
429299ebb4caSwyllys 
429399ebb4caSwyllys KMF_RETURN
429430a5e8faSwyllys openssl_import_objects(KMF_HANDLE *kmfh,
429599ebb4caSwyllys 	char *filename, KMF_CREDENTIAL *cred,
4296*5b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts,
429799ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
429899ebb4caSwyllys {
429999ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
430030a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
430130a5e8faSwyllys 	BIO		*bio = NULL;
4302*5b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*privkeys = NULL;
4303*5b3e1433Swyllys 	STACK_OF(X509)		*certs = NULL;
430499ebb4caSwyllys 	STACK_OF(X509)		*cacerts = NULL;
430599ebb4caSwyllys 
430630a5e8faSwyllys 	/*
430730a5e8faSwyllys 	 * auto-detect the file format, regardless of what
430830a5e8faSwyllys 	 * the 'format' parameters in the params say.
430930a5e8faSwyllys 	 */
431030a5e8faSwyllys 	rv = kmf_get_file_format(filename, &format);
431130a5e8faSwyllys 	if (rv != KMF_OK) {
431230a5e8faSwyllys 		return (rv);
431330a5e8faSwyllys 	}
431430a5e8faSwyllys 
431530a5e8faSwyllys 	/* This function only works for PEM or PKCS#12 files */
431630a5e8faSwyllys 	if (format != KMF_FORMAT_PEM &&
431730a5e8faSwyllys 	    format != KMF_FORMAT_PEM_KEYPAIR &&
431830a5e8faSwyllys 	    format != KMF_FORMAT_PKCS12)
431930a5e8faSwyllys 		return (KMF_ERR_ENCODING);
432030a5e8faSwyllys 
432130a5e8faSwyllys 	*certlist = NULL;
432230a5e8faSwyllys 	*keylist = NULL;
432330a5e8faSwyllys 	*ncerts = 0;
432430a5e8faSwyllys 	*nkeys = 0;
432530a5e8faSwyllys 
432630a5e8faSwyllys 	if (format == KMF_FORMAT_PKCS12) {
432799ebb4caSwyllys 		bio = BIO_new_file(filename, "rb");
432899ebb4caSwyllys 		if (bio == NULL) {
432999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
433099ebb4caSwyllys 			rv = KMF_ERR_OPEN_FILE;
433199ebb4caSwyllys 			goto end;
433299ebb4caSwyllys 		}
433399ebb4caSwyllys 
433434acef67Swyllys 		rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
4335*5b3e1433Swyllys 		    (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
433699ebb4caSwyllys 
433799ebb4caSwyllys 		if (rv  == KMF_OK)
433899ebb4caSwyllys 			/* Convert keys and certs to exportable format */
4339*5b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
434099ebb4caSwyllys 			    keylist, nkeys, certlist, ncerts);
434130a5e8faSwyllys 	} else {
4342*5b3e1433Swyllys 		EVP_PKEY *pkey;
4343*5b3e1433Swyllys 		KMF_DATA *certdata = NULL;
4344*5b3e1433Swyllys 		KMF_X509_DER_CERT *kmfcerts = NULL;
4345*5b3e1433Swyllys 		int i;
434630a5e8faSwyllys 		rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
434734acef67Swyllys 		    (uchar_t *)cred->cred, (uint32_t)cred->credlen,
4348*5b3e1433Swyllys 		    &pkey, &certdata, ncerts);
434971593db2Swyllys 
435071593db2Swyllys 		/* Reached end of import file? */
4351*5b3e1433Swyllys 		if (rv == KMF_OK && pkey != NULL) {
4352*5b3e1433Swyllys 			privkeys = sk_EVP_PKEY_new_null();
4353*5b3e1433Swyllys 			if (privkeys == NULL) {
4354*5b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
4355*5b3e1433Swyllys 				goto end;
4356*5b3e1433Swyllys 			}
4357*5b3e1433Swyllys 			(void) sk_EVP_PKEY_push(privkeys, pkey);
4358*5b3e1433Swyllys 			/* convert the certificate list here */
4359*5b3e1433Swyllys 			if (*ncerts > 0 && certlist != NULL) {
4360*5b3e1433Swyllys 				kmfcerts = (KMF_X509_DER_CERT *)malloc(*ncerts *
4361*5b3e1433Swyllys 				    sizeof (KMF_X509_DER_CERT));
4362*5b3e1433Swyllys 				if (kmfcerts == NULL) {
4363*5b3e1433Swyllys 					rv = KMF_ERR_MEMORY;
4364*5b3e1433Swyllys 					goto end;
4365*5b3e1433Swyllys 				}
4366*5b3e1433Swyllys 				(void) memset(kmfcerts, 0, *ncerts *
4367*5b3e1433Swyllys 				    sizeof (KMF_X509_DER_CERT));
4368*5b3e1433Swyllys 				for (i = 0; i < *ncerts; i++) {
4369*5b3e1433Swyllys 					kmfcerts[i].certificate = certdata[i];
4370*5b3e1433Swyllys 					kmfcerts[i].kmf_private.keystore_type =
4371*5b3e1433Swyllys 					    KMF_KEYSTORE_OPENSSL;
4372*5b3e1433Swyllys 				}
4373*5b3e1433Swyllys 				*certlist = kmfcerts;
4374*5b3e1433Swyllys 			}
4375*5b3e1433Swyllys 			/*
4376*5b3e1433Swyllys 			 * Convert keys to exportable format, the certs
4377*5b3e1433Swyllys 			 * are already OK.
4378*5b3e1433Swyllys 			 */
4379*5b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
438071593db2Swyllys 			    keylist, nkeys, NULL, NULL);
438130a5e8faSwyllys 		}
4382*5b3e1433Swyllys 	}
438371593db2Swyllys end:
438430a5e8faSwyllys 	if (bio != NULL)
438599ebb4caSwyllys 		(void) BIO_free(bio);
438699ebb4caSwyllys 
4387*5b3e1433Swyllys 	if (privkeys)
4388*5b3e1433Swyllys 		sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
4389*5b3e1433Swyllys 	if (certs)
4390*5b3e1433Swyllys 		sk_X509_pop_free(certs, X509_free);
439130a5e8faSwyllys 	if (cacerts)
4392*5b3e1433Swyllys 		sk_X509_pop_free(cacerts, X509_free);
439330a5e8faSwyllys 
439499ebb4caSwyllys 	return (rv);
439599ebb4caSwyllys }
439699ebb4caSwyllys 
439799ebb4caSwyllys static KMF_RETURN
439899ebb4caSwyllys create_deskey(DES_cblock **deskey)
439999ebb4caSwyllys {
440099ebb4caSwyllys 	DES_cblock *key;
440199ebb4caSwyllys 
440299ebb4caSwyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
440399ebb4caSwyllys 	if (key == NULL) {
440499ebb4caSwyllys 		return (KMF_ERR_MEMORY);
440599ebb4caSwyllys 	}
440699ebb4caSwyllys 
440799ebb4caSwyllys 	if (DES_random_key(key) == 0) {
440899ebb4caSwyllys 		free(key);
440999ebb4caSwyllys 		return (KMF_ERR_KEYGEN_FAILED);
441099ebb4caSwyllys 	}
441199ebb4caSwyllys 
441299ebb4caSwyllys 	*deskey = key;
441399ebb4caSwyllys 	return (KMF_OK);
441499ebb4caSwyllys }
441599ebb4caSwyllys 
441699ebb4caSwyllys #define	KEYGEN_RETRY 3
441799ebb4caSwyllys #define	DES3_KEY_SIZE 24
441899ebb4caSwyllys 
441999ebb4caSwyllys static KMF_RETURN
442099ebb4caSwyllys create_des3key(unsigned char **des3key)
442199ebb4caSwyllys {
442299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
442399ebb4caSwyllys 	DES_cblock *deskey1 = NULL;
442499ebb4caSwyllys 	DES_cblock *deskey2 = NULL;
442599ebb4caSwyllys 	DES_cblock *deskey3 = NULL;
442699ebb4caSwyllys 	unsigned char *newkey = NULL;
442799ebb4caSwyllys 	int retry;
442899ebb4caSwyllys 
442999ebb4caSwyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
443099ebb4caSwyllys 		return (KMF_ERR_MEMORY);
443199ebb4caSwyllys 	}
443299ebb4caSwyllys 
443399ebb4caSwyllys 	/* create the 1st DES key */
443499ebb4caSwyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
443599ebb4caSwyllys 		goto out;
443699ebb4caSwyllys 	}
443799ebb4caSwyllys 
443899ebb4caSwyllys 	/*
443999ebb4caSwyllys 	 * Create the 2nd DES key and make sure its value is different
444099ebb4caSwyllys 	 * from the 1st DES key.
444199ebb4caSwyllys 	 */
444299ebb4caSwyllys 	retry = 0;
444399ebb4caSwyllys 	do {
444499ebb4caSwyllys 		if (deskey2 != NULL) {
444599ebb4caSwyllys 			free(deskey2);
444699ebb4caSwyllys 			deskey2 = NULL;
444799ebb4caSwyllys 		}
444899ebb4caSwyllys 
444999ebb4caSwyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
445099ebb4caSwyllys 			goto out;
445199ebb4caSwyllys 		}
445299ebb4caSwyllys 
445399ebb4caSwyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
445499ebb4caSwyllys 		    == 0) {
445599ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
445699ebb4caSwyllys 			retry++;
445799ebb4caSwyllys 		}
445899ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
445999ebb4caSwyllys 
446099ebb4caSwyllys 	if (ret != KMF_OK) {
446199ebb4caSwyllys 		goto out;
446299ebb4caSwyllys 	}
446399ebb4caSwyllys 
446499ebb4caSwyllys 	/*
446599ebb4caSwyllys 	 * Create the 3rd DES key and make sure its value is different
446699ebb4caSwyllys 	 * from the 2nd DES key.
446799ebb4caSwyllys 	 */
446899ebb4caSwyllys 	retry = 0;
446999ebb4caSwyllys 	do {
447099ebb4caSwyllys 		if (deskey3 != NULL) {
447199ebb4caSwyllys 			free(deskey3);
447299ebb4caSwyllys 			deskey3 = NULL;
447399ebb4caSwyllys 		}
447499ebb4caSwyllys 
447599ebb4caSwyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
447699ebb4caSwyllys 			goto out;
447799ebb4caSwyllys 		}
447899ebb4caSwyllys 
447999ebb4caSwyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
448099ebb4caSwyllys 		    == 0) {
448199ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
448299ebb4caSwyllys 			retry++;
448399ebb4caSwyllys 		}
448499ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
448599ebb4caSwyllys 
448699ebb4caSwyllys 	if (ret != KMF_OK) {
448799ebb4caSwyllys 		goto out;
448899ebb4caSwyllys 	}
448999ebb4caSwyllys 
449099ebb4caSwyllys 	/* Concatenate 3 DES keys into a DES3 key */
449199ebb4caSwyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
449299ebb4caSwyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
449399ebb4caSwyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
449499ebb4caSwyllys 	*des3key = newkey;
449599ebb4caSwyllys 
449699ebb4caSwyllys out:
449799ebb4caSwyllys 	if (deskey1 != NULL)
449899ebb4caSwyllys 		free(deskey1);
449999ebb4caSwyllys 
450099ebb4caSwyllys 	if (deskey2 != NULL)
450199ebb4caSwyllys 		free(deskey2);
450299ebb4caSwyllys 
450399ebb4caSwyllys 	if (deskey3 != NULL)
450499ebb4caSwyllys 		free(deskey3);
450599ebb4caSwyllys 
450699ebb4caSwyllys 	if (ret != KMF_OK && newkey != NULL)
450799ebb4caSwyllys 		free(newkey);
450899ebb4caSwyllys 
450999ebb4caSwyllys 	return (ret);
451099ebb4caSwyllys }
451199ebb4caSwyllys 
451299ebb4caSwyllys KMF_RETURN
451330a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
451430a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
451599ebb4caSwyllys {
451699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
451799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
451899ebb4caSwyllys 	char *fullpath = NULL;
451999ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
452099ebb4caSwyllys 	DES_cblock *deskey = NULL;
452199ebb4caSwyllys 	unsigned char *des3key = NULL;
452299ebb4caSwyllys 	unsigned char *random = NULL;
452399ebb4caSwyllys 	int fd = -1;
452430a5e8faSwyllys 	KMF_KEY_HANDLE *symkey;
452530a5e8faSwyllys 	KMF_KEY_ALG keytype;
452630a5e8faSwyllys 	uint32_t keylen;
452730a5e8faSwyllys 	uint32_t keylen_size = sizeof (keylen);
452830a5e8faSwyllys 	char *dirpath;
452930a5e8faSwyllys 	char *keyfile;
453099ebb4caSwyllys 
453199ebb4caSwyllys 	if (kmfh == NULL)
453299ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
453399ebb4caSwyllys 
453430a5e8faSwyllys 	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
453530a5e8faSwyllys 	if (symkey == NULL)
453699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
453799ebb4caSwyllys 
453830a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
453930a5e8faSwyllys 
454030a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
454130a5e8faSwyllys 	if (keyfile == NULL)
454230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
454330a5e8faSwyllys 
454430a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
454530a5e8faSwyllys 	    (void *)&keytype, NULL);
454630a5e8faSwyllys 	if (ret != KMF_OK)
454730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
454830a5e8faSwyllys 
454930a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
455030a5e8faSwyllys 	    &keylen, &keylen_size);
455130a5e8faSwyllys 	if (ret == KMF_ERR_ATTR_NOT_FOUND &&
455230a5e8faSwyllys 	    (keytype == KMF_DES || keytype == KMF_DES3))
455330a5e8faSwyllys 		/* keylength is not required for DES and 3DES */
455430a5e8faSwyllys 		ret = KMF_OK;
455530a5e8faSwyllys 	if (ret != KMF_OK)
455630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
455730a5e8faSwyllys 
455830a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
455999ebb4caSwyllys 	if (fullpath == NULL)
456099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
456199ebb4caSwyllys 
456299ebb4caSwyllys 	/* If the requested file exists, return an error */
456330a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
456499ebb4caSwyllys 		free(fullpath);
456599ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
456699ebb4caSwyllys 	}
456799ebb4caSwyllys 
456899ebb4caSwyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
456999ebb4caSwyllys 	if (fd == -1) {
457099ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
457199ebb4caSwyllys 		goto out;
457299ebb4caSwyllys 	}
457399ebb4caSwyllys 
457499ebb4caSwyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
457599ebb4caSwyllys 	if (rkey == NULL) {
457699ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
457799ebb4caSwyllys 		goto out;
457899ebb4caSwyllys 	}
457999ebb4caSwyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
458099ebb4caSwyllys 
458130a5e8faSwyllys 	if (keytype == KMF_DES) {
458299ebb4caSwyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
458399ebb4caSwyllys 			goto out;
458499ebb4caSwyllys 		}
458599ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)deskey;
458699ebb4caSwyllys 		rkey->keydata.len = 8;
458799ebb4caSwyllys 
458899ebb4caSwyllys 		symkey->keyalg = KMF_DES;
458999ebb4caSwyllys 
459030a5e8faSwyllys 	} else if (keytype == KMF_DES3) {
459199ebb4caSwyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
459299ebb4caSwyllys 			goto out;
459399ebb4caSwyllys 		}
459499ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)des3key;
459599ebb4caSwyllys 		rkey->keydata.len = DES3_KEY_SIZE;
459699ebb4caSwyllys 		symkey->keyalg = KMF_DES3;
45979b37d296Swyllys 
459830a5e8faSwyllys 	} else if (keytype == KMF_AES || keytype == KMF_RC4 ||
459930a5e8faSwyllys 	    keytype == KMF_GENERIC_SECRET) {
460099ebb4caSwyllys 		int bytes;
460199ebb4caSwyllys 
460230a5e8faSwyllys 		if (keylen % 8 != 0) {
460399ebb4caSwyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
460499ebb4caSwyllys 			goto out;
460599ebb4caSwyllys 		}
460699ebb4caSwyllys 
460730a5e8faSwyllys 		if (keytype == KMF_AES) {
460830a5e8faSwyllys 			if (keylen != 128 &&
460930a5e8faSwyllys 			    keylen != 192 &&
461030a5e8faSwyllys 			    keylen != 256) {
461199ebb4caSwyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
461299ebb4caSwyllys 				goto out;
461399ebb4caSwyllys 			}
461499ebb4caSwyllys 		}
461599ebb4caSwyllys 
461630a5e8faSwyllys 		bytes = keylen/8;
461799ebb4caSwyllys 		random = malloc(bytes);
461899ebb4caSwyllys 		if (random == NULL) {
461999ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
462099ebb4caSwyllys 			goto out;
462199ebb4caSwyllys 		}
462299ebb4caSwyllys 		if (RAND_bytes(random, bytes) != 1) {
462399ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
462499ebb4caSwyllys 			goto out;
462599ebb4caSwyllys 		}
462699ebb4caSwyllys 
462799ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)random;
462899ebb4caSwyllys 		rkey->keydata.len = bytes;
462930a5e8faSwyllys 		symkey->keyalg = keytype;
463099ebb4caSwyllys 
463199ebb4caSwyllys 	} else {
463299ebb4caSwyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
463399ebb4caSwyllys 		goto out;
463499ebb4caSwyllys 	}
463599ebb4caSwyllys 
463699ebb4caSwyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
463799ebb4caSwyllys 
463899ebb4caSwyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
463999ebb4caSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
464099ebb4caSwyllys 	symkey->keylabel = (char *)fullpath;
464199ebb4caSwyllys 	symkey->israw = TRUE;
464299ebb4caSwyllys 	symkey->keyp = rkey;
464399ebb4caSwyllys 
464499ebb4caSwyllys out:
464599ebb4caSwyllys 	if (fd != -1)
464699ebb4caSwyllys 		(void) close(fd);
464799ebb4caSwyllys 
464899ebb4caSwyllys 	if (ret != KMF_OK && fullpath != NULL) {
464999ebb4caSwyllys 		free(fullpath);
465099ebb4caSwyllys 	}
465199ebb4caSwyllys 	if (ret != KMF_OK) {
465230a5e8faSwyllys 		kmf_free_raw_sym_key(rkey);
465399ebb4caSwyllys 		symkey->keyp = NULL;
465499ebb4caSwyllys 		symkey->keyalg = KMF_KEYALG_NONE;
465599ebb4caSwyllys 	}
465699ebb4caSwyllys 
465799ebb4caSwyllys 	return (ret);
465899ebb4caSwyllys }
465999ebb4caSwyllys 
466099ebb4caSwyllys /*
466199ebb4caSwyllys  * Check a file to see if it is a CRL file with PEM or DER format.
466299ebb4caSwyllys  * If success, return its format in the "pformat" argument.
466399ebb4caSwyllys  */
466499ebb4caSwyllys KMF_RETURN
466599ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
466699ebb4caSwyllys {
466799ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
466899ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
466999ebb4caSwyllys 	BIO		*bio = NULL;
467099ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
467199ebb4caSwyllys 
467299ebb4caSwyllys 	if (filename == NULL) {
467399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
467499ebb4caSwyllys 	}
467599ebb4caSwyllys 
467699ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
467799ebb4caSwyllys 	if (bio == NULL)	{
467899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
467999ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
468099ebb4caSwyllys 		goto out;
468199ebb4caSwyllys 	}
468299ebb4caSwyllys 
468399ebb4caSwyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
468499ebb4caSwyllys 		*pformat = KMF_FORMAT_PEM;
468599ebb4caSwyllys 		goto out;
468699ebb4caSwyllys 	}
468799ebb4caSwyllys 	(void) BIO_free(bio);
468899ebb4caSwyllys 
468999ebb4caSwyllys 	/*
469099ebb4caSwyllys 	 * Now try to read it as raw DER data.
469199ebb4caSwyllys 	 */
469299ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
469399ebb4caSwyllys 	if (bio == NULL)	{
469499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
469599ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
469699ebb4caSwyllys 		goto out;
469799ebb4caSwyllys 	}
469899ebb4caSwyllys 
469999ebb4caSwyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
470099ebb4caSwyllys 		*pformat = KMF_FORMAT_ASN1;
470199ebb4caSwyllys 	} else {
470299ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
470399ebb4caSwyllys 	}
470499ebb4caSwyllys 
470599ebb4caSwyllys out:
470699ebb4caSwyllys 	if (bio != NULL)
470799ebb4caSwyllys 		(void) BIO_free(bio);
470899ebb4caSwyllys 
470999ebb4caSwyllys 	if (xcrl != NULL)
471099ebb4caSwyllys 		X509_CRL_free(xcrl);
471199ebb4caSwyllys 
471299ebb4caSwyllys 	return (ret);
471399ebb4caSwyllys }
471499ebb4caSwyllys 
471599ebb4caSwyllys /*
471699ebb4caSwyllys  * Check a file to see if it is a certficate file with PEM or DER format.
471799ebb4caSwyllys  * If success, return its format in the pformat argument.
471899ebb4caSwyllys  */
471999ebb4caSwyllys KMF_RETURN
472099ebb4caSwyllys OpenSSL_IsCertFile(KMF_HANDLE_T handle, char *filename,
472199ebb4caSwyllys 	KMF_ENCODE_FORMAT *pformat)
472299ebb4caSwyllys {
472399ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
472499ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
472599ebb4caSwyllys 	BIO		*bio = NULL;
472699ebb4caSwyllys 	X509		*xcert = NULL;
472799ebb4caSwyllys 
472899ebb4caSwyllys 	if (filename == NULL) {
472999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
473099ebb4caSwyllys 	}
473199ebb4caSwyllys 
473230a5e8faSwyllys 	ret = kmf_get_file_format(filename, pformat);
473399ebb4caSwyllys 	if (ret != KMF_OK)
473499ebb4caSwyllys 		return (ret);
473599ebb4caSwyllys 
473699ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
473799ebb4caSwyllys 	if (bio == NULL)	{
473899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
473999ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
474099ebb4caSwyllys 		goto out;
474199ebb4caSwyllys 	}
474299ebb4caSwyllys 
474399ebb4caSwyllys 	if ((*pformat) == KMF_FORMAT_PEM) {
474499ebb4caSwyllys 		if ((xcert = PEM_read_bio_X509(bio, NULL,
474599ebb4caSwyllys 		    NULL, NULL)) == NULL) {
474699ebb4caSwyllys 			ret = KMF_ERR_BAD_CERTFILE;
474799ebb4caSwyllys 		}
474899ebb4caSwyllys 	} else if ((*pformat) == KMF_FORMAT_ASN1) {
474999ebb4caSwyllys 		if ((xcert = d2i_X509_bio(bio, NULL)) == NULL) {
475099ebb4caSwyllys 			ret = KMF_ERR_BAD_CERTFILE;
475199ebb4caSwyllys 		}
475299ebb4caSwyllys 	} else {
475399ebb4caSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
475499ebb4caSwyllys 	}
475599ebb4caSwyllys 
475699ebb4caSwyllys out:
475799ebb4caSwyllys 	if (bio != NULL)
475899ebb4caSwyllys 		(void) BIO_free(bio);
475999ebb4caSwyllys 
476099ebb4caSwyllys 	if (xcert != NULL)
476199ebb4caSwyllys 		X509_free(xcert);
476299ebb4caSwyllys 
476399ebb4caSwyllys 	return (ret);
476499ebb4caSwyllys }
476599ebb4caSwyllys 
476699ebb4caSwyllys KMF_RETURN
476799ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
476899ebb4caSwyllys     KMF_RAW_SYM_KEY *rkey)
476999ebb4caSwyllys {
477099ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
477199ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
477299ebb4caSwyllys 	KMF_DATA	keyvalue;
477399ebb4caSwyllys 
477499ebb4caSwyllys 	if (kmfh == NULL)
477599ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
477699ebb4caSwyllys 
477799ebb4caSwyllys 	if (symkey == NULL || rkey == NULL)
477899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
477999ebb4caSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
478099ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
478199ebb4caSwyllys 
478299ebb4caSwyllys 	if (symkey->israw) {
478399ebb4caSwyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
478499ebb4caSwyllys 
478599ebb4caSwyllys 		if (rawkey == NULL ||
478699ebb4caSwyllys 		    rawkey->keydata.val == NULL ||
478799ebb4caSwyllys 		    rawkey->keydata.len == 0)
478899ebb4caSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
478999ebb4caSwyllys 
479099ebb4caSwyllys 		rkey->keydata.len = rawkey->keydata.len;
479199ebb4caSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
479299ebb4caSwyllys 			return (KMF_ERR_MEMORY);
479399ebb4caSwyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
479499ebb4caSwyllys 		    rkey->keydata.len);
479599ebb4caSwyllys 	} else {
479630a5e8faSwyllys 		rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
479799ebb4caSwyllys 		if (rv != KMF_OK)
479899ebb4caSwyllys 			return (rv);
479999ebb4caSwyllys 		rkey->keydata.len = keyvalue.Length;
480099ebb4caSwyllys 		rkey->keydata.val = keyvalue.Data;
480199ebb4caSwyllys 	}
480299ebb4caSwyllys 
480399ebb4caSwyllys 	return (rv);
480499ebb4caSwyllys }
480502744e81Swyllys 
480602744e81Swyllys /*
480702744e81Swyllys  * id-sha1    OBJECT IDENTIFIER ::= {
480802744e81Swyllys  *     iso(1) identified-organization(3) oiw(14) secsig(3)
480902744e81Swyllys  *     algorithms(2) 26
481002744e81Swyllys  * }
481102744e81Swyllys  */
481202744e81Swyllys #define	ASN1_SHA1_OID_PREFIX_LEN 15
481302744e81Swyllys static uchar_t SHA1_DER_PREFIX[ASN1_SHA1_OID_PREFIX_LEN] = {
481402744e81Swyllys 	0x30, 0x21, 0x30, 0x09,
481502744e81Swyllys 	0x06, 0x05, 0x2b, 0x0e,
481602744e81Swyllys 	0x03, 0x02, 0x1a, 0x05,
481702744e81Swyllys 	0x00, 0x04, 0x14
481802744e81Swyllys };
481902744e81Swyllys 
482002744e81Swyllys /*
482102744e81Swyllys  * id-md2 OBJECT IDENTIFIER ::= {
482202744e81Swyllys  *     iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2
482302744e81Swyllys  * }
482402744e81Swyllys  */
482502744e81Swyllys #define	ASN1_MD2_OID_PREFIX_LEN 18
482602744e81Swyllys static uchar_t MD2_DER_PREFIX[ASN1_MD2_OID_PREFIX_LEN] = {
482702744e81Swyllys 	0x30, 0x20, 0x30, 0x0c,
482802744e81Swyllys 	0x06, 0x08, 0x2a, 0x86,
482902744e81Swyllys 	0x48, 0x86, 0xf7, 0x0d,
483002744e81Swyllys 	0x02, 0x02, 0x05, 0x00,
483102744e81Swyllys 	0x04, 0x10
483202744e81Swyllys };
483302744e81Swyllys 
483402744e81Swyllys /*
483502744e81Swyllys  * id-md5 OBJECT IDENTIFIER ::= {
483602744e81Swyllys  *     iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5
483702744e81Swyllys  * }
483802744e81Swyllys  */
483902744e81Swyllys #define	ASN1_MD5_OID_PREFIX_LEN 18
484002744e81Swyllys static uchar_t MD5_DER_PREFIX[ASN1_MD5_OID_PREFIX_LEN] = {
484102744e81Swyllys 	0x30, 0x20, 0x30, 0x0c,
484202744e81Swyllys 	0x06, 0x08, 0x2a, 0x86,
484302744e81Swyllys 	0x48, 0x86, 0xf7, 0x0d,
484402744e81Swyllys 	0x02, 0x05, 0x05, 0x00,
484502744e81Swyllys 	0x04, 0x10
484602744e81Swyllys };
484702744e81Swyllys 
484802744e81Swyllys KMF_RETURN
484902744e81Swyllys OpenSSL_VerifyDataWithCert(KMF_HANDLE_T handle,
485002744e81Swyllys 	KMF_ALGORITHM_INDEX algid, KMF_DATA *indata,
485102744e81Swyllys 	KMF_DATA *insig, KMF_DATA *cert)
485202744e81Swyllys {
485302744e81Swyllys 	KMF_RETURN ret = KMF_OK;
485402744e81Swyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
485502744e81Swyllys 	X509	*xcert = NULL;
485602744e81Swyllys 	EVP_PKEY *pkey = NULL;
485702744e81Swyllys 	uchar_t *p;
485802744e81Swyllys 	uchar_t *rsaout = NULL;
485902744e81Swyllys 	uchar_t *pfx = NULL;
486002744e81Swyllys 	const EVP_MD *md;
486102744e81Swyllys 	int pfxlen = 0, len;
486202744e81Swyllys 
486302744e81Swyllys 	if (handle == NULL || indata == NULL ||
486402744e81Swyllys 	    indata->Data == NULL || indata->Length == 0 ||
486502744e81Swyllys 	    insig == NULL|| insig->Data == NULL || insig->Length == 0 ||
486602744e81Swyllys 	    cert == NULL || cert->Data == NULL || cert->Length == 0)
486702744e81Swyllys 		return (KMF_ERR_BAD_PARAMETER);
486802744e81Swyllys 
486902744e81Swyllys 	p = cert->Data;
487002744e81Swyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, cert->Length);
487102744e81Swyllys 	if (xcert == NULL) {
487202744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
487302744e81Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
487402744e81Swyllys 		goto cleanup;
487502744e81Swyllys 	}
487602744e81Swyllys 
487702744e81Swyllys 	pkey = X509_get_pubkey(xcert);
487830a5e8faSwyllys 	if (pkey == NULL) {
487902744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
488002744e81Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
488102744e81Swyllys 		goto cleanup;
488202744e81Swyllys 	}
488302744e81Swyllys 
488402744e81Swyllys 	if (algid != KMF_ALGID_NONE) {
488502744e81Swyllys 		switch (algid) {
488602744e81Swyllys 			case KMF_ALGID_MD5WithRSA:
488702744e81Swyllys 				md = EVP_md5();
488802744e81Swyllys 				break;
488902744e81Swyllys 			case KMF_ALGID_MD2WithRSA:
489002744e81Swyllys 				md = EVP_md2();
489102744e81Swyllys 				break;
489202744e81Swyllys 			case KMF_ALGID_SHA1WithRSA:
489302744e81Swyllys 				md = EVP_sha1();
489402744e81Swyllys 				break;
489502744e81Swyllys 			case KMF_ALGID_RSA:
489602744e81Swyllys 				md = NULL;
489702744e81Swyllys 				break;
489802744e81Swyllys 			default:
489902744e81Swyllys 				ret = KMF_ERR_BAD_PARAMETER;
490002744e81Swyllys 				goto cleanup;
490102744e81Swyllys 		}
490202744e81Swyllys 	} else {
490302744e81Swyllys 		/* Get the hash type from the cert signature */
490402744e81Swyllys 		md = EVP_get_digestbyobj(xcert->sig_alg->algorithm);
490502744e81Swyllys 		if (md == NULL) {
490602744e81Swyllys 			SET_ERROR(kmfh, ERR_get_error());
490702744e81Swyllys 			ret = KMF_ERR_BAD_PARAMETER;
490802744e81Swyllys 			goto cleanup;
490902744e81Swyllys 		}
491002744e81Swyllys 	}
49119b37d296Swyllys 	if (md != NULL) {
491202744e81Swyllys 		switch (EVP_MD_type(md)) {
491302744e81Swyllys 		case NID_md2:
491402744e81Swyllys 		case NID_md2WithRSAEncryption:
491502744e81Swyllys 			pfxlen = ASN1_MD2_OID_PREFIX_LEN;
491602744e81Swyllys 			pfx = MD2_DER_PREFIX;
491702744e81Swyllys 			break;
491802744e81Swyllys 		case NID_md5:
491902744e81Swyllys 		case NID_md5WithRSAEncryption:
492002744e81Swyllys 			pfxlen = ASN1_MD5_OID_PREFIX_LEN;
492102744e81Swyllys 			pfx = MD5_DER_PREFIX;
492202744e81Swyllys 			break;
492302744e81Swyllys 		case NID_sha1:
492402744e81Swyllys 		case NID_sha1WithRSAEncryption:
492502744e81Swyllys 			pfxlen = ASN1_SHA1_OID_PREFIX_LEN;
492602744e81Swyllys 			pfx = SHA1_DER_PREFIX;
492702744e81Swyllys 			break;
492802744e81Swyllys 		default: /* Unsupported */
492902744e81Swyllys 			pfxlen = 0;
493002744e81Swyllys 			pfx = NULL;
493102744e81Swyllys 			break;
493202744e81Swyllys 		}
49339b37d296Swyllys 	}
493402744e81Swyllys 
493502744e81Swyllys 	/* RSA with no hash is a special case */
493602744e81Swyllys 	rsaout = malloc(RSA_size(pkey->pkey.rsa));
493702744e81Swyllys 	if (rsaout == NULL)
493802744e81Swyllys 		return (KMF_ERR_MEMORY);
493902744e81Swyllys 
494002744e81Swyllys 	/* Decrypt the input signature */
494102744e81Swyllys 	len = RSA_public_decrypt(insig->Length,
494202744e81Swyllys 	    insig->Data, rsaout, pkey->pkey.rsa, RSA_PKCS1_PADDING);
494302744e81Swyllys 	if (len < 1) {
494402744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
494502744e81Swyllys 		ret = KMF_ERR_BAD_PARAMETER;
494602744e81Swyllys 	} else {
494702744e81Swyllys 		size_t hashlen = 0;
494802744e81Swyllys 		uint32_t dlen;
494902744e81Swyllys 		char *digest = NULL;
495002744e81Swyllys 
495102744e81Swyllys 		/*
495202744e81Swyllys 		 * If the AlgId requires it, hash the input data before
495302744e81Swyllys 		 * comparing it to the decrypted signature.
495402744e81Swyllys 		 */
495502744e81Swyllys 		if (md) {
495602744e81Swyllys 			EVP_MD_CTX ctx;
495702744e81Swyllys 
495802744e81Swyllys 			hashlen = md->md_size;
495902744e81Swyllys 
496002744e81Swyllys 			digest = malloc(hashlen + pfxlen);
496102744e81Swyllys 			if (digest == NULL)
496202744e81Swyllys 				return (KMF_ERR_MEMORY);
496302744e81Swyllys 			/* Add the prefix to the comparison buffer. */
496402744e81Swyllys 			if (pfx && pfxlen > 0) {
496502744e81Swyllys 				(void) memcpy(digest, pfx, pfxlen);
496602744e81Swyllys 			}
496702744e81Swyllys 			(void) EVP_DigestInit(&ctx, md);
496802744e81Swyllys 			(void) EVP_DigestUpdate(&ctx, indata->Data,
496902744e81Swyllys 			    indata->Length);
497002744e81Swyllys 
497102744e81Swyllys 			/* Add the digest AFTER the ASN1 prefix */
497202744e81Swyllys 			(void) EVP_DigestFinal(&ctx,
497302744e81Swyllys 			    (uchar_t *)digest + pfxlen, &dlen);
497402744e81Swyllys 
497502744e81Swyllys 			dlen += pfxlen;
497602744e81Swyllys 		} else {
497702744e81Swyllys 			digest = (char *)indata->Data;
497802744e81Swyllys 			dlen = indata->Length;
497902744e81Swyllys 		}
498002744e81Swyllys 
498102744e81Swyllys 		/*
498202744e81Swyllys 		 * The result of the RSA decryption should be ASN1(OID | Hash).
498302744e81Swyllys 		 * Compare the output hash to the input data for the final
498402744e81Swyllys 		 * result.
498502744e81Swyllys 		 */
498602744e81Swyllys 		if (memcmp(rsaout, digest, dlen))
498702744e81Swyllys 			ret = KMF_ERR_INTERNAL;
498802744e81Swyllys 		else
498902744e81Swyllys 			ret = KMF_OK;
499002744e81Swyllys 
499102744e81Swyllys 		/* If we had to allocate space for the digest, free it now */
499202744e81Swyllys 		if (hashlen)
499302744e81Swyllys 			free(digest);
499402744e81Swyllys 	}
499502744e81Swyllys cleanup:
499602744e81Swyllys 	if (pkey)
499702744e81Swyllys 		EVP_PKEY_free(pkey);
499802744e81Swyllys 
499902744e81Swyllys 	if (xcert)
500002744e81Swyllys 		X509_free(xcert);
500102744e81Swyllys 
500202744e81Swyllys 	if (rsaout)
500302744e81Swyllys 		free(rsaout);
500402744e81Swyllys 
500502744e81Swyllys 	return (ret);
500602744e81Swyllys }
500730a5e8faSwyllys 
500830a5e8faSwyllys /*
500930a5e8faSwyllys  * substitute for the unsafe access(2) function.
501030a5e8faSwyllys  * If the file in question already exists, return 1.
501130a5e8faSwyllys  * else 0.  If an error occurs during testing (other
501230a5e8faSwyllys  * than EEXIST), return -1.
501330a5e8faSwyllys  */
501430a5e8faSwyllys static int
501530a5e8faSwyllys test_for_file(char *filename, mode_t mode)
501630a5e8faSwyllys {
501730a5e8faSwyllys 	int fd;
501830a5e8faSwyllys 
501930a5e8faSwyllys 	/*
502030a5e8faSwyllys 	 * Try to create the file with the EXCL flag.
502130a5e8faSwyllys 	 * The call should fail if the file exists.
502230a5e8faSwyllys 	 */
502330a5e8faSwyllys 	fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
502430a5e8faSwyllys 	if (fd == -1 && errno == EEXIST)
502530a5e8faSwyllys 		return (1);
502630a5e8faSwyllys 	else if (fd == -1) /* some other error */
502730a5e8faSwyllys 		return (-1);
502830a5e8faSwyllys 
502930a5e8faSwyllys 	/* The file did NOT exist.  Delete the testcase. */
503030a5e8faSwyllys 	(void) close(fd);
503130a5e8faSwyllys 	(void) unlink(filename);
503230a5e8faSwyllys 	return (0);
503330a5e8faSwyllys }
503430a5e8faSwyllys 
503530a5e8faSwyllys KMF_RETURN
503630a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
503730a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
503830a5e8faSwyllys {
503930a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
504030a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
504130a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
504230a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
504330a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
504430a5e8faSwyllys 	KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
504530a5e8faSwyllys 	KMF_CREDENTIAL cred = {NULL, 0};
504630a5e8faSwyllys 	BIO *out = NULL;
504730a5e8faSwyllys 	int keys = 0;
504830a5e8faSwyllys 	char *fullpath = NULL;
504930a5e8faSwyllys 	char *keyfile = NULL;
505030a5e8faSwyllys 	char *dirpath = NULL;
505130a5e8faSwyllys 
505230a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
505330a5e8faSwyllys 	if (pubkey != NULL)
505430a5e8faSwyllys 		keys++;
505530a5e8faSwyllys 
505630a5e8faSwyllys 	prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
505730a5e8faSwyllys 	if (prikey != NULL)
505830a5e8faSwyllys 		keys++;
505930a5e8faSwyllys 
506030a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
506130a5e8faSwyllys 	if (rawkey != NULL)
506230a5e8faSwyllys 		keys++;
506330a5e8faSwyllys 
506430a5e8faSwyllys 	/*
506530a5e8faSwyllys 	 * Exactly 1 type of key must be passed to this function.
506630a5e8faSwyllys 	 */
506730a5e8faSwyllys 	if (keys != 1)
506830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
506930a5e8faSwyllys 
507030a5e8faSwyllys 	keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
507130a5e8faSwyllys 	    numattr);
507230a5e8faSwyllys 	if (keyfile == NULL)
507330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
507430a5e8faSwyllys 
507530a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
507630a5e8faSwyllys 
507730a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
507830a5e8faSwyllys 
507930a5e8faSwyllys 	/* Once we have the full path, we don't need the pieces */
508030a5e8faSwyllys 	if (fullpath == NULL)
508130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
508230a5e8faSwyllys 
508330a5e8faSwyllys 	/* If the requested file exists, return an error */
508430a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
508530a5e8faSwyllys 		free(fullpath);
508630a5e8faSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
508730a5e8faSwyllys 	}
508830a5e8faSwyllys 
508930a5e8faSwyllys 	rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
509030a5e8faSwyllys 	    &format, NULL);
509130a5e8faSwyllys 	if (rv != KMF_OK)
509230a5e8faSwyllys 		/* format is optional. */
509330a5e8faSwyllys 		rv = KMF_OK;
509430a5e8faSwyllys 
509530a5e8faSwyllys 	/* CRED is not required for OpenSSL files */
509630a5e8faSwyllys 	(void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
509730a5e8faSwyllys 	    &cred, NULL);
509830a5e8faSwyllys 
509930a5e8faSwyllys 	/* Store the private key to the keyfile */
510030a5e8faSwyllys 	out = BIO_new_file(fullpath, "wb");
510130a5e8faSwyllys 	if (out == NULL) {
510230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
510330a5e8faSwyllys 		rv = KMF_ERR_OPEN_FILE;
510430a5e8faSwyllys 		goto end;
510530a5e8faSwyllys 	}
510630a5e8faSwyllys 
510730a5e8faSwyllys 	if (prikey != NULL && prikey->keyp != NULL) {
510830a5e8faSwyllys 		if (prikey->keyalg == KMF_RSA ||
510930a5e8faSwyllys 		    prikey->keyalg == KMF_DSA) {
511030a5e8faSwyllys 			pkey = (EVP_PKEY *)prikey->keyp;
511130a5e8faSwyllys 
511230a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
511330a5e8faSwyllys 			    out, &cred, pkey, TRUE);
511430a5e8faSwyllys 
511530a5e8faSwyllys 			if (rv == KMF_OK && prikey->keylabel == NULL) {
511630a5e8faSwyllys 				prikey->keylabel = strdup(fullpath);
511730a5e8faSwyllys 				if (prikey->keylabel == NULL)
511830a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
511930a5e8faSwyllys 			}
512030a5e8faSwyllys 		}
512130a5e8faSwyllys 	} else if (pubkey != NULL && pubkey->keyp != NULL) {
512230a5e8faSwyllys 		if (pubkey->keyalg == KMF_RSA ||
512330a5e8faSwyllys 		    pubkey->keyalg == KMF_DSA) {
512430a5e8faSwyllys 			pkey = (EVP_PKEY *)pubkey->keyp;
512530a5e8faSwyllys 
512630a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
512730a5e8faSwyllys 			    out, &cred, pkey, FALSE);
512830a5e8faSwyllys 
512930a5e8faSwyllys 			if (rv == KMF_OK && pubkey->keylabel == NULL) {
513030a5e8faSwyllys 				pubkey->keylabel = strdup(fullpath);
513130a5e8faSwyllys 				if (pubkey->keylabel == NULL)
513230a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
513330a5e8faSwyllys 			}
513430a5e8faSwyllys 		}
513530a5e8faSwyllys 	} else if (rawkey != NULL) {
513630a5e8faSwyllys 		/* RAW keys are always private */
513730a5e8faSwyllys 		if (rawkey->keytype == KMF_RSA) {
513830a5e8faSwyllys 			pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
513930a5e8faSwyllys 		} else if (rawkey->keytype == KMF_DSA) {
514030a5e8faSwyllys 			pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
514130a5e8faSwyllys 		} else {
514230a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
514330a5e8faSwyllys 		}
5144*5b3e1433Swyllys 		if (pkey != NULL) {
5145*5b3e1433Swyllys 			rv = ssl_write_key(kmfh, format, out,
5146*5b3e1433Swyllys 			    &cred, pkey, TRUE);
5147*5b3e1433Swyllys 			EVP_PKEY_free(pkey);
5148*5b3e1433Swyllys 		}
514930a5e8faSwyllys 	}
515030a5e8faSwyllys 
515130a5e8faSwyllys end:
515230a5e8faSwyllys 
515330a5e8faSwyllys 	if (out)
515430a5e8faSwyllys 		(void) BIO_free(out);
515530a5e8faSwyllys 
5156*5b3e1433Swyllys 
515730a5e8faSwyllys 	if (rv == KMF_OK)
515830a5e8faSwyllys 		(void) chmod(fullpath, 0400);
515930a5e8faSwyllys 
516030a5e8faSwyllys 	free(fullpath);
516130a5e8faSwyllys 	return (rv);
516230a5e8faSwyllys }
516330a5e8faSwyllys 
516430a5e8faSwyllys KMF_RETURN
516530a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
516630a5e8faSwyllys {
516730a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
516830a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
516930a5e8faSwyllys 	X509_CRL *xcrl = NULL;
517030a5e8faSwyllys 	X509 *xcert = NULL;
517130a5e8faSwyllys 	EVP_PKEY *pkey;
517230a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
517330a5e8faSwyllys 	BIO *in = NULL, *out = NULL;
517430a5e8faSwyllys 	int openssl_ret = 0;
517530a5e8faSwyllys 	KMF_ENCODE_FORMAT outformat;
517630a5e8faSwyllys 	boolean_t crlcheck = FALSE;
517730a5e8faSwyllys 	char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
517830a5e8faSwyllys 
517930a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
518030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
518130a5e8faSwyllys 	}
518230a5e8faSwyllys 
518330a5e8faSwyllys 	/* CRL check is optional */
518430a5e8faSwyllys 	(void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
518530a5e8faSwyllys 	    &crlcheck, NULL);
518630a5e8faSwyllys 
518730a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
518830a5e8faSwyllys 	if (crlcheck == B_TRUE && certfile == NULL) {
518930a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
519030a5e8faSwyllys 	}
519130a5e8faSwyllys 
519230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
519330a5e8faSwyllys 	incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
519430a5e8faSwyllys 	outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
519530a5e8faSwyllys 
519630a5e8faSwyllys 	crlfile = get_fullpath(dirpath, incrl);
519730a5e8faSwyllys 
519830a5e8faSwyllys 	if (crlfile == NULL)
519930a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
520030a5e8faSwyllys 
520130a5e8faSwyllys 	outcrlfile = get_fullpath(dirpath, outcrl);
520230a5e8faSwyllys 	if (outcrlfile == NULL)
520330a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
520430a5e8faSwyllys 
520530a5e8faSwyllys 	if (isdir(outcrlfile)) {
520630a5e8faSwyllys 		free(outcrlfile);
520730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
520830a5e8faSwyllys 	}
520930a5e8faSwyllys 
521030a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
521130a5e8faSwyllys 	if (ret != KMF_OK) {
521230a5e8faSwyllys 		free(outcrlfile);
521330a5e8faSwyllys 		return (ret);
521430a5e8faSwyllys 	}
521530a5e8faSwyllys 
521630a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
521730a5e8faSwyllys 	if (in == NULL)	{
521830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
521930a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
522030a5e8faSwyllys 		goto end;
522130a5e8faSwyllys 	}
522230a5e8faSwyllys 
522330a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
522430a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
522530a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
522630a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
522730a5e8faSwyllys 	}
522830a5e8faSwyllys 
522930a5e8faSwyllys 	if (xcrl == NULL) {
523030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
523130a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
523230a5e8faSwyllys 		goto end;
523330a5e8faSwyllys 	}
523430a5e8faSwyllys 
523530a5e8faSwyllys 	/* If bypasscheck is specified, no need to verify. */
523630a5e8faSwyllys 	if (crlcheck == B_FALSE)
523730a5e8faSwyllys 		goto output;
523830a5e8faSwyllys 
523930a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
524030a5e8faSwyllys 	if (ret != KMF_OK)
524130a5e8faSwyllys 		goto end;
524230a5e8faSwyllys 
524330a5e8faSwyllys 	/* Read in the CA cert file and convert to X509 */
524430a5e8faSwyllys 	if (BIO_read_filename(in, certfile) <= 0) {
524530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
524630a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
524730a5e8faSwyllys 		goto end;
524830a5e8faSwyllys 	}
524930a5e8faSwyllys 
525030a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
525130a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
525230a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
525330a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
525430a5e8faSwyllys 	} else {
525530a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
525630a5e8faSwyllys 		goto end;
525730a5e8faSwyllys 	}
525830a5e8faSwyllys 
525930a5e8faSwyllys 	if (xcert == NULL) {
526030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
526130a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
526230a5e8faSwyllys 		goto end;
526330a5e8faSwyllys 	}
526430a5e8faSwyllys 	/* Now get the public key from the CA cert */
526530a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
526630a5e8faSwyllys 	if (pkey == NULL) {
526730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
526830a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
526930a5e8faSwyllys 		goto end;
527030a5e8faSwyllys 	}
527130a5e8faSwyllys 
527230a5e8faSwyllys 	/* Verify the CRL with the CA's public key */
527330a5e8faSwyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
527430a5e8faSwyllys 	EVP_PKEY_free(pkey);
527530a5e8faSwyllys 	if (openssl_ret > 0) {
527630a5e8faSwyllys 		ret = KMF_OK;  /* verify succeed */
527730a5e8faSwyllys 	} else {
527830a5e8faSwyllys 		SET_ERROR(kmfh, openssl_ret);
527930a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
528030a5e8faSwyllys 	}
528130a5e8faSwyllys 
528230a5e8faSwyllys output:
528330a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
528430a5e8faSwyllys 	    &outformat, NULL);
528530a5e8faSwyllys 	if (ret != KMF_OK) {
528630a5e8faSwyllys 		ret = KMF_OK;
528730a5e8faSwyllys 		outformat = KMF_FORMAT_PEM;
528830a5e8faSwyllys 	}
528930a5e8faSwyllys 
529030a5e8faSwyllys 	out = BIO_new_file(outcrlfile, "wb");
529130a5e8faSwyllys 	if (out == NULL) {
529230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
529330a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
529430a5e8faSwyllys 		goto end;
529530a5e8faSwyllys 	}
529630a5e8faSwyllys 
529730a5e8faSwyllys 	if (outformat == KMF_FORMAT_ASN1) {
529830a5e8faSwyllys 		openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
529930a5e8faSwyllys 	} else if (outformat == KMF_FORMAT_PEM) {
530030a5e8faSwyllys 		openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
530130a5e8faSwyllys 	} else {
530230a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
530330a5e8faSwyllys 		goto end;
530430a5e8faSwyllys 	}
530530a5e8faSwyllys 
530630a5e8faSwyllys 	if (openssl_ret <= 0) {
530730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
530830a5e8faSwyllys 		ret = KMF_ERR_WRITE_FILE;
530930a5e8faSwyllys 	} else {
531030a5e8faSwyllys 		ret = KMF_OK;
531130a5e8faSwyllys 	}
531230a5e8faSwyllys 
531330a5e8faSwyllys end:
531430a5e8faSwyllys 	if (xcrl != NULL)
531530a5e8faSwyllys 		X509_CRL_free(xcrl);
531630a5e8faSwyllys 
531730a5e8faSwyllys 	if (xcert != NULL)
531830a5e8faSwyllys 		X509_free(xcert);
531930a5e8faSwyllys 
532030a5e8faSwyllys 	if (in != NULL)
532130a5e8faSwyllys 		(void) BIO_free(in);
532230a5e8faSwyllys 
532330a5e8faSwyllys 	if (out != NULL)
532430a5e8faSwyllys 		(void) BIO_free(out);
532530a5e8faSwyllys 
532630a5e8faSwyllys 	if (outcrlfile != NULL)
532730a5e8faSwyllys 		free(outcrlfile);
532830a5e8faSwyllys 
532930a5e8faSwyllys 	return (ret);
533030a5e8faSwyllys }
533130a5e8faSwyllys 
533230a5e8faSwyllys KMF_RETURN
533330a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
533430a5e8faSwyllys {
533530a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
533630a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
533730a5e8faSwyllys 	X509_CRL   *x = NULL;
533830a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
533930a5e8faSwyllys 	char *crlfile = NULL;
534030a5e8faSwyllys 	BIO *in = NULL;
534130a5e8faSwyllys 	BIO *mem = NULL;
534230a5e8faSwyllys 	long len;
534330a5e8faSwyllys 	char *memptr;
534430a5e8faSwyllys 	char *data = NULL;
534530a5e8faSwyllys 	char **crldata;
534630a5e8faSwyllys 	char *crlfilename, *dirpath;
534730a5e8faSwyllys 
534830a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
534930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
535030a5e8faSwyllys 	}
535130a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
535230a5e8faSwyllys 	    attrlist, numattr);
535330a5e8faSwyllys 	if (crlfilename == NULL)
535430a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
535530a5e8faSwyllys 
535630a5e8faSwyllys 	crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
535730a5e8faSwyllys 	    attrlist, numattr);
535830a5e8faSwyllys 
535930a5e8faSwyllys 	if (crldata == NULL)
536030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
536130a5e8faSwyllys 
536230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
536330a5e8faSwyllys 
536430a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
536530a5e8faSwyllys 
536630a5e8faSwyllys 	if (crlfile == NULL)
536730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
536830a5e8faSwyllys 
536930a5e8faSwyllys 	if (isdir(crlfile)) {
537030a5e8faSwyllys 		free(crlfile);
537130a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
537230a5e8faSwyllys 	}
537330a5e8faSwyllys 
537430a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
537530a5e8faSwyllys 	if (ret != KMF_OK) {
537630a5e8faSwyllys 		free(crlfile);
537730a5e8faSwyllys 		return (ret);
537830a5e8faSwyllys 	}
537930a5e8faSwyllys 
538030a5e8faSwyllys 	if (bio_err == NULL)
538130a5e8faSwyllys 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
538230a5e8faSwyllys 
538330a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
538430a5e8faSwyllys 	if (in == NULL)	{
538530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
538630a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
538730a5e8faSwyllys 		goto end;
538830a5e8faSwyllys 	}
538930a5e8faSwyllys 
539030a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
539130a5e8faSwyllys 		x = d2i_X509_CRL_bio(in, NULL);
539230a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
539330a5e8faSwyllys 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
539430a5e8faSwyllys 	}
539530a5e8faSwyllys 
539630a5e8faSwyllys 	if (x == NULL) { /* should not happen */
539730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
539830a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
539930a5e8faSwyllys 		goto end;
540030a5e8faSwyllys 	}
540130a5e8faSwyllys 
540230a5e8faSwyllys 	mem = BIO_new(BIO_s_mem());
540330a5e8faSwyllys 	if (mem == NULL) {
540430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
540530a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
540630a5e8faSwyllys 		goto end;
540730a5e8faSwyllys 	}
540830a5e8faSwyllys 
540930a5e8faSwyllys 	(void) X509_CRL_print(mem, x);
541030a5e8faSwyllys 	len = BIO_get_mem_data(mem, &memptr);
541130a5e8faSwyllys 	if (len <= 0) {
541230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
541330a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
541430a5e8faSwyllys 		goto end;
541530a5e8faSwyllys 	}
541630a5e8faSwyllys 
541730a5e8faSwyllys 	data = malloc(len + 1);
541830a5e8faSwyllys 	if (data == NULL) {
541930a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
542030a5e8faSwyllys 		goto end;
542130a5e8faSwyllys 	}
542230a5e8faSwyllys 
542330a5e8faSwyllys 	(void) memcpy(data, memptr, len);
542430a5e8faSwyllys 	data[len] = '\0';
542530a5e8faSwyllys 	*crldata = data;
542630a5e8faSwyllys 
542730a5e8faSwyllys end:
542830a5e8faSwyllys 	if (x != NULL)
542930a5e8faSwyllys 		X509_CRL_free(x);
543030a5e8faSwyllys 
543130a5e8faSwyllys 	if (crlfile != NULL)
543230a5e8faSwyllys 		free(crlfile);
543330a5e8faSwyllys 
543430a5e8faSwyllys 	if (in != NULL)
543530a5e8faSwyllys 		(void) BIO_free(in);
543630a5e8faSwyllys 
543730a5e8faSwyllys 	if (mem != NULL)
543830a5e8faSwyllys 		(void) BIO_free(mem);
543930a5e8faSwyllys 
544030a5e8faSwyllys 	return (ret);
544130a5e8faSwyllys }
544230a5e8faSwyllys 
544330a5e8faSwyllys KMF_RETURN
544430a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
544530a5e8faSwyllys {
544630a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
544730a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
544830a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
544930a5e8faSwyllys 	char *crlfile = NULL;
545030a5e8faSwyllys 	BIO *in = NULL;
545130a5e8faSwyllys 	char *crlfilename, *dirpath;
545230a5e8faSwyllys 
545330a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
545430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
545530a5e8faSwyllys 	}
545630a5e8faSwyllys 
545730a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
545830a5e8faSwyllys 	    attrlist, numattr);
545930a5e8faSwyllys 
546030a5e8faSwyllys 	if (crlfilename == NULL)
546130a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
546230a5e8faSwyllys 
546330a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
546430a5e8faSwyllys 
546530a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
546630a5e8faSwyllys 
546730a5e8faSwyllys 	if (crlfile == NULL)
546830a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
546930a5e8faSwyllys 
547030a5e8faSwyllys 	if (isdir(crlfile)) {
547130a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
547230a5e8faSwyllys 		goto end;
547330a5e8faSwyllys 	}
547430a5e8faSwyllys 
547530a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
547630a5e8faSwyllys 	if (ret != KMF_OK)
547730a5e8faSwyllys 		goto end;
547830a5e8faSwyllys 
547930a5e8faSwyllys 	if (unlink(crlfile) != 0) {
548030a5e8faSwyllys 		SET_SYS_ERROR(kmfh, errno);
548130a5e8faSwyllys 		ret = KMF_ERR_INTERNAL;
548230a5e8faSwyllys 		goto end;
548330a5e8faSwyllys 	}
548430a5e8faSwyllys 
548530a5e8faSwyllys end:
548630a5e8faSwyllys 	if (in != NULL)
548730a5e8faSwyllys 		(void) BIO_free(in);
548830a5e8faSwyllys 	if (crlfile != NULL)
548930a5e8faSwyllys 		free(crlfile);
549030a5e8faSwyllys 
549130a5e8faSwyllys 	return (ret);
549230a5e8faSwyllys }
549330a5e8faSwyllys 
549430a5e8faSwyllys KMF_RETURN
549530a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
549630a5e8faSwyllys {
549730a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
549830a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
549930a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
550030a5e8faSwyllys 	BIO *in = NULL;
550130a5e8faSwyllys 	X509   *xcert = NULL;
550230a5e8faSwyllys 	X509_CRL   *xcrl = NULL;
550330a5e8faSwyllys 	STACK_OF(X509_REVOKED) *revoke_stack = NULL;
550430a5e8faSwyllys 	X509_REVOKED *revoke;
550530a5e8faSwyllys 	int i;
550630a5e8faSwyllys 	char *crlfilename, *crlfile, *dirpath, *certfile;
550730a5e8faSwyllys 
550830a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
550930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
551030a5e8faSwyllys 	}
551130a5e8faSwyllys 
551230a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
551330a5e8faSwyllys 	    attrlist, numattr);
551430a5e8faSwyllys 
551530a5e8faSwyllys 	if (crlfilename == NULL)
551630a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
551730a5e8faSwyllys 
551830a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
551930a5e8faSwyllys 	if (certfile == NULL)
552030a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
552130a5e8faSwyllys 
552230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
552330a5e8faSwyllys 
552430a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
552530a5e8faSwyllys 
552630a5e8faSwyllys 	if (crlfile == NULL)
552730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
552830a5e8faSwyllys 
552930a5e8faSwyllys 	if (isdir(crlfile)) {
553030a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
553130a5e8faSwyllys 		goto end;
553230a5e8faSwyllys 	}
553330a5e8faSwyllys 
553430a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
553530a5e8faSwyllys 	if (ret != KMF_OK)
553630a5e8faSwyllys 		goto end;
553730a5e8faSwyllys 
553830a5e8faSwyllys 	/* Read the CRL file and load it into a X509_CRL structure */
553930a5e8faSwyllys 	in = BIO_new_file(crlfilename, "rb");
554030a5e8faSwyllys 	if (in == NULL)	{
554130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
554230a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
554330a5e8faSwyllys 		goto end;
554430a5e8faSwyllys 	}
554530a5e8faSwyllys 
554630a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
554730a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
554830a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
554930a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
555030a5e8faSwyllys 	}
555130a5e8faSwyllys 
555230a5e8faSwyllys 	if (xcrl == NULL) {
555330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
555430a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
555530a5e8faSwyllys 		goto end;
555630a5e8faSwyllys 	}
555730a5e8faSwyllys 	(void) BIO_free(in);
555830a5e8faSwyllys 
555930a5e8faSwyllys 	/* Read the Certificate file and load it into a X509 structure */
556030a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
556130a5e8faSwyllys 	if (ret != KMF_OK)
556230a5e8faSwyllys 		goto end;
556330a5e8faSwyllys 
556430a5e8faSwyllys 	in = BIO_new_file(certfile, "rb");
556530a5e8faSwyllys 	if (in == NULL)	{
556630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
556730a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
556830a5e8faSwyllys 		goto end;
556930a5e8faSwyllys 	}
557030a5e8faSwyllys 
557130a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
557230a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
557330a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
557430a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
557530a5e8faSwyllys 	}
557630a5e8faSwyllys 
557730a5e8faSwyllys 	if (xcert == NULL) {
557830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
557930a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
558030a5e8faSwyllys 		goto end;
558130a5e8faSwyllys 	}
558230a5e8faSwyllys 
558330a5e8faSwyllys 	/* Check if the certificate and the CRL have same issuer */
558430a5e8faSwyllys 	if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) {
558530a5e8faSwyllys 		ret = KMF_ERR_ISSUER;
558630a5e8faSwyllys 		goto end;
558730a5e8faSwyllys 	}
558830a5e8faSwyllys 
558930a5e8faSwyllys 	/* Check to see if the certificate serial number is revoked */
559030a5e8faSwyllys 	revoke_stack = X509_CRL_get_REVOKED(xcrl);
559130a5e8faSwyllys 	if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
559230a5e8faSwyllys 		/* No revoked certificates in the CRL file */
559330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
559430a5e8faSwyllys 		ret = KMF_ERR_EMPTY_CRL;
559530a5e8faSwyllys 		goto end;
559630a5e8faSwyllys 	}
559730a5e8faSwyllys 
559830a5e8faSwyllys 	for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
559930a5e8faSwyllys 		/*LINTED*/
560030a5e8faSwyllys 		revoke = sk_X509_REVOKED_value(revoke_stack, i);
560130a5e8faSwyllys 		if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber,
560230a5e8faSwyllys 		    revoke->serialNumber) == 0) {
560330a5e8faSwyllys 			break;
560430a5e8faSwyllys 		}
560530a5e8faSwyllys 	}
560630a5e8faSwyllys 
560730a5e8faSwyllys 	if (i < sk_X509_REVOKED_num(revoke_stack)) {
560830a5e8faSwyllys 		ret = KMF_OK;
560930a5e8faSwyllys 	} else {
561030a5e8faSwyllys 		ret = KMF_ERR_NOT_REVOKED;
561130a5e8faSwyllys 	}
561230a5e8faSwyllys 
561330a5e8faSwyllys end:
561430a5e8faSwyllys 	if (in != NULL)
561530a5e8faSwyllys 		(void) BIO_free(in);
561630a5e8faSwyllys 	if (xcrl != NULL)
561730a5e8faSwyllys 		X509_CRL_free(xcrl);
561830a5e8faSwyllys 	if (xcert != NULL)
561930a5e8faSwyllys 		X509_free(xcert);
562030a5e8faSwyllys 
562130a5e8faSwyllys 	return (ret);
562230a5e8faSwyllys }
562330a5e8faSwyllys 
562430a5e8faSwyllys KMF_RETURN
562530a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
562630a5e8faSwyllys {
562730a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
562830a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
562930a5e8faSwyllys 	BIO		*bcrl = NULL;
563030a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
563130a5e8faSwyllys 	X509		*xcert = NULL;
563230a5e8faSwyllys 	EVP_PKEY	*pkey;
563330a5e8faSwyllys 	int		sslret;
563430a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
563530a5e8faSwyllys 	unsigned char	*p;
563630a5e8faSwyllys 	long		len;
563730a5e8faSwyllys 
563830a5e8faSwyllys 	if (handle == NULL || crlname == NULL || tacert == NULL) {
563930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
564030a5e8faSwyllys 	}
564130a5e8faSwyllys 
564230a5e8faSwyllys 	ret = kmf_get_file_format(crlname, &crl_format);
564330a5e8faSwyllys 	if (ret != KMF_OK)
564430a5e8faSwyllys 		return (ret);
564530a5e8faSwyllys 
564630a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
564730a5e8faSwyllys 	if (bcrl == NULL)	{
564830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
564930a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
565030a5e8faSwyllys 		goto cleanup;
565130a5e8faSwyllys 	}
565230a5e8faSwyllys 
565330a5e8faSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
565430a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
565530a5e8faSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
565630a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
565730a5e8faSwyllys 	} else {
565830a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
565930a5e8faSwyllys 		goto cleanup;
566030a5e8faSwyllys 	}
566130a5e8faSwyllys 
566230a5e8faSwyllys 	if (xcrl == NULL) {
566330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
566430a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
566530a5e8faSwyllys 		goto cleanup;
566630a5e8faSwyllys 	}
566730a5e8faSwyllys 
566830a5e8faSwyllys 	p = tacert->Data;
566930a5e8faSwyllys 	len = tacert->Length;
567030a5e8faSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
567130a5e8faSwyllys 
567230a5e8faSwyllys 	if (xcert == NULL) {
567330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
567430a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
567530a5e8faSwyllys 		goto cleanup;
567630a5e8faSwyllys 	}
567730a5e8faSwyllys 
567830a5e8faSwyllys 	/* Get issuer certificate public key */
567930a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
568030a5e8faSwyllys 	if (pkey == NULL) {
568130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
568230a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
568330a5e8faSwyllys 		goto cleanup;
568430a5e8faSwyllys 	}
568530a5e8faSwyllys 
568630a5e8faSwyllys 	/* Verify CRL signature */
568730a5e8faSwyllys 	sslret = X509_CRL_verify(xcrl, pkey);
568830a5e8faSwyllys 	EVP_PKEY_free(pkey);
568930a5e8faSwyllys 	if (sslret > 0) {
569030a5e8faSwyllys 		ret = KMF_OK;
569130a5e8faSwyllys 	} else {
569230a5e8faSwyllys 		SET_ERROR(kmfh, sslret);
569330a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
569430a5e8faSwyllys 	}
569530a5e8faSwyllys 
569630a5e8faSwyllys cleanup:
569730a5e8faSwyllys 	if (bcrl != NULL)
569830a5e8faSwyllys 		(void) BIO_free(bcrl);
569930a5e8faSwyllys 
570030a5e8faSwyllys 	if (xcrl != NULL)
570130a5e8faSwyllys 		X509_CRL_free(xcrl);
570230a5e8faSwyllys 
570330a5e8faSwyllys 	if (xcert != NULL)
570430a5e8faSwyllys 		X509_free(xcert);
570530a5e8faSwyllys 
570630a5e8faSwyllys 	return (ret);
570730a5e8faSwyllys 
570830a5e8faSwyllys }
570930a5e8faSwyllys 
571030a5e8faSwyllys KMF_RETURN
571130a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
571230a5e8faSwyllys {
571330a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
571430a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
571530a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
571630a5e8faSwyllys 	BIO		*bcrl = NULL;
571730a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
571830a5e8faSwyllys 	int		i;
571930a5e8faSwyllys 
572030a5e8faSwyllys 	if (handle == NULL || crlname == NULL) {
572130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
572230a5e8faSwyllys 	}
572330a5e8faSwyllys 
572430a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlname, &crl_format);
572530a5e8faSwyllys 	if (ret != KMF_OK)
572630a5e8faSwyllys 		return (ret);
572730a5e8faSwyllys 
572830a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
572930a5e8faSwyllys 	if (bcrl == NULL) {
573030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
573130a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
573230a5e8faSwyllys 		goto cleanup;
573330a5e8faSwyllys 	}
573430a5e8faSwyllys 
5735*5b3e1433Swyllys 	if (crl_format == KMF_FORMAT_ASN1)
573630a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
5737*5b3e1433Swyllys 	else if (crl_format == KMF_FORMAT_PEM)
573830a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
573930a5e8faSwyllys 
574030a5e8faSwyllys 	if (xcrl == NULL) {
574130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
574230a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
574330a5e8faSwyllys 		goto cleanup;
574430a5e8faSwyllys 	}
574530a5e8faSwyllys 	i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL);
574630a5e8faSwyllys 	if (i >= 0) {
574730a5e8faSwyllys 		ret = KMF_ERR_VALIDITY_PERIOD;
574830a5e8faSwyllys 		goto cleanup;
574930a5e8faSwyllys 	}
575030a5e8faSwyllys 	if (X509_CRL_get_nextUpdate(xcrl)) {
575130a5e8faSwyllys 		i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL);
575230a5e8faSwyllys 
575330a5e8faSwyllys 		if (i <= 0) {
575430a5e8faSwyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
575530a5e8faSwyllys 			goto cleanup;
575630a5e8faSwyllys 		}
575730a5e8faSwyllys 	}
575830a5e8faSwyllys 
575930a5e8faSwyllys 	ret = KMF_OK;
576030a5e8faSwyllys 
576130a5e8faSwyllys cleanup:
576230a5e8faSwyllys 	if (bcrl != NULL)
576330a5e8faSwyllys 		(void) BIO_free(bcrl);
576430a5e8faSwyllys 
576530a5e8faSwyllys 	if (xcrl != NULL)
576630a5e8faSwyllys 		X509_CRL_free(xcrl);
576730a5e8faSwyllys 
576830a5e8faSwyllys 	return (ret);
576930a5e8faSwyllys }
5770