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. 8300fdee2SAndy Fiddaman * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. 9*553e44ceSAndrew Stormont * Copyright 2018 RackTop Systems. 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 */ 142*553e44ceSAndrew 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 /* LINTED E_STATIC_UNUSED */ 155300fdee2SAndy Fiddaman DEFINE_STACK_OF(EVP_PKEY) 156300fdee2SAndy Fiddaman #endif 157300fdee2SAndy Fiddaman 15899ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX; 15999ebb4caSwyllys static int ssl_initialized = 0; 16030a5e8faSwyllys static BIO *bio_err = NULL; 16130a5e8faSwyllys 16230a5e8faSwyllys static int 16330a5e8faSwyllys test_for_file(char *, mode_t); 1645b3e1433Swyllys static KMF_RETURN 1655b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *, char *, int, 1665b3e1433Swyllys STACK_OF(EVP_PKEY) *, STACK_OF(X509) *); 1675b3e1433Swyllys 1685b3e1433Swyllys static KMF_RETURN 1695b3e1433Swyllys local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *, 1705b3e1433Swyllys int, KMF_KEY_HANDLE *, char *); 1715b3e1433Swyllys 1725b3e1433Swyllys static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int); 17399ebb4caSwyllys 17471593db2Swyllys static KMF_RETURN 17530a5e8faSwyllys extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *, 17602744e81Swyllys CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *); 17771593db2Swyllys 17871593db2Swyllys static KMF_RETURN 17930a5e8faSwyllys kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY, 18030a5e8faSwyllys char *, KMF_DATA *); 18130a5e8faSwyllys 18230a5e8faSwyllys static KMF_RETURN 18330a5e8faSwyllys load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY, 18430a5e8faSwyllys char *, KMF_DATA **, uint32_t *); 18571593db2Swyllys 18602744e81Swyllys static KMF_RETURN 18702744e81Swyllys sslBN2KMFBN(BIGNUM *, KMF_BIGINT *); 18802744e81Swyllys 18902744e81Swyllys static EVP_PKEY * 19002744e81Swyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *); 19102744e81Swyllys 19230a5e8faSwyllys static KMF_RETURN 19330a5e8faSwyllys convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *); 19430a5e8faSwyllys 19599ebb4caSwyllys KMF_RETURN 19630a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 19799ebb4caSwyllys 19899ebb4caSwyllys void 19999ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *); 20099ebb4caSwyllys 20199ebb4caSwyllys KMF_RETURN 20230a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *); 20399ebb4caSwyllys 20499ebb4caSwyllys KMF_RETURN 20530a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *); 20699ebb4caSwyllys 20799ebb4caSwyllys KMF_RETURN 20830a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 20930a5e8faSwyllys 21030a5e8faSwyllys KMF_RETURN 21130a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 21299ebb4caSwyllys 21399ebb4caSwyllys KMF_RETURN 21499ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *); 21599ebb4caSwyllys 21699ebb4caSwyllys KMF_RETURN 21799ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *, 21899ebb4caSwyllys KMF_DATA *, KMF_DATA *); 21999ebb4caSwyllys 22099ebb4caSwyllys KMF_RETURN 22130a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 22299ebb4caSwyllys 22399ebb4caSwyllys KMF_RETURN 22430a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 22599ebb4caSwyllys 22699ebb4caSwyllys KMF_RETURN 22730a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 22899ebb4caSwyllys 22999ebb4caSwyllys KMF_RETURN 23030a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 23199ebb4caSwyllys 23299ebb4caSwyllys KMF_RETURN 23330a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 23499ebb4caSwyllys 23599ebb4caSwyllys KMF_RETURN 23699ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *, 23799ebb4caSwyllys KMF_PRINTABLE_ITEM, char *); 23899ebb4caSwyllys 23999ebb4caSwyllys KMF_RETURN 24099ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T, char **); 24199ebb4caSwyllys 24299ebb4caSwyllys KMF_RETURN 24330a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 24499ebb4caSwyllys 24599ebb4caSwyllys KMF_RETURN 24699ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *, 24799ebb4caSwyllys KMF_DATA *, KMF_DATA *); 24899ebb4caSwyllys 24999ebb4caSwyllys KMF_RETURN 25030a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 25199ebb4caSwyllys 25299ebb4caSwyllys KMF_RETURN 25330a5e8faSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 25499ebb4caSwyllys 25599ebb4caSwyllys KMF_RETURN 25630a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 25799ebb4caSwyllys 25899ebb4caSwyllys KMF_RETURN 25930a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 26099ebb4caSwyllys 26199ebb4caSwyllys KMF_RETURN 26230a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 26399ebb4caSwyllys 26499ebb4caSwyllys KMF_RETURN 26599ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *); 26699ebb4caSwyllys 26799ebb4caSwyllys KMF_RETURN 26830a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *); 26999ebb4caSwyllys 27099ebb4caSwyllys KMF_RETURN 27130a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *); 27299ebb4caSwyllys 27399ebb4caSwyllys static 27499ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table = 27599ebb4caSwyllys { 27699ebb4caSwyllys 1, /* Version */ 27799ebb4caSwyllys NULL, /* ConfigureKeystore */ 27899ebb4caSwyllys OpenSSL_FindCert, 27999ebb4caSwyllys OpenSSL_FreeKMFCert, 28099ebb4caSwyllys OpenSSL_StoreCert, 28199ebb4caSwyllys NULL, /* ImportCert */ 28299ebb4caSwyllys OpenSSL_ImportCRL, 28399ebb4caSwyllys OpenSSL_DeleteCert, 28499ebb4caSwyllys OpenSSL_DeleteCRL, 28599ebb4caSwyllys OpenSSL_CreateKeypair, 28699ebb4caSwyllys OpenSSL_FindKey, 28799ebb4caSwyllys OpenSSL_EncodePubKeyData, 28899ebb4caSwyllys OpenSSL_SignData, 28999ebb4caSwyllys OpenSSL_DeleteKey, 29099ebb4caSwyllys OpenSSL_ListCRL, 29199ebb4caSwyllys NULL, /* FindCRL */ 29299ebb4caSwyllys OpenSSL_FindCertInCRL, 29399ebb4caSwyllys OpenSSL_GetErrorString, 29430a5e8faSwyllys OpenSSL_FindPrikeyByCert, 29599ebb4caSwyllys OpenSSL_DecryptData, 29630a5e8faSwyllys OpenSSL_ExportPK12, 29799ebb4caSwyllys OpenSSL_CreateSymKey, 29899ebb4caSwyllys OpenSSL_GetSymKeyValue, 29999ebb4caSwyllys NULL, /* SetTokenPin */ 30030a5e8faSwyllys OpenSSL_StoreKey, 30199ebb4caSwyllys NULL /* Finalize */ 30299ebb4caSwyllys }; 30399ebb4caSwyllys 304*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 30599ebb4caSwyllys static mutex_t *lock_cs; 30699ebb4caSwyllys static long *lock_count; 30799ebb4caSwyllys 30899ebb4caSwyllys static void 309a2d4930dSDan OpenSolaris Anderson /* ARGSUSED1 */ 31099ebb4caSwyllys locking_cb(int mode, int type, char *file, int line) 31199ebb4caSwyllys { 31299ebb4caSwyllys if (mode & CRYPTO_LOCK) { 31399ebb4caSwyllys (void) mutex_lock(&(lock_cs[type])); 31499ebb4caSwyllys lock_count[type]++; 31599ebb4caSwyllys } else { 31699ebb4caSwyllys (void) mutex_unlock(&(lock_cs[type])); 31799ebb4caSwyllys } 31899ebb4caSwyllys } 31999ebb4caSwyllys 32099ebb4caSwyllys static unsigned long 32199ebb4caSwyllys thread_id() 32299ebb4caSwyllys { 32399ebb4caSwyllys return ((unsigned long)thr_self()); 32499ebb4caSwyllys } 325*553e44ceSAndrew Stormont #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER */ 32699ebb4caSwyllys 32799ebb4caSwyllys KMF_PLUGIN_FUNCLIST * 32899ebb4caSwyllys KMF_Plugin_Initialize() 32999ebb4caSwyllys { 330*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 33199ebb4caSwyllys int i; 332300fdee2SAndy Fiddaman #endif 33399ebb4caSwyllys 33499ebb4caSwyllys (void) mutex_lock(&init_lock); 33599ebb4caSwyllys if (!ssl_initialized) { 33699ebb4caSwyllys /* 33799ebb4caSwyllys * Add support for extension OIDs that are not yet in the 33899ebb4caSwyllys * openssl default set. 33999ebb4caSwyllys */ 34099ebb4caSwyllys (void) OBJ_create("2.5.29.30", "nameConstraints", 34199ebb4caSwyllys "X509v3 Name Constraints"); 34299ebb4caSwyllys (void) OBJ_create("2.5.29.33", "policyMappings", 34399ebb4caSwyllys "X509v3 Policy Mappings"); 34499ebb4caSwyllys (void) OBJ_create("2.5.29.36", "policyConstraints", 34599ebb4caSwyllys "X509v3 Policy Constraints"); 34699ebb4caSwyllys (void) OBJ_create("2.5.29.46", "freshestCRL", 34799ebb4caSwyllys "X509v3 Freshest CRL"); 34899ebb4caSwyllys (void) OBJ_create("2.5.29.54", "inhibitAnyPolicy", 34999ebb4caSwyllys "X509v3 Inhibit Any-Policy"); 350300fdee2SAndy Fiddaman 351*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 35299ebb4caSwyllys /* 35399ebb4caSwyllys * Set up for thread-safe operation. 354300fdee2SAndy Fiddaman * This is not required for OpenSSL 1.1 35599ebb4caSwyllys */ 35699ebb4caSwyllys lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t)); 35799ebb4caSwyllys if (lock_cs == NULL) { 35899ebb4caSwyllys (void) mutex_unlock(&init_lock); 35999ebb4caSwyllys return (NULL); 36099ebb4caSwyllys } 36199ebb4caSwyllys 36299ebb4caSwyllys lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long)); 36399ebb4caSwyllys if (lock_count == NULL) { 36499ebb4caSwyllys OPENSSL_free(lock_cs); 36599ebb4caSwyllys (void) mutex_unlock(&init_lock); 36699ebb4caSwyllys return (NULL); 36799ebb4caSwyllys } 36899ebb4caSwyllys 36999ebb4caSwyllys for (i = 0; i < CRYPTO_num_locks(); i++) { 37099ebb4caSwyllys lock_count[i] = 0; 37199ebb4caSwyllys (void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL); 37299ebb4caSwyllys } 37399ebb4caSwyllys 37499ebb4caSwyllys CRYPTO_set_id_callback((unsigned long (*)())thread_id); 3752c9a247fSWyllys Ingersoll if (CRYPTO_get_locking_callback() == NULL) 37699ebb4caSwyllys CRYPTO_set_locking_callback((void (*)())locking_cb); 3772c9a247fSWyllys Ingersoll 378300fdee2SAndy Fiddaman (void) OpenSSL_add_all_algorithms(); 3792c9a247fSWyllys Ingersoll 3802c9a247fSWyllys Ingersoll /* Enable error strings for reporting */ 381300fdee2SAndy Fiddaman (void) ERR_load_crypto_strings(); 382300fdee2SAndy Fiddaman #endif 3832c9a247fSWyllys Ingersoll 38499ebb4caSwyllys ssl_initialized = 1; 38599ebb4caSwyllys } 38699ebb4caSwyllys (void) mutex_unlock(&init_lock); 38799ebb4caSwyllys 38899ebb4caSwyllys return (&openssl_plugin_table); 38999ebb4caSwyllys } 390300fdee2SAndy Fiddaman 39199ebb4caSwyllys /* 39299ebb4caSwyllys * Convert an SSL DN to a KMF DN. 39399ebb4caSwyllys */ 39499ebb4caSwyllys static KMF_RETURN 39599ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN) 39699ebb4caSwyllys { 39799ebb4caSwyllys KMF_DATA derdata; 39899ebb4caSwyllys KMF_RETURN rv = KMF_OK; 39999ebb4caSwyllys uchar_t *tmp; 40099ebb4caSwyllys 40199ebb4caSwyllys /* Convert to raw DER format */ 40299ebb4caSwyllys derdata.Length = i2d_X509_NAME(sslDN, NULL); 40399ebb4caSwyllys if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length)) 40499ebb4caSwyllys == NULL) { 40599ebb4caSwyllys return (KMF_ERR_MEMORY); 40699ebb4caSwyllys } 40799ebb4caSwyllys (void) i2d_X509_NAME(sslDN, &tmp); 40899ebb4caSwyllys 40999ebb4caSwyllys /* Decode to KMF format */ 41099ebb4caSwyllys rv = DerDecodeName(&derdata, kmfDN); 41199ebb4caSwyllys if (rv != KMF_OK) { 41299ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 41399ebb4caSwyllys } 41499ebb4caSwyllys OPENSSL_free(derdata.Data); 41599ebb4caSwyllys 41699ebb4caSwyllys return (rv); 41799ebb4caSwyllys } 41899ebb4caSwyllys 41930a5e8faSwyllys int 42099ebb4caSwyllys isdir(char *path) 42199ebb4caSwyllys { 42299ebb4caSwyllys struct stat s; 42399ebb4caSwyllys 42499ebb4caSwyllys if (stat(path, &s) == -1) 42599ebb4caSwyllys return (0); 42699ebb4caSwyllys 42730a5e8faSwyllys return ((s.st_mode & S_IFMT) == S_IFDIR); 42899ebb4caSwyllys } 42999ebb4caSwyllys 43099ebb4caSwyllys static KMF_RETURN 43199ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert) 43299ebb4caSwyllys { 43399ebb4caSwyllys KMF_RETURN rv = KMF_OK; 43499ebb4caSwyllys unsigned char *buf = NULL, *p; 43599ebb4caSwyllys int len; 43699ebb4caSwyllys 43799ebb4caSwyllys /* 43899ebb4caSwyllys * Convert the X509 internal struct to DER encoded data 43999ebb4caSwyllys */ 44099ebb4caSwyllys if ((len = i2d_X509(x509cert, NULL)) < 0) { 44199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 44299ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 44399ebb4caSwyllys goto cleanup; 44499ebb4caSwyllys } 44599ebb4caSwyllys if ((buf = malloc(len)) == NULL) { 44699ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 44799ebb4caSwyllys rv = KMF_ERR_MEMORY; 44899ebb4caSwyllys goto cleanup; 44999ebb4caSwyllys } 45099ebb4caSwyllys 45199ebb4caSwyllys /* 45299ebb4caSwyllys * i2d_X509 will increment the buf pointer so that we need to 45399ebb4caSwyllys * save it. 45499ebb4caSwyllys */ 45599ebb4caSwyllys p = buf; 45699ebb4caSwyllys if ((len = i2d_X509(x509cert, &p)) < 0) { 45799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 45899ebb4caSwyllys free(buf); 45999ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 46099ebb4caSwyllys goto cleanup; 46199ebb4caSwyllys } 46299ebb4caSwyllys 46399ebb4caSwyllys /* caller's responsibility to free it */ 46499ebb4caSwyllys cert->Data = buf; 46599ebb4caSwyllys cert->Length = len; 46699ebb4caSwyllys 46799ebb4caSwyllys cleanup: 46899ebb4caSwyllys if (rv != KMF_OK) { 46999ebb4caSwyllys if (buf) 47099ebb4caSwyllys free(buf); 47199ebb4caSwyllys cert->Data = NULL; 47299ebb4caSwyllys cert->Length = 0; 47399ebb4caSwyllys } 47499ebb4caSwyllys 47599ebb4caSwyllys return (rv); 47699ebb4caSwyllys } 47799ebb4caSwyllys 47830a5e8faSwyllys 47999ebb4caSwyllys static KMF_RETURN 48030a5e8faSwyllys check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial, 48130a5e8faSwyllys boolean_t *match) 48299ebb4caSwyllys { 48399ebb4caSwyllys KMF_RETURN rv = KMF_OK; 48499ebb4caSwyllys boolean_t findIssuer = FALSE; 48599ebb4caSwyllys boolean_t findSubject = FALSE; 48699ebb4caSwyllys boolean_t findSerial = FALSE; 48799ebb4caSwyllys KMF_X509_NAME issuerDN, subjectDN; 48899ebb4caSwyllys KMF_X509_NAME certIssuerDN, certSubjectDN; 48999ebb4caSwyllys 49099ebb4caSwyllys *match = FALSE; 49199ebb4caSwyllys if (xcert == NULL) { 49299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 49399ebb4caSwyllys } 49499ebb4caSwyllys 49599ebb4caSwyllys (void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME)); 49699ebb4caSwyllys (void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME)); 49799ebb4caSwyllys (void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME)); 49899ebb4caSwyllys (void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME)); 49999ebb4caSwyllys 50030a5e8faSwyllys if (issuer != NULL && strlen(issuer)) { 50130a5e8faSwyllys rv = kmf_dn_parser(issuer, &issuerDN); 50299ebb4caSwyllys if (rv != KMF_OK) 50399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 50499ebb4caSwyllys 505300fdee2SAndy Fiddaman rv = get_x509_dn(X509_get_issuer_name(xcert), &certIssuerDN); 50699ebb4caSwyllys if (rv != KMF_OK) { 50730a5e8faSwyllys kmf_free_dn(&issuerDN); 50899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 50999ebb4caSwyllys } 51099ebb4caSwyllys 51199ebb4caSwyllys findIssuer = TRUE; 51299ebb4caSwyllys } 51330a5e8faSwyllys if (subject != NULL && strlen(subject)) { 51430a5e8faSwyllys rv = kmf_dn_parser(subject, &subjectDN); 51599ebb4caSwyllys if (rv != KMF_OK) { 51699ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 51799ebb4caSwyllys goto cleanup; 51899ebb4caSwyllys } 51999ebb4caSwyllys 520300fdee2SAndy Fiddaman rv = get_x509_dn(X509_get_subject_name(xcert), &certSubjectDN); 52199ebb4caSwyllys if (rv != KMF_OK) { 52299ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 52399ebb4caSwyllys goto cleanup; 52499ebb4caSwyllys } 52599ebb4caSwyllys findSubject = TRUE; 52699ebb4caSwyllys } 52730a5e8faSwyllys if (serial != NULL && serial->val != NULL) 52899ebb4caSwyllys findSerial = TRUE; 52999ebb4caSwyllys 53099ebb4caSwyllys if (findSerial) { 53199ebb4caSwyllys BIGNUM *bn; 53299ebb4caSwyllys 53399ebb4caSwyllys /* Comparing BIGNUMs is a pain! */ 534300fdee2SAndy Fiddaman bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(xcert), NULL); 53599ebb4caSwyllys if (bn != NULL) { 53699ebb4caSwyllys int bnlen = BN_num_bytes(bn); 53799ebb4caSwyllys 53830a5e8faSwyllys if (bnlen == serial->len) { 53999ebb4caSwyllys uchar_t *a = malloc(bnlen); 54099ebb4caSwyllys if (a == NULL) { 54199ebb4caSwyllys rv = KMF_ERR_MEMORY; 54299ebb4caSwyllys BN_free(bn); 54399ebb4caSwyllys goto cleanup; 54499ebb4caSwyllys } 54599ebb4caSwyllys bnlen = BN_bn2bin(bn, a); 54630a5e8faSwyllys *match = (memcmp(a, serial->val, serial->len) == 54730a5e8faSwyllys 0); 54899ebb4caSwyllys rv = KMF_OK; 54999ebb4caSwyllys free(a); 55099ebb4caSwyllys } 55199ebb4caSwyllys BN_free(bn); 55299ebb4caSwyllys if (!(*match)) 55399ebb4caSwyllys goto cleanup; 55499ebb4caSwyllys } else { 55599ebb4caSwyllys rv = KMF_OK; 55699ebb4caSwyllys goto cleanup; 55799ebb4caSwyllys } 55899ebb4caSwyllys } 55999ebb4caSwyllys if (findIssuer) { 56030a5e8faSwyllys *match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0); 56130a5e8faSwyllys if ((*match) == B_FALSE) { 56230a5e8faSwyllys /* stop checking and bail */ 56399ebb4caSwyllys rv = KMF_OK; 56499ebb4caSwyllys goto cleanup; 56599ebb4caSwyllys } 56699ebb4caSwyllys } 56799ebb4caSwyllys if (findSubject) { 56830a5e8faSwyllys *match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0); 56930a5e8faSwyllys if ((*match) == B_FALSE) { 57030a5e8faSwyllys /* stop checking and bail */ 57199ebb4caSwyllys rv = KMF_OK; 57299ebb4caSwyllys goto cleanup; 57399ebb4caSwyllys } 57499ebb4caSwyllys } 57599ebb4caSwyllys 57699ebb4caSwyllys *match = TRUE; 57799ebb4caSwyllys cleanup: 57899ebb4caSwyllys if (findIssuer) { 57930a5e8faSwyllys kmf_free_dn(&issuerDN); 58030a5e8faSwyllys kmf_free_dn(&certIssuerDN); 58199ebb4caSwyllys } 58299ebb4caSwyllys if (findSubject) { 58330a5e8faSwyllys kmf_free_dn(&subjectDN); 58430a5e8faSwyllys kmf_free_dn(&certSubjectDN); 58599ebb4caSwyllys } 58699ebb4caSwyllys 58799ebb4caSwyllys return (rv); 58899ebb4caSwyllys } 58999ebb4caSwyllys 59030a5e8faSwyllys 59130a5e8faSwyllys /* 59230a5e8faSwyllys * This function loads a certificate file into an X509 data structure, and 59330a5e8faSwyllys * checks if its issuer, subject or the serial number matches with those 59430a5e8faSwyllys * values. If it matches, then return the X509 data structure. 59530a5e8faSwyllys */ 59699ebb4caSwyllys static KMF_RETURN 59799ebb4caSwyllys load_X509cert(KMF_HANDLE *kmfh, 59830a5e8faSwyllys char *issuer, char *subject, KMF_BIGINT *serial, 59930a5e8faSwyllys char *pathname, X509 **outcert) 60099ebb4caSwyllys { 60199ebb4caSwyllys KMF_RETURN rv = KMF_OK; 60299ebb4caSwyllys X509 *xcert = NULL; 60399ebb4caSwyllys BIO *bcert = NULL; 60499ebb4caSwyllys boolean_t match = FALSE; 60599ebb4caSwyllys KMF_ENCODE_FORMAT format; 60699ebb4caSwyllys 60799ebb4caSwyllys /* 60899ebb4caSwyllys * auto-detect the file format, regardless of what 60999ebb4caSwyllys * the 'format' parameters in the params say. 61099ebb4caSwyllys */ 61130a5e8faSwyllys rv = kmf_get_file_format(pathname, &format); 61299ebb4caSwyllys if (rv != KMF_OK) { 61399ebb4caSwyllys if (rv == KMF_ERR_OPEN_FILE) 61499ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND; 61599ebb4caSwyllys return (rv); 61699ebb4caSwyllys } 61799ebb4caSwyllys 61899ebb4caSwyllys /* Not ASN1(DER) format */ 61999ebb4caSwyllys if ((bcert = BIO_new_file(pathname, "rb")) == NULL) { 62099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 62199ebb4caSwyllys rv = KMF_ERR_OPEN_FILE; 62299ebb4caSwyllys goto cleanup; 62399ebb4caSwyllys } 62499ebb4caSwyllys 62599ebb4caSwyllys if (format == KMF_FORMAT_PEM) 62699ebb4caSwyllys xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL); 62799ebb4caSwyllys else if (format == KMF_FORMAT_ASN1) 62899ebb4caSwyllys xcert = d2i_X509_bio(bcert, NULL); 62999ebb4caSwyllys else if (format == KMF_FORMAT_PKCS12) { 63099ebb4caSwyllys PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL); 63199ebb4caSwyllys if (p12 != NULL) { 63299ebb4caSwyllys (void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL); 63399ebb4caSwyllys PKCS12_free(p12); 63499ebb4caSwyllys p12 = NULL; 63599ebb4caSwyllys } else { 63699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 63799ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 63899ebb4caSwyllys } 63999ebb4caSwyllys } else { 64099ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 64199ebb4caSwyllys goto cleanup; 64299ebb4caSwyllys } 64399ebb4caSwyllys 64499ebb4caSwyllys if (xcert == NULL) { 64599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 64699ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 64799ebb4caSwyllys goto cleanup; 64899ebb4caSwyllys } 64999ebb4caSwyllys 65030a5e8faSwyllys if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK || 65130a5e8faSwyllys match == FALSE) { 65299ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND; 65399ebb4caSwyllys goto cleanup; 65499ebb4caSwyllys } 65599ebb4caSwyllys 65699ebb4caSwyllys if (outcert != NULL) { 65799ebb4caSwyllys *outcert = xcert; 65899ebb4caSwyllys } 65999ebb4caSwyllys 66099ebb4caSwyllys cleanup: 66199ebb4caSwyllys if (bcert != NULL) (void) BIO_free(bcert); 66299ebb4caSwyllys if (rv != KMF_OK && xcert != NULL) 66399ebb4caSwyllys X509_free(xcert); 66499ebb4caSwyllys 66599ebb4caSwyllys return (rv); 66699ebb4caSwyllys } 66799ebb4caSwyllys 66871593db2Swyllys static int 66971593db2Swyllys datacmp(const void *a, const void *b) 67071593db2Swyllys { 67171593db2Swyllys KMF_DATA *adata = (KMF_DATA *)a; 67271593db2Swyllys KMF_DATA *bdata = (KMF_DATA *)b; 67371593db2Swyllys if (adata->Length > bdata->Length) 67471593db2Swyllys return (-1); 67571593db2Swyllys if (adata->Length < bdata->Length) 67671593db2Swyllys return (1); 67771593db2Swyllys return (0); 67871593db2Swyllys } 67971593db2Swyllys 68071593db2Swyllys static KMF_RETURN 68130a5e8faSwyllys load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial, 68230a5e8faSwyllys KMF_CERT_VALIDITY validity, char *pathname, 68371593db2Swyllys KMF_DATA **certlist, uint32_t *numcerts) 68471593db2Swyllys { 68571593db2Swyllys KMF_RETURN rv = KMF_OK; 68671593db2Swyllys int i; 68771593db2Swyllys KMF_DATA *certs = NULL; 68871593db2Swyllys int nc = 0; 68971593db2Swyllys int hits = 0; 69071593db2Swyllys KMF_ENCODE_FORMAT format; 69171593db2Swyllys 69230a5e8faSwyllys rv = kmf_get_file_format(pathname, &format); 69371593db2Swyllys if (rv != KMF_OK) { 69471593db2Swyllys if (rv == KMF_ERR_OPEN_FILE) 69571593db2Swyllys rv = KMF_ERR_CERT_NOT_FOUND; 69671593db2Swyllys return (rv); 69771593db2Swyllys } 69871593db2Swyllys if (format == KMF_FORMAT_ASN1) { 69971593db2Swyllys /* load a single certificate */ 70071593db2Swyllys certs = (KMF_DATA *)malloc(sizeof (KMF_DATA)); 70171593db2Swyllys if (certs == NULL) 70271593db2Swyllys return (KMF_ERR_MEMORY); 70371593db2Swyllys certs->Data = NULL; 70471593db2Swyllys certs->Length = 0; 70530a5e8faSwyllys rv = kmf_load_cert(kmfh, issuer, subject, serial, validity, 70630a5e8faSwyllys pathname, certs); 70771593db2Swyllys if (rv == KMF_OK) { 70871593db2Swyllys *certlist = certs; 70971593db2Swyllys *numcerts = 1; 710a2d4930dSDan OpenSolaris Anderson } else { 711a2d4930dSDan OpenSolaris Anderson kmf_free_data(certs); 712a2d4930dSDan OpenSolaris Anderson free(certs); 713a2d4930dSDan OpenSolaris Anderson certs = NULL; 71471593db2Swyllys } 71571593db2Swyllys return (rv); 71671593db2Swyllys } else if (format == KMF_FORMAT_PKCS12) { 71771593db2Swyllys /* We need a credential to access a PKCS#12 file */ 71871593db2Swyllys rv = KMF_ERR_BAD_CERT_FORMAT; 71971593db2Swyllys } else if (format == KMF_FORMAT_PEM || 72071593db2Swyllys format != KMF_FORMAT_PEM_KEYPAIR) { 721e65e5c2dSWyllys Ingersoll 72271593db2Swyllys /* This function only works on PEM files */ 72330a5e8faSwyllys rv = extract_pem(kmfh, issuer, subject, serial, pathname, 72434acef67Swyllys (uchar_t *)NULL, 0, NULL, &certs, &nc); 72571593db2Swyllys } else { 72671593db2Swyllys return (KMF_ERR_ENCODING); 72771593db2Swyllys } 72871593db2Swyllys 72971593db2Swyllys if (rv != KMF_OK) 73071593db2Swyllys return (rv); 73171593db2Swyllys 73271593db2Swyllys for (i = 0; i < nc; i++) { 73330a5e8faSwyllys if (validity == KMF_NONEXPIRED_CERTS) { 73430a5e8faSwyllys rv = kmf_check_cert_date(kmfh, &certs[i]); 73530a5e8faSwyllys } else if (validity == KMF_EXPIRED_CERTS) { 73630a5e8faSwyllys rv = kmf_check_cert_date(kmfh, &certs[i]); 73771593db2Swyllys if (rv == KMF_OK) 73871593db2Swyllys rv = KMF_ERR_CERT_NOT_FOUND; 73971593db2Swyllys if (rv == KMF_ERR_VALIDITY_PERIOD) 74071593db2Swyllys rv = KMF_OK; 74171593db2Swyllys } 74271593db2Swyllys if (rv != KMF_OK) { 74371593db2Swyllys /* Remove this cert from the list by clearing it. */ 74430a5e8faSwyllys kmf_free_data(&certs[i]); 74571593db2Swyllys } else { 74671593db2Swyllys hits++; /* count valid certs found */ 74771593db2Swyllys } 74871593db2Swyllys rv = KMF_OK; 74971593db2Swyllys } 750a2d4930dSDan OpenSolaris Anderson if (rv == KMF_OK && hits > 0) { 75171593db2Swyllys /* 75271593db2Swyllys * Sort the list of certs by length to put the cleared ones 75371593db2Swyllys * at the end so they don't get accessed by the caller. 75471593db2Swyllys */ 75571593db2Swyllys qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp); 75671593db2Swyllys *certlist = certs; 75771593db2Swyllys 75871593db2Swyllys /* since we sorted the list, just return the number of hits */ 75971593db2Swyllys *numcerts = hits; 760a2d4930dSDan OpenSolaris Anderson } else { 761e65e5c2dSWyllys Ingersoll if (rv == KMF_OK && hits == 0) 762a2d4930dSDan OpenSolaris Anderson rv = KMF_ERR_CERT_NOT_FOUND; 763a2d4930dSDan OpenSolaris Anderson if (certs != NULL) { 764a2d4930dSDan OpenSolaris Anderson free(certs); 765a2d4930dSDan OpenSolaris Anderson certs = NULL; 766a2d4930dSDan OpenSolaris Anderson } 767a2d4930dSDan OpenSolaris Anderson } 76871593db2Swyllys return (rv); 76971593db2Swyllys } 77071593db2Swyllys 77199ebb4caSwyllys static KMF_RETURN 77299ebb4caSwyllys kmf_load_cert(KMF_HANDLE *kmfh, 77330a5e8faSwyllys char *issuer, char *subject, KMF_BIGINT *serial, 77430a5e8faSwyllys KMF_CERT_VALIDITY validity, 77599ebb4caSwyllys char *pathname, 77699ebb4caSwyllys KMF_DATA *cert) 77799ebb4caSwyllys { 77899ebb4caSwyllys KMF_RETURN rv = KMF_OK; 77999ebb4caSwyllys X509 *x509cert = NULL; 78099ebb4caSwyllys 78130a5e8faSwyllys rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert); 78299ebb4caSwyllys if (rv == KMF_OK && x509cert != NULL && cert != NULL) { 78399ebb4caSwyllys rv = ssl_cert2KMFDATA(kmfh, x509cert, cert); 78499ebb4caSwyllys if (rv != KMF_OK) { 78599ebb4caSwyllys goto cleanup; 78699ebb4caSwyllys } 78730a5e8faSwyllys if (validity == KMF_NONEXPIRED_CERTS) { 78830a5e8faSwyllys rv = kmf_check_cert_date(kmfh, cert); 78930a5e8faSwyllys } else if (validity == KMF_EXPIRED_CERTS) { 79030a5e8faSwyllys rv = kmf_check_cert_date(kmfh, cert); 79199ebb4caSwyllys if (rv == KMF_OK) { 79299ebb4caSwyllys /* 79399ebb4caSwyllys * This is a valid cert so skip it. 79499ebb4caSwyllys */ 79599ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND; 79699ebb4caSwyllys } 79799ebb4caSwyllys if (rv == KMF_ERR_VALIDITY_PERIOD) { 79899ebb4caSwyllys /* 79999ebb4caSwyllys * We want to return success when we 80099ebb4caSwyllys * find an invalid cert. 80199ebb4caSwyllys */ 80299ebb4caSwyllys rv = KMF_OK; 80399ebb4caSwyllys goto cleanup; 80499ebb4caSwyllys } 80599ebb4caSwyllys } 80699ebb4caSwyllys } 80799ebb4caSwyllys cleanup: 80899ebb4caSwyllys if (x509cert != NULL) 80999ebb4caSwyllys X509_free(x509cert); 81099ebb4caSwyllys 81199ebb4caSwyllys return (rv); 81299ebb4caSwyllys } 81399ebb4caSwyllys 81402744e81Swyllys static KMF_RETURN 81502744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey) 81602744e81Swyllys { 81702744e81Swyllys KMF_RETURN ret = KMF_OK; 81802744e81Swyllys KMF_RAW_RSA_KEY rsa; 81902744e81Swyllys BerElement *asn1 = NULL; 82002744e81Swyllys BerValue filebuf; 82102744e81Swyllys BerValue OID = { NULL, 0 }; 82202744e81Swyllys BerValue *Mod = NULL, *PubExp = NULL; 82302744e81Swyllys BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL; 82402744e81Swyllys BerValue *Coef = NULL; 82502744e81Swyllys BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL; 82602744e81Swyllys BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL; 82702744e81Swyllys BIGNUM *qminus1 = NULL; 82802744e81Swyllys BN_CTX *ctx = NULL; 82902744e81Swyllys 83002744e81Swyllys *pkey = NULL; 83102744e81Swyllys 83202744e81Swyllys filebuf.bv_val = (char *)filedata->Data; 83302744e81Swyllys filebuf.bv_len = filedata->Length; 83402744e81Swyllys 83502744e81Swyllys asn1 = kmfder_init(&filebuf); 83602744e81Swyllys if (asn1 == NULL) { 83702744e81Swyllys ret = KMF_ERR_MEMORY; 83802744e81Swyllys goto out; 83902744e81Swyllys } 84002744e81Swyllys 84102744e81Swyllys if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}", 84202744e81Swyllys &OID, &Mod, &PubExp, &PriExp, &Prime1, 84302744e81Swyllys &Prime2, &Coef) == -1) { 84402744e81Swyllys ret = KMF_ERR_ENCODING; 84502744e81Swyllys goto out; 84602744e81Swyllys } 84702744e81Swyllys 84802744e81Swyllys /* 84902744e81Swyllys * We have to derive the 2 Exponents using Bignumber math. 85002744e81Swyllys * Exp1 = PriExp mod (Prime1 - 1) 85102744e81Swyllys * Exp2 = PriExp mod (Prime2 - 1) 85202744e81Swyllys */ 85302744e81Swyllys 85402744e81Swyllys /* D = PrivateExponent */ 85502744e81Swyllys D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D); 85602744e81Swyllys if (D == NULL) { 85702744e81Swyllys ret = KMF_ERR_MEMORY; 85802744e81Swyllys goto out; 85902744e81Swyllys } 86002744e81Swyllys 86102744e81Swyllys /* P = Prime1 (first prime factor of Modulus) */ 86202744e81Swyllys P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P); 86302744e81Swyllys if (D == NULL) { 86402744e81Swyllys ret = KMF_ERR_MEMORY; 86502744e81Swyllys goto out; 86602744e81Swyllys } 86702744e81Swyllys 86802744e81Swyllys /* Q = Prime2 (second prime factor of Modulus) */ 86902744e81Swyllys Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q); 87002744e81Swyllys 87102744e81Swyllys if ((ctx = BN_CTX_new()) == NULL) { 87202744e81Swyllys ret = KMF_ERR_MEMORY; 87302744e81Swyllys goto out; 87402744e81Swyllys } 87502744e81Swyllys 87602744e81Swyllys /* Compute (P - 1) */ 87702744e81Swyllys pminus1 = BN_new(); 87802744e81Swyllys (void) BN_sub(pminus1, P, BN_value_one()); 87902744e81Swyllys 88002744e81Swyllys /* Exponent1 = D mod (P - 1) */ 88102744e81Swyllys Exp1 = BN_new(); 88202744e81Swyllys (void) BN_mod(Exp1, D, pminus1, ctx); 88302744e81Swyllys 88402744e81Swyllys /* Compute (Q - 1) */ 88502744e81Swyllys qminus1 = BN_new(); 88602744e81Swyllys (void) BN_sub(qminus1, Q, BN_value_one()); 88702744e81Swyllys 88802744e81Swyllys /* Exponent2 = D mod (Q - 1) */ 88902744e81Swyllys Exp2 = BN_new(); 89002744e81Swyllys (void) BN_mod(Exp2, D, qminus1, ctx); 89102744e81Swyllys 89202744e81Swyllys /* Coef = (Inverse Q) mod P */ 89302744e81Swyllys COEF = BN_new(); 89402744e81Swyllys (void) BN_mod_inverse(COEF, Q, P, ctx); 89502744e81Swyllys 89602744e81Swyllys /* Convert back to KMF format */ 89702744e81Swyllys (void) memset(&rsa, 0, sizeof (rsa)); 89802744e81Swyllys 89902744e81Swyllys if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK) 90002744e81Swyllys goto out; 90102744e81Swyllys if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK) 90202744e81Swyllys goto out; 90302744e81Swyllys if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK) 90402744e81Swyllys goto out; 90502744e81Swyllys 90602744e81Swyllys rsa.mod.val = (uchar_t *)Mod->bv_val; 90702744e81Swyllys rsa.mod.len = Mod->bv_len; 90802744e81Swyllys 90902744e81Swyllys rsa.pubexp.val = (uchar_t *)PubExp->bv_val; 91002744e81Swyllys rsa.pubexp.len = PubExp->bv_len; 91102744e81Swyllys 91202744e81Swyllys rsa.priexp.val = (uchar_t *)PriExp->bv_val; 91302744e81Swyllys rsa.priexp.len = PriExp->bv_len; 91402744e81Swyllys 91502744e81Swyllys rsa.prime1.val = (uchar_t *)Prime1->bv_val; 91602744e81Swyllys rsa.prime1.len = Prime1->bv_len; 91702744e81Swyllys 91802744e81Swyllys rsa.prime2.val = (uchar_t *)Prime2->bv_val; 91902744e81Swyllys rsa.prime2.len = Prime2->bv_len; 92002744e81Swyllys 92102744e81Swyllys *pkey = ImportRawRSAKey(&rsa); 92202744e81Swyllys out: 92302744e81Swyllys if (asn1 != NULL) 92402744e81Swyllys kmfber_free(asn1, 1); 92502744e81Swyllys 92602744e81Swyllys if (OID.bv_val) { 92702744e81Swyllys free(OID.bv_val); 92802744e81Swyllys } 92902744e81Swyllys if (PriExp) 93002744e81Swyllys free(PriExp); 93102744e81Swyllys 93202744e81Swyllys if (Mod) 93302744e81Swyllys free(Mod); 93402744e81Swyllys 93502744e81Swyllys if (PubExp) 93602744e81Swyllys free(PubExp); 93702744e81Swyllys 93802744e81Swyllys if (Coef) { 93902744e81Swyllys (void) memset(Coef->bv_val, 0, Coef->bv_len); 94002744e81Swyllys free(Coef->bv_val); 94102744e81Swyllys free(Coef); 94202744e81Swyllys } 94302744e81Swyllys if (Prime1) 94402744e81Swyllys free(Prime1); 94502744e81Swyllys if (Prime2) 94602744e81Swyllys free(Prime2); 94702744e81Swyllys 94802744e81Swyllys if (ctx != NULL) 94902744e81Swyllys BN_CTX_free(ctx); 95002744e81Swyllys 95102744e81Swyllys if (D) 95202744e81Swyllys BN_clear_free(D); 95302744e81Swyllys if (P) 95402744e81Swyllys BN_clear_free(P); 95502744e81Swyllys if (Q) 95602744e81Swyllys BN_clear_free(Q); 95702744e81Swyllys if (pminus1) 95802744e81Swyllys BN_clear_free(pminus1); 95902744e81Swyllys if (qminus1) 96002744e81Swyllys BN_clear_free(qminus1); 96102744e81Swyllys if (Exp1) 96202744e81Swyllys BN_clear_free(Exp1); 96302744e81Swyllys if (Exp2) 96402744e81Swyllys BN_clear_free(Exp2); 96502744e81Swyllys 96602744e81Swyllys return (ret); 96702744e81Swyllys 96802744e81Swyllys } 96902744e81Swyllys 97099ebb4caSwyllys static EVP_PKEY * 97199ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file) 97299ebb4caSwyllys { 97399ebb4caSwyllys BIO *keyfile = NULL; 97499ebb4caSwyllys EVP_PKEY *pkey = NULL; 97599ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 97699ebb4caSwyllys KMF_ENCODE_FORMAT format; 97702744e81Swyllys KMF_RETURN rv; 97802744e81Swyllys KMF_DATA filedata; 97999ebb4caSwyllys 98099ebb4caSwyllys if (file == NULL) { 98199ebb4caSwyllys return (NULL); 98299ebb4caSwyllys } 98399ebb4caSwyllys 98430a5e8faSwyllys if (kmf_get_file_format((char *)file, &format) != KMF_OK) 98599ebb4caSwyllys return (NULL); 98699ebb4caSwyllys 98799ebb4caSwyllys keyfile = BIO_new_file(file, "rb"); 98899ebb4caSwyllys if (keyfile == NULL) { 98999ebb4caSwyllys goto end; 99099ebb4caSwyllys } 99199ebb4caSwyllys 99202744e81Swyllys if (format == KMF_FORMAT_ASN1) { 99399ebb4caSwyllys pkey = d2i_PrivateKey_bio(keyfile, NULL); 99402744e81Swyllys if (pkey == NULL) { 99502744e81Swyllys 99602744e81Swyllys (void) BIO_free(keyfile); 99702744e81Swyllys keyfile = NULL; 99802744e81Swyllys /* Try odd ASN.1 variations */ 99930a5e8faSwyllys rv = kmf_read_input_file(kmfh, (char *)file, 100002744e81Swyllys &filedata); 100102744e81Swyllys if (rv == KMF_OK) { 100202744e81Swyllys (void) readAltFormatPrivateKey(&filedata, 100302744e81Swyllys &pkey); 100430a5e8faSwyllys kmf_free_data(&filedata); 100502744e81Swyllys } 100602744e81Swyllys } 100702744e81Swyllys } else if (format == KMF_FORMAT_PEM || 100802744e81Swyllys format == KMF_FORMAT_PEM_KEYPAIR) { 100999ebb4caSwyllys pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL); 101002744e81Swyllys if (pkey == NULL) { 101102744e81Swyllys KMF_DATA derdata; 101202744e81Swyllys /* 101302744e81Swyllys * Check if this is the alt. format 101402744e81Swyllys * RSA private key file. 101502744e81Swyllys */ 101630a5e8faSwyllys rv = kmf_read_input_file(kmfh, (char *)file, 101702744e81Swyllys &filedata); 101802744e81Swyllys if (rv == KMF_OK) { 101902744e81Swyllys uchar_t *d = NULL; 102002744e81Swyllys int len; 102130a5e8faSwyllys rv = kmf_pem_to_der(filedata.Data, 102202744e81Swyllys filedata.Length, &d, &len); 102302744e81Swyllys if (rv == KMF_OK && d != NULL) { 102402744e81Swyllys derdata.Data = d; 102502744e81Swyllys derdata.Length = (size_t)len; 102602744e81Swyllys (void) readAltFormatPrivateKey( 102702744e81Swyllys &derdata, &pkey); 102802744e81Swyllys free(d); 102902744e81Swyllys } 103030a5e8faSwyllys kmf_free_data(&filedata); 103102744e81Swyllys } 103202744e81Swyllys } 103302744e81Swyllys } 103499ebb4caSwyllys 103599ebb4caSwyllys end: 103699ebb4caSwyllys if (pkey == NULL) 103799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 103899ebb4caSwyllys 103999ebb4caSwyllys if (keyfile != NULL) 104099ebb4caSwyllys (void) BIO_free(keyfile); 104199ebb4caSwyllys 104299ebb4caSwyllys return (pkey); 104399ebb4caSwyllys } 104499ebb4caSwyllys 104599ebb4caSwyllys KMF_RETURN 104630a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 104799ebb4caSwyllys { 104899ebb4caSwyllys KMF_RETURN rv = KMF_OK; 104999ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 1050f482c776Swyllys int i, n; 1051f482c776Swyllys uint32_t maxcerts = 0; 105230a5e8faSwyllys uint32_t *num_certs; 105330a5e8faSwyllys KMF_X509_DER_CERT *kmf_cert = NULL; 105430a5e8faSwyllys char *dirpath = NULL; 105530a5e8faSwyllys char *filename = NULL; 105630a5e8faSwyllys char *fullpath = NULL; 105730a5e8faSwyllys char *issuer = NULL; 105830a5e8faSwyllys char *subject = NULL; 105930a5e8faSwyllys KMF_BIGINT *serial = NULL; 106030a5e8faSwyllys KMF_CERT_VALIDITY validity; 106199ebb4caSwyllys 106230a5e8faSwyllys num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr); 106330a5e8faSwyllys if (num_certs == NULL) 106499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 106599ebb4caSwyllys 106630a5e8faSwyllys /* num_certs should reference the size of kmf_cert */ 1067f482c776Swyllys maxcerts = *num_certs; 1068f482c776Swyllys if (maxcerts == 0) 1069f482c776Swyllys maxcerts = 0xFFFFFFFF; 107099ebb4caSwyllys *num_certs = 0; 107199ebb4caSwyllys 107230a5e8faSwyllys /* Get the optional returned certificate list */ 107330a5e8faSwyllys kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist, 107430a5e8faSwyllys numattr); 107599ebb4caSwyllys 107630a5e8faSwyllys /* 107730a5e8faSwyllys * The dirpath attribute and the filename attribute can not be NULL 107830a5e8faSwyllys * at the same time. 107930a5e8faSwyllys */ 108030a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 108130a5e8faSwyllys filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, 108230a5e8faSwyllys numattr); 108330a5e8faSwyllys 108430a5e8faSwyllys fullpath = get_fullpath(dirpath, filename); 108599ebb4caSwyllys if (fullpath == NULL) 108699ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 108799ebb4caSwyllys 108830a5e8faSwyllys /* Get optional search criteria attributes */ 108930a5e8faSwyllys issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr); 109030a5e8faSwyllys subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr); 109130a5e8faSwyllys serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr); 109230a5e8faSwyllys rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr, 109330a5e8faSwyllys &validity, NULL); 109430a5e8faSwyllys if (rv != KMF_OK) { 109530a5e8faSwyllys validity = KMF_ALL_CERTS; 109630a5e8faSwyllys rv = KMF_OK; 109730a5e8faSwyllys } 109830a5e8faSwyllys 109999ebb4caSwyllys if (isdir(fullpath)) { 110099ebb4caSwyllys DIR *dirp; 110199ebb4caSwyllys struct dirent *dp; 110299ebb4caSwyllys 1103f482c776Swyllys n = 0; 110499ebb4caSwyllys /* open all files in the directory and attempt to read them */ 110599ebb4caSwyllys if ((dirp = opendir(fullpath)) == NULL) { 110699ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 110799ebb4caSwyllys } 110899ebb4caSwyllys while ((dp = readdir(dirp)) != NULL) { 110999ebb4caSwyllys char *fname; 111071593db2Swyllys KMF_DATA *certlist = NULL; 1111f482c776Swyllys uint32_t loaded_certs = 0; 111271593db2Swyllys 111399ebb4caSwyllys if (strcmp(dp->d_name, ".") == 0 || 111499ebb4caSwyllys strcmp(dp->d_name, "..") == 0) 111599ebb4caSwyllys continue; 111699ebb4caSwyllys 111734acef67Swyllys fname = get_fullpath(fullpath, (char *)&dp->d_name); 111899ebb4caSwyllys 111930a5e8faSwyllys rv = load_certs(kmfh, issuer, subject, serial, 112030a5e8faSwyllys validity, fname, &certlist, &loaded_certs); 112199ebb4caSwyllys 112299ebb4caSwyllys if (rv != KMF_OK) { 112399ebb4caSwyllys free(fname); 112471593db2Swyllys if (certlist != NULL) { 1125f482c776Swyllys for (i = 0; i < loaded_certs; i++) 112630a5e8faSwyllys kmf_free_data(&certlist[i]); 112771593db2Swyllys free(certlist); 112871593db2Swyllys } 112999ebb4caSwyllys continue; 113099ebb4caSwyllys } 113199ebb4caSwyllys 113299ebb4caSwyllys /* If load succeeds, add certdata to the list */ 113399ebb4caSwyllys if (kmf_cert != NULL) { 1134f482c776Swyllys for (i = 0; i < loaded_certs && 1135b4058258Swyllys n < maxcerts; i++) { 113671593db2Swyllys kmf_cert[n].certificate.Data = 113771593db2Swyllys certlist[i].Data; 113899ebb4caSwyllys kmf_cert[n].certificate.Length = 113971593db2Swyllys certlist[i].Length; 114099ebb4caSwyllys 114199ebb4caSwyllys kmf_cert[n].kmf_private.keystore_type = 114299ebb4caSwyllys KMF_KEYSTORE_OPENSSL; 114399ebb4caSwyllys kmf_cert[n].kmf_private.flags = 114499ebb4caSwyllys KMF_FLAG_CERT_VALID; 114571593db2Swyllys kmf_cert[n].kmf_private.label = 114671593db2Swyllys strdup(fname); 114799ebb4caSwyllys n++; 114899ebb4caSwyllys } 1149b4058258Swyllys /* 1150b4058258Swyllys * If maxcerts < loaded_certs, clean up the 1151b4058258Swyllys * certs that were not used. 1152b4058258Swyllys */ 1153f482c776Swyllys for (; i < loaded_certs; i++) 115430a5e8faSwyllys kmf_free_data(&certlist[i]); 1155f482c776Swyllys } else { 1156f482c776Swyllys for (i = 0; i < loaded_certs; i++) 115730a5e8faSwyllys kmf_free_data(&certlist[i]); 1158f482c776Swyllys n += loaded_certs; 115971593db2Swyllys } 1160f482c776Swyllys free(certlist); 116171593db2Swyllys free(fname); 116271593db2Swyllys } 116399ebb4caSwyllys (*num_certs) = n; 116499ebb4caSwyllys if (*num_certs == 0) 116599ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND; 116630a5e8faSwyllys if (*num_certs > 0) 116799ebb4caSwyllys rv = KMF_OK; 116899ebb4caSwyllys exit: 116999ebb4caSwyllys (void) closedir(dirp); 117099ebb4caSwyllys } else { 117171593db2Swyllys KMF_DATA *certlist = NULL; 1172f482c776Swyllys uint32_t loaded_certs = 0; 117371593db2Swyllys 117430a5e8faSwyllys rv = load_certs(kmfh, issuer, subject, serial, validity, 117530a5e8faSwyllys fullpath, &certlist, &loaded_certs); 117699ebb4caSwyllys if (rv != KMF_OK) { 117799ebb4caSwyllys free(fullpath); 117899ebb4caSwyllys return (rv); 117999ebb4caSwyllys } 118099ebb4caSwyllys 1181f482c776Swyllys n = 0; 118271593db2Swyllys if (kmf_cert != NULL && certlist != NULL) { 1183f482c776Swyllys for (i = 0; i < loaded_certs && i < maxcerts; i++) { 1184f482c776Swyllys kmf_cert[n].certificate.Data = 118571593db2Swyllys certlist[i].Data; 1186f482c776Swyllys kmf_cert[n].certificate.Length = 118771593db2Swyllys certlist[i].Length; 1188f482c776Swyllys kmf_cert[n].kmf_private.keystore_type = 118999ebb4caSwyllys KMF_KEYSTORE_OPENSSL; 1190f482c776Swyllys kmf_cert[n].kmf_private.flags = 119171593db2Swyllys KMF_FLAG_CERT_VALID; 1192f482c776Swyllys kmf_cert[n].kmf_private.label = 119371593db2Swyllys strdup(fullpath); 1194f482c776Swyllys n++; 119571593db2Swyllys } 1196f482c776Swyllys /* If maxcerts < loaded_certs, clean up */ 1197f482c776Swyllys for (; i < loaded_certs; i++) 119830a5e8faSwyllys kmf_free_data(&certlist[i]); 1199f482c776Swyllys } else if (certlist != NULL) { 1200f482c776Swyllys for (i = 0; i < loaded_certs; i++) 120130a5e8faSwyllys kmf_free_data(&certlist[i]); 1202f482c776Swyllys n = loaded_certs; 1203f482c776Swyllys } 120430a5e8faSwyllys if (certlist != NULL) 120571593db2Swyllys free(certlist); 1206f482c776Swyllys *num_certs = n; 120799ebb4caSwyllys } 120899ebb4caSwyllys 120999ebb4caSwyllys free(fullpath); 121099ebb4caSwyllys 121199ebb4caSwyllys return (rv); 121299ebb4caSwyllys } 121399ebb4caSwyllys 121499ebb4caSwyllys void 121599ebb4caSwyllys /*ARGSUSED*/ 121699ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle, 121799ebb4caSwyllys KMF_X509_DER_CERT *kmf_cert) 121899ebb4caSwyllys { 121999ebb4caSwyllys if (kmf_cert != NULL) { 122099ebb4caSwyllys if (kmf_cert->certificate.Data != NULL) { 1221e65e5c2dSWyllys Ingersoll kmf_free_data(&kmf_cert->certificate); 122299ebb4caSwyllys } 122399ebb4caSwyllys if (kmf_cert->kmf_private.label) 122499ebb4caSwyllys free(kmf_cert->kmf_private.label); 122599ebb4caSwyllys } 122699ebb4caSwyllys } 122799ebb4caSwyllys 122830a5e8faSwyllys /*ARGSUSED*/ 122999ebb4caSwyllys KMF_RETURN 123030a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 123199ebb4caSwyllys { 123299ebb4caSwyllys KMF_RETURN ret = KMF_OK; 123330a5e8faSwyllys KMF_DATA *cert = NULL; 123430a5e8faSwyllys char *outfilename = NULL; 123530a5e8faSwyllys char *dirpath = NULL; 123630a5e8faSwyllys char *fullpath = NULL; 123799ebb4caSwyllys KMF_ENCODE_FORMAT format; 123899ebb4caSwyllys 123930a5e8faSwyllys /* Get the cert data */ 124030a5e8faSwyllys cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr); 124130a5e8faSwyllys if (cert == NULL || cert->Data == NULL) 124299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 124399ebb4caSwyllys 124430a5e8faSwyllys /* Check the output filename and directory attributes. */ 124530a5e8faSwyllys outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, 124630a5e8faSwyllys numattr); 124730a5e8faSwyllys if (outfilename == NULL) 124830a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 124999ebb4caSwyllys 125030a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 125130a5e8faSwyllys fullpath = get_fullpath(dirpath, outfilename); 125299ebb4caSwyllys if (fullpath == NULL) 125330a5e8faSwyllys return (KMF_ERR_BAD_CERTFILE); 125499ebb4caSwyllys 125530a5e8faSwyllys /* Check the optional format attribute */ 125630a5e8faSwyllys ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 125730a5e8faSwyllys &format, NULL); 125830a5e8faSwyllys if (ret != KMF_OK) { 125930a5e8faSwyllys /* If there is no format attribute, then default to PEM */ 126030a5e8faSwyllys format = KMF_FORMAT_PEM; 126199ebb4caSwyllys ret = KMF_OK; 126230a5e8faSwyllys } else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) { 126330a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 126499ebb4caSwyllys goto out; 126599ebb4caSwyllys } 126699ebb4caSwyllys 126730a5e8faSwyllys /* Store the certificate in the file with the specified format */ 126830a5e8faSwyllys ret = kmf_create_cert_file(cert, format, fullpath); 126999ebb4caSwyllys 127099ebb4caSwyllys out: 127199ebb4caSwyllys if (fullpath != NULL) 127299ebb4caSwyllys free(fullpath); 127399ebb4caSwyllys 127499ebb4caSwyllys return (ret); 127599ebb4caSwyllys } 127699ebb4caSwyllys 127730a5e8faSwyllys 127899ebb4caSwyllys KMF_RETURN 127930a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 128099ebb4caSwyllys { 128199ebb4caSwyllys KMF_RETURN rv; 128299ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 12836b35cb3cSRichard PALO KMF_DATA certdata = { 0, NULL }; 128430a5e8faSwyllys char *dirpath = NULL; 128530a5e8faSwyllys char *filename = NULL; 128630a5e8faSwyllys char *fullpath = NULL; 128730a5e8faSwyllys char *issuer = NULL; 128830a5e8faSwyllys char *subject = NULL; 128930a5e8faSwyllys KMF_BIGINT *serial = NULL; 129030a5e8faSwyllys KMF_CERT_VALIDITY validity; 129199ebb4caSwyllys 129230a5e8faSwyllys /* 129330a5e8faSwyllys * Get the DIRPATH and CERT_FILENAME attributes. They can not be 129430a5e8faSwyllys * NULL at the same time. 129530a5e8faSwyllys */ 129630a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 129730a5e8faSwyllys filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, 129830a5e8faSwyllys numattr); 129930a5e8faSwyllys fullpath = get_fullpath(dirpath, filename); 130099ebb4caSwyllys if (fullpath == NULL) 130199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 130299ebb4caSwyllys 130330a5e8faSwyllys /* Get optional search criteria attributes */ 130430a5e8faSwyllys issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr); 130530a5e8faSwyllys subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr); 130630a5e8faSwyllys serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr); 130730a5e8faSwyllys rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr, 130830a5e8faSwyllys &validity, NULL); 130930a5e8faSwyllys if (rv != KMF_OK) { 131030a5e8faSwyllys validity = KMF_ALL_CERTS; 131130a5e8faSwyllys rv = KMF_OK; 131230a5e8faSwyllys } 131330a5e8faSwyllys 131499ebb4caSwyllys if (isdir(fullpath)) { 131599ebb4caSwyllys DIR *dirp; 131699ebb4caSwyllys struct dirent *dp; 131799ebb4caSwyllys 131899ebb4caSwyllys /* open all files in the directory and attempt to read them */ 131999ebb4caSwyllys if ((dirp = opendir(fullpath)) == NULL) { 132099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 132199ebb4caSwyllys } 132299ebb4caSwyllys 132399ebb4caSwyllys while ((dp = readdir(dirp)) != NULL) { 132499ebb4caSwyllys if (strcmp(dp->d_name, ".") != 0 && 132599ebb4caSwyllys strcmp(dp->d_name, "..") != 0) { 132699ebb4caSwyllys char *fname; 132799ebb4caSwyllys 132899ebb4caSwyllys fname = get_fullpath(fullpath, 132999ebb4caSwyllys (char *)&dp->d_name); 133099ebb4caSwyllys 133199ebb4caSwyllys if (fname == NULL) { 133299ebb4caSwyllys rv = KMF_ERR_MEMORY; 133399ebb4caSwyllys break; 133499ebb4caSwyllys } 133599ebb4caSwyllys 133630a5e8faSwyllys rv = kmf_load_cert(kmfh, issuer, subject, 133730a5e8faSwyllys serial, validity, fname, &certdata); 133899ebb4caSwyllys 133999ebb4caSwyllys if (rv == KMF_ERR_CERT_NOT_FOUND) { 134099ebb4caSwyllys free(fname); 1341e65e5c2dSWyllys Ingersoll kmf_free_data(&certdata); 134299ebb4caSwyllys rv = KMF_OK; 134399ebb4caSwyllys continue; 134499ebb4caSwyllys } else if (rv != KMF_OK) { 134599ebb4caSwyllys free(fname); 134699ebb4caSwyllys break; 134799ebb4caSwyllys } 134899ebb4caSwyllys 134999ebb4caSwyllys if (unlink(fname) != 0) { 135099ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 135199ebb4caSwyllys rv = KMF_ERR_INTERNAL; 135299ebb4caSwyllys free(fname); 135399ebb4caSwyllys break; 135499ebb4caSwyllys } 135599ebb4caSwyllys free(fname); 1356e65e5c2dSWyllys Ingersoll kmf_free_data(&certdata); 135799ebb4caSwyllys } 135899ebb4caSwyllys } 135999ebb4caSwyllys (void) closedir(dirp); 136099ebb4caSwyllys } else { 136199ebb4caSwyllys /* Just try to load a single certificate */ 136230a5e8faSwyllys rv = kmf_load_cert(kmfh, issuer, subject, serial, validity, 136330a5e8faSwyllys fullpath, &certdata); 136499ebb4caSwyllys if (rv == KMF_OK) { 136599ebb4caSwyllys if (unlink(fullpath) != 0) { 136699ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 136799ebb4caSwyllys rv = KMF_ERR_INTERNAL; 136899ebb4caSwyllys } 136999ebb4caSwyllys } 137099ebb4caSwyllys } 137199ebb4caSwyllys 137299ebb4caSwyllys out: 137399ebb4caSwyllys if (fullpath != NULL) 137499ebb4caSwyllys free(fullpath); 137599ebb4caSwyllys 1376e65e5c2dSWyllys Ingersoll kmf_free_data(&certdata); 137799ebb4caSwyllys 137899ebb4caSwyllys return (rv); 137999ebb4caSwyllys } 138099ebb4caSwyllys 138199ebb4caSwyllys KMF_RETURN 138299ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, 138399ebb4caSwyllys KMF_DATA *keydata) 138499ebb4caSwyllys { 138599ebb4caSwyllys KMF_RETURN rv = KMF_OK; 138699ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 138799ebb4caSwyllys int n; 138899ebb4caSwyllys 138999ebb4caSwyllys if (key == NULL || keydata == NULL || 139099ebb4caSwyllys key->keyp == NULL) 139199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 139299ebb4caSwyllys 139399ebb4caSwyllys if (key->keyalg == KMF_RSA) { 139499ebb4caSwyllys RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp); 139599ebb4caSwyllys 139699ebb4caSwyllys if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) { 139799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 139899ebb4caSwyllys return (KMF_ERR_ENCODING); 139999ebb4caSwyllys } 140099ebb4caSwyllys RSA_free(pubkey); 140199ebb4caSwyllys } else if (key->keyalg == KMF_DSA) { 140299ebb4caSwyllys DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp); 140399ebb4caSwyllys 140499ebb4caSwyllys if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) { 140599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 140699ebb4caSwyllys return (KMF_ERR_ENCODING); 140799ebb4caSwyllys } 140899ebb4caSwyllys DSA_free(pubkey); 140999ebb4caSwyllys } else { 141099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 141199ebb4caSwyllys } 141299ebb4caSwyllys keydata->Length = n; 141399ebb4caSwyllys 141499ebb4caSwyllys cleanup: 141599ebb4caSwyllys if (rv != KMF_OK) { 141699ebb4caSwyllys if (keydata->Data) 141799ebb4caSwyllys free(keydata->Data); 141899ebb4caSwyllys keydata->Data = NULL; 141999ebb4caSwyllys keydata->Length = 0; 142099ebb4caSwyllys } 142199ebb4caSwyllys 142299ebb4caSwyllys return (rv); 142399ebb4caSwyllys } 142499ebb4caSwyllys 142599ebb4caSwyllys static KMF_RETURN 142630a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out, 142730a5e8faSwyllys KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private) 142899ebb4caSwyllys { 142999ebb4caSwyllys int rv = 0; 143099ebb4caSwyllys RSA *rsa; 143199ebb4caSwyllys DSA *dsa; 143299ebb4caSwyllys 14335b3e1433Swyllys if (pkey == NULL || out == NULL) 14345b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 14355b3e1433Swyllys 143699ebb4caSwyllys switch (format) { 143773cc0e02Swyllys case KMF_FORMAT_RAWKEY: 143873cc0e02Swyllys /* same as ASN.1 */ 143999ebb4caSwyllys case KMF_FORMAT_ASN1: 1440300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) { 144130a5e8faSwyllys if (private) 144299ebb4caSwyllys rv = i2d_RSAPrivateKey_bio(out, rsa); 144330a5e8faSwyllys else 144430a5e8faSwyllys rv = i2d_RSAPublicKey_bio(out, rsa); 1445300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) { 144699ebb4caSwyllys rv = i2d_DSAPrivateKey_bio(out, dsa); 144799ebb4caSwyllys } 144899ebb4caSwyllys if (rv == 1) { 144999ebb4caSwyllys rv = KMF_OK; 145099ebb4caSwyllys } else { 145199ebb4caSwyllys SET_ERROR(kmfh, rv); 145299ebb4caSwyllys } 145399ebb4caSwyllys break; 145499ebb4caSwyllys case KMF_FORMAT_PEM: 1455300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) { 145630a5e8faSwyllys if (private) 145799ebb4caSwyllys rv = PEM_write_bio_RSAPrivateKey(out, 145830a5e8faSwyllys rsa, NULL, NULL, 0, NULL, 145930a5e8faSwyllys (cred != NULL ? cred->cred : NULL)); 146030a5e8faSwyllys else 146130a5e8faSwyllys rv = PEM_write_bio_RSAPublicKey(out, 146230a5e8faSwyllys rsa); 1463300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) { 146499ebb4caSwyllys rv = PEM_write_bio_DSAPrivateKey(out, 146530a5e8faSwyllys dsa, NULL, NULL, 0, NULL, 146630a5e8faSwyllys (cred != NULL ? cred->cred : NULL)); 146799ebb4caSwyllys } 146899ebb4caSwyllys 146999ebb4caSwyllys if (rv == 1) { 147099ebb4caSwyllys rv = KMF_OK; 147199ebb4caSwyllys } else { 147299ebb4caSwyllys SET_ERROR(kmfh, rv); 147399ebb4caSwyllys } 147499ebb4caSwyllys break; 147599ebb4caSwyllys 147699ebb4caSwyllys default: 147799ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 147899ebb4caSwyllys } 147999ebb4caSwyllys 148099ebb4caSwyllys return (rv); 148199ebb4caSwyllys } 148299ebb4caSwyllys 148399ebb4caSwyllys KMF_RETURN 148430a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr, 148530a5e8faSwyllys KMF_ATTRIBUTE *attrlist) 148699ebb4caSwyllys { 148799ebb4caSwyllys KMF_RETURN rv = KMF_OK; 148899ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 1489300fdee2SAndy Fiddaman uint32_t eValue = RSA_F4; 1490300fdee2SAndy Fiddaman BIGNUM *eValue_bn = NULL; 149199ebb4caSwyllys RSA *sslPrivKey = NULL; 149299ebb4caSwyllys DSA *sslDSAKey = NULL; 149399ebb4caSwyllys EVP_PKEY *eprikey = NULL; 149499ebb4caSwyllys EVP_PKEY *epubkey = NULL; 149599ebb4caSwyllys BIO *out = NULL; 149630a5e8faSwyllys KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL; 149730a5e8faSwyllys uint32_t keylen = 1024; 149830a5e8faSwyllys uint32_t keylen_size = sizeof (uint32_t); 149930a5e8faSwyllys boolean_t storekey = TRUE; 150030a5e8faSwyllys KMF_KEY_ALG keytype = KMF_RSA; 150199ebb4caSwyllys 1502300fdee2SAndy Fiddaman eValue_bn = BN_new(); 1503300fdee2SAndy Fiddaman if (eValue_bn == NULL) 1504300fdee2SAndy Fiddaman return (KMF_ERR_MEMORY); 1505300fdee2SAndy Fiddaman if (BN_set_word(eValue_bn, eValue) == 0) { 1506300fdee2SAndy Fiddaman rv = KMF_ERR_KEYGEN_FAILED; 1507300fdee2SAndy Fiddaman goto cleanup; 1508300fdee2SAndy Fiddaman } 1509300fdee2SAndy Fiddaman 151030a5e8faSwyllys rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr, 151130a5e8faSwyllys &storekey, NULL); 151230a5e8faSwyllys if (rv != KMF_OK) { 151330a5e8faSwyllys /* "storekey" is optional. Default is TRUE */ 151430a5e8faSwyllys rv = KMF_OK; 151599ebb4caSwyllys } 151699ebb4caSwyllys 151730a5e8faSwyllys rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, 151830a5e8faSwyllys (void *)&keytype, NULL); 151930a5e8faSwyllys if (rv != KMF_OK) 152030a5e8faSwyllys /* keytype is optional. KMF_RSA is default */ 152130a5e8faSwyllys rv = KMF_OK; 152299ebb4caSwyllys 152330a5e8faSwyllys pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr); 1524300fdee2SAndy Fiddaman if (pubkey == NULL) { 1525300fdee2SAndy Fiddaman rv = KMF_ERR_BAD_PARAMETER; 1526300fdee2SAndy Fiddaman goto cleanup; 1527300fdee2SAndy Fiddaman } 152899ebb4caSwyllys 152930a5e8faSwyllys privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr); 1530300fdee2SAndy Fiddaman if (privkey == NULL) { 1531300fdee2SAndy Fiddaman rv = KMF_ERR_BAD_PARAMETER; 1532300fdee2SAndy Fiddaman goto cleanup; 1533300fdee2SAndy Fiddaman } 153430a5e8faSwyllys 153530a5e8faSwyllys (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE)); 153630a5e8faSwyllys (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE)); 153799ebb4caSwyllys 153899ebb4caSwyllys eprikey = EVP_PKEY_new(); 153999ebb4caSwyllys if (eprikey == NULL) { 154099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 154199ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 154299ebb4caSwyllys goto cleanup; 154399ebb4caSwyllys } 154499ebb4caSwyllys epubkey = EVP_PKEY_new(); 154599ebb4caSwyllys if (epubkey == NULL) { 154699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 154799ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 154899ebb4caSwyllys goto cleanup; 154999ebb4caSwyllys } 155030a5e8faSwyllys if (keytype == KMF_RSA) { 155130a5e8faSwyllys KMF_BIGINT *rsaexp = NULL; 155299ebb4caSwyllys 155330a5e8faSwyllys rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr); 155430a5e8faSwyllys if (rsaexp != NULL) { 155530a5e8faSwyllys if (rsaexp->len > 0 && 155630a5e8faSwyllys rsaexp->len <= sizeof (eValue) && 155730a5e8faSwyllys rsaexp->val != NULL) { 1558a2d4930dSDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */ 155930a5e8faSwyllys eValue = *(uint32_t *)rsaexp->val; 1560300fdee2SAndy Fiddaman if (BN_set_word(eValue_bn, eValue) == 0) { 1561300fdee2SAndy Fiddaman rv = KMF_ERR_BAD_PARAMETER; 1562300fdee2SAndy Fiddaman goto cleanup; 1563300fdee2SAndy Fiddaman } 156430a5e8faSwyllys } else { 156530a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 156630a5e8faSwyllys goto cleanup; 156730a5e8faSwyllys } 156830a5e8faSwyllys } else { 156930a5e8faSwyllys /* RSA Exponent is optional. Default is 0x10001 */ 157030a5e8faSwyllys rv = KMF_OK; 157130a5e8faSwyllys } 157230a5e8faSwyllys 157330a5e8faSwyllys rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, 157430a5e8faSwyllys &keylen, &keylen_size); 157530a5e8faSwyllys if (rv == KMF_ERR_ATTR_NOT_FOUND) 157630a5e8faSwyllys /* keylen is optional, default is 1024 */ 157730a5e8faSwyllys rv = KMF_OK; 157830a5e8faSwyllys if (rv != KMF_OK) { 157930a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 158030a5e8faSwyllys goto cleanup; 158130a5e8faSwyllys } 158230a5e8faSwyllys 1583300fdee2SAndy Fiddaman sslPrivKey = RSA_new(); 1584300fdee2SAndy Fiddaman if (sslPrivKey == NULL || 1585300fdee2SAndy Fiddaman RSA_generate_key_ex(sslPrivKey, keylen, eValue_bn, NULL) 1586300fdee2SAndy Fiddaman == 0) { 158799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 158899ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 158999ebb4caSwyllys } else { 159030a5e8faSwyllys (void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey); 159199ebb4caSwyllys privkey->kstype = KMF_KEYSTORE_OPENSSL; 159299ebb4caSwyllys privkey->keyalg = KMF_RSA; 159399ebb4caSwyllys privkey->keyclass = KMF_ASYM_PRI; 159499ebb4caSwyllys privkey->israw = FALSE; 159599ebb4caSwyllys privkey->keyp = (void *)eprikey; 159630a5e8faSwyllys 159799ebb4caSwyllys /* OpenSSL derives the public key from the private */ 159830a5e8faSwyllys (void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey); 159999ebb4caSwyllys pubkey->kstype = KMF_KEYSTORE_OPENSSL; 160099ebb4caSwyllys pubkey->keyalg = KMF_RSA; 160199ebb4caSwyllys pubkey->israw = FALSE; 160299ebb4caSwyllys pubkey->keyclass = KMF_ASYM_PUB; 160399ebb4caSwyllys pubkey->keyp = (void *)epubkey; 160499ebb4caSwyllys } 160530a5e8faSwyllys } else if (keytype == KMF_DSA) { 1606300fdee2SAndy Fiddaman BIGNUM *p, *q, *g; 1607300fdee2SAndy Fiddaman 160899ebb4caSwyllys sslDSAKey = DSA_new(); 160999ebb4caSwyllys if (sslDSAKey == NULL) { 161099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 161199ebb4caSwyllys return (KMF_ERR_MEMORY); 161299ebb4caSwyllys } 161399ebb4caSwyllys 1614300fdee2SAndy Fiddaman p = BN_bin2bn(P, sizeof (P), NULL); 1615300fdee2SAndy Fiddaman q = BN_bin2bn(Q, sizeof (Q), NULL); 1616300fdee2SAndy Fiddaman g = BN_bin2bn(G, sizeof (G), NULL); 1617300fdee2SAndy Fiddaman if (p == NULL || q == NULL || g == NULL) { 1618300fdee2SAndy Fiddaman BN_free(p); 1619300fdee2SAndy Fiddaman BN_free(q); 1620300fdee2SAndy Fiddaman BN_free(g); 162199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 162299ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 162399ebb4caSwyllys goto cleanup; 162499ebb4caSwyllys } 1625300fdee2SAndy Fiddaman 1626300fdee2SAndy Fiddaman if (DSA_set0_pqg(sslDSAKey, p, q, g) == 0) { 162799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 162899ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 162999ebb4caSwyllys goto cleanup; 163099ebb4caSwyllys } 163199ebb4caSwyllys 163299ebb4caSwyllys if (!DSA_generate_key(sslDSAKey)) { 163399ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 163499ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 163599ebb4caSwyllys goto cleanup; 163699ebb4caSwyllys } 163799ebb4caSwyllys 163899ebb4caSwyllys privkey->kstype = KMF_KEYSTORE_OPENSSL; 163999ebb4caSwyllys privkey->keyalg = KMF_DSA; 164099ebb4caSwyllys privkey->keyclass = KMF_ASYM_PRI; 164199ebb4caSwyllys privkey->israw = FALSE; 164299ebb4caSwyllys if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) { 164399ebb4caSwyllys privkey->keyp = (void *)eprikey; 164499ebb4caSwyllys } else { 164599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 164699ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 164799ebb4caSwyllys goto cleanup; 164899ebb4caSwyllys } 164999ebb4caSwyllys 165099ebb4caSwyllys pubkey->kstype = KMF_KEYSTORE_OPENSSL; 165199ebb4caSwyllys pubkey->keyalg = KMF_DSA; 165299ebb4caSwyllys pubkey->keyclass = KMF_ASYM_PUB; 165399ebb4caSwyllys pubkey->israw = FALSE; 165499ebb4caSwyllys 165599ebb4caSwyllys if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) { 165699ebb4caSwyllys pubkey->keyp = (void *)epubkey; 165799ebb4caSwyllys } else { 165899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 165999ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 166099ebb4caSwyllys goto cleanup; 166199ebb4caSwyllys } 166299ebb4caSwyllys } 166399ebb4caSwyllys 166499ebb4caSwyllys if (rv != KMF_OK) { 166599ebb4caSwyllys goto cleanup; 166699ebb4caSwyllys } 166799ebb4caSwyllys 166830a5e8faSwyllys if (storekey) { 166930a5e8faSwyllys KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */ 167030a5e8faSwyllys int i = 0; 167130a5e8faSwyllys char *keyfile = NULL, *dirpath = NULL; 167230a5e8faSwyllys KMF_ENCODE_FORMAT format; 167330a5e8faSwyllys /* 167430a5e8faSwyllys * Construct a new attribute arrray and call openssl_store_key 167530a5e8faSwyllys */ 167630a5e8faSwyllys kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR, 167730a5e8faSwyllys privkey, sizeof (privkey)); 167830a5e8faSwyllys i++; 167930a5e8faSwyllys 168030a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 168130a5e8faSwyllys if (dirpath != NULL) { 168230a5e8faSwyllys storeattrs[i].type = KMF_DIRPATH_ATTR; 168330a5e8faSwyllys storeattrs[i].pValue = dirpath; 168430a5e8faSwyllys storeattrs[i].valueLen = strlen(dirpath); 168530a5e8faSwyllys i++; 168630a5e8faSwyllys } else { 168730a5e8faSwyllys rv = KMF_OK; /* DIRPATH is optional */ 168899ebb4caSwyllys } 168930a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, 169030a5e8faSwyllys attrlist, numattr); 169130a5e8faSwyllys if (keyfile != NULL) { 169230a5e8faSwyllys storeattrs[i].type = KMF_KEY_FILENAME_ATTR; 169330a5e8faSwyllys storeattrs[i].pValue = keyfile; 169430a5e8faSwyllys storeattrs[i].valueLen = strlen(keyfile); 169530a5e8faSwyllys i++; 169630a5e8faSwyllys } else { 169730a5e8faSwyllys goto cleanup; /* KEYFILE is required */ 169830a5e8faSwyllys } 169930a5e8faSwyllys rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 170030a5e8faSwyllys (void *)&format, NULL); 170130a5e8faSwyllys if (rv == KMF_OK) { 170230a5e8faSwyllys storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR; 170330a5e8faSwyllys storeattrs[i].pValue = &format; 170430a5e8faSwyllys storeattrs[i].valueLen = sizeof (format); 170530a5e8faSwyllys i++; 170630a5e8faSwyllys } 170730a5e8faSwyllys 170830a5e8faSwyllys rv = OpenSSL_StoreKey(handle, i, storeattrs); 170930a5e8faSwyllys } 171099ebb4caSwyllys 171199ebb4caSwyllys cleanup: 1712300fdee2SAndy Fiddaman if (eValue_bn != NULL) 1713300fdee2SAndy Fiddaman BN_free(eValue_bn); 1714300fdee2SAndy Fiddaman 171599ebb4caSwyllys if (rv != KMF_OK) { 171699ebb4caSwyllys if (eprikey != NULL) 171799ebb4caSwyllys EVP_PKEY_free(eprikey); 171899ebb4caSwyllys 171999ebb4caSwyllys if (epubkey != NULL) 172099ebb4caSwyllys EVP_PKEY_free(epubkey); 172199ebb4caSwyllys 172299ebb4caSwyllys if (pubkey->keylabel) { 172399ebb4caSwyllys free(pubkey->keylabel); 172499ebb4caSwyllys pubkey->keylabel = NULL; 172599ebb4caSwyllys } 172699ebb4caSwyllys 172799ebb4caSwyllys if (privkey->keylabel) { 172899ebb4caSwyllys free(privkey->keylabel); 172999ebb4caSwyllys privkey->keylabel = NULL; 173099ebb4caSwyllys } 173199ebb4caSwyllys 173299ebb4caSwyllys pubkey->keyp = NULL; 173399ebb4caSwyllys privkey->keyp = NULL; 173499ebb4caSwyllys } 173599ebb4caSwyllys 173699ebb4caSwyllys if (sslPrivKey) 173799ebb4caSwyllys RSA_free(sslPrivKey); 173899ebb4caSwyllys 173999ebb4caSwyllys if (sslDSAKey) 174099ebb4caSwyllys DSA_free(sslDSAKey); 174199ebb4caSwyllys 174299ebb4caSwyllys if (out != NULL) 174399ebb4caSwyllys (void) BIO_free(out); 174499ebb4caSwyllys 174599ebb4caSwyllys return (rv); 174699ebb4caSwyllys } 174799ebb4caSwyllys 1748e65e5c2dSWyllys Ingersoll /* 1749e65e5c2dSWyllys Ingersoll * Make sure the BN conversion is properly padded with 0x00 1750e65e5c2dSWyllys Ingersoll * bytes. If not, signature verification for DSA signatures 1751e65e5c2dSWyllys Ingersoll * may fail in the case where the bignum value does not use 1752e65e5c2dSWyllys Ingersoll * all of the bits. 1753e65e5c2dSWyllys Ingersoll */ 1754e65e5c2dSWyllys Ingersoll static int 1755300fdee2SAndy Fiddaman fixbnlen(const BIGNUM *bn, unsigned char *buf, int len) { 1756e65e5c2dSWyllys Ingersoll int bytes = len - BN_num_bytes(bn); 17572c9a247fSWyllys Ingersoll 17582c9a247fSWyllys Ingersoll /* prepend with leading 0x00 if necessary */ 1759e65e5c2dSWyllys Ingersoll while (bytes-- > 0) 1760e65e5c2dSWyllys Ingersoll *buf++ = 0; 1761e65e5c2dSWyllys Ingersoll 17622c9a247fSWyllys Ingersoll (void) BN_bn2bin(bn, buf); 17632c9a247fSWyllys Ingersoll /* 17642c9a247fSWyllys Ingersoll * Return the desired length since we prepended it 17652c9a247fSWyllys Ingersoll * with the necessary 0x00 padding. 17662c9a247fSWyllys Ingersoll */ 17672c9a247fSWyllys Ingersoll return (len); 1768e65e5c2dSWyllys Ingersoll } 1769e65e5c2dSWyllys Ingersoll 177099ebb4caSwyllys KMF_RETURN 177199ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, 177299ebb4caSwyllys KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output) 177399ebb4caSwyllys { 177499ebb4caSwyllys KMF_RETURN ret = KMF_OK; 177599ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 177699ebb4caSwyllys KMF_ALGORITHM_INDEX AlgId; 1777300fdee2SAndy Fiddaman EVP_MD_CTX *ctx; 177899ebb4caSwyllys const EVP_MD *md; 177902744e81Swyllys 178099ebb4caSwyllys if (key == NULL || AlgOID == NULL || 178199ebb4caSwyllys tobesigned == NULL || output == NULL || 178299ebb4caSwyllys tobesigned->Data == NULL || 178399ebb4caSwyllys output->Data == NULL) 178499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 178599ebb4caSwyllys 178699ebb4caSwyllys /* Map the OID to an OpenSSL algorithm */ 178730a5e8faSwyllys AlgId = x509_algoid_to_algid(AlgOID); 178899ebb4caSwyllys if (AlgId == KMF_ALGID_NONE) 1789e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM); 179099ebb4caSwyllys 179199ebb4caSwyllys if (key->keyalg == KMF_RSA) { 179299ebb4caSwyllys EVP_PKEY *pkey = (EVP_PKEY *)key->keyp; 179399ebb4caSwyllys uchar_t *p; 179402744e81Swyllys int len; 1795*553e44ceSAndrew Stormont switch (AlgId) { 1796*553e44ceSAndrew Stormont #ifndef OPENSSL_NO_MD5 1797*553e44ceSAndrew Stormont case KMF_ALGID_MD5WithRSA: 179899ebb4caSwyllys md = EVP_md5(); 1799*553e44ceSAndrew Stormont break; 1800*553e44ceSAndrew Stormont #endif 1801*553e44ceSAndrew Stormont #ifndef OPENSSL_NO_SHA 1802*553e44ceSAndrew Stormont case KMF_ALGID_SHA1WithRSA: 180399ebb4caSwyllys md = EVP_sha1(); 1804*553e44ceSAndrew Stormont break; 1805*553e44ceSAndrew Stormont #endif 1806*553e44ceSAndrew Stormont #ifndef OPENSSL_NO_SHA256 1807*553e44ceSAndrew Stormont case KMF_ALGID_SHA256WithRSA: 1808e65e5c2dSWyllys Ingersoll md = EVP_sha256(); 1809*553e44ceSAndrew Stormont break; 1810*553e44ceSAndrew Stormont #endif 1811*553e44ceSAndrew Stormont #ifndef OPENSSL_NO_SHA512 1812*553e44ceSAndrew Stormont case KMF_ALGID_SHA384WithRSA: 1813e65e5c2dSWyllys Ingersoll md = EVP_sha384(); 1814*553e44ceSAndrew Stormont break; 1815*553e44ceSAndrew Stormont case KMF_ALGID_SHA512WithRSA: 1816e65e5c2dSWyllys Ingersoll md = EVP_sha512(); 1817*553e44ceSAndrew Stormont break; 1818*553e44ceSAndrew Stormont #endif 1819*553e44ceSAndrew Stormont case KMF_ALGID_RSA: 182002744e81Swyllys md = NULL; 1821*553e44ceSAndrew Stormont break; 1822*553e44ceSAndrew Stormont default: 1823e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM); 1824*553e44ceSAndrew Stormont } 182599ebb4caSwyllys 182602744e81Swyllys if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) { 182702744e81Swyllys RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey); 182899ebb4caSwyllys 182902744e81Swyllys p = output->Data; 183002744e81Swyllys if ((len = RSA_private_encrypt(tobesigned->Length, 183102744e81Swyllys tobesigned->Data, p, rsa, 183202744e81Swyllys RSA_PKCS1_PADDING)) <= 0) { 183302744e81Swyllys SET_ERROR(kmfh, ERR_get_error()); 183402744e81Swyllys ret = KMF_ERR_INTERNAL; 183502744e81Swyllys } 183602744e81Swyllys output->Length = len; 183702744e81Swyllys } else { 1838300fdee2SAndy Fiddaman if ((ctx = EVP_MD_CTX_new()) == NULL) 1839300fdee2SAndy Fiddaman return (KMF_ERR_MEMORY); 1840300fdee2SAndy Fiddaman (void) EVP_SignInit_ex(ctx, md, NULL); 1841300fdee2SAndy Fiddaman (void) EVP_SignUpdate(ctx, tobesigned->Data, 184299ebb4caSwyllys (uint32_t)tobesigned->Length); 184399ebb4caSwyllys len = (uint32_t)output->Length; 184499ebb4caSwyllys p = output->Data; 1845300fdee2SAndy Fiddaman if (!EVP_SignFinal(ctx, p, (uint32_t *)&len, pkey)) { 184699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 184702744e81Swyllys len = 0; 184802744e81Swyllys ret = KMF_ERR_INTERNAL; 184999ebb4caSwyllys } 185099ebb4caSwyllys output->Length = len; 1851300fdee2SAndy Fiddaman EVP_MD_CTX_free(ctx); 185202744e81Swyllys } 185399ebb4caSwyllys } else if (key->keyalg == KMF_DSA) { 185499ebb4caSwyllys DSA *dsa = EVP_PKEY_get1_DSA(key->keyp); 185599ebb4caSwyllys 185699ebb4caSwyllys uchar_t hash[EVP_MAX_MD_SIZE]; 185799ebb4caSwyllys uint32_t hashlen; 185899ebb4caSwyllys DSA_SIG *dsasig; 185999ebb4caSwyllys 1860e65e5c2dSWyllys Ingersoll if (AlgId == KMF_ALGID_DSA || 1861e65e5c2dSWyllys Ingersoll AlgId == KMF_ALGID_SHA1WithDSA) 1862e65e5c2dSWyllys Ingersoll md = EVP_sha1(); 1863e65e5c2dSWyllys Ingersoll else if (AlgId == KMF_ALGID_SHA256WithDSA) 1864e65e5c2dSWyllys Ingersoll md = EVP_sha256(); 1865e65e5c2dSWyllys Ingersoll else /* Bad algorithm */ 1866e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM); 1867e65e5c2dSWyllys Ingersoll 186899ebb4caSwyllys /* 186999ebb4caSwyllys * OpenSSL EVP_Sign operation automatically converts to 187099ebb4caSwyllys * ASN.1 output so we do the operations separately so we 187199ebb4caSwyllys * are assured of NOT getting ASN.1 output returned. 187299ebb4caSwyllys * KMF does not want ASN.1 encoded results because 187399ebb4caSwyllys * not all mechanisms return ASN.1 encodings (PKCS#11 187499ebb4caSwyllys * and NSS return raw signature data). 187599ebb4caSwyllys */ 1876300fdee2SAndy Fiddaman if ((ctx = EVP_MD_CTX_new()) == NULL) 1877300fdee2SAndy Fiddaman return (KMF_ERR_MEMORY); 1878300fdee2SAndy Fiddaman (void) EVP_DigestInit_ex(ctx, md, NULL); 1879300fdee2SAndy Fiddaman (void) EVP_DigestUpdate(ctx, tobesigned->Data, 188099ebb4caSwyllys tobesigned->Length); 1881300fdee2SAndy Fiddaman (void) EVP_DigestFinal_ex(ctx, hash, &hashlen); 188299ebb4caSwyllys 1883e65e5c2dSWyllys Ingersoll /* Only sign first 20 bytes for SHA2 */ 1884e65e5c2dSWyllys Ingersoll if (AlgId == KMF_ALGID_SHA256WithDSA) 1885e65e5c2dSWyllys Ingersoll hashlen = 20; 188699ebb4caSwyllys dsasig = DSA_do_sign(hash, hashlen, dsa); 188799ebb4caSwyllys if (dsasig != NULL) { 188899ebb4caSwyllys int i; 1889300fdee2SAndy Fiddaman const BIGNUM *r, *s; 1890300fdee2SAndy Fiddaman 1891300fdee2SAndy Fiddaman DSA_SIG_get0(dsasig, &r, &s); 1892300fdee2SAndy Fiddaman output->Length = i = fixbnlen(r, output->Data, 1893e65e5c2dSWyllys Ingersoll hashlen); 18942c9a247fSWyllys Ingersoll 1895300fdee2SAndy Fiddaman output->Length += fixbnlen(s, &output->Data[i], 1896e65e5c2dSWyllys Ingersoll hashlen); 18972c9a247fSWyllys Ingersoll 189899ebb4caSwyllys DSA_SIG_free(dsasig); 189999ebb4caSwyllys } else { 190099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 190199ebb4caSwyllys } 1902300fdee2SAndy Fiddaman EVP_MD_CTX_free(ctx); 190399ebb4caSwyllys } else { 190499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 190599ebb4caSwyllys } 190699ebb4caSwyllys cleanup: 190799ebb4caSwyllys return (ret); 190899ebb4caSwyllys } 190999ebb4caSwyllys 191099ebb4caSwyllys KMF_RETURN 191199ebb4caSwyllys /*ARGSUSED*/ 191230a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle, 191330a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 191499ebb4caSwyllys { 191599ebb4caSwyllys KMF_RETURN rv = KMF_OK; 191630a5e8faSwyllys KMF_KEY_HANDLE *key; 191730a5e8faSwyllys boolean_t destroy = B_TRUE; 191830a5e8faSwyllys 191930a5e8faSwyllys key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 192099ebb4caSwyllys if (key == NULL || key->keyp == NULL) 192199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 192299ebb4caSwyllys 192330a5e8faSwyllys rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr, 192430a5e8faSwyllys (void *)&destroy, NULL); 192530a5e8faSwyllys if (rv != KMF_OK) { 192630a5e8faSwyllys /* "destroy" is optional. Default is TRUE */ 192730a5e8faSwyllys rv = KMF_OK; 192830a5e8faSwyllys } 192930a5e8faSwyllys 193099ebb4caSwyllys if (key->keyclass != KMF_ASYM_PUB && 193199ebb4caSwyllys key->keyclass != KMF_ASYM_PRI && 193299ebb4caSwyllys key->keyclass != KMF_SYMMETRIC) 193399ebb4caSwyllys return (KMF_ERR_BAD_KEY_CLASS); 193499ebb4caSwyllys 193599ebb4caSwyllys if (key->keyclass == KMF_SYMMETRIC) { 193630a5e8faSwyllys kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp); 193799ebb4caSwyllys key->keyp = NULL; 193899ebb4caSwyllys } else { 193999ebb4caSwyllys if (key->keyp != NULL) { 194099ebb4caSwyllys EVP_PKEY_free(key->keyp); 194199ebb4caSwyllys key->keyp = NULL; 194299ebb4caSwyllys } 194399ebb4caSwyllys } 194499ebb4caSwyllys 194599ebb4caSwyllys if (key->keylabel != NULL) { 194699ebb4caSwyllys EVP_PKEY *pkey = NULL; 194799ebb4caSwyllys /* If the file exists, make sure it is a proper key. */ 194899ebb4caSwyllys pkey = openssl_load_key(handle, key->keylabel); 194999ebb4caSwyllys if (pkey == NULL) { 19505b3e1433Swyllys if (key->keylabel != NULL) { 195199ebb4caSwyllys free(key->keylabel); 195299ebb4caSwyllys key->keylabel = NULL; 19535b3e1433Swyllys } 195499ebb4caSwyllys return (KMF_ERR_KEY_NOT_FOUND); 195599ebb4caSwyllys } 195699ebb4caSwyllys EVP_PKEY_free(pkey); 195799ebb4caSwyllys 195899ebb4caSwyllys if (destroy) { 195999ebb4caSwyllys if (unlink(key->keylabel) != 0) { 196099ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 196199ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 196299ebb4caSwyllys rv = KMF_ERR_INTERNAL; 196399ebb4caSwyllys } 196499ebb4caSwyllys } 196599ebb4caSwyllys if (key->keylabel != NULL) { 196699ebb4caSwyllys free(key->keylabel); 196799ebb4caSwyllys key->keylabel = NULL; 196899ebb4caSwyllys } 196999ebb4caSwyllys } 197099ebb4caSwyllys return (rv); 197199ebb4caSwyllys } 197299ebb4caSwyllys 197399ebb4caSwyllys KMF_RETURN 197499ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr) 197599ebb4caSwyllys { 197699ebb4caSwyllys KMF_RETURN ret = KMF_OK; 197799ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 197899ebb4caSwyllys char str[256]; /* OpenSSL needs at least 120 byte buffer */ 197999ebb4caSwyllys 198099ebb4caSwyllys ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str)); 198199ebb4caSwyllys if (strlen(str)) { 198299ebb4caSwyllys *msgstr = (char *)strdup(str); 198399ebb4caSwyllys if ((*msgstr) == NULL) 198499ebb4caSwyllys ret = KMF_ERR_MEMORY; 198599ebb4caSwyllys } else { 198699ebb4caSwyllys *msgstr = NULL; 198799ebb4caSwyllys } 198899ebb4caSwyllys 198999ebb4caSwyllys return (ret); 199099ebb4caSwyllys } 199199ebb4caSwyllys 199299ebb4caSwyllys static int 199399ebb4caSwyllys ext2NID(int kmfext) 199499ebb4caSwyllys { 199599ebb4caSwyllys switch (kmfext) { 199699ebb4caSwyllys case KMF_X509_EXT_KEY_USAGE: 199799ebb4caSwyllys return (NID_key_usage); 199899ebb4caSwyllys case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD: 199999ebb4caSwyllys return (NID_private_key_usage_period); 200099ebb4caSwyllys case KMF_X509_EXT_CERT_POLICIES: 200199ebb4caSwyllys return (NID_certificate_policies); 200299ebb4caSwyllys case KMF_X509_EXT_SUBJ_ALTNAME: 200399ebb4caSwyllys return (NID_subject_alt_name); 200499ebb4caSwyllys case KMF_X509_EXT_ISSUER_ALTNAME: 200599ebb4caSwyllys return (NID_issuer_alt_name); 200699ebb4caSwyllys case KMF_X509_EXT_BASIC_CONSTRAINTS: 200799ebb4caSwyllys return (NID_basic_constraints); 200899ebb4caSwyllys case KMF_X509_EXT_EXT_KEY_USAGE: 200999ebb4caSwyllys return (NID_ext_key_usage); 201099ebb4caSwyllys case KMF_X509_EXT_AUTH_KEY_ID: 201199ebb4caSwyllys return (NID_authority_key_identifier); 201299ebb4caSwyllys case KMF_X509_EXT_CRL_DIST_POINTS: 201399ebb4caSwyllys return (NID_crl_distribution_points); 201499ebb4caSwyllys case KMF_X509_EXT_SUBJ_KEY_ID: 201599ebb4caSwyllys return (NID_subject_key_identifier); 201699ebb4caSwyllys case KMF_X509_EXT_POLICY_MAPPINGS: 201799ebb4caSwyllys return (OBJ_sn2nid("policyMappings")); 201899ebb4caSwyllys case KMF_X509_EXT_NAME_CONSTRAINTS: 201999ebb4caSwyllys return (OBJ_sn2nid("nameConstraints")); 202099ebb4caSwyllys case KMF_X509_EXT_POLICY_CONSTRAINTS: 202199ebb4caSwyllys return (OBJ_sn2nid("policyConstraints")); 202299ebb4caSwyllys case KMF_X509_EXT_INHIBIT_ANY_POLICY: 202399ebb4caSwyllys return (OBJ_sn2nid("inhibitAnyPolicy")); 202499ebb4caSwyllys case KMF_X509_EXT_FRESHEST_CRL: 202599ebb4caSwyllys return (OBJ_sn2nid("freshestCRL")); 202699ebb4caSwyllys default: 202799ebb4caSwyllys return (NID_undef); 202899ebb4caSwyllys } 202999ebb4caSwyllys } 203099ebb4caSwyllys 203199ebb4caSwyllys KMF_RETURN 203299ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert, 203399ebb4caSwyllys KMF_PRINTABLE_ITEM flag, char *resultStr) 203499ebb4caSwyllys { 203599ebb4caSwyllys KMF_RETURN ret = KMF_OK; 203699ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 203799ebb4caSwyllys X509 *xcert = NULL; 203899ebb4caSwyllys unsigned char *outbuf = NULL; 203999ebb4caSwyllys unsigned char *outbuf_p; 204099ebb4caSwyllys int j; 204199ebb4caSwyllys int ext_index, nid, len; 204299ebb4caSwyllys BIO *mem = NULL; 204370f9559bSTheo Schlossnagle STACK_OF(OPENSSL_STRING) *emlst = NULL; 204499ebb4caSwyllys X509_EXTENSION *ex; 204599ebb4caSwyllys 204699ebb4caSwyllys if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) { 204799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 204899ebb4caSwyllys } 204999ebb4caSwyllys 205099ebb4caSwyllys /* copy cert data to outbuf */ 205199ebb4caSwyllys outbuf = malloc(pcert->Length); 205299ebb4caSwyllys if (outbuf == NULL) { 205399ebb4caSwyllys return (KMF_ERR_MEMORY); 205499ebb4caSwyllys } 205599ebb4caSwyllys (void) memcpy(outbuf, pcert->Data, pcert->Length); 205699ebb4caSwyllys 205799ebb4caSwyllys outbuf_p = outbuf; /* use a temp pointer; required by openssl */ 205899ebb4caSwyllys xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length); 205999ebb4caSwyllys if (xcert == NULL) { 206099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 206199ebb4caSwyllys ret = KMF_ERR_ENCODING; 206299ebb4caSwyllys goto out; 206399ebb4caSwyllys } 206499ebb4caSwyllys 206599ebb4caSwyllys mem = BIO_new(BIO_s_mem()); 206699ebb4caSwyllys if (mem == NULL) { 206799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 206899ebb4caSwyllys ret = KMF_ERR_MEMORY; 206999ebb4caSwyllys goto out; 207099ebb4caSwyllys } 207199ebb4caSwyllys 207299ebb4caSwyllys switch (flag) { 207399ebb4caSwyllys case KMF_CERT_ISSUER: 207499ebb4caSwyllys (void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0, 207599ebb4caSwyllys XN_FLAG_SEP_CPLUS_SPC); 207699ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 207799ebb4caSwyllys break; 207899ebb4caSwyllys 207999ebb4caSwyllys case KMF_CERT_SUBJECT: 208099ebb4caSwyllys (void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0, 208199ebb4caSwyllys XN_FLAG_SEP_CPLUS_SPC); 208299ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 208399ebb4caSwyllys break; 208499ebb4caSwyllys 208599ebb4caSwyllys case KMF_CERT_VERSION: 2086300fdee2SAndy Fiddaman (void) snprintf(resultStr, KMF_CERT_PRINTABLE_LEN, 2087300fdee2SAndy Fiddaman "%ld", X509_get_version(xcert)); 208899ebb4caSwyllys len = strlen(resultStr); 208999ebb4caSwyllys break; 209099ebb4caSwyllys 209199ebb4caSwyllys case KMF_CERT_SERIALNUM: 209299ebb4caSwyllys if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) { 209399ebb4caSwyllys (void) strcpy(resultStr, "0x"); 209499ebb4caSwyllys len = BIO_gets(mem, &resultStr[2], 209599ebb4caSwyllys KMF_CERT_PRINTABLE_LEN - 2); 209699ebb4caSwyllys } 209799ebb4caSwyllys break; 209899ebb4caSwyllys 209999ebb4caSwyllys case KMF_CERT_NOTBEFORE: 2100300fdee2SAndy Fiddaman (void) ASN1_TIME_print(mem, X509_getm_notBefore(xcert)); 210199ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 210299ebb4caSwyllys break; 210399ebb4caSwyllys 210499ebb4caSwyllys case KMF_CERT_NOTAFTER: 2105300fdee2SAndy Fiddaman (void) ASN1_TIME_print(mem, X509_getm_notAfter(xcert)); 210699ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 210799ebb4caSwyllys break; 210899ebb4caSwyllys 210999ebb4caSwyllys case KMF_CERT_PUBKEY_DATA: 211099ebb4caSwyllys { 2111300fdee2SAndy Fiddaman RSA *rsa; 2112300fdee2SAndy Fiddaman DSA *dsa; 2113300fdee2SAndy Fiddaman 211499ebb4caSwyllys EVP_PKEY *pkey = X509_get_pubkey(xcert); 211599ebb4caSwyllys if (pkey == NULL) { 211699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 211799ebb4caSwyllys ret = KMF_ERR_ENCODING; 211899ebb4caSwyllys goto out; 211999ebb4caSwyllys } 212099ebb4caSwyllys 2121300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) { 212299ebb4caSwyllys (void) BIO_printf(mem, 212399ebb4caSwyllys "RSA Public Key: (%d bit)\n", 2124300fdee2SAndy Fiddaman RSA_bits(rsa)); 2125300fdee2SAndy Fiddaman (void) RSA_print(mem, rsa, 0); 2126300fdee2SAndy Fiddaman 2127300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) { 212899ebb4caSwyllys (void) BIO_printf(mem, 212999ebb4caSwyllys "%12sDSA Public Key:\n", ""); 2130300fdee2SAndy Fiddaman (void) DSA_print(mem, dsa, 0); 213199ebb4caSwyllys } else { 213299ebb4caSwyllys (void) BIO_printf(mem, 213399ebb4caSwyllys "%12sUnknown Public Key:\n", ""); 213499ebb4caSwyllys } 213599ebb4caSwyllys (void) BIO_printf(mem, "\n"); 213699ebb4caSwyllys EVP_PKEY_free(pkey); 213799ebb4caSwyllys } 213899ebb4caSwyllys len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 213999ebb4caSwyllys break; 214099ebb4caSwyllys case KMF_CERT_SIGNATURE_ALG: 214199ebb4caSwyllys case KMF_CERT_PUBKEY_ALG: 2142300fdee2SAndy Fiddaman { 2143*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 2144300fdee2SAndy Fiddaman ASN1_OBJECT *alg = NULL; 2145300fdee2SAndy Fiddaman #else 2146300fdee2SAndy Fiddaman const ASN1_OBJECT *alg = NULL; 2147300fdee2SAndy Fiddaman #endif 2148300fdee2SAndy Fiddaman 214999ebb4caSwyllys if (flag == KMF_CERT_SIGNATURE_ALG) { 2150*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 2151300fdee2SAndy Fiddaman alg = xcert->sig_alg->algorithm; 2152300fdee2SAndy Fiddaman #else 2153300fdee2SAndy Fiddaman const X509_ALGOR *sig_alg = NULL; 2154300fdee2SAndy Fiddaman 2155300fdee2SAndy Fiddaman X509_get0_signature(NULL, &sig_alg, xcert); 2156300fdee2SAndy Fiddaman if (sig_alg != NULL) 2157300fdee2SAndy Fiddaman X509_ALGOR_get0(&alg, NULL, NULL, 2158300fdee2SAndy Fiddaman sig_alg); 2159300fdee2SAndy Fiddaman #endif 216099ebb4caSwyllys } else { 2161*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 2162300fdee2SAndy Fiddaman alg = xcert->cert_info->key->algor->algorithm; 2163300fdee2SAndy Fiddaman #else 2164300fdee2SAndy Fiddaman X509_PUBKEY *key = X509_get_X509_PUBKEY(xcert); 2165300fdee2SAndy Fiddaman 2166300fdee2SAndy Fiddaman if (key != NULL) 2167300fdee2SAndy Fiddaman (void) X509_PUBKEY_get0_param( 2168300fdee2SAndy Fiddaman (ASN1_OBJECT **)&alg, NULL, 0, 2169300fdee2SAndy Fiddaman NULL, key); 2170300fdee2SAndy Fiddaman #endif 217199ebb4caSwyllys } 217299ebb4caSwyllys 2173300fdee2SAndy Fiddaman if (alg == NULL) 2174300fdee2SAndy Fiddaman len = -1; 2175300fdee2SAndy Fiddaman else if ((len = i2a_ASN1_OBJECT(mem, alg)) > 0) 217699ebb4caSwyllys len = BIO_read(mem, resultStr, 217799ebb4caSwyllys KMF_CERT_PRINTABLE_LEN); 217899ebb4caSwyllys } 217999ebb4caSwyllys break; 218099ebb4caSwyllys 218199ebb4caSwyllys case KMF_CERT_EMAIL: 218299ebb4caSwyllys emlst = X509_get1_email(xcert); 218370f9559bSTheo Schlossnagle for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) 218470f9559bSTheo Schlossnagle (void) BIO_printf(mem, "%s\n", 218570f9559bSTheo Schlossnagle sk_OPENSSL_STRING_value(emlst, j)); 218699ebb4caSwyllys 218799ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 218899ebb4caSwyllys X509_email_free(emlst); 218999ebb4caSwyllys break; 219099ebb4caSwyllys case KMF_X509_EXT_ISSUER_ALTNAME: 219199ebb4caSwyllys case KMF_X509_EXT_SUBJ_ALTNAME: 219299ebb4caSwyllys case KMF_X509_EXT_KEY_USAGE: 219399ebb4caSwyllys case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD: 219499ebb4caSwyllys case KMF_X509_EXT_CERT_POLICIES: 219599ebb4caSwyllys case KMF_X509_EXT_BASIC_CONSTRAINTS: 219699ebb4caSwyllys case KMF_X509_EXT_NAME_CONSTRAINTS: 219799ebb4caSwyllys case KMF_X509_EXT_POLICY_CONSTRAINTS: 219899ebb4caSwyllys case KMF_X509_EXT_EXT_KEY_USAGE: 219999ebb4caSwyllys case KMF_X509_EXT_INHIBIT_ANY_POLICY: 220099ebb4caSwyllys case KMF_X509_EXT_AUTH_KEY_ID: 220199ebb4caSwyllys case KMF_X509_EXT_SUBJ_KEY_ID: 220299ebb4caSwyllys case KMF_X509_EXT_POLICY_MAPPINGS: 220399ebb4caSwyllys case KMF_X509_EXT_CRL_DIST_POINTS: 220499ebb4caSwyllys case KMF_X509_EXT_FRESHEST_CRL: 220599ebb4caSwyllys nid = ext2NID(flag); 220699ebb4caSwyllys if (nid == NID_undef) { 220799ebb4caSwyllys ret = KMF_ERR_EXTENSION_NOT_FOUND; 220899ebb4caSwyllys goto out; 220999ebb4caSwyllys } 221099ebb4caSwyllys 2211300fdee2SAndy Fiddaman ext_index = X509_get_ext_by_NID(xcert, nid, -1); 221299ebb4caSwyllys if (ext_index == -1) { 221399ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 221499ebb4caSwyllys 221599ebb4caSwyllys ret = KMF_ERR_EXTENSION_NOT_FOUND; 221699ebb4caSwyllys goto out; 221799ebb4caSwyllys } 2218300fdee2SAndy Fiddaman ex = X509_get_ext(xcert, ext_index); 221999ebb4caSwyllys 222099ebb4caSwyllys (void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex)); 222199ebb4caSwyllys 222299ebb4caSwyllys if (BIO_printf(mem, ": %s\n", 222330a5e8faSwyllys X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) { 222499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 222599ebb4caSwyllys ret = KMF_ERR_ENCODING; 222699ebb4caSwyllys goto out; 222799ebb4caSwyllys } 222899ebb4caSwyllys if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) { 222999ebb4caSwyllys (void) BIO_printf(mem, "%*s", 4, ""); 2230300fdee2SAndy Fiddaman (void) ASN1_STRING_print(mem, 2231300fdee2SAndy Fiddaman X509_EXTENSION_get_data(ex)); 223299ebb4caSwyllys } 223399ebb4caSwyllys if (BIO_write(mem, "\n", 1) <= 0) { 223499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 223599ebb4caSwyllys ret = KMF_ERR_ENCODING; 223699ebb4caSwyllys goto out; 223799ebb4caSwyllys } 223899ebb4caSwyllys len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 223999ebb4caSwyllys } 224099ebb4caSwyllys if (len <= 0) { 224199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 224299ebb4caSwyllys ret = KMF_ERR_ENCODING; 224399ebb4caSwyllys } 224499ebb4caSwyllys 224599ebb4caSwyllys out: 224699ebb4caSwyllys if (outbuf != NULL) { 224799ebb4caSwyllys free(outbuf); 224899ebb4caSwyllys } 224999ebb4caSwyllys 225099ebb4caSwyllys if (xcert != NULL) { 225199ebb4caSwyllys X509_free(xcert); 225299ebb4caSwyllys } 225399ebb4caSwyllys 225499ebb4caSwyllys if (mem != NULL) { 225599ebb4caSwyllys (void) BIO_free(mem); 225699ebb4caSwyllys } 225799ebb4caSwyllys 225899ebb4caSwyllys return (ret); 225999ebb4caSwyllys } 226030a5e8faSwyllys 226199ebb4caSwyllys KMF_RETURN 226299ebb4caSwyllys /*ARGSUSED*/ 226330a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr, 226430a5e8faSwyllys KMF_ATTRIBUTE *attrlist) 226599ebb4caSwyllys { 226699ebb4caSwyllys KMF_RETURN rv = KMF_OK; 226730a5e8faSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL; 226830a5e8faSwyllys KMF_KEY_CLASS keyclass = KMF_ASYM_PRI; 226930a5e8faSwyllys KMF_KEY_HANDLE *key = NULL; 227030a5e8faSwyllys uint32_t numkeys = 1; /* 1 key only */ 227130a5e8faSwyllys char *dirpath = NULL; 227230a5e8faSwyllys char *keyfile = NULL; 227330a5e8faSwyllys KMF_ATTRIBUTE new_attrlist[16]; 227430a5e8faSwyllys int i = 0; 227599ebb4caSwyllys 227699ebb4caSwyllys /* 227799ebb4caSwyllys * This is really just a FindKey operation, reuse the 227899ebb4caSwyllys * FindKey function. 227999ebb4caSwyllys */ 228030a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 228130a5e8faSwyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 228230a5e8faSwyllys i++; 228399ebb4caSwyllys 228430a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 228530a5e8faSwyllys KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t)); 228630a5e8faSwyllys i++; 228799ebb4caSwyllys 228830a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 228930a5e8faSwyllys KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass)); 229030a5e8faSwyllys i++; 229130a5e8faSwyllys 229230a5e8faSwyllys key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 229330a5e8faSwyllys if (key == NULL) { 229430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 229530a5e8faSwyllys } else { 229630a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 229730a5e8faSwyllys KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE)); 229830a5e8faSwyllys i++; 229930a5e8faSwyllys } 230030a5e8faSwyllys 230130a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 230230a5e8faSwyllys if (dirpath != NULL) { 230330a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 230430a5e8faSwyllys KMF_DIRPATH_ATTR, dirpath, strlen(dirpath)); 230530a5e8faSwyllys i++; 230630a5e8faSwyllys } 230730a5e8faSwyllys 230830a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 230930a5e8faSwyllys if (keyfile == NULL) 231030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 231130a5e8faSwyllys else { 231230a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 231330a5e8faSwyllys KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile)); 231430a5e8faSwyllys i++; 231530a5e8faSwyllys } 231630a5e8faSwyllys 231730a5e8faSwyllys rv = OpenSSL_FindKey(handle, i, new_attrlist); 231899ebb4caSwyllys return (rv); 231999ebb4caSwyllys } 232099ebb4caSwyllys 232199ebb4caSwyllys KMF_RETURN 232299ebb4caSwyllys /*ARGSUSED*/ 232399ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, 232499ebb4caSwyllys KMF_OID *AlgOID, KMF_DATA *ciphertext, 232599ebb4caSwyllys KMF_DATA *output) 232699ebb4caSwyllys { 232799ebb4caSwyllys KMF_RETURN ret = KMF_OK; 232899ebb4caSwyllys RSA *rsa = NULL; 232999ebb4caSwyllys unsigned int in_len = 0, out_len = 0; 233099ebb4caSwyllys unsigned int total_decrypted = 0, modulus_len = 0; 233199ebb4caSwyllys uint8_t *in_data, *out_data; 233299ebb4caSwyllys int i, blocks; 233399ebb4caSwyllys 233499ebb4caSwyllys if (key == NULL || AlgOID == NULL || 233599ebb4caSwyllys ciphertext == NULL || output == NULL || 233699ebb4caSwyllys ciphertext->Data == NULL || 233799ebb4caSwyllys output->Data == NULL) 233899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 233999ebb4caSwyllys 234099ebb4caSwyllys if (key->keyalg == KMF_RSA) { 234199ebb4caSwyllys rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp); 234299ebb4caSwyllys modulus_len = RSA_size(rsa); 234399ebb4caSwyllys } else { 234499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 234599ebb4caSwyllys } 234699ebb4caSwyllys 234799ebb4caSwyllys blocks = ciphertext->Length/modulus_len; 234899ebb4caSwyllys out_data = output->Data; 234999ebb4caSwyllys in_data = ciphertext->Data; 235099ebb4caSwyllys out_len = modulus_len - 11; 235199ebb4caSwyllys in_len = modulus_len; 235299ebb4caSwyllys 235399ebb4caSwyllys for (i = 0; i < blocks; i++) { 235499ebb4caSwyllys out_len = RSA_private_decrypt(in_len, 235599ebb4caSwyllys in_data, out_data, rsa, RSA_PKCS1_PADDING); 235699ebb4caSwyllys 235799ebb4caSwyllys if (out_len == 0) { 235899ebb4caSwyllys ret = KMF_ERR_INTERNAL; 235999ebb4caSwyllys goto cleanup; 236099ebb4caSwyllys } 236199ebb4caSwyllys 236299ebb4caSwyllys out_data += out_len; 236399ebb4caSwyllys total_decrypted += out_len; 236499ebb4caSwyllys in_data += in_len; 236599ebb4caSwyllys } 236699ebb4caSwyllys 236799ebb4caSwyllys output->Length = total_decrypted; 236899ebb4caSwyllys 236999ebb4caSwyllys cleanup: 237099ebb4caSwyllys RSA_free(rsa); 237199ebb4caSwyllys if (ret != KMF_OK) 237299ebb4caSwyllys output->Length = 0; 237399ebb4caSwyllys 237499ebb4caSwyllys return (ret); 237599ebb4caSwyllys 237699ebb4caSwyllys } 237799ebb4caSwyllys 237899ebb4caSwyllys /* 237999ebb4caSwyllys * This function will create a certid from issuer_cert and user_cert. 238099ebb4caSwyllys * The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate 238199ebb4caSwyllys * certid memory after use. 238299ebb4caSwyllys */ 238399ebb4caSwyllys static KMF_RETURN 238499ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert, 238599ebb4caSwyllys const KMF_DATA *user_cert, OCSP_CERTID **certid) 238699ebb4caSwyllys { 238799ebb4caSwyllys KMF_RETURN ret = KMF_OK; 238899ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 238999ebb4caSwyllys X509 *issuer = NULL; 239099ebb4caSwyllys X509 *cert = NULL; 239199ebb4caSwyllys unsigned char *ptmp; 239299ebb4caSwyllys 239399ebb4caSwyllys if (issuer_cert == NULL || user_cert == NULL) { 239499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 239599ebb4caSwyllys } 239699ebb4caSwyllys 239799ebb4caSwyllys /* convert the DER-encoded issuer cert to an internal X509 */ 239899ebb4caSwyllys ptmp = issuer_cert->Data; 239999ebb4caSwyllys issuer = d2i_X509(NULL, (const uchar_t **)&ptmp, 240099ebb4caSwyllys issuer_cert->Length); 240199ebb4caSwyllys if (issuer == NULL) { 240299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 240399ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_ISSUER; 240499ebb4caSwyllys goto end; 240599ebb4caSwyllys } 240699ebb4caSwyllys 240799ebb4caSwyllys /* convert the DER-encoded user cert to an internal X509 */ 240899ebb4caSwyllys ptmp = user_cert->Data; 240999ebb4caSwyllys cert = d2i_X509(NULL, (const uchar_t **)&ptmp, 241099ebb4caSwyllys user_cert->Length); 241199ebb4caSwyllys if (cert == NULL) { 241299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 241399ebb4caSwyllys 241499ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_CERT; 241599ebb4caSwyllys goto end; 241699ebb4caSwyllys } 241799ebb4caSwyllys 241899ebb4caSwyllys /* create a CERTID */ 241999ebb4caSwyllys *certid = OCSP_cert_to_id(NULL, cert, issuer); 242099ebb4caSwyllys if (*certid == NULL) { 242199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 242299ebb4caSwyllys ret = KMF_ERR_OCSP_CERTID; 242399ebb4caSwyllys goto end; 242499ebb4caSwyllys } 242599ebb4caSwyllys 242699ebb4caSwyllys end: 242799ebb4caSwyllys if (issuer != NULL) { 242899ebb4caSwyllys X509_free(issuer); 242999ebb4caSwyllys } 243099ebb4caSwyllys 243199ebb4caSwyllys if (cert != NULL) { 243299ebb4caSwyllys X509_free(cert); 243399ebb4caSwyllys } 243499ebb4caSwyllys 243599ebb4caSwyllys return (ret); 243699ebb4caSwyllys } 243799ebb4caSwyllys 243899ebb4caSwyllys KMF_RETURN 243930a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle, 244030a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 244199ebb4caSwyllys { 244299ebb4caSwyllys KMF_RETURN ret = KMF_OK; 244399ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 244499ebb4caSwyllys OCSP_CERTID *id = NULL; 244599ebb4caSwyllys OCSP_REQUEST *req = NULL; 244699ebb4caSwyllys BIO *derbio = NULL; 244730a5e8faSwyllys char *reqfile; 244830a5e8faSwyllys KMF_DATA *issuer_cert; 244930a5e8faSwyllys KMF_DATA *user_cert; 245099ebb4caSwyllys 245130a5e8faSwyllys user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR, 245230a5e8faSwyllys attrlist, numattr); 245330a5e8faSwyllys if (user_cert == NULL) 245499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 245599ebb4caSwyllys 245630a5e8faSwyllys issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR, 245730a5e8faSwyllys attrlist, numattr); 245830a5e8faSwyllys if (issuer_cert == NULL) 245930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 246030a5e8faSwyllys 246130a5e8faSwyllys reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR, 246230a5e8faSwyllys attrlist, numattr); 246330a5e8faSwyllys if (reqfile == NULL) 246430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 246530a5e8faSwyllys 246630a5e8faSwyllys ret = create_certid(handle, issuer_cert, user_cert, &id); 246799ebb4caSwyllys if (ret != KMF_OK) { 246899ebb4caSwyllys return (ret); 246999ebb4caSwyllys } 247099ebb4caSwyllys 247199ebb4caSwyllys /* Create an OCSP request */ 247299ebb4caSwyllys req = OCSP_REQUEST_new(); 247399ebb4caSwyllys if (req == NULL) { 247499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 247599ebb4caSwyllys ret = KMF_ERR_OCSP_CREATE_REQUEST; 247699ebb4caSwyllys goto end; 247799ebb4caSwyllys } 247899ebb4caSwyllys 247999ebb4caSwyllys if (!OCSP_request_add0_id(req, id)) { 248099ebb4caSwyllys ret = KMF_ERR_OCSP_CREATE_REQUEST; 248199ebb4caSwyllys goto end; 248299ebb4caSwyllys } 248399ebb4caSwyllys 248499ebb4caSwyllys /* Write the request to the output file with DER encoding */ 248599ebb4caSwyllys derbio = BIO_new_file(reqfile, "wb"); 248699ebb4caSwyllys if (!derbio) { 248799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 248899ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 248999ebb4caSwyllys goto end; 249099ebb4caSwyllys } 249199ebb4caSwyllys if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) { 249299ebb4caSwyllys ret = KMF_ERR_ENCODING; 249399ebb4caSwyllys } 249499ebb4caSwyllys 249599ebb4caSwyllys end: 249699ebb4caSwyllys /* 2497e65e5c2dSWyllys Ingersoll * We don't need to free "id" explicitely, because OCSP_REQUEST_free() 2498a2d4930dSDan OpenSolaris Anderson * will also deallocate certid's space. 249999ebb4caSwyllys */ 250099ebb4caSwyllys if (req != NULL) { 250199ebb4caSwyllys OCSP_REQUEST_free(req); 250299ebb4caSwyllys } 250399ebb4caSwyllys 250499ebb4caSwyllys if (derbio != NULL) { 250599ebb4caSwyllys (void) BIO_free(derbio); 250699ebb4caSwyllys } 250799ebb4caSwyllys 250899ebb4caSwyllys return (ret); 250999ebb4caSwyllys } 251099ebb4caSwyllys 251199ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */ 2512300fdee2SAndy Fiddaman static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_BASICRESP *bs) 251399ebb4caSwyllys { 251499ebb4caSwyllys int i; 251599ebb4caSwyllys unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash; 2516300fdee2SAndy Fiddaman const ASN1_OCTET_STRING *pid; 251799ebb4caSwyllys 2518*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 2519300fdee2SAndy Fiddaman OCSP_RESPID *id = bs->tbsResponseData->responderId; 2520300fdee2SAndy Fiddaman 252199ebb4caSwyllys if (id->type == V_OCSP_RESPID_NAME) 252299ebb4caSwyllys return (X509_find_by_subject(certs, id->value.byName)); 252399ebb4caSwyllys 2524300fdee2SAndy Fiddaman pid = id->value.byKey; 2525300fdee2SAndy Fiddaman #else 2526300fdee2SAndy Fiddaman const X509_NAME *pname; 2527300fdee2SAndy Fiddaman 2528300fdee2SAndy Fiddaman if (OCSP_resp_get0_id(bs, &pid, &pname) == 0) 2529300fdee2SAndy Fiddaman return (NULL); 2530300fdee2SAndy Fiddaman 2531300fdee2SAndy Fiddaman if (pname != NULL) 2532300fdee2SAndy Fiddaman return (X509_find_by_subject(certs, (X509_NAME *)pname)); 2533300fdee2SAndy Fiddaman #endif 2534300fdee2SAndy Fiddaman 253599ebb4caSwyllys /* Lookup by key hash */ 253699ebb4caSwyllys 253799ebb4caSwyllys /* If key hash isn't SHA1 length then forget it */ 2538300fdee2SAndy Fiddaman if (pid->length != SHA_DIGEST_LENGTH) 253999ebb4caSwyllys return (NULL); 254099ebb4caSwyllys 2541300fdee2SAndy Fiddaman keyhash = pid->data; 254299ebb4caSwyllys /* Calculate hash of each key and compare */ 254399ebb4caSwyllys for (i = 0; i < sk_X509_num(certs); i++) { 2544d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 254599ebb4caSwyllys X509 *x = sk_X509_value(certs, i); 25465b3e1433Swyllys /* Use pubkey_digest to get the key ID value */ 254799ebb4caSwyllys (void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL); 254899ebb4caSwyllys if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH)) 254999ebb4caSwyllys return (x); 255099ebb4caSwyllys } 255199ebb4caSwyllys return (NULL); 255299ebb4caSwyllys } 255399ebb4caSwyllys 255499ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */ 2555a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */ 255699ebb4caSwyllys static int 255799ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs, 255899ebb4caSwyllys X509_STORE *st, unsigned long flags) 255999ebb4caSwyllys { 256099ebb4caSwyllys X509 *signer; 2561300fdee2SAndy Fiddaman if ((signer = ocsp_find_signer_sk(certs, bs))) { 256299ebb4caSwyllys *psigner = signer; 256399ebb4caSwyllys return (2); 256499ebb4caSwyllys } 2565300fdee2SAndy Fiddaman 256699ebb4caSwyllys if (!(flags & OCSP_NOINTERN) && 2567300fdee2SAndy Fiddaman (signer = ocsp_find_signer_sk( 2568300fdee2SAndy Fiddaman (STACK_OF(X509) *)OCSP_resp_get0_certs(bs), bs))) { 256999ebb4caSwyllys *psigner = signer; 257099ebb4caSwyllys return (1); 257199ebb4caSwyllys } 257299ebb4caSwyllys /* Maybe lookup from store if by subject name */ 257399ebb4caSwyllys 257499ebb4caSwyllys *psigner = NULL; 257599ebb4caSwyllys return (0); 257699ebb4caSwyllys } 257799ebb4caSwyllys 257899ebb4caSwyllys /* 257999ebb4caSwyllys * This function will verify the signature of a basic response, using 258099ebb4caSwyllys * the public key from the OCSP responder certificate. 258199ebb4caSwyllys */ 258299ebb4caSwyllys static KMF_RETURN 258399ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs, 258499ebb4caSwyllys KMF_DATA *signer_cert, KMF_DATA *issuer_cert) 258599ebb4caSwyllys { 258699ebb4caSwyllys KMF_RETURN ret = KMF_OK; 258799ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 258899ebb4caSwyllys STACK_OF(X509) *cert_stack = NULL; 258999ebb4caSwyllys X509 *signer = NULL; 259099ebb4caSwyllys X509 *issuer = NULL; 2591*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 259299ebb4caSwyllys EVP_PKEY *skey = NULL; 2593300fdee2SAndy Fiddaman #else 2594300fdee2SAndy Fiddaman STACK_OF(X509) *cert_stack2 = NULL; 2595300fdee2SAndy Fiddaman #endif 259699ebb4caSwyllys unsigned char *ptmp; 259799ebb4caSwyllys 259899ebb4caSwyllys if (bs == NULL || issuer_cert == NULL) 259999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 260099ebb4caSwyllys 260199ebb4caSwyllys /* 260299ebb4caSwyllys * Find the certificate that signed the basic response. 260399ebb4caSwyllys * 260499ebb4caSwyllys * If signer_cert is not NULL, we will use that as the signer cert. 260599ebb4caSwyllys * Otherwise, we will check if the issuer cert is actually the signer. 260699ebb4caSwyllys * If we still do not find a signer, we will look for it from the 260799ebb4caSwyllys * certificate list came with the response file. 260899ebb4caSwyllys */ 260999ebb4caSwyllys if (signer_cert != NULL) { 261099ebb4caSwyllys ptmp = signer_cert->Data; 261199ebb4caSwyllys signer = d2i_X509(NULL, (const uchar_t **)&ptmp, 261299ebb4caSwyllys signer_cert->Length); 261399ebb4caSwyllys if (signer == NULL) { 261499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 261599ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_SIGNER; 261699ebb4caSwyllys goto end; 261799ebb4caSwyllys } 261899ebb4caSwyllys } else { 261999ebb4caSwyllys /* 262099ebb4caSwyllys * Convert the issuer cert into X509 and push it into a 262199ebb4caSwyllys * stack to be used by ocsp_find_signer(). 262299ebb4caSwyllys */ 262399ebb4caSwyllys ptmp = issuer_cert->Data; 262499ebb4caSwyllys issuer = d2i_X509(NULL, (const uchar_t **)&ptmp, 262599ebb4caSwyllys issuer_cert->Length); 262699ebb4caSwyllys if (issuer == NULL) { 262799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 262899ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_ISSUER; 262999ebb4caSwyllys goto end; 263099ebb4caSwyllys } 263199ebb4caSwyllys 263299ebb4caSwyllys if ((cert_stack = sk_X509_new_null()) == NULL) { 263399ebb4caSwyllys ret = KMF_ERR_INTERNAL; 263499ebb4caSwyllys goto end; 263599ebb4caSwyllys } 263699ebb4caSwyllys 263799ebb4caSwyllys if (sk_X509_push(cert_stack, issuer) == NULL) { 263899ebb4caSwyllys ret = KMF_ERR_INTERNAL; 263999ebb4caSwyllys goto end; 264099ebb4caSwyllys } 264199ebb4caSwyllys 264299ebb4caSwyllys ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0); 264399ebb4caSwyllys if (!ret) { 264499ebb4caSwyllys /* can not find the signer */ 264599ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_SIGNER; 264699ebb4caSwyllys goto end; 264799ebb4caSwyllys } 264899ebb4caSwyllys } 264999ebb4caSwyllys 265099ebb4caSwyllys /* Verify the signature of the response */ 2651*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 265299ebb4caSwyllys skey = X509_get_pubkey(signer); 265399ebb4caSwyllys if (skey == NULL) { 265499ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_SIGNER; 265599ebb4caSwyllys goto end; 265699ebb4caSwyllys } 265799ebb4caSwyllys 265899ebb4caSwyllys ret = OCSP_BASICRESP_verify(bs, skey, 0); 2659300fdee2SAndy Fiddaman #else 2660300fdee2SAndy Fiddaman /* 2661300fdee2SAndy Fiddaman * Technique based on 2662300fdee2SAndy Fiddaman * https://mta.openssl.org/pipermail/openssl-users/ 2663300fdee2SAndy Fiddaman * 2017-October/006814.html 2664300fdee2SAndy Fiddaman */ 2665300fdee2SAndy Fiddaman if ((cert_stack2 = sk_X509_new_null()) == NULL) { 2666300fdee2SAndy Fiddaman ret = KMF_ERR_INTERNAL; 2667300fdee2SAndy Fiddaman goto end; 2668300fdee2SAndy Fiddaman } 2669300fdee2SAndy Fiddaman 2670300fdee2SAndy Fiddaman if (sk_X509_push(cert_stack2, signer) == NULL) { 2671300fdee2SAndy Fiddaman ret = KMF_ERR_INTERNAL; 2672300fdee2SAndy Fiddaman goto end; 2673300fdee2SAndy Fiddaman } 2674300fdee2SAndy Fiddaman 2675300fdee2SAndy Fiddaman ret = OCSP_basic_verify(bs, cert_stack2, NULL, OCSP_NOVERIFY); 2676300fdee2SAndy Fiddaman #endif 2677300fdee2SAndy Fiddaman 267899ebb4caSwyllys if (ret == 0) { 267999ebb4caSwyllys ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE; 268099ebb4caSwyllys goto end; 268199ebb4caSwyllys } 268299ebb4caSwyllys 268399ebb4caSwyllys end: 268499ebb4caSwyllys if (issuer != NULL) { 268599ebb4caSwyllys X509_free(issuer); 268699ebb4caSwyllys } 268799ebb4caSwyllys 268899ebb4caSwyllys if (signer != NULL) { 268999ebb4caSwyllys X509_free(signer); 269099ebb4caSwyllys } 269199ebb4caSwyllys 2692*553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 269399ebb4caSwyllys if (skey != NULL) { 269499ebb4caSwyllys EVP_PKEY_free(skey); 269599ebb4caSwyllys } 2696300fdee2SAndy Fiddaman #else 2697300fdee2SAndy Fiddaman if (cert_stack2 != NULL) { 2698300fdee2SAndy Fiddaman sk_X509_free(cert_stack2); 2699300fdee2SAndy Fiddaman } 2700300fdee2SAndy Fiddaman #endif 270199ebb4caSwyllys 270299ebb4caSwyllys if (cert_stack != NULL) { 270399ebb4caSwyllys sk_X509_free(cert_stack); 270499ebb4caSwyllys } 270599ebb4caSwyllys 270699ebb4caSwyllys return (ret); 270799ebb4caSwyllys } 270899ebb4caSwyllys 270999ebb4caSwyllys KMF_RETURN 271099ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle, 271130a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 271299ebb4caSwyllys { 271399ebb4caSwyllys KMF_RETURN ret = KMF_OK; 271499ebb4caSwyllys BIO *derbio = NULL; 271599ebb4caSwyllys OCSP_RESPONSE *resp = NULL; 271699ebb4caSwyllys OCSP_BASICRESP *bs = NULL; 271799ebb4caSwyllys OCSP_CERTID *id = NULL; 271899ebb4caSwyllys OCSP_SINGLERESP *single = NULL; 271999ebb4caSwyllys ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; 272099ebb4caSwyllys int index, status, reason; 272130a5e8faSwyllys KMF_DATA *issuer_cert; 272230a5e8faSwyllys KMF_DATA *user_cert; 272330a5e8faSwyllys KMF_DATA *signer_cert; 272430a5e8faSwyllys KMF_DATA *response; 272530a5e8faSwyllys int *response_reason, *response_status, *cert_status; 272630a5e8faSwyllys boolean_t ignore_response_sign = B_FALSE; /* default is FALSE */ 272730a5e8faSwyllys uint32_t response_lifetime; 272899ebb4caSwyllys 272930a5e8faSwyllys issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR, 273030a5e8faSwyllys attrlist, numattr); 273130a5e8faSwyllys if (issuer_cert == NULL) 273299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 273399ebb4caSwyllys 273430a5e8faSwyllys user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR, 273530a5e8faSwyllys attrlist, numattr); 273630a5e8faSwyllys if (user_cert == NULL) 273799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 273830a5e8faSwyllys 273930a5e8faSwyllys response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR, 274030a5e8faSwyllys attrlist, numattr); 274130a5e8faSwyllys if (response == NULL) 274230a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 274330a5e8faSwyllys 274430a5e8faSwyllys response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR, 274530a5e8faSwyllys attrlist, numattr); 274630a5e8faSwyllys if (response_status == NULL) 274730a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 274830a5e8faSwyllys 274930a5e8faSwyllys response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR, 275030a5e8faSwyllys attrlist, numattr); 275130a5e8faSwyllys if (response_reason == NULL) 275230a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 275330a5e8faSwyllys 275430a5e8faSwyllys cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR, 275530a5e8faSwyllys attrlist, numattr); 275630a5e8faSwyllys if (cert_status == NULL) 275730a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 275899ebb4caSwyllys 275999ebb4caSwyllys /* Read in the response */ 276030a5e8faSwyllys derbio = BIO_new_mem_buf(response->Data, response->Length); 276199ebb4caSwyllys if (!derbio) { 276299ebb4caSwyllys ret = KMF_ERR_MEMORY; 276399ebb4caSwyllys return (ret); 276499ebb4caSwyllys } 276599ebb4caSwyllys 276699ebb4caSwyllys resp = d2i_OCSP_RESPONSE_bio(derbio, NULL); 276799ebb4caSwyllys if (resp == NULL) { 276899ebb4caSwyllys ret = KMF_ERR_OCSP_MALFORMED_RESPONSE; 276999ebb4caSwyllys goto end; 277099ebb4caSwyllys } 277199ebb4caSwyllys 277299ebb4caSwyllys /* Check the response status */ 277399ebb4caSwyllys status = OCSP_response_status(resp); 277430a5e8faSwyllys *response_status = status; 277599ebb4caSwyllys if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { 277699ebb4caSwyllys ret = KMF_ERR_OCSP_RESPONSE_STATUS; 277799ebb4caSwyllys goto end; 277899ebb4caSwyllys } 277999ebb4caSwyllys 278099ebb4caSwyllys #ifdef DEBUG 278199ebb4caSwyllys printf("Successfully checked the response file status.\n"); 278299ebb4caSwyllys #endif /* DEBUG */ 278399ebb4caSwyllys 278499ebb4caSwyllys /* Extract basic response */ 278599ebb4caSwyllys bs = OCSP_response_get1_basic(resp); 278699ebb4caSwyllys if (bs == NULL) { 278799ebb4caSwyllys ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE; 278899ebb4caSwyllys goto end; 278999ebb4caSwyllys } 279099ebb4caSwyllys 279199ebb4caSwyllys #ifdef DEBUG 279299ebb4caSwyllys printf("Successfully retrieved the basic response.\n"); 279399ebb4caSwyllys #endif /* DEBUG */ 279499ebb4caSwyllys 279599ebb4caSwyllys /* Check the basic response signature if required */ 279630a5e8faSwyllys ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr, 279730a5e8faSwyllys (void *)&ignore_response_sign, NULL); 279830a5e8faSwyllys if (ret != KMF_OK) 279930a5e8faSwyllys ret = KMF_OK; 280030a5e8faSwyllys 280130a5e8faSwyllys signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR, 280230a5e8faSwyllys attrlist, numattr); 280330a5e8faSwyllys 280430a5e8faSwyllys if (ignore_response_sign == B_FALSE) { 280599ebb4caSwyllys ret = check_response_signature(handle, bs, 280630a5e8faSwyllys signer_cert, issuer_cert); 280799ebb4caSwyllys if (ret != KMF_OK) 280899ebb4caSwyllys goto end; 280999ebb4caSwyllys } 281099ebb4caSwyllys 281199ebb4caSwyllys #ifdef DEBUG 281299ebb4caSwyllys printf("Successfully verified the response signature.\n"); 281399ebb4caSwyllys #endif /* DEBUG */ 281499ebb4caSwyllys 281599ebb4caSwyllys /* Create a certid for the certificate in question */ 281630a5e8faSwyllys ret = create_certid(handle, issuer_cert, user_cert, &id); 281799ebb4caSwyllys if (ret != KMF_OK) { 281899ebb4caSwyllys ret = KMF_ERR_OCSP_CERTID; 281999ebb4caSwyllys goto end; 282099ebb4caSwyllys } 282199ebb4caSwyllys 282299ebb4caSwyllys #ifdef DEBUG 282399ebb4caSwyllys printf("successfully created a certid for the cert.\n"); 282499ebb4caSwyllys #endif /* DEBUG */ 282599ebb4caSwyllys 282699ebb4caSwyllys /* Find the index of the single response for the certid */ 282799ebb4caSwyllys index = OCSP_resp_find(bs, id, -1); 282899ebb4caSwyllys if (index < 0) { 282999ebb4caSwyllys /* cound not find this certificate in the response */ 283099ebb4caSwyllys ret = KMF_ERR_OCSP_UNKNOWN_CERT; 283199ebb4caSwyllys goto end; 283299ebb4caSwyllys } 283399ebb4caSwyllys 283499ebb4caSwyllys #ifdef DEBUG 283599ebb4caSwyllys printf("Successfully found the single response index for the cert.\n"); 283699ebb4caSwyllys #endif /* DEBUG */ 283799ebb4caSwyllys 283899ebb4caSwyllys /* Retrieve the single response and get the cert status */ 283999ebb4caSwyllys single = OCSP_resp_get0(bs, index); 284099ebb4caSwyllys status = OCSP_single_get0_status(single, &reason, &rev, &thisupd, 284199ebb4caSwyllys &nextupd); 284299ebb4caSwyllys if (status == V_OCSP_CERTSTATUS_GOOD) { 284330a5e8faSwyllys *cert_status = OCSP_GOOD; 284499ebb4caSwyllys } else if (status == V_OCSP_CERTSTATUS_UNKNOWN) { 284530a5e8faSwyllys *cert_status = OCSP_UNKNOWN; 284699ebb4caSwyllys } else { /* revoked */ 284730a5e8faSwyllys *cert_status = OCSP_REVOKED; 284830a5e8faSwyllys *response_reason = reason; 284999ebb4caSwyllys } 285099ebb4caSwyllys ret = KMF_OK; 285199ebb4caSwyllys 285230a5e8faSwyllys /* resp. time is optional, so we don't care about the return code. */ 285330a5e8faSwyllys (void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr, 285430a5e8faSwyllys (void *)&response_lifetime, NULL); 285530a5e8faSwyllys 285699ebb4caSwyllys if (!OCSP_check_validity(thisupd, nextupd, 300, 285730a5e8faSwyllys response_lifetime)) { 285899ebb4caSwyllys ret = KMF_ERR_OCSP_STATUS_TIME_INVALID; 285999ebb4caSwyllys goto end; 286099ebb4caSwyllys } 286199ebb4caSwyllys 286299ebb4caSwyllys #ifdef DEBUG 286399ebb4caSwyllys printf("Successfully verify the time.\n"); 286499ebb4caSwyllys #endif /* DEBUG */ 286599ebb4caSwyllys 286699ebb4caSwyllys end: 286799ebb4caSwyllys if (derbio != NULL) 286899ebb4caSwyllys (void) BIO_free(derbio); 286999ebb4caSwyllys 287099ebb4caSwyllys if (resp != NULL) 287199ebb4caSwyllys OCSP_RESPONSE_free(resp); 287299ebb4caSwyllys 287399ebb4caSwyllys if (bs != NULL) 287499ebb4caSwyllys OCSP_BASICRESP_free(bs); 287599ebb4caSwyllys 287699ebb4caSwyllys if (id != NULL) 287799ebb4caSwyllys OCSP_CERTID_free(id); 287899ebb4caSwyllys 287999ebb4caSwyllys return (ret); 288099ebb4caSwyllys } 288199ebb4caSwyllys 288299ebb4caSwyllys static KMF_RETURN 288399ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path, 288499ebb4caSwyllys KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key) 288599ebb4caSwyllys { 288699ebb4caSwyllys KMF_RETURN rv = KMF_OK; 288730a5e8faSwyllys EVP_PKEY *pkey = NULL; 288899ebb4caSwyllys KMF_RAW_SYM_KEY *rkey = NULL; 288999ebb4caSwyllys 289099ebb4caSwyllys if (keyclass == KMF_ASYM_PRI || 289199ebb4caSwyllys keyclass == KMF_ASYM_PUB) { 289299ebb4caSwyllys pkey = openssl_load_key(handle, path); 289399ebb4caSwyllys if (pkey == NULL) { 289499ebb4caSwyllys return (KMF_ERR_KEY_NOT_FOUND); 289599ebb4caSwyllys } 289699ebb4caSwyllys if (key != NULL) { 2897300fdee2SAndy Fiddaman if (EVP_PKEY_get0_RSA(pkey) != NULL) 289899ebb4caSwyllys key->keyalg = KMF_RSA; 2899300fdee2SAndy Fiddaman else if (EVP_PKEY_get0_DSA(pkey) != NULL) 290099ebb4caSwyllys key->keyalg = KMF_DSA; 290199ebb4caSwyllys 290299ebb4caSwyllys key->kstype = KMF_KEYSTORE_OPENSSL; 290399ebb4caSwyllys key->keyclass = keyclass; 290499ebb4caSwyllys key->keyp = (void *)pkey; 290599ebb4caSwyllys key->israw = FALSE; 29065b3e1433Swyllys if (path != NULL && 29075b3e1433Swyllys ((key->keylabel = strdup(path)) == NULL)) { 29085b3e1433Swyllys EVP_PKEY_free(pkey); 29095b3e1433Swyllys return (KMF_ERR_MEMORY); 29105b3e1433Swyllys } 291199ebb4caSwyllys } else { 291299ebb4caSwyllys EVP_PKEY_free(pkey); 291399ebb4caSwyllys pkey = NULL; 291499ebb4caSwyllys } 291599ebb4caSwyllys } else if (keyclass == KMF_SYMMETRIC) { 291699ebb4caSwyllys KMF_ENCODE_FORMAT fmt; 291799ebb4caSwyllys /* 291899ebb4caSwyllys * If the file is a recognized format, 291999ebb4caSwyllys * then it is NOT a symmetric key. 292099ebb4caSwyllys */ 292130a5e8faSwyllys rv = kmf_get_file_format(path, &fmt); 292299ebb4caSwyllys if (rv == KMF_OK || fmt != 0) { 292399ebb4caSwyllys return (KMF_ERR_KEY_NOT_FOUND); 292499ebb4caSwyllys } else if (rv == KMF_ERR_ENCODING) { 292599ebb4caSwyllys /* 292699ebb4caSwyllys * If we don't know the encoding, 292799ebb4caSwyllys * it is probably a symmetric key. 292899ebb4caSwyllys */ 292999ebb4caSwyllys rv = KMF_OK; 293030a5e8faSwyllys } else if (rv == KMF_ERR_OPEN_FILE) { 293130a5e8faSwyllys return (KMF_ERR_KEY_NOT_FOUND); 293299ebb4caSwyllys } 293399ebb4caSwyllys 293499ebb4caSwyllys if (key != NULL) { 293599ebb4caSwyllys KMF_DATA keyvalue; 293699ebb4caSwyllys rkey = malloc(sizeof (KMF_RAW_SYM_KEY)); 293799ebb4caSwyllys if (rkey == NULL) { 293899ebb4caSwyllys rv = KMF_ERR_MEMORY; 293999ebb4caSwyllys goto out; 294099ebb4caSwyllys } 294199ebb4caSwyllys 294299ebb4caSwyllys (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 294330a5e8faSwyllys rv = kmf_read_input_file(handle, path, &keyvalue); 294499ebb4caSwyllys if (rv != KMF_OK) 294599ebb4caSwyllys goto out; 294699ebb4caSwyllys 294799ebb4caSwyllys rkey->keydata.len = keyvalue.Length; 294899ebb4caSwyllys rkey->keydata.val = keyvalue.Data; 294999ebb4caSwyllys 295099ebb4caSwyllys key->kstype = KMF_KEYSTORE_OPENSSL; 295199ebb4caSwyllys key->keyclass = keyclass; 295299ebb4caSwyllys key->israw = TRUE; 295399ebb4caSwyllys key->keyp = (void *)rkey; 29545b3e1433Swyllys if (path != NULL && 29555b3e1433Swyllys ((key->keylabel = strdup(path)) == NULL)) { 29565b3e1433Swyllys rv = KMF_ERR_MEMORY; 29575b3e1433Swyllys } 295899ebb4caSwyllys } 295999ebb4caSwyllys } 296099ebb4caSwyllys out: 296199ebb4caSwyllys if (rv != KMF_OK) { 296299ebb4caSwyllys if (rkey != NULL) { 296330a5e8faSwyllys kmf_free_raw_sym_key(rkey); 296499ebb4caSwyllys } 296599ebb4caSwyllys if (pkey != NULL) 296699ebb4caSwyllys EVP_PKEY_free(pkey); 296799ebb4caSwyllys 296899ebb4caSwyllys if (key != NULL) { 296999ebb4caSwyllys key->keyalg = KMF_KEYALG_NONE; 297099ebb4caSwyllys key->keyclass = KMF_KEYCLASS_NONE; 297199ebb4caSwyllys key->keyp = NULL; 297299ebb4caSwyllys } 297399ebb4caSwyllys } 297499ebb4caSwyllys 297599ebb4caSwyllys return (rv); 297699ebb4caSwyllys } 297799ebb4caSwyllys 297899ebb4caSwyllys KMF_RETURN 297930a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle, 298030a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 298199ebb4caSwyllys { 298299ebb4caSwyllys KMF_RETURN rv = KMF_OK; 298399ebb4caSwyllys char *fullpath = NULL; 2984f482c776Swyllys uint32_t maxkeys; 298530a5e8faSwyllys KMF_KEY_HANDLE *key; 298630a5e8faSwyllys uint32_t *numkeys; 298730a5e8faSwyllys KMF_KEY_CLASS keyclass; 298830a5e8faSwyllys KMF_RAW_KEY_DATA *rawkey; 298930a5e8faSwyllys char *dirpath; 299030a5e8faSwyllys char *keyfile; 299199ebb4caSwyllys 299230a5e8faSwyllys if (handle == NULL) 299399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 299499ebb4caSwyllys 299530a5e8faSwyllys numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr); 299630a5e8faSwyllys if (numkeys == NULL) 299730a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 299830a5e8faSwyllys 299930a5e8faSwyllys rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr, 300030a5e8faSwyllys (void *)&keyclass, NULL); 300130a5e8faSwyllys if (rv != KMF_OK) 300230a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 300330a5e8faSwyllys 300430a5e8faSwyllys if (keyclass != KMF_ASYM_PUB && 300530a5e8faSwyllys keyclass != KMF_ASYM_PRI && 300630a5e8faSwyllys keyclass != KMF_SYMMETRIC) 300799ebb4caSwyllys return (KMF_ERR_BAD_KEY_CLASS); 300899ebb4caSwyllys 300930a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 301030a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 301130a5e8faSwyllys 301230a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 301399ebb4caSwyllys 301499ebb4caSwyllys if (fullpath == NULL) 301599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 301699ebb4caSwyllys 3017f482c776Swyllys maxkeys = *numkeys; 3018f482c776Swyllys if (maxkeys == 0) 3019f482c776Swyllys maxkeys = 0xFFFFFFFF; 302099ebb4caSwyllys *numkeys = 0; 302199ebb4caSwyllys 302230a5e8faSwyllys key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 302330a5e8faSwyllys /* it is okay to have "keys" contains NULL */ 302430a5e8faSwyllys 302530a5e8faSwyllys /* 302630a5e8faSwyllys * The caller may want a list of the raw key data as well. 302730a5e8faSwyllys * Useful for importing keys from a file into other keystores. 302830a5e8faSwyllys */ 302930a5e8faSwyllys rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr); 303030a5e8faSwyllys 303199ebb4caSwyllys if (isdir(fullpath)) { 303299ebb4caSwyllys DIR *dirp; 303399ebb4caSwyllys struct dirent *dp; 303499ebb4caSwyllys int n = 0; 303599ebb4caSwyllys 303699ebb4caSwyllys /* open all files in the directory and attempt to read them */ 303799ebb4caSwyllys if ((dirp = opendir(fullpath)) == NULL) { 303899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 303999ebb4caSwyllys } 304099ebb4caSwyllys rewinddir(dirp); 3041f482c776Swyllys while ((dp = readdir(dirp)) != NULL && n < maxkeys) { 304299ebb4caSwyllys if (strcmp(dp->d_name, ".") && 304399ebb4caSwyllys strcmp(dp->d_name, "..")) { 304499ebb4caSwyllys char *fname; 304599ebb4caSwyllys 304699ebb4caSwyllys fname = get_fullpath(fullpath, 304799ebb4caSwyllys (char *)&dp->d_name); 304899ebb4caSwyllys 304999ebb4caSwyllys rv = fetch_key(handle, fname, 305030a5e8faSwyllys keyclass, key ? &key[n] : NULL); 305199ebb4caSwyllys 305230a5e8faSwyllys if (rv == KMF_OK) { 305330a5e8faSwyllys if (key != NULL && rawkey != NULL) 305430a5e8faSwyllys rv = convertToRawKey( 305530a5e8faSwyllys key[n].keyp, &rawkey[n]); 305699ebb4caSwyllys n++; 305730a5e8faSwyllys } 305899ebb4caSwyllys 305999ebb4caSwyllys if (rv != KMF_OK || key == NULL) 306099ebb4caSwyllys free(fname); 306199ebb4caSwyllys } 306299ebb4caSwyllys } 306399ebb4caSwyllys (void) closedir(dirp); 306499ebb4caSwyllys free(fullpath); 306599ebb4caSwyllys (*numkeys) = n; 306699ebb4caSwyllys } else { 306730a5e8faSwyllys rv = fetch_key(handle, fullpath, keyclass, key); 306899ebb4caSwyllys if (rv == KMF_OK) 306999ebb4caSwyllys (*numkeys) = 1; 307099ebb4caSwyllys 307199ebb4caSwyllys if (rv != KMF_OK || key == NULL) 307299ebb4caSwyllys free(fullpath); 307330a5e8faSwyllys 307430a5e8faSwyllys if (rv == KMF_OK && key != NULL && rawkey != NULL) { 307530a5e8faSwyllys rv = convertToRawKey(key->keyp, rawkey); 307630a5e8faSwyllys } 307799ebb4caSwyllys } 307899ebb4caSwyllys 3079f482c776Swyllys if (rv == KMF_OK && (*numkeys) == 0) 308099ebb4caSwyllys rv = KMF_ERR_KEY_NOT_FOUND; 308173cc0e02Swyllys else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0) 308273cc0e02Swyllys rv = KMF_OK; 308399ebb4caSwyllys 308499ebb4caSwyllys return (rv); 308599ebb4caSwyllys } 308699ebb4caSwyllys 308799ebb4caSwyllys #define HANDLE_PK12_ERROR { \ 308899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); \ 308999ebb4caSwyllys rv = KMF_ERR_ENCODING; \ 309099ebb4caSwyllys goto out; \ 309199ebb4caSwyllys } 309299ebb4caSwyllys 30935b3e1433Swyllys static int 30945b3e1433Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert) 309599ebb4caSwyllys { 3096300fdee2SAndy Fiddaman unsigned char *alias; 3097300fdee2SAndy Fiddaman int len; 3098300fdee2SAndy Fiddaman 3099300fdee2SAndy Fiddaman if (xcert != NULL && (alias = X509_alias_get0(xcert, &len)) != NULL) { 31005b3e1433Swyllys if (PKCS12_add_friendlyname_asc(bag, 3101300fdee2SAndy Fiddaman (const char *)alias, len) == 0) 31025b3e1433Swyllys return (0); 31035b3e1433Swyllys } 31045b3e1433Swyllys return (1); 31055b3e1433Swyllys } 31065b3e1433Swyllys 31075b3e1433Swyllys static PKCS7 * 31085b3e1433Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred, 31095b3e1433Swyllys uchar_t *keyid, unsigned int keyidlen) 31105b3e1433Swyllys { 311199ebb4caSwyllys PKCS12_SAFEBAG *bag = NULL; 311299ebb4caSwyllys PKCS7 *cert_authsafe = NULL; 31135b3e1433Swyllys STACK_OF(PKCS12_SAFEBAG) *bag_stack; 311499ebb4caSwyllys 311599ebb4caSwyllys bag_stack = sk_PKCS12_SAFEBAG_new_null(); 311699ebb4caSwyllys if (bag_stack == NULL) 31175b3e1433Swyllys return (NULL); 311899ebb4caSwyllys 311999ebb4caSwyllys /* Convert cert from X509 struct to PKCS#12 bag */ 3120300fdee2SAndy Fiddaman bag = PKCS12_SAFEBAG_create_cert(sslcert); 312199ebb4caSwyllys if (bag == NULL) { 31225b3e1433Swyllys goto out; 312399ebb4caSwyllys } 312499ebb4caSwyllys 312599ebb4caSwyllys /* Add the key id to the certificate bag. */ 31265b3e1433Swyllys if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) { 31275b3e1433Swyllys goto out; 312899ebb4caSwyllys } 312999ebb4caSwyllys 31305b3e1433Swyllys if (!add_alias_to_bag(bag, sslcert)) 31315b3e1433Swyllys goto out; 31325b3e1433Swyllys 313399ebb4caSwyllys /* Pile it on the bag_stack. */ 313499ebb4caSwyllys if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) { 31355b3e1433Swyllys goto out; 313699ebb4caSwyllys } 313799ebb4caSwyllys /* Turn bag_stack of certs into encrypted authsafe. */ 313899ebb4caSwyllys cert_authsafe = PKCS12_pack_p7encdata( 313999ebb4caSwyllys NID_pbe_WithSHA1And40BitRC2_CBC, 314034acef67Swyllys cred->cred, cred->credlen, NULL, 0, 314134acef67Swyllys PKCS12_DEFAULT_ITER, bag_stack); 314299ebb4caSwyllys 31435b3e1433Swyllys out: 31445b3e1433Swyllys if (bag_stack != NULL) 314599ebb4caSwyllys sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); 314699ebb4caSwyllys 31475b3e1433Swyllys return (cert_authsafe); 314899ebb4caSwyllys } 31495b3e1433Swyllys 31505b3e1433Swyllys static PKCS7 * 31515b3e1433Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred, 31525b3e1433Swyllys uchar_t *keyid, unsigned int keyidlen, 31535b3e1433Swyllys char *label, int label_len) 31545b3e1433Swyllys { 31555b3e1433Swyllys PKCS8_PRIV_KEY_INFO *p8 = NULL; 31565b3e1433Swyllys STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL; 31575b3e1433Swyllys PKCS12_SAFEBAG *bag = NULL; 31585b3e1433Swyllys PKCS7 *key_authsafe = NULL; 31595b3e1433Swyllys 316099ebb4caSwyllys p8 = EVP_PKEY2PKCS8(pkey); 316199ebb4caSwyllys if (p8 == NULL) { 31625b3e1433Swyllys return (NULL); 316399ebb4caSwyllys } 316499ebb4caSwyllys /* Put the shrouded key into a PKCS#12 bag. */ 3165300fdee2SAndy Fiddaman bag = PKCS12_SAFEBAG_create_pkcs8_encrypt( 316699ebb4caSwyllys NID_pbe_WithSHA1And3_Key_TripleDES_CBC, 316799ebb4caSwyllys cred->cred, cred->credlen, 316899ebb4caSwyllys NULL, 0, PKCS12_DEFAULT_ITER, p8); 316999ebb4caSwyllys 317099ebb4caSwyllys /* Clean up the PKCS#8 shrouded key, don't need it now. */ 317199ebb4caSwyllys PKCS8_PRIV_KEY_INFO_free(p8); 317299ebb4caSwyllys p8 = NULL; 317399ebb4caSwyllys 317499ebb4caSwyllys if (bag == NULL) { 31755b3e1433Swyllys return (NULL); 317699ebb4caSwyllys } 31775b3e1433Swyllys if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) 31785b3e1433Swyllys goto out; 31795b3e1433Swyllys if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len)) 31805b3e1433Swyllys goto out; 31815b3e1433Swyllys 318299ebb4caSwyllys /* Start a PKCS#12 safebag container for the private key. */ 318399ebb4caSwyllys bag_stack = sk_PKCS12_SAFEBAG_new_null(); 31845b3e1433Swyllys if (bag_stack == NULL) 31855b3e1433Swyllys goto out; 318699ebb4caSwyllys 318799ebb4caSwyllys /* Pile on the private key on the bag_stack. */ 31885b3e1433Swyllys if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) 31895b3e1433Swyllys goto out; 31905b3e1433Swyllys 319199ebb4caSwyllys key_authsafe = PKCS12_pack_p7data(bag_stack); 319299ebb4caSwyllys 31935b3e1433Swyllys out: 31945b3e1433Swyllys if (bag_stack != NULL) 319599ebb4caSwyllys sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); 319699ebb4caSwyllys bag_stack = NULL; 31975b3e1433Swyllys return (key_authsafe); 319899ebb4caSwyllys } 319999ebb4caSwyllys 320099ebb4caSwyllys static EVP_PKEY * 320199ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key) 320299ebb4caSwyllys { 320399ebb4caSwyllys RSA *rsa = NULL; 320499ebb4caSwyllys EVP_PKEY *newkey = NULL; 3205300fdee2SAndy Fiddaman BIGNUM *n = NULL, *e = NULL, *d = NULL, 3206300fdee2SAndy Fiddaman *p = NULL, *q = NULL, 3207300fdee2SAndy Fiddaman *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; 320899ebb4caSwyllys 320999ebb4caSwyllys if ((rsa = RSA_new()) == NULL) 3210300fdee2SAndy Fiddaman goto cleanup; 321199ebb4caSwyllys 3212300fdee2SAndy Fiddaman if ((n = BN_bin2bn(key->mod.val, key->mod.len, NULL)) == NULL) 3213300fdee2SAndy Fiddaman goto cleanup; 321499ebb4caSwyllys 3215300fdee2SAndy Fiddaman if ((e = BN_bin2bn(key->pubexp.val, key->pubexp.len, NULL)) == NULL) 3216300fdee2SAndy Fiddaman goto cleanup; 321799ebb4caSwyllys 3218300fdee2SAndy Fiddaman if (key->priexp.val != NULL && 3219300fdee2SAndy Fiddaman (d = BN_bin2bn(key->priexp.val, key->priexp.len, NULL)) == NULL) 3220300fdee2SAndy Fiddaman goto cleanup; 322199ebb4caSwyllys 3222300fdee2SAndy Fiddaman if (key->prime1.val != NULL && 3223300fdee2SAndy Fiddaman (p = BN_bin2bn(key->prime1.val, key->prime1.len, NULL)) == NULL) 3224300fdee2SAndy Fiddaman goto cleanup; 322599ebb4caSwyllys 3226300fdee2SAndy Fiddaman if (key->prime2.val != NULL && 3227300fdee2SAndy Fiddaman (q = BN_bin2bn(key->prime2.val, key->prime2.len, NULL)) == NULL) 3228300fdee2SAndy Fiddaman goto cleanup; 322999ebb4caSwyllys 3230300fdee2SAndy Fiddaman if (key->exp1.val != NULL && 3231300fdee2SAndy Fiddaman (dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len, NULL)) == NULL) 3232300fdee2SAndy Fiddaman goto cleanup; 323399ebb4caSwyllys 3234300fdee2SAndy Fiddaman if (key->exp2.val != NULL && 3235300fdee2SAndy Fiddaman (dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len, NULL)) == NULL) 3236300fdee2SAndy Fiddaman goto cleanup; 323799ebb4caSwyllys 3238300fdee2SAndy Fiddaman if (key->coef.val != NULL && 3239300fdee2SAndy Fiddaman (iqmp = BN_bin2bn(key->coef.val, key->coef.len, NULL)) == NULL) 3240300fdee2SAndy Fiddaman goto cleanup; 3241300fdee2SAndy Fiddaman 3242300fdee2SAndy Fiddaman if (RSA_set0_key(rsa, n, e, d) == 0) 3243300fdee2SAndy Fiddaman goto cleanup; 3244300fdee2SAndy Fiddaman n = e = d = NULL; 3245300fdee2SAndy Fiddaman if (RSA_set0_factors(rsa, p, q) == 0) 3246300fdee2SAndy Fiddaman goto cleanup; 3247300fdee2SAndy Fiddaman p = q = NULL; 3248300fdee2SAndy Fiddaman if (RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp) == 0) 3249300fdee2SAndy Fiddaman goto cleanup; 3250300fdee2SAndy Fiddaman dmp1 = dmq1 = iqmp = NULL; 325199ebb4caSwyllys 325299ebb4caSwyllys if ((newkey = EVP_PKEY_new()) == NULL) 3253300fdee2SAndy Fiddaman goto cleanup; 325499ebb4caSwyllys 325599ebb4caSwyllys (void) EVP_PKEY_set1_RSA(newkey, rsa); 325699ebb4caSwyllys 3257300fdee2SAndy Fiddaman cleanup: 325899ebb4caSwyllys /* The original key must be freed once here or it leaks memory */ 3259300fdee2SAndy Fiddaman if (rsa) 326099ebb4caSwyllys RSA_free(rsa); 3261300fdee2SAndy Fiddaman BN_free(n); 3262300fdee2SAndy Fiddaman BN_free(e); 3263300fdee2SAndy Fiddaman BN_free(d); 3264300fdee2SAndy Fiddaman BN_free(p); 3265300fdee2SAndy Fiddaman BN_free(q); 3266300fdee2SAndy Fiddaman BN_free(dmp1); 3267300fdee2SAndy Fiddaman BN_free(dmq1); 3268300fdee2SAndy Fiddaman BN_free(iqmp); 326999ebb4caSwyllys 327099ebb4caSwyllys return (newkey); 327199ebb4caSwyllys } 327299ebb4caSwyllys 327399ebb4caSwyllys static EVP_PKEY * 327499ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key) 327599ebb4caSwyllys { 327699ebb4caSwyllys DSA *dsa = NULL; 327799ebb4caSwyllys EVP_PKEY *newkey = NULL; 3278300fdee2SAndy Fiddaman BIGNUM *p = NULL, *q = NULL, *g = NULL, 3279300fdee2SAndy Fiddaman *priv_key = NULL, *pub_key = NULL; 328099ebb4caSwyllys 328199ebb4caSwyllys if ((dsa = DSA_new()) == NULL) 3282300fdee2SAndy Fiddaman goto cleanup; 328399ebb4caSwyllys 3284300fdee2SAndy Fiddaman if ((p = BN_bin2bn(key->prime.val, key->prime.len, NULL)) == NULL) 3285300fdee2SAndy Fiddaman goto cleanup; 328699ebb4caSwyllys 3287300fdee2SAndy Fiddaman if ((q = BN_bin2bn(key->subprime.val, key->subprime.len, NULL)) == NULL) 3288300fdee2SAndy Fiddaman goto cleanup; 328999ebb4caSwyllys 3290300fdee2SAndy Fiddaman if ((g = BN_bin2bn(key->base.val, key->base.len, NULL)) == NULL) 3291300fdee2SAndy Fiddaman goto cleanup; 329299ebb4caSwyllys 3293300fdee2SAndy Fiddaman if ((priv_key = BN_bin2bn(key->value.val, key->value.len, 3294300fdee2SAndy Fiddaman NULL)) == NULL) 3295300fdee2SAndy Fiddaman goto cleanup; 329699ebb4caSwyllys 3297300fdee2SAndy Fiddaman if (key->pubvalue.val != NULL && (pub_key = 3298300fdee2SAndy Fiddaman BN_bin2bn(key->pubvalue.val, key->pubvalue.len, NULL)) == NULL) 3299300fdee2SAndy Fiddaman goto cleanup; 3300300fdee2SAndy Fiddaman 3301300fdee2SAndy Fiddaman if (DSA_set0_pqg(dsa, p, q, g) == 0) 3302300fdee2SAndy Fiddaman goto cleanup; 3303300fdee2SAndy Fiddaman p = q = g = NULL; 3304300fdee2SAndy Fiddaman if (DSA_set0_key(dsa, pub_key, priv_key) == 0) 3305300fdee2SAndy Fiddaman goto cleanup; 3306300fdee2SAndy Fiddaman pub_key = priv_key = 0; 330730a5e8faSwyllys 330899ebb4caSwyllys if ((newkey = EVP_PKEY_new()) == NULL) 3309300fdee2SAndy Fiddaman goto cleanup; 331099ebb4caSwyllys 331199ebb4caSwyllys (void) EVP_PKEY_set1_DSA(newkey, dsa); 331299ebb4caSwyllys 3313300fdee2SAndy Fiddaman cleanup: 331499ebb4caSwyllys /* The original key must be freed once here or it leaks memory */ 3315300fdee2SAndy Fiddaman if (dsa) 331699ebb4caSwyllys DSA_free(dsa); 3317300fdee2SAndy Fiddaman BN_free(p); 3318300fdee2SAndy Fiddaman BN_free(q); 3319300fdee2SAndy Fiddaman BN_free(g); 3320300fdee2SAndy Fiddaman BN_free(priv_key); 3321300fdee2SAndy Fiddaman BN_free(pub_key); 3322300fdee2SAndy Fiddaman 332399ebb4caSwyllys return (newkey); 332499ebb4caSwyllys } 332599ebb4caSwyllys 33265b3e1433Swyllys static EVP_PKEY * 33275b3e1433Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key) 33285b3e1433Swyllys { 33295b3e1433Swyllys EVP_PKEY *pkey = NULL; 33305b3e1433Swyllys KMF_RAW_KEY_DATA *rawkey; 33315b3e1433Swyllys ASN1_TYPE *attr = NULL; 33325b3e1433Swyllys KMF_RETURN ret; 33335b3e1433Swyllys 33345b3e1433Swyllys if (key == NULL || !key->israw) 33355b3e1433Swyllys return (NULL); 33365b3e1433Swyllys 33375b3e1433Swyllys rawkey = (KMF_RAW_KEY_DATA *)key->keyp; 33385b3e1433Swyllys if (rawkey->keytype == KMF_RSA) { 33395b3e1433Swyllys pkey = ImportRawRSAKey(&rawkey->rawdata.rsa); 33405b3e1433Swyllys } else if (rawkey->keytype == KMF_DSA) { 33415b3e1433Swyllys pkey = ImportRawDSAKey(&rawkey->rawdata.dsa); 3342e65e5c2dSWyllys Ingersoll } else if (rawkey->keytype == KMF_ECDSA) { 3343e65e5c2dSWyllys Ingersoll /* 3344e65e5c2dSWyllys Ingersoll * OpenSSL in Solaris does not support EC for 3345e65e5c2dSWyllys Ingersoll * legal reasons 3346e65e5c2dSWyllys Ingersoll */ 3347e65e5c2dSWyllys Ingersoll return (NULL); 33485b3e1433Swyllys } else { 33495b3e1433Swyllys /* wrong kind of key */ 33505b3e1433Swyllys return (NULL); 33515b3e1433Swyllys } 33525b3e1433Swyllys 33535b3e1433Swyllys if (rawkey->label != NULL) { 33545b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) { 33555b3e1433Swyllys EVP_PKEY_free(pkey); 33565b3e1433Swyllys return (NULL); 33575b3e1433Swyllys } 33585b3e1433Swyllys attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING); 33595b3e1433Swyllys (void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label, 33605b3e1433Swyllys strlen(rawkey->label)); 33615b3e1433Swyllys attr->type = V_ASN1_BMPSTRING; 33625b3e1433Swyllys attr->value.ptr = (char *)attr->value.bmpstring; 33635b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_friendlyName); 33645b3e1433Swyllys if (ret != KMF_OK) { 33655b3e1433Swyllys EVP_PKEY_free(pkey); 33665b3e1433Swyllys ASN1_TYPE_free(attr); 33675b3e1433Swyllys return (NULL); 33685b3e1433Swyllys } 33695b3e1433Swyllys } 33705b3e1433Swyllys if (rawkey->id.Data != NULL) { 33715b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) { 33725b3e1433Swyllys EVP_PKEY_free(pkey); 33735b3e1433Swyllys return (NULL); 33745b3e1433Swyllys } 33755b3e1433Swyllys attr->value.octet_string = 33765b3e1433Swyllys ASN1_STRING_type_new(V_ASN1_OCTET_STRING); 33775b3e1433Swyllys attr->type = V_ASN1_OCTET_STRING; 33785b3e1433Swyllys (void) ASN1_STRING_set(attr->value.octet_string, 33795b3e1433Swyllys rawkey->id.Data, rawkey->id.Length); 33805b3e1433Swyllys attr->value.ptr = (char *)attr->value.octet_string; 33815b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_localKeyID); 33825b3e1433Swyllys if (ret != KMF_OK) { 33835b3e1433Swyllys EVP_PKEY_free(pkey); 33845b3e1433Swyllys ASN1_TYPE_free(attr); 33855b3e1433Swyllys return (NULL); 33865b3e1433Swyllys } 33875b3e1433Swyllys } 33885b3e1433Swyllys return (pkey); 33895b3e1433Swyllys } 33905b3e1433Swyllys 33915b3e1433Swyllys /* 33925b3e1433Swyllys * Search a list of private keys to find one that goes with the certificate. 33935b3e1433Swyllys */ 33945b3e1433Swyllys static EVP_PKEY * 33955b3e1433Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist) 33965b3e1433Swyllys { 33975b3e1433Swyllys int i; 33985b3e1433Swyllys EVP_PKEY *pkey = NULL; 33995b3e1433Swyllys 34005b3e1433Swyllys if (numkeys == 0 || keylist == NULL || xcert == NULL) 34015b3e1433Swyllys return (NULL); 34025b3e1433Swyllys for (i = 0; i < numkeys; i++) { 34035b3e1433Swyllys if (keylist[i].israw) 34045b3e1433Swyllys pkey = raw_key_to_pkey(&keylist[i]); 34055b3e1433Swyllys else 34065b3e1433Swyllys pkey = (EVP_PKEY *)keylist[i].keyp; 34075b3e1433Swyllys if (pkey != NULL) { 34085b3e1433Swyllys if (X509_check_private_key(xcert, pkey)) { 34095b3e1433Swyllys return (pkey); 34105b3e1433Swyllys } else { 34115b3e1433Swyllys EVP_PKEY_free(pkey); 34125b3e1433Swyllys pkey = NULL; 34135b3e1433Swyllys } 34145b3e1433Swyllys } 34155b3e1433Swyllys } 34165b3e1433Swyllys return (pkey); 34175b3e1433Swyllys } 34185b3e1433Swyllys 341999ebb4caSwyllys static KMF_RETURN 34205b3e1433Swyllys local_export_pk12(KMF_HANDLE_T handle, 342199ebb4caSwyllys KMF_CREDENTIAL *cred, 342299ebb4caSwyllys int numcerts, KMF_X509_DER_CERT *certlist, 342399ebb4caSwyllys int numkeys, KMF_KEY_HANDLE *keylist, 342499ebb4caSwyllys char *filename) 342599ebb4caSwyllys { 342699ebb4caSwyllys KMF_RETURN rv = KMF_OK; 342799ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 342899ebb4caSwyllys BIO *bio = NULL; 34295b3e1433Swyllys PKCS7 *cert_authsafe = NULL; 34305b3e1433Swyllys PKCS7 *key_authsafe = NULL; 34315b3e1433Swyllys STACK_OF(PKCS7) *authsafe_stack = NULL; 34325b3e1433Swyllys PKCS12 *p12_elem = NULL; 343399ebb4caSwyllys int i; 343499ebb4caSwyllys 34355b3e1433Swyllys if (numcerts == 0 && numkeys == 0) 34365b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 34375b3e1433Swyllys 343899ebb4caSwyllys /* 343999ebb4caSwyllys * Open the output file. 344099ebb4caSwyllys */ 344199ebb4caSwyllys if ((bio = BIO_new_file(filename, "wb")) == NULL) { 344299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 344399ebb4caSwyllys rv = KMF_ERR_OPEN_FILE; 344499ebb4caSwyllys goto cleanup; 344599ebb4caSwyllys } 344699ebb4caSwyllys 34475b3e1433Swyllys /* Start a PKCS#7 stack. */ 34485b3e1433Swyllys authsafe_stack = sk_PKCS7_new_null(); 34495b3e1433Swyllys if (authsafe_stack == NULL) { 34505b3e1433Swyllys rv = KMF_ERR_MEMORY; 34515b3e1433Swyllys goto cleanup; 34525b3e1433Swyllys } 34535b3e1433Swyllys if (numcerts > 0) { 345499ebb4caSwyllys for (i = 0; rv == KMF_OK && i < numcerts; i++) { 345599ebb4caSwyllys const uchar_t *p = certlist[i].certificate.Data; 345699ebb4caSwyllys long len = certlist[i].certificate.Length; 34575b3e1433Swyllys X509 *xcert = NULL; 34585b3e1433Swyllys EVP_PKEY *pkey = NULL; 34595b3e1433Swyllys unsigned char keyid[EVP_MAX_MD_SIZE]; 34605b3e1433Swyllys unsigned int keyidlen = 0; 346199ebb4caSwyllys 346299ebb4caSwyllys xcert = d2i_X509(NULL, &p, len); 346399ebb4caSwyllys if (xcert == NULL) { 346499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 346599ebb4caSwyllys rv = KMF_ERR_ENCODING; 346699ebb4caSwyllys } 34675b3e1433Swyllys if (certlist[i].kmf_private.label != NULL) { 34685b3e1433Swyllys /* Set alias attribute */ 34695b3e1433Swyllys (void) X509_alias_set1(xcert, 34705b3e1433Swyllys (uchar_t *)certlist[i].kmf_private.label, 34715b3e1433Swyllys strlen(certlist[i].kmf_private.label)); 34725b3e1433Swyllys } 34735b3e1433Swyllys /* Check if there is a key corresponding to this cert */ 34745b3e1433Swyllys pkey = find_matching_key(xcert, numkeys, keylist); 34755b3e1433Swyllys 34765b3e1433Swyllys /* 34775b3e1433Swyllys * If key is found, get fingerprint and create a 34785b3e1433Swyllys * safebag. 34795b3e1433Swyllys */ 34805b3e1433Swyllys if (pkey != NULL) { 34815b3e1433Swyllys (void) X509_digest(xcert, EVP_sha1(), 34825b3e1433Swyllys keyid, &keyidlen); 34835b3e1433Swyllys key_authsafe = add_key_to_safe(pkey, cred, 34845b3e1433Swyllys keyid, keyidlen, 34855b3e1433Swyllys certlist[i].kmf_private.label, 34865b3e1433Swyllys (certlist[i].kmf_private.label ? 34875b3e1433Swyllys strlen(certlist[i].kmf_private.label) : 0)); 34885b3e1433Swyllys 34895b3e1433Swyllys if (key_authsafe == NULL) { 34905b3e1433Swyllys X509_free(xcert); 34915b3e1433Swyllys EVP_PKEY_free(pkey); 34925b3e1433Swyllys goto cleanup; 34935b3e1433Swyllys } 34945b3e1433Swyllys /* Put the key safe into the Auth Safe */ 34955b3e1433Swyllys if (!sk_PKCS7_push(authsafe_stack, 34965b3e1433Swyllys key_authsafe)) { 34975b3e1433Swyllys X509_free(xcert); 34985b3e1433Swyllys EVP_PKEY_free(pkey); 34995b3e1433Swyllys goto cleanup; 35005b3e1433Swyllys } 35015b3e1433Swyllys } 35025b3e1433Swyllys 35035b3e1433Swyllys /* create a certificate safebag */ 35045b3e1433Swyllys cert_authsafe = add_cert_to_safe(xcert, cred, keyid, 35055b3e1433Swyllys keyidlen); 35065b3e1433Swyllys if (cert_authsafe == NULL) { 35075b3e1433Swyllys X509_free(xcert); 35085b3e1433Swyllys EVP_PKEY_free(pkey); 35095b3e1433Swyllys goto cleanup; 35105b3e1433Swyllys } 35115b3e1433Swyllys if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) { 35125b3e1433Swyllys X509_free(xcert); 35135b3e1433Swyllys EVP_PKEY_free(pkey); 35145b3e1433Swyllys goto cleanup; 35155b3e1433Swyllys } 35165b3e1433Swyllys 351799ebb4caSwyllys X509_free(xcert); 351899ebb4caSwyllys if (pkey) 351999ebb4caSwyllys EVP_PKEY_free(pkey); 352099ebb4caSwyllys } 35215b3e1433Swyllys } else if (numcerts == 0 && numkeys > 0) { 35225b3e1433Swyllys /* 35235b3e1433Swyllys * If only adding keys to the file. 35245b3e1433Swyllys */ 35255b3e1433Swyllys for (i = 0; i < numkeys; i++) { 35265b3e1433Swyllys EVP_PKEY *pkey = NULL; 35275b3e1433Swyllys 35285b3e1433Swyllys if (keylist[i].israw) 35295b3e1433Swyllys pkey = raw_key_to_pkey(&keylist[i]); 35305b3e1433Swyllys else 35315b3e1433Swyllys pkey = (EVP_PKEY *)keylist[i].keyp; 35325b3e1433Swyllys 35335b3e1433Swyllys if (pkey == NULL) 35345b3e1433Swyllys continue; 35355b3e1433Swyllys 35365b3e1433Swyllys key_authsafe = add_key_to_safe(pkey, cred, 35375b3e1433Swyllys NULL, 0, NULL, 0); 35385b3e1433Swyllys 35395b3e1433Swyllys if (key_authsafe == NULL) { 35405b3e1433Swyllys EVP_PKEY_free(pkey); 35415b3e1433Swyllys goto cleanup; 35425b3e1433Swyllys } 35435b3e1433Swyllys if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) { 35445b3e1433Swyllys EVP_PKEY_free(pkey); 35455b3e1433Swyllys goto cleanup; 35465b3e1433Swyllys } 35475b3e1433Swyllys } 35485b3e1433Swyllys } 35495b3e1433Swyllys p12_elem = PKCS12_init(NID_pkcs7_data); 35505b3e1433Swyllys if (p12_elem == NULL) { 35515b3e1433Swyllys goto cleanup; 355299ebb4caSwyllys } 355399ebb4caSwyllys 35545b3e1433Swyllys /* Put the PKCS#7 stack into the PKCS#12 element. */ 35555b3e1433Swyllys if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) { 35565b3e1433Swyllys goto cleanup; 35575b3e1433Swyllys } 35585b3e1433Swyllys 35595b3e1433Swyllys /* Set the integrity MAC on the PKCS#12 element. */ 35605b3e1433Swyllys if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen, 35615b3e1433Swyllys NULL, 0, PKCS12_DEFAULT_ITER, NULL)) { 35625b3e1433Swyllys goto cleanup; 35635b3e1433Swyllys } 35645b3e1433Swyllys 35655b3e1433Swyllys /* Write the PKCS#12 element to the export file. */ 35665b3e1433Swyllys if (!i2d_PKCS12_bio(bio, p12_elem)) { 35675b3e1433Swyllys goto cleanup; 35685b3e1433Swyllys } 35695b3e1433Swyllys PKCS12_free(p12_elem); 35705b3e1433Swyllys 357199ebb4caSwyllys cleanup: 35725b3e1433Swyllys /* Clear away the PKCS#7 stack, we're done with it. */ 35735b3e1433Swyllys if (authsafe_stack) 35745b3e1433Swyllys sk_PKCS7_pop_free(authsafe_stack, PKCS7_free); 357599ebb4caSwyllys 357699ebb4caSwyllys if (bio != NULL) 357799ebb4caSwyllys (void) BIO_free_all(bio); 357899ebb4caSwyllys 357999ebb4caSwyllys return (rv); 358099ebb4caSwyllys } 358199ebb4caSwyllys 358299ebb4caSwyllys KMF_RETURN 358330a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts, 358430a5e8faSwyllys KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist, 358530a5e8faSwyllys KMF_CREDENTIAL *p12cred, char *filename) 358630a5e8faSwyllys { 358730a5e8faSwyllys KMF_RETURN rv; 358830a5e8faSwyllys 358930a5e8faSwyllys if (certlist == NULL && keylist == NULL) 359030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 359130a5e8faSwyllys 35925b3e1433Swyllys rv = local_export_pk12(handle, p12cred, numcerts, certlist, 359330a5e8faSwyllys numkeys, keylist, filename); 359430a5e8faSwyllys 359530a5e8faSwyllys return (rv); 359630a5e8faSwyllys } 359730a5e8faSwyllys 359830a5e8faSwyllys KMF_RETURN 359930a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 360099ebb4caSwyllys { 360199ebb4caSwyllys KMF_RETURN rv; 360299ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 360399ebb4caSwyllys char *fullpath = NULL; 360430a5e8faSwyllys char *dirpath = NULL; 360530a5e8faSwyllys char *certfile = NULL; 360630a5e8faSwyllys char *keyfile = NULL; 360730a5e8faSwyllys char *filename = NULL; 360830a5e8faSwyllys KMF_CREDENTIAL *p12cred = NULL; 36095b3e1433Swyllys KMF_X509_DER_CERT certdata; 36105b3e1433Swyllys KMF_KEY_HANDLE key; 36115b3e1433Swyllys int gotkey = 0; 36125b3e1433Swyllys int gotcert = 0; 361330a5e8faSwyllys 361430a5e8faSwyllys if (handle == NULL) 361530a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 361699ebb4caSwyllys 361799ebb4caSwyllys /* 361899ebb4caSwyllys * First, find the certificate. 361999ebb4caSwyllys */ 362030a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 362130a5e8faSwyllys certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr); 362230a5e8faSwyllys if (certfile != NULL) { 362330a5e8faSwyllys fullpath = get_fullpath(dirpath, certfile); 362499ebb4caSwyllys if (fullpath == NULL) 362599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 362699ebb4caSwyllys 362799ebb4caSwyllys if (isdir(fullpath)) { 362899ebb4caSwyllys free(fullpath); 362999ebb4caSwyllys return (KMF_ERR_AMBIGUOUS_PATHNAME); 363099ebb4caSwyllys } 363199ebb4caSwyllys 36325b3e1433Swyllys (void) memset(&certdata, 0, sizeof (certdata)); 36335b3e1433Swyllys rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL, 36345b3e1433Swyllys fullpath, &certdata.certificate); 363599ebb4caSwyllys if (rv != KMF_OK) 363699ebb4caSwyllys goto end; 363730a5e8faSwyllys 36385b3e1433Swyllys gotcert++; 36395b3e1433Swyllys certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL; 364030a5e8faSwyllys free(fullpath); 364199ebb4caSwyllys } 364299ebb4caSwyllys 364399ebb4caSwyllys /* 364499ebb4caSwyllys * Now find the private key. 364599ebb4caSwyllys */ 364630a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 364730a5e8faSwyllys if (keyfile != NULL) { 364830a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 364999ebb4caSwyllys if (fullpath == NULL) 365099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 365199ebb4caSwyllys 365299ebb4caSwyllys if (isdir(fullpath)) { 365399ebb4caSwyllys free(fullpath); 365499ebb4caSwyllys return (KMF_ERR_AMBIGUOUS_PATHNAME); 365599ebb4caSwyllys } 365699ebb4caSwyllys 36575b3e1433Swyllys (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE)); 36585b3e1433Swyllys rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key); 36595b3e1433Swyllys if (rv != KMF_OK) 366099ebb4caSwyllys goto end; 36615b3e1433Swyllys gotkey++; 366299ebb4caSwyllys } 366399ebb4caSwyllys 366499ebb4caSwyllys /* 366599ebb4caSwyllys * Open the output file. 366699ebb4caSwyllys */ 366730a5e8faSwyllys filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist, 366830a5e8faSwyllys numattr); 366930a5e8faSwyllys if (filename == NULL) { 367030a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 367130a5e8faSwyllys goto end; 367230a5e8faSwyllys } 367330a5e8faSwyllys 367499ebb4caSwyllys /* Stick the key and the cert into a PKCS#12 file */ 367530a5e8faSwyllys p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr); 367630a5e8faSwyllys if (p12cred == NULL) { 367730a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 367830a5e8faSwyllys goto end; 367930a5e8faSwyllys } 368030a5e8faSwyllys 36815b3e1433Swyllys rv = local_export_pk12(handle, p12cred, 1, &certdata, 36825b3e1433Swyllys 1, &key, filename); 368399ebb4caSwyllys 368499ebb4caSwyllys end: 368599ebb4caSwyllys if (fullpath) 368699ebb4caSwyllys free(fullpath); 368799ebb4caSwyllys 36885b3e1433Swyllys if (gotcert) 36895b3e1433Swyllys kmf_free_kmf_cert(handle, &certdata); 36905b3e1433Swyllys if (gotkey) 36915b3e1433Swyllys kmf_free_kmf_key(handle, &key); 369299ebb4caSwyllys return (rv); 369399ebb4caSwyllys } 369499ebb4caSwyllys 369571593db2Swyllys /* 369671593db2Swyllys * Helper function to extract keys and certificates from 369771593db2Swyllys * a single PEM file. Typically the file should contain a 369871593db2Swyllys * private key and an associated public key wrapped in an x509 cert. 369971593db2Swyllys * However, the file may be just a list of X509 certs with no keys. 370071593db2Swyllys */ 370171593db2Swyllys static KMF_RETURN 370230a5e8faSwyllys extract_pem(KMF_HANDLE *kmfh, 370330a5e8faSwyllys char *issuer, char *subject, KMF_BIGINT *serial, 370402744e81Swyllys char *filename, CK_UTF8CHAR *pin, 370571593db2Swyllys CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs, 370671593db2Swyllys int *numcerts) 3707a2d4930dSDan OpenSolaris Anderson /* ARGSUSED6 */ 370871593db2Swyllys { 370971593db2Swyllys KMF_RETURN rv = KMF_OK; 371071593db2Swyllys FILE *fp; 371134acef67Swyllys STACK_OF(X509_INFO) *x509_info_stack = NULL; 371202744e81Swyllys int i, ncerts = 0, matchcerts = 0; 371371593db2Swyllys EVP_PKEY *pkey = NULL; 371471593db2Swyllys X509_INFO *info; 371571593db2Swyllys X509 *x; 37165b3e1433Swyllys X509_INFO **cert_infos = NULL; 371771593db2Swyllys KMF_DATA *certlist = NULL; 371871593db2Swyllys 371971593db2Swyllys if (priv_key) 372071593db2Swyllys *priv_key = NULL; 372171593db2Swyllys if (certs) 372271593db2Swyllys *certs = NULL; 372371593db2Swyllys fp = fopen(filename, "r"); 37245b3e1433Swyllys if (fp == NULL) 372571593db2Swyllys return (KMF_ERR_OPEN_FILE); 37265b3e1433Swyllys 372771593db2Swyllys x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin); 372871593db2Swyllys if (x509_info_stack == NULL) { 372971593db2Swyllys (void) fclose(fp); 373071593db2Swyllys return (KMF_ERR_ENCODING); 373171593db2Swyllys } 37325b3e1433Swyllys cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) * 37335b3e1433Swyllys sizeof (X509_INFO *)); 37345b3e1433Swyllys if (cert_infos == NULL) { 37355b3e1433Swyllys (void) fclose(fp); 37365b3e1433Swyllys rv = KMF_ERR_MEMORY; 37375b3e1433Swyllys goto err; 37385b3e1433Swyllys } 373971593db2Swyllys 37405b3e1433Swyllys for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) { 3741d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 374234acef67Swyllys cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i); 374371593db2Swyllys ncerts++; 374471593db2Swyllys } 374571593db2Swyllys 374671593db2Swyllys if (ncerts == 0) { 374771593db2Swyllys (void) fclose(fp); 374834acef67Swyllys rv = KMF_ERR_CERT_NOT_FOUND; 374934acef67Swyllys goto err; 375071593db2Swyllys } 375171593db2Swyllys 375271593db2Swyllys if (priv_key != NULL) { 375371593db2Swyllys rewind(fp); 375471593db2Swyllys pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin); 375571593db2Swyllys } 375671593db2Swyllys (void) fclose(fp); 375771593db2Swyllys 375871593db2Swyllys x = cert_infos[ncerts - 1]->x509; 375971593db2Swyllys /* 376071593db2Swyllys * Make sure the private key matchs the last cert in the file. 376171593db2Swyllys */ 376271593db2Swyllys if (pkey != NULL && !X509_check_private_key(x, pkey)) { 376371593db2Swyllys EVP_PKEY_free(pkey); 376434acef67Swyllys rv = KMF_ERR_KEY_MISMATCH; 376534acef67Swyllys goto err; 376671593db2Swyllys } 376771593db2Swyllys 3768a2d4930dSDan OpenSolaris Anderson certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA)); 376971593db2Swyllys if (certlist == NULL) { 377071593db2Swyllys if (pkey != NULL) 377171593db2Swyllys EVP_PKEY_free(pkey); 377234acef67Swyllys rv = KMF_ERR_MEMORY; 377334acef67Swyllys goto err; 377471593db2Swyllys } 377571593db2Swyllys 377671593db2Swyllys /* 377771593db2Swyllys * Convert all of the certs to DER format. 377871593db2Swyllys */ 377902744e81Swyllys matchcerts = 0; 378071593db2Swyllys for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) { 378102744e81Swyllys boolean_t match = FALSE; 378271593db2Swyllys info = cert_infos[ncerts - 1 - i]; 378371593db2Swyllys 378430a5e8faSwyllys rv = check_cert(info->x509, issuer, subject, serial, &match); 378502744e81Swyllys if (rv != KMF_OK || match != TRUE) { 378602744e81Swyllys rv = KMF_OK; 378702744e81Swyllys continue; 378802744e81Swyllys } 378902744e81Swyllys 379002744e81Swyllys rv = ssl_cert2KMFDATA(kmfh, info->x509, 379102744e81Swyllys &certlist[matchcerts++]); 379271593db2Swyllys 379371593db2Swyllys if (rv != KMF_OK) { 3794e65e5c2dSWyllys Ingersoll int j; 3795e65e5c2dSWyllys Ingersoll for (j = 0; j < matchcerts; j++) 3796e65e5c2dSWyllys Ingersoll kmf_free_data(&certlist[j]); 379771593db2Swyllys free(certlist); 379871593db2Swyllys certlist = NULL; 379902744e81Swyllys ncerts = matchcerts = 0; 380071593db2Swyllys } 380171593db2Swyllys } 380271593db2Swyllys 380371593db2Swyllys if (numcerts != NULL) 380402744e81Swyllys *numcerts = matchcerts; 3805a2d4930dSDan OpenSolaris Anderson 3806e65e5c2dSWyllys Ingersoll if (certs != NULL) 380771593db2Swyllys *certs = certlist; 3808e65e5c2dSWyllys Ingersoll else if (certlist != NULL) { 3809e65e5c2dSWyllys Ingersoll for (i = 0; i < ncerts; i++) 3810e65e5c2dSWyllys Ingersoll kmf_free_data(&certlist[i]); 3811a2d4930dSDan OpenSolaris Anderson free(certlist); 3812a2d4930dSDan OpenSolaris Anderson certlist = NULL; 3813a2d4930dSDan OpenSolaris Anderson } 381471593db2Swyllys 381571593db2Swyllys if (priv_key == NULL && pkey != NULL) 381671593db2Swyllys EVP_PKEY_free(pkey); 381771593db2Swyllys else if (priv_key != NULL && pkey != NULL) 381871593db2Swyllys *priv_key = pkey; 381971593db2Swyllys 382034acef67Swyllys err: 382134acef67Swyllys /* Cleanup the stack of X509 info records */ 382234acef67Swyllys for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) { 3823d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 382434acef67Swyllys info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i); 382534acef67Swyllys X509_INFO_free(info); 382634acef67Swyllys } 382734acef67Swyllys if (x509_info_stack) 382834acef67Swyllys sk_X509_INFO_free(x509_info_stack); 382934acef67Swyllys 38305b3e1433Swyllys if (cert_infos != NULL) 38315b3e1433Swyllys free(cert_infos); 38325b3e1433Swyllys 383371593db2Swyllys return (rv); 383471593db2Swyllys } 383571593db2Swyllys 38365b3e1433Swyllys static KMF_RETURN 3837300fdee2SAndy Fiddaman openssl_parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, char *pin, 38385b3e1433Swyllys STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs) 38395b3e1433Swyllys { 38405b3e1433Swyllys KMF_RETURN ret; 38415b3e1433Swyllys int i; 38425b3e1433Swyllys 38435b3e1433Swyllys for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { 3844d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 38455b3e1433Swyllys PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i); 38465b3e1433Swyllys ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0), 38475b3e1433Swyllys keys, certs); 38485b3e1433Swyllys 38495b3e1433Swyllys if (ret != KMF_OK) 38505b3e1433Swyllys return (ret); 38515b3e1433Swyllys } 38525b3e1433Swyllys 38535b3e1433Swyllys return (ret); 38545b3e1433Swyllys } 38555b3e1433Swyllys 38565b3e1433Swyllys static KMF_RETURN 38575b3e1433Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid) 38585b3e1433Swyllys { 38595b3e1433Swyllys X509_ATTRIBUTE *attr = NULL; 38605b3e1433Swyllys 38615b3e1433Swyllys if (pkey == NULL || attrib == NULL) 38625b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 38635b3e1433Swyllys 38645b3e1433Swyllys attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr); 38655b3e1433Swyllys if (attr != NULL) { 38665b3e1433Swyllys int i; 3867300fdee2SAndy Fiddaman 3868300fdee2SAndy Fiddaman if ((i = EVP_PKEY_get_attr_by_NID(pkey, nid, -1)) != -1) 3869300fdee2SAndy Fiddaman (void) EVP_PKEY_delete_attr(pkey, i); 3870300fdee2SAndy Fiddaman if (EVP_PKEY_add1_attr(pkey, attr) == 0) { 38715b3e1433Swyllys X509_ATTRIBUTE_free(attr); 38725b3e1433Swyllys return (KMF_ERR_MEMORY); 38735b3e1433Swyllys } 38745b3e1433Swyllys } else { 38755b3e1433Swyllys return (KMF_ERR_MEMORY); 38765b3e1433Swyllys } 38775b3e1433Swyllys 38785b3e1433Swyllys return (KMF_OK); 38795b3e1433Swyllys } 38805b3e1433Swyllys 38815b3e1433Swyllys static KMF_RETURN 38825b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen, 38835b3e1433Swyllys STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist) 38845b3e1433Swyllys { 38855b3e1433Swyllys KMF_RETURN ret = KMF_OK; 38865b3e1433Swyllys PKCS8_PRIV_KEY_INFO *p8 = NULL; 38875b3e1433Swyllys EVP_PKEY *pkey = NULL; 38885b3e1433Swyllys X509 *xcert = NULL; 3889300fdee2SAndy Fiddaman const ASN1_TYPE *keyid = NULL; 3890300fdee2SAndy Fiddaman const ASN1_TYPE *fname = NULL; 38915b3e1433Swyllys uchar_t *data = NULL; 38925b3e1433Swyllys 3893300fdee2SAndy Fiddaman keyid = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID); 3894300fdee2SAndy Fiddaman fname = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName); 38955b3e1433Swyllys 3896300fdee2SAndy Fiddaman switch (PKCS12_SAFEBAG_get_nid(bag)) { 38975b3e1433Swyllys case NID_keyBag: 38985b3e1433Swyllys if (keylist == NULL) 38995b3e1433Swyllys goto end; 3900300fdee2SAndy Fiddaman pkey = EVP_PKCS82PKEY( 3901300fdee2SAndy Fiddaman PKCS12_SAFEBAG_get0_p8inf(bag)); 39025b3e1433Swyllys if (pkey == NULL) 39035b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39045b3e1433Swyllys 39055b3e1433Swyllys break; 39065b3e1433Swyllys case NID_pkcs8ShroudedKeyBag: 39075b3e1433Swyllys if (keylist == NULL) 39085b3e1433Swyllys goto end; 3909300fdee2SAndy Fiddaman p8 = PKCS12_decrypt_skey(bag, pass, passlen); 39105b3e1433Swyllys if (p8 == NULL) 39115b3e1433Swyllys return (KMF_ERR_AUTH_FAILED); 39125b3e1433Swyllys pkey = EVP_PKCS82PKEY(p8); 39135b3e1433Swyllys PKCS8_PRIV_KEY_INFO_free(p8); 39145b3e1433Swyllys if (pkey == NULL) 39155b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39165b3e1433Swyllys break; 39175b3e1433Swyllys case NID_certBag: 39185b3e1433Swyllys if (certlist == NULL) 39195b3e1433Swyllys goto end; 3920300fdee2SAndy Fiddaman if (PKCS12_SAFEBAG_get_bag_nid(bag) != 3921300fdee2SAndy Fiddaman NID_x509Certificate) 39225b3e1433Swyllys return (KMF_ERR_PKCS12_FORMAT); 3923300fdee2SAndy Fiddaman xcert = PKCS12_SAFEBAG_get1_cert(bag); 39245b3e1433Swyllys if (xcert == NULL) { 39255b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39265b3e1433Swyllys goto end; 39275b3e1433Swyllys } 39285b3e1433Swyllys if (keyid != NULL) { 39295b3e1433Swyllys if (X509_keyid_set1(xcert, 39305b3e1433Swyllys keyid->value.octet_string->data, 39315b3e1433Swyllys keyid->value.octet_string->length) == 0) { 39325b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39335b3e1433Swyllys goto end; 39345b3e1433Swyllys } 39355b3e1433Swyllys } 39365b3e1433Swyllys if (fname != NULL) { 39375b3e1433Swyllys int len, r; 39385b3e1433Swyllys len = ASN1_STRING_to_UTF8(&data, 39395b3e1433Swyllys fname->value.asn1_string); 39405b3e1433Swyllys if (len > 0 && data != NULL) { 39415b3e1433Swyllys r = X509_alias_set1(xcert, data, len); 39425b3e1433Swyllys if (r == NULL) { 39435b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39445b3e1433Swyllys goto end; 39455b3e1433Swyllys } 39465b3e1433Swyllys } else { 39475b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39485b3e1433Swyllys goto end; 39495b3e1433Swyllys } 39505b3e1433Swyllys } 39515b3e1433Swyllys if (sk_X509_push(certlist, xcert) == 0) 39525b3e1433Swyllys ret = KMF_ERR_MEMORY; 39535b3e1433Swyllys else 39545b3e1433Swyllys xcert = NULL; 39555b3e1433Swyllys break; 39565b3e1433Swyllys case NID_safeContentsBag: 3957300fdee2SAndy Fiddaman return (openssl_parse_bags( 3958300fdee2SAndy Fiddaman PKCS12_SAFEBAG_get0_safes(bag), 3959300fdee2SAndy Fiddaman pass, keylist, certlist)); 39605b3e1433Swyllys default: 39615b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39625b3e1433Swyllys break; 39635b3e1433Swyllys } 39645b3e1433Swyllys 39655b3e1433Swyllys /* 39665b3e1433Swyllys * Set the ID and/or FriendlyName attributes on the key. 39675b3e1433Swyllys * If converting to PKCS11 objects, these can translate to CKA_ID 39685b3e1433Swyllys * and CKA_LABEL values. 39695b3e1433Swyllys */ 39705b3e1433Swyllys if (pkey != NULL && ret == KMF_OK) { 39715b3e1433Swyllys ASN1_TYPE *attr = NULL; 39725b3e1433Swyllys if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) { 39735b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) 39745b3e1433Swyllys return (KMF_ERR_MEMORY); 39755b3e1433Swyllys attr->value.octet_string = 39765b3e1433Swyllys ASN1_STRING_dup(keyid->value.octet_string); 39775b3e1433Swyllys attr->type = V_ASN1_OCTET_STRING; 39785b3e1433Swyllys attr->value.ptr = (char *)attr->value.octet_string; 39795b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_localKeyID); 39805b3e1433Swyllys OPENSSL_free(attr); 39815b3e1433Swyllys } 39825b3e1433Swyllys 39835b3e1433Swyllys if (ret == KMF_OK && fname != NULL && 39845b3e1433Swyllys fname->type == V_ASN1_BMPSTRING) { 39855b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) 39865b3e1433Swyllys return (KMF_ERR_MEMORY); 39875b3e1433Swyllys attr->value.bmpstring = 39885b3e1433Swyllys ASN1_STRING_dup(fname->value.bmpstring); 39895b3e1433Swyllys attr->type = V_ASN1_BMPSTRING; 39905b3e1433Swyllys attr->value.ptr = (char *)attr->value.bmpstring; 39915b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_friendlyName); 39925b3e1433Swyllys OPENSSL_free(attr); 39935b3e1433Swyllys } 39945b3e1433Swyllys 39955b3e1433Swyllys if (ret == KMF_OK && keylist != NULL && 39965b3e1433Swyllys sk_EVP_PKEY_push(keylist, pkey) == 0) 39975b3e1433Swyllys ret = KMF_ERR_MEMORY; 39985b3e1433Swyllys } 39995b3e1433Swyllys if (ret == KMF_OK && keylist != NULL) 40005b3e1433Swyllys pkey = NULL; 40015b3e1433Swyllys end: 40025b3e1433Swyllys if (pkey != NULL) 40035b3e1433Swyllys EVP_PKEY_free(pkey); 40045b3e1433Swyllys if (xcert != NULL) 40055b3e1433Swyllys X509_free(xcert); 40065b3e1433Swyllys if (data != NULL) 40075b3e1433Swyllys OPENSSL_free(data); 40085b3e1433Swyllys 40095b3e1433Swyllys return (ret); 40105b3e1433Swyllys } 40115b3e1433Swyllys 40125b3e1433Swyllys static KMF_RETURN 40135b3e1433Swyllys openssl_pkcs12_parse(PKCS12 *p12, char *pin, 40145b3e1433Swyllys STACK_OF(EVP_PKEY) *keys, 40155b3e1433Swyllys STACK_OF(X509) *certs, 40165b3e1433Swyllys STACK_OF(X509) *ca) 4017a2d4930dSDan OpenSolaris Anderson /* ARGSUSED3 */ 40185b3e1433Swyllys { 40195b3e1433Swyllys KMF_RETURN ret = KMF_OK; 40205b3e1433Swyllys STACK_OF(PKCS7) *asafes = NULL; 40215b3e1433Swyllys STACK_OF(PKCS12_SAFEBAG) *bags = NULL; 40225b3e1433Swyllys int i, bagnid; 40235b3e1433Swyllys PKCS7 *p7; 40245b3e1433Swyllys 40255b3e1433Swyllys if (p12 == NULL || (keys == NULL && certs == NULL)) 40265b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 40275b3e1433Swyllys 40285b3e1433Swyllys if (pin == NULL || *pin == NULL) { 40295b3e1433Swyllys if (PKCS12_verify_mac(p12, NULL, 0)) { 40305b3e1433Swyllys pin = NULL; 40315b3e1433Swyllys } else if (PKCS12_verify_mac(p12, "", 0)) { 40325b3e1433Swyllys pin = ""; 40335b3e1433Swyllys } else { 40345b3e1433Swyllys return (KMF_ERR_AUTH_FAILED); 40355b3e1433Swyllys } 40365b3e1433Swyllys } else if (!PKCS12_verify_mac(p12, pin, -1)) { 40375b3e1433Swyllys return (KMF_ERR_AUTH_FAILED); 40385b3e1433Swyllys } 40395b3e1433Swyllys 40405b3e1433Swyllys if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) 40415b3e1433Swyllys return (KMF_ERR_PKCS12_FORMAT); 40425b3e1433Swyllys 40435b3e1433Swyllys for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) { 40445b3e1433Swyllys bags = NULL; 4045d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 40465b3e1433Swyllys p7 = sk_PKCS7_value(asafes, i); 40475b3e1433Swyllys bagnid = OBJ_obj2nid(p7->type); 40485b3e1433Swyllys 40495b3e1433Swyllys if (bagnid == NID_pkcs7_data) { 40505b3e1433Swyllys bags = PKCS12_unpack_p7data(p7); 40515b3e1433Swyllys } else if (bagnid == NID_pkcs7_encrypted) { 40525b3e1433Swyllys bags = PKCS12_unpack_p7encdata(p7, pin, 40535b3e1433Swyllys (pin ? strlen(pin) : 0)); 40545b3e1433Swyllys } else { 40555b3e1433Swyllys continue; 40565b3e1433Swyllys } 40575b3e1433Swyllys if (bags == NULL) { 40585b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 40595b3e1433Swyllys goto out; 40605b3e1433Swyllys } 40615b3e1433Swyllys 40625b3e1433Swyllys if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK) 40635b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 40645b3e1433Swyllys 40655b3e1433Swyllys sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 40665b3e1433Swyllys } 40675b3e1433Swyllys out: 40685b3e1433Swyllys if (asafes != NULL) 40695b3e1433Swyllys sk_PKCS7_pop_free(asafes, PKCS7_free); 40705b3e1433Swyllys 40715b3e1433Swyllys return (ret); 40725b3e1433Swyllys } 40735b3e1433Swyllys 407499ebb4caSwyllys /* 407599ebb4caSwyllys * Helper function to decrypt and parse PKCS#12 import file. 407699ebb4caSwyllys */ 407799ebb4caSwyllys static KMF_RETURN 407899ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen, 40795b3e1433Swyllys STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs, 40805b3e1433Swyllys STACK_OF(X509) **ca) 4081a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */ 408299ebb4caSwyllys { 408399ebb4caSwyllys PKCS12 *pk12, *pk12_tmp; 40845b3e1433Swyllys STACK_OF(EVP_PKEY) *pkeylist = NULL; 40855b3e1433Swyllys STACK_OF(X509) *xcertlist = NULL; 40865b3e1433Swyllys STACK_OF(X509) *cacertlist = NULL; 408799ebb4caSwyllys 408899ebb4caSwyllys if ((pk12 = PKCS12_new()) == NULL) { 408999ebb4caSwyllys return (KMF_ERR_MEMORY); 409099ebb4caSwyllys } 409199ebb4caSwyllys 409299ebb4caSwyllys if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) { 409399ebb4caSwyllys /* This is ok; it seems to mean there is no more to read. */ 409499ebb4caSwyllys if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 && 409599ebb4caSwyllys ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG) 409699ebb4caSwyllys goto end_extract_pkcs12; 409799ebb4caSwyllys 409899ebb4caSwyllys PKCS12_free(pk12); 409999ebb4caSwyllys return (KMF_ERR_PKCS12_FORMAT); 410099ebb4caSwyllys } 410199ebb4caSwyllys pk12 = pk12_tmp; 410299ebb4caSwyllys 41035b3e1433Swyllys xcertlist = sk_X509_new_null(); 41045b3e1433Swyllys if (xcertlist == NULL) { 41055b3e1433Swyllys PKCS12_free(pk12); 41065b3e1433Swyllys return (KMF_ERR_MEMORY); 41075b3e1433Swyllys } 41085b3e1433Swyllys pkeylist = sk_EVP_PKEY_new_null(); 41095b3e1433Swyllys if (pkeylist == NULL) { 41105b3e1433Swyllys sk_X509_pop_free(xcertlist, X509_free); 41115b3e1433Swyllys PKCS12_free(pk12); 41125b3e1433Swyllys return (KMF_ERR_MEMORY); 41135b3e1433Swyllys } 41145b3e1433Swyllys 41155b3e1433Swyllys if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist, 41165b3e1433Swyllys cacertlist) != KMF_OK) { 41175b3e1433Swyllys sk_X509_pop_free(xcertlist, X509_free); 41185b3e1433Swyllys sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free); 411999ebb4caSwyllys PKCS12_free(pk12); 412099ebb4caSwyllys return (KMF_ERR_PKCS12_FORMAT); 412199ebb4caSwyllys } 412299ebb4caSwyllys 41235b3e1433Swyllys if (priv_key && pkeylist) 41245b3e1433Swyllys *priv_key = pkeylist; 41255b3e1433Swyllys else if (pkeylist) 41265b3e1433Swyllys sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free); 41275b3e1433Swyllys if (certs && xcertlist) 41285b3e1433Swyllys *certs = xcertlist; 41295b3e1433Swyllys else if (xcertlist) 41305b3e1433Swyllys sk_X509_pop_free(xcertlist, X509_free); 41315b3e1433Swyllys if (ca && cacertlist) 41325b3e1433Swyllys *ca = cacertlist; 41335b3e1433Swyllys else if (cacertlist) 41345b3e1433Swyllys sk_X509_pop_free(cacertlist, X509_free); 413599ebb4caSwyllys 41365b3e1433Swyllys end_extract_pkcs12: 413799ebb4caSwyllys 413899ebb4caSwyllys PKCS12_free(pk12); 413999ebb4caSwyllys return (KMF_OK); 414099ebb4caSwyllys } 414199ebb4caSwyllys 414299ebb4caSwyllys static KMF_RETURN 414399ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to) 414499ebb4caSwyllys { 414599ebb4caSwyllys KMF_RETURN rv = KMF_OK; 414699ebb4caSwyllys uint32_t sz; 414799ebb4caSwyllys 414899ebb4caSwyllys sz = BN_num_bytes(from); 414999ebb4caSwyllys to->val = (uchar_t *)malloc(sz); 415099ebb4caSwyllys if (to->val == NULL) 415199ebb4caSwyllys return (KMF_ERR_MEMORY); 415299ebb4caSwyllys 415399ebb4caSwyllys if ((to->len = BN_bn2bin(from, to->val)) != sz) { 415499ebb4caSwyllys free(to->val); 415599ebb4caSwyllys to->val = NULL; 415699ebb4caSwyllys to->len = 0; 415799ebb4caSwyllys rv = KMF_ERR_MEMORY; 415899ebb4caSwyllys } 415999ebb4caSwyllys 416099ebb4caSwyllys return (rv); 416199ebb4caSwyllys } 416299ebb4caSwyllys 416399ebb4caSwyllys static KMF_RETURN 416499ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key) 416599ebb4caSwyllys { 416699ebb4caSwyllys KMF_RETURN rv; 416799ebb4caSwyllys KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa; 416899ebb4caSwyllys 4169300fdee2SAndy Fiddaman const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmpq, *iqmp; 4170300fdee2SAndy Fiddaman 4171300fdee2SAndy Fiddaman RSA_get0_key(rsa, &n, &e, &d); 4172300fdee2SAndy Fiddaman RSA_get0_factors(rsa, &p, &q); 4173300fdee2SAndy Fiddaman RSA_get0_crt_params(rsa, &dmp1, &dmpq, &iqmp); 4174300fdee2SAndy Fiddaman 417599ebb4caSwyllys (void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY)); 4176300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)n, &kmfkey->mod)) != KMF_OK) 417799ebb4caSwyllys goto cleanup; 417899ebb4caSwyllys 4179300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)e, &kmfkey->pubexp)) != KMF_OK) 418099ebb4caSwyllys goto cleanup; 418199ebb4caSwyllys 4182300fdee2SAndy Fiddaman if (d != NULL) 4183300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)d, &kmfkey->priexp)) != KMF_OK) 418499ebb4caSwyllys goto cleanup; 418599ebb4caSwyllys 4186300fdee2SAndy Fiddaman if (p != NULL) 4187300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime1)) != KMF_OK) 418899ebb4caSwyllys goto cleanup; 418999ebb4caSwyllys 4190300fdee2SAndy Fiddaman if (q != NULL) 4191300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->prime2)) != KMF_OK) 419299ebb4caSwyllys goto cleanup; 419399ebb4caSwyllys 4194300fdee2SAndy Fiddaman if (dmp1 != NULL) 4195300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)dmp1, &kmfkey->exp1)) != KMF_OK) 419699ebb4caSwyllys goto cleanup; 419799ebb4caSwyllys 4198300fdee2SAndy Fiddaman if (dmpq != NULL) 4199300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)dmpq, &kmfkey->exp2)) != KMF_OK) 420099ebb4caSwyllys goto cleanup; 420199ebb4caSwyllys 4202300fdee2SAndy Fiddaman if (iqmp != NULL) 4203300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)iqmp, &kmfkey->coef)) != KMF_OK) 420499ebb4caSwyllys goto cleanup; 420599ebb4caSwyllys cleanup: 420699ebb4caSwyllys if (rv != KMF_OK) 420730a5e8faSwyllys kmf_free_raw_key(key); 420899ebb4caSwyllys else 420999ebb4caSwyllys key->keytype = KMF_RSA; 421099ebb4caSwyllys 421199ebb4caSwyllys /* 421299ebb4caSwyllys * Free the reference to this key, SSL will not actually free 421399ebb4caSwyllys * the memory until the refcount == 0, so this is safe. 421499ebb4caSwyllys */ 421599ebb4caSwyllys RSA_free(rsa); 421699ebb4caSwyllys 421799ebb4caSwyllys return (rv); 421899ebb4caSwyllys } 421999ebb4caSwyllys 422099ebb4caSwyllys static KMF_RETURN 422199ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key) 422299ebb4caSwyllys { 422399ebb4caSwyllys KMF_RETURN rv; 422499ebb4caSwyllys KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa; 4225300fdee2SAndy Fiddaman const BIGNUM *p, *q, *g, *priv_key; 4226300fdee2SAndy Fiddaman 4227300fdee2SAndy Fiddaman DSA_get0_pqg(dsa, &p, &q, &g); 4228300fdee2SAndy Fiddaman DSA_get0_key(dsa, NULL, &priv_key); 422999ebb4caSwyllys 423099ebb4caSwyllys (void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY)); 4231300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime)) != KMF_OK) 423299ebb4caSwyllys goto cleanup; 423399ebb4caSwyllys 4234300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->subprime)) != KMF_OK) 423599ebb4caSwyllys goto cleanup; 423699ebb4caSwyllys 4237300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)g, &kmfkey->base)) != KMF_OK) 423899ebb4caSwyllys goto cleanup; 423999ebb4caSwyllys 4240300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)priv_key, &kmfkey->value)) != KMF_OK) 424199ebb4caSwyllys goto cleanup; 424299ebb4caSwyllys 424399ebb4caSwyllys cleanup: 424499ebb4caSwyllys if (rv != KMF_OK) 424530a5e8faSwyllys kmf_free_raw_key(key); 424699ebb4caSwyllys else 424799ebb4caSwyllys key->keytype = KMF_DSA; 424899ebb4caSwyllys 424999ebb4caSwyllys /* 425099ebb4caSwyllys * Free the reference to this key, SSL will not actually free 425199ebb4caSwyllys * the memory until the refcount == 0, so this is safe. 425299ebb4caSwyllys */ 425399ebb4caSwyllys DSA_free(dsa); 425499ebb4caSwyllys 425599ebb4caSwyllys return (rv); 425699ebb4caSwyllys } 425799ebb4caSwyllys 425899ebb4caSwyllys static KMF_RETURN 425999ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert, 42605b3e1433Swyllys KMF_X509_DER_CERT **certlist, int *ncerts) 426199ebb4caSwyllys { 426299ebb4caSwyllys KMF_RETURN rv = KMF_OK; 42635b3e1433Swyllys KMF_X509_DER_CERT *list = (*certlist); 42645b3e1433Swyllys KMF_X509_DER_CERT cert; 426599ebb4caSwyllys int n = (*ncerts); 426699ebb4caSwyllys 426799ebb4caSwyllys if (list == NULL) { 42685b3e1433Swyllys list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT)); 426999ebb4caSwyllys } else { 42705b3e1433Swyllys list = (KMF_X509_DER_CERT *)realloc(list, 42715b3e1433Swyllys sizeof (KMF_X509_DER_CERT) * (n + 1)); 427299ebb4caSwyllys } 427399ebb4caSwyllys 427499ebb4caSwyllys if (list == NULL) 427599ebb4caSwyllys return (KMF_ERR_MEMORY); 427699ebb4caSwyllys 42775b3e1433Swyllys (void) memset(&cert, 0, sizeof (cert)); 42785b3e1433Swyllys rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate); 427999ebb4caSwyllys if (rv == KMF_OK) { 42805b3e1433Swyllys int len = 0; 42815b3e1433Swyllys /* Get the alias name for the cert if there is one */ 42825b3e1433Swyllys char *a = (char *)X509_alias_get0(sslcert, &len); 42835b3e1433Swyllys if (a != NULL) 42845b3e1433Swyllys cert.kmf_private.label = strdup(a); 42855b3e1433Swyllys cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL; 42865b3e1433Swyllys 428799ebb4caSwyllys list[n] = cert; 428899ebb4caSwyllys (*ncerts) = n + 1; 428999ebb4caSwyllys 429099ebb4caSwyllys *certlist = list; 429199ebb4caSwyllys } else { 429299ebb4caSwyllys free(list); 429399ebb4caSwyllys } 429499ebb4caSwyllys 429599ebb4caSwyllys return (rv); 429699ebb4caSwyllys } 429799ebb4caSwyllys 429899ebb4caSwyllys static KMF_RETURN 429999ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist, 430099ebb4caSwyllys KMF_RAW_KEY_DATA *newkey, int *nkeys) 430199ebb4caSwyllys { 430299ebb4caSwyllys KMF_RAW_KEY_DATA *list = (*keylist); 430399ebb4caSwyllys int n = (*nkeys); 430499ebb4caSwyllys 430599ebb4caSwyllys if (list == NULL) { 430699ebb4caSwyllys list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA)); 430799ebb4caSwyllys } else { 430899ebb4caSwyllys list = (KMF_RAW_KEY_DATA *)realloc(list, 430999ebb4caSwyllys sizeof (KMF_RAW_KEY_DATA) * (n + 1)); 431099ebb4caSwyllys } 431199ebb4caSwyllys 431299ebb4caSwyllys if (list == NULL) 431399ebb4caSwyllys return (KMF_ERR_MEMORY); 431499ebb4caSwyllys 431599ebb4caSwyllys list[n] = *newkey; 431699ebb4caSwyllys (*nkeys) = n + 1; 431799ebb4caSwyllys 431899ebb4caSwyllys *keylist = list; 431999ebb4caSwyllys 432099ebb4caSwyllys return (KMF_OK); 432199ebb4caSwyllys } 432299ebb4caSwyllys 432330a5e8faSwyllys static KMF_RETURN 432430a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key) 432530a5e8faSwyllys { 432630a5e8faSwyllys KMF_RETURN rv = KMF_OK; 43275b3e1433Swyllys X509_ATTRIBUTE *attr; 4328300fdee2SAndy Fiddaman RSA *rsa; 4329300fdee2SAndy Fiddaman DSA *dsa; 4330300fdee2SAndy Fiddaman int loc; 433130a5e8faSwyllys 433230a5e8faSwyllys if (pkey == NULL || key == NULL) 433330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 433430a5e8faSwyllys /* Convert SSL key to raw key */ 4335300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get1_RSA(pkey)) != NULL) { 4336300fdee2SAndy Fiddaman rv = exportRawRSAKey(rsa, key); 433730a5e8faSwyllys if (rv != KMF_OK) 433830a5e8faSwyllys return (rv); 4339300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get1_DSA(pkey)) != NULL) { 4340300fdee2SAndy Fiddaman rv = exportRawDSAKey(dsa, key); 434130a5e8faSwyllys if (rv != KMF_OK) 434230a5e8faSwyllys return (rv); 4343300fdee2SAndy Fiddaman } else 434430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 4345300fdee2SAndy Fiddaman 43465b3e1433Swyllys /* 43475b3e1433Swyllys * If friendlyName, add it to record. 43485b3e1433Swyllys */ 4349300fdee2SAndy Fiddaman 4350300fdee2SAndy Fiddaman if ((loc = EVP_PKEY_get_attr_by_NID(pkey, 4351300fdee2SAndy Fiddaman NID_friendlyName, -1)) != -1 && 4352300fdee2SAndy Fiddaman (attr = EVP_PKEY_get_attr(pkey, loc))) { 43535b3e1433Swyllys ASN1_TYPE *ty = NULL; 4354300fdee2SAndy Fiddaman int numattr = X509_ATTRIBUTE_count(attr); 4355300fdee2SAndy Fiddaman if (numattr > 0) { 4356300fdee2SAndy Fiddaman ty = X509_ATTRIBUTE_get0_type(attr, 0); 43575b3e1433Swyllys } 43585b3e1433Swyllys if (ty != NULL) { 435970f9559bSTheo Schlossnagle key->label = OPENSSL_uni2asc(ty->value.bmpstring->data, 436070f9559bSTheo Schlossnagle ty->value.bmpstring->length); 43615b3e1433Swyllys } 43625b3e1433Swyllys } else { 43635b3e1433Swyllys key->label = NULL; 43645b3e1433Swyllys } 43655b3e1433Swyllys 43665b3e1433Swyllys /* 43675b3e1433Swyllys * If KeyID, add it to record as a KMF_DATA object. 43685b3e1433Swyllys */ 4369300fdee2SAndy Fiddaman if ((loc = EVP_PKEY_get_attr_by_NID(pkey, 4370300fdee2SAndy Fiddaman NID_localKeyID, -1)) != -1 && 4371300fdee2SAndy Fiddaman (attr = EVP_PKEY_get_attr(pkey, loc)) != NULL) { 43725b3e1433Swyllys ASN1_TYPE *ty = NULL; 4373300fdee2SAndy Fiddaman int numattr = X509_ATTRIBUTE_count(attr); 4374300fdee2SAndy Fiddaman if (numattr > 0) 4375300fdee2SAndy Fiddaman ty = X509_ATTRIBUTE_get0_type(attr, 0); 43765b3e1433Swyllys key->id.Data = (uchar_t *)malloc( 43775b3e1433Swyllys ty->value.octet_string->length); 43785b3e1433Swyllys if (key->id.Data == NULL) 43795b3e1433Swyllys return (KMF_ERR_MEMORY); 43805b3e1433Swyllys (void) memcpy(key->id.Data, ty->value.octet_string->data, 43815b3e1433Swyllys ty->value.octet_string->length); 43825b3e1433Swyllys key->id.Length = ty->value.octet_string->length; 43835b3e1433Swyllys } else { 43845b3e1433Swyllys (void) memset(&key->id, 0, sizeof (KMF_DATA)); 43855b3e1433Swyllys } 438630a5e8faSwyllys 438730a5e8faSwyllys return (rv); 438830a5e8faSwyllys } 438999ebb4caSwyllys 439099ebb4caSwyllys static KMF_RETURN 439199ebb4caSwyllys convertPK12Objects( 439299ebb4caSwyllys KMF_HANDLE *kmfh, 43935b3e1433Swyllys STACK_OF(EVP_PKEY) *sslkeys, 43945b3e1433Swyllys STACK_OF(X509) *sslcert, 43955b3e1433Swyllys STACK_OF(X509) *sslcacerts, 439699ebb4caSwyllys KMF_RAW_KEY_DATA **keylist, int *nkeys, 43975b3e1433Swyllys KMF_X509_DER_CERT **certlist, int *ncerts) 439899ebb4caSwyllys { 439999ebb4caSwyllys KMF_RETURN rv = KMF_OK; 440099ebb4caSwyllys KMF_RAW_KEY_DATA key; 440199ebb4caSwyllys int i; 440299ebb4caSwyllys 44035b3e1433Swyllys for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) { 4404d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 44055b3e1433Swyllys EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i); 44065b3e1433Swyllys rv = convertToRawKey(pkey, &key); 440730a5e8faSwyllys if (rv == KMF_OK) 440899ebb4caSwyllys rv = add_key_to_list(keylist, &key, nkeys); 440930a5e8faSwyllys 441099ebb4caSwyllys if (rv != KMF_OK) 441199ebb4caSwyllys return (rv); 441299ebb4caSwyllys } 441399ebb4caSwyllys 441499ebb4caSwyllys /* Now add the certificate to the certlist */ 44155b3e1433Swyllys for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) { 4416d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 44175b3e1433Swyllys X509 *cert = sk_X509_value(sslcert, i); 44185b3e1433Swyllys rv = add_cert_to_list(kmfh, cert, certlist, ncerts); 441999ebb4caSwyllys if (rv != KMF_OK) 442099ebb4caSwyllys return (rv); 442199ebb4caSwyllys } 442299ebb4caSwyllys 442399ebb4caSwyllys /* Also add any included CA certs to the list */ 442471593db2Swyllys for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) { 442599ebb4caSwyllys X509 *c; 442699ebb4caSwyllys /* 442799ebb4caSwyllys * sk_X509_value() is macro that embeds a cast to (X509 *). 442899ebb4caSwyllys * Here it translates into ((X509 *)sk_value((ca), (i))). 442999ebb4caSwyllys * Lint is complaining about the embedded casting, and 443099ebb4caSwyllys * to fix it, you need to fix openssl header files. 443199ebb4caSwyllys */ 4432d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 443399ebb4caSwyllys c = sk_X509_value(sslcacerts, i); 443499ebb4caSwyllys 443599ebb4caSwyllys /* Now add the ca cert to the certlist */ 443699ebb4caSwyllys rv = add_cert_to_list(kmfh, c, certlist, ncerts); 443799ebb4caSwyllys if (rv != KMF_OK) 443899ebb4caSwyllys return (rv); 443999ebb4caSwyllys } 444099ebb4caSwyllys return (rv); 444199ebb4caSwyllys } 444299ebb4caSwyllys 444399ebb4caSwyllys KMF_RETURN 444430a5e8faSwyllys openssl_import_objects(KMF_HANDLE *kmfh, 444599ebb4caSwyllys char *filename, KMF_CREDENTIAL *cred, 44465b3e1433Swyllys KMF_X509_DER_CERT **certlist, int *ncerts, 444799ebb4caSwyllys KMF_RAW_KEY_DATA **keylist, int *nkeys) 444899ebb4caSwyllys { 444999ebb4caSwyllys KMF_RETURN rv = KMF_OK; 445030a5e8faSwyllys KMF_ENCODE_FORMAT format; 445130a5e8faSwyllys BIO *bio = NULL; 44525b3e1433Swyllys STACK_OF(EVP_PKEY) *privkeys = NULL; 44535b3e1433Swyllys STACK_OF(X509) *certs = NULL; 445499ebb4caSwyllys STACK_OF(X509) *cacerts = NULL; 445599ebb4caSwyllys 445630a5e8faSwyllys /* 445730a5e8faSwyllys * auto-detect the file format, regardless of what 445830a5e8faSwyllys * the 'format' parameters in the params say. 445930a5e8faSwyllys */ 446030a5e8faSwyllys rv = kmf_get_file_format(filename, &format); 446130a5e8faSwyllys if (rv != KMF_OK) { 446230a5e8faSwyllys return (rv); 446330a5e8faSwyllys } 446430a5e8faSwyllys 446530a5e8faSwyllys /* This function only works for PEM or PKCS#12 files */ 446630a5e8faSwyllys if (format != KMF_FORMAT_PEM && 446730a5e8faSwyllys format != KMF_FORMAT_PEM_KEYPAIR && 446830a5e8faSwyllys format != KMF_FORMAT_PKCS12) 446930a5e8faSwyllys return (KMF_ERR_ENCODING); 447030a5e8faSwyllys 447130a5e8faSwyllys *certlist = NULL; 447230a5e8faSwyllys *keylist = NULL; 447330a5e8faSwyllys *ncerts = 0; 447430a5e8faSwyllys *nkeys = 0; 447530a5e8faSwyllys 447630a5e8faSwyllys if (format == KMF_FORMAT_PKCS12) { 447799ebb4caSwyllys bio = BIO_new_file(filename, "rb"); 447899ebb4caSwyllys if (bio == NULL) { 447999ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 448099ebb4caSwyllys rv = KMF_ERR_OPEN_FILE; 448199ebb4caSwyllys goto end; 448299ebb4caSwyllys } 448399ebb4caSwyllys 448434acef67Swyllys rv = extract_pkcs12(bio, (uchar_t *)cred->cred, 44855b3e1433Swyllys (uint32_t)cred->credlen, &privkeys, &certs, &cacerts); 448699ebb4caSwyllys 448799ebb4caSwyllys if (rv == KMF_OK) 448899ebb4caSwyllys /* Convert keys and certs to exportable format */ 44895b3e1433Swyllys rv = convertPK12Objects(kmfh, privkeys, certs, cacerts, 449099ebb4caSwyllys keylist, nkeys, certlist, ncerts); 449130a5e8faSwyllys } else { 44925b3e1433Swyllys EVP_PKEY *pkey; 44935b3e1433Swyllys KMF_DATA *certdata = NULL; 44945b3e1433Swyllys KMF_X509_DER_CERT *kmfcerts = NULL; 44955b3e1433Swyllys int i; 449630a5e8faSwyllys rv = extract_pem(kmfh, NULL, NULL, NULL, filename, 449734acef67Swyllys (uchar_t *)cred->cred, (uint32_t)cred->credlen, 44985b3e1433Swyllys &pkey, &certdata, ncerts); 449971593db2Swyllys 450071593db2Swyllys /* Reached end of import file? */ 45015b3e1433Swyllys if (rv == KMF_OK && pkey != NULL) { 45025b3e1433Swyllys privkeys = sk_EVP_PKEY_new_null(); 45035b3e1433Swyllys if (privkeys == NULL) { 45045b3e1433Swyllys rv = KMF_ERR_MEMORY; 45055b3e1433Swyllys goto end; 45065b3e1433Swyllys } 45075b3e1433Swyllys (void) sk_EVP_PKEY_push(privkeys, pkey); 45085b3e1433Swyllys /* convert the certificate list here */ 45095b3e1433Swyllys if (*ncerts > 0 && certlist != NULL) { 4510e65e5c2dSWyllys Ingersoll kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts, 45115b3e1433Swyllys sizeof (KMF_X509_DER_CERT)); 45125b3e1433Swyllys if (kmfcerts == NULL) { 45135b3e1433Swyllys rv = KMF_ERR_MEMORY; 45145b3e1433Swyllys goto end; 45155b3e1433Swyllys } 45165b3e1433Swyllys for (i = 0; i < *ncerts; i++) { 45175b3e1433Swyllys kmfcerts[i].certificate = certdata[i]; 45185b3e1433Swyllys kmfcerts[i].kmf_private.keystore_type = 45195b3e1433Swyllys KMF_KEYSTORE_OPENSSL; 45205b3e1433Swyllys } 45215b3e1433Swyllys *certlist = kmfcerts; 45225b3e1433Swyllys } 45235b3e1433Swyllys /* 45245b3e1433Swyllys * Convert keys to exportable format, the certs 45255b3e1433Swyllys * are already OK. 45265b3e1433Swyllys */ 45275b3e1433Swyllys rv = convertPK12Objects(kmfh, privkeys, NULL, NULL, 452871593db2Swyllys keylist, nkeys, NULL, NULL); 452930a5e8faSwyllys } 45305b3e1433Swyllys } 453171593db2Swyllys end: 453230a5e8faSwyllys if (bio != NULL) 453399ebb4caSwyllys (void) BIO_free(bio); 453499ebb4caSwyllys 45355b3e1433Swyllys if (privkeys) 45365b3e1433Swyllys sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free); 45375b3e1433Swyllys if (certs) 45385b3e1433Swyllys sk_X509_pop_free(certs, X509_free); 453930a5e8faSwyllys if (cacerts) 45405b3e1433Swyllys sk_X509_pop_free(cacerts, X509_free); 454130a5e8faSwyllys 454299ebb4caSwyllys return (rv); 454399ebb4caSwyllys } 454499ebb4caSwyllys 454599ebb4caSwyllys static KMF_RETURN 454699ebb4caSwyllys create_deskey(DES_cblock **deskey) 454799ebb4caSwyllys { 454899ebb4caSwyllys DES_cblock *key; 454999ebb4caSwyllys 455099ebb4caSwyllys key = (DES_cblock *) malloc(sizeof (DES_cblock)); 455199ebb4caSwyllys if (key == NULL) { 455299ebb4caSwyllys return (KMF_ERR_MEMORY); 455399ebb4caSwyllys } 455499ebb4caSwyllys 455599ebb4caSwyllys if (DES_random_key(key) == 0) { 455699ebb4caSwyllys free(key); 455799ebb4caSwyllys return (KMF_ERR_KEYGEN_FAILED); 455899ebb4caSwyllys } 455999ebb4caSwyllys 456099ebb4caSwyllys *deskey = key; 456199ebb4caSwyllys return (KMF_OK); 456299ebb4caSwyllys } 456399ebb4caSwyllys 456499ebb4caSwyllys #define KEYGEN_RETRY 3 456599ebb4caSwyllys #define DES3_KEY_SIZE 24 456699ebb4caSwyllys 456799ebb4caSwyllys static KMF_RETURN 456899ebb4caSwyllys create_des3key(unsigned char **des3key) 456999ebb4caSwyllys { 457099ebb4caSwyllys KMF_RETURN ret = KMF_OK; 457199ebb4caSwyllys DES_cblock *deskey1 = NULL; 457299ebb4caSwyllys DES_cblock *deskey2 = NULL; 457399ebb4caSwyllys DES_cblock *deskey3 = NULL; 457499ebb4caSwyllys unsigned char *newkey = NULL; 457599ebb4caSwyllys int retry; 457699ebb4caSwyllys 457799ebb4caSwyllys if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) { 457899ebb4caSwyllys return (KMF_ERR_MEMORY); 457999ebb4caSwyllys } 458099ebb4caSwyllys 458199ebb4caSwyllys /* create the 1st DES key */ 458299ebb4caSwyllys if ((ret = create_deskey(&deskey1)) != KMF_OK) { 458399ebb4caSwyllys goto out; 458499ebb4caSwyllys } 458599ebb4caSwyllys 458699ebb4caSwyllys /* 458799ebb4caSwyllys * Create the 2nd DES key and make sure its value is different 458899ebb4caSwyllys * from the 1st DES key. 458999ebb4caSwyllys */ 459099ebb4caSwyllys retry = 0; 459199ebb4caSwyllys do { 459299ebb4caSwyllys if (deskey2 != NULL) { 459399ebb4caSwyllys free(deskey2); 459499ebb4caSwyllys deskey2 = NULL; 459599ebb4caSwyllys } 459699ebb4caSwyllys 459799ebb4caSwyllys if ((ret = create_deskey(&deskey2)) != KMF_OK) { 459899ebb4caSwyllys goto out; 459999ebb4caSwyllys } 460099ebb4caSwyllys 460199ebb4caSwyllys if (memcmp((const void *) deskey1, (const void *) deskey2, 8) 460299ebb4caSwyllys == 0) { 460399ebb4caSwyllys ret = KMF_ERR_KEYGEN_FAILED; 460499ebb4caSwyllys retry++; 460599ebb4caSwyllys } 460699ebb4caSwyllys } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY); 460799ebb4caSwyllys 460899ebb4caSwyllys if (ret != KMF_OK) { 460999ebb4caSwyllys goto out; 461099ebb4caSwyllys } 461199ebb4caSwyllys 461299ebb4caSwyllys /* 461399ebb4caSwyllys * Create the 3rd DES key and make sure its value is different 461499ebb4caSwyllys * from the 2nd DES key. 461599ebb4caSwyllys */ 461699ebb4caSwyllys retry = 0; 461799ebb4caSwyllys do { 461899ebb4caSwyllys if (deskey3 != NULL) { 461999ebb4caSwyllys free(deskey3); 462099ebb4caSwyllys deskey3 = NULL; 462199ebb4caSwyllys } 462299ebb4caSwyllys 462399ebb4caSwyllys if ((ret = create_deskey(&deskey3)) != KMF_OK) { 462499ebb4caSwyllys goto out; 462599ebb4caSwyllys } 462699ebb4caSwyllys 462799ebb4caSwyllys if (memcmp((const void *)deskey2, (const void *)deskey3, 8) 462899ebb4caSwyllys == 0) { 462999ebb4caSwyllys ret = KMF_ERR_KEYGEN_FAILED; 463099ebb4caSwyllys retry++; 463199ebb4caSwyllys } 463299ebb4caSwyllys } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY); 463399ebb4caSwyllys 463499ebb4caSwyllys if (ret != KMF_OK) { 463599ebb4caSwyllys goto out; 463699ebb4caSwyllys } 463799ebb4caSwyllys 463899ebb4caSwyllys /* Concatenate 3 DES keys into a DES3 key */ 463999ebb4caSwyllys (void) memcpy((void *)newkey, (const void *)deskey1, 8); 464099ebb4caSwyllys (void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8); 464199ebb4caSwyllys (void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8); 464299ebb4caSwyllys *des3key = newkey; 464399ebb4caSwyllys 464499ebb4caSwyllys out: 464599ebb4caSwyllys if (deskey1 != NULL) 464699ebb4caSwyllys free(deskey1); 464799ebb4caSwyllys 464899ebb4caSwyllys if (deskey2 != NULL) 464999ebb4caSwyllys free(deskey2); 465099ebb4caSwyllys 465199ebb4caSwyllys if (deskey3 != NULL) 465299ebb4caSwyllys free(deskey3); 465399ebb4caSwyllys 465499ebb4caSwyllys if (ret != KMF_OK && newkey != NULL) 465599ebb4caSwyllys free(newkey); 465699ebb4caSwyllys 465799ebb4caSwyllys return (ret); 465899ebb4caSwyllys } 465999ebb4caSwyllys 466099ebb4caSwyllys KMF_RETURN 466130a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle, 466230a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 466399ebb4caSwyllys { 466499ebb4caSwyllys KMF_RETURN ret = KMF_OK; 466599ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 466699ebb4caSwyllys char *fullpath = NULL; 466799ebb4caSwyllys KMF_RAW_SYM_KEY *rkey = NULL; 466899ebb4caSwyllys DES_cblock *deskey = NULL; 466999ebb4caSwyllys unsigned char *des3key = NULL; 467099ebb4caSwyllys unsigned char *random = NULL; 467199ebb4caSwyllys int fd = -1; 467230a5e8faSwyllys KMF_KEY_HANDLE *symkey; 467330a5e8faSwyllys KMF_KEY_ALG keytype; 467430a5e8faSwyllys uint32_t keylen; 467530a5e8faSwyllys uint32_t keylen_size = sizeof (keylen); 467630a5e8faSwyllys char *dirpath; 467730a5e8faSwyllys char *keyfile; 467899ebb4caSwyllys 467999ebb4caSwyllys if (kmfh == NULL) 468099ebb4caSwyllys return (KMF_ERR_UNINITIALIZED); 468199ebb4caSwyllys 468230a5e8faSwyllys symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 468330a5e8faSwyllys if (symkey == NULL) 468499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 468599ebb4caSwyllys 468630a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 468730a5e8faSwyllys 468830a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 468930a5e8faSwyllys if (keyfile == NULL) 469030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 469130a5e8faSwyllys 469230a5e8faSwyllys ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, 469330a5e8faSwyllys (void *)&keytype, NULL); 469430a5e8faSwyllys if (ret != KMF_OK) 469530a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 469630a5e8faSwyllys 469730a5e8faSwyllys ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, 469830a5e8faSwyllys &keylen, &keylen_size); 469930a5e8faSwyllys if (ret == KMF_ERR_ATTR_NOT_FOUND && 470030a5e8faSwyllys (keytype == KMF_DES || keytype == KMF_DES3)) 470130a5e8faSwyllys /* keylength is not required for DES and 3DES */ 470230a5e8faSwyllys ret = KMF_OK; 470330a5e8faSwyllys if (ret != KMF_OK) 470430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 470530a5e8faSwyllys 470630a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 470799ebb4caSwyllys if (fullpath == NULL) 470899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 470999ebb4caSwyllys 471099ebb4caSwyllys /* If the requested file exists, return an error */ 471130a5e8faSwyllys if (test_for_file(fullpath, 0400) == 1) { 471299ebb4caSwyllys free(fullpath); 471399ebb4caSwyllys return (KMF_ERR_DUPLICATE_KEYFILE); 471499ebb4caSwyllys } 471599ebb4caSwyllys 471699ebb4caSwyllys fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400); 471799ebb4caSwyllys if (fd == -1) { 471899ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 471999ebb4caSwyllys goto out; 472099ebb4caSwyllys } 472199ebb4caSwyllys 472299ebb4caSwyllys rkey = malloc(sizeof (KMF_RAW_SYM_KEY)); 472399ebb4caSwyllys if (rkey == NULL) { 472499ebb4caSwyllys ret = KMF_ERR_MEMORY; 472599ebb4caSwyllys goto out; 472699ebb4caSwyllys } 472799ebb4caSwyllys (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 472899ebb4caSwyllys 472930a5e8faSwyllys if (keytype == KMF_DES) { 473099ebb4caSwyllys if ((ret = create_deskey(&deskey)) != KMF_OK) { 473199ebb4caSwyllys goto out; 473299ebb4caSwyllys } 473399ebb4caSwyllys rkey->keydata.val = (uchar_t *)deskey; 473499ebb4caSwyllys rkey->keydata.len = 8; 473599ebb4caSwyllys 473699ebb4caSwyllys symkey->keyalg = KMF_DES; 473799ebb4caSwyllys 473830a5e8faSwyllys } else if (keytype == KMF_DES3) { 473999ebb4caSwyllys if ((ret = create_des3key(&des3key)) != KMF_OK) { 474099ebb4caSwyllys goto out; 474199ebb4caSwyllys } 474299ebb4caSwyllys rkey->keydata.val = (uchar_t *)des3key; 474399ebb4caSwyllys rkey->keydata.len = DES3_KEY_SIZE; 474499ebb4caSwyllys symkey->keyalg = KMF_DES3; 47459b37d296Swyllys 474630a5e8faSwyllys } else if (keytype == KMF_AES || keytype == KMF_RC4 || 474730a5e8faSwyllys keytype == KMF_GENERIC_SECRET) { 474899ebb4caSwyllys int bytes; 474999ebb4caSwyllys 475030a5e8faSwyllys if (keylen % 8 != 0) { 475199ebb4caSwyllys ret = KMF_ERR_BAD_KEY_SIZE; 475299ebb4caSwyllys goto out; 475399ebb4caSwyllys } 475499ebb4caSwyllys 475530a5e8faSwyllys if (keytype == KMF_AES) { 475630a5e8faSwyllys if (keylen != 128 && 475730a5e8faSwyllys keylen != 192 && 475830a5e8faSwyllys keylen != 256) { 475999ebb4caSwyllys ret = KMF_ERR_BAD_KEY_SIZE; 476099ebb4caSwyllys goto out; 476199ebb4caSwyllys } 476299ebb4caSwyllys } 476399ebb4caSwyllys 476430a5e8faSwyllys bytes = keylen/8; 476599ebb4caSwyllys random = malloc(bytes); 476699ebb4caSwyllys if (random == NULL) { 476799ebb4caSwyllys ret = KMF_ERR_MEMORY; 476899ebb4caSwyllys goto out; 476999ebb4caSwyllys } 477099ebb4caSwyllys if (RAND_bytes(random, bytes) != 1) { 477199ebb4caSwyllys ret = KMF_ERR_KEYGEN_FAILED; 477299ebb4caSwyllys goto out; 477399ebb4caSwyllys } 477499ebb4caSwyllys 477599ebb4caSwyllys rkey->keydata.val = (uchar_t *)random; 477699ebb4caSwyllys rkey->keydata.len = bytes; 477730a5e8faSwyllys symkey->keyalg = keytype; 477899ebb4caSwyllys 477999ebb4caSwyllys } else { 478099ebb4caSwyllys ret = KMF_ERR_BAD_KEY_TYPE; 478199ebb4caSwyllys goto out; 478299ebb4caSwyllys } 478399ebb4caSwyllys 478499ebb4caSwyllys (void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len); 478599ebb4caSwyllys 478699ebb4caSwyllys symkey->kstype = KMF_KEYSTORE_OPENSSL; 478799ebb4caSwyllys symkey->keyclass = KMF_SYMMETRIC; 478899ebb4caSwyllys symkey->keylabel = (char *)fullpath; 478999ebb4caSwyllys symkey->israw = TRUE; 479099ebb4caSwyllys symkey->keyp = rkey; 479199ebb4caSwyllys 479299ebb4caSwyllys out: 479399ebb4caSwyllys if (fd != -1) 479499ebb4caSwyllys (void) close(fd); 479599ebb4caSwyllys 479699ebb4caSwyllys if (ret != KMF_OK && fullpath != NULL) { 479799ebb4caSwyllys free(fullpath); 479899ebb4caSwyllys } 479999ebb4caSwyllys if (ret != KMF_OK) { 480030a5e8faSwyllys kmf_free_raw_sym_key(rkey); 480199ebb4caSwyllys symkey->keyp = NULL; 480299ebb4caSwyllys symkey->keyalg = KMF_KEYALG_NONE; 480399ebb4caSwyllys } 480499ebb4caSwyllys 480599ebb4caSwyllys return (ret); 480699ebb4caSwyllys } 480799ebb4caSwyllys 480899ebb4caSwyllys /* 480999ebb4caSwyllys * Check a file to see if it is a CRL file with PEM or DER format. 481099ebb4caSwyllys * If success, return its format in the "pformat" argument. 481199ebb4caSwyllys */ 481299ebb4caSwyllys KMF_RETURN 481399ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat) 481499ebb4caSwyllys { 481599ebb4caSwyllys KMF_RETURN ret = KMF_OK; 481699ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 481799ebb4caSwyllys BIO *bio = NULL; 481899ebb4caSwyllys X509_CRL *xcrl = NULL; 481999ebb4caSwyllys 482099ebb4caSwyllys if (filename == NULL) { 482199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 482299ebb4caSwyllys } 482399ebb4caSwyllys 482499ebb4caSwyllys bio = BIO_new_file(filename, "rb"); 482599ebb4caSwyllys if (bio == NULL) { 482699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 482799ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 482899ebb4caSwyllys goto out; 482999ebb4caSwyllys } 483099ebb4caSwyllys 483199ebb4caSwyllys if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) { 483299ebb4caSwyllys *pformat = KMF_FORMAT_PEM; 483399ebb4caSwyllys goto out; 483499ebb4caSwyllys } 483599ebb4caSwyllys (void) BIO_free(bio); 483699ebb4caSwyllys 483799ebb4caSwyllys /* 483899ebb4caSwyllys * Now try to read it as raw DER data. 483999ebb4caSwyllys */ 484099ebb4caSwyllys bio = BIO_new_file(filename, "rb"); 484199ebb4caSwyllys if (bio == NULL) { 484299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 484399ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 484499ebb4caSwyllys goto out; 484599ebb4caSwyllys } 484699ebb4caSwyllys 484799ebb4caSwyllys if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) { 484899ebb4caSwyllys *pformat = KMF_FORMAT_ASN1; 484999ebb4caSwyllys } else { 485099ebb4caSwyllys ret = KMF_ERR_BAD_CRLFILE; 485199ebb4caSwyllys } 485299ebb4caSwyllys 485399ebb4caSwyllys out: 485499ebb4caSwyllys if (bio != NULL) 485599ebb4caSwyllys (void) BIO_free(bio); 485699ebb4caSwyllys 485799ebb4caSwyllys if (xcrl != NULL) 485899ebb4caSwyllys X509_CRL_free(xcrl); 485999ebb4caSwyllys 486099ebb4caSwyllys return (ret); 486199ebb4caSwyllys } 486299ebb4caSwyllys 486399ebb4caSwyllys KMF_RETURN 486499ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey, 486599ebb4caSwyllys KMF_RAW_SYM_KEY *rkey) 486699ebb4caSwyllys { 486799ebb4caSwyllys KMF_RETURN rv = KMF_OK; 486899ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 486999ebb4caSwyllys KMF_DATA keyvalue; 487099ebb4caSwyllys 487199ebb4caSwyllys if (kmfh == NULL) 487299ebb4caSwyllys return (KMF_ERR_UNINITIALIZED); 487399ebb4caSwyllys 487499ebb4caSwyllys if (symkey == NULL || rkey == NULL) 487599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 487699ebb4caSwyllys else if (symkey->keyclass != KMF_SYMMETRIC) 487799ebb4caSwyllys return (KMF_ERR_BAD_KEY_CLASS); 487899ebb4caSwyllys 487999ebb4caSwyllys if (symkey->israw) { 488099ebb4caSwyllys KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp; 488199ebb4caSwyllys 488299ebb4caSwyllys if (rawkey == NULL || 488399ebb4caSwyllys rawkey->keydata.val == NULL || 488499ebb4caSwyllys rawkey->keydata.len == 0) 488599ebb4caSwyllys return (KMF_ERR_BAD_KEYHANDLE); 488699ebb4caSwyllys 488799ebb4caSwyllys rkey->keydata.len = rawkey->keydata.len; 488899ebb4caSwyllys if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL) 488999ebb4caSwyllys return (KMF_ERR_MEMORY); 489099ebb4caSwyllys (void) memcpy(rkey->keydata.val, rawkey->keydata.val, 489199ebb4caSwyllys rkey->keydata.len); 489299ebb4caSwyllys } else { 489330a5e8faSwyllys rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue); 489499ebb4caSwyllys if (rv != KMF_OK) 489599ebb4caSwyllys return (rv); 489699ebb4caSwyllys rkey->keydata.len = keyvalue.Length; 489799ebb4caSwyllys rkey->keydata.val = keyvalue.Data; 489899ebb4caSwyllys } 489999ebb4caSwyllys 490099ebb4caSwyllys return (rv); 490199ebb4caSwyllys } 490202744e81Swyllys 490302744e81Swyllys /* 490430a5e8faSwyllys * substitute for the unsafe access(2) function. 490530a5e8faSwyllys * If the file in question already exists, return 1. 490630a5e8faSwyllys * else 0. If an error occurs during testing (other 490730a5e8faSwyllys * than EEXIST), return -1. 490830a5e8faSwyllys */ 490930a5e8faSwyllys static int 491030a5e8faSwyllys test_for_file(char *filename, mode_t mode) 491130a5e8faSwyllys { 491230a5e8faSwyllys int fd; 491330a5e8faSwyllys 491430a5e8faSwyllys /* 491530a5e8faSwyllys * Try to create the file with the EXCL flag. 491630a5e8faSwyllys * The call should fail if the file exists. 491730a5e8faSwyllys */ 491830a5e8faSwyllys fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode); 491930a5e8faSwyllys if (fd == -1 && errno == EEXIST) 492030a5e8faSwyllys return (1); 492130a5e8faSwyllys else if (fd == -1) /* some other error */ 492230a5e8faSwyllys return (-1); 492330a5e8faSwyllys 492430a5e8faSwyllys /* The file did NOT exist. Delete the testcase. */ 492530a5e8faSwyllys (void) close(fd); 492630a5e8faSwyllys (void) unlink(filename); 492730a5e8faSwyllys return (0); 492830a5e8faSwyllys } 492930a5e8faSwyllys 493030a5e8faSwyllys KMF_RETURN 493130a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr, 493230a5e8faSwyllys KMF_ATTRIBUTE *attrlist) 493330a5e8faSwyllys { 493430a5e8faSwyllys KMF_RETURN rv = KMF_OK; 493530a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 493630a5e8faSwyllys KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL; 493730a5e8faSwyllys KMF_RAW_KEY_DATA *rawkey; 493830a5e8faSwyllys EVP_PKEY *pkey = NULL; 493930a5e8faSwyllys KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM; 494030a5e8faSwyllys KMF_CREDENTIAL cred = { NULL, 0 }; 494130a5e8faSwyllys BIO *out = NULL; 494230a5e8faSwyllys int keys = 0; 494330a5e8faSwyllys char *fullpath = NULL; 494430a5e8faSwyllys char *keyfile = NULL; 494530a5e8faSwyllys char *dirpath = NULL; 494630a5e8faSwyllys 494730a5e8faSwyllys pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr); 494830a5e8faSwyllys if (pubkey != NULL) 494930a5e8faSwyllys keys++; 495030a5e8faSwyllys 495130a5e8faSwyllys prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr); 495230a5e8faSwyllys if (prikey != NULL) 495330a5e8faSwyllys keys++; 495430a5e8faSwyllys 495530a5e8faSwyllys rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr); 495630a5e8faSwyllys if (rawkey != NULL) 495730a5e8faSwyllys keys++; 495830a5e8faSwyllys 495930a5e8faSwyllys /* 496030a5e8faSwyllys * Exactly 1 type of key must be passed to this function. 496130a5e8faSwyllys */ 496230a5e8faSwyllys if (keys != 1) 496330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 496430a5e8faSwyllys 496530a5e8faSwyllys keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, 496630a5e8faSwyllys numattr); 496730a5e8faSwyllys if (keyfile == NULL) 496830a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 496930a5e8faSwyllys 497030a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 497130a5e8faSwyllys 497230a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 497330a5e8faSwyllys 497430a5e8faSwyllys /* Once we have the full path, we don't need the pieces */ 497530a5e8faSwyllys if (fullpath == NULL) 497630a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 497730a5e8faSwyllys 497830a5e8faSwyllys /* If the requested file exists, return an error */ 497930a5e8faSwyllys if (test_for_file(fullpath, 0400) == 1) { 498030a5e8faSwyllys free(fullpath); 498130a5e8faSwyllys return (KMF_ERR_DUPLICATE_KEYFILE); 498230a5e8faSwyllys } 498330a5e8faSwyllys 498430a5e8faSwyllys rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 498530a5e8faSwyllys &format, NULL); 498630a5e8faSwyllys if (rv != KMF_OK) 498730a5e8faSwyllys /* format is optional. */ 498830a5e8faSwyllys rv = KMF_OK; 498930a5e8faSwyllys 499030a5e8faSwyllys /* CRED is not required for OpenSSL files */ 499130a5e8faSwyllys (void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr, 499230a5e8faSwyllys &cred, NULL); 499330a5e8faSwyllys 499430a5e8faSwyllys /* Store the private key to the keyfile */ 499530a5e8faSwyllys out = BIO_new_file(fullpath, "wb"); 499630a5e8faSwyllys if (out == NULL) { 499730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 499830a5e8faSwyllys rv = KMF_ERR_OPEN_FILE; 499930a5e8faSwyllys goto end; 500030a5e8faSwyllys } 500130a5e8faSwyllys 500230a5e8faSwyllys if (prikey != NULL && prikey->keyp != NULL) { 500330a5e8faSwyllys if (prikey->keyalg == KMF_RSA || 500430a5e8faSwyllys prikey->keyalg == KMF_DSA) { 500530a5e8faSwyllys pkey = (EVP_PKEY *)prikey->keyp; 500630a5e8faSwyllys 500730a5e8faSwyllys rv = ssl_write_key(kmfh, format, 500830a5e8faSwyllys out, &cred, pkey, TRUE); 500930a5e8faSwyllys 501030a5e8faSwyllys if (rv == KMF_OK && prikey->keylabel == NULL) { 501130a5e8faSwyllys prikey->keylabel = strdup(fullpath); 501230a5e8faSwyllys if (prikey->keylabel == NULL) 501330a5e8faSwyllys rv = KMF_ERR_MEMORY; 501430a5e8faSwyllys } 501530a5e8faSwyllys } 501630a5e8faSwyllys } else if (pubkey != NULL && pubkey->keyp != NULL) { 501730a5e8faSwyllys if (pubkey->keyalg == KMF_RSA || 501830a5e8faSwyllys pubkey->keyalg == KMF_DSA) { 501930a5e8faSwyllys pkey = (EVP_PKEY *)pubkey->keyp; 502030a5e8faSwyllys 502130a5e8faSwyllys rv = ssl_write_key(kmfh, format, 502230a5e8faSwyllys out, &cred, pkey, FALSE); 502330a5e8faSwyllys 502430a5e8faSwyllys if (rv == KMF_OK && pubkey->keylabel == NULL) { 502530a5e8faSwyllys pubkey->keylabel = strdup(fullpath); 502630a5e8faSwyllys if (pubkey->keylabel == NULL) 502730a5e8faSwyllys rv = KMF_ERR_MEMORY; 502830a5e8faSwyllys } 502930a5e8faSwyllys } 503030a5e8faSwyllys } else if (rawkey != NULL) { 503130a5e8faSwyllys if (rawkey->keytype == KMF_RSA) { 503230a5e8faSwyllys pkey = ImportRawRSAKey(&rawkey->rawdata.rsa); 503330a5e8faSwyllys } else if (rawkey->keytype == KMF_DSA) { 503430a5e8faSwyllys pkey = ImportRawDSAKey(&rawkey->rawdata.dsa); 503530a5e8faSwyllys } else { 503630a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 503730a5e8faSwyllys } 50385b3e1433Swyllys if (pkey != NULL) { 503973cc0e02Swyllys KMF_KEY_CLASS kclass = KMF_ASYM_PRI; 504073cc0e02Swyllys 504173cc0e02Swyllys rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr, 504273cc0e02Swyllys (void *)&kclass, NULL); 504373cc0e02Swyllys if (rv != KMF_OK) 504473cc0e02Swyllys rv = KMF_OK; 50455b3e1433Swyllys rv = ssl_write_key(kmfh, format, out, 504673cc0e02Swyllys &cred, pkey, (kclass == KMF_ASYM_PRI)); 50475b3e1433Swyllys EVP_PKEY_free(pkey); 50485b3e1433Swyllys } 504930a5e8faSwyllys } 505030a5e8faSwyllys 505130a5e8faSwyllys end: 505230a5e8faSwyllys 505330a5e8faSwyllys if (out) 505430a5e8faSwyllys (void) BIO_free(out); 505530a5e8faSwyllys 50565b3e1433Swyllys 505730a5e8faSwyllys if (rv == KMF_OK) 505830a5e8faSwyllys (void) chmod(fullpath, 0400); 505930a5e8faSwyllys 506030a5e8faSwyllys free(fullpath); 506130a5e8faSwyllys return (rv); 506230a5e8faSwyllys } 506330a5e8faSwyllys 506430a5e8faSwyllys KMF_RETURN 506530a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 506630a5e8faSwyllys { 506730a5e8faSwyllys KMF_RETURN ret = KMF_OK; 506830a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 506930a5e8faSwyllys X509_CRL *xcrl = NULL; 507030a5e8faSwyllys X509 *xcert = NULL; 507130a5e8faSwyllys EVP_PKEY *pkey; 507230a5e8faSwyllys KMF_ENCODE_FORMAT format; 507330a5e8faSwyllys BIO *in = NULL, *out = NULL; 507430a5e8faSwyllys int openssl_ret = 0; 507530a5e8faSwyllys KMF_ENCODE_FORMAT outformat; 507630a5e8faSwyllys boolean_t crlcheck = FALSE; 507730a5e8faSwyllys char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile; 507830a5e8faSwyllys 507930a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 508030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 508130a5e8faSwyllys } 508230a5e8faSwyllys 508330a5e8faSwyllys /* CRL check is optional */ 508430a5e8faSwyllys (void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr, 508530a5e8faSwyllys &crlcheck, NULL); 508630a5e8faSwyllys 508730a5e8faSwyllys certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr); 508830a5e8faSwyllys if (crlcheck == B_TRUE && certfile == NULL) { 508930a5e8faSwyllys return (KMF_ERR_BAD_CERTFILE); 509030a5e8faSwyllys } 509130a5e8faSwyllys 509230a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 509330a5e8faSwyllys incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr); 509430a5e8faSwyllys outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr); 509530a5e8faSwyllys 509630a5e8faSwyllys crlfile = get_fullpath(dirpath, incrl); 509730a5e8faSwyllys 509830a5e8faSwyllys if (crlfile == NULL) 509930a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 510030a5e8faSwyllys 510130a5e8faSwyllys outcrlfile = get_fullpath(dirpath, outcrl); 510230a5e8faSwyllys if (outcrlfile == NULL) 510330a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 510430a5e8faSwyllys 510530a5e8faSwyllys if (isdir(outcrlfile)) { 510630a5e8faSwyllys free(outcrlfile); 510730a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 510830a5e8faSwyllys } 510930a5e8faSwyllys 511030a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 511130a5e8faSwyllys if (ret != KMF_OK) { 511230a5e8faSwyllys free(outcrlfile); 511330a5e8faSwyllys return (ret); 511430a5e8faSwyllys } 511530a5e8faSwyllys 511630a5e8faSwyllys in = BIO_new_file(crlfile, "rb"); 511730a5e8faSwyllys if (in == NULL) { 511830a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 511930a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 512030a5e8faSwyllys goto end; 512130a5e8faSwyllys } 512230a5e8faSwyllys 512330a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 512430a5e8faSwyllys xcrl = d2i_X509_CRL_bio(in, NULL); 512530a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 512630a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); 512730a5e8faSwyllys } 512830a5e8faSwyllys 512930a5e8faSwyllys if (xcrl == NULL) { 513030a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 513130a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 513230a5e8faSwyllys goto end; 513330a5e8faSwyllys } 513430a5e8faSwyllys 513530a5e8faSwyllys /* If bypasscheck is specified, no need to verify. */ 513630a5e8faSwyllys if (crlcheck == B_FALSE) 513730a5e8faSwyllys goto output; 513830a5e8faSwyllys 513930a5e8faSwyllys ret = kmf_is_cert_file(handle, certfile, &format); 514030a5e8faSwyllys if (ret != KMF_OK) 514130a5e8faSwyllys goto end; 514230a5e8faSwyllys 514330a5e8faSwyllys /* Read in the CA cert file and convert to X509 */ 514430a5e8faSwyllys if (BIO_read_filename(in, certfile) <= 0) { 514530a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 514630a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 514730a5e8faSwyllys goto end; 514830a5e8faSwyllys } 514930a5e8faSwyllys 515030a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 515130a5e8faSwyllys xcert = d2i_X509_bio(in, NULL); 515230a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 515330a5e8faSwyllys xcert = PEM_read_bio_X509(in, NULL, NULL, NULL); 515430a5e8faSwyllys } else { 515530a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 515630a5e8faSwyllys goto end; 515730a5e8faSwyllys } 515830a5e8faSwyllys 515930a5e8faSwyllys if (xcert == NULL) { 516030a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 516130a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 516230a5e8faSwyllys goto end; 516330a5e8faSwyllys } 516430a5e8faSwyllys /* Now get the public key from the CA cert */ 516530a5e8faSwyllys pkey = X509_get_pubkey(xcert); 516630a5e8faSwyllys if (pkey == NULL) { 516730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 516830a5e8faSwyllys ret = KMF_ERR_BAD_CERTFILE; 516930a5e8faSwyllys goto end; 517030a5e8faSwyllys } 517130a5e8faSwyllys 517230a5e8faSwyllys /* Verify the CRL with the CA's public key */ 517330a5e8faSwyllys openssl_ret = X509_CRL_verify(xcrl, pkey); 517430a5e8faSwyllys EVP_PKEY_free(pkey); 517530a5e8faSwyllys if (openssl_ret > 0) { 517630a5e8faSwyllys ret = KMF_OK; /* verify succeed */ 517730a5e8faSwyllys } else { 517830a5e8faSwyllys SET_ERROR(kmfh, openssl_ret); 517930a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 518030a5e8faSwyllys } 518130a5e8faSwyllys 518230a5e8faSwyllys output: 518330a5e8faSwyllys ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 518430a5e8faSwyllys &outformat, NULL); 518530a5e8faSwyllys if (ret != KMF_OK) { 518630a5e8faSwyllys ret = KMF_OK; 518730a5e8faSwyllys outformat = KMF_FORMAT_PEM; 518830a5e8faSwyllys } 518930a5e8faSwyllys 519030a5e8faSwyllys out = BIO_new_file(outcrlfile, "wb"); 519130a5e8faSwyllys if (out == NULL) { 519230a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 519330a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 519430a5e8faSwyllys goto end; 519530a5e8faSwyllys } 519630a5e8faSwyllys 519730a5e8faSwyllys if (outformat == KMF_FORMAT_ASN1) { 519830a5e8faSwyllys openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl); 519930a5e8faSwyllys } else if (outformat == KMF_FORMAT_PEM) { 520030a5e8faSwyllys openssl_ret = PEM_write_bio_X509_CRL(out, xcrl); 520130a5e8faSwyllys } else { 520230a5e8faSwyllys ret = KMF_ERR_BAD_PARAMETER; 520330a5e8faSwyllys goto end; 520430a5e8faSwyllys } 520530a5e8faSwyllys 520630a5e8faSwyllys if (openssl_ret <= 0) { 520730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 520830a5e8faSwyllys ret = KMF_ERR_WRITE_FILE; 520930a5e8faSwyllys } else { 521030a5e8faSwyllys ret = KMF_OK; 521130a5e8faSwyllys } 521230a5e8faSwyllys 521330a5e8faSwyllys end: 521430a5e8faSwyllys if (xcrl != NULL) 521530a5e8faSwyllys X509_CRL_free(xcrl); 521630a5e8faSwyllys 521730a5e8faSwyllys if (xcert != NULL) 521830a5e8faSwyllys X509_free(xcert); 521930a5e8faSwyllys 522030a5e8faSwyllys if (in != NULL) 522130a5e8faSwyllys (void) BIO_free(in); 522230a5e8faSwyllys 522330a5e8faSwyllys if (out != NULL) 522430a5e8faSwyllys (void) BIO_free(out); 522530a5e8faSwyllys 522630a5e8faSwyllys if (outcrlfile != NULL) 522730a5e8faSwyllys free(outcrlfile); 522830a5e8faSwyllys 522930a5e8faSwyllys return (ret); 523030a5e8faSwyllys } 523130a5e8faSwyllys 523230a5e8faSwyllys KMF_RETURN 523330a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 523430a5e8faSwyllys { 523530a5e8faSwyllys KMF_RETURN ret = KMF_OK; 523630a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 523730a5e8faSwyllys X509_CRL *x = NULL; 523830a5e8faSwyllys KMF_ENCODE_FORMAT format; 523930a5e8faSwyllys char *crlfile = NULL; 524030a5e8faSwyllys BIO *in = NULL; 524130a5e8faSwyllys BIO *mem = NULL; 524230a5e8faSwyllys long len; 524330a5e8faSwyllys char *memptr; 524430a5e8faSwyllys char *data = NULL; 524530a5e8faSwyllys char **crldata; 524630a5e8faSwyllys char *crlfilename, *dirpath; 524730a5e8faSwyllys 524830a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 524930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 525030a5e8faSwyllys } 525130a5e8faSwyllys crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, 525230a5e8faSwyllys attrlist, numattr); 525330a5e8faSwyllys if (crlfilename == NULL) 525430a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 525530a5e8faSwyllys 525630a5e8faSwyllys crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR, 525730a5e8faSwyllys attrlist, numattr); 525830a5e8faSwyllys 525930a5e8faSwyllys if (crldata == NULL) 526030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 526130a5e8faSwyllys 526230a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 526330a5e8faSwyllys 526430a5e8faSwyllys crlfile = get_fullpath(dirpath, crlfilename); 526530a5e8faSwyllys 526630a5e8faSwyllys if (crlfile == NULL) 526730a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 526830a5e8faSwyllys 526930a5e8faSwyllys if (isdir(crlfile)) { 527030a5e8faSwyllys free(crlfile); 527130a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 527230a5e8faSwyllys } 527330a5e8faSwyllys 527430a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 527530a5e8faSwyllys if (ret != KMF_OK) { 527630a5e8faSwyllys free(crlfile); 527730a5e8faSwyllys return (ret); 527830a5e8faSwyllys } 527930a5e8faSwyllys 528030a5e8faSwyllys if (bio_err == NULL) 528130a5e8faSwyllys bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 528230a5e8faSwyllys 528330a5e8faSwyllys in = BIO_new_file(crlfile, "rb"); 528430a5e8faSwyllys if (in == NULL) { 528530a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 528630a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 528730a5e8faSwyllys goto end; 528830a5e8faSwyllys } 528930a5e8faSwyllys 529030a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 529130a5e8faSwyllys x = d2i_X509_CRL_bio(in, NULL); 529230a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 529330a5e8faSwyllys x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); 529430a5e8faSwyllys } 529530a5e8faSwyllys 529630a5e8faSwyllys if (x == NULL) { /* should not happen */ 529730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 529830a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 529930a5e8faSwyllys goto end; 530030a5e8faSwyllys } 530130a5e8faSwyllys 530230a5e8faSwyllys mem = BIO_new(BIO_s_mem()); 530330a5e8faSwyllys if (mem == NULL) { 530430a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 530530a5e8faSwyllys ret = KMF_ERR_MEMORY; 530630a5e8faSwyllys goto end; 530730a5e8faSwyllys } 530830a5e8faSwyllys 530930a5e8faSwyllys (void) X509_CRL_print(mem, x); 531030a5e8faSwyllys len = BIO_get_mem_data(mem, &memptr); 531130a5e8faSwyllys if (len <= 0) { 531230a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 531330a5e8faSwyllys ret = KMF_ERR_MEMORY; 531430a5e8faSwyllys goto end; 531530a5e8faSwyllys } 531630a5e8faSwyllys 531730a5e8faSwyllys data = malloc(len + 1); 531830a5e8faSwyllys if (data == NULL) { 531930a5e8faSwyllys ret = KMF_ERR_MEMORY; 532030a5e8faSwyllys goto end; 532130a5e8faSwyllys } 532230a5e8faSwyllys 532330a5e8faSwyllys (void) memcpy(data, memptr, len); 532430a5e8faSwyllys data[len] = '\0'; 532530a5e8faSwyllys *crldata = data; 532630a5e8faSwyllys 532730a5e8faSwyllys end: 532830a5e8faSwyllys if (x != NULL) 532930a5e8faSwyllys X509_CRL_free(x); 533030a5e8faSwyllys 533130a5e8faSwyllys if (crlfile != NULL) 533230a5e8faSwyllys free(crlfile); 533330a5e8faSwyllys 533430a5e8faSwyllys if (in != NULL) 533530a5e8faSwyllys (void) BIO_free(in); 533630a5e8faSwyllys 533730a5e8faSwyllys if (mem != NULL) 533830a5e8faSwyllys (void) BIO_free(mem); 533930a5e8faSwyllys 534030a5e8faSwyllys return (ret); 534130a5e8faSwyllys } 534230a5e8faSwyllys 534330a5e8faSwyllys KMF_RETURN 534430a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 534530a5e8faSwyllys { 534630a5e8faSwyllys KMF_RETURN ret = KMF_OK; 534730a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 534830a5e8faSwyllys KMF_ENCODE_FORMAT format; 534930a5e8faSwyllys char *crlfile = NULL; 535030a5e8faSwyllys BIO *in = NULL; 535130a5e8faSwyllys char *crlfilename, *dirpath; 535230a5e8faSwyllys 535330a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 535430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 535530a5e8faSwyllys } 535630a5e8faSwyllys 535730a5e8faSwyllys crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, 535830a5e8faSwyllys attrlist, numattr); 535930a5e8faSwyllys 536030a5e8faSwyllys if (crlfilename == NULL) 536130a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 536230a5e8faSwyllys 536330a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 536430a5e8faSwyllys 536530a5e8faSwyllys crlfile = get_fullpath(dirpath, crlfilename); 536630a5e8faSwyllys 536730a5e8faSwyllys if (crlfile == NULL) 536830a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 536930a5e8faSwyllys 537030a5e8faSwyllys if (isdir(crlfile)) { 537130a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 537230a5e8faSwyllys goto end; 537330a5e8faSwyllys } 537430a5e8faSwyllys 537530a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 537630a5e8faSwyllys if (ret != KMF_OK) 537730a5e8faSwyllys goto end; 537830a5e8faSwyllys 537930a5e8faSwyllys if (unlink(crlfile) != 0) { 538030a5e8faSwyllys SET_SYS_ERROR(kmfh, errno); 538130a5e8faSwyllys ret = KMF_ERR_INTERNAL; 538230a5e8faSwyllys goto end; 538330a5e8faSwyllys } 538430a5e8faSwyllys 538530a5e8faSwyllys end: 538630a5e8faSwyllys if (in != NULL) 538730a5e8faSwyllys (void) BIO_free(in); 538830a5e8faSwyllys if (crlfile != NULL) 538930a5e8faSwyllys free(crlfile); 539030a5e8faSwyllys 539130a5e8faSwyllys return (ret); 539230a5e8faSwyllys } 539330a5e8faSwyllys 539430a5e8faSwyllys KMF_RETURN 539530a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 539630a5e8faSwyllys { 539730a5e8faSwyllys KMF_RETURN ret = KMF_OK; 539830a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 539930a5e8faSwyllys KMF_ENCODE_FORMAT format; 540030a5e8faSwyllys BIO *in = NULL; 540130a5e8faSwyllys X509 *xcert = NULL; 540230a5e8faSwyllys X509_CRL *xcrl = NULL; 540330a5e8faSwyllys STACK_OF(X509_REVOKED) *revoke_stack = NULL; 540430a5e8faSwyllys X509_REVOKED *revoke; 540530a5e8faSwyllys int i; 540630a5e8faSwyllys char *crlfilename, *crlfile, *dirpath, *certfile; 540730a5e8faSwyllys 540830a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 540930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 541030a5e8faSwyllys } 541130a5e8faSwyllys 541230a5e8faSwyllys crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, 541330a5e8faSwyllys attrlist, numattr); 541430a5e8faSwyllys 541530a5e8faSwyllys if (crlfilename == NULL) 541630a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 541730a5e8faSwyllys 541830a5e8faSwyllys certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr); 541930a5e8faSwyllys if (certfile == NULL) 542030a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 542130a5e8faSwyllys 542230a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 542330a5e8faSwyllys 542430a5e8faSwyllys crlfile = get_fullpath(dirpath, crlfilename); 542530a5e8faSwyllys 542630a5e8faSwyllys if (crlfile == NULL) 542730a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 542830a5e8faSwyllys 542930a5e8faSwyllys if (isdir(crlfile)) { 543030a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 543130a5e8faSwyllys goto end; 543230a5e8faSwyllys } 543330a5e8faSwyllys 543430a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 543530a5e8faSwyllys if (ret != KMF_OK) 543630a5e8faSwyllys goto end; 543730a5e8faSwyllys 543830a5e8faSwyllys /* Read the CRL file and load it into a X509_CRL structure */ 543930a5e8faSwyllys in = BIO_new_file(crlfilename, "rb"); 544030a5e8faSwyllys if (in == NULL) { 544130a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 544230a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 544330a5e8faSwyllys goto end; 544430a5e8faSwyllys } 544530a5e8faSwyllys 544630a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 544730a5e8faSwyllys xcrl = d2i_X509_CRL_bio(in, NULL); 544830a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 544930a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); 545030a5e8faSwyllys } 545130a5e8faSwyllys 545230a5e8faSwyllys if (xcrl == NULL) { 545330a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 545430a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 545530a5e8faSwyllys goto end; 545630a5e8faSwyllys } 545730a5e8faSwyllys (void) BIO_free(in); 545830a5e8faSwyllys 545930a5e8faSwyllys /* Read the Certificate file and load it into a X509 structure */ 546030a5e8faSwyllys ret = kmf_is_cert_file(handle, certfile, &format); 546130a5e8faSwyllys if (ret != KMF_OK) 546230a5e8faSwyllys goto end; 546330a5e8faSwyllys 546430a5e8faSwyllys in = BIO_new_file(certfile, "rb"); 546530a5e8faSwyllys if (in == NULL) { 546630a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 546730a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 546830a5e8faSwyllys goto end; 546930a5e8faSwyllys } 547030a5e8faSwyllys 547130a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 547230a5e8faSwyllys xcert = d2i_X509_bio(in, NULL); 547330a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 547430a5e8faSwyllys xcert = PEM_read_bio_X509(in, NULL, NULL, NULL); 547530a5e8faSwyllys } 547630a5e8faSwyllys 547730a5e8faSwyllys if (xcert == NULL) { 547830a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 547930a5e8faSwyllys ret = KMF_ERR_BAD_CERTFILE; 548030a5e8faSwyllys goto end; 548130a5e8faSwyllys } 548230a5e8faSwyllys 548330a5e8faSwyllys /* Check if the certificate and the CRL have same issuer */ 5484300fdee2SAndy Fiddaman if (X509_NAME_cmp(X509_get_issuer_name(xcert), 5485300fdee2SAndy Fiddaman X509_CRL_get_issuer(xcrl)) != 0) { 548630a5e8faSwyllys ret = KMF_ERR_ISSUER; 548730a5e8faSwyllys goto end; 548830a5e8faSwyllys } 548930a5e8faSwyllys 549030a5e8faSwyllys /* Check to see if the certificate serial number is revoked */ 549130a5e8faSwyllys revoke_stack = X509_CRL_get_REVOKED(xcrl); 549230a5e8faSwyllys if (sk_X509_REVOKED_num(revoke_stack) <= 0) { 549330a5e8faSwyllys /* No revoked certificates in the CRL file */ 549430a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 549530a5e8faSwyllys ret = KMF_ERR_EMPTY_CRL; 549630a5e8faSwyllys goto end; 549730a5e8faSwyllys } 549830a5e8faSwyllys 549930a5e8faSwyllys for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) { 5500d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 550130a5e8faSwyllys revoke = sk_X509_REVOKED_value(revoke_stack, i); 5502300fdee2SAndy Fiddaman if (ASN1_INTEGER_cmp(X509_get_serialNumber(xcert), 5503300fdee2SAndy Fiddaman X509_REVOKED_get0_serialNumber(revoke)) == 0) { 550430a5e8faSwyllys break; 550530a5e8faSwyllys } 550630a5e8faSwyllys } 550730a5e8faSwyllys 550830a5e8faSwyllys if (i < sk_X509_REVOKED_num(revoke_stack)) { 550930a5e8faSwyllys ret = KMF_OK; 551030a5e8faSwyllys } else { 551130a5e8faSwyllys ret = KMF_ERR_NOT_REVOKED; 551230a5e8faSwyllys } 551330a5e8faSwyllys 551430a5e8faSwyllys end: 551530a5e8faSwyllys if (in != NULL) 551630a5e8faSwyllys (void) BIO_free(in); 551730a5e8faSwyllys if (xcrl != NULL) 551830a5e8faSwyllys X509_CRL_free(xcrl); 551930a5e8faSwyllys if (xcert != NULL) 552030a5e8faSwyllys X509_free(xcert); 552130a5e8faSwyllys 552230a5e8faSwyllys return (ret); 552330a5e8faSwyllys } 552430a5e8faSwyllys 552530a5e8faSwyllys KMF_RETURN 552630a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert) 552730a5e8faSwyllys { 552830a5e8faSwyllys KMF_RETURN ret = KMF_OK; 552930a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 553030a5e8faSwyllys BIO *bcrl = NULL; 553130a5e8faSwyllys X509_CRL *xcrl = NULL; 553230a5e8faSwyllys X509 *xcert = NULL; 553330a5e8faSwyllys EVP_PKEY *pkey; 553430a5e8faSwyllys int sslret; 553530a5e8faSwyllys KMF_ENCODE_FORMAT crl_format; 553630a5e8faSwyllys unsigned char *p; 553730a5e8faSwyllys long len; 553830a5e8faSwyllys 553930a5e8faSwyllys if (handle == NULL || crlname == NULL || tacert == NULL) { 554030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 554130a5e8faSwyllys } 554230a5e8faSwyllys 554330a5e8faSwyllys ret = kmf_get_file_format(crlname, &crl_format); 554430a5e8faSwyllys if (ret != KMF_OK) 554530a5e8faSwyllys return (ret); 554630a5e8faSwyllys 554730a5e8faSwyllys bcrl = BIO_new_file(crlname, "rb"); 554830a5e8faSwyllys if (bcrl == NULL) { 554930a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 555030a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 555130a5e8faSwyllys goto cleanup; 555230a5e8faSwyllys } 555330a5e8faSwyllys 555430a5e8faSwyllys if (crl_format == KMF_FORMAT_ASN1) { 555530a5e8faSwyllys xcrl = d2i_X509_CRL_bio(bcrl, NULL); 555630a5e8faSwyllys } else if (crl_format == KMF_FORMAT_PEM) { 555730a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL); 555830a5e8faSwyllys } else { 555930a5e8faSwyllys ret = KMF_ERR_BAD_PARAMETER; 556030a5e8faSwyllys goto cleanup; 556130a5e8faSwyllys } 556230a5e8faSwyllys 556330a5e8faSwyllys if (xcrl == NULL) { 556430a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 556530a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 556630a5e8faSwyllys goto cleanup; 556730a5e8faSwyllys } 556830a5e8faSwyllys 556930a5e8faSwyllys p = tacert->Data; 557030a5e8faSwyllys len = tacert->Length; 557130a5e8faSwyllys xcert = d2i_X509(NULL, (const uchar_t **)&p, len); 557230a5e8faSwyllys 557330a5e8faSwyllys if (xcert == NULL) { 557430a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 557530a5e8faSwyllys ret = KMF_ERR_BAD_CERTFILE; 557630a5e8faSwyllys goto cleanup; 557730a5e8faSwyllys } 557830a5e8faSwyllys 557930a5e8faSwyllys /* Get issuer certificate public key */ 558030a5e8faSwyllys pkey = X509_get_pubkey(xcert); 558130a5e8faSwyllys if (pkey == NULL) { 558230a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 558330a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 558430a5e8faSwyllys goto cleanup; 558530a5e8faSwyllys } 558630a5e8faSwyllys 558730a5e8faSwyllys /* Verify CRL signature */ 558830a5e8faSwyllys sslret = X509_CRL_verify(xcrl, pkey); 558930a5e8faSwyllys EVP_PKEY_free(pkey); 559030a5e8faSwyllys if (sslret > 0) { 559130a5e8faSwyllys ret = KMF_OK; 559230a5e8faSwyllys } else { 559330a5e8faSwyllys SET_ERROR(kmfh, sslret); 559430a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 559530a5e8faSwyllys } 559630a5e8faSwyllys 559730a5e8faSwyllys cleanup: 559830a5e8faSwyllys if (bcrl != NULL) 559930a5e8faSwyllys (void) BIO_free(bcrl); 560030a5e8faSwyllys 560130a5e8faSwyllys if (xcrl != NULL) 560230a5e8faSwyllys X509_CRL_free(xcrl); 560330a5e8faSwyllys 560430a5e8faSwyllys if (xcert != NULL) 560530a5e8faSwyllys X509_free(xcert); 560630a5e8faSwyllys 560730a5e8faSwyllys return (ret); 560830a5e8faSwyllys 560930a5e8faSwyllys } 561030a5e8faSwyllys 561130a5e8faSwyllys KMF_RETURN 561230a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname) 561330a5e8faSwyllys { 561430a5e8faSwyllys KMF_RETURN ret = KMF_OK; 561530a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 561630a5e8faSwyllys KMF_ENCODE_FORMAT crl_format; 561730a5e8faSwyllys BIO *bcrl = NULL; 561830a5e8faSwyllys X509_CRL *xcrl = NULL; 561930a5e8faSwyllys int i; 562030a5e8faSwyllys 562130a5e8faSwyllys if (handle == NULL || crlname == NULL) { 562230a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 562330a5e8faSwyllys } 562430a5e8faSwyllys 562530a5e8faSwyllys ret = kmf_is_crl_file(handle, crlname, &crl_format); 562630a5e8faSwyllys if (ret != KMF_OK) 562730a5e8faSwyllys return (ret); 562830a5e8faSwyllys 562930a5e8faSwyllys bcrl = BIO_new_file(crlname, "rb"); 563030a5e8faSwyllys if (bcrl == NULL) { 563130a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 563230a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 563330a5e8faSwyllys goto cleanup; 563430a5e8faSwyllys } 563530a5e8faSwyllys 56365b3e1433Swyllys if (crl_format == KMF_FORMAT_ASN1) 563730a5e8faSwyllys xcrl = d2i_X509_CRL_bio(bcrl, NULL); 56385b3e1433Swyllys else if (crl_format == KMF_FORMAT_PEM) 563930a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL); 564030a5e8faSwyllys 564130a5e8faSwyllys if (xcrl == NULL) { 564230a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 564330a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 564430a5e8faSwyllys goto cleanup; 564530a5e8faSwyllys } 5646300fdee2SAndy Fiddaman i = X509_cmp_time(X509_CRL_get0_lastUpdate(xcrl), NULL); 564730a5e8faSwyllys if (i >= 0) { 564830a5e8faSwyllys ret = KMF_ERR_VALIDITY_PERIOD; 564930a5e8faSwyllys goto cleanup; 565030a5e8faSwyllys } 5651300fdee2SAndy Fiddaman if (X509_CRL_get0_nextUpdate(xcrl)) { 5652300fdee2SAndy Fiddaman i = X509_cmp_time(X509_CRL_get0_nextUpdate(xcrl), NULL); 565330a5e8faSwyllys 565430a5e8faSwyllys if (i <= 0) { 565530a5e8faSwyllys ret = KMF_ERR_VALIDITY_PERIOD; 565630a5e8faSwyllys goto cleanup; 565730a5e8faSwyllys } 565830a5e8faSwyllys } 565930a5e8faSwyllys 566030a5e8faSwyllys ret = KMF_OK; 566130a5e8faSwyllys 566230a5e8faSwyllys cleanup: 566330a5e8faSwyllys if (bcrl != NULL) 566430a5e8faSwyllys (void) BIO_free(bcrl); 566530a5e8faSwyllys 566630a5e8faSwyllys if (xcrl != NULL) 566730a5e8faSwyllys X509_CRL_free(xcrl); 566830a5e8faSwyllys 566930a5e8faSwyllys return (ret); 567030a5e8faSwyllys } 5671