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.
8300fdee2SAndy Fiddaman  * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
9*553e44ceSAndrew Stormont  * Copyright 2018 RackTop Systems.
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  */
142*553e44ceSAndrew 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 /* LINTED E_STATIC_UNUSED */
155300fdee2SAndy Fiddaman DEFINE_STACK_OF(EVP_PKEY)
156300fdee2SAndy Fiddaman #endif
157300fdee2SAndy Fiddaman 
15899ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX;
15999ebb4caSwyllys static int ssl_initialized = 0;
16030a5e8faSwyllys static BIO *bio_err = NULL;
16130a5e8faSwyllys 
16230a5e8faSwyllys static int
16330a5e8faSwyllys test_for_file(char *, mode_t);
1645b3e1433Swyllys static KMF_RETURN
1655b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *, char *, int,
1665b3e1433Swyllys     STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
1675b3e1433Swyllys 
1685b3e1433Swyllys static KMF_RETURN
1695b3e1433Swyllys local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *,
1705b3e1433Swyllys     int, KMF_KEY_HANDLE *, char *);
1715b3e1433Swyllys 
1725b3e1433Swyllys static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int);
17399ebb4caSwyllys 
17471593db2Swyllys static KMF_RETURN
17530a5e8faSwyllys extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *,
17602744e81Swyllys     CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
17771593db2Swyllys 
17871593db2Swyllys static KMF_RETURN
17930a5e8faSwyllys kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
18030a5e8faSwyllys     char *, KMF_DATA *);
18130a5e8faSwyllys 
18230a5e8faSwyllys static KMF_RETURN
18330a5e8faSwyllys load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
18430a5e8faSwyllys     char *, KMF_DATA **, uint32_t *);
18571593db2Swyllys 
18602744e81Swyllys static KMF_RETURN
18702744e81Swyllys sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
18802744e81Swyllys 
18902744e81Swyllys static EVP_PKEY *
19002744e81Swyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *);
19102744e81Swyllys 
19230a5e8faSwyllys static KMF_RETURN
19330a5e8faSwyllys convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
19430a5e8faSwyllys 
19599ebb4caSwyllys KMF_RETURN
19630a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
19799ebb4caSwyllys 
19899ebb4caSwyllys void
19999ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
20099ebb4caSwyllys 
20199ebb4caSwyllys KMF_RETURN
20230a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
20399ebb4caSwyllys 
20499ebb4caSwyllys KMF_RETURN
20530a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
20699ebb4caSwyllys 
20799ebb4caSwyllys KMF_RETURN
20830a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20930a5e8faSwyllys 
21030a5e8faSwyllys KMF_RETURN
21130a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21299ebb4caSwyllys 
21399ebb4caSwyllys KMF_RETURN
21499ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T,  KMF_KEY_HANDLE *, KMF_DATA *);
21599ebb4caSwyllys 
21699ebb4caSwyllys KMF_RETURN
21799ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
21899ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
21999ebb4caSwyllys 
22099ebb4caSwyllys KMF_RETURN
22130a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22299ebb4caSwyllys 
22399ebb4caSwyllys KMF_RETURN
22430a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22599ebb4caSwyllys 
22699ebb4caSwyllys KMF_RETURN
22730a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22899ebb4caSwyllys 
22999ebb4caSwyllys KMF_RETURN
23030a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23199ebb4caSwyllys 
23299ebb4caSwyllys KMF_RETURN
23330a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23499ebb4caSwyllys 
23599ebb4caSwyllys KMF_RETURN
23699ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
23799ebb4caSwyllys 	KMF_PRINTABLE_ITEM, char *);
23899ebb4caSwyllys 
23999ebb4caSwyllys KMF_RETURN
24099ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
24199ebb4caSwyllys 
24299ebb4caSwyllys KMF_RETURN
24330a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24499ebb4caSwyllys 
24599ebb4caSwyllys KMF_RETURN
24699ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
24799ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
24899ebb4caSwyllys 
24999ebb4caSwyllys KMF_RETURN
25030a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25199ebb4caSwyllys 
25299ebb4caSwyllys KMF_RETURN
25330a5e8faSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25499ebb4caSwyllys 
25599ebb4caSwyllys KMF_RETURN
25630a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25799ebb4caSwyllys 
25899ebb4caSwyllys KMF_RETURN
25930a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
26099ebb4caSwyllys 
26199ebb4caSwyllys KMF_RETURN
26230a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
26399ebb4caSwyllys 
26499ebb4caSwyllys KMF_RETURN
26599ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
26699ebb4caSwyllys 
26799ebb4caSwyllys KMF_RETURN
26830a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
26999ebb4caSwyllys 
27099ebb4caSwyllys KMF_RETURN
27130a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
27299ebb4caSwyllys 
27399ebb4caSwyllys static
27499ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table =
27599ebb4caSwyllys {
27699ebb4caSwyllys 	1,				/* Version */
27799ebb4caSwyllys 	NULL, /* ConfigureKeystore */
27899ebb4caSwyllys 	OpenSSL_FindCert,
27999ebb4caSwyllys 	OpenSSL_FreeKMFCert,
28099ebb4caSwyllys 	OpenSSL_StoreCert,
28199ebb4caSwyllys 	NULL, /* ImportCert */
28299ebb4caSwyllys 	OpenSSL_ImportCRL,
28399ebb4caSwyllys 	OpenSSL_DeleteCert,
28499ebb4caSwyllys 	OpenSSL_DeleteCRL,
28599ebb4caSwyllys 	OpenSSL_CreateKeypair,
28699ebb4caSwyllys 	OpenSSL_FindKey,
28799ebb4caSwyllys 	OpenSSL_EncodePubKeyData,
28899ebb4caSwyllys 	OpenSSL_SignData,
28999ebb4caSwyllys 	OpenSSL_DeleteKey,
29099ebb4caSwyllys 	OpenSSL_ListCRL,
29199ebb4caSwyllys 	NULL,	/* FindCRL */
29299ebb4caSwyllys 	OpenSSL_FindCertInCRL,
29399ebb4caSwyllys 	OpenSSL_GetErrorString,
29430a5e8faSwyllys 	OpenSSL_FindPrikeyByCert,
29599ebb4caSwyllys 	OpenSSL_DecryptData,
29630a5e8faSwyllys 	OpenSSL_ExportPK12,
29799ebb4caSwyllys 	OpenSSL_CreateSymKey,
29899ebb4caSwyllys 	OpenSSL_GetSymKeyValue,
29999ebb4caSwyllys 	NULL,	/* SetTokenPin */
30030a5e8faSwyllys 	OpenSSL_StoreKey,
30199ebb4caSwyllys 	NULL	/* Finalize */
30299ebb4caSwyllys };
30399ebb4caSwyllys 
304*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
30599ebb4caSwyllys static mutex_t *lock_cs;
30699ebb4caSwyllys static long *lock_count;
30799ebb4caSwyllys 
30899ebb4caSwyllys static void
309a2d4930dSDan OpenSolaris Anderson /* ARGSUSED1 */
31099ebb4caSwyllys locking_cb(int mode, int type, char *file, int line)
31199ebb4caSwyllys {
31299ebb4caSwyllys 	if (mode & CRYPTO_LOCK) {
31399ebb4caSwyllys 		(void) mutex_lock(&(lock_cs[type]));
31499ebb4caSwyllys 		lock_count[type]++;
31599ebb4caSwyllys 	} else {
31699ebb4caSwyllys 		(void) mutex_unlock(&(lock_cs[type]));
31799ebb4caSwyllys 	}
31899ebb4caSwyllys }
31999ebb4caSwyllys 
32099ebb4caSwyllys static unsigned long
32199ebb4caSwyllys thread_id()
32299ebb4caSwyllys {
32399ebb4caSwyllys 	return ((unsigned long)thr_self());
32499ebb4caSwyllys }
325*553e44ceSAndrew Stormont #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER */
32699ebb4caSwyllys 
32799ebb4caSwyllys KMF_PLUGIN_FUNCLIST *
32899ebb4caSwyllys KMF_Plugin_Initialize()
32999ebb4caSwyllys {
330*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
33199ebb4caSwyllys 	int i;
332300fdee2SAndy Fiddaman #endif
33399ebb4caSwyllys 
33499ebb4caSwyllys 	(void) mutex_lock(&init_lock);
33599ebb4caSwyllys 	if (!ssl_initialized) {
33699ebb4caSwyllys 		/*
33799ebb4caSwyllys 		 * Add support for extension OIDs that are not yet in the
33899ebb4caSwyllys 		 * openssl default set.
33999ebb4caSwyllys 		 */
34099ebb4caSwyllys 		(void) OBJ_create("2.5.29.30", "nameConstraints",
34199ebb4caSwyllys 		    "X509v3 Name Constraints");
34299ebb4caSwyllys 		(void) OBJ_create("2.5.29.33", "policyMappings",
34399ebb4caSwyllys 		    "X509v3 Policy Mappings");
34499ebb4caSwyllys 		(void) OBJ_create("2.5.29.36", "policyConstraints",
34599ebb4caSwyllys 		    "X509v3 Policy Constraints");
34699ebb4caSwyllys 		(void) OBJ_create("2.5.29.46", "freshestCRL",
34799ebb4caSwyllys 		    "X509v3 Freshest CRL");
34899ebb4caSwyllys 		(void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
34999ebb4caSwyllys 		    "X509v3 Inhibit Any-Policy");
350300fdee2SAndy Fiddaman 
351*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
35299ebb4caSwyllys 		/*
35399ebb4caSwyllys 		 * Set up for thread-safe operation.
354300fdee2SAndy Fiddaman 		 * This is not required for OpenSSL 1.1
35599ebb4caSwyllys 		 */
35699ebb4caSwyllys 		lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
35799ebb4caSwyllys 		if (lock_cs == NULL) {
35899ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
35999ebb4caSwyllys 			return (NULL);
36099ebb4caSwyllys 		}
36199ebb4caSwyllys 
36299ebb4caSwyllys 		lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
36399ebb4caSwyllys 		if (lock_count == NULL) {
36499ebb4caSwyllys 			OPENSSL_free(lock_cs);
36599ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
36699ebb4caSwyllys 			return (NULL);
36799ebb4caSwyllys 		}
36899ebb4caSwyllys 
36999ebb4caSwyllys 		for (i = 0; i < CRYPTO_num_locks(); i++) {
37099ebb4caSwyllys 			lock_count[i] = 0;
37199ebb4caSwyllys 			(void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
37299ebb4caSwyllys 		}
37399ebb4caSwyllys 
37499ebb4caSwyllys 		CRYPTO_set_id_callback((unsigned long (*)())thread_id);
3752c9a247fSWyllys Ingersoll 		if (CRYPTO_get_locking_callback() == NULL)
37699ebb4caSwyllys 			CRYPTO_set_locking_callback((void (*)())locking_cb);
3772c9a247fSWyllys Ingersoll 
378300fdee2SAndy Fiddaman 		(void) OpenSSL_add_all_algorithms();
3792c9a247fSWyllys Ingersoll 
3802c9a247fSWyllys Ingersoll 		/* Enable error strings for reporting */
381300fdee2SAndy Fiddaman 		(void) ERR_load_crypto_strings();
382300fdee2SAndy Fiddaman #endif
3832c9a247fSWyllys Ingersoll 
38499ebb4caSwyllys 		ssl_initialized = 1;
38599ebb4caSwyllys 	}
38699ebb4caSwyllys 	(void) mutex_unlock(&init_lock);
38799ebb4caSwyllys 
38899ebb4caSwyllys 	return (&openssl_plugin_table);
38999ebb4caSwyllys }
390300fdee2SAndy Fiddaman 
39199ebb4caSwyllys /*
39299ebb4caSwyllys  * Convert an SSL DN to a KMF DN.
39399ebb4caSwyllys  */
39499ebb4caSwyllys static KMF_RETURN
39599ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
39699ebb4caSwyllys {
39799ebb4caSwyllys 	KMF_DATA derdata;
39899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
39999ebb4caSwyllys 	uchar_t *tmp;
40099ebb4caSwyllys 
40199ebb4caSwyllys 	/* Convert to raw DER format */
40299ebb4caSwyllys 	derdata.Length = i2d_X509_NAME(sslDN, NULL);
40399ebb4caSwyllys 	if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
40499ebb4caSwyllys 	    == NULL) {
40599ebb4caSwyllys 		return (KMF_ERR_MEMORY);
40699ebb4caSwyllys 	}
40799ebb4caSwyllys 	(void) i2d_X509_NAME(sslDN, &tmp);
40899ebb4caSwyllys 
40999ebb4caSwyllys 	/* Decode to KMF format */
41099ebb4caSwyllys 	rv = DerDecodeName(&derdata, kmfDN);
41199ebb4caSwyllys 	if (rv != KMF_OK) {
41299ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
41399ebb4caSwyllys 	}
41499ebb4caSwyllys 	OPENSSL_free(derdata.Data);
41599ebb4caSwyllys 
41699ebb4caSwyllys 	return (rv);
41799ebb4caSwyllys }
41899ebb4caSwyllys 
41930a5e8faSwyllys int
42099ebb4caSwyllys isdir(char *path)
42199ebb4caSwyllys {
42299ebb4caSwyllys 	struct stat s;
42399ebb4caSwyllys 
42499ebb4caSwyllys 	if (stat(path, &s) == -1)
42599ebb4caSwyllys 		return (0);
42699ebb4caSwyllys 
42730a5e8faSwyllys 	return ((s.st_mode & S_IFMT) == S_IFDIR);
42899ebb4caSwyllys }
42999ebb4caSwyllys 
43099ebb4caSwyllys static KMF_RETURN
43199ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
43299ebb4caSwyllys {
43399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
43499ebb4caSwyllys 	unsigned char *buf = NULL, *p;
43599ebb4caSwyllys 	int len;
43699ebb4caSwyllys 
43799ebb4caSwyllys 	/*
43899ebb4caSwyllys 	 * Convert the X509 internal struct to DER encoded data
43999ebb4caSwyllys 	 */
44099ebb4caSwyllys 	if ((len = i2d_X509(x509cert, NULL)) < 0) {
44199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
44299ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
44399ebb4caSwyllys 		goto cleanup;
44499ebb4caSwyllys 	}
44599ebb4caSwyllys 	if ((buf = malloc(len)) == NULL) {
44699ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
44799ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
44899ebb4caSwyllys 		goto cleanup;
44999ebb4caSwyllys 	}
45099ebb4caSwyllys 
45199ebb4caSwyllys 	/*
45299ebb4caSwyllys 	 * i2d_X509 will increment the buf pointer so that we need to
45399ebb4caSwyllys 	 * save it.
45499ebb4caSwyllys 	 */
45599ebb4caSwyllys 	p = buf;
45699ebb4caSwyllys 	if ((len = i2d_X509(x509cert, &p)) < 0) {
45799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
45899ebb4caSwyllys 		free(buf);
45999ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
46099ebb4caSwyllys 		goto cleanup;
46199ebb4caSwyllys 	}
46299ebb4caSwyllys 
46399ebb4caSwyllys 	/* caller's responsibility to free it */
46499ebb4caSwyllys 	cert->Data = buf;
46599ebb4caSwyllys 	cert->Length = len;
46699ebb4caSwyllys 
46799ebb4caSwyllys cleanup:
46899ebb4caSwyllys 	if (rv != KMF_OK) {
46999ebb4caSwyllys 		if (buf)
47099ebb4caSwyllys 			free(buf);
47199ebb4caSwyllys 		cert->Data = NULL;
47299ebb4caSwyllys 		cert->Length = 0;
47399ebb4caSwyllys 	}
47499ebb4caSwyllys 
47599ebb4caSwyllys 	return (rv);
47699ebb4caSwyllys }
47799ebb4caSwyllys 
47830a5e8faSwyllys 
47999ebb4caSwyllys static KMF_RETURN
48030a5e8faSwyllys check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
48130a5e8faSwyllys     boolean_t *match)
48299ebb4caSwyllys {
48399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
48499ebb4caSwyllys 	boolean_t findIssuer = FALSE;
48599ebb4caSwyllys 	boolean_t findSubject = FALSE;
48699ebb4caSwyllys 	boolean_t findSerial = FALSE;
48799ebb4caSwyllys 	KMF_X509_NAME issuerDN, subjectDN;
48899ebb4caSwyllys 	KMF_X509_NAME certIssuerDN, certSubjectDN;
48999ebb4caSwyllys 
49099ebb4caSwyllys 	*match = FALSE;
49199ebb4caSwyllys 	if (xcert == NULL) {
49299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
49399ebb4caSwyllys 	}
49499ebb4caSwyllys 
49599ebb4caSwyllys 	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
49699ebb4caSwyllys 	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
49799ebb4caSwyllys 	(void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
49899ebb4caSwyllys 	(void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
49999ebb4caSwyllys 
50030a5e8faSwyllys 	if (issuer != NULL && strlen(issuer)) {
50130a5e8faSwyllys 		rv = kmf_dn_parser(issuer, &issuerDN);
50299ebb4caSwyllys 		if (rv != KMF_OK)
50399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
50499ebb4caSwyllys 
505300fdee2SAndy Fiddaman 		rv = get_x509_dn(X509_get_issuer_name(xcert), &certIssuerDN);
50699ebb4caSwyllys 		if (rv != KMF_OK) {
50730a5e8faSwyllys 			kmf_free_dn(&issuerDN);
50899ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
50999ebb4caSwyllys 		}
51099ebb4caSwyllys 
51199ebb4caSwyllys 		findIssuer = TRUE;
51299ebb4caSwyllys 	}
51330a5e8faSwyllys 	if (subject != NULL && strlen(subject)) {
51430a5e8faSwyllys 		rv = kmf_dn_parser(subject, &subjectDN);
51599ebb4caSwyllys 		if (rv != KMF_OK) {
51699ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
51799ebb4caSwyllys 			goto cleanup;
51899ebb4caSwyllys 		}
51999ebb4caSwyllys 
520300fdee2SAndy Fiddaman 		rv = get_x509_dn(X509_get_subject_name(xcert), &certSubjectDN);
52199ebb4caSwyllys 		if (rv != KMF_OK) {
52299ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
52399ebb4caSwyllys 			goto cleanup;
52499ebb4caSwyllys 		}
52599ebb4caSwyllys 		findSubject = TRUE;
52699ebb4caSwyllys 	}
52730a5e8faSwyllys 	if (serial != NULL && serial->val != NULL)
52899ebb4caSwyllys 		findSerial = TRUE;
52999ebb4caSwyllys 
53099ebb4caSwyllys 	if (findSerial) {
53199ebb4caSwyllys 		BIGNUM *bn;
53299ebb4caSwyllys 
53399ebb4caSwyllys 		/* Comparing BIGNUMs is a pain! */
534300fdee2SAndy Fiddaman 		bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(xcert), NULL);
53599ebb4caSwyllys 		if (bn != NULL) {
53699ebb4caSwyllys 			int bnlen = BN_num_bytes(bn);
53799ebb4caSwyllys 
53830a5e8faSwyllys 			if (bnlen == serial->len) {
53999ebb4caSwyllys 				uchar_t *a = malloc(bnlen);
54099ebb4caSwyllys 				if (a == NULL) {
54199ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
54299ebb4caSwyllys 					BN_free(bn);
54399ebb4caSwyllys 					goto cleanup;
54499ebb4caSwyllys 				}
54599ebb4caSwyllys 				bnlen = BN_bn2bin(bn, a);
54630a5e8faSwyllys 				*match = (memcmp(a, serial->val, serial->len) ==
54730a5e8faSwyllys 				    0);
54899ebb4caSwyllys 				rv = KMF_OK;
54999ebb4caSwyllys 				free(a);
55099ebb4caSwyllys 			}
55199ebb4caSwyllys 			BN_free(bn);
55299ebb4caSwyllys 			if (!(*match))
55399ebb4caSwyllys 				goto cleanup;
55499ebb4caSwyllys 		} else {
55599ebb4caSwyllys 			rv = KMF_OK;
55699ebb4caSwyllys 			goto cleanup;
55799ebb4caSwyllys 		}
55899ebb4caSwyllys 	}
55999ebb4caSwyllys 	if (findIssuer) {
56030a5e8faSwyllys 		*match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
56130a5e8faSwyllys 		if ((*match) == B_FALSE) {
56230a5e8faSwyllys 			/* stop checking and bail */
56399ebb4caSwyllys 			rv = KMF_OK;
56499ebb4caSwyllys 			goto cleanup;
56599ebb4caSwyllys 		}
56699ebb4caSwyllys 	}
56799ebb4caSwyllys 	if (findSubject) {
56830a5e8faSwyllys 		*match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
56930a5e8faSwyllys 		if ((*match) == B_FALSE) {
57030a5e8faSwyllys 			/* stop checking and bail */
57199ebb4caSwyllys 			rv = KMF_OK;
57299ebb4caSwyllys 			goto cleanup;
57399ebb4caSwyllys 		}
57499ebb4caSwyllys 	}
57599ebb4caSwyllys 
57699ebb4caSwyllys 	*match = TRUE;
57799ebb4caSwyllys cleanup:
57899ebb4caSwyllys 	if (findIssuer) {
57930a5e8faSwyllys 		kmf_free_dn(&issuerDN);
58030a5e8faSwyllys 		kmf_free_dn(&certIssuerDN);
58199ebb4caSwyllys 	}
58299ebb4caSwyllys 	if (findSubject) {
58330a5e8faSwyllys 		kmf_free_dn(&subjectDN);
58430a5e8faSwyllys 		kmf_free_dn(&certSubjectDN);
58599ebb4caSwyllys 	}
58699ebb4caSwyllys 
58799ebb4caSwyllys 	return (rv);
58899ebb4caSwyllys }
58999ebb4caSwyllys 
59030a5e8faSwyllys 
59130a5e8faSwyllys /*
59230a5e8faSwyllys  * This function loads a certificate file into an X509 data structure, and
59330a5e8faSwyllys  * checks if its issuer, subject or the serial number matches with those
59430a5e8faSwyllys  * values.  If it matches, then return the X509 data structure.
59530a5e8faSwyllys  */
59699ebb4caSwyllys static KMF_RETURN
59799ebb4caSwyllys load_X509cert(KMF_HANDLE *kmfh,
59830a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
59930a5e8faSwyllys     char *pathname, X509 **outcert)
60099ebb4caSwyllys {
60199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
60299ebb4caSwyllys 	X509 *xcert = NULL;
60399ebb4caSwyllys 	BIO *bcert = NULL;
60499ebb4caSwyllys 	boolean_t  match = FALSE;
60599ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
60699ebb4caSwyllys 
60799ebb4caSwyllys 	/*
60899ebb4caSwyllys 	 * auto-detect the file format, regardless of what
60999ebb4caSwyllys 	 * the 'format' parameters in the params say.
61099ebb4caSwyllys 	 */
61130a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
61299ebb4caSwyllys 	if (rv != KMF_OK) {
61399ebb4caSwyllys 		if (rv == KMF_ERR_OPEN_FILE)
61499ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
61599ebb4caSwyllys 		return (rv);
61699ebb4caSwyllys 	}
61799ebb4caSwyllys 
61899ebb4caSwyllys 	/* Not ASN1(DER) format */
61999ebb4caSwyllys 	if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
62099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
62199ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
62299ebb4caSwyllys 		goto cleanup;
62399ebb4caSwyllys 	}
62499ebb4caSwyllys 
62599ebb4caSwyllys 	if (format == KMF_FORMAT_PEM)
62699ebb4caSwyllys 		xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
62799ebb4caSwyllys 	else if (format == KMF_FORMAT_ASN1)
62899ebb4caSwyllys 		xcert = d2i_X509_bio(bcert, NULL);
62999ebb4caSwyllys 	else if (format == KMF_FORMAT_PKCS12) {
63099ebb4caSwyllys 		PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
63199ebb4caSwyllys 		if (p12 != NULL) {
63299ebb4caSwyllys 			(void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
63399ebb4caSwyllys 			PKCS12_free(p12);
63499ebb4caSwyllys 			p12 = NULL;
63599ebb4caSwyllys 		} else {
63699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
63799ebb4caSwyllys 			rv = KMF_ERR_BAD_CERT_FORMAT;
63899ebb4caSwyllys 		}
63999ebb4caSwyllys 	} else {
64099ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
64199ebb4caSwyllys 		goto cleanup;
64299ebb4caSwyllys 	}
64399ebb4caSwyllys 
64499ebb4caSwyllys 	if (xcert == NULL) {
64599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
64699ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
64799ebb4caSwyllys 		goto cleanup;
64899ebb4caSwyllys 	}
64999ebb4caSwyllys 
65030a5e8faSwyllys 	if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
65130a5e8faSwyllys 	    match == FALSE) {
65299ebb4caSwyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
65399ebb4caSwyllys 		goto cleanup;
65499ebb4caSwyllys 	}
65599ebb4caSwyllys 
65699ebb4caSwyllys 	if (outcert != NULL) {
65799ebb4caSwyllys 		*outcert = xcert;
65899ebb4caSwyllys 	}
65999ebb4caSwyllys 
66099ebb4caSwyllys cleanup:
66199ebb4caSwyllys 	if (bcert != NULL) (void) BIO_free(bcert);
66299ebb4caSwyllys 	if (rv != KMF_OK && xcert != NULL)
66399ebb4caSwyllys 		X509_free(xcert);
66499ebb4caSwyllys 
66599ebb4caSwyllys 	return (rv);
66699ebb4caSwyllys }
66799ebb4caSwyllys 
66871593db2Swyllys static int
66971593db2Swyllys datacmp(const void *a, const void *b)
67071593db2Swyllys {
67171593db2Swyllys 	KMF_DATA *adata = (KMF_DATA *)a;
67271593db2Swyllys 	KMF_DATA *bdata = (KMF_DATA *)b;
67371593db2Swyllys 	if (adata->Length > bdata->Length)
67471593db2Swyllys 		return (-1);
67571593db2Swyllys 	if (adata->Length < bdata->Length)
67671593db2Swyllys 		return (1);
67771593db2Swyllys 	return (0);
67871593db2Swyllys }
67971593db2Swyllys 
68071593db2Swyllys static KMF_RETURN
68130a5e8faSwyllys load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
68230a5e8faSwyllys     KMF_CERT_VALIDITY validity, char *pathname,
68371593db2Swyllys     KMF_DATA **certlist, uint32_t *numcerts)
68471593db2Swyllys {
68571593db2Swyllys 	KMF_RETURN rv = KMF_OK;
68671593db2Swyllys 	int i;
68771593db2Swyllys 	KMF_DATA *certs = NULL;
68871593db2Swyllys 	int nc = 0;
68971593db2Swyllys 	int hits = 0;
69071593db2Swyllys 	KMF_ENCODE_FORMAT format;
69171593db2Swyllys 
69230a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
69371593db2Swyllys 	if (rv != KMF_OK) {
69471593db2Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
69571593db2Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
69671593db2Swyllys 		return (rv);
69771593db2Swyllys 	}
69871593db2Swyllys 	if (format == KMF_FORMAT_ASN1) {
69971593db2Swyllys 		/* load a single certificate */
70071593db2Swyllys 		certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
70171593db2Swyllys 		if (certs == NULL)
70271593db2Swyllys 			return (KMF_ERR_MEMORY);
70371593db2Swyllys 		certs->Data = NULL;
70471593db2Swyllys 		certs->Length = 0;
70530a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
70630a5e8faSwyllys 		    pathname, certs);
70771593db2Swyllys 		if (rv == KMF_OK) {
70871593db2Swyllys 			*certlist = certs;
70971593db2Swyllys 			*numcerts = 1;
710a2d4930dSDan OpenSolaris Anderson 		} else {
711a2d4930dSDan OpenSolaris Anderson 			kmf_free_data(certs);
712a2d4930dSDan OpenSolaris Anderson 			free(certs);
713a2d4930dSDan OpenSolaris Anderson 			certs = NULL;
71471593db2Swyllys 		}
71571593db2Swyllys 		return (rv);
71671593db2Swyllys 	} else if (format == KMF_FORMAT_PKCS12) {
71771593db2Swyllys 		/* We need a credential to access a PKCS#12 file */
71871593db2Swyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
71971593db2Swyllys 	} else if (format == KMF_FORMAT_PEM ||
72071593db2Swyllys 	    format != KMF_FORMAT_PEM_KEYPAIR) {
721e65e5c2dSWyllys Ingersoll 
72271593db2Swyllys 		/* This function only works on PEM files */
72330a5e8faSwyllys 		rv = extract_pem(kmfh, issuer, subject, serial, pathname,
72434acef67Swyllys 		    (uchar_t *)NULL, 0, NULL, &certs, &nc);
72571593db2Swyllys 	} else {
72671593db2Swyllys 		return (KMF_ERR_ENCODING);
72771593db2Swyllys 	}
72871593db2Swyllys 
72971593db2Swyllys 	if (rv != KMF_OK)
73071593db2Swyllys 		return (rv);
73171593db2Swyllys 
73271593db2Swyllys 	for (i = 0; i < nc; i++) {
73330a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
73430a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
73530a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
73630a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
73771593db2Swyllys 			if (rv == KMF_OK)
73871593db2Swyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
73971593db2Swyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD)
74071593db2Swyllys 				rv = KMF_OK;
74171593db2Swyllys 		}
74271593db2Swyllys 		if (rv != KMF_OK) {
74371593db2Swyllys 			/* Remove this cert from the list by clearing it. */
74430a5e8faSwyllys 			kmf_free_data(&certs[i]);
74571593db2Swyllys 		} else {
74671593db2Swyllys 			hits++; /* count valid certs found */
74771593db2Swyllys 		}
74871593db2Swyllys 		rv = KMF_OK;
74971593db2Swyllys 	}
750a2d4930dSDan OpenSolaris Anderson 	if (rv == KMF_OK && hits > 0) {
75171593db2Swyllys 		/*
75271593db2Swyllys 		 * Sort the list of certs by length to put the cleared ones
75371593db2Swyllys 		 * at the end so they don't get accessed by the caller.
75471593db2Swyllys 		 */
75571593db2Swyllys 		qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
75671593db2Swyllys 		*certlist = certs;
75771593db2Swyllys 
75871593db2Swyllys 		/* since we sorted the list, just return the number of hits */
75971593db2Swyllys 		*numcerts = hits;
760a2d4930dSDan OpenSolaris Anderson 	} else {
761e65e5c2dSWyllys Ingersoll 		if (rv == KMF_OK && hits == 0)
762a2d4930dSDan OpenSolaris Anderson 			rv = KMF_ERR_CERT_NOT_FOUND;
763a2d4930dSDan OpenSolaris Anderson 		if (certs != NULL) {
764a2d4930dSDan OpenSolaris Anderson 			free(certs);
765a2d4930dSDan OpenSolaris Anderson 			certs = NULL;
766a2d4930dSDan OpenSolaris Anderson 		}
767a2d4930dSDan OpenSolaris Anderson 	}
76871593db2Swyllys 	return (rv);
76971593db2Swyllys }
77071593db2Swyllys 
77199ebb4caSwyllys static KMF_RETURN
77299ebb4caSwyllys kmf_load_cert(KMF_HANDLE *kmfh,
77330a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
77430a5e8faSwyllys     KMF_CERT_VALIDITY validity,
77599ebb4caSwyllys     char *pathname,
77699ebb4caSwyllys     KMF_DATA *cert)
77799ebb4caSwyllys {
77899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
77999ebb4caSwyllys 	X509 *x509cert = NULL;
78099ebb4caSwyllys 
78130a5e8faSwyllys 	rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
78299ebb4caSwyllys 	if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
78399ebb4caSwyllys 		rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
78499ebb4caSwyllys 		if (rv != KMF_OK) {
78599ebb4caSwyllys 			goto cleanup;
78699ebb4caSwyllys 		}
78730a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
78830a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
78930a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
79030a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
79199ebb4caSwyllys 			if (rv == KMF_OK)  {
79299ebb4caSwyllys 				/*
79399ebb4caSwyllys 				 * This is a valid cert so skip it.
79499ebb4caSwyllys 				 */
79599ebb4caSwyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
79699ebb4caSwyllys 			}
79799ebb4caSwyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD) {
79899ebb4caSwyllys 				/*
79999ebb4caSwyllys 				 * We want to return success when we
80099ebb4caSwyllys 				 * find an invalid cert.
80199ebb4caSwyllys 				 */
80299ebb4caSwyllys 				rv = KMF_OK;
80399ebb4caSwyllys 				goto cleanup;
80499ebb4caSwyllys 			}
80599ebb4caSwyllys 		}
80699ebb4caSwyllys 	}
80799ebb4caSwyllys cleanup:
80899ebb4caSwyllys 	if (x509cert != NULL)
80999ebb4caSwyllys 		X509_free(x509cert);
81099ebb4caSwyllys 
81199ebb4caSwyllys 	return (rv);
81299ebb4caSwyllys }
81399ebb4caSwyllys 
81402744e81Swyllys static KMF_RETURN
81502744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
81602744e81Swyllys {
81702744e81Swyllys 	KMF_RETURN ret = KMF_OK;
81802744e81Swyllys 	KMF_RAW_RSA_KEY rsa;
81902744e81Swyllys 	BerElement *asn1 = NULL;
82002744e81Swyllys 	BerValue filebuf;
82102744e81Swyllys 	BerValue OID = { NULL, 0 };
82202744e81Swyllys 	BerValue *Mod = NULL, *PubExp = NULL;
82302744e81Swyllys 	BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
82402744e81Swyllys 	BerValue *Coef = NULL;
82502744e81Swyllys 	BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
82602744e81Swyllys 	BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
82702744e81Swyllys 	BIGNUM *qminus1 = NULL;
82802744e81Swyllys 	BN_CTX *ctx = NULL;
82902744e81Swyllys 
83002744e81Swyllys 	*pkey = NULL;
83102744e81Swyllys 
83202744e81Swyllys 	filebuf.bv_val = (char *)filedata->Data;
83302744e81Swyllys 	filebuf.bv_len = filedata->Length;
83402744e81Swyllys 
83502744e81Swyllys 	asn1 = kmfder_init(&filebuf);
83602744e81Swyllys 	if (asn1 == NULL) {
83702744e81Swyllys 		ret = KMF_ERR_MEMORY;
83802744e81Swyllys 		goto out;
83902744e81Swyllys 	}
84002744e81Swyllys 
84102744e81Swyllys 	if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
84202744e81Swyllys 	    &OID, &Mod, &PubExp, &PriExp, &Prime1,
84302744e81Swyllys 	    &Prime2, &Coef) == -1)  {
84402744e81Swyllys 		ret = KMF_ERR_ENCODING;
84502744e81Swyllys 		goto out;
84602744e81Swyllys 	}
84702744e81Swyllys 
84802744e81Swyllys 	/*
84902744e81Swyllys 	 * We have to derive the 2 Exponents using Bignumber math.
85002744e81Swyllys 	 * Exp1 = PriExp mod (Prime1 - 1)
85102744e81Swyllys 	 * Exp2 = PriExp mod (Prime2 - 1)
85202744e81Swyllys 	 */
85302744e81Swyllys 
85402744e81Swyllys 	/* D = PrivateExponent */
85502744e81Swyllys 	D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
85602744e81Swyllys 	if (D == NULL) {
85702744e81Swyllys 		ret = KMF_ERR_MEMORY;
85802744e81Swyllys 		goto out;
85902744e81Swyllys 	}
86002744e81Swyllys 
86102744e81Swyllys 	/* P = Prime1 (first prime factor of Modulus) */
86202744e81Swyllys 	P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
86302744e81Swyllys 	if (D == NULL) {
86402744e81Swyllys 		ret = KMF_ERR_MEMORY;
86502744e81Swyllys 		goto out;
86602744e81Swyllys 	}
86702744e81Swyllys 
86802744e81Swyllys 	/* Q = Prime2 (second prime factor of Modulus) */
86902744e81Swyllys 	Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
87002744e81Swyllys 
87102744e81Swyllys 	if ((ctx = BN_CTX_new()) == NULL) {
87202744e81Swyllys 		ret = KMF_ERR_MEMORY;
87302744e81Swyllys 		goto out;
87402744e81Swyllys 	}
87502744e81Swyllys 
87602744e81Swyllys 	/* Compute (P - 1) */
87702744e81Swyllys 	pminus1 = BN_new();
87802744e81Swyllys 	(void) BN_sub(pminus1, P, BN_value_one());
87902744e81Swyllys 
88002744e81Swyllys 	/* Exponent1 = D mod (P - 1) */
88102744e81Swyllys 	Exp1 = BN_new();
88202744e81Swyllys 	(void) BN_mod(Exp1, D, pminus1, ctx);
88302744e81Swyllys 
88402744e81Swyllys 	/* Compute (Q - 1) */
88502744e81Swyllys 	qminus1 = BN_new();
88602744e81Swyllys 	(void) BN_sub(qminus1, Q, BN_value_one());
88702744e81Swyllys 
88802744e81Swyllys 	/* Exponent2 = D mod (Q - 1) */
88902744e81Swyllys 	Exp2 = BN_new();
89002744e81Swyllys 	(void) BN_mod(Exp2, D, qminus1, ctx);
89102744e81Swyllys 
89202744e81Swyllys 	/* Coef = (Inverse Q) mod P */
89302744e81Swyllys 	COEF = BN_new();
89402744e81Swyllys 	(void) BN_mod_inverse(COEF, Q, P, ctx);
89502744e81Swyllys 
89602744e81Swyllys 	/* Convert back to KMF format */
89702744e81Swyllys 	(void) memset(&rsa, 0, sizeof (rsa));
89802744e81Swyllys 
89902744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
90002744e81Swyllys 		goto out;
90102744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
90202744e81Swyllys 		goto out;
90302744e81Swyllys 	if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
90402744e81Swyllys 		goto out;
90502744e81Swyllys 
90602744e81Swyllys 	rsa.mod.val = (uchar_t *)Mod->bv_val;
90702744e81Swyllys 	rsa.mod.len = Mod->bv_len;
90802744e81Swyllys 
90902744e81Swyllys 	rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
91002744e81Swyllys 	rsa.pubexp.len = PubExp->bv_len;
91102744e81Swyllys 
91202744e81Swyllys 	rsa.priexp.val = (uchar_t *)PriExp->bv_val;
91302744e81Swyllys 	rsa.priexp.len = PriExp->bv_len;
91402744e81Swyllys 
91502744e81Swyllys 	rsa.prime1.val = (uchar_t *)Prime1->bv_val;
91602744e81Swyllys 	rsa.prime1.len = Prime1->bv_len;
91702744e81Swyllys 
91802744e81Swyllys 	rsa.prime2.val = (uchar_t *)Prime2->bv_val;
91902744e81Swyllys 	rsa.prime2.len = Prime2->bv_len;
92002744e81Swyllys 
92102744e81Swyllys 	*pkey = ImportRawRSAKey(&rsa);
92202744e81Swyllys out:
92302744e81Swyllys 	if (asn1 != NULL)
92402744e81Swyllys 		kmfber_free(asn1, 1);
92502744e81Swyllys 
92602744e81Swyllys 	if (OID.bv_val) {
92702744e81Swyllys 		free(OID.bv_val);
92802744e81Swyllys 	}
92902744e81Swyllys 	if (PriExp)
93002744e81Swyllys 		free(PriExp);
93102744e81Swyllys 
93202744e81Swyllys 	if (Mod)
93302744e81Swyllys 		free(Mod);
93402744e81Swyllys 
93502744e81Swyllys 	if (PubExp)
93602744e81Swyllys 		free(PubExp);
93702744e81Swyllys 
93802744e81Swyllys 	if (Coef) {
93902744e81Swyllys 		(void) memset(Coef->bv_val, 0, Coef->bv_len);
94002744e81Swyllys 		free(Coef->bv_val);
94102744e81Swyllys 		free(Coef);
94202744e81Swyllys 	}
94302744e81Swyllys 	if (Prime1)
94402744e81Swyllys 		free(Prime1);
94502744e81Swyllys 	if (Prime2)
94602744e81Swyllys 		free(Prime2);
94702744e81Swyllys 
94802744e81Swyllys 	if (ctx != NULL)
94902744e81Swyllys 		BN_CTX_free(ctx);
95002744e81Swyllys 
95102744e81Swyllys 	if (D)
95202744e81Swyllys 		BN_clear_free(D);
95302744e81Swyllys 	if (P)
95402744e81Swyllys 		BN_clear_free(P);
95502744e81Swyllys 	if (Q)
95602744e81Swyllys 		BN_clear_free(Q);
95702744e81Swyllys 	if (pminus1)
95802744e81Swyllys 		BN_clear_free(pminus1);
95902744e81Swyllys 	if (qminus1)
96002744e81Swyllys 		BN_clear_free(qminus1);
96102744e81Swyllys 	if (Exp1)
96202744e81Swyllys 		BN_clear_free(Exp1);
96302744e81Swyllys 	if (Exp2)
96402744e81Swyllys 		BN_clear_free(Exp2);
96502744e81Swyllys 
96602744e81Swyllys 	return (ret);
96702744e81Swyllys 
96802744e81Swyllys }
96902744e81Swyllys 
97099ebb4caSwyllys static EVP_PKEY *
97199ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file)
97299ebb4caSwyllys {
97399ebb4caSwyllys 	BIO *keyfile = NULL;
97499ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
97599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
97699ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
97702744e81Swyllys 	KMF_RETURN rv;
97802744e81Swyllys 	KMF_DATA filedata;
97999ebb4caSwyllys 
98099ebb4caSwyllys 	if (file == NULL) {
98199ebb4caSwyllys 		return (NULL);
98299ebb4caSwyllys 	}
98399ebb4caSwyllys 
98430a5e8faSwyllys 	if (kmf_get_file_format((char *)file, &format) != KMF_OK)
98599ebb4caSwyllys 		return (NULL);
98699ebb4caSwyllys 
98799ebb4caSwyllys 	keyfile = BIO_new_file(file, "rb");
98899ebb4caSwyllys 	if (keyfile == NULL) {
98999ebb4caSwyllys 		goto end;
99099ebb4caSwyllys 	}
99199ebb4caSwyllys 
99202744e81Swyllys 	if (format == KMF_FORMAT_ASN1) {
99399ebb4caSwyllys 		pkey = d2i_PrivateKey_bio(keyfile, NULL);
99402744e81Swyllys 		if (pkey == NULL) {
99502744e81Swyllys 
99602744e81Swyllys 			(void) BIO_free(keyfile);
99702744e81Swyllys 			keyfile = NULL;
99802744e81Swyllys 			/* Try odd ASN.1 variations */
99930a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
100002744e81Swyllys 			    &filedata);
100102744e81Swyllys 			if (rv == KMF_OK) {
100202744e81Swyllys 				(void) readAltFormatPrivateKey(&filedata,
100302744e81Swyllys 				    &pkey);
100430a5e8faSwyllys 				kmf_free_data(&filedata);
100502744e81Swyllys 			}
100602744e81Swyllys 		}
100702744e81Swyllys 	} else if (format == KMF_FORMAT_PEM ||
100802744e81Swyllys 	    format == KMF_FORMAT_PEM_KEYPAIR) {
100999ebb4caSwyllys 		pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
101002744e81Swyllys 		if (pkey == NULL) {
101102744e81Swyllys 			KMF_DATA derdata;
101202744e81Swyllys 			/*
101302744e81Swyllys 			 * Check if this is the alt. format
101402744e81Swyllys 			 * RSA private key file.
101502744e81Swyllys 			 */
101630a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
101702744e81Swyllys 			    &filedata);
101802744e81Swyllys 			if (rv == KMF_OK) {
101902744e81Swyllys 				uchar_t *d = NULL;
102002744e81Swyllys 				int len;
102130a5e8faSwyllys 				rv = kmf_pem_to_der(filedata.Data,
102202744e81Swyllys 				    filedata.Length, &d, &len);
102302744e81Swyllys 				if (rv == KMF_OK && d != NULL) {
102402744e81Swyllys 					derdata.Data = d;
102502744e81Swyllys 					derdata.Length = (size_t)len;
102602744e81Swyllys 					(void) readAltFormatPrivateKey(
102702744e81Swyllys 					    &derdata, &pkey);
102802744e81Swyllys 					free(d);
102902744e81Swyllys 				}
103030a5e8faSwyllys 				kmf_free_data(&filedata);
103102744e81Swyllys 			}
103202744e81Swyllys 		}
103302744e81Swyllys 	}
103499ebb4caSwyllys 
103599ebb4caSwyllys end:
103699ebb4caSwyllys 	if (pkey == NULL)
103799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
103899ebb4caSwyllys 
103999ebb4caSwyllys 	if (keyfile != NULL)
104099ebb4caSwyllys 		(void) BIO_free(keyfile);
104199ebb4caSwyllys 
104299ebb4caSwyllys 	return (pkey);
104399ebb4caSwyllys }
104499ebb4caSwyllys 
104599ebb4caSwyllys KMF_RETURN
104630a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
104799ebb4caSwyllys {
104899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
104999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1050f482c776Swyllys 	int i, n;
1051f482c776Swyllys 	uint32_t maxcerts = 0;
105230a5e8faSwyllys 	uint32_t *num_certs;
105330a5e8faSwyllys 	KMF_X509_DER_CERT *kmf_cert = NULL;
105430a5e8faSwyllys 	char *dirpath = NULL;
105530a5e8faSwyllys 	char *filename = NULL;
105630a5e8faSwyllys 	char *fullpath = NULL;
105730a5e8faSwyllys 	char *issuer = NULL;
105830a5e8faSwyllys 	char *subject = NULL;
105930a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
106030a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
106199ebb4caSwyllys 
106230a5e8faSwyllys 	num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
106330a5e8faSwyllys 	if (num_certs == NULL)
106499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
106599ebb4caSwyllys 
106630a5e8faSwyllys 	/* num_certs should reference the size of kmf_cert */
1067f482c776Swyllys 	maxcerts = *num_certs;
1068f482c776Swyllys 	if (maxcerts == 0)
1069f482c776Swyllys 		maxcerts = 0xFFFFFFFF;
107099ebb4caSwyllys 	*num_certs = 0;
107199ebb4caSwyllys 
107230a5e8faSwyllys 	/* Get the optional returned certificate list  */
107330a5e8faSwyllys 	kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
107430a5e8faSwyllys 	    numattr);
107599ebb4caSwyllys 
107630a5e8faSwyllys 	/*
107730a5e8faSwyllys 	 * The dirpath attribute and the filename attribute can not be NULL
107830a5e8faSwyllys 	 * at the same time.
107930a5e8faSwyllys 	 */
108030a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
108130a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
108230a5e8faSwyllys 	    numattr);
108330a5e8faSwyllys 
108430a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
108599ebb4caSwyllys 	if (fullpath == NULL)
108699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
108799ebb4caSwyllys 
108830a5e8faSwyllys 	/* Get optional search criteria attributes */
108930a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
109030a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
109130a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
109230a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
109330a5e8faSwyllys 	    &validity, NULL);
109430a5e8faSwyllys 	if (rv != KMF_OK) {
109530a5e8faSwyllys 		validity = KMF_ALL_CERTS;
109630a5e8faSwyllys 		rv = KMF_OK;
109730a5e8faSwyllys 	}
109830a5e8faSwyllys 
109999ebb4caSwyllys 	if (isdir(fullpath)) {
110099ebb4caSwyllys 		DIR *dirp;
110199ebb4caSwyllys 		struct dirent *dp;
110299ebb4caSwyllys 
1103f482c776Swyllys 		n = 0;
110499ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
110599ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
110699ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
110799ebb4caSwyllys 		}
110899ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
110999ebb4caSwyllys 			char *fname;
111071593db2Swyllys 			KMF_DATA *certlist = NULL;
1111f482c776Swyllys 			uint32_t loaded_certs = 0;
111271593db2Swyllys 
111399ebb4caSwyllys 			if (strcmp(dp->d_name, ".") == 0 ||
111499ebb4caSwyllys 			    strcmp(dp->d_name, "..") == 0)
111599ebb4caSwyllys 				continue;
111699ebb4caSwyllys 
111734acef67Swyllys 			fname = get_fullpath(fullpath, (char *)&dp->d_name);
111899ebb4caSwyllys 
111930a5e8faSwyllys 			rv = load_certs(kmfh, issuer, subject, serial,
112030a5e8faSwyllys 			    validity, fname, &certlist,	&loaded_certs);
112199ebb4caSwyllys 
112299ebb4caSwyllys 			if (rv != KMF_OK) {
112399ebb4caSwyllys 				free(fname);
112471593db2Swyllys 				if (certlist != NULL) {
1125f482c776Swyllys 					for (i = 0; i < loaded_certs; i++)
112630a5e8faSwyllys 						kmf_free_data(&certlist[i]);
112771593db2Swyllys 					free(certlist);
112871593db2Swyllys 				}
112999ebb4caSwyllys 				continue;
113099ebb4caSwyllys 			}
113199ebb4caSwyllys 
113299ebb4caSwyllys 			/* If load succeeds, add certdata to the list */
113399ebb4caSwyllys 			if (kmf_cert != NULL) {
1134f482c776Swyllys 				for (i = 0; i < loaded_certs &&
1135b4058258Swyllys 				    n < maxcerts; i++) {
113671593db2Swyllys 					kmf_cert[n].certificate.Data =
113771593db2Swyllys 					    certlist[i].Data;
113899ebb4caSwyllys 					kmf_cert[n].certificate.Length =
113971593db2Swyllys 					    certlist[i].Length;
114099ebb4caSwyllys 
114199ebb4caSwyllys 					kmf_cert[n].kmf_private.keystore_type =
114299ebb4caSwyllys 					    KMF_KEYSTORE_OPENSSL;
114399ebb4caSwyllys 					kmf_cert[n].kmf_private.flags =
114499ebb4caSwyllys 					    KMF_FLAG_CERT_VALID;
114571593db2Swyllys 					kmf_cert[n].kmf_private.label =
114671593db2Swyllys 					    strdup(fname);
114799ebb4caSwyllys 					n++;
114899ebb4caSwyllys 				}
1149b4058258Swyllys 				/*
1150b4058258Swyllys 				 * If maxcerts < loaded_certs, clean up the
1151b4058258Swyllys 				 * certs that were not used.
1152b4058258Swyllys 				 */
1153f482c776Swyllys 				for (; i < loaded_certs; i++)
115430a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1155f482c776Swyllys 			} else {
1156f482c776Swyllys 				for (i = 0; i < loaded_certs; i++)
115730a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1158f482c776Swyllys 				n += loaded_certs;
115971593db2Swyllys 			}
1160f482c776Swyllys 			free(certlist);
116171593db2Swyllys 			free(fname);
116271593db2Swyllys 		}
116399ebb4caSwyllys 		(*num_certs) = n;
116499ebb4caSwyllys 		if (*num_certs == 0)
116599ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
116630a5e8faSwyllys 		if (*num_certs > 0)
116799ebb4caSwyllys 			rv = KMF_OK;
116899ebb4caSwyllys exit:
116999ebb4caSwyllys 		(void) closedir(dirp);
117099ebb4caSwyllys 	} else {
117171593db2Swyllys 		KMF_DATA *certlist = NULL;
1172f482c776Swyllys 		uint32_t loaded_certs = 0;
117371593db2Swyllys 
117430a5e8faSwyllys 		rv = load_certs(kmfh, issuer, subject, serial, validity,
117530a5e8faSwyllys 		    fullpath, &certlist, &loaded_certs);
117699ebb4caSwyllys 		if (rv != KMF_OK) {
117799ebb4caSwyllys 			free(fullpath);
117899ebb4caSwyllys 			return (rv);
117999ebb4caSwyllys 		}
118099ebb4caSwyllys 
1181f482c776Swyllys 		n = 0;
118271593db2Swyllys 		if (kmf_cert != NULL && certlist != NULL) {
1183f482c776Swyllys 			for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1184f482c776Swyllys 				kmf_cert[n].certificate.Data =
118571593db2Swyllys 				    certlist[i].Data;
1186f482c776Swyllys 				kmf_cert[n].certificate.Length =
118771593db2Swyllys 				    certlist[i].Length;
1188f482c776Swyllys 				kmf_cert[n].kmf_private.keystore_type =
118999ebb4caSwyllys 				    KMF_KEYSTORE_OPENSSL;
1190f482c776Swyllys 				kmf_cert[n].kmf_private.flags =
119171593db2Swyllys 				    KMF_FLAG_CERT_VALID;
1192f482c776Swyllys 				kmf_cert[n].kmf_private.label =
119371593db2Swyllys 				    strdup(fullpath);
1194f482c776Swyllys 				n++;
119571593db2Swyllys 			}
1196f482c776Swyllys 			/* If maxcerts < loaded_certs, clean up */
1197f482c776Swyllys 			for (; i < loaded_certs; i++)
119830a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1199f482c776Swyllys 		} else if (certlist != NULL) {
1200f482c776Swyllys 			for (i = 0; i < loaded_certs; i++)
120130a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1202f482c776Swyllys 			n = loaded_certs;
1203f482c776Swyllys 		}
120430a5e8faSwyllys 		if (certlist != NULL)
120571593db2Swyllys 			free(certlist);
1206f482c776Swyllys 		*num_certs = n;
120799ebb4caSwyllys 	}
120899ebb4caSwyllys 
120999ebb4caSwyllys 	free(fullpath);
121099ebb4caSwyllys 
121199ebb4caSwyllys 	return (rv);
121299ebb4caSwyllys }
121399ebb4caSwyllys 
121499ebb4caSwyllys void
121599ebb4caSwyllys /*ARGSUSED*/
121699ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
121799ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert)
121899ebb4caSwyllys {
121999ebb4caSwyllys 	if (kmf_cert != NULL) {
122099ebb4caSwyllys 		if (kmf_cert->certificate.Data != NULL) {
1221e65e5c2dSWyllys Ingersoll 			kmf_free_data(&kmf_cert->certificate);
122299ebb4caSwyllys 		}
122399ebb4caSwyllys 		if (kmf_cert->kmf_private.label)
122499ebb4caSwyllys 			free(kmf_cert->kmf_private.label);
122599ebb4caSwyllys 	}
122699ebb4caSwyllys }
122799ebb4caSwyllys 
122830a5e8faSwyllys /*ARGSUSED*/
122999ebb4caSwyllys KMF_RETURN
123030a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
123199ebb4caSwyllys {
123299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
123330a5e8faSwyllys 	KMF_DATA *cert = NULL;
123430a5e8faSwyllys 	char *outfilename = NULL;
123530a5e8faSwyllys 	char *dirpath = NULL;
123630a5e8faSwyllys 	char *fullpath = NULL;
123799ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
123899ebb4caSwyllys 
123930a5e8faSwyllys 	/* Get the cert data */
124030a5e8faSwyllys 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
124130a5e8faSwyllys 	if (cert == NULL || cert->Data == NULL)
124299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
124399ebb4caSwyllys 
124430a5e8faSwyllys 	/* Check the output filename and directory attributes. */
124530a5e8faSwyllys 	outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
124630a5e8faSwyllys 	    numattr);
124730a5e8faSwyllys 	if (outfilename == NULL)
124830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
124999ebb4caSwyllys 
125030a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
125130a5e8faSwyllys 	fullpath = get_fullpath(dirpath, outfilename);
125299ebb4caSwyllys 	if (fullpath == NULL)
125330a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
125499ebb4caSwyllys 
125530a5e8faSwyllys 	/* Check the optional format attribute */
125630a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
125730a5e8faSwyllys 	    &format, NULL);
125830a5e8faSwyllys 	if (ret != KMF_OK) {
125930a5e8faSwyllys 		/* If there is no format attribute, then default to PEM */
126030a5e8faSwyllys 		format = KMF_FORMAT_PEM;
126199ebb4caSwyllys 		ret = KMF_OK;
126230a5e8faSwyllys 	} else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
126330a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
126499ebb4caSwyllys 		goto out;
126599ebb4caSwyllys 	}
126699ebb4caSwyllys 
126730a5e8faSwyllys 	/* Store the certificate in the file with the specified format */
126830a5e8faSwyllys 	ret = kmf_create_cert_file(cert, format, fullpath);
126999ebb4caSwyllys 
127099ebb4caSwyllys out:
127199ebb4caSwyllys 	if (fullpath != NULL)
127299ebb4caSwyllys 		free(fullpath);
127399ebb4caSwyllys 
127499ebb4caSwyllys 	return (ret);
127599ebb4caSwyllys }
127699ebb4caSwyllys 
127730a5e8faSwyllys 
127899ebb4caSwyllys KMF_RETURN
127930a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
128099ebb4caSwyllys {
128199ebb4caSwyllys 	KMF_RETURN rv;
128299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
12836b35cb3cSRichard PALO 	KMF_DATA certdata = { 0, NULL };
128430a5e8faSwyllys 	char *dirpath = NULL;
128530a5e8faSwyllys 	char *filename = NULL;
128630a5e8faSwyllys 	char *fullpath = NULL;
128730a5e8faSwyllys 	char *issuer = NULL;
128830a5e8faSwyllys 	char *subject = NULL;
128930a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
129030a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
129199ebb4caSwyllys 
129230a5e8faSwyllys 	/*
129330a5e8faSwyllys 	 * Get the DIRPATH and CERT_FILENAME attributes.  They can not be
129430a5e8faSwyllys 	 * NULL at the same time.
129530a5e8faSwyllys 	 */
129630a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
129730a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
129830a5e8faSwyllys 	    numattr);
129930a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
130099ebb4caSwyllys 	if (fullpath == NULL)
130199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
130299ebb4caSwyllys 
130330a5e8faSwyllys 	/* Get optional search criteria attributes */
130430a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
130530a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
130630a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
130730a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
130830a5e8faSwyllys 	    &validity, NULL);
130930a5e8faSwyllys 	if (rv != KMF_OK) {
131030a5e8faSwyllys 		validity = KMF_ALL_CERTS;
131130a5e8faSwyllys 		rv = KMF_OK;
131230a5e8faSwyllys 	}
131330a5e8faSwyllys 
131499ebb4caSwyllys 	if (isdir(fullpath)) {
131599ebb4caSwyllys 		DIR *dirp;
131699ebb4caSwyllys 		struct dirent *dp;
131799ebb4caSwyllys 
131899ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
131999ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
132099ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
132199ebb4caSwyllys 		}
132299ebb4caSwyllys 
132399ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
132499ebb4caSwyllys 			if (strcmp(dp->d_name, ".") != 0 &&
132599ebb4caSwyllys 			    strcmp(dp->d_name, "..") != 0) {
132699ebb4caSwyllys 				char *fname;
132799ebb4caSwyllys 
132899ebb4caSwyllys 				fname = get_fullpath(fullpath,
132999ebb4caSwyllys 				    (char *)&dp->d_name);
133099ebb4caSwyllys 
133199ebb4caSwyllys 				if (fname == NULL) {
133299ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
133399ebb4caSwyllys 					break;
133499ebb4caSwyllys 				}
133599ebb4caSwyllys 
133630a5e8faSwyllys 				rv = kmf_load_cert(kmfh, issuer, subject,
133730a5e8faSwyllys 				    serial, validity, fname, &certdata);
133899ebb4caSwyllys 
133999ebb4caSwyllys 				if (rv == KMF_ERR_CERT_NOT_FOUND) {
134099ebb4caSwyllys 					free(fname);
1341e65e5c2dSWyllys Ingersoll 					kmf_free_data(&certdata);
134299ebb4caSwyllys 					rv = KMF_OK;
134399ebb4caSwyllys 					continue;
134499ebb4caSwyllys 				} else if (rv != KMF_OK) {
134599ebb4caSwyllys 					free(fname);
134699ebb4caSwyllys 					break;
134799ebb4caSwyllys 				}
134899ebb4caSwyllys 
134999ebb4caSwyllys 				if (unlink(fname) != 0) {
135099ebb4caSwyllys 					SET_SYS_ERROR(kmfh, errno);
135199ebb4caSwyllys 					rv = KMF_ERR_INTERNAL;
135299ebb4caSwyllys 					free(fname);
135399ebb4caSwyllys 					break;
135499ebb4caSwyllys 				}
135599ebb4caSwyllys 				free(fname);
1356e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certdata);
135799ebb4caSwyllys 			}
135899ebb4caSwyllys 		}
135999ebb4caSwyllys 		(void) closedir(dirp);
136099ebb4caSwyllys 	} else {
136199ebb4caSwyllys 		/* Just try to load a single certificate */
136230a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
136330a5e8faSwyllys 		    fullpath, &certdata);
136499ebb4caSwyllys 		if (rv == KMF_OK) {
136599ebb4caSwyllys 			if (unlink(fullpath) != 0) {
136699ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
136799ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
136899ebb4caSwyllys 			}
136999ebb4caSwyllys 		}
137099ebb4caSwyllys 	}
137199ebb4caSwyllys 
137299ebb4caSwyllys out:
137399ebb4caSwyllys 	if (fullpath != NULL)
137499ebb4caSwyllys 		free(fullpath);
137599ebb4caSwyllys 
1376e65e5c2dSWyllys Ingersoll 	kmf_free_data(&certdata);
137799ebb4caSwyllys 
137899ebb4caSwyllys 	return (rv);
137999ebb4caSwyllys }
138099ebb4caSwyllys 
138199ebb4caSwyllys KMF_RETURN
138299ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
138399ebb4caSwyllys 	KMF_DATA *keydata)
138499ebb4caSwyllys {
138599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
138699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
138799ebb4caSwyllys 	int n;
138899ebb4caSwyllys 
138999ebb4caSwyllys 	if (key == NULL || keydata == NULL ||
139099ebb4caSwyllys 	    key->keyp == NULL)
139199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
139299ebb4caSwyllys 
139399ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
139499ebb4caSwyllys 		RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
139599ebb4caSwyllys 
139699ebb4caSwyllys 		if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
139799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
139899ebb4caSwyllys 			return (KMF_ERR_ENCODING);
139999ebb4caSwyllys 		}
140099ebb4caSwyllys 		RSA_free(pubkey);
140199ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
140299ebb4caSwyllys 		DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
140399ebb4caSwyllys 
140499ebb4caSwyllys 		if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
140599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
140699ebb4caSwyllys 			return (KMF_ERR_ENCODING);
140799ebb4caSwyllys 		}
140899ebb4caSwyllys 		DSA_free(pubkey);
140999ebb4caSwyllys 	} else {
141099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
141199ebb4caSwyllys 	}
141299ebb4caSwyllys 	keydata->Length = n;
141399ebb4caSwyllys 
141499ebb4caSwyllys cleanup:
141599ebb4caSwyllys 	if (rv != KMF_OK) {
141699ebb4caSwyllys 		if (keydata->Data)
141799ebb4caSwyllys 			free(keydata->Data);
141899ebb4caSwyllys 		keydata->Data = NULL;
141999ebb4caSwyllys 		keydata->Length = 0;
142099ebb4caSwyllys 	}
142199ebb4caSwyllys 
142299ebb4caSwyllys 	return (rv);
142399ebb4caSwyllys }
142499ebb4caSwyllys 
142599ebb4caSwyllys static KMF_RETURN
142630a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
142730a5e8faSwyllys 	KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
142899ebb4caSwyllys {
142999ebb4caSwyllys 	int rv = 0;
143099ebb4caSwyllys 	RSA *rsa;
143199ebb4caSwyllys 	DSA *dsa;
143299ebb4caSwyllys 
14335b3e1433Swyllys 	if (pkey == NULL || out == NULL)
14345b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
14355b3e1433Swyllys 
143699ebb4caSwyllys 	switch (format) {
143773cc0e02Swyllys 		case KMF_FORMAT_RAWKEY:
143873cc0e02Swyllys 			/* same as ASN.1 */
143999ebb4caSwyllys 		case KMF_FORMAT_ASN1:
1440300fdee2SAndy Fiddaman 			if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
144130a5e8faSwyllys 				if (private)
144299ebb4caSwyllys 					rv = i2d_RSAPrivateKey_bio(out, rsa);
144330a5e8faSwyllys 				else
144430a5e8faSwyllys 					rv = i2d_RSAPublicKey_bio(out, rsa);
1445300fdee2SAndy Fiddaman 			} else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
144699ebb4caSwyllys 				rv = i2d_DSAPrivateKey_bio(out, dsa);
144799ebb4caSwyllys 			}
144899ebb4caSwyllys 			if (rv == 1) {
144999ebb4caSwyllys 				rv = KMF_OK;
145099ebb4caSwyllys 			} else {
145199ebb4caSwyllys 				SET_ERROR(kmfh, rv);
145299ebb4caSwyllys 			}
145399ebb4caSwyllys 			break;
145499ebb4caSwyllys 		case KMF_FORMAT_PEM:
1455300fdee2SAndy Fiddaman 			if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
145630a5e8faSwyllys 				if (private)
145799ebb4caSwyllys 					rv = PEM_write_bio_RSAPrivateKey(out,
145830a5e8faSwyllys 					    rsa, NULL, NULL, 0, NULL,
145930a5e8faSwyllys 					    (cred != NULL ? cred->cred : NULL));
146030a5e8faSwyllys 				else
146130a5e8faSwyllys 					rv = PEM_write_bio_RSAPublicKey(out,
146230a5e8faSwyllys 					    rsa);
1463300fdee2SAndy Fiddaman 			} else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
146499ebb4caSwyllys 				rv = PEM_write_bio_DSAPrivateKey(out,
146530a5e8faSwyllys 				    dsa, NULL, NULL, 0, NULL,
146630a5e8faSwyllys 				    (cred != NULL ? cred->cred : NULL));
146799ebb4caSwyllys 			}
146899ebb4caSwyllys 
146999ebb4caSwyllys 			if (rv == 1) {
147099ebb4caSwyllys 				rv = KMF_OK;
147199ebb4caSwyllys 			} else {
147299ebb4caSwyllys 				SET_ERROR(kmfh, rv);
147399ebb4caSwyllys 			}
147499ebb4caSwyllys 			break;
147599ebb4caSwyllys 
147699ebb4caSwyllys 		default:
147799ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
147899ebb4caSwyllys 	}
147999ebb4caSwyllys 
148099ebb4caSwyllys 	return (rv);
148199ebb4caSwyllys }
148299ebb4caSwyllys 
148399ebb4caSwyllys KMF_RETURN
148430a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
148530a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
148699ebb4caSwyllys {
148799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
148899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1489300fdee2SAndy Fiddaman 	uint32_t eValue = RSA_F4;
1490300fdee2SAndy Fiddaman 	BIGNUM *eValue_bn = NULL;
149199ebb4caSwyllys 	RSA *sslPrivKey = NULL;
149299ebb4caSwyllys 	DSA *sslDSAKey = NULL;
149399ebb4caSwyllys 	EVP_PKEY *eprikey = NULL;
149499ebb4caSwyllys 	EVP_PKEY *epubkey = NULL;
149599ebb4caSwyllys 	BIO *out = NULL;
149630a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
149730a5e8faSwyllys 	uint32_t keylen = 1024;
149830a5e8faSwyllys 	uint32_t keylen_size = sizeof (uint32_t);
149930a5e8faSwyllys 	boolean_t storekey = TRUE;
150030a5e8faSwyllys 	KMF_KEY_ALG keytype = KMF_RSA;
150199ebb4caSwyllys 
1502300fdee2SAndy Fiddaman 	eValue_bn = BN_new();
1503300fdee2SAndy Fiddaman 	if (eValue_bn == NULL)
1504300fdee2SAndy Fiddaman 		return (KMF_ERR_MEMORY);
1505300fdee2SAndy Fiddaman 	if (BN_set_word(eValue_bn, eValue) == 0) {
1506300fdee2SAndy Fiddaman 		rv = KMF_ERR_KEYGEN_FAILED;
1507300fdee2SAndy Fiddaman 		goto cleanup;
1508300fdee2SAndy Fiddaman 	}
1509300fdee2SAndy Fiddaman 
151030a5e8faSwyllys 	rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
151130a5e8faSwyllys 	    &storekey, NULL);
151230a5e8faSwyllys 	if (rv != KMF_OK) {
151330a5e8faSwyllys 		/* "storekey" is optional. Default is TRUE */
151430a5e8faSwyllys 		rv = KMF_OK;
151599ebb4caSwyllys 	}
151699ebb4caSwyllys 
151730a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
151830a5e8faSwyllys 	    (void *)&keytype, NULL);
151930a5e8faSwyllys 	if (rv != KMF_OK)
152030a5e8faSwyllys 		/* keytype is optional.  KMF_RSA is default */
152130a5e8faSwyllys 		rv = KMF_OK;
152299ebb4caSwyllys 
152330a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
1524300fdee2SAndy Fiddaman 	if (pubkey == NULL) {
1525300fdee2SAndy Fiddaman 		rv = KMF_ERR_BAD_PARAMETER;
1526300fdee2SAndy Fiddaman 		goto cleanup;
1527300fdee2SAndy Fiddaman 	}
152899ebb4caSwyllys 
152930a5e8faSwyllys 	privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
1530300fdee2SAndy Fiddaman 	if (privkey == NULL) {
1531300fdee2SAndy Fiddaman 		rv = KMF_ERR_BAD_PARAMETER;
1532300fdee2SAndy Fiddaman 		goto cleanup;
1533300fdee2SAndy Fiddaman 	}
153430a5e8faSwyllys 
153530a5e8faSwyllys 	(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
153630a5e8faSwyllys 	(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
153799ebb4caSwyllys 
153899ebb4caSwyllys 	eprikey = EVP_PKEY_new();
153999ebb4caSwyllys 	if (eprikey == NULL) {
154099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
154199ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
154299ebb4caSwyllys 		goto cleanup;
154399ebb4caSwyllys 	}
154499ebb4caSwyllys 	epubkey = EVP_PKEY_new();
154599ebb4caSwyllys 	if (epubkey == NULL) {
154699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
154799ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
154899ebb4caSwyllys 		goto cleanup;
154999ebb4caSwyllys 	}
155030a5e8faSwyllys 	if (keytype == KMF_RSA) {
155130a5e8faSwyllys 		KMF_BIGINT *rsaexp = NULL;
155299ebb4caSwyllys 
155330a5e8faSwyllys 		rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
155430a5e8faSwyllys 		if (rsaexp != NULL) {
155530a5e8faSwyllys 			if (rsaexp->len > 0 &&
155630a5e8faSwyllys 			    rsaexp->len <= sizeof (eValue) &&
155730a5e8faSwyllys 			    rsaexp->val != NULL) {
1558a2d4930dSDan OpenSolaris Anderson 				/* LINTED E_BAD_PTR_CAST_ALIGN */
155930a5e8faSwyllys 				eValue = *(uint32_t *)rsaexp->val;
1560300fdee2SAndy Fiddaman 				if (BN_set_word(eValue_bn, eValue) == 0) {
1561300fdee2SAndy Fiddaman 					rv = KMF_ERR_BAD_PARAMETER;
1562300fdee2SAndy Fiddaman 					goto cleanup;
1563300fdee2SAndy Fiddaman 				}
156430a5e8faSwyllys 			} else {
156530a5e8faSwyllys 				rv = KMF_ERR_BAD_PARAMETER;
156630a5e8faSwyllys 				goto cleanup;
156730a5e8faSwyllys 			}
156830a5e8faSwyllys 		} else {
156930a5e8faSwyllys 			/* RSA Exponent is optional. Default is 0x10001 */
157030a5e8faSwyllys 			rv = KMF_OK;
157130a5e8faSwyllys 		}
157230a5e8faSwyllys 
157330a5e8faSwyllys 		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
157430a5e8faSwyllys 		    &keylen, &keylen_size);
157530a5e8faSwyllys 		if (rv == KMF_ERR_ATTR_NOT_FOUND)
157630a5e8faSwyllys 			/* keylen is optional, default is 1024 */
157730a5e8faSwyllys 			rv = KMF_OK;
157830a5e8faSwyllys 		if (rv != KMF_OK) {
157930a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
158030a5e8faSwyllys 			goto cleanup;
158130a5e8faSwyllys 		}
158230a5e8faSwyllys 
1583300fdee2SAndy Fiddaman 		sslPrivKey = RSA_new();
1584300fdee2SAndy Fiddaman 		if (sslPrivKey == NULL ||
1585300fdee2SAndy Fiddaman 		    RSA_generate_key_ex(sslPrivKey, keylen, eValue_bn, NULL)
1586300fdee2SAndy Fiddaman 		    == 0) {
158799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
158899ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
158999ebb4caSwyllys 		} else {
159030a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
159199ebb4caSwyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
159299ebb4caSwyllys 			privkey->keyalg = KMF_RSA;
159399ebb4caSwyllys 			privkey->keyclass = KMF_ASYM_PRI;
159499ebb4caSwyllys 			privkey->israw = FALSE;
159599ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
159630a5e8faSwyllys 
159799ebb4caSwyllys 			/* OpenSSL derives the public key from the private */
159830a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
159999ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
160099ebb4caSwyllys 			pubkey->keyalg = KMF_RSA;
160199ebb4caSwyllys 			pubkey->israw = FALSE;
160299ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
160399ebb4caSwyllys 			pubkey->keyp = (void *)epubkey;
160499ebb4caSwyllys 		}
160530a5e8faSwyllys 	} else if (keytype == KMF_DSA) {
1606300fdee2SAndy Fiddaman 		BIGNUM *p, *q, *g;
1607300fdee2SAndy Fiddaman 
160899ebb4caSwyllys 		sslDSAKey = DSA_new();
160999ebb4caSwyllys 		if (sslDSAKey == NULL) {
161099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
161199ebb4caSwyllys 			return (KMF_ERR_MEMORY);
161299ebb4caSwyllys 		}
161399ebb4caSwyllys 
1614300fdee2SAndy Fiddaman 		p = BN_bin2bn(P, sizeof (P), NULL);
1615300fdee2SAndy Fiddaman 		q = BN_bin2bn(Q, sizeof (Q), NULL);
1616300fdee2SAndy Fiddaman 		g = BN_bin2bn(G, sizeof (G), NULL);
1617300fdee2SAndy Fiddaman 		if (p == NULL || q == NULL || g == NULL) {
1618300fdee2SAndy Fiddaman 			BN_free(p);
1619300fdee2SAndy Fiddaman 			BN_free(q);
1620300fdee2SAndy Fiddaman 			BN_free(g);
162199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
162299ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
162399ebb4caSwyllys 			goto cleanup;
162499ebb4caSwyllys 		}
1625300fdee2SAndy Fiddaman 
1626300fdee2SAndy Fiddaman 		if (DSA_set0_pqg(sslDSAKey, p, q, g) == 0) {
162799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
162899ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
162999ebb4caSwyllys 			goto cleanup;
163099ebb4caSwyllys 		}
163199ebb4caSwyllys 
163299ebb4caSwyllys 		if (!DSA_generate_key(sslDSAKey)) {
163399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
163499ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
163599ebb4caSwyllys 			goto cleanup;
163699ebb4caSwyllys 		}
163799ebb4caSwyllys 
163899ebb4caSwyllys 		privkey->kstype = KMF_KEYSTORE_OPENSSL;
163999ebb4caSwyllys 		privkey->keyalg = KMF_DSA;
164099ebb4caSwyllys 		privkey->keyclass = KMF_ASYM_PRI;
164199ebb4caSwyllys 		privkey->israw = FALSE;
164299ebb4caSwyllys 		if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
164399ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
164499ebb4caSwyllys 		} else {
164599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
164699ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
164799ebb4caSwyllys 			goto cleanup;
164899ebb4caSwyllys 		}
164999ebb4caSwyllys 
165099ebb4caSwyllys 		pubkey->kstype = KMF_KEYSTORE_OPENSSL;
165199ebb4caSwyllys 		pubkey->keyalg = KMF_DSA;
165299ebb4caSwyllys 		pubkey->keyclass = KMF_ASYM_PUB;
165399ebb4caSwyllys 		pubkey->israw = FALSE;
165499ebb4caSwyllys 
165599ebb4caSwyllys 		if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
165699ebb4caSwyllys 			pubkey->keyp = (void *)epubkey;
165799ebb4caSwyllys 		} else {
165899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
165999ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
166099ebb4caSwyllys 			goto cleanup;
166199ebb4caSwyllys 		}
166299ebb4caSwyllys 	}
166399ebb4caSwyllys 
166499ebb4caSwyllys 	if (rv != KMF_OK) {
166599ebb4caSwyllys 		goto cleanup;
166699ebb4caSwyllys 	}
166799ebb4caSwyllys 
166830a5e8faSwyllys 	if (storekey) {
166930a5e8faSwyllys 		KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
167030a5e8faSwyllys 		int i = 0;
167130a5e8faSwyllys 		char *keyfile = NULL, *dirpath = NULL;
167230a5e8faSwyllys 		KMF_ENCODE_FORMAT format;
167330a5e8faSwyllys 		/*
167430a5e8faSwyllys 		 * Construct a new attribute arrray and call openssl_store_key
167530a5e8faSwyllys 		 */
167630a5e8faSwyllys 		kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
167730a5e8faSwyllys 		    privkey, sizeof (privkey));
167830a5e8faSwyllys 		i++;
167930a5e8faSwyllys 
168030a5e8faSwyllys 		dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
168130a5e8faSwyllys 		if (dirpath != NULL) {
168230a5e8faSwyllys 			storeattrs[i].type = KMF_DIRPATH_ATTR;
168330a5e8faSwyllys 			storeattrs[i].pValue = dirpath;
168430a5e8faSwyllys 			storeattrs[i].valueLen = strlen(dirpath);
168530a5e8faSwyllys 			i++;
168630a5e8faSwyllys 		} else {
168730a5e8faSwyllys 			rv = KMF_OK; /* DIRPATH is optional */
168899ebb4caSwyllys 		}
168930a5e8faSwyllys 		keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
169030a5e8faSwyllys 		    attrlist, numattr);
169130a5e8faSwyllys 		if (keyfile != NULL) {
169230a5e8faSwyllys 			storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
169330a5e8faSwyllys 			storeattrs[i].pValue = keyfile;
169430a5e8faSwyllys 			storeattrs[i].valueLen = strlen(keyfile);
169530a5e8faSwyllys 			i++;
169630a5e8faSwyllys 		} else {
169730a5e8faSwyllys 			goto cleanup; /* KEYFILE is required */
169830a5e8faSwyllys 		}
169930a5e8faSwyllys 		rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
170030a5e8faSwyllys 		    (void *)&format, NULL);
170130a5e8faSwyllys 		if (rv == KMF_OK) {
170230a5e8faSwyllys 			storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
170330a5e8faSwyllys 			storeattrs[i].pValue = &format;
170430a5e8faSwyllys 			storeattrs[i].valueLen = sizeof (format);
170530a5e8faSwyllys 			i++;
170630a5e8faSwyllys 		}
170730a5e8faSwyllys 
170830a5e8faSwyllys 		rv = OpenSSL_StoreKey(handle, i, storeattrs);
170930a5e8faSwyllys 	}
171099ebb4caSwyllys 
171199ebb4caSwyllys cleanup:
1712300fdee2SAndy Fiddaman 	if (eValue_bn != NULL)
1713300fdee2SAndy Fiddaman 		BN_free(eValue_bn);
1714300fdee2SAndy Fiddaman 
171599ebb4caSwyllys 	if (rv != KMF_OK) {
171699ebb4caSwyllys 		if (eprikey != NULL)
171799ebb4caSwyllys 			EVP_PKEY_free(eprikey);
171899ebb4caSwyllys 
171999ebb4caSwyllys 		if (epubkey != NULL)
172099ebb4caSwyllys 			EVP_PKEY_free(epubkey);
172199ebb4caSwyllys 
172299ebb4caSwyllys 		if (pubkey->keylabel) {
172399ebb4caSwyllys 			free(pubkey->keylabel);
172499ebb4caSwyllys 			pubkey->keylabel = NULL;
172599ebb4caSwyllys 		}
172699ebb4caSwyllys 
172799ebb4caSwyllys 		if (privkey->keylabel) {
172899ebb4caSwyllys 			free(privkey->keylabel);
172999ebb4caSwyllys 			privkey->keylabel = NULL;
173099ebb4caSwyllys 		}
173199ebb4caSwyllys 
173299ebb4caSwyllys 		pubkey->keyp = NULL;
173399ebb4caSwyllys 		privkey->keyp = NULL;
173499ebb4caSwyllys 	}
173599ebb4caSwyllys 
173699ebb4caSwyllys 	if (sslPrivKey)
173799ebb4caSwyllys 		RSA_free(sslPrivKey);
173899ebb4caSwyllys 
173999ebb4caSwyllys 	if (sslDSAKey)
174099ebb4caSwyllys 		DSA_free(sslDSAKey);
174199ebb4caSwyllys 
174299ebb4caSwyllys 	if (out != NULL)
174399ebb4caSwyllys 		(void) BIO_free(out);
174499ebb4caSwyllys 
174599ebb4caSwyllys 	return (rv);
174699ebb4caSwyllys }
174799ebb4caSwyllys 
1748e65e5c2dSWyllys Ingersoll /*
1749e65e5c2dSWyllys Ingersoll  * Make sure the BN conversion is properly padded with 0x00
1750e65e5c2dSWyllys Ingersoll  * bytes.  If not, signature verification for DSA signatures
1751e65e5c2dSWyllys Ingersoll  * may fail in the case where the bignum value does not use
1752e65e5c2dSWyllys Ingersoll  * all of the bits.
1753e65e5c2dSWyllys Ingersoll  */
1754e65e5c2dSWyllys Ingersoll static int
1755300fdee2SAndy Fiddaman fixbnlen(const BIGNUM *bn, unsigned char *buf, int len) {
1756e65e5c2dSWyllys Ingersoll 	int bytes = len - BN_num_bytes(bn);
17572c9a247fSWyllys Ingersoll 
17582c9a247fSWyllys Ingersoll 	/* prepend with leading 0x00 if necessary */
1759e65e5c2dSWyllys Ingersoll 	while (bytes-- > 0)
1760e65e5c2dSWyllys Ingersoll 		*buf++ = 0;
1761e65e5c2dSWyllys Ingersoll 
17622c9a247fSWyllys Ingersoll 	(void) BN_bn2bin(bn, buf);
17632c9a247fSWyllys Ingersoll 	/*
17642c9a247fSWyllys Ingersoll 	 * Return the desired length since we prepended it
17652c9a247fSWyllys Ingersoll 	 * with the necessary 0x00 padding.
17662c9a247fSWyllys Ingersoll 	 */
17672c9a247fSWyllys Ingersoll 	return (len);
1768e65e5c2dSWyllys Ingersoll }
1769e65e5c2dSWyllys Ingersoll 
177099ebb4caSwyllys KMF_RETURN
177199ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
177299ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
177399ebb4caSwyllys {
177499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
177599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
177699ebb4caSwyllys 	KMF_ALGORITHM_INDEX		AlgId;
1777300fdee2SAndy Fiddaman 	EVP_MD_CTX *ctx;
177899ebb4caSwyllys 	const EVP_MD *md;
177902744e81Swyllys 
178099ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
178199ebb4caSwyllys 	    tobesigned == NULL || output == NULL ||
178299ebb4caSwyllys 	    tobesigned->Data == NULL ||
178399ebb4caSwyllys 	    output->Data == NULL)
178499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
178599ebb4caSwyllys 
178699ebb4caSwyllys 	/* Map the OID to an OpenSSL algorithm */
178730a5e8faSwyllys 	AlgId = x509_algoid_to_algid(AlgOID);
178899ebb4caSwyllys 	if (AlgId == KMF_ALGID_NONE)
1789e65e5c2dSWyllys Ingersoll 		return (KMF_ERR_BAD_ALGORITHM);
179099ebb4caSwyllys 
179199ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
179299ebb4caSwyllys 		EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
179399ebb4caSwyllys 		uchar_t *p;
179402744e81Swyllys 		int len;
1795*553e44ceSAndrew Stormont 		switch (AlgId) {
1796*553e44ceSAndrew Stormont #ifndef	OPENSSL_NO_MD5
1797*553e44ceSAndrew Stormont 		case KMF_ALGID_MD5WithRSA:
179899ebb4caSwyllys 			md = EVP_md5();
1799*553e44ceSAndrew Stormont 			break;
1800*553e44ceSAndrew Stormont #endif
1801*553e44ceSAndrew Stormont #ifndef	OPENSSL_NO_SHA
1802*553e44ceSAndrew Stormont 		case KMF_ALGID_SHA1WithRSA:
180399ebb4caSwyllys 			md = EVP_sha1();
1804*553e44ceSAndrew Stormont 			break;
1805*553e44ceSAndrew Stormont #endif
1806*553e44ceSAndrew Stormont #ifndef	OPENSSL_NO_SHA256
1807*553e44ceSAndrew Stormont 		case KMF_ALGID_SHA256WithRSA:
1808e65e5c2dSWyllys Ingersoll 			md = EVP_sha256();
1809*553e44ceSAndrew Stormont 			break;
1810*553e44ceSAndrew Stormont #endif
1811*553e44ceSAndrew Stormont #ifndef	OPENSSL_NO_SHA512
1812*553e44ceSAndrew Stormont 		case KMF_ALGID_SHA384WithRSA:
1813e65e5c2dSWyllys Ingersoll 			md = EVP_sha384();
1814*553e44ceSAndrew Stormont 			break;
1815*553e44ceSAndrew Stormont 		case KMF_ALGID_SHA512WithRSA:
1816e65e5c2dSWyllys Ingersoll 			md = EVP_sha512();
1817*553e44ceSAndrew Stormont 			break;
1818*553e44ceSAndrew Stormont #endif
1819*553e44ceSAndrew Stormont 		case KMF_ALGID_RSA:
182002744e81Swyllys 			md = NULL;
1821*553e44ceSAndrew Stormont 			break;
1822*553e44ceSAndrew Stormont 		default:
1823e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_ALGORITHM);
1824*553e44ceSAndrew Stormont 		}
182599ebb4caSwyllys 
182602744e81Swyllys 		if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
182702744e81Swyllys 			RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
182899ebb4caSwyllys 
182902744e81Swyllys 			p = output->Data;
183002744e81Swyllys 			if ((len = RSA_private_encrypt(tobesigned->Length,
183102744e81Swyllys 			    tobesigned->Data, p, rsa,
183202744e81Swyllys 			    RSA_PKCS1_PADDING)) <= 0) {
183302744e81Swyllys 				SET_ERROR(kmfh, ERR_get_error());
183402744e81Swyllys 				ret = KMF_ERR_INTERNAL;
183502744e81Swyllys 			}
183602744e81Swyllys 			output->Length = len;
183702744e81Swyllys 		} else {
1838300fdee2SAndy Fiddaman 			if ((ctx = EVP_MD_CTX_new()) == NULL)
1839300fdee2SAndy Fiddaman 				return (KMF_ERR_MEMORY);
1840300fdee2SAndy Fiddaman 			(void) EVP_SignInit_ex(ctx, md, NULL);
1841300fdee2SAndy Fiddaman 			(void) EVP_SignUpdate(ctx, tobesigned->Data,
184299ebb4caSwyllys 			    (uint32_t)tobesigned->Length);
184399ebb4caSwyllys 			len = (uint32_t)output->Length;
184499ebb4caSwyllys 			p = output->Data;
1845300fdee2SAndy Fiddaman 			if (!EVP_SignFinal(ctx, p, (uint32_t *)&len, pkey)) {
184699ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
184702744e81Swyllys 				len = 0;
184802744e81Swyllys 				ret = KMF_ERR_INTERNAL;
184999ebb4caSwyllys 			}
185099ebb4caSwyllys 			output->Length = len;
1851300fdee2SAndy Fiddaman 			EVP_MD_CTX_free(ctx);
185202744e81Swyllys 		}
185399ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
185499ebb4caSwyllys 		DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
185599ebb4caSwyllys 
185699ebb4caSwyllys 		uchar_t hash[EVP_MAX_MD_SIZE];
185799ebb4caSwyllys 		uint32_t hashlen;
185899ebb4caSwyllys 		DSA_SIG *dsasig;
185999ebb4caSwyllys 
1860e65e5c2dSWyllys Ingersoll 		if (AlgId == KMF_ALGID_DSA ||
1861e65e5c2dSWyllys Ingersoll 		    AlgId == KMF_ALGID_SHA1WithDSA)
1862e65e5c2dSWyllys Ingersoll 			md = EVP_sha1();
1863e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA256WithDSA)
1864e65e5c2dSWyllys Ingersoll 			md = EVP_sha256();
1865e65e5c2dSWyllys Ingersoll 		else /* Bad algorithm */
1866e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_ALGORITHM);
1867e65e5c2dSWyllys Ingersoll 
186899ebb4caSwyllys 		/*
186999ebb4caSwyllys 		 * OpenSSL EVP_Sign operation automatically converts to
187099ebb4caSwyllys 		 * ASN.1 output so we do the operations separately so we
187199ebb4caSwyllys 		 * are assured of NOT getting ASN.1 output returned.
187299ebb4caSwyllys 		 * KMF does not want ASN.1 encoded results because
187399ebb4caSwyllys 		 * not all mechanisms return ASN.1 encodings (PKCS#11
187499ebb4caSwyllys 		 * and NSS return raw signature data).
187599ebb4caSwyllys 		 */
1876300fdee2SAndy Fiddaman 		if ((ctx = EVP_MD_CTX_new()) == NULL)
1877300fdee2SAndy Fiddaman 			return (KMF_ERR_MEMORY);
1878300fdee2SAndy Fiddaman 		(void) EVP_DigestInit_ex(ctx, md, NULL);
1879300fdee2SAndy Fiddaman 		(void) EVP_DigestUpdate(ctx, tobesigned->Data,
188099ebb4caSwyllys 		    tobesigned->Length);
1881300fdee2SAndy Fiddaman 		(void) EVP_DigestFinal_ex(ctx, hash, &hashlen);
188299ebb4caSwyllys 
1883e65e5c2dSWyllys Ingersoll 		/* Only sign first 20 bytes for SHA2 */
1884e65e5c2dSWyllys Ingersoll 		if (AlgId == KMF_ALGID_SHA256WithDSA)
1885e65e5c2dSWyllys Ingersoll 			hashlen = 20;
188699ebb4caSwyllys 		dsasig = DSA_do_sign(hash, hashlen, dsa);
188799ebb4caSwyllys 		if (dsasig != NULL) {
188899ebb4caSwyllys 			int i;
1889300fdee2SAndy Fiddaman 			const BIGNUM *r, *s;
1890300fdee2SAndy Fiddaman 
1891300fdee2SAndy Fiddaman 			DSA_SIG_get0(dsasig, &r, &s);
1892300fdee2SAndy Fiddaman 			output->Length = i = fixbnlen(r, output->Data,
1893e65e5c2dSWyllys Ingersoll 			    hashlen);
18942c9a247fSWyllys Ingersoll 
1895300fdee2SAndy Fiddaman 			output->Length += fixbnlen(s, &output->Data[i],
1896e65e5c2dSWyllys Ingersoll 			    hashlen);
18972c9a247fSWyllys Ingersoll 
189899ebb4caSwyllys 			DSA_SIG_free(dsasig);
189999ebb4caSwyllys 		} else {
190099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
190199ebb4caSwyllys 		}
1902300fdee2SAndy Fiddaman 		EVP_MD_CTX_free(ctx);
190399ebb4caSwyllys 	} else {
190499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
190599ebb4caSwyllys 	}
190699ebb4caSwyllys cleanup:
190799ebb4caSwyllys 	return (ret);
190899ebb4caSwyllys }
190999ebb4caSwyllys 
191099ebb4caSwyllys KMF_RETURN
191199ebb4caSwyllys /*ARGSUSED*/
191230a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle,
191330a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
191499ebb4caSwyllys {
191599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
191630a5e8faSwyllys 	KMF_KEY_HANDLE *key;
191730a5e8faSwyllys 	boolean_t destroy = B_TRUE;
191830a5e8faSwyllys 
191930a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
192099ebb4caSwyllys 	if (key == NULL || key->keyp == NULL)
192199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
192299ebb4caSwyllys 
192330a5e8faSwyllys 	rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
192430a5e8faSwyllys 	    (void *)&destroy, NULL);
192530a5e8faSwyllys 	if (rv != KMF_OK) {
192630a5e8faSwyllys 		/* "destroy" is optional. Default is TRUE */
192730a5e8faSwyllys 		rv = KMF_OK;
192830a5e8faSwyllys 	}
192930a5e8faSwyllys 
193099ebb4caSwyllys 	if (key->keyclass != KMF_ASYM_PUB &&
193199ebb4caSwyllys 	    key->keyclass != KMF_ASYM_PRI &&
193299ebb4caSwyllys 	    key->keyclass != KMF_SYMMETRIC)
193399ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
193499ebb4caSwyllys 
193599ebb4caSwyllys 	if (key->keyclass == KMF_SYMMETRIC) {
193630a5e8faSwyllys 		kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
193799ebb4caSwyllys 		key->keyp = NULL;
193899ebb4caSwyllys 	} else {
193999ebb4caSwyllys 		if (key->keyp != NULL) {
194099ebb4caSwyllys 			EVP_PKEY_free(key->keyp);
194199ebb4caSwyllys 			key->keyp = NULL;
194299ebb4caSwyllys 		}
194399ebb4caSwyllys 	}
194499ebb4caSwyllys 
194599ebb4caSwyllys 	if (key->keylabel != NULL) {
194699ebb4caSwyllys 		EVP_PKEY *pkey = NULL;
194799ebb4caSwyllys 		/* If the file exists, make sure it is a proper key. */
194899ebb4caSwyllys 		pkey = openssl_load_key(handle, key->keylabel);
194999ebb4caSwyllys 		if (pkey == NULL) {
19505b3e1433Swyllys 			if (key->keylabel != NULL) {
195199ebb4caSwyllys 				free(key->keylabel);
195299ebb4caSwyllys 				key->keylabel = NULL;
19535b3e1433Swyllys 			}
195499ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
195599ebb4caSwyllys 		}
195699ebb4caSwyllys 		EVP_PKEY_free(pkey);
195799ebb4caSwyllys 
195899ebb4caSwyllys 		if (destroy) {
195999ebb4caSwyllys 			if (unlink(key->keylabel) != 0) {
196099ebb4caSwyllys 				KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
196199ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
196299ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
196399ebb4caSwyllys 			}
196499ebb4caSwyllys 		}
196599ebb4caSwyllys 		if (key->keylabel != NULL) {
196699ebb4caSwyllys 			free(key->keylabel);
196799ebb4caSwyllys 			key->keylabel = NULL;
196899ebb4caSwyllys 		}
196999ebb4caSwyllys 	}
197099ebb4caSwyllys 	return (rv);
197199ebb4caSwyllys }
197299ebb4caSwyllys 
197399ebb4caSwyllys KMF_RETURN
197499ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
197599ebb4caSwyllys {
197699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
197799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
197899ebb4caSwyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
197999ebb4caSwyllys 
198099ebb4caSwyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
198199ebb4caSwyllys 	if (strlen(str)) {
198299ebb4caSwyllys 		*msgstr = (char *)strdup(str);
198399ebb4caSwyllys 		if ((*msgstr) == NULL)
198499ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
198599ebb4caSwyllys 	} else {
198699ebb4caSwyllys 		*msgstr = NULL;
198799ebb4caSwyllys 	}
198899ebb4caSwyllys 
198999ebb4caSwyllys 	return (ret);
199099ebb4caSwyllys }
199199ebb4caSwyllys 
199299ebb4caSwyllys static int
199399ebb4caSwyllys ext2NID(int kmfext)
199499ebb4caSwyllys {
199599ebb4caSwyllys 	switch (kmfext) {
199699ebb4caSwyllys 		case KMF_X509_EXT_KEY_USAGE:
199799ebb4caSwyllys 			return (NID_key_usage);
199899ebb4caSwyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
199999ebb4caSwyllys 			return (NID_private_key_usage_period);
200099ebb4caSwyllys 		case KMF_X509_EXT_CERT_POLICIES:
200199ebb4caSwyllys 			return (NID_certificate_policies);
200299ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
200399ebb4caSwyllys 			return (NID_subject_alt_name);
200499ebb4caSwyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
200599ebb4caSwyllys 			return (NID_issuer_alt_name);
200699ebb4caSwyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
200799ebb4caSwyllys 			return (NID_basic_constraints);
200899ebb4caSwyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
200999ebb4caSwyllys 			return (NID_ext_key_usage);
201099ebb4caSwyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
201199ebb4caSwyllys 			return (NID_authority_key_identifier);
201299ebb4caSwyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
201399ebb4caSwyllys 			return (NID_crl_distribution_points);
201499ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
201599ebb4caSwyllys 			return (NID_subject_key_identifier);
201699ebb4caSwyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
201799ebb4caSwyllys 			return (OBJ_sn2nid("policyMappings"));
201899ebb4caSwyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
201999ebb4caSwyllys 			return (OBJ_sn2nid("nameConstraints"));
202099ebb4caSwyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
202199ebb4caSwyllys 			return (OBJ_sn2nid("policyConstraints"));
202299ebb4caSwyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
202399ebb4caSwyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
202499ebb4caSwyllys 		case KMF_X509_EXT_FRESHEST_CRL:
202599ebb4caSwyllys 			return (OBJ_sn2nid("freshestCRL"));
202699ebb4caSwyllys 		default:
202799ebb4caSwyllys 			return (NID_undef);
202899ebb4caSwyllys 	}
202999ebb4caSwyllys }
203099ebb4caSwyllys 
203199ebb4caSwyllys KMF_RETURN
203299ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
203399ebb4caSwyllys 	KMF_PRINTABLE_ITEM flag, char *resultStr)
203499ebb4caSwyllys {
203599ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
203699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
203799ebb4caSwyllys 	X509 *xcert = NULL;
203899ebb4caSwyllys 	unsigned char *outbuf = NULL;
203999ebb4caSwyllys 	unsigned char *outbuf_p;
204099ebb4caSwyllys 	int j;
204199ebb4caSwyllys 	int ext_index, nid, len;
204299ebb4caSwyllys 	BIO *mem = NULL;
204370f9559bSTheo Schlossnagle 	STACK_OF(OPENSSL_STRING) *emlst = NULL;
204499ebb4caSwyllys 	X509_EXTENSION *ex;
204599ebb4caSwyllys 
204699ebb4caSwyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
204799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
204899ebb4caSwyllys 	}
204999ebb4caSwyllys 
205099ebb4caSwyllys 	/* copy cert data to outbuf */
205199ebb4caSwyllys 	outbuf = malloc(pcert->Length);
205299ebb4caSwyllys 	if (outbuf == NULL) {
205399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
205499ebb4caSwyllys 	}
205599ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
205699ebb4caSwyllys 
205799ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
205899ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
205999ebb4caSwyllys 	if (xcert == NULL) {
206099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
206199ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
206299ebb4caSwyllys 		goto out;
206399ebb4caSwyllys 	}
206499ebb4caSwyllys 
206599ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
206699ebb4caSwyllys 	if (mem == NULL) {
206799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
206899ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
206999ebb4caSwyllys 		goto out;
207099ebb4caSwyllys 	}
207199ebb4caSwyllys 
207299ebb4caSwyllys 	switch (flag) {
207399ebb4caSwyllys 	case KMF_CERT_ISSUER:
207499ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
207599ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
207699ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
207799ebb4caSwyllys 		break;
207899ebb4caSwyllys 
207999ebb4caSwyllys 	case KMF_CERT_SUBJECT:
208099ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
208199ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
208299ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
208399ebb4caSwyllys 		break;
208499ebb4caSwyllys 
208599ebb4caSwyllys 	case KMF_CERT_VERSION:
2086300fdee2SAndy Fiddaman 		(void) snprintf(resultStr, KMF_CERT_PRINTABLE_LEN,
2087300fdee2SAndy Fiddaman 		    "%ld", X509_get_version(xcert));
208899ebb4caSwyllys 		len = strlen(resultStr);
208999ebb4caSwyllys 		break;
209099ebb4caSwyllys 
209199ebb4caSwyllys 	case KMF_CERT_SERIALNUM:
209299ebb4caSwyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
209399ebb4caSwyllys 			(void) strcpy(resultStr, "0x");
209499ebb4caSwyllys 			len = BIO_gets(mem, &resultStr[2],
209599ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN - 2);
209699ebb4caSwyllys 		}
209799ebb4caSwyllys 		break;
209899ebb4caSwyllys 
209999ebb4caSwyllys 	case KMF_CERT_NOTBEFORE:
2100300fdee2SAndy Fiddaman 		(void) ASN1_TIME_print(mem, X509_getm_notBefore(xcert));
210199ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
210299ebb4caSwyllys 		break;
210399ebb4caSwyllys 
210499ebb4caSwyllys 	case KMF_CERT_NOTAFTER:
2105300fdee2SAndy Fiddaman 		(void) ASN1_TIME_print(mem, X509_getm_notAfter(xcert));
210699ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
210799ebb4caSwyllys 		break;
210899ebb4caSwyllys 
210999ebb4caSwyllys 	case KMF_CERT_PUBKEY_DATA:
211099ebb4caSwyllys 		{
2111300fdee2SAndy Fiddaman 			RSA *rsa;
2112300fdee2SAndy Fiddaman 			DSA *dsa;
2113300fdee2SAndy Fiddaman 
211499ebb4caSwyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
211599ebb4caSwyllys 			if (pkey == NULL) {
211699ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
211799ebb4caSwyllys 				ret = KMF_ERR_ENCODING;
211899ebb4caSwyllys 				goto out;
211999ebb4caSwyllys 			}
212099ebb4caSwyllys 
2121300fdee2SAndy Fiddaman 			if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
212299ebb4caSwyllys 				(void) BIO_printf(mem,
212399ebb4caSwyllys 				    "RSA Public Key: (%d bit)\n",
2124300fdee2SAndy Fiddaman 				    RSA_bits(rsa));
2125300fdee2SAndy Fiddaman 				(void) RSA_print(mem, rsa, 0);
2126300fdee2SAndy Fiddaman 
2127300fdee2SAndy Fiddaman 			} else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
212899ebb4caSwyllys 				(void) BIO_printf(mem,
212999ebb4caSwyllys 				    "%12sDSA Public Key:\n", "");
2130300fdee2SAndy Fiddaman 				(void) DSA_print(mem, dsa, 0);
213199ebb4caSwyllys 			} else {
213299ebb4caSwyllys 				(void) BIO_printf(mem,
213399ebb4caSwyllys 				    "%12sUnknown Public Key:\n", "");
213499ebb4caSwyllys 			}
213599ebb4caSwyllys 			(void) BIO_printf(mem, "\n");
213699ebb4caSwyllys 			EVP_PKEY_free(pkey);
213799ebb4caSwyllys 		}
213899ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
213999ebb4caSwyllys 		break;
214099ebb4caSwyllys 	case KMF_CERT_SIGNATURE_ALG:
214199ebb4caSwyllys 	case KMF_CERT_PUBKEY_ALG:
2142300fdee2SAndy Fiddaman 		{
2143*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2144300fdee2SAndy Fiddaman 			ASN1_OBJECT *alg = NULL;
2145300fdee2SAndy Fiddaman #else
2146300fdee2SAndy Fiddaman 			const ASN1_OBJECT *alg = NULL;
2147300fdee2SAndy Fiddaman #endif
2148300fdee2SAndy Fiddaman 
214999ebb4caSwyllys 			if (flag == KMF_CERT_SIGNATURE_ALG) {
2150*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2151300fdee2SAndy Fiddaman 				alg = xcert->sig_alg->algorithm;
2152300fdee2SAndy Fiddaman #else
2153300fdee2SAndy Fiddaman 				const X509_ALGOR *sig_alg = NULL;
2154300fdee2SAndy Fiddaman 
2155300fdee2SAndy Fiddaman 				X509_get0_signature(NULL, &sig_alg, xcert);
2156300fdee2SAndy Fiddaman 				if (sig_alg != NULL)
2157300fdee2SAndy Fiddaman 					X509_ALGOR_get0(&alg, NULL, NULL,
2158300fdee2SAndy Fiddaman 					    sig_alg);
2159300fdee2SAndy Fiddaman #endif
216099ebb4caSwyllys 			} else {
2161*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2162300fdee2SAndy Fiddaman 				alg = xcert->cert_info->key->algor->algorithm;
2163300fdee2SAndy Fiddaman #else
2164300fdee2SAndy Fiddaman 				X509_PUBKEY *key = X509_get_X509_PUBKEY(xcert);
2165300fdee2SAndy Fiddaman 
2166300fdee2SAndy Fiddaman 				if (key != NULL)
2167300fdee2SAndy Fiddaman 					(void) X509_PUBKEY_get0_param(
2168300fdee2SAndy Fiddaman 					    (ASN1_OBJECT **)&alg, NULL, 0,
2169300fdee2SAndy Fiddaman 					    NULL, key);
2170300fdee2SAndy Fiddaman #endif
217199ebb4caSwyllys 			}
217299ebb4caSwyllys 
2173300fdee2SAndy Fiddaman 			if (alg == NULL)
2174300fdee2SAndy Fiddaman 				len = -1;
2175300fdee2SAndy Fiddaman 			else if ((len = i2a_ASN1_OBJECT(mem, alg)) > 0)
217699ebb4caSwyllys 				len = BIO_read(mem, resultStr,
217799ebb4caSwyllys 				    KMF_CERT_PRINTABLE_LEN);
217899ebb4caSwyllys 		}
217999ebb4caSwyllys 		break;
218099ebb4caSwyllys 
218199ebb4caSwyllys 	case KMF_CERT_EMAIL:
218299ebb4caSwyllys 		emlst = X509_get1_email(xcert);
218370f9559bSTheo Schlossnagle 		for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
218470f9559bSTheo Schlossnagle 			(void) BIO_printf(mem, "%s\n",
218570f9559bSTheo Schlossnagle 			    sk_OPENSSL_STRING_value(emlst, j));
218699ebb4caSwyllys 
218799ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
218899ebb4caSwyllys 		X509_email_free(emlst);
218999ebb4caSwyllys 		break;
219099ebb4caSwyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
219199ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
219299ebb4caSwyllys 	case KMF_X509_EXT_KEY_USAGE:
219399ebb4caSwyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
219499ebb4caSwyllys 	case KMF_X509_EXT_CERT_POLICIES:
219599ebb4caSwyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
219699ebb4caSwyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
219799ebb4caSwyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
219899ebb4caSwyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
219999ebb4caSwyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
220099ebb4caSwyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
220199ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
220299ebb4caSwyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
220399ebb4caSwyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
220499ebb4caSwyllys 	case KMF_X509_EXT_FRESHEST_CRL:
220599ebb4caSwyllys 		nid = ext2NID(flag);
220699ebb4caSwyllys 		if (nid == NID_undef) {
220799ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
220899ebb4caSwyllys 			goto out;
220999ebb4caSwyllys 		}
221099ebb4caSwyllys 
2211300fdee2SAndy Fiddaman 		ext_index = X509_get_ext_by_NID(xcert, nid, -1);
221299ebb4caSwyllys 		if (ext_index == -1) {
221399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
221499ebb4caSwyllys 
221599ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
221699ebb4caSwyllys 			goto out;
221799ebb4caSwyllys 		}
2218300fdee2SAndy Fiddaman 		ex = X509_get_ext(xcert, ext_index);
221999ebb4caSwyllys 
222099ebb4caSwyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
222199ebb4caSwyllys 
222299ebb4caSwyllys 		if (BIO_printf(mem, ": %s\n",
222330a5e8faSwyllys 		    X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
222499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
222599ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
222699ebb4caSwyllys 			goto out;
222799ebb4caSwyllys 		}
222899ebb4caSwyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
222999ebb4caSwyllys 			(void) BIO_printf(mem, "%*s", 4, "");
2230300fdee2SAndy Fiddaman 			(void) ASN1_STRING_print(mem,
2231300fdee2SAndy Fiddaman 			    X509_EXTENSION_get_data(ex));
223299ebb4caSwyllys 		}
223399ebb4caSwyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
223499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
223599ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
223699ebb4caSwyllys 			goto out;
223799ebb4caSwyllys 		}
223899ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
223999ebb4caSwyllys 	}
224099ebb4caSwyllys 	if (len <= 0) {
224199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
224299ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
224399ebb4caSwyllys 	}
224499ebb4caSwyllys 
224599ebb4caSwyllys out:
224699ebb4caSwyllys 	if (outbuf != NULL) {
224799ebb4caSwyllys 		free(outbuf);
224899ebb4caSwyllys 	}
224999ebb4caSwyllys 
225099ebb4caSwyllys 	if (xcert != NULL) {
225199ebb4caSwyllys 		X509_free(xcert);
225299ebb4caSwyllys 	}
225399ebb4caSwyllys 
225499ebb4caSwyllys 	if (mem != NULL) {
225599ebb4caSwyllys 		(void) BIO_free(mem);
225699ebb4caSwyllys 	}
225799ebb4caSwyllys 
225899ebb4caSwyllys 	return (ret);
225999ebb4caSwyllys }
226030a5e8faSwyllys 
226199ebb4caSwyllys KMF_RETURN
226299ebb4caSwyllys /*ARGSUSED*/
226330a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
226430a5e8faSwyllys     KMF_ATTRIBUTE *attrlist)
226599ebb4caSwyllys {
226699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
226730a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
226830a5e8faSwyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
226930a5e8faSwyllys 	KMF_KEY_HANDLE *key = NULL;
227030a5e8faSwyllys 	uint32_t numkeys = 1; /* 1 key only */
227130a5e8faSwyllys 	char *dirpath = NULL;
227230a5e8faSwyllys 	char *keyfile = NULL;
227330a5e8faSwyllys 	KMF_ATTRIBUTE new_attrlist[16];
227430a5e8faSwyllys 	int i = 0;
227599ebb4caSwyllys 
227699ebb4caSwyllys 	/*
227799ebb4caSwyllys 	 * This is really just a FindKey operation, reuse the
227899ebb4caSwyllys 	 * FindKey function.
227999ebb4caSwyllys 	 */
228030a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
228130a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
228230a5e8faSwyllys 	i++;
228399ebb4caSwyllys 
228430a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
228530a5e8faSwyllys 	    KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
228630a5e8faSwyllys 	i++;
228799ebb4caSwyllys 
228830a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
228930a5e8faSwyllys 	    KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
229030a5e8faSwyllys 	i++;
229130a5e8faSwyllys 
229230a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
229330a5e8faSwyllys 	if (key == NULL) {
229430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
229530a5e8faSwyllys 	} else {
229630a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
229730a5e8faSwyllys 		    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
229830a5e8faSwyllys 		i++;
229930a5e8faSwyllys 	}
230030a5e8faSwyllys 
230130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
230230a5e8faSwyllys 	if (dirpath != NULL) {
230330a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
230430a5e8faSwyllys 		    KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
230530a5e8faSwyllys 		i++;
230630a5e8faSwyllys 	}
230730a5e8faSwyllys 
230830a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
230930a5e8faSwyllys 	if (keyfile == NULL)
231030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
231130a5e8faSwyllys 	else {
231230a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
231330a5e8faSwyllys 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
231430a5e8faSwyllys 		i++;
231530a5e8faSwyllys 	}
231630a5e8faSwyllys 
231730a5e8faSwyllys 	rv = OpenSSL_FindKey(handle, i, new_attrlist);
231899ebb4caSwyllys 	return (rv);
231999ebb4caSwyllys }
232099ebb4caSwyllys 
232199ebb4caSwyllys KMF_RETURN
232299ebb4caSwyllys /*ARGSUSED*/
232399ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
232499ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
232599ebb4caSwyllys 	KMF_DATA *output)
232699ebb4caSwyllys {
232799ebb4caSwyllys 	KMF_RETURN		ret = KMF_OK;
232899ebb4caSwyllys 	RSA *rsa = NULL;
232999ebb4caSwyllys 	unsigned int in_len = 0, out_len = 0;
233099ebb4caSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
233199ebb4caSwyllys 	uint8_t *in_data, *out_data;
233299ebb4caSwyllys 	int i, blocks;
233399ebb4caSwyllys 
233499ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
233599ebb4caSwyllys 	    ciphertext == NULL || output == NULL ||
233699ebb4caSwyllys 	    ciphertext->Data == NULL ||
233799ebb4caSwyllys 	    output->Data == NULL)
233899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
233999ebb4caSwyllys 
234099ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
234199ebb4caSwyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
234299ebb4caSwyllys 		modulus_len = RSA_size(rsa);
234399ebb4caSwyllys 	} else {
234499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
234599ebb4caSwyllys 	}
234699ebb4caSwyllys 
234799ebb4caSwyllys 	blocks = ciphertext->Length/modulus_len;
234899ebb4caSwyllys 	out_data = output->Data;
234999ebb4caSwyllys 	in_data = ciphertext->Data;
235099ebb4caSwyllys 	out_len = modulus_len - 11;
235199ebb4caSwyllys 	in_len = modulus_len;
235299ebb4caSwyllys 
235399ebb4caSwyllys 	for (i = 0; i < blocks; i++) {
235499ebb4caSwyllys 		out_len  = RSA_private_decrypt(in_len,
235599ebb4caSwyllys 		    in_data, out_data, rsa, RSA_PKCS1_PADDING);
235699ebb4caSwyllys 
235799ebb4caSwyllys 		if (out_len == 0) {
235899ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
235999ebb4caSwyllys 			goto cleanup;
236099ebb4caSwyllys 		}
236199ebb4caSwyllys 
236299ebb4caSwyllys 		out_data += out_len;
236399ebb4caSwyllys 		total_decrypted += out_len;
236499ebb4caSwyllys 		in_data += in_len;
236599ebb4caSwyllys 	}
236699ebb4caSwyllys 
236799ebb4caSwyllys 	output->Length = total_decrypted;
236899ebb4caSwyllys 
236999ebb4caSwyllys cleanup:
237099ebb4caSwyllys 	RSA_free(rsa);
237199ebb4caSwyllys 	if (ret != KMF_OK)
237299ebb4caSwyllys 		output->Length = 0;
237399ebb4caSwyllys 
237499ebb4caSwyllys 	return (ret);
237599ebb4caSwyllys 
237699ebb4caSwyllys }
237799ebb4caSwyllys 
237899ebb4caSwyllys /*
237999ebb4caSwyllys  *  This function will create a certid from issuer_cert and user_cert.
238099ebb4caSwyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
238199ebb4caSwyllys  *  certid memory after use.
238299ebb4caSwyllys  */
238399ebb4caSwyllys static KMF_RETURN
238499ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
238599ebb4caSwyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
238699ebb4caSwyllys {
238799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
238899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
238999ebb4caSwyllys 	X509   *issuer = NULL;
239099ebb4caSwyllys 	X509   *cert = NULL;
239199ebb4caSwyllys 	unsigned char *ptmp;
239299ebb4caSwyllys 
239399ebb4caSwyllys 	if (issuer_cert == NULL || user_cert == NULL) {
239499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
239599ebb4caSwyllys 	}
239699ebb4caSwyllys 
239799ebb4caSwyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
239899ebb4caSwyllys 	ptmp = issuer_cert->Data;
239999ebb4caSwyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
240099ebb4caSwyllys 	    issuer_cert->Length);
240199ebb4caSwyllys 	if (issuer == NULL) {
240299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
240399ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
240499ebb4caSwyllys 		goto end;
240599ebb4caSwyllys 	}
240699ebb4caSwyllys 
240799ebb4caSwyllys 	/* convert the DER-encoded user cert to an internal X509 */
240899ebb4caSwyllys 	ptmp = user_cert->Data;
240999ebb4caSwyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
241099ebb4caSwyllys 	    user_cert->Length);
241199ebb4caSwyllys 	if (cert == NULL) {
241299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
241399ebb4caSwyllys 
241499ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
241599ebb4caSwyllys 		goto end;
241699ebb4caSwyllys 	}
241799ebb4caSwyllys 
241899ebb4caSwyllys 	/* create a CERTID */
241999ebb4caSwyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
242099ebb4caSwyllys 	if (*certid == NULL) {
242199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
242299ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
242399ebb4caSwyllys 		goto end;
242499ebb4caSwyllys 	}
242599ebb4caSwyllys 
242699ebb4caSwyllys end:
242799ebb4caSwyllys 	if (issuer != NULL) {
242899ebb4caSwyllys 		X509_free(issuer);
242999ebb4caSwyllys 	}
243099ebb4caSwyllys 
243199ebb4caSwyllys 	if (cert != NULL) {
243299ebb4caSwyllys 		X509_free(cert);
243399ebb4caSwyllys 	}
243499ebb4caSwyllys 
243599ebb4caSwyllys 	return (ret);
243699ebb4caSwyllys }
243799ebb4caSwyllys 
243899ebb4caSwyllys KMF_RETURN
243930a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
244030a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
244199ebb4caSwyllys {
244299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
244399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
244499ebb4caSwyllys 	OCSP_CERTID *id = NULL;
244599ebb4caSwyllys 	OCSP_REQUEST *req = NULL;
244699ebb4caSwyllys 	BIO *derbio = NULL;
244730a5e8faSwyllys 	char *reqfile;
244830a5e8faSwyllys 	KMF_DATA *issuer_cert;
244930a5e8faSwyllys 	KMF_DATA *user_cert;
245099ebb4caSwyllys 
245130a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
245230a5e8faSwyllys 	    attrlist, numattr);
245330a5e8faSwyllys 	if (user_cert == NULL)
245499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
245599ebb4caSwyllys 
245630a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
245730a5e8faSwyllys 	    attrlist, numattr);
245830a5e8faSwyllys 	if (issuer_cert == NULL)
245930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
246030a5e8faSwyllys 
246130a5e8faSwyllys 	reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
246230a5e8faSwyllys 	    attrlist, numattr);
246330a5e8faSwyllys 	if (reqfile == NULL)
246430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
246530a5e8faSwyllys 
246630a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
246799ebb4caSwyllys 	if (ret != KMF_OK) {
246899ebb4caSwyllys 		return (ret);
246999ebb4caSwyllys 	}
247099ebb4caSwyllys 
247199ebb4caSwyllys 	/* Create an OCSP request */
247299ebb4caSwyllys 	req = OCSP_REQUEST_new();
247399ebb4caSwyllys 	if (req == NULL) {
247499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
247599ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
247699ebb4caSwyllys 		goto end;
247799ebb4caSwyllys 	}
247899ebb4caSwyllys 
247999ebb4caSwyllys 	if (!OCSP_request_add0_id(req, id)) {
248099ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
248199ebb4caSwyllys 		goto end;
248299ebb4caSwyllys 	}
248399ebb4caSwyllys 
248499ebb4caSwyllys 	/* Write the request to the output file with DER encoding */
248599ebb4caSwyllys 	derbio = BIO_new_file(reqfile, "wb");
248699ebb4caSwyllys 	if (!derbio) {
248799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
248899ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
248999ebb4caSwyllys 		goto end;
249099ebb4caSwyllys 	}
249199ebb4caSwyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
249299ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
249399ebb4caSwyllys 	}
249499ebb4caSwyllys 
249599ebb4caSwyllys end:
249699ebb4caSwyllys 	/*
2497e65e5c2dSWyllys Ingersoll 	 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2498a2d4930dSDan OpenSolaris Anderson 	 * will also deallocate certid's space.
249999ebb4caSwyllys 	 */
250099ebb4caSwyllys 	if (req != NULL) {
250199ebb4caSwyllys 		OCSP_REQUEST_free(req);
250299ebb4caSwyllys 	}
250399ebb4caSwyllys 
250499ebb4caSwyllys 	if (derbio != NULL) {
250599ebb4caSwyllys 		(void) BIO_free(derbio);
250699ebb4caSwyllys 	}
250799ebb4caSwyllys 
250899ebb4caSwyllys 	return (ret);
250999ebb4caSwyllys }
251099ebb4caSwyllys 
251199ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */
2512300fdee2SAndy Fiddaman static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_BASICRESP *bs)
251399ebb4caSwyllys {
251499ebb4caSwyllys 	int i;
251599ebb4caSwyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
2516300fdee2SAndy Fiddaman 	const ASN1_OCTET_STRING *pid;
251799ebb4caSwyllys 
2518*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2519300fdee2SAndy Fiddaman 	OCSP_RESPID *id = bs->tbsResponseData->responderId;
2520300fdee2SAndy Fiddaman 
252199ebb4caSwyllys 	if (id->type == V_OCSP_RESPID_NAME)
252299ebb4caSwyllys 		return (X509_find_by_subject(certs, id->value.byName));
252399ebb4caSwyllys 
2524300fdee2SAndy Fiddaman 	pid = id->value.byKey;
2525300fdee2SAndy Fiddaman #else
2526300fdee2SAndy Fiddaman 	const X509_NAME *pname;
2527300fdee2SAndy Fiddaman 
2528300fdee2SAndy Fiddaman 	if (OCSP_resp_get0_id(bs, &pid, &pname) == 0)
2529300fdee2SAndy Fiddaman 		return (NULL);
2530300fdee2SAndy Fiddaman 
2531300fdee2SAndy Fiddaman 	if (pname != NULL)
2532300fdee2SAndy Fiddaman 		return (X509_find_by_subject(certs, (X509_NAME *)pname));
2533300fdee2SAndy Fiddaman #endif
2534300fdee2SAndy Fiddaman 
253599ebb4caSwyllys 	/* Lookup by key hash */
253699ebb4caSwyllys 
253799ebb4caSwyllys 	/* If key hash isn't SHA1 length then forget it */
2538300fdee2SAndy Fiddaman 	if (pid->length != SHA_DIGEST_LENGTH)
253999ebb4caSwyllys 		return (NULL);
254099ebb4caSwyllys 
2541300fdee2SAndy Fiddaman 	keyhash = pid->data;
254299ebb4caSwyllys 	/* Calculate hash of each key and compare */
254399ebb4caSwyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
2544d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
254599ebb4caSwyllys 		X509 *x = sk_X509_value(certs, i);
25465b3e1433Swyllys 		/* Use pubkey_digest to get the key ID value */
254799ebb4caSwyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
254899ebb4caSwyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
254999ebb4caSwyllys 			return (x);
255099ebb4caSwyllys 	}
255199ebb4caSwyllys 	return (NULL);
255299ebb4caSwyllys }
255399ebb4caSwyllys 
255499ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */
2555a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */
255699ebb4caSwyllys static int
255799ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
255899ebb4caSwyllys     X509_STORE *st, unsigned long flags)
255999ebb4caSwyllys {
256099ebb4caSwyllys 	X509 *signer;
2561300fdee2SAndy Fiddaman 	if ((signer = ocsp_find_signer_sk(certs, bs)))	{
256299ebb4caSwyllys 		*psigner = signer;
256399ebb4caSwyllys 		return (2);
256499ebb4caSwyllys 	}
2565300fdee2SAndy Fiddaman 
256699ebb4caSwyllys 	if (!(flags & OCSP_NOINTERN) &&
2567300fdee2SAndy Fiddaman 	    (signer = ocsp_find_signer_sk(
2568300fdee2SAndy Fiddaman 	    (STACK_OF(X509) *)OCSP_resp_get0_certs(bs), bs))) {
256999ebb4caSwyllys 		*psigner = signer;
257099ebb4caSwyllys 		return (1);
257199ebb4caSwyllys 	}
257299ebb4caSwyllys 	/* Maybe lookup from store if by subject name */
257399ebb4caSwyllys 
257499ebb4caSwyllys 	*psigner = NULL;
257599ebb4caSwyllys 	return (0);
257699ebb4caSwyllys }
257799ebb4caSwyllys 
257899ebb4caSwyllys /*
257999ebb4caSwyllys  * This function will verify the signature of a basic response, using
258099ebb4caSwyllys  * the public key from the OCSP responder certificate.
258199ebb4caSwyllys  */
258299ebb4caSwyllys static KMF_RETURN
258399ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
258499ebb4caSwyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
258599ebb4caSwyllys {
258699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
258799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
258899ebb4caSwyllys 	STACK_OF(X509) *cert_stack = NULL;
258999ebb4caSwyllys 	X509 *signer = NULL;
259099ebb4caSwyllys 	X509 *issuer = NULL;
2591*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
259299ebb4caSwyllys 	EVP_PKEY *skey = NULL;
2593300fdee2SAndy Fiddaman #else
2594300fdee2SAndy Fiddaman 	STACK_OF(X509) *cert_stack2 = NULL;
2595300fdee2SAndy Fiddaman #endif
259699ebb4caSwyllys 	unsigned char *ptmp;
259799ebb4caSwyllys 
259899ebb4caSwyllys 	if (bs == NULL || issuer_cert == NULL)
259999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
260099ebb4caSwyllys 
260199ebb4caSwyllys 	/*
260299ebb4caSwyllys 	 * Find the certificate that signed the basic response.
260399ebb4caSwyllys 	 *
260499ebb4caSwyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
260599ebb4caSwyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
260699ebb4caSwyllys 	 * If we still do not find a signer, we will look for it from the
260799ebb4caSwyllys 	 * certificate list came with the response file.
260899ebb4caSwyllys 	 */
260999ebb4caSwyllys 	if (signer_cert != NULL) {
261099ebb4caSwyllys 		ptmp = signer_cert->Data;
261199ebb4caSwyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
261299ebb4caSwyllys 		    signer_cert->Length);
261399ebb4caSwyllys 		if (signer == NULL) {
261499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
261599ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
261699ebb4caSwyllys 			goto end;
261799ebb4caSwyllys 		}
261899ebb4caSwyllys 	} else {
261999ebb4caSwyllys 		/*
262099ebb4caSwyllys 		 * Convert the issuer cert into X509 and push it into a
262199ebb4caSwyllys 		 * stack to be used by ocsp_find_signer().
262299ebb4caSwyllys 		 */
262399ebb4caSwyllys 		ptmp = issuer_cert->Data;
262499ebb4caSwyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
262599ebb4caSwyllys 		    issuer_cert->Length);
262699ebb4caSwyllys 		if (issuer == NULL) {
262799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
262899ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
262999ebb4caSwyllys 			goto end;
263099ebb4caSwyllys 		}
263199ebb4caSwyllys 
263299ebb4caSwyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
263399ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
263499ebb4caSwyllys 			goto end;
263599ebb4caSwyllys 		}
263699ebb4caSwyllys 
263799ebb4caSwyllys 		if (sk_X509_push(cert_stack, issuer) == NULL) {
263899ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
263999ebb4caSwyllys 			goto end;
264099ebb4caSwyllys 		}
264199ebb4caSwyllys 
264299ebb4caSwyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
264399ebb4caSwyllys 		if (!ret) {
264499ebb4caSwyllys 			/* can not find the signer */
264599ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
264699ebb4caSwyllys 			goto end;
264799ebb4caSwyllys 		}
264899ebb4caSwyllys 	}
264999ebb4caSwyllys 
265099ebb4caSwyllys 	/* Verify the signature of the response */
2651*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
265299ebb4caSwyllys 	skey = X509_get_pubkey(signer);
265399ebb4caSwyllys 	if (skey == NULL) {
265499ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
265599ebb4caSwyllys 		goto end;
265699ebb4caSwyllys 	}
265799ebb4caSwyllys 
265899ebb4caSwyllys 	ret = OCSP_BASICRESP_verify(bs, skey, 0);
2659300fdee2SAndy Fiddaman #else
2660300fdee2SAndy Fiddaman 	/*
2661300fdee2SAndy Fiddaman 	 * Technique based on
2662300fdee2SAndy Fiddaman 	 * https://mta.openssl.org/pipermail/openssl-users/
2663300fdee2SAndy Fiddaman 	 *	2017-October/006814.html
2664300fdee2SAndy Fiddaman 	 */
2665300fdee2SAndy Fiddaman 	if ((cert_stack2 = sk_X509_new_null()) == NULL) {
2666300fdee2SAndy Fiddaman 		ret = KMF_ERR_INTERNAL;
2667300fdee2SAndy Fiddaman 		goto end;
2668300fdee2SAndy Fiddaman 	}
2669300fdee2SAndy Fiddaman 
2670300fdee2SAndy Fiddaman 	if (sk_X509_push(cert_stack2, signer) == NULL) {
2671300fdee2SAndy Fiddaman 		ret = KMF_ERR_INTERNAL;
2672300fdee2SAndy Fiddaman 		goto end;
2673300fdee2SAndy Fiddaman 	}
2674300fdee2SAndy Fiddaman 
2675300fdee2SAndy Fiddaman 	ret = OCSP_basic_verify(bs, cert_stack2, NULL, OCSP_NOVERIFY);
2676300fdee2SAndy Fiddaman #endif
2677300fdee2SAndy Fiddaman 
267899ebb4caSwyllys 	if (ret == 0) {
267999ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
268099ebb4caSwyllys 		goto end;
268199ebb4caSwyllys 	}
268299ebb4caSwyllys 
268399ebb4caSwyllys end:
268499ebb4caSwyllys 	if (issuer != NULL) {
268599ebb4caSwyllys 		X509_free(issuer);
268699ebb4caSwyllys 	}
268799ebb4caSwyllys 
268899ebb4caSwyllys 	if (signer != NULL) {
268999ebb4caSwyllys 		X509_free(signer);
269099ebb4caSwyllys 	}
269199ebb4caSwyllys 
2692*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
269399ebb4caSwyllys 	if (skey != NULL) {
269499ebb4caSwyllys 		EVP_PKEY_free(skey);
269599ebb4caSwyllys 	}
2696300fdee2SAndy Fiddaman #else
2697300fdee2SAndy Fiddaman 	if (cert_stack2 != NULL) {
2698300fdee2SAndy Fiddaman 		sk_X509_free(cert_stack2);
2699300fdee2SAndy Fiddaman 	}
2700300fdee2SAndy Fiddaman #endif
270199ebb4caSwyllys 
270299ebb4caSwyllys 	if (cert_stack != NULL) {
270399ebb4caSwyllys 		sk_X509_free(cert_stack);
270499ebb4caSwyllys 	}
270599ebb4caSwyllys 
270699ebb4caSwyllys 	return (ret);
270799ebb4caSwyllys }
270899ebb4caSwyllys 
270999ebb4caSwyllys KMF_RETURN
271099ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
271130a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
271299ebb4caSwyllys {
271399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
271499ebb4caSwyllys 	BIO *derbio = NULL;
271599ebb4caSwyllys 	OCSP_RESPONSE *resp = NULL;
271699ebb4caSwyllys 	OCSP_BASICRESP *bs = NULL;
271799ebb4caSwyllys 	OCSP_CERTID *id = NULL;
271899ebb4caSwyllys 	OCSP_SINGLERESP *single = NULL;
271999ebb4caSwyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
272099ebb4caSwyllys 	int index, status, reason;
272130a5e8faSwyllys 	KMF_DATA *issuer_cert;
272230a5e8faSwyllys 	KMF_DATA *user_cert;
272330a5e8faSwyllys 	KMF_DATA *signer_cert;
272430a5e8faSwyllys 	KMF_DATA *response;
272530a5e8faSwyllys 	int *response_reason, *response_status, *cert_status;
272630a5e8faSwyllys 	boolean_t ignore_response_sign = B_FALSE;	/* default is FALSE */
272730a5e8faSwyllys 	uint32_t response_lifetime;
272899ebb4caSwyllys 
272930a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
273030a5e8faSwyllys 	    attrlist, numattr);
273130a5e8faSwyllys 	if (issuer_cert == NULL)
273299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
273399ebb4caSwyllys 
273430a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
273530a5e8faSwyllys 	    attrlist, numattr);
273630a5e8faSwyllys 	if (user_cert == NULL)
273799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
273830a5e8faSwyllys 
273930a5e8faSwyllys 	response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
274030a5e8faSwyllys 	    attrlist, numattr);
274130a5e8faSwyllys 	if (response == NULL)
274230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
274330a5e8faSwyllys 
274430a5e8faSwyllys 	response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
274530a5e8faSwyllys 	    attrlist, numattr);
274630a5e8faSwyllys 	if (response_status == NULL)
274730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
274830a5e8faSwyllys 
274930a5e8faSwyllys 	response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
275030a5e8faSwyllys 	    attrlist, numattr);
275130a5e8faSwyllys 	if (response_reason == NULL)
275230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
275330a5e8faSwyllys 
275430a5e8faSwyllys 	cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
275530a5e8faSwyllys 	    attrlist, numattr);
275630a5e8faSwyllys 	if (cert_status == NULL)
275730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
275899ebb4caSwyllys 
275999ebb4caSwyllys 	/* Read in the response */
276030a5e8faSwyllys 	derbio = BIO_new_mem_buf(response->Data, response->Length);
276199ebb4caSwyllys 	if (!derbio) {
276299ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
276399ebb4caSwyllys 		return (ret);
276499ebb4caSwyllys 	}
276599ebb4caSwyllys 
276699ebb4caSwyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
276799ebb4caSwyllys 	if (resp == NULL) {
276899ebb4caSwyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
276999ebb4caSwyllys 		goto end;
277099ebb4caSwyllys 	}
277199ebb4caSwyllys 
277299ebb4caSwyllys 	/* Check the response status */
277399ebb4caSwyllys 	status = OCSP_response_status(resp);
277430a5e8faSwyllys 	*response_status = status;
277599ebb4caSwyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
277699ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
277799ebb4caSwyllys 		goto end;
277899ebb4caSwyllys 	}
277999ebb4caSwyllys 
278099ebb4caSwyllys #ifdef DEBUG
278199ebb4caSwyllys 	printf("Successfully checked the response file status.\n");
278299ebb4caSwyllys #endif /* DEBUG */
278399ebb4caSwyllys 
278499ebb4caSwyllys 	/* Extract basic response */
278599ebb4caSwyllys 	bs = OCSP_response_get1_basic(resp);
278699ebb4caSwyllys 	if (bs == NULL) {
278799ebb4caSwyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
278899ebb4caSwyllys 		goto end;
278999ebb4caSwyllys 	}
279099ebb4caSwyllys 
279199ebb4caSwyllys #ifdef DEBUG
279299ebb4caSwyllys 	printf("Successfully retrieved the basic response.\n");
279399ebb4caSwyllys #endif /* DEBUG */
279499ebb4caSwyllys 
279599ebb4caSwyllys 	/* Check the basic response signature if required */
279630a5e8faSwyllys 	ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
279730a5e8faSwyllys 	    (void *)&ignore_response_sign, NULL);
279830a5e8faSwyllys 	if (ret != KMF_OK)
279930a5e8faSwyllys 		ret = KMF_OK;
280030a5e8faSwyllys 
280130a5e8faSwyllys 	signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
280230a5e8faSwyllys 	    attrlist, numattr);
280330a5e8faSwyllys 
280430a5e8faSwyllys 	if (ignore_response_sign == B_FALSE) {
280599ebb4caSwyllys 		ret = check_response_signature(handle, bs,
280630a5e8faSwyllys 		    signer_cert, issuer_cert);
280799ebb4caSwyllys 		if (ret != KMF_OK)
280899ebb4caSwyllys 			goto end;
280999ebb4caSwyllys 	}
281099ebb4caSwyllys 
281199ebb4caSwyllys #ifdef DEBUG
281299ebb4caSwyllys 	printf("Successfully verified the response signature.\n");
281399ebb4caSwyllys #endif /* DEBUG */
281499ebb4caSwyllys 
281599ebb4caSwyllys 	/* Create a certid for the certificate in question */
281630a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
281799ebb4caSwyllys 	if (ret != KMF_OK) {
281899ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
281999ebb4caSwyllys 		goto end;
282099ebb4caSwyllys 	}
282199ebb4caSwyllys 
282299ebb4caSwyllys #ifdef DEBUG
282399ebb4caSwyllys 	printf("successfully created a certid for the cert.\n");
282499ebb4caSwyllys #endif /* DEBUG */
282599ebb4caSwyllys 
282699ebb4caSwyllys 	/* Find the index of the single response for the certid */
282799ebb4caSwyllys 	index = OCSP_resp_find(bs, id, -1);
282899ebb4caSwyllys 	if (index < 0) {
282999ebb4caSwyllys 		/* cound not find this certificate in the response */
283099ebb4caSwyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
283199ebb4caSwyllys 		goto end;
283299ebb4caSwyllys 	}
283399ebb4caSwyllys 
283499ebb4caSwyllys #ifdef DEBUG
283599ebb4caSwyllys 	printf("Successfully found the single response index for the cert.\n");
283699ebb4caSwyllys #endif /* DEBUG */
283799ebb4caSwyllys 
283899ebb4caSwyllys 	/* Retrieve the single response and get the cert status */
283999ebb4caSwyllys 	single = OCSP_resp_get0(bs, index);
284099ebb4caSwyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
284199ebb4caSwyllys 	    &nextupd);
284299ebb4caSwyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
284330a5e8faSwyllys 		*cert_status = OCSP_GOOD;
284499ebb4caSwyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
284530a5e8faSwyllys 		*cert_status = OCSP_UNKNOWN;
284699ebb4caSwyllys 	} else { /* revoked */
284730a5e8faSwyllys 		*cert_status = OCSP_REVOKED;
284830a5e8faSwyllys 		*response_reason = reason;
284999ebb4caSwyllys 	}
285099ebb4caSwyllys 	ret = KMF_OK;
285199ebb4caSwyllys 
285230a5e8faSwyllys 	/* resp. time is optional, so we don't care about the return code. */
285330a5e8faSwyllys 	(void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
285430a5e8faSwyllys 	    (void *)&response_lifetime, NULL);
285530a5e8faSwyllys 
285699ebb4caSwyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
285730a5e8faSwyllys 	    response_lifetime)) {
285899ebb4caSwyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
285999ebb4caSwyllys 		goto end;
286099ebb4caSwyllys 	}
286199ebb4caSwyllys 
286299ebb4caSwyllys #ifdef DEBUG
286399ebb4caSwyllys 	printf("Successfully verify the time.\n");
286499ebb4caSwyllys #endif /* DEBUG */
286599ebb4caSwyllys 
286699ebb4caSwyllys end:
286799ebb4caSwyllys 	if (derbio != NULL)
286899ebb4caSwyllys 		(void) BIO_free(derbio);
286999ebb4caSwyllys 
287099ebb4caSwyllys 	if (resp != NULL)
287199ebb4caSwyllys 		OCSP_RESPONSE_free(resp);
287299ebb4caSwyllys 
287399ebb4caSwyllys 	if (bs != NULL)
287499ebb4caSwyllys 		OCSP_BASICRESP_free(bs);
287599ebb4caSwyllys 
287699ebb4caSwyllys 	if (id != NULL)
287799ebb4caSwyllys 		OCSP_CERTID_free(id);
287899ebb4caSwyllys 
287999ebb4caSwyllys 	return (ret);
288099ebb4caSwyllys }
288199ebb4caSwyllys 
288299ebb4caSwyllys static KMF_RETURN
288399ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path,
288499ebb4caSwyllys 	KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
288599ebb4caSwyllys {
288699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
288730a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
288899ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
288999ebb4caSwyllys 
289099ebb4caSwyllys 	if (keyclass == KMF_ASYM_PRI ||
289199ebb4caSwyllys 	    keyclass == KMF_ASYM_PUB) {
289299ebb4caSwyllys 		pkey = openssl_load_key(handle, path);
289399ebb4caSwyllys 		if (pkey == NULL) {
289499ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
289599ebb4caSwyllys 		}
289699ebb4caSwyllys 		if (key != NULL) {
2897300fdee2SAndy Fiddaman 			if (EVP_PKEY_get0_RSA(pkey) != NULL)
289899ebb4caSwyllys 				key->keyalg = KMF_RSA;
2899300fdee2SAndy Fiddaman 			else if (EVP_PKEY_get0_DSA(pkey) != NULL)
290099ebb4caSwyllys 				key->keyalg = KMF_DSA;
290199ebb4caSwyllys 
290299ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
290399ebb4caSwyllys 			key->keyclass = keyclass;
290499ebb4caSwyllys 			key->keyp = (void *)pkey;
290599ebb4caSwyllys 			key->israw = FALSE;
29065b3e1433Swyllys 			if (path != NULL &&
29075b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
29085b3e1433Swyllys 				EVP_PKEY_free(pkey);
29095b3e1433Swyllys 				return (KMF_ERR_MEMORY);
29105b3e1433Swyllys 			}
291199ebb4caSwyllys 		} else {
291299ebb4caSwyllys 			EVP_PKEY_free(pkey);
291399ebb4caSwyllys 			pkey = NULL;
291499ebb4caSwyllys 		}
291599ebb4caSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
291699ebb4caSwyllys 		KMF_ENCODE_FORMAT fmt;
291799ebb4caSwyllys 		/*
291899ebb4caSwyllys 		 * If the file is a recognized format,
291999ebb4caSwyllys 		 * then it is NOT a symmetric key.
292099ebb4caSwyllys 		 */
292130a5e8faSwyllys 		rv = kmf_get_file_format(path, &fmt);
292299ebb4caSwyllys 		if (rv == KMF_OK || fmt != 0) {
292399ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
292499ebb4caSwyllys 		} else if (rv == KMF_ERR_ENCODING) {
292599ebb4caSwyllys 			/*
292699ebb4caSwyllys 			 * If we don't know the encoding,
292799ebb4caSwyllys 			 * it is probably  a symmetric key.
292899ebb4caSwyllys 			 */
292999ebb4caSwyllys 			rv = KMF_OK;
293030a5e8faSwyllys 		} else if (rv == KMF_ERR_OPEN_FILE) {
293130a5e8faSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
293299ebb4caSwyllys 		}
293399ebb4caSwyllys 
293499ebb4caSwyllys 		if (key != NULL) {
293599ebb4caSwyllys 			KMF_DATA keyvalue;
293699ebb4caSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
293799ebb4caSwyllys 			if (rkey == NULL) {
293899ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
293999ebb4caSwyllys 				goto out;
294099ebb4caSwyllys 			}
294199ebb4caSwyllys 
294299ebb4caSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
294330a5e8faSwyllys 			rv = kmf_read_input_file(handle, path, &keyvalue);
294499ebb4caSwyllys 			if (rv != KMF_OK)
294599ebb4caSwyllys 				goto out;
294699ebb4caSwyllys 
294799ebb4caSwyllys 			rkey->keydata.len = keyvalue.Length;
294899ebb4caSwyllys 			rkey->keydata.val = keyvalue.Data;
294999ebb4caSwyllys 
295099ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
295199ebb4caSwyllys 			key->keyclass = keyclass;
295299ebb4caSwyllys 			key->israw = TRUE;
295399ebb4caSwyllys 			key->keyp = (void *)rkey;
29545b3e1433Swyllys 			if (path != NULL &&
29555b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
29565b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
29575b3e1433Swyllys 			}
295899ebb4caSwyllys 		}
295999ebb4caSwyllys 	}
296099ebb4caSwyllys out:
296199ebb4caSwyllys 	if (rv != KMF_OK) {
296299ebb4caSwyllys 		if (rkey != NULL) {
296330a5e8faSwyllys 			kmf_free_raw_sym_key(rkey);
296499ebb4caSwyllys 		}
296599ebb4caSwyllys 		if (pkey != NULL)
296699ebb4caSwyllys 			EVP_PKEY_free(pkey);
296799ebb4caSwyllys 
296899ebb4caSwyllys 		if (key != NULL) {
296999ebb4caSwyllys 			key->keyalg = KMF_KEYALG_NONE;
297099ebb4caSwyllys 			key->keyclass = KMF_KEYCLASS_NONE;
297199ebb4caSwyllys 			key->keyp = NULL;
297299ebb4caSwyllys 		}
297399ebb4caSwyllys 	}
297499ebb4caSwyllys 
297599ebb4caSwyllys 	return (rv);
297699ebb4caSwyllys }
297799ebb4caSwyllys 
297899ebb4caSwyllys KMF_RETURN
297930a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle,
298030a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
298199ebb4caSwyllys {
298299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
298399ebb4caSwyllys 	char *fullpath = NULL;
2984f482c776Swyllys 	uint32_t maxkeys;
298530a5e8faSwyllys 	KMF_KEY_HANDLE *key;
298630a5e8faSwyllys 	uint32_t *numkeys;
298730a5e8faSwyllys 	KMF_KEY_CLASS keyclass;
298830a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
298930a5e8faSwyllys 	char *dirpath;
299030a5e8faSwyllys 	char *keyfile;
299199ebb4caSwyllys 
299230a5e8faSwyllys 	if (handle == NULL)
299399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
299499ebb4caSwyllys 
299530a5e8faSwyllys 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
299630a5e8faSwyllys 	if (numkeys == NULL)
299730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
299830a5e8faSwyllys 
299930a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
300030a5e8faSwyllys 	    (void *)&keyclass, NULL);
300130a5e8faSwyllys 	if (rv != KMF_OK)
300230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
300330a5e8faSwyllys 
300430a5e8faSwyllys 	if (keyclass != KMF_ASYM_PUB &&
300530a5e8faSwyllys 	    keyclass != KMF_ASYM_PRI &&
300630a5e8faSwyllys 	    keyclass != KMF_SYMMETRIC)
300799ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
300899ebb4caSwyllys 
300930a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
301030a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
301130a5e8faSwyllys 
301230a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
301399ebb4caSwyllys 
301499ebb4caSwyllys 	if (fullpath == NULL)
301599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
301699ebb4caSwyllys 
3017f482c776Swyllys 	maxkeys = *numkeys;
3018f482c776Swyllys 	if (maxkeys == 0)
3019f482c776Swyllys 		maxkeys = 0xFFFFFFFF;
302099ebb4caSwyllys 	*numkeys = 0;
302199ebb4caSwyllys 
302230a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
302330a5e8faSwyllys 	/* it is okay to have "keys" contains NULL */
302430a5e8faSwyllys 
302530a5e8faSwyllys 	/*
302630a5e8faSwyllys 	 * The caller may want a list of the raw key data as well.
302730a5e8faSwyllys 	 * Useful for importing keys from a file into other keystores.
302830a5e8faSwyllys 	 */
302930a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
303030a5e8faSwyllys 
303199ebb4caSwyllys 	if (isdir(fullpath)) {
303299ebb4caSwyllys 		DIR *dirp;
303399ebb4caSwyllys 		struct dirent *dp;
303499ebb4caSwyllys 		int n = 0;
303599ebb4caSwyllys 
303699ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
303799ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
303899ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
303999ebb4caSwyllys 		}
304099ebb4caSwyllys 		rewinddir(dirp);
3041f482c776Swyllys 		while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
304299ebb4caSwyllys 			if (strcmp(dp->d_name, ".") &&
304399ebb4caSwyllys 			    strcmp(dp->d_name, "..")) {
304499ebb4caSwyllys 				char *fname;
304599ebb4caSwyllys 
304699ebb4caSwyllys 				fname = get_fullpath(fullpath,
304799ebb4caSwyllys 				    (char *)&dp->d_name);
304899ebb4caSwyllys 
304999ebb4caSwyllys 				rv = fetch_key(handle, fname,
305030a5e8faSwyllys 				    keyclass, key ? &key[n] : NULL);
305199ebb4caSwyllys 
305230a5e8faSwyllys 				if (rv == KMF_OK) {
305330a5e8faSwyllys 					if (key != NULL && rawkey != NULL)
305430a5e8faSwyllys 						rv = convertToRawKey(
305530a5e8faSwyllys 						    key[n].keyp, &rawkey[n]);
305699ebb4caSwyllys 					n++;
305730a5e8faSwyllys 				}
305899ebb4caSwyllys 
305999ebb4caSwyllys 				if (rv != KMF_OK || key == NULL)
306099ebb4caSwyllys 					free(fname);
306199ebb4caSwyllys 			}
306299ebb4caSwyllys 		}
306399ebb4caSwyllys 		(void) closedir(dirp);
306499ebb4caSwyllys 		free(fullpath);
306599ebb4caSwyllys 		(*numkeys) = n;
306699ebb4caSwyllys 	} else {
306730a5e8faSwyllys 		rv = fetch_key(handle, fullpath, keyclass, key);
306899ebb4caSwyllys 		if (rv == KMF_OK)
306999ebb4caSwyllys 			(*numkeys) = 1;
307099ebb4caSwyllys 
307199ebb4caSwyllys 		if (rv != KMF_OK || key == NULL)
307299ebb4caSwyllys 			free(fullpath);
307330a5e8faSwyllys 
307430a5e8faSwyllys 		if (rv == KMF_OK && key != NULL && rawkey != NULL) {
307530a5e8faSwyllys 			rv = convertToRawKey(key->keyp, rawkey);
307630a5e8faSwyllys 		}
307799ebb4caSwyllys 	}
307899ebb4caSwyllys 
3079f482c776Swyllys 	if (rv == KMF_OK && (*numkeys) == 0)
308099ebb4caSwyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
308173cc0e02Swyllys 	else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
308273cc0e02Swyllys 		rv = KMF_OK;
308399ebb4caSwyllys 
308499ebb4caSwyllys 	return (rv);
308599ebb4caSwyllys }
308699ebb4caSwyllys 
308799ebb4caSwyllys #define	HANDLE_PK12_ERROR { \
308899ebb4caSwyllys 	SET_ERROR(kmfh, ERR_get_error()); \
308999ebb4caSwyllys 	rv = KMF_ERR_ENCODING; \
309099ebb4caSwyllys 	goto out; \
309199ebb4caSwyllys }
309299ebb4caSwyllys 
30935b3e1433Swyllys static int
30945b3e1433Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
309599ebb4caSwyllys {
3096300fdee2SAndy Fiddaman 	unsigned char *alias;
3097300fdee2SAndy Fiddaman 	int len;
3098300fdee2SAndy Fiddaman 
3099300fdee2SAndy Fiddaman 	if (xcert != NULL && (alias = X509_alias_get0(xcert, &len)) != NULL) {
31005b3e1433Swyllys 		if (PKCS12_add_friendlyname_asc(bag,
3101300fdee2SAndy Fiddaman 		    (const char *)alias, len) == 0)
31025b3e1433Swyllys 			return (0);
31035b3e1433Swyllys 	}
31045b3e1433Swyllys 	return (1);
31055b3e1433Swyllys }
31065b3e1433Swyllys 
31075b3e1433Swyllys static PKCS7 *
31085b3e1433Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
31095b3e1433Swyllys 	uchar_t *keyid, unsigned int keyidlen)
31105b3e1433Swyllys {
311199ebb4caSwyllys 	PKCS12_SAFEBAG *bag = NULL;
311299ebb4caSwyllys 	PKCS7 *cert_authsafe = NULL;
31135b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack;
311499ebb4caSwyllys 
311599ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
311699ebb4caSwyllys 	if (bag_stack == NULL)
31175b3e1433Swyllys 		return (NULL);
311899ebb4caSwyllys 
311999ebb4caSwyllys 	/* Convert cert from X509 struct to PKCS#12 bag */
3120300fdee2SAndy Fiddaman 	bag = PKCS12_SAFEBAG_create_cert(sslcert);
312199ebb4caSwyllys 	if (bag == NULL) {
31225b3e1433Swyllys 		goto out;
312399ebb4caSwyllys 	}
312499ebb4caSwyllys 
312599ebb4caSwyllys 	/* Add the key id to the certificate bag. */
31265b3e1433Swyllys 	if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
31275b3e1433Swyllys 		goto out;
312899ebb4caSwyllys 	}
312999ebb4caSwyllys 
31305b3e1433Swyllys 	if (!add_alias_to_bag(bag, sslcert))
31315b3e1433Swyllys 		goto out;
31325b3e1433Swyllys 
313399ebb4caSwyllys 	/* Pile it on the bag_stack. */
313499ebb4caSwyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
31355b3e1433Swyllys 		goto out;
313699ebb4caSwyllys 	}
313799ebb4caSwyllys 	/* Turn bag_stack of certs into encrypted authsafe. */
313899ebb4caSwyllys 	cert_authsafe = PKCS12_pack_p7encdata(
313999ebb4caSwyllys 	    NID_pbe_WithSHA1And40BitRC2_CBC,
314034acef67Swyllys 	    cred->cred, cred->credlen, NULL, 0,
314134acef67Swyllys 	    PKCS12_DEFAULT_ITER, bag_stack);
314299ebb4caSwyllys 
31435b3e1433Swyllys out:
31445b3e1433Swyllys 	if (bag_stack != NULL)
314599ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
314699ebb4caSwyllys 
31475b3e1433Swyllys 	return (cert_authsafe);
314899ebb4caSwyllys }
31495b3e1433Swyllys 
31505b3e1433Swyllys static PKCS7 *
31515b3e1433Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
31525b3e1433Swyllys 	uchar_t *keyid,  unsigned int keyidlen,
31535b3e1433Swyllys 	char *label, int label_len)
31545b3e1433Swyllys {
31555b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
31565b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
31575b3e1433Swyllys 	PKCS12_SAFEBAG *bag = NULL;
31585b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
31595b3e1433Swyllys 
316099ebb4caSwyllys 	p8 = EVP_PKEY2PKCS8(pkey);
316199ebb4caSwyllys 	if (p8 == NULL) {
31625b3e1433Swyllys 		return (NULL);
316399ebb4caSwyllys 	}
316499ebb4caSwyllys 	/* Put the shrouded key into a PKCS#12 bag. */
3165300fdee2SAndy Fiddaman 	bag = PKCS12_SAFEBAG_create_pkcs8_encrypt(
316699ebb4caSwyllys 	    NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
316799ebb4caSwyllys 	    cred->cred, cred->credlen,
316899ebb4caSwyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, p8);
316999ebb4caSwyllys 
317099ebb4caSwyllys 	/* Clean up the PKCS#8 shrouded key, don't need it now. */
317199ebb4caSwyllys 	PKCS8_PRIV_KEY_INFO_free(p8);
317299ebb4caSwyllys 	p8 = NULL;
317399ebb4caSwyllys 
317499ebb4caSwyllys 	if (bag == NULL) {
31755b3e1433Swyllys 		return (NULL);
317699ebb4caSwyllys 	}
31775b3e1433Swyllys 	if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
31785b3e1433Swyllys 		goto out;
31795b3e1433Swyllys 	if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
31805b3e1433Swyllys 		goto out;
31815b3e1433Swyllys 
318299ebb4caSwyllys 	/* Start a PKCS#12 safebag container for the private key. */
318399ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
31845b3e1433Swyllys 	if (bag_stack == NULL)
31855b3e1433Swyllys 		goto out;
318699ebb4caSwyllys 
318799ebb4caSwyllys 	/* Pile on the private key on the bag_stack. */
31885b3e1433Swyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
31895b3e1433Swyllys 		goto out;
31905b3e1433Swyllys 
319199ebb4caSwyllys 	key_authsafe = PKCS12_pack_p7data(bag_stack);
319299ebb4caSwyllys 
31935b3e1433Swyllys out:
31945b3e1433Swyllys 	if (bag_stack != NULL)
319599ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
319699ebb4caSwyllys 	bag_stack = NULL;
31975b3e1433Swyllys 	return (key_authsafe);
319899ebb4caSwyllys }
319999ebb4caSwyllys 
320099ebb4caSwyllys static EVP_PKEY *
320199ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
320299ebb4caSwyllys {
320399ebb4caSwyllys 	RSA		*rsa = NULL;
320499ebb4caSwyllys 	EVP_PKEY	*newkey = NULL;
3205300fdee2SAndy Fiddaman 	BIGNUM		*n = NULL, *e = NULL, *d = NULL,
3206300fdee2SAndy Fiddaman 			*p = NULL, *q = NULL,
3207300fdee2SAndy Fiddaman 			*dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
320899ebb4caSwyllys 
320999ebb4caSwyllys 	if ((rsa = RSA_new()) == NULL)
3210300fdee2SAndy Fiddaman 		goto cleanup;
321199ebb4caSwyllys 
3212300fdee2SAndy Fiddaman 	if ((n = BN_bin2bn(key->mod.val, key->mod.len, NULL)) == NULL)
3213300fdee2SAndy Fiddaman 		goto cleanup;
321499ebb4caSwyllys 
3215300fdee2SAndy Fiddaman 	if ((e = BN_bin2bn(key->pubexp.val, key->pubexp.len, NULL)) == NULL)
3216300fdee2SAndy Fiddaman 		goto cleanup;
321799ebb4caSwyllys 
3218300fdee2SAndy Fiddaman 	if (key->priexp.val != NULL &&
3219300fdee2SAndy Fiddaman 	    (d = BN_bin2bn(key->priexp.val, key->priexp.len, NULL)) == NULL)
3220300fdee2SAndy Fiddaman 		goto cleanup;
322199ebb4caSwyllys 
3222300fdee2SAndy Fiddaman 	if (key->prime1.val != NULL &&
3223300fdee2SAndy Fiddaman 	    (p = BN_bin2bn(key->prime1.val, key->prime1.len, NULL)) == NULL)
3224300fdee2SAndy Fiddaman 		goto cleanup;
322599ebb4caSwyllys 
3226300fdee2SAndy Fiddaman 	if (key->prime2.val != NULL &&
3227300fdee2SAndy Fiddaman 	    (q = BN_bin2bn(key->prime2.val, key->prime2.len, NULL)) == NULL)
3228300fdee2SAndy Fiddaman 		goto cleanup;
322999ebb4caSwyllys 
3230300fdee2SAndy Fiddaman 	if (key->exp1.val != NULL &&
3231300fdee2SAndy Fiddaman 	    (dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len, NULL)) == NULL)
3232300fdee2SAndy Fiddaman 		goto cleanup;
323399ebb4caSwyllys 
3234300fdee2SAndy Fiddaman 	if (key->exp2.val != NULL &&
3235300fdee2SAndy Fiddaman 	    (dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len, NULL)) == NULL)
3236300fdee2SAndy Fiddaman 		goto cleanup;
323799ebb4caSwyllys 
3238300fdee2SAndy Fiddaman 	if (key->coef.val != NULL &&
3239300fdee2SAndy Fiddaman 	    (iqmp = BN_bin2bn(key->coef.val, key->coef.len, NULL)) == NULL)
3240300fdee2SAndy Fiddaman 		goto cleanup;
3241300fdee2SAndy Fiddaman 
3242300fdee2SAndy Fiddaman 	if (RSA_set0_key(rsa, n, e, d) == 0)
3243300fdee2SAndy Fiddaman 		goto cleanup;
3244300fdee2SAndy Fiddaman 	n = e = d = NULL;
3245300fdee2SAndy Fiddaman 	if (RSA_set0_factors(rsa, p, q) == 0)
3246300fdee2SAndy Fiddaman 		goto cleanup;
3247300fdee2SAndy Fiddaman 	p = q = NULL;
3248300fdee2SAndy Fiddaman 	if (RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp) == 0)
3249300fdee2SAndy Fiddaman 		goto cleanup;
3250300fdee2SAndy Fiddaman 	dmp1 = dmq1 = iqmp = NULL;
325199ebb4caSwyllys 
325299ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
3253300fdee2SAndy Fiddaman 		goto cleanup;
325499ebb4caSwyllys 
325599ebb4caSwyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
325699ebb4caSwyllys 
3257300fdee2SAndy Fiddaman cleanup:
325899ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
3259300fdee2SAndy Fiddaman 	if (rsa)
326099ebb4caSwyllys 		RSA_free(rsa);
3261300fdee2SAndy Fiddaman 	BN_free(n);
3262300fdee2SAndy Fiddaman 	BN_free(e);
3263300fdee2SAndy Fiddaman 	BN_free(d);
3264300fdee2SAndy Fiddaman 	BN_free(p);
3265300fdee2SAndy Fiddaman 	BN_free(q);
3266300fdee2SAndy Fiddaman 	BN_free(dmp1);
3267300fdee2SAndy Fiddaman 	BN_free(dmq1);
3268300fdee2SAndy Fiddaman 	BN_free(iqmp);
326999ebb4caSwyllys 
327099ebb4caSwyllys 	return (newkey);
327199ebb4caSwyllys }
327299ebb4caSwyllys 
327399ebb4caSwyllys static EVP_PKEY *
327499ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
327599ebb4caSwyllys {
327699ebb4caSwyllys 	DSA		*dsa = NULL;
327799ebb4caSwyllys 	EVP_PKEY	*newkey = NULL;
3278300fdee2SAndy Fiddaman 	BIGNUM		*p = NULL, *q = NULL, *g = NULL,
3279300fdee2SAndy Fiddaman 			*priv_key = NULL, *pub_key = NULL;
328099ebb4caSwyllys 
328199ebb4caSwyllys 	if ((dsa = DSA_new()) == NULL)
3282300fdee2SAndy Fiddaman 		goto cleanup;
328399ebb4caSwyllys 
3284300fdee2SAndy Fiddaman 	if ((p = BN_bin2bn(key->prime.val, key->prime.len, NULL)) == NULL)
3285300fdee2SAndy Fiddaman 		goto cleanup;
328699ebb4caSwyllys 
3287300fdee2SAndy Fiddaman 	if ((q = BN_bin2bn(key->subprime.val, key->subprime.len, NULL)) == NULL)
3288300fdee2SAndy Fiddaman 		goto cleanup;
328999ebb4caSwyllys 
3290300fdee2SAndy Fiddaman 	if ((g = BN_bin2bn(key->base.val, key->base.len, NULL)) == NULL)
3291300fdee2SAndy Fiddaman 		goto cleanup;
329299ebb4caSwyllys 
3293300fdee2SAndy Fiddaman 	if ((priv_key = BN_bin2bn(key->value.val, key->value.len,
3294300fdee2SAndy Fiddaman 	    NULL)) == NULL)
3295300fdee2SAndy Fiddaman 		goto cleanup;
329699ebb4caSwyllys 
3297300fdee2SAndy Fiddaman 	if (key->pubvalue.val != NULL && (pub_key =
3298300fdee2SAndy Fiddaman 	    BN_bin2bn(key->pubvalue.val, key->pubvalue.len, NULL)) == NULL)
3299300fdee2SAndy Fiddaman 		goto cleanup;
3300300fdee2SAndy Fiddaman 
3301300fdee2SAndy Fiddaman 	if (DSA_set0_pqg(dsa, p, q, g) == 0)
3302300fdee2SAndy Fiddaman 		goto cleanup;
3303300fdee2SAndy Fiddaman 	p = q = g = NULL;
3304300fdee2SAndy Fiddaman 	if (DSA_set0_key(dsa, pub_key, priv_key) == 0)
3305300fdee2SAndy Fiddaman 		goto cleanup;
3306300fdee2SAndy Fiddaman 	pub_key = priv_key = 0;
330730a5e8faSwyllys 
330899ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
3309300fdee2SAndy Fiddaman 		goto cleanup;
331099ebb4caSwyllys 
331199ebb4caSwyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
331299ebb4caSwyllys 
3313300fdee2SAndy Fiddaman cleanup:
331499ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
3315300fdee2SAndy Fiddaman 	if (dsa)
331699ebb4caSwyllys 		DSA_free(dsa);
3317300fdee2SAndy Fiddaman 	BN_free(p);
3318300fdee2SAndy Fiddaman 	BN_free(q);
3319300fdee2SAndy Fiddaman 	BN_free(g);
3320300fdee2SAndy Fiddaman 	BN_free(priv_key);
3321300fdee2SAndy Fiddaman 	BN_free(pub_key);
3322300fdee2SAndy Fiddaman 
332399ebb4caSwyllys 	return (newkey);
332499ebb4caSwyllys }
332599ebb4caSwyllys 
33265b3e1433Swyllys static EVP_PKEY *
33275b3e1433Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key)
33285b3e1433Swyllys {
33295b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
33305b3e1433Swyllys 	KMF_RAW_KEY_DATA *rawkey;
33315b3e1433Swyllys 	ASN1_TYPE *attr = NULL;
33325b3e1433Swyllys 	KMF_RETURN ret;
33335b3e1433Swyllys 
33345b3e1433Swyllys 	if (key == NULL || !key->israw)
33355b3e1433Swyllys 		return (NULL);
33365b3e1433Swyllys 
33375b3e1433Swyllys 	rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
33385b3e1433Swyllys 	if (rawkey->keytype == KMF_RSA) {
33395b3e1433Swyllys 		pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
33405b3e1433Swyllys 	} else if (rawkey->keytype == KMF_DSA) {
33415b3e1433Swyllys 		pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
3342e65e5c2dSWyllys Ingersoll 	} else if (rawkey->keytype == KMF_ECDSA) {
3343e65e5c2dSWyllys Ingersoll 		/*
3344e65e5c2dSWyllys Ingersoll 		 * OpenSSL in Solaris does not support EC for
3345e65e5c2dSWyllys Ingersoll 		 * legal reasons
3346e65e5c2dSWyllys Ingersoll 		 */
3347e65e5c2dSWyllys Ingersoll 		return (NULL);
33485b3e1433Swyllys 	} else {
33495b3e1433Swyllys 		/* wrong kind of key */
33505b3e1433Swyllys 		return (NULL);
33515b3e1433Swyllys 	}
33525b3e1433Swyllys 
33535b3e1433Swyllys 	if (rawkey->label != NULL) {
33545b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
33555b3e1433Swyllys 			EVP_PKEY_free(pkey);
33565b3e1433Swyllys 			return (NULL);
33575b3e1433Swyllys 		}
33585b3e1433Swyllys 		attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
33595b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
33605b3e1433Swyllys 		    strlen(rawkey->label));
33615b3e1433Swyllys 		attr->type = V_ASN1_BMPSTRING;
33625b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.bmpstring;
33635b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
33645b3e1433Swyllys 		if (ret != KMF_OK) {
33655b3e1433Swyllys 			EVP_PKEY_free(pkey);
33665b3e1433Swyllys 			ASN1_TYPE_free(attr);
33675b3e1433Swyllys 			return (NULL);
33685b3e1433Swyllys 		}
33695b3e1433Swyllys 	}
33705b3e1433Swyllys 	if (rawkey->id.Data != NULL) {
33715b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
33725b3e1433Swyllys 			EVP_PKEY_free(pkey);
33735b3e1433Swyllys 			return (NULL);
33745b3e1433Swyllys 		}
33755b3e1433Swyllys 		attr->value.octet_string =
33765b3e1433Swyllys 		    ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
33775b3e1433Swyllys 		attr->type = V_ASN1_OCTET_STRING;
33785b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.octet_string,
33795b3e1433Swyllys 		    rawkey->id.Data, rawkey->id.Length);
33805b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.octet_string;
33815b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
33825b3e1433Swyllys 		if (ret != KMF_OK) {
33835b3e1433Swyllys 			EVP_PKEY_free(pkey);
33845b3e1433Swyllys 			ASN1_TYPE_free(attr);
33855b3e1433Swyllys 			return (NULL);
33865b3e1433Swyllys 		}
33875b3e1433Swyllys 	}
33885b3e1433Swyllys 	return (pkey);
33895b3e1433Swyllys }
33905b3e1433Swyllys 
33915b3e1433Swyllys /*
33925b3e1433Swyllys  * Search a list of private keys to find one that goes with the certificate.
33935b3e1433Swyllys  */
33945b3e1433Swyllys static EVP_PKEY *
33955b3e1433Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
33965b3e1433Swyllys {
33975b3e1433Swyllys 	int i;
33985b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
33995b3e1433Swyllys 
34005b3e1433Swyllys 	if (numkeys == 0 || keylist == NULL || xcert == NULL)
34015b3e1433Swyllys 		return (NULL);
34025b3e1433Swyllys 	for (i = 0; i < numkeys; i++) {
34035b3e1433Swyllys 		if (keylist[i].israw)
34045b3e1433Swyllys 			pkey = raw_key_to_pkey(&keylist[i]);
34055b3e1433Swyllys 		else
34065b3e1433Swyllys 			pkey = (EVP_PKEY *)keylist[i].keyp;
34075b3e1433Swyllys 		if (pkey != NULL) {
34085b3e1433Swyllys 			if (X509_check_private_key(xcert, pkey)) {
34095b3e1433Swyllys 				return (pkey);
34105b3e1433Swyllys 			} else {
34115b3e1433Swyllys 				EVP_PKEY_free(pkey);
34125b3e1433Swyllys 				pkey = NULL;
34135b3e1433Swyllys 			}
34145b3e1433Swyllys 		}
34155b3e1433Swyllys 	}
34165b3e1433Swyllys 	return (pkey);
34175b3e1433Swyllys }
34185b3e1433Swyllys 
341999ebb4caSwyllys static KMF_RETURN
34205b3e1433Swyllys local_export_pk12(KMF_HANDLE_T handle,
342199ebb4caSwyllys 	KMF_CREDENTIAL *cred,
342299ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
342399ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
342499ebb4caSwyllys 	char *filename)
342599ebb4caSwyllys {
342699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
342799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
342899ebb4caSwyllys 	BIO *bio = NULL;
34295b3e1433Swyllys 	PKCS7 *cert_authsafe = NULL;
34305b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
34315b3e1433Swyllys 	STACK_OF(PKCS7) *authsafe_stack = NULL;
34325b3e1433Swyllys 	PKCS12 *p12_elem = NULL;
343399ebb4caSwyllys 	int i;
343499ebb4caSwyllys 
34355b3e1433Swyllys 	if (numcerts == 0 && numkeys == 0)
34365b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
34375b3e1433Swyllys 
343899ebb4caSwyllys 	/*
343999ebb4caSwyllys 	 * Open the output file.
344099ebb4caSwyllys 	 */
344199ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
344299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
344399ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
344499ebb4caSwyllys 		goto cleanup;
344599ebb4caSwyllys 	}
344699ebb4caSwyllys 
34475b3e1433Swyllys 	/* Start a PKCS#7 stack. */
34485b3e1433Swyllys 	authsafe_stack = sk_PKCS7_new_null();
34495b3e1433Swyllys 	if (authsafe_stack == NULL) {
34505b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
34515b3e1433Swyllys 		goto cleanup;
34525b3e1433Swyllys 	}
34535b3e1433Swyllys 	if (numcerts > 0) {
345499ebb4caSwyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
345599ebb4caSwyllys 			const uchar_t *p = certlist[i].certificate.Data;
345699ebb4caSwyllys 			long len = certlist[i].certificate.Length;
34575b3e1433Swyllys 			X509 *xcert = NULL;
34585b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
34595b3e1433Swyllys 			unsigned char keyid[EVP_MAX_MD_SIZE];
34605b3e1433Swyllys 			unsigned int keyidlen = 0;
346199ebb4caSwyllys 
346299ebb4caSwyllys 			xcert = d2i_X509(NULL, &p, len);
346399ebb4caSwyllys 			if (xcert == NULL) {
346499ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
346599ebb4caSwyllys 				rv = KMF_ERR_ENCODING;
346699ebb4caSwyllys 			}
34675b3e1433Swyllys 			if (certlist[i].kmf_private.label != NULL) {
34685b3e1433Swyllys 				/* Set alias attribute */
34695b3e1433Swyllys 				(void) X509_alias_set1(xcert,
34705b3e1433Swyllys 				    (uchar_t *)certlist[i].kmf_private.label,
34715b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label));
34725b3e1433Swyllys 			}
34735b3e1433Swyllys 			/* Check if there is a key corresponding to this cert */
34745b3e1433Swyllys 			pkey = find_matching_key(xcert, numkeys, keylist);
34755b3e1433Swyllys 
34765b3e1433Swyllys 			/*
34775b3e1433Swyllys 			 * If key is found, get fingerprint and create a
34785b3e1433Swyllys 			 * safebag.
34795b3e1433Swyllys 			 */
34805b3e1433Swyllys 			if (pkey != NULL) {
34815b3e1433Swyllys 				(void) X509_digest(xcert, EVP_sha1(),
34825b3e1433Swyllys 				    keyid, &keyidlen);
34835b3e1433Swyllys 				key_authsafe = add_key_to_safe(pkey, cred,
34845b3e1433Swyllys 				    keyid, keyidlen,
34855b3e1433Swyllys 				    certlist[i].kmf_private.label,
34865b3e1433Swyllys 				    (certlist[i].kmf_private.label ?
34875b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label) : 0));
34885b3e1433Swyllys 
34895b3e1433Swyllys 				if (key_authsafe == NULL) {
34905b3e1433Swyllys 					X509_free(xcert);
34915b3e1433Swyllys 					EVP_PKEY_free(pkey);
34925b3e1433Swyllys 					goto cleanup;
34935b3e1433Swyllys 				}
34945b3e1433Swyllys 				/* Put the key safe into the Auth Safe */
34955b3e1433Swyllys 				if (!sk_PKCS7_push(authsafe_stack,
34965b3e1433Swyllys 				    key_authsafe)) {
34975b3e1433Swyllys 					X509_free(xcert);
34985b3e1433Swyllys 					EVP_PKEY_free(pkey);
34995b3e1433Swyllys 					goto cleanup;
35005b3e1433Swyllys 				}
35015b3e1433Swyllys 			}
35025b3e1433Swyllys 
35035b3e1433Swyllys 			/* create a certificate safebag */
35045b3e1433Swyllys 			cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
35055b3e1433Swyllys 			    keyidlen);
35065b3e1433Swyllys 			if (cert_authsafe == NULL) {
35075b3e1433Swyllys 				X509_free(xcert);
35085b3e1433Swyllys 				EVP_PKEY_free(pkey);
35095b3e1433Swyllys 				goto cleanup;
35105b3e1433Swyllys 			}
35115b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
35125b3e1433Swyllys 				X509_free(xcert);
35135b3e1433Swyllys 				EVP_PKEY_free(pkey);
35145b3e1433Swyllys 				goto cleanup;
35155b3e1433Swyllys 			}
35165b3e1433Swyllys 
351799ebb4caSwyllys 			X509_free(xcert);
351899ebb4caSwyllys 			if (pkey)
351999ebb4caSwyllys 				EVP_PKEY_free(pkey);
352099ebb4caSwyllys 		}
35215b3e1433Swyllys 	} else if (numcerts == 0 && numkeys > 0) {
35225b3e1433Swyllys 		/*
35235b3e1433Swyllys 		 * If only adding keys to the file.
35245b3e1433Swyllys 		 */
35255b3e1433Swyllys 		for (i = 0; i < numkeys; i++) {
35265b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
35275b3e1433Swyllys 
35285b3e1433Swyllys 			if (keylist[i].israw)
35295b3e1433Swyllys 				pkey = raw_key_to_pkey(&keylist[i]);
35305b3e1433Swyllys 			else
35315b3e1433Swyllys 				pkey = (EVP_PKEY *)keylist[i].keyp;
35325b3e1433Swyllys 
35335b3e1433Swyllys 			if (pkey == NULL)
35345b3e1433Swyllys 				continue;
35355b3e1433Swyllys 
35365b3e1433Swyllys 			key_authsafe = add_key_to_safe(pkey, cred,
35375b3e1433Swyllys 			    NULL, 0, NULL, 0);
35385b3e1433Swyllys 
35395b3e1433Swyllys 			if (key_authsafe == NULL) {
35405b3e1433Swyllys 				EVP_PKEY_free(pkey);
35415b3e1433Swyllys 				goto cleanup;
35425b3e1433Swyllys 			}
35435b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
35445b3e1433Swyllys 				EVP_PKEY_free(pkey);
35455b3e1433Swyllys 				goto cleanup;
35465b3e1433Swyllys 			}
35475b3e1433Swyllys 		}
35485b3e1433Swyllys 	}
35495b3e1433Swyllys 	p12_elem = PKCS12_init(NID_pkcs7_data);
35505b3e1433Swyllys 	if (p12_elem == NULL) {
35515b3e1433Swyllys 		goto cleanup;
355299ebb4caSwyllys 	}
355399ebb4caSwyllys 
35545b3e1433Swyllys 	/* Put the PKCS#7 stack into the PKCS#12 element. */
35555b3e1433Swyllys 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
35565b3e1433Swyllys 		goto cleanup;
35575b3e1433Swyllys 	}
35585b3e1433Swyllys 
35595b3e1433Swyllys 	/* Set the integrity MAC on the PKCS#12 element. */
35605b3e1433Swyllys 	if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
35615b3e1433Swyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
35625b3e1433Swyllys 		goto cleanup;
35635b3e1433Swyllys 	}
35645b3e1433Swyllys 
35655b3e1433Swyllys 	/* Write the PKCS#12 element to the export file. */
35665b3e1433Swyllys 	if (!i2d_PKCS12_bio(bio, p12_elem)) {
35675b3e1433Swyllys 		goto cleanup;
35685b3e1433Swyllys 	}
35695b3e1433Swyllys 	PKCS12_free(p12_elem);
35705b3e1433Swyllys 
357199ebb4caSwyllys cleanup:
35725b3e1433Swyllys 	/* Clear away the PKCS#7 stack, we're done with it. */
35735b3e1433Swyllys 	if (authsafe_stack)
35745b3e1433Swyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
357599ebb4caSwyllys 
357699ebb4caSwyllys 	if (bio != NULL)
357799ebb4caSwyllys 		(void) BIO_free_all(bio);
357899ebb4caSwyllys 
357999ebb4caSwyllys 	return (rv);
358099ebb4caSwyllys }
358199ebb4caSwyllys 
358299ebb4caSwyllys KMF_RETURN
358330a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
358430a5e8faSwyllys     KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
358530a5e8faSwyllys     KMF_CREDENTIAL *p12cred, char *filename)
358630a5e8faSwyllys {
358730a5e8faSwyllys 	KMF_RETURN rv;
358830a5e8faSwyllys 
358930a5e8faSwyllys 	if (certlist == NULL && keylist == NULL)
359030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
359130a5e8faSwyllys 
35925b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, numcerts, certlist,
359330a5e8faSwyllys 	    numkeys, keylist, filename);
359430a5e8faSwyllys 
359530a5e8faSwyllys 	return (rv);
359630a5e8faSwyllys }
359730a5e8faSwyllys 
359830a5e8faSwyllys KMF_RETURN
359930a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
360099ebb4caSwyllys {
360199ebb4caSwyllys 	KMF_RETURN rv;
360299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
360399ebb4caSwyllys 	char *fullpath = NULL;
360430a5e8faSwyllys 	char *dirpath = NULL;
360530a5e8faSwyllys 	char *certfile = NULL;
360630a5e8faSwyllys 	char *keyfile = NULL;
360730a5e8faSwyllys 	char *filename = NULL;
360830a5e8faSwyllys 	KMF_CREDENTIAL *p12cred = NULL;
36095b3e1433Swyllys 	KMF_X509_DER_CERT certdata;
36105b3e1433Swyllys 	KMF_KEY_HANDLE key;
36115b3e1433Swyllys 	int gotkey = 0;
36125b3e1433Swyllys 	int gotcert = 0;
361330a5e8faSwyllys 
361430a5e8faSwyllys 	if (handle == NULL)
361530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
361699ebb4caSwyllys 
361799ebb4caSwyllys 	/*
361899ebb4caSwyllys 	 *  First, find the certificate.
361999ebb4caSwyllys 	 */
362030a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
362130a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
362230a5e8faSwyllys 	if (certfile != NULL) {
362330a5e8faSwyllys 		fullpath = get_fullpath(dirpath, certfile);
362499ebb4caSwyllys 		if (fullpath == NULL)
362599ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
362699ebb4caSwyllys 
362799ebb4caSwyllys 		if (isdir(fullpath)) {
362899ebb4caSwyllys 			free(fullpath);
362999ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
363099ebb4caSwyllys 		}
363199ebb4caSwyllys 
36325b3e1433Swyllys 		(void) memset(&certdata, 0, sizeof (certdata));
36335b3e1433Swyllys 		rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL,
36345b3e1433Swyllys 		    fullpath, &certdata.certificate);
363599ebb4caSwyllys 		if (rv != KMF_OK)
363699ebb4caSwyllys 			goto end;
363730a5e8faSwyllys 
36385b3e1433Swyllys 		gotcert++;
36395b3e1433Swyllys 		certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
364030a5e8faSwyllys 		free(fullpath);
364199ebb4caSwyllys 	}
364299ebb4caSwyllys 
364399ebb4caSwyllys 	/*
364499ebb4caSwyllys 	 * Now find the private key.
364599ebb4caSwyllys 	 */
364630a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
364730a5e8faSwyllys 	if (keyfile != NULL) {
364830a5e8faSwyllys 		fullpath = get_fullpath(dirpath, keyfile);
364999ebb4caSwyllys 		if (fullpath == NULL)
365099ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
365199ebb4caSwyllys 
365299ebb4caSwyllys 		if (isdir(fullpath)) {
365399ebb4caSwyllys 			free(fullpath);
365499ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
365599ebb4caSwyllys 		}
365699ebb4caSwyllys 
36575b3e1433Swyllys 		(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
36585b3e1433Swyllys 		rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
36595b3e1433Swyllys 		if (rv != KMF_OK)
366099ebb4caSwyllys 			goto end;
36615b3e1433Swyllys 		gotkey++;
366299ebb4caSwyllys 	}
366399ebb4caSwyllys 
366499ebb4caSwyllys 	/*
366599ebb4caSwyllys 	 * Open the output file.
366699ebb4caSwyllys 	 */
366730a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
366830a5e8faSwyllys 	    numattr);
366930a5e8faSwyllys 	if (filename == NULL) {
367030a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
367130a5e8faSwyllys 		goto end;
367230a5e8faSwyllys 	}
367330a5e8faSwyllys 
367499ebb4caSwyllys 	/* Stick the key and the cert into a PKCS#12 file */
367530a5e8faSwyllys 	p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
367630a5e8faSwyllys 	if (p12cred == NULL) {
367730a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
367830a5e8faSwyllys 		goto end;
367930a5e8faSwyllys 	}
368030a5e8faSwyllys 
36815b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, 1, &certdata,
36825b3e1433Swyllys 	    1, &key, filename);
368399ebb4caSwyllys 
368499ebb4caSwyllys end:
368599ebb4caSwyllys 	if (fullpath)
368699ebb4caSwyllys 		free(fullpath);
368799ebb4caSwyllys 
36885b3e1433Swyllys 	if (gotcert)
36895b3e1433Swyllys 		kmf_free_kmf_cert(handle, &certdata);
36905b3e1433Swyllys 	if (gotkey)
36915b3e1433Swyllys 		kmf_free_kmf_key(handle, &key);
369299ebb4caSwyllys 	return (rv);
369399ebb4caSwyllys }
369499ebb4caSwyllys 
369571593db2Swyllys /*
369671593db2Swyllys  * Helper function to extract keys and certificates from
369771593db2Swyllys  * a single PEM file.  Typically the file should contain a
369871593db2Swyllys  * private key and an associated public key wrapped in an x509 cert.
369971593db2Swyllys  * However, the file may be just a list of X509 certs with no keys.
370071593db2Swyllys  */
370171593db2Swyllys static KMF_RETURN
370230a5e8faSwyllys extract_pem(KMF_HANDLE *kmfh,
370330a5e8faSwyllys 	char *issuer, char *subject, KMF_BIGINT *serial,
370402744e81Swyllys 	char *filename, CK_UTF8CHAR *pin,
370571593db2Swyllys 	CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
370671593db2Swyllys 	int *numcerts)
3707a2d4930dSDan OpenSolaris Anderson /* ARGSUSED6 */
370871593db2Swyllys {
370971593db2Swyllys 	KMF_RETURN rv = KMF_OK;
371071593db2Swyllys 	FILE *fp;
371134acef67Swyllys 	STACK_OF(X509_INFO) *x509_info_stack = NULL;
371202744e81Swyllys 	int i, ncerts = 0, matchcerts = 0;
371371593db2Swyllys 	EVP_PKEY *pkey = NULL;
371471593db2Swyllys 	X509_INFO *info;
371571593db2Swyllys 	X509 *x;
37165b3e1433Swyllys 	X509_INFO **cert_infos = NULL;
371771593db2Swyllys 	KMF_DATA *certlist = NULL;
371871593db2Swyllys 
371971593db2Swyllys 	if (priv_key)
372071593db2Swyllys 		*priv_key = NULL;
372171593db2Swyllys 	if (certs)
372271593db2Swyllys 		*certs = NULL;
372371593db2Swyllys 	fp = fopen(filename, "r");
37245b3e1433Swyllys 	if (fp == NULL)
372571593db2Swyllys 		return (KMF_ERR_OPEN_FILE);
37265b3e1433Swyllys 
372771593db2Swyllys 	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
372871593db2Swyllys 	if (x509_info_stack == NULL) {
372971593db2Swyllys 		(void) fclose(fp);
373071593db2Swyllys 		return (KMF_ERR_ENCODING);
373171593db2Swyllys 	}
37325b3e1433Swyllys 	cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
37335b3e1433Swyllys 	    sizeof (X509_INFO *));
37345b3e1433Swyllys 	if (cert_infos == NULL) {
37355b3e1433Swyllys 		(void) fclose(fp);
37365b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
37375b3e1433Swyllys 		goto err;
37385b3e1433Swyllys 	}
373971593db2Swyllys 
37405b3e1433Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3741d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
374234acef67Swyllys 		cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
374371593db2Swyllys 		ncerts++;
374471593db2Swyllys 	}
374571593db2Swyllys 
374671593db2Swyllys 	if (ncerts == 0) {
374771593db2Swyllys 		(void) fclose(fp);
374834acef67Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
374934acef67Swyllys 		goto err;
375071593db2Swyllys 	}
375171593db2Swyllys 
375271593db2Swyllys 	if (priv_key != NULL) {
375371593db2Swyllys 		rewind(fp);
375471593db2Swyllys 		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
375571593db2Swyllys 	}
375671593db2Swyllys 	(void) fclose(fp);
375771593db2Swyllys 
375871593db2Swyllys 	x = cert_infos[ncerts - 1]->x509;
375971593db2Swyllys 	/*
376071593db2Swyllys 	 * Make sure the private key matchs the last cert in the file.
376171593db2Swyllys 	 */
376271593db2Swyllys 	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
376371593db2Swyllys 		EVP_PKEY_free(pkey);
376434acef67Swyllys 		rv = KMF_ERR_KEY_MISMATCH;
376534acef67Swyllys 		goto err;
376671593db2Swyllys 	}
376771593db2Swyllys 
3768a2d4930dSDan OpenSolaris Anderson 	certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
376971593db2Swyllys 	if (certlist == NULL) {
377071593db2Swyllys 		if (pkey != NULL)
377171593db2Swyllys 			EVP_PKEY_free(pkey);
377234acef67Swyllys 		rv = KMF_ERR_MEMORY;
377334acef67Swyllys 		goto err;
377471593db2Swyllys 	}
377571593db2Swyllys 
377671593db2Swyllys 	/*
377771593db2Swyllys 	 * Convert all of the certs to DER format.
377871593db2Swyllys 	 */
377902744e81Swyllys 	matchcerts = 0;
378071593db2Swyllys 	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
378102744e81Swyllys 		boolean_t match = FALSE;
378271593db2Swyllys 		info =  cert_infos[ncerts - 1 - i];
378371593db2Swyllys 
378430a5e8faSwyllys 		rv = check_cert(info->x509, issuer, subject, serial, &match);
378502744e81Swyllys 		if (rv != KMF_OK || match != TRUE) {
378602744e81Swyllys 			rv = KMF_OK;
378702744e81Swyllys 			continue;
378802744e81Swyllys 		}
378902744e81Swyllys 
379002744e81Swyllys 		rv = ssl_cert2KMFDATA(kmfh, info->x509,
379102744e81Swyllys 			&certlist[matchcerts++]);
379271593db2Swyllys 
379371593db2Swyllys 		if (rv != KMF_OK) {
3794e65e5c2dSWyllys Ingersoll 			int j;
3795e65e5c2dSWyllys Ingersoll 			for (j = 0; j < matchcerts; j++)
3796e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certlist[j]);
379771593db2Swyllys 			free(certlist);
379871593db2Swyllys 			certlist = NULL;
379902744e81Swyllys 			ncerts = matchcerts = 0;
380071593db2Swyllys 		}
380171593db2Swyllys 	}
380271593db2Swyllys 
380371593db2Swyllys 	if (numcerts != NULL)
380402744e81Swyllys 		*numcerts = matchcerts;
3805a2d4930dSDan OpenSolaris Anderson 
3806e65e5c2dSWyllys Ingersoll 	if (certs != NULL)
380771593db2Swyllys 		*certs = certlist;
3808e65e5c2dSWyllys Ingersoll 	else if (certlist != NULL) {
3809e65e5c2dSWyllys Ingersoll 		for (i = 0; i < ncerts; i++)
3810e65e5c2dSWyllys Ingersoll 			kmf_free_data(&certlist[i]);
3811a2d4930dSDan OpenSolaris Anderson 		free(certlist);
3812a2d4930dSDan OpenSolaris Anderson 		certlist = NULL;
3813a2d4930dSDan OpenSolaris Anderson 	}
381471593db2Swyllys 
381571593db2Swyllys 	if (priv_key == NULL && pkey != NULL)
381671593db2Swyllys 		EVP_PKEY_free(pkey);
381771593db2Swyllys 	else if (priv_key != NULL && pkey != NULL)
381871593db2Swyllys 		*priv_key = pkey;
381971593db2Swyllys 
382034acef67Swyllys err:
382134acef67Swyllys 	/* Cleanup the stack of X509 info records */
382234acef67Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3823d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
382434acef67Swyllys 		info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
382534acef67Swyllys 		X509_INFO_free(info);
382634acef67Swyllys 	}
382734acef67Swyllys 	if (x509_info_stack)
382834acef67Swyllys 		sk_X509_INFO_free(x509_info_stack);
382934acef67Swyllys 
38305b3e1433Swyllys 	if (cert_infos != NULL)
38315b3e1433Swyllys 		free(cert_infos);
38325b3e1433Swyllys 
383371593db2Swyllys 	return (rv);
383471593db2Swyllys }
383571593db2Swyllys 
38365b3e1433Swyllys static KMF_RETURN
3837300fdee2SAndy Fiddaman openssl_parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
38385b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
38395b3e1433Swyllys {
38405b3e1433Swyllys 	KMF_RETURN ret;
38415b3e1433Swyllys 	int i;
38425b3e1433Swyllys 
38435b3e1433Swyllys 	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
3844d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
38455b3e1433Swyllys 		PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
38465b3e1433Swyllys 		ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
38475b3e1433Swyllys 		    keys, certs);
38485b3e1433Swyllys 
38495b3e1433Swyllys 		if (ret != KMF_OK)
38505b3e1433Swyllys 			return (ret);
38515b3e1433Swyllys 	}
38525b3e1433Swyllys 
38535b3e1433Swyllys 	return (ret);
38545b3e1433Swyllys }
38555b3e1433Swyllys 
38565b3e1433Swyllys static KMF_RETURN
38575b3e1433Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
38585b3e1433Swyllys {
38595b3e1433Swyllys 	X509_ATTRIBUTE *attr = NULL;
38605b3e1433Swyllys 
38615b3e1433Swyllys 	if (pkey == NULL || attrib == NULL)
38625b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
38635b3e1433Swyllys 
38645b3e1433Swyllys 	attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
38655b3e1433Swyllys 	if (attr != NULL) {
38665b3e1433Swyllys 		int i;
3867300fdee2SAndy Fiddaman 
3868300fdee2SAndy Fiddaman 		if ((i = EVP_PKEY_get_attr_by_NID(pkey, nid, -1)) != -1)
3869300fdee2SAndy Fiddaman 			(void) EVP_PKEY_delete_attr(pkey, i);
3870300fdee2SAndy Fiddaman 		if (EVP_PKEY_add1_attr(pkey, attr) == 0) {
38715b3e1433Swyllys 			X509_ATTRIBUTE_free(attr);
38725b3e1433Swyllys 			return (KMF_ERR_MEMORY);
38735b3e1433Swyllys 		}
38745b3e1433Swyllys 	} else {
38755b3e1433Swyllys 		return (KMF_ERR_MEMORY);
38765b3e1433Swyllys 	}
38775b3e1433Swyllys 
38785b3e1433Swyllys 	return (KMF_OK);
38795b3e1433Swyllys }
38805b3e1433Swyllys 
38815b3e1433Swyllys static KMF_RETURN
38825b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
38835b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
38845b3e1433Swyllys {
38855b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
38865b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
38875b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
38885b3e1433Swyllys 	X509 *xcert = NULL;
3889300fdee2SAndy Fiddaman 	const ASN1_TYPE *keyid = NULL;
3890300fdee2SAndy Fiddaman 	const ASN1_TYPE *fname = NULL;
38915b3e1433Swyllys 	uchar_t *data = NULL;
38925b3e1433Swyllys 
3893300fdee2SAndy Fiddaman 	keyid = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID);
3894300fdee2SAndy Fiddaman 	fname = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName);
38955b3e1433Swyllys 
3896300fdee2SAndy Fiddaman 	switch (PKCS12_SAFEBAG_get_nid(bag)) {
38975b3e1433Swyllys 		case NID_keyBag:
38985b3e1433Swyllys 			if (keylist == NULL)
38995b3e1433Swyllys 				goto end;
3900300fdee2SAndy Fiddaman 			pkey = EVP_PKCS82PKEY(
3901300fdee2SAndy Fiddaman 			    PKCS12_SAFEBAG_get0_p8inf(bag));
39025b3e1433Swyllys 			if (pkey == NULL)
39035b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
39045b3e1433Swyllys 
39055b3e1433Swyllys 			break;
39065b3e1433Swyllys 		case NID_pkcs8ShroudedKeyBag:
39075b3e1433Swyllys 			if (keylist == NULL)
39085b3e1433Swyllys 				goto end;
3909300fdee2SAndy Fiddaman 			p8 = PKCS12_decrypt_skey(bag, pass, passlen);
39105b3e1433Swyllys 			if (p8 == NULL)
39115b3e1433Swyllys 				return (KMF_ERR_AUTH_FAILED);
39125b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(p8);
39135b3e1433Swyllys 			PKCS8_PRIV_KEY_INFO_free(p8);
39145b3e1433Swyllys 			if (pkey == NULL)
39155b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
39165b3e1433Swyllys 			break;
39175b3e1433Swyllys 		case NID_certBag:
39185b3e1433Swyllys 			if (certlist == NULL)
39195b3e1433Swyllys 				goto end;
3920300fdee2SAndy Fiddaman 			if (PKCS12_SAFEBAG_get_bag_nid(bag) !=
3921300fdee2SAndy Fiddaman 			    NID_x509Certificate)
39225b3e1433Swyllys 				return (KMF_ERR_PKCS12_FORMAT);
3923300fdee2SAndy Fiddaman 			xcert = PKCS12_SAFEBAG_get1_cert(bag);
39245b3e1433Swyllys 			if (xcert == NULL) {
39255b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
39265b3e1433Swyllys 				goto end;
39275b3e1433Swyllys 			}
39285b3e1433Swyllys 			if (keyid != NULL) {
39295b3e1433Swyllys 				if (X509_keyid_set1(xcert,
39305b3e1433Swyllys 				    keyid->value.octet_string->data,
39315b3e1433Swyllys 				    keyid->value.octet_string->length) == 0) {
39325b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
39335b3e1433Swyllys 					goto end;
39345b3e1433Swyllys 				}
39355b3e1433Swyllys 			}
39365b3e1433Swyllys 			if (fname != NULL) {
39375b3e1433Swyllys 				int len, r;
39385b3e1433Swyllys 				len = ASN1_STRING_to_UTF8(&data,
39395b3e1433Swyllys 				    fname->value.asn1_string);
39405b3e1433Swyllys 				if (len > 0 && data != NULL) {
39415b3e1433Swyllys 					r = X509_alias_set1(xcert, data, len);
39425b3e1433Swyllys 					if (r == NULL) {
39435b3e1433Swyllys 						ret = KMF_ERR_PKCS12_FORMAT;
39445b3e1433Swyllys 						goto end;
39455b3e1433Swyllys 					}
39465b3e1433Swyllys 				} else {
39475b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
39485b3e1433Swyllys 					goto end;
39495b3e1433Swyllys 				}
39505b3e1433Swyllys 			}
39515b3e1433Swyllys 			if (sk_X509_push(certlist, xcert) == 0)
39525b3e1433Swyllys 				ret = KMF_ERR_MEMORY;
39535b3e1433Swyllys 			else
39545b3e1433Swyllys 				xcert = NULL;
39555b3e1433Swyllys 			break;
39565b3e1433Swyllys 		case NID_safeContentsBag:
3957300fdee2SAndy Fiddaman 			return (openssl_parse_bags(
3958300fdee2SAndy Fiddaman 			    PKCS12_SAFEBAG_get0_safes(bag),
3959300fdee2SAndy Fiddaman 			    pass, keylist, certlist));
39605b3e1433Swyllys 		default:
39615b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39625b3e1433Swyllys 			break;
39635b3e1433Swyllys 	}
39645b3e1433Swyllys 
39655b3e1433Swyllys 	/*
39665b3e1433Swyllys 	 * Set the ID and/or FriendlyName attributes on the key.
39675b3e1433Swyllys 	 * If converting to PKCS11 objects, these can translate to CKA_ID
39685b3e1433Swyllys 	 * and CKA_LABEL values.
39695b3e1433Swyllys 	 */
39705b3e1433Swyllys 	if (pkey != NULL && ret == KMF_OK) {
39715b3e1433Swyllys 		ASN1_TYPE *attr = NULL;
39725b3e1433Swyllys 		if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
39735b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
39745b3e1433Swyllys 				return (KMF_ERR_MEMORY);
39755b3e1433Swyllys 			attr->value.octet_string =
39765b3e1433Swyllys 			    ASN1_STRING_dup(keyid->value.octet_string);
39775b3e1433Swyllys 			attr->type = V_ASN1_OCTET_STRING;
39785b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.octet_string;
39795b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
39805b3e1433Swyllys 			OPENSSL_free(attr);
39815b3e1433Swyllys 		}
39825b3e1433Swyllys 
39835b3e1433Swyllys 		if (ret == KMF_OK && fname != NULL &&
39845b3e1433Swyllys 		    fname->type == V_ASN1_BMPSTRING) {
39855b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
39865b3e1433Swyllys 				return (KMF_ERR_MEMORY);
39875b3e1433Swyllys 			attr->value.bmpstring =
39885b3e1433Swyllys 			    ASN1_STRING_dup(fname->value.bmpstring);
39895b3e1433Swyllys 			attr->type = V_ASN1_BMPSTRING;
39905b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.bmpstring;
39915b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
39925b3e1433Swyllys 			OPENSSL_free(attr);
39935b3e1433Swyllys 		}
39945b3e1433Swyllys 
39955b3e1433Swyllys 		if (ret == KMF_OK && keylist != NULL &&
39965b3e1433Swyllys 		    sk_EVP_PKEY_push(keylist, pkey) == 0)
39975b3e1433Swyllys 			ret = KMF_ERR_MEMORY;
39985b3e1433Swyllys 	}
39995b3e1433Swyllys 	if (ret == KMF_OK && keylist != NULL)
40005b3e1433Swyllys 		pkey = NULL;
40015b3e1433Swyllys end:
40025b3e1433Swyllys 	if (pkey != NULL)
40035b3e1433Swyllys 		EVP_PKEY_free(pkey);
40045b3e1433Swyllys 	if (xcert != NULL)
40055b3e1433Swyllys 		X509_free(xcert);
40065b3e1433Swyllys 	if (data != NULL)
40075b3e1433Swyllys 		OPENSSL_free(data);
40085b3e1433Swyllys 
40095b3e1433Swyllys 	return (ret);
40105b3e1433Swyllys }
40115b3e1433Swyllys 
40125b3e1433Swyllys static KMF_RETURN
40135b3e1433Swyllys openssl_pkcs12_parse(PKCS12 *p12, char *pin,
40145b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys,
40155b3e1433Swyllys 	STACK_OF(X509) *certs,
40165b3e1433Swyllys 	STACK_OF(X509) *ca)
4017a2d4930dSDan OpenSolaris Anderson /* ARGSUSED3 */
40185b3e1433Swyllys {
40195b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
40205b3e1433Swyllys 	STACK_OF(PKCS7) *asafes = NULL;
40215b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
40225b3e1433Swyllys 	int i, bagnid;
40235b3e1433Swyllys 	PKCS7 *p7;
40245b3e1433Swyllys 
40255b3e1433Swyllys 	if (p12 == NULL || (keys == NULL && certs == NULL))
40265b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
40275b3e1433Swyllys 
40285b3e1433Swyllys 	if (pin == NULL || *pin == NULL) {
40295b3e1433Swyllys 		if (PKCS12_verify_mac(p12, NULL, 0)) {
40305b3e1433Swyllys 			pin = NULL;
40315b3e1433Swyllys 		} else if (PKCS12_verify_mac(p12, "", 0)) {
40325b3e1433Swyllys 			pin = "";
40335b3e1433Swyllys 		} else {
40345b3e1433Swyllys 			return (KMF_ERR_AUTH_FAILED);
40355b3e1433Swyllys 		}
40365b3e1433Swyllys 	} else if (!PKCS12_verify_mac(p12, pin, -1)) {
40375b3e1433Swyllys 		return (KMF_ERR_AUTH_FAILED);
40385b3e1433Swyllys 	}
40395b3e1433Swyllys 
40405b3e1433Swyllys 	if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
40415b3e1433Swyllys 		return (KMF_ERR_PKCS12_FORMAT);
40425b3e1433Swyllys 
40435b3e1433Swyllys 	for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
40445b3e1433Swyllys 		bags = NULL;
4045d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
40465b3e1433Swyllys 		p7 = sk_PKCS7_value(asafes, i);
40475b3e1433Swyllys 		bagnid = OBJ_obj2nid(p7->type);
40485b3e1433Swyllys 
40495b3e1433Swyllys 		if (bagnid == NID_pkcs7_data) {
40505b3e1433Swyllys 			bags = PKCS12_unpack_p7data(p7);
40515b3e1433Swyllys 		} else if (bagnid == NID_pkcs7_encrypted) {
40525b3e1433Swyllys 			bags = PKCS12_unpack_p7encdata(p7, pin,
40535b3e1433Swyllys 			    (pin ? strlen(pin) : 0));
40545b3e1433Swyllys 		} else {
40555b3e1433Swyllys 			continue;
40565b3e1433Swyllys 		}
40575b3e1433Swyllys 		if (bags == NULL) {
40585b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
40595b3e1433Swyllys 			goto out;
40605b3e1433Swyllys 		}
40615b3e1433Swyllys 
40625b3e1433Swyllys 		if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
40635b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
40645b3e1433Swyllys 
40655b3e1433Swyllys 		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
40665b3e1433Swyllys 	}
40675b3e1433Swyllys out:
40685b3e1433Swyllys 	if (asafes != NULL)
40695b3e1433Swyllys 		sk_PKCS7_pop_free(asafes, PKCS7_free);
40705b3e1433Swyllys 
40715b3e1433Swyllys 	return (ret);
40725b3e1433Swyllys }
40735b3e1433Swyllys 
407499ebb4caSwyllys /*
407599ebb4caSwyllys  * Helper function to decrypt and parse PKCS#12 import file.
407699ebb4caSwyllys  */
407799ebb4caSwyllys static KMF_RETURN
407899ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
40795b3e1433Swyllys 	STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs,
40805b3e1433Swyllys 	STACK_OF(X509) **ca)
4081a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */
408299ebb4caSwyllys {
408399ebb4caSwyllys 	PKCS12			*pk12, *pk12_tmp;
40845b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*pkeylist = NULL;
40855b3e1433Swyllys 	STACK_OF(X509)		*xcertlist = NULL;
40865b3e1433Swyllys 	STACK_OF(X509)		*cacertlist = NULL;
408799ebb4caSwyllys 
408899ebb4caSwyllys 	if ((pk12 = PKCS12_new()) == NULL) {
408999ebb4caSwyllys 		return (KMF_ERR_MEMORY);
409099ebb4caSwyllys 	}
409199ebb4caSwyllys 
409299ebb4caSwyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
409399ebb4caSwyllys 		/* This is ok; it seems to mean there is no more to read. */
409499ebb4caSwyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
409599ebb4caSwyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
409699ebb4caSwyllys 			goto end_extract_pkcs12;
409799ebb4caSwyllys 
409899ebb4caSwyllys 		PKCS12_free(pk12);
409999ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
410099ebb4caSwyllys 	}
410199ebb4caSwyllys 	pk12 = pk12_tmp;
410299ebb4caSwyllys 
41035b3e1433Swyllys 	xcertlist = sk_X509_new_null();
41045b3e1433Swyllys 	if (xcertlist == NULL) {
41055b3e1433Swyllys 		PKCS12_free(pk12);
41065b3e1433Swyllys 		return (KMF_ERR_MEMORY);
41075b3e1433Swyllys 	}
41085b3e1433Swyllys 	pkeylist = sk_EVP_PKEY_new_null();
41095b3e1433Swyllys 	if (pkeylist == NULL) {
41105b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
41115b3e1433Swyllys 		PKCS12_free(pk12);
41125b3e1433Swyllys 		return (KMF_ERR_MEMORY);
41135b3e1433Swyllys 	}
41145b3e1433Swyllys 
41155b3e1433Swyllys 	if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
41165b3e1433Swyllys 	    cacertlist) != KMF_OK) {
41175b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
41185b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
411999ebb4caSwyllys 		PKCS12_free(pk12);
412099ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
412199ebb4caSwyllys 	}
412299ebb4caSwyllys 
41235b3e1433Swyllys 	if (priv_key && pkeylist)
41245b3e1433Swyllys 		*priv_key = pkeylist;
41255b3e1433Swyllys 	else if (pkeylist)
41265b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
41275b3e1433Swyllys 	if (certs && xcertlist)
41285b3e1433Swyllys 		*certs = xcertlist;
41295b3e1433Swyllys 	else if (xcertlist)
41305b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
41315b3e1433Swyllys 	if (ca && cacertlist)
41325b3e1433Swyllys 		*ca = cacertlist;
41335b3e1433Swyllys 	else if (cacertlist)
41345b3e1433Swyllys 		sk_X509_pop_free(cacertlist, X509_free);
413599ebb4caSwyllys 
41365b3e1433Swyllys end_extract_pkcs12:
413799ebb4caSwyllys 
413899ebb4caSwyllys 	PKCS12_free(pk12);
413999ebb4caSwyllys 	return (KMF_OK);
414099ebb4caSwyllys }
414199ebb4caSwyllys 
414299ebb4caSwyllys static KMF_RETURN
414399ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
414499ebb4caSwyllys {
414599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
414699ebb4caSwyllys 	uint32_t sz;
414799ebb4caSwyllys 
414899ebb4caSwyllys 	sz = BN_num_bytes(from);
414999ebb4caSwyllys 	to->val = (uchar_t *)malloc(sz);
415099ebb4caSwyllys 	if (to->val == NULL)
415199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
415299ebb4caSwyllys 
415399ebb4caSwyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
415499ebb4caSwyllys 		free(to->val);
415599ebb4caSwyllys 		to->val = NULL;
415699ebb4caSwyllys 		to->len = 0;
415799ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
415899ebb4caSwyllys 	}
415999ebb4caSwyllys 
416099ebb4caSwyllys 	return (rv);
416199ebb4caSwyllys }
416299ebb4caSwyllys 
416399ebb4caSwyllys static KMF_RETURN
416499ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
416599ebb4caSwyllys {
416699ebb4caSwyllys 	KMF_RETURN rv;
416799ebb4caSwyllys 	KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
416899ebb4caSwyllys 
4169300fdee2SAndy Fiddaman 	const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmpq, *iqmp;
4170300fdee2SAndy Fiddaman 
4171300fdee2SAndy Fiddaman 	RSA_get0_key(rsa, &n, &e, &d);
4172300fdee2SAndy Fiddaman 	RSA_get0_factors(rsa, &p, &q);
4173300fdee2SAndy Fiddaman 	RSA_get0_crt_params(rsa, &dmp1, &dmpq, &iqmp);
4174300fdee2SAndy Fiddaman 
417599ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
4176300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)n, &kmfkey->mod)) != KMF_OK)
417799ebb4caSwyllys 		goto cleanup;
417899ebb4caSwyllys 
4179300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)e, &kmfkey->pubexp)) != KMF_OK)
418099ebb4caSwyllys 		goto cleanup;
418199ebb4caSwyllys 
4182300fdee2SAndy Fiddaman 	if (d != NULL)
4183300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)d, &kmfkey->priexp)) != KMF_OK)
418499ebb4caSwyllys 			goto cleanup;
418599ebb4caSwyllys 
4186300fdee2SAndy Fiddaman 	if (p != NULL)
4187300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime1)) != KMF_OK)
418899ebb4caSwyllys 			goto cleanup;
418999ebb4caSwyllys 
4190300fdee2SAndy Fiddaman 	if (q != NULL)
4191300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->prime2)) != KMF_OK)
419299ebb4caSwyllys 			goto cleanup;
419399ebb4caSwyllys 
4194300fdee2SAndy Fiddaman 	if (dmp1 != NULL)
4195300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)dmp1, &kmfkey->exp1)) != KMF_OK)
419699ebb4caSwyllys 			goto cleanup;
419799ebb4caSwyllys 
4198300fdee2SAndy Fiddaman 	if (dmpq != NULL)
4199300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)dmpq, &kmfkey->exp2)) != KMF_OK)
420099ebb4caSwyllys 			goto cleanup;
420199ebb4caSwyllys 
4202300fdee2SAndy Fiddaman 	if (iqmp != NULL)
4203300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)iqmp, &kmfkey->coef)) != KMF_OK)
420499ebb4caSwyllys 			goto cleanup;
420599ebb4caSwyllys cleanup:
420699ebb4caSwyllys 	if (rv != KMF_OK)
420730a5e8faSwyllys 		kmf_free_raw_key(key);
420899ebb4caSwyllys 	else
420999ebb4caSwyllys 		key->keytype = KMF_RSA;
421099ebb4caSwyllys 
421199ebb4caSwyllys 	/*
421299ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
421399ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
421499ebb4caSwyllys 	 */
421599ebb4caSwyllys 	RSA_free(rsa);
421699ebb4caSwyllys 
421799ebb4caSwyllys 	return (rv);
421899ebb4caSwyllys }
421999ebb4caSwyllys 
422099ebb4caSwyllys static KMF_RETURN
422199ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
422299ebb4caSwyllys {
422399ebb4caSwyllys 	KMF_RETURN rv;
422499ebb4caSwyllys 	KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
4225300fdee2SAndy Fiddaman 	const BIGNUM *p, *q, *g, *priv_key;
4226300fdee2SAndy Fiddaman 
4227300fdee2SAndy Fiddaman 	DSA_get0_pqg(dsa, &p, &q, &g);
4228300fdee2SAndy Fiddaman 	DSA_get0_key(dsa, NULL, &priv_key);
422999ebb4caSwyllys 
423099ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
4231300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime)) != KMF_OK)
423299ebb4caSwyllys 		goto cleanup;
423399ebb4caSwyllys 
4234300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->subprime)) != KMF_OK)
423599ebb4caSwyllys 		goto cleanup;
423699ebb4caSwyllys 
4237300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)g, &kmfkey->base)) != KMF_OK)
423899ebb4caSwyllys 		goto cleanup;
423999ebb4caSwyllys 
4240300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)priv_key, &kmfkey->value)) != KMF_OK)
424199ebb4caSwyllys 		goto cleanup;
424299ebb4caSwyllys 
424399ebb4caSwyllys cleanup:
424499ebb4caSwyllys 	if (rv != KMF_OK)
424530a5e8faSwyllys 		kmf_free_raw_key(key);
424699ebb4caSwyllys 	else
424799ebb4caSwyllys 		key->keytype = KMF_DSA;
424899ebb4caSwyllys 
424999ebb4caSwyllys 	/*
425099ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
425199ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
425299ebb4caSwyllys 	 */
425399ebb4caSwyllys 	DSA_free(dsa);
425499ebb4caSwyllys 
425599ebb4caSwyllys 	return (rv);
425699ebb4caSwyllys }
425799ebb4caSwyllys 
425899ebb4caSwyllys static KMF_RETURN
425999ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
42605b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
426199ebb4caSwyllys {
426299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
42635b3e1433Swyllys 	KMF_X509_DER_CERT *list = (*certlist);
42645b3e1433Swyllys 	KMF_X509_DER_CERT cert;
426599ebb4caSwyllys 	int n = (*ncerts);
426699ebb4caSwyllys 
426799ebb4caSwyllys 	if (list == NULL) {
42685b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
426999ebb4caSwyllys 	} else {
42705b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)realloc(list,
42715b3e1433Swyllys 		    sizeof (KMF_X509_DER_CERT) * (n + 1));
427299ebb4caSwyllys 	}
427399ebb4caSwyllys 
427499ebb4caSwyllys 	if (list == NULL)
427599ebb4caSwyllys 		return (KMF_ERR_MEMORY);
427699ebb4caSwyllys 
42775b3e1433Swyllys 	(void) memset(&cert, 0, sizeof (cert));
42785b3e1433Swyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
427999ebb4caSwyllys 	if (rv == KMF_OK) {
42805b3e1433Swyllys 		int len = 0;
42815b3e1433Swyllys 		/* Get the alias name for the cert if there is one */
42825b3e1433Swyllys 		char *a = (char *)X509_alias_get0(sslcert, &len);
42835b3e1433Swyllys 		if (a != NULL)
42845b3e1433Swyllys 			cert.kmf_private.label = strdup(a);
42855b3e1433Swyllys 		cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
42865b3e1433Swyllys 
428799ebb4caSwyllys 		list[n] = cert;
428899ebb4caSwyllys 		(*ncerts) = n + 1;
428999ebb4caSwyllys 
429099ebb4caSwyllys 		*certlist = list;
429199ebb4caSwyllys 	} else {
429299ebb4caSwyllys 		free(list);
429399ebb4caSwyllys 	}
429499ebb4caSwyllys 
429599ebb4caSwyllys 	return (rv);
429699ebb4caSwyllys }
429799ebb4caSwyllys 
429899ebb4caSwyllys static KMF_RETURN
429999ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
430099ebb4caSwyllys 	KMF_RAW_KEY_DATA *newkey, int *nkeys)
430199ebb4caSwyllys {
430299ebb4caSwyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
430399ebb4caSwyllys 	int n = (*nkeys);
430499ebb4caSwyllys 
430599ebb4caSwyllys 	if (list == NULL) {
430699ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
430799ebb4caSwyllys 	} else {
430899ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
430999ebb4caSwyllys 		    sizeof (KMF_RAW_KEY_DATA) * (n + 1));
431099ebb4caSwyllys 	}
431199ebb4caSwyllys 
431299ebb4caSwyllys 	if (list == NULL)
431399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
431499ebb4caSwyllys 
431599ebb4caSwyllys 	list[n] = *newkey;
431699ebb4caSwyllys 	(*nkeys) = n + 1;
431799ebb4caSwyllys 
431899ebb4caSwyllys 	*keylist = list;
431999ebb4caSwyllys 
432099ebb4caSwyllys 	return (KMF_OK);
432199ebb4caSwyllys }
432299ebb4caSwyllys 
432330a5e8faSwyllys static KMF_RETURN
432430a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
432530a5e8faSwyllys {
432630a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
43275b3e1433Swyllys 	X509_ATTRIBUTE *attr;
4328300fdee2SAndy Fiddaman 	RSA *rsa;
4329300fdee2SAndy Fiddaman 	DSA *dsa;
4330300fdee2SAndy Fiddaman 	int loc;
433130a5e8faSwyllys 
433230a5e8faSwyllys 	if (pkey == NULL || key == NULL)
433330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
433430a5e8faSwyllys 	/* Convert SSL key to raw key */
4335300fdee2SAndy Fiddaman 	if ((rsa = EVP_PKEY_get1_RSA(pkey)) != NULL) {
4336300fdee2SAndy Fiddaman 		rv = exportRawRSAKey(rsa, key);
433730a5e8faSwyllys 		if (rv != KMF_OK)
433830a5e8faSwyllys 			return (rv);
4339300fdee2SAndy Fiddaman 	} else if ((dsa = EVP_PKEY_get1_DSA(pkey)) != NULL) {
4340300fdee2SAndy Fiddaman 		rv = exportRawDSAKey(dsa, key);
434130a5e8faSwyllys 		if (rv != KMF_OK)
434230a5e8faSwyllys 			return (rv);
4343300fdee2SAndy Fiddaman 	} else
434430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
4345300fdee2SAndy Fiddaman 
43465b3e1433Swyllys 	/*
43475b3e1433Swyllys 	 * If friendlyName, add it to record.
43485b3e1433Swyllys 	 */
4349300fdee2SAndy Fiddaman 
4350300fdee2SAndy Fiddaman 	if ((loc = EVP_PKEY_get_attr_by_NID(pkey,
4351300fdee2SAndy Fiddaman 	    NID_friendlyName, -1)) != -1 &&
4352300fdee2SAndy Fiddaman 	    (attr = EVP_PKEY_get_attr(pkey, loc))) {
43535b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
4354300fdee2SAndy Fiddaman 		int numattr = X509_ATTRIBUTE_count(attr);
4355300fdee2SAndy Fiddaman 		if (numattr > 0) {
4356300fdee2SAndy Fiddaman 			ty = X509_ATTRIBUTE_get0_type(attr, 0);
43575b3e1433Swyllys 		}
43585b3e1433Swyllys 		if (ty != NULL) {
435970f9559bSTheo Schlossnagle 			key->label = OPENSSL_uni2asc(ty->value.bmpstring->data,
436070f9559bSTheo Schlossnagle 			    ty->value.bmpstring->length);
43615b3e1433Swyllys 		}
43625b3e1433Swyllys 	} else {
43635b3e1433Swyllys 		key->label = NULL;
43645b3e1433Swyllys 	}
43655b3e1433Swyllys 
43665b3e1433Swyllys 	/*
43675b3e1433Swyllys 	 * If KeyID, add it to record as a KMF_DATA object.
43685b3e1433Swyllys 	 */
4369300fdee2SAndy Fiddaman 	if ((loc = EVP_PKEY_get_attr_by_NID(pkey,
4370300fdee2SAndy Fiddaman 	    NID_localKeyID, -1)) != -1 &&
4371300fdee2SAndy Fiddaman 	    (attr = EVP_PKEY_get_attr(pkey, loc)) != NULL) {
43725b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
4373300fdee2SAndy Fiddaman 		int numattr = X509_ATTRIBUTE_count(attr);
4374300fdee2SAndy Fiddaman 		if (numattr > 0)
4375300fdee2SAndy Fiddaman 			ty = X509_ATTRIBUTE_get0_type(attr, 0);
43765b3e1433Swyllys 		key->id.Data = (uchar_t *)malloc(
43775b3e1433Swyllys 		    ty->value.octet_string->length);
43785b3e1433Swyllys 		if (key->id.Data == NULL)
43795b3e1433Swyllys 			return (KMF_ERR_MEMORY);
43805b3e1433Swyllys 		(void) memcpy(key->id.Data, ty->value.octet_string->data,
43815b3e1433Swyllys 		    ty->value.octet_string->length);
43825b3e1433Swyllys 		key->id.Length = ty->value.octet_string->length;
43835b3e1433Swyllys 	} else {
43845b3e1433Swyllys 		(void) memset(&key->id, 0, sizeof (KMF_DATA));
43855b3e1433Swyllys 	}
438630a5e8faSwyllys 
438730a5e8faSwyllys 	return (rv);
438830a5e8faSwyllys }
438999ebb4caSwyllys 
439099ebb4caSwyllys static KMF_RETURN
439199ebb4caSwyllys convertPK12Objects(
439299ebb4caSwyllys 	KMF_HANDLE *kmfh,
43935b3e1433Swyllys 	STACK_OF(EVP_PKEY) *sslkeys,
43945b3e1433Swyllys 	STACK_OF(X509) *sslcert,
43955b3e1433Swyllys 	STACK_OF(X509) *sslcacerts,
439699ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
43975b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
439899ebb4caSwyllys {
439999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
440099ebb4caSwyllys 	KMF_RAW_KEY_DATA key;
440199ebb4caSwyllys 	int i;
440299ebb4caSwyllys 
44035b3e1433Swyllys 	for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
4404d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
44055b3e1433Swyllys 		EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
44065b3e1433Swyllys 		rv = convertToRawKey(pkey, &key);
440730a5e8faSwyllys 		if (rv == KMF_OK)
440899ebb4caSwyllys 			rv = add_key_to_list(keylist, &key, nkeys);
440930a5e8faSwyllys 
441099ebb4caSwyllys 		if (rv != KMF_OK)
441199ebb4caSwyllys 			return (rv);
441299ebb4caSwyllys 	}
441399ebb4caSwyllys 
441499ebb4caSwyllys 	/* Now add the certificate to the certlist */
44155b3e1433Swyllys 	for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
4416d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
44175b3e1433Swyllys 		X509 *cert = sk_X509_value(sslcert, i);
44185b3e1433Swyllys 		rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
441999ebb4caSwyllys 		if (rv != KMF_OK)
442099ebb4caSwyllys 			return (rv);
442199ebb4caSwyllys 	}
442299ebb4caSwyllys 
442399ebb4caSwyllys 	/* Also add any included CA certs to the list */
442471593db2Swyllys 	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
442599ebb4caSwyllys 		X509 *c;
442699ebb4caSwyllys 		/*
442799ebb4caSwyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
442899ebb4caSwyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
442999ebb4caSwyllys 		 * Lint is complaining about the embedded casting, and
443099ebb4caSwyllys 		 * to fix it, you need to fix openssl header files.
443199ebb4caSwyllys 		 */
4432d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
443399ebb4caSwyllys 		c = sk_X509_value(sslcacerts, i);
443499ebb4caSwyllys 
443599ebb4caSwyllys 		/* Now add the ca cert to the certlist */
443699ebb4caSwyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
443799ebb4caSwyllys 		if (rv != KMF_OK)
443899ebb4caSwyllys 			return (rv);
443999ebb4caSwyllys 	}
444099ebb4caSwyllys 	return (rv);
444199ebb4caSwyllys }
444299ebb4caSwyllys 
444399ebb4caSwyllys KMF_RETURN
444430a5e8faSwyllys openssl_import_objects(KMF_HANDLE *kmfh,
444599ebb4caSwyllys 	char *filename, KMF_CREDENTIAL *cred,
44465b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts,
444799ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
444899ebb4caSwyllys {
444999ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
445030a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
445130a5e8faSwyllys 	BIO		*bio = NULL;
44525b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*privkeys = NULL;
44535b3e1433Swyllys 	STACK_OF(X509)		*certs = NULL;
445499ebb4caSwyllys 	STACK_OF(X509)		*cacerts = NULL;
445599ebb4caSwyllys 
445630a5e8faSwyllys 	/*
445730a5e8faSwyllys 	 * auto-detect the file format, regardless of what
445830a5e8faSwyllys 	 * the 'format' parameters in the params say.
445930a5e8faSwyllys 	 */
446030a5e8faSwyllys 	rv = kmf_get_file_format(filename, &format);
446130a5e8faSwyllys 	if (rv != KMF_OK) {
446230a5e8faSwyllys 		return (rv);
446330a5e8faSwyllys 	}
446430a5e8faSwyllys 
446530a5e8faSwyllys 	/* This function only works for PEM or PKCS#12 files */
446630a5e8faSwyllys 	if (format != KMF_FORMAT_PEM &&
446730a5e8faSwyllys 	    format != KMF_FORMAT_PEM_KEYPAIR &&
446830a5e8faSwyllys 	    format != KMF_FORMAT_PKCS12)
446930a5e8faSwyllys 		return (KMF_ERR_ENCODING);
447030a5e8faSwyllys 
447130a5e8faSwyllys 	*certlist = NULL;
447230a5e8faSwyllys 	*keylist = NULL;
447330a5e8faSwyllys 	*ncerts = 0;
447430a5e8faSwyllys 	*nkeys = 0;
447530a5e8faSwyllys 
447630a5e8faSwyllys 	if (format == KMF_FORMAT_PKCS12) {
447799ebb4caSwyllys 		bio = BIO_new_file(filename, "rb");
447899ebb4caSwyllys 		if (bio == NULL) {
447999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
448099ebb4caSwyllys 			rv = KMF_ERR_OPEN_FILE;
448199ebb4caSwyllys 			goto end;
448299ebb4caSwyllys 		}
448399ebb4caSwyllys 
448434acef67Swyllys 		rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
44855b3e1433Swyllys 		    (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
448699ebb4caSwyllys 
448799ebb4caSwyllys 		if (rv  == KMF_OK)
448899ebb4caSwyllys 			/* Convert keys and certs to exportable format */
44895b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
449099ebb4caSwyllys 			    keylist, nkeys, certlist, ncerts);
449130a5e8faSwyllys 	} else {
44925b3e1433Swyllys 		EVP_PKEY *pkey;
44935b3e1433Swyllys 		KMF_DATA *certdata = NULL;
44945b3e1433Swyllys 		KMF_X509_DER_CERT *kmfcerts = NULL;
44955b3e1433Swyllys 		int i;
449630a5e8faSwyllys 		rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
449734acef67Swyllys 		    (uchar_t *)cred->cred, (uint32_t)cred->credlen,
44985b3e1433Swyllys 		    &pkey, &certdata, ncerts);
449971593db2Swyllys 
450071593db2Swyllys 		/* Reached end of import file? */
45015b3e1433Swyllys 		if (rv == KMF_OK && pkey != NULL) {
45025b3e1433Swyllys 			privkeys = sk_EVP_PKEY_new_null();
45035b3e1433Swyllys 			if (privkeys == NULL) {
45045b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
45055b3e1433Swyllys 				goto end;
45065b3e1433Swyllys 			}
45075b3e1433Swyllys 			(void) sk_EVP_PKEY_push(privkeys, pkey);
45085b3e1433Swyllys 			/* convert the certificate list here */
45095b3e1433Swyllys 			if (*ncerts > 0 && certlist != NULL) {
4510e65e5c2dSWyllys Ingersoll 				kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
45115b3e1433Swyllys 				    sizeof (KMF_X509_DER_CERT));
45125b3e1433Swyllys 				if (kmfcerts == NULL) {
45135b3e1433Swyllys 					rv = KMF_ERR_MEMORY;
45145b3e1433Swyllys 					goto end;
45155b3e1433Swyllys 				}
45165b3e1433Swyllys 				for (i = 0; i < *ncerts; i++) {
45175b3e1433Swyllys 					kmfcerts[i].certificate = certdata[i];
45185b3e1433Swyllys 					kmfcerts[i].kmf_private.keystore_type =
45195b3e1433Swyllys 					    KMF_KEYSTORE_OPENSSL;
45205b3e1433Swyllys 				}
45215b3e1433Swyllys 				*certlist = kmfcerts;
45225b3e1433Swyllys 			}
45235b3e1433Swyllys 			/*
45245b3e1433Swyllys 			 * Convert keys to exportable format, the certs
45255b3e1433Swyllys 			 * are already OK.
45265b3e1433Swyllys 			 */
45275b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
452871593db2Swyllys 			    keylist, nkeys, NULL, NULL);
452930a5e8faSwyllys 		}
45305b3e1433Swyllys 	}
453171593db2Swyllys end:
453230a5e8faSwyllys 	if (bio != NULL)
453399ebb4caSwyllys 		(void) BIO_free(bio);
453499ebb4caSwyllys 
45355b3e1433Swyllys 	if (privkeys)
45365b3e1433Swyllys 		sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
45375b3e1433Swyllys 	if (certs)
45385b3e1433Swyllys 		sk_X509_pop_free(certs, X509_free);
453930a5e8faSwyllys 	if (cacerts)
45405b3e1433Swyllys 		sk_X509_pop_free(cacerts, X509_free);
454130a5e8faSwyllys 
454299ebb4caSwyllys 	return (rv);
454399ebb4caSwyllys }
454499ebb4caSwyllys 
454599ebb4caSwyllys static KMF_RETURN
454699ebb4caSwyllys create_deskey(DES_cblock **deskey)
454799ebb4caSwyllys {
454899ebb4caSwyllys 	DES_cblock *key;
454999ebb4caSwyllys 
455099ebb4caSwyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
455199ebb4caSwyllys 	if (key == NULL) {
455299ebb4caSwyllys 		return (KMF_ERR_MEMORY);
455399ebb4caSwyllys 	}
455499ebb4caSwyllys 
455599ebb4caSwyllys 	if (DES_random_key(key) == 0) {
455699ebb4caSwyllys 		free(key);
455799ebb4caSwyllys 		return (KMF_ERR_KEYGEN_FAILED);
455899ebb4caSwyllys 	}
455999ebb4caSwyllys 
456099ebb4caSwyllys 	*deskey = key;
456199ebb4caSwyllys 	return (KMF_OK);
456299ebb4caSwyllys }
456399ebb4caSwyllys 
456499ebb4caSwyllys #define	KEYGEN_RETRY 3
456599ebb4caSwyllys #define	DES3_KEY_SIZE 24
456699ebb4caSwyllys 
456799ebb4caSwyllys static KMF_RETURN
456899ebb4caSwyllys create_des3key(unsigned char **des3key)
456999ebb4caSwyllys {
457099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
457199ebb4caSwyllys 	DES_cblock *deskey1 = NULL;
457299ebb4caSwyllys 	DES_cblock *deskey2 = NULL;
457399ebb4caSwyllys 	DES_cblock *deskey3 = NULL;
457499ebb4caSwyllys 	unsigned char *newkey = NULL;
457599ebb4caSwyllys 	int retry;
457699ebb4caSwyllys 
457799ebb4caSwyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
457899ebb4caSwyllys 		return (KMF_ERR_MEMORY);
457999ebb4caSwyllys 	}
458099ebb4caSwyllys 
458199ebb4caSwyllys 	/* create the 1st DES key */
458299ebb4caSwyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
458399ebb4caSwyllys 		goto out;
458499ebb4caSwyllys 	}
458599ebb4caSwyllys 
458699ebb4caSwyllys 	/*
458799ebb4caSwyllys 	 * Create the 2nd DES key and make sure its value is different
458899ebb4caSwyllys 	 * from the 1st DES key.
458999ebb4caSwyllys 	 */
459099ebb4caSwyllys 	retry = 0;
459199ebb4caSwyllys 	do {
459299ebb4caSwyllys 		if (deskey2 != NULL) {
459399ebb4caSwyllys 			free(deskey2);
459499ebb4caSwyllys 			deskey2 = NULL;
459599ebb4caSwyllys 		}
459699ebb4caSwyllys 
459799ebb4caSwyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
459899ebb4caSwyllys 			goto out;
459999ebb4caSwyllys 		}
460099ebb4caSwyllys 
460199ebb4caSwyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
460299ebb4caSwyllys 		    == 0) {
460399ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
460499ebb4caSwyllys 			retry++;
460599ebb4caSwyllys 		}
460699ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
460799ebb4caSwyllys 
460899ebb4caSwyllys 	if (ret != KMF_OK) {
460999ebb4caSwyllys 		goto out;
461099ebb4caSwyllys 	}
461199ebb4caSwyllys 
461299ebb4caSwyllys 	/*
461399ebb4caSwyllys 	 * Create the 3rd DES key and make sure its value is different
461499ebb4caSwyllys 	 * from the 2nd DES key.
461599ebb4caSwyllys 	 */
461699ebb4caSwyllys 	retry = 0;
461799ebb4caSwyllys 	do {
461899ebb4caSwyllys 		if (deskey3 != NULL) {
461999ebb4caSwyllys 			free(deskey3);
462099ebb4caSwyllys 			deskey3 = NULL;
462199ebb4caSwyllys 		}
462299ebb4caSwyllys 
462399ebb4caSwyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
462499ebb4caSwyllys 			goto out;
462599ebb4caSwyllys 		}
462699ebb4caSwyllys 
462799ebb4caSwyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
462899ebb4caSwyllys 		    == 0) {
462999ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
463099ebb4caSwyllys 			retry++;
463199ebb4caSwyllys 		}
463299ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
463399ebb4caSwyllys 
463499ebb4caSwyllys 	if (ret != KMF_OK) {
463599ebb4caSwyllys 		goto out;
463699ebb4caSwyllys 	}
463799ebb4caSwyllys 
463899ebb4caSwyllys 	/* Concatenate 3 DES keys into a DES3 key */
463999ebb4caSwyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
464099ebb4caSwyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
464199ebb4caSwyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
464299ebb4caSwyllys 	*des3key = newkey;
464399ebb4caSwyllys 
464499ebb4caSwyllys out:
464599ebb4caSwyllys 	if (deskey1 != NULL)
464699ebb4caSwyllys 		free(deskey1);
464799ebb4caSwyllys 
464899ebb4caSwyllys 	if (deskey2 != NULL)
464999ebb4caSwyllys 		free(deskey2);
465099ebb4caSwyllys 
465199ebb4caSwyllys 	if (deskey3 != NULL)
465299ebb4caSwyllys 		free(deskey3);
465399ebb4caSwyllys 
465499ebb4caSwyllys 	if (ret != KMF_OK && newkey != NULL)
465599ebb4caSwyllys 		free(newkey);
465699ebb4caSwyllys 
465799ebb4caSwyllys 	return (ret);
465899ebb4caSwyllys }
465999ebb4caSwyllys 
466099ebb4caSwyllys KMF_RETURN
466130a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
466230a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
466399ebb4caSwyllys {
466499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
466599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
466699ebb4caSwyllys 	char *fullpath = NULL;
466799ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
466899ebb4caSwyllys 	DES_cblock *deskey = NULL;
466999ebb4caSwyllys 	unsigned char *des3key = NULL;
467099ebb4caSwyllys 	unsigned char *random = NULL;
467199ebb4caSwyllys 	int fd = -1;
467230a5e8faSwyllys 	KMF_KEY_HANDLE *symkey;
467330a5e8faSwyllys 	KMF_KEY_ALG keytype;
467430a5e8faSwyllys 	uint32_t keylen;
467530a5e8faSwyllys 	uint32_t keylen_size = sizeof (keylen);
467630a5e8faSwyllys 	char *dirpath;
467730a5e8faSwyllys 	char *keyfile;
467899ebb4caSwyllys 
467999ebb4caSwyllys 	if (kmfh == NULL)
468099ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
468199ebb4caSwyllys 
468230a5e8faSwyllys 	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
468330a5e8faSwyllys 	if (symkey == NULL)
468499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
468599ebb4caSwyllys 
468630a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
468730a5e8faSwyllys 
468830a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
468930a5e8faSwyllys 	if (keyfile == NULL)
469030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
469130a5e8faSwyllys 
469230a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
469330a5e8faSwyllys 	    (void *)&keytype, NULL);
469430a5e8faSwyllys 	if (ret != KMF_OK)
469530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
469630a5e8faSwyllys 
469730a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
469830a5e8faSwyllys 	    &keylen, &keylen_size);
469930a5e8faSwyllys 	if (ret == KMF_ERR_ATTR_NOT_FOUND &&
470030a5e8faSwyllys 	    (keytype == KMF_DES || keytype == KMF_DES3))
470130a5e8faSwyllys 		/* keylength is not required for DES and 3DES */
470230a5e8faSwyllys 		ret = KMF_OK;
470330a5e8faSwyllys 	if (ret != KMF_OK)
470430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
470530a5e8faSwyllys 
470630a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
470799ebb4caSwyllys 	if (fullpath == NULL)
470899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
470999ebb4caSwyllys 
471099ebb4caSwyllys 	/* If the requested file exists, return an error */
471130a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
471299ebb4caSwyllys 		free(fullpath);
471399ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
471499ebb4caSwyllys 	}
471599ebb4caSwyllys 
471699ebb4caSwyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
471799ebb4caSwyllys 	if (fd == -1) {
471899ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
471999ebb4caSwyllys 		goto out;
472099ebb4caSwyllys 	}
472199ebb4caSwyllys 
472299ebb4caSwyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
472399ebb4caSwyllys 	if (rkey == NULL) {
472499ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
472599ebb4caSwyllys 		goto out;
472699ebb4caSwyllys 	}
472799ebb4caSwyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
472899ebb4caSwyllys 
472930a5e8faSwyllys 	if (keytype == KMF_DES) {
473099ebb4caSwyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
473199ebb4caSwyllys 			goto out;
473299ebb4caSwyllys 		}
473399ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)deskey;
473499ebb4caSwyllys 		rkey->keydata.len = 8;
473599ebb4caSwyllys 
473699ebb4caSwyllys 		symkey->keyalg = KMF_DES;
473799ebb4caSwyllys 
473830a5e8faSwyllys 	} else if (keytype == KMF_DES3) {
473999ebb4caSwyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
474099ebb4caSwyllys 			goto out;
474199ebb4caSwyllys 		}
474299ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)des3key;
474399ebb4caSwyllys 		rkey->keydata.len = DES3_KEY_SIZE;
474499ebb4caSwyllys 		symkey->keyalg = KMF_DES3;
47459b37d296Swyllys 
474630a5e8faSwyllys 	} else if (keytype == KMF_AES || keytype == KMF_RC4 ||
474730a5e8faSwyllys 	    keytype == KMF_GENERIC_SECRET) {
474899ebb4caSwyllys 		int bytes;
474999ebb4caSwyllys 
475030a5e8faSwyllys 		if (keylen % 8 != 0) {
475199ebb4caSwyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
475299ebb4caSwyllys 			goto out;
475399ebb4caSwyllys 		}
475499ebb4caSwyllys 
475530a5e8faSwyllys 		if (keytype == KMF_AES) {
475630a5e8faSwyllys 			if (keylen != 128 &&
475730a5e8faSwyllys 			    keylen != 192 &&
475830a5e8faSwyllys 			    keylen != 256) {
475999ebb4caSwyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
476099ebb4caSwyllys 				goto out;
476199ebb4caSwyllys 			}
476299ebb4caSwyllys 		}
476399ebb4caSwyllys 
476430a5e8faSwyllys 		bytes = keylen/8;
476599ebb4caSwyllys 		random = malloc(bytes);
476699ebb4caSwyllys 		if (random == NULL) {
476799ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
476899ebb4caSwyllys 			goto out;
476999ebb4caSwyllys 		}
477099ebb4caSwyllys 		if (RAND_bytes(random, bytes) != 1) {
477199ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
477299ebb4caSwyllys 			goto out;
477399ebb4caSwyllys 		}
477499ebb4caSwyllys 
477599ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)random;
477699ebb4caSwyllys 		rkey->keydata.len = bytes;
477730a5e8faSwyllys 		symkey->keyalg = keytype;
477899ebb4caSwyllys 
477999ebb4caSwyllys 	} else {
478099ebb4caSwyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
478199ebb4caSwyllys 		goto out;
478299ebb4caSwyllys 	}
478399ebb4caSwyllys 
478499ebb4caSwyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
478599ebb4caSwyllys 
478699ebb4caSwyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
478799ebb4caSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
478899ebb4caSwyllys 	symkey->keylabel = (char *)fullpath;
478999ebb4caSwyllys 	symkey->israw = TRUE;
479099ebb4caSwyllys 	symkey->keyp = rkey;
479199ebb4caSwyllys 
479299ebb4caSwyllys out:
479399ebb4caSwyllys 	if (fd != -1)
479499ebb4caSwyllys 		(void) close(fd);
479599ebb4caSwyllys 
479699ebb4caSwyllys 	if (ret != KMF_OK && fullpath != NULL) {
479799ebb4caSwyllys 		free(fullpath);
479899ebb4caSwyllys 	}
479999ebb4caSwyllys 	if (ret != KMF_OK) {
480030a5e8faSwyllys 		kmf_free_raw_sym_key(rkey);
480199ebb4caSwyllys 		symkey->keyp = NULL;
480299ebb4caSwyllys 		symkey->keyalg = KMF_KEYALG_NONE;
480399ebb4caSwyllys 	}
480499ebb4caSwyllys 
480599ebb4caSwyllys 	return (ret);
480699ebb4caSwyllys }
480799ebb4caSwyllys 
480899ebb4caSwyllys /*
480999ebb4caSwyllys  * Check a file to see if it is a CRL file with PEM or DER format.
481099ebb4caSwyllys  * If success, return its format in the "pformat" argument.
481199ebb4caSwyllys  */
481299ebb4caSwyllys KMF_RETURN
481399ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
481499ebb4caSwyllys {
481599ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
481699ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
481799ebb4caSwyllys 	BIO		*bio = NULL;
481899ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
481999ebb4caSwyllys 
482099ebb4caSwyllys 	if (filename == NULL) {
482199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
482299ebb4caSwyllys 	}
482399ebb4caSwyllys 
482499ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
482599ebb4caSwyllys 	if (bio == NULL)	{
482699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
482799ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
482899ebb4caSwyllys 		goto out;
482999ebb4caSwyllys 	}
483099ebb4caSwyllys 
483199ebb4caSwyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
483299ebb4caSwyllys 		*pformat = KMF_FORMAT_PEM;
483399ebb4caSwyllys 		goto out;
483499ebb4caSwyllys 	}
483599ebb4caSwyllys 	(void) BIO_free(bio);
483699ebb4caSwyllys 
483799ebb4caSwyllys 	/*
483899ebb4caSwyllys 	 * Now try to read it as raw DER data.
483999ebb4caSwyllys 	 */
484099ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
484199ebb4caSwyllys 	if (bio == NULL)	{
484299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
484399ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
484499ebb4caSwyllys 		goto out;
484599ebb4caSwyllys 	}
484699ebb4caSwyllys 
484799ebb4caSwyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
484899ebb4caSwyllys 		*pformat = KMF_FORMAT_ASN1;
484999ebb4caSwyllys 	} else {
485099ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
485199ebb4caSwyllys 	}
485299ebb4caSwyllys 
485399ebb4caSwyllys out:
485499ebb4caSwyllys 	if (bio != NULL)
485599ebb4caSwyllys 		(void) BIO_free(bio);
485699ebb4caSwyllys 
485799ebb4caSwyllys 	if (xcrl != NULL)
485899ebb4caSwyllys 		X509_CRL_free(xcrl);
485999ebb4caSwyllys 
486099ebb4caSwyllys 	return (ret);
486199ebb4caSwyllys }
486299ebb4caSwyllys 
486399ebb4caSwyllys KMF_RETURN
486499ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
486599ebb4caSwyllys     KMF_RAW_SYM_KEY *rkey)
486699ebb4caSwyllys {
486799ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
486899ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
486999ebb4caSwyllys 	KMF_DATA	keyvalue;
487099ebb4caSwyllys 
487199ebb4caSwyllys 	if (kmfh == NULL)
487299ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
487399ebb4caSwyllys 
487499ebb4caSwyllys 	if (symkey == NULL || rkey == NULL)
487599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
487699ebb4caSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
487799ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
487899ebb4caSwyllys 
487999ebb4caSwyllys 	if (symkey->israw) {
488099ebb4caSwyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
488199ebb4caSwyllys 
488299ebb4caSwyllys 		if (rawkey == NULL ||
488399ebb4caSwyllys 		    rawkey->keydata.val == NULL ||
488499ebb4caSwyllys 		    rawkey->keydata.len == 0)
488599ebb4caSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
488699ebb4caSwyllys 
488799ebb4caSwyllys 		rkey->keydata.len = rawkey->keydata.len;
488899ebb4caSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
488999ebb4caSwyllys 			return (KMF_ERR_MEMORY);
489099ebb4caSwyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
489199ebb4caSwyllys 		    rkey->keydata.len);
489299ebb4caSwyllys 	} else {
489330a5e8faSwyllys 		rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
489499ebb4caSwyllys 		if (rv != KMF_OK)
489599ebb4caSwyllys 			return (rv);
489699ebb4caSwyllys 		rkey->keydata.len = keyvalue.Length;
489799ebb4caSwyllys 		rkey->keydata.val = keyvalue.Data;
489899ebb4caSwyllys 	}
489999ebb4caSwyllys 
490099ebb4caSwyllys 	return (rv);
490199ebb4caSwyllys }
490202744e81Swyllys 
490302744e81Swyllys /*
490430a5e8faSwyllys  * substitute for the unsafe access(2) function.
490530a5e8faSwyllys  * If the file in question already exists, return 1.
490630a5e8faSwyllys  * else 0.  If an error occurs during testing (other
490730a5e8faSwyllys  * than EEXIST), return -1.
490830a5e8faSwyllys  */
490930a5e8faSwyllys static int
491030a5e8faSwyllys test_for_file(char *filename, mode_t mode)
491130a5e8faSwyllys {
491230a5e8faSwyllys 	int fd;
491330a5e8faSwyllys 
491430a5e8faSwyllys 	/*
491530a5e8faSwyllys 	 * Try to create the file with the EXCL flag.
491630a5e8faSwyllys 	 * The call should fail if the file exists.
491730a5e8faSwyllys 	 */
491830a5e8faSwyllys 	fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
491930a5e8faSwyllys 	if (fd == -1 && errno == EEXIST)
492030a5e8faSwyllys 		return (1);
492130a5e8faSwyllys 	else if (fd == -1) /* some other error */
492230a5e8faSwyllys 		return (-1);
492330a5e8faSwyllys 
492430a5e8faSwyllys 	/* The file did NOT exist.  Delete the testcase. */
492530a5e8faSwyllys 	(void) close(fd);
492630a5e8faSwyllys 	(void) unlink(filename);
492730a5e8faSwyllys 	return (0);
492830a5e8faSwyllys }
492930a5e8faSwyllys 
493030a5e8faSwyllys KMF_RETURN
493130a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
493230a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
493330a5e8faSwyllys {
493430a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
493530a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
493630a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
493730a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
493830a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
493930a5e8faSwyllys 	KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
494030a5e8faSwyllys 	KMF_CREDENTIAL cred = { NULL, 0 };
494130a5e8faSwyllys 	BIO *out = NULL;
494230a5e8faSwyllys 	int keys = 0;
494330a5e8faSwyllys 	char *fullpath = NULL;
494430a5e8faSwyllys 	char *keyfile = NULL;
494530a5e8faSwyllys 	char *dirpath = NULL;
494630a5e8faSwyllys 
494730a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
494830a5e8faSwyllys 	if (pubkey != NULL)
494930a5e8faSwyllys 		keys++;
495030a5e8faSwyllys 
495130a5e8faSwyllys 	prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
495230a5e8faSwyllys 	if (prikey != NULL)
495330a5e8faSwyllys 		keys++;
495430a5e8faSwyllys 
495530a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
495630a5e8faSwyllys 	if (rawkey != NULL)
495730a5e8faSwyllys 		keys++;
495830a5e8faSwyllys 
495930a5e8faSwyllys 	/*
496030a5e8faSwyllys 	 * Exactly 1 type of key must be passed to this function.
496130a5e8faSwyllys 	 */
496230a5e8faSwyllys 	if (keys != 1)
496330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
496430a5e8faSwyllys 
496530a5e8faSwyllys 	keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
496630a5e8faSwyllys 	    numattr);
496730a5e8faSwyllys 	if (keyfile == NULL)
496830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
496930a5e8faSwyllys 
497030a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
497130a5e8faSwyllys 
497230a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
497330a5e8faSwyllys 
497430a5e8faSwyllys 	/* Once we have the full path, we don't need the pieces */
497530a5e8faSwyllys 	if (fullpath == NULL)
497630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
497730a5e8faSwyllys 
497830a5e8faSwyllys 	/* If the requested file exists, return an error */
497930a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
498030a5e8faSwyllys 		free(fullpath);
498130a5e8faSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
498230a5e8faSwyllys 	}
498330a5e8faSwyllys 
498430a5e8faSwyllys 	rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
498530a5e8faSwyllys 	    &format, NULL);
498630a5e8faSwyllys 	if (rv != KMF_OK)
498730a5e8faSwyllys 		/* format is optional. */
498830a5e8faSwyllys 		rv = KMF_OK;
498930a5e8faSwyllys 
499030a5e8faSwyllys 	/* CRED is not required for OpenSSL files */
499130a5e8faSwyllys 	(void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
499230a5e8faSwyllys 	    &cred, NULL);
499330a5e8faSwyllys 
499430a5e8faSwyllys 	/* Store the private key to the keyfile */
499530a5e8faSwyllys 	out = BIO_new_file(fullpath, "wb");
499630a5e8faSwyllys 	if (out == NULL) {
499730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
499830a5e8faSwyllys 		rv = KMF_ERR_OPEN_FILE;
499930a5e8faSwyllys 		goto end;
500030a5e8faSwyllys 	}
500130a5e8faSwyllys 
500230a5e8faSwyllys 	if (prikey != NULL && prikey->keyp != NULL) {
500330a5e8faSwyllys 		if (prikey->keyalg == KMF_RSA ||
500430a5e8faSwyllys 		    prikey->keyalg == KMF_DSA) {
500530a5e8faSwyllys 			pkey = (EVP_PKEY *)prikey->keyp;
500630a5e8faSwyllys 
500730a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
500830a5e8faSwyllys 			    out, &cred, pkey, TRUE);
500930a5e8faSwyllys 
501030a5e8faSwyllys 			if (rv == KMF_OK && prikey->keylabel == NULL) {
501130a5e8faSwyllys 				prikey->keylabel = strdup(fullpath);
501230a5e8faSwyllys 				if (prikey->keylabel == NULL)
501330a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
501430a5e8faSwyllys 			}
501530a5e8faSwyllys 		}
501630a5e8faSwyllys 	} else if (pubkey != NULL && pubkey->keyp != NULL) {
501730a5e8faSwyllys 		if (pubkey->keyalg == KMF_RSA ||
501830a5e8faSwyllys 		    pubkey->keyalg == KMF_DSA) {
501930a5e8faSwyllys 			pkey = (EVP_PKEY *)pubkey->keyp;
502030a5e8faSwyllys 
502130a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
502230a5e8faSwyllys 			    out, &cred, pkey, FALSE);
502330a5e8faSwyllys 
502430a5e8faSwyllys 			if (rv == KMF_OK && pubkey->keylabel == NULL) {
502530a5e8faSwyllys 				pubkey->keylabel = strdup(fullpath);
502630a5e8faSwyllys 				if (pubkey->keylabel == NULL)
502730a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
502830a5e8faSwyllys 			}
502930a5e8faSwyllys 		}
503030a5e8faSwyllys 	} else if (rawkey != NULL) {
503130a5e8faSwyllys 		if (rawkey->keytype == KMF_RSA) {
503230a5e8faSwyllys 			pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
503330a5e8faSwyllys 		} else if (rawkey->keytype == KMF_DSA) {
503430a5e8faSwyllys 			pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
503530a5e8faSwyllys 		} else {
503630a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
503730a5e8faSwyllys 		}
50385b3e1433Swyllys 		if (pkey != NULL) {
503973cc0e02Swyllys 			KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
504073cc0e02Swyllys 
504173cc0e02Swyllys 			rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
504273cc0e02Swyllys 			    (void *)&kclass, NULL);
504373cc0e02Swyllys 			if (rv != KMF_OK)
504473cc0e02Swyllys 				rv = KMF_OK;
50455b3e1433Swyllys 			rv = ssl_write_key(kmfh, format, out,
504673cc0e02Swyllys 			    &cred, pkey, (kclass == KMF_ASYM_PRI));
50475b3e1433Swyllys 			EVP_PKEY_free(pkey);
50485b3e1433Swyllys 		}
504930a5e8faSwyllys 	}
505030a5e8faSwyllys 
505130a5e8faSwyllys end:
505230a5e8faSwyllys 
505330a5e8faSwyllys 	if (out)
505430a5e8faSwyllys 		(void) BIO_free(out);
505530a5e8faSwyllys 
50565b3e1433Swyllys 
505730a5e8faSwyllys 	if (rv == KMF_OK)
505830a5e8faSwyllys 		(void) chmod(fullpath, 0400);
505930a5e8faSwyllys 
506030a5e8faSwyllys 	free(fullpath);
506130a5e8faSwyllys 	return (rv);
506230a5e8faSwyllys }
506330a5e8faSwyllys 
506430a5e8faSwyllys KMF_RETURN
506530a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
506630a5e8faSwyllys {
506730a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
506830a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
506930a5e8faSwyllys 	X509_CRL *xcrl = NULL;
507030a5e8faSwyllys 	X509 *xcert = NULL;
507130a5e8faSwyllys 	EVP_PKEY *pkey;
507230a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
507330a5e8faSwyllys 	BIO *in = NULL, *out = NULL;
507430a5e8faSwyllys 	int openssl_ret = 0;
507530a5e8faSwyllys 	KMF_ENCODE_FORMAT outformat;
507630a5e8faSwyllys 	boolean_t crlcheck = FALSE;
507730a5e8faSwyllys 	char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
507830a5e8faSwyllys 
507930a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
508030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
508130a5e8faSwyllys 	}
508230a5e8faSwyllys 
508330a5e8faSwyllys 	/* CRL check is optional */
508430a5e8faSwyllys 	(void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
508530a5e8faSwyllys 	    &crlcheck, NULL);
508630a5e8faSwyllys 
508730a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
508830a5e8faSwyllys 	if (crlcheck == B_TRUE && certfile == NULL) {
508930a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
509030a5e8faSwyllys 	}
509130a5e8faSwyllys 
509230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
509330a5e8faSwyllys 	incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
509430a5e8faSwyllys 	outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
509530a5e8faSwyllys 
509630a5e8faSwyllys 	crlfile = get_fullpath(dirpath, incrl);
509730a5e8faSwyllys 
509830a5e8faSwyllys 	if (crlfile == NULL)
509930a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
510030a5e8faSwyllys 
510130a5e8faSwyllys 	outcrlfile = get_fullpath(dirpath, outcrl);
510230a5e8faSwyllys 	if (outcrlfile == NULL)
510330a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
510430a5e8faSwyllys 
510530a5e8faSwyllys 	if (isdir(outcrlfile)) {
510630a5e8faSwyllys 		free(outcrlfile);
510730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
510830a5e8faSwyllys 	}
510930a5e8faSwyllys 
511030a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
511130a5e8faSwyllys 	if (ret != KMF_OK) {
511230a5e8faSwyllys 		free(outcrlfile);
511330a5e8faSwyllys 		return (ret);
511430a5e8faSwyllys 	}
511530a5e8faSwyllys 
511630a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
511730a5e8faSwyllys 	if (in == NULL)	{
511830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
511930a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
512030a5e8faSwyllys 		goto end;
512130a5e8faSwyllys 	}
512230a5e8faSwyllys 
512330a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
512430a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
512530a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
512630a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
512730a5e8faSwyllys 	}
512830a5e8faSwyllys 
512930a5e8faSwyllys 	if (xcrl == NULL) {
513030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
513130a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
513230a5e8faSwyllys 		goto end;
513330a5e8faSwyllys 	}
513430a5e8faSwyllys 
513530a5e8faSwyllys 	/* If bypasscheck is specified, no need to verify. */
513630a5e8faSwyllys 	if (crlcheck == B_FALSE)
513730a5e8faSwyllys 		goto output;
513830a5e8faSwyllys 
513930a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
514030a5e8faSwyllys 	if (ret != KMF_OK)
514130a5e8faSwyllys 		goto end;
514230a5e8faSwyllys 
514330a5e8faSwyllys 	/* Read in the CA cert file and convert to X509 */
514430a5e8faSwyllys 	if (BIO_read_filename(in, certfile) <= 0) {
514530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
514630a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
514730a5e8faSwyllys 		goto end;
514830a5e8faSwyllys 	}
514930a5e8faSwyllys 
515030a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
515130a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
515230a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
515330a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
515430a5e8faSwyllys 	} else {
515530a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
515630a5e8faSwyllys 		goto end;
515730a5e8faSwyllys 	}
515830a5e8faSwyllys 
515930a5e8faSwyllys 	if (xcert == NULL) {
516030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
516130a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
516230a5e8faSwyllys 		goto end;
516330a5e8faSwyllys 	}
516430a5e8faSwyllys 	/* Now get the public key from the CA cert */
516530a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
516630a5e8faSwyllys 	if (pkey == NULL) {
516730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
516830a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
516930a5e8faSwyllys 		goto end;
517030a5e8faSwyllys 	}
517130a5e8faSwyllys 
517230a5e8faSwyllys 	/* Verify the CRL with the CA's public key */
517330a5e8faSwyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
517430a5e8faSwyllys 	EVP_PKEY_free(pkey);
517530a5e8faSwyllys 	if (openssl_ret > 0) {
517630a5e8faSwyllys 		ret = KMF_OK;  /* verify succeed */
517730a5e8faSwyllys 	} else {
517830a5e8faSwyllys 		SET_ERROR(kmfh, openssl_ret);
517930a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
518030a5e8faSwyllys 	}
518130a5e8faSwyllys 
518230a5e8faSwyllys output:
518330a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
518430a5e8faSwyllys 	    &outformat, NULL);
518530a5e8faSwyllys 	if (ret != KMF_OK) {
518630a5e8faSwyllys 		ret = KMF_OK;
518730a5e8faSwyllys 		outformat = KMF_FORMAT_PEM;
518830a5e8faSwyllys 	}
518930a5e8faSwyllys 
519030a5e8faSwyllys 	out = BIO_new_file(outcrlfile, "wb");
519130a5e8faSwyllys 	if (out == NULL) {
519230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
519330a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
519430a5e8faSwyllys 		goto end;
519530a5e8faSwyllys 	}
519630a5e8faSwyllys 
519730a5e8faSwyllys 	if (outformat == KMF_FORMAT_ASN1) {
519830a5e8faSwyllys 		openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
519930a5e8faSwyllys 	} else if (outformat == KMF_FORMAT_PEM) {
520030a5e8faSwyllys 		openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
520130a5e8faSwyllys 	} else {
520230a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
520330a5e8faSwyllys 		goto end;
520430a5e8faSwyllys 	}
520530a5e8faSwyllys 
520630a5e8faSwyllys 	if (openssl_ret <= 0) {
520730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
520830a5e8faSwyllys 		ret = KMF_ERR_WRITE_FILE;
520930a5e8faSwyllys 	} else {
521030a5e8faSwyllys 		ret = KMF_OK;
521130a5e8faSwyllys 	}
521230a5e8faSwyllys 
521330a5e8faSwyllys end:
521430a5e8faSwyllys 	if (xcrl != NULL)
521530a5e8faSwyllys 		X509_CRL_free(xcrl);
521630a5e8faSwyllys 
521730a5e8faSwyllys 	if (xcert != NULL)
521830a5e8faSwyllys 		X509_free(xcert);
521930a5e8faSwyllys 
522030a5e8faSwyllys 	if (in != NULL)
522130a5e8faSwyllys 		(void) BIO_free(in);
522230a5e8faSwyllys 
522330a5e8faSwyllys 	if (out != NULL)
522430a5e8faSwyllys 		(void) BIO_free(out);
522530a5e8faSwyllys 
522630a5e8faSwyllys 	if (outcrlfile != NULL)
522730a5e8faSwyllys 		free(outcrlfile);
522830a5e8faSwyllys 
522930a5e8faSwyllys 	return (ret);
523030a5e8faSwyllys }
523130a5e8faSwyllys 
523230a5e8faSwyllys KMF_RETURN
523330a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
523430a5e8faSwyllys {
523530a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
523630a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
523730a5e8faSwyllys 	X509_CRL   *x = NULL;
523830a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
523930a5e8faSwyllys 	char *crlfile = NULL;
524030a5e8faSwyllys 	BIO *in = NULL;
524130a5e8faSwyllys 	BIO *mem = NULL;
524230a5e8faSwyllys 	long len;
524330a5e8faSwyllys 	char *memptr;
524430a5e8faSwyllys 	char *data = NULL;
524530a5e8faSwyllys 	char **crldata;
524630a5e8faSwyllys 	char *crlfilename, *dirpath;
524730a5e8faSwyllys 
524830a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
524930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
525030a5e8faSwyllys 	}
525130a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
525230a5e8faSwyllys 	    attrlist, numattr);
525330a5e8faSwyllys 	if (crlfilename == NULL)
525430a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
525530a5e8faSwyllys 
525630a5e8faSwyllys 	crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
525730a5e8faSwyllys 	    attrlist, numattr);
525830a5e8faSwyllys 
525930a5e8faSwyllys 	if (crldata == NULL)
526030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
526130a5e8faSwyllys 
526230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
526330a5e8faSwyllys 
526430a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
526530a5e8faSwyllys 
526630a5e8faSwyllys 	if (crlfile == NULL)
526730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
526830a5e8faSwyllys 
526930a5e8faSwyllys 	if (isdir(crlfile)) {
527030a5e8faSwyllys 		free(crlfile);
527130a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
527230a5e8faSwyllys 	}
527330a5e8faSwyllys 
527430a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
527530a5e8faSwyllys 	if (ret != KMF_OK) {
527630a5e8faSwyllys 		free(crlfile);
527730a5e8faSwyllys 		return (ret);
527830a5e8faSwyllys 	}
527930a5e8faSwyllys 
528030a5e8faSwyllys 	if (bio_err == NULL)
528130a5e8faSwyllys 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
528230a5e8faSwyllys 
528330a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
528430a5e8faSwyllys 	if (in == NULL)	{
528530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
528630a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
528730a5e8faSwyllys 		goto end;
528830a5e8faSwyllys 	}
528930a5e8faSwyllys 
529030a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
529130a5e8faSwyllys 		x = d2i_X509_CRL_bio(in, NULL);
529230a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
529330a5e8faSwyllys 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
529430a5e8faSwyllys 	}
529530a5e8faSwyllys 
529630a5e8faSwyllys 	if (x == NULL) { /* should not happen */
529730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
529830a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
529930a5e8faSwyllys 		goto end;
530030a5e8faSwyllys 	}
530130a5e8faSwyllys 
530230a5e8faSwyllys 	mem = BIO_new(BIO_s_mem());
530330a5e8faSwyllys 	if (mem == NULL) {
530430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
530530a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
530630a5e8faSwyllys 		goto end;
530730a5e8faSwyllys 	}
530830a5e8faSwyllys 
530930a5e8faSwyllys 	(void) X509_CRL_print(mem, x);
531030a5e8faSwyllys 	len = BIO_get_mem_data(mem, &memptr);
531130a5e8faSwyllys 	if (len <= 0) {
531230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
531330a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
531430a5e8faSwyllys 		goto end;
531530a5e8faSwyllys 	}
531630a5e8faSwyllys 
531730a5e8faSwyllys 	data = malloc(len + 1);
531830a5e8faSwyllys 	if (data == NULL) {
531930a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
532030a5e8faSwyllys 		goto end;
532130a5e8faSwyllys 	}
532230a5e8faSwyllys 
532330a5e8faSwyllys 	(void) memcpy(data, memptr, len);
532430a5e8faSwyllys 	data[len] = '\0';
532530a5e8faSwyllys 	*crldata = data;
532630a5e8faSwyllys 
532730a5e8faSwyllys end:
532830a5e8faSwyllys 	if (x != NULL)
532930a5e8faSwyllys 		X509_CRL_free(x);
533030a5e8faSwyllys 
533130a5e8faSwyllys 	if (crlfile != NULL)
533230a5e8faSwyllys 		free(crlfile);
533330a5e8faSwyllys 
533430a5e8faSwyllys 	if (in != NULL)
533530a5e8faSwyllys 		(void) BIO_free(in);
533630a5e8faSwyllys 
533730a5e8faSwyllys 	if (mem != NULL)
533830a5e8faSwyllys 		(void) BIO_free(mem);
533930a5e8faSwyllys 
534030a5e8faSwyllys 	return (ret);
534130a5e8faSwyllys }
534230a5e8faSwyllys 
534330a5e8faSwyllys KMF_RETURN
534430a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
534530a5e8faSwyllys {
534630a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
534730a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
534830a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
534930a5e8faSwyllys 	char *crlfile = NULL;
535030a5e8faSwyllys 	BIO *in = NULL;
535130a5e8faSwyllys 	char *crlfilename, *dirpath;
535230a5e8faSwyllys 
535330a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
535430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
535530a5e8faSwyllys 	}
535630a5e8faSwyllys 
535730a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
535830a5e8faSwyllys 	    attrlist, numattr);
535930a5e8faSwyllys 
536030a5e8faSwyllys 	if (crlfilename == NULL)
536130a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
536230a5e8faSwyllys 
536330a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
536430a5e8faSwyllys 
536530a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
536630a5e8faSwyllys 
536730a5e8faSwyllys 	if (crlfile == NULL)
536830a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
536930a5e8faSwyllys 
537030a5e8faSwyllys 	if (isdir(crlfile)) {
537130a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
537230a5e8faSwyllys 		goto end;
537330a5e8faSwyllys 	}
537430a5e8faSwyllys 
537530a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
537630a5e8faSwyllys 	if (ret != KMF_OK)
537730a5e8faSwyllys 		goto end;
537830a5e8faSwyllys 
537930a5e8faSwyllys 	if (unlink(crlfile) != 0) {
538030a5e8faSwyllys 		SET_SYS_ERROR(kmfh, errno);
538130a5e8faSwyllys 		ret = KMF_ERR_INTERNAL;
538230a5e8faSwyllys 		goto end;
538330a5e8faSwyllys 	}
538430a5e8faSwyllys 
538530a5e8faSwyllys end:
538630a5e8faSwyllys 	if (in != NULL)
538730a5e8faSwyllys 		(void) BIO_free(in);
538830a5e8faSwyllys 	if (crlfile != NULL)
538930a5e8faSwyllys 		free(crlfile);
539030a5e8faSwyllys 
539130a5e8faSwyllys 	return (ret);
539230a5e8faSwyllys }
539330a5e8faSwyllys 
539430a5e8faSwyllys KMF_RETURN
539530a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
539630a5e8faSwyllys {
539730a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
539830a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
539930a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
540030a5e8faSwyllys 	BIO *in = NULL;
540130a5e8faSwyllys 	X509   *xcert = NULL;
540230a5e8faSwyllys 	X509_CRL   *xcrl = NULL;
540330a5e8faSwyllys 	STACK_OF(X509_REVOKED) *revoke_stack = NULL;
540430a5e8faSwyllys 	X509_REVOKED *revoke;
540530a5e8faSwyllys 	int i;
540630a5e8faSwyllys 	char *crlfilename, *crlfile, *dirpath, *certfile;
540730a5e8faSwyllys 
540830a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
540930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
541030a5e8faSwyllys 	}
541130a5e8faSwyllys 
541230a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
541330a5e8faSwyllys 	    attrlist, numattr);
541430a5e8faSwyllys 
541530a5e8faSwyllys 	if (crlfilename == NULL)
541630a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
541730a5e8faSwyllys 
541830a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
541930a5e8faSwyllys 	if (certfile == NULL)
542030a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
542130a5e8faSwyllys 
542230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
542330a5e8faSwyllys 
542430a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
542530a5e8faSwyllys 
542630a5e8faSwyllys 	if (crlfile == NULL)
542730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
542830a5e8faSwyllys 
542930a5e8faSwyllys 	if (isdir(crlfile)) {
543030a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
543130a5e8faSwyllys 		goto end;
543230a5e8faSwyllys 	}
543330a5e8faSwyllys 
543430a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
543530a5e8faSwyllys 	if (ret != KMF_OK)
543630a5e8faSwyllys 		goto end;
543730a5e8faSwyllys 
543830a5e8faSwyllys 	/* Read the CRL file and load it into a X509_CRL structure */
543930a5e8faSwyllys 	in = BIO_new_file(crlfilename, "rb");
544030a5e8faSwyllys 	if (in == NULL)	{
544130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
544230a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
544330a5e8faSwyllys 		goto end;
544430a5e8faSwyllys 	}
544530a5e8faSwyllys 
544630a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
544730a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
544830a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
544930a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
545030a5e8faSwyllys 	}
545130a5e8faSwyllys 
545230a5e8faSwyllys 	if (xcrl == NULL) {
545330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
545430a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
545530a5e8faSwyllys 		goto end;
545630a5e8faSwyllys 	}
545730a5e8faSwyllys 	(void) BIO_free(in);
545830a5e8faSwyllys 
545930a5e8faSwyllys 	/* Read the Certificate file and load it into a X509 structure */
546030a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
546130a5e8faSwyllys 	if (ret != KMF_OK)
546230a5e8faSwyllys 		goto end;
546330a5e8faSwyllys 
546430a5e8faSwyllys 	in = BIO_new_file(certfile, "rb");
546530a5e8faSwyllys 	if (in == NULL)	{
546630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
546730a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
546830a5e8faSwyllys 		goto end;
546930a5e8faSwyllys 	}
547030a5e8faSwyllys 
547130a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
547230a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
547330a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
547430a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
547530a5e8faSwyllys 	}
547630a5e8faSwyllys 
547730a5e8faSwyllys 	if (xcert == NULL) {
547830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
547930a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
548030a5e8faSwyllys 		goto end;
548130a5e8faSwyllys 	}
548230a5e8faSwyllys 
548330a5e8faSwyllys 	/* Check if the certificate and the CRL have same issuer */
5484300fdee2SAndy Fiddaman 	if (X509_NAME_cmp(X509_get_issuer_name(xcert),
5485300fdee2SAndy Fiddaman 	    X509_CRL_get_issuer(xcrl)) != 0) {
548630a5e8faSwyllys 		ret = KMF_ERR_ISSUER;
548730a5e8faSwyllys 		goto end;
548830a5e8faSwyllys 	}
548930a5e8faSwyllys 
549030a5e8faSwyllys 	/* Check to see if the certificate serial number is revoked */
549130a5e8faSwyllys 	revoke_stack = X509_CRL_get_REVOKED(xcrl);
549230a5e8faSwyllys 	if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
549330a5e8faSwyllys 		/* No revoked certificates in the CRL file */
549430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
549530a5e8faSwyllys 		ret = KMF_ERR_EMPTY_CRL;
549630a5e8faSwyllys 		goto end;
549730a5e8faSwyllys 	}
549830a5e8faSwyllys 
549930a5e8faSwyllys 	for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
5500d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
550130a5e8faSwyllys 		revoke = sk_X509_REVOKED_value(revoke_stack, i);
5502300fdee2SAndy Fiddaman 		if (ASN1_INTEGER_cmp(X509_get_serialNumber(xcert),
5503300fdee2SAndy Fiddaman 		    X509_REVOKED_get0_serialNumber(revoke)) == 0) {
550430a5e8faSwyllys 			break;
550530a5e8faSwyllys 		}
550630a5e8faSwyllys 	}
550730a5e8faSwyllys 
550830a5e8faSwyllys 	if (i < sk_X509_REVOKED_num(revoke_stack)) {
550930a5e8faSwyllys 		ret = KMF_OK;
551030a5e8faSwyllys 	} else {
551130a5e8faSwyllys 		ret = KMF_ERR_NOT_REVOKED;
551230a5e8faSwyllys 	}
551330a5e8faSwyllys 
551430a5e8faSwyllys end:
551530a5e8faSwyllys 	if (in != NULL)
551630a5e8faSwyllys 		(void) BIO_free(in);
551730a5e8faSwyllys 	if (xcrl != NULL)
551830a5e8faSwyllys 		X509_CRL_free(xcrl);
551930a5e8faSwyllys 	if (xcert != NULL)
552030a5e8faSwyllys 		X509_free(xcert);
552130a5e8faSwyllys 
552230a5e8faSwyllys 	return (ret);
552330a5e8faSwyllys }
552430a5e8faSwyllys 
552530a5e8faSwyllys KMF_RETURN
552630a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
552730a5e8faSwyllys {
552830a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
552930a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
553030a5e8faSwyllys 	BIO		*bcrl = NULL;
553130a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
553230a5e8faSwyllys 	X509		*xcert = NULL;
553330a5e8faSwyllys 	EVP_PKEY	*pkey;
553430a5e8faSwyllys 	int		sslret;
553530a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
553630a5e8faSwyllys 	unsigned char	*p;
553730a5e8faSwyllys 	long		len;
553830a5e8faSwyllys 
553930a5e8faSwyllys 	if (handle == NULL || crlname == NULL || tacert == NULL) {
554030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
554130a5e8faSwyllys 	}
554230a5e8faSwyllys 
554330a5e8faSwyllys 	ret = kmf_get_file_format(crlname, &crl_format);
554430a5e8faSwyllys 	if (ret != KMF_OK)
554530a5e8faSwyllys 		return (ret);
554630a5e8faSwyllys 
554730a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
554830a5e8faSwyllys 	if (bcrl == NULL)	{
554930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
555030a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
555130a5e8faSwyllys 		goto cleanup;
555230a5e8faSwyllys 	}
555330a5e8faSwyllys 
555430a5e8faSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
555530a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
555630a5e8faSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
555730a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
555830a5e8faSwyllys 	} else {
555930a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
556030a5e8faSwyllys 		goto cleanup;
556130a5e8faSwyllys 	}
556230a5e8faSwyllys 
556330a5e8faSwyllys 	if (xcrl == NULL) {
556430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
556530a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
556630a5e8faSwyllys 		goto cleanup;
556730a5e8faSwyllys 	}
556830a5e8faSwyllys 
556930a5e8faSwyllys 	p = tacert->Data;
557030a5e8faSwyllys 	len = tacert->Length;
557130a5e8faSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
557230a5e8faSwyllys 
557330a5e8faSwyllys 	if (xcert == NULL) {
557430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
557530a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
557630a5e8faSwyllys 		goto cleanup;
557730a5e8faSwyllys 	}
557830a5e8faSwyllys 
557930a5e8faSwyllys 	/* Get issuer certificate public key */
558030a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
558130a5e8faSwyllys 	if (pkey == NULL) {
558230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
558330a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
558430a5e8faSwyllys 		goto cleanup;
558530a5e8faSwyllys 	}
558630a5e8faSwyllys 
558730a5e8faSwyllys 	/* Verify CRL signature */
558830a5e8faSwyllys 	sslret = X509_CRL_verify(xcrl, pkey);
558930a5e8faSwyllys 	EVP_PKEY_free(pkey);
559030a5e8faSwyllys 	if (sslret > 0) {
559130a5e8faSwyllys 		ret = KMF_OK;
559230a5e8faSwyllys 	} else {
559330a5e8faSwyllys 		SET_ERROR(kmfh, sslret);
559430a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
559530a5e8faSwyllys 	}
559630a5e8faSwyllys 
559730a5e8faSwyllys cleanup:
559830a5e8faSwyllys 	if (bcrl != NULL)
559930a5e8faSwyllys 		(void) BIO_free(bcrl);
560030a5e8faSwyllys 
560130a5e8faSwyllys 	if (xcrl != NULL)
560230a5e8faSwyllys 		X509_CRL_free(xcrl);
560330a5e8faSwyllys 
560430a5e8faSwyllys 	if (xcert != NULL)
560530a5e8faSwyllys 		X509_free(xcert);
560630a5e8faSwyllys 
560730a5e8faSwyllys 	return (ret);
560830a5e8faSwyllys 
560930a5e8faSwyllys }
561030a5e8faSwyllys 
561130a5e8faSwyllys KMF_RETURN
561230a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
561330a5e8faSwyllys {
561430a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
561530a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
561630a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
561730a5e8faSwyllys 	BIO		*bcrl = NULL;
561830a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
561930a5e8faSwyllys 	int		i;
562030a5e8faSwyllys 
562130a5e8faSwyllys 	if (handle == NULL || crlname == NULL) {
562230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
562330a5e8faSwyllys 	}
562430a5e8faSwyllys 
562530a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlname, &crl_format);
562630a5e8faSwyllys 	if (ret != KMF_OK)
562730a5e8faSwyllys 		return (ret);
562830a5e8faSwyllys 
562930a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
563030a5e8faSwyllys 	if (bcrl == NULL) {
563130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
563230a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
563330a5e8faSwyllys 		goto cleanup;
563430a5e8faSwyllys 	}
563530a5e8faSwyllys 
56365b3e1433Swyllys 	if (crl_format == KMF_FORMAT_ASN1)
563730a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
56385b3e1433Swyllys 	else if (crl_format == KMF_FORMAT_PEM)
563930a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
564030a5e8faSwyllys 
564130a5e8faSwyllys 	if (xcrl == NULL) {
564230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
564330a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
564430a5e8faSwyllys 		goto cleanup;
564530a5e8faSwyllys 	}
5646300fdee2SAndy Fiddaman 	i = X509_cmp_time(X509_CRL_get0_lastUpdate(xcrl), NULL);
564730a5e8faSwyllys 	if (i >= 0) {
564830a5e8faSwyllys 		ret = KMF_ERR_VALIDITY_PERIOD;
564930a5e8faSwyllys 		goto cleanup;
565030a5e8faSwyllys 	}
5651300fdee2SAndy Fiddaman 	if (X509_CRL_get0_nextUpdate(xcrl)) {
5652300fdee2SAndy Fiddaman 		i = X509_cmp_time(X509_CRL_get0_nextUpdate(xcrl), NULL);
565330a5e8faSwyllys 
565430a5e8faSwyllys 		if (i <= 0) {
565530a5e8faSwyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
565630a5e8faSwyllys 			goto cleanup;
565730a5e8faSwyllys 		}
565830a5e8faSwyllys 	}
565930a5e8faSwyllys 
566030a5e8faSwyllys 	ret = KMF_OK;
566130a5e8faSwyllys 
566230a5e8faSwyllys cleanup:
566330a5e8faSwyllys 	if (bcrl != NULL)
566430a5e8faSwyllys 		(void) BIO_free(bcrl);
566530a5e8faSwyllys 
566630a5e8faSwyllys 	if (xcrl != NULL)
566730a5e8faSwyllys 		X509_CRL_free(xcrl);
566830a5e8faSwyllys 
566930a5e8faSwyllys 	return (ret);
567030a5e8faSwyllys }
5671