199ebb4caSwyllys /* 22c9a247fSWyllys Ingersoll * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 32c9a247fSWyllys Ingersoll * 499ebb4caSwyllys * Use is subject to license terms. 599ebb4caSwyllys */ 69a767088Shaimay /* 770f9559bSTheo Schlossnagle * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved. 8553e44ceSAndrew Stormont * Copyright 2018 RackTop Systems. 9*4942e222SAndy Fiddaman * Copyright 2019 OmniOS Community Edition (OmniOSce) Association. 1070f9559bSTheo Schlossnagle */ 1170f9559bSTheo Schlossnagle /* 129a767088Shaimay * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL 139a767088Shaimay * project 2000. 149a767088Shaimay */ 159a767088Shaimay /* 169a767088Shaimay * ==================================================================== 179a767088Shaimay * Copyright (c) 2000-2004 The OpenSSL Project. All rights reserved. 189a767088Shaimay * 199a767088Shaimay * Redistribution and use in source and binary forms, with or without 209a767088Shaimay * modification, are permitted provided that the following conditions 219a767088Shaimay * are met: 229a767088Shaimay * 239a767088Shaimay * 1. Redistributions of source code must retain the above copyright 249a767088Shaimay * notice, this list of conditions and the following disclaimer. 259a767088Shaimay * 269a767088Shaimay * 2. Redistributions in binary form must reproduce the above copyright 279a767088Shaimay * notice, this list of conditions and the following disclaimer in 289a767088Shaimay * the documentation and/or other materials provided with the 299a767088Shaimay * distribution. 309a767088Shaimay * 319a767088Shaimay * 3. All advertising materials mentioning features or use of this 329a767088Shaimay * software must display the following acknowledgment: 339a767088Shaimay * "This product includes software developed by the OpenSSL Project 349a767088Shaimay * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 359a767088Shaimay * 369a767088Shaimay * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 379a767088Shaimay * endorse or promote products derived from this software without 389a767088Shaimay * prior written permission. For written permission, please contact 399a767088Shaimay * licensing@OpenSSL.org. 409a767088Shaimay * 419a767088Shaimay * 5. Products derived from this software may not be called "OpenSSL" 429a767088Shaimay * nor may "OpenSSL" appear in their names without prior written 439a767088Shaimay * permission of the OpenSSL Project. 449a767088Shaimay * 459a767088Shaimay * 6. Redistributions of any form whatsoever must retain the following 469a767088Shaimay * acknowledgment: 479a767088Shaimay * "This product includes software developed by the OpenSSL Project 489a767088Shaimay * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 499a767088Shaimay * 509a767088Shaimay * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 519a767088Shaimay * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 529a767088Shaimay * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 539a767088Shaimay * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 549a767088Shaimay * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 559a767088Shaimay * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 569a767088Shaimay * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 579a767088Shaimay * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 589a767088Shaimay * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 599a767088Shaimay * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 609a767088Shaimay * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 619a767088Shaimay * OF THE POSSIBILITY OF SUCH DAMAGE. 629a767088Shaimay * ==================================================================== 639a767088Shaimay * 649a767088Shaimay * This product includes cryptographic software written by Eric Young 659a767088Shaimay * (eay@cryptsoft.com). This product includes software written by Tim 669a767088Shaimay * Hudson (tjh@cryptsoft.com). 679a767088Shaimay * 689a767088Shaimay */ 6999ebb4caSwyllys 7071593db2Swyllys #include <stdlib.h> 7199ebb4caSwyllys #include <kmfapiP.h> 7299ebb4caSwyllys #include <ber_der.h> 7399ebb4caSwyllys #include <fcntl.h> 7499ebb4caSwyllys #include <sys/stat.h> 7599ebb4caSwyllys #include <dirent.h> 7699ebb4caSwyllys #include <cryptoutil.h> 7799ebb4caSwyllys #include <synch.h> 7899ebb4caSwyllys #include <thread.h> 7999ebb4caSwyllys 8099ebb4caSwyllys /* OPENSSL related headers */ 8199ebb4caSwyllys #include <openssl/bio.h> 8299ebb4caSwyllys #include <openssl/bn.h> 8399ebb4caSwyllys #include <openssl/asn1.h> 8499ebb4caSwyllys #include <openssl/err.h> 8599ebb4caSwyllys #include <openssl/x509.h> 8699ebb4caSwyllys #include <openssl/rsa.h> 8799ebb4caSwyllys #include <openssl/dsa.h> 8899ebb4caSwyllys #include <openssl/x509v3.h> 8999ebb4caSwyllys #include <openssl/objects.h> 9099ebb4caSwyllys #include <openssl/pem.h> 9199ebb4caSwyllys #include <openssl/pkcs12.h> 9299ebb4caSwyllys #include <openssl/ocsp.h> 9399ebb4caSwyllys #include <openssl/des.h> 9499ebb4caSwyllys #include <openssl/rand.h> 95300fdee2SAndy Fiddaman #include "compat.h" 9699ebb4caSwyllys 9799ebb4caSwyllys #define PRINT_ANY_EXTENSION (\ 9899ebb4caSwyllys KMF_X509_EXT_KEY_USAGE |\ 9999ebb4caSwyllys KMF_X509_EXT_CERT_POLICIES |\ 10099ebb4caSwyllys KMF_X509_EXT_SUBJALTNAME |\ 10199ebb4caSwyllys KMF_X509_EXT_BASIC_CONSTRAINTS |\ 10299ebb4caSwyllys KMF_X509_EXT_NAME_CONSTRAINTS |\ 10399ebb4caSwyllys KMF_X509_EXT_POLICY_CONSTRAINTS |\ 10499ebb4caSwyllys KMF_X509_EXT_EXT_KEY_USAGE |\ 10599ebb4caSwyllys KMF_X509_EXT_INHIBIT_ANY_POLICY |\ 10699ebb4caSwyllys KMF_X509_EXT_AUTH_KEY_ID |\ 10799ebb4caSwyllys KMF_X509_EXT_SUBJ_KEY_ID |\ 10899ebb4caSwyllys KMF_X509_EXT_POLICY_MAPPING) 10999ebb4caSwyllys 11099ebb4caSwyllys static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76, 11199ebb4caSwyllys 0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69, 11299ebb4caSwyllys 0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c, 11399ebb4caSwyllys 0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82, 11499ebb4caSwyllys 0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e, 11599ebb4caSwyllys 0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a, 11699ebb4caSwyllys 0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24, 11799ebb4caSwyllys 0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02, 11899ebb4caSwyllys 0x91 }; 11999ebb4caSwyllys 12099ebb4caSwyllys static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8, 12199ebb4caSwyllys 0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4, 12299ebb4caSwyllys 0x8e, 0xda, 0xce, 0x91, 0x5f }; 12399ebb4caSwyllys 12499ebb4caSwyllys static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a, 12599ebb4caSwyllys 0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5, 12699ebb4caSwyllys 0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef, 12799ebb4caSwyllys 0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c, 12899ebb4caSwyllys 0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba, 12999ebb4caSwyllys 0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c, 13099ebb4caSwyllys 0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08, 13199ebb4caSwyllys 0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88, 13299ebb4caSwyllys 0x02 }; 13399ebb4caSwyllys 13499ebb4caSwyllys #define SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \ 13599ebb4caSwyllys h->lasterr.errcode = c; 13699ebb4caSwyllys 13799ebb4caSwyllys #define SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c; 13899ebb4caSwyllys 1395b3e1433Swyllys /* 140bf5d9f18SAndy Fiddaman * Declare some new macros for managing stacks of EVP_PKEYS. 1415b3e1433Swyllys */ 142553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 1435b3e1433Swyllys DECLARE_STACK_OF(EVP_PKEY) 1445b3e1433Swyllys 1455b3e1433Swyllys #define sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY) 1465b3e1433Swyllys #define sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st)) 1475b3e1433Swyllys #define sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st)) 1485b3e1433Swyllys #define sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i)) 1495b3e1433Swyllys #define sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val)) 1505b3e1433Swyllys #define sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \ 1515b3e1433Swyllys (free_func)) 1525b3e1433Swyllys 153300fdee2SAndy Fiddaman #else 154300fdee2SAndy Fiddaman DEFINE_STACK_OF(EVP_PKEY) 155300fdee2SAndy Fiddaman #endif 156300fdee2SAndy Fiddaman 15799ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX; 15899ebb4caSwyllys static int ssl_initialized = 0; 15930a5e8faSwyllys static BIO *bio_err = NULL; 16030a5e8faSwyllys 161*4942e222SAndy Fiddaman static int test_for_file(char *, mode_t); 162*4942e222SAndy Fiddaman 163*4942e222SAndy Fiddaman static KMF_RETURN openssl_parse_bag(PKCS12_SAFEBAG *, char *, int, 1645b3e1433Swyllys STACK_OF(EVP_PKEY) *, STACK_OF(X509) *); 1655b3e1433Swyllys 166*4942e222SAndy Fiddaman static KMF_RETURN local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, 167*4942e222SAndy Fiddaman KMF_X509_DER_CERT *, int, KMF_KEY_HANDLE *, char *); 1685b3e1433Swyllys 1695b3e1433Swyllys static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int); 17099ebb4caSwyllys 171*4942e222SAndy Fiddaman static KMF_RETURN extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, 172*4942e222SAndy Fiddaman char *, CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *); 17371593db2Swyllys 174*4942e222SAndy Fiddaman static KMF_RETURN kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, 175*4942e222SAndy Fiddaman KMF_CERT_VALIDITY, char *, KMF_DATA *); 17630a5e8faSwyllys 177*4942e222SAndy Fiddaman static KMF_RETURN load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, 178*4942e222SAndy Fiddaman KMF_CERT_VALIDITY, char *, KMF_DATA **, uint32_t *); 17971593db2Swyllys 180*4942e222SAndy Fiddaman static KMF_RETURN sslBN2KMFBN(BIGNUM *, KMF_BIGINT *); 18102744e81Swyllys 182*4942e222SAndy Fiddaman static EVP_PKEY *ImportRawRSAKey(KMF_RAW_RSA_KEY *); 18302744e81Swyllys 184*4942e222SAndy Fiddaman static KMF_RETURN convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *); 18530a5e8faSwyllys 186*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 18799ebb4caSwyllys 188*4942e222SAndy Fiddaman void OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *); 18999ebb4caSwyllys 190*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *); 19199ebb4caSwyllys 192*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *); 19399ebb4caSwyllys 194*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 19530a5e8faSwyllys 196*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 19799ebb4caSwyllys 198*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, 199*4942e222SAndy Fiddaman KMF_DATA *); 20099ebb4caSwyllys 201*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *, 20299ebb4caSwyllys KMF_DATA *, KMF_DATA *); 20399ebb4caSwyllys 204*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 20599ebb4caSwyllys 206*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 20799ebb4caSwyllys 208*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 20999ebb4caSwyllys 210*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 21199ebb4caSwyllys 212*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 21399ebb4caSwyllys 214*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *, 21599ebb4caSwyllys KMF_PRINTABLE_ITEM, char *); 21699ebb4caSwyllys 217*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_GetErrorString(KMF_HANDLE_T, char **); 21899ebb4caSwyllys 219*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 22099ebb4caSwyllys 221*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *, 22299ebb4caSwyllys KMF_DATA *, KMF_DATA *); 22399ebb4caSwyllys 224*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 22599ebb4caSwyllys 226*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 22799ebb4caSwyllys 228*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 22999ebb4caSwyllys 230*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 23199ebb4caSwyllys 232*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 23399ebb4caSwyllys 234*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, 235*4942e222SAndy Fiddaman KMF_RAW_SYM_KEY *); 23699ebb4caSwyllys 237*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *); 23899ebb4caSwyllys 239*4942e222SAndy Fiddaman KMF_RETURN OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *); 24099ebb4caSwyllys 24199ebb4caSwyllys static 24299ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table = 24399ebb4caSwyllys { 24499ebb4caSwyllys 1, /* Version */ 24599ebb4caSwyllys NULL, /* ConfigureKeystore */ 24699ebb4caSwyllys OpenSSL_FindCert, 24799ebb4caSwyllys OpenSSL_FreeKMFCert, 24899ebb4caSwyllys OpenSSL_StoreCert, 24999ebb4caSwyllys NULL, /* ImportCert */ 25099ebb4caSwyllys OpenSSL_ImportCRL, 25199ebb4caSwyllys OpenSSL_DeleteCert, 25299ebb4caSwyllys OpenSSL_DeleteCRL, 25399ebb4caSwyllys OpenSSL_CreateKeypair, 25499ebb4caSwyllys OpenSSL_FindKey, 25599ebb4caSwyllys OpenSSL_EncodePubKeyData, 25699ebb4caSwyllys OpenSSL_SignData, 25799ebb4caSwyllys OpenSSL_DeleteKey, 25899ebb4caSwyllys OpenSSL_ListCRL, 25999ebb4caSwyllys NULL, /* FindCRL */ 26099ebb4caSwyllys OpenSSL_FindCertInCRL, 26199ebb4caSwyllys OpenSSL_GetErrorString, 26230a5e8faSwyllys OpenSSL_FindPrikeyByCert, 26399ebb4caSwyllys OpenSSL_DecryptData, 26430a5e8faSwyllys OpenSSL_ExportPK12, 26599ebb4caSwyllys OpenSSL_CreateSymKey, 26699ebb4caSwyllys OpenSSL_GetSymKeyValue, 26799ebb4caSwyllys NULL, /* SetTokenPin */ 26830a5e8faSwyllys OpenSSL_StoreKey, 26999ebb4caSwyllys NULL /* Finalize */ 27099ebb4caSwyllys }; 27199ebb4caSwyllys 272553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 27399ebb4caSwyllys static mutex_t *lock_cs; 27499ebb4caSwyllys static long *lock_count; 27599ebb4caSwyllys 27699ebb4caSwyllys static void 27799ebb4caSwyllys locking_cb(int mode, int type, char *file, int line) 27899ebb4caSwyllys { 27999ebb4caSwyllys if (mode & CRYPTO_LOCK) { 28099ebb4caSwyllys (void) mutex_lock(&(lock_cs[type])); 28199ebb4caSwyllys lock_count[type]++; 28299ebb4caSwyllys } else { 28399ebb4caSwyllys (void) mutex_unlock(&(lock_cs[type])); 28499ebb4caSwyllys } 28599ebb4caSwyllys } 28699ebb4caSwyllys 28799ebb4caSwyllys static unsigned long 28899ebb4caSwyllys thread_id() 28999ebb4caSwyllys { 29099ebb4caSwyllys return ((unsigned long)thr_self()); 29199ebb4caSwyllys } 292553e44ceSAndrew Stormont #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER */ 29399ebb4caSwyllys 29499ebb4caSwyllys KMF_PLUGIN_FUNCLIST * 29599ebb4caSwyllys KMF_Plugin_Initialize() 29699ebb4caSwyllys { 297553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 29899ebb4caSwyllys int i; 299300fdee2SAndy Fiddaman #endif 30099ebb4caSwyllys 30199ebb4caSwyllys (void) mutex_lock(&init_lock); 30299ebb4caSwyllys if (!ssl_initialized) { 30399ebb4caSwyllys /* 30499ebb4caSwyllys * Add support for extension OIDs that are not yet in the 30599ebb4caSwyllys * openssl default set. 30699ebb4caSwyllys */ 30799ebb4caSwyllys (void) OBJ_create("2.5.29.30", "nameConstraints", 30899ebb4caSwyllys "X509v3 Name Constraints"); 30999ebb4caSwyllys (void) OBJ_create("2.5.29.33", "policyMappings", 31099ebb4caSwyllys "X509v3 Policy Mappings"); 31199ebb4caSwyllys (void) OBJ_create("2.5.29.36", "policyConstraints", 31299ebb4caSwyllys "X509v3 Policy Constraints"); 31399ebb4caSwyllys (void) OBJ_create("2.5.29.46", "freshestCRL", 31499ebb4caSwyllys "X509v3 Freshest CRL"); 31599ebb4caSwyllys (void) OBJ_create("2.5.29.54", "inhibitAnyPolicy", 31699ebb4caSwyllys "X509v3 Inhibit Any-Policy"); 317300fdee2SAndy Fiddaman 318553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 31999ebb4caSwyllys /* 32099ebb4caSwyllys * Set up for thread-safe operation. 321300fdee2SAndy Fiddaman * This is not required for OpenSSL 1.1 32299ebb4caSwyllys */ 32399ebb4caSwyllys lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t)); 32499ebb4caSwyllys if (lock_cs == NULL) { 32599ebb4caSwyllys (void) mutex_unlock(&init_lock); 32699ebb4caSwyllys return (NULL); 32799ebb4caSwyllys } 32899ebb4caSwyllys 32999ebb4caSwyllys lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long)); 33099ebb4caSwyllys if (lock_count == NULL) { 33199ebb4caSwyllys OPENSSL_free(lock_cs); 33299ebb4caSwyllys (void) mutex_unlock(&init_lock); 33399ebb4caSwyllys return (NULL); 33499ebb4caSwyllys } 33599ebb4caSwyllys 33699ebb4caSwyllys for (i = 0; i < CRYPTO_num_locks(); i++) { 33799ebb4caSwyllys lock_count[i] = 0; 33899ebb4caSwyllys (void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL); 33999ebb4caSwyllys } 34099ebb4caSwyllys 34199ebb4caSwyllys CRYPTO_set_id_callback((unsigned long (*)())thread_id); 3422c9a247fSWyllys Ingersoll if (CRYPTO_get_locking_callback() == NULL) 34399ebb4caSwyllys CRYPTO_set_locking_callback((void (*)())locking_cb); 3442c9a247fSWyllys Ingersoll 345300fdee2SAndy Fiddaman (void) OpenSSL_add_all_algorithms(); 3462c9a247fSWyllys Ingersoll 3472c9a247fSWyllys Ingersoll /* Enable error strings for reporting */ 348300fdee2SAndy Fiddaman (void) ERR_load_crypto_strings(); 349300fdee2SAndy Fiddaman #endif 3502c9a247fSWyllys Ingersoll 35199ebb4caSwyllys ssl_initialized = 1; 35299ebb4caSwyllys } 35399ebb4caSwyllys (void) mutex_unlock(&init_lock); 35499ebb4caSwyllys 35599ebb4caSwyllys return (&openssl_plugin_table); 35699ebb4caSwyllys } 357300fdee2SAndy Fiddaman 35899ebb4caSwyllys /* 35999ebb4caSwyllys * Convert an SSL DN to a KMF DN. 36099ebb4caSwyllys */ 36199ebb4caSwyllys static KMF_RETURN 36299ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN) 36399ebb4caSwyllys { 36499ebb4caSwyllys KMF_DATA derdata; 36599ebb4caSwyllys KMF_RETURN rv = KMF_OK; 36699ebb4caSwyllys uchar_t *tmp; 36799ebb4caSwyllys 36899ebb4caSwyllys /* Convert to raw DER format */ 36999ebb4caSwyllys derdata.Length = i2d_X509_NAME(sslDN, NULL); 37099ebb4caSwyllys if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length)) 37199ebb4caSwyllys == NULL) { 37299ebb4caSwyllys return (KMF_ERR_MEMORY); 37399ebb4caSwyllys } 37499ebb4caSwyllys (void) i2d_X509_NAME(sslDN, &tmp); 37599ebb4caSwyllys 37699ebb4caSwyllys /* Decode to KMF format */ 37799ebb4caSwyllys rv = DerDecodeName(&derdata, kmfDN); 37899ebb4caSwyllys if (rv != KMF_OK) { 37999ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 38099ebb4caSwyllys } 38199ebb4caSwyllys OPENSSL_free(derdata.Data); 38299ebb4caSwyllys 38399ebb4caSwyllys return (rv); 38499ebb4caSwyllys } 38599ebb4caSwyllys 38630a5e8faSwyllys int 38799ebb4caSwyllys isdir(char *path) 38899ebb4caSwyllys { 38999ebb4caSwyllys struct stat s; 39099ebb4caSwyllys 39199ebb4caSwyllys if (stat(path, &s) == -1) 39299ebb4caSwyllys return (0); 39399ebb4caSwyllys 39430a5e8faSwyllys return ((s.st_mode & S_IFMT) == S_IFDIR); 39599ebb4caSwyllys } 39699ebb4caSwyllys 39799ebb4caSwyllys static KMF_RETURN 39899ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert) 39999ebb4caSwyllys { 40099ebb4caSwyllys KMF_RETURN rv = KMF_OK; 40199ebb4caSwyllys unsigned char *buf = NULL, *p; 40299ebb4caSwyllys int len; 40399ebb4caSwyllys 40499ebb4caSwyllys /* 40599ebb4caSwyllys * Convert the X509 internal struct to DER encoded data 40699ebb4caSwyllys */ 40799ebb4caSwyllys if ((len = i2d_X509(x509cert, NULL)) < 0) { 40899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 40999ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 41099ebb4caSwyllys goto cleanup; 41199ebb4caSwyllys } 41299ebb4caSwyllys if ((buf = malloc(len)) == NULL) { 41399ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 41499ebb4caSwyllys rv = KMF_ERR_MEMORY; 41599ebb4caSwyllys goto cleanup; 41699ebb4caSwyllys } 41799ebb4caSwyllys 41899ebb4caSwyllys /* 41999ebb4caSwyllys * i2d_X509 will increment the buf pointer so that we need to 42099ebb4caSwyllys * save it. 42199ebb4caSwyllys */ 42299ebb4caSwyllys p = buf; 42399ebb4caSwyllys if ((len = i2d_X509(x509cert, &p)) < 0) { 42499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 42599ebb4caSwyllys free(buf); 42699ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 42799ebb4caSwyllys goto cleanup; 42899ebb4caSwyllys } 42999ebb4caSwyllys 43099ebb4caSwyllys /* caller's responsibility to free it */ 43199ebb4caSwyllys cert->Data = buf; 43299ebb4caSwyllys cert->Length = len; 43399ebb4caSwyllys 43499ebb4caSwyllys cleanup: 43599ebb4caSwyllys if (rv != KMF_OK) { 43699ebb4caSwyllys if (buf) 43799ebb4caSwyllys free(buf); 43899ebb4caSwyllys cert->Data = NULL; 43999ebb4caSwyllys cert->Length = 0; 44099ebb4caSwyllys } 44199ebb4caSwyllys 44299ebb4caSwyllys return (rv); 44399ebb4caSwyllys } 44499ebb4caSwyllys 44530a5e8faSwyllys 44699ebb4caSwyllys static KMF_RETURN 44730a5e8faSwyllys check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial, 44830a5e8faSwyllys boolean_t *match) 44999ebb4caSwyllys { 45099ebb4caSwyllys KMF_RETURN rv = KMF_OK; 45199ebb4caSwyllys boolean_t findIssuer = FALSE; 45299ebb4caSwyllys boolean_t findSubject = FALSE; 45399ebb4caSwyllys boolean_t findSerial = FALSE; 45499ebb4caSwyllys KMF_X509_NAME issuerDN, subjectDN; 45599ebb4caSwyllys KMF_X509_NAME certIssuerDN, certSubjectDN; 45699ebb4caSwyllys 45799ebb4caSwyllys *match = FALSE; 45899ebb4caSwyllys if (xcert == NULL) { 45999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 46099ebb4caSwyllys } 46199ebb4caSwyllys 46299ebb4caSwyllys (void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME)); 46399ebb4caSwyllys (void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME)); 46499ebb4caSwyllys (void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME)); 46599ebb4caSwyllys (void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME)); 46699ebb4caSwyllys 46730a5e8faSwyllys if (issuer != NULL && strlen(issuer)) { 46830a5e8faSwyllys rv = kmf_dn_parser(issuer, &issuerDN); 46999ebb4caSwyllys if (rv != KMF_OK) 47099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 47199ebb4caSwyllys 472300fdee2SAndy Fiddaman rv = get_x509_dn(X509_get_issuer_name(xcert), &certIssuerDN); 47399ebb4caSwyllys if (rv != KMF_OK) { 47430a5e8faSwyllys kmf_free_dn(&issuerDN); 47599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 47699ebb4caSwyllys } 47799ebb4caSwyllys 47899ebb4caSwyllys findIssuer = TRUE; 47999ebb4caSwyllys } 48030a5e8faSwyllys if (subject != NULL && strlen(subject)) { 48130a5e8faSwyllys rv = kmf_dn_parser(subject, &subjectDN); 48299ebb4caSwyllys if (rv != KMF_OK) { 48399ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 48499ebb4caSwyllys goto cleanup; 48599ebb4caSwyllys } 48699ebb4caSwyllys 487300fdee2SAndy Fiddaman rv = get_x509_dn(X509_get_subject_name(xcert), &certSubjectDN); 48899ebb4caSwyllys if (rv != KMF_OK) { 48999ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 49099ebb4caSwyllys goto cleanup; 49199ebb4caSwyllys } 49299ebb4caSwyllys findSubject = TRUE; 49399ebb4caSwyllys } 49430a5e8faSwyllys if (serial != NULL && serial->val != NULL) 49599ebb4caSwyllys findSerial = TRUE; 49699ebb4caSwyllys 49799ebb4caSwyllys if (findSerial) { 49899ebb4caSwyllys BIGNUM *bn; 49999ebb4caSwyllys 50099ebb4caSwyllys /* Comparing BIGNUMs is a pain! */ 501300fdee2SAndy Fiddaman bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(xcert), NULL); 50299ebb4caSwyllys if (bn != NULL) { 50399ebb4caSwyllys int bnlen = BN_num_bytes(bn); 50499ebb4caSwyllys 50530a5e8faSwyllys if (bnlen == serial->len) { 50699ebb4caSwyllys uchar_t *a = malloc(bnlen); 50799ebb4caSwyllys if (a == NULL) { 50899ebb4caSwyllys rv = KMF_ERR_MEMORY; 50999ebb4caSwyllys BN_free(bn); 51099ebb4caSwyllys goto cleanup; 51199ebb4caSwyllys } 51299ebb4caSwyllys bnlen = BN_bn2bin(bn, a); 51330a5e8faSwyllys *match = (memcmp(a, serial->val, serial->len) == 51430a5e8faSwyllys 0); 51599ebb4caSwyllys rv = KMF_OK; 51699ebb4caSwyllys free(a); 51799ebb4caSwyllys } 51899ebb4caSwyllys BN_free(bn); 51999ebb4caSwyllys if (!(*match)) 52099ebb4caSwyllys goto cleanup; 52199ebb4caSwyllys } else { 52299ebb4caSwyllys rv = KMF_OK; 52399ebb4caSwyllys goto cleanup; 52499ebb4caSwyllys } 52599ebb4caSwyllys } 52699ebb4caSwyllys if (findIssuer) { 52730a5e8faSwyllys *match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0); 52830a5e8faSwyllys if ((*match) == B_FALSE) { 52930a5e8faSwyllys /* stop checking and bail */ 53099ebb4caSwyllys rv = KMF_OK; 53199ebb4caSwyllys goto cleanup; 53299ebb4caSwyllys } 53399ebb4caSwyllys } 53499ebb4caSwyllys if (findSubject) { 53530a5e8faSwyllys *match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0); 53630a5e8faSwyllys if ((*match) == B_FALSE) { 53730a5e8faSwyllys /* stop checking and bail */ 53899ebb4caSwyllys rv = KMF_OK; 53999ebb4caSwyllys goto cleanup; 54099ebb4caSwyllys } 54199ebb4caSwyllys } 54299ebb4caSwyllys 54399ebb4caSwyllys *match = TRUE; 54499ebb4caSwyllys cleanup: 54599ebb4caSwyllys if (findIssuer) { 54630a5e8faSwyllys kmf_free_dn(&issuerDN); 54730a5e8faSwyllys kmf_free_dn(&certIssuerDN); 54899ebb4caSwyllys } 54999ebb4caSwyllys if (findSubject) { 55030a5e8faSwyllys kmf_free_dn(&subjectDN); 55130a5e8faSwyllys kmf_free_dn(&certSubjectDN); 55299ebb4caSwyllys } 55399ebb4caSwyllys 55499ebb4caSwyllys return (rv); 55599ebb4caSwyllys } 55699ebb4caSwyllys 55730a5e8faSwyllys 55830a5e8faSwyllys /* 55930a5e8faSwyllys * This function loads a certificate file into an X509 data structure, and 56030a5e8faSwyllys * checks if its issuer, subject or the serial number matches with those 56130a5e8faSwyllys * values. If it matches, then return the X509 data structure. 56230a5e8faSwyllys */ 56399ebb4caSwyllys static KMF_RETURN 564*4942e222SAndy Fiddaman load_X509cert(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial, 56530a5e8faSwyllys char *pathname, X509 **outcert) 56699ebb4caSwyllys { 56799ebb4caSwyllys KMF_RETURN rv = KMF_OK; 56899ebb4caSwyllys X509 *xcert = NULL; 56999ebb4caSwyllys BIO *bcert = NULL; 57099ebb4caSwyllys boolean_t match = FALSE; 57199ebb4caSwyllys KMF_ENCODE_FORMAT format; 57299ebb4caSwyllys 57399ebb4caSwyllys /* 57499ebb4caSwyllys * auto-detect the file format, regardless of what 57599ebb4caSwyllys * the 'format' parameters in the params say. 57699ebb4caSwyllys */ 57730a5e8faSwyllys rv = kmf_get_file_format(pathname, &format); 57899ebb4caSwyllys if (rv != KMF_OK) { 57999ebb4caSwyllys if (rv == KMF_ERR_OPEN_FILE) 58099ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND; 58199ebb4caSwyllys return (rv); 58299ebb4caSwyllys } 58399ebb4caSwyllys 58499ebb4caSwyllys /* Not ASN1(DER) format */ 58599ebb4caSwyllys if ((bcert = BIO_new_file(pathname, "rb")) == NULL) { 58699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 58799ebb4caSwyllys rv = KMF_ERR_OPEN_FILE; 58899ebb4caSwyllys goto cleanup; 58999ebb4caSwyllys } 59099ebb4caSwyllys 59199ebb4caSwyllys if (format == KMF_FORMAT_PEM) 59299ebb4caSwyllys xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL); 59399ebb4caSwyllys else if (format == KMF_FORMAT_ASN1) 59499ebb4caSwyllys xcert = d2i_X509_bio(bcert, NULL); 59599ebb4caSwyllys else if (format == KMF_FORMAT_PKCS12) { 59699ebb4caSwyllys PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL); 59799ebb4caSwyllys if (p12 != NULL) { 59899ebb4caSwyllys (void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL); 59999ebb4caSwyllys PKCS12_free(p12); 60099ebb4caSwyllys p12 = NULL; 60199ebb4caSwyllys } else { 60299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 60399ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 60499ebb4caSwyllys } 60599ebb4caSwyllys } else { 60699ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 60799ebb4caSwyllys goto cleanup; 60899ebb4caSwyllys } 60999ebb4caSwyllys 61099ebb4caSwyllys if (xcert == NULL) { 61199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 61299ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 61399ebb4caSwyllys goto cleanup; 61499ebb4caSwyllys } 61599ebb4caSwyllys 61630a5e8faSwyllys if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK || 61730a5e8faSwyllys match == FALSE) { 61899ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND; 61999ebb4caSwyllys goto cleanup; 62099ebb4caSwyllys } 62199ebb4caSwyllys 62299ebb4caSwyllys if (outcert != NULL) { 62399ebb4caSwyllys *outcert = xcert; 62499ebb4caSwyllys } 62599ebb4caSwyllys 62699ebb4caSwyllys cleanup: 62799ebb4caSwyllys if (bcert != NULL) (void) BIO_free(bcert); 62899ebb4caSwyllys if (rv != KMF_OK && xcert != NULL) 62999ebb4caSwyllys X509_free(xcert); 63099ebb4caSwyllys 63199ebb4caSwyllys return (rv); 63299ebb4caSwyllys } 63399ebb4caSwyllys 63471593db2Swyllys static int 63571593db2Swyllys datacmp(const void *a, const void *b) 63671593db2Swyllys { 63771593db2Swyllys KMF_DATA *adata = (KMF_DATA *)a; 63871593db2Swyllys KMF_DATA *bdata = (KMF_DATA *)b; 63971593db2Swyllys if (adata->Length > bdata->Length) 64071593db2Swyllys return (-1); 64171593db2Swyllys if (adata->Length < bdata->Length) 64271593db2Swyllys return (1); 64371593db2Swyllys return (0); 64471593db2Swyllys } 64571593db2Swyllys 64671593db2Swyllys static KMF_RETURN 64730a5e8faSwyllys load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial, 64830a5e8faSwyllys KMF_CERT_VALIDITY validity, char *pathname, 64971593db2Swyllys KMF_DATA **certlist, uint32_t *numcerts) 65071593db2Swyllys { 65171593db2Swyllys KMF_RETURN rv = KMF_OK; 65271593db2Swyllys int i; 65371593db2Swyllys KMF_DATA *certs = NULL; 65471593db2Swyllys int nc = 0; 65571593db2Swyllys int hits = 0; 65671593db2Swyllys KMF_ENCODE_FORMAT format; 65771593db2Swyllys 65830a5e8faSwyllys rv = kmf_get_file_format(pathname, &format); 65971593db2Swyllys if (rv != KMF_OK) { 66071593db2Swyllys if (rv == KMF_ERR_OPEN_FILE) 66171593db2Swyllys rv = KMF_ERR_CERT_NOT_FOUND; 66271593db2Swyllys return (rv); 66371593db2Swyllys } 66471593db2Swyllys if (format == KMF_FORMAT_ASN1) { 66571593db2Swyllys /* load a single certificate */ 66671593db2Swyllys certs = (KMF_DATA *)malloc(sizeof (KMF_DATA)); 66771593db2Swyllys if (certs == NULL) 66871593db2Swyllys return (KMF_ERR_MEMORY); 66971593db2Swyllys certs->Data = NULL; 67071593db2Swyllys certs->Length = 0; 67130a5e8faSwyllys rv = kmf_load_cert(kmfh, issuer, subject, serial, validity, 67230a5e8faSwyllys pathname, certs); 67371593db2Swyllys if (rv == KMF_OK) { 67471593db2Swyllys *certlist = certs; 67571593db2Swyllys *numcerts = 1; 676a2d4930dSDan OpenSolaris Anderson } else { 677a2d4930dSDan OpenSolaris Anderson kmf_free_data(certs); 678a2d4930dSDan OpenSolaris Anderson free(certs); 679a2d4930dSDan OpenSolaris Anderson certs = NULL; 68071593db2Swyllys } 68171593db2Swyllys return (rv); 68271593db2Swyllys } else if (format == KMF_FORMAT_PKCS12) { 68371593db2Swyllys /* We need a credential to access a PKCS#12 file */ 68471593db2Swyllys rv = KMF_ERR_BAD_CERT_FORMAT; 68571593db2Swyllys } else if (format == KMF_FORMAT_PEM || 68671593db2Swyllys format != KMF_FORMAT_PEM_KEYPAIR) { 687e65e5c2dSWyllys Ingersoll 68871593db2Swyllys /* This function only works on PEM files */ 68930a5e8faSwyllys rv = extract_pem(kmfh, issuer, subject, serial, pathname, 69034acef67Swyllys (uchar_t *)NULL, 0, NULL, &certs, &nc); 69171593db2Swyllys } else { 69271593db2Swyllys return (KMF_ERR_ENCODING); 69371593db2Swyllys } 69471593db2Swyllys 69571593db2Swyllys if (rv != KMF_OK) 69671593db2Swyllys return (rv); 69771593db2Swyllys 69871593db2Swyllys for (i = 0; i < nc; i++) { 69930a5e8faSwyllys if (validity == KMF_NONEXPIRED_CERTS) { 70030a5e8faSwyllys rv = kmf_check_cert_date(kmfh, &certs[i]); 70130a5e8faSwyllys } else if (validity == KMF_EXPIRED_CERTS) { 70230a5e8faSwyllys rv = kmf_check_cert_date(kmfh, &certs[i]); 70371593db2Swyllys if (rv == KMF_OK) 70471593db2Swyllys rv = KMF_ERR_CERT_NOT_FOUND; 70571593db2Swyllys if (rv == KMF_ERR_VALIDITY_PERIOD) 70671593db2Swyllys rv = KMF_OK; 70771593db2Swyllys } 70871593db2Swyllys if (rv != KMF_OK) { 70971593db2Swyllys /* Remove this cert from the list by clearing it. */ 71030a5e8faSwyllys kmf_free_data(&certs[i]); 71171593db2Swyllys } else { 71271593db2Swyllys hits++; /* count valid certs found */ 71371593db2Swyllys } 71471593db2Swyllys rv = KMF_OK; 71571593db2Swyllys } 716a2d4930dSDan OpenSolaris Anderson if (rv == KMF_OK && hits > 0) { 71771593db2Swyllys /* 71871593db2Swyllys * Sort the list of certs by length to put the cleared ones 71971593db2Swyllys * at the end so they don't get accessed by the caller. 72071593db2Swyllys */ 72171593db2Swyllys qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp); 72271593db2Swyllys *certlist = certs; 72371593db2Swyllys 72471593db2Swyllys /* since we sorted the list, just return the number of hits */ 72571593db2Swyllys *numcerts = hits; 726a2d4930dSDan OpenSolaris Anderson } else { 727e65e5c2dSWyllys Ingersoll if (rv == KMF_OK && hits == 0) 728a2d4930dSDan OpenSolaris Anderson rv = KMF_ERR_CERT_NOT_FOUND; 729a2d4930dSDan OpenSolaris Anderson if (certs != NULL) { 730a2d4930dSDan OpenSolaris Anderson free(certs); 731a2d4930dSDan OpenSolaris Anderson certs = NULL; 732a2d4930dSDan OpenSolaris Anderson } 733a2d4930dSDan OpenSolaris Anderson } 73471593db2Swyllys return (rv); 73571593db2Swyllys } 73671593db2Swyllys 73799ebb4caSwyllys static KMF_RETURN 738*4942e222SAndy Fiddaman kmf_load_cert(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial, 739*4942e222SAndy Fiddaman KMF_CERT_VALIDITY validity, char *pathname, KMF_DATA *cert) 74099ebb4caSwyllys { 74199ebb4caSwyllys KMF_RETURN rv = KMF_OK; 74299ebb4caSwyllys X509 *x509cert = NULL; 74399ebb4caSwyllys 74430a5e8faSwyllys rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert); 74599ebb4caSwyllys if (rv == KMF_OK && x509cert != NULL && cert != NULL) { 74699ebb4caSwyllys rv = ssl_cert2KMFDATA(kmfh, x509cert, cert); 74799ebb4caSwyllys if (rv != KMF_OK) { 74899ebb4caSwyllys goto cleanup; 74999ebb4caSwyllys } 75030a5e8faSwyllys if (validity == KMF_NONEXPIRED_CERTS) { 75130a5e8faSwyllys rv = kmf_check_cert_date(kmfh, cert); 75230a5e8faSwyllys } else if (validity == KMF_EXPIRED_CERTS) { 75330a5e8faSwyllys rv = kmf_check_cert_date(kmfh, cert); 75499ebb4caSwyllys if (rv == KMF_OK) { 75599ebb4caSwyllys /* 75699ebb4caSwyllys * This is a valid cert so skip it. 75799ebb4caSwyllys */ 75899ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND; 75999ebb4caSwyllys } 76099ebb4caSwyllys if (rv == KMF_ERR_VALIDITY_PERIOD) { 76199ebb4caSwyllys /* 76299ebb4caSwyllys * We want to return success when we 76399ebb4caSwyllys * find an invalid cert. 76499ebb4caSwyllys */ 76599ebb4caSwyllys rv = KMF_OK; 76699ebb4caSwyllys goto cleanup; 76799ebb4caSwyllys } 76899ebb4caSwyllys } 76999ebb4caSwyllys } 77099ebb4caSwyllys cleanup: 77199ebb4caSwyllys if (x509cert != NULL) 77299ebb4caSwyllys X509_free(x509cert); 77399ebb4caSwyllys 77499ebb4caSwyllys return (rv); 77599ebb4caSwyllys } 77699ebb4caSwyllys 77702744e81Swyllys static KMF_RETURN 77802744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey) 77902744e81Swyllys { 78002744e81Swyllys KMF_RETURN ret = KMF_OK; 78102744e81Swyllys KMF_RAW_RSA_KEY rsa; 78202744e81Swyllys BerElement *asn1 = NULL; 78302744e81Swyllys BerValue filebuf; 784f810c7e5SToomas Soome BerValue OID = { 0, 0 }; 78502744e81Swyllys BerValue *Mod = NULL, *PubExp = NULL; 78602744e81Swyllys BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL; 78702744e81Swyllys BerValue *Coef = NULL; 78802744e81Swyllys BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL; 78902744e81Swyllys BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL; 79002744e81Swyllys BIGNUM *qminus1 = NULL; 79102744e81Swyllys BN_CTX *ctx = NULL; 79202744e81Swyllys 79302744e81Swyllys *pkey = NULL; 79402744e81Swyllys 79502744e81Swyllys filebuf.bv_val = (char *)filedata->Data; 79602744e81Swyllys filebuf.bv_len = filedata->Length; 79702744e81Swyllys 79802744e81Swyllys asn1 = kmfder_init(&filebuf); 79902744e81Swyllys if (asn1 == NULL) { 80002744e81Swyllys ret = KMF_ERR_MEMORY; 80102744e81Swyllys goto out; 80202744e81Swyllys } 80302744e81Swyllys 80402744e81Swyllys if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}", 80502744e81Swyllys &OID, &Mod, &PubExp, &PriExp, &Prime1, 80602744e81Swyllys &Prime2, &Coef) == -1) { 80702744e81Swyllys ret = KMF_ERR_ENCODING; 80802744e81Swyllys goto out; 80902744e81Swyllys } 81002744e81Swyllys 81102744e81Swyllys /* 81202744e81Swyllys * We have to derive the 2 Exponents using Bignumber math. 81302744e81Swyllys * Exp1 = PriExp mod (Prime1 - 1) 81402744e81Swyllys * Exp2 = PriExp mod (Prime2 - 1) 81502744e81Swyllys */ 81602744e81Swyllys 81702744e81Swyllys /* D = PrivateExponent */ 81802744e81Swyllys D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D); 81902744e81Swyllys if (D == NULL) { 82002744e81Swyllys ret = KMF_ERR_MEMORY; 82102744e81Swyllys goto out; 82202744e81Swyllys } 82302744e81Swyllys 82402744e81Swyllys /* P = Prime1 (first prime factor of Modulus) */ 82502744e81Swyllys P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P); 82602744e81Swyllys if (D == NULL) { 82702744e81Swyllys ret = KMF_ERR_MEMORY; 82802744e81Swyllys goto out; 82902744e81Swyllys } 83002744e81Swyllys 83102744e81Swyllys /* Q = Prime2 (second prime factor of Modulus) */ 83202744e81Swyllys Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q); 83302744e81Swyllys 83402744e81Swyllys if ((ctx = BN_CTX_new()) == NULL) { 83502744e81Swyllys ret = KMF_ERR_MEMORY; 83602744e81Swyllys goto out; 83702744e81Swyllys } 83802744e81Swyllys 83902744e81Swyllys /* Compute (P - 1) */ 84002744e81Swyllys pminus1 = BN_new(); 84102744e81Swyllys (void) BN_sub(pminus1, P, BN_value_one()); 84202744e81Swyllys 84302744e81Swyllys /* Exponent1 = D mod (P - 1) */ 84402744e81Swyllys Exp1 = BN_new(); 84502744e81Swyllys (void) BN_mod(Exp1, D, pminus1, ctx); 84602744e81Swyllys 84702744e81Swyllys /* Compute (Q - 1) */ 84802744e81Swyllys qminus1 = BN_new(); 84902744e81Swyllys (void) BN_sub(qminus1, Q, BN_value_one()); 85002744e81Swyllys 85102744e81Swyllys /* Exponent2 = D mod (Q - 1) */ 85202744e81Swyllys Exp2 = BN_new(); 85302744e81Swyllys (void) BN_mod(Exp2, D, qminus1, ctx); 85402744e81Swyllys 85502744e81Swyllys /* Coef = (Inverse Q) mod P */ 85602744e81Swyllys COEF = BN_new(); 85702744e81Swyllys (void) BN_mod_inverse(COEF, Q, P, ctx); 85802744e81Swyllys 85902744e81Swyllys /* Convert back to KMF format */ 86002744e81Swyllys (void) memset(&rsa, 0, sizeof (rsa)); 86102744e81Swyllys 86202744e81Swyllys if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK) 86302744e81Swyllys goto out; 86402744e81Swyllys if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK) 86502744e81Swyllys goto out; 86602744e81Swyllys if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK) 86702744e81Swyllys goto out; 86802744e81Swyllys 86902744e81Swyllys rsa.mod.val = (uchar_t *)Mod->bv_val; 87002744e81Swyllys rsa.mod.len = Mod->bv_len; 87102744e81Swyllys 87202744e81Swyllys rsa.pubexp.val = (uchar_t *)PubExp->bv_val; 87302744e81Swyllys rsa.pubexp.len = PubExp->bv_len; 87402744e81Swyllys 87502744e81Swyllys rsa.priexp.val = (uchar_t *)PriExp->bv_val; 87602744e81Swyllys rsa.priexp.len = PriExp->bv_len; 87702744e81Swyllys 87802744e81Swyllys rsa.prime1.val = (uchar_t *)Prime1->bv_val; 87902744e81Swyllys rsa.prime1.len = Prime1->bv_len; 88002744e81Swyllys 88102744e81Swyllys rsa.prime2.val = (uchar_t *)Prime2->bv_val; 88202744e81Swyllys rsa.prime2.len = Prime2->bv_len; 88302744e81Swyllys 88402744e81Swyllys *pkey = ImportRawRSAKey(&rsa); 88502744e81Swyllys out: 88602744e81Swyllys if (asn1 != NULL) 88702744e81Swyllys kmfber_free(asn1, 1); 88802744e81Swyllys 88902744e81Swyllys if (OID.bv_val) { 89002744e81Swyllys free(OID.bv_val); 89102744e81Swyllys } 89202744e81Swyllys if (PriExp) 89302744e81Swyllys free(PriExp); 89402744e81Swyllys 89502744e81Swyllys if (Mod) 89602744e81Swyllys free(Mod); 89702744e81Swyllys 89802744e81Swyllys if (PubExp) 89902744e81Swyllys free(PubExp); 90002744e81Swyllys 90102744e81Swyllys if (Coef) { 90202744e81Swyllys (void) memset(Coef->bv_val, 0, Coef->bv_len); 90302744e81Swyllys free(Coef->bv_val); 90402744e81Swyllys free(Coef); 90502744e81Swyllys } 90602744e81Swyllys if (Prime1) 90702744e81Swyllys free(Prime1); 90802744e81Swyllys if (Prime2) 90902744e81Swyllys free(Prime2); 91002744e81Swyllys 91102744e81Swyllys if (ctx != NULL) 91202744e81Swyllys BN_CTX_free(ctx); 91302744e81Swyllys 91402744e81Swyllys if (D) 91502744e81Swyllys BN_clear_free(D); 91602744e81Swyllys if (P) 91702744e81Swyllys BN_clear_free(P); 91802744e81Swyllys if (Q) 91902744e81Swyllys BN_clear_free(Q); 92002744e81Swyllys if (pminus1) 92102744e81Swyllys BN_clear_free(pminus1); 92202744e81Swyllys if (qminus1) 92302744e81Swyllys BN_clear_free(qminus1); 92402744e81Swyllys if (Exp1) 92502744e81Swyllys BN_clear_free(Exp1); 92602744e81Swyllys if (Exp2) 92702744e81Swyllys BN_clear_free(Exp2); 92802744e81Swyllys 92902744e81Swyllys return (ret); 93002744e81Swyllys 93102744e81Swyllys } 93202744e81Swyllys 93399ebb4caSwyllys static EVP_PKEY * 93499ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file) 93599ebb4caSwyllys { 93699ebb4caSwyllys BIO *keyfile = NULL; 93799ebb4caSwyllys EVP_PKEY *pkey = NULL; 93899ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 93999ebb4caSwyllys KMF_ENCODE_FORMAT format; 94002744e81Swyllys KMF_RETURN rv; 94102744e81Swyllys KMF_DATA filedata; 94299ebb4caSwyllys 94399ebb4caSwyllys if (file == NULL) { 94499ebb4caSwyllys return (NULL); 94599ebb4caSwyllys } 94699ebb4caSwyllys 94730a5e8faSwyllys if (kmf_get_file_format((char *)file, &format) != KMF_OK) 94899ebb4caSwyllys return (NULL); 94999ebb4caSwyllys 95099ebb4caSwyllys keyfile = BIO_new_file(file, "rb"); 95199ebb4caSwyllys if (keyfile == NULL) { 95299ebb4caSwyllys goto end; 95399ebb4caSwyllys } 95499ebb4caSwyllys 95502744e81Swyllys if (format == KMF_FORMAT_ASN1) { 95699ebb4caSwyllys pkey = d2i_PrivateKey_bio(keyfile, NULL); 95702744e81Swyllys if (pkey == NULL) { 95802744e81Swyllys 95902744e81Swyllys (void) BIO_free(keyfile); 96002744e81Swyllys keyfile = NULL; 96102744e81Swyllys /* Try odd ASN.1 variations */ 96230a5e8faSwyllys rv = kmf_read_input_file(kmfh, (char *)file, 96302744e81Swyllys &filedata); 96402744e81Swyllys if (rv == KMF_OK) { 96502744e81Swyllys (void) readAltFormatPrivateKey(&filedata, 96602744e81Swyllys &pkey); 96730a5e8faSwyllys kmf_free_data(&filedata); 96802744e81Swyllys } 96902744e81Swyllys } 97002744e81Swyllys } else if (format == KMF_FORMAT_PEM || 97102744e81Swyllys format == KMF_FORMAT_PEM_KEYPAIR) { 97299ebb4caSwyllys pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL); 97302744e81Swyllys if (pkey == NULL) { 97402744e81Swyllys KMF_DATA derdata; 97502744e81Swyllys /* 97602744e81Swyllys * Check if this is the alt. format 97702744e81Swyllys * RSA private key file. 97802744e81Swyllys */ 97930a5e8faSwyllys rv = kmf_read_input_file(kmfh, (char *)file, 98002744e81Swyllys &filedata); 98102744e81Swyllys if (rv == KMF_OK) { 98202744e81Swyllys uchar_t *d = NULL; 98302744e81Swyllys int len; 98430a5e8faSwyllys rv = kmf_pem_to_der(filedata.Data, 98502744e81Swyllys filedata.Length, &d, &len); 98602744e81Swyllys if (rv == KMF_OK && d != NULL) { 98702744e81Swyllys derdata.Data = d; 98802744e81Swyllys derdata.Length = (size_t)len; 98902744e81Swyllys (void) readAltFormatPrivateKey( 99002744e81Swyllys &derdata, &pkey); 99102744e81Swyllys free(d); 99202744e81Swyllys } 99330a5e8faSwyllys kmf_free_data(&filedata); 99402744e81Swyllys } 99502744e81Swyllys } 99602744e81Swyllys } 99799ebb4caSwyllys 99899ebb4caSwyllys end: 999a50e8766SToomas Soome if (pkey == NULL) { 100099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 1001a50e8766SToomas Soome } 100299ebb4caSwyllys 100399ebb4caSwyllys if (keyfile != NULL) 100499ebb4caSwyllys (void) BIO_free(keyfile); 100599ebb4caSwyllys 100699ebb4caSwyllys return (pkey); 100799ebb4caSwyllys } 100899ebb4caSwyllys 100999ebb4caSwyllys KMF_RETURN 101030a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 101199ebb4caSwyllys { 101299ebb4caSwyllys KMF_RETURN rv = KMF_OK; 101399ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 1014f482c776Swyllys int i, n; 1015f482c776Swyllys uint32_t maxcerts = 0; 101630a5e8faSwyllys uint32_t *num_certs; 101730a5e8faSwyllys KMF_X509_DER_CERT *kmf_cert = NULL; 101830a5e8faSwyllys char *dirpath = NULL; 101930a5e8faSwyllys char *filename = NULL; 102030a5e8faSwyllys char *fullpath = NULL; 102130a5e8faSwyllys char *issuer = NULL; 102230a5e8faSwyllys char *subject = NULL; 102330a5e8faSwyllys KMF_BIGINT *serial = NULL; 102430a5e8faSwyllys KMF_CERT_VALIDITY validity; 102599ebb4caSwyllys 102630a5e8faSwyllys num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr); 102730a5e8faSwyllys if (num_certs == NULL) 102899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 102999ebb4caSwyllys 103030a5e8faSwyllys /* num_certs should reference the size of kmf_cert */ 1031f482c776Swyllys maxcerts = *num_certs; 1032f482c776Swyllys if (maxcerts == 0) 1033f482c776Swyllys maxcerts = 0xFFFFFFFF; 103499ebb4caSwyllys *num_certs = 0; 103599ebb4caSwyllys 103630a5e8faSwyllys /* Get the optional returned certificate list */ 103730a5e8faSwyllys kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist, 103830a5e8faSwyllys numattr); 103999ebb4caSwyllys 104030a5e8faSwyllys /* 104130a5e8faSwyllys * The dirpath attribute and the filename attribute can not be NULL 104230a5e8faSwyllys * at the same time. 104330a5e8faSwyllys */ 104430a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 104530a5e8faSwyllys filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, 104630a5e8faSwyllys numattr); 104730a5e8faSwyllys 104830a5e8faSwyllys fullpath = get_fullpath(dirpath, filename); 104999ebb4caSwyllys if (fullpath == NULL) 105099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 105199ebb4caSwyllys 105230a5e8faSwyllys /* Get optional search criteria attributes */ 105330a5e8faSwyllys issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr); 105430a5e8faSwyllys subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr); 105530a5e8faSwyllys serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr); 105630a5e8faSwyllys rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr, 105730a5e8faSwyllys &validity, NULL); 105830a5e8faSwyllys if (rv != KMF_OK) { 105930a5e8faSwyllys validity = KMF_ALL_CERTS; 106030a5e8faSwyllys rv = KMF_OK; 106130a5e8faSwyllys } 106230a5e8faSwyllys 106399ebb4caSwyllys if (isdir(fullpath)) { 106499ebb4caSwyllys DIR *dirp; 106599ebb4caSwyllys struct dirent *dp; 106699ebb4caSwyllys 1067f482c776Swyllys n = 0; 106899ebb4caSwyllys /* open all files in the directory and attempt to read them */ 106999ebb4caSwyllys if ((dirp = opendir(fullpath)) == NULL) { 107099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 107199ebb4caSwyllys } 107299ebb4caSwyllys while ((dp = readdir(dirp)) != NULL) { 107399ebb4caSwyllys char *fname; 107471593db2Swyllys KMF_DATA *certlist = NULL; 1075f482c776Swyllys uint32_t loaded_certs = 0; 107671593db2Swyllys 107799ebb4caSwyllys if (strcmp(dp->d_name, ".") == 0 || 107899ebb4caSwyllys strcmp(dp->d_name, "..") == 0) 107999ebb4caSwyllys continue; 108099ebb4caSwyllys 108134acef67Swyllys fname = get_fullpath(fullpath, (char *)&dp->d_name); 108299ebb4caSwyllys 108330a5e8faSwyllys rv = load_certs(kmfh, issuer, subject, serial, 108430a5e8faSwyllys validity, fname, &certlist, &loaded_certs); 108599ebb4caSwyllys 108699ebb4caSwyllys if (rv != KMF_OK) { 108799ebb4caSwyllys free(fname); 108871593db2Swyllys if (certlist != NULL) { 1089f482c776Swyllys for (i = 0; i < loaded_certs; i++) 109030a5e8faSwyllys kmf_free_data(&certlist[i]); 109171593db2Swyllys free(certlist); 109271593db2Swyllys } 109399ebb4caSwyllys continue; 109499ebb4caSwyllys } 109599ebb4caSwyllys 109699ebb4caSwyllys /* If load succeeds, add certdata to the list */ 109799ebb4caSwyllys if (kmf_cert != NULL) { 1098f482c776Swyllys for (i = 0; i < loaded_certs && 1099b4058258Swyllys n < maxcerts; i++) { 110071593db2Swyllys kmf_cert[n].certificate.Data = 110171593db2Swyllys certlist[i].Data; 110299ebb4caSwyllys kmf_cert[n].certificate.Length = 110371593db2Swyllys certlist[i].Length; 110499ebb4caSwyllys 110599ebb4caSwyllys kmf_cert[n].kmf_private.keystore_type = 110699ebb4caSwyllys KMF_KEYSTORE_OPENSSL; 110799ebb4caSwyllys kmf_cert[n].kmf_private.flags = 110899ebb4caSwyllys KMF_FLAG_CERT_VALID; 110971593db2Swyllys kmf_cert[n].kmf_private.label = 111071593db2Swyllys strdup(fname); 111199ebb4caSwyllys n++; 111299ebb4caSwyllys } 1113b4058258Swyllys /* 1114b4058258Swyllys * If maxcerts < loaded_certs, clean up the 1115b4058258Swyllys * certs that were not used. 1116b4058258Swyllys */ 1117f482c776Swyllys for (; i < loaded_certs; i++) 111830a5e8faSwyllys kmf_free_data(&certlist[i]); 1119f482c776Swyllys } else { 1120f482c776Swyllys for (i = 0; i < loaded_certs; i++) 112130a5e8faSwyllys kmf_free_data(&certlist[i]); 1122f482c776Swyllys n += loaded_certs; 112371593db2Swyllys } 1124f482c776Swyllys free(certlist); 112571593db2Swyllys free(fname); 112671593db2Swyllys } 112799ebb4caSwyllys (*num_certs) = n; 112899ebb4caSwyllys if (*num_certs == 0) 112999ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND; 113030a5e8faSwyllys if (*num_certs > 0) 113199ebb4caSwyllys rv = KMF_OK; 113299ebb4caSwyllys exit: 113399ebb4caSwyllys (void) closedir(dirp); 113499ebb4caSwyllys } else { 113571593db2Swyllys KMF_DATA *certlist = NULL; 1136f482c776Swyllys uint32_t loaded_certs = 0; 113771593db2Swyllys 113830a5e8faSwyllys rv = load_certs(kmfh, issuer, subject, serial, validity, 113930a5e8faSwyllys fullpath, &certlist, &loaded_certs); 114099ebb4caSwyllys if (rv != KMF_OK) { 114199ebb4caSwyllys free(fullpath); 114299ebb4caSwyllys return (rv); 114399ebb4caSwyllys } 114499ebb4caSwyllys 1145f482c776Swyllys n = 0; 114671593db2Swyllys if (kmf_cert != NULL && certlist != NULL) { 1147f482c776Swyllys for (i = 0; i < loaded_certs && i < maxcerts; i++) { 1148f482c776Swyllys kmf_cert[n].certificate.Data = 114971593db2Swyllys certlist[i].Data; 1150f482c776Swyllys kmf_cert[n].certificate.Length = 115171593db2Swyllys certlist[i].Length; 1152f482c776Swyllys kmf_cert[n].kmf_private.keystore_type = 115399ebb4caSwyllys KMF_KEYSTORE_OPENSSL; 1154f482c776Swyllys kmf_cert[n].kmf_private.flags = 115571593db2Swyllys KMF_FLAG_CERT_VALID; 1156f482c776Swyllys kmf_cert[n].kmf_private.label = 115771593db2Swyllys strdup(fullpath); 1158f482c776Swyllys n++; 115971593db2Swyllys } 1160f482c776Swyllys /* If maxcerts < loaded_certs, clean up */ 1161f482c776Swyllys for (; i < loaded_certs; i++) 116230a5e8faSwyllys kmf_free_data(&certlist[i]); 1163f482c776Swyllys } else if (certlist != NULL) { 1164f482c776Swyllys for (i = 0; i < loaded_certs; i++) 116530a5e8faSwyllys kmf_free_data(&certlist[i]); 1166f482c776Swyllys n = loaded_certs; 1167f482c776Swyllys } 116830a5e8faSwyllys if (certlist != NULL) 116971593db2Swyllys free(certlist); 1170f482c776Swyllys *num_certs = n; 117199ebb4caSwyllys } 117299ebb4caSwyllys 117399ebb4caSwyllys free(fullpath); 117499ebb4caSwyllys 117599ebb4caSwyllys return (rv); 117699ebb4caSwyllys } 117799ebb4caSwyllys 117899ebb4caSwyllys void 1179*4942e222SAndy Fiddaman OpenSSL_FreeKMFCert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert) 118099ebb4caSwyllys { 118199ebb4caSwyllys if (kmf_cert != NULL) { 118299ebb4caSwyllys if (kmf_cert->certificate.Data != NULL) { 1183e65e5c2dSWyllys Ingersoll kmf_free_data(&kmf_cert->certificate); 118499ebb4caSwyllys } 118599ebb4caSwyllys if (kmf_cert->kmf_private.label) 118699ebb4caSwyllys free(kmf_cert->kmf_private.label); 118799ebb4caSwyllys } 118899ebb4caSwyllys } 118999ebb4caSwyllys 119099ebb4caSwyllys KMF_RETURN 119130a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 119299ebb4caSwyllys { 119399ebb4caSwyllys KMF_RETURN ret = KMF_OK; 119430a5e8faSwyllys KMF_DATA *cert = NULL; 119530a5e8faSwyllys char *outfilename = NULL; 119630a5e8faSwyllys char *dirpath = NULL; 119730a5e8faSwyllys char *fullpath = NULL; 119899ebb4caSwyllys KMF_ENCODE_FORMAT format; 119999ebb4caSwyllys 120030a5e8faSwyllys /* Get the cert data */ 120130a5e8faSwyllys cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr); 120230a5e8faSwyllys if (cert == NULL || cert->Data == NULL) 120399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 120499ebb4caSwyllys 120530a5e8faSwyllys /* Check the output filename and directory attributes. */ 120630a5e8faSwyllys outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, 120730a5e8faSwyllys numattr); 120830a5e8faSwyllys if (outfilename == NULL) 120930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 121099ebb4caSwyllys 121130a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 121230a5e8faSwyllys fullpath = get_fullpath(dirpath, outfilename); 121399ebb4caSwyllys if (fullpath == NULL) 121430a5e8faSwyllys return (KMF_ERR_BAD_CERTFILE); 121599ebb4caSwyllys 121630a5e8faSwyllys /* Check the optional format attribute */ 121730a5e8faSwyllys ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 121830a5e8faSwyllys &format, NULL); 121930a5e8faSwyllys if (ret != KMF_OK) { 122030a5e8faSwyllys /* If there is no format attribute, then default to PEM */ 122130a5e8faSwyllys format = KMF_FORMAT_PEM; 122299ebb4caSwyllys ret = KMF_OK; 122330a5e8faSwyllys } else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) { 122430a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 122599ebb4caSwyllys goto out; 122699ebb4caSwyllys } 122799ebb4caSwyllys 122830a5e8faSwyllys /* Store the certificate in the file with the specified format */ 122930a5e8faSwyllys ret = kmf_create_cert_file(cert, format, fullpath); 123099ebb4caSwyllys 123199ebb4caSwyllys out: 123299ebb4caSwyllys if (fullpath != NULL) 123399ebb4caSwyllys free(fullpath); 123499ebb4caSwyllys 123599ebb4caSwyllys return (ret); 123699ebb4caSwyllys } 123799ebb4caSwyllys 123830a5e8faSwyllys 123999ebb4caSwyllys KMF_RETURN 124030a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 124199ebb4caSwyllys { 124299ebb4caSwyllys KMF_RETURN rv; 124399ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 12446b35cb3cSRichard PALO KMF_DATA certdata = { 0, NULL }; 124530a5e8faSwyllys char *dirpath = NULL; 124630a5e8faSwyllys char *filename = NULL; 124730a5e8faSwyllys char *fullpath = NULL; 124830a5e8faSwyllys char *issuer = NULL; 124930a5e8faSwyllys char *subject = NULL; 125030a5e8faSwyllys KMF_BIGINT *serial = NULL; 125130a5e8faSwyllys KMF_CERT_VALIDITY validity; 125299ebb4caSwyllys 125330a5e8faSwyllys /* 125430a5e8faSwyllys * Get the DIRPATH and CERT_FILENAME attributes. They can not be 125530a5e8faSwyllys * NULL at the same time. 125630a5e8faSwyllys */ 125730a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 125830a5e8faSwyllys filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, 125930a5e8faSwyllys numattr); 126030a5e8faSwyllys fullpath = get_fullpath(dirpath, filename); 126199ebb4caSwyllys if (fullpath == NULL) 126299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 126399ebb4caSwyllys 126430a5e8faSwyllys /* Get optional search criteria attributes */ 126530a5e8faSwyllys issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr); 126630a5e8faSwyllys subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr); 126730a5e8faSwyllys serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr); 126830a5e8faSwyllys rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr, 126930a5e8faSwyllys &validity, NULL); 127030a5e8faSwyllys if (rv != KMF_OK) { 127130a5e8faSwyllys validity = KMF_ALL_CERTS; 127230a5e8faSwyllys rv = KMF_OK; 127330a5e8faSwyllys } 127430a5e8faSwyllys 127599ebb4caSwyllys if (isdir(fullpath)) { 127699ebb4caSwyllys DIR *dirp; 127799ebb4caSwyllys struct dirent *dp; 127899ebb4caSwyllys 127999ebb4caSwyllys /* open all files in the directory and attempt to read them */ 128099ebb4caSwyllys if ((dirp = opendir(fullpath)) == NULL) { 128199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 128299ebb4caSwyllys } 128399ebb4caSwyllys 128499ebb4caSwyllys while ((dp = readdir(dirp)) != NULL) { 128599ebb4caSwyllys if (strcmp(dp->d_name, ".") != 0 && 128699ebb4caSwyllys strcmp(dp->d_name, "..") != 0) { 128799ebb4caSwyllys char *fname; 128899ebb4caSwyllys 128999ebb4caSwyllys fname = get_fullpath(fullpath, 129099ebb4caSwyllys (char *)&dp->d_name); 129199ebb4caSwyllys 129299ebb4caSwyllys if (fname == NULL) { 129399ebb4caSwyllys rv = KMF_ERR_MEMORY; 129499ebb4caSwyllys break; 129599ebb4caSwyllys } 129699ebb4caSwyllys 129730a5e8faSwyllys rv = kmf_load_cert(kmfh, issuer, subject, 129830a5e8faSwyllys serial, validity, fname, &certdata); 129999ebb4caSwyllys 130099ebb4caSwyllys if (rv == KMF_ERR_CERT_NOT_FOUND) { 130199ebb4caSwyllys free(fname); 1302e65e5c2dSWyllys Ingersoll kmf_free_data(&certdata); 130399ebb4caSwyllys rv = KMF_OK; 130499ebb4caSwyllys continue; 130599ebb4caSwyllys } else if (rv != KMF_OK) { 130699ebb4caSwyllys free(fname); 130799ebb4caSwyllys break; 130899ebb4caSwyllys } 130999ebb4caSwyllys 131099ebb4caSwyllys if (unlink(fname) != 0) { 131199ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 131299ebb4caSwyllys rv = KMF_ERR_INTERNAL; 131399ebb4caSwyllys free(fname); 131499ebb4caSwyllys break; 131599ebb4caSwyllys } 131699ebb4caSwyllys free(fname); 1317e65e5c2dSWyllys Ingersoll kmf_free_data(&certdata); 131899ebb4caSwyllys } 131999ebb4caSwyllys } 132099ebb4caSwyllys (void) closedir(dirp); 132199ebb4caSwyllys } else { 132299ebb4caSwyllys /* Just try to load a single certificate */ 132330a5e8faSwyllys rv = kmf_load_cert(kmfh, issuer, subject, serial, validity, 132430a5e8faSwyllys fullpath, &certdata); 132599ebb4caSwyllys if (rv == KMF_OK) { 132699ebb4caSwyllys if (unlink(fullpath) != 0) { 132799ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 132899ebb4caSwyllys rv = KMF_ERR_INTERNAL; 132999ebb4caSwyllys } 133099ebb4caSwyllys } 133199ebb4caSwyllys } 133299ebb4caSwyllys 133399ebb4caSwyllys out: 133499ebb4caSwyllys if (fullpath != NULL) 133599ebb4caSwyllys free(fullpath); 133699ebb4caSwyllys 1337e65e5c2dSWyllys Ingersoll kmf_free_data(&certdata); 133899ebb4caSwyllys 133999ebb4caSwyllys return (rv); 134099ebb4caSwyllys } 134199ebb4caSwyllys 134299ebb4caSwyllys KMF_RETURN 134399ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, 134499ebb4caSwyllys KMF_DATA *keydata) 134599ebb4caSwyllys { 134699ebb4caSwyllys KMF_RETURN rv = KMF_OK; 134799ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 134899ebb4caSwyllys int n; 134999ebb4caSwyllys 135099ebb4caSwyllys if (key == NULL || keydata == NULL || 135199ebb4caSwyllys key->keyp == NULL) 135299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 135399ebb4caSwyllys 135499ebb4caSwyllys if (key->keyalg == KMF_RSA) { 135599ebb4caSwyllys RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp); 135699ebb4caSwyllys 135799ebb4caSwyllys if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) { 135899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 135999ebb4caSwyllys return (KMF_ERR_ENCODING); 136099ebb4caSwyllys } 136199ebb4caSwyllys RSA_free(pubkey); 136299ebb4caSwyllys } else if (key->keyalg == KMF_DSA) { 136399ebb4caSwyllys DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp); 136499ebb4caSwyllys 136599ebb4caSwyllys if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) { 136699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 136799ebb4caSwyllys return (KMF_ERR_ENCODING); 136899ebb4caSwyllys } 136999ebb4caSwyllys DSA_free(pubkey); 137099ebb4caSwyllys } else { 137199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 137299ebb4caSwyllys } 137399ebb4caSwyllys keydata->Length = n; 137499ebb4caSwyllys 137599ebb4caSwyllys cleanup: 137699ebb4caSwyllys if (rv != KMF_OK) { 137799ebb4caSwyllys if (keydata->Data) 137899ebb4caSwyllys free(keydata->Data); 137999ebb4caSwyllys keydata->Data = NULL; 138099ebb4caSwyllys keydata->Length = 0; 138199ebb4caSwyllys } 138299ebb4caSwyllys 138399ebb4caSwyllys return (rv); 138499ebb4caSwyllys } 138599ebb4caSwyllys 138699ebb4caSwyllys static KMF_RETURN 138730a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out, 138830a5e8faSwyllys KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private) 138999ebb4caSwyllys { 139099ebb4caSwyllys int rv = 0; 139199ebb4caSwyllys RSA *rsa; 139299ebb4caSwyllys DSA *dsa; 139399ebb4caSwyllys 13945b3e1433Swyllys if (pkey == NULL || out == NULL) 13955b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 13965b3e1433Swyllys 139799ebb4caSwyllys switch (format) { 139873cc0e02Swyllys case KMF_FORMAT_RAWKEY: 139973cc0e02Swyllys /* same as ASN.1 */ 140099ebb4caSwyllys case KMF_FORMAT_ASN1: 1401300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) { 140230a5e8faSwyllys if (private) 140399ebb4caSwyllys rv = i2d_RSAPrivateKey_bio(out, rsa); 140430a5e8faSwyllys else 140530a5e8faSwyllys rv = i2d_RSAPublicKey_bio(out, rsa); 1406300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) { 140799ebb4caSwyllys rv = i2d_DSAPrivateKey_bio(out, dsa); 140899ebb4caSwyllys } 140999ebb4caSwyllys if (rv == 1) { 141099ebb4caSwyllys rv = KMF_OK; 141199ebb4caSwyllys } else { 141299ebb4caSwyllys SET_ERROR(kmfh, rv); 141399ebb4caSwyllys } 141499ebb4caSwyllys break; 141599ebb4caSwyllys case KMF_FORMAT_PEM: 1416300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) { 141730a5e8faSwyllys if (private) 141899ebb4caSwyllys rv = PEM_write_bio_RSAPrivateKey(out, 141930a5e8faSwyllys rsa, NULL, NULL, 0, NULL, 142030a5e8faSwyllys (cred != NULL ? cred->cred : NULL)); 142130a5e8faSwyllys else 142230a5e8faSwyllys rv = PEM_write_bio_RSAPublicKey(out, 142330a5e8faSwyllys rsa); 1424300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) { 142599ebb4caSwyllys rv = PEM_write_bio_DSAPrivateKey(out, 142630a5e8faSwyllys dsa, NULL, NULL, 0, NULL, 142730a5e8faSwyllys (cred != NULL ? cred->cred : NULL)); 142899ebb4caSwyllys } 142999ebb4caSwyllys 143099ebb4caSwyllys if (rv == 1) { 143199ebb4caSwyllys rv = KMF_OK; 143299ebb4caSwyllys } else { 143399ebb4caSwyllys SET_ERROR(kmfh, rv); 143499ebb4caSwyllys } 143599ebb4caSwyllys break; 143699ebb4caSwyllys 143799ebb4caSwyllys default: 143899ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 143999ebb4caSwyllys } 144099ebb4caSwyllys 144199ebb4caSwyllys return (rv); 144299ebb4caSwyllys } 144399ebb4caSwyllys 144499ebb4caSwyllys KMF_RETURN 1445*4942e222SAndy Fiddaman OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 144699ebb4caSwyllys { 144799ebb4caSwyllys KMF_RETURN rv = KMF_OK; 144899ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 1449300fdee2SAndy Fiddaman uint32_t eValue = RSA_F4; 1450300fdee2SAndy Fiddaman BIGNUM *eValue_bn = NULL; 145199ebb4caSwyllys RSA *sslPrivKey = NULL; 145299ebb4caSwyllys DSA *sslDSAKey = NULL; 145399ebb4caSwyllys EVP_PKEY *eprikey = NULL; 145499ebb4caSwyllys EVP_PKEY *epubkey = NULL; 145599ebb4caSwyllys BIO *out = NULL; 145630a5e8faSwyllys KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL; 145730a5e8faSwyllys uint32_t keylen = 1024; 145830a5e8faSwyllys uint32_t keylen_size = sizeof (uint32_t); 145930a5e8faSwyllys boolean_t storekey = TRUE; 146030a5e8faSwyllys KMF_KEY_ALG keytype = KMF_RSA; 146199ebb4caSwyllys 1462300fdee2SAndy Fiddaman eValue_bn = BN_new(); 1463300fdee2SAndy Fiddaman if (eValue_bn == NULL) 1464300fdee2SAndy Fiddaman return (KMF_ERR_MEMORY); 1465300fdee2SAndy Fiddaman if (BN_set_word(eValue_bn, eValue) == 0) { 1466300fdee2SAndy Fiddaman rv = KMF_ERR_KEYGEN_FAILED; 1467300fdee2SAndy Fiddaman goto cleanup; 1468300fdee2SAndy Fiddaman } 1469300fdee2SAndy Fiddaman 147030a5e8faSwyllys rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr, 147130a5e8faSwyllys &storekey, NULL); 147230a5e8faSwyllys if (rv != KMF_OK) { 147330a5e8faSwyllys /* "storekey" is optional. Default is TRUE */ 147430a5e8faSwyllys rv = KMF_OK; 147599ebb4caSwyllys } 147699ebb4caSwyllys 147730a5e8faSwyllys rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, 147830a5e8faSwyllys (void *)&keytype, NULL); 147930a5e8faSwyllys if (rv != KMF_OK) 148030a5e8faSwyllys /* keytype is optional. KMF_RSA is default */ 148130a5e8faSwyllys rv = KMF_OK; 148299ebb4caSwyllys 148330a5e8faSwyllys pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr); 1484300fdee2SAndy Fiddaman if (pubkey == NULL) { 1485300fdee2SAndy Fiddaman rv = KMF_ERR_BAD_PARAMETER; 1486300fdee2SAndy Fiddaman goto cleanup; 1487300fdee2SAndy Fiddaman } 148899ebb4caSwyllys 148930a5e8faSwyllys privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr); 1490300fdee2SAndy Fiddaman if (privkey == NULL) { 1491300fdee2SAndy Fiddaman rv = KMF_ERR_BAD_PARAMETER; 1492300fdee2SAndy Fiddaman goto cleanup; 1493300fdee2SAndy Fiddaman } 149430a5e8faSwyllys 149530a5e8faSwyllys (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE)); 149630a5e8faSwyllys (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE)); 149799ebb4caSwyllys 149899ebb4caSwyllys eprikey = EVP_PKEY_new(); 149999ebb4caSwyllys if (eprikey == NULL) { 150099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 150199ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 150299ebb4caSwyllys goto cleanup; 150399ebb4caSwyllys } 150499ebb4caSwyllys epubkey = EVP_PKEY_new(); 150599ebb4caSwyllys if (epubkey == NULL) { 150699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 150799ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 150899ebb4caSwyllys goto cleanup; 150999ebb4caSwyllys } 151030a5e8faSwyllys if (keytype == KMF_RSA) { 151130a5e8faSwyllys KMF_BIGINT *rsaexp = NULL; 151299ebb4caSwyllys 151330a5e8faSwyllys rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr); 151430a5e8faSwyllys if (rsaexp != NULL) { 151530a5e8faSwyllys if (rsaexp->len > 0 && 151630a5e8faSwyllys rsaexp->len <= sizeof (eValue) && 151730a5e8faSwyllys rsaexp->val != NULL) { 151830a5e8faSwyllys eValue = *(uint32_t *)rsaexp->val; 1519300fdee2SAndy Fiddaman if (BN_set_word(eValue_bn, eValue) == 0) { 1520300fdee2SAndy Fiddaman rv = KMF_ERR_BAD_PARAMETER; 1521300fdee2SAndy Fiddaman goto cleanup; 1522300fdee2SAndy Fiddaman } 152330a5e8faSwyllys } else { 152430a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 152530a5e8faSwyllys goto cleanup; 152630a5e8faSwyllys } 152730a5e8faSwyllys } else { 152830a5e8faSwyllys /* RSA Exponent is optional. Default is 0x10001 */ 152930a5e8faSwyllys rv = KMF_OK; 153030a5e8faSwyllys } 153130a5e8faSwyllys 153230a5e8faSwyllys rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, 153330a5e8faSwyllys &keylen, &keylen_size); 153430a5e8faSwyllys if (rv == KMF_ERR_ATTR_NOT_FOUND) 153530a5e8faSwyllys /* keylen is optional, default is 1024 */ 153630a5e8faSwyllys rv = KMF_OK; 153730a5e8faSwyllys if (rv != KMF_OK) { 153830a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 153930a5e8faSwyllys goto cleanup; 154030a5e8faSwyllys } 154130a5e8faSwyllys 1542300fdee2SAndy Fiddaman sslPrivKey = RSA_new(); 1543300fdee2SAndy Fiddaman if (sslPrivKey == NULL || 1544300fdee2SAndy Fiddaman RSA_generate_key_ex(sslPrivKey, keylen, eValue_bn, NULL) 1545300fdee2SAndy Fiddaman == 0) { 154699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 154799ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 154899ebb4caSwyllys } else { 154930a5e8faSwyllys (void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey); 155099ebb4caSwyllys privkey->kstype = KMF_KEYSTORE_OPENSSL; 155199ebb4caSwyllys privkey->keyalg = KMF_RSA; 155299ebb4caSwyllys privkey->keyclass = KMF_ASYM_PRI; 155399ebb4caSwyllys privkey->israw = FALSE; 155499ebb4caSwyllys privkey->keyp = (void *)eprikey; 155530a5e8faSwyllys 155699ebb4caSwyllys /* OpenSSL derives the public key from the private */ 155730a5e8faSwyllys (void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey); 155899ebb4caSwyllys pubkey->kstype = KMF_KEYSTORE_OPENSSL; 155999ebb4caSwyllys pubkey->keyalg = KMF_RSA; 156099ebb4caSwyllys pubkey->israw = FALSE; 156199ebb4caSwyllys pubkey->keyclass = KMF_ASYM_PUB; 156299ebb4caSwyllys pubkey->keyp = (void *)epubkey; 156399ebb4caSwyllys } 156430a5e8faSwyllys } else if (keytype == KMF_DSA) { 1565300fdee2SAndy Fiddaman BIGNUM *p, *q, *g; 1566300fdee2SAndy Fiddaman 156799ebb4caSwyllys sslDSAKey = DSA_new(); 156899ebb4caSwyllys if (sslDSAKey == NULL) { 156999ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 157099ebb4caSwyllys return (KMF_ERR_MEMORY); 157199ebb4caSwyllys } 157299ebb4caSwyllys 1573300fdee2SAndy Fiddaman p = BN_bin2bn(P, sizeof (P), NULL); 1574300fdee2SAndy Fiddaman q = BN_bin2bn(Q, sizeof (Q), NULL); 1575300fdee2SAndy Fiddaman g = BN_bin2bn(G, sizeof (G), NULL); 1576300fdee2SAndy Fiddaman if (p == NULL || q == NULL || g == NULL) { 1577300fdee2SAndy Fiddaman BN_free(p); 1578300fdee2SAndy Fiddaman BN_free(q); 1579300fdee2SAndy Fiddaman BN_free(g); 158099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 158199ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 158299ebb4caSwyllys goto cleanup; 158399ebb4caSwyllys } 1584300fdee2SAndy Fiddaman 1585300fdee2SAndy Fiddaman if (DSA_set0_pqg(sslDSAKey, p, q, g) == 0) { 158699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 158799ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 158899ebb4caSwyllys goto cleanup; 158999ebb4caSwyllys } 159099ebb4caSwyllys 159199ebb4caSwyllys if (!DSA_generate_key(sslDSAKey)) { 159299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 159399ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 159499ebb4caSwyllys goto cleanup; 159599ebb4caSwyllys } 159699ebb4caSwyllys 159799ebb4caSwyllys privkey->kstype = KMF_KEYSTORE_OPENSSL; 159899ebb4caSwyllys privkey->keyalg = KMF_DSA; 159999ebb4caSwyllys privkey->keyclass = KMF_ASYM_PRI; 160099ebb4caSwyllys privkey->israw = FALSE; 160199ebb4caSwyllys if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) { 160299ebb4caSwyllys privkey->keyp = (void *)eprikey; 160399ebb4caSwyllys } else { 160499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 160599ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 160699ebb4caSwyllys goto cleanup; 160799ebb4caSwyllys } 160899ebb4caSwyllys 160999ebb4caSwyllys pubkey->kstype = KMF_KEYSTORE_OPENSSL; 161099ebb4caSwyllys pubkey->keyalg = KMF_DSA; 161199ebb4caSwyllys pubkey->keyclass = KMF_ASYM_PUB; 161299ebb4caSwyllys pubkey->israw = FALSE; 161399ebb4caSwyllys 161499ebb4caSwyllys if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) { 161599ebb4caSwyllys pubkey->keyp = (void *)epubkey; 161699ebb4caSwyllys } else { 161799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 161899ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 161999ebb4caSwyllys goto cleanup; 162099ebb4caSwyllys } 162199ebb4caSwyllys } 162299ebb4caSwyllys 162399ebb4caSwyllys if (rv != KMF_OK) { 162499ebb4caSwyllys goto cleanup; 162599ebb4caSwyllys } 162699ebb4caSwyllys 162730a5e8faSwyllys if (storekey) { 162830a5e8faSwyllys KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */ 162930a5e8faSwyllys int i = 0; 163030a5e8faSwyllys char *keyfile = NULL, *dirpath = NULL; 163130a5e8faSwyllys KMF_ENCODE_FORMAT format; 163230a5e8faSwyllys /* 163330a5e8faSwyllys * Construct a new attribute arrray and call openssl_store_key 163430a5e8faSwyllys */ 163530a5e8faSwyllys kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR, 163630a5e8faSwyllys privkey, sizeof (privkey)); 163730a5e8faSwyllys i++; 163830a5e8faSwyllys 163930a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 164030a5e8faSwyllys if (dirpath != NULL) { 164130a5e8faSwyllys storeattrs[i].type = KMF_DIRPATH_ATTR; 164230a5e8faSwyllys storeattrs[i].pValue = dirpath; 164330a5e8faSwyllys storeattrs[i].valueLen = strlen(dirpath); 164430a5e8faSwyllys i++; 164530a5e8faSwyllys } else { 164630a5e8faSwyllys rv = KMF_OK; /* DIRPATH is optional */ 164799ebb4caSwyllys } 164830a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, 164930a5e8faSwyllys attrlist, numattr); 165030a5e8faSwyllys if (keyfile != NULL) { 165130a5e8faSwyllys storeattrs[i].type = KMF_KEY_FILENAME_ATTR; 165230a5e8faSwyllys storeattrs[i].pValue = keyfile; 165330a5e8faSwyllys storeattrs[i].valueLen = strlen(keyfile); 165430a5e8faSwyllys i++; 165530a5e8faSwyllys } else { 165630a5e8faSwyllys goto cleanup; /* KEYFILE is required */ 165730a5e8faSwyllys } 165830a5e8faSwyllys rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 165930a5e8faSwyllys (void *)&format, NULL); 166030a5e8faSwyllys if (rv == KMF_OK) { 166130a5e8faSwyllys storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR; 166230a5e8faSwyllys storeattrs[i].pValue = &format; 166330a5e8faSwyllys storeattrs[i].valueLen = sizeof (format); 166430a5e8faSwyllys i++; 166530a5e8faSwyllys } 166630a5e8faSwyllys 166730a5e8faSwyllys rv = OpenSSL_StoreKey(handle, i, storeattrs); 166830a5e8faSwyllys } 166999ebb4caSwyllys 167099ebb4caSwyllys cleanup: 1671300fdee2SAndy Fiddaman if (eValue_bn != NULL) 1672300fdee2SAndy Fiddaman BN_free(eValue_bn); 1673300fdee2SAndy Fiddaman 167499ebb4caSwyllys if (rv != KMF_OK) { 167599ebb4caSwyllys if (eprikey != NULL) 167699ebb4caSwyllys EVP_PKEY_free(eprikey); 167799ebb4caSwyllys 167899ebb4caSwyllys if (epubkey != NULL) 167999ebb4caSwyllys EVP_PKEY_free(epubkey); 168099ebb4caSwyllys 168199ebb4caSwyllys if (pubkey->keylabel) { 168299ebb4caSwyllys free(pubkey->keylabel); 168399ebb4caSwyllys pubkey->keylabel = NULL; 168499ebb4caSwyllys } 168599ebb4caSwyllys 168699ebb4caSwyllys if (privkey->keylabel) { 168799ebb4caSwyllys free(privkey->keylabel); 168899ebb4caSwyllys privkey->keylabel = NULL; 168999ebb4caSwyllys } 169099ebb4caSwyllys 169199ebb4caSwyllys pubkey->keyp = NULL; 169299ebb4caSwyllys privkey->keyp = NULL; 169399ebb4caSwyllys } 169499ebb4caSwyllys 169599ebb4caSwyllys if (sslPrivKey) 169699ebb4caSwyllys RSA_free(sslPrivKey); 169799ebb4caSwyllys 169899ebb4caSwyllys if (sslDSAKey) 169999ebb4caSwyllys DSA_free(sslDSAKey); 170099ebb4caSwyllys 170199ebb4caSwyllys if (out != NULL) 170299ebb4caSwyllys (void) BIO_free(out); 170399ebb4caSwyllys 170499ebb4caSwyllys return (rv); 170599ebb4caSwyllys } 170699ebb4caSwyllys 1707e65e5c2dSWyllys Ingersoll /* 1708e65e5c2dSWyllys Ingersoll * Make sure the BN conversion is properly padded with 0x00 1709e65e5c2dSWyllys Ingersoll * bytes. If not, signature verification for DSA signatures 1710e65e5c2dSWyllys Ingersoll * may fail in the case where the bignum value does not use 1711e65e5c2dSWyllys Ingersoll * all of the bits. 1712e65e5c2dSWyllys Ingersoll */ 1713e65e5c2dSWyllys Ingersoll static int 1714*4942e222SAndy Fiddaman fixbnlen(const BIGNUM *bn, unsigned char *buf, int len) 1715*4942e222SAndy Fiddaman { 1716e65e5c2dSWyllys Ingersoll int bytes = len - BN_num_bytes(bn); 17172c9a247fSWyllys Ingersoll 17182c9a247fSWyllys Ingersoll /* prepend with leading 0x00 if necessary */ 1719e65e5c2dSWyllys Ingersoll while (bytes-- > 0) 1720e65e5c2dSWyllys Ingersoll *buf++ = 0; 1721e65e5c2dSWyllys Ingersoll 17222c9a247fSWyllys Ingersoll (void) BN_bn2bin(bn, buf); 17232c9a247fSWyllys Ingersoll /* 17242c9a247fSWyllys Ingersoll * Return the desired length since we prepended it 17252c9a247fSWyllys Ingersoll * with the necessary 0x00 padding. 17262c9a247fSWyllys Ingersoll */ 17272c9a247fSWyllys Ingersoll return (len); 1728e65e5c2dSWyllys Ingersoll } 1729e65e5c2dSWyllys Ingersoll 173099ebb4caSwyllys KMF_RETURN 173199ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, 173299ebb4caSwyllys KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output) 173399ebb4caSwyllys { 173499ebb4caSwyllys KMF_RETURN ret = KMF_OK; 173599ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 173699ebb4caSwyllys KMF_ALGORITHM_INDEX AlgId; 1737300fdee2SAndy Fiddaman EVP_MD_CTX *ctx; 173899ebb4caSwyllys const EVP_MD *md; 173902744e81Swyllys 174099ebb4caSwyllys if (key == NULL || AlgOID == NULL || 174199ebb4caSwyllys tobesigned == NULL || output == NULL || 174299ebb4caSwyllys tobesigned->Data == NULL || 174399ebb4caSwyllys output->Data == NULL) 174499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 174599ebb4caSwyllys 174699ebb4caSwyllys /* Map the OID to an OpenSSL algorithm */ 174730a5e8faSwyllys AlgId = x509_algoid_to_algid(AlgOID); 174899ebb4caSwyllys if (AlgId == KMF_ALGID_NONE) 1749e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM); 175099ebb4caSwyllys 175199ebb4caSwyllys if (key->keyalg == KMF_RSA) { 175299ebb4caSwyllys EVP_PKEY *pkey = (EVP_PKEY *)key->keyp; 175399ebb4caSwyllys uchar_t *p; 175402744e81Swyllys int len; 1755553e44ceSAndrew Stormont switch (AlgId) { 1756553e44ceSAndrew Stormont #ifndef OPENSSL_NO_MD5 1757553e44ceSAndrew Stormont case KMF_ALGID_MD5WithRSA: 175899ebb4caSwyllys md = EVP_md5(); 1759553e44ceSAndrew Stormont break; 1760553e44ceSAndrew Stormont #endif 1761553e44ceSAndrew Stormont #ifndef OPENSSL_NO_SHA 1762553e44ceSAndrew Stormont case KMF_ALGID_SHA1WithRSA: 176399ebb4caSwyllys md = EVP_sha1(); 1764553e44ceSAndrew Stormont break; 1765553e44ceSAndrew Stormont #endif 1766553e44ceSAndrew Stormont #ifndef OPENSSL_NO_SHA256 1767553e44ceSAndrew Stormont case KMF_ALGID_SHA256WithRSA: 1768e65e5c2dSWyllys Ingersoll md = EVP_sha256(); 1769553e44ceSAndrew Stormont break; 1770553e44ceSAndrew Stormont #endif 1771553e44ceSAndrew Stormont #ifndef OPENSSL_NO_SHA512 1772553e44ceSAndrew Stormont case KMF_ALGID_SHA384WithRSA: 1773e65e5c2dSWyllys Ingersoll md = EVP_sha384(); 1774553e44ceSAndrew Stormont break; 1775553e44ceSAndrew Stormont case KMF_ALGID_SHA512WithRSA: 1776e65e5c2dSWyllys Ingersoll md = EVP_sha512(); 1777553e44ceSAndrew Stormont break; 1778553e44ceSAndrew Stormont #endif 1779553e44ceSAndrew Stormont case KMF_ALGID_RSA: 178002744e81Swyllys md = NULL; 1781553e44ceSAndrew Stormont break; 1782553e44ceSAndrew Stormont default: 1783e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM); 1784553e44ceSAndrew Stormont } 178599ebb4caSwyllys 178602744e81Swyllys if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) { 178702744e81Swyllys RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey); 178899ebb4caSwyllys 178902744e81Swyllys p = output->Data; 179002744e81Swyllys if ((len = RSA_private_encrypt(tobesigned->Length, 179102744e81Swyllys tobesigned->Data, p, rsa, 179202744e81Swyllys RSA_PKCS1_PADDING)) <= 0) { 179302744e81Swyllys SET_ERROR(kmfh, ERR_get_error()); 179402744e81Swyllys ret = KMF_ERR_INTERNAL; 179502744e81Swyllys } 179602744e81Swyllys output->Length = len; 179702744e81Swyllys } else { 1798300fdee2SAndy Fiddaman if ((ctx = EVP_MD_CTX_new()) == NULL) 1799300fdee2SAndy Fiddaman return (KMF_ERR_MEMORY); 1800300fdee2SAndy Fiddaman (void) EVP_SignInit_ex(ctx, md, NULL); 1801300fdee2SAndy Fiddaman (void) EVP_SignUpdate(ctx, tobesigned->Data, 180299ebb4caSwyllys (uint32_t)tobesigned->Length); 180399ebb4caSwyllys len = (uint32_t)output->Length; 180499ebb4caSwyllys p = output->Data; 1805300fdee2SAndy Fiddaman if (!EVP_SignFinal(ctx, p, (uint32_t *)&len, pkey)) { 180699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 180702744e81Swyllys len = 0; 180802744e81Swyllys ret = KMF_ERR_INTERNAL; 180999ebb4caSwyllys } 181099ebb4caSwyllys output->Length = len; 1811300fdee2SAndy Fiddaman EVP_MD_CTX_free(ctx); 181202744e81Swyllys } 181399ebb4caSwyllys } else if (key->keyalg == KMF_DSA) { 181499ebb4caSwyllys DSA *dsa = EVP_PKEY_get1_DSA(key->keyp); 181599ebb4caSwyllys 181699ebb4caSwyllys uchar_t hash[EVP_MAX_MD_SIZE]; 181799ebb4caSwyllys uint32_t hashlen; 181899ebb4caSwyllys DSA_SIG *dsasig; 181999ebb4caSwyllys 1820e65e5c2dSWyllys Ingersoll if (AlgId == KMF_ALGID_DSA || 1821e65e5c2dSWyllys Ingersoll AlgId == KMF_ALGID_SHA1WithDSA) 1822e65e5c2dSWyllys Ingersoll md = EVP_sha1(); 1823e65e5c2dSWyllys Ingersoll else if (AlgId == KMF_ALGID_SHA256WithDSA) 1824e65e5c2dSWyllys Ingersoll md = EVP_sha256(); 1825e65e5c2dSWyllys Ingersoll else /* Bad algorithm */ 1826e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM); 1827e65e5c2dSWyllys Ingersoll 182899ebb4caSwyllys /* 182999ebb4caSwyllys * OpenSSL EVP_Sign operation automatically converts to 183099ebb4caSwyllys * ASN.1 output so we do the operations separately so we 183199ebb4caSwyllys * are assured of NOT getting ASN.1 output returned. 183299ebb4caSwyllys * KMF does not want ASN.1 encoded results because 183399ebb4caSwyllys * not all mechanisms return ASN.1 encodings (PKCS#11 183499ebb4caSwyllys * and NSS return raw signature data). 183599ebb4caSwyllys */ 1836300fdee2SAndy Fiddaman if ((ctx = EVP_MD_CTX_new()) == NULL) 1837300fdee2SAndy Fiddaman return (KMF_ERR_MEMORY); 1838300fdee2SAndy Fiddaman (void) EVP_DigestInit_ex(ctx, md, NULL); 1839300fdee2SAndy Fiddaman (void) EVP_DigestUpdate(ctx, tobesigned->Data, 184099ebb4caSwyllys tobesigned->Length); 1841300fdee2SAndy Fiddaman (void) EVP_DigestFinal_ex(ctx, hash, &hashlen); 184299ebb4caSwyllys 1843e65e5c2dSWyllys Ingersoll /* Only sign first 20 bytes for SHA2 */ 1844e65e5c2dSWyllys Ingersoll if (AlgId == KMF_ALGID_SHA256WithDSA) 1845e65e5c2dSWyllys Ingersoll hashlen = 20; 184699ebb4caSwyllys dsasig = DSA_do_sign(hash, hashlen, dsa); 184799ebb4caSwyllys if (dsasig != NULL) { 184899ebb4caSwyllys int i; 1849300fdee2SAndy Fiddaman const BIGNUM *r, *s; 1850300fdee2SAndy Fiddaman 1851300fdee2SAndy Fiddaman DSA_SIG_get0(dsasig, &r, &s); 1852300fdee2SAndy Fiddaman output->Length = i = fixbnlen(r, output->Data, 1853e65e5c2dSWyllys Ingersoll hashlen); 18542c9a247fSWyllys Ingersoll 1855300fdee2SAndy Fiddaman output->Length += fixbnlen(s, &output->Data[i], 1856e65e5c2dSWyllys Ingersoll hashlen); 18572c9a247fSWyllys Ingersoll 185899ebb4caSwyllys DSA_SIG_free(dsasig); 185999ebb4caSwyllys } else { 186099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 186199ebb4caSwyllys } 1862300fdee2SAndy Fiddaman EVP_MD_CTX_free(ctx); 186399ebb4caSwyllys } else { 186499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 186599ebb4caSwyllys } 186699ebb4caSwyllys cleanup: 186799ebb4caSwyllys return (ret); 186899ebb4caSwyllys } 186999ebb4caSwyllys 187099ebb4caSwyllys KMF_RETURN 1871*4942e222SAndy Fiddaman OpenSSL_DeleteKey(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 187299ebb4caSwyllys { 187399ebb4caSwyllys KMF_RETURN rv = KMF_OK; 187430a5e8faSwyllys KMF_KEY_HANDLE *key; 187530a5e8faSwyllys boolean_t destroy = B_TRUE; 187630a5e8faSwyllys 187730a5e8faSwyllys key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 187899ebb4caSwyllys if (key == NULL || key->keyp == NULL) 187999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 188099ebb4caSwyllys 188130a5e8faSwyllys rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr, 188230a5e8faSwyllys (void *)&destroy, NULL); 188330a5e8faSwyllys if (rv != KMF_OK) { 188430a5e8faSwyllys /* "destroy" is optional. Default is TRUE */ 188530a5e8faSwyllys rv = KMF_OK; 188630a5e8faSwyllys } 188730a5e8faSwyllys 188899ebb4caSwyllys if (key->keyclass != KMF_ASYM_PUB && 188999ebb4caSwyllys key->keyclass != KMF_ASYM_PRI && 189099ebb4caSwyllys key->keyclass != KMF_SYMMETRIC) 189199ebb4caSwyllys return (KMF_ERR_BAD_KEY_CLASS); 189299ebb4caSwyllys 189399ebb4caSwyllys if (key->keyclass == KMF_SYMMETRIC) { 189430a5e8faSwyllys kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp); 189599ebb4caSwyllys key->keyp = NULL; 189699ebb4caSwyllys } else { 189799ebb4caSwyllys if (key->keyp != NULL) { 189899ebb4caSwyllys EVP_PKEY_free(key->keyp); 189999ebb4caSwyllys key->keyp = NULL; 190099ebb4caSwyllys } 190199ebb4caSwyllys } 190299ebb4caSwyllys 190399ebb4caSwyllys if (key->keylabel != NULL) { 190499ebb4caSwyllys EVP_PKEY *pkey = NULL; 190599ebb4caSwyllys /* If the file exists, make sure it is a proper key. */ 190699ebb4caSwyllys pkey = openssl_load_key(handle, key->keylabel); 190799ebb4caSwyllys if (pkey == NULL) { 19085b3e1433Swyllys if (key->keylabel != NULL) { 190999ebb4caSwyllys free(key->keylabel); 191099ebb4caSwyllys key->keylabel = NULL; 19115b3e1433Swyllys } 191299ebb4caSwyllys return (KMF_ERR_KEY_NOT_FOUND); 191399ebb4caSwyllys } 191499ebb4caSwyllys EVP_PKEY_free(pkey); 191599ebb4caSwyllys 191699ebb4caSwyllys if (destroy) { 191799ebb4caSwyllys if (unlink(key->keylabel) != 0) { 191899ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 191999ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 192099ebb4caSwyllys rv = KMF_ERR_INTERNAL; 192199ebb4caSwyllys } 192299ebb4caSwyllys } 192399ebb4caSwyllys if (key->keylabel != NULL) { 192499ebb4caSwyllys free(key->keylabel); 192599ebb4caSwyllys key->keylabel = NULL; 192699ebb4caSwyllys } 192799ebb4caSwyllys } 192899ebb4caSwyllys return (rv); 192999ebb4caSwyllys } 193099ebb4caSwyllys 193199ebb4caSwyllys KMF_RETURN 193299ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr) 193399ebb4caSwyllys { 193499ebb4caSwyllys KMF_RETURN ret = KMF_OK; 193599ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 193699ebb4caSwyllys char str[256]; /* OpenSSL needs at least 120 byte buffer */ 193799ebb4caSwyllys 193899ebb4caSwyllys ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str)); 193999ebb4caSwyllys if (strlen(str)) { 194099ebb4caSwyllys *msgstr = (char *)strdup(str); 194199ebb4caSwyllys if ((*msgstr) == NULL) 194299ebb4caSwyllys ret = KMF_ERR_MEMORY; 194399ebb4caSwyllys } else { 194499ebb4caSwyllys *msgstr = NULL; 194599ebb4caSwyllys } 194699ebb4caSwyllys 194799ebb4caSwyllys return (ret); 194899ebb4caSwyllys } 194999ebb4caSwyllys 195099ebb4caSwyllys static int 195199ebb4caSwyllys ext2NID(int kmfext) 195299ebb4caSwyllys { 195399ebb4caSwyllys switch (kmfext) { 195499ebb4caSwyllys case KMF_X509_EXT_KEY_USAGE: 195599ebb4caSwyllys return (NID_key_usage); 195699ebb4caSwyllys case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD: 195799ebb4caSwyllys return (NID_private_key_usage_period); 195899ebb4caSwyllys case KMF_X509_EXT_CERT_POLICIES: 195999ebb4caSwyllys return (NID_certificate_policies); 196099ebb4caSwyllys case KMF_X509_EXT_SUBJ_ALTNAME: 196199ebb4caSwyllys return (NID_subject_alt_name); 196299ebb4caSwyllys case KMF_X509_EXT_ISSUER_ALTNAME: 196399ebb4caSwyllys return (NID_issuer_alt_name); 196499ebb4caSwyllys case KMF_X509_EXT_BASIC_CONSTRAINTS: 196599ebb4caSwyllys return (NID_basic_constraints); 196699ebb4caSwyllys case KMF_X509_EXT_EXT_KEY_USAGE: 196799ebb4caSwyllys return (NID_ext_key_usage); 196899ebb4caSwyllys case KMF_X509_EXT_AUTH_KEY_ID: 196999ebb4caSwyllys return (NID_authority_key_identifier); 197099ebb4caSwyllys case KMF_X509_EXT_CRL_DIST_POINTS: 197199ebb4caSwyllys return (NID_crl_distribution_points); 197299ebb4caSwyllys case KMF_X509_EXT_SUBJ_KEY_ID: 197399ebb4caSwyllys return (NID_subject_key_identifier); 197499ebb4caSwyllys case KMF_X509_EXT_POLICY_MAPPINGS: 197599ebb4caSwyllys return (OBJ_sn2nid("policyMappings")); 197699ebb4caSwyllys case KMF_X509_EXT_NAME_CONSTRAINTS: 197799ebb4caSwyllys return (OBJ_sn2nid("nameConstraints")); 197899ebb4caSwyllys case KMF_X509_EXT_POLICY_CONSTRAINTS: 197999ebb4caSwyllys return (OBJ_sn2nid("policyConstraints")); 198099ebb4caSwyllys case KMF_X509_EXT_INHIBIT_ANY_POLICY: 198199ebb4caSwyllys return (OBJ_sn2nid("inhibitAnyPolicy")); 198299ebb4caSwyllys case KMF_X509_EXT_FRESHEST_CRL: 198399ebb4caSwyllys return (OBJ_sn2nid("freshestCRL")); 198499ebb4caSwyllys default: 198599ebb4caSwyllys return (NID_undef); 198699ebb4caSwyllys } 198799ebb4caSwyllys } 198899ebb4caSwyllys 198999ebb4caSwyllys KMF_RETURN 199099ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert, 199199ebb4caSwyllys KMF_PRINTABLE_ITEM flag, char *resultStr) 199299ebb4caSwyllys { 199399ebb4caSwyllys KMF_RETURN ret = KMF_OK; 199499ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 199599ebb4caSwyllys X509 *xcert = NULL; 199699ebb4caSwyllys unsigned char *outbuf = NULL; 199799ebb4caSwyllys unsigned char *outbuf_p; 199899ebb4caSwyllys int j; 199999ebb4caSwyllys int ext_index, nid, len; 200099ebb4caSwyllys BIO *mem = NULL; 200170f9559bSTheo Schlossnagle STACK_OF(OPENSSL_STRING) *emlst = NULL; 200299ebb4caSwyllys X509_EXTENSION *ex; 200399ebb4caSwyllys 200499ebb4caSwyllys if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) { 200599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 200699ebb4caSwyllys } 200799ebb4caSwyllys 200899ebb4caSwyllys /* copy cert data to outbuf */ 200999ebb4caSwyllys outbuf = malloc(pcert->Length); 201099ebb4caSwyllys if (outbuf == NULL) { 201199ebb4caSwyllys return (KMF_ERR_MEMORY); 201299ebb4caSwyllys } 201399ebb4caSwyllys (void) memcpy(outbuf, pcert->Data, pcert->Length); 201499ebb4caSwyllys 201599ebb4caSwyllys outbuf_p = outbuf; /* use a temp pointer; required by openssl */ 201699ebb4caSwyllys xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length); 201799ebb4caSwyllys if (xcert == NULL) { 201899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 201999ebb4caSwyllys ret = KMF_ERR_ENCODING; 202099ebb4caSwyllys goto out; 202199ebb4caSwyllys } 202299ebb4caSwyllys 202399ebb4caSwyllys mem = BIO_new(BIO_s_mem()); 202499ebb4caSwyllys if (mem == NULL) { 202599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 202699ebb4caSwyllys ret = KMF_ERR_MEMORY; 202799ebb4caSwyllys goto out; 202899ebb4caSwyllys } 202999ebb4caSwyllys 203099ebb4caSwyllys switch (flag) { 203199ebb4caSwyllys case KMF_CERT_ISSUER: 203299ebb4caSwyllys (void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0, 203399ebb4caSwyllys XN_FLAG_SEP_CPLUS_SPC); 203499ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 203599ebb4caSwyllys break; 203699ebb4caSwyllys 203799ebb4caSwyllys case KMF_CERT_SUBJECT: 203899ebb4caSwyllys (void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0, 203999ebb4caSwyllys XN_FLAG_SEP_CPLUS_SPC); 204099ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 204199ebb4caSwyllys break; 204299ebb4caSwyllys 204399ebb4caSwyllys case KMF_CERT_VERSION: 2044300fdee2SAndy Fiddaman (void) snprintf(resultStr, KMF_CERT_PRINTABLE_LEN, 2045300fdee2SAndy Fiddaman "%ld", X509_get_version(xcert)); 204699ebb4caSwyllys len = strlen(resultStr); 204799ebb4caSwyllys break; 204899ebb4caSwyllys 204999ebb4caSwyllys case KMF_CERT_SERIALNUM: 205099ebb4caSwyllys if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) { 205199ebb4caSwyllys (void) strcpy(resultStr, "0x"); 205299ebb4caSwyllys len = BIO_gets(mem, &resultStr[2], 205399ebb4caSwyllys KMF_CERT_PRINTABLE_LEN - 2); 205499ebb4caSwyllys } 205599ebb4caSwyllys break; 205699ebb4caSwyllys 205799ebb4caSwyllys case KMF_CERT_NOTBEFORE: 2058300fdee2SAndy Fiddaman (void) ASN1_TIME_print(mem, X509_getm_notBefore(xcert)); 205999ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 206099ebb4caSwyllys break; 206199ebb4caSwyllys 206299ebb4caSwyllys case KMF_CERT_NOTAFTER: 2063300fdee2SAndy Fiddaman (void) ASN1_TIME_print(mem, X509_getm_notAfter(xcert)); 206499ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 206599ebb4caSwyllys break; 206699ebb4caSwyllys 206799ebb4caSwyllys case KMF_CERT_PUBKEY_DATA: 206899ebb4caSwyllys { 2069300fdee2SAndy Fiddaman RSA *rsa; 2070300fdee2SAndy Fiddaman DSA *dsa; 2071300fdee2SAndy Fiddaman 207299ebb4caSwyllys EVP_PKEY *pkey = X509_get_pubkey(xcert); 207399ebb4caSwyllys if (pkey == NULL) { 207499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 207599ebb4caSwyllys ret = KMF_ERR_ENCODING; 207699ebb4caSwyllys goto out; 207799ebb4caSwyllys } 207899ebb4caSwyllys 2079300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) { 208099ebb4caSwyllys (void) BIO_printf(mem, 208199ebb4caSwyllys "RSA Public Key: (%d bit)\n", 2082300fdee2SAndy Fiddaman RSA_bits(rsa)); 2083300fdee2SAndy Fiddaman (void) RSA_print(mem, rsa, 0); 2084300fdee2SAndy Fiddaman 2085300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) { 208699ebb4caSwyllys (void) BIO_printf(mem, 208799ebb4caSwyllys "%12sDSA Public Key:\n", ""); 2088300fdee2SAndy Fiddaman (void) DSA_print(mem, dsa, 0); 208999ebb4caSwyllys } else { 209099ebb4caSwyllys (void) BIO_printf(mem, 209199ebb4caSwyllys "%12sUnknown Public Key:\n", ""); 209299ebb4caSwyllys } 209399ebb4caSwyllys (void) BIO_printf(mem, "\n"); 209499ebb4caSwyllys EVP_PKEY_free(pkey); 209599ebb4caSwyllys } 209699ebb4caSwyllys len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 209799ebb4caSwyllys break; 209899ebb4caSwyllys case KMF_CERT_SIGNATURE_ALG: 209999ebb4caSwyllys case KMF_CERT_PUBKEY_ALG: 2100300fdee2SAndy Fiddaman { 2101553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 2102300fdee2SAndy Fiddaman ASN1_OBJECT *alg = NULL; 2103300fdee2SAndy Fiddaman #else 2104300fdee2SAndy Fiddaman const ASN1_OBJECT *alg = NULL; 2105300fdee2SAndy Fiddaman #endif 2106300fdee2SAndy Fiddaman 210799ebb4caSwyllys if (flag == KMF_CERT_SIGNATURE_ALG) { 2108553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 2109300fdee2SAndy Fiddaman alg = xcert->sig_alg->algorithm; 2110300fdee2SAndy Fiddaman #else 2111300fdee2SAndy Fiddaman const X509_ALGOR *sig_alg = NULL; 2112300fdee2SAndy Fiddaman 2113300fdee2SAndy Fiddaman X509_get0_signature(NULL, &sig_alg, xcert); 2114300fdee2SAndy Fiddaman if (sig_alg != NULL) 2115300fdee2SAndy Fiddaman X509_ALGOR_get0(&alg, NULL, NULL, 2116300fdee2SAndy Fiddaman sig_alg); 2117300fdee2SAndy Fiddaman #endif 211899ebb4caSwyllys } else { 2119553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 2120300fdee2SAndy Fiddaman alg = xcert->cert_info->key->algor->algorithm; 2121300fdee2SAndy Fiddaman #else 2122300fdee2SAndy Fiddaman X509_PUBKEY *key = X509_get_X509_PUBKEY(xcert); 2123300fdee2SAndy Fiddaman 2124300fdee2SAndy Fiddaman if (key != NULL) 2125300fdee2SAndy Fiddaman (void) X509_PUBKEY_get0_param( 2126300fdee2SAndy Fiddaman (ASN1_OBJECT **)&alg, NULL, 0, 2127300fdee2SAndy Fiddaman NULL, key); 2128300fdee2SAndy Fiddaman #endif 212999ebb4caSwyllys } 213099ebb4caSwyllys 2131300fdee2SAndy Fiddaman if (alg == NULL) 2132300fdee2SAndy Fiddaman len = -1; 2133300fdee2SAndy Fiddaman else if ((len = i2a_ASN1_OBJECT(mem, alg)) > 0) 213499ebb4caSwyllys len = BIO_read(mem, resultStr, 213599ebb4caSwyllys KMF_CERT_PRINTABLE_LEN); 213699ebb4caSwyllys } 213799ebb4caSwyllys break; 213899ebb4caSwyllys 213999ebb4caSwyllys case KMF_CERT_EMAIL: 214099ebb4caSwyllys emlst = X509_get1_email(xcert); 214170f9559bSTheo Schlossnagle for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) 214270f9559bSTheo Schlossnagle (void) BIO_printf(mem, "%s\n", 214370f9559bSTheo Schlossnagle sk_OPENSSL_STRING_value(emlst, j)); 214499ebb4caSwyllys 214599ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 214699ebb4caSwyllys X509_email_free(emlst); 214799ebb4caSwyllys break; 214899ebb4caSwyllys case KMF_X509_EXT_ISSUER_ALTNAME: 214999ebb4caSwyllys case KMF_X509_EXT_SUBJ_ALTNAME: 215099ebb4caSwyllys case KMF_X509_EXT_KEY_USAGE: 215199ebb4caSwyllys case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD: 215299ebb4caSwyllys case KMF_X509_EXT_CERT_POLICIES: 215399ebb4caSwyllys case KMF_X509_EXT_BASIC_CONSTRAINTS: 215499ebb4caSwyllys case KMF_X509_EXT_NAME_CONSTRAINTS: 215599ebb4caSwyllys case KMF_X509_EXT_POLICY_CONSTRAINTS: 215699ebb4caSwyllys case KMF_X509_EXT_EXT_KEY_USAGE: 215799ebb4caSwyllys case KMF_X509_EXT_INHIBIT_ANY_POLICY: 215899ebb4caSwyllys case KMF_X509_EXT_AUTH_KEY_ID: 215999ebb4caSwyllys case KMF_X509_EXT_SUBJ_KEY_ID: 216099ebb4caSwyllys case KMF_X509_EXT_POLICY_MAPPINGS: 216199ebb4caSwyllys case KMF_X509_EXT_CRL_DIST_POINTS: 216299ebb4caSwyllys case KMF_X509_EXT_FRESHEST_CRL: 216399ebb4caSwyllys nid = ext2NID(flag); 216499ebb4caSwyllys if (nid == NID_undef) { 216599ebb4caSwyllys ret = KMF_ERR_EXTENSION_NOT_FOUND; 216699ebb4caSwyllys goto out; 216799ebb4caSwyllys } 216899ebb4caSwyllys 2169300fdee2SAndy Fiddaman ext_index = X509_get_ext_by_NID(xcert, nid, -1); 217099ebb4caSwyllys if (ext_index == -1) { 217199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 217299ebb4caSwyllys 217399ebb4caSwyllys ret = KMF_ERR_EXTENSION_NOT_FOUND; 217499ebb4caSwyllys goto out; 217599ebb4caSwyllys } 2176300fdee2SAndy Fiddaman ex = X509_get_ext(xcert, ext_index); 217799ebb4caSwyllys 217899ebb4caSwyllys (void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex)); 217999ebb4caSwyllys 218099ebb4caSwyllys if (BIO_printf(mem, ": %s\n", 218130a5e8faSwyllys X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) { 218299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 218399ebb4caSwyllys ret = KMF_ERR_ENCODING; 218499ebb4caSwyllys goto out; 218599ebb4caSwyllys } 218699ebb4caSwyllys if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) { 218799ebb4caSwyllys (void) BIO_printf(mem, "%*s", 4, ""); 2188300fdee2SAndy Fiddaman (void) ASN1_STRING_print(mem, 2189300fdee2SAndy Fiddaman X509_EXTENSION_get_data(ex)); 219099ebb4caSwyllys } 219199ebb4caSwyllys if (BIO_write(mem, "\n", 1) <= 0) { 219299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 219399ebb4caSwyllys ret = KMF_ERR_ENCODING; 219499ebb4caSwyllys goto out; 219599ebb4caSwyllys } 219699ebb4caSwyllys len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 219799ebb4caSwyllys } 219899ebb4caSwyllys if (len <= 0) { 219999ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 220099ebb4caSwyllys ret = KMF_ERR_ENCODING; 220199ebb4caSwyllys } 220299ebb4caSwyllys 220399ebb4caSwyllys out: 220499ebb4caSwyllys if (outbuf != NULL) { 220599ebb4caSwyllys free(outbuf); 220699ebb4caSwyllys } 220799ebb4caSwyllys 220899ebb4caSwyllys if (xcert != NULL) { 220999ebb4caSwyllys X509_free(xcert); 221099ebb4caSwyllys } 221199ebb4caSwyllys 221299ebb4caSwyllys if (mem != NULL) { 221399ebb4caSwyllys (void) BIO_free(mem); 221499ebb4caSwyllys } 221599ebb4caSwyllys 221699ebb4caSwyllys return (ret); 221799ebb4caSwyllys } 221830a5e8faSwyllys 221999ebb4caSwyllys KMF_RETURN 222030a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr, 222130a5e8faSwyllys KMF_ATTRIBUTE *attrlist) 222299ebb4caSwyllys { 222399ebb4caSwyllys KMF_RETURN rv = KMF_OK; 222430a5e8faSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL; 222530a5e8faSwyllys KMF_KEY_CLASS keyclass = KMF_ASYM_PRI; 222630a5e8faSwyllys KMF_KEY_HANDLE *key = NULL; 222730a5e8faSwyllys uint32_t numkeys = 1; /* 1 key only */ 222830a5e8faSwyllys char *dirpath = NULL; 222930a5e8faSwyllys char *keyfile = NULL; 223030a5e8faSwyllys KMF_ATTRIBUTE new_attrlist[16]; 223130a5e8faSwyllys int i = 0; 223299ebb4caSwyllys 223399ebb4caSwyllys /* 223499ebb4caSwyllys * This is really just a FindKey operation, reuse the 223599ebb4caSwyllys * FindKey function. 223699ebb4caSwyllys */ 223730a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 223830a5e8faSwyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 223930a5e8faSwyllys i++; 224099ebb4caSwyllys 224130a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 224230a5e8faSwyllys KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t)); 224330a5e8faSwyllys i++; 224499ebb4caSwyllys 224530a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 224630a5e8faSwyllys KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass)); 224730a5e8faSwyllys i++; 224830a5e8faSwyllys 224930a5e8faSwyllys key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 225030a5e8faSwyllys if (key == NULL) { 225130a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 225230a5e8faSwyllys } else { 225330a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 225430a5e8faSwyllys KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE)); 225530a5e8faSwyllys i++; 225630a5e8faSwyllys } 225730a5e8faSwyllys 225830a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 225930a5e8faSwyllys if (dirpath != NULL) { 226030a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 226130a5e8faSwyllys KMF_DIRPATH_ATTR, dirpath, strlen(dirpath)); 226230a5e8faSwyllys i++; 226330a5e8faSwyllys } 226430a5e8faSwyllys 226530a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 226630a5e8faSwyllys if (keyfile == NULL) 226730a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 226830a5e8faSwyllys else { 226930a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 227030a5e8faSwyllys KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile)); 227130a5e8faSwyllys i++; 227230a5e8faSwyllys } 227330a5e8faSwyllys 227430a5e8faSwyllys rv = OpenSSL_FindKey(handle, i, new_attrlist); 227599ebb4caSwyllys return (rv); 227699ebb4caSwyllys } 227799ebb4caSwyllys 227899ebb4caSwyllys KMF_RETURN 227999ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, 2280*4942e222SAndy Fiddaman KMF_OID *AlgOID, KMF_DATA *ciphertext, KMF_DATA *output) 228199ebb4caSwyllys { 228299ebb4caSwyllys KMF_RETURN ret = KMF_OK; 228399ebb4caSwyllys RSA *rsa = NULL; 228499ebb4caSwyllys unsigned int in_len = 0, out_len = 0; 228599ebb4caSwyllys unsigned int total_decrypted = 0, modulus_len = 0; 228699ebb4caSwyllys uint8_t *in_data, *out_data; 228799ebb4caSwyllys int i, blocks; 228899ebb4caSwyllys 228999ebb4caSwyllys if (key == NULL || AlgOID == NULL || 229099ebb4caSwyllys ciphertext == NULL || output == NULL || 229199ebb4caSwyllys ciphertext->Data == NULL || 229299ebb4caSwyllys output->Data == NULL) 229399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 229499ebb4caSwyllys 229599ebb4caSwyllys if (key->keyalg == KMF_RSA) { 229699ebb4caSwyllys rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp); 229799ebb4caSwyllys modulus_len = RSA_size(rsa); 229899ebb4caSwyllys } else { 229999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 230099ebb4caSwyllys } 230199ebb4caSwyllys 230299ebb4caSwyllys blocks = ciphertext->Length/modulus_len; 230399ebb4caSwyllys out_data = output->Data; 230499ebb4caSwyllys in_data = ciphertext->Data; 230599ebb4caSwyllys out_len = modulus_len - 11; 230699ebb4caSwyllys in_len = modulus_len; 230799ebb4caSwyllys 230899ebb4caSwyllys for (i = 0; i < blocks; i++) { 230999ebb4caSwyllys out_len = RSA_private_decrypt(in_len, 231099ebb4caSwyllys in_data, out_data, rsa, RSA_PKCS1_PADDING); 231199ebb4caSwyllys 231299ebb4caSwyllys if (out_len == 0) { 231399ebb4caSwyllys ret = KMF_ERR_INTERNAL; 231499ebb4caSwyllys goto cleanup; 231599ebb4caSwyllys } 231699ebb4caSwyllys 231799ebb4caSwyllys out_data += out_len; 231899ebb4caSwyllys total_decrypted += out_len; 231999ebb4caSwyllys in_data += in_len; 232099ebb4caSwyllys } 232199ebb4caSwyllys 232299ebb4caSwyllys output->Length = total_decrypted; 232399ebb4caSwyllys 232499ebb4caSwyllys cleanup: 232599ebb4caSwyllys RSA_free(rsa); 232699ebb4caSwyllys if (ret != KMF_OK) 232799ebb4caSwyllys output->Length = 0; 232899ebb4caSwyllys 232999ebb4caSwyllys return (ret); 233099ebb4caSwyllys 233199ebb4caSwyllys } 233299ebb4caSwyllys 233399ebb4caSwyllys /* 233499ebb4caSwyllys * This function will create a certid from issuer_cert and user_cert. 233599ebb4caSwyllys * The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate 233699ebb4caSwyllys * certid memory after use. 233799ebb4caSwyllys */ 233899ebb4caSwyllys static KMF_RETURN 233999ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert, 234099ebb4caSwyllys const KMF_DATA *user_cert, OCSP_CERTID **certid) 234199ebb4caSwyllys { 234299ebb4caSwyllys KMF_RETURN ret = KMF_OK; 234399ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 234499ebb4caSwyllys X509 *issuer = NULL; 234599ebb4caSwyllys X509 *cert = NULL; 234699ebb4caSwyllys unsigned char *ptmp; 234799ebb4caSwyllys 234899ebb4caSwyllys if (issuer_cert == NULL || user_cert == NULL) { 234999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 235099ebb4caSwyllys } 235199ebb4caSwyllys 235299ebb4caSwyllys /* convert the DER-encoded issuer cert to an internal X509 */ 235399ebb4caSwyllys ptmp = issuer_cert->Data; 235499ebb4caSwyllys issuer = d2i_X509(NULL, (const uchar_t **)&ptmp, 235599ebb4caSwyllys issuer_cert->Length); 235699ebb4caSwyllys if (issuer == NULL) { 235799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 235899ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_ISSUER; 235999ebb4caSwyllys goto end; 236099ebb4caSwyllys } 236199ebb4caSwyllys 236299ebb4caSwyllys /* convert the DER-encoded user cert to an internal X509 */ 236399ebb4caSwyllys ptmp = user_cert->Data; 236499ebb4caSwyllys cert = d2i_X509(NULL, (const uchar_t **)&ptmp, 236599ebb4caSwyllys user_cert->Length); 236699ebb4caSwyllys if (cert == NULL) { 236799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 236899ebb4caSwyllys 236999ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_CERT; 237099ebb4caSwyllys goto end; 237199ebb4caSwyllys } 237299ebb4caSwyllys 237399ebb4caSwyllys /* create a CERTID */ 237499ebb4caSwyllys *certid = OCSP_cert_to_id(NULL, cert, issuer); 237599ebb4caSwyllys if (*certid == NULL) { 237699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 237799ebb4caSwyllys ret = KMF_ERR_OCSP_CERTID; 237899ebb4caSwyllys goto end; 237999ebb4caSwyllys } 238099ebb4caSwyllys 238199ebb4caSwyllys end: 238299ebb4caSwyllys if (issuer != NULL) { 238399ebb4caSwyllys X509_free(issuer); 238499ebb4caSwyllys } 238599ebb4caSwyllys 238699ebb4caSwyllys if (cert != NULL) { 238799ebb4caSwyllys X509_free(cert); 238899ebb4caSwyllys } 238999ebb4caSwyllys 239099ebb4caSwyllys return (ret); 239199ebb4caSwyllys } 239299ebb4caSwyllys 239399ebb4caSwyllys KMF_RETURN 239430a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle, 239530a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 239699ebb4caSwyllys { 239799ebb4caSwyllys KMF_RETURN ret = KMF_OK; 239899ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 239999ebb4caSwyllys OCSP_CERTID *id = NULL; 240099ebb4caSwyllys OCSP_REQUEST *req = NULL; 240199ebb4caSwyllys BIO *derbio = NULL; 240230a5e8faSwyllys char *reqfile; 240330a5e8faSwyllys KMF_DATA *issuer_cert; 240430a5e8faSwyllys KMF_DATA *user_cert; 240599ebb4caSwyllys 240630a5e8faSwyllys user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR, 240730a5e8faSwyllys attrlist, numattr); 240830a5e8faSwyllys if (user_cert == NULL) 240999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 241099ebb4caSwyllys 241130a5e8faSwyllys issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR, 241230a5e8faSwyllys attrlist, numattr); 241330a5e8faSwyllys if (issuer_cert == NULL) 241430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 241530a5e8faSwyllys 241630a5e8faSwyllys reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR, 241730a5e8faSwyllys attrlist, numattr); 241830a5e8faSwyllys if (reqfile == NULL) 241930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 242030a5e8faSwyllys 242130a5e8faSwyllys ret = create_certid(handle, issuer_cert, user_cert, &id); 242299ebb4caSwyllys if (ret != KMF_OK) { 242399ebb4caSwyllys return (ret); 242499ebb4caSwyllys } 242599ebb4caSwyllys 242699ebb4caSwyllys /* Create an OCSP request */ 242799ebb4caSwyllys req = OCSP_REQUEST_new(); 242899ebb4caSwyllys if (req == NULL) { 242999ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 243099ebb4caSwyllys ret = KMF_ERR_OCSP_CREATE_REQUEST; 243199ebb4caSwyllys goto end; 243299ebb4caSwyllys } 243399ebb4caSwyllys 243499ebb4caSwyllys if (!OCSP_request_add0_id(req, id)) { 243599ebb4caSwyllys ret = KMF_ERR_OCSP_CREATE_REQUEST; 243699ebb4caSwyllys goto end; 243799ebb4caSwyllys } 243899ebb4caSwyllys 243999ebb4caSwyllys /* Write the request to the output file with DER encoding */ 244099ebb4caSwyllys derbio = BIO_new_file(reqfile, "wb"); 244199ebb4caSwyllys if (!derbio) { 244299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 244399ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 244499ebb4caSwyllys goto end; 244599ebb4caSwyllys } 244699ebb4caSwyllys if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) { 244799ebb4caSwyllys ret = KMF_ERR_ENCODING; 244899ebb4caSwyllys } 244999ebb4caSwyllys 245099ebb4caSwyllys end: 245199ebb4caSwyllys /* 2452e65e5c2dSWyllys Ingersoll * We don't need to free "id" explicitely, because OCSP_REQUEST_free() 2453a2d4930dSDan OpenSolaris Anderson * will also deallocate certid's space. 245499ebb4caSwyllys */ 245599ebb4caSwyllys if (req != NULL) { 245699ebb4caSwyllys OCSP_REQUEST_free(req); 245799ebb4caSwyllys } 245899ebb4caSwyllys 245999ebb4caSwyllys if (derbio != NULL) { 246099ebb4caSwyllys (void) BIO_free(derbio); 246199ebb4caSwyllys } 246299ebb4caSwyllys 246399ebb4caSwyllys return (ret); 246499ebb4caSwyllys } 246599ebb4caSwyllys 246699ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */ 2467300fdee2SAndy Fiddaman static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_BASICRESP *bs) 246899ebb4caSwyllys { 246999ebb4caSwyllys int i; 247099ebb4caSwyllys unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash; 2471300fdee2SAndy Fiddaman const ASN1_OCTET_STRING *pid; 247299ebb4caSwyllys 2473553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 2474300fdee2SAndy Fiddaman OCSP_RESPID *id = bs->tbsResponseData->responderId; 2475300fdee2SAndy Fiddaman 247699ebb4caSwyllys if (id->type == V_OCSP_RESPID_NAME) 247799ebb4caSwyllys return (X509_find_by_subject(certs, id->value.byName)); 247899ebb4caSwyllys 2479300fdee2SAndy Fiddaman pid = id->value.byKey; 2480300fdee2SAndy Fiddaman #else 2481300fdee2SAndy Fiddaman const X509_NAME *pname; 2482300fdee2SAndy Fiddaman 2483300fdee2SAndy Fiddaman if (OCSP_resp_get0_id(bs, &pid, &pname) == 0) 2484300fdee2SAndy Fiddaman return (NULL); 2485300fdee2SAndy Fiddaman 2486300fdee2SAndy Fiddaman if (pname != NULL) 2487300fdee2SAndy Fiddaman return (X509_find_by_subject(certs, (X509_NAME *)pname)); 2488300fdee2SAndy Fiddaman #endif 2489300fdee2SAndy Fiddaman 249099ebb4caSwyllys /* Lookup by key hash */ 249199ebb4caSwyllys 249299ebb4caSwyllys /* If key hash isn't SHA1 length then forget it */ 2493300fdee2SAndy Fiddaman if (pid->length != SHA_DIGEST_LENGTH) 249499ebb4caSwyllys return (NULL); 249599ebb4caSwyllys 2496300fdee2SAndy Fiddaman keyhash = pid->data; 249799ebb4caSwyllys /* Calculate hash of each key and compare */ 249899ebb4caSwyllys for (i = 0; i < sk_X509_num(certs); i++) { 249999ebb4caSwyllys X509 *x = sk_X509_value(certs, i); 25005b3e1433Swyllys /* Use pubkey_digest to get the key ID value */ 250199ebb4caSwyllys (void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL); 250299ebb4caSwyllys if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH)) 250399ebb4caSwyllys return (x); 250499ebb4caSwyllys } 250599ebb4caSwyllys return (NULL); 250699ebb4caSwyllys } 250799ebb4caSwyllys 250899ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */ 250999ebb4caSwyllys static int 251099ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs, 251199ebb4caSwyllys X509_STORE *st, unsigned long flags) 251299ebb4caSwyllys { 251399ebb4caSwyllys X509 *signer; 2514300fdee2SAndy Fiddaman if ((signer = ocsp_find_signer_sk(certs, bs))) { 251599ebb4caSwyllys *psigner = signer; 251699ebb4caSwyllys return (2); 251799ebb4caSwyllys } 2518300fdee2SAndy Fiddaman 251999ebb4caSwyllys if (!(flags & OCSP_NOINTERN) && 2520300fdee2SAndy Fiddaman (signer = ocsp_find_signer_sk( 2521300fdee2SAndy Fiddaman (STACK_OF(X509) *)OCSP_resp_get0_certs(bs), bs))) { 252299ebb4caSwyllys *psigner = signer; 252399ebb4caSwyllys return (1); 252499ebb4caSwyllys } 252599ebb4caSwyllys /* Maybe lookup from store if by subject name */ 252699ebb4caSwyllys 252799ebb4caSwyllys *psigner = NULL; 252899ebb4caSwyllys return (0); 252999ebb4caSwyllys } 253099ebb4caSwyllys 253199ebb4caSwyllys /* 253299ebb4caSwyllys * This function will verify the signature of a basic response, using 253399ebb4caSwyllys * the public key from the OCSP responder certificate. 253499ebb4caSwyllys */ 253599ebb4caSwyllys static KMF_RETURN 253699ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs, 253799ebb4caSwyllys KMF_DATA *signer_cert, KMF_DATA *issuer_cert) 253899ebb4caSwyllys { 253999ebb4caSwyllys KMF_RETURN ret = KMF_OK; 254099ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 254199ebb4caSwyllys STACK_OF(X509) *cert_stack = NULL; 254299ebb4caSwyllys X509 *signer = NULL; 254399ebb4caSwyllys X509 *issuer = NULL; 2544553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 254599ebb4caSwyllys EVP_PKEY *skey = NULL; 2546300fdee2SAndy Fiddaman #else 2547300fdee2SAndy Fiddaman STACK_OF(X509) *cert_stack2 = NULL; 2548300fdee2SAndy Fiddaman #endif 254999ebb4caSwyllys unsigned char *ptmp; 255099ebb4caSwyllys 255199ebb4caSwyllys if (bs == NULL || issuer_cert == NULL) 255299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 255399ebb4caSwyllys 255499ebb4caSwyllys /* 255599ebb4caSwyllys * Find the certificate that signed the basic response. 255699ebb4caSwyllys * 255799ebb4caSwyllys * If signer_cert is not NULL, we will use that as the signer cert. 255899ebb4caSwyllys * Otherwise, we will check if the issuer cert is actually the signer. 255999ebb4caSwyllys * If we still do not find a signer, we will look for it from the 256099ebb4caSwyllys * certificate list came with the response file. 256199ebb4caSwyllys */ 256299ebb4caSwyllys if (signer_cert != NULL) { 256399ebb4caSwyllys ptmp = signer_cert->Data; 256499ebb4caSwyllys signer = d2i_X509(NULL, (const uchar_t **)&ptmp, 256599ebb4caSwyllys signer_cert->Length); 256699ebb4caSwyllys if (signer == NULL) { 256799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 256899ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_SIGNER; 256999ebb4caSwyllys goto end; 257099ebb4caSwyllys } 257199ebb4caSwyllys } else { 257299ebb4caSwyllys /* 257399ebb4caSwyllys * Convert the issuer cert into X509 and push it into a 257499ebb4caSwyllys * stack to be used by ocsp_find_signer(). 257599ebb4caSwyllys */ 257699ebb4caSwyllys ptmp = issuer_cert->Data; 257799ebb4caSwyllys issuer = d2i_X509(NULL, (const uchar_t **)&ptmp, 257899ebb4caSwyllys issuer_cert->Length); 257999ebb4caSwyllys if (issuer == NULL) { 258099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 258199ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_ISSUER; 258299ebb4caSwyllys goto end; 258399ebb4caSwyllys } 258499ebb4caSwyllys 258599ebb4caSwyllys if ((cert_stack = sk_X509_new_null()) == NULL) { 258699ebb4caSwyllys ret = KMF_ERR_INTERNAL; 258799ebb4caSwyllys goto end; 258899ebb4caSwyllys } 258999ebb4caSwyllys 2590f810c7e5SToomas Soome if (sk_X509_push(cert_stack, issuer) == 0) { 259199ebb4caSwyllys ret = KMF_ERR_INTERNAL; 259299ebb4caSwyllys goto end; 259399ebb4caSwyllys } 259499ebb4caSwyllys 259599ebb4caSwyllys ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0); 259699ebb4caSwyllys if (!ret) { 259799ebb4caSwyllys /* can not find the signer */ 259899ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_SIGNER; 259999ebb4caSwyllys goto end; 260099ebb4caSwyllys } 260199ebb4caSwyllys } 260299ebb4caSwyllys 260399ebb4caSwyllys /* Verify the signature of the response */ 2604553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 260599ebb4caSwyllys skey = X509_get_pubkey(signer); 260699ebb4caSwyllys if (skey == NULL) { 260799ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_SIGNER; 260899ebb4caSwyllys goto end; 260999ebb4caSwyllys } 261099ebb4caSwyllys 261199ebb4caSwyllys ret = OCSP_BASICRESP_verify(bs, skey, 0); 2612300fdee2SAndy Fiddaman #else 2613300fdee2SAndy Fiddaman /* 2614300fdee2SAndy Fiddaman * Technique based on 2615300fdee2SAndy Fiddaman * https://mta.openssl.org/pipermail/openssl-users/ 2616300fdee2SAndy Fiddaman * 2017-October/006814.html 2617300fdee2SAndy Fiddaman */ 2618300fdee2SAndy Fiddaman if ((cert_stack2 = sk_X509_new_null()) == NULL) { 2619300fdee2SAndy Fiddaman ret = KMF_ERR_INTERNAL; 2620300fdee2SAndy Fiddaman goto end; 2621300fdee2SAndy Fiddaman } 2622300fdee2SAndy Fiddaman 2623*4942e222SAndy Fiddaman if (sk_X509_push(cert_stack2, signer) == 0) { 2624300fdee2SAndy Fiddaman ret = KMF_ERR_INTERNAL; 2625300fdee2SAndy Fiddaman goto end; 2626300fdee2SAndy Fiddaman } 2627300fdee2SAndy Fiddaman 2628300fdee2SAndy Fiddaman ret = OCSP_basic_verify(bs, cert_stack2, NULL, OCSP_NOVERIFY); 2629300fdee2SAndy Fiddaman #endif 2630300fdee2SAndy Fiddaman 263199ebb4caSwyllys if (ret == 0) { 263299ebb4caSwyllys ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE; 263399ebb4caSwyllys goto end; 263499ebb4caSwyllys } 263599ebb4caSwyllys 263699ebb4caSwyllys end: 263799ebb4caSwyllys if (issuer != NULL) { 263899ebb4caSwyllys X509_free(issuer); 263999ebb4caSwyllys } 264099ebb4caSwyllys 264199ebb4caSwyllys if (signer != NULL) { 264299ebb4caSwyllys X509_free(signer); 264399ebb4caSwyllys } 264499ebb4caSwyllys 2645553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 264699ebb4caSwyllys if (skey != NULL) { 264799ebb4caSwyllys EVP_PKEY_free(skey); 264899ebb4caSwyllys } 2649300fdee2SAndy Fiddaman #else 2650300fdee2SAndy Fiddaman if (cert_stack2 != NULL) { 2651300fdee2SAndy Fiddaman sk_X509_free(cert_stack2); 2652300fdee2SAndy Fiddaman } 2653300fdee2SAndy Fiddaman #endif 265499ebb4caSwyllys 265599ebb4caSwyllys if (cert_stack != NULL) { 265699ebb4caSwyllys sk_X509_free(cert_stack); 265799ebb4caSwyllys } 265899ebb4caSwyllys 265999ebb4caSwyllys return (ret); 266099ebb4caSwyllys } 266199ebb4caSwyllys 266299ebb4caSwyllys KMF_RETURN 2663*4942e222SAndy Fiddaman OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle, int numattr, 2664*4942e222SAndy Fiddaman KMF_ATTRIBUTE *attrlist) 266599ebb4caSwyllys { 266699ebb4caSwyllys KMF_RETURN ret = KMF_OK; 266799ebb4caSwyllys BIO *derbio = NULL; 266899ebb4caSwyllys OCSP_RESPONSE *resp = NULL; 266999ebb4caSwyllys OCSP_BASICRESP *bs = NULL; 267099ebb4caSwyllys OCSP_CERTID *id = NULL; 267199ebb4caSwyllys OCSP_SINGLERESP *single = NULL; 267299ebb4caSwyllys ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; 267399ebb4caSwyllys int index, status, reason; 267430a5e8faSwyllys KMF_DATA *issuer_cert; 267530a5e8faSwyllys KMF_DATA *user_cert; 267630a5e8faSwyllys KMF_DATA *signer_cert; 267730a5e8faSwyllys KMF_DATA *response; 267830a5e8faSwyllys int *response_reason, *response_status, *cert_status; 267930a5e8faSwyllys boolean_t ignore_response_sign = B_FALSE; /* default is FALSE */ 268030a5e8faSwyllys uint32_t response_lifetime; 268199ebb4caSwyllys 268230a5e8faSwyllys issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR, 268330a5e8faSwyllys attrlist, numattr); 268430a5e8faSwyllys if (issuer_cert == NULL) 268599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 268699ebb4caSwyllys 268730a5e8faSwyllys user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR, 268830a5e8faSwyllys attrlist, numattr); 268930a5e8faSwyllys if (user_cert == NULL) 269099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 269130a5e8faSwyllys 269230a5e8faSwyllys response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR, 269330a5e8faSwyllys attrlist, numattr); 269430a5e8faSwyllys if (response == NULL) 269530a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 269630a5e8faSwyllys 269730a5e8faSwyllys response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR, 269830a5e8faSwyllys attrlist, numattr); 269930a5e8faSwyllys if (response_status == NULL) 270030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 270130a5e8faSwyllys 270230a5e8faSwyllys response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR, 270330a5e8faSwyllys attrlist, numattr); 270430a5e8faSwyllys if (response_reason == NULL) 270530a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 270630a5e8faSwyllys 270730a5e8faSwyllys cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR, 270830a5e8faSwyllys attrlist, numattr); 270930a5e8faSwyllys if (cert_status == NULL) 271030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 271199ebb4caSwyllys 271299ebb4caSwyllys /* Read in the response */ 271330a5e8faSwyllys derbio = BIO_new_mem_buf(response->Data, response->Length); 271499ebb4caSwyllys if (!derbio) { 271599ebb4caSwyllys ret = KMF_ERR_MEMORY; 271699ebb4caSwyllys return (ret); 271799ebb4caSwyllys } 271899ebb4caSwyllys 271999ebb4caSwyllys resp = d2i_OCSP_RESPONSE_bio(derbio, NULL); 272099ebb4caSwyllys if (resp == NULL) { 272199ebb4caSwyllys ret = KMF_ERR_OCSP_MALFORMED_RESPONSE; 272299ebb4caSwyllys goto end; 272399ebb4caSwyllys } 272499ebb4caSwyllys 272599ebb4caSwyllys /* Check the response status */ 272699ebb4caSwyllys status = OCSP_response_status(resp); 272730a5e8faSwyllys *response_status = status; 272899ebb4caSwyllys if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { 272999ebb4caSwyllys ret = KMF_ERR_OCSP_RESPONSE_STATUS; 273099ebb4caSwyllys goto end; 273199ebb4caSwyllys } 273299ebb4caSwyllys 273399ebb4caSwyllys #ifdef DEBUG 273499ebb4caSwyllys printf("Successfully checked the response file status.\n"); 273599ebb4caSwyllys #endif /* DEBUG */ 273699ebb4caSwyllys 273799ebb4caSwyllys /* Extract basic response */ 273899ebb4caSwyllys bs = OCSP_response_get1_basic(resp); 273999ebb4caSwyllys if (bs == NULL) { 274099ebb4caSwyllys ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE; 274199ebb4caSwyllys goto end; 274299ebb4caSwyllys } 274399ebb4caSwyllys 274499ebb4caSwyllys #ifdef DEBUG 274599ebb4caSwyllys printf("Successfully retrieved the basic response.\n"); 274699ebb4caSwyllys #endif /* DEBUG */ 274799ebb4caSwyllys 274899ebb4caSwyllys /* Check the basic response signature if required */ 274930a5e8faSwyllys ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr, 275030a5e8faSwyllys (void *)&ignore_response_sign, NULL); 275130a5e8faSwyllys if (ret != KMF_OK) 275230a5e8faSwyllys ret = KMF_OK; 275330a5e8faSwyllys 275430a5e8faSwyllys signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR, 275530a5e8faSwyllys attrlist, numattr); 275630a5e8faSwyllys 275730a5e8faSwyllys if (ignore_response_sign == B_FALSE) { 275899ebb4caSwyllys ret = check_response_signature(handle, bs, 275930a5e8faSwyllys signer_cert, issuer_cert); 276099ebb4caSwyllys if (ret != KMF_OK) 276199ebb4caSwyllys goto end; 276299ebb4caSwyllys } 276399ebb4caSwyllys 276499ebb4caSwyllys #ifdef DEBUG 276599ebb4caSwyllys printf("Successfully verified the response signature.\n"); 276699ebb4caSwyllys #endif /* DEBUG */ 276799ebb4caSwyllys 276899ebb4caSwyllys /* Create a certid for the certificate in question */ 276930a5e8faSwyllys ret = create_certid(handle, issuer_cert, user_cert, &id); 277099ebb4caSwyllys if (ret != KMF_OK) { 277199ebb4caSwyllys ret = KMF_ERR_OCSP_CERTID; 277299ebb4caSwyllys goto end; 277399ebb4caSwyllys } 277499ebb4caSwyllys 277599ebb4caSwyllys #ifdef DEBUG 277699ebb4caSwyllys printf("successfully created a certid for the cert.\n"); 277799ebb4caSwyllys #endif /* DEBUG */ 277899ebb4caSwyllys 277999ebb4caSwyllys /* Find the index of the single response for the certid */ 278099ebb4caSwyllys index = OCSP_resp_find(bs, id, -1); 278199ebb4caSwyllys if (index < 0) { 278299ebb4caSwyllys /* cound not find this certificate in the response */ 278399ebb4caSwyllys ret = KMF_ERR_OCSP_UNKNOWN_CERT; 278499ebb4caSwyllys goto end; 278599ebb4caSwyllys } 278699ebb4caSwyllys 278799ebb4caSwyllys #ifdef DEBUG 278899ebb4caSwyllys printf("Successfully found the single response index for the cert.\n"); 278999ebb4caSwyllys #endif /* DEBUG */ 279099ebb4caSwyllys 279199ebb4caSwyllys /* Retrieve the single response and get the cert status */ 279299ebb4caSwyllys single = OCSP_resp_get0(bs, index); 279399ebb4caSwyllys status = OCSP_single_get0_status(single, &reason, &rev, &thisupd, 279499ebb4caSwyllys &nextupd); 279599ebb4caSwyllys if (status == V_OCSP_CERTSTATUS_GOOD) { 279630a5e8faSwyllys *cert_status = OCSP_GOOD; 279799ebb4caSwyllys } else if (status == V_OCSP_CERTSTATUS_UNKNOWN) { 279830a5e8faSwyllys *cert_status = OCSP_UNKNOWN; 279999ebb4caSwyllys } else { /* revoked */ 280030a5e8faSwyllys *cert_status = OCSP_REVOKED; 280130a5e8faSwyllys *response_reason = reason; 280299ebb4caSwyllys } 280399ebb4caSwyllys ret = KMF_OK; 280499ebb4caSwyllys 280530a5e8faSwyllys /* resp. time is optional, so we don't care about the return code. */ 280630a5e8faSwyllys (void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr, 280730a5e8faSwyllys (void *)&response_lifetime, NULL); 280830a5e8faSwyllys 280999ebb4caSwyllys if (!OCSP_check_validity(thisupd, nextupd, 300, 281030a5e8faSwyllys response_lifetime)) { 281199ebb4caSwyllys ret = KMF_ERR_OCSP_STATUS_TIME_INVALID; 281299ebb4caSwyllys goto end; 281399ebb4caSwyllys } 281499ebb4caSwyllys 281599ebb4caSwyllys #ifdef DEBUG 281699ebb4caSwyllys printf("Successfully verify the time.\n"); 281799ebb4caSwyllys #endif /* DEBUG */ 281899ebb4caSwyllys 281999ebb4caSwyllys end: 282099ebb4caSwyllys if (derbio != NULL) 282199ebb4caSwyllys (void) BIO_free(derbio); 282299ebb4caSwyllys 282399ebb4caSwyllys if (resp != NULL) 282499ebb4caSwyllys OCSP_RESPONSE_free(resp); 282599ebb4caSwyllys 282699ebb4caSwyllys if (bs != NULL) 282799ebb4caSwyllys OCSP_BASICRESP_free(bs); 282899ebb4caSwyllys 282999ebb4caSwyllys if (id != NULL) 283099ebb4caSwyllys OCSP_CERTID_free(id); 283199ebb4caSwyllys 283299ebb4caSwyllys return (ret); 283399ebb4caSwyllys } 283499ebb4caSwyllys 283599ebb4caSwyllys static KMF_RETURN 2836*4942e222SAndy Fiddaman fetch_key(KMF_HANDLE_T handle, char *path, KMF_KEY_CLASS keyclass, 2837*4942e222SAndy Fiddaman KMF_KEY_HANDLE *key) 283899ebb4caSwyllys { 283999ebb4caSwyllys KMF_RETURN rv = KMF_OK; 284030a5e8faSwyllys EVP_PKEY *pkey = NULL; 284199ebb4caSwyllys KMF_RAW_SYM_KEY *rkey = NULL; 284299ebb4caSwyllys 284399ebb4caSwyllys if (keyclass == KMF_ASYM_PRI || 284499ebb4caSwyllys keyclass == KMF_ASYM_PUB) { 284599ebb4caSwyllys pkey = openssl_load_key(handle, path); 284699ebb4caSwyllys if (pkey == NULL) { 284799ebb4caSwyllys return (KMF_ERR_KEY_NOT_FOUND); 284899ebb4caSwyllys } 284999ebb4caSwyllys if (key != NULL) { 2850300fdee2SAndy Fiddaman if (EVP_PKEY_get0_RSA(pkey) != NULL) 285199ebb4caSwyllys key->keyalg = KMF_RSA; 2852300fdee2SAndy Fiddaman else if (EVP_PKEY_get0_DSA(pkey) != NULL) 285399ebb4caSwyllys key->keyalg = KMF_DSA; 285499ebb4caSwyllys 285599ebb4caSwyllys key->kstype = KMF_KEYSTORE_OPENSSL; 285699ebb4caSwyllys key->keyclass = keyclass; 285799ebb4caSwyllys key->keyp = (void *)pkey; 285899ebb4caSwyllys key->israw = FALSE; 28595b3e1433Swyllys if (path != NULL && 28605b3e1433Swyllys ((key->keylabel = strdup(path)) == NULL)) { 28615b3e1433Swyllys EVP_PKEY_free(pkey); 28625b3e1433Swyllys return (KMF_ERR_MEMORY); 28635b3e1433Swyllys } 286499ebb4caSwyllys } else { 286599ebb4caSwyllys EVP_PKEY_free(pkey); 286699ebb4caSwyllys pkey = NULL; 286799ebb4caSwyllys } 286899ebb4caSwyllys } else if (keyclass == KMF_SYMMETRIC) { 286999ebb4caSwyllys KMF_ENCODE_FORMAT fmt; 287099ebb4caSwyllys /* 287199ebb4caSwyllys * If the file is a recognized format, 287299ebb4caSwyllys * then it is NOT a symmetric key. 287399ebb4caSwyllys */ 287430a5e8faSwyllys rv = kmf_get_file_format(path, &fmt); 287599ebb4caSwyllys if (rv == KMF_OK || fmt != 0) { 287699ebb4caSwyllys return (KMF_ERR_KEY_NOT_FOUND); 287799ebb4caSwyllys } else if (rv == KMF_ERR_ENCODING) { 287899ebb4caSwyllys /* 287999ebb4caSwyllys * If we don't know the encoding, 288099ebb4caSwyllys * it is probably a symmetric key. 288199ebb4caSwyllys */ 288299ebb4caSwyllys rv = KMF_OK; 288330a5e8faSwyllys } else if (rv == KMF_ERR_OPEN_FILE) { 288430a5e8faSwyllys return (KMF_ERR_KEY_NOT_FOUND); 288599ebb4caSwyllys } 288699ebb4caSwyllys 288799ebb4caSwyllys if (key != NULL) { 288899ebb4caSwyllys KMF_DATA keyvalue; 288999ebb4caSwyllys rkey = malloc(sizeof (KMF_RAW_SYM_KEY)); 289099ebb4caSwyllys if (rkey == NULL) { 289199ebb4caSwyllys rv = KMF_ERR_MEMORY; 289299ebb4caSwyllys goto out; 289399ebb4caSwyllys } 289499ebb4caSwyllys 289599ebb4caSwyllys (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 289630a5e8faSwyllys rv = kmf_read_input_file(handle, path, &keyvalue); 289799ebb4caSwyllys if (rv != KMF_OK) 289899ebb4caSwyllys goto out; 289999ebb4caSwyllys 290099ebb4caSwyllys rkey->keydata.len = keyvalue.Length; 290199ebb4caSwyllys rkey->keydata.val = keyvalue.Data; 290299ebb4caSwyllys 290399ebb4caSwyllys key->kstype = KMF_KEYSTORE_OPENSSL; 290499ebb4caSwyllys key->keyclass = keyclass; 290599ebb4caSwyllys key->israw = TRUE; 290699ebb4caSwyllys key->keyp = (void *)rkey; 29075b3e1433Swyllys if (path != NULL && 29085b3e1433Swyllys ((key->keylabel = strdup(path)) == NULL)) { 29095b3e1433Swyllys rv = KMF_ERR_MEMORY; 29105b3e1433Swyllys } 291199ebb4caSwyllys } 291299ebb4caSwyllys } 291399ebb4caSwyllys out: 291499ebb4caSwyllys if (rv != KMF_OK) { 291599ebb4caSwyllys if (rkey != NULL) { 291630a5e8faSwyllys kmf_free_raw_sym_key(rkey); 291799ebb4caSwyllys } 291899ebb4caSwyllys if (pkey != NULL) 291999ebb4caSwyllys EVP_PKEY_free(pkey); 292099ebb4caSwyllys 292199ebb4caSwyllys if (key != NULL) { 292299ebb4caSwyllys key->keyalg = KMF_KEYALG_NONE; 292399ebb4caSwyllys key->keyclass = KMF_KEYCLASS_NONE; 292499ebb4caSwyllys key->keyp = NULL; 292599ebb4caSwyllys } 292699ebb4caSwyllys } 292799ebb4caSwyllys 292899ebb4caSwyllys return (rv); 292999ebb4caSwyllys } 293099ebb4caSwyllys 293199ebb4caSwyllys KMF_RETURN 2932*4942e222SAndy Fiddaman OpenSSL_FindKey(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 293399ebb4caSwyllys { 293499ebb4caSwyllys KMF_RETURN rv = KMF_OK; 293599ebb4caSwyllys char *fullpath = NULL; 2936f482c776Swyllys uint32_t maxkeys; 293730a5e8faSwyllys KMF_KEY_HANDLE *key; 293830a5e8faSwyllys uint32_t *numkeys; 293930a5e8faSwyllys KMF_KEY_CLASS keyclass; 294030a5e8faSwyllys KMF_RAW_KEY_DATA *rawkey; 294130a5e8faSwyllys char *dirpath; 294230a5e8faSwyllys char *keyfile; 294399ebb4caSwyllys 294430a5e8faSwyllys if (handle == NULL) 294599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 294699ebb4caSwyllys 294730a5e8faSwyllys numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr); 294830a5e8faSwyllys if (numkeys == NULL) 294930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 295030a5e8faSwyllys 295130a5e8faSwyllys rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr, 295230a5e8faSwyllys (void *)&keyclass, NULL); 295330a5e8faSwyllys if (rv != KMF_OK) 295430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 295530a5e8faSwyllys 295630a5e8faSwyllys if (keyclass != KMF_ASYM_PUB && 295730a5e8faSwyllys keyclass != KMF_ASYM_PRI && 295830a5e8faSwyllys keyclass != KMF_SYMMETRIC) 295999ebb4caSwyllys return (KMF_ERR_BAD_KEY_CLASS); 296099ebb4caSwyllys 296130a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 296230a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 296330a5e8faSwyllys 296430a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 296599ebb4caSwyllys 296699ebb4caSwyllys if (fullpath == NULL) 296799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 296899ebb4caSwyllys 2969f482c776Swyllys maxkeys = *numkeys; 2970f482c776Swyllys if (maxkeys == 0) 2971f482c776Swyllys maxkeys = 0xFFFFFFFF; 297299ebb4caSwyllys *numkeys = 0; 297399ebb4caSwyllys 297430a5e8faSwyllys key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 297530a5e8faSwyllys /* it is okay to have "keys" contains NULL */ 297630a5e8faSwyllys 297730a5e8faSwyllys /* 297830a5e8faSwyllys * The caller may want a list of the raw key data as well. 297930a5e8faSwyllys * Useful for importing keys from a file into other keystores. 298030a5e8faSwyllys */ 298130a5e8faSwyllys rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr); 298230a5e8faSwyllys 298399ebb4caSwyllys if (isdir(fullpath)) { 298499ebb4caSwyllys DIR *dirp; 298599ebb4caSwyllys struct dirent *dp; 298699ebb4caSwyllys int n = 0; 298799ebb4caSwyllys 298899ebb4caSwyllys /* open all files in the directory and attempt to read them */ 298999ebb4caSwyllys if ((dirp = opendir(fullpath)) == NULL) { 299099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 299199ebb4caSwyllys } 299299ebb4caSwyllys rewinddir(dirp); 2993f482c776Swyllys while ((dp = readdir(dirp)) != NULL && n < maxkeys) { 299499ebb4caSwyllys if (strcmp(dp->d_name, ".") && 299599ebb4caSwyllys strcmp(dp->d_name, "..")) { 299699ebb4caSwyllys char *fname; 299799ebb4caSwyllys 299899ebb4caSwyllys fname = get_fullpath(fullpath, 299999ebb4caSwyllys (char *)&dp->d_name); 300099ebb4caSwyllys 300199ebb4caSwyllys rv = fetch_key(handle, fname, 300230a5e8faSwyllys keyclass, key ? &key[n] : NULL); 300399ebb4caSwyllys 300430a5e8faSwyllys if (rv == KMF_OK) { 300530a5e8faSwyllys if (key != NULL && rawkey != NULL) 300630a5e8faSwyllys rv = convertToRawKey( 300730a5e8faSwyllys key[n].keyp, &rawkey[n]); 300899ebb4caSwyllys n++; 300930a5e8faSwyllys } 301099ebb4caSwyllys 301199ebb4caSwyllys if (rv != KMF_OK || key == NULL) 301299ebb4caSwyllys free(fname); 301399ebb4caSwyllys } 301499ebb4caSwyllys } 301599ebb4caSwyllys (void) closedir(dirp); 301699ebb4caSwyllys free(fullpath); 301799ebb4caSwyllys (*numkeys) = n; 301899ebb4caSwyllys } else { 301930a5e8faSwyllys rv = fetch_key(handle, fullpath, keyclass, key); 302099ebb4caSwyllys if (rv == KMF_OK) 302199ebb4caSwyllys (*numkeys) = 1; 302299ebb4caSwyllys 302399ebb4caSwyllys if (rv != KMF_OK || key == NULL) 302499ebb4caSwyllys free(fullpath); 302530a5e8faSwyllys 302630a5e8faSwyllys if (rv == KMF_OK && key != NULL && rawkey != NULL) { 302730a5e8faSwyllys rv = convertToRawKey(key->keyp, rawkey); 302830a5e8faSwyllys } 302999ebb4caSwyllys } 303099ebb4caSwyllys 3031f482c776Swyllys if (rv == KMF_OK && (*numkeys) == 0) 303299ebb4caSwyllys rv = KMF_ERR_KEY_NOT_FOUND; 303373cc0e02Swyllys else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0) 303473cc0e02Swyllys rv = KMF_OK; 303599ebb4caSwyllys 303699ebb4caSwyllys return (rv); 303799ebb4caSwyllys } 303899ebb4caSwyllys 303999ebb4caSwyllys #define HANDLE_PK12_ERROR { \ 304099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); \ 304199ebb4caSwyllys rv = KMF_ERR_ENCODING; \ 304299ebb4caSwyllys goto out; \ 304399ebb4caSwyllys } 304499ebb4caSwyllys 30455b3e1433Swyllys static int 30465b3e1433Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert) 304799ebb4caSwyllys { 3048300fdee2SAndy Fiddaman unsigned char *alias; 3049300fdee2SAndy Fiddaman int len; 3050300fdee2SAndy Fiddaman 3051300fdee2SAndy Fiddaman if (xcert != NULL && (alias = X509_alias_get0(xcert, &len)) != NULL) { 30525b3e1433Swyllys if (PKCS12_add_friendlyname_asc(bag, 3053300fdee2SAndy Fiddaman (const char *)alias, len) == 0) 30545b3e1433Swyllys return (0); 30555b3e1433Swyllys } 30565b3e1433Swyllys return (1); 30575b3e1433Swyllys } 30585b3e1433Swyllys 30595b3e1433Swyllys static PKCS7 * 30605b3e1433Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred, 30615b3e1433Swyllys uchar_t *keyid, unsigned int keyidlen) 30625b3e1433Swyllys { 306399ebb4caSwyllys PKCS12_SAFEBAG *bag = NULL; 306499ebb4caSwyllys PKCS7 *cert_authsafe = NULL; 30655b3e1433Swyllys STACK_OF(PKCS12_SAFEBAG) *bag_stack; 306699ebb4caSwyllys 306799ebb4caSwyllys bag_stack = sk_PKCS12_SAFEBAG_new_null(); 306899ebb4caSwyllys if (bag_stack == NULL) 30695b3e1433Swyllys return (NULL); 307099ebb4caSwyllys 307199ebb4caSwyllys /* Convert cert from X509 struct to PKCS#12 bag */ 3072300fdee2SAndy Fiddaman bag = PKCS12_SAFEBAG_create_cert(sslcert); 307399ebb4caSwyllys if (bag == NULL) { 30745b3e1433Swyllys goto out; 307599ebb4caSwyllys } 307699ebb4caSwyllys 307799ebb4caSwyllys /* Add the key id to the certificate bag. */ 30785b3e1433Swyllys if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) { 30795b3e1433Swyllys goto out; 308099ebb4caSwyllys } 308199ebb4caSwyllys 30825b3e1433Swyllys if (!add_alias_to_bag(bag, sslcert)) 30835b3e1433Swyllys goto out; 30845b3e1433Swyllys 308599ebb4caSwyllys /* Pile it on the bag_stack. */ 308699ebb4caSwyllys if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) { 30875b3e1433Swyllys goto out; 308899ebb4caSwyllys } 308999ebb4caSwyllys /* Turn bag_stack of certs into encrypted authsafe. */ 309099ebb4caSwyllys cert_authsafe = PKCS12_pack_p7encdata( 309199ebb4caSwyllys NID_pbe_WithSHA1And40BitRC2_CBC, 309234acef67Swyllys cred->cred, cred->credlen, NULL, 0, 309334acef67Swyllys PKCS12_DEFAULT_ITER, bag_stack); 309499ebb4caSwyllys 30955b3e1433Swyllys out: 30965b3e1433Swyllys if (bag_stack != NULL) 309799ebb4caSwyllys sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); 309899ebb4caSwyllys 30995b3e1433Swyllys return (cert_authsafe); 310099ebb4caSwyllys } 31015b3e1433Swyllys 31025b3e1433Swyllys static PKCS7 * 31035b3e1433Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred, 3104*4942e222SAndy Fiddaman uchar_t *keyid, unsigned int keyidlen, char *label, int label_len) 31055b3e1433Swyllys { 31065b3e1433Swyllys PKCS8_PRIV_KEY_INFO *p8 = NULL; 31075b3e1433Swyllys STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL; 31085b3e1433Swyllys PKCS12_SAFEBAG *bag = NULL; 31095b3e1433Swyllys PKCS7 *key_authsafe = NULL; 31105b3e1433Swyllys 311199ebb4caSwyllys p8 = EVP_PKEY2PKCS8(pkey); 311299ebb4caSwyllys if (p8 == NULL) { 31135b3e1433Swyllys return (NULL); 311499ebb4caSwyllys } 311599ebb4caSwyllys /* Put the shrouded key into a PKCS#12 bag. */ 3116300fdee2SAndy Fiddaman bag = PKCS12_SAFEBAG_create_pkcs8_encrypt( 311799ebb4caSwyllys NID_pbe_WithSHA1And3_Key_TripleDES_CBC, 311899ebb4caSwyllys cred->cred, cred->credlen, 311999ebb4caSwyllys NULL, 0, PKCS12_DEFAULT_ITER, p8); 312099ebb4caSwyllys 312199ebb4caSwyllys /* Clean up the PKCS#8 shrouded key, don't need it now. */ 312299ebb4caSwyllys PKCS8_PRIV_KEY_INFO_free(p8); 312399ebb4caSwyllys p8 = NULL; 312499ebb4caSwyllys 312599ebb4caSwyllys if (bag == NULL) { 31265b3e1433Swyllys return (NULL); 312799ebb4caSwyllys } 31285b3e1433Swyllys if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) 31295b3e1433Swyllys goto out; 31305b3e1433Swyllys if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len)) 31315b3e1433Swyllys goto out; 31325b3e1433Swyllys 313399ebb4caSwyllys /* Start a PKCS#12 safebag container for the private key. */ 313499ebb4caSwyllys bag_stack = sk_PKCS12_SAFEBAG_new_null(); 31355b3e1433Swyllys if (bag_stack == NULL) 31365b3e1433Swyllys goto out; 313799ebb4caSwyllys 313899ebb4caSwyllys /* Pile on the private key on the bag_stack. */ 31395b3e1433Swyllys if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) 31405b3e1433Swyllys goto out; 31415b3e1433Swyllys 314299ebb4caSwyllys key_authsafe = PKCS12_pack_p7data(bag_stack); 314399ebb4caSwyllys 31445b3e1433Swyllys out: 31455b3e1433Swyllys if (bag_stack != NULL) 314699ebb4caSwyllys sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); 314799ebb4caSwyllys bag_stack = NULL; 31485b3e1433Swyllys return (key_authsafe); 314999ebb4caSwyllys } 315099ebb4caSwyllys 315199ebb4caSwyllys static EVP_PKEY * 315299ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key) 315399ebb4caSwyllys { 315499ebb4caSwyllys RSA *rsa = NULL; 315599ebb4caSwyllys EVP_PKEY *newkey = NULL; 3156*4942e222SAndy Fiddaman BIGNUM *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL; 3157*4942e222SAndy Fiddaman BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; 315899ebb4caSwyllys 315999ebb4caSwyllys if ((rsa = RSA_new()) == NULL) 3160300fdee2SAndy Fiddaman goto cleanup; 316199ebb4caSwyllys 3162300fdee2SAndy Fiddaman if ((n = BN_bin2bn(key->mod.val, key->mod.len, NULL)) == NULL) 3163300fdee2SAndy Fiddaman goto cleanup; 316499ebb4caSwyllys 3165300fdee2SAndy Fiddaman if ((e = BN_bin2bn(key->pubexp.val, key->pubexp.len, NULL)) == NULL) 3166300fdee2SAndy Fiddaman goto cleanup; 316799ebb4caSwyllys 3168300fdee2SAndy Fiddaman if (key->priexp.val != NULL && 3169300fdee2SAndy Fiddaman (d = BN_bin2bn(key->priexp.val, key->priexp.len, NULL)) == NULL) 3170300fdee2SAndy Fiddaman goto cleanup; 317199ebb4caSwyllys 3172300fdee2SAndy Fiddaman if (key->prime1.val != NULL && 3173300fdee2SAndy Fiddaman (p = BN_bin2bn(key->prime1.val, key->prime1.len, NULL)) == NULL) 3174300fdee2SAndy Fiddaman goto cleanup; 317599ebb4caSwyllys 3176300fdee2SAndy Fiddaman if (key->prime2.val != NULL && 3177300fdee2SAndy Fiddaman (q = BN_bin2bn(key->prime2.val, key->prime2.len, NULL)) == NULL) 3178300fdee2SAndy Fiddaman goto cleanup; 317999ebb4caSwyllys 3180300fdee2SAndy Fiddaman if (key->exp1.val != NULL && 3181300fdee2SAndy Fiddaman (dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len, NULL)) == NULL) 3182300fdee2SAndy Fiddaman goto cleanup; 318399ebb4caSwyllys 3184300fdee2SAndy Fiddaman if (key->exp2.val != NULL && 3185300fdee2SAndy Fiddaman (dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len, NULL)) == NULL) 3186300fdee2SAndy Fiddaman goto cleanup; 318799ebb4caSwyllys 3188300fdee2SAndy Fiddaman if (key->coef.val != NULL && 3189300fdee2SAndy Fiddaman (iqmp = BN_bin2bn(key->coef.val, key->coef.len, NULL)) == NULL) 3190300fdee2SAndy Fiddaman goto cleanup; 3191300fdee2SAndy Fiddaman 3192300fdee2SAndy Fiddaman if (RSA_set0_key(rsa, n, e, d) == 0) 3193300fdee2SAndy Fiddaman goto cleanup; 3194300fdee2SAndy Fiddaman n = e = d = NULL; 3195300fdee2SAndy Fiddaman if (RSA_set0_factors(rsa, p, q) == 0) 3196300fdee2SAndy Fiddaman goto cleanup; 3197300fdee2SAndy Fiddaman p = q = NULL; 3198300fdee2SAndy Fiddaman if (RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp) == 0) 3199300fdee2SAndy Fiddaman goto cleanup; 3200300fdee2SAndy Fiddaman dmp1 = dmq1 = iqmp = NULL; 320199ebb4caSwyllys 320299ebb4caSwyllys if ((newkey = EVP_PKEY_new()) == NULL) 3203300fdee2SAndy Fiddaman goto cleanup; 320499ebb4caSwyllys 320599ebb4caSwyllys (void) EVP_PKEY_set1_RSA(newkey, rsa); 320699ebb4caSwyllys 3207300fdee2SAndy Fiddaman cleanup: 320899ebb4caSwyllys /* The original key must be freed once here or it leaks memory */ 3209300fdee2SAndy Fiddaman if (rsa) 321099ebb4caSwyllys RSA_free(rsa); 3211300fdee2SAndy Fiddaman BN_free(n); 3212300fdee2SAndy Fiddaman BN_free(e); 3213300fdee2SAndy Fiddaman BN_free(d); 3214300fdee2SAndy Fiddaman BN_free(p); 3215300fdee2SAndy Fiddaman BN_free(q); 3216300fdee2SAndy Fiddaman BN_free(dmp1); 3217300fdee2SAndy Fiddaman BN_free(dmq1); 3218300fdee2SAndy Fiddaman BN_free(iqmp); 321999ebb4caSwyllys 322099ebb4caSwyllys return (newkey); 322199ebb4caSwyllys } 322299ebb4caSwyllys 322399ebb4caSwyllys static EVP_PKEY * 322499ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key) 322599ebb4caSwyllys { 322699ebb4caSwyllys DSA *dsa = NULL; 322799ebb4caSwyllys EVP_PKEY *newkey = NULL; 3228*4942e222SAndy Fiddaman BIGNUM *p = NULL, *q = NULL, *g = NULL; 3229*4942e222SAndy Fiddaman BIGNUM *priv_key = NULL, *pub_key = NULL; 323099ebb4caSwyllys 323199ebb4caSwyllys if ((dsa = DSA_new()) == NULL) 3232300fdee2SAndy Fiddaman goto cleanup; 323399ebb4caSwyllys 3234300fdee2SAndy Fiddaman if ((p = BN_bin2bn(key->prime.val, key->prime.len, NULL)) == NULL) 3235300fdee2SAndy Fiddaman goto cleanup; 323699ebb4caSwyllys 3237300fdee2SAndy Fiddaman if ((q = BN_bin2bn(key->subprime.val, key->subprime.len, NULL)) == NULL) 3238300fdee2SAndy Fiddaman goto cleanup; 323999ebb4caSwyllys 3240300fdee2SAndy Fiddaman if ((g = BN_bin2bn(key->base.val, key->base.len, NULL)) == NULL) 3241300fdee2SAndy Fiddaman goto cleanup; 324299ebb4caSwyllys 3243300fdee2SAndy Fiddaman if ((priv_key = BN_bin2bn(key->value.val, key->value.len, 3244300fdee2SAndy Fiddaman NULL)) == NULL) 3245300fdee2SAndy Fiddaman goto cleanup; 324699ebb4caSwyllys 3247300fdee2SAndy Fiddaman if (key->pubvalue.val != NULL && (pub_key = 3248300fdee2SAndy Fiddaman BN_bin2bn(key->pubvalue.val, key->pubvalue.len, NULL)) == NULL) 3249300fdee2SAndy Fiddaman goto cleanup; 3250300fdee2SAndy Fiddaman 3251300fdee2SAndy Fiddaman if (DSA_set0_pqg(dsa, p, q, g) == 0) 3252300fdee2SAndy Fiddaman goto cleanup; 3253300fdee2SAndy Fiddaman p = q = g = NULL; 3254300fdee2SAndy Fiddaman if (DSA_set0_key(dsa, pub_key, priv_key) == 0) 3255300fdee2SAndy Fiddaman goto cleanup; 3256300fdee2SAndy Fiddaman pub_key = priv_key = 0; 325730a5e8faSwyllys 325899ebb4caSwyllys if ((newkey = EVP_PKEY_new()) == NULL) 3259300fdee2SAndy Fiddaman goto cleanup; 326099ebb4caSwyllys 326199ebb4caSwyllys (void) EVP_PKEY_set1_DSA(newkey, dsa); 326299ebb4caSwyllys 3263300fdee2SAndy Fiddaman cleanup: 326499ebb4caSwyllys /* The original key must be freed once here or it leaks memory */ 3265300fdee2SAndy Fiddaman if (dsa) 326699ebb4caSwyllys DSA_free(dsa); 3267300fdee2SAndy Fiddaman BN_free(p); 3268300fdee2SAndy Fiddaman BN_free(q); 3269300fdee2SAndy Fiddaman BN_free(g); 3270300fdee2SAndy Fiddaman BN_free(priv_key); 3271300fdee2SAndy Fiddaman BN_free(pub_key); 3272300fdee2SAndy Fiddaman 327399ebb4caSwyllys return (newkey); 327499ebb4caSwyllys } 327599ebb4caSwyllys 32765b3e1433Swyllys static EVP_PKEY * 32775b3e1433Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key) 32785b3e1433Swyllys { 32795b3e1433Swyllys EVP_PKEY *pkey = NULL; 32805b3e1433Swyllys KMF_RAW_KEY_DATA *rawkey; 32815b3e1433Swyllys ASN1_TYPE *attr = NULL; 32825b3e1433Swyllys KMF_RETURN ret; 32835b3e1433Swyllys 32845b3e1433Swyllys if (key == NULL || !key->israw) 32855b3e1433Swyllys return (NULL); 32865b3e1433Swyllys 32875b3e1433Swyllys rawkey = (KMF_RAW_KEY_DATA *)key->keyp; 32885b3e1433Swyllys if (rawkey->keytype == KMF_RSA) { 32895b3e1433Swyllys pkey = ImportRawRSAKey(&rawkey->rawdata.rsa); 32905b3e1433Swyllys } else if (rawkey->keytype == KMF_DSA) { 32915b3e1433Swyllys pkey = ImportRawDSAKey(&rawkey->rawdata.dsa); 3292e65e5c2dSWyllys Ingersoll } else if (rawkey->keytype == KMF_ECDSA) { 3293e65e5c2dSWyllys Ingersoll /* 3294e65e5c2dSWyllys Ingersoll * OpenSSL in Solaris does not support EC for 3295e65e5c2dSWyllys Ingersoll * legal reasons 3296e65e5c2dSWyllys Ingersoll */ 3297e65e5c2dSWyllys Ingersoll return (NULL); 32985b3e1433Swyllys } else { 32995b3e1433Swyllys /* wrong kind of key */ 33005b3e1433Swyllys return (NULL); 33015b3e1433Swyllys } 33025b3e1433Swyllys 33035b3e1433Swyllys if (rawkey->label != NULL) { 33045b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) { 33055b3e1433Swyllys EVP_PKEY_free(pkey); 33065b3e1433Swyllys return (NULL); 33075b3e1433Swyllys } 33085b3e1433Swyllys attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING); 33095b3e1433Swyllys (void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label, 33105b3e1433Swyllys strlen(rawkey->label)); 33115b3e1433Swyllys attr->type = V_ASN1_BMPSTRING; 33125b3e1433Swyllys attr->value.ptr = (char *)attr->value.bmpstring; 33135b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_friendlyName); 33145b3e1433Swyllys if (ret != KMF_OK) { 33155b3e1433Swyllys EVP_PKEY_free(pkey); 33165b3e1433Swyllys ASN1_TYPE_free(attr); 33175b3e1433Swyllys return (NULL); 33185b3e1433Swyllys } 33195b3e1433Swyllys } 33205b3e1433Swyllys if (rawkey->id.Data != NULL) { 33215b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) { 33225b3e1433Swyllys EVP_PKEY_free(pkey); 33235b3e1433Swyllys return (NULL); 33245b3e1433Swyllys } 33255b3e1433Swyllys attr->value.octet_string = 33265b3e1433Swyllys ASN1_STRING_type_new(V_ASN1_OCTET_STRING); 33275b3e1433Swyllys attr->type = V_ASN1_OCTET_STRING; 33285b3e1433Swyllys (void) ASN1_STRING_set(attr->value.octet_string, 33295b3e1433Swyllys rawkey->id.Data, rawkey->id.Length); 33305b3e1433Swyllys attr->value.ptr = (char *)attr->value.octet_string; 33315b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_localKeyID); 33325b3e1433Swyllys if (ret != KMF_OK) { 33335b3e1433Swyllys EVP_PKEY_free(pkey); 33345b3e1433Swyllys ASN1_TYPE_free(attr); 33355b3e1433Swyllys return (NULL); 33365b3e1433Swyllys } 33375b3e1433Swyllys } 33385b3e1433Swyllys return (pkey); 33395b3e1433Swyllys } 33405b3e1433Swyllys 33415b3e1433Swyllys /* 33425b3e1433Swyllys * Search a list of private keys to find one that goes with the certificate. 33435b3e1433Swyllys */ 33445b3e1433Swyllys static EVP_PKEY * 33455b3e1433Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist) 33465b3e1433Swyllys { 33475b3e1433Swyllys int i; 33485b3e1433Swyllys EVP_PKEY *pkey = NULL; 33495b3e1433Swyllys 33505b3e1433Swyllys if (numkeys == 0 || keylist == NULL || xcert == NULL) 33515b3e1433Swyllys return (NULL); 33525b3e1433Swyllys for (i = 0; i < numkeys; i++) { 33535b3e1433Swyllys if (keylist[i].israw) 33545b3e1433Swyllys pkey = raw_key_to_pkey(&keylist[i]); 33555b3e1433Swyllys else 33565b3e1433Swyllys pkey = (EVP_PKEY *)keylist[i].keyp; 33575b3e1433Swyllys if (pkey != NULL) { 33585b3e1433Swyllys if (X509_check_private_key(xcert, pkey)) { 33595b3e1433Swyllys return (pkey); 33605b3e1433Swyllys } else { 33615b3e1433Swyllys EVP_PKEY_free(pkey); 33625b3e1433Swyllys pkey = NULL; 33635b3e1433Swyllys } 33645b3e1433Swyllys } 33655b3e1433Swyllys } 33665b3e1433Swyllys return (pkey); 33675b3e1433Swyllys } 33685b3e1433Swyllys 336999ebb4caSwyllys static KMF_RETURN 3370*4942e222SAndy Fiddaman local_export_pk12(KMF_HANDLE_T handle, KMF_CREDENTIAL *cred, int numcerts, 3371*4942e222SAndy Fiddaman KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist, 337299ebb4caSwyllys char *filename) 337399ebb4caSwyllys { 337499ebb4caSwyllys KMF_RETURN rv = KMF_OK; 337599ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 337699ebb4caSwyllys BIO *bio = NULL; 33775b3e1433Swyllys PKCS7 *cert_authsafe = NULL; 33785b3e1433Swyllys PKCS7 *key_authsafe = NULL; 33795b3e1433Swyllys STACK_OF(PKCS7) *authsafe_stack = NULL; 33805b3e1433Swyllys PKCS12 *p12_elem = NULL; 338199ebb4caSwyllys int i; 338299ebb4caSwyllys 33835b3e1433Swyllys if (numcerts == 0 && numkeys == 0) 33845b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 33855b3e1433Swyllys 338699ebb4caSwyllys /* 338799ebb4caSwyllys * Open the output file. 338899ebb4caSwyllys */ 338999ebb4caSwyllys if ((bio = BIO_new_file(filename, "wb")) == NULL) { 339099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 339199ebb4caSwyllys rv = KMF_ERR_OPEN_FILE; 339299ebb4caSwyllys goto cleanup; 339399ebb4caSwyllys } 339499ebb4caSwyllys 33955b3e1433Swyllys /* Start a PKCS#7 stack. */ 33965b3e1433Swyllys authsafe_stack = sk_PKCS7_new_null(); 33975b3e1433Swyllys if (authsafe_stack == NULL) { 33985b3e1433Swyllys rv = KMF_ERR_MEMORY; 33995b3e1433Swyllys goto cleanup; 34005b3e1433Swyllys } 34015b3e1433Swyllys if (numcerts > 0) { 340299ebb4caSwyllys for (i = 0; rv == KMF_OK && i < numcerts; i++) { 340399ebb4caSwyllys const uchar_t *p = certlist[i].certificate.Data; 340499ebb4caSwyllys long len = certlist[i].certificate.Length; 34055b3e1433Swyllys X509 *xcert = NULL; 34065b3e1433Swyllys EVP_PKEY *pkey = NULL; 34075b3e1433Swyllys unsigned char keyid[EVP_MAX_MD_SIZE]; 34085b3e1433Swyllys unsigned int keyidlen = 0; 340999ebb4caSwyllys 341099ebb4caSwyllys xcert = d2i_X509(NULL, &p, len); 341199ebb4caSwyllys if (xcert == NULL) { 341299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 341399ebb4caSwyllys rv = KMF_ERR_ENCODING; 341499ebb4caSwyllys } 34155b3e1433Swyllys if (certlist[i].kmf_private.label != NULL) { 34165b3e1433Swyllys /* Set alias attribute */ 34175b3e1433Swyllys (void) X509_alias_set1(xcert, 34185b3e1433Swyllys (uchar_t *)certlist[i].kmf_private.label, 34195b3e1433Swyllys strlen(certlist[i].kmf_private.label)); 34205b3e1433Swyllys } 34215b3e1433Swyllys /* Check if there is a key corresponding to this cert */ 34225b3e1433Swyllys pkey = find_matching_key(xcert, numkeys, keylist); 34235b3e1433Swyllys 34245b3e1433Swyllys /* 34255b3e1433Swyllys * If key is found, get fingerprint and create a 34265b3e1433Swyllys * safebag. 34275b3e1433Swyllys */ 34285b3e1433Swyllys if (pkey != NULL) { 34295b3e1433Swyllys (void) X509_digest(xcert, EVP_sha1(), 34305b3e1433Swyllys keyid, &keyidlen); 34315b3e1433Swyllys key_authsafe = add_key_to_safe(pkey, cred, 34325b3e1433Swyllys keyid, keyidlen, 34335b3e1433Swyllys certlist[i].kmf_private.label, 34345b3e1433Swyllys (certlist[i].kmf_private.label ? 34355b3e1433Swyllys strlen(certlist[i].kmf_private.label) : 0)); 34365b3e1433Swyllys 34375b3e1433Swyllys if (key_authsafe == NULL) { 34385b3e1433Swyllys X509_free(xcert); 34395b3e1433Swyllys EVP_PKEY_free(pkey); 34405b3e1433Swyllys goto cleanup; 34415b3e1433Swyllys } 34425b3e1433Swyllys /* Put the key safe into the Auth Safe */ 34435b3e1433Swyllys if (!sk_PKCS7_push(authsafe_stack, 34445b3e1433Swyllys key_authsafe)) { 34455b3e1433Swyllys X509_free(xcert); 34465b3e1433Swyllys EVP_PKEY_free(pkey); 34475b3e1433Swyllys goto cleanup; 34485b3e1433Swyllys } 34495b3e1433Swyllys } 34505b3e1433Swyllys 34515b3e1433Swyllys /* create a certificate safebag */ 34525b3e1433Swyllys cert_authsafe = add_cert_to_safe(xcert, cred, keyid, 34535b3e1433Swyllys keyidlen); 34545b3e1433Swyllys if (cert_authsafe == NULL) { 34555b3e1433Swyllys X509_free(xcert); 34565b3e1433Swyllys EVP_PKEY_free(pkey); 34575b3e1433Swyllys goto cleanup; 34585b3e1433Swyllys } 34595b3e1433Swyllys if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) { 34605b3e1433Swyllys X509_free(xcert); 34615b3e1433Swyllys EVP_PKEY_free(pkey); 34625b3e1433Swyllys goto cleanup; 34635b3e1433Swyllys } 34645b3e1433Swyllys 346599ebb4caSwyllys X509_free(xcert); 346699ebb4caSwyllys if (pkey) 346799ebb4caSwyllys EVP_PKEY_free(pkey); 346899ebb4caSwyllys } 34695b3e1433Swyllys } else if (numcerts == 0 && numkeys > 0) { 34705b3e1433Swyllys /* 34715b3e1433Swyllys * If only adding keys to the file. 34725b3e1433Swyllys */ 34735b3e1433Swyllys for (i = 0; i < numkeys; i++) { 34745b3e1433Swyllys EVP_PKEY *pkey = NULL; 34755b3e1433Swyllys 34765b3e1433Swyllys if (keylist[i].israw) 34775b3e1433Swyllys pkey = raw_key_to_pkey(&keylist[i]); 34785b3e1433Swyllys else 34795b3e1433Swyllys pkey = (EVP_PKEY *)keylist[i].keyp; 34805b3e1433Swyllys 34815b3e1433Swyllys if (pkey == NULL) 34825b3e1433Swyllys continue; 34835b3e1433Swyllys 34845b3e1433Swyllys key_authsafe = add_key_to_safe(pkey, cred, 34855b3e1433Swyllys NULL, 0, NULL, 0); 34865b3e1433Swyllys 34875b3e1433Swyllys if (key_authsafe == NULL) { 34885b3e1433Swyllys EVP_PKEY_free(pkey); 34895b3e1433Swyllys goto cleanup; 34905b3e1433Swyllys } 34915b3e1433Swyllys if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) { 34925b3e1433Swyllys EVP_PKEY_free(pkey); 34935b3e1433Swyllys goto cleanup; 34945b3e1433Swyllys } 34955b3e1433Swyllys } 34965b3e1433Swyllys } 34975b3e1433Swyllys p12_elem = PKCS12_init(NID_pkcs7_data); 34985b3e1433Swyllys if (p12_elem == NULL) { 34995b3e1433Swyllys goto cleanup; 350099ebb4caSwyllys } 350199ebb4caSwyllys 35025b3e1433Swyllys /* Put the PKCS#7 stack into the PKCS#12 element. */ 35035b3e1433Swyllys if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) { 35045b3e1433Swyllys goto cleanup; 35055b3e1433Swyllys } 35065b3e1433Swyllys 35075b3e1433Swyllys /* Set the integrity MAC on the PKCS#12 element. */ 35085b3e1433Swyllys if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen, 35095b3e1433Swyllys NULL, 0, PKCS12_DEFAULT_ITER, NULL)) { 35105b3e1433Swyllys goto cleanup; 35115b3e1433Swyllys } 35125b3e1433Swyllys 35135b3e1433Swyllys /* Write the PKCS#12 element to the export file. */ 35145b3e1433Swyllys if (!i2d_PKCS12_bio(bio, p12_elem)) { 35155b3e1433Swyllys goto cleanup; 35165b3e1433Swyllys } 35175b3e1433Swyllys PKCS12_free(p12_elem); 35185b3e1433Swyllys 351999ebb4caSwyllys cleanup: 35205b3e1433Swyllys /* Clear away the PKCS#7 stack, we're done with it. */ 35215b3e1433Swyllys if (authsafe_stack) 35225b3e1433Swyllys sk_PKCS7_pop_free(authsafe_stack, PKCS7_free); 352399ebb4caSwyllys 352499ebb4caSwyllys if (bio != NULL) 352599ebb4caSwyllys (void) BIO_free_all(bio); 352699ebb4caSwyllys 352799ebb4caSwyllys return (rv); 352899ebb4caSwyllys } 352999ebb4caSwyllys 353099ebb4caSwyllys KMF_RETURN 353130a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts, 353230a5e8faSwyllys KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist, 353330a5e8faSwyllys KMF_CREDENTIAL *p12cred, char *filename) 353430a5e8faSwyllys { 353530a5e8faSwyllys KMF_RETURN rv; 353630a5e8faSwyllys 353730a5e8faSwyllys if (certlist == NULL && keylist == NULL) 353830a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 353930a5e8faSwyllys 35405b3e1433Swyllys rv = local_export_pk12(handle, p12cred, numcerts, certlist, 354130a5e8faSwyllys numkeys, keylist, filename); 354230a5e8faSwyllys 354330a5e8faSwyllys return (rv); 354430a5e8faSwyllys } 354530a5e8faSwyllys 354630a5e8faSwyllys KMF_RETURN 354730a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 354899ebb4caSwyllys { 354999ebb4caSwyllys KMF_RETURN rv; 355099ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 355199ebb4caSwyllys char *fullpath = NULL; 355230a5e8faSwyllys char *dirpath = NULL; 355330a5e8faSwyllys char *certfile = NULL; 355430a5e8faSwyllys char *keyfile = NULL; 355530a5e8faSwyllys char *filename = NULL; 355630a5e8faSwyllys KMF_CREDENTIAL *p12cred = NULL; 35575b3e1433Swyllys KMF_X509_DER_CERT certdata; 35585b3e1433Swyllys KMF_KEY_HANDLE key; 35595b3e1433Swyllys int gotkey = 0; 35605b3e1433Swyllys int gotcert = 0; 356130a5e8faSwyllys 356230a5e8faSwyllys if (handle == NULL) 356330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 356499ebb4caSwyllys 356599ebb4caSwyllys /* 356699ebb4caSwyllys * First, find the certificate. 356799ebb4caSwyllys */ 356830a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 356930a5e8faSwyllys certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr); 357030a5e8faSwyllys if (certfile != NULL) { 357130a5e8faSwyllys fullpath = get_fullpath(dirpath, certfile); 357299ebb4caSwyllys if (fullpath == NULL) 357399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 357499ebb4caSwyllys 357599ebb4caSwyllys if (isdir(fullpath)) { 357699ebb4caSwyllys free(fullpath); 357799ebb4caSwyllys return (KMF_ERR_AMBIGUOUS_PATHNAME); 357899ebb4caSwyllys } 357999ebb4caSwyllys 35805b3e1433Swyllys (void) memset(&certdata, 0, sizeof (certdata)); 3581f810c7e5SToomas Soome rv = kmf_load_cert(kmfh, NULL, NULL, NULL, 0, 35825b3e1433Swyllys fullpath, &certdata.certificate); 358399ebb4caSwyllys if (rv != KMF_OK) 358499ebb4caSwyllys goto end; 358530a5e8faSwyllys 35865b3e1433Swyllys gotcert++; 35875b3e1433Swyllys certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL; 358830a5e8faSwyllys free(fullpath); 358999ebb4caSwyllys } 359099ebb4caSwyllys 359199ebb4caSwyllys /* 359299ebb4caSwyllys * Now find the private key. 359399ebb4caSwyllys */ 359430a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 359530a5e8faSwyllys if (keyfile != NULL) { 359630a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 359799ebb4caSwyllys if (fullpath == NULL) 359899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 359999ebb4caSwyllys 360099ebb4caSwyllys if (isdir(fullpath)) { 360199ebb4caSwyllys free(fullpath); 360299ebb4caSwyllys return (KMF_ERR_AMBIGUOUS_PATHNAME); 360399ebb4caSwyllys } 360499ebb4caSwyllys 36055b3e1433Swyllys (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE)); 36065b3e1433Swyllys rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key); 36075b3e1433Swyllys if (rv != KMF_OK) 360899ebb4caSwyllys goto end; 36095b3e1433Swyllys gotkey++; 361099ebb4caSwyllys } 361199ebb4caSwyllys 361299ebb4caSwyllys /* 361399ebb4caSwyllys * Open the output file. 361499ebb4caSwyllys */ 361530a5e8faSwyllys filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist, 361630a5e8faSwyllys numattr); 361730a5e8faSwyllys if (filename == NULL) { 361830a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 361930a5e8faSwyllys goto end; 362030a5e8faSwyllys } 362130a5e8faSwyllys 362299ebb4caSwyllys /* Stick the key and the cert into a PKCS#12 file */ 362330a5e8faSwyllys p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr); 362430a5e8faSwyllys if (p12cred == NULL) { 362530a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 362630a5e8faSwyllys goto end; 362730a5e8faSwyllys } 362830a5e8faSwyllys 36295b3e1433Swyllys rv = local_export_pk12(handle, p12cred, 1, &certdata, 36305b3e1433Swyllys 1, &key, filename); 363199ebb4caSwyllys 363299ebb4caSwyllys end: 363399ebb4caSwyllys if (fullpath) 363499ebb4caSwyllys free(fullpath); 363599ebb4caSwyllys 36365b3e1433Swyllys if (gotcert) 36375b3e1433Swyllys kmf_free_kmf_cert(handle, &certdata); 36385b3e1433Swyllys if (gotkey) 36395b3e1433Swyllys kmf_free_kmf_key(handle, &key); 364099ebb4caSwyllys return (rv); 364199ebb4caSwyllys } 364299ebb4caSwyllys 364371593db2Swyllys /* 364471593db2Swyllys * Helper function to extract keys and certificates from 364571593db2Swyllys * a single PEM file. Typically the file should contain a 364671593db2Swyllys * private key and an associated public key wrapped in an x509 cert. 364771593db2Swyllys * However, the file may be just a list of X509 certs with no keys. 364871593db2Swyllys */ 364971593db2Swyllys static KMF_RETURN 3650*4942e222SAndy Fiddaman extract_pem(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial, 3651*4942e222SAndy Fiddaman char *filename, CK_UTF8CHAR *pin, CK_ULONG pinlen, EVP_PKEY **priv_key, 3652*4942e222SAndy Fiddaman KMF_DATA **certs, int *numcerts) 365371593db2Swyllys { 365471593db2Swyllys KMF_RETURN rv = KMF_OK; 365571593db2Swyllys FILE *fp; 365634acef67Swyllys STACK_OF(X509_INFO) *x509_info_stack = NULL; 365702744e81Swyllys int i, ncerts = 0, matchcerts = 0; 365871593db2Swyllys EVP_PKEY *pkey = NULL; 365971593db2Swyllys X509_INFO *info; 366071593db2Swyllys X509 *x; 36615b3e1433Swyllys X509_INFO **cert_infos = NULL; 366271593db2Swyllys KMF_DATA *certlist = NULL; 366371593db2Swyllys 366471593db2Swyllys if (priv_key) 366571593db2Swyllys *priv_key = NULL; 366671593db2Swyllys if (certs) 366771593db2Swyllys *certs = NULL; 366871593db2Swyllys fp = fopen(filename, "r"); 36695b3e1433Swyllys if (fp == NULL) 367071593db2Swyllys return (KMF_ERR_OPEN_FILE); 36715b3e1433Swyllys 367271593db2Swyllys x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin); 367371593db2Swyllys if (x509_info_stack == NULL) { 367471593db2Swyllys (void) fclose(fp); 367571593db2Swyllys return (KMF_ERR_ENCODING); 367671593db2Swyllys } 36775b3e1433Swyllys cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) * 36785b3e1433Swyllys sizeof (X509_INFO *)); 36795b3e1433Swyllys if (cert_infos == NULL) { 36805b3e1433Swyllys (void) fclose(fp); 36815b3e1433Swyllys rv = KMF_ERR_MEMORY; 36825b3e1433Swyllys goto err; 36835b3e1433Swyllys } 368471593db2Swyllys 36855b3e1433Swyllys for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) { 368634acef67Swyllys cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i); 368771593db2Swyllys ncerts++; 368871593db2Swyllys } 368971593db2Swyllys 369071593db2Swyllys if (ncerts == 0) { 369171593db2Swyllys (void) fclose(fp); 369234acef67Swyllys rv = KMF_ERR_CERT_NOT_FOUND; 369334acef67Swyllys goto err; 369471593db2Swyllys } 369571593db2Swyllys 369671593db2Swyllys if (priv_key != NULL) { 369771593db2Swyllys rewind(fp); 369871593db2Swyllys pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin); 369971593db2Swyllys } 370071593db2Swyllys (void) fclose(fp); 370171593db2Swyllys 370271593db2Swyllys x = cert_infos[ncerts - 1]->x509; 370371593db2Swyllys /* 370471593db2Swyllys * Make sure the private key matchs the last cert in the file. 370571593db2Swyllys */ 370671593db2Swyllys if (pkey != NULL && !X509_check_private_key(x, pkey)) { 370771593db2Swyllys EVP_PKEY_free(pkey); 370834acef67Swyllys rv = KMF_ERR_KEY_MISMATCH; 370934acef67Swyllys goto err; 371071593db2Swyllys } 371171593db2Swyllys 3712a2d4930dSDan OpenSolaris Anderson certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA)); 371371593db2Swyllys if (certlist == NULL) { 371471593db2Swyllys if (pkey != NULL) 371571593db2Swyllys EVP_PKEY_free(pkey); 371634acef67Swyllys rv = KMF_ERR_MEMORY; 371734acef67Swyllys goto err; 371871593db2Swyllys } 371971593db2Swyllys 372071593db2Swyllys /* 372171593db2Swyllys * Convert all of the certs to DER format. 372271593db2Swyllys */ 372302744e81Swyllys matchcerts = 0; 372471593db2Swyllys for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) { 372502744e81Swyllys boolean_t match = FALSE; 372671593db2Swyllys info = cert_infos[ncerts - 1 - i]; 372771593db2Swyllys 372830a5e8faSwyllys rv = check_cert(info->x509, issuer, subject, serial, &match); 372902744e81Swyllys if (rv != KMF_OK || match != TRUE) { 373002744e81Swyllys rv = KMF_OK; 373102744e81Swyllys continue; 373202744e81Swyllys } 373302744e81Swyllys 373402744e81Swyllys rv = ssl_cert2KMFDATA(kmfh, info->x509, 373502744e81Swyllys &certlist[matchcerts++]); 373671593db2Swyllys 373771593db2Swyllys if (rv != KMF_OK) { 3738e65e5c2dSWyllys Ingersoll int j; 3739e65e5c2dSWyllys Ingersoll for (j = 0; j < matchcerts; j++) 3740e65e5c2dSWyllys Ingersoll kmf_free_data(&certlist[j]); 374171593db2Swyllys free(certlist); 374271593db2Swyllys certlist = NULL; 374302744e81Swyllys ncerts = matchcerts = 0; 374471593db2Swyllys } 374571593db2Swyllys } 374671593db2Swyllys 374771593db2Swyllys if (numcerts != NULL) 374802744e81Swyllys *numcerts = matchcerts; 3749a2d4930dSDan OpenSolaris Anderson 3750e65e5c2dSWyllys Ingersoll if (certs != NULL) 375171593db2Swyllys *certs = certlist; 3752e65e5c2dSWyllys Ingersoll else if (certlist != NULL) { 3753e65e5c2dSWyllys Ingersoll for (i = 0; i < ncerts; i++) 3754e65e5c2dSWyllys Ingersoll kmf_free_data(&certlist[i]); 3755a2d4930dSDan OpenSolaris Anderson free(certlist); 3756a2d4930dSDan OpenSolaris Anderson certlist = NULL; 3757a2d4930dSDan OpenSolaris Anderson } 375871593db2Swyllys 375971593db2Swyllys if (priv_key == NULL && pkey != NULL) 376071593db2Swyllys EVP_PKEY_free(pkey); 376171593db2Swyllys else if (priv_key != NULL && pkey != NULL) 376271593db2Swyllys *priv_key = pkey; 376371593db2Swyllys 376434acef67Swyllys err: 376534acef67Swyllys /* Cleanup the stack of X509 info records */ 376634acef67Swyllys for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) { 376734acef67Swyllys info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i); 376834acef67Swyllys X509_INFO_free(info); 376934acef67Swyllys } 377034acef67Swyllys if (x509_info_stack) 377134acef67Swyllys sk_X509_INFO_free(x509_info_stack); 377234acef67Swyllys 37735b3e1433Swyllys if (cert_infos != NULL) 37745b3e1433Swyllys free(cert_infos); 37755b3e1433Swyllys 377671593db2Swyllys return (rv); 377771593db2Swyllys } 377871593db2Swyllys 37795b3e1433Swyllys static KMF_RETURN 3780300fdee2SAndy Fiddaman openssl_parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, char *pin, 37815b3e1433Swyllys STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs) 37825b3e1433Swyllys { 37835b3e1433Swyllys KMF_RETURN ret; 37845b3e1433Swyllys int i; 37855b3e1433Swyllys 37865b3e1433Swyllys for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { 37875b3e1433Swyllys PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i); 37885b3e1433Swyllys ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0), 37895b3e1433Swyllys keys, certs); 37905b3e1433Swyllys 37915b3e1433Swyllys if (ret != KMF_OK) 37925b3e1433Swyllys return (ret); 37935b3e1433Swyllys } 37945b3e1433Swyllys 37955b3e1433Swyllys return (ret); 37965b3e1433Swyllys } 37975b3e1433Swyllys 37985b3e1433Swyllys static KMF_RETURN 37995b3e1433Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid) 38005b3e1433Swyllys { 38015b3e1433Swyllys X509_ATTRIBUTE *attr = NULL; 38025b3e1433Swyllys 38035b3e1433Swyllys if (pkey == NULL || attrib == NULL) 38045b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 38055b3e1433Swyllys 38065b3e1433Swyllys attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr); 38075b3e1433Swyllys if (attr != NULL) { 38085b3e1433Swyllys int i; 3809300fdee2SAndy Fiddaman 3810300fdee2SAndy Fiddaman if ((i = EVP_PKEY_get_attr_by_NID(pkey, nid, -1)) != -1) 3811300fdee2SAndy Fiddaman (void) EVP_PKEY_delete_attr(pkey, i); 3812300fdee2SAndy Fiddaman if (EVP_PKEY_add1_attr(pkey, attr) == 0) { 38135b3e1433Swyllys X509_ATTRIBUTE_free(attr); 38145b3e1433Swyllys return (KMF_ERR_MEMORY); 38155b3e1433Swyllys } 38165b3e1433Swyllys } else { 38175b3e1433Swyllys return (KMF_ERR_MEMORY); 38185b3e1433Swyllys } 38195b3e1433Swyllys 38205b3e1433Swyllys return (KMF_OK); 38215b3e1433Swyllys } 38225b3e1433Swyllys 38235b3e1433Swyllys static KMF_RETURN 38245b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen, 38255b3e1433Swyllys STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist) 38265b3e1433Swyllys { 38275b3e1433Swyllys KMF_RETURN ret = KMF_OK; 38285b3e1433Swyllys PKCS8_PRIV_KEY_INFO *p8 = NULL; 38295b3e1433Swyllys EVP_PKEY *pkey = NULL; 38305b3e1433Swyllys X509 *xcert = NULL; 3831300fdee2SAndy Fiddaman const ASN1_TYPE *keyid = NULL; 3832300fdee2SAndy Fiddaman const ASN1_TYPE *fname = NULL; 38335b3e1433Swyllys uchar_t *data = NULL; 38345b3e1433Swyllys 3835300fdee2SAndy Fiddaman keyid = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID); 3836300fdee2SAndy Fiddaman fname = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName); 38375b3e1433Swyllys 3838300fdee2SAndy Fiddaman switch (PKCS12_SAFEBAG_get_nid(bag)) { 38395b3e1433Swyllys case NID_keyBag: 38405b3e1433Swyllys if (keylist == NULL) 38415b3e1433Swyllys goto end; 3842300fdee2SAndy Fiddaman pkey = EVP_PKCS82PKEY( 3843300fdee2SAndy Fiddaman PKCS12_SAFEBAG_get0_p8inf(bag)); 38445b3e1433Swyllys if (pkey == NULL) 38455b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 38465b3e1433Swyllys 38475b3e1433Swyllys break; 38485b3e1433Swyllys case NID_pkcs8ShroudedKeyBag: 38495b3e1433Swyllys if (keylist == NULL) 38505b3e1433Swyllys goto end; 3851300fdee2SAndy Fiddaman p8 = PKCS12_decrypt_skey(bag, pass, passlen); 38525b3e1433Swyllys if (p8 == NULL) 38535b3e1433Swyllys return (KMF_ERR_AUTH_FAILED); 38545b3e1433Swyllys pkey = EVP_PKCS82PKEY(p8); 38555b3e1433Swyllys PKCS8_PRIV_KEY_INFO_free(p8); 38565b3e1433Swyllys if (pkey == NULL) 38575b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 38585b3e1433Swyllys break; 38595b3e1433Swyllys case NID_certBag: 38605b3e1433Swyllys if (certlist == NULL) 38615b3e1433Swyllys goto end; 3862300fdee2SAndy Fiddaman if (PKCS12_SAFEBAG_get_bag_nid(bag) != 3863300fdee2SAndy Fiddaman NID_x509Certificate) 38645b3e1433Swyllys return (KMF_ERR_PKCS12_FORMAT); 3865300fdee2SAndy Fiddaman xcert = PKCS12_SAFEBAG_get1_cert(bag); 38665b3e1433Swyllys if (xcert == NULL) { 38675b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 38685b3e1433Swyllys goto end; 38695b3e1433Swyllys } 38705b3e1433Swyllys if (keyid != NULL) { 38715b3e1433Swyllys if (X509_keyid_set1(xcert, 38725b3e1433Swyllys keyid->value.octet_string->data, 38735b3e1433Swyllys keyid->value.octet_string->length) == 0) { 38745b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 38755b3e1433Swyllys goto end; 38765b3e1433Swyllys } 38775b3e1433Swyllys } 38785b3e1433Swyllys if (fname != NULL) { 38795b3e1433Swyllys int len, r; 38805b3e1433Swyllys len = ASN1_STRING_to_UTF8(&data, 38815b3e1433Swyllys fname->value.asn1_string); 38825b3e1433Swyllys if (len > 0 && data != NULL) { 38835b3e1433Swyllys r = X509_alias_set1(xcert, data, len); 3884f810c7e5SToomas Soome if (r == 0) { 38855b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 38865b3e1433Swyllys goto end; 38875b3e1433Swyllys } 38885b3e1433Swyllys } else { 38895b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 38905b3e1433Swyllys goto end; 38915b3e1433Swyllys } 38925b3e1433Swyllys } 38935b3e1433Swyllys if (sk_X509_push(certlist, xcert) == 0) 38945b3e1433Swyllys ret = KMF_ERR_MEMORY; 38955b3e1433Swyllys else 38965b3e1433Swyllys xcert = NULL; 38975b3e1433Swyllys break; 38985b3e1433Swyllys case NID_safeContentsBag: 3899300fdee2SAndy Fiddaman return (openssl_parse_bags( 3900300fdee2SAndy Fiddaman PKCS12_SAFEBAG_get0_safes(bag), 3901300fdee2SAndy Fiddaman pass, keylist, certlist)); 39025b3e1433Swyllys default: 39035b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39045b3e1433Swyllys break; 39055b3e1433Swyllys } 39065b3e1433Swyllys 39075b3e1433Swyllys /* 39085b3e1433Swyllys * Set the ID and/or FriendlyName attributes on the key. 39095b3e1433Swyllys * If converting to PKCS11 objects, these can translate to CKA_ID 39105b3e1433Swyllys * and CKA_LABEL values. 39115b3e1433Swyllys */ 39125b3e1433Swyllys if (pkey != NULL && ret == KMF_OK) { 39135b3e1433Swyllys ASN1_TYPE *attr = NULL; 39145b3e1433Swyllys if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) { 39155b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) 39165b3e1433Swyllys return (KMF_ERR_MEMORY); 39175b3e1433Swyllys attr->value.octet_string = 39185b3e1433Swyllys ASN1_STRING_dup(keyid->value.octet_string); 39195b3e1433Swyllys attr->type = V_ASN1_OCTET_STRING; 39205b3e1433Swyllys attr->value.ptr = (char *)attr->value.octet_string; 39215b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_localKeyID); 39225b3e1433Swyllys OPENSSL_free(attr); 39235b3e1433Swyllys } 39245b3e1433Swyllys 39255b3e1433Swyllys if (ret == KMF_OK && fname != NULL && 39265b3e1433Swyllys fname->type == V_ASN1_BMPSTRING) { 39275b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) 39285b3e1433Swyllys return (KMF_ERR_MEMORY); 39295b3e1433Swyllys attr->value.bmpstring = 39305b3e1433Swyllys ASN1_STRING_dup(fname->value.bmpstring); 39315b3e1433Swyllys attr->type = V_ASN1_BMPSTRING; 39325b3e1433Swyllys attr->value.ptr = (char *)attr->value.bmpstring; 39335b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_friendlyName); 39345b3e1433Swyllys OPENSSL_free(attr); 39355b3e1433Swyllys } 39365b3e1433Swyllys 39375b3e1433Swyllys if (ret == KMF_OK && keylist != NULL && 39385b3e1433Swyllys sk_EVP_PKEY_push(keylist, pkey) == 0) 39395b3e1433Swyllys ret = KMF_ERR_MEMORY; 39405b3e1433Swyllys } 39415b3e1433Swyllys if (ret == KMF_OK && keylist != NULL) 39425b3e1433Swyllys pkey = NULL; 39435b3e1433Swyllys end: 39445b3e1433Swyllys if (pkey != NULL) 39455b3e1433Swyllys EVP_PKEY_free(pkey); 39465b3e1433Swyllys if (xcert != NULL) 39475b3e1433Swyllys X509_free(xcert); 39485b3e1433Swyllys if (data != NULL) 39495b3e1433Swyllys OPENSSL_free(data); 39505b3e1433Swyllys 39515b3e1433Swyllys return (ret); 39525b3e1433Swyllys } 39535b3e1433Swyllys 39545b3e1433Swyllys static KMF_RETURN 3955*4942e222SAndy Fiddaman openssl_pkcs12_parse(PKCS12 *p12, char *pin, STACK_OF(EVP_PKEY) *keys, 3956*4942e222SAndy Fiddaman STACK_OF(X509) *certs, STACK_OF(X509) *ca) 39575b3e1433Swyllys { 39585b3e1433Swyllys KMF_RETURN ret = KMF_OK; 39595b3e1433Swyllys STACK_OF(PKCS7) *asafes = NULL; 39605b3e1433Swyllys STACK_OF(PKCS12_SAFEBAG) *bags = NULL; 39615b3e1433Swyllys int i, bagnid; 39625b3e1433Swyllys PKCS7 *p7; 39635b3e1433Swyllys 39645b3e1433Swyllys if (p12 == NULL || (keys == NULL && certs == NULL)) 39655b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 39665b3e1433Swyllys 3967f810c7e5SToomas Soome if (pin == NULL || *pin == '\0') { 39685b3e1433Swyllys if (PKCS12_verify_mac(p12, NULL, 0)) { 39695b3e1433Swyllys pin = NULL; 39705b3e1433Swyllys } else if (PKCS12_verify_mac(p12, "", 0)) { 39715b3e1433Swyllys pin = ""; 39725b3e1433Swyllys } else { 39735b3e1433Swyllys return (KMF_ERR_AUTH_FAILED); 39745b3e1433Swyllys } 39755b3e1433Swyllys } else if (!PKCS12_verify_mac(p12, pin, -1)) { 39765b3e1433Swyllys return (KMF_ERR_AUTH_FAILED); 39775b3e1433Swyllys } 39785b3e1433Swyllys 39795b3e1433Swyllys if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) 39805b3e1433Swyllys return (KMF_ERR_PKCS12_FORMAT); 39815b3e1433Swyllys 39825b3e1433Swyllys for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) { 39835b3e1433Swyllys bags = NULL; 39845b3e1433Swyllys p7 = sk_PKCS7_value(asafes, i); 39855b3e1433Swyllys bagnid = OBJ_obj2nid(p7->type); 39865b3e1433Swyllys 39875b3e1433Swyllys if (bagnid == NID_pkcs7_data) { 39885b3e1433Swyllys bags = PKCS12_unpack_p7data(p7); 39895b3e1433Swyllys } else if (bagnid == NID_pkcs7_encrypted) { 39905b3e1433Swyllys bags = PKCS12_unpack_p7encdata(p7, pin, 39915b3e1433Swyllys (pin ? strlen(pin) : 0)); 39925b3e1433Swyllys } else { 39935b3e1433Swyllys continue; 39945b3e1433Swyllys } 39955b3e1433Swyllys if (bags == NULL) { 39965b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39975b3e1433Swyllys goto out; 39985b3e1433Swyllys } 39995b3e1433Swyllys 40005b3e1433Swyllys if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK) 40015b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 40025b3e1433Swyllys 40035b3e1433Swyllys sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 40045b3e1433Swyllys } 40055b3e1433Swyllys out: 40065b3e1433Swyllys if (asafes != NULL) 40075b3e1433Swyllys sk_PKCS7_pop_free(asafes, PKCS7_free); 40085b3e1433Swyllys 40095b3e1433Swyllys return (ret); 40105b3e1433Swyllys } 40115b3e1433Swyllys 401299ebb4caSwyllys /* 401399ebb4caSwyllys * Helper function to decrypt and parse PKCS#12 import file. 401499ebb4caSwyllys */ 401599ebb4caSwyllys static KMF_RETURN 401699ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen, 4017*4942e222SAndy Fiddaman STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs, STACK_OF(X509) **ca) 401899ebb4caSwyllys { 401999ebb4caSwyllys PKCS12 *pk12, *pk12_tmp; 40205b3e1433Swyllys STACK_OF(EVP_PKEY) *pkeylist = NULL; 40215b3e1433Swyllys STACK_OF(X509) *xcertlist = NULL; 40225b3e1433Swyllys STACK_OF(X509) *cacertlist = NULL; 402399ebb4caSwyllys 402499ebb4caSwyllys if ((pk12 = PKCS12_new()) == NULL) { 402599ebb4caSwyllys return (KMF_ERR_MEMORY); 402699ebb4caSwyllys } 402799ebb4caSwyllys 402899ebb4caSwyllys if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) { 402999ebb4caSwyllys /* This is ok; it seems to mean there is no more to read. */ 403099ebb4caSwyllys if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 && 403199ebb4caSwyllys ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG) 403299ebb4caSwyllys goto end_extract_pkcs12; 403399ebb4caSwyllys 403499ebb4caSwyllys PKCS12_free(pk12); 403599ebb4caSwyllys return (KMF_ERR_PKCS12_FORMAT); 403699ebb4caSwyllys } 403799ebb4caSwyllys pk12 = pk12_tmp; 403899ebb4caSwyllys 40395b3e1433Swyllys xcertlist = sk_X509_new_null(); 40405b3e1433Swyllys if (xcertlist == NULL) { 40415b3e1433Swyllys PKCS12_free(pk12); 40425b3e1433Swyllys return (KMF_ERR_MEMORY); 40435b3e1433Swyllys } 40445b3e1433Swyllys pkeylist = sk_EVP_PKEY_new_null(); 40455b3e1433Swyllys if (pkeylist == NULL) { 40465b3e1433Swyllys sk_X509_pop_free(xcertlist, X509_free); 40475b3e1433Swyllys PKCS12_free(pk12); 40485b3e1433Swyllys return (KMF_ERR_MEMORY); 40495b3e1433Swyllys } 40505b3e1433Swyllys 40515b3e1433Swyllys if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist, 40525b3e1433Swyllys cacertlist) != KMF_OK) { 40535b3e1433Swyllys sk_X509_pop_free(xcertlist, X509_free); 40545b3e1433Swyllys sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free); 405599ebb4caSwyllys PKCS12_free(pk12); 405699ebb4caSwyllys return (KMF_ERR_PKCS12_FORMAT); 405799ebb4caSwyllys } 405899ebb4caSwyllys 40595b3e1433Swyllys if (priv_key && pkeylist) 40605b3e1433Swyllys *priv_key = pkeylist; 40615b3e1433Swyllys else if (pkeylist) 40625b3e1433Swyllys sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free); 40635b3e1433Swyllys if (certs && xcertlist) 40645b3e1433Swyllys *certs = xcertlist; 40655b3e1433Swyllys else if (xcertlist) 40665b3e1433Swyllys sk_X509_pop_free(xcertlist, X509_free); 40675b3e1433Swyllys if (ca && cacertlist) 40685b3e1433Swyllys *ca = cacertlist; 40695b3e1433Swyllys else if (cacertlist) 40705b3e1433Swyllys sk_X509_pop_free(cacertlist, X509_free); 407199ebb4caSwyllys 40725b3e1433Swyllys end_extract_pkcs12: 407399ebb4caSwyllys 407499ebb4caSwyllys PKCS12_free(pk12); 407599ebb4caSwyllys return (KMF_OK); 407699ebb4caSwyllys } 407799ebb4caSwyllys 407899ebb4caSwyllys static KMF_RETURN 407999ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to) 408099ebb4caSwyllys { 408199ebb4caSwyllys KMF_RETURN rv = KMF_OK; 408299ebb4caSwyllys uint32_t sz; 408399ebb4caSwyllys 408499ebb4caSwyllys sz = BN_num_bytes(from); 408599ebb4caSwyllys to->val = (uchar_t *)malloc(sz); 408699ebb4caSwyllys if (to->val == NULL) 408799ebb4caSwyllys return (KMF_ERR_MEMORY); 408899ebb4caSwyllys 408999ebb4caSwyllys if ((to->len = BN_bn2bin(from, to->val)) != sz) { 409099ebb4caSwyllys free(to->val); 409199ebb4caSwyllys to->val = NULL; 409299ebb4caSwyllys to->len = 0; 409399ebb4caSwyllys rv = KMF_ERR_MEMORY; 409499ebb4caSwyllys } 409599ebb4caSwyllys 409699ebb4caSwyllys return (rv); 409799ebb4caSwyllys } 409899ebb4caSwyllys 409999ebb4caSwyllys static KMF_RETURN 410099ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key) 410199ebb4caSwyllys { 410299ebb4caSwyllys KMF_RETURN rv; 410399ebb4caSwyllys KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa; 410499ebb4caSwyllys 4105300fdee2SAndy Fiddaman const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmpq, *iqmp; 4106300fdee2SAndy Fiddaman 4107300fdee2SAndy Fiddaman RSA_get0_key(rsa, &n, &e, &d); 4108300fdee2SAndy Fiddaman RSA_get0_factors(rsa, &p, &q); 4109300fdee2SAndy Fiddaman RSA_get0_crt_params(rsa, &dmp1, &dmpq, &iqmp); 4110300fdee2SAndy Fiddaman 411199ebb4caSwyllys (void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY)); 4112300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)n, &kmfkey->mod)) != KMF_OK) 411399ebb4caSwyllys goto cleanup; 411499ebb4caSwyllys 4115300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)e, &kmfkey->pubexp)) != KMF_OK) 411699ebb4caSwyllys goto cleanup; 411799ebb4caSwyllys 4118300fdee2SAndy Fiddaman if (d != NULL) 4119300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)d, &kmfkey->priexp)) != KMF_OK) 412099ebb4caSwyllys goto cleanup; 412199ebb4caSwyllys 4122300fdee2SAndy Fiddaman if (p != NULL) 4123300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime1)) != KMF_OK) 412499ebb4caSwyllys goto cleanup; 412599ebb4caSwyllys 4126300fdee2SAndy Fiddaman if (q != NULL) 4127300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->prime2)) != KMF_OK) 412899ebb4caSwyllys goto cleanup; 412999ebb4caSwyllys 4130300fdee2SAndy Fiddaman if (dmp1 != NULL) 4131300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)dmp1, &kmfkey->exp1)) != KMF_OK) 413299ebb4caSwyllys goto cleanup; 413399ebb4caSwyllys 4134300fdee2SAndy Fiddaman if (dmpq != NULL) 4135300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)dmpq, &kmfkey->exp2)) != KMF_OK) 413699ebb4caSwyllys goto cleanup; 413799ebb4caSwyllys 4138300fdee2SAndy Fiddaman if (iqmp != NULL) 4139300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)iqmp, &kmfkey->coef)) != KMF_OK) 414099ebb4caSwyllys goto cleanup; 414199ebb4caSwyllys cleanup: 414299ebb4caSwyllys if (rv != KMF_OK) 414330a5e8faSwyllys kmf_free_raw_key(key); 414499ebb4caSwyllys else 414599ebb4caSwyllys key->keytype = KMF_RSA; 414699ebb4caSwyllys 414799ebb4caSwyllys /* 414899ebb4caSwyllys * Free the reference to this key, SSL will not actually free 414999ebb4caSwyllys * the memory until the refcount == 0, so this is safe. 415099ebb4caSwyllys */ 415199ebb4caSwyllys RSA_free(rsa); 415299ebb4caSwyllys 415399ebb4caSwyllys return (rv); 415499ebb4caSwyllys } 415599ebb4caSwyllys 415699ebb4caSwyllys static KMF_RETURN 415799ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key) 415899ebb4caSwyllys { 415999ebb4caSwyllys KMF_RETURN rv; 416099ebb4caSwyllys KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa; 4161300fdee2SAndy Fiddaman const BIGNUM *p, *q, *g, *priv_key; 4162300fdee2SAndy Fiddaman 4163300fdee2SAndy Fiddaman DSA_get0_pqg(dsa, &p, &q, &g); 4164300fdee2SAndy Fiddaman DSA_get0_key(dsa, NULL, &priv_key); 416599ebb4caSwyllys 416699ebb4caSwyllys (void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY)); 4167300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime)) != KMF_OK) 416899ebb4caSwyllys goto cleanup; 416999ebb4caSwyllys 4170300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->subprime)) != KMF_OK) 417199ebb4caSwyllys goto cleanup; 417299ebb4caSwyllys 4173300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)g, &kmfkey->base)) != KMF_OK) 417499ebb4caSwyllys goto cleanup; 417599ebb4caSwyllys 4176300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)priv_key, &kmfkey->value)) != KMF_OK) 417799ebb4caSwyllys goto cleanup; 417899ebb4caSwyllys 417999ebb4caSwyllys cleanup: 418099ebb4caSwyllys if (rv != KMF_OK) 418130a5e8faSwyllys kmf_free_raw_key(key); 418299ebb4caSwyllys else 418399ebb4caSwyllys key->keytype = KMF_DSA; 418499ebb4caSwyllys 418599ebb4caSwyllys /* 418699ebb4caSwyllys * Free the reference to this key, SSL will not actually free 418799ebb4caSwyllys * the memory until the refcount == 0, so this is safe. 418899ebb4caSwyllys */ 418999ebb4caSwyllys DSA_free(dsa); 419099ebb4caSwyllys 419199ebb4caSwyllys return (rv); 419299ebb4caSwyllys } 419399ebb4caSwyllys 419499ebb4caSwyllys static KMF_RETURN 419599ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert, 41965b3e1433Swyllys KMF_X509_DER_CERT **certlist, int *ncerts) 419799ebb4caSwyllys { 419899ebb4caSwyllys KMF_RETURN rv = KMF_OK; 41995b3e1433Swyllys KMF_X509_DER_CERT *list = (*certlist); 42005b3e1433Swyllys KMF_X509_DER_CERT cert; 420199ebb4caSwyllys int n = (*ncerts); 420299ebb4caSwyllys 420399ebb4caSwyllys if (list == NULL) { 42045b3e1433Swyllys list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT)); 420599ebb4caSwyllys } else { 42065b3e1433Swyllys list = (KMF_X509_DER_CERT *)realloc(list, 42075b3e1433Swyllys sizeof (KMF_X509_DER_CERT) * (n + 1)); 420899ebb4caSwyllys } 420999ebb4caSwyllys 421099ebb4caSwyllys if (list == NULL) 421199ebb4caSwyllys return (KMF_ERR_MEMORY); 421299ebb4caSwyllys 42135b3e1433Swyllys (void) memset(&cert, 0, sizeof (cert)); 42145b3e1433Swyllys rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate); 421599ebb4caSwyllys if (rv == KMF_OK) { 42165b3e1433Swyllys int len = 0; 42175b3e1433Swyllys /* Get the alias name for the cert if there is one */ 42185b3e1433Swyllys char *a = (char *)X509_alias_get0(sslcert, &len); 42195b3e1433Swyllys if (a != NULL) 42205b3e1433Swyllys cert.kmf_private.label = strdup(a); 42215b3e1433Swyllys cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL; 42225b3e1433Swyllys 422399ebb4caSwyllys list[n] = cert; 422499ebb4caSwyllys (*ncerts) = n + 1; 422599ebb4caSwyllys 422699ebb4caSwyllys *certlist = list; 422799ebb4caSwyllys } else { 422899ebb4caSwyllys free(list); 422999ebb4caSwyllys } 423099ebb4caSwyllys 423199ebb4caSwyllys return (rv); 423299ebb4caSwyllys } 423399ebb4caSwyllys 423499ebb4caSwyllys static KMF_RETURN 423599ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist, 423699ebb4caSwyllys KMF_RAW_KEY_DATA *newkey, int *nkeys) 423799ebb4caSwyllys { 423899ebb4caSwyllys KMF_RAW_KEY_DATA *list = (*keylist); 423999ebb4caSwyllys int n = (*nkeys); 424099ebb4caSwyllys 424199ebb4caSwyllys if (list == NULL) { 424299ebb4caSwyllys list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA)); 424399ebb4caSwyllys } else { 424499ebb4caSwyllys list = (KMF_RAW_KEY_DATA *)realloc(list, 424599ebb4caSwyllys sizeof (KMF_RAW_KEY_DATA) * (n + 1)); 424699ebb4caSwyllys } 424799ebb4caSwyllys 424899ebb4caSwyllys if (list == NULL) 424999ebb4caSwyllys return (KMF_ERR_MEMORY); 425099ebb4caSwyllys 425199ebb4caSwyllys list[n] = *newkey; 425299ebb4caSwyllys (*nkeys) = n + 1; 425399ebb4caSwyllys 425499ebb4caSwyllys *keylist = list; 425599ebb4caSwyllys 425699ebb4caSwyllys return (KMF_OK); 425799ebb4caSwyllys } 425899ebb4caSwyllys 425930a5e8faSwyllys static KMF_RETURN 426030a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key) 426130a5e8faSwyllys { 426230a5e8faSwyllys KMF_RETURN rv = KMF_OK; 42635b3e1433Swyllys X509_ATTRIBUTE *attr; 4264300fdee2SAndy Fiddaman RSA *rsa; 4265300fdee2SAndy Fiddaman DSA *dsa; 4266300fdee2SAndy Fiddaman int loc; 426730a5e8faSwyllys 426830a5e8faSwyllys if (pkey == NULL || key == NULL) 426930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 427030a5e8faSwyllys /* Convert SSL key to raw key */ 4271300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get1_RSA(pkey)) != NULL) { 4272300fdee2SAndy Fiddaman rv = exportRawRSAKey(rsa, key); 427330a5e8faSwyllys if (rv != KMF_OK) 427430a5e8faSwyllys return (rv); 4275300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get1_DSA(pkey)) != NULL) { 4276300fdee2SAndy Fiddaman rv = exportRawDSAKey(dsa, key); 427730a5e8faSwyllys if (rv != KMF_OK) 427830a5e8faSwyllys return (rv); 4279300fdee2SAndy Fiddaman } else 428030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 4281300fdee2SAndy Fiddaman 42825b3e1433Swyllys /* 42835b3e1433Swyllys * If friendlyName, add it to record. 42845b3e1433Swyllys */ 4285300fdee2SAndy Fiddaman 4286300fdee2SAndy Fiddaman if ((loc = EVP_PKEY_get_attr_by_NID(pkey, 4287300fdee2SAndy Fiddaman NID_friendlyName, -1)) != -1 && 4288300fdee2SAndy Fiddaman (attr = EVP_PKEY_get_attr(pkey, loc))) { 42895b3e1433Swyllys ASN1_TYPE *ty = NULL; 4290300fdee2SAndy Fiddaman int numattr = X509_ATTRIBUTE_count(attr); 4291300fdee2SAndy Fiddaman if (numattr > 0) { 4292300fdee2SAndy Fiddaman ty = X509_ATTRIBUTE_get0_type(attr, 0); 42935b3e1433Swyllys } 42945b3e1433Swyllys if (ty != NULL) { 429570f9559bSTheo Schlossnagle key->label = OPENSSL_uni2asc(ty->value.bmpstring->data, 429670f9559bSTheo Schlossnagle ty->value.bmpstring->length); 42975b3e1433Swyllys } 42985b3e1433Swyllys } else { 42995b3e1433Swyllys key->label = NULL; 43005b3e1433Swyllys } 43015b3e1433Swyllys 43025b3e1433Swyllys /* 43035b3e1433Swyllys * If KeyID, add it to record as a KMF_DATA object. 43045b3e1433Swyllys */ 4305300fdee2SAndy Fiddaman if ((loc = EVP_PKEY_get_attr_by_NID(pkey, 4306300fdee2SAndy Fiddaman NID_localKeyID, -1)) != -1 && 4307300fdee2SAndy Fiddaman (attr = EVP_PKEY_get_attr(pkey, loc)) != NULL) { 43085b3e1433Swyllys ASN1_TYPE *ty = NULL; 4309300fdee2SAndy Fiddaman int numattr = X509_ATTRIBUTE_count(attr); 4310300fdee2SAndy Fiddaman if (numattr > 0) 4311300fdee2SAndy Fiddaman ty = X509_ATTRIBUTE_get0_type(attr, 0); 43125b3e1433Swyllys key->id.Data = (uchar_t *)malloc( 43135b3e1433Swyllys ty->value.octet_string->length); 43145b3e1433Swyllys if (key->id.Data == NULL) 43155b3e1433Swyllys return (KMF_ERR_MEMORY); 43165b3e1433Swyllys (void) memcpy(key->id.Data, ty->value.octet_string->data, 43175b3e1433Swyllys ty->value.octet_string->length); 43185b3e1433Swyllys key->id.Length = ty->value.octet_string->length; 43195b3e1433Swyllys } else { 43205b3e1433Swyllys (void) memset(&key->id, 0, sizeof (KMF_DATA)); 43215b3e1433Swyllys } 432230a5e8faSwyllys 432330a5e8faSwyllys return (rv); 432430a5e8faSwyllys } 432599ebb4caSwyllys 432699ebb4caSwyllys static KMF_RETURN 432799ebb4caSwyllys convertPK12Objects( 432899ebb4caSwyllys KMF_HANDLE *kmfh, 43295b3e1433Swyllys STACK_OF(EVP_PKEY) *sslkeys, 43305b3e1433Swyllys STACK_OF(X509) *sslcert, 43315b3e1433Swyllys STACK_OF(X509) *sslcacerts, 433299ebb4caSwyllys KMF_RAW_KEY_DATA **keylist, int *nkeys, 43335b3e1433Swyllys KMF_X509_DER_CERT **certlist, int *ncerts) 433499ebb4caSwyllys { 433599ebb4caSwyllys KMF_RETURN rv = KMF_OK; 433699ebb4caSwyllys KMF_RAW_KEY_DATA key; 433799ebb4caSwyllys int i; 433899ebb4caSwyllys 43395b3e1433Swyllys for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) { 43405b3e1433Swyllys EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i); 43415b3e1433Swyllys rv = convertToRawKey(pkey, &key); 434230a5e8faSwyllys if (rv == KMF_OK) 434399ebb4caSwyllys rv = add_key_to_list(keylist, &key, nkeys); 434430a5e8faSwyllys 434599ebb4caSwyllys if (rv != KMF_OK) 434699ebb4caSwyllys return (rv); 434799ebb4caSwyllys } 434899ebb4caSwyllys 434999ebb4caSwyllys /* Now add the certificate to the certlist */ 43505b3e1433Swyllys for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) { 43515b3e1433Swyllys X509 *cert = sk_X509_value(sslcert, i); 43525b3e1433Swyllys rv = add_cert_to_list(kmfh, cert, certlist, ncerts); 435399ebb4caSwyllys if (rv != KMF_OK) 435499ebb4caSwyllys return (rv); 435599ebb4caSwyllys } 435699ebb4caSwyllys 435799ebb4caSwyllys /* Also add any included CA certs to the list */ 435871593db2Swyllys for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) { 435999ebb4caSwyllys X509 *c; 436099ebb4caSwyllys /* 436199ebb4caSwyllys * sk_X509_value() is macro that embeds a cast to (X509 *). 436299ebb4caSwyllys * Here it translates into ((X509 *)sk_value((ca), (i))). 436399ebb4caSwyllys * Lint is complaining about the embedded casting, and 436499ebb4caSwyllys * to fix it, you need to fix openssl header files. 436599ebb4caSwyllys */ 436699ebb4caSwyllys c = sk_X509_value(sslcacerts, i); 436799ebb4caSwyllys 436899ebb4caSwyllys /* Now add the ca cert to the certlist */ 436999ebb4caSwyllys rv = add_cert_to_list(kmfh, c, certlist, ncerts); 437099ebb4caSwyllys if (rv != KMF_OK) 437199ebb4caSwyllys return (rv); 437299ebb4caSwyllys } 437399ebb4caSwyllys return (rv); 437499ebb4caSwyllys } 437599ebb4caSwyllys 437699ebb4caSwyllys KMF_RETURN 4377*4942e222SAndy Fiddaman openssl_import_objects(KMF_HANDLE *kmfh, char *filename, KMF_CREDENTIAL *cred, 43785b3e1433Swyllys KMF_X509_DER_CERT **certlist, int *ncerts, 437999ebb4caSwyllys KMF_RAW_KEY_DATA **keylist, int *nkeys) 438099ebb4caSwyllys { 438199ebb4caSwyllys KMF_RETURN rv = KMF_OK; 438230a5e8faSwyllys KMF_ENCODE_FORMAT format; 438330a5e8faSwyllys BIO *bio = NULL; 43845b3e1433Swyllys STACK_OF(EVP_PKEY) *privkeys = NULL; 43855b3e1433Swyllys STACK_OF(X509) *certs = NULL; 438699ebb4caSwyllys STACK_OF(X509) *cacerts = NULL; 438799ebb4caSwyllys 438830a5e8faSwyllys /* 438930a5e8faSwyllys * auto-detect the file format, regardless of what 439030a5e8faSwyllys * the 'format' parameters in the params say. 439130a5e8faSwyllys */ 439230a5e8faSwyllys rv = kmf_get_file_format(filename, &format); 439330a5e8faSwyllys if (rv != KMF_OK) { 439430a5e8faSwyllys return (rv); 439530a5e8faSwyllys } 439630a5e8faSwyllys 439730a5e8faSwyllys /* This function only works for PEM or PKCS#12 files */ 439830a5e8faSwyllys if (format != KMF_FORMAT_PEM && 439930a5e8faSwyllys format != KMF_FORMAT_PEM_KEYPAIR && 440030a5e8faSwyllys format != KMF_FORMAT_PKCS12) 440130a5e8faSwyllys return (KMF_ERR_ENCODING); 440230a5e8faSwyllys 440330a5e8faSwyllys *certlist = NULL; 440430a5e8faSwyllys *keylist = NULL; 440530a5e8faSwyllys *ncerts = 0; 440630a5e8faSwyllys *nkeys = 0; 440730a5e8faSwyllys 440830a5e8faSwyllys if (format == KMF_FORMAT_PKCS12) { 440999ebb4caSwyllys bio = BIO_new_file(filename, "rb"); 441099ebb4caSwyllys if (bio == NULL) { 441199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 441299ebb4caSwyllys rv = KMF_ERR_OPEN_FILE; 441399ebb4caSwyllys goto end; 441499ebb4caSwyllys } 441599ebb4caSwyllys 441634acef67Swyllys rv = extract_pkcs12(bio, (uchar_t *)cred->cred, 44175b3e1433Swyllys (uint32_t)cred->credlen, &privkeys, &certs, &cacerts); 441899ebb4caSwyllys 441999ebb4caSwyllys if (rv == KMF_OK) 442099ebb4caSwyllys /* Convert keys and certs to exportable format */ 44215b3e1433Swyllys rv = convertPK12Objects(kmfh, privkeys, certs, cacerts, 442299ebb4caSwyllys keylist, nkeys, certlist, ncerts); 442330a5e8faSwyllys } else { 44245b3e1433Swyllys EVP_PKEY *pkey; 44255b3e1433Swyllys KMF_DATA *certdata = NULL; 44265b3e1433Swyllys KMF_X509_DER_CERT *kmfcerts = NULL; 44275b3e1433Swyllys int i; 442830a5e8faSwyllys rv = extract_pem(kmfh, NULL, NULL, NULL, filename, 442934acef67Swyllys (uchar_t *)cred->cred, (uint32_t)cred->credlen, 44305b3e1433Swyllys &pkey, &certdata, ncerts); 443171593db2Swyllys 443271593db2Swyllys /* Reached end of import file? */ 44335b3e1433Swyllys if (rv == KMF_OK && pkey != NULL) { 44345b3e1433Swyllys privkeys = sk_EVP_PKEY_new_null(); 44355b3e1433Swyllys if (privkeys == NULL) { 44365b3e1433Swyllys rv = KMF_ERR_MEMORY; 44375b3e1433Swyllys goto end; 44385b3e1433Swyllys } 44395b3e1433Swyllys (void) sk_EVP_PKEY_push(privkeys, pkey); 44405b3e1433Swyllys /* convert the certificate list here */ 44415b3e1433Swyllys if (*ncerts > 0 && certlist != NULL) { 4442e65e5c2dSWyllys Ingersoll kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts, 44435b3e1433Swyllys sizeof (KMF_X509_DER_CERT)); 44445b3e1433Swyllys if (kmfcerts == NULL) { 44455b3e1433Swyllys rv = KMF_ERR_MEMORY; 44465b3e1433Swyllys goto end; 44475b3e1433Swyllys } 44485b3e1433Swyllys for (i = 0; i < *ncerts; i++) { 44495b3e1433Swyllys kmfcerts[i].certificate = certdata[i]; 44505b3e1433Swyllys kmfcerts[i].kmf_private.keystore_type = 44515b3e1433Swyllys KMF_KEYSTORE_OPENSSL; 44525b3e1433Swyllys } 44535b3e1433Swyllys *certlist = kmfcerts; 44545b3e1433Swyllys } 44555b3e1433Swyllys /* 44565b3e1433Swyllys * Convert keys to exportable format, the certs 44575b3e1433Swyllys * are already OK. 44585b3e1433Swyllys */ 44595b3e1433Swyllys rv = convertPK12Objects(kmfh, privkeys, NULL, NULL, 446071593db2Swyllys keylist, nkeys, NULL, NULL); 446130a5e8faSwyllys } 44625b3e1433Swyllys } 446371593db2Swyllys end: 446430a5e8faSwyllys if (bio != NULL) 446599ebb4caSwyllys (void) BIO_free(bio); 446699ebb4caSwyllys 44675b3e1433Swyllys if (privkeys) 44685b3e1433Swyllys sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free); 44695b3e1433Swyllys if (certs) 44705b3e1433Swyllys sk_X509_pop_free(certs, X509_free); 447130a5e8faSwyllys if (cacerts) 44725b3e1433Swyllys sk_X509_pop_free(cacerts, X509_free); 447330a5e8faSwyllys 447499ebb4caSwyllys return (rv); 447599ebb4caSwyllys } 447699ebb4caSwyllys 447799ebb4caSwyllys static KMF_RETURN 447899ebb4caSwyllys create_deskey(DES_cblock **deskey) 447999ebb4caSwyllys { 448099ebb4caSwyllys DES_cblock *key; 448199ebb4caSwyllys 448299ebb4caSwyllys key = (DES_cblock *) malloc(sizeof (DES_cblock)); 448399ebb4caSwyllys if (key == NULL) { 448499ebb4caSwyllys return (KMF_ERR_MEMORY); 448599ebb4caSwyllys } 448699ebb4caSwyllys 448799ebb4caSwyllys if (DES_random_key(key) == 0) { 448899ebb4caSwyllys free(key); 448999ebb4caSwyllys return (KMF_ERR_KEYGEN_FAILED); 449099ebb4caSwyllys } 449199ebb4caSwyllys 449299ebb4caSwyllys *deskey = key; 449399ebb4caSwyllys return (KMF_OK); 449499ebb4caSwyllys } 449599ebb4caSwyllys 449699ebb4caSwyllys #define KEYGEN_RETRY 3 449799ebb4caSwyllys #define DES3_KEY_SIZE 24 449899ebb4caSwyllys 449999ebb4caSwyllys static KMF_RETURN 450099ebb4caSwyllys create_des3key(unsigned char **des3key) 450199ebb4caSwyllys { 450299ebb4caSwyllys KMF_RETURN ret = KMF_OK; 450399ebb4caSwyllys DES_cblock *deskey1 = NULL; 450499ebb4caSwyllys DES_cblock *deskey2 = NULL; 450599ebb4caSwyllys DES_cblock *deskey3 = NULL; 450699ebb4caSwyllys unsigned char *newkey = NULL; 450799ebb4caSwyllys int retry; 450899ebb4caSwyllys 450999ebb4caSwyllys if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) { 451099ebb4caSwyllys return (KMF_ERR_MEMORY); 451199ebb4caSwyllys } 451299ebb4caSwyllys 451399ebb4caSwyllys /* create the 1st DES key */ 451499ebb4caSwyllys if ((ret = create_deskey(&deskey1)) != KMF_OK) { 451599ebb4caSwyllys goto out; 451699ebb4caSwyllys } 451799ebb4caSwyllys 451899ebb4caSwyllys /* 451999ebb4caSwyllys * Create the 2nd DES key and make sure its value is different 452099ebb4caSwyllys * from the 1st DES key. 452199ebb4caSwyllys */ 452299ebb4caSwyllys retry = 0; 452399ebb4caSwyllys do { 452499ebb4caSwyllys if (deskey2 != NULL) { 452599ebb4caSwyllys free(deskey2); 452699ebb4caSwyllys deskey2 = NULL; 452799ebb4caSwyllys } 452899ebb4caSwyllys 452999ebb4caSwyllys if ((ret = create_deskey(&deskey2)) != KMF_OK) { 453099ebb4caSwyllys goto out; 453199ebb4caSwyllys } 453299ebb4caSwyllys 453399ebb4caSwyllys if (memcmp((const void *) deskey1, (const void *) deskey2, 8) 453499ebb4caSwyllys == 0) { 453599ebb4caSwyllys ret = KMF_ERR_KEYGEN_FAILED; 453699ebb4caSwyllys retry++; 453799ebb4caSwyllys } 453899ebb4caSwyllys } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY); 453999ebb4caSwyllys 454099ebb4caSwyllys if (ret != KMF_OK) { 454199ebb4caSwyllys goto out; 454299ebb4caSwyllys } 454399ebb4caSwyllys 454499ebb4caSwyllys /* 454599ebb4caSwyllys * Create the 3rd DES key and make sure its value is different 454699ebb4caSwyllys * from the 2nd DES key. 454799ebb4caSwyllys */ 454899ebb4caSwyllys retry = 0; 454999ebb4caSwyllys do { 455099ebb4caSwyllys if (deskey3 != NULL) { 455199ebb4caSwyllys free(deskey3); 455299ebb4caSwyllys deskey3 = NULL; 455399ebb4caSwyllys } 455499ebb4caSwyllys 455599ebb4caSwyllys if ((ret = create_deskey(&deskey3)) != KMF_OK) { 455699ebb4caSwyllys goto out; 455799ebb4caSwyllys } 455899ebb4caSwyllys 455999ebb4caSwyllys if (memcmp((const void *)deskey2, (const void *)deskey3, 8) 456099ebb4caSwyllys == 0) { 456199ebb4caSwyllys ret = KMF_ERR_KEYGEN_FAILED; 456299ebb4caSwyllys retry++; 456399ebb4caSwyllys } 456499ebb4caSwyllys } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY); 456599ebb4caSwyllys 456699ebb4caSwyllys if (ret != KMF_OK) { 456799ebb4caSwyllys goto out; 456899ebb4caSwyllys } 456999ebb4caSwyllys 457099ebb4caSwyllys /* Concatenate 3 DES keys into a DES3 key */ 457199ebb4caSwyllys (void) memcpy((void *)newkey, (const void *)deskey1, 8); 457299ebb4caSwyllys (void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8); 457399ebb4caSwyllys (void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8); 457499ebb4caSwyllys *des3key = newkey; 457599ebb4caSwyllys 457699ebb4caSwyllys out: 457799ebb4caSwyllys if (deskey1 != NULL) 457899ebb4caSwyllys free(deskey1); 457999ebb4caSwyllys 458099ebb4caSwyllys if (deskey2 != NULL) 458199ebb4caSwyllys free(deskey2); 458299ebb4caSwyllys 458399ebb4caSwyllys if (deskey3 != NULL) 458499ebb4caSwyllys free(deskey3); 458599ebb4caSwyllys 458699ebb4caSwyllys if (ret != KMF_OK && newkey != NULL) 458799ebb4caSwyllys free(newkey); 458899ebb4caSwyllys 458999ebb4caSwyllys return (ret); 459099ebb4caSwyllys } 459199ebb4caSwyllys 459299ebb4caSwyllys KMF_RETURN 4593*4942e222SAndy Fiddaman OpenSSL_CreateSymKey(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 459499ebb4caSwyllys { 459599ebb4caSwyllys KMF_RETURN ret = KMF_OK; 459699ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 459799ebb4caSwyllys char *fullpath = NULL; 459899ebb4caSwyllys KMF_RAW_SYM_KEY *rkey = NULL; 459999ebb4caSwyllys DES_cblock *deskey = NULL; 460099ebb4caSwyllys unsigned char *des3key = NULL; 460199ebb4caSwyllys unsigned char *random = NULL; 460299ebb4caSwyllys int fd = -1; 460330a5e8faSwyllys KMF_KEY_HANDLE *symkey; 460430a5e8faSwyllys KMF_KEY_ALG keytype; 460530a5e8faSwyllys uint32_t keylen; 460630a5e8faSwyllys uint32_t keylen_size = sizeof (keylen); 460730a5e8faSwyllys char *dirpath; 460830a5e8faSwyllys char *keyfile; 460999ebb4caSwyllys 461099ebb4caSwyllys if (kmfh == NULL) 461199ebb4caSwyllys return (KMF_ERR_UNINITIALIZED); 461299ebb4caSwyllys 461330a5e8faSwyllys symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 461430a5e8faSwyllys if (symkey == NULL) 461599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 461699ebb4caSwyllys 461730a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 461830a5e8faSwyllys 461930a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 462030a5e8faSwyllys if (keyfile == NULL) 462130a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 462230a5e8faSwyllys 462330a5e8faSwyllys ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, 462430a5e8faSwyllys (void *)&keytype, NULL); 462530a5e8faSwyllys if (ret != KMF_OK) 462630a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 462730a5e8faSwyllys 462830a5e8faSwyllys ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, 462930a5e8faSwyllys &keylen, &keylen_size); 463030a5e8faSwyllys if (ret == KMF_ERR_ATTR_NOT_FOUND && 463130a5e8faSwyllys (keytype == KMF_DES || keytype == KMF_DES3)) 463230a5e8faSwyllys /* keylength is not required for DES and 3DES */ 463330a5e8faSwyllys ret = KMF_OK; 463430a5e8faSwyllys if (ret != KMF_OK) 463530a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 463630a5e8faSwyllys 463730a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 463899ebb4caSwyllys if (fullpath == NULL) 463999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 464099ebb4caSwyllys 464199ebb4caSwyllys /* If the requested file exists, return an error */ 464230a5e8faSwyllys if (test_for_file(fullpath, 0400) == 1) { 464399ebb4caSwyllys free(fullpath); 464499ebb4caSwyllys return (KMF_ERR_DUPLICATE_KEYFILE); 464599ebb4caSwyllys } 464699ebb4caSwyllys 464799ebb4caSwyllys fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400); 464899ebb4caSwyllys if (fd == -1) { 464999ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 465099ebb4caSwyllys goto out; 465199ebb4caSwyllys } 465299ebb4caSwyllys 465399ebb4caSwyllys rkey = malloc(sizeof (KMF_RAW_SYM_KEY)); 465499ebb4caSwyllys if (rkey == NULL) { 465599ebb4caSwyllys ret = KMF_ERR_MEMORY; 465699ebb4caSwyllys goto out; 465799ebb4caSwyllys } 465899ebb4caSwyllys (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 465999ebb4caSwyllys 466030a5e8faSwyllys if (keytype == KMF_DES) { 466199ebb4caSwyllys if ((ret = create_deskey(&deskey)) != KMF_OK) { 466299ebb4caSwyllys goto out; 466399ebb4caSwyllys } 466499ebb4caSwyllys rkey->keydata.val = (uchar_t *)deskey; 466599ebb4caSwyllys rkey->keydata.len = 8; 466699ebb4caSwyllys 466799ebb4caSwyllys symkey->keyalg = KMF_DES; 466899ebb4caSwyllys 466930a5e8faSwyllys } else if (keytype == KMF_DES3) { 467099ebb4caSwyllys if ((ret = create_des3key(&des3key)) != KMF_OK) { 467199ebb4caSwyllys goto out; 467299ebb4caSwyllys } 467399ebb4caSwyllys rkey->keydata.val = (uchar_t *)des3key; 467499ebb4caSwyllys rkey->keydata.len = DES3_KEY_SIZE; 467599ebb4caSwyllys symkey->keyalg = KMF_DES3; 46769b37d296Swyllys 467730a5e8faSwyllys } else if (keytype == KMF_AES || keytype == KMF_RC4 || 467830a5e8faSwyllys keytype == KMF_GENERIC_SECRET) { 467999ebb4caSwyllys int bytes; 468099ebb4caSwyllys 468130a5e8faSwyllys if (keylen % 8 != 0) { 468299ebb4caSwyllys ret = KMF_ERR_BAD_KEY_SIZE; 468399ebb4caSwyllys goto out; 468499ebb4caSwyllys } 468599ebb4caSwyllys 468630a5e8faSwyllys if (keytype == KMF_AES) { 468730a5e8faSwyllys if (keylen != 128 && 468830a5e8faSwyllys keylen != 192 && 468930a5e8faSwyllys keylen != 256) { 469099ebb4caSwyllys ret = KMF_ERR_BAD_KEY_SIZE; 469199ebb4caSwyllys goto out; 469299ebb4caSwyllys } 469399ebb4caSwyllys } 469499ebb4caSwyllys 469530a5e8faSwyllys bytes = keylen/8; 469699ebb4caSwyllys random = malloc(bytes); 469799ebb4caSwyllys if (random == NULL) { 469899ebb4caSwyllys ret = KMF_ERR_MEMORY; 469999ebb4caSwyllys goto out; 470099ebb4caSwyllys } 470199ebb4caSwyllys if (RAND_bytes(random, bytes) != 1) { 470299ebb4caSwyllys ret = KMF_ERR_KEYGEN_FAILED; 470399ebb4caSwyllys goto out; 470499ebb4caSwyllys } 470599ebb4caSwyllys 470699ebb4caSwyllys rkey->keydata.val = (uchar_t *)random; 470799ebb4caSwyllys rkey->keydata.len = bytes; 470830a5e8faSwyllys symkey->keyalg = keytype; 470999ebb4caSwyllys 471099ebb4caSwyllys } else { 471199ebb4caSwyllys ret = KMF_ERR_BAD_KEY_TYPE; 471299ebb4caSwyllys goto out; 471399ebb4caSwyllys } 471499ebb4caSwyllys 471599ebb4caSwyllys (void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len); 471699ebb4caSwyllys 471799ebb4caSwyllys symkey->kstype = KMF_KEYSTORE_OPENSSL; 471899ebb4caSwyllys symkey->keyclass = KMF_SYMMETRIC; 471999ebb4caSwyllys symkey->keylabel = (char *)fullpath; 472099ebb4caSwyllys symkey->israw = TRUE; 472199ebb4caSwyllys symkey->keyp = rkey; 472299ebb4caSwyllys 472399ebb4caSwyllys out: 472499ebb4caSwyllys if (fd != -1) 472599ebb4caSwyllys (void) close(fd); 472699ebb4caSwyllys 472799ebb4caSwyllys if (ret != KMF_OK && fullpath != NULL) { 472899ebb4caSwyllys free(fullpath); 472999ebb4caSwyllys } 473099ebb4caSwyllys if (ret != KMF_OK) { 473130a5e8faSwyllys kmf_free_raw_sym_key(rkey); 473299ebb4caSwyllys symkey->keyp = NULL; 473399ebb4caSwyllys symkey->keyalg = KMF_KEYALG_NONE; 473499ebb4caSwyllys } 473599ebb4caSwyllys 473699ebb4caSwyllys return (ret); 473799ebb4caSwyllys } 473899ebb4caSwyllys 473999ebb4caSwyllys /* 474099ebb4caSwyllys * Check a file to see if it is a CRL file with PEM or DER format. 474199ebb4caSwyllys * If success, return its format in the "pformat" argument. 474299ebb4caSwyllys */ 474399ebb4caSwyllys KMF_RETURN 474499ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat) 474599ebb4caSwyllys { 474699ebb4caSwyllys KMF_RETURN ret = KMF_OK; 474799ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 474899ebb4caSwyllys BIO *bio = NULL; 474999ebb4caSwyllys X509_CRL *xcrl = NULL; 475099ebb4caSwyllys 475199ebb4caSwyllys if (filename == NULL) { 475299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 475399ebb4caSwyllys } 475499ebb4caSwyllys 475599ebb4caSwyllys bio = BIO_new_file(filename, "rb"); 475699ebb4caSwyllys if (bio == NULL) { 475799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 475899ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 475999ebb4caSwyllys goto out; 476099ebb4caSwyllys } 476199ebb4caSwyllys 476299ebb4caSwyllys if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) { 476399ebb4caSwyllys *pformat = KMF_FORMAT_PEM; 476499ebb4caSwyllys goto out; 476599ebb4caSwyllys } 476699ebb4caSwyllys (void) BIO_free(bio); 476799ebb4caSwyllys 476899ebb4caSwyllys /* 476999ebb4caSwyllys * Now try to read it as raw DER data. 477099ebb4caSwyllys */ 477199ebb4caSwyllys bio = BIO_new_file(filename, "rb"); 477299ebb4caSwyllys if (bio == NULL) { 477399ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 477499ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 477599ebb4caSwyllys goto out; 477699ebb4caSwyllys } 477799ebb4caSwyllys 477899ebb4caSwyllys if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) { 477999ebb4caSwyllys *pformat = KMF_FORMAT_ASN1; 478099ebb4caSwyllys } else { 478199ebb4caSwyllys ret = KMF_ERR_BAD_CRLFILE; 478299ebb4caSwyllys } 478399ebb4caSwyllys 478499ebb4caSwyllys out: 478599ebb4caSwyllys if (bio != NULL) 478699ebb4caSwyllys (void) BIO_free(bio); 478799ebb4caSwyllys 478899ebb4caSwyllys if (xcrl != NULL) 478999ebb4caSwyllys X509_CRL_free(xcrl); 479099ebb4caSwyllys 479199ebb4caSwyllys return (ret); 479299ebb4caSwyllys } 479399ebb4caSwyllys 479499ebb4caSwyllys KMF_RETURN 479599ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey, 479699ebb4caSwyllys KMF_RAW_SYM_KEY *rkey) 479799ebb4caSwyllys { 479899ebb4caSwyllys KMF_RETURN rv = KMF_OK; 479999ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 480099ebb4caSwyllys KMF_DATA keyvalue; 480199ebb4caSwyllys 480299ebb4caSwyllys if (kmfh == NULL) 480399ebb4caSwyllys return (KMF_ERR_UNINITIALIZED); 480499ebb4caSwyllys 480599ebb4caSwyllys if (symkey == NULL || rkey == NULL) 480699ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 480799ebb4caSwyllys else if (symkey->keyclass != KMF_SYMMETRIC) 480899ebb4caSwyllys return (KMF_ERR_BAD_KEY_CLASS); 480999ebb4caSwyllys 481099ebb4caSwyllys if (symkey->israw) { 481199ebb4caSwyllys KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp; 481299ebb4caSwyllys 481399ebb4caSwyllys if (rawkey == NULL || 481499ebb4caSwyllys rawkey->keydata.val == NULL || 481599ebb4caSwyllys rawkey->keydata.len == 0) 481699ebb4caSwyllys return (KMF_ERR_BAD_KEYHANDLE); 481799ebb4caSwyllys 481899ebb4caSwyllys rkey->keydata.len = rawkey->keydata.len; 481999ebb4caSwyllys if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL) 482099ebb4caSwyllys return (KMF_ERR_MEMORY); 482199ebb4caSwyllys (void) memcpy(rkey->keydata.val, rawkey->keydata.val, 482299ebb4caSwyllys rkey->keydata.len); 482399ebb4caSwyllys } else { 482430a5e8faSwyllys rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue); 482599ebb4caSwyllys if (rv != KMF_OK) 482699ebb4caSwyllys return (rv); 482799ebb4caSwyllys rkey->keydata.len = keyvalue.Length; 482899ebb4caSwyllys rkey->keydata.val = keyvalue.Data; 482999ebb4caSwyllys } 483099ebb4caSwyllys 483199ebb4caSwyllys return (rv); 483299ebb4caSwyllys } 483302744e81Swyllys 483402744e81Swyllys /* 483530a5e8faSwyllys * substitute for the unsafe access(2) function. 483630a5e8faSwyllys * If the file in question already exists, return 1. 483730a5e8faSwyllys * else 0. If an error occurs during testing (other 483830a5e8faSwyllys * than EEXIST), return -1. 483930a5e8faSwyllys */ 484030a5e8faSwyllys static int 484130a5e8faSwyllys test_for_file(char *filename, mode_t mode) 484230a5e8faSwyllys { 484330a5e8faSwyllys int fd; 484430a5e8faSwyllys 484530a5e8faSwyllys /* 484630a5e8faSwyllys * Try to create the file with the EXCL flag. 484730a5e8faSwyllys * The call should fail if the file exists. 484830a5e8faSwyllys */ 484930a5e8faSwyllys fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode); 485030a5e8faSwyllys if (fd == -1 && errno == EEXIST) 485130a5e8faSwyllys return (1); 485230a5e8faSwyllys else if (fd == -1) /* some other error */ 485330a5e8faSwyllys return (-1); 485430a5e8faSwyllys 485530a5e8faSwyllys /* The file did NOT exist. Delete the testcase. */ 485630a5e8faSwyllys (void) close(fd); 485730a5e8faSwyllys (void) unlink(filename); 485830a5e8faSwyllys return (0); 485930a5e8faSwyllys } 486030a5e8faSwyllys 486130a5e8faSwyllys KMF_RETURN 4862*4942e222SAndy Fiddaman OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 486330a5e8faSwyllys { 486430a5e8faSwyllys KMF_RETURN rv = KMF_OK; 486530a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 486630a5e8faSwyllys KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL; 486730a5e8faSwyllys KMF_RAW_KEY_DATA *rawkey; 486830a5e8faSwyllys EVP_PKEY *pkey = NULL; 486930a5e8faSwyllys KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM; 487030a5e8faSwyllys KMF_CREDENTIAL cred = { NULL, 0 }; 487130a5e8faSwyllys BIO *out = NULL; 487230a5e8faSwyllys int keys = 0; 487330a5e8faSwyllys char *fullpath = NULL; 487430a5e8faSwyllys char *keyfile = NULL; 487530a5e8faSwyllys char *dirpath = NULL; 487630a5e8faSwyllys 487730a5e8faSwyllys pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr); 487830a5e8faSwyllys if (pubkey != NULL) 487930a5e8faSwyllys keys++; 488030a5e8faSwyllys 488130a5e8faSwyllys prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr); 488230a5e8faSwyllys if (prikey != NULL) 488330a5e8faSwyllys keys++; 488430a5e8faSwyllys 488530a5e8faSwyllys rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr); 488630a5e8faSwyllys if (rawkey != NULL) 488730a5e8faSwyllys keys++; 488830a5e8faSwyllys 488930a5e8faSwyllys /* 489030a5e8faSwyllys * Exactly 1 type of key must be passed to this function. 489130a5e8faSwyllys */ 489230a5e8faSwyllys if (keys != 1) 489330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 489430a5e8faSwyllys 489530a5e8faSwyllys keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, 489630a5e8faSwyllys numattr); 489730a5e8faSwyllys if (keyfile == NULL) 489830a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 489930a5e8faSwyllys 490030a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 490130a5e8faSwyllys 490230a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 490330a5e8faSwyllys 490430a5e8faSwyllys /* Once we have the full path, we don't need the pieces */ 490530a5e8faSwyllys if (fullpath == NULL) 490630a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 490730a5e8faSwyllys 490830a5e8faSwyllys /* If the requested file exists, return an error */ 490930a5e8faSwyllys if (test_for_file(fullpath, 0400) == 1) { 491030a5e8faSwyllys free(fullpath); 491130a5e8faSwyllys return (KMF_ERR_DUPLICATE_KEYFILE); 491230a5e8faSwyllys } 491330a5e8faSwyllys 491430a5e8faSwyllys rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 491530a5e8faSwyllys &format, NULL); 491630a5e8faSwyllys if (rv != KMF_OK) 491730a5e8faSwyllys /* format is optional. */ 491830a5e8faSwyllys rv = KMF_OK; 491930a5e8faSwyllys 492030a5e8faSwyllys /* CRED is not required for OpenSSL files */ 492130a5e8faSwyllys (void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr, 492230a5e8faSwyllys &cred, NULL); 492330a5e8faSwyllys 492430a5e8faSwyllys /* Store the private key to the keyfile */ 492530a5e8faSwyllys out = BIO_new_file(fullpath, "wb"); 492630a5e8faSwyllys if (out == NULL) { 492730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 492830a5e8faSwyllys rv = KMF_ERR_OPEN_FILE; 492930a5e8faSwyllys goto end; 493030a5e8faSwyllys } 493130a5e8faSwyllys 493230a5e8faSwyllys if (prikey != NULL && prikey->keyp != NULL) { 493330a5e8faSwyllys if (prikey->keyalg == KMF_RSA || 493430a5e8faSwyllys prikey->keyalg == KMF_DSA) { 493530a5e8faSwyllys pkey = (EVP_PKEY *)prikey->keyp; 493630a5e8faSwyllys 493730a5e8faSwyllys rv = ssl_write_key(kmfh, format, 493830a5e8faSwyllys out, &cred, pkey, TRUE); 493930a5e8faSwyllys 494030a5e8faSwyllys if (rv == KMF_OK && prikey->keylabel == NULL) { 494130a5e8faSwyllys prikey->keylabel = strdup(fullpath); 494230a5e8faSwyllys if (prikey->keylabel == NULL) 494330a5e8faSwyllys rv = KMF_ERR_MEMORY; 494430a5e8faSwyllys } 494530a5e8faSwyllys } 494630a5e8faSwyllys } else if (pubkey != NULL && pubkey->keyp != NULL) { 494730a5e8faSwyllys if (pubkey->keyalg == KMF_RSA || 494830a5e8faSwyllys pubkey->keyalg == KMF_DSA) { 494930a5e8faSwyllys pkey = (EVP_PKEY *)pubkey->keyp; 495030a5e8faSwyllys 495130a5e8faSwyllys rv = ssl_write_key(kmfh, format, 495230a5e8faSwyllys out, &cred, pkey, FALSE); 495330a5e8faSwyllys 495430a5e8faSwyllys if (rv == KMF_OK && pubkey->keylabel == NULL) { 495530a5e8faSwyllys pubkey->keylabel = strdup(fullpath); 495630a5e8faSwyllys if (pubkey->keylabel == NULL) 495730a5e8faSwyllys rv = KMF_ERR_MEMORY; 495830a5e8faSwyllys } 495930a5e8faSwyllys } 496030a5e8faSwyllys } else if (rawkey != NULL) { 496130a5e8faSwyllys if (rawkey->keytype == KMF_RSA) { 496230a5e8faSwyllys pkey = ImportRawRSAKey(&rawkey->rawdata.rsa); 496330a5e8faSwyllys } else if (rawkey->keytype == KMF_DSA) { 496430a5e8faSwyllys pkey = ImportRawDSAKey(&rawkey->rawdata.dsa); 496530a5e8faSwyllys } else { 496630a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 496730a5e8faSwyllys } 49685b3e1433Swyllys if (pkey != NULL) { 496973cc0e02Swyllys KMF_KEY_CLASS kclass = KMF_ASYM_PRI; 497073cc0e02Swyllys 497173cc0e02Swyllys rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr, 497273cc0e02Swyllys (void *)&kclass, NULL); 497373cc0e02Swyllys if (rv != KMF_OK) 497473cc0e02Swyllys rv = KMF_OK; 49755b3e1433Swyllys rv = ssl_write_key(kmfh, format, out, 497673cc0e02Swyllys &cred, pkey, (kclass == KMF_ASYM_PRI)); 49775b3e1433Swyllys EVP_PKEY_free(pkey); 49785b3e1433Swyllys } 497930a5e8faSwyllys } 498030a5e8faSwyllys 498130a5e8faSwyllys end: 498230a5e8faSwyllys 498330a5e8faSwyllys if (out) 498430a5e8faSwyllys (void) BIO_free(out); 498530a5e8faSwyllys 49865b3e1433Swyllys 498730a5e8faSwyllys if (rv == KMF_OK) 498830a5e8faSwyllys (void) chmod(fullpath, 0400); 498930a5e8faSwyllys 499030a5e8faSwyllys free(fullpath); 499130a5e8faSwyllys return (rv); 499230a5e8faSwyllys } 499330a5e8faSwyllys 499430a5e8faSwyllys KMF_RETURN 499530a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 499630a5e8faSwyllys { 499730a5e8faSwyllys KMF_RETURN ret = KMF_OK; 499830a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 499930a5e8faSwyllys X509_CRL *xcrl = NULL; 500030a5e8faSwyllys X509 *xcert = NULL; 500130a5e8faSwyllys EVP_PKEY *pkey; 500230a5e8faSwyllys KMF_ENCODE_FORMAT format; 500330a5e8faSwyllys BIO *in = NULL, *out = NULL; 500430a5e8faSwyllys int openssl_ret = 0; 500530a5e8faSwyllys KMF_ENCODE_FORMAT outformat; 500630a5e8faSwyllys boolean_t crlcheck = FALSE; 500730a5e8faSwyllys char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile; 500830a5e8faSwyllys 500930a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 501030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 501130a5e8faSwyllys } 501230a5e8faSwyllys 501330a5e8faSwyllys /* CRL check is optional */ 501430a5e8faSwyllys (void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr, 501530a5e8faSwyllys &crlcheck, NULL); 501630a5e8faSwyllys 501730a5e8faSwyllys certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr); 501830a5e8faSwyllys if (crlcheck == B_TRUE && certfile == NULL) { 501930a5e8faSwyllys return (KMF_ERR_BAD_CERTFILE); 502030a5e8faSwyllys } 502130a5e8faSwyllys 502230a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 502330a5e8faSwyllys incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr); 502430a5e8faSwyllys outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr); 502530a5e8faSwyllys 502630a5e8faSwyllys crlfile = get_fullpath(dirpath, incrl); 502730a5e8faSwyllys 502830a5e8faSwyllys if (crlfile == NULL) 502930a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 503030a5e8faSwyllys 503130a5e8faSwyllys outcrlfile = get_fullpath(dirpath, outcrl); 503230a5e8faSwyllys if (outcrlfile == NULL) 503330a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 503430a5e8faSwyllys 503530a5e8faSwyllys if (isdir(outcrlfile)) { 503630a5e8faSwyllys free(outcrlfile); 503730a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 503830a5e8faSwyllys } 503930a5e8faSwyllys 504030a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 504130a5e8faSwyllys if (ret != KMF_OK) { 504230a5e8faSwyllys free(outcrlfile); 504330a5e8faSwyllys return (ret); 504430a5e8faSwyllys } 504530a5e8faSwyllys 504630a5e8faSwyllys in = BIO_new_file(crlfile, "rb"); 504730a5e8faSwyllys if (in == NULL) { 504830a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 504930a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 505030a5e8faSwyllys goto end; 505130a5e8faSwyllys } 505230a5e8faSwyllys 505330a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 505430a5e8faSwyllys xcrl = d2i_X509_CRL_bio(in, NULL); 505530a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 505630a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); 505730a5e8faSwyllys } 505830a5e8faSwyllys 505930a5e8faSwyllys if (xcrl == NULL) { 506030a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 506130a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 506230a5e8faSwyllys goto end; 506330a5e8faSwyllys } 506430a5e8faSwyllys 506530a5e8faSwyllys /* If bypasscheck is specified, no need to verify. */ 506630a5e8faSwyllys if (crlcheck == B_FALSE) 506730a5e8faSwyllys goto output; 506830a5e8faSwyllys 506930a5e8faSwyllys ret = kmf_is_cert_file(handle, certfile, &format); 507030a5e8faSwyllys if (ret != KMF_OK) 507130a5e8faSwyllys goto end; 507230a5e8faSwyllys 507330a5e8faSwyllys /* Read in the CA cert file and convert to X509 */ 507430a5e8faSwyllys if (BIO_read_filename(in, certfile) <= 0) { 507530a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 507630a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 507730a5e8faSwyllys goto end; 507830a5e8faSwyllys } 507930a5e8faSwyllys 508030a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 508130a5e8faSwyllys xcert = d2i_X509_bio(in, NULL); 508230a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 508330a5e8faSwyllys xcert = PEM_read_bio_X509(in, NULL, NULL, NULL); 508430a5e8faSwyllys } else { 508530a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 508630a5e8faSwyllys goto end; 508730a5e8faSwyllys } 508830a5e8faSwyllys 508930a5e8faSwyllys if (xcert == NULL) { 509030a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 509130a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 509230a5e8faSwyllys goto end; 509330a5e8faSwyllys } 509430a5e8faSwyllys /* Now get the public key from the CA cert */ 509530a5e8faSwyllys pkey = X509_get_pubkey(xcert); 509630a5e8faSwyllys if (pkey == NULL) { 509730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 509830a5e8faSwyllys ret = KMF_ERR_BAD_CERTFILE; 509930a5e8faSwyllys goto end; 510030a5e8faSwyllys } 510130a5e8faSwyllys 510230a5e8faSwyllys /* Verify the CRL with the CA's public key */ 510330a5e8faSwyllys openssl_ret = X509_CRL_verify(xcrl, pkey); 510430a5e8faSwyllys EVP_PKEY_free(pkey); 510530a5e8faSwyllys if (openssl_ret > 0) { 510630a5e8faSwyllys ret = KMF_OK; /* verify succeed */ 510730a5e8faSwyllys } else { 510830a5e8faSwyllys SET_ERROR(kmfh, openssl_ret); 510930a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 511030a5e8faSwyllys } 511130a5e8faSwyllys 511230a5e8faSwyllys output: 511330a5e8faSwyllys ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 511430a5e8faSwyllys &outformat, NULL); 511530a5e8faSwyllys if (ret != KMF_OK) { 511630a5e8faSwyllys ret = KMF_OK; 511730a5e8faSwyllys outformat = KMF_FORMAT_PEM; 511830a5e8faSwyllys } 511930a5e8faSwyllys 512030a5e8faSwyllys out = BIO_new_file(outcrlfile, "wb"); 512130a5e8faSwyllys if (out == NULL) { 512230a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 512330a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 512430a5e8faSwyllys goto end; 512530a5e8faSwyllys } 512630a5e8faSwyllys 512730a5e8faSwyllys if (outformat == KMF_FORMAT_ASN1) { 512830a5e8faSwyllys openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl); 512930a5e8faSwyllys } else if (outformat == KMF_FORMAT_PEM) { 513030a5e8faSwyllys openssl_ret = PEM_write_bio_X509_CRL(out, xcrl); 513130a5e8faSwyllys } else { 513230a5e8faSwyllys ret = KMF_ERR_BAD_PARAMETER; 513330a5e8faSwyllys goto end; 513430a5e8faSwyllys } 513530a5e8faSwyllys 513630a5e8faSwyllys if (openssl_ret <= 0) { 513730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 513830a5e8faSwyllys ret = KMF_ERR_WRITE_FILE; 513930a5e8faSwyllys } else { 514030a5e8faSwyllys ret = KMF_OK; 514130a5e8faSwyllys } 514230a5e8faSwyllys 514330a5e8faSwyllys end: 514430a5e8faSwyllys if (xcrl != NULL) 514530a5e8faSwyllys X509_CRL_free(xcrl); 514630a5e8faSwyllys 514730a5e8faSwyllys if (xcert != NULL) 514830a5e8faSwyllys X509_free(xcert); 514930a5e8faSwyllys 515030a5e8faSwyllys if (in != NULL) 515130a5e8faSwyllys (void) BIO_free(in); 515230a5e8faSwyllys 515330a5e8faSwyllys if (out != NULL) 515430a5e8faSwyllys (void) BIO_free(out); 515530a5e8faSwyllys 515630a5e8faSwyllys if (outcrlfile != NULL) 515730a5e8faSwyllys free(outcrlfile); 515830a5e8faSwyllys 515930a5e8faSwyllys return (ret); 516030a5e8faSwyllys } 516130a5e8faSwyllys 516230a5e8faSwyllys KMF_RETURN 516330a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 516430a5e8faSwyllys { 516530a5e8faSwyllys KMF_RETURN ret = KMF_OK; 516630a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 516730a5e8faSwyllys X509_CRL *x = NULL; 516830a5e8faSwyllys KMF_ENCODE_FORMAT format; 516930a5e8faSwyllys char *crlfile = NULL; 517030a5e8faSwyllys BIO *in = NULL; 517130a5e8faSwyllys BIO *mem = NULL; 517230a5e8faSwyllys long len; 517330a5e8faSwyllys char *memptr; 517430a5e8faSwyllys char *data = NULL; 517530a5e8faSwyllys char **crldata; 517630a5e8faSwyllys char *crlfilename, *dirpath; 517730a5e8faSwyllys 517830a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 517930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 518030a5e8faSwyllys } 518130a5e8faSwyllys crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, 518230a5e8faSwyllys attrlist, numattr); 518330a5e8faSwyllys if (crlfilename == NULL) 518430a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 518530a5e8faSwyllys 518630a5e8faSwyllys crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR, 518730a5e8faSwyllys attrlist, numattr); 518830a5e8faSwyllys 518930a5e8faSwyllys if (crldata == NULL) 519030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 519130a5e8faSwyllys 519230a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 519330a5e8faSwyllys 519430a5e8faSwyllys crlfile = get_fullpath(dirpath, crlfilename); 519530a5e8faSwyllys 519630a5e8faSwyllys if (crlfile == NULL) 519730a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 519830a5e8faSwyllys 519930a5e8faSwyllys if (isdir(crlfile)) { 520030a5e8faSwyllys free(crlfile); 520130a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 520230a5e8faSwyllys } 520330a5e8faSwyllys 520430a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 520530a5e8faSwyllys if (ret != KMF_OK) { 520630a5e8faSwyllys free(crlfile); 520730a5e8faSwyllys return (ret); 520830a5e8faSwyllys } 520930a5e8faSwyllys 521030a5e8faSwyllys if (bio_err == NULL) 521130a5e8faSwyllys bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 521230a5e8faSwyllys 521330a5e8faSwyllys in = BIO_new_file(crlfile, "rb"); 521430a5e8faSwyllys if (in == NULL) { 521530a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 521630a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 521730a5e8faSwyllys goto end; 521830a5e8faSwyllys } 521930a5e8faSwyllys 522030a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 522130a5e8faSwyllys x = d2i_X509_CRL_bio(in, NULL); 522230a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 522330a5e8faSwyllys x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); 522430a5e8faSwyllys } 522530a5e8faSwyllys 522630a5e8faSwyllys if (x == NULL) { /* should not happen */ 522730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 522830a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 522930a5e8faSwyllys goto end; 523030a5e8faSwyllys } 523130a5e8faSwyllys 523230a5e8faSwyllys mem = BIO_new(BIO_s_mem()); 523330a5e8faSwyllys if (mem == NULL) { 523430a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 523530a5e8faSwyllys ret = KMF_ERR_MEMORY; 523630a5e8faSwyllys goto end; 523730a5e8faSwyllys } 523830a5e8faSwyllys 523930a5e8faSwyllys (void) X509_CRL_print(mem, x); 524030a5e8faSwyllys len = BIO_get_mem_data(mem, &memptr); 524130a5e8faSwyllys if (len <= 0) { 524230a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 524330a5e8faSwyllys ret = KMF_ERR_MEMORY; 524430a5e8faSwyllys goto end; 524530a5e8faSwyllys } 524630a5e8faSwyllys 524730a5e8faSwyllys data = malloc(len + 1); 524830a5e8faSwyllys if (data == NULL) { 524930a5e8faSwyllys ret = KMF_ERR_MEMORY; 525030a5e8faSwyllys goto end; 525130a5e8faSwyllys } 525230a5e8faSwyllys 525330a5e8faSwyllys (void) memcpy(data, memptr, len); 525430a5e8faSwyllys data[len] = '\0'; 525530a5e8faSwyllys *crldata = data; 525630a5e8faSwyllys 525730a5e8faSwyllys end: 525830a5e8faSwyllys if (x != NULL) 525930a5e8faSwyllys X509_CRL_free(x); 526030a5e8faSwyllys 526130a5e8faSwyllys if (crlfile != NULL) 526230a5e8faSwyllys free(crlfile); 526330a5e8faSwyllys 526430a5e8faSwyllys if (in != NULL) 526530a5e8faSwyllys (void) BIO_free(in); 526630a5e8faSwyllys 526730a5e8faSwyllys if (mem != NULL) 526830a5e8faSwyllys (void) BIO_free(mem); 526930a5e8faSwyllys 527030a5e8faSwyllys return (ret); 527130a5e8faSwyllys } 527230a5e8faSwyllys 527330a5e8faSwyllys KMF_RETURN 527430a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 527530a5e8faSwyllys { 527630a5e8faSwyllys KMF_RETURN ret = KMF_OK; 527730a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 527830a5e8faSwyllys KMF_ENCODE_FORMAT format; 527930a5e8faSwyllys char *crlfile = NULL; 528030a5e8faSwyllys BIO *in = NULL; 528130a5e8faSwyllys char *crlfilename, *dirpath; 528230a5e8faSwyllys 528330a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 528430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 528530a5e8faSwyllys } 528630a5e8faSwyllys 528730a5e8faSwyllys crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, 528830a5e8faSwyllys attrlist, numattr); 528930a5e8faSwyllys 529030a5e8faSwyllys if (crlfilename == NULL) 529130a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 529230a5e8faSwyllys 529330a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 529430a5e8faSwyllys 529530a5e8faSwyllys crlfile = get_fullpath(dirpath, crlfilename); 529630a5e8faSwyllys 529730a5e8faSwyllys if (crlfile == NULL) 529830a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 529930a5e8faSwyllys 530030a5e8faSwyllys if (isdir(crlfile)) { 530130a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 530230a5e8faSwyllys goto end; 530330a5e8faSwyllys } 530430a5e8faSwyllys 530530a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 530630a5e8faSwyllys if (ret != KMF_OK) 530730a5e8faSwyllys goto end; 530830a5e8faSwyllys 530930a5e8faSwyllys if (unlink(crlfile) != 0) { 531030a5e8faSwyllys SET_SYS_ERROR(kmfh, errno); 531130a5e8faSwyllys ret = KMF_ERR_INTERNAL; 531230a5e8faSwyllys goto end; 531330a5e8faSwyllys } 531430a5e8faSwyllys 531530a5e8faSwyllys end: 531630a5e8faSwyllys if (in != NULL) 531730a5e8faSwyllys (void) BIO_free(in); 531830a5e8faSwyllys if (crlfile != NULL) 531930a5e8faSwyllys free(crlfile); 532030a5e8faSwyllys 532130a5e8faSwyllys return (ret); 532230a5e8faSwyllys } 532330a5e8faSwyllys 532430a5e8faSwyllys KMF_RETURN 532530a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 532630a5e8faSwyllys { 532730a5e8faSwyllys KMF_RETURN ret = KMF_OK; 532830a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 532930a5e8faSwyllys KMF_ENCODE_FORMAT format; 533030a5e8faSwyllys BIO *in = NULL; 533130a5e8faSwyllys X509 *xcert = NULL; 533230a5e8faSwyllys X509_CRL *xcrl = NULL; 533330a5e8faSwyllys STACK_OF(X509_REVOKED) *revoke_stack = NULL; 533430a5e8faSwyllys X509_REVOKED *revoke; 533530a5e8faSwyllys int i; 533630a5e8faSwyllys char *crlfilename, *crlfile, *dirpath, *certfile; 533730a5e8faSwyllys 533830a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 533930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 534030a5e8faSwyllys } 534130a5e8faSwyllys 534230a5e8faSwyllys crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, 534330a5e8faSwyllys attrlist, numattr); 534430a5e8faSwyllys 534530a5e8faSwyllys if (crlfilename == NULL) 534630a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 534730a5e8faSwyllys 534830a5e8faSwyllys certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr); 534930a5e8faSwyllys if (certfile == NULL) 535030a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 535130a5e8faSwyllys 535230a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 535330a5e8faSwyllys 535430a5e8faSwyllys crlfile = get_fullpath(dirpath, crlfilename); 535530a5e8faSwyllys 535630a5e8faSwyllys if (crlfile == NULL) 535730a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 535830a5e8faSwyllys 535930a5e8faSwyllys if (isdir(crlfile)) { 536030a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 536130a5e8faSwyllys goto end; 536230a5e8faSwyllys } 536330a5e8faSwyllys 536430a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 536530a5e8faSwyllys if (ret != KMF_OK) 536630a5e8faSwyllys goto end; 536730a5e8faSwyllys 536830a5e8faSwyllys /* Read the CRL file and load it into a X509_CRL structure */ 536930a5e8faSwyllys in = BIO_new_file(crlfilename, "rb"); 537030a5e8faSwyllys if (in == NULL) { 537130a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 537230a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 537330a5e8faSwyllys goto end; 537430a5e8faSwyllys } 537530a5e8faSwyllys 537630a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 537730a5e8faSwyllys xcrl = d2i_X509_CRL_bio(in, NULL); 537830a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 537930a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); 538030a5e8faSwyllys } 538130a5e8faSwyllys 538230a5e8faSwyllys if (xcrl == NULL) { 538330a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 538430a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 538530a5e8faSwyllys goto end; 538630a5e8faSwyllys } 538730a5e8faSwyllys (void) BIO_free(in); 538830a5e8faSwyllys 538930a5e8faSwyllys /* Read the Certificate file and load it into a X509 structure */ 539030a5e8faSwyllys ret = kmf_is_cert_file(handle, certfile, &format); 539130a5e8faSwyllys if (ret != KMF_OK) 539230a5e8faSwyllys goto end; 539330a5e8faSwyllys 539430a5e8faSwyllys in = BIO_new_file(certfile, "rb"); 539530a5e8faSwyllys if (in == NULL) { 539630a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 539730a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 539830a5e8faSwyllys goto end; 539930a5e8faSwyllys } 540030a5e8faSwyllys 540130a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 540230a5e8faSwyllys xcert = d2i_X509_bio(in, NULL); 540330a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 540430a5e8faSwyllys xcert = PEM_read_bio_X509(in, NULL, NULL, NULL); 540530a5e8faSwyllys } 540630a5e8faSwyllys 540730a5e8faSwyllys if (xcert == NULL) { 540830a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 540930a5e8faSwyllys ret = KMF_ERR_BAD_CERTFILE; 541030a5e8faSwyllys goto end; 541130a5e8faSwyllys } 541230a5e8faSwyllys 541330a5e8faSwyllys /* Check if the certificate and the CRL have same issuer */ 5414300fdee2SAndy Fiddaman if (X509_NAME_cmp(X509_get_issuer_name(xcert), 5415300fdee2SAndy Fiddaman X509_CRL_get_issuer(xcrl)) != 0) { 541630a5e8faSwyllys ret = KMF_ERR_ISSUER; 541730a5e8faSwyllys goto end; 541830a5e8faSwyllys } 541930a5e8faSwyllys 542030a5e8faSwyllys /* Check to see if the certificate serial number is revoked */ 542130a5e8faSwyllys revoke_stack = X509_CRL_get_REVOKED(xcrl); 542230a5e8faSwyllys if (sk_X509_REVOKED_num(revoke_stack) <= 0) { 542330a5e8faSwyllys /* No revoked certificates in the CRL file */ 542430a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 542530a5e8faSwyllys ret = KMF_ERR_EMPTY_CRL; 542630a5e8faSwyllys goto end; 542730a5e8faSwyllys } 542830a5e8faSwyllys 542930a5e8faSwyllys for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) { 543030a5e8faSwyllys revoke = sk_X509_REVOKED_value(revoke_stack, i); 5431300fdee2SAndy Fiddaman if (ASN1_INTEGER_cmp(X509_get_serialNumber(xcert), 5432300fdee2SAndy Fiddaman X509_REVOKED_get0_serialNumber(revoke)) == 0) { 543330a5e8faSwyllys break; 543430a5e8faSwyllys } 543530a5e8faSwyllys } 543630a5e8faSwyllys 543730a5e8faSwyllys if (i < sk_X509_REVOKED_num(revoke_stack)) { 543830a5e8faSwyllys ret = KMF_OK; 543930a5e8faSwyllys } else { 544030a5e8faSwyllys ret = KMF_ERR_NOT_REVOKED; 544130a5e8faSwyllys } 544230a5e8faSwyllys 544330a5e8faSwyllys end: 544430a5e8faSwyllys if (in != NULL) 544530a5e8faSwyllys (void) BIO_free(in); 544630a5e8faSwyllys if (xcrl != NULL) 544730a5e8faSwyllys X509_CRL_free(xcrl); 544830a5e8faSwyllys if (xcert != NULL) 544930a5e8faSwyllys X509_free(xcert); 545030a5e8faSwyllys 545130a5e8faSwyllys return (ret); 545230a5e8faSwyllys } 545330a5e8faSwyllys 545430a5e8faSwyllys KMF_RETURN 545530a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert) 545630a5e8faSwyllys { 545730a5e8faSwyllys KMF_RETURN ret = KMF_OK; 545830a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 545930a5e8faSwyllys BIO *bcrl = NULL; 546030a5e8faSwyllys X509_CRL *xcrl = NULL; 546130a5e8faSwyllys X509 *xcert = NULL; 546230a5e8faSwyllys EVP_PKEY *pkey; 546330a5e8faSwyllys int sslret; 546430a5e8faSwyllys KMF_ENCODE_FORMAT crl_format; 546530a5e8faSwyllys unsigned char *p; 546630a5e8faSwyllys long len; 546730a5e8faSwyllys 546830a5e8faSwyllys if (handle == NULL || crlname == NULL || tacert == NULL) { 546930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 547030a5e8faSwyllys } 547130a5e8faSwyllys 547230a5e8faSwyllys ret = kmf_get_file_format(crlname, &crl_format); 547330a5e8faSwyllys if (ret != KMF_OK) 547430a5e8faSwyllys return (ret); 547530a5e8faSwyllys 547630a5e8faSwyllys bcrl = BIO_new_file(crlname, "rb"); 547730a5e8faSwyllys if (bcrl == NULL) { 547830a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 547930a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 548030a5e8faSwyllys goto cleanup; 548130a5e8faSwyllys } 548230a5e8faSwyllys 548330a5e8faSwyllys if (crl_format == KMF_FORMAT_ASN1) { 548430a5e8faSwyllys xcrl = d2i_X509_CRL_bio(bcrl, NULL); 548530a5e8faSwyllys } else if (crl_format == KMF_FORMAT_PEM) { 548630a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL); 548730a5e8faSwyllys } else { 548830a5e8faSwyllys ret = KMF_ERR_BAD_PARAMETER; 548930a5e8faSwyllys goto cleanup; 549030a5e8faSwyllys } 549130a5e8faSwyllys 549230a5e8faSwyllys if (xcrl == NULL) { 549330a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 549430a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 549530a5e8faSwyllys goto cleanup; 549630a5e8faSwyllys } 549730a5e8faSwyllys 549830a5e8faSwyllys p = tacert->Data; 549930a5e8faSwyllys len = tacert->Length; 550030a5e8faSwyllys xcert = d2i_X509(NULL, (const uchar_t **)&p, len); 550130a5e8faSwyllys 550230a5e8faSwyllys if (xcert == NULL) { 550330a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 550430a5e8faSwyllys ret = KMF_ERR_BAD_CERTFILE; 550530a5e8faSwyllys goto cleanup; 550630a5e8faSwyllys } 550730a5e8faSwyllys 550830a5e8faSwyllys /* Get issuer certificate public key */ 550930a5e8faSwyllys pkey = X509_get_pubkey(xcert); 551030a5e8faSwyllys if (pkey == NULL) { 551130a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 551230a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 551330a5e8faSwyllys goto cleanup; 551430a5e8faSwyllys } 551530a5e8faSwyllys 551630a5e8faSwyllys /* Verify CRL signature */ 551730a5e8faSwyllys sslret = X509_CRL_verify(xcrl, pkey); 551830a5e8faSwyllys EVP_PKEY_free(pkey); 551930a5e8faSwyllys if (sslret > 0) { 552030a5e8faSwyllys ret = KMF_OK; 552130a5e8faSwyllys } else { 552230a5e8faSwyllys SET_ERROR(kmfh, sslret); 552330a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 552430a5e8faSwyllys } 552530a5e8faSwyllys 552630a5e8faSwyllys cleanup: 552730a5e8faSwyllys if (bcrl != NULL) 552830a5e8faSwyllys (void) BIO_free(bcrl); 552930a5e8faSwyllys 553030a5e8faSwyllys if (xcrl != NULL) 553130a5e8faSwyllys X509_CRL_free(xcrl); 553230a5e8faSwyllys 553330a5e8faSwyllys if (xcert != NULL) 553430a5e8faSwyllys X509_free(xcert); 553530a5e8faSwyllys 553630a5e8faSwyllys return (ret); 553730a5e8faSwyllys 553830a5e8faSwyllys } 553930a5e8faSwyllys 554030a5e8faSwyllys KMF_RETURN 554130a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname) 554230a5e8faSwyllys { 554330a5e8faSwyllys KMF_RETURN ret = KMF_OK; 554430a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 554530a5e8faSwyllys KMF_ENCODE_FORMAT crl_format; 554630a5e8faSwyllys BIO *bcrl = NULL; 554730a5e8faSwyllys X509_CRL *xcrl = NULL; 554830a5e8faSwyllys int i; 554930a5e8faSwyllys 555030a5e8faSwyllys if (handle == NULL || crlname == NULL) { 555130a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 555230a5e8faSwyllys } 555330a5e8faSwyllys 555430a5e8faSwyllys ret = kmf_is_crl_file(handle, crlname, &crl_format); 555530a5e8faSwyllys if (ret != KMF_OK) 555630a5e8faSwyllys return (ret); 555730a5e8faSwyllys 555830a5e8faSwyllys bcrl = BIO_new_file(crlname, "rb"); 555930a5e8faSwyllys if (bcrl == NULL) { 556030a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 556130a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 556230a5e8faSwyllys goto cleanup; 556330a5e8faSwyllys } 556430a5e8faSwyllys 55655b3e1433Swyllys if (crl_format == KMF_FORMAT_ASN1) 556630a5e8faSwyllys xcrl = d2i_X509_CRL_bio(bcrl, NULL); 55675b3e1433Swyllys else if (crl_format == KMF_FORMAT_PEM) 556830a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL); 556930a5e8faSwyllys 557030a5e8faSwyllys if (xcrl == NULL) { 557130a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 557230a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 557330a5e8faSwyllys goto cleanup; 557430a5e8faSwyllys } 5575300fdee2SAndy Fiddaman i = X509_cmp_time(X509_CRL_get0_lastUpdate(xcrl), NULL); 557630a5e8faSwyllys if (i >= 0) { 557730a5e8faSwyllys ret = KMF_ERR_VALIDITY_PERIOD; 557830a5e8faSwyllys goto cleanup; 557930a5e8faSwyllys } 5580300fdee2SAndy Fiddaman if (X509_CRL_get0_nextUpdate(xcrl)) { 5581300fdee2SAndy Fiddaman i = X509_cmp_time(X509_CRL_get0_nextUpdate(xcrl), NULL); 558230a5e8faSwyllys 558330a5e8faSwyllys if (i <= 0) { 558430a5e8faSwyllys ret = KMF_ERR_VALIDITY_PERIOD; 558530a5e8faSwyllys goto cleanup; 558630a5e8faSwyllys } 558730a5e8faSwyllys } 558830a5e8faSwyllys 558930a5e8faSwyllys ret = KMF_OK; 559030a5e8faSwyllys 559130a5e8faSwyllys cleanup: 559230a5e8faSwyllys if (bcrl != NULL) 559330a5e8faSwyllys (void) BIO_free(bcrl); 559430a5e8faSwyllys 559530a5e8faSwyllys if (xcrl != NULL) 559630a5e8faSwyllys X509_CRL_free(xcrl); 559730a5e8faSwyllys 559830a5e8faSwyllys return (ret); 559930a5e8faSwyllys } 5600