199ebb4caSwyllys /*
22c9a247fSWyllys Ingersoll  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
32c9a247fSWyllys Ingersoll  *
499ebb4caSwyllys  * Use is subject to license terms.
599ebb4caSwyllys  */
69a767088Shaimay /*
770f9559bSTheo Schlossnagle  * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
8553e44ceSAndrew Stormont  * Copyright 2018 RackTop Systems.
9*4942e222SAndy Fiddaman  * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
1070f9559bSTheo Schlossnagle  */
1170f9559bSTheo Schlossnagle /*
129a767088Shaimay  * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
139a767088Shaimay  * project 2000.
149a767088Shaimay  */
159a767088Shaimay /*
169a767088Shaimay  * ====================================================================
179a767088Shaimay  * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
189a767088Shaimay  *
199a767088Shaimay  * Redistribution and use in source and binary forms, with or without
209a767088Shaimay  * modification, are permitted provided that the following conditions
219a767088Shaimay  * are met:
229a767088Shaimay  *
239a767088Shaimay  * 1. Redistributions of source code must retain the above copyright
249a767088Shaimay  *    notice, this list of conditions and the following disclaimer.
259a767088Shaimay  *
269a767088Shaimay  * 2. Redistributions in binary form must reproduce the above copyright
279a767088Shaimay  *    notice, this list of conditions and the following disclaimer in
289a767088Shaimay  *    the documentation and/or other materials provided with the
299a767088Shaimay  *    distribution.
309a767088Shaimay  *
319a767088Shaimay  * 3. All advertising materials mentioning features or use of this
329a767088Shaimay  *    software must display the following acknowledgment:
339a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
349a767088Shaimay  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
359a767088Shaimay  *
369a767088Shaimay  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
379a767088Shaimay  *    endorse or promote products derived from this software without
389a767088Shaimay  *    prior written permission. For written permission, please contact
399a767088Shaimay  *    licensing@OpenSSL.org.
409a767088Shaimay  *
419a767088Shaimay  * 5. Products derived from this software may not be called "OpenSSL"
429a767088Shaimay  *    nor may "OpenSSL" appear in their names without prior written
439a767088Shaimay  *    permission of the OpenSSL Project.
449a767088Shaimay  *
459a767088Shaimay  * 6. Redistributions of any form whatsoever must retain the following
469a767088Shaimay  *    acknowledgment:
479a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
489a767088Shaimay  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
499a767088Shaimay  *
509a767088Shaimay  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
519a767088Shaimay  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
529a767088Shaimay  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
539a767088Shaimay  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
549a767088Shaimay  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
559a767088Shaimay  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
569a767088Shaimay  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
579a767088Shaimay  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
589a767088Shaimay  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
599a767088Shaimay  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
609a767088Shaimay  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
619a767088Shaimay  * OF THE POSSIBILITY OF SUCH DAMAGE.
629a767088Shaimay  * ====================================================================
639a767088Shaimay  *
649a767088Shaimay  * This product includes cryptographic software written by Eric Young
659a767088Shaimay  * (eay@cryptsoft.com).  This product includes software written by Tim
669a767088Shaimay  * Hudson (tjh@cryptsoft.com).
679a767088Shaimay  *
689a767088Shaimay  */
6999ebb4caSwyllys 
7071593db2Swyllys #include <stdlib.h>
7199ebb4caSwyllys #include <kmfapiP.h>
7299ebb4caSwyllys #include <ber_der.h>
7399ebb4caSwyllys #include <fcntl.h>
7499ebb4caSwyllys #include <sys/stat.h>
7599ebb4caSwyllys #include <dirent.h>
7699ebb4caSwyllys #include <cryptoutil.h>
7799ebb4caSwyllys #include <synch.h>
7899ebb4caSwyllys #include <thread.h>
7999ebb4caSwyllys 
8099ebb4caSwyllys /* OPENSSL related headers */
8199ebb4caSwyllys #include <openssl/bio.h>
8299ebb4caSwyllys #include <openssl/bn.h>
8399ebb4caSwyllys #include <openssl/asn1.h>
8499ebb4caSwyllys #include <openssl/err.h>
8599ebb4caSwyllys #include <openssl/x509.h>
8699ebb4caSwyllys #include <openssl/rsa.h>
8799ebb4caSwyllys #include <openssl/dsa.h>
8899ebb4caSwyllys #include <openssl/x509v3.h>
8999ebb4caSwyllys #include <openssl/objects.h>
9099ebb4caSwyllys #include <openssl/pem.h>
9199ebb4caSwyllys #include <openssl/pkcs12.h>
9299ebb4caSwyllys #include <openssl/ocsp.h>
9399ebb4caSwyllys #include <openssl/des.h>
9499ebb4caSwyllys #include <openssl/rand.h>
95300fdee2SAndy Fiddaman #include "compat.h"
9699ebb4caSwyllys 
9799ebb4caSwyllys #define	PRINT_ANY_EXTENSION (\
9899ebb4caSwyllys 	KMF_X509_EXT_KEY_USAGE |\
9999ebb4caSwyllys 	KMF_X509_EXT_CERT_POLICIES |\
10099ebb4caSwyllys 	KMF_X509_EXT_SUBJALTNAME |\
10199ebb4caSwyllys 	KMF_X509_EXT_BASIC_CONSTRAINTS |\
10299ebb4caSwyllys 	KMF_X509_EXT_NAME_CONSTRAINTS |\
10399ebb4caSwyllys 	KMF_X509_EXT_POLICY_CONSTRAINTS |\
10499ebb4caSwyllys 	KMF_X509_EXT_EXT_KEY_USAGE |\
10599ebb4caSwyllys 	KMF_X509_EXT_INHIBIT_ANY_POLICY |\
10699ebb4caSwyllys 	KMF_X509_EXT_AUTH_KEY_ID |\
10799ebb4caSwyllys 	KMF_X509_EXT_SUBJ_KEY_ID |\
10899ebb4caSwyllys 	KMF_X509_EXT_POLICY_MAPPING)
10999ebb4caSwyllys 
11099ebb4caSwyllys static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
11199ebb4caSwyllys 	0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
11299ebb4caSwyllys 	0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
11399ebb4caSwyllys 	0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
11499ebb4caSwyllys 	0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
11599ebb4caSwyllys 	0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
11699ebb4caSwyllys 	0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
11799ebb4caSwyllys 	0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
11899ebb4caSwyllys 	0x91 };
11999ebb4caSwyllys 
12099ebb4caSwyllys static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
12199ebb4caSwyllys 	0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
12299ebb4caSwyllys 	0x8e, 0xda, 0xce, 0x91, 0x5f };
12399ebb4caSwyllys 
12499ebb4caSwyllys static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
12599ebb4caSwyllys 	0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
12699ebb4caSwyllys 	0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
12799ebb4caSwyllys 	0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
12899ebb4caSwyllys 	0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
12999ebb4caSwyllys 	0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
13099ebb4caSwyllys 	0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
13199ebb4caSwyllys 	0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
13299ebb4caSwyllys 	0x02 };
13399ebb4caSwyllys 
13499ebb4caSwyllys #define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
13599ebb4caSwyllys 	h->lasterr.errcode = c;
13699ebb4caSwyllys 
13799ebb4caSwyllys #define	SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
13899ebb4caSwyllys 
1395b3e1433Swyllys /*
140bf5d9f18SAndy Fiddaman  * Declare some new macros for managing stacks of EVP_PKEYS.
1415b3e1433Swyllys  */
142553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
1435b3e1433Swyllys DECLARE_STACK_OF(EVP_PKEY)
1445b3e1433Swyllys 
1455b3e1433Swyllys #define	sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
1465b3e1433Swyllys #define	sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
1475b3e1433Swyllys #define	sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
1485b3e1433Swyllys #define	sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
1495b3e1433Swyllys #define	sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
1505b3e1433Swyllys #define	sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
1515b3e1433Swyllys 	(free_func))
1525b3e1433Swyllys 
153300fdee2SAndy Fiddaman #else
154300fdee2SAndy Fiddaman DEFINE_STACK_OF(EVP_PKEY)
155300fdee2SAndy Fiddaman #endif
156300fdee2SAndy Fiddaman 
15799ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX;
15899ebb4caSwyllys static int ssl_initialized = 0;
15930a5e8faSwyllys static BIO *bio_err = NULL;
16030a5e8faSwyllys 
161*4942e222SAndy Fiddaman static int test_for_file(char *, mode_t);
162*4942e222SAndy Fiddaman 
163*4942e222SAndy Fiddaman static KMF_RETURN openssl_parse_bag(PKCS12_SAFEBAG *, char *, int,
1645b3e1433Swyllys     STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
1655b3e1433Swyllys 
166*4942e222SAndy Fiddaman static KMF_RETURN local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int,
167*4942e222SAndy Fiddaman     KMF_X509_DER_CERT *, int, KMF_KEY_HANDLE *, char *);
1685b3e1433Swyllys 
1695b3e1433Swyllys static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int);
17099ebb4caSwyllys 
171*4942e222SAndy Fiddaman static KMF_RETURN extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *,
172*4942e222SAndy Fiddaman     char *, CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
17371593db2Swyllys 
174*4942e222SAndy Fiddaman static KMF_RETURN kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *,
175*4942e222SAndy Fiddaman     KMF_CERT_VALIDITY, char *, KMF_DATA *);
17630a5e8faSwyllys 
177*4942e222SAndy Fiddaman static KMF_RETURN load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *,
178*4942e222SAndy Fiddaman     KMF_CERT_VALIDITY, char *, KMF_DATA **, uint32_t *);
17971593db2Swyllys 
180*4942e222SAndy Fiddaman static KMF_RETURN sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
18102744e81Swyllys 
182*4942e222SAndy Fiddaman static EVP_PKEY *ImportRawRSAKey(KMF_RAW_RSA_KEY *);
18302744e81Swyllys 
184*4942e222SAndy Fiddaman static KMF_RETURN convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
18530a5e8faSwyllys 
186*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
18799ebb4caSwyllys 
188*4942e222SAndy Fiddaman void OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
18999ebb4caSwyllys 
190*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
19199ebb4caSwyllys 
192*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
19399ebb4caSwyllys 
194*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
19530a5e8faSwyllys 
196*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
19799ebb4caSwyllys 
198*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_EncodePubKeyData(KMF_HANDLE_T,  KMF_KEY_HANDLE *,
199*4942e222SAndy Fiddaman     KMF_DATA *);
20099ebb4caSwyllys 
201*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
20299ebb4caSwyllys     KMF_DATA *, KMF_DATA *);
20399ebb4caSwyllys 
204*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20599ebb4caSwyllys 
206*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20799ebb4caSwyllys 
208*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20999ebb4caSwyllys 
210*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21199ebb4caSwyllys 
212*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21399ebb4caSwyllys 
214*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
21599ebb4caSwyllys     KMF_PRINTABLE_ITEM, char *);
21699ebb4caSwyllys 
217*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
21899ebb4caSwyllys 
219*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22099ebb4caSwyllys 
221*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
22299ebb4caSwyllys     KMF_DATA *, KMF_DATA *);
22399ebb4caSwyllys 
224*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22599ebb4caSwyllys 
226*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22799ebb4caSwyllys 
228*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22999ebb4caSwyllys 
230*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23199ebb4caSwyllys 
232*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23399ebb4caSwyllys 
234*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *,
235*4942e222SAndy Fiddaman     KMF_RAW_SYM_KEY *);
23699ebb4caSwyllys 
237*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
23899ebb4caSwyllys 
239*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
24099ebb4caSwyllys 
24199ebb4caSwyllys static
24299ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table =
24399ebb4caSwyllys {
24499ebb4caSwyllys 	1,				/* Version */
24599ebb4caSwyllys 	NULL, /* ConfigureKeystore */
24699ebb4caSwyllys 	OpenSSL_FindCert,
24799ebb4caSwyllys 	OpenSSL_FreeKMFCert,
24899ebb4caSwyllys 	OpenSSL_StoreCert,
24999ebb4caSwyllys 	NULL, /* ImportCert */
25099ebb4caSwyllys 	OpenSSL_ImportCRL,
25199ebb4caSwyllys 	OpenSSL_DeleteCert,
25299ebb4caSwyllys 	OpenSSL_DeleteCRL,
25399ebb4caSwyllys 	OpenSSL_CreateKeypair,
25499ebb4caSwyllys 	OpenSSL_FindKey,
25599ebb4caSwyllys 	OpenSSL_EncodePubKeyData,
25699ebb4caSwyllys 	OpenSSL_SignData,
25799ebb4caSwyllys 	OpenSSL_DeleteKey,
25899ebb4caSwyllys 	OpenSSL_ListCRL,
25999ebb4caSwyllys 	NULL,	/* FindCRL */
26099ebb4caSwyllys 	OpenSSL_FindCertInCRL,
26199ebb4caSwyllys 	OpenSSL_GetErrorString,
26230a5e8faSwyllys 	OpenSSL_FindPrikeyByCert,
26399ebb4caSwyllys 	OpenSSL_DecryptData,
26430a5e8faSwyllys 	OpenSSL_ExportPK12,
26599ebb4caSwyllys 	OpenSSL_CreateSymKey,
26699ebb4caSwyllys 	OpenSSL_GetSymKeyValue,
26799ebb4caSwyllys 	NULL,	/* SetTokenPin */
26830a5e8faSwyllys 	OpenSSL_StoreKey,
26999ebb4caSwyllys 	NULL	/* Finalize */
27099ebb4caSwyllys };
27199ebb4caSwyllys 
272553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
27399ebb4caSwyllys static mutex_t *lock_cs;
27499ebb4caSwyllys static long *lock_count;
27599ebb4caSwyllys 
27699ebb4caSwyllys static void
27799ebb4caSwyllys locking_cb(int mode, int type, char *file, int line)
27899ebb4caSwyllys {
27999ebb4caSwyllys 	if (mode & CRYPTO_LOCK) {
28099ebb4caSwyllys 		(void) mutex_lock(&(lock_cs[type]));
28199ebb4caSwyllys 		lock_count[type]++;
28299ebb4caSwyllys 	} else {
28399ebb4caSwyllys 		(void) mutex_unlock(&(lock_cs[type]));
28499ebb4caSwyllys 	}
28599ebb4caSwyllys }
28699ebb4caSwyllys 
28799ebb4caSwyllys static unsigned long
28899ebb4caSwyllys thread_id()
28999ebb4caSwyllys {
29099ebb4caSwyllys 	return ((unsigned long)thr_self());
29199ebb4caSwyllys }
292553e44ceSAndrew Stormont #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER */
29399ebb4caSwyllys 
29499ebb4caSwyllys KMF_PLUGIN_FUNCLIST *
29599ebb4caSwyllys KMF_Plugin_Initialize()
29699ebb4caSwyllys {
297553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
29899ebb4caSwyllys 	int i;
299300fdee2SAndy Fiddaman #endif
30099ebb4caSwyllys 
30199ebb4caSwyllys 	(void) mutex_lock(&init_lock);
30299ebb4caSwyllys 	if (!ssl_initialized) {
30399ebb4caSwyllys 		/*
30499ebb4caSwyllys 		 * Add support for extension OIDs that are not yet in the
30599ebb4caSwyllys 		 * openssl default set.
30699ebb4caSwyllys 		 */
30799ebb4caSwyllys 		(void) OBJ_create("2.5.29.30", "nameConstraints",
30899ebb4caSwyllys 		    "X509v3 Name Constraints");
30999ebb4caSwyllys 		(void) OBJ_create("2.5.29.33", "policyMappings",
31099ebb4caSwyllys 		    "X509v3 Policy Mappings");
31199ebb4caSwyllys 		(void) OBJ_create("2.5.29.36", "policyConstraints",
31299ebb4caSwyllys 		    "X509v3 Policy Constraints");
31399ebb4caSwyllys 		(void) OBJ_create("2.5.29.46", "freshestCRL",
31499ebb4caSwyllys 		    "X509v3 Freshest CRL");
31599ebb4caSwyllys 		(void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
31699ebb4caSwyllys 		    "X509v3 Inhibit Any-Policy");
317300fdee2SAndy Fiddaman 
318553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
31999ebb4caSwyllys 		/*
32099ebb4caSwyllys 		 * Set up for thread-safe operation.
321300fdee2SAndy Fiddaman 		 * This is not required for OpenSSL 1.1
32299ebb4caSwyllys 		 */
32399ebb4caSwyllys 		lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
32499ebb4caSwyllys 		if (lock_cs == NULL) {
32599ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
32699ebb4caSwyllys 			return (NULL);
32799ebb4caSwyllys 		}
32899ebb4caSwyllys 
32999ebb4caSwyllys 		lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
33099ebb4caSwyllys 		if (lock_count == NULL) {
33199ebb4caSwyllys 			OPENSSL_free(lock_cs);
33299ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
33399ebb4caSwyllys 			return (NULL);
33499ebb4caSwyllys 		}
33599ebb4caSwyllys 
33699ebb4caSwyllys 		for (i = 0; i < CRYPTO_num_locks(); i++) {
33799ebb4caSwyllys 			lock_count[i] = 0;
33899ebb4caSwyllys 			(void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
33999ebb4caSwyllys 		}
34099ebb4caSwyllys 
34199ebb4caSwyllys 		CRYPTO_set_id_callback((unsigned long (*)())thread_id);
3422c9a247fSWyllys Ingersoll 		if (CRYPTO_get_locking_callback() == NULL)
34399ebb4caSwyllys 			CRYPTO_set_locking_callback((void (*)())locking_cb);
3442c9a247fSWyllys Ingersoll 
345300fdee2SAndy Fiddaman 		(void) OpenSSL_add_all_algorithms();
3462c9a247fSWyllys Ingersoll 
3472c9a247fSWyllys Ingersoll 		/* Enable error strings for reporting */
348300fdee2SAndy Fiddaman 		(void) ERR_load_crypto_strings();
349300fdee2SAndy Fiddaman #endif
3502c9a247fSWyllys Ingersoll 
35199ebb4caSwyllys 		ssl_initialized = 1;
35299ebb4caSwyllys 	}
35399ebb4caSwyllys 	(void) mutex_unlock(&init_lock);
35499ebb4caSwyllys 
35599ebb4caSwyllys 	return (&openssl_plugin_table);
35699ebb4caSwyllys }
357300fdee2SAndy Fiddaman 
35899ebb4caSwyllys /*
35999ebb4caSwyllys  * Convert an SSL DN to a KMF DN.
36099ebb4caSwyllys  */
36199ebb4caSwyllys static KMF_RETURN
36299ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
36399ebb4caSwyllys {
36499ebb4caSwyllys 	KMF_DATA derdata;
36599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
36699ebb4caSwyllys 	uchar_t *tmp;
36799ebb4caSwyllys 
36899ebb4caSwyllys 	/* Convert to raw DER format */
36999ebb4caSwyllys 	derdata.Length = i2d_X509_NAME(sslDN, NULL);
37099ebb4caSwyllys 	if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
37199ebb4caSwyllys 	    == NULL) {
37299ebb4caSwyllys 		return (KMF_ERR_MEMORY);
37399ebb4caSwyllys 	}
37499ebb4caSwyllys 	(void) i2d_X509_NAME(sslDN, &tmp);
37599ebb4caSwyllys 
37699ebb4caSwyllys 	/* Decode to KMF format */
37799ebb4caSwyllys 	rv = DerDecodeName(&derdata, kmfDN);
37899ebb4caSwyllys 	if (rv != KMF_OK) {
37999ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
38099ebb4caSwyllys 	}
38199ebb4caSwyllys 	OPENSSL_free(derdata.Data);
38299ebb4caSwyllys 
38399ebb4caSwyllys 	return (rv);
38499ebb4caSwyllys }
38599ebb4caSwyllys 
38630a5e8faSwyllys int
38799ebb4caSwyllys isdir(char *path)
38899ebb4caSwyllys {
38999ebb4caSwyllys 	struct stat s;
39099ebb4caSwyllys 
39199ebb4caSwyllys 	if (stat(path, &s) == -1)
39299ebb4caSwyllys 		return (0);
39399ebb4caSwyllys 
39430a5e8faSwyllys 	return ((s.st_mode & S_IFMT) == S_IFDIR);
39599ebb4caSwyllys }
39699ebb4caSwyllys 
39799ebb4caSwyllys static KMF_RETURN
39899ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
39999ebb4caSwyllys {
40099ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
40199ebb4caSwyllys 	unsigned char *buf = NULL, *p;
40299ebb4caSwyllys 	int len;
40399ebb4caSwyllys 
40499ebb4caSwyllys 	/*
40599ebb4caSwyllys 	 * Convert the X509 internal struct to DER encoded data
40699ebb4caSwyllys 	 */
40799ebb4caSwyllys 	if ((len = i2d_X509(x509cert, NULL)) < 0) {
40899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
40999ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
41099ebb4caSwyllys 		goto cleanup;
41199ebb4caSwyllys 	}
41299ebb4caSwyllys 	if ((buf = malloc(len)) == NULL) {
41399ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
41499ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
41599ebb4caSwyllys 		goto cleanup;
41699ebb4caSwyllys 	}
41799ebb4caSwyllys 
41899ebb4caSwyllys 	/*
41999ebb4caSwyllys 	 * i2d_X509 will increment the buf pointer so that we need to
42099ebb4caSwyllys 	 * save it.
42199ebb4caSwyllys 	 */
42299ebb4caSwyllys 	p = buf;
42399ebb4caSwyllys 	if ((len = i2d_X509(x509cert, &p)) < 0) {
42499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
42599ebb4caSwyllys 		free(buf);
42699ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
42799ebb4caSwyllys 		goto cleanup;
42899ebb4caSwyllys 	}
42999ebb4caSwyllys 
43099ebb4caSwyllys 	/* caller's responsibility to free it */
43199ebb4caSwyllys 	cert->Data = buf;
43299ebb4caSwyllys 	cert->Length = len;
43399ebb4caSwyllys 
43499ebb4caSwyllys cleanup:
43599ebb4caSwyllys 	if (rv != KMF_OK) {
43699ebb4caSwyllys 		if (buf)
43799ebb4caSwyllys 			free(buf);
43899ebb4caSwyllys 		cert->Data = NULL;
43999ebb4caSwyllys 		cert->Length = 0;
44099ebb4caSwyllys 	}
44199ebb4caSwyllys 
44299ebb4caSwyllys 	return (rv);
44399ebb4caSwyllys }
44499ebb4caSwyllys 
44530a5e8faSwyllys 
44699ebb4caSwyllys static KMF_RETURN
44730a5e8faSwyllys check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
44830a5e8faSwyllys     boolean_t *match)
44999ebb4caSwyllys {
45099ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
45199ebb4caSwyllys 	boolean_t findIssuer = FALSE;
45299ebb4caSwyllys 	boolean_t findSubject = FALSE;
45399ebb4caSwyllys 	boolean_t findSerial = FALSE;
45499ebb4caSwyllys 	KMF_X509_NAME issuerDN, subjectDN;
45599ebb4caSwyllys 	KMF_X509_NAME certIssuerDN, certSubjectDN;
45699ebb4caSwyllys 
45799ebb4caSwyllys 	*match = FALSE;
45899ebb4caSwyllys 	if (xcert == NULL) {
45999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
46099ebb4caSwyllys 	}
46199ebb4caSwyllys 
46299ebb4caSwyllys 	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
46399ebb4caSwyllys 	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
46499ebb4caSwyllys 	(void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
46599ebb4caSwyllys 	(void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
46699ebb4caSwyllys 
46730a5e8faSwyllys 	if (issuer != NULL && strlen(issuer)) {
46830a5e8faSwyllys 		rv = kmf_dn_parser(issuer, &issuerDN);
46999ebb4caSwyllys 		if (rv != KMF_OK)
47099ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
47199ebb4caSwyllys 
472300fdee2SAndy Fiddaman 		rv = get_x509_dn(X509_get_issuer_name(xcert), &certIssuerDN);
47399ebb4caSwyllys 		if (rv != KMF_OK) {
47430a5e8faSwyllys 			kmf_free_dn(&issuerDN);
47599ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
47699ebb4caSwyllys 		}
47799ebb4caSwyllys 
47899ebb4caSwyllys 		findIssuer = TRUE;
47999ebb4caSwyllys 	}
48030a5e8faSwyllys 	if (subject != NULL && strlen(subject)) {
48130a5e8faSwyllys 		rv = kmf_dn_parser(subject, &subjectDN);
48299ebb4caSwyllys 		if (rv != KMF_OK) {
48399ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
48499ebb4caSwyllys 			goto cleanup;
48599ebb4caSwyllys 		}
48699ebb4caSwyllys 
487300fdee2SAndy Fiddaman 		rv = get_x509_dn(X509_get_subject_name(xcert), &certSubjectDN);
48899ebb4caSwyllys 		if (rv != KMF_OK) {
48999ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
49099ebb4caSwyllys 			goto cleanup;
49199ebb4caSwyllys 		}
49299ebb4caSwyllys 		findSubject = TRUE;
49399ebb4caSwyllys 	}
49430a5e8faSwyllys 	if (serial != NULL && serial->val != NULL)
49599ebb4caSwyllys 		findSerial = TRUE;
49699ebb4caSwyllys 
49799ebb4caSwyllys 	if (findSerial) {
49899ebb4caSwyllys 		BIGNUM *bn;
49999ebb4caSwyllys 
50099ebb4caSwyllys 		/* Comparing BIGNUMs is a pain! */
501300fdee2SAndy Fiddaman 		bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(xcert), NULL);
50299ebb4caSwyllys 		if (bn != NULL) {
50399ebb4caSwyllys 			int bnlen = BN_num_bytes(bn);
50499ebb4caSwyllys 
50530a5e8faSwyllys 			if (bnlen == serial->len) {
50699ebb4caSwyllys 				uchar_t *a = malloc(bnlen);
50799ebb4caSwyllys 				if (a == NULL) {
50899ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
50999ebb4caSwyllys 					BN_free(bn);
51099ebb4caSwyllys 					goto cleanup;
51199ebb4caSwyllys 				}
51299ebb4caSwyllys 				bnlen = BN_bn2bin(bn, a);
51330a5e8faSwyllys 				*match = (memcmp(a, serial->val, serial->len) ==
51430a5e8faSwyllys 				    0);
51599ebb4caSwyllys 				rv = KMF_OK;
51699ebb4caSwyllys 				free(a);
51799ebb4caSwyllys 			}
51899ebb4caSwyllys 			BN_free(bn);
51999ebb4caSwyllys 			if (!(*match))
52099ebb4caSwyllys 				goto cleanup;
52199ebb4caSwyllys 		} else {
52299ebb4caSwyllys 			rv = KMF_OK;
52399ebb4caSwyllys 			goto cleanup;
52499ebb4caSwyllys 		}
52599ebb4caSwyllys 	}
52699ebb4caSwyllys 	if (findIssuer) {
52730a5e8faSwyllys 		*match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
52830a5e8faSwyllys 		if ((*match) == B_FALSE) {
52930a5e8faSwyllys 			/* stop checking and bail */
53099ebb4caSwyllys 			rv = KMF_OK;
53199ebb4caSwyllys 			goto cleanup;
53299ebb4caSwyllys 		}
53399ebb4caSwyllys 	}
53499ebb4caSwyllys 	if (findSubject) {
53530a5e8faSwyllys 		*match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
53630a5e8faSwyllys 		if ((*match) == B_FALSE) {
53730a5e8faSwyllys 			/* stop checking and bail */
53899ebb4caSwyllys 			rv = KMF_OK;
53999ebb4caSwyllys 			goto cleanup;
54099ebb4caSwyllys 		}
54199ebb4caSwyllys 	}
54299ebb4caSwyllys 
54399ebb4caSwyllys 	*match = TRUE;
54499ebb4caSwyllys cleanup:
54599ebb4caSwyllys 	if (findIssuer) {
54630a5e8faSwyllys 		kmf_free_dn(&issuerDN);
54730a5e8faSwyllys 		kmf_free_dn(&certIssuerDN);
54899ebb4caSwyllys 	}
54999ebb4caSwyllys 	if (findSubject) {
55030a5e8faSwyllys 		kmf_free_dn(&subjectDN);
55130a5e8faSwyllys 		kmf_free_dn(&certSubjectDN);
55299ebb4caSwyllys 	}
55399ebb4caSwyllys 
55499ebb4caSwyllys 	return (rv);
55599ebb4caSwyllys }
55699ebb4caSwyllys 
55730a5e8faSwyllys 
55830a5e8faSwyllys /*
55930a5e8faSwyllys  * This function loads a certificate file into an X509 data structure, and
56030a5e8faSwyllys  * checks if its issuer, subject or the serial number matches with those
56130a5e8faSwyllys  * values.  If it matches, then return the X509 data structure.
56230a5e8faSwyllys  */
56399ebb4caSwyllys static KMF_RETURN
564*4942e222SAndy Fiddaman load_X509cert(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
56530a5e8faSwyllys     char *pathname, X509 **outcert)
56699ebb4caSwyllys {
56799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
56899ebb4caSwyllys 	X509 *xcert = NULL;
56999ebb4caSwyllys 	BIO *bcert = NULL;
57099ebb4caSwyllys 	boolean_t  match = FALSE;
57199ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
57299ebb4caSwyllys 
57399ebb4caSwyllys 	/*
57499ebb4caSwyllys 	 * auto-detect the file format, regardless of what
57599ebb4caSwyllys 	 * the 'format' parameters in the params say.
57699ebb4caSwyllys 	 */
57730a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
57899ebb4caSwyllys 	if (rv != KMF_OK) {
57999ebb4caSwyllys 		if (rv == KMF_ERR_OPEN_FILE)
58099ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
58199ebb4caSwyllys 		return (rv);
58299ebb4caSwyllys 	}
58399ebb4caSwyllys 
58499ebb4caSwyllys 	/* Not ASN1(DER) format */
58599ebb4caSwyllys 	if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
58699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
58799ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
58899ebb4caSwyllys 		goto cleanup;
58999ebb4caSwyllys 	}
59099ebb4caSwyllys 
59199ebb4caSwyllys 	if (format == KMF_FORMAT_PEM)
59299ebb4caSwyllys 		xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
59399ebb4caSwyllys 	else if (format == KMF_FORMAT_ASN1)
59499ebb4caSwyllys 		xcert = d2i_X509_bio(bcert, NULL);
59599ebb4caSwyllys 	else if (format == KMF_FORMAT_PKCS12) {
59699ebb4caSwyllys 		PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
59799ebb4caSwyllys 		if (p12 != NULL) {
59899ebb4caSwyllys 			(void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
59999ebb4caSwyllys 			PKCS12_free(p12);
60099ebb4caSwyllys 			p12 = NULL;
60199ebb4caSwyllys 		} else {
60299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
60399ebb4caSwyllys 			rv = KMF_ERR_BAD_CERT_FORMAT;
60499ebb4caSwyllys 		}
60599ebb4caSwyllys 	} else {
60699ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
60799ebb4caSwyllys 		goto cleanup;
60899ebb4caSwyllys 	}
60999ebb4caSwyllys 
61099ebb4caSwyllys 	if (xcert == NULL) {
61199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
61299ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
61399ebb4caSwyllys 		goto cleanup;
61499ebb4caSwyllys 	}
61599ebb4caSwyllys 
61630a5e8faSwyllys 	if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
61730a5e8faSwyllys 	    match == FALSE) {
61899ebb4caSwyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
61999ebb4caSwyllys 		goto cleanup;
62099ebb4caSwyllys 	}
62199ebb4caSwyllys 
62299ebb4caSwyllys 	if (outcert != NULL) {
62399ebb4caSwyllys 		*outcert = xcert;
62499ebb4caSwyllys 	}
62599ebb4caSwyllys 
62699ebb4caSwyllys cleanup:
62799ebb4caSwyllys 	if (bcert != NULL) (void) BIO_free(bcert);
62899ebb4caSwyllys 	if (rv != KMF_OK && xcert != NULL)
62999ebb4caSwyllys 		X509_free(xcert);
63099ebb4caSwyllys 
63199ebb4caSwyllys 	return (rv);
63299ebb4caSwyllys }
63399ebb4caSwyllys 
63471593db2Swyllys static int
63571593db2Swyllys datacmp(const void *a, const void *b)
63671593db2Swyllys {
63771593db2Swyllys 	KMF_DATA *adata = (KMF_DATA *)a;
63871593db2Swyllys 	KMF_DATA *bdata = (KMF_DATA *)b;
63971593db2Swyllys 	if (adata->Length > bdata->Length)
64071593db2Swyllys 		return (-1);
64171593db2Swyllys 	if (adata->Length < bdata->Length)
64271593db2Swyllys 		return (1);
64371593db2Swyllys 	return (0);
64471593db2Swyllys }
64571593db2Swyllys 
64671593db2Swyllys static KMF_RETURN
64730a5e8faSwyllys load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
64830a5e8faSwyllys     KMF_CERT_VALIDITY validity, char *pathname,
64971593db2Swyllys     KMF_DATA **certlist, uint32_t *numcerts)
65071593db2Swyllys {
65171593db2Swyllys 	KMF_RETURN rv = KMF_OK;
65271593db2Swyllys 	int i;
65371593db2Swyllys 	KMF_DATA *certs = NULL;
65471593db2Swyllys 	int nc = 0;
65571593db2Swyllys 	int hits = 0;
65671593db2Swyllys 	KMF_ENCODE_FORMAT format;
65771593db2Swyllys 
65830a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
65971593db2Swyllys 	if (rv != KMF_OK) {
66071593db2Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
66171593db2Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
66271593db2Swyllys 		return (rv);
66371593db2Swyllys 	}
66471593db2Swyllys 	if (format == KMF_FORMAT_ASN1) {
66571593db2Swyllys 		/* load a single certificate */
66671593db2Swyllys 		certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
66771593db2Swyllys 		if (certs == NULL)
66871593db2Swyllys 			return (KMF_ERR_MEMORY);
66971593db2Swyllys 		certs->Data = NULL;
67071593db2Swyllys 		certs->Length = 0;
67130a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
67230a5e8faSwyllys 		    pathname, certs);
67371593db2Swyllys 		if (rv == KMF_OK) {
67471593db2Swyllys 			*certlist = certs;
67571593db2Swyllys 			*numcerts = 1;
676a2d4930dSDan OpenSolaris Anderson 		} else {
677a2d4930dSDan OpenSolaris Anderson 			kmf_free_data(certs);
678a2d4930dSDan OpenSolaris Anderson 			free(certs);
679a2d4930dSDan OpenSolaris Anderson 			certs = NULL;
68071593db2Swyllys 		}
68171593db2Swyllys 		return (rv);
68271593db2Swyllys 	} else if (format == KMF_FORMAT_PKCS12) {
68371593db2Swyllys 		/* We need a credential to access a PKCS#12 file */
68471593db2Swyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
68571593db2Swyllys 	} else if (format == KMF_FORMAT_PEM ||
68671593db2Swyllys 	    format != KMF_FORMAT_PEM_KEYPAIR) {
687e65e5c2dSWyllys Ingersoll 
68871593db2Swyllys 		/* This function only works on PEM files */
68930a5e8faSwyllys 		rv = extract_pem(kmfh, issuer, subject, serial, pathname,
69034acef67Swyllys 		    (uchar_t *)NULL, 0, NULL, &certs, &nc);
69171593db2Swyllys 	} else {
69271593db2Swyllys 		return (KMF_ERR_ENCODING);
69371593db2Swyllys 	}
69471593db2Swyllys 
69571593db2Swyllys 	if (rv != KMF_OK)
69671593db2Swyllys 		return (rv);
69771593db2Swyllys 
69871593db2Swyllys 	for (i = 0; i < nc; i++) {
69930a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
70030a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
70130a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
70230a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
70371593db2Swyllys 			if (rv == KMF_OK)
70471593db2Swyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
70571593db2Swyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD)
70671593db2Swyllys 				rv = KMF_OK;
70771593db2Swyllys 		}
70871593db2Swyllys 		if (rv != KMF_OK) {
70971593db2Swyllys 			/* Remove this cert from the list by clearing it. */
71030a5e8faSwyllys 			kmf_free_data(&certs[i]);
71171593db2Swyllys 		} else {
71271593db2Swyllys 			hits++; /* count valid certs found */
71371593db2Swyllys 		}
71471593db2Swyllys 		rv = KMF_OK;
71571593db2Swyllys 	}
716a2d4930dSDan OpenSolaris Anderson 	if (rv == KMF_OK && hits > 0) {
71771593db2Swyllys 		/*
71871593db2Swyllys 		 * Sort the list of certs by length to put the cleared ones
71971593db2Swyllys 		 * at the end so they don't get accessed by the caller.
72071593db2Swyllys 		 */
72171593db2Swyllys 		qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
72271593db2Swyllys 		*certlist = certs;
72371593db2Swyllys 
72471593db2Swyllys 		/* since we sorted the list, just return the number of hits */
72571593db2Swyllys 		*numcerts = hits;
726a2d4930dSDan OpenSolaris Anderson 	} else {
727e65e5c2dSWyllys Ingersoll 		if (rv == KMF_OK && hits == 0)
728a2d4930dSDan OpenSolaris Anderson 			rv = KMF_ERR_CERT_NOT_FOUND;
729a2d4930dSDan OpenSolaris Anderson 		if (certs != NULL) {
730a2d4930dSDan OpenSolaris Anderson 			free(certs);
731a2d4930dSDan OpenSolaris Anderson 			certs = NULL;
732a2d4930dSDan OpenSolaris Anderson 		}
733a2d4930dSDan OpenSolaris Anderson 	}
73471593db2Swyllys 	return (rv);
73571593db2Swyllys }
73671593db2Swyllys 
73799ebb4caSwyllys static KMF_RETURN
738*4942e222SAndy Fiddaman kmf_load_cert(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
739*4942e222SAndy Fiddaman     KMF_CERT_VALIDITY validity, char *pathname, KMF_DATA *cert)
74099ebb4caSwyllys {
74199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
74299ebb4caSwyllys 	X509 *x509cert = NULL;
74399ebb4caSwyllys 
74430a5e8faSwyllys 	rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
74599ebb4caSwyllys 	if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
74699ebb4caSwyllys 		rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
74799ebb4caSwyllys 		if (rv != KMF_OK) {
74899ebb4caSwyllys 			goto cleanup;
74999ebb4caSwyllys 		}
75030a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
75130a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
75230a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
75330a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
75499ebb4caSwyllys 			if (rv == KMF_OK)  {
75599ebb4caSwyllys 				/*
75699ebb4caSwyllys 				 * This is a valid cert so skip it.
75799ebb4caSwyllys 				 */
75899ebb4caSwyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
75999ebb4caSwyllys 			}
76099ebb4caSwyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD) {
76199ebb4caSwyllys 				/*
76299ebb4caSwyllys 				 * We want to return success when we
76399ebb4caSwyllys 				 * find an invalid cert.
76499ebb4caSwyllys 				 */
76599ebb4caSwyllys 				rv = KMF_OK;
76699ebb4caSwyllys 				goto cleanup;
76799ebb4caSwyllys 			}
76899ebb4caSwyllys 		}
76999ebb4caSwyllys 	}
77099ebb4caSwyllys cleanup:
77199ebb4caSwyllys 	if (x509cert != NULL)
77299ebb4caSwyllys 		X509_free(x509cert);
77399ebb4caSwyllys 
77499ebb4caSwyllys 	return (rv);
77599ebb4caSwyllys }
77699ebb4caSwyllys 
77702744e81Swyllys static KMF_RETURN
77802744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
77902744e81Swyllys {
78002744e81Swyllys 	KMF_RETURN ret = KMF_OK;
78102744e81Swyllys 	KMF_RAW_RSA_KEY rsa;
78202744e81Swyllys 	BerElement *asn1 = NULL;
78302744e81Swyllys 	BerValue filebuf;
784f810c7e5SToomas Soome 	BerValue OID = { 0, 0 };
78502744e81Swyllys 	BerValue *Mod = NULL, *PubExp = NULL;
78602744e81Swyllys 	BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
78702744e81Swyllys 	BerValue *Coef = NULL;
78802744e81Swyllys 	BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
78902744e81Swyllys 	BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
79002744e81Swyllys 	BIGNUM *qminus1 = NULL;
79102744e81Swyllys 	BN_CTX *ctx = NULL;
79202744e81Swyllys 
79302744e81Swyllys 	*pkey = NULL;
79402744e81Swyllys 
79502744e81Swyllys 	filebuf.bv_val = (char *)filedata->Data;
79602744e81Swyllys 	filebuf.bv_len = filedata->Length;
79702744e81Swyllys 
79802744e81Swyllys 	asn1 = kmfder_init(&filebuf);
79902744e81Swyllys 	if (asn1 == NULL) {
80002744e81Swyllys 		ret = KMF_ERR_MEMORY;
80102744e81Swyllys 		goto out;
80202744e81Swyllys 	}
80302744e81Swyllys 
80402744e81Swyllys 	if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
80502744e81Swyllys 	    &OID, &Mod, &PubExp, &PriExp, &Prime1,
80602744e81Swyllys 	    &Prime2, &Coef) == -1)  {
80702744e81Swyllys 		ret = KMF_ERR_ENCODING;
80802744e81Swyllys 		goto out;
80902744e81Swyllys 	}
81002744e81Swyllys 
81102744e81Swyllys 	/*
81202744e81Swyllys 	 * We have to derive the 2 Exponents using Bignumber math.
81302744e81Swyllys 	 * Exp1 = PriExp mod (Prime1 - 1)
81402744e81Swyllys 	 * Exp2 = PriExp mod (Prime2 - 1)
81502744e81Swyllys 	 */
81602744e81Swyllys 
81702744e81Swyllys 	/* D = PrivateExponent */
81802744e81Swyllys 	D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
81902744e81Swyllys 	if (D == NULL) {
82002744e81Swyllys 		ret = KMF_ERR_MEMORY;
82102744e81Swyllys 		goto out;
82202744e81Swyllys 	}
82302744e81Swyllys 
82402744e81Swyllys 	/* P = Prime1 (first prime factor of Modulus) */
82502744e81Swyllys 	P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
82602744e81Swyllys 	if (D == NULL) {
82702744e81Swyllys 		ret = KMF_ERR_MEMORY;
82802744e81Swyllys 		goto out;
82902744e81Swyllys 	}
83002744e81Swyllys 
83102744e81Swyllys 	/* Q = Prime2 (second prime factor of Modulus) */
83202744e81Swyllys 	Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
83302744e81Swyllys 
83402744e81Swyllys 	if ((ctx = BN_CTX_new()) == NULL) {
83502744e81Swyllys 		ret = KMF_ERR_MEMORY;
83602744e81Swyllys 		goto out;
83702744e81Swyllys 	}
83802744e81Swyllys 
83902744e81Swyllys 	/* Compute (P - 1) */
84002744e81Swyllys 	pminus1 = BN_new();
84102744e81Swyllys 	(void) BN_sub(pminus1, P, BN_value_one());
84202744e81Swyllys 
84302744e81Swyllys 	/* Exponent1 = D mod (P - 1) */
84402744e81Swyllys 	Exp1 = BN_new();
84502744e81Swyllys 	(void) BN_mod(Exp1, D, pminus1, ctx);
84602744e81Swyllys 
84702744e81Swyllys 	/* Compute (Q - 1) */
84802744e81Swyllys 	qminus1 = BN_new();
84902744e81Swyllys 	(void) BN_sub(qminus1, Q, BN_value_one());
85002744e81Swyllys 
85102744e81Swyllys 	/* Exponent2 = D mod (Q - 1) */
85202744e81Swyllys 	Exp2 = BN_new();
85302744e81Swyllys 	(void) BN_mod(Exp2, D, qminus1, ctx);
85402744e81Swyllys 
85502744e81Swyllys 	/* Coef = (Inverse Q) mod P */
85602744e81Swyllys 	COEF = BN_new();
85702744e81Swyllys 	(void) BN_mod_inverse(COEF, Q, P, ctx);
85802744e81Swyllys 
85902744e81Swyllys 	/* Convert back to KMF format */
86002744e81Swyllys 	(void) memset(&rsa, 0, sizeof (rsa));
86102744e81Swyllys 
86202744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
86302744e81Swyllys 		goto out;
86402744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
86502744e81Swyllys 		goto out;
86602744e81Swyllys 	if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
86702744e81Swyllys 		goto out;
86802744e81Swyllys 
86902744e81Swyllys 	rsa.mod.val = (uchar_t *)Mod->bv_val;
87002744e81Swyllys 	rsa.mod.len = Mod->bv_len;
87102744e81Swyllys 
87202744e81Swyllys 	rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
87302744e81Swyllys 	rsa.pubexp.len = PubExp->bv_len;
87402744e81Swyllys 
87502744e81Swyllys 	rsa.priexp.val = (uchar_t *)PriExp->bv_val;
87602744e81Swyllys 	rsa.priexp.len = PriExp->bv_len;
87702744e81Swyllys 
87802744e81Swyllys 	rsa.prime1.val = (uchar_t *)Prime1->bv_val;
87902744e81Swyllys 	rsa.prime1.len = Prime1->bv_len;
88002744e81Swyllys 
88102744e81Swyllys 	rsa.prime2.val = (uchar_t *)Prime2->bv_val;
88202744e81Swyllys 	rsa.prime2.len = Prime2->bv_len;
88302744e81Swyllys 
88402744e81Swyllys 	*pkey = ImportRawRSAKey(&rsa);
88502744e81Swyllys out:
88602744e81Swyllys 	if (asn1 != NULL)
88702744e81Swyllys 		kmfber_free(asn1, 1);
88802744e81Swyllys 
88902744e81Swyllys 	if (OID.bv_val) {
89002744e81Swyllys 		free(OID.bv_val);
89102744e81Swyllys 	}
89202744e81Swyllys 	if (PriExp)
89302744e81Swyllys 		free(PriExp);
89402744e81Swyllys 
89502744e81Swyllys 	if (Mod)
89602744e81Swyllys 		free(Mod);
89702744e81Swyllys 
89802744e81Swyllys 	if (PubExp)
89902744e81Swyllys 		free(PubExp);
90002744e81Swyllys 
90102744e81Swyllys 	if (Coef) {
90202744e81Swyllys 		(void) memset(Coef->bv_val, 0, Coef->bv_len);
90302744e81Swyllys 		free(Coef->bv_val);
90402744e81Swyllys 		free(Coef);
90502744e81Swyllys 	}
90602744e81Swyllys 	if (Prime1)
90702744e81Swyllys 		free(Prime1);
90802744e81Swyllys 	if (Prime2)
90902744e81Swyllys 		free(Prime2);
91002744e81Swyllys 
91102744e81Swyllys 	if (ctx != NULL)
91202744e81Swyllys 		BN_CTX_free(ctx);
91302744e81Swyllys 
91402744e81Swyllys 	if (D)
91502744e81Swyllys 		BN_clear_free(D);
91602744e81Swyllys 	if (P)
91702744e81Swyllys 		BN_clear_free(P);
91802744e81Swyllys 	if (Q)
91902744e81Swyllys 		BN_clear_free(Q);
92002744e81Swyllys 	if (pminus1)
92102744e81Swyllys 		BN_clear_free(pminus1);
92202744e81Swyllys 	if (qminus1)
92302744e81Swyllys 		BN_clear_free(qminus1);
92402744e81Swyllys 	if (Exp1)
92502744e81Swyllys 		BN_clear_free(Exp1);
92602744e81Swyllys 	if (Exp2)
92702744e81Swyllys 		BN_clear_free(Exp2);
92802744e81Swyllys 
92902744e81Swyllys 	return (ret);
93002744e81Swyllys 
93102744e81Swyllys }
93202744e81Swyllys 
93399ebb4caSwyllys static EVP_PKEY *
93499ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file)
93599ebb4caSwyllys {
93699ebb4caSwyllys 	BIO *keyfile = NULL;
93799ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
93899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
93999ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
94002744e81Swyllys 	KMF_RETURN rv;
94102744e81Swyllys 	KMF_DATA filedata;
94299ebb4caSwyllys 
94399ebb4caSwyllys 	if (file == NULL) {
94499ebb4caSwyllys 		return (NULL);
94599ebb4caSwyllys 	}
94699ebb4caSwyllys 
94730a5e8faSwyllys 	if (kmf_get_file_format((char *)file, &format) != KMF_OK)
94899ebb4caSwyllys 		return (NULL);
94999ebb4caSwyllys 
95099ebb4caSwyllys 	keyfile = BIO_new_file(file, "rb");
95199ebb4caSwyllys 	if (keyfile == NULL) {
95299ebb4caSwyllys 		goto end;
95399ebb4caSwyllys 	}
95499ebb4caSwyllys 
95502744e81Swyllys 	if (format == KMF_FORMAT_ASN1) {
95699ebb4caSwyllys 		pkey = d2i_PrivateKey_bio(keyfile, NULL);
95702744e81Swyllys 		if (pkey == NULL) {
95802744e81Swyllys 
95902744e81Swyllys 			(void) BIO_free(keyfile);
96002744e81Swyllys 			keyfile = NULL;
96102744e81Swyllys 			/* Try odd ASN.1 variations */
96230a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
96302744e81Swyllys 			    &filedata);
96402744e81Swyllys 			if (rv == KMF_OK) {
96502744e81Swyllys 				(void) readAltFormatPrivateKey(&filedata,
96602744e81Swyllys 				    &pkey);
96730a5e8faSwyllys 				kmf_free_data(&filedata);
96802744e81Swyllys 			}
96902744e81Swyllys 		}
97002744e81Swyllys 	} else if (format == KMF_FORMAT_PEM ||
97102744e81Swyllys 	    format == KMF_FORMAT_PEM_KEYPAIR) {
97299ebb4caSwyllys 		pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
97302744e81Swyllys 		if (pkey == NULL) {
97402744e81Swyllys 			KMF_DATA derdata;
97502744e81Swyllys 			/*
97602744e81Swyllys 			 * Check if this is the alt. format
97702744e81Swyllys 			 * RSA private key file.
97802744e81Swyllys 			 */
97930a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
98002744e81Swyllys 			    &filedata);
98102744e81Swyllys 			if (rv == KMF_OK) {
98202744e81Swyllys 				uchar_t *d = NULL;
98302744e81Swyllys 				int len;
98430a5e8faSwyllys 				rv = kmf_pem_to_der(filedata.Data,
98502744e81Swyllys 				    filedata.Length, &d, &len);
98602744e81Swyllys 				if (rv == KMF_OK && d != NULL) {
98702744e81Swyllys 					derdata.Data = d;
98802744e81Swyllys 					derdata.Length = (size_t)len;
98902744e81Swyllys 					(void) readAltFormatPrivateKey(
99002744e81Swyllys 					    &derdata, &pkey);
99102744e81Swyllys 					free(d);
99202744e81Swyllys 				}
99330a5e8faSwyllys 				kmf_free_data(&filedata);
99402744e81Swyllys 			}
99502744e81Swyllys 		}
99602744e81Swyllys 	}
99799ebb4caSwyllys 
99899ebb4caSwyllys end:
999a50e8766SToomas Soome 	if (pkey == NULL) {
100099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1001a50e8766SToomas Soome 	}
100299ebb4caSwyllys 
100399ebb4caSwyllys 	if (keyfile != NULL)
100499ebb4caSwyllys 		(void) BIO_free(keyfile);
100599ebb4caSwyllys 
100699ebb4caSwyllys 	return (pkey);
100799ebb4caSwyllys }
100899ebb4caSwyllys 
100999ebb4caSwyllys KMF_RETURN
101030a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
101199ebb4caSwyllys {
101299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
101399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1014f482c776Swyllys 	int i, n;
1015f482c776Swyllys 	uint32_t maxcerts = 0;
101630a5e8faSwyllys 	uint32_t *num_certs;
101730a5e8faSwyllys 	KMF_X509_DER_CERT *kmf_cert = NULL;
101830a5e8faSwyllys 	char *dirpath = NULL;
101930a5e8faSwyllys 	char *filename = NULL;
102030a5e8faSwyllys 	char *fullpath = NULL;
102130a5e8faSwyllys 	char *issuer = NULL;
102230a5e8faSwyllys 	char *subject = NULL;
102330a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
102430a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
102599ebb4caSwyllys 
102630a5e8faSwyllys 	num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
102730a5e8faSwyllys 	if (num_certs == NULL)
102899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
102999ebb4caSwyllys 
103030a5e8faSwyllys 	/* num_certs should reference the size of kmf_cert */
1031f482c776Swyllys 	maxcerts = *num_certs;
1032f482c776Swyllys 	if (maxcerts == 0)
1033f482c776Swyllys 		maxcerts = 0xFFFFFFFF;
103499ebb4caSwyllys 	*num_certs = 0;
103599ebb4caSwyllys 
103630a5e8faSwyllys 	/* Get the optional returned certificate list  */
103730a5e8faSwyllys 	kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
103830a5e8faSwyllys 	    numattr);
103999ebb4caSwyllys 
104030a5e8faSwyllys 	/*
104130a5e8faSwyllys 	 * The dirpath attribute and the filename attribute can not be NULL
104230a5e8faSwyllys 	 * at the same time.
104330a5e8faSwyllys 	 */
104430a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
104530a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
104630a5e8faSwyllys 	    numattr);
104730a5e8faSwyllys 
104830a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
104999ebb4caSwyllys 	if (fullpath == NULL)
105099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
105199ebb4caSwyllys 
105230a5e8faSwyllys 	/* Get optional search criteria attributes */
105330a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
105430a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
105530a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
105630a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
105730a5e8faSwyllys 	    &validity, NULL);
105830a5e8faSwyllys 	if (rv != KMF_OK) {
105930a5e8faSwyllys 		validity = KMF_ALL_CERTS;
106030a5e8faSwyllys 		rv = KMF_OK;
106130a5e8faSwyllys 	}
106230a5e8faSwyllys 
106399ebb4caSwyllys 	if (isdir(fullpath)) {
106499ebb4caSwyllys 		DIR *dirp;
106599ebb4caSwyllys 		struct dirent *dp;
106699ebb4caSwyllys 
1067f482c776Swyllys 		n = 0;
106899ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
106999ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
107099ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
107199ebb4caSwyllys 		}
107299ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
107399ebb4caSwyllys 			char *fname;
107471593db2Swyllys 			KMF_DATA *certlist = NULL;
1075f482c776Swyllys 			uint32_t loaded_certs = 0;
107671593db2Swyllys 
107799ebb4caSwyllys 			if (strcmp(dp->d_name, ".") == 0 ||
107899ebb4caSwyllys 			    strcmp(dp->d_name, "..") == 0)
107999ebb4caSwyllys 				continue;
108099ebb4caSwyllys 
108134acef67Swyllys 			fname = get_fullpath(fullpath, (char *)&dp->d_name);
108299ebb4caSwyllys 
108330a5e8faSwyllys 			rv = load_certs(kmfh, issuer, subject, serial,
108430a5e8faSwyllys 			    validity, fname, &certlist,	&loaded_certs);
108599ebb4caSwyllys 
108699ebb4caSwyllys 			if (rv != KMF_OK) {
108799ebb4caSwyllys 				free(fname);
108871593db2Swyllys 				if (certlist != NULL) {
1089f482c776Swyllys 					for (i = 0; i < loaded_certs; i++)
109030a5e8faSwyllys 						kmf_free_data(&certlist[i]);
109171593db2Swyllys 					free(certlist);
109271593db2Swyllys 				}
109399ebb4caSwyllys 				continue;
109499ebb4caSwyllys 			}
109599ebb4caSwyllys 
109699ebb4caSwyllys 			/* If load succeeds, add certdata to the list */
109799ebb4caSwyllys 			if (kmf_cert != NULL) {
1098f482c776Swyllys 				for (i = 0; i < loaded_certs &&
1099b4058258Swyllys 				    n < maxcerts; i++) {
110071593db2Swyllys 					kmf_cert[n].certificate.Data =
110171593db2Swyllys 					    certlist[i].Data;
110299ebb4caSwyllys 					kmf_cert[n].certificate.Length =
110371593db2Swyllys 					    certlist[i].Length;
110499ebb4caSwyllys 
110599ebb4caSwyllys 					kmf_cert[n].kmf_private.keystore_type =
110699ebb4caSwyllys 					    KMF_KEYSTORE_OPENSSL;
110799ebb4caSwyllys 					kmf_cert[n].kmf_private.flags =
110899ebb4caSwyllys 					    KMF_FLAG_CERT_VALID;
110971593db2Swyllys 					kmf_cert[n].kmf_private.label =
111071593db2Swyllys 					    strdup(fname);
111199ebb4caSwyllys 					n++;
111299ebb4caSwyllys 				}
1113b4058258Swyllys 				/*
1114b4058258Swyllys 				 * If maxcerts < loaded_certs, clean up the
1115b4058258Swyllys 				 * certs that were not used.
1116b4058258Swyllys 				 */
1117f482c776Swyllys 				for (; i < loaded_certs; i++)
111830a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1119f482c776Swyllys 			} else {
1120f482c776Swyllys 				for (i = 0; i < loaded_certs; i++)
112130a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1122f482c776Swyllys 				n += loaded_certs;
112371593db2Swyllys 			}
1124f482c776Swyllys 			free(certlist);
112571593db2Swyllys 			free(fname);
112671593db2Swyllys 		}
112799ebb4caSwyllys 		(*num_certs) = n;
112899ebb4caSwyllys 		if (*num_certs == 0)
112999ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
113030a5e8faSwyllys 		if (*num_certs > 0)
113199ebb4caSwyllys 			rv = KMF_OK;
113299ebb4caSwyllys exit:
113399ebb4caSwyllys 		(void) closedir(dirp);
113499ebb4caSwyllys 	} else {
113571593db2Swyllys 		KMF_DATA *certlist = NULL;
1136f482c776Swyllys 		uint32_t loaded_certs = 0;
113771593db2Swyllys 
113830a5e8faSwyllys 		rv = load_certs(kmfh, issuer, subject, serial, validity,
113930a5e8faSwyllys 		    fullpath, &certlist, &loaded_certs);
114099ebb4caSwyllys 		if (rv != KMF_OK) {
114199ebb4caSwyllys 			free(fullpath);
114299ebb4caSwyllys 			return (rv);
114399ebb4caSwyllys 		}
114499ebb4caSwyllys 
1145f482c776Swyllys 		n = 0;
114671593db2Swyllys 		if (kmf_cert != NULL && certlist != NULL) {
1147f482c776Swyllys 			for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1148f482c776Swyllys 				kmf_cert[n].certificate.Data =
114971593db2Swyllys 				    certlist[i].Data;
1150f482c776Swyllys 				kmf_cert[n].certificate.Length =
115171593db2Swyllys 				    certlist[i].Length;
1152f482c776Swyllys 				kmf_cert[n].kmf_private.keystore_type =
115399ebb4caSwyllys 				    KMF_KEYSTORE_OPENSSL;
1154f482c776Swyllys 				kmf_cert[n].kmf_private.flags =
115571593db2Swyllys 				    KMF_FLAG_CERT_VALID;
1156f482c776Swyllys 				kmf_cert[n].kmf_private.label =
115771593db2Swyllys 				    strdup(fullpath);
1158f482c776Swyllys 				n++;
115971593db2Swyllys 			}
1160f482c776Swyllys 			/* If maxcerts < loaded_certs, clean up */
1161f482c776Swyllys 			for (; i < loaded_certs; i++)
116230a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1163f482c776Swyllys 		} else if (certlist != NULL) {
1164f482c776Swyllys 			for (i = 0; i < loaded_certs; i++)
116530a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1166f482c776Swyllys 			n = loaded_certs;
1167f482c776Swyllys 		}
116830a5e8faSwyllys 		if (certlist != NULL)
116971593db2Swyllys 			free(certlist);
1170f482c776Swyllys 		*num_certs = n;
117199ebb4caSwyllys 	}
117299ebb4caSwyllys 
117399ebb4caSwyllys 	free(fullpath);
117499ebb4caSwyllys 
117599ebb4caSwyllys 	return (rv);
117699ebb4caSwyllys }
117799ebb4caSwyllys 
117899ebb4caSwyllys void
1179*4942e222SAndy Fiddaman OpenSSL_FreeKMFCert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
118099ebb4caSwyllys {
118199ebb4caSwyllys 	if (kmf_cert != NULL) {
118299ebb4caSwyllys 		if (kmf_cert->certificate.Data != NULL) {
1183e65e5c2dSWyllys Ingersoll 			kmf_free_data(&kmf_cert->certificate);
118499ebb4caSwyllys 		}
118599ebb4caSwyllys 		if (kmf_cert->kmf_private.label)
118699ebb4caSwyllys 			free(kmf_cert->kmf_private.label);
118799ebb4caSwyllys 	}
118899ebb4caSwyllys }
118999ebb4caSwyllys 
119099ebb4caSwyllys KMF_RETURN
119130a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
119299ebb4caSwyllys {
119399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
119430a5e8faSwyllys 	KMF_DATA *cert = NULL;
119530a5e8faSwyllys 	char *outfilename = NULL;
119630a5e8faSwyllys 	char *dirpath = NULL;
119730a5e8faSwyllys 	char *fullpath = NULL;
119899ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
119999ebb4caSwyllys 
120030a5e8faSwyllys 	/* Get the cert data */
120130a5e8faSwyllys 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
120230a5e8faSwyllys 	if (cert == NULL || cert->Data == NULL)
120399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
120499ebb4caSwyllys 
120530a5e8faSwyllys 	/* Check the output filename and directory attributes. */
120630a5e8faSwyllys 	outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
120730a5e8faSwyllys 	    numattr);
120830a5e8faSwyllys 	if (outfilename == NULL)
120930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
121099ebb4caSwyllys 
121130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
121230a5e8faSwyllys 	fullpath = get_fullpath(dirpath, outfilename);
121399ebb4caSwyllys 	if (fullpath == NULL)
121430a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
121599ebb4caSwyllys 
121630a5e8faSwyllys 	/* Check the optional format attribute */
121730a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
121830a5e8faSwyllys 	    &format, NULL);
121930a5e8faSwyllys 	if (ret != KMF_OK) {
122030a5e8faSwyllys 		/* If there is no format attribute, then default to PEM */
122130a5e8faSwyllys 		format = KMF_FORMAT_PEM;
122299ebb4caSwyllys 		ret = KMF_OK;
122330a5e8faSwyllys 	} else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
122430a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
122599ebb4caSwyllys 		goto out;
122699ebb4caSwyllys 	}
122799ebb4caSwyllys 
122830a5e8faSwyllys 	/* Store the certificate in the file with the specified format */
122930a5e8faSwyllys 	ret = kmf_create_cert_file(cert, format, fullpath);
123099ebb4caSwyllys 
123199ebb4caSwyllys out:
123299ebb4caSwyllys 	if (fullpath != NULL)
123399ebb4caSwyllys 		free(fullpath);
123499ebb4caSwyllys 
123599ebb4caSwyllys 	return (ret);
123699ebb4caSwyllys }
123799ebb4caSwyllys 
123830a5e8faSwyllys 
123999ebb4caSwyllys KMF_RETURN
124030a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
124199ebb4caSwyllys {
124299ebb4caSwyllys 	KMF_RETURN rv;
124399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
12446b35cb3cSRichard PALO 	KMF_DATA certdata = { 0, NULL };
124530a5e8faSwyllys 	char *dirpath = NULL;
124630a5e8faSwyllys 	char *filename = NULL;
124730a5e8faSwyllys 	char *fullpath = NULL;
124830a5e8faSwyllys 	char *issuer = NULL;
124930a5e8faSwyllys 	char *subject = NULL;
125030a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
125130a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
125299ebb4caSwyllys 
125330a5e8faSwyllys 	/*
125430a5e8faSwyllys 	 * Get the DIRPATH and CERT_FILENAME attributes.  They can not be
125530a5e8faSwyllys 	 * NULL at the same time.
125630a5e8faSwyllys 	 */
125730a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
125830a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
125930a5e8faSwyllys 	    numattr);
126030a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
126199ebb4caSwyllys 	if (fullpath == NULL)
126299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
126399ebb4caSwyllys 
126430a5e8faSwyllys 	/* Get optional search criteria attributes */
126530a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
126630a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
126730a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
126830a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
126930a5e8faSwyllys 	    &validity, NULL);
127030a5e8faSwyllys 	if (rv != KMF_OK) {
127130a5e8faSwyllys 		validity = KMF_ALL_CERTS;
127230a5e8faSwyllys 		rv = KMF_OK;
127330a5e8faSwyllys 	}
127430a5e8faSwyllys 
127599ebb4caSwyllys 	if (isdir(fullpath)) {
127699ebb4caSwyllys 		DIR *dirp;
127799ebb4caSwyllys 		struct dirent *dp;
127899ebb4caSwyllys 
127999ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
128099ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
128199ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
128299ebb4caSwyllys 		}
128399ebb4caSwyllys 
128499ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
128599ebb4caSwyllys 			if (strcmp(dp->d_name, ".") != 0 &&
128699ebb4caSwyllys 			    strcmp(dp->d_name, "..") != 0) {
128799ebb4caSwyllys 				char *fname;
128899ebb4caSwyllys 
128999ebb4caSwyllys 				fname = get_fullpath(fullpath,
129099ebb4caSwyllys 				    (char *)&dp->d_name);
129199ebb4caSwyllys 
129299ebb4caSwyllys 				if (fname == NULL) {
129399ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
129499ebb4caSwyllys 					break;
129599ebb4caSwyllys 				}
129699ebb4caSwyllys 
129730a5e8faSwyllys 				rv = kmf_load_cert(kmfh, issuer, subject,
129830a5e8faSwyllys 				    serial, validity, fname, &certdata);
129999ebb4caSwyllys 
130099ebb4caSwyllys 				if (rv == KMF_ERR_CERT_NOT_FOUND) {
130199ebb4caSwyllys 					free(fname);
1302e65e5c2dSWyllys Ingersoll 					kmf_free_data(&certdata);
130399ebb4caSwyllys 					rv = KMF_OK;
130499ebb4caSwyllys 					continue;
130599ebb4caSwyllys 				} else if (rv != KMF_OK) {
130699ebb4caSwyllys 					free(fname);
130799ebb4caSwyllys 					break;
130899ebb4caSwyllys 				}
130999ebb4caSwyllys 
131099ebb4caSwyllys 				if (unlink(fname) != 0) {
131199ebb4caSwyllys 					SET_SYS_ERROR(kmfh, errno);
131299ebb4caSwyllys 					rv = KMF_ERR_INTERNAL;
131399ebb4caSwyllys 					free(fname);
131499ebb4caSwyllys 					break;
131599ebb4caSwyllys 				}
131699ebb4caSwyllys 				free(fname);
1317e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certdata);
131899ebb4caSwyllys 			}
131999ebb4caSwyllys 		}
132099ebb4caSwyllys 		(void) closedir(dirp);
132199ebb4caSwyllys 	} else {
132299ebb4caSwyllys 		/* Just try to load a single certificate */
132330a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
132430a5e8faSwyllys 		    fullpath, &certdata);
132599ebb4caSwyllys 		if (rv == KMF_OK) {
132699ebb4caSwyllys 			if (unlink(fullpath) != 0) {
132799ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
132899ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
132999ebb4caSwyllys 			}
133099ebb4caSwyllys 		}
133199ebb4caSwyllys 	}
133299ebb4caSwyllys 
133399ebb4caSwyllys out:
133499ebb4caSwyllys 	if (fullpath != NULL)
133599ebb4caSwyllys 		free(fullpath);
133699ebb4caSwyllys 
1337e65e5c2dSWyllys Ingersoll 	kmf_free_data(&certdata);
133899ebb4caSwyllys 
133999ebb4caSwyllys 	return (rv);
134099ebb4caSwyllys }
134199ebb4caSwyllys 
134299ebb4caSwyllys KMF_RETURN
134399ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
134499ebb4caSwyllys     KMF_DATA *keydata)
134599ebb4caSwyllys {
134699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
134799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
134899ebb4caSwyllys 	int n;
134999ebb4caSwyllys 
135099ebb4caSwyllys 	if (key == NULL || keydata == NULL ||
135199ebb4caSwyllys 	    key->keyp == NULL)
135299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
135399ebb4caSwyllys 
135499ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
135599ebb4caSwyllys 		RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
135699ebb4caSwyllys 
135799ebb4caSwyllys 		if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
135899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
135999ebb4caSwyllys 			return (KMF_ERR_ENCODING);
136099ebb4caSwyllys 		}
136199ebb4caSwyllys 		RSA_free(pubkey);
136299ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
136399ebb4caSwyllys 		DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
136499ebb4caSwyllys 
136599ebb4caSwyllys 		if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
136699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
136799ebb4caSwyllys 			return (KMF_ERR_ENCODING);
136899ebb4caSwyllys 		}
136999ebb4caSwyllys 		DSA_free(pubkey);
137099ebb4caSwyllys 	} else {
137199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
137299ebb4caSwyllys 	}
137399ebb4caSwyllys 	keydata->Length = n;
137499ebb4caSwyllys 
137599ebb4caSwyllys cleanup:
137699ebb4caSwyllys 	if (rv != KMF_OK) {
137799ebb4caSwyllys 		if (keydata->Data)
137899ebb4caSwyllys 			free(keydata->Data);
137999ebb4caSwyllys 		keydata->Data = NULL;
138099ebb4caSwyllys 		keydata->Length = 0;
138199ebb4caSwyllys 	}
138299ebb4caSwyllys 
138399ebb4caSwyllys 	return (rv);
138499ebb4caSwyllys }
138599ebb4caSwyllys 
138699ebb4caSwyllys static KMF_RETURN
138730a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
138830a5e8faSwyllys     KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
138999ebb4caSwyllys {
139099ebb4caSwyllys 	int rv = 0;
139199ebb4caSwyllys 	RSA *rsa;
139299ebb4caSwyllys 	DSA *dsa;
139399ebb4caSwyllys 
13945b3e1433Swyllys 	if (pkey == NULL || out == NULL)
13955b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
13965b3e1433Swyllys 
139799ebb4caSwyllys 	switch (format) {
139873cc0e02Swyllys 		case KMF_FORMAT_RAWKEY:
139973cc0e02Swyllys 			/* same as ASN.1 */
140099ebb4caSwyllys 		case KMF_FORMAT_ASN1:
1401300fdee2SAndy Fiddaman 			if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
140230a5e8faSwyllys 				if (private)
140399ebb4caSwyllys 					rv = i2d_RSAPrivateKey_bio(out, rsa);
140430a5e8faSwyllys 				else
140530a5e8faSwyllys 					rv = i2d_RSAPublicKey_bio(out, rsa);
1406300fdee2SAndy Fiddaman 			} else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
140799ebb4caSwyllys 				rv = i2d_DSAPrivateKey_bio(out, dsa);
140899ebb4caSwyllys 			}
140999ebb4caSwyllys 			if (rv == 1) {
141099ebb4caSwyllys 				rv = KMF_OK;
141199ebb4caSwyllys 			} else {
141299ebb4caSwyllys 				SET_ERROR(kmfh, rv);
141399ebb4caSwyllys 			}
141499ebb4caSwyllys 			break;
141599ebb4caSwyllys 		case KMF_FORMAT_PEM:
1416300fdee2SAndy Fiddaman 			if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
141730a5e8faSwyllys 				if (private)
141899ebb4caSwyllys 					rv = PEM_write_bio_RSAPrivateKey(out,
141930a5e8faSwyllys 					    rsa, NULL, NULL, 0, NULL,
142030a5e8faSwyllys 					    (cred != NULL ? cred->cred : NULL));
142130a5e8faSwyllys 				else
142230a5e8faSwyllys 					rv = PEM_write_bio_RSAPublicKey(out,
142330a5e8faSwyllys 					    rsa);
1424300fdee2SAndy Fiddaman 			} else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
142599ebb4caSwyllys 				rv = PEM_write_bio_DSAPrivateKey(out,
142630a5e8faSwyllys 				    dsa, NULL, NULL, 0, NULL,
142730a5e8faSwyllys 				    (cred != NULL ? cred->cred : NULL));
142899ebb4caSwyllys 			}
142999ebb4caSwyllys 
143099ebb4caSwyllys 			if (rv == 1) {
143199ebb4caSwyllys 				rv = KMF_OK;
143299ebb4caSwyllys 			} else {
143399ebb4caSwyllys 				SET_ERROR(kmfh, rv);
143499ebb4caSwyllys 			}
143599ebb4caSwyllys 			break;
143699ebb4caSwyllys 
143799ebb4caSwyllys 		default:
143899ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
143999ebb4caSwyllys 	}
144099ebb4caSwyllys 
144199ebb4caSwyllys 	return (rv);
144299ebb4caSwyllys }
144399ebb4caSwyllys 
144499ebb4caSwyllys KMF_RETURN
1445*4942e222SAndy Fiddaman OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
144699ebb4caSwyllys {
144799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
144899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1449300fdee2SAndy Fiddaman 	uint32_t eValue = RSA_F4;
1450300fdee2SAndy Fiddaman 	BIGNUM *eValue_bn = NULL;
145199ebb4caSwyllys 	RSA *sslPrivKey = NULL;
145299ebb4caSwyllys 	DSA *sslDSAKey = NULL;
145399ebb4caSwyllys 	EVP_PKEY *eprikey = NULL;
145499ebb4caSwyllys 	EVP_PKEY *epubkey = NULL;
145599ebb4caSwyllys 	BIO *out = NULL;
145630a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
145730a5e8faSwyllys 	uint32_t keylen = 1024;
145830a5e8faSwyllys 	uint32_t keylen_size = sizeof (uint32_t);
145930a5e8faSwyllys 	boolean_t storekey = TRUE;
146030a5e8faSwyllys 	KMF_KEY_ALG keytype = KMF_RSA;
146199ebb4caSwyllys 
1462300fdee2SAndy Fiddaman 	eValue_bn = BN_new();
1463300fdee2SAndy Fiddaman 	if (eValue_bn == NULL)
1464300fdee2SAndy Fiddaman 		return (KMF_ERR_MEMORY);
1465300fdee2SAndy Fiddaman 	if (BN_set_word(eValue_bn, eValue) == 0) {
1466300fdee2SAndy Fiddaman 		rv = KMF_ERR_KEYGEN_FAILED;
1467300fdee2SAndy Fiddaman 		goto cleanup;
1468300fdee2SAndy Fiddaman 	}
1469300fdee2SAndy Fiddaman 
147030a5e8faSwyllys 	rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
147130a5e8faSwyllys 	    &storekey, NULL);
147230a5e8faSwyllys 	if (rv != KMF_OK) {
147330a5e8faSwyllys 		/* "storekey" is optional. Default is TRUE */
147430a5e8faSwyllys 		rv = KMF_OK;
147599ebb4caSwyllys 	}
147699ebb4caSwyllys 
147730a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
147830a5e8faSwyllys 	    (void *)&keytype, NULL);
147930a5e8faSwyllys 	if (rv != KMF_OK)
148030a5e8faSwyllys 		/* keytype is optional.  KMF_RSA is default */
148130a5e8faSwyllys 		rv = KMF_OK;
148299ebb4caSwyllys 
148330a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
1484300fdee2SAndy Fiddaman 	if (pubkey == NULL) {
1485300fdee2SAndy Fiddaman 		rv = KMF_ERR_BAD_PARAMETER;
1486300fdee2SAndy Fiddaman 		goto cleanup;
1487300fdee2SAndy Fiddaman 	}
148899ebb4caSwyllys 
148930a5e8faSwyllys 	privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
1490300fdee2SAndy Fiddaman 	if (privkey == NULL) {
1491300fdee2SAndy Fiddaman 		rv = KMF_ERR_BAD_PARAMETER;
1492300fdee2SAndy Fiddaman 		goto cleanup;
1493300fdee2SAndy Fiddaman 	}
149430a5e8faSwyllys 
149530a5e8faSwyllys 	(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
149630a5e8faSwyllys 	(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
149799ebb4caSwyllys 
149899ebb4caSwyllys 	eprikey = EVP_PKEY_new();
149999ebb4caSwyllys 	if (eprikey == NULL) {
150099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
150199ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
150299ebb4caSwyllys 		goto cleanup;
150399ebb4caSwyllys 	}
150499ebb4caSwyllys 	epubkey = EVP_PKEY_new();
150599ebb4caSwyllys 	if (epubkey == NULL) {
150699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
150799ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
150899ebb4caSwyllys 		goto cleanup;
150999ebb4caSwyllys 	}
151030a5e8faSwyllys 	if (keytype == KMF_RSA) {
151130a5e8faSwyllys 		KMF_BIGINT *rsaexp = NULL;
151299ebb4caSwyllys 
151330a5e8faSwyllys 		rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
151430a5e8faSwyllys 		if (rsaexp != NULL) {
151530a5e8faSwyllys 			if (rsaexp->len > 0 &&
151630a5e8faSwyllys 			    rsaexp->len <= sizeof (eValue) &&
151730a5e8faSwyllys 			    rsaexp->val != NULL) {
151830a5e8faSwyllys 				eValue = *(uint32_t *)rsaexp->val;
1519300fdee2SAndy Fiddaman 				if (BN_set_word(eValue_bn, eValue) == 0) {
1520300fdee2SAndy Fiddaman 					rv = KMF_ERR_BAD_PARAMETER;
1521300fdee2SAndy Fiddaman 					goto cleanup;
1522300fdee2SAndy Fiddaman 				}
152330a5e8faSwyllys 			} else {
152430a5e8faSwyllys 				rv = KMF_ERR_BAD_PARAMETER;
152530a5e8faSwyllys 				goto cleanup;
152630a5e8faSwyllys 			}
152730a5e8faSwyllys 		} else {
152830a5e8faSwyllys 			/* RSA Exponent is optional. Default is 0x10001 */
152930a5e8faSwyllys 			rv = KMF_OK;
153030a5e8faSwyllys 		}
153130a5e8faSwyllys 
153230a5e8faSwyllys 		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
153330a5e8faSwyllys 		    &keylen, &keylen_size);
153430a5e8faSwyllys 		if (rv == KMF_ERR_ATTR_NOT_FOUND)
153530a5e8faSwyllys 			/* keylen is optional, default is 1024 */
153630a5e8faSwyllys 			rv = KMF_OK;
153730a5e8faSwyllys 		if (rv != KMF_OK) {
153830a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
153930a5e8faSwyllys 			goto cleanup;
154030a5e8faSwyllys 		}
154130a5e8faSwyllys 
1542300fdee2SAndy Fiddaman 		sslPrivKey = RSA_new();
1543300fdee2SAndy Fiddaman 		if (sslPrivKey == NULL ||
1544300fdee2SAndy Fiddaman 		    RSA_generate_key_ex(sslPrivKey, keylen, eValue_bn, NULL)
1545300fdee2SAndy Fiddaman 		    == 0) {
154699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
154799ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
154899ebb4caSwyllys 		} else {
154930a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
155099ebb4caSwyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
155199ebb4caSwyllys 			privkey->keyalg = KMF_RSA;
155299ebb4caSwyllys 			privkey->keyclass = KMF_ASYM_PRI;
155399ebb4caSwyllys 			privkey->israw = FALSE;
155499ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
155530a5e8faSwyllys 
155699ebb4caSwyllys 			/* OpenSSL derives the public key from the private */
155730a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
155899ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
155999ebb4caSwyllys 			pubkey->keyalg = KMF_RSA;
156099ebb4caSwyllys 			pubkey->israw = FALSE;
156199ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
156299ebb4caSwyllys 			pubkey->keyp = (void *)epubkey;
156399ebb4caSwyllys 		}
156430a5e8faSwyllys 	} else if (keytype == KMF_DSA) {
1565300fdee2SAndy Fiddaman 		BIGNUM *p, *q, *g;
1566300fdee2SAndy Fiddaman 
156799ebb4caSwyllys 		sslDSAKey = DSA_new();
156899ebb4caSwyllys 		if (sslDSAKey == NULL) {
156999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
157099ebb4caSwyllys 			return (KMF_ERR_MEMORY);
157199ebb4caSwyllys 		}
157299ebb4caSwyllys 
1573300fdee2SAndy Fiddaman 		p = BN_bin2bn(P, sizeof (P), NULL);
1574300fdee2SAndy Fiddaman 		q = BN_bin2bn(Q, sizeof (Q), NULL);
1575300fdee2SAndy Fiddaman 		g = BN_bin2bn(G, sizeof (G), NULL);
1576300fdee2SAndy Fiddaman 		if (p == NULL || q == NULL || g == NULL) {
1577300fdee2SAndy Fiddaman 			BN_free(p);
1578300fdee2SAndy Fiddaman 			BN_free(q);
1579300fdee2SAndy Fiddaman 			BN_free(g);
158099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
158199ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
158299ebb4caSwyllys 			goto cleanup;
158399ebb4caSwyllys 		}
1584300fdee2SAndy Fiddaman 
1585300fdee2SAndy Fiddaman 		if (DSA_set0_pqg(sslDSAKey, p, q, g) == 0) {
158699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
158799ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
158899ebb4caSwyllys 			goto cleanup;
158999ebb4caSwyllys 		}
159099ebb4caSwyllys 
159199ebb4caSwyllys 		if (!DSA_generate_key(sslDSAKey)) {
159299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
159399ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
159499ebb4caSwyllys 			goto cleanup;
159599ebb4caSwyllys 		}
159699ebb4caSwyllys 
159799ebb4caSwyllys 		privkey->kstype = KMF_KEYSTORE_OPENSSL;
159899ebb4caSwyllys 		privkey->keyalg = KMF_DSA;
159999ebb4caSwyllys 		privkey->keyclass = KMF_ASYM_PRI;
160099ebb4caSwyllys 		privkey->israw = FALSE;
160199ebb4caSwyllys 		if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
160299ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
160399ebb4caSwyllys 		} else {
160499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
160599ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
160699ebb4caSwyllys 			goto cleanup;
160799ebb4caSwyllys 		}
160899ebb4caSwyllys 
160999ebb4caSwyllys 		pubkey->kstype = KMF_KEYSTORE_OPENSSL;
161099ebb4caSwyllys 		pubkey->keyalg = KMF_DSA;
161199ebb4caSwyllys 		pubkey->keyclass = KMF_ASYM_PUB;
161299ebb4caSwyllys 		pubkey->israw = FALSE;
161399ebb4caSwyllys 
161499ebb4caSwyllys 		if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
161599ebb4caSwyllys 			pubkey->keyp = (void *)epubkey;
161699ebb4caSwyllys 		} else {
161799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
161899ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
161999ebb4caSwyllys 			goto cleanup;
162099ebb4caSwyllys 		}
162199ebb4caSwyllys 	}
162299ebb4caSwyllys 
162399ebb4caSwyllys 	if (rv != KMF_OK) {
162499ebb4caSwyllys 		goto cleanup;
162599ebb4caSwyllys 	}
162699ebb4caSwyllys 
162730a5e8faSwyllys 	if (storekey) {
162830a5e8faSwyllys 		KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
162930a5e8faSwyllys 		int i = 0;
163030a5e8faSwyllys 		char *keyfile = NULL, *dirpath = NULL;
163130a5e8faSwyllys 		KMF_ENCODE_FORMAT format;
163230a5e8faSwyllys 		/*
163330a5e8faSwyllys 		 * Construct a new attribute arrray and call openssl_store_key
163430a5e8faSwyllys 		 */
163530a5e8faSwyllys 		kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
163630a5e8faSwyllys 		    privkey, sizeof (privkey));
163730a5e8faSwyllys 		i++;
163830a5e8faSwyllys 
163930a5e8faSwyllys 		dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
164030a5e8faSwyllys 		if (dirpath != NULL) {
164130a5e8faSwyllys 			storeattrs[i].type = KMF_DIRPATH_ATTR;
164230a5e8faSwyllys 			storeattrs[i].pValue = dirpath;
164330a5e8faSwyllys 			storeattrs[i].valueLen = strlen(dirpath);
164430a5e8faSwyllys 			i++;
164530a5e8faSwyllys 		} else {
164630a5e8faSwyllys 			rv = KMF_OK; /* DIRPATH is optional */
164799ebb4caSwyllys 		}
164830a5e8faSwyllys 		keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
164930a5e8faSwyllys 		    attrlist, numattr);
165030a5e8faSwyllys 		if (keyfile != NULL) {
165130a5e8faSwyllys 			storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
165230a5e8faSwyllys 			storeattrs[i].pValue = keyfile;
165330a5e8faSwyllys 			storeattrs[i].valueLen = strlen(keyfile);
165430a5e8faSwyllys 			i++;
165530a5e8faSwyllys 		} else {
165630a5e8faSwyllys 			goto cleanup; /* KEYFILE is required */
165730a5e8faSwyllys 		}
165830a5e8faSwyllys 		rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
165930a5e8faSwyllys 		    (void *)&format, NULL);
166030a5e8faSwyllys 		if (rv == KMF_OK) {
166130a5e8faSwyllys 			storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
166230a5e8faSwyllys 			storeattrs[i].pValue = &format;
166330a5e8faSwyllys 			storeattrs[i].valueLen = sizeof (format);
166430a5e8faSwyllys 			i++;
166530a5e8faSwyllys 		}
166630a5e8faSwyllys 
166730a5e8faSwyllys 		rv = OpenSSL_StoreKey(handle, i, storeattrs);
166830a5e8faSwyllys 	}
166999ebb4caSwyllys 
167099ebb4caSwyllys cleanup:
1671300fdee2SAndy Fiddaman 	if (eValue_bn != NULL)
1672300fdee2SAndy Fiddaman 		BN_free(eValue_bn);
1673300fdee2SAndy Fiddaman 
167499ebb4caSwyllys 	if (rv != KMF_OK) {
167599ebb4caSwyllys 		if (eprikey != NULL)
167699ebb4caSwyllys 			EVP_PKEY_free(eprikey);
167799ebb4caSwyllys 
167899ebb4caSwyllys 		if (epubkey != NULL)
167999ebb4caSwyllys 			EVP_PKEY_free(epubkey);
168099ebb4caSwyllys 
168199ebb4caSwyllys 		if (pubkey->keylabel) {
168299ebb4caSwyllys 			free(pubkey->keylabel);
168399ebb4caSwyllys 			pubkey->keylabel = NULL;
168499ebb4caSwyllys 		}
168599ebb4caSwyllys 
168699ebb4caSwyllys 		if (privkey->keylabel) {
168799ebb4caSwyllys 			free(privkey->keylabel);
168899ebb4caSwyllys 			privkey->keylabel = NULL;
168999ebb4caSwyllys 		}
169099ebb4caSwyllys 
169199ebb4caSwyllys 		pubkey->keyp = NULL;
169299ebb4caSwyllys 		privkey->keyp = NULL;
169399ebb4caSwyllys 	}
169499ebb4caSwyllys 
169599ebb4caSwyllys 	if (sslPrivKey)
169699ebb4caSwyllys 		RSA_free(sslPrivKey);
169799ebb4caSwyllys 
169899ebb4caSwyllys 	if (sslDSAKey)
169999ebb4caSwyllys 		DSA_free(sslDSAKey);
170099ebb4caSwyllys 
170199ebb4caSwyllys 	if (out != NULL)
170299ebb4caSwyllys 		(void) BIO_free(out);
170399ebb4caSwyllys 
170499ebb4caSwyllys 	return (rv);
170599ebb4caSwyllys }
170699ebb4caSwyllys 
1707e65e5c2dSWyllys Ingersoll /*
1708e65e5c2dSWyllys Ingersoll  * Make sure the BN conversion is properly padded with 0x00
1709e65e5c2dSWyllys Ingersoll  * bytes.  If not, signature verification for DSA signatures
1710e65e5c2dSWyllys Ingersoll  * may fail in the case where the bignum value does not use
1711e65e5c2dSWyllys Ingersoll  * all of the bits.
1712e65e5c2dSWyllys Ingersoll  */
1713e65e5c2dSWyllys Ingersoll static int
1714*4942e222SAndy Fiddaman fixbnlen(const BIGNUM *bn, unsigned char *buf, int len)
1715*4942e222SAndy Fiddaman {
1716e65e5c2dSWyllys Ingersoll 	int bytes = len - BN_num_bytes(bn);
17172c9a247fSWyllys Ingersoll 
17182c9a247fSWyllys Ingersoll 	/* prepend with leading 0x00 if necessary */
1719e65e5c2dSWyllys Ingersoll 	while (bytes-- > 0)
1720e65e5c2dSWyllys Ingersoll 		*buf++ = 0;
1721e65e5c2dSWyllys Ingersoll 
17222c9a247fSWyllys Ingersoll 	(void) BN_bn2bin(bn, buf);
17232c9a247fSWyllys Ingersoll 	/*
17242c9a247fSWyllys Ingersoll 	 * Return the desired length since we prepended it
17252c9a247fSWyllys Ingersoll 	 * with the necessary 0x00 padding.
17262c9a247fSWyllys Ingersoll 	 */
17272c9a247fSWyllys Ingersoll 	return (len);
1728e65e5c2dSWyllys Ingersoll }
1729e65e5c2dSWyllys Ingersoll 
173099ebb4caSwyllys KMF_RETURN
173199ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
173299ebb4caSwyllys     KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
173399ebb4caSwyllys {
173499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
173599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
173699ebb4caSwyllys 	KMF_ALGORITHM_INDEX		AlgId;
1737300fdee2SAndy Fiddaman 	EVP_MD_CTX *ctx;
173899ebb4caSwyllys 	const EVP_MD *md;
173902744e81Swyllys 
174099ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
174199ebb4caSwyllys 	    tobesigned == NULL || output == NULL ||
174299ebb4caSwyllys 	    tobesigned->Data == NULL ||
174399ebb4caSwyllys 	    output->Data == NULL)
174499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
174599ebb4caSwyllys 
174699ebb4caSwyllys 	/* Map the OID to an OpenSSL algorithm */
174730a5e8faSwyllys 	AlgId = x509_algoid_to_algid(AlgOID);
174899ebb4caSwyllys 	if (AlgId == KMF_ALGID_NONE)
1749e65e5c2dSWyllys Ingersoll 		return (KMF_ERR_BAD_ALGORITHM);
175099ebb4caSwyllys 
175199ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
175299ebb4caSwyllys 		EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
175399ebb4caSwyllys 		uchar_t *p;
175402744e81Swyllys 		int len;
1755553e44ceSAndrew Stormont 		switch (AlgId) {
1756553e44ceSAndrew Stormont #ifndef	OPENSSL_NO_MD5
1757553e44ceSAndrew Stormont 		case KMF_ALGID_MD5WithRSA:
175899ebb4caSwyllys 			md = EVP_md5();
1759553e44ceSAndrew Stormont 			break;
1760553e44ceSAndrew Stormont #endif
1761553e44ceSAndrew Stormont #ifndef	OPENSSL_NO_SHA
1762553e44ceSAndrew Stormont 		case KMF_ALGID_SHA1WithRSA:
176399ebb4caSwyllys 			md = EVP_sha1();
1764553e44ceSAndrew Stormont 			break;
1765553e44ceSAndrew Stormont #endif
1766553e44ceSAndrew Stormont #ifndef	OPENSSL_NO_SHA256
1767553e44ceSAndrew Stormont 		case KMF_ALGID_SHA256WithRSA:
1768e65e5c2dSWyllys Ingersoll 			md = EVP_sha256();
1769553e44ceSAndrew Stormont 			break;
1770553e44ceSAndrew Stormont #endif
1771553e44ceSAndrew Stormont #ifndef	OPENSSL_NO_SHA512
1772553e44ceSAndrew Stormont 		case KMF_ALGID_SHA384WithRSA:
1773e65e5c2dSWyllys Ingersoll 			md = EVP_sha384();
1774553e44ceSAndrew Stormont 			break;
1775553e44ceSAndrew Stormont 		case KMF_ALGID_SHA512WithRSA:
1776e65e5c2dSWyllys Ingersoll 			md = EVP_sha512();
1777553e44ceSAndrew Stormont 			break;
1778553e44ceSAndrew Stormont #endif
1779553e44ceSAndrew Stormont 		case KMF_ALGID_RSA:
178002744e81Swyllys 			md = NULL;
1781553e44ceSAndrew Stormont 			break;
1782553e44ceSAndrew Stormont 		default:
1783e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_ALGORITHM);
1784553e44ceSAndrew Stormont 		}
178599ebb4caSwyllys 
178602744e81Swyllys 		if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
178702744e81Swyllys 			RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
178899ebb4caSwyllys 
178902744e81Swyllys 			p = output->Data;
179002744e81Swyllys 			if ((len = RSA_private_encrypt(tobesigned->Length,
179102744e81Swyllys 			    tobesigned->Data, p, rsa,
179202744e81Swyllys 			    RSA_PKCS1_PADDING)) <= 0) {
179302744e81Swyllys 				SET_ERROR(kmfh, ERR_get_error());
179402744e81Swyllys 				ret = KMF_ERR_INTERNAL;
179502744e81Swyllys 			}
179602744e81Swyllys 			output->Length = len;
179702744e81Swyllys 		} else {
1798300fdee2SAndy Fiddaman 			if ((ctx = EVP_MD_CTX_new()) == NULL)
1799300fdee2SAndy Fiddaman 				return (KMF_ERR_MEMORY);
1800300fdee2SAndy Fiddaman 			(void) EVP_SignInit_ex(ctx, md, NULL);
1801300fdee2SAndy Fiddaman 			(void) EVP_SignUpdate(ctx, tobesigned->Data,
180299ebb4caSwyllys 			    (uint32_t)tobesigned->Length);
180399ebb4caSwyllys 			len = (uint32_t)output->Length;
180499ebb4caSwyllys 			p = output->Data;
1805300fdee2SAndy Fiddaman 			if (!EVP_SignFinal(ctx, p, (uint32_t *)&len, pkey)) {
180699ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
180702744e81Swyllys 				len = 0;
180802744e81Swyllys 				ret = KMF_ERR_INTERNAL;
180999ebb4caSwyllys 			}
181099ebb4caSwyllys 			output->Length = len;
1811300fdee2SAndy Fiddaman 			EVP_MD_CTX_free(ctx);
181202744e81Swyllys 		}
181399ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
181499ebb4caSwyllys 		DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
181599ebb4caSwyllys 
181699ebb4caSwyllys 		uchar_t hash[EVP_MAX_MD_SIZE];
181799ebb4caSwyllys 		uint32_t hashlen;
181899ebb4caSwyllys 		DSA_SIG *dsasig;
181999ebb4caSwyllys 
1820e65e5c2dSWyllys Ingersoll 		if (AlgId == KMF_ALGID_DSA ||
1821e65e5c2dSWyllys Ingersoll 		    AlgId == KMF_ALGID_SHA1WithDSA)
1822e65e5c2dSWyllys Ingersoll 			md = EVP_sha1();
1823e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA256WithDSA)
1824e65e5c2dSWyllys Ingersoll 			md = EVP_sha256();
1825e65e5c2dSWyllys Ingersoll 		else /* Bad algorithm */
1826e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_ALGORITHM);
1827e65e5c2dSWyllys Ingersoll 
182899ebb4caSwyllys 		/*
182999ebb4caSwyllys 		 * OpenSSL EVP_Sign operation automatically converts to
183099ebb4caSwyllys 		 * ASN.1 output so we do the operations separately so we
183199ebb4caSwyllys 		 * are assured of NOT getting ASN.1 output returned.
183299ebb4caSwyllys 		 * KMF does not want ASN.1 encoded results because
183399ebb4caSwyllys 		 * not all mechanisms return ASN.1 encodings (PKCS#11
183499ebb4caSwyllys 		 * and NSS return raw signature data).
183599ebb4caSwyllys 		 */
1836300fdee2SAndy Fiddaman 		if ((ctx = EVP_MD_CTX_new()) == NULL)
1837300fdee2SAndy Fiddaman 			return (KMF_ERR_MEMORY);
1838300fdee2SAndy Fiddaman 		(void) EVP_DigestInit_ex(ctx, md, NULL);
1839300fdee2SAndy Fiddaman 		(void) EVP_DigestUpdate(ctx, tobesigned->Data,
184099ebb4caSwyllys 		    tobesigned->Length);
1841300fdee2SAndy Fiddaman 		(void) EVP_DigestFinal_ex(ctx, hash, &hashlen);
184299ebb4caSwyllys 
1843e65e5c2dSWyllys Ingersoll 		/* Only sign first 20 bytes for SHA2 */
1844e65e5c2dSWyllys Ingersoll 		if (AlgId == KMF_ALGID_SHA256WithDSA)
1845e65e5c2dSWyllys Ingersoll 			hashlen = 20;
184699ebb4caSwyllys 		dsasig = DSA_do_sign(hash, hashlen, dsa);
184799ebb4caSwyllys 		if (dsasig != NULL) {
184899ebb4caSwyllys 			int i;
1849300fdee2SAndy Fiddaman 			const BIGNUM *r, *s;
1850300fdee2SAndy Fiddaman 
1851300fdee2SAndy Fiddaman 			DSA_SIG_get0(dsasig, &r, &s);
1852300fdee2SAndy Fiddaman 			output->Length = i = fixbnlen(r, output->Data,
1853e65e5c2dSWyllys Ingersoll 			    hashlen);
18542c9a247fSWyllys Ingersoll 
1855300fdee2SAndy Fiddaman 			output->Length += fixbnlen(s, &output->Data[i],
1856e65e5c2dSWyllys Ingersoll 			    hashlen);
18572c9a247fSWyllys Ingersoll 
185899ebb4caSwyllys 			DSA_SIG_free(dsasig);
185999ebb4caSwyllys 		} else {
186099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
186199ebb4caSwyllys 		}
1862300fdee2SAndy Fiddaman 		EVP_MD_CTX_free(ctx);
186399ebb4caSwyllys 	} else {
186499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
186599ebb4caSwyllys 	}
186699ebb4caSwyllys cleanup:
186799ebb4caSwyllys 	return (ret);
186899ebb4caSwyllys }
186999ebb4caSwyllys 
187099ebb4caSwyllys KMF_RETURN
1871*4942e222SAndy Fiddaman OpenSSL_DeleteKey(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
187299ebb4caSwyllys {
187399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
187430a5e8faSwyllys 	KMF_KEY_HANDLE *key;
187530a5e8faSwyllys 	boolean_t destroy = B_TRUE;
187630a5e8faSwyllys 
187730a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
187899ebb4caSwyllys 	if (key == NULL || key->keyp == NULL)
187999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
188099ebb4caSwyllys 
188130a5e8faSwyllys 	rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
188230a5e8faSwyllys 	    (void *)&destroy, NULL);
188330a5e8faSwyllys 	if (rv != KMF_OK) {
188430a5e8faSwyllys 		/* "destroy" is optional. Default is TRUE */
188530a5e8faSwyllys 		rv = KMF_OK;
188630a5e8faSwyllys 	}
188730a5e8faSwyllys 
188899ebb4caSwyllys 	if (key->keyclass != KMF_ASYM_PUB &&
188999ebb4caSwyllys 	    key->keyclass != KMF_ASYM_PRI &&
189099ebb4caSwyllys 	    key->keyclass != KMF_SYMMETRIC)
189199ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
189299ebb4caSwyllys 
189399ebb4caSwyllys 	if (key->keyclass == KMF_SYMMETRIC) {
189430a5e8faSwyllys 		kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
189599ebb4caSwyllys 		key->keyp = NULL;
189699ebb4caSwyllys 	} else {
189799ebb4caSwyllys 		if (key->keyp != NULL) {
189899ebb4caSwyllys 			EVP_PKEY_free(key->keyp);
189999ebb4caSwyllys 			key->keyp = NULL;
190099ebb4caSwyllys 		}
190199ebb4caSwyllys 	}
190299ebb4caSwyllys 
190399ebb4caSwyllys 	if (key->keylabel != NULL) {
190499ebb4caSwyllys 		EVP_PKEY *pkey = NULL;
190599ebb4caSwyllys 		/* If the file exists, make sure it is a proper key. */
190699ebb4caSwyllys 		pkey = openssl_load_key(handle, key->keylabel);
190799ebb4caSwyllys 		if (pkey == NULL) {
19085b3e1433Swyllys 			if (key->keylabel != NULL) {
190999ebb4caSwyllys 				free(key->keylabel);
191099ebb4caSwyllys 				key->keylabel = NULL;
19115b3e1433Swyllys 			}
191299ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
191399ebb4caSwyllys 		}
191499ebb4caSwyllys 		EVP_PKEY_free(pkey);
191599ebb4caSwyllys 
191699ebb4caSwyllys 		if (destroy) {
191799ebb4caSwyllys 			if (unlink(key->keylabel) != 0) {
191899ebb4caSwyllys 				KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
191999ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
192099ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
192199ebb4caSwyllys 			}
192299ebb4caSwyllys 		}
192399ebb4caSwyllys 		if (key->keylabel != NULL) {
192499ebb4caSwyllys 			free(key->keylabel);
192599ebb4caSwyllys 			key->keylabel = NULL;
192699ebb4caSwyllys 		}
192799ebb4caSwyllys 	}
192899ebb4caSwyllys 	return (rv);
192999ebb4caSwyllys }
193099ebb4caSwyllys 
193199ebb4caSwyllys KMF_RETURN
193299ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
193399ebb4caSwyllys {
193499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
193599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
193699ebb4caSwyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
193799ebb4caSwyllys 
193899ebb4caSwyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
193999ebb4caSwyllys 	if (strlen(str)) {
194099ebb4caSwyllys 		*msgstr = (char *)strdup(str);
194199ebb4caSwyllys 		if ((*msgstr) == NULL)
194299ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
194399ebb4caSwyllys 	} else {
194499ebb4caSwyllys 		*msgstr = NULL;
194599ebb4caSwyllys 	}
194699ebb4caSwyllys 
194799ebb4caSwyllys 	return (ret);
194899ebb4caSwyllys }
194999ebb4caSwyllys 
195099ebb4caSwyllys static int
195199ebb4caSwyllys ext2NID(int kmfext)
195299ebb4caSwyllys {
195399ebb4caSwyllys 	switch (kmfext) {
195499ebb4caSwyllys 		case KMF_X509_EXT_KEY_USAGE:
195599ebb4caSwyllys 			return (NID_key_usage);
195699ebb4caSwyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
195799ebb4caSwyllys 			return (NID_private_key_usage_period);
195899ebb4caSwyllys 		case KMF_X509_EXT_CERT_POLICIES:
195999ebb4caSwyllys 			return (NID_certificate_policies);
196099ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
196199ebb4caSwyllys 			return (NID_subject_alt_name);
196299ebb4caSwyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
196399ebb4caSwyllys 			return (NID_issuer_alt_name);
196499ebb4caSwyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
196599ebb4caSwyllys 			return (NID_basic_constraints);
196699ebb4caSwyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
196799ebb4caSwyllys 			return (NID_ext_key_usage);
196899ebb4caSwyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
196999ebb4caSwyllys 			return (NID_authority_key_identifier);
197099ebb4caSwyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
197199ebb4caSwyllys 			return (NID_crl_distribution_points);
197299ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
197399ebb4caSwyllys 			return (NID_subject_key_identifier);
197499ebb4caSwyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
197599ebb4caSwyllys 			return (OBJ_sn2nid("policyMappings"));
197699ebb4caSwyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
197799ebb4caSwyllys 			return (OBJ_sn2nid("nameConstraints"));
197899ebb4caSwyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
197999ebb4caSwyllys 			return (OBJ_sn2nid("policyConstraints"));
198099ebb4caSwyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
198199ebb4caSwyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
198299ebb4caSwyllys 		case KMF_X509_EXT_FRESHEST_CRL:
198399ebb4caSwyllys 			return (OBJ_sn2nid("freshestCRL"));
198499ebb4caSwyllys 		default:
198599ebb4caSwyllys 			return (NID_undef);
198699ebb4caSwyllys 	}
198799ebb4caSwyllys }
198899ebb4caSwyllys 
198999ebb4caSwyllys KMF_RETURN
199099ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
199199ebb4caSwyllys     KMF_PRINTABLE_ITEM flag, char *resultStr)
199299ebb4caSwyllys {
199399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
199499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
199599ebb4caSwyllys 	X509 *xcert = NULL;
199699ebb4caSwyllys 	unsigned char *outbuf = NULL;
199799ebb4caSwyllys 	unsigned char *outbuf_p;
199899ebb4caSwyllys 	int j;
199999ebb4caSwyllys 	int ext_index, nid, len;
200099ebb4caSwyllys 	BIO *mem = NULL;
200170f9559bSTheo Schlossnagle 	STACK_OF(OPENSSL_STRING) *emlst = NULL;
200299ebb4caSwyllys 	X509_EXTENSION *ex;
200399ebb4caSwyllys 
200499ebb4caSwyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
200599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
200699ebb4caSwyllys 	}
200799ebb4caSwyllys 
200899ebb4caSwyllys 	/* copy cert data to outbuf */
200999ebb4caSwyllys 	outbuf = malloc(pcert->Length);
201099ebb4caSwyllys 	if (outbuf == NULL) {
201199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
201299ebb4caSwyllys 	}
201399ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
201499ebb4caSwyllys 
201599ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
201699ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
201799ebb4caSwyllys 	if (xcert == NULL) {
201899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
201999ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
202099ebb4caSwyllys 		goto out;
202199ebb4caSwyllys 	}
202299ebb4caSwyllys 
202399ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
202499ebb4caSwyllys 	if (mem == NULL) {
202599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
202699ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
202799ebb4caSwyllys 		goto out;
202899ebb4caSwyllys 	}
202999ebb4caSwyllys 
203099ebb4caSwyllys 	switch (flag) {
203199ebb4caSwyllys 	case KMF_CERT_ISSUER:
203299ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
203399ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
203499ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
203599ebb4caSwyllys 		break;
203699ebb4caSwyllys 
203799ebb4caSwyllys 	case KMF_CERT_SUBJECT:
203899ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
203999ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
204099ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
204199ebb4caSwyllys 		break;
204299ebb4caSwyllys 
204399ebb4caSwyllys 	case KMF_CERT_VERSION:
2044300fdee2SAndy Fiddaman 		(void) snprintf(resultStr, KMF_CERT_PRINTABLE_LEN,
2045300fdee2SAndy Fiddaman 		    "%ld", X509_get_version(xcert));
204699ebb4caSwyllys 		len = strlen(resultStr);
204799ebb4caSwyllys 		break;
204899ebb4caSwyllys 
204999ebb4caSwyllys 	case KMF_CERT_SERIALNUM:
205099ebb4caSwyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
205199ebb4caSwyllys 			(void) strcpy(resultStr, "0x");
205299ebb4caSwyllys 			len = BIO_gets(mem, &resultStr[2],
205399ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN - 2);
205499ebb4caSwyllys 		}
205599ebb4caSwyllys 		break;
205699ebb4caSwyllys 
205799ebb4caSwyllys 	case KMF_CERT_NOTBEFORE:
2058300fdee2SAndy Fiddaman 		(void) ASN1_TIME_print(mem, X509_getm_notBefore(xcert));
205999ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
206099ebb4caSwyllys 		break;
206199ebb4caSwyllys 
206299ebb4caSwyllys 	case KMF_CERT_NOTAFTER:
2063300fdee2SAndy Fiddaman 		(void) ASN1_TIME_print(mem, X509_getm_notAfter(xcert));
206499ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
206599ebb4caSwyllys 		break;
206699ebb4caSwyllys 
206799ebb4caSwyllys 	case KMF_CERT_PUBKEY_DATA:
206899ebb4caSwyllys 		{
2069300fdee2SAndy Fiddaman 			RSA *rsa;
2070300fdee2SAndy Fiddaman 			DSA *dsa;
2071300fdee2SAndy Fiddaman 
207299ebb4caSwyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
207399ebb4caSwyllys 			if (pkey == NULL) {
207499ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
207599ebb4caSwyllys 				ret = KMF_ERR_ENCODING;
207699ebb4caSwyllys 				goto out;
207799ebb4caSwyllys 			}
207899ebb4caSwyllys 
2079300fdee2SAndy Fiddaman 			if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
208099ebb4caSwyllys 				(void) BIO_printf(mem,
208199ebb4caSwyllys 				    "RSA Public Key: (%d bit)\n",
2082300fdee2SAndy Fiddaman 				    RSA_bits(rsa));
2083300fdee2SAndy Fiddaman 				(void) RSA_print(mem, rsa, 0);
2084300fdee2SAndy Fiddaman 
2085300fdee2SAndy Fiddaman 			} else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
208699ebb4caSwyllys 				(void) BIO_printf(mem,
208799ebb4caSwyllys 				    "%12sDSA Public Key:\n", "");
2088300fdee2SAndy Fiddaman 				(void) DSA_print(mem, dsa, 0);
208999ebb4caSwyllys 			} else {
209099ebb4caSwyllys 				(void) BIO_printf(mem,
209199ebb4caSwyllys 				    "%12sUnknown Public Key:\n", "");
209299ebb4caSwyllys 			}
209399ebb4caSwyllys 			(void) BIO_printf(mem, "\n");
209499ebb4caSwyllys 			EVP_PKEY_free(pkey);
209599ebb4caSwyllys 		}
209699ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
209799ebb4caSwyllys 		break;
209899ebb4caSwyllys 	case KMF_CERT_SIGNATURE_ALG:
209999ebb4caSwyllys 	case KMF_CERT_PUBKEY_ALG:
2100300fdee2SAndy Fiddaman 		{
2101553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2102300fdee2SAndy Fiddaman 			ASN1_OBJECT *alg = NULL;
2103300fdee2SAndy Fiddaman #else
2104300fdee2SAndy Fiddaman 			const ASN1_OBJECT *alg = NULL;
2105300fdee2SAndy Fiddaman #endif
2106300fdee2SAndy Fiddaman 
210799ebb4caSwyllys 			if (flag == KMF_CERT_SIGNATURE_ALG) {
2108553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2109300fdee2SAndy Fiddaman 				alg = xcert->sig_alg->algorithm;
2110300fdee2SAndy Fiddaman #else
2111300fdee2SAndy Fiddaman 				const X509_ALGOR *sig_alg = NULL;
2112300fdee2SAndy Fiddaman 
2113300fdee2SAndy Fiddaman 				X509_get0_signature(NULL, &sig_alg, xcert);
2114300fdee2SAndy Fiddaman 				if (sig_alg != NULL)
2115300fdee2SAndy Fiddaman 					X509_ALGOR_get0(&alg, NULL, NULL,
2116300fdee2SAndy Fiddaman 					    sig_alg);
2117300fdee2SAndy Fiddaman #endif
211899ebb4caSwyllys 			} else {
2119553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2120300fdee2SAndy Fiddaman 				alg = xcert->cert_info->key->algor->algorithm;
2121300fdee2SAndy Fiddaman #else
2122300fdee2SAndy Fiddaman 				X509_PUBKEY *key = X509_get_X509_PUBKEY(xcert);
2123300fdee2SAndy Fiddaman 
2124300fdee2SAndy Fiddaman 				if (key != NULL)
2125300fdee2SAndy Fiddaman 					(void) X509_PUBKEY_get0_param(
2126300fdee2SAndy Fiddaman 					    (ASN1_OBJECT **)&alg, NULL, 0,
2127300fdee2SAndy Fiddaman 					    NULL, key);
2128300fdee2SAndy Fiddaman #endif
212999ebb4caSwyllys 			}
213099ebb4caSwyllys 
2131300fdee2SAndy Fiddaman 			if (alg == NULL)
2132300fdee2SAndy Fiddaman 				len = -1;
2133300fdee2SAndy Fiddaman 			else if ((len = i2a_ASN1_OBJECT(mem, alg)) > 0)
213499ebb4caSwyllys 				len = BIO_read(mem, resultStr,
213599ebb4caSwyllys 				    KMF_CERT_PRINTABLE_LEN);
213699ebb4caSwyllys 		}
213799ebb4caSwyllys 		break;
213899ebb4caSwyllys 
213999ebb4caSwyllys 	case KMF_CERT_EMAIL:
214099ebb4caSwyllys 		emlst = X509_get1_email(xcert);
214170f9559bSTheo Schlossnagle 		for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
214270f9559bSTheo Schlossnagle 			(void) BIO_printf(mem, "%s\n",
214370f9559bSTheo Schlossnagle 			    sk_OPENSSL_STRING_value(emlst, j));
214499ebb4caSwyllys 
214599ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
214699ebb4caSwyllys 		X509_email_free(emlst);
214799ebb4caSwyllys 		break;
214899ebb4caSwyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
214999ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
215099ebb4caSwyllys 	case KMF_X509_EXT_KEY_USAGE:
215199ebb4caSwyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
215299ebb4caSwyllys 	case KMF_X509_EXT_CERT_POLICIES:
215399ebb4caSwyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
215499ebb4caSwyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
215599ebb4caSwyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
215699ebb4caSwyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
215799ebb4caSwyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
215899ebb4caSwyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
215999ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
216099ebb4caSwyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
216199ebb4caSwyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
216299ebb4caSwyllys 	case KMF_X509_EXT_FRESHEST_CRL:
216399ebb4caSwyllys 		nid = ext2NID(flag);
216499ebb4caSwyllys 		if (nid == NID_undef) {
216599ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
216699ebb4caSwyllys 			goto out;
216799ebb4caSwyllys 		}
216899ebb4caSwyllys 
2169300fdee2SAndy Fiddaman 		ext_index = X509_get_ext_by_NID(xcert, nid, -1);
217099ebb4caSwyllys 		if (ext_index == -1) {
217199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
217299ebb4caSwyllys 
217399ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
217499ebb4caSwyllys 			goto out;
217599ebb4caSwyllys 		}
2176300fdee2SAndy Fiddaman 		ex = X509_get_ext(xcert, ext_index);
217799ebb4caSwyllys 
217899ebb4caSwyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
217999ebb4caSwyllys 
218099ebb4caSwyllys 		if (BIO_printf(mem, ": %s\n",
218130a5e8faSwyllys 		    X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
218299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
218399ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
218499ebb4caSwyllys 			goto out;
218599ebb4caSwyllys 		}
218699ebb4caSwyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
218799ebb4caSwyllys 			(void) BIO_printf(mem, "%*s", 4, "");
2188300fdee2SAndy Fiddaman 			(void) ASN1_STRING_print(mem,
2189300fdee2SAndy Fiddaman 			    X509_EXTENSION_get_data(ex));
219099ebb4caSwyllys 		}
219199ebb4caSwyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
219299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
219399ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
219499ebb4caSwyllys 			goto out;
219599ebb4caSwyllys 		}
219699ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
219799ebb4caSwyllys 	}
219899ebb4caSwyllys 	if (len <= 0) {
219999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
220099ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
220199ebb4caSwyllys 	}
220299ebb4caSwyllys 
220399ebb4caSwyllys out:
220499ebb4caSwyllys 	if (outbuf != NULL) {
220599ebb4caSwyllys 		free(outbuf);
220699ebb4caSwyllys 	}
220799ebb4caSwyllys 
220899ebb4caSwyllys 	if (xcert != NULL) {
220999ebb4caSwyllys 		X509_free(xcert);
221099ebb4caSwyllys 	}
221199ebb4caSwyllys 
221299ebb4caSwyllys 	if (mem != NULL) {
221399ebb4caSwyllys 		(void) BIO_free(mem);
221499ebb4caSwyllys 	}
221599ebb4caSwyllys 
221699ebb4caSwyllys 	return (ret);
221799ebb4caSwyllys }
221830a5e8faSwyllys 
221999ebb4caSwyllys KMF_RETURN
222030a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
222130a5e8faSwyllys     KMF_ATTRIBUTE *attrlist)
222299ebb4caSwyllys {
222399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
222430a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
222530a5e8faSwyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
222630a5e8faSwyllys 	KMF_KEY_HANDLE *key = NULL;
222730a5e8faSwyllys 	uint32_t numkeys = 1; /* 1 key only */
222830a5e8faSwyllys 	char *dirpath = NULL;
222930a5e8faSwyllys 	char *keyfile = NULL;
223030a5e8faSwyllys 	KMF_ATTRIBUTE new_attrlist[16];
223130a5e8faSwyllys 	int i = 0;
223299ebb4caSwyllys 
223399ebb4caSwyllys 	/*
223499ebb4caSwyllys 	 * This is really just a FindKey operation, reuse the
223599ebb4caSwyllys 	 * FindKey function.
223699ebb4caSwyllys 	 */
223730a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
223830a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
223930a5e8faSwyllys 	i++;
224099ebb4caSwyllys 
224130a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
224230a5e8faSwyllys 	    KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
224330a5e8faSwyllys 	i++;
224499ebb4caSwyllys 
224530a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
224630a5e8faSwyllys 	    KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
224730a5e8faSwyllys 	i++;
224830a5e8faSwyllys 
224930a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
225030a5e8faSwyllys 	if (key == NULL) {
225130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
225230a5e8faSwyllys 	} else {
225330a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
225430a5e8faSwyllys 		    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
225530a5e8faSwyllys 		i++;
225630a5e8faSwyllys 	}
225730a5e8faSwyllys 
225830a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
225930a5e8faSwyllys 	if (dirpath != NULL) {
226030a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
226130a5e8faSwyllys 		    KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
226230a5e8faSwyllys 		i++;
226330a5e8faSwyllys 	}
226430a5e8faSwyllys 
226530a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
226630a5e8faSwyllys 	if (keyfile == NULL)
226730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
226830a5e8faSwyllys 	else {
226930a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
227030a5e8faSwyllys 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
227130a5e8faSwyllys 		i++;
227230a5e8faSwyllys 	}
227330a5e8faSwyllys 
227430a5e8faSwyllys 	rv = OpenSSL_FindKey(handle, i, new_attrlist);
227599ebb4caSwyllys 	return (rv);
227699ebb4caSwyllys }
227799ebb4caSwyllys 
227899ebb4caSwyllys KMF_RETURN
227999ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
2280*4942e222SAndy Fiddaman     KMF_OID *AlgOID, KMF_DATA *ciphertext, KMF_DATA *output)
228199ebb4caSwyllys {
228299ebb4caSwyllys 	KMF_RETURN		ret = KMF_OK;
228399ebb4caSwyllys 	RSA *rsa = NULL;
228499ebb4caSwyllys 	unsigned int in_len = 0, out_len = 0;
228599ebb4caSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
228699ebb4caSwyllys 	uint8_t *in_data, *out_data;
228799ebb4caSwyllys 	int i, blocks;
228899ebb4caSwyllys 
228999ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
229099ebb4caSwyllys 	    ciphertext == NULL || output == NULL ||
229199ebb4caSwyllys 	    ciphertext->Data == NULL ||
229299ebb4caSwyllys 	    output->Data == NULL)
229399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
229499ebb4caSwyllys 
229599ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
229699ebb4caSwyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
229799ebb4caSwyllys 		modulus_len = RSA_size(rsa);
229899ebb4caSwyllys 	} else {
229999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
230099ebb4caSwyllys 	}
230199ebb4caSwyllys 
230299ebb4caSwyllys 	blocks = ciphertext->Length/modulus_len;
230399ebb4caSwyllys 	out_data = output->Data;
230499ebb4caSwyllys 	in_data = ciphertext->Data;
230599ebb4caSwyllys 	out_len = modulus_len - 11;
230699ebb4caSwyllys 	in_len = modulus_len;
230799ebb4caSwyllys 
230899ebb4caSwyllys 	for (i = 0; i < blocks; i++) {
230999ebb4caSwyllys 		out_len  = RSA_private_decrypt(in_len,
231099ebb4caSwyllys 		    in_data, out_data, rsa, RSA_PKCS1_PADDING);
231199ebb4caSwyllys 
231299ebb4caSwyllys 		if (out_len == 0) {
231399ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
231499ebb4caSwyllys 			goto cleanup;
231599ebb4caSwyllys 		}
231699ebb4caSwyllys 
231799ebb4caSwyllys 		out_data += out_len;
231899ebb4caSwyllys 		total_decrypted += out_len;
231999ebb4caSwyllys 		in_data += in_len;
232099ebb4caSwyllys 	}
232199ebb4caSwyllys 
232299ebb4caSwyllys 	output->Length = total_decrypted;
232399ebb4caSwyllys 
232499ebb4caSwyllys cleanup:
232599ebb4caSwyllys 	RSA_free(rsa);
232699ebb4caSwyllys 	if (ret != KMF_OK)
232799ebb4caSwyllys 		output->Length = 0;
232899ebb4caSwyllys 
232999ebb4caSwyllys 	return (ret);
233099ebb4caSwyllys 
233199ebb4caSwyllys }
233299ebb4caSwyllys 
233399ebb4caSwyllys /*
233499ebb4caSwyllys  *  This function will create a certid from issuer_cert and user_cert.
233599ebb4caSwyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
233699ebb4caSwyllys  *  certid memory after use.
233799ebb4caSwyllys  */
233899ebb4caSwyllys static KMF_RETURN
233999ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
234099ebb4caSwyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
234199ebb4caSwyllys {
234299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
234399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
234499ebb4caSwyllys 	X509   *issuer = NULL;
234599ebb4caSwyllys 	X509   *cert = NULL;
234699ebb4caSwyllys 	unsigned char *ptmp;
234799ebb4caSwyllys 
234899ebb4caSwyllys 	if (issuer_cert == NULL || user_cert == NULL) {
234999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
235099ebb4caSwyllys 	}
235199ebb4caSwyllys 
235299ebb4caSwyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
235399ebb4caSwyllys 	ptmp = issuer_cert->Data;
235499ebb4caSwyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
235599ebb4caSwyllys 	    issuer_cert->Length);
235699ebb4caSwyllys 	if (issuer == NULL) {
235799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
235899ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
235999ebb4caSwyllys 		goto end;
236099ebb4caSwyllys 	}
236199ebb4caSwyllys 
236299ebb4caSwyllys 	/* convert the DER-encoded user cert to an internal X509 */
236399ebb4caSwyllys 	ptmp = user_cert->Data;
236499ebb4caSwyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
236599ebb4caSwyllys 	    user_cert->Length);
236699ebb4caSwyllys 	if (cert == NULL) {
236799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
236899ebb4caSwyllys 
236999ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
237099ebb4caSwyllys 		goto end;
237199ebb4caSwyllys 	}
237299ebb4caSwyllys 
237399ebb4caSwyllys 	/* create a CERTID */
237499ebb4caSwyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
237599ebb4caSwyllys 	if (*certid == NULL) {
237699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
237799ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
237899ebb4caSwyllys 		goto end;
237999ebb4caSwyllys 	}
238099ebb4caSwyllys 
238199ebb4caSwyllys end:
238299ebb4caSwyllys 	if (issuer != NULL) {
238399ebb4caSwyllys 		X509_free(issuer);
238499ebb4caSwyllys 	}
238599ebb4caSwyllys 
238699ebb4caSwyllys 	if (cert != NULL) {
238799ebb4caSwyllys 		X509_free(cert);
238899ebb4caSwyllys 	}
238999ebb4caSwyllys 
239099ebb4caSwyllys 	return (ret);
239199ebb4caSwyllys }
239299ebb4caSwyllys 
239399ebb4caSwyllys KMF_RETURN
239430a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
239530a5e8faSwyllys     int numattr, KMF_ATTRIBUTE *attrlist)
239699ebb4caSwyllys {
239799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
239899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
239999ebb4caSwyllys 	OCSP_CERTID *id = NULL;
240099ebb4caSwyllys 	OCSP_REQUEST *req = NULL;
240199ebb4caSwyllys 	BIO *derbio = NULL;
240230a5e8faSwyllys 	char *reqfile;
240330a5e8faSwyllys 	KMF_DATA *issuer_cert;
240430a5e8faSwyllys 	KMF_DATA *user_cert;
240599ebb4caSwyllys 
240630a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
240730a5e8faSwyllys 	    attrlist, numattr);
240830a5e8faSwyllys 	if (user_cert == NULL)
240999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
241099ebb4caSwyllys 
241130a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
241230a5e8faSwyllys 	    attrlist, numattr);
241330a5e8faSwyllys 	if (issuer_cert == NULL)
241430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
241530a5e8faSwyllys 
241630a5e8faSwyllys 	reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
241730a5e8faSwyllys 	    attrlist, numattr);
241830a5e8faSwyllys 	if (reqfile == NULL)
241930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
242030a5e8faSwyllys 
242130a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
242299ebb4caSwyllys 	if (ret != KMF_OK) {
242399ebb4caSwyllys 		return (ret);
242499ebb4caSwyllys 	}
242599ebb4caSwyllys 
242699ebb4caSwyllys 	/* Create an OCSP request */
242799ebb4caSwyllys 	req = OCSP_REQUEST_new();
242899ebb4caSwyllys 	if (req == NULL) {
242999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
243099ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
243199ebb4caSwyllys 		goto end;
243299ebb4caSwyllys 	}
243399ebb4caSwyllys 
243499ebb4caSwyllys 	if (!OCSP_request_add0_id(req, id)) {
243599ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
243699ebb4caSwyllys 		goto end;
243799ebb4caSwyllys 	}
243899ebb4caSwyllys 
243999ebb4caSwyllys 	/* Write the request to the output file with DER encoding */
244099ebb4caSwyllys 	derbio = BIO_new_file(reqfile, "wb");
244199ebb4caSwyllys 	if (!derbio) {
244299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
244399ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
244499ebb4caSwyllys 		goto end;
244599ebb4caSwyllys 	}
244699ebb4caSwyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
244799ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
244899ebb4caSwyllys 	}
244999ebb4caSwyllys 
245099ebb4caSwyllys end:
245199ebb4caSwyllys 	/*
2452e65e5c2dSWyllys Ingersoll 	 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2453a2d4930dSDan OpenSolaris Anderson 	 * will also deallocate certid's space.
245499ebb4caSwyllys 	 */
245599ebb4caSwyllys 	if (req != NULL) {
245699ebb4caSwyllys 		OCSP_REQUEST_free(req);
245799ebb4caSwyllys 	}
245899ebb4caSwyllys 
245999ebb4caSwyllys 	if (derbio != NULL) {
246099ebb4caSwyllys 		(void) BIO_free(derbio);
246199ebb4caSwyllys 	}
246299ebb4caSwyllys 
246399ebb4caSwyllys 	return (ret);
246499ebb4caSwyllys }
246599ebb4caSwyllys 
246699ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */
2467300fdee2SAndy Fiddaman static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_BASICRESP *bs)
246899ebb4caSwyllys {
246999ebb4caSwyllys 	int i;
247099ebb4caSwyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
2471300fdee2SAndy Fiddaman 	const ASN1_OCTET_STRING *pid;
247299ebb4caSwyllys 
2473553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2474300fdee2SAndy Fiddaman 	OCSP_RESPID *id = bs->tbsResponseData->responderId;
2475300fdee2SAndy Fiddaman 
247699ebb4caSwyllys 	if (id->type == V_OCSP_RESPID_NAME)
247799ebb4caSwyllys 		return (X509_find_by_subject(certs, id->value.byName));
247899ebb4caSwyllys 
2479300fdee2SAndy Fiddaman 	pid = id->value.byKey;
2480300fdee2SAndy Fiddaman #else
2481300fdee2SAndy Fiddaman 	const X509_NAME *pname;
2482300fdee2SAndy Fiddaman 
2483300fdee2SAndy Fiddaman 	if (OCSP_resp_get0_id(bs, &pid, &pname) == 0)
2484300fdee2SAndy Fiddaman 		return (NULL);
2485300fdee2SAndy Fiddaman 
2486300fdee2SAndy Fiddaman 	if (pname != NULL)
2487300fdee2SAndy Fiddaman 		return (X509_find_by_subject(certs, (X509_NAME *)pname));
2488300fdee2SAndy Fiddaman #endif
2489300fdee2SAndy Fiddaman 
249099ebb4caSwyllys 	/* Lookup by key hash */
249199ebb4caSwyllys 
249299ebb4caSwyllys 	/* If key hash isn't SHA1 length then forget it */
2493300fdee2SAndy Fiddaman 	if (pid->length != SHA_DIGEST_LENGTH)
249499ebb4caSwyllys 		return (NULL);
249599ebb4caSwyllys 
2496300fdee2SAndy Fiddaman 	keyhash = pid->data;
249799ebb4caSwyllys 	/* Calculate hash of each key and compare */
249899ebb4caSwyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
249999ebb4caSwyllys 		X509 *x = sk_X509_value(certs, i);
25005b3e1433Swyllys 		/* Use pubkey_digest to get the key ID value */
250199ebb4caSwyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
250299ebb4caSwyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
250399ebb4caSwyllys 			return (x);
250499ebb4caSwyllys 	}
250599ebb4caSwyllys 	return (NULL);
250699ebb4caSwyllys }
250799ebb4caSwyllys 
250899ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */
250999ebb4caSwyllys static int
251099ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
251199ebb4caSwyllys     X509_STORE *st, unsigned long flags)
251299ebb4caSwyllys {
251399ebb4caSwyllys 	X509 *signer;
2514300fdee2SAndy Fiddaman 	if ((signer = ocsp_find_signer_sk(certs, bs)))	{
251599ebb4caSwyllys 		*psigner = signer;
251699ebb4caSwyllys 		return (2);
251799ebb4caSwyllys 	}
2518300fdee2SAndy Fiddaman 
251999ebb4caSwyllys 	if (!(flags & OCSP_NOINTERN) &&
2520300fdee2SAndy Fiddaman 	    (signer = ocsp_find_signer_sk(
2521300fdee2SAndy Fiddaman 	    (STACK_OF(X509) *)OCSP_resp_get0_certs(bs), bs))) {
252299ebb4caSwyllys 		*psigner = signer;
252399ebb4caSwyllys 		return (1);
252499ebb4caSwyllys 	}
252599ebb4caSwyllys 	/* Maybe lookup from store if by subject name */
252699ebb4caSwyllys 
252799ebb4caSwyllys 	*psigner = NULL;
252899ebb4caSwyllys 	return (0);
252999ebb4caSwyllys }
253099ebb4caSwyllys 
253199ebb4caSwyllys /*
253299ebb4caSwyllys  * This function will verify the signature of a basic response, using
253399ebb4caSwyllys  * the public key from the OCSP responder certificate.
253499ebb4caSwyllys  */
253599ebb4caSwyllys static KMF_RETURN
253699ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
253799ebb4caSwyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
253899ebb4caSwyllys {
253999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
254099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
254199ebb4caSwyllys 	STACK_OF(X509) *cert_stack = NULL;
254299ebb4caSwyllys 	X509 *signer = NULL;
254399ebb4caSwyllys 	X509 *issuer = NULL;
2544553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
254599ebb4caSwyllys 	EVP_PKEY *skey = NULL;
2546300fdee2SAndy Fiddaman #else
2547300fdee2SAndy Fiddaman 	STACK_OF(X509) *cert_stack2 = NULL;
2548300fdee2SAndy Fiddaman #endif
254999ebb4caSwyllys 	unsigned char *ptmp;
255099ebb4caSwyllys 
255199ebb4caSwyllys 	if (bs == NULL || issuer_cert == NULL)
255299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
255399ebb4caSwyllys 
255499ebb4caSwyllys 	/*
255599ebb4caSwyllys 	 * Find the certificate that signed the basic response.
255699ebb4caSwyllys 	 *
255799ebb4caSwyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
255899ebb4caSwyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
255999ebb4caSwyllys 	 * If we still do not find a signer, we will look for it from the
256099ebb4caSwyllys 	 * certificate list came with the response file.
256199ebb4caSwyllys 	 */
256299ebb4caSwyllys 	if (signer_cert != NULL) {
256399ebb4caSwyllys 		ptmp = signer_cert->Data;
256499ebb4caSwyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
256599ebb4caSwyllys 		    signer_cert->Length);
256699ebb4caSwyllys 		if (signer == NULL) {
256799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
256899ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
256999ebb4caSwyllys 			goto end;
257099ebb4caSwyllys 		}
257199ebb4caSwyllys 	} else {
257299ebb4caSwyllys 		/*
257399ebb4caSwyllys 		 * Convert the issuer cert into X509 and push it into a
257499ebb4caSwyllys 		 * stack to be used by ocsp_find_signer().
257599ebb4caSwyllys 		 */
257699ebb4caSwyllys 		ptmp = issuer_cert->Data;
257799ebb4caSwyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
257899ebb4caSwyllys 		    issuer_cert->Length);
257999ebb4caSwyllys 		if (issuer == NULL) {
258099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
258199ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
258299ebb4caSwyllys 			goto end;
258399ebb4caSwyllys 		}
258499ebb4caSwyllys 
258599ebb4caSwyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
258699ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
258799ebb4caSwyllys 			goto end;
258899ebb4caSwyllys 		}
258999ebb4caSwyllys 
2590f810c7e5SToomas Soome 		if (sk_X509_push(cert_stack, issuer) == 0) {
259199ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
259299ebb4caSwyllys 			goto end;
259399ebb4caSwyllys 		}
259499ebb4caSwyllys 
259599ebb4caSwyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
259699ebb4caSwyllys 		if (!ret) {
259799ebb4caSwyllys 			/* can not find the signer */
259899ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
259999ebb4caSwyllys 			goto end;
260099ebb4caSwyllys 		}
260199ebb4caSwyllys 	}
260299ebb4caSwyllys 
260399ebb4caSwyllys 	/* Verify the signature of the response */
2604553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
260599ebb4caSwyllys 	skey = X509_get_pubkey(signer);
260699ebb4caSwyllys 	if (skey == NULL) {
260799ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
260899ebb4caSwyllys 		goto end;
260999ebb4caSwyllys 	}
261099ebb4caSwyllys 
261199ebb4caSwyllys 	ret = OCSP_BASICRESP_verify(bs, skey, 0);
2612300fdee2SAndy Fiddaman #else
2613300fdee2SAndy Fiddaman 	/*
2614300fdee2SAndy Fiddaman 	 * Technique based on
2615300fdee2SAndy Fiddaman 	 * https://mta.openssl.org/pipermail/openssl-users/
2616300fdee2SAndy Fiddaman 	 *	2017-October/006814.html
2617300fdee2SAndy Fiddaman 	 */
2618300fdee2SAndy Fiddaman 	if ((cert_stack2 = sk_X509_new_null()) == NULL) {
2619300fdee2SAndy Fiddaman 		ret = KMF_ERR_INTERNAL;
2620300fdee2SAndy Fiddaman 		goto end;
2621300fdee2SAndy Fiddaman 	}
2622300fdee2SAndy Fiddaman 
2623*4942e222SAndy Fiddaman 	if (sk_X509_push(cert_stack2, signer) == 0) {
2624300fdee2SAndy Fiddaman 		ret = KMF_ERR_INTERNAL;
2625300fdee2SAndy Fiddaman 		goto end;
2626300fdee2SAndy Fiddaman 	}
2627300fdee2SAndy Fiddaman 
2628300fdee2SAndy Fiddaman 	ret = OCSP_basic_verify(bs, cert_stack2, NULL, OCSP_NOVERIFY);
2629300fdee2SAndy Fiddaman #endif
2630300fdee2SAndy Fiddaman 
263199ebb4caSwyllys 	if (ret == 0) {
263299ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
263399ebb4caSwyllys 		goto end;
263499ebb4caSwyllys 	}
263599ebb4caSwyllys 
263699ebb4caSwyllys end:
263799ebb4caSwyllys 	if (issuer != NULL) {
263899ebb4caSwyllys 		X509_free(issuer);
263999ebb4caSwyllys 	}
264099ebb4caSwyllys 
264199ebb4caSwyllys 	if (signer != NULL) {
264299ebb4caSwyllys 		X509_free(signer);
264399ebb4caSwyllys 	}
264499ebb4caSwyllys 
2645553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
264699ebb4caSwyllys 	if (skey != NULL) {
264799ebb4caSwyllys 		EVP_PKEY_free(skey);
264899ebb4caSwyllys 	}
2649300fdee2SAndy Fiddaman #else
2650300fdee2SAndy Fiddaman 	if (cert_stack2 != NULL) {
2651300fdee2SAndy Fiddaman 		sk_X509_free(cert_stack2);
2652300fdee2SAndy Fiddaman 	}
2653300fdee2SAndy Fiddaman #endif
265499ebb4caSwyllys 
265599ebb4caSwyllys 	if (cert_stack != NULL) {
265699ebb4caSwyllys 		sk_X509_free(cert_stack);
265799ebb4caSwyllys 	}
265899ebb4caSwyllys 
265999ebb4caSwyllys 	return (ret);
266099ebb4caSwyllys }
266199ebb4caSwyllys 
266299ebb4caSwyllys KMF_RETURN
2663*4942e222SAndy Fiddaman OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle, int numattr,
2664*4942e222SAndy Fiddaman     KMF_ATTRIBUTE *attrlist)
266599ebb4caSwyllys {
266699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
266799ebb4caSwyllys 	BIO *derbio = NULL;
266899ebb4caSwyllys 	OCSP_RESPONSE *resp = NULL;
266999ebb4caSwyllys 	OCSP_BASICRESP *bs = NULL;
267099ebb4caSwyllys 	OCSP_CERTID *id = NULL;
267199ebb4caSwyllys 	OCSP_SINGLERESP *single = NULL;
267299ebb4caSwyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
267399ebb4caSwyllys 	int index, status, reason;
267430a5e8faSwyllys 	KMF_DATA *issuer_cert;
267530a5e8faSwyllys 	KMF_DATA *user_cert;
267630a5e8faSwyllys 	KMF_DATA *signer_cert;
267730a5e8faSwyllys 	KMF_DATA *response;
267830a5e8faSwyllys 	int *response_reason, *response_status, *cert_status;
267930a5e8faSwyllys 	boolean_t ignore_response_sign = B_FALSE;	/* default is FALSE */
268030a5e8faSwyllys 	uint32_t response_lifetime;
268199ebb4caSwyllys 
268230a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
268330a5e8faSwyllys 	    attrlist, numattr);
268430a5e8faSwyllys 	if (issuer_cert == NULL)
268599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
268699ebb4caSwyllys 
268730a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
268830a5e8faSwyllys 	    attrlist, numattr);
268930a5e8faSwyllys 	if (user_cert == NULL)
269099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
269130a5e8faSwyllys 
269230a5e8faSwyllys 	response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
269330a5e8faSwyllys 	    attrlist, numattr);
269430a5e8faSwyllys 	if (response == NULL)
269530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
269630a5e8faSwyllys 
269730a5e8faSwyllys 	response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
269830a5e8faSwyllys 	    attrlist, numattr);
269930a5e8faSwyllys 	if (response_status == NULL)
270030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
270130a5e8faSwyllys 
270230a5e8faSwyllys 	response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
270330a5e8faSwyllys 	    attrlist, numattr);
270430a5e8faSwyllys 	if (response_reason == NULL)
270530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
270630a5e8faSwyllys 
270730a5e8faSwyllys 	cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
270830a5e8faSwyllys 	    attrlist, numattr);
270930a5e8faSwyllys 	if (cert_status == NULL)
271030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
271199ebb4caSwyllys 
271299ebb4caSwyllys 	/* Read in the response */
271330a5e8faSwyllys 	derbio = BIO_new_mem_buf(response->Data, response->Length);
271499ebb4caSwyllys 	if (!derbio) {
271599ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
271699ebb4caSwyllys 		return (ret);
271799ebb4caSwyllys 	}
271899ebb4caSwyllys 
271999ebb4caSwyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
272099ebb4caSwyllys 	if (resp == NULL) {
272199ebb4caSwyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
272299ebb4caSwyllys 		goto end;
272399ebb4caSwyllys 	}
272499ebb4caSwyllys 
272599ebb4caSwyllys 	/* Check the response status */
272699ebb4caSwyllys 	status = OCSP_response_status(resp);
272730a5e8faSwyllys 	*response_status = status;
272899ebb4caSwyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
272999ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
273099ebb4caSwyllys 		goto end;
273199ebb4caSwyllys 	}
273299ebb4caSwyllys 
273399ebb4caSwyllys #ifdef DEBUG
273499ebb4caSwyllys 	printf("Successfully checked the response file status.\n");
273599ebb4caSwyllys #endif /* DEBUG */
273699ebb4caSwyllys 
273799ebb4caSwyllys 	/* Extract basic response */
273899ebb4caSwyllys 	bs = OCSP_response_get1_basic(resp);
273999ebb4caSwyllys 	if (bs == NULL) {
274099ebb4caSwyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
274199ebb4caSwyllys 		goto end;
274299ebb4caSwyllys 	}
274399ebb4caSwyllys 
274499ebb4caSwyllys #ifdef DEBUG
274599ebb4caSwyllys 	printf("Successfully retrieved the basic response.\n");
274699ebb4caSwyllys #endif /* DEBUG */
274799ebb4caSwyllys 
274899ebb4caSwyllys 	/* Check the basic response signature if required */
274930a5e8faSwyllys 	ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
275030a5e8faSwyllys 	    (void *)&ignore_response_sign, NULL);
275130a5e8faSwyllys 	if (ret != KMF_OK)
275230a5e8faSwyllys 		ret = KMF_OK;
275330a5e8faSwyllys 
275430a5e8faSwyllys 	signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
275530a5e8faSwyllys 	    attrlist, numattr);
275630a5e8faSwyllys 
275730a5e8faSwyllys 	if (ignore_response_sign == B_FALSE) {
275899ebb4caSwyllys 		ret = check_response_signature(handle, bs,
275930a5e8faSwyllys 		    signer_cert, issuer_cert);
276099ebb4caSwyllys 		if (ret != KMF_OK)
276199ebb4caSwyllys 			goto end;
276299ebb4caSwyllys 	}
276399ebb4caSwyllys 
276499ebb4caSwyllys #ifdef DEBUG
276599ebb4caSwyllys 	printf("Successfully verified the response signature.\n");
276699ebb4caSwyllys #endif /* DEBUG */
276799ebb4caSwyllys 
276899ebb4caSwyllys 	/* Create a certid for the certificate in question */
276930a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
277099ebb4caSwyllys 	if (ret != KMF_OK) {
277199ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
277299ebb4caSwyllys 		goto end;
277399ebb4caSwyllys 	}
277499ebb4caSwyllys 
277599ebb4caSwyllys #ifdef DEBUG
277699ebb4caSwyllys 	printf("successfully created a certid for the cert.\n");
277799ebb4caSwyllys #endif /* DEBUG */
277899ebb4caSwyllys 
277999ebb4caSwyllys 	/* Find the index of the single response for the certid */
278099ebb4caSwyllys 	index = OCSP_resp_find(bs, id, -1);
278199ebb4caSwyllys 	if (index < 0) {
278299ebb4caSwyllys 		/* cound not find this certificate in the response */
278399ebb4caSwyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
278499ebb4caSwyllys 		goto end;
278599ebb4caSwyllys 	}
278699ebb4caSwyllys 
278799ebb4caSwyllys #ifdef DEBUG
278899ebb4caSwyllys 	printf("Successfully found the single response index for the cert.\n");
278999ebb4caSwyllys #endif /* DEBUG */
279099ebb4caSwyllys 
279199ebb4caSwyllys 	/* Retrieve the single response and get the cert status */
279299ebb4caSwyllys 	single = OCSP_resp_get0(bs, index);
279399ebb4caSwyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
279499ebb4caSwyllys 	    &nextupd);
279599ebb4caSwyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
279630a5e8faSwyllys 		*cert_status = OCSP_GOOD;
279799ebb4caSwyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
279830a5e8faSwyllys 		*cert_status = OCSP_UNKNOWN;
279999ebb4caSwyllys 	} else { /* revoked */
280030a5e8faSwyllys 		*cert_status = OCSP_REVOKED;
280130a5e8faSwyllys 		*response_reason = reason;
280299ebb4caSwyllys 	}
280399ebb4caSwyllys 	ret = KMF_OK;
280499ebb4caSwyllys 
280530a5e8faSwyllys 	/* resp. time is optional, so we don't care about the return code. */
280630a5e8faSwyllys 	(void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
280730a5e8faSwyllys 	    (void *)&response_lifetime, NULL);
280830a5e8faSwyllys 
280999ebb4caSwyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
281030a5e8faSwyllys 	    response_lifetime)) {
281199ebb4caSwyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
281299ebb4caSwyllys 		goto end;
281399ebb4caSwyllys 	}
281499ebb4caSwyllys 
281599ebb4caSwyllys #ifdef DEBUG
281699ebb4caSwyllys 	printf("Successfully verify the time.\n");
281799ebb4caSwyllys #endif /* DEBUG */
281899ebb4caSwyllys 
281999ebb4caSwyllys end:
282099ebb4caSwyllys 	if (derbio != NULL)
282199ebb4caSwyllys 		(void) BIO_free(derbio);
282299ebb4caSwyllys 
282399ebb4caSwyllys 	if (resp != NULL)
282499ebb4caSwyllys 		OCSP_RESPONSE_free(resp);
282599ebb4caSwyllys 
282699ebb4caSwyllys 	if (bs != NULL)
282799ebb4caSwyllys 		OCSP_BASICRESP_free(bs);
282899ebb4caSwyllys 
282999ebb4caSwyllys 	if (id != NULL)
283099ebb4caSwyllys 		OCSP_CERTID_free(id);
283199ebb4caSwyllys 
283299ebb4caSwyllys 	return (ret);
283399ebb4caSwyllys }
283499ebb4caSwyllys 
283599ebb4caSwyllys static KMF_RETURN
2836*4942e222SAndy Fiddaman fetch_key(KMF_HANDLE_T handle, char *path, KMF_KEY_CLASS keyclass,
2837*4942e222SAndy Fiddaman     KMF_KEY_HANDLE *key)
283899ebb4caSwyllys {
283999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
284030a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
284199ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
284299ebb4caSwyllys 
284399ebb4caSwyllys 	if (keyclass == KMF_ASYM_PRI ||
284499ebb4caSwyllys 	    keyclass == KMF_ASYM_PUB) {
284599ebb4caSwyllys 		pkey = openssl_load_key(handle, path);
284699ebb4caSwyllys 		if (pkey == NULL) {
284799ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
284899ebb4caSwyllys 		}
284999ebb4caSwyllys 		if (key != NULL) {
2850300fdee2SAndy Fiddaman 			if (EVP_PKEY_get0_RSA(pkey) != NULL)
285199ebb4caSwyllys 				key->keyalg = KMF_RSA;
2852300fdee2SAndy Fiddaman 			else if (EVP_PKEY_get0_DSA(pkey) != NULL)
285399ebb4caSwyllys 				key->keyalg = KMF_DSA;
285499ebb4caSwyllys 
285599ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
285699ebb4caSwyllys 			key->keyclass = keyclass;
285799ebb4caSwyllys 			key->keyp = (void *)pkey;
285899ebb4caSwyllys 			key->israw = FALSE;
28595b3e1433Swyllys 			if (path != NULL &&
28605b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
28615b3e1433Swyllys 				EVP_PKEY_free(pkey);
28625b3e1433Swyllys 				return (KMF_ERR_MEMORY);
28635b3e1433Swyllys 			}
286499ebb4caSwyllys 		} else {
286599ebb4caSwyllys 			EVP_PKEY_free(pkey);
286699ebb4caSwyllys 			pkey = NULL;
286799ebb4caSwyllys 		}
286899ebb4caSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
286999ebb4caSwyllys 		KMF_ENCODE_FORMAT fmt;
287099ebb4caSwyllys 		/*
287199ebb4caSwyllys 		 * If the file is a recognized format,
287299ebb4caSwyllys 		 * then it is NOT a symmetric key.
287399ebb4caSwyllys 		 */
287430a5e8faSwyllys 		rv = kmf_get_file_format(path, &fmt);
287599ebb4caSwyllys 		if (rv == KMF_OK || fmt != 0) {
287699ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
287799ebb4caSwyllys 		} else if (rv == KMF_ERR_ENCODING) {
287899ebb4caSwyllys 			/*
287999ebb4caSwyllys 			 * If we don't know the encoding,
288099ebb4caSwyllys 			 * it is probably  a symmetric key.
288199ebb4caSwyllys 			 */
288299ebb4caSwyllys 			rv = KMF_OK;
288330a5e8faSwyllys 		} else if (rv == KMF_ERR_OPEN_FILE) {
288430a5e8faSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
288599ebb4caSwyllys 		}
288699ebb4caSwyllys 
288799ebb4caSwyllys 		if (key != NULL) {
288899ebb4caSwyllys 			KMF_DATA keyvalue;
288999ebb4caSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
289099ebb4caSwyllys 			if (rkey == NULL) {
289199ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
289299ebb4caSwyllys 				goto out;
289399ebb4caSwyllys 			}
289499ebb4caSwyllys 
289599ebb4caSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
289630a5e8faSwyllys 			rv = kmf_read_input_file(handle, path, &keyvalue);
289799ebb4caSwyllys 			if (rv != KMF_OK)
289899ebb4caSwyllys 				goto out;
289999ebb4caSwyllys 
290099ebb4caSwyllys 			rkey->keydata.len = keyvalue.Length;
290199ebb4caSwyllys 			rkey->keydata.val = keyvalue.Data;
290299ebb4caSwyllys 
290399ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
290499ebb4caSwyllys 			key->keyclass = keyclass;
290599ebb4caSwyllys 			key->israw = TRUE;
290699ebb4caSwyllys 			key->keyp = (void *)rkey;
29075b3e1433Swyllys 			if (path != NULL &&
29085b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
29095b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
29105b3e1433Swyllys 			}
291199ebb4caSwyllys 		}
291299ebb4caSwyllys 	}
291399ebb4caSwyllys out:
291499ebb4caSwyllys 	if (rv != KMF_OK) {
291599ebb4caSwyllys 		if (rkey != NULL) {
291630a5e8faSwyllys 			kmf_free_raw_sym_key(rkey);
291799ebb4caSwyllys 		}
291899ebb4caSwyllys 		if (pkey != NULL)
291999ebb4caSwyllys 			EVP_PKEY_free(pkey);
292099ebb4caSwyllys 
292199ebb4caSwyllys 		if (key != NULL) {
292299ebb4caSwyllys 			key->keyalg = KMF_KEYALG_NONE;
292399ebb4caSwyllys 			key->keyclass = KMF_KEYCLASS_NONE;
292499ebb4caSwyllys 			key->keyp = NULL;
292599ebb4caSwyllys 		}
292699ebb4caSwyllys 	}
292799ebb4caSwyllys 
292899ebb4caSwyllys 	return (rv);
292999ebb4caSwyllys }
293099ebb4caSwyllys 
293199ebb4caSwyllys KMF_RETURN
2932*4942e222SAndy Fiddaman OpenSSL_FindKey(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
293399ebb4caSwyllys {
293499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
293599ebb4caSwyllys 	char *fullpath = NULL;
2936f482c776Swyllys 	uint32_t maxkeys;
293730a5e8faSwyllys 	KMF_KEY_HANDLE *key;
293830a5e8faSwyllys 	uint32_t *numkeys;
293930a5e8faSwyllys 	KMF_KEY_CLASS keyclass;
294030a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
294130a5e8faSwyllys 	char *dirpath;
294230a5e8faSwyllys 	char *keyfile;
294399ebb4caSwyllys 
294430a5e8faSwyllys 	if (handle == NULL)
294599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
294699ebb4caSwyllys 
294730a5e8faSwyllys 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
294830a5e8faSwyllys 	if (numkeys == NULL)
294930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
295030a5e8faSwyllys 
295130a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
295230a5e8faSwyllys 	    (void *)&keyclass, NULL);
295330a5e8faSwyllys 	if (rv != KMF_OK)
295430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
295530a5e8faSwyllys 
295630a5e8faSwyllys 	if (keyclass != KMF_ASYM_PUB &&
295730a5e8faSwyllys 	    keyclass != KMF_ASYM_PRI &&
295830a5e8faSwyllys 	    keyclass != KMF_SYMMETRIC)
295999ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
296099ebb4caSwyllys 
296130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
296230a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
296330a5e8faSwyllys 
296430a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
296599ebb4caSwyllys 
296699ebb4caSwyllys 	if (fullpath == NULL)
296799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
296899ebb4caSwyllys 
2969f482c776Swyllys 	maxkeys = *numkeys;
2970f482c776Swyllys 	if (maxkeys == 0)
2971f482c776Swyllys 		maxkeys = 0xFFFFFFFF;
297299ebb4caSwyllys 	*numkeys = 0;
297399ebb4caSwyllys 
297430a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
297530a5e8faSwyllys 	/* it is okay to have "keys" contains NULL */
297630a5e8faSwyllys 
297730a5e8faSwyllys 	/*
297830a5e8faSwyllys 	 * The caller may want a list of the raw key data as well.
297930a5e8faSwyllys 	 * Useful for importing keys from a file into other keystores.
298030a5e8faSwyllys 	 */
298130a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
298230a5e8faSwyllys 
298399ebb4caSwyllys 	if (isdir(fullpath)) {
298499ebb4caSwyllys 		DIR *dirp;
298599ebb4caSwyllys 		struct dirent *dp;
298699ebb4caSwyllys 		int n = 0;
298799ebb4caSwyllys 
298899ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
298999ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
299099ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
299199ebb4caSwyllys 		}
299299ebb4caSwyllys 		rewinddir(dirp);
2993f482c776Swyllys 		while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
299499ebb4caSwyllys 			if (strcmp(dp->d_name, ".") &&
299599ebb4caSwyllys 			    strcmp(dp->d_name, "..")) {
299699ebb4caSwyllys 				char *fname;
299799ebb4caSwyllys 
299899ebb4caSwyllys 				fname = get_fullpath(fullpath,
299999ebb4caSwyllys 				    (char *)&dp->d_name);
300099ebb4caSwyllys 
300199ebb4caSwyllys 				rv = fetch_key(handle, fname,
300230a5e8faSwyllys 				    keyclass, key ? &key[n] : NULL);
300399ebb4caSwyllys 
300430a5e8faSwyllys 				if (rv == KMF_OK) {
300530a5e8faSwyllys 					if (key != NULL && rawkey != NULL)
300630a5e8faSwyllys 						rv = convertToRawKey(
300730a5e8faSwyllys 						    key[n].keyp, &rawkey[n]);
300899ebb4caSwyllys 					n++;
300930a5e8faSwyllys 				}
301099ebb4caSwyllys 
301199ebb4caSwyllys 				if (rv != KMF_OK || key == NULL)
301299ebb4caSwyllys 					free(fname);
301399ebb4caSwyllys 			}
301499ebb4caSwyllys 		}
301599ebb4caSwyllys 		(void) closedir(dirp);
301699ebb4caSwyllys 		free(fullpath);
301799ebb4caSwyllys 		(*numkeys) = n;
301899ebb4caSwyllys 	} else {
301930a5e8faSwyllys 		rv = fetch_key(handle, fullpath, keyclass, key);
302099ebb4caSwyllys 		if (rv == KMF_OK)
302199ebb4caSwyllys 			(*numkeys) = 1;
302299ebb4caSwyllys 
302399ebb4caSwyllys 		if (rv != KMF_OK || key == NULL)
302499ebb4caSwyllys 			free(fullpath);
302530a5e8faSwyllys 
302630a5e8faSwyllys 		if (rv == KMF_OK && key != NULL && rawkey != NULL) {
302730a5e8faSwyllys 			rv = convertToRawKey(key->keyp, rawkey);
302830a5e8faSwyllys 		}
302999ebb4caSwyllys 	}
303099ebb4caSwyllys 
3031f482c776Swyllys 	if (rv == KMF_OK && (*numkeys) == 0)
303299ebb4caSwyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
303373cc0e02Swyllys 	else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
303473cc0e02Swyllys 		rv = KMF_OK;
303599ebb4caSwyllys 
303699ebb4caSwyllys 	return (rv);
303799ebb4caSwyllys }
303899ebb4caSwyllys 
303999ebb4caSwyllys #define	HANDLE_PK12_ERROR { \
304099ebb4caSwyllys 	SET_ERROR(kmfh, ERR_get_error()); \
304199ebb4caSwyllys 	rv = KMF_ERR_ENCODING; \
304299ebb4caSwyllys 	goto out; \
304399ebb4caSwyllys }
304499ebb4caSwyllys 
30455b3e1433Swyllys static int
30465b3e1433Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
304799ebb4caSwyllys {
3048300fdee2SAndy Fiddaman 	unsigned char *alias;
3049300fdee2SAndy Fiddaman 	int len;
3050300fdee2SAndy Fiddaman 
3051300fdee2SAndy Fiddaman 	if (xcert != NULL && (alias = X509_alias_get0(xcert, &len)) != NULL) {
30525b3e1433Swyllys 		if (PKCS12_add_friendlyname_asc(bag,
3053300fdee2SAndy Fiddaman 		    (const char *)alias, len) == 0)
30545b3e1433Swyllys 			return (0);
30555b3e1433Swyllys 	}
30565b3e1433Swyllys 	return (1);
30575b3e1433Swyllys }
30585b3e1433Swyllys 
30595b3e1433Swyllys static PKCS7 *
30605b3e1433Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
30615b3e1433Swyllys     uchar_t *keyid, unsigned int keyidlen)
30625b3e1433Swyllys {
306399ebb4caSwyllys 	PKCS12_SAFEBAG *bag = NULL;
306499ebb4caSwyllys 	PKCS7 *cert_authsafe = NULL;
30655b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack;
306699ebb4caSwyllys 
306799ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
306899ebb4caSwyllys 	if (bag_stack == NULL)
30695b3e1433Swyllys 		return (NULL);
307099ebb4caSwyllys 
307199ebb4caSwyllys 	/* Convert cert from X509 struct to PKCS#12 bag */
3072300fdee2SAndy Fiddaman 	bag = PKCS12_SAFEBAG_create_cert(sslcert);
307399ebb4caSwyllys 	if (bag == NULL) {
30745b3e1433Swyllys 		goto out;
307599ebb4caSwyllys 	}
307699ebb4caSwyllys 
307799ebb4caSwyllys 	/* Add the key id to the certificate bag. */
30785b3e1433Swyllys 	if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
30795b3e1433Swyllys 		goto out;
308099ebb4caSwyllys 	}
308199ebb4caSwyllys 
30825b3e1433Swyllys 	if (!add_alias_to_bag(bag, sslcert))
30835b3e1433Swyllys 		goto out;
30845b3e1433Swyllys 
308599ebb4caSwyllys 	/* Pile it on the bag_stack. */
308699ebb4caSwyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
30875b3e1433Swyllys 		goto out;
308899ebb4caSwyllys 	}
308999ebb4caSwyllys 	/* Turn bag_stack of certs into encrypted authsafe. */
309099ebb4caSwyllys 	cert_authsafe = PKCS12_pack_p7encdata(
309199ebb4caSwyllys 	    NID_pbe_WithSHA1And40BitRC2_CBC,
309234acef67Swyllys 	    cred->cred, cred->credlen, NULL, 0,
309334acef67Swyllys 	    PKCS12_DEFAULT_ITER, bag_stack);
309499ebb4caSwyllys 
30955b3e1433Swyllys out:
30965b3e1433Swyllys 	if (bag_stack != NULL)
309799ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
309899ebb4caSwyllys 
30995b3e1433Swyllys 	return (cert_authsafe);
310099ebb4caSwyllys }
31015b3e1433Swyllys 
31025b3e1433Swyllys static PKCS7 *
31035b3e1433Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
3104*4942e222SAndy Fiddaman     uchar_t *keyid,  unsigned int keyidlen, char *label, int label_len)
31055b3e1433Swyllys {
31065b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
31075b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
31085b3e1433Swyllys 	PKCS12_SAFEBAG *bag = NULL;
31095b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
31105b3e1433Swyllys 
311199ebb4caSwyllys 	p8 = EVP_PKEY2PKCS8(pkey);
311299ebb4caSwyllys 	if (p8 == NULL) {
31135b3e1433Swyllys 		return (NULL);
311499ebb4caSwyllys 	}
311599ebb4caSwyllys 	/* Put the shrouded key into a PKCS#12 bag. */
3116300fdee2SAndy Fiddaman 	bag = PKCS12_SAFEBAG_create_pkcs8_encrypt(
311799ebb4caSwyllys 	    NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
311899ebb4caSwyllys 	    cred->cred, cred->credlen,
311999ebb4caSwyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, p8);
312099ebb4caSwyllys 
312199ebb4caSwyllys 	/* Clean up the PKCS#8 shrouded key, don't need it now. */
312299ebb4caSwyllys 	PKCS8_PRIV_KEY_INFO_free(p8);
312399ebb4caSwyllys 	p8 = NULL;
312499ebb4caSwyllys 
312599ebb4caSwyllys 	if (bag == NULL) {
31265b3e1433Swyllys 		return (NULL);
312799ebb4caSwyllys 	}
31285b3e1433Swyllys 	if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
31295b3e1433Swyllys 		goto out;
31305b3e1433Swyllys 	if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
31315b3e1433Swyllys 		goto out;
31325b3e1433Swyllys 
313399ebb4caSwyllys 	/* Start a PKCS#12 safebag container for the private key. */
313499ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
31355b3e1433Swyllys 	if (bag_stack == NULL)
31365b3e1433Swyllys 		goto out;
313799ebb4caSwyllys 
313899ebb4caSwyllys 	/* Pile on the private key on the bag_stack. */
31395b3e1433Swyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
31405b3e1433Swyllys 		goto out;
31415b3e1433Swyllys 
314299ebb4caSwyllys 	key_authsafe = PKCS12_pack_p7data(bag_stack);
314399ebb4caSwyllys 
31445b3e1433Swyllys out:
31455b3e1433Swyllys 	if (bag_stack != NULL)
314699ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
314799ebb4caSwyllys 	bag_stack = NULL;
31485b3e1433Swyllys 	return (key_authsafe);
314999ebb4caSwyllys }
315099ebb4caSwyllys 
315199ebb4caSwyllys static EVP_PKEY *
315299ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
315399ebb4caSwyllys {
315499ebb4caSwyllys 	RSA		*rsa = NULL;
315599ebb4caSwyllys 	EVP_PKEY	*newkey = NULL;
3156*4942e222SAndy Fiddaman 	BIGNUM		*n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL;
3157*4942e222SAndy Fiddaman 	BIGNUM		*dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
315899ebb4caSwyllys 
315999ebb4caSwyllys 	if ((rsa = RSA_new()) == NULL)
3160300fdee2SAndy Fiddaman 		goto cleanup;
316199ebb4caSwyllys 
3162300fdee2SAndy Fiddaman 	if ((n = BN_bin2bn(key->mod.val, key->mod.len, NULL)) == NULL)
3163300fdee2SAndy Fiddaman 		goto cleanup;
316499ebb4caSwyllys 
3165300fdee2SAndy Fiddaman 	if ((e = BN_bin2bn(key->pubexp.val, key->pubexp.len, NULL)) == NULL)
3166300fdee2SAndy Fiddaman 		goto cleanup;
316799ebb4caSwyllys 
3168300fdee2SAndy Fiddaman 	if (key->priexp.val != NULL &&
3169300fdee2SAndy Fiddaman 	    (d = BN_bin2bn(key->priexp.val, key->priexp.len, NULL)) == NULL)
3170300fdee2SAndy Fiddaman 		goto cleanup;
317199ebb4caSwyllys 
3172300fdee2SAndy Fiddaman 	if (key->prime1.val != NULL &&
3173300fdee2SAndy Fiddaman 	    (p = BN_bin2bn(key->prime1.val, key->prime1.len, NULL)) == NULL)
3174300fdee2SAndy Fiddaman 		goto cleanup;
317599ebb4caSwyllys 
3176300fdee2SAndy Fiddaman 	if (key->prime2.val != NULL &&
3177300fdee2SAndy Fiddaman 	    (q = BN_bin2bn(key->prime2.val, key->prime2.len, NULL)) == NULL)
3178300fdee2SAndy Fiddaman 		goto cleanup;
317999ebb4caSwyllys 
3180300fdee2SAndy Fiddaman 	if (key->exp1.val != NULL &&
3181300fdee2SAndy Fiddaman 	    (dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len, NULL)) == NULL)
3182300fdee2SAndy Fiddaman 		goto cleanup;
318399ebb4caSwyllys 
3184300fdee2SAndy Fiddaman 	if (key->exp2.val != NULL &&
3185300fdee2SAndy Fiddaman 	    (dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len, NULL)) == NULL)
3186300fdee2SAndy Fiddaman 		goto cleanup;
318799ebb4caSwyllys 
3188300fdee2SAndy Fiddaman 	if (key->coef.val != NULL &&
3189300fdee2SAndy Fiddaman 	    (iqmp = BN_bin2bn(key->coef.val, key->coef.len, NULL)) == NULL)
3190300fdee2SAndy Fiddaman 		goto cleanup;
3191300fdee2SAndy Fiddaman 
3192300fdee2SAndy Fiddaman 	if (RSA_set0_key(rsa, n, e, d) == 0)
3193300fdee2SAndy Fiddaman 		goto cleanup;
3194300fdee2SAndy Fiddaman 	n = e = d = NULL;
3195300fdee2SAndy Fiddaman 	if (RSA_set0_factors(rsa, p, q) == 0)
3196300fdee2SAndy Fiddaman 		goto cleanup;
3197300fdee2SAndy Fiddaman 	p = q = NULL;
3198300fdee2SAndy Fiddaman 	if (RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp) == 0)
3199300fdee2SAndy Fiddaman 		goto cleanup;
3200300fdee2SAndy Fiddaman 	dmp1 = dmq1 = iqmp = NULL;
320199ebb4caSwyllys 
320299ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
3203300fdee2SAndy Fiddaman 		goto cleanup;
320499ebb4caSwyllys 
320599ebb4caSwyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
320699ebb4caSwyllys 
3207300fdee2SAndy Fiddaman cleanup:
320899ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
3209300fdee2SAndy Fiddaman 	if (rsa)
321099ebb4caSwyllys 		RSA_free(rsa);
3211300fdee2SAndy Fiddaman 	BN_free(n);
3212300fdee2SAndy Fiddaman 	BN_free(e);
3213300fdee2SAndy Fiddaman 	BN_free(d);
3214300fdee2SAndy Fiddaman 	BN_free(p);
3215300fdee2SAndy Fiddaman 	BN_free(q);
3216300fdee2SAndy Fiddaman 	BN_free(dmp1);
3217300fdee2SAndy Fiddaman 	BN_free(dmq1);
3218300fdee2SAndy Fiddaman 	BN_free(iqmp);
321999ebb4caSwyllys 
322099ebb4caSwyllys 	return (newkey);
322199ebb4caSwyllys }
322299ebb4caSwyllys 
322399ebb4caSwyllys static EVP_PKEY *
322499ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
322599ebb4caSwyllys {
322699ebb4caSwyllys 	DSA		*dsa = NULL;
322799ebb4caSwyllys 	EVP_PKEY	*newkey = NULL;
3228*4942e222SAndy Fiddaman 	BIGNUM		*p = NULL, *q = NULL, *g = NULL;
3229*4942e222SAndy Fiddaman 	BIGNUM		*priv_key = NULL, *pub_key = NULL;
323099ebb4caSwyllys 
323199ebb4caSwyllys 	if ((dsa = DSA_new()) == NULL)
3232300fdee2SAndy Fiddaman 		goto cleanup;
323399ebb4caSwyllys 
3234300fdee2SAndy Fiddaman 	if ((p = BN_bin2bn(key->prime.val, key->prime.len, NULL)) == NULL)
3235300fdee2SAndy Fiddaman 		goto cleanup;
323699ebb4caSwyllys 
3237300fdee2SAndy Fiddaman 	if ((q = BN_bin2bn(key->subprime.val, key->subprime.len, NULL)) == NULL)
3238300fdee2SAndy Fiddaman 		goto cleanup;
323999ebb4caSwyllys 
3240300fdee2SAndy Fiddaman 	if ((g = BN_bin2bn(key->base.val, key->base.len, NULL)) == NULL)
3241300fdee2SAndy Fiddaman 		goto cleanup;
324299ebb4caSwyllys 
3243300fdee2SAndy Fiddaman 	if ((priv_key = BN_bin2bn(key->value.val, key->value.len,
3244300fdee2SAndy Fiddaman 	    NULL)) == NULL)
3245300fdee2SAndy Fiddaman 		goto cleanup;
324699ebb4caSwyllys 
3247300fdee2SAndy Fiddaman 	if (key->pubvalue.val != NULL && (pub_key =
3248300fdee2SAndy Fiddaman 	    BN_bin2bn(key->pubvalue.val, key->pubvalue.len, NULL)) == NULL)
3249300fdee2SAndy Fiddaman 		goto cleanup;
3250300fdee2SAndy Fiddaman 
3251300fdee2SAndy Fiddaman 	if (DSA_set0_pqg(dsa, p, q, g) == 0)
3252300fdee2SAndy Fiddaman 		goto cleanup;
3253300fdee2SAndy Fiddaman 	p = q = g = NULL;
3254300fdee2SAndy Fiddaman 	if (DSA_set0_key(dsa, pub_key, priv_key) == 0)
3255300fdee2SAndy Fiddaman 		goto cleanup;
3256300fdee2SAndy Fiddaman 	pub_key = priv_key = 0;
325730a5e8faSwyllys 
325899ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
3259300fdee2SAndy Fiddaman 		goto cleanup;
326099ebb4caSwyllys 
326199ebb4caSwyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
326299ebb4caSwyllys 
3263300fdee2SAndy Fiddaman cleanup:
326499ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
3265300fdee2SAndy Fiddaman 	if (dsa)
326699ebb4caSwyllys 		DSA_free(dsa);
3267300fdee2SAndy Fiddaman 	BN_free(p);
3268300fdee2SAndy Fiddaman 	BN_free(q);
3269300fdee2SAndy Fiddaman 	BN_free(g);
3270300fdee2SAndy Fiddaman 	BN_free(priv_key);
3271300fdee2SAndy Fiddaman 	BN_free(pub_key);
3272300fdee2SAndy Fiddaman 
327399ebb4caSwyllys 	return (newkey);
327499ebb4caSwyllys }
327599ebb4caSwyllys 
32765b3e1433Swyllys static EVP_PKEY *
32775b3e1433Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key)
32785b3e1433Swyllys {
32795b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
32805b3e1433Swyllys 	KMF_RAW_KEY_DATA *rawkey;
32815b3e1433Swyllys 	ASN1_TYPE *attr = NULL;
32825b3e1433Swyllys 	KMF_RETURN ret;
32835b3e1433Swyllys 
32845b3e1433Swyllys 	if (key == NULL || !key->israw)
32855b3e1433Swyllys 		return (NULL);
32865b3e1433Swyllys 
32875b3e1433Swyllys 	rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
32885b3e1433Swyllys 	if (rawkey->keytype == KMF_RSA) {
32895b3e1433Swyllys 		pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
32905b3e1433Swyllys 	} else if (rawkey->keytype == KMF_DSA) {
32915b3e1433Swyllys 		pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
3292e65e5c2dSWyllys Ingersoll 	} else if (rawkey->keytype == KMF_ECDSA) {
3293e65e5c2dSWyllys Ingersoll 		/*
3294e65e5c2dSWyllys Ingersoll 		 * OpenSSL in Solaris does not support EC for
3295e65e5c2dSWyllys Ingersoll 		 * legal reasons
3296e65e5c2dSWyllys Ingersoll 		 */
3297e65e5c2dSWyllys Ingersoll 		return (NULL);
32985b3e1433Swyllys 	} else {
32995b3e1433Swyllys 		/* wrong kind of key */
33005b3e1433Swyllys 		return (NULL);
33015b3e1433Swyllys 	}
33025b3e1433Swyllys 
33035b3e1433Swyllys 	if (rawkey->label != NULL) {
33045b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
33055b3e1433Swyllys 			EVP_PKEY_free(pkey);
33065b3e1433Swyllys 			return (NULL);
33075b3e1433Swyllys 		}
33085b3e1433Swyllys 		attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
33095b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
33105b3e1433Swyllys 		    strlen(rawkey->label));
33115b3e1433Swyllys 		attr->type = V_ASN1_BMPSTRING;
33125b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.bmpstring;
33135b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
33145b3e1433Swyllys 		if (ret != KMF_OK) {
33155b3e1433Swyllys 			EVP_PKEY_free(pkey);
33165b3e1433Swyllys 			ASN1_TYPE_free(attr);
33175b3e1433Swyllys 			return (NULL);
33185b3e1433Swyllys 		}
33195b3e1433Swyllys 	}
33205b3e1433Swyllys 	if (rawkey->id.Data != NULL) {
33215b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
33225b3e1433Swyllys 			EVP_PKEY_free(pkey);
33235b3e1433Swyllys 			return (NULL);
33245b3e1433Swyllys 		}
33255b3e1433Swyllys 		attr->value.octet_string =
33265b3e1433Swyllys 		    ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
33275b3e1433Swyllys 		attr->type = V_ASN1_OCTET_STRING;
33285b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.octet_string,
33295b3e1433Swyllys 		    rawkey->id.Data, rawkey->id.Length);
33305b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.octet_string;
33315b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
33325b3e1433Swyllys 		if (ret != KMF_OK) {
33335b3e1433Swyllys 			EVP_PKEY_free(pkey);
33345b3e1433Swyllys 			ASN1_TYPE_free(attr);
33355b3e1433Swyllys 			return (NULL);
33365b3e1433Swyllys 		}
33375b3e1433Swyllys 	}
33385b3e1433Swyllys 	return (pkey);
33395b3e1433Swyllys }
33405b3e1433Swyllys 
33415b3e1433Swyllys /*
33425b3e1433Swyllys  * Search a list of private keys to find one that goes with the certificate.
33435b3e1433Swyllys  */
33445b3e1433Swyllys static EVP_PKEY *
33455b3e1433Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
33465b3e1433Swyllys {
33475b3e1433Swyllys 	int i;
33485b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
33495b3e1433Swyllys 
33505b3e1433Swyllys 	if (numkeys == 0 || keylist == NULL || xcert == NULL)
33515b3e1433Swyllys 		return (NULL);
33525b3e1433Swyllys 	for (i = 0; i < numkeys; i++) {
33535b3e1433Swyllys 		if (keylist[i].israw)
33545b3e1433Swyllys 			pkey = raw_key_to_pkey(&keylist[i]);
33555b3e1433Swyllys 		else
33565b3e1433Swyllys 			pkey = (EVP_PKEY *)keylist[i].keyp;
33575b3e1433Swyllys 		if (pkey != NULL) {
33585b3e1433Swyllys 			if (X509_check_private_key(xcert, pkey)) {
33595b3e1433Swyllys 				return (pkey);
33605b3e1433Swyllys 			} else {
33615b3e1433Swyllys 				EVP_PKEY_free(pkey);
33625b3e1433Swyllys 				pkey = NULL;
33635b3e1433Swyllys 			}
33645b3e1433Swyllys 		}
33655b3e1433Swyllys 	}
33665b3e1433Swyllys 	return (pkey);
33675b3e1433Swyllys }
33685b3e1433Swyllys 
336999ebb4caSwyllys static KMF_RETURN
3370*4942e222SAndy Fiddaman local_export_pk12(KMF_HANDLE_T handle, KMF_CREDENTIAL *cred, int numcerts,
3371*4942e222SAndy Fiddaman     KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
337299ebb4caSwyllys     char *filename)
337399ebb4caSwyllys {
337499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
337599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
337699ebb4caSwyllys 	BIO *bio = NULL;
33775b3e1433Swyllys 	PKCS7 *cert_authsafe = NULL;
33785b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
33795b3e1433Swyllys 	STACK_OF(PKCS7) *authsafe_stack = NULL;
33805b3e1433Swyllys 	PKCS12 *p12_elem = NULL;
338199ebb4caSwyllys 	int i;
338299ebb4caSwyllys 
33835b3e1433Swyllys 	if (numcerts == 0 && numkeys == 0)
33845b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
33855b3e1433Swyllys 
338699ebb4caSwyllys 	/*
338799ebb4caSwyllys 	 * Open the output file.
338899ebb4caSwyllys 	 */
338999ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
339099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
339199ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
339299ebb4caSwyllys 		goto cleanup;
339399ebb4caSwyllys 	}
339499ebb4caSwyllys 
33955b3e1433Swyllys 	/* Start a PKCS#7 stack. */
33965b3e1433Swyllys 	authsafe_stack = sk_PKCS7_new_null();
33975b3e1433Swyllys 	if (authsafe_stack == NULL) {
33985b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
33995b3e1433Swyllys 		goto cleanup;
34005b3e1433Swyllys 	}
34015b3e1433Swyllys 	if (numcerts > 0) {
340299ebb4caSwyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
340399ebb4caSwyllys 			const uchar_t *p = certlist[i].certificate.Data;
340499ebb4caSwyllys 			long len = certlist[i].certificate.Length;
34055b3e1433Swyllys 			X509 *xcert = NULL;
34065b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
34075b3e1433Swyllys 			unsigned char keyid[EVP_MAX_MD_SIZE];
34085b3e1433Swyllys 			unsigned int keyidlen = 0;
340999ebb4caSwyllys 
341099ebb4caSwyllys 			xcert = d2i_X509(NULL, &p, len);
341199ebb4caSwyllys 			if (xcert == NULL) {
341299ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
341399ebb4caSwyllys 				rv = KMF_ERR_ENCODING;
341499ebb4caSwyllys 			}
34155b3e1433Swyllys 			if (certlist[i].kmf_private.label != NULL) {
34165b3e1433Swyllys 				/* Set alias attribute */
34175b3e1433Swyllys 				(void) X509_alias_set1(xcert,
34185b3e1433Swyllys 				    (uchar_t *)certlist[i].kmf_private.label,
34195b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label));
34205b3e1433Swyllys 			}
34215b3e1433Swyllys 			/* Check if there is a key corresponding to this cert */
34225b3e1433Swyllys 			pkey = find_matching_key(xcert, numkeys, keylist);
34235b3e1433Swyllys 
34245b3e1433Swyllys 			/*
34255b3e1433Swyllys 			 * If key is found, get fingerprint and create a
34265b3e1433Swyllys 			 * safebag.
34275b3e1433Swyllys 			 */
34285b3e1433Swyllys 			if (pkey != NULL) {
34295b3e1433Swyllys 				(void) X509_digest(xcert, EVP_sha1(),
34305b3e1433Swyllys 				    keyid, &keyidlen);
34315b3e1433Swyllys 				key_authsafe = add_key_to_safe(pkey, cred,
34325b3e1433Swyllys 				    keyid, keyidlen,
34335b3e1433Swyllys 				    certlist[i].kmf_private.label,
34345b3e1433Swyllys 				    (certlist[i].kmf_private.label ?
34355b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label) : 0));
34365b3e1433Swyllys 
34375b3e1433Swyllys 				if (key_authsafe == NULL) {
34385b3e1433Swyllys 					X509_free(xcert);
34395b3e1433Swyllys 					EVP_PKEY_free(pkey);
34405b3e1433Swyllys 					goto cleanup;
34415b3e1433Swyllys 				}
34425b3e1433Swyllys 				/* Put the key safe into the Auth Safe */
34435b3e1433Swyllys 				if (!sk_PKCS7_push(authsafe_stack,
34445b3e1433Swyllys 				    key_authsafe)) {
34455b3e1433Swyllys 					X509_free(xcert);
34465b3e1433Swyllys 					EVP_PKEY_free(pkey);
34475b3e1433Swyllys 					goto cleanup;
34485b3e1433Swyllys 				}
34495b3e1433Swyllys 			}
34505b3e1433Swyllys 
34515b3e1433Swyllys 			/* create a certificate safebag */
34525b3e1433Swyllys 			cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
34535b3e1433Swyllys 			    keyidlen);
34545b3e1433Swyllys 			if (cert_authsafe == NULL) {
34555b3e1433Swyllys 				X509_free(xcert);
34565b3e1433Swyllys 				EVP_PKEY_free(pkey);
34575b3e1433Swyllys 				goto cleanup;
34585b3e1433Swyllys 			}
34595b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
34605b3e1433Swyllys 				X509_free(xcert);
34615b3e1433Swyllys 				EVP_PKEY_free(pkey);
34625b3e1433Swyllys 				goto cleanup;
34635b3e1433Swyllys 			}
34645b3e1433Swyllys 
346599ebb4caSwyllys 			X509_free(xcert);
346699ebb4caSwyllys 			if (pkey)
346799ebb4caSwyllys 				EVP_PKEY_free(pkey);
346899ebb4caSwyllys 		}
34695b3e1433Swyllys 	} else if (numcerts == 0 && numkeys > 0) {
34705b3e1433Swyllys 		/*
34715b3e1433Swyllys 		 * If only adding keys to the file.
34725b3e1433Swyllys 		 */
34735b3e1433Swyllys 		for (i = 0; i < numkeys; i++) {
34745b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
34755b3e1433Swyllys 
34765b3e1433Swyllys 			if (keylist[i].israw)
34775b3e1433Swyllys 				pkey = raw_key_to_pkey(&keylist[i]);
34785b3e1433Swyllys 			else
34795b3e1433Swyllys 				pkey = (EVP_PKEY *)keylist[i].keyp;
34805b3e1433Swyllys 
34815b3e1433Swyllys 			if (pkey == NULL)
34825b3e1433Swyllys 				continue;
34835b3e1433Swyllys 
34845b3e1433Swyllys 			key_authsafe = add_key_to_safe(pkey, cred,
34855b3e1433Swyllys 			    NULL, 0, NULL, 0);
34865b3e1433Swyllys 
34875b3e1433Swyllys 			if (key_authsafe == NULL) {
34885b3e1433Swyllys 				EVP_PKEY_free(pkey);
34895b3e1433Swyllys 				goto cleanup;
34905b3e1433Swyllys 			}
34915b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
34925b3e1433Swyllys 				EVP_PKEY_free(pkey);
34935b3e1433Swyllys 				goto cleanup;
34945b3e1433Swyllys 			}
34955b3e1433Swyllys 		}
34965b3e1433Swyllys 	}
34975b3e1433Swyllys 	p12_elem = PKCS12_init(NID_pkcs7_data);
34985b3e1433Swyllys 	if (p12_elem == NULL) {
34995b3e1433Swyllys 		goto cleanup;
350099ebb4caSwyllys 	}
350199ebb4caSwyllys 
35025b3e1433Swyllys 	/* Put the PKCS#7 stack into the PKCS#12 element. */
35035b3e1433Swyllys 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
35045b3e1433Swyllys 		goto cleanup;
35055b3e1433Swyllys 	}
35065b3e1433Swyllys 
35075b3e1433Swyllys 	/* Set the integrity MAC on the PKCS#12 element. */
35085b3e1433Swyllys 	if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
35095b3e1433Swyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
35105b3e1433Swyllys 		goto cleanup;
35115b3e1433Swyllys 	}
35125b3e1433Swyllys 
35135b3e1433Swyllys 	/* Write the PKCS#12 element to the export file. */
35145b3e1433Swyllys 	if (!i2d_PKCS12_bio(bio, p12_elem)) {
35155b3e1433Swyllys 		goto cleanup;
35165b3e1433Swyllys 	}
35175b3e1433Swyllys 	PKCS12_free(p12_elem);
35185b3e1433Swyllys 
351999ebb4caSwyllys cleanup:
35205b3e1433Swyllys 	/* Clear away the PKCS#7 stack, we're done with it. */
35215b3e1433Swyllys 	if (authsafe_stack)
35225b3e1433Swyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
352399ebb4caSwyllys 
352499ebb4caSwyllys 	if (bio != NULL)
352599ebb4caSwyllys 		(void) BIO_free_all(bio);
352699ebb4caSwyllys 
352799ebb4caSwyllys 	return (rv);
352899ebb4caSwyllys }
352999ebb4caSwyllys 
353099ebb4caSwyllys KMF_RETURN
353130a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
353230a5e8faSwyllys     KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
353330a5e8faSwyllys     KMF_CREDENTIAL *p12cred, char *filename)
353430a5e8faSwyllys {
353530a5e8faSwyllys 	KMF_RETURN rv;
353630a5e8faSwyllys 
353730a5e8faSwyllys 	if (certlist == NULL && keylist == NULL)
353830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
353930a5e8faSwyllys 
35405b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, numcerts, certlist,
354130a5e8faSwyllys 	    numkeys, keylist, filename);
354230a5e8faSwyllys 
354330a5e8faSwyllys 	return (rv);
354430a5e8faSwyllys }
354530a5e8faSwyllys 
354630a5e8faSwyllys KMF_RETURN
354730a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
354899ebb4caSwyllys {
354999ebb4caSwyllys 	KMF_RETURN rv;
355099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
355199ebb4caSwyllys 	char *fullpath = NULL;
355230a5e8faSwyllys 	char *dirpath = NULL;
355330a5e8faSwyllys 	char *certfile = NULL;
355430a5e8faSwyllys 	char *keyfile = NULL;
355530a5e8faSwyllys 	char *filename = NULL;
355630a5e8faSwyllys 	KMF_CREDENTIAL *p12cred = NULL;
35575b3e1433Swyllys 	KMF_X509_DER_CERT certdata;
35585b3e1433Swyllys 	KMF_KEY_HANDLE key;
35595b3e1433Swyllys 	int gotkey = 0;
35605b3e1433Swyllys 	int gotcert = 0;
356130a5e8faSwyllys 
356230a5e8faSwyllys 	if (handle == NULL)
356330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
356499ebb4caSwyllys 
356599ebb4caSwyllys 	/*
356699ebb4caSwyllys 	 *  First, find the certificate.
356799ebb4caSwyllys 	 */
356830a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
356930a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
357030a5e8faSwyllys 	if (certfile != NULL) {
357130a5e8faSwyllys 		fullpath = get_fullpath(dirpath, certfile);
357299ebb4caSwyllys 		if (fullpath == NULL)
357399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
357499ebb4caSwyllys 
357599ebb4caSwyllys 		if (isdir(fullpath)) {
357699ebb4caSwyllys 			free(fullpath);
357799ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
357899ebb4caSwyllys 		}
357999ebb4caSwyllys 
35805b3e1433Swyllys 		(void) memset(&certdata, 0, sizeof (certdata));
3581f810c7e5SToomas Soome 		rv = kmf_load_cert(kmfh, NULL, NULL, NULL, 0,
35825b3e1433Swyllys 		    fullpath, &certdata.certificate);
358399ebb4caSwyllys 		if (rv != KMF_OK)
358499ebb4caSwyllys 			goto end;
358530a5e8faSwyllys 
35865b3e1433Swyllys 		gotcert++;
35875b3e1433Swyllys 		certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
358830a5e8faSwyllys 		free(fullpath);
358999ebb4caSwyllys 	}
359099ebb4caSwyllys 
359199ebb4caSwyllys 	/*
359299ebb4caSwyllys 	 * Now find the private key.
359399ebb4caSwyllys 	 */
359430a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
359530a5e8faSwyllys 	if (keyfile != NULL) {
359630a5e8faSwyllys 		fullpath = get_fullpath(dirpath, keyfile);
359799ebb4caSwyllys 		if (fullpath == NULL)
359899ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
359999ebb4caSwyllys 
360099ebb4caSwyllys 		if (isdir(fullpath)) {
360199ebb4caSwyllys 			free(fullpath);
360299ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
360399ebb4caSwyllys 		}
360499ebb4caSwyllys 
36055b3e1433Swyllys 		(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
36065b3e1433Swyllys 		rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
36075b3e1433Swyllys 		if (rv != KMF_OK)
360899ebb4caSwyllys 			goto end;
36095b3e1433Swyllys 		gotkey++;
361099ebb4caSwyllys 	}
361199ebb4caSwyllys 
361299ebb4caSwyllys 	/*
361399ebb4caSwyllys 	 * Open the output file.
361499ebb4caSwyllys 	 */
361530a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
361630a5e8faSwyllys 	    numattr);
361730a5e8faSwyllys 	if (filename == NULL) {
361830a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
361930a5e8faSwyllys 		goto end;
362030a5e8faSwyllys 	}
362130a5e8faSwyllys 
362299ebb4caSwyllys 	/* Stick the key and the cert into a PKCS#12 file */
362330a5e8faSwyllys 	p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
362430a5e8faSwyllys 	if (p12cred == NULL) {
362530a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
362630a5e8faSwyllys 		goto end;
362730a5e8faSwyllys 	}
362830a5e8faSwyllys 
36295b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, 1, &certdata,
36305b3e1433Swyllys 	    1, &key, filename);
363199ebb4caSwyllys 
363299ebb4caSwyllys end:
363399ebb4caSwyllys 	if (fullpath)
363499ebb4caSwyllys 		free(fullpath);
363599ebb4caSwyllys 
36365b3e1433Swyllys 	if (gotcert)
36375b3e1433Swyllys 		kmf_free_kmf_cert(handle, &certdata);
36385b3e1433Swyllys 	if (gotkey)
36395b3e1433Swyllys 		kmf_free_kmf_key(handle, &key);
364099ebb4caSwyllys 	return (rv);
364199ebb4caSwyllys }
364299ebb4caSwyllys 
364371593db2Swyllys /*
364471593db2Swyllys  * Helper function to extract keys and certificates from
364571593db2Swyllys  * a single PEM file.  Typically the file should contain a
364671593db2Swyllys  * private key and an associated public key wrapped in an x509 cert.
364771593db2Swyllys  * However, the file may be just a list of X509 certs with no keys.
364871593db2Swyllys  */
364971593db2Swyllys static KMF_RETURN
3650*4942e222SAndy Fiddaman extract_pem(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
3651*4942e222SAndy Fiddaman     char *filename, CK_UTF8CHAR *pin, CK_ULONG pinlen, EVP_PKEY **priv_key,
3652*4942e222SAndy Fiddaman     KMF_DATA **certs, int *numcerts)
365371593db2Swyllys {
365471593db2Swyllys 	KMF_RETURN rv = KMF_OK;
365571593db2Swyllys 	FILE *fp;
365634acef67Swyllys 	STACK_OF(X509_INFO) *x509_info_stack = NULL;
365702744e81Swyllys 	int i, ncerts = 0, matchcerts = 0;
365871593db2Swyllys 	EVP_PKEY *pkey = NULL;
365971593db2Swyllys 	X509_INFO *info;
366071593db2Swyllys 	X509 *x;
36615b3e1433Swyllys 	X509_INFO **cert_infos = NULL;
366271593db2Swyllys 	KMF_DATA *certlist = NULL;
366371593db2Swyllys 
366471593db2Swyllys 	if (priv_key)
366571593db2Swyllys 		*priv_key = NULL;
366671593db2Swyllys 	if (certs)
366771593db2Swyllys 		*certs = NULL;
366871593db2Swyllys 	fp = fopen(filename, "r");
36695b3e1433Swyllys 	if (fp == NULL)
367071593db2Swyllys 		return (KMF_ERR_OPEN_FILE);
36715b3e1433Swyllys 
367271593db2Swyllys 	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
367371593db2Swyllys 	if (x509_info_stack == NULL) {
367471593db2Swyllys 		(void) fclose(fp);
367571593db2Swyllys 		return (KMF_ERR_ENCODING);
367671593db2Swyllys 	}
36775b3e1433Swyllys 	cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
36785b3e1433Swyllys 	    sizeof (X509_INFO *));
36795b3e1433Swyllys 	if (cert_infos == NULL) {
36805b3e1433Swyllys 		(void) fclose(fp);
36815b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
36825b3e1433Swyllys 		goto err;
36835b3e1433Swyllys 	}
368471593db2Swyllys 
36855b3e1433Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
368634acef67Swyllys 		cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
368771593db2Swyllys 		ncerts++;
368871593db2Swyllys 	}
368971593db2Swyllys 
369071593db2Swyllys 	if (ncerts == 0) {
369171593db2Swyllys 		(void) fclose(fp);
369234acef67Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
369334acef67Swyllys 		goto err;
369471593db2Swyllys 	}
369571593db2Swyllys 
369671593db2Swyllys 	if (priv_key != NULL) {
369771593db2Swyllys 		rewind(fp);
369871593db2Swyllys 		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
369971593db2Swyllys 	}
370071593db2Swyllys 	(void) fclose(fp);
370171593db2Swyllys 
370271593db2Swyllys 	x = cert_infos[ncerts - 1]->x509;
370371593db2Swyllys 	/*
370471593db2Swyllys 	 * Make sure the private key matchs the last cert in the file.
370571593db2Swyllys 	 */
370671593db2Swyllys 	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
370771593db2Swyllys 		EVP_PKEY_free(pkey);
370834acef67Swyllys 		rv = KMF_ERR_KEY_MISMATCH;
370934acef67Swyllys 		goto err;
371071593db2Swyllys 	}
371171593db2Swyllys 
3712a2d4930dSDan OpenSolaris Anderson 	certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
371371593db2Swyllys 	if (certlist == NULL) {
371471593db2Swyllys 		if (pkey != NULL)
371571593db2Swyllys 			EVP_PKEY_free(pkey);
371634acef67Swyllys 		rv = KMF_ERR_MEMORY;
371734acef67Swyllys 		goto err;
371871593db2Swyllys 	}
371971593db2Swyllys 
372071593db2Swyllys 	/*
372171593db2Swyllys 	 * Convert all of the certs to DER format.
372271593db2Swyllys 	 */
372302744e81Swyllys 	matchcerts = 0;
372471593db2Swyllys 	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
372502744e81Swyllys 		boolean_t match = FALSE;
372671593db2Swyllys 		info =  cert_infos[ncerts - 1 - i];
372771593db2Swyllys 
372830a5e8faSwyllys 		rv = check_cert(info->x509, issuer, subject, serial, &match);
372902744e81Swyllys 		if (rv != KMF_OK || match != TRUE) {
373002744e81Swyllys 			rv = KMF_OK;
373102744e81Swyllys 			continue;
373202744e81Swyllys 		}
373302744e81Swyllys 
373402744e81Swyllys 		rv = ssl_cert2KMFDATA(kmfh, info->x509,
373502744e81Swyllys 		    &certlist[matchcerts++]);
373671593db2Swyllys 
373771593db2Swyllys 		if (rv != KMF_OK) {
3738e65e5c2dSWyllys Ingersoll 			int j;
3739e65e5c2dSWyllys Ingersoll 			for (j = 0; j < matchcerts; j++)
3740e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certlist[j]);
374171593db2Swyllys 			free(certlist);
374271593db2Swyllys 			certlist = NULL;
374302744e81Swyllys 			ncerts = matchcerts = 0;
374471593db2Swyllys 		}
374571593db2Swyllys 	}
374671593db2Swyllys 
374771593db2Swyllys 	if (numcerts != NULL)
374802744e81Swyllys 		*numcerts = matchcerts;
3749a2d4930dSDan OpenSolaris Anderson 
3750e65e5c2dSWyllys Ingersoll 	if (certs != NULL)
375171593db2Swyllys 		*certs = certlist;
3752e65e5c2dSWyllys Ingersoll 	else if (certlist != NULL) {
3753e65e5c2dSWyllys Ingersoll 		for (i = 0; i < ncerts; i++)
3754e65e5c2dSWyllys Ingersoll 			kmf_free_data(&certlist[i]);
3755a2d4930dSDan OpenSolaris Anderson 		free(certlist);
3756a2d4930dSDan OpenSolaris Anderson 		certlist = NULL;
3757a2d4930dSDan OpenSolaris Anderson 	}
375871593db2Swyllys 
375971593db2Swyllys 	if (priv_key == NULL && pkey != NULL)
376071593db2Swyllys 		EVP_PKEY_free(pkey);
376171593db2Swyllys 	else if (priv_key != NULL && pkey != NULL)
376271593db2Swyllys 		*priv_key = pkey;
376371593db2Swyllys 
376434acef67Swyllys err:
376534acef67Swyllys 	/* Cleanup the stack of X509 info records */
376634acef67Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
376734acef67Swyllys 		info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
376834acef67Swyllys 		X509_INFO_free(info);
376934acef67Swyllys 	}
377034acef67Swyllys 	if (x509_info_stack)
377134acef67Swyllys 		sk_X509_INFO_free(x509_info_stack);
377234acef67Swyllys 
37735b3e1433Swyllys 	if (cert_infos != NULL)
37745b3e1433Swyllys 		free(cert_infos);
37755b3e1433Swyllys 
377671593db2Swyllys 	return (rv);
377771593db2Swyllys }
377871593db2Swyllys 
37795b3e1433Swyllys static KMF_RETURN
3780300fdee2SAndy Fiddaman openssl_parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
37815b3e1433Swyllys     STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
37825b3e1433Swyllys {
37835b3e1433Swyllys 	KMF_RETURN ret;
37845b3e1433Swyllys 	int i;
37855b3e1433Swyllys 
37865b3e1433Swyllys 	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
37875b3e1433Swyllys 		PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
37885b3e1433Swyllys 		ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
37895b3e1433Swyllys 		    keys, certs);
37905b3e1433Swyllys 
37915b3e1433Swyllys 		if (ret != KMF_OK)
37925b3e1433Swyllys 			return (ret);
37935b3e1433Swyllys 	}
37945b3e1433Swyllys 
37955b3e1433Swyllys 	return (ret);
37965b3e1433Swyllys }
37975b3e1433Swyllys 
37985b3e1433Swyllys static KMF_RETURN
37995b3e1433Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
38005b3e1433Swyllys {
38015b3e1433Swyllys 	X509_ATTRIBUTE *attr = NULL;
38025b3e1433Swyllys 
38035b3e1433Swyllys 	if (pkey == NULL || attrib == NULL)
38045b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
38055b3e1433Swyllys 
38065b3e1433Swyllys 	attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
38075b3e1433Swyllys 	if (attr != NULL) {
38085b3e1433Swyllys 		int i;
3809300fdee2SAndy Fiddaman 
3810300fdee2SAndy Fiddaman 		if ((i = EVP_PKEY_get_attr_by_NID(pkey, nid, -1)) != -1)
3811300fdee2SAndy Fiddaman 			(void) EVP_PKEY_delete_attr(pkey, i);
3812300fdee2SAndy Fiddaman 		if (EVP_PKEY_add1_attr(pkey, attr) == 0) {
38135b3e1433Swyllys 			X509_ATTRIBUTE_free(attr);
38145b3e1433Swyllys 			return (KMF_ERR_MEMORY);
38155b3e1433Swyllys 		}
38165b3e1433Swyllys 	} else {
38175b3e1433Swyllys 		return (KMF_ERR_MEMORY);
38185b3e1433Swyllys 	}
38195b3e1433Swyllys 
38205b3e1433Swyllys 	return (KMF_OK);
38215b3e1433Swyllys }
38225b3e1433Swyllys 
38235b3e1433Swyllys static KMF_RETURN
38245b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
38255b3e1433Swyllys     STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
38265b3e1433Swyllys {
38275b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
38285b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
38295b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
38305b3e1433Swyllys 	X509 *xcert = NULL;
3831300fdee2SAndy Fiddaman 	const ASN1_TYPE *keyid = NULL;
3832300fdee2SAndy Fiddaman 	const ASN1_TYPE *fname = NULL;
38335b3e1433Swyllys 	uchar_t *data = NULL;
38345b3e1433Swyllys 
3835300fdee2SAndy Fiddaman 	keyid = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID);
3836300fdee2SAndy Fiddaman 	fname = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName);
38375b3e1433Swyllys 
3838300fdee2SAndy Fiddaman 	switch (PKCS12_SAFEBAG_get_nid(bag)) {
38395b3e1433Swyllys 		case NID_keyBag:
38405b3e1433Swyllys 			if (keylist == NULL)
38415b3e1433Swyllys 				goto end;
3842300fdee2SAndy Fiddaman 			pkey = EVP_PKCS82PKEY(
3843300fdee2SAndy Fiddaman 			    PKCS12_SAFEBAG_get0_p8inf(bag));
38445b3e1433Swyllys 			if (pkey == NULL)
38455b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38465b3e1433Swyllys 
38475b3e1433Swyllys 			break;
38485b3e1433Swyllys 		case NID_pkcs8ShroudedKeyBag:
38495b3e1433Swyllys 			if (keylist == NULL)
38505b3e1433Swyllys 				goto end;
3851300fdee2SAndy Fiddaman 			p8 = PKCS12_decrypt_skey(bag, pass, passlen);
38525b3e1433Swyllys 			if (p8 == NULL)
38535b3e1433Swyllys 				return (KMF_ERR_AUTH_FAILED);
38545b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(p8);
38555b3e1433Swyllys 			PKCS8_PRIV_KEY_INFO_free(p8);
38565b3e1433Swyllys 			if (pkey == NULL)
38575b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38585b3e1433Swyllys 			break;
38595b3e1433Swyllys 		case NID_certBag:
38605b3e1433Swyllys 			if (certlist == NULL)
38615b3e1433Swyllys 				goto end;
3862300fdee2SAndy Fiddaman 			if (PKCS12_SAFEBAG_get_bag_nid(bag) !=
3863300fdee2SAndy Fiddaman 			    NID_x509Certificate)
38645b3e1433Swyllys 				return (KMF_ERR_PKCS12_FORMAT);
3865300fdee2SAndy Fiddaman 			xcert = PKCS12_SAFEBAG_get1_cert(bag);
38665b3e1433Swyllys 			if (xcert == NULL) {
38675b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38685b3e1433Swyllys 				goto end;
38695b3e1433Swyllys 			}
38705b3e1433Swyllys 			if (keyid != NULL) {
38715b3e1433Swyllys 				if (X509_keyid_set1(xcert,
38725b3e1433Swyllys 				    keyid->value.octet_string->data,
38735b3e1433Swyllys 				    keyid->value.octet_string->length) == 0) {
38745b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
38755b3e1433Swyllys 					goto end;
38765b3e1433Swyllys 				}
38775b3e1433Swyllys 			}
38785b3e1433Swyllys 			if (fname != NULL) {
38795b3e1433Swyllys 				int len, r;
38805b3e1433Swyllys 				len = ASN1_STRING_to_UTF8(&data,
38815b3e1433Swyllys 				    fname->value.asn1_string);
38825b3e1433Swyllys 				if (len > 0 && data != NULL) {
38835b3e1433Swyllys 					r = X509_alias_set1(xcert, data, len);
3884f810c7e5SToomas Soome 					if (r == 0) {
38855b3e1433Swyllys 						ret = KMF_ERR_PKCS12_FORMAT;
38865b3e1433Swyllys 						goto end;
38875b3e1433Swyllys 					}
38885b3e1433Swyllys 				} else {
38895b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
38905b3e1433Swyllys 					goto end;
38915b3e1433Swyllys 				}
38925b3e1433Swyllys 			}
38935b3e1433Swyllys 			if (sk_X509_push(certlist, xcert) == 0)
38945b3e1433Swyllys 				ret = KMF_ERR_MEMORY;
38955b3e1433Swyllys 			else
38965b3e1433Swyllys 				xcert = NULL;
38975b3e1433Swyllys 			break;
38985b3e1433Swyllys 		case NID_safeContentsBag:
3899300fdee2SAndy Fiddaman 			return (openssl_parse_bags(
3900300fdee2SAndy Fiddaman 			    PKCS12_SAFEBAG_get0_safes(bag),
3901300fdee2SAndy Fiddaman 			    pass, keylist, certlist));
39025b3e1433Swyllys 		default:
39035b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39045b3e1433Swyllys 			break;
39055b3e1433Swyllys 	}
39065b3e1433Swyllys 
39075b3e1433Swyllys 	/*
39085b3e1433Swyllys 	 * Set the ID and/or FriendlyName attributes on the key.
39095b3e1433Swyllys 	 * If converting to PKCS11 objects, these can translate to CKA_ID
39105b3e1433Swyllys 	 * and CKA_LABEL values.
39115b3e1433Swyllys 	 */
39125b3e1433Swyllys 	if (pkey != NULL && ret == KMF_OK) {
39135b3e1433Swyllys 		ASN1_TYPE *attr = NULL;
39145b3e1433Swyllys 		if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
39155b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
39165b3e1433Swyllys 				return (KMF_ERR_MEMORY);
39175b3e1433Swyllys 			attr->value.octet_string =
39185b3e1433Swyllys 			    ASN1_STRING_dup(keyid->value.octet_string);
39195b3e1433Swyllys 			attr->type = V_ASN1_OCTET_STRING;
39205b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.octet_string;
39215b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
39225b3e1433Swyllys 			OPENSSL_free(attr);
39235b3e1433Swyllys 		}
39245b3e1433Swyllys 
39255b3e1433Swyllys 		if (ret == KMF_OK && fname != NULL &&
39265b3e1433Swyllys 		    fname->type == V_ASN1_BMPSTRING) {
39275b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
39285b3e1433Swyllys 				return (KMF_ERR_MEMORY);
39295b3e1433Swyllys 			attr->value.bmpstring =
39305b3e1433Swyllys 			    ASN1_STRING_dup(fname->value.bmpstring);
39315b3e1433Swyllys 			attr->type = V_ASN1_BMPSTRING;
39325b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.bmpstring;
39335b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
39345b3e1433Swyllys 			OPENSSL_free(attr);
39355b3e1433Swyllys 		}
39365b3e1433Swyllys 
39375b3e1433Swyllys 		if (ret == KMF_OK && keylist != NULL &&
39385b3e1433Swyllys 		    sk_EVP_PKEY_push(keylist, pkey) == 0)
39395b3e1433Swyllys 			ret = KMF_ERR_MEMORY;
39405b3e1433Swyllys 	}
39415b3e1433Swyllys 	if (ret == KMF_OK && keylist != NULL)
39425b3e1433Swyllys 		pkey = NULL;
39435b3e1433Swyllys end:
39445b3e1433Swyllys 	if (pkey != NULL)
39455b3e1433Swyllys 		EVP_PKEY_free(pkey);
39465b3e1433Swyllys 	if (xcert != NULL)
39475b3e1433Swyllys 		X509_free(xcert);
39485b3e1433Swyllys 	if (data != NULL)
39495b3e1433Swyllys 		OPENSSL_free(data);
39505b3e1433Swyllys 
39515b3e1433Swyllys 	return (ret);
39525b3e1433Swyllys }
39535b3e1433Swyllys 
39545b3e1433Swyllys static KMF_RETURN
3955*4942e222SAndy Fiddaman openssl_pkcs12_parse(PKCS12 *p12, char *pin, STACK_OF(EVP_PKEY) *keys,
3956*4942e222SAndy Fiddaman     STACK_OF(X509) *certs, STACK_OF(X509) *ca)
39575b3e1433Swyllys {
39585b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
39595b3e1433Swyllys 	STACK_OF(PKCS7) *asafes = NULL;
39605b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
39615b3e1433Swyllys 	int i, bagnid;
39625b3e1433Swyllys 	PKCS7 *p7;
39635b3e1433Swyllys 
39645b3e1433Swyllys 	if (p12 == NULL || (keys == NULL && certs == NULL))
39655b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
39665b3e1433Swyllys 
3967f810c7e5SToomas Soome 	if (pin == NULL || *pin == '\0') {
39685b3e1433Swyllys 		if (PKCS12_verify_mac(p12, NULL, 0)) {
39695b3e1433Swyllys 			pin = NULL;
39705b3e1433Swyllys 		} else if (PKCS12_verify_mac(p12, "", 0)) {
39715b3e1433Swyllys 			pin = "";
39725b3e1433Swyllys 		} else {
39735b3e1433Swyllys 			return (KMF_ERR_AUTH_FAILED);
39745b3e1433Swyllys 		}
39755b3e1433Swyllys 	} else if (!PKCS12_verify_mac(p12, pin, -1)) {
39765b3e1433Swyllys 		return (KMF_ERR_AUTH_FAILED);
39775b3e1433Swyllys 	}
39785b3e1433Swyllys 
39795b3e1433Swyllys 	if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
39805b3e1433Swyllys 		return (KMF_ERR_PKCS12_FORMAT);
39815b3e1433Swyllys 
39825b3e1433Swyllys 	for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
39835b3e1433Swyllys 		bags = NULL;
39845b3e1433Swyllys 		p7 = sk_PKCS7_value(asafes, i);
39855b3e1433Swyllys 		bagnid = OBJ_obj2nid(p7->type);
39865b3e1433Swyllys 
39875b3e1433Swyllys 		if (bagnid == NID_pkcs7_data) {
39885b3e1433Swyllys 			bags = PKCS12_unpack_p7data(p7);
39895b3e1433Swyllys 		} else if (bagnid == NID_pkcs7_encrypted) {
39905b3e1433Swyllys 			bags = PKCS12_unpack_p7encdata(p7, pin,
39915b3e1433Swyllys 			    (pin ? strlen(pin) : 0));
39925b3e1433Swyllys 		} else {
39935b3e1433Swyllys 			continue;
39945b3e1433Swyllys 		}
39955b3e1433Swyllys 		if (bags == NULL) {
39965b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39975b3e1433Swyllys 			goto out;
39985b3e1433Swyllys 		}
39995b3e1433Swyllys 
40005b3e1433Swyllys 		if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
40015b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
40025b3e1433Swyllys 
40035b3e1433Swyllys 		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
40045b3e1433Swyllys 	}
40055b3e1433Swyllys out:
40065b3e1433Swyllys 	if (asafes != NULL)
40075b3e1433Swyllys 		sk_PKCS7_pop_free(asafes, PKCS7_free);
40085b3e1433Swyllys 
40095b3e1433Swyllys 	return (ret);
40105b3e1433Swyllys }
40115b3e1433Swyllys 
401299ebb4caSwyllys /*
401399ebb4caSwyllys  * Helper function to decrypt and parse PKCS#12 import file.
401499ebb4caSwyllys  */
401599ebb4caSwyllys static KMF_RETURN
401699ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
4017*4942e222SAndy Fiddaman     STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs, STACK_OF(X509) **ca)
401899ebb4caSwyllys {
401999ebb4caSwyllys 	PKCS12			*pk12, *pk12_tmp;
40205b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*pkeylist = NULL;
40215b3e1433Swyllys 	STACK_OF(X509)		*xcertlist = NULL;
40225b3e1433Swyllys 	STACK_OF(X509)		*cacertlist = NULL;
402399ebb4caSwyllys 
402499ebb4caSwyllys 	if ((pk12 = PKCS12_new()) == NULL) {
402599ebb4caSwyllys 		return (KMF_ERR_MEMORY);
402699ebb4caSwyllys 	}
402799ebb4caSwyllys 
402899ebb4caSwyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
402999ebb4caSwyllys 		/* This is ok; it seems to mean there is no more to read. */
403099ebb4caSwyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
403199ebb4caSwyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
403299ebb4caSwyllys 			goto end_extract_pkcs12;
403399ebb4caSwyllys 
403499ebb4caSwyllys 		PKCS12_free(pk12);
403599ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
403699ebb4caSwyllys 	}
403799ebb4caSwyllys 	pk12 = pk12_tmp;
403899ebb4caSwyllys 
40395b3e1433Swyllys 	xcertlist = sk_X509_new_null();
40405b3e1433Swyllys 	if (xcertlist == NULL) {
40415b3e1433Swyllys 		PKCS12_free(pk12);
40425b3e1433Swyllys 		return (KMF_ERR_MEMORY);
40435b3e1433Swyllys 	}
40445b3e1433Swyllys 	pkeylist = sk_EVP_PKEY_new_null();
40455b3e1433Swyllys 	if (pkeylist == NULL) {
40465b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40475b3e1433Swyllys 		PKCS12_free(pk12);
40485b3e1433Swyllys 		return (KMF_ERR_MEMORY);
40495b3e1433Swyllys 	}
40505b3e1433Swyllys 
40515b3e1433Swyllys 	if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
40525b3e1433Swyllys 	    cacertlist) != KMF_OK) {
40535b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40545b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
405599ebb4caSwyllys 		PKCS12_free(pk12);
405699ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
405799ebb4caSwyllys 	}
405899ebb4caSwyllys 
40595b3e1433Swyllys 	if (priv_key && pkeylist)
40605b3e1433Swyllys 		*priv_key = pkeylist;
40615b3e1433Swyllys 	else if (pkeylist)
40625b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
40635b3e1433Swyllys 	if (certs && xcertlist)
40645b3e1433Swyllys 		*certs = xcertlist;
40655b3e1433Swyllys 	else if (xcertlist)
40665b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40675b3e1433Swyllys 	if (ca && cacertlist)
40685b3e1433Swyllys 		*ca = cacertlist;
40695b3e1433Swyllys 	else if (cacertlist)
40705b3e1433Swyllys 		sk_X509_pop_free(cacertlist, X509_free);
407199ebb4caSwyllys 
40725b3e1433Swyllys end_extract_pkcs12:
407399ebb4caSwyllys 
407499ebb4caSwyllys 	PKCS12_free(pk12);
407599ebb4caSwyllys 	return (KMF_OK);
407699ebb4caSwyllys }
407799ebb4caSwyllys 
407899ebb4caSwyllys static KMF_RETURN
407999ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
408099ebb4caSwyllys {
408199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
408299ebb4caSwyllys 	uint32_t sz;
408399ebb4caSwyllys 
408499ebb4caSwyllys 	sz = BN_num_bytes(from);
408599ebb4caSwyllys 	to->val = (uchar_t *)malloc(sz);
408699ebb4caSwyllys 	if (to->val == NULL)
408799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
408899ebb4caSwyllys 
408999ebb4caSwyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
409099ebb4caSwyllys 		free(to->val);
409199ebb4caSwyllys 		to->val = NULL;
409299ebb4caSwyllys 		to->len = 0;
409399ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
409499ebb4caSwyllys 	}
409599ebb4caSwyllys 
409699ebb4caSwyllys 	return (rv);
409799ebb4caSwyllys }
409899ebb4caSwyllys 
409999ebb4caSwyllys static KMF_RETURN
410099ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
410199ebb4caSwyllys {
410299ebb4caSwyllys 	KMF_RETURN rv;
410399ebb4caSwyllys 	KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
410499ebb4caSwyllys 
4105300fdee2SAndy Fiddaman 	const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmpq, *iqmp;
4106300fdee2SAndy Fiddaman 
4107300fdee2SAndy Fiddaman 	RSA_get0_key(rsa, &n, &e, &d);
4108300fdee2SAndy Fiddaman 	RSA_get0_factors(rsa, &p, &q);
4109300fdee2SAndy Fiddaman 	RSA_get0_crt_params(rsa, &dmp1, &dmpq, &iqmp);
4110300fdee2SAndy Fiddaman 
411199ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
4112300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)n, &kmfkey->mod)) != KMF_OK)
411399ebb4caSwyllys 		goto cleanup;
411499ebb4caSwyllys 
4115300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)e, &kmfkey->pubexp)) != KMF_OK)
411699ebb4caSwyllys 		goto cleanup;
411799ebb4caSwyllys 
4118300fdee2SAndy Fiddaman 	if (d != NULL)
4119300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)d, &kmfkey->priexp)) != KMF_OK)
412099ebb4caSwyllys 			goto cleanup;
412199ebb4caSwyllys 
4122300fdee2SAndy Fiddaman 	if (p != NULL)
4123300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime1)) != KMF_OK)
412499ebb4caSwyllys 			goto cleanup;
412599ebb4caSwyllys 
4126300fdee2SAndy Fiddaman 	if (q != NULL)
4127300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->prime2)) != KMF_OK)
412899ebb4caSwyllys 			goto cleanup;
412999ebb4caSwyllys 
4130300fdee2SAndy Fiddaman 	if (dmp1 != NULL)
4131300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)dmp1, &kmfkey->exp1)) != KMF_OK)
413299ebb4caSwyllys 			goto cleanup;
413399ebb4caSwyllys 
4134300fdee2SAndy Fiddaman 	if (dmpq != NULL)
4135300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)dmpq, &kmfkey->exp2)) != KMF_OK)
413699ebb4caSwyllys 			goto cleanup;
413799ebb4caSwyllys 
4138300fdee2SAndy Fiddaman 	if (iqmp != NULL)
4139300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)iqmp, &kmfkey->coef)) != KMF_OK)
414099ebb4caSwyllys 			goto cleanup;
414199ebb4caSwyllys cleanup:
414299ebb4caSwyllys 	if (rv != KMF_OK)
414330a5e8faSwyllys 		kmf_free_raw_key(key);
414499ebb4caSwyllys 	else
414599ebb4caSwyllys 		key->keytype = KMF_RSA;
414699ebb4caSwyllys 
414799ebb4caSwyllys 	/*
414899ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
414999ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
415099ebb4caSwyllys 	 */
415199ebb4caSwyllys 	RSA_free(rsa);
415299ebb4caSwyllys 
415399ebb4caSwyllys 	return (rv);
415499ebb4caSwyllys }
415599ebb4caSwyllys 
415699ebb4caSwyllys static KMF_RETURN
415799ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
415899ebb4caSwyllys {
415999ebb4caSwyllys 	KMF_RETURN rv;
416099ebb4caSwyllys 	KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
4161300fdee2SAndy Fiddaman 	const BIGNUM *p, *q, *g, *priv_key;
4162300fdee2SAndy Fiddaman 
4163300fdee2SAndy Fiddaman 	DSA_get0_pqg(dsa, &p, &q, &g);
4164300fdee2SAndy Fiddaman 	DSA_get0_key(dsa, NULL, &priv_key);
416599ebb4caSwyllys 
416699ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
4167300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime)) != KMF_OK)
416899ebb4caSwyllys 		goto cleanup;
416999ebb4caSwyllys 
4170300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->subprime)) != KMF_OK)
417199ebb4caSwyllys 		goto cleanup;
417299ebb4caSwyllys 
4173300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)g, &kmfkey->base)) != KMF_OK)
417499ebb4caSwyllys 		goto cleanup;
417599ebb4caSwyllys 
4176300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)priv_key, &kmfkey->value)) != KMF_OK)
417799ebb4caSwyllys 		goto cleanup;
417899ebb4caSwyllys 
417999ebb4caSwyllys cleanup:
418099ebb4caSwyllys 	if (rv != KMF_OK)
418130a5e8faSwyllys 		kmf_free_raw_key(key);
418299ebb4caSwyllys 	else
418399ebb4caSwyllys 		key->keytype = KMF_DSA;
418499ebb4caSwyllys 
418599ebb4caSwyllys 	/*
418699ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
418799ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
418899ebb4caSwyllys 	 */
418999ebb4caSwyllys 	DSA_free(dsa);
419099ebb4caSwyllys 
419199ebb4caSwyllys 	return (rv);
419299ebb4caSwyllys }
419399ebb4caSwyllys 
419499ebb4caSwyllys static KMF_RETURN
419599ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
41965b3e1433Swyllys     KMF_X509_DER_CERT **certlist, int *ncerts)
419799ebb4caSwyllys {
419899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
41995b3e1433Swyllys 	KMF_X509_DER_CERT *list = (*certlist);
42005b3e1433Swyllys 	KMF_X509_DER_CERT cert;
420199ebb4caSwyllys 	int n = (*ncerts);
420299ebb4caSwyllys 
420399ebb4caSwyllys 	if (list == NULL) {
42045b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
420599ebb4caSwyllys 	} else {
42065b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)realloc(list,
42075b3e1433Swyllys 		    sizeof (KMF_X509_DER_CERT) * (n + 1));
420899ebb4caSwyllys 	}
420999ebb4caSwyllys 
421099ebb4caSwyllys 	if (list == NULL)
421199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
421299ebb4caSwyllys 
42135b3e1433Swyllys 	(void) memset(&cert, 0, sizeof (cert));
42145b3e1433Swyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
421599ebb4caSwyllys 	if (rv == KMF_OK) {
42165b3e1433Swyllys 		int len = 0;
42175b3e1433Swyllys 		/* Get the alias name for the cert if there is one */
42185b3e1433Swyllys 		char *a = (char *)X509_alias_get0(sslcert, &len);
42195b3e1433Swyllys 		if (a != NULL)
42205b3e1433Swyllys 			cert.kmf_private.label = strdup(a);
42215b3e1433Swyllys 		cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
42225b3e1433Swyllys 
422399ebb4caSwyllys 		list[n] = cert;
422499ebb4caSwyllys 		(*ncerts) = n + 1;
422599ebb4caSwyllys 
422699ebb4caSwyllys 		*certlist = list;
422799ebb4caSwyllys 	} else {
422899ebb4caSwyllys 		free(list);
422999ebb4caSwyllys 	}
423099ebb4caSwyllys 
423199ebb4caSwyllys 	return (rv);
423299ebb4caSwyllys }
423399ebb4caSwyllys 
423499ebb4caSwyllys static KMF_RETURN
423599ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
423699ebb4caSwyllys     KMF_RAW_KEY_DATA *newkey, int *nkeys)
423799ebb4caSwyllys {
423899ebb4caSwyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
423999ebb4caSwyllys 	int n = (*nkeys);
424099ebb4caSwyllys 
424199ebb4caSwyllys 	if (list == NULL) {
424299ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
424399ebb4caSwyllys 	} else {
424499ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
424599ebb4caSwyllys 		    sizeof (KMF_RAW_KEY_DATA) * (n + 1));
424699ebb4caSwyllys 	}
424799ebb4caSwyllys 
424899ebb4caSwyllys 	if (list == NULL)
424999ebb4caSwyllys 		return (KMF_ERR_MEMORY);
425099ebb4caSwyllys 
425199ebb4caSwyllys 	list[n] = *newkey;
425299ebb4caSwyllys 	(*nkeys) = n + 1;
425399ebb4caSwyllys 
425499ebb4caSwyllys 	*keylist = list;
425599ebb4caSwyllys 
425699ebb4caSwyllys 	return (KMF_OK);
425799ebb4caSwyllys }
425899ebb4caSwyllys 
425930a5e8faSwyllys static KMF_RETURN
426030a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
426130a5e8faSwyllys {
426230a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
42635b3e1433Swyllys 	X509_ATTRIBUTE *attr;
4264300fdee2SAndy Fiddaman 	RSA *rsa;
4265300fdee2SAndy Fiddaman 	DSA *dsa;
4266300fdee2SAndy Fiddaman 	int loc;
426730a5e8faSwyllys 
426830a5e8faSwyllys 	if (pkey == NULL || key == NULL)
426930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
427030a5e8faSwyllys 	/* Convert SSL key to raw key */
4271300fdee2SAndy Fiddaman 	if ((rsa = EVP_PKEY_get1_RSA(pkey)) != NULL) {
4272300fdee2SAndy Fiddaman 		rv = exportRawRSAKey(rsa, key);
427330a5e8faSwyllys 		if (rv != KMF_OK)
427430a5e8faSwyllys 			return (rv);
4275300fdee2SAndy Fiddaman 	} else if ((dsa = EVP_PKEY_get1_DSA(pkey)) != NULL) {
4276300fdee2SAndy Fiddaman 		rv = exportRawDSAKey(dsa, key);
427730a5e8faSwyllys 		if (rv != KMF_OK)
427830a5e8faSwyllys 			return (rv);
4279300fdee2SAndy Fiddaman 	} else
428030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
4281300fdee2SAndy Fiddaman 
42825b3e1433Swyllys 	/*
42835b3e1433Swyllys 	 * If friendlyName, add it to record.
42845b3e1433Swyllys 	 */
4285300fdee2SAndy Fiddaman 
4286300fdee2SAndy Fiddaman 	if ((loc = EVP_PKEY_get_attr_by_NID(pkey,
4287300fdee2SAndy Fiddaman 	    NID_friendlyName, -1)) != -1 &&
4288300fdee2SAndy Fiddaman 	    (attr = EVP_PKEY_get_attr(pkey, loc))) {
42895b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
4290300fdee2SAndy Fiddaman 		int numattr = X509_ATTRIBUTE_count(attr);
4291300fdee2SAndy Fiddaman 		if (numattr > 0) {
4292300fdee2SAndy Fiddaman 			ty = X509_ATTRIBUTE_get0_type(attr, 0);
42935b3e1433Swyllys 		}
42945b3e1433Swyllys 		if (ty != NULL) {
429570f9559bSTheo Schlossnagle 			key->label = OPENSSL_uni2asc(ty->value.bmpstring->data,
429670f9559bSTheo Schlossnagle 			    ty->value.bmpstring->length);
42975b3e1433Swyllys 		}
42985b3e1433Swyllys 	} else {
42995b3e1433Swyllys 		key->label = NULL;
43005b3e1433Swyllys 	}
43015b3e1433Swyllys 
43025b3e1433Swyllys 	/*
43035b3e1433Swyllys 	 * If KeyID, add it to record as a KMF_DATA object.
43045b3e1433Swyllys 	 */
4305300fdee2SAndy Fiddaman 	if ((loc = EVP_PKEY_get_attr_by_NID(pkey,
4306300fdee2SAndy Fiddaman 	    NID_localKeyID, -1)) != -1 &&
4307300fdee2SAndy Fiddaman 	    (attr = EVP_PKEY_get_attr(pkey, loc)) != NULL) {
43085b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
4309300fdee2SAndy Fiddaman 		int numattr = X509_ATTRIBUTE_count(attr);
4310300fdee2SAndy Fiddaman 		if (numattr > 0)
4311300fdee2SAndy Fiddaman 			ty = X509_ATTRIBUTE_get0_type(attr, 0);
43125b3e1433Swyllys 		key->id.Data = (uchar_t *)malloc(
43135b3e1433Swyllys 		    ty->value.octet_string->length);
43145b3e1433Swyllys 		if (key->id.Data == NULL)
43155b3e1433Swyllys 			return (KMF_ERR_MEMORY);
43165b3e1433Swyllys 		(void) memcpy(key->id.Data, ty->value.octet_string->data,
43175b3e1433Swyllys 		    ty->value.octet_string->length);
43185b3e1433Swyllys 		key->id.Length = ty->value.octet_string->length;
43195b3e1433Swyllys 	} else {
43205b3e1433Swyllys 		(void) memset(&key->id, 0, sizeof (KMF_DATA));
43215b3e1433Swyllys 	}
432230a5e8faSwyllys 
432330a5e8faSwyllys 	return (rv);
432430a5e8faSwyllys }
432599ebb4caSwyllys 
432699ebb4caSwyllys static KMF_RETURN
432799ebb4caSwyllys convertPK12Objects(
432899ebb4caSwyllys 	KMF_HANDLE *kmfh,
43295b3e1433Swyllys 	STACK_OF(EVP_PKEY) *sslkeys,
43305b3e1433Swyllys 	STACK_OF(X509) *sslcert,
43315b3e1433Swyllys 	STACK_OF(X509) *sslcacerts,
433299ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
43335b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
433499ebb4caSwyllys {
433599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
433699ebb4caSwyllys 	KMF_RAW_KEY_DATA key;
433799ebb4caSwyllys 	int i;
433899ebb4caSwyllys 
43395b3e1433Swyllys 	for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
43405b3e1433Swyllys 		EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
43415b3e1433Swyllys 		rv = convertToRawKey(pkey, &key);
434230a5e8faSwyllys 		if (rv == KMF_OK)
434399ebb4caSwyllys 			rv = add_key_to_list(keylist, &key, nkeys);
434430a5e8faSwyllys 
434599ebb4caSwyllys 		if (rv != KMF_OK)
434699ebb4caSwyllys 			return (rv);
434799ebb4caSwyllys 	}
434899ebb4caSwyllys 
434999ebb4caSwyllys 	/* Now add the certificate to the certlist */
43505b3e1433Swyllys 	for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
43515b3e1433Swyllys 		X509 *cert = sk_X509_value(sslcert, i);
43525b3e1433Swyllys 		rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
435399ebb4caSwyllys 		if (rv != KMF_OK)
435499ebb4caSwyllys 			return (rv);
435599ebb4caSwyllys 	}
435699ebb4caSwyllys 
435799ebb4caSwyllys 	/* Also add any included CA certs to the list */
435871593db2Swyllys 	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
435999ebb4caSwyllys 		X509 *c;
436099ebb4caSwyllys 		/*
436199ebb4caSwyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
436299ebb4caSwyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
436399ebb4caSwyllys 		 * Lint is complaining about the embedded casting, and
436499ebb4caSwyllys 		 * to fix it, you need to fix openssl header files.
436599ebb4caSwyllys 		 */
436699ebb4caSwyllys 		c = sk_X509_value(sslcacerts, i);
436799ebb4caSwyllys 
436899ebb4caSwyllys 		/* Now add the ca cert to the certlist */
436999ebb4caSwyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
437099ebb4caSwyllys 		if (rv != KMF_OK)
437199ebb4caSwyllys 			return (rv);
437299ebb4caSwyllys 	}
437399ebb4caSwyllys 	return (rv);
437499ebb4caSwyllys }
437599ebb4caSwyllys 
437699ebb4caSwyllys KMF_RETURN
4377*4942e222SAndy Fiddaman openssl_import_objects(KMF_HANDLE *kmfh, char *filename, KMF_CREDENTIAL *cred,
43785b3e1433Swyllys     KMF_X509_DER_CERT **certlist, int *ncerts,
437999ebb4caSwyllys     KMF_RAW_KEY_DATA **keylist, int *nkeys)
438099ebb4caSwyllys {
438199ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
438230a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
438330a5e8faSwyllys 	BIO		*bio = NULL;
43845b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*privkeys = NULL;
43855b3e1433Swyllys 	STACK_OF(X509)		*certs = NULL;
438699ebb4caSwyllys 	STACK_OF(X509)		*cacerts = NULL;
438799ebb4caSwyllys 
438830a5e8faSwyllys 	/*
438930a5e8faSwyllys 	 * auto-detect the file format, regardless of what
439030a5e8faSwyllys 	 * the 'format' parameters in the params say.
439130a5e8faSwyllys 	 */
439230a5e8faSwyllys 	rv = kmf_get_file_format(filename, &format);
439330a5e8faSwyllys 	if (rv != KMF_OK) {
439430a5e8faSwyllys 		return (rv);
439530a5e8faSwyllys 	}
439630a5e8faSwyllys 
439730a5e8faSwyllys 	/* This function only works for PEM or PKCS#12 files */
439830a5e8faSwyllys 	if (format != KMF_FORMAT_PEM &&
439930a5e8faSwyllys 	    format != KMF_FORMAT_PEM_KEYPAIR &&
440030a5e8faSwyllys 	    format != KMF_FORMAT_PKCS12)
440130a5e8faSwyllys 		return (KMF_ERR_ENCODING);
440230a5e8faSwyllys 
440330a5e8faSwyllys 	*certlist = NULL;
440430a5e8faSwyllys 	*keylist = NULL;
440530a5e8faSwyllys 	*ncerts = 0;
440630a5e8faSwyllys 	*nkeys = 0;
440730a5e8faSwyllys 
440830a5e8faSwyllys 	if (format == KMF_FORMAT_PKCS12) {
440999ebb4caSwyllys 		bio = BIO_new_file(filename, "rb");
441099ebb4caSwyllys 		if (bio == NULL) {
441199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
441299ebb4caSwyllys 			rv = KMF_ERR_OPEN_FILE;
441399ebb4caSwyllys 			goto end;
441499ebb4caSwyllys 		}
441599ebb4caSwyllys 
441634acef67Swyllys 		rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
44175b3e1433Swyllys 		    (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
441899ebb4caSwyllys 
441999ebb4caSwyllys 		if (rv  == KMF_OK)
442099ebb4caSwyllys 			/* Convert keys and certs to exportable format */
44215b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
442299ebb4caSwyllys 			    keylist, nkeys, certlist, ncerts);
442330a5e8faSwyllys 	} else {
44245b3e1433Swyllys 		EVP_PKEY *pkey;
44255b3e1433Swyllys 		KMF_DATA *certdata = NULL;
44265b3e1433Swyllys 		KMF_X509_DER_CERT *kmfcerts = NULL;
44275b3e1433Swyllys 		int i;
442830a5e8faSwyllys 		rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
442934acef67Swyllys 		    (uchar_t *)cred->cred, (uint32_t)cred->credlen,
44305b3e1433Swyllys 		    &pkey, &certdata, ncerts);
443171593db2Swyllys 
443271593db2Swyllys 		/* Reached end of import file? */
44335b3e1433Swyllys 		if (rv == KMF_OK && pkey != NULL) {
44345b3e1433Swyllys 			privkeys = sk_EVP_PKEY_new_null();
44355b3e1433Swyllys 			if (privkeys == NULL) {
44365b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
44375b3e1433Swyllys 				goto end;
44385b3e1433Swyllys 			}
44395b3e1433Swyllys 			(void) sk_EVP_PKEY_push(privkeys, pkey);
44405b3e1433Swyllys 			/* convert the certificate list here */
44415b3e1433Swyllys 			if (*ncerts > 0 && certlist != NULL) {
4442e65e5c2dSWyllys Ingersoll 				kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
44435b3e1433Swyllys 				    sizeof (KMF_X509_DER_CERT));
44445b3e1433Swyllys 				if (kmfcerts == NULL) {
44455b3e1433Swyllys 					rv = KMF_ERR_MEMORY;
44465b3e1433Swyllys 					goto end;
44475b3e1433Swyllys 				}
44485b3e1433Swyllys 				for (i = 0; i < *ncerts; i++) {
44495b3e1433Swyllys 					kmfcerts[i].certificate = certdata[i];
44505b3e1433Swyllys 					kmfcerts[i].kmf_private.keystore_type =
44515b3e1433Swyllys 					    KMF_KEYSTORE_OPENSSL;
44525b3e1433Swyllys 				}
44535b3e1433Swyllys 				*certlist = kmfcerts;
44545b3e1433Swyllys 			}
44555b3e1433Swyllys 			/*
44565b3e1433Swyllys 			 * Convert keys to exportable format, the certs
44575b3e1433Swyllys 			 * are already OK.
44585b3e1433Swyllys 			 */
44595b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
446071593db2Swyllys 			    keylist, nkeys, NULL, NULL);
446130a5e8faSwyllys 		}
44625b3e1433Swyllys 	}
446371593db2Swyllys end:
446430a5e8faSwyllys 	if (bio != NULL)
446599ebb4caSwyllys 		(void) BIO_free(bio);
446699ebb4caSwyllys 
44675b3e1433Swyllys 	if (privkeys)
44685b3e1433Swyllys 		sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
44695b3e1433Swyllys 	if (certs)
44705b3e1433Swyllys 		sk_X509_pop_free(certs, X509_free);
447130a5e8faSwyllys 	if (cacerts)
44725b3e1433Swyllys 		sk_X509_pop_free(cacerts, X509_free);
447330a5e8faSwyllys 
447499ebb4caSwyllys 	return (rv);
447599ebb4caSwyllys }
447699ebb4caSwyllys 
447799ebb4caSwyllys static KMF_RETURN
447899ebb4caSwyllys create_deskey(DES_cblock **deskey)
447999ebb4caSwyllys {
448099ebb4caSwyllys 	DES_cblock *key;
448199ebb4caSwyllys 
448299ebb4caSwyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
448399ebb4caSwyllys 	if (key == NULL) {
448499ebb4caSwyllys 		return (KMF_ERR_MEMORY);
448599ebb4caSwyllys 	}
448699ebb4caSwyllys 
448799ebb4caSwyllys 	if (DES_random_key(key) == 0) {
448899ebb4caSwyllys 		free(key);
448999ebb4caSwyllys 		return (KMF_ERR_KEYGEN_FAILED);
449099ebb4caSwyllys 	}
449199ebb4caSwyllys 
449299ebb4caSwyllys 	*deskey = key;
449399ebb4caSwyllys 	return (KMF_OK);
449499ebb4caSwyllys }
449599ebb4caSwyllys 
449699ebb4caSwyllys #define	KEYGEN_RETRY 3
449799ebb4caSwyllys #define	DES3_KEY_SIZE 24
449899ebb4caSwyllys 
449999ebb4caSwyllys static KMF_RETURN
450099ebb4caSwyllys create_des3key(unsigned char **des3key)
450199ebb4caSwyllys {
450299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
450399ebb4caSwyllys 	DES_cblock *deskey1 = NULL;
450499ebb4caSwyllys 	DES_cblock *deskey2 = NULL;
450599ebb4caSwyllys 	DES_cblock *deskey3 = NULL;
450699ebb4caSwyllys 	unsigned char *newkey = NULL;
450799ebb4caSwyllys 	int retry;
450899ebb4caSwyllys 
450999ebb4caSwyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
451099ebb4caSwyllys 		return (KMF_ERR_MEMORY);
451199ebb4caSwyllys 	}
451299ebb4caSwyllys 
451399ebb4caSwyllys 	/* create the 1st DES key */
451499ebb4caSwyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
451599ebb4caSwyllys 		goto out;
451699ebb4caSwyllys 	}
451799ebb4caSwyllys 
451899ebb4caSwyllys 	/*
451999ebb4caSwyllys 	 * Create the 2nd DES key and make sure its value is different
452099ebb4caSwyllys 	 * from the 1st DES key.
452199ebb4caSwyllys 	 */
452299ebb4caSwyllys 	retry = 0;
452399ebb4caSwyllys 	do {
452499ebb4caSwyllys 		if (deskey2 != NULL) {
452599ebb4caSwyllys 			free(deskey2);
452699ebb4caSwyllys 			deskey2 = NULL;
452799ebb4caSwyllys 		}
452899ebb4caSwyllys 
452999ebb4caSwyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
453099ebb4caSwyllys 			goto out;
453199ebb4caSwyllys 		}
453299ebb4caSwyllys 
453399ebb4caSwyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
453499ebb4caSwyllys 		    == 0) {
453599ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
453699ebb4caSwyllys 			retry++;
453799ebb4caSwyllys 		}
453899ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
453999ebb4caSwyllys 
454099ebb4caSwyllys 	if (ret != KMF_OK) {
454199ebb4caSwyllys 		goto out;
454299ebb4caSwyllys 	}
454399ebb4caSwyllys 
454499ebb4caSwyllys 	/*
454599ebb4caSwyllys 	 * Create the 3rd DES key and make sure its value is different
454699ebb4caSwyllys 	 * from the 2nd DES key.
454799ebb4caSwyllys 	 */
454899ebb4caSwyllys 	retry = 0;
454999ebb4caSwyllys 	do {
455099ebb4caSwyllys 		if (deskey3 != NULL) {
455199ebb4caSwyllys 			free(deskey3);
455299ebb4caSwyllys 			deskey3 = NULL;
455399ebb4caSwyllys 		}
455499ebb4caSwyllys 
455599ebb4caSwyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
455699ebb4caSwyllys 			goto out;
455799ebb4caSwyllys 		}
455899ebb4caSwyllys 
455999ebb4caSwyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
456099ebb4caSwyllys 		    == 0) {
456199ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
456299ebb4caSwyllys 			retry++;
456399ebb4caSwyllys 		}
456499ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
456599ebb4caSwyllys 
456699ebb4caSwyllys 	if (ret != KMF_OK) {
456799ebb4caSwyllys 		goto out;
456899ebb4caSwyllys 	}
456999ebb4caSwyllys 
457099ebb4caSwyllys 	/* Concatenate 3 DES keys into a DES3 key */
457199ebb4caSwyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
457299ebb4caSwyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
457399ebb4caSwyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
457499ebb4caSwyllys 	*des3key = newkey;
457599ebb4caSwyllys 
457699ebb4caSwyllys out:
457799ebb4caSwyllys 	if (deskey1 != NULL)
457899ebb4caSwyllys 		free(deskey1);
457999ebb4caSwyllys 
458099ebb4caSwyllys 	if (deskey2 != NULL)
458199ebb4caSwyllys 		free(deskey2);
458299ebb4caSwyllys 
458399ebb4caSwyllys 	if (deskey3 != NULL)
458499ebb4caSwyllys 		free(deskey3);
458599ebb4caSwyllys 
458699ebb4caSwyllys 	if (ret != KMF_OK && newkey != NULL)
458799ebb4caSwyllys 		free(newkey);
458899ebb4caSwyllys 
458999ebb4caSwyllys 	return (ret);
459099ebb4caSwyllys }
459199ebb4caSwyllys 
459299ebb4caSwyllys KMF_RETURN
4593*4942e222SAndy Fiddaman OpenSSL_CreateSymKey(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
459499ebb4caSwyllys {
459599ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
459699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
459799ebb4caSwyllys 	char *fullpath = NULL;
459899ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
459999ebb4caSwyllys 	DES_cblock *deskey = NULL;
460099ebb4caSwyllys 	unsigned char *des3key = NULL;
460199ebb4caSwyllys 	unsigned char *random = NULL;
460299ebb4caSwyllys 	int fd = -1;
460330a5e8faSwyllys 	KMF_KEY_HANDLE *symkey;
460430a5e8faSwyllys 	KMF_KEY_ALG keytype;
460530a5e8faSwyllys 	uint32_t keylen;
460630a5e8faSwyllys 	uint32_t keylen_size = sizeof (keylen);
460730a5e8faSwyllys 	char *dirpath;
460830a5e8faSwyllys 	char *keyfile;
460999ebb4caSwyllys 
461099ebb4caSwyllys 	if (kmfh == NULL)
461199ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
461299ebb4caSwyllys 
461330a5e8faSwyllys 	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
461430a5e8faSwyllys 	if (symkey == NULL)
461599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
461699ebb4caSwyllys 
461730a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
461830a5e8faSwyllys 
461930a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
462030a5e8faSwyllys 	if (keyfile == NULL)
462130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
462230a5e8faSwyllys 
462330a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
462430a5e8faSwyllys 	    (void *)&keytype, NULL);
462530a5e8faSwyllys 	if (ret != KMF_OK)
462630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
462730a5e8faSwyllys 
462830a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
462930a5e8faSwyllys 	    &keylen, &keylen_size);
463030a5e8faSwyllys 	if (ret == KMF_ERR_ATTR_NOT_FOUND &&
463130a5e8faSwyllys 	    (keytype == KMF_DES || keytype == KMF_DES3))
463230a5e8faSwyllys 		/* keylength is not required for DES and 3DES */
463330a5e8faSwyllys 		ret = KMF_OK;
463430a5e8faSwyllys 	if (ret != KMF_OK)
463530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
463630a5e8faSwyllys 
463730a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
463899ebb4caSwyllys 	if (fullpath == NULL)
463999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
464099ebb4caSwyllys 
464199ebb4caSwyllys 	/* If the requested file exists, return an error */
464230a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
464399ebb4caSwyllys 		free(fullpath);
464499ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
464599ebb4caSwyllys 	}
464699ebb4caSwyllys 
464799ebb4caSwyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
464899ebb4caSwyllys 	if (fd == -1) {
464999ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
465099ebb4caSwyllys 		goto out;
465199ebb4caSwyllys 	}
465299ebb4caSwyllys 
465399ebb4caSwyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
465499ebb4caSwyllys 	if (rkey == NULL) {
465599ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
465699ebb4caSwyllys 		goto out;
465799ebb4caSwyllys 	}
465899ebb4caSwyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
465999ebb4caSwyllys 
466030a5e8faSwyllys 	if (keytype == KMF_DES) {
466199ebb4caSwyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
466299ebb4caSwyllys 			goto out;
466399ebb4caSwyllys 		}
466499ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)deskey;
466599ebb4caSwyllys 		rkey->keydata.len = 8;
466699ebb4caSwyllys 
466799ebb4caSwyllys 		symkey->keyalg = KMF_DES;
466899ebb4caSwyllys 
466930a5e8faSwyllys 	} else if (keytype == KMF_DES3) {
467099ebb4caSwyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
467199ebb4caSwyllys 			goto out;
467299ebb4caSwyllys 		}
467399ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)des3key;
467499ebb4caSwyllys 		rkey->keydata.len = DES3_KEY_SIZE;
467599ebb4caSwyllys 		symkey->keyalg = KMF_DES3;
46769b37d296Swyllys 
467730a5e8faSwyllys 	} else if (keytype == KMF_AES || keytype == KMF_RC4 ||
467830a5e8faSwyllys 	    keytype == KMF_GENERIC_SECRET) {
467999ebb4caSwyllys 		int bytes;
468099ebb4caSwyllys 
468130a5e8faSwyllys 		if (keylen % 8 != 0) {
468299ebb4caSwyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
468399ebb4caSwyllys 			goto out;
468499ebb4caSwyllys 		}
468599ebb4caSwyllys 
468630a5e8faSwyllys 		if (keytype == KMF_AES) {
468730a5e8faSwyllys 			if (keylen != 128 &&
468830a5e8faSwyllys 			    keylen != 192 &&
468930a5e8faSwyllys 			    keylen != 256) {
469099ebb4caSwyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
469199ebb4caSwyllys 				goto out;
469299ebb4caSwyllys 			}
469399ebb4caSwyllys 		}
469499ebb4caSwyllys 
469530a5e8faSwyllys 		bytes = keylen/8;
469699ebb4caSwyllys 		random = malloc(bytes);
469799ebb4caSwyllys 		if (random == NULL) {
469899ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
469999ebb4caSwyllys 			goto out;
470099ebb4caSwyllys 		}
470199ebb4caSwyllys 		if (RAND_bytes(random, bytes) != 1) {
470299ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
470399ebb4caSwyllys 			goto out;
470499ebb4caSwyllys 		}
470599ebb4caSwyllys 
470699ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)random;
470799ebb4caSwyllys 		rkey->keydata.len = bytes;
470830a5e8faSwyllys 		symkey->keyalg = keytype;
470999ebb4caSwyllys 
471099ebb4caSwyllys 	} else {
471199ebb4caSwyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
471299ebb4caSwyllys 		goto out;
471399ebb4caSwyllys 	}
471499ebb4caSwyllys 
471599ebb4caSwyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
471699ebb4caSwyllys 
471799ebb4caSwyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
471899ebb4caSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
471999ebb4caSwyllys 	symkey->keylabel = (char *)fullpath;
472099ebb4caSwyllys 	symkey->israw = TRUE;
472199ebb4caSwyllys 	symkey->keyp = rkey;
472299ebb4caSwyllys 
472399ebb4caSwyllys out:
472499ebb4caSwyllys 	if (fd != -1)
472599ebb4caSwyllys 		(void) close(fd);
472699ebb4caSwyllys 
472799ebb4caSwyllys 	if (ret != KMF_OK && fullpath != NULL) {
472899ebb4caSwyllys 		free(fullpath);
472999ebb4caSwyllys 	}
473099ebb4caSwyllys 	if (ret != KMF_OK) {
473130a5e8faSwyllys 		kmf_free_raw_sym_key(rkey);
473299ebb4caSwyllys 		symkey->keyp = NULL;
473399ebb4caSwyllys 		symkey->keyalg = KMF_KEYALG_NONE;
473499ebb4caSwyllys 	}
473599ebb4caSwyllys 
473699ebb4caSwyllys 	return (ret);
473799ebb4caSwyllys }
473899ebb4caSwyllys 
473999ebb4caSwyllys /*
474099ebb4caSwyllys  * Check a file to see if it is a CRL file with PEM or DER format.
474199ebb4caSwyllys  * If success, return its format in the "pformat" argument.
474299ebb4caSwyllys  */
474399ebb4caSwyllys KMF_RETURN
474499ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
474599ebb4caSwyllys {
474699ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
474799ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
474899ebb4caSwyllys 	BIO		*bio = NULL;
474999ebb4caSwyllys 	X509_CRL	*xcrl = NULL;
475099ebb4caSwyllys 
475199ebb4caSwyllys 	if (filename == NULL) {
475299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
475399ebb4caSwyllys 	}
475499ebb4caSwyllys 
475599ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
475699ebb4caSwyllys 	if (bio == NULL)	{
475799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
475899ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
475999ebb4caSwyllys 		goto out;
476099ebb4caSwyllys 	}
476199ebb4caSwyllys 
476299ebb4caSwyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
476399ebb4caSwyllys 		*pformat = KMF_FORMAT_PEM;
476499ebb4caSwyllys 		goto out;
476599ebb4caSwyllys 	}
476699ebb4caSwyllys 	(void) BIO_free(bio);
476799ebb4caSwyllys 
476899ebb4caSwyllys 	/*
476999ebb4caSwyllys 	 * Now try to read it as raw DER data.
477099ebb4caSwyllys 	 */
477199ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
477299ebb4caSwyllys 	if (bio == NULL)	{
477399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
477499ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
477599ebb4caSwyllys 		goto out;
477699ebb4caSwyllys 	}
477799ebb4caSwyllys 
477899ebb4caSwyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
477999ebb4caSwyllys 		*pformat = KMF_FORMAT_ASN1;
478099ebb4caSwyllys 	} else {
478199ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
478299ebb4caSwyllys 	}
478399ebb4caSwyllys 
478499ebb4caSwyllys out:
478599ebb4caSwyllys 	if (bio != NULL)
478699ebb4caSwyllys 		(void) BIO_free(bio);
478799ebb4caSwyllys 
478899ebb4caSwyllys 	if (xcrl != NULL)
478999ebb4caSwyllys 		X509_CRL_free(xcrl);
479099ebb4caSwyllys 
479199ebb4caSwyllys 	return (ret);
479299ebb4caSwyllys }
479399ebb4caSwyllys 
479499ebb4caSwyllys KMF_RETURN
479599ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
479699ebb4caSwyllys     KMF_RAW_SYM_KEY *rkey)
479799ebb4caSwyllys {
479899ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
479999ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
480099ebb4caSwyllys 	KMF_DATA	keyvalue;
480199ebb4caSwyllys 
480299ebb4caSwyllys 	if (kmfh == NULL)
480399ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
480499ebb4caSwyllys 
480599ebb4caSwyllys 	if (symkey == NULL || rkey == NULL)
480699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
480799ebb4caSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
480899ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
480999ebb4caSwyllys 
481099ebb4caSwyllys 	if (symkey->israw) {
481199ebb4caSwyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
481299ebb4caSwyllys 
481399ebb4caSwyllys 		if (rawkey == NULL ||
481499ebb4caSwyllys 		    rawkey->keydata.val == NULL ||
481599ebb4caSwyllys 		    rawkey->keydata.len == 0)
481699ebb4caSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
481799ebb4caSwyllys 
481899ebb4caSwyllys 		rkey->keydata.len = rawkey->keydata.len;
481999ebb4caSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
482099ebb4caSwyllys 			return (KMF_ERR_MEMORY);
482199ebb4caSwyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
482299ebb4caSwyllys 		    rkey->keydata.len);
482399ebb4caSwyllys 	} else {
482430a5e8faSwyllys 		rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
482599ebb4caSwyllys 		if (rv != KMF_OK)
482699ebb4caSwyllys 			return (rv);
482799ebb4caSwyllys 		rkey->keydata.len = keyvalue.Length;
482899ebb4caSwyllys 		rkey->keydata.val = keyvalue.Data;
482999ebb4caSwyllys 	}
483099ebb4caSwyllys 
483199ebb4caSwyllys 	return (rv);
483299ebb4caSwyllys }
483302744e81Swyllys 
483402744e81Swyllys /*
483530a5e8faSwyllys  * substitute for the unsafe access(2) function.
483630a5e8faSwyllys  * If the file in question already exists, return 1.
483730a5e8faSwyllys  * else 0.  If an error occurs during testing (other
483830a5e8faSwyllys  * than EEXIST), return -1.
483930a5e8faSwyllys  */
484030a5e8faSwyllys static int
484130a5e8faSwyllys test_for_file(char *filename, mode_t mode)
484230a5e8faSwyllys {
484330a5e8faSwyllys 	int fd;
484430a5e8faSwyllys 
484530a5e8faSwyllys 	/*
484630a5e8faSwyllys 	 * Try to create the file with the EXCL flag.
484730a5e8faSwyllys 	 * The call should fail if the file exists.
484830a5e8faSwyllys 	 */
484930a5e8faSwyllys 	fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
485030a5e8faSwyllys 	if (fd == -1 && errno == EEXIST)
485130a5e8faSwyllys 		return (1);
485230a5e8faSwyllys 	else if (fd == -1) /* some other error */
485330a5e8faSwyllys 		return (-1);
485430a5e8faSwyllys 
485530a5e8faSwyllys 	/* The file did NOT exist.  Delete the testcase. */
485630a5e8faSwyllys 	(void) close(fd);
485730a5e8faSwyllys 	(void) unlink(filename);
485830a5e8faSwyllys 	return (0);
485930a5e8faSwyllys }
486030a5e8faSwyllys 
486130a5e8faSwyllys KMF_RETURN
4862*4942e222SAndy Fiddaman OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
486330a5e8faSwyllys {
486430a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
486530a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
486630a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
486730a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
486830a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
486930a5e8faSwyllys 	KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
487030a5e8faSwyllys 	KMF_CREDENTIAL cred = { NULL, 0 };
487130a5e8faSwyllys 	BIO *out = NULL;
487230a5e8faSwyllys 	int keys = 0;
487330a5e8faSwyllys 	char *fullpath = NULL;
487430a5e8faSwyllys 	char *keyfile = NULL;
487530a5e8faSwyllys 	char *dirpath = NULL;
487630a5e8faSwyllys 
487730a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
487830a5e8faSwyllys 	if (pubkey != NULL)
487930a5e8faSwyllys 		keys++;
488030a5e8faSwyllys 
488130a5e8faSwyllys 	prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
488230a5e8faSwyllys 	if (prikey != NULL)
488330a5e8faSwyllys 		keys++;
488430a5e8faSwyllys 
488530a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
488630a5e8faSwyllys 	if (rawkey != NULL)
488730a5e8faSwyllys 		keys++;
488830a5e8faSwyllys 
488930a5e8faSwyllys 	/*
489030a5e8faSwyllys 	 * Exactly 1 type of key must be passed to this function.
489130a5e8faSwyllys 	 */
489230a5e8faSwyllys 	if (keys != 1)
489330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
489430a5e8faSwyllys 
489530a5e8faSwyllys 	keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
489630a5e8faSwyllys 	    numattr);
489730a5e8faSwyllys 	if (keyfile == NULL)
489830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
489930a5e8faSwyllys 
490030a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
490130a5e8faSwyllys 
490230a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
490330a5e8faSwyllys 
490430a5e8faSwyllys 	/* Once we have the full path, we don't need the pieces */
490530a5e8faSwyllys 	if (fullpath == NULL)
490630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
490730a5e8faSwyllys 
490830a5e8faSwyllys 	/* If the requested file exists, return an error */
490930a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
491030a5e8faSwyllys 		free(fullpath);
491130a5e8faSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
491230a5e8faSwyllys 	}
491330a5e8faSwyllys 
491430a5e8faSwyllys 	rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
491530a5e8faSwyllys 	    &format, NULL);
491630a5e8faSwyllys 	if (rv != KMF_OK)
491730a5e8faSwyllys 		/* format is optional. */
491830a5e8faSwyllys 		rv = KMF_OK;
491930a5e8faSwyllys 
492030a5e8faSwyllys 	/* CRED is not required for OpenSSL files */
492130a5e8faSwyllys 	(void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
492230a5e8faSwyllys 	    &cred, NULL);
492330a5e8faSwyllys 
492430a5e8faSwyllys 	/* Store the private key to the keyfile */
492530a5e8faSwyllys 	out = BIO_new_file(fullpath, "wb");
492630a5e8faSwyllys 	if (out == NULL) {
492730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
492830a5e8faSwyllys 		rv = KMF_ERR_OPEN_FILE;
492930a5e8faSwyllys 		goto end;
493030a5e8faSwyllys 	}
493130a5e8faSwyllys 
493230a5e8faSwyllys 	if (prikey != NULL && prikey->keyp != NULL) {
493330a5e8faSwyllys 		if (prikey->keyalg == KMF_RSA ||
493430a5e8faSwyllys 		    prikey->keyalg == KMF_DSA) {
493530a5e8faSwyllys 			pkey = (EVP_PKEY *)prikey->keyp;
493630a5e8faSwyllys 
493730a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
493830a5e8faSwyllys 			    out, &cred, pkey, TRUE);
493930a5e8faSwyllys 
494030a5e8faSwyllys 			if (rv == KMF_OK && prikey->keylabel == NULL) {
494130a5e8faSwyllys 				prikey->keylabel = strdup(fullpath);
494230a5e8faSwyllys 				if (prikey->keylabel == NULL)
494330a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
494430a5e8faSwyllys 			}
494530a5e8faSwyllys 		}
494630a5e8faSwyllys 	} else if (pubkey != NULL && pubkey->keyp != NULL) {
494730a5e8faSwyllys 		if (pubkey->keyalg == KMF_RSA ||
494830a5e8faSwyllys 		    pubkey->keyalg == KMF_DSA) {
494930a5e8faSwyllys 			pkey = (EVP_PKEY *)pubkey->keyp;
495030a5e8faSwyllys 
495130a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
495230a5e8faSwyllys 			    out, &cred, pkey, FALSE);
495330a5e8faSwyllys 
495430a5e8faSwyllys 			if (rv == KMF_OK && pubkey->keylabel == NULL) {
495530a5e8faSwyllys 				pubkey->keylabel = strdup(fullpath);
495630a5e8faSwyllys 				if (pubkey->keylabel == NULL)
495730a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
495830a5e8faSwyllys 			}
495930a5e8faSwyllys 		}
496030a5e8faSwyllys 	} else if (rawkey != NULL) {
496130a5e8faSwyllys 		if (rawkey->keytype == KMF_RSA) {
496230a5e8faSwyllys 			pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
496330a5e8faSwyllys 		} else if (rawkey->keytype == KMF_DSA) {
496430a5e8faSwyllys 			pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
496530a5e8faSwyllys 		} else {
496630a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
496730a5e8faSwyllys 		}
49685b3e1433Swyllys 		if (pkey != NULL) {
496973cc0e02Swyllys 			KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
497073cc0e02Swyllys 
497173cc0e02Swyllys 			rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
497273cc0e02Swyllys 			    (void *)&kclass, NULL);
497373cc0e02Swyllys 			if (rv != KMF_OK)
497473cc0e02Swyllys 				rv = KMF_OK;
49755b3e1433Swyllys 			rv = ssl_write_key(kmfh, format, out,
497673cc0e02Swyllys 			    &cred, pkey, (kclass == KMF_ASYM_PRI));
49775b3e1433Swyllys 			EVP_PKEY_free(pkey);
49785b3e1433Swyllys 		}
497930a5e8faSwyllys 	}
498030a5e8faSwyllys 
498130a5e8faSwyllys end:
498230a5e8faSwyllys 
498330a5e8faSwyllys 	if (out)
498430a5e8faSwyllys 		(void) BIO_free(out);
498530a5e8faSwyllys 
49865b3e1433Swyllys 
498730a5e8faSwyllys 	if (rv == KMF_OK)
498830a5e8faSwyllys 		(void) chmod(fullpath, 0400);
498930a5e8faSwyllys 
499030a5e8faSwyllys 	free(fullpath);
499130a5e8faSwyllys 	return (rv);
499230a5e8faSwyllys }
499330a5e8faSwyllys 
499430a5e8faSwyllys KMF_RETURN
499530a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
499630a5e8faSwyllys {
499730a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
499830a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
499930a5e8faSwyllys 	X509_CRL *xcrl = NULL;
500030a5e8faSwyllys 	X509 *xcert = NULL;
500130a5e8faSwyllys 	EVP_PKEY *pkey;
500230a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
500330a5e8faSwyllys 	BIO *in = NULL, *out = NULL;
500430a5e8faSwyllys 	int openssl_ret = 0;
500530a5e8faSwyllys 	KMF_ENCODE_FORMAT outformat;
500630a5e8faSwyllys 	boolean_t crlcheck = FALSE;
500730a5e8faSwyllys 	char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
500830a5e8faSwyllys 
500930a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
501030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
501130a5e8faSwyllys 	}
501230a5e8faSwyllys 
501330a5e8faSwyllys 	/* CRL check is optional */
501430a5e8faSwyllys 	(void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
501530a5e8faSwyllys 	    &crlcheck, NULL);
501630a5e8faSwyllys 
501730a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
501830a5e8faSwyllys 	if (crlcheck == B_TRUE && certfile == NULL) {
501930a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
502030a5e8faSwyllys 	}
502130a5e8faSwyllys 
502230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
502330a5e8faSwyllys 	incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
502430a5e8faSwyllys 	outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
502530a5e8faSwyllys 
502630a5e8faSwyllys 	crlfile = get_fullpath(dirpath, incrl);
502730a5e8faSwyllys 
502830a5e8faSwyllys 	if (crlfile == NULL)
502930a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
503030a5e8faSwyllys 
503130a5e8faSwyllys 	outcrlfile = get_fullpath(dirpath, outcrl);
503230a5e8faSwyllys 	if (outcrlfile == NULL)
503330a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
503430a5e8faSwyllys 
503530a5e8faSwyllys 	if (isdir(outcrlfile)) {
503630a5e8faSwyllys 		free(outcrlfile);
503730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
503830a5e8faSwyllys 	}
503930a5e8faSwyllys 
504030a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
504130a5e8faSwyllys 	if (ret != KMF_OK) {
504230a5e8faSwyllys 		free(outcrlfile);
504330a5e8faSwyllys 		return (ret);
504430a5e8faSwyllys 	}
504530a5e8faSwyllys 
504630a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
504730a5e8faSwyllys 	if (in == NULL)	{
504830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
504930a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
505030a5e8faSwyllys 		goto end;
505130a5e8faSwyllys 	}
505230a5e8faSwyllys 
505330a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
505430a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
505530a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
505630a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
505730a5e8faSwyllys 	}
505830a5e8faSwyllys 
505930a5e8faSwyllys 	if (xcrl == NULL) {
506030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
506130a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
506230a5e8faSwyllys 		goto end;
506330a5e8faSwyllys 	}
506430a5e8faSwyllys 
506530a5e8faSwyllys 	/* If bypasscheck is specified, no need to verify. */
506630a5e8faSwyllys 	if (crlcheck == B_FALSE)
506730a5e8faSwyllys 		goto output;
506830a5e8faSwyllys 
506930a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
507030a5e8faSwyllys 	if (ret != KMF_OK)
507130a5e8faSwyllys 		goto end;
507230a5e8faSwyllys 
507330a5e8faSwyllys 	/* Read in the CA cert file and convert to X509 */
507430a5e8faSwyllys 	if (BIO_read_filename(in, certfile) <= 0) {
507530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
507630a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
507730a5e8faSwyllys 		goto end;
507830a5e8faSwyllys 	}
507930a5e8faSwyllys 
508030a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
508130a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
508230a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
508330a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
508430a5e8faSwyllys 	} else {
508530a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
508630a5e8faSwyllys 		goto end;
508730a5e8faSwyllys 	}
508830a5e8faSwyllys 
508930a5e8faSwyllys 	if (xcert == NULL) {
509030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
509130a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
509230a5e8faSwyllys 		goto end;
509330a5e8faSwyllys 	}
509430a5e8faSwyllys 	/* Now get the public key from the CA cert */
509530a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
509630a5e8faSwyllys 	if (pkey == NULL) {
509730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
509830a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
509930a5e8faSwyllys 		goto end;
510030a5e8faSwyllys 	}
510130a5e8faSwyllys 
510230a5e8faSwyllys 	/* Verify the CRL with the CA's public key */
510330a5e8faSwyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
510430a5e8faSwyllys 	EVP_PKEY_free(pkey);
510530a5e8faSwyllys 	if (openssl_ret > 0) {
510630a5e8faSwyllys 		ret = KMF_OK;  /* verify succeed */
510730a5e8faSwyllys 	} else {
510830a5e8faSwyllys 		SET_ERROR(kmfh, openssl_ret);
510930a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
511030a5e8faSwyllys 	}
511130a5e8faSwyllys 
511230a5e8faSwyllys output:
511330a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
511430a5e8faSwyllys 	    &outformat, NULL);
511530a5e8faSwyllys 	if (ret != KMF_OK) {
511630a5e8faSwyllys 		ret = KMF_OK;
511730a5e8faSwyllys 		outformat = KMF_FORMAT_PEM;
511830a5e8faSwyllys 	}
511930a5e8faSwyllys 
512030a5e8faSwyllys 	out = BIO_new_file(outcrlfile, "wb");
512130a5e8faSwyllys 	if (out == NULL) {
512230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
512330a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
512430a5e8faSwyllys 		goto end;
512530a5e8faSwyllys 	}
512630a5e8faSwyllys 
512730a5e8faSwyllys 	if (outformat == KMF_FORMAT_ASN1) {
512830a5e8faSwyllys 		openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
512930a5e8faSwyllys 	} else if (outformat == KMF_FORMAT_PEM) {
513030a5e8faSwyllys 		openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
513130a5e8faSwyllys 	} else {
513230a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
513330a5e8faSwyllys 		goto end;
513430a5e8faSwyllys 	}
513530a5e8faSwyllys 
513630a5e8faSwyllys 	if (openssl_ret <= 0) {
513730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
513830a5e8faSwyllys 		ret = KMF_ERR_WRITE_FILE;
513930a5e8faSwyllys 	} else {
514030a5e8faSwyllys 		ret = KMF_OK;
514130a5e8faSwyllys 	}
514230a5e8faSwyllys 
514330a5e8faSwyllys end:
514430a5e8faSwyllys 	if (xcrl != NULL)
514530a5e8faSwyllys 		X509_CRL_free(xcrl);
514630a5e8faSwyllys 
514730a5e8faSwyllys 	if (xcert != NULL)
514830a5e8faSwyllys 		X509_free(xcert);
514930a5e8faSwyllys 
515030a5e8faSwyllys 	if (in != NULL)
515130a5e8faSwyllys 		(void) BIO_free(in);
515230a5e8faSwyllys 
515330a5e8faSwyllys 	if (out != NULL)
515430a5e8faSwyllys 		(void) BIO_free(out);
515530a5e8faSwyllys 
515630a5e8faSwyllys 	if (outcrlfile != NULL)
515730a5e8faSwyllys 		free(outcrlfile);
515830a5e8faSwyllys 
515930a5e8faSwyllys 	return (ret);
516030a5e8faSwyllys }
516130a5e8faSwyllys 
516230a5e8faSwyllys KMF_RETURN
516330a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
516430a5e8faSwyllys {
516530a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
516630a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
516730a5e8faSwyllys 	X509_CRL   *x = NULL;
516830a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
516930a5e8faSwyllys 	char *crlfile = NULL;
517030a5e8faSwyllys 	BIO *in = NULL;
517130a5e8faSwyllys 	BIO *mem = NULL;
517230a5e8faSwyllys 	long len;
517330a5e8faSwyllys 	char *memptr;
517430a5e8faSwyllys 	char *data = NULL;
517530a5e8faSwyllys 	char **crldata;
517630a5e8faSwyllys 	char *crlfilename, *dirpath;
517730a5e8faSwyllys 
517830a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
517930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
518030a5e8faSwyllys 	}
518130a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
518230a5e8faSwyllys 	    attrlist, numattr);
518330a5e8faSwyllys 	if (crlfilename == NULL)
518430a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
518530a5e8faSwyllys 
518630a5e8faSwyllys 	crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
518730a5e8faSwyllys 	    attrlist, numattr);
518830a5e8faSwyllys 
518930a5e8faSwyllys 	if (crldata == NULL)
519030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
519130a5e8faSwyllys 
519230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
519330a5e8faSwyllys 
519430a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
519530a5e8faSwyllys 
519630a5e8faSwyllys 	if (crlfile == NULL)
519730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
519830a5e8faSwyllys 
519930a5e8faSwyllys 	if (isdir(crlfile)) {
520030a5e8faSwyllys 		free(crlfile);
520130a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
520230a5e8faSwyllys 	}
520330a5e8faSwyllys 
520430a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
520530a5e8faSwyllys 	if (ret != KMF_OK) {
520630a5e8faSwyllys 		free(crlfile);
520730a5e8faSwyllys 		return (ret);
520830a5e8faSwyllys 	}
520930a5e8faSwyllys 
521030a5e8faSwyllys 	if (bio_err == NULL)
521130a5e8faSwyllys 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
521230a5e8faSwyllys 
521330a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
521430a5e8faSwyllys 	if (in == NULL)	{
521530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
521630a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
521730a5e8faSwyllys 		goto end;
521830a5e8faSwyllys 	}
521930a5e8faSwyllys 
522030a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
522130a5e8faSwyllys 		x = d2i_X509_CRL_bio(in, NULL);
522230a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
522330a5e8faSwyllys 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
522430a5e8faSwyllys 	}
522530a5e8faSwyllys 
522630a5e8faSwyllys 	if (x == NULL) { /* should not happen */
522730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
522830a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
522930a5e8faSwyllys 		goto end;
523030a5e8faSwyllys 	}
523130a5e8faSwyllys 
523230a5e8faSwyllys 	mem = BIO_new(BIO_s_mem());
523330a5e8faSwyllys 	if (mem == NULL) {
523430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
523530a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
523630a5e8faSwyllys 		goto end;
523730a5e8faSwyllys 	}
523830a5e8faSwyllys 
523930a5e8faSwyllys 	(void) X509_CRL_print(mem, x);
524030a5e8faSwyllys 	len = BIO_get_mem_data(mem, &memptr);
524130a5e8faSwyllys 	if (len <= 0) {
524230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
524330a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
524430a5e8faSwyllys 		goto end;
524530a5e8faSwyllys 	}
524630a5e8faSwyllys 
524730a5e8faSwyllys 	data = malloc(len + 1);
524830a5e8faSwyllys 	if (data == NULL) {
524930a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
525030a5e8faSwyllys 		goto end;
525130a5e8faSwyllys 	}
525230a5e8faSwyllys 
525330a5e8faSwyllys 	(void) memcpy(data, memptr, len);
525430a5e8faSwyllys 	data[len] = '\0';
525530a5e8faSwyllys 	*crldata = data;
525630a5e8faSwyllys 
525730a5e8faSwyllys end:
525830a5e8faSwyllys 	if (x != NULL)
525930a5e8faSwyllys 		X509_CRL_free(x);
526030a5e8faSwyllys 
526130a5e8faSwyllys 	if (crlfile != NULL)
526230a5e8faSwyllys 		free(crlfile);
526330a5e8faSwyllys 
526430a5e8faSwyllys 	if (in != NULL)
526530a5e8faSwyllys 		(void) BIO_free(in);
526630a5e8faSwyllys 
526730a5e8faSwyllys 	if (mem != NULL)
526830a5e8faSwyllys 		(void) BIO_free(mem);
526930a5e8faSwyllys 
527030a5e8faSwyllys 	return (ret);
527130a5e8faSwyllys }
527230a5e8faSwyllys 
527330a5e8faSwyllys KMF_RETURN
527430a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
527530a5e8faSwyllys {
527630a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
527730a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
527830a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
527930a5e8faSwyllys 	char *crlfile = NULL;
528030a5e8faSwyllys 	BIO *in = NULL;
528130a5e8faSwyllys 	char *crlfilename, *dirpath;
528230a5e8faSwyllys 
528330a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
528430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
528530a5e8faSwyllys 	}
528630a5e8faSwyllys 
528730a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
528830a5e8faSwyllys 	    attrlist, numattr);
528930a5e8faSwyllys 
529030a5e8faSwyllys 	if (crlfilename == NULL)
529130a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
529230a5e8faSwyllys 
529330a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
529430a5e8faSwyllys 
529530a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
529630a5e8faSwyllys 
529730a5e8faSwyllys 	if (crlfile == NULL)
529830a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
529930a5e8faSwyllys 
530030a5e8faSwyllys 	if (isdir(crlfile)) {
530130a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
530230a5e8faSwyllys 		goto end;
530330a5e8faSwyllys 	}
530430a5e8faSwyllys 
530530a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
530630a5e8faSwyllys 	if (ret != KMF_OK)
530730a5e8faSwyllys 		goto end;
530830a5e8faSwyllys 
530930a5e8faSwyllys 	if (unlink(crlfile) != 0) {
531030a5e8faSwyllys 		SET_SYS_ERROR(kmfh, errno);
531130a5e8faSwyllys 		ret = KMF_ERR_INTERNAL;
531230a5e8faSwyllys 		goto end;
531330a5e8faSwyllys 	}
531430a5e8faSwyllys 
531530a5e8faSwyllys end:
531630a5e8faSwyllys 	if (in != NULL)
531730a5e8faSwyllys 		(void) BIO_free(in);
531830a5e8faSwyllys 	if (crlfile != NULL)
531930a5e8faSwyllys 		free(crlfile);
532030a5e8faSwyllys 
532130a5e8faSwyllys 	return (ret);
532230a5e8faSwyllys }
532330a5e8faSwyllys 
532430a5e8faSwyllys KMF_RETURN
532530a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
532630a5e8faSwyllys {
532730a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
532830a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
532930a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
533030a5e8faSwyllys 	BIO *in = NULL;
533130a5e8faSwyllys 	X509   *xcert = NULL;
533230a5e8faSwyllys 	X509_CRL   *xcrl = NULL;
533330a5e8faSwyllys 	STACK_OF(X509_REVOKED) *revoke_stack = NULL;
533430a5e8faSwyllys 	X509_REVOKED *revoke;
533530a5e8faSwyllys 	int i;
533630a5e8faSwyllys 	char *crlfilename, *crlfile, *dirpath, *certfile;
533730a5e8faSwyllys 
533830a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
533930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
534030a5e8faSwyllys 	}
534130a5e8faSwyllys 
534230a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
534330a5e8faSwyllys 	    attrlist, numattr);
534430a5e8faSwyllys 
534530a5e8faSwyllys 	if (crlfilename == NULL)
534630a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
534730a5e8faSwyllys 
534830a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
534930a5e8faSwyllys 	if (certfile == NULL)
535030a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
535130a5e8faSwyllys 
535230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
535330a5e8faSwyllys 
535430a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
535530a5e8faSwyllys 
535630a5e8faSwyllys 	if (crlfile == NULL)
535730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
535830a5e8faSwyllys 
535930a5e8faSwyllys 	if (isdir(crlfile)) {
536030a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
536130a5e8faSwyllys 		goto end;
536230a5e8faSwyllys 	}
536330a5e8faSwyllys 
536430a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
536530a5e8faSwyllys 	if (ret != KMF_OK)
536630a5e8faSwyllys 		goto end;
536730a5e8faSwyllys 
536830a5e8faSwyllys 	/* Read the CRL file and load it into a X509_CRL structure */
536930a5e8faSwyllys 	in = BIO_new_file(crlfilename, "rb");
537030a5e8faSwyllys 	if (in == NULL)	{
537130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
537230a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
537330a5e8faSwyllys 		goto end;
537430a5e8faSwyllys 	}
537530a5e8faSwyllys 
537630a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
537730a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
537830a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
537930a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
538030a5e8faSwyllys 	}
538130a5e8faSwyllys 
538230a5e8faSwyllys 	if (xcrl == NULL) {
538330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
538430a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
538530a5e8faSwyllys 		goto end;
538630a5e8faSwyllys 	}
538730a5e8faSwyllys 	(void) BIO_free(in);
538830a5e8faSwyllys 
538930a5e8faSwyllys 	/* Read the Certificate file and load it into a X509 structure */
539030a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
539130a5e8faSwyllys 	if (ret != KMF_OK)
539230a5e8faSwyllys 		goto end;
539330a5e8faSwyllys 
539430a5e8faSwyllys 	in = BIO_new_file(certfile, "rb");
539530a5e8faSwyllys 	if (in == NULL)	{
539630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
539730a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
539830a5e8faSwyllys 		goto end;
539930a5e8faSwyllys 	}
540030a5e8faSwyllys 
540130a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
540230a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
540330a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
540430a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
540530a5e8faSwyllys 	}
540630a5e8faSwyllys 
540730a5e8faSwyllys 	if (xcert == NULL) {
540830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
540930a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
541030a5e8faSwyllys 		goto end;
541130a5e8faSwyllys 	}
541230a5e8faSwyllys 
541330a5e8faSwyllys 	/* Check if the certificate and the CRL have same issuer */
5414300fdee2SAndy Fiddaman 	if (X509_NAME_cmp(X509_get_issuer_name(xcert),
5415300fdee2SAndy Fiddaman 	    X509_CRL_get_issuer(xcrl)) != 0) {
541630a5e8faSwyllys 		ret = KMF_ERR_ISSUER;
541730a5e8faSwyllys 		goto end;
541830a5e8faSwyllys 	}
541930a5e8faSwyllys 
542030a5e8faSwyllys 	/* Check to see if the certificate serial number is revoked */
542130a5e8faSwyllys 	revoke_stack = X509_CRL_get_REVOKED(xcrl);
542230a5e8faSwyllys 	if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
542330a5e8faSwyllys 		/* No revoked certificates in the CRL file */
542430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
542530a5e8faSwyllys 		ret = KMF_ERR_EMPTY_CRL;
542630a5e8faSwyllys 		goto end;
542730a5e8faSwyllys 	}
542830a5e8faSwyllys 
542930a5e8faSwyllys 	for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
543030a5e8faSwyllys 		revoke = sk_X509_REVOKED_value(revoke_stack, i);
5431300fdee2SAndy Fiddaman 		if (ASN1_INTEGER_cmp(X509_get_serialNumber(xcert),
5432300fdee2SAndy Fiddaman 		    X509_REVOKED_get0_serialNumber(revoke)) == 0) {
543330a5e8faSwyllys 			break;
543430a5e8faSwyllys 		}
543530a5e8faSwyllys 	}
543630a5e8faSwyllys 
543730a5e8faSwyllys 	if (i < sk_X509_REVOKED_num(revoke_stack)) {
543830a5e8faSwyllys 		ret = KMF_OK;
543930a5e8faSwyllys 	} else {
544030a5e8faSwyllys 		ret = KMF_ERR_NOT_REVOKED;
544130a5e8faSwyllys 	}
544230a5e8faSwyllys 
544330a5e8faSwyllys end:
544430a5e8faSwyllys 	if (in != NULL)
544530a5e8faSwyllys 		(void) BIO_free(in);
544630a5e8faSwyllys 	if (xcrl != NULL)
544730a5e8faSwyllys 		X509_CRL_free(xcrl);
544830a5e8faSwyllys 	if (xcert != NULL)
544930a5e8faSwyllys 		X509_free(xcert);
545030a5e8faSwyllys 
545130a5e8faSwyllys 	return (ret);
545230a5e8faSwyllys }
545330a5e8faSwyllys 
545430a5e8faSwyllys KMF_RETURN
545530a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
545630a5e8faSwyllys {
545730a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
545830a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
545930a5e8faSwyllys 	BIO		*bcrl = NULL;
546030a5e8faSwyllys 	X509_CRL	*xcrl = NULL;
546130a5e8faSwyllys 	X509		*xcert = NULL;
546230a5e8faSwyllys 	EVP_PKEY	*pkey;
546330a5e8faSwyllys 	int		sslret;
546430a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
546530a5e8faSwyllys 	unsigned char	*p;
546630a5e8faSwyllys 	long		len;
546730a5e8faSwyllys 
546830a5e8faSwyllys 	if (handle == NULL || crlname == NULL || tacert == NULL) {
546930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
547030a5e8faSwyllys 	}
547130a5e8faSwyllys 
547230a5e8faSwyllys 	ret = kmf_get_file_format(crlname, &crl_format);
547330a5e8faSwyllys 	if (ret != KMF_OK)
547430a5e8faSwyllys 		return (ret);
547530a5e8faSwyllys 
547630a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
547730a5e8faSwyllys 	if (bcrl == NULL)	{
547830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
547930a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
548030a5e8faSwyllys 		goto cleanup;
548130a5e8faSwyllys 	}
548230a5e8faSwyllys 
548330a5e8faSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
548430a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
548530a5e8faSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
548630a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
548730a5e8faSwyllys 	} else {
548830a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
548930a5e8faSwyllys 		goto cleanup;
549030a5e8faSwyllys 	}
549130a5e8faSwyllys 
549230a5e8faSwyllys 	if (xcrl == NULL) {
549330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
549430a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
549530a5e8faSwyllys 		goto cleanup;
549630a5e8faSwyllys 	}
549730a5e8faSwyllys 
549830a5e8faSwyllys 	p = tacert->Data;
549930a5e8faSwyllys 	len = tacert->Length;
550030a5e8faSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
550130a5e8faSwyllys 
550230a5e8faSwyllys 	if (xcert == NULL) {
550330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
550430a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
550530a5e8faSwyllys 		goto cleanup;
550630a5e8faSwyllys 	}
550730a5e8faSwyllys 
550830a5e8faSwyllys 	/* Get issuer certificate public key */
550930a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
551030a5e8faSwyllys 	if (pkey == NULL) {
551130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
551230a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
551330a5e8faSwyllys 		goto cleanup;
551430a5e8faSwyllys 	}
551530a5e8faSwyllys 
551630a5e8faSwyllys 	/* Verify CRL signature */
551730a5e8faSwyllys 	sslret = X509_CRL_verify(xcrl, pkey);
551830a5e8faSwyllys 	EVP_PKEY_free(pkey);
551930a5e8faSwyllys 	if (sslret > 0) {
552030a5e8faSwyllys 		ret = KMF_OK;
552130a5e8faSwyllys 	} else {
552230a5e8faSwyllys 		SET_ERROR(kmfh, sslret);
552330a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
552430a5e8faSwyllys 	}
552530a5e8faSwyllys 
552630a5e8faSwyllys cleanup:
552730a5e8faSwyllys 	if (bcrl != NULL)
552830a5e8faSwyllys 		(void) BIO_free(bcrl);
552930a5e8faSwyllys 
553030a5e8faSwyllys 	if (xcrl != NULL)
553130a5e8faSwyllys 		X509_CRL_free(xcrl);
553230a5e8faSwyllys 
553330a5e8faSwyllys 	if (xcert != NULL)
553430a5e8faSwyllys 		X509_free(xcert);
553530a5e8faSwyllys 
553630a5e8faSwyllys 	return (ret);
553730a5e8faSwyllys 
553830a5e8faSwyllys }
553930a5e8faSwyllys 
554030a5e8faSwyllys KMF_RETURN
554130a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
554230a5e8faSwyllys {
554330a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
554430a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
554530a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
554630a5e8faSwyllys 	BIO		*bcrl = NULL;
554730a5e8faSwyllys 	X509_CRL	*xcrl = NULL;
554830a5e8faSwyllys 	int		i;
554930a5e8faSwyllys 
555030a5e8faSwyllys 	if (handle == NULL || crlname == NULL) {
555130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
555230a5e8faSwyllys 	}
555330a5e8faSwyllys 
555430a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlname, &crl_format);
555530a5e8faSwyllys 	if (ret != KMF_OK)
555630a5e8faSwyllys 		return (ret);
555730a5e8faSwyllys 
555830a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
555930a5e8faSwyllys 	if (bcrl == NULL) {
556030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
556130a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
556230a5e8faSwyllys 		goto cleanup;
556330a5e8faSwyllys 	}
556430a5e8faSwyllys 
55655b3e1433Swyllys 	if (crl_format == KMF_FORMAT_ASN1)
556630a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
55675b3e1433Swyllys 	else if (crl_format == KMF_FORMAT_PEM)
556830a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
556930a5e8faSwyllys 
557030a5e8faSwyllys 	if (xcrl == NULL) {
557130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
557230a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
557330a5e8faSwyllys 		goto cleanup;
557430a5e8faSwyllys 	}
5575300fdee2SAndy Fiddaman 	i = X509_cmp_time(X509_CRL_get0_lastUpdate(xcrl), NULL);
557630a5e8faSwyllys 	if (i >= 0) {
557730a5e8faSwyllys 		ret = KMF_ERR_VALIDITY_PERIOD;
557830a5e8faSwyllys 		goto cleanup;
557930a5e8faSwyllys 	}
5580300fdee2SAndy Fiddaman 	if (X509_CRL_get0_nextUpdate(xcrl)) {
5581300fdee2SAndy Fiddaman 		i = X509_cmp_time(X509_CRL_get0_nextUpdate(xcrl), NULL);
558230a5e8faSwyllys 
558330a5e8faSwyllys 		if (i <= 0) {
558430a5e8faSwyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
558530a5e8faSwyllys 			goto cleanup;
558630a5e8faSwyllys 		}
558730a5e8faSwyllys 	}
558830a5e8faSwyllys 
558930a5e8faSwyllys 	ret = KMF_OK;
559030a5e8faSwyllys 
559130a5e8faSwyllys cleanup:
559230a5e8faSwyllys 	if (bcrl != NULL)
559330a5e8faSwyllys 		(void) BIO_free(bcrl);
559430a5e8faSwyllys 
559530a5e8faSwyllys 	if (xcrl != NULL)
559630a5e8faSwyllys 		X509_CRL_free(xcrl);
559730a5e8faSwyllys 
559830a5e8faSwyllys 	return (ret);
559930a5e8faSwyllys }
5600