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.
8*300fdee2SAndy Fiddaman  * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
970f9559bSTheo Schlossnagle  */
1070f9559bSTheo Schlossnagle /*
119a767088Shaimay  * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
129a767088Shaimay  * project 2000.
139a767088Shaimay  */
149a767088Shaimay /*
159a767088Shaimay  * ====================================================================
169a767088Shaimay  * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
179a767088Shaimay  *
189a767088Shaimay  * Redistribution and use in source and binary forms, with or without
199a767088Shaimay  * modification, are permitted provided that the following conditions
209a767088Shaimay  * are met:
219a767088Shaimay  *
229a767088Shaimay  * 1. Redistributions of source code must retain the above copyright
239a767088Shaimay  *    notice, this list of conditions and the following disclaimer.
249a767088Shaimay  *
259a767088Shaimay  * 2. Redistributions in binary form must reproduce the above copyright
269a767088Shaimay  *    notice, this list of conditions and the following disclaimer in
279a767088Shaimay  *    the documentation and/or other materials provided with the
289a767088Shaimay  *    distribution.
299a767088Shaimay  *
309a767088Shaimay  * 3. All advertising materials mentioning features or use of this
319a767088Shaimay  *    software must display the following acknowledgment:
329a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
339a767088Shaimay  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
349a767088Shaimay  *
359a767088Shaimay  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
369a767088Shaimay  *    endorse or promote products derived from this software without
379a767088Shaimay  *    prior written permission. For written permission, please contact
389a767088Shaimay  *    licensing@OpenSSL.org.
399a767088Shaimay  *
409a767088Shaimay  * 5. Products derived from this software may not be called "OpenSSL"
419a767088Shaimay  *    nor may "OpenSSL" appear in their names without prior written
429a767088Shaimay  *    permission of the OpenSSL Project.
439a767088Shaimay  *
449a767088Shaimay  * 6. Redistributions of any form whatsoever must retain the following
459a767088Shaimay  *    acknowledgment:
469a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
479a767088Shaimay  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
489a767088Shaimay  *
499a767088Shaimay  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
509a767088Shaimay  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
519a767088Shaimay  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
529a767088Shaimay  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
539a767088Shaimay  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
549a767088Shaimay  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
559a767088Shaimay  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
569a767088Shaimay  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
579a767088Shaimay  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
589a767088Shaimay  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
599a767088Shaimay  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
609a767088Shaimay  * OF THE POSSIBILITY OF SUCH DAMAGE.
619a767088Shaimay  * ====================================================================
629a767088Shaimay  *
639a767088Shaimay  * This product includes cryptographic software written by Eric Young
649a767088Shaimay  * (eay@cryptsoft.com).  This product includes software written by Tim
659a767088Shaimay  * Hudson (tjh@cryptsoft.com).
669a767088Shaimay  *
679a767088Shaimay  */
6899ebb4caSwyllys 
6971593db2Swyllys #include <stdlib.h>
7099ebb4caSwyllys #include <kmfapiP.h>
7199ebb4caSwyllys #include <ber_der.h>
7299ebb4caSwyllys #include <fcntl.h>
7399ebb4caSwyllys #include <sys/stat.h>
7499ebb4caSwyllys #include <dirent.h>
7599ebb4caSwyllys #include <cryptoutil.h>
7699ebb4caSwyllys #include <synch.h>
7799ebb4caSwyllys #include <thread.h>
7899ebb4caSwyllys 
7999ebb4caSwyllys /* OPENSSL related headers */
8099ebb4caSwyllys #include <openssl/bio.h>
8199ebb4caSwyllys #include <openssl/bn.h>
8299ebb4caSwyllys #include <openssl/asn1.h>
8399ebb4caSwyllys #include <openssl/err.h>
8499ebb4caSwyllys #include <openssl/x509.h>
8599ebb4caSwyllys #include <openssl/rsa.h>
8699ebb4caSwyllys #include <openssl/dsa.h>
8799ebb4caSwyllys #include <openssl/x509v3.h>
8899ebb4caSwyllys #include <openssl/objects.h>
8999ebb4caSwyllys #include <openssl/pem.h>
9099ebb4caSwyllys #include <openssl/pkcs12.h>
9199ebb4caSwyllys #include <openssl/ocsp.h>
9299ebb4caSwyllys #include <openssl/des.h>
9399ebb4caSwyllys #include <openssl/rand.h>
94*300fdee2SAndy Fiddaman #include "compat.h"
9599ebb4caSwyllys 
9699ebb4caSwyllys #define	PRINT_ANY_EXTENSION (\
9799ebb4caSwyllys 	KMF_X509_EXT_KEY_USAGE |\
9899ebb4caSwyllys 	KMF_X509_EXT_CERT_POLICIES |\
9999ebb4caSwyllys 	KMF_X509_EXT_SUBJALTNAME |\
10099ebb4caSwyllys 	KMF_X509_EXT_BASIC_CONSTRAINTS |\
10199ebb4caSwyllys 	KMF_X509_EXT_NAME_CONSTRAINTS |\
10299ebb4caSwyllys 	KMF_X509_EXT_POLICY_CONSTRAINTS |\
10399ebb4caSwyllys 	KMF_X509_EXT_EXT_KEY_USAGE |\
10499ebb4caSwyllys 	KMF_X509_EXT_INHIBIT_ANY_POLICY |\
10599ebb4caSwyllys 	KMF_X509_EXT_AUTH_KEY_ID |\
10699ebb4caSwyllys 	KMF_X509_EXT_SUBJ_KEY_ID |\
10799ebb4caSwyllys 	KMF_X509_EXT_POLICY_MAPPING)
10899ebb4caSwyllys 
10999ebb4caSwyllys static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
11099ebb4caSwyllys 	0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
11199ebb4caSwyllys 	0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
11299ebb4caSwyllys 	0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
11399ebb4caSwyllys 	0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
11499ebb4caSwyllys 	0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
11599ebb4caSwyllys 	0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
11699ebb4caSwyllys 	0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
11799ebb4caSwyllys 	0x91 };
11899ebb4caSwyllys 
11999ebb4caSwyllys static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
12099ebb4caSwyllys 	0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
12199ebb4caSwyllys 	0x8e, 0xda, 0xce, 0x91, 0x5f };
12299ebb4caSwyllys 
12399ebb4caSwyllys static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
12499ebb4caSwyllys 	0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
12599ebb4caSwyllys 	0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
12699ebb4caSwyllys 	0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
12799ebb4caSwyllys 	0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
12899ebb4caSwyllys 	0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
12999ebb4caSwyllys 	0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
13099ebb4caSwyllys 	0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
13199ebb4caSwyllys 	0x02 };
13299ebb4caSwyllys 
13399ebb4caSwyllys #define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
13499ebb4caSwyllys 	h->lasterr.errcode = c;
13599ebb4caSwyllys 
13699ebb4caSwyllys #define	SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
13799ebb4caSwyllys 
1385b3e1433Swyllys /*
139bf5d9f18SAndy Fiddaman  * Declare some new macros for managing stacks of EVP_PKEYS.
1405b3e1433Swyllys  */
141*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L
1425b3e1433Swyllys DECLARE_STACK_OF(EVP_PKEY)
1435b3e1433Swyllys 
1445b3e1433Swyllys #define	sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
1455b3e1433Swyllys #define	sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
1465b3e1433Swyllys #define	sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
1475b3e1433Swyllys #define	sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
1485b3e1433Swyllys #define	sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
1495b3e1433Swyllys #define	sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
1505b3e1433Swyllys 	(free_func))
1515b3e1433Swyllys 
152*300fdee2SAndy Fiddaman #else
153*300fdee2SAndy Fiddaman /* LINTED E_STATIC_UNUSED */
154*300fdee2SAndy Fiddaman DEFINE_STACK_OF(EVP_PKEY)
155*300fdee2SAndy Fiddaman #endif
156*300fdee2SAndy Fiddaman 
15799ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX;
15899ebb4caSwyllys static int ssl_initialized = 0;
15930a5e8faSwyllys static BIO *bio_err = NULL;
16030a5e8faSwyllys 
16130a5e8faSwyllys static int
16230a5e8faSwyllys test_for_file(char *, mode_t);
1635b3e1433Swyllys static KMF_RETURN
1645b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *, char *, int,
1655b3e1433Swyllys     STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
1665b3e1433Swyllys 
1675b3e1433Swyllys static KMF_RETURN
1685b3e1433Swyllys local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *,
1695b3e1433Swyllys     int, KMF_KEY_HANDLE *, char *);
1705b3e1433Swyllys 
1715b3e1433Swyllys static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int);
17299ebb4caSwyllys 
17371593db2Swyllys static KMF_RETURN
17430a5e8faSwyllys extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *,
17502744e81Swyllys     CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
17671593db2Swyllys 
17771593db2Swyllys static KMF_RETURN
17830a5e8faSwyllys kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
17930a5e8faSwyllys     char *, KMF_DATA *);
18030a5e8faSwyllys 
18130a5e8faSwyllys static KMF_RETURN
18230a5e8faSwyllys load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
18330a5e8faSwyllys     char *, KMF_DATA **, uint32_t *);
18471593db2Swyllys 
18502744e81Swyllys static KMF_RETURN
18602744e81Swyllys sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
18702744e81Swyllys 
18802744e81Swyllys static EVP_PKEY *
18902744e81Swyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *);
19002744e81Swyllys 
19130a5e8faSwyllys static KMF_RETURN
19230a5e8faSwyllys convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
19330a5e8faSwyllys 
19499ebb4caSwyllys KMF_RETURN
19530a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
19699ebb4caSwyllys 
19799ebb4caSwyllys void
19899ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
19999ebb4caSwyllys 
20099ebb4caSwyllys KMF_RETURN
20130a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
20299ebb4caSwyllys 
20399ebb4caSwyllys KMF_RETURN
20430a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
20599ebb4caSwyllys 
20699ebb4caSwyllys KMF_RETURN
20730a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20830a5e8faSwyllys 
20930a5e8faSwyllys KMF_RETURN
21030a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21199ebb4caSwyllys 
21299ebb4caSwyllys KMF_RETURN
21399ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T,  KMF_KEY_HANDLE *, KMF_DATA *);
21499ebb4caSwyllys 
21599ebb4caSwyllys KMF_RETURN
21699ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
21799ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
21899ebb4caSwyllys 
21999ebb4caSwyllys KMF_RETURN
22030a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22199ebb4caSwyllys 
22299ebb4caSwyllys KMF_RETURN
22330a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22499ebb4caSwyllys 
22599ebb4caSwyllys KMF_RETURN
22630a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22799ebb4caSwyllys 
22899ebb4caSwyllys KMF_RETURN
22930a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23099ebb4caSwyllys 
23199ebb4caSwyllys KMF_RETURN
23230a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23399ebb4caSwyllys 
23499ebb4caSwyllys KMF_RETURN
23599ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
23699ebb4caSwyllys 	KMF_PRINTABLE_ITEM, char *);
23799ebb4caSwyllys 
23899ebb4caSwyllys KMF_RETURN
23999ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
24099ebb4caSwyllys 
24199ebb4caSwyllys KMF_RETURN
24230a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
24399ebb4caSwyllys 
24499ebb4caSwyllys KMF_RETURN
24599ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
24699ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
24799ebb4caSwyllys 
24899ebb4caSwyllys KMF_RETURN
24930a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25099ebb4caSwyllys 
25199ebb4caSwyllys KMF_RETURN
25230a5e8faSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25399ebb4caSwyllys 
25499ebb4caSwyllys KMF_RETURN
25530a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25699ebb4caSwyllys 
25799ebb4caSwyllys KMF_RETURN
25830a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
25999ebb4caSwyllys 
26099ebb4caSwyllys KMF_RETURN
26130a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
26299ebb4caSwyllys 
26399ebb4caSwyllys KMF_RETURN
26499ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
26599ebb4caSwyllys 
26699ebb4caSwyllys KMF_RETURN
26730a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
26899ebb4caSwyllys 
26999ebb4caSwyllys KMF_RETURN
27030a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
27199ebb4caSwyllys 
27299ebb4caSwyllys static
27399ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table =
27499ebb4caSwyllys {
27599ebb4caSwyllys 	1,				/* Version */
27699ebb4caSwyllys 	NULL, /* ConfigureKeystore */
27799ebb4caSwyllys 	OpenSSL_FindCert,
27899ebb4caSwyllys 	OpenSSL_FreeKMFCert,
27999ebb4caSwyllys 	OpenSSL_StoreCert,
28099ebb4caSwyllys 	NULL, /* ImportCert */
28199ebb4caSwyllys 	OpenSSL_ImportCRL,
28299ebb4caSwyllys 	OpenSSL_DeleteCert,
28399ebb4caSwyllys 	OpenSSL_DeleteCRL,
28499ebb4caSwyllys 	OpenSSL_CreateKeypair,
28599ebb4caSwyllys 	OpenSSL_FindKey,
28699ebb4caSwyllys 	OpenSSL_EncodePubKeyData,
28799ebb4caSwyllys 	OpenSSL_SignData,
28899ebb4caSwyllys 	OpenSSL_DeleteKey,
28999ebb4caSwyllys 	OpenSSL_ListCRL,
29099ebb4caSwyllys 	NULL,	/* FindCRL */
29199ebb4caSwyllys 	OpenSSL_FindCertInCRL,
29299ebb4caSwyllys 	OpenSSL_GetErrorString,
29330a5e8faSwyllys 	OpenSSL_FindPrikeyByCert,
29499ebb4caSwyllys 	OpenSSL_DecryptData,
29530a5e8faSwyllys 	OpenSSL_ExportPK12,
29699ebb4caSwyllys 	OpenSSL_CreateSymKey,
29799ebb4caSwyllys 	OpenSSL_GetSymKeyValue,
29899ebb4caSwyllys 	NULL,	/* SetTokenPin */
29930a5e8faSwyllys 	OpenSSL_StoreKey,
30099ebb4caSwyllys 	NULL	/* Finalize */
30199ebb4caSwyllys };
30299ebb4caSwyllys 
303*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L
30499ebb4caSwyllys static mutex_t *lock_cs;
30599ebb4caSwyllys static long *lock_count;
30699ebb4caSwyllys 
30799ebb4caSwyllys static void
308a2d4930dSDan OpenSolaris Anderson /* ARGSUSED1 */
30999ebb4caSwyllys locking_cb(int mode, int type, char *file, int line)
31099ebb4caSwyllys {
31199ebb4caSwyllys 	if (mode & CRYPTO_LOCK) {
31299ebb4caSwyllys 		(void) mutex_lock(&(lock_cs[type]));
31399ebb4caSwyllys 		lock_count[type]++;
31499ebb4caSwyllys 	} else {
31599ebb4caSwyllys 		(void) mutex_unlock(&(lock_cs[type]));
31699ebb4caSwyllys 	}
31799ebb4caSwyllys }
31899ebb4caSwyllys 
31999ebb4caSwyllys static unsigned long
32099ebb4caSwyllys thread_id()
32199ebb4caSwyllys {
32299ebb4caSwyllys 	return ((unsigned long)thr_self());
32399ebb4caSwyllys }
324*300fdee2SAndy Fiddaman #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
32599ebb4caSwyllys 
32699ebb4caSwyllys KMF_PLUGIN_FUNCLIST *
32799ebb4caSwyllys KMF_Plugin_Initialize()
32899ebb4caSwyllys {
329*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L
33099ebb4caSwyllys 	int i;
331*300fdee2SAndy Fiddaman #endif
33299ebb4caSwyllys 
33399ebb4caSwyllys 	(void) mutex_lock(&init_lock);
33499ebb4caSwyllys 	if (!ssl_initialized) {
33599ebb4caSwyllys 		/*
33699ebb4caSwyllys 		 * Add support for extension OIDs that are not yet in the
33799ebb4caSwyllys 		 * openssl default set.
33899ebb4caSwyllys 		 */
33999ebb4caSwyllys 		(void) OBJ_create("2.5.29.30", "nameConstraints",
34099ebb4caSwyllys 		    "X509v3 Name Constraints");
34199ebb4caSwyllys 		(void) OBJ_create("2.5.29.33", "policyMappings",
34299ebb4caSwyllys 		    "X509v3 Policy Mappings");
34399ebb4caSwyllys 		(void) OBJ_create("2.5.29.36", "policyConstraints",
34499ebb4caSwyllys 		    "X509v3 Policy Constraints");
34599ebb4caSwyllys 		(void) OBJ_create("2.5.29.46", "freshestCRL",
34699ebb4caSwyllys 		    "X509v3 Freshest CRL");
34799ebb4caSwyllys 		(void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
34899ebb4caSwyllys 		    "X509v3 Inhibit Any-Policy");
349*300fdee2SAndy Fiddaman 
350*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L
35199ebb4caSwyllys 		/*
35299ebb4caSwyllys 		 * Set up for thread-safe operation.
353*300fdee2SAndy Fiddaman 		 * This is not required for OpenSSL 1.1
35499ebb4caSwyllys 		 */
35599ebb4caSwyllys 		lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
35699ebb4caSwyllys 		if (lock_cs == NULL) {
35799ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
35899ebb4caSwyllys 			return (NULL);
35999ebb4caSwyllys 		}
36099ebb4caSwyllys 
36199ebb4caSwyllys 		lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
36299ebb4caSwyllys 		if (lock_count == NULL) {
36399ebb4caSwyllys 			OPENSSL_free(lock_cs);
36499ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
36599ebb4caSwyllys 			return (NULL);
36699ebb4caSwyllys 		}
36799ebb4caSwyllys 
36899ebb4caSwyllys 		for (i = 0; i < CRYPTO_num_locks(); i++) {
36999ebb4caSwyllys 			lock_count[i] = 0;
37099ebb4caSwyllys 			(void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
37199ebb4caSwyllys 		}
37299ebb4caSwyllys 
37399ebb4caSwyllys 		CRYPTO_set_id_callback((unsigned long (*)())thread_id);
3742c9a247fSWyllys Ingersoll 		if (CRYPTO_get_locking_callback() == NULL)
37599ebb4caSwyllys 			CRYPTO_set_locking_callback((void (*)())locking_cb);
3762c9a247fSWyllys Ingersoll 
377*300fdee2SAndy Fiddaman 		(void) OpenSSL_add_all_algorithms();
3782c9a247fSWyllys Ingersoll 
3792c9a247fSWyllys Ingersoll 		/* Enable error strings for reporting */
380*300fdee2SAndy Fiddaman 		(void) ERR_load_crypto_strings();
381*300fdee2SAndy Fiddaman #endif
3822c9a247fSWyllys Ingersoll 
38399ebb4caSwyllys 		ssl_initialized = 1;
38499ebb4caSwyllys 	}
38599ebb4caSwyllys 	(void) mutex_unlock(&init_lock);
38699ebb4caSwyllys 
38799ebb4caSwyllys 	return (&openssl_plugin_table);
38899ebb4caSwyllys }
389*300fdee2SAndy Fiddaman 
39099ebb4caSwyllys /*
39199ebb4caSwyllys  * Convert an SSL DN to a KMF DN.
39299ebb4caSwyllys  */
39399ebb4caSwyllys static KMF_RETURN
39499ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
39599ebb4caSwyllys {
39699ebb4caSwyllys 	KMF_DATA derdata;
39799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
39899ebb4caSwyllys 	uchar_t *tmp;
39999ebb4caSwyllys 
40099ebb4caSwyllys 	/* Convert to raw DER format */
40199ebb4caSwyllys 	derdata.Length = i2d_X509_NAME(sslDN, NULL);
40299ebb4caSwyllys 	if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
40399ebb4caSwyllys 	    == NULL) {
40499ebb4caSwyllys 		return (KMF_ERR_MEMORY);
40599ebb4caSwyllys 	}
40699ebb4caSwyllys 	(void) i2d_X509_NAME(sslDN, &tmp);
40799ebb4caSwyllys 
40899ebb4caSwyllys 	/* Decode to KMF format */
40999ebb4caSwyllys 	rv = DerDecodeName(&derdata, kmfDN);
41099ebb4caSwyllys 	if (rv != KMF_OK) {
41199ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
41299ebb4caSwyllys 	}
41399ebb4caSwyllys 	OPENSSL_free(derdata.Data);
41499ebb4caSwyllys 
41599ebb4caSwyllys 	return (rv);
41699ebb4caSwyllys }
41799ebb4caSwyllys 
41830a5e8faSwyllys int
41999ebb4caSwyllys isdir(char *path)
42099ebb4caSwyllys {
42199ebb4caSwyllys 	struct stat s;
42299ebb4caSwyllys 
42399ebb4caSwyllys 	if (stat(path, &s) == -1)
42499ebb4caSwyllys 		return (0);
42599ebb4caSwyllys 
42630a5e8faSwyllys 	return ((s.st_mode & S_IFMT) == S_IFDIR);
42799ebb4caSwyllys }
42899ebb4caSwyllys 
42999ebb4caSwyllys static KMF_RETURN
43099ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
43199ebb4caSwyllys {
43299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
43399ebb4caSwyllys 	unsigned char *buf = NULL, *p;
43499ebb4caSwyllys 	int len;
43599ebb4caSwyllys 
43699ebb4caSwyllys 	/*
43799ebb4caSwyllys 	 * Convert the X509 internal struct to DER encoded data
43899ebb4caSwyllys 	 */
43999ebb4caSwyllys 	if ((len = i2d_X509(x509cert, NULL)) < 0) {
44099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
44199ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
44299ebb4caSwyllys 		goto cleanup;
44399ebb4caSwyllys 	}
44499ebb4caSwyllys 	if ((buf = malloc(len)) == NULL) {
44599ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
44699ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
44799ebb4caSwyllys 		goto cleanup;
44899ebb4caSwyllys 	}
44999ebb4caSwyllys 
45099ebb4caSwyllys 	/*
45199ebb4caSwyllys 	 * i2d_X509 will increment the buf pointer so that we need to
45299ebb4caSwyllys 	 * save it.
45399ebb4caSwyllys 	 */
45499ebb4caSwyllys 	p = buf;
45599ebb4caSwyllys 	if ((len = i2d_X509(x509cert, &p)) < 0) {
45699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
45799ebb4caSwyllys 		free(buf);
45899ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
45999ebb4caSwyllys 		goto cleanup;
46099ebb4caSwyllys 	}
46199ebb4caSwyllys 
46299ebb4caSwyllys 	/* caller's responsibility to free it */
46399ebb4caSwyllys 	cert->Data = buf;
46499ebb4caSwyllys 	cert->Length = len;
46599ebb4caSwyllys 
46699ebb4caSwyllys cleanup:
46799ebb4caSwyllys 	if (rv != KMF_OK) {
46899ebb4caSwyllys 		if (buf)
46999ebb4caSwyllys 			free(buf);
47099ebb4caSwyllys 		cert->Data = NULL;
47199ebb4caSwyllys 		cert->Length = 0;
47299ebb4caSwyllys 	}
47399ebb4caSwyllys 
47499ebb4caSwyllys 	return (rv);
47599ebb4caSwyllys }
47699ebb4caSwyllys 
47730a5e8faSwyllys 
47899ebb4caSwyllys static KMF_RETURN
47930a5e8faSwyllys check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
48030a5e8faSwyllys     boolean_t *match)
48199ebb4caSwyllys {
48299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
48399ebb4caSwyllys 	boolean_t findIssuer = FALSE;
48499ebb4caSwyllys 	boolean_t findSubject = FALSE;
48599ebb4caSwyllys 	boolean_t findSerial = FALSE;
48699ebb4caSwyllys 	KMF_X509_NAME issuerDN, subjectDN;
48799ebb4caSwyllys 	KMF_X509_NAME certIssuerDN, certSubjectDN;
48899ebb4caSwyllys 
48999ebb4caSwyllys 	*match = FALSE;
49099ebb4caSwyllys 	if (xcert == NULL) {
49199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
49299ebb4caSwyllys 	}
49399ebb4caSwyllys 
49499ebb4caSwyllys 	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
49599ebb4caSwyllys 	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
49699ebb4caSwyllys 	(void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
49799ebb4caSwyllys 	(void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
49899ebb4caSwyllys 
49930a5e8faSwyllys 	if (issuer != NULL && strlen(issuer)) {
50030a5e8faSwyllys 		rv = kmf_dn_parser(issuer, &issuerDN);
50199ebb4caSwyllys 		if (rv != KMF_OK)
50299ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
50399ebb4caSwyllys 
504*300fdee2SAndy Fiddaman 		rv = get_x509_dn(X509_get_issuer_name(xcert), &certIssuerDN);
50599ebb4caSwyllys 		if (rv != KMF_OK) {
50630a5e8faSwyllys 			kmf_free_dn(&issuerDN);
50799ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
50899ebb4caSwyllys 		}
50999ebb4caSwyllys 
51099ebb4caSwyllys 		findIssuer = TRUE;
51199ebb4caSwyllys 	}
51230a5e8faSwyllys 	if (subject != NULL && strlen(subject)) {
51330a5e8faSwyllys 		rv = kmf_dn_parser(subject, &subjectDN);
51499ebb4caSwyllys 		if (rv != KMF_OK) {
51599ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
51699ebb4caSwyllys 			goto cleanup;
51799ebb4caSwyllys 		}
51899ebb4caSwyllys 
519*300fdee2SAndy Fiddaman 		rv = get_x509_dn(X509_get_subject_name(xcert), &certSubjectDN);
52099ebb4caSwyllys 		if (rv != KMF_OK) {
52199ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
52299ebb4caSwyllys 			goto cleanup;
52399ebb4caSwyllys 		}
52499ebb4caSwyllys 		findSubject = TRUE;
52599ebb4caSwyllys 	}
52630a5e8faSwyllys 	if (serial != NULL && serial->val != NULL)
52799ebb4caSwyllys 		findSerial = TRUE;
52899ebb4caSwyllys 
52999ebb4caSwyllys 	if (findSerial) {
53099ebb4caSwyllys 		BIGNUM *bn;
53199ebb4caSwyllys 
53299ebb4caSwyllys 		/* Comparing BIGNUMs is a pain! */
533*300fdee2SAndy Fiddaman 		bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(xcert), NULL);
53499ebb4caSwyllys 		if (bn != NULL) {
53599ebb4caSwyllys 			int bnlen = BN_num_bytes(bn);
53699ebb4caSwyllys 
53730a5e8faSwyllys 			if (bnlen == serial->len) {
53899ebb4caSwyllys 				uchar_t *a = malloc(bnlen);
53999ebb4caSwyllys 				if (a == NULL) {
54099ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
54199ebb4caSwyllys 					BN_free(bn);
54299ebb4caSwyllys 					goto cleanup;
54399ebb4caSwyllys 				}
54499ebb4caSwyllys 				bnlen = BN_bn2bin(bn, a);
54530a5e8faSwyllys 				*match = (memcmp(a, serial->val, serial->len) ==
54630a5e8faSwyllys 				    0);
54799ebb4caSwyllys 				rv = KMF_OK;
54899ebb4caSwyllys 				free(a);
54999ebb4caSwyllys 			}
55099ebb4caSwyllys 			BN_free(bn);
55199ebb4caSwyllys 			if (!(*match))
55299ebb4caSwyllys 				goto cleanup;
55399ebb4caSwyllys 		} else {
55499ebb4caSwyllys 			rv = KMF_OK;
55599ebb4caSwyllys 			goto cleanup;
55699ebb4caSwyllys 		}
55799ebb4caSwyllys 	}
55899ebb4caSwyllys 	if (findIssuer) {
55930a5e8faSwyllys 		*match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
56030a5e8faSwyllys 		if ((*match) == B_FALSE) {
56130a5e8faSwyllys 			/* stop checking and bail */
56299ebb4caSwyllys 			rv = KMF_OK;
56399ebb4caSwyllys 			goto cleanup;
56499ebb4caSwyllys 		}
56599ebb4caSwyllys 	}
56699ebb4caSwyllys 	if (findSubject) {
56730a5e8faSwyllys 		*match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
56830a5e8faSwyllys 		if ((*match) == B_FALSE) {
56930a5e8faSwyllys 			/* stop checking and bail */
57099ebb4caSwyllys 			rv = KMF_OK;
57199ebb4caSwyllys 			goto cleanup;
57299ebb4caSwyllys 		}
57399ebb4caSwyllys 	}
57499ebb4caSwyllys 
57599ebb4caSwyllys 	*match = TRUE;
57699ebb4caSwyllys cleanup:
57799ebb4caSwyllys 	if (findIssuer) {
57830a5e8faSwyllys 		kmf_free_dn(&issuerDN);
57930a5e8faSwyllys 		kmf_free_dn(&certIssuerDN);
58099ebb4caSwyllys 	}
58199ebb4caSwyllys 	if (findSubject) {
58230a5e8faSwyllys 		kmf_free_dn(&subjectDN);
58330a5e8faSwyllys 		kmf_free_dn(&certSubjectDN);
58499ebb4caSwyllys 	}
58599ebb4caSwyllys 
58699ebb4caSwyllys 	return (rv);
58799ebb4caSwyllys }
58899ebb4caSwyllys 
58930a5e8faSwyllys 
59030a5e8faSwyllys /*
59130a5e8faSwyllys  * This function loads a certificate file into an X509 data structure, and
59230a5e8faSwyllys  * checks if its issuer, subject or the serial number matches with those
59330a5e8faSwyllys  * values.  If it matches, then return the X509 data structure.
59430a5e8faSwyllys  */
59599ebb4caSwyllys static KMF_RETURN
59699ebb4caSwyllys load_X509cert(KMF_HANDLE *kmfh,
59730a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
59830a5e8faSwyllys     char *pathname, X509 **outcert)
59999ebb4caSwyllys {
60099ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
60199ebb4caSwyllys 	X509 *xcert = NULL;
60299ebb4caSwyllys 	BIO *bcert = NULL;
60399ebb4caSwyllys 	boolean_t  match = FALSE;
60499ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
60599ebb4caSwyllys 
60699ebb4caSwyllys 	/*
60799ebb4caSwyllys 	 * auto-detect the file format, regardless of what
60899ebb4caSwyllys 	 * the 'format' parameters in the params say.
60999ebb4caSwyllys 	 */
61030a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
61199ebb4caSwyllys 	if (rv != KMF_OK) {
61299ebb4caSwyllys 		if (rv == KMF_ERR_OPEN_FILE)
61399ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
61499ebb4caSwyllys 		return (rv);
61599ebb4caSwyllys 	}
61699ebb4caSwyllys 
61799ebb4caSwyllys 	/* Not ASN1(DER) format */
61899ebb4caSwyllys 	if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
61999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
62099ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
62199ebb4caSwyllys 		goto cleanup;
62299ebb4caSwyllys 	}
62399ebb4caSwyllys 
62499ebb4caSwyllys 	if (format == KMF_FORMAT_PEM)
62599ebb4caSwyllys 		xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
62699ebb4caSwyllys 	else if (format == KMF_FORMAT_ASN1)
62799ebb4caSwyllys 		xcert = d2i_X509_bio(bcert, NULL);
62899ebb4caSwyllys 	else if (format == KMF_FORMAT_PKCS12) {
62999ebb4caSwyllys 		PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
63099ebb4caSwyllys 		if (p12 != NULL) {
63199ebb4caSwyllys 			(void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
63299ebb4caSwyllys 			PKCS12_free(p12);
63399ebb4caSwyllys 			p12 = NULL;
63499ebb4caSwyllys 		} else {
63599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
63699ebb4caSwyllys 			rv = KMF_ERR_BAD_CERT_FORMAT;
63799ebb4caSwyllys 		}
63899ebb4caSwyllys 	} else {
63999ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
64099ebb4caSwyllys 		goto cleanup;
64199ebb4caSwyllys 	}
64299ebb4caSwyllys 
64399ebb4caSwyllys 	if (xcert == NULL) {
64499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
64599ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
64699ebb4caSwyllys 		goto cleanup;
64799ebb4caSwyllys 	}
64899ebb4caSwyllys 
64930a5e8faSwyllys 	if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
65030a5e8faSwyllys 	    match == FALSE) {
65199ebb4caSwyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
65299ebb4caSwyllys 		goto cleanup;
65399ebb4caSwyllys 	}
65499ebb4caSwyllys 
65599ebb4caSwyllys 	if (outcert != NULL) {
65699ebb4caSwyllys 		*outcert = xcert;
65799ebb4caSwyllys 	}
65899ebb4caSwyllys 
65999ebb4caSwyllys cleanup:
66099ebb4caSwyllys 	if (bcert != NULL) (void) BIO_free(bcert);
66199ebb4caSwyllys 	if (rv != KMF_OK && xcert != NULL)
66299ebb4caSwyllys 		X509_free(xcert);
66399ebb4caSwyllys 
66499ebb4caSwyllys 	return (rv);
66599ebb4caSwyllys }
66699ebb4caSwyllys 
66771593db2Swyllys static int
66871593db2Swyllys datacmp(const void *a, const void *b)
66971593db2Swyllys {
67071593db2Swyllys 	KMF_DATA *adata = (KMF_DATA *)a;
67171593db2Swyllys 	KMF_DATA *bdata = (KMF_DATA *)b;
67271593db2Swyllys 	if (adata->Length > bdata->Length)
67371593db2Swyllys 		return (-1);
67471593db2Swyllys 	if (adata->Length < bdata->Length)
67571593db2Swyllys 		return (1);
67671593db2Swyllys 	return (0);
67771593db2Swyllys }
67871593db2Swyllys 
67971593db2Swyllys static KMF_RETURN
68030a5e8faSwyllys load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
68130a5e8faSwyllys     KMF_CERT_VALIDITY validity, char *pathname,
68271593db2Swyllys     KMF_DATA **certlist, uint32_t *numcerts)
68371593db2Swyllys {
68471593db2Swyllys 	KMF_RETURN rv = KMF_OK;
68571593db2Swyllys 	int i;
68671593db2Swyllys 	KMF_DATA *certs = NULL;
68771593db2Swyllys 	int nc = 0;
68871593db2Swyllys 	int hits = 0;
68971593db2Swyllys 	KMF_ENCODE_FORMAT format;
69071593db2Swyllys 
69130a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
69271593db2Swyllys 	if (rv != KMF_OK) {
69371593db2Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
69471593db2Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
69571593db2Swyllys 		return (rv);
69671593db2Swyllys 	}
69771593db2Swyllys 	if (format == KMF_FORMAT_ASN1) {
69871593db2Swyllys 		/* load a single certificate */
69971593db2Swyllys 		certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
70071593db2Swyllys 		if (certs == NULL)
70171593db2Swyllys 			return (KMF_ERR_MEMORY);
70271593db2Swyllys 		certs->Data = NULL;
70371593db2Swyllys 		certs->Length = 0;
70430a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
70530a5e8faSwyllys 		    pathname, certs);
70671593db2Swyllys 		if (rv == KMF_OK) {
70771593db2Swyllys 			*certlist = certs;
70871593db2Swyllys 			*numcerts = 1;
709a2d4930dSDan OpenSolaris Anderson 		} else {
710a2d4930dSDan OpenSolaris Anderson 			kmf_free_data(certs);
711a2d4930dSDan OpenSolaris Anderson 			free(certs);
712a2d4930dSDan OpenSolaris Anderson 			certs = NULL;
71371593db2Swyllys 		}
71471593db2Swyllys 		return (rv);
71571593db2Swyllys 	} else if (format == KMF_FORMAT_PKCS12) {
71671593db2Swyllys 		/* We need a credential to access a PKCS#12 file */
71771593db2Swyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
71871593db2Swyllys 	} else if (format == KMF_FORMAT_PEM ||
71971593db2Swyllys 	    format != KMF_FORMAT_PEM_KEYPAIR) {
720e65e5c2dSWyllys Ingersoll 
72171593db2Swyllys 		/* This function only works on PEM files */
72230a5e8faSwyllys 		rv = extract_pem(kmfh, issuer, subject, serial, pathname,
72334acef67Swyllys 		    (uchar_t *)NULL, 0, NULL, &certs, &nc);
72471593db2Swyllys 	} else {
72571593db2Swyllys 		return (KMF_ERR_ENCODING);
72671593db2Swyllys 	}
72771593db2Swyllys 
72871593db2Swyllys 	if (rv != KMF_OK)
72971593db2Swyllys 		return (rv);
73071593db2Swyllys 
73171593db2Swyllys 	for (i = 0; i < nc; i++) {
73230a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
73330a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
73430a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
73530a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
73671593db2Swyllys 			if (rv == KMF_OK)
73771593db2Swyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
73871593db2Swyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD)
73971593db2Swyllys 				rv = KMF_OK;
74071593db2Swyllys 		}
74171593db2Swyllys 		if (rv != KMF_OK) {
74271593db2Swyllys 			/* Remove this cert from the list by clearing it. */
74330a5e8faSwyllys 			kmf_free_data(&certs[i]);
74471593db2Swyllys 		} else {
74571593db2Swyllys 			hits++; /* count valid certs found */
74671593db2Swyllys 		}
74771593db2Swyllys 		rv = KMF_OK;
74871593db2Swyllys 	}
749a2d4930dSDan OpenSolaris Anderson 	if (rv == KMF_OK && hits > 0) {
75071593db2Swyllys 		/*
75171593db2Swyllys 		 * Sort the list of certs by length to put the cleared ones
75271593db2Swyllys 		 * at the end so they don't get accessed by the caller.
75371593db2Swyllys 		 */
75471593db2Swyllys 		qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
75571593db2Swyllys 		*certlist = certs;
75671593db2Swyllys 
75771593db2Swyllys 		/* since we sorted the list, just return the number of hits */
75871593db2Swyllys 		*numcerts = hits;
759a2d4930dSDan OpenSolaris Anderson 	} else {
760e65e5c2dSWyllys Ingersoll 		if (rv == KMF_OK && hits == 0)
761a2d4930dSDan OpenSolaris Anderson 			rv = KMF_ERR_CERT_NOT_FOUND;
762a2d4930dSDan OpenSolaris Anderson 		if (certs != NULL) {
763a2d4930dSDan OpenSolaris Anderson 			free(certs);
764a2d4930dSDan OpenSolaris Anderson 			certs = NULL;
765a2d4930dSDan OpenSolaris Anderson 		}
766a2d4930dSDan OpenSolaris Anderson 	}
76771593db2Swyllys 	return (rv);
76871593db2Swyllys }
76971593db2Swyllys 
77099ebb4caSwyllys static KMF_RETURN
77199ebb4caSwyllys kmf_load_cert(KMF_HANDLE *kmfh,
77230a5e8faSwyllys     char *issuer, char *subject, KMF_BIGINT *serial,
77330a5e8faSwyllys     KMF_CERT_VALIDITY validity,
77499ebb4caSwyllys     char *pathname,
77599ebb4caSwyllys     KMF_DATA *cert)
77699ebb4caSwyllys {
77799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
77899ebb4caSwyllys 	X509 *x509cert = NULL;
77999ebb4caSwyllys 
78030a5e8faSwyllys 	rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
78199ebb4caSwyllys 	if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
78299ebb4caSwyllys 		rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
78399ebb4caSwyllys 		if (rv != KMF_OK) {
78499ebb4caSwyllys 			goto cleanup;
78599ebb4caSwyllys 		}
78630a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
78730a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
78830a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
78930a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
79099ebb4caSwyllys 			if (rv == KMF_OK)  {
79199ebb4caSwyllys 				/*
79299ebb4caSwyllys 				 * This is a valid cert so skip it.
79399ebb4caSwyllys 				 */
79499ebb4caSwyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
79599ebb4caSwyllys 			}
79699ebb4caSwyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD) {
79799ebb4caSwyllys 				/*
79899ebb4caSwyllys 				 * We want to return success when we
79999ebb4caSwyllys 				 * find an invalid cert.
80099ebb4caSwyllys 				 */
80199ebb4caSwyllys 				rv = KMF_OK;
80299ebb4caSwyllys 				goto cleanup;
80399ebb4caSwyllys 			}
80499ebb4caSwyllys 		}
80599ebb4caSwyllys 	}
80699ebb4caSwyllys cleanup:
80799ebb4caSwyllys 	if (x509cert != NULL)
80899ebb4caSwyllys 		X509_free(x509cert);
80999ebb4caSwyllys 
81099ebb4caSwyllys 	return (rv);
81199ebb4caSwyllys }
81299ebb4caSwyllys 
81302744e81Swyllys static KMF_RETURN
81402744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
81502744e81Swyllys {
81602744e81Swyllys 	KMF_RETURN ret = KMF_OK;
81702744e81Swyllys 	KMF_RAW_RSA_KEY rsa;
81802744e81Swyllys 	BerElement *asn1 = NULL;
81902744e81Swyllys 	BerValue filebuf;
82002744e81Swyllys 	BerValue OID = { NULL, 0 };
82102744e81Swyllys 	BerValue *Mod = NULL, *PubExp = NULL;
82202744e81Swyllys 	BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
82302744e81Swyllys 	BerValue *Coef = NULL;
82402744e81Swyllys 	BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
82502744e81Swyllys 	BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
82602744e81Swyllys 	BIGNUM *qminus1 = NULL;
82702744e81Swyllys 	BN_CTX *ctx = NULL;
82802744e81Swyllys 
82902744e81Swyllys 	*pkey = NULL;
83002744e81Swyllys 
83102744e81Swyllys 	filebuf.bv_val = (char *)filedata->Data;
83202744e81Swyllys 	filebuf.bv_len = filedata->Length;
83302744e81Swyllys 
83402744e81Swyllys 	asn1 = kmfder_init(&filebuf);
83502744e81Swyllys 	if (asn1 == NULL) {
83602744e81Swyllys 		ret = KMF_ERR_MEMORY;
83702744e81Swyllys 		goto out;
83802744e81Swyllys 	}
83902744e81Swyllys 
84002744e81Swyllys 	if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
84102744e81Swyllys 	    &OID, &Mod, &PubExp, &PriExp, &Prime1,
84202744e81Swyllys 	    &Prime2, &Coef) == -1)  {
84302744e81Swyllys 		ret = KMF_ERR_ENCODING;
84402744e81Swyllys 		goto out;
84502744e81Swyllys 	}
84602744e81Swyllys 
84702744e81Swyllys 	/*
84802744e81Swyllys 	 * We have to derive the 2 Exponents using Bignumber math.
84902744e81Swyllys 	 * Exp1 = PriExp mod (Prime1 - 1)
85002744e81Swyllys 	 * Exp2 = PriExp mod (Prime2 - 1)
85102744e81Swyllys 	 */
85202744e81Swyllys 
85302744e81Swyllys 	/* D = PrivateExponent */
85402744e81Swyllys 	D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
85502744e81Swyllys 	if (D == NULL) {
85602744e81Swyllys 		ret = KMF_ERR_MEMORY;
85702744e81Swyllys 		goto out;
85802744e81Swyllys 	}
85902744e81Swyllys 
86002744e81Swyllys 	/* P = Prime1 (first prime factor of Modulus) */
86102744e81Swyllys 	P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
86202744e81Swyllys 	if (D == NULL) {
86302744e81Swyllys 		ret = KMF_ERR_MEMORY;
86402744e81Swyllys 		goto out;
86502744e81Swyllys 	}
86602744e81Swyllys 
86702744e81Swyllys 	/* Q = Prime2 (second prime factor of Modulus) */
86802744e81Swyllys 	Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
86902744e81Swyllys 
87002744e81Swyllys 	if ((ctx = BN_CTX_new()) == NULL) {
87102744e81Swyllys 		ret = KMF_ERR_MEMORY;
87202744e81Swyllys 		goto out;
87302744e81Swyllys 	}
87402744e81Swyllys 
87502744e81Swyllys 	/* Compute (P - 1) */
87602744e81Swyllys 	pminus1 = BN_new();
87702744e81Swyllys 	(void) BN_sub(pminus1, P, BN_value_one());
87802744e81Swyllys 
87902744e81Swyllys 	/* Exponent1 = D mod (P - 1) */
88002744e81Swyllys 	Exp1 = BN_new();
88102744e81Swyllys 	(void) BN_mod(Exp1, D, pminus1, ctx);
88202744e81Swyllys 
88302744e81Swyllys 	/* Compute (Q - 1) */
88402744e81Swyllys 	qminus1 = BN_new();
88502744e81Swyllys 	(void) BN_sub(qminus1, Q, BN_value_one());
88602744e81Swyllys 
88702744e81Swyllys 	/* Exponent2 = D mod (Q - 1) */
88802744e81Swyllys 	Exp2 = BN_new();
88902744e81Swyllys 	(void) BN_mod(Exp2, D, qminus1, ctx);
89002744e81Swyllys 
89102744e81Swyllys 	/* Coef = (Inverse Q) mod P */
89202744e81Swyllys 	COEF = BN_new();
89302744e81Swyllys 	(void) BN_mod_inverse(COEF, Q, P, ctx);
89402744e81Swyllys 
89502744e81Swyllys 	/* Convert back to KMF format */
89602744e81Swyllys 	(void) memset(&rsa, 0, sizeof (rsa));
89702744e81Swyllys 
89802744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
89902744e81Swyllys 		goto out;
90002744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
90102744e81Swyllys 		goto out;
90202744e81Swyllys 	if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
90302744e81Swyllys 		goto out;
90402744e81Swyllys 
90502744e81Swyllys 	rsa.mod.val = (uchar_t *)Mod->bv_val;
90602744e81Swyllys 	rsa.mod.len = Mod->bv_len;
90702744e81Swyllys 
90802744e81Swyllys 	rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
90902744e81Swyllys 	rsa.pubexp.len = PubExp->bv_len;
91002744e81Swyllys 
91102744e81Swyllys 	rsa.priexp.val = (uchar_t *)PriExp->bv_val;
91202744e81Swyllys 	rsa.priexp.len = PriExp->bv_len;
91302744e81Swyllys 
91402744e81Swyllys 	rsa.prime1.val = (uchar_t *)Prime1->bv_val;
91502744e81Swyllys 	rsa.prime1.len = Prime1->bv_len;
91602744e81Swyllys 
91702744e81Swyllys 	rsa.prime2.val = (uchar_t *)Prime2->bv_val;
91802744e81Swyllys 	rsa.prime2.len = Prime2->bv_len;
91902744e81Swyllys 
92002744e81Swyllys 	*pkey = ImportRawRSAKey(&rsa);
92102744e81Swyllys out:
92202744e81Swyllys 	if (asn1 != NULL)
92302744e81Swyllys 		kmfber_free(asn1, 1);
92402744e81Swyllys 
92502744e81Swyllys 	if (OID.bv_val) {
92602744e81Swyllys 		free(OID.bv_val);
92702744e81Swyllys 	}
92802744e81Swyllys 	if (PriExp)
92902744e81Swyllys 		free(PriExp);
93002744e81Swyllys 
93102744e81Swyllys 	if (Mod)
93202744e81Swyllys 		free(Mod);
93302744e81Swyllys 
93402744e81Swyllys 	if (PubExp)
93502744e81Swyllys 		free(PubExp);
93602744e81Swyllys 
93702744e81Swyllys 	if (Coef) {
93802744e81Swyllys 		(void) memset(Coef->bv_val, 0, Coef->bv_len);
93902744e81Swyllys 		free(Coef->bv_val);
94002744e81Swyllys 		free(Coef);
94102744e81Swyllys 	}
94202744e81Swyllys 	if (Prime1)
94302744e81Swyllys 		free(Prime1);
94402744e81Swyllys 	if (Prime2)
94502744e81Swyllys 		free(Prime2);
94602744e81Swyllys 
94702744e81Swyllys 	if (ctx != NULL)
94802744e81Swyllys 		BN_CTX_free(ctx);
94902744e81Swyllys 
95002744e81Swyllys 	if (D)
95102744e81Swyllys 		BN_clear_free(D);
95202744e81Swyllys 	if (P)
95302744e81Swyllys 		BN_clear_free(P);
95402744e81Swyllys 	if (Q)
95502744e81Swyllys 		BN_clear_free(Q);
95602744e81Swyllys 	if (pminus1)
95702744e81Swyllys 		BN_clear_free(pminus1);
95802744e81Swyllys 	if (qminus1)
95902744e81Swyllys 		BN_clear_free(qminus1);
96002744e81Swyllys 	if (Exp1)
96102744e81Swyllys 		BN_clear_free(Exp1);
96202744e81Swyllys 	if (Exp2)
96302744e81Swyllys 		BN_clear_free(Exp2);
96402744e81Swyllys 
96502744e81Swyllys 	return (ret);
96602744e81Swyllys 
96702744e81Swyllys }
96802744e81Swyllys 
96999ebb4caSwyllys static EVP_PKEY *
97099ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file)
97199ebb4caSwyllys {
97299ebb4caSwyllys 	BIO *keyfile = NULL;
97399ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
97499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
97599ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
97602744e81Swyllys 	KMF_RETURN rv;
97702744e81Swyllys 	KMF_DATA filedata;
97899ebb4caSwyllys 
97999ebb4caSwyllys 	if (file == NULL) {
98099ebb4caSwyllys 		return (NULL);
98199ebb4caSwyllys 	}
98299ebb4caSwyllys 
98330a5e8faSwyllys 	if (kmf_get_file_format((char *)file, &format) != KMF_OK)
98499ebb4caSwyllys 		return (NULL);
98599ebb4caSwyllys 
98699ebb4caSwyllys 	keyfile = BIO_new_file(file, "rb");
98799ebb4caSwyllys 	if (keyfile == NULL) {
98899ebb4caSwyllys 		goto end;
98999ebb4caSwyllys 	}
99099ebb4caSwyllys 
99102744e81Swyllys 	if (format == KMF_FORMAT_ASN1) {
99299ebb4caSwyllys 		pkey = d2i_PrivateKey_bio(keyfile, NULL);
99302744e81Swyllys 		if (pkey == NULL) {
99402744e81Swyllys 
99502744e81Swyllys 			(void) BIO_free(keyfile);
99602744e81Swyllys 			keyfile = NULL;
99702744e81Swyllys 			/* Try odd ASN.1 variations */
99830a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
99902744e81Swyllys 			    &filedata);
100002744e81Swyllys 			if (rv == KMF_OK) {
100102744e81Swyllys 				(void) readAltFormatPrivateKey(&filedata,
100202744e81Swyllys 				    &pkey);
100330a5e8faSwyllys 				kmf_free_data(&filedata);
100402744e81Swyllys 			}
100502744e81Swyllys 		}
100602744e81Swyllys 	} else if (format == KMF_FORMAT_PEM ||
100702744e81Swyllys 	    format == KMF_FORMAT_PEM_KEYPAIR) {
100899ebb4caSwyllys 		pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
100902744e81Swyllys 		if (pkey == NULL) {
101002744e81Swyllys 			KMF_DATA derdata;
101102744e81Swyllys 			/*
101202744e81Swyllys 			 * Check if this is the alt. format
101302744e81Swyllys 			 * RSA private key file.
101402744e81Swyllys 			 */
101530a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
101602744e81Swyllys 			    &filedata);
101702744e81Swyllys 			if (rv == KMF_OK) {
101802744e81Swyllys 				uchar_t *d = NULL;
101902744e81Swyllys 				int len;
102030a5e8faSwyllys 				rv = kmf_pem_to_der(filedata.Data,
102102744e81Swyllys 				    filedata.Length, &d, &len);
102202744e81Swyllys 				if (rv == KMF_OK && d != NULL) {
102302744e81Swyllys 					derdata.Data = d;
102402744e81Swyllys 					derdata.Length = (size_t)len;
102502744e81Swyllys 					(void) readAltFormatPrivateKey(
102602744e81Swyllys 					    &derdata, &pkey);
102702744e81Swyllys 					free(d);
102802744e81Swyllys 				}
102930a5e8faSwyllys 				kmf_free_data(&filedata);
103002744e81Swyllys 			}
103102744e81Swyllys 		}
103202744e81Swyllys 	}
103399ebb4caSwyllys 
103499ebb4caSwyllys end:
103599ebb4caSwyllys 	if (pkey == NULL)
103699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
103799ebb4caSwyllys 
103899ebb4caSwyllys 	if (keyfile != NULL)
103999ebb4caSwyllys 		(void) BIO_free(keyfile);
104099ebb4caSwyllys 
104199ebb4caSwyllys 	return (pkey);
104299ebb4caSwyllys }
104399ebb4caSwyllys 
104499ebb4caSwyllys KMF_RETURN
104530a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
104699ebb4caSwyllys {
104799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
104899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1049f482c776Swyllys 	int i, n;
1050f482c776Swyllys 	uint32_t maxcerts = 0;
105130a5e8faSwyllys 	uint32_t *num_certs;
105230a5e8faSwyllys 	KMF_X509_DER_CERT *kmf_cert = NULL;
105330a5e8faSwyllys 	char *dirpath = NULL;
105430a5e8faSwyllys 	char *filename = NULL;
105530a5e8faSwyllys 	char *fullpath = NULL;
105630a5e8faSwyllys 	char *issuer = NULL;
105730a5e8faSwyllys 	char *subject = NULL;
105830a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
105930a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
106099ebb4caSwyllys 
106130a5e8faSwyllys 	num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
106230a5e8faSwyllys 	if (num_certs == NULL)
106399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
106499ebb4caSwyllys 
106530a5e8faSwyllys 	/* num_certs should reference the size of kmf_cert */
1066f482c776Swyllys 	maxcerts = *num_certs;
1067f482c776Swyllys 	if (maxcerts == 0)
1068f482c776Swyllys 		maxcerts = 0xFFFFFFFF;
106999ebb4caSwyllys 	*num_certs = 0;
107099ebb4caSwyllys 
107130a5e8faSwyllys 	/* Get the optional returned certificate list  */
107230a5e8faSwyllys 	kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
107330a5e8faSwyllys 	    numattr);
107499ebb4caSwyllys 
107530a5e8faSwyllys 	/*
107630a5e8faSwyllys 	 * The dirpath attribute and the filename attribute can not be NULL
107730a5e8faSwyllys 	 * at the same time.
107830a5e8faSwyllys 	 */
107930a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
108030a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
108130a5e8faSwyllys 	    numattr);
108230a5e8faSwyllys 
108330a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
108499ebb4caSwyllys 	if (fullpath == NULL)
108599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
108699ebb4caSwyllys 
108730a5e8faSwyllys 	/* Get optional search criteria attributes */
108830a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
108930a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
109030a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
109130a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
109230a5e8faSwyllys 	    &validity, NULL);
109330a5e8faSwyllys 	if (rv != KMF_OK) {
109430a5e8faSwyllys 		validity = KMF_ALL_CERTS;
109530a5e8faSwyllys 		rv = KMF_OK;
109630a5e8faSwyllys 	}
109730a5e8faSwyllys 
109899ebb4caSwyllys 	if (isdir(fullpath)) {
109999ebb4caSwyllys 		DIR *dirp;
110099ebb4caSwyllys 		struct dirent *dp;
110199ebb4caSwyllys 
1102f482c776Swyllys 		n = 0;
110399ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
110499ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
110599ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
110699ebb4caSwyllys 		}
110799ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
110899ebb4caSwyllys 			char *fname;
110971593db2Swyllys 			KMF_DATA *certlist = NULL;
1110f482c776Swyllys 			uint32_t loaded_certs = 0;
111171593db2Swyllys 
111299ebb4caSwyllys 			if (strcmp(dp->d_name, ".") == 0 ||
111399ebb4caSwyllys 			    strcmp(dp->d_name, "..") == 0)
111499ebb4caSwyllys 				continue;
111599ebb4caSwyllys 
111634acef67Swyllys 			fname = get_fullpath(fullpath, (char *)&dp->d_name);
111799ebb4caSwyllys 
111830a5e8faSwyllys 			rv = load_certs(kmfh, issuer, subject, serial,
111930a5e8faSwyllys 			    validity, fname, &certlist,	&loaded_certs);
112099ebb4caSwyllys 
112199ebb4caSwyllys 			if (rv != KMF_OK) {
112299ebb4caSwyllys 				free(fname);
112371593db2Swyllys 				if (certlist != NULL) {
1124f482c776Swyllys 					for (i = 0; i < loaded_certs; i++)
112530a5e8faSwyllys 						kmf_free_data(&certlist[i]);
112671593db2Swyllys 					free(certlist);
112771593db2Swyllys 				}
112899ebb4caSwyllys 				continue;
112999ebb4caSwyllys 			}
113099ebb4caSwyllys 
113199ebb4caSwyllys 			/* If load succeeds, add certdata to the list */
113299ebb4caSwyllys 			if (kmf_cert != NULL) {
1133f482c776Swyllys 				for (i = 0; i < loaded_certs &&
1134b4058258Swyllys 				    n < maxcerts; i++) {
113571593db2Swyllys 					kmf_cert[n].certificate.Data =
113671593db2Swyllys 					    certlist[i].Data;
113799ebb4caSwyllys 					kmf_cert[n].certificate.Length =
113871593db2Swyllys 					    certlist[i].Length;
113999ebb4caSwyllys 
114099ebb4caSwyllys 					kmf_cert[n].kmf_private.keystore_type =
114199ebb4caSwyllys 					    KMF_KEYSTORE_OPENSSL;
114299ebb4caSwyllys 					kmf_cert[n].kmf_private.flags =
114399ebb4caSwyllys 					    KMF_FLAG_CERT_VALID;
114471593db2Swyllys 					kmf_cert[n].kmf_private.label =
114571593db2Swyllys 					    strdup(fname);
114699ebb4caSwyllys 					n++;
114799ebb4caSwyllys 				}
1148b4058258Swyllys 				/*
1149b4058258Swyllys 				 * If maxcerts < loaded_certs, clean up the
1150b4058258Swyllys 				 * certs that were not used.
1151b4058258Swyllys 				 */
1152f482c776Swyllys 				for (; i < loaded_certs; i++)
115330a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1154f482c776Swyllys 			} else {
1155f482c776Swyllys 				for (i = 0; i < loaded_certs; i++)
115630a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1157f482c776Swyllys 				n += loaded_certs;
115871593db2Swyllys 			}
1159f482c776Swyllys 			free(certlist);
116071593db2Swyllys 			free(fname);
116171593db2Swyllys 		}
116299ebb4caSwyllys 		(*num_certs) = n;
116399ebb4caSwyllys 		if (*num_certs == 0)
116499ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
116530a5e8faSwyllys 		if (*num_certs > 0)
116699ebb4caSwyllys 			rv = KMF_OK;
116799ebb4caSwyllys exit:
116899ebb4caSwyllys 		(void) closedir(dirp);
116999ebb4caSwyllys 	} else {
117071593db2Swyllys 		KMF_DATA *certlist = NULL;
1171f482c776Swyllys 		uint32_t loaded_certs = 0;
117271593db2Swyllys 
117330a5e8faSwyllys 		rv = load_certs(kmfh, issuer, subject, serial, validity,
117430a5e8faSwyllys 		    fullpath, &certlist, &loaded_certs);
117599ebb4caSwyllys 		if (rv != KMF_OK) {
117699ebb4caSwyllys 			free(fullpath);
117799ebb4caSwyllys 			return (rv);
117899ebb4caSwyllys 		}
117999ebb4caSwyllys 
1180f482c776Swyllys 		n = 0;
118171593db2Swyllys 		if (kmf_cert != NULL && certlist != NULL) {
1182f482c776Swyllys 			for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1183f482c776Swyllys 				kmf_cert[n].certificate.Data =
118471593db2Swyllys 				    certlist[i].Data;
1185f482c776Swyllys 				kmf_cert[n].certificate.Length =
118671593db2Swyllys 				    certlist[i].Length;
1187f482c776Swyllys 				kmf_cert[n].kmf_private.keystore_type =
118899ebb4caSwyllys 				    KMF_KEYSTORE_OPENSSL;
1189f482c776Swyllys 				kmf_cert[n].kmf_private.flags =
119071593db2Swyllys 				    KMF_FLAG_CERT_VALID;
1191f482c776Swyllys 				kmf_cert[n].kmf_private.label =
119271593db2Swyllys 				    strdup(fullpath);
1193f482c776Swyllys 				n++;
119471593db2Swyllys 			}
1195f482c776Swyllys 			/* If maxcerts < loaded_certs, clean up */
1196f482c776Swyllys 			for (; i < loaded_certs; i++)
119730a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1198f482c776Swyllys 		} else if (certlist != NULL) {
1199f482c776Swyllys 			for (i = 0; i < loaded_certs; i++)
120030a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1201f482c776Swyllys 			n = loaded_certs;
1202f482c776Swyllys 		}
120330a5e8faSwyllys 		if (certlist != NULL)
120471593db2Swyllys 			free(certlist);
1205f482c776Swyllys 		*num_certs = n;
120699ebb4caSwyllys 	}
120799ebb4caSwyllys 
120899ebb4caSwyllys 	free(fullpath);
120999ebb4caSwyllys 
121099ebb4caSwyllys 	return (rv);
121199ebb4caSwyllys }
121299ebb4caSwyllys 
121399ebb4caSwyllys void
121499ebb4caSwyllys /*ARGSUSED*/
121599ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
121699ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert)
121799ebb4caSwyllys {
121899ebb4caSwyllys 	if (kmf_cert != NULL) {
121999ebb4caSwyllys 		if (kmf_cert->certificate.Data != NULL) {
1220e65e5c2dSWyllys Ingersoll 			kmf_free_data(&kmf_cert->certificate);
122199ebb4caSwyllys 		}
122299ebb4caSwyllys 		if (kmf_cert->kmf_private.label)
122399ebb4caSwyllys 			free(kmf_cert->kmf_private.label);
122499ebb4caSwyllys 	}
122599ebb4caSwyllys }
122699ebb4caSwyllys 
122730a5e8faSwyllys /*ARGSUSED*/
122899ebb4caSwyllys KMF_RETURN
122930a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
123099ebb4caSwyllys {
123199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
123230a5e8faSwyllys 	KMF_DATA *cert = NULL;
123330a5e8faSwyllys 	char *outfilename = NULL;
123430a5e8faSwyllys 	char *dirpath = NULL;
123530a5e8faSwyllys 	char *fullpath = NULL;
123699ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
123799ebb4caSwyllys 
123830a5e8faSwyllys 	/* Get the cert data */
123930a5e8faSwyllys 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
124030a5e8faSwyllys 	if (cert == NULL || cert->Data == NULL)
124199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
124299ebb4caSwyllys 
124330a5e8faSwyllys 	/* Check the output filename and directory attributes. */
124430a5e8faSwyllys 	outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
124530a5e8faSwyllys 	    numattr);
124630a5e8faSwyllys 	if (outfilename == NULL)
124730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
124899ebb4caSwyllys 
124930a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
125030a5e8faSwyllys 	fullpath = get_fullpath(dirpath, outfilename);
125199ebb4caSwyllys 	if (fullpath == NULL)
125230a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
125399ebb4caSwyllys 
125430a5e8faSwyllys 	/* Check the optional format attribute */
125530a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
125630a5e8faSwyllys 	    &format, NULL);
125730a5e8faSwyllys 	if (ret != KMF_OK) {
125830a5e8faSwyllys 		/* If there is no format attribute, then default to PEM */
125930a5e8faSwyllys 		format = KMF_FORMAT_PEM;
126099ebb4caSwyllys 		ret = KMF_OK;
126130a5e8faSwyllys 	} else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
126230a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
126399ebb4caSwyllys 		goto out;
126499ebb4caSwyllys 	}
126599ebb4caSwyllys 
126630a5e8faSwyllys 	/* Store the certificate in the file with the specified format */
126730a5e8faSwyllys 	ret = kmf_create_cert_file(cert, format, fullpath);
126899ebb4caSwyllys 
126999ebb4caSwyllys out:
127099ebb4caSwyllys 	if (fullpath != NULL)
127199ebb4caSwyllys 		free(fullpath);
127299ebb4caSwyllys 
127399ebb4caSwyllys 	return (ret);
127499ebb4caSwyllys }
127599ebb4caSwyllys 
127630a5e8faSwyllys 
127799ebb4caSwyllys KMF_RETURN
127830a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
127999ebb4caSwyllys {
128099ebb4caSwyllys 	KMF_RETURN rv;
128199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
12826b35cb3cSRichard PALO 	KMF_DATA certdata = { 0, NULL };
128330a5e8faSwyllys 	char *dirpath = NULL;
128430a5e8faSwyllys 	char *filename = NULL;
128530a5e8faSwyllys 	char *fullpath = NULL;
128630a5e8faSwyllys 	char *issuer = NULL;
128730a5e8faSwyllys 	char *subject = NULL;
128830a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
128930a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
129099ebb4caSwyllys 
129130a5e8faSwyllys 	/*
129230a5e8faSwyllys 	 * Get the DIRPATH and CERT_FILENAME attributes.  They can not be
129330a5e8faSwyllys 	 * NULL at the same time.
129430a5e8faSwyllys 	 */
129530a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
129630a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
129730a5e8faSwyllys 	    numattr);
129830a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
129999ebb4caSwyllys 	if (fullpath == NULL)
130099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
130199ebb4caSwyllys 
130230a5e8faSwyllys 	/* Get optional search criteria attributes */
130330a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
130430a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
130530a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
130630a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
130730a5e8faSwyllys 	    &validity, NULL);
130830a5e8faSwyllys 	if (rv != KMF_OK) {
130930a5e8faSwyllys 		validity = KMF_ALL_CERTS;
131030a5e8faSwyllys 		rv = KMF_OK;
131130a5e8faSwyllys 	}
131230a5e8faSwyllys 
131399ebb4caSwyllys 	if (isdir(fullpath)) {
131499ebb4caSwyllys 		DIR *dirp;
131599ebb4caSwyllys 		struct dirent *dp;
131699ebb4caSwyllys 
131799ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
131899ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
131999ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
132099ebb4caSwyllys 		}
132199ebb4caSwyllys 
132299ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
132399ebb4caSwyllys 			if (strcmp(dp->d_name, ".") != 0 &&
132499ebb4caSwyllys 			    strcmp(dp->d_name, "..") != 0) {
132599ebb4caSwyllys 				char *fname;
132699ebb4caSwyllys 
132799ebb4caSwyllys 				fname = get_fullpath(fullpath,
132899ebb4caSwyllys 				    (char *)&dp->d_name);
132999ebb4caSwyllys 
133099ebb4caSwyllys 				if (fname == NULL) {
133199ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
133299ebb4caSwyllys 					break;
133399ebb4caSwyllys 				}
133499ebb4caSwyllys 
133530a5e8faSwyllys 				rv = kmf_load_cert(kmfh, issuer, subject,
133630a5e8faSwyllys 				    serial, validity, fname, &certdata);
133799ebb4caSwyllys 
133899ebb4caSwyllys 				if (rv == KMF_ERR_CERT_NOT_FOUND) {
133999ebb4caSwyllys 					free(fname);
1340e65e5c2dSWyllys Ingersoll 					kmf_free_data(&certdata);
134199ebb4caSwyllys 					rv = KMF_OK;
134299ebb4caSwyllys 					continue;
134399ebb4caSwyllys 				} else if (rv != KMF_OK) {
134499ebb4caSwyllys 					free(fname);
134599ebb4caSwyllys 					break;
134699ebb4caSwyllys 				}
134799ebb4caSwyllys 
134899ebb4caSwyllys 				if (unlink(fname) != 0) {
134999ebb4caSwyllys 					SET_SYS_ERROR(kmfh, errno);
135099ebb4caSwyllys 					rv = KMF_ERR_INTERNAL;
135199ebb4caSwyllys 					free(fname);
135299ebb4caSwyllys 					break;
135399ebb4caSwyllys 				}
135499ebb4caSwyllys 				free(fname);
1355e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certdata);
135699ebb4caSwyllys 			}
135799ebb4caSwyllys 		}
135899ebb4caSwyllys 		(void) closedir(dirp);
135999ebb4caSwyllys 	} else {
136099ebb4caSwyllys 		/* Just try to load a single certificate */
136130a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
136230a5e8faSwyllys 		    fullpath, &certdata);
136399ebb4caSwyllys 		if (rv == KMF_OK) {
136499ebb4caSwyllys 			if (unlink(fullpath) != 0) {
136599ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
136699ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
136799ebb4caSwyllys 			}
136899ebb4caSwyllys 		}
136999ebb4caSwyllys 	}
137099ebb4caSwyllys 
137199ebb4caSwyllys out:
137299ebb4caSwyllys 	if (fullpath != NULL)
137399ebb4caSwyllys 		free(fullpath);
137499ebb4caSwyllys 
1375e65e5c2dSWyllys Ingersoll 	kmf_free_data(&certdata);
137699ebb4caSwyllys 
137799ebb4caSwyllys 	return (rv);
137899ebb4caSwyllys }
137999ebb4caSwyllys 
138099ebb4caSwyllys KMF_RETURN
138199ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
138299ebb4caSwyllys 	KMF_DATA *keydata)
138399ebb4caSwyllys {
138499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
138599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
138699ebb4caSwyllys 	int n;
138799ebb4caSwyllys 
138899ebb4caSwyllys 	if (key == NULL || keydata == NULL ||
138999ebb4caSwyllys 	    key->keyp == NULL)
139099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
139199ebb4caSwyllys 
139299ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
139399ebb4caSwyllys 		RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
139499ebb4caSwyllys 
139599ebb4caSwyllys 		if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
139699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
139799ebb4caSwyllys 			return (KMF_ERR_ENCODING);
139899ebb4caSwyllys 		}
139999ebb4caSwyllys 		RSA_free(pubkey);
140099ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
140199ebb4caSwyllys 		DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
140299ebb4caSwyllys 
140399ebb4caSwyllys 		if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
140499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
140599ebb4caSwyllys 			return (KMF_ERR_ENCODING);
140699ebb4caSwyllys 		}
140799ebb4caSwyllys 		DSA_free(pubkey);
140899ebb4caSwyllys 	} else {
140999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
141099ebb4caSwyllys 	}
141199ebb4caSwyllys 	keydata->Length = n;
141299ebb4caSwyllys 
141399ebb4caSwyllys cleanup:
141499ebb4caSwyllys 	if (rv != KMF_OK) {
141599ebb4caSwyllys 		if (keydata->Data)
141699ebb4caSwyllys 			free(keydata->Data);
141799ebb4caSwyllys 		keydata->Data = NULL;
141899ebb4caSwyllys 		keydata->Length = 0;
141999ebb4caSwyllys 	}
142099ebb4caSwyllys 
142199ebb4caSwyllys 	return (rv);
142299ebb4caSwyllys }
142399ebb4caSwyllys 
142499ebb4caSwyllys static KMF_RETURN
142530a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
142630a5e8faSwyllys 	KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
142799ebb4caSwyllys {
142899ebb4caSwyllys 	int rv = 0;
142999ebb4caSwyllys 	RSA *rsa;
143099ebb4caSwyllys 	DSA *dsa;
143199ebb4caSwyllys 
14325b3e1433Swyllys 	if (pkey == NULL || out == NULL)
14335b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
14345b3e1433Swyllys 
143599ebb4caSwyllys 	switch (format) {
143673cc0e02Swyllys 		case KMF_FORMAT_RAWKEY:
143773cc0e02Swyllys 			/* same as ASN.1 */
143899ebb4caSwyllys 		case KMF_FORMAT_ASN1:
1439*300fdee2SAndy Fiddaman 			if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
144030a5e8faSwyllys 				if (private)
144199ebb4caSwyllys 					rv = i2d_RSAPrivateKey_bio(out, rsa);
144230a5e8faSwyllys 				else
144330a5e8faSwyllys 					rv = i2d_RSAPublicKey_bio(out, rsa);
1444*300fdee2SAndy Fiddaman 			} else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
144599ebb4caSwyllys 				rv = i2d_DSAPrivateKey_bio(out, dsa);
144699ebb4caSwyllys 			}
144799ebb4caSwyllys 			if (rv == 1) {
144899ebb4caSwyllys 				rv = KMF_OK;
144999ebb4caSwyllys 			} else {
145099ebb4caSwyllys 				SET_ERROR(kmfh, rv);
145199ebb4caSwyllys 			}
145299ebb4caSwyllys 			break;
145399ebb4caSwyllys 		case KMF_FORMAT_PEM:
1454*300fdee2SAndy Fiddaman 			if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
145530a5e8faSwyllys 				if (private)
145699ebb4caSwyllys 					rv = PEM_write_bio_RSAPrivateKey(out,
145730a5e8faSwyllys 					    rsa, NULL, NULL, 0, NULL,
145830a5e8faSwyllys 					    (cred != NULL ? cred->cred : NULL));
145930a5e8faSwyllys 				else
146030a5e8faSwyllys 					rv = PEM_write_bio_RSAPublicKey(out,
146130a5e8faSwyllys 					    rsa);
1462*300fdee2SAndy Fiddaman 			} else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
146399ebb4caSwyllys 				rv = PEM_write_bio_DSAPrivateKey(out,
146430a5e8faSwyllys 				    dsa, NULL, NULL, 0, NULL,
146530a5e8faSwyllys 				    (cred != NULL ? cred->cred : NULL));
146699ebb4caSwyllys 			}
146799ebb4caSwyllys 
146899ebb4caSwyllys 			if (rv == 1) {
146999ebb4caSwyllys 				rv = KMF_OK;
147099ebb4caSwyllys 			} else {
147199ebb4caSwyllys 				SET_ERROR(kmfh, rv);
147299ebb4caSwyllys 			}
147399ebb4caSwyllys 			break;
147499ebb4caSwyllys 
147599ebb4caSwyllys 		default:
147699ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
147799ebb4caSwyllys 	}
147899ebb4caSwyllys 
147999ebb4caSwyllys 	return (rv);
148099ebb4caSwyllys }
148199ebb4caSwyllys 
148299ebb4caSwyllys KMF_RETURN
148330a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
148430a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
148599ebb4caSwyllys {
148699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
148799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1488*300fdee2SAndy Fiddaman 	uint32_t eValue = RSA_F4;
1489*300fdee2SAndy Fiddaman 	BIGNUM *eValue_bn = NULL;
149099ebb4caSwyllys 	RSA *sslPrivKey = NULL;
149199ebb4caSwyllys 	DSA *sslDSAKey = NULL;
149299ebb4caSwyllys 	EVP_PKEY *eprikey = NULL;
149399ebb4caSwyllys 	EVP_PKEY *epubkey = NULL;
149499ebb4caSwyllys 	BIO *out = NULL;
149530a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
149630a5e8faSwyllys 	uint32_t keylen = 1024;
149730a5e8faSwyllys 	uint32_t keylen_size = sizeof (uint32_t);
149830a5e8faSwyllys 	boolean_t storekey = TRUE;
149930a5e8faSwyllys 	KMF_KEY_ALG keytype = KMF_RSA;
150099ebb4caSwyllys 
1501*300fdee2SAndy Fiddaman 	eValue_bn = BN_new();
1502*300fdee2SAndy Fiddaman 	if (eValue_bn == NULL)
1503*300fdee2SAndy Fiddaman 		return (KMF_ERR_MEMORY);
1504*300fdee2SAndy Fiddaman 	if (BN_set_word(eValue_bn, eValue) == 0) {
1505*300fdee2SAndy Fiddaman 		rv = KMF_ERR_KEYGEN_FAILED;
1506*300fdee2SAndy Fiddaman 		goto cleanup;
1507*300fdee2SAndy Fiddaman 	}
1508*300fdee2SAndy Fiddaman 
150930a5e8faSwyllys 	rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
151030a5e8faSwyllys 	    &storekey, NULL);
151130a5e8faSwyllys 	if (rv != KMF_OK) {
151230a5e8faSwyllys 		/* "storekey" is optional. Default is TRUE */
151330a5e8faSwyllys 		rv = KMF_OK;
151499ebb4caSwyllys 	}
151599ebb4caSwyllys 
151630a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
151730a5e8faSwyllys 	    (void *)&keytype, NULL);
151830a5e8faSwyllys 	if (rv != KMF_OK)
151930a5e8faSwyllys 		/* keytype is optional.  KMF_RSA is default */
152030a5e8faSwyllys 		rv = KMF_OK;
152199ebb4caSwyllys 
152230a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
1523*300fdee2SAndy Fiddaman 	if (pubkey == NULL) {
1524*300fdee2SAndy Fiddaman 		rv = KMF_ERR_BAD_PARAMETER;
1525*300fdee2SAndy Fiddaman 		goto cleanup;
1526*300fdee2SAndy Fiddaman 	}
152799ebb4caSwyllys 
152830a5e8faSwyllys 	privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
1529*300fdee2SAndy Fiddaman 	if (privkey == NULL) {
1530*300fdee2SAndy Fiddaman 		rv = KMF_ERR_BAD_PARAMETER;
1531*300fdee2SAndy Fiddaman 		goto cleanup;
1532*300fdee2SAndy Fiddaman 	}
153330a5e8faSwyllys 
153430a5e8faSwyllys 	(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
153530a5e8faSwyllys 	(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
153699ebb4caSwyllys 
153799ebb4caSwyllys 	eprikey = EVP_PKEY_new();
153899ebb4caSwyllys 	if (eprikey == NULL) {
153999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
154099ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
154199ebb4caSwyllys 		goto cleanup;
154299ebb4caSwyllys 	}
154399ebb4caSwyllys 	epubkey = EVP_PKEY_new();
154499ebb4caSwyllys 	if (epubkey == NULL) {
154599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
154699ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
154799ebb4caSwyllys 		goto cleanup;
154899ebb4caSwyllys 	}
154930a5e8faSwyllys 	if (keytype == KMF_RSA) {
155030a5e8faSwyllys 		KMF_BIGINT *rsaexp = NULL;
155199ebb4caSwyllys 
155230a5e8faSwyllys 		rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
155330a5e8faSwyllys 		if (rsaexp != NULL) {
155430a5e8faSwyllys 			if (rsaexp->len > 0 &&
155530a5e8faSwyllys 			    rsaexp->len <= sizeof (eValue) &&
155630a5e8faSwyllys 			    rsaexp->val != NULL) {
1557a2d4930dSDan OpenSolaris Anderson 				/* LINTED E_BAD_PTR_CAST_ALIGN */
155830a5e8faSwyllys 				eValue = *(uint32_t *)rsaexp->val;
1559*300fdee2SAndy Fiddaman 				if (BN_set_word(eValue_bn, eValue) == 0) {
1560*300fdee2SAndy Fiddaman 					rv = KMF_ERR_BAD_PARAMETER;
1561*300fdee2SAndy Fiddaman 					goto cleanup;
1562*300fdee2SAndy Fiddaman 				}
156330a5e8faSwyllys 			} else {
156430a5e8faSwyllys 				rv = KMF_ERR_BAD_PARAMETER;
156530a5e8faSwyllys 				goto cleanup;
156630a5e8faSwyllys 			}
156730a5e8faSwyllys 		} else {
156830a5e8faSwyllys 			/* RSA Exponent is optional. Default is 0x10001 */
156930a5e8faSwyllys 			rv = KMF_OK;
157030a5e8faSwyllys 		}
157130a5e8faSwyllys 
157230a5e8faSwyllys 		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
157330a5e8faSwyllys 		    &keylen, &keylen_size);
157430a5e8faSwyllys 		if (rv == KMF_ERR_ATTR_NOT_FOUND)
157530a5e8faSwyllys 			/* keylen is optional, default is 1024 */
157630a5e8faSwyllys 			rv = KMF_OK;
157730a5e8faSwyllys 		if (rv != KMF_OK) {
157830a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
157930a5e8faSwyllys 			goto cleanup;
158030a5e8faSwyllys 		}
158130a5e8faSwyllys 
1582*300fdee2SAndy Fiddaman 		sslPrivKey = RSA_new();
1583*300fdee2SAndy Fiddaman 		if (sslPrivKey == NULL ||
1584*300fdee2SAndy Fiddaman 		    RSA_generate_key_ex(sslPrivKey, keylen, eValue_bn, NULL)
1585*300fdee2SAndy Fiddaman 		    == 0) {
158699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
158799ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
158899ebb4caSwyllys 		} else {
158930a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
159099ebb4caSwyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
159199ebb4caSwyllys 			privkey->keyalg = KMF_RSA;
159299ebb4caSwyllys 			privkey->keyclass = KMF_ASYM_PRI;
159399ebb4caSwyllys 			privkey->israw = FALSE;
159499ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
159530a5e8faSwyllys 
159699ebb4caSwyllys 			/* OpenSSL derives the public key from the private */
159730a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
159899ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
159999ebb4caSwyllys 			pubkey->keyalg = KMF_RSA;
160099ebb4caSwyllys 			pubkey->israw = FALSE;
160199ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
160299ebb4caSwyllys 			pubkey->keyp = (void *)epubkey;
160399ebb4caSwyllys 		}
160430a5e8faSwyllys 	} else if (keytype == KMF_DSA) {
1605*300fdee2SAndy Fiddaman 		BIGNUM *p, *q, *g;
1606*300fdee2SAndy Fiddaman 
160799ebb4caSwyllys 		sslDSAKey = DSA_new();
160899ebb4caSwyllys 		if (sslDSAKey == NULL) {
160999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
161099ebb4caSwyllys 			return (KMF_ERR_MEMORY);
161199ebb4caSwyllys 		}
161299ebb4caSwyllys 
1613*300fdee2SAndy Fiddaman 		p = BN_bin2bn(P, sizeof (P), NULL);
1614*300fdee2SAndy Fiddaman 		q = BN_bin2bn(Q, sizeof (Q), NULL);
1615*300fdee2SAndy Fiddaman 		g = BN_bin2bn(G, sizeof (G), NULL);
1616*300fdee2SAndy Fiddaman 		if (p == NULL || q == NULL || g == NULL) {
1617*300fdee2SAndy Fiddaman 			BN_free(p);
1618*300fdee2SAndy Fiddaman 			BN_free(q);
1619*300fdee2SAndy Fiddaman 			BN_free(g);
162099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
162199ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
162299ebb4caSwyllys 			goto cleanup;
162399ebb4caSwyllys 		}
1624*300fdee2SAndy Fiddaman 
1625*300fdee2SAndy Fiddaman 		if (DSA_set0_pqg(sslDSAKey, p, q, g) == 0) {
162699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
162799ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
162899ebb4caSwyllys 			goto cleanup;
162999ebb4caSwyllys 		}
163099ebb4caSwyllys 
163199ebb4caSwyllys 		if (!DSA_generate_key(sslDSAKey)) {
163299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
163399ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
163499ebb4caSwyllys 			goto cleanup;
163599ebb4caSwyllys 		}
163699ebb4caSwyllys 
163799ebb4caSwyllys 		privkey->kstype = KMF_KEYSTORE_OPENSSL;
163899ebb4caSwyllys 		privkey->keyalg = KMF_DSA;
163999ebb4caSwyllys 		privkey->keyclass = KMF_ASYM_PRI;
164099ebb4caSwyllys 		privkey->israw = FALSE;
164199ebb4caSwyllys 		if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
164299ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
164399ebb4caSwyllys 		} else {
164499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
164599ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
164699ebb4caSwyllys 			goto cleanup;
164799ebb4caSwyllys 		}
164899ebb4caSwyllys 
164999ebb4caSwyllys 		pubkey->kstype = KMF_KEYSTORE_OPENSSL;
165099ebb4caSwyllys 		pubkey->keyalg = KMF_DSA;
165199ebb4caSwyllys 		pubkey->keyclass = KMF_ASYM_PUB;
165299ebb4caSwyllys 		pubkey->israw = FALSE;
165399ebb4caSwyllys 
165499ebb4caSwyllys 		if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
165599ebb4caSwyllys 			pubkey->keyp = (void *)epubkey;
165699ebb4caSwyllys 		} else {
165799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
165899ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
165999ebb4caSwyllys 			goto cleanup;
166099ebb4caSwyllys 		}
166199ebb4caSwyllys 	}
166299ebb4caSwyllys 
166399ebb4caSwyllys 	if (rv != KMF_OK) {
166499ebb4caSwyllys 		goto cleanup;
166599ebb4caSwyllys 	}
166699ebb4caSwyllys 
166730a5e8faSwyllys 	if (storekey) {
166830a5e8faSwyllys 		KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
166930a5e8faSwyllys 		int i = 0;
167030a5e8faSwyllys 		char *keyfile = NULL, *dirpath = NULL;
167130a5e8faSwyllys 		KMF_ENCODE_FORMAT format;
167230a5e8faSwyllys 		/*
167330a5e8faSwyllys 		 * Construct a new attribute arrray and call openssl_store_key
167430a5e8faSwyllys 		 */
167530a5e8faSwyllys 		kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
167630a5e8faSwyllys 		    privkey, sizeof (privkey));
167730a5e8faSwyllys 		i++;
167830a5e8faSwyllys 
167930a5e8faSwyllys 		dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
168030a5e8faSwyllys 		if (dirpath != NULL) {
168130a5e8faSwyllys 			storeattrs[i].type = KMF_DIRPATH_ATTR;
168230a5e8faSwyllys 			storeattrs[i].pValue = dirpath;
168330a5e8faSwyllys 			storeattrs[i].valueLen = strlen(dirpath);
168430a5e8faSwyllys 			i++;
168530a5e8faSwyllys 		} else {
168630a5e8faSwyllys 			rv = KMF_OK; /* DIRPATH is optional */
168799ebb4caSwyllys 		}
168830a5e8faSwyllys 		keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
168930a5e8faSwyllys 		    attrlist, numattr);
169030a5e8faSwyllys 		if (keyfile != NULL) {
169130a5e8faSwyllys 			storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
169230a5e8faSwyllys 			storeattrs[i].pValue = keyfile;
169330a5e8faSwyllys 			storeattrs[i].valueLen = strlen(keyfile);
169430a5e8faSwyllys 			i++;
169530a5e8faSwyllys 		} else {
169630a5e8faSwyllys 			goto cleanup; /* KEYFILE is required */
169730a5e8faSwyllys 		}
169830a5e8faSwyllys 		rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
169930a5e8faSwyllys 		    (void *)&format, NULL);
170030a5e8faSwyllys 		if (rv == KMF_OK) {
170130a5e8faSwyllys 			storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
170230a5e8faSwyllys 			storeattrs[i].pValue = &format;
170330a5e8faSwyllys 			storeattrs[i].valueLen = sizeof (format);
170430a5e8faSwyllys 			i++;
170530a5e8faSwyllys 		}
170630a5e8faSwyllys 
170730a5e8faSwyllys 		rv = OpenSSL_StoreKey(handle, i, storeattrs);
170830a5e8faSwyllys 	}
170999ebb4caSwyllys 
171099ebb4caSwyllys cleanup:
1711*300fdee2SAndy Fiddaman 	if (eValue_bn != NULL)
1712*300fdee2SAndy Fiddaman 		BN_free(eValue_bn);
1713*300fdee2SAndy Fiddaman 
171499ebb4caSwyllys 	if (rv != KMF_OK) {
171599ebb4caSwyllys 		if (eprikey != NULL)
171699ebb4caSwyllys 			EVP_PKEY_free(eprikey);
171799ebb4caSwyllys 
171899ebb4caSwyllys 		if (epubkey != NULL)
171999ebb4caSwyllys 			EVP_PKEY_free(epubkey);
172099ebb4caSwyllys 
172199ebb4caSwyllys 		if (pubkey->keylabel) {
172299ebb4caSwyllys 			free(pubkey->keylabel);
172399ebb4caSwyllys 			pubkey->keylabel = NULL;
172499ebb4caSwyllys 		}
172599ebb4caSwyllys 
172699ebb4caSwyllys 		if (privkey->keylabel) {
172799ebb4caSwyllys 			free(privkey->keylabel);
172899ebb4caSwyllys 			privkey->keylabel = NULL;
172999ebb4caSwyllys 		}
173099ebb4caSwyllys 
173199ebb4caSwyllys 		pubkey->keyp = NULL;
173299ebb4caSwyllys 		privkey->keyp = NULL;
173399ebb4caSwyllys 	}
173499ebb4caSwyllys 
173599ebb4caSwyllys 	if (sslPrivKey)
173699ebb4caSwyllys 		RSA_free(sslPrivKey);
173799ebb4caSwyllys 
173899ebb4caSwyllys 	if (sslDSAKey)
173999ebb4caSwyllys 		DSA_free(sslDSAKey);
174099ebb4caSwyllys 
174199ebb4caSwyllys 	if (out != NULL)
174299ebb4caSwyllys 		(void) BIO_free(out);
174399ebb4caSwyllys 
174499ebb4caSwyllys 	return (rv);
174599ebb4caSwyllys }
174699ebb4caSwyllys 
1747e65e5c2dSWyllys Ingersoll /*
1748e65e5c2dSWyllys Ingersoll  * Make sure the BN conversion is properly padded with 0x00
1749e65e5c2dSWyllys Ingersoll  * bytes.  If not, signature verification for DSA signatures
1750e65e5c2dSWyllys Ingersoll  * may fail in the case where the bignum value does not use
1751e65e5c2dSWyllys Ingersoll  * all of the bits.
1752e65e5c2dSWyllys Ingersoll  */
1753e65e5c2dSWyllys Ingersoll static int
1754*300fdee2SAndy Fiddaman fixbnlen(const BIGNUM *bn, unsigned char *buf, int len) {
1755e65e5c2dSWyllys Ingersoll 	int bytes = len - BN_num_bytes(bn);
17562c9a247fSWyllys Ingersoll 
17572c9a247fSWyllys Ingersoll 	/* prepend with leading 0x00 if necessary */
1758e65e5c2dSWyllys Ingersoll 	while (bytes-- > 0)
1759e65e5c2dSWyllys Ingersoll 		*buf++ = 0;
1760e65e5c2dSWyllys Ingersoll 
17612c9a247fSWyllys Ingersoll 	(void) BN_bn2bin(bn, buf);
17622c9a247fSWyllys Ingersoll 	/*
17632c9a247fSWyllys Ingersoll 	 * Return the desired length since we prepended it
17642c9a247fSWyllys Ingersoll 	 * with the necessary 0x00 padding.
17652c9a247fSWyllys Ingersoll 	 */
17662c9a247fSWyllys Ingersoll 	return (len);
1767e65e5c2dSWyllys Ingersoll }
1768e65e5c2dSWyllys Ingersoll 
176999ebb4caSwyllys KMF_RETURN
177099ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
177199ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
177299ebb4caSwyllys {
177399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
177499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
177599ebb4caSwyllys 	KMF_ALGORITHM_INDEX		AlgId;
1776*300fdee2SAndy Fiddaman 	EVP_MD_CTX *ctx;
177799ebb4caSwyllys 	const EVP_MD *md;
177802744e81Swyllys 
177999ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
178099ebb4caSwyllys 	    tobesigned == NULL || output == NULL ||
178199ebb4caSwyllys 	    tobesigned->Data == NULL ||
178299ebb4caSwyllys 	    output->Data == NULL)
178399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
178499ebb4caSwyllys 
178599ebb4caSwyllys 	/* Map the OID to an OpenSSL algorithm */
178630a5e8faSwyllys 	AlgId = x509_algoid_to_algid(AlgOID);
178799ebb4caSwyllys 	if (AlgId == KMF_ALGID_NONE)
1788e65e5c2dSWyllys Ingersoll 		return (KMF_ERR_BAD_ALGORITHM);
178999ebb4caSwyllys 
179099ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
179199ebb4caSwyllys 		EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
179299ebb4caSwyllys 		uchar_t *p;
179302744e81Swyllys 		int len;
179499ebb4caSwyllys 		if (AlgId == KMF_ALGID_MD5WithRSA)
179599ebb4caSwyllys 			md = EVP_md5();
179699ebb4caSwyllys 		else if (AlgId == KMF_ALGID_SHA1WithRSA)
179799ebb4caSwyllys 			md = EVP_sha1();
1798e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA256WithRSA)
1799e65e5c2dSWyllys Ingersoll 			md = EVP_sha256();
1800e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA384WithRSA)
1801e65e5c2dSWyllys Ingersoll 			md = EVP_sha384();
1802e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA512WithRSA)
1803e65e5c2dSWyllys Ingersoll 			md = EVP_sha512();
180402744e81Swyllys 		else if (AlgId == KMF_ALGID_RSA)
180502744e81Swyllys 			md = NULL;
180699ebb4caSwyllys 		else
1807e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_ALGORITHM);
180899ebb4caSwyllys 
180902744e81Swyllys 		if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
181002744e81Swyllys 			RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
181199ebb4caSwyllys 
181202744e81Swyllys 			p = output->Data;
181302744e81Swyllys 			if ((len = RSA_private_encrypt(tobesigned->Length,
181402744e81Swyllys 			    tobesigned->Data, p, rsa,
181502744e81Swyllys 			    RSA_PKCS1_PADDING)) <= 0) {
181602744e81Swyllys 				SET_ERROR(kmfh, ERR_get_error());
181702744e81Swyllys 				ret = KMF_ERR_INTERNAL;
181802744e81Swyllys 			}
181902744e81Swyllys 			output->Length = len;
182002744e81Swyllys 		} else {
1821*300fdee2SAndy Fiddaman 			if ((ctx = EVP_MD_CTX_new()) == NULL)
1822*300fdee2SAndy Fiddaman 				return (KMF_ERR_MEMORY);
1823*300fdee2SAndy Fiddaman 			(void) EVP_SignInit_ex(ctx, md, NULL);
1824*300fdee2SAndy Fiddaman 			(void) EVP_SignUpdate(ctx, tobesigned->Data,
182599ebb4caSwyllys 			    (uint32_t)tobesigned->Length);
182699ebb4caSwyllys 			len = (uint32_t)output->Length;
182799ebb4caSwyllys 			p = output->Data;
1828*300fdee2SAndy Fiddaman 			if (!EVP_SignFinal(ctx, p, (uint32_t *)&len, pkey)) {
182999ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
183002744e81Swyllys 				len = 0;
183102744e81Swyllys 				ret = KMF_ERR_INTERNAL;
183299ebb4caSwyllys 			}
183399ebb4caSwyllys 			output->Length = len;
1834*300fdee2SAndy Fiddaman 			EVP_MD_CTX_free(ctx);
183502744e81Swyllys 		}
183699ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
183799ebb4caSwyllys 		DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
183899ebb4caSwyllys 
183999ebb4caSwyllys 		uchar_t hash[EVP_MAX_MD_SIZE];
184099ebb4caSwyllys 		uint32_t hashlen;
184199ebb4caSwyllys 		DSA_SIG *dsasig;
184299ebb4caSwyllys 
1843e65e5c2dSWyllys Ingersoll 		if (AlgId == KMF_ALGID_DSA ||
1844e65e5c2dSWyllys Ingersoll 		    AlgId == KMF_ALGID_SHA1WithDSA)
1845e65e5c2dSWyllys Ingersoll 			md = EVP_sha1();
1846e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA256WithDSA)
1847e65e5c2dSWyllys Ingersoll 			md = EVP_sha256();
1848e65e5c2dSWyllys Ingersoll 		else /* Bad algorithm */
1849e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_ALGORITHM);
1850e65e5c2dSWyllys Ingersoll 
185199ebb4caSwyllys 		/*
185299ebb4caSwyllys 		 * OpenSSL EVP_Sign operation automatically converts to
185399ebb4caSwyllys 		 * ASN.1 output so we do the operations separately so we
185499ebb4caSwyllys 		 * are assured of NOT getting ASN.1 output returned.
185599ebb4caSwyllys 		 * KMF does not want ASN.1 encoded results because
185699ebb4caSwyllys 		 * not all mechanisms return ASN.1 encodings (PKCS#11
185799ebb4caSwyllys 		 * and NSS return raw signature data).
185899ebb4caSwyllys 		 */
1859*300fdee2SAndy Fiddaman 		if ((ctx = EVP_MD_CTX_new()) == NULL)
1860*300fdee2SAndy Fiddaman 			return (KMF_ERR_MEMORY);
1861*300fdee2SAndy Fiddaman 		(void) EVP_DigestInit_ex(ctx, md, NULL);
1862*300fdee2SAndy Fiddaman 		(void) EVP_DigestUpdate(ctx, tobesigned->Data,
186399ebb4caSwyllys 		    tobesigned->Length);
1864*300fdee2SAndy Fiddaman 		(void) EVP_DigestFinal_ex(ctx, hash, &hashlen);
186599ebb4caSwyllys 
1866e65e5c2dSWyllys Ingersoll 		/* Only sign first 20 bytes for SHA2 */
1867e65e5c2dSWyllys Ingersoll 		if (AlgId == KMF_ALGID_SHA256WithDSA)
1868e65e5c2dSWyllys Ingersoll 			hashlen = 20;
186999ebb4caSwyllys 		dsasig = DSA_do_sign(hash, hashlen, dsa);
187099ebb4caSwyllys 		if (dsasig != NULL) {
187199ebb4caSwyllys 			int i;
1872*300fdee2SAndy Fiddaman 			const BIGNUM *r, *s;
1873*300fdee2SAndy Fiddaman 
1874*300fdee2SAndy Fiddaman 			DSA_SIG_get0(dsasig, &r, &s);
1875*300fdee2SAndy Fiddaman 			output->Length = i = fixbnlen(r, output->Data,
1876e65e5c2dSWyllys Ingersoll 			    hashlen);
18772c9a247fSWyllys Ingersoll 
1878*300fdee2SAndy Fiddaman 			output->Length += fixbnlen(s, &output->Data[i],
1879e65e5c2dSWyllys Ingersoll 			    hashlen);
18802c9a247fSWyllys Ingersoll 
188199ebb4caSwyllys 			DSA_SIG_free(dsasig);
188299ebb4caSwyllys 		} else {
188399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
188499ebb4caSwyllys 		}
1885*300fdee2SAndy Fiddaman 		EVP_MD_CTX_free(ctx);
188699ebb4caSwyllys 	} else {
188799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
188899ebb4caSwyllys 	}
188999ebb4caSwyllys cleanup:
189099ebb4caSwyllys 	return (ret);
189199ebb4caSwyllys }
189299ebb4caSwyllys 
189399ebb4caSwyllys KMF_RETURN
189499ebb4caSwyllys /*ARGSUSED*/
189530a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle,
189630a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
189799ebb4caSwyllys {
189899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
189930a5e8faSwyllys 	KMF_KEY_HANDLE *key;
190030a5e8faSwyllys 	boolean_t destroy = B_TRUE;
190130a5e8faSwyllys 
190230a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
190399ebb4caSwyllys 	if (key == NULL || key->keyp == NULL)
190499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
190599ebb4caSwyllys 
190630a5e8faSwyllys 	rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
190730a5e8faSwyllys 	    (void *)&destroy, NULL);
190830a5e8faSwyllys 	if (rv != KMF_OK) {
190930a5e8faSwyllys 		/* "destroy" is optional. Default is TRUE */
191030a5e8faSwyllys 		rv = KMF_OK;
191130a5e8faSwyllys 	}
191230a5e8faSwyllys 
191399ebb4caSwyllys 	if (key->keyclass != KMF_ASYM_PUB &&
191499ebb4caSwyllys 	    key->keyclass != KMF_ASYM_PRI &&
191599ebb4caSwyllys 	    key->keyclass != KMF_SYMMETRIC)
191699ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
191799ebb4caSwyllys 
191899ebb4caSwyllys 	if (key->keyclass == KMF_SYMMETRIC) {
191930a5e8faSwyllys 		kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
192099ebb4caSwyllys 		key->keyp = NULL;
192199ebb4caSwyllys 	} else {
192299ebb4caSwyllys 		if (key->keyp != NULL) {
192399ebb4caSwyllys 			EVP_PKEY_free(key->keyp);
192499ebb4caSwyllys 			key->keyp = NULL;
192599ebb4caSwyllys 		}
192699ebb4caSwyllys 	}
192799ebb4caSwyllys 
192899ebb4caSwyllys 	if (key->keylabel != NULL) {
192999ebb4caSwyllys 		EVP_PKEY *pkey = NULL;
193099ebb4caSwyllys 		/* If the file exists, make sure it is a proper key. */
193199ebb4caSwyllys 		pkey = openssl_load_key(handle, key->keylabel);
193299ebb4caSwyllys 		if (pkey == NULL) {
19335b3e1433Swyllys 			if (key->keylabel != NULL) {
193499ebb4caSwyllys 				free(key->keylabel);
193599ebb4caSwyllys 				key->keylabel = NULL;
19365b3e1433Swyllys 			}
193799ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
193899ebb4caSwyllys 		}
193999ebb4caSwyllys 		EVP_PKEY_free(pkey);
194099ebb4caSwyllys 
194199ebb4caSwyllys 		if (destroy) {
194299ebb4caSwyllys 			if (unlink(key->keylabel) != 0) {
194399ebb4caSwyllys 				KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
194499ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
194599ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
194699ebb4caSwyllys 			}
194799ebb4caSwyllys 		}
194899ebb4caSwyllys 		if (key->keylabel != NULL) {
194999ebb4caSwyllys 			free(key->keylabel);
195099ebb4caSwyllys 			key->keylabel = NULL;
195199ebb4caSwyllys 		}
195299ebb4caSwyllys 	}
195399ebb4caSwyllys 	return (rv);
195499ebb4caSwyllys }
195599ebb4caSwyllys 
195699ebb4caSwyllys KMF_RETURN
195799ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
195899ebb4caSwyllys {
195999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
196099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
196199ebb4caSwyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
196299ebb4caSwyllys 
196399ebb4caSwyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
196499ebb4caSwyllys 	if (strlen(str)) {
196599ebb4caSwyllys 		*msgstr = (char *)strdup(str);
196699ebb4caSwyllys 		if ((*msgstr) == NULL)
196799ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
196899ebb4caSwyllys 	} else {
196999ebb4caSwyllys 		*msgstr = NULL;
197099ebb4caSwyllys 	}
197199ebb4caSwyllys 
197299ebb4caSwyllys 	return (ret);
197399ebb4caSwyllys }
197499ebb4caSwyllys 
197599ebb4caSwyllys static int
197699ebb4caSwyllys ext2NID(int kmfext)
197799ebb4caSwyllys {
197899ebb4caSwyllys 	switch (kmfext) {
197999ebb4caSwyllys 		case KMF_X509_EXT_KEY_USAGE:
198099ebb4caSwyllys 			return (NID_key_usage);
198199ebb4caSwyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
198299ebb4caSwyllys 			return (NID_private_key_usage_period);
198399ebb4caSwyllys 		case KMF_X509_EXT_CERT_POLICIES:
198499ebb4caSwyllys 			return (NID_certificate_policies);
198599ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
198699ebb4caSwyllys 			return (NID_subject_alt_name);
198799ebb4caSwyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
198899ebb4caSwyllys 			return (NID_issuer_alt_name);
198999ebb4caSwyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
199099ebb4caSwyllys 			return (NID_basic_constraints);
199199ebb4caSwyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
199299ebb4caSwyllys 			return (NID_ext_key_usage);
199399ebb4caSwyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
199499ebb4caSwyllys 			return (NID_authority_key_identifier);
199599ebb4caSwyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
199699ebb4caSwyllys 			return (NID_crl_distribution_points);
199799ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
199899ebb4caSwyllys 			return (NID_subject_key_identifier);
199999ebb4caSwyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
200099ebb4caSwyllys 			return (OBJ_sn2nid("policyMappings"));
200199ebb4caSwyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
200299ebb4caSwyllys 			return (OBJ_sn2nid("nameConstraints"));
200399ebb4caSwyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
200499ebb4caSwyllys 			return (OBJ_sn2nid("policyConstraints"));
200599ebb4caSwyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
200699ebb4caSwyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
200799ebb4caSwyllys 		case KMF_X509_EXT_FRESHEST_CRL:
200899ebb4caSwyllys 			return (OBJ_sn2nid("freshestCRL"));
200999ebb4caSwyllys 		default:
201099ebb4caSwyllys 			return (NID_undef);
201199ebb4caSwyllys 	}
201299ebb4caSwyllys }
201399ebb4caSwyllys 
201499ebb4caSwyllys KMF_RETURN
201599ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
201699ebb4caSwyllys 	KMF_PRINTABLE_ITEM flag, char *resultStr)
201799ebb4caSwyllys {
201899ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
201999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
202099ebb4caSwyllys 	X509 *xcert = NULL;
202199ebb4caSwyllys 	unsigned char *outbuf = NULL;
202299ebb4caSwyllys 	unsigned char *outbuf_p;
202399ebb4caSwyllys 	int j;
202499ebb4caSwyllys 	int ext_index, nid, len;
202599ebb4caSwyllys 	BIO *mem = NULL;
202670f9559bSTheo Schlossnagle 	STACK_OF(OPENSSL_STRING) *emlst = NULL;
202799ebb4caSwyllys 	X509_EXTENSION *ex;
202899ebb4caSwyllys 
202999ebb4caSwyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
203099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
203199ebb4caSwyllys 	}
203299ebb4caSwyllys 
203399ebb4caSwyllys 	/* copy cert data to outbuf */
203499ebb4caSwyllys 	outbuf = malloc(pcert->Length);
203599ebb4caSwyllys 	if (outbuf == NULL) {
203699ebb4caSwyllys 		return (KMF_ERR_MEMORY);
203799ebb4caSwyllys 	}
203899ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
203999ebb4caSwyllys 
204099ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
204199ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
204299ebb4caSwyllys 	if (xcert == NULL) {
204399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
204499ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
204599ebb4caSwyllys 		goto out;
204699ebb4caSwyllys 	}
204799ebb4caSwyllys 
204899ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
204999ebb4caSwyllys 	if (mem == NULL) {
205099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
205199ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
205299ebb4caSwyllys 		goto out;
205399ebb4caSwyllys 	}
205499ebb4caSwyllys 
205599ebb4caSwyllys 	switch (flag) {
205699ebb4caSwyllys 	case KMF_CERT_ISSUER:
205799ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
205899ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
205999ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
206099ebb4caSwyllys 		break;
206199ebb4caSwyllys 
206299ebb4caSwyllys 	case KMF_CERT_SUBJECT:
206399ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
206499ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
206599ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
206699ebb4caSwyllys 		break;
206799ebb4caSwyllys 
206899ebb4caSwyllys 	case KMF_CERT_VERSION:
2069*300fdee2SAndy Fiddaman 		(void) snprintf(resultStr, KMF_CERT_PRINTABLE_LEN,
2070*300fdee2SAndy Fiddaman 		    "%ld", X509_get_version(xcert));
207199ebb4caSwyllys 		len = strlen(resultStr);
207299ebb4caSwyllys 		break;
207399ebb4caSwyllys 
207499ebb4caSwyllys 	case KMF_CERT_SERIALNUM:
207599ebb4caSwyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
207699ebb4caSwyllys 			(void) strcpy(resultStr, "0x");
207799ebb4caSwyllys 			len = BIO_gets(mem, &resultStr[2],
207899ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN - 2);
207999ebb4caSwyllys 		}
208099ebb4caSwyllys 		break;
208199ebb4caSwyllys 
208299ebb4caSwyllys 	case KMF_CERT_NOTBEFORE:
2083*300fdee2SAndy Fiddaman 		(void) ASN1_TIME_print(mem, X509_getm_notBefore(xcert));
208499ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
208599ebb4caSwyllys 		break;
208699ebb4caSwyllys 
208799ebb4caSwyllys 	case KMF_CERT_NOTAFTER:
2088*300fdee2SAndy Fiddaman 		(void) ASN1_TIME_print(mem, X509_getm_notAfter(xcert));
208999ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
209099ebb4caSwyllys 		break;
209199ebb4caSwyllys 
209299ebb4caSwyllys 	case KMF_CERT_PUBKEY_DATA:
209399ebb4caSwyllys 		{
2094*300fdee2SAndy Fiddaman 			RSA *rsa;
2095*300fdee2SAndy Fiddaman 			DSA *dsa;
2096*300fdee2SAndy Fiddaman 
209799ebb4caSwyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
209899ebb4caSwyllys 			if (pkey == NULL) {
209999ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
210099ebb4caSwyllys 				ret = KMF_ERR_ENCODING;
210199ebb4caSwyllys 				goto out;
210299ebb4caSwyllys 			}
210399ebb4caSwyllys 
2104*300fdee2SAndy Fiddaman 			if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
210599ebb4caSwyllys 				(void) BIO_printf(mem,
210699ebb4caSwyllys 				    "RSA Public Key: (%d bit)\n",
2107*300fdee2SAndy Fiddaman 				    RSA_bits(rsa));
2108*300fdee2SAndy Fiddaman 				(void) RSA_print(mem, rsa, 0);
2109*300fdee2SAndy Fiddaman 
2110*300fdee2SAndy Fiddaman 			} else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
211199ebb4caSwyllys 				(void) BIO_printf(mem,
211299ebb4caSwyllys 				    "%12sDSA Public Key:\n", "");
2113*300fdee2SAndy Fiddaman 				(void) DSA_print(mem, dsa, 0);
211499ebb4caSwyllys 			} else {
211599ebb4caSwyllys 				(void) BIO_printf(mem,
211699ebb4caSwyllys 				    "%12sUnknown Public Key:\n", "");
211799ebb4caSwyllys 			}
211899ebb4caSwyllys 			(void) BIO_printf(mem, "\n");
211999ebb4caSwyllys 			EVP_PKEY_free(pkey);
212099ebb4caSwyllys 		}
212199ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
212299ebb4caSwyllys 		break;
212399ebb4caSwyllys 	case KMF_CERT_SIGNATURE_ALG:
212499ebb4caSwyllys 	case KMF_CERT_PUBKEY_ALG:
2125*300fdee2SAndy Fiddaman 		{
2126*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L
2127*300fdee2SAndy Fiddaman 			ASN1_OBJECT *alg = NULL;
2128*300fdee2SAndy Fiddaman #else
2129*300fdee2SAndy Fiddaman 			const ASN1_OBJECT *alg = NULL;
2130*300fdee2SAndy Fiddaman #endif
2131*300fdee2SAndy Fiddaman 
213299ebb4caSwyllys 			if (flag == KMF_CERT_SIGNATURE_ALG) {
2133*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L
2134*300fdee2SAndy Fiddaman 				alg = xcert->sig_alg->algorithm;
2135*300fdee2SAndy Fiddaman #else
2136*300fdee2SAndy Fiddaman 				const X509_ALGOR *sig_alg = NULL;
2137*300fdee2SAndy Fiddaman 
2138*300fdee2SAndy Fiddaman 				X509_get0_signature(NULL, &sig_alg, xcert);
2139*300fdee2SAndy Fiddaman 				if (sig_alg != NULL)
2140*300fdee2SAndy Fiddaman 					X509_ALGOR_get0(&alg, NULL, NULL,
2141*300fdee2SAndy Fiddaman 					    sig_alg);
2142*300fdee2SAndy Fiddaman #endif
214399ebb4caSwyllys 			} else {
2144*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L
2145*300fdee2SAndy Fiddaman 				alg = xcert->cert_info->key->algor->algorithm;
2146*300fdee2SAndy Fiddaman #else
2147*300fdee2SAndy Fiddaman 				X509_PUBKEY *key = X509_get_X509_PUBKEY(xcert);
2148*300fdee2SAndy Fiddaman 
2149*300fdee2SAndy Fiddaman 				if (key != NULL)
2150*300fdee2SAndy Fiddaman 					(void) X509_PUBKEY_get0_param(
2151*300fdee2SAndy Fiddaman 					    (ASN1_OBJECT **)&alg, NULL, 0,
2152*300fdee2SAndy Fiddaman 					    NULL, key);
2153*300fdee2SAndy Fiddaman #endif
215499ebb4caSwyllys 			}
215599ebb4caSwyllys 
2156*300fdee2SAndy Fiddaman 			if (alg == NULL)
2157*300fdee2SAndy Fiddaman 				len = -1;
2158*300fdee2SAndy Fiddaman 			else if ((len = i2a_ASN1_OBJECT(mem, alg)) > 0)
215999ebb4caSwyllys 				len = BIO_read(mem, resultStr,
216099ebb4caSwyllys 				    KMF_CERT_PRINTABLE_LEN);
216199ebb4caSwyllys 		}
216299ebb4caSwyllys 		break;
216399ebb4caSwyllys 
216499ebb4caSwyllys 	case KMF_CERT_EMAIL:
216599ebb4caSwyllys 		emlst = X509_get1_email(xcert);
216670f9559bSTheo Schlossnagle 		for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
216770f9559bSTheo Schlossnagle 			(void) BIO_printf(mem, "%s\n",
216870f9559bSTheo Schlossnagle 			    sk_OPENSSL_STRING_value(emlst, j));
216999ebb4caSwyllys 
217099ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
217199ebb4caSwyllys 		X509_email_free(emlst);
217299ebb4caSwyllys 		break;
217399ebb4caSwyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
217499ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
217599ebb4caSwyllys 	case KMF_X509_EXT_KEY_USAGE:
217699ebb4caSwyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
217799ebb4caSwyllys 	case KMF_X509_EXT_CERT_POLICIES:
217899ebb4caSwyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
217999ebb4caSwyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
218099ebb4caSwyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
218199ebb4caSwyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
218299ebb4caSwyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
218399ebb4caSwyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
218499ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
218599ebb4caSwyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
218699ebb4caSwyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
218799ebb4caSwyllys 	case KMF_X509_EXT_FRESHEST_CRL:
218899ebb4caSwyllys 		nid = ext2NID(flag);
218999ebb4caSwyllys 		if (nid == NID_undef) {
219099ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
219199ebb4caSwyllys 			goto out;
219299ebb4caSwyllys 		}
219399ebb4caSwyllys 
2194*300fdee2SAndy Fiddaman 		ext_index = X509_get_ext_by_NID(xcert, nid, -1);
219599ebb4caSwyllys 		if (ext_index == -1) {
219699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
219799ebb4caSwyllys 
219899ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
219999ebb4caSwyllys 			goto out;
220099ebb4caSwyllys 		}
2201*300fdee2SAndy Fiddaman 		ex = X509_get_ext(xcert, ext_index);
220299ebb4caSwyllys 
220399ebb4caSwyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
220499ebb4caSwyllys 
220599ebb4caSwyllys 		if (BIO_printf(mem, ": %s\n",
220630a5e8faSwyllys 		    X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
220799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
220899ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
220999ebb4caSwyllys 			goto out;
221099ebb4caSwyllys 		}
221199ebb4caSwyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
221299ebb4caSwyllys 			(void) BIO_printf(mem, "%*s", 4, "");
2213*300fdee2SAndy Fiddaman 			(void) ASN1_STRING_print(mem,
2214*300fdee2SAndy Fiddaman 			    X509_EXTENSION_get_data(ex));
221599ebb4caSwyllys 		}
221699ebb4caSwyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
221799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
221899ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
221999ebb4caSwyllys 			goto out;
222099ebb4caSwyllys 		}
222199ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
222299ebb4caSwyllys 	}
222399ebb4caSwyllys 	if (len <= 0) {
222499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
222599ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
222699ebb4caSwyllys 	}
222799ebb4caSwyllys 
222899ebb4caSwyllys out:
222999ebb4caSwyllys 	if (outbuf != NULL) {
223099ebb4caSwyllys 		free(outbuf);
223199ebb4caSwyllys 	}
223299ebb4caSwyllys 
223399ebb4caSwyllys 	if (xcert != NULL) {
223499ebb4caSwyllys 		X509_free(xcert);
223599ebb4caSwyllys 	}
223699ebb4caSwyllys 
223799ebb4caSwyllys 	if (mem != NULL) {
223899ebb4caSwyllys 		(void) BIO_free(mem);
223999ebb4caSwyllys 	}
224099ebb4caSwyllys 
224199ebb4caSwyllys 	return (ret);
224299ebb4caSwyllys }
224330a5e8faSwyllys 
224499ebb4caSwyllys KMF_RETURN
224599ebb4caSwyllys /*ARGSUSED*/
224630a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
224730a5e8faSwyllys     KMF_ATTRIBUTE *attrlist)
224899ebb4caSwyllys {
224999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
225030a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
225130a5e8faSwyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
225230a5e8faSwyllys 	KMF_KEY_HANDLE *key = NULL;
225330a5e8faSwyllys 	uint32_t numkeys = 1; /* 1 key only */
225430a5e8faSwyllys 	char *dirpath = NULL;
225530a5e8faSwyllys 	char *keyfile = NULL;
225630a5e8faSwyllys 	KMF_ATTRIBUTE new_attrlist[16];
225730a5e8faSwyllys 	int i = 0;
225899ebb4caSwyllys 
225999ebb4caSwyllys 	/*
226099ebb4caSwyllys 	 * This is really just a FindKey operation, reuse the
226199ebb4caSwyllys 	 * FindKey function.
226299ebb4caSwyllys 	 */
226330a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
226430a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
226530a5e8faSwyllys 	i++;
226699ebb4caSwyllys 
226730a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
226830a5e8faSwyllys 	    KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
226930a5e8faSwyllys 	i++;
227099ebb4caSwyllys 
227130a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
227230a5e8faSwyllys 	    KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
227330a5e8faSwyllys 	i++;
227430a5e8faSwyllys 
227530a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
227630a5e8faSwyllys 	if (key == NULL) {
227730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
227830a5e8faSwyllys 	} else {
227930a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
228030a5e8faSwyllys 		    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
228130a5e8faSwyllys 		i++;
228230a5e8faSwyllys 	}
228330a5e8faSwyllys 
228430a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
228530a5e8faSwyllys 	if (dirpath != NULL) {
228630a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
228730a5e8faSwyllys 		    KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
228830a5e8faSwyllys 		i++;
228930a5e8faSwyllys 	}
229030a5e8faSwyllys 
229130a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
229230a5e8faSwyllys 	if (keyfile == NULL)
229330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
229430a5e8faSwyllys 	else {
229530a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
229630a5e8faSwyllys 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
229730a5e8faSwyllys 		i++;
229830a5e8faSwyllys 	}
229930a5e8faSwyllys 
230030a5e8faSwyllys 	rv = OpenSSL_FindKey(handle, i, new_attrlist);
230199ebb4caSwyllys 	return (rv);
230299ebb4caSwyllys }
230399ebb4caSwyllys 
230499ebb4caSwyllys KMF_RETURN
230599ebb4caSwyllys /*ARGSUSED*/
230699ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
230799ebb4caSwyllys 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
230899ebb4caSwyllys 	KMF_DATA *output)
230999ebb4caSwyllys {
231099ebb4caSwyllys 	KMF_RETURN		ret = KMF_OK;
231199ebb4caSwyllys 	RSA *rsa = NULL;
231299ebb4caSwyllys 	unsigned int in_len = 0, out_len = 0;
231399ebb4caSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
231499ebb4caSwyllys 	uint8_t *in_data, *out_data;
231599ebb4caSwyllys 	int i, blocks;
231699ebb4caSwyllys 
231799ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
231899ebb4caSwyllys 	    ciphertext == NULL || output == NULL ||
231999ebb4caSwyllys 	    ciphertext->Data == NULL ||
232099ebb4caSwyllys 	    output->Data == NULL)
232199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
232299ebb4caSwyllys 
232399ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
232499ebb4caSwyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
232599ebb4caSwyllys 		modulus_len = RSA_size(rsa);
232699ebb4caSwyllys 	} else {
232799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
232899ebb4caSwyllys 	}
232999ebb4caSwyllys 
233099ebb4caSwyllys 	blocks = ciphertext->Length/modulus_len;
233199ebb4caSwyllys 	out_data = output->Data;
233299ebb4caSwyllys 	in_data = ciphertext->Data;
233399ebb4caSwyllys 	out_len = modulus_len - 11;
233499ebb4caSwyllys 	in_len = modulus_len;
233599ebb4caSwyllys 
233699ebb4caSwyllys 	for (i = 0; i < blocks; i++) {
233799ebb4caSwyllys 		out_len  = RSA_private_decrypt(in_len,
233899ebb4caSwyllys 		    in_data, out_data, rsa, RSA_PKCS1_PADDING);
233999ebb4caSwyllys 
234099ebb4caSwyllys 		if (out_len == 0) {
234199ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
234299ebb4caSwyllys 			goto cleanup;
234399ebb4caSwyllys 		}
234499ebb4caSwyllys 
234599ebb4caSwyllys 		out_data += out_len;
234699ebb4caSwyllys 		total_decrypted += out_len;
234799ebb4caSwyllys 		in_data += in_len;
234899ebb4caSwyllys 	}
234999ebb4caSwyllys 
235099ebb4caSwyllys 	output->Length = total_decrypted;
235199ebb4caSwyllys 
235299ebb4caSwyllys cleanup:
235399ebb4caSwyllys 	RSA_free(rsa);
235499ebb4caSwyllys 	if (ret != KMF_OK)
235599ebb4caSwyllys 		output->Length = 0;
235699ebb4caSwyllys 
235799ebb4caSwyllys 	return (ret);
235899ebb4caSwyllys 
235999ebb4caSwyllys }
236099ebb4caSwyllys 
236199ebb4caSwyllys /*
236299ebb4caSwyllys  *  This function will create a certid from issuer_cert and user_cert.
236399ebb4caSwyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
236499ebb4caSwyllys  *  certid memory after use.
236599ebb4caSwyllys  */
236699ebb4caSwyllys static KMF_RETURN
236799ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
236899ebb4caSwyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
236999ebb4caSwyllys {
237099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
237199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
237299ebb4caSwyllys 	X509   *issuer = NULL;
237399ebb4caSwyllys 	X509   *cert = NULL;
237499ebb4caSwyllys 	unsigned char *ptmp;
237599ebb4caSwyllys 
237699ebb4caSwyllys 	if (issuer_cert == NULL || user_cert == NULL) {
237799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
237899ebb4caSwyllys 	}
237999ebb4caSwyllys 
238099ebb4caSwyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
238199ebb4caSwyllys 	ptmp = issuer_cert->Data;
238299ebb4caSwyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
238399ebb4caSwyllys 	    issuer_cert->Length);
238499ebb4caSwyllys 	if (issuer == NULL) {
238599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
238699ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
238799ebb4caSwyllys 		goto end;
238899ebb4caSwyllys 	}
238999ebb4caSwyllys 
239099ebb4caSwyllys 	/* convert the DER-encoded user cert to an internal X509 */
239199ebb4caSwyllys 	ptmp = user_cert->Data;
239299ebb4caSwyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
239399ebb4caSwyllys 	    user_cert->Length);
239499ebb4caSwyllys 	if (cert == NULL) {
239599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
239699ebb4caSwyllys 
239799ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
239899ebb4caSwyllys 		goto end;
239999ebb4caSwyllys 	}
240099ebb4caSwyllys 
240199ebb4caSwyllys 	/* create a CERTID */
240299ebb4caSwyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
240399ebb4caSwyllys 	if (*certid == NULL) {
240499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
240599ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
240699ebb4caSwyllys 		goto end;
240799ebb4caSwyllys 	}
240899ebb4caSwyllys 
240999ebb4caSwyllys end:
241099ebb4caSwyllys 	if (issuer != NULL) {
241199ebb4caSwyllys 		X509_free(issuer);
241299ebb4caSwyllys 	}
241399ebb4caSwyllys 
241499ebb4caSwyllys 	if (cert != NULL) {
241599ebb4caSwyllys 		X509_free(cert);
241699ebb4caSwyllys 	}
241799ebb4caSwyllys 
241899ebb4caSwyllys 	return (ret);
241999ebb4caSwyllys }
242099ebb4caSwyllys 
242199ebb4caSwyllys KMF_RETURN
242230a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
242330a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
242499ebb4caSwyllys {
242599ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
242699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
242799ebb4caSwyllys 	OCSP_CERTID *id = NULL;
242899ebb4caSwyllys 	OCSP_REQUEST *req = NULL;
242999ebb4caSwyllys 	BIO *derbio = NULL;
243030a5e8faSwyllys 	char *reqfile;
243130a5e8faSwyllys 	KMF_DATA *issuer_cert;
243230a5e8faSwyllys 	KMF_DATA *user_cert;
243399ebb4caSwyllys 
243430a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
243530a5e8faSwyllys 	    attrlist, numattr);
243630a5e8faSwyllys 	if (user_cert == NULL)
243799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
243899ebb4caSwyllys 
243930a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
244030a5e8faSwyllys 	    attrlist, numattr);
244130a5e8faSwyllys 	if (issuer_cert == NULL)
244230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
244330a5e8faSwyllys 
244430a5e8faSwyllys 	reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
244530a5e8faSwyllys 	    attrlist, numattr);
244630a5e8faSwyllys 	if (reqfile == NULL)
244730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
244830a5e8faSwyllys 
244930a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
245099ebb4caSwyllys 	if (ret != KMF_OK) {
245199ebb4caSwyllys 		return (ret);
245299ebb4caSwyllys 	}
245399ebb4caSwyllys 
245499ebb4caSwyllys 	/* Create an OCSP request */
245599ebb4caSwyllys 	req = OCSP_REQUEST_new();
245699ebb4caSwyllys 	if (req == NULL) {
245799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
245899ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
245999ebb4caSwyllys 		goto end;
246099ebb4caSwyllys 	}
246199ebb4caSwyllys 
246299ebb4caSwyllys 	if (!OCSP_request_add0_id(req, id)) {
246399ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
246499ebb4caSwyllys 		goto end;
246599ebb4caSwyllys 	}
246699ebb4caSwyllys 
246799ebb4caSwyllys 	/* Write the request to the output file with DER encoding */
246899ebb4caSwyllys 	derbio = BIO_new_file(reqfile, "wb");
246999ebb4caSwyllys 	if (!derbio) {
247099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
247199ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
247299ebb4caSwyllys 		goto end;
247399ebb4caSwyllys 	}
247499ebb4caSwyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
247599ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
247699ebb4caSwyllys 	}
247799ebb4caSwyllys 
247899ebb4caSwyllys end:
247999ebb4caSwyllys 	/*
2480e65e5c2dSWyllys Ingersoll 	 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2481a2d4930dSDan OpenSolaris Anderson 	 * will also deallocate certid's space.
248299ebb4caSwyllys 	 */
248399ebb4caSwyllys 	if (req != NULL) {
248499ebb4caSwyllys 		OCSP_REQUEST_free(req);
248599ebb4caSwyllys 	}
248699ebb4caSwyllys 
248799ebb4caSwyllys 	if (derbio != NULL) {
248899ebb4caSwyllys 		(void) BIO_free(derbio);
248999ebb4caSwyllys 	}
249099ebb4caSwyllys 
249199ebb4caSwyllys 	return (ret);
249299ebb4caSwyllys }
249399ebb4caSwyllys 
249499ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */
2495*300fdee2SAndy Fiddaman static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_BASICRESP *bs)
249699ebb4caSwyllys {
249799ebb4caSwyllys 	int i;
249899ebb4caSwyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
2499*300fdee2SAndy Fiddaman 	const ASN1_OCTET_STRING *pid;
250099ebb4caSwyllys 
2501*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L
2502*300fdee2SAndy Fiddaman 	OCSP_RESPID *id = bs->tbsResponseData->responderId;
2503*300fdee2SAndy Fiddaman 
250499ebb4caSwyllys 	if (id->type == V_OCSP_RESPID_NAME)
250599ebb4caSwyllys 		return (X509_find_by_subject(certs, id->value.byName));
250699ebb4caSwyllys 
2507*300fdee2SAndy Fiddaman 	pid = id->value.byKey;
2508*300fdee2SAndy Fiddaman #else
2509*300fdee2SAndy Fiddaman 	const X509_NAME *pname;
2510*300fdee2SAndy Fiddaman 
2511*300fdee2SAndy Fiddaman 	if (OCSP_resp_get0_id(bs, &pid, &pname) == 0)
2512*300fdee2SAndy Fiddaman 		return (NULL);
2513*300fdee2SAndy Fiddaman 
2514*300fdee2SAndy Fiddaman 	if (pname != NULL)
2515*300fdee2SAndy Fiddaman 		return (X509_find_by_subject(certs, (X509_NAME *)pname));
2516*300fdee2SAndy Fiddaman #endif
2517*300fdee2SAndy Fiddaman 
251899ebb4caSwyllys 	/* Lookup by key hash */
251999ebb4caSwyllys 
252099ebb4caSwyllys 	/* If key hash isn't SHA1 length then forget it */
2521*300fdee2SAndy Fiddaman 	if (pid->length != SHA_DIGEST_LENGTH)
252299ebb4caSwyllys 		return (NULL);
252399ebb4caSwyllys 
2524*300fdee2SAndy Fiddaman 	keyhash = pid->data;
252599ebb4caSwyllys 	/* Calculate hash of each key and compare */
252699ebb4caSwyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
2527d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
252899ebb4caSwyllys 		X509 *x = sk_X509_value(certs, i);
25295b3e1433Swyllys 		/* Use pubkey_digest to get the key ID value */
253099ebb4caSwyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
253199ebb4caSwyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
253299ebb4caSwyllys 			return (x);
253399ebb4caSwyllys 	}
253499ebb4caSwyllys 	return (NULL);
253599ebb4caSwyllys }
253699ebb4caSwyllys 
253799ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */
2538a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */
253999ebb4caSwyllys static int
254099ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
254199ebb4caSwyllys     X509_STORE *st, unsigned long flags)
254299ebb4caSwyllys {
254399ebb4caSwyllys 	X509 *signer;
2544*300fdee2SAndy Fiddaman 	if ((signer = ocsp_find_signer_sk(certs, bs)))	{
254599ebb4caSwyllys 		*psigner = signer;
254699ebb4caSwyllys 		return (2);
254799ebb4caSwyllys 	}
2548*300fdee2SAndy Fiddaman 
254999ebb4caSwyllys 	if (!(flags & OCSP_NOINTERN) &&
2550*300fdee2SAndy Fiddaman 	    (signer = ocsp_find_signer_sk(
2551*300fdee2SAndy Fiddaman 	    (STACK_OF(X509) *)OCSP_resp_get0_certs(bs), bs))) {
255299ebb4caSwyllys 		*psigner = signer;
255399ebb4caSwyllys 		return (1);
255499ebb4caSwyllys 	}
255599ebb4caSwyllys 	/* Maybe lookup from store if by subject name */
255699ebb4caSwyllys 
255799ebb4caSwyllys 	*psigner = NULL;
255899ebb4caSwyllys 	return (0);
255999ebb4caSwyllys }
256099ebb4caSwyllys 
256199ebb4caSwyllys /*
256299ebb4caSwyllys  * This function will verify the signature of a basic response, using
256399ebb4caSwyllys  * the public key from the OCSP responder certificate.
256499ebb4caSwyllys  */
256599ebb4caSwyllys static KMF_RETURN
256699ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
256799ebb4caSwyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
256899ebb4caSwyllys {
256999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
257099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
257199ebb4caSwyllys 	STACK_OF(X509) *cert_stack = NULL;
257299ebb4caSwyllys 	X509 *signer = NULL;
257399ebb4caSwyllys 	X509 *issuer = NULL;
2574*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L
257599ebb4caSwyllys 	EVP_PKEY *skey = NULL;
2576*300fdee2SAndy Fiddaman #else
2577*300fdee2SAndy Fiddaman 	STACK_OF(X509) *cert_stack2 = NULL;
2578*300fdee2SAndy Fiddaman #endif
257999ebb4caSwyllys 	unsigned char *ptmp;
258099ebb4caSwyllys 
258199ebb4caSwyllys 	if (bs == NULL || issuer_cert == NULL)
258299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
258399ebb4caSwyllys 
258499ebb4caSwyllys 	/*
258599ebb4caSwyllys 	 * Find the certificate that signed the basic response.
258699ebb4caSwyllys 	 *
258799ebb4caSwyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
258899ebb4caSwyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
258999ebb4caSwyllys 	 * If we still do not find a signer, we will look for it from the
259099ebb4caSwyllys 	 * certificate list came with the response file.
259199ebb4caSwyllys 	 */
259299ebb4caSwyllys 	if (signer_cert != NULL) {
259399ebb4caSwyllys 		ptmp = signer_cert->Data;
259499ebb4caSwyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
259599ebb4caSwyllys 		    signer_cert->Length);
259699ebb4caSwyllys 		if (signer == NULL) {
259799ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
259899ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
259999ebb4caSwyllys 			goto end;
260099ebb4caSwyllys 		}
260199ebb4caSwyllys 	} else {
260299ebb4caSwyllys 		/*
260399ebb4caSwyllys 		 * Convert the issuer cert into X509 and push it into a
260499ebb4caSwyllys 		 * stack to be used by ocsp_find_signer().
260599ebb4caSwyllys 		 */
260699ebb4caSwyllys 		ptmp = issuer_cert->Data;
260799ebb4caSwyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
260899ebb4caSwyllys 		    issuer_cert->Length);
260999ebb4caSwyllys 		if (issuer == NULL) {
261099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
261199ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
261299ebb4caSwyllys 			goto end;
261399ebb4caSwyllys 		}
261499ebb4caSwyllys 
261599ebb4caSwyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
261699ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
261799ebb4caSwyllys 			goto end;
261899ebb4caSwyllys 		}
261999ebb4caSwyllys 
262099ebb4caSwyllys 		if (sk_X509_push(cert_stack, issuer) == NULL) {
262199ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
262299ebb4caSwyllys 			goto end;
262399ebb4caSwyllys 		}
262499ebb4caSwyllys 
262599ebb4caSwyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
262699ebb4caSwyllys 		if (!ret) {
262799ebb4caSwyllys 			/* can not find the signer */
262899ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
262999ebb4caSwyllys 			goto end;
263099ebb4caSwyllys 		}
263199ebb4caSwyllys 	}
263299ebb4caSwyllys 
263399ebb4caSwyllys 	/* Verify the signature of the response */
2634*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L
263599ebb4caSwyllys 	skey = X509_get_pubkey(signer);
263699ebb4caSwyllys 	if (skey == NULL) {
263799ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
263899ebb4caSwyllys 		goto end;
263999ebb4caSwyllys 	}
264099ebb4caSwyllys 
264199ebb4caSwyllys 	ret = OCSP_BASICRESP_verify(bs, skey, 0);
2642*300fdee2SAndy Fiddaman #else
2643*300fdee2SAndy Fiddaman 	/*
2644*300fdee2SAndy Fiddaman 	 * Technique based on
2645*300fdee2SAndy Fiddaman 	 * https://mta.openssl.org/pipermail/openssl-users/
2646*300fdee2SAndy Fiddaman 	 *	2017-October/006814.html
2647*300fdee2SAndy Fiddaman 	 */
2648*300fdee2SAndy Fiddaman 	if ((cert_stack2 = sk_X509_new_null()) == NULL) {
2649*300fdee2SAndy Fiddaman 		ret = KMF_ERR_INTERNAL;
2650*300fdee2SAndy Fiddaman 		goto end;
2651*300fdee2SAndy Fiddaman 	}
2652*300fdee2SAndy Fiddaman 
2653*300fdee2SAndy Fiddaman 	if (sk_X509_push(cert_stack2, signer) == NULL) {
2654*300fdee2SAndy Fiddaman 		ret = KMF_ERR_INTERNAL;
2655*300fdee2SAndy Fiddaman 		goto end;
2656*300fdee2SAndy Fiddaman 	}
2657*300fdee2SAndy Fiddaman 
2658*300fdee2SAndy Fiddaman 	ret = OCSP_basic_verify(bs, cert_stack2, NULL, OCSP_NOVERIFY);
2659*300fdee2SAndy Fiddaman #endif
2660*300fdee2SAndy Fiddaman 
266199ebb4caSwyllys 	if (ret == 0) {
266299ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
266399ebb4caSwyllys 		goto end;
266499ebb4caSwyllys 	}
266599ebb4caSwyllys 
266699ebb4caSwyllys end:
266799ebb4caSwyllys 	if (issuer != NULL) {
266899ebb4caSwyllys 		X509_free(issuer);
266999ebb4caSwyllys 	}
267099ebb4caSwyllys 
267199ebb4caSwyllys 	if (signer != NULL) {
267299ebb4caSwyllys 		X509_free(signer);
267399ebb4caSwyllys 	}
267499ebb4caSwyllys 
2675*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L
267699ebb4caSwyllys 	if (skey != NULL) {
267799ebb4caSwyllys 		EVP_PKEY_free(skey);
267899ebb4caSwyllys 	}
2679*300fdee2SAndy Fiddaman #else
2680*300fdee2SAndy Fiddaman 	if (cert_stack2 != NULL) {
2681*300fdee2SAndy Fiddaman 		sk_X509_free(cert_stack2);
2682*300fdee2SAndy Fiddaman 	}
2683*300fdee2SAndy Fiddaman #endif
268499ebb4caSwyllys 
268599ebb4caSwyllys 	if (cert_stack != NULL) {
268699ebb4caSwyllys 		sk_X509_free(cert_stack);
268799ebb4caSwyllys 	}
268899ebb4caSwyllys 
268999ebb4caSwyllys 	return (ret);
269099ebb4caSwyllys }
269199ebb4caSwyllys 
269299ebb4caSwyllys KMF_RETURN
269399ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
269430a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
269599ebb4caSwyllys {
269699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
269799ebb4caSwyllys 	BIO *derbio = NULL;
269899ebb4caSwyllys 	OCSP_RESPONSE *resp = NULL;
269999ebb4caSwyllys 	OCSP_BASICRESP *bs = NULL;
270099ebb4caSwyllys 	OCSP_CERTID *id = NULL;
270199ebb4caSwyllys 	OCSP_SINGLERESP *single = NULL;
270299ebb4caSwyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
270399ebb4caSwyllys 	int index, status, reason;
270430a5e8faSwyllys 	KMF_DATA *issuer_cert;
270530a5e8faSwyllys 	KMF_DATA *user_cert;
270630a5e8faSwyllys 	KMF_DATA *signer_cert;
270730a5e8faSwyllys 	KMF_DATA *response;
270830a5e8faSwyllys 	int *response_reason, *response_status, *cert_status;
270930a5e8faSwyllys 	boolean_t ignore_response_sign = B_FALSE;	/* default is FALSE */
271030a5e8faSwyllys 	uint32_t response_lifetime;
271199ebb4caSwyllys 
271230a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
271330a5e8faSwyllys 	    attrlist, numattr);
271430a5e8faSwyllys 	if (issuer_cert == NULL)
271599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
271699ebb4caSwyllys 
271730a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
271830a5e8faSwyllys 	    attrlist, numattr);
271930a5e8faSwyllys 	if (user_cert == NULL)
272099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
272130a5e8faSwyllys 
272230a5e8faSwyllys 	response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
272330a5e8faSwyllys 	    attrlist, numattr);
272430a5e8faSwyllys 	if (response == NULL)
272530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
272630a5e8faSwyllys 
272730a5e8faSwyllys 	response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
272830a5e8faSwyllys 	    attrlist, numattr);
272930a5e8faSwyllys 	if (response_status == NULL)
273030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
273130a5e8faSwyllys 
273230a5e8faSwyllys 	response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
273330a5e8faSwyllys 	    attrlist, numattr);
273430a5e8faSwyllys 	if (response_reason == NULL)
273530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
273630a5e8faSwyllys 
273730a5e8faSwyllys 	cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
273830a5e8faSwyllys 	    attrlist, numattr);
273930a5e8faSwyllys 	if (cert_status == NULL)
274030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
274199ebb4caSwyllys 
274299ebb4caSwyllys 	/* Read in the response */
274330a5e8faSwyllys 	derbio = BIO_new_mem_buf(response->Data, response->Length);
274499ebb4caSwyllys 	if (!derbio) {
274599ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
274699ebb4caSwyllys 		return (ret);
274799ebb4caSwyllys 	}
274899ebb4caSwyllys 
274999ebb4caSwyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
275099ebb4caSwyllys 	if (resp == NULL) {
275199ebb4caSwyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
275299ebb4caSwyllys 		goto end;
275399ebb4caSwyllys 	}
275499ebb4caSwyllys 
275599ebb4caSwyllys 	/* Check the response status */
275699ebb4caSwyllys 	status = OCSP_response_status(resp);
275730a5e8faSwyllys 	*response_status = status;
275899ebb4caSwyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
275999ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
276099ebb4caSwyllys 		goto end;
276199ebb4caSwyllys 	}
276299ebb4caSwyllys 
276399ebb4caSwyllys #ifdef DEBUG
276499ebb4caSwyllys 	printf("Successfully checked the response file status.\n");
276599ebb4caSwyllys #endif /* DEBUG */
276699ebb4caSwyllys 
276799ebb4caSwyllys 	/* Extract basic response */
276899ebb4caSwyllys 	bs = OCSP_response_get1_basic(resp);
276999ebb4caSwyllys 	if (bs == NULL) {
277099ebb4caSwyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
277199ebb4caSwyllys 		goto end;
277299ebb4caSwyllys 	}
277399ebb4caSwyllys 
277499ebb4caSwyllys #ifdef DEBUG
277599ebb4caSwyllys 	printf("Successfully retrieved the basic response.\n");
277699ebb4caSwyllys #endif /* DEBUG */
277799ebb4caSwyllys 
277899ebb4caSwyllys 	/* Check the basic response signature if required */
277930a5e8faSwyllys 	ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
278030a5e8faSwyllys 	    (void *)&ignore_response_sign, NULL);
278130a5e8faSwyllys 	if (ret != KMF_OK)
278230a5e8faSwyllys 		ret = KMF_OK;
278330a5e8faSwyllys 
278430a5e8faSwyllys 	signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
278530a5e8faSwyllys 	    attrlist, numattr);
278630a5e8faSwyllys 
278730a5e8faSwyllys 	if (ignore_response_sign == B_FALSE) {
278899ebb4caSwyllys 		ret = check_response_signature(handle, bs,
278930a5e8faSwyllys 		    signer_cert, issuer_cert);
279099ebb4caSwyllys 		if (ret != KMF_OK)
279199ebb4caSwyllys 			goto end;
279299ebb4caSwyllys 	}
279399ebb4caSwyllys 
279499ebb4caSwyllys #ifdef DEBUG
279599ebb4caSwyllys 	printf("Successfully verified the response signature.\n");
279699ebb4caSwyllys #endif /* DEBUG */
279799ebb4caSwyllys 
279899ebb4caSwyllys 	/* Create a certid for the certificate in question */
279930a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
280099ebb4caSwyllys 	if (ret != KMF_OK) {
280199ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
280299ebb4caSwyllys 		goto end;
280399ebb4caSwyllys 	}
280499ebb4caSwyllys 
280599ebb4caSwyllys #ifdef DEBUG
280699ebb4caSwyllys 	printf("successfully created a certid for the cert.\n");
280799ebb4caSwyllys #endif /* DEBUG */
280899ebb4caSwyllys 
280999ebb4caSwyllys 	/* Find the index of the single response for the certid */
281099ebb4caSwyllys 	index = OCSP_resp_find(bs, id, -1);
281199ebb4caSwyllys 	if (index < 0) {
281299ebb4caSwyllys 		/* cound not find this certificate in the response */
281399ebb4caSwyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
281499ebb4caSwyllys 		goto end;
281599ebb4caSwyllys 	}
281699ebb4caSwyllys 
281799ebb4caSwyllys #ifdef DEBUG
281899ebb4caSwyllys 	printf("Successfully found the single response index for the cert.\n");
281999ebb4caSwyllys #endif /* DEBUG */
282099ebb4caSwyllys 
282199ebb4caSwyllys 	/* Retrieve the single response and get the cert status */
282299ebb4caSwyllys 	single = OCSP_resp_get0(bs, index);
282399ebb4caSwyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
282499ebb4caSwyllys 	    &nextupd);
282599ebb4caSwyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
282630a5e8faSwyllys 		*cert_status = OCSP_GOOD;
282799ebb4caSwyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
282830a5e8faSwyllys 		*cert_status = OCSP_UNKNOWN;
282999ebb4caSwyllys 	} else { /* revoked */
283030a5e8faSwyllys 		*cert_status = OCSP_REVOKED;
283130a5e8faSwyllys 		*response_reason = reason;
283299ebb4caSwyllys 	}
283399ebb4caSwyllys 	ret = KMF_OK;
283499ebb4caSwyllys 
283530a5e8faSwyllys 	/* resp. time is optional, so we don't care about the return code. */
283630a5e8faSwyllys 	(void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
283730a5e8faSwyllys 	    (void *)&response_lifetime, NULL);
283830a5e8faSwyllys 
283999ebb4caSwyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
284030a5e8faSwyllys 	    response_lifetime)) {
284199ebb4caSwyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
284299ebb4caSwyllys 		goto end;
284399ebb4caSwyllys 	}
284499ebb4caSwyllys 
284599ebb4caSwyllys #ifdef DEBUG
284699ebb4caSwyllys 	printf("Successfully verify the time.\n");
284799ebb4caSwyllys #endif /* DEBUG */
284899ebb4caSwyllys 
284999ebb4caSwyllys end:
285099ebb4caSwyllys 	if (derbio != NULL)
285199ebb4caSwyllys 		(void) BIO_free(derbio);
285299ebb4caSwyllys 
285399ebb4caSwyllys 	if (resp != NULL)
285499ebb4caSwyllys 		OCSP_RESPONSE_free(resp);
285599ebb4caSwyllys 
285699ebb4caSwyllys 	if (bs != NULL)
285799ebb4caSwyllys 		OCSP_BASICRESP_free(bs);
285899ebb4caSwyllys 
285999ebb4caSwyllys 	if (id != NULL)
286099ebb4caSwyllys 		OCSP_CERTID_free(id);
286199ebb4caSwyllys 
286299ebb4caSwyllys 	return (ret);
286399ebb4caSwyllys }
286499ebb4caSwyllys 
286599ebb4caSwyllys static KMF_RETURN
286699ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path,
286799ebb4caSwyllys 	KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
286899ebb4caSwyllys {
286999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
287030a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
287199ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
287299ebb4caSwyllys 
287399ebb4caSwyllys 	if (keyclass == KMF_ASYM_PRI ||
287499ebb4caSwyllys 	    keyclass == KMF_ASYM_PUB) {
287599ebb4caSwyllys 		pkey = openssl_load_key(handle, path);
287699ebb4caSwyllys 		if (pkey == NULL) {
287799ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
287899ebb4caSwyllys 		}
287999ebb4caSwyllys 		if (key != NULL) {
2880*300fdee2SAndy Fiddaman 			if (EVP_PKEY_get0_RSA(pkey) != NULL)
288199ebb4caSwyllys 				key->keyalg = KMF_RSA;
2882*300fdee2SAndy Fiddaman 			else if (EVP_PKEY_get0_DSA(pkey) != NULL)
288399ebb4caSwyllys 				key->keyalg = KMF_DSA;
288499ebb4caSwyllys 
288599ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
288699ebb4caSwyllys 			key->keyclass = keyclass;
288799ebb4caSwyllys 			key->keyp = (void *)pkey;
288899ebb4caSwyllys 			key->israw = FALSE;
28895b3e1433Swyllys 			if (path != NULL &&
28905b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
28915b3e1433Swyllys 				EVP_PKEY_free(pkey);
28925b3e1433Swyllys 				return (KMF_ERR_MEMORY);
28935b3e1433Swyllys 			}
289499ebb4caSwyllys 		} else {
289599ebb4caSwyllys 			EVP_PKEY_free(pkey);
289699ebb4caSwyllys 			pkey = NULL;
289799ebb4caSwyllys 		}
289899ebb4caSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
289999ebb4caSwyllys 		KMF_ENCODE_FORMAT fmt;
290099ebb4caSwyllys 		/*
290199ebb4caSwyllys 		 * If the file is a recognized format,
290299ebb4caSwyllys 		 * then it is NOT a symmetric key.
290399ebb4caSwyllys 		 */
290430a5e8faSwyllys 		rv = kmf_get_file_format(path, &fmt);
290599ebb4caSwyllys 		if (rv == KMF_OK || fmt != 0) {
290699ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
290799ebb4caSwyllys 		} else if (rv == KMF_ERR_ENCODING) {
290899ebb4caSwyllys 			/*
290999ebb4caSwyllys 			 * If we don't know the encoding,
291099ebb4caSwyllys 			 * it is probably  a symmetric key.
291199ebb4caSwyllys 			 */
291299ebb4caSwyllys 			rv = KMF_OK;
291330a5e8faSwyllys 		} else if (rv == KMF_ERR_OPEN_FILE) {
291430a5e8faSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
291599ebb4caSwyllys 		}
291699ebb4caSwyllys 
291799ebb4caSwyllys 		if (key != NULL) {
291899ebb4caSwyllys 			KMF_DATA keyvalue;
291999ebb4caSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
292099ebb4caSwyllys 			if (rkey == NULL) {
292199ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
292299ebb4caSwyllys 				goto out;
292399ebb4caSwyllys 			}
292499ebb4caSwyllys 
292599ebb4caSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
292630a5e8faSwyllys 			rv = kmf_read_input_file(handle, path, &keyvalue);
292799ebb4caSwyllys 			if (rv != KMF_OK)
292899ebb4caSwyllys 				goto out;
292999ebb4caSwyllys 
293099ebb4caSwyllys 			rkey->keydata.len = keyvalue.Length;
293199ebb4caSwyllys 			rkey->keydata.val = keyvalue.Data;
293299ebb4caSwyllys 
293399ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
293499ebb4caSwyllys 			key->keyclass = keyclass;
293599ebb4caSwyllys 			key->israw = TRUE;
293699ebb4caSwyllys 			key->keyp = (void *)rkey;
29375b3e1433Swyllys 			if (path != NULL &&
29385b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
29395b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
29405b3e1433Swyllys 			}
294199ebb4caSwyllys 		}
294299ebb4caSwyllys 	}
294399ebb4caSwyllys out:
294499ebb4caSwyllys 	if (rv != KMF_OK) {
294599ebb4caSwyllys 		if (rkey != NULL) {
294630a5e8faSwyllys 			kmf_free_raw_sym_key(rkey);
294799ebb4caSwyllys 		}
294899ebb4caSwyllys 		if (pkey != NULL)
294999ebb4caSwyllys 			EVP_PKEY_free(pkey);
295099ebb4caSwyllys 
295199ebb4caSwyllys 		if (key != NULL) {
295299ebb4caSwyllys 			key->keyalg = KMF_KEYALG_NONE;
295399ebb4caSwyllys 			key->keyclass = KMF_KEYCLASS_NONE;
295499ebb4caSwyllys 			key->keyp = NULL;
295599ebb4caSwyllys 		}
295699ebb4caSwyllys 	}
295799ebb4caSwyllys 
295899ebb4caSwyllys 	return (rv);
295999ebb4caSwyllys }
296099ebb4caSwyllys 
296199ebb4caSwyllys KMF_RETURN
296230a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle,
296330a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
296499ebb4caSwyllys {
296599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
296699ebb4caSwyllys 	char *fullpath = NULL;
2967f482c776Swyllys 	uint32_t maxkeys;
296830a5e8faSwyllys 	KMF_KEY_HANDLE *key;
296930a5e8faSwyllys 	uint32_t *numkeys;
297030a5e8faSwyllys 	KMF_KEY_CLASS keyclass;
297130a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
297230a5e8faSwyllys 	char *dirpath;
297330a5e8faSwyllys 	char *keyfile;
297499ebb4caSwyllys 
297530a5e8faSwyllys 	if (handle == NULL)
297699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
297799ebb4caSwyllys 
297830a5e8faSwyllys 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
297930a5e8faSwyllys 	if (numkeys == NULL)
298030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
298130a5e8faSwyllys 
298230a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
298330a5e8faSwyllys 	    (void *)&keyclass, NULL);
298430a5e8faSwyllys 	if (rv != KMF_OK)
298530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
298630a5e8faSwyllys 
298730a5e8faSwyllys 	if (keyclass != KMF_ASYM_PUB &&
298830a5e8faSwyllys 	    keyclass != KMF_ASYM_PRI &&
298930a5e8faSwyllys 	    keyclass != KMF_SYMMETRIC)
299099ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
299199ebb4caSwyllys 
299230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
299330a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
299430a5e8faSwyllys 
299530a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
299699ebb4caSwyllys 
299799ebb4caSwyllys 	if (fullpath == NULL)
299899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
299999ebb4caSwyllys 
3000f482c776Swyllys 	maxkeys = *numkeys;
3001f482c776Swyllys 	if (maxkeys == 0)
3002f482c776Swyllys 		maxkeys = 0xFFFFFFFF;
300399ebb4caSwyllys 	*numkeys = 0;
300499ebb4caSwyllys 
300530a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
300630a5e8faSwyllys 	/* it is okay to have "keys" contains NULL */
300730a5e8faSwyllys 
300830a5e8faSwyllys 	/*
300930a5e8faSwyllys 	 * The caller may want a list of the raw key data as well.
301030a5e8faSwyllys 	 * Useful for importing keys from a file into other keystores.
301130a5e8faSwyllys 	 */
301230a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
301330a5e8faSwyllys 
301499ebb4caSwyllys 	if (isdir(fullpath)) {
301599ebb4caSwyllys 		DIR *dirp;
301699ebb4caSwyllys 		struct dirent *dp;
301799ebb4caSwyllys 		int n = 0;
301899ebb4caSwyllys 
301999ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
302099ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
302199ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
302299ebb4caSwyllys 		}
302399ebb4caSwyllys 		rewinddir(dirp);
3024f482c776Swyllys 		while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
302599ebb4caSwyllys 			if (strcmp(dp->d_name, ".") &&
302699ebb4caSwyllys 			    strcmp(dp->d_name, "..")) {
302799ebb4caSwyllys 				char *fname;
302899ebb4caSwyllys 
302999ebb4caSwyllys 				fname = get_fullpath(fullpath,
303099ebb4caSwyllys 				    (char *)&dp->d_name);
303199ebb4caSwyllys 
303299ebb4caSwyllys 				rv = fetch_key(handle, fname,
303330a5e8faSwyllys 				    keyclass, key ? &key[n] : NULL);
303499ebb4caSwyllys 
303530a5e8faSwyllys 				if (rv == KMF_OK) {
303630a5e8faSwyllys 					if (key != NULL && rawkey != NULL)
303730a5e8faSwyllys 						rv = convertToRawKey(
303830a5e8faSwyllys 						    key[n].keyp, &rawkey[n]);
303999ebb4caSwyllys 					n++;
304030a5e8faSwyllys 				}
304199ebb4caSwyllys 
304299ebb4caSwyllys 				if (rv != KMF_OK || key == NULL)
304399ebb4caSwyllys 					free(fname);
304499ebb4caSwyllys 			}
304599ebb4caSwyllys 		}
304699ebb4caSwyllys 		(void) closedir(dirp);
304799ebb4caSwyllys 		free(fullpath);
304899ebb4caSwyllys 		(*numkeys) = n;
304999ebb4caSwyllys 	} else {
305030a5e8faSwyllys 		rv = fetch_key(handle, fullpath, keyclass, key);
305199ebb4caSwyllys 		if (rv == KMF_OK)
305299ebb4caSwyllys 			(*numkeys) = 1;
305399ebb4caSwyllys 
305499ebb4caSwyllys 		if (rv != KMF_OK || key == NULL)
305599ebb4caSwyllys 			free(fullpath);
305630a5e8faSwyllys 
305730a5e8faSwyllys 		if (rv == KMF_OK && key != NULL && rawkey != NULL) {
305830a5e8faSwyllys 			rv = convertToRawKey(key->keyp, rawkey);
305930a5e8faSwyllys 		}
306099ebb4caSwyllys 	}
306199ebb4caSwyllys 
3062f482c776Swyllys 	if (rv == KMF_OK && (*numkeys) == 0)
306399ebb4caSwyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
306473cc0e02Swyllys 	else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
306573cc0e02Swyllys 		rv = KMF_OK;
306699ebb4caSwyllys 
306799ebb4caSwyllys 	return (rv);
306899ebb4caSwyllys }
306999ebb4caSwyllys 
307099ebb4caSwyllys #define	HANDLE_PK12_ERROR { \
307199ebb4caSwyllys 	SET_ERROR(kmfh, ERR_get_error()); \
307299ebb4caSwyllys 	rv = KMF_ERR_ENCODING; \
307399ebb4caSwyllys 	goto out; \
307499ebb4caSwyllys }
307599ebb4caSwyllys 
30765b3e1433Swyllys static int
30775b3e1433Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
307899ebb4caSwyllys {
3079*300fdee2SAndy Fiddaman 	unsigned char *alias;
3080*300fdee2SAndy Fiddaman 	int len;
3081*300fdee2SAndy Fiddaman 
3082*300fdee2SAndy Fiddaman 	if (xcert != NULL && (alias = X509_alias_get0(xcert, &len)) != NULL) {
30835b3e1433Swyllys 		if (PKCS12_add_friendlyname_asc(bag,
3084*300fdee2SAndy Fiddaman 		    (const char *)alias, len) == 0)
30855b3e1433Swyllys 			return (0);
30865b3e1433Swyllys 	}
30875b3e1433Swyllys 	return (1);
30885b3e1433Swyllys }
30895b3e1433Swyllys 
30905b3e1433Swyllys static PKCS7 *
30915b3e1433Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
30925b3e1433Swyllys 	uchar_t *keyid, unsigned int keyidlen)
30935b3e1433Swyllys {
309499ebb4caSwyllys 	PKCS12_SAFEBAG *bag = NULL;
309599ebb4caSwyllys 	PKCS7 *cert_authsafe = NULL;
30965b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack;
309799ebb4caSwyllys 
309899ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
309999ebb4caSwyllys 	if (bag_stack == NULL)
31005b3e1433Swyllys 		return (NULL);
310199ebb4caSwyllys 
310299ebb4caSwyllys 	/* Convert cert from X509 struct to PKCS#12 bag */
3103*300fdee2SAndy Fiddaman 	bag = PKCS12_SAFEBAG_create_cert(sslcert);
310499ebb4caSwyllys 	if (bag == NULL) {
31055b3e1433Swyllys 		goto out;
310699ebb4caSwyllys 	}
310799ebb4caSwyllys 
310899ebb4caSwyllys 	/* Add the key id to the certificate bag. */
31095b3e1433Swyllys 	if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
31105b3e1433Swyllys 		goto out;
311199ebb4caSwyllys 	}
311299ebb4caSwyllys 
31135b3e1433Swyllys 	if (!add_alias_to_bag(bag, sslcert))
31145b3e1433Swyllys 		goto out;
31155b3e1433Swyllys 
311699ebb4caSwyllys 	/* Pile it on the bag_stack. */
311799ebb4caSwyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
31185b3e1433Swyllys 		goto out;
311999ebb4caSwyllys 	}
312099ebb4caSwyllys 	/* Turn bag_stack of certs into encrypted authsafe. */
312199ebb4caSwyllys 	cert_authsafe = PKCS12_pack_p7encdata(
312299ebb4caSwyllys 	    NID_pbe_WithSHA1And40BitRC2_CBC,
312334acef67Swyllys 	    cred->cred, cred->credlen, NULL, 0,
312434acef67Swyllys 	    PKCS12_DEFAULT_ITER, bag_stack);
312599ebb4caSwyllys 
31265b3e1433Swyllys out:
31275b3e1433Swyllys 	if (bag_stack != NULL)
312899ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
312999ebb4caSwyllys 
31305b3e1433Swyllys 	return (cert_authsafe);
313199ebb4caSwyllys }
31325b3e1433Swyllys 
31335b3e1433Swyllys static PKCS7 *
31345b3e1433Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
31355b3e1433Swyllys 	uchar_t *keyid,  unsigned int keyidlen,
31365b3e1433Swyllys 	char *label, int label_len)
31375b3e1433Swyllys {
31385b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
31395b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
31405b3e1433Swyllys 	PKCS12_SAFEBAG *bag = NULL;
31415b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
31425b3e1433Swyllys 
314399ebb4caSwyllys 	p8 = EVP_PKEY2PKCS8(pkey);
314499ebb4caSwyllys 	if (p8 == NULL) {
31455b3e1433Swyllys 		return (NULL);
314699ebb4caSwyllys 	}
314799ebb4caSwyllys 	/* Put the shrouded key into a PKCS#12 bag. */
3148*300fdee2SAndy Fiddaman 	bag = PKCS12_SAFEBAG_create_pkcs8_encrypt(
314999ebb4caSwyllys 	    NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
315099ebb4caSwyllys 	    cred->cred, cred->credlen,
315199ebb4caSwyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, p8);
315299ebb4caSwyllys 
315399ebb4caSwyllys 	/* Clean up the PKCS#8 shrouded key, don't need it now. */
315499ebb4caSwyllys 	PKCS8_PRIV_KEY_INFO_free(p8);
315599ebb4caSwyllys 	p8 = NULL;
315699ebb4caSwyllys 
315799ebb4caSwyllys 	if (bag == NULL) {
31585b3e1433Swyllys 		return (NULL);
315999ebb4caSwyllys 	}
31605b3e1433Swyllys 	if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
31615b3e1433Swyllys 		goto out;
31625b3e1433Swyllys 	if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
31635b3e1433Swyllys 		goto out;
31645b3e1433Swyllys 
316599ebb4caSwyllys 	/* Start a PKCS#12 safebag container for the private key. */
316699ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
31675b3e1433Swyllys 	if (bag_stack == NULL)
31685b3e1433Swyllys 		goto out;
316999ebb4caSwyllys 
317099ebb4caSwyllys 	/* Pile on the private key on the bag_stack. */
31715b3e1433Swyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
31725b3e1433Swyllys 		goto out;
31735b3e1433Swyllys 
317499ebb4caSwyllys 	key_authsafe = PKCS12_pack_p7data(bag_stack);
317599ebb4caSwyllys 
31765b3e1433Swyllys out:
31775b3e1433Swyllys 	if (bag_stack != NULL)
317899ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
317999ebb4caSwyllys 	bag_stack = NULL;
31805b3e1433Swyllys 	return (key_authsafe);
318199ebb4caSwyllys }
318299ebb4caSwyllys 
318399ebb4caSwyllys static EVP_PKEY *
318499ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
318599ebb4caSwyllys {
318699ebb4caSwyllys 	RSA		*rsa = NULL;
318799ebb4caSwyllys 	EVP_PKEY	*newkey = NULL;
3188*300fdee2SAndy Fiddaman 	BIGNUM		*n = NULL, *e = NULL, *d = NULL,
3189*300fdee2SAndy Fiddaman 			*p = NULL, *q = NULL,
3190*300fdee2SAndy Fiddaman 			*dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
319199ebb4caSwyllys 
319299ebb4caSwyllys 	if ((rsa = RSA_new()) == NULL)
3193*300fdee2SAndy Fiddaman 		goto cleanup;
319499ebb4caSwyllys 
3195*300fdee2SAndy Fiddaman 	if ((n = BN_bin2bn(key->mod.val, key->mod.len, NULL)) == NULL)
3196*300fdee2SAndy Fiddaman 		goto cleanup;
319799ebb4caSwyllys 
3198*300fdee2SAndy Fiddaman 	if ((e = BN_bin2bn(key->pubexp.val, key->pubexp.len, NULL)) == NULL)
3199*300fdee2SAndy Fiddaman 		goto cleanup;
320099ebb4caSwyllys 
3201*300fdee2SAndy Fiddaman 	if (key->priexp.val != NULL &&
3202*300fdee2SAndy Fiddaman 	    (d = BN_bin2bn(key->priexp.val, key->priexp.len, NULL)) == NULL)
3203*300fdee2SAndy Fiddaman 		goto cleanup;
320499ebb4caSwyllys 
3205*300fdee2SAndy Fiddaman 	if (key->prime1.val != NULL &&
3206*300fdee2SAndy Fiddaman 	    (p = BN_bin2bn(key->prime1.val, key->prime1.len, NULL)) == NULL)
3207*300fdee2SAndy Fiddaman 		goto cleanup;
320899ebb4caSwyllys 
3209*300fdee2SAndy Fiddaman 	if (key->prime2.val != NULL &&
3210*300fdee2SAndy Fiddaman 	    (q = BN_bin2bn(key->prime2.val, key->prime2.len, NULL)) == NULL)
3211*300fdee2SAndy Fiddaman 		goto cleanup;
321299ebb4caSwyllys 
3213*300fdee2SAndy Fiddaman 	if (key->exp1.val != NULL &&
3214*300fdee2SAndy Fiddaman 	    (dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len, NULL)) == NULL)
3215*300fdee2SAndy Fiddaman 		goto cleanup;
321699ebb4caSwyllys 
3217*300fdee2SAndy Fiddaman 	if (key->exp2.val != NULL &&
3218*300fdee2SAndy Fiddaman 	    (dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len, NULL)) == NULL)
3219*300fdee2SAndy Fiddaman 		goto cleanup;
322099ebb4caSwyllys 
3221*300fdee2SAndy Fiddaman 	if (key->coef.val != NULL &&
3222*300fdee2SAndy Fiddaman 	    (iqmp = BN_bin2bn(key->coef.val, key->coef.len, NULL)) == NULL)
3223*300fdee2SAndy Fiddaman 		goto cleanup;
3224*300fdee2SAndy Fiddaman 
3225*300fdee2SAndy Fiddaman 	if (RSA_set0_key(rsa, n, e, d) == 0)
3226*300fdee2SAndy Fiddaman 		goto cleanup;
3227*300fdee2SAndy Fiddaman 	n = e = d = NULL;
3228*300fdee2SAndy Fiddaman 	if (RSA_set0_factors(rsa, p, q) == 0)
3229*300fdee2SAndy Fiddaman 		goto cleanup;
3230*300fdee2SAndy Fiddaman 	p = q = NULL;
3231*300fdee2SAndy Fiddaman 	if (RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp) == 0)
3232*300fdee2SAndy Fiddaman 		goto cleanup;
3233*300fdee2SAndy Fiddaman 	dmp1 = dmq1 = iqmp = NULL;
323499ebb4caSwyllys 
323599ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
3236*300fdee2SAndy Fiddaman 		goto cleanup;
323799ebb4caSwyllys 
323899ebb4caSwyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
323999ebb4caSwyllys 
3240*300fdee2SAndy Fiddaman cleanup:
324199ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
3242*300fdee2SAndy Fiddaman 	if (rsa)
324399ebb4caSwyllys 		RSA_free(rsa);
3244*300fdee2SAndy Fiddaman 	BN_free(n);
3245*300fdee2SAndy Fiddaman 	BN_free(e);
3246*300fdee2SAndy Fiddaman 	BN_free(d);
3247*300fdee2SAndy Fiddaman 	BN_free(p);
3248*300fdee2SAndy Fiddaman 	BN_free(q);
3249*300fdee2SAndy Fiddaman 	BN_free(dmp1);
3250*300fdee2SAndy Fiddaman 	BN_free(dmq1);
3251*300fdee2SAndy Fiddaman 	BN_free(iqmp);
325299ebb4caSwyllys 
325399ebb4caSwyllys 	return (newkey);
325499ebb4caSwyllys }
325599ebb4caSwyllys 
325699ebb4caSwyllys static EVP_PKEY *
325799ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
325899ebb4caSwyllys {
325999ebb4caSwyllys 	DSA		*dsa = NULL;
326099ebb4caSwyllys 	EVP_PKEY	*newkey = NULL;
3261*300fdee2SAndy Fiddaman 	BIGNUM		*p = NULL, *q = NULL, *g = NULL,
3262*300fdee2SAndy Fiddaman 			*priv_key = NULL, *pub_key = NULL;
326399ebb4caSwyllys 
326499ebb4caSwyllys 	if ((dsa = DSA_new()) == NULL)
3265*300fdee2SAndy Fiddaman 		goto cleanup;
326699ebb4caSwyllys 
3267*300fdee2SAndy Fiddaman 	if ((p = BN_bin2bn(key->prime.val, key->prime.len, NULL)) == NULL)
3268*300fdee2SAndy Fiddaman 		goto cleanup;
326999ebb4caSwyllys 
3270*300fdee2SAndy Fiddaman 	if ((q = BN_bin2bn(key->subprime.val, key->subprime.len, NULL)) == NULL)
3271*300fdee2SAndy Fiddaman 		goto cleanup;
327299ebb4caSwyllys 
3273*300fdee2SAndy Fiddaman 	if ((g = BN_bin2bn(key->base.val, key->base.len, NULL)) == NULL)
3274*300fdee2SAndy Fiddaman 		goto cleanup;
327599ebb4caSwyllys 
3276*300fdee2SAndy Fiddaman 	if ((priv_key = BN_bin2bn(key->value.val, key->value.len,
3277*300fdee2SAndy Fiddaman 	    NULL)) == NULL)
3278*300fdee2SAndy Fiddaman 		goto cleanup;
327999ebb4caSwyllys 
3280*300fdee2SAndy Fiddaman 	if (key->pubvalue.val != NULL && (pub_key =
3281*300fdee2SAndy Fiddaman 	    BN_bin2bn(key->pubvalue.val, key->pubvalue.len, NULL)) == NULL)
3282*300fdee2SAndy Fiddaman 		goto cleanup;
3283*300fdee2SAndy Fiddaman 
3284*300fdee2SAndy Fiddaman 	if (DSA_set0_pqg(dsa, p, q, g) == 0)
3285*300fdee2SAndy Fiddaman 		goto cleanup;
3286*300fdee2SAndy Fiddaman 	p = q = g = NULL;
3287*300fdee2SAndy Fiddaman 	if (DSA_set0_key(dsa, pub_key, priv_key) == 0)
3288*300fdee2SAndy Fiddaman 		goto cleanup;
3289*300fdee2SAndy Fiddaman 	pub_key = priv_key = 0;
329030a5e8faSwyllys 
329199ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
3292*300fdee2SAndy Fiddaman 		goto cleanup;
329399ebb4caSwyllys 
329499ebb4caSwyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
329599ebb4caSwyllys 
3296*300fdee2SAndy Fiddaman cleanup:
329799ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
3298*300fdee2SAndy Fiddaman 	if (dsa)
329999ebb4caSwyllys 		DSA_free(dsa);
3300*300fdee2SAndy Fiddaman 	BN_free(p);
3301*300fdee2SAndy Fiddaman 	BN_free(q);
3302*300fdee2SAndy Fiddaman 	BN_free(g);
3303*300fdee2SAndy Fiddaman 	BN_free(priv_key);
3304*300fdee2SAndy Fiddaman 	BN_free(pub_key);
3305*300fdee2SAndy Fiddaman 
330699ebb4caSwyllys 	return (newkey);
330799ebb4caSwyllys }
330899ebb4caSwyllys 
33095b3e1433Swyllys static EVP_PKEY *
33105b3e1433Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key)
33115b3e1433Swyllys {
33125b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
33135b3e1433Swyllys 	KMF_RAW_KEY_DATA *rawkey;
33145b3e1433Swyllys 	ASN1_TYPE *attr = NULL;
33155b3e1433Swyllys 	KMF_RETURN ret;
33165b3e1433Swyllys 
33175b3e1433Swyllys 	if (key == NULL || !key->israw)
33185b3e1433Swyllys 		return (NULL);
33195b3e1433Swyllys 
33205b3e1433Swyllys 	rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
33215b3e1433Swyllys 	if (rawkey->keytype == KMF_RSA) {
33225b3e1433Swyllys 		pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
33235b3e1433Swyllys 	} else if (rawkey->keytype == KMF_DSA) {
33245b3e1433Swyllys 		pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
3325e65e5c2dSWyllys Ingersoll 	} else if (rawkey->keytype == KMF_ECDSA) {
3326e65e5c2dSWyllys Ingersoll 		/*
3327e65e5c2dSWyllys Ingersoll 		 * OpenSSL in Solaris does not support EC for
3328e65e5c2dSWyllys Ingersoll 		 * legal reasons
3329e65e5c2dSWyllys Ingersoll 		 */
3330e65e5c2dSWyllys Ingersoll 		return (NULL);
33315b3e1433Swyllys 	} else {
33325b3e1433Swyllys 		/* wrong kind of key */
33335b3e1433Swyllys 		return (NULL);
33345b3e1433Swyllys 	}
33355b3e1433Swyllys 
33365b3e1433Swyllys 	if (rawkey->label != NULL) {
33375b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
33385b3e1433Swyllys 			EVP_PKEY_free(pkey);
33395b3e1433Swyllys 			return (NULL);
33405b3e1433Swyllys 		}
33415b3e1433Swyllys 		attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
33425b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
33435b3e1433Swyllys 		    strlen(rawkey->label));
33445b3e1433Swyllys 		attr->type = V_ASN1_BMPSTRING;
33455b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.bmpstring;
33465b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
33475b3e1433Swyllys 		if (ret != KMF_OK) {
33485b3e1433Swyllys 			EVP_PKEY_free(pkey);
33495b3e1433Swyllys 			ASN1_TYPE_free(attr);
33505b3e1433Swyllys 			return (NULL);
33515b3e1433Swyllys 		}
33525b3e1433Swyllys 	}
33535b3e1433Swyllys 	if (rawkey->id.Data != NULL) {
33545b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
33555b3e1433Swyllys 			EVP_PKEY_free(pkey);
33565b3e1433Swyllys 			return (NULL);
33575b3e1433Swyllys 		}
33585b3e1433Swyllys 		attr->value.octet_string =
33595b3e1433Swyllys 		    ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
33605b3e1433Swyllys 		attr->type = V_ASN1_OCTET_STRING;
33615b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.octet_string,
33625b3e1433Swyllys 		    rawkey->id.Data, rawkey->id.Length);
33635b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.octet_string;
33645b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
33655b3e1433Swyllys 		if (ret != KMF_OK) {
33665b3e1433Swyllys 			EVP_PKEY_free(pkey);
33675b3e1433Swyllys 			ASN1_TYPE_free(attr);
33685b3e1433Swyllys 			return (NULL);
33695b3e1433Swyllys 		}
33705b3e1433Swyllys 	}
33715b3e1433Swyllys 	return (pkey);
33725b3e1433Swyllys }
33735b3e1433Swyllys 
33745b3e1433Swyllys /*
33755b3e1433Swyllys  * Search a list of private keys to find one that goes with the certificate.
33765b3e1433Swyllys  */
33775b3e1433Swyllys static EVP_PKEY *
33785b3e1433Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
33795b3e1433Swyllys {
33805b3e1433Swyllys 	int i;
33815b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
33825b3e1433Swyllys 
33835b3e1433Swyllys 	if (numkeys == 0 || keylist == NULL || xcert == NULL)
33845b3e1433Swyllys 		return (NULL);
33855b3e1433Swyllys 	for (i = 0; i < numkeys; i++) {
33865b3e1433Swyllys 		if (keylist[i].israw)
33875b3e1433Swyllys 			pkey = raw_key_to_pkey(&keylist[i]);
33885b3e1433Swyllys 		else
33895b3e1433Swyllys 			pkey = (EVP_PKEY *)keylist[i].keyp;
33905b3e1433Swyllys 		if (pkey != NULL) {
33915b3e1433Swyllys 			if (X509_check_private_key(xcert, pkey)) {
33925b3e1433Swyllys 				return (pkey);
33935b3e1433Swyllys 			} else {
33945b3e1433Swyllys 				EVP_PKEY_free(pkey);
33955b3e1433Swyllys 				pkey = NULL;
33965b3e1433Swyllys 			}
33975b3e1433Swyllys 		}
33985b3e1433Swyllys 	}
33995b3e1433Swyllys 	return (pkey);
34005b3e1433Swyllys }
34015b3e1433Swyllys 
340299ebb4caSwyllys static KMF_RETURN
34035b3e1433Swyllys local_export_pk12(KMF_HANDLE_T handle,
340499ebb4caSwyllys 	KMF_CREDENTIAL *cred,
340599ebb4caSwyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
340699ebb4caSwyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
340799ebb4caSwyllys 	char *filename)
340899ebb4caSwyllys {
340999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
341099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
341199ebb4caSwyllys 	BIO *bio = NULL;
34125b3e1433Swyllys 	PKCS7 *cert_authsafe = NULL;
34135b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
34145b3e1433Swyllys 	STACK_OF(PKCS7) *authsafe_stack = NULL;
34155b3e1433Swyllys 	PKCS12 *p12_elem = NULL;
341699ebb4caSwyllys 	int i;
341799ebb4caSwyllys 
34185b3e1433Swyllys 	if (numcerts == 0 && numkeys == 0)
34195b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
34205b3e1433Swyllys 
342199ebb4caSwyllys 	/*
342299ebb4caSwyllys 	 * Open the output file.
342399ebb4caSwyllys 	 */
342499ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
342599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
342699ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
342799ebb4caSwyllys 		goto cleanup;
342899ebb4caSwyllys 	}
342999ebb4caSwyllys 
34305b3e1433Swyllys 	/* Start a PKCS#7 stack. */
34315b3e1433Swyllys 	authsafe_stack = sk_PKCS7_new_null();
34325b3e1433Swyllys 	if (authsafe_stack == NULL) {
34335b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
34345b3e1433Swyllys 		goto cleanup;
34355b3e1433Swyllys 	}
34365b3e1433Swyllys 	if (numcerts > 0) {
343799ebb4caSwyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
343899ebb4caSwyllys 			const uchar_t *p = certlist[i].certificate.Data;
343999ebb4caSwyllys 			long len = certlist[i].certificate.Length;
34405b3e1433Swyllys 			X509 *xcert = NULL;
34415b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
34425b3e1433Swyllys 			unsigned char keyid[EVP_MAX_MD_SIZE];
34435b3e1433Swyllys 			unsigned int keyidlen = 0;
344499ebb4caSwyllys 
344599ebb4caSwyllys 			xcert = d2i_X509(NULL, &p, len);
344699ebb4caSwyllys 			if (xcert == NULL) {
344799ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
344899ebb4caSwyllys 				rv = KMF_ERR_ENCODING;
344999ebb4caSwyllys 			}
34505b3e1433Swyllys 			if (certlist[i].kmf_private.label != NULL) {
34515b3e1433Swyllys 				/* Set alias attribute */
34525b3e1433Swyllys 				(void) X509_alias_set1(xcert,
34535b3e1433Swyllys 				    (uchar_t *)certlist[i].kmf_private.label,
34545b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label));
34555b3e1433Swyllys 			}
34565b3e1433Swyllys 			/* Check if there is a key corresponding to this cert */
34575b3e1433Swyllys 			pkey = find_matching_key(xcert, numkeys, keylist);
34585b3e1433Swyllys 
34595b3e1433Swyllys 			/*
34605b3e1433Swyllys 			 * If key is found, get fingerprint and create a
34615b3e1433Swyllys 			 * safebag.
34625b3e1433Swyllys 			 */
34635b3e1433Swyllys 			if (pkey != NULL) {
34645b3e1433Swyllys 				(void) X509_digest(xcert, EVP_sha1(),
34655b3e1433Swyllys 				    keyid, &keyidlen);
34665b3e1433Swyllys 				key_authsafe = add_key_to_safe(pkey, cred,
34675b3e1433Swyllys 				    keyid, keyidlen,
34685b3e1433Swyllys 				    certlist[i].kmf_private.label,
34695b3e1433Swyllys 				    (certlist[i].kmf_private.label ?
34705b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label) : 0));
34715b3e1433Swyllys 
34725b3e1433Swyllys 				if (key_authsafe == NULL) {
34735b3e1433Swyllys 					X509_free(xcert);
34745b3e1433Swyllys 					EVP_PKEY_free(pkey);
34755b3e1433Swyllys 					goto cleanup;
34765b3e1433Swyllys 				}
34775b3e1433Swyllys 				/* Put the key safe into the Auth Safe */
34785b3e1433Swyllys 				if (!sk_PKCS7_push(authsafe_stack,
34795b3e1433Swyllys 				    key_authsafe)) {
34805b3e1433Swyllys 					X509_free(xcert);
34815b3e1433Swyllys 					EVP_PKEY_free(pkey);
34825b3e1433Swyllys 					goto cleanup;
34835b3e1433Swyllys 				}
34845b3e1433Swyllys 			}
34855b3e1433Swyllys 
34865b3e1433Swyllys 			/* create a certificate safebag */
34875b3e1433Swyllys 			cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
34885b3e1433Swyllys 			    keyidlen);
34895b3e1433Swyllys 			if (cert_authsafe == NULL) {
34905b3e1433Swyllys 				X509_free(xcert);
34915b3e1433Swyllys 				EVP_PKEY_free(pkey);
34925b3e1433Swyllys 				goto cleanup;
34935b3e1433Swyllys 			}
34945b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
34955b3e1433Swyllys 				X509_free(xcert);
34965b3e1433Swyllys 				EVP_PKEY_free(pkey);
34975b3e1433Swyllys 				goto cleanup;
34985b3e1433Swyllys 			}
34995b3e1433Swyllys 
350099ebb4caSwyllys 			X509_free(xcert);
350199ebb4caSwyllys 			if (pkey)
350299ebb4caSwyllys 				EVP_PKEY_free(pkey);
350399ebb4caSwyllys 		}
35045b3e1433Swyllys 	} else if (numcerts == 0 && numkeys > 0) {
35055b3e1433Swyllys 		/*
35065b3e1433Swyllys 		 * If only adding keys to the file.
35075b3e1433Swyllys 		 */
35085b3e1433Swyllys 		for (i = 0; i < numkeys; i++) {
35095b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
35105b3e1433Swyllys 
35115b3e1433Swyllys 			if (keylist[i].israw)
35125b3e1433Swyllys 				pkey = raw_key_to_pkey(&keylist[i]);
35135b3e1433Swyllys 			else
35145b3e1433Swyllys 				pkey = (EVP_PKEY *)keylist[i].keyp;
35155b3e1433Swyllys 
35165b3e1433Swyllys 			if (pkey == NULL)
35175b3e1433Swyllys 				continue;
35185b3e1433Swyllys 
35195b3e1433Swyllys 			key_authsafe = add_key_to_safe(pkey, cred,
35205b3e1433Swyllys 			    NULL, 0, NULL, 0);
35215b3e1433Swyllys 
35225b3e1433Swyllys 			if (key_authsafe == NULL) {
35235b3e1433Swyllys 				EVP_PKEY_free(pkey);
35245b3e1433Swyllys 				goto cleanup;
35255b3e1433Swyllys 			}
35265b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
35275b3e1433Swyllys 				EVP_PKEY_free(pkey);
35285b3e1433Swyllys 				goto cleanup;
35295b3e1433Swyllys 			}
35305b3e1433Swyllys 		}
35315b3e1433Swyllys 	}
35325b3e1433Swyllys 	p12_elem = PKCS12_init(NID_pkcs7_data);
35335b3e1433Swyllys 	if (p12_elem == NULL) {
35345b3e1433Swyllys 		goto cleanup;
353599ebb4caSwyllys 	}
353699ebb4caSwyllys 
35375b3e1433Swyllys 	/* Put the PKCS#7 stack into the PKCS#12 element. */
35385b3e1433Swyllys 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
35395b3e1433Swyllys 		goto cleanup;
35405b3e1433Swyllys 	}
35415b3e1433Swyllys 
35425b3e1433Swyllys 	/* Set the integrity MAC on the PKCS#12 element. */
35435b3e1433Swyllys 	if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
35445b3e1433Swyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
35455b3e1433Swyllys 		goto cleanup;
35465b3e1433Swyllys 	}
35475b3e1433Swyllys 
35485b3e1433Swyllys 	/* Write the PKCS#12 element to the export file. */
35495b3e1433Swyllys 	if (!i2d_PKCS12_bio(bio, p12_elem)) {
35505b3e1433Swyllys 		goto cleanup;
35515b3e1433Swyllys 	}
35525b3e1433Swyllys 	PKCS12_free(p12_elem);
35535b3e1433Swyllys 
355499ebb4caSwyllys cleanup:
35555b3e1433Swyllys 	/* Clear away the PKCS#7 stack, we're done with it. */
35565b3e1433Swyllys 	if (authsafe_stack)
35575b3e1433Swyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
355899ebb4caSwyllys 
355999ebb4caSwyllys 	if (bio != NULL)
356099ebb4caSwyllys 		(void) BIO_free_all(bio);
356199ebb4caSwyllys 
356299ebb4caSwyllys 	return (rv);
356399ebb4caSwyllys }
356499ebb4caSwyllys 
356599ebb4caSwyllys KMF_RETURN
356630a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
356730a5e8faSwyllys     KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
356830a5e8faSwyllys     KMF_CREDENTIAL *p12cred, char *filename)
356930a5e8faSwyllys {
357030a5e8faSwyllys 	KMF_RETURN rv;
357130a5e8faSwyllys 
357230a5e8faSwyllys 	if (certlist == NULL && keylist == NULL)
357330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
357430a5e8faSwyllys 
35755b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, numcerts, certlist,
357630a5e8faSwyllys 	    numkeys, keylist, filename);
357730a5e8faSwyllys 
357830a5e8faSwyllys 	return (rv);
357930a5e8faSwyllys }
358030a5e8faSwyllys 
358130a5e8faSwyllys KMF_RETURN
358230a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
358399ebb4caSwyllys {
358499ebb4caSwyllys 	KMF_RETURN rv;
358599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
358699ebb4caSwyllys 	char *fullpath = NULL;
358730a5e8faSwyllys 	char *dirpath = NULL;
358830a5e8faSwyllys 	char *certfile = NULL;
358930a5e8faSwyllys 	char *keyfile = NULL;
359030a5e8faSwyllys 	char *filename = NULL;
359130a5e8faSwyllys 	KMF_CREDENTIAL *p12cred = NULL;
35925b3e1433Swyllys 	KMF_X509_DER_CERT certdata;
35935b3e1433Swyllys 	KMF_KEY_HANDLE key;
35945b3e1433Swyllys 	int gotkey = 0;
35955b3e1433Swyllys 	int gotcert = 0;
359630a5e8faSwyllys 
359730a5e8faSwyllys 	if (handle == NULL)
359830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
359999ebb4caSwyllys 
360099ebb4caSwyllys 	/*
360199ebb4caSwyllys 	 *  First, find the certificate.
360299ebb4caSwyllys 	 */
360330a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
360430a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
360530a5e8faSwyllys 	if (certfile != NULL) {
360630a5e8faSwyllys 		fullpath = get_fullpath(dirpath, certfile);
360799ebb4caSwyllys 		if (fullpath == NULL)
360899ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
360999ebb4caSwyllys 
361099ebb4caSwyllys 		if (isdir(fullpath)) {
361199ebb4caSwyllys 			free(fullpath);
361299ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
361399ebb4caSwyllys 		}
361499ebb4caSwyllys 
36155b3e1433Swyllys 		(void) memset(&certdata, 0, sizeof (certdata));
36165b3e1433Swyllys 		rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL,
36175b3e1433Swyllys 		    fullpath, &certdata.certificate);
361899ebb4caSwyllys 		if (rv != KMF_OK)
361999ebb4caSwyllys 			goto end;
362030a5e8faSwyllys 
36215b3e1433Swyllys 		gotcert++;
36225b3e1433Swyllys 		certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
362330a5e8faSwyllys 		free(fullpath);
362499ebb4caSwyllys 	}
362599ebb4caSwyllys 
362699ebb4caSwyllys 	/*
362799ebb4caSwyllys 	 * Now find the private key.
362899ebb4caSwyllys 	 */
362930a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
363030a5e8faSwyllys 	if (keyfile != NULL) {
363130a5e8faSwyllys 		fullpath = get_fullpath(dirpath, keyfile);
363299ebb4caSwyllys 		if (fullpath == NULL)
363399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
363499ebb4caSwyllys 
363599ebb4caSwyllys 		if (isdir(fullpath)) {
363699ebb4caSwyllys 			free(fullpath);
363799ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
363899ebb4caSwyllys 		}
363999ebb4caSwyllys 
36405b3e1433Swyllys 		(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
36415b3e1433Swyllys 		rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
36425b3e1433Swyllys 		if (rv != KMF_OK)
364399ebb4caSwyllys 			goto end;
36445b3e1433Swyllys 		gotkey++;
364599ebb4caSwyllys 	}
364699ebb4caSwyllys 
364799ebb4caSwyllys 	/*
364899ebb4caSwyllys 	 * Open the output file.
364999ebb4caSwyllys 	 */
365030a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
365130a5e8faSwyllys 	    numattr);
365230a5e8faSwyllys 	if (filename == NULL) {
365330a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
365430a5e8faSwyllys 		goto end;
365530a5e8faSwyllys 	}
365630a5e8faSwyllys 
365799ebb4caSwyllys 	/* Stick the key and the cert into a PKCS#12 file */
365830a5e8faSwyllys 	p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
365930a5e8faSwyllys 	if (p12cred == NULL) {
366030a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
366130a5e8faSwyllys 		goto end;
366230a5e8faSwyllys 	}
366330a5e8faSwyllys 
36645b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, 1, &certdata,
36655b3e1433Swyllys 	    1, &key, filename);
366699ebb4caSwyllys 
366799ebb4caSwyllys end:
366899ebb4caSwyllys 	if (fullpath)
366999ebb4caSwyllys 		free(fullpath);
367099ebb4caSwyllys 
36715b3e1433Swyllys 	if (gotcert)
36725b3e1433Swyllys 		kmf_free_kmf_cert(handle, &certdata);
36735b3e1433Swyllys 	if (gotkey)
36745b3e1433Swyllys 		kmf_free_kmf_key(handle, &key);
367599ebb4caSwyllys 	return (rv);
367699ebb4caSwyllys }
367799ebb4caSwyllys 
367871593db2Swyllys /*
367971593db2Swyllys  * Helper function to extract keys and certificates from
368071593db2Swyllys  * a single PEM file.  Typically the file should contain a
368171593db2Swyllys  * private key and an associated public key wrapped in an x509 cert.
368271593db2Swyllys  * However, the file may be just a list of X509 certs with no keys.
368371593db2Swyllys  */
368471593db2Swyllys static KMF_RETURN
368530a5e8faSwyllys extract_pem(KMF_HANDLE *kmfh,
368630a5e8faSwyllys 	char *issuer, char *subject, KMF_BIGINT *serial,
368702744e81Swyllys 	char *filename, CK_UTF8CHAR *pin,
368871593db2Swyllys 	CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
368971593db2Swyllys 	int *numcerts)
3690a2d4930dSDan OpenSolaris Anderson /* ARGSUSED6 */
369171593db2Swyllys {
369271593db2Swyllys 	KMF_RETURN rv = KMF_OK;
369371593db2Swyllys 	FILE *fp;
369434acef67Swyllys 	STACK_OF(X509_INFO) *x509_info_stack = NULL;
369502744e81Swyllys 	int i, ncerts = 0, matchcerts = 0;
369671593db2Swyllys 	EVP_PKEY *pkey = NULL;
369771593db2Swyllys 	X509_INFO *info;
369871593db2Swyllys 	X509 *x;
36995b3e1433Swyllys 	X509_INFO **cert_infos = NULL;
370071593db2Swyllys 	KMF_DATA *certlist = NULL;
370171593db2Swyllys 
370271593db2Swyllys 	if (priv_key)
370371593db2Swyllys 		*priv_key = NULL;
370471593db2Swyllys 	if (certs)
370571593db2Swyllys 		*certs = NULL;
370671593db2Swyllys 	fp = fopen(filename, "r");
37075b3e1433Swyllys 	if (fp == NULL)
370871593db2Swyllys 		return (KMF_ERR_OPEN_FILE);
37095b3e1433Swyllys 
371071593db2Swyllys 	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
371171593db2Swyllys 	if (x509_info_stack == NULL) {
371271593db2Swyllys 		(void) fclose(fp);
371371593db2Swyllys 		return (KMF_ERR_ENCODING);
371471593db2Swyllys 	}
37155b3e1433Swyllys 	cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
37165b3e1433Swyllys 	    sizeof (X509_INFO *));
37175b3e1433Swyllys 	if (cert_infos == NULL) {
37185b3e1433Swyllys 		(void) fclose(fp);
37195b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
37205b3e1433Swyllys 		goto err;
37215b3e1433Swyllys 	}
372271593db2Swyllys 
37235b3e1433Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3724d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
372534acef67Swyllys 		cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
372671593db2Swyllys 		ncerts++;
372771593db2Swyllys 	}
372871593db2Swyllys 
372971593db2Swyllys 	if (ncerts == 0) {
373071593db2Swyllys 		(void) fclose(fp);
373134acef67Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
373234acef67Swyllys 		goto err;
373371593db2Swyllys 	}
373471593db2Swyllys 
373571593db2Swyllys 	if (priv_key != NULL) {
373671593db2Swyllys 		rewind(fp);
373771593db2Swyllys 		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
373871593db2Swyllys 	}
373971593db2Swyllys 	(void) fclose(fp);
374071593db2Swyllys 
374171593db2Swyllys 	x = cert_infos[ncerts - 1]->x509;
374271593db2Swyllys 	/*
374371593db2Swyllys 	 * Make sure the private key matchs the last cert in the file.
374471593db2Swyllys 	 */
374571593db2Swyllys 	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
374671593db2Swyllys 		EVP_PKEY_free(pkey);
374734acef67Swyllys 		rv = KMF_ERR_KEY_MISMATCH;
374834acef67Swyllys 		goto err;
374971593db2Swyllys 	}
375071593db2Swyllys 
3751a2d4930dSDan OpenSolaris Anderson 	certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
375271593db2Swyllys 	if (certlist == NULL) {
375371593db2Swyllys 		if (pkey != NULL)
375471593db2Swyllys 			EVP_PKEY_free(pkey);
375534acef67Swyllys 		rv = KMF_ERR_MEMORY;
375634acef67Swyllys 		goto err;
375771593db2Swyllys 	}
375871593db2Swyllys 
375971593db2Swyllys 	/*
376071593db2Swyllys 	 * Convert all of the certs to DER format.
376171593db2Swyllys 	 */
376202744e81Swyllys 	matchcerts = 0;
376371593db2Swyllys 	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
376402744e81Swyllys 		boolean_t match = FALSE;
376571593db2Swyllys 		info =  cert_infos[ncerts - 1 - i];
376671593db2Swyllys 
376730a5e8faSwyllys 		rv = check_cert(info->x509, issuer, subject, serial, &match);
376802744e81Swyllys 		if (rv != KMF_OK || match != TRUE) {
376902744e81Swyllys 			rv = KMF_OK;
377002744e81Swyllys 			continue;
377102744e81Swyllys 		}
377202744e81Swyllys 
377302744e81Swyllys 		rv = ssl_cert2KMFDATA(kmfh, info->x509,
377402744e81Swyllys 			&certlist[matchcerts++]);
377571593db2Swyllys 
377671593db2Swyllys 		if (rv != KMF_OK) {
3777e65e5c2dSWyllys Ingersoll 			int j;
3778e65e5c2dSWyllys Ingersoll 			for (j = 0; j < matchcerts; j++)
3779e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certlist[j]);
378071593db2Swyllys 			free(certlist);
378171593db2Swyllys 			certlist = NULL;
378202744e81Swyllys 			ncerts = matchcerts = 0;
378371593db2Swyllys 		}
378471593db2Swyllys 	}
378571593db2Swyllys 
378671593db2Swyllys 	if (numcerts != NULL)
378702744e81Swyllys 		*numcerts = matchcerts;
3788a2d4930dSDan OpenSolaris Anderson 
3789e65e5c2dSWyllys Ingersoll 	if (certs != NULL)
379071593db2Swyllys 		*certs = certlist;
3791e65e5c2dSWyllys Ingersoll 	else if (certlist != NULL) {
3792e65e5c2dSWyllys Ingersoll 		for (i = 0; i < ncerts; i++)
3793e65e5c2dSWyllys Ingersoll 			kmf_free_data(&certlist[i]);
3794a2d4930dSDan OpenSolaris Anderson 		free(certlist);
3795a2d4930dSDan OpenSolaris Anderson 		certlist = NULL;
3796a2d4930dSDan OpenSolaris Anderson 	}
379771593db2Swyllys 
379871593db2Swyllys 	if (priv_key == NULL && pkey != NULL)
379971593db2Swyllys 		EVP_PKEY_free(pkey);
380071593db2Swyllys 	else if (priv_key != NULL && pkey != NULL)
380171593db2Swyllys 		*priv_key = pkey;
380271593db2Swyllys 
380334acef67Swyllys err:
380434acef67Swyllys 	/* Cleanup the stack of X509 info records */
380534acef67Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3806d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
380734acef67Swyllys 		info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
380834acef67Swyllys 		X509_INFO_free(info);
380934acef67Swyllys 	}
381034acef67Swyllys 	if (x509_info_stack)
381134acef67Swyllys 		sk_X509_INFO_free(x509_info_stack);
381234acef67Swyllys 
38135b3e1433Swyllys 	if (cert_infos != NULL)
38145b3e1433Swyllys 		free(cert_infos);
38155b3e1433Swyllys 
381671593db2Swyllys 	return (rv);
381771593db2Swyllys }
381871593db2Swyllys 
38195b3e1433Swyllys static KMF_RETURN
3820*300fdee2SAndy Fiddaman openssl_parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
38215b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
38225b3e1433Swyllys {
38235b3e1433Swyllys 	KMF_RETURN ret;
38245b3e1433Swyllys 	int i;
38255b3e1433Swyllys 
38265b3e1433Swyllys 	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
3827d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
38285b3e1433Swyllys 		PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
38295b3e1433Swyllys 		ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
38305b3e1433Swyllys 		    keys, certs);
38315b3e1433Swyllys 
38325b3e1433Swyllys 		if (ret != KMF_OK)
38335b3e1433Swyllys 			return (ret);
38345b3e1433Swyllys 	}
38355b3e1433Swyllys 
38365b3e1433Swyllys 	return (ret);
38375b3e1433Swyllys }
38385b3e1433Swyllys 
38395b3e1433Swyllys static KMF_RETURN
38405b3e1433Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
38415b3e1433Swyllys {
38425b3e1433Swyllys 	X509_ATTRIBUTE *attr = NULL;
38435b3e1433Swyllys 
38445b3e1433Swyllys 	if (pkey == NULL || attrib == NULL)
38455b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
38465b3e1433Swyllys 
38475b3e1433Swyllys 	attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
38485b3e1433Swyllys 	if (attr != NULL) {
38495b3e1433Swyllys 		int i;
3850*300fdee2SAndy Fiddaman 
3851*300fdee2SAndy Fiddaman 		if ((i = EVP_PKEY_get_attr_by_NID(pkey, nid, -1)) != -1)
3852*300fdee2SAndy Fiddaman 			(void) EVP_PKEY_delete_attr(pkey, i);
3853*300fdee2SAndy Fiddaman 		if (EVP_PKEY_add1_attr(pkey, attr) == 0) {
38545b3e1433Swyllys 			X509_ATTRIBUTE_free(attr);
38555b3e1433Swyllys 			return (KMF_ERR_MEMORY);
38565b3e1433Swyllys 		}
38575b3e1433Swyllys 	} else {
38585b3e1433Swyllys 		return (KMF_ERR_MEMORY);
38595b3e1433Swyllys 	}
38605b3e1433Swyllys 
38615b3e1433Swyllys 	return (KMF_OK);
38625b3e1433Swyllys }
38635b3e1433Swyllys 
38645b3e1433Swyllys static KMF_RETURN
38655b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
38665b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
38675b3e1433Swyllys {
38685b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
38695b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
38705b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
38715b3e1433Swyllys 	X509 *xcert = NULL;
3872*300fdee2SAndy Fiddaman 	const ASN1_TYPE *keyid = NULL;
3873*300fdee2SAndy Fiddaman 	const ASN1_TYPE *fname = NULL;
38745b3e1433Swyllys 	uchar_t *data = NULL;
38755b3e1433Swyllys 
3876*300fdee2SAndy Fiddaman 	keyid = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID);
3877*300fdee2SAndy Fiddaman 	fname = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName);
38785b3e1433Swyllys 
3879*300fdee2SAndy Fiddaman 	switch (PKCS12_SAFEBAG_get_nid(bag)) {
38805b3e1433Swyllys 		case NID_keyBag:
38815b3e1433Swyllys 			if (keylist == NULL)
38825b3e1433Swyllys 				goto end;
3883*300fdee2SAndy Fiddaman 			pkey = EVP_PKCS82PKEY(
3884*300fdee2SAndy Fiddaman 			    PKCS12_SAFEBAG_get0_p8inf(bag));
38855b3e1433Swyllys 			if (pkey == NULL)
38865b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38875b3e1433Swyllys 
38885b3e1433Swyllys 			break;
38895b3e1433Swyllys 		case NID_pkcs8ShroudedKeyBag:
38905b3e1433Swyllys 			if (keylist == NULL)
38915b3e1433Swyllys 				goto end;
3892*300fdee2SAndy Fiddaman 			p8 = PKCS12_decrypt_skey(bag, pass, passlen);
38935b3e1433Swyllys 			if (p8 == NULL)
38945b3e1433Swyllys 				return (KMF_ERR_AUTH_FAILED);
38955b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(p8);
38965b3e1433Swyllys 			PKCS8_PRIV_KEY_INFO_free(p8);
38975b3e1433Swyllys 			if (pkey == NULL)
38985b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38995b3e1433Swyllys 			break;
39005b3e1433Swyllys 		case NID_certBag:
39015b3e1433Swyllys 			if (certlist == NULL)
39025b3e1433Swyllys 				goto end;
3903*300fdee2SAndy Fiddaman 			if (PKCS12_SAFEBAG_get_bag_nid(bag) !=
3904*300fdee2SAndy Fiddaman 			    NID_x509Certificate)
39055b3e1433Swyllys 				return (KMF_ERR_PKCS12_FORMAT);
3906*300fdee2SAndy Fiddaman 			xcert = PKCS12_SAFEBAG_get1_cert(bag);
39075b3e1433Swyllys 			if (xcert == NULL) {
39085b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
39095b3e1433Swyllys 				goto end;
39105b3e1433Swyllys 			}
39115b3e1433Swyllys 			if (keyid != NULL) {
39125b3e1433Swyllys 				if (X509_keyid_set1(xcert,
39135b3e1433Swyllys 				    keyid->value.octet_string->data,
39145b3e1433Swyllys 				    keyid->value.octet_string->length) == 0) {
39155b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
39165b3e1433Swyllys 					goto end;
39175b3e1433Swyllys 				}
39185b3e1433Swyllys 			}
39195b3e1433Swyllys 			if (fname != NULL) {
39205b3e1433Swyllys 				int len, r;
39215b3e1433Swyllys 				len = ASN1_STRING_to_UTF8(&data,
39225b3e1433Swyllys 				    fname->value.asn1_string);
39235b3e1433Swyllys 				if (len > 0 && data != NULL) {
39245b3e1433Swyllys 					r = X509_alias_set1(xcert, data, len);
39255b3e1433Swyllys 					if (r == NULL) {
39265b3e1433Swyllys 						ret = KMF_ERR_PKCS12_FORMAT;
39275b3e1433Swyllys 						goto end;
39285b3e1433Swyllys 					}
39295b3e1433Swyllys 				} else {
39305b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
39315b3e1433Swyllys 					goto end;
39325b3e1433Swyllys 				}
39335b3e1433Swyllys 			}
39345b3e1433Swyllys 			if (sk_X509_push(certlist, xcert) == 0)
39355b3e1433Swyllys 				ret = KMF_ERR_MEMORY;
39365b3e1433Swyllys 			else
39375b3e1433Swyllys 				xcert = NULL;
39385b3e1433Swyllys 			break;
39395b3e1433Swyllys 		case NID_safeContentsBag:
3940*300fdee2SAndy Fiddaman 			return (openssl_parse_bags(
3941*300fdee2SAndy Fiddaman 			    PKCS12_SAFEBAG_get0_safes(bag),
3942*300fdee2SAndy Fiddaman 			    pass, keylist, certlist));
39435b3e1433Swyllys 		default:
39445b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39455b3e1433Swyllys 			break;
39465b3e1433Swyllys 	}
39475b3e1433Swyllys 
39485b3e1433Swyllys 	/*
39495b3e1433Swyllys 	 * Set the ID and/or FriendlyName attributes on the key.
39505b3e1433Swyllys 	 * If converting to PKCS11 objects, these can translate to CKA_ID
39515b3e1433Swyllys 	 * and CKA_LABEL values.
39525b3e1433Swyllys 	 */
39535b3e1433Swyllys 	if (pkey != NULL && ret == KMF_OK) {
39545b3e1433Swyllys 		ASN1_TYPE *attr = NULL;
39555b3e1433Swyllys 		if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
39565b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
39575b3e1433Swyllys 				return (KMF_ERR_MEMORY);
39585b3e1433Swyllys 			attr->value.octet_string =
39595b3e1433Swyllys 			    ASN1_STRING_dup(keyid->value.octet_string);
39605b3e1433Swyllys 			attr->type = V_ASN1_OCTET_STRING;
39615b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.octet_string;
39625b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
39635b3e1433Swyllys 			OPENSSL_free(attr);
39645b3e1433Swyllys 		}
39655b3e1433Swyllys 
39665b3e1433Swyllys 		if (ret == KMF_OK && fname != NULL &&
39675b3e1433Swyllys 		    fname->type == V_ASN1_BMPSTRING) {
39685b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
39695b3e1433Swyllys 				return (KMF_ERR_MEMORY);
39705b3e1433Swyllys 			attr->value.bmpstring =
39715b3e1433Swyllys 			    ASN1_STRING_dup(fname->value.bmpstring);
39725b3e1433Swyllys 			attr->type = V_ASN1_BMPSTRING;
39735b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.bmpstring;
39745b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
39755b3e1433Swyllys 			OPENSSL_free(attr);
39765b3e1433Swyllys 		}
39775b3e1433Swyllys 
39785b3e1433Swyllys 		if (ret == KMF_OK && keylist != NULL &&
39795b3e1433Swyllys 		    sk_EVP_PKEY_push(keylist, pkey) == 0)
39805b3e1433Swyllys 			ret = KMF_ERR_MEMORY;
39815b3e1433Swyllys 	}
39825b3e1433Swyllys 	if (ret == KMF_OK && keylist != NULL)
39835b3e1433Swyllys 		pkey = NULL;
39845b3e1433Swyllys end:
39855b3e1433Swyllys 	if (pkey != NULL)
39865b3e1433Swyllys 		EVP_PKEY_free(pkey);
39875b3e1433Swyllys 	if (xcert != NULL)
39885b3e1433Swyllys 		X509_free(xcert);
39895b3e1433Swyllys 	if (data != NULL)
39905b3e1433Swyllys 		OPENSSL_free(data);
39915b3e1433Swyllys 
39925b3e1433Swyllys 	return (ret);
39935b3e1433Swyllys }
39945b3e1433Swyllys 
39955b3e1433Swyllys static KMF_RETURN
39965b3e1433Swyllys openssl_pkcs12_parse(PKCS12 *p12, char *pin,
39975b3e1433Swyllys 	STACK_OF(EVP_PKEY) *keys,
39985b3e1433Swyllys 	STACK_OF(X509) *certs,
39995b3e1433Swyllys 	STACK_OF(X509) *ca)
4000a2d4930dSDan OpenSolaris Anderson /* ARGSUSED3 */
40015b3e1433Swyllys {
40025b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
40035b3e1433Swyllys 	STACK_OF(PKCS7) *asafes = NULL;
40045b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
40055b3e1433Swyllys 	int i, bagnid;
40065b3e1433Swyllys 	PKCS7 *p7;
40075b3e1433Swyllys 
40085b3e1433Swyllys 	if (p12 == NULL || (keys == NULL && certs == NULL))
40095b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
40105b3e1433Swyllys 
40115b3e1433Swyllys 	if (pin == NULL || *pin == NULL) {
40125b3e1433Swyllys 		if (PKCS12_verify_mac(p12, NULL, 0)) {
40135b3e1433Swyllys 			pin = NULL;
40145b3e1433Swyllys 		} else if (PKCS12_verify_mac(p12, "", 0)) {
40155b3e1433Swyllys 			pin = "";
40165b3e1433Swyllys 		} else {
40175b3e1433Swyllys 			return (KMF_ERR_AUTH_FAILED);
40185b3e1433Swyllys 		}
40195b3e1433Swyllys 	} else if (!PKCS12_verify_mac(p12, pin, -1)) {
40205b3e1433Swyllys 		return (KMF_ERR_AUTH_FAILED);
40215b3e1433Swyllys 	}
40225b3e1433Swyllys 
40235b3e1433Swyllys 	if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
40245b3e1433Swyllys 		return (KMF_ERR_PKCS12_FORMAT);
40255b3e1433Swyllys 
40265b3e1433Swyllys 	for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
40275b3e1433Swyllys 		bags = NULL;
4028d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
40295b3e1433Swyllys 		p7 = sk_PKCS7_value(asafes, i);
40305b3e1433Swyllys 		bagnid = OBJ_obj2nid(p7->type);
40315b3e1433Swyllys 
40325b3e1433Swyllys 		if (bagnid == NID_pkcs7_data) {
40335b3e1433Swyllys 			bags = PKCS12_unpack_p7data(p7);
40345b3e1433Swyllys 		} else if (bagnid == NID_pkcs7_encrypted) {
40355b3e1433Swyllys 			bags = PKCS12_unpack_p7encdata(p7, pin,
40365b3e1433Swyllys 			    (pin ? strlen(pin) : 0));
40375b3e1433Swyllys 		} else {
40385b3e1433Swyllys 			continue;
40395b3e1433Swyllys 		}
40405b3e1433Swyllys 		if (bags == NULL) {
40415b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
40425b3e1433Swyllys 			goto out;
40435b3e1433Swyllys 		}
40445b3e1433Swyllys 
40455b3e1433Swyllys 		if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
40465b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
40475b3e1433Swyllys 
40485b3e1433Swyllys 		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
40495b3e1433Swyllys 	}
40505b3e1433Swyllys out:
40515b3e1433Swyllys 	if (asafes != NULL)
40525b3e1433Swyllys 		sk_PKCS7_pop_free(asafes, PKCS7_free);
40535b3e1433Swyllys 
40545b3e1433Swyllys 	return (ret);
40555b3e1433Swyllys }
40565b3e1433Swyllys 
405799ebb4caSwyllys /*
405899ebb4caSwyllys  * Helper function to decrypt and parse PKCS#12 import file.
405999ebb4caSwyllys  */
406099ebb4caSwyllys static KMF_RETURN
406199ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
40625b3e1433Swyllys 	STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs,
40635b3e1433Swyllys 	STACK_OF(X509) **ca)
4064a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */
406599ebb4caSwyllys {
406699ebb4caSwyllys 	PKCS12			*pk12, *pk12_tmp;
40675b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*pkeylist = NULL;
40685b3e1433Swyllys 	STACK_OF(X509)		*xcertlist = NULL;
40695b3e1433Swyllys 	STACK_OF(X509)		*cacertlist = NULL;
407099ebb4caSwyllys 
407199ebb4caSwyllys 	if ((pk12 = PKCS12_new()) == NULL) {
407299ebb4caSwyllys 		return (KMF_ERR_MEMORY);
407399ebb4caSwyllys 	}
407499ebb4caSwyllys 
407599ebb4caSwyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
407699ebb4caSwyllys 		/* This is ok; it seems to mean there is no more to read. */
407799ebb4caSwyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
407899ebb4caSwyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
407999ebb4caSwyllys 			goto end_extract_pkcs12;
408099ebb4caSwyllys 
408199ebb4caSwyllys 		PKCS12_free(pk12);
408299ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
408399ebb4caSwyllys 	}
408499ebb4caSwyllys 	pk12 = pk12_tmp;
408599ebb4caSwyllys 
40865b3e1433Swyllys 	xcertlist = sk_X509_new_null();
40875b3e1433Swyllys 	if (xcertlist == NULL) {
40885b3e1433Swyllys 		PKCS12_free(pk12);
40895b3e1433Swyllys 		return (KMF_ERR_MEMORY);
40905b3e1433Swyllys 	}
40915b3e1433Swyllys 	pkeylist = sk_EVP_PKEY_new_null();
40925b3e1433Swyllys 	if (pkeylist == NULL) {
40935b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40945b3e1433Swyllys 		PKCS12_free(pk12);
40955b3e1433Swyllys 		return (KMF_ERR_MEMORY);
40965b3e1433Swyllys 	}
40975b3e1433Swyllys 
40985b3e1433Swyllys 	if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
40995b3e1433Swyllys 	    cacertlist) != KMF_OK) {
41005b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
41015b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
410299ebb4caSwyllys 		PKCS12_free(pk12);
410399ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
410499ebb4caSwyllys 	}
410599ebb4caSwyllys 
41065b3e1433Swyllys 	if (priv_key && pkeylist)
41075b3e1433Swyllys 		*priv_key = pkeylist;
41085b3e1433Swyllys 	else if (pkeylist)
41095b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
41105b3e1433Swyllys 	if (certs && xcertlist)
41115b3e1433Swyllys 		*certs = xcertlist;
41125b3e1433Swyllys 	else if (xcertlist)
41135b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
41145b3e1433Swyllys 	if (ca && cacertlist)
41155b3e1433Swyllys 		*ca = cacertlist;
41165b3e1433Swyllys 	else if (cacertlist)
41175b3e1433Swyllys 		sk_X509_pop_free(cacertlist, X509_free);
411899ebb4caSwyllys 
41195b3e1433Swyllys end_extract_pkcs12:
412099ebb4caSwyllys 
412199ebb4caSwyllys 	PKCS12_free(pk12);
412299ebb4caSwyllys 	return (KMF_OK);
412399ebb4caSwyllys }
412499ebb4caSwyllys 
412599ebb4caSwyllys static KMF_RETURN
412699ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
412799ebb4caSwyllys {
412899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
412999ebb4caSwyllys 	uint32_t sz;
413099ebb4caSwyllys 
413199ebb4caSwyllys 	sz = BN_num_bytes(from);
413299ebb4caSwyllys 	to->val = (uchar_t *)malloc(sz);
413399ebb4caSwyllys 	if (to->val == NULL)
413499ebb4caSwyllys 		return (KMF_ERR_MEMORY);
413599ebb4caSwyllys 
413699ebb4caSwyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
413799ebb4caSwyllys 		free(to->val);
413899ebb4caSwyllys 		to->val = NULL;
413999ebb4caSwyllys 		to->len = 0;
414099ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
414199ebb4caSwyllys 	}
414299ebb4caSwyllys 
414399ebb4caSwyllys 	return (rv);
414499ebb4caSwyllys }
414599ebb4caSwyllys 
414699ebb4caSwyllys static KMF_RETURN
414799ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
414899ebb4caSwyllys {
414999ebb4caSwyllys 	KMF_RETURN rv;
415099ebb4caSwyllys 	KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
415199ebb4caSwyllys 
4152*300fdee2SAndy Fiddaman 	const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmpq, *iqmp;
4153*300fdee2SAndy Fiddaman 
4154*300fdee2SAndy Fiddaman 	RSA_get0_key(rsa, &n, &e, &d);
4155*300fdee2SAndy Fiddaman 	RSA_get0_factors(rsa, &p, &q);
4156*300fdee2SAndy Fiddaman 	RSA_get0_crt_params(rsa, &dmp1, &dmpq, &iqmp);
4157*300fdee2SAndy Fiddaman 
415899ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
4159*300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)n, &kmfkey->mod)) != KMF_OK)
416099ebb4caSwyllys 		goto cleanup;
416199ebb4caSwyllys 
4162*300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)e, &kmfkey->pubexp)) != KMF_OK)
416399ebb4caSwyllys 		goto cleanup;
416499ebb4caSwyllys 
4165*300fdee2SAndy Fiddaman 	if (d != NULL)
4166*300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)d, &kmfkey->priexp)) != KMF_OK)
416799ebb4caSwyllys 			goto cleanup;
416899ebb4caSwyllys 
4169*300fdee2SAndy Fiddaman 	if (p != NULL)
4170*300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime1)) != KMF_OK)
417199ebb4caSwyllys 			goto cleanup;
417299ebb4caSwyllys 
4173*300fdee2SAndy Fiddaman 	if (q != NULL)
4174*300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->prime2)) != KMF_OK)
417599ebb4caSwyllys 			goto cleanup;
417699ebb4caSwyllys 
4177*300fdee2SAndy Fiddaman 	if (dmp1 != NULL)
4178*300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)dmp1, &kmfkey->exp1)) != KMF_OK)
417999ebb4caSwyllys 			goto cleanup;
418099ebb4caSwyllys 
4181*300fdee2SAndy Fiddaman 	if (dmpq != NULL)
4182*300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)dmpq, &kmfkey->exp2)) != KMF_OK)
418399ebb4caSwyllys 			goto cleanup;
418499ebb4caSwyllys 
4185*300fdee2SAndy Fiddaman 	if (iqmp != NULL)
4186*300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)iqmp, &kmfkey->coef)) != KMF_OK)
418799ebb4caSwyllys 			goto cleanup;
418899ebb4caSwyllys cleanup:
418999ebb4caSwyllys 	if (rv != KMF_OK)
419030a5e8faSwyllys 		kmf_free_raw_key(key);
419199ebb4caSwyllys 	else
419299ebb4caSwyllys 		key->keytype = KMF_RSA;
419399ebb4caSwyllys 
419499ebb4caSwyllys 	/*
419599ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
419699ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
419799ebb4caSwyllys 	 */
419899ebb4caSwyllys 	RSA_free(rsa);
419999ebb4caSwyllys 
420099ebb4caSwyllys 	return (rv);
420199ebb4caSwyllys }
420299ebb4caSwyllys 
420399ebb4caSwyllys static KMF_RETURN
420499ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
420599ebb4caSwyllys {
420699ebb4caSwyllys 	KMF_RETURN rv;
420799ebb4caSwyllys 	KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
4208*300fdee2SAndy Fiddaman 	const BIGNUM *p, *q, *g, *priv_key;
4209*300fdee2SAndy Fiddaman 
4210*300fdee2SAndy Fiddaman 	DSA_get0_pqg(dsa, &p, &q, &g);
4211*300fdee2SAndy Fiddaman 	DSA_get0_key(dsa, NULL, &priv_key);
421299ebb4caSwyllys 
421399ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
4214*300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime)) != KMF_OK)
421599ebb4caSwyllys 		goto cleanup;
421699ebb4caSwyllys 
4217*300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->subprime)) != KMF_OK)
421899ebb4caSwyllys 		goto cleanup;
421999ebb4caSwyllys 
4220*300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)g, &kmfkey->base)) != KMF_OK)
422199ebb4caSwyllys 		goto cleanup;
422299ebb4caSwyllys 
4223*300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)priv_key, &kmfkey->value)) != KMF_OK)
422499ebb4caSwyllys 		goto cleanup;
422599ebb4caSwyllys 
422699ebb4caSwyllys cleanup:
422799ebb4caSwyllys 	if (rv != KMF_OK)
422830a5e8faSwyllys 		kmf_free_raw_key(key);
422999ebb4caSwyllys 	else
423099ebb4caSwyllys 		key->keytype = KMF_DSA;
423199ebb4caSwyllys 
423299ebb4caSwyllys 	/*
423399ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
423499ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
423599ebb4caSwyllys 	 */
423699ebb4caSwyllys 	DSA_free(dsa);
423799ebb4caSwyllys 
423899ebb4caSwyllys 	return (rv);
423999ebb4caSwyllys }
424099ebb4caSwyllys 
424199ebb4caSwyllys static KMF_RETURN
424299ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
42435b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
424499ebb4caSwyllys {
424599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
42465b3e1433Swyllys 	KMF_X509_DER_CERT *list = (*certlist);
42475b3e1433Swyllys 	KMF_X509_DER_CERT cert;
424899ebb4caSwyllys 	int n = (*ncerts);
424999ebb4caSwyllys 
425099ebb4caSwyllys 	if (list == NULL) {
42515b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
425299ebb4caSwyllys 	} else {
42535b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)realloc(list,
42545b3e1433Swyllys 		    sizeof (KMF_X509_DER_CERT) * (n + 1));
425599ebb4caSwyllys 	}
425699ebb4caSwyllys 
425799ebb4caSwyllys 	if (list == NULL)
425899ebb4caSwyllys 		return (KMF_ERR_MEMORY);
425999ebb4caSwyllys 
42605b3e1433Swyllys 	(void) memset(&cert, 0, sizeof (cert));
42615b3e1433Swyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
426299ebb4caSwyllys 	if (rv == KMF_OK) {
42635b3e1433Swyllys 		int len = 0;
42645b3e1433Swyllys 		/* Get the alias name for the cert if there is one */
42655b3e1433Swyllys 		char *a = (char *)X509_alias_get0(sslcert, &len);
42665b3e1433Swyllys 		if (a != NULL)
42675b3e1433Swyllys 			cert.kmf_private.label = strdup(a);
42685b3e1433Swyllys 		cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
42695b3e1433Swyllys 
427099ebb4caSwyllys 		list[n] = cert;
427199ebb4caSwyllys 		(*ncerts) = n + 1;
427299ebb4caSwyllys 
427399ebb4caSwyllys 		*certlist = list;
427499ebb4caSwyllys 	} else {
427599ebb4caSwyllys 		free(list);
427699ebb4caSwyllys 	}
427799ebb4caSwyllys 
427899ebb4caSwyllys 	return (rv);
427999ebb4caSwyllys }
428099ebb4caSwyllys 
428199ebb4caSwyllys static KMF_RETURN
428299ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
428399ebb4caSwyllys 	KMF_RAW_KEY_DATA *newkey, int *nkeys)
428499ebb4caSwyllys {
428599ebb4caSwyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
428699ebb4caSwyllys 	int n = (*nkeys);
428799ebb4caSwyllys 
428899ebb4caSwyllys 	if (list == NULL) {
428999ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
429099ebb4caSwyllys 	} else {
429199ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
429299ebb4caSwyllys 		    sizeof (KMF_RAW_KEY_DATA) * (n + 1));
429399ebb4caSwyllys 	}
429499ebb4caSwyllys 
429599ebb4caSwyllys 	if (list == NULL)
429699ebb4caSwyllys 		return (KMF_ERR_MEMORY);
429799ebb4caSwyllys 
429899ebb4caSwyllys 	list[n] = *newkey;
429999ebb4caSwyllys 	(*nkeys) = n + 1;
430099ebb4caSwyllys 
430199ebb4caSwyllys 	*keylist = list;
430299ebb4caSwyllys 
430399ebb4caSwyllys 	return (KMF_OK);
430499ebb4caSwyllys }
430599ebb4caSwyllys 
430630a5e8faSwyllys static KMF_RETURN
430730a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
430830a5e8faSwyllys {
430930a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
43105b3e1433Swyllys 	X509_ATTRIBUTE *attr;
4311*300fdee2SAndy Fiddaman 	RSA *rsa;
4312*300fdee2SAndy Fiddaman 	DSA *dsa;
4313*300fdee2SAndy Fiddaman 	int loc;
431430a5e8faSwyllys 
431530a5e8faSwyllys 	if (pkey == NULL || key == NULL)
431630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
431730a5e8faSwyllys 	/* Convert SSL key to raw key */
4318*300fdee2SAndy Fiddaman 	if ((rsa = EVP_PKEY_get1_RSA(pkey)) != NULL) {
4319*300fdee2SAndy Fiddaman 		rv = exportRawRSAKey(rsa, key);
432030a5e8faSwyllys 		if (rv != KMF_OK)
432130a5e8faSwyllys 			return (rv);
4322*300fdee2SAndy Fiddaman 	} else if ((dsa = EVP_PKEY_get1_DSA(pkey)) != NULL) {
4323*300fdee2SAndy Fiddaman 		rv = exportRawDSAKey(dsa, key);
432430a5e8faSwyllys 		if (rv != KMF_OK)
432530a5e8faSwyllys 			return (rv);
4326*300fdee2SAndy Fiddaman 	} else
432730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
4328*300fdee2SAndy Fiddaman 
43295b3e1433Swyllys 	/*
43305b3e1433Swyllys 	 * If friendlyName, add it to record.
43315b3e1433Swyllys 	 */
4332*300fdee2SAndy Fiddaman 
4333*300fdee2SAndy Fiddaman 	if ((loc = EVP_PKEY_get_attr_by_NID(pkey,
4334*300fdee2SAndy Fiddaman 	    NID_friendlyName, -1)) != -1 &&
4335*300fdee2SAndy Fiddaman 	    (attr = EVP_PKEY_get_attr(pkey, loc))) {
43365b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
4337*300fdee2SAndy Fiddaman 		int numattr = X509_ATTRIBUTE_count(attr);
4338*300fdee2SAndy Fiddaman 		if (numattr > 0) {
4339*300fdee2SAndy Fiddaman 			ty = X509_ATTRIBUTE_get0_type(attr, 0);
43405b3e1433Swyllys 		}
43415b3e1433Swyllys 		if (ty != NULL) {
434270f9559bSTheo Schlossnagle 			key->label = OPENSSL_uni2asc(ty->value.bmpstring->data,
434370f9559bSTheo Schlossnagle 			    ty->value.bmpstring->length);
43445b3e1433Swyllys 		}
43455b3e1433Swyllys 	} else {
43465b3e1433Swyllys 		key->label = NULL;
43475b3e1433Swyllys 	}
43485b3e1433Swyllys 
43495b3e1433Swyllys 	/*
43505b3e1433Swyllys 	 * If KeyID, add it to record as a KMF_DATA object.
43515b3e1433Swyllys 	 */
4352*300fdee2SAndy Fiddaman 	if ((loc = EVP_PKEY_get_attr_by_NID(pkey,
4353*300fdee2SAndy Fiddaman 	    NID_localKeyID, -1)) != -1 &&
4354*300fdee2SAndy Fiddaman 	    (attr = EVP_PKEY_get_attr(pkey, loc)) != NULL) {
43555b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
4356*300fdee2SAndy Fiddaman 		int numattr = X509_ATTRIBUTE_count(attr);
4357*300fdee2SAndy Fiddaman 		if (numattr > 0)
4358*300fdee2SAndy Fiddaman 			ty = X509_ATTRIBUTE_get0_type(attr, 0);
43595b3e1433Swyllys 		key->id.Data = (uchar_t *)malloc(
43605b3e1433Swyllys 		    ty->value.octet_string->length);
43615b3e1433Swyllys 		if (key->id.Data == NULL)
43625b3e1433Swyllys 			return (KMF_ERR_MEMORY);
43635b3e1433Swyllys 		(void) memcpy(key->id.Data, ty->value.octet_string->data,
43645b3e1433Swyllys 		    ty->value.octet_string->length);
43655b3e1433Swyllys 		key->id.Length = ty->value.octet_string->length;
43665b3e1433Swyllys 	} else {
43675b3e1433Swyllys 		(void) memset(&key->id, 0, sizeof (KMF_DATA));
43685b3e1433Swyllys 	}
436930a5e8faSwyllys 
437030a5e8faSwyllys 	return (rv);
437130a5e8faSwyllys }
437299ebb4caSwyllys 
437399ebb4caSwyllys static KMF_RETURN
437499ebb4caSwyllys convertPK12Objects(
437599ebb4caSwyllys 	KMF_HANDLE *kmfh,
43765b3e1433Swyllys 	STACK_OF(EVP_PKEY) *sslkeys,
43775b3e1433Swyllys 	STACK_OF(X509) *sslcert,
43785b3e1433Swyllys 	STACK_OF(X509) *sslcacerts,
437999ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
43805b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
438199ebb4caSwyllys {
438299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
438399ebb4caSwyllys 	KMF_RAW_KEY_DATA key;
438499ebb4caSwyllys 	int i;
438599ebb4caSwyllys 
43865b3e1433Swyllys 	for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
4387d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
43885b3e1433Swyllys 		EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
43895b3e1433Swyllys 		rv = convertToRawKey(pkey, &key);
439030a5e8faSwyllys 		if (rv == KMF_OK)
439199ebb4caSwyllys 			rv = add_key_to_list(keylist, &key, nkeys);
439230a5e8faSwyllys 
439399ebb4caSwyllys 		if (rv != KMF_OK)
439499ebb4caSwyllys 			return (rv);
439599ebb4caSwyllys 	}
439699ebb4caSwyllys 
439799ebb4caSwyllys 	/* Now add the certificate to the certlist */
43985b3e1433Swyllys 	for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
4399d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
44005b3e1433Swyllys 		X509 *cert = sk_X509_value(sslcert, i);
44015b3e1433Swyllys 		rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
440299ebb4caSwyllys 		if (rv != KMF_OK)
440399ebb4caSwyllys 			return (rv);
440499ebb4caSwyllys 	}
440599ebb4caSwyllys 
440699ebb4caSwyllys 	/* Also add any included CA certs to the list */
440771593db2Swyllys 	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
440899ebb4caSwyllys 		X509 *c;
440999ebb4caSwyllys 		/*
441099ebb4caSwyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
441199ebb4caSwyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
441299ebb4caSwyllys 		 * Lint is complaining about the embedded casting, and
441399ebb4caSwyllys 		 * to fix it, you need to fix openssl header files.
441499ebb4caSwyllys 		 */
4415d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
441699ebb4caSwyllys 		c = sk_X509_value(sslcacerts, i);
441799ebb4caSwyllys 
441899ebb4caSwyllys 		/* Now add the ca cert to the certlist */
441999ebb4caSwyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
442099ebb4caSwyllys 		if (rv != KMF_OK)
442199ebb4caSwyllys 			return (rv);
442299ebb4caSwyllys 	}
442399ebb4caSwyllys 	return (rv);
442499ebb4caSwyllys }
442599ebb4caSwyllys 
442699ebb4caSwyllys KMF_RETURN
442730a5e8faSwyllys openssl_import_objects(KMF_HANDLE *kmfh,
442899ebb4caSwyllys 	char *filename, KMF_CREDENTIAL *cred,
44295b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts,
443099ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
443199ebb4caSwyllys {
443299ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
443330a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
443430a5e8faSwyllys 	BIO		*bio = NULL;
44355b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*privkeys = NULL;
44365b3e1433Swyllys 	STACK_OF(X509)		*certs = NULL;
443799ebb4caSwyllys 	STACK_OF(X509)		*cacerts = NULL;
443899ebb4caSwyllys 
443930a5e8faSwyllys 	/*
444030a5e8faSwyllys 	 * auto-detect the file format, regardless of what
444130a5e8faSwyllys 	 * the 'format' parameters in the params say.
444230a5e8faSwyllys 	 */
444330a5e8faSwyllys 	rv = kmf_get_file_format(filename, &format);
444430a5e8faSwyllys 	if (rv != KMF_OK) {
444530a5e8faSwyllys 		return (rv);
444630a5e8faSwyllys 	}
444730a5e8faSwyllys 
444830a5e8faSwyllys 	/* This function only works for PEM or PKCS#12 files */
444930a5e8faSwyllys 	if (format != KMF_FORMAT_PEM &&
445030a5e8faSwyllys 	    format != KMF_FORMAT_PEM_KEYPAIR &&
445130a5e8faSwyllys 	    format != KMF_FORMAT_PKCS12)
445230a5e8faSwyllys 		return (KMF_ERR_ENCODING);
445330a5e8faSwyllys 
445430a5e8faSwyllys 	*certlist = NULL;
445530a5e8faSwyllys 	*keylist = NULL;
445630a5e8faSwyllys 	*ncerts = 0;
445730a5e8faSwyllys 	*nkeys = 0;
445830a5e8faSwyllys 
445930a5e8faSwyllys 	if (format == KMF_FORMAT_PKCS12) {
446099ebb4caSwyllys 		bio = BIO_new_file(filename, "rb");
446199ebb4caSwyllys 		if (bio == NULL) {
446299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
446399ebb4caSwyllys 			rv = KMF_ERR_OPEN_FILE;
446499ebb4caSwyllys 			goto end;
446599ebb4caSwyllys 		}
446699ebb4caSwyllys 
446734acef67Swyllys 		rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
44685b3e1433Swyllys 		    (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
446999ebb4caSwyllys 
447099ebb4caSwyllys 		if (rv  == KMF_OK)
447199ebb4caSwyllys 			/* Convert keys and certs to exportable format */
44725b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
447399ebb4caSwyllys 			    keylist, nkeys, certlist, ncerts);
447430a5e8faSwyllys 	} else {
44755b3e1433Swyllys 		EVP_PKEY *pkey;
44765b3e1433Swyllys 		KMF_DATA *certdata = NULL;
44775b3e1433Swyllys 		KMF_X509_DER_CERT *kmfcerts = NULL;
44785b3e1433Swyllys 		int i;
447930a5e8faSwyllys 		rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
448034acef67Swyllys 		    (uchar_t *)cred->cred, (uint32_t)cred->credlen,
44815b3e1433Swyllys 		    &pkey, &certdata, ncerts);
448271593db2Swyllys 
448371593db2Swyllys 		/* Reached end of import file? */
44845b3e1433Swyllys 		if (rv == KMF_OK && pkey != NULL) {
44855b3e1433Swyllys 			privkeys = sk_EVP_PKEY_new_null();
44865b3e1433Swyllys 			if (privkeys == NULL) {
44875b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
44885b3e1433Swyllys 				goto end;
44895b3e1433Swyllys 			}
44905b3e1433Swyllys 			(void) sk_EVP_PKEY_push(privkeys, pkey);
44915b3e1433Swyllys 			/* convert the certificate list here */
44925b3e1433Swyllys 			if (*ncerts > 0 && certlist != NULL) {
4493e65e5c2dSWyllys Ingersoll 				kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
44945b3e1433Swyllys 				    sizeof (KMF_X509_DER_CERT));
44955b3e1433Swyllys 				if (kmfcerts == NULL) {
44965b3e1433Swyllys 					rv = KMF_ERR_MEMORY;
44975b3e1433Swyllys 					goto end;
44985b3e1433Swyllys 				}
44995b3e1433Swyllys 				for (i = 0; i < *ncerts; i++) {
45005b3e1433Swyllys 					kmfcerts[i].certificate = certdata[i];
45015b3e1433Swyllys 					kmfcerts[i].kmf_private.keystore_type =
45025b3e1433Swyllys 					    KMF_KEYSTORE_OPENSSL;
45035b3e1433Swyllys 				}
45045b3e1433Swyllys 				*certlist = kmfcerts;
45055b3e1433Swyllys 			}
45065b3e1433Swyllys 			/*
45075b3e1433Swyllys 			 * Convert keys to exportable format, the certs
45085b3e1433Swyllys 			 * are already OK.
45095b3e1433Swyllys 			 */
45105b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
451171593db2Swyllys 			    keylist, nkeys, NULL, NULL);
451230a5e8faSwyllys 		}
45135b3e1433Swyllys 	}
451471593db2Swyllys end:
451530a5e8faSwyllys 	if (bio != NULL)
451699ebb4caSwyllys 		(void) BIO_free(bio);
451799ebb4caSwyllys 
45185b3e1433Swyllys 	if (privkeys)
45195b3e1433Swyllys 		sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
45205b3e1433Swyllys 	if (certs)
45215b3e1433Swyllys 		sk_X509_pop_free(certs, X509_free);
452230a5e8faSwyllys 	if (cacerts)
45235b3e1433Swyllys 		sk_X509_pop_free(cacerts, X509_free);
452430a5e8faSwyllys 
452599ebb4caSwyllys 	return (rv);
452699ebb4caSwyllys }
452799ebb4caSwyllys 
452899ebb4caSwyllys static KMF_RETURN
452999ebb4caSwyllys create_deskey(DES_cblock **deskey)
453099ebb4caSwyllys {
453199ebb4caSwyllys 	DES_cblock *key;
453299ebb4caSwyllys 
453399ebb4caSwyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
453499ebb4caSwyllys 	if (key == NULL) {
453599ebb4caSwyllys 		return (KMF_ERR_MEMORY);
453699ebb4caSwyllys 	}
453799ebb4caSwyllys 
453899ebb4caSwyllys 	if (DES_random_key(key) == 0) {
453999ebb4caSwyllys 		free(key);
454099ebb4caSwyllys 		return (KMF_ERR_KEYGEN_FAILED);
454199ebb4caSwyllys 	}
454299ebb4caSwyllys 
454399ebb4caSwyllys 	*deskey = key;
454499ebb4caSwyllys 	return (KMF_OK);
454599ebb4caSwyllys }
454699ebb4caSwyllys 
454799ebb4caSwyllys #define	KEYGEN_RETRY 3
454899ebb4caSwyllys #define	DES3_KEY_SIZE 24
454999ebb4caSwyllys 
455099ebb4caSwyllys static KMF_RETURN
455199ebb4caSwyllys create_des3key(unsigned char **des3key)
455299ebb4caSwyllys {
455399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
455499ebb4caSwyllys 	DES_cblock *deskey1 = NULL;
455599ebb4caSwyllys 	DES_cblock *deskey2 = NULL;
455699ebb4caSwyllys 	DES_cblock *deskey3 = NULL;
455799ebb4caSwyllys 	unsigned char *newkey = NULL;
455899ebb4caSwyllys 	int retry;
455999ebb4caSwyllys 
456099ebb4caSwyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
456199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
456299ebb4caSwyllys 	}
456399ebb4caSwyllys 
456499ebb4caSwyllys 	/* create the 1st DES key */
456599ebb4caSwyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
456699ebb4caSwyllys 		goto out;
456799ebb4caSwyllys 	}
456899ebb4caSwyllys 
456999ebb4caSwyllys 	/*
457099ebb4caSwyllys 	 * Create the 2nd DES key and make sure its value is different
457199ebb4caSwyllys 	 * from the 1st DES key.
457299ebb4caSwyllys 	 */
457399ebb4caSwyllys 	retry = 0;
457499ebb4caSwyllys 	do {
457599ebb4caSwyllys 		if (deskey2 != NULL) {
457699ebb4caSwyllys 			free(deskey2);
457799ebb4caSwyllys 			deskey2 = NULL;
457899ebb4caSwyllys 		}
457999ebb4caSwyllys 
458099ebb4caSwyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
458199ebb4caSwyllys 			goto out;
458299ebb4caSwyllys 		}
458399ebb4caSwyllys 
458499ebb4caSwyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
458599ebb4caSwyllys 		    == 0) {
458699ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
458799ebb4caSwyllys 			retry++;
458899ebb4caSwyllys 		}
458999ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
459099ebb4caSwyllys 
459199ebb4caSwyllys 	if (ret != KMF_OK) {
459299ebb4caSwyllys 		goto out;
459399ebb4caSwyllys 	}
459499ebb4caSwyllys 
459599ebb4caSwyllys 	/*
459699ebb4caSwyllys 	 * Create the 3rd DES key and make sure its value is different
459799ebb4caSwyllys 	 * from the 2nd DES key.
459899ebb4caSwyllys 	 */
459999ebb4caSwyllys 	retry = 0;
460099ebb4caSwyllys 	do {
460199ebb4caSwyllys 		if (deskey3 != NULL) {
460299ebb4caSwyllys 			free(deskey3);
460399ebb4caSwyllys 			deskey3 = NULL;
460499ebb4caSwyllys 		}
460599ebb4caSwyllys 
460699ebb4caSwyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
460799ebb4caSwyllys 			goto out;
460899ebb4caSwyllys 		}
460999ebb4caSwyllys 
461099ebb4caSwyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
461199ebb4caSwyllys 		    == 0) {
461299ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
461399ebb4caSwyllys 			retry++;
461499ebb4caSwyllys 		}
461599ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
461699ebb4caSwyllys 
461799ebb4caSwyllys 	if (ret != KMF_OK) {
461899ebb4caSwyllys 		goto out;
461999ebb4caSwyllys 	}
462099ebb4caSwyllys 
462199ebb4caSwyllys 	/* Concatenate 3 DES keys into a DES3 key */
462299ebb4caSwyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
462399ebb4caSwyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
462499ebb4caSwyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
462599ebb4caSwyllys 	*des3key = newkey;
462699ebb4caSwyllys 
462799ebb4caSwyllys out:
462899ebb4caSwyllys 	if (deskey1 != NULL)
462999ebb4caSwyllys 		free(deskey1);
463099ebb4caSwyllys 
463199ebb4caSwyllys 	if (deskey2 != NULL)
463299ebb4caSwyllys 		free(deskey2);
463399ebb4caSwyllys 
463499ebb4caSwyllys 	if (deskey3 != NULL)
463599ebb4caSwyllys 		free(deskey3);
463699ebb4caSwyllys 
463799ebb4caSwyllys 	if (ret != KMF_OK && newkey != NULL)
463899ebb4caSwyllys 		free(newkey);
463999ebb4caSwyllys 
464099ebb4caSwyllys 	return (ret);
464199ebb4caSwyllys }
464299ebb4caSwyllys 
464399ebb4caSwyllys KMF_RETURN
464430a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
464530a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
464699ebb4caSwyllys {
464799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
464899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
464999ebb4caSwyllys 	char *fullpath = NULL;
465099ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
465199ebb4caSwyllys 	DES_cblock *deskey = NULL;
465299ebb4caSwyllys 	unsigned char *des3key = NULL;
465399ebb4caSwyllys 	unsigned char *random = NULL;
465499ebb4caSwyllys 	int fd = -1;
465530a5e8faSwyllys 	KMF_KEY_HANDLE *symkey;
465630a5e8faSwyllys 	KMF_KEY_ALG keytype;
465730a5e8faSwyllys 	uint32_t keylen;
465830a5e8faSwyllys 	uint32_t keylen_size = sizeof (keylen);
465930a5e8faSwyllys 	char *dirpath;
466030a5e8faSwyllys 	char *keyfile;
466199ebb4caSwyllys 
466299ebb4caSwyllys 	if (kmfh == NULL)
466399ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
466499ebb4caSwyllys 
466530a5e8faSwyllys 	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
466630a5e8faSwyllys 	if (symkey == NULL)
466799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
466899ebb4caSwyllys 
466930a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
467030a5e8faSwyllys 
467130a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
467230a5e8faSwyllys 	if (keyfile == NULL)
467330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
467430a5e8faSwyllys 
467530a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
467630a5e8faSwyllys 	    (void *)&keytype, NULL);
467730a5e8faSwyllys 	if (ret != KMF_OK)
467830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
467930a5e8faSwyllys 
468030a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
468130a5e8faSwyllys 	    &keylen, &keylen_size);
468230a5e8faSwyllys 	if (ret == KMF_ERR_ATTR_NOT_FOUND &&
468330a5e8faSwyllys 	    (keytype == KMF_DES || keytype == KMF_DES3))
468430a5e8faSwyllys 		/* keylength is not required for DES and 3DES */
468530a5e8faSwyllys 		ret = KMF_OK;
468630a5e8faSwyllys 	if (ret != KMF_OK)
468730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
468830a5e8faSwyllys 
468930a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
469099ebb4caSwyllys 	if (fullpath == NULL)
469199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
469299ebb4caSwyllys 
469399ebb4caSwyllys 	/* If the requested file exists, return an error */
469430a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
469599ebb4caSwyllys 		free(fullpath);
469699ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
469799ebb4caSwyllys 	}
469899ebb4caSwyllys 
469999ebb4caSwyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
470099ebb4caSwyllys 	if (fd == -1) {
470199ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
470299ebb4caSwyllys 		goto out;
470399ebb4caSwyllys 	}
470499ebb4caSwyllys 
470599ebb4caSwyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
470699ebb4caSwyllys 	if (rkey == NULL) {
470799ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
470899ebb4caSwyllys 		goto out;
470999ebb4caSwyllys 	}
471099ebb4caSwyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
471199ebb4caSwyllys 
471230a5e8faSwyllys 	if (keytype == KMF_DES) {
471399ebb4caSwyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
471499ebb4caSwyllys 			goto out;
471599ebb4caSwyllys 		}
471699ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)deskey;
471799ebb4caSwyllys 		rkey->keydata.len = 8;
471899ebb4caSwyllys 
471999ebb4caSwyllys 		symkey->keyalg = KMF_DES;
472099ebb4caSwyllys 
472130a5e8faSwyllys 	} else if (keytype == KMF_DES3) {
472299ebb4caSwyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
472399ebb4caSwyllys 			goto out;
472499ebb4caSwyllys 		}
472599ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)des3key;
472699ebb4caSwyllys 		rkey->keydata.len = DES3_KEY_SIZE;
472799ebb4caSwyllys 		symkey->keyalg = KMF_DES3;
47289b37d296Swyllys 
472930a5e8faSwyllys 	} else if (keytype == KMF_AES || keytype == KMF_RC4 ||
473030a5e8faSwyllys 	    keytype == KMF_GENERIC_SECRET) {
473199ebb4caSwyllys 		int bytes;
473299ebb4caSwyllys 
473330a5e8faSwyllys 		if (keylen % 8 != 0) {
473499ebb4caSwyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
473599ebb4caSwyllys 			goto out;
473699ebb4caSwyllys 		}
473799ebb4caSwyllys 
473830a5e8faSwyllys 		if (keytype == KMF_AES) {
473930a5e8faSwyllys 			if (keylen != 128 &&
474030a5e8faSwyllys 			    keylen != 192 &&
474130a5e8faSwyllys 			    keylen != 256) {
474299ebb4caSwyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
474399ebb4caSwyllys 				goto out;
474499ebb4caSwyllys 			}
474599ebb4caSwyllys 		}
474699ebb4caSwyllys 
474730a5e8faSwyllys 		bytes = keylen/8;
474899ebb4caSwyllys 		random = malloc(bytes);
474999ebb4caSwyllys 		if (random == NULL) {
475099ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
475199ebb4caSwyllys 			goto out;
475299ebb4caSwyllys 		}
475399ebb4caSwyllys 		if (RAND_bytes(random, bytes) != 1) {
475499ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
475599ebb4caSwyllys 			goto out;
475699ebb4caSwyllys 		}
475799ebb4caSwyllys 
475899ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)random;
475999ebb4caSwyllys 		rkey->keydata.len = bytes;
476030a5e8faSwyllys 		symkey->keyalg = keytype;
476199ebb4caSwyllys 
476299ebb4caSwyllys 	} else {
476399ebb4caSwyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
476499ebb4caSwyllys 		goto out;
476599ebb4caSwyllys 	}
476699ebb4caSwyllys 
476799ebb4caSwyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
476899ebb4caSwyllys 
476999ebb4caSwyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
477099ebb4caSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
477199ebb4caSwyllys 	symkey->keylabel = (char *)fullpath;
477299ebb4caSwyllys 	symkey->israw = TRUE;
477399ebb4caSwyllys 	symkey->keyp = rkey;
477499ebb4caSwyllys 
477599ebb4caSwyllys out:
477699ebb4caSwyllys 	if (fd != -1)
477799ebb4caSwyllys 		(void) close(fd);
477899ebb4caSwyllys 
477999ebb4caSwyllys 	if (ret != KMF_OK && fullpath != NULL) {
478099ebb4caSwyllys 		free(fullpath);
478199ebb4caSwyllys 	}
478299ebb4caSwyllys 	if (ret != KMF_OK) {
478330a5e8faSwyllys 		kmf_free_raw_sym_key(rkey);
478499ebb4caSwyllys 		symkey->keyp = NULL;
478599ebb4caSwyllys 		symkey->keyalg = KMF_KEYALG_NONE;
478699ebb4caSwyllys 	}
478799ebb4caSwyllys 
478899ebb4caSwyllys 	return (ret);
478999ebb4caSwyllys }
479099ebb4caSwyllys 
479199ebb4caSwyllys /*
479299ebb4caSwyllys  * Check a file to see if it is a CRL file with PEM or DER format.
479399ebb4caSwyllys  * If success, return its format in the "pformat" argument.
479499ebb4caSwyllys  */
479599ebb4caSwyllys KMF_RETURN
479699ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
479799ebb4caSwyllys {
479899ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
479999ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
480099ebb4caSwyllys 	BIO		*bio = NULL;
480199ebb4caSwyllys 	X509_CRL   	*xcrl = NULL;
480299ebb4caSwyllys 
480399ebb4caSwyllys 	if (filename == NULL) {
480499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
480599ebb4caSwyllys 	}
480699ebb4caSwyllys 
480799ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
480899ebb4caSwyllys 	if (bio == NULL)	{
480999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
481099ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
481199ebb4caSwyllys 		goto out;
481299ebb4caSwyllys 	}
481399ebb4caSwyllys 
481499ebb4caSwyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
481599ebb4caSwyllys 		*pformat = KMF_FORMAT_PEM;
481699ebb4caSwyllys 		goto out;
481799ebb4caSwyllys 	}
481899ebb4caSwyllys 	(void) BIO_free(bio);
481999ebb4caSwyllys 
482099ebb4caSwyllys 	/*
482199ebb4caSwyllys 	 * Now try to read it as raw DER data.
482299ebb4caSwyllys 	 */
482399ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
482499ebb4caSwyllys 	if (bio == NULL)	{
482599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
482699ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
482799ebb4caSwyllys 		goto out;
482899ebb4caSwyllys 	}
482999ebb4caSwyllys 
483099ebb4caSwyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
483199ebb4caSwyllys 		*pformat = KMF_FORMAT_ASN1;
483299ebb4caSwyllys 	} else {
483399ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
483499ebb4caSwyllys 	}
483599ebb4caSwyllys 
483699ebb4caSwyllys out:
483799ebb4caSwyllys 	if (bio != NULL)
483899ebb4caSwyllys 		(void) BIO_free(bio);
483999ebb4caSwyllys 
484099ebb4caSwyllys 	if (xcrl != NULL)
484199ebb4caSwyllys 		X509_CRL_free(xcrl);
484299ebb4caSwyllys 
484399ebb4caSwyllys 	return (ret);
484499ebb4caSwyllys }
484599ebb4caSwyllys 
484699ebb4caSwyllys KMF_RETURN
484799ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
484899ebb4caSwyllys     KMF_RAW_SYM_KEY *rkey)
484999ebb4caSwyllys {
485099ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
485199ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
485299ebb4caSwyllys 	KMF_DATA	keyvalue;
485399ebb4caSwyllys 
485499ebb4caSwyllys 	if (kmfh == NULL)
485599ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
485699ebb4caSwyllys 
485799ebb4caSwyllys 	if (symkey == NULL || rkey == NULL)
485899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
485999ebb4caSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
486099ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
486199ebb4caSwyllys 
486299ebb4caSwyllys 	if (symkey->israw) {
486399ebb4caSwyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
486499ebb4caSwyllys 
486599ebb4caSwyllys 		if (rawkey == NULL ||
486699ebb4caSwyllys 		    rawkey->keydata.val == NULL ||
486799ebb4caSwyllys 		    rawkey->keydata.len == 0)
486899ebb4caSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
486999ebb4caSwyllys 
487099ebb4caSwyllys 		rkey->keydata.len = rawkey->keydata.len;
487199ebb4caSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
487299ebb4caSwyllys 			return (KMF_ERR_MEMORY);
487399ebb4caSwyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
487499ebb4caSwyllys 		    rkey->keydata.len);
487599ebb4caSwyllys 	} else {
487630a5e8faSwyllys 		rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
487799ebb4caSwyllys 		if (rv != KMF_OK)
487899ebb4caSwyllys 			return (rv);
487999ebb4caSwyllys 		rkey->keydata.len = keyvalue.Length;
488099ebb4caSwyllys 		rkey->keydata.val = keyvalue.Data;
488199ebb4caSwyllys 	}
488299ebb4caSwyllys 
488399ebb4caSwyllys 	return (rv);
488499ebb4caSwyllys }
488502744e81Swyllys 
488602744e81Swyllys /*
488730a5e8faSwyllys  * substitute for the unsafe access(2) function.
488830a5e8faSwyllys  * If the file in question already exists, return 1.
488930a5e8faSwyllys  * else 0.  If an error occurs during testing (other
489030a5e8faSwyllys  * than EEXIST), return -1.
489130a5e8faSwyllys  */
489230a5e8faSwyllys static int
489330a5e8faSwyllys test_for_file(char *filename, mode_t mode)
489430a5e8faSwyllys {
489530a5e8faSwyllys 	int fd;
489630a5e8faSwyllys 
489730a5e8faSwyllys 	/*
489830a5e8faSwyllys 	 * Try to create the file with the EXCL flag.
489930a5e8faSwyllys 	 * The call should fail if the file exists.
490030a5e8faSwyllys 	 */
490130a5e8faSwyllys 	fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
490230a5e8faSwyllys 	if (fd == -1 && errno == EEXIST)
490330a5e8faSwyllys 		return (1);
490430a5e8faSwyllys 	else if (fd == -1) /* some other error */
490530a5e8faSwyllys 		return (-1);
490630a5e8faSwyllys 
490730a5e8faSwyllys 	/* The file did NOT exist.  Delete the testcase. */
490830a5e8faSwyllys 	(void) close(fd);
490930a5e8faSwyllys 	(void) unlink(filename);
491030a5e8faSwyllys 	return (0);
491130a5e8faSwyllys }
491230a5e8faSwyllys 
491330a5e8faSwyllys KMF_RETURN
491430a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
491530a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist)
491630a5e8faSwyllys {
491730a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
491830a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
491930a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
492030a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
492130a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
492230a5e8faSwyllys 	KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
492330a5e8faSwyllys 	KMF_CREDENTIAL cred = { NULL, 0 };
492430a5e8faSwyllys 	BIO *out = NULL;
492530a5e8faSwyllys 	int keys = 0;
492630a5e8faSwyllys 	char *fullpath = NULL;
492730a5e8faSwyllys 	char *keyfile = NULL;
492830a5e8faSwyllys 	char *dirpath = NULL;
492930a5e8faSwyllys 
493030a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
493130a5e8faSwyllys 	if (pubkey != NULL)
493230a5e8faSwyllys 		keys++;
493330a5e8faSwyllys 
493430a5e8faSwyllys 	prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
493530a5e8faSwyllys 	if (prikey != NULL)
493630a5e8faSwyllys 		keys++;
493730a5e8faSwyllys 
493830a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
493930a5e8faSwyllys 	if (rawkey != NULL)
494030a5e8faSwyllys 		keys++;
494130a5e8faSwyllys 
494230a5e8faSwyllys 	/*
494330a5e8faSwyllys 	 * Exactly 1 type of key must be passed to this function.
494430a5e8faSwyllys 	 */
494530a5e8faSwyllys 	if (keys != 1)
494630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
494730a5e8faSwyllys 
494830a5e8faSwyllys 	keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
494930a5e8faSwyllys 	    numattr);
495030a5e8faSwyllys 	if (keyfile == NULL)
495130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
495230a5e8faSwyllys 
495330a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
495430a5e8faSwyllys 
495530a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
495630a5e8faSwyllys 
495730a5e8faSwyllys 	/* Once we have the full path, we don't need the pieces */
495830a5e8faSwyllys 	if (fullpath == NULL)
495930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
496030a5e8faSwyllys 
496130a5e8faSwyllys 	/* If the requested file exists, return an error */
496230a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
496330a5e8faSwyllys 		free(fullpath);
496430a5e8faSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
496530a5e8faSwyllys 	}
496630a5e8faSwyllys 
496730a5e8faSwyllys 	rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
496830a5e8faSwyllys 	    &format, NULL);
496930a5e8faSwyllys 	if (rv != KMF_OK)
497030a5e8faSwyllys 		/* format is optional. */
497130a5e8faSwyllys 		rv = KMF_OK;
497230a5e8faSwyllys 
497330a5e8faSwyllys 	/* CRED is not required for OpenSSL files */
497430a5e8faSwyllys 	(void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
497530a5e8faSwyllys 	    &cred, NULL);
497630a5e8faSwyllys 
497730a5e8faSwyllys 	/* Store the private key to the keyfile */
497830a5e8faSwyllys 	out = BIO_new_file(fullpath, "wb");
497930a5e8faSwyllys 	if (out == NULL) {
498030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
498130a5e8faSwyllys 		rv = KMF_ERR_OPEN_FILE;
498230a5e8faSwyllys 		goto end;
498330a5e8faSwyllys 	}
498430a5e8faSwyllys 
498530a5e8faSwyllys 	if (prikey != NULL && prikey->keyp != NULL) {
498630a5e8faSwyllys 		if (prikey->keyalg == KMF_RSA ||
498730a5e8faSwyllys 		    prikey->keyalg == KMF_DSA) {
498830a5e8faSwyllys 			pkey = (EVP_PKEY *)prikey->keyp;
498930a5e8faSwyllys 
499030a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
499130a5e8faSwyllys 			    out, &cred, pkey, TRUE);
499230a5e8faSwyllys 
499330a5e8faSwyllys 			if (rv == KMF_OK && prikey->keylabel == NULL) {
499430a5e8faSwyllys 				prikey->keylabel = strdup(fullpath);
499530a5e8faSwyllys 				if (prikey->keylabel == NULL)
499630a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
499730a5e8faSwyllys 			}
499830a5e8faSwyllys 		}
499930a5e8faSwyllys 	} else if (pubkey != NULL && pubkey->keyp != NULL) {
500030a5e8faSwyllys 		if (pubkey->keyalg == KMF_RSA ||
500130a5e8faSwyllys 		    pubkey->keyalg == KMF_DSA) {
500230a5e8faSwyllys 			pkey = (EVP_PKEY *)pubkey->keyp;
500330a5e8faSwyllys 
500430a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
500530a5e8faSwyllys 			    out, &cred, pkey, FALSE);
500630a5e8faSwyllys 
500730a5e8faSwyllys 			if (rv == KMF_OK && pubkey->keylabel == NULL) {
500830a5e8faSwyllys 				pubkey->keylabel = strdup(fullpath);
500930a5e8faSwyllys 				if (pubkey->keylabel == NULL)
501030a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
501130a5e8faSwyllys 			}
501230a5e8faSwyllys 		}
501330a5e8faSwyllys 	} else if (rawkey != NULL) {
501430a5e8faSwyllys 		if (rawkey->keytype == KMF_RSA) {
501530a5e8faSwyllys 			pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
501630a5e8faSwyllys 		} else if (rawkey->keytype == KMF_DSA) {
501730a5e8faSwyllys 			pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
501830a5e8faSwyllys 		} else {
501930a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
502030a5e8faSwyllys 		}
50215b3e1433Swyllys 		if (pkey != NULL) {
502273cc0e02Swyllys 			KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
502373cc0e02Swyllys 
502473cc0e02Swyllys 			rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
502573cc0e02Swyllys 			    (void *)&kclass, NULL);
502673cc0e02Swyllys 			if (rv != KMF_OK)
502773cc0e02Swyllys 				rv = KMF_OK;
50285b3e1433Swyllys 			rv = ssl_write_key(kmfh, format, out,
502973cc0e02Swyllys 			    &cred, pkey, (kclass == KMF_ASYM_PRI));
50305b3e1433Swyllys 			EVP_PKEY_free(pkey);
50315b3e1433Swyllys 		}
503230a5e8faSwyllys 	}
503330a5e8faSwyllys 
503430a5e8faSwyllys end:
503530a5e8faSwyllys 
503630a5e8faSwyllys 	if (out)
503730a5e8faSwyllys 		(void) BIO_free(out);
503830a5e8faSwyllys 
50395b3e1433Swyllys 
504030a5e8faSwyllys 	if (rv == KMF_OK)
504130a5e8faSwyllys 		(void) chmod(fullpath, 0400);
504230a5e8faSwyllys 
504330a5e8faSwyllys 	free(fullpath);
504430a5e8faSwyllys 	return (rv);
504530a5e8faSwyllys }
504630a5e8faSwyllys 
504730a5e8faSwyllys KMF_RETURN
504830a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
504930a5e8faSwyllys {
505030a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
505130a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
505230a5e8faSwyllys 	X509_CRL *xcrl = NULL;
505330a5e8faSwyllys 	X509 *xcert = NULL;
505430a5e8faSwyllys 	EVP_PKEY *pkey;
505530a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
505630a5e8faSwyllys 	BIO *in = NULL, *out = NULL;
505730a5e8faSwyllys 	int openssl_ret = 0;
505830a5e8faSwyllys 	KMF_ENCODE_FORMAT outformat;
505930a5e8faSwyllys 	boolean_t crlcheck = FALSE;
506030a5e8faSwyllys 	char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
506130a5e8faSwyllys 
506230a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
506330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
506430a5e8faSwyllys 	}
506530a5e8faSwyllys 
506630a5e8faSwyllys 	/* CRL check is optional */
506730a5e8faSwyllys 	(void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
506830a5e8faSwyllys 	    &crlcheck, NULL);
506930a5e8faSwyllys 
507030a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
507130a5e8faSwyllys 	if (crlcheck == B_TRUE && certfile == NULL) {
507230a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
507330a5e8faSwyllys 	}
507430a5e8faSwyllys 
507530a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
507630a5e8faSwyllys 	incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
507730a5e8faSwyllys 	outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
507830a5e8faSwyllys 
507930a5e8faSwyllys 	crlfile = get_fullpath(dirpath, incrl);
508030a5e8faSwyllys 
508130a5e8faSwyllys 	if (crlfile == NULL)
508230a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
508330a5e8faSwyllys 
508430a5e8faSwyllys 	outcrlfile = get_fullpath(dirpath, outcrl);
508530a5e8faSwyllys 	if (outcrlfile == NULL)
508630a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
508730a5e8faSwyllys 
508830a5e8faSwyllys 	if (isdir(outcrlfile)) {
508930a5e8faSwyllys 		free(outcrlfile);
509030a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
509130a5e8faSwyllys 	}
509230a5e8faSwyllys 
509330a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
509430a5e8faSwyllys 	if (ret != KMF_OK) {
509530a5e8faSwyllys 		free(outcrlfile);
509630a5e8faSwyllys 		return (ret);
509730a5e8faSwyllys 	}
509830a5e8faSwyllys 
509930a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
510030a5e8faSwyllys 	if (in == NULL)	{
510130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
510230a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
510330a5e8faSwyllys 		goto end;
510430a5e8faSwyllys 	}
510530a5e8faSwyllys 
510630a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
510730a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
510830a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
510930a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
511030a5e8faSwyllys 	}
511130a5e8faSwyllys 
511230a5e8faSwyllys 	if (xcrl == NULL) {
511330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
511430a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
511530a5e8faSwyllys 		goto end;
511630a5e8faSwyllys 	}
511730a5e8faSwyllys 
511830a5e8faSwyllys 	/* If bypasscheck is specified, no need to verify. */
511930a5e8faSwyllys 	if (crlcheck == B_FALSE)
512030a5e8faSwyllys 		goto output;
512130a5e8faSwyllys 
512230a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
512330a5e8faSwyllys 	if (ret != KMF_OK)
512430a5e8faSwyllys 		goto end;
512530a5e8faSwyllys 
512630a5e8faSwyllys 	/* Read in the CA cert file and convert to X509 */
512730a5e8faSwyllys 	if (BIO_read_filename(in, certfile) <= 0) {
512830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
512930a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
513030a5e8faSwyllys 		goto end;
513130a5e8faSwyllys 	}
513230a5e8faSwyllys 
513330a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
513430a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
513530a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
513630a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
513730a5e8faSwyllys 	} else {
513830a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
513930a5e8faSwyllys 		goto end;
514030a5e8faSwyllys 	}
514130a5e8faSwyllys 
514230a5e8faSwyllys 	if (xcert == NULL) {
514330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
514430a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
514530a5e8faSwyllys 		goto end;
514630a5e8faSwyllys 	}
514730a5e8faSwyllys 	/* Now get the public key from the CA cert */
514830a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
514930a5e8faSwyllys 	if (pkey == NULL) {
515030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
515130a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
515230a5e8faSwyllys 		goto end;
515330a5e8faSwyllys 	}
515430a5e8faSwyllys 
515530a5e8faSwyllys 	/* Verify the CRL with the CA's public key */
515630a5e8faSwyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
515730a5e8faSwyllys 	EVP_PKEY_free(pkey);
515830a5e8faSwyllys 	if (openssl_ret > 0) {
515930a5e8faSwyllys 		ret = KMF_OK;  /* verify succeed */
516030a5e8faSwyllys 	} else {
516130a5e8faSwyllys 		SET_ERROR(kmfh, openssl_ret);
516230a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
516330a5e8faSwyllys 	}
516430a5e8faSwyllys 
516530a5e8faSwyllys output:
516630a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
516730a5e8faSwyllys 	    &outformat, NULL);
516830a5e8faSwyllys 	if (ret != KMF_OK) {
516930a5e8faSwyllys 		ret = KMF_OK;
517030a5e8faSwyllys 		outformat = KMF_FORMAT_PEM;
517130a5e8faSwyllys 	}
517230a5e8faSwyllys 
517330a5e8faSwyllys 	out = BIO_new_file(outcrlfile, "wb");
517430a5e8faSwyllys 	if (out == NULL) {
517530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
517630a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
517730a5e8faSwyllys 		goto end;
517830a5e8faSwyllys 	}
517930a5e8faSwyllys 
518030a5e8faSwyllys 	if (outformat == KMF_FORMAT_ASN1) {
518130a5e8faSwyllys 		openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
518230a5e8faSwyllys 	} else if (outformat == KMF_FORMAT_PEM) {
518330a5e8faSwyllys 		openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
518430a5e8faSwyllys 	} else {
518530a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
518630a5e8faSwyllys 		goto end;
518730a5e8faSwyllys 	}
518830a5e8faSwyllys 
518930a5e8faSwyllys 	if (openssl_ret <= 0) {
519030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
519130a5e8faSwyllys 		ret = KMF_ERR_WRITE_FILE;
519230a5e8faSwyllys 	} else {
519330a5e8faSwyllys 		ret = KMF_OK;
519430a5e8faSwyllys 	}
519530a5e8faSwyllys 
519630a5e8faSwyllys end:
519730a5e8faSwyllys 	if (xcrl != NULL)
519830a5e8faSwyllys 		X509_CRL_free(xcrl);
519930a5e8faSwyllys 
520030a5e8faSwyllys 	if (xcert != NULL)
520130a5e8faSwyllys 		X509_free(xcert);
520230a5e8faSwyllys 
520330a5e8faSwyllys 	if (in != NULL)
520430a5e8faSwyllys 		(void) BIO_free(in);
520530a5e8faSwyllys 
520630a5e8faSwyllys 	if (out != NULL)
520730a5e8faSwyllys 		(void) BIO_free(out);
520830a5e8faSwyllys 
520930a5e8faSwyllys 	if (outcrlfile != NULL)
521030a5e8faSwyllys 		free(outcrlfile);
521130a5e8faSwyllys 
521230a5e8faSwyllys 	return (ret);
521330a5e8faSwyllys }
521430a5e8faSwyllys 
521530a5e8faSwyllys KMF_RETURN
521630a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
521730a5e8faSwyllys {
521830a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
521930a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
522030a5e8faSwyllys 	X509_CRL   *x = NULL;
522130a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
522230a5e8faSwyllys 	char *crlfile = NULL;
522330a5e8faSwyllys 	BIO *in = NULL;
522430a5e8faSwyllys 	BIO *mem = NULL;
522530a5e8faSwyllys 	long len;
522630a5e8faSwyllys 	char *memptr;
522730a5e8faSwyllys 	char *data = NULL;
522830a5e8faSwyllys 	char **crldata;
522930a5e8faSwyllys 	char *crlfilename, *dirpath;
523030a5e8faSwyllys 
523130a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
523230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
523330a5e8faSwyllys 	}
523430a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
523530a5e8faSwyllys 	    attrlist, numattr);
523630a5e8faSwyllys 	if (crlfilename == NULL)
523730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
523830a5e8faSwyllys 
523930a5e8faSwyllys 	crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
524030a5e8faSwyllys 	    attrlist, numattr);
524130a5e8faSwyllys 
524230a5e8faSwyllys 	if (crldata == NULL)
524330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
524430a5e8faSwyllys 
524530a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
524630a5e8faSwyllys 
524730a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
524830a5e8faSwyllys 
524930a5e8faSwyllys 	if (crlfile == NULL)
525030a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
525130a5e8faSwyllys 
525230a5e8faSwyllys 	if (isdir(crlfile)) {
525330a5e8faSwyllys 		free(crlfile);
525430a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
525530a5e8faSwyllys 	}
525630a5e8faSwyllys 
525730a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
525830a5e8faSwyllys 	if (ret != KMF_OK) {
525930a5e8faSwyllys 		free(crlfile);
526030a5e8faSwyllys 		return (ret);
526130a5e8faSwyllys 	}
526230a5e8faSwyllys 
526330a5e8faSwyllys 	if (bio_err == NULL)
526430a5e8faSwyllys 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
526530a5e8faSwyllys 
526630a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
526730a5e8faSwyllys 	if (in == NULL)	{
526830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
526930a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
527030a5e8faSwyllys 		goto end;
527130a5e8faSwyllys 	}
527230a5e8faSwyllys 
527330a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
527430a5e8faSwyllys 		x = d2i_X509_CRL_bio(in, NULL);
527530a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
527630a5e8faSwyllys 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
527730a5e8faSwyllys 	}
527830a5e8faSwyllys 
527930a5e8faSwyllys 	if (x == NULL) { /* should not happen */
528030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
528130a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
528230a5e8faSwyllys 		goto end;
528330a5e8faSwyllys 	}
528430a5e8faSwyllys 
528530a5e8faSwyllys 	mem = BIO_new(BIO_s_mem());
528630a5e8faSwyllys 	if (mem == NULL) {
528730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
528830a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
528930a5e8faSwyllys 		goto end;
529030a5e8faSwyllys 	}
529130a5e8faSwyllys 
529230a5e8faSwyllys 	(void) X509_CRL_print(mem, x);
529330a5e8faSwyllys 	len = BIO_get_mem_data(mem, &memptr);
529430a5e8faSwyllys 	if (len <= 0) {
529530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
529630a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
529730a5e8faSwyllys 		goto end;
529830a5e8faSwyllys 	}
529930a5e8faSwyllys 
530030a5e8faSwyllys 	data = malloc(len + 1);
530130a5e8faSwyllys 	if (data == NULL) {
530230a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
530330a5e8faSwyllys 		goto end;
530430a5e8faSwyllys 	}
530530a5e8faSwyllys 
530630a5e8faSwyllys 	(void) memcpy(data, memptr, len);
530730a5e8faSwyllys 	data[len] = '\0';
530830a5e8faSwyllys 	*crldata = data;
530930a5e8faSwyllys 
531030a5e8faSwyllys end:
531130a5e8faSwyllys 	if (x != NULL)
531230a5e8faSwyllys 		X509_CRL_free(x);
531330a5e8faSwyllys 
531430a5e8faSwyllys 	if (crlfile != NULL)
531530a5e8faSwyllys 		free(crlfile);
531630a5e8faSwyllys 
531730a5e8faSwyllys 	if (in != NULL)
531830a5e8faSwyllys 		(void) BIO_free(in);
531930a5e8faSwyllys 
532030a5e8faSwyllys 	if (mem != NULL)
532130a5e8faSwyllys 		(void) BIO_free(mem);
532230a5e8faSwyllys 
532330a5e8faSwyllys 	return (ret);
532430a5e8faSwyllys }
532530a5e8faSwyllys 
532630a5e8faSwyllys KMF_RETURN
532730a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
532830a5e8faSwyllys {
532930a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
533030a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
533130a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
533230a5e8faSwyllys 	char *crlfile = NULL;
533330a5e8faSwyllys 	BIO *in = NULL;
533430a5e8faSwyllys 	char *crlfilename, *dirpath;
533530a5e8faSwyllys 
533630a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
533730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
533830a5e8faSwyllys 	}
533930a5e8faSwyllys 
534030a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
534130a5e8faSwyllys 	    attrlist, numattr);
534230a5e8faSwyllys 
534330a5e8faSwyllys 	if (crlfilename == NULL)
534430a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
534530a5e8faSwyllys 
534630a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
534730a5e8faSwyllys 
534830a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
534930a5e8faSwyllys 
535030a5e8faSwyllys 	if (crlfile == NULL)
535130a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
535230a5e8faSwyllys 
535330a5e8faSwyllys 	if (isdir(crlfile)) {
535430a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
535530a5e8faSwyllys 		goto end;
535630a5e8faSwyllys 	}
535730a5e8faSwyllys 
535830a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
535930a5e8faSwyllys 	if (ret != KMF_OK)
536030a5e8faSwyllys 		goto end;
536130a5e8faSwyllys 
536230a5e8faSwyllys 	if (unlink(crlfile) != 0) {
536330a5e8faSwyllys 		SET_SYS_ERROR(kmfh, errno);
536430a5e8faSwyllys 		ret = KMF_ERR_INTERNAL;
536530a5e8faSwyllys 		goto end;
536630a5e8faSwyllys 	}
536730a5e8faSwyllys 
536830a5e8faSwyllys end:
536930a5e8faSwyllys 	if (in != NULL)
537030a5e8faSwyllys 		(void) BIO_free(in);
537130a5e8faSwyllys 	if (crlfile != NULL)
537230a5e8faSwyllys 		free(crlfile);
537330a5e8faSwyllys 
537430a5e8faSwyllys 	return (ret);
537530a5e8faSwyllys }
537630a5e8faSwyllys 
537730a5e8faSwyllys KMF_RETURN
537830a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
537930a5e8faSwyllys {
538030a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
538130a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
538230a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
538330a5e8faSwyllys 	BIO *in = NULL;
538430a5e8faSwyllys 	X509   *xcert = NULL;
538530a5e8faSwyllys 	X509_CRL   *xcrl = NULL;
538630a5e8faSwyllys 	STACK_OF(X509_REVOKED) *revoke_stack = NULL;
538730a5e8faSwyllys 	X509_REVOKED *revoke;
538830a5e8faSwyllys 	int i;
538930a5e8faSwyllys 	char *crlfilename, *crlfile, *dirpath, *certfile;
539030a5e8faSwyllys 
539130a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
539230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
539330a5e8faSwyllys 	}
539430a5e8faSwyllys 
539530a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
539630a5e8faSwyllys 	    attrlist, numattr);
539730a5e8faSwyllys 
539830a5e8faSwyllys 	if (crlfilename == NULL)
539930a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
540030a5e8faSwyllys 
540130a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
540230a5e8faSwyllys 	if (certfile == NULL)
540330a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
540430a5e8faSwyllys 
540530a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
540630a5e8faSwyllys 
540730a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
540830a5e8faSwyllys 
540930a5e8faSwyllys 	if (crlfile == NULL)
541030a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
541130a5e8faSwyllys 
541230a5e8faSwyllys 	if (isdir(crlfile)) {
541330a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
541430a5e8faSwyllys 		goto end;
541530a5e8faSwyllys 	}
541630a5e8faSwyllys 
541730a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
541830a5e8faSwyllys 	if (ret != KMF_OK)
541930a5e8faSwyllys 		goto end;
542030a5e8faSwyllys 
542130a5e8faSwyllys 	/* Read the CRL file and load it into a X509_CRL structure */
542230a5e8faSwyllys 	in = BIO_new_file(crlfilename, "rb");
542330a5e8faSwyllys 	if (in == NULL)	{
542430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
542530a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
542630a5e8faSwyllys 		goto end;
542730a5e8faSwyllys 	}
542830a5e8faSwyllys 
542930a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
543030a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
543130a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
543230a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
543330a5e8faSwyllys 	}
543430a5e8faSwyllys 
543530a5e8faSwyllys 	if (xcrl == NULL) {
543630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
543730a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
543830a5e8faSwyllys 		goto end;
543930a5e8faSwyllys 	}
544030a5e8faSwyllys 	(void) BIO_free(in);
544130a5e8faSwyllys 
544230a5e8faSwyllys 	/* Read the Certificate file and load it into a X509 structure */
544330a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
544430a5e8faSwyllys 	if (ret != KMF_OK)
544530a5e8faSwyllys 		goto end;
544630a5e8faSwyllys 
544730a5e8faSwyllys 	in = BIO_new_file(certfile, "rb");
544830a5e8faSwyllys 	if (in == NULL)	{
544930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
545030a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
545130a5e8faSwyllys 		goto end;
545230a5e8faSwyllys 	}
545330a5e8faSwyllys 
545430a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
545530a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
545630a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
545730a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
545830a5e8faSwyllys 	}
545930a5e8faSwyllys 
546030a5e8faSwyllys 	if (xcert == NULL) {
546130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
546230a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
546330a5e8faSwyllys 		goto end;
546430a5e8faSwyllys 	}
546530a5e8faSwyllys 
546630a5e8faSwyllys 	/* Check if the certificate and the CRL have same issuer */
5467*300fdee2SAndy Fiddaman 	if (X509_NAME_cmp(X509_get_issuer_name(xcert),
5468*300fdee2SAndy Fiddaman 	    X509_CRL_get_issuer(xcrl)) != 0) {
546930a5e8faSwyllys 		ret = KMF_ERR_ISSUER;
547030a5e8faSwyllys 		goto end;
547130a5e8faSwyllys 	}
547230a5e8faSwyllys 
547330a5e8faSwyllys 	/* Check to see if the certificate serial number is revoked */
547430a5e8faSwyllys 	revoke_stack = X509_CRL_get_REVOKED(xcrl);
547530a5e8faSwyllys 	if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
547630a5e8faSwyllys 		/* No revoked certificates in the CRL file */
547730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
547830a5e8faSwyllys 		ret = KMF_ERR_EMPTY_CRL;
547930a5e8faSwyllys 		goto end;
548030a5e8faSwyllys 	}
548130a5e8faSwyllys 
548230a5e8faSwyllys 	for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
5483d7141854SRobert Mustacchi 		/* LINTED E_BAD_PTR_CAST_ALIGN */
548430a5e8faSwyllys 		revoke = sk_X509_REVOKED_value(revoke_stack, i);
5485*300fdee2SAndy Fiddaman 		if (ASN1_INTEGER_cmp(X509_get_serialNumber(xcert),
5486*300fdee2SAndy Fiddaman 		    X509_REVOKED_get0_serialNumber(revoke)) == 0) {
548730a5e8faSwyllys 			break;
548830a5e8faSwyllys 		}
548930a5e8faSwyllys 	}
549030a5e8faSwyllys 
549130a5e8faSwyllys 	if (i < sk_X509_REVOKED_num(revoke_stack)) {
549230a5e8faSwyllys 		ret = KMF_OK;
549330a5e8faSwyllys 	} else {
549430a5e8faSwyllys 		ret = KMF_ERR_NOT_REVOKED;
549530a5e8faSwyllys 	}
549630a5e8faSwyllys 
549730a5e8faSwyllys end:
549830a5e8faSwyllys 	if (in != NULL)
549930a5e8faSwyllys 		(void) BIO_free(in);
550030a5e8faSwyllys 	if (xcrl != NULL)
550130a5e8faSwyllys 		X509_CRL_free(xcrl);
550230a5e8faSwyllys 	if (xcert != NULL)
550330a5e8faSwyllys 		X509_free(xcert);
550430a5e8faSwyllys 
550530a5e8faSwyllys 	return (ret);
550630a5e8faSwyllys }
550730a5e8faSwyllys 
550830a5e8faSwyllys KMF_RETURN
550930a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
551030a5e8faSwyllys {
551130a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
551230a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
551330a5e8faSwyllys 	BIO		*bcrl = NULL;
551430a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
551530a5e8faSwyllys 	X509		*xcert = NULL;
551630a5e8faSwyllys 	EVP_PKEY	*pkey;
551730a5e8faSwyllys 	int		sslret;
551830a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
551930a5e8faSwyllys 	unsigned char	*p;
552030a5e8faSwyllys 	long		len;
552130a5e8faSwyllys 
552230a5e8faSwyllys 	if (handle == NULL || crlname == NULL || tacert == NULL) {
552330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
552430a5e8faSwyllys 	}
552530a5e8faSwyllys 
552630a5e8faSwyllys 	ret = kmf_get_file_format(crlname, &crl_format);
552730a5e8faSwyllys 	if (ret != KMF_OK)
552830a5e8faSwyllys 		return (ret);
552930a5e8faSwyllys 
553030a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
553130a5e8faSwyllys 	if (bcrl == NULL)	{
553230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
553330a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
553430a5e8faSwyllys 		goto cleanup;
553530a5e8faSwyllys 	}
553630a5e8faSwyllys 
553730a5e8faSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
553830a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
553930a5e8faSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
554030a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
554130a5e8faSwyllys 	} else {
554230a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
554330a5e8faSwyllys 		goto cleanup;
554430a5e8faSwyllys 	}
554530a5e8faSwyllys 
554630a5e8faSwyllys 	if (xcrl == NULL) {
554730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
554830a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
554930a5e8faSwyllys 		goto cleanup;
555030a5e8faSwyllys 	}
555130a5e8faSwyllys 
555230a5e8faSwyllys 	p = tacert->Data;
555330a5e8faSwyllys 	len = tacert->Length;
555430a5e8faSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
555530a5e8faSwyllys 
555630a5e8faSwyllys 	if (xcert == NULL) {
555730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
555830a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
555930a5e8faSwyllys 		goto cleanup;
556030a5e8faSwyllys 	}
556130a5e8faSwyllys 
556230a5e8faSwyllys 	/* Get issuer certificate public key */
556330a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
556430a5e8faSwyllys 	if (pkey == NULL) {
556530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
556630a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
556730a5e8faSwyllys 		goto cleanup;
556830a5e8faSwyllys 	}
556930a5e8faSwyllys 
557030a5e8faSwyllys 	/* Verify CRL signature */
557130a5e8faSwyllys 	sslret = X509_CRL_verify(xcrl, pkey);
557230a5e8faSwyllys 	EVP_PKEY_free(pkey);
557330a5e8faSwyllys 	if (sslret > 0) {
557430a5e8faSwyllys 		ret = KMF_OK;
557530a5e8faSwyllys 	} else {
557630a5e8faSwyllys 		SET_ERROR(kmfh, sslret);
557730a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
557830a5e8faSwyllys 	}
557930a5e8faSwyllys 
558030a5e8faSwyllys cleanup:
558130a5e8faSwyllys 	if (bcrl != NULL)
558230a5e8faSwyllys 		(void) BIO_free(bcrl);
558330a5e8faSwyllys 
558430a5e8faSwyllys 	if (xcrl != NULL)
558530a5e8faSwyllys 		X509_CRL_free(xcrl);
558630a5e8faSwyllys 
558730a5e8faSwyllys 	if (xcert != NULL)
558830a5e8faSwyllys 		X509_free(xcert);
558930a5e8faSwyllys 
559030a5e8faSwyllys 	return (ret);
559130a5e8faSwyllys 
559230a5e8faSwyllys }
559330a5e8faSwyllys 
559430a5e8faSwyllys KMF_RETURN
559530a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
559630a5e8faSwyllys {
559730a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
559830a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
559930a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
560030a5e8faSwyllys 	BIO		*bcrl = NULL;
560130a5e8faSwyllys 	X509_CRL   	*xcrl = NULL;
560230a5e8faSwyllys 	int		i;
560330a5e8faSwyllys 
560430a5e8faSwyllys 	if (handle == NULL || crlname == NULL) {
560530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
560630a5e8faSwyllys 	}
560730a5e8faSwyllys 
560830a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlname, &crl_format);
560930a5e8faSwyllys 	if (ret != KMF_OK)
561030a5e8faSwyllys 		return (ret);
561130a5e8faSwyllys 
561230a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
561330a5e8faSwyllys 	if (bcrl == NULL) {
561430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
561530a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
561630a5e8faSwyllys 		goto cleanup;
561730a5e8faSwyllys 	}
561830a5e8faSwyllys 
56195b3e1433Swyllys 	if (crl_format == KMF_FORMAT_ASN1)
562030a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
56215b3e1433Swyllys 	else if (crl_format == KMF_FORMAT_PEM)
562230a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
562330a5e8faSwyllys 
562430a5e8faSwyllys 	if (xcrl == NULL) {
562530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
562630a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
562730a5e8faSwyllys 		goto cleanup;
562830a5e8faSwyllys 	}
5629*300fdee2SAndy Fiddaman 	i = X509_cmp_time(X509_CRL_get0_lastUpdate(xcrl), NULL);
563030a5e8faSwyllys 	if (i >= 0) {
563130a5e8faSwyllys 		ret = KMF_ERR_VALIDITY_PERIOD;
563230a5e8faSwyllys 		goto cleanup;
563330a5e8faSwyllys 	}
5634*300fdee2SAndy Fiddaman 	if (X509_CRL_get0_nextUpdate(xcrl)) {
5635*300fdee2SAndy Fiddaman 		i = X509_cmp_time(X509_CRL_get0_nextUpdate(xcrl), NULL);
563630a5e8faSwyllys 
563730a5e8faSwyllys 		if (i <= 0) {
563830a5e8faSwyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
563930a5e8faSwyllys 			goto cleanup;
564030a5e8faSwyllys 		}
564130a5e8faSwyllys 	}
564230a5e8faSwyllys 
564330a5e8faSwyllys 	ret = KMF_OK;
564430a5e8faSwyllys 
564530a5e8faSwyllys cleanup:
564630a5e8faSwyllys 	if (bcrl != NULL)
564730a5e8faSwyllys 		(void) BIO_free(bcrl);
564830a5e8faSwyllys 
564930a5e8faSwyllys 	if (xcrl != NULL)
565030a5e8faSwyllys 		X509_CRL_free(xcrl);
565130a5e8faSwyllys 
565230a5e8faSwyllys 	return (ret);
565330a5e8faSwyllys }
5654