199ebb4caSwyllys /*
22c9a247fSWyllys Ingersoll  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
32c9a247fSWyllys Ingersoll  *
49a767088Shaimay  * Use is subject to license terms.
59a767088Shaimay  */
670f9559bSTheo Schlossnagle /*
770f9559bSTheo Schlossnagle  * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
8553e44ceSAndrew Stormont  * Copyright 2018 RackTop Systems.
94942e222SAndy Fiddaman  * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
1070f9559bSTheo Schlossnagle  */
119a767088Shaimay /*
129a767088Shaimay  * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
139a767088Shaimay  * project 2000.
149a767088Shaimay  */
159a767088Shaimay /*
169a767088Shaimay  * ====================================================================
179a767088Shaimay  * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
1899ebb4caSwyllys  *
199a767088Shaimay  * Redistribution and use in source and binary forms, with or without
209a767088Shaimay  * modification, are permitted provided that the following conditions
219a767088Shaimay  * are met:
2299ebb4caSwyllys  *
239a767088Shaimay  * 1. Redistributions of source code must retain the above copyright
249a767088Shaimay  *    notice, this list of conditions and the following disclaimer.
2599ebb4caSwyllys  *
269a767088Shaimay  * 2. Redistributions in binary form must reproduce the above copyright
279a767088Shaimay  *    notice, this list of conditions and the following disclaimer in
289a767088Shaimay  *    the documentation and/or other materials provided with the
299a767088Shaimay  *    distribution.
3099ebb4caSwyllys  *
319a767088Shaimay  * 3. All advertising materials mentioning features or use of this
329a767088Shaimay  *    software must display the following acknowledgment:
339a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
349a767088Shaimay  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
3599ebb4caSwyllys  *
369a767088Shaimay  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
379a767088Shaimay  *    endorse or promote products derived from this software without
389a767088Shaimay  *    prior written permission. For written permission, please contact
399a767088Shaimay  *    licensing@OpenSSL.org.
409a767088Shaimay  *
419a767088Shaimay  * 5. Products derived from this software may not be called "OpenSSL"
429a767088Shaimay  *    nor may "OpenSSL" appear in their names without prior written
439a767088Shaimay  *    permission of the OpenSSL Project.
449a767088Shaimay  *
459a767088Shaimay  * 6. Redistributions of any form whatsoever must retain the following
469a767088Shaimay  *    acknowledgment:
479a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
489a767088Shaimay  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
499a767088Shaimay  *
509a767088Shaimay  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
519a767088Shaimay  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
529a767088Shaimay  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
539a767088Shaimay  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
549a767088Shaimay  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
559a767088Shaimay  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
569a767088Shaimay  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
579a767088Shaimay  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
589a767088Shaimay  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
599a767088Shaimay  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
609a767088Shaimay  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
619a767088Shaimay  * OF THE POSSIBILITY OF SUCH DAMAGE.
629a767088Shaimay  * ====================================================================
639a767088Shaimay  *
649a767088Shaimay  * This product includes cryptographic software written by Eric Young
659a767088Shaimay  * (eay@cryptsoft.com).  This product includes software written by Tim
669a767088Shaimay  * Hudson (tjh@cryptsoft.com).
6799ebb4caSwyllys  *
6899ebb4caSwyllys  */
6999ebb4caSwyllys 
7071593db2Swyllys #include <stdlib.h>
7199ebb4caSwyllys #include <kmfapiP.h>
7299ebb4caSwyllys #include <ber_der.h>
7399ebb4caSwyllys #include <fcntl.h>
7499ebb4caSwyllys #include <sys/stat.h>
7599ebb4caSwyllys #include <dirent.h>
7699ebb4caSwyllys #include <cryptoutil.h>
7799ebb4caSwyllys #include <synch.h>
7899ebb4caSwyllys #include <thread.h>
7999ebb4caSwyllys 
8099ebb4caSwyllys /* OPENSSL related headers */
8199ebb4caSwyllys #include <openssl/bio.h>
8299ebb4caSwyllys #include <openssl/bn.h>
8399ebb4caSwyllys #include <openssl/asn1.h>
8499ebb4caSwyllys #include <openssl/err.h>
8599ebb4caSwyllys #include <openssl/x509.h>
8699ebb4caSwyllys #include <openssl/rsa.h>
8799ebb4caSwyllys #include <openssl/dsa.h>
8899ebb4caSwyllys #include <openssl/x509v3.h>
8999ebb4caSwyllys #include <openssl/objects.h>
9099ebb4caSwyllys #include <openssl/pem.h>
9199ebb4caSwyllys #include <openssl/pkcs12.h>
9299ebb4caSwyllys #include <openssl/ocsp.h>
9399ebb4caSwyllys #include <openssl/des.h>
9499ebb4caSwyllys #include <openssl/rand.h>
95300fdee2SAndy Fiddaman #include "compat.h"
9699ebb4caSwyllys 
9799ebb4caSwyllys #define	PRINT_ANY_EXTENSION (\
9899ebb4caSwyllys 	KMF_X509_EXT_KEY_USAGE |\
9999ebb4caSwyllys 	KMF_X509_EXT_CERT_POLICIES |\
10099ebb4caSwyllys 	KMF_X509_EXT_SUBJALTNAME |\
10199ebb4caSwyllys 	KMF_X509_EXT_BASIC_CONSTRAINTS |\
10299ebb4caSwyllys 	KMF_X509_EXT_NAME_CONSTRAINTS |\
10399ebb4caSwyllys 	KMF_X509_EXT_POLICY_CONSTRAINTS |\
10499ebb4caSwyllys 	KMF_X509_EXT_EXT_KEY_USAGE |\
10599ebb4caSwyllys 	KMF_X509_EXT_INHIBIT_ANY_POLICY |\
10699ebb4caSwyllys 	KMF_X509_EXT_AUTH_KEY_ID |\
10799ebb4caSwyllys 	KMF_X509_EXT_SUBJ_KEY_ID |\
10899ebb4caSwyllys 	KMF_X509_EXT_POLICY_MAPPING)
10999ebb4caSwyllys 
11099ebb4caSwyllys static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
11199ebb4caSwyllys 	0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
11299ebb4caSwyllys 	0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
11399ebb4caSwyllys 	0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
11499ebb4caSwyllys 	0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
11599ebb4caSwyllys 	0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
11699ebb4caSwyllys 	0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
11799ebb4caSwyllys 	0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
11899ebb4caSwyllys 	0x91 };
11999ebb4caSwyllys 
12099ebb4caSwyllys static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
12199ebb4caSwyllys 	0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
12299ebb4caSwyllys 	0x8e, 0xda, 0xce, 0x91, 0x5f };
12399ebb4caSwyllys 
12499ebb4caSwyllys static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
12599ebb4caSwyllys 	0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
12699ebb4caSwyllys 	0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
12799ebb4caSwyllys 	0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
12899ebb4caSwyllys 	0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
12999ebb4caSwyllys 	0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
13099ebb4caSwyllys 	0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
13199ebb4caSwyllys 	0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
13299ebb4caSwyllys 	0x02 };
13399ebb4caSwyllys 
13499ebb4caSwyllys #define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
13599ebb4caSwyllys 	h->lasterr.errcode = c;
13699ebb4caSwyllys 
13799ebb4caSwyllys #define	SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
13899ebb4caSwyllys 
1395b3e1433Swyllys /*
140bf5d9f18SAndy Fiddaman  * Declare some new macros for managing stacks of EVP_PKEYS.
1415b3e1433Swyllys  */
142553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
143*6ff4183cSAndy Fiddaman /* BEGIN CSTYLED */
1445b3e1433Swyllys DECLARE_STACK_OF(EVP_PKEY)
145*6ff4183cSAndy Fiddaman /* END CSTYLED */
1465b3e1433Swyllys 
1475b3e1433Swyllys #define	sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
1485b3e1433Swyllys #define	sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
1495b3e1433Swyllys #define	sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
1505b3e1433Swyllys #define	sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
1515b3e1433Swyllys #define	sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
1525b3e1433Swyllys #define	sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
1535b3e1433Swyllys 	(free_func))
1545b3e1433Swyllys 
155300fdee2SAndy Fiddaman #else
156*6ff4183cSAndy Fiddaman /* BEGIN CSTYLED */
157300fdee2SAndy Fiddaman DEFINE_STACK_OF(EVP_PKEY)
158*6ff4183cSAndy Fiddaman /* END CSTYLED */
159300fdee2SAndy Fiddaman #endif
160300fdee2SAndy Fiddaman 
16199ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX;
16299ebb4caSwyllys static int ssl_initialized = 0;
16330a5e8faSwyllys static BIO *bio_err = NULL;
16430a5e8faSwyllys 
1654942e222SAndy Fiddaman static int test_for_file(char *, mode_t);
1664942e222SAndy Fiddaman 
1674942e222SAndy Fiddaman static KMF_RETURN openssl_parse_bag(PKCS12_SAFEBAG *, char *, int,
1685b3e1433Swyllys     STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
1695b3e1433Swyllys 
1704942e222SAndy Fiddaman static KMF_RETURN local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int,
1714942e222SAndy Fiddaman     KMF_X509_DER_CERT *, int, KMF_KEY_HANDLE *, char *);
1725b3e1433Swyllys 
1735b3e1433Swyllys static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int);
17499ebb4caSwyllys 
1754942e222SAndy Fiddaman static KMF_RETURN extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *,
1764942e222SAndy Fiddaman     char *, CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
17771593db2Swyllys 
1784942e222SAndy Fiddaman static KMF_RETURN kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *,
1794942e222SAndy Fiddaman     KMF_CERT_VALIDITY, char *, KMF_DATA *);
18030a5e8faSwyllys 
1814942e222SAndy Fiddaman static KMF_RETURN load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *,
1824942e222SAndy Fiddaman     KMF_CERT_VALIDITY, char *, KMF_DATA **, uint32_t *);
18371593db2Swyllys 
1844942e222SAndy Fiddaman static KMF_RETURN sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
18502744e81Swyllys 
1864942e222SAndy Fiddaman static EVP_PKEY *ImportRawRSAKey(KMF_RAW_RSA_KEY *);
18702744e81Swyllys 
1884942e222SAndy Fiddaman static KMF_RETURN convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
18930a5e8faSwyllys 
1904942e222SAndy Fiddaman KMF_RETURN OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
19199ebb4caSwyllys 
1924942e222SAndy Fiddaman void OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
19399ebb4caSwyllys 
1944942e222SAndy Fiddaman KMF_RETURN OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
19599ebb4caSwyllys 
1964942e222SAndy Fiddaman KMF_RETURN OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
19799ebb4caSwyllys 
1984942e222SAndy Fiddaman KMF_RETURN OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
19930a5e8faSwyllys 
2004942e222SAndy Fiddaman KMF_RETURN OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20199ebb4caSwyllys 
2024942e222SAndy Fiddaman KMF_RETURN OpenSSL_EncodePubKeyData(KMF_HANDLE_T,  KMF_KEY_HANDLE *,
2034942e222SAndy Fiddaman     KMF_DATA *);
20499ebb4caSwyllys 
2054942e222SAndy Fiddaman KMF_RETURN OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
2064942e222SAndy Fiddaman     KMF_DATA *, KMF_DATA *);
20799ebb4caSwyllys 
2084942e222SAndy Fiddaman KMF_RETURN OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20999ebb4caSwyllys 
2104942e222SAndy Fiddaman KMF_RETURN OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21199ebb4caSwyllys 
2124942e222SAndy Fiddaman KMF_RETURN OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21399ebb4caSwyllys 
2144942e222SAndy Fiddaman KMF_RETURN OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21599ebb4caSwyllys 
2164942e222SAndy Fiddaman KMF_RETURN OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21799ebb4caSwyllys 
2184942e222SAndy Fiddaman KMF_RETURN OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
2194942e222SAndy Fiddaman     KMF_PRINTABLE_ITEM, char *);
22099ebb4caSwyllys 
2214942e222SAndy Fiddaman KMF_RETURN OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
22299ebb4caSwyllys 
2234942e222SAndy Fiddaman KMF_RETURN OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22499ebb4caSwyllys 
2254942e222SAndy Fiddaman KMF_RETURN OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
2264942e222SAndy Fiddaman     KMF_DATA *, KMF_DATA *);
22799ebb4caSwyllys 
2284942e222SAndy Fiddaman KMF_RETURN OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22999ebb4caSwyllys 
2304942e222SAndy Fiddaman KMF_RETURN OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23199ebb4caSwyllys 
2324942e222SAndy Fiddaman KMF_RETURN OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23399ebb4caSwyllys 
2344942e222SAndy Fiddaman KMF_RETURN OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23599ebb4caSwyllys 
2364942e222SAndy Fiddaman KMF_RETURN OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23799ebb4caSwyllys 
2384942e222SAndy Fiddaman KMF_RETURN OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *,
2394942e222SAndy Fiddaman     KMF_RAW_SYM_KEY *);
24099ebb4caSwyllys 
2414942e222SAndy Fiddaman KMF_RETURN OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
24299ebb4caSwyllys 
2434942e222SAndy Fiddaman KMF_RETURN OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
24499ebb4caSwyllys 
24599ebb4caSwyllys static
24699ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table =
24799ebb4caSwyllys {
24899ebb4caSwyllys 	1,				/* Version */
24999ebb4caSwyllys 	NULL, /* ConfigureKeystore */
25099ebb4caSwyllys 	OpenSSL_FindCert,
25199ebb4caSwyllys 	OpenSSL_FreeKMFCert,
25299ebb4caSwyllys 	OpenSSL_StoreCert,
25399ebb4caSwyllys 	NULL, /* ImportCert */
25499ebb4caSwyllys 	OpenSSL_ImportCRL,
25599ebb4caSwyllys 	OpenSSL_DeleteCert,
25699ebb4caSwyllys 	OpenSSL_DeleteCRL,
25799ebb4caSwyllys 	OpenSSL_CreateKeypair,
25899ebb4caSwyllys 	OpenSSL_FindKey,
25999ebb4caSwyllys 	OpenSSL_EncodePubKeyData,
26099ebb4caSwyllys 	OpenSSL_SignData,
26199ebb4caSwyllys 	OpenSSL_DeleteKey,
26299ebb4caSwyllys 	OpenSSL_ListCRL,
26399ebb4caSwyllys 	NULL,	/* FindCRL */
26499ebb4caSwyllys 	OpenSSL_FindCertInCRL,
26599ebb4caSwyllys 	OpenSSL_GetErrorString,
26630a5e8faSwyllys 	OpenSSL_FindPrikeyByCert,
26799ebb4caSwyllys 	OpenSSL_DecryptData,
26830a5e8faSwyllys 	OpenSSL_ExportPK12,
26999ebb4caSwyllys 	OpenSSL_CreateSymKey,
27099ebb4caSwyllys 	OpenSSL_GetSymKeyValue,
27199ebb4caSwyllys 	NULL,	/* SetTokenPin */
27230a5e8faSwyllys 	OpenSSL_StoreKey,
27399ebb4caSwyllys 	NULL	/* Finalize */
27499ebb4caSwyllys };
27599ebb4caSwyllys 
276553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
27799ebb4caSwyllys static mutex_t *lock_cs;
27899ebb4caSwyllys static long *lock_count;
27999ebb4caSwyllys 
28099ebb4caSwyllys static void
locking_cb(int mode,int type,char * file,int line)28199ebb4caSwyllys locking_cb(int mode, int type, char *file, int line)
28299ebb4caSwyllys {
28399ebb4caSwyllys 	if (mode & CRYPTO_LOCK) {
28499ebb4caSwyllys 		(void) mutex_lock(&(lock_cs[type]));
28599ebb4caSwyllys 		lock_count[type]++;
28699ebb4caSwyllys 	} else {
28799ebb4caSwyllys 		(void) mutex_unlock(&(lock_cs[type]));
28899ebb4caSwyllys 	}
28999ebb4caSwyllys }
29099ebb4caSwyllys 
29199ebb4caSwyllys static unsigned long
thread_id()29299ebb4caSwyllys thread_id()
29399ebb4caSwyllys {
29499ebb4caSwyllys 	return ((unsigned long)thr_self());
29599ebb4caSwyllys }
296553e44ceSAndrew Stormont #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER */
29799ebb4caSwyllys 
29899ebb4caSwyllys KMF_PLUGIN_FUNCLIST *
KMF_Plugin_Initialize()29999ebb4caSwyllys KMF_Plugin_Initialize()
30099ebb4caSwyllys {
301553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
30299ebb4caSwyllys 	int i;
303300fdee2SAndy Fiddaman #endif
30499ebb4caSwyllys 
30599ebb4caSwyllys 	(void) mutex_lock(&init_lock);
30699ebb4caSwyllys 	if (!ssl_initialized) {
30799ebb4caSwyllys 		/*
30899ebb4caSwyllys 		 * Add support for extension OIDs that are not yet in the
30999ebb4caSwyllys 		 * openssl default set.
31099ebb4caSwyllys 		 */
31199ebb4caSwyllys 		(void) OBJ_create("2.5.29.30", "nameConstraints",
31234acef67Swyllys 		    "X509v3 Name Constraints");
31399ebb4caSwyllys 		(void) OBJ_create("2.5.29.33", "policyMappings",
31434acef67Swyllys 		    "X509v3 Policy Mappings");
31599ebb4caSwyllys 		(void) OBJ_create("2.5.29.36", "policyConstraints",
31634acef67Swyllys 		    "X509v3 Policy Constraints");
31799ebb4caSwyllys 		(void) OBJ_create("2.5.29.46", "freshestCRL",
31834acef67Swyllys 		    "X509v3 Freshest CRL");
31999ebb4caSwyllys 		(void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
32034acef67Swyllys 		    "X509v3 Inhibit Any-Policy");
321300fdee2SAndy Fiddaman 
322553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
32399ebb4caSwyllys 		/*
32499ebb4caSwyllys 		 * Set up for thread-safe operation.
325300fdee2SAndy Fiddaman 		 * This is not required for OpenSSL 1.1
32699ebb4caSwyllys 		 */
32799ebb4caSwyllys 		lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
32899ebb4caSwyllys 		if (lock_cs == NULL) {
32999ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
33099ebb4caSwyllys 			return (NULL);
33199ebb4caSwyllys 		}
33299ebb4caSwyllys 
33399ebb4caSwyllys 		lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
33499ebb4caSwyllys 		if (lock_count == NULL) {
33599ebb4caSwyllys 			OPENSSL_free(lock_cs);
33699ebb4caSwyllys 			(void) mutex_unlock(&init_lock);
33799ebb4caSwyllys 			return (NULL);
33899ebb4caSwyllys 		}
33999ebb4caSwyllys 
34099ebb4caSwyllys 		for (i = 0; i < CRYPTO_num_locks(); i++) {
34199ebb4caSwyllys 			lock_count[i] = 0;
34299ebb4caSwyllys 			(void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
34399ebb4caSwyllys 		}
34499ebb4caSwyllys 
34599ebb4caSwyllys 		CRYPTO_set_id_callback((unsigned long (*)())thread_id);
3462c9a247fSWyllys Ingersoll 		if (CRYPTO_get_locking_callback() == NULL)
3472c9a247fSWyllys Ingersoll 			CRYPTO_set_locking_callback((void (*)())locking_cb);
3482c9a247fSWyllys Ingersoll 
349300fdee2SAndy Fiddaman 		(void) OpenSSL_add_all_algorithms();
3502c9a247fSWyllys Ingersoll 
3512c9a247fSWyllys Ingersoll 		/* Enable error strings for reporting */
352300fdee2SAndy Fiddaman 		(void) ERR_load_crypto_strings();
353300fdee2SAndy Fiddaman #endif
3542c9a247fSWyllys Ingersoll 
35599ebb4caSwyllys 		ssl_initialized = 1;
35699ebb4caSwyllys 	}
35799ebb4caSwyllys 	(void) mutex_unlock(&init_lock);
35899ebb4caSwyllys 
35999ebb4caSwyllys 	return (&openssl_plugin_table);
36099ebb4caSwyllys }
361300fdee2SAndy Fiddaman 
36299ebb4caSwyllys /*
36399ebb4caSwyllys  * Convert an SSL DN to a KMF DN.
36499ebb4caSwyllys  */
36599ebb4caSwyllys static KMF_RETURN
get_x509_dn(X509_NAME * sslDN,KMF_X509_NAME * kmfDN)36699ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
36799ebb4caSwyllys {
36899ebb4caSwyllys 	KMF_DATA derdata;
36999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
37099ebb4caSwyllys 	uchar_t *tmp;
37199ebb4caSwyllys 
37299ebb4caSwyllys 	/* Convert to raw DER format */
37399ebb4caSwyllys 	derdata.Length = i2d_X509_NAME(sslDN, NULL);
37499ebb4caSwyllys 	if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
37534acef67Swyllys 	    == NULL) {
37699ebb4caSwyllys 		return (KMF_ERR_MEMORY);
37799ebb4caSwyllys 	}
37899ebb4caSwyllys 	(void) i2d_X509_NAME(sslDN, &tmp);
37999ebb4caSwyllys 
38099ebb4caSwyllys 	/* Decode to KMF format */
38199ebb4caSwyllys 	rv = DerDecodeName(&derdata, kmfDN);
38299ebb4caSwyllys 	if (rv != KMF_OK) {
38399ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
38499ebb4caSwyllys 	}
38599ebb4caSwyllys 	OPENSSL_free(derdata.Data);
38699ebb4caSwyllys 
38799ebb4caSwyllys 	return (rv);
38899ebb4caSwyllys }
38999ebb4caSwyllys 
39030a5e8faSwyllys int
isdir(char * path)39199ebb4caSwyllys isdir(char *path)
39299ebb4caSwyllys {
39399ebb4caSwyllys 	struct stat s;
39499ebb4caSwyllys 
39599ebb4caSwyllys 	if (stat(path, &s) == -1)
39699ebb4caSwyllys 		return (0);
39799ebb4caSwyllys 
39830a5e8faSwyllys 	return ((s.st_mode & S_IFMT) == S_IFDIR);
39999ebb4caSwyllys }
40099ebb4caSwyllys 
40199ebb4caSwyllys static KMF_RETURN
ssl_cert2KMFDATA(KMF_HANDLE * kmfh,X509 * x509cert,KMF_DATA * cert)40299ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
40399ebb4caSwyllys {
40499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
40599ebb4caSwyllys 	unsigned char *buf = NULL, *p;
40699ebb4caSwyllys 	int len;
40799ebb4caSwyllys 
40899ebb4caSwyllys 	/*
40999ebb4caSwyllys 	 * Convert the X509 internal struct to DER encoded data
41099ebb4caSwyllys 	 */
41199ebb4caSwyllys 	if ((len = i2d_X509(x509cert, NULL)) < 0) {
41299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
41399ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
41499ebb4caSwyllys 		goto cleanup;
41599ebb4caSwyllys 	}
41699ebb4caSwyllys 	if ((buf = malloc(len)) == NULL) {
41799ebb4caSwyllys 		SET_SYS_ERROR(kmfh, errno);
41899ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
41999ebb4caSwyllys 		goto cleanup;
42099ebb4caSwyllys 	}
42199ebb4caSwyllys 
42299ebb4caSwyllys 	/*
42399ebb4caSwyllys 	 * i2d_X509 will increment the buf pointer so that we need to
42499ebb4caSwyllys 	 * save it.
42599ebb4caSwyllys 	 */
42699ebb4caSwyllys 	p = buf;
42799ebb4caSwyllys 	if ((len = i2d_X509(x509cert, &p)) < 0) {
42899ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
42999ebb4caSwyllys 		free(buf);
43099ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
43199ebb4caSwyllys 		goto cleanup;
43299ebb4caSwyllys 	}
43399ebb4caSwyllys 
43499ebb4caSwyllys 	/* caller's responsibility to free it */
43599ebb4caSwyllys 	cert->Data = buf;
43699ebb4caSwyllys 	cert->Length = len;
43799ebb4caSwyllys 
43899ebb4caSwyllys cleanup:
43999ebb4caSwyllys 	if (rv != KMF_OK) {
44099ebb4caSwyllys 		if (buf)
44199ebb4caSwyllys 			free(buf);
44299ebb4caSwyllys 		cert->Data = NULL;
44399ebb4caSwyllys 		cert->Length = 0;
44499ebb4caSwyllys 	}
44599ebb4caSwyllys 
44699ebb4caSwyllys 	return (rv);
44799ebb4caSwyllys }
44899ebb4caSwyllys 
44930a5e8faSwyllys 
45099ebb4caSwyllys static KMF_RETURN
check_cert(X509 * xcert,char * issuer,char * subject,KMF_BIGINT * serial,boolean_t * match)45130a5e8faSwyllys check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
45230a5e8faSwyllys     boolean_t *match)
45399ebb4caSwyllys {
45499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
45599ebb4caSwyllys 	boolean_t findIssuer = FALSE;
45699ebb4caSwyllys 	boolean_t findSubject = FALSE;
45799ebb4caSwyllys 	boolean_t findSerial = FALSE;
45899ebb4caSwyllys 	KMF_X509_NAME issuerDN, subjectDN;
45999ebb4caSwyllys 	KMF_X509_NAME certIssuerDN, certSubjectDN;
46099ebb4caSwyllys 
46199ebb4caSwyllys 	*match = FALSE;
46299ebb4caSwyllys 	if (xcert == NULL) {
46399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
46499ebb4caSwyllys 	}
46599ebb4caSwyllys 
46699ebb4caSwyllys 	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
46799ebb4caSwyllys 	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
46899ebb4caSwyllys 	(void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
46999ebb4caSwyllys 	(void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
47099ebb4caSwyllys 
47130a5e8faSwyllys 	if (issuer != NULL && strlen(issuer)) {
47230a5e8faSwyllys 		rv = kmf_dn_parser(issuer, &issuerDN);
47399ebb4caSwyllys 		if (rv != KMF_OK)
47499ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
47599ebb4caSwyllys 
476300fdee2SAndy Fiddaman 		rv = get_x509_dn(X509_get_issuer_name(xcert), &certIssuerDN);
47799ebb4caSwyllys 		if (rv != KMF_OK) {
47830a5e8faSwyllys 			kmf_free_dn(&issuerDN);
47999ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
48099ebb4caSwyllys 		}
48199ebb4caSwyllys 
48299ebb4caSwyllys 		findIssuer = TRUE;
48399ebb4caSwyllys 	}
48430a5e8faSwyllys 	if (subject != NULL && strlen(subject)) {
48530a5e8faSwyllys 		rv = kmf_dn_parser(subject, &subjectDN);
48699ebb4caSwyllys 		if (rv != KMF_OK) {
48799ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
48899ebb4caSwyllys 			goto cleanup;
48999ebb4caSwyllys 		}
49099ebb4caSwyllys 
491300fdee2SAndy Fiddaman 		rv = get_x509_dn(X509_get_subject_name(xcert), &certSubjectDN);
49299ebb4caSwyllys 		if (rv != KMF_OK) {
49399ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
49499ebb4caSwyllys 			goto cleanup;
49599ebb4caSwyllys 		}
49699ebb4caSwyllys 		findSubject = TRUE;
49799ebb4caSwyllys 	}
49830a5e8faSwyllys 	if (serial != NULL && serial->val != NULL)
49999ebb4caSwyllys 		findSerial = TRUE;
50099ebb4caSwyllys 
50199ebb4caSwyllys 	if (findSerial) {
50299ebb4caSwyllys 		BIGNUM *bn;
50399ebb4caSwyllys 
50499ebb4caSwyllys 		/* Comparing BIGNUMs is a pain! */
505300fdee2SAndy Fiddaman 		bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(xcert), NULL);
50699ebb4caSwyllys 		if (bn != NULL) {
50799ebb4caSwyllys 			int bnlen = BN_num_bytes(bn);
50899ebb4caSwyllys 
50930a5e8faSwyllys 			if (bnlen == serial->len) {
51099ebb4caSwyllys 				uchar_t *a = malloc(bnlen);
51199ebb4caSwyllys 				if (a == NULL) {
51299ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
51399ebb4caSwyllys 					BN_free(bn);
51499ebb4caSwyllys 					goto cleanup;
51599ebb4caSwyllys 				}
51699ebb4caSwyllys 				bnlen = BN_bn2bin(bn, a);
51730a5e8faSwyllys 				*match = (memcmp(a, serial->val, serial->len) ==
51830a5e8faSwyllys 				    0);
51999ebb4caSwyllys 				rv = KMF_OK;
52099ebb4caSwyllys 				free(a);
52199ebb4caSwyllys 			}
52299ebb4caSwyllys 			BN_free(bn);
52399ebb4caSwyllys 			if (!(*match))
52499ebb4caSwyllys 				goto cleanup;
52599ebb4caSwyllys 		} else {
52699ebb4caSwyllys 			rv = KMF_OK;
52799ebb4caSwyllys 			goto cleanup;
52899ebb4caSwyllys 		}
52999ebb4caSwyllys 	}
53099ebb4caSwyllys 	if (findIssuer) {
53130a5e8faSwyllys 		*match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
53230a5e8faSwyllys 		if ((*match) == B_FALSE) {
53330a5e8faSwyllys 			/* stop checking and bail */
53499ebb4caSwyllys 			rv = KMF_OK;
53599ebb4caSwyllys 			goto cleanup;
53699ebb4caSwyllys 		}
53799ebb4caSwyllys 	}
53899ebb4caSwyllys 	if (findSubject) {
53930a5e8faSwyllys 		*match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
54030a5e8faSwyllys 		if ((*match) == B_FALSE) {
54130a5e8faSwyllys 			/* stop checking and bail */
54299ebb4caSwyllys 			rv = KMF_OK;
54399ebb4caSwyllys 			goto cleanup;
54499ebb4caSwyllys 		}
54599ebb4caSwyllys 	}
54699ebb4caSwyllys 
54799ebb4caSwyllys 	*match = TRUE;
54899ebb4caSwyllys cleanup:
54999ebb4caSwyllys 	if (findIssuer) {
55030a5e8faSwyllys 		kmf_free_dn(&issuerDN);
55130a5e8faSwyllys 		kmf_free_dn(&certIssuerDN);
55299ebb4caSwyllys 	}
55399ebb4caSwyllys 	if (findSubject) {
55430a5e8faSwyllys 		kmf_free_dn(&subjectDN);
55530a5e8faSwyllys 		kmf_free_dn(&certSubjectDN);
55699ebb4caSwyllys 	}
55799ebb4caSwyllys 
55899ebb4caSwyllys 	return (rv);
55999ebb4caSwyllys }
56099ebb4caSwyllys 
56130a5e8faSwyllys 
56230a5e8faSwyllys /*
56330a5e8faSwyllys  * This function loads a certificate file into an X509 data structure, and
56430a5e8faSwyllys  * checks if its issuer, subject or the serial number matches with those
56530a5e8faSwyllys  * values.  If it matches, then return the X509 data structure.
56630a5e8faSwyllys  */
56799ebb4caSwyllys static KMF_RETURN
load_X509cert(KMF_HANDLE * kmfh,char * issuer,char * subject,KMF_BIGINT * serial,char * pathname,X509 ** outcert)5684942e222SAndy Fiddaman load_X509cert(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
56930a5e8faSwyllys     char *pathname, X509 **outcert)
57099ebb4caSwyllys {
57199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
57299ebb4caSwyllys 	X509 *xcert = NULL;
57399ebb4caSwyllys 	BIO *bcert = NULL;
57499ebb4caSwyllys 	boolean_t  match = FALSE;
57599ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
57699ebb4caSwyllys 
57799ebb4caSwyllys 	/*
57899ebb4caSwyllys 	 * auto-detect the file format, regardless of what
57999ebb4caSwyllys 	 * the 'format' parameters in the params say.
58099ebb4caSwyllys 	 */
58130a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
58299ebb4caSwyllys 	if (rv != KMF_OK) {
58399ebb4caSwyllys 		if (rv == KMF_ERR_OPEN_FILE)
58499ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
58599ebb4caSwyllys 		return (rv);
58699ebb4caSwyllys 	}
58799ebb4caSwyllys 
58899ebb4caSwyllys 	/* Not ASN1(DER) format */
58999ebb4caSwyllys 	if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
59099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
59199ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
59299ebb4caSwyllys 		goto cleanup;
59399ebb4caSwyllys 	}
59499ebb4caSwyllys 
59599ebb4caSwyllys 	if (format == KMF_FORMAT_PEM)
59699ebb4caSwyllys 		xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
59799ebb4caSwyllys 	else if (format == KMF_FORMAT_ASN1)
59899ebb4caSwyllys 		xcert = d2i_X509_bio(bcert, NULL);
59999ebb4caSwyllys 	else if (format == KMF_FORMAT_PKCS12) {
60099ebb4caSwyllys 		PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
60199ebb4caSwyllys 		if (p12 != NULL) {
60299ebb4caSwyllys 			(void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
60399ebb4caSwyllys 			PKCS12_free(p12);
60499ebb4caSwyllys 			p12 = NULL;
60599ebb4caSwyllys 		} else {
60699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
60799ebb4caSwyllys 			rv = KMF_ERR_BAD_CERT_FORMAT;
60899ebb4caSwyllys 		}
60999ebb4caSwyllys 	} else {
61099ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
61199ebb4caSwyllys 		goto cleanup;
61299ebb4caSwyllys 	}
61399ebb4caSwyllys 
61499ebb4caSwyllys 	if (xcert == NULL) {
61599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
61699ebb4caSwyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
61799ebb4caSwyllys 		goto cleanup;
61899ebb4caSwyllys 	}
61999ebb4caSwyllys 
62030a5e8faSwyllys 	if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
62130a5e8faSwyllys 	    match == FALSE) {
62299ebb4caSwyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
62399ebb4caSwyllys 		goto cleanup;
62499ebb4caSwyllys 	}
62599ebb4caSwyllys 
62699ebb4caSwyllys 	if (outcert != NULL) {
62799ebb4caSwyllys 		*outcert = xcert;
62899ebb4caSwyllys 	}
62999ebb4caSwyllys 
63099ebb4caSwyllys cleanup:
63199ebb4caSwyllys 	if (bcert != NULL) (void) BIO_free(bcert);
63299ebb4caSwyllys 	if (rv != KMF_OK && xcert != NULL)
63399ebb4caSwyllys 		X509_free(xcert);
63499ebb4caSwyllys 
63599ebb4caSwyllys 	return (rv);
63699ebb4caSwyllys }
63799ebb4caSwyllys 
63871593db2Swyllys static int
datacmp(const void * a,const void * b)63971593db2Swyllys datacmp(const void *a, const void *b)
64071593db2Swyllys {
64171593db2Swyllys 	KMF_DATA *adata = (KMF_DATA *)a;
64271593db2Swyllys 	KMF_DATA *bdata = (KMF_DATA *)b;
64371593db2Swyllys 	if (adata->Length > bdata->Length)
64471593db2Swyllys 		return (-1);
64571593db2Swyllys 	if (adata->Length < bdata->Length)
64671593db2Swyllys 		return (1);
64771593db2Swyllys 	return (0);
64871593db2Swyllys }
64971593db2Swyllys 
65071593db2Swyllys static KMF_RETURN
load_certs(KMF_HANDLE * kmfh,char * issuer,char * subject,KMF_BIGINT * serial,KMF_CERT_VALIDITY validity,char * pathname,KMF_DATA ** certlist,uint32_t * numcerts)65130a5e8faSwyllys load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
65230a5e8faSwyllys     KMF_CERT_VALIDITY validity, char *pathname,
65330a5e8faSwyllys     KMF_DATA **certlist, uint32_t *numcerts)
65471593db2Swyllys {
65571593db2Swyllys 	KMF_RETURN rv = KMF_OK;
65671593db2Swyllys 	int i;
65771593db2Swyllys 	KMF_DATA *certs = NULL;
65871593db2Swyllys 	int nc = 0;
65971593db2Swyllys 	int hits = 0;
66071593db2Swyllys 	KMF_ENCODE_FORMAT format;
66171593db2Swyllys 
66230a5e8faSwyllys 	rv = kmf_get_file_format(pathname, &format);
66371593db2Swyllys 	if (rv != KMF_OK) {
66471593db2Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
66571593db2Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
66671593db2Swyllys 		return (rv);
66771593db2Swyllys 	}
66871593db2Swyllys 	if (format == KMF_FORMAT_ASN1) {
66971593db2Swyllys 		/* load a single certificate */
67071593db2Swyllys 		certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
67171593db2Swyllys 		if (certs == NULL)
67271593db2Swyllys 			return (KMF_ERR_MEMORY);
67371593db2Swyllys 		certs->Data = NULL;
67471593db2Swyllys 		certs->Length = 0;
67530a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
67630a5e8faSwyllys 		    pathname, certs);
67771593db2Swyllys 		if (rv == KMF_OK) {
67871593db2Swyllys 			*certlist = certs;
67971593db2Swyllys 			*numcerts = 1;
680a2d4930dSDan OpenSolaris Anderson 		} else {
681a2d4930dSDan OpenSolaris Anderson 			kmf_free_data(certs);
682a2d4930dSDan OpenSolaris Anderson 			free(certs);
683a2d4930dSDan OpenSolaris Anderson 			certs = NULL;
68471593db2Swyllys 		}
68571593db2Swyllys 		return (rv);
68671593db2Swyllys 	} else if (format == KMF_FORMAT_PKCS12) {
68771593db2Swyllys 		/* We need a credential to access a PKCS#12 file */
68871593db2Swyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
68971593db2Swyllys 	} else if (format == KMF_FORMAT_PEM ||
69034acef67Swyllys 	    format != KMF_FORMAT_PEM_KEYPAIR) {
691e65e5c2dSWyllys Ingersoll 
69271593db2Swyllys 		/* This function only works on PEM files */
69330a5e8faSwyllys 		rv = extract_pem(kmfh, issuer, subject, serial, pathname,
69434acef67Swyllys 		    (uchar_t *)NULL, 0, NULL, &certs, &nc);
69571593db2Swyllys 	} else {
69671593db2Swyllys 		return (KMF_ERR_ENCODING);
69771593db2Swyllys 	}
69871593db2Swyllys 
69971593db2Swyllys 	if (rv != KMF_OK)
70071593db2Swyllys 		return (rv);
70171593db2Swyllys 
70271593db2Swyllys 	for (i = 0; i < nc; i++) {
70330a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
70430a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
70530a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
70630a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
70771593db2Swyllys 			if (rv == KMF_OK)
70871593db2Swyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
70971593db2Swyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD)
71071593db2Swyllys 				rv = KMF_OK;
71171593db2Swyllys 		}
71271593db2Swyllys 		if (rv != KMF_OK) {
71371593db2Swyllys 			/* Remove this cert from the list by clearing it. */
71430a5e8faSwyllys 			kmf_free_data(&certs[i]);
71571593db2Swyllys 		} else {
71671593db2Swyllys 			hits++; /* count valid certs found */
71771593db2Swyllys 		}
71871593db2Swyllys 		rv = KMF_OK;
71971593db2Swyllys 	}
720a2d4930dSDan OpenSolaris Anderson 	if (rv == KMF_OK && hits > 0) {
72171593db2Swyllys 		/*
72271593db2Swyllys 		 * Sort the list of certs by length to put the cleared ones
72371593db2Swyllys 		 * at the end so they don't get accessed by the caller.
72471593db2Swyllys 		 */
72571593db2Swyllys 		qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
72671593db2Swyllys 		*certlist = certs;
72771593db2Swyllys 
72871593db2Swyllys 		/* since we sorted the list, just return the number of hits */
72971593db2Swyllys 		*numcerts = hits;
730a2d4930dSDan OpenSolaris Anderson 	} else {
731e65e5c2dSWyllys Ingersoll 		if (rv == KMF_OK && hits == 0)
732a2d4930dSDan OpenSolaris Anderson 			rv = KMF_ERR_CERT_NOT_FOUND;
733a2d4930dSDan OpenSolaris Anderson 		if (certs != NULL) {
734a2d4930dSDan OpenSolaris Anderson 			free(certs);
735a2d4930dSDan OpenSolaris Anderson 			certs = NULL;
736a2d4930dSDan OpenSolaris Anderson 		}
73771593db2Swyllys 	}
73871593db2Swyllys 	return (rv);
73971593db2Swyllys }
74071593db2Swyllys 
74199ebb4caSwyllys static KMF_RETURN
kmf_load_cert(KMF_HANDLE * kmfh,char * issuer,char * subject,KMF_BIGINT * serial,KMF_CERT_VALIDITY validity,char * pathname,KMF_DATA * cert)7424942e222SAndy Fiddaman kmf_load_cert(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
7434942e222SAndy Fiddaman     KMF_CERT_VALIDITY validity, char *pathname, KMF_DATA *cert)
74499ebb4caSwyllys {
74599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
74699ebb4caSwyllys 	X509 *x509cert = NULL;
74799ebb4caSwyllys 
74830a5e8faSwyllys 	rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
74999ebb4caSwyllys 	if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
75099ebb4caSwyllys 		rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
75199ebb4caSwyllys 		if (rv != KMF_OK) {
75299ebb4caSwyllys 			goto cleanup;
75399ebb4caSwyllys 		}
75430a5e8faSwyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
75530a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
75630a5e8faSwyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
75730a5e8faSwyllys 			rv = kmf_check_cert_date(kmfh, cert);
75899ebb4caSwyllys 			if (rv == KMF_OK)  {
75999ebb4caSwyllys 				/*
76099ebb4caSwyllys 				 * This is a valid cert so skip it.
76199ebb4caSwyllys 				 */
76299ebb4caSwyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
76399ebb4caSwyllys 			}
76499ebb4caSwyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD) {
76599ebb4caSwyllys 				/*
76699ebb4caSwyllys 				 * We want to return success when we
76799ebb4caSwyllys 				 * find an invalid cert.
76899ebb4caSwyllys 				 */
76999ebb4caSwyllys 				rv = KMF_OK;
77099ebb4caSwyllys 				goto cleanup;
77199ebb4caSwyllys 			}
77299ebb4caSwyllys 		}
77399ebb4caSwyllys 	}
77499ebb4caSwyllys cleanup:
77599ebb4caSwyllys 	if (x509cert != NULL)
77699ebb4caSwyllys 		X509_free(x509cert);
77799ebb4caSwyllys 
77899ebb4caSwyllys 	return (rv);
77999ebb4caSwyllys }
78099ebb4caSwyllys 
78102744e81Swyllys static KMF_RETURN
readAltFormatPrivateKey(KMF_DATA * filedata,EVP_PKEY ** pkey)78202744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
78302744e81Swyllys {
78402744e81Swyllys 	KMF_RETURN ret = KMF_OK;
78502744e81Swyllys 	KMF_RAW_RSA_KEY rsa;
78602744e81Swyllys 	BerElement *asn1 = NULL;
78702744e81Swyllys 	BerValue filebuf;
788f810c7e5SToomas Soome 	BerValue OID = { 0, 0 };
78902744e81Swyllys 	BerValue *Mod = NULL, *PubExp = NULL;
79002744e81Swyllys 	BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
79102744e81Swyllys 	BerValue *Coef = NULL;
79202744e81Swyllys 	BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
79302744e81Swyllys 	BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
79402744e81Swyllys 	BIGNUM *qminus1 = NULL;
79502744e81Swyllys 	BN_CTX *ctx = NULL;
79602744e81Swyllys 
79702744e81Swyllys 	*pkey = NULL;
79802744e81Swyllys 
79902744e81Swyllys 	filebuf.bv_val = (char *)filedata->Data;
80002744e81Swyllys 	filebuf.bv_len = filedata->Length;
80102744e81Swyllys 
80202744e81Swyllys 	asn1 = kmfder_init(&filebuf);
80302744e81Swyllys 	if (asn1 == NULL) {
80402744e81Swyllys 		ret = KMF_ERR_MEMORY;
80502744e81Swyllys 		goto out;
80602744e81Swyllys 	}
80702744e81Swyllys 
80802744e81Swyllys 	if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
80934acef67Swyllys 	    &OID, &Mod, &PubExp, &PriExp, &Prime1,
81034acef67Swyllys 	    &Prime2, &Coef) == -1)  {
81102744e81Swyllys 		ret = KMF_ERR_ENCODING;
81202744e81Swyllys 		goto out;
81302744e81Swyllys 	}
81402744e81Swyllys 
81502744e81Swyllys 	/*
81602744e81Swyllys 	 * We have to derive the 2 Exponents using Bignumber math.
81702744e81Swyllys 	 * Exp1 = PriExp mod (Prime1 - 1)
81802744e81Swyllys 	 * Exp2 = PriExp mod (Prime2 - 1)
81902744e81Swyllys 	 */
82002744e81Swyllys 
82102744e81Swyllys 	/* D = PrivateExponent */
82202744e81Swyllys 	D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
82302744e81Swyllys 	if (D == NULL) {
82402744e81Swyllys 		ret = KMF_ERR_MEMORY;
82502744e81Swyllys 		goto out;
82602744e81Swyllys 	}
82702744e81Swyllys 
82802744e81Swyllys 	/* P = Prime1 (first prime factor of Modulus) */
82902744e81Swyllys 	P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
83002744e81Swyllys 	if (D == NULL) {
83102744e81Swyllys 		ret = KMF_ERR_MEMORY;
83202744e81Swyllys 		goto out;
83302744e81Swyllys 	}
83402744e81Swyllys 
83502744e81Swyllys 	/* Q = Prime2 (second prime factor of Modulus) */
83602744e81Swyllys 	Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
83702744e81Swyllys 
83802744e81Swyllys 	if ((ctx = BN_CTX_new()) == NULL) {
83902744e81Swyllys 		ret = KMF_ERR_MEMORY;
84002744e81Swyllys 		goto out;
84102744e81Swyllys 	}
84202744e81Swyllys 
84302744e81Swyllys 	/* Compute (P - 1) */
84402744e81Swyllys 	pminus1 = BN_new();
84502744e81Swyllys 	(void) BN_sub(pminus1, P, BN_value_one());
84602744e81Swyllys 
84702744e81Swyllys 	/* Exponent1 = D mod (P - 1) */
84802744e81Swyllys 	Exp1 = BN_new();
84902744e81Swyllys 	(void) BN_mod(Exp1, D, pminus1, ctx);
85002744e81Swyllys 
85102744e81Swyllys 	/* Compute (Q - 1) */
85202744e81Swyllys 	qminus1 = BN_new();
85302744e81Swyllys 	(void) BN_sub(qminus1, Q, BN_value_one());
85402744e81Swyllys 
85502744e81Swyllys 	/* Exponent2 = D mod (Q - 1) */
85602744e81Swyllys 	Exp2 = BN_new();
85702744e81Swyllys 	(void) BN_mod(Exp2, D, qminus1, ctx);
85802744e81Swyllys 
85902744e81Swyllys 	/* Coef = (Inverse Q) mod P */
86002744e81Swyllys 	COEF = BN_new();
86102744e81Swyllys 	(void) BN_mod_inverse(COEF, Q, P, ctx);
86202744e81Swyllys 
86302744e81Swyllys 	/* Convert back to KMF format */
86402744e81Swyllys 	(void) memset(&rsa, 0, sizeof (rsa));
86502744e81Swyllys 
86602744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
86702744e81Swyllys 		goto out;
86802744e81Swyllys 	if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
86902744e81Swyllys 		goto out;
87002744e81Swyllys 	if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
87102744e81Swyllys 		goto out;
87202744e81Swyllys 
87302744e81Swyllys 	rsa.mod.val = (uchar_t *)Mod->bv_val;
87402744e81Swyllys 	rsa.mod.len = Mod->bv_len;
87502744e81Swyllys 
87602744e81Swyllys 	rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
87702744e81Swyllys 	rsa.pubexp.len = PubExp->bv_len;
87802744e81Swyllys 
87902744e81Swyllys 	rsa.priexp.val = (uchar_t *)PriExp->bv_val;
88002744e81Swyllys 	rsa.priexp.len = PriExp->bv_len;
88102744e81Swyllys 
88202744e81Swyllys 	rsa.prime1.val = (uchar_t *)Prime1->bv_val;
88302744e81Swyllys 	rsa.prime1.len = Prime1->bv_len;
88402744e81Swyllys 
88502744e81Swyllys 	rsa.prime2.val = (uchar_t *)Prime2->bv_val;
88602744e81Swyllys 	rsa.prime2.len = Prime2->bv_len;
88702744e81Swyllys 
88802744e81Swyllys 	*pkey = ImportRawRSAKey(&rsa);
88902744e81Swyllys out:
89002744e81Swyllys 	if (asn1 != NULL)
89102744e81Swyllys 		kmfber_free(asn1, 1);
89202744e81Swyllys 
89302744e81Swyllys 	if (OID.bv_val) {
89402744e81Swyllys 		free(OID.bv_val);
89502744e81Swyllys 	}
89602744e81Swyllys 	if (PriExp)
89702744e81Swyllys 		free(PriExp);
89802744e81Swyllys 
89902744e81Swyllys 	if (Mod)
90002744e81Swyllys 		free(Mod);
90102744e81Swyllys 
90202744e81Swyllys 	if (PubExp)
90302744e81Swyllys 		free(PubExp);
90402744e81Swyllys 
90502744e81Swyllys 	if (Coef) {
90602744e81Swyllys 		(void) memset(Coef->bv_val, 0, Coef->bv_len);
90702744e81Swyllys 		free(Coef->bv_val);
90802744e81Swyllys 		free(Coef);
90902744e81Swyllys 	}
91002744e81Swyllys 	if (Prime1)
91102744e81Swyllys 		free(Prime1);
91202744e81Swyllys 	if (Prime2)
91302744e81Swyllys 		free(Prime2);
91402744e81Swyllys 
91502744e81Swyllys 	if (ctx != NULL)
91602744e81Swyllys 		BN_CTX_free(ctx);
91702744e81Swyllys 
91802744e81Swyllys 	if (D)
91902744e81Swyllys 		BN_clear_free(D);
92002744e81Swyllys 	if (P)
92102744e81Swyllys 		BN_clear_free(P);
92202744e81Swyllys 	if (Q)
92302744e81Swyllys 		BN_clear_free(Q);
92402744e81Swyllys 	if (pminus1)
92502744e81Swyllys 		BN_clear_free(pminus1);
92602744e81Swyllys 	if (qminus1)
92702744e81Swyllys 		BN_clear_free(qminus1);
92802744e81Swyllys 	if (Exp1)
92902744e81Swyllys 		BN_clear_free(Exp1);
93002744e81Swyllys 	if (Exp2)
93102744e81Swyllys 		BN_clear_free(Exp2);
93202744e81Swyllys 
93302744e81Swyllys 	return (ret);
93402744e81Swyllys 
93502744e81Swyllys }
93602744e81Swyllys 
93799ebb4caSwyllys static EVP_PKEY *
openssl_load_key(KMF_HANDLE_T handle,const char * file)93899ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file)
93999ebb4caSwyllys {
94099ebb4caSwyllys 	BIO *keyfile = NULL;
94199ebb4caSwyllys 	EVP_PKEY *pkey = NULL;
94299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
94399ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
94402744e81Swyllys 	KMF_RETURN rv;
94502744e81Swyllys 	KMF_DATA filedata;
94699ebb4caSwyllys 
94799ebb4caSwyllys 	if (file == NULL) {
94899ebb4caSwyllys 		return (NULL);
94999ebb4caSwyllys 	}
95099ebb4caSwyllys 
95130a5e8faSwyllys 	if (kmf_get_file_format((char *)file, &format) != KMF_OK)
95299ebb4caSwyllys 		return (NULL);
95399ebb4caSwyllys 
95499ebb4caSwyllys 	keyfile = BIO_new_file(file, "rb");
95599ebb4caSwyllys 	if (keyfile == NULL) {
95699ebb4caSwyllys 		goto end;
95799ebb4caSwyllys 	}
95899ebb4caSwyllys 
95902744e81Swyllys 	if (format == KMF_FORMAT_ASN1) {
96099ebb4caSwyllys 		pkey = d2i_PrivateKey_bio(keyfile, NULL);
96102744e81Swyllys 		if (pkey == NULL) {
96202744e81Swyllys 
96302744e81Swyllys 			(void) BIO_free(keyfile);
96402744e81Swyllys 			keyfile = NULL;
96502744e81Swyllys 			/* Try odd ASN.1 variations */
96630a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
96734acef67Swyllys 			    &filedata);
96802744e81Swyllys 			if (rv == KMF_OK) {
96902744e81Swyllys 				(void) readAltFormatPrivateKey(&filedata,
97034acef67Swyllys 				    &pkey);
97130a5e8faSwyllys 				kmf_free_data(&filedata);
97202744e81Swyllys 			}
97302744e81Swyllys 		}
97402744e81Swyllys 	} else if (format == KMF_FORMAT_PEM ||
97534acef67Swyllys 	    format == KMF_FORMAT_PEM_KEYPAIR) {
97699ebb4caSwyllys 		pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
97702744e81Swyllys 		if (pkey == NULL) {
97802744e81Swyllys 			KMF_DATA derdata;
97902744e81Swyllys 			/*
98002744e81Swyllys 			 * Check if this is the alt. format
98102744e81Swyllys 			 * RSA private key file.
98202744e81Swyllys 			 */
98330a5e8faSwyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
98434acef67Swyllys 			    &filedata);
98502744e81Swyllys 			if (rv == KMF_OK) {
98602744e81Swyllys 				uchar_t *d = NULL;
98702744e81Swyllys 				int len;
98830a5e8faSwyllys 				rv = kmf_pem_to_der(filedata.Data,
98934acef67Swyllys 				    filedata.Length, &d, &len);
99002744e81Swyllys 				if (rv == KMF_OK && d != NULL) {
99102744e81Swyllys 					derdata.Data = d;
99202744e81Swyllys 					derdata.Length = (size_t)len;
99302744e81Swyllys 					(void) readAltFormatPrivateKey(
99434acef67Swyllys 					    &derdata, &pkey);
99502744e81Swyllys 					free(d);
99602744e81Swyllys 				}
99730a5e8faSwyllys 				kmf_free_data(&filedata);
99802744e81Swyllys 			}
99902744e81Swyllys 		}
100002744e81Swyllys 	}
100199ebb4caSwyllys 
100299ebb4caSwyllys end:
1003a50e8766SToomas Soome 	if (pkey == NULL) {
100499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
1005a50e8766SToomas Soome 	}
100699ebb4caSwyllys 
100799ebb4caSwyllys 	if (keyfile != NULL)
100899ebb4caSwyllys 		(void) BIO_free(keyfile);
100999ebb4caSwyllys 
101099ebb4caSwyllys 	return (pkey);
101199ebb4caSwyllys }
101299ebb4caSwyllys 
101399ebb4caSwyllys KMF_RETURN
OpenSSL_FindCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)101430a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
101599ebb4caSwyllys {
101699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
101799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1018f482c776Swyllys 	int i, n;
1019f482c776Swyllys 	uint32_t maxcerts = 0;
102030a5e8faSwyllys 	uint32_t *num_certs;
102130a5e8faSwyllys 	KMF_X509_DER_CERT *kmf_cert = NULL;
102230a5e8faSwyllys 	char *dirpath = NULL;
102330a5e8faSwyllys 	char *filename = NULL;
102430a5e8faSwyllys 	char *fullpath = NULL;
102530a5e8faSwyllys 	char *issuer = NULL;
102630a5e8faSwyllys 	char *subject = NULL;
102730a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
102830a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
102999ebb4caSwyllys 
103030a5e8faSwyllys 	num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
103130a5e8faSwyllys 	if (num_certs == NULL)
103299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
103399ebb4caSwyllys 
103430a5e8faSwyllys 	/* num_certs should reference the size of kmf_cert */
1035f482c776Swyllys 	maxcerts = *num_certs;
1036f482c776Swyllys 	if (maxcerts == 0)
1037f482c776Swyllys 		maxcerts = 0xFFFFFFFF;
103899ebb4caSwyllys 	*num_certs = 0;
103999ebb4caSwyllys 
104030a5e8faSwyllys 	/* Get the optional returned certificate list  */
104130a5e8faSwyllys 	kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
104230a5e8faSwyllys 	    numattr);
104330a5e8faSwyllys 
104430a5e8faSwyllys 	/*
104530a5e8faSwyllys 	 * The dirpath attribute and the filename attribute can not be NULL
104630a5e8faSwyllys 	 * at the same time.
104730a5e8faSwyllys 	 */
104830a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
104930a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
105030a5e8faSwyllys 	    numattr);
105199ebb4caSwyllys 
105230a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
105399ebb4caSwyllys 	if (fullpath == NULL)
105499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
105599ebb4caSwyllys 
105630a5e8faSwyllys 	/* Get optional search criteria attributes */
105730a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
105830a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
105930a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
106030a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
106130a5e8faSwyllys 	    &validity, NULL);
106230a5e8faSwyllys 	if (rv != KMF_OK) {
106330a5e8faSwyllys 		validity = KMF_ALL_CERTS;
106430a5e8faSwyllys 		rv = KMF_OK;
106530a5e8faSwyllys 	}
106630a5e8faSwyllys 
106799ebb4caSwyllys 	if (isdir(fullpath)) {
106899ebb4caSwyllys 		DIR *dirp;
106999ebb4caSwyllys 		struct dirent *dp;
107099ebb4caSwyllys 
1071f482c776Swyllys 		n = 0;
107299ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
107399ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
107499ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
107599ebb4caSwyllys 		}
107699ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
107799ebb4caSwyllys 			char *fname;
107871593db2Swyllys 			KMF_DATA *certlist = NULL;
1079f482c776Swyllys 			uint32_t loaded_certs = 0;
108071593db2Swyllys 
108199ebb4caSwyllys 			if (strcmp(dp->d_name, ".") == 0 ||
108299ebb4caSwyllys 			    strcmp(dp->d_name, "..") == 0)
108399ebb4caSwyllys 				continue;
108499ebb4caSwyllys 
108534acef67Swyllys 			fname = get_fullpath(fullpath, (char *)&dp->d_name);
108699ebb4caSwyllys 
108730a5e8faSwyllys 			rv = load_certs(kmfh, issuer, subject, serial,
108830a5e8faSwyllys 			    validity, fname, &certlist,	&loaded_certs);
108999ebb4caSwyllys 
109099ebb4caSwyllys 			if (rv != KMF_OK) {
109199ebb4caSwyllys 				free(fname);
109271593db2Swyllys 				if (certlist != NULL) {
1093f482c776Swyllys 					for (i = 0; i < loaded_certs; i++)
109430a5e8faSwyllys 						kmf_free_data(&certlist[i]);
109571593db2Swyllys 					free(certlist);
109671593db2Swyllys 				}
109799ebb4caSwyllys 				continue;
109899ebb4caSwyllys 			}
109999ebb4caSwyllys 
110099ebb4caSwyllys 			/* If load succeeds, add certdata to the list */
110199ebb4caSwyllys 			if (kmf_cert != NULL) {
1102f482c776Swyllys 				for (i = 0; i < loaded_certs &&
1103b4058258Swyllys 				    n < maxcerts; i++) {
110471593db2Swyllys 					kmf_cert[n].certificate.Data =
110534acef67Swyllys 					    certlist[i].Data;
110671593db2Swyllys 					kmf_cert[n].certificate.Length =
110734acef67Swyllys 					    certlist[i].Length;
110871593db2Swyllys 
110971593db2Swyllys 					kmf_cert[n].kmf_private.keystore_type =
111034acef67Swyllys 					    KMF_KEYSTORE_OPENSSL;
111171593db2Swyllys 					kmf_cert[n].kmf_private.flags =
111234acef67Swyllys 					    KMF_FLAG_CERT_VALID;
111371593db2Swyllys 					kmf_cert[n].kmf_private.label =
111434acef67Swyllys 					    strdup(fname);
111571593db2Swyllys 					n++;
111671593db2Swyllys 				}
1117b4058258Swyllys 				/*
1118b4058258Swyllys 				 * If maxcerts < loaded_certs, clean up the
1119b4058258Swyllys 				 * certs that were not used.
1120b4058258Swyllys 				 */
1121f482c776Swyllys 				for (; i < loaded_certs; i++)
112230a5e8faSwyllys 					kmf_free_data(&certlist[i]);
112399ebb4caSwyllys 			} else {
1124f482c776Swyllys 				for (i = 0; i < loaded_certs; i++)
112530a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1126f482c776Swyllys 				n += loaded_certs;
112799ebb4caSwyllys 			}
1128f482c776Swyllys 			free(certlist);
112971593db2Swyllys 			free(fname);
113099ebb4caSwyllys 		}
113199ebb4caSwyllys 		(*num_certs) = n;
113299ebb4caSwyllys 		if (*num_certs == 0)
113399ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
113430a5e8faSwyllys 		if (*num_certs > 0)
113599ebb4caSwyllys 			rv = KMF_OK;
113699ebb4caSwyllys exit:
113799ebb4caSwyllys 		(void) closedir(dirp);
113899ebb4caSwyllys 	} else {
113971593db2Swyllys 		KMF_DATA *certlist = NULL;
1140f482c776Swyllys 		uint32_t loaded_certs = 0;
114171593db2Swyllys 
114230a5e8faSwyllys 		rv = load_certs(kmfh, issuer, subject, serial, validity,
114330a5e8faSwyllys 		    fullpath, &certlist, &loaded_certs);
114499ebb4caSwyllys 		if (rv != KMF_OK) {
114599ebb4caSwyllys 			free(fullpath);
114699ebb4caSwyllys 			return (rv);
114799ebb4caSwyllys 		}
114899ebb4caSwyllys 
1149f482c776Swyllys 		n = 0;
115071593db2Swyllys 		if (kmf_cert != NULL && certlist != NULL) {
1151f482c776Swyllys 			for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1152f482c776Swyllys 				kmf_cert[n].certificate.Data =
115334acef67Swyllys 				    certlist[i].Data;
1154f482c776Swyllys 				kmf_cert[n].certificate.Length =
115534acef67Swyllys 				    certlist[i].Length;
1156f482c776Swyllys 				kmf_cert[n].kmf_private.keystore_type =
115734acef67Swyllys 				    KMF_KEYSTORE_OPENSSL;
1158f482c776Swyllys 				kmf_cert[n].kmf_private.flags =
115934acef67Swyllys 				    KMF_FLAG_CERT_VALID;
1160f482c776Swyllys 				kmf_cert[n].kmf_private.label =
116134acef67Swyllys 				    strdup(fullpath);
1162f482c776Swyllys 				n++;
116371593db2Swyllys 			}
1164f482c776Swyllys 			/* If maxcerts < loaded_certs, clean up */
1165f482c776Swyllys 			for (; i < loaded_certs; i++)
116630a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1167f482c776Swyllys 		} else if (certlist != NULL) {
1168f482c776Swyllys 			for (i = 0; i < loaded_certs; i++)
116930a5e8faSwyllys 				kmf_free_data(&certlist[i]);
1170f482c776Swyllys 			n = loaded_certs;
1171f482c776Swyllys 		}
117230a5e8faSwyllys 		if (certlist != NULL)
117371593db2Swyllys 			free(certlist);
1174f482c776Swyllys 		*num_certs = n;
117599ebb4caSwyllys 	}
117699ebb4caSwyllys 
117771593db2Swyllys 	free(fullpath);
117899ebb4caSwyllys 
117999ebb4caSwyllys 	return (rv);
118099ebb4caSwyllys }
118199ebb4caSwyllys 
118299ebb4caSwyllys void
OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,KMF_X509_DER_CERT * kmf_cert)11834942e222SAndy Fiddaman OpenSSL_FreeKMFCert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
118499ebb4caSwyllys {
118599ebb4caSwyllys 	if (kmf_cert != NULL) {
118699ebb4caSwyllys 		if (kmf_cert->certificate.Data != NULL) {
1187e65e5c2dSWyllys Ingersoll 			kmf_free_data(&kmf_cert->certificate);
118899ebb4caSwyllys 		}
118999ebb4caSwyllys 		if (kmf_cert->kmf_private.label)
119099ebb4caSwyllys 			free(kmf_cert->kmf_private.label);
119199ebb4caSwyllys 	}
119299ebb4caSwyllys }
119399ebb4caSwyllys 
119499ebb4caSwyllys KMF_RETURN
OpenSSL_StoreCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)119530a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
119699ebb4caSwyllys {
119799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
119830a5e8faSwyllys 	KMF_DATA *cert = NULL;
119930a5e8faSwyllys 	char *outfilename = NULL;
120030a5e8faSwyllys 	char *dirpath = NULL;
120130a5e8faSwyllys 	char *fullpath = NULL;
120299ebb4caSwyllys 	KMF_ENCODE_FORMAT format;
120399ebb4caSwyllys 
120430a5e8faSwyllys 	/* Get the cert data */
120530a5e8faSwyllys 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
120630a5e8faSwyllys 	if (cert == NULL || cert->Data == NULL)
120799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
120899ebb4caSwyllys 
120930a5e8faSwyllys 	/* Check the output filename and directory attributes. */
121030a5e8faSwyllys 	outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
121130a5e8faSwyllys 	    numattr);
121230a5e8faSwyllys 	if (outfilename == NULL)
121399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
121499ebb4caSwyllys 
121530a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
121630a5e8faSwyllys 	fullpath = get_fullpath(dirpath, outfilename);
121730a5e8faSwyllys 	if (fullpath == NULL)
121830a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
121999ebb4caSwyllys 
122030a5e8faSwyllys 	/* Check the optional format attribute */
122130a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
122230a5e8faSwyllys 	    &format, NULL);
122330a5e8faSwyllys 	if (ret != KMF_OK) {
122430a5e8faSwyllys 		/* If there is no format attribute, then default to PEM */
122530a5e8faSwyllys 		format = KMF_FORMAT_PEM;
122630a5e8faSwyllys 		ret = KMF_OK;
122730a5e8faSwyllys 	} else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
122830a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
122999ebb4caSwyllys 		goto out;
123099ebb4caSwyllys 	}
123199ebb4caSwyllys 
123230a5e8faSwyllys 	/* Store the certificate in the file with the specified format */
123330a5e8faSwyllys 	ret = kmf_create_cert_file(cert, format, fullpath);
123499ebb4caSwyllys 
123599ebb4caSwyllys out:
123699ebb4caSwyllys 	if (fullpath != NULL)
123799ebb4caSwyllys 		free(fullpath);
123899ebb4caSwyllys 
123999ebb4caSwyllys 	return (ret);
124099ebb4caSwyllys }
124199ebb4caSwyllys 
124230a5e8faSwyllys 
124399ebb4caSwyllys KMF_RETURN
OpenSSL_DeleteCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)124430a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
124599ebb4caSwyllys {
124699ebb4caSwyllys 	KMF_RETURN rv;
124799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
12486b35cb3cSRichard PALO 	KMF_DATA certdata = { 0, NULL };
124930a5e8faSwyllys 	char *dirpath = NULL;
125030a5e8faSwyllys 	char *filename = NULL;
125130a5e8faSwyllys 	char *fullpath = NULL;
125230a5e8faSwyllys 	char *issuer = NULL;
125330a5e8faSwyllys 	char *subject = NULL;
125430a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
125530a5e8faSwyllys 	KMF_CERT_VALIDITY validity;
125699ebb4caSwyllys 
125730a5e8faSwyllys 	/*
125830a5e8faSwyllys 	 * Get the DIRPATH and CERT_FILENAME attributes.  They can not be
125930a5e8faSwyllys 	 * NULL at the same time.
126030a5e8faSwyllys 	 */
126130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
126230a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
126330a5e8faSwyllys 	    numattr);
126430a5e8faSwyllys 	fullpath = get_fullpath(dirpath, filename);
126599ebb4caSwyllys 	if (fullpath == NULL)
126699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
126799ebb4caSwyllys 
126830a5e8faSwyllys 	/* Get optional search criteria attributes */
126930a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
127030a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
127130a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
127230a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
127330a5e8faSwyllys 	    &validity, NULL);
127430a5e8faSwyllys 	if (rv != KMF_OK) {
127530a5e8faSwyllys 		validity = KMF_ALL_CERTS;
127630a5e8faSwyllys 		rv = KMF_OK;
127730a5e8faSwyllys 	}
127830a5e8faSwyllys 
127999ebb4caSwyllys 	if (isdir(fullpath)) {
128099ebb4caSwyllys 		DIR *dirp;
128199ebb4caSwyllys 		struct dirent *dp;
128299ebb4caSwyllys 
128399ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
128499ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
128599ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
128699ebb4caSwyllys 		}
128799ebb4caSwyllys 
128899ebb4caSwyllys 		while ((dp = readdir(dirp)) != NULL) {
128999ebb4caSwyllys 			if (strcmp(dp->d_name, ".") != 0 &&
129099ebb4caSwyllys 			    strcmp(dp->d_name, "..") != 0) {
129199ebb4caSwyllys 				char *fname;
129299ebb4caSwyllys 
129399ebb4caSwyllys 				fname = get_fullpath(fullpath,
129434acef67Swyllys 				    (char *)&dp->d_name);
129599ebb4caSwyllys 
129699ebb4caSwyllys 				if (fname == NULL) {
129799ebb4caSwyllys 					rv = KMF_ERR_MEMORY;
129899ebb4caSwyllys 					break;
129999ebb4caSwyllys 				}
130099ebb4caSwyllys 
130130a5e8faSwyllys 				rv = kmf_load_cert(kmfh, issuer, subject,
130230a5e8faSwyllys 				    serial, validity, fname, &certdata);
130399ebb4caSwyllys 
130499ebb4caSwyllys 				if (rv == KMF_ERR_CERT_NOT_FOUND) {
130599ebb4caSwyllys 					free(fname);
1306e65e5c2dSWyllys Ingersoll 					kmf_free_data(&certdata);
130799ebb4caSwyllys 					rv = KMF_OK;
130899ebb4caSwyllys 					continue;
130999ebb4caSwyllys 				} else if (rv != KMF_OK) {
131099ebb4caSwyllys 					free(fname);
131199ebb4caSwyllys 					break;
131299ebb4caSwyllys 				}
131399ebb4caSwyllys 
131499ebb4caSwyllys 				if (unlink(fname) != 0) {
131599ebb4caSwyllys 					SET_SYS_ERROR(kmfh, errno);
131699ebb4caSwyllys 					rv = KMF_ERR_INTERNAL;
131799ebb4caSwyllys 					free(fname);
131899ebb4caSwyllys 					break;
131999ebb4caSwyllys 				}
132099ebb4caSwyllys 				free(fname);
1321e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certdata);
132299ebb4caSwyllys 			}
132399ebb4caSwyllys 		}
132499ebb4caSwyllys 		(void) closedir(dirp);
132599ebb4caSwyllys 	} else {
132699ebb4caSwyllys 		/* Just try to load a single certificate */
132730a5e8faSwyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
132830a5e8faSwyllys 		    fullpath, &certdata);
132999ebb4caSwyllys 		if (rv == KMF_OK) {
133099ebb4caSwyllys 			if (unlink(fullpath) != 0) {
133199ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
133299ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
133399ebb4caSwyllys 			}
133499ebb4caSwyllys 		}
133599ebb4caSwyllys 	}
133699ebb4caSwyllys 
133799ebb4caSwyllys out:
133899ebb4caSwyllys 	if (fullpath != NULL)
133999ebb4caSwyllys 		free(fullpath);
134099ebb4caSwyllys 
1341e65e5c2dSWyllys Ingersoll 	kmf_free_data(&certdata);
134299ebb4caSwyllys 
134399ebb4caSwyllys 	return (rv);
134499ebb4caSwyllys }
134599ebb4caSwyllys 
134699ebb4caSwyllys KMF_RETURN
OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle,KMF_KEY_HANDLE * key,KMF_DATA * keydata)134799ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
13484942e222SAndy Fiddaman     KMF_DATA *keydata)
134999ebb4caSwyllys {
135099ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
135199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
135299ebb4caSwyllys 	int n;
135399ebb4caSwyllys 
135499ebb4caSwyllys 	if (key == NULL || keydata == NULL ||
135599ebb4caSwyllys 	    key->keyp == NULL)
135699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
135799ebb4caSwyllys 
135899ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
135999ebb4caSwyllys 		RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
136099ebb4caSwyllys 
136199ebb4caSwyllys 		if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
136299ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
136399ebb4caSwyllys 			return (KMF_ERR_ENCODING);
136499ebb4caSwyllys 		}
136599ebb4caSwyllys 		RSA_free(pubkey);
136699ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
136799ebb4caSwyllys 		DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
136899ebb4caSwyllys 
136999ebb4caSwyllys 		if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
137099ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
137199ebb4caSwyllys 			return (KMF_ERR_ENCODING);
137299ebb4caSwyllys 		}
137399ebb4caSwyllys 		DSA_free(pubkey);
137499ebb4caSwyllys 	} else {
137534acef67Swyllys 		return (KMF_ERR_BAD_PARAMETER);
137699ebb4caSwyllys 	}
137799ebb4caSwyllys 	keydata->Length = n;
137899ebb4caSwyllys 
137999ebb4caSwyllys cleanup:
138099ebb4caSwyllys 	if (rv != KMF_OK) {
138199ebb4caSwyllys 		if (keydata->Data)
138299ebb4caSwyllys 			free(keydata->Data);
138399ebb4caSwyllys 		keydata->Data = NULL;
138499ebb4caSwyllys 		keydata->Length = 0;
138599ebb4caSwyllys 	}
138699ebb4caSwyllys 
138799ebb4caSwyllys 	return (rv);
138899ebb4caSwyllys }
138999ebb4caSwyllys 
139099ebb4caSwyllys static KMF_RETURN
ssl_write_key(KMF_HANDLE * kmfh,KMF_ENCODE_FORMAT format,BIO * out,KMF_CREDENTIAL * cred,EVP_PKEY * pkey,boolean_t private)139130a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
13924942e222SAndy Fiddaman     KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
139399ebb4caSwyllys {
139499ebb4caSwyllys 	int rv = 0;
1395*6ff4183cSAndy Fiddaman #if OPENSSL_VERSION_NUMBER >= 0x30000000L
1396*6ff4183cSAndy Fiddaman 	const RSA *rsa;
1397*6ff4183cSAndy Fiddaman 	const DSA *dsa;
1398*6ff4183cSAndy Fiddaman #else
139999ebb4caSwyllys 	RSA *rsa;
140099ebb4caSwyllys 	DSA *dsa;
1401*6ff4183cSAndy Fiddaman #endif
140299ebb4caSwyllys 
14035b3e1433Swyllys 	if (pkey == NULL || out == NULL)
14045b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
14055b3e1433Swyllys 
140699ebb4caSwyllys 	switch (format) {
140773cc0e02Swyllys 		case KMF_FORMAT_RAWKEY:
140873cc0e02Swyllys 			/* same as ASN.1 */
140999ebb4caSwyllys 		case KMF_FORMAT_ASN1:
1410300fdee2SAndy Fiddaman 			if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
141130a5e8faSwyllys 				if (private)
141230a5e8faSwyllys 					rv = i2d_RSAPrivateKey_bio(out, rsa);
141330a5e8faSwyllys 				else
141430a5e8faSwyllys 					rv = i2d_RSAPublicKey_bio(out, rsa);
1415300fdee2SAndy Fiddaman 			} else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
141699ebb4caSwyllys 				rv = i2d_DSAPrivateKey_bio(out, dsa);
141799ebb4caSwyllys 			}
141899ebb4caSwyllys 			if (rv == 1) {
141999ebb4caSwyllys 				rv = KMF_OK;
142099ebb4caSwyllys 			} else {
142199ebb4caSwyllys 				SET_ERROR(kmfh, rv);
142299ebb4caSwyllys 			}
142399ebb4caSwyllys 			break;
142499ebb4caSwyllys 		case KMF_FORMAT_PEM:
1425300fdee2SAndy Fiddaman 			if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
142630a5e8faSwyllys 				if (private)
142730a5e8faSwyllys 					rv = PEM_write_bio_RSAPrivateKey(out,
142830a5e8faSwyllys 					    rsa, NULL, NULL, 0, NULL,
142930a5e8faSwyllys 					    (cred != NULL ? cred->cred : NULL));
143030a5e8faSwyllys 				else
143130a5e8faSwyllys 					rv = PEM_write_bio_RSAPublicKey(out,
143230a5e8faSwyllys 					    rsa);
1433300fdee2SAndy Fiddaman 			} else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
143499ebb4caSwyllys 				rv = PEM_write_bio_DSAPrivateKey(out,
143530a5e8faSwyllys 				    dsa, NULL, NULL, 0, NULL,
143630a5e8faSwyllys 				    (cred != NULL ? cred->cred : NULL));
143799ebb4caSwyllys 			}
143899ebb4caSwyllys 
143999ebb4caSwyllys 			if (rv == 1) {
144099ebb4caSwyllys 				rv = KMF_OK;
144199ebb4caSwyllys 			} else {
144299ebb4caSwyllys 				SET_ERROR(kmfh, rv);
144399ebb4caSwyllys 			}
144499ebb4caSwyllys 			break;
144599ebb4caSwyllys 
144699ebb4caSwyllys 		default:
144799ebb4caSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
144899ebb4caSwyllys 	}
144999ebb4caSwyllys 
145099ebb4caSwyllys 	return (rv);
145199ebb4caSwyllys }
145299ebb4caSwyllys 
145399ebb4caSwyllys KMF_RETURN
OpenSSL_CreateKeypair(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)14544942e222SAndy Fiddaman OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
145599ebb4caSwyllys {
145699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
145799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1458300fdee2SAndy Fiddaman 	uint32_t eValue = RSA_F4;
1459300fdee2SAndy Fiddaman 	BIGNUM *eValue_bn = NULL;
146099ebb4caSwyllys 	RSA *sslPrivKey = NULL;
146199ebb4caSwyllys 	DSA *sslDSAKey = NULL;
146299ebb4caSwyllys 	EVP_PKEY *eprikey = NULL;
146399ebb4caSwyllys 	EVP_PKEY *epubkey = NULL;
146499ebb4caSwyllys 	BIO *out = NULL;
146530a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
146630a5e8faSwyllys 	uint32_t keylen = 1024;
146730a5e8faSwyllys 	uint32_t keylen_size = sizeof (uint32_t);
146830a5e8faSwyllys 	boolean_t storekey = TRUE;
146930a5e8faSwyllys 	KMF_KEY_ALG keytype = KMF_RSA;
147030a5e8faSwyllys 
1471300fdee2SAndy Fiddaman 	eValue_bn = BN_new();
1472300fdee2SAndy Fiddaman 	if (eValue_bn == NULL)
1473300fdee2SAndy Fiddaman 		return (KMF_ERR_MEMORY);
1474300fdee2SAndy Fiddaman 	if (BN_set_word(eValue_bn, eValue) == 0) {
1475300fdee2SAndy Fiddaman 		rv = KMF_ERR_KEYGEN_FAILED;
1476300fdee2SAndy Fiddaman 		goto cleanup;
1477300fdee2SAndy Fiddaman 	}
1478300fdee2SAndy Fiddaman 
147930a5e8faSwyllys 	rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
148030a5e8faSwyllys 	    &storekey, NULL);
148130a5e8faSwyllys 	if (rv != KMF_OK) {
148230a5e8faSwyllys 		/* "storekey" is optional. Default is TRUE */
148330a5e8faSwyllys 		rv = KMF_OK;
148499ebb4caSwyllys 	}
148599ebb4caSwyllys 
148630a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
148730a5e8faSwyllys 	    (void *)&keytype, NULL);
148830a5e8faSwyllys 	if (rv != KMF_OK)
148930a5e8faSwyllys 		/* keytype is optional.  KMF_RSA is default */
149030a5e8faSwyllys 		rv = KMF_OK;
149130a5e8faSwyllys 
149230a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
1493300fdee2SAndy Fiddaman 	if (pubkey == NULL) {
1494300fdee2SAndy Fiddaman 		rv = KMF_ERR_BAD_PARAMETER;
1495300fdee2SAndy Fiddaman 		goto cleanup;
1496300fdee2SAndy Fiddaman 	}
149799ebb4caSwyllys 
149830a5e8faSwyllys 	privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
1499300fdee2SAndy Fiddaman 	if (privkey == NULL) {
1500300fdee2SAndy Fiddaman 		rv = KMF_ERR_BAD_PARAMETER;
1501300fdee2SAndy Fiddaman 		goto cleanup;
1502300fdee2SAndy Fiddaman 	}
150399ebb4caSwyllys 
150430a5e8faSwyllys 	(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
150530a5e8faSwyllys 	(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
150699ebb4caSwyllys 
150799ebb4caSwyllys 	eprikey = EVP_PKEY_new();
150899ebb4caSwyllys 	if (eprikey == NULL) {
150999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
151099ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
151199ebb4caSwyllys 		goto cleanup;
151299ebb4caSwyllys 	}
151399ebb4caSwyllys 	epubkey = EVP_PKEY_new();
151499ebb4caSwyllys 	if (epubkey == NULL) {
151599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
151699ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
151799ebb4caSwyllys 		goto cleanup;
151899ebb4caSwyllys 	}
151930a5e8faSwyllys 	if (keytype == KMF_RSA) {
152030a5e8faSwyllys 		KMF_BIGINT *rsaexp = NULL;
152130a5e8faSwyllys 
152230a5e8faSwyllys 		rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
152330a5e8faSwyllys 		if (rsaexp != NULL) {
152430a5e8faSwyllys 			if (rsaexp->len > 0 &&
152530a5e8faSwyllys 			    rsaexp->len <= sizeof (eValue) &&
152630a5e8faSwyllys 			    rsaexp->val != NULL) {
152730a5e8faSwyllys 				eValue = *(uint32_t *)rsaexp->val;
1528300fdee2SAndy Fiddaman 				if (BN_set_word(eValue_bn, eValue) == 0) {
1529300fdee2SAndy Fiddaman 					rv = KMF_ERR_BAD_PARAMETER;
1530300fdee2SAndy Fiddaman 					goto cleanup;
1531300fdee2SAndy Fiddaman 				}
153230a5e8faSwyllys 			} else {
153330a5e8faSwyllys 				rv = KMF_ERR_BAD_PARAMETER;
153430a5e8faSwyllys 				goto cleanup;
153530a5e8faSwyllys 			}
153630a5e8faSwyllys 		} else {
153730a5e8faSwyllys 			/* RSA Exponent is optional. Default is 0x10001 */
153830a5e8faSwyllys 			rv = KMF_OK;
153930a5e8faSwyllys 		}
154030a5e8faSwyllys 
154130a5e8faSwyllys 		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
154230a5e8faSwyllys 		    &keylen, &keylen_size);
154330a5e8faSwyllys 		if (rv == KMF_ERR_ATTR_NOT_FOUND)
154430a5e8faSwyllys 			/* keylen is optional, default is 1024 */
154530a5e8faSwyllys 			rv = KMF_OK;
154630a5e8faSwyllys 		if (rv != KMF_OK) {
154730a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
154830a5e8faSwyllys 			goto cleanup;
154930a5e8faSwyllys 		}
155099ebb4caSwyllys 
1551300fdee2SAndy Fiddaman 		sslPrivKey = RSA_new();
1552300fdee2SAndy Fiddaman 		if (sslPrivKey == NULL ||
1553300fdee2SAndy Fiddaman 		    RSA_generate_key_ex(sslPrivKey, keylen, eValue_bn, NULL)
1554300fdee2SAndy Fiddaman 		    == 0) {
155599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
155699ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
155799ebb4caSwyllys 		} else {
155830a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
155930a5e8faSwyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
156030a5e8faSwyllys 			privkey->keyalg = KMF_RSA;
156130a5e8faSwyllys 			privkey->keyclass = KMF_ASYM_PRI;
156230a5e8faSwyllys 			privkey->israw = FALSE;
156330a5e8faSwyllys 			privkey->keyp = (void *)eprikey;
156430a5e8faSwyllys 
156599ebb4caSwyllys 			/* OpenSSL derives the public key from the private */
156630a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
156730a5e8faSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
156830a5e8faSwyllys 			pubkey->keyalg = KMF_RSA;
156930a5e8faSwyllys 			pubkey->israw = FALSE;
157030a5e8faSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
157130a5e8faSwyllys 			pubkey->keyp = (void *)epubkey;
157299ebb4caSwyllys 		}
157330a5e8faSwyllys 	} else if (keytype == KMF_DSA) {
1574300fdee2SAndy Fiddaman 		BIGNUM *p, *q, *g;
1575300fdee2SAndy Fiddaman 
157699ebb4caSwyllys 		sslDSAKey = DSA_new();
157799ebb4caSwyllys 		if (sslDSAKey == NULL) {
157899ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
157999ebb4caSwyllys 			return (KMF_ERR_MEMORY);
158099ebb4caSwyllys 		}
158199ebb4caSwyllys 
1582300fdee2SAndy Fiddaman 		p = BN_bin2bn(P, sizeof (P), NULL);
1583300fdee2SAndy Fiddaman 		q = BN_bin2bn(Q, sizeof (Q), NULL);
1584300fdee2SAndy Fiddaman 		g = BN_bin2bn(G, sizeof (G), NULL);
1585300fdee2SAndy Fiddaman 		if (p == NULL || q == NULL || g == NULL) {
1586300fdee2SAndy Fiddaman 			BN_free(p);
1587300fdee2SAndy Fiddaman 			BN_free(q);
1588300fdee2SAndy Fiddaman 			BN_free(g);
158999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
159099ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
159199ebb4caSwyllys 			goto cleanup;
159299ebb4caSwyllys 		}
1593300fdee2SAndy Fiddaman 
1594300fdee2SAndy Fiddaman 		if (DSA_set0_pqg(sslDSAKey, p, q, g) == 0) {
159599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
159699ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
159799ebb4caSwyllys 			goto cleanup;
159899ebb4caSwyllys 		}
159999ebb4caSwyllys 
160099ebb4caSwyllys 		if (!DSA_generate_key(sslDSAKey)) {
160199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
160299ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
160399ebb4caSwyllys 			goto cleanup;
160499ebb4caSwyllys 		}
160599ebb4caSwyllys 
160630a5e8faSwyllys 		privkey->kstype = KMF_KEYSTORE_OPENSSL;
160730a5e8faSwyllys 		privkey->keyalg = KMF_DSA;
160830a5e8faSwyllys 		privkey->keyclass = KMF_ASYM_PRI;
160930a5e8faSwyllys 		privkey->israw = FALSE;
161030a5e8faSwyllys 		if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
161130a5e8faSwyllys 			privkey->keyp = (void *)eprikey;
161230a5e8faSwyllys 		} else {
161330a5e8faSwyllys 			SET_ERROR(kmfh, ERR_get_error());
161430a5e8faSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
161530a5e8faSwyllys 			goto cleanup;
161630a5e8faSwyllys 		}
161730a5e8faSwyllys 
1618300fdee2SAndy Fiddaman 		pubkey->kstype = KMF_KEYSTORE_OPENSSL;
1619300fdee2SAndy Fiddaman 		pubkey->keyalg = KMF_DSA;
1620300fdee2SAndy Fiddaman 		pubkey->keyclass = KMF_ASYM_PUB;
1621300fdee2SAndy Fiddaman 		pubkey->israw = FALSE;
162230a5e8faSwyllys 
1623300fdee2SAndy Fiddaman 		if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
1624300fdee2SAndy Fiddaman 			pubkey->keyp = (void *)epubkey;
1625300fdee2SAndy Fiddaman 		} else {
1626300fdee2SAndy Fiddaman 			SET_ERROR(kmfh, ERR_get_error());
1627300fdee2SAndy Fiddaman 			rv = KMF_ERR_KEYGEN_FAILED;
1628300fdee2SAndy Fiddaman 			goto cleanup;
162999ebb4caSwyllys 		}
163099ebb4caSwyllys 	}
163199ebb4caSwyllys 
163299ebb4caSwyllys 	if (rv != KMF_OK) {
163399ebb4caSwyllys 		goto cleanup;
163499ebb4caSwyllys 	}
163599ebb4caSwyllys 
163630a5e8faSwyllys 	if (storekey) {
163730a5e8faSwyllys 		KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
163830a5e8faSwyllys 		int i = 0;
163930a5e8faSwyllys 		char *keyfile = NULL, *dirpath = NULL;
164030a5e8faSwyllys 		KMF_ENCODE_FORMAT format;
164130a5e8faSwyllys 		/*
164230a5e8faSwyllys 		 * Construct a new attribute arrray and call openssl_store_key
164330a5e8faSwyllys 		 */
164430a5e8faSwyllys 		kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
164530a5e8faSwyllys 		    privkey, sizeof (privkey));
164630a5e8faSwyllys 		i++;
164730a5e8faSwyllys 
164830a5e8faSwyllys 		dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
164930a5e8faSwyllys 		if (dirpath != NULL) {
165030a5e8faSwyllys 			storeattrs[i].type = KMF_DIRPATH_ATTR;
165130a5e8faSwyllys 			storeattrs[i].pValue = dirpath;
165230a5e8faSwyllys 			storeattrs[i].valueLen = strlen(dirpath);
165330a5e8faSwyllys 			i++;
165430a5e8faSwyllys 		} else {
165530a5e8faSwyllys 			rv = KMF_OK; /* DIRPATH is optional */
165630a5e8faSwyllys 		}
165730a5e8faSwyllys 		keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
165830a5e8faSwyllys 		    attrlist, numattr);
165930a5e8faSwyllys 		if (keyfile != NULL) {
166030a5e8faSwyllys 			storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
166130a5e8faSwyllys 			storeattrs[i].pValue = keyfile;
166230a5e8faSwyllys 			storeattrs[i].valueLen = strlen(keyfile);
166330a5e8faSwyllys 			i++;
166430a5e8faSwyllys 		} else {
166530a5e8faSwyllys 			goto cleanup; /* KEYFILE is required */
166630a5e8faSwyllys 		}
166730a5e8faSwyllys 		rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
166830a5e8faSwyllys 		    (void *)&format, NULL);
166930a5e8faSwyllys 		if (rv == KMF_OK) {
167030a5e8faSwyllys 			storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
167130a5e8faSwyllys 			storeattrs[i].pValue = &format;
167230a5e8faSwyllys 			storeattrs[i].valueLen = sizeof (format);
167330a5e8faSwyllys 			i++;
167430a5e8faSwyllys 		}
167530a5e8faSwyllys 
167630a5e8faSwyllys 		rv = OpenSSL_StoreKey(handle, i, storeattrs);
167799ebb4caSwyllys 	}
167899ebb4caSwyllys 
167999ebb4caSwyllys cleanup:
1680300fdee2SAndy Fiddaman 	if (eValue_bn != NULL)
1681300fdee2SAndy Fiddaman 		BN_free(eValue_bn);
1682300fdee2SAndy Fiddaman 
168399ebb4caSwyllys 	if (rv != KMF_OK) {
168499ebb4caSwyllys 		if (eprikey != NULL)
168599ebb4caSwyllys 			EVP_PKEY_free(eprikey);
168699ebb4caSwyllys 
168799ebb4caSwyllys 		if (epubkey != NULL)
168899ebb4caSwyllys 			EVP_PKEY_free(epubkey);
168999ebb4caSwyllys 
169099ebb4caSwyllys 		if (pubkey->keylabel) {
169199ebb4caSwyllys 			free(pubkey->keylabel);
169299ebb4caSwyllys 			pubkey->keylabel = NULL;
169399ebb4caSwyllys 		}
169499ebb4caSwyllys 
169599ebb4caSwyllys 		if (privkey->keylabel) {
169699ebb4caSwyllys 			free(privkey->keylabel);
169799ebb4caSwyllys 			privkey->keylabel = NULL;
169899ebb4caSwyllys 		}
169999ebb4caSwyllys 
170099ebb4caSwyllys 		pubkey->keyp = NULL;
170199ebb4caSwyllys 		privkey->keyp = NULL;
170299ebb4caSwyllys 	}
170399ebb4caSwyllys 
170499ebb4caSwyllys 	if (sslPrivKey)
170599ebb4caSwyllys 		RSA_free(sslPrivKey);
170699ebb4caSwyllys 
170799ebb4caSwyllys 	if (sslDSAKey)
170899ebb4caSwyllys 		DSA_free(sslDSAKey);
170999ebb4caSwyllys 
171099ebb4caSwyllys 	if (out != NULL)
171199ebb4caSwyllys 		(void) BIO_free(out);
171299ebb4caSwyllys 
171399ebb4caSwyllys 	return (rv);
171499ebb4caSwyllys }
171599ebb4caSwyllys 
1716e65e5c2dSWyllys Ingersoll /*
1717e65e5c2dSWyllys Ingersoll  * Make sure the BN conversion is properly padded with 0x00
1718e65e5c2dSWyllys Ingersoll  * bytes.  If not, signature verification for DSA signatures
1719e65e5c2dSWyllys Ingersoll  * may fail in the case where the bignum value does not use
1720e65e5c2dSWyllys Ingersoll  * all of the bits.
1721e65e5c2dSWyllys Ingersoll  */
1722e65e5c2dSWyllys Ingersoll static int
fixbnlen(const BIGNUM * bn,unsigned char * buf,int len)17234942e222SAndy Fiddaman fixbnlen(const BIGNUM *bn, unsigned char *buf, int len)
17244942e222SAndy Fiddaman {
1725e65e5c2dSWyllys Ingersoll 	int bytes = len - BN_num_bytes(bn);
17262c9a247fSWyllys Ingersoll 
17272c9a247fSWyllys Ingersoll 	/* prepend with leading 0x00 if necessary */
1728e65e5c2dSWyllys Ingersoll 	while (bytes-- > 0)
1729e65e5c2dSWyllys Ingersoll 		*buf++ = 0;
1730e65e5c2dSWyllys Ingersoll 
17312c9a247fSWyllys Ingersoll 	(void) BN_bn2bin(bn, buf);
17322c9a247fSWyllys Ingersoll 	/*
17332c9a247fSWyllys Ingersoll 	 * Return the desired length since we prepended it
17342c9a247fSWyllys Ingersoll 	 * with the necessary 0x00 padding.
17352c9a247fSWyllys Ingersoll 	 */
17362c9a247fSWyllys Ingersoll 	return (len);
1737e65e5c2dSWyllys Ingersoll }
1738e65e5c2dSWyllys Ingersoll 
173999ebb4caSwyllys KMF_RETURN
OpenSSL_SignData(KMF_HANDLE_T handle,KMF_KEY_HANDLE * key,KMF_OID * AlgOID,KMF_DATA * tobesigned,KMF_DATA * output)174099ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
17414942e222SAndy Fiddaman     KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
174299ebb4caSwyllys {
174399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
174499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
174599ebb4caSwyllys 	KMF_ALGORITHM_INDEX		AlgId;
1746300fdee2SAndy Fiddaman 	EVP_MD_CTX *ctx;
174799ebb4caSwyllys 	const EVP_MD *md;
174802744e81Swyllys 
174999ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
175034acef67Swyllys 	    tobesigned == NULL || output == NULL ||
175134acef67Swyllys 	    tobesigned->Data == NULL ||
175234acef67Swyllys 	    output->Data == NULL)
175399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
175499ebb4caSwyllys 
175599ebb4caSwyllys 	/* Map the OID to an OpenSSL algorithm */
175630a5e8faSwyllys 	AlgId = x509_algoid_to_algid(AlgOID);
175799ebb4caSwyllys 	if (AlgId == KMF_ALGID_NONE)
1758e65e5c2dSWyllys Ingersoll 		return (KMF_ERR_BAD_ALGORITHM);
175999ebb4caSwyllys 
176099ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
176199ebb4caSwyllys 		EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
176299ebb4caSwyllys 		uchar_t *p;
176302744e81Swyllys 		int len;
1764553e44ceSAndrew Stormont 		switch (AlgId) {
1765553e44ceSAndrew Stormont #ifndef	OPENSSL_NO_MD5
1766553e44ceSAndrew Stormont 		case KMF_ALGID_MD5WithRSA:
176799ebb4caSwyllys 			md = EVP_md5();
1768553e44ceSAndrew Stormont 			break;
1769553e44ceSAndrew Stormont #endif
1770553e44ceSAndrew Stormont #ifndef	OPENSSL_NO_SHA
1771553e44ceSAndrew Stormont 		case KMF_ALGID_SHA1WithRSA:
177299ebb4caSwyllys 			md = EVP_sha1();
1773553e44ceSAndrew Stormont 			break;
1774553e44ceSAndrew Stormont #endif
1775553e44ceSAndrew Stormont #ifndef	OPENSSL_NO_SHA256
1776553e44ceSAndrew Stormont 		case KMF_ALGID_SHA256WithRSA:
1777e65e5c2dSWyllys Ingersoll 			md = EVP_sha256();
1778553e44ceSAndrew Stormont 			break;
1779553e44ceSAndrew Stormont #endif
1780553e44ceSAndrew Stormont #ifndef	OPENSSL_NO_SHA512
1781553e44ceSAndrew Stormont 		case KMF_ALGID_SHA384WithRSA:
1782e65e5c2dSWyllys Ingersoll 			md = EVP_sha384();
1783553e44ceSAndrew Stormont 			break;
1784553e44ceSAndrew Stormont 		case KMF_ALGID_SHA512WithRSA:
1785e65e5c2dSWyllys Ingersoll 			md = EVP_sha512();
1786553e44ceSAndrew Stormont 			break;
1787553e44ceSAndrew Stormont #endif
1788553e44ceSAndrew Stormont 		case KMF_ALGID_RSA:
178902744e81Swyllys 			md = NULL;
1790553e44ceSAndrew Stormont 			break;
1791553e44ceSAndrew Stormont 		default:
1792e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_ALGORITHM);
1793553e44ceSAndrew Stormont 		}
179499ebb4caSwyllys 
179502744e81Swyllys 		if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
179602744e81Swyllys 			RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
179799ebb4caSwyllys 
179802744e81Swyllys 			p = output->Data;
179902744e81Swyllys 			if ((len = RSA_private_encrypt(tobesigned->Length,
180034acef67Swyllys 			    tobesigned->Data, p, rsa,
180134acef67Swyllys 			    RSA_PKCS1_PADDING)) <= 0) {
180202744e81Swyllys 				SET_ERROR(kmfh, ERR_get_error());
180302744e81Swyllys 				ret = KMF_ERR_INTERNAL;
180402744e81Swyllys 			}
180502744e81Swyllys 			output->Length = len;
180602744e81Swyllys 		} else {
1807300fdee2SAndy Fiddaman 			if ((ctx = EVP_MD_CTX_new()) == NULL)
1808300fdee2SAndy Fiddaman 				return (KMF_ERR_MEMORY);
1809300fdee2SAndy Fiddaman 			(void) EVP_SignInit_ex(ctx, md, NULL);
1810300fdee2SAndy Fiddaman 			(void) EVP_SignUpdate(ctx, tobesigned->Data,
181134acef67Swyllys 			    (uint32_t)tobesigned->Length);
181202744e81Swyllys 			len = (uint32_t)output->Length;
181302744e81Swyllys 			p = output->Data;
1814300fdee2SAndy Fiddaman 			if (!EVP_SignFinal(ctx, p, (uint32_t *)&len, pkey)) {
181502744e81Swyllys 				SET_ERROR(kmfh, ERR_get_error());
181602744e81Swyllys 				len = 0;
181702744e81Swyllys 				ret = KMF_ERR_INTERNAL;
181802744e81Swyllys 			}
181902744e81Swyllys 			output->Length = len;
1820300fdee2SAndy Fiddaman 			EVP_MD_CTX_free(ctx);
182199ebb4caSwyllys 		}
182299ebb4caSwyllys 	} else if (key->keyalg == KMF_DSA) {
182399ebb4caSwyllys 		DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
182499ebb4caSwyllys 
182599ebb4caSwyllys 		uchar_t hash[EVP_MAX_MD_SIZE];
182699ebb4caSwyllys 		uint32_t hashlen;
182799ebb4caSwyllys 		DSA_SIG *dsasig;
182899ebb4caSwyllys 
1829e65e5c2dSWyllys Ingersoll 		if (AlgId == KMF_ALGID_DSA ||
1830e65e5c2dSWyllys Ingersoll 		    AlgId == KMF_ALGID_SHA1WithDSA)
1831e65e5c2dSWyllys Ingersoll 			md = EVP_sha1();
1832e65e5c2dSWyllys Ingersoll 		else if (AlgId == KMF_ALGID_SHA256WithDSA)
1833e65e5c2dSWyllys Ingersoll 			md = EVP_sha256();
1834e65e5c2dSWyllys Ingersoll 		else /* Bad algorithm */
1835e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_ALGORITHM);
1836e65e5c2dSWyllys Ingersoll 
183799ebb4caSwyllys 		/*
183899ebb4caSwyllys 		 * OpenSSL EVP_Sign operation automatically converts to
183999ebb4caSwyllys 		 * ASN.1 output so we do the operations separately so we
184099ebb4caSwyllys 		 * are assured of NOT getting ASN.1 output returned.
184199ebb4caSwyllys 		 * KMF does not want ASN.1 encoded results because
184299ebb4caSwyllys 		 * not all mechanisms return ASN.1 encodings (PKCS#11
184399ebb4caSwyllys 		 * and NSS return raw signature data).
184499ebb4caSwyllys 		 */
1845300fdee2SAndy Fiddaman 		if ((ctx = EVP_MD_CTX_new()) == NULL)
1846300fdee2SAndy Fiddaman 			return (KMF_ERR_MEMORY);
1847300fdee2SAndy Fiddaman 		(void) EVP_DigestInit_ex(ctx, md, NULL);
1848300fdee2SAndy Fiddaman 		(void) EVP_DigestUpdate(ctx, tobesigned->Data,
184934acef67Swyllys 		    tobesigned->Length);
1850300fdee2SAndy Fiddaman 		(void) EVP_DigestFinal_ex(ctx, hash, &hashlen);
185199ebb4caSwyllys 
1852e65e5c2dSWyllys Ingersoll 		/* Only sign first 20 bytes for SHA2 */
1853e65e5c2dSWyllys Ingersoll 		if (AlgId == KMF_ALGID_SHA256WithDSA)
1854e65e5c2dSWyllys Ingersoll 			hashlen = 20;
185599ebb4caSwyllys 		dsasig = DSA_do_sign(hash, hashlen, dsa);
185699ebb4caSwyllys 		if (dsasig != NULL) {
185799ebb4caSwyllys 			int i;
1858300fdee2SAndy Fiddaman 			const BIGNUM *r, *s;
1859300fdee2SAndy Fiddaman 
1860300fdee2SAndy Fiddaman 			DSA_SIG_get0(dsasig, &r, &s);
1861300fdee2SAndy Fiddaman 			output->Length = i = fixbnlen(r, output->Data,
1862e65e5c2dSWyllys Ingersoll 			    hashlen);
18632c9a247fSWyllys Ingersoll 
1864300fdee2SAndy Fiddaman 			output->Length += fixbnlen(s, &output->Data[i],
1865e65e5c2dSWyllys Ingersoll 			    hashlen);
18662c9a247fSWyllys Ingersoll 
186799ebb4caSwyllys 			DSA_SIG_free(dsasig);
186899ebb4caSwyllys 		} else {
186999ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
187099ebb4caSwyllys 		}
1871300fdee2SAndy Fiddaman 		EVP_MD_CTX_free(ctx);
187299ebb4caSwyllys 	} else {
187399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
187499ebb4caSwyllys 	}
187599ebb4caSwyllys cleanup:
187699ebb4caSwyllys 	return (ret);
187799ebb4caSwyllys }
187899ebb4caSwyllys 
187999ebb4caSwyllys KMF_RETURN
OpenSSL_DeleteKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)18804942e222SAndy Fiddaman OpenSSL_DeleteKey(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
188199ebb4caSwyllys {
188299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
188330a5e8faSwyllys 	KMF_KEY_HANDLE *key;
188430a5e8faSwyllys 	boolean_t destroy = B_TRUE;
188530a5e8faSwyllys 
188630a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
188799ebb4caSwyllys 	if (key == NULL || key->keyp == NULL)
188899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
188999ebb4caSwyllys 
189030a5e8faSwyllys 	rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
189130a5e8faSwyllys 	    (void *)&destroy, NULL);
189230a5e8faSwyllys 	if (rv != KMF_OK) {
189330a5e8faSwyllys 		/* "destroy" is optional. Default is TRUE */
189430a5e8faSwyllys 		rv = KMF_OK;
189530a5e8faSwyllys 	}
189630a5e8faSwyllys 
189799ebb4caSwyllys 	if (key->keyclass != KMF_ASYM_PUB &&
189834acef67Swyllys 	    key->keyclass != KMF_ASYM_PRI &&
189934acef67Swyllys 	    key->keyclass != KMF_SYMMETRIC)
190099ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
190199ebb4caSwyllys 
190299ebb4caSwyllys 	if (key->keyclass == KMF_SYMMETRIC) {
190330a5e8faSwyllys 		kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
190499ebb4caSwyllys 		key->keyp = NULL;
190599ebb4caSwyllys 	} else {
190699ebb4caSwyllys 		if (key->keyp != NULL) {
190799ebb4caSwyllys 			EVP_PKEY_free(key->keyp);
190899ebb4caSwyllys 			key->keyp = NULL;
190999ebb4caSwyllys 		}
191099ebb4caSwyllys 	}
191199ebb4caSwyllys 
191299ebb4caSwyllys 	if (key->keylabel != NULL) {
191399ebb4caSwyllys 		EVP_PKEY *pkey = NULL;
191499ebb4caSwyllys 		/* If the file exists, make sure it is a proper key. */
191599ebb4caSwyllys 		pkey = openssl_load_key(handle, key->keylabel);
191699ebb4caSwyllys 		if (pkey == NULL) {
19175b3e1433Swyllys 			if (key->keylabel != NULL) {
19185b3e1433Swyllys 				free(key->keylabel);
19195b3e1433Swyllys 				key->keylabel = NULL;
19205b3e1433Swyllys 			}
192199ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
192299ebb4caSwyllys 		}
192399ebb4caSwyllys 		EVP_PKEY_free(pkey);
192499ebb4caSwyllys 
192599ebb4caSwyllys 		if (destroy) {
192699ebb4caSwyllys 			if (unlink(key->keylabel) != 0) {
192799ebb4caSwyllys 				KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
192899ebb4caSwyllys 				SET_SYS_ERROR(kmfh, errno);
192999ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
193099ebb4caSwyllys 			}
193199ebb4caSwyllys 		}
193299ebb4caSwyllys 		if (key->keylabel != NULL) {
193399ebb4caSwyllys 			free(key->keylabel);
193499ebb4caSwyllys 			key->keylabel = NULL;
193599ebb4caSwyllys 		}
193699ebb4caSwyllys 	}
193799ebb4caSwyllys 	return (rv);
193899ebb4caSwyllys }
193999ebb4caSwyllys 
194099ebb4caSwyllys KMF_RETURN
OpenSSL_GetErrorString(KMF_HANDLE_T handle,char ** msgstr)194130a5e8faSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
194299ebb4caSwyllys {
194330a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
194499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
194530a5e8faSwyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
194699ebb4caSwyllys 
194730a5e8faSwyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
194830a5e8faSwyllys 	if (strlen(str)) {
194930a5e8faSwyllys 		*msgstr = (char *)strdup(str);
195030a5e8faSwyllys 		if ((*msgstr) == NULL)
195130a5e8faSwyllys 			ret = KMF_ERR_MEMORY;
195230a5e8faSwyllys 	} else {
195330a5e8faSwyllys 		*msgstr = NULL;
195499ebb4caSwyllys 	}
195599ebb4caSwyllys 
195630a5e8faSwyllys 	return (ret);
195730a5e8faSwyllys }
195899ebb4caSwyllys 
195930a5e8faSwyllys static int
ext2NID(int kmfext)196030a5e8faSwyllys ext2NID(int kmfext)
196130a5e8faSwyllys {
196230a5e8faSwyllys 	switch (kmfext) {
196330a5e8faSwyllys 		case KMF_X509_EXT_KEY_USAGE:
196430a5e8faSwyllys 			return (NID_key_usage);
196530a5e8faSwyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
196630a5e8faSwyllys 			return (NID_private_key_usage_period);
196730a5e8faSwyllys 		case KMF_X509_EXT_CERT_POLICIES:
196830a5e8faSwyllys 			return (NID_certificate_policies);
196930a5e8faSwyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
197030a5e8faSwyllys 			return (NID_subject_alt_name);
197130a5e8faSwyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
197230a5e8faSwyllys 			return (NID_issuer_alt_name);
197330a5e8faSwyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
197430a5e8faSwyllys 			return (NID_basic_constraints);
197530a5e8faSwyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
197630a5e8faSwyllys 			return (NID_ext_key_usage);
197730a5e8faSwyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
197830a5e8faSwyllys 			return (NID_authority_key_identifier);
197930a5e8faSwyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
198030a5e8faSwyllys 			return (NID_crl_distribution_points);
198130a5e8faSwyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
198230a5e8faSwyllys 			return (NID_subject_key_identifier);
198330a5e8faSwyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
198430a5e8faSwyllys 			return (OBJ_sn2nid("policyMappings"));
198530a5e8faSwyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
198630a5e8faSwyllys 			return (OBJ_sn2nid("nameConstraints"));
198730a5e8faSwyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
198830a5e8faSwyllys 			return (OBJ_sn2nid("policyConstraints"));
198930a5e8faSwyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
199030a5e8faSwyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
199130a5e8faSwyllys 		case KMF_X509_EXT_FRESHEST_CRL:
199230a5e8faSwyllys 			return (OBJ_sn2nid("freshestCRL"));
199330a5e8faSwyllys 		default:
199430a5e8faSwyllys 			return (NID_undef);
199599ebb4caSwyllys 	}
199699ebb4caSwyllys }
199799ebb4caSwyllys 
199899ebb4caSwyllys KMF_RETURN
OpenSSL_CertGetPrintable(KMF_HANDLE_T handle,const KMF_DATA * pcert,KMF_PRINTABLE_ITEM flag,char * resultStr)199930a5e8faSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
20004942e222SAndy Fiddaman     KMF_PRINTABLE_ITEM flag, char *resultStr)
200199ebb4caSwyllys {
200299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
200399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
200430a5e8faSwyllys 	X509 *xcert = NULL;
200530a5e8faSwyllys 	unsigned char *outbuf = NULL;
200630a5e8faSwyllys 	unsigned char *outbuf_p;
200730a5e8faSwyllys 	int j;
200830a5e8faSwyllys 	int ext_index, nid, len;
200999ebb4caSwyllys 	BIO *mem = NULL;
20106b35cb3cSRichard PALO 	STACK_OF(OPENSSL_STRING) *emlst = NULL;
201130a5e8faSwyllys 	X509_EXTENSION *ex;
201299ebb4caSwyllys 
201330a5e8faSwyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
201499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
201599ebb4caSwyllys 	}
201699ebb4caSwyllys 
201730a5e8faSwyllys 	/* copy cert data to outbuf */
201830a5e8faSwyllys 	outbuf = malloc(pcert->Length);
201930a5e8faSwyllys 	if (outbuf == NULL) {
202030a5e8faSwyllys 		return (KMF_ERR_MEMORY);
202199ebb4caSwyllys 	}
202230a5e8faSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
202399ebb4caSwyllys 
202430a5e8faSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
202530a5e8faSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
202630a5e8faSwyllys 	if (xcert == NULL) {
202799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
202830a5e8faSwyllys 		ret = KMF_ERR_ENCODING;
202930a5e8faSwyllys 		goto out;
203099ebb4caSwyllys 	}
203199ebb4caSwyllys 
203299ebb4caSwyllys 	mem = BIO_new(BIO_s_mem());
203399ebb4caSwyllys 	if (mem == NULL) {
203499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
203599ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
203630a5e8faSwyllys 		goto out;
203799ebb4caSwyllys 	}
203899ebb4caSwyllys 
203930a5e8faSwyllys 	switch (flag) {
204030a5e8faSwyllys 	case KMF_CERT_ISSUER:
204130a5e8faSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
204230a5e8faSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
204330a5e8faSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
204430a5e8faSwyllys 		break;
204599ebb4caSwyllys 
204630a5e8faSwyllys 	case KMF_CERT_SUBJECT:
204730a5e8faSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
204830a5e8faSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
204930a5e8faSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
205030a5e8faSwyllys 		break;
205199ebb4caSwyllys 
205230a5e8faSwyllys 	case KMF_CERT_VERSION:
2053300fdee2SAndy Fiddaman 		(void) snprintf(resultStr, KMF_CERT_PRINTABLE_LEN,
2054300fdee2SAndy Fiddaman 		    "%ld", X509_get_version(xcert));
205530a5e8faSwyllys 		len = strlen(resultStr);
205630a5e8faSwyllys 		break;
205799ebb4caSwyllys 
205830a5e8faSwyllys 	case KMF_CERT_SERIALNUM:
205930a5e8faSwyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
206030a5e8faSwyllys 			(void) strcpy(resultStr, "0x");
206130a5e8faSwyllys 			len = BIO_gets(mem, &resultStr[2],
206230a5e8faSwyllys 			    KMF_CERT_PRINTABLE_LEN - 2);
206330a5e8faSwyllys 		}
206430a5e8faSwyllys 		break;
206599ebb4caSwyllys 
206630a5e8faSwyllys 	case KMF_CERT_NOTBEFORE:
2067300fdee2SAndy Fiddaman 		(void) ASN1_TIME_print(mem, X509_getm_notBefore(xcert));
206830a5e8faSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
206930a5e8faSwyllys 		break;
207099ebb4caSwyllys 
207130a5e8faSwyllys 	case KMF_CERT_NOTAFTER:
2072300fdee2SAndy Fiddaman 		(void) ASN1_TIME_print(mem, X509_getm_notAfter(xcert));
207330a5e8faSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
207430a5e8faSwyllys 		break;
207599ebb4caSwyllys 
207630a5e8faSwyllys 	case KMF_CERT_PUBKEY_DATA:
207730a5e8faSwyllys 		{
2078*6ff4183cSAndy Fiddaman #if OPENSSL_VERSION_NUMBER >= 0x30000000L
2079*6ff4183cSAndy Fiddaman 			const RSA *rsa;
2080*6ff4183cSAndy Fiddaman 			const DSA *dsa;
2081*6ff4183cSAndy Fiddaman #else
2082300fdee2SAndy Fiddaman 			RSA *rsa;
2083300fdee2SAndy Fiddaman 			DSA *dsa;
2084*6ff4183cSAndy Fiddaman #endif
2085300fdee2SAndy Fiddaman 
208630a5e8faSwyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
208730a5e8faSwyllys 			if (pkey == NULL) {
208830a5e8faSwyllys 				SET_ERROR(kmfh, ERR_get_error());
208930a5e8faSwyllys 				ret = KMF_ERR_ENCODING;
209030a5e8faSwyllys 				goto out;
209130a5e8faSwyllys 			}
209230a5e8faSwyllys 
2093300fdee2SAndy Fiddaman 			if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
209430a5e8faSwyllys 				(void) BIO_printf(mem,
209530a5e8faSwyllys 				    "RSA Public Key: (%d bit)\n",
2096300fdee2SAndy Fiddaman 				    RSA_bits(rsa));
2097300fdee2SAndy Fiddaman 				(void) RSA_print(mem, rsa, 0);
2098300fdee2SAndy Fiddaman 
2099300fdee2SAndy Fiddaman 			} else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
210030a5e8faSwyllys 				(void) BIO_printf(mem,
210130a5e8faSwyllys 				    "%12sDSA Public Key:\n", "");
2102300fdee2SAndy Fiddaman 				(void) DSA_print(mem, dsa, 0);
210330a5e8faSwyllys 			} else {
210430a5e8faSwyllys 				(void) BIO_printf(mem,
210530a5e8faSwyllys 				    "%12sUnknown Public Key:\n", "");
210630a5e8faSwyllys 			}
210730a5e8faSwyllys 			(void) BIO_printf(mem, "\n");
210830a5e8faSwyllys 			EVP_PKEY_free(pkey);
210930a5e8faSwyllys 		}
211030a5e8faSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
211130a5e8faSwyllys 		break;
211230a5e8faSwyllys 	case KMF_CERT_SIGNATURE_ALG:
211330a5e8faSwyllys 	case KMF_CERT_PUBKEY_ALG:
2114300fdee2SAndy Fiddaman 		{
2115553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2116300fdee2SAndy Fiddaman 			ASN1_OBJECT *alg = NULL;
2117300fdee2SAndy Fiddaman #else
2118300fdee2SAndy Fiddaman 			const ASN1_OBJECT *alg = NULL;
2119300fdee2SAndy Fiddaman #endif
2120300fdee2SAndy Fiddaman 
2121300fdee2SAndy Fiddaman 			if (flag == KMF_CERT_SIGNATURE_ALG) {
2122553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2123300fdee2SAndy Fiddaman 				alg = xcert->sig_alg->algorithm;
2124300fdee2SAndy Fiddaman #else
2125300fdee2SAndy Fiddaman 				const X509_ALGOR *sig_alg = NULL;
2126300fdee2SAndy Fiddaman 
2127300fdee2SAndy Fiddaman 				X509_get0_signature(NULL, &sig_alg, xcert);
2128300fdee2SAndy Fiddaman 				if (sig_alg != NULL)
2129300fdee2SAndy Fiddaman 					X509_ALGOR_get0(&alg, NULL, NULL,
2130300fdee2SAndy Fiddaman 					    sig_alg);
2131300fdee2SAndy Fiddaman #endif
2132300fdee2SAndy Fiddaman 			} else {
2133553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2134300fdee2SAndy Fiddaman 				alg = xcert->cert_info->key->algor->algorithm;
2135300fdee2SAndy Fiddaman #else
2136300fdee2SAndy Fiddaman 				X509_PUBKEY *key = X509_get_X509_PUBKEY(xcert);
2137300fdee2SAndy Fiddaman 
2138300fdee2SAndy Fiddaman 				if (key != NULL)
2139300fdee2SAndy Fiddaman 					(void) X509_PUBKEY_get0_param(
2140300fdee2SAndy Fiddaman 					    (ASN1_OBJECT **)&alg, NULL, 0,
2141300fdee2SAndy Fiddaman 					    NULL, key);
2142300fdee2SAndy Fiddaman #endif
2143300fdee2SAndy Fiddaman 			}
214430a5e8faSwyllys 
2145300fdee2SAndy Fiddaman 			if (alg == NULL)
2146300fdee2SAndy Fiddaman 				len = -1;
2147300fdee2SAndy Fiddaman 			else if ((len = i2a_ASN1_OBJECT(mem, alg)) > 0)
2148300fdee2SAndy Fiddaman 				len = BIO_read(mem, resultStr,
2149300fdee2SAndy Fiddaman 				    KMF_CERT_PRINTABLE_LEN);
215030a5e8faSwyllys 		}
215130a5e8faSwyllys 		break;
215230a5e8faSwyllys 
215330a5e8faSwyllys 	case KMF_CERT_EMAIL:
215430a5e8faSwyllys 		emlst = X509_get1_email(xcert);
215570f9559bSTheo Schlossnagle 		for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
215670f9559bSTheo Schlossnagle 			(void) BIO_printf(mem, "%s\n",
21576b35cb3cSRichard PALO 			    sk_OPENSSL_STRING_value(emlst, j));
215830a5e8faSwyllys 
215930a5e8faSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
216030a5e8faSwyllys 		X509_email_free(emlst);
216130a5e8faSwyllys 		break;
216230a5e8faSwyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
216330a5e8faSwyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
216430a5e8faSwyllys 	case KMF_X509_EXT_KEY_USAGE:
216530a5e8faSwyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
216630a5e8faSwyllys 	case KMF_X509_EXT_CERT_POLICIES:
216730a5e8faSwyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
216830a5e8faSwyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
216930a5e8faSwyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
217030a5e8faSwyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
217130a5e8faSwyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
217230a5e8faSwyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
217330a5e8faSwyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
217430a5e8faSwyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
217530a5e8faSwyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
217630a5e8faSwyllys 	case KMF_X509_EXT_FRESHEST_CRL:
217730a5e8faSwyllys 		nid = ext2NID(flag);
217830a5e8faSwyllys 		if (nid == NID_undef) {
217930a5e8faSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
218030a5e8faSwyllys 			goto out;
218130a5e8faSwyllys 		}
218230a5e8faSwyllys 
2183300fdee2SAndy Fiddaman 		ext_index = X509_get_ext_by_NID(xcert, nid, -1);
218430a5e8faSwyllys 		if (ext_index == -1) {
218530a5e8faSwyllys 			SET_ERROR(kmfh, ERR_get_error());
218630a5e8faSwyllys 
218730a5e8faSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
218830a5e8faSwyllys 			goto out;
218930a5e8faSwyllys 		}
2190300fdee2SAndy Fiddaman 		ex = X509_get_ext(xcert, ext_index);
219130a5e8faSwyllys 
219230a5e8faSwyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
219330a5e8faSwyllys 
219430a5e8faSwyllys 		if (BIO_printf(mem, ": %s\n",
219530a5e8faSwyllys 		    X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
219630a5e8faSwyllys 			SET_ERROR(kmfh, ERR_get_error());
219730a5e8faSwyllys 			ret = KMF_ERR_ENCODING;
219830a5e8faSwyllys 			goto out;
219930a5e8faSwyllys 		}
220030a5e8faSwyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
220130a5e8faSwyllys 			(void) BIO_printf(mem, "%*s", 4, "");
2202300fdee2SAndy Fiddaman 			(void) ASN1_STRING_print(mem,
2203300fdee2SAndy Fiddaman 			    X509_EXTENSION_get_data(ex));
220430a5e8faSwyllys 		}
220530a5e8faSwyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
220630a5e8faSwyllys 			SET_ERROR(kmfh, ERR_get_error());
220730a5e8faSwyllys 			ret = KMF_ERR_ENCODING;
220830a5e8faSwyllys 			goto out;
220930a5e8faSwyllys 		}
221030a5e8faSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
221130a5e8faSwyllys 	}
221230a5e8faSwyllys 	if (len <= 0) {
221330a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
221430a5e8faSwyllys 		ret = KMF_ERR_ENCODING;
221530a5e8faSwyllys 	}
221630a5e8faSwyllys 
221730a5e8faSwyllys out:
221830a5e8faSwyllys 	if (outbuf != NULL) {
221930a5e8faSwyllys 		free(outbuf);
222030a5e8faSwyllys 	}
222130a5e8faSwyllys 
222230a5e8faSwyllys 	if (xcert != NULL) {
222330a5e8faSwyllys 		X509_free(xcert);
222430a5e8faSwyllys 	}
222530a5e8faSwyllys 
222630a5e8faSwyllys 	if (mem != NULL) {
222730a5e8faSwyllys 		(void) BIO_free(mem);
222830a5e8faSwyllys 	}
222999ebb4caSwyllys 
223099ebb4caSwyllys 	return (ret);
223199ebb4caSwyllys }
223299ebb4caSwyllys 
223399ebb4caSwyllys KMF_RETURN
OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)223430a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
223530a5e8faSwyllys     KMF_ATTRIBUTE *attrlist)
223699ebb4caSwyllys {
223730a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
223830a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
223930a5e8faSwyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
224030a5e8faSwyllys 	KMF_KEY_HANDLE *key = NULL;
224130a5e8faSwyllys 	uint32_t numkeys = 1; /* 1 key only */
224230a5e8faSwyllys 	char *dirpath = NULL;
224330a5e8faSwyllys 	char *keyfile = NULL;
224430a5e8faSwyllys 	KMF_ATTRIBUTE new_attrlist[16];
224530a5e8faSwyllys 	int i = 0;
224630a5e8faSwyllys 
224730a5e8faSwyllys 	/*
224830a5e8faSwyllys 	 * This is really just a FindKey operation, reuse the
224930a5e8faSwyllys 	 * FindKey function.
225030a5e8faSwyllys 	 */
225130a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
225230a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
225330a5e8faSwyllys 	i++;
225430a5e8faSwyllys 
225530a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
225630a5e8faSwyllys 	    KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
225730a5e8faSwyllys 	i++;
225899ebb4caSwyllys 
225930a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
226030a5e8faSwyllys 	    KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
226130a5e8faSwyllys 	i++;
226230a5e8faSwyllys 
226330a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
226430a5e8faSwyllys 	if (key == NULL) {
226599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
226630a5e8faSwyllys 	} else {
226730a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
226830a5e8faSwyllys 		    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
226930a5e8faSwyllys 		i++;
227099ebb4caSwyllys 	}
227199ebb4caSwyllys 
227230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
227330a5e8faSwyllys 	if (dirpath != NULL) {
227430a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
227530a5e8faSwyllys 		    KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
227630a5e8faSwyllys 		i++;
227730a5e8faSwyllys 	}
227899ebb4caSwyllys 
227930a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
228030a5e8faSwyllys 	if (keyfile == NULL)
228130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
228230a5e8faSwyllys 	else {
228330a5e8faSwyllys 		kmf_set_attr_at_index(new_attrlist, i,
228430a5e8faSwyllys 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
228530a5e8faSwyllys 		i++;
228630a5e8faSwyllys 	}
228730a5e8faSwyllys 
228830a5e8faSwyllys 	rv = OpenSSL_FindKey(handle, i, new_attrlist);
228930a5e8faSwyllys 	return (rv);
229030a5e8faSwyllys }
229130a5e8faSwyllys 
229230a5e8faSwyllys KMF_RETURN
OpenSSL_DecryptData(KMF_HANDLE_T handle,KMF_KEY_HANDLE * key,KMF_OID * AlgOID,KMF_DATA * ciphertext,KMF_DATA * output)229330a5e8faSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
22944942e222SAndy Fiddaman     KMF_OID *AlgOID, KMF_DATA *ciphertext, KMF_DATA *output)
229530a5e8faSwyllys {
229630a5e8faSwyllys 	KMF_RETURN		ret = KMF_OK;
229730a5e8faSwyllys 	RSA *rsa = NULL;
229830a5e8faSwyllys 	unsigned int in_len = 0, out_len = 0;
229930a5e8faSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
230030a5e8faSwyllys 	uint8_t *in_data, *out_data;
230130a5e8faSwyllys 	int i, blocks;
230230a5e8faSwyllys 
230330a5e8faSwyllys 	if (key == NULL || AlgOID == NULL ||
230430a5e8faSwyllys 	    ciphertext == NULL || output == NULL ||
230530a5e8faSwyllys 	    ciphertext->Data == NULL ||
230630a5e8faSwyllys 	    output->Data == NULL)
230799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
230899ebb4caSwyllys 
230930a5e8faSwyllys 	if (key->keyalg == KMF_RSA) {
231030a5e8faSwyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
231130a5e8faSwyllys 		modulus_len = RSA_size(rsa);
231230a5e8faSwyllys 	} else {
231330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
231499ebb4caSwyllys 	}
231599ebb4caSwyllys 
231630a5e8faSwyllys 	blocks = ciphertext->Length/modulus_len;
231730a5e8faSwyllys 	out_data = output->Data;
231830a5e8faSwyllys 	in_data = ciphertext->Data;
231930a5e8faSwyllys 	out_len = modulus_len - 11;
232030a5e8faSwyllys 	in_len = modulus_len;
232199ebb4caSwyllys 
232230a5e8faSwyllys 	for (i = 0; i < blocks; i++) {
232330a5e8faSwyllys 		out_len  = RSA_private_decrypt(in_len,
232430a5e8faSwyllys 		    in_data, out_data, rsa, RSA_PKCS1_PADDING);
232530a5e8faSwyllys 
232630a5e8faSwyllys 		if (out_len == 0) {
232730a5e8faSwyllys 			ret = KMF_ERR_INTERNAL;
232830a5e8faSwyllys 			goto cleanup;
232930a5e8faSwyllys 		}
233030a5e8faSwyllys 
233130a5e8faSwyllys 		out_data += out_len;
233230a5e8faSwyllys 		total_decrypted += out_len;
233330a5e8faSwyllys 		in_data += in_len;
233499ebb4caSwyllys 	}
233599ebb4caSwyllys 
233630a5e8faSwyllys 	output->Length = total_decrypted;
233730a5e8faSwyllys 
233830a5e8faSwyllys cleanup:
233930a5e8faSwyllys 	RSA_free(rsa);
234030a5e8faSwyllys 	if (ret != KMF_OK)
234130a5e8faSwyllys 		output->Length = 0;
234299ebb4caSwyllys 
234399ebb4caSwyllys 	return (ret);
234499ebb4caSwyllys 
234530a5e8faSwyllys }
234699ebb4caSwyllys 
234730a5e8faSwyllys /*
234830a5e8faSwyllys  *  This function will create a certid from issuer_cert and user_cert.
234930a5e8faSwyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
235030a5e8faSwyllys  *  certid memory after use.
235130a5e8faSwyllys  */
235230a5e8faSwyllys static KMF_RETURN
create_certid(KMF_HANDLE_T handle,const KMF_DATA * issuer_cert,const KMF_DATA * user_cert,OCSP_CERTID ** certid)235330a5e8faSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
235430a5e8faSwyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
235599ebb4caSwyllys {
235699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
235799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
235830a5e8faSwyllys 	X509   *issuer = NULL;
235930a5e8faSwyllys 	X509   *cert = NULL;
236030a5e8faSwyllys 	unsigned char *ptmp;
236199ebb4caSwyllys 
236230a5e8faSwyllys 	if (issuer_cert == NULL || user_cert == NULL) {
236399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
236499ebb4caSwyllys 	}
236599ebb4caSwyllys 
236630a5e8faSwyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
236730a5e8faSwyllys 	ptmp = issuer_cert->Data;
236830a5e8faSwyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
236930a5e8faSwyllys 	    issuer_cert->Length);
237030a5e8faSwyllys 	if (issuer == NULL) {
237199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
237230a5e8faSwyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
237399ebb4caSwyllys 		goto end;
237499ebb4caSwyllys 	}
237599ebb4caSwyllys 
237630a5e8faSwyllys 	/* convert the DER-encoded user cert to an internal X509 */
237730a5e8faSwyllys 	ptmp = user_cert->Data;
237830a5e8faSwyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
237930a5e8faSwyllys 	    user_cert->Length);
238030a5e8faSwyllys 	if (cert == NULL) {
238199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
238299ebb4caSwyllys 
238330a5e8faSwyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
238499ebb4caSwyllys 		goto end;
238530a5e8faSwyllys 	}
238699ebb4caSwyllys 
238730a5e8faSwyllys 	/* create a CERTID */
238830a5e8faSwyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
238930a5e8faSwyllys 	if (*certid == NULL) {
239099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
239130a5e8faSwyllys 		ret = KMF_ERR_OCSP_CERTID;
239299ebb4caSwyllys 		goto end;
239399ebb4caSwyllys 	}
239499ebb4caSwyllys 
239530a5e8faSwyllys end:
239630a5e8faSwyllys 	if (issuer != NULL) {
239730a5e8faSwyllys 		X509_free(issuer);
239899ebb4caSwyllys 	}
239999ebb4caSwyllys 
240030a5e8faSwyllys 	if (cert != NULL) {
240130a5e8faSwyllys 		X509_free(cert);
240230a5e8faSwyllys 	}
240330a5e8faSwyllys 
240430a5e8faSwyllys 	return (ret);
240530a5e8faSwyllys }
240630a5e8faSwyllys 
240730a5e8faSwyllys KMF_RETURN
OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)240830a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
24094942e222SAndy Fiddaman     int numattr, KMF_ATTRIBUTE *attrlist)
241030a5e8faSwyllys {
241130a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
241230a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
241330a5e8faSwyllys 	OCSP_CERTID *id = NULL;
241430a5e8faSwyllys 	OCSP_REQUEST *req = NULL;
241530a5e8faSwyllys 	BIO *derbio = NULL;
241630a5e8faSwyllys 	char *reqfile;
241730a5e8faSwyllys 	KMF_DATA *issuer_cert;
241830a5e8faSwyllys 	KMF_DATA *user_cert;
241930a5e8faSwyllys 
242030a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
242130a5e8faSwyllys 	    attrlist, numattr);
242230a5e8faSwyllys 	if (user_cert == NULL)
242330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
242430a5e8faSwyllys 
242530a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
242630a5e8faSwyllys 	    attrlist, numattr);
242730a5e8faSwyllys 	if (issuer_cert == NULL)
242830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
242930a5e8faSwyllys 
243030a5e8faSwyllys 	reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
243130a5e8faSwyllys 	    attrlist, numattr);
243230a5e8faSwyllys 	if (reqfile == NULL)
243330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
243430a5e8faSwyllys 
243530a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
243630a5e8faSwyllys 	if (ret != KMF_OK) {
243730a5e8faSwyllys 		return (ret);
243830a5e8faSwyllys 	}
243930a5e8faSwyllys 
244030a5e8faSwyllys 	/* Create an OCSP request */
244130a5e8faSwyllys 	req = OCSP_REQUEST_new();
244230a5e8faSwyllys 	if (req == NULL) {
244399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
244430a5e8faSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
244599ebb4caSwyllys 		goto end;
244699ebb4caSwyllys 	}
244799ebb4caSwyllys 
244830a5e8faSwyllys 	if (!OCSP_request_add0_id(req, id)) {
244930a5e8faSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
245099ebb4caSwyllys 		goto end;
245199ebb4caSwyllys 	}
245299ebb4caSwyllys 
245330a5e8faSwyllys 	/* Write the request to the output file with DER encoding */
245430a5e8faSwyllys 	derbio = BIO_new_file(reqfile, "wb");
245530a5e8faSwyllys 	if (!derbio) {
245699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
245730a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
245899ebb4caSwyllys 		goto end;
245999ebb4caSwyllys 	}
246030a5e8faSwyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
246130a5e8faSwyllys 		ret = KMF_ERR_ENCODING;
246299ebb4caSwyllys 	}
246399ebb4caSwyllys 
246430a5e8faSwyllys end:
246530a5e8faSwyllys 	/*
2466e65e5c2dSWyllys Ingersoll 	 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2467a2d4930dSDan OpenSolaris Anderson 	 * will also deallocate certid's space.
246830a5e8faSwyllys 	 */
246930a5e8faSwyllys 	if (req != NULL) {
247030a5e8faSwyllys 		OCSP_REQUEST_free(req);
247199ebb4caSwyllys 	}
247299ebb4caSwyllys 
247330a5e8faSwyllys 	if (derbio != NULL) {
247430a5e8faSwyllys 		(void) BIO_free(derbio);
247530a5e8faSwyllys 	}
247699ebb4caSwyllys 
247799ebb4caSwyllys 	return (ret);
247899ebb4caSwyllys }
247999ebb4caSwyllys 
248030a5e8faSwyllys /* ocsp_find_signer_sk() is copied from openssl source */
ocsp_find_signer_sk(STACK_OF (X509)* certs,OCSP_BASICRESP * bs)2481300fdee2SAndy Fiddaman static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_BASICRESP *bs)
248299ebb4caSwyllys {
248330a5e8faSwyllys 	int i;
248430a5e8faSwyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
2485300fdee2SAndy Fiddaman 	const ASN1_OCTET_STRING *pid;
2486300fdee2SAndy Fiddaman 
2487553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2488300fdee2SAndy Fiddaman 	OCSP_RESPID *id = bs->tbsResponseData->responderId;
248999ebb4caSwyllys 
249030a5e8faSwyllys 	if (id->type == V_OCSP_RESPID_NAME)
249130a5e8faSwyllys 		return (X509_find_by_subject(certs, id->value.byName));
249299ebb4caSwyllys 
2493300fdee2SAndy Fiddaman 	pid = id->value.byKey;
2494300fdee2SAndy Fiddaman #else
2495300fdee2SAndy Fiddaman 	const X509_NAME *pname;
2496300fdee2SAndy Fiddaman 
2497300fdee2SAndy Fiddaman 	if (OCSP_resp_get0_id(bs, &pid, &pname) == 0)
2498300fdee2SAndy Fiddaman 		return (NULL);
2499300fdee2SAndy Fiddaman 
2500300fdee2SAndy Fiddaman 	if (pname != NULL)
2501300fdee2SAndy Fiddaman 		return (X509_find_by_subject(certs, (X509_NAME *)pname));
2502300fdee2SAndy Fiddaman #endif
2503300fdee2SAndy Fiddaman 
250430a5e8faSwyllys 	/* Lookup by key hash */
250530a5e8faSwyllys 
250630a5e8faSwyllys 	/* If key hash isn't SHA1 length then forget it */
2507300fdee2SAndy Fiddaman 	if (pid->length != SHA_DIGEST_LENGTH)
250830a5e8faSwyllys 		return (NULL);
250930a5e8faSwyllys 
2510300fdee2SAndy Fiddaman 	keyhash = pid->data;
251130a5e8faSwyllys 	/* Calculate hash of each key and compare */
251230a5e8faSwyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
251330a5e8faSwyllys 		X509 *x = sk_X509_value(certs, i);
25145b3e1433Swyllys 		/* Use pubkey_digest to get the key ID value */
251530a5e8faSwyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
251630a5e8faSwyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
251730a5e8faSwyllys 			return (x);
251830a5e8faSwyllys 	}
251930a5e8faSwyllys 	return (NULL);
252099ebb4caSwyllys }
252199ebb4caSwyllys 
252230a5e8faSwyllys /* ocsp_find_signer() is copied from openssl source */
252399ebb4caSwyllys static int
ocsp_find_signer(X509 ** psigner,OCSP_BASICRESP * bs,STACK_OF (X509)* certs,X509_STORE * st,unsigned long flags)252430a5e8faSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
252530a5e8faSwyllys     X509_STORE *st, unsigned long flags)
252699ebb4caSwyllys {
252730a5e8faSwyllys 	X509 *signer;
2528300fdee2SAndy Fiddaman 	if ((signer = ocsp_find_signer_sk(certs, bs)))	{
252930a5e8faSwyllys 		*psigner = signer;
253030a5e8faSwyllys 		return (2);
253130a5e8faSwyllys 	}
2532300fdee2SAndy Fiddaman 
253330a5e8faSwyllys 	if (!(flags & OCSP_NOINTERN) &&
2534300fdee2SAndy Fiddaman 	    (signer = ocsp_find_signer_sk(
2535300fdee2SAndy Fiddaman 	    (STACK_OF(X509) *)OCSP_resp_get0_certs(bs), bs))) {
253630a5e8faSwyllys 		*psigner = signer;
253730a5e8faSwyllys 		return (1);
253899ebb4caSwyllys 	}
253930a5e8faSwyllys 	/* Maybe lookup from store if by subject name */
254030a5e8faSwyllys 
254130a5e8faSwyllys 	*psigner = NULL;
254230a5e8faSwyllys 	return (0);
254399ebb4caSwyllys }
254499ebb4caSwyllys 
254530a5e8faSwyllys /*
254630a5e8faSwyllys  * This function will verify the signature of a basic response, using
254730a5e8faSwyllys  * the public key from the OCSP responder certificate.
254830a5e8faSwyllys  */
254930a5e8faSwyllys static KMF_RETURN
check_response_signature(KMF_HANDLE_T handle,OCSP_BASICRESP * bs,KMF_DATA * signer_cert,KMF_DATA * issuer_cert)255030a5e8faSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
255130a5e8faSwyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
255299ebb4caSwyllys {
255399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
255499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
255530a5e8faSwyllys 	STACK_OF(X509) *cert_stack = NULL;
255630a5e8faSwyllys 	X509 *signer = NULL;
255730a5e8faSwyllys 	X509 *issuer = NULL;
2558553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
255930a5e8faSwyllys 	EVP_PKEY *skey = NULL;
2560300fdee2SAndy Fiddaman #else
2561300fdee2SAndy Fiddaman 	STACK_OF(X509) *cert_stack2 = NULL;
2562300fdee2SAndy Fiddaman #endif
256330a5e8faSwyllys 	unsigned char *ptmp;
256499ebb4caSwyllys 
256530a5e8faSwyllys 	if (bs == NULL || issuer_cert == NULL)
256699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
256799ebb4caSwyllys 
256830a5e8faSwyllys 	/*
256930a5e8faSwyllys 	 * Find the certificate that signed the basic response.
257030a5e8faSwyllys 	 *
257130a5e8faSwyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
257230a5e8faSwyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
257330a5e8faSwyllys 	 * If we still do not find a signer, we will look for it from the
257430a5e8faSwyllys 	 * certificate list came with the response file.
257530a5e8faSwyllys 	 */
257630a5e8faSwyllys 	if (signer_cert != NULL) {
257730a5e8faSwyllys 		ptmp = signer_cert->Data;
257830a5e8faSwyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
257930a5e8faSwyllys 		    signer_cert->Length);
258030a5e8faSwyllys 		if (signer == NULL) {
258130a5e8faSwyllys 			SET_ERROR(kmfh, ERR_get_error());
258230a5e8faSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
258330a5e8faSwyllys 			goto end;
258430a5e8faSwyllys 		}
258530a5e8faSwyllys 	} else {
258630a5e8faSwyllys 		/*
258730a5e8faSwyllys 		 * Convert the issuer cert into X509 and push it into a
258830a5e8faSwyllys 		 * stack to be used by ocsp_find_signer().
258930a5e8faSwyllys 		 */
259030a5e8faSwyllys 		ptmp = issuer_cert->Data;
259130a5e8faSwyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
259230a5e8faSwyllys 		    issuer_cert->Length);
259330a5e8faSwyllys 		if (issuer == NULL) {
259430a5e8faSwyllys 			SET_ERROR(kmfh, ERR_get_error());
259530a5e8faSwyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
259630a5e8faSwyllys 			goto end;
259730a5e8faSwyllys 		}
259899ebb4caSwyllys 
259930a5e8faSwyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
260030a5e8faSwyllys 			ret = KMF_ERR_INTERNAL;
260130a5e8faSwyllys 			goto end;
260230a5e8faSwyllys 		}
260399ebb4caSwyllys 
2604f810c7e5SToomas Soome 		if (sk_X509_push(cert_stack, issuer) == 0) {
260530a5e8faSwyllys 			ret = KMF_ERR_INTERNAL;
260630a5e8faSwyllys 			goto end;
260730a5e8faSwyllys 		}
260899ebb4caSwyllys 
260930a5e8faSwyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
261030a5e8faSwyllys 		if (!ret) {
261130a5e8faSwyllys 			/* can not find the signer */
261230a5e8faSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
261330a5e8faSwyllys 			goto end;
261499ebb4caSwyllys 		}
261530a5e8faSwyllys 	}
261699ebb4caSwyllys 
261730a5e8faSwyllys 	/* Verify the signature of the response */
2618553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
261930a5e8faSwyllys 	skey = X509_get_pubkey(signer);
262030a5e8faSwyllys 	if (skey == NULL) {
262130a5e8faSwyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
262230a5e8faSwyllys 		goto end;
262330a5e8faSwyllys 	}
262499ebb4caSwyllys 
262530a5e8faSwyllys 	ret = OCSP_BASICRESP_verify(bs, skey, 0);
2626300fdee2SAndy Fiddaman #else
2627300fdee2SAndy Fiddaman 	/*
2628300fdee2SAndy Fiddaman 	 * Technique based on
2629300fdee2SAndy Fiddaman 	 * https://mta.openssl.org/pipermail/openssl-users/
2630300fdee2SAndy Fiddaman 	 *	2017-October/006814.html
2631300fdee2SAndy Fiddaman 	 */
2632300fdee2SAndy Fiddaman 	if ((cert_stack2 = sk_X509_new_null()) == NULL) {
2633300fdee2SAndy Fiddaman 		ret = KMF_ERR_INTERNAL;
2634300fdee2SAndy Fiddaman 		goto end;
2635300fdee2SAndy Fiddaman 	}
2636300fdee2SAndy Fiddaman 
26374942e222SAndy Fiddaman 	if (sk_X509_push(cert_stack2, signer) == 0) {
2638300fdee2SAndy Fiddaman 		ret = KMF_ERR_INTERNAL;
2639300fdee2SAndy Fiddaman 		goto end;
2640300fdee2SAndy Fiddaman 	}
2641300fdee2SAndy Fiddaman 
2642300fdee2SAndy Fiddaman 	ret = OCSP_basic_verify(bs, cert_stack2, NULL, OCSP_NOVERIFY);
2643300fdee2SAndy Fiddaman #endif
2644300fdee2SAndy Fiddaman 
264530a5e8faSwyllys 	if (ret == 0) {
264630a5e8faSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
264730a5e8faSwyllys 		goto end;
264899ebb4caSwyllys 	}
264930a5e8faSwyllys 
265030a5e8faSwyllys end:
265130a5e8faSwyllys 	if (issuer != NULL) {
265230a5e8faSwyllys 		X509_free(issuer);
265399ebb4caSwyllys 	}
265499ebb4caSwyllys 
265530a5e8faSwyllys 	if (signer != NULL) {
265630a5e8faSwyllys 		X509_free(signer);
265799ebb4caSwyllys 	}
265899ebb4caSwyllys 
2659553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
266030a5e8faSwyllys 	if (skey != NULL) {
266130a5e8faSwyllys 		EVP_PKEY_free(skey);
266299ebb4caSwyllys 	}
2663300fdee2SAndy Fiddaman #else
2664300fdee2SAndy Fiddaman 	if (cert_stack2 != NULL) {
2665300fdee2SAndy Fiddaman 		sk_X509_free(cert_stack2);
2666300fdee2SAndy Fiddaman 	}
2667300fdee2SAndy Fiddaman #endif
266899ebb4caSwyllys 
266930a5e8faSwyllys 	if (cert_stack != NULL) {
267030a5e8faSwyllys 		sk_X509_free(cert_stack);
267199ebb4caSwyllys 	}
267299ebb4caSwyllys 
267399ebb4caSwyllys 	return (ret);
267499ebb4caSwyllys }
267599ebb4caSwyllys 
267699ebb4caSwyllys KMF_RETURN
OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)26774942e222SAndy Fiddaman OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle, int numattr,
26784942e222SAndy Fiddaman     KMF_ATTRIBUTE *attrlist)
267999ebb4caSwyllys {
268030a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
268130a5e8faSwyllys 	BIO *derbio = NULL;
268230a5e8faSwyllys 	OCSP_RESPONSE *resp = NULL;
268330a5e8faSwyllys 	OCSP_BASICRESP *bs = NULL;
268430a5e8faSwyllys 	OCSP_CERTID *id = NULL;
268530a5e8faSwyllys 	OCSP_SINGLERESP *single = NULL;
268630a5e8faSwyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
268730a5e8faSwyllys 	int index, status, reason;
268830a5e8faSwyllys 	KMF_DATA *issuer_cert;
268930a5e8faSwyllys 	KMF_DATA *user_cert;
269030a5e8faSwyllys 	KMF_DATA *signer_cert;
269130a5e8faSwyllys 	KMF_DATA *response;
269230a5e8faSwyllys 	int *response_reason, *response_status, *cert_status;
269330a5e8faSwyllys 	boolean_t ignore_response_sign = B_FALSE;	/* default is FALSE */
269430a5e8faSwyllys 	uint32_t response_lifetime;
269530a5e8faSwyllys 
269630a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
269730a5e8faSwyllys 	    attrlist, numattr);
269830a5e8faSwyllys 	if (issuer_cert == NULL)
269930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
270099ebb4caSwyllys 
270130a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
270230a5e8faSwyllys 	    attrlist, numattr);
270330a5e8faSwyllys 	if (user_cert == NULL)
270499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
270599ebb4caSwyllys 
270630a5e8faSwyllys 	response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
270730a5e8faSwyllys 	    attrlist, numattr);
270830a5e8faSwyllys 	if (response == NULL)
270999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
271099ebb4caSwyllys 
271130a5e8faSwyllys 	response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
271230a5e8faSwyllys 	    attrlist, numattr);
271330a5e8faSwyllys 	if (response_status == NULL)
271430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
271599ebb4caSwyllys 
271630a5e8faSwyllys 	response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
271730a5e8faSwyllys 	    attrlist, numattr);
271830a5e8faSwyllys 	if (response_reason == NULL)
271930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
272099ebb4caSwyllys 
272130a5e8faSwyllys 	cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
272230a5e8faSwyllys 	    attrlist, numattr);
272330a5e8faSwyllys 	if (cert_status == NULL)
272430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
272599ebb4caSwyllys 
272630a5e8faSwyllys 	/* Read in the response */
272730a5e8faSwyllys 	derbio = BIO_new_mem_buf(response->Data, response->Length);
272830a5e8faSwyllys 	if (!derbio) {
272930a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
273030a5e8faSwyllys 		return (ret);
273199ebb4caSwyllys 	}
273299ebb4caSwyllys 
273330a5e8faSwyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
273430a5e8faSwyllys 	if (resp == NULL) {
273530a5e8faSwyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
273630a5e8faSwyllys 		goto end;
273730a5e8faSwyllys 	}
273899ebb4caSwyllys 
273930a5e8faSwyllys 	/* Check the response status */
274030a5e8faSwyllys 	status = OCSP_response_status(resp);
274130a5e8faSwyllys 	*response_status = status;
274230a5e8faSwyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
274330a5e8faSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
274430a5e8faSwyllys 		goto end;
274530a5e8faSwyllys 	}
274699ebb4caSwyllys 
274730a5e8faSwyllys #ifdef DEBUG
274830a5e8faSwyllys 	printf("Successfully checked the response file status.\n");
274930a5e8faSwyllys #endif /* DEBUG */
275099ebb4caSwyllys 
275130a5e8faSwyllys 	/* Extract basic response */
275230a5e8faSwyllys 	bs = OCSP_response_get1_basic(resp);
275330a5e8faSwyllys 	if (bs == NULL) {
275430a5e8faSwyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
275599ebb4caSwyllys 		goto end;
275699ebb4caSwyllys 	}
275799ebb4caSwyllys 
275830a5e8faSwyllys #ifdef DEBUG
275930a5e8faSwyllys 	printf("Successfully retrieved the basic response.\n");
276030a5e8faSwyllys #endif /* DEBUG */
276199ebb4caSwyllys 
276230a5e8faSwyllys 	/* Check the basic response signature if required */
276330a5e8faSwyllys 	ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
276430a5e8faSwyllys 	    (void *)&ignore_response_sign, NULL);
276530a5e8faSwyllys 	if (ret != KMF_OK)
276630a5e8faSwyllys 		ret = KMF_OK;
276730a5e8faSwyllys 
276830a5e8faSwyllys 	signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
276930a5e8faSwyllys 	    attrlist, numattr);
277030a5e8faSwyllys 
277130a5e8faSwyllys 	if (ignore_response_sign == B_FALSE) {
277230a5e8faSwyllys 		ret = check_response_signature(handle, bs,
277330a5e8faSwyllys 		    signer_cert, issuer_cert);
277430a5e8faSwyllys 		if (ret != KMF_OK)
277530a5e8faSwyllys 			goto end;
277699ebb4caSwyllys 	}
277799ebb4caSwyllys 
277830a5e8faSwyllys #ifdef DEBUG
277930a5e8faSwyllys 	printf("Successfully verified the response signature.\n");
278030a5e8faSwyllys #endif /* DEBUG */
278130a5e8faSwyllys 
278230a5e8faSwyllys 	/* Create a certid for the certificate in question */
278330a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
278430a5e8faSwyllys 	if (ret != KMF_OK) {
278599ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
278699ebb4caSwyllys 		goto end;
278799ebb4caSwyllys 	}
278899ebb4caSwyllys 
278930a5e8faSwyllys #ifdef DEBUG
279030a5e8faSwyllys 	printf("successfully created a certid for the cert.\n");
279130a5e8faSwyllys #endif /* DEBUG */
279299ebb4caSwyllys 
279330a5e8faSwyllys 	/* Find the index of the single response for the certid */
279430a5e8faSwyllys 	index = OCSP_resp_find(bs, id, -1);
279530a5e8faSwyllys 	if (index < 0) {
279630a5e8faSwyllys 		/* cound not find this certificate in the response */
279730a5e8faSwyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
279830a5e8faSwyllys 		goto end;
279999ebb4caSwyllys 	}
280099ebb4caSwyllys 
280130a5e8faSwyllys #ifdef DEBUG
280230a5e8faSwyllys 	printf("Successfully found the single response index for the cert.\n");
280330a5e8faSwyllys #endif /* DEBUG */
280499ebb4caSwyllys 
280530a5e8faSwyllys 	/* Retrieve the single response and get the cert status */
280630a5e8faSwyllys 	single = OCSP_resp_get0(bs, index);
280730a5e8faSwyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
280830a5e8faSwyllys 	    &nextupd);
280930a5e8faSwyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
281030a5e8faSwyllys 		*cert_status = OCSP_GOOD;
281130a5e8faSwyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
281230a5e8faSwyllys 		*cert_status = OCSP_UNKNOWN;
281330a5e8faSwyllys 	} else { /* revoked */
281430a5e8faSwyllys 		*cert_status = OCSP_REVOKED;
281530a5e8faSwyllys 		*response_reason = reason;
281699ebb4caSwyllys 	}
281730a5e8faSwyllys 	ret = KMF_OK;
281899ebb4caSwyllys 
281930a5e8faSwyllys 	/* resp. time is optional, so we don't care about the return code. */
282030a5e8faSwyllys 	(void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
282130a5e8faSwyllys 	    (void *)&response_lifetime, NULL);
282299ebb4caSwyllys 
282330a5e8faSwyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
282430a5e8faSwyllys 	    response_lifetime)) {
282530a5e8faSwyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
282699ebb4caSwyllys 		goto end;
282799ebb4caSwyllys 	}
282899ebb4caSwyllys 
282930a5e8faSwyllys #ifdef DEBUG
283030a5e8faSwyllys 	printf("Successfully verify the time.\n");
283130a5e8faSwyllys #endif /* DEBUG */
283299ebb4caSwyllys 
283399ebb4caSwyllys end:
283430a5e8faSwyllys 	if (derbio != NULL)
283599ebb4caSwyllys 		(void) BIO_free(derbio);
283630a5e8faSwyllys 
283730a5e8faSwyllys 	if (resp != NULL)
283830a5e8faSwyllys 		OCSP_RESPONSE_free(resp);
283930a5e8faSwyllys 
284030a5e8faSwyllys 	if (bs != NULL)
284130a5e8faSwyllys 		OCSP_BASICRESP_free(bs);
284230a5e8faSwyllys 
284330a5e8faSwyllys 	if (id != NULL)
284430a5e8faSwyllys 		OCSP_CERTID_free(id);
284599ebb4caSwyllys 
284699ebb4caSwyllys 	return (ret);
284799ebb4caSwyllys }
284899ebb4caSwyllys 
284930a5e8faSwyllys static KMF_RETURN
fetch_key(KMF_HANDLE_T handle,char * path,KMF_KEY_CLASS keyclass,KMF_KEY_HANDLE * key)28504942e222SAndy Fiddaman fetch_key(KMF_HANDLE_T handle, char *path, KMF_KEY_CLASS keyclass,
28514942e222SAndy Fiddaman     KMF_KEY_HANDLE *key)
285299ebb4caSwyllys {
285330a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
285430a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
285530a5e8faSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
285699ebb4caSwyllys 
285730a5e8faSwyllys 	if (keyclass == KMF_ASYM_PRI ||
285830a5e8faSwyllys 	    keyclass == KMF_ASYM_PUB) {
285930a5e8faSwyllys 		pkey = openssl_load_key(handle, path);
286030a5e8faSwyllys 		if (pkey == NULL) {
286130a5e8faSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
286230a5e8faSwyllys 		}
286330a5e8faSwyllys 		if (key != NULL) {
2864300fdee2SAndy Fiddaman 			if (EVP_PKEY_get0_RSA(pkey) != NULL)
286530a5e8faSwyllys 				key->keyalg = KMF_RSA;
2866300fdee2SAndy Fiddaman 			else if (EVP_PKEY_get0_DSA(pkey) != NULL)
286730a5e8faSwyllys 				key->keyalg = KMF_DSA;
286899ebb4caSwyllys 
286930a5e8faSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
287030a5e8faSwyllys 			key->keyclass = keyclass;
287130a5e8faSwyllys 			key->keyp = (void *)pkey;
287230a5e8faSwyllys 			key->israw = FALSE;
28735b3e1433Swyllys 			if (path != NULL &&
28745b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
28755b3e1433Swyllys 				EVP_PKEY_free(pkey);
28765b3e1433Swyllys 				return (KMF_ERR_MEMORY);
28775b3e1433Swyllys 			}
287830a5e8faSwyllys 		} else {
287930a5e8faSwyllys 			EVP_PKEY_free(pkey);
288030a5e8faSwyllys 			pkey = NULL;
288130a5e8faSwyllys 		}
288230a5e8faSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
288330a5e8faSwyllys 		KMF_ENCODE_FORMAT fmt;
288430a5e8faSwyllys 		/*
288530a5e8faSwyllys 		 * If the file is a recognized format,
288630a5e8faSwyllys 		 * then it is NOT a symmetric key.
288730a5e8faSwyllys 		 */
288830a5e8faSwyllys 		rv = kmf_get_file_format(path, &fmt);
288930a5e8faSwyllys 		if (rv == KMF_OK || fmt != 0) {
289030a5e8faSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
289130a5e8faSwyllys 		} else if (rv == KMF_ERR_ENCODING) {
289230a5e8faSwyllys 			/*
289330a5e8faSwyllys 			 * If we don't know the encoding,
289430a5e8faSwyllys 			 * it is probably  a symmetric key.
289530a5e8faSwyllys 			 */
289630a5e8faSwyllys 			rv = KMF_OK;
289730a5e8faSwyllys 		} else if (rv == KMF_ERR_OPEN_FILE) {
289830a5e8faSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
289930a5e8faSwyllys 		}
290099ebb4caSwyllys 
290130a5e8faSwyllys 		if (key != NULL) {
290230a5e8faSwyllys 			KMF_DATA keyvalue;
290330a5e8faSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
290430a5e8faSwyllys 			if (rkey == NULL) {
290530a5e8faSwyllys 				rv = KMF_ERR_MEMORY;
290630a5e8faSwyllys 				goto out;
290730a5e8faSwyllys 			}
290899ebb4caSwyllys 
290930a5e8faSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
291030a5e8faSwyllys 			rv = kmf_read_input_file(handle, path, &keyvalue);
291130a5e8faSwyllys 			if (rv != KMF_OK)
291230a5e8faSwyllys 				goto out;
291399ebb4caSwyllys 
291430a5e8faSwyllys 			rkey->keydata.len = keyvalue.Length;
291530a5e8faSwyllys 			rkey->keydata.val = keyvalue.Data;
291630a5e8faSwyllys 
291730a5e8faSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
291830a5e8faSwyllys 			key->keyclass = keyclass;
291930a5e8faSwyllys 			key->israw = TRUE;
292030a5e8faSwyllys 			key->keyp = (void *)rkey;
29215b3e1433Swyllys 			if (path != NULL &&
29225b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
29235b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
29245b3e1433Swyllys 			}
292530a5e8faSwyllys 		}
292699ebb4caSwyllys 	}
292730a5e8faSwyllys out:
292830a5e8faSwyllys 	if (rv != KMF_OK) {
292930a5e8faSwyllys 		if (rkey != NULL) {
293030a5e8faSwyllys 			kmf_free_raw_sym_key(rkey);
293130a5e8faSwyllys 		}
293230a5e8faSwyllys 		if (pkey != NULL)
293330a5e8faSwyllys 			EVP_PKEY_free(pkey);
293430a5e8faSwyllys 
293530a5e8faSwyllys 		if (key != NULL) {
293630a5e8faSwyllys 			key->keyalg = KMF_KEYALG_NONE;
293730a5e8faSwyllys 			key->keyclass = KMF_KEYCLASS_NONE;
293830a5e8faSwyllys 			key->keyp = NULL;
293930a5e8faSwyllys 		}
294099ebb4caSwyllys 	}
294199ebb4caSwyllys 
294230a5e8faSwyllys 	return (rv);
294399ebb4caSwyllys }
294499ebb4caSwyllys 
294530a5e8faSwyllys KMF_RETURN
OpenSSL_FindKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)29464942e222SAndy Fiddaman OpenSSL_FindKey(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
294799ebb4caSwyllys {
294830a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
294930a5e8faSwyllys 	char *fullpath = NULL;
295030a5e8faSwyllys 	uint32_t maxkeys;
295130a5e8faSwyllys 	KMF_KEY_HANDLE *key;
295230a5e8faSwyllys 	uint32_t *numkeys;
295330a5e8faSwyllys 	KMF_KEY_CLASS keyclass;
295430a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
295530a5e8faSwyllys 	char *dirpath;
295630a5e8faSwyllys 	char *keyfile;
295730a5e8faSwyllys 
295830a5e8faSwyllys 	if (handle == NULL)
295930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
296030a5e8faSwyllys 
296130a5e8faSwyllys 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
296230a5e8faSwyllys 	if (numkeys == NULL)
296330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
296499ebb4caSwyllys 
296530a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
296630a5e8faSwyllys 	    (void *)&keyclass, NULL);
296730a5e8faSwyllys 	if (rv != KMF_OK)
296830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
296999ebb4caSwyllys 
297030a5e8faSwyllys 	if (keyclass != KMF_ASYM_PUB &&
297130a5e8faSwyllys 	    keyclass != KMF_ASYM_PRI &&
297230a5e8faSwyllys 	    keyclass != KMF_SYMMETRIC)
297330a5e8faSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
297430a5e8faSwyllys 
297530a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
297630a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
297730a5e8faSwyllys 
297830a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
297930a5e8faSwyllys 
298030a5e8faSwyllys 	if (fullpath == NULL)
298199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
298299ebb4caSwyllys 
298330a5e8faSwyllys 	maxkeys = *numkeys;
298430a5e8faSwyllys 	if (maxkeys == 0)
298530a5e8faSwyllys 		maxkeys = 0xFFFFFFFF;
298630a5e8faSwyllys 	*numkeys = 0;
298730a5e8faSwyllys 
298830a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
298930a5e8faSwyllys 	/* it is okay to have "keys" contains NULL */
299030a5e8faSwyllys 
299199ebb4caSwyllys 	/*
299230a5e8faSwyllys 	 * The caller may want a list of the raw key data as well.
299330a5e8faSwyllys 	 * Useful for importing keys from a file into other keystores.
299499ebb4caSwyllys 	 */
299530a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
299699ebb4caSwyllys 
299730a5e8faSwyllys 	if (isdir(fullpath)) {
299830a5e8faSwyllys 		DIR *dirp;
299930a5e8faSwyllys 		struct dirent *dp;
300030a5e8faSwyllys 		int n = 0;
300199ebb4caSwyllys 
300230a5e8faSwyllys 		/* open all files in the directory and attempt to read them */
300330a5e8faSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
300430a5e8faSwyllys 			return (KMF_ERR_BAD_PARAMETER);
300599ebb4caSwyllys 		}
300630a5e8faSwyllys 		rewinddir(dirp);
300730a5e8faSwyllys 		while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
300830a5e8faSwyllys 			if (strcmp(dp->d_name, ".") &&
300930a5e8faSwyllys 			    strcmp(dp->d_name, "..")) {
301030a5e8faSwyllys 				char *fname;
301199ebb4caSwyllys 
301230a5e8faSwyllys 				fname = get_fullpath(fullpath,
301330a5e8faSwyllys 				    (char *)&dp->d_name);
301499ebb4caSwyllys 
301530a5e8faSwyllys 				rv = fetch_key(handle, fname,
301630a5e8faSwyllys 				    keyclass, key ? &key[n] : NULL);
301799ebb4caSwyllys 
301830a5e8faSwyllys 				if (rv == KMF_OK) {
301930a5e8faSwyllys 					if (key != NULL && rawkey != NULL)
302030a5e8faSwyllys 						rv = convertToRawKey(
302130a5e8faSwyllys 						    key[n].keyp, &rawkey[n]);
302230a5e8faSwyllys 					n++;
302330a5e8faSwyllys 				}
302499ebb4caSwyllys 
302530a5e8faSwyllys 				if (rv != KMF_OK || key == NULL)
302630a5e8faSwyllys 					free(fname);
302730a5e8faSwyllys 			}
302830a5e8faSwyllys 		}
302930a5e8faSwyllys 		(void) closedir(dirp);
303030a5e8faSwyllys 		free(fullpath);
303130a5e8faSwyllys 		(*numkeys) = n;
303230a5e8faSwyllys 	} else {
303330a5e8faSwyllys 		rv = fetch_key(handle, fullpath, keyclass, key);
303430a5e8faSwyllys 		if (rv == KMF_OK)
303530a5e8faSwyllys 			(*numkeys) = 1;
303699ebb4caSwyllys 
303730a5e8faSwyllys 		if (rv != KMF_OK || key == NULL)
303830a5e8faSwyllys 			free(fullpath);
303999ebb4caSwyllys 
304030a5e8faSwyllys 		if (rv == KMF_OK && key != NULL && rawkey != NULL) {
304130a5e8faSwyllys 			rv = convertToRawKey(key->keyp, rawkey);
304230a5e8faSwyllys 		}
304399ebb4caSwyllys 	}
304499ebb4caSwyllys 
304530a5e8faSwyllys 	if (rv == KMF_OK && (*numkeys) == 0)
304630a5e8faSwyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
304773cc0e02Swyllys 	else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
304873cc0e02Swyllys 		rv = KMF_OK;
304999ebb4caSwyllys 
305030a5e8faSwyllys 	return (rv);
305199ebb4caSwyllys }
305299ebb4caSwyllys 
305330a5e8faSwyllys #define	HANDLE_PK12_ERROR { \
305430a5e8faSwyllys 	SET_ERROR(kmfh, ERR_get_error()); \
305530a5e8faSwyllys 	rv = KMF_ERR_ENCODING; \
305630a5e8faSwyllys 	goto out; \
305730a5e8faSwyllys }
305899ebb4caSwyllys 
30595b3e1433Swyllys static int
add_alias_to_bag(PKCS12_SAFEBAG * bag,X509 * xcert)30605b3e1433Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
306199ebb4caSwyllys {
3062300fdee2SAndy Fiddaman 	unsigned char *alias;
3063300fdee2SAndy Fiddaman 	int len;
3064300fdee2SAndy Fiddaman 
3065300fdee2SAndy Fiddaman 	if (xcert != NULL && (alias = X509_alias_get0(xcert, &len)) != NULL) {
30665b3e1433Swyllys 		if (PKCS12_add_friendlyname_asc(bag,
3067300fdee2SAndy Fiddaman 		    (const char *)alias, len) == 0)
30685b3e1433Swyllys 			return (0);
30695b3e1433Swyllys 	}
30705b3e1433Swyllys 	return (1);
30715b3e1433Swyllys }
307299ebb4caSwyllys 
30735b3e1433Swyllys static PKCS7 *
add_cert_to_safe(X509 * sslcert,KMF_CREDENTIAL * cred,uchar_t * keyid,unsigned int keyidlen)30745b3e1433Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
30754942e222SAndy Fiddaman     uchar_t *keyid, unsigned int keyidlen)
30765b3e1433Swyllys {
30775b3e1433Swyllys 	PKCS12_SAFEBAG *bag = NULL;
30785b3e1433Swyllys 	PKCS7 *cert_authsafe = NULL;
30795b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack;
308099ebb4caSwyllys 
308130a5e8faSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
308230a5e8faSwyllys 	if (bag_stack == NULL)
30835b3e1433Swyllys 		return (NULL);
308499ebb4caSwyllys 
30855b3e1433Swyllys 	/* Convert cert from X509 struct to PKCS#12 bag */
3086300fdee2SAndy Fiddaman 	bag = PKCS12_SAFEBAG_create_cert(sslcert);
30875b3e1433Swyllys 	if (bag == NULL) {
30885b3e1433Swyllys 		goto out;
30895b3e1433Swyllys 	}
309099ebb4caSwyllys 
30915b3e1433Swyllys 	/* Add the key id to the certificate bag. */
30925b3e1433Swyllys 	if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
30935b3e1433Swyllys 		goto out;
30945b3e1433Swyllys 	}
309599ebb4caSwyllys 
30965b3e1433Swyllys 	if (!add_alias_to_bag(bag, sslcert))
30975b3e1433Swyllys 		goto out;
309830a5e8faSwyllys 
30995b3e1433Swyllys 	/* Pile it on the bag_stack. */
31005b3e1433Swyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
31015b3e1433Swyllys 		goto out;
310299ebb4caSwyllys 	}
31035b3e1433Swyllys 	/* Turn bag_stack of certs into encrypted authsafe. */
31045b3e1433Swyllys 	cert_authsafe = PKCS12_pack_p7encdata(
31055b3e1433Swyllys 	    NID_pbe_WithSHA1And40BitRC2_CBC,
31065b3e1433Swyllys 	    cred->cred, cred->credlen, NULL, 0,
31075b3e1433Swyllys 	    PKCS12_DEFAULT_ITER, bag_stack);
310830a5e8faSwyllys 
31095b3e1433Swyllys out:
31105b3e1433Swyllys 	if (bag_stack != NULL)
311130a5e8faSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
311230a5e8faSwyllys 
31135b3e1433Swyllys 	return (cert_authsafe);
31145b3e1433Swyllys }
311599ebb4caSwyllys 
31165b3e1433Swyllys static PKCS7 *
add_key_to_safe(EVP_PKEY * pkey,KMF_CREDENTIAL * cred,uchar_t * keyid,unsigned int keyidlen,char * label,int label_len)31175b3e1433Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
31184942e222SAndy Fiddaman     uchar_t *keyid,  unsigned int keyidlen, char *label, int label_len)
31195b3e1433Swyllys {
31205b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
31215b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
31225b3e1433Swyllys 	PKCS12_SAFEBAG *bag = NULL;
31235b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
312499ebb4caSwyllys 
31255b3e1433Swyllys 	p8 = EVP_PKEY2PKCS8(pkey);
31265b3e1433Swyllys 	if (p8 == NULL) {
31275b3e1433Swyllys 		return (NULL);
312899ebb4caSwyllys 	}
31295b3e1433Swyllys 	/* Put the shrouded key into a PKCS#12 bag. */
3130300fdee2SAndy Fiddaman 	bag = PKCS12_SAFEBAG_create_pkcs8_encrypt(
31315b3e1433Swyllys 	    NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
31325b3e1433Swyllys 	    cred->cred, cred->credlen,
31335b3e1433Swyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, p8);
313499ebb4caSwyllys 
31355b3e1433Swyllys 	/* Clean up the PKCS#8 shrouded key, don't need it now. */
31365b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO_free(p8);
31375b3e1433Swyllys 	p8 = NULL;
313899ebb4caSwyllys 
31395b3e1433Swyllys 	if (bag == NULL) {
31405b3e1433Swyllys 		return (NULL);
314130a5e8faSwyllys 	}
31425b3e1433Swyllys 	if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
31435b3e1433Swyllys 		goto out;
31445b3e1433Swyllys 	if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
31455b3e1433Swyllys 		goto out;
31465b3e1433Swyllys 
31475b3e1433Swyllys 	/* Start a PKCS#12 safebag container for the private key. */
31485b3e1433Swyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
31495b3e1433Swyllys 	if (bag_stack == NULL)
31505b3e1433Swyllys 		goto out;
31515b3e1433Swyllys 
31525b3e1433Swyllys 	/* Pile on the private key on the bag_stack. */
31535b3e1433Swyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
31545b3e1433Swyllys 		goto out;
31555b3e1433Swyllys 
31565b3e1433Swyllys 	key_authsafe = PKCS12_pack_p7data(bag_stack);
315799ebb4caSwyllys 
315830a5e8faSwyllys out:
31595b3e1433Swyllys 	if (bag_stack != NULL)
316030a5e8faSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
31615b3e1433Swyllys 	bag_stack = NULL;
31625b3e1433Swyllys 	return (key_authsafe);
316330a5e8faSwyllys }
316499ebb4caSwyllys 
316530a5e8faSwyllys static EVP_PKEY *
ImportRawRSAKey(KMF_RAW_RSA_KEY * key)316630a5e8faSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
316730a5e8faSwyllys {
316830a5e8faSwyllys 	RSA		*rsa = NULL;
3169300fdee2SAndy Fiddaman 	EVP_PKEY	*newkey = NULL;
31704942e222SAndy Fiddaman 	BIGNUM		*n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL;
31714942e222SAndy Fiddaman 	BIGNUM		*dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
317299ebb4caSwyllys 
317330a5e8faSwyllys 	if ((rsa = RSA_new()) == NULL)
3174300fdee2SAndy Fiddaman 		goto cleanup;
317599ebb4caSwyllys 
3176300fdee2SAndy Fiddaman 	if ((n = BN_bin2bn(key->mod.val, key->mod.len, NULL)) == NULL)
3177300fdee2SAndy Fiddaman 		goto cleanup;
317899ebb4caSwyllys 
3179300fdee2SAndy Fiddaman 	if ((e = BN_bin2bn(key->pubexp.val, key->pubexp.len, NULL)) == NULL)
3180300fdee2SAndy Fiddaman 		goto cleanup;
318199ebb4caSwyllys 
3182300fdee2SAndy Fiddaman 	if (key->priexp.val != NULL &&
3183300fdee2SAndy Fiddaman 	    (d = BN_bin2bn(key->priexp.val, key->priexp.len, NULL)) == NULL)
3184300fdee2SAndy Fiddaman 		goto cleanup;
318599ebb4caSwyllys 
3186300fdee2SAndy Fiddaman 	if (key->prime1.val != NULL &&
3187300fdee2SAndy Fiddaman 	    (p = BN_bin2bn(key->prime1.val, key->prime1.len, NULL)) == NULL)
3188300fdee2SAndy Fiddaman 		goto cleanup;
318999ebb4caSwyllys 
3190300fdee2SAndy Fiddaman 	if (key->prime2.val != NULL &&
3191300fdee2SAndy Fiddaman 	    (q = BN_bin2bn(key->prime2.val, key->prime2.len, NULL)) == NULL)
3192300fdee2SAndy Fiddaman 		goto cleanup;
319399ebb4caSwyllys 
3194300fdee2SAndy Fiddaman 	if (key->exp1.val != NULL &&
3195300fdee2SAndy Fiddaman 	    (dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len, NULL)) == NULL)
3196300fdee2SAndy Fiddaman 		goto cleanup;
319799ebb4caSwyllys 
3198300fdee2SAndy Fiddaman 	if (key->exp2.val != NULL &&
3199300fdee2SAndy Fiddaman 	    (dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len, NULL)) == NULL)
3200300fdee2SAndy Fiddaman 		goto cleanup;
320199ebb4caSwyllys 
3202300fdee2SAndy Fiddaman 	if (key->coef.val != NULL &&
3203300fdee2SAndy Fiddaman 	    (iqmp = BN_bin2bn(key->coef.val, key->coef.len, NULL)) == NULL)
3204300fdee2SAndy Fiddaman 		goto cleanup;
3205300fdee2SAndy Fiddaman 
3206300fdee2SAndy Fiddaman 	if (RSA_set0_key(rsa, n, e, d) == 0)
3207300fdee2SAndy Fiddaman 		goto cleanup;
3208300fdee2SAndy Fiddaman 	n = e = d = NULL;
3209300fdee2SAndy Fiddaman 	if (RSA_set0_factors(rsa, p, q) == 0)
3210300fdee2SAndy Fiddaman 		goto cleanup;
3211300fdee2SAndy Fiddaman 	p = q = NULL;
3212300fdee2SAndy Fiddaman 	if (RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp) == 0)
3213300fdee2SAndy Fiddaman 		goto cleanup;
3214300fdee2SAndy Fiddaman 	dmp1 = dmq1 = iqmp = NULL;
321599ebb4caSwyllys 
321630a5e8faSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
3217300fdee2SAndy Fiddaman 		goto cleanup;
321899ebb4caSwyllys 
321930a5e8faSwyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
322099ebb4caSwyllys 
3221300fdee2SAndy Fiddaman cleanup:
322230a5e8faSwyllys 	/* The original key must be freed once here or it leaks memory */
3223300fdee2SAndy Fiddaman 	if (rsa)
3224300fdee2SAndy Fiddaman 		RSA_free(rsa);
3225300fdee2SAndy Fiddaman 	BN_free(n);
3226300fdee2SAndy Fiddaman 	BN_free(e);
3227300fdee2SAndy Fiddaman 	BN_free(d);
3228300fdee2SAndy Fiddaman 	BN_free(p);
3229300fdee2SAndy Fiddaman 	BN_free(q);
3230300fdee2SAndy Fiddaman 	BN_free(dmp1);
3231300fdee2SAndy Fiddaman 	BN_free(dmq1);
3232300fdee2SAndy Fiddaman 	BN_free(iqmp);
323399ebb4caSwyllys 
323430a5e8faSwyllys 	return (newkey);
323599ebb4caSwyllys }
323699ebb4caSwyllys 
323730a5e8faSwyllys static EVP_PKEY *
ImportRawDSAKey(KMF_RAW_DSA_KEY * key)323830a5e8faSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
323999ebb4caSwyllys {
324030a5e8faSwyllys 	DSA		*dsa = NULL;
3241300fdee2SAndy Fiddaman 	EVP_PKEY	*newkey = NULL;
32424942e222SAndy Fiddaman 	BIGNUM		*p = NULL, *q = NULL, *g = NULL;
32434942e222SAndy Fiddaman 	BIGNUM		*priv_key = NULL, *pub_key = NULL;
324499ebb4caSwyllys 
324530a5e8faSwyllys 	if ((dsa = DSA_new()) == NULL)
3246300fdee2SAndy Fiddaman 		goto cleanup;
324799ebb4caSwyllys 
3248300fdee2SAndy Fiddaman 	if ((p = BN_bin2bn(key->prime.val, key->prime.len, NULL)) == NULL)
3249300fdee2SAndy Fiddaman 		goto cleanup;
325099ebb4caSwyllys 
3251300fdee2SAndy Fiddaman 	if ((q = BN_bin2bn(key->subprime.val, key->subprime.len, NULL)) == NULL)
3252300fdee2SAndy Fiddaman 		goto cleanup;
325399ebb4caSwyllys 
3254300fdee2SAndy Fiddaman 	if ((g = BN_bin2bn(key->base.val, key->base.len, NULL)) == NULL)
3255300fdee2SAndy Fiddaman 		goto cleanup;
325699ebb4caSwyllys 
3257300fdee2SAndy Fiddaman 	if ((priv_key = BN_bin2bn(key->value.val, key->value.len,
3258300fdee2SAndy Fiddaman 	    NULL)) == NULL)
3259300fdee2SAndy Fiddaman 		goto cleanup;
3260f482c776Swyllys 
3261300fdee2SAndy Fiddaman 	if (key->pubvalue.val != NULL && (pub_key =
3262300fdee2SAndy Fiddaman 	    BN_bin2bn(key->pubvalue.val, key->pubvalue.len, NULL)) == NULL)
3263300fdee2SAndy Fiddaman 		goto cleanup;
3264300fdee2SAndy Fiddaman 
3265300fdee2SAndy Fiddaman 	if (DSA_set0_pqg(dsa, p, q, g) == 0)
3266300fdee2SAndy Fiddaman 		goto cleanup;
3267300fdee2SAndy Fiddaman 	p = q = g = NULL;
3268300fdee2SAndy Fiddaman 	if (DSA_set0_key(dsa, pub_key, priv_key) == 0)
3269300fdee2SAndy Fiddaman 		goto cleanup;
3270300fdee2SAndy Fiddaman 	pub_key = priv_key = 0;
327199ebb4caSwyllys 
327230a5e8faSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
3273300fdee2SAndy Fiddaman 		goto cleanup;
327499ebb4caSwyllys 
327530a5e8faSwyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
327630a5e8faSwyllys 
3277300fdee2SAndy Fiddaman cleanup:
327830a5e8faSwyllys 	/* The original key must be freed once here or it leaks memory */
3279300fdee2SAndy Fiddaman 	if (dsa)
3280300fdee2SAndy Fiddaman 		DSA_free(dsa);
3281300fdee2SAndy Fiddaman 	BN_free(p);
3282300fdee2SAndy Fiddaman 	BN_free(q);
3283300fdee2SAndy Fiddaman 	BN_free(g);
3284300fdee2SAndy Fiddaman 	BN_free(priv_key);
3285300fdee2SAndy Fiddaman 	BN_free(pub_key);
3286300fdee2SAndy Fiddaman 
328730a5e8faSwyllys 	return (newkey);
328830a5e8faSwyllys }
328930a5e8faSwyllys 
32905b3e1433Swyllys static EVP_PKEY *
raw_key_to_pkey(KMF_KEY_HANDLE * key)32915b3e1433Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key)
32925b3e1433Swyllys {
32935b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
32945b3e1433Swyllys 	KMF_RAW_KEY_DATA *rawkey;
32955b3e1433Swyllys 	ASN1_TYPE *attr = NULL;
32965b3e1433Swyllys 	KMF_RETURN ret;
32975b3e1433Swyllys 
32985b3e1433Swyllys 	if (key == NULL || !key->israw)
32995b3e1433Swyllys 		return (NULL);
33005b3e1433Swyllys 
33015b3e1433Swyllys 	rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
33025b3e1433Swyllys 	if (rawkey->keytype == KMF_RSA) {
33035b3e1433Swyllys 		pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
33045b3e1433Swyllys 	} else if (rawkey->keytype == KMF_DSA) {
33055b3e1433Swyllys 		pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
3306e65e5c2dSWyllys Ingersoll 	} else if (rawkey->keytype == KMF_ECDSA) {
3307e65e5c2dSWyllys Ingersoll 		/*
3308e65e5c2dSWyllys Ingersoll 		 * OpenSSL in Solaris does not support EC for
3309e65e5c2dSWyllys Ingersoll 		 * legal reasons
3310e65e5c2dSWyllys Ingersoll 		 */
3311e65e5c2dSWyllys Ingersoll 		return (NULL);
33125b3e1433Swyllys 	} else {
33135b3e1433Swyllys 		/* wrong kind of key */
33145b3e1433Swyllys 		return (NULL);
33155b3e1433Swyllys 	}
33165b3e1433Swyllys 
33175b3e1433Swyllys 	if (rawkey->label != NULL) {
33185b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
33195b3e1433Swyllys 			EVP_PKEY_free(pkey);
33205b3e1433Swyllys 			return (NULL);
33215b3e1433Swyllys 		}
33225b3e1433Swyllys 		attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
33235b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
33245b3e1433Swyllys 		    strlen(rawkey->label));
33255b3e1433Swyllys 		attr->type = V_ASN1_BMPSTRING;
33265b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.bmpstring;
33275b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
33285b3e1433Swyllys 		if (ret != KMF_OK) {
33295b3e1433Swyllys 			EVP_PKEY_free(pkey);
33305b3e1433Swyllys 			ASN1_TYPE_free(attr);
33315b3e1433Swyllys 			return (NULL);
33325b3e1433Swyllys 		}
33335b3e1433Swyllys 	}
33345b3e1433Swyllys 	if (rawkey->id.Data != NULL) {
33355b3e1433Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
33365b3e1433Swyllys 			EVP_PKEY_free(pkey);
33375b3e1433Swyllys 			return (NULL);
33385b3e1433Swyllys 		}
33395b3e1433Swyllys 		attr->value.octet_string =
33405b3e1433Swyllys 		    ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
33415b3e1433Swyllys 		attr->type = V_ASN1_OCTET_STRING;
33425b3e1433Swyllys 		(void) ASN1_STRING_set(attr->value.octet_string,
33435b3e1433Swyllys 		    rawkey->id.Data, rawkey->id.Length);
33445b3e1433Swyllys 		attr->value.ptr = (char *)attr->value.octet_string;
33455b3e1433Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
33465b3e1433Swyllys 		if (ret != KMF_OK) {
33475b3e1433Swyllys 			EVP_PKEY_free(pkey);
33485b3e1433Swyllys 			ASN1_TYPE_free(attr);
33495b3e1433Swyllys 			return (NULL);
33505b3e1433Swyllys 		}
33515b3e1433Swyllys 	}
33525b3e1433Swyllys 	return (pkey);
33535b3e1433Swyllys }
33545b3e1433Swyllys 
33555b3e1433Swyllys /*
33565b3e1433Swyllys  * Search a list of private keys to find one that goes with the certificate.
33575b3e1433Swyllys  */
33585b3e1433Swyllys static EVP_PKEY *
find_matching_key(X509 * xcert,int numkeys,KMF_KEY_HANDLE * keylist)33595b3e1433Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
33605b3e1433Swyllys {
33615b3e1433Swyllys 	int i;
33625b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
33635b3e1433Swyllys 
33645b3e1433Swyllys 	if (numkeys == 0 || keylist == NULL || xcert == NULL)
33655b3e1433Swyllys 		return (NULL);
33665b3e1433Swyllys 	for (i = 0; i < numkeys; i++) {
33675b3e1433Swyllys 		if (keylist[i].israw)
33685b3e1433Swyllys 			pkey = raw_key_to_pkey(&keylist[i]);
33695b3e1433Swyllys 		else
33705b3e1433Swyllys 			pkey = (EVP_PKEY *)keylist[i].keyp;
33715b3e1433Swyllys 		if (pkey != NULL) {
33725b3e1433Swyllys 			if (X509_check_private_key(xcert, pkey)) {
33735b3e1433Swyllys 				return (pkey);
33745b3e1433Swyllys 			} else {
33755b3e1433Swyllys 				EVP_PKEY_free(pkey);
33765b3e1433Swyllys 				pkey = NULL;
33775b3e1433Swyllys 			}
33785b3e1433Swyllys 		}
33795b3e1433Swyllys 	}
33805b3e1433Swyllys 	return (pkey);
33815b3e1433Swyllys }
33825b3e1433Swyllys 
338330a5e8faSwyllys static KMF_RETURN
local_export_pk12(KMF_HANDLE_T handle,KMF_CREDENTIAL * cred,int numcerts,KMF_X509_DER_CERT * certlist,int numkeys,KMF_KEY_HANDLE * keylist,char * filename)33844942e222SAndy Fiddaman local_export_pk12(KMF_HANDLE_T handle, KMF_CREDENTIAL *cred, int numcerts,
33854942e222SAndy Fiddaman     KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
33864942e222SAndy Fiddaman     char *filename)
338730a5e8faSwyllys {
338830a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
338930a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
339030a5e8faSwyllys 	BIO *bio = NULL;
33915b3e1433Swyllys 	PKCS7 *cert_authsafe = NULL;
33925b3e1433Swyllys 	PKCS7 *key_authsafe = NULL;
33935b3e1433Swyllys 	STACK_OF(PKCS7) *authsafe_stack = NULL;
33945b3e1433Swyllys 	PKCS12 *p12_elem = NULL;
339530a5e8faSwyllys 	int i;
339630a5e8faSwyllys 
33975b3e1433Swyllys 	if (numcerts == 0 && numkeys == 0)
33985b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
33995b3e1433Swyllys 
340030a5e8faSwyllys 	/*
340130a5e8faSwyllys 	 * Open the output file.
340230a5e8faSwyllys 	 */
340330a5e8faSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
340430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
340530a5e8faSwyllys 		rv = KMF_ERR_OPEN_FILE;
340630a5e8faSwyllys 		goto cleanup;
340730a5e8faSwyllys 	}
340830a5e8faSwyllys 
34095b3e1433Swyllys 	/* Start a PKCS#7 stack. */
34105b3e1433Swyllys 	authsafe_stack = sk_PKCS7_new_null();
34115b3e1433Swyllys 	if (authsafe_stack == NULL) {
34125b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
34135b3e1433Swyllys 		goto cleanup;
34145b3e1433Swyllys 	}
34155b3e1433Swyllys 	if (numcerts > 0) {
341630a5e8faSwyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
341730a5e8faSwyllys 			const uchar_t *p = certlist[i].certificate.Data;
341830a5e8faSwyllys 			long len = certlist[i].certificate.Length;
34195b3e1433Swyllys 			X509 *xcert = NULL;
34205b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
34215b3e1433Swyllys 			unsigned char keyid[EVP_MAX_MD_SIZE];
34225b3e1433Swyllys 			unsigned int keyidlen = 0;
342330a5e8faSwyllys 
342430a5e8faSwyllys 			xcert = d2i_X509(NULL, &p, len);
342530a5e8faSwyllys 			if (xcert == NULL) {
342630a5e8faSwyllys 				SET_ERROR(kmfh, ERR_get_error());
342730a5e8faSwyllys 				rv = KMF_ERR_ENCODING;
342830a5e8faSwyllys 			}
34295b3e1433Swyllys 			if (certlist[i].kmf_private.label != NULL) {
34305b3e1433Swyllys 				/* Set alias attribute */
34315b3e1433Swyllys 				(void) X509_alias_set1(xcert,
34325b3e1433Swyllys 				    (uchar_t *)certlist[i].kmf_private.label,
34335b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label));
34345b3e1433Swyllys 			}
34355b3e1433Swyllys 			/* Check if there is a key corresponding to this cert */
34365b3e1433Swyllys 			pkey = find_matching_key(xcert, numkeys, keylist);
34375b3e1433Swyllys 
34385b3e1433Swyllys 			/*
34395b3e1433Swyllys 			 * If key is found, get fingerprint and create a
34405b3e1433Swyllys 			 * safebag.
34415b3e1433Swyllys 			 */
34425b3e1433Swyllys 			if (pkey != NULL) {
34435b3e1433Swyllys 				(void) X509_digest(xcert, EVP_sha1(),
34445b3e1433Swyllys 				    keyid, &keyidlen);
34455b3e1433Swyllys 				key_authsafe = add_key_to_safe(pkey, cred,
34465b3e1433Swyllys 				    keyid, keyidlen,
34475b3e1433Swyllys 				    certlist[i].kmf_private.label,
34485b3e1433Swyllys 				    (certlist[i].kmf_private.label ?
34495b3e1433Swyllys 				    strlen(certlist[i].kmf_private.label) : 0));
34505b3e1433Swyllys 
34515b3e1433Swyllys 				if (key_authsafe == NULL) {
34525b3e1433Swyllys 					X509_free(xcert);
34535b3e1433Swyllys 					EVP_PKEY_free(pkey);
34545b3e1433Swyllys 					goto cleanup;
34555b3e1433Swyllys 				}
34565b3e1433Swyllys 				/* Put the key safe into the Auth Safe */
34575b3e1433Swyllys 				if (!sk_PKCS7_push(authsafe_stack,
34585b3e1433Swyllys 				    key_authsafe)) {
34595b3e1433Swyllys 					X509_free(xcert);
34605b3e1433Swyllys 					EVP_PKEY_free(pkey);
34615b3e1433Swyllys 					goto cleanup;
34625b3e1433Swyllys 				}
34635b3e1433Swyllys 			}
34645b3e1433Swyllys 
34655b3e1433Swyllys 			/* create a certificate safebag */
34665b3e1433Swyllys 			cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
34675b3e1433Swyllys 			    keyidlen);
34685b3e1433Swyllys 			if (cert_authsafe == NULL) {
34695b3e1433Swyllys 				X509_free(xcert);
34705b3e1433Swyllys 				EVP_PKEY_free(pkey);
34715b3e1433Swyllys 				goto cleanup;
34725b3e1433Swyllys 			}
34735b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
347430a5e8faSwyllys 				X509_free(xcert);
34755b3e1433Swyllys 				EVP_PKEY_free(pkey);
34765b3e1433Swyllys 				goto cleanup;
34775b3e1433Swyllys 			}
34785b3e1433Swyllys 
34795b3e1433Swyllys 			X509_free(xcert);
348030a5e8faSwyllys 			if (pkey)
348130a5e8faSwyllys 				EVP_PKEY_free(pkey);
348299ebb4caSwyllys 		}
34835b3e1433Swyllys 	} else if (numcerts == 0 && numkeys > 0) {
34845b3e1433Swyllys 		/*
34855b3e1433Swyllys 		 * If only adding keys to the file.
34865b3e1433Swyllys 		 */
34875b3e1433Swyllys 		for (i = 0; i < numkeys; i++) {
34885b3e1433Swyllys 			EVP_PKEY *pkey = NULL;
34895b3e1433Swyllys 
34905b3e1433Swyllys 			if (keylist[i].israw)
34915b3e1433Swyllys 				pkey = raw_key_to_pkey(&keylist[i]);
34925b3e1433Swyllys 			else
34935b3e1433Swyllys 				pkey = (EVP_PKEY *)keylist[i].keyp;
34945b3e1433Swyllys 
34955b3e1433Swyllys 			if (pkey == NULL)
34965b3e1433Swyllys 				continue;
34975b3e1433Swyllys 
34985b3e1433Swyllys 			key_authsafe = add_key_to_safe(pkey, cred,
34995b3e1433Swyllys 			    NULL, 0, NULL, 0);
35005b3e1433Swyllys 
35015b3e1433Swyllys 			if (key_authsafe == NULL) {
35025b3e1433Swyllys 				EVP_PKEY_free(pkey);
35035b3e1433Swyllys 				goto cleanup;
35045b3e1433Swyllys 			}
35055b3e1433Swyllys 			if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
35065b3e1433Swyllys 				EVP_PKEY_free(pkey);
35075b3e1433Swyllys 				goto cleanup;
35085b3e1433Swyllys 			}
35095b3e1433Swyllys 		}
35105b3e1433Swyllys 	}
35115b3e1433Swyllys 	p12_elem = PKCS12_init(NID_pkcs7_data);
35125b3e1433Swyllys 	if (p12_elem == NULL) {
35135b3e1433Swyllys 		goto cleanup;
35145b3e1433Swyllys 	}
35155b3e1433Swyllys 
35165b3e1433Swyllys 	/* Put the PKCS#7 stack into the PKCS#12 element. */
35175b3e1433Swyllys 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
35185b3e1433Swyllys 		goto cleanup;
35195b3e1433Swyllys 	}
35205b3e1433Swyllys 
35215b3e1433Swyllys 	/* Set the integrity MAC on the PKCS#12 element. */
35225b3e1433Swyllys 	if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
35235b3e1433Swyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
35245b3e1433Swyllys 		goto cleanup;
35255b3e1433Swyllys 	}
35265b3e1433Swyllys 
35275b3e1433Swyllys 	/* Write the PKCS#12 element to the export file. */
35285b3e1433Swyllys 	if (!i2d_PKCS12_bio(bio, p12_elem)) {
35295b3e1433Swyllys 		goto cleanup;
353030a5e8faSwyllys 	}
35315b3e1433Swyllys 	PKCS12_free(p12_elem);
353299ebb4caSwyllys 
353330a5e8faSwyllys cleanup:
35345b3e1433Swyllys 	/* Clear away the PKCS#7 stack, we're done with it. */
35355b3e1433Swyllys 	if (authsafe_stack)
35365b3e1433Swyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
353799ebb4caSwyllys 
353830a5e8faSwyllys 	if (bio != NULL)
353930a5e8faSwyllys 		(void) BIO_free_all(bio);
354099ebb4caSwyllys 
354130a5e8faSwyllys 	return (rv);
354230a5e8faSwyllys }
354399ebb4caSwyllys 
354430a5e8faSwyllys KMF_RETURN
openssl_build_pk12(KMF_HANDLE_T handle,int numcerts,KMF_X509_DER_CERT * certlist,int numkeys,KMF_KEY_HANDLE * keylist,KMF_CREDENTIAL * p12cred,char * filename)354530a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
354630a5e8faSwyllys     KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
354730a5e8faSwyllys     KMF_CREDENTIAL *p12cred, char *filename)
354830a5e8faSwyllys {
354930a5e8faSwyllys 	KMF_RETURN rv;
355099ebb4caSwyllys 
355130a5e8faSwyllys 	if (certlist == NULL && keylist == NULL)
355230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
355330a5e8faSwyllys 
35545b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, numcerts, certlist,
355530a5e8faSwyllys 	    numkeys, keylist, filename);
355699ebb4caSwyllys 
355799ebb4caSwyllys 	return (rv);
355899ebb4caSwyllys }
355999ebb4caSwyllys 
356030a5e8faSwyllys KMF_RETURN
OpenSSL_ExportPK12(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)356130a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
356299ebb4caSwyllys {
356330a5e8faSwyllys 	KMF_RETURN rv;
356430a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
356530a5e8faSwyllys 	char *fullpath = NULL;
356630a5e8faSwyllys 	char *dirpath = NULL;
356730a5e8faSwyllys 	char *certfile = NULL;
356830a5e8faSwyllys 	char *keyfile = NULL;
356930a5e8faSwyllys 	char *filename = NULL;
357030a5e8faSwyllys 	KMF_CREDENTIAL *p12cred = NULL;
35715b3e1433Swyllys 	KMF_X509_DER_CERT certdata;
35725b3e1433Swyllys 	KMF_KEY_HANDLE key;
35735b3e1433Swyllys 	int gotkey = 0;
35745b3e1433Swyllys 	int gotcert = 0;
357599ebb4caSwyllys 
357630a5e8faSwyllys 	if (handle == NULL)
357799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
357899ebb4caSwyllys 
357999ebb4caSwyllys 	/*
358030a5e8faSwyllys 	 *  First, find the certificate.
358199ebb4caSwyllys 	 */
358230a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
358330a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
358430a5e8faSwyllys 	if (certfile != NULL) {
358530a5e8faSwyllys 		fullpath = get_fullpath(dirpath, certfile);
358630a5e8faSwyllys 		if (fullpath == NULL)
358730a5e8faSwyllys 			return (KMF_ERR_BAD_PARAMETER);
358899ebb4caSwyllys 
358930a5e8faSwyllys 		if (isdir(fullpath)) {
359030a5e8faSwyllys 			free(fullpath);
359130a5e8faSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
359299ebb4caSwyllys 		}
359399ebb4caSwyllys 
35945b3e1433Swyllys 		(void) memset(&certdata, 0, sizeof (certdata));
3595f810c7e5SToomas Soome 		rv = kmf_load_cert(kmfh, NULL, NULL, NULL, 0,
35965b3e1433Swyllys 		    fullpath, &certdata.certificate);
359730a5e8faSwyllys 		if (rv != KMF_OK)
359830a5e8faSwyllys 			goto end;
359999ebb4caSwyllys 
36005b3e1433Swyllys 		gotcert++;
36015b3e1433Swyllys 		certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
360230a5e8faSwyllys 		free(fullpath);
360330a5e8faSwyllys 	}
360499ebb4caSwyllys 
360530a5e8faSwyllys 	/*
360630a5e8faSwyllys 	 * Now find the private key.
360730a5e8faSwyllys 	 */
360830a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
360930a5e8faSwyllys 	if (keyfile != NULL) {
361030a5e8faSwyllys 		fullpath = get_fullpath(dirpath, keyfile);
361130a5e8faSwyllys 		if (fullpath == NULL)
361230a5e8faSwyllys 			return (KMF_ERR_BAD_PARAMETER);
361399ebb4caSwyllys 
361430a5e8faSwyllys 		if (isdir(fullpath)) {
361530a5e8faSwyllys 			free(fullpath);
361630a5e8faSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
361730a5e8faSwyllys 		}
361899ebb4caSwyllys 
36195b3e1433Swyllys 		(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
36205b3e1433Swyllys 		rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
36215b3e1433Swyllys 		if (rv != KMF_OK)
362230a5e8faSwyllys 			goto end;
36235b3e1433Swyllys 		gotkey++;
362499ebb4caSwyllys 	}
362530a5e8faSwyllys 
362699ebb4caSwyllys 	/*
362730a5e8faSwyllys 	 * Open the output file.
362899ebb4caSwyllys 	 */
362930a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
363030a5e8faSwyllys 	    numattr);
363130a5e8faSwyllys 	if (filename == NULL) {
363230a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
363330a5e8faSwyllys 		goto end;
363430a5e8faSwyllys 	}
363599ebb4caSwyllys 
363630a5e8faSwyllys 	/* Stick the key and the cert into a PKCS#12 file */
363730a5e8faSwyllys 	p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
363830a5e8faSwyllys 	if (p12cred == NULL) {
363930a5e8faSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
364030a5e8faSwyllys 		goto end;
364130a5e8faSwyllys 	}
364230a5e8faSwyllys 
36435b3e1433Swyllys 	rv = local_export_pk12(handle, p12cred, 1, &certdata,
36445b3e1433Swyllys 	    1, &key, filename);
364530a5e8faSwyllys 
364630a5e8faSwyllys end:
364730a5e8faSwyllys 	if (fullpath)
364830a5e8faSwyllys 		free(fullpath);
364930a5e8faSwyllys 
36505b3e1433Swyllys 	if (gotcert)
36515b3e1433Swyllys 		kmf_free_kmf_cert(handle, &certdata);
36525b3e1433Swyllys 	if (gotkey)
36535b3e1433Swyllys 		kmf_free_kmf_key(handle, &key);
365430a5e8faSwyllys 	return (rv);
365530a5e8faSwyllys }
365630a5e8faSwyllys 
365730a5e8faSwyllys /*
365830a5e8faSwyllys  * Helper function to extract keys and certificates from
365930a5e8faSwyllys  * a single PEM file.  Typically the file should contain a
366030a5e8faSwyllys  * private key and an associated public key wrapped in an x509 cert.
366130a5e8faSwyllys  * However, the file may be just a list of X509 certs with no keys.
366230a5e8faSwyllys  */
366330a5e8faSwyllys static KMF_RETURN
extract_pem(KMF_HANDLE * kmfh,char * issuer,char * subject,KMF_BIGINT * serial,char * filename,CK_UTF8CHAR * pin,CK_ULONG pinlen,EVP_PKEY ** priv_key,KMF_DATA ** certs,int * numcerts)36644942e222SAndy Fiddaman extract_pem(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
36654942e222SAndy Fiddaman     char *filename, CK_UTF8CHAR *pin, CK_ULONG pinlen, EVP_PKEY **priv_key,
36664942e222SAndy Fiddaman     KMF_DATA **certs, int *numcerts)
366730a5e8faSwyllys {
366830a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
366930a5e8faSwyllys 	FILE *fp;
367030a5e8faSwyllys 	STACK_OF(X509_INFO) *x509_info_stack = NULL;
367130a5e8faSwyllys 	int i, ncerts = 0, matchcerts = 0;
367230a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
367330a5e8faSwyllys 	X509_INFO *info;
367430a5e8faSwyllys 	X509 *x;
36755b3e1433Swyllys 	X509_INFO **cert_infos = NULL;
367630a5e8faSwyllys 	KMF_DATA *certlist = NULL;
367730a5e8faSwyllys 
367830a5e8faSwyllys 	if (priv_key)
367930a5e8faSwyllys 		*priv_key = NULL;
368030a5e8faSwyllys 	if (certs)
368130a5e8faSwyllys 		*certs = NULL;
368230a5e8faSwyllys 	fp = fopen(filename, "r");
36835b3e1433Swyllys 	if (fp == NULL)
368430a5e8faSwyllys 		return (KMF_ERR_OPEN_FILE);
36855b3e1433Swyllys 
368630a5e8faSwyllys 	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
368730a5e8faSwyllys 	if (x509_info_stack == NULL) {
368830a5e8faSwyllys 		(void) fclose(fp);
368930a5e8faSwyllys 		return (KMF_ERR_ENCODING);
369030a5e8faSwyllys 	}
36915b3e1433Swyllys 	cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
36925b3e1433Swyllys 	    sizeof (X509_INFO *));
36935b3e1433Swyllys 	if (cert_infos == NULL) {
36945b3e1433Swyllys 		(void) fclose(fp);
36955b3e1433Swyllys 		rv = KMF_ERR_MEMORY;
36965b3e1433Swyllys 		goto err;
36975b3e1433Swyllys 	}
369899ebb4caSwyllys 
36995b3e1433Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
370030a5e8faSwyllys 		cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
370130a5e8faSwyllys 		ncerts++;
370230a5e8faSwyllys 	}
370399ebb4caSwyllys 
370430a5e8faSwyllys 	if (ncerts == 0) {
370530a5e8faSwyllys 		(void) fclose(fp);
370630a5e8faSwyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
370730a5e8faSwyllys 		goto err;
370830a5e8faSwyllys 	}
370930a5e8faSwyllys 
371030a5e8faSwyllys 	if (priv_key != NULL) {
371130a5e8faSwyllys 		rewind(fp);
371230a5e8faSwyllys 		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
371399ebb4caSwyllys 	}
371430a5e8faSwyllys 	(void) fclose(fp);
371530a5e8faSwyllys 
371630a5e8faSwyllys 	x = cert_infos[ncerts - 1]->x509;
371799ebb4caSwyllys 	/*
371830a5e8faSwyllys 	 * Make sure the private key matchs the last cert in the file.
371999ebb4caSwyllys 	 */
372030a5e8faSwyllys 	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
372130a5e8faSwyllys 		EVP_PKEY_free(pkey);
372230a5e8faSwyllys 		rv = KMF_ERR_KEY_MISMATCH;
372330a5e8faSwyllys 		goto err;
372430a5e8faSwyllys 	}
372599ebb4caSwyllys 
3726a2d4930dSDan OpenSolaris Anderson 	certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
372730a5e8faSwyllys 	if (certlist == NULL) {
372830a5e8faSwyllys 		if (pkey != NULL)
372930a5e8faSwyllys 			EVP_PKEY_free(pkey);
373030a5e8faSwyllys 		rv = KMF_ERR_MEMORY;
373130a5e8faSwyllys 		goto err;
373299ebb4caSwyllys 	}
373330a5e8faSwyllys 
373430a5e8faSwyllys 	/*
373530a5e8faSwyllys 	 * Convert all of the certs to DER format.
373630a5e8faSwyllys 	 */
373730a5e8faSwyllys 	matchcerts = 0;
373830a5e8faSwyllys 	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
373930a5e8faSwyllys 		boolean_t match = FALSE;
374030a5e8faSwyllys 		info =  cert_infos[ncerts - 1 - i];
374130a5e8faSwyllys 
374230a5e8faSwyllys 		rv = check_cert(info->x509, issuer, subject, serial, &match);
374330a5e8faSwyllys 		if (rv != KMF_OK || match != TRUE) {
374430a5e8faSwyllys 			rv = KMF_OK;
374530a5e8faSwyllys 			continue;
374699ebb4caSwyllys 		}
374730a5e8faSwyllys 
374830a5e8faSwyllys 		rv = ssl_cert2KMFDATA(kmfh, info->x509,
37494942e222SAndy Fiddaman 		    &certlist[matchcerts++]);
375030a5e8faSwyllys 
375130a5e8faSwyllys 		if (rv != KMF_OK) {
3752e65e5c2dSWyllys Ingersoll 			int j;
3753e65e5c2dSWyllys Ingersoll 			for (j = 0; j < matchcerts; j++)
3754e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certlist[j]);
375530a5e8faSwyllys 			free(certlist);
375630a5e8faSwyllys 			certlist = NULL;
375730a5e8faSwyllys 			ncerts = matchcerts = 0;
375899ebb4caSwyllys 		}
375999ebb4caSwyllys 	}
376099ebb4caSwyllys 
376130a5e8faSwyllys 	if (numcerts != NULL)
376230a5e8faSwyllys 		*numcerts = matchcerts;
3763a2d4930dSDan OpenSolaris Anderson 
3764e65e5c2dSWyllys Ingersoll 	if (certs != NULL)
376530a5e8faSwyllys 		*certs = certlist;
3766e65e5c2dSWyllys Ingersoll 	else if (certlist != NULL) {
3767e65e5c2dSWyllys Ingersoll 		for (i = 0; i < ncerts; i++)
3768e65e5c2dSWyllys Ingersoll 			kmf_free_data(&certlist[i]);
3769a2d4930dSDan OpenSolaris Anderson 		free(certlist);
3770a2d4930dSDan OpenSolaris Anderson 		certlist = NULL;
3771a2d4930dSDan OpenSolaris Anderson 	}
377230a5e8faSwyllys 
377330a5e8faSwyllys 	if (priv_key == NULL && pkey != NULL)
377430a5e8faSwyllys 		EVP_PKEY_free(pkey);
377530a5e8faSwyllys 	else if (priv_key != NULL && pkey != NULL)
377630a5e8faSwyllys 		*priv_key = pkey;
377730a5e8faSwyllys 
377830a5e8faSwyllys err:
377930a5e8faSwyllys 	/* Cleanup the stack of X509 info records */
378030a5e8faSwyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
378130a5e8faSwyllys 		info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
378230a5e8faSwyllys 		X509_INFO_free(info);
378399ebb4caSwyllys 	}
378430a5e8faSwyllys 	if (x509_info_stack)
378530a5e8faSwyllys 		sk_X509_INFO_free(x509_info_stack);
378699ebb4caSwyllys 
37875b3e1433Swyllys 	if (cert_infos != NULL)
37885b3e1433Swyllys 		free(cert_infos);
37895b3e1433Swyllys 
379030a5e8faSwyllys 	return (rv);
379130a5e8faSwyllys }
379230a5e8faSwyllys 
37935b3e1433Swyllys static KMF_RETURN
openssl_parse_bags(const STACK_OF (PKCS12_SAFEBAG)* bags,char * pin,STACK_OF (EVP_PKEY)* keys,STACK_OF (X509)* certs)3794300fdee2SAndy Fiddaman openssl_parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
37954942e222SAndy Fiddaman     STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
37965b3e1433Swyllys {
37975b3e1433Swyllys 	KMF_RETURN ret;
37985b3e1433Swyllys 	int i;
37995b3e1433Swyllys 
38005b3e1433Swyllys 	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
38015b3e1433Swyllys 		PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
38025b3e1433Swyllys 		ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
38035b3e1433Swyllys 		    keys, certs);
38045b3e1433Swyllys 
38055b3e1433Swyllys 		if (ret != KMF_OK)
38065b3e1433Swyllys 			return (ret);
38075b3e1433Swyllys 	}
38085b3e1433Swyllys 
38095b3e1433Swyllys 	return (ret);
38105b3e1433Swyllys }
38115b3e1433Swyllys 
38125b3e1433Swyllys static KMF_RETURN
set_pkey_attrib(EVP_PKEY * pkey,ASN1_TYPE * attrib,int nid)38135b3e1433Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
38145b3e1433Swyllys {
38155b3e1433Swyllys 	X509_ATTRIBUTE *attr = NULL;
38165b3e1433Swyllys 
38175b3e1433Swyllys 	if (pkey == NULL || attrib == NULL)
38185b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
38195b3e1433Swyllys 
38205b3e1433Swyllys 	attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
38215b3e1433Swyllys 	if (attr != NULL) {
38225b3e1433Swyllys 		int i;
3823300fdee2SAndy Fiddaman 
3824300fdee2SAndy Fiddaman 		if ((i = EVP_PKEY_get_attr_by_NID(pkey, nid, -1)) != -1)
3825300fdee2SAndy Fiddaman 			(void) EVP_PKEY_delete_attr(pkey, i);
3826300fdee2SAndy Fiddaman 		if (EVP_PKEY_add1_attr(pkey, attr) == 0) {
38275b3e1433Swyllys 			X509_ATTRIBUTE_free(attr);
38285b3e1433Swyllys 			return (KMF_ERR_MEMORY);
38295b3e1433Swyllys 		}
38305b3e1433Swyllys 	} else {
38315b3e1433Swyllys 		return (KMF_ERR_MEMORY);
38325b3e1433Swyllys 	}
38335b3e1433Swyllys 
38345b3e1433Swyllys 	return (KMF_OK);
38355b3e1433Swyllys }
38365b3e1433Swyllys 
38375b3e1433Swyllys static KMF_RETURN
openssl_parse_bag(PKCS12_SAFEBAG * bag,char * pass,int passlen,STACK_OF (EVP_PKEY)* keylist,STACK_OF (X509)* certlist)38385b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
38394942e222SAndy Fiddaman     STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
38405b3e1433Swyllys {
38415b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
38425b3e1433Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
38435b3e1433Swyllys 	EVP_PKEY *pkey = NULL;
38445b3e1433Swyllys 	X509 *xcert = NULL;
3845300fdee2SAndy Fiddaman 	const ASN1_TYPE *keyid = NULL;
3846300fdee2SAndy Fiddaman 	const ASN1_TYPE *fname = NULL;
38475b3e1433Swyllys 	uchar_t *data = NULL;
38485b3e1433Swyllys 
3849300fdee2SAndy Fiddaman 	keyid = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID);
3850300fdee2SAndy Fiddaman 	fname = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName);
38515b3e1433Swyllys 
3852300fdee2SAndy Fiddaman 	switch (PKCS12_SAFEBAG_get_nid(bag)) {
38535b3e1433Swyllys 		case NID_keyBag:
38545b3e1433Swyllys 			if (keylist == NULL)
38555b3e1433Swyllys 				goto end;
3856300fdee2SAndy Fiddaman 			pkey = EVP_PKCS82PKEY(
3857300fdee2SAndy Fiddaman 			    PKCS12_SAFEBAG_get0_p8inf(bag));
38585b3e1433Swyllys 			if (pkey == NULL)
38595b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38605b3e1433Swyllys 
38615b3e1433Swyllys 			break;
38625b3e1433Swyllys 		case NID_pkcs8ShroudedKeyBag:
38635b3e1433Swyllys 			if (keylist == NULL)
38645b3e1433Swyllys 				goto end;
3865300fdee2SAndy Fiddaman 			p8 = PKCS12_decrypt_skey(bag, pass, passlen);
38665b3e1433Swyllys 			if (p8 == NULL)
38675b3e1433Swyllys 				return (KMF_ERR_AUTH_FAILED);
38685b3e1433Swyllys 			pkey = EVP_PKCS82PKEY(p8);
38695b3e1433Swyllys 			PKCS8_PRIV_KEY_INFO_free(p8);
38705b3e1433Swyllys 			if (pkey == NULL)
38715b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38725b3e1433Swyllys 			break;
38735b3e1433Swyllys 		case NID_certBag:
38745b3e1433Swyllys 			if (certlist == NULL)
38755b3e1433Swyllys 				goto end;
3876300fdee2SAndy Fiddaman 			if (PKCS12_SAFEBAG_get_bag_nid(bag) !=
3877300fdee2SAndy Fiddaman 			    NID_x509Certificate)
38785b3e1433Swyllys 				return (KMF_ERR_PKCS12_FORMAT);
3879300fdee2SAndy Fiddaman 			xcert = PKCS12_SAFEBAG_get1_cert(bag);
38805b3e1433Swyllys 			if (xcert == NULL) {
38815b3e1433Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38825b3e1433Swyllys 				goto end;
38835b3e1433Swyllys 			}
38845b3e1433Swyllys 			if (keyid != NULL) {
38855b3e1433Swyllys 				if (X509_keyid_set1(xcert,
38865b3e1433Swyllys 				    keyid->value.octet_string->data,
38875b3e1433Swyllys 				    keyid->value.octet_string->length) == 0) {
38885b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
38895b3e1433Swyllys 					goto end;
38905b3e1433Swyllys 				}
38915b3e1433Swyllys 			}
38925b3e1433Swyllys 			if (fname != NULL) {
38935b3e1433Swyllys 				int len, r;
38945b3e1433Swyllys 				len = ASN1_STRING_to_UTF8(&data,
38955b3e1433Swyllys 				    fname->value.asn1_string);
38965b3e1433Swyllys 				if (len > 0 && data != NULL) {
38975b3e1433Swyllys 					r = X509_alias_set1(xcert, data, len);
3898f810c7e5SToomas Soome 					if (r == 0) {
38995b3e1433Swyllys 						ret = KMF_ERR_PKCS12_FORMAT;
39005b3e1433Swyllys 						goto end;
39015b3e1433Swyllys 					}
39025b3e1433Swyllys 				} else {
39035b3e1433Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
39045b3e1433Swyllys 					goto end;
39055b3e1433Swyllys 				}
39065b3e1433Swyllys 			}
39075b3e1433Swyllys 			if (sk_X509_push(certlist, xcert) == 0)
39085b3e1433Swyllys 				ret = KMF_ERR_MEMORY;
39095b3e1433Swyllys 			else
39105b3e1433Swyllys 				xcert = NULL;
39115b3e1433Swyllys 			break;
39125b3e1433Swyllys 		case NID_safeContentsBag:
3913300fdee2SAndy Fiddaman 			return (openssl_parse_bags(
3914300fdee2SAndy Fiddaman 			    PKCS12_SAFEBAG_get0_safes(bag),
3915300fdee2SAndy Fiddaman 			    pass, keylist, certlist));
39165b3e1433Swyllys 		default:
39175b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39185b3e1433Swyllys 			break;
39195b3e1433Swyllys 	}
39205b3e1433Swyllys 
39215b3e1433Swyllys 	/*
39225b3e1433Swyllys 	 * Set the ID and/or FriendlyName attributes on the key.
39235b3e1433Swyllys 	 * If converting to PKCS11 objects, these can translate to CKA_ID
39245b3e1433Swyllys 	 * and CKA_LABEL values.
39255b3e1433Swyllys 	 */
39265b3e1433Swyllys 	if (pkey != NULL && ret == KMF_OK) {
39275b3e1433Swyllys 		ASN1_TYPE *attr = NULL;
39285b3e1433Swyllys 		if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
39295b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
39305b3e1433Swyllys 				return (KMF_ERR_MEMORY);
39315b3e1433Swyllys 			attr->value.octet_string =
39325b3e1433Swyllys 			    ASN1_STRING_dup(keyid->value.octet_string);
39335b3e1433Swyllys 			attr->type = V_ASN1_OCTET_STRING;
39345b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.octet_string;
39355b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
39365b3e1433Swyllys 			OPENSSL_free(attr);
39375b3e1433Swyllys 		}
39385b3e1433Swyllys 
39395b3e1433Swyllys 		if (ret == KMF_OK && fname != NULL &&
39405b3e1433Swyllys 		    fname->type == V_ASN1_BMPSTRING) {
39415b3e1433Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
39425b3e1433Swyllys 				return (KMF_ERR_MEMORY);
39435b3e1433Swyllys 			attr->value.bmpstring =
39445b3e1433Swyllys 			    ASN1_STRING_dup(fname->value.bmpstring);
39455b3e1433Swyllys 			attr->type = V_ASN1_BMPSTRING;
39465b3e1433Swyllys 			attr->value.ptr = (char *)attr->value.bmpstring;
39475b3e1433Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
39485b3e1433Swyllys 			OPENSSL_free(attr);
39495b3e1433Swyllys 		}
39505b3e1433Swyllys 
39515b3e1433Swyllys 		if (ret == KMF_OK && keylist != NULL &&
39525b3e1433Swyllys 		    sk_EVP_PKEY_push(keylist, pkey) == 0)
39535b3e1433Swyllys 			ret = KMF_ERR_MEMORY;
39545b3e1433Swyllys 	}
39555b3e1433Swyllys 	if (ret == KMF_OK && keylist != NULL)
39565b3e1433Swyllys 		pkey = NULL;
39575b3e1433Swyllys end:
39585b3e1433Swyllys 	if (pkey != NULL)
39595b3e1433Swyllys 		EVP_PKEY_free(pkey);
39605b3e1433Swyllys 	if (xcert != NULL)
39615b3e1433Swyllys 		X509_free(xcert);
39625b3e1433Swyllys 	if (data != NULL)
39635b3e1433Swyllys 		OPENSSL_free(data);
39645b3e1433Swyllys 
39655b3e1433Swyllys 	return (ret);
39665b3e1433Swyllys }
39675b3e1433Swyllys 
39685b3e1433Swyllys static KMF_RETURN
openssl_pkcs12_parse(PKCS12 * p12,char * pin,STACK_OF (EVP_PKEY)* keys,STACK_OF (X509)* certs,STACK_OF (X509)* ca)39694942e222SAndy Fiddaman openssl_pkcs12_parse(PKCS12 *p12, char *pin, STACK_OF(EVP_PKEY) *keys,
39704942e222SAndy Fiddaman     STACK_OF(X509) *certs, STACK_OF(X509) *ca)
39715b3e1433Swyllys {
39725b3e1433Swyllys 	KMF_RETURN ret = KMF_OK;
39735b3e1433Swyllys 	STACK_OF(PKCS7) *asafes = NULL;
39745b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
39755b3e1433Swyllys 	int i, bagnid;
39765b3e1433Swyllys 	PKCS7 *p7;
39775b3e1433Swyllys 
39785b3e1433Swyllys 	if (p12 == NULL || (keys == NULL && certs == NULL))
39795b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
39805b3e1433Swyllys 
3981f810c7e5SToomas Soome 	if (pin == NULL || *pin == '\0') {
39825b3e1433Swyllys 		if (PKCS12_verify_mac(p12, NULL, 0)) {
39835b3e1433Swyllys 			pin = NULL;
39845b3e1433Swyllys 		} else if (PKCS12_verify_mac(p12, "", 0)) {
39855b3e1433Swyllys 			pin = "";
39865b3e1433Swyllys 		} else {
39875b3e1433Swyllys 			return (KMF_ERR_AUTH_FAILED);
39885b3e1433Swyllys 		}
39895b3e1433Swyllys 	} else if (!PKCS12_verify_mac(p12, pin, -1)) {
39905b3e1433Swyllys 		return (KMF_ERR_AUTH_FAILED);
39915b3e1433Swyllys 	}
39925b3e1433Swyllys 
39935b3e1433Swyllys 	if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
39945b3e1433Swyllys 		return (KMF_ERR_PKCS12_FORMAT);
39955b3e1433Swyllys 
39965b3e1433Swyllys 	for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
39975b3e1433Swyllys 		bags = NULL;
39985b3e1433Swyllys 		p7 = sk_PKCS7_value(asafes, i);
39995b3e1433Swyllys 		bagnid = OBJ_obj2nid(p7->type);
40005b3e1433Swyllys 
40015b3e1433Swyllys 		if (bagnid == NID_pkcs7_data) {
40025b3e1433Swyllys 			bags = PKCS12_unpack_p7data(p7);
40035b3e1433Swyllys 		} else if (bagnid == NID_pkcs7_encrypted) {
40045b3e1433Swyllys 			bags = PKCS12_unpack_p7encdata(p7, pin,
40055b3e1433Swyllys 			    (pin ? strlen(pin) : 0));
40065b3e1433Swyllys 		} else {
40075b3e1433Swyllys 			continue;
40085b3e1433Swyllys 		}
40095b3e1433Swyllys 		if (bags == NULL) {
40105b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
40115b3e1433Swyllys 			goto out;
40125b3e1433Swyllys 		}
40135b3e1433Swyllys 
40145b3e1433Swyllys 		if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
40155b3e1433Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
40165b3e1433Swyllys 
40175b3e1433Swyllys 		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
40185b3e1433Swyllys 	}
40195b3e1433Swyllys out:
40205b3e1433Swyllys 	if (asafes != NULL)
40215b3e1433Swyllys 		sk_PKCS7_pop_free(asafes, PKCS7_free);
40225b3e1433Swyllys 
40235b3e1433Swyllys 	return (ret);
40245b3e1433Swyllys }
40255b3e1433Swyllys 
402630a5e8faSwyllys /*
402730a5e8faSwyllys  * Helper function to decrypt and parse PKCS#12 import file.
402830a5e8faSwyllys  */
402930a5e8faSwyllys static KMF_RETURN
extract_pkcs12(BIO * fbio,CK_UTF8CHAR * pin,CK_ULONG pinlen,STACK_OF (EVP_PKEY)** priv_key,STACK_OF (X509)** certs,STACK_OF (X509)** ca)403030a5e8faSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
40314942e222SAndy Fiddaman     STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs, STACK_OF(X509) **ca)
403230a5e8faSwyllys {
40335b3e1433Swyllys 	PKCS12			*pk12, *pk12_tmp;
40345b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*pkeylist = NULL;
40355b3e1433Swyllys 	STACK_OF(X509)		*xcertlist = NULL;
40365b3e1433Swyllys 	STACK_OF(X509)		*cacertlist = NULL;
403730a5e8faSwyllys 
403830a5e8faSwyllys 	if ((pk12 = PKCS12_new()) == NULL) {
403930a5e8faSwyllys 		return (KMF_ERR_MEMORY);
404099ebb4caSwyllys 	}
404199ebb4caSwyllys 
404230a5e8faSwyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
404330a5e8faSwyllys 		/* This is ok; it seems to mean there is no more to read. */
404430a5e8faSwyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
404530a5e8faSwyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
404630a5e8faSwyllys 			goto end_extract_pkcs12;
404730a5e8faSwyllys 
404830a5e8faSwyllys 		PKCS12_free(pk12);
404930a5e8faSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
405099ebb4caSwyllys 	}
405130a5e8faSwyllys 	pk12 = pk12_tmp;
405299ebb4caSwyllys 
40535b3e1433Swyllys 	xcertlist = sk_X509_new_null();
40545b3e1433Swyllys 	if (xcertlist == NULL) {
40555b3e1433Swyllys 		PKCS12_free(pk12);
40565b3e1433Swyllys 		return (KMF_ERR_MEMORY);
40575b3e1433Swyllys 	}
40585b3e1433Swyllys 	pkeylist = sk_EVP_PKEY_new_null();
40595b3e1433Swyllys 	if (pkeylist == NULL) {
40605b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40615b3e1433Swyllys 		PKCS12_free(pk12);
40625b3e1433Swyllys 		return (KMF_ERR_MEMORY);
40635b3e1433Swyllys 	}
40645b3e1433Swyllys 
40655b3e1433Swyllys 	if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
40665b3e1433Swyllys 	    cacertlist) != KMF_OK) {
40675b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40685b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
406930a5e8faSwyllys 		PKCS12_free(pk12);
407030a5e8faSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
407199ebb4caSwyllys 	}
407230a5e8faSwyllys 
40735b3e1433Swyllys 	if (priv_key && pkeylist)
40745b3e1433Swyllys 		*priv_key = pkeylist;
40755b3e1433Swyllys 	else if (pkeylist)
40765b3e1433Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
40775b3e1433Swyllys 	if (certs && xcertlist)
40785b3e1433Swyllys 		*certs = xcertlist;
40795b3e1433Swyllys 	else if (xcertlist)
40805b3e1433Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40815b3e1433Swyllys 	if (ca && cacertlist)
40825b3e1433Swyllys 		*ca = cacertlist;
40835b3e1433Swyllys 	else if (cacertlist)
40845b3e1433Swyllys 		sk_X509_pop_free(cacertlist, X509_free);
408530a5e8faSwyllys 
40865b3e1433Swyllys end_extract_pkcs12:
408730a5e8faSwyllys 
408830a5e8faSwyllys 	PKCS12_free(pk12);
408930a5e8faSwyllys 	return (KMF_OK);
409099ebb4caSwyllys }
409199ebb4caSwyllys 
409230a5e8faSwyllys static KMF_RETURN
sslBN2KMFBN(BIGNUM * from,KMF_BIGINT * to)409330a5e8faSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
409499ebb4caSwyllys {
409530a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
409630a5e8faSwyllys 	uint32_t sz;
409799ebb4caSwyllys 
409830a5e8faSwyllys 	sz = BN_num_bytes(from);
409930a5e8faSwyllys 	to->val = (uchar_t *)malloc(sz);
410030a5e8faSwyllys 	if (to->val == NULL)
410130a5e8faSwyllys 		return (KMF_ERR_MEMORY);
410299ebb4caSwyllys 
410330a5e8faSwyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
410430a5e8faSwyllys 		free(to->val);
410530a5e8faSwyllys 		to->val = NULL;
410630a5e8faSwyllys 		to->len = 0;
410730a5e8faSwyllys 		rv = KMF_ERR_MEMORY;
410830a5e8faSwyllys 	}
410999ebb4caSwyllys 
411030a5e8faSwyllys 	return (rv);
411130a5e8faSwyllys }
411299ebb4caSwyllys 
411330a5e8faSwyllys static KMF_RETURN
exportRawRSAKey(RSA * rsa,KMF_RAW_KEY_DATA * key)411430a5e8faSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
411530a5e8faSwyllys {
411630a5e8faSwyllys 	KMF_RETURN rv;
411730a5e8faSwyllys 	KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
411899ebb4caSwyllys 
4119300fdee2SAndy Fiddaman 	const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmpq, *iqmp;
4120300fdee2SAndy Fiddaman 
4121300fdee2SAndy Fiddaman 	RSA_get0_key(rsa, &n, &e, &d);
4122300fdee2SAndy Fiddaman 	RSA_get0_factors(rsa, &p, &q);
4123300fdee2SAndy Fiddaman 	RSA_get0_crt_params(rsa, &dmp1, &dmpq, &iqmp);
4124300fdee2SAndy Fiddaman 
412530a5e8faSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
4126300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)n, &kmfkey->mod)) != KMF_OK)
412730a5e8faSwyllys 		goto cleanup;
412899ebb4caSwyllys 
4129300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)e, &kmfkey->pubexp)) != KMF_OK)
413030a5e8faSwyllys 		goto cleanup;
413199ebb4caSwyllys 
4132300fdee2SAndy Fiddaman 	if (d != NULL)
4133300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)d, &kmfkey->priexp)) != KMF_OK)
413430a5e8faSwyllys 			goto cleanup;
413599ebb4caSwyllys 
4136300fdee2SAndy Fiddaman 	if (p != NULL)
4137300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime1)) != KMF_OK)
413830a5e8faSwyllys 			goto cleanup;
413999ebb4caSwyllys 
4140300fdee2SAndy Fiddaman 	if (q != NULL)
4141300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->prime2)) != KMF_OK)
414230a5e8faSwyllys 			goto cleanup;
414399ebb4caSwyllys 
4144300fdee2SAndy Fiddaman 	if (dmp1 != NULL)
4145300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)dmp1, &kmfkey->exp1)) != KMF_OK)
414630a5e8faSwyllys 			goto cleanup;
414799ebb4caSwyllys 
4148300fdee2SAndy Fiddaman 	if (dmpq != NULL)
4149300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)dmpq, &kmfkey->exp2)) != KMF_OK)
415030a5e8faSwyllys 			goto cleanup;
415199ebb4caSwyllys 
4152300fdee2SAndy Fiddaman 	if (iqmp != NULL)
4153300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)iqmp, &kmfkey->coef)) != KMF_OK)
415430a5e8faSwyllys 			goto cleanup;
415530a5e8faSwyllys cleanup:
415630a5e8faSwyllys 	if (rv != KMF_OK)
415730a5e8faSwyllys 		kmf_free_raw_key(key);
415830a5e8faSwyllys 	else
415930a5e8faSwyllys 		key->keytype = KMF_RSA;
416030a5e8faSwyllys 
416130a5e8faSwyllys 	/*
416230a5e8faSwyllys 	 * Free the reference to this key, SSL will not actually free
416330a5e8faSwyllys 	 * the memory until the refcount == 0, so this is safe.
416430a5e8faSwyllys 	 */
416599ebb4caSwyllys 	RSA_free(rsa);
416699ebb4caSwyllys 
416730a5e8faSwyllys 	return (rv);
416899ebb4caSwyllys }
416999ebb4caSwyllys 
417030a5e8faSwyllys static KMF_RETURN
exportRawDSAKey(DSA * dsa,KMF_RAW_KEY_DATA * key)417130a5e8faSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
417299ebb4caSwyllys {
417330a5e8faSwyllys 	KMF_RETURN rv;
417430a5e8faSwyllys 	KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
4175300fdee2SAndy Fiddaman 	const BIGNUM *p, *q, *g, *priv_key;
4176300fdee2SAndy Fiddaman 
4177300fdee2SAndy Fiddaman 	DSA_get0_pqg(dsa, &p, &q, &g);
4178300fdee2SAndy Fiddaman 	DSA_get0_key(dsa, NULL, &priv_key);
417999ebb4caSwyllys 
418030a5e8faSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
4181300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime)) != KMF_OK)
418230a5e8faSwyllys 		goto cleanup;
418399ebb4caSwyllys 
4184300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->subprime)) != KMF_OK)
418530a5e8faSwyllys 		goto cleanup;
418699ebb4caSwyllys 
4187300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)g, &kmfkey->base)) != KMF_OK)
418830a5e8faSwyllys 		goto cleanup;
418999ebb4caSwyllys 
4190300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)priv_key, &kmfkey->value)) != KMF_OK)
419130a5e8faSwyllys 		goto cleanup;
419299ebb4caSwyllys 
419330a5e8faSwyllys cleanup:
419430a5e8faSwyllys 	if (rv != KMF_OK)
419530a5e8faSwyllys 		kmf_free_raw_key(key);
419630a5e8faSwyllys 	else
419730a5e8faSwyllys 		key->keytype = KMF_DSA;
419899ebb4caSwyllys 
419930a5e8faSwyllys 	/*
420030a5e8faSwyllys 	 * Free the reference to this key, SSL will not actually free
420130a5e8faSwyllys 	 * the memory until the refcount == 0, so this is safe.
420230a5e8faSwyllys 	 */
420399ebb4caSwyllys 	DSA_free(dsa);
420430a5e8faSwyllys 
420530a5e8faSwyllys 	return (rv);
420699ebb4caSwyllys }
420799ebb4caSwyllys 
420899ebb4caSwyllys static KMF_RETURN
add_cert_to_list(KMF_HANDLE * kmfh,X509 * sslcert,KMF_X509_DER_CERT ** certlist,int * ncerts)420930a5e8faSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
42104942e222SAndy Fiddaman     KMF_X509_DER_CERT **certlist, int *ncerts)
421199ebb4caSwyllys {
421299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
42135b3e1433Swyllys 	KMF_X509_DER_CERT *list = (*certlist);
42145b3e1433Swyllys 	KMF_X509_DER_CERT cert;
421530a5e8faSwyllys 	int n = (*ncerts);
421699ebb4caSwyllys 
421730a5e8faSwyllys 	if (list == NULL) {
42185b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
421930a5e8faSwyllys 	} else {
42205b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)realloc(list,
42215b3e1433Swyllys 		    sizeof (KMF_X509_DER_CERT) * (n + 1));
422299ebb4caSwyllys 	}
422399ebb4caSwyllys 
422430a5e8faSwyllys 	if (list == NULL)
422530a5e8faSwyllys 		return (KMF_ERR_MEMORY);
422699ebb4caSwyllys 
42275b3e1433Swyllys 	(void) memset(&cert, 0, sizeof (cert));
42285b3e1433Swyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
422930a5e8faSwyllys 	if (rv == KMF_OK) {
42305b3e1433Swyllys 		int len = 0;
42315b3e1433Swyllys 		/* Get the alias name for the cert if there is one */
42325b3e1433Swyllys 		char *a = (char *)X509_alias_get0(sslcert, &len);
42335b3e1433Swyllys 		if (a != NULL)
42345b3e1433Swyllys 			cert.kmf_private.label = strdup(a);
42355b3e1433Swyllys 		cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
42365b3e1433Swyllys 
423730a5e8faSwyllys 		list[n] = cert;
423830a5e8faSwyllys 		(*ncerts) = n + 1;
423999ebb4caSwyllys 
424030a5e8faSwyllys 		*certlist = list;
424130a5e8faSwyllys 	} else {
424230a5e8faSwyllys 		free(list);
424399ebb4caSwyllys 	}
424499ebb4caSwyllys 
424599ebb4caSwyllys 	return (rv);
424699ebb4caSwyllys }
424799ebb4caSwyllys 
424830a5e8faSwyllys static KMF_RETURN
add_key_to_list(KMF_RAW_KEY_DATA ** keylist,KMF_RAW_KEY_DATA * newkey,int * nkeys)424930a5e8faSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
42504942e222SAndy Fiddaman     KMF_RAW_KEY_DATA *newkey, int *nkeys)
425199ebb4caSwyllys {
425230a5e8faSwyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
425330a5e8faSwyllys 	int n = (*nkeys);
425499ebb4caSwyllys 
425530a5e8faSwyllys 	if (list == NULL) {
425630a5e8faSwyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
425730a5e8faSwyllys 	} else {
425830a5e8faSwyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
425930a5e8faSwyllys 		    sizeof (KMF_RAW_KEY_DATA) * (n + 1));
426099ebb4caSwyllys 	}
426199ebb4caSwyllys 
426230a5e8faSwyllys 	if (list == NULL)
426330a5e8faSwyllys 		return (KMF_ERR_MEMORY);
426499ebb4caSwyllys 
426530a5e8faSwyllys 	list[n] = *newkey;
426630a5e8faSwyllys 	(*nkeys) = n + 1;
426799ebb4caSwyllys 
426830a5e8faSwyllys 	*keylist = list;
426999ebb4caSwyllys 
427030a5e8faSwyllys 	return (KMF_OK);
427130a5e8faSwyllys }
427299ebb4caSwyllys 
427330a5e8faSwyllys static KMF_RETURN
convertToRawKey(EVP_PKEY * pkey,KMF_RAW_KEY_DATA * key)427430a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
427530a5e8faSwyllys {
427630a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
42775b3e1433Swyllys 	X509_ATTRIBUTE *attr;
4278300fdee2SAndy Fiddaman 	RSA *rsa;
4279300fdee2SAndy Fiddaman 	DSA *dsa;
4280300fdee2SAndy Fiddaman 	int loc;
428199ebb4caSwyllys 
428230a5e8faSwyllys 	if (pkey == NULL || key == NULL)
428330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
428430a5e8faSwyllys 	/* Convert SSL key to raw key */
4285300fdee2SAndy Fiddaman 	if ((rsa = EVP_PKEY_get1_RSA(pkey)) != NULL) {
4286300fdee2SAndy Fiddaman 		rv = exportRawRSAKey(rsa, key);
4287300fdee2SAndy Fiddaman 		if (rv != KMF_OK)
4288300fdee2SAndy Fiddaman 			return (rv);
4289300fdee2SAndy Fiddaman 	} else if ((dsa = EVP_PKEY_get1_DSA(pkey)) != NULL) {
4290300fdee2SAndy Fiddaman 		rv = exportRawDSAKey(dsa, key);
4291300fdee2SAndy Fiddaman 		if (rv != KMF_OK)
4292300fdee2SAndy Fiddaman 			return (rv);
4293300fdee2SAndy Fiddaman 	} else
4294300fdee2SAndy Fiddaman 		return (KMF_ERR_BAD_PARAMETER);
4295300fdee2SAndy Fiddaman 
42965b3e1433Swyllys 	/*
42975b3e1433Swyllys 	 * If friendlyName, add it to record.
42985b3e1433Swyllys 	 */
4299300fdee2SAndy Fiddaman 
4300300fdee2SAndy Fiddaman 	if ((loc = EVP_PKEY_get_attr_by_NID(pkey,
4301300fdee2SAndy Fiddaman 	    NID_friendlyName, -1)) != -1 &&
4302300fdee2SAndy Fiddaman 	    (attr = EVP_PKEY_get_attr(pkey, loc))) {
43035b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
4304300fdee2SAndy Fiddaman 		int numattr = X509_ATTRIBUTE_count(attr);
4305300fdee2SAndy Fiddaman 		if (numattr > 0) {
4306300fdee2SAndy Fiddaman 			ty = X509_ATTRIBUTE_get0_type(attr, 0);
43075b3e1433Swyllys 		}
43085b3e1433Swyllys 		if (ty != NULL) {
430970f9559bSTheo Schlossnagle 			key->label = OPENSSL_uni2asc(ty->value.bmpstring->data,
431070f9559bSTheo Schlossnagle 			    ty->value.bmpstring->length);
43115b3e1433Swyllys 		}
43125b3e1433Swyllys 	} else {
43135b3e1433Swyllys 		key->label = NULL;
43145b3e1433Swyllys 	}
43155b3e1433Swyllys 
43165b3e1433Swyllys 	/*
43175b3e1433Swyllys 	 * If KeyID, add it to record as a KMF_DATA object.
43185b3e1433Swyllys 	 */
4319300fdee2SAndy Fiddaman 	if ((loc = EVP_PKEY_get_attr_by_NID(pkey,
4320300fdee2SAndy Fiddaman 	    NID_localKeyID, -1)) != -1 &&
4321300fdee2SAndy Fiddaman 	    (attr = EVP_PKEY_get_attr(pkey, loc)) != NULL) {
43225b3e1433Swyllys 		ASN1_TYPE *ty = NULL;
4323300fdee2SAndy Fiddaman 		int numattr = X509_ATTRIBUTE_count(attr);
4324300fdee2SAndy Fiddaman 		if (numattr > 0)
4325300fdee2SAndy Fiddaman 			ty = X509_ATTRIBUTE_get0_type(attr, 0);
43265b3e1433Swyllys 		key->id.Data = (uchar_t *)malloc(
43275b3e1433Swyllys 		    ty->value.octet_string->length);
43285b3e1433Swyllys 		if (key->id.Data == NULL)
43295b3e1433Swyllys 			return (KMF_ERR_MEMORY);
43305b3e1433Swyllys 		(void) memcpy(key->id.Data, ty->value.octet_string->data,
43315b3e1433Swyllys 		    ty->value.octet_string->length);
43325b3e1433Swyllys 		key->id.Length = ty->value.octet_string->length;
43335b3e1433Swyllys 	} else {
43345b3e1433Swyllys 		(void) memset(&key->id, 0, sizeof (KMF_DATA));
43355b3e1433Swyllys 	}
433699ebb4caSwyllys 
433799ebb4caSwyllys 	return (rv);
433899ebb4caSwyllys }
433999ebb4caSwyllys 
434071593db2Swyllys static KMF_RETURN
convertPK12Objects(KMF_HANDLE * kmfh,STACK_OF (EVP_PKEY)* sslkeys,STACK_OF (X509)* sslcert,STACK_OF (X509)* sslcacerts,KMF_RAW_KEY_DATA ** keylist,int * nkeys,KMF_X509_DER_CERT ** certlist,int * ncerts)434130a5e8faSwyllys convertPK12Objects(
434230a5e8faSwyllys 	KMF_HANDLE *kmfh,
43435b3e1433Swyllys 	STACK_OF(EVP_PKEY) *sslkeys,
43445b3e1433Swyllys 	STACK_OF(X509) *sslcert,
43455b3e1433Swyllys 	STACK_OF(X509) *sslcacerts,
434630a5e8faSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
43475b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
434871593db2Swyllys {
434971593db2Swyllys 	KMF_RETURN rv = KMF_OK;
435030a5e8faSwyllys 	KMF_RAW_KEY_DATA key;
435130a5e8faSwyllys 	int i;
435271593db2Swyllys 
43535b3e1433Swyllys 	for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
43545b3e1433Swyllys 		EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
43555b3e1433Swyllys 		rv = convertToRawKey(pkey, &key);
435630a5e8faSwyllys 		if (rv == KMF_OK)
435730a5e8faSwyllys 			rv = add_key_to_list(keylist, &key, nkeys);
435830a5e8faSwyllys 
435930a5e8faSwyllys 		if (rv != KMF_OK)
436030a5e8faSwyllys 			return (rv);
436171593db2Swyllys 	}
436271593db2Swyllys 
436330a5e8faSwyllys 	/* Now add the certificate to the certlist */
43645b3e1433Swyllys 	for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
43655b3e1433Swyllys 		X509 *cert = sk_X509_value(sslcert, i);
43665b3e1433Swyllys 		rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
436730a5e8faSwyllys 		if (rv != KMF_OK)
436830a5e8faSwyllys 			return (rv);
436971593db2Swyllys 	}
437071593db2Swyllys 
437130a5e8faSwyllys 	/* Also add any included CA certs to the list */
437230a5e8faSwyllys 	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
437330a5e8faSwyllys 		X509 *c;
437430a5e8faSwyllys 		/*
437530a5e8faSwyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
437630a5e8faSwyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
437730a5e8faSwyllys 		 * Lint is complaining about the embedded casting, and
437830a5e8faSwyllys 		 * to fix it, you need to fix openssl header files.
437930a5e8faSwyllys 		 */
438030a5e8faSwyllys 		c = sk_X509_value(sslcacerts, i);
438130a5e8faSwyllys 
438230a5e8faSwyllys 		/* Now add the ca cert to the certlist */
438330a5e8faSwyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
438430a5e8faSwyllys 		if (rv != KMF_OK)
438530a5e8faSwyllys 			return (rv);
438671593db2Swyllys 	}
438730a5e8faSwyllys 	return (rv);
438830a5e8faSwyllys }
438930a5e8faSwyllys 
439030a5e8faSwyllys KMF_RETURN
openssl_import_objects(KMF_HANDLE * kmfh,char * filename,KMF_CREDENTIAL * cred,KMF_X509_DER_CERT ** certlist,int * ncerts,KMF_RAW_KEY_DATA ** keylist,int * nkeys)43914942e222SAndy Fiddaman openssl_import_objects(KMF_HANDLE *kmfh, char *filename, KMF_CREDENTIAL *cred,
43924942e222SAndy Fiddaman     KMF_X509_DER_CERT **certlist, int *ncerts,
43934942e222SAndy Fiddaman     KMF_RAW_KEY_DATA **keylist, int *nkeys)
439430a5e8faSwyllys {
439530a5e8faSwyllys 	KMF_RETURN	rv = KMF_OK;
439630a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
439730a5e8faSwyllys 	BIO		*bio = NULL;
43985b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*privkeys = NULL;
43995b3e1433Swyllys 	STACK_OF(X509)		*certs = NULL;
44005b3e1433Swyllys 	STACK_OF(X509)		*cacerts = NULL;
440171593db2Swyllys 
440271593db2Swyllys 	/*
440330a5e8faSwyllys 	 * auto-detect the file format, regardless of what
440430a5e8faSwyllys 	 * the 'format' parameters in the params say.
440571593db2Swyllys 	 */
440630a5e8faSwyllys 	rv = kmf_get_file_format(filename, &format);
440730a5e8faSwyllys 	if (rv != KMF_OK) {
440830a5e8faSwyllys 		return (rv);
440971593db2Swyllys 	}
441071593db2Swyllys 
441130a5e8faSwyllys 	/* This function only works for PEM or PKCS#12 files */
441230a5e8faSwyllys 	if (format != KMF_FORMAT_PEM &&
441330a5e8faSwyllys 	    format != KMF_FORMAT_PEM_KEYPAIR &&
441430a5e8faSwyllys 	    format != KMF_FORMAT_PKCS12)
441530a5e8faSwyllys 		return (KMF_ERR_ENCODING);
441671593db2Swyllys 
441730a5e8faSwyllys 	*certlist = NULL;
441830a5e8faSwyllys 	*keylist = NULL;
441930a5e8faSwyllys 	*ncerts = 0;
442030a5e8faSwyllys 	*nkeys = 0;
442171593db2Swyllys 
442230a5e8faSwyllys 	if (format == KMF_FORMAT_PKCS12) {
442330a5e8faSwyllys 		bio = BIO_new_file(filename, "rb");
442430a5e8faSwyllys 		if (bio == NULL) {
442530a5e8faSwyllys 			SET_ERROR(kmfh, ERR_get_error());
442630a5e8faSwyllys 			rv = KMF_ERR_OPEN_FILE;
442730a5e8faSwyllys 			goto end;
442802744e81Swyllys 		}
442902744e81Swyllys 
443030a5e8faSwyllys 		rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
44315b3e1433Swyllys 		    (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
443271593db2Swyllys 
443330a5e8faSwyllys 		if (rv  == KMF_OK)
443430a5e8faSwyllys 			/* Convert keys and certs to exportable format */
44355b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
443630a5e8faSwyllys 			    keylist, nkeys, certlist, ncerts);
443730a5e8faSwyllys 	} else {
44385b3e1433Swyllys 		EVP_PKEY *pkey;
44395b3e1433Swyllys 		KMF_DATA *certdata = NULL;
44405b3e1433Swyllys 		KMF_X509_DER_CERT *kmfcerts = NULL;
44415b3e1433Swyllys 		int i;
444230a5e8faSwyllys 		rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
444330a5e8faSwyllys 		    (uchar_t *)cred->cred, (uint32_t)cred->credlen,
44445b3e1433Swyllys 		    &pkey, &certdata, ncerts);
444530a5e8faSwyllys 
444630a5e8faSwyllys 		/* Reached end of import file? */
44475b3e1433Swyllys 		if (rv == KMF_OK && pkey != NULL) {
44485b3e1433Swyllys 			privkeys = sk_EVP_PKEY_new_null();
44495b3e1433Swyllys 			if (privkeys == NULL) {
44505b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
44515b3e1433Swyllys 				goto end;
44525b3e1433Swyllys 			}
44535b3e1433Swyllys 			(void) sk_EVP_PKEY_push(privkeys, pkey);
44545b3e1433Swyllys 			/* convert the certificate list here */
44555b3e1433Swyllys 			if (*ncerts > 0 && certlist != NULL) {
4456e65e5c2dSWyllys Ingersoll 				kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
44575b3e1433Swyllys 				    sizeof (KMF_X509_DER_CERT));
44585b3e1433Swyllys 				if (kmfcerts == NULL) {
44595b3e1433Swyllys 					rv = KMF_ERR_MEMORY;
44605b3e1433Swyllys 					goto end;
44615b3e1433Swyllys 				}
44625b3e1433Swyllys 				for (i = 0; i < *ncerts; i++) {
44635b3e1433Swyllys 					kmfcerts[i].certificate = certdata[i];
44645b3e1433Swyllys 					kmfcerts[i].kmf_private.keystore_type =
44655b3e1433Swyllys 					    KMF_KEYSTORE_OPENSSL;
44665b3e1433Swyllys 				}
44675b3e1433Swyllys 				*certlist = kmfcerts;
44685b3e1433Swyllys 			}
44695b3e1433Swyllys 			/*
44705b3e1433Swyllys 			 * Convert keys to exportable format, the certs
44715b3e1433Swyllys 			 * are already OK.
44725b3e1433Swyllys 			 */
44735b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
447430a5e8faSwyllys 			    keylist, nkeys, NULL, NULL);
44755b3e1433Swyllys 		}
447671593db2Swyllys 	}
447730a5e8faSwyllys end:
447830a5e8faSwyllys 	if (bio != NULL)
447930a5e8faSwyllys 		(void) BIO_free(bio);
448071593db2Swyllys 
44815b3e1433Swyllys 	if (privkeys)
44825b3e1433Swyllys 		sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
44835b3e1433Swyllys 	if (certs)
44845b3e1433Swyllys 		sk_X509_pop_free(certs, X509_free);
448530a5e8faSwyllys 	if (cacerts)
44865b3e1433Swyllys 		sk_X509_pop_free(cacerts, X509_free);
448734acef67Swyllys 
448871593db2Swyllys 	return (rv);
448971593db2Swyllys }
449071593db2Swyllys 
449199ebb4caSwyllys static KMF_RETURN
create_deskey(DES_cblock ** deskey)449230a5e8faSwyllys create_deskey(DES_cblock **deskey)
449399ebb4caSwyllys {
449430a5e8faSwyllys 	DES_cblock *key;
449599ebb4caSwyllys 
449630a5e8faSwyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
449730a5e8faSwyllys 	if (key == NULL) {
449899ebb4caSwyllys 		return (KMF_ERR_MEMORY);
449999ebb4caSwyllys 	}
450099ebb4caSwyllys 
450130a5e8faSwyllys 	if (DES_random_key(key) == 0) {
450230a5e8faSwyllys 		free(key);
450330a5e8faSwyllys 		return (KMF_ERR_KEYGEN_FAILED);
450499ebb4caSwyllys 	}
450599ebb4caSwyllys 
450630a5e8faSwyllys 	*deskey = key;
450799ebb4caSwyllys 	return (KMF_OK);
450899ebb4caSwyllys }
450999ebb4caSwyllys 
451030a5e8faSwyllys #define	KEYGEN_RETRY 3
451130a5e8faSwyllys #define	DES3_KEY_SIZE 24
451230a5e8faSwyllys 
451399ebb4caSwyllys static KMF_RETURN
create_des3key(unsigned char ** des3key)451430a5e8faSwyllys create_des3key(unsigned char **des3key)
451599ebb4caSwyllys {
451630a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
451730a5e8faSwyllys 	DES_cblock *deskey1 = NULL;
451830a5e8faSwyllys 	DES_cblock *deskey2 = NULL;
451930a5e8faSwyllys 	DES_cblock *deskey3 = NULL;
452030a5e8faSwyllys 	unsigned char *newkey = NULL;
452130a5e8faSwyllys 	int retry;
452299ebb4caSwyllys 
452330a5e8faSwyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
452499ebb4caSwyllys 		return (KMF_ERR_MEMORY);
452530a5e8faSwyllys 	}
452699ebb4caSwyllys 
452730a5e8faSwyllys 	/* create the 1st DES key */
452830a5e8faSwyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
452930a5e8faSwyllys 		goto out;
453030a5e8faSwyllys 	}
453130a5e8faSwyllys 
453230a5e8faSwyllys 	/*
453330a5e8faSwyllys 	 * Create the 2nd DES key and make sure its value is different
453430a5e8faSwyllys 	 * from the 1st DES key.
453530a5e8faSwyllys 	 */
453630a5e8faSwyllys 	retry = 0;
453730a5e8faSwyllys 	do {
453830a5e8faSwyllys 		if (deskey2 != NULL) {
453930a5e8faSwyllys 			free(deskey2);
454030a5e8faSwyllys 			deskey2 = NULL;
454130a5e8faSwyllys 		}
454230a5e8faSwyllys 
454330a5e8faSwyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
454430a5e8faSwyllys 			goto out;
454530a5e8faSwyllys 		}
454630a5e8faSwyllys 
454730a5e8faSwyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
454830a5e8faSwyllys 		    == 0) {
454930a5e8faSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
455030a5e8faSwyllys 			retry++;
455130a5e8faSwyllys 		}
455230a5e8faSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
455330a5e8faSwyllys 
455430a5e8faSwyllys 	if (ret != KMF_OK) {
455530a5e8faSwyllys 		goto out;
455630a5e8faSwyllys 	}
455730a5e8faSwyllys 
455830a5e8faSwyllys 	/*
455930a5e8faSwyllys 	 * Create the 3rd DES key and make sure its value is different
456030a5e8faSwyllys 	 * from the 2nd DES key.
456130a5e8faSwyllys 	 */
456230a5e8faSwyllys 	retry = 0;
456330a5e8faSwyllys 	do {
456430a5e8faSwyllys 		if (deskey3 != NULL) {
456530a5e8faSwyllys 			free(deskey3);
456630a5e8faSwyllys 			deskey3 = NULL;
456730a5e8faSwyllys 		}
456830a5e8faSwyllys 
456930a5e8faSwyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
457030a5e8faSwyllys 			goto out;
457130a5e8faSwyllys 		}
457230a5e8faSwyllys 
457330a5e8faSwyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
457430a5e8faSwyllys 		    == 0) {
457530a5e8faSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
457630a5e8faSwyllys 			retry++;
457730a5e8faSwyllys 		}
457830a5e8faSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
457930a5e8faSwyllys 
458030a5e8faSwyllys 	if (ret != KMF_OK) {
458130a5e8faSwyllys 		goto out;
458299ebb4caSwyllys 	}
458399ebb4caSwyllys 
458430a5e8faSwyllys 	/* Concatenate 3 DES keys into a DES3 key */
458530a5e8faSwyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
458630a5e8faSwyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
458730a5e8faSwyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
458830a5e8faSwyllys 	*des3key = newkey;
458930a5e8faSwyllys 
459030a5e8faSwyllys out:
459130a5e8faSwyllys 	if (deskey1 != NULL)
459230a5e8faSwyllys 		free(deskey1);
459330a5e8faSwyllys 
459430a5e8faSwyllys 	if (deskey2 != NULL)
459530a5e8faSwyllys 		free(deskey2);
459630a5e8faSwyllys 
459730a5e8faSwyllys 	if (deskey3 != NULL)
459830a5e8faSwyllys 		free(deskey3);
459930a5e8faSwyllys 
460030a5e8faSwyllys 	if (ret != KMF_OK && newkey != NULL)
460130a5e8faSwyllys 		free(newkey);
460230a5e8faSwyllys 
460330a5e8faSwyllys 	return (ret);
460499ebb4caSwyllys }
460599ebb4caSwyllys 
460630a5e8faSwyllys KMF_RETURN
OpenSSL_CreateSymKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)46074942e222SAndy Fiddaman OpenSSL_CreateSymKey(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
460899ebb4caSwyllys {
460930a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
461030a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
461130a5e8faSwyllys 	char *fullpath = NULL;
461230a5e8faSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
461330a5e8faSwyllys 	DES_cblock *deskey = NULL;
461430a5e8faSwyllys 	unsigned char *des3key = NULL;
461530a5e8faSwyllys 	unsigned char *random = NULL;
461630a5e8faSwyllys 	int fd = -1;
461730a5e8faSwyllys 	KMF_KEY_HANDLE *symkey;
461830a5e8faSwyllys 	KMF_KEY_ALG keytype;
461930a5e8faSwyllys 	uint32_t keylen;
462030a5e8faSwyllys 	uint32_t keylen_size = sizeof (keylen);
462130a5e8faSwyllys 	char *dirpath;
462230a5e8faSwyllys 	char *keyfile;
462399ebb4caSwyllys 
462430a5e8faSwyllys 	if (kmfh == NULL)
462530a5e8faSwyllys 		return (KMF_ERR_UNINITIALIZED);
462699ebb4caSwyllys 
462730a5e8faSwyllys 	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
462830a5e8faSwyllys 	if (symkey == NULL)
462930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
463099ebb4caSwyllys 
463130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
463299ebb4caSwyllys 
463330a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
463430a5e8faSwyllys 	if (keyfile == NULL)
463530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
463699ebb4caSwyllys 
463730a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
463830a5e8faSwyllys 	    (void *)&keytype, NULL);
463930a5e8faSwyllys 	if (ret != KMF_OK)
464030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
464199ebb4caSwyllys 
464230a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
464330a5e8faSwyllys 	    &keylen, &keylen_size);
464430a5e8faSwyllys 	if (ret == KMF_ERR_ATTR_NOT_FOUND &&
464530a5e8faSwyllys 	    (keytype == KMF_DES || keytype == KMF_DES3))
464630a5e8faSwyllys 		/* keylength is not required for DES and 3DES */
464730a5e8faSwyllys 		ret = KMF_OK;
464830a5e8faSwyllys 	if (ret != KMF_OK)
464930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
465099ebb4caSwyllys 
465130a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
465230a5e8faSwyllys 	if (fullpath == NULL)
465330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
465499ebb4caSwyllys 
465530a5e8faSwyllys 	/* If the requested file exists, return an error */
465630a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
465730a5e8faSwyllys 		free(fullpath);
465830a5e8faSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
465930a5e8faSwyllys 	}
466099ebb4caSwyllys 
466130a5e8faSwyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
466230a5e8faSwyllys 	if (fd == -1) {
466330a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
466430a5e8faSwyllys 		goto out;
466530a5e8faSwyllys 	}
466699ebb4caSwyllys 
466730a5e8faSwyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
466830a5e8faSwyllys 	if (rkey == NULL) {
466930a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
467030a5e8faSwyllys 		goto out;
467130a5e8faSwyllys 	}
467230a5e8faSwyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
467399ebb4caSwyllys 
467430a5e8faSwyllys 	if (keytype == KMF_DES) {
467530a5e8faSwyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
467630a5e8faSwyllys 			goto out;
467730a5e8faSwyllys 		}
467830a5e8faSwyllys 		rkey->keydata.val = (uchar_t *)deskey;
467930a5e8faSwyllys 		rkey->keydata.len = 8;
468099ebb4caSwyllys 
468130a5e8faSwyllys 		symkey->keyalg = KMF_DES;
468299ebb4caSwyllys 
468330a5e8faSwyllys 	} else if (keytype == KMF_DES3) {
468430a5e8faSwyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
468530a5e8faSwyllys 			goto out;
468630a5e8faSwyllys 		}
468730a5e8faSwyllys 		rkey->keydata.val = (uchar_t *)des3key;
468830a5e8faSwyllys 		rkey->keydata.len = DES3_KEY_SIZE;
468930a5e8faSwyllys 		symkey->keyalg = KMF_DES3;
469099ebb4caSwyllys 
469130a5e8faSwyllys 	} else if (keytype == KMF_AES || keytype == KMF_RC4 ||
469230a5e8faSwyllys 	    keytype == KMF_GENERIC_SECRET) {
469330a5e8faSwyllys 		int bytes;
469499ebb4caSwyllys 
469530a5e8faSwyllys 		if (keylen % 8 != 0) {
469630a5e8faSwyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
469730a5e8faSwyllys 			goto out;
469830a5e8faSwyllys 		}
469999ebb4caSwyllys 
470030a5e8faSwyllys 		if (keytype == KMF_AES) {
470130a5e8faSwyllys 			if (keylen != 128 &&
470230a5e8faSwyllys 			    keylen != 192 &&
470330a5e8faSwyllys 			    keylen != 256) {
470430a5e8faSwyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
470530a5e8faSwyllys 				goto out;
470630a5e8faSwyllys 			}
470730a5e8faSwyllys 		}
470899ebb4caSwyllys 
470930a5e8faSwyllys 		bytes = keylen/8;
471030a5e8faSwyllys 		random = malloc(bytes);
471130a5e8faSwyllys 		if (random == NULL) {
471230a5e8faSwyllys 			ret = KMF_ERR_MEMORY;
471330a5e8faSwyllys 			goto out;
471430a5e8faSwyllys 		}
471530a5e8faSwyllys 		if (RAND_bytes(random, bytes) != 1) {
471630a5e8faSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
471730a5e8faSwyllys 			goto out;
471830a5e8faSwyllys 		}
471999ebb4caSwyllys 
472030a5e8faSwyllys 		rkey->keydata.val = (uchar_t *)random;
472130a5e8faSwyllys 		rkey->keydata.len = bytes;
472230a5e8faSwyllys 		symkey->keyalg = keytype;
472399ebb4caSwyllys 
472499ebb4caSwyllys 	} else {
472530a5e8faSwyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
472630a5e8faSwyllys 		goto out;
472799ebb4caSwyllys 	}
472899ebb4caSwyllys 
472930a5e8faSwyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
473099ebb4caSwyllys 
473130a5e8faSwyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
473230a5e8faSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
473330a5e8faSwyllys 	symkey->keylabel = (char *)fullpath;
473430a5e8faSwyllys 	symkey->israw = TRUE;
473530a5e8faSwyllys 	symkey->keyp = rkey;
473699ebb4caSwyllys 
473730a5e8faSwyllys out:
473830a5e8faSwyllys 	if (fd != -1)
473930a5e8faSwyllys 		(void) close(fd);
474030a5e8faSwyllys 
474130a5e8faSwyllys 	if (ret != KMF_OK && fullpath != NULL) {
474230a5e8faSwyllys 		free(fullpath);
474330a5e8faSwyllys 	}
474430a5e8faSwyllys 	if (ret != KMF_OK) {
474530a5e8faSwyllys 		kmf_free_raw_sym_key(rkey);
474630a5e8faSwyllys 		symkey->keyp = NULL;
474730a5e8faSwyllys 		symkey->keyalg = KMF_KEYALG_NONE;
474899ebb4caSwyllys 	}
474999ebb4caSwyllys 
475030a5e8faSwyllys 	return (ret);
475199ebb4caSwyllys }
475299ebb4caSwyllys 
475330a5e8faSwyllys /*
475430a5e8faSwyllys  * Check a file to see if it is a CRL file with PEM or DER format.
475530a5e8faSwyllys  * If success, return its format in the "pformat" argument.
475630a5e8faSwyllys  */
475730a5e8faSwyllys KMF_RETURN
OpenSSL_IsCRLFile(KMF_HANDLE_T handle,char * filename,int * pformat)475830a5e8faSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
475999ebb4caSwyllys {
476030a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
476130a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
476230a5e8faSwyllys 	BIO		*bio = NULL;
47634942e222SAndy Fiddaman 	X509_CRL	*xcrl = NULL;
476499ebb4caSwyllys 
476530a5e8faSwyllys 	if (filename == NULL) {
476630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
476799ebb4caSwyllys 	}
476899ebb4caSwyllys 
476930a5e8faSwyllys 	bio = BIO_new_file(filename, "rb");
477030a5e8faSwyllys 	if (bio == NULL)	{
477130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
477230a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
477330a5e8faSwyllys 		goto out;
477430a5e8faSwyllys 	}
477599ebb4caSwyllys 
477630a5e8faSwyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
477730a5e8faSwyllys 		*pformat = KMF_FORMAT_PEM;
477830a5e8faSwyllys 		goto out;
477930a5e8faSwyllys 	}
478030a5e8faSwyllys 	(void) BIO_free(bio);
478199ebb4caSwyllys 
478230a5e8faSwyllys 	/*
478330a5e8faSwyllys 	 * Now try to read it as raw DER data.
478430a5e8faSwyllys 	 */
478530a5e8faSwyllys 	bio = BIO_new_file(filename, "rb");
478630a5e8faSwyllys 	if (bio == NULL)	{
478730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
478830a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
478930a5e8faSwyllys 		goto out;
479030a5e8faSwyllys 	}
479199ebb4caSwyllys 
479230a5e8faSwyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
479330a5e8faSwyllys 		*pformat = KMF_FORMAT_ASN1;
479430a5e8faSwyllys 	} else {
479530a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
479630a5e8faSwyllys 	}
479799ebb4caSwyllys 
479830a5e8faSwyllys out:
479930a5e8faSwyllys 	if (bio != NULL)
480030a5e8faSwyllys 		(void) BIO_free(bio);
480199ebb4caSwyllys 
480230a5e8faSwyllys 	if (xcrl != NULL)
480330a5e8faSwyllys 		X509_CRL_free(xcrl);
480499ebb4caSwyllys 
480530a5e8faSwyllys 	return (ret);
480630a5e8faSwyllys }
480730a5e8faSwyllys 
480899ebb4caSwyllys KMF_RETURN
OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle,KMF_KEY_HANDLE * symkey,KMF_RAW_SYM_KEY * rkey)480930a5e8faSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
481030a5e8faSwyllys     KMF_RAW_SYM_KEY *rkey)
481199ebb4caSwyllys {
481299ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
481330a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
481430a5e8faSwyllys 	KMF_DATA	keyvalue;
481599ebb4caSwyllys 
481630a5e8faSwyllys 	if (kmfh == NULL)
481730a5e8faSwyllys 		return (KMF_ERR_UNINITIALIZED);
481899ebb4caSwyllys 
481930a5e8faSwyllys 	if (symkey == NULL || rkey == NULL)
482030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
482130a5e8faSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
482230a5e8faSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
482399ebb4caSwyllys 
482430a5e8faSwyllys 	if (symkey->israw) {
482530a5e8faSwyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
482699ebb4caSwyllys 
482730a5e8faSwyllys 		if (rawkey == NULL ||
482830a5e8faSwyllys 		    rawkey->keydata.val == NULL ||
482930a5e8faSwyllys 		    rawkey->keydata.len == 0)
483030a5e8faSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
483199ebb4caSwyllys 
483230a5e8faSwyllys 		rkey->keydata.len = rawkey->keydata.len;
483330a5e8faSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
483430a5e8faSwyllys 			return (KMF_ERR_MEMORY);
483530a5e8faSwyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
483630a5e8faSwyllys 		    rkey->keydata.len);
483730a5e8faSwyllys 	} else {
483830a5e8faSwyllys 		rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
483930a5e8faSwyllys 		if (rv != KMF_OK)
484030a5e8faSwyllys 			return (rv);
484130a5e8faSwyllys 		rkey->keydata.len = keyvalue.Length;
484230a5e8faSwyllys 		rkey->keydata.val = keyvalue.Data;
484330a5e8faSwyllys 	}
484499ebb4caSwyllys 
484530a5e8faSwyllys 	return (rv);
484630a5e8faSwyllys }
484799ebb4caSwyllys 
484830a5e8faSwyllys /*
484930a5e8faSwyllys  * substitute for the unsafe access(2) function.
485030a5e8faSwyllys  * If the file in question already exists, return 1.
485130a5e8faSwyllys  * else 0.  If an error occurs during testing (other
485230a5e8faSwyllys  * than EEXIST), return -1.
485330a5e8faSwyllys  */
485430a5e8faSwyllys static int
test_for_file(char * filename,mode_t mode)485530a5e8faSwyllys test_for_file(char *filename, mode_t mode)
485699ebb4caSwyllys {
485730a5e8faSwyllys 	int fd;
485899ebb4caSwyllys 
485930a5e8faSwyllys 	/*
486030a5e8faSwyllys 	 * Try to create the file with the EXCL flag.
486130a5e8faSwyllys 	 * The call should fail if the file exists.
486230a5e8faSwyllys 	 */
486330a5e8faSwyllys 	fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
486430a5e8faSwyllys 	if (fd == -1 && errno == EEXIST)
486530a5e8faSwyllys 		return (1);
486630a5e8faSwyllys 	else if (fd == -1) /* some other error */
486730a5e8faSwyllys 		return (-1);
486899ebb4caSwyllys 
486930a5e8faSwyllys 	/* The file did NOT exist.  Delete the testcase. */
487030a5e8faSwyllys 	(void) close(fd);
487130a5e8faSwyllys 	(void) unlink(filename);
487230a5e8faSwyllys 	return (0);
487399ebb4caSwyllys }
487499ebb4caSwyllys 
487530a5e8faSwyllys KMF_RETURN
OpenSSL_StoreKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)48764942e222SAndy Fiddaman OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
487799ebb4caSwyllys {
487830a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
487930a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
488030a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
488130a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey;
488230a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
488330a5e8faSwyllys 	KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
48846b35cb3cSRichard PALO 	KMF_CREDENTIAL cred = { NULL, 0 };
488530a5e8faSwyllys 	BIO *out = NULL;
488630a5e8faSwyllys 	int keys = 0;
488730a5e8faSwyllys 	char *fullpath = NULL;
488830a5e8faSwyllys 	char *keyfile = NULL;
488930a5e8faSwyllys 	char *dirpath = NULL;
489099ebb4caSwyllys 
489130a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
489230a5e8faSwyllys 	if (pubkey != NULL)
489330a5e8faSwyllys 		keys++;
489499ebb4caSwyllys 
489530a5e8faSwyllys 	prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
489630a5e8faSwyllys 	if (prikey != NULL)
489730a5e8faSwyllys 		keys++;
489899ebb4caSwyllys 
489930a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
490030a5e8faSwyllys 	if (rawkey != NULL)
490130a5e8faSwyllys 		keys++;
490299ebb4caSwyllys 
490399ebb4caSwyllys 	/*
490430a5e8faSwyllys 	 * Exactly 1 type of key must be passed to this function.
490599ebb4caSwyllys 	 */
490630a5e8faSwyllys 	if (keys != 1)
490730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
490899ebb4caSwyllys 
490930a5e8faSwyllys 	keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
491030a5e8faSwyllys 	    numattr);
491130a5e8faSwyllys 	if (keyfile == NULL)
491230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
491399ebb4caSwyllys 
491430a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
491599ebb4caSwyllys 
491630a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
491799ebb4caSwyllys 
491830a5e8faSwyllys 	/* Once we have the full path, we don't need the pieces */
491999ebb4caSwyllys 	if (fullpath == NULL)
492099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
492199ebb4caSwyllys 
492299ebb4caSwyllys 	/* If the requested file exists, return an error */
492330a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
492499ebb4caSwyllys 		free(fullpath);
492599ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
492699ebb4caSwyllys 	}
492799ebb4caSwyllys 
492830a5e8faSwyllys 	rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
492930a5e8faSwyllys 	    &format, NULL);
493030a5e8faSwyllys 	if (rv != KMF_OK)
493130a5e8faSwyllys 		/* format is optional. */
493230a5e8faSwyllys 		rv = KMF_OK;
493399ebb4caSwyllys 
493430a5e8faSwyllys 	/* CRED is not required for OpenSSL files */
493530a5e8faSwyllys 	(void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
493630a5e8faSwyllys 	    &cred, NULL);
493799ebb4caSwyllys 
493830a5e8faSwyllys 	/* Store the private key to the keyfile */
493930a5e8faSwyllys 	out = BIO_new_file(fullpath, "wb");
494030a5e8faSwyllys 	if (out == NULL) {
494130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
494230a5e8faSwyllys 		rv = KMF_ERR_OPEN_FILE;
494330a5e8faSwyllys 		goto end;
494430a5e8faSwyllys 	}
49459b37d296Swyllys 
494630a5e8faSwyllys 	if (prikey != NULL && prikey->keyp != NULL) {
494730a5e8faSwyllys 		if (prikey->keyalg == KMF_RSA ||
494830a5e8faSwyllys 		    prikey->keyalg == KMF_DSA) {
494930a5e8faSwyllys 			pkey = (EVP_PKEY *)prikey->keyp;
495099ebb4caSwyllys 
495130a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
495230a5e8faSwyllys 			    out, &cred, pkey, TRUE);
495399ebb4caSwyllys 
495430a5e8faSwyllys 			if (rv == KMF_OK && prikey->keylabel == NULL) {
495530a5e8faSwyllys 				prikey->keylabel = strdup(fullpath);
495630a5e8faSwyllys 				if (prikey->keylabel == NULL)
495730a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
495899ebb4caSwyllys 			}
495999ebb4caSwyllys 		}
496030a5e8faSwyllys 	} else if (pubkey != NULL && pubkey->keyp != NULL) {
496130a5e8faSwyllys 		if (pubkey->keyalg == KMF_RSA ||
496230a5e8faSwyllys 		    pubkey->keyalg == KMF_DSA) {
496330a5e8faSwyllys 			pkey = (EVP_PKEY *)pubkey->keyp;
496499ebb4caSwyllys 
496530a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
496630a5e8faSwyllys 			    out, &cred, pkey, FALSE);
496730a5e8faSwyllys 
496830a5e8faSwyllys 			if (rv == KMF_OK && pubkey->keylabel == NULL) {
496930a5e8faSwyllys 				pubkey->keylabel = strdup(fullpath);
497030a5e8faSwyllys 				if (pubkey->keylabel == NULL)
497130a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
497230a5e8faSwyllys 			}
497399ebb4caSwyllys 		}
497430a5e8faSwyllys 	} else if (rawkey != NULL) {
497530a5e8faSwyllys 		if (rawkey->keytype == KMF_RSA) {
497630a5e8faSwyllys 			pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
497730a5e8faSwyllys 		} else if (rawkey->keytype == KMF_DSA) {
497830a5e8faSwyllys 			pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
497930a5e8faSwyllys 		} else {
498030a5e8faSwyllys 			rv = KMF_ERR_BAD_PARAMETER;
498199ebb4caSwyllys 		}
49825b3e1433Swyllys 		if (pkey != NULL) {
498373cc0e02Swyllys 			KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
498473cc0e02Swyllys 
498573cc0e02Swyllys 			rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
498673cc0e02Swyllys 			    (void *)&kclass, NULL);
498773cc0e02Swyllys 			if (rv != KMF_OK)
498873cc0e02Swyllys 				rv = KMF_OK;
49895b3e1433Swyllys 			rv = ssl_write_key(kmfh, format, out,
499073cc0e02Swyllys 			    &cred, pkey, (kclass == KMF_ASYM_PRI));
49915b3e1433Swyllys 			EVP_PKEY_free(pkey);
49925b3e1433Swyllys 		}
499330a5e8faSwyllys 	}
499499ebb4caSwyllys 
499530a5e8faSwyllys end:
499699ebb4caSwyllys 
499730a5e8faSwyllys 	if (out)
499830a5e8faSwyllys 		(void) BIO_free(out);
499999ebb4caSwyllys 
50005b3e1433Swyllys 
500130a5e8faSwyllys 	if (rv == KMF_OK)
500230a5e8faSwyllys 		(void) chmod(fullpath, 0400);
500399ebb4caSwyllys 
500430a5e8faSwyllys 	free(fullpath);
500530a5e8faSwyllys 	return (rv);
500630a5e8faSwyllys }
500799ebb4caSwyllys 
500830a5e8faSwyllys KMF_RETURN
OpenSSL_ImportCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)500930a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
501030a5e8faSwyllys {
501130a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
501230a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
501330a5e8faSwyllys 	X509_CRL *xcrl = NULL;
501430a5e8faSwyllys 	X509 *xcert = NULL;
501530a5e8faSwyllys 	EVP_PKEY *pkey;
501630a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
501730a5e8faSwyllys 	BIO *in = NULL, *out = NULL;
501830a5e8faSwyllys 	int openssl_ret = 0;
501930a5e8faSwyllys 	KMF_ENCODE_FORMAT outformat;
502030a5e8faSwyllys 	boolean_t crlcheck = FALSE;
502130a5e8faSwyllys 	char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
502299ebb4caSwyllys 
502330a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
502430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
502599ebb4caSwyllys 	}
502630a5e8faSwyllys 
502730a5e8faSwyllys 	/* CRL check is optional */
502830a5e8faSwyllys 	(void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
502930a5e8faSwyllys 	    &crlcheck, NULL);
503030a5e8faSwyllys 
503130a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
503230a5e8faSwyllys 	if (crlcheck == B_TRUE && certfile == NULL) {
503330a5e8faSwyllys 		return (KMF_ERR_BAD_CERTFILE);
503499ebb4caSwyllys 	}
503599ebb4caSwyllys 
503630a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
503730a5e8faSwyllys 	incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
503830a5e8faSwyllys 	outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
503999ebb4caSwyllys 
504030a5e8faSwyllys 	crlfile = get_fullpath(dirpath, incrl);
504199ebb4caSwyllys 
504230a5e8faSwyllys 	if (crlfile == NULL)
504330a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
504499ebb4caSwyllys 
504530a5e8faSwyllys 	outcrlfile = get_fullpath(dirpath, outcrl);
504630a5e8faSwyllys 	if (outcrlfile == NULL)
504730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
504830a5e8faSwyllys 
504930a5e8faSwyllys 	if (isdir(outcrlfile)) {
505030a5e8faSwyllys 		free(outcrlfile);
505130a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
505299ebb4caSwyllys 	}
505399ebb4caSwyllys 
505430a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
505530a5e8faSwyllys 	if (ret != KMF_OK) {
505630a5e8faSwyllys 		free(outcrlfile);
505799ebb4caSwyllys 		return (ret);
505830a5e8faSwyllys 	}
505999ebb4caSwyllys 
506030a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
506130a5e8faSwyllys 	if (in == NULL)	{
506299ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
506399ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
506430a5e8faSwyllys 		goto end;
506599ebb4caSwyllys 	}
506699ebb4caSwyllys 
506730a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
506830a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
506930a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
507030a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
507199ebb4caSwyllys 	}
507299ebb4caSwyllys 
507399ebb4caSwyllys 	if (xcrl == NULL) {
507499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
507599ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
507630a5e8faSwyllys 		goto end;
507799ebb4caSwyllys 	}
507899ebb4caSwyllys 
507930a5e8faSwyllys 	/* If bypasscheck is specified, no need to verify. */
508030a5e8faSwyllys 	if (crlcheck == B_FALSE)
508130a5e8faSwyllys 		goto output;
508299ebb4caSwyllys 
508330a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
508430a5e8faSwyllys 	if (ret != KMF_OK)
508530a5e8faSwyllys 		goto end;
508630a5e8faSwyllys 
508730a5e8faSwyllys 	/* Read in the CA cert file and convert to X509 */
508830a5e8faSwyllys 	if (BIO_read_filename(in, certfile) <= 0) {
508999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
509030a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
509130a5e8faSwyllys 		goto end;
509299ebb4caSwyllys 	}
509399ebb4caSwyllys 
509430a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
509530a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
509630a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
509730a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
509830a5e8faSwyllys 	} else {
509930a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
510030a5e8faSwyllys 		goto end;
510130a5e8faSwyllys 	}
510230a5e8faSwyllys 
510330a5e8faSwyllys 	if (xcert == NULL) {
510499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
510599ebb4caSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
510630a5e8faSwyllys 		goto end;
510730a5e8faSwyllys 	}
510830a5e8faSwyllys 	/* Now get the public key from the CA cert */
510930a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
511030a5e8faSwyllys 	if (pkey == NULL) {
511130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
511230a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
511330a5e8faSwyllys 		goto end;
511499ebb4caSwyllys 	}
511599ebb4caSwyllys 
511630a5e8faSwyllys 	/* Verify the CRL with the CA's public key */
511730a5e8faSwyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
511899ebb4caSwyllys 	EVP_PKEY_free(pkey);
511930a5e8faSwyllys 	if (openssl_ret > 0) {
512030a5e8faSwyllys 		ret = KMF_OK;  /* verify succeed */
512199ebb4caSwyllys 	} else {
512230a5e8faSwyllys 		SET_ERROR(kmfh, openssl_ret);
512399ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
512499ebb4caSwyllys 	}
512599ebb4caSwyllys 
512630a5e8faSwyllys output:
512730a5e8faSwyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
512830a5e8faSwyllys 	    &outformat, NULL);
512930a5e8faSwyllys 	if (ret != KMF_OK) {
513030a5e8faSwyllys 		ret = KMF_OK;
513130a5e8faSwyllys 		outformat = KMF_FORMAT_PEM;
513230a5e8faSwyllys 	}
513330a5e8faSwyllys 
513430a5e8faSwyllys 	out = BIO_new_file(outcrlfile, "wb");
513530a5e8faSwyllys 	if (out == NULL) {
513630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
513730a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
513830a5e8faSwyllys 		goto end;
513930a5e8faSwyllys 	}
514099ebb4caSwyllys 
514130a5e8faSwyllys 	if (outformat == KMF_FORMAT_ASN1) {
514230a5e8faSwyllys 		openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
514330a5e8faSwyllys 	} else if (outformat == KMF_FORMAT_PEM) {
514430a5e8faSwyllys 		openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
514530a5e8faSwyllys 	} else {
514630a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
514730a5e8faSwyllys 		goto end;
514830a5e8faSwyllys 	}
514930a5e8faSwyllys 
515030a5e8faSwyllys 	if (openssl_ret <= 0) {
515130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
515230a5e8faSwyllys 		ret = KMF_ERR_WRITE_FILE;
515330a5e8faSwyllys 	} else {
515430a5e8faSwyllys 		ret = KMF_OK;
515530a5e8faSwyllys 	}
515630a5e8faSwyllys 
515730a5e8faSwyllys end:
515899ebb4caSwyllys 	if (xcrl != NULL)
515999ebb4caSwyllys 		X509_CRL_free(xcrl);
516099ebb4caSwyllys 
516199ebb4caSwyllys 	if (xcert != NULL)
516299ebb4caSwyllys 		X509_free(xcert);
516399ebb4caSwyllys 
516430a5e8faSwyllys 	if (in != NULL)
516530a5e8faSwyllys 		(void) BIO_free(in);
516630a5e8faSwyllys 
516730a5e8faSwyllys 	if (out != NULL)
516830a5e8faSwyllys 		(void) BIO_free(out);
516930a5e8faSwyllys 
517030a5e8faSwyllys 	if (outcrlfile != NULL)
517130a5e8faSwyllys 		free(outcrlfile);
517299ebb4caSwyllys 
517330a5e8faSwyllys 	return (ret);
517499ebb4caSwyllys }
517599ebb4caSwyllys 
517699ebb4caSwyllys KMF_RETURN
OpenSSL_ListCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)517730a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
517899ebb4caSwyllys {
517930a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
518030a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
518130a5e8faSwyllys 	X509_CRL   *x = NULL;
518230a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
518330a5e8faSwyllys 	char *crlfile = NULL;
518430a5e8faSwyllys 	BIO *in = NULL;
518530a5e8faSwyllys 	BIO *mem = NULL;
518630a5e8faSwyllys 	long len;
518730a5e8faSwyllys 	char *memptr;
518830a5e8faSwyllys 	char *data = NULL;
518930a5e8faSwyllys 	char **crldata;
519030a5e8faSwyllys 	char *crlfilename, *dirpath;
519199ebb4caSwyllys 
519230a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
519330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
519430a5e8faSwyllys 	}
519530a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
519630a5e8faSwyllys 	    attrlist, numattr);
519730a5e8faSwyllys 	if (crlfilename == NULL)
519830a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
519930a5e8faSwyllys 
520030a5e8faSwyllys 	crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
520130a5e8faSwyllys 	    attrlist, numattr);
520299ebb4caSwyllys 
520330a5e8faSwyllys 	if (crldata == NULL)
520499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
520530a5e8faSwyllys 
520630a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
520730a5e8faSwyllys 
520830a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
520930a5e8faSwyllys 
521030a5e8faSwyllys 	if (crlfile == NULL)
521130a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
521230a5e8faSwyllys 
521330a5e8faSwyllys 	if (isdir(crlfile)) {
521430a5e8faSwyllys 		free(crlfile);
521530a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
521699ebb4caSwyllys 	}
521799ebb4caSwyllys 
521830a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
521930a5e8faSwyllys 	if (ret != KMF_OK) {
522030a5e8faSwyllys 		free(crlfile);
522199ebb4caSwyllys 		return (ret);
522230a5e8faSwyllys 	}
522399ebb4caSwyllys 
522430a5e8faSwyllys 	if (bio_err == NULL)
522530a5e8faSwyllys 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
522630a5e8faSwyllys 
522730a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
522830a5e8faSwyllys 	if (in == NULL)	{
522999ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
523099ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
523130a5e8faSwyllys 		goto end;
523299ebb4caSwyllys 	}
523399ebb4caSwyllys 
523430a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
523530a5e8faSwyllys 		x = d2i_X509_CRL_bio(in, NULL);
523630a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
523730a5e8faSwyllys 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
523899ebb4caSwyllys 	}
523999ebb4caSwyllys 
524030a5e8faSwyllys 	if (x == NULL) { /* should not happen */
524199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
524230a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
524330a5e8faSwyllys 		goto end;
524499ebb4caSwyllys 	}
524599ebb4caSwyllys 
524630a5e8faSwyllys 	mem = BIO_new(BIO_s_mem());
524730a5e8faSwyllys 	if (mem == NULL) {
524830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
524930a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
525030a5e8faSwyllys 		goto end;
525130a5e8faSwyllys 	}
525230a5e8faSwyllys 
525330a5e8faSwyllys 	(void) X509_CRL_print(mem, x);
525430a5e8faSwyllys 	len = BIO_get_mem_data(mem, &memptr);
525530a5e8faSwyllys 	if (len <= 0) {
525630a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
525730a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
525830a5e8faSwyllys 		goto end;
525999ebb4caSwyllys 	}
526099ebb4caSwyllys 
526130a5e8faSwyllys 	data = malloc(len + 1);
526230a5e8faSwyllys 	if (data == NULL) {
526330a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
526430a5e8faSwyllys 		goto end;
526599ebb4caSwyllys 	}
526699ebb4caSwyllys 
526730a5e8faSwyllys 	(void) memcpy(data, memptr, len);
526830a5e8faSwyllys 	data[len] = '\0';
526930a5e8faSwyllys 	*crldata = data;
527099ebb4caSwyllys 
527130a5e8faSwyllys end:
527230a5e8faSwyllys 	if (x != NULL)
527330a5e8faSwyllys 		X509_CRL_free(x);
527499ebb4caSwyllys 
527530a5e8faSwyllys 	if (crlfile != NULL)
527630a5e8faSwyllys 		free(crlfile);
527730a5e8faSwyllys 
527830a5e8faSwyllys 	if (in != NULL)
527930a5e8faSwyllys 		(void) BIO_free(in);
528030a5e8faSwyllys 
528130a5e8faSwyllys 	if (mem != NULL)
528230a5e8faSwyllys 		(void) BIO_free(mem);
528399ebb4caSwyllys 
528499ebb4caSwyllys 	return (ret);
528599ebb4caSwyllys }
528699ebb4caSwyllys 
528799ebb4caSwyllys KMF_RETURN
OpenSSL_DeleteCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)528830a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
528999ebb4caSwyllys {
529030a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
529130a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
529230a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
529330a5e8faSwyllys 	char *crlfile = NULL;
529430a5e8faSwyllys 	BIO *in = NULL;
529530a5e8faSwyllys 	char *crlfilename, *dirpath;
529699ebb4caSwyllys 
529730a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
529899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
529999ebb4caSwyllys 	}
530099ebb4caSwyllys 
530130a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
530230a5e8faSwyllys 	    attrlist, numattr);
530399ebb4caSwyllys 
530430a5e8faSwyllys 	if (crlfilename == NULL)
530530a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
530699ebb4caSwyllys 
530730a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
530899ebb4caSwyllys 
530930a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
531030a5e8faSwyllys 
531130a5e8faSwyllys 	if (crlfile == NULL)
531230a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
531330a5e8faSwyllys 
531430a5e8faSwyllys 	if (isdir(crlfile)) {
531599ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
531630a5e8faSwyllys 		goto end;
531799ebb4caSwyllys 	}
531899ebb4caSwyllys 
531930a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
532030a5e8faSwyllys 	if (ret != KMF_OK)
532130a5e8faSwyllys 		goto end;
532299ebb4caSwyllys 
532330a5e8faSwyllys 	if (unlink(crlfile) != 0) {
532430a5e8faSwyllys 		SET_SYS_ERROR(kmfh, errno);
532530a5e8faSwyllys 		ret = KMF_ERR_INTERNAL;
532630a5e8faSwyllys 		goto end;
532730a5e8faSwyllys 	}
532830a5e8faSwyllys 
532930a5e8faSwyllys end:
533030a5e8faSwyllys 	if (in != NULL)
533130a5e8faSwyllys 		(void) BIO_free(in);
533230a5e8faSwyllys 	if (crlfile != NULL)
533330a5e8faSwyllys 		free(crlfile);
533499ebb4caSwyllys 
533599ebb4caSwyllys 	return (ret);
533699ebb4caSwyllys }
533799ebb4caSwyllys 
533899ebb4caSwyllys KMF_RETURN
OpenSSL_FindCertInCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)533930a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
534099ebb4caSwyllys {
534130a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
534230a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
534330a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
534430a5e8faSwyllys 	BIO *in = NULL;
534530a5e8faSwyllys 	X509   *xcert = NULL;
534630a5e8faSwyllys 	X509_CRL   *xcrl = NULL;
534730a5e8faSwyllys 	STACK_OF(X509_REVOKED) *revoke_stack = NULL;
534830a5e8faSwyllys 	X509_REVOKED *revoke;
534930a5e8faSwyllys 	int i;
535030a5e8faSwyllys 	char *crlfilename, *crlfile, *dirpath, *certfile;
535199ebb4caSwyllys 
535230a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
535399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
535499ebb4caSwyllys 	}
535599ebb4caSwyllys 
535630a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
535730a5e8faSwyllys 	    attrlist, numattr);
535830a5e8faSwyllys 
535930a5e8faSwyllys 	if (crlfilename == NULL)
536030a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
536130a5e8faSwyllys 
536230a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
536330a5e8faSwyllys 	if (certfile == NULL)
536430a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
536530a5e8faSwyllys 
536630a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
536730a5e8faSwyllys 
536830a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
536930a5e8faSwyllys 
537030a5e8faSwyllys 	if (crlfile == NULL)
537130a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
537230a5e8faSwyllys 
537330a5e8faSwyllys 	if (isdir(crlfile)) {
537430a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
537530a5e8faSwyllys 		goto end;
537630a5e8faSwyllys 	}
537730a5e8faSwyllys 
537830a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
537999ebb4caSwyllys 	if (ret != KMF_OK)
538030a5e8faSwyllys 		goto end;
538199ebb4caSwyllys 
538230a5e8faSwyllys 	/* Read the CRL file and load it into a X509_CRL structure */
538330a5e8faSwyllys 	in = BIO_new_file(crlfilename, "rb");
538430a5e8faSwyllys 	if (in == NULL)	{
538599ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
538699ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
538730a5e8faSwyllys 		goto end;
538899ebb4caSwyllys 	}
538999ebb4caSwyllys 
539030a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
539130a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
539230a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
539330a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
539499ebb4caSwyllys 	}
539599ebb4caSwyllys 
539630a5e8faSwyllys 	if (xcrl == NULL) {
539730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
539830a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
539930a5e8faSwyllys 		goto end;
540030a5e8faSwyllys 	}
540130a5e8faSwyllys 	(void) BIO_free(in);
540299ebb4caSwyllys 
540330a5e8faSwyllys 	/* Read the Certificate file and load it into a X509 structure */
540430a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
540530a5e8faSwyllys 	if (ret != KMF_OK)
540630a5e8faSwyllys 		goto end;
540799ebb4caSwyllys 
540830a5e8faSwyllys 	in = BIO_new_file(certfile, "rb");
540930a5e8faSwyllys 	if (in == NULL)	{
541030a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
541130a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
541230a5e8faSwyllys 		goto end;
541330a5e8faSwyllys 	}
541499ebb4caSwyllys 
541530a5e8faSwyllys 	if (format == KMF_FORMAT_ASN1) {
541630a5e8faSwyllys 		xcert = d2i_X509_bio(in, NULL);
541730a5e8faSwyllys 	} else if (format == KMF_FORMAT_PEM) {
541830a5e8faSwyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
541930a5e8faSwyllys 	}
542099ebb4caSwyllys 
542130a5e8faSwyllys 	if (xcert == NULL) {
542230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
542330a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
542430a5e8faSwyllys 		goto end;
542599ebb4caSwyllys 	}
542699ebb4caSwyllys 
542730a5e8faSwyllys 	/* Check if the certificate and the CRL have same issuer */
5428300fdee2SAndy Fiddaman 	if (X509_NAME_cmp(X509_get_issuer_name(xcert),
5429300fdee2SAndy Fiddaman 	    X509_CRL_get_issuer(xcrl)) != 0) {
543030a5e8faSwyllys 		ret = KMF_ERR_ISSUER;
543130a5e8faSwyllys 		goto end;
543230a5e8faSwyllys 	}
543302744e81Swyllys 
543430a5e8faSwyllys 	/* Check to see if the certificate serial number is revoked */
543530a5e8faSwyllys 	revoke_stack = X509_CRL_get_REVOKED(xcrl);
543630a5e8faSwyllys 	if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
543730a5e8faSwyllys 		/* No revoked certificates in the CRL file */
543830a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
543930a5e8faSwyllys 		ret = KMF_ERR_EMPTY_CRL;
544030a5e8faSwyllys 		goto end;
544130a5e8faSwyllys 	}
544202744e81Swyllys 
544330a5e8faSwyllys 	for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
544430a5e8faSwyllys 		revoke = sk_X509_REVOKED_value(revoke_stack, i);
5445300fdee2SAndy Fiddaman 		if (ASN1_INTEGER_cmp(X509_get_serialNumber(xcert),
5446300fdee2SAndy Fiddaman 		    X509_REVOKED_get0_serialNumber(revoke)) == 0) {
544730a5e8faSwyllys 			break;
544830a5e8faSwyllys 		}
544930a5e8faSwyllys 	}
545002744e81Swyllys 
545130a5e8faSwyllys 	if (i < sk_X509_REVOKED_num(revoke_stack)) {
545230a5e8faSwyllys 		ret = KMF_OK;
545330a5e8faSwyllys 	} else {
545430a5e8faSwyllys 		ret = KMF_ERR_NOT_REVOKED;
545530a5e8faSwyllys 	}
545630a5e8faSwyllys 
545730a5e8faSwyllys end:
545830a5e8faSwyllys 	if (in != NULL)
545930a5e8faSwyllys 		(void) BIO_free(in);
546030a5e8faSwyllys 	if (xcrl != NULL)
546130a5e8faSwyllys 		X509_CRL_free(xcrl);
546230a5e8faSwyllys 	if (xcert != NULL)
546330a5e8faSwyllys 		X509_free(xcert);
546430a5e8faSwyllys 
546530a5e8faSwyllys 	return (ret);
546630a5e8faSwyllys }
546702744e81Swyllys 
546802744e81Swyllys KMF_RETURN
OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle,char * crlname,KMF_DATA * tacert)546930a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
547002744e81Swyllys {
547130a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
547202744e81Swyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
547330a5e8faSwyllys 	BIO		*bcrl = NULL;
54744942e222SAndy Fiddaman 	X509_CRL	*xcrl = NULL;
547530a5e8faSwyllys 	X509		*xcert = NULL;
547630a5e8faSwyllys 	EVP_PKEY	*pkey;
547730a5e8faSwyllys 	int		sslret;
547830a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
547930a5e8faSwyllys 	unsigned char	*p;
548030a5e8faSwyllys 	long		len;
548102744e81Swyllys 
548230a5e8faSwyllys 	if (handle == NULL || crlname == NULL || tacert == NULL) {
548302744e81Swyllys 		return (KMF_ERR_BAD_PARAMETER);
548430a5e8faSwyllys 	}
548530a5e8faSwyllys 
548630a5e8faSwyllys 	ret = kmf_get_file_format(crlname, &crl_format);
548730a5e8faSwyllys 	if (ret != KMF_OK)
548830a5e8faSwyllys 		return (ret);
548930a5e8faSwyllys 
549030a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
549130a5e8faSwyllys 	if (bcrl == NULL)	{
549230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
549330a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
549430a5e8faSwyllys 		goto cleanup;
549530a5e8faSwyllys 	}
549630a5e8faSwyllys 
549730a5e8faSwyllys 	if (crl_format == KMF_FORMAT_ASN1) {
549830a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
549930a5e8faSwyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
550030a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
550130a5e8faSwyllys 	} else {
550230a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
550330a5e8faSwyllys 		goto cleanup;
550430a5e8faSwyllys 	}
550530a5e8faSwyllys 
550630a5e8faSwyllys 	if (xcrl == NULL) {
550730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
550830a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
550930a5e8faSwyllys 		goto cleanup;
551030a5e8faSwyllys 	}
551130a5e8faSwyllys 
551230a5e8faSwyllys 	p = tacert->Data;
551330a5e8faSwyllys 	len = tacert->Length;
551430a5e8faSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
551502744e81Swyllys 
551602744e81Swyllys 	if (xcert == NULL) {
551702744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
551830a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
551902744e81Swyllys 		goto cleanup;
552002744e81Swyllys 	}
552102744e81Swyllys 
552230a5e8faSwyllys 	/* Get issuer certificate public key */
552302744e81Swyllys 	pkey = X509_get_pubkey(xcert);
552430a5e8faSwyllys 	if (pkey == NULL) {
552502744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
552602744e81Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
552702744e81Swyllys 		goto cleanup;
552802744e81Swyllys 	}
552902744e81Swyllys 
553030a5e8faSwyllys 	/* Verify CRL signature */
553130a5e8faSwyllys 	sslret = X509_CRL_verify(xcrl, pkey);
553230a5e8faSwyllys 	EVP_PKEY_free(pkey);
553330a5e8faSwyllys 	if (sslret > 0) {
553430a5e8faSwyllys 		ret = KMF_OK;
553502744e81Swyllys 	} else {
553630a5e8faSwyllys 		SET_ERROR(kmfh, sslret);
553730a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
553802744e81Swyllys 	}
553930a5e8faSwyllys 
554030a5e8faSwyllys cleanup:
554130a5e8faSwyllys 	if (bcrl != NULL)
554230a5e8faSwyllys 		(void) BIO_free(bcrl);
554330a5e8faSwyllys 
554430a5e8faSwyllys 	if (xcrl != NULL)
554530a5e8faSwyllys 		X509_CRL_free(xcrl);
554630a5e8faSwyllys 
554730a5e8faSwyllys 	if (xcert != NULL)
554830a5e8faSwyllys 		X509_free(xcert);
554930a5e8faSwyllys 
555030a5e8faSwyllys 	return (ret);
555130a5e8faSwyllys 
555230a5e8faSwyllys }
555330a5e8faSwyllys 
555430a5e8faSwyllys KMF_RETURN
OpenSSL_CheckCRLDate(KMF_HANDLE_T handle,char * crlname)555530a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
555630a5e8faSwyllys {
555730a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
555830a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
555930a5e8faSwyllys 	KMF_ENCODE_FORMAT crl_format;
556030a5e8faSwyllys 	BIO		*bcrl = NULL;
55614942e222SAndy Fiddaman 	X509_CRL	*xcrl = NULL;
556230a5e8faSwyllys 	int		i;
556330a5e8faSwyllys 
556430a5e8faSwyllys 	if (handle == NULL || crlname == NULL) {
556530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
556602744e81Swyllys 	}
556702744e81Swyllys 
556830a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlname, &crl_format);
556930a5e8faSwyllys 	if (ret != KMF_OK)
557030a5e8faSwyllys 		return (ret);
557102744e81Swyllys 
557230a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
55735b3e1433Swyllys 	if (bcrl == NULL) {
557402744e81Swyllys 		SET_ERROR(kmfh, ERR_get_error());
557530a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
557630a5e8faSwyllys 		goto cleanup;
557730a5e8faSwyllys 	}
557802744e81Swyllys 
55795b3e1433Swyllys 	if (crl_format == KMF_FORMAT_ASN1)
558030a5e8faSwyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
55815b3e1433Swyllys 	else if (crl_format == KMF_FORMAT_PEM)
558230a5e8faSwyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
558302744e81Swyllys 
558430a5e8faSwyllys 	if (xcrl == NULL) {
558530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
558630a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
558730a5e8faSwyllys 		goto cleanup;
558830a5e8faSwyllys 	}
5589300fdee2SAndy Fiddaman 	i = X509_cmp_time(X509_CRL_get0_lastUpdate(xcrl), NULL);
559030a5e8faSwyllys 	if (i >= 0) {
559130a5e8faSwyllys 		ret = KMF_ERR_VALIDITY_PERIOD;
559230a5e8faSwyllys 		goto cleanup;
559330a5e8faSwyllys 	}
5594300fdee2SAndy Fiddaman 	if (X509_CRL_get0_nextUpdate(xcrl)) {
5595300fdee2SAndy Fiddaman 		i = X509_cmp_time(X509_CRL_get0_nextUpdate(xcrl), NULL);
559602744e81Swyllys 
559730a5e8faSwyllys 		if (i <= 0) {
559830a5e8faSwyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
559930a5e8faSwyllys 			goto cleanup;
560002744e81Swyllys 		}
560130a5e8faSwyllys 	}
560202744e81Swyllys 
560330a5e8faSwyllys 	ret = KMF_OK;
560402744e81Swyllys 
560502744e81Swyllys cleanup:
560630a5e8faSwyllys 	if (bcrl != NULL)
560730a5e8faSwyllys 		(void) BIO_free(bcrl);
560802744e81Swyllys 
560930a5e8faSwyllys 	if (xcrl != NULL)
561030a5e8faSwyllys 		X509_CRL_free(xcrl);
561102744e81Swyllys 
561202744e81Swyllys 	return (ret);
561302744e81Swyllys }
5614