199ebb4caSwyllys /*
22c9a247fSWyllys Ingersoll  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
32c9a247fSWyllys Ingersoll  *
499ebb4caSwyllys  * Use is subject to license terms.
599ebb4caSwyllys  */
69a767088Shaimay /*
770f9559bSTheo Schlossnagle  * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
8553e44ceSAndrew Stormont  * Copyright 2018 RackTop Systems.
94942e222SAndy Fiddaman  * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
1070f9559bSTheo Schlossnagle  */
1170f9559bSTheo Schlossnagle /*
129a767088Shaimay  * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
139a767088Shaimay  * project 2000.
149a767088Shaimay  */
159a767088Shaimay /*
169a767088Shaimay  * ====================================================================
179a767088Shaimay  * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
189a767088Shaimay  *
199a767088Shaimay  * Redistribution and use in source and binary forms, with or without
209a767088Shaimay  * modification, are permitted provided that the following conditions
219a767088Shaimay  * are met:
229a767088Shaimay  *
239a767088Shaimay  * 1. Redistributions of source code must retain the above copyright
249a767088Shaimay  *    notice, this list of conditions and the following disclaimer.
259a767088Shaimay  *
269a767088Shaimay  * 2. Redistributions in binary form must reproduce the above copyright
279a767088Shaimay  *    notice, this list of conditions and the following disclaimer in
289a767088Shaimay  *    the documentation and/or other materials provided with the
299a767088Shaimay  *    distribution.
309a767088Shaimay  *
319a767088Shaimay  * 3. All advertising materials mentioning features or use of this
329a767088Shaimay  *    software must display the following acknowledgment:
339a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
349a767088Shaimay  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
359a767088Shaimay  *
369a767088Shaimay  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
379a767088Shaimay  *    endorse or promote products derived from this software without
389a767088Shaimay  *    prior written permission. For written permission, please contact
399a767088Shaimay  *    licensing@OpenSSL.org.
409a767088Shaimay  *
419a767088Shaimay  * 5. Products derived from this software may not be called "OpenSSL"
429a767088Shaimay  *    nor may "OpenSSL" appear in their names without prior written
439a767088Shaimay  *    permission of the OpenSSL Project.
449a767088Shaimay  *
459a767088Shaimay  * 6. Redistributions of any form whatsoever must retain the following
469a767088Shaimay  *    acknowledgment:
479a767088Shaimay  *    "This product includes software developed by the OpenSSL Project
489a767088Shaimay  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
499a767088Shaimay  *
509a767088Shaimay  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
519a767088Shaimay  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
529a767088Shaimay  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
539a767088Shaimay  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
549a767088Shaimay  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
559a767088Shaimay  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
569a767088Shaimay  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
579a767088Shaimay  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
589a767088Shaimay  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
599a767088Shaimay  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
609a767088Shaimay  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
619a767088Shaimay  * OF THE POSSIBILITY OF SUCH DAMAGE.
629a767088Shaimay  * ====================================================================
639a767088Shaimay  *
649a767088Shaimay  * This product includes cryptographic software written by Eric Young
659a767088Shaimay  * (eay@cryptsoft.com).  This product includes software written by Tim
669a767088Shaimay  * Hudson (tjh@cryptsoft.com).
679a767088Shaimay  *
689a767088Shaimay  */
6999ebb4caSwyllys 
7071593db2Swyllys #include <stdlib.h>
7199ebb4caSwyllys #include <kmfapiP.h>
7299ebb4caSwyllys #include <ber_der.h>
7399ebb4caSwyllys #include <fcntl.h>
7499ebb4caSwyllys #include <sys/stat.h>
7599ebb4caSwyllys #include <dirent.h>
7699ebb4caSwyllys #include <cryptoutil.h>
7799ebb4caSwyllys #include <synch.h>
7899ebb4caSwyllys #include <thread.h>
7999ebb4caSwyllys 
8099ebb4caSwyllys /* OPENSSL related headers */
8199ebb4caSwyllys #include <openssl/bio.h>
8299ebb4caSwyllys #include <openssl/bn.h>
8399ebb4caSwyllys #include <openssl/asn1.h>
8499ebb4caSwyllys #include <openssl/err.h>
8599ebb4caSwyllys #include <openssl/x509.h>
8699ebb4caSwyllys #include <openssl/rsa.h>
8799ebb4caSwyllys #include <openssl/dsa.h>
8899ebb4caSwyllys #include <openssl/x509v3.h>
8999ebb4caSwyllys #include <openssl/objects.h>
9099ebb4caSwyllys #include <openssl/pem.h>
9199ebb4caSwyllys #include <openssl/pkcs12.h>
9299ebb4caSwyllys #include <openssl/ocsp.h>
9399ebb4caSwyllys #include <openssl/des.h>
9499ebb4caSwyllys #include <openssl/rand.h>
95300fdee2SAndy Fiddaman #include "compat.h"
9699ebb4caSwyllys 
9799ebb4caSwyllys #define	PRINT_ANY_EXTENSION (\
9899ebb4caSwyllys 	KMF_X509_EXT_KEY_USAGE |\
9999ebb4caSwyllys 	KMF_X509_EXT_CERT_POLICIES |\
10099ebb4caSwyllys 	KMF_X509_EXT_SUBJALTNAME |\
10199ebb4caSwyllys 	KMF_X509_EXT_BASIC_CONSTRAINTS |\
10299ebb4caSwyllys 	KMF_X509_EXT_NAME_CONSTRAINTS |\
10399ebb4caSwyllys 	KMF_X509_EXT_POLICY_CONSTRAINTS |\
10499ebb4caSwyllys 	KMF_X509_EXT_EXT_KEY_USAGE |\
10599ebb4caSwyllys 	KMF_X509_EXT_INHIBIT_ANY_POLICY |\
10699ebb4caSwyllys 	KMF_X509_EXT_AUTH_KEY_ID |\
10799ebb4caSwyllys 	KMF_X509_EXT_SUBJ_KEY_ID |\
10899ebb4caSwyllys 	KMF_X509_EXT_POLICY_MAPPING)
10999ebb4caSwyllys 
11099ebb4caSwyllys static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
11199ebb4caSwyllys 	0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
11299ebb4caSwyllys 	0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
11399ebb4caSwyllys 	0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
11499ebb4caSwyllys 	0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
11599ebb4caSwyllys 	0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
11699ebb4caSwyllys 	0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
11799ebb4caSwyllys 	0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
11899ebb4caSwyllys 	0x91 };
11999ebb4caSwyllys 
12099ebb4caSwyllys static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
12199ebb4caSwyllys 	0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
12299ebb4caSwyllys 	0x8e, 0xda, 0xce, 0x91, 0x5f };
12399ebb4caSwyllys 
12499ebb4caSwyllys static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
12599ebb4caSwyllys 	0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
12699ebb4caSwyllys 	0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
12799ebb4caSwyllys 	0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
12899ebb4caSwyllys 	0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
12999ebb4caSwyllys 	0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
13099ebb4caSwyllys 	0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
13199ebb4caSwyllys 	0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
13299ebb4caSwyllys 	0x02 };
13399ebb4caSwyllys 
13499ebb4caSwyllys #define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
13599ebb4caSwyllys 	h->lasterr.errcode = c;
13699ebb4caSwyllys 
13799ebb4caSwyllys #define	SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
13899ebb4caSwyllys 
1395b3e1433Swyllys /*
140bf5d9f18SAndy Fiddaman  * Declare some new macros for managing stacks of EVP_PKEYS.
1415b3e1433Swyllys  */
142553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
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 *,
20699ebb4caSwyllys     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 *,
21999ebb4caSwyllys     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 *,
22699ebb4caSwyllys     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",
31299ebb4caSwyllys 		    "X509v3 Name Constraints");
31399ebb4caSwyllys 		(void) OBJ_create("2.5.29.33", "policyMappings",
31499ebb4caSwyllys 		    "X509v3 Policy Mappings");
31599ebb4caSwyllys 		(void) OBJ_create("2.5.29.36", "policyConstraints",
31699ebb4caSwyllys 		    "X509v3 Policy Constraints");
31799ebb4caSwyllys 		(void) OBJ_create("2.5.29.46", "freshestCRL",
31899ebb4caSwyllys 		    "X509v3 Freshest CRL");
31999ebb4caSwyllys 		(void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
32099ebb4caSwyllys 		    "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)
34799ebb4caSwyllys 			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))
37599ebb4caSwyllys 	    == 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,
65371593db2Swyllys     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 ||
69071593db2Swyllys 	    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 		}
737a2d4930dSDan OpenSolaris Anderson 	}
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}}}",
80902744e81Swyllys 	    &OID, &Mod, &PubExp, &PriExp, &Prime1,
81002744e81Swyllys 	    &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,
96702744e81Swyllys 			    &filedata);
96802744e81Swyllys 			if (rv == KMF_OK) {
96902744e81Swyllys 				(void) readAltFormatPrivateKey(&filedata,
97002744e81Swyllys 				    &pkey);
97130a5e8faSwyllys 				kmf_free_data(&filedata);
97202744e81Swyllys 			}
97302744e81Swyllys 		}
97402744e81Swyllys 	} else if (format == KMF_FORMAT_PEM ||
97502744e81Swyllys 	    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,
98402744e81Swyllys 			    &filedata);
98502744e81Swyllys 			if (rv == KMF_OK) {
98602744e81Swyllys 				uchar_t *d = NULL;
98702744e81Swyllys 				int len;
98830a5e8faSwyllys 				rv = kmf_pem_to_der(filedata.Data,
98902744e81Swyllys 				    filedata.Length, &d, &len);
99002744e81Swyllys 				if (rv == KMF_OK && d != NULL) {
99102744e81Swyllys 					derdata.Data = d;
99202744e81Swyllys 					derdata.Length = (size_t)len;
99302744e81Swyllys 					(void) readAltFormatPrivateKey(
99402744e81Swyllys 					    &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);
104399ebb4caSwyllys 
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);
105130a5e8faSwyllys 
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 =
110571593db2Swyllys 					    certlist[i].Data;
110699ebb4caSwyllys 					kmf_cert[n].certificate.Length =
110771593db2Swyllys 					    certlist[i].Length;
110899ebb4caSwyllys 
110999ebb4caSwyllys 					kmf_cert[n].kmf_private.keystore_type =
111099ebb4caSwyllys 					    KMF_KEYSTORE_OPENSSL;
111199ebb4caSwyllys 					kmf_cert[n].kmf_private.flags =
111299ebb4caSwyllys 					    KMF_FLAG_CERT_VALID;
111371593db2Swyllys 					kmf_cert[n].kmf_private.label =
111471593db2Swyllys 					    strdup(fname);
111599ebb4caSwyllys 					n++;
111699ebb4caSwyllys 				}
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]);
1123f482c776Swyllys 			} else {
1124f482c776Swyllys 				for (i = 0; i < loaded_certs; i++)
112530a5e8faSwyllys 					kmf_free_data(&certlist[i]);
1126f482c776Swyllys 				n += loaded_certs;
112771593db2Swyllys 			}
1128f482c776Swyllys 			free(certlist);
112971593db2Swyllys 			free(fname);
113071593db2Swyllys 		}
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 =
115371593db2Swyllys 				    certlist[i].Data;
1154f482c776Swyllys 				kmf_cert[n].certificate.Length =
115571593db2Swyllys 				    certlist[i].Length;
1156f482c776Swyllys 				kmf_cert[n].kmf_private.keystore_type =
115799ebb4caSwyllys 				    KMF_KEYSTORE_OPENSSL;
1158f482c776Swyllys 				kmf_cert[n].kmf_private.flags =
115971593db2Swyllys 				    KMF_FLAG_CERT_VALID;
1160f482c776Swyllys 				kmf_cert[n].kmf_private.label =
116171593db2Swyllys 				    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 
117799ebb4caSwyllys 	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)
121330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
121499ebb4caSwyllys 
121530a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
121630a5e8faSwyllys 	fullpath = get_fullpath(dirpath, outfilename);
121799ebb4caSwyllys 	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;
122699ebb4caSwyllys 		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,
129499ebb4caSwyllys 				    (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,
134899ebb4caSwyllys     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 {
137599ebb4caSwyllys 		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,
139230a5e8faSwyllys     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)
141299ebb4caSwyllys 					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)
142799ebb4caSwyllys 					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;
147099ebb4caSwyllys 
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;
149199ebb4caSwyllys 
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 	}
150330a5e8faSwyllys 
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;
152199ebb4caSwyllys 
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 		}
155030a5e8faSwyllys 
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);
155999ebb4caSwyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
156099ebb4caSwyllys 			privkey->keyalg = KMF_RSA;
156199ebb4caSwyllys 			privkey->keyclass = KMF_ASYM_PRI;
156299ebb4caSwyllys 			privkey->israw = FALSE;
156399ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
156430a5e8faSwyllys 
156599ebb4caSwyllys 			/* OpenSSL derives the public key from the private */
156630a5e8faSwyllys 			(void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
156799ebb4caSwyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
156899ebb4caSwyllys 			pubkey->keyalg = KMF_RSA;
156999ebb4caSwyllys 			pubkey->israw = FALSE;
157099ebb4caSwyllys 			pubkey->keyclass = KMF_ASYM_PUB;
157199ebb4caSwyllys 			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 
160699ebb4caSwyllys 		privkey->kstype = KMF_KEYSTORE_OPENSSL;
160799ebb4caSwyllys 		privkey->keyalg = KMF_DSA;
160899ebb4caSwyllys 		privkey->keyclass = KMF_ASYM_PRI;
160999ebb4caSwyllys 		privkey->israw = FALSE;
161099ebb4caSwyllys 		if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
161199ebb4caSwyllys 			privkey->keyp = (void *)eprikey;
161299ebb4caSwyllys 		} else {
161399ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
161499ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
161599ebb4caSwyllys 			goto cleanup;
161699ebb4caSwyllys 		}
161799ebb4caSwyllys 
161899ebb4caSwyllys 		pubkey->kstype = KMF_KEYSTORE_OPENSSL;
161999ebb4caSwyllys 		pubkey->keyalg = KMF_DSA;
162099ebb4caSwyllys 		pubkey->keyclass = KMF_ASYM_PUB;
162199ebb4caSwyllys 		pubkey->israw = FALSE;
162299ebb4caSwyllys 
162399ebb4caSwyllys 		if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
162499ebb4caSwyllys 			pubkey->keyp = (void *)epubkey;
162599ebb4caSwyllys 		} else {
162699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
162799ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
162899ebb4caSwyllys 			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 */
165699ebb4caSwyllys 		}
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);
167730a5e8faSwyllys 	}
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,
174199ebb4caSwyllys     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 ||
175099ebb4caSwyllys 	    tobesigned == NULL || output == NULL ||
175199ebb4caSwyllys 	    tobesigned->Data == NULL ||
175299ebb4caSwyllys 	    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,
180002744e81Swyllys 			    tobesigned->Data, p, rsa,
180102744e81Swyllys 			    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,
181199ebb4caSwyllys 			    (uint32_t)tobesigned->Length);
181299ebb4caSwyllys 			len = (uint32_t)output->Length;
181399ebb4caSwyllys 			p = output->Data;
1814300fdee2SAndy Fiddaman 			if (!EVP_SignFinal(ctx, p, (uint32_t *)&len, pkey)) {
181599ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
181602744e81Swyllys 				len = 0;
181702744e81Swyllys 				ret = KMF_ERR_INTERNAL;
181899ebb4caSwyllys 			}
181999ebb4caSwyllys 			output->Length = len;
1820300fdee2SAndy Fiddaman 			EVP_MD_CTX_free(ctx);
182102744e81Swyllys 		}
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,
184999ebb4caSwyllys 		    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 &&
189899ebb4caSwyllys 	    key->keyclass != KMF_ASYM_PRI &&
189999ebb4caSwyllys 	    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) {
191899ebb4caSwyllys 				free(key->keylabel);
191999ebb4caSwyllys 				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)194199ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
194299ebb4caSwyllys {
194399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
194499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
194599ebb4caSwyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
194699ebb4caSwyllys 
194799ebb4caSwyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
194899ebb4caSwyllys 	if (strlen(str)) {
194999ebb4caSwyllys 		*msgstr = (char *)strdup(str);
195099ebb4caSwyllys 		if ((*msgstr) == NULL)
195199ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
195299ebb4caSwyllys 	} else {
195399ebb4caSwyllys 		*msgstr = NULL;
195499ebb4caSwyllys 	}
195599ebb4caSwyllys 
195699ebb4caSwyllys 	return (ret);
195799ebb4caSwyllys }
195899ebb4caSwyllys 
195999ebb4caSwyllys static int
ext2NID(int kmfext)196099ebb4caSwyllys ext2NID(int kmfext)
196199ebb4caSwyllys {
196299ebb4caSwyllys 	switch (kmfext) {
196399ebb4caSwyllys 		case KMF_X509_EXT_KEY_USAGE:
196499ebb4caSwyllys 			return (NID_key_usage);
196599ebb4caSwyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
196699ebb4caSwyllys 			return (NID_private_key_usage_period);
196799ebb4caSwyllys 		case KMF_X509_EXT_CERT_POLICIES:
196899ebb4caSwyllys 			return (NID_certificate_policies);
196999ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
197099ebb4caSwyllys 			return (NID_subject_alt_name);
197199ebb4caSwyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
197299ebb4caSwyllys 			return (NID_issuer_alt_name);
197399ebb4caSwyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
197499ebb4caSwyllys 			return (NID_basic_constraints);
197599ebb4caSwyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
197699ebb4caSwyllys 			return (NID_ext_key_usage);
197799ebb4caSwyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
197899ebb4caSwyllys 			return (NID_authority_key_identifier);
197999ebb4caSwyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
198099ebb4caSwyllys 			return (NID_crl_distribution_points);
198199ebb4caSwyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
198299ebb4caSwyllys 			return (NID_subject_key_identifier);
198399ebb4caSwyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
198499ebb4caSwyllys 			return (OBJ_sn2nid("policyMappings"));
198599ebb4caSwyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
198699ebb4caSwyllys 			return (OBJ_sn2nid("nameConstraints"));
198799ebb4caSwyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
198899ebb4caSwyllys 			return (OBJ_sn2nid("policyConstraints"));
198999ebb4caSwyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
199099ebb4caSwyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
199199ebb4caSwyllys 		case KMF_X509_EXT_FRESHEST_CRL:
199299ebb4caSwyllys 			return (OBJ_sn2nid("freshestCRL"));
199399ebb4caSwyllys 		default:
199499ebb4caSwyllys 			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)199999ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
200099ebb4caSwyllys     KMF_PRINTABLE_ITEM flag, char *resultStr)
200199ebb4caSwyllys {
200299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
200399ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
200499ebb4caSwyllys 	X509 *xcert = NULL;
200599ebb4caSwyllys 	unsigned char *outbuf = NULL;
200699ebb4caSwyllys 	unsigned char *outbuf_p;
200799ebb4caSwyllys 	int j;
200899ebb4caSwyllys 	int ext_index, nid, len;
200999ebb4caSwyllys 	BIO *mem = NULL;
201070f9559bSTheo Schlossnagle 	STACK_OF(OPENSSL_STRING) *emlst = NULL;
201199ebb4caSwyllys 	X509_EXTENSION *ex;
201299ebb4caSwyllys 
201399ebb4caSwyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
201499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
201599ebb4caSwyllys 	}
201699ebb4caSwyllys 
201799ebb4caSwyllys 	/* copy cert data to outbuf */
201899ebb4caSwyllys 	outbuf = malloc(pcert->Length);
201999ebb4caSwyllys 	if (outbuf == NULL) {
202099ebb4caSwyllys 		return (KMF_ERR_MEMORY);
202199ebb4caSwyllys 	}
202299ebb4caSwyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
202399ebb4caSwyllys 
202499ebb4caSwyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
202599ebb4caSwyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
202699ebb4caSwyllys 	if (xcert == NULL) {
202799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
202899ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
202999ebb4caSwyllys 		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;
203699ebb4caSwyllys 		goto out;
203799ebb4caSwyllys 	}
203899ebb4caSwyllys 
203999ebb4caSwyllys 	switch (flag) {
204099ebb4caSwyllys 	case KMF_CERT_ISSUER:
204199ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
204299ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
204399ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
204499ebb4caSwyllys 		break;
204599ebb4caSwyllys 
204699ebb4caSwyllys 	case KMF_CERT_SUBJECT:
204799ebb4caSwyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
204899ebb4caSwyllys 		    XN_FLAG_SEP_CPLUS_SPC);
204999ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
205099ebb4caSwyllys 		break;
205199ebb4caSwyllys 
205299ebb4caSwyllys 	case KMF_CERT_VERSION:
2053300fdee2SAndy Fiddaman 		(void) snprintf(resultStr, KMF_CERT_PRINTABLE_LEN,
2054300fdee2SAndy Fiddaman 		    "%ld", X509_get_version(xcert));
205599ebb4caSwyllys 		len = strlen(resultStr);
205699ebb4caSwyllys 		break;
205799ebb4caSwyllys 
205899ebb4caSwyllys 	case KMF_CERT_SERIALNUM:
205999ebb4caSwyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
206099ebb4caSwyllys 			(void) strcpy(resultStr, "0x");
206199ebb4caSwyllys 			len = BIO_gets(mem, &resultStr[2],
206299ebb4caSwyllys 			    KMF_CERT_PRINTABLE_LEN - 2);
206399ebb4caSwyllys 		}
206499ebb4caSwyllys 		break;
206599ebb4caSwyllys 
206699ebb4caSwyllys 	case KMF_CERT_NOTBEFORE:
2067300fdee2SAndy Fiddaman 		(void) ASN1_TIME_print(mem, X509_getm_notBefore(xcert));
206899ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
206999ebb4caSwyllys 		break;
207099ebb4caSwyllys 
207199ebb4caSwyllys 	case KMF_CERT_NOTAFTER:
2072300fdee2SAndy Fiddaman 		(void) ASN1_TIME_print(mem, X509_getm_notAfter(xcert));
207399ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
207499ebb4caSwyllys 		break;
207599ebb4caSwyllys 
207699ebb4caSwyllys 	case KMF_CERT_PUBKEY_DATA:
207799ebb4caSwyllys 		{
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 
208699ebb4caSwyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
208799ebb4caSwyllys 			if (pkey == NULL) {
208899ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
208999ebb4caSwyllys 				ret = KMF_ERR_ENCODING;
209099ebb4caSwyllys 				goto out;
209199ebb4caSwyllys 			}
209299ebb4caSwyllys 
2093300fdee2SAndy Fiddaman 			if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
209499ebb4caSwyllys 				(void) BIO_printf(mem,
209599ebb4caSwyllys 				    "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) {
210099ebb4caSwyllys 				(void) BIO_printf(mem,
210199ebb4caSwyllys 				    "%12sDSA Public Key:\n", "");
2102300fdee2SAndy Fiddaman 				(void) DSA_print(mem, dsa, 0);
210399ebb4caSwyllys 			} else {
210499ebb4caSwyllys 				(void) BIO_printf(mem,
210599ebb4caSwyllys 				    "%12sUnknown Public Key:\n", "");
210699ebb4caSwyllys 			}
210799ebb4caSwyllys 			(void) BIO_printf(mem, "\n");
210899ebb4caSwyllys 			EVP_PKEY_free(pkey);
210999ebb4caSwyllys 		}
211099ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
211199ebb4caSwyllys 		break;
211299ebb4caSwyllys 	case KMF_CERT_SIGNATURE_ALG:
211399ebb4caSwyllys 	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 
212199ebb4caSwyllys 			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
213299ebb4caSwyllys 			} 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
214399ebb4caSwyllys 			}
214499ebb4caSwyllys 
2145300fdee2SAndy Fiddaman 			if (alg == NULL)
2146300fdee2SAndy Fiddaman 				len = -1;
2147300fdee2SAndy Fiddaman 			else if ((len = i2a_ASN1_OBJECT(mem, alg)) > 0)
214899ebb4caSwyllys 				len = BIO_read(mem, resultStr,
214999ebb4caSwyllys 				    KMF_CERT_PRINTABLE_LEN);
215099ebb4caSwyllys 		}
215199ebb4caSwyllys 		break;
215299ebb4caSwyllys 
215399ebb4caSwyllys 	case KMF_CERT_EMAIL:
215499ebb4caSwyllys 		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",
215770f9559bSTheo Schlossnagle 			    sk_OPENSSL_STRING_value(emlst, j));
215899ebb4caSwyllys 
215999ebb4caSwyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
216099ebb4caSwyllys 		X509_email_free(emlst);
216199ebb4caSwyllys 		break;
216299ebb4caSwyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
216399ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
216499ebb4caSwyllys 	case KMF_X509_EXT_KEY_USAGE:
216599ebb4caSwyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
216699ebb4caSwyllys 	case KMF_X509_EXT_CERT_POLICIES:
216799ebb4caSwyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
216899ebb4caSwyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
216999ebb4caSwyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
217099ebb4caSwyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
217199ebb4caSwyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
217299ebb4caSwyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
217399ebb4caSwyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
217499ebb4caSwyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
217599ebb4caSwyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
217699ebb4caSwyllys 	case KMF_X509_EXT_FRESHEST_CRL:
217799ebb4caSwyllys 		nid = ext2NID(flag);
217899ebb4caSwyllys 		if (nid == NID_undef) {
217999ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
218099ebb4caSwyllys 			goto out;
218199ebb4caSwyllys 		}
218299ebb4caSwyllys 
2183300fdee2SAndy Fiddaman 		ext_index = X509_get_ext_by_NID(xcert, nid, -1);
218499ebb4caSwyllys 		if (ext_index == -1) {
218599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
218699ebb4caSwyllys 
218799ebb4caSwyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
218899ebb4caSwyllys 			goto out;
218999ebb4caSwyllys 		}
2190300fdee2SAndy Fiddaman 		ex = X509_get_ext(xcert, ext_index);
219199ebb4caSwyllys 
219299ebb4caSwyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
219399ebb4caSwyllys 
219499ebb4caSwyllys 		if (BIO_printf(mem, ": %s\n",
219530a5e8faSwyllys 		    X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
219699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
219799ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
219899ebb4caSwyllys 			goto out;
219999ebb4caSwyllys 		}
220099ebb4caSwyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
220199ebb4caSwyllys 			(void) BIO_printf(mem, "%*s", 4, "");
2202300fdee2SAndy Fiddaman 			(void) ASN1_STRING_print(mem,
2203300fdee2SAndy Fiddaman 			    X509_EXTENSION_get_data(ex));
220499ebb4caSwyllys 		}
220599ebb4caSwyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
220699ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
220799ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
220899ebb4caSwyllys 			goto out;
220999ebb4caSwyllys 		}
221099ebb4caSwyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
221199ebb4caSwyllys 	}
221299ebb4caSwyllys 	if (len <= 0) {
221399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
221499ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
221599ebb4caSwyllys 	}
221699ebb4caSwyllys 
221799ebb4caSwyllys out:
221899ebb4caSwyllys 	if (outbuf != NULL) {
221999ebb4caSwyllys 		free(outbuf);
222099ebb4caSwyllys 	}
222199ebb4caSwyllys 
222299ebb4caSwyllys 	if (xcert != NULL) {
222399ebb4caSwyllys 		X509_free(xcert);
222499ebb4caSwyllys 	}
222599ebb4caSwyllys 
222699ebb4caSwyllys 	if (mem != NULL) {
222799ebb4caSwyllys 		(void) BIO_free(mem);
222899ebb4caSwyllys 	}
222999ebb4caSwyllys 
223099ebb4caSwyllys 	return (ret);
223199ebb4caSwyllys }
223230a5e8faSwyllys 
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 {
223799ebb4caSwyllys 	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;
224699ebb4caSwyllys 
224799ebb4caSwyllys 	/*
224899ebb4caSwyllys 	 * This is really just a FindKey operation, reuse the
224999ebb4caSwyllys 	 * FindKey function.
225099ebb4caSwyllys 	 */
225130a5e8faSwyllys 	kmf_set_attr_at_index(new_attrlist, i,
225230a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
225330a5e8faSwyllys 	i++;
225499ebb4caSwyllys 
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) {
226530a5e8faSwyllys 		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++;
227030a5e8faSwyllys 	}
227130a5e8faSwyllys 
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 	}
227830a5e8faSwyllys 
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);
228999ebb4caSwyllys 	return (rv);
229099ebb4caSwyllys }
229199ebb4caSwyllys 
229299ebb4caSwyllys KMF_RETURN
OpenSSL_DecryptData(KMF_HANDLE_T handle,KMF_KEY_HANDLE * key,KMF_OID * AlgOID,KMF_DATA * ciphertext,KMF_DATA * output)229399ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
22944942e222SAndy Fiddaman     KMF_OID *AlgOID, KMF_DATA *ciphertext, KMF_DATA *output)
229599ebb4caSwyllys {
229699ebb4caSwyllys 	KMF_RETURN		ret = KMF_OK;
229799ebb4caSwyllys 	RSA *rsa = NULL;
229899ebb4caSwyllys 	unsigned int in_len = 0, out_len = 0;
229999ebb4caSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
230099ebb4caSwyllys 	uint8_t *in_data, *out_data;
230199ebb4caSwyllys 	int i, blocks;
230299ebb4caSwyllys 
230399ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
230499ebb4caSwyllys 	    ciphertext == NULL || output == NULL ||
230599ebb4caSwyllys 	    ciphertext->Data == NULL ||
230699ebb4caSwyllys 	    output->Data == NULL)
230799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
230899ebb4caSwyllys 
230999ebb4caSwyllys 	if (key->keyalg == KMF_RSA) {
231099ebb4caSwyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
231199ebb4caSwyllys 		modulus_len = RSA_size(rsa);
231299ebb4caSwyllys 	} else {
231399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
231499ebb4caSwyllys 	}
231599ebb4caSwyllys 
231699ebb4caSwyllys 	blocks = ciphertext->Length/modulus_len;
231799ebb4caSwyllys 	out_data = output->Data;
231899ebb4caSwyllys 	in_data = ciphertext->Data;
231999ebb4caSwyllys 	out_len = modulus_len - 11;
232099ebb4caSwyllys 	in_len = modulus_len;
232199ebb4caSwyllys 
232299ebb4caSwyllys 	for (i = 0; i < blocks; i++) {
232399ebb4caSwyllys 		out_len  = RSA_private_decrypt(in_len,
232499ebb4caSwyllys 		    in_data, out_data, rsa, RSA_PKCS1_PADDING);
232599ebb4caSwyllys 
232699ebb4caSwyllys 		if (out_len == 0) {
232799ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
232899ebb4caSwyllys 			goto cleanup;
232999ebb4caSwyllys 		}
233099ebb4caSwyllys 
233199ebb4caSwyllys 		out_data += out_len;
233299ebb4caSwyllys 		total_decrypted += out_len;
233399ebb4caSwyllys 		in_data += in_len;
233499ebb4caSwyllys 	}
233599ebb4caSwyllys 
233699ebb4caSwyllys 	output->Length = total_decrypted;
233799ebb4caSwyllys 
233899ebb4caSwyllys cleanup:
233999ebb4caSwyllys 	RSA_free(rsa);
234099ebb4caSwyllys 	if (ret != KMF_OK)
234199ebb4caSwyllys 		output->Length = 0;
234299ebb4caSwyllys 
234399ebb4caSwyllys 	return (ret);
234499ebb4caSwyllys 
234599ebb4caSwyllys }
234699ebb4caSwyllys 
234799ebb4caSwyllys /*
234899ebb4caSwyllys  *  This function will create a certid from issuer_cert and user_cert.
234999ebb4caSwyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
235099ebb4caSwyllys  *  certid memory after use.
235199ebb4caSwyllys  */
235299ebb4caSwyllys static KMF_RETURN
create_certid(KMF_HANDLE_T handle,const KMF_DATA * issuer_cert,const KMF_DATA * user_cert,OCSP_CERTID ** certid)235399ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
235499ebb4caSwyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
235599ebb4caSwyllys {
235699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
235799ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
235899ebb4caSwyllys 	X509   *issuer = NULL;
235999ebb4caSwyllys 	X509   *cert = NULL;
236099ebb4caSwyllys 	unsigned char *ptmp;
236199ebb4caSwyllys 
236299ebb4caSwyllys 	if (issuer_cert == NULL || user_cert == NULL) {
236399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
236499ebb4caSwyllys 	}
236599ebb4caSwyllys 
236699ebb4caSwyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
236799ebb4caSwyllys 	ptmp = issuer_cert->Data;
236899ebb4caSwyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
236999ebb4caSwyllys 	    issuer_cert->Length);
237099ebb4caSwyllys 	if (issuer == NULL) {
237199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
237299ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
237399ebb4caSwyllys 		goto end;
237499ebb4caSwyllys 	}
237599ebb4caSwyllys 
237699ebb4caSwyllys 	/* convert the DER-encoded user cert to an internal X509 */
237799ebb4caSwyllys 	ptmp = user_cert->Data;
237899ebb4caSwyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
237999ebb4caSwyllys 	    user_cert->Length);
238099ebb4caSwyllys 	if (cert == NULL) {
238199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
238299ebb4caSwyllys 
238399ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
238499ebb4caSwyllys 		goto end;
238599ebb4caSwyllys 	}
238699ebb4caSwyllys 
238799ebb4caSwyllys 	/* create a CERTID */
238899ebb4caSwyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
238999ebb4caSwyllys 	if (*certid == NULL) {
239099ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
239199ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
239299ebb4caSwyllys 		goto end;
239399ebb4caSwyllys 	}
239499ebb4caSwyllys 
239599ebb4caSwyllys end:
239699ebb4caSwyllys 	if (issuer != NULL) {
239799ebb4caSwyllys 		X509_free(issuer);
239899ebb4caSwyllys 	}
239999ebb4caSwyllys 
240099ebb4caSwyllys 	if (cert != NULL) {
240199ebb4caSwyllys 		X509_free(cert);
240299ebb4caSwyllys 	}
240399ebb4caSwyllys 
240499ebb4caSwyllys 	return (ret);
240599ebb4caSwyllys }
240699ebb4caSwyllys 
240799ebb4caSwyllys KMF_RETURN
OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)240830a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
240930a5e8faSwyllys     int numattr, KMF_ATTRIBUTE *attrlist)
241099ebb4caSwyllys {
241199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
241299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
241399ebb4caSwyllys 	OCSP_CERTID *id = NULL;
241499ebb4caSwyllys 	OCSP_REQUEST *req = NULL;
241599ebb4caSwyllys 	BIO *derbio = NULL;
241630a5e8faSwyllys 	char *reqfile;
241730a5e8faSwyllys 	KMF_DATA *issuer_cert;
241830a5e8faSwyllys 	KMF_DATA *user_cert;
241999ebb4caSwyllys 
242030a5e8faSwyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
242130a5e8faSwyllys 	    attrlist, numattr);
242230a5e8faSwyllys 	if (user_cert == NULL)
242399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
242499ebb4caSwyllys 
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);
243699ebb4caSwyllys 	if (ret != KMF_OK) {
243799ebb4caSwyllys 		return (ret);
243899ebb4caSwyllys 	}
243999ebb4caSwyllys 
244099ebb4caSwyllys 	/* Create an OCSP request */
244199ebb4caSwyllys 	req = OCSP_REQUEST_new();
244299ebb4caSwyllys 	if (req == NULL) {
244399ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
244499ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
244599ebb4caSwyllys 		goto end;
244699ebb4caSwyllys 	}
244799ebb4caSwyllys 
244899ebb4caSwyllys 	if (!OCSP_request_add0_id(req, id)) {
244999ebb4caSwyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
245099ebb4caSwyllys 		goto end;
245199ebb4caSwyllys 	}
245299ebb4caSwyllys 
245399ebb4caSwyllys 	/* Write the request to the output file with DER encoding */
245499ebb4caSwyllys 	derbio = BIO_new_file(reqfile, "wb");
245599ebb4caSwyllys 	if (!derbio) {
245699ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
245799ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
245899ebb4caSwyllys 		goto end;
245999ebb4caSwyllys 	}
246099ebb4caSwyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
246199ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
246299ebb4caSwyllys 	}
246399ebb4caSwyllys 
246499ebb4caSwyllys end:
246599ebb4caSwyllys 	/*
2466e65e5c2dSWyllys Ingersoll 	 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2467a2d4930dSDan OpenSolaris Anderson 	 * will also deallocate certid's space.
246899ebb4caSwyllys 	 */
246999ebb4caSwyllys 	if (req != NULL) {
247099ebb4caSwyllys 		OCSP_REQUEST_free(req);
247199ebb4caSwyllys 	}
247299ebb4caSwyllys 
247399ebb4caSwyllys 	if (derbio != NULL) {
247499ebb4caSwyllys 		(void) BIO_free(derbio);
247599ebb4caSwyllys 	}
247699ebb4caSwyllys 
247799ebb4caSwyllys 	return (ret);
247899ebb4caSwyllys }
247999ebb4caSwyllys 
248099ebb4caSwyllys /* 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 {
248399ebb4caSwyllys 	int i;
248499ebb4caSwyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
2485300fdee2SAndy Fiddaman 	const ASN1_OCTET_STRING *pid;
248699ebb4caSwyllys 
2487553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2488300fdee2SAndy Fiddaman 	OCSP_RESPID *id = bs->tbsResponseData->responderId;
2489300fdee2SAndy Fiddaman 
249099ebb4caSwyllys 	if (id->type == V_OCSP_RESPID_NAME)
249199ebb4caSwyllys 		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 
250499ebb4caSwyllys 	/* Lookup by key hash */
250599ebb4caSwyllys 
250699ebb4caSwyllys 	/* If key hash isn't SHA1 length then forget it */
2507300fdee2SAndy Fiddaman 	if (pid->length != SHA_DIGEST_LENGTH)
250899ebb4caSwyllys 		return (NULL);
250999ebb4caSwyllys 
2510300fdee2SAndy Fiddaman 	keyhash = pid->data;
251199ebb4caSwyllys 	/* Calculate hash of each key and compare */
251299ebb4caSwyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
251399ebb4caSwyllys 		X509 *x = sk_X509_value(certs, i);
25145b3e1433Swyllys 		/* Use pubkey_digest to get the key ID value */
251599ebb4caSwyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
251699ebb4caSwyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
251799ebb4caSwyllys 			return (x);
251899ebb4caSwyllys 	}
251999ebb4caSwyllys 	return (NULL);
252099ebb4caSwyllys }
252199ebb4caSwyllys 
252299ebb4caSwyllys /* 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)252499ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
252599ebb4caSwyllys     X509_STORE *st, unsigned long flags)
252699ebb4caSwyllys {
252799ebb4caSwyllys 	X509 *signer;
2528300fdee2SAndy Fiddaman 	if ((signer = ocsp_find_signer_sk(certs, bs)))	{
252999ebb4caSwyllys 		*psigner = signer;
253099ebb4caSwyllys 		return (2);
253199ebb4caSwyllys 	}
2532300fdee2SAndy Fiddaman 
253399ebb4caSwyllys 	if (!(flags & OCSP_NOINTERN) &&
2534300fdee2SAndy Fiddaman 	    (signer = ocsp_find_signer_sk(
2535300fdee2SAndy Fiddaman 	    (STACK_OF(X509) *)OCSP_resp_get0_certs(bs), bs))) {
253699ebb4caSwyllys 		*psigner = signer;
253799ebb4caSwyllys 		return (1);
253899ebb4caSwyllys 	}
253999ebb4caSwyllys 	/* Maybe lookup from store if by subject name */
254099ebb4caSwyllys 
254199ebb4caSwyllys 	*psigner = NULL;
254299ebb4caSwyllys 	return (0);
254399ebb4caSwyllys }
254499ebb4caSwyllys 
254599ebb4caSwyllys /*
254699ebb4caSwyllys  * This function will verify the signature of a basic response, using
254799ebb4caSwyllys  * the public key from the OCSP responder certificate.
254899ebb4caSwyllys  */
254999ebb4caSwyllys static KMF_RETURN
check_response_signature(KMF_HANDLE_T handle,OCSP_BASICRESP * bs,KMF_DATA * signer_cert,KMF_DATA * issuer_cert)255099ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
255199ebb4caSwyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
255299ebb4caSwyllys {
255399ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
255499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
255599ebb4caSwyllys 	STACK_OF(X509) *cert_stack = NULL;
255699ebb4caSwyllys 	X509 *signer = NULL;
255799ebb4caSwyllys 	X509 *issuer = NULL;
2558553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
255999ebb4caSwyllys 	EVP_PKEY *skey = NULL;
2560300fdee2SAndy Fiddaman #else
2561300fdee2SAndy Fiddaman 	STACK_OF(X509) *cert_stack2 = NULL;
2562300fdee2SAndy Fiddaman #endif
256399ebb4caSwyllys 	unsigned char *ptmp;
256499ebb4caSwyllys 
256599ebb4caSwyllys 	if (bs == NULL || issuer_cert == NULL)
256699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
256799ebb4caSwyllys 
256899ebb4caSwyllys 	/*
256999ebb4caSwyllys 	 * Find the certificate that signed the basic response.
257099ebb4caSwyllys 	 *
257199ebb4caSwyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
257299ebb4caSwyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
257399ebb4caSwyllys 	 * If we still do not find a signer, we will look for it from the
257499ebb4caSwyllys 	 * certificate list came with the response file.
257599ebb4caSwyllys 	 */
257699ebb4caSwyllys 	if (signer_cert != NULL) {
257799ebb4caSwyllys 		ptmp = signer_cert->Data;
257899ebb4caSwyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
257999ebb4caSwyllys 		    signer_cert->Length);
258099ebb4caSwyllys 		if (signer == NULL) {
258199ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
258299ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
258399ebb4caSwyllys 			goto end;
258499ebb4caSwyllys 		}
258599ebb4caSwyllys 	} else {
258699ebb4caSwyllys 		/*
258799ebb4caSwyllys 		 * Convert the issuer cert into X509 and push it into a
258899ebb4caSwyllys 		 * stack to be used by ocsp_find_signer().
258999ebb4caSwyllys 		 */
259099ebb4caSwyllys 		ptmp = issuer_cert->Data;
259199ebb4caSwyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
259299ebb4caSwyllys 		    issuer_cert->Length);
259399ebb4caSwyllys 		if (issuer == NULL) {
259499ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
259599ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
259699ebb4caSwyllys 			goto end;
259799ebb4caSwyllys 		}
259899ebb4caSwyllys 
259999ebb4caSwyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
260099ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
260199ebb4caSwyllys 			goto end;
260299ebb4caSwyllys 		}
260399ebb4caSwyllys 
2604f810c7e5SToomas Soome 		if (sk_X509_push(cert_stack, issuer) == 0) {
260599ebb4caSwyllys 			ret = KMF_ERR_INTERNAL;
260699ebb4caSwyllys 			goto end;
260799ebb4caSwyllys 		}
260899ebb4caSwyllys 
260999ebb4caSwyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
261099ebb4caSwyllys 		if (!ret) {
261199ebb4caSwyllys 			/* can not find the signer */
261299ebb4caSwyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
261399ebb4caSwyllys 			goto end;
261499ebb4caSwyllys 		}
261599ebb4caSwyllys 	}
261699ebb4caSwyllys 
261799ebb4caSwyllys 	/* Verify the signature of the response */
2618553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
261999ebb4caSwyllys 	skey = X509_get_pubkey(signer);
262099ebb4caSwyllys 	if (skey == NULL) {
262199ebb4caSwyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
262299ebb4caSwyllys 		goto end;
262399ebb4caSwyllys 	}
262499ebb4caSwyllys 
262599ebb4caSwyllys 	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 
264599ebb4caSwyllys 	if (ret == 0) {
264699ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
264799ebb4caSwyllys 		goto end;
264899ebb4caSwyllys 	}
264999ebb4caSwyllys 
265099ebb4caSwyllys end:
265199ebb4caSwyllys 	if (issuer != NULL) {
265299ebb4caSwyllys 		X509_free(issuer);
265399ebb4caSwyllys 	}
265499ebb4caSwyllys 
265599ebb4caSwyllys 	if (signer != NULL) {
265699ebb4caSwyllys 		X509_free(signer);
265799ebb4caSwyllys 	}
265899ebb4caSwyllys 
2659553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
266099ebb4caSwyllys 	if (skey != NULL) {
266199ebb4caSwyllys 		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 
266999ebb4caSwyllys 	if (cert_stack != NULL) {
267099ebb4caSwyllys 		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 {
268099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
268199ebb4caSwyllys 	BIO *derbio = NULL;
268299ebb4caSwyllys 	OCSP_RESPONSE *resp = NULL;
268399ebb4caSwyllys 	OCSP_BASICRESP *bs = NULL;
268499ebb4caSwyllys 	OCSP_CERTID *id = NULL;
268599ebb4caSwyllys 	OCSP_SINGLERESP *single = NULL;
268699ebb4caSwyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
268799ebb4caSwyllys 	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;
269599ebb4caSwyllys 
269630a5e8faSwyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
269730a5e8faSwyllys 	    attrlist, numattr);
269830a5e8faSwyllys 	if (issuer_cert == NULL)
269999ebb4caSwyllys 		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);
270530a5e8faSwyllys 
270630a5e8faSwyllys 	response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
270730a5e8faSwyllys 	    attrlist, numattr);
270830a5e8faSwyllys 	if (response == NULL)
270930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
271030a5e8faSwyllys 
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);
271530a5e8faSwyllys 
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);
272030a5e8faSwyllys 
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 
272699ebb4caSwyllys 	/* Read in the response */
272730a5e8faSwyllys 	derbio = BIO_new_mem_buf(response->Data, response->Length);
272899ebb4caSwyllys 	if (!derbio) {
272999ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
273099ebb4caSwyllys 		return (ret);
273199ebb4caSwyllys 	}
273299ebb4caSwyllys 
273399ebb4caSwyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
273499ebb4caSwyllys 	if (resp == NULL) {
273599ebb4caSwyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
273699ebb4caSwyllys 		goto end;
273799ebb4caSwyllys 	}
273899ebb4caSwyllys 
273999ebb4caSwyllys 	/* Check the response status */
274099ebb4caSwyllys 	status = OCSP_response_status(resp);
274130a5e8faSwyllys 	*response_status = status;
274299ebb4caSwyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
274399ebb4caSwyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
274499ebb4caSwyllys 		goto end;
274599ebb4caSwyllys 	}
274699ebb4caSwyllys 
274799ebb4caSwyllys #ifdef DEBUG
274899ebb4caSwyllys 	printf("Successfully checked the response file status.\n");
274999ebb4caSwyllys #endif /* DEBUG */
275099ebb4caSwyllys 
275199ebb4caSwyllys 	/* Extract basic response */
275299ebb4caSwyllys 	bs = OCSP_response_get1_basic(resp);
275399ebb4caSwyllys 	if (bs == NULL) {
275499ebb4caSwyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
275599ebb4caSwyllys 		goto end;
275699ebb4caSwyllys 	}
275799ebb4caSwyllys 
275899ebb4caSwyllys #ifdef DEBUG
275999ebb4caSwyllys 	printf("Successfully retrieved the basic response.\n");
276099ebb4caSwyllys #endif /* DEBUG */
276199ebb4caSwyllys 
276299ebb4caSwyllys 	/* 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) {
277299ebb4caSwyllys 		ret = check_response_signature(handle, bs,
277330a5e8faSwyllys 		    signer_cert, issuer_cert);
277499ebb4caSwyllys 		if (ret != KMF_OK)
277599ebb4caSwyllys 			goto end;
277699ebb4caSwyllys 	}
277799ebb4caSwyllys 
277899ebb4caSwyllys #ifdef DEBUG
277999ebb4caSwyllys 	printf("Successfully verified the response signature.\n");
278099ebb4caSwyllys #endif /* DEBUG */
278199ebb4caSwyllys 
278299ebb4caSwyllys 	/* Create a certid for the certificate in question */
278330a5e8faSwyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
278499ebb4caSwyllys 	if (ret != KMF_OK) {
278599ebb4caSwyllys 		ret = KMF_ERR_OCSP_CERTID;
278699ebb4caSwyllys 		goto end;
278799ebb4caSwyllys 	}
278899ebb4caSwyllys 
278999ebb4caSwyllys #ifdef DEBUG
279099ebb4caSwyllys 	printf("successfully created a certid for the cert.\n");
279199ebb4caSwyllys #endif /* DEBUG */
279299ebb4caSwyllys 
279399ebb4caSwyllys 	/* Find the index of the single response for the certid */
279499ebb4caSwyllys 	index = OCSP_resp_find(bs, id, -1);
279599ebb4caSwyllys 	if (index < 0) {
279699ebb4caSwyllys 		/* cound not find this certificate in the response */
279799ebb4caSwyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
279899ebb4caSwyllys 		goto end;
279999ebb4caSwyllys 	}
280099ebb4caSwyllys 
280199ebb4caSwyllys #ifdef DEBUG
280299ebb4caSwyllys 	printf("Successfully found the single response index for the cert.\n");
280399ebb4caSwyllys #endif /* DEBUG */
280499ebb4caSwyllys 
280599ebb4caSwyllys 	/* Retrieve the single response and get the cert status */
280699ebb4caSwyllys 	single = OCSP_resp_get0(bs, index);
280799ebb4caSwyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
280899ebb4caSwyllys 	    &nextupd);
280999ebb4caSwyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
281030a5e8faSwyllys 		*cert_status = OCSP_GOOD;
281199ebb4caSwyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
281230a5e8faSwyllys 		*cert_status = OCSP_UNKNOWN;
281399ebb4caSwyllys 	} else { /* revoked */
281430a5e8faSwyllys 		*cert_status = OCSP_REVOKED;
281530a5e8faSwyllys 		*response_reason = reason;
281699ebb4caSwyllys 	}
281799ebb4caSwyllys 	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);
282230a5e8faSwyllys 
282399ebb4caSwyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
282430a5e8faSwyllys 	    response_lifetime)) {
282599ebb4caSwyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
282699ebb4caSwyllys 		goto end;
282799ebb4caSwyllys 	}
282899ebb4caSwyllys 
282999ebb4caSwyllys #ifdef DEBUG
283099ebb4caSwyllys 	printf("Successfully verify the time.\n");
283199ebb4caSwyllys #endif /* DEBUG */
283299ebb4caSwyllys 
283399ebb4caSwyllys end:
283499ebb4caSwyllys 	if (derbio != NULL)
283599ebb4caSwyllys 		(void) BIO_free(derbio);
283699ebb4caSwyllys 
283799ebb4caSwyllys 	if (resp != NULL)
283899ebb4caSwyllys 		OCSP_RESPONSE_free(resp);
283999ebb4caSwyllys 
284099ebb4caSwyllys 	if (bs != NULL)
284199ebb4caSwyllys 		OCSP_BASICRESP_free(bs);
284299ebb4caSwyllys 
284399ebb4caSwyllys 	if (id != NULL)
284499ebb4caSwyllys 		OCSP_CERTID_free(id);
284599ebb4caSwyllys 
284699ebb4caSwyllys 	return (ret);
284799ebb4caSwyllys }
284899ebb4caSwyllys 
284999ebb4caSwyllys 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 {
285399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
285430a5e8faSwyllys 	EVP_PKEY *pkey = NULL;
285599ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
285699ebb4caSwyllys 
285799ebb4caSwyllys 	if (keyclass == KMF_ASYM_PRI ||
285899ebb4caSwyllys 	    keyclass == KMF_ASYM_PUB) {
285999ebb4caSwyllys 		pkey = openssl_load_key(handle, path);
286099ebb4caSwyllys 		if (pkey == NULL) {
286199ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
286299ebb4caSwyllys 		}
286399ebb4caSwyllys 		if (key != NULL) {
2864300fdee2SAndy Fiddaman 			if (EVP_PKEY_get0_RSA(pkey) != NULL)
286599ebb4caSwyllys 				key->keyalg = KMF_RSA;
2866300fdee2SAndy Fiddaman 			else if (EVP_PKEY_get0_DSA(pkey) != NULL)
286799ebb4caSwyllys 				key->keyalg = KMF_DSA;
286899ebb4caSwyllys 
286999ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
287099ebb4caSwyllys 			key->keyclass = keyclass;
287199ebb4caSwyllys 			key->keyp = (void *)pkey;
287299ebb4caSwyllys 			key->israw = FALSE;
28735b3e1433Swyllys 			if (path != NULL &&
28745b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
28755b3e1433Swyllys 				EVP_PKEY_free(pkey);
28765b3e1433Swyllys 				return (KMF_ERR_MEMORY);
28775b3e1433Swyllys 			}
287899ebb4caSwyllys 		} else {
287999ebb4caSwyllys 			EVP_PKEY_free(pkey);
288099ebb4caSwyllys 			pkey = NULL;
288199ebb4caSwyllys 		}
288299ebb4caSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
288399ebb4caSwyllys 		KMF_ENCODE_FORMAT fmt;
288499ebb4caSwyllys 		/*
288599ebb4caSwyllys 		 * If the file is a recognized format,
288699ebb4caSwyllys 		 * then it is NOT a symmetric key.
288799ebb4caSwyllys 		 */
288830a5e8faSwyllys 		rv = kmf_get_file_format(path, &fmt);
288999ebb4caSwyllys 		if (rv == KMF_OK || fmt != 0) {
289099ebb4caSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
289199ebb4caSwyllys 		} else if (rv == KMF_ERR_ENCODING) {
289299ebb4caSwyllys 			/*
289399ebb4caSwyllys 			 * If we don't know the encoding,
289499ebb4caSwyllys 			 * it is probably  a symmetric key.
289599ebb4caSwyllys 			 */
289699ebb4caSwyllys 			rv = KMF_OK;
289730a5e8faSwyllys 		} else if (rv == KMF_ERR_OPEN_FILE) {
289830a5e8faSwyllys 			return (KMF_ERR_KEY_NOT_FOUND);
289999ebb4caSwyllys 		}
290099ebb4caSwyllys 
290199ebb4caSwyllys 		if (key != NULL) {
290299ebb4caSwyllys 			KMF_DATA keyvalue;
290399ebb4caSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
290499ebb4caSwyllys 			if (rkey == NULL) {
290599ebb4caSwyllys 				rv = KMF_ERR_MEMORY;
290699ebb4caSwyllys 				goto out;
290799ebb4caSwyllys 			}
290899ebb4caSwyllys 
290999ebb4caSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
291030a5e8faSwyllys 			rv = kmf_read_input_file(handle, path, &keyvalue);
291199ebb4caSwyllys 			if (rv != KMF_OK)
291299ebb4caSwyllys 				goto out;
291399ebb4caSwyllys 
291499ebb4caSwyllys 			rkey->keydata.len = keyvalue.Length;
291599ebb4caSwyllys 			rkey->keydata.val = keyvalue.Data;
291699ebb4caSwyllys 
291799ebb4caSwyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
291899ebb4caSwyllys 			key->keyclass = keyclass;
291999ebb4caSwyllys 			key->israw = TRUE;
292099ebb4caSwyllys 			key->keyp = (void *)rkey;
29215b3e1433Swyllys 			if (path != NULL &&
29225b3e1433Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
29235b3e1433Swyllys 				rv = KMF_ERR_MEMORY;
29245b3e1433Swyllys 			}
292599ebb4caSwyllys 		}
292699ebb4caSwyllys 	}
292799ebb4caSwyllys out:
292899ebb4caSwyllys 	if (rv != KMF_OK) {
292999ebb4caSwyllys 		if (rkey != NULL) {
293030a5e8faSwyllys 			kmf_free_raw_sym_key(rkey);
293199ebb4caSwyllys 		}
293299ebb4caSwyllys 		if (pkey != NULL)
293399ebb4caSwyllys 			EVP_PKEY_free(pkey);
293499ebb4caSwyllys 
293599ebb4caSwyllys 		if (key != NULL) {
293699ebb4caSwyllys 			key->keyalg = KMF_KEYALG_NONE;
293799ebb4caSwyllys 			key->keyclass = KMF_KEYCLASS_NONE;
293899ebb4caSwyllys 			key->keyp = NULL;
293999ebb4caSwyllys 		}
294099ebb4caSwyllys 	}
294199ebb4caSwyllys 
294299ebb4caSwyllys 	return (rv);
294399ebb4caSwyllys }
294499ebb4caSwyllys 
294599ebb4caSwyllys 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 {
294899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
294999ebb4caSwyllys 	char *fullpath = NULL;
2950f482c776Swyllys 	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;
295799ebb4caSwyllys 
295830a5e8faSwyllys 	if (handle == NULL)
295999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
296099ebb4caSwyllys 
296130a5e8faSwyllys 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
296230a5e8faSwyllys 	if (numkeys == NULL)
296330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
296430a5e8faSwyllys 
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);
296930a5e8faSwyllys 
297030a5e8faSwyllys 	if (keyclass != KMF_ASYM_PUB &&
297130a5e8faSwyllys 	    keyclass != KMF_ASYM_PRI &&
297230a5e8faSwyllys 	    keyclass != KMF_SYMMETRIC)
297399ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
297499ebb4caSwyllys 
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);
297999ebb4caSwyllys 
298099ebb4caSwyllys 	if (fullpath == NULL)
298199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
298299ebb4caSwyllys 
2983f482c776Swyllys 	maxkeys = *numkeys;
2984f482c776Swyllys 	if (maxkeys == 0)
2985f482c776Swyllys 		maxkeys = 0xFFFFFFFF;
298699ebb4caSwyllys 	*numkeys = 0;
298799ebb4caSwyllys 
298830a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
298930a5e8faSwyllys 	/* it is okay to have "keys" contains NULL */
299030a5e8faSwyllys 
299130a5e8faSwyllys 	/*
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.
299430a5e8faSwyllys 	 */
299530a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
299630a5e8faSwyllys 
299799ebb4caSwyllys 	if (isdir(fullpath)) {
299899ebb4caSwyllys 		DIR *dirp;
299999ebb4caSwyllys 		struct dirent *dp;
300099ebb4caSwyllys 		int n = 0;
300199ebb4caSwyllys 
300299ebb4caSwyllys 		/* open all files in the directory and attempt to read them */
300399ebb4caSwyllys 		if ((dirp = opendir(fullpath)) == NULL) {
300499ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
300599ebb4caSwyllys 		}
300699ebb4caSwyllys 		rewinddir(dirp);
3007f482c776Swyllys 		while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
300899ebb4caSwyllys 			if (strcmp(dp->d_name, ".") &&
300999ebb4caSwyllys 			    strcmp(dp->d_name, "..")) {
301099ebb4caSwyllys 				char *fname;
301199ebb4caSwyllys 
301299ebb4caSwyllys 				fname = get_fullpath(fullpath,
301399ebb4caSwyllys 				    (char *)&dp->d_name);
301499ebb4caSwyllys 
301599ebb4caSwyllys 				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]);
302299ebb4caSwyllys 					n++;
302330a5e8faSwyllys 				}
302499ebb4caSwyllys 
302599ebb4caSwyllys 				if (rv != KMF_OK || key == NULL)
302699ebb4caSwyllys 					free(fname);
302799ebb4caSwyllys 			}
302899ebb4caSwyllys 		}
302999ebb4caSwyllys 		(void) closedir(dirp);
303099ebb4caSwyllys 		free(fullpath);
303199ebb4caSwyllys 		(*numkeys) = n;
303299ebb4caSwyllys 	} else {
303330a5e8faSwyllys 		rv = fetch_key(handle, fullpath, keyclass, key);
303499ebb4caSwyllys 		if (rv == KMF_OK)
303599ebb4caSwyllys 			(*numkeys) = 1;
303699ebb4caSwyllys 
303799ebb4caSwyllys 		if (rv != KMF_OK || key == NULL)
303899ebb4caSwyllys 			free(fullpath);
303930a5e8faSwyllys 
304030a5e8faSwyllys 		if (rv == KMF_OK && key != NULL && rawkey != NULL) {
304130a5e8faSwyllys 			rv = convertToRawKey(key->keyp, rawkey);
304230a5e8faSwyllys 		}
304399ebb4caSwyllys 	}
304499ebb4caSwyllys 
3045f482c776Swyllys 	if (rv == KMF_OK && (*numkeys) == 0)
304699ebb4caSwyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
304773cc0e02Swyllys 	else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
304873cc0e02Swyllys 		rv = KMF_OK;
304999ebb4caSwyllys 
305099ebb4caSwyllys 	return (rv);
305199ebb4caSwyllys }
305299ebb4caSwyllys 
305399ebb4caSwyllys #define	HANDLE_PK12_ERROR { \
305499ebb4caSwyllys 	SET_ERROR(kmfh, ERR_get_error()); \
305599ebb4caSwyllys 	rv = KMF_ERR_ENCODING; \
305699ebb4caSwyllys 	goto out; \
305799ebb4caSwyllys }
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 }
30725b3e1433Swyllys 
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,
30755b3e1433Swyllys     uchar_t *keyid, unsigned int keyidlen)
30765b3e1433Swyllys {
307799ebb4caSwyllys 	PKCS12_SAFEBAG *bag = NULL;
307899ebb4caSwyllys 	PKCS7 *cert_authsafe = NULL;
30795b3e1433Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack;
308099ebb4caSwyllys 
308199ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
308299ebb4caSwyllys 	if (bag_stack == NULL)
30835b3e1433Swyllys 		return (NULL);
308499ebb4caSwyllys 
308599ebb4caSwyllys 	/* Convert cert from X509 struct to PKCS#12 bag */
3086300fdee2SAndy Fiddaman 	bag = PKCS12_SAFEBAG_create_cert(sslcert);
308799ebb4caSwyllys 	if (bag == NULL) {
30885b3e1433Swyllys 		goto out;
308999ebb4caSwyllys 	}
309099ebb4caSwyllys 
309199ebb4caSwyllys 	/* Add the key id to the certificate bag. */
30925b3e1433Swyllys 	if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
30935b3e1433Swyllys 		goto out;
309499ebb4caSwyllys 	}
309599ebb4caSwyllys 
30965b3e1433Swyllys 	if (!add_alias_to_bag(bag, sslcert))
30975b3e1433Swyllys 		goto out;
30985b3e1433Swyllys 
309999ebb4caSwyllys 	/* Pile it on the bag_stack. */
310099ebb4caSwyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
31015b3e1433Swyllys 		goto out;
310299ebb4caSwyllys 	}
310399ebb4caSwyllys 	/* Turn bag_stack of certs into encrypted authsafe. */
310499ebb4caSwyllys 	cert_authsafe = PKCS12_pack_p7encdata(
310599ebb4caSwyllys 	    NID_pbe_WithSHA1And40BitRC2_CBC,
310634acef67Swyllys 	    cred->cred, cred->credlen, NULL, 0,
310734acef67Swyllys 	    PKCS12_DEFAULT_ITER, bag_stack);
310899ebb4caSwyllys 
31095b3e1433Swyllys out:
31105b3e1433Swyllys 	if (bag_stack != NULL)
311199ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
311299ebb4caSwyllys 
31135b3e1433Swyllys 	return (cert_authsafe);
311499ebb4caSwyllys }
31155b3e1433Swyllys 
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;
31245b3e1433Swyllys 
312599ebb4caSwyllys 	p8 = EVP_PKEY2PKCS8(pkey);
312699ebb4caSwyllys 	if (p8 == NULL) {
31275b3e1433Swyllys 		return (NULL);
312899ebb4caSwyllys 	}
312999ebb4caSwyllys 	/* Put the shrouded key into a PKCS#12 bag. */
3130300fdee2SAndy Fiddaman 	bag = PKCS12_SAFEBAG_create_pkcs8_encrypt(
313199ebb4caSwyllys 	    NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
313299ebb4caSwyllys 	    cred->cred, cred->credlen,
313399ebb4caSwyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, p8);
313499ebb4caSwyllys 
313599ebb4caSwyllys 	/* Clean up the PKCS#8 shrouded key, don't need it now. */
313699ebb4caSwyllys 	PKCS8_PRIV_KEY_INFO_free(p8);
313799ebb4caSwyllys 	p8 = NULL;
313899ebb4caSwyllys 
313999ebb4caSwyllys 	if (bag == NULL) {
31405b3e1433Swyllys 		return (NULL);
314199ebb4caSwyllys 	}
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 
314799ebb4caSwyllys 	/* Start a PKCS#12 safebag container for the private key. */
314899ebb4caSwyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
31495b3e1433Swyllys 	if (bag_stack == NULL)
31505b3e1433Swyllys 		goto out;
315199ebb4caSwyllys 
315299ebb4caSwyllys 	/* Pile on the private key on the bag_stack. */
31535b3e1433Swyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
31545b3e1433Swyllys 		goto out;
31555b3e1433Swyllys 
315699ebb4caSwyllys 	key_authsafe = PKCS12_pack_p7data(bag_stack);
315799ebb4caSwyllys 
31585b3e1433Swyllys out:
31595b3e1433Swyllys 	if (bag_stack != NULL)
316099ebb4caSwyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
316199ebb4caSwyllys 	bag_stack = NULL;
31625b3e1433Swyllys 	return (key_authsafe);
316399ebb4caSwyllys }
316499ebb4caSwyllys 
316599ebb4caSwyllys static EVP_PKEY *
ImportRawRSAKey(KMF_RAW_RSA_KEY * key)316699ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
316799ebb4caSwyllys {
316899ebb4caSwyllys 	RSA		*rsa = NULL;
316999ebb4caSwyllys 	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 
317399ebb4caSwyllys 	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 
321699ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
3217300fdee2SAndy Fiddaman 		goto cleanup;
321899ebb4caSwyllys 
321999ebb4caSwyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
322099ebb4caSwyllys 
3221300fdee2SAndy Fiddaman cleanup:
322299ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
3223300fdee2SAndy Fiddaman 	if (rsa)
322499ebb4caSwyllys 		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 
323499ebb4caSwyllys 	return (newkey);
323599ebb4caSwyllys }
323699ebb4caSwyllys 
323799ebb4caSwyllys static EVP_PKEY *
ImportRawDSAKey(KMF_RAW_DSA_KEY * key)323899ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
323999ebb4caSwyllys {
324099ebb4caSwyllys 	DSA		*dsa = NULL;
324199ebb4caSwyllys 	EVP_PKEY	*newkey = NULL;
32424942e222SAndy Fiddaman 	BIGNUM		*p = NULL, *q = NULL, *g = NULL;
32434942e222SAndy Fiddaman 	BIGNUM		*priv_key = NULL, *pub_key = NULL;
324499ebb4caSwyllys 
324599ebb4caSwyllys 	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;
326099ebb4caSwyllys 
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;
327130a5e8faSwyllys 
327299ebb4caSwyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
3273300fdee2SAndy Fiddaman 		goto cleanup;
327499ebb4caSwyllys 
327599ebb4caSwyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
327699ebb4caSwyllys 
3277300fdee2SAndy Fiddaman cleanup:
327899ebb4caSwyllys 	/* The original key must be freed once here or it leaks memory */
3279300fdee2SAndy Fiddaman 	if (dsa)
328099ebb4caSwyllys 		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 
328799ebb4caSwyllys 	return (newkey);
328899ebb4caSwyllys }
328999ebb4caSwyllys 
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 
338399ebb4caSwyllys 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,
338699ebb4caSwyllys     char *filename)
338799ebb4caSwyllys {
338899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
338999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
339099ebb4caSwyllys 	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;
339599ebb4caSwyllys 	int i;
339699ebb4caSwyllys 
33975b3e1433Swyllys 	if (numcerts == 0 && numkeys == 0)
33985b3e1433Swyllys 		return (KMF_ERR_BAD_PARAMETER);
33995b3e1433Swyllys 
340099ebb4caSwyllys 	/*
340199ebb4caSwyllys 	 * Open the output file.
340299ebb4caSwyllys 	 */
340399ebb4caSwyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
340499ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
340599ebb4caSwyllys 		rv = KMF_ERR_OPEN_FILE;
340699ebb4caSwyllys 		goto cleanup;
340799ebb4caSwyllys 	}
340899ebb4caSwyllys 
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) {
341699ebb4caSwyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
341799ebb4caSwyllys 			const uchar_t *p = certlist[i].certificate.Data;
341899ebb4caSwyllys 			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;
342399ebb4caSwyllys 
342499ebb4caSwyllys 			xcert = d2i_X509(NULL, &p, len);
342599ebb4caSwyllys 			if (xcert == NULL) {
342699ebb4caSwyllys 				SET_ERROR(kmfh, ERR_get_error());
342799ebb4caSwyllys 				rv = KMF_ERR_ENCODING;
342899ebb4caSwyllys 			}
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)) {
34745b3e1433Swyllys 				X509_free(xcert);
34755b3e1433Swyllys 				EVP_PKEY_free(pkey);
34765b3e1433Swyllys 				goto cleanup;
34775b3e1433Swyllys 			}
34785b3e1433Swyllys 
347999ebb4caSwyllys 			X509_free(xcert);
348099ebb4caSwyllys 			if (pkey)
348199ebb4caSwyllys 				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;
351499ebb4caSwyllys 	}
351599ebb4caSwyllys 
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;
35305b3e1433Swyllys 	}
35315b3e1433Swyllys 	PKCS12_free(p12_elem);
35325b3e1433Swyllys 
353399ebb4caSwyllys 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 
353899ebb4caSwyllys 	if (bio != NULL)
353999ebb4caSwyllys 		(void) BIO_free_all(bio);
354099ebb4caSwyllys 
354199ebb4caSwyllys 	return (rv);
354299ebb4caSwyllys }
354399ebb4caSwyllys 
354499ebb4caSwyllys 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;
355030a5e8faSwyllys 
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);
355630a5e8faSwyllys 
355730a5e8faSwyllys 	return (rv);
355830a5e8faSwyllys }
355930a5e8faSwyllys 
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 {
356399ebb4caSwyllys 	KMF_RETURN rv;
356499ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
356599ebb4caSwyllys 	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;
357530a5e8faSwyllys 
357630a5e8faSwyllys 	if (handle == NULL)
357730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
357899ebb4caSwyllys 
357999ebb4caSwyllys 	/*
358099ebb4caSwyllys 	 *  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);
358699ebb4caSwyllys 		if (fullpath == NULL)
358799ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
358899ebb4caSwyllys 
358999ebb4caSwyllys 		if (isdir(fullpath)) {
359099ebb4caSwyllys 			free(fullpath);
359199ebb4caSwyllys 			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);
359799ebb4caSwyllys 		if (rv != KMF_OK)
359899ebb4caSwyllys 			goto end;
359930a5e8faSwyllys 
36005b3e1433Swyllys 		gotcert++;
36015b3e1433Swyllys 		certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
360230a5e8faSwyllys 		free(fullpath);
360399ebb4caSwyllys 	}
360499ebb4caSwyllys 
360599ebb4caSwyllys 	/*
360699ebb4caSwyllys 	 * Now find the private key.
360799ebb4caSwyllys 	 */
360830a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
360930a5e8faSwyllys 	if (keyfile != NULL) {
361030a5e8faSwyllys 		fullpath = get_fullpath(dirpath, keyfile);
361199ebb4caSwyllys 		if (fullpath == NULL)
361299ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
361399ebb4caSwyllys 
361499ebb4caSwyllys 		if (isdir(fullpath)) {
361599ebb4caSwyllys 			free(fullpath);
361699ebb4caSwyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
361799ebb4caSwyllys 		}
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)
362299ebb4caSwyllys 			goto end;
36235b3e1433Swyllys 		gotkey++;
362499ebb4caSwyllys 	}
362599ebb4caSwyllys 
362699ebb4caSwyllys 	/*
362799ebb4caSwyllys 	 * 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 	}
363530a5e8faSwyllys 
363699ebb4caSwyllys 	/* 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);
364599ebb4caSwyllys 
364699ebb4caSwyllys end:
364799ebb4caSwyllys 	if (fullpath)
364899ebb4caSwyllys 		free(fullpath);
364999ebb4caSwyllys 
36505b3e1433Swyllys 	if (gotcert)
36515b3e1433Swyllys 		kmf_free_kmf_cert(handle, &certdata);
36525b3e1433Swyllys 	if (gotkey)
36535b3e1433Swyllys 		kmf_free_kmf_key(handle, &key);
365499ebb4caSwyllys 	return (rv);
365599ebb4caSwyllys }
365699ebb4caSwyllys 
365771593db2Swyllys /*
365871593db2Swyllys  * Helper function to extract keys and certificates from
365971593db2Swyllys  * a single PEM file.  Typically the file should contain a
366071593db2Swyllys  * private key and an associated public key wrapped in an x509 cert.
366171593db2Swyllys  * However, the file may be just a list of X509 certs with no keys.
366271593db2Swyllys  */
366371593db2Swyllys 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)
366771593db2Swyllys {
366871593db2Swyllys 	KMF_RETURN rv = KMF_OK;
366971593db2Swyllys 	FILE *fp;
367034acef67Swyllys 	STACK_OF(X509_INFO) *x509_info_stack = NULL;
367102744e81Swyllys 	int i, ncerts = 0, matchcerts = 0;
367271593db2Swyllys 	EVP_PKEY *pkey = NULL;
367371593db2Swyllys 	X509_INFO *info;
367471593db2Swyllys 	X509 *x;
36755b3e1433Swyllys 	X509_INFO **cert_infos = NULL;
367671593db2Swyllys 	KMF_DATA *certlist = NULL;
367771593db2Swyllys 
367871593db2Swyllys 	if (priv_key)
367971593db2Swyllys 		*priv_key = NULL;
368071593db2Swyllys 	if (certs)
368171593db2Swyllys 		*certs = NULL;
368271593db2Swyllys 	fp = fopen(filename, "r");
36835b3e1433Swyllys 	if (fp == NULL)
368471593db2Swyllys 		return (KMF_ERR_OPEN_FILE);
36855b3e1433Swyllys 
368671593db2Swyllys 	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
368771593db2Swyllys 	if (x509_info_stack == NULL) {
368871593db2Swyllys 		(void) fclose(fp);
368971593db2Swyllys 		return (KMF_ERR_ENCODING);
369071593db2Swyllys 	}
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 	}
369871593db2Swyllys 
36995b3e1433Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
370034acef67Swyllys 		cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
370171593db2Swyllys 		ncerts++;
370271593db2Swyllys 	}
370371593db2Swyllys 
370471593db2Swyllys 	if (ncerts == 0) {
370571593db2Swyllys 		(void) fclose(fp);
370634acef67Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
370734acef67Swyllys 		goto err;
370871593db2Swyllys 	}
370971593db2Swyllys 
371071593db2Swyllys 	if (priv_key != NULL) {
371171593db2Swyllys 		rewind(fp);
371271593db2Swyllys 		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
371371593db2Swyllys 	}
371471593db2Swyllys 	(void) fclose(fp);
371571593db2Swyllys 
371671593db2Swyllys 	x = cert_infos[ncerts - 1]->x509;
371771593db2Swyllys 	/*
371871593db2Swyllys 	 * Make sure the private key matchs the last cert in the file.
371971593db2Swyllys 	 */
372071593db2Swyllys 	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
372171593db2Swyllys 		EVP_PKEY_free(pkey);
372234acef67Swyllys 		rv = KMF_ERR_KEY_MISMATCH;
372334acef67Swyllys 		goto err;
372471593db2Swyllys 	}
372571593db2Swyllys 
3726a2d4930dSDan OpenSolaris Anderson 	certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
372771593db2Swyllys 	if (certlist == NULL) {
372871593db2Swyllys 		if (pkey != NULL)
372971593db2Swyllys 			EVP_PKEY_free(pkey);
373034acef67Swyllys 		rv = KMF_ERR_MEMORY;
373134acef67Swyllys 		goto err;
373271593db2Swyllys 	}
373371593db2Swyllys 
373471593db2Swyllys 	/*
373571593db2Swyllys 	 * Convert all of the certs to DER format.
373671593db2Swyllys 	 */
373702744e81Swyllys 	matchcerts = 0;
373871593db2Swyllys 	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
373902744e81Swyllys 		boolean_t match = FALSE;
374071593db2Swyllys 		info =  cert_infos[ncerts - 1 - i];
374171593db2Swyllys 
374230a5e8faSwyllys 		rv = check_cert(info->x509, issuer, subject, serial, &match);
374302744e81Swyllys 		if (rv != KMF_OK || match != TRUE) {
374402744e81Swyllys 			rv = KMF_OK;
374502744e81Swyllys 			continue;
374602744e81Swyllys 		}
374702744e81Swyllys 
374802744e81Swyllys 		rv = ssl_cert2KMFDATA(kmfh, info->x509,
374902744e81Swyllys 		    &certlist[matchcerts++]);
375071593db2Swyllys 
375171593db2Swyllys 		if (rv != KMF_OK) {
3752e65e5c2dSWyllys Ingersoll 			int j;
3753e65e5c2dSWyllys Ingersoll 			for (j = 0; j < matchcerts; j++)
3754e65e5c2dSWyllys Ingersoll 				kmf_free_data(&certlist[j]);
375571593db2Swyllys 			free(certlist);
375671593db2Swyllys 			certlist = NULL;
375702744e81Swyllys 			ncerts = matchcerts = 0;
375871593db2Swyllys 		}
375971593db2Swyllys 	}
376071593db2Swyllys 
376171593db2Swyllys 	if (numcerts != NULL)
376202744e81Swyllys 		*numcerts = matchcerts;
3763a2d4930dSDan OpenSolaris Anderson 
3764e65e5c2dSWyllys Ingersoll 	if (certs != NULL)
376571593db2Swyllys 		*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 	}
377271593db2Swyllys 
377371593db2Swyllys 	if (priv_key == NULL && pkey != NULL)
377471593db2Swyllys 		EVP_PKEY_free(pkey);
377571593db2Swyllys 	else if (priv_key != NULL && pkey != NULL)
377671593db2Swyllys 		*priv_key = pkey;
377771593db2Swyllys 
377834acef67Swyllys err:
377934acef67Swyllys 	/* Cleanup the stack of X509 info records */
378034acef67Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
378134acef67Swyllys 		info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
378234acef67Swyllys 		X509_INFO_free(info);
378334acef67Swyllys 	}
378434acef67Swyllys 	if (x509_info_stack)
378534acef67Swyllys 		sk_X509_INFO_free(x509_info_stack);
378634acef67Swyllys 
37875b3e1433Swyllys 	if (cert_infos != NULL)
37885b3e1433Swyllys 		free(cert_infos);
37895b3e1433Swyllys 
379071593db2Swyllys 	return (rv);
379171593db2Swyllys }
379271593db2Swyllys 
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,
37955b3e1433Swyllys     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,
38395b3e1433Swyllys     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 
402699ebb4caSwyllys /*
402799ebb4caSwyllys  * Helper function to decrypt and parse PKCS#12 import file.
402899ebb4caSwyllys  */
402999ebb4caSwyllys 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)403099ebb4caSwyllys 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)
403299ebb4caSwyllys {
403399ebb4caSwyllys 	PKCS12			*pk12, *pk12_tmp;
40345b3e1433Swyllys 	STACK_OF(EVP_PKEY)	*pkeylist = NULL;
40355b3e1433Swyllys 	STACK_OF(X509)		*xcertlist = NULL;
40365b3e1433Swyllys 	STACK_OF(X509)		*cacertlist = NULL;
403799ebb4caSwyllys 
403899ebb4caSwyllys 	if ((pk12 = PKCS12_new()) == NULL) {
403999ebb4caSwyllys 		return (KMF_ERR_MEMORY);
404099ebb4caSwyllys 	}
404199ebb4caSwyllys 
404299ebb4caSwyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
404399ebb4caSwyllys 		/* This is ok; it seems to mean there is no more to read. */
404499ebb4caSwyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
404599ebb4caSwyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
404699ebb4caSwyllys 			goto end_extract_pkcs12;
404799ebb4caSwyllys 
404899ebb4caSwyllys 		PKCS12_free(pk12);
404999ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
405099ebb4caSwyllys 	}
405199ebb4caSwyllys 	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);
406999ebb4caSwyllys 		PKCS12_free(pk12);
407099ebb4caSwyllys 		return (KMF_ERR_PKCS12_FORMAT);
407199ebb4caSwyllys 	}
407299ebb4caSwyllys 
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);
408599ebb4caSwyllys 
40865b3e1433Swyllys end_extract_pkcs12:
408799ebb4caSwyllys 
408899ebb4caSwyllys 	PKCS12_free(pk12);
408999ebb4caSwyllys 	return (KMF_OK);
409099ebb4caSwyllys }
409199ebb4caSwyllys 
409299ebb4caSwyllys static KMF_RETURN
sslBN2KMFBN(BIGNUM * from,KMF_BIGINT * to)409399ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
409499ebb4caSwyllys {
409599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
409699ebb4caSwyllys 	uint32_t sz;
409799ebb4caSwyllys 
409899ebb4caSwyllys 	sz = BN_num_bytes(from);
409999ebb4caSwyllys 	to->val = (uchar_t *)malloc(sz);
410099ebb4caSwyllys 	if (to->val == NULL)
410199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
410299ebb4caSwyllys 
410399ebb4caSwyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
410499ebb4caSwyllys 		free(to->val);
410599ebb4caSwyllys 		to->val = NULL;
410699ebb4caSwyllys 		to->len = 0;
410799ebb4caSwyllys 		rv = KMF_ERR_MEMORY;
410899ebb4caSwyllys 	}
410999ebb4caSwyllys 
411099ebb4caSwyllys 	return (rv);
411199ebb4caSwyllys }
411299ebb4caSwyllys 
411399ebb4caSwyllys static KMF_RETURN
exportRawRSAKey(RSA * rsa,KMF_RAW_KEY_DATA * key)411499ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
411599ebb4caSwyllys {
411699ebb4caSwyllys 	KMF_RETURN rv;
411799ebb4caSwyllys 	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 
412599ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
4126300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)n, &kmfkey->mod)) != KMF_OK)
412799ebb4caSwyllys 		goto cleanup;
412899ebb4caSwyllys 
4129300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)e, &kmfkey->pubexp)) != KMF_OK)
413099ebb4caSwyllys 		goto cleanup;
413199ebb4caSwyllys 
4132300fdee2SAndy Fiddaman 	if (d != NULL)
4133300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)d, &kmfkey->priexp)) != KMF_OK)
413499ebb4caSwyllys 			goto cleanup;
413599ebb4caSwyllys 
4136300fdee2SAndy Fiddaman 	if (p != NULL)
4137300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime1)) != KMF_OK)
413899ebb4caSwyllys 			goto cleanup;
413999ebb4caSwyllys 
4140300fdee2SAndy Fiddaman 	if (q != NULL)
4141300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->prime2)) != KMF_OK)
414299ebb4caSwyllys 			goto cleanup;
414399ebb4caSwyllys 
4144300fdee2SAndy Fiddaman 	if (dmp1 != NULL)
4145300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)dmp1, &kmfkey->exp1)) != KMF_OK)
414699ebb4caSwyllys 			goto cleanup;
414799ebb4caSwyllys 
4148300fdee2SAndy Fiddaman 	if (dmpq != NULL)
4149300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)dmpq, &kmfkey->exp2)) != KMF_OK)
415099ebb4caSwyllys 			goto cleanup;
415199ebb4caSwyllys 
4152300fdee2SAndy Fiddaman 	if (iqmp != NULL)
4153300fdee2SAndy Fiddaman 		if ((rv = sslBN2KMFBN((BIGNUM *)iqmp, &kmfkey->coef)) != KMF_OK)
415499ebb4caSwyllys 			goto cleanup;
415599ebb4caSwyllys cleanup:
415699ebb4caSwyllys 	if (rv != KMF_OK)
415730a5e8faSwyllys 		kmf_free_raw_key(key);
415899ebb4caSwyllys 	else
415999ebb4caSwyllys 		key->keytype = KMF_RSA;
416099ebb4caSwyllys 
416199ebb4caSwyllys 	/*
416299ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
416399ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
416499ebb4caSwyllys 	 */
416599ebb4caSwyllys 	RSA_free(rsa);
416699ebb4caSwyllys 
416799ebb4caSwyllys 	return (rv);
416899ebb4caSwyllys }
416999ebb4caSwyllys 
417099ebb4caSwyllys static KMF_RETURN
exportRawDSAKey(DSA * dsa,KMF_RAW_KEY_DATA * key)417199ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
417299ebb4caSwyllys {
417399ebb4caSwyllys 	KMF_RETURN rv;
417499ebb4caSwyllys 	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 
418099ebb4caSwyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
4181300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime)) != KMF_OK)
418299ebb4caSwyllys 		goto cleanup;
418399ebb4caSwyllys 
4184300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->subprime)) != KMF_OK)
418599ebb4caSwyllys 		goto cleanup;
418699ebb4caSwyllys 
4187300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)g, &kmfkey->base)) != KMF_OK)
418899ebb4caSwyllys 		goto cleanup;
418999ebb4caSwyllys 
4190300fdee2SAndy Fiddaman 	if ((rv = sslBN2KMFBN((BIGNUM *)priv_key, &kmfkey->value)) != KMF_OK)
419199ebb4caSwyllys 		goto cleanup;
419299ebb4caSwyllys 
419399ebb4caSwyllys cleanup:
419499ebb4caSwyllys 	if (rv != KMF_OK)
419530a5e8faSwyllys 		kmf_free_raw_key(key);
419699ebb4caSwyllys 	else
419799ebb4caSwyllys 		key->keytype = KMF_DSA;
419899ebb4caSwyllys 
419999ebb4caSwyllys 	/*
420099ebb4caSwyllys 	 * Free the reference to this key, SSL will not actually free
420199ebb4caSwyllys 	 * the memory until the refcount == 0, so this is safe.
420299ebb4caSwyllys 	 */
420399ebb4caSwyllys 	DSA_free(dsa);
420499ebb4caSwyllys 
420599ebb4caSwyllys 	return (rv);
420699ebb4caSwyllys }
420799ebb4caSwyllys 
420899ebb4caSwyllys static KMF_RETURN
add_cert_to_list(KMF_HANDLE * kmfh,X509 * sslcert,KMF_X509_DER_CERT ** certlist,int * ncerts)420999ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
42105b3e1433Swyllys     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;
421599ebb4caSwyllys 	int n = (*ncerts);
421699ebb4caSwyllys 
421799ebb4caSwyllys 	if (list == NULL) {
42185b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
421999ebb4caSwyllys 	} else {
42205b3e1433Swyllys 		list = (KMF_X509_DER_CERT *)realloc(list,
42215b3e1433Swyllys 		    sizeof (KMF_X509_DER_CERT) * (n + 1));
422299ebb4caSwyllys 	}
422399ebb4caSwyllys 
422499ebb4caSwyllys 	if (list == NULL)
422599ebb4caSwyllys 		return (KMF_ERR_MEMORY);
422699ebb4caSwyllys 
42275b3e1433Swyllys 	(void) memset(&cert, 0, sizeof (cert));
42285b3e1433Swyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
422999ebb4caSwyllys 	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 
423799ebb4caSwyllys 		list[n] = cert;
423899ebb4caSwyllys 		(*ncerts) = n + 1;
423999ebb4caSwyllys 
424099ebb4caSwyllys 		*certlist = list;
424199ebb4caSwyllys 	} else {
424299ebb4caSwyllys 		free(list);
424399ebb4caSwyllys 	}
424499ebb4caSwyllys 
424599ebb4caSwyllys 	return (rv);
424699ebb4caSwyllys }
424799ebb4caSwyllys 
424899ebb4caSwyllys static KMF_RETURN
add_key_to_list(KMF_RAW_KEY_DATA ** keylist,KMF_RAW_KEY_DATA * newkey,int * nkeys)424999ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
425099ebb4caSwyllys     KMF_RAW_KEY_DATA *newkey, int *nkeys)
425199ebb4caSwyllys {
425299ebb4caSwyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
425399ebb4caSwyllys 	int n = (*nkeys);
425499ebb4caSwyllys 
425599ebb4caSwyllys 	if (list == NULL) {
425699ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
425799ebb4caSwyllys 	} else {
425899ebb4caSwyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
425999ebb4caSwyllys 		    sizeof (KMF_RAW_KEY_DATA) * (n + 1));
426099ebb4caSwyllys 	}
426199ebb4caSwyllys 
426299ebb4caSwyllys 	if (list == NULL)
426399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
426499ebb4caSwyllys 
426599ebb4caSwyllys 	list[n] = *newkey;
426699ebb4caSwyllys 	(*nkeys) = n + 1;
426799ebb4caSwyllys 
426899ebb4caSwyllys 	*keylist = list;
426999ebb4caSwyllys 
427099ebb4caSwyllys 	return (KMF_OK);
427199ebb4caSwyllys }
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;
428130a5e8faSwyllys 
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);
428730a5e8faSwyllys 		if (rv != KMF_OK)
428830a5e8faSwyllys 			return (rv);
4289300fdee2SAndy Fiddaman 	} else if ((dsa = EVP_PKEY_get1_DSA(pkey)) != NULL) {
4290300fdee2SAndy Fiddaman 		rv = exportRawDSAKey(dsa, key);
429130a5e8faSwyllys 		if (rv != KMF_OK)
429230a5e8faSwyllys 			return (rv);
4293300fdee2SAndy Fiddaman 	} else
429430a5e8faSwyllys 		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 	}
433630a5e8faSwyllys 
433730a5e8faSwyllys 	return (rv);
433830a5e8faSwyllys }
433999ebb4caSwyllys 
434099ebb4caSwyllys 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)434199ebb4caSwyllys convertPK12Objects(
434299ebb4caSwyllys 	KMF_HANDLE *kmfh,
43435b3e1433Swyllys 	STACK_OF(EVP_PKEY) *sslkeys,
43445b3e1433Swyllys 	STACK_OF(X509) *sslcert,
43455b3e1433Swyllys 	STACK_OF(X509) *sslcacerts,
434699ebb4caSwyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
43475b3e1433Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
434899ebb4caSwyllys {
434999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
435099ebb4caSwyllys 	KMF_RAW_KEY_DATA key;
435199ebb4caSwyllys 	int i;
435299ebb4caSwyllys 
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)
435799ebb4caSwyllys 			rv = add_key_to_list(keylist, &key, nkeys);
435830a5e8faSwyllys 
435999ebb4caSwyllys 		if (rv != KMF_OK)
436099ebb4caSwyllys 			return (rv);
436199ebb4caSwyllys 	}
436299ebb4caSwyllys 
436399ebb4caSwyllys 	/* 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);
436799ebb4caSwyllys 		if (rv != KMF_OK)
436899ebb4caSwyllys 			return (rv);
436999ebb4caSwyllys 	}
437099ebb4caSwyllys 
437199ebb4caSwyllys 	/* Also add any included CA certs to the list */
437271593db2Swyllys 	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
437399ebb4caSwyllys 		X509 *c;
437499ebb4caSwyllys 		/*
437599ebb4caSwyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
437699ebb4caSwyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
437799ebb4caSwyllys 		 * Lint is complaining about the embedded casting, and
437899ebb4caSwyllys 		 * to fix it, you need to fix openssl header files.
437999ebb4caSwyllys 		 */
438099ebb4caSwyllys 		c = sk_X509_value(sslcacerts, i);
438199ebb4caSwyllys 
438299ebb4caSwyllys 		/* Now add the ca cert to the certlist */
438399ebb4caSwyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
438499ebb4caSwyllys 		if (rv != KMF_OK)
438599ebb4caSwyllys 			return (rv);
438699ebb4caSwyllys 	}
438799ebb4caSwyllys 	return (rv);
438899ebb4caSwyllys }
438999ebb4caSwyllys 
439099ebb4caSwyllys 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,
43925b3e1433Swyllys     KMF_X509_DER_CERT **certlist, int *ncerts,
439399ebb4caSwyllys     KMF_RAW_KEY_DATA **keylist, int *nkeys)
439499ebb4caSwyllys {
439599ebb4caSwyllys 	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;
440099ebb4caSwyllys 	STACK_OF(X509)		*cacerts = NULL;
440199ebb4caSwyllys 
440230a5e8faSwyllys 	/*
440330a5e8faSwyllys 	 * auto-detect the file format, regardless of what
440430a5e8faSwyllys 	 * the 'format' parameters in the params say.
440530a5e8faSwyllys 	 */
440630a5e8faSwyllys 	rv = kmf_get_file_format(filename, &format);
440730a5e8faSwyllys 	if (rv != KMF_OK) {
440830a5e8faSwyllys 		return (rv);
440930a5e8faSwyllys 	}
441030a5e8faSwyllys 
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);
441630a5e8faSwyllys 
441730a5e8faSwyllys 	*certlist = NULL;
441830a5e8faSwyllys 	*keylist = NULL;
441930a5e8faSwyllys 	*ncerts = 0;
442030a5e8faSwyllys 	*nkeys = 0;
442130a5e8faSwyllys 
442230a5e8faSwyllys 	if (format == KMF_FORMAT_PKCS12) {
442399ebb4caSwyllys 		bio = BIO_new_file(filename, "rb");
442499ebb4caSwyllys 		if (bio == NULL) {
442599ebb4caSwyllys 			SET_ERROR(kmfh, ERR_get_error());
442699ebb4caSwyllys 			rv = KMF_ERR_OPEN_FILE;
442799ebb4caSwyllys 			goto end;
442899ebb4caSwyllys 		}
442999ebb4caSwyllys 
443034acef67Swyllys 		rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
44315b3e1433Swyllys 		    (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
443299ebb4caSwyllys 
443399ebb4caSwyllys 		if (rv  == KMF_OK)
443499ebb4caSwyllys 			/* Convert keys and certs to exportable format */
44355b3e1433Swyllys 			rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
443699ebb4caSwyllys 			    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,
444334acef67Swyllys 		    (uchar_t *)cred->cred, (uint32_t)cred->credlen,
44445b3e1433Swyllys 		    &pkey, &certdata, ncerts);
444571593db2Swyllys 
444671593db2Swyllys 		/* 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,
447471593db2Swyllys 			    keylist, nkeys, NULL, NULL);
447530a5e8faSwyllys 		}
44765b3e1433Swyllys 	}
447771593db2Swyllys end:
447830a5e8faSwyllys 	if (bio != NULL)
447999ebb4caSwyllys 		(void) BIO_free(bio);
448099ebb4caSwyllys 
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);
448730a5e8faSwyllys 
448899ebb4caSwyllys 	return (rv);
448999ebb4caSwyllys }
449099ebb4caSwyllys 
449199ebb4caSwyllys static KMF_RETURN
create_deskey(DES_cblock ** deskey)449299ebb4caSwyllys create_deskey(DES_cblock **deskey)
449399ebb4caSwyllys {
449499ebb4caSwyllys 	DES_cblock *key;
449599ebb4caSwyllys 
449699ebb4caSwyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
449799ebb4caSwyllys 	if (key == NULL) {
449899ebb4caSwyllys 		return (KMF_ERR_MEMORY);
449999ebb4caSwyllys 	}
450099ebb4caSwyllys 
450199ebb4caSwyllys 	if (DES_random_key(key) == 0) {
450299ebb4caSwyllys 		free(key);
450399ebb4caSwyllys 		return (KMF_ERR_KEYGEN_FAILED);
450499ebb4caSwyllys 	}
450599ebb4caSwyllys 
450699ebb4caSwyllys 	*deskey = key;
450799ebb4caSwyllys 	return (KMF_OK);
450899ebb4caSwyllys }
450999ebb4caSwyllys 
451099ebb4caSwyllys #define	KEYGEN_RETRY 3
451199ebb4caSwyllys #define	DES3_KEY_SIZE 24
451299ebb4caSwyllys 
451399ebb4caSwyllys static KMF_RETURN
create_des3key(unsigned char ** des3key)451499ebb4caSwyllys create_des3key(unsigned char **des3key)
451599ebb4caSwyllys {
451699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
451799ebb4caSwyllys 	DES_cblock *deskey1 = NULL;
451899ebb4caSwyllys 	DES_cblock *deskey2 = NULL;
451999ebb4caSwyllys 	DES_cblock *deskey3 = NULL;
452099ebb4caSwyllys 	unsigned char *newkey = NULL;
452199ebb4caSwyllys 	int retry;
452299ebb4caSwyllys 
452399ebb4caSwyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
452499ebb4caSwyllys 		return (KMF_ERR_MEMORY);
452599ebb4caSwyllys 	}
452699ebb4caSwyllys 
452799ebb4caSwyllys 	/* create the 1st DES key */
452899ebb4caSwyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
452999ebb4caSwyllys 		goto out;
453099ebb4caSwyllys 	}
453199ebb4caSwyllys 
453299ebb4caSwyllys 	/*
453399ebb4caSwyllys 	 * Create the 2nd DES key and make sure its value is different
453499ebb4caSwyllys 	 * from the 1st DES key.
453599ebb4caSwyllys 	 */
453699ebb4caSwyllys 	retry = 0;
453799ebb4caSwyllys 	do {
453899ebb4caSwyllys 		if (deskey2 != NULL) {
453999ebb4caSwyllys 			free(deskey2);
454099ebb4caSwyllys 			deskey2 = NULL;
454199ebb4caSwyllys 		}
454299ebb4caSwyllys 
454399ebb4caSwyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
454499ebb4caSwyllys 			goto out;
454599ebb4caSwyllys 		}
454699ebb4caSwyllys 
454799ebb4caSwyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
454899ebb4caSwyllys 		    == 0) {
454999ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
455099ebb4caSwyllys 			retry++;
455199ebb4caSwyllys 		}
455299ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
455399ebb4caSwyllys 
455499ebb4caSwyllys 	if (ret != KMF_OK) {
455599ebb4caSwyllys 		goto out;
455699ebb4caSwyllys 	}
455799ebb4caSwyllys 
455899ebb4caSwyllys 	/*
455999ebb4caSwyllys 	 * Create the 3rd DES key and make sure its value is different
456099ebb4caSwyllys 	 * from the 2nd DES key.
456199ebb4caSwyllys 	 */
456299ebb4caSwyllys 	retry = 0;
456399ebb4caSwyllys 	do {
456499ebb4caSwyllys 		if (deskey3 != NULL) {
456599ebb4caSwyllys 			free(deskey3);
456699ebb4caSwyllys 			deskey3 = NULL;
456799ebb4caSwyllys 		}
456899ebb4caSwyllys 
456999ebb4caSwyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
457099ebb4caSwyllys 			goto out;
457199ebb4caSwyllys 		}
457299ebb4caSwyllys 
457399ebb4caSwyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
457499ebb4caSwyllys 		    == 0) {
457599ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
457699ebb4caSwyllys 			retry++;
457799ebb4caSwyllys 		}
457899ebb4caSwyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
457999ebb4caSwyllys 
458099ebb4caSwyllys 	if (ret != KMF_OK) {
458199ebb4caSwyllys 		goto out;
458299ebb4caSwyllys 	}
458399ebb4caSwyllys 
458499ebb4caSwyllys 	/* Concatenate 3 DES keys into a DES3 key */
458599ebb4caSwyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
458699ebb4caSwyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
458799ebb4caSwyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
458899ebb4caSwyllys 	*des3key = newkey;
458999ebb4caSwyllys 
459099ebb4caSwyllys out:
459199ebb4caSwyllys 	if (deskey1 != NULL)
459299ebb4caSwyllys 		free(deskey1);
459399ebb4caSwyllys 
459499ebb4caSwyllys 	if (deskey2 != NULL)
459599ebb4caSwyllys 		free(deskey2);
459699ebb4caSwyllys 
459799ebb4caSwyllys 	if (deskey3 != NULL)
459899ebb4caSwyllys 		free(deskey3);
459999ebb4caSwyllys 
460099ebb4caSwyllys 	if (ret != KMF_OK && newkey != NULL)
460199ebb4caSwyllys 		free(newkey);
460299ebb4caSwyllys 
460399ebb4caSwyllys 	return (ret);
460499ebb4caSwyllys }
460599ebb4caSwyllys 
460699ebb4caSwyllys 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 {
460999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
461099ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
461199ebb4caSwyllys 	char *fullpath = NULL;
461299ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
461399ebb4caSwyllys 	DES_cblock *deskey = NULL;
461499ebb4caSwyllys 	unsigned char *des3key = NULL;
461599ebb4caSwyllys 	unsigned char *random = NULL;
461699ebb4caSwyllys 	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 
462499ebb4caSwyllys 	if (kmfh == NULL)
462599ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
462699ebb4caSwyllys 
462730a5e8faSwyllys 	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
462830a5e8faSwyllys 	if (symkey == NULL)
462999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
463099ebb4caSwyllys 
463130a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
463230a5e8faSwyllys 
463330a5e8faSwyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
463430a5e8faSwyllys 	if (keyfile == NULL)
463530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
463630a5e8faSwyllys 
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);
464130a5e8faSwyllys 
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);
465030a5e8faSwyllys 
465130a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
465299ebb4caSwyllys 	if (fullpath == NULL)
465399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
465499ebb4caSwyllys 
465599ebb4caSwyllys 	/* If the requested file exists, return an error */
465630a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
465799ebb4caSwyllys 		free(fullpath);
465899ebb4caSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
465999ebb4caSwyllys 	}
466099ebb4caSwyllys 
466199ebb4caSwyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
466299ebb4caSwyllys 	if (fd == -1) {
466399ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
466499ebb4caSwyllys 		goto out;
466599ebb4caSwyllys 	}
466699ebb4caSwyllys 
466799ebb4caSwyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
466899ebb4caSwyllys 	if (rkey == NULL) {
466999ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
467099ebb4caSwyllys 		goto out;
467199ebb4caSwyllys 	}
467299ebb4caSwyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
467399ebb4caSwyllys 
467430a5e8faSwyllys 	if (keytype == KMF_DES) {
467599ebb4caSwyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
467699ebb4caSwyllys 			goto out;
467799ebb4caSwyllys 		}
467899ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)deskey;
467999ebb4caSwyllys 		rkey->keydata.len = 8;
468099ebb4caSwyllys 
468199ebb4caSwyllys 		symkey->keyalg = KMF_DES;
468299ebb4caSwyllys 
468330a5e8faSwyllys 	} else if (keytype == KMF_DES3) {
468499ebb4caSwyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
468599ebb4caSwyllys 			goto out;
468699ebb4caSwyllys 		}
468799ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)des3key;
468899ebb4caSwyllys 		rkey->keydata.len = DES3_KEY_SIZE;
468999ebb4caSwyllys 		symkey->keyalg = KMF_DES3;
46909b37d296Swyllys 
469130a5e8faSwyllys 	} else if (keytype == KMF_AES || keytype == KMF_RC4 ||
469230a5e8faSwyllys 	    keytype == KMF_GENERIC_SECRET) {
469399ebb4caSwyllys 		int bytes;
469499ebb4caSwyllys 
469530a5e8faSwyllys 		if (keylen % 8 != 0) {
469699ebb4caSwyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
469799ebb4caSwyllys 			goto out;
469899ebb4caSwyllys 		}
469999ebb4caSwyllys 
470030a5e8faSwyllys 		if (keytype == KMF_AES) {
470130a5e8faSwyllys 			if (keylen != 128 &&
470230a5e8faSwyllys 			    keylen != 192 &&
470330a5e8faSwyllys 			    keylen != 256) {
470499ebb4caSwyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
470599ebb4caSwyllys 				goto out;
470699ebb4caSwyllys 			}
470799ebb4caSwyllys 		}
470899ebb4caSwyllys 
470930a5e8faSwyllys 		bytes = keylen/8;
471099ebb4caSwyllys 		random = malloc(bytes);
471199ebb4caSwyllys 		if (random == NULL) {
471299ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
471399ebb4caSwyllys 			goto out;
471499ebb4caSwyllys 		}
471599ebb4caSwyllys 		if (RAND_bytes(random, bytes) != 1) {
471699ebb4caSwyllys 			ret = KMF_ERR_KEYGEN_FAILED;
471799ebb4caSwyllys 			goto out;
471899ebb4caSwyllys 		}
471999ebb4caSwyllys 
472099ebb4caSwyllys 		rkey->keydata.val = (uchar_t *)random;
472199ebb4caSwyllys 		rkey->keydata.len = bytes;
472230a5e8faSwyllys 		symkey->keyalg = keytype;
472399ebb4caSwyllys 
472499ebb4caSwyllys 	} else {
472599ebb4caSwyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
472699ebb4caSwyllys 		goto out;
472799ebb4caSwyllys 	}
472899ebb4caSwyllys 
472999ebb4caSwyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
473099ebb4caSwyllys 
473199ebb4caSwyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
473299ebb4caSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
473399ebb4caSwyllys 	symkey->keylabel = (char *)fullpath;
473499ebb4caSwyllys 	symkey->israw = TRUE;
473599ebb4caSwyllys 	symkey->keyp = rkey;
473699ebb4caSwyllys 
473799ebb4caSwyllys out:
473899ebb4caSwyllys 	if (fd != -1)
473999ebb4caSwyllys 		(void) close(fd);
474099ebb4caSwyllys 
474199ebb4caSwyllys 	if (ret != KMF_OK && fullpath != NULL) {
474299ebb4caSwyllys 		free(fullpath);
474399ebb4caSwyllys 	}
474499ebb4caSwyllys 	if (ret != KMF_OK) {
474530a5e8faSwyllys 		kmf_free_raw_sym_key(rkey);
474699ebb4caSwyllys 		symkey->keyp = NULL;
474799ebb4caSwyllys 		symkey->keyalg = KMF_KEYALG_NONE;
474899ebb4caSwyllys 	}
474999ebb4caSwyllys 
475099ebb4caSwyllys 	return (ret);
475199ebb4caSwyllys }
475299ebb4caSwyllys 
475399ebb4caSwyllys /*
475499ebb4caSwyllys  * Check a file to see if it is a CRL file with PEM or DER format.
475599ebb4caSwyllys  * If success, return its format in the "pformat" argument.
475699ebb4caSwyllys  */
475799ebb4caSwyllys KMF_RETURN
OpenSSL_IsCRLFile(KMF_HANDLE_T handle,char * filename,int * pformat)475899ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
475999ebb4caSwyllys {
476099ebb4caSwyllys 	KMF_RETURN	ret = KMF_OK;
476199ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
476299ebb4caSwyllys 	BIO		*bio = NULL;
476399ebb4caSwyllys 	X509_CRL	*xcrl = NULL;
476499ebb4caSwyllys 
476599ebb4caSwyllys 	if (filename == NULL) {
476699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
476799ebb4caSwyllys 	}
476899ebb4caSwyllys 
476999ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
477099ebb4caSwyllys 	if (bio == NULL)	{
477199ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
477299ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
477399ebb4caSwyllys 		goto out;
477499ebb4caSwyllys 	}
477599ebb4caSwyllys 
477699ebb4caSwyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
477799ebb4caSwyllys 		*pformat = KMF_FORMAT_PEM;
477899ebb4caSwyllys 		goto out;
477999ebb4caSwyllys 	}
478099ebb4caSwyllys 	(void) BIO_free(bio);
478199ebb4caSwyllys 
478299ebb4caSwyllys 	/*
478399ebb4caSwyllys 	 * Now try to read it as raw DER data.
478499ebb4caSwyllys 	 */
478599ebb4caSwyllys 	bio = BIO_new_file(filename, "rb");
478699ebb4caSwyllys 	if (bio == NULL)	{
478799ebb4caSwyllys 		SET_ERROR(kmfh, ERR_get_error());
478899ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
478999ebb4caSwyllys 		goto out;
479099ebb4caSwyllys 	}
479199ebb4caSwyllys 
479299ebb4caSwyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
479399ebb4caSwyllys 		*pformat = KMF_FORMAT_ASN1;
479499ebb4caSwyllys 	} else {
479599ebb4caSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
479699ebb4caSwyllys 	}
479799ebb4caSwyllys 
479899ebb4caSwyllys out:
479999ebb4caSwyllys 	if (bio != NULL)
480099ebb4caSwyllys 		(void) BIO_free(bio);
480199ebb4caSwyllys 
480299ebb4caSwyllys 	if (xcrl != NULL)
480399ebb4caSwyllys 		X509_CRL_free(xcrl);
480499ebb4caSwyllys 
480599ebb4caSwyllys 	return (ret);
480699ebb4caSwyllys }
480799ebb4caSwyllys 
480899ebb4caSwyllys KMF_RETURN
OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle,KMF_KEY_HANDLE * symkey,KMF_RAW_SYM_KEY * rkey)480999ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
481099ebb4caSwyllys     KMF_RAW_SYM_KEY *rkey)
481199ebb4caSwyllys {
481299ebb4caSwyllys 	KMF_RETURN	rv = KMF_OK;
481399ebb4caSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
481499ebb4caSwyllys 	KMF_DATA	keyvalue;
481599ebb4caSwyllys 
481699ebb4caSwyllys 	if (kmfh == NULL)
481799ebb4caSwyllys 		return (KMF_ERR_UNINITIALIZED);
481899ebb4caSwyllys 
481999ebb4caSwyllys 	if (symkey == NULL || rkey == NULL)
482099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
482199ebb4caSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
482299ebb4caSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
482399ebb4caSwyllys 
482499ebb4caSwyllys 	if (symkey->israw) {
482599ebb4caSwyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
482699ebb4caSwyllys 
482799ebb4caSwyllys 		if (rawkey == NULL ||
482899ebb4caSwyllys 		    rawkey->keydata.val == NULL ||
482999ebb4caSwyllys 		    rawkey->keydata.len == 0)
483099ebb4caSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
483199ebb4caSwyllys 
483299ebb4caSwyllys 		rkey->keydata.len = rawkey->keydata.len;
483399ebb4caSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
483499ebb4caSwyllys 			return (KMF_ERR_MEMORY);
483599ebb4caSwyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
483699ebb4caSwyllys 		    rkey->keydata.len);
483799ebb4caSwyllys 	} else {
483830a5e8faSwyllys 		rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
483999ebb4caSwyllys 		if (rv != KMF_OK)
484099ebb4caSwyllys 			return (rv);
484199ebb4caSwyllys 		rkey->keydata.len = keyvalue.Length;
484299ebb4caSwyllys 		rkey->keydata.val = keyvalue.Data;
484399ebb4caSwyllys 	}
484499ebb4caSwyllys 
484599ebb4caSwyllys 	return (rv);
484699ebb4caSwyllys }
484702744e81Swyllys 
484802744e81Swyllys /*
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)
485630a5e8faSwyllys {
485730a5e8faSwyllys 	int fd;
485830a5e8faSwyllys 
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);
486830a5e8faSwyllys 
486930a5e8faSwyllys 	/* The file did NOT exist.  Delete the testcase. */
487030a5e8faSwyllys 	(void) close(fd);
487130a5e8faSwyllys 	(void) unlink(filename);
487230a5e8faSwyllys 	return (0);
487330a5e8faSwyllys }
487430a5e8faSwyllys 
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)
487730a5e8faSwyllys {
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;
488430a5e8faSwyllys 	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;
489030a5e8faSwyllys 
489130a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
489230a5e8faSwyllys 	if (pubkey != NULL)
489330a5e8faSwyllys 		keys++;
489430a5e8faSwyllys 
489530a5e8faSwyllys 	prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
489630a5e8faSwyllys 	if (prikey != NULL)
489730a5e8faSwyllys 		keys++;
489830a5e8faSwyllys 
489930a5e8faSwyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
490030a5e8faSwyllys 	if (rawkey != NULL)
490130a5e8faSwyllys 		keys++;
490230a5e8faSwyllys 
490330a5e8faSwyllys 	/*
490430a5e8faSwyllys 	 * Exactly 1 type of key must be passed to this function.
490530a5e8faSwyllys 	 */
490630a5e8faSwyllys 	if (keys != 1)
490730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
490830a5e8faSwyllys 
490930a5e8faSwyllys 	keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
491030a5e8faSwyllys 	    numattr);
491130a5e8faSwyllys 	if (keyfile == NULL)
491230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
491330a5e8faSwyllys 
491430a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
491530a5e8faSwyllys 
491630a5e8faSwyllys 	fullpath = get_fullpath(dirpath, keyfile);
491730a5e8faSwyllys 
491830a5e8faSwyllys 	/* Once we have the full path, we don't need the pieces */
491930a5e8faSwyllys 	if (fullpath == NULL)
492030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
492130a5e8faSwyllys 
492230a5e8faSwyllys 	/* If the requested file exists, return an error */
492330a5e8faSwyllys 	if (test_for_file(fullpath, 0400) == 1) {
492430a5e8faSwyllys 		free(fullpath);
492530a5e8faSwyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
492630a5e8faSwyllys 	}
492730a5e8faSwyllys 
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;
493330a5e8faSwyllys 
493430a5e8faSwyllys 	/* CRED is not required for OpenSSL files */
493530a5e8faSwyllys 	(void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
493630a5e8faSwyllys 	    &cred, NULL);
493730a5e8faSwyllys 
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 	}
494530a5e8faSwyllys 
494630a5e8faSwyllys 	if (prikey != NULL && prikey->keyp != NULL) {
494730a5e8faSwyllys 		if (prikey->keyalg == KMF_RSA ||
494830a5e8faSwyllys 		    prikey->keyalg == KMF_DSA) {
494930a5e8faSwyllys 			pkey = (EVP_PKEY *)prikey->keyp;
495030a5e8faSwyllys 
495130a5e8faSwyllys 			rv = ssl_write_key(kmfh, format,
495230a5e8faSwyllys 			    out, &cred, pkey, TRUE);
495330a5e8faSwyllys 
495430a5e8faSwyllys 			if (rv == KMF_OK && prikey->keylabel == NULL) {
495530a5e8faSwyllys 				prikey->keylabel = strdup(fullpath);
495630a5e8faSwyllys 				if (prikey->keylabel == NULL)
495730a5e8faSwyllys 					rv = KMF_ERR_MEMORY;
495830a5e8faSwyllys 			}
495930a5e8faSwyllys 		}
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;
496430a5e8faSwyllys 
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 			}
497330a5e8faSwyllys 		}
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;
498130a5e8faSwyllys 		}
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 	}
499430a5e8faSwyllys 
499530a5e8faSwyllys end:
499630a5e8faSwyllys 
499730a5e8faSwyllys 	if (out)
499830a5e8faSwyllys 		(void) BIO_free(out);
499930a5e8faSwyllys 
50005b3e1433Swyllys 
500130a5e8faSwyllys 	if (rv == KMF_OK)
500230a5e8faSwyllys 		(void) chmod(fullpath, 0400);
500330a5e8faSwyllys 
500430a5e8faSwyllys 	free(fullpath);
500530a5e8faSwyllys 	return (rv);
500630a5e8faSwyllys }
500730a5e8faSwyllys 
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;
502230a5e8faSwyllys 
502330a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
502430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
502530a5e8faSwyllys 	}
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);
503430a5e8faSwyllys 	}
503530a5e8faSwyllys 
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);
503930a5e8faSwyllys 
504030a5e8faSwyllys 	crlfile = get_fullpath(dirpath, incrl);
504130a5e8faSwyllys 
504230a5e8faSwyllys 	if (crlfile == NULL)
504330a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
504430a5e8faSwyllys 
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);
505230a5e8faSwyllys 	}
505330a5e8faSwyllys 
505430a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
505530a5e8faSwyllys 	if (ret != KMF_OK) {
505630a5e8faSwyllys 		free(outcrlfile);
505730a5e8faSwyllys 		return (ret);
505830a5e8faSwyllys 	}
505930a5e8faSwyllys 
506030a5e8faSwyllys 	in = BIO_new_file(crlfile, "rb");
506130a5e8faSwyllys 	if (in == NULL)	{
506230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
506330a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
506430a5e8faSwyllys 		goto end;
506530a5e8faSwyllys 	}
506630a5e8faSwyllys 
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);
507130a5e8faSwyllys 	}
507230a5e8faSwyllys 
507330a5e8faSwyllys 	if (xcrl == NULL) {
507430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
507530a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
507630a5e8faSwyllys 		goto end;
507730a5e8faSwyllys 	}
507830a5e8faSwyllys 
507930a5e8faSwyllys 	/* If bypasscheck is specified, no need to verify. */
508030a5e8faSwyllys 	if (crlcheck == B_FALSE)
508130a5e8faSwyllys 		goto output;
508230a5e8faSwyllys 
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) {
508930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
509030a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
509130a5e8faSwyllys 		goto end;
509230a5e8faSwyllys 	}
509330a5e8faSwyllys 
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) {
510430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
510530a5e8faSwyllys 		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;
511430a5e8faSwyllys 	}
511530a5e8faSwyllys 
511630a5e8faSwyllys 	/* Verify the CRL with the CA's public key */
511730a5e8faSwyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
511830a5e8faSwyllys 	EVP_PKEY_free(pkey);
511930a5e8faSwyllys 	if (openssl_ret > 0) {
512030a5e8faSwyllys 		ret = KMF_OK;  /* verify succeed */
512130a5e8faSwyllys 	} else {
512230a5e8faSwyllys 		SET_ERROR(kmfh, openssl_ret);
512330a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
512430a5e8faSwyllys 	}
512530a5e8faSwyllys 
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 	}
514030a5e8faSwyllys 
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:
515830a5e8faSwyllys 	if (xcrl != NULL)
515930a5e8faSwyllys 		X509_CRL_free(xcrl);
516030a5e8faSwyllys 
516130a5e8faSwyllys 	if (xcert != NULL)
516230a5e8faSwyllys 		X509_free(xcert);
516330a5e8faSwyllys 
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);
517230a5e8faSwyllys 
517330a5e8faSwyllys 	return (ret);
517430a5e8faSwyllys }
517530a5e8faSwyllys 
517630a5e8faSwyllys 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)
517830a5e8faSwyllys {
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;
519130a5e8faSwyllys 
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);
520230a5e8faSwyllys 
520330a5e8faSwyllys 	if (crldata == NULL)
520430a5e8faSwyllys 		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);
521630a5e8faSwyllys 	}
521730a5e8faSwyllys 
521830a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
521930a5e8faSwyllys 	if (ret != KMF_OK) {
522030a5e8faSwyllys 		free(crlfile);
522130a5e8faSwyllys 		return (ret);
522230a5e8faSwyllys 	}
522330a5e8faSwyllys 
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)	{
522930a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
523030a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
523130a5e8faSwyllys 		goto end;
523230a5e8faSwyllys 	}
523330a5e8faSwyllys 
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);
523830a5e8faSwyllys 	}
523930a5e8faSwyllys 
524030a5e8faSwyllys 	if (x == NULL) { /* should not happen */
524130a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
524230a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
524330a5e8faSwyllys 		goto end;
524430a5e8faSwyllys 	}
524530a5e8faSwyllys 
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;
525930a5e8faSwyllys 	}
526030a5e8faSwyllys 
526130a5e8faSwyllys 	data = malloc(len + 1);
526230a5e8faSwyllys 	if (data == NULL) {
526330a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
526430a5e8faSwyllys 		goto end;
526530a5e8faSwyllys 	}
526630a5e8faSwyllys 
526730a5e8faSwyllys 	(void) memcpy(data, memptr, len);
526830a5e8faSwyllys 	data[len] = '\0';
526930a5e8faSwyllys 	*crldata = data;
527030a5e8faSwyllys 
527130a5e8faSwyllys end:
527230a5e8faSwyllys 	if (x != NULL)
527330a5e8faSwyllys 		X509_CRL_free(x);
527430a5e8faSwyllys 
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);
528330a5e8faSwyllys 
528430a5e8faSwyllys 	return (ret);
528530a5e8faSwyllys }
528630a5e8faSwyllys 
528730a5e8faSwyllys 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)
528930a5e8faSwyllys {
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;
529630a5e8faSwyllys 
529730a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
529830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
529930a5e8faSwyllys 	}
530030a5e8faSwyllys 
530130a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
530230a5e8faSwyllys 	    attrlist, numattr);
530330a5e8faSwyllys 
530430a5e8faSwyllys 	if (crlfilename == NULL)
530530a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
530630a5e8faSwyllys 
530730a5e8faSwyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
530830a5e8faSwyllys 
530930a5e8faSwyllys 	crlfile = get_fullpath(dirpath, crlfilename);
531030a5e8faSwyllys 
531130a5e8faSwyllys 	if (crlfile == NULL)
531230a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
531330a5e8faSwyllys 
531430a5e8faSwyllys 	if (isdir(crlfile)) {
531530a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
531630a5e8faSwyllys 		goto end;
531730a5e8faSwyllys 	}
531830a5e8faSwyllys 
531930a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
532030a5e8faSwyllys 	if (ret != KMF_OK)
532130a5e8faSwyllys 		goto end;
532230a5e8faSwyllys 
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);
533430a5e8faSwyllys 
533530a5e8faSwyllys 	return (ret);
533630a5e8faSwyllys }
533730a5e8faSwyllys 
533830a5e8faSwyllys 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)
534030a5e8faSwyllys {
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;
535130a5e8faSwyllys 
535230a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
535330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
535430a5e8faSwyllys 	}
535530a5e8faSwyllys 
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);
537930a5e8faSwyllys 	if (ret != KMF_OK)
538030a5e8faSwyllys 		goto end;
538130a5e8faSwyllys 
538230a5e8faSwyllys 	/* Read the CRL file and load it into a X509_CRL structure */
538330a5e8faSwyllys 	in = BIO_new_file(crlfilename, "rb");
538430a5e8faSwyllys 	if (in == NULL)	{
538530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
538630a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
538730a5e8faSwyllys 		goto end;
538830a5e8faSwyllys 	}
538930a5e8faSwyllys 
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);
539430a5e8faSwyllys 	}
539530a5e8faSwyllys 
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);
540230a5e8faSwyllys 
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;
540730a5e8faSwyllys 
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 	}
541430a5e8faSwyllys 
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 	}
542030a5e8faSwyllys 
542130a5e8faSwyllys 	if (xcert == NULL) {
542230a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
542330a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
542430a5e8faSwyllys 		goto end;
542530a5e8faSwyllys 	}
542630a5e8faSwyllys 
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 	}
543330a5e8faSwyllys 
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 	}
544230a5e8faSwyllys 
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 	}
545030a5e8faSwyllys 
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 }
546730a5e8faSwyllys 
546830a5e8faSwyllys 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)
547030a5e8faSwyllys {
547130a5e8faSwyllys 	KMF_RETURN	ret = KMF_OK;
547230a5e8faSwyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
547330a5e8faSwyllys 	BIO		*bcrl = NULL;
547430a5e8faSwyllys 	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;
548130a5e8faSwyllys 
548230a5e8faSwyllys 	if (handle == NULL || crlname == NULL || tacert == NULL) {
548330a5e8faSwyllys 		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);
551530a5e8faSwyllys 
551630a5e8faSwyllys 	if (xcert == NULL) {
551730a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
551830a5e8faSwyllys 		ret = KMF_ERR_BAD_CERTFILE;
551930a5e8faSwyllys 		goto cleanup;
552030a5e8faSwyllys 	}
552130a5e8faSwyllys 
552230a5e8faSwyllys 	/* Get issuer certificate public key */
552330a5e8faSwyllys 	pkey = X509_get_pubkey(xcert);
552430a5e8faSwyllys 	if (pkey == NULL) {
552530a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
552630a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
552730a5e8faSwyllys 		goto cleanup;
552830a5e8faSwyllys 	}
552930a5e8faSwyllys 
553030a5e8faSwyllys 	/* Verify CRL signature */
553130a5e8faSwyllys 	sslret = X509_CRL_verify(xcrl, pkey);
553230a5e8faSwyllys 	EVP_PKEY_free(pkey);
553330a5e8faSwyllys 	if (sslret > 0) {
553430a5e8faSwyllys 		ret = KMF_OK;
553530a5e8faSwyllys 	} else {
553630a5e8faSwyllys 		SET_ERROR(kmfh, sslret);
553730a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
553830a5e8faSwyllys 	}
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;
556130a5e8faSwyllys 	X509_CRL	*xcrl = NULL;
556230a5e8faSwyllys 	int		i;
556330a5e8faSwyllys 
556430a5e8faSwyllys 	if (handle == NULL || crlname == NULL) {
556530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
556630a5e8faSwyllys 	}
556730a5e8faSwyllys 
556830a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlname, &crl_format);
556930a5e8faSwyllys 	if (ret != KMF_OK)
557030a5e8faSwyllys 		return (ret);
557130a5e8faSwyllys 
557230a5e8faSwyllys 	bcrl = BIO_new_file(crlname, "rb");
557330a5e8faSwyllys 	if (bcrl == NULL) {
557430a5e8faSwyllys 		SET_ERROR(kmfh, ERR_get_error());
557530a5e8faSwyllys 		ret = KMF_ERR_OPEN_FILE;
557630a5e8faSwyllys 		goto cleanup;
557730a5e8faSwyllys 	}
557830a5e8faSwyllys 
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);
558330a5e8faSwyllys 
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);
559630a5e8faSwyllys 
559730a5e8faSwyllys 		if (i <= 0) {
559830a5e8faSwyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
559930a5e8faSwyllys 			goto cleanup;
560030a5e8faSwyllys 		}
560130a5e8faSwyllys 	}
560230a5e8faSwyllys 
560330a5e8faSwyllys 	ret = KMF_OK;
560430a5e8faSwyllys 
560530a5e8faSwyllys cleanup:
560630a5e8faSwyllys 	if (bcrl != NULL)
560730a5e8faSwyllys 		(void) BIO_free(bcrl);
560830a5e8faSwyllys 
560930a5e8faSwyllys 	if (xcrl != NULL)
561030a5e8faSwyllys 		X509_CRL_free(xcrl);
561130a5e8faSwyllys 
561230a5e8faSwyllys 	return (ret);
561330a5e8faSwyllys }
5614