13089Swyllys /*
2*12234Swyllys.ingersoll@sun.com  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
3*12234Swyllys.ingersoll@sun.com  *
43089Swyllys  * Use is subject to license terms.
53089Swyllys  */
63433Shaimay /*
73433Shaimay  * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
83433Shaimay  * project 2000.
93433Shaimay  */
103433Shaimay /*
113433Shaimay  * ====================================================================
123433Shaimay  * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
133433Shaimay  *
143433Shaimay  * Redistribution and use in source and binary forms, with or without
153433Shaimay  * modification, are permitted provided that the following conditions
163433Shaimay  * are met:
173433Shaimay  *
183433Shaimay  * 1. Redistributions of source code must retain the above copyright
193433Shaimay  *    notice, this list of conditions and the following disclaimer.
203433Shaimay  *
213433Shaimay  * 2. Redistributions in binary form must reproduce the above copyright
223433Shaimay  *    notice, this list of conditions and the following disclaimer in
233433Shaimay  *    the documentation and/or other materials provided with the
243433Shaimay  *    distribution.
253433Shaimay  *
263433Shaimay  * 3. All advertising materials mentioning features or use of this
273433Shaimay  *    software must display the following acknowledgment:
283433Shaimay  *    "This product includes software developed by the OpenSSL Project
293433Shaimay  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
303433Shaimay  *
313433Shaimay  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
323433Shaimay  *    endorse or promote products derived from this software without
333433Shaimay  *    prior written permission. For written permission, please contact
343433Shaimay  *    licensing@OpenSSL.org.
353433Shaimay  *
363433Shaimay  * 5. Products derived from this software may not be called "OpenSSL"
373433Shaimay  *    nor may "OpenSSL" appear in their names without prior written
383433Shaimay  *    permission of the OpenSSL Project.
393433Shaimay  *
403433Shaimay  * 6. Redistributions of any form whatsoever must retain the following
413433Shaimay  *    acknowledgment:
423433Shaimay  *    "This product includes software developed by the OpenSSL Project
433433Shaimay  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
443433Shaimay  *
453433Shaimay  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
463433Shaimay  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
473433Shaimay  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
483433Shaimay  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
493433Shaimay  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
503433Shaimay  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
513433Shaimay  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
523433Shaimay  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
533433Shaimay  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
543433Shaimay  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
553433Shaimay  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
563433Shaimay  * OF THE POSSIBILITY OF SUCH DAMAGE.
573433Shaimay  * ====================================================================
583433Shaimay  *
593433Shaimay  * This product includes cryptographic software written by Eric Young
603433Shaimay  * (eay@cryptsoft.com).  This product includes software written by Tim
613433Shaimay  * Hudson (tjh@cryptsoft.com).
623433Shaimay  *
633433Shaimay  */
643089Swyllys 
653408Swyllys #include <stdlib.h>
663089Swyllys #include <kmfapiP.h>
673089Swyllys #include <ber_der.h>
683089Swyllys #include <fcntl.h>
693089Swyllys #include <sys/stat.h>
703089Swyllys #include <dirent.h>
713089Swyllys #include <cryptoutil.h>
723089Swyllys #include <synch.h>
733089Swyllys #include <thread.h>
743089Swyllys 
753089Swyllys /* OPENSSL related headers */
763089Swyllys #include <openssl/bio.h>
773089Swyllys #include <openssl/bn.h>
783089Swyllys #include <openssl/asn1.h>
793089Swyllys #include <openssl/err.h>
803089Swyllys #include <openssl/bn.h>
813089Swyllys #include <openssl/x509.h>
823089Swyllys #include <openssl/rsa.h>
833089Swyllys #include <openssl/dsa.h>
843089Swyllys #include <openssl/x509v3.h>
853089Swyllys #include <openssl/objects.h>
863089Swyllys #include <openssl/pem.h>
873089Swyllys #include <openssl/pkcs12.h>
883089Swyllys #include <openssl/ocsp.h>
893089Swyllys #include <openssl/des.h>
903089Swyllys #include <openssl/rand.h>
913089Swyllys 
923089Swyllys #define	PRINT_ANY_EXTENSION (\
933089Swyllys 	KMF_X509_EXT_KEY_USAGE |\
943089Swyllys 	KMF_X509_EXT_CERT_POLICIES |\
953089Swyllys 	KMF_X509_EXT_SUBJALTNAME |\
963089Swyllys 	KMF_X509_EXT_BASIC_CONSTRAINTS |\
973089Swyllys 	KMF_X509_EXT_NAME_CONSTRAINTS |\
983089Swyllys 	KMF_X509_EXT_POLICY_CONSTRAINTS |\
993089Swyllys 	KMF_X509_EXT_EXT_KEY_USAGE |\
1003089Swyllys 	KMF_X509_EXT_INHIBIT_ANY_POLICY |\
1013089Swyllys 	KMF_X509_EXT_AUTH_KEY_ID |\
1023089Swyllys 	KMF_X509_EXT_SUBJ_KEY_ID |\
1033089Swyllys 	KMF_X509_EXT_POLICY_MAPPING)
1043089Swyllys 
1053089Swyllys static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
1063089Swyllys 	0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
1073089Swyllys 	0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
1083089Swyllys 	0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
1093089Swyllys 	0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
1103089Swyllys 	0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
1113089Swyllys 	0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
1123089Swyllys 	0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
1133089Swyllys 	0x91 };
1143089Swyllys 
1153089Swyllys static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
1163089Swyllys 	0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
1173089Swyllys 	0x8e, 0xda, 0xce, 0x91, 0x5f };
1183089Swyllys 
1193089Swyllys static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
1203089Swyllys 	0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
1213089Swyllys 	0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
1223089Swyllys 	0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
1233089Swyllys 	0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
1243089Swyllys 	0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
1253089Swyllys 	0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
1263089Swyllys 	0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
1273089Swyllys 	0x02 };
1283089Swyllys 
1293089Swyllys #define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
1303089Swyllys 	h->lasterr.errcode = c;
1313089Swyllys 
1323089Swyllys #define	SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
1333089Swyllys 
1345536Swyllys /*
1355536Swyllys  * Declare some new macros for managing stacks of EVP_PKEYS, similar to
1365536Swyllys  * what wanboot did.
1375536Swyllys  */
1385536Swyllys DECLARE_STACK_OF(EVP_PKEY)
1395536Swyllys 
1405536Swyllys #define	sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
1415536Swyllys #define	sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
1425536Swyllys #define	sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
1435536Swyllys #define	sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
1445536Swyllys #define	sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
1455536Swyllys #define	sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
1465536Swyllys 	(free_func))
1475536Swyllys 
1483089Swyllys mutex_t init_lock = DEFAULTMUTEX;
1493089Swyllys static int ssl_initialized = 0;
1505051Swyllys static BIO *bio_err = NULL;
1515051Swyllys 
1525051Swyllys static int
1535051Swyllys test_for_file(char *, mode_t);
1545536Swyllys static KMF_RETURN
1555536Swyllys openssl_parse_bag(PKCS12_SAFEBAG *, char *, int,
1565536Swyllys     STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
1575536Swyllys 
1585536Swyllys static KMF_RETURN
1595536Swyllys local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *,
1605536Swyllys     int, KMF_KEY_HANDLE *, char *);
1615536Swyllys 
1625536Swyllys static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int);
1633089Swyllys 
1643408Swyllys static KMF_RETURN
1655051Swyllys extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *,
1665051Swyllys     CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
1673408Swyllys 
1683408Swyllys static KMF_RETURN
1695051Swyllys kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
1705051Swyllys     char *, KMF_DATA *);
1715051Swyllys 
1725051Swyllys static KMF_RETURN
1735051Swyllys load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
1745051Swyllys     char *, KMF_DATA **, uint32_t *);
1753408Swyllys 
1763754Swyllys static KMF_RETURN
1773754Swyllys sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
1783754Swyllys 
1793754Swyllys static EVP_PKEY *
1803754Swyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *);
1813754Swyllys 
1825051Swyllys static KMF_RETURN
1835051Swyllys convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
1845051Swyllys 
1853089Swyllys KMF_RETURN
1865051Swyllys OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
1873089Swyllys 
1883089Swyllys void
1893089Swyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
1903089Swyllys 
1913089Swyllys KMF_RETURN
1925051Swyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
1933089Swyllys 
1943089Swyllys KMF_RETURN
1955051Swyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
1963089Swyllys 
1973089Swyllys KMF_RETURN
1985051Swyllys OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
1995051Swyllys 
2005051Swyllys KMF_RETURN
2015051Swyllys OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2023089Swyllys 
2033089Swyllys KMF_RETURN
2043089Swyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T,  KMF_KEY_HANDLE *, KMF_DATA *);
2053089Swyllys 
2063089Swyllys KMF_RETURN
2073089Swyllys OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
2083089Swyllys 	KMF_DATA *, KMF_DATA *);
2093089Swyllys 
2103089Swyllys KMF_RETURN
2115051Swyllys OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2123089Swyllys 
2133089Swyllys KMF_RETURN
2145051Swyllys OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2153089Swyllys 
2163089Swyllys KMF_RETURN
2175051Swyllys OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2183089Swyllys 
2193089Swyllys KMF_RETURN
2205051Swyllys OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2213089Swyllys 
2223089Swyllys KMF_RETURN
2235051Swyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2243089Swyllys 
2253089Swyllys KMF_RETURN
2263089Swyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
2273089Swyllys 	KMF_PRINTABLE_ITEM, char *);
2283089Swyllys 
2293089Swyllys KMF_RETURN
2303089Swyllys OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
2313089Swyllys 
2323089Swyllys KMF_RETURN
2335051Swyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2343089Swyllys 
2353089Swyllys KMF_RETURN
2363089Swyllys OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
2373089Swyllys 	KMF_DATA *, KMF_DATA *);
2383089Swyllys 
2393089Swyllys KMF_RETURN
2405051Swyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2413089Swyllys 
2423089Swyllys KMF_RETURN
2435051Swyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2443089Swyllys 
2453089Swyllys KMF_RETURN
2465051Swyllys OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2473089Swyllys 
2483089Swyllys KMF_RETURN
2495051Swyllys OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2503089Swyllys 
2513089Swyllys KMF_RETURN
2525051Swyllys OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2533089Swyllys 
2543089Swyllys KMF_RETURN
2553089Swyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
2563089Swyllys 
2573089Swyllys KMF_RETURN
2585051Swyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
2593089Swyllys 
2603089Swyllys KMF_RETURN
2615051Swyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
2623089Swyllys 
2633089Swyllys static
2643089Swyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table =
2653089Swyllys {
2663089Swyllys 	1,				/* Version */
2673089Swyllys 	NULL, /* ConfigureKeystore */
2683089Swyllys 	OpenSSL_FindCert,
2693089Swyllys 	OpenSSL_FreeKMFCert,
2703089Swyllys 	OpenSSL_StoreCert,
2713089Swyllys 	NULL, /* ImportCert */
2723089Swyllys 	OpenSSL_ImportCRL,
2733089Swyllys 	OpenSSL_DeleteCert,
2743089Swyllys 	OpenSSL_DeleteCRL,
2753089Swyllys 	OpenSSL_CreateKeypair,
2763089Swyllys 	OpenSSL_FindKey,
2773089Swyllys 	OpenSSL_EncodePubKeyData,
2783089Swyllys 	OpenSSL_SignData,
2793089Swyllys 	OpenSSL_DeleteKey,
2803089Swyllys 	OpenSSL_ListCRL,
2813089Swyllys 	NULL,	/* FindCRL */
2823089Swyllys 	OpenSSL_FindCertInCRL,
2833089Swyllys 	OpenSSL_GetErrorString,
2845051Swyllys 	OpenSSL_FindPrikeyByCert,
2853089Swyllys 	OpenSSL_DecryptData,
2865051Swyllys 	OpenSSL_ExportPK12,
2873089Swyllys 	OpenSSL_CreateSymKey,
2883089Swyllys 	OpenSSL_GetSymKeyValue,
2893089Swyllys 	NULL,	/* SetTokenPin */
2905051Swyllys 	OpenSSL_StoreKey,
2913089Swyllys 	NULL	/* Finalize */
2923089Swyllys };
2933089Swyllys 
2943089Swyllys static mutex_t *lock_cs;
2953089Swyllys static long *lock_count;
2963089Swyllys 
2973089Swyllys static void
29811673Sopensolaris@drydog.com /* ARGSUSED1 */
locking_cb(int mode,int type,char * file,int line)2993089Swyllys locking_cb(int mode, int type, char *file, int line)
3003089Swyllys {
3013089Swyllys 	if (mode & CRYPTO_LOCK) {
3023089Swyllys 		(void) mutex_lock(&(lock_cs[type]));
3033089Swyllys 		lock_count[type]++;
3043089Swyllys 	} else {
3053089Swyllys 		(void) mutex_unlock(&(lock_cs[type]));
3063089Swyllys 	}
3073089Swyllys }
3083089Swyllys 
3093089Swyllys static unsigned long
thread_id()3103089Swyllys thread_id()
3113089Swyllys {
3123089Swyllys 	return ((unsigned long)thr_self());
3133089Swyllys }
3143089Swyllys 
3153089Swyllys KMF_PLUGIN_FUNCLIST *
KMF_Plugin_Initialize()3163089Swyllys KMF_Plugin_Initialize()
3173089Swyllys {
3183089Swyllys 	int i;
3193089Swyllys 
3203089Swyllys 	(void) mutex_lock(&init_lock);
3213089Swyllys 	if (!ssl_initialized) {
3223089Swyllys 		/*
3233089Swyllys 		 * Add support for extension OIDs that are not yet in the
3243089Swyllys 		 * openssl default set.
3253089Swyllys 		 */
3263089Swyllys 		(void) OBJ_create("2.5.29.30", "nameConstraints",
3274315Swyllys 		    "X509v3 Name Constraints");
3283089Swyllys 		(void) OBJ_create("2.5.29.33", "policyMappings",
3294315Swyllys 		    "X509v3 Policy Mappings");
3303089Swyllys 		(void) OBJ_create("2.5.29.36", "policyConstraints",
3314315Swyllys 		    "X509v3 Policy Constraints");
3323089Swyllys 		(void) OBJ_create("2.5.29.46", "freshestCRL",
3334315Swyllys 		    "X509v3 Freshest CRL");
3343089Swyllys 		(void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
3354315Swyllys 		    "X509v3 Inhibit Any-Policy");
3363089Swyllys 		/*
3373089Swyllys 		 * Set up for thread-safe operation.
3383089Swyllys 		 */
3393089Swyllys 		lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
3403089Swyllys 		if (lock_cs == NULL) {
3413089Swyllys 			(void) mutex_unlock(&init_lock);
3423089Swyllys 			return (NULL);
3433089Swyllys 		}
3443089Swyllys 
3453089Swyllys 		lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
3463089Swyllys 		if (lock_count == NULL) {
3473089Swyllys 			OPENSSL_free(lock_cs);
3483089Swyllys 			(void) mutex_unlock(&init_lock);
3493089Swyllys 			return (NULL);
3503089Swyllys 		}
3513089Swyllys 
3523089Swyllys 		for (i = 0; i < CRYPTO_num_locks(); i++) {
3533089Swyllys 			lock_count[i] = 0;
3543089Swyllys 			(void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
3553089Swyllys 		}
3563089Swyllys 
3573089Swyllys 		CRYPTO_set_id_callback((unsigned long (*)())thread_id);
358*12234Swyllys.ingersoll@sun.com 		if (CRYPTO_get_locking_callback() == NULL)
359*12234Swyllys.ingersoll@sun.com 			CRYPTO_set_locking_callback((void (*)())locking_cb);
360*12234Swyllys.ingersoll@sun.com 
361*12234Swyllys.ingersoll@sun.com 		OpenSSL_add_all_algorithms();
362*12234Swyllys.ingersoll@sun.com 
363*12234Swyllys.ingersoll@sun.com 		/* Enable error strings for reporting */
364*12234Swyllys.ingersoll@sun.com 		ERR_load_crypto_strings();
365*12234Swyllys.ingersoll@sun.com 
3663089Swyllys 		ssl_initialized = 1;
3673089Swyllys 	}
3683089Swyllys 	(void) mutex_unlock(&init_lock);
3693089Swyllys 
3703089Swyllys 	return (&openssl_plugin_table);
3713089Swyllys }
3723089Swyllys /*
3733089Swyllys  * Convert an SSL DN to a KMF DN.
3743089Swyllys  */
3753089Swyllys static KMF_RETURN
get_x509_dn(X509_NAME * sslDN,KMF_X509_NAME * kmfDN)3763089Swyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
3773089Swyllys {
3783089Swyllys 	KMF_DATA derdata;
3793089Swyllys 	KMF_RETURN rv = KMF_OK;
3803089Swyllys 	uchar_t *tmp;
3813089Swyllys 
3823089Swyllys 	/* Convert to raw DER format */
3833089Swyllys 	derdata.Length = i2d_X509_NAME(sslDN, NULL);
3843089Swyllys 	if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
3854315Swyllys 	    == NULL) {
3863089Swyllys 		return (KMF_ERR_MEMORY);
3873089Swyllys 	}
3883089Swyllys 	(void) i2d_X509_NAME(sslDN, &tmp);
3893089Swyllys 
3903089Swyllys 	/* Decode to KMF format */
3913089Swyllys 	rv = DerDecodeName(&derdata, kmfDN);
3923089Swyllys 	if (rv != KMF_OK) {
3933089Swyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
3943089Swyllys 	}
3953089Swyllys 	OPENSSL_free(derdata.Data);
3963089Swyllys 
3973089Swyllys 	return (rv);
3983089Swyllys }
3993089Swyllys 
4005051Swyllys int
isdir(char * path)4013089Swyllys isdir(char *path)
4023089Swyllys {
4033089Swyllys 	struct stat s;
4043089Swyllys 
4053089Swyllys 	if (stat(path, &s) == -1)
4063089Swyllys 		return (0);
4073089Swyllys 
4085051Swyllys 	return ((s.st_mode & S_IFMT) == S_IFDIR);
4093089Swyllys }
4103089Swyllys 
4113089Swyllys static KMF_RETURN
ssl_cert2KMFDATA(KMF_HANDLE * kmfh,X509 * x509cert,KMF_DATA * cert)4123089Swyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
4133089Swyllys {
4143089Swyllys 	KMF_RETURN rv = KMF_OK;
4153089Swyllys 	unsigned char *buf = NULL, *p;
4163089Swyllys 	int len;
4173089Swyllys 
4183089Swyllys 	/*
4193089Swyllys 	 * Convert the X509 internal struct to DER encoded data
4203089Swyllys 	 */
4213089Swyllys 	if ((len = i2d_X509(x509cert, NULL)) < 0) {
4223089Swyllys 		SET_ERROR(kmfh, ERR_get_error());
4233089Swyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
4243089Swyllys 		goto cleanup;
4253089Swyllys 	}
4263089Swyllys 	if ((buf = malloc(len)) == NULL) {
4273089Swyllys 		SET_SYS_ERROR(kmfh, errno);
4283089Swyllys 		rv = KMF_ERR_MEMORY;
4293089Swyllys 		goto cleanup;
4303089Swyllys 	}
4313089Swyllys 
4323089Swyllys 	/*
4333089Swyllys 	 * i2d_X509 will increment the buf pointer so that we need to
4343089Swyllys 	 * save it.
4353089Swyllys 	 */
4363089Swyllys 	p = buf;
4373089Swyllys 	if ((len = i2d_X509(x509cert, &p)) < 0) {
4383089Swyllys 		SET_ERROR(kmfh, ERR_get_error());
4393089Swyllys 		free(buf);
4403089Swyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
4413089Swyllys 		goto cleanup;
4423089Swyllys 	}
4433089Swyllys 
4443089Swyllys 	/* caller's responsibility to free it */
4453089Swyllys 	cert->Data = buf;
4463089Swyllys 	cert->Length = len;
4473089Swyllys 
4483089Swyllys cleanup:
4493089Swyllys 	if (rv != KMF_OK) {
4503089Swyllys 		if (buf)
4513089Swyllys 			free(buf);
4523089Swyllys 		cert->Data = NULL;
4533089Swyllys 		cert->Length = 0;
4543089Swyllys 	}
4553089Swyllys 
4563089Swyllys 	return (rv);
4573089Swyllys }
4583089Swyllys 
4595051Swyllys 
4603089Swyllys static KMF_RETURN
check_cert(X509 * xcert,char * issuer,char * subject,KMF_BIGINT * serial,boolean_t * match)4615051Swyllys check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
4625051Swyllys     boolean_t *match)
4633089Swyllys {
4643089Swyllys 	KMF_RETURN rv = KMF_OK;
4653089Swyllys 	boolean_t findIssuer = FALSE;
4663089Swyllys 	boolean_t findSubject = FALSE;
4673089Swyllys 	boolean_t findSerial = FALSE;
4683089Swyllys 	KMF_X509_NAME issuerDN, subjectDN;
4693089Swyllys 	KMF_X509_NAME certIssuerDN, certSubjectDN;
4703089Swyllys 
4713089Swyllys 	*match = FALSE;
4723089Swyllys 	if (xcert == NULL) {
4733089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
4743089Swyllys 	}
4753089Swyllys 
4763089Swyllys 	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
4773089Swyllys 	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
4783089Swyllys 	(void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
4793089Swyllys 	(void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
4803089Swyllys 
4815051Swyllys 	if (issuer != NULL && strlen(issuer)) {
4825051Swyllys 		rv = kmf_dn_parser(issuer, &issuerDN);
4833089Swyllys 		if (rv != KMF_OK)
4843089Swyllys 			return (KMF_ERR_BAD_PARAMETER);
4853089Swyllys 
4863089Swyllys 		rv = get_x509_dn(xcert->cert_info->issuer, &certIssuerDN);
4873089Swyllys 		if (rv != KMF_OK) {
4885051Swyllys 			kmf_free_dn(&issuerDN);
4893089Swyllys 			return (KMF_ERR_BAD_PARAMETER);
4903089Swyllys 		}
4913089Swyllys 
4923089Swyllys 		findIssuer = TRUE;
4933089Swyllys 	}
4945051Swyllys 	if (subject != NULL && strlen(subject)) {
4955051Swyllys 		rv = kmf_dn_parser(subject, &subjectDN);
4963089Swyllys 		if (rv != KMF_OK) {
4973089Swyllys 			rv = KMF_ERR_BAD_PARAMETER;
4983089Swyllys 			goto cleanup;
4993089Swyllys 		}
5003089Swyllys 
5013089Swyllys 		rv = get_x509_dn(xcert->cert_info->subject, &certSubjectDN);
5023089Swyllys 		if (rv != KMF_OK) {
5033089Swyllys 			rv = KMF_ERR_BAD_PARAMETER;
5043089Swyllys 			goto cleanup;
5053089Swyllys 		}
5063089Swyllys 		findSubject = TRUE;
5073089Swyllys 	}
5085051Swyllys 	if (serial != NULL && serial->val != NULL)
5093089Swyllys 		findSerial = TRUE;
5103089Swyllys 
5113089Swyllys 	if (findSerial) {
5123089Swyllys 		BIGNUM *bn;
5133089Swyllys 
5143089Swyllys 		/* Comparing BIGNUMs is a pain! */
5153089Swyllys 		bn = ASN1_INTEGER_to_BN(xcert->cert_info->serialNumber, NULL);
5163089Swyllys 		if (bn != NULL) {
5173089Swyllys 			int bnlen = BN_num_bytes(bn);
5183089Swyllys 
5195051Swyllys 			if (bnlen == serial->len) {
5203089Swyllys 				uchar_t *a = malloc(bnlen);
5213089Swyllys 				if (a == NULL) {
5223089Swyllys 					rv = KMF_ERR_MEMORY;
5233089Swyllys 					BN_free(bn);
5243089Swyllys 					goto cleanup;
5253089Swyllys 				}
5263089Swyllys 				bnlen = BN_bn2bin(bn, a);
5275051Swyllys 				*match = (memcmp(a, serial->val, serial->len) ==
5285051Swyllys 				    0);
5293089Swyllys 				rv = KMF_OK;
5303089Swyllys 				free(a);
5313089Swyllys 			}
5323089Swyllys 			BN_free(bn);
5333089Swyllys 			if (!(*match))
5343089Swyllys 				goto cleanup;
5353089Swyllys 		} else {
5363089Swyllys 			rv = KMF_OK;
5373089Swyllys 			goto cleanup;
5383089Swyllys 		}
5393089Swyllys 	}
5403089Swyllys 	if (findIssuer) {
5415051Swyllys 		*match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
5425051Swyllys 		if ((*match) == B_FALSE) {
5435051Swyllys 			/* stop checking and bail */
5443089Swyllys 			rv = KMF_OK;
5453089Swyllys 			goto cleanup;
5463089Swyllys 		}
5473089Swyllys 	}
5483089Swyllys 	if (findSubject) {
5495051Swyllys 		*match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
5505051Swyllys 		if ((*match) == B_FALSE) {
5515051Swyllys 			/* stop checking and bail */
5523089Swyllys 			rv = KMF_OK;
5533089Swyllys 			goto cleanup;
5543089Swyllys 		}
5553089Swyllys 	}
5563089Swyllys 
5573089Swyllys 	*match = TRUE;
5583089Swyllys cleanup:
5593089Swyllys 	if (findIssuer) {
5605051Swyllys 		kmf_free_dn(&issuerDN);
5615051Swyllys 		kmf_free_dn(&certIssuerDN);
5623089Swyllys 	}
5633089Swyllys 	if (findSubject) {
5645051Swyllys 		kmf_free_dn(&subjectDN);
5655051Swyllys 		kmf_free_dn(&certSubjectDN);
5663089Swyllys 	}
5673089Swyllys 
5683089Swyllys 	return (rv);
5693089Swyllys }
5703089Swyllys 
5715051Swyllys 
5725051Swyllys /*
5735051Swyllys  * This function loads a certificate file into an X509 data structure, and
5745051Swyllys  * checks if its issuer, subject or the serial number matches with those
5755051Swyllys  * values.  If it matches, then return the X509 data structure.
5765051Swyllys  */
5773089Swyllys static KMF_RETURN
load_X509cert(KMF_HANDLE * kmfh,char * issuer,char * subject,KMF_BIGINT * serial,char * pathname,X509 ** outcert)5783089Swyllys load_X509cert(KMF_HANDLE *kmfh,
5795051Swyllys     char *issuer, char *subject, KMF_BIGINT *serial,
5805051Swyllys     char *pathname, X509 **outcert)
5813089Swyllys {
5823089Swyllys 	KMF_RETURN rv = KMF_OK;
5833089Swyllys 	X509 *xcert = NULL;
5843089Swyllys 	BIO *bcert = NULL;
5853089Swyllys 	boolean_t  match = FALSE;
5863089Swyllys 	KMF_ENCODE_FORMAT format;
5873089Swyllys 
5883089Swyllys 	/*
5893089Swyllys 	 * auto-detect the file format, regardless of what
5903089Swyllys 	 * the 'format' parameters in the params say.
5913089Swyllys 	 */
5925051Swyllys 	rv = kmf_get_file_format(pathname, &format);
5933089Swyllys 	if (rv != KMF_OK) {
5943089Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
5953089Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
5963089Swyllys 		return (rv);
5973089Swyllys 	}
5983089Swyllys 
5993089Swyllys 	/* Not ASN1(DER) format */
6003089Swyllys 	if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
6013089Swyllys 		SET_ERROR(kmfh, ERR_get_error());
6023089Swyllys 		rv = KMF_ERR_OPEN_FILE;
6033089Swyllys 		goto cleanup;
6043089Swyllys 	}
6053089Swyllys 
6063089Swyllys 	if (format == KMF_FORMAT_PEM)
6073089Swyllys 		xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
6083089Swyllys 	else if (format == KMF_FORMAT_ASN1)
6093089Swyllys 		xcert = d2i_X509_bio(bcert, NULL);
6103089Swyllys 	else if (format == KMF_FORMAT_PKCS12) {
6113089Swyllys 		PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
6123089Swyllys 		if (p12 != NULL) {
6133089Swyllys 			(void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
6143089Swyllys 			PKCS12_free(p12);
6153089Swyllys 			p12 = NULL;
6163089Swyllys 		} else {
6173089Swyllys 			SET_ERROR(kmfh, ERR_get_error());
6183089Swyllys 			rv = KMF_ERR_BAD_CERT_FORMAT;
6193089Swyllys 		}
6203089Swyllys 	} else {
6213089Swyllys 		rv = KMF_ERR_BAD_PARAMETER;
6223089Swyllys 		goto cleanup;
6233089Swyllys 	}
6243089Swyllys 
6253089Swyllys 	if (xcert == NULL) {
6263089Swyllys 		SET_ERROR(kmfh, ERR_get_error());
6273089Swyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
6283089Swyllys 		goto cleanup;
6293089Swyllys 	}
6303089Swyllys 
6315051Swyllys 	if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
6325051Swyllys 	    match == FALSE) {
6333089Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
6343089Swyllys 		goto cleanup;
6353089Swyllys 	}
6363089Swyllys 
6373089Swyllys 	if (outcert != NULL) {
6383089Swyllys 		*outcert = xcert;
6393089Swyllys 	}
6403089Swyllys 
6413089Swyllys cleanup:
6423089Swyllys 	if (bcert != NULL) (void) BIO_free(bcert);
6433089Swyllys 	if (rv != KMF_OK && xcert != NULL)
6443089Swyllys 		X509_free(xcert);
6453089Swyllys 
6463089Swyllys 	return (rv);
6473089Swyllys }
6483089Swyllys 
6493408Swyllys static int
datacmp(const void * a,const void * b)6503408Swyllys datacmp(const void *a, const void *b)
6513408Swyllys {
6523408Swyllys 	KMF_DATA *adata = (KMF_DATA *)a;
6533408Swyllys 	KMF_DATA *bdata = (KMF_DATA *)b;
6543408Swyllys 	if (adata->Length > bdata->Length)
6553408Swyllys 		return (-1);
6563408Swyllys 	if (adata->Length < bdata->Length)
6573408Swyllys 		return (1);
6583408Swyllys 	return (0);
6593408Swyllys }
6603408Swyllys 
6613408Swyllys 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)6625051Swyllys load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
6635051Swyllys     KMF_CERT_VALIDITY validity, char *pathname,
6645051Swyllys     KMF_DATA **certlist, uint32_t *numcerts)
6653408Swyllys {
6663408Swyllys 	KMF_RETURN rv = KMF_OK;
6673408Swyllys 	int i;
6683408Swyllys 	KMF_DATA *certs = NULL;
6693408Swyllys 	int nc = 0;
6703408Swyllys 	int hits = 0;
6713408Swyllys 	KMF_ENCODE_FORMAT format;
6723408Swyllys 
6735051Swyllys 	rv = kmf_get_file_format(pathname, &format);
6743408Swyllys 	if (rv != KMF_OK) {
6753408Swyllys 		if (rv == KMF_ERR_OPEN_FILE)
6763408Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
6773408Swyllys 		return (rv);
6783408Swyllys 	}
6793408Swyllys 	if (format == KMF_FORMAT_ASN1) {
6803408Swyllys 		/* load a single certificate */
6813408Swyllys 		certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
6823408Swyllys 		if (certs == NULL)
6833408Swyllys 			return (KMF_ERR_MEMORY);
6843408Swyllys 		certs->Data = NULL;
6853408Swyllys 		certs->Length = 0;
6865051Swyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
6875051Swyllys 		    pathname, certs);
6883408Swyllys 		if (rv == KMF_OK) {
6893408Swyllys 			*certlist = certs;
6903408Swyllys 			*numcerts = 1;
69111673Sopensolaris@drydog.com 		} else {
69211673Sopensolaris@drydog.com 			kmf_free_data(certs);
69311673Sopensolaris@drydog.com 			free(certs);
69411673Sopensolaris@drydog.com 			certs = NULL;
6953408Swyllys 		}
6963408Swyllys 		return (rv);
6973408Swyllys 	} else if (format == KMF_FORMAT_PKCS12) {
6983408Swyllys 		/* We need a credential to access a PKCS#12 file */
6993408Swyllys 		rv = KMF_ERR_BAD_CERT_FORMAT;
7003408Swyllys 	} else if (format == KMF_FORMAT_PEM ||
7014315Swyllys 	    format != KMF_FORMAT_PEM_KEYPAIR) {
70211973Swyllys.ingersoll@sun.com 
7033408Swyllys 		/* This function only works on PEM files */
7045051Swyllys 		rv = extract_pem(kmfh, issuer, subject, serial, pathname,
7054315Swyllys 		    (uchar_t *)NULL, 0, NULL, &certs, &nc);
7063408Swyllys 	} else {
7073408Swyllys 		return (KMF_ERR_ENCODING);
7083408Swyllys 	}
7093408Swyllys 
7103408Swyllys 	if (rv != KMF_OK)
7113408Swyllys 		return (rv);
7123408Swyllys 
7133408Swyllys 	for (i = 0; i < nc; i++) {
7145051Swyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
7155051Swyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
7165051Swyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
7175051Swyllys 			rv = kmf_check_cert_date(kmfh, &certs[i]);
7183408Swyllys 			if (rv == KMF_OK)
7193408Swyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
7203408Swyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD)
7213408Swyllys 				rv = KMF_OK;
7223408Swyllys 		}
7233408Swyllys 		if (rv != KMF_OK) {
7243408Swyllys 			/* Remove this cert from the list by clearing it. */
7255051Swyllys 			kmf_free_data(&certs[i]);
7263408Swyllys 		} else {
7273408Swyllys 			hits++; /* count valid certs found */
7283408Swyllys 		}
7293408Swyllys 		rv = KMF_OK;
7303408Swyllys 	}
73111673Sopensolaris@drydog.com 	if (rv == KMF_OK && hits > 0) {
7323408Swyllys 		/*
7333408Swyllys 		 * Sort the list of certs by length to put the cleared ones
7343408Swyllys 		 * at the end so they don't get accessed by the caller.
7353408Swyllys 		 */
7363408Swyllys 		qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
7373408Swyllys 		*certlist = certs;
7383408Swyllys 
7393408Swyllys 		/* since we sorted the list, just return the number of hits */
7403408Swyllys 		*numcerts = hits;
74111673Sopensolaris@drydog.com 	} else {
74211973Swyllys.ingersoll@sun.com 		if (rv == KMF_OK && hits == 0)
74311673Sopensolaris@drydog.com 			rv = KMF_ERR_CERT_NOT_FOUND;
74411673Sopensolaris@drydog.com 		if (certs != NULL) {
74511673Sopensolaris@drydog.com 			free(certs);
74611673Sopensolaris@drydog.com 			certs = NULL;
74711673Sopensolaris@drydog.com 		}
74811673Sopensolaris@drydog.com 	}
7493408Swyllys 	return (rv);
7503408Swyllys }
7513408Swyllys 
7523089Swyllys 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)7533089Swyllys kmf_load_cert(KMF_HANDLE *kmfh,
7545051Swyllys     char *issuer, char *subject, KMF_BIGINT *serial,
7555051Swyllys     KMF_CERT_VALIDITY validity,
7565051Swyllys     char *pathname,
7575051Swyllys     KMF_DATA *cert)
7583089Swyllys {
7593089Swyllys 	KMF_RETURN rv = KMF_OK;
7603089Swyllys 	X509 *x509cert = NULL;
7613089Swyllys 
7625051Swyllys 	rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
7633089Swyllys 	if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
7643089Swyllys 		rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
7653089Swyllys 		if (rv != KMF_OK) {
7663089Swyllys 			goto cleanup;
7673089Swyllys 		}
7685051Swyllys 		if (validity == KMF_NONEXPIRED_CERTS) {
7695051Swyllys 			rv = kmf_check_cert_date(kmfh, cert);
7705051Swyllys 		} else if (validity == KMF_EXPIRED_CERTS) {
7715051Swyllys 			rv = kmf_check_cert_date(kmfh, cert);
7723089Swyllys 			if (rv == KMF_OK)  {
7733089Swyllys 				/*
7743089Swyllys 				 * This is a valid cert so skip it.
7753089Swyllys 				 */
7763089Swyllys 				rv = KMF_ERR_CERT_NOT_FOUND;
7773089Swyllys 			}
7783089Swyllys 			if (rv == KMF_ERR_VALIDITY_PERIOD) {
7793089Swyllys 				/*
7803089Swyllys 				 * We want to return success when we
7813089Swyllys 				 * find an invalid cert.
7823089Swyllys 				 */
7833089Swyllys 				rv = KMF_OK;
7843089Swyllys 				goto cleanup;
7853089Swyllys 			}
7863089Swyllys 		}
7873089Swyllys 	}
7883089Swyllys cleanup:
7893089Swyllys 	if (x509cert != NULL)
7903089Swyllys 		X509_free(x509cert);
7913089Swyllys 
7923089Swyllys 	return (rv);
7933089Swyllys }
7943089Swyllys 
7953754Swyllys static KMF_RETURN
readAltFormatPrivateKey(KMF_DATA * filedata,EVP_PKEY ** pkey)7963754Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
7973754Swyllys {
7983754Swyllys 	KMF_RETURN ret = KMF_OK;
7993754Swyllys 	KMF_RAW_RSA_KEY rsa;
8003754Swyllys 	BerElement *asn1 = NULL;
8013754Swyllys 	BerValue filebuf;
8023754Swyllys 	BerValue OID = { NULL, 0 };
8033754Swyllys 	BerValue *Mod = NULL, *PubExp = NULL;
8043754Swyllys 	BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
8053754Swyllys 	BerValue *Coef = NULL;
8063754Swyllys 	BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
8073754Swyllys 	BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
8083754Swyllys 	BIGNUM *qminus1 = NULL;
8093754Swyllys 	BN_CTX *ctx = NULL;
8103754Swyllys 
8113754Swyllys 	*pkey = NULL;
8123754Swyllys 
8133754Swyllys 	filebuf.bv_val = (char *)filedata->Data;
8143754Swyllys 	filebuf.bv_len = filedata->Length;
8153754Swyllys 
8163754Swyllys 	asn1 = kmfder_init(&filebuf);
8173754Swyllys 	if (asn1 == NULL) {
8183754Swyllys 		ret = KMF_ERR_MEMORY;
8193754Swyllys 		goto out;
8203754Swyllys 	}
8213754Swyllys 
8223754Swyllys 	if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
8234315Swyllys 	    &OID, &Mod, &PubExp, &PriExp, &Prime1,
8244315Swyllys 	    &Prime2, &Coef) == -1)  {
8253754Swyllys 		ret = KMF_ERR_ENCODING;
8263754Swyllys 		goto out;
8273754Swyllys 	}
8283754Swyllys 
8293754Swyllys 	/*
8303754Swyllys 	 * We have to derive the 2 Exponents using Bignumber math.
8313754Swyllys 	 * Exp1 = PriExp mod (Prime1 - 1)
8323754Swyllys 	 * Exp2 = PriExp mod (Prime2 - 1)
8333754Swyllys 	 */
8343754Swyllys 
8353754Swyllys 	/* D = PrivateExponent */
8363754Swyllys 	D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
8373754Swyllys 	if (D == NULL) {
8383754Swyllys 		ret = KMF_ERR_MEMORY;
8393754Swyllys 		goto out;
8403754Swyllys 	}
8413754Swyllys 
8423754Swyllys 	/* P = Prime1 (first prime factor of Modulus) */
8433754Swyllys 	P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
8443754Swyllys 	if (D == NULL) {
8453754Swyllys 		ret = KMF_ERR_MEMORY;
8463754Swyllys 		goto out;
8473754Swyllys 	}
8483754Swyllys 
8493754Swyllys 	/* Q = Prime2 (second prime factor of Modulus) */
8503754Swyllys 	Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
8513754Swyllys 
8523754Swyllys 	if ((ctx = BN_CTX_new()) == NULL) {
8533754Swyllys 		ret = KMF_ERR_MEMORY;
8543754Swyllys 		goto out;
8553754Swyllys 	}
8563754Swyllys 
8573754Swyllys 	/* Compute (P - 1) */
8583754Swyllys 	pminus1 = BN_new();
8593754Swyllys 	(void) BN_sub(pminus1, P, BN_value_one());
8603754Swyllys 
8613754Swyllys 	/* Exponent1 = D mod (P - 1) */
8623754Swyllys 	Exp1 = BN_new();
8633754Swyllys 	(void) BN_mod(Exp1, D, pminus1, ctx);
8643754Swyllys 
8653754Swyllys 	/* Compute (Q - 1) */
8663754Swyllys 	qminus1 = BN_new();
8673754Swyllys 	(void) BN_sub(qminus1, Q, BN_value_one());
8683754Swyllys 
8693754Swyllys 	/* Exponent2 = D mod (Q - 1) */
8703754Swyllys 	Exp2 = BN_new();
8713754Swyllys 	(void) BN_mod(Exp2, D, qminus1, ctx);
8723754Swyllys 
8733754Swyllys 	/* Coef = (Inverse Q) mod P */
8743754Swyllys 	COEF = BN_new();
8753754Swyllys 	(void) BN_mod_inverse(COEF, Q, P, ctx);
8763754Swyllys 
8773754Swyllys 	/* Convert back to KMF format */
8783754Swyllys 	(void) memset(&rsa, 0, sizeof (rsa));
8793754Swyllys 
8803754Swyllys 	if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
8813754Swyllys 		goto out;
8823754Swyllys 	if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
8833754Swyllys 		goto out;
8843754Swyllys 	if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
8853754Swyllys 		goto out;
8863754Swyllys 
8873754Swyllys 	rsa.mod.val = (uchar_t *)Mod->bv_val;
8883754Swyllys 	rsa.mod.len = Mod->bv_len;
8893754Swyllys 
8903754Swyllys 	rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
8913754Swyllys 	rsa.pubexp.len = PubExp->bv_len;
8923754Swyllys 
8933754Swyllys 	rsa.priexp.val = (uchar_t *)PriExp->bv_val;
8943754Swyllys 	rsa.priexp.len = PriExp->bv_len;
8953754Swyllys 
8963754Swyllys 	rsa.prime1.val = (uchar_t *)Prime1->bv_val;
8973754Swyllys 	rsa.prime1.len = Prime1->bv_len;
8983754Swyllys 
8993754Swyllys 	rsa.prime2.val = (uchar_t *)Prime2->bv_val;
9003754Swyllys 	rsa.prime2.len = Prime2->bv_len;
9013754Swyllys 
9023754Swyllys 	*pkey = ImportRawRSAKey(&rsa);
9033754Swyllys out:
9043754Swyllys 	if (asn1 != NULL)
9053754Swyllys 		kmfber_free(asn1, 1);
9063754Swyllys 
9073754Swyllys 	if (OID.bv_val) {
9083754Swyllys 		free(OID.bv_val);
9093754Swyllys 	}
9103754Swyllys 	if (PriExp)
9113754Swyllys 		free(PriExp);
9123754Swyllys 
9133754Swyllys 	if (Mod)
9143754Swyllys 		free(Mod);
9153754Swyllys 
9163754Swyllys 	if (PubExp)
9173754Swyllys 		free(PubExp);
9183754Swyllys 
9193754Swyllys 	if (Coef) {
9203754Swyllys 		(void) memset(Coef->bv_val, 0, Coef->bv_len);
9213754Swyllys 		free(Coef->bv_val);
9223754Swyllys 		free(Coef);
9233754Swyllys 	}
9243754Swyllys 	if (Prime1)
9253754Swyllys 		free(Prime1);
9263754Swyllys 	if (Prime2)
9273754Swyllys 		free(Prime2);
9283754Swyllys 
9293754Swyllys 	if (ctx != NULL)
9303754Swyllys 		BN_CTX_free(ctx);
9313754Swyllys 
9323754Swyllys 	if (D)
9333754Swyllys 		BN_clear_free(D);
9343754Swyllys 	if (P)
9353754Swyllys 		BN_clear_free(P);
9363754Swyllys 	if (Q)
9373754Swyllys 		BN_clear_free(Q);
9383754Swyllys 	if (pminus1)
9393754Swyllys 		BN_clear_free(pminus1);
9403754Swyllys 	if (qminus1)
9413754Swyllys 		BN_clear_free(qminus1);
9423754Swyllys 	if (Exp1)
9433754Swyllys 		BN_clear_free(Exp1);
9443754Swyllys 	if (Exp2)
9453754Swyllys 		BN_clear_free(Exp2);
9463754Swyllys 
9473754Swyllys 	return (ret);
9483754Swyllys 
9493754Swyllys }
9503754Swyllys 
9513089Swyllys static EVP_PKEY *
openssl_load_key(KMF_HANDLE_T handle,const char * file)9523089Swyllys openssl_load_key(KMF_HANDLE_T handle, const char *file)
9533089Swyllys {
9543089Swyllys 	BIO *keyfile = NULL;
9553089Swyllys 	EVP_PKEY *pkey = NULL;
9563089Swyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
9573089Swyllys 	KMF_ENCODE_FORMAT format;
9583754Swyllys 	KMF_RETURN rv;
9593754Swyllys 	KMF_DATA filedata;
9603089Swyllys 
9613089Swyllys 	if (file == NULL) {
9623089Swyllys 		return (NULL);
9633089Swyllys 	}
9643089Swyllys 
9655051Swyllys 	if (kmf_get_file_format((char *)file, &format) != KMF_OK)
9663089Swyllys 		return (NULL);
9673089Swyllys 
9683089Swyllys 	keyfile = BIO_new_file(file, "rb");
9693089Swyllys 	if (keyfile == NULL) {
9703089Swyllys 		goto end;
9713089Swyllys 	}
9723089Swyllys 
9733754Swyllys 	if (format == KMF_FORMAT_ASN1) {
9743089Swyllys 		pkey = d2i_PrivateKey_bio(keyfile, NULL);
9753754Swyllys 		if (pkey == NULL) {
9763754Swyllys 
9773754Swyllys 			(void) BIO_free(keyfile);
9783754Swyllys 			keyfile = NULL;
9793754Swyllys 			/* Try odd ASN.1 variations */
9805051Swyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
9814315Swyllys 			    &filedata);
9823754Swyllys 			if (rv == KMF_OK) {
9833754Swyllys 				(void) readAltFormatPrivateKey(&filedata,
9844315Swyllys 				    &pkey);
9855051Swyllys 				kmf_free_data(&filedata);
9863754Swyllys 			}
9873754Swyllys 		}
9883754Swyllys 	} else if (format == KMF_FORMAT_PEM ||
9894315Swyllys 	    format == KMF_FORMAT_PEM_KEYPAIR) {
9903089Swyllys 		pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
9913754Swyllys 		if (pkey == NULL) {
9923754Swyllys 			KMF_DATA derdata;
9933754Swyllys 			/*
9943754Swyllys 			 * Check if this is the alt. format
9953754Swyllys 			 * RSA private key file.
9963754Swyllys 			 */
9975051Swyllys 			rv = kmf_read_input_file(kmfh, (char *)file,
9984315Swyllys 			    &filedata);
9993754Swyllys 			if (rv == KMF_OK) {
10003754Swyllys 				uchar_t *d = NULL;
10013754Swyllys 				int len;
10025051Swyllys 				rv = kmf_pem_to_der(filedata.Data,
10034315Swyllys 				    filedata.Length, &d, &len);
10043754Swyllys 				if (rv == KMF_OK && d != NULL) {
10053754Swyllys 					derdata.Data = d;
10063754Swyllys 					derdata.Length = (size_t)len;
10073754Swyllys 					(void) readAltFormatPrivateKey(
10084315Swyllys 					    &derdata, &pkey);
10093754Swyllys 					free(d);
10103754Swyllys 				}
10115051Swyllys 				kmf_free_data(&filedata);
10123754Swyllys 			}
10133754Swyllys 		}
10143754Swyllys 	}
10153089Swyllys 
10163089Swyllys end:
10173089Swyllys 	if (pkey == NULL)
10183089Swyllys 		SET_ERROR(kmfh, ERR_get_error());
10193089Swyllys 
10203089Swyllys 	if (keyfile != NULL)
10213089Swyllys 		(void) BIO_free(keyfile);
10223089Swyllys 
10233089Swyllys 	return (pkey);
10243089Swyllys }
10253089Swyllys 
10263089Swyllys KMF_RETURN
OpenSSL_FindCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)10275051Swyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
10283089Swyllys {
10293089Swyllys 	KMF_RETURN rv = KMF_OK;
10303089Swyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
10314025Swyllys 	int i, n;
10324025Swyllys 	uint32_t maxcerts = 0;
10335051Swyllys 	uint32_t *num_certs;
10345051Swyllys 	KMF_X509_DER_CERT *kmf_cert = NULL;
10355051Swyllys 	char *dirpath = NULL;
10365051Swyllys 	char *filename = NULL;
10375051Swyllys 	char *fullpath = NULL;
10385051Swyllys 	char *issuer = NULL;
10395051Swyllys 	char *subject = NULL;
10405051Swyllys 	KMF_BIGINT *serial = NULL;
10415051Swyllys 	KMF_CERT_VALIDITY validity;
10425051Swyllys 
10435051Swyllys 	num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
10445051Swyllys 	if (num_certs == NULL)
10453089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
10463089Swyllys 
10475051Swyllys 	/* num_certs should reference the size of kmf_cert */
10484025Swyllys 	maxcerts = *num_certs;
10494025Swyllys 	if (maxcerts == 0)
10504025Swyllys 		maxcerts = 0xFFFFFFFF;
10513089Swyllys 	*num_certs = 0;
10523089Swyllys 
10535051Swyllys 	/* Get the optional returned certificate list  */
10545051Swyllys 	kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
10555051Swyllys 	    numattr);
10565051Swyllys 
10575051Swyllys 	/*
10585051Swyllys 	 * The dirpath attribute and the filename attribute can not be NULL
10595051Swyllys 	 * at the same time.
10605051Swyllys 	 */
10615051Swyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
10625051Swyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
10635051Swyllys 	    numattr);
10645051Swyllys 
10655051Swyllys 	fullpath = get_fullpath(dirpath, filename);
10663089Swyllys 	if (fullpath == NULL)
10673089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
10683089Swyllys 
10695051Swyllys 	/* Get optional search criteria attributes */
10705051Swyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
10715051Swyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
10725051Swyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
10735051Swyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
10745051Swyllys 	    &validity, NULL);
10755051Swyllys 	if (rv != KMF_OK) {
10765051Swyllys 		validity = KMF_ALL_CERTS;
10775051Swyllys 		rv = KMF_OK;
10785051Swyllys 	}
10795051Swyllys 
10803089Swyllys 	if (isdir(fullpath)) {
10813089Swyllys 		DIR *dirp;
10823089Swyllys 		struct dirent *dp;
10834025Swyllys 
10844025Swyllys 		n = 0;
10853089Swyllys 		/* open all files in the directory and attempt to read them */
10863089Swyllys 		if ((dirp = opendir(fullpath)) == NULL) {
10873089Swyllys 			return (KMF_ERR_BAD_PARAMETER);
10883089Swyllys 		}
10893089Swyllys 		while ((dp = readdir(dirp)) != NULL) {
10903089Swyllys 			char *fname;
10913408Swyllys 			KMF_DATA *certlist = NULL;
10924025Swyllys 			uint32_t loaded_certs = 0;
10933408Swyllys 
10943089Swyllys 			if (strcmp(dp->d_name, ".") == 0 ||
10953089Swyllys 			    strcmp(dp->d_name, "..") == 0)
10963089Swyllys 				continue;
10973089Swyllys 
10984315Swyllys 			fname = get_fullpath(fullpath, (char *)&dp->d_name);
10993089Swyllys 
11005051Swyllys 			rv = load_certs(kmfh, issuer, subject, serial,
11015051Swyllys 			    validity, fname, &certlist,	&loaded_certs);
11023089Swyllys 
11033089Swyllys 			if (rv != KMF_OK) {
11043089Swyllys 				free(fname);
11053408Swyllys 				if (certlist != NULL) {
11064025Swyllys 					for (i = 0; i < loaded_certs; i++)
11075051Swyllys 						kmf_free_data(&certlist[i]);
11083408Swyllys 					free(certlist);
11093408Swyllys 				}
11103089Swyllys 				continue;
11113089Swyllys 			}
11123089Swyllys 
11133089Swyllys 			/* If load succeeds, add certdata to the list */
11143089Swyllys 			if (kmf_cert != NULL) {
11154025Swyllys 				for (i = 0; i < loaded_certs &&
11164090Swyllys 				    n < maxcerts; i++) {
11173408Swyllys 					kmf_cert[n].certificate.Data =
11184315Swyllys 					    certlist[i].Data;
11193408Swyllys 					kmf_cert[n].certificate.Length =
11204315Swyllys 					    certlist[i].Length;
11213408Swyllys 
11223408Swyllys 					kmf_cert[n].kmf_private.keystore_type =
11234315Swyllys 					    KMF_KEYSTORE_OPENSSL;
11243408Swyllys 					kmf_cert[n].kmf_private.flags =
11254315Swyllys 					    KMF_FLAG_CERT_VALID;
11263408Swyllys 					kmf_cert[n].kmf_private.label =
11274315Swyllys 					    strdup(fname);
11283408Swyllys 					n++;
11293408Swyllys 				}
11304090Swyllys 				/*
11314090Swyllys 				 * If maxcerts < loaded_certs, clean up the
11324090Swyllys 				 * certs that were not used.
11334090Swyllys 				 */
11344025Swyllys 				for (; i < loaded_certs; i++)
11355051Swyllys 					kmf_free_data(&certlist[i]);
11364025Swyllys 			} else {
11374025Swyllys 				for (i = 0; i < loaded_certs; i++)
11385051Swyllys 					kmf_free_data(&certlist[i]);
11394025Swyllys 				n += loaded_certs;
11403089Swyllys 			}
11414025Swyllys 			free(certlist);
11423408Swyllys 			free(fname);
11433089Swyllys 		}
11443089Swyllys 		(*num_certs) = n;
11453089Swyllys 		if (*num_certs == 0)
11463089Swyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
11475051Swyllys 		if (*num_certs > 0)
11483089Swyllys 			rv = KMF_OK;
11493089Swyllys exit:
11503089Swyllys 		(void) closedir(dirp);
11513089Swyllys 	} else {
11523408Swyllys 		KMF_DATA *certlist = NULL;
11534025Swyllys 		uint32_t loaded_certs = 0;
11544025Swyllys 
11555051Swyllys 		rv = load_certs(kmfh, issuer, subject, serial, validity,
11565051Swyllys 		    fullpath, &certlist, &loaded_certs);
11573089Swyllys 		if (rv != KMF_OK) {
11583089Swyllys 			free(fullpath);
11593089Swyllys 			return (rv);
11603089Swyllys 		}
11613089Swyllys 
11624025Swyllys 		n = 0;
11633408Swyllys 		if (kmf_cert != NULL && certlist != NULL) {
11644025Swyllys 			for (i = 0; i < loaded_certs && i < maxcerts; i++) {
11654025Swyllys 				kmf_cert[n].certificate.Data =
11664315Swyllys 				    certlist[i].Data;
11674025Swyllys 				kmf_cert[n].certificate.Length =
11684315Swyllys 				    certlist[i].Length;
11694025Swyllys 				kmf_cert[n].kmf_private.keystore_type =
11704315Swyllys 				    KMF_KEYSTORE_OPENSSL;
11714025Swyllys 				kmf_cert[n].kmf_private.flags =
11724315Swyllys 				    KMF_FLAG_CERT_VALID;
11734025Swyllys 				kmf_cert[n].kmf_private.label =
11744315Swyllys 				    strdup(fullpath);
11754025Swyllys 				n++;
11763408Swyllys 			}
11774025Swyllys 			/* If maxcerts < loaded_certs, clean up */
11784025Swyllys 			for (; i < loaded_certs; i++)
11795051Swyllys 				kmf_free_data(&certlist[i]);
11804025Swyllys 		} else if (certlist != NULL) {
11814025Swyllys 			for (i = 0; i < loaded_certs; i++)
11825051Swyllys 				kmf_free_data(&certlist[i]);
11834025Swyllys 			n = loaded_certs;
11844025Swyllys 		}
11855051Swyllys 		if (certlist != NULL)
11863408Swyllys 			free(certlist);
11874025Swyllys 		*num_certs = n;
11883408Swyllys 	}
11893408Swyllys 
11903408Swyllys 	free(fullpath);
11913089Swyllys 
11923089Swyllys 	return (rv);
11933089Swyllys }
11943089Swyllys 
11953089Swyllys void
11963089Swyllys /*ARGSUSED*/
OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,KMF_X509_DER_CERT * kmf_cert)11973089Swyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
11983089Swyllys 	KMF_X509_DER_CERT *kmf_cert)
11993089Swyllys {
12003089Swyllys 	if (kmf_cert != NULL) {
12013089Swyllys 		if (kmf_cert->certificate.Data != NULL) {
120211973Swyllys.ingersoll@sun.com 			kmf_free_data(&kmf_cert->certificate);
12033089Swyllys 		}
12043089Swyllys 		if (kmf_cert->kmf_private.label)
12053089Swyllys 			free(kmf_cert->kmf_private.label);
12063089Swyllys 	}
12073089Swyllys }
12083089Swyllys 
12095051Swyllys /*ARGSUSED*/
12103089Swyllys KMF_RETURN
OpenSSL_StoreCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)12115051Swyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
12123089Swyllys {
12133089Swyllys 	KMF_RETURN ret = KMF_OK;
12145051Swyllys 	KMF_DATA *cert = NULL;
12155051Swyllys 	char *outfilename = NULL;
12165051Swyllys 	char *dirpath = NULL;
12175051Swyllys 	char *fullpath = NULL;
12183089Swyllys 	KMF_ENCODE_FORMAT format;
12193089Swyllys 
12205051Swyllys 	/* Get the cert data */
12215051Swyllys 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
12225051Swyllys 	if (cert == NULL || cert->Data == NULL)
12233089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
12245051Swyllys 
12255051Swyllys 	/* Check the output filename and directory attributes. */
12265051Swyllys 	outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
12275051Swyllys 	    numattr);
12285051Swyllys 	if (outfilename == NULL)
12293089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
12305051Swyllys 
12315051Swyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
12325051Swyllys 	fullpath = get_fullpath(dirpath, outfilename);
12335051Swyllys 	if (fullpath == NULL)
12345051Swyllys 		return (KMF_ERR_BAD_CERTFILE);
12355051Swyllys 
12365051Swyllys 	/* Check the optional format attribute */
12375051Swyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
12385051Swyllys 	    &format, NULL);
12395051Swyllys 	if (ret != KMF_OK) {
12405051Swyllys 		/* If there is no format attribute, then default to PEM */
12415051Swyllys 		format = KMF_FORMAT_PEM;
12425051Swyllys 		ret = KMF_OK;
12435051Swyllys 	} else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
12445051Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
12453089Swyllys 		goto out;
12463089Swyllys 	}
12473089Swyllys 
12485051Swyllys 	/* Store the certificate in the file with the specified format */
12495051Swyllys 	ret = kmf_create_cert_file(cert, format, fullpath);
12503089Swyllys 
12513089Swyllys out:
12523089Swyllys 	if (fullpath != NULL)
12533089Swyllys 		free(fullpath);
12543089Swyllys 
12553089Swyllys 	return (ret);
12563089Swyllys }
12573089Swyllys 
12585051Swyllys 
12593089Swyllys KMF_RETURN
OpenSSL_DeleteCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)12605051Swyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
12613089Swyllys {
12623089Swyllys 	KMF_RETURN rv;
12633089Swyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
12645051Swyllys 	KMF_DATA certdata = {NULL, 0};
12655051Swyllys 	char *dirpath = NULL;
12665051Swyllys 	char *filename = NULL;
12673089Swyllys 	char *fullpath = NULL;
12685051Swyllys 	char *issuer = NULL;
12695051Swyllys 	char *subject = NULL;
12705051Swyllys 	KMF_BIGINT *serial = NULL;
12715051Swyllys 	KMF_CERT_VALIDITY validity;
12725051Swyllys 
12735051Swyllys 	/*
12745051Swyllys 	 * Get the DIRPATH and CERT_FILENAME attributes.  They can not be
12755051Swyllys 	 * NULL at the same time.
12765051Swyllys 	 */
12775051Swyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
12785051Swyllys 	filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
12795051Swyllys 	    numattr);
12805051Swyllys 	fullpath = get_fullpath(dirpath, filename);
12813089Swyllys 	if (fullpath == NULL)
12823089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
12833089Swyllys 
12845051Swyllys 	/* Get optional search criteria attributes */
12855051Swyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
12865051Swyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
12875051Swyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
12885051Swyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
12895051Swyllys 	    &validity, NULL);
12905051Swyllys 	if (rv != KMF_OK) {
12915051Swyllys 		validity = KMF_ALL_CERTS;
12925051Swyllys 		rv = KMF_OK;
12935051Swyllys 	}
12945051Swyllys 
12953089Swyllys 	if (isdir(fullpath)) {
12963089Swyllys 		DIR *dirp;
12973089Swyllys 		struct dirent *dp;
12983089Swyllys 
12993089Swyllys 		/* open all files in the directory and attempt to read them */
13003089Swyllys 		if ((dirp = opendir(fullpath)) == NULL) {
13013089Swyllys 			return (KMF_ERR_BAD_PARAMETER);
13023089Swyllys 		}
13033089Swyllys 
13043089Swyllys 		while ((dp = readdir(dirp)) != NULL) {
13053089Swyllys 			if (strcmp(dp->d_name, ".") != 0 &&
13063089Swyllys 			    strcmp(dp->d_name, "..") != 0) {
13073089Swyllys 				char *fname;
13083089Swyllys 
13093089Swyllys 				fname = get_fullpath(fullpath,
13104315Swyllys 				    (char *)&dp->d_name);
13113089Swyllys 
13123089Swyllys 				if (fname == NULL) {
13133089Swyllys 					rv = KMF_ERR_MEMORY;
13143089Swyllys 					break;
13153089Swyllys 				}
13163089Swyllys 
13175051Swyllys 				rv = kmf_load_cert(kmfh, issuer, subject,
13185051Swyllys 				    serial, validity, fname, &certdata);
13193089Swyllys 
13203089Swyllys 				if (rv == KMF_ERR_CERT_NOT_FOUND) {
13213089Swyllys 					free(fname);
132211973Swyllys.ingersoll@sun.com 					kmf_free_data(&certdata);
13233089Swyllys 					rv = KMF_OK;
13243089Swyllys 					continue;
13253089Swyllys 				} else if (rv != KMF_OK) {
13263089Swyllys 					free(fname);
13273089Swyllys 					break;
13283089Swyllys 				}
13293089Swyllys 
13303089Swyllys 				if (unlink(fname) != 0) {
13313089Swyllys 					SET_SYS_ERROR(kmfh, errno);
13323089Swyllys 					rv = KMF_ERR_INTERNAL;
13333089Swyllys 					free(fname);
13343089Swyllys 					break;
13353089Swyllys 				}
13363089Swyllys 				free(fname);
133711973Swyllys.ingersoll@sun.com 				kmf_free_data(&certdata);
13383089Swyllys 			}
13393089Swyllys 		}
13403089Swyllys 		(void) closedir(dirp);
13413089Swyllys 	} else {
13423089Swyllys 		/* Just try to load a single certificate */
13435051Swyllys 		rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
13445051Swyllys 		    fullpath, &certdata);
13453089Swyllys 		if (rv == KMF_OK) {
13463089Swyllys 			if (unlink(fullpath) != 0) {
13473089Swyllys 				SET_SYS_ERROR(kmfh, errno);
13483089Swyllys 				rv = KMF_ERR_INTERNAL;
13493089Swyllys 			}
13503089Swyllys 		}
13513089Swyllys 	}
13523089Swyllys 
13533089Swyllys out:
13543089Swyllys 	if (fullpath != NULL)
13553089Swyllys 		free(fullpath);
13563089Swyllys 
135711973Swyllys.ingersoll@sun.com 	kmf_free_data(&certdata);
13583089Swyllys 
13593089Swyllys 	return (rv);
13603089Swyllys }
13613089Swyllys 
13623089Swyllys KMF_RETURN
OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle,KMF_KEY_HANDLE * key,KMF_DATA * keydata)13633089Swyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
13643089Swyllys 	KMF_DATA *keydata)
13653089Swyllys {
13663089Swyllys 	KMF_RETURN rv = KMF_OK;
13673089Swyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
13683089Swyllys 	int n;
13693089Swyllys 
13703089Swyllys 	if (key == NULL || keydata == NULL ||
13713089Swyllys 	    key->keyp == NULL)
13723089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
13733089Swyllys 
13743089Swyllys 	if (key->keyalg == KMF_RSA) {
13753089Swyllys 		RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
13763089Swyllys 
13773089Swyllys 		if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
13783089Swyllys 			SET_ERROR(kmfh, ERR_get_error());
13793089Swyllys 			return (KMF_ERR_ENCODING);
13803089Swyllys 		}
13813089Swyllys 		RSA_free(pubkey);
13823089Swyllys 	} else if (key->keyalg == KMF_DSA) {
13833089Swyllys 		DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
13843089Swyllys 
13853089Swyllys 		if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
13863089Swyllys 			SET_ERROR(kmfh, ERR_get_error());
13873089Swyllys 			return (KMF_ERR_ENCODING);
13883089Swyllys 		}
13893089Swyllys 		DSA_free(pubkey);
13903089Swyllys 	} else {
13914315Swyllys 		return (KMF_ERR_BAD_PARAMETER);
13923089Swyllys 	}
13933089Swyllys 	keydata->Length = n;
13943089Swyllys 
13953089Swyllys cleanup:
13963089Swyllys 	if (rv != KMF_OK) {
13973089Swyllys 		if (keydata->Data)
13983089Swyllys 			free(keydata->Data);
13993089Swyllys 		keydata->Data = NULL;
14003089Swyllys 		keydata->Length = 0;
14013089Swyllys 	}
14023089Swyllys 
14033089Swyllys 	return (rv);
14043089Swyllys }
14053089Swyllys 
14063089Swyllys static KMF_RETURN
ssl_write_key(KMF_HANDLE * kmfh,KMF_ENCODE_FORMAT format,BIO * out,KMF_CREDENTIAL * cred,EVP_PKEY * pkey,boolean_t private)14075051Swyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
14085051Swyllys 	KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
14093089Swyllys {
14103089Swyllys 	int rv = 0;
14113089Swyllys 	RSA *rsa;
14123089Swyllys 	DSA *dsa;
14133089Swyllys 
14145536Swyllys 	if (pkey == NULL || out == NULL)
14155536Swyllys 		return (KMF_ERR_BAD_PARAMETER);
14165536Swyllys 
14173089Swyllys 	switch (format) {
14185637Swyllys 		case KMF_FORMAT_RAWKEY:
14195637Swyllys 			/* same as ASN.1 */
14203089Swyllys 		case KMF_FORMAT_ASN1:
14213089Swyllys 			if (pkey->type == EVP_PKEY_RSA) {
14223089Swyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
14235051Swyllys 				if (private)
14245051Swyllys 					rv = i2d_RSAPrivateKey_bio(out, rsa);
14255051Swyllys 				else
14265051Swyllys 					rv = i2d_RSAPublicKey_bio(out, rsa);
14273089Swyllys 				RSA_free(rsa);
14283089Swyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
14293089Swyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
14303089Swyllys 				rv = i2d_DSAPrivateKey_bio(out, dsa);
14313089Swyllys 				DSA_free(dsa);
14323089Swyllys 			}
14333089Swyllys 			if (rv == 1) {
14343089Swyllys 				rv = KMF_OK;
14353089Swyllys 			} else {
14363089Swyllys 				SET_ERROR(kmfh, rv);
14373089Swyllys 			}
14383089Swyllys 			break;
14393089Swyllys 		case KMF_FORMAT_PEM:
14403089Swyllys 			if (pkey->type == EVP_PKEY_RSA) {
14413089Swyllys 				rsa = EVP_PKEY_get1_RSA(pkey);
14425051Swyllys 				if (private)
14435051Swyllys 					rv = PEM_write_bio_RSAPrivateKey(out,
14445051Swyllys 					    rsa, NULL, NULL, 0, NULL,
14455051Swyllys 					    (cred != NULL ? cred->cred : NULL));
14465051Swyllys 				else
14475051Swyllys 					rv = PEM_write_bio_RSAPublicKey(out,
14485051Swyllys 					    rsa);
14493089Swyllys 				RSA_free(rsa);
14503089Swyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
14513089Swyllys 				dsa = EVP_PKEY_get1_DSA(pkey);
14523089Swyllys 				rv = PEM_write_bio_DSAPrivateKey(out,
14535051Swyllys 				    dsa, NULL, NULL, 0, NULL,
14545051Swyllys 				    (cred != NULL ? cred->cred : NULL));
14553089Swyllys 				DSA_free(dsa);
14563089Swyllys 			}
14573089Swyllys 
14583089Swyllys 			if (rv == 1) {
14593089Swyllys 				rv = KMF_OK;
14603089Swyllys 			} else {
14613089Swyllys 				SET_ERROR(kmfh, rv);
14623089Swyllys 			}
14633089Swyllys 			break;
14643089Swyllys 
14653089Swyllys 		default:
14663089Swyllys 			rv = KMF_ERR_BAD_PARAMETER;
14673089Swyllys 	}
14683089Swyllys 
14693089Swyllys 	return (rv);
14703089Swyllys }
14713089Swyllys 
14723089Swyllys KMF_RETURN
OpenSSL_CreateKeypair(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)14735051Swyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
14745051Swyllys 	KMF_ATTRIBUTE *attrlist)
14753089Swyllys {
14763089Swyllys 	KMF_RETURN rv = KMF_OK;
14773089Swyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
14783089Swyllys 	uint32_t eValue = 0x010001;
14793089Swyllys 	RSA *sslPrivKey = NULL;
14803089Swyllys 	DSA *sslDSAKey = NULL;
14813089Swyllys 	EVP_PKEY *eprikey = NULL;
14823089Swyllys 	EVP_PKEY *epubkey = NULL;
14833089Swyllys 	BIO *out = NULL;
14845051Swyllys 	KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
14855051Swyllys 	uint32_t keylen = 1024;
14865051Swyllys 	uint32_t keylen_size = sizeof (uint32_t);
14875051Swyllys 	boolean_t storekey = TRUE;
14885051Swyllys 	KMF_KEY_ALG keytype = KMF_RSA;
14895051Swyllys 
14905051Swyllys 	rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
14915051Swyllys 	    &storekey, NULL);
14925051Swyllys 	if (rv != KMF_OK) {
14935051Swyllys 		/* "storekey" is optional. Default is TRUE */
14945051Swyllys 		rv = KMF_OK;
14955051Swyllys 	}
14965051Swyllys 
14975051Swyllys 	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
14985051Swyllys 	    (void *)&keytype, NULL);
14995051Swyllys 	if (rv != KMF_OK)
15005051Swyllys 		/* keytype is optional.  KMF_RSA is default */
15015051Swyllys 		rv = KMF_OK;
15025051Swyllys 
15035051Swyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
15045051Swyllys 	if (pubkey == NULL)
15053089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
15065051Swyllys 
15075051Swyllys 	privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
15085051Swyllys 	if (privkey == NULL)
15093089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
15103089Swyllys 
15115051Swyllys 	(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
15125051Swyllys 	(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
15133089Swyllys 
15143089Swyllys 	eprikey = EVP_PKEY_new();
15153089Swyllys 	if (eprikey == NULL) {
15163089Swyllys 		SET_ERROR(kmfh, ERR_get_error());
15173089Swyllys 		rv = KMF_ERR_KEYGEN_FAILED;
15183089Swyllys 		goto cleanup;
15193089Swyllys 	}
15203089Swyllys 	epubkey = EVP_PKEY_new();
15213089Swyllys 	if (epubkey == NULL) {
15223089Swyllys 		SET_ERROR(kmfh, ERR_get_error());
15233089Swyllys 		rv = KMF_ERR_KEYGEN_FAILED;
15243089Swyllys 		goto cleanup;
15253089Swyllys 	}
15265051Swyllys 	if (keytype == KMF_RSA) {
15275051Swyllys 		KMF_BIGINT *rsaexp = NULL;
15285051Swyllys 
15295051Swyllys 		rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
15305051Swyllys 		if (rsaexp != NULL) {
15315051Swyllys 			if (rsaexp->len > 0 &&
15325051Swyllys 			    rsaexp->len <= sizeof (eValue) &&
15335051Swyllys 			    rsaexp->val != NULL) {
153411673Sopensolaris@drydog.com 				/* LINTED E_BAD_PTR_CAST_ALIGN */
15355051Swyllys 				eValue = *(uint32_t *)rsaexp->val;
15365051Swyllys 			} else {
15375051Swyllys 				rv = KMF_ERR_BAD_PARAMETER;
15385051Swyllys 				goto cleanup;
15395051Swyllys 			}
15405051Swyllys 		} else {
15415051Swyllys 			/* RSA Exponent is optional. Default is 0x10001 */
15425051Swyllys 			rv = KMF_OK;
15435051Swyllys 		}
15445051Swyllys 
15455051Swyllys 		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
15465051Swyllys 		    &keylen, &keylen_size);
15475051Swyllys 		if (rv == KMF_ERR_ATTR_NOT_FOUND)
15485051Swyllys 			/* keylen is optional, default is 1024 */
15495051Swyllys 			rv = KMF_OK;
15505051Swyllys 		if (rv != KMF_OK) {
15515051Swyllys 			rv = KMF_ERR_BAD_PARAMETER;
15525051Swyllys 			goto cleanup;
15535051Swyllys 		}
15545051Swyllys 
15555051Swyllys 		sslPrivKey = RSA_generate_key(keylen, eValue, NULL, NULL);
15563089Swyllys 		if (sslPrivKey == NULL) {
15573089Swyllys 			SET_ERROR(kmfh, ERR_get_error());
15583089Swyllys 			rv = KMF_ERR_KEYGEN_FAILED;
15593089Swyllys 		} else {
15605051Swyllys 			(void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
15615051Swyllys 			privkey->kstype = KMF_KEYSTORE_OPENSSL;
15625051Swyllys 			privkey->keyalg = KMF_RSA;
15635051Swyllys 			privkey->keyclass = KMF_ASYM_PRI;
15645051Swyllys 			privkey->israw = FALSE;
15655051Swyllys 			privkey->keyp = (void *)eprikey;
15665051Swyllys 
15673089Swyllys 			/* OpenSSL derives the public key from the private */
15685051Swyllys 			(void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
15695051Swyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
15705051Swyllys 			pubkey->keyalg = KMF_RSA;
15715051Swyllys 			pubkey->israw = FALSE;
15725051Swyllys 			pubkey->keyclass = KMF_ASYM_PUB;
15735051Swyllys 			pubkey->keyp = (void *)epubkey;
15743089Swyllys 		}
15755051Swyllys 	} else if (keytype == KMF_DSA) {
15765051Swyllys 		DSA *dp;
15773089Swyllys 		sslDSAKey = DSA_new();
15783089Swyllys 		if (sslDSAKey == NULL) {
15793089Swyllys 			SET_ERROR(kmfh, ERR_get_error());
15803089Swyllys 			return (KMF_ERR_MEMORY);
15813089Swyllys 		}
15823089Swyllys 
15833089Swyllys 		if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) ==
15844315Swyllys 		    NULL) {
15853089Swyllys 			SET_ERROR(kmfh, ERR_get_error());
15863089Swyllys 			rv = KMF_ERR_KEYGEN_FAILED;
15873089Swyllys 			goto cleanup;
15883089Swyllys 		}
15893089Swyllys 		if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) ==
15904315Swyllys 		    NULL) {
15913089Swyllys 			SET_ERROR(kmfh, ERR_get_error());
15923089Swyllys 			rv = KMF_ERR_KEYGEN_FAILED;
15933089Swyllys 			goto cleanup;
15943089Swyllys 		}
15953089Swyllys 		if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) ==
15964315Swyllys 		    NULL) {
15973089Swyllys 			SET_ERROR(kmfh, ERR_get_error());
15983089Swyllys 			rv = KMF_ERR_KEYGEN_FAILED;
15993089Swyllys 			goto cleanup;
16003089Swyllys 		}
16013089Swyllys 
16023089Swyllys 		if (!DSA_generate_key(sslDSAKey)) {
16033089Swyllys 			SET_ERROR(kmfh, ERR_get_error());
16043089Swyllys 			rv = KMF_ERR_KEYGEN_FAILED;
16053089Swyllys 			goto cleanup;
16063089Swyllys 		}
16073089Swyllys 
16085051Swyllys 		privkey->kstype = KMF_KEYSTORE_OPENSSL;
16095051Swyllys 		privkey->keyalg = KMF_DSA;
16105051Swyllys 		privkey->keyclass = KMF_ASYM_PRI;
16115051Swyllys 		privkey->israw = FALSE;
16125051Swyllys 		if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
16135051Swyllys 			privkey->keyp = (void *)eprikey;
16145051Swyllys 		} else {
16155051Swyllys 			SET_ERROR(kmfh, ERR_get_error());
16165051Swyllys 			rv = KMF_ERR_KEYGEN_FAILED;
16175051Swyllys 			goto cleanup;
16185051Swyllys 		}
16195051Swyllys 		dp = DSA_new();
16205051Swyllys 		/* Make a copy for the public key */
16215051Swyllys 		if (dp != NULL) {
16225051Swyllys 			if ((dp->p = BN_new()) == NULL) {
16235051Swyllys 				SET_ERROR(kmfh, ERR_get_error());
16245051Swyllys 				rv = KMF_ERR_MEMORY;
16255051Swyllys 				DSA_free(dp);
16265051Swyllys 				goto cleanup;
16275051Swyllys 			}
16285051Swyllys 			if ((dp->q = BN_new()) == NULL) {
16295051Swyllys 				SET_ERROR(kmfh, ERR_get_error());
16305051Swyllys 				rv = KMF_ERR_MEMORY;
16315051Swyllys 				BN_free(dp->p);
16325051Swyllys 				DSA_free(dp);
16335051Swyllys 				goto cleanup;
16345051Swyllys 			}
16355051Swyllys 			if ((dp->g = BN_new()) == NULL) {
16365051Swyllys 				SET_ERROR(kmfh, ERR_get_error());
16375051Swyllys 				rv = KMF_ERR_MEMORY;
16385051Swyllys 				BN_free(dp->q);
16395051Swyllys 				BN_free(dp->p);
16405051Swyllys 				DSA_free(dp);
16415051Swyllys 				goto cleanup;
16425051Swyllys 			}
16435051Swyllys 			if ((dp->pub_key = BN_new()) == NULL) {
16445051Swyllys 				SET_ERROR(kmfh, ERR_get_error());
16455051Swyllys 				rv = KMF_ERR_MEMORY;
16465051Swyllys 				BN_free(dp->q);
16475051Swyllys 				BN_free(dp->p);
16485051Swyllys 				BN_free(dp->g);
16495051Swyllys 				DSA_free(dp);
16505051Swyllys 				goto cleanup;
16515051Swyllys 			}
16525051Swyllys 			(void) BN_copy(dp->p, sslDSAKey->p);
16535051Swyllys 			(void) BN_copy(dp->q, sslDSAKey->q);
16545051Swyllys 			(void) BN_copy(dp->g, sslDSAKey->g);
16555051Swyllys 			(void) BN_copy(dp->pub_key, sslDSAKey->pub_key);
16565051Swyllys 
16575051Swyllys 			pubkey->kstype = KMF_KEYSTORE_OPENSSL;
16585051Swyllys 			pubkey->keyalg = KMF_DSA;
16595051Swyllys 			pubkey->keyclass = KMF_ASYM_PUB;
16605051Swyllys 			pubkey->israw = FALSE;
16615051Swyllys 
16625051Swyllys 			if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
16635051Swyllys 				pubkey->keyp = (void *)epubkey;
16643089Swyllys 			} else {
16653089Swyllys 				SET_ERROR(kmfh, ERR_get_error());
16663089Swyllys 				rv = KMF_ERR_KEYGEN_FAILED;
16673089Swyllys 				goto cleanup;
16683089Swyllys 			}
16693089Swyllys 		}
16703089Swyllys 	}
16713089Swyllys 
16723089Swyllys 	if (rv != KMF_OK) {
16733089Swyllys 		goto cleanup;
16743089Swyllys 	}
16753089Swyllys 
16765051Swyllys 	if (storekey) {
16775051Swyllys 		KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
16785051Swyllys 		int i = 0;
16795051Swyllys 		char *keyfile = NULL, *dirpath = NULL;
16805051Swyllys 		KMF_ENCODE_FORMAT format;
16815051Swyllys 		/*
16825051Swyllys 		 * Construct a new attribute arrray and call openssl_store_key
16835051Swyllys 		 */
16845051Swyllys 		kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
16855051Swyllys 		    privkey, sizeof (privkey));
16865051Swyllys 		i++;
16875051Swyllys 
16885051Swyllys 		dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
16895051Swyllys 		if (dirpath != NULL) {
16905051Swyllys 			storeattrs[i].type = KMF_DIRPATH_ATTR;
16915051Swyllys 			storeattrs[i].pValue = dirpath;
16925051Swyllys 			storeattrs[i].valueLen = strlen(dirpath);
16935051Swyllys 			i++;
16945051Swyllys 		} else {
16955051Swyllys 			rv = KMF_OK; /* DIRPATH is optional */
16965051Swyllys 		}
16975051Swyllys 		keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
16985051Swyllys 		    attrlist, numattr);
16995051Swyllys 		if (keyfile != NULL) {
17005051Swyllys 			storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
17015051Swyllys 			storeattrs[i].pValue = keyfile;
17025051Swyllys 			storeattrs[i].valueLen = strlen(keyfile);
17035051Swyllys 			i++;
17045051Swyllys 		} else {
17055051Swyllys 			goto cleanup; /* KEYFILE is required */
17065051Swyllys 		}
17075051Swyllys 		rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
17085051Swyllys 		    (void *)&format, NULL);
17095051Swyllys 		if (rv == KMF_OK) {
17105051Swyllys 			storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
17115051Swyllys 			storeattrs[i].pValue = &format;
17125051Swyllys 			storeattrs[i].valueLen = sizeof (format);
17135051Swyllys 			i++;
17145051Swyllys 		}
17155051Swyllys 
17165051Swyllys 		rv = OpenSSL_StoreKey(handle, i, storeattrs);
17175051Swyllys 	}
17183089Swyllys 
17193089Swyllys cleanup:
17203089Swyllys 	if (rv != KMF_OK) {
17213089Swyllys 		if (eprikey != NULL)
17223089Swyllys 			EVP_PKEY_free(eprikey);
17233089Swyllys 
17243089Swyllys 		if (epubkey != NULL)
17253089Swyllys 			EVP_PKEY_free(epubkey);
17263089Swyllys 
17273089Swyllys 		if (pubkey->keylabel) {
17283089Swyllys 			free(pubkey->keylabel);
17293089Swyllys 			pubkey->keylabel = NULL;
17303089Swyllys 		}
17313089Swyllys 
17323089Swyllys 		if (privkey->keylabel) {
17333089Swyllys 			free(privkey->keylabel);
17343089Swyllys 			privkey->keylabel = NULL;
17353089Swyllys 		}
17363089Swyllys 
17373089Swyllys 		pubkey->keyp = NULL;
17383089Swyllys 		privkey->keyp = NULL;
17393089Swyllys 	}
17403089Swyllys 
17413089Swyllys 	if (sslPrivKey)
17423089Swyllys 		RSA_free(sslPrivKey);
17433089Swyllys 
17443089Swyllys 	if (sslDSAKey)
17453089Swyllys 		DSA_free(sslDSAKey);
17463089Swyllys 
17473089Swyllys 	if (out != NULL)
17483089Swyllys 		(void) BIO_free(out);
17493089Swyllys 
17503089Swyllys 	return (rv);
17513089Swyllys }
17523089Swyllys 
175311973Swyllys.ingersoll@sun.com /*
175411973Swyllys.ingersoll@sun.com  * Make sure the BN conversion is properly padded with 0x00
175511973Swyllys.ingersoll@sun.com  * bytes.  If not, signature verification for DSA signatures
175611973Swyllys.ingersoll@sun.com  * may fail in the case where the bignum value does not use
175711973Swyllys.ingersoll@sun.com  * all of the bits.
175811973Swyllys.ingersoll@sun.com  */
175911973Swyllys.ingersoll@sun.com static int
fixbnlen(BIGNUM * bn,unsigned char * buf,int len)176011973Swyllys.ingersoll@sun.com fixbnlen(BIGNUM *bn, unsigned char *buf, int len) {
176111973Swyllys.ingersoll@sun.com 	int bytes = len - BN_num_bytes(bn);
1762*12234Swyllys.ingersoll@sun.com 
1763*12234Swyllys.ingersoll@sun.com 	/* prepend with leading 0x00 if necessary */
176411973Swyllys.ingersoll@sun.com 	while (bytes-- > 0)
176511973Swyllys.ingersoll@sun.com 		*buf++ = 0;
176611973Swyllys.ingersoll@sun.com 
1767*12234Swyllys.ingersoll@sun.com 	(void) BN_bn2bin(bn, buf);
1768*12234Swyllys.ingersoll@sun.com 	/*
1769*12234Swyllys.ingersoll@sun.com 	 * Return the desired length since we prepended it
1770*12234Swyllys.ingersoll@sun.com 	 * with the necessary 0x00 padding.
1771*12234Swyllys.ingersoll@sun.com 	 */
1772*12234Swyllys.ingersoll@sun.com 	return (len);
177311973Swyllys.ingersoll@sun.com }
177411973Swyllys.ingersoll@sun.com 
17753089Swyllys KMF_RETURN
OpenSSL_SignData(KMF_HANDLE_T handle,KMF_KEY_HANDLE * key,KMF_OID * AlgOID,KMF_DATA * tobesigned,KMF_DATA * output)17763089Swyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
17773089Swyllys 	KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
17783089Swyllys {
17793089Swyllys 	KMF_RETURN ret = KMF_OK;
17803089Swyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
17813089Swyllys 	KMF_ALGORITHM_INDEX		AlgId;
17823089Swyllys 	EVP_MD_CTX ctx;
17833089Swyllys 	const EVP_MD *md;
17843754Swyllys 
17853089Swyllys 	if (key == NULL || AlgOID == NULL ||
17864315Swyllys 	    tobesigned == NULL || output == NULL ||
17874315Swyllys 	    tobesigned->Data == NULL ||
17884315Swyllys 	    output->Data == NULL)
17893089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
17903089Swyllys 
17913089Swyllys 	/* Map the OID to an OpenSSL algorithm */
17925051Swyllys 	AlgId = x509_algoid_to_algid(AlgOID);
17933089Swyllys 	if (AlgId == KMF_ALGID_NONE)
179411973Swyllys.ingersoll@sun.com 		return (KMF_ERR_BAD_ALGORITHM);
17953089Swyllys 
17963089Swyllys 	if (key->keyalg == KMF_RSA) {
17973089Swyllys 		EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
17983089Swyllys 		uchar_t *p;
17993754Swyllys 		int len;
18003089Swyllys 		if (AlgId == KMF_ALGID_MD5WithRSA)
18013089Swyllys 			md = EVP_md5();
18023089Swyllys 		else if (AlgId == KMF_ALGID_MD2WithRSA)
18033089Swyllys 			md = EVP_md2();
18043089Swyllys 		else if (AlgId == KMF_ALGID_SHA1WithRSA)
18053089Swyllys 			md = EVP_sha1();
180611973Swyllys.ingersoll@sun.com 		else if (AlgId == KMF_ALGID_SHA256WithRSA)
180711973Swyllys.ingersoll@sun.com 			md = EVP_sha256();
180811973Swyllys.ingersoll@sun.com 		else if (AlgId == KMF_ALGID_SHA384WithRSA)
180911973Swyllys.ingersoll@sun.com 			md = EVP_sha384();
181011973Swyllys.ingersoll@sun.com 		else if (AlgId == KMF_ALGID_SHA512WithRSA)
181111973Swyllys.ingersoll@sun.com 			md = EVP_sha512();
18123754Swyllys 		else if (AlgId == KMF_ALGID_RSA)
18133754Swyllys 			md = NULL;
18143089Swyllys 		else
181511973Swyllys.ingersoll@sun.com 			return (KMF_ERR_BAD_ALGORITHM);
18163089Swyllys 
18173754Swyllys 		if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
18183754Swyllys 			RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
18193754Swyllys 
18203754Swyllys 			p = output->Data;
18213754Swyllys 			if ((len = RSA_private_encrypt(tobesigned->Length,
18224315Swyllys 			    tobesigned->Data, p, rsa,
18234315Swyllys 			    RSA_PKCS1_PADDING)) <= 0) {
18243754Swyllys 				SET_ERROR(kmfh, ERR_get_error());
18253754Swyllys 				ret = KMF_ERR_INTERNAL;
18263754Swyllys 			}
18273754Swyllys 			output->Length = len;
18283754Swyllys 		} else {
18293754Swyllys 			(void) EVP_MD_CTX_init(&ctx);
18303754Swyllys 			(void) EVP_SignInit_ex(&ctx, md, NULL);
18313754Swyllys 			(void) EVP_SignUpdate(&ctx, tobesigned->Data,
18324315Swyllys 			    (uint32_t)tobesigned->Length);
18333754Swyllys 			len = (uint32_t)output->Length;
18343754Swyllys 			p = output->Data;
18353754Swyllys 			if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) {
18363754Swyllys 				SET_ERROR(kmfh, ERR_get_error());
18373754Swyllys 				len = 0;
18383754Swyllys 				ret = KMF_ERR_INTERNAL;
18393754Swyllys 			}
18403754Swyllys 			output->Length = len;
18413754Swyllys 			(void) EVP_MD_CTX_cleanup(&ctx);
18423089Swyllys 		}
18433089Swyllys 	} else if (key->keyalg == KMF_DSA) {
18443089Swyllys 		DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
18453089Swyllys 
18463089Swyllys 		uchar_t hash[EVP_MAX_MD_SIZE];
18473089Swyllys 		uint32_t hashlen;
18483089Swyllys 		DSA_SIG *dsasig;
18493089Swyllys 
185011973Swyllys.ingersoll@sun.com 		if (AlgId == KMF_ALGID_DSA ||
185111973Swyllys.ingersoll@sun.com 		    AlgId == KMF_ALGID_SHA1WithDSA)
185211973Swyllys.ingersoll@sun.com 			md = EVP_sha1();
185311973Swyllys.ingersoll@sun.com 		else if (AlgId == KMF_ALGID_SHA256WithDSA)
185411973Swyllys.ingersoll@sun.com 			md = EVP_sha256();
185511973Swyllys.ingersoll@sun.com 		else /* Bad algorithm */
185611973Swyllys.ingersoll@sun.com 			return (KMF_ERR_BAD_ALGORITHM);
185711973Swyllys.ingersoll@sun.com 
18583089Swyllys 		/*
18593089Swyllys 		 * OpenSSL EVP_Sign operation automatically converts to
18603089Swyllys 		 * ASN.1 output so we do the operations separately so we
18613089Swyllys 		 * are assured of NOT getting ASN.1 output returned.
18623089Swyllys 		 * KMF does not want ASN.1 encoded results because
18633089Swyllys 		 * not all mechanisms return ASN.1 encodings (PKCS#11
18643089Swyllys 		 * and NSS return raw signature data).
18653089Swyllys 		 */
18663089Swyllys 		EVP_MD_CTX_init(&ctx);
18673089Swyllys 		(void) EVP_DigestInit_ex(&ctx, md, NULL);
18683089Swyllys 		(void) EVP_DigestUpdate(&ctx, tobesigned->Data,
18694315Swyllys 		    tobesigned->Length);
18703089Swyllys 		(void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
187111973Swyllys.ingersoll@sun.com 
187211973Swyllys.ingersoll@sun.com 		/* Only sign first 20 bytes for SHA2 */
187311973Swyllys.ingersoll@sun.com 		if (AlgId == KMF_ALGID_SHA256WithDSA)
187411973Swyllys.ingersoll@sun.com 			hashlen = 20;
18753089Swyllys 		dsasig = DSA_do_sign(hash, hashlen, dsa);
18763089Swyllys 		if (dsasig != NULL) {
18773089Swyllys 			int i;
187811973Swyllys.ingersoll@sun.com 			output->Length = i = fixbnlen(dsasig->r, output->Data,
187911973Swyllys.ingersoll@sun.com 			    hashlen);
1880*12234Swyllys.ingersoll@sun.com 
188111973Swyllys.ingersoll@sun.com 			output->Length += fixbnlen(dsasig->s, &output->Data[i],
188211973Swyllys.ingersoll@sun.com 			    hashlen);
1883*12234Swyllys.ingersoll@sun.com 
18843089Swyllys 			DSA_SIG_free(dsasig);
18853089Swyllys 		} else {
18863089Swyllys 			SET_ERROR(kmfh, ERR_get_error());
18873089Swyllys 		}
188811973Swyllys.ingersoll@sun.com 		(void) EVP_MD_CTX_cleanup(&ctx);
18893089Swyllys 	} else {
18903089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
18913089Swyllys 	}
18923089Swyllys cleanup:
18933089Swyllys 	return (ret);
18943089Swyllys }
18953089Swyllys 
18963089Swyllys KMF_RETURN
18973089Swyllys /*ARGSUSED*/
OpenSSL_DeleteKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)18985051Swyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle,
18995051Swyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
19003089Swyllys {
19013089Swyllys 	KMF_RETURN rv = KMF_OK;
19025051Swyllys 	KMF_KEY_HANDLE *key;
19035051Swyllys 	boolean_t destroy = B_TRUE;
19045051Swyllys 
19055051Swyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
19063089Swyllys 	if (key == NULL || key->keyp == NULL)
19073089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
19083089Swyllys 
19095051Swyllys 	rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
19105051Swyllys 	    (void *)&destroy, NULL);
19115051Swyllys 	if (rv != KMF_OK) {
19125051Swyllys 		/* "destroy" is optional. Default is TRUE */
19135051Swyllys 		rv = KMF_OK;
19145051Swyllys 	}
19155051Swyllys 
19163089Swyllys 	if (key->keyclass != KMF_ASYM_PUB &&
19174315Swyllys 	    key->keyclass != KMF_ASYM_PRI &&
19184315Swyllys 	    key->keyclass != KMF_SYMMETRIC)
19193089Swyllys 		return (KMF_ERR_BAD_KEY_CLASS);
19203089Swyllys 
19213089Swyllys 	if (key->keyclass == KMF_SYMMETRIC) {
19225051Swyllys 		kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
19233089Swyllys 		key->keyp = NULL;
19243089Swyllys 	} else {
19253089Swyllys 		if (key->keyp != NULL) {
19263089Swyllys 			EVP_PKEY_free(key->keyp);
19273089Swyllys 			key->keyp = NULL;
19283089Swyllys 		}
19293089Swyllys 	}
19303089Swyllys 
19313089Swyllys 	if (key->keylabel != NULL) {
19323089Swyllys 		EVP_PKEY *pkey = NULL;
19333089Swyllys 		/* If the file exists, make sure it is a proper key. */
19343089Swyllys 		pkey = openssl_load_key(handle, key->keylabel);
19353089Swyllys 		if (pkey == NULL) {
19365536Swyllys 			if (key->keylabel != NULL) {
19375536Swyllys 				free(key->keylabel);
19385536Swyllys 				key->keylabel = NULL;
19395536Swyllys 			}
19403089Swyllys 			return (KMF_ERR_KEY_NOT_FOUND);
19413089Swyllys 		}
19423089Swyllys 		EVP_PKEY_free(pkey);
19433089Swyllys 
19443089Swyllys 		if (destroy) {
19453089Swyllys 			if (unlink(key->keylabel) != 0) {
19463089Swyllys 				KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
19473089Swyllys 				SET_SYS_ERROR(kmfh, errno);
19483089Swyllys 				rv = KMF_ERR_INTERNAL;
19493089Swyllys 			}
19503089Swyllys 		}
19513089Swyllys 		if (key->keylabel != NULL) {
19523089Swyllys 			free(key->keylabel);
19533089Swyllys 			key->keylabel = NULL;
19543089Swyllys 		}
19553089Swyllys 	}
19563089Swyllys 	return (rv);
19573089Swyllys }
19583089Swyllys 
19593089Swyllys KMF_RETURN
OpenSSL_GetErrorString(KMF_HANDLE_T handle,char ** msgstr)19603089Swyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
19613089Swyllys {
19623089Swyllys 	KMF_RETURN ret = KMF_OK;
19633089Swyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
19643089Swyllys 	char str[256];	/* OpenSSL needs at least 120 byte buffer */
19653089Swyllys 
19663089Swyllys 	ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
19673089Swyllys 	if (strlen(str)) {
19683089Swyllys 		*msgstr = (char *)strdup(str);
19693089Swyllys 		if ((*msgstr) == NULL)
19703089Swyllys 			ret = KMF_ERR_MEMORY;
19713089Swyllys 	} else {
19723089Swyllys 		*msgstr = NULL;
19733089Swyllys 	}
19743089Swyllys 
19753089Swyllys 	return (ret);
19763089Swyllys }
19773089Swyllys 
19783089Swyllys static int
ext2NID(int kmfext)19793089Swyllys ext2NID(int kmfext)
19803089Swyllys {
19813089Swyllys 	switch (kmfext) {
19823089Swyllys 		case KMF_X509_EXT_KEY_USAGE:
19833089Swyllys 			return (NID_key_usage);
19843089Swyllys 		case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
19853089Swyllys 			return (NID_private_key_usage_period);
19863089Swyllys 		case KMF_X509_EXT_CERT_POLICIES:
19873089Swyllys 			return (NID_certificate_policies);
19883089Swyllys 		case KMF_X509_EXT_SUBJ_ALTNAME:
19893089Swyllys 			return (NID_subject_alt_name);
19903089Swyllys 		case KMF_X509_EXT_ISSUER_ALTNAME:
19913089Swyllys 			return (NID_issuer_alt_name);
19923089Swyllys 		case KMF_X509_EXT_BASIC_CONSTRAINTS:
19933089Swyllys 			return (NID_basic_constraints);
19943089Swyllys 		case KMF_X509_EXT_EXT_KEY_USAGE:
19953089Swyllys 			return (NID_ext_key_usage);
19963089Swyllys 		case KMF_X509_EXT_AUTH_KEY_ID:
19973089Swyllys 			return (NID_authority_key_identifier);
19983089Swyllys 		case KMF_X509_EXT_CRL_DIST_POINTS:
19993089Swyllys 			return (NID_crl_distribution_points);
20003089Swyllys 		case KMF_X509_EXT_SUBJ_KEY_ID:
20013089Swyllys 			return (NID_subject_key_identifier);
20023089Swyllys 		case KMF_X509_EXT_POLICY_MAPPINGS:
20033089Swyllys 			return (OBJ_sn2nid("policyMappings"));
20043089Swyllys 		case KMF_X509_EXT_NAME_CONSTRAINTS:
20053089Swyllys 			return (OBJ_sn2nid("nameConstraints"));
20063089Swyllys 		case KMF_X509_EXT_POLICY_CONSTRAINTS:
20073089Swyllys 			return (OBJ_sn2nid("policyConstraints"));
20083089Swyllys 		case KMF_X509_EXT_INHIBIT_ANY_POLICY:
20093089Swyllys 			return (OBJ_sn2nid("inhibitAnyPolicy"));
20103089Swyllys 		case KMF_X509_EXT_FRESHEST_CRL:
20113089Swyllys 			return (OBJ_sn2nid("freshestCRL"));
20123089Swyllys 		default:
20133089Swyllys 			return (NID_undef);
20143089Swyllys 	}
20153089Swyllys }
20163089Swyllys 
20173089Swyllys KMF_RETURN
OpenSSL_CertGetPrintable(KMF_HANDLE_T handle,const KMF_DATA * pcert,KMF_PRINTABLE_ITEM flag,char * resultStr)20183089Swyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
20193089Swyllys 	KMF_PRINTABLE_ITEM flag, char *resultStr)
20203089Swyllys {
20213089Swyllys 	KMF_RETURN ret = KMF_OK;
20223089Swyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
20233089Swyllys 	X509 *xcert = NULL;
20243089Swyllys 	unsigned char *outbuf = NULL;
20253089Swyllys 	unsigned char *outbuf_p;
20263089Swyllys 	char *tmpstr = NULL;
20273089Swyllys 	int j;
20283089Swyllys 	int ext_index, nid, len;
20293089Swyllys 	BIO *mem = NULL;
20303089Swyllys 	STACK *emlst = NULL;
20313089Swyllys 	X509_EXTENSION *ex;
20323089Swyllys 	X509_CINF *ci;
20333089Swyllys 
20343089Swyllys 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
20353089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
20363089Swyllys 	}
20373089Swyllys 
20383089Swyllys 	/* copy cert data to outbuf */
20393089Swyllys 	outbuf = malloc(pcert->Length);
20403089Swyllys 	if (outbuf == NULL) {
20413089Swyllys 		return (KMF_ERR_MEMORY);
20423089Swyllys 	}
20433089Swyllys 	(void) memcpy(outbuf, pcert->Data, pcert->Length);
20443089Swyllys 
20453089Swyllys 	outbuf_p = outbuf; /* use a temp pointer; required by openssl */
20463089Swyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
20473089Swyllys 	if (xcert == NULL) {
20483089Swyllys 		SET_ERROR(kmfh, ERR_get_error());
20493089Swyllys 		ret = KMF_ERR_ENCODING;
20503089Swyllys 		goto out;
20513089Swyllys 	}
20523089Swyllys 
20533089Swyllys 	mem = BIO_new(BIO_s_mem());
20543089Swyllys 	if (mem == NULL) {
20553089Swyllys 		SET_ERROR(kmfh, ERR_get_error());
20563089Swyllys 		ret = KMF_ERR_MEMORY;
20573089Swyllys 		goto out;
20583089Swyllys 	}
20593089Swyllys 
20603089Swyllys 	switch (flag) {
20613089Swyllys 	case KMF_CERT_ISSUER:
20623089Swyllys 		(void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
20633089Swyllys 		    XN_FLAG_SEP_CPLUS_SPC);
20643089Swyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
20653089Swyllys 		break;
20663089Swyllys 
20673089Swyllys 	case KMF_CERT_SUBJECT:
20683089Swyllys 		(void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
20693089Swyllys 		    XN_FLAG_SEP_CPLUS_SPC);
20703089Swyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
20713089Swyllys 		break;
20723089Swyllys 
20733089Swyllys 	case KMF_CERT_VERSION:
20743089Swyllys 		tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version);
20753089Swyllys 		(void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN);
20763089Swyllys 		OPENSSL_free(tmpstr);
20773089Swyllys 		len = strlen(resultStr);
20783089Swyllys 		break;
20793089Swyllys 
20803089Swyllys 	case KMF_CERT_SERIALNUM:
20813089Swyllys 		if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
20823089Swyllys 			(void) strcpy(resultStr, "0x");
20833089Swyllys 			len = BIO_gets(mem, &resultStr[2],
20844315Swyllys 			    KMF_CERT_PRINTABLE_LEN - 2);
20853089Swyllys 		}
20863089Swyllys 		break;
20873089Swyllys 
20883089Swyllys 	case KMF_CERT_NOTBEFORE:
20893089Swyllys 		(void) ASN1_TIME_print(mem, X509_get_notBefore(xcert));
20903089Swyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
20913089Swyllys 		break;
20923089Swyllys 
20933089Swyllys 	case KMF_CERT_NOTAFTER:
20943089Swyllys 		(void) ASN1_TIME_print(mem, X509_get_notAfter(xcert));
20953089Swyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
20963089Swyllys 		break;
20973089Swyllys 
20983089Swyllys 	case KMF_CERT_PUBKEY_DATA:
20993089Swyllys 		{
21003089Swyllys 			EVP_PKEY *pkey = X509_get_pubkey(xcert);
21013089Swyllys 			if (pkey == NULL) {
21023089Swyllys 				SET_ERROR(kmfh, ERR_get_error());
21033089Swyllys 				ret = KMF_ERR_ENCODING;
21043089Swyllys 				goto out;
21053089Swyllys 			}
21063089Swyllys 
21073089Swyllys 			if (pkey->type == EVP_PKEY_RSA) {
21083089Swyllys 				(void) BIO_printf(mem,
21094315Swyllys 				    "RSA Public Key: (%d bit)\n",
21104315Swyllys 				    BN_num_bits(pkey->pkey.rsa->n));
21113089Swyllys 				(void) RSA_print(mem, pkey->pkey.rsa, 0);
21123089Swyllys 			} else if (pkey->type == EVP_PKEY_DSA) {
21133089Swyllys 				(void) BIO_printf(mem,
21144315Swyllys 				    "%12sDSA Public Key:\n", "");
21153089Swyllys 				(void) DSA_print(mem, pkey->pkey.dsa, 0);
21163089Swyllys 			} else {
21173089Swyllys 				(void) BIO_printf(mem,
21184315Swyllys 				    "%12sUnknown Public Key:\n", "");
21193089Swyllys 			}
21203089Swyllys 			(void) BIO_printf(mem, "\n");
21213089Swyllys 			EVP_PKEY_free(pkey);
21223089Swyllys 		}
21233089Swyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
21243089Swyllys 		break;
21253089Swyllys 	case KMF_CERT_SIGNATURE_ALG:
21263089Swyllys 	case KMF_CERT_PUBKEY_ALG:
21273089Swyllys 		if (flag == KMF_CERT_SIGNATURE_ALG) {
21283089Swyllys 			len = i2a_ASN1_OBJECT(mem,
21294315Swyllys 			    xcert->sig_alg->algorithm);
21303089Swyllys 		} else {
21313089Swyllys 			len = i2a_ASN1_OBJECT(mem,
21324315Swyllys 			    xcert->cert_info->key->algor->algorithm);
21333089Swyllys 		}
21343089Swyllys 
21353089Swyllys 		if (len > 0) {
21363089Swyllys 			len = BIO_read(mem, resultStr,
21374315Swyllys 			    KMF_CERT_PRINTABLE_LEN);
21383089Swyllys 		}
21393089Swyllys 		break;
21403089Swyllys 
21413089Swyllys 	case KMF_CERT_EMAIL:
21423089Swyllys 		emlst = X509_get1_email(xcert);
21433089Swyllys 		for (j = 0; j < sk_num(emlst); j++)
21443089Swyllys 			(void) BIO_printf(mem, "%s\n", sk_value(emlst, j));
21453089Swyllys 
21463089Swyllys 		len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
21473089Swyllys 		X509_email_free(emlst);
21483089Swyllys 		break;
21493089Swyllys 	case KMF_X509_EXT_ISSUER_ALTNAME:
21503089Swyllys 	case KMF_X509_EXT_SUBJ_ALTNAME:
21513089Swyllys 	case KMF_X509_EXT_KEY_USAGE:
21523089Swyllys 	case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
21533089Swyllys 	case KMF_X509_EXT_CERT_POLICIES:
21543089Swyllys 	case KMF_X509_EXT_BASIC_CONSTRAINTS:
21553089Swyllys 	case KMF_X509_EXT_NAME_CONSTRAINTS:
21563089Swyllys 	case KMF_X509_EXT_POLICY_CONSTRAINTS:
21573089Swyllys 	case KMF_X509_EXT_EXT_KEY_USAGE:
21583089Swyllys 	case KMF_X509_EXT_INHIBIT_ANY_POLICY:
21593089Swyllys 	case KMF_X509_EXT_AUTH_KEY_ID:
21603089Swyllys 	case KMF_X509_EXT_SUBJ_KEY_ID:
21613089Swyllys 	case KMF_X509_EXT_POLICY_MAPPINGS:
21623089Swyllys 	case KMF_X509_EXT_CRL_DIST_POINTS:
21633089Swyllys 	case KMF_X509_EXT_FRESHEST_CRL:
21643089Swyllys 		nid = ext2NID(flag);
21653089Swyllys 		if (nid == NID_undef) {
21663089Swyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
21673089Swyllys 			goto out;
21683089Swyllys 		}
21693089Swyllys 		ci = xcert->cert_info;
21703089Swyllys 
21713089Swyllys 		ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1);
21723089Swyllys 		if (ext_index == -1) {
21733089Swyllys 			SET_ERROR(kmfh, ERR_get_error());
21743089Swyllys 
21753089Swyllys 			ret = KMF_ERR_EXTENSION_NOT_FOUND;
21763089Swyllys 			goto out;
21773089Swyllys 		}
21783089Swyllys 		ex = X509v3_get_ext(ci->extensions, ext_index);
21793089Swyllys 
21803089Swyllys 		(void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
21813089Swyllys 
21823089Swyllys 		if (BIO_printf(mem, ": %s\n",
21835051Swyllys 		    X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
21843089Swyllys 			SET_ERROR(kmfh, ERR_get_error());
21853089Swyllys 			ret = KMF_ERR_ENCODING;
21863089Swyllys 			goto out;
21873089Swyllys 		}
21883089Swyllys 		if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
21893089Swyllys 			(void) BIO_printf(mem, "%*s", 4, "");
21903089Swyllys 			(void) M_ASN1_OCTET_STRING_print(mem, ex->value);
21913089Swyllys 		}
21923089Swyllys 		if (BIO_write(mem, "\n", 1) <= 0) {
21933089Swyllys 			SET_ERROR(kmfh, ERR_get_error());
21943089Swyllys 			ret = KMF_ERR_ENCODING;
21953089Swyllys 			goto out;
21963089Swyllys 		}
21973089Swyllys 		len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
21983089Swyllys 	}
21993089Swyllys 	if (len <= 0) {
22003089Swyllys 		SET_ERROR(kmfh, ERR_get_error());
22013089Swyllys 		ret = KMF_ERR_ENCODING;
22023089Swyllys 	}
22033089Swyllys 
22043089Swyllys out:
22053089Swyllys 	if (outbuf != NULL) {
22063089Swyllys 		free(outbuf);
22073089Swyllys 	}
22083089Swyllys 
22093089Swyllys 	if (xcert != NULL) {
22103089Swyllys 		X509_free(xcert);
22113089Swyllys 	}
22123089Swyllys 
22133089Swyllys 	if (mem != NULL) {
22143089Swyllys 		(void) BIO_free(mem);
22153089Swyllys 	}
22163089Swyllys 
22173089Swyllys 	return (ret);
22183089Swyllys }
22195051Swyllys 
22203089Swyllys KMF_RETURN
22213089Swyllys /*ARGSUSED*/
OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)22225051Swyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
22235051Swyllys     KMF_ATTRIBUTE *attrlist)
22243089Swyllys {
22253089Swyllys 	KMF_RETURN rv = KMF_OK;
22265051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
22275051Swyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
22285051Swyllys 	KMF_KEY_HANDLE *key = NULL;
22295051Swyllys 	uint32_t numkeys = 1; /* 1 key only */
22305051Swyllys 	char *dirpath = NULL;
22315051Swyllys 	char *keyfile = NULL;
22325051Swyllys 	KMF_ATTRIBUTE new_attrlist[16];
22335051Swyllys 	int i = 0;
22343089Swyllys 
22353089Swyllys 	/*
22363089Swyllys 	 * This is really just a FindKey operation, reuse the
22373089Swyllys 	 * FindKey function.
22383089Swyllys 	 */
22395051Swyllys 	kmf_set_attr_at_index(new_attrlist, i,
22405051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
22415051Swyllys 	i++;
22425051Swyllys 
22435051Swyllys 	kmf_set_attr_at_index(new_attrlist, i,
22445051Swyllys 	    KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
22455051Swyllys 	i++;
22465051Swyllys 
22475051Swyllys 	kmf_set_attr_at_index(new_attrlist, i,
22485051Swyllys 	    KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
22495051Swyllys 	i++;
22505051Swyllys 
22515051Swyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
22525051Swyllys 	if (key == NULL) {
22535051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
22545051Swyllys 	} else {
22555051Swyllys 		kmf_set_attr_at_index(new_attrlist, i,
22565051Swyllys 		    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
22575051Swyllys 		i++;
22585051Swyllys 	}
22595051Swyllys 
22605051Swyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
22615051Swyllys 	if (dirpath != NULL) {
22625051Swyllys 		kmf_set_attr_at_index(new_attrlist, i,
22635051Swyllys 		    KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
22645051Swyllys 		i++;
22655051Swyllys 	}
22665051Swyllys 
22675051Swyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
22685051Swyllys 	if (keyfile == NULL)
22695051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
22705051Swyllys 	else {
22715051Swyllys 		kmf_set_attr_at_index(new_attrlist, i,
22725051Swyllys 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
22735051Swyllys 		i++;
22745051Swyllys 	}
22755051Swyllys 
22765051Swyllys 	rv = OpenSSL_FindKey(handle, i, new_attrlist);
22773089Swyllys 	return (rv);
22783089Swyllys }
22793089Swyllys 
22803089Swyllys KMF_RETURN
22813089Swyllys /*ARGSUSED*/
OpenSSL_DecryptData(KMF_HANDLE_T handle,KMF_KEY_HANDLE * key,KMF_OID * AlgOID,KMF_DATA * ciphertext,KMF_DATA * output)22823089Swyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
22833089Swyllys 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
22843089Swyllys 	KMF_DATA *output)
22853089Swyllys {
22863089Swyllys 	KMF_RETURN		ret = KMF_OK;
22873089Swyllys 	RSA *rsa = NULL;
22883089Swyllys 	unsigned int in_len = 0, out_len = 0;
22893089Swyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
22903089Swyllys 	uint8_t *in_data, *out_data;
22913089Swyllys 	int i, blocks;
22923089Swyllys 
22933089Swyllys 	if (key == NULL || AlgOID == NULL ||
22943089Swyllys 	    ciphertext == NULL || output == NULL ||
22953089Swyllys 	    ciphertext->Data == NULL ||
22963089Swyllys 	    output->Data == NULL)
22973089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
22983089Swyllys 
22993089Swyllys 	if (key->keyalg == KMF_RSA) {
23003089Swyllys 		rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
23013089Swyllys 		modulus_len = RSA_size(rsa);
23023089Swyllys 	} else {
23033089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
23043089Swyllys 	}
23053089Swyllys 
23063089Swyllys 	blocks = ciphertext->Length/modulus_len;
23073089Swyllys 	out_data = output->Data;
23083089Swyllys 	in_data = ciphertext->Data;
23093089Swyllys 	out_len = modulus_len - 11;
23103089Swyllys 	in_len = modulus_len;
23113089Swyllys 
23123089Swyllys 	for (i = 0; i < blocks; i++) {
23133089Swyllys 		out_len  = RSA_private_decrypt(in_len,
23144315Swyllys 		    in_data, out_data, rsa, RSA_PKCS1_PADDING);
23153089Swyllys 
23163089Swyllys 		if (out_len == 0) {
23173089Swyllys 			ret = KMF_ERR_INTERNAL;
23183089Swyllys 			goto cleanup;
23193089Swyllys 		}
23203089Swyllys 
23213089Swyllys 		out_data += out_len;
23223089Swyllys 		total_decrypted += out_len;
23233089Swyllys 		in_data += in_len;
23243089Swyllys 	}
23253089Swyllys 
23263089Swyllys 	output->Length = total_decrypted;
23273089Swyllys 
23283089Swyllys cleanup:
23293089Swyllys 	RSA_free(rsa);
23303089Swyllys 	if (ret != KMF_OK)
23313089Swyllys 		output->Length = 0;
23323089Swyllys 
23333089Swyllys 	return (ret);
23343089Swyllys 
23353089Swyllys }
23363089Swyllys 
23373089Swyllys /*
23383089Swyllys  *  This function will create a certid from issuer_cert and user_cert.
23393089Swyllys  *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
23403089Swyllys  *  certid memory after use.
23413089Swyllys  */
23423089Swyllys static KMF_RETURN
create_certid(KMF_HANDLE_T handle,const KMF_DATA * issuer_cert,const KMF_DATA * user_cert,OCSP_CERTID ** certid)23433089Swyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
23443089Swyllys     const KMF_DATA *user_cert, OCSP_CERTID **certid)
23453089Swyllys {
23463089Swyllys 	KMF_RETURN ret = KMF_OK;
23473089Swyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
23483089Swyllys 	X509   *issuer = NULL;
23493089Swyllys 	X509   *cert = NULL;
23503089Swyllys 	unsigned char *ptmp;
23513089Swyllys 
23523089Swyllys 	if (issuer_cert == NULL || user_cert == NULL) {
23533089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
23543089Swyllys 	}
23553089Swyllys 
23563089Swyllys 	/* convert the DER-encoded issuer cert to an internal X509 */
23573089Swyllys 	ptmp = issuer_cert->Data;
23583089Swyllys 	issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
23594315Swyllys 	    issuer_cert->Length);
23603089Swyllys 	if (issuer == NULL) {
23613089Swyllys 		SET_ERROR(kmfh, ERR_get_error());
23623089Swyllys 		ret = KMF_ERR_OCSP_BAD_ISSUER;
23633089Swyllys 		goto end;
23643089Swyllys 	}
23653089Swyllys 
23663089Swyllys 	/* convert the DER-encoded user cert to an internal X509 */
23673089Swyllys 	ptmp = user_cert->Data;
23683089Swyllys 	cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
23694315Swyllys 	    user_cert->Length);
23703089Swyllys 	if (cert == NULL) {
23713089Swyllys 		SET_ERROR(kmfh, ERR_get_error());
23723089Swyllys 
23733089Swyllys 		ret = KMF_ERR_OCSP_BAD_CERT;
23743089Swyllys 		goto end;
23753089Swyllys 	}
23763089Swyllys 
23773089Swyllys 	/* create a CERTID */
23783089Swyllys 	*certid = OCSP_cert_to_id(NULL, cert, issuer);
23793089Swyllys 	if (*certid == NULL) {
23803089Swyllys 		SET_ERROR(kmfh, ERR_get_error());
23813089Swyllys 		ret = KMF_ERR_OCSP_CERTID;
23823089Swyllys 		goto end;
23833089Swyllys 	}
23843089Swyllys 
23853089Swyllys end:
23863089Swyllys 	if (issuer != NULL) {
23873089Swyllys 		X509_free(issuer);
23883089Swyllys 	}
23893089Swyllys 
23903089Swyllys 	if (cert != NULL) {
23913089Swyllys 		X509_free(cert);
23923089Swyllys 	}
23933089Swyllys 
23943089Swyllys 	return (ret);
23953089Swyllys }
23963089Swyllys 
23973089Swyllys KMF_RETURN
OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)23985051Swyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
23995051Swyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
24003089Swyllys {
24013089Swyllys 	KMF_RETURN ret = KMF_OK;
24023089Swyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
24033089Swyllys 	OCSP_CERTID *id = NULL;
24043089Swyllys 	OCSP_REQUEST *req = NULL;
24053089Swyllys 	BIO *derbio = NULL;
24065051Swyllys 	char *reqfile;
24075051Swyllys 	KMF_DATA *issuer_cert;
24085051Swyllys 	KMF_DATA *user_cert;
24095051Swyllys 
24105051Swyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
24115051Swyllys 	    attrlist, numattr);
24125051Swyllys 	if (user_cert == NULL)
24133089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
24145051Swyllys 
24155051Swyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
24165051Swyllys 	    attrlist, numattr);
24175051Swyllys 	if (issuer_cert == NULL)
24185051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
24195051Swyllys 
24205051Swyllys 	reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
24215051Swyllys 	    attrlist, numattr);
24225051Swyllys 	if (reqfile == NULL)
24235051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
24245051Swyllys 
24255051Swyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
24263089Swyllys 	if (ret != KMF_OK) {
24273089Swyllys 		return (ret);
24283089Swyllys 	}
24293089Swyllys 
24303089Swyllys 	/* Create an OCSP request */
24313089Swyllys 	req = OCSP_REQUEST_new();
24323089Swyllys 	if (req == NULL) {
24333089Swyllys 		SET_ERROR(kmfh, ERR_get_error());
24343089Swyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
24353089Swyllys 		goto end;
24363089Swyllys 	}
24373089Swyllys 
24383089Swyllys 	if (!OCSP_request_add0_id(req, id)) {
24393089Swyllys 		ret = KMF_ERR_OCSP_CREATE_REQUEST;
24403089Swyllys 		goto end;
24413089Swyllys 	}
24423089Swyllys 
24433089Swyllys 	/* Write the request to the output file with DER encoding */
24443089Swyllys 	derbio = BIO_new_file(reqfile, "wb");
24453089Swyllys 	if (!derbio) {
24463089Swyllys 		SET_ERROR(kmfh, ERR_get_error());
24473089Swyllys 		ret = KMF_ERR_OPEN_FILE;
24483089Swyllys 		goto end;
24493089Swyllys 	}
24503089Swyllys 	if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
24513089Swyllys 		ret = KMF_ERR_ENCODING;
24523089Swyllys 	}
24533089Swyllys 
24543089Swyllys end:
24553089Swyllys 	/*
245611973Swyllys.ingersoll@sun.com 	 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
245711673Sopensolaris@drydog.com 	 * will also deallocate certid's space.
24583089Swyllys 	 */
24593089Swyllys 	if (req != NULL) {
24603089Swyllys 		OCSP_REQUEST_free(req);
24613089Swyllys 	}
24623089Swyllys 
24633089Swyllys 	if (derbio != NULL) {
24643089Swyllys 		(void) BIO_free(derbio);
24653089Swyllys 	}
24663089Swyllys 
24673089Swyllys 	return (ret);
24683089Swyllys }
24693089Swyllys 
24703089Swyllys /* ocsp_find_signer_sk() is copied from openssl source */
ocsp_find_signer_sk(STACK_OF (X509)* certs,OCSP_RESPID * id)24713089Swyllys static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
24723089Swyllys {
24733089Swyllys 	int i;
24743089Swyllys 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
24753089Swyllys 
24763089Swyllys 	/* Easy if lookup by name */
24773089Swyllys 	if (id->type == V_OCSP_RESPID_NAME)
24783089Swyllys 		return (X509_find_by_subject(certs, id->value.byName));
24793089Swyllys 
24803089Swyllys 	/* Lookup by key hash */
24813089Swyllys 
24823089Swyllys 	/* If key hash isn't SHA1 length then forget it */
24833089Swyllys 	if (id->value.byKey->length != SHA_DIGEST_LENGTH)
24843089Swyllys 		return (NULL);
24853089Swyllys 
24863089Swyllys 	keyhash = id->value.byKey->data;
24873089Swyllys 	/* Calculate hash of each key and compare */
24883089Swyllys 	for (i = 0; i < sk_X509_num(certs); i++) {
248911673Sopensolaris@drydog.com 		/* LINTED E_BAD_PTR_CAST_ALIGN */
24903089Swyllys 		X509 *x = sk_X509_value(certs, i);
24915536Swyllys 		/* Use pubkey_digest to get the key ID value */
24923089Swyllys 		(void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
24933089Swyllys 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
24943089Swyllys 			return (x);
24953089Swyllys 	}
24963089Swyllys 	return (NULL);
24973089Swyllys }
24983089Swyllys 
24993089Swyllys /* ocsp_find_signer() is copied from openssl source */
250011673Sopensolaris@drydog.com /* ARGSUSED2 */
25013089Swyllys static int
ocsp_find_signer(X509 ** psigner,OCSP_BASICRESP * bs,STACK_OF (X509)* certs,X509_STORE * st,unsigned long flags)25023089Swyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
25033089Swyllys     X509_STORE *st, unsigned long flags)
25043089Swyllys {
25053089Swyllys 	X509 *signer;
25063089Swyllys 	OCSP_RESPID *rid = bs->tbsResponseData->responderId;
25073089Swyllys 	if ((signer = ocsp_find_signer_sk(certs, rid)))	{
25083089Swyllys 		*psigner = signer;
25093089Swyllys 		return (2);
25103089Swyllys 	}
25113089Swyllys 	if (!(flags & OCSP_NOINTERN) &&
25123089Swyllys 	    (signer = ocsp_find_signer_sk(bs->certs, rid))) {
25133089Swyllys 		*psigner = signer;
25143089Swyllys 		return (1);
25153089Swyllys 	}
25163089Swyllys 	/* Maybe lookup from store if by subject name */
25173089Swyllys 
25183089Swyllys 	*psigner = NULL;
25193089Swyllys 	return (0);
25203089Swyllys }
25213089Swyllys 
25223089Swyllys /*
25233089Swyllys  * This function will verify the signature of a basic response, using
25243089Swyllys  * the public key from the OCSP responder certificate.
25253089Swyllys  */
25263089Swyllys static KMF_RETURN
check_response_signature(KMF_HANDLE_T handle,OCSP_BASICRESP * bs,KMF_DATA * signer_cert,KMF_DATA * issuer_cert)25273089Swyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
25283089Swyllys     KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
25293089Swyllys {
25303089Swyllys 	KMF_RETURN ret = KMF_OK;
25313089Swyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
25323089Swyllys 	STACK_OF(X509) *cert_stack = NULL;
25333089Swyllys 	X509 *signer = NULL;
25343089Swyllys 	X509 *issuer = NULL;
25353089Swyllys 	EVP_PKEY *skey = NULL;
25363089Swyllys 	unsigned char *ptmp;
25373089Swyllys 
25383089Swyllys 
25393089Swyllys 	if (bs == NULL || issuer_cert == NULL)
25403089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
25413089Swyllys 
25423089Swyllys 	/*
25433089Swyllys 	 * Find the certificate that signed the basic response.
25443089Swyllys 	 *
25453089Swyllys 	 * If signer_cert is not NULL, we will use that as the signer cert.
25463089Swyllys 	 * Otherwise, we will check if the issuer cert is actually the signer.
25473089Swyllys 	 * If we still do not find a signer, we will look for it from the
25483089Swyllys 	 * certificate list came with the response file.
25493089Swyllys 	 */
25503089Swyllys 	if (signer_cert != NULL) {
25513089Swyllys 		ptmp = signer_cert->Data;
25523089Swyllys 		signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
25533089Swyllys 		    signer_cert->Length);
25543089Swyllys 		if (signer == NULL) {
25553089Swyllys 			SET_ERROR(kmfh, ERR_get_error());
25563089Swyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
25573089Swyllys 			goto end;
25583089Swyllys 		}
25593089Swyllys 	} else {
25603089Swyllys 		/*
25613089Swyllys 		 * Convert the issuer cert into X509 and push it into a
25623089Swyllys 		 * stack to be used by ocsp_find_signer().
25633089Swyllys 		 */
25643089Swyllys 		ptmp = issuer_cert->Data;
25653089Swyllys 		issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
25664315Swyllys 		    issuer_cert->Length);
25673089Swyllys 		if (issuer == NULL) {
25683089Swyllys 			SET_ERROR(kmfh, ERR_get_error());
25693089Swyllys 			ret = KMF_ERR_OCSP_BAD_ISSUER;
25703089Swyllys 			goto end;
25713089Swyllys 		}
25723089Swyllys 
25733089Swyllys 		if ((cert_stack = sk_X509_new_null()) == NULL) {
25743089Swyllys 			ret = KMF_ERR_INTERNAL;
25753089Swyllys 			goto end;
25763089Swyllys 		}
25773089Swyllys 
25783089Swyllys 		if (sk_X509_push(cert_stack, issuer) == NULL) {
25793089Swyllys 			ret = KMF_ERR_INTERNAL;
25803089Swyllys 			goto end;
25813089Swyllys 		}
25823089Swyllys 
25833089Swyllys 		ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
25843089Swyllys 		if (!ret) {
25853089Swyllys 			/* can not find the signer */
25863089Swyllys 			ret = KMF_ERR_OCSP_BAD_SIGNER;
25873089Swyllys 			goto end;
25883089Swyllys 		}
25893089Swyllys 	}
25903089Swyllys 
25913089Swyllys 	/* Verify the signature of the response */
25923089Swyllys 	skey = X509_get_pubkey(signer);
25933089Swyllys 	if (skey == NULL) {
25943089Swyllys 		ret = KMF_ERR_OCSP_BAD_SIGNER;
25953089Swyllys 		goto end;
25963089Swyllys 	}
25973089Swyllys 
25983089Swyllys 	ret = OCSP_BASICRESP_verify(bs, skey, 0);
25993089Swyllys 	if (ret == 0) {
26003089Swyllys 		ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
26013089Swyllys 		goto end;
26023089Swyllys 	}
26033089Swyllys 
26043089Swyllys end:
26053089Swyllys 	if (issuer != NULL) {
26063089Swyllys 		X509_free(issuer);
26073089Swyllys 	}
26083089Swyllys 
26093089Swyllys 	if (signer != NULL) {
26103089Swyllys 		X509_free(signer);
26113089Swyllys 	}
26123089Swyllys 
26133089Swyllys 	if (skey != NULL) {
26143089Swyllys 		EVP_PKEY_free(skey);
26153089Swyllys 	}
26163089Swyllys 
26173089Swyllys 	if (cert_stack != NULL) {
26183089Swyllys 		sk_X509_free(cert_stack);
26193089Swyllys 	}
26203089Swyllys 
26213089Swyllys 	return (ret);
26223089Swyllys }
26233089Swyllys 
26243089Swyllys 
26253089Swyllys 
26263089Swyllys KMF_RETURN
OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)26273089Swyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
26285051Swyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
26293089Swyllys {
26303089Swyllys 	KMF_RETURN ret = KMF_OK;
26313089Swyllys 	BIO *derbio = NULL;
26323089Swyllys 	OCSP_RESPONSE *resp = NULL;
26333089Swyllys 	OCSP_BASICRESP *bs = NULL;
26343089Swyllys 	OCSP_CERTID *id = NULL;
26353089Swyllys 	OCSP_SINGLERESP *single = NULL;
26363089Swyllys 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
26373089Swyllys 	int index, status, reason;
26385051Swyllys 	KMF_DATA *issuer_cert;
26395051Swyllys 	KMF_DATA *user_cert;
26405051Swyllys 	KMF_DATA *signer_cert;
26415051Swyllys 	KMF_DATA *response;
26425051Swyllys 	int *response_reason, *response_status, *cert_status;
26435051Swyllys 	boolean_t ignore_response_sign = B_FALSE;	/* default is FALSE */
26445051Swyllys 	uint32_t response_lifetime;
26455051Swyllys 
26465051Swyllys 	issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
26475051Swyllys 	    attrlist, numattr);
26485051Swyllys 	if (issuer_cert == NULL)
26495051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
26505051Swyllys 
26515051Swyllys 	user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
26525051Swyllys 	    attrlist, numattr);
26535051Swyllys 	if (user_cert == NULL)
26543089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
26555051Swyllys 
26565051Swyllys 	response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
26575051Swyllys 	    attrlist, numattr);
26585051Swyllys 	if (response == NULL)
26595051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
26605051Swyllys 
26615051Swyllys 	response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
26625051Swyllys 	    attrlist, numattr);
26635051Swyllys 	if (response_status == NULL)
26643089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
26655051Swyllys 
26665051Swyllys 	response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
26675051Swyllys 	    attrlist, numattr);
26685051Swyllys 	if (response_reason == NULL)
26695051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
26705051Swyllys 
26715051Swyllys 	cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
26725051Swyllys 	    attrlist, numattr);
26735051Swyllys 	if (cert_status == NULL)
26745051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
26753089Swyllys 
26763089Swyllys 	/* Read in the response */
26775051Swyllys 	derbio = BIO_new_mem_buf(response->Data, response->Length);
26783089Swyllys 	if (!derbio) {
26793089Swyllys 		ret = KMF_ERR_MEMORY;
26803089Swyllys 		return (ret);
26813089Swyllys 	}
26823089Swyllys 
26833089Swyllys 	resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
26843089Swyllys 	if (resp == NULL) {
26853089Swyllys 		ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
26863089Swyllys 		goto end;
26873089Swyllys 	}
26883089Swyllys 
26893089Swyllys 	/* Check the response status */
26903089Swyllys 	status = OCSP_response_status(resp);
26915051Swyllys 	*response_status = status;
26923089Swyllys 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
26933089Swyllys 		ret = KMF_ERR_OCSP_RESPONSE_STATUS;
26943089Swyllys 		goto end;
26953089Swyllys 	}
26963089Swyllys 
26973089Swyllys #ifdef DEBUG
26983089Swyllys 	printf("Successfully checked the response file status.\n");
26993089Swyllys #endif /* DEBUG */
27003089Swyllys 
27013089Swyllys 	/* Extract basic response */
27023089Swyllys 	bs = OCSP_response_get1_basic(resp);
27033089Swyllys 	if (bs == NULL) {
27043089Swyllys 		ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
27053089Swyllys 		goto end;
27063089Swyllys 	}
27073089Swyllys 
27083089Swyllys #ifdef DEBUG
27093089Swyllys 	printf("Successfully retrieved the basic response.\n");
27103089Swyllys #endif /* DEBUG */
27113089Swyllys 
27123089Swyllys 	/* Check the basic response signature if required */
27135051Swyllys 	ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
27145051Swyllys 	    (void *)&ignore_response_sign, NULL);
27155051Swyllys 	if (ret != KMF_OK)
27165051Swyllys 		ret = KMF_OK;
27175051Swyllys 
27185051Swyllys 	signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
27195051Swyllys 	    attrlist, numattr);
27205051Swyllys 
27215051Swyllys 	if (ignore_response_sign == B_FALSE) {
27223089Swyllys 		ret = check_response_signature(handle, bs,
27235051Swyllys 		    signer_cert, issuer_cert);
27243089Swyllys 		if (ret != KMF_OK)
27253089Swyllys 			goto end;
27263089Swyllys 	}
27273089Swyllys 
27283089Swyllys #ifdef DEBUG
27293089Swyllys 	printf("Successfully verified the response signature.\n");
27303089Swyllys #endif /* DEBUG */
27313089Swyllys 
27323089Swyllys 	/* Create a certid for the certificate in question */
27335051Swyllys 	ret = create_certid(handle, issuer_cert, user_cert, &id);
27343089Swyllys 	if (ret != KMF_OK) {
27353089Swyllys 		ret = KMF_ERR_OCSP_CERTID;
27363089Swyllys 		goto end;
27373089Swyllys 	}
27383089Swyllys 
27393089Swyllys #ifdef DEBUG
27403089Swyllys 	printf("successfully created a certid for the cert.\n");
27413089Swyllys #endif /* DEBUG */
27423089Swyllys 
27433089Swyllys 	/* Find the index of the single response for the certid */
27443089Swyllys 	index = OCSP_resp_find(bs, id, -1);
27453089Swyllys 	if (index < 0) {
27463089Swyllys 		/* cound not find this certificate in the response */
27473089Swyllys 		ret = KMF_ERR_OCSP_UNKNOWN_CERT;
27483089Swyllys 		goto end;
27493089Swyllys 	}
27503089Swyllys 
27513089Swyllys #ifdef DEBUG
27523089Swyllys 	printf("Successfully found the single response index for the cert.\n");
27533089Swyllys #endif /* DEBUG */
27543089Swyllys 
27553089Swyllys 	/* Retrieve the single response and get the cert status */
27563089Swyllys 	single = OCSP_resp_get0(bs, index);
27573089Swyllys 	status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
27583089Swyllys 	    &nextupd);
27593089Swyllys 	if (status == V_OCSP_CERTSTATUS_GOOD) {
27605051Swyllys 		*cert_status = OCSP_GOOD;
27613089Swyllys 	} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
27625051Swyllys 		*cert_status = OCSP_UNKNOWN;
27633089Swyllys 	} else { /* revoked */
27645051Swyllys 		*cert_status = OCSP_REVOKED;
27655051Swyllys 		*response_reason = reason;
27663089Swyllys 	}
27673089Swyllys 	ret = KMF_OK;
27683089Swyllys 
27695051Swyllys 	/* resp. time is optional, so we don't care about the return code. */
27705051Swyllys 	(void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
27715051Swyllys 	    (void *)&response_lifetime, NULL);
27725051Swyllys 
27733089Swyllys 	if (!OCSP_check_validity(thisupd, nextupd, 300,
27745051Swyllys 	    response_lifetime)) {
27753089Swyllys 		ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
27763089Swyllys 		goto end;
27773089Swyllys 	}
27783089Swyllys 
27793089Swyllys #ifdef DEBUG
27803089Swyllys 	printf("Successfully verify the time.\n");
27813089Swyllys #endif /* DEBUG */
27823089Swyllys 
27833089Swyllys end:
27843089Swyllys 	if (derbio != NULL)
27853089Swyllys 		(void) BIO_free(derbio);
27863089Swyllys 
27873089Swyllys 	if (resp != NULL)
27883089Swyllys 		OCSP_RESPONSE_free(resp);
27893089Swyllys 
27903089Swyllys 	if (bs != NULL)
27913089Swyllys 		OCSP_BASICRESP_free(bs);
27923089Swyllys 
27933089Swyllys 	if (id != NULL)
27943089Swyllys 		OCSP_CERTID_free(id);
27953089Swyllys 
27963089Swyllys 	return (ret);
27973089Swyllys }
27983089Swyllys 
27993089Swyllys static KMF_RETURN
fetch_key(KMF_HANDLE_T handle,char * path,KMF_KEY_CLASS keyclass,KMF_KEY_HANDLE * key)28003089Swyllys fetch_key(KMF_HANDLE_T handle, char *path,
28013089Swyllys 	KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
28023089Swyllys {
28033089Swyllys 	KMF_RETURN rv = KMF_OK;
28045051Swyllys 	EVP_PKEY *pkey = NULL;
28053089Swyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
28063089Swyllys 
28073089Swyllys 	if (keyclass == KMF_ASYM_PRI ||
28083089Swyllys 	    keyclass == KMF_ASYM_PUB) {
28093089Swyllys 		pkey = openssl_load_key(handle, path);
28103089Swyllys 		if (pkey == NULL) {
28113089Swyllys 			return (KMF_ERR_KEY_NOT_FOUND);
28123089Swyllys 		}
28133089Swyllys 		if (key != NULL) {
28143089Swyllys 			if (pkey->type == EVP_PKEY_RSA)
28153089Swyllys 				key->keyalg = KMF_RSA;
28163089Swyllys 			else if (pkey->type == EVP_PKEY_DSA)
28173089Swyllys 				key->keyalg = KMF_DSA;
28183089Swyllys 
28193089Swyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
28203089Swyllys 			key->keyclass = keyclass;
28213089Swyllys 			key->keyp = (void *)pkey;
28223089Swyllys 			key->israw = FALSE;
28235536Swyllys 			if (path != NULL &&
28245536Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
28255536Swyllys 				EVP_PKEY_free(pkey);
28265536Swyllys 				return (KMF_ERR_MEMORY);
28275536Swyllys 			}
28283089Swyllys 		} else {
28293089Swyllys 			EVP_PKEY_free(pkey);
28303089Swyllys 			pkey = NULL;
28313089Swyllys 		}
28323089Swyllys 	} else if (keyclass == KMF_SYMMETRIC) {
28333089Swyllys 		KMF_ENCODE_FORMAT fmt;
28343089Swyllys 		/*
28353089Swyllys 		 * If the file is a recognized format,
28363089Swyllys 		 * then it is NOT a symmetric key.
28373089Swyllys 		 */
28385051Swyllys 		rv = kmf_get_file_format(path, &fmt);
28393089Swyllys 		if (rv == KMF_OK || fmt != 0) {
28403089Swyllys 			return (KMF_ERR_KEY_NOT_FOUND);
28413089Swyllys 		} else if (rv == KMF_ERR_ENCODING) {
28423089Swyllys 			/*
28433089Swyllys 			 * If we don't know the encoding,
28443089Swyllys 			 * it is probably  a symmetric key.
28453089Swyllys 			 */
28463089Swyllys 			rv = KMF_OK;
28475051Swyllys 		} else if (rv == KMF_ERR_OPEN_FILE) {
28485051Swyllys 			return (KMF_ERR_KEY_NOT_FOUND);
28493089Swyllys 		}
28503089Swyllys 
28513089Swyllys 		if (key != NULL) {
28523089Swyllys 			KMF_DATA keyvalue;
28533089Swyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
28543089Swyllys 			if (rkey == NULL) {
28553089Swyllys 				rv = KMF_ERR_MEMORY;
28563089Swyllys 				goto out;
28573089Swyllys 			}
28583089Swyllys 
28593089Swyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
28605051Swyllys 			rv = kmf_read_input_file(handle, path, &keyvalue);
28613089Swyllys 			if (rv != KMF_OK)
28623089Swyllys 				goto out;
28633089Swyllys 
28643089Swyllys 			rkey->keydata.len = keyvalue.Length;
28653089Swyllys 			rkey->keydata.val = keyvalue.Data;
28663089Swyllys 
28673089Swyllys 			key->kstype = KMF_KEYSTORE_OPENSSL;
28683089Swyllys 			key->keyclass = keyclass;
28693089Swyllys 			key->israw = TRUE;
28703089Swyllys 			key->keyp = (void *)rkey;
28715536Swyllys 			if (path != NULL &&
28725536Swyllys 			    ((key->keylabel = strdup(path)) == NULL)) {
28735536Swyllys 				rv = KMF_ERR_MEMORY;
28745536Swyllys 			}
28753089Swyllys 		}
28763089Swyllys 	}
28773089Swyllys out:
28783089Swyllys 	if (rv != KMF_OK) {
28793089Swyllys 		if (rkey != NULL) {
28805051Swyllys 			kmf_free_raw_sym_key(rkey);
28813089Swyllys 		}
28823089Swyllys 		if (pkey != NULL)
28833089Swyllys 			EVP_PKEY_free(pkey);
28843089Swyllys 
28853089Swyllys 		if (key != NULL) {
28863089Swyllys 			key->keyalg = KMF_KEYALG_NONE;
28873089Swyllys 			key->keyclass = KMF_KEYCLASS_NONE;
28883089Swyllys 			key->keyp = NULL;
28893089Swyllys 		}
28903089Swyllys 	}
28913089Swyllys 
28923089Swyllys 	return (rv);
28933089Swyllys }
28943089Swyllys 
28953089Swyllys KMF_RETURN
OpenSSL_FindKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)28965051Swyllys OpenSSL_FindKey(KMF_HANDLE_T handle,
28975051Swyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
28983089Swyllys {
28993089Swyllys 	KMF_RETURN rv = KMF_OK;
29003089Swyllys 	char *fullpath = NULL;
29014025Swyllys 	uint32_t maxkeys;
29025051Swyllys 	KMF_KEY_HANDLE *key;
29035051Swyllys 	uint32_t *numkeys;
29045051Swyllys 	KMF_KEY_CLASS keyclass;
29055051Swyllys 	KMF_RAW_KEY_DATA *rawkey;
29065051Swyllys 	char *dirpath;
29075051Swyllys 	char *keyfile;
29085051Swyllys 
29095051Swyllys 	if (handle == NULL)
29105051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
29115051Swyllys 
29125051Swyllys 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
29135051Swyllys 	if (numkeys == NULL)
29143089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
29153089Swyllys 
29165051Swyllys 	rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
29175051Swyllys 	    (void *)&keyclass, NULL);
29185051Swyllys 	if (rv != KMF_OK)
29195051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
29205051Swyllys 
29215051Swyllys 	if (keyclass != KMF_ASYM_PUB &&
29225051Swyllys 	    keyclass != KMF_ASYM_PRI &&
29235051Swyllys 	    keyclass != KMF_SYMMETRIC)
29243089Swyllys 		return (KMF_ERR_BAD_KEY_CLASS);
29253089Swyllys 
29265051Swyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
29275051Swyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
29285051Swyllys 
29295051Swyllys 	fullpath = get_fullpath(dirpath, keyfile);
29303089Swyllys 
29313089Swyllys 	if (fullpath == NULL)
29323089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
29333089Swyllys 
29344025Swyllys 	maxkeys = *numkeys;
29354025Swyllys 	if (maxkeys == 0)
29364025Swyllys 		maxkeys = 0xFFFFFFFF;
29373089Swyllys 	*numkeys = 0;
29383089Swyllys 
29395051Swyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
29405051Swyllys 	/* it is okay to have "keys" contains NULL */
29415051Swyllys 
29425051Swyllys 	/*
29435051Swyllys 	 * The caller may want a list of the raw key data as well.
29445051Swyllys 	 * Useful for importing keys from a file into other keystores.
29455051Swyllys 	 */
29465051Swyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
29475051Swyllys 
29483089Swyllys 	if (isdir(fullpath)) {
29493089Swyllys 		DIR *dirp;
29503089Swyllys 		struct dirent *dp;
29513089Swyllys 		int n = 0;
29523089Swyllys 
29533089Swyllys 		/* open all files in the directory and attempt to read them */
29543089Swyllys 		if ((dirp = opendir(fullpath)) == NULL) {
29553089Swyllys 			return (KMF_ERR_BAD_PARAMETER);
29563089Swyllys 		}
29573089Swyllys 		rewinddir(dirp);
29584025Swyllys 		while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
29593089Swyllys 			if (strcmp(dp->d_name, ".") &&
29603089Swyllys 			    strcmp(dp->d_name, "..")) {
29613089Swyllys 				char *fname;
29623089Swyllys 
29633089Swyllys 				fname = get_fullpath(fullpath,
29644315Swyllys 				    (char *)&dp->d_name);
29653089Swyllys 
29663089Swyllys 				rv = fetch_key(handle, fname,
29675051Swyllys 				    keyclass, key ? &key[n] : NULL);
29685051Swyllys 
29695051Swyllys 				if (rv == KMF_OK) {
29705051Swyllys 					if (key != NULL && rawkey != NULL)
29715051Swyllys 						rv = convertToRawKey(
29725051Swyllys 						    key[n].keyp, &rawkey[n]);
29733089Swyllys 					n++;
29745051Swyllys 				}
29753089Swyllys 
29763089Swyllys 				if (rv != KMF_OK || key == NULL)
29773089Swyllys 					free(fname);
29783089Swyllys 			}
29793089Swyllys 		}
29803089Swyllys 		(void) closedir(dirp);
29813089Swyllys 		free(fullpath);
29823089Swyllys 		(*numkeys) = n;
29833089Swyllys 	} else {
29845051Swyllys 		rv = fetch_key(handle, fullpath, keyclass, key);
29853089Swyllys 		if (rv == KMF_OK)
29863089Swyllys 			(*numkeys) = 1;
29873089Swyllys 
29883089Swyllys 		if (rv != KMF_OK || key == NULL)
29893089Swyllys 			free(fullpath);
29905051Swyllys 
29915051Swyllys 		if (rv == KMF_OK && key != NULL && rawkey != NULL) {
29925051Swyllys 			rv = convertToRawKey(key->keyp, rawkey);
29935051Swyllys 		}
29943089Swyllys 	}
29953089Swyllys 
29964025Swyllys 	if (rv == KMF_OK && (*numkeys) == 0)
29973089Swyllys 		rv = KMF_ERR_KEY_NOT_FOUND;
29985637Swyllys 	else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
29995637Swyllys 		rv = KMF_OK;
30003089Swyllys 
30013089Swyllys 	return (rv);
30023089Swyllys }
30033089Swyllys 
30043089Swyllys #define	HANDLE_PK12_ERROR { \
30053089Swyllys 	SET_ERROR(kmfh, ERR_get_error()); \
30063089Swyllys 	rv = KMF_ERR_ENCODING; \
30073089Swyllys 	goto out; \
30083089Swyllys }
30093089Swyllys 
30105536Swyllys static int
add_alias_to_bag(PKCS12_SAFEBAG * bag,X509 * xcert)30115536Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
30123089Swyllys {
30135536Swyllys 	if (xcert != NULL && xcert->aux != NULL &&
30145536Swyllys 	    xcert->aux->alias != NULL) {
30155536Swyllys 		if (PKCS12_add_friendlyname_asc(bag,
30165536Swyllys 		    (const char *)xcert->aux->alias->data,
30175536Swyllys 		    xcert->aux->alias->length) == 0)
30185536Swyllys 			return (0);
30195536Swyllys 	}
30205536Swyllys 	return (1);
30215536Swyllys }
30225536Swyllys 
30235536Swyllys static PKCS7 *
add_cert_to_safe(X509 * sslcert,KMF_CREDENTIAL * cred,uchar_t * keyid,unsigned int keyidlen)30245536Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
30255536Swyllys 	uchar_t *keyid, unsigned int keyidlen)
30265536Swyllys {
30275536Swyllys 	PKCS12_SAFEBAG *bag = NULL;
30285536Swyllys 	PKCS7 *cert_authsafe = NULL;
30295536Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack;
30303089Swyllys 
30313089Swyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
30323089Swyllys 	if (bag_stack == NULL)
30335536Swyllys 		return (NULL);
30345536Swyllys 
30355536Swyllys 	/* Convert cert from X509 struct to PKCS#12 bag */
30365536Swyllys 	bag = PKCS12_x5092certbag(sslcert);
30375536Swyllys 	if (bag == NULL) {
30385536Swyllys 		goto out;
30395536Swyllys 	}
30405536Swyllys 
30415536Swyllys 	/* Add the key id to the certificate bag. */
30425536Swyllys 	if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
30435536Swyllys 		goto out;
30445536Swyllys 	}
30455536Swyllys 
30465536Swyllys 	if (!add_alias_to_bag(bag, sslcert))
30475536Swyllys 		goto out;
30485536Swyllys 
30495536Swyllys 	/* Pile it on the bag_stack. */
30505536Swyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
30515536Swyllys 		goto out;
30525536Swyllys 	}
30535536Swyllys 	/* Turn bag_stack of certs into encrypted authsafe. */
30545536Swyllys 	cert_authsafe = PKCS12_pack_p7encdata(
30555536Swyllys 	    NID_pbe_WithSHA1And40BitRC2_CBC,
30565536Swyllys 	    cred->cred, cred->credlen, NULL, 0,
30575536Swyllys 	    PKCS12_DEFAULT_ITER, bag_stack);
30585536Swyllys 
30595536Swyllys out:
30605536Swyllys 	if (bag_stack != NULL)
30613089Swyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
30625536Swyllys 
30635536Swyllys 	return (cert_authsafe);
30645536Swyllys }
30655536Swyllys 
30665536Swyllys static PKCS7 *
add_key_to_safe(EVP_PKEY * pkey,KMF_CREDENTIAL * cred,uchar_t * keyid,unsigned int keyidlen,char * label,int label_len)30675536Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
30685536Swyllys 	uchar_t *keyid,  unsigned int keyidlen,
30695536Swyllys 	char *label, int label_len)
30705536Swyllys {
30715536Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
30725536Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
30735536Swyllys 	PKCS12_SAFEBAG *bag = NULL;
30745536Swyllys 	PKCS7 *key_authsafe = NULL;
30755536Swyllys 
30765536Swyllys 	p8 = EVP_PKEY2PKCS8(pkey);
30775536Swyllys 	if (p8 == NULL) {
30785536Swyllys 		return (NULL);
30795536Swyllys 	}
30805536Swyllys 	/* Put the shrouded key into a PKCS#12 bag. */
30815536Swyllys 	bag = PKCS12_MAKE_SHKEYBAG(
30825536Swyllys 	    NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
30835536Swyllys 	    cred->cred, cred->credlen,
30845536Swyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, p8);
30855536Swyllys 
30865536Swyllys 	/* Clean up the PKCS#8 shrouded key, don't need it now. */
30875536Swyllys 	PKCS8_PRIV_KEY_INFO_free(p8);
30885536Swyllys 	p8 = NULL;
30895536Swyllys 
30905536Swyllys 	if (bag == NULL) {
30915536Swyllys 		return (NULL);
30925536Swyllys 	}
30935536Swyllys 	if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
30945536Swyllys 		goto out;
30955536Swyllys 	if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
30965536Swyllys 		goto out;
30975536Swyllys 
30985536Swyllys 	/* Start a PKCS#12 safebag container for the private key. */
30995536Swyllys 	bag_stack = sk_PKCS12_SAFEBAG_new_null();
31005536Swyllys 	if (bag_stack == NULL)
31015536Swyllys 		goto out;
31025536Swyllys 
31035536Swyllys 	/* Pile on the private key on the bag_stack. */
31045536Swyllys 	if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
31055536Swyllys 		goto out;
31065536Swyllys 
31075536Swyllys 	key_authsafe = PKCS12_pack_p7data(bag_stack);
31085536Swyllys 
31095536Swyllys out:
31105536Swyllys 	if (bag_stack != NULL)
31113089Swyllys 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
31125536Swyllys 	bag_stack = NULL;
31135536Swyllys 	return (key_authsafe);
31143089Swyllys }
31153089Swyllys 
31163089Swyllys static EVP_PKEY *
ImportRawRSAKey(KMF_RAW_RSA_KEY * key)31173089Swyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
31183089Swyllys {
31193089Swyllys 	RSA		*rsa = NULL;
31203089Swyllys 	EVP_PKEY 	*newkey = NULL;
31213089Swyllys 
31223089Swyllys 	if ((rsa = RSA_new()) == NULL)
31233089Swyllys 		return (NULL);
31243089Swyllys 
31253089Swyllys 	if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL)
31263089Swyllys 		return (NULL);
31273089Swyllys 
31283089Swyllys 	if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) ==
31294315Swyllys 	    NULL)
31303089Swyllys 		return (NULL);
31313089Swyllys 
31323089Swyllys 	if (key->priexp.val != NULL)
31333089Swyllys 		if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len,
31344315Swyllys 		    rsa->d)) == NULL)
31353089Swyllys 			return (NULL);
31363089Swyllys 
31373089Swyllys 	if (key->prime1.val != NULL)
31383089Swyllys 		if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len,
31394315Swyllys 		    rsa->p)) == NULL)
31403089Swyllys 			return (NULL);
31413089Swyllys 
31423089Swyllys 	if (key->prime2.val != NULL)
31433089Swyllys 		if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len,
31444315Swyllys 		    rsa->q)) == NULL)
31453089Swyllys 			return (NULL);
31463089Swyllys 
31473089Swyllys 	if (key->exp1.val != NULL)
31483089Swyllys 		if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len,
31494315Swyllys 		    rsa->dmp1)) == NULL)
31503089Swyllys 			return (NULL);
31513089Swyllys 
31523089Swyllys 	if (key->exp2.val != NULL)
31533089Swyllys 		if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len,
31544315Swyllys 		    rsa->dmq1)) == NULL)
31553089Swyllys 			return (NULL);
31563089Swyllys 
31573089Swyllys 	if (key->coef.val != NULL)
31583089Swyllys 		if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len,
31594315Swyllys 		    rsa->iqmp)) == NULL)
31603089Swyllys 			return (NULL);
31613089Swyllys 
31623089Swyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
31633089Swyllys 		return (NULL);
31643089Swyllys 
31653089Swyllys 	(void) EVP_PKEY_set1_RSA(newkey, rsa);
31663089Swyllys 
31673089Swyllys 	/* The original key must be freed once here or it leaks memory */
31683089Swyllys 	RSA_free(rsa);
31693089Swyllys 
31703089Swyllys 	return (newkey);
31713089Swyllys }
31723089Swyllys 
31733089Swyllys static EVP_PKEY *
ImportRawDSAKey(KMF_RAW_DSA_KEY * key)31743089Swyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
31753089Swyllys {
31763089Swyllys 	DSA		*dsa = NULL;
31773089Swyllys 	EVP_PKEY 	*newkey = NULL;
31783089Swyllys 
31793089Swyllys 	if ((dsa = DSA_new()) == NULL)
31803089Swyllys 		return (NULL);
31813089Swyllys 
31823089Swyllys 	if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len,
31834315Swyllys 	    dsa->p)) == NULL)
31843089Swyllys 		return (NULL);
31853089Swyllys 
31863089Swyllys 	if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len,
31874315Swyllys 	    dsa->q)) == NULL)
31883089Swyllys 		return (NULL);
31893089Swyllys 
31903089Swyllys 	if ((dsa->g = BN_bin2bn(key->base.val, key->base.len,
31914315Swyllys 	    dsa->g)) == NULL)
31923089Swyllys 		return (NULL);
31933089Swyllys 
31943089Swyllys 	if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len,
31954315Swyllys 	    dsa->priv_key)) == NULL)
31963089Swyllys 		return (NULL);
31973089Swyllys 
31985051Swyllys 	if (key->pubvalue.val != NULL) {
31995051Swyllys 		if ((dsa->pub_key = BN_bin2bn(key->pubvalue.val,
32005051Swyllys 		    key->pubvalue.len, dsa->pub_key)) == NULL)
32015051Swyllys 			return (NULL);
32025051Swyllys 	}
32035051Swyllys 
32043089Swyllys 	if ((newkey = EVP_PKEY_new()) == NULL)
32053089Swyllys 		return (NULL);
32063089Swyllys 
32073089Swyllys 	(void) EVP_PKEY_set1_DSA(newkey, dsa);
32083089Swyllys 
32093089Swyllys 	/* The original key must be freed once here or it leaks memory */
32103089Swyllys 	DSA_free(dsa);
32113089Swyllys 	return (newkey);
32123089Swyllys }
32133089Swyllys 
32145536Swyllys static EVP_PKEY *
raw_key_to_pkey(KMF_KEY_HANDLE * key)32155536Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key)
32165536Swyllys {
32175536Swyllys 	EVP_PKEY *pkey = NULL;
32185536Swyllys 	KMF_RAW_KEY_DATA *rawkey;
32195536Swyllys 	ASN1_TYPE *attr = NULL;
32205536Swyllys 	KMF_RETURN ret;
32215536Swyllys 
32225536Swyllys 	if (key == NULL || !key->israw)
32235536Swyllys 		return (NULL);
32245536Swyllys 
32255536Swyllys 	rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
32265536Swyllys 	if (rawkey->keytype == KMF_RSA) {
32275536Swyllys 		pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
32285536Swyllys 	} else if (rawkey->keytype == KMF_DSA) {
32295536Swyllys 		pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
323011973Swyllys.ingersoll@sun.com 	} else if (rawkey->keytype == KMF_ECDSA) {
323111973Swyllys.ingersoll@sun.com 		/*
323211973Swyllys.ingersoll@sun.com 		 * OpenSSL in Solaris does not support EC for
323311973Swyllys.ingersoll@sun.com 		 * legal reasons
323411973Swyllys.ingersoll@sun.com 		 */
323511973Swyllys.ingersoll@sun.com 		return (NULL);
32365536Swyllys 	} else {
32375536Swyllys 		/* wrong kind of key */
32385536Swyllys 		return (NULL);
32395536Swyllys 	}
32405536Swyllys 
32415536Swyllys 	if (rawkey->label != NULL) {
32425536Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
32435536Swyllys 			EVP_PKEY_free(pkey);
32445536Swyllys 			return (NULL);
32455536Swyllys 		}
32465536Swyllys 		attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
32475536Swyllys 		(void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
32485536Swyllys 		    strlen(rawkey->label));
32495536Swyllys 		attr->type = V_ASN1_BMPSTRING;
32505536Swyllys 		attr->value.ptr = (char *)attr->value.bmpstring;
32515536Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
32525536Swyllys 		if (ret != KMF_OK) {
32535536Swyllys 			EVP_PKEY_free(pkey);
32545536Swyllys 			ASN1_TYPE_free(attr);
32555536Swyllys 			return (NULL);
32565536Swyllys 		}
32575536Swyllys 	}
32585536Swyllys 	if (rawkey->id.Data != NULL) {
32595536Swyllys 		if ((attr = ASN1_TYPE_new()) == NULL) {
32605536Swyllys 			EVP_PKEY_free(pkey);
32615536Swyllys 			return (NULL);
32625536Swyllys 		}
32635536Swyllys 		attr->value.octet_string =
32645536Swyllys 		    ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
32655536Swyllys 		attr->type = V_ASN1_OCTET_STRING;
32665536Swyllys 		(void) ASN1_STRING_set(attr->value.octet_string,
32675536Swyllys 		    rawkey->id.Data, rawkey->id.Length);
32685536Swyllys 		attr->value.ptr = (char *)attr->value.octet_string;
32695536Swyllys 		ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
32705536Swyllys 		if (ret != KMF_OK) {
32715536Swyllys 			EVP_PKEY_free(pkey);
32725536Swyllys 			ASN1_TYPE_free(attr);
32735536Swyllys 			return (NULL);
32745536Swyllys 		}
32755536Swyllys 	}
32765536Swyllys 	return (pkey);
32775536Swyllys }
32785536Swyllys 
32795536Swyllys /*
32805536Swyllys  * Search a list of private keys to find one that goes with the certificate.
32815536Swyllys  */
32825536Swyllys static EVP_PKEY *
find_matching_key(X509 * xcert,int numkeys,KMF_KEY_HANDLE * keylist)32835536Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
32845536Swyllys {
32855536Swyllys 	int i;
32865536Swyllys 	EVP_PKEY *pkey = NULL;
32875536Swyllys 
32885536Swyllys 	if (numkeys == 0 || keylist == NULL || xcert == NULL)
32895536Swyllys 		return (NULL);
32905536Swyllys 	for (i = 0; i < numkeys; i++) {
32915536Swyllys 		if (keylist[i].israw)
32925536Swyllys 			pkey = raw_key_to_pkey(&keylist[i]);
32935536Swyllys 		else
32945536Swyllys 			pkey = (EVP_PKEY *)keylist[i].keyp;
32955536Swyllys 		if (pkey != NULL) {
32965536Swyllys 			if (X509_check_private_key(xcert, pkey)) {
32975536Swyllys 				return (pkey);
32985536Swyllys 			} else {
32995536Swyllys 				EVP_PKEY_free(pkey);
33005536Swyllys 				pkey = NULL;
33015536Swyllys 			}
33025536Swyllys 		}
33035536Swyllys 	}
33045536Swyllys 	return (pkey);
33055536Swyllys }
33065536Swyllys 
33073089Swyllys 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)33085536Swyllys local_export_pk12(KMF_HANDLE_T handle,
33093089Swyllys 	KMF_CREDENTIAL *cred,
33103089Swyllys 	int numcerts, KMF_X509_DER_CERT *certlist,
33113089Swyllys 	int numkeys, KMF_KEY_HANDLE *keylist,
33123089Swyllys 	char *filename)
33133089Swyllys {
33143089Swyllys 	KMF_RETURN rv = KMF_OK;
33153089Swyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
33163089Swyllys 	BIO *bio = NULL;
33175536Swyllys 	PKCS7 *cert_authsafe = NULL;
33185536Swyllys 	PKCS7 *key_authsafe = NULL;
33195536Swyllys 	STACK_OF(PKCS7) *authsafe_stack = NULL;
33205536Swyllys 	PKCS12 *p12_elem = NULL;
33213089Swyllys 	int i;
33223089Swyllys 
33235536Swyllys 	if (numcerts == 0 && numkeys == 0)
33245536Swyllys 		return (KMF_ERR_BAD_PARAMETER);
33255536Swyllys 
33263089Swyllys 	/*
33273089Swyllys 	 * Open the output file.
33283089Swyllys 	 */
33293089Swyllys 	if ((bio = BIO_new_file(filename, "wb")) == NULL) {
33303089Swyllys 		SET_ERROR(kmfh, ERR_get_error());
33313089Swyllys 		rv = KMF_ERR_OPEN_FILE;
33323089Swyllys 		goto cleanup;
33333089Swyllys 	}
33343089Swyllys 
33355536Swyllys 	/* Start a PKCS#7 stack. */
33365536Swyllys 	authsafe_stack = sk_PKCS7_new_null();
33375536Swyllys 	if (authsafe_stack == NULL) {
33385536Swyllys 		rv = KMF_ERR_MEMORY;
33395536Swyllys 		goto cleanup;
33405536Swyllys 	}
33415536Swyllys 	if (numcerts > 0) {
33423089Swyllys 		for (i = 0; rv == KMF_OK && i < numcerts; i++) {
33433089Swyllys 			const uchar_t *p = certlist[i].certificate.Data;
33443089Swyllys 			long len = certlist[i].certificate.Length;
33455536Swyllys 			X509 *xcert = NULL;
33465536Swyllys 			EVP_PKEY *pkey = NULL;
33475536Swyllys 			unsigned char keyid[EVP_MAX_MD_SIZE];
33485536Swyllys 			unsigned int keyidlen = 0;
33493089Swyllys 
33503089Swyllys 			xcert = d2i_X509(NULL, &p, len);
33513089Swyllys 			if (xcert == NULL) {
33523089Swyllys 				SET_ERROR(kmfh, ERR_get_error());
33533089Swyllys 				rv = KMF_ERR_ENCODING;
33543089Swyllys 			}
33555536Swyllys 			if (certlist[i].kmf_private.label != NULL) {
33565536Swyllys 				/* Set alias attribute */
33575536Swyllys 				(void) X509_alias_set1(xcert,
33585536Swyllys 				    (uchar_t *)certlist[i].kmf_private.label,
33595536Swyllys 				    strlen(certlist[i].kmf_private.label));
33605536Swyllys 			}
33615536Swyllys 			/* Check if there is a key corresponding to this cert */
33625536Swyllys 			pkey = find_matching_key(xcert, numkeys, keylist);
33635536Swyllys 
33645536Swyllys 			/*
33655536Swyllys 			 * If key is found, get fingerprint and create a
33665536Swyllys 			 * safebag.
33675536Swyllys 			 */
33685536Swyllys 			if (pkey != NULL) {
33695536Swyllys 				(void) X509_digest(xcert, EVP_sha1(),
33705536Swyllys 				    keyid, &keyidlen);
33715536Swyllys 				key_authsafe = add_key_to_safe(pkey, cred,
33725536Swyllys 				    keyid, keyidlen,
33735536Swyllys 				    certlist[i].kmf_private.label,
33745536Swyllys 				    (certlist[i].kmf_private.label ?
33755536Swyllys 				    strlen(certlist[i].kmf_private.label) : 0));
33765536Swyllys 
33775536Swyllys 				if (key_authsafe == NULL) {
33785536Swyllys 					X509_free(xcert);
33795536Swyllys 					EVP_PKEY_free(pkey);
33805536Swyllys 					goto cleanup;
33815536Swyllys 				}
33825536Swyllys 				/* Put the key safe into the Auth Safe */
33835536Swyllys 				if (!sk_PKCS7_push(authsafe_stack,
33845536Swyllys 				    key_authsafe)) {
33855536Swyllys 					X509_free(xcert);
33865536Swyllys 					EVP_PKEY_free(pkey);
33875536Swyllys 					goto cleanup;
33885536Swyllys 				}
33895536Swyllys 			}
33905536Swyllys 
33915536Swyllys 			/* create a certificate safebag */
33925536Swyllys 			cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
33935536Swyllys 			    keyidlen);
33945536Swyllys 			if (cert_authsafe == NULL) {
33953089Swyllys 				X509_free(xcert);
33965536Swyllys 				EVP_PKEY_free(pkey);
33975536Swyllys 				goto cleanup;
33985536Swyllys 			}
33995536Swyllys 			if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
34005536Swyllys 				X509_free(xcert);
34015536Swyllys 				EVP_PKEY_free(pkey);
34025536Swyllys 				goto cleanup;
34035536Swyllys 			}
34045536Swyllys 
34055536Swyllys 			X509_free(xcert);
34063089Swyllys 			if (pkey)
34073089Swyllys 				EVP_PKEY_free(pkey);
34083089Swyllys 		}
34095536Swyllys 	} else if (numcerts == 0 && numkeys > 0) {
34105536Swyllys 		/*
34115536Swyllys 		 * If only adding keys to the file.
34125536Swyllys 		 */
34135536Swyllys 		for (i = 0; i < numkeys; i++) {
34145536Swyllys 			EVP_PKEY *pkey = NULL;
34155536Swyllys 
34165536Swyllys 			if (keylist[i].israw)
34175536Swyllys 				pkey = raw_key_to_pkey(&keylist[i]);
34185536Swyllys 			else
34195536Swyllys 				pkey = (EVP_PKEY *)keylist[i].keyp;
34205536Swyllys 
34215536Swyllys 			if (pkey == NULL)
34225536Swyllys 				continue;
34235536Swyllys 
34245536Swyllys 			key_authsafe = add_key_to_safe(pkey, cred,
34255536Swyllys 			    NULL, 0, NULL, 0);
34265536Swyllys 
34275536Swyllys 			if (key_authsafe == NULL) {
34285536Swyllys 				EVP_PKEY_free(pkey);
34295536Swyllys 				goto cleanup;
34305536Swyllys 			}
34315536Swyllys 			if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
34325536Swyllys 				EVP_PKEY_free(pkey);
34335536Swyllys 				goto cleanup;
34345536Swyllys 			}
34355536Swyllys 		}
34365536Swyllys 	}
34375536Swyllys 	p12_elem = PKCS12_init(NID_pkcs7_data);
34385536Swyllys 	if (p12_elem == NULL) {
34395536Swyllys 		goto cleanup;
34405536Swyllys 	}
34415536Swyllys 
34425536Swyllys 	/* Put the PKCS#7 stack into the PKCS#12 element. */
34435536Swyllys 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
34445536Swyllys 		goto cleanup;
34455536Swyllys 	}
34465536Swyllys 
34475536Swyllys 	/* Set the integrity MAC on the PKCS#12 element. */
34485536Swyllys 	if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
34495536Swyllys 	    NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
34505536Swyllys 		goto cleanup;
34515536Swyllys 	}
34525536Swyllys 
34535536Swyllys 	/* Write the PKCS#12 element to the export file. */
34545536Swyllys 	if (!i2d_PKCS12_bio(bio, p12_elem)) {
34555536Swyllys 		goto cleanup;
34565536Swyllys 	}
34575536Swyllys 	PKCS12_free(p12_elem);
34583089Swyllys 
34593089Swyllys cleanup:
34605536Swyllys 	/* Clear away the PKCS#7 stack, we're done with it. */
34615536Swyllys 	if (authsafe_stack)
34625536Swyllys 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
34633089Swyllys 
34643089Swyllys 	if (bio != NULL)
34653089Swyllys 		(void) BIO_free_all(bio);
34663089Swyllys 
34673089Swyllys 	return (rv);
34683089Swyllys }
34693089Swyllys 
34703089Swyllys 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)34715051Swyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
34725051Swyllys     KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
34735051Swyllys     KMF_CREDENTIAL *p12cred, char *filename)
34745051Swyllys {
34755051Swyllys 	KMF_RETURN rv;
34765051Swyllys 
34775051Swyllys 	if (certlist == NULL && keylist == NULL)
34785051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
34795051Swyllys 
34805536Swyllys 	rv = local_export_pk12(handle, p12cred, numcerts, certlist,
34815051Swyllys 	    numkeys, keylist, filename);
34825051Swyllys 
34835051Swyllys 	return (rv);
34845051Swyllys }
34855051Swyllys 
34865051Swyllys KMF_RETURN
OpenSSL_ExportPK12(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)34875051Swyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
34883089Swyllys {
34893089Swyllys 	KMF_RETURN rv;
34903089Swyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
34913089Swyllys 	char *fullpath = NULL;
34925051Swyllys 	char *dirpath = NULL;
34935051Swyllys 	char *certfile = NULL;
34945051Swyllys 	char *keyfile = NULL;
34955051Swyllys 	char *filename = NULL;
34965051Swyllys 	KMF_CREDENTIAL *p12cred = NULL;
34975536Swyllys 	KMF_X509_DER_CERT certdata;
34985536Swyllys 	KMF_KEY_HANDLE key;
34995536Swyllys 	int gotkey = 0;
35005536Swyllys 	int gotcert = 0;
35015051Swyllys 
35025051Swyllys 	if (handle == NULL)
35035051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
35043089Swyllys 
35053089Swyllys 	/*
35063089Swyllys 	 *  First, find the certificate.
35073089Swyllys 	 */
35085051Swyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
35095051Swyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
35105051Swyllys 	if (certfile != NULL) {
35115051Swyllys 		fullpath = get_fullpath(dirpath, certfile);
35123089Swyllys 		if (fullpath == NULL)
35133089Swyllys 			return (KMF_ERR_BAD_PARAMETER);
35143089Swyllys 
35153089Swyllys 		if (isdir(fullpath)) {
35163089Swyllys 			free(fullpath);
35173089Swyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
35183089Swyllys 		}
35193089Swyllys 
35205536Swyllys 		(void) memset(&certdata, 0, sizeof (certdata));
35215536Swyllys 		rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL,
35225536Swyllys 		    fullpath, &certdata.certificate);
35233089Swyllys 		if (rv != KMF_OK)
35243089Swyllys 			goto end;
35255051Swyllys 
35265536Swyllys 		gotcert++;
35275536Swyllys 		certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
35285051Swyllys 		free(fullpath);
35293089Swyllys 	}
35303089Swyllys 
35313089Swyllys 	/*
35323089Swyllys 	 * Now find the private key.
35333089Swyllys 	 */
35345051Swyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
35355051Swyllys 	if (keyfile != NULL) {
35365051Swyllys 		fullpath = get_fullpath(dirpath, keyfile);
35373089Swyllys 		if (fullpath == NULL)
35383089Swyllys 			return (KMF_ERR_BAD_PARAMETER);
35393089Swyllys 
35403089Swyllys 		if (isdir(fullpath)) {
35413089Swyllys 			free(fullpath);
35423089Swyllys 			return (KMF_ERR_AMBIGUOUS_PATHNAME);
35433089Swyllys 		}
35443089Swyllys 
35455536Swyllys 		(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
35465536Swyllys 		rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
35475536Swyllys 		if (rv != KMF_OK)
35483089Swyllys 			goto end;
35495536Swyllys 		gotkey++;
35503089Swyllys 	}
35513089Swyllys 
35523089Swyllys 	/*
35533089Swyllys 	 * Open the output file.
35543089Swyllys 	 */
35555051Swyllys 	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
35565051Swyllys 	    numattr);
35575051Swyllys 	if (filename == NULL) {
35585051Swyllys 		rv = KMF_ERR_BAD_PARAMETER;
35595051Swyllys 		goto end;
35605051Swyllys 	}
35615051Swyllys 
35623089Swyllys 	/* Stick the key and the cert into a PKCS#12 file */
35635051Swyllys 	p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
35645051Swyllys 	if (p12cred == NULL) {
35655051Swyllys 		rv = KMF_ERR_BAD_PARAMETER;
35665051Swyllys 		goto end;
35675051Swyllys 	}
35685051Swyllys 
35695536Swyllys 	rv = local_export_pk12(handle, p12cred, 1, &certdata,
35705536Swyllys 	    1, &key, filename);
35713089Swyllys 
35723089Swyllys end:
35733089Swyllys 	if (fullpath)
35743089Swyllys 		free(fullpath);
35755536Swyllys 
35765536Swyllys 	if (gotcert)
35775536Swyllys 		kmf_free_kmf_cert(handle, &certdata);
35785536Swyllys 	if (gotkey)
35795536Swyllys 		kmf_free_kmf_key(handle, &key);
35803089Swyllys 	return (rv);
35813089Swyllys }
35823089Swyllys 
35833408Swyllys /*
35843408Swyllys  * Helper function to extract keys and certificates from
35853408Swyllys  * a single PEM file.  Typically the file should contain a
35863408Swyllys  * private key and an associated public key wrapped in an x509 cert.
35873408Swyllys  * However, the file may be just a list of X509 certs with no keys.
35883408Swyllys  */
35893408Swyllys 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)35905051Swyllys extract_pem(KMF_HANDLE *kmfh,
35915051Swyllys 	char *issuer, char *subject, KMF_BIGINT *serial,
35923754Swyllys 	char *filename, CK_UTF8CHAR *pin,
35933408Swyllys 	CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
35943408Swyllys 	int *numcerts)
359511673Sopensolaris@drydog.com /* ARGSUSED6 */
35963408Swyllys {
35973408Swyllys 	KMF_RETURN rv = KMF_OK;
35983408Swyllys 	FILE *fp;
35994315Swyllys 	STACK_OF(X509_INFO) *x509_info_stack = NULL;
36003754Swyllys 	int i, ncerts = 0, matchcerts = 0;
36013408Swyllys 	EVP_PKEY *pkey = NULL;
36023408Swyllys 	X509_INFO *info;
36033408Swyllys 	X509 *x;
36045536Swyllys 	X509_INFO **cert_infos = NULL;
36053408Swyllys 	KMF_DATA *certlist = NULL;
36063408Swyllys 
36073408Swyllys 	if (priv_key)
36083408Swyllys 		*priv_key = NULL;
36093408Swyllys 	if (certs)
36103408Swyllys 		*certs = NULL;
36113408Swyllys 	fp = fopen(filename, "r");
36125536Swyllys 	if (fp == NULL)
36133408Swyllys 		return (KMF_ERR_OPEN_FILE);
36145536Swyllys 
36153408Swyllys 	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
36163408Swyllys 	if (x509_info_stack == NULL) {
36173408Swyllys 		(void) fclose(fp);
36183408Swyllys 		return (KMF_ERR_ENCODING);
36193408Swyllys 	}
36205536Swyllys 	cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
36215536Swyllys 	    sizeof (X509_INFO *));
36225536Swyllys 	if (cert_infos == NULL) {
36235536Swyllys 		(void) fclose(fp);
36245536Swyllys 		rv = KMF_ERR_MEMORY;
36255536Swyllys 		goto err;
36265536Swyllys 	}
36275536Swyllys 
36285536Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
362911673Sopensolaris@drydog.com 		/* LINTED E_BAD_PTR_CAST_ALIGN */
36304315Swyllys 		cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
36313408Swyllys 		ncerts++;
36323408Swyllys 	}
36333408Swyllys 
36343408Swyllys 	if (ncerts == 0) {
36353408Swyllys 		(void) fclose(fp);
36364315Swyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
36374315Swyllys 		goto err;
36383408Swyllys 	}
36393408Swyllys 
36403408Swyllys 	if (priv_key != NULL) {
36413408Swyllys 		rewind(fp);
36423408Swyllys 		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
36433408Swyllys 	}
36443408Swyllys 	(void) fclose(fp);
36453408Swyllys 
36463408Swyllys 	x = cert_infos[ncerts - 1]->x509;
36473408Swyllys 	/*
36483408Swyllys 	 * Make sure the private key matchs the last cert in the file.
36493408Swyllys 	 */
36503408Swyllys 	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
36513408Swyllys 		EVP_PKEY_free(pkey);
36524315Swyllys 		rv = KMF_ERR_KEY_MISMATCH;
36534315Swyllys 		goto err;
36543408Swyllys 	}
36553408Swyllys 
365611673Sopensolaris@drydog.com 	certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
36573408Swyllys 	if (certlist == NULL) {
36583408Swyllys 		if (pkey != NULL)
36593408Swyllys 			EVP_PKEY_free(pkey);
36604315Swyllys 		rv = KMF_ERR_MEMORY;
36614315Swyllys 		goto err;
36623408Swyllys 	}
36633408Swyllys 
36643408Swyllys 	/*
36653408Swyllys 	 * Convert all of the certs to DER format.
36663408Swyllys 	 */
36673754Swyllys 	matchcerts = 0;
36683408Swyllys 	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
36693754Swyllys 		boolean_t match = FALSE;
36703408Swyllys 		info =  cert_infos[ncerts - 1 - i];
36713408Swyllys 
36725051Swyllys 		rv = check_cert(info->x509, issuer, subject, serial, &match);
36735051Swyllys 		if (rv != KMF_OK || match != TRUE) {
36745051Swyllys 			rv = KMF_OK;
36755051Swyllys 			continue;
36763754Swyllys 		}
36773754Swyllys 
36783754Swyllys 		rv = ssl_cert2KMFDATA(kmfh, info->x509,
36793754Swyllys 			&certlist[matchcerts++]);
36803408Swyllys 
36813408Swyllys 		if (rv != KMF_OK) {
368211973Swyllys.ingersoll@sun.com 			int j;
368311973Swyllys.ingersoll@sun.com 			for (j = 0; j < matchcerts; j++)
368411973Swyllys.ingersoll@sun.com 				kmf_free_data(&certlist[j]);
36853408Swyllys 			free(certlist);
36863408Swyllys 			certlist = NULL;
36873754Swyllys 			ncerts = matchcerts = 0;
36883408Swyllys 		}
36893408Swyllys 	}
36903408Swyllys 
36913408Swyllys 	if (numcerts != NULL)
36923754Swyllys 		*numcerts = matchcerts;
369311673Sopensolaris@drydog.com 
369411973Swyllys.ingersoll@sun.com 	if (certs != NULL)
36953408Swyllys 		*certs = certlist;
369611973Swyllys.ingersoll@sun.com 	else if (certlist != NULL) {
369711973Swyllys.ingersoll@sun.com 		for (i = 0; i < ncerts; i++)
369811973Swyllys.ingersoll@sun.com 			kmf_free_data(&certlist[i]);
369911673Sopensolaris@drydog.com 		free(certlist);
370011673Sopensolaris@drydog.com 		certlist = NULL;
370111673Sopensolaris@drydog.com 	}
37023408Swyllys 
37033408Swyllys 	if (priv_key == NULL && pkey != NULL)
37043408Swyllys 		EVP_PKEY_free(pkey);
37053408Swyllys 	else if (priv_key != NULL && pkey != NULL)
37063408Swyllys 		*priv_key = pkey;
37073408Swyllys 
37084315Swyllys err:
37094315Swyllys 	/* Cleanup the stack of X509 info records */
37104315Swyllys 	for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
371111673Sopensolaris@drydog.com 		/* LINTED E_BAD_PTR_CAST_ALIGN */
37124315Swyllys 		info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
37134315Swyllys 		X509_INFO_free(info);
37144315Swyllys 	}
37154315Swyllys 	if (x509_info_stack)
37164315Swyllys 		sk_X509_INFO_free(x509_info_stack);
37174315Swyllys 
37185536Swyllys 	if (cert_infos != NULL)
37195536Swyllys 		free(cert_infos);
37205536Swyllys 
37213408Swyllys 	return (rv);
37223408Swyllys }
37233408Swyllys 
37245536Swyllys static KMF_RETURN
openssl_parse_bags(STACK_OF (PKCS12_SAFEBAG)* bags,char * pin,STACK_OF (EVP_PKEY)* keys,STACK_OF (X509)* certs)37255536Swyllys openssl_parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
37265536Swyllys 	STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
37275536Swyllys {
37285536Swyllys 	KMF_RETURN ret;
37295536Swyllys 	int i;
37305536Swyllys 
37315536Swyllys 	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
373211673Sopensolaris@drydog.com 		/* LINTED E_BAD_PTR_CAST_ALIGN */
37335536Swyllys 		PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
37345536Swyllys 		ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
37355536Swyllys 		    keys, certs);
37365536Swyllys 
37375536Swyllys 		if (ret != KMF_OK)
37385536Swyllys 			return (ret);
37395536Swyllys 	}
37405536Swyllys 
37415536Swyllys 	return (ret);
37425536Swyllys }
37435536Swyllys 
37445536Swyllys static KMF_RETURN
set_pkey_attrib(EVP_PKEY * pkey,ASN1_TYPE * attrib,int nid)37455536Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
37465536Swyllys {
37475536Swyllys 	X509_ATTRIBUTE *attr = NULL;
37485536Swyllys 
37495536Swyllys 	if (pkey == NULL || attrib == NULL)
37505536Swyllys 		return (KMF_ERR_BAD_PARAMETER);
37515536Swyllys 
37525536Swyllys 	if (pkey->attributes == NULL) {
37535536Swyllys 		pkey->attributes = sk_X509_ATTRIBUTE_new_null();
37545536Swyllys 		if (pkey->attributes == NULL)
37555536Swyllys 			return (KMF_ERR_MEMORY);
37565536Swyllys 	}
37575536Swyllys 	attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
37585536Swyllys 	if (attr != NULL) {
37595536Swyllys 		int i;
37605536Swyllys 		X509_ATTRIBUTE *a;
37615536Swyllys 		for (i = 0;
37625536Swyllys 		    i < sk_X509_ATTRIBUTE_num(pkey->attributes); i++) {
376311973Swyllys.ingersoll@sun.com 			/* LINTED E_BAD_PTR_CASE_ALIGN */
37645536Swyllys 			a = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
37655536Swyllys 			if (OBJ_obj2nid(a->object) == nid) {
37665536Swyllys 				X509_ATTRIBUTE_free(a);
376711673Sopensolaris@drydog.com 				/* LINTED E_BAD_PTR_CAST_ALIGN */
37685536Swyllys 				sk_X509_ATTRIBUTE_set(pkey->attributes,
37695536Swyllys 				    i, attr);
37705536Swyllys 				return (KMF_OK);
37715536Swyllys 			}
37725536Swyllys 		}
37735536Swyllys 		if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == NULL) {
37745536Swyllys 			X509_ATTRIBUTE_free(attr);
37755536Swyllys 			return (KMF_ERR_MEMORY);
37765536Swyllys 		}
37775536Swyllys 	} else {
37785536Swyllys 		return (KMF_ERR_MEMORY);
37795536Swyllys 	}
37805536Swyllys 
37815536Swyllys 	return (KMF_OK);
37825536Swyllys }
37835536Swyllys 
37845536Swyllys static KMF_RETURN
openssl_parse_bag(PKCS12_SAFEBAG * bag,char * pass,int passlen,STACK_OF (EVP_PKEY)* keylist,STACK_OF (X509)* certlist)37855536Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
37865536Swyllys 	STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
37875536Swyllys {
37885536Swyllys 	KMF_RETURN ret = KMF_OK;
37895536Swyllys 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
37905536Swyllys 	EVP_PKEY *pkey = NULL;
37915536Swyllys 	X509 *xcert = NULL;
37925536Swyllys 	ASN1_TYPE *keyid = NULL;
37935536Swyllys 	ASN1_TYPE *fname = NULL;
37945536Swyllys 	uchar_t *data = NULL;
37955536Swyllys 
37965536Swyllys 	keyid = PKCS12_get_attr(bag, NID_localKeyID);
37975536Swyllys 	fname = PKCS12_get_attr(bag, NID_friendlyName);
37985536Swyllys 
37995536Swyllys 	switch (M_PKCS12_bag_type(bag)) {
38005536Swyllys 		case NID_keyBag:
38015536Swyllys 			if (keylist == NULL)
38025536Swyllys 				goto end;
38035536Swyllys 			pkey = EVP_PKCS82PKEY(bag->value.keybag);
38045536Swyllys 			if (pkey == NULL)
38055536Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38065536Swyllys 
38075536Swyllys 			break;
38085536Swyllys 		case NID_pkcs8ShroudedKeyBag:
38095536Swyllys 			if (keylist == NULL)
38105536Swyllys 				goto end;
38115536Swyllys 			p8 = M_PKCS12_decrypt_skey(bag, pass, passlen);
38125536Swyllys 			if (p8 == NULL)
38135536Swyllys 				return (KMF_ERR_AUTH_FAILED);
38145536Swyllys 			pkey = EVP_PKCS82PKEY(p8);
38155536Swyllys 			PKCS8_PRIV_KEY_INFO_free(p8);
38165536Swyllys 			if (pkey == NULL)
38175536Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38185536Swyllys 			break;
38195536Swyllys 		case NID_certBag:
38205536Swyllys 			if (certlist == NULL)
38215536Swyllys 				goto end;
38225536Swyllys 			if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate)
38235536Swyllys 				return (KMF_ERR_PKCS12_FORMAT);
38245536Swyllys 			xcert = M_PKCS12_certbag2x509(bag);
38255536Swyllys 			if (xcert == NULL) {
38265536Swyllys 				ret = KMF_ERR_PKCS12_FORMAT;
38275536Swyllys 				goto end;
38285536Swyllys 			}
38295536Swyllys 			if (keyid != NULL) {
38305536Swyllys 				if (X509_keyid_set1(xcert,
38315536Swyllys 				    keyid->value.octet_string->data,
38325536Swyllys 				    keyid->value.octet_string->length) == 0) {
38335536Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
38345536Swyllys 					goto end;
38355536Swyllys 				}
38365536Swyllys 			}
38375536Swyllys 			if (fname != NULL) {
38385536Swyllys 				int len, r;
38395536Swyllys 				len = ASN1_STRING_to_UTF8(&data,
38405536Swyllys 				    fname->value.asn1_string);
38415536Swyllys 				if (len > 0 && data != NULL) {
38425536Swyllys 					r = X509_alias_set1(xcert, data, len);
38435536Swyllys 					if (r == NULL) {
38445536Swyllys 						ret = KMF_ERR_PKCS12_FORMAT;
38455536Swyllys 						goto end;
38465536Swyllys 					}
38475536Swyllys 				} else {
38485536Swyllys 					ret = KMF_ERR_PKCS12_FORMAT;
38495536Swyllys 					goto end;
38505536Swyllys 				}
38515536Swyllys 			}
38525536Swyllys 			if (sk_X509_push(certlist, xcert) == 0)
38535536Swyllys 				ret = KMF_ERR_MEMORY;
38545536Swyllys 			else
38555536Swyllys 				xcert = NULL;
38565536Swyllys 			break;
38575536Swyllys 		case NID_safeContentsBag:
38585536Swyllys 			return (openssl_parse_bags(bag->value.safes, pass,
38595536Swyllys 			    keylist, certlist));
38605536Swyllys 		default:
38615536Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
38625536Swyllys 			break;
38635536Swyllys 	}
38645536Swyllys 
38655536Swyllys 	/*
38665536Swyllys 	 * Set the ID and/or FriendlyName attributes on the key.
38675536Swyllys 	 * If converting to PKCS11 objects, these can translate to CKA_ID
38685536Swyllys 	 * and CKA_LABEL values.
38695536Swyllys 	 */
38705536Swyllys 	if (pkey != NULL && ret == KMF_OK) {
38715536Swyllys 		ASN1_TYPE *attr = NULL;
38725536Swyllys 		if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
38735536Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
38745536Swyllys 				return (KMF_ERR_MEMORY);
38755536Swyllys 			attr->value.octet_string =
38765536Swyllys 			    ASN1_STRING_dup(keyid->value.octet_string);
38775536Swyllys 			attr->type = V_ASN1_OCTET_STRING;
38785536Swyllys 			attr->value.ptr = (char *)attr->value.octet_string;
38795536Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
38805536Swyllys 			OPENSSL_free(attr);
38815536Swyllys 		}
38825536Swyllys 
38835536Swyllys 		if (ret == KMF_OK && fname != NULL &&
38845536Swyllys 		    fname->type == V_ASN1_BMPSTRING) {
38855536Swyllys 			if ((attr = ASN1_TYPE_new()) == NULL)
38865536Swyllys 				return (KMF_ERR_MEMORY);
38875536Swyllys 			attr->value.bmpstring =
38885536Swyllys 			    ASN1_STRING_dup(fname->value.bmpstring);
38895536Swyllys 			attr->type = V_ASN1_BMPSTRING;
38905536Swyllys 			attr->value.ptr = (char *)attr->value.bmpstring;
38915536Swyllys 			ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
38925536Swyllys 			OPENSSL_free(attr);
38935536Swyllys 		}
38945536Swyllys 
38955536Swyllys 		if (ret == KMF_OK && keylist != NULL &&
38965536Swyllys 		    sk_EVP_PKEY_push(keylist, pkey) == 0)
38975536Swyllys 			ret = KMF_ERR_MEMORY;
38985536Swyllys 	}
38995536Swyllys 	if (ret == KMF_OK && keylist != NULL)
39005536Swyllys 		pkey = NULL;
39015536Swyllys end:
39025536Swyllys 	if (pkey != NULL)
39035536Swyllys 		EVP_PKEY_free(pkey);
39045536Swyllys 	if (xcert != NULL)
39055536Swyllys 		X509_free(xcert);
39065536Swyllys 	if (data != NULL)
39075536Swyllys 		OPENSSL_free(data);
39085536Swyllys 
39095536Swyllys 	return (ret);
39105536Swyllys }
39115536Swyllys 
39125536Swyllys static KMF_RETURN
openssl_pkcs12_parse(PKCS12 * p12,char * pin,STACK_OF (EVP_PKEY)* keys,STACK_OF (X509)* certs,STACK_OF (X509)* ca)39135536Swyllys openssl_pkcs12_parse(PKCS12 *p12, char *pin,
39145536Swyllys 	STACK_OF(EVP_PKEY) *keys,
39155536Swyllys 	STACK_OF(X509) *certs,
39165536Swyllys 	STACK_OF(X509) *ca)
391711673Sopensolaris@drydog.com /* ARGSUSED3 */
39185536Swyllys {
39195536Swyllys 	KMF_RETURN ret = KMF_OK;
39205536Swyllys 	STACK_OF(PKCS7) *asafes = NULL;
39215536Swyllys 	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
39225536Swyllys 	int i, bagnid;
39235536Swyllys 	PKCS7 *p7;
39245536Swyllys 
39255536Swyllys 	if (p12 == NULL || (keys == NULL && certs == NULL))
39265536Swyllys 		return (KMF_ERR_BAD_PARAMETER);
39275536Swyllys 
39285536Swyllys 	if (pin == NULL || *pin == NULL) {
39295536Swyllys 		if (PKCS12_verify_mac(p12, NULL, 0)) {
39305536Swyllys 			pin = NULL;
39315536Swyllys 		} else if (PKCS12_verify_mac(p12, "", 0)) {
39325536Swyllys 			pin = "";
39335536Swyllys 		} else {
39345536Swyllys 			return (KMF_ERR_AUTH_FAILED);
39355536Swyllys 		}
39365536Swyllys 	} else if (!PKCS12_verify_mac(p12, pin, -1)) {
39375536Swyllys 		return (KMF_ERR_AUTH_FAILED);
39385536Swyllys 	}
39395536Swyllys 
39405536Swyllys 	if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
39415536Swyllys 		return (KMF_ERR_PKCS12_FORMAT);
39425536Swyllys 
39435536Swyllys 	for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
39445536Swyllys 		bags = NULL;
394511673Sopensolaris@drydog.com 		/* LINTED E_BAD_PTR_CAST_ALIGN */
39465536Swyllys 		p7 = sk_PKCS7_value(asafes, i);
39475536Swyllys 		bagnid = OBJ_obj2nid(p7->type);
39485536Swyllys 
39495536Swyllys 		if (bagnid == NID_pkcs7_data) {
39505536Swyllys 			bags = PKCS12_unpack_p7data(p7);
39515536Swyllys 		} else if (bagnid == NID_pkcs7_encrypted) {
39525536Swyllys 			bags = PKCS12_unpack_p7encdata(p7, pin,
39535536Swyllys 			    (pin ? strlen(pin) : 0));
39545536Swyllys 		} else {
39555536Swyllys 			continue;
39565536Swyllys 		}
39575536Swyllys 		if (bags == NULL) {
39585536Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39595536Swyllys 			goto out;
39605536Swyllys 		}
39615536Swyllys 
39625536Swyllys 		if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
39635536Swyllys 			ret = KMF_ERR_PKCS12_FORMAT;
39645536Swyllys 
39655536Swyllys 		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
39665536Swyllys 	}
39675536Swyllys out:
39685536Swyllys 	if (asafes != NULL)
39695536Swyllys 		sk_PKCS7_pop_free(asafes, PKCS7_free);
39705536Swyllys 
39715536Swyllys 	return (ret);
39725536Swyllys }
39735536Swyllys 
39743089Swyllys /*
39753089Swyllys  * Helper function to decrypt and parse PKCS#12 import file.
39763089Swyllys  */
39773089Swyllys 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)39783089Swyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
39795536Swyllys 	STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs,
39805536Swyllys 	STACK_OF(X509) **ca)
398111673Sopensolaris@drydog.com /* ARGSUSED2 */
39823089Swyllys {
39835536Swyllys 	PKCS12			*pk12, *pk12_tmp;
39845536Swyllys 	STACK_OF(EVP_PKEY)	*pkeylist = NULL;
39855536Swyllys 	STACK_OF(X509)		*xcertlist = NULL;
39865536Swyllys 	STACK_OF(X509)		*cacertlist = NULL;
39873089Swyllys 
39883089Swyllys 	if ((pk12 = PKCS12_new()) == NULL) {
39893089Swyllys 		return (KMF_ERR_MEMORY);
39903089Swyllys 	}
39913089Swyllys 
39923089Swyllys 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
39933089Swyllys 		/* This is ok; it seems to mean there is no more to read. */
39943089Swyllys 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
39953089Swyllys 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
39963089Swyllys 			goto end_extract_pkcs12;
39973089Swyllys 
39983089Swyllys 		PKCS12_free(pk12);
39993089Swyllys 		return (KMF_ERR_PKCS12_FORMAT);
40003089Swyllys 	}
40013089Swyllys 	pk12 = pk12_tmp;
40023089Swyllys 
40035536Swyllys 	xcertlist = sk_X509_new_null();
40045536Swyllys 	if (xcertlist == NULL) {
40055536Swyllys 		PKCS12_free(pk12);
40065536Swyllys 		return (KMF_ERR_MEMORY);
40075536Swyllys 	}
40085536Swyllys 	pkeylist = sk_EVP_PKEY_new_null();
40095536Swyllys 	if (pkeylist == NULL) {
40105536Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40115536Swyllys 		PKCS12_free(pk12);
40125536Swyllys 		return (KMF_ERR_MEMORY);
40135536Swyllys 	}
40145536Swyllys 
40155536Swyllys 	if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
40165536Swyllys 	    cacertlist) != KMF_OK) {
40175536Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40185536Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
40193089Swyllys 		PKCS12_free(pk12);
40203089Swyllys 		return (KMF_ERR_PKCS12_FORMAT);
40213089Swyllys 	}
40223089Swyllys 
40235536Swyllys 	if (priv_key && pkeylist)
40245536Swyllys 		*priv_key = pkeylist;
40255536Swyllys 	else if (pkeylist)
40265536Swyllys 		sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
40275536Swyllys 	if (certs && xcertlist)
40285536Swyllys 		*certs = xcertlist;
40295536Swyllys 	else if (xcertlist)
40305536Swyllys 		sk_X509_pop_free(xcertlist, X509_free);
40315536Swyllys 	if (ca && cacertlist)
40325536Swyllys 		*ca = cacertlist;
40335536Swyllys 	else if (cacertlist)
40345536Swyllys 		sk_X509_pop_free(cacertlist, X509_free);
40355536Swyllys 
40363089Swyllys end_extract_pkcs12:
40373089Swyllys 
40383089Swyllys 	PKCS12_free(pk12);
40393089Swyllys 	return (KMF_OK);
40403089Swyllys }
40413089Swyllys 
40423089Swyllys static KMF_RETURN
sslBN2KMFBN(BIGNUM * from,KMF_BIGINT * to)40433089Swyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
40443089Swyllys {
40453089Swyllys 	KMF_RETURN rv = KMF_OK;
40463089Swyllys 	uint32_t sz;
40473089Swyllys 
40483089Swyllys 	sz = BN_num_bytes(from);
40493089Swyllys 	to->val = (uchar_t *)malloc(sz);
40503089Swyllys 	if (to->val == NULL)
40513089Swyllys 		return (KMF_ERR_MEMORY);
40523089Swyllys 
40533089Swyllys 	if ((to->len = BN_bn2bin(from, to->val)) != sz) {
40543089Swyllys 		free(to->val);
40553089Swyllys 		to->val = NULL;
40563089Swyllys 		to->len = 0;
40573089Swyllys 		rv = KMF_ERR_MEMORY;
40583089Swyllys 	}
40593089Swyllys 
40603089Swyllys 	return (rv);
40613089Swyllys }
40623089Swyllys 
40633089Swyllys static KMF_RETURN
exportRawRSAKey(RSA * rsa,KMF_RAW_KEY_DATA * key)40643089Swyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
40653089Swyllys {
40663089Swyllys 	KMF_RETURN rv;
40673089Swyllys 	KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
40683089Swyllys 
40693089Swyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
40703089Swyllys 	if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK)
40713089Swyllys 		goto cleanup;
40723089Swyllys 
40733089Swyllys 	if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK)
40743089Swyllys 		goto cleanup;
40753089Swyllys 
40763089Swyllys 	if (rsa->d != NULL)
40773089Swyllys 		if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK)
40783089Swyllys 			goto cleanup;
40793089Swyllys 
40803089Swyllys 	if (rsa->p != NULL)
40813089Swyllys 		if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK)
40823089Swyllys 			goto cleanup;
40833089Swyllys 
40843089Swyllys 	if (rsa->q != NULL)
40853089Swyllys 		if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK)
40863089Swyllys 			goto cleanup;
40873089Swyllys 
40883089Swyllys 	if (rsa->dmp1 != NULL)
40893089Swyllys 		if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK)
40903089Swyllys 			goto cleanup;
40913089Swyllys 
40923089Swyllys 	if (rsa->dmq1 != NULL)
40933089Swyllys 		if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK)
40943089Swyllys 			goto cleanup;
40953089Swyllys 
40963089Swyllys 	if (rsa->iqmp != NULL)
40973089Swyllys 		if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK)
40983089Swyllys 			goto cleanup;
40993089Swyllys cleanup:
41003089Swyllys 	if (rv != KMF_OK)
41015051Swyllys 		kmf_free_raw_key(key);
41023089Swyllys 	else
41033089Swyllys 		key->keytype = KMF_RSA;
41043089Swyllys 
41053089Swyllys 	/*
41063089Swyllys 	 * Free the reference to this key, SSL will not actually free
41073089Swyllys 	 * the memory until the refcount == 0, so this is safe.
41083089Swyllys 	 */
41093089Swyllys 	RSA_free(rsa);
41103089Swyllys 
41113089Swyllys 	return (rv);
41123089Swyllys }
41133089Swyllys 
41143089Swyllys static KMF_RETURN
exportRawDSAKey(DSA * dsa,KMF_RAW_KEY_DATA * key)41153089Swyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
41163089Swyllys {
41173089Swyllys 	KMF_RETURN rv;
41183089Swyllys 	KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
41193089Swyllys 
41203089Swyllys 	(void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
41213089Swyllys 	if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK)
41223089Swyllys 		goto cleanup;
41233089Swyllys 
41243089Swyllys 	if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK)
41253089Swyllys 		goto cleanup;
41263089Swyllys 
41273089Swyllys 	if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK)
41283089Swyllys 		goto cleanup;
41293089Swyllys 
41303089Swyllys 	if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK)
41313089Swyllys 		goto cleanup;
41323089Swyllys 
41333089Swyllys cleanup:
41343089Swyllys 	if (rv != KMF_OK)
41355051Swyllys 		kmf_free_raw_key(key);
41363089Swyllys 	else
41373089Swyllys 		key->keytype = KMF_DSA;
41383089Swyllys 
41393089Swyllys 	/*
41403089Swyllys 	 * Free the reference to this key, SSL will not actually free
41413089Swyllys 	 * the memory until the refcount == 0, so this is safe.
41423089Swyllys 	 */
41433089Swyllys 	DSA_free(dsa);
41443089Swyllys 
41453089Swyllys 	return (rv);
41463089Swyllys }
41473089Swyllys 
41483089Swyllys static KMF_RETURN
add_cert_to_list(KMF_HANDLE * kmfh,X509 * sslcert,KMF_X509_DER_CERT ** certlist,int * ncerts)41493089Swyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
41505536Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
41513089Swyllys {
41523089Swyllys 	KMF_RETURN rv = KMF_OK;
41535536Swyllys 	KMF_X509_DER_CERT *list = (*certlist);
41545536Swyllys 	KMF_X509_DER_CERT cert;
41553089Swyllys 	int n = (*ncerts);
41563089Swyllys 
41573089Swyllys 	if (list == NULL) {
41585536Swyllys 		list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
41593089Swyllys 	} else {
41605536Swyllys 		list = (KMF_X509_DER_CERT *)realloc(list,
41615536Swyllys 		    sizeof (KMF_X509_DER_CERT) * (n + 1));
41623089Swyllys 	}
41633089Swyllys 
41643089Swyllys 	if (list == NULL)
41653089Swyllys 		return (KMF_ERR_MEMORY);
41663089Swyllys 
41675536Swyllys 	(void) memset(&cert, 0, sizeof (cert));
41685536Swyllys 	rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
41693089Swyllys 	if (rv == KMF_OK) {
41705536Swyllys 		int len = 0;
41715536Swyllys 		/* Get the alias name for the cert if there is one */
41725536Swyllys 		char *a = (char *)X509_alias_get0(sslcert, &len);
41735536Swyllys 		if (a != NULL)
41745536Swyllys 			cert.kmf_private.label = strdup(a);
41755536Swyllys 		cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
41765536Swyllys 
41773089Swyllys 		list[n] = cert;
41783089Swyllys 		(*ncerts) = n + 1;
41793089Swyllys 
41803089Swyllys 		*certlist = list;
41813089Swyllys 	} else {
41823089Swyllys 		free(list);
41833089Swyllys 	}
41843089Swyllys 
41853089Swyllys 	return (rv);
41863089Swyllys }
41873089Swyllys 
41883089Swyllys static KMF_RETURN
add_key_to_list(KMF_RAW_KEY_DATA ** keylist,KMF_RAW_KEY_DATA * newkey,int * nkeys)41893089Swyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
41903089Swyllys 	KMF_RAW_KEY_DATA *newkey, int *nkeys)
41913089Swyllys {
41923089Swyllys 	KMF_RAW_KEY_DATA *list = (*keylist);
41933089Swyllys 	int n = (*nkeys);
41943089Swyllys 
41953089Swyllys 	if (list == NULL) {
41963089Swyllys 		list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
41973089Swyllys 	} else {
41983089Swyllys 		list = (KMF_RAW_KEY_DATA *)realloc(list,
41994315Swyllys 		    sizeof (KMF_RAW_KEY_DATA) * (n + 1));
42003089Swyllys 	}
42013089Swyllys 
42023089Swyllys 	if (list == NULL)
42033089Swyllys 		return (KMF_ERR_MEMORY);
42043089Swyllys 
42053089Swyllys 	list[n] = *newkey;
42063089Swyllys 	(*nkeys) = n + 1;
42073089Swyllys 
42083089Swyllys 	*keylist = list;
42093089Swyllys 
42103089Swyllys 	return (KMF_OK);
42113089Swyllys }
42123089Swyllys 
42135536Swyllys static X509_ATTRIBUTE *
find_attr(STACK_OF (X509_ATTRIBUTE)* attrs,int nid)42145536Swyllys find_attr(STACK_OF(X509_ATTRIBUTE) *attrs, int nid)
42155536Swyllys {
42165536Swyllys 	X509_ATTRIBUTE *a;
42175536Swyllys 	int i;
42185536Swyllys 
42195536Swyllys 	if (attrs == NULL)
42205536Swyllys 		return (NULL);
42215536Swyllys 
42225536Swyllys 	for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
422311673Sopensolaris@drydog.com 		/* LINTED E_BAD_PTR_CAST_ALIGN */
42245536Swyllys 		a = sk_X509_ATTRIBUTE_value(attrs, i);
42255536Swyllys 		if (OBJ_obj2nid(a->object) == nid)
42265536Swyllys 			return (a);
42275536Swyllys 	}
42285536Swyllys 	return (NULL);
42295536Swyllys }
42305536Swyllys 
42315051Swyllys static KMF_RETURN
convertToRawKey(EVP_PKEY * pkey,KMF_RAW_KEY_DATA * key)42325051Swyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
42335051Swyllys {
42345051Swyllys 	KMF_RETURN rv = KMF_OK;
42355536Swyllys 	X509_ATTRIBUTE *attr;
42365051Swyllys 
42375051Swyllys 	if (pkey == NULL || key == NULL)
42385051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
42395051Swyllys 	/* Convert SSL key to raw key */
42405051Swyllys 	switch (pkey->type) {
42415051Swyllys 		case EVP_PKEY_RSA:
42425051Swyllys 			rv = exportRawRSAKey(EVP_PKEY_get1_RSA(pkey),
42435051Swyllys 			    key);
42445051Swyllys 			if (rv != KMF_OK)
42455051Swyllys 				return (rv);
42465051Swyllys 			break;
42475051Swyllys 		case EVP_PKEY_DSA:
42485051Swyllys 			rv = exportRawDSAKey(EVP_PKEY_get1_DSA(pkey),
42495051Swyllys 			    key);
42505051Swyllys 			if (rv != KMF_OK)
42515051Swyllys 				return (rv);
42525051Swyllys 			break;
42535051Swyllys 		default:
42545051Swyllys 			return (KMF_ERR_BAD_PARAMETER);
42555051Swyllys 	}
42565536Swyllys 	/*
42575536Swyllys 	 * If friendlyName, add it to record.
42585536Swyllys 	 */
42595536Swyllys 	attr = find_attr(pkey->attributes, NID_friendlyName);
42605536Swyllys 	if (attr != NULL) {
42615536Swyllys 		ASN1_TYPE *ty = NULL;
42625536Swyllys 		int numattr = sk_ASN1_TYPE_num(attr->value.set);
42635536Swyllys 		if (attr->single == 0 && numattr > 0) {
426411673Sopensolaris@drydog.com 			/* LINTED E_BAD_PTR_CAST_ALIGN */
42655536Swyllys 			ty = sk_ASN1_TYPE_value(attr->value.set, 0);
42665536Swyllys 		}
42675536Swyllys 		if (ty != NULL) {
42685536Swyllys 			key->label = uni2asc(ty->value.bmpstring->data,
42695536Swyllys 			    ty->value.bmpstring->length);
42705536Swyllys 		}
42715536Swyllys 	} else {
42725536Swyllys 		key->label = NULL;
42735536Swyllys 	}
42745536Swyllys 
42755536Swyllys 	/*
42765536Swyllys 	 * If KeyID, add it to record as a KMF_DATA object.
42775536Swyllys 	 */
42785536Swyllys 	attr = find_attr(pkey->attributes, NID_localKeyID);
42795536Swyllys 	if (attr != NULL) {
42805536Swyllys 		ASN1_TYPE *ty = NULL;
42815536Swyllys 		int numattr = sk_ASN1_TYPE_num(attr->value.set);
42825536Swyllys 		if (attr->single == 0 && numattr > 0) {
428311673Sopensolaris@drydog.com 			/* LINTED E_BAD_PTR_CAST_ALIGN */
42845536Swyllys 			ty = sk_ASN1_TYPE_value(attr->value.set, 0);
42855536Swyllys 		}
42865536Swyllys 		key->id.Data = (uchar_t *)malloc(
42875536Swyllys 		    ty->value.octet_string->length);
42885536Swyllys 		if (key->id.Data == NULL)
42895536Swyllys 			return (KMF_ERR_MEMORY);
42905536Swyllys 		(void) memcpy(key->id.Data, ty->value.octet_string->data,
42915536Swyllys 		    ty->value.octet_string->length);
42925536Swyllys 		key->id.Length = ty->value.octet_string->length;
42935536Swyllys 	} else {
42945536Swyllys 		(void) memset(&key->id, 0, sizeof (KMF_DATA));
42955536Swyllys 	}
42965051Swyllys 
42975051Swyllys 	return (rv);
42985051Swyllys }
42993089Swyllys 
43003089Swyllys 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)43013089Swyllys convertPK12Objects(
43023089Swyllys 	KMF_HANDLE *kmfh,
43035536Swyllys 	STACK_OF(EVP_PKEY) *sslkeys,
43045536Swyllys 	STACK_OF(X509) *sslcert,
43055536Swyllys 	STACK_OF(X509) *sslcacerts,
43063089Swyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys,
43075536Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts)
43083089Swyllys {
43093089Swyllys 	KMF_RETURN rv = KMF_OK;
43103089Swyllys 	KMF_RAW_KEY_DATA key;
43113089Swyllys 	int i;
43123089Swyllys 
43135536Swyllys 	for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
431411673Sopensolaris@drydog.com 		/* LINTED E_BAD_PTR_CAST_ALIGN */
43155536Swyllys 		EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
43165536Swyllys 		rv = convertToRawKey(pkey, &key);
43175051Swyllys 		if (rv == KMF_OK)
43185051Swyllys 			rv = add_key_to_list(keylist, &key, nkeys);
43195051Swyllys 
43203089Swyllys 		if (rv != KMF_OK)
43213089Swyllys 			return (rv);
43223089Swyllys 	}
43233089Swyllys 
43243089Swyllys 	/* Now add the certificate to the certlist */
43255536Swyllys 	for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
432611673Sopensolaris@drydog.com 		/* LINTED E_BAD_PTR_CAST_ALIGN */
43275536Swyllys 		X509 *cert = sk_X509_value(sslcert, i);
43285536Swyllys 		rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
43293089Swyllys 		if (rv != KMF_OK)
43303089Swyllys 			return (rv);
43313089Swyllys 	}
43323089Swyllys 
43333089Swyllys 	/* Also add any included CA certs to the list */
43343408Swyllys 	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
43353089Swyllys 		X509 *c;
43363089Swyllys 		/*
43373089Swyllys 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
43383089Swyllys 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
43393089Swyllys 		 * Lint is complaining about the embedded casting, and
43403089Swyllys 		 * to fix it, you need to fix openssl header files.
43413089Swyllys 		 */
43423089Swyllys 		/* LINTED E_BAD_PTR_CAST_ALIGN */
43433089Swyllys 		c = sk_X509_value(sslcacerts, i);
43443089Swyllys 
43453089Swyllys 		/* Now add the ca cert to the certlist */
43463089Swyllys 		rv = add_cert_to_list(kmfh, c, certlist, ncerts);
43473089Swyllys 		if (rv != KMF_OK)
43483089Swyllys 			return (rv);
43493089Swyllys 	}
43503089Swyllys 	return (rv);
43513089Swyllys }
43523089Swyllys 
43533089Swyllys 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)43545051Swyllys openssl_import_objects(KMF_HANDLE *kmfh,
43553408Swyllys 	char *filename, KMF_CREDENTIAL *cred,
43565536Swyllys 	KMF_X509_DER_CERT **certlist, int *ncerts,
43573408Swyllys 	KMF_RAW_KEY_DATA **keylist, int *nkeys)
43583408Swyllys {
43593408Swyllys 	KMF_RETURN	rv = KMF_OK;
43603408Swyllys 	KMF_ENCODE_FORMAT format;
43615051Swyllys 	BIO		*bio = NULL;
43625536Swyllys 	STACK_OF(EVP_PKEY)	*privkeys = NULL;
43635536Swyllys 	STACK_OF(X509)		*certs = NULL;
43645536Swyllys 	STACK_OF(X509)		*cacerts = NULL;
43653408Swyllys 
43663408Swyllys 	/*
43673408Swyllys 	 * auto-detect the file format, regardless of what
43683408Swyllys 	 * the 'format' parameters in the params say.
43693408Swyllys 	 */
43705051Swyllys 	rv = kmf_get_file_format(filename, &format);
43713408Swyllys 	if (rv != KMF_OK) {
43723408Swyllys 		return (rv);
43733408Swyllys 	}
43743408Swyllys 
43755051Swyllys 	/* This function only works for PEM or PKCS#12 files */
43763408Swyllys 	if (format != KMF_FORMAT_PEM &&
43775051Swyllys 	    format != KMF_FORMAT_PEM_KEYPAIR &&
43785051Swyllys 	    format != KMF_FORMAT_PKCS12)
43793408Swyllys 		return (KMF_ERR_ENCODING);
43803408Swyllys 
43813408Swyllys 	*certlist = NULL;
43823408Swyllys 	*keylist = NULL;
43833408Swyllys 	*ncerts = 0;
43843408Swyllys 	*nkeys = 0;
43855051Swyllys 
43865051Swyllys 	if (format == KMF_FORMAT_PKCS12) {
43875051Swyllys 		bio = BIO_new_file(filename, "rb");
43885051Swyllys 		if (bio == NULL) {
43895051Swyllys 			SET_ERROR(kmfh, ERR_get_error());
43905051Swyllys 			rv = KMF_ERR_OPEN_FILE;
43915051Swyllys 			goto end;
43925051Swyllys 		}
43935051Swyllys 
43945051Swyllys 		rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
43955536Swyllys 		    (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
43965051Swyllys 
43975051Swyllys 		if (rv  == KMF_OK)
43985051Swyllys 			/* Convert keys and certs to exportable format */
43995536Swyllys 			rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
44005051Swyllys 			    keylist, nkeys, certlist, ncerts);
44015051Swyllys 	} else {
44025536Swyllys 		EVP_PKEY *pkey;
44035536Swyllys 		KMF_DATA *certdata = NULL;
44045536Swyllys 		KMF_X509_DER_CERT *kmfcerts = NULL;
44055536Swyllys 		int i;
44065051Swyllys 		rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
44075051Swyllys 		    (uchar_t *)cred->cred, (uint32_t)cred->credlen,
44085536Swyllys 		    &pkey, &certdata, ncerts);
44095051Swyllys 
44105051Swyllys 		/* Reached end of import file? */
44115536Swyllys 		if (rv == KMF_OK && pkey != NULL) {
44125536Swyllys 			privkeys = sk_EVP_PKEY_new_null();
44135536Swyllys 			if (privkeys == NULL) {
44145536Swyllys 				rv = KMF_ERR_MEMORY;
44155536Swyllys 				goto end;
44165536Swyllys 			}
44175536Swyllys 			(void) sk_EVP_PKEY_push(privkeys, pkey);
44185536Swyllys 			/* convert the certificate list here */
44195536Swyllys 			if (*ncerts > 0 && certlist != NULL) {
442011973Swyllys.ingersoll@sun.com 				kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
44215536Swyllys 				    sizeof (KMF_X509_DER_CERT));
44225536Swyllys 				if (kmfcerts == NULL) {
44235536Swyllys 					rv = KMF_ERR_MEMORY;
44245536Swyllys 					goto end;
44255536Swyllys 				}
44265536Swyllys 				for (i = 0; i < *ncerts; i++) {
44275536Swyllys 					kmfcerts[i].certificate = certdata[i];
44285536Swyllys 					kmfcerts[i].kmf_private.keystore_type =
44295536Swyllys 					    KMF_KEYSTORE_OPENSSL;
44305536Swyllys 				}
44315536Swyllys 				*certlist = kmfcerts;
44325536Swyllys 			}
44335536Swyllys 			/*
44345536Swyllys 			 * Convert keys to exportable format, the certs
44355536Swyllys 			 * are already OK.
44365536Swyllys 			 */
44375536Swyllys 			rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
44385051Swyllys 			    keylist, nkeys, NULL, NULL);
44395536Swyllys 		}
44405536Swyllys 	}
44413408Swyllys end:
44425051Swyllys 	if (bio != NULL)
44433089Swyllys 		(void) BIO_free(bio);
44443089Swyllys 
44455536Swyllys 	if (privkeys)
44465536Swyllys 		sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
44475536Swyllys 	if (certs)
44485536Swyllys 		sk_X509_pop_free(certs, X509_free);
44495051Swyllys 	if (cacerts)
44505536Swyllys 		sk_X509_pop_free(cacerts, X509_free);
44515051Swyllys 
44523089Swyllys 	return (rv);
44533089Swyllys }
44543089Swyllys 
44553089Swyllys static KMF_RETURN
create_deskey(DES_cblock ** deskey)44563089Swyllys create_deskey(DES_cblock **deskey)
44573089Swyllys {
44583089Swyllys 	DES_cblock *key;
44593089Swyllys 
44603089Swyllys 	key = (DES_cblock *) malloc(sizeof (DES_cblock));
44613089Swyllys 	if (key == NULL) {
44623089Swyllys 		return (KMF_ERR_MEMORY);
44633089Swyllys 	}
44643089Swyllys 
44653089Swyllys 	if (DES_random_key(key) == 0) {
44663089Swyllys 		free(key);
44673089Swyllys 		return (KMF_ERR_KEYGEN_FAILED);
44683089Swyllys 	}
44693089Swyllys 
44703089Swyllys 	*deskey = key;
44713089Swyllys 	return (KMF_OK);
44723089Swyllys }
44733089Swyllys 
44743089Swyllys #define	KEYGEN_RETRY 3
44753089Swyllys #define	DES3_KEY_SIZE 24
44763089Swyllys 
44773089Swyllys static KMF_RETURN
create_des3key(unsigned char ** des3key)44783089Swyllys create_des3key(unsigned char **des3key)
44793089Swyllys {
44803089Swyllys 	KMF_RETURN ret = KMF_OK;
44813089Swyllys 	DES_cblock *deskey1 = NULL;
44823089Swyllys 	DES_cblock *deskey2 = NULL;
44833089Swyllys 	DES_cblock *deskey3 = NULL;
44843089Swyllys 	unsigned char *newkey = NULL;
44853089Swyllys 	int retry;
44863089Swyllys 
44873089Swyllys 	if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
44883089Swyllys 		return (KMF_ERR_MEMORY);
44893089Swyllys 	}
44903089Swyllys 
44913089Swyllys 	/* create the 1st DES key */
44923089Swyllys 	if ((ret = create_deskey(&deskey1)) != KMF_OK) {
44933089Swyllys 		goto out;
44943089Swyllys 	}
44953089Swyllys 
44963089Swyllys 	/*
44973089Swyllys 	 * Create the 2nd DES key and make sure its value is different
44983089Swyllys 	 * from the 1st DES key.
44993089Swyllys 	 */
45003089Swyllys 	retry = 0;
45013089Swyllys 	do {
45023089Swyllys 		if (deskey2 != NULL) {
45033089Swyllys 			free(deskey2);
45043089Swyllys 			deskey2 = NULL;
45053089Swyllys 		}
45063089Swyllys 
45073089Swyllys 		if ((ret = create_deskey(&deskey2)) != KMF_OK) {
45083089Swyllys 			goto out;
45093089Swyllys 		}
45103089Swyllys 
45113089Swyllys 		if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
45123089Swyllys 		    == 0) {
45133089Swyllys 			ret = KMF_ERR_KEYGEN_FAILED;
45143089Swyllys 			retry++;
45153089Swyllys 		}
45163089Swyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
45173089Swyllys 
45183089Swyllys 	if (ret != KMF_OK) {
45193089Swyllys 		goto out;
45203089Swyllys 	}
45213089Swyllys 
45223089Swyllys 	/*
45233089Swyllys 	 * Create the 3rd DES key and make sure its value is different
45243089Swyllys 	 * from the 2nd DES key.
45253089Swyllys 	 */
45263089Swyllys 	retry = 0;
45273089Swyllys 	do {
45283089Swyllys 		if (deskey3 != NULL) {
45293089Swyllys 			free(deskey3);
45303089Swyllys 			deskey3 = NULL;
45313089Swyllys 		}
45323089Swyllys 
45333089Swyllys 		if ((ret = create_deskey(&deskey3)) != KMF_OK) {
45343089Swyllys 			goto out;
45353089Swyllys 		}
45363089Swyllys 
45373089Swyllys 		if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
45383089Swyllys 		    == 0) {
45393089Swyllys 			ret = KMF_ERR_KEYGEN_FAILED;
45403089Swyllys 			retry++;
45413089Swyllys 		}
45423089Swyllys 	} while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
45433089Swyllys 
45443089Swyllys 	if (ret != KMF_OK) {
45453089Swyllys 		goto out;
45463089Swyllys 	}
45473089Swyllys 
45483089Swyllys 	/* Concatenate 3 DES keys into a DES3 key */
45493089Swyllys 	(void) memcpy((void *)newkey, (const void *)deskey1, 8);
45503089Swyllys 	(void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
45513089Swyllys 	(void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
45523089Swyllys 	*des3key = newkey;
45533089Swyllys 
45543089Swyllys out:
45553089Swyllys 	if (deskey1 != NULL)
45563089Swyllys 		free(deskey1);
45573089Swyllys 
45583089Swyllys 	if (deskey2 != NULL)
45593089Swyllys 		free(deskey2);
45603089Swyllys 
45613089Swyllys 	if (deskey3 != NULL)
45623089Swyllys 		free(deskey3);
45633089Swyllys 
45643089Swyllys 	if (ret != KMF_OK && newkey != NULL)
45653089Swyllys 		free(newkey);
45663089Swyllys 
45673089Swyllys 	return (ret);
45683089Swyllys }
45693089Swyllys 
45703089Swyllys KMF_RETURN
OpenSSL_CreateSymKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)45715051Swyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
45725051Swyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
45733089Swyllys {
45743089Swyllys 	KMF_RETURN ret = KMF_OK;
45753089Swyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
45763089Swyllys 	char *fullpath = NULL;
45773089Swyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
45783089Swyllys 	DES_cblock *deskey = NULL;
45793089Swyllys 	unsigned char *des3key = NULL;
45803089Swyllys 	unsigned char *random = NULL;
45813089Swyllys 	int fd = -1;
45825051Swyllys 	KMF_KEY_HANDLE *symkey;
45835051Swyllys 	KMF_KEY_ALG keytype;
45845051Swyllys 	uint32_t keylen;
45855051Swyllys 	uint32_t keylen_size = sizeof (keylen);
45865051Swyllys 	char *dirpath;
45875051Swyllys 	char *keyfile;
45883089Swyllys 
45893089Swyllys 	if (kmfh == NULL)
45903089Swyllys 		return (KMF_ERR_UNINITIALIZED);
45913089Swyllys 
45925051Swyllys 	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
45935051Swyllys 	if (symkey == NULL)
45945051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
45955051Swyllys 
45965051Swyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
45975051Swyllys 
45985051Swyllys 	keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
45995051Swyllys 	if (keyfile == NULL)
46003089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
46015051Swyllys 
46025051Swyllys 	ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
46035051Swyllys 	    (void *)&keytype, NULL);
46045051Swyllys 	if (ret != KMF_OK)
46055051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
46065051Swyllys 
46075051Swyllys 	ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
46085051Swyllys 	    &keylen, &keylen_size);
46095051Swyllys 	if (ret == KMF_ERR_ATTR_NOT_FOUND &&
46105051Swyllys 	    (keytype == KMF_DES || keytype == KMF_DES3))
46115051Swyllys 		/* keylength is not required for DES and 3DES */
46125051Swyllys 		ret = KMF_OK;
46135051Swyllys 	if (ret != KMF_OK)
46145051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
46155051Swyllys 
46165051Swyllys 	fullpath = get_fullpath(dirpath, keyfile);
46173089Swyllys 	if (fullpath == NULL)
46183089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
46193089Swyllys 
46203089Swyllys 	/* If the requested file exists, return an error */
46215051Swyllys 	if (test_for_file(fullpath, 0400) == 1) {
46223089Swyllys 		free(fullpath);
46233089Swyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
46243089Swyllys 	}
46253089Swyllys 
46263089Swyllys 	fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
46273089Swyllys 	if (fd == -1) {
46283089Swyllys 		ret = KMF_ERR_OPEN_FILE;
46293089Swyllys 		goto out;
46303089Swyllys 	}
46313089Swyllys 
46323089Swyllys 	rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
46333089Swyllys 	if (rkey == NULL) {
46343089Swyllys 		ret = KMF_ERR_MEMORY;
46353089Swyllys 		goto out;
46363089Swyllys 	}
46373089Swyllys 	(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
46383089Swyllys 
46395051Swyllys 	if (keytype == KMF_DES) {
46403089Swyllys 		if ((ret = create_deskey(&deskey)) != KMF_OK) {
46413089Swyllys 			goto out;
46423089Swyllys 		}
46433089Swyllys 		rkey->keydata.val = (uchar_t *)deskey;
46443089Swyllys 		rkey->keydata.len = 8;
46453089Swyllys 
46463089Swyllys 		symkey->keyalg = KMF_DES;
46473089Swyllys 
46485051Swyllys 	} else if (keytype == KMF_DES3) {
46493089Swyllys 		if ((ret = create_des3key(&des3key)) != KMF_OK) {
46503089Swyllys 			goto out;
46513089Swyllys 		}
46523089Swyllys 		rkey->keydata.val = (uchar_t *)des3key;
46533089Swyllys 		rkey->keydata.len = DES3_KEY_SIZE;
46543089Swyllys 		symkey->keyalg = KMF_DES3;
46553825Swyllys 
46565051Swyllys 	} else if (keytype == KMF_AES || keytype == KMF_RC4 ||
46575051Swyllys 	    keytype == KMF_GENERIC_SECRET) {
46583089Swyllys 		int bytes;
46593089Swyllys 
46605051Swyllys 		if (keylen % 8 != 0) {
46613089Swyllys 			ret = KMF_ERR_BAD_KEY_SIZE;
46623089Swyllys 			goto out;
46633089Swyllys 		}
46643089Swyllys 
46655051Swyllys 		if (keytype == KMF_AES) {
46665051Swyllys 			if (keylen != 128 &&
46675051Swyllys 			    keylen != 192 &&
46685051Swyllys 			    keylen != 256) {
46693089Swyllys 				ret = KMF_ERR_BAD_KEY_SIZE;
46703089Swyllys 				goto out;
46713089Swyllys 			}
46723089Swyllys 		}
46733089Swyllys 
46745051Swyllys 		bytes = keylen/8;
46753089Swyllys 		random = malloc(bytes);
46763089Swyllys 		if (random == NULL) {
46773089Swyllys 			ret = KMF_ERR_MEMORY;
46783089Swyllys 			goto out;
46793089Swyllys 		}
46803089Swyllys 		if (RAND_bytes(random, bytes) != 1) {
46813089Swyllys 			ret = KMF_ERR_KEYGEN_FAILED;
46823089Swyllys 			goto out;
46833089Swyllys 		}
46843089Swyllys 
46853089Swyllys 		rkey->keydata.val = (uchar_t *)random;
46863089Swyllys 		rkey->keydata.len = bytes;
46875051Swyllys 		symkey->keyalg = keytype;
46883089Swyllys 
46893089Swyllys 	} else {
46903089Swyllys 		ret = KMF_ERR_BAD_KEY_TYPE;
46913089Swyllys 		goto out;
46923089Swyllys 	}
46933089Swyllys 
46943089Swyllys 	(void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
46953089Swyllys 
46963089Swyllys 	symkey->kstype = KMF_KEYSTORE_OPENSSL;
46973089Swyllys 	symkey->keyclass = KMF_SYMMETRIC;
46983089Swyllys 	symkey->keylabel = (char *)fullpath;
46993089Swyllys 	symkey->israw = TRUE;
47003089Swyllys 	symkey->keyp = rkey;
47013089Swyllys 
47023089Swyllys out:
47033089Swyllys 	if (fd != -1)
47043089Swyllys 		(void) close(fd);
47053089Swyllys 
47063089Swyllys 	if (ret != KMF_OK && fullpath != NULL) {
47073089Swyllys 		free(fullpath);
47083089Swyllys 	}
47093089Swyllys 	if (ret != KMF_OK) {
47105051Swyllys 		kmf_free_raw_sym_key(rkey);
47113089Swyllys 		symkey->keyp = NULL;
47123089Swyllys 		symkey->keyalg = KMF_KEYALG_NONE;
47133089Swyllys 	}
47143089Swyllys 
47153089Swyllys 	return (ret);
47163089Swyllys }
47173089Swyllys 
47183089Swyllys /*
47193089Swyllys  * Check a file to see if it is a CRL file with PEM or DER format.
47203089Swyllys  * If success, return its format in the "pformat" argument.
47213089Swyllys  */
47223089Swyllys KMF_RETURN
OpenSSL_IsCRLFile(KMF_HANDLE_T handle,char * filename,int * pformat)47233089Swyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
47243089Swyllys {
47253089Swyllys 	KMF_RETURN	ret = KMF_OK;
47263089Swyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
47273089Swyllys 	BIO		*bio = NULL;
47283089Swyllys 	X509_CRL   	*xcrl = NULL;
47293089Swyllys 
47303089Swyllys 	if (filename == NULL) {
47313089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
47323089Swyllys 	}
47333089Swyllys 
47343089Swyllys 	bio = BIO_new_file(filename, "rb");
47353089Swyllys 	if (bio == NULL)	{
47363089Swyllys 		SET_ERROR(kmfh, ERR_get_error());
47373089Swyllys 		ret = KMF_ERR_OPEN_FILE;
47383089Swyllys 		goto out;
47393089Swyllys 	}
47403089Swyllys 
47413089Swyllys 	if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
47423089Swyllys 		*pformat = KMF_FORMAT_PEM;
47433089Swyllys 		goto out;
47443089Swyllys 	}
47453089Swyllys 	(void) BIO_free(bio);
47463089Swyllys 
47473089Swyllys 	/*
47483089Swyllys 	 * Now try to read it as raw DER data.
47493089Swyllys 	 */
47503089Swyllys 	bio = BIO_new_file(filename, "rb");
47513089Swyllys 	if (bio == NULL)	{
47523089Swyllys 		SET_ERROR(kmfh, ERR_get_error());
47533089Swyllys 		ret = KMF_ERR_OPEN_FILE;
47543089Swyllys 		goto out;
47553089Swyllys 	}
47563089Swyllys 
47573089Swyllys 	if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
47583089Swyllys 		*pformat = KMF_FORMAT_ASN1;
47593089Swyllys 	} else {
47603089Swyllys 		ret = KMF_ERR_BAD_CRLFILE;
47613089Swyllys 	}
47623089Swyllys 
47633089Swyllys out:
47643089Swyllys 	if (bio != NULL)
47653089Swyllys 		(void) BIO_free(bio);
47663089Swyllys 
47673089Swyllys 	if (xcrl != NULL)
47683089Swyllys 		X509_CRL_free(xcrl);
47693089Swyllys 
47703089Swyllys 	return (ret);
47713089Swyllys }
47723089Swyllys 
47733089Swyllys KMF_RETURN
OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle,KMF_KEY_HANDLE * symkey,KMF_RAW_SYM_KEY * rkey)47743089Swyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
47753089Swyllys     KMF_RAW_SYM_KEY *rkey)
47763089Swyllys {
47773089Swyllys 	KMF_RETURN	rv = KMF_OK;
47783089Swyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
47793089Swyllys 	KMF_DATA	keyvalue;
47803089Swyllys 
47813089Swyllys 	if (kmfh == NULL)
47823089Swyllys 		return (KMF_ERR_UNINITIALIZED);
47833089Swyllys 
47843089Swyllys 	if (symkey == NULL || rkey == NULL)
47853089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
47863089Swyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
47873089Swyllys 		return (KMF_ERR_BAD_KEY_CLASS);
47883089Swyllys 
47893089Swyllys 	if (symkey->israw) {
47903089Swyllys 		KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
47913089Swyllys 
47923089Swyllys 		if (rawkey == NULL ||
47933089Swyllys 		    rawkey->keydata.val == NULL ||
47943089Swyllys 		    rawkey->keydata.len == 0)
47953089Swyllys 			return (KMF_ERR_BAD_KEYHANDLE);
47963089Swyllys 
47973089Swyllys 		rkey->keydata.len = rawkey->keydata.len;
47983089Swyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
47993089Swyllys 			return (KMF_ERR_MEMORY);
48003089Swyllys 		(void) memcpy(rkey->keydata.val, rawkey->keydata.val,
48013089Swyllys 		    rkey->keydata.len);
48023089Swyllys 	} else {
48035051Swyllys 		rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
48043089Swyllys 		if (rv != KMF_OK)
48053089Swyllys 			return (rv);
48063089Swyllys 		rkey->keydata.len = keyvalue.Length;
48073089Swyllys 		rkey->keydata.val = keyvalue.Data;
48083089Swyllys 	}
48093089Swyllys 
48103089Swyllys 	return (rv);
48113089Swyllys }
48123754Swyllys 
48133754Swyllys /*
48145051Swyllys  * substitute for the unsafe access(2) function.
48155051Swyllys  * If the file in question already exists, return 1.
48165051Swyllys  * else 0.  If an error occurs during testing (other
48175051Swyllys  * than EEXIST), return -1.
48185051Swyllys  */
48195051Swyllys static int
test_for_file(char * filename,mode_t mode)48205051Swyllys test_for_file(char *filename, mode_t mode)
48215051Swyllys {
48225051Swyllys 	int fd;
48235051Swyllys 
48245051Swyllys 	/*
48255051Swyllys 	 * Try to create the file with the EXCL flag.
48265051Swyllys 	 * The call should fail if the file exists.
48275051Swyllys 	 */
48285051Swyllys 	fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
48295051Swyllys 	if (fd == -1 && errno == EEXIST)
48305051Swyllys 		return (1);
48315051Swyllys 	else if (fd == -1) /* some other error */
48325051Swyllys 		return (-1);
48335051Swyllys 
48345051Swyllys 	/* The file did NOT exist.  Delete the testcase. */
48355051Swyllys 	(void) close(fd);
48365051Swyllys 	(void) unlink(filename);
48375051Swyllys 	return (0);
48385051Swyllys }
48395051Swyllys 
48405051Swyllys KMF_RETURN
OpenSSL_StoreKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)48415051Swyllys OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
48425051Swyllys 	KMF_ATTRIBUTE *attrlist)
48435051Swyllys {
48445051Swyllys 	KMF_RETURN rv = KMF_OK;
48455051Swyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
48465051Swyllys 	KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
48475051Swyllys 	KMF_RAW_KEY_DATA *rawkey;
48485051Swyllys 	EVP_PKEY *pkey = NULL;
48495051Swyllys 	KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
48505051Swyllys 	KMF_CREDENTIAL cred = {NULL, 0};
48515051Swyllys 	BIO *out = NULL;
48525051Swyllys 	int keys = 0;
48535051Swyllys 	char *fullpath = NULL;
48545051Swyllys 	char *keyfile = NULL;
48555051Swyllys 	char *dirpath = NULL;
48565051Swyllys 
48575051Swyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
48585051Swyllys 	if (pubkey != NULL)
48595051Swyllys 		keys++;
48605051Swyllys 
48615051Swyllys 	prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
48625051Swyllys 	if (prikey != NULL)
48635051Swyllys 		keys++;
48645051Swyllys 
48655051Swyllys 	rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
48665051Swyllys 	if (rawkey != NULL)
48675051Swyllys 		keys++;
48685051Swyllys 
48695051Swyllys 	/*
48705051Swyllys 	 * Exactly 1 type of key must be passed to this function.
48715051Swyllys 	 */
48725051Swyllys 	if (keys != 1)
48735051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
48745051Swyllys 
48755051Swyllys 	keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
48765051Swyllys 	    numattr);
48775051Swyllys 	if (keyfile == NULL)
48785051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
48795051Swyllys 
48805051Swyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
48815051Swyllys 
48825051Swyllys 	fullpath = get_fullpath(dirpath, keyfile);
48835051Swyllys 
48845051Swyllys 	/* Once we have the full path, we don't need the pieces */
48855051Swyllys 	if (fullpath == NULL)
48865051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
48875051Swyllys 
48885051Swyllys 	/* If the requested file exists, return an error */
48895051Swyllys 	if (test_for_file(fullpath, 0400) == 1) {
48905051Swyllys 		free(fullpath);
48915051Swyllys 		return (KMF_ERR_DUPLICATE_KEYFILE);
48925051Swyllys 	}
48935051Swyllys 
48945051Swyllys 	rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
48955051Swyllys 	    &format, NULL);
48965051Swyllys 	if (rv != KMF_OK)
48975051Swyllys 		/* format is optional. */
48985051Swyllys 		rv = KMF_OK;
48995051Swyllys 
49005051Swyllys 	/* CRED is not required for OpenSSL files */
49015051Swyllys 	(void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
49025051Swyllys 	    &cred, NULL);
49035051Swyllys 
49045051Swyllys 	/* Store the private key to the keyfile */
49055051Swyllys 	out = BIO_new_file(fullpath, "wb");
49065051Swyllys 	if (out == NULL) {
49075051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
49085051Swyllys 		rv = KMF_ERR_OPEN_FILE;
49095051Swyllys 		goto end;
49105051Swyllys 	}
49115051Swyllys 
49125051Swyllys 	if (prikey != NULL && prikey->keyp != NULL) {
49135051Swyllys 		if (prikey->keyalg == KMF_RSA ||
49145051Swyllys 		    prikey->keyalg == KMF_DSA) {
49155051Swyllys 			pkey = (EVP_PKEY *)prikey->keyp;
49165051Swyllys 
49175051Swyllys 			rv = ssl_write_key(kmfh, format,
49185051Swyllys 			    out, &cred, pkey, TRUE);
49195051Swyllys 
49205051Swyllys 			if (rv == KMF_OK && prikey->keylabel == NULL) {
49215051Swyllys 				prikey->keylabel = strdup(fullpath);
49225051Swyllys 				if (prikey->keylabel == NULL)
49235051Swyllys 					rv = KMF_ERR_MEMORY;
49245051Swyllys 			}
49255051Swyllys 		}
49265051Swyllys 	} else if (pubkey != NULL && pubkey->keyp != NULL) {
49275051Swyllys 		if (pubkey->keyalg == KMF_RSA ||
49285051Swyllys 		    pubkey->keyalg == KMF_DSA) {
49295051Swyllys 			pkey = (EVP_PKEY *)pubkey->keyp;
49305051Swyllys 
49315051Swyllys 			rv = ssl_write_key(kmfh, format,
49325051Swyllys 			    out, &cred, pkey, FALSE);
49335051Swyllys 
49345051Swyllys 			if (rv == KMF_OK && pubkey->keylabel == NULL) {
49355051Swyllys 				pubkey->keylabel = strdup(fullpath);
49365051Swyllys 				if (pubkey->keylabel == NULL)
49375051Swyllys 					rv = KMF_ERR_MEMORY;
49385051Swyllys 			}
49395051Swyllys 		}
49405051Swyllys 	} else if (rawkey != NULL) {
49415051Swyllys 		if (rawkey->keytype == KMF_RSA) {
49425051Swyllys 			pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
49435051Swyllys 		} else if (rawkey->keytype == KMF_DSA) {
49445051Swyllys 			pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
49455051Swyllys 		} else {
49465051Swyllys 			rv = KMF_ERR_BAD_PARAMETER;
49475051Swyllys 		}
49485536Swyllys 		if (pkey != NULL) {
49495637Swyllys 			KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
49505637Swyllys 
49515637Swyllys 			rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
49525637Swyllys 			    (void *)&kclass, NULL);
49535637Swyllys 			if (rv != KMF_OK)
49545637Swyllys 				rv = KMF_OK;
49555536Swyllys 			rv = ssl_write_key(kmfh, format, out,
49565637Swyllys 			    &cred, pkey, (kclass == KMF_ASYM_PRI));
49575536Swyllys 			EVP_PKEY_free(pkey);
49585536Swyllys 		}
49595051Swyllys 	}
49605051Swyllys 
49615051Swyllys end:
49625051Swyllys 
49635051Swyllys 	if (out)
49645051Swyllys 		(void) BIO_free(out);
49655051Swyllys 
49665536Swyllys 
49675051Swyllys 	if (rv == KMF_OK)
49685051Swyllys 		(void) chmod(fullpath, 0400);
49695051Swyllys 
49705051Swyllys 	free(fullpath);
49715051Swyllys 	return (rv);
49725051Swyllys }
49735051Swyllys 
49745051Swyllys KMF_RETURN
OpenSSL_ImportCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)49755051Swyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
49765051Swyllys {
49775051Swyllys 	KMF_RETURN ret = KMF_OK;
49785051Swyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
49795051Swyllys 	X509_CRL *xcrl = NULL;
49805051Swyllys 	X509 *xcert = NULL;
49815051Swyllys 	EVP_PKEY *pkey;
49825051Swyllys 	KMF_ENCODE_FORMAT format;
49835051Swyllys 	BIO *in = NULL, *out = NULL;
49845051Swyllys 	int openssl_ret = 0;
49855051Swyllys 	KMF_ENCODE_FORMAT outformat;
49865051Swyllys 	boolean_t crlcheck = FALSE;
49875051Swyllys 	char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
49885051Swyllys 
49895051Swyllys 	if (numattr == 0 || attrlist == NULL) {
49905051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
49915051Swyllys 	}
49925051Swyllys 
49935051Swyllys 	/* CRL check is optional */
49945051Swyllys 	(void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
49955051Swyllys 	    &crlcheck, NULL);
49965051Swyllys 
49975051Swyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
49985051Swyllys 	if (crlcheck == B_TRUE && certfile == NULL) {
49995051Swyllys 		return (KMF_ERR_BAD_CERTFILE);
50005051Swyllys 	}
50015051Swyllys 
50025051Swyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
50035051Swyllys 	incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
50045051Swyllys 	outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
50055051Swyllys 
50065051Swyllys 	crlfile = get_fullpath(dirpath, incrl);
50075051Swyllys 
50085051Swyllys 	if (crlfile == NULL)
50095051Swyllys 		return (KMF_ERR_BAD_CRLFILE);
50105051Swyllys 
50115051Swyllys 	outcrlfile = get_fullpath(dirpath, outcrl);
50125051Swyllys 	if (outcrlfile == NULL)
50135051Swyllys 		return (KMF_ERR_BAD_CRLFILE);
50145051Swyllys 
50155051Swyllys 	if (isdir(outcrlfile)) {
50165051Swyllys 		free(outcrlfile);
50175051Swyllys 		return (KMF_ERR_BAD_CRLFILE);
50185051Swyllys 	}
50195051Swyllys 
50205051Swyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
50215051Swyllys 	if (ret != KMF_OK) {
50225051Swyllys 		free(outcrlfile);
50235051Swyllys 		return (ret);
50245051Swyllys 	}
50255051Swyllys 
50265051Swyllys 	in = BIO_new_file(crlfile, "rb");
50275051Swyllys 	if (in == NULL)	{
50285051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
50295051Swyllys 		ret = KMF_ERR_OPEN_FILE;
50305051Swyllys 		goto end;
50315051Swyllys 	}
50325051Swyllys 
50335051Swyllys 	if (format == KMF_FORMAT_ASN1) {
50345051Swyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
50355051Swyllys 	} else if (format == KMF_FORMAT_PEM) {
50365051Swyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
50375051Swyllys 	}
50385051Swyllys 
50395051Swyllys 	if (xcrl == NULL) {
50405051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
50415051Swyllys 		ret = KMF_ERR_BAD_CRLFILE;
50425051Swyllys 		goto end;
50435051Swyllys 	}
50445051Swyllys 
50455051Swyllys 	/* If bypasscheck is specified, no need to verify. */
50465051Swyllys 	if (crlcheck == B_FALSE)
50475051Swyllys 		goto output;
50485051Swyllys 
50495051Swyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
50505051Swyllys 	if (ret != KMF_OK)
50515051Swyllys 		goto end;
50525051Swyllys 
50535051Swyllys 	/* Read in the CA cert file and convert to X509 */
50545051Swyllys 	if (BIO_read_filename(in, certfile) <= 0) {
50555051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
50565051Swyllys 		ret = KMF_ERR_OPEN_FILE;
50575051Swyllys 		goto end;
50585051Swyllys 	}
50595051Swyllys 
50605051Swyllys 	if (format == KMF_FORMAT_ASN1) {
50615051Swyllys 		xcert = d2i_X509_bio(in, NULL);
50625051Swyllys 	} else if (format == KMF_FORMAT_PEM) {
50635051Swyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
50645051Swyllys 	} else {
50655051Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
50665051Swyllys 		goto end;
50675051Swyllys 	}
50685051Swyllys 
50695051Swyllys 	if (xcert == NULL) {
50705051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
50715051Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
50725051Swyllys 		goto end;
50735051Swyllys 	}
50745051Swyllys 	/* Now get the public key from the CA cert */
50755051Swyllys 	pkey = X509_get_pubkey(xcert);
50765051Swyllys 	if (pkey == NULL) {
50775051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
50785051Swyllys 		ret = KMF_ERR_BAD_CERTFILE;
50795051Swyllys 		goto end;
50805051Swyllys 	}
50815051Swyllys 
50825051Swyllys 	/* Verify the CRL with the CA's public key */
50835051Swyllys 	openssl_ret = X509_CRL_verify(xcrl, pkey);
50845051Swyllys 	EVP_PKEY_free(pkey);
50855051Swyllys 	if (openssl_ret > 0) {
50865051Swyllys 		ret = KMF_OK;  /* verify succeed */
50875051Swyllys 	} else {
50885051Swyllys 		SET_ERROR(kmfh, openssl_ret);
50895051Swyllys 		ret = KMF_ERR_BAD_CRLFILE;
50905051Swyllys 	}
50915051Swyllys 
50925051Swyllys output:
50935051Swyllys 	ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
50945051Swyllys 	    &outformat, NULL);
50955051Swyllys 	if (ret != KMF_OK) {
50965051Swyllys 		ret = KMF_OK;
50975051Swyllys 		outformat = KMF_FORMAT_PEM;
50985051Swyllys 	}
50995051Swyllys 
51005051Swyllys 	out = BIO_new_file(outcrlfile, "wb");
51015051Swyllys 	if (out == NULL) {
51025051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
51035051Swyllys 		ret = KMF_ERR_OPEN_FILE;
51045051Swyllys 		goto end;
51055051Swyllys 	}
51065051Swyllys 
51075051Swyllys 	if (outformat == KMF_FORMAT_ASN1) {
51085051Swyllys 		openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
51095051Swyllys 	} else if (outformat == KMF_FORMAT_PEM) {
51105051Swyllys 		openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
51115051Swyllys 	} else {
51125051Swyllys 		ret = KMF_ERR_BAD_PARAMETER;
51135051Swyllys 		goto end;
51145051Swyllys 	}
51155051Swyllys 
51165051Swyllys 	if (openssl_ret <= 0) {
51175051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
51185051Swyllys 		ret = KMF_ERR_WRITE_FILE;
51195051Swyllys 	} else {
51205051Swyllys 		ret = KMF_OK;
51215051Swyllys 	}
51225051Swyllys 
51235051Swyllys end:
51245051Swyllys 	if (xcrl != NULL)
51255051Swyllys 		X509_CRL_free(xcrl);
51265051Swyllys 
51275051Swyllys 	if (xcert != NULL)
51285051Swyllys 		X509_free(xcert);
51295051Swyllys 
51305051Swyllys 	if (in != NULL)
51315051Swyllys 		(void) BIO_free(in);
51325051Swyllys 
51335051Swyllys 	if (out != NULL)
51345051Swyllys 		(void) BIO_free(out);
51355051Swyllys 
51365051Swyllys 	if (outcrlfile != NULL)
51375051Swyllys 		free(outcrlfile);
51385051Swyllys 
51395051Swyllys 	return (ret);
51405051Swyllys }
51415051Swyllys 
51425051Swyllys KMF_RETURN
OpenSSL_ListCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)51435051Swyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
51445051Swyllys {
51455051Swyllys 	KMF_RETURN ret = KMF_OK;
51465051Swyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
51475051Swyllys 	X509_CRL   *x = NULL;
51485051Swyllys 	KMF_ENCODE_FORMAT format;
51495051Swyllys 	char *crlfile = NULL;
51505051Swyllys 	BIO *in = NULL;
51515051Swyllys 	BIO *mem = NULL;
51525051Swyllys 	long len;
51535051Swyllys 	char *memptr;
51545051Swyllys 	char *data = NULL;
51555051Swyllys 	char **crldata;
51565051Swyllys 	char *crlfilename, *dirpath;
51575051Swyllys 
51585051Swyllys 	if (numattr == 0 || attrlist == NULL) {
51595051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
51605051Swyllys 	}
51615051Swyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
51625051Swyllys 	    attrlist, numattr);
51635051Swyllys 	if (crlfilename == NULL)
51645051Swyllys 		return (KMF_ERR_BAD_CRLFILE);
51655051Swyllys 
51665051Swyllys 	crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
51675051Swyllys 	    attrlist, numattr);
51685051Swyllys 
51695051Swyllys 	if (crldata == NULL)
51705051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
51715051Swyllys 
51725051Swyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
51735051Swyllys 
51745051Swyllys 	crlfile = get_fullpath(dirpath, crlfilename);
51755051Swyllys 
51765051Swyllys 	if (crlfile == NULL)
51775051Swyllys 		return (KMF_ERR_BAD_CRLFILE);
51785051Swyllys 
51795051Swyllys 	if (isdir(crlfile)) {
51805051Swyllys 		free(crlfile);
51815051Swyllys 		return (KMF_ERR_BAD_CRLFILE);
51825051Swyllys 	}
51835051Swyllys 
51845051Swyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
51855051Swyllys 	if (ret != KMF_OK) {
51865051Swyllys 		free(crlfile);
51875051Swyllys 		return (ret);
51885051Swyllys 	}
51895051Swyllys 
51905051Swyllys 	if (bio_err == NULL)
51915051Swyllys 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
51925051Swyllys 
51935051Swyllys 	in = BIO_new_file(crlfile, "rb");
51945051Swyllys 	if (in == NULL)	{
51955051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
51965051Swyllys 		ret = KMF_ERR_OPEN_FILE;
51975051Swyllys 		goto end;
51985051Swyllys 	}
51995051Swyllys 
52005051Swyllys 	if (format == KMF_FORMAT_ASN1) {
52015051Swyllys 		x = d2i_X509_CRL_bio(in, NULL);
52025051Swyllys 	} else if (format == KMF_FORMAT_PEM) {
52035051Swyllys 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
52045051Swyllys 	}
52055051Swyllys 
52065051Swyllys 	if (x == NULL) { /* should not happen */
52075051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
52085051Swyllys 		ret = KMF_ERR_OPEN_FILE;
52095051Swyllys 		goto end;
52105051Swyllys 	}
52115051Swyllys 
52125051Swyllys 	mem = BIO_new(BIO_s_mem());
52135051Swyllys 	if (mem == NULL) {
52145051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
52155051Swyllys 		ret = KMF_ERR_MEMORY;
52165051Swyllys 		goto end;
52175051Swyllys 	}
52185051Swyllys 
52195051Swyllys 	(void) X509_CRL_print(mem, x);
52205051Swyllys 	len = BIO_get_mem_data(mem, &memptr);
52215051Swyllys 	if (len <= 0) {
52225051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
52235051Swyllys 		ret = KMF_ERR_MEMORY;
52245051Swyllys 		goto end;
52255051Swyllys 	}
52265051Swyllys 
52275051Swyllys 	data = malloc(len + 1);
52285051Swyllys 	if (data == NULL) {
52295051Swyllys 		ret = KMF_ERR_MEMORY;
52305051Swyllys 		goto end;
52315051Swyllys 	}
52325051Swyllys 
52335051Swyllys 	(void) memcpy(data, memptr, len);
52345051Swyllys 	data[len] = '\0';
52355051Swyllys 	*crldata = data;
52365051Swyllys 
52375051Swyllys end:
52385051Swyllys 	if (x != NULL)
52395051Swyllys 		X509_CRL_free(x);
52405051Swyllys 
52415051Swyllys 	if (crlfile != NULL)
52425051Swyllys 		free(crlfile);
52435051Swyllys 
52445051Swyllys 	if (in != NULL)
52455051Swyllys 		(void) BIO_free(in);
52465051Swyllys 
52475051Swyllys 	if (mem != NULL)
52485051Swyllys 		(void) BIO_free(mem);
52495051Swyllys 
52505051Swyllys 	return (ret);
52515051Swyllys }
52525051Swyllys 
52535051Swyllys KMF_RETURN
OpenSSL_DeleteCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)52545051Swyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
52555051Swyllys {
52565051Swyllys 	KMF_RETURN ret = KMF_OK;
52575051Swyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
52585051Swyllys 	KMF_ENCODE_FORMAT format;
52595051Swyllys 	char *crlfile = NULL;
52605051Swyllys 	BIO *in = NULL;
52615051Swyllys 	char *crlfilename, *dirpath;
52625051Swyllys 
52635051Swyllys 	if (numattr == 0 || attrlist == NULL) {
52645051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
52655051Swyllys 	}
52665051Swyllys 
52675051Swyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
52685051Swyllys 	    attrlist, numattr);
52695051Swyllys 
52705051Swyllys 	if (crlfilename == NULL)
52715051Swyllys 		return (KMF_ERR_BAD_CRLFILE);
52725051Swyllys 
52735051Swyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
52745051Swyllys 
52755051Swyllys 	crlfile = get_fullpath(dirpath, crlfilename);
52765051Swyllys 
52775051Swyllys 	if (crlfile == NULL)
52785051Swyllys 		return (KMF_ERR_BAD_CRLFILE);
52795051Swyllys 
52805051Swyllys 	if (isdir(crlfile)) {
52815051Swyllys 		ret = KMF_ERR_BAD_CRLFILE;
52825051Swyllys 		goto end;
52835051Swyllys 	}
52845051Swyllys 
52855051Swyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
52865051Swyllys 	if (ret != KMF_OK)
52875051Swyllys 		goto end;
52885051Swyllys 
52895051Swyllys 	if (unlink(crlfile) != 0) {
52905051Swyllys 		SET_SYS_ERROR(kmfh, errno);
52915051Swyllys 		ret = KMF_ERR_INTERNAL;
52925051Swyllys 		goto end;
52935051Swyllys 	}
52945051Swyllys 
52955051Swyllys end:
52965051Swyllys 	if (in != NULL)
52975051Swyllys 		(void) BIO_free(in);
52985051Swyllys 	if (crlfile != NULL)
52995051Swyllys 		free(crlfile);
53005051Swyllys 
53015051Swyllys 	return (ret);
53025051Swyllys }
53035051Swyllys 
53045051Swyllys KMF_RETURN
OpenSSL_FindCertInCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)53055051Swyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
53065051Swyllys {
53075051Swyllys 	KMF_RETURN ret = KMF_OK;
53085051Swyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
53095051Swyllys 	KMF_ENCODE_FORMAT format;
53105051Swyllys 	BIO *in = NULL;
53115051Swyllys 	X509   *xcert = NULL;
53125051Swyllys 	X509_CRL   *xcrl = NULL;
53135051Swyllys 	STACK_OF(X509_REVOKED) *revoke_stack = NULL;
53145051Swyllys 	X509_REVOKED *revoke;
53155051Swyllys 	int i;
53165051Swyllys 	char *crlfilename, *crlfile, *dirpath, *certfile;
53175051Swyllys 
53185051Swyllys 	if (numattr == 0 || attrlist == NULL) {
53195051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
53205051Swyllys 	}
53215051Swyllys 
53225051Swyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
53235051Swyllys 	    attrlist, numattr);
53245051Swyllys 
53255051Swyllys 	if (crlfilename == NULL)
53265051Swyllys 		return (KMF_ERR_BAD_CRLFILE);
53275051Swyllys 
53285051Swyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
53295051Swyllys 	if (certfile == NULL)
53305051Swyllys 		return (KMF_ERR_BAD_CRLFILE);
53315051Swyllys 
53325051Swyllys 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
53335051Swyllys 
53345051Swyllys 	crlfile = get_fullpath(dirpath, crlfilename);
53355051Swyllys 
53365051Swyllys 	if (crlfile == NULL)
53375051Swyllys 		return (KMF_ERR_BAD_CRLFILE);
53385051Swyllys 
53395051Swyllys 	if (isdir(crlfile)) {
53405051Swyllys 		ret = KMF_ERR_BAD_CRLFILE;
53415051Swyllys 		goto end;
53425051Swyllys 	}
53435051Swyllys 
53445051Swyllys 	ret = kmf_is_crl_file(handle, crlfile, &format);
53455051Swyllys 	if (ret != KMF_OK)
53465051Swyllys 		goto end;
53475051Swyllys 
53485051Swyllys 	/* Read the CRL file and load it into a X509_CRL structure */
53495051Swyllys 	in = BIO_new_file(crlfilename, "rb");
53505051Swyllys 	if (in == NULL)	{
53515051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
53525051Swyllys 		ret = KMF_ERR_OPEN_FILE;
53535051Swyllys 		goto end;
53545051Swyllys 	}
53555051Swyllys 
53565051Swyllys 	if (format == KMF_FORMAT_ASN1) {
53575051Swyllys 		xcrl = d2i_X509_CRL_bio(in, NULL);
53585051Swyllys 	} else if (format == KMF_FORMAT_PEM) {
53595051Swyllys 		xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
53605051Swyllys 	}
53615051Swyllys 
53625051Swyllys 	if (xcrl == NULL) {
53635051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
53645051Swyllys 		ret = KMF_ERR_BAD_CRLFILE;
53655051Swyllys 		goto end;
53665051Swyllys 	}
53675051Swyllys 	(void) BIO_free(in);
53685051Swyllys 
53695051Swyllys 	/* Read the Certificate file and load it into a X509 structure */
53705051Swyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
53715051Swyllys 	if (ret != KMF_OK)
53725051Swyllys 		goto end;
53735051Swyllys 
53745051Swyllys 	in = BIO_new_file(certfile, "rb");
53755051Swyllys 	if (in == NULL)	{
53765051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
53775051Swyllys 		ret = KMF_ERR_OPEN_FILE;
53785051Swyllys 		goto end;
53795051Swyllys 	}
53805051Swyllys 
53815051Swyllys 	if (format == KMF_FORMAT_ASN1) {
53825051Swyllys 		xcert = d2i_X509_bio(in, NULL);
53835051Swyllys 	} else if (format == KMF_FORMAT_PEM) {
53845051Swyllys 		xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
53855051Swyllys 	}
53865051Swyllys 
53875051Swyllys 	if (xcert == NULL) {
53885051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
53895051Swyllys 		ret = KMF_ERR_BAD_CERTFILE;
53905051Swyllys 		goto end;
53915051Swyllys 	}
53925051Swyllys 
53935051Swyllys 	/* Check if the certificate and the CRL have same issuer */
53945051Swyllys 	if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) {
53955051Swyllys 		ret = KMF_ERR_ISSUER;
53965051Swyllys 		goto end;
53975051Swyllys 	}
53985051Swyllys 
53995051Swyllys 	/* Check to see if the certificate serial number is revoked */
54005051Swyllys 	revoke_stack = X509_CRL_get_REVOKED(xcrl);
54015051Swyllys 	if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
54025051Swyllys 		/* No revoked certificates in the CRL file */
54035051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
54045051Swyllys 		ret = KMF_ERR_EMPTY_CRL;
54055051Swyllys 		goto end;
54065051Swyllys 	}
54075051Swyllys 
54085051Swyllys 	for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
540911673Sopensolaris@drydog.com 		/* LINTED E_BAD_PTR_CAST_ALIGN */
54105051Swyllys 		revoke = sk_X509_REVOKED_value(revoke_stack, i);
54115051Swyllys 		if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber,
54125051Swyllys 		    revoke->serialNumber) == 0) {
54135051Swyllys 			break;
54145051Swyllys 		}
54155051Swyllys 	}
54165051Swyllys 
54175051Swyllys 	if (i < sk_X509_REVOKED_num(revoke_stack)) {
54185051Swyllys 		ret = KMF_OK;
54195051Swyllys 	} else {
54205051Swyllys 		ret = KMF_ERR_NOT_REVOKED;
54215051Swyllys 	}
54225051Swyllys 
54235051Swyllys end:
54245051Swyllys 	if (in != NULL)
54255051Swyllys 		(void) BIO_free(in);
54265051Swyllys 	if (xcrl != NULL)
54275051Swyllys 		X509_CRL_free(xcrl);
54285051Swyllys 	if (xcert != NULL)
54295051Swyllys 		X509_free(xcert);
54305051Swyllys 
54315051Swyllys 	return (ret);
54325051Swyllys }
54335051Swyllys 
54345051Swyllys KMF_RETURN
OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle,char * crlname,KMF_DATA * tacert)54355051Swyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
54365051Swyllys {
54375051Swyllys 	KMF_RETURN	ret = KMF_OK;
54385051Swyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
54395051Swyllys 	BIO		*bcrl = NULL;
54405051Swyllys 	X509_CRL   	*xcrl = NULL;
54415051Swyllys 	X509		*xcert = NULL;
54425051Swyllys 	EVP_PKEY	*pkey;
54435051Swyllys 	int		sslret;
54445051Swyllys 	KMF_ENCODE_FORMAT crl_format;
54455051Swyllys 	unsigned char	*p;
54465051Swyllys 	long		len;
54475051Swyllys 
54485051Swyllys 	if (handle == NULL || crlname == NULL || tacert == NULL) {
54495051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
54505051Swyllys 	}
54515051Swyllys 
54525051Swyllys 	ret = kmf_get_file_format(crlname, &crl_format);
54535051Swyllys 	if (ret != KMF_OK)
54545051Swyllys 		return (ret);
54555051Swyllys 
54565051Swyllys 	bcrl = BIO_new_file(crlname, "rb");
54575051Swyllys 	if (bcrl == NULL)	{
54585051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
54595051Swyllys 		ret = KMF_ERR_OPEN_FILE;
54605051Swyllys 		goto cleanup;
54615051Swyllys 	}
54625051Swyllys 
54635051Swyllys 	if (crl_format == KMF_FORMAT_ASN1) {
54645051Swyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
54655051Swyllys 	} else if (crl_format == KMF_FORMAT_PEM) {
54665051Swyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
54675051Swyllys 	} else {
54685051Swyllys 		ret = KMF_ERR_BAD_PARAMETER;
54695051Swyllys 		goto cleanup;
54705051Swyllys 	}
54715051Swyllys 
54725051Swyllys 	if (xcrl == NULL) {
54735051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
54745051Swyllys 		ret = KMF_ERR_BAD_CRLFILE;
54755051Swyllys 		goto cleanup;
54765051Swyllys 	}
54775051Swyllys 
54785051Swyllys 	p = tacert->Data;
54795051Swyllys 	len = tacert->Length;
54805051Swyllys 	xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
54815051Swyllys 
54825051Swyllys 	if (xcert == NULL) {
54835051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
54845051Swyllys 		ret = KMF_ERR_BAD_CERTFILE;
54855051Swyllys 		goto cleanup;
54865051Swyllys 	}
54875051Swyllys 
54885051Swyllys 	/* Get issuer certificate public key */
54895051Swyllys 	pkey = X509_get_pubkey(xcert);
54905051Swyllys 	if (pkey == NULL) {
54915051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
54925051Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
54935051Swyllys 		goto cleanup;
54945051Swyllys 	}
54955051Swyllys 
54965051Swyllys 	/* Verify CRL signature */
54975051Swyllys 	sslret = X509_CRL_verify(xcrl, pkey);
54985051Swyllys 	EVP_PKEY_free(pkey);
54995051Swyllys 	if (sslret > 0) {
55005051Swyllys 		ret = KMF_OK;
55015051Swyllys 	} else {
55025051Swyllys 		SET_ERROR(kmfh, sslret);
55035051Swyllys 		ret = KMF_ERR_BAD_CRLFILE;
55045051Swyllys 	}
55055051Swyllys 
55065051Swyllys cleanup:
55075051Swyllys 	if (bcrl != NULL)
55085051Swyllys 		(void) BIO_free(bcrl);
55095051Swyllys 
55105051Swyllys 	if (xcrl != NULL)
55115051Swyllys 		X509_CRL_free(xcrl);
55125051Swyllys 
55135051Swyllys 	if (xcert != NULL)
55145051Swyllys 		X509_free(xcert);
55155051Swyllys 
55165051Swyllys 	return (ret);
55175051Swyllys 
55185051Swyllys }
55195051Swyllys 
55205051Swyllys KMF_RETURN
OpenSSL_CheckCRLDate(KMF_HANDLE_T handle,char * crlname)55215051Swyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
55225051Swyllys {
55235051Swyllys 	KMF_RETURN	ret = KMF_OK;
55245051Swyllys 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
55255051Swyllys 	KMF_ENCODE_FORMAT crl_format;
55265051Swyllys 	BIO		*bcrl = NULL;
55275051Swyllys 	X509_CRL   	*xcrl = NULL;
55285051Swyllys 	int		i;
55295051Swyllys 
55305051Swyllys 	if (handle == NULL || crlname == NULL) {
55315051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
55325051Swyllys 	}
55335051Swyllys 
55345051Swyllys 	ret = kmf_is_crl_file(handle, crlname, &crl_format);
55355051Swyllys 	if (ret != KMF_OK)
55365051Swyllys 		return (ret);
55375051Swyllys 
55385051Swyllys 	bcrl = BIO_new_file(crlname, "rb");
55395536Swyllys 	if (bcrl == NULL) {
55405051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
55415051Swyllys 		ret = KMF_ERR_OPEN_FILE;
55425051Swyllys 		goto cleanup;
55435051Swyllys 	}
55445051Swyllys 
55455536Swyllys 	if (crl_format == KMF_FORMAT_ASN1)
55465051Swyllys 		xcrl = d2i_X509_CRL_bio(bcrl, NULL);
55475536Swyllys 	else if (crl_format == KMF_FORMAT_PEM)
55485051Swyllys 		xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
55495051Swyllys 
55505051Swyllys 	if (xcrl == NULL) {
55515051Swyllys 		SET_ERROR(kmfh, ERR_get_error());
55525051Swyllys 		ret = KMF_ERR_BAD_CRLFILE;
55535051Swyllys 		goto cleanup;
55545051Swyllys 	}
55555051Swyllys 	i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL);
55565051Swyllys 	if (i >= 0) {
55575051Swyllys 		ret = KMF_ERR_VALIDITY_PERIOD;
55585051Swyllys 		goto cleanup;
55595051Swyllys 	}
55605051Swyllys 	if (X509_CRL_get_nextUpdate(xcrl)) {
55615051Swyllys 		i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL);
55625051Swyllys 
55635051Swyllys 		if (i <= 0) {
55645051Swyllys 			ret = KMF_ERR_VALIDITY_PERIOD;
55655051Swyllys 			goto cleanup;
55665051Swyllys 		}
55675051Swyllys 	}
55685051Swyllys 
55695051Swyllys 	ret = KMF_OK;
55705051Swyllys 
55715051Swyllys cleanup:
55725051Swyllys 	if (bcrl != NULL)
55735051Swyllys 		(void) BIO_free(bcrl);
55745051Swyllys 
55755051Swyllys 	if (xcrl != NULL)
55765051Swyllys 		X509_CRL_free(xcrl);
55775051Swyllys 
55785051Swyllys 	return (ret);
55795051Swyllys }
5580