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