199ebb4caSwyllys /*
22c9a247fSWyllys Ingersoll * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
32c9a247fSWyllys Ingersoll *
499ebb4caSwyllys * Use is subject to license terms.
599ebb4caSwyllys */
69a767088Shaimay /*
770f9559bSTheo Schlossnagle * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
8553e44ceSAndrew Stormont * Copyright 2018 RackTop Systems.
94942e222SAndy Fiddaman * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
1070f9559bSTheo Schlossnagle */
1170f9559bSTheo Schlossnagle /*
129a767088Shaimay * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
139a767088Shaimay * project 2000.
149a767088Shaimay */
159a767088Shaimay /*
169a767088Shaimay * ====================================================================
179a767088Shaimay * Copyright (c) 2000-2004 The OpenSSL Project. All rights reserved.
189a767088Shaimay *
199a767088Shaimay * Redistribution and use in source and binary forms, with or without
209a767088Shaimay * modification, are permitted provided that the following conditions
219a767088Shaimay * are met:
229a767088Shaimay *
239a767088Shaimay * 1. Redistributions of source code must retain the above copyright
249a767088Shaimay * notice, this list of conditions and the following disclaimer.
259a767088Shaimay *
269a767088Shaimay * 2. Redistributions in binary form must reproduce the above copyright
279a767088Shaimay * notice, this list of conditions and the following disclaimer in
289a767088Shaimay * the documentation and/or other materials provided with the
299a767088Shaimay * distribution.
309a767088Shaimay *
319a767088Shaimay * 3. All advertising materials mentioning features or use of this
329a767088Shaimay * software must display the following acknowledgment:
339a767088Shaimay * "This product includes software developed by the OpenSSL Project
349a767088Shaimay * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
359a767088Shaimay *
369a767088Shaimay * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
379a767088Shaimay * endorse or promote products derived from this software without
389a767088Shaimay * prior written permission. For written permission, please contact
399a767088Shaimay * licensing@OpenSSL.org.
409a767088Shaimay *
419a767088Shaimay * 5. Products derived from this software may not be called "OpenSSL"
429a767088Shaimay * nor may "OpenSSL" appear in their names without prior written
439a767088Shaimay * permission of the OpenSSL Project.
449a767088Shaimay *
459a767088Shaimay * 6. Redistributions of any form whatsoever must retain the following
469a767088Shaimay * acknowledgment:
479a767088Shaimay * "This product includes software developed by the OpenSSL Project
489a767088Shaimay * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
499a767088Shaimay *
509a767088Shaimay * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
519a767088Shaimay * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
529a767088Shaimay * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
539a767088Shaimay * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
549a767088Shaimay * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
559a767088Shaimay * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
569a767088Shaimay * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
579a767088Shaimay * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
589a767088Shaimay * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
599a767088Shaimay * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
609a767088Shaimay * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
619a767088Shaimay * OF THE POSSIBILITY OF SUCH DAMAGE.
629a767088Shaimay * ====================================================================
639a767088Shaimay *
649a767088Shaimay * This product includes cryptographic software written by Eric Young
659a767088Shaimay * (eay@cryptsoft.com). This product includes software written by Tim
669a767088Shaimay * Hudson (tjh@cryptsoft.com).
679a767088Shaimay *
689a767088Shaimay */
6999ebb4caSwyllys
7071593db2Swyllys #include <stdlib.h>
7199ebb4caSwyllys #include <kmfapiP.h>
7299ebb4caSwyllys #include <ber_der.h>
7399ebb4caSwyllys #include <fcntl.h>
7499ebb4caSwyllys #include <sys/stat.h>
7599ebb4caSwyllys #include <dirent.h>
7699ebb4caSwyllys #include <cryptoutil.h>
7799ebb4caSwyllys #include <synch.h>
7899ebb4caSwyllys #include <thread.h>
7999ebb4caSwyllys
8099ebb4caSwyllys /* OPENSSL related headers */
8199ebb4caSwyllys #include <openssl/bio.h>
8299ebb4caSwyllys #include <openssl/bn.h>
8399ebb4caSwyllys #include <openssl/asn1.h>
8499ebb4caSwyllys #include <openssl/err.h>
8599ebb4caSwyllys #include <openssl/x509.h>
8699ebb4caSwyllys #include <openssl/rsa.h>
8799ebb4caSwyllys #include <openssl/dsa.h>
8899ebb4caSwyllys #include <openssl/x509v3.h>
8999ebb4caSwyllys #include <openssl/objects.h>
9099ebb4caSwyllys #include <openssl/pem.h>
9199ebb4caSwyllys #include <openssl/pkcs12.h>
9299ebb4caSwyllys #include <openssl/ocsp.h>
9399ebb4caSwyllys #include <openssl/des.h>
9499ebb4caSwyllys #include <openssl/rand.h>
95300fdee2SAndy Fiddaman #include "compat.h"
9699ebb4caSwyllys
9799ebb4caSwyllys #define PRINT_ANY_EXTENSION (\
9899ebb4caSwyllys KMF_X509_EXT_KEY_USAGE |\
9999ebb4caSwyllys KMF_X509_EXT_CERT_POLICIES |\
10099ebb4caSwyllys KMF_X509_EXT_SUBJALTNAME |\
10199ebb4caSwyllys KMF_X509_EXT_BASIC_CONSTRAINTS |\
10299ebb4caSwyllys KMF_X509_EXT_NAME_CONSTRAINTS |\
10399ebb4caSwyllys KMF_X509_EXT_POLICY_CONSTRAINTS |\
10499ebb4caSwyllys KMF_X509_EXT_EXT_KEY_USAGE |\
10599ebb4caSwyllys KMF_X509_EXT_INHIBIT_ANY_POLICY |\
10699ebb4caSwyllys KMF_X509_EXT_AUTH_KEY_ID |\
10799ebb4caSwyllys KMF_X509_EXT_SUBJ_KEY_ID |\
10899ebb4caSwyllys KMF_X509_EXT_POLICY_MAPPING)
10999ebb4caSwyllys
11099ebb4caSwyllys static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
11199ebb4caSwyllys 0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
11299ebb4caSwyllys 0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
11399ebb4caSwyllys 0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
11499ebb4caSwyllys 0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
11599ebb4caSwyllys 0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
11699ebb4caSwyllys 0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
11799ebb4caSwyllys 0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
11899ebb4caSwyllys 0x91 };
11999ebb4caSwyllys
12099ebb4caSwyllys static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
12199ebb4caSwyllys 0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
12299ebb4caSwyllys 0x8e, 0xda, 0xce, 0x91, 0x5f };
12399ebb4caSwyllys
12499ebb4caSwyllys static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
12599ebb4caSwyllys 0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
12699ebb4caSwyllys 0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
12799ebb4caSwyllys 0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
12899ebb4caSwyllys 0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
12999ebb4caSwyllys 0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
13099ebb4caSwyllys 0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
13199ebb4caSwyllys 0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
13299ebb4caSwyllys 0x02 };
13399ebb4caSwyllys
13499ebb4caSwyllys #define SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
13599ebb4caSwyllys h->lasterr.errcode = c;
13699ebb4caSwyllys
13799ebb4caSwyllys #define SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
13899ebb4caSwyllys
1395b3e1433Swyllys /*
140bf5d9f18SAndy Fiddaman * Declare some new macros for managing stacks of EVP_PKEYS.
1415b3e1433Swyllys */
142553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
143*6ff4183cSAndy Fiddaman /* BEGIN CSTYLED */
1445b3e1433Swyllys DECLARE_STACK_OF(EVP_PKEY)
145*6ff4183cSAndy Fiddaman /* END CSTYLED */
1465b3e1433Swyllys
1475b3e1433Swyllys #define sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
1485b3e1433Swyllys #define sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
1495b3e1433Swyllys #define sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
1505b3e1433Swyllys #define sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
1515b3e1433Swyllys #define sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
1525b3e1433Swyllys #define sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
1535b3e1433Swyllys (free_func))
1545b3e1433Swyllys
155300fdee2SAndy Fiddaman #else
156*6ff4183cSAndy Fiddaman /* BEGIN CSTYLED */
157300fdee2SAndy Fiddaman DEFINE_STACK_OF(EVP_PKEY)
158*6ff4183cSAndy Fiddaman /* END CSTYLED */
159300fdee2SAndy Fiddaman #endif
160300fdee2SAndy Fiddaman
16199ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX;
16299ebb4caSwyllys static int ssl_initialized = 0;
16330a5e8faSwyllys static BIO *bio_err = NULL;
16430a5e8faSwyllys
1654942e222SAndy Fiddaman static int test_for_file(char *, mode_t);
1664942e222SAndy Fiddaman
1674942e222SAndy Fiddaman static KMF_RETURN openssl_parse_bag(PKCS12_SAFEBAG *, char *, int,
1685b3e1433Swyllys STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
1695b3e1433Swyllys
1704942e222SAndy Fiddaman static KMF_RETURN local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int,
1714942e222SAndy Fiddaman KMF_X509_DER_CERT *, int, KMF_KEY_HANDLE *, char *);
1725b3e1433Swyllys
1735b3e1433Swyllys static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int);
17499ebb4caSwyllys
1754942e222SAndy Fiddaman static KMF_RETURN extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *,
1764942e222SAndy Fiddaman char *, CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
17771593db2Swyllys
1784942e222SAndy Fiddaman static KMF_RETURN kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *,
1794942e222SAndy Fiddaman KMF_CERT_VALIDITY, char *, KMF_DATA *);
18030a5e8faSwyllys
1814942e222SAndy Fiddaman static KMF_RETURN load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *,
1824942e222SAndy Fiddaman KMF_CERT_VALIDITY, char *, KMF_DATA **, uint32_t *);
18371593db2Swyllys
1844942e222SAndy Fiddaman static KMF_RETURN sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
18502744e81Swyllys
1864942e222SAndy Fiddaman static EVP_PKEY *ImportRawRSAKey(KMF_RAW_RSA_KEY *);
18702744e81Swyllys
1884942e222SAndy Fiddaman static KMF_RETURN convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
18930a5e8faSwyllys
1904942e222SAndy Fiddaman KMF_RETURN OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
19199ebb4caSwyllys
1924942e222SAndy Fiddaman void OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
19399ebb4caSwyllys
1944942e222SAndy Fiddaman KMF_RETURN OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
19599ebb4caSwyllys
1964942e222SAndy Fiddaman KMF_RETURN OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
19799ebb4caSwyllys
1984942e222SAndy Fiddaman KMF_RETURN OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
19930a5e8faSwyllys
2004942e222SAndy Fiddaman KMF_RETURN OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20199ebb4caSwyllys
2024942e222SAndy Fiddaman KMF_RETURN OpenSSL_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *,
2034942e222SAndy Fiddaman KMF_DATA *);
20499ebb4caSwyllys
2054942e222SAndy Fiddaman KMF_RETURN OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
20699ebb4caSwyllys KMF_DATA *, KMF_DATA *);
20799ebb4caSwyllys
2084942e222SAndy Fiddaman KMF_RETURN OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
20999ebb4caSwyllys
2104942e222SAndy Fiddaman KMF_RETURN OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21199ebb4caSwyllys
2124942e222SAndy Fiddaman KMF_RETURN OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21399ebb4caSwyllys
2144942e222SAndy Fiddaman KMF_RETURN OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21599ebb4caSwyllys
2164942e222SAndy Fiddaman KMF_RETURN OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
21799ebb4caSwyllys
2184942e222SAndy Fiddaman KMF_RETURN OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
21999ebb4caSwyllys KMF_PRINTABLE_ITEM, char *);
22099ebb4caSwyllys
2214942e222SAndy Fiddaman KMF_RETURN OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
22299ebb4caSwyllys
2234942e222SAndy Fiddaman KMF_RETURN OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22499ebb4caSwyllys
2254942e222SAndy Fiddaman KMF_RETURN OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
22699ebb4caSwyllys KMF_DATA *, KMF_DATA *);
22799ebb4caSwyllys
2284942e222SAndy Fiddaman KMF_RETURN OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
22999ebb4caSwyllys
2304942e222SAndy Fiddaman KMF_RETURN OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23199ebb4caSwyllys
2324942e222SAndy Fiddaman KMF_RETURN OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23399ebb4caSwyllys
2344942e222SAndy Fiddaman KMF_RETURN OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23599ebb4caSwyllys
2364942e222SAndy Fiddaman KMF_RETURN OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
23799ebb4caSwyllys
2384942e222SAndy Fiddaman KMF_RETURN OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *,
2394942e222SAndy Fiddaman KMF_RAW_SYM_KEY *);
24099ebb4caSwyllys
2414942e222SAndy Fiddaman KMF_RETURN OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
24299ebb4caSwyllys
2434942e222SAndy Fiddaman KMF_RETURN OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
24499ebb4caSwyllys
24599ebb4caSwyllys static
24699ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table =
24799ebb4caSwyllys {
24899ebb4caSwyllys 1, /* Version */
24999ebb4caSwyllys NULL, /* ConfigureKeystore */
25099ebb4caSwyllys OpenSSL_FindCert,
25199ebb4caSwyllys OpenSSL_FreeKMFCert,
25299ebb4caSwyllys OpenSSL_StoreCert,
25399ebb4caSwyllys NULL, /* ImportCert */
25499ebb4caSwyllys OpenSSL_ImportCRL,
25599ebb4caSwyllys OpenSSL_DeleteCert,
25699ebb4caSwyllys OpenSSL_DeleteCRL,
25799ebb4caSwyllys OpenSSL_CreateKeypair,
25899ebb4caSwyllys OpenSSL_FindKey,
25999ebb4caSwyllys OpenSSL_EncodePubKeyData,
26099ebb4caSwyllys OpenSSL_SignData,
26199ebb4caSwyllys OpenSSL_DeleteKey,
26299ebb4caSwyllys OpenSSL_ListCRL,
26399ebb4caSwyllys NULL, /* FindCRL */
26499ebb4caSwyllys OpenSSL_FindCertInCRL,
26599ebb4caSwyllys OpenSSL_GetErrorString,
26630a5e8faSwyllys OpenSSL_FindPrikeyByCert,
26799ebb4caSwyllys OpenSSL_DecryptData,
26830a5e8faSwyllys OpenSSL_ExportPK12,
26999ebb4caSwyllys OpenSSL_CreateSymKey,
27099ebb4caSwyllys OpenSSL_GetSymKeyValue,
27199ebb4caSwyllys NULL, /* SetTokenPin */
27230a5e8faSwyllys OpenSSL_StoreKey,
27399ebb4caSwyllys NULL /* Finalize */
27499ebb4caSwyllys };
27599ebb4caSwyllys
276553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
27799ebb4caSwyllys static mutex_t *lock_cs;
27899ebb4caSwyllys static long *lock_count;
27999ebb4caSwyllys
28099ebb4caSwyllys static void
locking_cb(int mode,int type,char * file,int line)28199ebb4caSwyllys locking_cb(int mode, int type, char *file, int line)
28299ebb4caSwyllys {
28399ebb4caSwyllys if (mode & CRYPTO_LOCK) {
28499ebb4caSwyllys (void) mutex_lock(&(lock_cs[type]));
28599ebb4caSwyllys lock_count[type]++;
28699ebb4caSwyllys } else {
28799ebb4caSwyllys (void) mutex_unlock(&(lock_cs[type]));
28899ebb4caSwyllys }
28999ebb4caSwyllys }
29099ebb4caSwyllys
29199ebb4caSwyllys static unsigned long
thread_id()29299ebb4caSwyllys thread_id()
29399ebb4caSwyllys {
29499ebb4caSwyllys return ((unsigned long)thr_self());
29599ebb4caSwyllys }
296553e44ceSAndrew Stormont #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER */
29799ebb4caSwyllys
29899ebb4caSwyllys KMF_PLUGIN_FUNCLIST *
KMF_Plugin_Initialize()29999ebb4caSwyllys KMF_Plugin_Initialize()
30099ebb4caSwyllys {
301553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
30299ebb4caSwyllys int i;
303300fdee2SAndy Fiddaman #endif
30499ebb4caSwyllys
30599ebb4caSwyllys (void) mutex_lock(&init_lock);
30699ebb4caSwyllys if (!ssl_initialized) {
30799ebb4caSwyllys /*
30899ebb4caSwyllys * Add support for extension OIDs that are not yet in the
30999ebb4caSwyllys * openssl default set.
31099ebb4caSwyllys */
31199ebb4caSwyllys (void) OBJ_create("2.5.29.30", "nameConstraints",
31299ebb4caSwyllys "X509v3 Name Constraints");
31399ebb4caSwyllys (void) OBJ_create("2.5.29.33", "policyMappings",
31499ebb4caSwyllys "X509v3 Policy Mappings");
31599ebb4caSwyllys (void) OBJ_create("2.5.29.36", "policyConstraints",
31699ebb4caSwyllys "X509v3 Policy Constraints");
31799ebb4caSwyllys (void) OBJ_create("2.5.29.46", "freshestCRL",
31899ebb4caSwyllys "X509v3 Freshest CRL");
31999ebb4caSwyllys (void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
32099ebb4caSwyllys "X509v3 Inhibit Any-Policy");
321300fdee2SAndy Fiddaman
322553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
32399ebb4caSwyllys /*
32499ebb4caSwyllys * Set up for thread-safe operation.
325300fdee2SAndy Fiddaman * This is not required for OpenSSL 1.1
32699ebb4caSwyllys */
32799ebb4caSwyllys lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
32899ebb4caSwyllys if (lock_cs == NULL) {
32999ebb4caSwyllys (void) mutex_unlock(&init_lock);
33099ebb4caSwyllys return (NULL);
33199ebb4caSwyllys }
33299ebb4caSwyllys
33399ebb4caSwyllys lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
33499ebb4caSwyllys if (lock_count == NULL) {
33599ebb4caSwyllys OPENSSL_free(lock_cs);
33699ebb4caSwyllys (void) mutex_unlock(&init_lock);
33799ebb4caSwyllys return (NULL);
33899ebb4caSwyllys }
33999ebb4caSwyllys
34099ebb4caSwyllys for (i = 0; i < CRYPTO_num_locks(); i++) {
34199ebb4caSwyllys lock_count[i] = 0;
34299ebb4caSwyllys (void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
34399ebb4caSwyllys }
34499ebb4caSwyllys
34599ebb4caSwyllys CRYPTO_set_id_callback((unsigned long (*)())thread_id);
3462c9a247fSWyllys Ingersoll if (CRYPTO_get_locking_callback() == NULL)
34799ebb4caSwyllys CRYPTO_set_locking_callback((void (*)())locking_cb);
3482c9a247fSWyllys Ingersoll
349300fdee2SAndy Fiddaman (void) OpenSSL_add_all_algorithms();
3502c9a247fSWyllys Ingersoll
3512c9a247fSWyllys Ingersoll /* Enable error strings for reporting */
352300fdee2SAndy Fiddaman (void) ERR_load_crypto_strings();
353300fdee2SAndy Fiddaman #endif
3542c9a247fSWyllys Ingersoll
35599ebb4caSwyllys ssl_initialized = 1;
35699ebb4caSwyllys }
35799ebb4caSwyllys (void) mutex_unlock(&init_lock);
35899ebb4caSwyllys
35999ebb4caSwyllys return (&openssl_plugin_table);
36099ebb4caSwyllys }
361300fdee2SAndy Fiddaman
36299ebb4caSwyllys /*
36399ebb4caSwyllys * Convert an SSL DN to a KMF DN.
36499ebb4caSwyllys */
36599ebb4caSwyllys static KMF_RETURN
get_x509_dn(X509_NAME * sslDN,KMF_X509_NAME * kmfDN)36699ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
36799ebb4caSwyllys {
36899ebb4caSwyllys KMF_DATA derdata;
36999ebb4caSwyllys KMF_RETURN rv = KMF_OK;
37099ebb4caSwyllys uchar_t *tmp;
37199ebb4caSwyllys
37299ebb4caSwyllys /* Convert to raw DER format */
37399ebb4caSwyllys derdata.Length = i2d_X509_NAME(sslDN, NULL);
37499ebb4caSwyllys if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
37599ebb4caSwyllys == NULL) {
37699ebb4caSwyllys return (KMF_ERR_MEMORY);
37799ebb4caSwyllys }
37899ebb4caSwyllys (void) i2d_X509_NAME(sslDN, &tmp);
37999ebb4caSwyllys
38099ebb4caSwyllys /* Decode to KMF format */
38199ebb4caSwyllys rv = DerDecodeName(&derdata, kmfDN);
38299ebb4caSwyllys if (rv != KMF_OK) {
38399ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT;
38499ebb4caSwyllys }
38599ebb4caSwyllys OPENSSL_free(derdata.Data);
38699ebb4caSwyllys
38799ebb4caSwyllys return (rv);
38899ebb4caSwyllys }
38999ebb4caSwyllys
39030a5e8faSwyllys int
isdir(char * path)39199ebb4caSwyllys isdir(char *path)
39299ebb4caSwyllys {
39399ebb4caSwyllys struct stat s;
39499ebb4caSwyllys
39599ebb4caSwyllys if (stat(path, &s) == -1)
39699ebb4caSwyllys return (0);
39799ebb4caSwyllys
39830a5e8faSwyllys return ((s.st_mode & S_IFMT) == S_IFDIR);
39999ebb4caSwyllys }
40099ebb4caSwyllys
40199ebb4caSwyllys static KMF_RETURN
ssl_cert2KMFDATA(KMF_HANDLE * kmfh,X509 * x509cert,KMF_DATA * cert)40299ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
40399ebb4caSwyllys {
40499ebb4caSwyllys KMF_RETURN rv = KMF_OK;
40599ebb4caSwyllys unsigned char *buf = NULL, *p;
40699ebb4caSwyllys int len;
40799ebb4caSwyllys
40899ebb4caSwyllys /*
40999ebb4caSwyllys * Convert the X509 internal struct to DER encoded data
41099ebb4caSwyllys */
41199ebb4caSwyllys if ((len = i2d_X509(x509cert, NULL)) < 0) {
41299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
41399ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT;
41499ebb4caSwyllys goto cleanup;
41599ebb4caSwyllys }
41699ebb4caSwyllys if ((buf = malloc(len)) == NULL) {
41799ebb4caSwyllys SET_SYS_ERROR(kmfh, errno);
41899ebb4caSwyllys rv = KMF_ERR_MEMORY;
41999ebb4caSwyllys goto cleanup;
42099ebb4caSwyllys }
42199ebb4caSwyllys
42299ebb4caSwyllys /*
42399ebb4caSwyllys * i2d_X509 will increment the buf pointer so that we need to
42499ebb4caSwyllys * save it.
42599ebb4caSwyllys */
42699ebb4caSwyllys p = buf;
42799ebb4caSwyllys if ((len = i2d_X509(x509cert, &p)) < 0) {
42899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
42999ebb4caSwyllys free(buf);
43099ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT;
43199ebb4caSwyllys goto cleanup;
43299ebb4caSwyllys }
43399ebb4caSwyllys
43499ebb4caSwyllys /* caller's responsibility to free it */
43599ebb4caSwyllys cert->Data = buf;
43699ebb4caSwyllys cert->Length = len;
43799ebb4caSwyllys
43899ebb4caSwyllys cleanup:
43999ebb4caSwyllys if (rv != KMF_OK) {
44099ebb4caSwyllys if (buf)
44199ebb4caSwyllys free(buf);
44299ebb4caSwyllys cert->Data = NULL;
44399ebb4caSwyllys cert->Length = 0;
44499ebb4caSwyllys }
44599ebb4caSwyllys
44699ebb4caSwyllys return (rv);
44799ebb4caSwyllys }
44899ebb4caSwyllys
44930a5e8faSwyllys
45099ebb4caSwyllys static KMF_RETURN
check_cert(X509 * xcert,char * issuer,char * subject,KMF_BIGINT * serial,boolean_t * match)45130a5e8faSwyllys check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
45230a5e8faSwyllys boolean_t *match)
45399ebb4caSwyllys {
45499ebb4caSwyllys KMF_RETURN rv = KMF_OK;
45599ebb4caSwyllys boolean_t findIssuer = FALSE;
45699ebb4caSwyllys boolean_t findSubject = FALSE;
45799ebb4caSwyllys boolean_t findSerial = FALSE;
45899ebb4caSwyllys KMF_X509_NAME issuerDN, subjectDN;
45999ebb4caSwyllys KMF_X509_NAME certIssuerDN, certSubjectDN;
46099ebb4caSwyllys
46199ebb4caSwyllys *match = FALSE;
46299ebb4caSwyllys if (xcert == NULL) {
46399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
46499ebb4caSwyllys }
46599ebb4caSwyllys
46699ebb4caSwyllys (void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
46799ebb4caSwyllys (void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
46899ebb4caSwyllys (void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
46999ebb4caSwyllys (void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
47099ebb4caSwyllys
47130a5e8faSwyllys if (issuer != NULL && strlen(issuer)) {
47230a5e8faSwyllys rv = kmf_dn_parser(issuer, &issuerDN);
47399ebb4caSwyllys if (rv != KMF_OK)
47499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
47599ebb4caSwyllys
476300fdee2SAndy Fiddaman rv = get_x509_dn(X509_get_issuer_name(xcert), &certIssuerDN);
47799ebb4caSwyllys if (rv != KMF_OK) {
47830a5e8faSwyllys kmf_free_dn(&issuerDN);
47999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
48099ebb4caSwyllys }
48199ebb4caSwyllys
48299ebb4caSwyllys findIssuer = TRUE;
48399ebb4caSwyllys }
48430a5e8faSwyllys if (subject != NULL && strlen(subject)) {
48530a5e8faSwyllys rv = kmf_dn_parser(subject, &subjectDN);
48699ebb4caSwyllys if (rv != KMF_OK) {
48799ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER;
48899ebb4caSwyllys goto cleanup;
48999ebb4caSwyllys }
49099ebb4caSwyllys
491300fdee2SAndy Fiddaman rv = get_x509_dn(X509_get_subject_name(xcert), &certSubjectDN);
49299ebb4caSwyllys if (rv != KMF_OK) {
49399ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER;
49499ebb4caSwyllys goto cleanup;
49599ebb4caSwyllys }
49699ebb4caSwyllys findSubject = TRUE;
49799ebb4caSwyllys }
49830a5e8faSwyllys if (serial != NULL && serial->val != NULL)
49999ebb4caSwyllys findSerial = TRUE;
50099ebb4caSwyllys
50199ebb4caSwyllys if (findSerial) {
50299ebb4caSwyllys BIGNUM *bn;
50399ebb4caSwyllys
50499ebb4caSwyllys /* Comparing BIGNUMs is a pain! */
505300fdee2SAndy Fiddaman bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(xcert), NULL);
50699ebb4caSwyllys if (bn != NULL) {
50799ebb4caSwyllys int bnlen = BN_num_bytes(bn);
50899ebb4caSwyllys
50930a5e8faSwyllys if (bnlen == serial->len) {
51099ebb4caSwyllys uchar_t *a = malloc(bnlen);
51199ebb4caSwyllys if (a == NULL) {
51299ebb4caSwyllys rv = KMF_ERR_MEMORY;
51399ebb4caSwyllys BN_free(bn);
51499ebb4caSwyllys goto cleanup;
51599ebb4caSwyllys }
51699ebb4caSwyllys bnlen = BN_bn2bin(bn, a);
51730a5e8faSwyllys *match = (memcmp(a, serial->val, serial->len) ==
51830a5e8faSwyllys 0);
51999ebb4caSwyllys rv = KMF_OK;
52099ebb4caSwyllys free(a);
52199ebb4caSwyllys }
52299ebb4caSwyllys BN_free(bn);
52399ebb4caSwyllys if (!(*match))
52499ebb4caSwyllys goto cleanup;
52599ebb4caSwyllys } else {
52699ebb4caSwyllys rv = KMF_OK;
52799ebb4caSwyllys goto cleanup;
52899ebb4caSwyllys }
52999ebb4caSwyllys }
53099ebb4caSwyllys if (findIssuer) {
53130a5e8faSwyllys *match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
53230a5e8faSwyllys if ((*match) == B_FALSE) {
53330a5e8faSwyllys /* stop checking and bail */
53499ebb4caSwyllys rv = KMF_OK;
53599ebb4caSwyllys goto cleanup;
53699ebb4caSwyllys }
53799ebb4caSwyllys }
53899ebb4caSwyllys if (findSubject) {
53930a5e8faSwyllys *match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
54030a5e8faSwyllys if ((*match) == B_FALSE) {
54130a5e8faSwyllys /* stop checking and bail */
54299ebb4caSwyllys rv = KMF_OK;
54399ebb4caSwyllys goto cleanup;
54499ebb4caSwyllys }
54599ebb4caSwyllys }
54699ebb4caSwyllys
54799ebb4caSwyllys *match = TRUE;
54899ebb4caSwyllys cleanup:
54999ebb4caSwyllys if (findIssuer) {
55030a5e8faSwyllys kmf_free_dn(&issuerDN);
55130a5e8faSwyllys kmf_free_dn(&certIssuerDN);
55299ebb4caSwyllys }
55399ebb4caSwyllys if (findSubject) {
55430a5e8faSwyllys kmf_free_dn(&subjectDN);
55530a5e8faSwyllys kmf_free_dn(&certSubjectDN);
55699ebb4caSwyllys }
55799ebb4caSwyllys
55899ebb4caSwyllys return (rv);
55999ebb4caSwyllys }
56099ebb4caSwyllys
56130a5e8faSwyllys
56230a5e8faSwyllys /*
56330a5e8faSwyllys * This function loads a certificate file into an X509 data structure, and
56430a5e8faSwyllys * checks if its issuer, subject or the serial number matches with those
56530a5e8faSwyllys * values. If it matches, then return the X509 data structure.
56630a5e8faSwyllys */
56799ebb4caSwyllys static KMF_RETURN
load_X509cert(KMF_HANDLE * kmfh,char * issuer,char * subject,KMF_BIGINT * serial,char * pathname,X509 ** outcert)5684942e222SAndy Fiddaman load_X509cert(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
56930a5e8faSwyllys char *pathname, X509 **outcert)
57099ebb4caSwyllys {
57199ebb4caSwyllys KMF_RETURN rv = KMF_OK;
57299ebb4caSwyllys X509 *xcert = NULL;
57399ebb4caSwyllys BIO *bcert = NULL;
57499ebb4caSwyllys boolean_t match = FALSE;
57599ebb4caSwyllys KMF_ENCODE_FORMAT format;
57699ebb4caSwyllys
57799ebb4caSwyllys /*
57899ebb4caSwyllys * auto-detect the file format, regardless of what
57999ebb4caSwyllys * the 'format' parameters in the params say.
58099ebb4caSwyllys */
58130a5e8faSwyllys rv = kmf_get_file_format(pathname, &format);
58299ebb4caSwyllys if (rv != KMF_OK) {
58399ebb4caSwyllys if (rv == KMF_ERR_OPEN_FILE)
58499ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND;
58599ebb4caSwyllys return (rv);
58699ebb4caSwyllys }
58799ebb4caSwyllys
58899ebb4caSwyllys /* Not ASN1(DER) format */
58999ebb4caSwyllys if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
59099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
59199ebb4caSwyllys rv = KMF_ERR_OPEN_FILE;
59299ebb4caSwyllys goto cleanup;
59399ebb4caSwyllys }
59499ebb4caSwyllys
59599ebb4caSwyllys if (format == KMF_FORMAT_PEM)
59699ebb4caSwyllys xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
59799ebb4caSwyllys else if (format == KMF_FORMAT_ASN1)
59899ebb4caSwyllys xcert = d2i_X509_bio(bcert, NULL);
59999ebb4caSwyllys else if (format == KMF_FORMAT_PKCS12) {
60099ebb4caSwyllys PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
60199ebb4caSwyllys if (p12 != NULL) {
60299ebb4caSwyllys (void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
60399ebb4caSwyllys PKCS12_free(p12);
60499ebb4caSwyllys p12 = NULL;
60599ebb4caSwyllys } else {
60699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
60799ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT;
60899ebb4caSwyllys }
60999ebb4caSwyllys } else {
61099ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER;
61199ebb4caSwyllys goto cleanup;
61299ebb4caSwyllys }
61399ebb4caSwyllys
61499ebb4caSwyllys if (xcert == NULL) {
61599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
61699ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT;
61799ebb4caSwyllys goto cleanup;
61899ebb4caSwyllys }
61999ebb4caSwyllys
62030a5e8faSwyllys if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
62130a5e8faSwyllys match == FALSE) {
62299ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND;
62399ebb4caSwyllys goto cleanup;
62499ebb4caSwyllys }
62599ebb4caSwyllys
62699ebb4caSwyllys if (outcert != NULL) {
62799ebb4caSwyllys *outcert = xcert;
62899ebb4caSwyllys }
62999ebb4caSwyllys
63099ebb4caSwyllys cleanup:
63199ebb4caSwyllys if (bcert != NULL) (void) BIO_free(bcert);
63299ebb4caSwyllys if (rv != KMF_OK && xcert != NULL)
63399ebb4caSwyllys X509_free(xcert);
63499ebb4caSwyllys
63599ebb4caSwyllys return (rv);
63699ebb4caSwyllys }
63799ebb4caSwyllys
63871593db2Swyllys static int
datacmp(const void * a,const void * b)63971593db2Swyllys datacmp(const void *a, const void *b)
64071593db2Swyllys {
64171593db2Swyllys KMF_DATA *adata = (KMF_DATA *)a;
64271593db2Swyllys KMF_DATA *bdata = (KMF_DATA *)b;
64371593db2Swyllys if (adata->Length > bdata->Length)
64471593db2Swyllys return (-1);
64571593db2Swyllys if (adata->Length < bdata->Length)
64671593db2Swyllys return (1);
64771593db2Swyllys return (0);
64871593db2Swyllys }
64971593db2Swyllys
65071593db2Swyllys static KMF_RETURN
load_certs(KMF_HANDLE * kmfh,char * issuer,char * subject,KMF_BIGINT * serial,KMF_CERT_VALIDITY validity,char * pathname,KMF_DATA ** certlist,uint32_t * numcerts)65130a5e8faSwyllys load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
65230a5e8faSwyllys KMF_CERT_VALIDITY validity, char *pathname,
65371593db2Swyllys KMF_DATA **certlist, uint32_t *numcerts)
65471593db2Swyllys {
65571593db2Swyllys KMF_RETURN rv = KMF_OK;
65671593db2Swyllys int i;
65771593db2Swyllys KMF_DATA *certs = NULL;
65871593db2Swyllys int nc = 0;
65971593db2Swyllys int hits = 0;
66071593db2Swyllys KMF_ENCODE_FORMAT format;
66171593db2Swyllys
66230a5e8faSwyllys rv = kmf_get_file_format(pathname, &format);
66371593db2Swyllys if (rv != KMF_OK) {
66471593db2Swyllys if (rv == KMF_ERR_OPEN_FILE)
66571593db2Swyllys rv = KMF_ERR_CERT_NOT_FOUND;
66671593db2Swyllys return (rv);
66771593db2Swyllys }
66871593db2Swyllys if (format == KMF_FORMAT_ASN1) {
66971593db2Swyllys /* load a single certificate */
67071593db2Swyllys certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
67171593db2Swyllys if (certs == NULL)
67271593db2Swyllys return (KMF_ERR_MEMORY);
67371593db2Swyllys certs->Data = NULL;
67471593db2Swyllys certs->Length = 0;
67530a5e8faSwyllys rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
67630a5e8faSwyllys pathname, certs);
67771593db2Swyllys if (rv == KMF_OK) {
67871593db2Swyllys *certlist = certs;
67971593db2Swyllys *numcerts = 1;
680a2d4930dSDan OpenSolaris Anderson } else {
681a2d4930dSDan OpenSolaris Anderson kmf_free_data(certs);
682a2d4930dSDan OpenSolaris Anderson free(certs);
683a2d4930dSDan OpenSolaris Anderson certs = NULL;
68471593db2Swyllys }
68571593db2Swyllys return (rv);
68671593db2Swyllys } else if (format == KMF_FORMAT_PKCS12) {
68771593db2Swyllys /* We need a credential to access a PKCS#12 file */
68871593db2Swyllys rv = KMF_ERR_BAD_CERT_FORMAT;
68971593db2Swyllys } else if (format == KMF_FORMAT_PEM ||
69071593db2Swyllys format != KMF_FORMAT_PEM_KEYPAIR) {
691e65e5c2dSWyllys Ingersoll
69271593db2Swyllys /* This function only works on PEM files */
69330a5e8faSwyllys rv = extract_pem(kmfh, issuer, subject, serial, pathname,
69434acef67Swyllys (uchar_t *)NULL, 0, NULL, &certs, &nc);
69571593db2Swyllys } else {
69671593db2Swyllys return (KMF_ERR_ENCODING);
69771593db2Swyllys }
69871593db2Swyllys
69971593db2Swyllys if (rv != KMF_OK)
70071593db2Swyllys return (rv);
70171593db2Swyllys
70271593db2Swyllys for (i = 0; i < nc; i++) {
70330a5e8faSwyllys if (validity == KMF_NONEXPIRED_CERTS) {
70430a5e8faSwyllys rv = kmf_check_cert_date(kmfh, &certs[i]);
70530a5e8faSwyllys } else if (validity == KMF_EXPIRED_CERTS) {
70630a5e8faSwyllys rv = kmf_check_cert_date(kmfh, &certs[i]);
70771593db2Swyllys if (rv == KMF_OK)
70871593db2Swyllys rv = KMF_ERR_CERT_NOT_FOUND;
70971593db2Swyllys if (rv == KMF_ERR_VALIDITY_PERIOD)
71071593db2Swyllys rv = KMF_OK;
71171593db2Swyllys }
71271593db2Swyllys if (rv != KMF_OK) {
71371593db2Swyllys /* Remove this cert from the list by clearing it. */
71430a5e8faSwyllys kmf_free_data(&certs[i]);
71571593db2Swyllys } else {
71671593db2Swyllys hits++; /* count valid certs found */
71771593db2Swyllys }
71871593db2Swyllys rv = KMF_OK;
71971593db2Swyllys }
720a2d4930dSDan OpenSolaris Anderson if (rv == KMF_OK && hits > 0) {
72171593db2Swyllys /*
72271593db2Swyllys * Sort the list of certs by length to put the cleared ones
72371593db2Swyllys * at the end so they don't get accessed by the caller.
72471593db2Swyllys */
72571593db2Swyllys qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
72671593db2Swyllys *certlist = certs;
72771593db2Swyllys
72871593db2Swyllys /* since we sorted the list, just return the number of hits */
72971593db2Swyllys *numcerts = hits;
730a2d4930dSDan OpenSolaris Anderson } else {
731e65e5c2dSWyllys Ingersoll if (rv == KMF_OK && hits == 0)
732a2d4930dSDan OpenSolaris Anderson rv = KMF_ERR_CERT_NOT_FOUND;
733a2d4930dSDan OpenSolaris Anderson if (certs != NULL) {
734a2d4930dSDan OpenSolaris Anderson free(certs);
735a2d4930dSDan OpenSolaris Anderson certs = NULL;
736a2d4930dSDan OpenSolaris Anderson }
737a2d4930dSDan OpenSolaris Anderson }
73871593db2Swyllys return (rv);
73971593db2Swyllys }
74071593db2Swyllys
74199ebb4caSwyllys static KMF_RETURN
kmf_load_cert(KMF_HANDLE * kmfh,char * issuer,char * subject,KMF_BIGINT * serial,KMF_CERT_VALIDITY validity,char * pathname,KMF_DATA * cert)7424942e222SAndy Fiddaman kmf_load_cert(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
7434942e222SAndy Fiddaman KMF_CERT_VALIDITY validity, char *pathname, KMF_DATA *cert)
74499ebb4caSwyllys {
74599ebb4caSwyllys KMF_RETURN rv = KMF_OK;
74699ebb4caSwyllys X509 *x509cert = NULL;
74799ebb4caSwyllys
74830a5e8faSwyllys rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
74999ebb4caSwyllys if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
75099ebb4caSwyllys rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
75199ebb4caSwyllys if (rv != KMF_OK) {
75299ebb4caSwyllys goto cleanup;
75399ebb4caSwyllys }
75430a5e8faSwyllys if (validity == KMF_NONEXPIRED_CERTS) {
75530a5e8faSwyllys rv = kmf_check_cert_date(kmfh, cert);
75630a5e8faSwyllys } else if (validity == KMF_EXPIRED_CERTS) {
75730a5e8faSwyllys rv = kmf_check_cert_date(kmfh, cert);
75899ebb4caSwyllys if (rv == KMF_OK) {
75999ebb4caSwyllys /*
76099ebb4caSwyllys * This is a valid cert so skip it.
76199ebb4caSwyllys */
76299ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND;
76399ebb4caSwyllys }
76499ebb4caSwyllys if (rv == KMF_ERR_VALIDITY_PERIOD) {
76599ebb4caSwyllys /*
76699ebb4caSwyllys * We want to return success when we
76799ebb4caSwyllys * find an invalid cert.
76899ebb4caSwyllys */
76999ebb4caSwyllys rv = KMF_OK;
77099ebb4caSwyllys goto cleanup;
77199ebb4caSwyllys }
77299ebb4caSwyllys }
77399ebb4caSwyllys }
77499ebb4caSwyllys cleanup:
77599ebb4caSwyllys if (x509cert != NULL)
77699ebb4caSwyllys X509_free(x509cert);
77799ebb4caSwyllys
77899ebb4caSwyllys return (rv);
77999ebb4caSwyllys }
78099ebb4caSwyllys
78102744e81Swyllys static KMF_RETURN
readAltFormatPrivateKey(KMF_DATA * filedata,EVP_PKEY ** pkey)78202744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
78302744e81Swyllys {
78402744e81Swyllys KMF_RETURN ret = KMF_OK;
78502744e81Swyllys KMF_RAW_RSA_KEY rsa;
78602744e81Swyllys BerElement *asn1 = NULL;
78702744e81Swyllys BerValue filebuf;
788f810c7e5SToomas Soome BerValue OID = { 0, 0 };
78902744e81Swyllys BerValue *Mod = NULL, *PubExp = NULL;
79002744e81Swyllys BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
79102744e81Swyllys BerValue *Coef = NULL;
79202744e81Swyllys BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
79302744e81Swyllys BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
79402744e81Swyllys BIGNUM *qminus1 = NULL;
79502744e81Swyllys BN_CTX *ctx = NULL;
79602744e81Swyllys
79702744e81Swyllys *pkey = NULL;
79802744e81Swyllys
79902744e81Swyllys filebuf.bv_val = (char *)filedata->Data;
80002744e81Swyllys filebuf.bv_len = filedata->Length;
80102744e81Swyllys
80202744e81Swyllys asn1 = kmfder_init(&filebuf);
80302744e81Swyllys if (asn1 == NULL) {
80402744e81Swyllys ret = KMF_ERR_MEMORY;
80502744e81Swyllys goto out;
80602744e81Swyllys }
80702744e81Swyllys
80802744e81Swyllys if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
80902744e81Swyllys &OID, &Mod, &PubExp, &PriExp, &Prime1,
81002744e81Swyllys &Prime2, &Coef) == -1) {
81102744e81Swyllys ret = KMF_ERR_ENCODING;
81202744e81Swyllys goto out;
81302744e81Swyllys }
81402744e81Swyllys
81502744e81Swyllys /*
81602744e81Swyllys * We have to derive the 2 Exponents using Bignumber math.
81702744e81Swyllys * Exp1 = PriExp mod (Prime1 - 1)
81802744e81Swyllys * Exp2 = PriExp mod (Prime2 - 1)
81902744e81Swyllys */
82002744e81Swyllys
82102744e81Swyllys /* D = PrivateExponent */
82202744e81Swyllys D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
82302744e81Swyllys if (D == NULL) {
82402744e81Swyllys ret = KMF_ERR_MEMORY;
82502744e81Swyllys goto out;
82602744e81Swyllys }
82702744e81Swyllys
82802744e81Swyllys /* P = Prime1 (first prime factor of Modulus) */
82902744e81Swyllys P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
83002744e81Swyllys if (D == NULL) {
83102744e81Swyllys ret = KMF_ERR_MEMORY;
83202744e81Swyllys goto out;
83302744e81Swyllys }
83402744e81Swyllys
83502744e81Swyllys /* Q = Prime2 (second prime factor of Modulus) */
83602744e81Swyllys Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
83702744e81Swyllys
83802744e81Swyllys if ((ctx = BN_CTX_new()) == NULL) {
83902744e81Swyllys ret = KMF_ERR_MEMORY;
84002744e81Swyllys goto out;
84102744e81Swyllys }
84202744e81Swyllys
84302744e81Swyllys /* Compute (P - 1) */
84402744e81Swyllys pminus1 = BN_new();
84502744e81Swyllys (void) BN_sub(pminus1, P, BN_value_one());
84602744e81Swyllys
84702744e81Swyllys /* Exponent1 = D mod (P - 1) */
84802744e81Swyllys Exp1 = BN_new();
84902744e81Swyllys (void) BN_mod(Exp1, D, pminus1, ctx);
85002744e81Swyllys
85102744e81Swyllys /* Compute (Q - 1) */
85202744e81Swyllys qminus1 = BN_new();
85302744e81Swyllys (void) BN_sub(qminus1, Q, BN_value_one());
85402744e81Swyllys
85502744e81Swyllys /* Exponent2 = D mod (Q - 1) */
85602744e81Swyllys Exp2 = BN_new();
85702744e81Swyllys (void) BN_mod(Exp2, D, qminus1, ctx);
85802744e81Swyllys
85902744e81Swyllys /* Coef = (Inverse Q) mod P */
86002744e81Swyllys COEF = BN_new();
86102744e81Swyllys (void) BN_mod_inverse(COEF, Q, P, ctx);
86202744e81Swyllys
86302744e81Swyllys /* Convert back to KMF format */
86402744e81Swyllys (void) memset(&rsa, 0, sizeof (rsa));
86502744e81Swyllys
86602744e81Swyllys if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
86702744e81Swyllys goto out;
86802744e81Swyllys if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
86902744e81Swyllys goto out;
87002744e81Swyllys if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
87102744e81Swyllys goto out;
87202744e81Swyllys
87302744e81Swyllys rsa.mod.val = (uchar_t *)Mod->bv_val;
87402744e81Swyllys rsa.mod.len = Mod->bv_len;
87502744e81Swyllys
87602744e81Swyllys rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
87702744e81Swyllys rsa.pubexp.len = PubExp->bv_len;
87802744e81Swyllys
87902744e81Swyllys rsa.priexp.val = (uchar_t *)PriExp->bv_val;
88002744e81Swyllys rsa.priexp.len = PriExp->bv_len;
88102744e81Swyllys
88202744e81Swyllys rsa.prime1.val = (uchar_t *)Prime1->bv_val;
88302744e81Swyllys rsa.prime1.len = Prime1->bv_len;
88402744e81Swyllys
88502744e81Swyllys rsa.prime2.val = (uchar_t *)Prime2->bv_val;
88602744e81Swyllys rsa.prime2.len = Prime2->bv_len;
88702744e81Swyllys
88802744e81Swyllys *pkey = ImportRawRSAKey(&rsa);
88902744e81Swyllys out:
89002744e81Swyllys if (asn1 != NULL)
89102744e81Swyllys kmfber_free(asn1, 1);
89202744e81Swyllys
89302744e81Swyllys if (OID.bv_val) {
89402744e81Swyllys free(OID.bv_val);
89502744e81Swyllys }
89602744e81Swyllys if (PriExp)
89702744e81Swyllys free(PriExp);
89802744e81Swyllys
89902744e81Swyllys if (Mod)
90002744e81Swyllys free(Mod);
90102744e81Swyllys
90202744e81Swyllys if (PubExp)
90302744e81Swyllys free(PubExp);
90402744e81Swyllys
90502744e81Swyllys if (Coef) {
90602744e81Swyllys (void) memset(Coef->bv_val, 0, Coef->bv_len);
90702744e81Swyllys free(Coef->bv_val);
90802744e81Swyllys free(Coef);
90902744e81Swyllys }
91002744e81Swyllys if (Prime1)
91102744e81Swyllys free(Prime1);
91202744e81Swyllys if (Prime2)
91302744e81Swyllys free(Prime2);
91402744e81Swyllys
91502744e81Swyllys if (ctx != NULL)
91602744e81Swyllys BN_CTX_free(ctx);
91702744e81Swyllys
91802744e81Swyllys if (D)
91902744e81Swyllys BN_clear_free(D);
92002744e81Swyllys if (P)
92102744e81Swyllys BN_clear_free(P);
92202744e81Swyllys if (Q)
92302744e81Swyllys BN_clear_free(Q);
92402744e81Swyllys if (pminus1)
92502744e81Swyllys BN_clear_free(pminus1);
92602744e81Swyllys if (qminus1)
92702744e81Swyllys BN_clear_free(qminus1);
92802744e81Swyllys if (Exp1)
92902744e81Swyllys BN_clear_free(Exp1);
93002744e81Swyllys if (Exp2)
93102744e81Swyllys BN_clear_free(Exp2);
93202744e81Swyllys
93302744e81Swyllys return (ret);
93402744e81Swyllys
93502744e81Swyllys }
93602744e81Swyllys
93799ebb4caSwyllys static EVP_PKEY *
openssl_load_key(KMF_HANDLE_T handle,const char * file)93899ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file)
93999ebb4caSwyllys {
94099ebb4caSwyllys BIO *keyfile = NULL;
94199ebb4caSwyllys EVP_PKEY *pkey = NULL;
94299ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
94399ebb4caSwyllys KMF_ENCODE_FORMAT format;
94402744e81Swyllys KMF_RETURN rv;
94502744e81Swyllys KMF_DATA filedata;
94699ebb4caSwyllys
94799ebb4caSwyllys if (file == NULL) {
94899ebb4caSwyllys return (NULL);
94999ebb4caSwyllys }
95099ebb4caSwyllys
95130a5e8faSwyllys if (kmf_get_file_format((char *)file, &format) != KMF_OK)
95299ebb4caSwyllys return (NULL);
95399ebb4caSwyllys
95499ebb4caSwyllys keyfile = BIO_new_file(file, "rb");
95599ebb4caSwyllys if (keyfile == NULL) {
95699ebb4caSwyllys goto end;
95799ebb4caSwyllys }
95899ebb4caSwyllys
95902744e81Swyllys if (format == KMF_FORMAT_ASN1) {
96099ebb4caSwyllys pkey = d2i_PrivateKey_bio(keyfile, NULL);
96102744e81Swyllys if (pkey == NULL) {
96202744e81Swyllys
96302744e81Swyllys (void) BIO_free(keyfile);
96402744e81Swyllys keyfile = NULL;
96502744e81Swyllys /* Try odd ASN.1 variations */
96630a5e8faSwyllys rv = kmf_read_input_file(kmfh, (char *)file,
96702744e81Swyllys &filedata);
96802744e81Swyllys if (rv == KMF_OK) {
96902744e81Swyllys (void) readAltFormatPrivateKey(&filedata,
97002744e81Swyllys &pkey);
97130a5e8faSwyllys kmf_free_data(&filedata);
97202744e81Swyllys }
97302744e81Swyllys }
97402744e81Swyllys } else if (format == KMF_FORMAT_PEM ||
97502744e81Swyllys format == KMF_FORMAT_PEM_KEYPAIR) {
97699ebb4caSwyllys pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
97702744e81Swyllys if (pkey == NULL) {
97802744e81Swyllys KMF_DATA derdata;
97902744e81Swyllys /*
98002744e81Swyllys * Check if this is the alt. format
98102744e81Swyllys * RSA private key file.
98202744e81Swyllys */
98330a5e8faSwyllys rv = kmf_read_input_file(kmfh, (char *)file,
98402744e81Swyllys &filedata);
98502744e81Swyllys if (rv == KMF_OK) {
98602744e81Swyllys uchar_t *d = NULL;
98702744e81Swyllys int len;
98830a5e8faSwyllys rv = kmf_pem_to_der(filedata.Data,
98902744e81Swyllys filedata.Length, &d, &len);
99002744e81Swyllys if (rv == KMF_OK && d != NULL) {
99102744e81Swyllys derdata.Data = d;
99202744e81Swyllys derdata.Length = (size_t)len;
99302744e81Swyllys (void) readAltFormatPrivateKey(
99402744e81Swyllys &derdata, &pkey);
99502744e81Swyllys free(d);
99602744e81Swyllys }
99730a5e8faSwyllys kmf_free_data(&filedata);
99802744e81Swyllys }
99902744e81Swyllys }
100002744e81Swyllys }
100199ebb4caSwyllys
100299ebb4caSwyllys end:
1003a50e8766SToomas Soome if (pkey == NULL) {
100499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
1005a50e8766SToomas Soome }
100699ebb4caSwyllys
100799ebb4caSwyllys if (keyfile != NULL)
100899ebb4caSwyllys (void) BIO_free(keyfile);
100999ebb4caSwyllys
101099ebb4caSwyllys return (pkey);
101199ebb4caSwyllys }
101299ebb4caSwyllys
101399ebb4caSwyllys KMF_RETURN
OpenSSL_FindCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)101430a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
101599ebb4caSwyllys {
101699ebb4caSwyllys KMF_RETURN rv = KMF_OK;
101799ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1018f482c776Swyllys int i, n;
1019f482c776Swyllys uint32_t maxcerts = 0;
102030a5e8faSwyllys uint32_t *num_certs;
102130a5e8faSwyllys KMF_X509_DER_CERT *kmf_cert = NULL;
102230a5e8faSwyllys char *dirpath = NULL;
102330a5e8faSwyllys char *filename = NULL;
102430a5e8faSwyllys char *fullpath = NULL;
102530a5e8faSwyllys char *issuer = NULL;
102630a5e8faSwyllys char *subject = NULL;
102730a5e8faSwyllys KMF_BIGINT *serial = NULL;
102830a5e8faSwyllys KMF_CERT_VALIDITY validity;
102999ebb4caSwyllys
103030a5e8faSwyllys num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
103130a5e8faSwyllys if (num_certs == NULL)
103299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
103399ebb4caSwyllys
103430a5e8faSwyllys /* num_certs should reference the size of kmf_cert */
1035f482c776Swyllys maxcerts = *num_certs;
1036f482c776Swyllys if (maxcerts == 0)
1037f482c776Swyllys maxcerts = 0xFFFFFFFF;
103899ebb4caSwyllys *num_certs = 0;
103999ebb4caSwyllys
104030a5e8faSwyllys /* Get the optional returned certificate list */
104130a5e8faSwyllys kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
104230a5e8faSwyllys numattr);
104399ebb4caSwyllys
104430a5e8faSwyllys /*
104530a5e8faSwyllys * The dirpath attribute and the filename attribute can not be NULL
104630a5e8faSwyllys * at the same time.
104730a5e8faSwyllys */
104830a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
104930a5e8faSwyllys filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
105030a5e8faSwyllys numattr);
105130a5e8faSwyllys
105230a5e8faSwyllys fullpath = get_fullpath(dirpath, filename);
105399ebb4caSwyllys if (fullpath == NULL)
105499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
105599ebb4caSwyllys
105630a5e8faSwyllys /* Get optional search criteria attributes */
105730a5e8faSwyllys issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
105830a5e8faSwyllys subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
105930a5e8faSwyllys serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
106030a5e8faSwyllys rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
106130a5e8faSwyllys &validity, NULL);
106230a5e8faSwyllys if (rv != KMF_OK) {
106330a5e8faSwyllys validity = KMF_ALL_CERTS;
106430a5e8faSwyllys rv = KMF_OK;
106530a5e8faSwyllys }
106630a5e8faSwyllys
106799ebb4caSwyllys if (isdir(fullpath)) {
106899ebb4caSwyllys DIR *dirp;
106999ebb4caSwyllys struct dirent *dp;
107099ebb4caSwyllys
1071f482c776Swyllys n = 0;
107299ebb4caSwyllys /* open all files in the directory and attempt to read them */
107399ebb4caSwyllys if ((dirp = opendir(fullpath)) == NULL) {
107499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
107599ebb4caSwyllys }
107699ebb4caSwyllys while ((dp = readdir(dirp)) != NULL) {
107799ebb4caSwyllys char *fname;
107871593db2Swyllys KMF_DATA *certlist = NULL;
1079f482c776Swyllys uint32_t loaded_certs = 0;
108071593db2Swyllys
108199ebb4caSwyllys if (strcmp(dp->d_name, ".") == 0 ||
108299ebb4caSwyllys strcmp(dp->d_name, "..") == 0)
108399ebb4caSwyllys continue;
108499ebb4caSwyllys
108534acef67Swyllys fname = get_fullpath(fullpath, (char *)&dp->d_name);
108699ebb4caSwyllys
108730a5e8faSwyllys rv = load_certs(kmfh, issuer, subject, serial,
108830a5e8faSwyllys validity, fname, &certlist, &loaded_certs);
108999ebb4caSwyllys
109099ebb4caSwyllys if (rv != KMF_OK) {
109199ebb4caSwyllys free(fname);
109271593db2Swyllys if (certlist != NULL) {
1093f482c776Swyllys for (i = 0; i < loaded_certs; i++)
109430a5e8faSwyllys kmf_free_data(&certlist[i]);
109571593db2Swyllys free(certlist);
109671593db2Swyllys }
109799ebb4caSwyllys continue;
109899ebb4caSwyllys }
109999ebb4caSwyllys
110099ebb4caSwyllys /* If load succeeds, add certdata to the list */
110199ebb4caSwyllys if (kmf_cert != NULL) {
1102f482c776Swyllys for (i = 0; i < loaded_certs &&
1103b4058258Swyllys n < maxcerts; i++) {
110471593db2Swyllys kmf_cert[n].certificate.Data =
110571593db2Swyllys certlist[i].Data;
110699ebb4caSwyllys kmf_cert[n].certificate.Length =
110771593db2Swyllys certlist[i].Length;
110899ebb4caSwyllys
110999ebb4caSwyllys kmf_cert[n].kmf_private.keystore_type =
111099ebb4caSwyllys KMF_KEYSTORE_OPENSSL;
111199ebb4caSwyllys kmf_cert[n].kmf_private.flags =
111299ebb4caSwyllys KMF_FLAG_CERT_VALID;
111371593db2Swyllys kmf_cert[n].kmf_private.label =
111471593db2Swyllys strdup(fname);
111599ebb4caSwyllys n++;
111699ebb4caSwyllys }
1117b4058258Swyllys /*
1118b4058258Swyllys * If maxcerts < loaded_certs, clean up the
1119b4058258Swyllys * certs that were not used.
1120b4058258Swyllys */
1121f482c776Swyllys for (; i < loaded_certs; i++)
112230a5e8faSwyllys kmf_free_data(&certlist[i]);
1123f482c776Swyllys } else {
1124f482c776Swyllys for (i = 0; i < loaded_certs; i++)
112530a5e8faSwyllys kmf_free_data(&certlist[i]);
1126f482c776Swyllys n += loaded_certs;
112771593db2Swyllys }
1128f482c776Swyllys free(certlist);
112971593db2Swyllys free(fname);
113071593db2Swyllys }
113199ebb4caSwyllys (*num_certs) = n;
113299ebb4caSwyllys if (*num_certs == 0)
113399ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND;
113430a5e8faSwyllys if (*num_certs > 0)
113599ebb4caSwyllys rv = KMF_OK;
113699ebb4caSwyllys exit:
113799ebb4caSwyllys (void) closedir(dirp);
113899ebb4caSwyllys } else {
113971593db2Swyllys KMF_DATA *certlist = NULL;
1140f482c776Swyllys uint32_t loaded_certs = 0;
114171593db2Swyllys
114230a5e8faSwyllys rv = load_certs(kmfh, issuer, subject, serial, validity,
114330a5e8faSwyllys fullpath, &certlist, &loaded_certs);
114499ebb4caSwyllys if (rv != KMF_OK) {
114599ebb4caSwyllys free(fullpath);
114699ebb4caSwyllys return (rv);
114799ebb4caSwyllys }
114899ebb4caSwyllys
1149f482c776Swyllys n = 0;
115071593db2Swyllys if (kmf_cert != NULL && certlist != NULL) {
1151f482c776Swyllys for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1152f482c776Swyllys kmf_cert[n].certificate.Data =
115371593db2Swyllys certlist[i].Data;
1154f482c776Swyllys kmf_cert[n].certificate.Length =
115571593db2Swyllys certlist[i].Length;
1156f482c776Swyllys kmf_cert[n].kmf_private.keystore_type =
115799ebb4caSwyllys KMF_KEYSTORE_OPENSSL;
1158f482c776Swyllys kmf_cert[n].kmf_private.flags =
115971593db2Swyllys KMF_FLAG_CERT_VALID;
1160f482c776Swyllys kmf_cert[n].kmf_private.label =
116171593db2Swyllys strdup(fullpath);
1162f482c776Swyllys n++;
116371593db2Swyllys }
1164f482c776Swyllys /* If maxcerts < loaded_certs, clean up */
1165f482c776Swyllys for (; i < loaded_certs; i++)
116630a5e8faSwyllys kmf_free_data(&certlist[i]);
1167f482c776Swyllys } else if (certlist != NULL) {
1168f482c776Swyllys for (i = 0; i < loaded_certs; i++)
116930a5e8faSwyllys kmf_free_data(&certlist[i]);
1170f482c776Swyllys n = loaded_certs;
1171f482c776Swyllys }
117230a5e8faSwyllys if (certlist != NULL)
117371593db2Swyllys free(certlist);
1174f482c776Swyllys *num_certs = n;
117599ebb4caSwyllys }
117699ebb4caSwyllys
117799ebb4caSwyllys free(fullpath);
117899ebb4caSwyllys
117999ebb4caSwyllys return (rv);
118099ebb4caSwyllys }
118199ebb4caSwyllys
118299ebb4caSwyllys void
OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,KMF_X509_DER_CERT * kmf_cert)11834942e222SAndy Fiddaman OpenSSL_FreeKMFCert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
118499ebb4caSwyllys {
118599ebb4caSwyllys if (kmf_cert != NULL) {
118699ebb4caSwyllys if (kmf_cert->certificate.Data != NULL) {
1187e65e5c2dSWyllys Ingersoll kmf_free_data(&kmf_cert->certificate);
118899ebb4caSwyllys }
118999ebb4caSwyllys if (kmf_cert->kmf_private.label)
119099ebb4caSwyllys free(kmf_cert->kmf_private.label);
119199ebb4caSwyllys }
119299ebb4caSwyllys }
119399ebb4caSwyllys
119499ebb4caSwyllys KMF_RETURN
OpenSSL_StoreCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)119530a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
119699ebb4caSwyllys {
119799ebb4caSwyllys KMF_RETURN ret = KMF_OK;
119830a5e8faSwyllys KMF_DATA *cert = NULL;
119930a5e8faSwyllys char *outfilename = NULL;
120030a5e8faSwyllys char *dirpath = NULL;
120130a5e8faSwyllys char *fullpath = NULL;
120299ebb4caSwyllys KMF_ENCODE_FORMAT format;
120399ebb4caSwyllys
120430a5e8faSwyllys /* Get the cert data */
120530a5e8faSwyllys cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
120630a5e8faSwyllys if (cert == NULL || cert->Data == NULL)
120799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
120899ebb4caSwyllys
120930a5e8faSwyllys /* Check the output filename and directory attributes. */
121030a5e8faSwyllys outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
121130a5e8faSwyllys numattr);
121230a5e8faSwyllys if (outfilename == NULL)
121330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
121499ebb4caSwyllys
121530a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
121630a5e8faSwyllys fullpath = get_fullpath(dirpath, outfilename);
121799ebb4caSwyllys if (fullpath == NULL)
121830a5e8faSwyllys return (KMF_ERR_BAD_CERTFILE);
121999ebb4caSwyllys
122030a5e8faSwyllys /* Check the optional format attribute */
122130a5e8faSwyllys ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
122230a5e8faSwyllys &format, NULL);
122330a5e8faSwyllys if (ret != KMF_OK) {
122430a5e8faSwyllys /* If there is no format attribute, then default to PEM */
122530a5e8faSwyllys format = KMF_FORMAT_PEM;
122699ebb4caSwyllys ret = KMF_OK;
122730a5e8faSwyllys } else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
122830a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
122999ebb4caSwyllys goto out;
123099ebb4caSwyllys }
123199ebb4caSwyllys
123230a5e8faSwyllys /* Store the certificate in the file with the specified format */
123330a5e8faSwyllys ret = kmf_create_cert_file(cert, format, fullpath);
123499ebb4caSwyllys
123599ebb4caSwyllys out:
123699ebb4caSwyllys if (fullpath != NULL)
123799ebb4caSwyllys free(fullpath);
123899ebb4caSwyllys
123999ebb4caSwyllys return (ret);
124099ebb4caSwyllys }
124199ebb4caSwyllys
124230a5e8faSwyllys
124399ebb4caSwyllys KMF_RETURN
OpenSSL_DeleteCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)124430a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
124599ebb4caSwyllys {
124699ebb4caSwyllys KMF_RETURN rv;
124799ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
12486b35cb3cSRichard PALO KMF_DATA certdata = { 0, NULL };
124930a5e8faSwyllys char *dirpath = NULL;
125030a5e8faSwyllys char *filename = NULL;
125130a5e8faSwyllys char *fullpath = NULL;
125230a5e8faSwyllys char *issuer = NULL;
125330a5e8faSwyllys char *subject = NULL;
125430a5e8faSwyllys KMF_BIGINT *serial = NULL;
125530a5e8faSwyllys KMF_CERT_VALIDITY validity;
125699ebb4caSwyllys
125730a5e8faSwyllys /*
125830a5e8faSwyllys * Get the DIRPATH and CERT_FILENAME attributes. They can not be
125930a5e8faSwyllys * NULL at the same time.
126030a5e8faSwyllys */
126130a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
126230a5e8faSwyllys filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
126330a5e8faSwyllys numattr);
126430a5e8faSwyllys fullpath = get_fullpath(dirpath, filename);
126599ebb4caSwyllys if (fullpath == NULL)
126699ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
126799ebb4caSwyllys
126830a5e8faSwyllys /* Get optional search criteria attributes */
126930a5e8faSwyllys issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
127030a5e8faSwyllys subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
127130a5e8faSwyllys serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
127230a5e8faSwyllys rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
127330a5e8faSwyllys &validity, NULL);
127430a5e8faSwyllys if (rv != KMF_OK) {
127530a5e8faSwyllys validity = KMF_ALL_CERTS;
127630a5e8faSwyllys rv = KMF_OK;
127730a5e8faSwyllys }
127830a5e8faSwyllys
127999ebb4caSwyllys if (isdir(fullpath)) {
128099ebb4caSwyllys DIR *dirp;
128199ebb4caSwyllys struct dirent *dp;
128299ebb4caSwyllys
128399ebb4caSwyllys /* open all files in the directory and attempt to read them */
128499ebb4caSwyllys if ((dirp = opendir(fullpath)) == NULL) {
128599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
128699ebb4caSwyllys }
128799ebb4caSwyllys
128899ebb4caSwyllys while ((dp = readdir(dirp)) != NULL) {
128999ebb4caSwyllys if (strcmp(dp->d_name, ".") != 0 &&
129099ebb4caSwyllys strcmp(dp->d_name, "..") != 0) {
129199ebb4caSwyllys char *fname;
129299ebb4caSwyllys
129399ebb4caSwyllys fname = get_fullpath(fullpath,
129499ebb4caSwyllys (char *)&dp->d_name);
129599ebb4caSwyllys
129699ebb4caSwyllys if (fname == NULL) {
129799ebb4caSwyllys rv = KMF_ERR_MEMORY;
129899ebb4caSwyllys break;
129999ebb4caSwyllys }
130099ebb4caSwyllys
130130a5e8faSwyllys rv = kmf_load_cert(kmfh, issuer, subject,
130230a5e8faSwyllys serial, validity, fname, &certdata);
130399ebb4caSwyllys
130499ebb4caSwyllys if (rv == KMF_ERR_CERT_NOT_FOUND) {
130599ebb4caSwyllys free(fname);
1306e65e5c2dSWyllys Ingersoll kmf_free_data(&certdata);
130799ebb4caSwyllys rv = KMF_OK;
130899ebb4caSwyllys continue;
130999ebb4caSwyllys } else if (rv != KMF_OK) {
131099ebb4caSwyllys free(fname);
131199ebb4caSwyllys break;
131299ebb4caSwyllys }
131399ebb4caSwyllys
131499ebb4caSwyllys if (unlink(fname) != 0) {
131599ebb4caSwyllys SET_SYS_ERROR(kmfh, errno);
131699ebb4caSwyllys rv = KMF_ERR_INTERNAL;
131799ebb4caSwyllys free(fname);
131899ebb4caSwyllys break;
131999ebb4caSwyllys }
132099ebb4caSwyllys free(fname);
1321e65e5c2dSWyllys Ingersoll kmf_free_data(&certdata);
132299ebb4caSwyllys }
132399ebb4caSwyllys }
132499ebb4caSwyllys (void) closedir(dirp);
132599ebb4caSwyllys } else {
132699ebb4caSwyllys /* Just try to load a single certificate */
132730a5e8faSwyllys rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
132830a5e8faSwyllys fullpath, &certdata);
132999ebb4caSwyllys if (rv == KMF_OK) {
133099ebb4caSwyllys if (unlink(fullpath) != 0) {
133199ebb4caSwyllys SET_SYS_ERROR(kmfh, errno);
133299ebb4caSwyllys rv = KMF_ERR_INTERNAL;
133399ebb4caSwyllys }
133499ebb4caSwyllys }
133599ebb4caSwyllys }
133699ebb4caSwyllys
133799ebb4caSwyllys out:
133899ebb4caSwyllys if (fullpath != NULL)
133999ebb4caSwyllys free(fullpath);
134099ebb4caSwyllys
1341e65e5c2dSWyllys Ingersoll kmf_free_data(&certdata);
134299ebb4caSwyllys
134399ebb4caSwyllys return (rv);
134499ebb4caSwyllys }
134599ebb4caSwyllys
134699ebb4caSwyllys KMF_RETURN
OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle,KMF_KEY_HANDLE * key,KMF_DATA * keydata)134799ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
134899ebb4caSwyllys KMF_DATA *keydata)
134999ebb4caSwyllys {
135099ebb4caSwyllys KMF_RETURN rv = KMF_OK;
135199ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
135299ebb4caSwyllys int n;
135399ebb4caSwyllys
135499ebb4caSwyllys if (key == NULL || keydata == NULL ||
135599ebb4caSwyllys key->keyp == NULL)
135699ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
135799ebb4caSwyllys
135899ebb4caSwyllys if (key->keyalg == KMF_RSA) {
135999ebb4caSwyllys RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
136099ebb4caSwyllys
136199ebb4caSwyllys if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
136299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
136399ebb4caSwyllys return (KMF_ERR_ENCODING);
136499ebb4caSwyllys }
136599ebb4caSwyllys RSA_free(pubkey);
136699ebb4caSwyllys } else if (key->keyalg == KMF_DSA) {
136799ebb4caSwyllys DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
136899ebb4caSwyllys
136999ebb4caSwyllys if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
137099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
137199ebb4caSwyllys return (KMF_ERR_ENCODING);
137299ebb4caSwyllys }
137399ebb4caSwyllys DSA_free(pubkey);
137499ebb4caSwyllys } else {
137599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
137699ebb4caSwyllys }
137799ebb4caSwyllys keydata->Length = n;
137899ebb4caSwyllys
137999ebb4caSwyllys cleanup:
138099ebb4caSwyllys if (rv != KMF_OK) {
138199ebb4caSwyllys if (keydata->Data)
138299ebb4caSwyllys free(keydata->Data);
138399ebb4caSwyllys keydata->Data = NULL;
138499ebb4caSwyllys keydata->Length = 0;
138599ebb4caSwyllys }
138699ebb4caSwyllys
138799ebb4caSwyllys return (rv);
138899ebb4caSwyllys }
138999ebb4caSwyllys
139099ebb4caSwyllys static KMF_RETURN
ssl_write_key(KMF_HANDLE * kmfh,KMF_ENCODE_FORMAT format,BIO * out,KMF_CREDENTIAL * cred,EVP_PKEY * pkey,boolean_t private)139130a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
139230a5e8faSwyllys KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
139399ebb4caSwyllys {
139499ebb4caSwyllys int rv = 0;
1395*6ff4183cSAndy Fiddaman #if OPENSSL_VERSION_NUMBER >= 0x30000000L
1396*6ff4183cSAndy Fiddaman const RSA *rsa;
1397*6ff4183cSAndy Fiddaman const DSA *dsa;
1398*6ff4183cSAndy Fiddaman #else
139999ebb4caSwyllys RSA *rsa;
140099ebb4caSwyllys DSA *dsa;
1401*6ff4183cSAndy Fiddaman #endif
140299ebb4caSwyllys
14035b3e1433Swyllys if (pkey == NULL || out == NULL)
14045b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER);
14055b3e1433Swyllys
140699ebb4caSwyllys switch (format) {
140773cc0e02Swyllys case KMF_FORMAT_RAWKEY:
140873cc0e02Swyllys /* same as ASN.1 */
140999ebb4caSwyllys case KMF_FORMAT_ASN1:
1410300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
141130a5e8faSwyllys if (private)
141299ebb4caSwyllys rv = i2d_RSAPrivateKey_bio(out, rsa);
141330a5e8faSwyllys else
141430a5e8faSwyllys rv = i2d_RSAPublicKey_bio(out, rsa);
1415300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
141699ebb4caSwyllys rv = i2d_DSAPrivateKey_bio(out, dsa);
141799ebb4caSwyllys }
141899ebb4caSwyllys if (rv == 1) {
141999ebb4caSwyllys rv = KMF_OK;
142099ebb4caSwyllys } else {
142199ebb4caSwyllys SET_ERROR(kmfh, rv);
142299ebb4caSwyllys }
142399ebb4caSwyllys break;
142499ebb4caSwyllys case KMF_FORMAT_PEM:
1425300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
142630a5e8faSwyllys if (private)
142799ebb4caSwyllys rv = PEM_write_bio_RSAPrivateKey(out,
142830a5e8faSwyllys rsa, NULL, NULL, 0, NULL,
142930a5e8faSwyllys (cred != NULL ? cred->cred : NULL));
143030a5e8faSwyllys else
143130a5e8faSwyllys rv = PEM_write_bio_RSAPublicKey(out,
143230a5e8faSwyllys rsa);
1433300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
143499ebb4caSwyllys rv = PEM_write_bio_DSAPrivateKey(out,
143530a5e8faSwyllys dsa, NULL, NULL, 0, NULL,
143630a5e8faSwyllys (cred != NULL ? cred->cred : NULL));
143799ebb4caSwyllys }
143899ebb4caSwyllys
143999ebb4caSwyllys if (rv == 1) {
144099ebb4caSwyllys rv = KMF_OK;
144199ebb4caSwyllys } else {
144299ebb4caSwyllys SET_ERROR(kmfh, rv);
144399ebb4caSwyllys }
144499ebb4caSwyllys break;
144599ebb4caSwyllys
144699ebb4caSwyllys default:
144799ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER;
144899ebb4caSwyllys }
144999ebb4caSwyllys
145099ebb4caSwyllys return (rv);
145199ebb4caSwyllys }
145299ebb4caSwyllys
145399ebb4caSwyllys KMF_RETURN
OpenSSL_CreateKeypair(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)14544942e222SAndy Fiddaman OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
145599ebb4caSwyllys {
145699ebb4caSwyllys KMF_RETURN rv = KMF_OK;
145799ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1458300fdee2SAndy Fiddaman uint32_t eValue = RSA_F4;
1459300fdee2SAndy Fiddaman BIGNUM *eValue_bn = NULL;
146099ebb4caSwyllys RSA *sslPrivKey = NULL;
146199ebb4caSwyllys DSA *sslDSAKey = NULL;
146299ebb4caSwyllys EVP_PKEY *eprikey = NULL;
146399ebb4caSwyllys EVP_PKEY *epubkey = NULL;
146499ebb4caSwyllys BIO *out = NULL;
146530a5e8faSwyllys KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
146630a5e8faSwyllys uint32_t keylen = 1024;
146730a5e8faSwyllys uint32_t keylen_size = sizeof (uint32_t);
146830a5e8faSwyllys boolean_t storekey = TRUE;
146930a5e8faSwyllys KMF_KEY_ALG keytype = KMF_RSA;
147099ebb4caSwyllys
1471300fdee2SAndy Fiddaman eValue_bn = BN_new();
1472300fdee2SAndy Fiddaman if (eValue_bn == NULL)
1473300fdee2SAndy Fiddaman return (KMF_ERR_MEMORY);
1474300fdee2SAndy Fiddaman if (BN_set_word(eValue_bn, eValue) == 0) {
1475300fdee2SAndy Fiddaman rv = KMF_ERR_KEYGEN_FAILED;
1476300fdee2SAndy Fiddaman goto cleanup;
1477300fdee2SAndy Fiddaman }
1478300fdee2SAndy Fiddaman
147930a5e8faSwyllys rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
148030a5e8faSwyllys &storekey, NULL);
148130a5e8faSwyllys if (rv != KMF_OK) {
148230a5e8faSwyllys /* "storekey" is optional. Default is TRUE */
148330a5e8faSwyllys rv = KMF_OK;
148499ebb4caSwyllys }
148599ebb4caSwyllys
148630a5e8faSwyllys rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
148730a5e8faSwyllys (void *)&keytype, NULL);
148830a5e8faSwyllys if (rv != KMF_OK)
148930a5e8faSwyllys /* keytype is optional. KMF_RSA is default */
149030a5e8faSwyllys rv = KMF_OK;
149199ebb4caSwyllys
149230a5e8faSwyllys pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
1493300fdee2SAndy Fiddaman if (pubkey == NULL) {
1494300fdee2SAndy Fiddaman rv = KMF_ERR_BAD_PARAMETER;
1495300fdee2SAndy Fiddaman goto cleanup;
1496300fdee2SAndy Fiddaman }
149799ebb4caSwyllys
149830a5e8faSwyllys privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
1499300fdee2SAndy Fiddaman if (privkey == NULL) {
1500300fdee2SAndy Fiddaman rv = KMF_ERR_BAD_PARAMETER;
1501300fdee2SAndy Fiddaman goto cleanup;
1502300fdee2SAndy Fiddaman }
150330a5e8faSwyllys
150430a5e8faSwyllys (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
150530a5e8faSwyllys (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
150699ebb4caSwyllys
150799ebb4caSwyllys eprikey = EVP_PKEY_new();
150899ebb4caSwyllys if (eprikey == NULL) {
150999ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
151099ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED;
151199ebb4caSwyllys goto cleanup;
151299ebb4caSwyllys }
151399ebb4caSwyllys epubkey = EVP_PKEY_new();
151499ebb4caSwyllys if (epubkey == NULL) {
151599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
151699ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED;
151799ebb4caSwyllys goto cleanup;
151899ebb4caSwyllys }
151930a5e8faSwyllys if (keytype == KMF_RSA) {
152030a5e8faSwyllys KMF_BIGINT *rsaexp = NULL;
152199ebb4caSwyllys
152230a5e8faSwyllys rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
152330a5e8faSwyllys if (rsaexp != NULL) {
152430a5e8faSwyllys if (rsaexp->len > 0 &&
152530a5e8faSwyllys rsaexp->len <= sizeof (eValue) &&
152630a5e8faSwyllys rsaexp->val != NULL) {
152730a5e8faSwyllys eValue = *(uint32_t *)rsaexp->val;
1528300fdee2SAndy Fiddaman if (BN_set_word(eValue_bn, eValue) == 0) {
1529300fdee2SAndy Fiddaman rv = KMF_ERR_BAD_PARAMETER;
1530300fdee2SAndy Fiddaman goto cleanup;
1531300fdee2SAndy Fiddaman }
153230a5e8faSwyllys } else {
153330a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER;
153430a5e8faSwyllys goto cleanup;
153530a5e8faSwyllys }
153630a5e8faSwyllys } else {
153730a5e8faSwyllys /* RSA Exponent is optional. Default is 0x10001 */
153830a5e8faSwyllys rv = KMF_OK;
153930a5e8faSwyllys }
154030a5e8faSwyllys
154130a5e8faSwyllys rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
154230a5e8faSwyllys &keylen, &keylen_size);
154330a5e8faSwyllys if (rv == KMF_ERR_ATTR_NOT_FOUND)
154430a5e8faSwyllys /* keylen is optional, default is 1024 */
154530a5e8faSwyllys rv = KMF_OK;
154630a5e8faSwyllys if (rv != KMF_OK) {
154730a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER;
154830a5e8faSwyllys goto cleanup;
154930a5e8faSwyllys }
155030a5e8faSwyllys
1551300fdee2SAndy Fiddaman sslPrivKey = RSA_new();
1552300fdee2SAndy Fiddaman if (sslPrivKey == NULL ||
1553300fdee2SAndy Fiddaman RSA_generate_key_ex(sslPrivKey, keylen, eValue_bn, NULL)
1554300fdee2SAndy Fiddaman == 0) {
155599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
155699ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED;
155799ebb4caSwyllys } else {
155830a5e8faSwyllys (void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
155999ebb4caSwyllys privkey->kstype = KMF_KEYSTORE_OPENSSL;
156099ebb4caSwyllys privkey->keyalg = KMF_RSA;
156199ebb4caSwyllys privkey->keyclass = KMF_ASYM_PRI;
156299ebb4caSwyllys privkey->israw = FALSE;
156399ebb4caSwyllys privkey->keyp = (void *)eprikey;
156430a5e8faSwyllys
156599ebb4caSwyllys /* OpenSSL derives the public key from the private */
156630a5e8faSwyllys (void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
156799ebb4caSwyllys pubkey->kstype = KMF_KEYSTORE_OPENSSL;
156899ebb4caSwyllys pubkey->keyalg = KMF_RSA;
156999ebb4caSwyllys pubkey->israw = FALSE;
157099ebb4caSwyllys pubkey->keyclass = KMF_ASYM_PUB;
157199ebb4caSwyllys pubkey->keyp = (void *)epubkey;
157299ebb4caSwyllys }
157330a5e8faSwyllys } else if (keytype == KMF_DSA) {
1574300fdee2SAndy Fiddaman BIGNUM *p, *q, *g;
1575300fdee2SAndy Fiddaman
157699ebb4caSwyllys sslDSAKey = DSA_new();
157799ebb4caSwyllys if (sslDSAKey == NULL) {
157899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
157999ebb4caSwyllys return (KMF_ERR_MEMORY);
158099ebb4caSwyllys }
158199ebb4caSwyllys
1582300fdee2SAndy Fiddaman p = BN_bin2bn(P, sizeof (P), NULL);
1583300fdee2SAndy Fiddaman q = BN_bin2bn(Q, sizeof (Q), NULL);
1584300fdee2SAndy Fiddaman g = BN_bin2bn(G, sizeof (G), NULL);
1585300fdee2SAndy Fiddaman if (p == NULL || q == NULL || g == NULL) {
1586300fdee2SAndy Fiddaman BN_free(p);
1587300fdee2SAndy Fiddaman BN_free(q);
1588300fdee2SAndy Fiddaman BN_free(g);
158999ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
159099ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED;
159199ebb4caSwyllys goto cleanup;
159299ebb4caSwyllys }
1593300fdee2SAndy Fiddaman
1594300fdee2SAndy Fiddaman if (DSA_set0_pqg(sslDSAKey, p, q, g) == 0) {
159599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
159699ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED;
159799ebb4caSwyllys goto cleanup;
159899ebb4caSwyllys }
159999ebb4caSwyllys
160099ebb4caSwyllys if (!DSA_generate_key(sslDSAKey)) {
160199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
160299ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED;
160399ebb4caSwyllys goto cleanup;
160499ebb4caSwyllys }
160599ebb4caSwyllys
160699ebb4caSwyllys privkey->kstype = KMF_KEYSTORE_OPENSSL;
160799ebb4caSwyllys privkey->keyalg = KMF_DSA;
160899ebb4caSwyllys privkey->keyclass = KMF_ASYM_PRI;
160999ebb4caSwyllys privkey->israw = FALSE;
161099ebb4caSwyllys if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
161199ebb4caSwyllys privkey->keyp = (void *)eprikey;
161299ebb4caSwyllys } else {
161399ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
161499ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED;
161599ebb4caSwyllys goto cleanup;
161699ebb4caSwyllys }
161799ebb4caSwyllys
161899ebb4caSwyllys pubkey->kstype = KMF_KEYSTORE_OPENSSL;
161999ebb4caSwyllys pubkey->keyalg = KMF_DSA;
162099ebb4caSwyllys pubkey->keyclass = KMF_ASYM_PUB;
162199ebb4caSwyllys pubkey->israw = FALSE;
162299ebb4caSwyllys
162399ebb4caSwyllys if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
162499ebb4caSwyllys pubkey->keyp = (void *)epubkey;
162599ebb4caSwyllys } else {
162699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
162799ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED;
162899ebb4caSwyllys goto cleanup;
162999ebb4caSwyllys }
163099ebb4caSwyllys }
163199ebb4caSwyllys
163299ebb4caSwyllys if (rv != KMF_OK) {
163399ebb4caSwyllys goto cleanup;
163499ebb4caSwyllys }
163599ebb4caSwyllys
163630a5e8faSwyllys if (storekey) {
163730a5e8faSwyllys KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
163830a5e8faSwyllys int i = 0;
163930a5e8faSwyllys char *keyfile = NULL, *dirpath = NULL;
164030a5e8faSwyllys KMF_ENCODE_FORMAT format;
164130a5e8faSwyllys /*
164230a5e8faSwyllys * Construct a new attribute arrray and call openssl_store_key
164330a5e8faSwyllys */
164430a5e8faSwyllys kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
164530a5e8faSwyllys privkey, sizeof (privkey));
164630a5e8faSwyllys i++;
164730a5e8faSwyllys
164830a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
164930a5e8faSwyllys if (dirpath != NULL) {
165030a5e8faSwyllys storeattrs[i].type = KMF_DIRPATH_ATTR;
165130a5e8faSwyllys storeattrs[i].pValue = dirpath;
165230a5e8faSwyllys storeattrs[i].valueLen = strlen(dirpath);
165330a5e8faSwyllys i++;
165430a5e8faSwyllys } else {
165530a5e8faSwyllys rv = KMF_OK; /* DIRPATH is optional */
165699ebb4caSwyllys }
165730a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
165830a5e8faSwyllys attrlist, numattr);
165930a5e8faSwyllys if (keyfile != NULL) {
166030a5e8faSwyllys storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
166130a5e8faSwyllys storeattrs[i].pValue = keyfile;
166230a5e8faSwyllys storeattrs[i].valueLen = strlen(keyfile);
166330a5e8faSwyllys i++;
166430a5e8faSwyllys } else {
166530a5e8faSwyllys goto cleanup; /* KEYFILE is required */
166630a5e8faSwyllys }
166730a5e8faSwyllys rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
166830a5e8faSwyllys (void *)&format, NULL);
166930a5e8faSwyllys if (rv == KMF_OK) {
167030a5e8faSwyllys storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
167130a5e8faSwyllys storeattrs[i].pValue = &format;
167230a5e8faSwyllys storeattrs[i].valueLen = sizeof (format);
167330a5e8faSwyllys i++;
167430a5e8faSwyllys }
167530a5e8faSwyllys
167630a5e8faSwyllys rv = OpenSSL_StoreKey(handle, i, storeattrs);
167730a5e8faSwyllys }
167899ebb4caSwyllys
167999ebb4caSwyllys cleanup:
1680300fdee2SAndy Fiddaman if (eValue_bn != NULL)
1681300fdee2SAndy Fiddaman BN_free(eValue_bn);
1682300fdee2SAndy Fiddaman
168399ebb4caSwyllys if (rv != KMF_OK) {
168499ebb4caSwyllys if (eprikey != NULL)
168599ebb4caSwyllys EVP_PKEY_free(eprikey);
168699ebb4caSwyllys
168799ebb4caSwyllys if (epubkey != NULL)
168899ebb4caSwyllys EVP_PKEY_free(epubkey);
168999ebb4caSwyllys
169099ebb4caSwyllys if (pubkey->keylabel) {
169199ebb4caSwyllys free(pubkey->keylabel);
169299ebb4caSwyllys pubkey->keylabel = NULL;
169399ebb4caSwyllys }
169499ebb4caSwyllys
169599ebb4caSwyllys if (privkey->keylabel) {
169699ebb4caSwyllys free(privkey->keylabel);
169799ebb4caSwyllys privkey->keylabel = NULL;
169899ebb4caSwyllys }
169999ebb4caSwyllys
170099ebb4caSwyllys pubkey->keyp = NULL;
170199ebb4caSwyllys privkey->keyp = NULL;
170299ebb4caSwyllys }
170399ebb4caSwyllys
170499ebb4caSwyllys if (sslPrivKey)
170599ebb4caSwyllys RSA_free(sslPrivKey);
170699ebb4caSwyllys
170799ebb4caSwyllys if (sslDSAKey)
170899ebb4caSwyllys DSA_free(sslDSAKey);
170999ebb4caSwyllys
171099ebb4caSwyllys if (out != NULL)
171199ebb4caSwyllys (void) BIO_free(out);
171299ebb4caSwyllys
171399ebb4caSwyllys return (rv);
171499ebb4caSwyllys }
171599ebb4caSwyllys
1716e65e5c2dSWyllys Ingersoll /*
1717e65e5c2dSWyllys Ingersoll * Make sure the BN conversion is properly padded with 0x00
1718e65e5c2dSWyllys Ingersoll * bytes. If not, signature verification for DSA signatures
1719e65e5c2dSWyllys Ingersoll * may fail in the case where the bignum value does not use
1720e65e5c2dSWyllys Ingersoll * all of the bits.
1721e65e5c2dSWyllys Ingersoll */
1722e65e5c2dSWyllys Ingersoll static int
fixbnlen(const BIGNUM * bn,unsigned char * buf,int len)17234942e222SAndy Fiddaman fixbnlen(const BIGNUM *bn, unsigned char *buf, int len)
17244942e222SAndy Fiddaman {
1725e65e5c2dSWyllys Ingersoll int bytes = len - BN_num_bytes(bn);
17262c9a247fSWyllys Ingersoll
17272c9a247fSWyllys Ingersoll /* prepend with leading 0x00 if necessary */
1728e65e5c2dSWyllys Ingersoll while (bytes-- > 0)
1729e65e5c2dSWyllys Ingersoll *buf++ = 0;
1730e65e5c2dSWyllys Ingersoll
17312c9a247fSWyllys Ingersoll (void) BN_bn2bin(bn, buf);
17322c9a247fSWyllys Ingersoll /*
17332c9a247fSWyllys Ingersoll * Return the desired length since we prepended it
17342c9a247fSWyllys Ingersoll * with the necessary 0x00 padding.
17352c9a247fSWyllys Ingersoll */
17362c9a247fSWyllys Ingersoll return (len);
1737e65e5c2dSWyllys Ingersoll }
1738e65e5c2dSWyllys Ingersoll
173999ebb4caSwyllys KMF_RETURN
OpenSSL_SignData(KMF_HANDLE_T handle,KMF_KEY_HANDLE * key,KMF_OID * AlgOID,KMF_DATA * tobesigned,KMF_DATA * output)174099ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
174199ebb4caSwyllys KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
174299ebb4caSwyllys {
174399ebb4caSwyllys KMF_RETURN ret = KMF_OK;
174499ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
174599ebb4caSwyllys KMF_ALGORITHM_INDEX AlgId;
1746300fdee2SAndy Fiddaman EVP_MD_CTX *ctx;
174799ebb4caSwyllys const EVP_MD *md;
174802744e81Swyllys
174999ebb4caSwyllys if (key == NULL || AlgOID == NULL ||
175099ebb4caSwyllys tobesigned == NULL || output == NULL ||
175199ebb4caSwyllys tobesigned->Data == NULL ||
175299ebb4caSwyllys output->Data == NULL)
175399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
175499ebb4caSwyllys
175599ebb4caSwyllys /* Map the OID to an OpenSSL algorithm */
175630a5e8faSwyllys AlgId = x509_algoid_to_algid(AlgOID);
175799ebb4caSwyllys if (AlgId == KMF_ALGID_NONE)
1758e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM);
175999ebb4caSwyllys
176099ebb4caSwyllys if (key->keyalg == KMF_RSA) {
176199ebb4caSwyllys EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
176299ebb4caSwyllys uchar_t *p;
176302744e81Swyllys int len;
1764553e44ceSAndrew Stormont switch (AlgId) {
1765553e44ceSAndrew Stormont #ifndef OPENSSL_NO_MD5
1766553e44ceSAndrew Stormont case KMF_ALGID_MD5WithRSA:
176799ebb4caSwyllys md = EVP_md5();
1768553e44ceSAndrew Stormont break;
1769553e44ceSAndrew Stormont #endif
1770553e44ceSAndrew Stormont #ifndef OPENSSL_NO_SHA
1771553e44ceSAndrew Stormont case KMF_ALGID_SHA1WithRSA:
177299ebb4caSwyllys md = EVP_sha1();
1773553e44ceSAndrew Stormont break;
1774553e44ceSAndrew Stormont #endif
1775553e44ceSAndrew Stormont #ifndef OPENSSL_NO_SHA256
1776553e44ceSAndrew Stormont case KMF_ALGID_SHA256WithRSA:
1777e65e5c2dSWyllys Ingersoll md = EVP_sha256();
1778553e44ceSAndrew Stormont break;
1779553e44ceSAndrew Stormont #endif
1780553e44ceSAndrew Stormont #ifndef OPENSSL_NO_SHA512
1781553e44ceSAndrew Stormont case KMF_ALGID_SHA384WithRSA:
1782e65e5c2dSWyllys Ingersoll md = EVP_sha384();
1783553e44ceSAndrew Stormont break;
1784553e44ceSAndrew Stormont case KMF_ALGID_SHA512WithRSA:
1785e65e5c2dSWyllys Ingersoll md = EVP_sha512();
1786553e44ceSAndrew Stormont break;
1787553e44ceSAndrew Stormont #endif
1788553e44ceSAndrew Stormont case KMF_ALGID_RSA:
178902744e81Swyllys md = NULL;
1790553e44ceSAndrew Stormont break;
1791553e44ceSAndrew Stormont default:
1792e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM);
1793553e44ceSAndrew Stormont }
179499ebb4caSwyllys
179502744e81Swyllys if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
179602744e81Swyllys RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
179799ebb4caSwyllys
179802744e81Swyllys p = output->Data;
179902744e81Swyllys if ((len = RSA_private_encrypt(tobesigned->Length,
180002744e81Swyllys tobesigned->Data, p, rsa,
180102744e81Swyllys RSA_PKCS1_PADDING)) <= 0) {
180202744e81Swyllys SET_ERROR(kmfh, ERR_get_error());
180302744e81Swyllys ret = KMF_ERR_INTERNAL;
180402744e81Swyllys }
180502744e81Swyllys output->Length = len;
180602744e81Swyllys } else {
1807300fdee2SAndy Fiddaman if ((ctx = EVP_MD_CTX_new()) == NULL)
1808300fdee2SAndy Fiddaman return (KMF_ERR_MEMORY);
1809300fdee2SAndy Fiddaman (void) EVP_SignInit_ex(ctx, md, NULL);
1810300fdee2SAndy Fiddaman (void) EVP_SignUpdate(ctx, tobesigned->Data,
181199ebb4caSwyllys (uint32_t)tobesigned->Length);
181299ebb4caSwyllys len = (uint32_t)output->Length;
181399ebb4caSwyllys p = output->Data;
1814300fdee2SAndy Fiddaman if (!EVP_SignFinal(ctx, p, (uint32_t *)&len, pkey)) {
181599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
181602744e81Swyllys len = 0;
181702744e81Swyllys ret = KMF_ERR_INTERNAL;
181899ebb4caSwyllys }
181999ebb4caSwyllys output->Length = len;
1820300fdee2SAndy Fiddaman EVP_MD_CTX_free(ctx);
182102744e81Swyllys }
182299ebb4caSwyllys } else if (key->keyalg == KMF_DSA) {
182399ebb4caSwyllys DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
182499ebb4caSwyllys
182599ebb4caSwyllys uchar_t hash[EVP_MAX_MD_SIZE];
182699ebb4caSwyllys uint32_t hashlen;
182799ebb4caSwyllys DSA_SIG *dsasig;
182899ebb4caSwyllys
1829e65e5c2dSWyllys Ingersoll if (AlgId == KMF_ALGID_DSA ||
1830e65e5c2dSWyllys Ingersoll AlgId == KMF_ALGID_SHA1WithDSA)
1831e65e5c2dSWyllys Ingersoll md = EVP_sha1();
1832e65e5c2dSWyllys Ingersoll else if (AlgId == KMF_ALGID_SHA256WithDSA)
1833e65e5c2dSWyllys Ingersoll md = EVP_sha256();
1834e65e5c2dSWyllys Ingersoll else /* Bad algorithm */
1835e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM);
1836e65e5c2dSWyllys Ingersoll
183799ebb4caSwyllys /*
183899ebb4caSwyllys * OpenSSL EVP_Sign operation automatically converts to
183999ebb4caSwyllys * ASN.1 output so we do the operations separately so we
184099ebb4caSwyllys * are assured of NOT getting ASN.1 output returned.
184199ebb4caSwyllys * KMF does not want ASN.1 encoded results because
184299ebb4caSwyllys * not all mechanisms return ASN.1 encodings (PKCS#11
184399ebb4caSwyllys * and NSS return raw signature data).
184499ebb4caSwyllys */
1845300fdee2SAndy Fiddaman if ((ctx = EVP_MD_CTX_new()) == NULL)
1846300fdee2SAndy Fiddaman return (KMF_ERR_MEMORY);
1847300fdee2SAndy Fiddaman (void) EVP_DigestInit_ex(ctx, md, NULL);
1848300fdee2SAndy Fiddaman (void) EVP_DigestUpdate(ctx, tobesigned->Data,
184999ebb4caSwyllys tobesigned->Length);
1850300fdee2SAndy Fiddaman (void) EVP_DigestFinal_ex(ctx, hash, &hashlen);
185199ebb4caSwyllys
1852e65e5c2dSWyllys Ingersoll /* Only sign first 20 bytes for SHA2 */
1853e65e5c2dSWyllys Ingersoll if (AlgId == KMF_ALGID_SHA256WithDSA)
1854e65e5c2dSWyllys Ingersoll hashlen = 20;
185599ebb4caSwyllys dsasig = DSA_do_sign(hash, hashlen, dsa);
185699ebb4caSwyllys if (dsasig != NULL) {
185799ebb4caSwyllys int i;
1858300fdee2SAndy Fiddaman const BIGNUM *r, *s;
1859300fdee2SAndy Fiddaman
1860300fdee2SAndy Fiddaman DSA_SIG_get0(dsasig, &r, &s);
1861300fdee2SAndy Fiddaman output->Length = i = fixbnlen(r, output->Data,
1862e65e5c2dSWyllys Ingersoll hashlen);
18632c9a247fSWyllys Ingersoll
1864300fdee2SAndy Fiddaman output->Length += fixbnlen(s, &output->Data[i],
1865e65e5c2dSWyllys Ingersoll hashlen);
18662c9a247fSWyllys Ingersoll
186799ebb4caSwyllys DSA_SIG_free(dsasig);
186899ebb4caSwyllys } else {
186999ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
187099ebb4caSwyllys }
1871300fdee2SAndy Fiddaman EVP_MD_CTX_free(ctx);
187299ebb4caSwyllys } else {
187399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
187499ebb4caSwyllys }
187599ebb4caSwyllys cleanup:
187699ebb4caSwyllys return (ret);
187799ebb4caSwyllys }
187899ebb4caSwyllys
187999ebb4caSwyllys KMF_RETURN
OpenSSL_DeleteKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)18804942e222SAndy Fiddaman OpenSSL_DeleteKey(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
188199ebb4caSwyllys {
188299ebb4caSwyllys KMF_RETURN rv = KMF_OK;
188330a5e8faSwyllys KMF_KEY_HANDLE *key;
188430a5e8faSwyllys boolean_t destroy = B_TRUE;
188530a5e8faSwyllys
188630a5e8faSwyllys key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
188799ebb4caSwyllys if (key == NULL || key->keyp == NULL)
188899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
188999ebb4caSwyllys
189030a5e8faSwyllys rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
189130a5e8faSwyllys (void *)&destroy, NULL);
189230a5e8faSwyllys if (rv != KMF_OK) {
189330a5e8faSwyllys /* "destroy" is optional. Default is TRUE */
189430a5e8faSwyllys rv = KMF_OK;
189530a5e8faSwyllys }
189630a5e8faSwyllys
189799ebb4caSwyllys if (key->keyclass != KMF_ASYM_PUB &&
189899ebb4caSwyllys key->keyclass != KMF_ASYM_PRI &&
189999ebb4caSwyllys key->keyclass != KMF_SYMMETRIC)
190099ebb4caSwyllys return (KMF_ERR_BAD_KEY_CLASS);
190199ebb4caSwyllys
190299ebb4caSwyllys if (key->keyclass == KMF_SYMMETRIC) {
190330a5e8faSwyllys kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
190499ebb4caSwyllys key->keyp = NULL;
190599ebb4caSwyllys } else {
190699ebb4caSwyllys if (key->keyp != NULL) {
190799ebb4caSwyllys EVP_PKEY_free(key->keyp);
190899ebb4caSwyllys key->keyp = NULL;
190999ebb4caSwyllys }
191099ebb4caSwyllys }
191199ebb4caSwyllys
191299ebb4caSwyllys if (key->keylabel != NULL) {
191399ebb4caSwyllys EVP_PKEY *pkey = NULL;
191499ebb4caSwyllys /* If the file exists, make sure it is a proper key. */
191599ebb4caSwyllys pkey = openssl_load_key(handle, key->keylabel);
191699ebb4caSwyllys if (pkey == NULL) {
19175b3e1433Swyllys if (key->keylabel != NULL) {
191899ebb4caSwyllys free(key->keylabel);
191999ebb4caSwyllys key->keylabel = NULL;
19205b3e1433Swyllys }
192199ebb4caSwyllys return (KMF_ERR_KEY_NOT_FOUND);
192299ebb4caSwyllys }
192399ebb4caSwyllys EVP_PKEY_free(pkey);
192499ebb4caSwyllys
192599ebb4caSwyllys if (destroy) {
192699ebb4caSwyllys if (unlink(key->keylabel) != 0) {
192799ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
192899ebb4caSwyllys SET_SYS_ERROR(kmfh, errno);
192999ebb4caSwyllys rv = KMF_ERR_INTERNAL;
193099ebb4caSwyllys }
193199ebb4caSwyllys }
193299ebb4caSwyllys if (key->keylabel != NULL) {
193399ebb4caSwyllys free(key->keylabel);
193499ebb4caSwyllys key->keylabel = NULL;
193599ebb4caSwyllys }
193699ebb4caSwyllys }
193799ebb4caSwyllys return (rv);
193899ebb4caSwyllys }
193999ebb4caSwyllys
194099ebb4caSwyllys KMF_RETURN
OpenSSL_GetErrorString(KMF_HANDLE_T handle,char ** msgstr)194199ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
194299ebb4caSwyllys {
194399ebb4caSwyllys KMF_RETURN ret = KMF_OK;
194499ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
194599ebb4caSwyllys char str[256]; /* OpenSSL needs at least 120 byte buffer */
194699ebb4caSwyllys
194799ebb4caSwyllys ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
194899ebb4caSwyllys if (strlen(str)) {
194999ebb4caSwyllys *msgstr = (char *)strdup(str);
195099ebb4caSwyllys if ((*msgstr) == NULL)
195199ebb4caSwyllys ret = KMF_ERR_MEMORY;
195299ebb4caSwyllys } else {
195399ebb4caSwyllys *msgstr = NULL;
195499ebb4caSwyllys }
195599ebb4caSwyllys
195699ebb4caSwyllys return (ret);
195799ebb4caSwyllys }
195899ebb4caSwyllys
195999ebb4caSwyllys static int
ext2NID(int kmfext)196099ebb4caSwyllys ext2NID(int kmfext)
196199ebb4caSwyllys {
196299ebb4caSwyllys switch (kmfext) {
196399ebb4caSwyllys case KMF_X509_EXT_KEY_USAGE:
196499ebb4caSwyllys return (NID_key_usage);
196599ebb4caSwyllys case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
196699ebb4caSwyllys return (NID_private_key_usage_period);
196799ebb4caSwyllys case KMF_X509_EXT_CERT_POLICIES:
196899ebb4caSwyllys return (NID_certificate_policies);
196999ebb4caSwyllys case KMF_X509_EXT_SUBJ_ALTNAME:
197099ebb4caSwyllys return (NID_subject_alt_name);
197199ebb4caSwyllys case KMF_X509_EXT_ISSUER_ALTNAME:
197299ebb4caSwyllys return (NID_issuer_alt_name);
197399ebb4caSwyllys case KMF_X509_EXT_BASIC_CONSTRAINTS:
197499ebb4caSwyllys return (NID_basic_constraints);
197599ebb4caSwyllys case KMF_X509_EXT_EXT_KEY_USAGE:
197699ebb4caSwyllys return (NID_ext_key_usage);
197799ebb4caSwyllys case KMF_X509_EXT_AUTH_KEY_ID:
197899ebb4caSwyllys return (NID_authority_key_identifier);
197999ebb4caSwyllys case KMF_X509_EXT_CRL_DIST_POINTS:
198099ebb4caSwyllys return (NID_crl_distribution_points);
198199ebb4caSwyllys case KMF_X509_EXT_SUBJ_KEY_ID:
198299ebb4caSwyllys return (NID_subject_key_identifier);
198399ebb4caSwyllys case KMF_X509_EXT_POLICY_MAPPINGS:
198499ebb4caSwyllys return (OBJ_sn2nid("policyMappings"));
198599ebb4caSwyllys case KMF_X509_EXT_NAME_CONSTRAINTS:
198699ebb4caSwyllys return (OBJ_sn2nid("nameConstraints"));
198799ebb4caSwyllys case KMF_X509_EXT_POLICY_CONSTRAINTS:
198899ebb4caSwyllys return (OBJ_sn2nid("policyConstraints"));
198999ebb4caSwyllys case KMF_X509_EXT_INHIBIT_ANY_POLICY:
199099ebb4caSwyllys return (OBJ_sn2nid("inhibitAnyPolicy"));
199199ebb4caSwyllys case KMF_X509_EXT_FRESHEST_CRL:
199299ebb4caSwyllys return (OBJ_sn2nid("freshestCRL"));
199399ebb4caSwyllys default:
199499ebb4caSwyllys return (NID_undef);
199599ebb4caSwyllys }
199699ebb4caSwyllys }
199799ebb4caSwyllys
199899ebb4caSwyllys KMF_RETURN
OpenSSL_CertGetPrintable(KMF_HANDLE_T handle,const KMF_DATA * pcert,KMF_PRINTABLE_ITEM flag,char * resultStr)199999ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
200099ebb4caSwyllys KMF_PRINTABLE_ITEM flag, char *resultStr)
200199ebb4caSwyllys {
200299ebb4caSwyllys KMF_RETURN ret = KMF_OK;
200399ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
200499ebb4caSwyllys X509 *xcert = NULL;
200599ebb4caSwyllys unsigned char *outbuf = NULL;
200699ebb4caSwyllys unsigned char *outbuf_p;
200799ebb4caSwyllys int j;
200899ebb4caSwyllys int ext_index, nid, len;
200999ebb4caSwyllys BIO *mem = NULL;
201070f9559bSTheo Schlossnagle STACK_OF(OPENSSL_STRING) *emlst = NULL;
201199ebb4caSwyllys X509_EXTENSION *ex;
201299ebb4caSwyllys
201399ebb4caSwyllys if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
201499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
201599ebb4caSwyllys }
201699ebb4caSwyllys
201799ebb4caSwyllys /* copy cert data to outbuf */
201899ebb4caSwyllys outbuf = malloc(pcert->Length);
201999ebb4caSwyllys if (outbuf == NULL) {
202099ebb4caSwyllys return (KMF_ERR_MEMORY);
202199ebb4caSwyllys }
202299ebb4caSwyllys (void) memcpy(outbuf, pcert->Data, pcert->Length);
202399ebb4caSwyllys
202499ebb4caSwyllys outbuf_p = outbuf; /* use a temp pointer; required by openssl */
202599ebb4caSwyllys xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
202699ebb4caSwyllys if (xcert == NULL) {
202799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
202899ebb4caSwyllys ret = KMF_ERR_ENCODING;
202999ebb4caSwyllys goto out;
203099ebb4caSwyllys }
203199ebb4caSwyllys
203299ebb4caSwyllys mem = BIO_new(BIO_s_mem());
203399ebb4caSwyllys if (mem == NULL) {
203499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
203599ebb4caSwyllys ret = KMF_ERR_MEMORY;
203699ebb4caSwyllys goto out;
203799ebb4caSwyllys }
203899ebb4caSwyllys
203999ebb4caSwyllys switch (flag) {
204099ebb4caSwyllys case KMF_CERT_ISSUER:
204199ebb4caSwyllys (void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
204299ebb4caSwyllys XN_FLAG_SEP_CPLUS_SPC);
204399ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
204499ebb4caSwyllys break;
204599ebb4caSwyllys
204699ebb4caSwyllys case KMF_CERT_SUBJECT:
204799ebb4caSwyllys (void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
204899ebb4caSwyllys XN_FLAG_SEP_CPLUS_SPC);
204999ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
205099ebb4caSwyllys break;
205199ebb4caSwyllys
205299ebb4caSwyllys case KMF_CERT_VERSION:
2053300fdee2SAndy Fiddaman (void) snprintf(resultStr, KMF_CERT_PRINTABLE_LEN,
2054300fdee2SAndy Fiddaman "%ld", X509_get_version(xcert));
205599ebb4caSwyllys len = strlen(resultStr);
205699ebb4caSwyllys break;
205799ebb4caSwyllys
205899ebb4caSwyllys case KMF_CERT_SERIALNUM:
205999ebb4caSwyllys if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
206099ebb4caSwyllys (void) strcpy(resultStr, "0x");
206199ebb4caSwyllys len = BIO_gets(mem, &resultStr[2],
206299ebb4caSwyllys KMF_CERT_PRINTABLE_LEN - 2);
206399ebb4caSwyllys }
206499ebb4caSwyllys break;
206599ebb4caSwyllys
206699ebb4caSwyllys case KMF_CERT_NOTBEFORE:
2067300fdee2SAndy Fiddaman (void) ASN1_TIME_print(mem, X509_getm_notBefore(xcert));
206899ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
206999ebb4caSwyllys break;
207099ebb4caSwyllys
207199ebb4caSwyllys case KMF_CERT_NOTAFTER:
2072300fdee2SAndy Fiddaman (void) ASN1_TIME_print(mem, X509_getm_notAfter(xcert));
207399ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
207499ebb4caSwyllys break;
207599ebb4caSwyllys
207699ebb4caSwyllys case KMF_CERT_PUBKEY_DATA:
207799ebb4caSwyllys {
2078*6ff4183cSAndy Fiddaman #if OPENSSL_VERSION_NUMBER >= 0x30000000L
2079*6ff4183cSAndy Fiddaman const RSA *rsa;
2080*6ff4183cSAndy Fiddaman const DSA *dsa;
2081*6ff4183cSAndy Fiddaman #else
2082300fdee2SAndy Fiddaman RSA *rsa;
2083300fdee2SAndy Fiddaman DSA *dsa;
2084*6ff4183cSAndy Fiddaman #endif
2085300fdee2SAndy Fiddaman
208699ebb4caSwyllys EVP_PKEY *pkey = X509_get_pubkey(xcert);
208799ebb4caSwyllys if (pkey == NULL) {
208899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
208999ebb4caSwyllys ret = KMF_ERR_ENCODING;
209099ebb4caSwyllys goto out;
209199ebb4caSwyllys }
209299ebb4caSwyllys
2093300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
209499ebb4caSwyllys (void) BIO_printf(mem,
209599ebb4caSwyllys "RSA Public Key: (%d bit)\n",
2096300fdee2SAndy Fiddaman RSA_bits(rsa));
2097300fdee2SAndy Fiddaman (void) RSA_print(mem, rsa, 0);
2098300fdee2SAndy Fiddaman
2099300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
210099ebb4caSwyllys (void) BIO_printf(mem,
210199ebb4caSwyllys "%12sDSA Public Key:\n", "");
2102300fdee2SAndy Fiddaman (void) DSA_print(mem, dsa, 0);
210399ebb4caSwyllys } else {
210499ebb4caSwyllys (void) BIO_printf(mem,
210599ebb4caSwyllys "%12sUnknown Public Key:\n", "");
210699ebb4caSwyllys }
210799ebb4caSwyllys (void) BIO_printf(mem, "\n");
210899ebb4caSwyllys EVP_PKEY_free(pkey);
210999ebb4caSwyllys }
211099ebb4caSwyllys len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
211199ebb4caSwyllys break;
211299ebb4caSwyllys case KMF_CERT_SIGNATURE_ALG:
211399ebb4caSwyllys case KMF_CERT_PUBKEY_ALG:
2114300fdee2SAndy Fiddaman {
2115553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2116300fdee2SAndy Fiddaman ASN1_OBJECT *alg = NULL;
2117300fdee2SAndy Fiddaman #else
2118300fdee2SAndy Fiddaman const ASN1_OBJECT *alg = NULL;
2119300fdee2SAndy Fiddaman #endif
2120300fdee2SAndy Fiddaman
212199ebb4caSwyllys if (flag == KMF_CERT_SIGNATURE_ALG) {
2122553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2123300fdee2SAndy Fiddaman alg = xcert->sig_alg->algorithm;
2124300fdee2SAndy Fiddaman #else
2125300fdee2SAndy Fiddaman const X509_ALGOR *sig_alg = NULL;
2126300fdee2SAndy Fiddaman
2127300fdee2SAndy Fiddaman X509_get0_signature(NULL, &sig_alg, xcert);
2128300fdee2SAndy Fiddaman if (sig_alg != NULL)
2129300fdee2SAndy Fiddaman X509_ALGOR_get0(&alg, NULL, NULL,
2130300fdee2SAndy Fiddaman sig_alg);
2131300fdee2SAndy Fiddaman #endif
213299ebb4caSwyllys } else {
2133553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2134300fdee2SAndy Fiddaman alg = xcert->cert_info->key->algor->algorithm;
2135300fdee2SAndy Fiddaman #else
2136300fdee2SAndy Fiddaman X509_PUBKEY *key = X509_get_X509_PUBKEY(xcert);
2137300fdee2SAndy Fiddaman
2138300fdee2SAndy Fiddaman if (key != NULL)
2139300fdee2SAndy Fiddaman (void) X509_PUBKEY_get0_param(
2140300fdee2SAndy Fiddaman (ASN1_OBJECT **)&alg, NULL, 0,
2141300fdee2SAndy Fiddaman NULL, key);
2142300fdee2SAndy Fiddaman #endif
214399ebb4caSwyllys }
214499ebb4caSwyllys
2145300fdee2SAndy Fiddaman if (alg == NULL)
2146300fdee2SAndy Fiddaman len = -1;
2147300fdee2SAndy Fiddaman else if ((len = i2a_ASN1_OBJECT(mem, alg)) > 0)
214899ebb4caSwyllys len = BIO_read(mem, resultStr,
214999ebb4caSwyllys KMF_CERT_PRINTABLE_LEN);
215099ebb4caSwyllys }
215199ebb4caSwyllys break;
215299ebb4caSwyllys
215399ebb4caSwyllys case KMF_CERT_EMAIL:
215499ebb4caSwyllys emlst = X509_get1_email(xcert);
215570f9559bSTheo Schlossnagle for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
215670f9559bSTheo Schlossnagle (void) BIO_printf(mem, "%s\n",
215770f9559bSTheo Schlossnagle sk_OPENSSL_STRING_value(emlst, j));
215899ebb4caSwyllys
215999ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
216099ebb4caSwyllys X509_email_free(emlst);
216199ebb4caSwyllys break;
216299ebb4caSwyllys case KMF_X509_EXT_ISSUER_ALTNAME:
216399ebb4caSwyllys case KMF_X509_EXT_SUBJ_ALTNAME:
216499ebb4caSwyllys case KMF_X509_EXT_KEY_USAGE:
216599ebb4caSwyllys case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
216699ebb4caSwyllys case KMF_X509_EXT_CERT_POLICIES:
216799ebb4caSwyllys case KMF_X509_EXT_BASIC_CONSTRAINTS:
216899ebb4caSwyllys case KMF_X509_EXT_NAME_CONSTRAINTS:
216999ebb4caSwyllys case KMF_X509_EXT_POLICY_CONSTRAINTS:
217099ebb4caSwyllys case KMF_X509_EXT_EXT_KEY_USAGE:
217199ebb4caSwyllys case KMF_X509_EXT_INHIBIT_ANY_POLICY:
217299ebb4caSwyllys case KMF_X509_EXT_AUTH_KEY_ID:
217399ebb4caSwyllys case KMF_X509_EXT_SUBJ_KEY_ID:
217499ebb4caSwyllys case KMF_X509_EXT_POLICY_MAPPINGS:
217599ebb4caSwyllys case KMF_X509_EXT_CRL_DIST_POINTS:
217699ebb4caSwyllys case KMF_X509_EXT_FRESHEST_CRL:
217799ebb4caSwyllys nid = ext2NID(flag);
217899ebb4caSwyllys if (nid == NID_undef) {
217999ebb4caSwyllys ret = KMF_ERR_EXTENSION_NOT_FOUND;
218099ebb4caSwyllys goto out;
218199ebb4caSwyllys }
218299ebb4caSwyllys
2183300fdee2SAndy Fiddaman ext_index = X509_get_ext_by_NID(xcert, nid, -1);
218499ebb4caSwyllys if (ext_index == -1) {
218599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
218699ebb4caSwyllys
218799ebb4caSwyllys ret = KMF_ERR_EXTENSION_NOT_FOUND;
218899ebb4caSwyllys goto out;
218999ebb4caSwyllys }
2190300fdee2SAndy Fiddaman ex = X509_get_ext(xcert, ext_index);
219199ebb4caSwyllys
219299ebb4caSwyllys (void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
219399ebb4caSwyllys
219499ebb4caSwyllys if (BIO_printf(mem, ": %s\n",
219530a5e8faSwyllys X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
219699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
219799ebb4caSwyllys ret = KMF_ERR_ENCODING;
219899ebb4caSwyllys goto out;
219999ebb4caSwyllys }
220099ebb4caSwyllys if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
220199ebb4caSwyllys (void) BIO_printf(mem, "%*s", 4, "");
2202300fdee2SAndy Fiddaman (void) ASN1_STRING_print(mem,
2203300fdee2SAndy Fiddaman X509_EXTENSION_get_data(ex));
220499ebb4caSwyllys }
220599ebb4caSwyllys if (BIO_write(mem, "\n", 1) <= 0) {
220699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
220799ebb4caSwyllys ret = KMF_ERR_ENCODING;
220899ebb4caSwyllys goto out;
220999ebb4caSwyllys }
221099ebb4caSwyllys len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
221199ebb4caSwyllys }
221299ebb4caSwyllys if (len <= 0) {
221399ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
221499ebb4caSwyllys ret = KMF_ERR_ENCODING;
221599ebb4caSwyllys }
221699ebb4caSwyllys
221799ebb4caSwyllys out:
221899ebb4caSwyllys if (outbuf != NULL) {
221999ebb4caSwyllys free(outbuf);
222099ebb4caSwyllys }
222199ebb4caSwyllys
222299ebb4caSwyllys if (xcert != NULL) {
222399ebb4caSwyllys X509_free(xcert);
222499ebb4caSwyllys }
222599ebb4caSwyllys
222699ebb4caSwyllys if (mem != NULL) {
222799ebb4caSwyllys (void) BIO_free(mem);
222899ebb4caSwyllys }
222999ebb4caSwyllys
223099ebb4caSwyllys return (ret);
223199ebb4caSwyllys }
223230a5e8faSwyllys
223399ebb4caSwyllys KMF_RETURN
OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)223430a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
223530a5e8faSwyllys KMF_ATTRIBUTE *attrlist)
223699ebb4caSwyllys {
223799ebb4caSwyllys KMF_RETURN rv = KMF_OK;
223830a5e8faSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
223930a5e8faSwyllys KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
224030a5e8faSwyllys KMF_KEY_HANDLE *key = NULL;
224130a5e8faSwyllys uint32_t numkeys = 1; /* 1 key only */
224230a5e8faSwyllys char *dirpath = NULL;
224330a5e8faSwyllys char *keyfile = NULL;
224430a5e8faSwyllys KMF_ATTRIBUTE new_attrlist[16];
224530a5e8faSwyllys int i = 0;
224699ebb4caSwyllys
224799ebb4caSwyllys /*
224899ebb4caSwyllys * This is really just a FindKey operation, reuse the
224999ebb4caSwyllys * FindKey function.
225099ebb4caSwyllys */
225130a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i,
225230a5e8faSwyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
225330a5e8faSwyllys i++;
225499ebb4caSwyllys
225530a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i,
225630a5e8faSwyllys KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
225730a5e8faSwyllys i++;
225899ebb4caSwyllys
225930a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i,
226030a5e8faSwyllys KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
226130a5e8faSwyllys i++;
226230a5e8faSwyllys
226330a5e8faSwyllys key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
226430a5e8faSwyllys if (key == NULL) {
226530a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
226630a5e8faSwyllys } else {
226730a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i,
226830a5e8faSwyllys KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
226930a5e8faSwyllys i++;
227030a5e8faSwyllys }
227130a5e8faSwyllys
227230a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
227330a5e8faSwyllys if (dirpath != NULL) {
227430a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i,
227530a5e8faSwyllys KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
227630a5e8faSwyllys i++;
227730a5e8faSwyllys }
227830a5e8faSwyllys
227930a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
228030a5e8faSwyllys if (keyfile == NULL)
228130a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
228230a5e8faSwyllys else {
228330a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i,
228430a5e8faSwyllys KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
228530a5e8faSwyllys i++;
228630a5e8faSwyllys }
228730a5e8faSwyllys
228830a5e8faSwyllys rv = OpenSSL_FindKey(handle, i, new_attrlist);
228999ebb4caSwyllys return (rv);
229099ebb4caSwyllys }
229199ebb4caSwyllys
229299ebb4caSwyllys KMF_RETURN
OpenSSL_DecryptData(KMF_HANDLE_T handle,KMF_KEY_HANDLE * key,KMF_OID * AlgOID,KMF_DATA * ciphertext,KMF_DATA * output)229399ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
22944942e222SAndy Fiddaman KMF_OID *AlgOID, KMF_DATA *ciphertext, KMF_DATA *output)
229599ebb4caSwyllys {
229699ebb4caSwyllys KMF_RETURN ret = KMF_OK;
229799ebb4caSwyllys RSA *rsa = NULL;
229899ebb4caSwyllys unsigned int in_len = 0, out_len = 0;
229999ebb4caSwyllys unsigned int total_decrypted = 0, modulus_len = 0;
230099ebb4caSwyllys uint8_t *in_data, *out_data;
230199ebb4caSwyllys int i, blocks;
230299ebb4caSwyllys
230399ebb4caSwyllys if (key == NULL || AlgOID == NULL ||
230499ebb4caSwyllys ciphertext == NULL || output == NULL ||
230599ebb4caSwyllys ciphertext->Data == NULL ||
230699ebb4caSwyllys output->Data == NULL)
230799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
230899ebb4caSwyllys
230999ebb4caSwyllys if (key->keyalg == KMF_RSA) {
231099ebb4caSwyllys rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
231199ebb4caSwyllys modulus_len = RSA_size(rsa);
231299ebb4caSwyllys } else {
231399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
231499ebb4caSwyllys }
231599ebb4caSwyllys
231699ebb4caSwyllys blocks = ciphertext->Length/modulus_len;
231799ebb4caSwyllys out_data = output->Data;
231899ebb4caSwyllys in_data = ciphertext->Data;
231999ebb4caSwyllys out_len = modulus_len - 11;
232099ebb4caSwyllys in_len = modulus_len;
232199ebb4caSwyllys
232299ebb4caSwyllys for (i = 0; i < blocks; i++) {
232399ebb4caSwyllys out_len = RSA_private_decrypt(in_len,
232499ebb4caSwyllys in_data, out_data, rsa, RSA_PKCS1_PADDING);
232599ebb4caSwyllys
232699ebb4caSwyllys if (out_len == 0) {
232799ebb4caSwyllys ret = KMF_ERR_INTERNAL;
232899ebb4caSwyllys goto cleanup;
232999ebb4caSwyllys }
233099ebb4caSwyllys
233199ebb4caSwyllys out_data += out_len;
233299ebb4caSwyllys total_decrypted += out_len;
233399ebb4caSwyllys in_data += in_len;
233499ebb4caSwyllys }
233599ebb4caSwyllys
233699ebb4caSwyllys output->Length = total_decrypted;
233799ebb4caSwyllys
233899ebb4caSwyllys cleanup:
233999ebb4caSwyllys RSA_free(rsa);
234099ebb4caSwyllys if (ret != KMF_OK)
234199ebb4caSwyllys output->Length = 0;
234299ebb4caSwyllys
234399ebb4caSwyllys return (ret);
234499ebb4caSwyllys
234599ebb4caSwyllys }
234699ebb4caSwyllys
234799ebb4caSwyllys /*
234899ebb4caSwyllys * This function will create a certid from issuer_cert and user_cert.
234999ebb4caSwyllys * The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
235099ebb4caSwyllys * certid memory after use.
235199ebb4caSwyllys */
235299ebb4caSwyllys static KMF_RETURN
create_certid(KMF_HANDLE_T handle,const KMF_DATA * issuer_cert,const KMF_DATA * user_cert,OCSP_CERTID ** certid)235399ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
235499ebb4caSwyllys const KMF_DATA *user_cert, OCSP_CERTID **certid)
235599ebb4caSwyllys {
235699ebb4caSwyllys KMF_RETURN ret = KMF_OK;
235799ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
235899ebb4caSwyllys X509 *issuer = NULL;
235999ebb4caSwyllys X509 *cert = NULL;
236099ebb4caSwyllys unsigned char *ptmp;
236199ebb4caSwyllys
236299ebb4caSwyllys if (issuer_cert == NULL || user_cert == NULL) {
236399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
236499ebb4caSwyllys }
236599ebb4caSwyllys
236699ebb4caSwyllys /* convert the DER-encoded issuer cert to an internal X509 */
236799ebb4caSwyllys ptmp = issuer_cert->Data;
236899ebb4caSwyllys issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
236999ebb4caSwyllys issuer_cert->Length);
237099ebb4caSwyllys if (issuer == NULL) {
237199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
237299ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_ISSUER;
237399ebb4caSwyllys goto end;
237499ebb4caSwyllys }
237599ebb4caSwyllys
237699ebb4caSwyllys /* convert the DER-encoded user cert to an internal X509 */
237799ebb4caSwyllys ptmp = user_cert->Data;
237899ebb4caSwyllys cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
237999ebb4caSwyllys user_cert->Length);
238099ebb4caSwyllys if (cert == NULL) {
238199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
238299ebb4caSwyllys
238399ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_CERT;
238499ebb4caSwyllys goto end;
238599ebb4caSwyllys }
238699ebb4caSwyllys
238799ebb4caSwyllys /* create a CERTID */
238899ebb4caSwyllys *certid = OCSP_cert_to_id(NULL, cert, issuer);
238999ebb4caSwyllys if (*certid == NULL) {
239099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
239199ebb4caSwyllys ret = KMF_ERR_OCSP_CERTID;
239299ebb4caSwyllys goto end;
239399ebb4caSwyllys }
239499ebb4caSwyllys
239599ebb4caSwyllys end:
239699ebb4caSwyllys if (issuer != NULL) {
239799ebb4caSwyllys X509_free(issuer);
239899ebb4caSwyllys }
239999ebb4caSwyllys
240099ebb4caSwyllys if (cert != NULL) {
240199ebb4caSwyllys X509_free(cert);
240299ebb4caSwyllys }
240399ebb4caSwyllys
240499ebb4caSwyllys return (ret);
240599ebb4caSwyllys }
240699ebb4caSwyllys
240799ebb4caSwyllys KMF_RETURN
OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)240830a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
240930a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist)
241099ebb4caSwyllys {
241199ebb4caSwyllys KMF_RETURN ret = KMF_OK;
241299ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
241399ebb4caSwyllys OCSP_CERTID *id = NULL;
241499ebb4caSwyllys OCSP_REQUEST *req = NULL;
241599ebb4caSwyllys BIO *derbio = NULL;
241630a5e8faSwyllys char *reqfile;
241730a5e8faSwyllys KMF_DATA *issuer_cert;
241830a5e8faSwyllys KMF_DATA *user_cert;
241999ebb4caSwyllys
242030a5e8faSwyllys user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
242130a5e8faSwyllys attrlist, numattr);
242230a5e8faSwyllys if (user_cert == NULL)
242399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
242499ebb4caSwyllys
242530a5e8faSwyllys issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
242630a5e8faSwyllys attrlist, numattr);
242730a5e8faSwyllys if (issuer_cert == NULL)
242830a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
242930a5e8faSwyllys
243030a5e8faSwyllys reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
243130a5e8faSwyllys attrlist, numattr);
243230a5e8faSwyllys if (reqfile == NULL)
243330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
243430a5e8faSwyllys
243530a5e8faSwyllys ret = create_certid(handle, issuer_cert, user_cert, &id);
243699ebb4caSwyllys if (ret != KMF_OK) {
243799ebb4caSwyllys return (ret);
243899ebb4caSwyllys }
243999ebb4caSwyllys
244099ebb4caSwyllys /* Create an OCSP request */
244199ebb4caSwyllys req = OCSP_REQUEST_new();
244299ebb4caSwyllys if (req == NULL) {
244399ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
244499ebb4caSwyllys ret = KMF_ERR_OCSP_CREATE_REQUEST;
244599ebb4caSwyllys goto end;
244699ebb4caSwyllys }
244799ebb4caSwyllys
244899ebb4caSwyllys if (!OCSP_request_add0_id(req, id)) {
244999ebb4caSwyllys ret = KMF_ERR_OCSP_CREATE_REQUEST;
245099ebb4caSwyllys goto end;
245199ebb4caSwyllys }
245299ebb4caSwyllys
245399ebb4caSwyllys /* Write the request to the output file with DER encoding */
245499ebb4caSwyllys derbio = BIO_new_file(reqfile, "wb");
245599ebb4caSwyllys if (!derbio) {
245699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
245799ebb4caSwyllys ret = KMF_ERR_OPEN_FILE;
245899ebb4caSwyllys goto end;
245999ebb4caSwyllys }
246099ebb4caSwyllys if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
246199ebb4caSwyllys ret = KMF_ERR_ENCODING;
246299ebb4caSwyllys }
246399ebb4caSwyllys
246499ebb4caSwyllys end:
246599ebb4caSwyllys /*
2466e65e5c2dSWyllys Ingersoll * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2467a2d4930dSDan OpenSolaris Anderson * will also deallocate certid's space.
246899ebb4caSwyllys */
246999ebb4caSwyllys if (req != NULL) {
247099ebb4caSwyllys OCSP_REQUEST_free(req);
247199ebb4caSwyllys }
247299ebb4caSwyllys
247399ebb4caSwyllys if (derbio != NULL) {
247499ebb4caSwyllys (void) BIO_free(derbio);
247599ebb4caSwyllys }
247699ebb4caSwyllys
247799ebb4caSwyllys return (ret);
247899ebb4caSwyllys }
247999ebb4caSwyllys
248099ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */
ocsp_find_signer_sk(STACK_OF (X509)* certs,OCSP_BASICRESP * bs)2481300fdee2SAndy Fiddaman static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_BASICRESP *bs)
248299ebb4caSwyllys {
248399ebb4caSwyllys int i;
248499ebb4caSwyllys unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
2485300fdee2SAndy Fiddaman const ASN1_OCTET_STRING *pid;
248699ebb4caSwyllys
2487553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2488300fdee2SAndy Fiddaman OCSP_RESPID *id = bs->tbsResponseData->responderId;
2489300fdee2SAndy Fiddaman
249099ebb4caSwyllys if (id->type == V_OCSP_RESPID_NAME)
249199ebb4caSwyllys return (X509_find_by_subject(certs, id->value.byName));
249299ebb4caSwyllys
2493300fdee2SAndy Fiddaman pid = id->value.byKey;
2494300fdee2SAndy Fiddaman #else
2495300fdee2SAndy Fiddaman const X509_NAME *pname;
2496300fdee2SAndy Fiddaman
2497300fdee2SAndy Fiddaman if (OCSP_resp_get0_id(bs, &pid, &pname) == 0)
2498300fdee2SAndy Fiddaman return (NULL);
2499300fdee2SAndy Fiddaman
2500300fdee2SAndy Fiddaman if (pname != NULL)
2501300fdee2SAndy Fiddaman return (X509_find_by_subject(certs, (X509_NAME *)pname));
2502300fdee2SAndy Fiddaman #endif
2503300fdee2SAndy Fiddaman
250499ebb4caSwyllys /* Lookup by key hash */
250599ebb4caSwyllys
250699ebb4caSwyllys /* If key hash isn't SHA1 length then forget it */
2507300fdee2SAndy Fiddaman if (pid->length != SHA_DIGEST_LENGTH)
250899ebb4caSwyllys return (NULL);
250999ebb4caSwyllys
2510300fdee2SAndy Fiddaman keyhash = pid->data;
251199ebb4caSwyllys /* Calculate hash of each key and compare */
251299ebb4caSwyllys for (i = 0; i < sk_X509_num(certs); i++) {
251399ebb4caSwyllys X509 *x = sk_X509_value(certs, i);
25145b3e1433Swyllys /* Use pubkey_digest to get the key ID value */
251599ebb4caSwyllys (void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
251699ebb4caSwyllys if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
251799ebb4caSwyllys return (x);
251899ebb4caSwyllys }
251999ebb4caSwyllys return (NULL);
252099ebb4caSwyllys }
252199ebb4caSwyllys
252299ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */
252399ebb4caSwyllys static int
ocsp_find_signer(X509 ** psigner,OCSP_BASICRESP * bs,STACK_OF (X509)* certs,X509_STORE * st,unsigned long flags)252499ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
252599ebb4caSwyllys X509_STORE *st, unsigned long flags)
252699ebb4caSwyllys {
252799ebb4caSwyllys X509 *signer;
2528300fdee2SAndy Fiddaman if ((signer = ocsp_find_signer_sk(certs, bs))) {
252999ebb4caSwyllys *psigner = signer;
253099ebb4caSwyllys return (2);
253199ebb4caSwyllys }
2532300fdee2SAndy Fiddaman
253399ebb4caSwyllys if (!(flags & OCSP_NOINTERN) &&
2534300fdee2SAndy Fiddaman (signer = ocsp_find_signer_sk(
2535300fdee2SAndy Fiddaman (STACK_OF(X509) *)OCSP_resp_get0_certs(bs), bs))) {
253699ebb4caSwyllys *psigner = signer;
253799ebb4caSwyllys return (1);
253899ebb4caSwyllys }
253999ebb4caSwyllys /* Maybe lookup from store if by subject name */
254099ebb4caSwyllys
254199ebb4caSwyllys *psigner = NULL;
254299ebb4caSwyllys return (0);
254399ebb4caSwyllys }
254499ebb4caSwyllys
254599ebb4caSwyllys /*
254699ebb4caSwyllys * This function will verify the signature of a basic response, using
254799ebb4caSwyllys * the public key from the OCSP responder certificate.
254899ebb4caSwyllys */
254999ebb4caSwyllys static KMF_RETURN
check_response_signature(KMF_HANDLE_T handle,OCSP_BASICRESP * bs,KMF_DATA * signer_cert,KMF_DATA * issuer_cert)255099ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
255199ebb4caSwyllys KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
255299ebb4caSwyllys {
255399ebb4caSwyllys KMF_RETURN ret = KMF_OK;
255499ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
255599ebb4caSwyllys STACK_OF(X509) *cert_stack = NULL;
255699ebb4caSwyllys X509 *signer = NULL;
255799ebb4caSwyllys X509 *issuer = NULL;
2558553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
255999ebb4caSwyllys EVP_PKEY *skey = NULL;
2560300fdee2SAndy Fiddaman #else
2561300fdee2SAndy Fiddaman STACK_OF(X509) *cert_stack2 = NULL;
2562300fdee2SAndy Fiddaman #endif
256399ebb4caSwyllys unsigned char *ptmp;
256499ebb4caSwyllys
256599ebb4caSwyllys if (bs == NULL || issuer_cert == NULL)
256699ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
256799ebb4caSwyllys
256899ebb4caSwyllys /*
256999ebb4caSwyllys * Find the certificate that signed the basic response.
257099ebb4caSwyllys *
257199ebb4caSwyllys * If signer_cert is not NULL, we will use that as the signer cert.
257299ebb4caSwyllys * Otherwise, we will check if the issuer cert is actually the signer.
257399ebb4caSwyllys * If we still do not find a signer, we will look for it from the
257499ebb4caSwyllys * certificate list came with the response file.
257599ebb4caSwyllys */
257699ebb4caSwyllys if (signer_cert != NULL) {
257799ebb4caSwyllys ptmp = signer_cert->Data;
257899ebb4caSwyllys signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
257999ebb4caSwyllys signer_cert->Length);
258099ebb4caSwyllys if (signer == NULL) {
258199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
258299ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_SIGNER;
258399ebb4caSwyllys goto end;
258499ebb4caSwyllys }
258599ebb4caSwyllys } else {
258699ebb4caSwyllys /*
258799ebb4caSwyllys * Convert the issuer cert into X509 and push it into a
258899ebb4caSwyllys * stack to be used by ocsp_find_signer().
258999ebb4caSwyllys */
259099ebb4caSwyllys ptmp = issuer_cert->Data;
259199ebb4caSwyllys issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
259299ebb4caSwyllys issuer_cert->Length);
259399ebb4caSwyllys if (issuer == NULL) {
259499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
259599ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_ISSUER;
259699ebb4caSwyllys goto end;
259799ebb4caSwyllys }
259899ebb4caSwyllys
259999ebb4caSwyllys if ((cert_stack = sk_X509_new_null()) == NULL) {
260099ebb4caSwyllys ret = KMF_ERR_INTERNAL;
260199ebb4caSwyllys goto end;
260299ebb4caSwyllys }
260399ebb4caSwyllys
2604f810c7e5SToomas Soome if (sk_X509_push(cert_stack, issuer) == 0) {
260599ebb4caSwyllys ret = KMF_ERR_INTERNAL;
260699ebb4caSwyllys goto end;
260799ebb4caSwyllys }
260899ebb4caSwyllys
260999ebb4caSwyllys ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
261099ebb4caSwyllys if (!ret) {
261199ebb4caSwyllys /* can not find the signer */
261299ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_SIGNER;
261399ebb4caSwyllys goto end;
261499ebb4caSwyllys }
261599ebb4caSwyllys }
261699ebb4caSwyllys
261799ebb4caSwyllys /* Verify the signature of the response */
2618553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
261999ebb4caSwyllys skey = X509_get_pubkey(signer);
262099ebb4caSwyllys if (skey == NULL) {
262199ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_SIGNER;
262299ebb4caSwyllys goto end;
262399ebb4caSwyllys }
262499ebb4caSwyllys
262599ebb4caSwyllys ret = OCSP_BASICRESP_verify(bs, skey, 0);
2626300fdee2SAndy Fiddaman #else
2627300fdee2SAndy Fiddaman /*
2628300fdee2SAndy Fiddaman * Technique based on
2629300fdee2SAndy Fiddaman * https://mta.openssl.org/pipermail/openssl-users/
2630300fdee2SAndy Fiddaman * 2017-October/006814.html
2631300fdee2SAndy Fiddaman */
2632300fdee2SAndy Fiddaman if ((cert_stack2 = sk_X509_new_null()) == NULL) {
2633300fdee2SAndy Fiddaman ret = KMF_ERR_INTERNAL;
2634300fdee2SAndy Fiddaman goto end;
2635300fdee2SAndy Fiddaman }
2636300fdee2SAndy Fiddaman
26374942e222SAndy Fiddaman if (sk_X509_push(cert_stack2, signer) == 0) {
2638300fdee2SAndy Fiddaman ret = KMF_ERR_INTERNAL;
2639300fdee2SAndy Fiddaman goto end;
2640300fdee2SAndy Fiddaman }
2641300fdee2SAndy Fiddaman
2642300fdee2SAndy Fiddaman ret = OCSP_basic_verify(bs, cert_stack2, NULL, OCSP_NOVERIFY);
2643300fdee2SAndy Fiddaman #endif
2644300fdee2SAndy Fiddaman
264599ebb4caSwyllys if (ret == 0) {
264699ebb4caSwyllys ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
264799ebb4caSwyllys goto end;
264899ebb4caSwyllys }
264999ebb4caSwyllys
265099ebb4caSwyllys end:
265199ebb4caSwyllys if (issuer != NULL) {
265299ebb4caSwyllys X509_free(issuer);
265399ebb4caSwyllys }
265499ebb4caSwyllys
265599ebb4caSwyllys if (signer != NULL) {
265699ebb4caSwyllys X509_free(signer);
265799ebb4caSwyllys }
265899ebb4caSwyllys
2659553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
266099ebb4caSwyllys if (skey != NULL) {
266199ebb4caSwyllys EVP_PKEY_free(skey);
266299ebb4caSwyllys }
2663300fdee2SAndy Fiddaman #else
2664300fdee2SAndy Fiddaman if (cert_stack2 != NULL) {
2665300fdee2SAndy Fiddaman sk_X509_free(cert_stack2);
2666300fdee2SAndy Fiddaman }
2667300fdee2SAndy Fiddaman #endif
266899ebb4caSwyllys
266999ebb4caSwyllys if (cert_stack != NULL) {
267099ebb4caSwyllys sk_X509_free(cert_stack);
267199ebb4caSwyllys }
267299ebb4caSwyllys
267399ebb4caSwyllys return (ret);
267499ebb4caSwyllys }
267599ebb4caSwyllys
267699ebb4caSwyllys KMF_RETURN
OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)26774942e222SAndy Fiddaman OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle, int numattr,
26784942e222SAndy Fiddaman KMF_ATTRIBUTE *attrlist)
267999ebb4caSwyllys {
268099ebb4caSwyllys KMF_RETURN ret = KMF_OK;
268199ebb4caSwyllys BIO *derbio = NULL;
268299ebb4caSwyllys OCSP_RESPONSE *resp = NULL;
268399ebb4caSwyllys OCSP_BASICRESP *bs = NULL;
268499ebb4caSwyllys OCSP_CERTID *id = NULL;
268599ebb4caSwyllys OCSP_SINGLERESP *single = NULL;
268699ebb4caSwyllys ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
268799ebb4caSwyllys int index, status, reason;
268830a5e8faSwyllys KMF_DATA *issuer_cert;
268930a5e8faSwyllys KMF_DATA *user_cert;
269030a5e8faSwyllys KMF_DATA *signer_cert;
269130a5e8faSwyllys KMF_DATA *response;
269230a5e8faSwyllys int *response_reason, *response_status, *cert_status;
269330a5e8faSwyllys boolean_t ignore_response_sign = B_FALSE; /* default is FALSE */
269430a5e8faSwyllys uint32_t response_lifetime;
269599ebb4caSwyllys
269630a5e8faSwyllys issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
269730a5e8faSwyllys attrlist, numattr);
269830a5e8faSwyllys if (issuer_cert == NULL)
269999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
270099ebb4caSwyllys
270130a5e8faSwyllys user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
270230a5e8faSwyllys attrlist, numattr);
270330a5e8faSwyllys if (user_cert == NULL)
270499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
270530a5e8faSwyllys
270630a5e8faSwyllys response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
270730a5e8faSwyllys attrlist, numattr);
270830a5e8faSwyllys if (response == NULL)
270930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
271030a5e8faSwyllys
271130a5e8faSwyllys response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
271230a5e8faSwyllys attrlist, numattr);
271330a5e8faSwyllys if (response_status == NULL)
271430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
271530a5e8faSwyllys
271630a5e8faSwyllys response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
271730a5e8faSwyllys attrlist, numattr);
271830a5e8faSwyllys if (response_reason == NULL)
271930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
272030a5e8faSwyllys
272130a5e8faSwyllys cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
272230a5e8faSwyllys attrlist, numattr);
272330a5e8faSwyllys if (cert_status == NULL)
272430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
272599ebb4caSwyllys
272699ebb4caSwyllys /* Read in the response */
272730a5e8faSwyllys derbio = BIO_new_mem_buf(response->Data, response->Length);
272899ebb4caSwyllys if (!derbio) {
272999ebb4caSwyllys ret = KMF_ERR_MEMORY;
273099ebb4caSwyllys return (ret);
273199ebb4caSwyllys }
273299ebb4caSwyllys
273399ebb4caSwyllys resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
273499ebb4caSwyllys if (resp == NULL) {
273599ebb4caSwyllys ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
273699ebb4caSwyllys goto end;
273799ebb4caSwyllys }
273899ebb4caSwyllys
273999ebb4caSwyllys /* Check the response status */
274099ebb4caSwyllys status = OCSP_response_status(resp);
274130a5e8faSwyllys *response_status = status;
274299ebb4caSwyllys if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
274399ebb4caSwyllys ret = KMF_ERR_OCSP_RESPONSE_STATUS;
274499ebb4caSwyllys goto end;
274599ebb4caSwyllys }
274699ebb4caSwyllys
274799ebb4caSwyllys #ifdef DEBUG
274899ebb4caSwyllys printf("Successfully checked the response file status.\n");
274999ebb4caSwyllys #endif /* DEBUG */
275099ebb4caSwyllys
275199ebb4caSwyllys /* Extract basic response */
275299ebb4caSwyllys bs = OCSP_response_get1_basic(resp);
275399ebb4caSwyllys if (bs == NULL) {
275499ebb4caSwyllys ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
275599ebb4caSwyllys goto end;
275699ebb4caSwyllys }
275799ebb4caSwyllys
275899ebb4caSwyllys #ifdef DEBUG
275999ebb4caSwyllys printf("Successfully retrieved the basic response.\n");
276099ebb4caSwyllys #endif /* DEBUG */
276199ebb4caSwyllys
276299ebb4caSwyllys /* Check the basic response signature if required */
276330a5e8faSwyllys ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
276430a5e8faSwyllys (void *)&ignore_response_sign, NULL);
276530a5e8faSwyllys if (ret != KMF_OK)
276630a5e8faSwyllys ret = KMF_OK;
276730a5e8faSwyllys
276830a5e8faSwyllys signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
276930a5e8faSwyllys attrlist, numattr);
277030a5e8faSwyllys
277130a5e8faSwyllys if (ignore_response_sign == B_FALSE) {
277299ebb4caSwyllys ret = check_response_signature(handle, bs,
277330a5e8faSwyllys signer_cert, issuer_cert);
277499ebb4caSwyllys if (ret != KMF_OK)
277599ebb4caSwyllys goto end;
277699ebb4caSwyllys }
277799ebb4caSwyllys
277899ebb4caSwyllys #ifdef DEBUG
277999ebb4caSwyllys printf("Successfully verified the response signature.\n");
278099ebb4caSwyllys #endif /* DEBUG */
278199ebb4caSwyllys
278299ebb4caSwyllys /* Create a certid for the certificate in question */
278330a5e8faSwyllys ret = create_certid(handle, issuer_cert, user_cert, &id);
278499ebb4caSwyllys if (ret != KMF_OK) {
278599ebb4caSwyllys ret = KMF_ERR_OCSP_CERTID;
278699ebb4caSwyllys goto end;
278799ebb4caSwyllys }
278899ebb4caSwyllys
278999ebb4caSwyllys #ifdef DEBUG
279099ebb4caSwyllys printf("successfully created a certid for the cert.\n");
279199ebb4caSwyllys #endif /* DEBUG */
279299ebb4caSwyllys
279399ebb4caSwyllys /* Find the index of the single response for the certid */
279499ebb4caSwyllys index = OCSP_resp_find(bs, id, -1);
279599ebb4caSwyllys if (index < 0) {
279699ebb4caSwyllys /* cound not find this certificate in the response */
279799ebb4caSwyllys ret = KMF_ERR_OCSP_UNKNOWN_CERT;
279899ebb4caSwyllys goto end;
279999ebb4caSwyllys }
280099ebb4caSwyllys
280199ebb4caSwyllys #ifdef DEBUG
280299ebb4caSwyllys printf("Successfully found the single response index for the cert.\n");
280399ebb4caSwyllys #endif /* DEBUG */
280499ebb4caSwyllys
280599ebb4caSwyllys /* Retrieve the single response and get the cert status */
280699ebb4caSwyllys single = OCSP_resp_get0(bs, index);
280799ebb4caSwyllys status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
280899ebb4caSwyllys &nextupd);
280999ebb4caSwyllys if (status == V_OCSP_CERTSTATUS_GOOD) {
281030a5e8faSwyllys *cert_status = OCSP_GOOD;
281199ebb4caSwyllys } else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
281230a5e8faSwyllys *cert_status = OCSP_UNKNOWN;
281399ebb4caSwyllys } else { /* revoked */
281430a5e8faSwyllys *cert_status = OCSP_REVOKED;
281530a5e8faSwyllys *response_reason = reason;
281699ebb4caSwyllys }
281799ebb4caSwyllys ret = KMF_OK;
281899ebb4caSwyllys
281930a5e8faSwyllys /* resp. time is optional, so we don't care about the return code. */
282030a5e8faSwyllys (void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
282130a5e8faSwyllys (void *)&response_lifetime, NULL);
282230a5e8faSwyllys
282399ebb4caSwyllys if (!OCSP_check_validity(thisupd, nextupd, 300,
282430a5e8faSwyllys response_lifetime)) {
282599ebb4caSwyllys ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
282699ebb4caSwyllys goto end;
282799ebb4caSwyllys }
282899ebb4caSwyllys
282999ebb4caSwyllys #ifdef DEBUG
283099ebb4caSwyllys printf("Successfully verify the time.\n");
283199ebb4caSwyllys #endif /* DEBUG */
283299ebb4caSwyllys
283399ebb4caSwyllys end:
283499ebb4caSwyllys if (derbio != NULL)
283599ebb4caSwyllys (void) BIO_free(derbio);
283699ebb4caSwyllys
283799ebb4caSwyllys if (resp != NULL)
283899ebb4caSwyllys OCSP_RESPONSE_free(resp);
283999ebb4caSwyllys
284099ebb4caSwyllys if (bs != NULL)
284199ebb4caSwyllys OCSP_BASICRESP_free(bs);
284299ebb4caSwyllys
284399ebb4caSwyllys if (id != NULL)
284499ebb4caSwyllys OCSP_CERTID_free(id);
284599ebb4caSwyllys
284699ebb4caSwyllys return (ret);
284799ebb4caSwyllys }
284899ebb4caSwyllys
284999ebb4caSwyllys static KMF_RETURN
fetch_key(KMF_HANDLE_T handle,char * path,KMF_KEY_CLASS keyclass,KMF_KEY_HANDLE * key)28504942e222SAndy Fiddaman fetch_key(KMF_HANDLE_T handle, char *path, KMF_KEY_CLASS keyclass,
28514942e222SAndy Fiddaman KMF_KEY_HANDLE *key)
285299ebb4caSwyllys {
285399ebb4caSwyllys KMF_RETURN rv = KMF_OK;
285430a5e8faSwyllys EVP_PKEY *pkey = NULL;
285599ebb4caSwyllys KMF_RAW_SYM_KEY *rkey = NULL;
285699ebb4caSwyllys
285799ebb4caSwyllys if (keyclass == KMF_ASYM_PRI ||
285899ebb4caSwyllys keyclass == KMF_ASYM_PUB) {
285999ebb4caSwyllys pkey = openssl_load_key(handle, path);
286099ebb4caSwyllys if (pkey == NULL) {
286199ebb4caSwyllys return (KMF_ERR_KEY_NOT_FOUND);
286299ebb4caSwyllys }
286399ebb4caSwyllys if (key != NULL) {
2864300fdee2SAndy Fiddaman if (EVP_PKEY_get0_RSA(pkey) != NULL)
286599ebb4caSwyllys key->keyalg = KMF_RSA;
2866300fdee2SAndy Fiddaman else if (EVP_PKEY_get0_DSA(pkey) != NULL)
286799ebb4caSwyllys key->keyalg = KMF_DSA;
286899ebb4caSwyllys
286999ebb4caSwyllys key->kstype = KMF_KEYSTORE_OPENSSL;
287099ebb4caSwyllys key->keyclass = keyclass;
287199ebb4caSwyllys key->keyp = (void *)pkey;
287299ebb4caSwyllys key->israw = FALSE;
28735b3e1433Swyllys if (path != NULL &&
28745b3e1433Swyllys ((key->keylabel = strdup(path)) == NULL)) {
28755b3e1433Swyllys EVP_PKEY_free(pkey);
28765b3e1433Swyllys return (KMF_ERR_MEMORY);
28775b3e1433Swyllys }
287899ebb4caSwyllys } else {
287999ebb4caSwyllys EVP_PKEY_free(pkey);
288099ebb4caSwyllys pkey = NULL;
288199ebb4caSwyllys }
288299ebb4caSwyllys } else if (keyclass == KMF_SYMMETRIC) {
288399ebb4caSwyllys KMF_ENCODE_FORMAT fmt;
288499ebb4caSwyllys /*
288599ebb4caSwyllys * If the file is a recognized format,
288699ebb4caSwyllys * then it is NOT a symmetric key.
288799ebb4caSwyllys */
288830a5e8faSwyllys rv = kmf_get_file_format(path, &fmt);
288999ebb4caSwyllys if (rv == KMF_OK || fmt != 0) {
289099ebb4caSwyllys return (KMF_ERR_KEY_NOT_FOUND);
289199ebb4caSwyllys } else if (rv == KMF_ERR_ENCODING) {
289299ebb4caSwyllys /*
289399ebb4caSwyllys * If we don't know the encoding,
289499ebb4caSwyllys * it is probably a symmetric key.
289599ebb4caSwyllys */
289699ebb4caSwyllys rv = KMF_OK;
289730a5e8faSwyllys } else if (rv == KMF_ERR_OPEN_FILE) {
289830a5e8faSwyllys return (KMF_ERR_KEY_NOT_FOUND);
289999ebb4caSwyllys }
290099ebb4caSwyllys
290199ebb4caSwyllys if (key != NULL) {
290299ebb4caSwyllys KMF_DATA keyvalue;
290399ebb4caSwyllys rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
290499ebb4caSwyllys if (rkey == NULL) {
290599ebb4caSwyllys rv = KMF_ERR_MEMORY;
290699ebb4caSwyllys goto out;
290799ebb4caSwyllys }
290899ebb4caSwyllys
290999ebb4caSwyllys (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
291030a5e8faSwyllys rv = kmf_read_input_file(handle, path, &keyvalue);
291199ebb4caSwyllys if (rv != KMF_OK)
291299ebb4caSwyllys goto out;
291399ebb4caSwyllys
291499ebb4caSwyllys rkey->keydata.len = keyvalue.Length;
291599ebb4caSwyllys rkey->keydata.val = keyvalue.Data;
291699ebb4caSwyllys
291799ebb4caSwyllys key->kstype = KMF_KEYSTORE_OPENSSL;
291899ebb4caSwyllys key->keyclass = keyclass;
291999ebb4caSwyllys key->israw = TRUE;
292099ebb4caSwyllys key->keyp = (void *)rkey;
29215b3e1433Swyllys if (path != NULL &&
29225b3e1433Swyllys ((key->keylabel = strdup(path)) == NULL)) {
29235b3e1433Swyllys rv = KMF_ERR_MEMORY;
29245b3e1433Swyllys }
292599ebb4caSwyllys }
292699ebb4caSwyllys }
292799ebb4caSwyllys out:
292899ebb4caSwyllys if (rv != KMF_OK) {
292999ebb4caSwyllys if (rkey != NULL) {
293030a5e8faSwyllys kmf_free_raw_sym_key(rkey);
293199ebb4caSwyllys }
293299ebb4caSwyllys if (pkey != NULL)
293399ebb4caSwyllys EVP_PKEY_free(pkey);
293499ebb4caSwyllys
293599ebb4caSwyllys if (key != NULL) {
293699ebb4caSwyllys key->keyalg = KMF_KEYALG_NONE;
293799ebb4caSwyllys key->keyclass = KMF_KEYCLASS_NONE;
293899ebb4caSwyllys key->keyp = NULL;
293999ebb4caSwyllys }
294099ebb4caSwyllys }
294199ebb4caSwyllys
294299ebb4caSwyllys return (rv);
294399ebb4caSwyllys }
294499ebb4caSwyllys
294599ebb4caSwyllys KMF_RETURN
OpenSSL_FindKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)29464942e222SAndy Fiddaman OpenSSL_FindKey(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
294799ebb4caSwyllys {
294899ebb4caSwyllys KMF_RETURN rv = KMF_OK;
294999ebb4caSwyllys char *fullpath = NULL;
2950f482c776Swyllys uint32_t maxkeys;
295130a5e8faSwyllys KMF_KEY_HANDLE *key;
295230a5e8faSwyllys uint32_t *numkeys;
295330a5e8faSwyllys KMF_KEY_CLASS keyclass;
295430a5e8faSwyllys KMF_RAW_KEY_DATA *rawkey;
295530a5e8faSwyllys char *dirpath;
295630a5e8faSwyllys char *keyfile;
295799ebb4caSwyllys
295830a5e8faSwyllys if (handle == NULL)
295999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
296099ebb4caSwyllys
296130a5e8faSwyllys numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
296230a5e8faSwyllys if (numkeys == NULL)
296330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
296430a5e8faSwyllys
296530a5e8faSwyllys rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
296630a5e8faSwyllys (void *)&keyclass, NULL);
296730a5e8faSwyllys if (rv != KMF_OK)
296830a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
296930a5e8faSwyllys
297030a5e8faSwyllys if (keyclass != KMF_ASYM_PUB &&
297130a5e8faSwyllys keyclass != KMF_ASYM_PRI &&
297230a5e8faSwyllys keyclass != KMF_SYMMETRIC)
297399ebb4caSwyllys return (KMF_ERR_BAD_KEY_CLASS);
297499ebb4caSwyllys
297530a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
297630a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
297730a5e8faSwyllys
297830a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile);
297999ebb4caSwyllys
298099ebb4caSwyllys if (fullpath == NULL)
298199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
298299ebb4caSwyllys
2983f482c776Swyllys maxkeys = *numkeys;
2984f482c776Swyllys if (maxkeys == 0)
2985f482c776Swyllys maxkeys = 0xFFFFFFFF;
298699ebb4caSwyllys *numkeys = 0;
298799ebb4caSwyllys
298830a5e8faSwyllys key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
298930a5e8faSwyllys /* it is okay to have "keys" contains NULL */
299030a5e8faSwyllys
299130a5e8faSwyllys /*
299230a5e8faSwyllys * The caller may want a list of the raw key data as well.
299330a5e8faSwyllys * Useful for importing keys from a file into other keystores.
299430a5e8faSwyllys */
299530a5e8faSwyllys rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
299630a5e8faSwyllys
299799ebb4caSwyllys if (isdir(fullpath)) {
299899ebb4caSwyllys DIR *dirp;
299999ebb4caSwyllys struct dirent *dp;
300099ebb4caSwyllys int n = 0;
300199ebb4caSwyllys
300299ebb4caSwyllys /* open all files in the directory and attempt to read them */
300399ebb4caSwyllys if ((dirp = opendir(fullpath)) == NULL) {
300499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
300599ebb4caSwyllys }
300699ebb4caSwyllys rewinddir(dirp);
3007f482c776Swyllys while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
300899ebb4caSwyllys if (strcmp(dp->d_name, ".") &&
300999ebb4caSwyllys strcmp(dp->d_name, "..")) {
301099ebb4caSwyllys char *fname;
301199ebb4caSwyllys
301299ebb4caSwyllys fname = get_fullpath(fullpath,
301399ebb4caSwyllys (char *)&dp->d_name);
301499ebb4caSwyllys
301599ebb4caSwyllys rv = fetch_key(handle, fname,
301630a5e8faSwyllys keyclass, key ? &key[n] : NULL);
301799ebb4caSwyllys
301830a5e8faSwyllys if (rv == KMF_OK) {
301930a5e8faSwyllys if (key != NULL && rawkey != NULL)
302030a5e8faSwyllys rv = convertToRawKey(
302130a5e8faSwyllys key[n].keyp, &rawkey[n]);
302299ebb4caSwyllys n++;
302330a5e8faSwyllys }
302499ebb4caSwyllys
302599ebb4caSwyllys if (rv != KMF_OK || key == NULL)
302699ebb4caSwyllys free(fname);
302799ebb4caSwyllys }
302899ebb4caSwyllys }
302999ebb4caSwyllys (void) closedir(dirp);
303099ebb4caSwyllys free(fullpath);
303199ebb4caSwyllys (*numkeys) = n;
303299ebb4caSwyllys } else {
303330a5e8faSwyllys rv = fetch_key(handle, fullpath, keyclass, key);
303499ebb4caSwyllys if (rv == KMF_OK)
303599ebb4caSwyllys (*numkeys) = 1;
303699ebb4caSwyllys
303799ebb4caSwyllys if (rv != KMF_OK || key == NULL)
303899ebb4caSwyllys free(fullpath);
303930a5e8faSwyllys
304030a5e8faSwyllys if (rv == KMF_OK && key != NULL && rawkey != NULL) {
304130a5e8faSwyllys rv = convertToRawKey(key->keyp, rawkey);
304230a5e8faSwyllys }
304399ebb4caSwyllys }
304499ebb4caSwyllys
3045f482c776Swyllys if (rv == KMF_OK && (*numkeys) == 0)
304699ebb4caSwyllys rv = KMF_ERR_KEY_NOT_FOUND;
304773cc0e02Swyllys else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
304873cc0e02Swyllys rv = KMF_OK;
304999ebb4caSwyllys
305099ebb4caSwyllys return (rv);
305199ebb4caSwyllys }
305299ebb4caSwyllys
305399ebb4caSwyllys #define HANDLE_PK12_ERROR { \
305499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); \
305599ebb4caSwyllys rv = KMF_ERR_ENCODING; \
305699ebb4caSwyllys goto out; \
305799ebb4caSwyllys }
305899ebb4caSwyllys
30595b3e1433Swyllys static int
add_alias_to_bag(PKCS12_SAFEBAG * bag,X509 * xcert)30605b3e1433Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
306199ebb4caSwyllys {
3062300fdee2SAndy Fiddaman unsigned char *alias;
3063300fdee2SAndy Fiddaman int len;
3064300fdee2SAndy Fiddaman
3065300fdee2SAndy Fiddaman if (xcert != NULL && (alias = X509_alias_get0(xcert, &len)) != NULL) {
30665b3e1433Swyllys if (PKCS12_add_friendlyname_asc(bag,
3067300fdee2SAndy Fiddaman (const char *)alias, len) == 0)
30685b3e1433Swyllys return (0);
30695b3e1433Swyllys }
30705b3e1433Swyllys return (1);
30715b3e1433Swyllys }
30725b3e1433Swyllys
30735b3e1433Swyllys static PKCS7 *
add_cert_to_safe(X509 * sslcert,KMF_CREDENTIAL * cred,uchar_t * keyid,unsigned int keyidlen)30745b3e1433Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
30755b3e1433Swyllys uchar_t *keyid, unsigned int keyidlen)
30765b3e1433Swyllys {
307799ebb4caSwyllys PKCS12_SAFEBAG *bag = NULL;
307899ebb4caSwyllys PKCS7 *cert_authsafe = NULL;
30795b3e1433Swyllys STACK_OF(PKCS12_SAFEBAG) *bag_stack;
308099ebb4caSwyllys
308199ebb4caSwyllys bag_stack = sk_PKCS12_SAFEBAG_new_null();
308299ebb4caSwyllys if (bag_stack == NULL)
30835b3e1433Swyllys return (NULL);
308499ebb4caSwyllys
308599ebb4caSwyllys /* Convert cert from X509 struct to PKCS#12 bag */
3086300fdee2SAndy Fiddaman bag = PKCS12_SAFEBAG_create_cert(sslcert);
308799ebb4caSwyllys if (bag == NULL) {
30885b3e1433Swyllys goto out;
308999ebb4caSwyllys }
309099ebb4caSwyllys
309199ebb4caSwyllys /* Add the key id to the certificate bag. */
30925b3e1433Swyllys if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
30935b3e1433Swyllys goto out;
309499ebb4caSwyllys }
309599ebb4caSwyllys
30965b3e1433Swyllys if (!add_alias_to_bag(bag, sslcert))
30975b3e1433Swyllys goto out;
30985b3e1433Swyllys
309999ebb4caSwyllys /* Pile it on the bag_stack. */
310099ebb4caSwyllys if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
31015b3e1433Swyllys goto out;
310299ebb4caSwyllys }
310399ebb4caSwyllys /* Turn bag_stack of certs into encrypted authsafe. */
310499ebb4caSwyllys cert_authsafe = PKCS12_pack_p7encdata(
310599ebb4caSwyllys NID_pbe_WithSHA1And40BitRC2_CBC,
310634acef67Swyllys cred->cred, cred->credlen, NULL, 0,
310734acef67Swyllys PKCS12_DEFAULT_ITER, bag_stack);
310899ebb4caSwyllys
31095b3e1433Swyllys out:
31105b3e1433Swyllys if (bag_stack != NULL)
311199ebb4caSwyllys sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
311299ebb4caSwyllys
31135b3e1433Swyllys return (cert_authsafe);
311499ebb4caSwyllys }
31155b3e1433Swyllys
31165b3e1433Swyllys static PKCS7 *
add_key_to_safe(EVP_PKEY * pkey,KMF_CREDENTIAL * cred,uchar_t * keyid,unsigned int keyidlen,char * label,int label_len)31175b3e1433Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
31184942e222SAndy Fiddaman uchar_t *keyid, unsigned int keyidlen, char *label, int label_len)
31195b3e1433Swyllys {
31205b3e1433Swyllys PKCS8_PRIV_KEY_INFO *p8 = NULL;
31215b3e1433Swyllys STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
31225b3e1433Swyllys PKCS12_SAFEBAG *bag = NULL;
31235b3e1433Swyllys PKCS7 *key_authsafe = NULL;
31245b3e1433Swyllys
312599ebb4caSwyllys p8 = EVP_PKEY2PKCS8(pkey);
312699ebb4caSwyllys if (p8 == NULL) {
31275b3e1433Swyllys return (NULL);
312899ebb4caSwyllys }
312999ebb4caSwyllys /* Put the shrouded key into a PKCS#12 bag. */
3130300fdee2SAndy Fiddaman bag = PKCS12_SAFEBAG_create_pkcs8_encrypt(
313199ebb4caSwyllys NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
313299ebb4caSwyllys cred->cred, cred->credlen,
313399ebb4caSwyllys NULL, 0, PKCS12_DEFAULT_ITER, p8);
313499ebb4caSwyllys
313599ebb4caSwyllys /* Clean up the PKCS#8 shrouded key, don't need it now. */
313699ebb4caSwyllys PKCS8_PRIV_KEY_INFO_free(p8);
313799ebb4caSwyllys p8 = NULL;
313899ebb4caSwyllys
313999ebb4caSwyllys if (bag == NULL) {
31405b3e1433Swyllys return (NULL);
314199ebb4caSwyllys }
31425b3e1433Swyllys if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
31435b3e1433Swyllys goto out;
31445b3e1433Swyllys if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
31455b3e1433Swyllys goto out;
31465b3e1433Swyllys
314799ebb4caSwyllys /* Start a PKCS#12 safebag container for the private key. */
314899ebb4caSwyllys bag_stack = sk_PKCS12_SAFEBAG_new_null();
31495b3e1433Swyllys if (bag_stack == NULL)
31505b3e1433Swyllys goto out;
315199ebb4caSwyllys
315299ebb4caSwyllys /* Pile on the private key on the bag_stack. */
31535b3e1433Swyllys if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
31545b3e1433Swyllys goto out;
31555b3e1433Swyllys
315699ebb4caSwyllys key_authsafe = PKCS12_pack_p7data(bag_stack);
315799ebb4caSwyllys
31585b3e1433Swyllys out:
31595b3e1433Swyllys if (bag_stack != NULL)
316099ebb4caSwyllys sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
316199ebb4caSwyllys bag_stack = NULL;
31625b3e1433Swyllys return (key_authsafe);
316399ebb4caSwyllys }
316499ebb4caSwyllys
316599ebb4caSwyllys static EVP_PKEY *
ImportRawRSAKey(KMF_RAW_RSA_KEY * key)316699ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
316799ebb4caSwyllys {
316899ebb4caSwyllys RSA *rsa = NULL;
316999ebb4caSwyllys EVP_PKEY *newkey = NULL;
31704942e222SAndy Fiddaman BIGNUM *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL;
31714942e222SAndy Fiddaman BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
317299ebb4caSwyllys
317399ebb4caSwyllys if ((rsa = RSA_new()) == NULL)
3174300fdee2SAndy Fiddaman goto cleanup;
317599ebb4caSwyllys
3176300fdee2SAndy Fiddaman if ((n = BN_bin2bn(key->mod.val, key->mod.len, NULL)) == NULL)
3177300fdee2SAndy Fiddaman goto cleanup;
317899ebb4caSwyllys
3179300fdee2SAndy Fiddaman if ((e = BN_bin2bn(key->pubexp.val, key->pubexp.len, NULL)) == NULL)
3180300fdee2SAndy Fiddaman goto cleanup;
318199ebb4caSwyllys
3182300fdee2SAndy Fiddaman if (key->priexp.val != NULL &&
3183300fdee2SAndy Fiddaman (d = BN_bin2bn(key->priexp.val, key->priexp.len, NULL)) == NULL)
3184300fdee2SAndy Fiddaman goto cleanup;
318599ebb4caSwyllys
3186300fdee2SAndy Fiddaman if (key->prime1.val != NULL &&
3187300fdee2SAndy Fiddaman (p = BN_bin2bn(key->prime1.val, key->prime1.len, NULL)) == NULL)
3188300fdee2SAndy Fiddaman goto cleanup;
318999ebb4caSwyllys
3190300fdee2SAndy Fiddaman if (key->prime2.val != NULL &&
3191300fdee2SAndy Fiddaman (q = BN_bin2bn(key->prime2.val, key->prime2.len, NULL)) == NULL)
3192300fdee2SAndy Fiddaman goto cleanup;
319399ebb4caSwyllys
3194300fdee2SAndy Fiddaman if (key->exp1.val != NULL &&
3195300fdee2SAndy Fiddaman (dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len, NULL)) == NULL)
3196300fdee2SAndy Fiddaman goto cleanup;
319799ebb4caSwyllys
3198300fdee2SAndy Fiddaman if (key->exp2.val != NULL &&
3199300fdee2SAndy Fiddaman (dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len, NULL)) == NULL)
3200300fdee2SAndy Fiddaman goto cleanup;
320199ebb4caSwyllys
3202300fdee2SAndy Fiddaman if (key->coef.val != NULL &&
3203300fdee2SAndy Fiddaman (iqmp = BN_bin2bn(key->coef.val, key->coef.len, NULL)) == NULL)
3204300fdee2SAndy Fiddaman goto cleanup;
3205300fdee2SAndy Fiddaman
3206300fdee2SAndy Fiddaman if (RSA_set0_key(rsa, n, e, d) == 0)
3207300fdee2SAndy Fiddaman goto cleanup;
3208300fdee2SAndy Fiddaman n = e = d = NULL;
3209300fdee2SAndy Fiddaman if (RSA_set0_factors(rsa, p, q) == 0)
3210300fdee2SAndy Fiddaman goto cleanup;
3211300fdee2SAndy Fiddaman p = q = NULL;
3212300fdee2SAndy Fiddaman if (RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp) == 0)
3213300fdee2SAndy Fiddaman goto cleanup;
3214300fdee2SAndy Fiddaman dmp1 = dmq1 = iqmp = NULL;
321599ebb4caSwyllys
321699ebb4caSwyllys if ((newkey = EVP_PKEY_new()) == NULL)
3217300fdee2SAndy Fiddaman goto cleanup;
321899ebb4caSwyllys
321999ebb4caSwyllys (void) EVP_PKEY_set1_RSA(newkey, rsa);
322099ebb4caSwyllys
3221300fdee2SAndy Fiddaman cleanup:
322299ebb4caSwyllys /* The original key must be freed once here or it leaks memory */
3223300fdee2SAndy Fiddaman if (rsa)
322499ebb4caSwyllys RSA_free(rsa);
3225300fdee2SAndy Fiddaman BN_free(n);
3226300fdee2SAndy Fiddaman BN_free(e);
3227300fdee2SAndy Fiddaman BN_free(d);
3228300fdee2SAndy Fiddaman BN_free(p);
3229300fdee2SAndy Fiddaman BN_free(q);
3230300fdee2SAndy Fiddaman BN_free(dmp1);
3231300fdee2SAndy Fiddaman BN_free(dmq1);
3232300fdee2SAndy Fiddaman BN_free(iqmp);
323399ebb4caSwyllys
323499ebb4caSwyllys return (newkey);
323599ebb4caSwyllys }
323699ebb4caSwyllys
323799ebb4caSwyllys static EVP_PKEY *
ImportRawDSAKey(KMF_RAW_DSA_KEY * key)323899ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
323999ebb4caSwyllys {
324099ebb4caSwyllys DSA *dsa = NULL;
324199ebb4caSwyllys EVP_PKEY *newkey = NULL;
32424942e222SAndy Fiddaman BIGNUM *p = NULL, *q = NULL, *g = NULL;
32434942e222SAndy Fiddaman BIGNUM *priv_key = NULL, *pub_key = NULL;
324499ebb4caSwyllys
324599ebb4caSwyllys if ((dsa = DSA_new()) == NULL)
3246300fdee2SAndy Fiddaman goto cleanup;
324799ebb4caSwyllys
3248300fdee2SAndy Fiddaman if ((p = BN_bin2bn(key->prime.val, key->prime.len, NULL)) == NULL)
3249300fdee2SAndy Fiddaman goto cleanup;
325099ebb4caSwyllys
3251300fdee2SAndy Fiddaman if ((q = BN_bin2bn(key->subprime.val, key->subprime.len, NULL)) == NULL)
3252300fdee2SAndy Fiddaman goto cleanup;
325399ebb4caSwyllys
3254300fdee2SAndy Fiddaman if ((g = BN_bin2bn(key->base.val, key->base.len, NULL)) == NULL)
3255300fdee2SAndy Fiddaman goto cleanup;
325699ebb4caSwyllys
3257300fdee2SAndy Fiddaman if ((priv_key = BN_bin2bn(key->value.val, key->value.len,
3258300fdee2SAndy Fiddaman NULL)) == NULL)
3259300fdee2SAndy Fiddaman goto cleanup;
326099ebb4caSwyllys
3261300fdee2SAndy Fiddaman if (key->pubvalue.val != NULL && (pub_key =
3262300fdee2SAndy Fiddaman BN_bin2bn(key->pubvalue.val, key->pubvalue.len, NULL)) == NULL)
3263300fdee2SAndy Fiddaman goto cleanup;
3264300fdee2SAndy Fiddaman
3265300fdee2SAndy Fiddaman if (DSA_set0_pqg(dsa, p, q, g) == 0)
3266300fdee2SAndy Fiddaman goto cleanup;
3267300fdee2SAndy Fiddaman p = q = g = NULL;
3268300fdee2SAndy Fiddaman if (DSA_set0_key(dsa, pub_key, priv_key) == 0)
3269300fdee2SAndy Fiddaman goto cleanup;
3270300fdee2SAndy Fiddaman pub_key = priv_key = 0;
327130a5e8faSwyllys
327299ebb4caSwyllys if ((newkey = EVP_PKEY_new()) == NULL)
3273300fdee2SAndy Fiddaman goto cleanup;
327499ebb4caSwyllys
327599ebb4caSwyllys (void) EVP_PKEY_set1_DSA(newkey, dsa);
327699ebb4caSwyllys
3277300fdee2SAndy Fiddaman cleanup:
327899ebb4caSwyllys /* The original key must be freed once here or it leaks memory */
3279300fdee2SAndy Fiddaman if (dsa)
328099ebb4caSwyllys DSA_free(dsa);
3281300fdee2SAndy Fiddaman BN_free(p);
3282300fdee2SAndy Fiddaman BN_free(q);
3283300fdee2SAndy Fiddaman BN_free(g);
3284300fdee2SAndy Fiddaman BN_free(priv_key);
3285300fdee2SAndy Fiddaman BN_free(pub_key);
3286300fdee2SAndy Fiddaman
328799ebb4caSwyllys return (newkey);
328899ebb4caSwyllys }
328999ebb4caSwyllys
32905b3e1433Swyllys static EVP_PKEY *
raw_key_to_pkey(KMF_KEY_HANDLE * key)32915b3e1433Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key)
32925b3e1433Swyllys {
32935b3e1433Swyllys EVP_PKEY *pkey = NULL;
32945b3e1433Swyllys KMF_RAW_KEY_DATA *rawkey;
32955b3e1433Swyllys ASN1_TYPE *attr = NULL;
32965b3e1433Swyllys KMF_RETURN ret;
32975b3e1433Swyllys
32985b3e1433Swyllys if (key == NULL || !key->israw)
32995b3e1433Swyllys return (NULL);
33005b3e1433Swyllys
33015b3e1433Swyllys rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
33025b3e1433Swyllys if (rawkey->keytype == KMF_RSA) {
33035b3e1433Swyllys pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
33045b3e1433Swyllys } else if (rawkey->keytype == KMF_DSA) {
33055b3e1433Swyllys pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
3306e65e5c2dSWyllys Ingersoll } else if (rawkey->keytype == KMF_ECDSA) {
3307e65e5c2dSWyllys Ingersoll /*
3308e65e5c2dSWyllys Ingersoll * OpenSSL in Solaris does not support EC for
3309e65e5c2dSWyllys Ingersoll * legal reasons
3310e65e5c2dSWyllys Ingersoll */
3311e65e5c2dSWyllys Ingersoll return (NULL);
33125b3e1433Swyllys } else {
33135b3e1433Swyllys /* wrong kind of key */
33145b3e1433Swyllys return (NULL);
33155b3e1433Swyllys }
33165b3e1433Swyllys
33175b3e1433Swyllys if (rawkey->label != NULL) {
33185b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) {
33195b3e1433Swyllys EVP_PKEY_free(pkey);
33205b3e1433Swyllys return (NULL);
33215b3e1433Swyllys }
33225b3e1433Swyllys attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
33235b3e1433Swyllys (void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
33245b3e1433Swyllys strlen(rawkey->label));
33255b3e1433Swyllys attr->type = V_ASN1_BMPSTRING;
33265b3e1433Swyllys attr->value.ptr = (char *)attr->value.bmpstring;
33275b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
33285b3e1433Swyllys if (ret != KMF_OK) {
33295b3e1433Swyllys EVP_PKEY_free(pkey);
33305b3e1433Swyllys ASN1_TYPE_free(attr);
33315b3e1433Swyllys return (NULL);
33325b3e1433Swyllys }
33335b3e1433Swyllys }
33345b3e1433Swyllys if (rawkey->id.Data != NULL) {
33355b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) {
33365b3e1433Swyllys EVP_PKEY_free(pkey);
33375b3e1433Swyllys return (NULL);
33385b3e1433Swyllys }
33395b3e1433Swyllys attr->value.octet_string =
33405b3e1433Swyllys ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
33415b3e1433Swyllys attr->type = V_ASN1_OCTET_STRING;
33425b3e1433Swyllys (void) ASN1_STRING_set(attr->value.octet_string,
33435b3e1433Swyllys rawkey->id.Data, rawkey->id.Length);
33445b3e1433Swyllys attr->value.ptr = (char *)attr->value.octet_string;
33455b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
33465b3e1433Swyllys if (ret != KMF_OK) {
33475b3e1433Swyllys EVP_PKEY_free(pkey);
33485b3e1433Swyllys ASN1_TYPE_free(attr);
33495b3e1433Swyllys return (NULL);
33505b3e1433Swyllys }
33515b3e1433Swyllys }
33525b3e1433Swyllys return (pkey);
33535b3e1433Swyllys }
33545b3e1433Swyllys
33555b3e1433Swyllys /*
33565b3e1433Swyllys * Search a list of private keys to find one that goes with the certificate.
33575b3e1433Swyllys */
33585b3e1433Swyllys static EVP_PKEY *
find_matching_key(X509 * xcert,int numkeys,KMF_KEY_HANDLE * keylist)33595b3e1433Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
33605b3e1433Swyllys {
33615b3e1433Swyllys int i;
33625b3e1433Swyllys EVP_PKEY *pkey = NULL;
33635b3e1433Swyllys
33645b3e1433Swyllys if (numkeys == 0 || keylist == NULL || xcert == NULL)
33655b3e1433Swyllys return (NULL);
33665b3e1433Swyllys for (i = 0; i < numkeys; i++) {
33675b3e1433Swyllys if (keylist[i].israw)
33685b3e1433Swyllys pkey = raw_key_to_pkey(&keylist[i]);
33695b3e1433Swyllys else
33705b3e1433Swyllys pkey = (EVP_PKEY *)keylist[i].keyp;
33715b3e1433Swyllys if (pkey != NULL) {
33725b3e1433Swyllys if (X509_check_private_key(xcert, pkey)) {
33735b3e1433Swyllys return (pkey);
33745b3e1433Swyllys } else {
33755b3e1433Swyllys EVP_PKEY_free(pkey);
33765b3e1433Swyllys pkey = NULL;
33775b3e1433Swyllys }
33785b3e1433Swyllys }
33795b3e1433Swyllys }
33805b3e1433Swyllys return (pkey);
33815b3e1433Swyllys }
33825b3e1433Swyllys
338399ebb4caSwyllys static KMF_RETURN
local_export_pk12(KMF_HANDLE_T handle,KMF_CREDENTIAL * cred,int numcerts,KMF_X509_DER_CERT * certlist,int numkeys,KMF_KEY_HANDLE * keylist,char * filename)33844942e222SAndy Fiddaman local_export_pk12(KMF_HANDLE_T handle, KMF_CREDENTIAL *cred, int numcerts,
33854942e222SAndy Fiddaman KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
338699ebb4caSwyllys char *filename)
338799ebb4caSwyllys {
338899ebb4caSwyllys KMF_RETURN rv = KMF_OK;
338999ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
339099ebb4caSwyllys BIO *bio = NULL;
33915b3e1433Swyllys PKCS7 *cert_authsafe = NULL;
33925b3e1433Swyllys PKCS7 *key_authsafe = NULL;
33935b3e1433Swyllys STACK_OF(PKCS7) *authsafe_stack = NULL;
33945b3e1433Swyllys PKCS12 *p12_elem = NULL;
339599ebb4caSwyllys int i;
339699ebb4caSwyllys
33975b3e1433Swyllys if (numcerts == 0 && numkeys == 0)
33985b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER);
33995b3e1433Swyllys
340099ebb4caSwyllys /*
340199ebb4caSwyllys * Open the output file.
340299ebb4caSwyllys */
340399ebb4caSwyllys if ((bio = BIO_new_file(filename, "wb")) == NULL) {
340499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
340599ebb4caSwyllys rv = KMF_ERR_OPEN_FILE;
340699ebb4caSwyllys goto cleanup;
340799ebb4caSwyllys }
340899ebb4caSwyllys
34095b3e1433Swyllys /* Start a PKCS#7 stack. */
34105b3e1433Swyllys authsafe_stack = sk_PKCS7_new_null();
34115b3e1433Swyllys if (authsafe_stack == NULL) {
34125b3e1433Swyllys rv = KMF_ERR_MEMORY;
34135b3e1433Swyllys goto cleanup;
34145b3e1433Swyllys }
34155b3e1433Swyllys if (numcerts > 0) {
341699ebb4caSwyllys for (i = 0; rv == KMF_OK && i < numcerts; i++) {
341799ebb4caSwyllys const uchar_t *p = certlist[i].certificate.Data;
341899ebb4caSwyllys long len = certlist[i].certificate.Length;
34195b3e1433Swyllys X509 *xcert = NULL;
34205b3e1433Swyllys EVP_PKEY *pkey = NULL;
34215b3e1433Swyllys unsigned char keyid[EVP_MAX_MD_SIZE];
34225b3e1433Swyllys unsigned int keyidlen = 0;
342399ebb4caSwyllys
342499ebb4caSwyllys xcert = d2i_X509(NULL, &p, len);
342599ebb4caSwyllys if (xcert == NULL) {
342699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
342799ebb4caSwyllys rv = KMF_ERR_ENCODING;
342899ebb4caSwyllys }
34295b3e1433Swyllys if (certlist[i].kmf_private.label != NULL) {
34305b3e1433Swyllys /* Set alias attribute */
34315b3e1433Swyllys (void) X509_alias_set1(xcert,
34325b3e1433Swyllys (uchar_t *)certlist[i].kmf_private.label,
34335b3e1433Swyllys strlen(certlist[i].kmf_private.label));
34345b3e1433Swyllys }
34355b3e1433Swyllys /* Check if there is a key corresponding to this cert */
34365b3e1433Swyllys pkey = find_matching_key(xcert, numkeys, keylist);
34375b3e1433Swyllys
34385b3e1433Swyllys /*
34395b3e1433Swyllys * If key is found, get fingerprint and create a
34405b3e1433Swyllys * safebag.
34415b3e1433Swyllys */
34425b3e1433Swyllys if (pkey != NULL) {
34435b3e1433Swyllys (void) X509_digest(xcert, EVP_sha1(),
34445b3e1433Swyllys keyid, &keyidlen);
34455b3e1433Swyllys key_authsafe = add_key_to_safe(pkey, cred,
34465b3e1433Swyllys keyid, keyidlen,
34475b3e1433Swyllys certlist[i].kmf_private.label,
34485b3e1433Swyllys (certlist[i].kmf_private.label ?
34495b3e1433Swyllys strlen(certlist[i].kmf_private.label) : 0));
34505b3e1433Swyllys
34515b3e1433Swyllys if (key_authsafe == NULL) {
34525b3e1433Swyllys X509_free(xcert);
34535b3e1433Swyllys EVP_PKEY_free(pkey);
34545b3e1433Swyllys goto cleanup;
34555b3e1433Swyllys }
34565b3e1433Swyllys /* Put the key safe into the Auth Safe */
34575b3e1433Swyllys if (!sk_PKCS7_push(authsafe_stack,
34585b3e1433Swyllys key_authsafe)) {
34595b3e1433Swyllys X509_free(xcert);
34605b3e1433Swyllys EVP_PKEY_free(pkey);
34615b3e1433Swyllys goto cleanup;
34625b3e1433Swyllys }
34635b3e1433Swyllys }
34645b3e1433Swyllys
34655b3e1433Swyllys /* create a certificate safebag */
34665b3e1433Swyllys cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
34675b3e1433Swyllys keyidlen);
34685b3e1433Swyllys if (cert_authsafe == NULL) {
34695b3e1433Swyllys X509_free(xcert);
34705b3e1433Swyllys EVP_PKEY_free(pkey);
34715b3e1433Swyllys goto cleanup;
34725b3e1433Swyllys }
34735b3e1433Swyllys if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
34745b3e1433Swyllys X509_free(xcert);
34755b3e1433Swyllys EVP_PKEY_free(pkey);
34765b3e1433Swyllys goto cleanup;
34775b3e1433Swyllys }
34785b3e1433Swyllys
347999ebb4caSwyllys X509_free(xcert);
348099ebb4caSwyllys if (pkey)
348199ebb4caSwyllys EVP_PKEY_free(pkey);
348299ebb4caSwyllys }
34835b3e1433Swyllys } else if (numcerts == 0 && numkeys > 0) {
34845b3e1433Swyllys /*
34855b3e1433Swyllys * If only adding keys to the file.
34865b3e1433Swyllys */
34875b3e1433Swyllys for (i = 0; i < numkeys; i++) {
34885b3e1433Swyllys EVP_PKEY *pkey = NULL;
34895b3e1433Swyllys
34905b3e1433Swyllys if (keylist[i].israw)
34915b3e1433Swyllys pkey = raw_key_to_pkey(&keylist[i]);
34925b3e1433Swyllys else
34935b3e1433Swyllys pkey = (EVP_PKEY *)keylist[i].keyp;
34945b3e1433Swyllys
34955b3e1433Swyllys if (pkey == NULL)
34965b3e1433Swyllys continue;
34975b3e1433Swyllys
34985b3e1433Swyllys key_authsafe = add_key_to_safe(pkey, cred,
34995b3e1433Swyllys NULL, 0, NULL, 0);
35005b3e1433Swyllys
35015b3e1433Swyllys if (key_authsafe == NULL) {
35025b3e1433Swyllys EVP_PKEY_free(pkey);
35035b3e1433Swyllys goto cleanup;
35045b3e1433Swyllys }
35055b3e1433Swyllys if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
35065b3e1433Swyllys EVP_PKEY_free(pkey);
35075b3e1433Swyllys goto cleanup;
35085b3e1433Swyllys }
35095b3e1433Swyllys }
35105b3e1433Swyllys }
35115b3e1433Swyllys p12_elem = PKCS12_init(NID_pkcs7_data);
35125b3e1433Swyllys if (p12_elem == NULL) {
35135b3e1433Swyllys goto cleanup;
351499ebb4caSwyllys }
351599ebb4caSwyllys
35165b3e1433Swyllys /* Put the PKCS#7 stack into the PKCS#12 element. */
35175b3e1433Swyllys if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
35185b3e1433Swyllys goto cleanup;
35195b3e1433Swyllys }
35205b3e1433Swyllys
35215b3e1433Swyllys /* Set the integrity MAC on the PKCS#12 element. */
35225b3e1433Swyllys if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
35235b3e1433Swyllys NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
35245b3e1433Swyllys goto cleanup;
35255b3e1433Swyllys }
35265b3e1433Swyllys
35275b3e1433Swyllys /* Write the PKCS#12 element to the export file. */
35285b3e1433Swyllys if (!i2d_PKCS12_bio(bio, p12_elem)) {
35295b3e1433Swyllys goto cleanup;
35305b3e1433Swyllys }
35315b3e1433Swyllys PKCS12_free(p12_elem);
35325b3e1433Swyllys
353399ebb4caSwyllys cleanup:
35345b3e1433Swyllys /* Clear away the PKCS#7 stack, we're done with it. */
35355b3e1433Swyllys if (authsafe_stack)
35365b3e1433Swyllys sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
353799ebb4caSwyllys
353899ebb4caSwyllys if (bio != NULL)
353999ebb4caSwyllys (void) BIO_free_all(bio);
354099ebb4caSwyllys
354199ebb4caSwyllys return (rv);
354299ebb4caSwyllys }
354399ebb4caSwyllys
354499ebb4caSwyllys KMF_RETURN
openssl_build_pk12(KMF_HANDLE_T handle,int numcerts,KMF_X509_DER_CERT * certlist,int numkeys,KMF_KEY_HANDLE * keylist,KMF_CREDENTIAL * p12cred,char * filename)354530a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
354630a5e8faSwyllys KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
354730a5e8faSwyllys KMF_CREDENTIAL *p12cred, char *filename)
354830a5e8faSwyllys {
354930a5e8faSwyllys KMF_RETURN rv;
355030a5e8faSwyllys
355130a5e8faSwyllys if (certlist == NULL && keylist == NULL)
355230a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
355330a5e8faSwyllys
35545b3e1433Swyllys rv = local_export_pk12(handle, p12cred, numcerts, certlist,
355530a5e8faSwyllys numkeys, keylist, filename);
355630a5e8faSwyllys
355730a5e8faSwyllys return (rv);
355830a5e8faSwyllys }
355930a5e8faSwyllys
356030a5e8faSwyllys KMF_RETURN
OpenSSL_ExportPK12(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)356130a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
356299ebb4caSwyllys {
356399ebb4caSwyllys KMF_RETURN rv;
356499ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
356599ebb4caSwyllys char *fullpath = NULL;
356630a5e8faSwyllys char *dirpath = NULL;
356730a5e8faSwyllys char *certfile = NULL;
356830a5e8faSwyllys char *keyfile = NULL;
356930a5e8faSwyllys char *filename = NULL;
357030a5e8faSwyllys KMF_CREDENTIAL *p12cred = NULL;
35715b3e1433Swyllys KMF_X509_DER_CERT certdata;
35725b3e1433Swyllys KMF_KEY_HANDLE key;
35735b3e1433Swyllys int gotkey = 0;
35745b3e1433Swyllys int gotcert = 0;
357530a5e8faSwyllys
357630a5e8faSwyllys if (handle == NULL)
357730a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
357899ebb4caSwyllys
357999ebb4caSwyllys /*
358099ebb4caSwyllys * First, find the certificate.
358199ebb4caSwyllys */
358230a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
358330a5e8faSwyllys certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
358430a5e8faSwyllys if (certfile != NULL) {
358530a5e8faSwyllys fullpath = get_fullpath(dirpath, certfile);
358699ebb4caSwyllys if (fullpath == NULL)
358799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
358899ebb4caSwyllys
358999ebb4caSwyllys if (isdir(fullpath)) {
359099ebb4caSwyllys free(fullpath);
359199ebb4caSwyllys return (KMF_ERR_AMBIGUOUS_PATHNAME);
359299ebb4caSwyllys }
359399ebb4caSwyllys
35945b3e1433Swyllys (void) memset(&certdata, 0, sizeof (certdata));
3595f810c7e5SToomas Soome rv = kmf_load_cert(kmfh, NULL, NULL, NULL, 0,
35965b3e1433Swyllys fullpath, &certdata.certificate);
359799ebb4caSwyllys if (rv != KMF_OK)
359899ebb4caSwyllys goto end;
359930a5e8faSwyllys
36005b3e1433Swyllys gotcert++;
36015b3e1433Swyllys certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
360230a5e8faSwyllys free(fullpath);
360399ebb4caSwyllys }
360499ebb4caSwyllys
360599ebb4caSwyllys /*
360699ebb4caSwyllys * Now find the private key.
360799ebb4caSwyllys */
360830a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
360930a5e8faSwyllys if (keyfile != NULL) {
361030a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile);
361199ebb4caSwyllys if (fullpath == NULL)
361299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
361399ebb4caSwyllys
361499ebb4caSwyllys if (isdir(fullpath)) {
361599ebb4caSwyllys free(fullpath);
361699ebb4caSwyllys return (KMF_ERR_AMBIGUOUS_PATHNAME);
361799ebb4caSwyllys }
361899ebb4caSwyllys
36195b3e1433Swyllys (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
36205b3e1433Swyllys rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
36215b3e1433Swyllys if (rv != KMF_OK)
362299ebb4caSwyllys goto end;
36235b3e1433Swyllys gotkey++;
362499ebb4caSwyllys }
362599ebb4caSwyllys
362699ebb4caSwyllys /*
362799ebb4caSwyllys * Open the output file.
362899ebb4caSwyllys */
362930a5e8faSwyllys filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
363030a5e8faSwyllys numattr);
363130a5e8faSwyllys if (filename == NULL) {
363230a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER;
363330a5e8faSwyllys goto end;
363430a5e8faSwyllys }
363530a5e8faSwyllys
363699ebb4caSwyllys /* Stick the key and the cert into a PKCS#12 file */
363730a5e8faSwyllys p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
363830a5e8faSwyllys if (p12cred == NULL) {
363930a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER;
364030a5e8faSwyllys goto end;
364130a5e8faSwyllys }
364230a5e8faSwyllys
36435b3e1433Swyllys rv = local_export_pk12(handle, p12cred, 1, &certdata,
36445b3e1433Swyllys 1, &key, filename);
364599ebb4caSwyllys
364699ebb4caSwyllys end:
364799ebb4caSwyllys if (fullpath)
364899ebb4caSwyllys free(fullpath);
364999ebb4caSwyllys
36505b3e1433Swyllys if (gotcert)
36515b3e1433Swyllys kmf_free_kmf_cert(handle, &certdata);
36525b3e1433Swyllys if (gotkey)
36535b3e1433Swyllys kmf_free_kmf_key(handle, &key);
365499ebb4caSwyllys return (rv);
365599ebb4caSwyllys }
365699ebb4caSwyllys
365771593db2Swyllys /*
365871593db2Swyllys * Helper function to extract keys and certificates from
365971593db2Swyllys * a single PEM file. Typically the file should contain a
366071593db2Swyllys * private key and an associated public key wrapped in an x509 cert.
366171593db2Swyllys * However, the file may be just a list of X509 certs with no keys.
366271593db2Swyllys */
366371593db2Swyllys static KMF_RETURN
extract_pem(KMF_HANDLE * kmfh,char * issuer,char * subject,KMF_BIGINT * serial,char * filename,CK_UTF8CHAR * pin,CK_ULONG pinlen,EVP_PKEY ** priv_key,KMF_DATA ** certs,int * numcerts)36644942e222SAndy Fiddaman extract_pem(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
36654942e222SAndy Fiddaman char *filename, CK_UTF8CHAR *pin, CK_ULONG pinlen, EVP_PKEY **priv_key,
36664942e222SAndy Fiddaman KMF_DATA **certs, int *numcerts)
366771593db2Swyllys {
366871593db2Swyllys KMF_RETURN rv = KMF_OK;
366971593db2Swyllys FILE *fp;
367034acef67Swyllys STACK_OF(X509_INFO) *x509_info_stack = NULL;
367102744e81Swyllys int i, ncerts = 0, matchcerts = 0;
367271593db2Swyllys EVP_PKEY *pkey = NULL;
367371593db2Swyllys X509_INFO *info;
367471593db2Swyllys X509 *x;
36755b3e1433Swyllys X509_INFO **cert_infos = NULL;
367671593db2Swyllys KMF_DATA *certlist = NULL;
367771593db2Swyllys
367871593db2Swyllys if (priv_key)
367971593db2Swyllys *priv_key = NULL;
368071593db2Swyllys if (certs)
368171593db2Swyllys *certs = NULL;
368271593db2Swyllys fp = fopen(filename, "r");
36835b3e1433Swyllys if (fp == NULL)
368471593db2Swyllys return (KMF_ERR_OPEN_FILE);
36855b3e1433Swyllys
368671593db2Swyllys x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
368771593db2Swyllys if (x509_info_stack == NULL) {
368871593db2Swyllys (void) fclose(fp);
368971593db2Swyllys return (KMF_ERR_ENCODING);
369071593db2Swyllys }
36915b3e1433Swyllys cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
36925b3e1433Swyllys sizeof (X509_INFO *));
36935b3e1433Swyllys if (cert_infos == NULL) {
36945b3e1433Swyllys (void) fclose(fp);
36955b3e1433Swyllys rv = KMF_ERR_MEMORY;
36965b3e1433Swyllys goto err;
36975b3e1433Swyllys }
369871593db2Swyllys
36995b3e1433Swyllys for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
370034acef67Swyllys cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
370171593db2Swyllys ncerts++;
370271593db2Swyllys }
370371593db2Swyllys
370471593db2Swyllys if (ncerts == 0) {
370571593db2Swyllys (void) fclose(fp);
370634acef67Swyllys rv = KMF_ERR_CERT_NOT_FOUND;
370734acef67Swyllys goto err;
370871593db2Swyllys }
370971593db2Swyllys
371071593db2Swyllys if (priv_key != NULL) {
371171593db2Swyllys rewind(fp);
371271593db2Swyllys pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
371371593db2Swyllys }
371471593db2Swyllys (void) fclose(fp);
371571593db2Swyllys
371671593db2Swyllys x = cert_infos[ncerts - 1]->x509;
371771593db2Swyllys /*
371871593db2Swyllys * Make sure the private key matchs the last cert in the file.
371971593db2Swyllys */
372071593db2Swyllys if (pkey != NULL && !X509_check_private_key(x, pkey)) {
372171593db2Swyllys EVP_PKEY_free(pkey);
372234acef67Swyllys rv = KMF_ERR_KEY_MISMATCH;
372334acef67Swyllys goto err;
372471593db2Swyllys }
372571593db2Swyllys
3726a2d4930dSDan OpenSolaris Anderson certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
372771593db2Swyllys if (certlist == NULL) {
372871593db2Swyllys if (pkey != NULL)
372971593db2Swyllys EVP_PKEY_free(pkey);
373034acef67Swyllys rv = KMF_ERR_MEMORY;
373134acef67Swyllys goto err;
373271593db2Swyllys }
373371593db2Swyllys
373471593db2Swyllys /*
373571593db2Swyllys * Convert all of the certs to DER format.
373671593db2Swyllys */
373702744e81Swyllys matchcerts = 0;
373871593db2Swyllys for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
373902744e81Swyllys boolean_t match = FALSE;
374071593db2Swyllys info = cert_infos[ncerts - 1 - i];
374171593db2Swyllys
374230a5e8faSwyllys rv = check_cert(info->x509, issuer, subject, serial, &match);
374302744e81Swyllys if (rv != KMF_OK || match != TRUE) {
374402744e81Swyllys rv = KMF_OK;
374502744e81Swyllys continue;
374602744e81Swyllys }
374702744e81Swyllys
374802744e81Swyllys rv = ssl_cert2KMFDATA(kmfh, info->x509,
374902744e81Swyllys &certlist[matchcerts++]);
375071593db2Swyllys
375171593db2Swyllys if (rv != KMF_OK) {
3752e65e5c2dSWyllys Ingersoll int j;
3753e65e5c2dSWyllys Ingersoll for (j = 0; j < matchcerts; j++)
3754e65e5c2dSWyllys Ingersoll kmf_free_data(&certlist[j]);
375571593db2Swyllys free(certlist);
375671593db2Swyllys certlist = NULL;
375702744e81Swyllys ncerts = matchcerts = 0;
375871593db2Swyllys }
375971593db2Swyllys }
376071593db2Swyllys
376171593db2Swyllys if (numcerts != NULL)
376202744e81Swyllys *numcerts = matchcerts;
3763a2d4930dSDan OpenSolaris Anderson
3764e65e5c2dSWyllys Ingersoll if (certs != NULL)
376571593db2Swyllys *certs = certlist;
3766e65e5c2dSWyllys Ingersoll else if (certlist != NULL) {
3767e65e5c2dSWyllys Ingersoll for (i = 0; i < ncerts; i++)
3768e65e5c2dSWyllys Ingersoll kmf_free_data(&certlist[i]);
3769a2d4930dSDan OpenSolaris Anderson free(certlist);
3770a2d4930dSDan OpenSolaris Anderson certlist = NULL;
3771a2d4930dSDan OpenSolaris Anderson }
377271593db2Swyllys
377371593db2Swyllys if (priv_key == NULL && pkey != NULL)
377471593db2Swyllys EVP_PKEY_free(pkey);
377571593db2Swyllys else if (priv_key != NULL && pkey != NULL)
377671593db2Swyllys *priv_key = pkey;
377771593db2Swyllys
377834acef67Swyllys err:
377934acef67Swyllys /* Cleanup the stack of X509 info records */
378034acef67Swyllys for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
378134acef67Swyllys info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
378234acef67Swyllys X509_INFO_free(info);
378334acef67Swyllys }
378434acef67Swyllys if (x509_info_stack)
378534acef67Swyllys sk_X509_INFO_free(x509_info_stack);
378634acef67Swyllys
37875b3e1433Swyllys if (cert_infos != NULL)
37885b3e1433Swyllys free(cert_infos);
37895b3e1433Swyllys
379071593db2Swyllys return (rv);
379171593db2Swyllys }
379271593db2Swyllys
37935b3e1433Swyllys static KMF_RETURN
openssl_parse_bags(const STACK_OF (PKCS12_SAFEBAG)* bags,char * pin,STACK_OF (EVP_PKEY)* keys,STACK_OF (X509)* certs)3794300fdee2SAndy Fiddaman openssl_parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
37955b3e1433Swyllys STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
37965b3e1433Swyllys {
37975b3e1433Swyllys KMF_RETURN ret;
37985b3e1433Swyllys int i;
37995b3e1433Swyllys
38005b3e1433Swyllys for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
38015b3e1433Swyllys PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
38025b3e1433Swyllys ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
38035b3e1433Swyllys keys, certs);
38045b3e1433Swyllys
38055b3e1433Swyllys if (ret != KMF_OK)
38065b3e1433Swyllys return (ret);
38075b3e1433Swyllys }
38085b3e1433Swyllys
38095b3e1433Swyllys return (ret);
38105b3e1433Swyllys }
38115b3e1433Swyllys
38125b3e1433Swyllys static KMF_RETURN
set_pkey_attrib(EVP_PKEY * pkey,ASN1_TYPE * attrib,int nid)38135b3e1433Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
38145b3e1433Swyllys {
38155b3e1433Swyllys X509_ATTRIBUTE *attr = NULL;
38165b3e1433Swyllys
38175b3e1433Swyllys if (pkey == NULL || attrib == NULL)
38185b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER);
38195b3e1433Swyllys
38205b3e1433Swyllys attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
38215b3e1433Swyllys if (attr != NULL) {
38225b3e1433Swyllys int i;
3823300fdee2SAndy Fiddaman
3824300fdee2SAndy Fiddaman if ((i = EVP_PKEY_get_attr_by_NID(pkey, nid, -1)) != -1)
3825300fdee2SAndy Fiddaman (void) EVP_PKEY_delete_attr(pkey, i);
3826300fdee2SAndy Fiddaman if (EVP_PKEY_add1_attr(pkey, attr) == 0) {
38275b3e1433Swyllys X509_ATTRIBUTE_free(attr);
38285b3e1433Swyllys return (KMF_ERR_MEMORY);
38295b3e1433Swyllys }
38305b3e1433Swyllys } else {
38315b3e1433Swyllys return (KMF_ERR_MEMORY);
38325b3e1433Swyllys }
38335b3e1433Swyllys
38345b3e1433Swyllys return (KMF_OK);
38355b3e1433Swyllys }
38365b3e1433Swyllys
38375b3e1433Swyllys static KMF_RETURN
openssl_parse_bag(PKCS12_SAFEBAG * bag,char * pass,int passlen,STACK_OF (EVP_PKEY)* keylist,STACK_OF (X509)* certlist)38385b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
38395b3e1433Swyllys STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
38405b3e1433Swyllys {
38415b3e1433Swyllys KMF_RETURN ret = KMF_OK;
38425b3e1433Swyllys PKCS8_PRIV_KEY_INFO *p8 = NULL;
38435b3e1433Swyllys EVP_PKEY *pkey = NULL;
38445b3e1433Swyllys X509 *xcert = NULL;
3845300fdee2SAndy Fiddaman const ASN1_TYPE *keyid = NULL;
3846300fdee2SAndy Fiddaman const ASN1_TYPE *fname = NULL;
38475b3e1433Swyllys uchar_t *data = NULL;
38485b3e1433Swyllys
3849300fdee2SAndy Fiddaman keyid = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID);
3850300fdee2SAndy Fiddaman fname = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName);
38515b3e1433Swyllys
3852300fdee2SAndy Fiddaman switch (PKCS12_SAFEBAG_get_nid(bag)) {
38535b3e1433Swyllys case NID_keyBag:
38545b3e1433Swyllys if (keylist == NULL)
38555b3e1433Swyllys goto end;
3856300fdee2SAndy Fiddaman pkey = EVP_PKCS82PKEY(
3857300fdee2SAndy Fiddaman PKCS12_SAFEBAG_get0_p8inf(bag));
38585b3e1433Swyllys if (pkey == NULL)
38595b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT;
38605b3e1433Swyllys
38615b3e1433Swyllys break;
38625b3e1433Swyllys case NID_pkcs8ShroudedKeyBag:
38635b3e1433Swyllys if (keylist == NULL)
38645b3e1433Swyllys goto end;
3865300fdee2SAndy Fiddaman p8 = PKCS12_decrypt_skey(bag, pass, passlen);
38665b3e1433Swyllys if (p8 == NULL)
38675b3e1433Swyllys return (KMF_ERR_AUTH_FAILED);
38685b3e1433Swyllys pkey = EVP_PKCS82PKEY(p8);
38695b3e1433Swyllys PKCS8_PRIV_KEY_INFO_free(p8);
38705b3e1433Swyllys if (pkey == NULL)
38715b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT;
38725b3e1433Swyllys break;
38735b3e1433Swyllys case NID_certBag:
38745b3e1433Swyllys if (certlist == NULL)
38755b3e1433Swyllys goto end;
3876300fdee2SAndy Fiddaman if (PKCS12_SAFEBAG_get_bag_nid(bag) !=
3877300fdee2SAndy Fiddaman NID_x509Certificate)
38785b3e1433Swyllys return (KMF_ERR_PKCS12_FORMAT);
3879300fdee2SAndy Fiddaman xcert = PKCS12_SAFEBAG_get1_cert(bag);
38805b3e1433Swyllys if (xcert == NULL) {
38815b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT;
38825b3e1433Swyllys goto end;
38835b3e1433Swyllys }
38845b3e1433Swyllys if (keyid != NULL) {
38855b3e1433Swyllys if (X509_keyid_set1(xcert,
38865b3e1433Swyllys keyid->value.octet_string->data,
38875b3e1433Swyllys keyid->value.octet_string->length) == 0) {
38885b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT;
38895b3e1433Swyllys goto end;
38905b3e1433Swyllys }
38915b3e1433Swyllys }
38925b3e1433Swyllys if (fname != NULL) {
38935b3e1433Swyllys int len, r;
38945b3e1433Swyllys len = ASN1_STRING_to_UTF8(&data,
38955b3e1433Swyllys fname->value.asn1_string);
38965b3e1433Swyllys if (len > 0 && data != NULL) {
38975b3e1433Swyllys r = X509_alias_set1(xcert, data, len);
3898f810c7e5SToomas Soome if (r == 0) {
38995b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT;
39005b3e1433Swyllys goto end;
39015b3e1433Swyllys }
39025b3e1433Swyllys } else {
39035b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT;
39045b3e1433Swyllys goto end;
39055b3e1433Swyllys }
39065b3e1433Swyllys }
39075b3e1433Swyllys if (sk_X509_push(certlist, xcert) == 0)
39085b3e1433Swyllys ret = KMF_ERR_MEMORY;
39095b3e1433Swyllys else
39105b3e1433Swyllys xcert = NULL;
39115b3e1433Swyllys break;
39125b3e1433Swyllys case NID_safeContentsBag:
3913300fdee2SAndy Fiddaman return (openssl_parse_bags(
3914300fdee2SAndy Fiddaman PKCS12_SAFEBAG_get0_safes(bag),
3915300fdee2SAndy Fiddaman pass, keylist, certlist));
39165b3e1433Swyllys default:
39175b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT;
39185b3e1433Swyllys break;
39195b3e1433Swyllys }
39205b3e1433Swyllys
39215b3e1433Swyllys /*
39225b3e1433Swyllys * Set the ID and/or FriendlyName attributes on the key.
39235b3e1433Swyllys * If converting to PKCS11 objects, these can translate to CKA_ID
39245b3e1433Swyllys * and CKA_LABEL values.
39255b3e1433Swyllys */
39265b3e1433Swyllys if (pkey != NULL && ret == KMF_OK) {
39275b3e1433Swyllys ASN1_TYPE *attr = NULL;
39285b3e1433Swyllys if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
39295b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL)
39305b3e1433Swyllys return (KMF_ERR_MEMORY);
39315b3e1433Swyllys attr->value.octet_string =
39325b3e1433Swyllys ASN1_STRING_dup(keyid->value.octet_string);
39335b3e1433Swyllys attr->type = V_ASN1_OCTET_STRING;
39345b3e1433Swyllys attr->value.ptr = (char *)attr->value.octet_string;
39355b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
39365b3e1433Swyllys OPENSSL_free(attr);
39375b3e1433Swyllys }
39385b3e1433Swyllys
39395b3e1433Swyllys if (ret == KMF_OK && fname != NULL &&
39405b3e1433Swyllys fname->type == V_ASN1_BMPSTRING) {
39415b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL)
39425b3e1433Swyllys return (KMF_ERR_MEMORY);
39435b3e1433Swyllys attr->value.bmpstring =
39445b3e1433Swyllys ASN1_STRING_dup(fname->value.bmpstring);
39455b3e1433Swyllys attr->type = V_ASN1_BMPSTRING;
39465b3e1433Swyllys attr->value.ptr = (char *)attr->value.bmpstring;
39475b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
39485b3e1433Swyllys OPENSSL_free(attr);
39495b3e1433Swyllys }
39505b3e1433Swyllys
39515b3e1433Swyllys if (ret == KMF_OK && keylist != NULL &&
39525b3e1433Swyllys sk_EVP_PKEY_push(keylist, pkey) == 0)
39535b3e1433Swyllys ret = KMF_ERR_MEMORY;
39545b3e1433Swyllys }
39555b3e1433Swyllys if (ret == KMF_OK && keylist != NULL)
39565b3e1433Swyllys pkey = NULL;
39575b3e1433Swyllys end:
39585b3e1433Swyllys if (pkey != NULL)
39595b3e1433Swyllys EVP_PKEY_free(pkey);
39605b3e1433Swyllys if (xcert != NULL)
39615b3e1433Swyllys X509_free(xcert);
39625b3e1433Swyllys if (data != NULL)
39635b3e1433Swyllys OPENSSL_free(data);
39645b3e1433Swyllys
39655b3e1433Swyllys return (ret);
39665b3e1433Swyllys }
39675b3e1433Swyllys
39685b3e1433Swyllys static KMF_RETURN
openssl_pkcs12_parse(PKCS12 * p12,char * pin,STACK_OF (EVP_PKEY)* keys,STACK_OF (X509)* certs,STACK_OF (X509)* ca)39694942e222SAndy Fiddaman openssl_pkcs12_parse(PKCS12 *p12, char *pin, STACK_OF(EVP_PKEY) *keys,
39704942e222SAndy Fiddaman STACK_OF(X509) *certs, STACK_OF(X509) *ca)
39715b3e1433Swyllys {
39725b3e1433Swyllys KMF_RETURN ret = KMF_OK;
39735b3e1433Swyllys STACK_OF(PKCS7) *asafes = NULL;
39745b3e1433Swyllys STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
39755b3e1433Swyllys int i, bagnid;
39765b3e1433Swyllys PKCS7 *p7;
39775b3e1433Swyllys
39785b3e1433Swyllys if (p12 == NULL || (keys == NULL && certs == NULL))
39795b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER);
39805b3e1433Swyllys
3981f810c7e5SToomas Soome if (pin == NULL || *pin == '\0') {
39825b3e1433Swyllys if (PKCS12_verify_mac(p12, NULL, 0)) {
39835b3e1433Swyllys pin = NULL;
39845b3e1433Swyllys } else if (PKCS12_verify_mac(p12, "", 0)) {
39855b3e1433Swyllys pin = "";
39865b3e1433Swyllys } else {
39875b3e1433Swyllys return (KMF_ERR_AUTH_FAILED);
39885b3e1433Swyllys }
39895b3e1433Swyllys } else if (!PKCS12_verify_mac(p12, pin, -1)) {
39905b3e1433Swyllys return (KMF_ERR_AUTH_FAILED);
39915b3e1433Swyllys }
39925b3e1433Swyllys
39935b3e1433Swyllys if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
39945b3e1433Swyllys return (KMF_ERR_PKCS12_FORMAT);
39955b3e1433Swyllys
39965b3e1433Swyllys for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
39975b3e1433Swyllys bags = NULL;
39985b3e1433Swyllys p7 = sk_PKCS7_value(asafes, i);
39995b3e1433Swyllys bagnid = OBJ_obj2nid(p7->type);
40005b3e1433Swyllys
40015b3e1433Swyllys if (bagnid == NID_pkcs7_data) {
40025b3e1433Swyllys bags = PKCS12_unpack_p7data(p7);
40035b3e1433Swyllys } else if (bagnid == NID_pkcs7_encrypted) {
40045b3e1433Swyllys bags = PKCS12_unpack_p7encdata(p7, pin,
40055b3e1433Swyllys (pin ? strlen(pin) : 0));
40065b3e1433Swyllys } else {
40075b3e1433Swyllys continue;
40085b3e1433Swyllys }
40095b3e1433Swyllys if (bags == NULL) {
40105b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT;
40115b3e1433Swyllys goto out;
40125b3e1433Swyllys }
40135b3e1433Swyllys
40145b3e1433Swyllys if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
40155b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT;
40165b3e1433Swyllys
40175b3e1433Swyllys sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
40185b3e1433Swyllys }
40195b3e1433Swyllys out:
40205b3e1433Swyllys if (asafes != NULL)
40215b3e1433Swyllys sk_PKCS7_pop_free(asafes, PKCS7_free);
40225b3e1433Swyllys
40235b3e1433Swyllys return (ret);
40245b3e1433Swyllys }
40255b3e1433Swyllys
402699ebb4caSwyllys /*
402799ebb4caSwyllys * Helper function to decrypt and parse PKCS#12 import file.
402899ebb4caSwyllys */
402999ebb4caSwyllys static KMF_RETURN
extract_pkcs12(BIO * fbio,CK_UTF8CHAR * pin,CK_ULONG pinlen,STACK_OF (EVP_PKEY)** priv_key,STACK_OF (X509)** certs,STACK_OF (X509)** ca)403099ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
40314942e222SAndy Fiddaman STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs, STACK_OF(X509) **ca)
403299ebb4caSwyllys {
403399ebb4caSwyllys PKCS12 *pk12, *pk12_tmp;
40345b3e1433Swyllys STACK_OF(EVP_PKEY) *pkeylist = NULL;
40355b3e1433Swyllys STACK_OF(X509) *xcertlist = NULL;
40365b3e1433Swyllys STACK_OF(X509) *cacertlist = NULL;
403799ebb4caSwyllys
403899ebb4caSwyllys if ((pk12 = PKCS12_new()) == NULL) {
403999ebb4caSwyllys return (KMF_ERR_MEMORY);
404099ebb4caSwyllys }
404199ebb4caSwyllys
404299ebb4caSwyllys if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
404399ebb4caSwyllys /* This is ok; it seems to mean there is no more to read. */
404499ebb4caSwyllys if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
404599ebb4caSwyllys ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
404699ebb4caSwyllys goto end_extract_pkcs12;
404799ebb4caSwyllys
404899ebb4caSwyllys PKCS12_free(pk12);
404999ebb4caSwyllys return (KMF_ERR_PKCS12_FORMAT);
405099ebb4caSwyllys }
405199ebb4caSwyllys pk12 = pk12_tmp;
405299ebb4caSwyllys
40535b3e1433Swyllys xcertlist = sk_X509_new_null();
40545b3e1433Swyllys if (xcertlist == NULL) {
40555b3e1433Swyllys PKCS12_free(pk12);
40565b3e1433Swyllys return (KMF_ERR_MEMORY);
40575b3e1433Swyllys }
40585b3e1433Swyllys pkeylist = sk_EVP_PKEY_new_null();
40595b3e1433Swyllys if (pkeylist == NULL) {
40605b3e1433Swyllys sk_X509_pop_free(xcertlist, X509_free);
40615b3e1433Swyllys PKCS12_free(pk12);
40625b3e1433Swyllys return (KMF_ERR_MEMORY);
40635b3e1433Swyllys }
40645b3e1433Swyllys
40655b3e1433Swyllys if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
40665b3e1433Swyllys cacertlist) != KMF_OK) {
40675b3e1433Swyllys sk_X509_pop_free(xcertlist, X509_free);
40685b3e1433Swyllys sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
406999ebb4caSwyllys PKCS12_free(pk12);
407099ebb4caSwyllys return (KMF_ERR_PKCS12_FORMAT);
407199ebb4caSwyllys }
407299ebb4caSwyllys
40735b3e1433Swyllys if (priv_key && pkeylist)
40745b3e1433Swyllys *priv_key = pkeylist;
40755b3e1433Swyllys else if (pkeylist)
40765b3e1433Swyllys sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
40775b3e1433Swyllys if (certs && xcertlist)
40785b3e1433Swyllys *certs = xcertlist;
40795b3e1433Swyllys else if (xcertlist)
40805b3e1433Swyllys sk_X509_pop_free(xcertlist, X509_free);
40815b3e1433Swyllys if (ca && cacertlist)
40825b3e1433Swyllys *ca = cacertlist;
40835b3e1433Swyllys else if (cacertlist)
40845b3e1433Swyllys sk_X509_pop_free(cacertlist, X509_free);
408599ebb4caSwyllys
40865b3e1433Swyllys end_extract_pkcs12:
408799ebb4caSwyllys
408899ebb4caSwyllys PKCS12_free(pk12);
408999ebb4caSwyllys return (KMF_OK);
409099ebb4caSwyllys }
409199ebb4caSwyllys
409299ebb4caSwyllys static KMF_RETURN
sslBN2KMFBN(BIGNUM * from,KMF_BIGINT * to)409399ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
409499ebb4caSwyllys {
409599ebb4caSwyllys KMF_RETURN rv = KMF_OK;
409699ebb4caSwyllys uint32_t sz;
409799ebb4caSwyllys
409899ebb4caSwyllys sz = BN_num_bytes(from);
409999ebb4caSwyllys to->val = (uchar_t *)malloc(sz);
410099ebb4caSwyllys if (to->val == NULL)
410199ebb4caSwyllys return (KMF_ERR_MEMORY);
410299ebb4caSwyllys
410399ebb4caSwyllys if ((to->len = BN_bn2bin(from, to->val)) != sz) {
410499ebb4caSwyllys free(to->val);
410599ebb4caSwyllys to->val = NULL;
410699ebb4caSwyllys to->len = 0;
410799ebb4caSwyllys rv = KMF_ERR_MEMORY;
410899ebb4caSwyllys }
410999ebb4caSwyllys
411099ebb4caSwyllys return (rv);
411199ebb4caSwyllys }
411299ebb4caSwyllys
411399ebb4caSwyllys static KMF_RETURN
exportRawRSAKey(RSA * rsa,KMF_RAW_KEY_DATA * key)411499ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
411599ebb4caSwyllys {
411699ebb4caSwyllys KMF_RETURN rv;
411799ebb4caSwyllys KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
411899ebb4caSwyllys
4119300fdee2SAndy Fiddaman const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmpq, *iqmp;
4120300fdee2SAndy Fiddaman
4121300fdee2SAndy Fiddaman RSA_get0_key(rsa, &n, &e, &d);
4122300fdee2SAndy Fiddaman RSA_get0_factors(rsa, &p, &q);
4123300fdee2SAndy Fiddaman RSA_get0_crt_params(rsa, &dmp1, &dmpq, &iqmp);
4124300fdee2SAndy Fiddaman
412599ebb4caSwyllys (void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
4126300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)n, &kmfkey->mod)) != KMF_OK)
412799ebb4caSwyllys goto cleanup;
412899ebb4caSwyllys
4129300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)e, &kmfkey->pubexp)) != KMF_OK)
413099ebb4caSwyllys goto cleanup;
413199ebb4caSwyllys
4132300fdee2SAndy Fiddaman if (d != NULL)
4133300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)d, &kmfkey->priexp)) != KMF_OK)
413499ebb4caSwyllys goto cleanup;
413599ebb4caSwyllys
4136300fdee2SAndy Fiddaman if (p != NULL)
4137300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime1)) != KMF_OK)
413899ebb4caSwyllys goto cleanup;
413999ebb4caSwyllys
4140300fdee2SAndy Fiddaman if (q != NULL)
4141300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->prime2)) != KMF_OK)
414299ebb4caSwyllys goto cleanup;
414399ebb4caSwyllys
4144300fdee2SAndy Fiddaman if (dmp1 != NULL)
4145300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)dmp1, &kmfkey->exp1)) != KMF_OK)
414699ebb4caSwyllys goto cleanup;
414799ebb4caSwyllys
4148300fdee2SAndy Fiddaman if (dmpq != NULL)
4149300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)dmpq, &kmfkey->exp2)) != KMF_OK)
415099ebb4caSwyllys goto cleanup;
415199ebb4caSwyllys
4152300fdee2SAndy Fiddaman if (iqmp != NULL)
4153300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)iqmp, &kmfkey->coef)) != KMF_OK)
415499ebb4caSwyllys goto cleanup;
415599ebb4caSwyllys cleanup:
415699ebb4caSwyllys if (rv != KMF_OK)
415730a5e8faSwyllys kmf_free_raw_key(key);
415899ebb4caSwyllys else
415999ebb4caSwyllys key->keytype = KMF_RSA;
416099ebb4caSwyllys
416199ebb4caSwyllys /*
416299ebb4caSwyllys * Free the reference to this key, SSL will not actually free
416399ebb4caSwyllys * the memory until the refcount == 0, so this is safe.
416499ebb4caSwyllys */
416599ebb4caSwyllys RSA_free(rsa);
416699ebb4caSwyllys
416799ebb4caSwyllys return (rv);
416899ebb4caSwyllys }
416999ebb4caSwyllys
417099ebb4caSwyllys static KMF_RETURN
exportRawDSAKey(DSA * dsa,KMF_RAW_KEY_DATA * key)417199ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
417299ebb4caSwyllys {
417399ebb4caSwyllys KMF_RETURN rv;
417499ebb4caSwyllys KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
4175300fdee2SAndy Fiddaman const BIGNUM *p, *q, *g, *priv_key;
4176300fdee2SAndy Fiddaman
4177300fdee2SAndy Fiddaman DSA_get0_pqg(dsa, &p, &q, &g);
4178300fdee2SAndy Fiddaman DSA_get0_key(dsa, NULL, &priv_key);
417999ebb4caSwyllys
418099ebb4caSwyllys (void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
4181300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime)) != KMF_OK)
418299ebb4caSwyllys goto cleanup;
418399ebb4caSwyllys
4184300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->subprime)) != KMF_OK)
418599ebb4caSwyllys goto cleanup;
418699ebb4caSwyllys
4187300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)g, &kmfkey->base)) != KMF_OK)
418899ebb4caSwyllys goto cleanup;
418999ebb4caSwyllys
4190300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)priv_key, &kmfkey->value)) != KMF_OK)
419199ebb4caSwyllys goto cleanup;
419299ebb4caSwyllys
419399ebb4caSwyllys cleanup:
419499ebb4caSwyllys if (rv != KMF_OK)
419530a5e8faSwyllys kmf_free_raw_key(key);
419699ebb4caSwyllys else
419799ebb4caSwyllys key->keytype = KMF_DSA;
419899ebb4caSwyllys
419999ebb4caSwyllys /*
420099ebb4caSwyllys * Free the reference to this key, SSL will not actually free
420199ebb4caSwyllys * the memory until the refcount == 0, so this is safe.
420299ebb4caSwyllys */
420399ebb4caSwyllys DSA_free(dsa);
420499ebb4caSwyllys
420599ebb4caSwyllys return (rv);
420699ebb4caSwyllys }
420799ebb4caSwyllys
420899ebb4caSwyllys static KMF_RETURN
add_cert_to_list(KMF_HANDLE * kmfh,X509 * sslcert,KMF_X509_DER_CERT ** certlist,int * ncerts)420999ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
42105b3e1433Swyllys KMF_X509_DER_CERT **certlist, int *ncerts)
421199ebb4caSwyllys {
421299ebb4caSwyllys KMF_RETURN rv = KMF_OK;
42135b3e1433Swyllys KMF_X509_DER_CERT *list = (*certlist);
42145b3e1433Swyllys KMF_X509_DER_CERT cert;
421599ebb4caSwyllys int n = (*ncerts);
421699ebb4caSwyllys
421799ebb4caSwyllys if (list == NULL) {
42185b3e1433Swyllys list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
421999ebb4caSwyllys } else {
42205b3e1433Swyllys list = (KMF_X509_DER_CERT *)realloc(list,
42215b3e1433Swyllys sizeof (KMF_X509_DER_CERT) * (n + 1));
422299ebb4caSwyllys }
422399ebb4caSwyllys
422499ebb4caSwyllys if (list == NULL)
422599ebb4caSwyllys return (KMF_ERR_MEMORY);
422699ebb4caSwyllys
42275b3e1433Swyllys (void) memset(&cert, 0, sizeof (cert));
42285b3e1433Swyllys rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
422999ebb4caSwyllys if (rv == KMF_OK) {
42305b3e1433Swyllys int len = 0;
42315b3e1433Swyllys /* Get the alias name for the cert if there is one */
42325b3e1433Swyllys char *a = (char *)X509_alias_get0(sslcert, &len);
42335b3e1433Swyllys if (a != NULL)
42345b3e1433Swyllys cert.kmf_private.label = strdup(a);
42355b3e1433Swyllys cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
42365b3e1433Swyllys
423799ebb4caSwyllys list[n] = cert;
423899ebb4caSwyllys (*ncerts) = n + 1;
423999ebb4caSwyllys
424099ebb4caSwyllys *certlist = list;
424199ebb4caSwyllys } else {
424299ebb4caSwyllys free(list);
424399ebb4caSwyllys }
424499ebb4caSwyllys
424599ebb4caSwyllys return (rv);
424699ebb4caSwyllys }
424799ebb4caSwyllys
424899ebb4caSwyllys static KMF_RETURN
add_key_to_list(KMF_RAW_KEY_DATA ** keylist,KMF_RAW_KEY_DATA * newkey,int * nkeys)424999ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist,
425099ebb4caSwyllys KMF_RAW_KEY_DATA *newkey, int *nkeys)
425199ebb4caSwyllys {
425299ebb4caSwyllys KMF_RAW_KEY_DATA *list = (*keylist);
425399ebb4caSwyllys int n = (*nkeys);
425499ebb4caSwyllys
425599ebb4caSwyllys if (list == NULL) {
425699ebb4caSwyllys list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
425799ebb4caSwyllys } else {
425899ebb4caSwyllys list = (KMF_RAW_KEY_DATA *)realloc(list,
425999ebb4caSwyllys sizeof (KMF_RAW_KEY_DATA) * (n + 1));
426099ebb4caSwyllys }
426199ebb4caSwyllys
426299ebb4caSwyllys if (list == NULL)
426399ebb4caSwyllys return (KMF_ERR_MEMORY);
426499ebb4caSwyllys
426599ebb4caSwyllys list[n] = *newkey;
426699ebb4caSwyllys (*nkeys) = n + 1;
426799ebb4caSwyllys
426899ebb4caSwyllys *keylist = list;
426999ebb4caSwyllys
427099ebb4caSwyllys return (KMF_OK);
427199ebb4caSwyllys }
427299ebb4caSwyllys
427330a5e8faSwyllys static KMF_RETURN
convertToRawKey(EVP_PKEY * pkey,KMF_RAW_KEY_DATA * key)427430a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
427530a5e8faSwyllys {
427630a5e8faSwyllys KMF_RETURN rv = KMF_OK;
42775b3e1433Swyllys X509_ATTRIBUTE *attr;
4278300fdee2SAndy Fiddaman RSA *rsa;
4279300fdee2SAndy Fiddaman DSA *dsa;
4280300fdee2SAndy Fiddaman int loc;
428130a5e8faSwyllys
428230a5e8faSwyllys if (pkey == NULL || key == NULL)
428330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
428430a5e8faSwyllys /* Convert SSL key to raw key */
4285300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get1_RSA(pkey)) != NULL) {
4286300fdee2SAndy Fiddaman rv = exportRawRSAKey(rsa, key);
428730a5e8faSwyllys if (rv != KMF_OK)
428830a5e8faSwyllys return (rv);
4289300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get1_DSA(pkey)) != NULL) {
4290300fdee2SAndy Fiddaman rv = exportRawDSAKey(dsa, key);
429130a5e8faSwyllys if (rv != KMF_OK)
429230a5e8faSwyllys return (rv);
4293300fdee2SAndy Fiddaman } else
429430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
4295300fdee2SAndy Fiddaman
42965b3e1433Swyllys /*
42975b3e1433Swyllys * If friendlyName, add it to record.
42985b3e1433Swyllys */
4299300fdee2SAndy Fiddaman
4300300fdee2SAndy Fiddaman if ((loc = EVP_PKEY_get_attr_by_NID(pkey,
4301300fdee2SAndy Fiddaman NID_friendlyName, -1)) != -1 &&
4302300fdee2SAndy Fiddaman (attr = EVP_PKEY_get_attr(pkey, loc))) {
43035b3e1433Swyllys ASN1_TYPE *ty = NULL;
4304300fdee2SAndy Fiddaman int numattr = X509_ATTRIBUTE_count(attr);
4305300fdee2SAndy Fiddaman if (numattr > 0) {
4306300fdee2SAndy Fiddaman ty = X509_ATTRIBUTE_get0_type(attr, 0);
43075b3e1433Swyllys }
43085b3e1433Swyllys if (ty != NULL) {
430970f9559bSTheo Schlossnagle key->label = OPENSSL_uni2asc(ty->value.bmpstring->data,
431070f9559bSTheo Schlossnagle ty->value.bmpstring->length);
43115b3e1433Swyllys }
43125b3e1433Swyllys } else {
43135b3e1433Swyllys key->label = NULL;
43145b3e1433Swyllys }
43155b3e1433Swyllys
43165b3e1433Swyllys /*
43175b3e1433Swyllys * If KeyID, add it to record as a KMF_DATA object.
43185b3e1433Swyllys */
4319300fdee2SAndy Fiddaman if ((loc = EVP_PKEY_get_attr_by_NID(pkey,
4320300fdee2SAndy Fiddaman NID_localKeyID, -1)) != -1 &&
4321300fdee2SAndy Fiddaman (attr = EVP_PKEY_get_attr(pkey, loc)) != NULL) {
43225b3e1433Swyllys ASN1_TYPE *ty = NULL;
4323300fdee2SAndy Fiddaman int numattr = X509_ATTRIBUTE_count(attr);
4324300fdee2SAndy Fiddaman if (numattr > 0)
4325300fdee2SAndy Fiddaman ty = X509_ATTRIBUTE_get0_type(attr, 0);
43265b3e1433Swyllys key->id.Data = (uchar_t *)malloc(
43275b3e1433Swyllys ty->value.octet_string->length);
43285b3e1433Swyllys if (key->id.Data == NULL)
43295b3e1433Swyllys return (KMF_ERR_MEMORY);
43305b3e1433Swyllys (void) memcpy(key->id.Data, ty->value.octet_string->data,
43315b3e1433Swyllys ty->value.octet_string->length);
43325b3e1433Swyllys key->id.Length = ty->value.octet_string->length;
43335b3e1433Swyllys } else {
43345b3e1433Swyllys (void) memset(&key->id, 0, sizeof (KMF_DATA));
43355b3e1433Swyllys }
433630a5e8faSwyllys
433730a5e8faSwyllys return (rv);
433830a5e8faSwyllys }
433999ebb4caSwyllys
434099ebb4caSwyllys static KMF_RETURN
convertPK12Objects(KMF_HANDLE * kmfh,STACK_OF (EVP_PKEY)* sslkeys,STACK_OF (X509)* sslcert,STACK_OF (X509)* sslcacerts,KMF_RAW_KEY_DATA ** keylist,int * nkeys,KMF_X509_DER_CERT ** certlist,int * ncerts)434199ebb4caSwyllys convertPK12Objects(
434299ebb4caSwyllys KMF_HANDLE *kmfh,
43435b3e1433Swyllys STACK_OF(EVP_PKEY) *sslkeys,
43445b3e1433Swyllys STACK_OF(X509) *sslcert,
43455b3e1433Swyllys STACK_OF(X509) *sslcacerts,
434699ebb4caSwyllys KMF_RAW_KEY_DATA **keylist, int *nkeys,
43475b3e1433Swyllys KMF_X509_DER_CERT **certlist, int *ncerts)
434899ebb4caSwyllys {
434999ebb4caSwyllys KMF_RETURN rv = KMF_OK;
435099ebb4caSwyllys KMF_RAW_KEY_DATA key;
435199ebb4caSwyllys int i;
435299ebb4caSwyllys
43535b3e1433Swyllys for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
43545b3e1433Swyllys EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
43555b3e1433Swyllys rv = convertToRawKey(pkey, &key);
435630a5e8faSwyllys if (rv == KMF_OK)
435799ebb4caSwyllys rv = add_key_to_list(keylist, &key, nkeys);
435830a5e8faSwyllys
435999ebb4caSwyllys if (rv != KMF_OK)
436099ebb4caSwyllys return (rv);
436199ebb4caSwyllys }
436299ebb4caSwyllys
436399ebb4caSwyllys /* Now add the certificate to the certlist */
43645b3e1433Swyllys for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
43655b3e1433Swyllys X509 *cert = sk_X509_value(sslcert, i);
43665b3e1433Swyllys rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
436799ebb4caSwyllys if (rv != KMF_OK)
436899ebb4caSwyllys return (rv);
436999ebb4caSwyllys }
437099ebb4caSwyllys
437199ebb4caSwyllys /* Also add any included CA certs to the list */
437271593db2Swyllys for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
437399ebb4caSwyllys X509 *c;
437499ebb4caSwyllys /*
437599ebb4caSwyllys * sk_X509_value() is macro that embeds a cast to (X509 *).
437699ebb4caSwyllys * Here it translates into ((X509 *)sk_value((ca), (i))).
437799ebb4caSwyllys * Lint is complaining about the embedded casting, and
437899ebb4caSwyllys * to fix it, you need to fix openssl header files.
437999ebb4caSwyllys */
438099ebb4caSwyllys c = sk_X509_value(sslcacerts, i);
438199ebb4caSwyllys
438299ebb4caSwyllys /* Now add the ca cert to the certlist */
438399ebb4caSwyllys rv = add_cert_to_list(kmfh, c, certlist, ncerts);
438499ebb4caSwyllys if (rv != KMF_OK)
438599ebb4caSwyllys return (rv);
438699ebb4caSwyllys }
438799ebb4caSwyllys return (rv);
438899ebb4caSwyllys }
438999ebb4caSwyllys
439099ebb4caSwyllys KMF_RETURN
openssl_import_objects(KMF_HANDLE * kmfh,char * filename,KMF_CREDENTIAL * cred,KMF_X509_DER_CERT ** certlist,int * ncerts,KMF_RAW_KEY_DATA ** keylist,int * nkeys)43914942e222SAndy Fiddaman openssl_import_objects(KMF_HANDLE *kmfh, char *filename, KMF_CREDENTIAL *cred,
43925b3e1433Swyllys KMF_X509_DER_CERT **certlist, int *ncerts,
439399ebb4caSwyllys KMF_RAW_KEY_DATA **keylist, int *nkeys)
439499ebb4caSwyllys {
439599ebb4caSwyllys KMF_RETURN rv = KMF_OK;
439630a5e8faSwyllys KMF_ENCODE_FORMAT format;
439730a5e8faSwyllys BIO *bio = NULL;
43985b3e1433Swyllys STACK_OF(EVP_PKEY) *privkeys = NULL;
43995b3e1433Swyllys STACK_OF(X509) *certs = NULL;
440099ebb4caSwyllys STACK_OF(X509) *cacerts = NULL;
440199ebb4caSwyllys
440230a5e8faSwyllys /*
440330a5e8faSwyllys * auto-detect the file format, regardless of what
440430a5e8faSwyllys * the 'format' parameters in the params say.
440530a5e8faSwyllys */
440630a5e8faSwyllys rv = kmf_get_file_format(filename, &format);
440730a5e8faSwyllys if (rv != KMF_OK) {
440830a5e8faSwyllys return (rv);
440930a5e8faSwyllys }
441030a5e8faSwyllys
441130a5e8faSwyllys /* This function only works for PEM or PKCS#12 files */
441230a5e8faSwyllys if (format != KMF_FORMAT_PEM &&
441330a5e8faSwyllys format != KMF_FORMAT_PEM_KEYPAIR &&
441430a5e8faSwyllys format != KMF_FORMAT_PKCS12)
441530a5e8faSwyllys return (KMF_ERR_ENCODING);
441630a5e8faSwyllys
441730a5e8faSwyllys *certlist = NULL;
441830a5e8faSwyllys *keylist = NULL;
441930a5e8faSwyllys *ncerts = 0;
442030a5e8faSwyllys *nkeys = 0;
442130a5e8faSwyllys
442230a5e8faSwyllys if (format == KMF_FORMAT_PKCS12) {
442399ebb4caSwyllys bio = BIO_new_file(filename, "rb");
442499ebb4caSwyllys if (bio == NULL) {
442599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
442699ebb4caSwyllys rv = KMF_ERR_OPEN_FILE;
442799ebb4caSwyllys goto end;
442899ebb4caSwyllys }
442999ebb4caSwyllys
443034acef67Swyllys rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
44315b3e1433Swyllys (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
443299ebb4caSwyllys
443399ebb4caSwyllys if (rv == KMF_OK)
443499ebb4caSwyllys /* Convert keys and certs to exportable format */
44355b3e1433Swyllys rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
443699ebb4caSwyllys keylist, nkeys, certlist, ncerts);
443730a5e8faSwyllys } else {
44385b3e1433Swyllys EVP_PKEY *pkey;
44395b3e1433Swyllys KMF_DATA *certdata = NULL;
44405b3e1433Swyllys KMF_X509_DER_CERT *kmfcerts = NULL;
44415b3e1433Swyllys int i;
444230a5e8faSwyllys rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
444334acef67Swyllys (uchar_t *)cred->cred, (uint32_t)cred->credlen,
44445b3e1433Swyllys &pkey, &certdata, ncerts);
444571593db2Swyllys
444671593db2Swyllys /* Reached end of import file? */
44475b3e1433Swyllys if (rv == KMF_OK && pkey != NULL) {
44485b3e1433Swyllys privkeys = sk_EVP_PKEY_new_null();
44495b3e1433Swyllys if (privkeys == NULL) {
44505b3e1433Swyllys rv = KMF_ERR_MEMORY;
44515b3e1433Swyllys goto end;
44525b3e1433Swyllys }
44535b3e1433Swyllys (void) sk_EVP_PKEY_push(privkeys, pkey);
44545b3e1433Swyllys /* convert the certificate list here */
44555b3e1433Swyllys if (*ncerts > 0 && certlist != NULL) {
4456e65e5c2dSWyllys Ingersoll kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
44575b3e1433Swyllys sizeof (KMF_X509_DER_CERT));
44585b3e1433Swyllys if (kmfcerts == NULL) {
44595b3e1433Swyllys rv = KMF_ERR_MEMORY;
44605b3e1433Swyllys goto end;
44615b3e1433Swyllys }
44625b3e1433Swyllys for (i = 0; i < *ncerts; i++) {
44635b3e1433Swyllys kmfcerts[i].certificate = certdata[i];
44645b3e1433Swyllys kmfcerts[i].kmf_private.keystore_type =
44655b3e1433Swyllys KMF_KEYSTORE_OPENSSL;
44665b3e1433Swyllys }
44675b3e1433Swyllys *certlist = kmfcerts;
44685b3e1433Swyllys }
44695b3e1433Swyllys /*
44705b3e1433Swyllys * Convert keys to exportable format, the certs
44715b3e1433Swyllys * are already OK.
44725b3e1433Swyllys */
44735b3e1433Swyllys rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
447471593db2Swyllys keylist, nkeys, NULL, NULL);
447530a5e8faSwyllys }
44765b3e1433Swyllys }
447771593db2Swyllys end:
447830a5e8faSwyllys if (bio != NULL)
447999ebb4caSwyllys (void) BIO_free(bio);
448099ebb4caSwyllys
44815b3e1433Swyllys if (privkeys)
44825b3e1433Swyllys sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
44835b3e1433Swyllys if (certs)
44845b3e1433Swyllys sk_X509_pop_free(certs, X509_free);
448530a5e8faSwyllys if (cacerts)
44865b3e1433Swyllys sk_X509_pop_free(cacerts, X509_free);
448730a5e8faSwyllys
448899ebb4caSwyllys return (rv);
448999ebb4caSwyllys }
449099ebb4caSwyllys
449199ebb4caSwyllys static KMF_RETURN
create_deskey(DES_cblock ** deskey)449299ebb4caSwyllys create_deskey(DES_cblock **deskey)
449399ebb4caSwyllys {
449499ebb4caSwyllys DES_cblock *key;
449599ebb4caSwyllys
449699ebb4caSwyllys key = (DES_cblock *) malloc(sizeof (DES_cblock));
449799ebb4caSwyllys if (key == NULL) {
449899ebb4caSwyllys return (KMF_ERR_MEMORY);
449999ebb4caSwyllys }
450099ebb4caSwyllys
450199ebb4caSwyllys if (DES_random_key(key) == 0) {
450299ebb4caSwyllys free(key);
450399ebb4caSwyllys return (KMF_ERR_KEYGEN_FAILED);
450499ebb4caSwyllys }
450599ebb4caSwyllys
450699ebb4caSwyllys *deskey = key;
450799ebb4caSwyllys return (KMF_OK);
450899ebb4caSwyllys }
450999ebb4caSwyllys
451099ebb4caSwyllys #define KEYGEN_RETRY 3
451199ebb4caSwyllys #define DES3_KEY_SIZE 24
451299ebb4caSwyllys
451399ebb4caSwyllys static KMF_RETURN
create_des3key(unsigned char ** des3key)451499ebb4caSwyllys create_des3key(unsigned char **des3key)
451599ebb4caSwyllys {
451699ebb4caSwyllys KMF_RETURN ret = KMF_OK;
451799ebb4caSwyllys DES_cblock *deskey1 = NULL;
451899ebb4caSwyllys DES_cblock *deskey2 = NULL;
451999ebb4caSwyllys DES_cblock *deskey3 = NULL;
452099ebb4caSwyllys unsigned char *newkey = NULL;
452199ebb4caSwyllys int retry;
452299ebb4caSwyllys
452399ebb4caSwyllys if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
452499ebb4caSwyllys return (KMF_ERR_MEMORY);
452599ebb4caSwyllys }
452699ebb4caSwyllys
452799ebb4caSwyllys /* create the 1st DES key */
452899ebb4caSwyllys if ((ret = create_deskey(&deskey1)) != KMF_OK) {
452999ebb4caSwyllys goto out;
453099ebb4caSwyllys }
453199ebb4caSwyllys
453299ebb4caSwyllys /*
453399ebb4caSwyllys * Create the 2nd DES key and make sure its value is different
453499ebb4caSwyllys * from the 1st DES key.
453599ebb4caSwyllys */
453699ebb4caSwyllys retry = 0;
453799ebb4caSwyllys do {
453899ebb4caSwyllys if (deskey2 != NULL) {
453999ebb4caSwyllys free(deskey2);
454099ebb4caSwyllys deskey2 = NULL;
454199ebb4caSwyllys }
454299ebb4caSwyllys
454399ebb4caSwyllys if ((ret = create_deskey(&deskey2)) != KMF_OK) {
454499ebb4caSwyllys goto out;
454599ebb4caSwyllys }
454699ebb4caSwyllys
454799ebb4caSwyllys if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
454899ebb4caSwyllys == 0) {
454999ebb4caSwyllys ret = KMF_ERR_KEYGEN_FAILED;
455099ebb4caSwyllys retry++;
455199ebb4caSwyllys }
455299ebb4caSwyllys } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
455399ebb4caSwyllys
455499ebb4caSwyllys if (ret != KMF_OK) {
455599ebb4caSwyllys goto out;
455699ebb4caSwyllys }
455799ebb4caSwyllys
455899ebb4caSwyllys /*
455999ebb4caSwyllys * Create the 3rd DES key and make sure its value is different
456099ebb4caSwyllys * from the 2nd DES key.
456199ebb4caSwyllys */
456299ebb4caSwyllys retry = 0;
456399ebb4caSwyllys do {
456499ebb4caSwyllys if (deskey3 != NULL) {
456599ebb4caSwyllys free(deskey3);
456699ebb4caSwyllys deskey3 = NULL;
456799ebb4caSwyllys }
456899ebb4caSwyllys
456999ebb4caSwyllys if ((ret = create_deskey(&deskey3)) != KMF_OK) {
457099ebb4caSwyllys goto out;
457199ebb4caSwyllys }
457299ebb4caSwyllys
457399ebb4caSwyllys if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
457499ebb4caSwyllys == 0) {
457599ebb4caSwyllys ret = KMF_ERR_KEYGEN_FAILED;
457699ebb4caSwyllys retry++;
457799ebb4caSwyllys }
457899ebb4caSwyllys } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
457999ebb4caSwyllys
458099ebb4caSwyllys if (ret != KMF_OK) {
458199ebb4caSwyllys goto out;
458299ebb4caSwyllys }
458399ebb4caSwyllys
458499ebb4caSwyllys /* Concatenate 3 DES keys into a DES3 key */
458599ebb4caSwyllys (void) memcpy((void *)newkey, (const void *)deskey1, 8);
458699ebb4caSwyllys (void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
458799ebb4caSwyllys (void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
458899ebb4caSwyllys *des3key = newkey;
458999ebb4caSwyllys
459099ebb4caSwyllys out:
459199ebb4caSwyllys if (deskey1 != NULL)
459299ebb4caSwyllys free(deskey1);
459399ebb4caSwyllys
459499ebb4caSwyllys if (deskey2 != NULL)
459599ebb4caSwyllys free(deskey2);
459699ebb4caSwyllys
459799ebb4caSwyllys if (deskey3 != NULL)
459899ebb4caSwyllys free(deskey3);
459999ebb4caSwyllys
460099ebb4caSwyllys if (ret != KMF_OK && newkey != NULL)
460199ebb4caSwyllys free(newkey);
460299ebb4caSwyllys
460399ebb4caSwyllys return (ret);
460499ebb4caSwyllys }
460599ebb4caSwyllys
460699ebb4caSwyllys KMF_RETURN
OpenSSL_CreateSymKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)46074942e222SAndy Fiddaman OpenSSL_CreateSymKey(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
460899ebb4caSwyllys {
460999ebb4caSwyllys KMF_RETURN ret = KMF_OK;
461099ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
461199ebb4caSwyllys char *fullpath = NULL;
461299ebb4caSwyllys KMF_RAW_SYM_KEY *rkey = NULL;
461399ebb4caSwyllys DES_cblock *deskey = NULL;
461499ebb4caSwyllys unsigned char *des3key = NULL;
461599ebb4caSwyllys unsigned char *random = NULL;
461699ebb4caSwyllys int fd = -1;
461730a5e8faSwyllys KMF_KEY_HANDLE *symkey;
461830a5e8faSwyllys KMF_KEY_ALG keytype;
461930a5e8faSwyllys uint32_t keylen;
462030a5e8faSwyllys uint32_t keylen_size = sizeof (keylen);
462130a5e8faSwyllys char *dirpath;
462230a5e8faSwyllys char *keyfile;
462399ebb4caSwyllys
462499ebb4caSwyllys if (kmfh == NULL)
462599ebb4caSwyllys return (KMF_ERR_UNINITIALIZED);
462699ebb4caSwyllys
462730a5e8faSwyllys symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
462830a5e8faSwyllys if (symkey == NULL)
462999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
463099ebb4caSwyllys
463130a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
463230a5e8faSwyllys
463330a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
463430a5e8faSwyllys if (keyfile == NULL)
463530a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
463630a5e8faSwyllys
463730a5e8faSwyllys ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
463830a5e8faSwyllys (void *)&keytype, NULL);
463930a5e8faSwyllys if (ret != KMF_OK)
464030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
464130a5e8faSwyllys
464230a5e8faSwyllys ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
464330a5e8faSwyllys &keylen, &keylen_size);
464430a5e8faSwyllys if (ret == KMF_ERR_ATTR_NOT_FOUND &&
464530a5e8faSwyllys (keytype == KMF_DES || keytype == KMF_DES3))
464630a5e8faSwyllys /* keylength is not required for DES and 3DES */
464730a5e8faSwyllys ret = KMF_OK;
464830a5e8faSwyllys if (ret != KMF_OK)
464930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
465030a5e8faSwyllys
465130a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile);
465299ebb4caSwyllys if (fullpath == NULL)
465399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
465499ebb4caSwyllys
465599ebb4caSwyllys /* If the requested file exists, return an error */
465630a5e8faSwyllys if (test_for_file(fullpath, 0400) == 1) {
465799ebb4caSwyllys free(fullpath);
465899ebb4caSwyllys return (KMF_ERR_DUPLICATE_KEYFILE);
465999ebb4caSwyllys }
466099ebb4caSwyllys
466199ebb4caSwyllys fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
466299ebb4caSwyllys if (fd == -1) {
466399ebb4caSwyllys ret = KMF_ERR_OPEN_FILE;
466499ebb4caSwyllys goto out;
466599ebb4caSwyllys }
466699ebb4caSwyllys
466799ebb4caSwyllys rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
466899ebb4caSwyllys if (rkey == NULL) {
466999ebb4caSwyllys ret = KMF_ERR_MEMORY;
467099ebb4caSwyllys goto out;
467199ebb4caSwyllys }
467299ebb4caSwyllys (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
467399ebb4caSwyllys
467430a5e8faSwyllys if (keytype == KMF_DES) {
467599ebb4caSwyllys if ((ret = create_deskey(&deskey)) != KMF_OK) {
467699ebb4caSwyllys goto out;
467799ebb4caSwyllys }
467899ebb4caSwyllys rkey->keydata.val = (uchar_t *)deskey;
467999ebb4caSwyllys rkey->keydata.len = 8;
468099ebb4caSwyllys
468199ebb4caSwyllys symkey->keyalg = KMF_DES;
468299ebb4caSwyllys
468330a5e8faSwyllys } else if (keytype == KMF_DES3) {
468499ebb4caSwyllys if ((ret = create_des3key(&des3key)) != KMF_OK) {
468599ebb4caSwyllys goto out;
468699ebb4caSwyllys }
468799ebb4caSwyllys rkey->keydata.val = (uchar_t *)des3key;
468899ebb4caSwyllys rkey->keydata.len = DES3_KEY_SIZE;
468999ebb4caSwyllys symkey->keyalg = KMF_DES3;
46909b37d296Swyllys
469130a5e8faSwyllys } else if (keytype == KMF_AES || keytype == KMF_RC4 ||
469230a5e8faSwyllys keytype == KMF_GENERIC_SECRET) {
469399ebb4caSwyllys int bytes;
469499ebb4caSwyllys
469530a5e8faSwyllys if (keylen % 8 != 0) {
469699ebb4caSwyllys ret = KMF_ERR_BAD_KEY_SIZE;
469799ebb4caSwyllys goto out;
469899ebb4caSwyllys }
469999ebb4caSwyllys
470030a5e8faSwyllys if (keytype == KMF_AES) {
470130a5e8faSwyllys if (keylen != 128 &&
470230a5e8faSwyllys keylen != 192 &&
470330a5e8faSwyllys keylen != 256) {
470499ebb4caSwyllys ret = KMF_ERR_BAD_KEY_SIZE;
470599ebb4caSwyllys goto out;
470699ebb4caSwyllys }
470799ebb4caSwyllys }
470899ebb4caSwyllys
470930a5e8faSwyllys bytes = keylen/8;
471099ebb4caSwyllys random = malloc(bytes);
471199ebb4caSwyllys if (random == NULL) {
471299ebb4caSwyllys ret = KMF_ERR_MEMORY;
471399ebb4caSwyllys goto out;
471499ebb4caSwyllys }
471599ebb4caSwyllys if (RAND_bytes(random, bytes) != 1) {
471699ebb4caSwyllys ret = KMF_ERR_KEYGEN_FAILED;
471799ebb4caSwyllys goto out;
471899ebb4caSwyllys }
471999ebb4caSwyllys
472099ebb4caSwyllys rkey->keydata.val = (uchar_t *)random;
472199ebb4caSwyllys rkey->keydata.len = bytes;
472230a5e8faSwyllys symkey->keyalg = keytype;
472399ebb4caSwyllys
472499ebb4caSwyllys } else {
472599ebb4caSwyllys ret = KMF_ERR_BAD_KEY_TYPE;
472699ebb4caSwyllys goto out;
472799ebb4caSwyllys }
472899ebb4caSwyllys
472999ebb4caSwyllys (void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
473099ebb4caSwyllys
473199ebb4caSwyllys symkey->kstype = KMF_KEYSTORE_OPENSSL;
473299ebb4caSwyllys symkey->keyclass = KMF_SYMMETRIC;
473399ebb4caSwyllys symkey->keylabel = (char *)fullpath;
473499ebb4caSwyllys symkey->israw = TRUE;
473599ebb4caSwyllys symkey->keyp = rkey;
473699ebb4caSwyllys
473799ebb4caSwyllys out:
473899ebb4caSwyllys if (fd != -1)
473999ebb4caSwyllys (void) close(fd);
474099ebb4caSwyllys
474199ebb4caSwyllys if (ret != KMF_OK && fullpath != NULL) {
474299ebb4caSwyllys free(fullpath);
474399ebb4caSwyllys }
474499ebb4caSwyllys if (ret != KMF_OK) {
474530a5e8faSwyllys kmf_free_raw_sym_key(rkey);
474699ebb4caSwyllys symkey->keyp = NULL;
474799ebb4caSwyllys symkey->keyalg = KMF_KEYALG_NONE;
474899ebb4caSwyllys }
474999ebb4caSwyllys
475099ebb4caSwyllys return (ret);
475199ebb4caSwyllys }
475299ebb4caSwyllys
475399ebb4caSwyllys /*
475499ebb4caSwyllys * Check a file to see if it is a CRL file with PEM or DER format.
475599ebb4caSwyllys * If success, return its format in the "pformat" argument.
475699ebb4caSwyllys */
475799ebb4caSwyllys KMF_RETURN
OpenSSL_IsCRLFile(KMF_HANDLE_T handle,char * filename,int * pformat)475899ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
475999ebb4caSwyllys {
476099ebb4caSwyllys KMF_RETURN ret = KMF_OK;
476199ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
476299ebb4caSwyllys BIO *bio = NULL;
476399ebb4caSwyllys X509_CRL *xcrl = NULL;
476499ebb4caSwyllys
476599ebb4caSwyllys if (filename == NULL) {
476699ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
476799ebb4caSwyllys }
476899ebb4caSwyllys
476999ebb4caSwyllys bio = BIO_new_file(filename, "rb");
477099ebb4caSwyllys if (bio == NULL) {
477199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
477299ebb4caSwyllys ret = KMF_ERR_OPEN_FILE;
477399ebb4caSwyllys goto out;
477499ebb4caSwyllys }
477599ebb4caSwyllys
477699ebb4caSwyllys if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
477799ebb4caSwyllys *pformat = KMF_FORMAT_PEM;
477899ebb4caSwyllys goto out;
477999ebb4caSwyllys }
478099ebb4caSwyllys (void) BIO_free(bio);
478199ebb4caSwyllys
478299ebb4caSwyllys /*
478399ebb4caSwyllys * Now try to read it as raw DER data.
478499ebb4caSwyllys */
478599ebb4caSwyllys bio = BIO_new_file(filename, "rb");
478699ebb4caSwyllys if (bio == NULL) {
478799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error());
478899ebb4caSwyllys ret = KMF_ERR_OPEN_FILE;
478999ebb4caSwyllys goto out;
479099ebb4caSwyllys }
479199ebb4caSwyllys
479299ebb4caSwyllys if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
479399ebb4caSwyllys *pformat = KMF_FORMAT_ASN1;
479499ebb4caSwyllys } else {
479599ebb4caSwyllys ret = KMF_ERR_BAD_CRLFILE;
479699ebb4caSwyllys }
479799ebb4caSwyllys
479899ebb4caSwyllys out:
479999ebb4caSwyllys if (bio != NULL)
480099ebb4caSwyllys (void) BIO_free(bio);
480199ebb4caSwyllys
480299ebb4caSwyllys if (xcrl != NULL)
480399ebb4caSwyllys X509_CRL_free(xcrl);
480499ebb4caSwyllys
480599ebb4caSwyllys return (ret);
480699ebb4caSwyllys }
480799ebb4caSwyllys
480899ebb4caSwyllys KMF_RETURN
OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle,KMF_KEY_HANDLE * symkey,KMF_RAW_SYM_KEY * rkey)480999ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
481099ebb4caSwyllys KMF_RAW_SYM_KEY *rkey)
481199ebb4caSwyllys {
481299ebb4caSwyllys KMF_RETURN rv = KMF_OK;
481399ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
481499ebb4caSwyllys KMF_DATA keyvalue;
481599ebb4caSwyllys
481699ebb4caSwyllys if (kmfh == NULL)
481799ebb4caSwyllys return (KMF_ERR_UNINITIALIZED);
481899ebb4caSwyllys
481999ebb4caSwyllys if (symkey == NULL || rkey == NULL)
482099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
482199ebb4caSwyllys else if (symkey->keyclass != KMF_SYMMETRIC)
482299ebb4caSwyllys return (KMF_ERR_BAD_KEY_CLASS);
482399ebb4caSwyllys
482499ebb4caSwyllys if (symkey->israw) {
482599ebb4caSwyllys KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
482699ebb4caSwyllys
482799ebb4caSwyllys if (rawkey == NULL ||
482899ebb4caSwyllys rawkey->keydata.val == NULL ||
482999ebb4caSwyllys rawkey->keydata.len == 0)
483099ebb4caSwyllys return (KMF_ERR_BAD_KEYHANDLE);
483199ebb4caSwyllys
483299ebb4caSwyllys rkey->keydata.len = rawkey->keydata.len;
483399ebb4caSwyllys if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
483499ebb4caSwyllys return (KMF_ERR_MEMORY);
483599ebb4caSwyllys (void) memcpy(rkey->keydata.val, rawkey->keydata.val,
483699ebb4caSwyllys rkey->keydata.len);
483799ebb4caSwyllys } else {
483830a5e8faSwyllys rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
483999ebb4caSwyllys if (rv != KMF_OK)
484099ebb4caSwyllys return (rv);
484199ebb4caSwyllys rkey->keydata.len = keyvalue.Length;
484299ebb4caSwyllys rkey->keydata.val = keyvalue.Data;
484399ebb4caSwyllys }
484499ebb4caSwyllys
484599ebb4caSwyllys return (rv);
484699ebb4caSwyllys }
484702744e81Swyllys
484802744e81Swyllys /*
484930a5e8faSwyllys * substitute for the unsafe access(2) function.
485030a5e8faSwyllys * If the file in question already exists, return 1.
485130a5e8faSwyllys * else 0. If an error occurs during testing (other
485230a5e8faSwyllys * than EEXIST), return -1.
485330a5e8faSwyllys */
485430a5e8faSwyllys static int
test_for_file(char * filename,mode_t mode)485530a5e8faSwyllys test_for_file(char *filename, mode_t mode)
485630a5e8faSwyllys {
485730a5e8faSwyllys int fd;
485830a5e8faSwyllys
485930a5e8faSwyllys /*
486030a5e8faSwyllys * Try to create the file with the EXCL flag.
486130a5e8faSwyllys * The call should fail if the file exists.
486230a5e8faSwyllys */
486330a5e8faSwyllys fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
486430a5e8faSwyllys if (fd == -1 && errno == EEXIST)
486530a5e8faSwyllys return (1);
486630a5e8faSwyllys else if (fd == -1) /* some other error */
486730a5e8faSwyllys return (-1);
486830a5e8faSwyllys
486930a5e8faSwyllys /* The file did NOT exist. Delete the testcase. */
487030a5e8faSwyllys (void) close(fd);
487130a5e8faSwyllys (void) unlink(filename);
487230a5e8faSwyllys return (0);
487330a5e8faSwyllys }
487430a5e8faSwyllys
487530a5e8faSwyllys KMF_RETURN
OpenSSL_StoreKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)48764942e222SAndy Fiddaman OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
487730a5e8faSwyllys {
487830a5e8faSwyllys KMF_RETURN rv = KMF_OK;
487930a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
488030a5e8faSwyllys KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
488130a5e8faSwyllys KMF_RAW_KEY_DATA *rawkey;
488230a5e8faSwyllys EVP_PKEY *pkey = NULL;
488330a5e8faSwyllys KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
488430a5e8faSwyllys KMF_CREDENTIAL cred = { NULL, 0 };
488530a5e8faSwyllys BIO *out = NULL;
488630a5e8faSwyllys int keys = 0;
488730a5e8faSwyllys char *fullpath = NULL;
488830a5e8faSwyllys char *keyfile = NULL;
488930a5e8faSwyllys char *dirpath = NULL;
489030a5e8faSwyllys
489130a5e8faSwyllys pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
489230a5e8faSwyllys if (pubkey != NULL)
489330a5e8faSwyllys keys++;
489430a5e8faSwyllys
489530a5e8faSwyllys prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
489630a5e8faSwyllys if (prikey != NULL)
489730a5e8faSwyllys keys++;
489830a5e8faSwyllys
489930a5e8faSwyllys rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
490030a5e8faSwyllys if (rawkey != NULL)
490130a5e8faSwyllys keys++;
490230a5e8faSwyllys
490330a5e8faSwyllys /*
490430a5e8faSwyllys * Exactly 1 type of key must be passed to this function.
490530a5e8faSwyllys */
490630a5e8faSwyllys if (keys != 1)
490730a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
490830a5e8faSwyllys
490930a5e8faSwyllys keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
491030a5e8faSwyllys numattr);
491130a5e8faSwyllys if (keyfile == NULL)
491230a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
491330a5e8faSwyllys
491430a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
491530a5e8faSwyllys
491630a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile);
491730a5e8faSwyllys
491830a5e8faSwyllys /* Once we have the full path, we don't need the pieces */
491930a5e8faSwyllys if (fullpath == NULL)
492030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
492130a5e8faSwyllys
492230a5e8faSwyllys /* If the requested file exists, return an error */
492330a5e8faSwyllys if (test_for_file(fullpath, 0400) == 1) {
492430a5e8faSwyllys free(fullpath);
492530a5e8faSwyllys return (KMF_ERR_DUPLICATE_KEYFILE);
492630a5e8faSwyllys }
492730a5e8faSwyllys
492830a5e8faSwyllys rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
492930a5e8faSwyllys &format, NULL);
493030a5e8faSwyllys if (rv != KMF_OK)
493130a5e8faSwyllys /* format is optional. */
493230a5e8faSwyllys rv = KMF_OK;
493330a5e8faSwyllys
493430a5e8faSwyllys /* CRED is not required for OpenSSL files */
493530a5e8faSwyllys (void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
493630a5e8faSwyllys &cred, NULL);
493730a5e8faSwyllys
493830a5e8faSwyllys /* Store the private key to the keyfile */
493930a5e8faSwyllys out = BIO_new_file(fullpath, "wb");
494030a5e8faSwyllys if (out == NULL) {
494130a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
494230a5e8faSwyllys rv = KMF_ERR_OPEN_FILE;
494330a5e8faSwyllys goto end;
494430a5e8faSwyllys }
494530a5e8faSwyllys
494630a5e8faSwyllys if (prikey != NULL && prikey->keyp != NULL) {
494730a5e8faSwyllys if (prikey->keyalg == KMF_RSA ||
494830a5e8faSwyllys prikey->keyalg == KMF_DSA) {
494930a5e8faSwyllys pkey = (EVP_PKEY *)prikey->keyp;
495030a5e8faSwyllys
495130a5e8faSwyllys rv = ssl_write_key(kmfh, format,
495230a5e8faSwyllys out, &cred, pkey, TRUE);
495330a5e8faSwyllys
495430a5e8faSwyllys if (rv == KMF_OK && prikey->keylabel == NULL) {
495530a5e8faSwyllys prikey->keylabel = strdup(fullpath);
495630a5e8faSwyllys if (prikey->keylabel == NULL)
495730a5e8faSwyllys rv = KMF_ERR_MEMORY;
495830a5e8faSwyllys }
495930a5e8faSwyllys }
496030a5e8faSwyllys } else if (pubkey != NULL && pubkey->keyp != NULL) {
496130a5e8faSwyllys if (pubkey->keyalg == KMF_RSA ||
496230a5e8faSwyllys pubkey->keyalg == KMF_DSA) {
496330a5e8faSwyllys pkey = (EVP_PKEY *)pubkey->keyp;
496430a5e8faSwyllys
496530a5e8faSwyllys rv = ssl_write_key(kmfh, format,
496630a5e8faSwyllys out, &cred, pkey, FALSE);
496730a5e8faSwyllys
496830a5e8faSwyllys if (rv == KMF_OK && pubkey->keylabel == NULL) {
496930a5e8faSwyllys pubkey->keylabel = strdup(fullpath);
497030a5e8faSwyllys if (pubkey->keylabel == NULL)
497130a5e8faSwyllys rv = KMF_ERR_MEMORY;
497230a5e8faSwyllys }
497330a5e8faSwyllys }
497430a5e8faSwyllys } else if (rawkey != NULL) {
497530a5e8faSwyllys if (rawkey->keytype == KMF_RSA) {
497630a5e8faSwyllys pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
497730a5e8faSwyllys } else if (rawkey->keytype == KMF_DSA) {
497830a5e8faSwyllys pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
497930a5e8faSwyllys } else {
498030a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER;
498130a5e8faSwyllys }
49825b3e1433Swyllys if (pkey != NULL) {
498373cc0e02Swyllys KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
498473cc0e02Swyllys
498573cc0e02Swyllys rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
498673cc0e02Swyllys (void *)&kclass, NULL);
498773cc0e02Swyllys if (rv != KMF_OK)
498873cc0e02Swyllys rv = KMF_OK;
49895b3e1433Swyllys rv = ssl_write_key(kmfh, format, out,
499073cc0e02Swyllys &cred, pkey, (kclass == KMF_ASYM_PRI));
49915b3e1433Swyllys EVP_PKEY_free(pkey);
49925b3e1433Swyllys }
499330a5e8faSwyllys }
499430a5e8faSwyllys
499530a5e8faSwyllys end:
499630a5e8faSwyllys
499730a5e8faSwyllys if (out)
499830a5e8faSwyllys (void) BIO_free(out);
499930a5e8faSwyllys
50005b3e1433Swyllys
500130a5e8faSwyllys if (rv == KMF_OK)
500230a5e8faSwyllys (void) chmod(fullpath, 0400);
500330a5e8faSwyllys
500430a5e8faSwyllys free(fullpath);
500530a5e8faSwyllys return (rv);
500630a5e8faSwyllys }
500730a5e8faSwyllys
500830a5e8faSwyllys KMF_RETURN
OpenSSL_ImportCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)500930a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
501030a5e8faSwyllys {
501130a5e8faSwyllys KMF_RETURN ret = KMF_OK;
501230a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
501330a5e8faSwyllys X509_CRL *xcrl = NULL;
501430a5e8faSwyllys X509 *xcert = NULL;
501530a5e8faSwyllys EVP_PKEY *pkey;
501630a5e8faSwyllys KMF_ENCODE_FORMAT format;
501730a5e8faSwyllys BIO *in = NULL, *out = NULL;
501830a5e8faSwyllys int openssl_ret = 0;
501930a5e8faSwyllys KMF_ENCODE_FORMAT outformat;
502030a5e8faSwyllys boolean_t crlcheck = FALSE;
502130a5e8faSwyllys char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
502230a5e8faSwyllys
502330a5e8faSwyllys if (numattr == 0 || attrlist == NULL) {
502430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
502530a5e8faSwyllys }
502630a5e8faSwyllys
502730a5e8faSwyllys /* CRL check is optional */
502830a5e8faSwyllys (void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
502930a5e8faSwyllys &crlcheck, NULL);
503030a5e8faSwyllys
503130a5e8faSwyllys certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
503230a5e8faSwyllys if (crlcheck == B_TRUE && certfile == NULL) {
503330a5e8faSwyllys return (KMF_ERR_BAD_CERTFILE);
503430a5e8faSwyllys }
503530a5e8faSwyllys
503630a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
503730a5e8faSwyllys incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
503830a5e8faSwyllys outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
503930a5e8faSwyllys
504030a5e8faSwyllys crlfile = get_fullpath(dirpath, incrl);
504130a5e8faSwyllys
504230a5e8faSwyllys if (crlfile == NULL)
504330a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE);
504430a5e8faSwyllys
504530a5e8faSwyllys outcrlfile = get_fullpath(dirpath, outcrl);
504630a5e8faSwyllys if (outcrlfile == NULL)
504730a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE);
504830a5e8faSwyllys
504930a5e8faSwyllys if (isdir(outcrlfile)) {
505030a5e8faSwyllys free(outcrlfile);
505130a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE);
505230a5e8faSwyllys }
505330a5e8faSwyllys
505430a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format);
505530a5e8faSwyllys if (ret != KMF_OK) {
505630a5e8faSwyllys free(outcrlfile);
505730a5e8faSwyllys return (ret);
505830a5e8faSwyllys }
505930a5e8faSwyllys
506030a5e8faSwyllys in = BIO_new_file(crlfile, "rb");
506130a5e8faSwyllys if (in == NULL) {
506230a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
506330a5e8faSwyllys ret = KMF_ERR_OPEN_FILE;
506430a5e8faSwyllys goto end;
506530a5e8faSwyllys }
506630a5e8faSwyllys
506730a5e8faSwyllys if (format == KMF_FORMAT_ASN1) {
506830a5e8faSwyllys xcrl = d2i_X509_CRL_bio(in, NULL);
506930a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) {
507030a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
507130a5e8faSwyllys }
507230a5e8faSwyllys
507330a5e8faSwyllys if (xcrl == NULL) {
507430a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
507530a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE;
507630a5e8faSwyllys goto end;
507730a5e8faSwyllys }
507830a5e8faSwyllys
507930a5e8faSwyllys /* If bypasscheck is specified, no need to verify. */
508030a5e8faSwyllys if (crlcheck == B_FALSE)
508130a5e8faSwyllys goto output;
508230a5e8faSwyllys
508330a5e8faSwyllys ret = kmf_is_cert_file(handle, certfile, &format);
508430a5e8faSwyllys if (ret != KMF_OK)
508530a5e8faSwyllys goto end;
508630a5e8faSwyllys
508730a5e8faSwyllys /* Read in the CA cert file and convert to X509 */
508830a5e8faSwyllys if (BIO_read_filename(in, certfile) <= 0) {
508930a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
509030a5e8faSwyllys ret = KMF_ERR_OPEN_FILE;
509130a5e8faSwyllys goto end;
509230a5e8faSwyllys }
509330a5e8faSwyllys
509430a5e8faSwyllys if (format == KMF_FORMAT_ASN1) {
509530a5e8faSwyllys xcert = d2i_X509_bio(in, NULL);
509630a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) {
509730a5e8faSwyllys xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
509830a5e8faSwyllys } else {
509930a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
510030a5e8faSwyllys goto end;
510130a5e8faSwyllys }
510230a5e8faSwyllys
510330a5e8faSwyllys if (xcert == NULL) {
510430a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
510530a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
510630a5e8faSwyllys goto end;
510730a5e8faSwyllys }
510830a5e8faSwyllys /* Now get the public key from the CA cert */
510930a5e8faSwyllys pkey = X509_get_pubkey(xcert);
511030a5e8faSwyllys if (pkey == NULL) {
511130a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
511230a5e8faSwyllys ret = KMF_ERR_BAD_CERTFILE;
511330a5e8faSwyllys goto end;
511430a5e8faSwyllys }
511530a5e8faSwyllys
511630a5e8faSwyllys /* Verify the CRL with the CA's public key */
511730a5e8faSwyllys openssl_ret = X509_CRL_verify(xcrl, pkey);
511830a5e8faSwyllys EVP_PKEY_free(pkey);
511930a5e8faSwyllys if (openssl_ret > 0) {
512030a5e8faSwyllys ret = KMF_OK; /* verify succeed */
512130a5e8faSwyllys } else {
512230a5e8faSwyllys SET_ERROR(kmfh, openssl_ret);
512330a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE;
512430a5e8faSwyllys }
512530a5e8faSwyllys
512630a5e8faSwyllys output:
512730a5e8faSwyllys ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
512830a5e8faSwyllys &outformat, NULL);
512930a5e8faSwyllys if (ret != KMF_OK) {
513030a5e8faSwyllys ret = KMF_OK;
513130a5e8faSwyllys outformat = KMF_FORMAT_PEM;
513230a5e8faSwyllys }
513330a5e8faSwyllys
513430a5e8faSwyllys out = BIO_new_file(outcrlfile, "wb");
513530a5e8faSwyllys if (out == NULL) {
513630a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
513730a5e8faSwyllys ret = KMF_ERR_OPEN_FILE;
513830a5e8faSwyllys goto end;
513930a5e8faSwyllys }
514030a5e8faSwyllys
514130a5e8faSwyllys if (outformat == KMF_FORMAT_ASN1) {
514230a5e8faSwyllys openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
514330a5e8faSwyllys } else if (outformat == KMF_FORMAT_PEM) {
514430a5e8faSwyllys openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
514530a5e8faSwyllys } else {
514630a5e8faSwyllys ret = KMF_ERR_BAD_PARAMETER;
514730a5e8faSwyllys goto end;
514830a5e8faSwyllys }
514930a5e8faSwyllys
515030a5e8faSwyllys if (openssl_ret <= 0) {
515130a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
515230a5e8faSwyllys ret = KMF_ERR_WRITE_FILE;
515330a5e8faSwyllys } else {
515430a5e8faSwyllys ret = KMF_OK;
515530a5e8faSwyllys }
515630a5e8faSwyllys
515730a5e8faSwyllys end:
515830a5e8faSwyllys if (xcrl != NULL)
515930a5e8faSwyllys X509_CRL_free(xcrl);
516030a5e8faSwyllys
516130a5e8faSwyllys if (xcert != NULL)
516230a5e8faSwyllys X509_free(xcert);
516330a5e8faSwyllys
516430a5e8faSwyllys if (in != NULL)
516530a5e8faSwyllys (void) BIO_free(in);
516630a5e8faSwyllys
516730a5e8faSwyllys if (out != NULL)
516830a5e8faSwyllys (void) BIO_free(out);
516930a5e8faSwyllys
517030a5e8faSwyllys if (outcrlfile != NULL)
517130a5e8faSwyllys free(outcrlfile);
517230a5e8faSwyllys
517330a5e8faSwyllys return (ret);
517430a5e8faSwyllys }
517530a5e8faSwyllys
517630a5e8faSwyllys KMF_RETURN
OpenSSL_ListCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)517730a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
517830a5e8faSwyllys {
517930a5e8faSwyllys KMF_RETURN ret = KMF_OK;
518030a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
518130a5e8faSwyllys X509_CRL *x = NULL;
518230a5e8faSwyllys KMF_ENCODE_FORMAT format;
518330a5e8faSwyllys char *crlfile = NULL;
518430a5e8faSwyllys BIO *in = NULL;
518530a5e8faSwyllys BIO *mem = NULL;
518630a5e8faSwyllys long len;
518730a5e8faSwyllys char *memptr;
518830a5e8faSwyllys char *data = NULL;
518930a5e8faSwyllys char **crldata;
519030a5e8faSwyllys char *crlfilename, *dirpath;
519130a5e8faSwyllys
519230a5e8faSwyllys if (numattr == 0 || attrlist == NULL) {
519330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
519430a5e8faSwyllys }
519530a5e8faSwyllys crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
519630a5e8faSwyllys attrlist, numattr);
519730a5e8faSwyllys if (crlfilename == NULL)
519830a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE);
519930a5e8faSwyllys
520030a5e8faSwyllys crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
520130a5e8faSwyllys attrlist, numattr);
520230a5e8faSwyllys
520330a5e8faSwyllys if (crldata == NULL)
520430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
520530a5e8faSwyllys
520630a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
520730a5e8faSwyllys
520830a5e8faSwyllys crlfile = get_fullpath(dirpath, crlfilename);
520930a5e8faSwyllys
521030a5e8faSwyllys if (crlfile == NULL)
521130a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE);
521230a5e8faSwyllys
521330a5e8faSwyllys if (isdir(crlfile)) {
521430a5e8faSwyllys free(crlfile);
521530a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE);
521630a5e8faSwyllys }
521730a5e8faSwyllys
521830a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format);
521930a5e8faSwyllys if (ret != KMF_OK) {
522030a5e8faSwyllys free(crlfile);
522130a5e8faSwyllys return (ret);
522230a5e8faSwyllys }
522330a5e8faSwyllys
522430a5e8faSwyllys if (bio_err == NULL)
522530a5e8faSwyllys bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
522630a5e8faSwyllys
522730a5e8faSwyllys in = BIO_new_file(crlfile, "rb");
522830a5e8faSwyllys if (in == NULL) {
522930a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
523030a5e8faSwyllys ret = KMF_ERR_OPEN_FILE;
523130a5e8faSwyllys goto end;
523230a5e8faSwyllys }
523330a5e8faSwyllys
523430a5e8faSwyllys if (format == KMF_FORMAT_ASN1) {
523530a5e8faSwyllys x = d2i_X509_CRL_bio(in, NULL);
523630a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) {
523730a5e8faSwyllys x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
523830a5e8faSwyllys }
523930a5e8faSwyllys
524030a5e8faSwyllys if (x == NULL) { /* should not happen */
524130a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
524230a5e8faSwyllys ret = KMF_ERR_OPEN_FILE;
524330a5e8faSwyllys goto end;
524430a5e8faSwyllys }
524530a5e8faSwyllys
524630a5e8faSwyllys mem = BIO_new(BIO_s_mem());
524730a5e8faSwyllys if (mem == NULL) {
524830a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
524930a5e8faSwyllys ret = KMF_ERR_MEMORY;
525030a5e8faSwyllys goto end;
525130a5e8faSwyllys }
525230a5e8faSwyllys
525330a5e8faSwyllys (void) X509_CRL_print(mem, x);
525430a5e8faSwyllys len = BIO_get_mem_data(mem, &memptr);
525530a5e8faSwyllys if (len <= 0) {
525630a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
525730a5e8faSwyllys ret = KMF_ERR_MEMORY;
525830a5e8faSwyllys goto end;
525930a5e8faSwyllys }
526030a5e8faSwyllys
526130a5e8faSwyllys data = malloc(len + 1);
526230a5e8faSwyllys if (data == NULL) {
526330a5e8faSwyllys ret = KMF_ERR_MEMORY;
526430a5e8faSwyllys goto end;
526530a5e8faSwyllys }
526630a5e8faSwyllys
526730a5e8faSwyllys (void) memcpy(data, memptr, len);
526830a5e8faSwyllys data[len] = '\0';
526930a5e8faSwyllys *crldata = data;
527030a5e8faSwyllys
527130a5e8faSwyllys end:
527230a5e8faSwyllys if (x != NULL)
527330a5e8faSwyllys X509_CRL_free(x);
527430a5e8faSwyllys
527530a5e8faSwyllys if (crlfile != NULL)
527630a5e8faSwyllys free(crlfile);
527730a5e8faSwyllys
527830a5e8faSwyllys if (in != NULL)
527930a5e8faSwyllys (void) BIO_free(in);
528030a5e8faSwyllys
528130a5e8faSwyllys if (mem != NULL)
528230a5e8faSwyllys (void) BIO_free(mem);
528330a5e8faSwyllys
528430a5e8faSwyllys return (ret);
528530a5e8faSwyllys }
528630a5e8faSwyllys
528730a5e8faSwyllys KMF_RETURN
OpenSSL_DeleteCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)528830a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
528930a5e8faSwyllys {
529030a5e8faSwyllys KMF_RETURN ret = KMF_OK;
529130a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
529230a5e8faSwyllys KMF_ENCODE_FORMAT format;
529330a5e8faSwyllys char *crlfile = NULL;
529430a5e8faSwyllys BIO *in = NULL;
529530a5e8faSwyllys char *crlfilename, *dirpath;
529630a5e8faSwyllys
529730a5e8faSwyllys if (numattr == 0 || attrlist == NULL) {
529830a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
529930a5e8faSwyllys }
530030a5e8faSwyllys
530130a5e8faSwyllys crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
530230a5e8faSwyllys attrlist, numattr);
530330a5e8faSwyllys
530430a5e8faSwyllys if (crlfilename == NULL)
530530a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE);
530630a5e8faSwyllys
530730a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
530830a5e8faSwyllys
530930a5e8faSwyllys crlfile = get_fullpath(dirpath, crlfilename);
531030a5e8faSwyllys
531130a5e8faSwyllys if (crlfile == NULL)
531230a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE);
531330a5e8faSwyllys
531430a5e8faSwyllys if (isdir(crlfile)) {
531530a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE;
531630a5e8faSwyllys goto end;
531730a5e8faSwyllys }
531830a5e8faSwyllys
531930a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format);
532030a5e8faSwyllys if (ret != KMF_OK)
532130a5e8faSwyllys goto end;
532230a5e8faSwyllys
532330a5e8faSwyllys if (unlink(crlfile) != 0) {
532430a5e8faSwyllys SET_SYS_ERROR(kmfh, errno);
532530a5e8faSwyllys ret = KMF_ERR_INTERNAL;
532630a5e8faSwyllys goto end;
532730a5e8faSwyllys }
532830a5e8faSwyllys
532930a5e8faSwyllys end:
533030a5e8faSwyllys if (in != NULL)
533130a5e8faSwyllys (void) BIO_free(in);
533230a5e8faSwyllys if (crlfile != NULL)
533330a5e8faSwyllys free(crlfile);
533430a5e8faSwyllys
533530a5e8faSwyllys return (ret);
533630a5e8faSwyllys }
533730a5e8faSwyllys
533830a5e8faSwyllys KMF_RETURN
OpenSSL_FindCertInCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)533930a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
534030a5e8faSwyllys {
534130a5e8faSwyllys KMF_RETURN ret = KMF_OK;
534230a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
534330a5e8faSwyllys KMF_ENCODE_FORMAT format;
534430a5e8faSwyllys BIO *in = NULL;
534530a5e8faSwyllys X509 *xcert = NULL;
534630a5e8faSwyllys X509_CRL *xcrl = NULL;
534730a5e8faSwyllys STACK_OF(X509_REVOKED) *revoke_stack = NULL;
534830a5e8faSwyllys X509_REVOKED *revoke;
534930a5e8faSwyllys int i;
535030a5e8faSwyllys char *crlfilename, *crlfile, *dirpath, *certfile;
535130a5e8faSwyllys
535230a5e8faSwyllys if (numattr == 0 || attrlist == NULL) {
535330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
535430a5e8faSwyllys }
535530a5e8faSwyllys
535630a5e8faSwyllys crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
535730a5e8faSwyllys attrlist, numattr);
535830a5e8faSwyllys
535930a5e8faSwyllys if (crlfilename == NULL)
536030a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE);
536130a5e8faSwyllys
536230a5e8faSwyllys certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
536330a5e8faSwyllys if (certfile == NULL)
536430a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE);
536530a5e8faSwyllys
536630a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
536730a5e8faSwyllys
536830a5e8faSwyllys crlfile = get_fullpath(dirpath, crlfilename);
536930a5e8faSwyllys
537030a5e8faSwyllys if (crlfile == NULL)
537130a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE);
537230a5e8faSwyllys
537330a5e8faSwyllys if (isdir(crlfile)) {
537430a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE;
537530a5e8faSwyllys goto end;
537630a5e8faSwyllys }
537730a5e8faSwyllys
537830a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format);
537930a5e8faSwyllys if (ret != KMF_OK)
538030a5e8faSwyllys goto end;
538130a5e8faSwyllys
538230a5e8faSwyllys /* Read the CRL file and load it into a X509_CRL structure */
538330a5e8faSwyllys in = BIO_new_file(crlfilename, "rb");
538430a5e8faSwyllys if (in == NULL) {
538530a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
538630a5e8faSwyllys ret = KMF_ERR_OPEN_FILE;
538730a5e8faSwyllys goto end;
538830a5e8faSwyllys }
538930a5e8faSwyllys
539030a5e8faSwyllys if (format == KMF_FORMAT_ASN1) {
539130a5e8faSwyllys xcrl = d2i_X509_CRL_bio(in, NULL);
539230a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) {
539330a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
539430a5e8faSwyllys }
539530a5e8faSwyllys
539630a5e8faSwyllys if (xcrl == NULL) {
539730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
539830a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE;
539930a5e8faSwyllys goto end;
540030a5e8faSwyllys }
540130a5e8faSwyllys (void) BIO_free(in);
540230a5e8faSwyllys
540330a5e8faSwyllys /* Read the Certificate file and load it into a X509 structure */
540430a5e8faSwyllys ret = kmf_is_cert_file(handle, certfile, &format);
540530a5e8faSwyllys if (ret != KMF_OK)
540630a5e8faSwyllys goto end;
540730a5e8faSwyllys
540830a5e8faSwyllys in = BIO_new_file(certfile, "rb");
540930a5e8faSwyllys if (in == NULL) {
541030a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
541130a5e8faSwyllys ret = KMF_ERR_OPEN_FILE;
541230a5e8faSwyllys goto end;
541330a5e8faSwyllys }
541430a5e8faSwyllys
541530a5e8faSwyllys if (format == KMF_FORMAT_ASN1) {
541630a5e8faSwyllys xcert = d2i_X509_bio(in, NULL);
541730a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) {
541830a5e8faSwyllys xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
541930a5e8faSwyllys }
542030a5e8faSwyllys
542130a5e8faSwyllys if (xcert == NULL) {
542230a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
542330a5e8faSwyllys ret = KMF_ERR_BAD_CERTFILE;
542430a5e8faSwyllys goto end;
542530a5e8faSwyllys }
542630a5e8faSwyllys
542730a5e8faSwyllys /* Check if the certificate and the CRL have same issuer */
5428300fdee2SAndy Fiddaman if (X509_NAME_cmp(X509_get_issuer_name(xcert),
5429300fdee2SAndy Fiddaman X509_CRL_get_issuer(xcrl)) != 0) {
543030a5e8faSwyllys ret = KMF_ERR_ISSUER;
543130a5e8faSwyllys goto end;
543230a5e8faSwyllys }
543330a5e8faSwyllys
543430a5e8faSwyllys /* Check to see if the certificate serial number is revoked */
543530a5e8faSwyllys revoke_stack = X509_CRL_get_REVOKED(xcrl);
543630a5e8faSwyllys if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
543730a5e8faSwyllys /* No revoked certificates in the CRL file */
543830a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
543930a5e8faSwyllys ret = KMF_ERR_EMPTY_CRL;
544030a5e8faSwyllys goto end;
544130a5e8faSwyllys }
544230a5e8faSwyllys
544330a5e8faSwyllys for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
544430a5e8faSwyllys revoke = sk_X509_REVOKED_value(revoke_stack, i);
5445300fdee2SAndy Fiddaman if (ASN1_INTEGER_cmp(X509_get_serialNumber(xcert),
5446300fdee2SAndy Fiddaman X509_REVOKED_get0_serialNumber(revoke)) == 0) {
544730a5e8faSwyllys break;
544830a5e8faSwyllys }
544930a5e8faSwyllys }
545030a5e8faSwyllys
545130a5e8faSwyllys if (i < sk_X509_REVOKED_num(revoke_stack)) {
545230a5e8faSwyllys ret = KMF_OK;
545330a5e8faSwyllys } else {
545430a5e8faSwyllys ret = KMF_ERR_NOT_REVOKED;
545530a5e8faSwyllys }
545630a5e8faSwyllys
545730a5e8faSwyllys end:
545830a5e8faSwyllys if (in != NULL)
545930a5e8faSwyllys (void) BIO_free(in);
546030a5e8faSwyllys if (xcrl != NULL)
546130a5e8faSwyllys X509_CRL_free(xcrl);
546230a5e8faSwyllys if (xcert != NULL)
546330a5e8faSwyllys X509_free(xcert);
546430a5e8faSwyllys
546530a5e8faSwyllys return (ret);
546630a5e8faSwyllys }
546730a5e8faSwyllys
546830a5e8faSwyllys KMF_RETURN
OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle,char * crlname,KMF_DATA * tacert)546930a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
547030a5e8faSwyllys {
547130a5e8faSwyllys KMF_RETURN ret = KMF_OK;
547230a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
547330a5e8faSwyllys BIO *bcrl = NULL;
547430a5e8faSwyllys X509_CRL *xcrl = NULL;
547530a5e8faSwyllys X509 *xcert = NULL;
547630a5e8faSwyllys EVP_PKEY *pkey;
547730a5e8faSwyllys int sslret;
547830a5e8faSwyllys KMF_ENCODE_FORMAT crl_format;
547930a5e8faSwyllys unsigned char *p;
548030a5e8faSwyllys long len;
548130a5e8faSwyllys
548230a5e8faSwyllys if (handle == NULL || crlname == NULL || tacert == NULL) {
548330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
548430a5e8faSwyllys }
548530a5e8faSwyllys
548630a5e8faSwyllys ret = kmf_get_file_format(crlname, &crl_format);
548730a5e8faSwyllys if (ret != KMF_OK)
548830a5e8faSwyllys return (ret);
548930a5e8faSwyllys
549030a5e8faSwyllys bcrl = BIO_new_file(crlname, "rb");
549130a5e8faSwyllys if (bcrl == NULL) {
549230a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
549330a5e8faSwyllys ret = KMF_ERR_OPEN_FILE;
549430a5e8faSwyllys goto cleanup;
549530a5e8faSwyllys }
549630a5e8faSwyllys
549730a5e8faSwyllys if (crl_format == KMF_FORMAT_ASN1) {
549830a5e8faSwyllys xcrl = d2i_X509_CRL_bio(bcrl, NULL);
549930a5e8faSwyllys } else if (crl_format == KMF_FORMAT_PEM) {
550030a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
550130a5e8faSwyllys } else {
550230a5e8faSwyllys ret = KMF_ERR_BAD_PARAMETER;
550330a5e8faSwyllys goto cleanup;
550430a5e8faSwyllys }
550530a5e8faSwyllys
550630a5e8faSwyllys if (xcrl == NULL) {
550730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
550830a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE;
550930a5e8faSwyllys goto cleanup;
551030a5e8faSwyllys }
551130a5e8faSwyllys
551230a5e8faSwyllys p = tacert->Data;
551330a5e8faSwyllys len = tacert->Length;
551430a5e8faSwyllys xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
551530a5e8faSwyllys
551630a5e8faSwyllys if (xcert == NULL) {
551730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
551830a5e8faSwyllys ret = KMF_ERR_BAD_CERTFILE;
551930a5e8faSwyllys goto cleanup;
552030a5e8faSwyllys }
552130a5e8faSwyllys
552230a5e8faSwyllys /* Get issuer certificate public key */
552330a5e8faSwyllys pkey = X509_get_pubkey(xcert);
552430a5e8faSwyllys if (pkey == NULL) {
552530a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
552630a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
552730a5e8faSwyllys goto cleanup;
552830a5e8faSwyllys }
552930a5e8faSwyllys
553030a5e8faSwyllys /* Verify CRL signature */
553130a5e8faSwyllys sslret = X509_CRL_verify(xcrl, pkey);
553230a5e8faSwyllys EVP_PKEY_free(pkey);
553330a5e8faSwyllys if (sslret > 0) {
553430a5e8faSwyllys ret = KMF_OK;
553530a5e8faSwyllys } else {
553630a5e8faSwyllys SET_ERROR(kmfh, sslret);
553730a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE;
553830a5e8faSwyllys }
553930a5e8faSwyllys
554030a5e8faSwyllys cleanup:
554130a5e8faSwyllys if (bcrl != NULL)
554230a5e8faSwyllys (void) BIO_free(bcrl);
554330a5e8faSwyllys
554430a5e8faSwyllys if (xcrl != NULL)
554530a5e8faSwyllys X509_CRL_free(xcrl);
554630a5e8faSwyllys
554730a5e8faSwyllys if (xcert != NULL)
554830a5e8faSwyllys X509_free(xcert);
554930a5e8faSwyllys
555030a5e8faSwyllys return (ret);
555130a5e8faSwyllys
555230a5e8faSwyllys }
555330a5e8faSwyllys
555430a5e8faSwyllys KMF_RETURN
OpenSSL_CheckCRLDate(KMF_HANDLE_T handle,char * crlname)555530a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
555630a5e8faSwyllys {
555730a5e8faSwyllys KMF_RETURN ret = KMF_OK;
555830a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
555930a5e8faSwyllys KMF_ENCODE_FORMAT crl_format;
556030a5e8faSwyllys BIO *bcrl = NULL;
556130a5e8faSwyllys X509_CRL *xcrl = NULL;
556230a5e8faSwyllys int i;
556330a5e8faSwyllys
556430a5e8faSwyllys if (handle == NULL || crlname == NULL) {
556530a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
556630a5e8faSwyllys }
556730a5e8faSwyllys
556830a5e8faSwyllys ret = kmf_is_crl_file(handle, crlname, &crl_format);
556930a5e8faSwyllys if (ret != KMF_OK)
557030a5e8faSwyllys return (ret);
557130a5e8faSwyllys
557230a5e8faSwyllys bcrl = BIO_new_file(crlname, "rb");
557330a5e8faSwyllys if (bcrl == NULL) {
557430a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
557530a5e8faSwyllys ret = KMF_ERR_OPEN_FILE;
557630a5e8faSwyllys goto cleanup;
557730a5e8faSwyllys }
557830a5e8faSwyllys
55795b3e1433Swyllys if (crl_format == KMF_FORMAT_ASN1)
558030a5e8faSwyllys xcrl = d2i_X509_CRL_bio(bcrl, NULL);
55815b3e1433Swyllys else if (crl_format == KMF_FORMAT_PEM)
558230a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
558330a5e8faSwyllys
558430a5e8faSwyllys if (xcrl == NULL) {
558530a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error());
558630a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE;
558730a5e8faSwyllys goto cleanup;
558830a5e8faSwyllys }
5589300fdee2SAndy Fiddaman i = X509_cmp_time(X509_CRL_get0_lastUpdate(xcrl), NULL);
559030a5e8faSwyllys if (i >= 0) {
559130a5e8faSwyllys ret = KMF_ERR_VALIDITY_PERIOD;
559230a5e8faSwyllys goto cleanup;
559330a5e8faSwyllys }
5594300fdee2SAndy Fiddaman if (X509_CRL_get0_nextUpdate(xcrl)) {
5595300fdee2SAndy Fiddaman i = X509_cmp_time(X509_CRL_get0_nextUpdate(xcrl), NULL);
559630a5e8faSwyllys
559730a5e8faSwyllys if (i <= 0) {
559830a5e8faSwyllys ret = KMF_ERR_VALIDITY_PERIOD;
559930a5e8faSwyllys goto cleanup;
560030a5e8faSwyllys }
560130a5e8faSwyllys }
560230a5e8faSwyllys
560330a5e8faSwyllys ret = KMF_OK;
560430a5e8faSwyllys
560530a5e8faSwyllys cleanup:
560630a5e8faSwyllys if (bcrl != NULL)
560730a5e8faSwyllys (void) BIO_free(bcrl);
560830a5e8faSwyllys
560930a5e8faSwyllys if (xcrl != NULL)
561030a5e8faSwyllys X509_CRL_free(xcrl);
561130a5e8faSwyllys
561230a5e8faSwyllys return (ret);
561330a5e8faSwyllys }
5614