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.
9553e44ceSAndrew 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  */
142553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
1435b3e1433Swyllys DECLARE_STACK_OF(EVP_PKEY)
1445b3e1433Swyllys 
1455b3e1433Swyllys #define	sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
1465b3e1433Swyllys #define	sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
1475b3e1433Swyllys #define	sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
1485b3e1433Swyllys #define	sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
1495b3e1433Swyllys #define	sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
1505b3e1433Swyllys #define	sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
1515b3e1433Swyllys 	(free_func))
1525b3e1433Swyllys 
153300fdee2SAndy Fiddaman #else
154300fdee2SAndy Fiddaman /* 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 
304553e44ceSAndrew 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 }
325553e44ceSAndrew Stormont #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER */
32699ebb4caSwyllys 
32799ebb4caSwyllys KMF_PLUGIN_FUNCLIST *
32899ebb4caSwyllys KMF_Plugin_Initialize()
32999ebb4caSwyllys {
330553e44ceSAndrew 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 
351553e44ceSAndrew 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:
1036*a50e8766SToomas Soome 	if (pkey == NULL) {
103799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1038*a50e8766SToomas Soome 	}
103999ebb4caSwyllys 
104099ebb4caSwyllys 	if (keyfile != NULL)
104199ebb4caSwyllys 		(void) BIO_free(keyfile);
104299ebb4caSwyllys 
104399ebb4caSwyllys 	return (pkey);
104499ebb4caSwyllys }
104599ebb4caSwyllys 
104699ebb4caSwyllys KMF_RETURN
104730a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
104899ebb4caSwyllys {
104999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
105099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1051f482c776Swyllys 	int i, n;
1052f482c776Swyllys 	uint32_t maxcerts = 0;
105330a5e8faSwyllys 	uint32_t *num_certs;
105430a5e8faSwyllys 	KMF_X509_DER_CERT *kmf_cert = NULL;
105530a5e8faSwyllys 	char *dirpath = NULL;
105630a5e8faSwyllys 	char *filename = NULL;
105730a5e8faSwyllys 	char *fullpath = NULL;
105830a5e8faSwyllys 	char *issuer = NULL;
105930a5e8faSwyllys 	char *subject = NULL;
106030a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
106130a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
106299ebb4caSwyllys 
106330a5e8faSwyllys 	num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
106430a5e8faSwyllys 	if (num_certs == NULL)
106599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
106699ebb4caSwyllys 
106730a5e8faSwyllys 	/* num_certs should reference the size of kmf_cert */
1068f482c776Swyllys 	maxcerts = *num_certs;
1069f482c776Swyllys 	if (maxcerts == 0)
1070f482c776Swyllys 		maxcerts = 0xFFFFFFFF;
107199ebb4caSwyllys 	*num_certs = 0;
107299ebb4caSwyllys 
107330a5e8faSwyllys 	/* Get the optional returned certificate list  */
107430a5e8faSwyllys 	kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
107530a5e8faSwyllys 	    numattr);
107699ebb4caSwyllys 
107730a5e8faSwyllys 	/*
107830a5e8faSwyllys 	 * The dirpath attribute and the filename attribute can not be NULL
107930a5e8faSwyllys 	 * at the same time.
108030a5e8faSwyllys 	 */
108130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
108230a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
108330a5e8faSwyllys 	    numattr);
108430a5e8faSwyllys 
108530a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
108699ebb4caSwyllys 	if (fullpath == NULL)
108799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
108899ebb4caSwyllys 
108930a5e8faSwyllys 	/* Get optional search criteria attributes */
109030a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
109130a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
109230a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
109330a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
109430a5e8faSwyllys 	    &validity, NULL);
109530a5e8faSwyllys 	if (rv != KMF_OK) {
109630a5e8faSwyllys 		validity = KMF_ALL_CERTS;
109730a5e8faSwyllys 		rv = KMF_OK;
109830a5e8faSwyllys 	}
109930a5e8faSwyllys 
110099ebb4caSwyllys 	if (isdir(fullpath)) {
110199ebb4caSwyllys 		DIR *dirp;
110299ebb4caSwyllys 		struct dirent *dp;
110399ebb4caSwyllys 
1104f482c776Swyllys 		n = 0;
110599ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
110699ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
110799ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
110899ebb4caSwyllys 		}
110999ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
111099ebb4caSwyllys 			char *fname;
111171593db2Swyllys 			KMF_DATA *certlist = NULL;
1112f482c776Swyllys 			uint32_t loaded_certs = 0;
111371593db2Swyllys 
111499ebb4caSwyllys 			if (strcmp(dp->d_name, ".") == 0 ||
111599ebb4caSwyllys 			    strcmp(dp->d_name, "..") == 0)
111699ebb4caSwyllys 				continue;
111799ebb4caSwyllys 
111834acef67Swyllys 			fname = get_fullpath(fullpath, (char *)&dp->d_name);
111999ebb4caSwyllys 
112030a5e8faSwyllys 			rv = load_certs(kmfh, issuer, subject, serial,
112130a5e8faSwyllys 			    validity, fname, &certlist,	&loaded_certs);
112299ebb4caSwyllys 
112399ebb4caSwyllys 			if (rv != KMF_OK) {
112499ebb4caSwyllys 				free(fname);
112571593db2Swyllys 				if (certlist != NULL) {
1126f482c776Swyllys 					for (i = 0; i < loaded_certs; i++)
112730a5e8faSwyllys 						kmf_free_data(&certlist[i]);
112871593db2Swyllys 					free(certlist);
112971593db2Swyllys 				}
113099ebb4caSwyllys 				continue;
113199ebb4caSwyllys 			}
113299ebb4caSwyllys 
113399ebb4caSwyllys 			/* If load succeeds, add certdata to the list */
113499ebb4caSwyllys 			if (kmf_cert != NULL) {
1135f482c776Swyllys 				for (i = 0; i < loaded_certs &&
1136b4058258Swyllys 				    n < maxcerts; i++) {
113771593db2Swyllys 					kmf_cert[n].certificate.Data =
113871593db2Swyllys 					    certlist[i].Data;
113999ebb4caSwyllys 					kmf_cert[n].certificate.Length =
114071593db2Swyllys 					    certlist[i].Length;
114199ebb4caSwyllys 
114299ebb4caSwyllys 					kmf_cert[n].kmf_private.keystore_type =
114399ebb4caSwyllys 					    KMF_KEYSTORE_OPENSSL;
114499ebb4caSwyllys 					kmf_cert[n].kmf_private.flags =
114599ebb4caSwyllys 					    KMF_FLAG_CERT_VALID;
114671593db2Swyllys 					kmf_cert[n].kmf_private.label =
114771593db2Swyllys 					    strdup(fname);
114899ebb4caSwyllys 					n++;
114999ebb4caSwyllys 				}
1150b4058258Swyllys 				/*
1151b4058258Swyllys 				 * If maxcerts < loaded_certs, clean up the
1152b4058258Swyllys 				 * certs that were not used.
1153b4058258Swyllys 				 */
1154f482c776Swyllys 				for (; i < loaded_certs; i++)
115530a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1156f482c776Swyllys 			} else {
1157f482c776Swyllys 				for (i = 0; i < loaded_certs; i++)
115830a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1159f482c776Swyllys 				n += loaded_certs;
116071593db2Swyllys 			}
1161f482c776Swyllys 			free(certlist);
116271593db2Swyllys 			free(fname);
116371593db2Swyllys 		}
116499ebb4caSwyllys 		(*num_certs) = n;
116599ebb4caSwyllys 		if (*num_certs == 0)
116699ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
116730a5e8faSwyllys 		if (*num_certs > 0)
116899ebb4caSwyllys 			rv = KMF_OK;
116999ebb4caSwyllys exit:
117099ebb4caSwyllys 		(void) closedir(dirp);
117199ebb4caSwyllys 	} else {
117271593db2Swyllys 		KMF_DATA *certlist = NULL;
1173f482c776Swyllys 		uint32_t loaded_certs = 0;
117471593db2Swyllys 
117530a5e8faSwyllys 		rv = load_certs(kmfh, issuer, subject, serial, validity,
117630a5e8faSwyllys 		    fullpath, &certlist, &loaded_certs);
117799ebb4caSwyllys 		if (rv != KMF_OK) {
117899ebb4caSwyllys 			free(fullpath);
117999ebb4caSwyllys 			return (rv);
118099ebb4caSwyllys 		}
118199ebb4caSwyllys 
1182f482c776Swyllys 		n = 0;
118371593db2Swyllys 		if (kmf_cert != NULL && certlist != NULL) {
1184f482c776Swyllys 			for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1185f482c776Swyllys 				kmf_cert[n].certificate.Data =
118671593db2Swyllys 				    certlist[i].Data;
1187f482c776Swyllys 				kmf_cert[n].certificate.Length =
118871593db2Swyllys 				    certlist[i].Length;
1189f482c776Swyllys 				kmf_cert[n].kmf_private.keystore_type =
119099ebb4caSwyllys 				    KMF_KEYSTORE_OPENSSL;
1191f482c776Swyllys 				kmf_cert[n].kmf_private.flags =
119271593db2Swyllys 				    KMF_FLAG_CERT_VALID;
1193f482c776Swyllys 				kmf_cert[n].kmf_private.label =
119471593db2Swyllys 				    strdup(fullpath);
1195f482c776Swyllys 				n++;
119671593db2Swyllys 			}
1197f482c776Swyllys 			/* If maxcerts < loaded_certs, clean up */
1198f482c776Swyllys 			for (; i < loaded_certs; i++)
119930a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1200f482c776Swyllys 		} else if (certlist != NULL) {
1201f482c776Swyllys 			for (i = 0; i < loaded_certs; i++)
120230a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1203f482c776Swyllys 			n = loaded_certs;
1204f482c776Swyllys 		}
120530a5e8faSwyllys 		if (certlist != NULL)
120671593db2Swyllys 			free(certlist);
1207f482c776Swyllys 		*num_certs = n;
120899ebb4caSwyllys 	}
120999ebb4caSwyllys 
121099ebb4caSwyllys 	free(fullpath);
121199ebb4caSwyllys 
121299ebb4caSwyllys 	return (rv);
121399ebb4caSwyllys }
121499ebb4caSwyllys 
121599ebb4caSwyllys void
121699ebb4caSwyllys /*ARGSUSED*/
121799ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
121899ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert)
121999ebb4caSwyllys {
122099ebb4caSwyllys 	if (kmf_cert != NULL) {
122199ebb4caSwyllys 		if (kmf_cert->certificate.Data != NULL) {
1222e65e5c2dSWyllys Ingersoll 			kmf_free_data(&kmf_cert->certificate);
122399ebb4caSwyllys 		}
122499ebb4caSwyllys 		if (kmf_cert->kmf_private.label)
122599ebb4caSwyllys 			free(kmf_cert->kmf_private.label);
122699ebb4caSwyllys 	}
122799ebb4caSwyllys }
122899ebb4caSwyllys 
122930a5e8faSwyllys /*ARGSUSED*/
123099ebb4caSwyllys KMF_RETURN
123130a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
123299ebb4caSwyllys {
123399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
123430a5e8faSwyllys 	KMF_DATA *cert = NULL;
123530a5e8faSwyllys 	char *outfilename = NULL;
123630a5e8faSwyllys 	char *dirpath = NULL;
123730a5e8faSwyllys 	char *fullpath = NULL;
123899ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
123999ebb4caSwyllys 
124030a5e8faSwyllys 	/* Get the cert data */
124130a5e8faSwyllys 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
124230a5e8faSwyllys 	if (cert == NULL || cert->Data == NULL)
124399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
124499ebb4caSwyllys 
124530a5e8faSwyllys 	/* Check the output filename and directory attributes. */
124630a5e8faSwyllys 	outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
124730a5e8faSwyllys 	    numattr);
124830a5e8faSwyllys 	if (outfilename == NULL)
124930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
125099ebb4caSwyllys 
125130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
125230a5e8faSwyllys 	fullpath = get_fullpath(dirpath, outfilename);
125399ebb4caSwyllys 	if (fullpath == NULL)
125430a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
125599ebb4caSwyllys 
125630a5e8faSwyllys 	/* Check the optional format attribute */
125730a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
125830a5e8faSwyllys 	    &format, NULL);
125930a5e8faSwyllys 	if (ret != KMF_OK) {
126030a5e8faSwyllys 		/* If there is no format attribute, then default to PEM */
126130a5e8faSwyllys 		format = KMF_FORMAT_PEM;
126299ebb4caSwyllys 		ret = KMF_OK;
126330a5e8faSwyllys 	} else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
126430a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
126599ebb4caSwyllys 		goto out;
126699ebb4caSwyllys 	}
126799ebb4caSwyllys 
126830a5e8faSwyllys 	/* Store the certificate in the file with the specified format */
126930a5e8faSwyllys 	ret = kmf_create_cert_file(cert, format, fullpath);
127099ebb4caSwyllys 
127199ebb4caSwyllys out:
127299ebb4caSwyllys 	if (fullpath != NULL)
127399ebb4caSwyllys 		free(fullpath);
127499ebb4caSwyllys 
127599ebb4caSwyllys 	return (ret);
127699ebb4caSwyllys }
127799ebb4caSwyllys 
127830a5e8faSwyllys 
127999ebb4caSwyllys KMF_RETURN
128030a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
128199ebb4caSwyllys {
128299ebb4caSwyllys 	KMF_RETURN rv;
128399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
12846b35cb3cSRichard PALO 	KMF_DATA certdata = { 0, NULL };
128530a5e8faSwyllys 	char *dirpath = NULL;
128630a5e8faSwyllys 	char *filename = NULL;
128730a5e8faSwyllys 	char *fullpath = NULL;
128830a5e8faSwyllys 	char *issuer = NULL;
128930a5e8faSwyllys 	char *subject = NULL;
129030a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
129130a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
129299ebb4caSwyllys 
129330a5e8faSwyllys 	/*
129430a5e8faSwyllys 	 * Get the DIRPATH and CERT_FILENAME attributes.  They can not be
129530a5e8faSwyllys 	 * NULL at the same time.
129630a5e8faSwyllys 	 */
129730a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
129830a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
129930a5e8faSwyllys 	    numattr);
130030a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
130199ebb4caSwyllys 	if (fullpath == NULL)
130299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
130399ebb4caSwyllys 
130430a5e8faSwyllys 	/* Get optional search criteria attributes */
130530a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
130630a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
130730a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
130830a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
130930a5e8faSwyllys 	    &validity, NULL);
131030a5e8faSwyllys 	if (rv != KMF_OK) {
131130a5e8faSwyllys 		validity = KMF_ALL_CERTS;
131230a5e8faSwyllys 		rv = KMF_OK;
131330a5e8faSwyllys 	}
131430a5e8faSwyllys 
131599ebb4caSwyllys 	if (isdir(fullpath)) {
131699ebb4caSwyllys 		DIR *dirp;
131799ebb4caSwyllys 		struct dirent *dp;
131899ebb4caSwyllys 
131999ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
132099ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
132199ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
132299ebb4caSwyllys 		}
132399ebb4caSwyllys 
132499ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
132599ebb4caSwyllys 			if (strcmp(dp->d_name, ".") != 0 &&
132699ebb4caSwyllys 			    strcmp(dp->d_name, "..") != 0) {
132799ebb4caSwyllys 				char *fname;
132899ebb4caSwyllys 
132999ebb4caSwyllys 				fname = get_fullpath(fullpath,
133099ebb4caSwyllys 				    (char *)&dp->d_name);
133199ebb4caSwyllys 
133299ebb4caSwyllys 				if (fname == NULL) {
133399ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
133499ebb4caSwyllys 					break;
133599ebb4caSwyllys 				}
133699ebb4caSwyllys 
133730a5e8faSwyllys 				rv = kmf_load_cert(kmfh, issuer, subject,
133830a5e8faSwyllys 				    serial, validity, fname, &certdata);
133999ebb4caSwyllys 
134099ebb4caSwyllys 				if (rv == KMF_ERR_CERT_NOT_FOUND) {
134199ebb4caSwyllys 					free(fname);
1342e65e5c2dSWyllys Ingersoll 					kmf_free_data(&certdata);
134399ebb4caSwyllys 					rv = KMF_OK;
134499ebb4caSwyllys 					continue;
134599ebb4caSwyllys 				} else if (rv != KMF_OK) {
134699ebb4caSwyllys 					free(fname);
134799ebb4caSwyllys 					break;
134899ebb4caSwyllys 				}
134999ebb4caSwyllys 
135099ebb4caSwyllys 				if (unlink(fname) != 0) {
135199ebb4caSwyllys 					SET_SYS_ERROR(kmfh, errno);
135299ebb4caSwyllys 					rv = KMF_ERR_INTERNAL;
135399ebb4caSwyllys 					free(fname);
135499ebb4caSwyllys 					break;
135599ebb4caSwyllys 				}
135699ebb4caSwyllys 				free(fname);
1357e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certdata);
135899ebb4caSwyllys 			}
135999ebb4caSwyllys 		}
136099ebb4caSwyllys 		(void) closedir(dirp);
136199ebb4caSwyllys 	} else {
136299ebb4caSwyllys 		/* Just try to load a single certificate */
136330a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
136430a5e8faSwyllys 		    fullpath, &certdata);
136599ebb4caSwyllys 		if (rv == KMF_OK) {
136699ebb4caSwyllys 			if (unlink(fullpath) != 0) {
136799ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
136899ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
136999ebb4caSwyllys 			}
137099ebb4caSwyllys 		}
137199ebb4caSwyllys 	}
137299ebb4caSwyllys 
137399ebb4caSwyllys out:
137499ebb4caSwyllys 	if (fullpath != NULL)
137599ebb4caSwyllys 		free(fullpath);
137699ebb4caSwyllys 
1377e65e5c2dSWyllys Ingersoll 	kmf_free_data(&certdata);
137899ebb4caSwyllys 
137999ebb4caSwyllys 	return (rv);
138099ebb4caSwyllys }
138199ebb4caSwyllys 
138299ebb4caSwyllys KMF_RETURN
138399ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
138499ebb4caSwyllys 	KMF_DATA *keydata)
138599ebb4caSwyllys {
138699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
138799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
138899ebb4caSwyllys 	int n;
138999ebb4caSwyllys 
139099ebb4caSwyllys 	if (key == NULL || keydata == NULL ||
139199ebb4caSwyllys 	    key->keyp == NULL)
139299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
139399ebb4caSwyllys 
139499ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
139599ebb4caSwyllys 		RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
139699ebb4caSwyllys 
139799ebb4caSwyllys 		if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
139899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
139999ebb4caSwyllys 			return (KMF_ERR_ENCODING);
140099ebb4caSwyllys 		}
140199ebb4caSwyllys 		RSA_free(pubkey);
140299ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
140399ebb4caSwyllys 		DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
140499ebb4caSwyllys 
140599ebb4caSwyllys 		if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
140699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
140799ebb4caSwyllys 			return (KMF_ERR_ENCODING);
140899ebb4caSwyllys 		}
140999ebb4caSwyllys 		DSA_free(pubkey);
141099ebb4caSwyllys 	} else {
141199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
141299ebb4caSwyllys 	}
141399ebb4caSwyllys 	keydata->Length = n;
141499ebb4caSwyllys 
141599ebb4caSwyllys cleanup:
141699ebb4caSwyllys 	if (rv != KMF_OK) {
141799ebb4caSwyllys 		if (keydata->Data)
141899ebb4caSwyllys 			free(keydata->Data);
141999ebb4caSwyllys 		keydata->Data = NULL;
142099ebb4caSwyllys 		keydata->Length = 0;
142199ebb4caSwyllys 	}
142299ebb4caSwyllys 
142399ebb4caSwyllys 	return (rv);
142499ebb4caSwyllys }
142599ebb4caSwyllys 
142699ebb4caSwyllys static KMF_RETURN
142730a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
142830a5e8faSwyllys 	KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
142999ebb4caSwyllys {
143099ebb4caSwyllys 	int rv = 0;
143199ebb4caSwyllys 	RSA *rsa;
143299ebb4caSwyllys 	DSA *dsa;
143399ebb4caSwyllys 
14345b3e1433Swyllys 	if (pkey == NULL || out == NULL)
14355b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
14365b3e1433Swyllys 
143799ebb4caSwyllys 	switch (format) {
143873cc0e02Swyllys 		case KMF_FORMAT_RAWKEY:
143973cc0e02Swyllys 			/* same as ASN.1 */
144099ebb4caSwyllys 		case KMF_FORMAT_ASN1:
1441300fdee2SAndy Fiddaman 			if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
144230a5e8faSwyllys 				if (private)
144399ebb4caSwyllys 					rv = i2d_RSAPrivateKey_bio(out, rsa);
144430a5e8faSwyllys 				else
144530a5e8faSwyllys 					rv = i2d_RSAPublicKey_bio(out, rsa);
1446300fdee2SAndy Fiddaman 			} else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
144799ebb4caSwyllys 				rv = i2d_DSAPrivateKey_bio(out, dsa);
144899ebb4caSwyllys 			}
144999ebb4caSwyllys 			if (rv == 1) {
145099ebb4caSwyllys 				rv = KMF_OK;
145199ebb4caSwyllys 			} else {
145299ebb4caSwyllys 				SET_ERROR(kmfh, rv);
145399ebb4caSwyllys 			}
145499ebb4caSwyllys 			break;
145599ebb4caSwyllys 		case KMF_FORMAT_PEM:
1456300fdee2SAndy Fiddaman 			if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
145730a5e8faSwyllys 				if (private)
145899ebb4caSwyllys 					rv = PEM_write_bio_RSAPrivateKey(out,
145930a5e8faSwyllys 					    rsa, NULL, NULL, 0, NULL,
146030a5e8faSwyllys 					    (cred != NULL ? cred->cred : NULL));
146130a5e8faSwyllys 				else
146230a5e8faSwyllys 					rv = PEM_write_bio_RSAPublicKey(out,
146330a5e8faSwyllys 					    rsa);
1464300fdee2SAndy Fiddaman 			} else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
146599ebb4caSwyllys 				rv = PEM_write_bio_DSAPrivateKey(out,
146630a5e8faSwyllys 				    dsa, NULL, NULL, 0, NULL,
146730a5e8faSwyllys 				    (cred != NULL ? cred->cred : NULL));
146899ebb4caSwyllys 			}
146999ebb4caSwyllys 
147099ebb4caSwyllys 			if (rv == 1) {
147199ebb4caSwyllys 				rv = KMF_OK;
147299ebb4caSwyllys 			} else {
147399ebb4caSwyllys 				SET_ERROR(kmfh, rv);
147499ebb4caSwyllys 			}
147599ebb4caSwyllys 			break;
147699ebb4caSwyllys 
147799ebb4caSwyllys 		default:
147899ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
147999ebb4caSwyllys 	}
148099ebb4caSwyllys 
148199ebb4caSwyllys 	return (rv);
148299ebb4caSwyllys }
148399ebb4caSwyllys 
148499ebb4caSwyllys KMF_RETURN
148530a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
148630a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
148799ebb4caSwyllys {
148899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
148999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1490300fdee2SAndy Fiddaman 	uint32_t eValue = RSA_F4;
1491300fdee2SAndy Fiddaman 	BIGNUM *eValue_bn = NULL;
149299ebb4caSwyllys 	RSA *sslPrivKey = NULL;
149399ebb4caSwyllys 	DSA *sslDSAKey = NULL;
149499ebb4caSwyllys 	EVP_PKEY *eprikey = NULL;
149599ebb4caSwyllys 	EVP_PKEY *epubkey = NULL;
149699ebb4caSwyllys 	BIO *out = NULL;
149730a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
149830a5e8faSwyllys 	uint32_t keylen = 1024;
149930a5e8faSwyllys 	uint32_t keylen_size = sizeof (uint32_t);
150030a5e8faSwyllys 	boolean_t storekey = TRUE;
150130a5e8faSwyllys 	KMF_KEY_ALG keytype = KMF_RSA;
150299ebb4caSwyllys 
1503300fdee2SAndy Fiddaman 	eValue_bn = BN_new();
1504300fdee2SAndy Fiddaman 	if (eValue_bn == NULL)
1505300fdee2SAndy Fiddaman 		return (KMF_ERR_MEMORY);
1506300fdee2SAndy Fiddaman 	if (BN_set_word(eValue_bn, eValue) == 0) {
1507300fdee2SAndy Fiddaman 		rv = KMF_ERR_KEYGEN_FAILED;
1508300fdee2SAndy Fiddaman 		goto cleanup;
1509300fdee2SAndy Fiddaman 	}
1510300fdee2SAndy Fiddaman 
151130a5e8faSwyllys 	rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
151230a5e8faSwyllys 	    &storekey, NULL);
151330a5e8faSwyllys 	if (rv != KMF_OK) {
151430a5e8faSwyllys 		/* "storekey" is optional. Default is TRUE */
151530a5e8faSwyllys 		rv = KMF_OK;
151699ebb4caSwyllys 	}
151799ebb4caSwyllys 
151830a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
151930a5e8faSwyllys 	    (void *)&keytype, NULL);
152030a5e8faSwyllys 	if (rv != KMF_OK)
152130a5e8faSwyllys 		/* keytype is optional.  KMF_RSA is default */
152230a5e8faSwyllys 		rv = KMF_OK;
152399ebb4caSwyllys 
152430a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
1525300fdee2SAndy Fiddaman 	if (pubkey == NULL) {
1526300fdee2SAndy Fiddaman 		rv = KMF_ERR_BAD_PARAMETER;
1527300fdee2SAndy Fiddaman 		goto cleanup;
1528300fdee2SAndy Fiddaman 	}
152999ebb4caSwyllys 
153030a5e8faSwyllys 	privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
1531300fdee2SAndy Fiddaman 	if (privkey == NULL) {
1532300fdee2SAndy Fiddaman 		rv = KMF_ERR_BAD_PARAMETER;
1533300fdee2SAndy Fiddaman 		goto cleanup;
1534300fdee2SAndy Fiddaman 	}
153530a5e8faSwyllys 
153630a5e8faSwyllys 	(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
153730a5e8faSwyllys 	(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
153899ebb4caSwyllys 
153999ebb4caSwyllys 	eprikey = EVP_PKEY_new();
154099ebb4caSwyllys 	if (eprikey == NULL) {
154199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
154299ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
154399ebb4caSwyllys 		goto cleanup;
154499ebb4caSwyllys 	}
154599ebb4caSwyllys 	epubkey = EVP_PKEY_new();
154699ebb4caSwyllys 	if (epubkey == NULL) {
154799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
154899ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
154999ebb4caSwyllys 		goto cleanup;
155099ebb4caSwyllys 	}
155130a5e8faSwyllys 	if (keytype == KMF_RSA) {
155230a5e8faSwyllys 		KMF_BIGINT *rsaexp = NULL;
155399ebb4caSwyllys 
155430a5e8faSwyllys 		rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
155530a5e8faSwyllys 		if (rsaexp != NULL) {
155630a5e8faSwyllys 			if (rsaexp->len > 0 &&
155730a5e8faSwyllys 			    rsaexp->len <= sizeof (eValue) &&
155830a5e8faSwyllys 			    rsaexp->val != NULL) {
1559a2d4930dSDan OpenSolaris Anderson 				/* LINTED E_BAD_PTR_CAST_ALIGN */
156030a5e8faSwyllys 				eValue = *(uint32_t *)rsaexp->val;
1561300fdee2SAndy Fiddaman 				if (BN_set_word(eValue_bn, eValue) == 0) {
1562300fdee2SAndy Fiddaman 					rv = KMF_ERR_BAD_PARAMETER;
1563300fdee2SAndy Fiddaman 					goto cleanup;
1564300fdee2SAndy Fiddaman 				}
156530a5e8faSwyllys 			} else {
156630a5e8faSwyllys 				rv = KMF_ERR_BAD_PARAMETER;
156730a5e8faSwyllys 				goto cleanup;
156830a5e8faSwyllys 			}
156930a5e8faSwyllys 		} else {
157030a5e8faSwyllys 			/* RSA Exponent is optional. Default is 0x10001 */
157130a5e8faSwyllys 			rv = KMF_OK;
157230a5e8faSwyllys 		}
157330a5e8faSwyllys 
157430a5e8faSwyllys 		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
157530a5e8faSwyllys 		    &keylen, &keylen_size);
157630a5e8faSwyllys 		if (rv == KMF_ERR_ATTR_NOT_FOUND)
157730a5e8faSwyllys 			/* keylen is optional, default is 1024 */
157830a5e8faSwyllys 			rv = KMF_OK;
157930a5e8faSwyllys 		if (rv != KMF_OK) {
158030a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
158130a5e8faSwyllys 			goto cleanup;
158230a5e8faSwyllys 		}
158330a5e8faSwyllys 
1584300fdee2SAndy Fiddaman 		sslPrivKey = RSA_new();
1585300fdee2SAndy Fiddaman 		if (sslPrivKey == NULL ||
1586300fdee2SAndy Fiddaman 		    RSA_generate_key_ex(sslPrivKey, keylen, eValue_bn, NULL)
1587300fdee2SAndy Fiddaman 		    == 0) {
158899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
158999ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
159099ebb4caSwyllys 		} else {
159130a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
159299ebb4caSwyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
159399ebb4caSwyllys 			privkey->keyalg = KMF_RSA;
159499ebb4caSwyllys 			privkey->keyclass = KMF_ASYM_PRI;
159599ebb4caSwyllys 			privkey->israw = FALSE;
159699ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
159730a5e8faSwyllys 
159899ebb4caSwyllys 			/* OpenSSL derives the public key from the private */
159930a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
160099ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
160199ebb4caSwyllys 			pubkey->keyalg = KMF_RSA;
160299ebb4caSwyllys 			pubkey->israw = FALSE;
160399ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
160499ebb4caSwyllys 			pubkey->keyp = (void *)epubkey;
160599ebb4caSwyllys 		}
160630a5e8faSwyllys 	} else if (keytype == KMF_DSA) {
1607300fdee2SAndy Fiddaman 		BIGNUM *p, *q, *g;
1608300fdee2SAndy Fiddaman 
160999ebb4caSwyllys 		sslDSAKey = DSA_new();
161099ebb4caSwyllys 		if (sslDSAKey == NULL) {
161199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
161299ebb4caSwyllys 			return (KMF_ERR_MEMORY);
161399ebb4caSwyllys 		}
161499ebb4caSwyllys 
1615300fdee2SAndy Fiddaman 		p = BN_bin2bn(P, sizeof (P), NULL);
1616300fdee2SAndy Fiddaman 		q = BN_bin2bn(Q, sizeof (Q), NULL);
1617300fdee2SAndy Fiddaman 		g = BN_bin2bn(G, sizeof (G), NULL);
1618300fdee2SAndy Fiddaman 		if (p == NULL || q == NULL || g == NULL) {
1619300fdee2SAndy Fiddaman 			BN_free(p);
1620300fdee2SAndy Fiddaman 			BN_free(q);
1621300fdee2SAndy Fiddaman 			BN_free(g);
162299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
162399ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
162499ebb4caSwyllys 			goto cleanup;
162599ebb4caSwyllys 		}
1626300fdee2SAndy Fiddaman 
1627300fdee2SAndy Fiddaman 		if (DSA_set0_pqg(sslDSAKey, p, q, g) == 0) {
162899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
162999ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
163099ebb4caSwyllys 			goto cleanup;
163199ebb4caSwyllys 		}
163299ebb4caSwyllys 
163399ebb4caSwyllys 		if (!DSA_generate_key(sslDSAKey)) {
163499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
163599ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
163699ebb4caSwyllys 			goto cleanup;
163799ebb4caSwyllys 		}
163899ebb4caSwyllys 
163999ebb4caSwyllys 		privkey->kstype = KMF_KEYSTORE_OPENSSL;
164099ebb4caSwyllys 		privkey->keyalg = KMF_DSA;
164199ebb4caSwyllys 		privkey->keyclass = KMF_ASYM_PRI;
164299ebb4caSwyllys 		privkey->israw = FALSE;
164399ebb4caSwyllys 		if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
164499ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
164599ebb4caSwyllys 		} else {
164699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
164799ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
164899ebb4caSwyllys 			goto cleanup;
164999ebb4caSwyllys 		}
165099ebb4caSwyllys 
165199ebb4caSwyllys 		pubkey->kstype = KMF_KEYSTORE_OPENSSL;
165299ebb4caSwyllys 		pubkey->keyalg = KMF_DSA;
165399ebb4caSwyllys 		pubkey->keyclass = KMF_ASYM_PUB;
165499ebb4caSwyllys 		pubkey->israw = FALSE;
165599ebb4caSwyllys 
165699ebb4caSwyllys 		if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
165799ebb4caSwyllys 			pubkey->keyp = (void *)epubkey;
165899ebb4caSwyllys 		} else {
165999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
166099ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
166199ebb4caSwyllys 			goto cleanup;
166299ebb4caSwyllys 		}
166399ebb4caSwyllys 	}
166499ebb4caSwyllys 
166599ebb4caSwyllys 	if (rv != KMF_OK) {
166699ebb4caSwyllys 		goto cleanup;
166799ebb4caSwyllys 	}
166899ebb4caSwyllys 
166930a5e8faSwyllys 	if (storekey) {
167030a5e8faSwyllys 		KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
167130a5e8faSwyllys 		int i = 0;
167230a5e8faSwyllys 		char *keyfile = NULL, *dirpath = NULL;
167330a5e8faSwyllys 		KMF_ENCODE_FORMAT format;
167430a5e8faSwyllys 		/*
167530a5e8faSwyllys 		 * Construct a new attribute arrray and call openssl_store_key
167630a5e8faSwyllys 		 */
167730a5e8faSwyllys 		kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
167830a5e8faSwyllys 		    privkey, sizeof (privkey));
167930a5e8faSwyllys 		i++;
168030a5e8faSwyllys 
168130a5e8faSwyllys 		dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
168230a5e8faSwyllys 		if (dirpath != NULL) {
168330a5e8faSwyllys 			storeattrs[i].type = KMF_DIRPATH_ATTR;
168430a5e8faSwyllys 			storeattrs[i].pValue = dirpath;
168530a5e8faSwyllys 			storeattrs[i].valueLen = strlen(dirpath);
168630a5e8faSwyllys 			i++;
168730a5e8faSwyllys 		} else {
168830a5e8faSwyllys 			rv = KMF_OK; /* DIRPATH is optional */
168999ebb4caSwyllys 		}
169030a5e8faSwyllys 		keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
169130a5e8faSwyllys 		    attrlist, numattr);
169230a5e8faSwyllys 		if (keyfile != NULL) {
169330a5e8faSwyllys 			storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
169430a5e8faSwyllys 			storeattrs[i].pValue = keyfile;
169530a5e8faSwyllys 			storeattrs[i].valueLen = strlen(keyfile);
169630a5e8faSwyllys 			i++;
169730a5e8faSwyllys 		} else {
169830a5e8faSwyllys 			goto cleanup; /* KEYFILE is required */
169930a5e8faSwyllys 		}
170030a5e8faSwyllys 		rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
170130a5e8faSwyllys 		    (void *)&format, NULL);
170230a5e8faSwyllys 		if (rv == KMF_OK) {
170330a5e8faSwyllys 			storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
170430a5e8faSwyllys 			storeattrs[i].pValue = &format;
170530a5e8faSwyllys 			storeattrs[i].valueLen = sizeof (format);
170630a5e8faSwyllys 			i++;
170730a5e8faSwyllys 		}
170830a5e8faSwyllys 
170930a5e8faSwyllys 		rv = OpenSSL_StoreKey(handle, i, storeattrs);
171030a5e8faSwyllys 	}
171199ebb4caSwyllys 
171299ebb4caSwyllys cleanup:
1713300fdee2SAndy Fiddaman 	if (eValue_bn != NULL)
1714300fdee2SAndy Fiddaman 		BN_free(eValue_bn);
1715300fdee2SAndy Fiddaman 
171699ebb4caSwyllys 	if (rv != KMF_OK) {
171799ebb4caSwyllys 		if (eprikey != NULL)
171899ebb4caSwyllys 			EVP_PKEY_free(eprikey);
171999ebb4caSwyllys 
172099ebb4caSwyllys 		if (epubkey != NULL)
172199ebb4caSwyllys 			EVP_PKEY_free(epubkey);
172299ebb4caSwyllys 
172399ebb4caSwyllys 		if (pubkey->keylabel) {
172499ebb4caSwyllys 			free(pubkey->keylabel);
172599ebb4caSwyllys 			pubkey->keylabel = NULL;
172699ebb4caSwyllys 		}
172799ebb4caSwyllys 
172899ebb4caSwyllys 		if (privkey->keylabel) {
172999ebb4caSwyllys 			free(privkey->keylabel);
173099ebb4caSwyllys 			privkey->keylabel = NULL;
173199ebb4caSwyllys 		}
173299ebb4caSwyllys 
173399ebb4caSwyllys 		pubkey->keyp = NULL;
173499ebb4caSwyllys 		privkey->keyp = NULL;
173599ebb4caSwyllys 	}
173699ebb4caSwyllys 
173799ebb4caSwyllys 	if (sslPrivKey)
173899ebb4caSwyllys 		RSA_free(sslPrivKey);
173999ebb4caSwyllys 
174099ebb4caSwyllys 	if (sslDSAKey)
174199ebb4caSwyllys 		DSA_free(sslDSAKey);
174299ebb4caSwyllys 
174399ebb4caSwyllys 	if (out != NULL)
174499ebb4caSwyllys 		(void) BIO_free(out);
174599ebb4caSwyllys 
174699ebb4caSwyllys 	return (rv);
174799ebb4caSwyllys }
174899ebb4caSwyllys 
1749e65e5c2dSWyllys Ingersoll /*
1750e65e5c2dSWyllys Ingersoll  * Make sure the BN conversion is properly padded with 0x00
1751e65e5c2dSWyllys Ingersoll  * bytes.  If not, signature verification for DSA signatures
1752e65e5c2dSWyllys Ingersoll  * may fail in the case where the bignum value does not use
1753e65e5c2dSWyllys Ingersoll  * all of the bits.
1754e65e5c2dSWyllys Ingersoll  */
1755e65e5c2dSWyllys Ingersoll static int
1756300fdee2SAndy Fiddaman fixbnlen(const BIGNUM *bn, unsigned char *buf, int len) {
1757e65e5c2dSWyllys Ingersoll 	int bytes = len - BN_num_bytes(bn);
17582c9a247fSWyllys Ingersoll 
17592c9a247fSWyllys Ingersoll 	/* prepend with leading 0x00 if necessary */
1760e65e5c2dSWyllys Ingersoll 	while (bytes-- > 0)
1761e65e5c2dSWyllys Ingersoll 		*buf++ = 0;
1762e65e5c2dSWyllys Ingersoll 
17632c9a247fSWyllys Ingersoll 	(void) BN_bn2bin(bn, buf);
17642c9a247fSWyllys Ingersoll 	/*
17652c9a247fSWyllys Ingersoll 	 * Return the desired length since we prepended it
17662c9a247fSWyllys Ingersoll 	 * with the necessary 0x00 padding.
17672c9a247fSWyllys Ingersoll 	 */
17682c9a247fSWyllys Ingersoll 	return (len);
1769e65e5c2dSWyllys Ingersoll }
1770e65e5c2dSWyllys Ingersoll 
177199ebb4caSwyllys KMF_RETURN
177299ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
177399ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
177499ebb4caSwyllys {
177599ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
177699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
177799ebb4caSwyllys 	KMF_ALGORITHM_INDEX		AlgId;
1778300fdee2SAndy Fiddaman 	EVP_MD_CTX *ctx;
177999ebb4caSwyllys 	const EVP_MD *md;
178002744e81Swyllys 
178199ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
178299ebb4caSwyllys 	    tobesigned == NULL || output == NULL ||
178399ebb4caSwyllys 	    tobesigned->Data == NULL ||
178499ebb4caSwyllys 	    output->Data == NULL)
178599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
178699ebb4caSwyllys 
178799ebb4caSwyllys 	/* Map the OID to an OpenSSL algorithm */
178830a5e8faSwyllys 	AlgId = x509_algoid_to_algid(AlgOID);
178999ebb4caSwyllys 	if (AlgId == KMF_ALGID_NONE)
1790e65e5c2dSWyllys Ingersoll 		return (KMF_ERR_BAD_ALGORITHM);
179199ebb4caSwyllys 
179299ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
179399ebb4caSwyllys 		EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
179499ebb4caSwyllys 		uchar_t *p;
179502744e81Swyllys 		int len;
1796553e44ceSAndrew Stormont 		switch (AlgId) {
1797553e44ceSAndrew Stormont #ifndef	OPENSSL_NO_MD5
1798553e44ceSAndrew Stormont 		case KMF_ALGID_MD5WithRSA:
179999ebb4caSwyllys 			md = EVP_md5();
1800553e44ceSAndrew Stormont 			break;
1801553e44ceSAndrew Stormont #endif
1802553e44ceSAndrew Stormont #ifndef	OPENSSL_NO_SHA
1803553e44ceSAndrew Stormont 		case KMF_ALGID_SHA1WithRSA:
180499ebb4caSwyllys 			md = EVP_sha1();
1805553e44ceSAndrew Stormont 			break;
1806553e44ceSAndrew Stormont #endif
1807553e44ceSAndrew Stormont #ifndef	OPENSSL_NO_SHA256
1808553e44ceSAndrew Stormont 		case KMF_ALGID_SHA256WithRSA:
1809e65e5c2dSWyllys Ingersoll 			md = EVP_sha256();
1810553e44ceSAndrew Stormont 			break;
1811553e44ceSAndrew Stormont #endif
1812553e44ceSAndrew Stormont #ifndef	OPENSSL_NO_SHA512
1813553e44ceSAndrew Stormont 		case KMF_ALGID_SHA384WithRSA:
1814e65e5c2dSWyllys Ingersoll 			md = EVP_sha384();
1815553e44ceSAndrew Stormont 			break;
1816553e44ceSAndrew Stormont 		case KMF_ALGID_SHA512WithRSA:
1817e65e5c2dSWyllys Ingersoll 			md = EVP_sha512();
1818553e44ceSAndrew Stormont 			break;
1819553e44ceSAndrew Stormont #endif
1820553e44ceSAndrew Stormont 		case KMF_ALGID_RSA:
182102744e81Swyllys 			md = NULL;
1822553e44ceSAndrew Stormont 			break;
1823553e44ceSAndrew Stormont 		default:
1824e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_ALGORITHM);
1825553e44ceSAndrew Stormont 		}
182699ebb4caSwyllys 
182702744e81Swyllys 		if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
182802744e81Swyllys 			RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
182999ebb4caSwyllys 
183002744e81Swyllys 			p = output->Data;
183102744e81Swyllys 			if ((len = RSA_private_encrypt(tobesigned->Length,
183202744e81Swyllys 			    tobesigned->Data, p, rsa,
183302744e81Swyllys 			    RSA_PKCS1_PADDING)) <= 0) {
183402744e81Swyllys 				SET_ERROR(kmfh, ERR_get_error());
183502744e81Swyllys 				ret = KMF_ERR_INTERNAL;
183602744e81Swyllys 			}
183702744e81Swyllys 			output->Length = len;
183802744e81Swyllys 		} else {
1839300fdee2SAndy Fiddaman 			if ((ctx = EVP_MD_CTX_new()) == NULL)
1840300fdee2SAndy Fiddaman 				return (KMF_ERR_MEMORY);
1841300fdee2SAndy Fiddaman 			(void) EVP_SignInit_ex(ctx, md, NULL);
1842300fdee2SAndy Fiddaman 			(void) EVP_SignUpdate(ctx, tobesigned->Data,
184399ebb4caSwyllys 			    (uint32_t)tobesigned->Length);
184499ebb4caSwyllys 			len = (uint32_t)output->Length;
184599ebb4caSwyllys 			p = output->Data;
1846300fdee2SAndy Fiddaman 			if (!EVP_SignFinal(ctx, p, (uint32_t *)&len, pkey)) {
184799ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
184802744e81Swyllys 				len = 0;
184902744e81Swyllys 				ret = KMF_ERR_INTERNAL;
185099ebb4caSwyllys 			}
185199ebb4caSwyllys 			output->Length = len;
1852300fdee2SAndy Fiddaman 			EVP_MD_CTX_free(ctx);
185302744e81Swyllys 		}
185499ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
185599ebb4caSwyllys 		DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
185699ebb4caSwyllys 
185799ebb4caSwyllys 		uchar_t hash[EVP_MAX_MD_SIZE];
185899ebb4caSwyllys 		uint32_t hashlen;
185999ebb4caSwyllys 		DSA_SIG *dsasig;
186099ebb4caSwyllys 
1861e65e5c2dSWyllys Ingersoll 		if (AlgId == KMF_ALGID_DSA ||
1862e65e5c2dSWyllys Ingersoll 		    AlgId == KMF_ALGID_SHA1WithDSA)
1863e65e5c2dSWyllys Ingersoll 			md = EVP_sha1();
1864e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA256WithDSA)
1865e65e5c2dSWyllys Ingersoll 			md = EVP_sha256();
1866e65e5c2dSWyllys Ingersoll 		else /* Bad algorithm */
1867e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_ALGORITHM);
1868e65e5c2dSWyllys Ingersoll 
186999ebb4caSwyllys 		/*
187099ebb4caSwyllys 		 * OpenSSL EVP_Sign operation automatically converts to
187199ebb4caSwyllys 		 * ASN.1 output so we do the operations separately so we
187299ebb4caSwyllys 		 * are assured of NOT getting ASN.1 output returned.
187399ebb4caSwyllys 		 * KMF does not want ASN.1 encoded results because
187499ebb4caSwyllys 		 * not all mechanisms return ASN.1 encodings (PKCS#11
187599ebb4caSwyllys 		 * and NSS return raw signature data).
187699ebb4caSwyllys 		 */
1877300fdee2SAndy Fiddaman 		if ((ctx = EVP_MD_CTX_new()) == NULL)
1878300fdee2SAndy Fiddaman 			return (KMF_ERR_MEMORY);
1879300fdee2SAndy Fiddaman 		(void) EVP_DigestInit_ex(ctx, md, NULL);
1880300fdee2SAndy Fiddaman 		(void) EVP_DigestUpdate(ctx, tobesigned->Data,
188199ebb4caSwyllys 		    tobesigned->Length);
1882300fdee2SAndy Fiddaman 		(void) EVP_DigestFinal_ex(ctx, hash, &hashlen);
188399ebb4caSwyllys 
1884e65e5c2dSWyllys Ingersoll 		/* Only sign first 20 bytes for SHA2 */
1885e65e5c2dSWyllys Ingersoll 		if (AlgId == KMF_ALGID_SHA256WithDSA)
1886e65e5c2dSWyllys Ingersoll 			hashlen = 20;
188799ebb4caSwyllys 		dsasig = DSA_do_sign(hash, hashlen, dsa);
188899ebb4caSwyllys 		if (dsasig != NULL) {
188999ebb4caSwyllys 			int i;
1890300fdee2SAndy Fiddaman 			const BIGNUM *r, *s;
1891300fdee2SAndy Fiddaman 
1892300fdee2SAndy Fiddaman 			DSA_SIG_get0(dsasig, &r, &s);
1893300fdee2SAndy Fiddaman 			output->Length = i = fixbnlen(r, output->Data,
1894e65e5c2dSWyllys Ingersoll 			    hashlen);
18952c9a247fSWyllys Ingersoll 
1896300fdee2SAndy Fiddaman 			output->Length += fixbnlen(s, &output->Data[i],
1897e65e5c2dSWyllys Ingersoll 			    hashlen);
18982c9a247fSWyllys Ingersoll 
189999ebb4caSwyllys 			DSA_SIG_free(dsasig);
190099ebb4caSwyllys 		} else {
190199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
190299ebb4caSwyllys 		}
1903300fdee2SAndy Fiddaman 		EVP_MD_CTX_free(ctx);
190499ebb4caSwyllys 	} else {
190599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
190699ebb4caSwyllys 	}
190799ebb4caSwyllys cleanup:
190899ebb4caSwyllys 	return (ret);
190999ebb4caSwyllys }
191099ebb4caSwyllys 
191199ebb4caSwyllys KMF_RETURN
191299ebb4caSwyllys /*ARGSUSED*/
191330a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle,
191430a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
191599ebb4caSwyllys {
191699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
191730a5e8faSwyllys 	KMF_KEY_HANDLE *key;
191830a5e8faSwyllys 	boolean_t destroy = B_TRUE;
191930a5e8faSwyllys 
192030a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
192199ebb4caSwyllys 	if (key == NULL || key->keyp == NULL)
192299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
192399ebb4caSwyllys 
192430a5e8faSwyllys 	rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
192530a5e8faSwyllys 	    (void *)&destroy, NULL);
192630a5e8faSwyllys 	if (rv != KMF_OK) {
192730a5e8faSwyllys 		/* "destroy" is optional. Default is TRUE */
192830a5e8faSwyllys 		rv = KMF_OK;
192930a5e8faSwyllys 	}
193030a5e8faSwyllys 
193199ebb4caSwyllys 	if (key->keyclass != KMF_ASYM_PUB &&
193299ebb4caSwyllys 	    key->keyclass != KMF_ASYM_PRI &&
193399ebb4caSwyllys 	    key->keyclass != KMF_SYMMETRIC)
193499ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
193599ebb4caSwyllys 
193699ebb4caSwyllys 	if (key->keyclass == KMF_SYMMETRIC) {
193730a5e8faSwyllys 		kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
193899ebb4caSwyllys 		key->keyp = NULL;
193999ebb4caSwyllys 	} else {
194099ebb4caSwyllys 		if (key->keyp != NULL) {
194199ebb4caSwyllys 			EVP_PKEY_free(key->keyp);
194299ebb4caSwyllys 			key->keyp = NULL;
194399ebb4caSwyllys 		}
194499ebb4caSwyllys 	}
194599ebb4caSwyllys 
194699ebb4caSwyllys 	if (key->keylabel != NULL) {
194799ebb4caSwyllys 		EVP_PKEY *pkey = NULL;
194899ebb4caSwyllys 		/* If the file exists, make sure it is a proper key. */
194999ebb4caSwyllys 		pkey = openssl_load_key(handle, key->keylabel);
195099ebb4caSwyllys 		if (pkey == NULL) {
19515b3e1433Swyllys 			if (key->keylabel != NULL) {
195299ebb4caSwyllys 				free(key->keylabel);
195399ebb4caSwyllys 				key->keylabel = NULL;
19545b3e1433Swyllys 			}
195599ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
195699ebb4caSwyllys 		}
195799ebb4caSwyllys 		EVP_PKEY_free(pkey);
195899ebb4caSwyllys 
195999ebb4caSwyllys 		if (destroy) {
196099ebb4caSwyllys 			if (unlink(key->keylabel) != 0) {
196199ebb4caSwyllys 				KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
196299ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
196399ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
196499ebb4caSwyllys 			}
196599ebb4caSwyllys 		}
196699ebb4caSwyllys 		if (key->keylabel != NULL) {
196799ebb4caSwyllys 			free(key->keylabel);
196899ebb4caSwyllys 			key->keylabel = NULL;
196999ebb4caSwyllys 		}
197099ebb4caSwyllys 	}
197199ebb4caSwyllys 	return (rv);
197299ebb4caSwyllys }
197399ebb4caSwyllys 
197499ebb4caSwyllys KMF_RETURN
197599ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
197699ebb4caSwyllys {
197799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
197899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
197999ebb4caSwyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
198099ebb4caSwyllys 
198199ebb4caSwyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
198299ebb4caSwyllys 	if (strlen(str)) {
198399ebb4caSwyllys 		*msgstr = (char *)strdup(str);
198499ebb4caSwyllys 		if ((*msgstr) == NULL)
198599ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
198699ebb4caSwyllys 	} else {
198799ebb4caSwyllys 		*msgstr = NULL;
198899ebb4caSwyllys 	}
198999ebb4caSwyllys 
199099ebb4caSwyllys 	return (ret);
199199ebb4caSwyllys }
199299ebb4caSwyllys 
199399ebb4caSwyllys static int
199499ebb4caSwyllys ext2NID(int kmfext)
199599ebb4caSwyllys {
199699ebb4caSwyllys 	switch (kmfext) {
199799ebb4caSwyllys 		case KMF_X509_EXT_KEY_USAGE:
199899ebb4caSwyllys 			return (NID_key_usage);
199999ebb4caSwyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
200099ebb4caSwyllys 			return (NID_private_key_usage_period);
200199ebb4caSwyllys 		case KMF_X509_EXT_CERT_POLICIES:
200299ebb4caSwyllys 			return (NID_certificate_policies);
200399ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
200499ebb4caSwyllys 			return (NID_subject_alt_name);
200599ebb4caSwyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
200699ebb4caSwyllys 			return (NID_issuer_alt_name);
200799ebb4caSwyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
200899ebb4caSwyllys 			return (NID_basic_constraints);
200999ebb4caSwyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
201099ebb4caSwyllys 			return (NID_ext_key_usage);
201199ebb4caSwyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
201299ebb4caSwyllys 			return (NID_authority_key_identifier);
201399ebb4caSwyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
201499ebb4caSwyllys 			return (NID_crl_distribution_points);
201599ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
201699ebb4caSwyllys 			return (NID_subject_key_identifier);
201799ebb4caSwyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
201899ebb4caSwyllys 			return (OBJ_sn2nid("policyMappings"));
201999ebb4caSwyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
202099ebb4caSwyllys 			return (OBJ_sn2nid("nameConstraints"));
202199ebb4caSwyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
202299ebb4caSwyllys 			return (OBJ_sn2nid("policyConstraints"));
202399ebb4caSwyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
202499ebb4caSwyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
202599ebb4caSwyllys 		case KMF_X509_EXT_FRESHEST_CRL:
202699ebb4caSwyllys 			return (OBJ_sn2nid("freshestCRL"));
202799ebb4caSwyllys 		default:
202899ebb4caSwyllys 			return (NID_undef);
202999ebb4caSwyllys 	}
203099ebb4caSwyllys }
203199ebb4caSwyllys 
203299ebb4caSwyllys KMF_RETURN
203399ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
203499ebb4caSwyllys 	KMF_PRINTABLE_ITEM flag, char *resultStr)
203599ebb4caSwyllys {
203699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
203799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
203899ebb4caSwyllys 	X509 *xcert = NULL;
203999ebb4caSwyllys 	unsigned char *outbuf = NULL;
204099ebb4caSwyllys 	unsigned char *outbuf_p;
204199ebb4caSwyllys 	int j;
204299ebb4caSwyllys 	int ext_index, nid, len;
204399ebb4caSwyllys 	BIO *mem = NULL;
204470f9559bSTheo Schlossnagle 	STACK_OF(OPENSSL_STRING) *emlst = NULL;
204599ebb4caSwyllys 	X509_EXTENSION *ex;
204699ebb4caSwyllys 
204799ebb4caSwyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
204899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
204999ebb4caSwyllys 	}
205099ebb4caSwyllys 
205199ebb4caSwyllys 	/* copy cert data to outbuf */
205299ebb4caSwyllys 	outbuf = malloc(pcert->Length);
205399ebb4caSwyllys 	if (outbuf == NULL) {
205499ebb4caSwyllys 		return (KMF_ERR_MEMORY);
205599ebb4caSwyllys 	}
205699ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
205799ebb4caSwyllys 
205899ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
205999ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
206099ebb4caSwyllys 	if (xcert == NULL) {
206199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
206299ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
206399ebb4caSwyllys 		goto out;
206499ebb4caSwyllys 	}
206599ebb4caSwyllys 
206699ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
206799ebb4caSwyllys 	if (mem == NULL) {
206899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
206999ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
207099ebb4caSwyllys 		goto out;
207199ebb4caSwyllys 	}
207299ebb4caSwyllys 
207399ebb4caSwyllys 	switch (flag) {
207499ebb4caSwyllys 	case KMF_CERT_ISSUER:
207599ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
207699ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
207799ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
207899ebb4caSwyllys 		break;
207999ebb4caSwyllys 
208099ebb4caSwyllys 	case KMF_CERT_SUBJECT:
208199ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
208299ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
208399ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
208499ebb4caSwyllys 		break;
208599ebb4caSwyllys 
208699ebb4caSwyllys 	case KMF_CERT_VERSION:
2087300fdee2SAndy Fiddaman 		(void) snprintf(resultStr, KMF_CERT_PRINTABLE_LEN,
2088300fdee2SAndy Fiddaman 		    "%ld", X509_get_version(xcert));
208999ebb4caSwyllys 		len = strlen(resultStr);
209099ebb4caSwyllys 		break;
209199ebb4caSwyllys 
209299ebb4caSwyllys 	case KMF_CERT_SERIALNUM:
209399ebb4caSwyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
209499ebb4caSwyllys 			(void) strcpy(resultStr, "0x");
209599ebb4caSwyllys 			len = BIO_gets(mem, &resultStr[2],
209699ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN - 2);
209799ebb4caSwyllys 		}
209899ebb4caSwyllys 		break;
209999ebb4caSwyllys 
210099ebb4caSwyllys 	case KMF_CERT_NOTBEFORE:
2101300fdee2SAndy Fiddaman 		(void) ASN1_TIME_print(mem, X509_getm_notBefore(xcert));
210299ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
210399ebb4caSwyllys 		break;
210499ebb4caSwyllys 
210599ebb4caSwyllys 	case KMF_CERT_NOTAFTER:
2106300fdee2SAndy Fiddaman 		(void) ASN1_TIME_print(mem, X509_getm_notAfter(xcert));
210799ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
210899ebb4caSwyllys 		break;
210999ebb4caSwyllys 
211099ebb4caSwyllys 	case KMF_CERT_PUBKEY_DATA:
211199ebb4caSwyllys 		{
2112300fdee2SAndy Fiddaman 			RSA *rsa;
2113300fdee2SAndy Fiddaman 			DSA *dsa;
2114300fdee2SAndy Fiddaman 
211599ebb4caSwyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
211699ebb4caSwyllys 			if (pkey == NULL) {
211799ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
211899ebb4caSwyllys 				ret = KMF_ERR_ENCODING;
211999ebb4caSwyllys 				goto out;
212099ebb4caSwyllys 			}
212199ebb4caSwyllys 
2122300fdee2SAndy Fiddaman 			if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
212399ebb4caSwyllys 				(void) BIO_printf(mem,
212499ebb4caSwyllys 				    "RSA Public Key: (%d bit)\n",
2125300fdee2SAndy Fiddaman 				    RSA_bits(rsa));
2126300fdee2SAndy Fiddaman 				(void) RSA_print(mem, rsa, 0);
2127300fdee2SAndy Fiddaman 
2128300fdee2SAndy Fiddaman 			} else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
212999ebb4caSwyllys 				(void) BIO_printf(mem,
213099ebb4caSwyllys 				    "%12sDSA Public Key:\n", "");
2131300fdee2SAndy Fiddaman 				(void) DSA_print(mem, dsa, 0);
213299ebb4caSwyllys 			} else {
213399ebb4caSwyllys 				(void) BIO_printf(mem,
213499ebb4caSwyllys 				    "%12sUnknown Public Key:\n", "");
213599ebb4caSwyllys 			}
213699ebb4caSwyllys 			(void) BIO_printf(mem, "\n");
213799ebb4caSwyllys 			EVP_PKEY_free(pkey);
213899ebb4caSwyllys 		}
213999ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
214099ebb4caSwyllys 		break;
214199ebb4caSwyllys 	case KMF_CERT_SIGNATURE_ALG:
214299ebb4caSwyllys 	case KMF_CERT_PUBKEY_ALG:
2143300fdee2SAndy Fiddaman 		{
2144553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2145300fdee2SAndy Fiddaman 			ASN1_OBJECT *alg = NULL;
2146300fdee2SAndy Fiddaman #else
2147300fdee2SAndy Fiddaman 			const ASN1_OBJECT *alg = NULL;
2148300fdee2SAndy Fiddaman #endif
2149300fdee2SAndy Fiddaman 
215099ebb4caSwyllys 			if (flag == KMF_CERT_SIGNATURE_ALG) {
2151553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2152300fdee2SAndy Fiddaman 				alg = xcert->sig_alg->algorithm;
2153300fdee2SAndy Fiddaman #else
2154300fdee2SAndy Fiddaman 				const X509_ALGOR *sig_alg = NULL;
2155300fdee2SAndy Fiddaman 
2156300fdee2SAndy Fiddaman 				X509_get0_signature(NULL, &sig_alg, xcert);
2157300fdee2SAndy Fiddaman 				if (sig_alg != NULL)
2158300fdee2SAndy Fiddaman 					X509_ALGOR_get0(&alg, NULL, NULL,
2159300fdee2SAndy Fiddaman 					    sig_alg);
2160300fdee2SAndy Fiddaman #endif
216199ebb4caSwyllys 			} else {
2162553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2163300fdee2SAndy Fiddaman 				alg = xcert->cert_info->key->algor->algorithm;
2164300fdee2SAndy Fiddaman #else
2165300fdee2SAndy Fiddaman 				X509_PUBKEY *key = X509_get_X509_PUBKEY(xcert);
2166300fdee2SAndy Fiddaman 
2167300fdee2SAndy Fiddaman 				if (key != NULL)
2168300fdee2SAndy Fiddaman 					(void) X509_PUBKEY_get0_param(
2169300fdee2SAndy Fiddaman 					    (ASN1_OBJECT **)&alg, NULL, 0,
2170300fdee2SAndy Fiddaman 					    NULL, key);
2171300fdee2SAndy Fiddaman #endif
217299ebb4caSwyllys 			}
217399ebb4caSwyllys 
2174300fdee2SAndy Fiddaman 			if (alg == NULL)
2175300fdee2SAndy Fiddaman 				len = -1;
2176300fdee2SAndy Fiddaman 			else if ((len = i2a_ASN1_OBJECT(mem, alg)) > 0)
217799ebb4caSwyllys 				len = BIO_read(mem, resultStr,
217899ebb4caSwyllys 				    KMF_CERT_PRINTABLE_LEN);
217999ebb4caSwyllys 		}
218099ebb4caSwyllys 		break;
218199ebb4caSwyllys 
218299ebb4caSwyllys 	case KMF_CERT_EMAIL:
218399ebb4caSwyllys 		emlst = X509_get1_email(xcert);
218470f9559bSTheo Schlossnagle 		for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
218570f9559bSTheo Schlossnagle 			(void) BIO_printf(mem, "%s\n",
218670f9559bSTheo Schlossnagle 			    sk_OPENSSL_STRING_value(emlst, j));
218799ebb4caSwyllys 
218899ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
218999ebb4caSwyllys 		X509_email_free(emlst);
219099ebb4caSwyllys 		break;
219199ebb4caSwyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
219299ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
219399ebb4caSwyllys 	case KMF_X509_EXT_KEY_USAGE:
219499ebb4caSwyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
219599ebb4caSwyllys 	case KMF_X509_EXT_CERT_POLICIES:
219699ebb4caSwyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
219799ebb4caSwyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
219899ebb4caSwyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
219999ebb4caSwyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
220099ebb4caSwyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
220199ebb4caSwyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
220299ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
220399ebb4caSwyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
220499ebb4caSwyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
220599ebb4caSwyllys 	case KMF_X509_EXT_FRESHEST_CRL:
220699ebb4caSwyllys 		nid = ext2NID(flag);
220799ebb4caSwyllys 		if (nid == NID_undef) {
220899ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
220999ebb4caSwyllys 			goto out;
221099ebb4caSwyllys 		}
221199ebb4caSwyllys 
2212300fdee2SAndy Fiddaman 		ext_index = X509_get_ext_by_NID(xcert, nid, -1);
221399ebb4caSwyllys 		if (ext_index == -1) {
221499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
221599ebb4caSwyllys 
221699ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
221799ebb4caSwyllys 			goto out;
221899ebb4caSwyllys 		}
2219300fdee2SAndy Fiddaman 		ex = X509_get_ext(xcert, ext_index);
222099ebb4caSwyllys 
222199ebb4caSwyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
222299ebb4caSwyllys 
222399ebb4caSwyllys 		if (BIO_printf(mem, ": %s\n",
222430a5e8faSwyllys 		    X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
222599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
222699ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
222799ebb4caSwyllys 			goto out;
222899ebb4caSwyllys 		}
222999ebb4caSwyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
223099ebb4caSwyllys 			(void) BIO_printf(mem, "%*s", 4, "");
2231300fdee2SAndy Fiddaman 			(void) ASN1_STRING_print(mem,
2232300fdee2SAndy Fiddaman 			    X509_EXTENSION_get_data(ex));
223399ebb4caSwyllys 		}
223499ebb4caSwyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
223599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
223699ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
223799ebb4caSwyllys 			goto out;
223899ebb4caSwyllys 		}
223999ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
224099ebb4caSwyllys 	}
224199ebb4caSwyllys 	if (len <= 0) {
224299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
224399ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
224499ebb4caSwyllys 	}
224599ebb4caSwyllys 
224699ebb4caSwyllys out:
224799ebb4caSwyllys 	if (outbuf != NULL) {
224899ebb4caSwyllys 		free(outbuf);
224999ebb4caSwyllys 	}
225099ebb4caSwyllys 
225199ebb4caSwyllys 	if (xcert != NULL) {
225299ebb4caSwyllys 		X509_free(xcert);
225399ebb4caSwyllys 	}
225499ebb4caSwyllys 
225599ebb4caSwyllys 	if (mem != NULL) {
225699ebb4caSwyllys 		(void) BIO_free(mem);
225799ebb4caSwyllys 	}
225899ebb4caSwyllys 
225999ebb4caSwyllys 	return (ret);
226099ebb4caSwyllys }
226130a5e8faSwyllys 
226299ebb4caSwyllys KMF_RETURN
226399ebb4caSwyllys /*ARGSUSED*/
226430a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
226530a5e8faSwyllys     KMF_ATTRIBUTE *attrlist)
226699ebb4caSwyllys {
226799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
226830a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
226930a5e8faSwyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
227030a5e8faSwyllys 	KMF_KEY_HANDLE *key = NULL;
227130a5e8faSwyllys 	uint32_t numkeys = 1; /* 1 key only */
227230a5e8faSwyllys 	char *dirpath = NULL;
227330a5e8faSwyllys 	char *keyfile = NULL;
227430a5e8faSwyllys 	KMF_ATTRIBUTE new_attrlist[16];
227530a5e8faSwyllys 	int i = 0;
227699ebb4caSwyllys 
227799ebb4caSwyllys 	/*
227899ebb4caSwyllys 	 * This is really just a FindKey operation, reuse the
227999ebb4caSwyllys 	 * FindKey function.
228099ebb4caSwyllys 	 */
228130a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
228230a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
228330a5e8faSwyllys 	i++;
228499ebb4caSwyllys 
228530a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
228630a5e8faSwyllys 	    KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
228730a5e8faSwyllys 	i++;
228899ebb4caSwyllys 
228930a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
229030a5e8faSwyllys 	    KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
229130a5e8faSwyllys 	i++;
229230a5e8faSwyllys 
229330a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
229430a5e8faSwyllys 	if (key == NULL) {
229530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
229630a5e8faSwyllys 	} else {
229730a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
229830a5e8faSwyllys 		    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
229930a5e8faSwyllys 		i++;
230030a5e8faSwyllys 	}
230130a5e8faSwyllys 
230230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
230330a5e8faSwyllys 	if (dirpath != NULL) {
230430a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
230530a5e8faSwyllys 		    KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
230630a5e8faSwyllys 		i++;
230730a5e8faSwyllys 	}
230830a5e8faSwyllys 
230930a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
231030a5e8faSwyllys 	if (keyfile == NULL)
231130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
231230a5e8faSwyllys 	else {
231330a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
231430a5e8faSwyllys 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
231530a5e8faSwyllys 		i++;
231630a5e8faSwyllys 	}
231730a5e8faSwyllys 
231830a5e8faSwyllys 	rv = OpenSSL_FindKey(handle, i, new_attrlist);
231999ebb4caSwyllys 	return (rv);
232099ebb4caSwyllys }
232199ebb4caSwyllys 
232299ebb4caSwyllys KMF_RETURN
232399ebb4caSwyllys /*ARGSUSED*/
232499ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
232599ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
232699ebb4caSwyllys 	KMF_DATA *output)
232799ebb4caSwyllys {
232899ebb4caSwyllys 	KMF_RETURN		ret = KMF_OK;
232999ebb4caSwyllys 	RSA *rsa = NULL;
233099ebb4caSwyllys 	unsigned int in_len = 0, out_len = 0;
233199ebb4caSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
233299ebb4caSwyllys 	uint8_t *in_data, *out_data;
233399ebb4caSwyllys 	int i, blocks;
233499ebb4caSwyllys 
233599ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
233699ebb4caSwyllys 	    ciphertext == NULL || output == NULL ||
233799ebb4caSwyllys 	    ciphertext->Data == NULL ||
233899ebb4caSwyllys 	    output->Data == NULL)
233999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
234099ebb4caSwyllys 
234199ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
234299ebb4caSwyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
234399ebb4caSwyllys 		modulus_len = RSA_size(rsa);
234499ebb4caSwyllys 	} else {
234599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
234699ebb4caSwyllys 	}
234799ebb4caSwyllys 
234899ebb4caSwyllys 	blocks = ciphertext->Length/modulus_len;
234999ebb4caSwyllys 	out_data = output->Data;
235099ebb4caSwyllys 	in_data = ciphertext->Data;
235199ebb4caSwyllys 	out_len = modulus_len - 11;
235299ebb4caSwyllys 	in_len = modulus_len;
235399ebb4caSwyllys 
235499ebb4caSwyllys 	for (i = 0; i < blocks; i++) {
235599ebb4caSwyllys 		out_len  = RSA_private_decrypt(in_len,
235699ebb4caSwyllys 		    in_data, out_data, rsa, RSA_PKCS1_PADDING);
235799ebb4caSwyllys 
235899ebb4caSwyllys 		if (out_len == 0) {
235999ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
236099ebb4caSwyllys 			goto cleanup;
236199ebb4caSwyllys 		}
236299ebb4caSwyllys 
236399ebb4caSwyllys 		out_data += out_len;
236499ebb4caSwyllys 		total_decrypted += out_len;
236599ebb4caSwyllys 		in_data += in_len;
236699ebb4caSwyllys 	}
236799ebb4caSwyllys 
236899ebb4caSwyllys 	output->Length = total_decrypted;
236999ebb4caSwyllys 
237099ebb4caSwyllys cleanup:
237199ebb4caSwyllys 	RSA_free(rsa);
237299ebb4caSwyllys 	if (ret != KMF_OK)
237399ebb4caSwyllys 		output->Length = 0;
237499ebb4caSwyllys 
237599ebb4caSwyllys 	return (ret);
237699ebb4caSwyllys 
237799ebb4caSwyllys }
237899ebb4caSwyllys 
237999ebb4caSwyllys /*
238099ebb4caSwyllys  *  This function will create a certid from issuer_cert and user_cert.
238199ebb4caSwyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
238299ebb4caSwyllys  *  certid memory after use.
238399ebb4caSwyllys  */
238499ebb4caSwyllys static KMF_RETURN
238599ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
238699ebb4caSwyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
238799ebb4caSwyllys {
238899ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
238999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
239099ebb4caSwyllys 	X509   *issuer = NULL;
239199ebb4caSwyllys 	X509   *cert = NULL;
239299ebb4caSwyllys 	unsigned char *ptmp;
239399ebb4caSwyllys 
239499ebb4caSwyllys 	if (issuer_cert == NULL || user_cert == NULL) {
239599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
239699ebb4caSwyllys 	}
239799ebb4caSwyllys 
239899ebb4caSwyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
239999ebb4caSwyllys 	ptmp = issuer_cert->Data;
240099ebb4caSwyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
240199ebb4caSwyllys 	    issuer_cert->Length);
240299ebb4caSwyllys 	if (issuer == NULL) {
240399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
240499ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
240599ebb4caSwyllys 		goto end;
240699ebb4caSwyllys 	}
240799ebb4caSwyllys 
240899ebb4caSwyllys 	/* convert the DER-encoded user cert to an internal X509 */
240999ebb4caSwyllys 	ptmp = user_cert->Data;
241099ebb4caSwyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
241199ebb4caSwyllys 	    user_cert->Length);
241299ebb4caSwyllys 	if (cert == NULL) {
241399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
241499ebb4caSwyllys 
241599ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
241699ebb4caSwyllys 		goto end;
241799ebb4caSwyllys 	}
241899ebb4caSwyllys 
241999ebb4caSwyllys 	/* create a CERTID */
242099ebb4caSwyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
242199ebb4caSwyllys 	if (*certid == NULL) {
242299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
242399ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
242499ebb4caSwyllys 		goto end;
242599ebb4caSwyllys 	}
242699ebb4caSwyllys 
242799ebb4caSwyllys end:
242899ebb4caSwyllys 	if (issuer != NULL) {
242999ebb4caSwyllys 		X509_free(issuer);
243099ebb4caSwyllys 	}
243199ebb4caSwyllys 
243299ebb4caSwyllys 	if (cert != NULL) {
243399ebb4caSwyllys 		X509_free(cert);
243499ebb4caSwyllys 	}
243599ebb4caSwyllys 
243699ebb4caSwyllys 	return (ret);
243799ebb4caSwyllys }
243899ebb4caSwyllys 
243999ebb4caSwyllys KMF_RETURN
244030a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
244130a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
244299ebb4caSwyllys {
244399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
244499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
244599ebb4caSwyllys 	OCSP_CERTID *id = NULL;
244699ebb4caSwyllys 	OCSP_REQUEST *req = NULL;
244799ebb4caSwyllys 	BIO *derbio = NULL;
244830a5e8faSwyllys 	char *reqfile;
244930a5e8faSwyllys 	KMF_DATA *issuer_cert;
245030a5e8faSwyllys 	KMF_DATA *user_cert;
245199ebb4caSwyllys 
245230a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
245330a5e8faSwyllys 	    attrlist, numattr);
245430a5e8faSwyllys 	if (user_cert == NULL)
245599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
245699ebb4caSwyllys 
245730a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
245830a5e8faSwyllys 	    attrlist, numattr);
245930a5e8faSwyllys 	if (issuer_cert == NULL)
246030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
246130a5e8faSwyllys 
246230a5e8faSwyllys 	reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
246330a5e8faSwyllys 	    attrlist, numattr);
246430a5e8faSwyllys 	if (reqfile == NULL)
246530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
246630a5e8faSwyllys 
246730a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
246899ebb4caSwyllys 	if (ret != KMF_OK) {
246999ebb4caSwyllys 		return (ret);
247099ebb4caSwyllys 	}
247199ebb4caSwyllys 
247299ebb4caSwyllys 	/* Create an OCSP request */
247399ebb4caSwyllys 	req = OCSP_REQUEST_new();
247499ebb4caSwyllys 	if (req == NULL) {
247599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
247699ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
247799ebb4caSwyllys 		goto end;
247899ebb4caSwyllys 	}
247999ebb4caSwyllys 
248099ebb4caSwyllys 	if (!OCSP_request_add0_id(req, id)) {
248199ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
248299ebb4caSwyllys 		goto end;
248399ebb4caSwyllys 	}
248499ebb4caSwyllys 
248599ebb4caSwyllys 	/* Write the request to the output file with DER encoding */
248699ebb4caSwyllys 	derbio = BIO_new_file(reqfile, "wb");
248799ebb4caSwyllys 	if (!derbio) {
248899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
248999ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
249099ebb4caSwyllys 		goto end;
249199ebb4caSwyllys 	}
249299ebb4caSwyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
249399ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
249499ebb4caSwyllys 	}
249599ebb4caSwyllys 
249699ebb4caSwyllys end:
249799ebb4caSwyllys 	/*
2498e65e5c2dSWyllys Ingersoll 	 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2499a2d4930dSDan OpenSolaris Anderson 	 * will also deallocate certid's space.
250099ebb4caSwyllys 	 */
250199ebb4caSwyllys 	if (req != NULL) {
250299ebb4caSwyllys 		OCSP_REQUEST_free(req);
250399ebb4caSwyllys 	}
250499ebb4caSwyllys 
250599ebb4caSwyllys 	if (derbio != NULL) {
250699ebb4caSwyllys 		(void) BIO_free(derbio);
250799ebb4caSwyllys 	}
250899ebb4caSwyllys 
250999ebb4caSwyllys 	return (ret);
251099ebb4caSwyllys }
251199ebb4caSwyllys 
251299ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */
2513300fdee2SAndy Fiddaman static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_BASICRESP *bs)
251499ebb4caSwyllys {
251599ebb4caSwyllys 	int i;
251699ebb4caSwyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
2517300fdee2SAndy Fiddaman 	const ASN1_OCTET_STRING *pid;
251899ebb4caSwyllys 
2519553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2520300fdee2SAndy Fiddaman 	OCSP_RESPID *id = bs->tbsResponseData->responderId;
2521300fdee2SAndy Fiddaman 
252299ebb4caSwyllys 	if (id->type == V_OCSP_RESPID_NAME)
252399ebb4caSwyllys 		return (X509_find_by_subject(certs, id->value.byName));
252499ebb4caSwyllys 
2525300fdee2SAndy Fiddaman 	pid = id->value.byKey;
2526300fdee2SAndy Fiddaman #else
2527300fdee2SAndy Fiddaman 	const X509_NAME *pname;
2528300fdee2SAndy Fiddaman 
2529300fdee2SAndy Fiddaman 	if (OCSP_resp_get0_id(bs, &pid, &pname) == 0)
2530300fdee2SAndy Fiddaman 		return (NULL);
2531300fdee2SAndy Fiddaman 
2532300fdee2SAndy Fiddaman 	if (pname != NULL)
2533300fdee2SAndy Fiddaman 		return (X509_find_by_subject(certs, (X509_NAME *)pname));
2534300fdee2SAndy Fiddaman #endif
2535300fdee2SAndy Fiddaman 
253699ebb4caSwyllys 	/* Lookup by key hash */
253799ebb4caSwyllys 
253899ebb4caSwyllys 	/* If key hash isn't SHA1 length then forget it */
2539300fdee2SAndy Fiddaman 	if (pid->length != SHA_DIGEST_LENGTH)
254099ebb4caSwyllys 		return (NULL);
254199ebb4caSwyllys 
2542300fdee2SAndy Fiddaman 	keyhash = pid->data;
254399ebb4caSwyllys 	/* Calculate hash of each key and compare */
254499ebb4caSwyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
2545d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
254699ebb4caSwyllys 		X509 *x = sk_X509_value(certs, i);
25475b3e1433Swyllys 		/* Use pubkey_digest to get the key ID value */
254899ebb4caSwyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
254999ebb4caSwyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
255099ebb4caSwyllys 			return (x);
255199ebb4caSwyllys 	}
255299ebb4caSwyllys 	return (NULL);
255399ebb4caSwyllys }
255499ebb4caSwyllys 
255599ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */
2556a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */
255799ebb4caSwyllys static int
255899ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
255999ebb4caSwyllys     X509_STORE *st, unsigned long flags)
256099ebb4caSwyllys {
256199ebb4caSwyllys 	X509 *signer;
2562300fdee2SAndy Fiddaman 	if ((signer = ocsp_find_signer_sk(certs, bs)))	{
256399ebb4caSwyllys 		*psigner = signer;
256499ebb4caSwyllys 		return (2);
256599ebb4caSwyllys 	}
2566300fdee2SAndy Fiddaman 
256799ebb4caSwyllys 	if (!(flags & OCSP_NOINTERN) &&
2568300fdee2SAndy Fiddaman 	    (signer = ocsp_find_signer_sk(
2569300fdee2SAndy Fiddaman 	    (STACK_OF(X509) *)OCSP_resp_get0_certs(bs), bs))) {
257099ebb4caSwyllys 		*psigner = signer;
257199ebb4caSwyllys 		return (1);
257299ebb4caSwyllys 	}
257399ebb4caSwyllys 	/* Maybe lookup from store if by subject name */
257499ebb4caSwyllys 
257599ebb4caSwyllys 	*psigner = NULL;
257699ebb4caSwyllys 	return (0);
257799ebb4caSwyllys }
257899ebb4caSwyllys 
257999ebb4caSwyllys /*
258099ebb4caSwyllys  * This function will verify the signature of a basic response, using
258199ebb4caSwyllys  * the public key from the OCSP responder certificate.
258299ebb4caSwyllys  */
258399ebb4caSwyllys static KMF_RETURN
258499ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
258599ebb4caSwyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
258699ebb4caSwyllys {
258799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
258899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
258999ebb4caSwyllys 	STACK_OF(X509) *cert_stack = NULL;
259099ebb4caSwyllys 	X509 *signer = NULL;
259199ebb4caSwyllys 	X509 *issuer = NULL;
2592553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
259399ebb4caSwyllys 	EVP_PKEY *skey = NULL;
2594300fdee2SAndy Fiddaman #else
2595300fdee2SAndy Fiddaman 	STACK_OF(X509) *cert_stack2 = NULL;
2596300fdee2SAndy Fiddaman #endif
259799ebb4caSwyllys 	unsigned char *ptmp;
259899ebb4caSwyllys 
259999ebb4caSwyllys 	if (bs == NULL || issuer_cert == NULL)
260099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
260199ebb4caSwyllys 
260299ebb4caSwyllys 	/*
260399ebb4caSwyllys 	 * Find the certificate that signed the basic response.
260499ebb4caSwyllys 	 *
260599ebb4caSwyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
260699ebb4caSwyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
260799ebb4caSwyllys 	 * If we still do not find a signer, we will look for it from the
260899ebb4caSwyllys 	 * certificate list came with the response file.
260999ebb4caSwyllys 	 */
261099ebb4caSwyllys 	if (signer_cert != NULL) {
261199ebb4caSwyllys 		ptmp = signer_cert->Data;
261299ebb4caSwyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
261399ebb4caSwyllys 		    signer_cert->Length);
261499ebb4caSwyllys 		if (signer == NULL) {
261599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
261699ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
261799ebb4caSwyllys 			goto end;
261899ebb4caSwyllys 		}
261999ebb4caSwyllys 	} else {
262099ebb4caSwyllys 		/*
262199ebb4caSwyllys 		 * Convert the issuer cert into X509 and push it into a
262299ebb4caSwyllys 		 * stack to be used by ocsp_find_signer().
262399ebb4caSwyllys 		 */
262499ebb4caSwyllys 		ptmp = issuer_cert->Data;
262599ebb4caSwyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
262699ebb4caSwyllys 		    issuer_cert->Length);
262799ebb4caSwyllys 		if (issuer == NULL) {
262899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
262999ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
263099ebb4caSwyllys 			goto end;
263199ebb4caSwyllys 		}
263299ebb4caSwyllys 
263399ebb4caSwyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
263499ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
263599ebb4caSwyllys 			goto end;
263699ebb4caSwyllys 		}
263799ebb4caSwyllys 
263899ebb4caSwyllys 		if (sk_X509_push(cert_stack, issuer) == NULL) {
263999ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
264099ebb4caSwyllys 			goto end;
264199ebb4caSwyllys 		}
264299ebb4caSwyllys 
264399ebb4caSwyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
264499ebb4caSwyllys 		if (!ret) {
264599ebb4caSwyllys 			/* can not find the signer */
264699ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
264799ebb4caSwyllys 			goto end;
264899ebb4caSwyllys 		}
264999ebb4caSwyllys 	}
265099ebb4caSwyllys 
265199ebb4caSwyllys 	/* Verify the signature of the response */
2652553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
265399ebb4caSwyllys 	skey = X509_get_pubkey(signer);
265499ebb4caSwyllys 	if (skey == NULL) {
265599ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
265699ebb4caSwyllys 		goto end;
265799ebb4caSwyllys 	}
265899ebb4caSwyllys 
265999ebb4caSwyllys 	ret = OCSP_BASICRESP_verify(bs, skey, 0);
2660300fdee2SAndy Fiddaman #else
2661300fdee2SAndy Fiddaman 	/*
2662300fdee2SAndy Fiddaman 	 * Technique based on
2663300fdee2SAndy Fiddaman 	 * https://mta.openssl.org/pipermail/openssl-users/
2664300fdee2SAndy Fiddaman 	 *	2017-October/006814.html
2665300fdee2SAndy Fiddaman 	 */
2666300fdee2SAndy Fiddaman 	if ((cert_stack2 = sk_X509_new_null()) == NULL) {
2667300fdee2SAndy Fiddaman 		ret = KMF_ERR_INTERNAL;
2668300fdee2SAndy Fiddaman 		goto end;
2669300fdee2SAndy Fiddaman 	}
2670300fdee2SAndy Fiddaman 
2671300fdee2SAndy Fiddaman 	if (sk_X509_push(cert_stack2, signer) == NULL) {
2672300fdee2SAndy Fiddaman 		ret = KMF_ERR_INTERNAL;
2673300fdee2SAndy Fiddaman 		goto end;
2674300fdee2SAndy Fiddaman 	}
2675300fdee2SAndy Fiddaman 
2676300fdee2SAndy Fiddaman 	ret = OCSP_basic_verify(bs, cert_stack2, NULL, OCSP_NOVERIFY);
2677300fdee2SAndy Fiddaman #endif
2678300fdee2SAndy Fiddaman 
267999ebb4caSwyllys 	if (ret == 0) {
268099ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
268199ebb4caSwyllys 		goto end;
268299ebb4caSwyllys 	}
268399ebb4caSwyllys 
268499ebb4caSwyllys end:
268599ebb4caSwyllys 	if (issuer != NULL) {
268699ebb4caSwyllys 		X509_free(issuer);
268799ebb4caSwyllys 	}
268899ebb4caSwyllys 
268999ebb4caSwyllys 	if (signer != NULL) {
269099ebb4caSwyllys 		X509_free(signer);
269199ebb4caSwyllys 	}
269299ebb4caSwyllys 
2693553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
269499ebb4caSwyllys 	if (skey != NULL) {
269599ebb4caSwyllys 		EVP_PKEY_free(skey);
269699ebb4caSwyllys 	}
2697300fdee2SAndy Fiddaman #else
2698300fdee2SAndy Fiddaman 	if (cert_stack2 != NULL) {
2699300fdee2SAndy Fiddaman 		sk_X509_free(cert_stack2);
2700300fdee2SAndy Fiddaman 	}
2701300fdee2SAndy Fiddaman #endif
270299ebb4caSwyllys 
270399ebb4caSwyllys 	if (cert_stack != NULL) {
270499ebb4caSwyllys 		sk_X509_free(cert_stack);
270599ebb4caSwyllys 	}
270699ebb4caSwyllys 
270799ebb4caSwyllys 	return (ret);
270899ebb4caSwyllys }
270999ebb4caSwyllys 
271099ebb4caSwyllys KMF_RETURN
271199ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
271230a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
271399ebb4caSwyllys {
271499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
271599ebb4caSwyllys 	BIO *derbio = NULL;
271699ebb4caSwyllys 	OCSP_RESPONSE *resp = NULL;
271799ebb4caSwyllys 	OCSP_BASICRESP *bs = NULL;
271899ebb4caSwyllys 	OCSP_CERTID *id = NULL;
271999ebb4caSwyllys 	OCSP_SINGLERESP *single = NULL;
272099ebb4caSwyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
272199ebb4caSwyllys 	int index, status, reason;
272230a5e8faSwyllys 	KMF_DATA *issuer_cert;
272330a5e8faSwyllys 	KMF_DATA *user_cert;
272430a5e8faSwyllys 	KMF_DATA *signer_cert;
272530a5e8faSwyllys 	KMF_DATA *response;
272630a5e8faSwyllys 	int *response_reason, *response_status, *cert_status;
272730a5e8faSwyllys 	boolean_t ignore_response_sign = B_FALSE;	/* default is FALSE */
272830a5e8faSwyllys 	uint32_t response_lifetime;
272999ebb4caSwyllys 
273030a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
273130a5e8faSwyllys 	    attrlist, numattr);
273230a5e8faSwyllys 	if (issuer_cert == NULL)
273399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
273499ebb4caSwyllys 
273530a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
273630a5e8faSwyllys 	    attrlist, numattr);
273730a5e8faSwyllys 	if (user_cert == NULL)
273899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
273930a5e8faSwyllys 
274030a5e8faSwyllys 	response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
274130a5e8faSwyllys 	    attrlist, numattr);
274230a5e8faSwyllys 	if (response == NULL)
274330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
274430a5e8faSwyllys 
274530a5e8faSwyllys 	response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
274630a5e8faSwyllys 	    attrlist, numattr);
274730a5e8faSwyllys 	if (response_status == NULL)
274830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
274930a5e8faSwyllys 
275030a5e8faSwyllys 	response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
275130a5e8faSwyllys 	    attrlist, numattr);
275230a5e8faSwyllys 	if (response_reason == NULL)
275330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
275430a5e8faSwyllys 
275530a5e8faSwyllys 	cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
275630a5e8faSwyllys 	    attrlist, numattr);
275730a5e8faSwyllys 	if (cert_status == NULL)
275830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
275999ebb4caSwyllys 
276099ebb4caSwyllys 	/* Read in the response */
276130a5e8faSwyllys 	derbio = BIO_new_mem_buf(response->Data, response->Length);
276299ebb4caSwyllys 	if (!derbio) {
276399ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
276499ebb4caSwyllys 		return (ret);
276599ebb4caSwyllys 	}
276699ebb4caSwyllys 
276799ebb4caSwyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
276899ebb4caSwyllys 	if (resp == NULL) {
276999ebb4caSwyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
277099ebb4caSwyllys 		goto end;
277199ebb4caSwyllys 	}
277299ebb4caSwyllys 
277399ebb4caSwyllys 	/* Check the response status */
277499ebb4caSwyllys 	status = OCSP_response_status(resp);
277530a5e8faSwyllys 	*response_status = status;
277699ebb4caSwyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
277799ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
277899ebb4caSwyllys 		goto end;
277999ebb4caSwyllys 	}
278099ebb4caSwyllys 
278199ebb4caSwyllys #ifdef DEBUG
278299ebb4caSwyllys 	printf("Successfully checked the response file status.\n");
278399ebb4caSwyllys #endif /* DEBUG */
278499ebb4caSwyllys 
278599ebb4caSwyllys 	/* Extract basic response */
278699ebb4caSwyllys 	bs = OCSP_response_get1_basic(resp);
278799ebb4caSwyllys 	if (bs == NULL) {
278899ebb4caSwyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
278999ebb4caSwyllys 		goto end;
279099ebb4caSwyllys 	}
279199ebb4caSwyllys 
279299ebb4caSwyllys #ifdef DEBUG
279399ebb4caSwyllys 	printf("Successfully retrieved the basic response.\n");
279499ebb4caSwyllys #endif /* DEBUG */
279599ebb4caSwyllys 
279699ebb4caSwyllys 	/* Check the basic response signature if required */
279730a5e8faSwyllys 	ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
279830a5e8faSwyllys 	    (void *)&ignore_response_sign, NULL);
279930a5e8faSwyllys 	if (ret != KMF_OK)
280030a5e8faSwyllys 		ret = KMF_OK;
280130a5e8faSwyllys 
280230a5e8faSwyllys 	signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
280330a5e8faSwyllys 	    attrlist, numattr);
280430a5e8faSwyllys 
280530a5e8faSwyllys 	if (ignore_response_sign == B_FALSE) {
280699ebb4caSwyllys 		ret = check_response_signature(handle, bs,
280730a5e8faSwyllys 		    signer_cert, issuer_cert);
280899ebb4caSwyllys 		if (ret != KMF_OK)
280999ebb4caSwyllys 			goto end;
281099ebb4caSwyllys 	}
281199ebb4caSwyllys 
281299ebb4caSwyllys #ifdef DEBUG
281399ebb4caSwyllys 	printf("Successfully verified the response signature.\n");
281499ebb4caSwyllys #endif /* DEBUG */
281599ebb4caSwyllys 
281699ebb4caSwyllys 	/* Create a certid for the certificate in question */
281730a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
281899ebb4caSwyllys 	if (ret != KMF_OK) {
281999ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
282099ebb4caSwyllys 		goto end;
282199ebb4caSwyllys 	}
282299ebb4caSwyllys 
282399ebb4caSwyllys #ifdef DEBUG
282499ebb4caSwyllys 	printf("successfully created a certid for the cert.\n");
282599ebb4caSwyllys #endif /* DEBUG */
282699ebb4caSwyllys 
282799ebb4caSwyllys 	/* Find the index of the single response for the certid */
282899ebb4caSwyllys 	index = OCSP_resp_find(bs, id, -1);
282999ebb4caSwyllys 	if (index < 0) {
283099ebb4caSwyllys 		/* cound not find this certificate in the response */
283199ebb4caSwyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
283299ebb4caSwyllys 		goto end;
283399ebb4caSwyllys 	}
283499ebb4caSwyllys 
283599ebb4caSwyllys #ifdef DEBUG
283699ebb4caSwyllys 	printf("Successfully found the single response index for the cert.\n");
283799ebb4caSwyllys #endif /* DEBUG */
283899ebb4caSwyllys 
283999ebb4caSwyllys 	/* Retrieve the single response and get the cert status */
284099ebb4caSwyllys 	single = OCSP_resp_get0(bs, index);
284199ebb4caSwyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
284299ebb4caSwyllys 	    &nextupd);
284399ebb4caSwyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
284430a5e8faSwyllys 		*cert_status = OCSP_GOOD;
284599ebb4caSwyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
284630a5e8faSwyllys 		*cert_status = OCSP_UNKNOWN;
284799ebb4caSwyllys 	} else { /* revoked */
284830a5e8faSwyllys 		*cert_status = OCSP_REVOKED;
284930a5e8faSwyllys 		*response_reason = reason;
285099ebb4caSwyllys 	}
285199ebb4caSwyllys 	ret = KMF_OK;
285299ebb4caSwyllys 
285330a5e8faSwyllys 	/* resp. time is optional, so we don't care about the return code. */
285430a5e8faSwyllys 	(void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
285530a5e8faSwyllys 	    (void *)&response_lifetime, NULL);
285630a5e8faSwyllys 
285799ebb4caSwyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
285830a5e8faSwyllys 	    response_lifetime)) {
285999ebb4caSwyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
286099ebb4caSwyllys 		goto end;
286199ebb4caSwyllys 	}
286299ebb4caSwyllys 
286399ebb4caSwyllys #ifdef DEBUG
286499ebb4caSwyllys 	printf("Successfully verify the time.\n");
286599ebb4caSwyllys #endif /* DEBUG */
286699ebb4caSwyllys 
286799ebb4caSwyllys end:
286899ebb4caSwyllys 	if (derbio != NULL)
286999ebb4caSwyllys 		(void) BIO_free(derbio);
287099ebb4caSwyllys 
287199ebb4caSwyllys 	if (resp != NULL)
287299ebb4caSwyllys 		OCSP_RESPONSE_free(resp);
287399ebb4caSwyllys 
287499ebb4caSwyllys 	if (bs != NULL)
287599ebb4caSwyllys 		OCSP_BASICRESP_free(bs);
287699ebb4caSwyllys 
287799ebb4caSwyllys 	if (id != NULL)
287899ebb4caSwyllys 		OCSP_CERTID_free(id);
287999ebb4caSwyllys 
288099ebb4caSwyllys 	return (ret);
288199ebb4caSwyllys }
288299ebb4caSwyllys 
288399ebb4caSwyllys static KMF_RETURN
288499ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path,
288599ebb4caSwyllys 	KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
288699ebb4caSwyllys {
288799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
288830a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
288999ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
289099ebb4caSwyllys 
289199ebb4caSwyllys 	if (keyclass == KMF_ASYM_PRI ||
289299ebb4caSwyllys 	    keyclass == KMF_ASYM_PUB) {
289399ebb4caSwyllys 		pkey = openssl_load_key(handle, path);
289499ebb4caSwyllys 		if (pkey == NULL) {
289599ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
289699ebb4caSwyllys 		}
289799ebb4caSwyllys 		if (key != NULL) {
2898300fdee2SAndy Fiddaman 			if (EVP_PKEY_get0_RSA(pkey) != NULL)
289999ebb4caSwyllys 				key->keyalg = KMF_RSA;
2900300fdee2SAndy Fiddaman 			else if (EVP_PKEY_get0_DSA(pkey) != NULL)
290199ebb4caSwyllys 				key->keyalg = KMF_DSA;
290299ebb4caSwyllys 
290399ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
290499ebb4caSwyllys 			key->keyclass = keyclass;
290599ebb4caSwyllys 			key->keyp = (void *)pkey;
290699ebb4caSwyllys 			key->israw = FALSE;
29075b3e1433Swyllys 			if (path != NULL &&
29085b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
29095b3e1433Swyllys 				EVP_PKEY_free(pkey);
29105b3e1433Swyllys 				return (KMF_ERR_MEMORY);
29115b3e1433Swyllys 			}
291299ebb4caSwyllys 		} else {
291399ebb4caSwyllys 			EVP_PKEY_free(pkey);
291499ebb4caSwyllys 			pkey = NULL;
291599ebb4caSwyllys 		}
291699ebb4caSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
291799ebb4caSwyllys 		KMF_ENCODE_FORMAT fmt;
291899ebb4caSwyllys 		/*
291999ebb4caSwyllys 		 * If the file is a recognized format,
292099ebb4caSwyllys 		 * then it is NOT a symmetric key.
292199ebb4caSwyllys 		 */
292230a5e8faSwyllys 		rv = kmf_get_file_format(path, &fmt);
292399ebb4caSwyllys 		if (rv == KMF_OK || fmt != 0) {
292499ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
292599ebb4caSwyllys 		} else if (rv == KMF_ERR_ENCODING) {
292699ebb4caSwyllys 			/*
292799ebb4caSwyllys 			 * If we don't know the encoding,
292899ebb4caSwyllys 			 * it is probably  a symmetric key.
292999ebb4caSwyllys 			 */
293099ebb4caSwyllys 			rv = KMF_OK;
293130a5e8faSwyllys 		} else if (rv == KMF_ERR_OPEN_FILE) {
293230a5e8faSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
293399ebb4caSwyllys 		}
293499ebb4caSwyllys 
293599ebb4caSwyllys 		if (key != NULL) {
293699ebb4caSwyllys 			KMF_DATA keyvalue;
293799ebb4caSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
293899ebb4caSwyllys 			if (rkey == NULL) {
293999ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
294099ebb4caSwyllys 				goto out;
294199ebb4caSwyllys 			}
294299ebb4caSwyllys 
294399ebb4caSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
294430a5e8faSwyllys 			rv = kmf_read_input_file(handle, path, &keyvalue);
294599ebb4caSwyllys 			if (rv != KMF_OK)
294699ebb4caSwyllys 				goto out;
294799ebb4caSwyllys 
294899ebb4caSwyllys 			rkey->keydata.len = keyvalue.Length;
294999ebb4caSwyllys 			rkey->keydata.val = keyvalue.Data;
295099ebb4caSwyllys 
295199ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
295299ebb4caSwyllys 			key->keyclass = keyclass;
295399ebb4caSwyllys 			key->israw = TRUE;
295499ebb4caSwyllys 			key->keyp = (void *)rkey;
29555b3e1433Swyllys 			if (path != NULL &&
29565b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
29575b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
29585b3e1433Swyllys 			}
295999ebb4caSwyllys 		}
296099ebb4caSwyllys 	}
296199ebb4caSwyllys out:
296299ebb4caSwyllys 	if (rv != KMF_OK) {
296399ebb4caSwyllys 		if (rkey != NULL) {
296430a5e8faSwyllys 			kmf_free_raw_sym_key(rkey);
296599ebb4caSwyllys 		}
296699ebb4caSwyllys 		if (pkey != NULL)
296799ebb4caSwyllys 			EVP_PKEY_free(pkey);
296899ebb4caSwyllys 
296999ebb4caSwyllys 		if (key != NULL) {
297099ebb4caSwyllys 			key->keyalg = KMF_KEYALG_NONE;
297199ebb4caSwyllys 			key->keyclass = KMF_KEYCLASS_NONE;
297299ebb4caSwyllys 			key->keyp = NULL;
297399ebb4caSwyllys 		}
297499ebb4caSwyllys 	}
297599ebb4caSwyllys 
297699ebb4caSwyllys 	return (rv);
297799ebb4caSwyllys }
297899ebb4caSwyllys 
297999ebb4caSwyllys KMF_RETURN
298030a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle,
298130a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
298299ebb4caSwyllys {
298399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
298499ebb4caSwyllys 	char *fullpath = NULL;
2985f482c776Swyllys 	uint32_t maxkeys;
298630a5e8faSwyllys 	KMF_KEY_HANDLE *key;
298730a5e8faSwyllys 	uint32_t *numkeys;
298830a5e8faSwyllys 	KMF_KEY_CLASS keyclass;
298930a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
299030a5e8faSwyllys 	char *dirpath;
299130a5e8faSwyllys 	char *keyfile;
299299ebb4caSwyllys 
299330a5e8faSwyllys 	if (handle == NULL)
299499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
299599ebb4caSwyllys 
299630a5e8faSwyllys 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
299730a5e8faSwyllys 	if (numkeys == NULL)
299830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
299930a5e8faSwyllys 
300030a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
300130a5e8faSwyllys 	    (void *)&keyclass, NULL);
300230a5e8faSwyllys 	if (rv != KMF_OK)
300330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
300430a5e8faSwyllys 
300530a5e8faSwyllys 	if (keyclass != KMF_ASYM_PUB &&
300630a5e8faSwyllys 	    keyclass != KMF_ASYM_PRI &&
300730a5e8faSwyllys 	    keyclass != KMF_SYMMETRIC)
300899ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
300999ebb4caSwyllys 
301030a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
301130a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
301230a5e8faSwyllys 
301330a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
301499ebb4caSwyllys 
301599ebb4caSwyllys 	if (fullpath == NULL)
301699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
301799ebb4caSwyllys 
3018f482c776Swyllys 	maxkeys = *numkeys;
3019f482c776Swyllys 	if (maxkeys == 0)
3020f482c776Swyllys 		maxkeys = 0xFFFFFFFF;
302199ebb4caSwyllys 	*numkeys = 0;
302299ebb4caSwyllys 
302330a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
302430a5e8faSwyllys 	/* it is okay to have "keys" contains NULL */
302530a5e8faSwyllys 
302630a5e8faSwyllys 	/*
302730a5e8faSwyllys 	 * The caller may want a list of the raw key data as well.
302830a5e8faSwyllys 	 * Useful for importing keys from a file into other keystores.
302930a5e8faSwyllys 	 */
303030a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
303130a5e8faSwyllys 
303299ebb4caSwyllys 	if (isdir(fullpath)) {
303399ebb4caSwyllys 		DIR *dirp;
303499ebb4caSwyllys 		struct dirent *dp;
303599ebb4caSwyllys 		int n = 0;
303699ebb4caSwyllys 
303799ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
303899ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
303999ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
304099ebb4caSwyllys 		}
304199ebb4caSwyllys 		rewinddir(dirp);
3042f482c776Swyllys 		while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
304399ebb4caSwyllys 			if (strcmp(dp->d_name, ".") &&
304499ebb4caSwyllys 			    strcmp(dp->d_name, "..")) {
304599ebb4caSwyllys 				char *fname;
304699ebb4caSwyllys 
304799ebb4caSwyllys 				fname = get_fullpath(fullpath,
304899ebb4caSwyllys 				    (char *)&dp->d_name);
304999ebb4caSwyllys 
305099ebb4caSwyllys 				rv = fetch_key(handle, fname,
305130a5e8faSwyllys 				    keyclass, key ? &key[n] : NULL);
305299ebb4caSwyllys 
305330a5e8faSwyllys 				if (rv == KMF_OK) {
305430a5e8faSwyllys 					if (key != NULL && rawkey != NULL)
305530a5e8faSwyllys 						rv = convertToRawKey(
305630a5e8faSwyllys 						    key[n].keyp, &rawkey[n]);
305799ebb4caSwyllys 					n++;
305830a5e8faSwyllys 				}
305999ebb4caSwyllys 
306099ebb4caSwyllys 				if (rv != KMF_OK || key == NULL)
306199ebb4caSwyllys 					free(fname);
306299ebb4caSwyllys 			}
306399ebb4caSwyllys 		}
306499ebb4caSwyllys 		(void) closedir(dirp);
306599ebb4caSwyllys 		free(fullpath);
306699ebb4caSwyllys 		(*numkeys) = n;
306799ebb4caSwyllys 	} else {
306830a5e8faSwyllys 		rv = fetch_key(handle, fullpath, keyclass, key);
306999ebb4caSwyllys 		if (rv == KMF_OK)
307099ebb4caSwyllys 			(*numkeys) = 1;
307199ebb4caSwyllys 
307299ebb4caSwyllys 		if (rv != KMF_OK || key == NULL)
307399ebb4caSwyllys 			free(fullpath);
307430a5e8faSwyllys 
307530a5e8faSwyllys 		if (rv == KMF_OK && key != NULL && rawkey != NULL) {
307630a5e8faSwyllys 			rv = convertToRawKey(key->keyp, rawkey);
307730a5e8faSwyllys 		}
307899ebb4caSwyllys 	}
307999ebb4caSwyllys 
3080f482c776Swyllys 	if (rv == KMF_OK && (*numkeys) == 0)
308199ebb4caSwyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
308273cc0e02Swyllys 	else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
308373cc0e02Swyllys 		rv = KMF_OK;
308499ebb4caSwyllys 
308599ebb4caSwyllys 	return (rv);
308699ebb4caSwyllys }
308799ebb4caSwyllys 
308899ebb4caSwyllys #define	HANDLE_PK12_ERROR { \
308999ebb4caSwyllys 	SET_ERROR(kmfh, ERR_get_error()); \
309099ebb4caSwyllys 	rv = KMF_ERR_ENCODING; \
309199ebb4caSwyllys 	goto out; \
309299ebb4caSwyllys }
309399ebb4caSwyllys 
30945b3e1433Swyllys static int
30955b3e1433Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
309699ebb4caSwyllys {
3097300fdee2SAndy Fiddaman 	unsigned char *alias;
3098300fdee2SAndy Fiddaman 	int len;
3099300fdee2SAndy Fiddaman 
3100300fdee2SAndy Fiddaman 	if (xcert != NULL && (alias = X509_alias_get0(xcert, &len)) != NULL) {
31015b3e1433Swyllys 		if (PKCS12_add_friendlyname_asc(bag,
3102300fdee2SAndy Fiddaman 		    (const char *)alias, len) == 0)
31035b3e1433Swyllys 			return (0);
31045b3e1433Swyllys 	}
31055b3e1433Swyllys 	return (1);
31065b3e1433Swyllys }
31075b3e1433Swyllys 
31085b3e1433Swyllys static PKCS7 *
31095b3e1433Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
31105b3e1433Swyllys 	uchar_t *keyid, unsigned int keyidlen)
31115b3e1433Swyllys {
311299ebb4caSwyllys 	PKCS12_SAFEBAG *bag = NULL;
311399ebb4caSwyllys 	PKCS7 *cert_authsafe = NULL;
31145b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack;
311599ebb4caSwyllys 
311699ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
311799ebb4caSwyllys 	if (bag_stack == NULL)
31185b3e1433Swyllys 		return (NULL);
311999ebb4caSwyllys 
312099ebb4caSwyllys 	/* Convert cert from X509 struct to PKCS#12 bag */
3121300fdee2SAndy Fiddaman 	bag = PKCS12_SAFEBAG_create_cert(sslcert);
312299ebb4caSwyllys 	if (bag == NULL) {
31235b3e1433Swyllys 		goto out;
312499ebb4caSwyllys 	}
312599ebb4caSwyllys 
312699ebb4caSwyllys 	/* Add the key id to the certificate bag. */
31275b3e1433Swyllys 	if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
31285b3e1433Swyllys 		goto out;
312999ebb4caSwyllys 	}
313099ebb4caSwyllys 
31315b3e1433Swyllys 	if (!add_alias_to_bag(bag, sslcert))
31325b3e1433Swyllys 		goto out;
31335b3e1433Swyllys 
313499ebb4caSwyllys 	/* Pile it on the bag_stack. */
313599ebb4caSwyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
31365b3e1433Swyllys 		goto out;
313799ebb4caSwyllys 	}
313899ebb4caSwyllys 	/* Turn bag_stack of certs into encrypted authsafe. */
313999ebb4caSwyllys 	cert_authsafe = PKCS12_pack_p7encdata(
314099ebb4caSwyllys 	    NID_pbe_WithSHA1And40BitRC2_CBC,
314134acef67Swyllys 	    cred->cred, cred->credlen, NULL, 0,
314234acef67Swyllys 	    PKCS12_DEFAULT_ITER, bag_stack);
314399ebb4caSwyllys 
31445b3e1433Swyllys out:
31455b3e1433Swyllys 	if (bag_stack != NULL)
314699ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
314799ebb4caSwyllys 
31485b3e1433Swyllys 	return (cert_authsafe);
314999ebb4caSwyllys }
31505b3e1433Swyllys 
31515b3e1433Swyllys static PKCS7 *
31525b3e1433Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
31535b3e1433Swyllys 	uchar_t *keyid,  unsigned int keyidlen,
31545b3e1433Swyllys 	char *label, int label_len)
31555b3e1433Swyllys {
31565b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
31575b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
31585b3e1433Swyllys 	PKCS12_SAFEBAG *bag = NULL;
31595b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
31605b3e1433Swyllys 
316199ebb4caSwyllys 	p8 = EVP_PKEY2PKCS8(pkey);
316299ebb4caSwyllys 	if (p8 == NULL) {
31635b3e1433Swyllys 		return (NULL);
316499ebb4caSwyllys 	}
316599ebb4caSwyllys 	/* Put the shrouded key into a PKCS#12 bag. */
3166300fdee2SAndy Fiddaman 	bag = PKCS12_SAFEBAG_create_pkcs8_encrypt(
316799ebb4caSwyllys 	    NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
316899ebb4caSwyllys 	    cred->cred, cred->credlen,
316999ebb4caSwyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, p8);
317099ebb4caSwyllys 
317199ebb4caSwyllys 	/* Clean up the PKCS#8 shrouded key, don't need it now. */
317299ebb4caSwyllys 	PKCS8_PRIV_KEY_INFO_free(p8);
317399ebb4caSwyllys 	p8 = NULL;
317499ebb4caSwyllys 
317599ebb4caSwyllys 	if (bag == NULL) {
31765b3e1433Swyllys 		return (NULL);
317799ebb4caSwyllys 	}
31785b3e1433Swyllys 	if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
31795b3e1433Swyllys 		goto out;
31805b3e1433Swyllys 	if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
31815b3e1433Swyllys 		goto out;
31825b3e1433Swyllys 
318399ebb4caSwyllys 	/* Start a PKCS#12 safebag container for the private key. */
318499ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
31855b3e1433Swyllys 	if (bag_stack == NULL)
31865b3e1433Swyllys 		goto out;
318799ebb4caSwyllys 
318899ebb4caSwyllys 	/* Pile on the private key on the bag_stack. */
31895b3e1433Swyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
31905b3e1433Swyllys 		goto out;
31915b3e1433Swyllys 
319299ebb4caSwyllys 	key_authsafe = PKCS12_pack_p7data(bag_stack);
319399ebb4caSwyllys 
31945b3e1433Swyllys out:
31955b3e1433Swyllys 	if (bag_stack != NULL)
319699ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
319799ebb4caSwyllys 	bag_stack = NULL;
31985b3e1433Swyllys 	return (key_authsafe);
319999ebb4caSwyllys }
320099ebb4caSwyllys 
320199ebb4caSwyllys static EVP_PKEY *
320299ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
320399ebb4caSwyllys {
320499ebb4caSwyllys 	RSA		*rsa = NULL;
320599ebb4caSwyllys 	EVP_PKEY	*newkey = NULL;
3206300fdee2SAndy Fiddaman 	BIGNUM		*n = NULL, *e = NULL, *d = NULL,
3207300fdee2SAndy Fiddaman 			*p = NULL, *q = NULL,
3208300fdee2SAndy Fiddaman 			*dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
320999ebb4caSwyllys 
321099ebb4caSwyllys 	if ((rsa = RSA_new()) == NULL)
3211300fdee2SAndy Fiddaman 		goto cleanup;
321299ebb4caSwyllys 
3213300fdee2SAndy Fiddaman 	if ((n = BN_bin2bn(key->mod.val, key->mod.len, NULL)) == NULL)
3214300fdee2SAndy Fiddaman 		goto cleanup;
321599ebb4caSwyllys 
3216300fdee2SAndy Fiddaman 	if ((e = BN_bin2bn(key->pubexp.val, key->pubexp.len, NULL)) == NULL)
3217300fdee2SAndy Fiddaman 		goto cleanup;
321899ebb4caSwyllys 
3219300fdee2SAndy Fiddaman 	if (key->priexp.val != NULL &&
3220300fdee2SAndy Fiddaman 	    (d = BN_bin2bn(key->priexp.val, key->priexp.len, NULL)) == NULL)
3221300fdee2SAndy Fiddaman 		goto cleanup;
322299ebb4caSwyllys 
3223300fdee2SAndy Fiddaman 	if (key->prime1.val != NULL &&
3224300fdee2SAndy Fiddaman 	    (p = BN_bin2bn(key->prime1.val, key->prime1.len, NULL)) == NULL)
3225300fdee2SAndy Fiddaman 		goto cleanup;
322699ebb4caSwyllys 
3227300fdee2SAndy Fiddaman 	if (key->prime2.val != NULL &&
3228300fdee2SAndy Fiddaman 	    (q = BN_bin2bn(key->prime2.val, key->prime2.len, NULL)) == NULL)
3229300fdee2SAndy Fiddaman 		goto cleanup;
323099ebb4caSwyllys 
3231300fdee2SAndy Fiddaman 	if (key->exp1.val != NULL &&
3232300fdee2SAndy Fiddaman 	    (dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len, NULL)) == NULL)
3233300fdee2SAndy Fiddaman 		goto cleanup;
323499ebb4caSwyllys 
3235300fdee2SAndy Fiddaman 	if (key->exp2.val != NULL &&
3236300fdee2SAndy Fiddaman 	    (dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len, NULL)) == NULL)
3237300fdee2SAndy Fiddaman 		goto cleanup;
323899ebb4caSwyllys 
3239300fdee2SAndy Fiddaman 	if (key->coef.val != NULL &&
3240300fdee2SAndy Fiddaman 	    (iqmp = BN_bin2bn(key->coef.val, key->coef.len, NULL)) == NULL)
3241300fdee2SAndy Fiddaman 		goto cleanup;
3242300fdee2SAndy Fiddaman 
3243300fdee2SAndy Fiddaman 	if (RSA_set0_key(rsa, n, e, d) == 0)
3244300fdee2SAndy Fiddaman 		goto cleanup;
3245300fdee2SAndy Fiddaman 	n = e = d = NULL;
3246300fdee2SAndy Fiddaman 	if (RSA_set0_factors(rsa, p, q) == 0)
3247300fdee2SAndy Fiddaman 		goto cleanup;
3248300fdee2SAndy Fiddaman 	p = q = NULL;
3249300fdee2SAndy Fiddaman 	if (RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp) == 0)
3250300fdee2SAndy Fiddaman 		goto cleanup;
3251300fdee2SAndy Fiddaman 	dmp1 = dmq1 = iqmp = NULL;
325299ebb4caSwyllys 
325399ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
3254300fdee2SAndy Fiddaman 		goto cleanup;
325599ebb4caSwyllys 
325699ebb4caSwyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
325799ebb4caSwyllys 
3258300fdee2SAndy Fiddaman cleanup:
325999ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
3260300fdee2SAndy Fiddaman 	if (rsa)
326199ebb4caSwyllys 		RSA_free(rsa);
3262300fdee2SAndy Fiddaman 	BN_free(n);
3263300fdee2SAndy Fiddaman 	BN_free(e);
3264300fdee2SAndy Fiddaman 	BN_free(d);
3265300fdee2SAndy Fiddaman 	BN_free(p);
3266300fdee2SAndy Fiddaman 	BN_free(q);
3267300fdee2SAndy Fiddaman 	BN_free(dmp1);
3268300fdee2SAndy Fiddaman 	BN_free(dmq1);
3269300fdee2SAndy Fiddaman 	BN_free(iqmp);
327099ebb4caSwyllys 
327199ebb4caSwyllys 	return (newkey);
327299ebb4caSwyllys }
327399ebb4caSwyllys 
327499ebb4caSwyllys static EVP_PKEY *
327599ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
327699ebb4caSwyllys {
327799ebb4caSwyllys 	DSA		*dsa = NULL;
327899ebb4caSwyllys 	EVP_PKEY	*newkey = NULL;
3279300fdee2SAndy Fiddaman 	BIGNUM		*p = NULL, *q = NULL, *g = NULL,
3280300fdee2SAndy Fiddaman 			*priv_key = NULL, *pub_key = NULL;
328199ebb4caSwyllys 
328299ebb4caSwyllys 	if ((dsa = DSA_new()) == NULL)
3283300fdee2SAndy Fiddaman 		goto cleanup;
328499ebb4caSwyllys 
3285300fdee2SAndy Fiddaman 	if ((p = BN_bin2bn(key->prime.val, key->prime.len, NULL)) == NULL)
3286300fdee2SAndy Fiddaman 		goto cleanup;
328799ebb4caSwyllys 
3288300fdee2SAndy Fiddaman 	if ((q = BN_bin2bn(key->subprime.val, key->subprime.len, NULL)) == NULL)
3289300fdee2SAndy Fiddaman 		goto cleanup;
329099ebb4caSwyllys 
3291300fdee2SAndy Fiddaman 	if ((g = BN_bin2bn(key->base.val, key->base.len, NULL)) == NULL)
3292300fdee2SAndy Fiddaman 		goto cleanup;
329399ebb4caSwyllys 
3294300fdee2SAndy Fiddaman 	if ((priv_key = BN_bin2bn(key->value.val, key->value.len,
3295300fdee2SAndy Fiddaman 	    NULL)) == NULL)
3296300fdee2SAndy Fiddaman 		goto cleanup;
329799ebb4caSwyllys 
3298300fdee2SAndy Fiddaman 	if (key->pubvalue.val != NULL && (pub_key =
3299300fdee2SAndy Fiddaman 	    BN_bin2bn(key->pubvalue.val, key->pubvalue.len, NULL)) == NULL)
3300300fdee2SAndy Fiddaman 		goto cleanup;
3301300fdee2SAndy Fiddaman 
3302300fdee2SAndy Fiddaman 	if (DSA_set0_pqg(dsa, p, q, g) == 0)
3303300fdee2SAndy Fiddaman 		goto cleanup;
3304300fdee2SAndy Fiddaman 	p = q = g = NULL;
3305300fdee2SAndy Fiddaman 	if (DSA_set0_key(dsa, pub_key, priv_key) == 0)
3306300fdee2SAndy Fiddaman 		goto cleanup;
3307300fdee2SAndy Fiddaman 	pub_key = priv_key = 0;
330830a5e8faSwyllys 
330999ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
3310300fdee2SAndy Fiddaman 		goto cleanup;
331199ebb4caSwyllys 
331299ebb4caSwyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
331399ebb4caSwyllys 
3314300fdee2SAndy Fiddaman cleanup:
331599ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
3316300fdee2SAndy Fiddaman 	if (dsa)
331799ebb4caSwyllys 		DSA_free(dsa);
3318300fdee2SAndy Fiddaman 	BN_free(p);
3319300fdee2SAndy Fiddaman 	BN_free(q);
3320300fdee2SAndy Fiddaman 	BN_free(g);
3321300fdee2SAndy Fiddaman 	BN_free(priv_key);
3322300fdee2SAndy Fiddaman 	BN_free(pub_key);
3323300fdee2SAndy Fiddaman 
332499ebb4caSwyllys 	return (newkey);
332599ebb4caSwyllys }
332699ebb4caSwyllys 
33275b3e1433Swyllys static EVP_PKEY *
33285b3e1433Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key)
33295b3e1433Swyllys {
33305b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
33315b3e1433Swyllys 	KMF_RAW_KEY_DATA *rawkey;
33325b3e1433Swyllys 	ASN1_TYPE *attr = NULL;
33335b3e1433Swyllys 	KMF_RETURN ret;
33345b3e1433Swyllys 
33355b3e1433Swyllys 	if (key == NULL || !key->israw)
33365b3e1433Swyllys 		return (NULL);
33375b3e1433Swyllys 
33385b3e1433Swyllys 	rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
33395b3e1433Swyllys 	if (rawkey->keytype == KMF_RSA) {
33405b3e1433Swyllys 		pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
33415b3e1433Swyllys 	} else if (rawkey->keytype == KMF_DSA) {
33425b3e1433Swyllys 		pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
3343e65e5c2dSWyllys Ingersoll 	} else if (rawkey->keytype == KMF_ECDSA) {
3344e65e5c2dSWyllys Ingersoll 		/*
3345e65e5c2dSWyllys Ingersoll 		 * OpenSSL in Solaris does not support EC for
3346e65e5c2dSWyllys Ingersoll 		 * legal reasons
3347e65e5c2dSWyllys Ingersoll 		 */
3348e65e5c2dSWyllys Ingersoll 		return (NULL);
33495b3e1433Swyllys 	} else {
33505b3e1433Swyllys 		/* wrong kind of key */
33515b3e1433Swyllys 		return (NULL);
33525b3e1433Swyllys 	}
33535b3e1433Swyllys 
33545b3e1433Swyllys 	if (rawkey->label != NULL) {
33555b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
33565b3e1433Swyllys 			EVP_PKEY_free(pkey);
33575b3e1433Swyllys 			return (NULL);
33585b3e1433Swyllys 		}
33595b3e1433Swyllys 		attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
33605b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
33615b3e1433Swyllys 		    strlen(rawkey->label));
33625b3e1433Swyllys 		attr->type = V_ASN1_BMPSTRING;
33635b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.bmpstring;
33645b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
33655b3e1433Swyllys 		if (ret != KMF_OK) {
33665b3e1433Swyllys 			EVP_PKEY_free(pkey);
33675b3e1433Swyllys 			ASN1_TYPE_free(attr);
33685b3e1433Swyllys 			return (NULL);
33695b3e1433Swyllys 		}
33705b3e1433Swyllys 	}
33715b3e1433Swyllys 	if (rawkey->id.Data != NULL) {
33725b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
33735b3e1433Swyllys 			EVP_PKEY_free(pkey);
33745b3e1433Swyllys 			return (NULL);
33755b3e1433Swyllys 		}
33765b3e1433Swyllys 		attr->value.octet_string =
33775b3e1433Swyllys 		    ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
33785b3e1433Swyllys 		attr->type = V_ASN1_OCTET_STRING;
33795b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.octet_string,
33805b3e1433Swyllys 		    rawkey->id.Data, rawkey->id.Length);
33815b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.octet_string;
33825b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
33835b3e1433Swyllys 		if (ret != KMF_OK) {
33845b3e1433Swyllys 			EVP_PKEY_free(pkey);
33855b3e1433Swyllys 			ASN1_TYPE_free(attr);
33865b3e1433Swyllys 			return (NULL);
33875b3e1433Swyllys 		}
33885b3e1433Swyllys 	}
33895b3e1433Swyllys 	return (pkey);
33905b3e1433Swyllys }
33915b3e1433Swyllys 
33925b3e1433Swyllys /*
33935b3e1433Swyllys  * Search a list of private keys to find one that goes with the certificate.
33945b3e1433Swyllys  */
33955b3e1433Swyllys static EVP_PKEY *
33965b3e1433Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
33975b3e1433Swyllys {
33985b3e1433Swyllys 	int i;
33995b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
34005b3e1433Swyllys 
34015b3e1433Swyllys 	if (numkeys == 0 || keylist == NULL || xcert == NULL)
34025b3e1433Swyllys 		return (NULL);
34035b3e1433Swyllys 	for (i = 0; i < numkeys; i++) {
34045b3e1433Swyllys 		if (keylist[i].israw)
34055b3e1433Swyllys 			pkey = raw_key_to_pkey(&keylist[i]);
34065b3e1433Swyllys 		else
34075b3e1433Swyllys 			pkey = (EVP_PKEY *)keylist[i].keyp;
34085b3e1433Swyllys 		if (pkey != NULL) {
34095b3e1433Swyllys 			if (X509_check_private_key(xcert, pkey)) {
34105b3e1433Swyllys 				return (pkey);
34115b3e1433Swyllys 			} else {
34125b3e1433Swyllys 				EVP_PKEY_free(pkey);
34135b3e1433Swyllys 				pkey = NULL;
34145b3e1433Swyllys 			}
34155b3e1433Swyllys 		}
34165b3e1433Swyllys 	}
34175b3e1433Swyllys 	return (pkey);
34185b3e1433Swyllys }
34195b3e1433Swyllys 
342099ebb4caSwyllys static KMF_RETURN
34215b3e1433Swyllys local_export_pk12(KMF_HANDLE_T handle,
342299ebb4caSwyllys 	KMF_CREDENTIAL *cred,
342399ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
342499ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
342599ebb4caSwyllys 	char *filename)
342699ebb4caSwyllys {
342799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
342899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
342999ebb4caSwyllys 	BIO *bio = NULL;
34305b3e1433Swyllys 	PKCS7 *cert_authsafe = NULL;
34315b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
34325b3e1433Swyllys 	STACK_OF(PKCS7) *authsafe_stack = NULL;
34335b3e1433Swyllys 	PKCS12 *p12_elem = NULL;
343499ebb4caSwyllys 	int i;
343599ebb4caSwyllys 
34365b3e1433Swyllys 	if (numcerts == 0 && numkeys == 0)
34375b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
34385b3e1433Swyllys 
343999ebb4caSwyllys 	/*
344099ebb4caSwyllys 	 * Open the output file.
344199ebb4caSwyllys 	 */
344299ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
344399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
344499ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
344599ebb4caSwyllys 		goto cleanup;
344699ebb4caSwyllys 	}
344799ebb4caSwyllys 
34485b3e1433Swyllys 	/* Start a PKCS#7 stack. */
34495b3e1433Swyllys 	authsafe_stack = sk_PKCS7_new_null();
34505b3e1433Swyllys 	if (authsafe_stack == NULL) {
34515b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
34525b3e1433Swyllys 		goto cleanup;
34535b3e1433Swyllys 	}
34545b3e1433Swyllys 	if (numcerts > 0) {
345599ebb4caSwyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
345699ebb4caSwyllys 			const uchar_t *p = certlist[i].certificate.Data;
345799ebb4caSwyllys 			long len = certlist[i].certificate.Length;
34585b3e1433Swyllys 			X509 *xcert = NULL;
34595b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
34605b3e1433Swyllys 			unsigned char keyid[EVP_MAX_MD_SIZE];
34615b3e1433Swyllys 			unsigned int keyidlen = 0;
346299ebb4caSwyllys 
346399ebb4caSwyllys 			xcert = d2i_X509(NULL, &p, len);
346499ebb4caSwyllys 			if (xcert == NULL) {
346599ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
346699ebb4caSwyllys 				rv = KMF_ERR_ENCODING;
346799ebb4caSwyllys 			}
34685b3e1433Swyllys 			if (certlist[i].kmf_private.label != NULL) {
34695b3e1433Swyllys 				/* Set alias attribute */
34705b3e1433Swyllys 				(void) X509_alias_set1(xcert,
34715b3e1433Swyllys 				    (uchar_t *)certlist[i].kmf_private.label,
34725b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label));
34735b3e1433Swyllys 			}
34745b3e1433Swyllys 			/* Check if there is a key corresponding to this cert */
34755b3e1433Swyllys 			pkey = find_matching_key(xcert, numkeys, keylist);
34765b3e1433Swyllys 
34775b3e1433Swyllys 			/*
34785b3e1433Swyllys 			 * If key is found, get fingerprint and create a
34795b3e1433Swyllys 			 * safebag.
34805b3e1433Swyllys 			 */
34815b3e1433Swyllys 			if (pkey != NULL) {
34825b3e1433Swyllys 				(void) X509_digest(xcert, EVP_sha1(),
34835b3e1433Swyllys 				    keyid, &keyidlen);
34845b3e1433Swyllys 				key_authsafe = add_key_to_safe(pkey, cred,
34855b3e1433Swyllys 				    keyid, keyidlen,
34865b3e1433Swyllys 				    certlist[i].kmf_private.label,
34875b3e1433Swyllys 				    (certlist[i].kmf_private.label ?
34885b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label) : 0));
34895b3e1433Swyllys 
34905b3e1433Swyllys 				if (key_authsafe == NULL) {
34915b3e1433Swyllys 					X509_free(xcert);
34925b3e1433Swyllys 					EVP_PKEY_free(pkey);
34935b3e1433Swyllys 					goto cleanup;
34945b3e1433Swyllys 				}
34955b3e1433Swyllys 				/* Put the key safe into the Auth Safe */
34965b3e1433Swyllys 				if (!sk_PKCS7_push(authsafe_stack,
34975b3e1433Swyllys 				    key_authsafe)) {
34985b3e1433Swyllys 					X509_free(xcert);
34995b3e1433Swyllys 					EVP_PKEY_free(pkey);
35005b3e1433Swyllys 					goto cleanup;
35015b3e1433Swyllys 				}
35025b3e1433Swyllys 			}
35035b3e1433Swyllys 
35045b3e1433Swyllys 			/* create a certificate safebag */
35055b3e1433Swyllys 			cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
35065b3e1433Swyllys 			    keyidlen);
35075b3e1433Swyllys 			if (cert_authsafe == NULL) {
35085b3e1433Swyllys 				X509_free(xcert);
35095b3e1433Swyllys 				EVP_PKEY_free(pkey);
35105b3e1433Swyllys 				goto cleanup;
35115b3e1433Swyllys 			}
35125b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
35135b3e1433Swyllys 				X509_free(xcert);
35145b3e1433Swyllys 				EVP_PKEY_free(pkey);
35155b3e1433Swyllys 				goto cleanup;
35165b3e1433Swyllys 			}
35175b3e1433Swyllys 
351899ebb4caSwyllys 			X509_free(xcert);
351999ebb4caSwyllys 			if (pkey)
352099ebb4caSwyllys 				EVP_PKEY_free(pkey);
352199ebb4caSwyllys 		}
35225b3e1433Swyllys 	} else if (numcerts == 0 && numkeys > 0) {
35235b3e1433Swyllys 		/*
35245b3e1433Swyllys 		 * If only adding keys to the file.
35255b3e1433Swyllys 		 */
35265b3e1433Swyllys 		for (i = 0; i < numkeys; i++) {
35275b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
35285b3e1433Swyllys 
35295b3e1433Swyllys 			if (keylist[i].israw)
35305b3e1433Swyllys 				pkey = raw_key_to_pkey(&keylist[i]);
35315b3e1433Swyllys 			else
35325b3e1433Swyllys 				pkey = (EVP_PKEY *)keylist[i].keyp;
35335b3e1433Swyllys 
35345b3e1433Swyllys 			if (pkey == NULL)
35355b3e1433Swyllys 				continue;
35365b3e1433Swyllys 
35375b3e1433Swyllys 			key_authsafe = add_key_to_safe(pkey, cred,
35385b3e1433Swyllys 			    NULL, 0, NULL, 0);
35395b3e1433Swyllys 
35405b3e1433Swyllys 			if (key_authsafe == NULL) {
35415b3e1433Swyllys 				EVP_PKEY_free(pkey);
35425b3e1433Swyllys 				goto cleanup;
35435b3e1433Swyllys 			}
35445b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
35455b3e1433Swyllys 				EVP_PKEY_free(pkey);
35465b3e1433Swyllys 				goto cleanup;
35475b3e1433Swyllys 			}
35485b3e1433Swyllys 		}
35495b3e1433Swyllys 	}
35505b3e1433Swyllys 	p12_elem = PKCS12_init(NID_pkcs7_data);
35515b3e1433Swyllys 	if (p12_elem == NULL) {
35525b3e1433Swyllys 		goto cleanup;
355399ebb4caSwyllys 	}
355499ebb4caSwyllys 
35555b3e1433Swyllys 	/* Put the PKCS#7 stack into the PKCS#12 element. */
35565b3e1433Swyllys 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
35575b3e1433Swyllys 		goto cleanup;
35585b3e1433Swyllys 	}
35595b3e1433Swyllys 
35605b3e1433Swyllys 	/* Set the integrity MAC on the PKCS#12 element. */
35615b3e1433Swyllys 	if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
35625b3e1433Swyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
35635b3e1433Swyllys 		goto cleanup;
35645b3e1433Swyllys 	}
35655b3e1433Swyllys 
35665b3e1433Swyllys 	/* Write the PKCS#12 element to the export file. */
35675b3e1433Swyllys 	if (!i2d_PKCS12_bio(bio, p12_elem)) {
35685b3e1433Swyllys 		goto cleanup;
35695b3e1433Swyllys 	}
35705b3e1433Swyllys 	PKCS12_free(p12_elem);
35715b3e1433Swyllys 
357299ebb4caSwyllys cleanup:
35735b3e1433Swyllys 	/* Clear away the PKCS#7 stack, we're done with it. */
35745b3e1433Swyllys 	if (authsafe_stack)
35755b3e1433Swyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
357699ebb4caSwyllys 
357799ebb4caSwyllys 	if (bio != NULL)
357899ebb4caSwyllys 		(void) BIO_free_all(bio);
357999ebb4caSwyllys 
358099ebb4caSwyllys 	return (rv);
358199ebb4caSwyllys }
358299ebb4caSwyllys 
358399ebb4caSwyllys KMF_RETURN
358430a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
358530a5e8faSwyllys     KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
358630a5e8faSwyllys     KMF_CREDENTIAL *p12cred, char *filename)
358730a5e8faSwyllys {
358830a5e8faSwyllys 	KMF_RETURN rv;
358930a5e8faSwyllys 
359030a5e8faSwyllys 	if (certlist == NULL && keylist == NULL)
359130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
359230a5e8faSwyllys 
35935b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, numcerts, certlist,
359430a5e8faSwyllys 	    numkeys, keylist, filename);
359530a5e8faSwyllys 
359630a5e8faSwyllys 	return (rv);
359730a5e8faSwyllys }
359830a5e8faSwyllys 
359930a5e8faSwyllys KMF_RETURN
360030a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
360199ebb4caSwyllys {
360299ebb4caSwyllys 	KMF_RETURN rv;
360399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
360499ebb4caSwyllys 	char *fullpath = NULL;
360530a5e8faSwyllys 	char *dirpath = NULL;
360630a5e8faSwyllys 	char *certfile = NULL;
360730a5e8faSwyllys 	char *keyfile = NULL;
360830a5e8faSwyllys 	char *filename = NULL;
360930a5e8faSwyllys 	KMF_CREDENTIAL *p12cred = NULL;
36105b3e1433Swyllys 	KMF_X509_DER_CERT certdata;
36115b3e1433Swyllys 	KMF_KEY_HANDLE key;
36125b3e1433Swyllys 	int gotkey = 0;
36135b3e1433Swyllys 	int gotcert = 0;
361430a5e8faSwyllys 
361530a5e8faSwyllys 	if (handle == NULL)
361630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
361799ebb4caSwyllys 
361899ebb4caSwyllys 	/*
361999ebb4caSwyllys 	 *  First, find the certificate.
362099ebb4caSwyllys 	 */
362130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
362230a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
362330a5e8faSwyllys 	if (certfile != NULL) {
362430a5e8faSwyllys 		fullpath = get_fullpath(dirpath, certfile);
362599ebb4caSwyllys 		if (fullpath == NULL)
362699ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
362799ebb4caSwyllys 
362899ebb4caSwyllys 		if (isdir(fullpath)) {
362999ebb4caSwyllys 			free(fullpath);
363099ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
363199ebb4caSwyllys 		}
363299ebb4caSwyllys 
36335b3e1433Swyllys 		(void) memset(&certdata, 0, sizeof (certdata));
36345b3e1433Swyllys 		rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL,
36355b3e1433Swyllys 		    fullpath, &certdata.certificate);
363699ebb4caSwyllys 		if (rv != KMF_OK)
363799ebb4caSwyllys 			goto end;
363830a5e8faSwyllys 
36395b3e1433Swyllys 		gotcert++;
36405b3e1433Swyllys 		certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
364130a5e8faSwyllys 		free(fullpath);
364299ebb4caSwyllys 	}
364399ebb4caSwyllys 
364499ebb4caSwyllys 	/*
364599ebb4caSwyllys 	 * Now find the private key.
364699ebb4caSwyllys 	 */
364730a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
364830a5e8faSwyllys 	if (keyfile != NULL) {
364930a5e8faSwyllys 		fullpath = get_fullpath(dirpath, keyfile);
365099ebb4caSwyllys 		if (fullpath == NULL)
365199ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
365299ebb4caSwyllys 
365399ebb4caSwyllys 		if (isdir(fullpath)) {
365499ebb4caSwyllys 			free(fullpath);
365599ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
365699ebb4caSwyllys 		}
365799ebb4caSwyllys 
36585b3e1433Swyllys 		(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
36595b3e1433Swyllys 		rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
36605b3e1433Swyllys 		if (rv != KMF_OK)
366199ebb4caSwyllys 			goto end;
36625b3e1433Swyllys 		gotkey++;
366399ebb4caSwyllys 	}
366499ebb4caSwyllys 
366599ebb4caSwyllys 	/*
366699ebb4caSwyllys 	 * Open the output file.
366799ebb4caSwyllys 	 */
366830a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
366930a5e8faSwyllys 	    numattr);
367030a5e8faSwyllys 	if (filename == NULL) {
367130a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
367230a5e8faSwyllys 		goto end;
367330a5e8faSwyllys 	}
367430a5e8faSwyllys 
367599ebb4caSwyllys 	/* Stick the key and the cert into a PKCS#12 file */
367630a5e8faSwyllys 	p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
367730a5e8faSwyllys 	if (p12cred == NULL) {
367830a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
367930a5e8faSwyllys 		goto end;
368030a5e8faSwyllys 	}
368130a5e8faSwyllys 
36825b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, 1, &certdata,
36835b3e1433Swyllys 	    1, &key, filename);
368499ebb4caSwyllys 
368599ebb4caSwyllys end:
368699ebb4caSwyllys 	if (fullpath)
368799ebb4caSwyllys 		free(fullpath);
368899ebb4caSwyllys 
36895b3e1433Swyllys 	if (gotcert)
36905b3e1433Swyllys 		kmf_free_kmf_cert(handle, &certdata);
36915b3e1433Swyllys 	if (gotkey)
36925b3e1433Swyllys 		kmf_free_kmf_key(handle, &key);
369399ebb4caSwyllys 	return (rv);
369499ebb4caSwyllys }
369599ebb4caSwyllys 
369671593db2Swyllys /*
369771593db2Swyllys  * Helper function to extract keys and certificates from
369871593db2Swyllys  * a single PEM file.  Typically the file should contain a
369971593db2Swyllys  * private key and an associated public key wrapped in an x509 cert.
370071593db2Swyllys  * However, the file may be just a list of X509 certs with no keys.
370171593db2Swyllys  */
370271593db2Swyllys static KMF_RETURN
370330a5e8faSwyllys extract_pem(KMF_HANDLE *kmfh,
370430a5e8faSwyllys 	char *issuer, char *subject, KMF_BIGINT *serial,
370502744e81Swyllys 	char *filename, CK_UTF8CHAR *pin,
370671593db2Swyllys 	CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
370771593db2Swyllys 	int *numcerts)
3708a2d4930dSDan OpenSolaris Anderson /* ARGSUSED6 */
370971593db2Swyllys {
371071593db2Swyllys 	KMF_RETURN rv = KMF_OK;
371171593db2Swyllys 	FILE *fp;
371234acef67Swyllys 	STACK_OF(X509_INFO) *x509_info_stack = NULL;
371302744e81Swyllys 	int i, ncerts = 0, matchcerts = 0;
371471593db2Swyllys 	EVP_PKEY *pkey = NULL;
371571593db2Swyllys 	X509_INFO *info;
371671593db2Swyllys 	X509 *x;
37175b3e1433Swyllys 	X509_INFO **cert_infos = NULL;
371871593db2Swyllys 	KMF_DATA *certlist = NULL;
371971593db2Swyllys 
372071593db2Swyllys 	if (priv_key)
372171593db2Swyllys 		*priv_key = NULL;
372271593db2Swyllys 	if (certs)
372371593db2Swyllys 		*certs = NULL;
372471593db2Swyllys 	fp = fopen(filename, "r");
37255b3e1433Swyllys 	if (fp == NULL)
372671593db2Swyllys 		return (KMF_ERR_OPEN_FILE);
37275b3e1433Swyllys 
372871593db2Swyllys 	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
372971593db2Swyllys 	if (x509_info_stack == NULL) {
373071593db2Swyllys 		(void) fclose(fp);
373171593db2Swyllys 		return (KMF_ERR_ENCODING);
373271593db2Swyllys 	}
37335b3e1433Swyllys 	cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
37345b3e1433Swyllys 	    sizeof (X509_INFO *));
37355b3e1433Swyllys 	if (cert_infos == NULL) {
37365b3e1433Swyllys 		(void) fclose(fp);
37375b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
37385b3e1433Swyllys 		goto err;
37395b3e1433Swyllys 	}
374071593db2Swyllys 
37415b3e1433Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3742d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
374334acef67Swyllys 		cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
374471593db2Swyllys 		ncerts++;
374571593db2Swyllys 	}
374671593db2Swyllys 
374771593db2Swyllys 	if (ncerts == 0) {
374871593db2Swyllys 		(void) fclose(fp);
374934acef67Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
375034acef67Swyllys 		goto err;
375171593db2Swyllys 	}
375271593db2Swyllys 
375371593db2Swyllys 	if (priv_key != NULL) {
375471593db2Swyllys 		rewind(fp);
375571593db2Swyllys 		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
375671593db2Swyllys 	}
375771593db2Swyllys 	(void) fclose(fp);
375871593db2Swyllys 
375971593db2Swyllys 	x = cert_infos[ncerts - 1]->x509;
376071593db2Swyllys 	/*
376171593db2Swyllys 	 * Make sure the private key matchs the last cert in the file.
376271593db2Swyllys 	 */
376371593db2Swyllys 	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
376471593db2Swyllys 		EVP_PKEY_free(pkey);
376534acef67Swyllys 		rv = KMF_ERR_KEY_MISMATCH;
376634acef67Swyllys 		goto err;
376771593db2Swyllys 	}
376871593db2Swyllys 
3769a2d4930dSDan OpenSolaris Anderson 	certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
377071593db2Swyllys 	if (certlist == NULL) {
377171593db2Swyllys 		if (pkey != NULL)
377271593db2Swyllys 			EVP_PKEY_free(pkey);
377334acef67Swyllys 		rv = KMF_ERR_MEMORY;
377434acef67Swyllys 		goto err;
377571593db2Swyllys 	}
377671593db2Swyllys 
377771593db2Swyllys 	/*
377871593db2Swyllys 	 * Convert all of the certs to DER format.
377971593db2Swyllys 	 */
378002744e81Swyllys 	matchcerts = 0;
378171593db2Swyllys 	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
378202744e81Swyllys 		boolean_t match = FALSE;
378371593db2Swyllys 		info =  cert_infos[ncerts - 1 - i];
378471593db2Swyllys 
378530a5e8faSwyllys 		rv = check_cert(info->x509, issuer, subject, serial, &match);
378602744e81Swyllys 		if (rv != KMF_OK || match != TRUE) {
378702744e81Swyllys 			rv = KMF_OK;
378802744e81Swyllys 			continue;
378902744e81Swyllys 		}
379002744e81Swyllys 
379102744e81Swyllys 		rv = ssl_cert2KMFDATA(kmfh, info->x509,
379202744e81Swyllys 			&certlist[matchcerts++]);
379371593db2Swyllys 
379471593db2Swyllys 		if (rv != KMF_OK) {
3795e65e5c2dSWyllys Ingersoll 			int j;
3796e65e5c2dSWyllys Ingersoll 			for (j = 0; j < matchcerts; j++)
3797e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certlist[j]);
379871593db2Swyllys 			free(certlist);
379971593db2Swyllys 			certlist = NULL;
380002744e81Swyllys 			ncerts = matchcerts = 0;
380171593db2Swyllys 		}
380271593db2Swyllys 	}
380371593db2Swyllys 
380471593db2Swyllys 	if (numcerts != NULL)
380502744e81Swyllys 		*numcerts = matchcerts;
3806a2d4930dSDan OpenSolaris Anderson 
3807e65e5c2dSWyllys Ingersoll 	if (certs != NULL)
380871593db2Swyllys 		*certs = certlist;
3809e65e5c2dSWyllys Ingersoll 	else if (certlist != NULL) {
3810e65e5c2dSWyllys Ingersoll 		for (i = 0; i < ncerts; i++)
3811e65e5c2dSWyllys Ingersoll 			kmf_free_data(&certlist[i]);
3812a2d4930dSDan OpenSolaris Anderson 		free(certlist);
3813a2d4930dSDan OpenSolaris Anderson 		certlist = NULL;
3814a2d4930dSDan OpenSolaris Anderson 	}
381571593db2Swyllys 
381671593db2Swyllys 	if (priv_key == NULL && pkey != NULL)
381771593db2Swyllys 		EVP_PKEY_free(pkey);
381871593db2Swyllys 	else if (priv_key != NULL && pkey != NULL)
381971593db2Swyllys 		*priv_key = pkey;
382071593db2Swyllys 
382134acef67Swyllys err:
382234acef67Swyllys 	/* Cleanup the stack of X509 info records */
382334acef67Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3824d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
382534acef67Swyllys 		info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
382634acef67Swyllys 		X509_INFO_free(info);
382734acef67Swyllys 	}
382834acef67Swyllys 	if (x509_info_stack)
382934acef67Swyllys 		sk_X509_INFO_free(x509_info_stack);
383034acef67Swyllys 
38315b3e1433Swyllys 	if (cert_infos != NULL)
38325b3e1433Swyllys 		free(cert_infos);
38335b3e1433Swyllys 
383471593db2Swyllys 	return (rv);
383571593db2Swyllys }
383671593db2Swyllys 
38375b3e1433Swyllys static KMF_RETURN
3838300fdee2SAndy Fiddaman openssl_parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
38395b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
38405b3e1433Swyllys {
38415b3e1433Swyllys 	KMF_RETURN ret;
38425b3e1433Swyllys 	int i;
38435b3e1433Swyllys 
38445b3e1433Swyllys 	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
3845d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
38465b3e1433Swyllys 		PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
38475b3e1433Swyllys 		ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
38485b3e1433Swyllys 		    keys, certs);
38495b3e1433Swyllys 
38505b3e1433Swyllys 		if (ret != KMF_OK)
38515b3e1433Swyllys 			return (ret);
38525b3e1433Swyllys 	}
38535b3e1433Swyllys 
38545b3e1433Swyllys 	return (ret);
38555b3e1433Swyllys }
38565b3e1433Swyllys 
38575b3e1433Swyllys static KMF_RETURN
38585b3e1433Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
38595b3e1433Swyllys {
38605b3e1433Swyllys 	X509_ATTRIBUTE *attr = NULL;
38615b3e1433Swyllys 
38625b3e1433Swyllys 	if (pkey == NULL || attrib == NULL)
38635b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
38645b3e1433Swyllys 
38655b3e1433Swyllys 	attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
38665b3e1433Swyllys 	if (attr != NULL) {
38675b3e1433Swyllys 		int i;
3868300fdee2SAndy Fiddaman 
3869300fdee2SAndy Fiddaman 		if ((i = EVP_PKEY_get_attr_by_NID(pkey, nid, -1)) != -1)
3870300fdee2SAndy Fiddaman 			(void) EVP_PKEY_delete_attr(pkey, i);
3871300fdee2SAndy Fiddaman 		if (EVP_PKEY_add1_attr(pkey, attr) == 0) {
38725b3e1433Swyllys 			X509_ATTRIBUTE_free(attr);
38735b3e1433Swyllys 			return (KMF_ERR_MEMORY);
38745b3e1433Swyllys 		}
38755b3e1433Swyllys 	} else {
38765b3e1433Swyllys 		return (KMF_ERR_MEMORY);
38775b3e1433Swyllys 	}
38785b3e1433Swyllys 
38795b3e1433Swyllys 	return (KMF_OK);
38805b3e1433Swyllys }
38815b3e1433Swyllys 
38825b3e1433Swyllys static KMF_RETURN
38835b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
38845b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
38855b3e1433Swyllys {
38865b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
38875b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
38885b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
38895b3e1433Swyllys 	X509 *xcert = NULL;
3890300fdee2SAndy Fiddaman 	const ASN1_TYPE *keyid = NULL;
3891300fdee2SAndy Fiddaman 	const ASN1_TYPE *fname = NULL;
38925b3e1433Swyllys 	uchar_t *data = NULL;
38935b3e1433Swyllys 
3894300fdee2SAndy Fiddaman 	keyid = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID);
3895300fdee2SAndy Fiddaman 	fname = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName);
38965b3e1433Swyllys 
3897300fdee2SAndy Fiddaman 	switch (PKCS12_SAFEBAG_get_nid(bag)) {
38985b3e1433Swyllys 		case NID_keyBag:
38995b3e1433Swyllys 			if (keylist == NULL)
39005b3e1433Swyllys 				goto end;
3901300fdee2SAndy Fiddaman 			pkey = EVP_PKCS82PKEY(
3902300fdee2SAndy Fiddaman 			    PKCS12_SAFEBAG_get0_p8inf(bag));
39035b3e1433Swyllys 			if (pkey == NULL)
39045b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
39055b3e1433Swyllys 
39065b3e1433Swyllys 			break;
39075b3e1433Swyllys 		case NID_pkcs8ShroudedKeyBag:
39085b3e1433Swyllys 			if (keylist == NULL)
39095b3e1433Swyllys 				goto end;
3910300fdee2SAndy Fiddaman 			p8 = PKCS12_decrypt_skey(bag, pass, passlen);
39115b3e1433Swyllys 			if (p8 == NULL)
39125b3e1433Swyllys 				return (KMF_ERR_AUTH_FAILED);
39135b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(p8);
39145b3e1433Swyllys 			PKCS8_PRIV_KEY_INFO_free(p8);
39155b3e1433Swyllys 			if (pkey == NULL)
39165b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
39175b3e1433Swyllys 			break;
39185b3e1433Swyllys 		case NID_certBag:
39195b3e1433Swyllys 			if (certlist == NULL)
39205b3e1433Swyllys 				goto end;
3921300fdee2SAndy Fiddaman 			if (PKCS12_SAFEBAG_get_bag_nid(bag) !=
3922300fdee2SAndy Fiddaman 			    NID_x509Certificate)
39235b3e1433Swyllys 				return (KMF_ERR_PKCS12_FORMAT);
3924300fdee2SAndy Fiddaman 			xcert = PKCS12_SAFEBAG_get1_cert(bag);
39255b3e1433Swyllys 			if (xcert == NULL) {
39265b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
39275b3e1433Swyllys 				goto end;
39285b3e1433Swyllys 			}
39295b3e1433Swyllys 			if (keyid != NULL) {
39305b3e1433Swyllys 				if (X509_keyid_set1(xcert,
39315b3e1433Swyllys 				    keyid->value.octet_string->data,
39325b3e1433Swyllys 				    keyid->value.octet_string->length) == 0) {
39335b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
39345b3e1433Swyllys 					goto end;
39355b3e1433Swyllys 				}
39365b3e1433Swyllys 			}
39375b3e1433Swyllys 			if (fname != NULL) {
39385b3e1433Swyllys 				int len, r;
39395b3e1433Swyllys 				len = ASN1_STRING_to_UTF8(&data,
39405b3e1433Swyllys 				    fname->value.asn1_string);
39415b3e1433Swyllys 				if (len > 0 && data != NULL) {
39425b3e1433Swyllys 					r = X509_alias_set1(xcert, data, len);
39435b3e1433Swyllys 					if (r == NULL) {
39445b3e1433Swyllys 						ret = KMF_ERR_PKCS12_FORMAT;
39455b3e1433Swyllys 						goto end;
39465b3e1433Swyllys 					}
39475b3e1433Swyllys 				} else {
39485b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
39495b3e1433Swyllys 					goto end;
39505b3e1433Swyllys 				}
39515b3e1433Swyllys 			}
39525b3e1433Swyllys 			if (sk_X509_push(certlist, xcert) == 0)
39535b3e1433Swyllys 				ret = KMF_ERR_MEMORY;
39545b3e1433Swyllys 			else
39555b3e1433Swyllys 				xcert = NULL;
39565b3e1433Swyllys 			break;
39575b3e1433Swyllys 		case NID_safeContentsBag:
3958300fdee2SAndy Fiddaman 			return (openssl_parse_bags(
3959300fdee2SAndy Fiddaman 			    PKCS12_SAFEBAG_get0_safes(bag),
3960300fdee2SAndy Fiddaman 			    pass, keylist, certlist));
39615b3e1433Swyllys 		default:
39625b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39635b3e1433Swyllys 			break;
39645b3e1433Swyllys 	}
39655b3e1433Swyllys 
39665b3e1433Swyllys 	/*
39675b3e1433Swyllys 	 * Set the ID and/or FriendlyName attributes on the key.
39685b3e1433Swyllys 	 * If converting to PKCS11 objects, these can translate to CKA_ID
39695b3e1433Swyllys 	 * and CKA_LABEL values.
39705b3e1433Swyllys 	 */
39715b3e1433Swyllys 	if (pkey != NULL && ret == KMF_OK) {
39725b3e1433Swyllys 		ASN1_TYPE *attr = NULL;
39735b3e1433Swyllys 		if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
39745b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
39755b3e1433Swyllys 				return (KMF_ERR_MEMORY);
39765b3e1433Swyllys 			attr->value.octet_string =
39775b3e1433Swyllys 			    ASN1_STRING_dup(keyid->value.octet_string);
39785b3e1433Swyllys 			attr->type = V_ASN1_OCTET_STRING;
39795b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.octet_string;
39805b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
39815b3e1433Swyllys 			OPENSSL_free(attr);
39825b3e1433Swyllys 		}
39835b3e1433Swyllys 
39845b3e1433Swyllys 		if (ret == KMF_OK && fname != NULL &&
39855b3e1433Swyllys 		    fname->type == V_ASN1_BMPSTRING) {
39865b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
39875b3e1433Swyllys 				return (KMF_ERR_MEMORY);
39885b3e1433Swyllys 			attr->value.bmpstring =
39895b3e1433Swyllys 			    ASN1_STRING_dup(fname->value.bmpstring);
39905b3e1433Swyllys 			attr->type = V_ASN1_BMPSTRING;
39915b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.bmpstring;
39925b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
39935b3e1433Swyllys 			OPENSSL_free(attr);
39945b3e1433Swyllys 		}
39955b3e1433Swyllys 
39965b3e1433Swyllys 		if (ret == KMF_OK && keylist != NULL &&
39975b3e1433Swyllys 		    sk_EVP_PKEY_push(keylist, pkey) == 0)
39985b3e1433Swyllys 			ret = KMF_ERR_MEMORY;
39995b3e1433Swyllys 	}
40005b3e1433Swyllys 	if (ret == KMF_OK && keylist != NULL)
40015b3e1433Swyllys 		pkey = NULL;
40025b3e1433Swyllys end:
40035b3e1433Swyllys 	if (pkey != NULL)
40045b3e1433Swyllys 		EVP_PKEY_free(pkey);
40055b3e1433Swyllys 	if (xcert != NULL)
40065b3e1433Swyllys 		X509_free(xcert);
40075b3e1433Swyllys 	if (data != NULL)
40085b3e1433Swyllys 		OPENSSL_free(data);
40095b3e1433Swyllys 
40105b3e1433Swyllys 	return (ret);
40115b3e1433Swyllys }
40125b3e1433Swyllys 
40135b3e1433Swyllys static KMF_RETURN
40145b3e1433Swyllys openssl_pkcs12_parse(PKCS12 *p12, char *pin,
40155b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys,
40165b3e1433Swyllys 	STACK_OF(X509) *certs,
40175b3e1433Swyllys 	STACK_OF(X509) *ca)
4018a2d4930dSDan OpenSolaris Anderson /* ARGSUSED3 */
40195b3e1433Swyllys {
40205b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
40215b3e1433Swyllys 	STACK_OF(PKCS7) *asafes = NULL;
40225b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
40235b3e1433Swyllys 	int i, bagnid;
40245b3e1433Swyllys 	PKCS7 *p7;
40255b3e1433Swyllys 
40265b3e1433Swyllys 	if (p12 == NULL || (keys == NULL && certs == NULL))
40275b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
40285b3e1433Swyllys 
40295b3e1433Swyllys 	if (pin == NULL || *pin == NULL) {
40305b3e1433Swyllys 		if (PKCS12_verify_mac(p12, NULL, 0)) {
40315b3e1433Swyllys 			pin = NULL;
40325b3e1433Swyllys 		} else if (PKCS12_verify_mac(p12, "", 0)) {
40335b3e1433Swyllys 			pin = "";
40345b3e1433Swyllys 		} else {
40355b3e1433Swyllys 			return (KMF_ERR_AUTH_FAILED);
40365b3e1433Swyllys 		}
40375b3e1433Swyllys 	} else if (!PKCS12_verify_mac(p12, pin, -1)) {
40385b3e1433Swyllys 		return (KMF_ERR_AUTH_FAILED);
40395b3e1433Swyllys 	}
40405b3e1433Swyllys 
40415b3e1433Swyllys 	if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
40425b3e1433Swyllys 		return (KMF_ERR_PKCS12_FORMAT);
40435b3e1433Swyllys 
40445b3e1433Swyllys 	for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
40455b3e1433Swyllys 		bags = NULL;
4046d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
40475b3e1433Swyllys 		p7 = sk_PKCS7_value(asafes, i);
40485b3e1433Swyllys 		bagnid = OBJ_obj2nid(p7->type);
40495b3e1433Swyllys 
40505b3e1433Swyllys 		if (bagnid == NID_pkcs7_data) {
40515b3e1433Swyllys 			bags = PKCS12_unpack_p7data(p7);
40525b3e1433Swyllys 		} else if (bagnid == NID_pkcs7_encrypted) {
40535b3e1433Swyllys 			bags = PKCS12_unpack_p7encdata(p7, pin,
40545b3e1433Swyllys 			    (pin ? strlen(pin) : 0));
40555b3e1433Swyllys 		} else {
40565b3e1433Swyllys 			continue;
40575b3e1433Swyllys 		}
40585b3e1433Swyllys 		if (bags == NULL) {
40595b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
40605b3e1433Swyllys 			goto out;
40615b3e1433Swyllys 		}
40625b3e1433Swyllys 
40635b3e1433Swyllys 		if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
40645b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
40655b3e1433Swyllys 
40665b3e1433Swyllys 		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
40675b3e1433Swyllys 	}
40685b3e1433Swyllys out:
40695b3e1433Swyllys 	if (asafes != NULL)
40705b3e1433Swyllys 		sk_PKCS7_pop_free(asafes, PKCS7_free);
40715b3e1433Swyllys 
40725b3e1433Swyllys 	return (ret);
40735b3e1433Swyllys }
40745b3e1433Swyllys 
407599ebb4caSwyllys /*
407699ebb4caSwyllys  * Helper function to decrypt and parse PKCS#12 import file.
407799ebb4caSwyllys  */
407899ebb4caSwyllys static KMF_RETURN
407999ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
40805b3e1433Swyllys 	STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs,
40815b3e1433Swyllys 	STACK_OF(X509) **ca)
4082a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */
408399ebb4caSwyllys {
408499ebb4caSwyllys 	PKCS12			*pk12, *pk12_tmp;
40855b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*pkeylist = NULL;
40865b3e1433Swyllys 	STACK_OF(X509)		*xcertlist = NULL;
40875b3e1433Swyllys 	STACK_OF(X509)		*cacertlist = NULL;
408899ebb4caSwyllys 
408999ebb4caSwyllys 	if ((pk12 = PKCS12_new()) == NULL) {
409099ebb4caSwyllys 		return (KMF_ERR_MEMORY);
409199ebb4caSwyllys 	}
409299ebb4caSwyllys 
409399ebb4caSwyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
409499ebb4caSwyllys 		/* This is ok; it seems to mean there is no more to read. */
409599ebb4caSwyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
409699ebb4caSwyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
409799ebb4caSwyllys 			goto end_extract_pkcs12;
409899ebb4caSwyllys 
409999ebb4caSwyllys 		PKCS12_free(pk12);
410099ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
410199ebb4caSwyllys 	}
410299ebb4caSwyllys 	pk12 = pk12_tmp;
410399ebb4caSwyllys 
41045b3e1433Swyllys 	xcertlist = sk_X509_new_null();
41055b3e1433Swyllys 	if (xcertlist == NULL) {
41065b3e1433Swyllys 		PKCS12_free(pk12);
41075b3e1433Swyllys 		return (KMF_ERR_MEMORY);
41085b3e1433Swyllys 	}
41095b3e1433Swyllys 	pkeylist = sk_EVP_PKEY_new_null();
41105b3e1433Swyllys 	if (pkeylist == NULL) {
41115b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
41125b3e1433Swyllys 		PKCS12_free(pk12);
41135b3e1433Swyllys 		return (KMF_ERR_MEMORY);
41145b3e1433Swyllys 	}
41155b3e1433Swyllys 
41165b3e1433Swyllys 	if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
41175b3e1433Swyllys 	    cacertlist) != KMF_OK) {
41185b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
41195b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
412099ebb4caSwyllys 		PKCS12_free(pk12);
412199ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
412299ebb4caSwyllys 	}
412399ebb4caSwyllys 
41245b3e1433Swyllys 	if (priv_key && pkeylist)
41255b3e1433Swyllys 		*priv_key = pkeylist;
41265b3e1433Swyllys 	else if (pkeylist)
41275b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
41285b3e1433Swyllys 	if (certs && xcertlist)
41295b3e1433Swyllys 		*certs = xcertlist;
41305b3e1433Swyllys 	else if (xcertlist)
41315b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
41325b3e1433Swyllys 	if (ca && cacertlist)
41335b3e1433Swyllys 		*ca = cacertlist;
41345b3e1433Swyllys 	else if (cacertlist)
41355b3e1433Swyllys 		sk_X509_pop_free(cacertlist, X509_free);
413699ebb4caSwyllys 
41375b3e1433Swyllys end_extract_pkcs12:
413899ebb4caSwyllys 
413999ebb4caSwyllys 	PKCS12_free(pk12);
414099ebb4caSwyllys 	return (KMF_OK);
414199ebb4caSwyllys }
414299ebb4caSwyllys 
414399ebb4caSwyllys static KMF_RETURN
414499ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
414599ebb4caSwyllys {
414699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
414799ebb4caSwyllys 	uint32_t sz;
414899ebb4caSwyllys 
414999ebb4caSwyllys 	sz = BN_num_bytes(from);
415099ebb4caSwyllys 	to->val = (uchar_t *)malloc(sz);
415199ebb4caSwyllys 	if (to->val == NULL)
415299ebb4caSwyllys 		return (KMF_ERR_MEMORY);
415399ebb4caSwyllys 
415499ebb4caSwyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
415599ebb4caSwyllys 		free(to->val);
415699ebb4caSwyllys 		to->val = NULL;
415799ebb4caSwyllys 		to->len = 0;
415899ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
415999ebb4caSwyllys 	}
416099ebb4caSwyllys 
416199ebb4caSwyllys 	return (rv);
416299ebb4caSwyllys }
416399ebb4caSwyllys 
416499ebb4caSwyllys static KMF_RETURN
416599ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
416699ebb4caSwyllys {
416799ebb4caSwyllys 	KMF_RETURN rv;
416899ebb4caSwyllys 	KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
416999ebb4caSwyllys 
4170300fdee2SAndy Fiddaman 	const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmpq, *iqmp;
4171300fdee2SAndy Fiddaman 
4172300fdee2SAndy Fiddaman 	RSA_get0_key(rsa, &n, &e, &d);
4173300fdee2SAndy Fiddaman 	RSA_get0_factors(rsa, &p, &q);
4174300fdee2SAndy Fiddaman 	RSA_get0_crt_params(rsa, &dmp1, &dmpq, &iqmp);
4175300fdee2SAndy Fiddaman 
417699ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
4177300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)n, &kmfkey->mod)) != KMF_OK)
417899ebb4caSwyllys 		goto cleanup;
417999ebb4caSwyllys 
4180300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)e, &kmfkey->pubexp)) != KMF_OK)
418199ebb4caSwyllys 		goto cleanup;
418299ebb4caSwyllys 
4183300fdee2SAndy Fiddaman 	if (d != NULL)
4184300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)d, &kmfkey->priexp)) != KMF_OK)
418599ebb4caSwyllys 			goto cleanup;
418699ebb4caSwyllys 
4187300fdee2SAndy Fiddaman 	if (p != NULL)
4188300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime1)) != KMF_OK)
418999ebb4caSwyllys 			goto cleanup;
419099ebb4caSwyllys 
4191300fdee2SAndy Fiddaman 	if (q != NULL)
4192300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->prime2)) != KMF_OK)
419399ebb4caSwyllys 			goto cleanup;
419499ebb4caSwyllys 
4195300fdee2SAndy Fiddaman 	if (dmp1 != NULL)
4196300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)dmp1, &kmfkey->exp1)) != KMF_OK)
419799ebb4caSwyllys 			goto cleanup;
419899ebb4caSwyllys 
4199300fdee2SAndy Fiddaman 	if (dmpq != NULL)
4200300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)dmpq, &kmfkey->exp2)) != KMF_OK)
420199ebb4caSwyllys 			goto cleanup;
420299ebb4caSwyllys 
4203300fdee2SAndy Fiddaman 	if (iqmp != NULL)
4204300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)iqmp, &kmfkey->coef)) != KMF_OK)
420599ebb4caSwyllys 			goto cleanup;
420699ebb4caSwyllys cleanup:
420799ebb4caSwyllys 	if (rv != KMF_OK)
420830a5e8faSwyllys 		kmf_free_raw_key(key);
420999ebb4caSwyllys 	else
421099ebb4caSwyllys 		key->keytype = KMF_RSA;
421199ebb4caSwyllys 
421299ebb4caSwyllys 	/*
421399ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
421499ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
421599ebb4caSwyllys 	 */
421699ebb4caSwyllys 	RSA_free(rsa);
421799ebb4caSwyllys 
421899ebb4caSwyllys 	return (rv);
421999ebb4caSwyllys }
422099ebb4caSwyllys 
422199ebb4caSwyllys static KMF_RETURN
422299ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
422399ebb4caSwyllys {
422499ebb4caSwyllys 	KMF_RETURN rv;
422599ebb4caSwyllys 	KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
4226300fdee2SAndy Fiddaman 	const BIGNUM *p, *q, *g, *priv_key;
4227300fdee2SAndy Fiddaman 
4228300fdee2SAndy Fiddaman 	DSA_get0_pqg(dsa, &p, &q, &g);
4229300fdee2SAndy Fiddaman 	DSA_get0_key(dsa, NULL, &priv_key);
423099ebb4caSwyllys 
423199ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
4232300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime)) != KMF_OK)
423399ebb4caSwyllys 		goto cleanup;
423499ebb4caSwyllys 
4235300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->subprime)) != KMF_OK)
423699ebb4caSwyllys 		goto cleanup;
423799ebb4caSwyllys 
4238300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)g, &kmfkey->base)) != KMF_OK)
423999ebb4caSwyllys 		goto cleanup;
424099ebb4caSwyllys 
4241300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)priv_key, &kmfkey->value)) != KMF_OK)
424299ebb4caSwyllys 		goto cleanup;
424399ebb4caSwyllys 
424499ebb4caSwyllys cleanup:
424599ebb4caSwyllys 	if (rv != KMF_OK)
424630a5e8faSwyllys 		kmf_free_raw_key(key);
424799ebb4caSwyllys 	else
424899ebb4caSwyllys 		key->keytype = KMF_DSA;
424999ebb4caSwyllys 
425099ebb4caSwyllys 	/*
425199ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
425299ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
425399ebb4caSwyllys 	 */
425499ebb4caSwyllys 	DSA_free(dsa);
425599ebb4caSwyllys 
425699ebb4caSwyllys 	return (rv);
425799ebb4caSwyllys }
425899ebb4caSwyllys 
425999ebb4caSwyllys static KMF_RETURN
426099ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
42615b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
426299ebb4caSwyllys {
426399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
42645b3e1433Swyllys 	KMF_X509_DER_CERT *list = (*certlist);
42655b3e1433Swyllys 	KMF_X509_DER_CERT cert;
426699ebb4caSwyllys 	int n = (*ncerts);
426799ebb4caSwyllys 
426899ebb4caSwyllys 	if (list == NULL) {
42695b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
427099ebb4caSwyllys 	} else {
42715b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)realloc(list,
42725b3e1433Swyllys 		    sizeof (KMF_X509_DER_CERT) * (n + 1));
427399ebb4caSwyllys 	}
427499ebb4caSwyllys 
427599ebb4caSwyllys 	if (list == NULL)
427699ebb4caSwyllys 		return (KMF_ERR_MEMORY);
427799ebb4caSwyllys 
42785b3e1433Swyllys 	(void) memset(&cert, 0, sizeof (cert));
42795b3e1433Swyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
428099ebb4caSwyllys 	if (rv == KMF_OK) {
42815b3e1433Swyllys 		int len = 0;
42825b3e1433Swyllys 		/* Get the alias name for the cert if there is one */
42835b3e1433Swyllys 		char *a = (char *)X509_alias_get0(sslcert, &len);
42845b3e1433Swyllys 		if (a != NULL)
42855b3e1433Swyllys 			cert.kmf_private.label = strdup(a);
42865b3e1433Swyllys 		cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
42875b3e1433Swyllys 
428899ebb4caSwyllys 		list[n] = cert;
428999ebb4caSwyllys 		(*ncerts) = n + 1;
429099ebb4caSwyllys 
429199ebb4caSwyllys 		*certlist = list;
429299ebb4caSwyllys 	} else {
429399ebb4caSwyllys 		free(list);
429499ebb4caSwyllys 	}
429599ebb4caSwyllys 
429699ebb4caSwyllys 	return (rv);
429799ebb4caSwyllys }
429899ebb4caSwyllys 
429999ebb4caSwyllys static KMF_RETURN
430099ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
430199ebb4caSwyllys 	KMF_RAW_KEY_DATA *newkey, int *nkeys)
430299ebb4caSwyllys {
430399ebb4caSwyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
430499ebb4caSwyllys 	int n = (*nkeys);
430599ebb4caSwyllys 
430699ebb4caSwyllys 	if (list == NULL) {
430799ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
430899ebb4caSwyllys 	} else {
430999ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
431099ebb4caSwyllys 		    sizeof (KMF_RAW_KEY_DATA) * (n + 1));
431199ebb4caSwyllys 	}
431299ebb4caSwyllys 
431399ebb4caSwyllys 	if (list == NULL)
431499ebb4caSwyllys 		return (KMF_ERR_MEMORY);
431599ebb4caSwyllys 
431699ebb4caSwyllys 	list[n] = *newkey;
431799ebb4caSwyllys 	(*nkeys) = n + 1;
431899ebb4caSwyllys 
431999ebb4caSwyllys 	*keylist = list;
432099ebb4caSwyllys 
432199ebb4caSwyllys 	return (KMF_OK);
432299ebb4caSwyllys }
432399ebb4caSwyllys 
432430a5e8faSwyllys static KMF_RETURN
432530a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
432630a5e8faSwyllys {
432730a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
43285b3e1433Swyllys 	X509_ATTRIBUTE *attr;
4329300fdee2SAndy Fiddaman 	RSA *rsa;
4330300fdee2SAndy Fiddaman 	DSA *dsa;
4331300fdee2SAndy Fiddaman 	int loc;
433230a5e8faSwyllys 
433330a5e8faSwyllys 	if (pkey == NULL || key == NULL)
433430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
433530a5e8faSwyllys 	/* Convert SSL key to raw key */
4336300fdee2SAndy Fiddaman 	if ((rsa = EVP_PKEY_get1_RSA(pkey)) != NULL) {
4337300fdee2SAndy Fiddaman 		rv = exportRawRSAKey(rsa, key);
433830a5e8faSwyllys 		if (rv != KMF_OK)
433930a5e8faSwyllys 			return (rv);
4340300fdee2SAndy Fiddaman 	} else if ((dsa = EVP_PKEY_get1_DSA(pkey)) != NULL) {
4341300fdee2SAndy Fiddaman 		rv = exportRawDSAKey(dsa, key);
434230a5e8faSwyllys 		if (rv != KMF_OK)
434330a5e8faSwyllys 			return (rv);
4344300fdee2SAndy Fiddaman 	} else
434530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
4346300fdee2SAndy Fiddaman 
43475b3e1433Swyllys 	/*
43485b3e1433Swyllys 	 * If friendlyName, add it to record.
43495b3e1433Swyllys 	 */
4350300fdee2SAndy Fiddaman 
4351300fdee2SAndy Fiddaman 	if ((loc = EVP_PKEY_get_attr_by_NID(pkey,
4352300fdee2SAndy Fiddaman 	    NID_friendlyName, -1)) != -1 &&
4353300fdee2SAndy Fiddaman 	    (attr = EVP_PKEY_get_attr(pkey, loc))) {
43545b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
4355300fdee2SAndy Fiddaman 		int numattr = X509_ATTRIBUTE_count(attr);
4356300fdee2SAndy Fiddaman 		if (numattr > 0) {
4357300fdee2SAndy Fiddaman 			ty = X509_ATTRIBUTE_get0_type(attr, 0);
43585b3e1433Swyllys 		}
43595b3e1433Swyllys 		if (ty != NULL) {
436070f9559bSTheo Schlossnagle 			key->label = OPENSSL_uni2asc(ty->value.bmpstring->data,
436170f9559bSTheo Schlossnagle 			    ty->value.bmpstring->length);
43625b3e1433Swyllys 		}
43635b3e1433Swyllys 	} else {
43645b3e1433Swyllys 		key->label = NULL;
43655b3e1433Swyllys 	}
43665b3e1433Swyllys 
43675b3e1433Swyllys 	/*
43685b3e1433Swyllys 	 * If KeyID, add it to record as a KMF_DATA object.
43695b3e1433Swyllys 	 */
4370300fdee2SAndy Fiddaman 	if ((loc = EVP_PKEY_get_attr_by_NID(pkey,
4371300fdee2SAndy Fiddaman 	    NID_localKeyID, -1)) != -1 &&
4372300fdee2SAndy Fiddaman 	    (attr = EVP_PKEY_get_attr(pkey, loc)) != NULL) {
43735b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
4374300fdee2SAndy Fiddaman 		int numattr = X509_ATTRIBUTE_count(attr);
4375300fdee2SAndy Fiddaman 		if (numattr > 0)
4376300fdee2SAndy Fiddaman 			ty = X509_ATTRIBUTE_get0_type(attr, 0);
43775b3e1433Swyllys 		key->id.Data = (uchar_t *)malloc(
43785b3e1433Swyllys 		    ty->value.octet_string->length);
43795b3e1433Swyllys 		if (key->id.Data == NULL)
43805b3e1433Swyllys 			return (KMF_ERR_MEMORY);
43815b3e1433Swyllys 		(void) memcpy(key->id.Data, ty->value.octet_string->data,
43825b3e1433Swyllys 		    ty->value.octet_string->length);
43835b3e1433Swyllys 		key->id.Length = ty->value.octet_string->length;
43845b3e1433Swyllys 	} else {
43855b3e1433Swyllys 		(void) memset(&key->id, 0, sizeof (KMF_DATA));
43865b3e1433Swyllys 	}
438730a5e8faSwyllys 
438830a5e8faSwyllys 	return (rv);
438930a5e8faSwyllys }
439099ebb4caSwyllys 
439199ebb4caSwyllys static KMF_RETURN
439299ebb4caSwyllys convertPK12Objects(
439399ebb4caSwyllys 	KMF_HANDLE *kmfh,
43945b3e1433Swyllys 	STACK_OF(EVP_PKEY) *sslkeys,
43955b3e1433Swyllys 	STACK_OF(X509) *sslcert,
43965b3e1433Swyllys 	STACK_OF(X509) *sslcacerts,
439799ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
43985b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
439999ebb4caSwyllys {
440099ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
440199ebb4caSwyllys 	KMF_RAW_KEY_DATA key;
440299ebb4caSwyllys 	int i;
440399ebb4caSwyllys 
44045b3e1433Swyllys 	for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
4405d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
44065b3e1433Swyllys 		EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
44075b3e1433Swyllys 		rv = convertToRawKey(pkey, &key);
440830a5e8faSwyllys 		if (rv == KMF_OK)
440999ebb4caSwyllys 			rv = add_key_to_list(keylist, &key, nkeys);
441030a5e8faSwyllys 
441199ebb4caSwyllys 		if (rv != KMF_OK)
441299ebb4caSwyllys 			return (rv);
441399ebb4caSwyllys 	}
441499ebb4caSwyllys 
441599ebb4caSwyllys 	/* Now add the certificate to the certlist */
44165b3e1433Swyllys 	for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
4417d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
44185b3e1433Swyllys 		X509 *cert = sk_X509_value(sslcert, i);
44195b3e1433Swyllys 		rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
442099ebb4caSwyllys 		if (rv != KMF_OK)
442199ebb4caSwyllys 			return (rv);
442299ebb4caSwyllys 	}
442399ebb4caSwyllys 
442499ebb4caSwyllys 	/* Also add any included CA certs to the list */
442571593db2Swyllys 	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
442699ebb4caSwyllys 		X509 *c;
442799ebb4caSwyllys 		/*
442899ebb4caSwyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
442999ebb4caSwyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
443099ebb4caSwyllys 		 * Lint is complaining about the embedded casting, and
443199ebb4caSwyllys 		 * to fix it, you need to fix openssl header files.
443299ebb4caSwyllys 		 */
4433d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
443499ebb4caSwyllys 		c = sk_X509_value(sslcacerts, i);
443599ebb4caSwyllys 
443699ebb4caSwyllys 		/* Now add the ca cert to the certlist */
443799ebb4caSwyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
443899ebb4caSwyllys 		if (rv != KMF_OK)
443999ebb4caSwyllys 			return (rv);
444099ebb4caSwyllys 	}
444199ebb4caSwyllys 	return (rv);
444299ebb4caSwyllys }
444399ebb4caSwyllys 
444499ebb4caSwyllys KMF_RETURN
444530a5e8faSwyllys openssl_import_objects(KMF_HANDLE *kmfh,
444699ebb4caSwyllys 	char *filename, KMF_CREDENTIAL *cred,
44475b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts,
444899ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
444999ebb4caSwyllys {
445099ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
445130a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
445230a5e8faSwyllys 	BIO		*bio = NULL;
44535b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*privkeys = NULL;
44545b3e1433Swyllys 	STACK_OF(X509)		*certs = NULL;
445599ebb4caSwyllys 	STACK_OF(X509)		*cacerts = NULL;
445699ebb4caSwyllys 
445730a5e8faSwyllys 	/*
445830a5e8faSwyllys 	 * auto-detect the file format, regardless of what
445930a5e8faSwyllys 	 * the 'format' parameters in the params say.
446030a5e8faSwyllys 	 */
446130a5e8faSwyllys 	rv = kmf_get_file_format(filename, &format);
446230a5e8faSwyllys 	if (rv != KMF_OK) {
446330a5e8faSwyllys 		return (rv);
446430a5e8faSwyllys 	}
446530a5e8faSwyllys 
446630a5e8faSwyllys 	/* This function only works for PEM or PKCS#12 files */
446730a5e8faSwyllys 	if (format != KMF_FORMAT_PEM &&
446830a5e8faSwyllys 	    format != KMF_FORMAT_PEM_KEYPAIR &&
446930a5e8faSwyllys 	    format != KMF_FORMAT_PKCS12)
447030a5e8faSwyllys 		return (KMF_ERR_ENCODING);
447130a5e8faSwyllys 
447230a5e8faSwyllys 	*certlist = NULL;
447330a5e8faSwyllys 	*keylist = NULL;
447430a5e8faSwyllys 	*ncerts = 0;
447530a5e8faSwyllys 	*nkeys = 0;
447630a5e8faSwyllys 
447730a5e8faSwyllys 	if (format == KMF_FORMAT_PKCS12) {
447899ebb4caSwyllys 		bio = BIO_new_file(filename, "rb");
447999ebb4caSwyllys 		if (bio == NULL) {
448099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
448199ebb4caSwyllys 			rv = KMF_ERR_OPEN_FILE;
448299ebb4caSwyllys 			goto end;
448399ebb4caSwyllys 		}
448499ebb4caSwyllys 
448534acef67Swyllys 		rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
44865b3e1433Swyllys 		    (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
448799ebb4caSwyllys 
448899ebb4caSwyllys 		if (rv  == KMF_OK)
448999ebb4caSwyllys 			/* Convert keys and certs to exportable format */
44905b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
449199ebb4caSwyllys 			    keylist, nkeys, certlist, ncerts);
449230a5e8faSwyllys 	} else {
44935b3e1433Swyllys 		EVP_PKEY *pkey;
44945b3e1433Swyllys 		KMF_DATA *certdata = NULL;
44955b3e1433Swyllys 		KMF_X509_DER_CERT *kmfcerts = NULL;
44965b3e1433Swyllys 		int i;
449730a5e8faSwyllys 		rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
449834acef67Swyllys 		    (uchar_t *)cred->cred, (uint32_t)cred->credlen,
44995b3e1433Swyllys 		    &pkey, &certdata, ncerts);
450071593db2Swyllys 
450171593db2Swyllys 		/* Reached end of import file? */
45025b3e1433Swyllys 		if (rv == KMF_OK && pkey != NULL) {
45035b3e1433Swyllys 			privkeys = sk_EVP_PKEY_new_null();
45045b3e1433Swyllys 			if (privkeys == NULL) {
45055b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
45065b3e1433Swyllys 				goto end;
45075b3e1433Swyllys 			}
45085b3e1433Swyllys 			(void) sk_EVP_PKEY_push(privkeys, pkey);
45095b3e1433Swyllys 			/* convert the certificate list here */
45105b3e1433Swyllys 			if (*ncerts > 0 && certlist != NULL) {
4511e65e5c2dSWyllys Ingersoll 				kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
45125b3e1433Swyllys 				    sizeof (KMF_X509_DER_CERT));
45135b3e1433Swyllys 				if (kmfcerts == NULL) {
45145b3e1433Swyllys 					rv = KMF_ERR_MEMORY;
45155b3e1433Swyllys 					goto end;
45165b3e1433Swyllys 				}
45175b3e1433Swyllys 				for (i = 0; i < *ncerts; i++) {
45185b3e1433Swyllys 					kmfcerts[i].certificate = certdata[i];
45195b3e1433Swyllys 					kmfcerts[i].kmf_private.keystore_type =
45205b3e1433Swyllys 					    KMF_KEYSTORE_OPENSSL;
45215b3e1433Swyllys 				}
45225b3e1433Swyllys 				*certlist = kmfcerts;
45235b3e1433Swyllys 			}
45245b3e1433Swyllys 			/*
45255b3e1433Swyllys 			 * Convert keys to exportable format, the certs
45265b3e1433Swyllys 			 * are already OK.
45275b3e1433Swyllys 			 */
45285b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
452971593db2Swyllys 			    keylist, nkeys, NULL, NULL);
453030a5e8faSwyllys 		}
45315b3e1433Swyllys 	}
453271593db2Swyllys end:
453330a5e8faSwyllys 	if (bio != NULL)
453499ebb4caSwyllys 		(void) BIO_free(bio);
453599ebb4caSwyllys 
45365b3e1433Swyllys 	if (privkeys)
45375b3e1433Swyllys 		sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
45385b3e1433Swyllys 	if (certs)
45395b3e1433Swyllys 		sk_X509_pop_free(certs, X509_free);
454030a5e8faSwyllys 	if (cacerts)
45415b3e1433Swyllys 		sk_X509_pop_free(cacerts, X509_free);
454230a5e8faSwyllys 
454399ebb4caSwyllys 	return (rv);
454499ebb4caSwyllys }
454599ebb4caSwyllys 
454699ebb4caSwyllys static KMF_RETURN
454799ebb4caSwyllys create_deskey(DES_cblock **deskey)
454899ebb4caSwyllys {
454999ebb4caSwyllys 	DES_cblock *key;
455099ebb4caSwyllys 
455199ebb4caSwyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
455299ebb4caSwyllys 	if (key == NULL) {
455399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
455499ebb4caSwyllys 	}
455599ebb4caSwyllys 
455699ebb4caSwyllys 	if (DES_random_key(key) == 0) {
455799ebb4caSwyllys 		free(key);
455899ebb4caSwyllys 		return (KMF_ERR_KEYGEN_FAILED);
455999ebb4caSwyllys 	}
456099ebb4caSwyllys 
456199ebb4caSwyllys 	*deskey = key;
456299ebb4caSwyllys 	return (KMF_OK);
456399ebb4caSwyllys }
456499ebb4caSwyllys 
456599ebb4caSwyllys #define	KEYGEN_RETRY 3
456699ebb4caSwyllys #define	DES3_KEY_SIZE 24
456799ebb4caSwyllys 
456899ebb4caSwyllys static KMF_RETURN
456999ebb4caSwyllys create_des3key(unsigned char **des3key)
457099ebb4caSwyllys {
457199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
457299ebb4caSwyllys 	DES_cblock *deskey1 = NULL;
457399ebb4caSwyllys 	DES_cblock *deskey2 = NULL;
457499ebb4caSwyllys 	DES_cblock *deskey3 = NULL;
457599ebb4caSwyllys 	unsigned char *newkey = NULL;
457699ebb4caSwyllys 	int retry;
457799ebb4caSwyllys 
457899ebb4caSwyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
457999ebb4caSwyllys 		return (KMF_ERR_MEMORY);
458099ebb4caSwyllys 	}
458199ebb4caSwyllys 
458299ebb4caSwyllys 	/* create the 1st DES key */
458399ebb4caSwyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
458499ebb4caSwyllys 		goto out;
458599ebb4caSwyllys 	}
458699ebb4caSwyllys 
458799ebb4caSwyllys 	/*
458899ebb4caSwyllys 	 * Create the 2nd DES key and make sure its value is different
458999ebb4caSwyllys 	 * from the 1st DES key.
459099ebb4caSwyllys 	 */
459199ebb4caSwyllys 	retry = 0;
459299ebb4caSwyllys 	do {
459399ebb4caSwyllys 		if (deskey2 != NULL) {
459499ebb4caSwyllys 			free(deskey2);
459599ebb4caSwyllys 			deskey2 = NULL;
459699ebb4caSwyllys 		}
459799ebb4caSwyllys 
459899ebb4caSwyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
459999ebb4caSwyllys 			goto out;
460099ebb4caSwyllys 		}
460199ebb4caSwyllys 
460299ebb4caSwyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
460399ebb4caSwyllys 		    == 0) {
460499ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
460599ebb4caSwyllys 			retry++;
460699ebb4caSwyllys 		}
460799ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
460899ebb4caSwyllys 
460999ebb4caSwyllys 	if (ret != KMF_OK) {
461099ebb4caSwyllys 		goto out;
461199ebb4caSwyllys 	}
461299ebb4caSwyllys 
461399ebb4caSwyllys 	/*
461499ebb4caSwyllys 	 * Create the 3rd DES key and make sure its value is different
461599ebb4caSwyllys 	 * from the 2nd DES key.
461699ebb4caSwyllys 	 */
461799ebb4caSwyllys 	retry = 0;
461899ebb4caSwyllys 	do {
461999ebb4caSwyllys 		if (deskey3 != NULL) {
462099ebb4caSwyllys 			free(deskey3);
462199ebb4caSwyllys 			deskey3 = NULL;
462299ebb4caSwyllys 		}
462399ebb4caSwyllys 
462499ebb4caSwyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
462599ebb4caSwyllys 			goto out;
462699ebb4caSwyllys 		}
462799ebb4caSwyllys 
462899ebb4caSwyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
462999ebb4caSwyllys 		    == 0) {
463099ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
463199ebb4caSwyllys 			retry++;
463299ebb4caSwyllys 		}
463399ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
463499ebb4caSwyllys 
463599ebb4caSwyllys 	if (ret != KMF_OK) {
463699ebb4caSwyllys 		goto out;
463799ebb4caSwyllys 	}
463899ebb4caSwyllys 
463999ebb4caSwyllys 	/* Concatenate 3 DES keys into a DES3 key */
464099ebb4caSwyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
464199ebb4caSwyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
464299ebb4caSwyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
464399ebb4caSwyllys 	*des3key = newkey;
464499ebb4caSwyllys 
464599ebb4caSwyllys out:
464699ebb4caSwyllys 	if (deskey1 != NULL)
464799ebb4caSwyllys 		free(deskey1);
464899ebb4caSwyllys 
464999ebb4caSwyllys 	if (deskey2 != NULL)
465099ebb4caSwyllys 		free(deskey2);
465199ebb4caSwyllys 
465299ebb4caSwyllys 	if (deskey3 != NULL)
465399ebb4caSwyllys 		free(deskey3);
465499ebb4caSwyllys 
465599ebb4caSwyllys 	if (ret != KMF_OK && newkey != NULL)
465699ebb4caSwyllys 		free(newkey);
465799ebb4caSwyllys 
465899ebb4caSwyllys 	return (ret);
465999ebb4caSwyllys }
466099ebb4caSwyllys 
466199ebb4caSwyllys KMF_RETURN
466230a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
466330a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
466499ebb4caSwyllys {
466599ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
466699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
466799ebb4caSwyllys 	char *fullpath = NULL;
466899ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
466999ebb4caSwyllys 	DES_cblock *deskey = NULL;
467099ebb4caSwyllys 	unsigned char *des3key = NULL;
467199ebb4caSwyllys 	unsigned char *random = NULL;
467299ebb4caSwyllys 	int fd = -1;
467330a5e8faSwyllys 	KMF_KEY_HANDLE *symkey;
467430a5e8faSwyllys 	KMF_KEY_ALG keytype;
467530a5e8faSwyllys 	uint32_t keylen;
467630a5e8faSwyllys 	uint32_t keylen_size = sizeof (keylen);
467730a5e8faSwyllys 	char *dirpath;
467830a5e8faSwyllys 	char *keyfile;
467999ebb4caSwyllys 
468099ebb4caSwyllys 	if (kmfh == NULL)
468199ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
468299ebb4caSwyllys 
468330a5e8faSwyllys 	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
468430a5e8faSwyllys 	if (symkey == NULL)
468599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
468699ebb4caSwyllys 
468730a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
468830a5e8faSwyllys 
468930a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
469030a5e8faSwyllys 	if (keyfile == NULL)
469130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
469230a5e8faSwyllys 
469330a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
469430a5e8faSwyllys 	    (void *)&keytype, NULL);
469530a5e8faSwyllys 	if (ret != KMF_OK)
469630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
469730a5e8faSwyllys 
469830a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
469930a5e8faSwyllys 	    &keylen, &keylen_size);
470030a5e8faSwyllys 	if (ret == KMF_ERR_ATTR_NOT_FOUND &&
470130a5e8faSwyllys 	    (keytype == KMF_DES || keytype == KMF_DES3))
470230a5e8faSwyllys 		/* keylength is not required for DES and 3DES */
470330a5e8faSwyllys 		ret = KMF_OK;
470430a5e8faSwyllys 	if (ret != KMF_OK)
470530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
470630a5e8faSwyllys 
470730a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
470899ebb4caSwyllys 	if (fullpath == NULL)
470999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
471099ebb4caSwyllys 
471199ebb4caSwyllys 	/* If the requested file exists, return an error */
471230a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
471399ebb4caSwyllys 		free(fullpath);
471499ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
471599ebb4caSwyllys 	}
471699ebb4caSwyllys 
471799ebb4caSwyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
471899ebb4caSwyllys 	if (fd == -1) {
471999ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
472099ebb4caSwyllys 		goto out;
472199ebb4caSwyllys 	}
472299ebb4caSwyllys 
472399ebb4caSwyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
472499ebb4caSwyllys 	if (rkey == NULL) {
472599ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
472699ebb4caSwyllys 		goto out;
472799ebb4caSwyllys 	}
472899ebb4caSwyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
472999ebb4caSwyllys 
473030a5e8faSwyllys 	if (keytype == KMF_DES) {
473199ebb4caSwyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
473299ebb4caSwyllys 			goto out;
473399ebb4caSwyllys 		}
473499ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)deskey;
473599ebb4caSwyllys 		rkey->keydata.len = 8;
473699ebb4caSwyllys 
473799ebb4caSwyllys 		symkey->keyalg = KMF_DES;
473899ebb4caSwyllys 
473930a5e8faSwyllys 	} else if (keytype == KMF_DES3) {
474099ebb4caSwyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
474199ebb4caSwyllys 			goto out;
474299ebb4caSwyllys 		}
474399ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)des3key;
474499ebb4caSwyllys 		rkey->keydata.len = DES3_KEY_SIZE;
474599ebb4caSwyllys 		symkey->keyalg = KMF_DES3;
47469b37d296Swyllys 
474730a5e8faSwyllys 	} else if (keytype == KMF_AES || keytype == KMF_RC4 ||
474830a5e8faSwyllys 	    keytype == KMF_GENERIC_SECRET) {
474999ebb4caSwyllys 		int bytes;
475099ebb4caSwyllys 
475130a5e8faSwyllys 		if (keylen % 8 != 0) {
475299ebb4caSwyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
475399ebb4caSwyllys 			goto out;
475499ebb4caSwyllys 		}
475599ebb4caSwyllys 
475630a5e8faSwyllys 		if (keytype == KMF_AES) {
475730a5e8faSwyllys 			if (keylen != 128 &&
475830a5e8faSwyllys 			    keylen != 192 &&
475930a5e8faSwyllys 			    keylen != 256) {
476099ebb4caSwyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
476199ebb4caSwyllys 				goto out;
476299ebb4caSwyllys 			}
476399ebb4caSwyllys 		}
476499ebb4caSwyllys 
476530a5e8faSwyllys 		bytes = keylen/8;
476699ebb4caSwyllys 		random = malloc(bytes);
476799ebb4caSwyllys 		if (random == NULL) {
476899ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
476999ebb4caSwyllys 			goto out;
477099ebb4caSwyllys 		}
477199ebb4caSwyllys 		if (RAND_bytes(random, bytes) != 1) {
477299ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
477399ebb4caSwyllys 			goto out;
477499ebb4caSwyllys 		}
477599ebb4caSwyllys 
477699ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)random;
477799ebb4caSwyllys 		rkey->keydata.len = bytes;
477830a5e8faSwyllys 		symkey->keyalg = keytype;
477999ebb4caSwyllys 
478099ebb4caSwyllys 	} else {
478199ebb4caSwyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
478299ebb4caSwyllys 		goto out;
478399ebb4caSwyllys 	}
478499ebb4caSwyllys 
478599ebb4caSwyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
478699ebb4caSwyllys 
478799ebb4caSwyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
478899ebb4caSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
478999ebb4caSwyllys 	symkey->keylabel = (char *)fullpath;
479099ebb4caSwyllys 	symkey->israw = TRUE;
479199ebb4caSwyllys 	symkey->keyp = rkey;
479299ebb4caSwyllys 
479399ebb4caSwyllys out:
479499ebb4caSwyllys 	if (fd != -1)
479599ebb4caSwyllys 		(void) close(fd);
479699ebb4caSwyllys 
479799ebb4caSwyllys 	if (ret != KMF_OK && fullpath != NULL) {
479899ebb4caSwyllys 		free(fullpath);
479999ebb4caSwyllys 	}
480099ebb4caSwyllys 	if (ret != KMF_OK) {
480130a5e8faSwyllys 		kmf_free_raw_sym_key(rkey);
480299ebb4caSwyllys 		symkey->keyp = NULL;
480399ebb4caSwyllys 		symkey->keyalg = KMF_KEYALG_NONE;
480499ebb4caSwyllys 	}
480599ebb4caSwyllys 
480699ebb4caSwyllys 	return (ret);
480799ebb4caSwyllys }
480899ebb4caSwyllys 
480999ebb4caSwyllys /*
481099ebb4caSwyllys  * Check a file to see if it is a CRL file with PEM or DER format.
481199ebb4caSwyllys  * If success, return its format in the "pformat" argument.
481299ebb4caSwyllys  */
481399ebb4caSwyllys KMF_RETURN
481499ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
481599ebb4caSwyllys {
481699ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
481799ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
481899ebb4caSwyllys 	BIO		*bio = NULL;
481999ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
482099ebb4caSwyllys 
482199ebb4caSwyllys 	if (filename == NULL) {
482299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
482399ebb4caSwyllys 	}
482499ebb4caSwyllys 
482599ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
482699ebb4caSwyllys 	if (bio == NULL)	{
482799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
482899ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
482999ebb4caSwyllys 		goto out;
483099ebb4caSwyllys 	}
483199ebb4caSwyllys 
483299ebb4caSwyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
483399ebb4caSwyllys 		*pformat = KMF_FORMAT_PEM;
483499ebb4caSwyllys 		goto out;
483599ebb4caSwyllys 	}
483699ebb4caSwyllys 	(void) BIO_free(bio);
483799ebb4caSwyllys 
483899ebb4caSwyllys 	/*
483999ebb4caSwyllys 	 * Now try to read it as raw DER data.
484099ebb4caSwyllys 	 */
484199ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
484299ebb4caSwyllys 	if (bio == NULL)	{
484399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
484499ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
484599ebb4caSwyllys 		goto out;
484699ebb4caSwyllys 	}
484799ebb4caSwyllys 
484899ebb4caSwyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
484999ebb4caSwyllys 		*pformat = KMF_FORMAT_ASN1;
485099ebb4caSwyllys 	} else {
485199ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
485299ebb4caSwyllys 	}
485399ebb4caSwyllys 
485499ebb4caSwyllys out:
485599ebb4caSwyllys 	if (bio != NULL)
485699ebb4caSwyllys 		(void) BIO_free(bio);
485799ebb4caSwyllys 
485899ebb4caSwyllys 	if (xcrl != NULL)
485999ebb4caSwyllys 		X509_CRL_free(xcrl);
486099ebb4caSwyllys 
486199ebb4caSwyllys 	return (ret);
486299ebb4caSwyllys }
486399ebb4caSwyllys 
486499ebb4caSwyllys KMF_RETURN
486599ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
486699ebb4caSwyllys     KMF_RAW_SYM_KEY *rkey)
486799ebb4caSwyllys {
486899ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
486999ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
487099ebb4caSwyllys 	KMF_DATA	keyvalue;
487199ebb4caSwyllys 
487299ebb4caSwyllys 	if (kmfh == NULL)
487399ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
487499ebb4caSwyllys 
487599ebb4caSwyllys 	if (symkey == NULL || rkey == NULL)
487699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
487799ebb4caSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
487899ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
487999ebb4caSwyllys 
488099ebb4caSwyllys 	if (symkey->israw) {
488199ebb4caSwyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
488299ebb4caSwyllys 
488399ebb4caSwyllys 		if (rawkey == NULL ||
488499ebb4caSwyllys 		    rawkey->keydata.val == NULL ||
488599ebb4caSwyllys 		    rawkey->keydata.len == 0)
488699ebb4caSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
488799ebb4caSwyllys 
488899ebb4caSwyllys 		rkey->keydata.len = rawkey->keydata.len;
488999ebb4caSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
489099ebb4caSwyllys 			return (KMF_ERR_MEMORY);
489199ebb4caSwyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
489299ebb4caSwyllys 		    rkey->keydata.len);
489399ebb4caSwyllys 	} else {
489430a5e8faSwyllys 		rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
489599ebb4caSwyllys 		if (rv != KMF_OK)
489699ebb4caSwyllys 			return (rv);
489799ebb4caSwyllys 		rkey->keydata.len = keyvalue.Length;
489899ebb4caSwyllys 		rkey->keydata.val = keyvalue.Data;
489999ebb4caSwyllys 	}
490099ebb4caSwyllys 
490199ebb4caSwyllys 	return (rv);
490299ebb4caSwyllys }
490302744e81Swyllys 
490402744e81Swyllys /*
490530a5e8faSwyllys  * substitute for the unsafe access(2) function.
490630a5e8faSwyllys  * If the file in question already exists, return 1.
490730a5e8faSwyllys  * else 0.  If an error occurs during testing (other
490830a5e8faSwyllys  * than EEXIST), return -1.
490930a5e8faSwyllys  */
491030a5e8faSwyllys static int
491130a5e8faSwyllys test_for_file(char *filename, mode_t mode)
491230a5e8faSwyllys {
491330a5e8faSwyllys 	int fd;
491430a5e8faSwyllys 
491530a5e8faSwyllys 	/*
491630a5e8faSwyllys 	 * Try to create the file with the EXCL flag.
491730a5e8faSwyllys 	 * The call should fail if the file exists.
491830a5e8faSwyllys 	 */
491930a5e8faSwyllys 	fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
492030a5e8faSwyllys 	if (fd == -1 && errno == EEXIST)
492130a5e8faSwyllys 		return (1);
492230a5e8faSwyllys 	else if (fd == -1) /* some other error */
492330a5e8faSwyllys 		return (-1);
492430a5e8faSwyllys 
492530a5e8faSwyllys 	/* The file did NOT exist.  Delete the testcase. */
492630a5e8faSwyllys 	(void) close(fd);
492730a5e8faSwyllys 	(void) unlink(filename);
492830a5e8faSwyllys 	return (0);
492930a5e8faSwyllys }
493030a5e8faSwyllys 
493130a5e8faSwyllys KMF_RETURN
493230a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
493330a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
493430a5e8faSwyllys {
493530a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
493630a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
493730a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
493830a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
493930a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
494030a5e8faSwyllys 	KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
494130a5e8faSwyllys 	KMF_CREDENTIAL cred = { NULL, 0 };
494230a5e8faSwyllys 	BIO *out = NULL;
494330a5e8faSwyllys 	int keys = 0;
494430a5e8faSwyllys 	char *fullpath = NULL;
494530a5e8faSwyllys 	char *keyfile = NULL;
494630a5e8faSwyllys 	char *dirpath = NULL;
494730a5e8faSwyllys 
494830a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
494930a5e8faSwyllys 	if (pubkey != NULL)
495030a5e8faSwyllys 		keys++;
495130a5e8faSwyllys 
495230a5e8faSwyllys 	prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
495330a5e8faSwyllys 	if (prikey != NULL)
495430a5e8faSwyllys 		keys++;
495530a5e8faSwyllys 
495630a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
495730a5e8faSwyllys 	if (rawkey != NULL)
495830a5e8faSwyllys 		keys++;
495930a5e8faSwyllys 
496030a5e8faSwyllys 	/*
496130a5e8faSwyllys 	 * Exactly 1 type of key must be passed to this function.
496230a5e8faSwyllys 	 */
496330a5e8faSwyllys 	if (keys != 1)
496430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
496530a5e8faSwyllys 
496630a5e8faSwyllys 	keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
496730a5e8faSwyllys 	    numattr);
496830a5e8faSwyllys 	if (keyfile == NULL)
496930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
497030a5e8faSwyllys 
497130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
497230a5e8faSwyllys 
497330a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
497430a5e8faSwyllys 
497530a5e8faSwyllys 	/* Once we have the full path, we don't need the pieces */
497630a5e8faSwyllys 	if (fullpath == NULL)
497730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
497830a5e8faSwyllys 
497930a5e8faSwyllys 	/* If the requested file exists, return an error */
498030a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
498130a5e8faSwyllys 		free(fullpath);
498230a5e8faSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
498330a5e8faSwyllys 	}
498430a5e8faSwyllys 
498530a5e8faSwyllys 	rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
498630a5e8faSwyllys 	    &format, NULL);
498730a5e8faSwyllys 	if (rv != KMF_OK)
498830a5e8faSwyllys 		/* format is optional. */
498930a5e8faSwyllys 		rv = KMF_OK;
499030a5e8faSwyllys 
499130a5e8faSwyllys 	/* CRED is not required for OpenSSL files */
499230a5e8faSwyllys 	(void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
499330a5e8faSwyllys 	    &cred, NULL);
499430a5e8faSwyllys 
499530a5e8faSwyllys 	/* Store the private key to the keyfile */
499630a5e8faSwyllys 	out = BIO_new_file(fullpath, "wb");
499730a5e8faSwyllys 	if (out == NULL) {
499830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
499930a5e8faSwyllys 		rv = KMF_ERR_OPEN_FILE;
500030a5e8faSwyllys 		goto end;
500130a5e8faSwyllys 	}
500230a5e8faSwyllys 
500330a5e8faSwyllys 	if (prikey != NULL && prikey->keyp != NULL) {
500430a5e8faSwyllys 		if (prikey->keyalg == KMF_RSA ||
500530a5e8faSwyllys 		    prikey->keyalg == KMF_DSA) {
500630a5e8faSwyllys 			pkey = (EVP_PKEY *)prikey->keyp;
500730a5e8faSwyllys 
500830a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
500930a5e8faSwyllys 			    out, &cred, pkey, TRUE);
501030a5e8faSwyllys 
501130a5e8faSwyllys 			if (rv == KMF_OK && prikey->keylabel == NULL) {
501230a5e8faSwyllys 				prikey->keylabel = strdup(fullpath);
501330a5e8faSwyllys 				if (prikey->keylabel == NULL)
501430a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
501530a5e8faSwyllys 			}
501630a5e8faSwyllys 		}
501730a5e8faSwyllys 	} else if (pubkey != NULL && pubkey->keyp != NULL) {
501830a5e8faSwyllys 		if (pubkey->keyalg == KMF_RSA ||
501930a5e8faSwyllys 		    pubkey->keyalg == KMF_DSA) {
502030a5e8faSwyllys 			pkey = (EVP_PKEY *)pubkey->keyp;
502130a5e8faSwyllys 
502230a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
502330a5e8faSwyllys 			    out, &cred, pkey, FALSE);
502430a5e8faSwyllys 
502530a5e8faSwyllys 			if (rv == KMF_OK && pubkey->keylabel == NULL) {
502630a5e8faSwyllys 				pubkey->keylabel = strdup(fullpath);
502730a5e8faSwyllys 				if (pubkey->keylabel == NULL)
502830a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
502930a5e8faSwyllys 			}
503030a5e8faSwyllys 		}
503130a5e8faSwyllys 	} else if (rawkey != NULL) {
503230a5e8faSwyllys 		if (rawkey->keytype == KMF_RSA) {
503330a5e8faSwyllys 			pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
503430a5e8faSwyllys 		} else if (rawkey->keytype == KMF_DSA) {
503530a5e8faSwyllys 			pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
503630a5e8faSwyllys 		} else {
503730a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
503830a5e8faSwyllys 		}
50395b3e1433Swyllys 		if (pkey != NULL) {
504073cc0e02Swyllys 			KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
504173cc0e02Swyllys 
504273cc0e02Swyllys 			rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
504373cc0e02Swyllys 			    (void *)&kclass, NULL);
504473cc0e02Swyllys 			if (rv != KMF_OK)
504573cc0e02Swyllys 				rv = KMF_OK;
50465b3e1433Swyllys 			rv = ssl_write_key(kmfh, format, out,
504773cc0e02Swyllys 			    &cred, pkey, (kclass == KMF_ASYM_PRI));
50485b3e1433Swyllys 			EVP_PKEY_free(pkey);
50495b3e1433Swyllys 		}
505030a5e8faSwyllys 	}
505130a5e8faSwyllys 
505230a5e8faSwyllys end:
505330a5e8faSwyllys 
505430a5e8faSwyllys 	if (out)
505530a5e8faSwyllys 		(void) BIO_free(out);
505630a5e8faSwyllys 
50575b3e1433Swyllys 
505830a5e8faSwyllys 	if (rv == KMF_OK)
505930a5e8faSwyllys 		(void) chmod(fullpath, 0400);
506030a5e8faSwyllys 
506130a5e8faSwyllys 	free(fullpath);
506230a5e8faSwyllys 	return (rv);
506330a5e8faSwyllys }
506430a5e8faSwyllys 
506530a5e8faSwyllys KMF_RETURN
506630a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
506730a5e8faSwyllys {
506830a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
506930a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
507030a5e8faSwyllys 	X509_CRL *xcrl = NULL;
507130a5e8faSwyllys 	X509 *xcert = NULL;
507230a5e8faSwyllys 	EVP_PKEY *pkey;
507330a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
507430a5e8faSwyllys 	BIO *in = NULL, *out = NULL;
507530a5e8faSwyllys 	int openssl_ret = 0;
507630a5e8faSwyllys 	KMF_ENCODE_FORMAT outformat;
507730a5e8faSwyllys 	boolean_t crlcheck = FALSE;
507830a5e8faSwyllys 	char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
507930a5e8faSwyllys 
508030a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
508130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
508230a5e8faSwyllys 	}
508330a5e8faSwyllys 
508430a5e8faSwyllys 	/* CRL check is optional */
508530a5e8faSwyllys 	(void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
508630a5e8faSwyllys 	    &crlcheck, NULL);
508730a5e8faSwyllys 
508830a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
508930a5e8faSwyllys 	if (crlcheck == B_TRUE && certfile == NULL) {
509030a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
509130a5e8faSwyllys 	}
509230a5e8faSwyllys 
509330a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
509430a5e8faSwyllys 	incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
509530a5e8faSwyllys 	outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
509630a5e8faSwyllys 
509730a5e8faSwyllys 	crlfile = get_fullpath(dirpath, incrl);
509830a5e8faSwyllys 
509930a5e8faSwyllys 	if (crlfile == NULL)
510030a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
510130a5e8faSwyllys 
510230a5e8faSwyllys 	outcrlfile = get_fullpath(dirpath, outcrl);
510330a5e8faSwyllys 	if (outcrlfile == NULL)
510430a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
510530a5e8faSwyllys 
510630a5e8faSwyllys 	if (isdir(outcrlfile)) {
510730a5e8faSwyllys 		free(outcrlfile);
510830a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
510930a5e8faSwyllys 	}
511030a5e8faSwyllys 
511130a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
511230a5e8faSwyllys 	if (ret != KMF_OK) {
511330a5e8faSwyllys 		free(outcrlfile);
511430a5e8faSwyllys 		return (ret);
511530a5e8faSwyllys 	}
511630a5e8faSwyllys 
511730a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
511830a5e8faSwyllys 	if (in == NULL)	{
511930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
512030a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
512130a5e8faSwyllys 		goto end;
512230a5e8faSwyllys 	}
512330a5e8faSwyllys 
512430a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
512530a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
512630a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
512730a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
512830a5e8faSwyllys 	}
512930a5e8faSwyllys 
513030a5e8faSwyllys 	if (xcrl == NULL) {
513130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
513230a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
513330a5e8faSwyllys 		goto end;
513430a5e8faSwyllys 	}
513530a5e8faSwyllys 
513630a5e8faSwyllys 	/* If bypasscheck is specified, no need to verify. */
513730a5e8faSwyllys 	if (crlcheck == B_FALSE)
513830a5e8faSwyllys 		goto output;
513930a5e8faSwyllys 
514030a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
514130a5e8faSwyllys 	if (ret != KMF_OK)
514230a5e8faSwyllys 		goto end;
514330a5e8faSwyllys 
514430a5e8faSwyllys 	/* Read in the CA cert file and convert to X509 */
514530a5e8faSwyllys 	if (BIO_read_filename(in, certfile) <= 0) {
514630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
514730a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
514830a5e8faSwyllys 		goto end;
514930a5e8faSwyllys 	}
515030a5e8faSwyllys 
515130a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
515230a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
515330a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
515430a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
515530a5e8faSwyllys 	} else {
515630a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
515730a5e8faSwyllys 		goto end;
515830a5e8faSwyllys 	}
515930a5e8faSwyllys 
516030a5e8faSwyllys 	if (xcert == NULL) {
516130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
516230a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
516330a5e8faSwyllys 		goto end;
516430a5e8faSwyllys 	}
516530a5e8faSwyllys 	/* Now get the public key from the CA cert */
516630a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
516730a5e8faSwyllys 	if (pkey == NULL) {
516830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
516930a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
517030a5e8faSwyllys 		goto end;
517130a5e8faSwyllys 	}
517230a5e8faSwyllys 
517330a5e8faSwyllys 	/* Verify the CRL with the CA's public key */
517430a5e8faSwyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
517530a5e8faSwyllys 	EVP_PKEY_free(pkey);
517630a5e8faSwyllys 	if (openssl_ret > 0) {
517730a5e8faSwyllys 		ret = KMF_OK;  /* verify succeed */
517830a5e8faSwyllys 	} else {
517930a5e8faSwyllys 		SET_ERROR(kmfh, openssl_ret);
518030a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
518130a5e8faSwyllys 	}
518230a5e8faSwyllys 
518330a5e8faSwyllys output:
518430a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
518530a5e8faSwyllys 	    &outformat, NULL);
518630a5e8faSwyllys 	if (ret != KMF_OK) {
518730a5e8faSwyllys 		ret = KMF_OK;
518830a5e8faSwyllys 		outformat = KMF_FORMAT_PEM;
518930a5e8faSwyllys 	}
519030a5e8faSwyllys 
519130a5e8faSwyllys 	out = BIO_new_file(outcrlfile, "wb");
519230a5e8faSwyllys 	if (out == NULL) {
519330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
519430a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
519530a5e8faSwyllys 		goto end;
519630a5e8faSwyllys 	}
519730a5e8faSwyllys 
519830a5e8faSwyllys 	if (outformat == KMF_FORMAT_ASN1) {
519930a5e8faSwyllys 		openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
520030a5e8faSwyllys 	} else if (outformat == KMF_FORMAT_PEM) {
520130a5e8faSwyllys 		openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
520230a5e8faSwyllys 	} else {
520330a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
520430a5e8faSwyllys 		goto end;
520530a5e8faSwyllys 	}
520630a5e8faSwyllys 
520730a5e8faSwyllys 	if (openssl_ret <= 0) {
520830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
520930a5e8faSwyllys 		ret = KMF_ERR_WRITE_FILE;
521030a5e8faSwyllys 	} else {
521130a5e8faSwyllys 		ret = KMF_OK;
521230a5e8faSwyllys 	}
521330a5e8faSwyllys 
521430a5e8faSwyllys end:
521530a5e8faSwyllys 	if (xcrl != NULL)
521630a5e8faSwyllys 		X509_CRL_free(xcrl);
521730a5e8faSwyllys 
521830a5e8faSwyllys 	if (xcert != NULL)
521930a5e8faSwyllys 		X509_free(xcert);
522030a5e8faSwyllys 
522130a5e8faSwyllys 	if (in != NULL)
522230a5e8faSwyllys 		(void) BIO_free(in);
522330a5e8faSwyllys 
522430a5e8faSwyllys 	if (out != NULL)
522530a5e8faSwyllys 		(void) BIO_free(out);
522630a5e8faSwyllys 
522730a5e8faSwyllys 	if (outcrlfile != NULL)
522830a5e8faSwyllys 		free(outcrlfile);
522930a5e8faSwyllys 
523030a5e8faSwyllys 	return (ret);
523130a5e8faSwyllys }
523230a5e8faSwyllys 
523330a5e8faSwyllys KMF_RETURN
523430a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
523530a5e8faSwyllys {
523630a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
523730a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
523830a5e8faSwyllys 	X509_CRL   *x = NULL;
523930a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
524030a5e8faSwyllys 	char *crlfile = NULL;
524130a5e8faSwyllys 	BIO *in = NULL;
524230a5e8faSwyllys 	BIO *mem = NULL;
524330a5e8faSwyllys 	long len;
524430a5e8faSwyllys 	char *memptr;
524530a5e8faSwyllys 	char *data = NULL;
524630a5e8faSwyllys 	char **crldata;
524730a5e8faSwyllys 	char *crlfilename, *dirpath;
524830a5e8faSwyllys 
524930a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
525030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
525130a5e8faSwyllys 	}
525230a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
525330a5e8faSwyllys 	    attrlist, numattr);
525430a5e8faSwyllys 	if (crlfilename == NULL)
525530a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
525630a5e8faSwyllys 
525730a5e8faSwyllys 	crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
525830a5e8faSwyllys 	    attrlist, numattr);
525930a5e8faSwyllys 
526030a5e8faSwyllys 	if (crldata == NULL)
526130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
526230a5e8faSwyllys 
526330a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
526430a5e8faSwyllys 
526530a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
526630a5e8faSwyllys 
526730a5e8faSwyllys 	if (crlfile == NULL)
526830a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
526930a5e8faSwyllys 
527030a5e8faSwyllys 	if (isdir(crlfile)) {
527130a5e8faSwyllys 		free(crlfile);
527230a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
527330a5e8faSwyllys 	}
527430a5e8faSwyllys 
527530a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
527630a5e8faSwyllys 	if (ret != KMF_OK) {
527730a5e8faSwyllys 		free(crlfile);
527830a5e8faSwyllys 		return (ret);
527930a5e8faSwyllys 	}
528030a5e8faSwyllys 
528130a5e8faSwyllys 	if (bio_err == NULL)
528230a5e8faSwyllys 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
528330a5e8faSwyllys 
528430a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
528530a5e8faSwyllys 	if (in == NULL)	{
528630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
528730a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
528830a5e8faSwyllys 		goto end;
528930a5e8faSwyllys 	}
529030a5e8faSwyllys 
529130a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
529230a5e8faSwyllys 		x = d2i_X509_CRL_bio(in, NULL);
529330a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
529430a5e8faSwyllys 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
529530a5e8faSwyllys 	}
529630a5e8faSwyllys 
529730a5e8faSwyllys 	if (x == NULL) { /* should not happen */
529830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
529930a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
530030a5e8faSwyllys 		goto end;
530130a5e8faSwyllys 	}
530230a5e8faSwyllys 
530330a5e8faSwyllys 	mem = BIO_new(BIO_s_mem());
530430a5e8faSwyllys 	if (mem == NULL) {
530530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
530630a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
530730a5e8faSwyllys 		goto end;
530830a5e8faSwyllys 	}
530930a5e8faSwyllys 
531030a5e8faSwyllys 	(void) X509_CRL_print(mem, x);
531130a5e8faSwyllys 	len = BIO_get_mem_data(mem, &memptr);
531230a5e8faSwyllys 	if (len <= 0) {
531330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
531430a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
531530a5e8faSwyllys 		goto end;
531630a5e8faSwyllys 	}
531730a5e8faSwyllys 
531830a5e8faSwyllys 	data = malloc(len + 1);
531930a5e8faSwyllys 	if (data == NULL) {
532030a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
532130a5e8faSwyllys 		goto end;
532230a5e8faSwyllys 	}
532330a5e8faSwyllys 
532430a5e8faSwyllys 	(void) memcpy(data, memptr, len);
532530a5e8faSwyllys 	data[len] = '\0';
532630a5e8faSwyllys 	*crldata = data;
532730a5e8faSwyllys 
532830a5e8faSwyllys end:
532930a5e8faSwyllys 	if (x != NULL)
533030a5e8faSwyllys 		X509_CRL_free(x);
533130a5e8faSwyllys 
533230a5e8faSwyllys 	if (crlfile != NULL)
533330a5e8faSwyllys 		free(crlfile);
533430a5e8faSwyllys 
533530a5e8faSwyllys 	if (in != NULL)
533630a5e8faSwyllys 		(void) BIO_free(in);
533730a5e8faSwyllys 
533830a5e8faSwyllys 	if (mem != NULL)
533930a5e8faSwyllys 		(void) BIO_free(mem);
534030a5e8faSwyllys 
534130a5e8faSwyllys 	return (ret);
534230a5e8faSwyllys }
534330a5e8faSwyllys 
534430a5e8faSwyllys KMF_RETURN
534530a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
534630a5e8faSwyllys {
534730a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
534830a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
534930a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
535030a5e8faSwyllys 	char *crlfile = NULL;
535130a5e8faSwyllys 	BIO *in = NULL;
535230a5e8faSwyllys 	char *crlfilename, *dirpath;
535330a5e8faSwyllys 
535430a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
535530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
535630a5e8faSwyllys 	}
535730a5e8faSwyllys 
535830a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
535930a5e8faSwyllys 	    attrlist, numattr);
536030a5e8faSwyllys 
536130a5e8faSwyllys 	if (crlfilename == NULL)
536230a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
536330a5e8faSwyllys 
536430a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
536530a5e8faSwyllys 
536630a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
536730a5e8faSwyllys 
536830a5e8faSwyllys 	if (crlfile == NULL)
536930a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
537030a5e8faSwyllys 
537130a5e8faSwyllys 	if (isdir(crlfile)) {
537230a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
537330a5e8faSwyllys 		goto end;
537430a5e8faSwyllys 	}
537530a5e8faSwyllys 
537630a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
537730a5e8faSwyllys 	if (ret != KMF_OK)
537830a5e8faSwyllys 		goto end;
537930a5e8faSwyllys 
538030a5e8faSwyllys 	if (unlink(crlfile) != 0) {
538130a5e8faSwyllys 		SET_SYS_ERROR(kmfh, errno);
538230a5e8faSwyllys 		ret = KMF_ERR_INTERNAL;
538330a5e8faSwyllys 		goto end;
538430a5e8faSwyllys 	}
538530a5e8faSwyllys 
538630a5e8faSwyllys end:
538730a5e8faSwyllys 	if (in != NULL)
538830a5e8faSwyllys 		(void) BIO_free(in);
538930a5e8faSwyllys 	if (crlfile != NULL)
539030a5e8faSwyllys 		free(crlfile);
539130a5e8faSwyllys 
539230a5e8faSwyllys 	return (ret);
539330a5e8faSwyllys }
539430a5e8faSwyllys 
539530a5e8faSwyllys KMF_RETURN
539630a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
539730a5e8faSwyllys {
539830a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
539930a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
540030a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
540130a5e8faSwyllys 	BIO *in = NULL;
540230a5e8faSwyllys 	X509   *xcert = NULL;
540330a5e8faSwyllys 	X509_CRL   *xcrl = NULL;
540430a5e8faSwyllys 	STACK_OF(X509_REVOKED) *revoke_stack = NULL;
540530a5e8faSwyllys 	X509_REVOKED *revoke;
540630a5e8faSwyllys 	int i;
540730a5e8faSwyllys 	char *crlfilename, *crlfile, *dirpath, *certfile;
540830a5e8faSwyllys 
540930a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
541030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
541130a5e8faSwyllys 	}
541230a5e8faSwyllys 
541330a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
541430a5e8faSwyllys 	    attrlist, numattr);
541530a5e8faSwyllys 
541630a5e8faSwyllys 	if (crlfilename == NULL)
541730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
541830a5e8faSwyllys 
541930a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
542030a5e8faSwyllys 	if (certfile == NULL)
542130a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
542230a5e8faSwyllys 
542330a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
542430a5e8faSwyllys 
542530a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
542630a5e8faSwyllys 
542730a5e8faSwyllys 	if (crlfile == NULL)
542830a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
542930a5e8faSwyllys 
543030a5e8faSwyllys 	if (isdir(crlfile)) {
543130a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
543230a5e8faSwyllys 		goto end;
543330a5e8faSwyllys 	}
543430a5e8faSwyllys 
543530a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
543630a5e8faSwyllys 	if (ret != KMF_OK)
543730a5e8faSwyllys 		goto end;
543830a5e8faSwyllys 
543930a5e8faSwyllys 	/* Read the CRL file and load it into a X509_CRL structure */
544030a5e8faSwyllys 	in = BIO_new_file(crlfilename, "rb");
544130a5e8faSwyllys 	if (in == NULL)	{
544230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
544330a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
544430a5e8faSwyllys 		goto end;
544530a5e8faSwyllys 	}
544630a5e8faSwyllys 
544730a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
544830a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
544930a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
545030a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
545130a5e8faSwyllys 	}
545230a5e8faSwyllys 
545330a5e8faSwyllys 	if (xcrl == NULL) {
545430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
545530a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
545630a5e8faSwyllys 		goto end;
545730a5e8faSwyllys 	}
545830a5e8faSwyllys 	(void) BIO_free(in);
545930a5e8faSwyllys 
546030a5e8faSwyllys 	/* Read the Certificate file and load it into a X509 structure */
546130a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
546230a5e8faSwyllys 	if (ret != KMF_OK)
546330a5e8faSwyllys 		goto end;
546430a5e8faSwyllys 
546530a5e8faSwyllys 	in = BIO_new_file(certfile, "rb");
546630a5e8faSwyllys 	if (in == NULL)	{
546730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
546830a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
546930a5e8faSwyllys 		goto end;
547030a5e8faSwyllys 	}
547130a5e8faSwyllys 
547230a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
547330a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
547430a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
547530a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
547630a5e8faSwyllys 	}
547730a5e8faSwyllys 
547830a5e8faSwyllys 	if (xcert == NULL) {
547930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
548030a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
548130a5e8faSwyllys 		goto end;
548230a5e8faSwyllys 	}
548330a5e8faSwyllys 
548430a5e8faSwyllys 	/* Check if the certificate and the CRL have same issuer */
5485300fdee2SAndy Fiddaman 	if (X509_NAME_cmp(X509_get_issuer_name(xcert),
5486300fdee2SAndy Fiddaman 	    X509_CRL_get_issuer(xcrl)) != 0) {
548730a5e8faSwyllys 		ret = KMF_ERR_ISSUER;
548830a5e8faSwyllys 		goto end;
548930a5e8faSwyllys 	}
549030a5e8faSwyllys 
549130a5e8faSwyllys 	/* Check to see if the certificate serial number is revoked */
549230a5e8faSwyllys 	revoke_stack = X509_CRL_get_REVOKED(xcrl);
549330a5e8faSwyllys 	if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
549430a5e8faSwyllys 		/* No revoked certificates in the CRL file */
549530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
549630a5e8faSwyllys 		ret = KMF_ERR_EMPTY_CRL;
549730a5e8faSwyllys 		goto end;
549830a5e8faSwyllys 	}
549930a5e8faSwyllys 
550030a5e8faSwyllys 	for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
5501d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
550230a5e8faSwyllys 		revoke = sk_X509_REVOKED_value(revoke_stack, i);
5503300fdee2SAndy Fiddaman 		if (ASN1_INTEGER_cmp(X509_get_serialNumber(xcert),
5504300fdee2SAndy Fiddaman 		    X509_REVOKED_get0_serialNumber(revoke)) == 0) {
550530a5e8faSwyllys 			break;
550630a5e8faSwyllys 		}
550730a5e8faSwyllys 	}
550830a5e8faSwyllys 
550930a5e8faSwyllys 	if (i < sk_X509_REVOKED_num(revoke_stack)) {
551030a5e8faSwyllys 		ret = KMF_OK;
551130a5e8faSwyllys 	} else {
551230a5e8faSwyllys 		ret = KMF_ERR_NOT_REVOKED;
551330a5e8faSwyllys 	}
551430a5e8faSwyllys 
551530a5e8faSwyllys end:
551630a5e8faSwyllys 	if (in != NULL)
551730a5e8faSwyllys 		(void) BIO_free(in);
551830a5e8faSwyllys 	if (xcrl != NULL)
551930a5e8faSwyllys 		X509_CRL_free(xcrl);
552030a5e8faSwyllys 	if (xcert != NULL)
552130a5e8faSwyllys 		X509_free(xcert);
552230a5e8faSwyllys 
552330a5e8faSwyllys 	return (ret);
552430a5e8faSwyllys }
552530a5e8faSwyllys 
552630a5e8faSwyllys KMF_RETURN
552730a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
552830a5e8faSwyllys {
552930a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
553030a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
553130a5e8faSwyllys 	BIO		*bcrl = NULL;
553230a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
553330a5e8faSwyllys 	X509		*xcert = NULL;
553430a5e8faSwyllys 	EVP_PKEY	*pkey;
553530a5e8faSwyllys 	int		sslret;
553630a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
553730a5e8faSwyllys 	unsigned char	*p;
553830a5e8faSwyllys 	long		len;
553930a5e8faSwyllys 
554030a5e8faSwyllys 	if (handle == NULL || crlname == NULL || tacert == NULL) {
554130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
554230a5e8faSwyllys 	}
554330a5e8faSwyllys 
554430a5e8faSwyllys 	ret = kmf_get_file_format(crlname, &crl_format);
554530a5e8faSwyllys 	if (ret != KMF_OK)
554630a5e8faSwyllys 		return (ret);
554730a5e8faSwyllys 
554830a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
554930a5e8faSwyllys 	if (bcrl == NULL)	{
555030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
555130a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
555230a5e8faSwyllys 		goto cleanup;
555330a5e8faSwyllys 	}
555430a5e8faSwyllys 
555530a5e8faSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
555630a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
555730a5e8faSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
555830a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
555930a5e8faSwyllys 	} else {
556030a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
556130a5e8faSwyllys 		goto cleanup;
556230a5e8faSwyllys 	}
556330a5e8faSwyllys 
556430a5e8faSwyllys 	if (xcrl == NULL) {
556530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
556630a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
556730a5e8faSwyllys 		goto cleanup;
556830a5e8faSwyllys 	}
556930a5e8faSwyllys 
557030a5e8faSwyllys 	p = tacert->Data;
557130a5e8faSwyllys 	len = tacert->Length;
557230a5e8faSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
557330a5e8faSwyllys 
557430a5e8faSwyllys 	if (xcert == NULL) {
557530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
557630a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
557730a5e8faSwyllys 		goto cleanup;
557830a5e8faSwyllys 	}
557930a5e8faSwyllys 
558030a5e8faSwyllys 	/* Get issuer certificate public key */
558130a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
558230a5e8faSwyllys 	if (pkey == NULL) {
558330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
558430a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
558530a5e8faSwyllys 		goto cleanup;
558630a5e8faSwyllys 	}
558730a5e8faSwyllys 
558830a5e8faSwyllys 	/* Verify CRL signature */
558930a5e8faSwyllys 	sslret = X509_CRL_verify(xcrl, pkey);
559030a5e8faSwyllys 	EVP_PKEY_free(pkey);
559130a5e8faSwyllys 	if (sslret > 0) {
559230a5e8faSwyllys 		ret = KMF_OK;
559330a5e8faSwyllys 	} else {
559430a5e8faSwyllys 		SET_ERROR(kmfh, sslret);
559530a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
559630a5e8faSwyllys 	}
559730a5e8faSwyllys 
559830a5e8faSwyllys cleanup:
559930a5e8faSwyllys 	if (bcrl != NULL)
560030a5e8faSwyllys 		(void) BIO_free(bcrl);
560130a5e8faSwyllys 
560230a5e8faSwyllys 	if (xcrl != NULL)
560330a5e8faSwyllys 		X509_CRL_free(xcrl);
560430a5e8faSwyllys 
560530a5e8faSwyllys 	if (xcert != NULL)
560630a5e8faSwyllys 		X509_free(xcert);
560730a5e8faSwyllys 
560830a5e8faSwyllys 	return (ret);
560930a5e8faSwyllys 
561030a5e8faSwyllys }
561130a5e8faSwyllys 
561230a5e8faSwyllys KMF_RETURN
561330a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
561430a5e8faSwyllys {
561530a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
561630a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
561730a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
561830a5e8faSwyllys 	BIO		*bcrl = NULL;
561930a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
562030a5e8faSwyllys 	int		i;
562130a5e8faSwyllys 
562230a5e8faSwyllys 	if (handle == NULL || crlname == NULL) {
562330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
562430a5e8faSwyllys 	}
562530a5e8faSwyllys 
562630a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlname, &crl_format);
562730a5e8faSwyllys 	if (ret != KMF_OK)
562830a5e8faSwyllys 		return (ret);
562930a5e8faSwyllys 
563030a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
563130a5e8faSwyllys 	if (bcrl == NULL) {
563230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
563330a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
563430a5e8faSwyllys 		goto cleanup;
563530a5e8faSwyllys 	}
563630a5e8faSwyllys 
56375b3e1433Swyllys 	if (crl_format == KMF_FORMAT_ASN1)
563830a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
56395b3e1433Swyllys 	else if (crl_format == KMF_FORMAT_PEM)
564030a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
564130a5e8faSwyllys 
564230a5e8faSwyllys 	if (xcrl == NULL) {
564330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
564430a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
564530a5e8faSwyllys 		goto cleanup;
564630a5e8faSwyllys 	}
5647300fdee2SAndy Fiddaman 	i = X509_cmp_time(X509_CRL_get0_lastUpdate(xcrl), NULL);
564830a5e8faSwyllys 	if (i >= 0) {
564930a5e8faSwyllys 		ret = KMF_ERR_VALIDITY_PERIOD;
565030a5e8faSwyllys 		goto cleanup;
565130a5e8faSwyllys 	}
5652300fdee2SAndy Fiddaman 	if (X509_CRL_get0_nextUpdate(xcrl)) {
5653300fdee2SAndy Fiddaman 		i = X509_cmp_time(X509_CRL_get0_nextUpdate(xcrl), NULL);
565430a5e8faSwyllys 
565530a5e8faSwyllys 		if (i <= 0) {
565630a5e8faSwyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
565730a5e8faSwyllys 			goto cleanup;
565830a5e8faSwyllys 		}
565930a5e8faSwyllys 	}
566030a5e8faSwyllys 
566130a5e8faSwyllys 	ret = KMF_OK;
566230a5e8faSwyllys 
566330a5e8faSwyllys cleanup:
566430a5e8faSwyllys 	if (bcrl != NULL)
566530a5e8faSwyllys 		(void) BIO_free(bcrl);
566630a5e8faSwyllys 
566730a5e8faSwyllys 	if (xcrl != NULL)
566830a5e8faSwyllys 		X509_CRL_free(xcrl);
566930a5e8faSwyllys 
567030a5e8faSwyllys 	return (ret);
567130a5e8faSwyllys }
5672