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. 9553e44ceSAndrew 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 */ 142553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 1435b3e1433Swyllys DECLARE_STACK_OF(EVP_PKEY) 1445b3e1433Swyllys 1455b3e1433Swyllys #define sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY) 1465b3e1433Swyllys #define sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st)) 1475b3e1433Swyllys #define sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st)) 1485b3e1433Swyllys #define sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i)) 1495b3e1433Swyllys #define sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val)) 1505b3e1433Swyllys #define sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \ 1515b3e1433Swyllys (free_func)) 1525b3e1433Swyllys 153300fdee2SAndy Fiddaman #else 154300fdee2SAndy Fiddaman /* 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 304553e44ceSAndrew 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 } 325553e44ceSAndrew Stormont #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER */ 32699ebb4caSwyllys 32799ebb4caSwyllys KMF_PLUGIN_FUNCLIST * 32899ebb4caSwyllys KMF_Plugin_Initialize() 32999ebb4caSwyllys { 330553e44ceSAndrew 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 351553e44ceSAndrew 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; 821*f810c7e5SToomas Soome BerValue OID = { 0, 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: 1036a50e8766SToomas Soome if (pkey == NULL) { 103799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 1038a50e8766SToomas Soome } 103999ebb4caSwyllys 104099ebb4caSwyllys if (keyfile != NULL) 104199ebb4caSwyllys (void) BIO_free(keyfile); 104299ebb4caSwyllys 104399ebb4caSwyllys return (pkey); 104499ebb4caSwyllys } 104599ebb4caSwyllys 104699ebb4caSwyllys KMF_RETURN 104730a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 104899ebb4caSwyllys { 104999ebb4caSwyllys KMF_RETURN rv = KMF_OK; 105099ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 1051f482c776Swyllys int i, n; 1052f482c776Swyllys uint32_t maxcerts = 0; 105330a5e8faSwyllys uint32_t *num_certs; 105430a5e8faSwyllys KMF_X509_DER_CERT *kmf_cert = NULL; 105530a5e8faSwyllys char *dirpath = NULL; 105630a5e8faSwyllys char *filename = NULL; 105730a5e8faSwyllys char *fullpath = NULL; 105830a5e8faSwyllys char *issuer = NULL; 105930a5e8faSwyllys char *subject = NULL; 106030a5e8faSwyllys KMF_BIGINT *serial = NULL; 106130a5e8faSwyllys KMF_CERT_VALIDITY validity; 106299ebb4caSwyllys 106330a5e8faSwyllys num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr); 106430a5e8faSwyllys if (num_certs == NULL) 106599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 106699ebb4caSwyllys 106730a5e8faSwyllys /* num_certs should reference the size of kmf_cert */ 1068f482c776Swyllys maxcerts = *num_certs; 1069f482c776Swyllys if (maxcerts == 0) 1070f482c776Swyllys maxcerts = 0xFFFFFFFF; 107199ebb4caSwyllys *num_certs = 0; 107299ebb4caSwyllys 107330a5e8faSwyllys /* Get the optional returned certificate list */ 107430a5e8faSwyllys kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist, 107530a5e8faSwyllys numattr); 107699ebb4caSwyllys 107730a5e8faSwyllys /* 107830a5e8faSwyllys * The dirpath attribute and the filename attribute can not be NULL 107930a5e8faSwyllys * at the same time. 108030a5e8faSwyllys */ 108130a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 108230a5e8faSwyllys filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, 108330a5e8faSwyllys numattr); 108430a5e8faSwyllys 108530a5e8faSwyllys fullpath = get_fullpath(dirpath, filename); 108699ebb4caSwyllys if (fullpath == NULL) 108799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 108899ebb4caSwyllys 108930a5e8faSwyllys /* Get optional search criteria attributes */ 109030a5e8faSwyllys issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr); 109130a5e8faSwyllys subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr); 109230a5e8faSwyllys serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr); 109330a5e8faSwyllys rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr, 109430a5e8faSwyllys &validity, NULL); 109530a5e8faSwyllys if (rv != KMF_OK) { 109630a5e8faSwyllys validity = KMF_ALL_CERTS; 109730a5e8faSwyllys rv = KMF_OK; 109830a5e8faSwyllys } 109930a5e8faSwyllys 110099ebb4caSwyllys if (isdir(fullpath)) { 110199ebb4caSwyllys DIR *dirp; 110299ebb4caSwyllys struct dirent *dp; 110399ebb4caSwyllys 1104f482c776Swyllys n = 0; 110599ebb4caSwyllys /* open all files in the directory and attempt to read them */ 110699ebb4caSwyllys if ((dirp = opendir(fullpath)) == NULL) { 110799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 110899ebb4caSwyllys } 110999ebb4caSwyllys while ((dp = readdir(dirp)) != NULL) { 111099ebb4caSwyllys char *fname; 111171593db2Swyllys KMF_DATA *certlist = NULL; 1112f482c776Swyllys uint32_t loaded_certs = 0; 111371593db2Swyllys 111499ebb4caSwyllys if (strcmp(dp->d_name, ".") == 0 || 111599ebb4caSwyllys strcmp(dp->d_name, "..") == 0) 111699ebb4caSwyllys continue; 111799ebb4caSwyllys 111834acef67Swyllys fname = get_fullpath(fullpath, (char *)&dp->d_name); 111999ebb4caSwyllys 112030a5e8faSwyllys rv = load_certs(kmfh, issuer, subject, serial, 112130a5e8faSwyllys validity, fname, &certlist, &loaded_certs); 112299ebb4caSwyllys 112399ebb4caSwyllys if (rv != KMF_OK) { 112499ebb4caSwyllys free(fname); 112571593db2Swyllys if (certlist != NULL) { 1126f482c776Swyllys for (i = 0; i < loaded_certs; i++) 112730a5e8faSwyllys kmf_free_data(&certlist[i]); 112871593db2Swyllys free(certlist); 112971593db2Swyllys } 113099ebb4caSwyllys continue; 113199ebb4caSwyllys } 113299ebb4caSwyllys 113399ebb4caSwyllys /* If load succeeds, add certdata to the list */ 113499ebb4caSwyllys if (kmf_cert != NULL) { 1135f482c776Swyllys for (i = 0; i < loaded_certs && 1136b4058258Swyllys n < maxcerts; i++) { 113771593db2Swyllys kmf_cert[n].certificate.Data = 113871593db2Swyllys certlist[i].Data; 113999ebb4caSwyllys kmf_cert[n].certificate.Length = 114071593db2Swyllys certlist[i].Length; 114199ebb4caSwyllys 114299ebb4caSwyllys kmf_cert[n].kmf_private.keystore_type = 114399ebb4caSwyllys KMF_KEYSTORE_OPENSSL; 114499ebb4caSwyllys kmf_cert[n].kmf_private.flags = 114599ebb4caSwyllys KMF_FLAG_CERT_VALID; 114671593db2Swyllys kmf_cert[n].kmf_private.label = 114771593db2Swyllys strdup(fname); 114899ebb4caSwyllys n++; 114999ebb4caSwyllys } 1150b4058258Swyllys /* 1151b4058258Swyllys * If maxcerts < loaded_certs, clean up the 1152b4058258Swyllys * certs that were not used. 1153b4058258Swyllys */ 1154f482c776Swyllys for (; i < loaded_certs; i++) 115530a5e8faSwyllys kmf_free_data(&certlist[i]); 1156f482c776Swyllys } else { 1157f482c776Swyllys for (i = 0; i < loaded_certs; i++) 115830a5e8faSwyllys kmf_free_data(&certlist[i]); 1159f482c776Swyllys n += loaded_certs; 116071593db2Swyllys } 1161f482c776Swyllys free(certlist); 116271593db2Swyllys free(fname); 116371593db2Swyllys } 116499ebb4caSwyllys (*num_certs) = n; 116599ebb4caSwyllys if (*num_certs == 0) 116699ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND; 116730a5e8faSwyllys if (*num_certs > 0) 116899ebb4caSwyllys rv = KMF_OK; 116999ebb4caSwyllys exit: 117099ebb4caSwyllys (void) closedir(dirp); 117199ebb4caSwyllys } else { 117271593db2Swyllys KMF_DATA *certlist = NULL; 1173f482c776Swyllys uint32_t loaded_certs = 0; 117471593db2Swyllys 117530a5e8faSwyllys rv = load_certs(kmfh, issuer, subject, serial, validity, 117630a5e8faSwyllys fullpath, &certlist, &loaded_certs); 117799ebb4caSwyllys if (rv != KMF_OK) { 117899ebb4caSwyllys free(fullpath); 117999ebb4caSwyllys return (rv); 118099ebb4caSwyllys } 118199ebb4caSwyllys 1182f482c776Swyllys n = 0; 118371593db2Swyllys if (kmf_cert != NULL && certlist != NULL) { 1184f482c776Swyllys for (i = 0; i < loaded_certs && i < maxcerts; i++) { 1185f482c776Swyllys kmf_cert[n].certificate.Data = 118671593db2Swyllys certlist[i].Data; 1187f482c776Swyllys kmf_cert[n].certificate.Length = 118871593db2Swyllys certlist[i].Length; 1189f482c776Swyllys kmf_cert[n].kmf_private.keystore_type = 119099ebb4caSwyllys KMF_KEYSTORE_OPENSSL; 1191f482c776Swyllys kmf_cert[n].kmf_private.flags = 119271593db2Swyllys KMF_FLAG_CERT_VALID; 1193f482c776Swyllys kmf_cert[n].kmf_private.label = 119471593db2Swyllys strdup(fullpath); 1195f482c776Swyllys n++; 119671593db2Swyllys } 1197f482c776Swyllys /* If maxcerts < loaded_certs, clean up */ 1198f482c776Swyllys for (; i < loaded_certs; i++) 119930a5e8faSwyllys kmf_free_data(&certlist[i]); 1200f482c776Swyllys } else if (certlist != NULL) { 1201f482c776Swyllys for (i = 0; i < loaded_certs; i++) 120230a5e8faSwyllys kmf_free_data(&certlist[i]); 1203f482c776Swyllys n = loaded_certs; 1204f482c776Swyllys } 120530a5e8faSwyllys if (certlist != NULL) 120671593db2Swyllys free(certlist); 1207f482c776Swyllys *num_certs = n; 120899ebb4caSwyllys } 120999ebb4caSwyllys 121099ebb4caSwyllys free(fullpath); 121199ebb4caSwyllys 121299ebb4caSwyllys return (rv); 121399ebb4caSwyllys } 121499ebb4caSwyllys 121599ebb4caSwyllys void 121699ebb4caSwyllys /*ARGSUSED*/ 121799ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle, 121899ebb4caSwyllys KMF_X509_DER_CERT *kmf_cert) 121999ebb4caSwyllys { 122099ebb4caSwyllys if (kmf_cert != NULL) { 122199ebb4caSwyllys if (kmf_cert->certificate.Data != NULL) { 1222e65e5c2dSWyllys Ingersoll kmf_free_data(&kmf_cert->certificate); 122399ebb4caSwyllys } 122499ebb4caSwyllys if (kmf_cert->kmf_private.label) 122599ebb4caSwyllys free(kmf_cert->kmf_private.label); 122699ebb4caSwyllys } 122799ebb4caSwyllys } 122899ebb4caSwyllys 122930a5e8faSwyllys /*ARGSUSED*/ 123099ebb4caSwyllys KMF_RETURN 123130a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 123299ebb4caSwyllys { 123399ebb4caSwyllys KMF_RETURN ret = KMF_OK; 123430a5e8faSwyllys KMF_DATA *cert = NULL; 123530a5e8faSwyllys char *outfilename = NULL; 123630a5e8faSwyllys char *dirpath = NULL; 123730a5e8faSwyllys char *fullpath = NULL; 123899ebb4caSwyllys KMF_ENCODE_FORMAT format; 123999ebb4caSwyllys 124030a5e8faSwyllys /* Get the cert data */ 124130a5e8faSwyllys cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr); 124230a5e8faSwyllys if (cert == NULL || cert->Data == NULL) 124399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 124499ebb4caSwyllys 124530a5e8faSwyllys /* Check the output filename and directory attributes. */ 124630a5e8faSwyllys outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, 124730a5e8faSwyllys numattr); 124830a5e8faSwyllys if (outfilename == NULL) 124930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 125099ebb4caSwyllys 125130a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 125230a5e8faSwyllys fullpath = get_fullpath(dirpath, outfilename); 125399ebb4caSwyllys if (fullpath == NULL) 125430a5e8faSwyllys return (KMF_ERR_BAD_CERTFILE); 125599ebb4caSwyllys 125630a5e8faSwyllys /* Check the optional format attribute */ 125730a5e8faSwyllys ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 125830a5e8faSwyllys &format, NULL); 125930a5e8faSwyllys if (ret != KMF_OK) { 126030a5e8faSwyllys /* If there is no format attribute, then default to PEM */ 126130a5e8faSwyllys format = KMF_FORMAT_PEM; 126299ebb4caSwyllys ret = KMF_OK; 126330a5e8faSwyllys } else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) { 126430a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 126599ebb4caSwyllys goto out; 126699ebb4caSwyllys } 126799ebb4caSwyllys 126830a5e8faSwyllys /* Store the certificate in the file with the specified format */ 126930a5e8faSwyllys ret = kmf_create_cert_file(cert, format, fullpath); 127099ebb4caSwyllys 127199ebb4caSwyllys out: 127299ebb4caSwyllys if (fullpath != NULL) 127399ebb4caSwyllys free(fullpath); 127499ebb4caSwyllys 127599ebb4caSwyllys return (ret); 127699ebb4caSwyllys } 127799ebb4caSwyllys 127830a5e8faSwyllys 127999ebb4caSwyllys KMF_RETURN 128030a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 128199ebb4caSwyllys { 128299ebb4caSwyllys KMF_RETURN rv; 128399ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 12846b35cb3cSRichard PALO KMF_DATA certdata = { 0, NULL }; 128530a5e8faSwyllys char *dirpath = NULL; 128630a5e8faSwyllys char *filename = NULL; 128730a5e8faSwyllys char *fullpath = NULL; 128830a5e8faSwyllys char *issuer = NULL; 128930a5e8faSwyllys char *subject = NULL; 129030a5e8faSwyllys KMF_BIGINT *serial = NULL; 129130a5e8faSwyllys KMF_CERT_VALIDITY validity; 129299ebb4caSwyllys 129330a5e8faSwyllys /* 129430a5e8faSwyllys * Get the DIRPATH and CERT_FILENAME attributes. They can not be 129530a5e8faSwyllys * NULL at the same time. 129630a5e8faSwyllys */ 129730a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 129830a5e8faSwyllys filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, 129930a5e8faSwyllys numattr); 130030a5e8faSwyllys fullpath = get_fullpath(dirpath, filename); 130199ebb4caSwyllys if (fullpath == NULL) 130299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 130399ebb4caSwyllys 130430a5e8faSwyllys /* Get optional search criteria attributes */ 130530a5e8faSwyllys issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr); 130630a5e8faSwyllys subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr); 130730a5e8faSwyllys serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr); 130830a5e8faSwyllys rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr, 130930a5e8faSwyllys &validity, NULL); 131030a5e8faSwyllys if (rv != KMF_OK) { 131130a5e8faSwyllys validity = KMF_ALL_CERTS; 131230a5e8faSwyllys rv = KMF_OK; 131330a5e8faSwyllys } 131430a5e8faSwyllys 131599ebb4caSwyllys if (isdir(fullpath)) { 131699ebb4caSwyllys DIR *dirp; 131799ebb4caSwyllys struct dirent *dp; 131899ebb4caSwyllys 131999ebb4caSwyllys /* open all files in the directory and attempt to read them */ 132099ebb4caSwyllys if ((dirp = opendir(fullpath)) == NULL) { 132199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 132299ebb4caSwyllys } 132399ebb4caSwyllys 132499ebb4caSwyllys while ((dp = readdir(dirp)) != NULL) { 132599ebb4caSwyllys if (strcmp(dp->d_name, ".") != 0 && 132699ebb4caSwyllys strcmp(dp->d_name, "..") != 0) { 132799ebb4caSwyllys char *fname; 132899ebb4caSwyllys 132999ebb4caSwyllys fname = get_fullpath(fullpath, 133099ebb4caSwyllys (char *)&dp->d_name); 133199ebb4caSwyllys 133299ebb4caSwyllys if (fname == NULL) { 133399ebb4caSwyllys rv = KMF_ERR_MEMORY; 133499ebb4caSwyllys break; 133599ebb4caSwyllys } 133699ebb4caSwyllys 133730a5e8faSwyllys rv = kmf_load_cert(kmfh, issuer, subject, 133830a5e8faSwyllys serial, validity, fname, &certdata); 133999ebb4caSwyllys 134099ebb4caSwyllys if (rv == KMF_ERR_CERT_NOT_FOUND) { 134199ebb4caSwyllys free(fname); 1342e65e5c2dSWyllys Ingersoll kmf_free_data(&certdata); 134399ebb4caSwyllys rv = KMF_OK; 134499ebb4caSwyllys continue; 134599ebb4caSwyllys } else if (rv != KMF_OK) { 134699ebb4caSwyllys free(fname); 134799ebb4caSwyllys break; 134899ebb4caSwyllys } 134999ebb4caSwyllys 135099ebb4caSwyllys if (unlink(fname) != 0) { 135199ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 135299ebb4caSwyllys rv = KMF_ERR_INTERNAL; 135399ebb4caSwyllys free(fname); 135499ebb4caSwyllys break; 135599ebb4caSwyllys } 135699ebb4caSwyllys free(fname); 1357e65e5c2dSWyllys Ingersoll kmf_free_data(&certdata); 135899ebb4caSwyllys } 135999ebb4caSwyllys } 136099ebb4caSwyllys (void) closedir(dirp); 136199ebb4caSwyllys } else { 136299ebb4caSwyllys /* Just try to load a single certificate */ 136330a5e8faSwyllys rv = kmf_load_cert(kmfh, issuer, subject, serial, validity, 136430a5e8faSwyllys fullpath, &certdata); 136599ebb4caSwyllys if (rv == KMF_OK) { 136699ebb4caSwyllys if (unlink(fullpath) != 0) { 136799ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 136899ebb4caSwyllys rv = KMF_ERR_INTERNAL; 136999ebb4caSwyllys } 137099ebb4caSwyllys } 137199ebb4caSwyllys } 137299ebb4caSwyllys 137399ebb4caSwyllys out: 137499ebb4caSwyllys if (fullpath != NULL) 137599ebb4caSwyllys free(fullpath); 137699ebb4caSwyllys 1377e65e5c2dSWyllys Ingersoll kmf_free_data(&certdata); 137899ebb4caSwyllys 137999ebb4caSwyllys return (rv); 138099ebb4caSwyllys } 138199ebb4caSwyllys 138299ebb4caSwyllys KMF_RETURN 138399ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, 138499ebb4caSwyllys KMF_DATA *keydata) 138599ebb4caSwyllys { 138699ebb4caSwyllys KMF_RETURN rv = KMF_OK; 138799ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 138899ebb4caSwyllys int n; 138999ebb4caSwyllys 139099ebb4caSwyllys if (key == NULL || keydata == NULL || 139199ebb4caSwyllys key->keyp == NULL) 139299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 139399ebb4caSwyllys 139499ebb4caSwyllys if (key->keyalg == KMF_RSA) { 139599ebb4caSwyllys RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp); 139699ebb4caSwyllys 139799ebb4caSwyllys if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) { 139899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 139999ebb4caSwyllys return (KMF_ERR_ENCODING); 140099ebb4caSwyllys } 140199ebb4caSwyllys RSA_free(pubkey); 140299ebb4caSwyllys } else if (key->keyalg == KMF_DSA) { 140399ebb4caSwyllys DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp); 140499ebb4caSwyllys 140599ebb4caSwyllys if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) { 140699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 140799ebb4caSwyllys return (KMF_ERR_ENCODING); 140899ebb4caSwyllys } 140999ebb4caSwyllys DSA_free(pubkey); 141099ebb4caSwyllys } else { 141199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 141299ebb4caSwyllys } 141399ebb4caSwyllys keydata->Length = n; 141499ebb4caSwyllys 141599ebb4caSwyllys cleanup: 141699ebb4caSwyllys if (rv != KMF_OK) { 141799ebb4caSwyllys if (keydata->Data) 141899ebb4caSwyllys free(keydata->Data); 141999ebb4caSwyllys keydata->Data = NULL; 142099ebb4caSwyllys keydata->Length = 0; 142199ebb4caSwyllys } 142299ebb4caSwyllys 142399ebb4caSwyllys return (rv); 142499ebb4caSwyllys } 142599ebb4caSwyllys 142699ebb4caSwyllys static KMF_RETURN 142730a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out, 142830a5e8faSwyllys KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private) 142999ebb4caSwyllys { 143099ebb4caSwyllys int rv = 0; 143199ebb4caSwyllys RSA *rsa; 143299ebb4caSwyllys DSA *dsa; 143399ebb4caSwyllys 14345b3e1433Swyllys if (pkey == NULL || out == NULL) 14355b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 14365b3e1433Swyllys 143799ebb4caSwyllys switch (format) { 143873cc0e02Swyllys case KMF_FORMAT_RAWKEY: 143973cc0e02Swyllys /* same as ASN.1 */ 144099ebb4caSwyllys case KMF_FORMAT_ASN1: 1441300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) { 144230a5e8faSwyllys if (private) 144399ebb4caSwyllys rv = i2d_RSAPrivateKey_bio(out, rsa); 144430a5e8faSwyllys else 144530a5e8faSwyllys rv = i2d_RSAPublicKey_bio(out, rsa); 1446300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) { 144799ebb4caSwyllys rv = i2d_DSAPrivateKey_bio(out, dsa); 144899ebb4caSwyllys } 144999ebb4caSwyllys if (rv == 1) { 145099ebb4caSwyllys rv = KMF_OK; 145199ebb4caSwyllys } else { 145299ebb4caSwyllys SET_ERROR(kmfh, rv); 145399ebb4caSwyllys } 145499ebb4caSwyllys break; 145599ebb4caSwyllys case KMF_FORMAT_PEM: 1456300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) { 145730a5e8faSwyllys if (private) 145899ebb4caSwyllys rv = PEM_write_bio_RSAPrivateKey(out, 145930a5e8faSwyllys rsa, NULL, NULL, 0, NULL, 146030a5e8faSwyllys (cred != NULL ? cred->cred : NULL)); 146130a5e8faSwyllys else 146230a5e8faSwyllys rv = PEM_write_bio_RSAPublicKey(out, 146330a5e8faSwyllys rsa); 1464300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) { 146599ebb4caSwyllys rv = PEM_write_bio_DSAPrivateKey(out, 146630a5e8faSwyllys dsa, NULL, NULL, 0, NULL, 146730a5e8faSwyllys (cred != NULL ? cred->cred : NULL)); 146899ebb4caSwyllys } 146999ebb4caSwyllys 147099ebb4caSwyllys if (rv == 1) { 147199ebb4caSwyllys rv = KMF_OK; 147299ebb4caSwyllys } else { 147399ebb4caSwyllys SET_ERROR(kmfh, rv); 147499ebb4caSwyllys } 147599ebb4caSwyllys break; 147699ebb4caSwyllys 147799ebb4caSwyllys default: 147899ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 147999ebb4caSwyllys } 148099ebb4caSwyllys 148199ebb4caSwyllys return (rv); 148299ebb4caSwyllys } 148399ebb4caSwyllys 148499ebb4caSwyllys KMF_RETURN 148530a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr, 148630a5e8faSwyllys KMF_ATTRIBUTE *attrlist) 148799ebb4caSwyllys { 148899ebb4caSwyllys KMF_RETURN rv = KMF_OK; 148999ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 1490300fdee2SAndy Fiddaman uint32_t eValue = RSA_F4; 1491300fdee2SAndy Fiddaman BIGNUM *eValue_bn = NULL; 149299ebb4caSwyllys RSA *sslPrivKey = NULL; 149399ebb4caSwyllys DSA *sslDSAKey = NULL; 149499ebb4caSwyllys EVP_PKEY *eprikey = NULL; 149599ebb4caSwyllys EVP_PKEY *epubkey = NULL; 149699ebb4caSwyllys BIO *out = NULL; 149730a5e8faSwyllys KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL; 149830a5e8faSwyllys uint32_t keylen = 1024; 149930a5e8faSwyllys uint32_t keylen_size = sizeof (uint32_t); 150030a5e8faSwyllys boolean_t storekey = TRUE; 150130a5e8faSwyllys KMF_KEY_ALG keytype = KMF_RSA; 150299ebb4caSwyllys 1503300fdee2SAndy Fiddaman eValue_bn = BN_new(); 1504300fdee2SAndy Fiddaman if (eValue_bn == NULL) 1505300fdee2SAndy Fiddaman return (KMF_ERR_MEMORY); 1506300fdee2SAndy Fiddaman if (BN_set_word(eValue_bn, eValue) == 0) { 1507300fdee2SAndy Fiddaman rv = KMF_ERR_KEYGEN_FAILED; 1508300fdee2SAndy Fiddaman goto cleanup; 1509300fdee2SAndy Fiddaman } 1510300fdee2SAndy Fiddaman 151130a5e8faSwyllys rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr, 151230a5e8faSwyllys &storekey, NULL); 151330a5e8faSwyllys if (rv != KMF_OK) { 151430a5e8faSwyllys /* "storekey" is optional. Default is TRUE */ 151530a5e8faSwyllys rv = KMF_OK; 151699ebb4caSwyllys } 151799ebb4caSwyllys 151830a5e8faSwyllys rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, 151930a5e8faSwyllys (void *)&keytype, NULL); 152030a5e8faSwyllys if (rv != KMF_OK) 152130a5e8faSwyllys /* keytype is optional. KMF_RSA is default */ 152230a5e8faSwyllys rv = KMF_OK; 152399ebb4caSwyllys 152430a5e8faSwyllys pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr); 1525300fdee2SAndy Fiddaman if (pubkey == NULL) { 1526300fdee2SAndy Fiddaman rv = KMF_ERR_BAD_PARAMETER; 1527300fdee2SAndy Fiddaman goto cleanup; 1528300fdee2SAndy Fiddaman } 152999ebb4caSwyllys 153030a5e8faSwyllys privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr); 1531300fdee2SAndy Fiddaman if (privkey == NULL) { 1532300fdee2SAndy Fiddaman rv = KMF_ERR_BAD_PARAMETER; 1533300fdee2SAndy Fiddaman goto cleanup; 1534300fdee2SAndy Fiddaman } 153530a5e8faSwyllys 153630a5e8faSwyllys (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE)); 153730a5e8faSwyllys (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE)); 153899ebb4caSwyllys 153999ebb4caSwyllys eprikey = EVP_PKEY_new(); 154099ebb4caSwyllys if (eprikey == NULL) { 154199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 154299ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 154399ebb4caSwyllys goto cleanup; 154499ebb4caSwyllys } 154599ebb4caSwyllys epubkey = EVP_PKEY_new(); 154699ebb4caSwyllys if (epubkey == NULL) { 154799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 154899ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 154999ebb4caSwyllys goto cleanup; 155099ebb4caSwyllys } 155130a5e8faSwyllys if (keytype == KMF_RSA) { 155230a5e8faSwyllys KMF_BIGINT *rsaexp = NULL; 155399ebb4caSwyllys 155430a5e8faSwyllys rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr); 155530a5e8faSwyllys if (rsaexp != NULL) { 155630a5e8faSwyllys if (rsaexp->len > 0 && 155730a5e8faSwyllys rsaexp->len <= sizeof (eValue) && 155830a5e8faSwyllys rsaexp->val != NULL) { 1559a2d4930dSDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */ 156030a5e8faSwyllys eValue = *(uint32_t *)rsaexp->val; 1561300fdee2SAndy Fiddaman if (BN_set_word(eValue_bn, eValue) == 0) { 1562300fdee2SAndy Fiddaman rv = KMF_ERR_BAD_PARAMETER; 1563300fdee2SAndy Fiddaman goto cleanup; 1564300fdee2SAndy Fiddaman } 156530a5e8faSwyllys } else { 156630a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 156730a5e8faSwyllys goto cleanup; 156830a5e8faSwyllys } 156930a5e8faSwyllys } else { 157030a5e8faSwyllys /* RSA Exponent is optional. Default is 0x10001 */ 157130a5e8faSwyllys rv = KMF_OK; 157230a5e8faSwyllys } 157330a5e8faSwyllys 157430a5e8faSwyllys rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, 157530a5e8faSwyllys &keylen, &keylen_size); 157630a5e8faSwyllys if (rv == KMF_ERR_ATTR_NOT_FOUND) 157730a5e8faSwyllys /* keylen is optional, default is 1024 */ 157830a5e8faSwyllys rv = KMF_OK; 157930a5e8faSwyllys if (rv != KMF_OK) { 158030a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 158130a5e8faSwyllys goto cleanup; 158230a5e8faSwyllys } 158330a5e8faSwyllys 1584300fdee2SAndy Fiddaman sslPrivKey = RSA_new(); 1585300fdee2SAndy Fiddaman if (sslPrivKey == NULL || 1586300fdee2SAndy Fiddaman RSA_generate_key_ex(sslPrivKey, keylen, eValue_bn, NULL) 1587300fdee2SAndy Fiddaman == 0) { 158899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 158999ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 159099ebb4caSwyllys } else { 159130a5e8faSwyllys (void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey); 159299ebb4caSwyllys privkey->kstype = KMF_KEYSTORE_OPENSSL; 159399ebb4caSwyllys privkey->keyalg = KMF_RSA; 159499ebb4caSwyllys privkey->keyclass = KMF_ASYM_PRI; 159599ebb4caSwyllys privkey->israw = FALSE; 159699ebb4caSwyllys privkey->keyp = (void *)eprikey; 159730a5e8faSwyllys 159899ebb4caSwyllys /* OpenSSL derives the public key from the private */ 159930a5e8faSwyllys (void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey); 160099ebb4caSwyllys pubkey->kstype = KMF_KEYSTORE_OPENSSL; 160199ebb4caSwyllys pubkey->keyalg = KMF_RSA; 160299ebb4caSwyllys pubkey->israw = FALSE; 160399ebb4caSwyllys pubkey->keyclass = KMF_ASYM_PUB; 160499ebb4caSwyllys pubkey->keyp = (void *)epubkey; 160599ebb4caSwyllys } 160630a5e8faSwyllys } else if (keytype == KMF_DSA) { 1607300fdee2SAndy Fiddaman BIGNUM *p, *q, *g; 1608300fdee2SAndy Fiddaman 160999ebb4caSwyllys sslDSAKey = DSA_new(); 161099ebb4caSwyllys if (sslDSAKey == NULL) { 161199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 161299ebb4caSwyllys return (KMF_ERR_MEMORY); 161399ebb4caSwyllys } 161499ebb4caSwyllys 1615300fdee2SAndy Fiddaman p = BN_bin2bn(P, sizeof (P), NULL); 1616300fdee2SAndy Fiddaman q = BN_bin2bn(Q, sizeof (Q), NULL); 1617300fdee2SAndy Fiddaman g = BN_bin2bn(G, sizeof (G), NULL); 1618300fdee2SAndy Fiddaman if (p == NULL || q == NULL || g == NULL) { 1619300fdee2SAndy Fiddaman BN_free(p); 1620300fdee2SAndy Fiddaman BN_free(q); 1621300fdee2SAndy Fiddaman BN_free(g); 162299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 162399ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 162499ebb4caSwyllys goto cleanup; 162599ebb4caSwyllys } 1626300fdee2SAndy Fiddaman 1627300fdee2SAndy Fiddaman if (DSA_set0_pqg(sslDSAKey, p, q, g) == 0) { 162899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 162999ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 163099ebb4caSwyllys goto cleanup; 163199ebb4caSwyllys } 163299ebb4caSwyllys 163399ebb4caSwyllys if (!DSA_generate_key(sslDSAKey)) { 163499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 163599ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 163699ebb4caSwyllys goto cleanup; 163799ebb4caSwyllys } 163899ebb4caSwyllys 163999ebb4caSwyllys privkey->kstype = KMF_KEYSTORE_OPENSSL; 164099ebb4caSwyllys privkey->keyalg = KMF_DSA; 164199ebb4caSwyllys privkey->keyclass = KMF_ASYM_PRI; 164299ebb4caSwyllys privkey->israw = FALSE; 164399ebb4caSwyllys if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) { 164499ebb4caSwyllys privkey->keyp = (void *)eprikey; 164599ebb4caSwyllys } else { 164699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 164799ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 164899ebb4caSwyllys goto cleanup; 164999ebb4caSwyllys } 165099ebb4caSwyllys 165199ebb4caSwyllys pubkey->kstype = KMF_KEYSTORE_OPENSSL; 165299ebb4caSwyllys pubkey->keyalg = KMF_DSA; 165399ebb4caSwyllys pubkey->keyclass = KMF_ASYM_PUB; 165499ebb4caSwyllys pubkey->israw = FALSE; 165599ebb4caSwyllys 165699ebb4caSwyllys if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) { 165799ebb4caSwyllys pubkey->keyp = (void *)epubkey; 165899ebb4caSwyllys } else { 165999ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 166099ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 166199ebb4caSwyllys goto cleanup; 166299ebb4caSwyllys } 166399ebb4caSwyllys } 166499ebb4caSwyllys 166599ebb4caSwyllys if (rv != KMF_OK) { 166699ebb4caSwyllys goto cleanup; 166799ebb4caSwyllys } 166899ebb4caSwyllys 166930a5e8faSwyllys if (storekey) { 167030a5e8faSwyllys KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */ 167130a5e8faSwyllys int i = 0; 167230a5e8faSwyllys char *keyfile = NULL, *dirpath = NULL; 167330a5e8faSwyllys KMF_ENCODE_FORMAT format; 167430a5e8faSwyllys /* 167530a5e8faSwyllys * Construct a new attribute arrray and call openssl_store_key 167630a5e8faSwyllys */ 167730a5e8faSwyllys kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR, 167830a5e8faSwyllys privkey, sizeof (privkey)); 167930a5e8faSwyllys i++; 168030a5e8faSwyllys 168130a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 168230a5e8faSwyllys if (dirpath != NULL) { 168330a5e8faSwyllys storeattrs[i].type = KMF_DIRPATH_ATTR; 168430a5e8faSwyllys storeattrs[i].pValue = dirpath; 168530a5e8faSwyllys storeattrs[i].valueLen = strlen(dirpath); 168630a5e8faSwyllys i++; 168730a5e8faSwyllys } else { 168830a5e8faSwyllys rv = KMF_OK; /* DIRPATH is optional */ 168999ebb4caSwyllys } 169030a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, 169130a5e8faSwyllys attrlist, numattr); 169230a5e8faSwyllys if (keyfile != NULL) { 169330a5e8faSwyllys storeattrs[i].type = KMF_KEY_FILENAME_ATTR; 169430a5e8faSwyllys storeattrs[i].pValue = keyfile; 169530a5e8faSwyllys storeattrs[i].valueLen = strlen(keyfile); 169630a5e8faSwyllys i++; 169730a5e8faSwyllys } else { 169830a5e8faSwyllys goto cleanup; /* KEYFILE is required */ 169930a5e8faSwyllys } 170030a5e8faSwyllys rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 170130a5e8faSwyllys (void *)&format, NULL); 170230a5e8faSwyllys if (rv == KMF_OK) { 170330a5e8faSwyllys storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR; 170430a5e8faSwyllys storeattrs[i].pValue = &format; 170530a5e8faSwyllys storeattrs[i].valueLen = sizeof (format); 170630a5e8faSwyllys i++; 170730a5e8faSwyllys } 170830a5e8faSwyllys 170930a5e8faSwyllys rv = OpenSSL_StoreKey(handle, i, storeattrs); 171030a5e8faSwyllys } 171199ebb4caSwyllys 171299ebb4caSwyllys cleanup: 1713300fdee2SAndy Fiddaman if (eValue_bn != NULL) 1714300fdee2SAndy Fiddaman BN_free(eValue_bn); 1715300fdee2SAndy Fiddaman 171699ebb4caSwyllys if (rv != KMF_OK) { 171799ebb4caSwyllys if (eprikey != NULL) 171899ebb4caSwyllys EVP_PKEY_free(eprikey); 171999ebb4caSwyllys 172099ebb4caSwyllys if (epubkey != NULL) 172199ebb4caSwyllys EVP_PKEY_free(epubkey); 172299ebb4caSwyllys 172399ebb4caSwyllys if (pubkey->keylabel) { 172499ebb4caSwyllys free(pubkey->keylabel); 172599ebb4caSwyllys pubkey->keylabel = NULL; 172699ebb4caSwyllys } 172799ebb4caSwyllys 172899ebb4caSwyllys if (privkey->keylabel) { 172999ebb4caSwyllys free(privkey->keylabel); 173099ebb4caSwyllys privkey->keylabel = NULL; 173199ebb4caSwyllys } 173299ebb4caSwyllys 173399ebb4caSwyllys pubkey->keyp = NULL; 173499ebb4caSwyllys privkey->keyp = NULL; 173599ebb4caSwyllys } 173699ebb4caSwyllys 173799ebb4caSwyllys if (sslPrivKey) 173899ebb4caSwyllys RSA_free(sslPrivKey); 173999ebb4caSwyllys 174099ebb4caSwyllys if (sslDSAKey) 174199ebb4caSwyllys DSA_free(sslDSAKey); 174299ebb4caSwyllys 174399ebb4caSwyllys if (out != NULL) 174499ebb4caSwyllys (void) BIO_free(out); 174599ebb4caSwyllys 174699ebb4caSwyllys return (rv); 174799ebb4caSwyllys } 174899ebb4caSwyllys 1749e65e5c2dSWyllys Ingersoll /* 1750e65e5c2dSWyllys Ingersoll * Make sure the BN conversion is properly padded with 0x00 1751e65e5c2dSWyllys Ingersoll * bytes. If not, signature verification for DSA signatures 1752e65e5c2dSWyllys Ingersoll * may fail in the case where the bignum value does not use 1753e65e5c2dSWyllys Ingersoll * all of the bits. 1754e65e5c2dSWyllys Ingersoll */ 1755e65e5c2dSWyllys Ingersoll static int 1756300fdee2SAndy Fiddaman fixbnlen(const BIGNUM *bn, unsigned char *buf, int len) { 1757e65e5c2dSWyllys Ingersoll int bytes = len - BN_num_bytes(bn); 17582c9a247fSWyllys Ingersoll 17592c9a247fSWyllys Ingersoll /* prepend with leading 0x00 if necessary */ 1760e65e5c2dSWyllys Ingersoll while (bytes-- > 0) 1761e65e5c2dSWyllys Ingersoll *buf++ = 0; 1762e65e5c2dSWyllys Ingersoll 17632c9a247fSWyllys Ingersoll (void) BN_bn2bin(bn, buf); 17642c9a247fSWyllys Ingersoll /* 17652c9a247fSWyllys Ingersoll * Return the desired length since we prepended it 17662c9a247fSWyllys Ingersoll * with the necessary 0x00 padding. 17672c9a247fSWyllys Ingersoll */ 17682c9a247fSWyllys Ingersoll return (len); 1769e65e5c2dSWyllys Ingersoll } 1770e65e5c2dSWyllys Ingersoll 177199ebb4caSwyllys KMF_RETURN 177299ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, 177399ebb4caSwyllys KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output) 177499ebb4caSwyllys { 177599ebb4caSwyllys KMF_RETURN ret = KMF_OK; 177699ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 177799ebb4caSwyllys KMF_ALGORITHM_INDEX AlgId; 1778300fdee2SAndy Fiddaman EVP_MD_CTX *ctx; 177999ebb4caSwyllys const EVP_MD *md; 178002744e81Swyllys 178199ebb4caSwyllys if (key == NULL || AlgOID == NULL || 178299ebb4caSwyllys tobesigned == NULL || output == NULL || 178399ebb4caSwyllys tobesigned->Data == NULL || 178499ebb4caSwyllys output->Data == NULL) 178599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 178699ebb4caSwyllys 178799ebb4caSwyllys /* Map the OID to an OpenSSL algorithm */ 178830a5e8faSwyllys AlgId = x509_algoid_to_algid(AlgOID); 178999ebb4caSwyllys if (AlgId == KMF_ALGID_NONE) 1790e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM); 179199ebb4caSwyllys 179299ebb4caSwyllys if (key->keyalg == KMF_RSA) { 179399ebb4caSwyllys EVP_PKEY *pkey = (EVP_PKEY *)key->keyp; 179499ebb4caSwyllys uchar_t *p; 179502744e81Swyllys int len; 1796553e44ceSAndrew Stormont switch (AlgId) { 1797553e44ceSAndrew Stormont #ifndef OPENSSL_NO_MD5 1798553e44ceSAndrew Stormont case KMF_ALGID_MD5WithRSA: 179999ebb4caSwyllys md = EVP_md5(); 1800553e44ceSAndrew Stormont break; 1801553e44ceSAndrew Stormont #endif 1802553e44ceSAndrew Stormont #ifndef OPENSSL_NO_SHA 1803553e44ceSAndrew Stormont case KMF_ALGID_SHA1WithRSA: 180499ebb4caSwyllys md = EVP_sha1(); 1805553e44ceSAndrew Stormont break; 1806553e44ceSAndrew Stormont #endif 1807553e44ceSAndrew Stormont #ifndef OPENSSL_NO_SHA256 1808553e44ceSAndrew Stormont case KMF_ALGID_SHA256WithRSA: 1809e65e5c2dSWyllys Ingersoll md = EVP_sha256(); 1810553e44ceSAndrew Stormont break; 1811553e44ceSAndrew Stormont #endif 1812553e44ceSAndrew Stormont #ifndef OPENSSL_NO_SHA512 1813553e44ceSAndrew Stormont case KMF_ALGID_SHA384WithRSA: 1814e65e5c2dSWyllys Ingersoll md = EVP_sha384(); 1815553e44ceSAndrew Stormont break; 1816553e44ceSAndrew Stormont case KMF_ALGID_SHA512WithRSA: 1817e65e5c2dSWyllys Ingersoll md = EVP_sha512(); 1818553e44ceSAndrew Stormont break; 1819553e44ceSAndrew Stormont #endif 1820553e44ceSAndrew Stormont case KMF_ALGID_RSA: 182102744e81Swyllys md = NULL; 1822553e44ceSAndrew Stormont break; 1823553e44ceSAndrew Stormont default: 1824e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM); 1825553e44ceSAndrew Stormont } 182699ebb4caSwyllys 182702744e81Swyllys if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) { 182802744e81Swyllys RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey); 182999ebb4caSwyllys 183002744e81Swyllys p = output->Data; 183102744e81Swyllys if ((len = RSA_private_encrypt(tobesigned->Length, 183202744e81Swyllys tobesigned->Data, p, rsa, 183302744e81Swyllys RSA_PKCS1_PADDING)) <= 0) { 183402744e81Swyllys SET_ERROR(kmfh, ERR_get_error()); 183502744e81Swyllys ret = KMF_ERR_INTERNAL; 183602744e81Swyllys } 183702744e81Swyllys output->Length = len; 183802744e81Swyllys } else { 1839300fdee2SAndy Fiddaman if ((ctx = EVP_MD_CTX_new()) == NULL) 1840300fdee2SAndy Fiddaman return (KMF_ERR_MEMORY); 1841300fdee2SAndy Fiddaman (void) EVP_SignInit_ex(ctx, md, NULL); 1842300fdee2SAndy Fiddaman (void) EVP_SignUpdate(ctx, tobesigned->Data, 184399ebb4caSwyllys (uint32_t)tobesigned->Length); 184499ebb4caSwyllys len = (uint32_t)output->Length; 184599ebb4caSwyllys p = output->Data; 1846300fdee2SAndy Fiddaman if (!EVP_SignFinal(ctx, p, (uint32_t *)&len, pkey)) { 184799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 184802744e81Swyllys len = 0; 184902744e81Swyllys ret = KMF_ERR_INTERNAL; 185099ebb4caSwyllys } 185199ebb4caSwyllys output->Length = len; 1852300fdee2SAndy Fiddaman EVP_MD_CTX_free(ctx); 185302744e81Swyllys } 185499ebb4caSwyllys } else if (key->keyalg == KMF_DSA) { 185599ebb4caSwyllys DSA *dsa = EVP_PKEY_get1_DSA(key->keyp); 185699ebb4caSwyllys 185799ebb4caSwyllys uchar_t hash[EVP_MAX_MD_SIZE]; 185899ebb4caSwyllys uint32_t hashlen; 185999ebb4caSwyllys DSA_SIG *dsasig; 186099ebb4caSwyllys 1861e65e5c2dSWyllys Ingersoll if (AlgId == KMF_ALGID_DSA || 1862e65e5c2dSWyllys Ingersoll AlgId == KMF_ALGID_SHA1WithDSA) 1863e65e5c2dSWyllys Ingersoll md = EVP_sha1(); 1864e65e5c2dSWyllys Ingersoll else if (AlgId == KMF_ALGID_SHA256WithDSA) 1865e65e5c2dSWyllys Ingersoll md = EVP_sha256(); 1866e65e5c2dSWyllys Ingersoll else /* Bad algorithm */ 1867e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM); 1868e65e5c2dSWyllys Ingersoll 186999ebb4caSwyllys /* 187099ebb4caSwyllys * OpenSSL EVP_Sign operation automatically converts to 187199ebb4caSwyllys * ASN.1 output so we do the operations separately so we 187299ebb4caSwyllys * are assured of NOT getting ASN.1 output returned. 187399ebb4caSwyllys * KMF does not want ASN.1 encoded results because 187499ebb4caSwyllys * not all mechanisms return ASN.1 encodings (PKCS#11 187599ebb4caSwyllys * and NSS return raw signature data). 187699ebb4caSwyllys */ 1877300fdee2SAndy Fiddaman if ((ctx = EVP_MD_CTX_new()) == NULL) 1878300fdee2SAndy Fiddaman return (KMF_ERR_MEMORY); 1879300fdee2SAndy Fiddaman (void) EVP_DigestInit_ex(ctx, md, NULL); 1880300fdee2SAndy Fiddaman (void) EVP_DigestUpdate(ctx, tobesigned->Data, 188199ebb4caSwyllys tobesigned->Length); 1882300fdee2SAndy Fiddaman (void) EVP_DigestFinal_ex(ctx, hash, &hashlen); 188399ebb4caSwyllys 1884e65e5c2dSWyllys Ingersoll /* Only sign first 20 bytes for SHA2 */ 1885e65e5c2dSWyllys Ingersoll if (AlgId == KMF_ALGID_SHA256WithDSA) 1886e65e5c2dSWyllys Ingersoll hashlen = 20; 188799ebb4caSwyllys dsasig = DSA_do_sign(hash, hashlen, dsa); 188899ebb4caSwyllys if (dsasig != NULL) { 188999ebb4caSwyllys int i; 1890300fdee2SAndy Fiddaman const BIGNUM *r, *s; 1891300fdee2SAndy Fiddaman 1892300fdee2SAndy Fiddaman DSA_SIG_get0(dsasig, &r, &s); 1893300fdee2SAndy Fiddaman output->Length = i = fixbnlen(r, output->Data, 1894e65e5c2dSWyllys Ingersoll hashlen); 18952c9a247fSWyllys Ingersoll 1896300fdee2SAndy Fiddaman output->Length += fixbnlen(s, &output->Data[i], 1897e65e5c2dSWyllys Ingersoll hashlen); 18982c9a247fSWyllys Ingersoll 189999ebb4caSwyllys DSA_SIG_free(dsasig); 190099ebb4caSwyllys } else { 190199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 190299ebb4caSwyllys } 1903300fdee2SAndy Fiddaman EVP_MD_CTX_free(ctx); 190499ebb4caSwyllys } else { 190599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 190699ebb4caSwyllys } 190799ebb4caSwyllys cleanup: 190899ebb4caSwyllys return (ret); 190999ebb4caSwyllys } 191099ebb4caSwyllys 191199ebb4caSwyllys KMF_RETURN 191299ebb4caSwyllys /*ARGSUSED*/ 191330a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle, 191430a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 191599ebb4caSwyllys { 191699ebb4caSwyllys KMF_RETURN rv = KMF_OK; 191730a5e8faSwyllys KMF_KEY_HANDLE *key; 191830a5e8faSwyllys boolean_t destroy = B_TRUE; 191930a5e8faSwyllys 192030a5e8faSwyllys key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 192199ebb4caSwyllys if (key == NULL || key->keyp == NULL) 192299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 192399ebb4caSwyllys 192430a5e8faSwyllys rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr, 192530a5e8faSwyllys (void *)&destroy, NULL); 192630a5e8faSwyllys if (rv != KMF_OK) { 192730a5e8faSwyllys /* "destroy" is optional. Default is TRUE */ 192830a5e8faSwyllys rv = KMF_OK; 192930a5e8faSwyllys } 193030a5e8faSwyllys 193199ebb4caSwyllys if (key->keyclass != KMF_ASYM_PUB && 193299ebb4caSwyllys key->keyclass != KMF_ASYM_PRI && 193399ebb4caSwyllys key->keyclass != KMF_SYMMETRIC) 193499ebb4caSwyllys return (KMF_ERR_BAD_KEY_CLASS); 193599ebb4caSwyllys 193699ebb4caSwyllys if (key->keyclass == KMF_SYMMETRIC) { 193730a5e8faSwyllys kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp); 193899ebb4caSwyllys key->keyp = NULL; 193999ebb4caSwyllys } else { 194099ebb4caSwyllys if (key->keyp != NULL) { 194199ebb4caSwyllys EVP_PKEY_free(key->keyp); 194299ebb4caSwyllys key->keyp = NULL; 194399ebb4caSwyllys } 194499ebb4caSwyllys } 194599ebb4caSwyllys 194699ebb4caSwyllys if (key->keylabel != NULL) { 194799ebb4caSwyllys EVP_PKEY *pkey = NULL; 194899ebb4caSwyllys /* If the file exists, make sure it is a proper key. */ 194999ebb4caSwyllys pkey = openssl_load_key(handle, key->keylabel); 195099ebb4caSwyllys if (pkey == NULL) { 19515b3e1433Swyllys if (key->keylabel != NULL) { 195299ebb4caSwyllys free(key->keylabel); 195399ebb4caSwyllys key->keylabel = NULL; 19545b3e1433Swyllys } 195599ebb4caSwyllys return (KMF_ERR_KEY_NOT_FOUND); 195699ebb4caSwyllys } 195799ebb4caSwyllys EVP_PKEY_free(pkey); 195899ebb4caSwyllys 195999ebb4caSwyllys if (destroy) { 196099ebb4caSwyllys if (unlink(key->keylabel) != 0) { 196199ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 196299ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 196399ebb4caSwyllys rv = KMF_ERR_INTERNAL; 196499ebb4caSwyllys } 196599ebb4caSwyllys } 196699ebb4caSwyllys if (key->keylabel != NULL) { 196799ebb4caSwyllys free(key->keylabel); 196899ebb4caSwyllys key->keylabel = NULL; 196999ebb4caSwyllys } 197099ebb4caSwyllys } 197199ebb4caSwyllys return (rv); 197299ebb4caSwyllys } 197399ebb4caSwyllys 197499ebb4caSwyllys KMF_RETURN 197599ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr) 197699ebb4caSwyllys { 197799ebb4caSwyllys KMF_RETURN ret = KMF_OK; 197899ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 197999ebb4caSwyllys char str[256]; /* OpenSSL needs at least 120 byte buffer */ 198099ebb4caSwyllys 198199ebb4caSwyllys ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str)); 198299ebb4caSwyllys if (strlen(str)) { 198399ebb4caSwyllys *msgstr = (char *)strdup(str); 198499ebb4caSwyllys if ((*msgstr) == NULL) 198599ebb4caSwyllys ret = KMF_ERR_MEMORY; 198699ebb4caSwyllys } else { 198799ebb4caSwyllys *msgstr = NULL; 198899ebb4caSwyllys } 198999ebb4caSwyllys 199099ebb4caSwyllys return (ret); 199199ebb4caSwyllys } 199299ebb4caSwyllys 199399ebb4caSwyllys static int 199499ebb4caSwyllys ext2NID(int kmfext) 199599ebb4caSwyllys { 199699ebb4caSwyllys switch (kmfext) { 199799ebb4caSwyllys case KMF_X509_EXT_KEY_USAGE: 199899ebb4caSwyllys return (NID_key_usage); 199999ebb4caSwyllys case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD: 200099ebb4caSwyllys return (NID_private_key_usage_period); 200199ebb4caSwyllys case KMF_X509_EXT_CERT_POLICIES: 200299ebb4caSwyllys return (NID_certificate_policies); 200399ebb4caSwyllys case KMF_X509_EXT_SUBJ_ALTNAME: 200499ebb4caSwyllys return (NID_subject_alt_name); 200599ebb4caSwyllys case KMF_X509_EXT_ISSUER_ALTNAME: 200699ebb4caSwyllys return (NID_issuer_alt_name); 200799ebb4caSwyllys case KMF_X509_EXT_BASIC_CONSTRAINTS: 200899ebb4caSwyllys return (NID_basic_constraints); 200999ebb4caSwyllys case KMF_X509_EXT_EXT_KEY_USAGE: 201099ebb4caSwyllys return (NID_ext_key_usage); 201199ebb4caSwyllys case KMF_X509_EXT_AUTH_KEY_ID: 201299ebb4caSwyllys return (NID_authority_key_identifier); 201399ebb4caSwyllys case KMF_X509_EXT_CRL_DIST_POINTS: 201499ebb4caSwyllys return (NID_crl_distribution_points); 201599ebb4caSwyllys case KMF_X509_EXT_SUBJ_KEY_ID: 201699ebb4caSwyllys return (NID_subject_key_identifier); 201799ebb4caSwyllys case KMF_X509_EXT_POLICY_MAPPINGS: 201899ebb4caSwyllys return (OBJ_sn2nid("policyMappings")); 201999ebb4caSwyllys case KMF_X509_EXT_NAME_CONSTRAINTS: 202099ebb4caSwyllys return (OBJ_sn2nid("nameConstraints")); 202199ebb4caSwyllys case KMF_X509_EXT_POLICY_CONSTRAINTS: 202299ebb4caSwyllys return (OBJ_sn2nid("policyConstraints")); 202399ebb4caSwyllys case KMF_X509_EXT_INHIBIT_ANY_POLICY: 202499ebb4caSwyllys return (OBJ_sn2nid("inhibitAnyPolicy")); 202599ebb4caSwyllys case KMF_X509_EXT_FRESHEST_CRL: 202699ebb4caSwyllys return (OBJ_sn2nid("freshestCRL")); 202799ebb4caSwyllys default: 202899ebb4caSwyllys return (NID_undef); 202999ebb4caSwyllys } 203099ebb4caSwyllys } 203199ebb4caSwyllys 203299ebb4caSwyllys KMF_RETURN 203399ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert, 203499ebb4caSwyllys KMF_PRINTABLE_ITEM flag, char *resultStr) 203599ebb4caSwyllys { 203699ebb4caSwyllys KMF_RETURN ret = KMF_OK; 203799ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 203899ebb4caSwyllys X509 *xcert = NULL; 203999ebb4caSwyllys unsigned char *outbuf = NULL; 204099ebb4caSwyllys unsigned char *outbuf_p; 204199ebb4caSwyllys int j; 204299ebb4caSwyllys int ext_index, nid, len; 204399ebb4caSwyllys BIO *mem = NULL; 204470f9559bSTheo Schlossnagle STACK_OF(OPENSSL_STRING) *emlst = NULL; 204599ebb4caSwyllys X509_EXTENSION *ex; 204699ebb4caSwyllys 204799ebb4caSwyllys if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) { 204899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 204999ebb4caSwyllys } 205099ebb4caSwyllys 205199ebb4caSwyllys /* copy cert data to outbuf */ 205299ebb4caSwyllys outbuf = malloc(pcert->Length); 205399ebb4caSwyllys if (outbuf == NULL) { 205499ebb4caSwyllys return (KMF_ERR_MEMORY); 205599ebb4caSwyllys } 205699ebb4caSwyllys (void) memcpy(outbuf, pcert->Data, pcert->Length); 205799ebb4caSwyllys 205899ebb4caSwyllys outbuf_p = outbuf; /* use a temp pointer; required by openssl */ 205999ebb4caSwyllys xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length); 206099ebb4caSwyllys if (xcert == NULL) { 206199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 206299ebb4caSwyllys ret = KMF_ERR_ENCODING; 206399ebb4caSwyllys goto out; 206499ebb4caSwyllys } 206599ebb4caSwyllys 206699ebb4caSwyllys mem = BIO_new(BIO_s_mem()); 206799ebb4caSwyllys if (mem == NULL) { 206899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 206999ebb4caSwyllys ret = KMF_ERR_MEMORY; 207099ebb4caSwyllys goto out; 207199ebb4caSwyllys } 207299ebb4caSwyllys 207399ebb4caSwyllys switch (flag) { 207499ebb4caSwyllys case KMF_CERT_ISSUER: 207599ebb4caSwyllys (void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0, 207699ebb4caSwyllys XN_FLAG_SEP_CPLUS_SPC); 207799ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 207899ebb4caSwyllys break; 207999ebb4caSwyllys 208099ebb4caSwyllys case KMF_CERT_SUBJECT: 208199ebb4caSwyllys (void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0, 208299ebb4caSwyllys XN_FLAG_SEP_CPLUS_SPC); 208399ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 208499ebb4caSwyllys break; 208599ebb4caSwyllys 208699ebb4caSwyllys case KMF_CERT_VERSION: 2087300fdee2SAndy Fiddaman (void) snprintf(resultStr, KMF_CERT_PRINTABLE_LEN, 2088300fdee2SAndy Fiddaman "%ld", X509_get_version(xcert)); 208999ebb4caSwyllys len = strlen(resultStr); 209099ebb4caSwyllys break; 209199ebb4caSwyllys 209299ebb4caSwyllys case KMF_CERT_SERIALNUM: 209399ebb4caSwyllys if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) { 209499ebb4caSwyllys (void) strcpy(resultStr, "0x"); 209599ebb4caSwyllys len = BIO_gets(mem, &resultStr[2], 209699ebb4caSwyllys KMF_CERT_PRINTABLE_LEN - 2); 209799ebb4caSwyllys } 209899ebb4caSwyllys break; 209999ebb4caSwyllys 210099ebb4caSwyllys case KMF_CERT_NOTBEFORE: 2101300fdee2SAndy Fiddaman (void) ASN1_TIME_print(mem, X509_getm_notBefore(xcert)); 210299ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 210399ebb4caSwyllys break; 210499ebb4caSwyllys 210599ebb4caSwyllys case KMF_CERT_NOTAFTER: 2106300fdee2SAndy Fiddaman (void) ASN1_TIME_print(mem, X509_getm_notAfter(xcert)); 210799ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 210899ebb4caSwyllys break; 210999ebb4caSwyllys 211099ebb4caSwyllys case KMF_CERT_PUBKEY_DATA: 211199ebb4caSwyllys { 2112300fdee2SAndy Fiddaman RSA *rsa; 2113300fdee2SAndy Fiddaman DSA *dsa; 2114300fdee2SAndy Fiddaman 211599ebb4caSwyllys EVP_PKEY *pkey = X509_get_pubkey(xcert); 211699ebb4caSwyllys if (pkey == NULL) { 211799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 211899ebb4caSwyllys ret = KMF_ERR_ENCODING; 211999ebb4caSwyllys goto out; 212099ebb4caSwyllys } 212199ebb4caSwyllys 2122300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) { 212399ebb4caSwyllys (void) BIO_printf(mem, 212499ebb4caSwyllys "RSA Public Key: (%d bit)\n", 2125300fdee2SAndy Fiddaman RSA_bits(rsa)); 2126300fdee2SAndy Fiddaman (void) RSA_print(mem, rsa, 0); 2127300fdee2SAndy Fiddaman 2128300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) { 212999ebb4caSwyllys (void) BIO_printf(mem, 213099ebb4caSwyllys "%12sDSA Public Key:\n", ""); 2131300fdee2SAndy Fiddaman (void) DSA_print(mem, dsa, 0); 213299ebb4caSwyllys } else { 213399ebb4caSwyllys (void) BIO_printf(mem, 213499ebb4caSwyllys "%12sUnknown Public Key:\n", ""); 213599ebb4caSwyllys } 213699ebb4caSwyllys (void) BIO_printf(mem, "\n"); 213799ebb4caSwyllys EVP_PKEY_free(pkey); 213899ebb4caSwyllys } 213999ebb4caSwyllys len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 214099ebb4caSwyllys break; 214199ebb4caSwyllys case KMF_CERT_SIGNATURE_ALG: 214299ebb4caSwyllys case KMF_CERT_PUBKEY_ALG: 2143300fdee2SAndy Fiddaman { 2144553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 2145300fdee2SAndy Fiddaman ASN1_OBJECT *alg = NULL; 2146300fdee2SAndy Fiddaman #else 2147300fdee2SAndy Fiddaman const ASN1_OBJECT *alg = NULL; 2148300fdee2SAndy Fiddaman #endif 2149300fdee2SAndy Fiddaman 215099ebb4caSwyllys if (flag == KMF_CERT_SIGNATURE_ALG) { 2151553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 2152300fdee2SAndy Fiddaman alg = xcert->sig_alg->algorithm; 2153300fdee2SAndy Fiddaman #else 2154300fdee2SAndy Fiddaman const X509_ALGOR *sig_alg = NULL; 2155300fdee2SAndy Fiddaman 2156300fdee2SAndy Fiddaman X509_get0_signature(NULL, &sig_alg, xcert); 2157300fdee2SAndy Fiddaman if (sig_alg != NULL) 2158300fdee2SAndy Fiddaman X509_ALGOR_get0(&alg, NULL, NULL, 2159300fdee2SAndy Fiddaman sig_alg); 2160300fdee2SAndy Fiddaman #endif 216199ebb4caSwyllys } else { 2162553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 2163300fdee2SAndy Fiddaman alg = xcert->cert_info->key->algor->algorithm; 2164300fdee2SAndy Fiddaman #else 2165300fdee2SAndy Fiddaman X509_PUBKEY *key = X509_get_X509_PUBKEY(xcert); 2166300fdee2SAndy Fiddaman 2167300fdee2SAndy Fiddaman if (key != NULL) 2168300fdee2SAndy Fiddaman (void) X509_PUBKEY_get0_param( 2169300fdee2SAndy Fiddaman (ASN1_OBJECT **)&alg, NULL, 0, 2170300fdee2SAndy Fiddaman NULL, key); 2171300fdee2SAndy Fiddaman #endif 217299ebb4caSwyllys } 217399ebb4caSwyllys 2174300fdee2SAndy Fiddaman if (alg == NULL) 2175300fdee2SAndy Fiddaman len = -1; 2176300fdee2SAndy Fiddaman else if ((len = i2a_ASN1_OBJECT(mem, alg)) > 0) 217799ebb4caSwyllys len = BIO_read(mem, resultStr, 217899ebb4caSwyllys KMF_CERT_PRINTABLE_LEN); 217999ebb4caSwyllys } 218099ebb4caSwyllys break; 218199ebb4caSwyllys 218299ebb4caSwyllys case KMF_CERT_EMAIL: 218399ebb4caSwyllys emlst = X509_get1_email(xcert); 218470f9559bSTheo Schlossnagle for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) 218570f9559bSTheo Schlossnagle (void) BIO_printf(mem, "%s\n", 218670f9559bSTheo Schlossnagle sk_OPENSSL_STRING_value(emlst, j)); 218799ebb4caSwyllys 218899ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 218999ebb4caSwyllys X509_email_free(emlst); 219099ebb4caSwyllys break; 219199ebb4caSwyllys case KMF_X509_EXT_ISSUER_ALTNAME: 219299ebb4caSwyllys case KMF_X509_EXT_SUBJ_ALTNAME: 219399ebb4caSwyllys case KMF_X509_EXT_KEY_USAGE: 219499ebb4caSwyllys case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD: 219599ebb4caSwyllys case KMF_X509_EXT_CERT_POLICIES: 219699ebb4caSwyllys case KMF_X509_EXT_BASIC_CONSTRAINTS: 219799ebb4caSwyllys case KMF_X509_EXT_NAME_CONSTRAINTS: 219899ebb4caSwyllys case KMF_X509_EXT_POLICY_CONSTRAINTS: 219999ebb4caSwyllys case KMF_X509_EXT_EXT_KEY_USAGE: 220099ebb4caSwyllys case KMF_X509_EXT_INHIBIT_ANY_POLICY: 220199ebb4caSwyllys case KMF_X509_EXT_AUTH_KEY_ID: 220299ebb4caSwyllys case KMF_X509_EXT_SUBJ_KEY_ID: 220399ebb4caSwyllys case KMF_X509_EXT_POLICY_MAPPINGS: 220499ebb4caSwyllys case KMF_X509_EXT_CRL_DIST_POINTS: 220599ebb4caSwyllys case KMF_X509_EXT_FRESHEST_CRL: 220699ebb4caSwyllys nid = ext2NID(flag); 220799ebb4caSwyllys if (nid == NID_undef) { 220899ebb4caSwyllys ret = KMF_ERR_EXTENSION_NOT_FOUND; 220999ebb4caSwyllys goto out; 221099ebb4caSwyllys } 221199ebb4caSwyllys 2212300fdee2SAndy Fiddaman ext_index = X509_get_ext_by_NID(xcert, nid, -1); 221399ebb4caSwyllys if (ext_index == -1) { 221499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 221599ebb4caSwyllys 221699ebb4caSwyllys ret = KMF_ERR_EXTENSION_NOT_FOUND; 221799ebb4caSwyllys goto out; 221899ebb4caSwyllys } 2219300fdee2SAndy Fiddaman ex = X509_get_ext(xcert, ext_index); 222099ebb4caSwyllys 222199ebb4caSwyllys (void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex)); 222299ebb4caSwyllys 222399ebb4caSwyllys if (BIO_printf(mem, ": %s\n", 222430a5e8faSwyllys X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) { 222599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 222699ebb4caSwyllys ret = KMF_ERR_ENCODING; 222799ebb4caSwyllys goto out; 222899ebb4caSwyllys } 222999ebb4caSwyllys if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) { 223099ebb4caSwyllys (void) BIO_printf(mem, "%*s", 4, ""); 2231300fdee2SAndy Fiddaman (void) ASN1_STRING_print(mem, 2232300fdee2SAndy Fiddaman X509_EXTENSION_get_data(ex)); 223399ebb4caSwyllys } 223499ebb4caSwyllys if (BIO_write(mem, "\n", 1) <= 0) { 223599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 223699ebb4caSwyllys ret = KMF_ERR_ENCODING; 223799ebb4caSwyllys goto out; 223899ebb4caSwyllys } 223999ebb4caSwyllys len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 224099ebb4caSwyllys } 224199ebb4caSwyllys if (len <= 0) { 224299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 224399ebb4caSwyllys ret = KMF_ERR_ENCODING; 224499ebb4caSwyllys } 224599ebb4caSwyllys 224699ebb4caSwyllys out: 224799ebb4caSwyllys if (outbuf != NULL) { 224899ebb4caSwyllys free(outbuf); 224999ebb4caSwyllys } 225099ebb4caSwyllys 225199ebb4caSwyllys if (xcert != NULL) { 225299ebb4caSwyllys X509_free(xcert); 225399ebb4caSwyllys } 225499ebb4caSwyllys 225599ebb4caSwyllys if (mem != NULL) { 225699ebb4caSwyllys (void) BIO_free(mem); 225799ebb4caSwyllys } 225899ebb4caSwyllys 225999ebb4caSwyllys return (ret); 226099ebb4caSwyllys } 226130a5e8faSwyllys 226299ebb4caSwyllys KMF_RETURN 226399ebb4caSwyllys /*ARGSUSED*/ 226430a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr, 226530a5e8faSwyllys KMF_ATTRIBUTE *attrlist) 226699ebb4caSwyllys { 226799ebb4caSwyllys KMF_RETURN rv = KMF_OK; 226830a5e8faSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL; 226930a5e8faSwyllys KMF_KEY_CLASS keyclass = KMF_ASYM_PRI; 227030a5e8faSwyllys KMF_KEY_HANDLE *key = NULL; 227130a5e8faSwyllys uint32_t numkeys = 1; /* 1 key only */ 227230a5e8faSwyllys char *dirpath = NULL; 227330a5e8faSwyllys char *keyfile = NULL; 227430a5e8faSwyllys KMF_ATTRIBUTE new_attrlist[16]; 227530a5e8faSwyllys int i = 0; 227699ebb4caSwyllys 227799ebb4caSwyllys /* 227899ebb4caSwyllys * This is really just a FindKey operation, reuse the 227999ebb4caSwyllys * FindKey function. 228099ebb4caSwyllys */ 228130a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 228230a5e8faSwyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 228330a5e8faSwyllys i++; 228499ebb4caSwyllys 228530a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 228630a5e8faSwyllys KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t)); 228730a5e8faSwyllys i++; 228899ebb4caSwyllys 228930a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 229030a5e8faSwyllys KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass)); 229130a5e8faSwyllys i++; 229230a5e8faSwyllys 229330a5e8faSwyllys key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 229430a5e8faSwyllys if (key == NULL) { 229530a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 229630a5e8faSwyllys } else { 229730a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 229830a5e8faSwyllys KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE)); 229930a5e8faSwyllys i++; 230030a5e8faSwyllys } 230130a5e8faSwyllys 230230a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 230330a5e8faSwyllys if (dirpath != NULL) { 230430a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 230530a5e8faSwyllys KMF_DIRPATH_ATTR, dirpath, strlen(dirpath)); 230630a5e8faSwyllys i++; 230730a5e8faSwyllys } 230830a5e8faSwyllys 230930a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 231030a5e8faSwyllys if (keyfile == NULL) 231130a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 231230a5e8faSwyllys else { 231330a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 231430a5e8faSwyllys KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile)); 231530a5e8faSwyllys i++; 231630a5e8faSwyllys } 231730a5e8faSwyllys 231830a5e8faSwyllys rv = OpenSSL_FindKey(handle, i, new_attrlist); 231999ebb4caSwyllys return (rv); 232099ebb4caSwyllys } 232199ebb4caSwyllys 232299ebb4caSwyllys KMF_RETURN 232399ebb4caSwyllys /*ARGSUSED*/ 232499ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, 232599ebb4caSwyllys KMF_OID *AlgOID, KMF_DATA *ciphertext, 232699ebb4caSwyllys KMF_DATA *output) 232799ebb4caSwyllys { 232899ebb4caSwyllys KMF_RETURN ret = KMF_OK; 232999ebb4caSwyllys RSA *rsa = NULL; 233099ebb4caSwyllys unsigned int in_len = 0, out_len = 0; 233199ebb4caSwyllys unsigned int total_decrypted = 0, modulus_len = 0; 233299ebb4caSwyllys uint8_t *in_data, *out_data; 233399ebb4caSwyllys int i, blocks; 233499ebb4caSwyllys 233599ebb4caSwyllys if (key == NULL || AlgOID == NULL || 233699ebb4caSwyllys ciphertext == NULL || output == NULL || 233799ebb4caSwyllys ciphertext->Data == NULL || 233899ebb4caSwyllys output->Data == NULL) 233999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 234099ebb4caSwyllys 234199ebb4caSwyllys if (key->keyalg == KMF_RSA) { 234299ebb4caSwyllys rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp); 234399ebb4caSwyllys modulus_len = RSA_size(rsa); 234499ebb4caSwyllys } else { 234599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 234699ebb4caSwyllys } 234799ebb4caSwyllys 234899ebb4caSwyllys blocks = ciphertext->Length/modulus_len; 234999ebb4caSwyllys out_data = output->Data; 235099ebb4caSwyllys in_data = ciphertext->Data; 235199ebb4caSwyllys out_len = modulus_len - 11; 235299ebb4caSwyllys in_len = modulus_len; 235399ebb4caSwyllys 235499ebb4caSwyllys for (i = 0; i < blocks; i++) { 235599ebb4caSwyllys out_len = RSA_private_decrypt(in_len, 235699ebb4caSwyllys in_data, out_data, rsa, RSA_PKCS1_PADDING); 235799ebb4caSwyllys 235899ebb4caSwyllys if (out_len == 0) { 235999ebb4caSwyllys ret = KMF_ERR_INTERNAL; 236099ebb4caSwyllys goto cleanup; 236199ebb4caSwyllys } 236299ebb4caSwyllys 236399ebb4caSwyllys out_data += out_len; 236499ebb4caSwyllys total_decrypted += out_len; 236599ebb4caSwyllys in_data += in_len; 236699ebb4caSwyllys } 236799ebb4caSwyllys 236899ebb4caSwyllys output->Length = total_decrypted; 236999ebb4caSwyllys 237099ebb4caSwyllys cleanup: 237199ebb4caSwyllys RSA_free(rsa); 237299ebb4caSwyllys if (ret != KMF_OK) 237399ebb4caSwyllys output->Length = 0; 237499ebb4caSwyllys 237599ebb4caSwyllys return (ret); 237699ebb4caSwyllys 237799ebb4caSwyllys } 237899ebb4caSwyllys 237999ebb4caSwyllys /* 238099ebb4caSwyllys * This function will create a certid from issuer_cert and user_cert. 238199ebb4caSwyllys * The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate 238299ebb4caSwyllys * certid memory after use. 238399ebb4caSwyllys */ 238499ebb4caSwyllys static KMF_RETURN 238599ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert, 238699ebb4caSwyllys const KMF_DATA *user_cert, OCSP_CERTID **certid) 238799ebb4caSwyllys { 238899ebb4caSwyllys KMF_RETURN ret = KMF_OK; 238999ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 239099ebb4caSwyllys X509 *issuer = NULL; 239199ebb4caSwyllys X509 *cert = NULL; 239299ebb4caSwyllys unsigned char *ptmp; 239399ebb4caSwyllys 239499ebb4caSwyllys if (issuer_cert == NULL || user_cert == NULL) { 239599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 239699ebb4caSwyllys } 239799ebb4caSwyllys 239899ebb4caSwyllys /* convert the DER-encoded issuer cert to an internal X509 */ 239999ebb4caSwyllys ptmp = issuer_cert->Data; 240099ebb4caSwyllys issuer = d2i_X509(NULL, (const uchar_t **)&ptmp, 240199ebb4caSwyllys issuer_cert->Length); 240299ebb4caSwyllys if (issuer == NULL) { 240399ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 240499ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_ISSUER; 240599ebb4caSwyllys goto end; 240699ebb4caSwyllys } 240799ebb4caSwyllys 240899ebb4caSwyllys /* convert the DER-encoded user cert to an internal X509 */ 240999ebb4caSwyllys ptmp = user_cert->Data; 241099ebb4caSwyllys cert = d2i_X509(NULL, (const uchar_t **)&ptmp, 241199ebb4caSwyllys user_cert->Length); 241299ebb4caSwyllys if (cert == NULL) { 241399ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 241499ebb4caSwyllys 241599ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_CERT; 241699ebb4caSwyllys goto end; 241799ebb4caSwyllys } 241899ebb4caSwyllys 241999ebb4caSwyllys /* create a CERTID */ 242099ebb4caSwyllys *certid = OCSP_cert_to_id(NULL, cert, issuer); 242199ebb4caSwyllys if (*certid == NULL) { 242299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 242399ebb4caSwyllys ret = KMF_ERR_OCSP_CERTID; 242499ebb4caSwyllys goto end; 242599ebb4caSwyllys } 242699ebb4caSwyllys 242799ebb4caSwyllys end: 242899ebb4caSwyllys if (issuer != NULL) { 242999ebb4caSwyllys X509_free(issuer); 243099ebb4caSwyllys } 243199ebb4caSwyllys 243299ebb4caSwyllys if (cert != NULL) { 243399ebb4caSwyllys X509_free(cert); 243499ebb4caSwyllys } 243599ebb4caSwyllys 243699ebb4caSwyllys return (ret); 243799ebb4caSwyllys } 243899ebb4caSwyllys 243999ebb4caSwyllys KMF_RETURN 244030a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle, 244130a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 244299ebb4caSwyllys { 244399ebb4caSwyllys KMF_RETURN ret = KMF_OK; 244499ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 244599ebb4caSwyllys OCSP_CERTID *id = NULL; 244699ebb4caSwyllys OCSP_REQUEST *req = NULL; 244799ebb4caSwyllys BIO *derbio = NULL; 244830a5e8faSwyllys char *reqfile; 244930a5e8faSwyllys KMF_DATA *issuer_cert; 245030a5e8faSwyllys KMF_DATA *user_cert; 245199ebb4caSwyllys 245230a5e8faSwyllys user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR, 245330a5e8faSwyllys attrlist, numattr); 245430a5e8faSwyllys if (user_cert == NULL) 245599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 245699ebb4caSwyllys 245730a5e8faSwyllys issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR, 245830a5e8faSwyllys attrlist, numattr); 245930a5e8faSwyllys if (issuer_cert == NULL) 246030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 246130a5e8faSwyllys 246230a5e8faSwyllys reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR, 246330a5e8faSwyllys attrlist, numattr); 246430a5e8faSwyllys if (reqfile == NULL) 246530a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 246630a5e8faSwyllys 246730a5e8faSwyllys ret = create_certid(handle, issuer_cert, user_cert, &id); 246899ebb4caSwyllys if (ret != KMF_OK) { 246999ebb4caSwyllys return (ret); 247099ebb4caSwyllys } 247199ebb4caSwyllys 247299ebb4caSwyllys /* Create an OCSP request */ 247399ebb4caSwyllys req = OCSP_REQUEST_new(); 247499ebb4caSwyllys if (req == NULL) { 247599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 247699ebb4caSwyllys ret = KMF_ERR_OCSP_CREATE_REQUEST; 247799ebb4caSwyllys goto end; 247899ebb4caSwyllys } 247999ebb4caSwyllys 248099ebb4caSwyllys if (!OCSP_request_add0_id(req, id)) { 248199ebb4caSwyllys ret = KMF_ERR_OCSP_CREATE_REQUEST; 248299ebb4caSwyllys goto end; 248399ebb4caSwyllys } 248499ebb4caSwyllys 248599ebb4caSwyllys /* Write the request to the output file with DER encoding */ 248699ebb4caSwyllys derbio = BIO_new_file(reqfile, "wb"); 248799ebb4caSwyllys if (!derbio) { 248899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 248999ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 249099ebb4caSwyllys goto end; 249199ebb4caSwyllys } 249299ebb4caSwyllys if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) { 249399ebb4caSwyllys ret = KMF_ERR_ENCODING; 249499ebb4caSwyllys } 249599ebb4caSwyllys 249699ebb4caSwyllys end: 249799ebb4caSwyllys /* 2498e65e5c2dSWyllys Ingersoll * We don't need to free "id" explicitely, because OCSP_REQUEST_free() 2499a2d4930dSDan OpenSolaris Anderson * will also deallocate certid's space. 250099ebb4caSwyllys */ 250199ebb4caSwyllys if (req != NULL) { 250299ebb4caSwyllys OCSP_REQUEST_free(req); 250399ebb4caSwyllys } 250499ebb4caSwyllys 250599ebb4caSwyllys if (derbio != NULL) { 250699ebb4caSwyllys (void) BIO_free(derbio); 250799ebb4caSwyllys } 250899ebb4caSwyllys 250999ebb4caSwyllys return (ret); 251099ebb4caSwyllys } 251199ebb4caSwyllys 251299ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */ 2513300fdee2SAndy Fiddaman static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_BASICRESP *bs) 251499ebb4caSwyllys { 251599ebb4caSwyllys int i; 251699ebb4caSwyllys unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash; 2517300fdee2SAndy Fiddaman const ASN1_OCTET_STRING *pid; 251899ebb4caSwyllys 2519553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 2520300fdee2SAndy Fiddaman OCSP_RESPID *id = bs->tbsResponseData->responderId; 2521300fdee2SAndy Fiddaman 252299ebb4caSwyllys if (id->type == V_OCSP_RESPID_NAME) 252399ebb4caSwyllys return (X509_find_by_subject(certs, id->value.byName)); 252499ebb4caSwyllys 2525300fdee2SAndy Fiddaman pid = id->value.byKey; 2526300fdee2SAndy Fiddaman #else 2527300fdee2SAndy Fiddaman const X509_NAME *pname; 2528300fdee2SAndy Fiddaman 2529300fdee2SAndy Fiddaman if (OCSP_resp_get0_id(bs, &pid, &pname) == 0) 2530300fdee2SAndy Fiddaman return (NULL); 2531300fdee2SAndy Fiddaman 2532300fdee2SAndy Fiddaman if (pname != NULL) 2533300fdee2SAndy Fiddaman return (X509_find_by_subject(certs, (X509_NAME *)pname)); 2534300fdee2SAndy Fiddaman #endif 2535300fdee2SAndy Fiddaman 253699ebb4caSwyllys /* Lookup by key hash */ 253799ebb4caSwyllys 253899ebb4caSwyllys /* If key hash isn't SHA1 length then forget it */ 2539300fdee2SAndy Fiddaman if (pid->length != SHA_DIGEST_LENGTH) 254099ebb4caSwyllys return (NULL); 254199ebb4caSwyllys 2542300fdee2SAndy Fiddaman keyhash = pid->data; 254399ebb4caSwyllys /* Calculate hash of each key and compare */ 254499ebb4caSwyllys for (i = 0; i < sk_X509_num(certs); i++) { 2545d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 254699ebb4caSwyllys X509 *x = sk_X509_value(certs, i); 25475b3e1433Swyllys /* Use pubkey_digest to get the key ID value */ 254899ebb4caSwyllys (void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL); 254999ebb4caSwyllys if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH)) 255099ebb4caSwyllys return (x); 255199ebb4caSwyllys } 255299ebb4caSwyllys return (NULL); 255399ebb4caSwyllys } 255499ebb4caSwyllys 255599ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */ 2556a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */ 255799ebb4caSwyllys static int 255899ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs, 255999ebb4caSwyllys X509_STORE *st, unsigned long flags) 256099ebb4caSwyllys { 256199ebb4caSwyllys X509 *signer; 2562300fdee2SAndy Fiddaman if ((signer = ocsp_find_signer_sk(certs, bs))) { 256399ebb4caSwyllys *psigner = signer; 256499ebb4caSwyllys return (2); 256599ebb4caSwyllys } 2566300fdee2SAndy Fiddaman 256799ebb4caSwyllys if (!(flags & OCSP_NOINTERN) && 2568300fdee2SAndy Fiddaman (signer = ocsp_find_signer_sk( 2569300fdee2SAndy Fiddaman (STACK_OF(X509) *)OCSP_resp_get0_certs(bs), bs))) { 257099ebb4caSwyllys *psigner = signer; 257199ebb4caSwyllys return (1); 257299ebb4caSwyllys } 257399ebb4caSwyllys /* Maybe lookup from store if by subject name */ 257499ebb4caSwyllys 257599ebb4caSwyllys *psigner = NULL; 257699ebb4caSwyllys return (0); 257799ebb4caSwyllys } 257899ebb4caSwyllys 257999ebb4caSwyllys /* 258099ebb4caSwyllys * This function will verify the signature of a basic response, using 258199ebb4caSwyllys * the public key from the OCSP responder certificate. 258299ebb4caSwyllys */ 258399ebb4caSwyllys static KMF_RETURN 258499ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs, 258599ebb4caSwyllys KMF_DATA *signer_cert, KMF_DATA *issuer_cert) 258699ebb4caSwyllys { 258799ebb4caSwyllys KMF_RETURN ret = KMF_OK; 258899ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 258999ebb4caSwyllys STACK_OF(X509) *cert_stack = NULL; 259099ebb4caSwyllys X509 *signer = NULL; 259199ebb4caSwyllys X509 *issuer = NULL; 2592553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 259399ebb4caSwyllys EVP_PKEY *skey = NULL; 2594300fdee2SAndy Fiddaman #else 2595300fdee2SAndy Fiddaman STACK_OF(X509) *cert_stack2 = NULL; 2596300fdee2SAndy Fiddaman #endif 259799ebb4caSwyllys unsigned char *ptmp; 259899ebb4caSwyllys 259999ebb4caSwyllys if (bs == NULL || issuer_cert == NULL) 260099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 260199ebb4caSwyllys 260299ebb4caSwyllys /* 260399ebb4caSwyllys * Find the certificate that signed the basic response. 260499ebb4caSwyllys * 260599ebb4caSwyllys * If signer_cert is not NULL, we will use that as the signer cert. 260699ebb4caSwyllys * Otherwise, we will check if the issuer cert is actually the signer. 260799ebb4caSwyllys * If we still do not find a signer, we will look for it from the 260899ebb4caSwyllys * certificate list came with the response file. 260999ebb4caSwyllys */ 261099ebb4caSwyllys if (signer_cert != NULL) { 261199ebb4caSwyllys ptmp = signer_cert->Data; 261299ebb4caSwyllys signer = d2i_X509(NULL, (const uchar_t **)&ptmp, 261399ebb4caSwyllys signer_cert->Length); 261499ebb4caSwyllys if (signer == NULL) { 261599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 261699ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_SIGNER; 261799ebb4caSwyllys goto end; 261899ebb4caSwyllys } 261999ebb4caSwyllys } else { 262099ebb4caSwyllys /* 262199ebb4caSwyllys * Convert the issuer cert into X509 and push it into a 262299ebb4caSwyllys * stack to be used by ocsp_find_signer(). 262399ebb4caSwyllys */ 262499ebb4caSwyllys ptmp = issuer_cert->Data; 262599ebb4caSwyllys issuer = d2i_X509(NULL, (const uchar_t **)&ptmp, 262699ebb4caSwyllys issuer_cert->Length); 262799ebb4caSwyllys if (issuer == NULL) { 262899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 262999ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_ISSUER; 263099ebb4caSwyllys goto end; 263199ebb4caSwyllys } 263299ebb4caSwyllys 263399ebb4caSwyllys if ((cert_stack = sk_X509_new_null()) == NULL) { 263499ebb4caSwyllys ret = KMF_ERR_INTERNAL; 263599ebb4caSwyllys goto end; 263699ebb4caSwyllys } 263799ebb4caSwyllys 2638*f810c7e5SToomas Soome if (sk_X509_push(cert_stack, issuer) == 0) { 263999ebb4caSwyllys ret = KMF_ERR_INTERNAL; 264099ebb4caSwyllys goto end; 264199ebb4caSwyllys } 264299ebb4caSwyllys 264399ebb4caSwyllys ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0); 264499ebb4caSwyllys if (!ret) { 264599ebb4caSwyllys /* can not find the signer */ 264699ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_SIGNER; 264799ebb4caSwyllys goto end; 264899ebb4caSwyllys } 264999ebb4caSwyllys } 265099ebb4caSwyllys 265199ebb4caSwyllys /* Verify the signature of the response */ 2652553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 265399ebb4caSwyllys skey = X509_get_pubkey(signer); 265499ebb4caSwyllys if (skey == NULL) { 265599ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_SIGNER; 265699ebb4caSwyllys goto end; 265799ebb4caSwyllys } 265899ebb4caSwyllys 265999ebb4caSwyllys ret = OCSP_BASICRESP_verify(bs, skey, 0); 2660300fdee2SAndy Fiddaman #else 2661300fdee2SAndy Fiddaman /* 2662300fdee2SAndy Fiddaman * Technique based on 2663300fdee2SAndy Fiddaman * https://mta.openssl.org/pipermail/openssl-users/ 2664300fdee2SAndy Fiddaman * 2017-October/006814.html 2665300fdee2SAndy Fiddaman */ 2666300fdee2SAndy Fiddaman if ((cert_stack2 = sk_X509_new_null()) == NULL) { 2667300fdee2SAndy Fiddaman ret = KMF_ERR_INTERNAL; 2668300fdee2SAndy Fiddaman goto end; 2669300fdee2SAndy Fiddaman } 2670300fdee2SAndy Fiddaman 2671300fdee2SAndy Fiddaman if (sk_X509_push(cert_stack2, signer) == NULL) { 2672300fdee2SAndy Fiddaman ret = KMF_ERR_INTERNAL; 2673300fdee2SAndy Fiddaman goto end; 2674300fdee2SAndy Fiddaman } 2675300fdee2SAndy Fiddaman 2676300fdee2SAndy Fiddaman ret = OCSP_basic_verify(bs, cert_stack2, NULL, OCSP_NOVERIFY); 2677300fdee2SAndy Fiddaman #endif 2678300fdee2SAndy Fiddaman 267999ebb4caSwyllys if (ret == 0) { 268099ebb4caSwyllys ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE; 268199ebb4caSwyllys goto end; 268299ebb4caSwyllys } 268399ebb4caSwyllys 268499ebb4caSwyllys end: 268599ebb4caSwyllys if (issuer != NULL) { 268699ebb4caSwyllys X509_free(issuer); 268799ebb4caSwyllys } 268899ebb4caSwyllys 268999ebb4caSwyllys if (signer != NULL) { 269099ebb4caSwyllys X509_free(signer); 269199ebb4caSwyllys } 269299ebb4caSwyllys 2693553e44ceSAndrew Stormont #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 269499ebb4caSwyllys if (skey != NULL) { 269599ebb4caSwyllys EVP_PKEY_free(skey); 269699ebb4caSwyllys } 2697300fdee2SAndy Fiddaman #else 2698300fdee2SAndy Fiddaman if (cert_stack2 != NULL) { 2699300fdee2SAndy Fiddaman sk_X509_free(cert_stack2); 2700300fdee2SAndy Fiddaman } 2701300fdee2SAndy Fiddaman #endif 270299ebb4caSwyllys 270399ebb4caSwyllys if (cert_stack != NULL) { 270499ebb4caSwyllys sk_X509_free(cert_stack); 270599ebb4caSwyllys } 270699ebb4caSwyllys 270799ebb4caSwyllys return (ret); 270899ebb4caSwyllys } 270999ebb4caSwyllys 271099ebb4caSwyllys KMF_RETURN 271199ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle, 271230a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 271399ebb4caSwyllys { 271499ebb4caSwyllys KMF_RETURN ret = KMF_OK; 271599ebb4caSwyllys BIO *derbio = NULL; 271699ebb4caSwyllys OCSP_RESPONSE *resp = NULL; 271799ebb4caSwyllys OCSP_BASICRESP *bs = NULL; 271899ebb4caSwyllys OCSP_CERTID *id = NULL; 271999ebb4caSwyllys OCSP_SINGLERESP *single = NULL; 272099ebb4caSwyllys ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; 272199ebb4caSwyllys int index, status, reason; 272230a5e8faSwyllys KMF_DATA *issuer_cert; 272330a5e8faSwyllys KMF_DATA *user_cert; 272430a5e8faSwyllys KMF_DATA *signer_cert; 272530a5e8faSwyllys KMF_DATA *response; 272630a5e8faSwyllys int *response_reason, *response_status, *cert_status; 272730a5e8faSwyllys boolean_t ignore_response_sign = B_FALSE; /* default is FALSE */ 272830a5e8faSwyllys uint32_t response_lifetime; 272999ebb4caSwyllys 273030a5e8faSwyllys issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR, 273130a5e8faSwyllys attrlist, numattr); 273230a5e8faSwyllys if (issuer_cert == NULL) 273399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 273499ebb4caSwyllys 273530a5e8faSwyllys user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR, 273630a5e8faSwyllys attrlist, numattr); 273730a5e8faSwyllys if (user_cert == NULL) 273899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 273930a5e8faSwyllys 274030a5e8faSwyllys response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR, 274130a5e8faSwyllys attrlist, numattr); 274230a5e8faSwyllys if (response == NULL) 274330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 274430a5e8faSwyllys 274530a5e8faSwyllys response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR, 274630a5e8faSwyllys attrlist, numattr); 274730a5e8faSwyllys if (response_status == NULL) 274830a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 274930a5e8faSwyllys 275030a5e8faSwyllys response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR, 275130a5e8faSwyllys attrlist, numattr); 275230a5e8faSwyllys if (response_reason == NULL) 275330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 275430a5e8faSwyllys 275530a5e8faSwyllys cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR, 275630a5e8faSwyllys attrlist, numattr); 275730a5e8faSwyllys if (cert_status == NULL) 275830a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 275999ebb4caSwyllys 276099ebb4caSwyllys /* Read in the response */ 276130a5e8faSwyllys derbio = BIO_new_mem_buf(response->Data, response->Length); 276299ebb4caSwyllys if (!derbio) { 276399ebb4caSwyllys ret = KMF_ERR_MEMORY; 276499ebb4caSwyllys return (ret); 276599ebb4caSwyllys } 276699ebb4caSwyllys 276799ebb4caSwyllys resp = d2i_OCSP_RESPONSE_bio(derbio, NULL); 276899ebb4caSwyllys if (resp == NULL) { 276999ebb4caSwyllys ret = KMF_ERR_OCSP_MALFORMED_RESPONSE; 277099ebb4caSwyllys goto end; 277199ebb4caSwyllys } 277299ebb4caSwyllys 277399ebb4caSwyllys /* Check the response status */ 277499ebb4caSwyllys status = OCSP_response_status(resp); 277530a5e8faSwyllys *response_status = status; 277699ebb4caSwyllys if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { 277799ebb4caSwyllys ret = KMF_ERR_OCSP_RESPONSE_STATUS; 277899ebb4caSwyllys goto end; 277999ebb4caSwyllys } 278099ebb4caSwyllys 278199ebb4caSwyllys #ifdef DEBUG 278299ebb4caSwyllys printf("Successfully checked the response file status.\n"); 278399ebb4caSwyllys #endif /* DEBUG */ 278499ebb4caSwyllys 278599ebb4caSwyllys /* Extract basic response */ 278699ebb4caSwyllys bs = OCSP_response_get1_basic(resp); 278799ebb4caSwyllys if (bs == NULL) { 278899ebb4caSwyllys ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE; 278999ebb4caSwyllys goto end; 279099ebb4caSwyllys } 279199ebb4caSwyllys 279299ebb4caSwyllys #ifdef DEBUG 279399ebb4caSwyllys printf("Successfully retrieved the basic response.\n"); 279499ebb4caSwyllys #endif /* DEBUG */ 279599ebb4caSwyllys 279699ebb4caSwyllys /* Check the basic response signature if required */ 279730a5e8faSwyllys ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr, 279830a5e8faSwyllys (void *)&ignore_response_sign, NULL); 279930a5e8faSwyllys if (ret != KMF_OK) 280030a5e8faSwyllys ret = KMF_OK; 280130a5e8faSwyllys 280230a5e8faSwyllys signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR, 280330a5e8faSwyllys attrlist, numattr); 280430a5e8faSwyllys 280530a5e8faSwyllys if (ignore_response_sign == B_FALSE) { 280699ebb4caSwyllys ret = check_response_signature(handle, bs, 280730a5e8faSwyllys signer_cert, issuer_cert); 280899ebb4caSwyllys if (ret != KMF_OK) 280999ebb4caSwyllys goto end; 281099ebb4caSwyllys } 281199ebb4caSwyllys 281299ebb4caSwyllys #ifdef DEBUG 281399ebb4caSwyllys printf("Successfully verified the response signature.\n"); 281499ebb4caSwyllys #endif /* DEBUG */ 281599ebb4caSwyllys 281699ebb4caSwyllys /* Create a certid for the certificate in question */ 281730a5e8faSwyllys ret = create_certid(handle, issuer_cert, user_cert, &id); 281899ebb4caSwyllys if (ret != KMF_OK) { 281999ebb4caSwyllys ret = KMF_ERR_OCSP_CERTID; 282099ebb4caSwyllys goto end; 282199ebb4caSwyllys } 282299ebb4caSwyllys 282399ebb4caSwyllys #ifdef DEBUG 282499ebb4caSwyllys printf("successfully created a certid for the cert.\n"); 282599ebb4caSwyllys #endif /* DEBUG */ 282699ebb4caSwyllys 282799ebb4caSwyllys /* Find the index of the single response for the certid */ 282899ebb4caSwyllys index = OCSP_resp_find(bs, id, -1); 282999ebb4caSwyllys if (index < 0) { 283099ebb4caSwyllys /* cound not find this certificate in the response */ 283199ebb4caSwyllys ret = KMF_ERR_OCSP_UNKNOWN_CERT; 283299ebb4caSwyllys goto end; 283399ebb4caSwyllys } 283499ebb4caSwyllys 283599ebb4caSwyllys #ifdef DEBUG 283699ebb4caSwyllys printf("Successfully found the single response index for the cert.\n"); 283799ebb4caSwyllys #endif /* DEBUG */ 283899ebb4caSwyllys 283999ebb4caSwyllys /* Retrieve the single response and get the cert status */ 284099ebb4caSwyllys single = OCSP_resp_get0(bs, index); 284199ebb4caSwyllys status = OCSP_single_get0_status(single, &reason, &rev, &thisupd, 284299ebb4caSwyllys &nextupd); 284399ebb4caSwyllys if (status == V_OCSP_CERTSTATUS_GOOD) { 284430a5e8faSwyllys *cert_status = OCSP_GOOD; 284599ebb4caSwyllys } else if (status == V_OCSP_CERTSTATUS_UNKNOWN) { 284630a5e8faSwyllys *cert_status = OCSP_UNKNOWN; 284799ebb4caSwyllys } else { /* revoked */ 284830a5e8faSwyllys *cert_status = OCSP_REVOKED; 284930a5e8faSwyllys *response_reason = reason; 285099ebb4caSwyllys } 285199ebb4caSwyllys ret = KMF_OK; 285299ebb4caSwyllys 285330a5e8faSwyllys /* resp. time is optional, so we don't care about the return code. */ 285430a5e8faSwyllys (void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr, 285530a5e8faSwyllys (void *)&response_lifetime, NULL); 285630a5e8faSwyllys 285799ebb4caSwyllys if (!OCSP_check_validity(thisupd, nextupd, 300, 285830a5e8faSwyllys response_lifetime)) { 285999ebb4caSwyllys ret = KMF_ERR_OCSP_STATUS_TIME_INVALID; 286099ebb4caSwyllys goto end; 286199ebb4caSwyllys } 286299ebb4caSwyllys 286399ebb4caSwyllys #ifdef DEBUG 286499ebb4caSwyllys printf("Successfully verify the time.\n"); 286599ebb4caSwyllys #endif /* DEBUG */ 286699ebb4caSwyllys 286799ebb4caSwyllys end: 286899ebb4caSwyllys if (derbio != NULL) 286999ebb4caSwyllys (void) BIO_free(derbio); 287099ebb4caSwyllys 287199ebb4caSwyllys if (resp != NULL) 287299ebb4caSwyllys OCSP_RESPONSE_free(resp); 287399ebb4caSwyllys 287499ebb4caSwyllys if (bs != NULL) 287599ebb4caSwyllys OCSP_BASICRESP_free(bs); 287699ebb4caSwyllys 287799ebb4caSwyllys if (id != NULL) 287899ebb4caSwyllys OCSP_CERTID_free(id); 287999ebb4caSwyllys 288099ebb4caSwyllys return (ret); 288199ebb4caSwyllys } 288299ebb4caSwyllys 288399ebb4caSwyllys static KMF_RETURN 288499ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path, 288599ebb4caSwyllys KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key) 288699ebb4caSwyllys { 288799ebb4caSwyllys KMF_RETURN rv = KMF_OK; 288830a5e8faSwyllys EVP_PKEY *pkey = NULL; 288999ebb4caSwyllys KMF_RAW_SYM_KEY *rkey = NULL; 289099ebb4caSwyllys 289199ebb4caSwyllys if (keyclass == KMF_ASYM_PRI || 289299ebb4caSwyllys keyclass == KMF_ASYM_PUB) { 289399ebb4caSwyllys pkey = openssl_load_key(handle, path); 289499ebb4caSwyllys if (pkey == NULL) { 289599ebb4caSwyllys return (KMF_ERR_KEY_NOT_FOUND); 289699ebb4caSwyllys } 289799ebb4caSwyllys if (key != NULL) { 2898300fdee2SAndy Fiddaman if (EVP_PKEY_get0_RSA(pkey) != NULL) 289999ebb4caSwyllys key->keyalg = KMF_RSA; 2900300fdee2SAndy Fiddaman else if (EVP_PKEY_get0_DSA(pkey) != NULL) 290199ebb4caSwyllys key->keyalg = KMF_DSA; 290299ebb4caSwyllys 290399ebb4caSwyllys key->kstype = KMF_KEYSTORE_OPENSSL; 290499ebb4caSwyllys key->keyclass = keyclass; 290599ebb4caSwyllys key->keyp = (void *)pkey; 290699ebb4caSwyllys key->israw = FALSE; 29075b3e1433Swyllys if (path != NULL && 29085b3e1433Swyllys ((key->keylabel = strdup(path)) == NULL)) { 29095b3e1433Swyllys EVP_PKEY_free(pkey); 29105b3e1433Swyllys return (KMF_ERR_MEMORY); 29115b3e1433Swyllys } 291299ebb4caSwyllys } else { 291399ebb4caSwyllys EVP_PKEY_free(pkey); 291499ebb4caSwyllys pkey = NULL; 291599ebb4caSwyllys } 291699ebb4caSwyllys } else if (keyclass == KMF_SYMMETRIC) { 291799ebb4caSwyllys KMF_ENCODE_FORMAT fmt; 291899ebb4caSwyllys /* 291999ebb4caSwyllys * If the file is a recognized format, 292099ebb4caSwyllys * then it is NOT a symmetric key. 292199ebb4caSwyllys */ 292230a5e8faSwyllys rv = kmf_get_file_format(path, &fmt); 292399ebb4caSwyllys if (rv == KMF_OK || fmt != 0) { 292499ebb4caSwyllys return (KMF_ERR_KEY_NOT_FOUND); 292599ebb4caSwyllys } else if (rv == KMF_ERR_ENCODING) { 292699ebb4caSwyllys /* 292799ebb4caSwyllys * If we don't know the encoding, 292899ebb4caSwyllys * it is probably a symmetric key. 292999ebb4caSwyllys */ 293099ebb4caSwyllys rv = KMF_OK; 293130a5e8faSwyllys } else if (rv == KMF_ERR_OPEN_FILE) { 293230a5e8faSwyllys return (KMF_ERR_KEY_NOT_FOUND); 293399ebb4caSwyllys } 293499ebb4caSwyllys 293599ebb4caSwyllys if (key != NULL) { 293699ebb4caSwyllys KMF_DATA keyvalue; 293799ebb4caSwyllys rkey = malloc(sizeof (KMF_RAW_SYM_KEY)); 293899ebb4caSwyllys if (rkey == NULL) { 293999ebb4caSwyllys rv = KMF_ERR_MEMORY; 294099ebb4caSwyllys goto out; 294199ebb4caSwyllys } 294299ebb4caSwyllys 294399ebb4caSwyllys (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 294430a5e8faSwyllys rv = kmf_read_input_file(handle, path, &keyvalue); 294599ebb4caSwyllys if (rv != KMF_OK) 294699ebb4caSwyllys goto out; 294799ebb4caSwyllys 294899ebb4caSwyllys rkey->keydata.len = keyvalue.Length; 294999ebb4caSwyllys rkey->keydata.val = keyvalue.Data; 295099ebb4caSwyllys 295199ebb4caSwyllys key->kstype = KMF_KEYSTORE_OPENSSL; 295299ebb4caSwyllys key->keyclass = keyclass; 295399ebb4caSwyllys key->israw = TRUE; 295499ebb4caSwyllys key->keyp = (void *)rkey; 29555b3e1433Swyllys if (path != NULL && 29565b3e1433Swyllys ((key->keylabel = strdup(path)) == NULL)) { 29575b3e1433Swyllys rv = KMF_ERR_MEMORY; 29585b3e1433Swyllys } 295999ebb4caSwyllys } 296099ebb4caSwyllys } 296199ebb4caSwyllys out: 296299ebb4caSwyllys if (rv != KMF_OK) { 296399ebb4caSwyllys if (rkey != NULL) { 296430a5e8faSwyllys kmf_free_raw_sym_key(rkey); 296599ebb4caSwyllys } 296699ebb4caSwyllys if (pkey != NULL) 296799ebb4caSwyllys EVP_PKEY_free(pkey); 296899ebb4caSwyllys 296999ebb4caSwyllys if (key != NULL) { 297099ebb4caSwyllys key->keyalg = KMF_KEYALG_NONE; 297199ebb4caSwyllys key->keyclass = KMF_KEYCLASS_NONE; 297299ebb4caSwyllys key->keyp = NULL; 297399ebb4caSwyllys } 297499ebb4caSwyllys } 297599ebb4caSwyllys 297699ebb4caSwyllys return (rv); 297799ebb4caSwyllys } 297899ebb4caSwyllys 297999ebb4caSwyllys KMF_RETURN 298030a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle, 298130a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 298299ebb4caSwyllys { 298399ebb4caSwyllys KMF_RETURN rv = KMF_OK; 298499ebb4caSwyllys char *fullpath = NULL; 2985f482c776Swyllys uint32_t maxkeys; 298630a5e8faSwyllys KMF_KEY_HANDLE *key; 298730a5e8faSwyllys uint32_t *numkeys; 298830a5e8faSwyllys KMF_KEY_CLASS keyclass; 298930a5e8faSwyllys KMF_RAW_KEY_DATA *rawkey; 299030a5e8faSwyllys char *dirpath; 299130a5e8faSwyllys char *keyfile; 299299ebb4caSwyllys 299330a5e8faSwyllys if (handle == NULL) 299499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 299599ebb4caSwyllys 299630a5e8faSwyllys numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr); 299730a5e8faSwyllys if (numkeys == NULL) 299830a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 299930a5e8faSwyllys 300030a5e8faSwyllys rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr, 300130a5e8faSwyllys (void *)&keyclass, NULL); 300230a5e8faSwyllys if (rv != KMF_OK) 300330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 300430a5e8faSwyllys 300530a5e8faSwyllys if (keyclass != KMF_ASYM_PUB && 300630a5e8faSwyllys keyclass != KMF_ASYM_PRI && 300730a5e8faSwyllys keyclass != KMF_SYMMETRIC) 300899ebb4caSwyllys return (KMF_ERR_BAD_KEY_CLASS); 300999ebb4caSwyllys 301030a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 301130a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 301230a5e8faSwyllys 301330a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 301499ebb4caSwyllys 301599ebb4caSwyllys if (fullpath == NULL) 301699ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 301799ebb4caSwyllys 3018f482c776Swyllys maxkeys = *numkeys; 3019f482c776Swyllys if (maxkeys == 0) 3020f482c776Swyllys maxkeys = 0xFFFFFFFF; 302199ebb4caSwyllys *numkeys = 0; 302299ebb4caSwyllys 302330a5e8faSwyllys key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 302430a5e8faSwyllys /* it is okay to have "keys" contains NULL */ 302530a5e8faSwyllys 302630a5e8faSwyllys /* 302730a5e8faSwyllys * The caller may want a list of the raw key data as well. 302830a5e8faSwyllys * Useful for importing keys from a file into other keystores. 302930a5e8faSwyllys */ 303030a5e8faSwyllys rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr); 303130a5e8faSwyllys 303299ebb4caSwyllys if (isdir(fullpath)) { 303399ebb4caSwyllys DIR *dirp; 303499ebb4caSwyllys struct dirent *dp; 303599ebb4caSwyllys int n = 0; 303699ebb4caSwyllys 303799ebb4caSwyllys /* open all files in the directory and attempt to read them */ 303899ebb4caSwyllys if ((dirp = opendir(fullpath)) == NULL) { 303999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 304099ebb4caSwyllys } 304199ebb4caSwyllys rewinddir(dirp); 3042f482c776Swyllys while ((dp = readdir(dirp)) != NULL && n < maxkeys) { 304399ebb4caSwyllys if (strcmp(dp->d_name, ".") && 304499ebb4caSwyllys strcmp(dp->d_name, "..")) { 304599ebb4caSwyllys char *fname; 304699ebb4caSwyllys 304799ebb4caSwyllys fname = get_fullpath(fullpath, 304899ebb4caSwyllys (char *)&dp->d_name); 304999ebb4caSwyllys 305099ebb4caSwyllys rv = fetch_key(handle, fname, 305130a5e8faSwyllys keyclass, key ? &key[n] : NULL); 305299ebb4caSwyllys 305330a5e8faSwyllys if (rv == KMF_OK) { 305430a5e8faSwyllys if (key != NULL && rawkey != NULL) 305530a5e8faSwyllys rv = convertToRawKey( 305630a5e8faSwyllys key[n].keyp, &rawkey[n]); 305799ebb4caSwyllys n++; 305830a5e8faSwyllys } 305999ebb4caSwyllys 306099ebb4caSwyllys if (rv != KMF_OK || key == NULL) 306199ebb4caSwyllys free(fname); 306299ebb4caSwyllys } 306399ebb4caSwyllys } 306499ebb4caSwyllys (void) closedir(dirp); 306599ebb4caSwyllys free(fullpath); 306699ebb4caSwyllys (*numkeys) = n; 306799ebb4caSwyllys } else { 306830a5e8faSwyllys rv = fetch_key(handle, fullpath, keyclass, key); 306999ebb4caSwyllys if (rv == KMF_OK) 307099ebb4caSwyllys (*numkeys) = 1; 307199ebb4caSwyllys 307299ebb4caSwyllys if (rv != KMF_OK || key == NULL) 307399ebb4caSwyllys free(fullpath); 307430a5e8faSwyllys 307530a5e8faSwyllys if (rv == KMF_OK && key != NULL && rawkey != NULL) { 307630a5e8faSwyllys rv = convertToRawKey(key->keyp, rawkey); 307730a5e8faSwyllys } 307899ebb4caSwyllys } 307999ebb4caSwyllys 3080f482c776Swyllys if (rv == KMF_OK && (*numkeys) == 0) 308199ebb4caSwyllys rv = KMF_ERR_KEY_NOT_FOUND; 308273cc0e02Swyllys else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0) 308373cc0e02Swyllys rv = KMF_OK; 308499ebb4caSwyllys 308599ebb4caSwyllys return (rv); 308699ebb4caSwyllys } 308799ebb4caSwyllys 308899ebb4caSwyllys #define HANDLE_PK12_ERROR { \ 308999ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); \ 309099ebb4caSwyllys rv = KMF_ERR_ENCODING; \ 309199ebb4caSwyllys goto out; \ 309299ebb4caSwyllys } 309399ebb4caSwyllys 30945b3e1433Swyllys static int 30955b3e1433Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert) 309699ebb4caSwyllys { 3097300fdee2SAndy Fiddaman unsigned char *alias; 3098300fdee2SAndy Fiddaman int len; 3099300fdee2SAndy Fiddaman 3100300fdee2SAndy Fiddaman if (xcert != NULL && (alias = X509_alias_get0(xcert, &len)) != NULL) { 31015b3e1433Swyllys if (PKCS12_add_friendlyname_asc(bag, 3102300fdee2SAndy Fiddaman (const char *)alias, len) == 0) 31035b3e1433Swyllys return (0); 31045b3e1433Swyllys } 31055b3e1433Swyllys return (1); 31065b3e1433Swyllys } 31075b3e1433Swyllys 31085b3e1433Swyllys static PKCS7 * 31095b3e1433Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred, 31105b3e1433Swyllys uchar_t *keyid, unsigned int keyidlen) 31115b3e1433Swyllys { 311299ebb4caSwyllys PKCS12_SAFEBAG *bag = NULL; 311399ebb4caSwyllys PKCS7 *cert_authsafe = NULL; 31145b3e1433Swyllys STACK_OF(PKCS12_SAFEBAG) *bag_stack; 311599ebb4caSwyllys 311699ebb4caSwyllys bag_stack = sk_PKCS12_SAFEBAG_new_null(); 311799ebb4caSwyllys if (bag_stack == NULL) 31185b3e1433Swyllys return (NULL); 311999ebb4caSwyllys 312099ebb4caSwyllys /* Convert cert from X509 struct to PKCS#12 bag */ 3121300fdee2SAndy Fiddaman bag = PKCS12_SAFEBAG_create_cert(sslcert); 312299ebb4caSwyllys if (bag == NULL) { 31235b3e1433Swyllys goto out; 312499ebb4caSwyllys } 312599ebb4caSwyllys 312699ebb4caSwyllys /* Add the key id to the certificate bag. */ 31275b3e1433Swyllys if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) { 31285b3e1433Swyllys goto out; 312999ebb4caSwyllys } 313099ebb4caSwyllys 31315b3e1433Swyllys if (!add_alias_to_bag(bag, sslcert)) 31325b3e1433Swyllys goto out; 31335b3e1433Swyllys 313499ebb4caSwyllys /* Pile it on the bag_stack. */ 313599ebb4caSwyllys if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) { 31365b3e1433Swyllys goto out; 313799ebb4caSwyllys } 313899ebb4caSwyllys /* Turn bag_stack of certs into encrypted authsafe. */ 313999ebb4caSwyllys cert_authsafe = PKCS12_pack_p7encdata( 314099ebb4caSwyllys NID_pbe_WithSHA1And40BitRC2_CBC, 314134acef67Swyllys cred->cred, cred->credlen, NULL, 0, 314234acef67Swyllys PKCS12_DEFAULT_ITER, bag_stack); 314399ebb4caSwyllys 31445b3e1433Swyllys out: 31455b3e1433Swyllys if (bag_stack != NULL) 314699ebb4caSwyllys sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); 314799ebb4caSwyllys 31485b3e1433Swyllys return (cert_authsafe); 314999ebb4caSwyllys } 31505b3e1433Swyllys 31515b3e1433Swyllys static PKCS7 * 31525b3e1433Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred, 31535b3e1433Swyllys uchar_t *keyid, unsigned int keyidlen, 31545b3e1433Swyllys char *label, int label_len) 31555b3e1433Swyllys { 31565b3e1433Swyllys PKCS8_PRIV_KEY_INFO *p8 = NULL; 31575b3e1433Swyllys STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL; 31585b3e1433Swyllys PKCS12_SAFEBAG *bag = NULL; 31595b3e1433Swyllys PKCS7 *key_authsafe = NULL; 31605b3e1433Swyllys 316199ebb4caSwyllys p8 = EVP_PKEY2PKCS8(pkey); 316299ebb4caSwyllys if (p8 == NULL) { 31635b3e1433Swyllys return (NULL); 316499ebb4caSwyllys } 316599ebb4caSwyllys /* Put the shrouded key into a PKCS#12 bag. */ 3166300fdee2SAndy Fiddaman bag = PKCS12_SAFEBAG_create_pkcs8_encrypt( 316799ebb4caSwyllys NID_pbe_WithSHA1And3_Key_TripleDES_CBC, 316899ebb4caSwyllys cred->cred, cred->credlen, 316999ebb4caSwyllys NULL, 0, PKCS12_DEFAULT_ITER, p8); 317099ebb4caSwyllys 317199ebb4caSwyllys /* Clean up the PKCS#8 shrouded key, don't need it now. */ 317299ebb4caSwyllys PKCS8_PRIV_KEY_INFO_free(p8); 317399ebb4caSwyllys p8 = NULL; 317499ebb4caSwyllys 317599ebb4caSwyllys if (bag == NULL) { 31765b3e1433Swyllys return (NULL); 317799ebb4caSwyllys } 31785b3e1433Swyllys if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) 31795b3e1433Swyllys goto out; 31805b3e1433Swyllys if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len)) 31815b3e1433Swyllys goto out; 31825b3e1433Swyllys 318399ebb4caSwyllys /* Start a PKCS#12 safebag container for the private key. */ 318499ebb4caSwyllys bag_stack = sk_PKCS12_SAFEBAG_new_null(); 31855b3e1433Swyllys if (bag_stack == NULL) 31865b3e1433Swyllys goto out; 318799ebb4caSwyllys 318899ebb4caSwyllys /* Pile on the private key on the bag_stack. */ 31895b3e1433Swyllys if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) 31905b3e1433Swyllys goto out; 31915b3e1433Swyllys 319299ebb4caSwyllys key_authsafe = PKCS12_pack_p7data(bag_stack); 319399ebb4caSwyllys 31945b3e1433Swyllys out: 31955b3e1433Swyllys if (bag_stack != NULL) 319699ebb4caSwyllys sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); 319799ebb4caSwyllys bag_stack = NULL; 31985b3e1433Swyllys return (key_authsafe); 319999ebb4caSwyllys } 320099ebb4caSwyllys 320199ebb4caSwyllys static EVP_PKEY * 320299ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key) 320399ebb4caSwyllys { 320499ebb4caSwyllys RSA *rsa = NULL; 320599ebb4caSwyllys EVP_PKEY *newkey = NULL; 3206300fdee2SAndy Fiddaman BIGNUM *n = NULL, *e = NULL, *d = NULL, 3207300fdee2SAndy Fiddaman *p = NULL, *q = NULL, 3208300fdee2SAndy Fiddaman *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; 320999ebb4caSwyllys 321099ebb4caSwyllys if ((rsa = RSA_new()) == NULL) 3211300fdee2SAndy Fiddaman goto cleanup; 321299ebb4caSwyllys 3213300fdee2SAndy Fiddaman if ((n = BN_bin2bn(key->mod.val, key->mod.len, NULL)) == NULL) 3214300fdee2SAndy Fiddaman goto cleanup; 321599ebb4caSwyllys 3216300fdee2SAndy Fiddaman if ((e = BN_bin2bn(key->pubexp.val, key->pubexp.len, NULL)) == NULL) 3217300fdee2SAndy Fiddaman goto cleanup; 321899ebb4caSwyllys 3219300fdee2SAndy Fiddaman if (key->priexp.val != NULL && 3220300fdee2SAndy Fiddaman (d = BN_bin2bn(key->priexp.val, key->priexp.len, NULL)) == NULL) 3221300fdee2SAndy Fiddaman goto cleanup; 322299ebb4caSwyllys 3223300fdee2SAndy Fiddaman if (key->prime1.val != NULL && 3224300fdee2SAndy Fiddaman (p = BN_bin2bn(key->prime1.val, key->prime1.len, NULL)) == NULL) 3225300fdee2SAndy Fiddaman goto cleanup; 322699ebb4caSwyllys 3227300fdee2SAndy Fiddaman if (key->prime2.val != NULL && 3228300fdee2SAndy Fiddaman (q = BN_bin2bn(key->prime2.val, key->prime2.len, NULL)) == NULL) 3229300fdee2SAndy Fiddaman goto cleanup; 323099ebb4caSwyllys 3231300fdee2SAndy Fiddaman if (key->exp1.val != NULL && 3232300fdee2SAndy Fiddaman (dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len, NULL)) == NULL) 3233300fdee2SAndy Fiddaman goto cleanup; 323499ebb4caSwyllys 3235300fdee2SAndy Fiddaman if (key->exp2.val != NULL && 3236300fdee2SAndy Fiddaman (dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len, NULL)) == NULL) 3237300fdee2SAndy Fiddaman goto cleanup; 323899ebb4caSwyllys 3239300fdee2SAndy Fiddaman if (key->coef.val != NULL && 3240300fdee2SAndy Fiddaman (iqmp = BN_bin2bn(key->coef.val, key->coef.len, NULL)) == NULL) 3241300fdee2SAndy Fiddaman goto cleanup; 3242300fdee2SAndy Fiddaman 3243300fdee2SAndy Fiddaman if (RSA_set0_key(rsa, n, e, d) == 0) 3244300fdee2SAndy Fiddaman goto cleanup; 3245300fdee2SAndy Fiddaman n = e = d = NULL; 3246300fdee2SAndy Fiddaman if (RSA_set0_factors(rsa, p, q) == 0) 3247300fdee2SAndy Fiddaman goto cleanup; 3248300fdee2SAndy Fiddaman p = q = NULL; 3249300fdee2SAndy Fiddaman if (RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp) == 0) 3250300fdee2SAndy Fiddaman goto cleanup; 3251300fdee2SAndy Fiddaman dmp1 = dmq1 = iqmp = NULL; 325299ebb4caSwyllys 325399ebb4caSwyllys if ((newkey = EVP_PKEY_new()) == NULL) 3254300fdee2SAndy Fiddaman goto cleanup; 325599ebb4caSwyllys 325699ebb4caSwyllys (void) EVP_PKEY_set1_RSA(newkey, rsa); 325799ebb4caSwyllys 3258300fdee2SAndy Fiddaman cleanup: 325999ebb4caSwyllys /* The original key must be freed once here or it leaks memory */ 3260300fdee2SAndy Fiddaman if (rsa) 326199ebb4caSwyllys RSA_free(rsa); 3262300fdee2SAndy Fiddaman BN_free(n); 3263300fdee2SAndy Fiddaman BN_free(e); 3264300fdee2SAndy Fiddaman BN_free(d); 3265300fdee2SAndy Fiddaman BN_free(p); 3266300fdee2SAndy Fiddaman BN_free(q); 3267300fdee2SAndy Fiddaman BN_free(dmp1); 3268300fdee2SAndy Fiddaman BN_free(dmq1); 3269300fdee2SAndy Fiddaman BN_free(iqmp); 327099ebb4caSwyllys 327199ebb4caSwyllys return (newkey); 327299ebb4caSwyllys } 327399ebb4caSwyllys 327499ebb4caSwyllys static EVP_PKEY * 327599ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key) 327699ebb4caSwyllys { 327799ebb4caSwyllys DSA *dsa = NULL; 327899ebb4caSwyllys EVP_PKEY *newkey = NULL; 3279300fdee2SAndy Fiddaman BIGNUM *p = NULL, *q = NULL, *g = NULL, 3280300fdee2SAndy Fiddaman *priv_key = NULL, *pub_key = NULL; 328199ebb4caSwyllys 328299ebb4caSwyllys if ((dsa = DSA_new()) == NULL) 3283300fdee2SAndy Fiddaman goto cleanup; 328499ebb4caSwyllys 3285300fdee2SAndy Fiddaman if ((p = BN_bin2bn(key->prime.val, key->prime.len, NULL)) == NULL) 3286300fdee2SAndy Fiddaman goto cleanup; 328799ebb4caSwyllys 3288300fdee2SAndy Fiddaman if ((q = BN_bin2bn(key->subprime.val, key->subprime.len, NULL)) == NULL) 3289300fdee2SAndy Fiddaman goto cleanup; 329099ebb4caSwyllys 3291300fdee2SAndy Fiddaman if ((g = BN_bin2bn(key->base.val, key->base.len, NULL)) == NULL) 3292300fdee2SAndy Fiddaman goto cleanup; 329399ebb4caSwyllys 3294300fdee2SAndy Fiddaman if ((priv_key = BN_bin2bn(key->value.val, key->value.len, 3295300fdee2SAndy Fiddaman NULL)) == NULL) 3296300fdee2SAndy Fiddaman goto cleanup; 329799ebb4caSwyllys 3298300fdee2SAndy Fiddaman if (key->pubvalue.val != NULL && (pub_key = 3299300fdee2SAndy Fiddaman BN_bin2bn(key->pubvalue.val, key->pubvalue.len, NULL)) == NULL) 3300300fdee2SAndy Fiddaman goto cleanup; 3301300fdee2SAndy Fiddaman 3302300fdee2SAndy Fiddaman if (DSA_set0_pqg(dsa, p, q, g) == 0) 3303300fdee2SAndy Fiddaman goto cleanup; 3304300fdee2SAndy Fiddaman p = q = g = NULL; 3305300fdee2SAndy Fiddaman if (DSA_set0_key(dsa, pub_key, priv_key) == 0) 3306300fdee2SAndy Fiddaman goto cleanup; 3307300fdee2SAndy Fiddaman pub_key = priv_key = 0; 330830a5e8faSwyllys 330999ebb4caSwyllys if ((newkey = EVP_PKEY_new()) == NULL) 3310300fdee2SAndy Fiddaman goto cleanup; 331199ebb4caSwyllys 331299ebb4caSwyllys (void) EVP_PKEY_set1_DSA(newkey, dsa); 331399ebb4caSwyllys 3314300fdee2SAndy Fiddaman cleanup: 331599ebb4caSwyllys /* The original key must be freed once here or it leaks memory */ 3316300fdee2SAndy Fiddaman if (dsa) 331799ebb4caSwyllys DSA_free(dsa); 3318300fdee2SAndy Fiddaman BN_free(p); 3319300fdee2SAndy Fiddaman BN_free(q); 3320300fdee2SAndy Fiddaman BN_free(g); 3321300fdee2SAndy Fiddaman BN_free(priv_key); 3322300fdee2SAndy Fiddaman BN_free(pub_key); 3323300fdee2SAndy Fiddaman 332499ebb4caSwyllys return (newkey); 332599ebb4caSwyllys } 332699ebb4caSwyllys 33275b3e1433Swyllys static EVP_PKEY * 33285b3e1433Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key) 33295b3e1433Swyllys { 33305b3e1433Swyllys EVP_PKEY *pkey = NULL; 33315b3e1433Swyllys KMF_RAW_KEY_DATA *rawkey; 33325b3e1433Swyllys ASN1_TYPE *attr = NULL; 33335b3e1433Swyllys KMF_RETURN ret; 33345b3e1433Swyllys 33355b3e1433Swyllys if (key == NULL || !key->israw) 33365b3e1433Swyllys return (NULL); 33375b3e1433Swyllys 33385b3e1433Swyllys rawkey = (KMF_RAW_KEY_DATA *)key->keyp; 33395b3e1433Swyllys if (rawkey->keytype == KMF_RSA) { 33405b3e1433Swyllys pkey = ImportRawRSAKey(&rawkey->rawdata.rsa); 33415b3e1433Swyllys } else if (rawkey->keytype == KMF_DSA) { 33425b3e1433Swyllys pkey = ImportRawDSAKey(&rawkey->rawdata.dsa); 3343e65e5c2dSWyllys Ingersoll } else if (rawkey->keytype == KMF_ECDSA) { 3344e65e5c2dSWyllys Ingersoll /* 3345e65e5c2dSWyllys Ingersoll * OpenSSL in Solaris does not support EC for 3346e65e5c2dSWyllys Ingersoll * legal reasons 3347e65e5c2dSWyllys Ingersoll */ 3348e65e5c2dSWyllys Ingersoll return (NULL); 33495b3e1433Swyllys } else { 33505b3e1433Swyllys /* wrong kind of key */ 33515b3e1433Swyllys return (NULL); 33525b3e1433Swyllys } 33535b3e1433Swyllys 33545b3e1433Swyllys if (rawkey->label != NULL) { 33555b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) { 33565b3e1433Swyllys EVP_PKEY_free(pkey); 33575b3e1433Swyllys return (NULL); 33585b3e1433Swyllys } 33595b3e1433Swyllys attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING); 33605b3e1433Swyllys (void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label, 33615b3e1433Swyllys strlen(rawkey->label)); 33625b3e1433Swyllys attr->type = V_ASN1_BMPSTRING; 33635b3e1433Swyllys attr->value.ptr = (char *)attr->value.bmpstring; 33645b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_friendlyName); 33655b3e1433Swyllys if (ret != KMF_OK) { 33665b3e1433Swyllys EVP_PKEY_free(pkey); 33675b3e1433Swyllys ASN1_TYPE_free(attr); 33685b3e1433Swyllys return (NULL); 33695b3e1433Swyllys } 33705b3e1433Swyllys } 33715b3e1433Swyllys if (rawkey->id.Data != NULL) { 33725b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) { 33735b3e1433Swyllys EVP_PKEY_free(pkey); 33745b3e1433Swyllys return (NULL); 33755b3e1433Swyllys } 33765b3e1433Swyllys attr->value.octet_string = 33775b3e1433Swyllys ASN1_STRING_type_new(V_ASN1_OCTET_STRING); 33785b3e1433Swyllys attr->type = V_ASN1_OCTET_STRING; 33795b3e1433Swyllys (void) ASN1_STRING_set(attr->value.octet_string, 33805b3e1433Swyllys rawkey->id.Data, rawkey->id.Length); 33815b3e1433Swyllys attr->value.ptr = (char *)attr->value.octet_string; 33825b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_localKeyID); 33835b3e1433Swyllys if (ret != KMF_OK) { 33845b3e1433Swyllys EVP_PKEY_free(pkey); 33855b3e1433Swyllys ASN1_TYPE_free(attr); 33865b3e1433Swyllys return (NULL); 33875b3e1433Swyllys } 33885b3e1433Swyllys } 33895b3e1433Swyllys return (pkey); 33905b3e1433Swyllys } 33915b3e1433Swyllys 33925b3e1433Swyllys /* 33935b3e1433Swyllys * Search a list of private keys to find one that goes with the certificate. 33945b3e1433Swyllys */ 33955b3e1433Swyllys static EVP_PKEY * 33965b3e1433Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist) 33975b3e1433Swyllys { 33985b3e1433Swyllys int i; 33995b3e1433Swyllys EVP_PKEY *pkey = NULL; 34005b3e1433Swyllys 34015b3e1433Swyllys if (numkeys == 0 || keylist == NULL || xcert == NULL) 34025b3e1433Swyllys return (NULL); 34035b3e1433Swyllys for (i = 0; i < numkeys; i++) { 34045b3e1433Swyllys if (keylist[i].israw) 34055b3e1433Swyllys pkey = raw_key_to_pkey(&keylist[i]); 34065b3e1433Swyllys else 34075b3e1433Swyllys pkey = (EVP_PKEY *)keylist[i].keyp; 34085b3e1433Swyllys if (pkey != NULL) { 34095b3e1433Swyllys if (X509_check_private_key(xcert, pkey)) { 34105b3e1433Swyllys return (pkey); 34115b3e1433Swyllys } else { 34125b3e1433Swyllys EVP_PKEY_free(pkey); 34135b3e1433Swyllys pkey = NULL; 34145b3e1433Swyllys } 34155b3e1433Swyllys } 34165b3e1433Swyllys } 34175b3e1433Swyllys return (pkey); 34185b3e1433Swyllys } 34195b3e1433Swyllys 342099ebb4caSwyllys static KMF_RETURN 34215b3e1433Swyllys local_export_pk12(KMF_HANDLE_T handle, 342299ebb4caSwyllys KMF_CREDENTIAL *cred, 342399ebb4caSwyllys int numcerts, KMF_X509_DER_CERT *certlist, 342499ebb4caSwyllys int numkeys, KMF_KEY_HANDLE *keylist, 342599ebb4caSwyllys char *filename) 342699ebb4caSwyllys { 342799ebb4caSwyllys KMF_RETURN rv = KMF_OK; 342899ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 342999ebb4caSwyllys BIO *bio = NULL; 34305b3e1433Swyllys PKCS7 *cert_authsafe = NULL; 34315b3e1433Swyllys PKCS7 *key_authsafe = NULL; 34325b3e1433Swyllys STACK_OF(PKCS7) *authsafe_stack = NULL; 34335b3e1433Swyllys PKCS12 *p12_elem = NULL; 343499ebb4caSwyllys int i; 343599ebb4caSwyllys 34365b3e1433Swyllys if (numcerts == 0 && numkeys == 0) 34375b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 34385b3e1433Swyllys 343999ebb4caSwyllys /* 344099ebb4caSwyllys * Open the output file. 344199ebb4caSwyllys */ 344299ebb4caSwyllys if ((bio = BIO_new_file(filename, "wb")) == NULL) { 344399ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 344499ebb4caSwyllys rv = KMF_ERR_OPEN_FILE; 344599ebb4caSwyllys goto cleanup; 344699ebb4caSwyllys } 344799ebb4caSwyllys 34485b3e1433Swyllys /* Start a PKCS#7 stack. */ 34495b3e1433Swyllys authsafe_stack = sk_PKCS7_new_null(); 34505b3e1433Swyllys if (authsafe_stack == NULL) { 34515b3e1433Swyllys rv = KMF_ERR_MEMORY; 34525b3e1433Swyllys goto cleanup; 34535b3e1433Swyllys } 34545b3e1433Swyllys if (numcerts > 0) { 345599ebb4caSwyllys for (i = 0; rv == KMF_OK && i < numcerts; i++) { 345699ebb4caSwyllys const uchar_t *p = certlist[i].certificate.Data; 345799ebb4caSwyllys long len = certlist[i].certificate.Length; 34585b3e1433Swyllys X509 *xcert = NULL; 34595b3e1433Swyllys EVP_PKEY *pkey = NULL; 34605b3e1433Swyllys unsigned char keyid[EVP_MAX_MD_SIZE]; 34615b3e1433Swyllys unsigned int keyidlen = 0; 346299ebb4caSwyllys 346399ebb4caSwyllys xcert = d2i_X509(NULL, &p, len); 346499ebb4caSwyllys if (xcert == NULL) { 346599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 346699ebb4caSwyllys rv = KMF_ERR_ENCODING; 346799ebb4caSwyllys } 34685b3e1433Swyllys if (certlist[i].kmf_private.label != NULL) { 34695b3e1433Swyllys /* Set alias attribute */ 34705b3e1433Swyllys (void) X509_alias_set1(xcert, 34715b3e1433Swyllys (uchar_t *)certlist[i].kmf_private.label, 34725b3e1433Swyllys strlen(certlist[i].kmf_private.label)); 34735b3e1433Swyllys } 34745b3e1433Swyllys /* Check if there is a key corresponding to this cert */ 34755b3e1433Swyllys pkey = find_matching_key(xcert, numkeys, keylist); 34765b3e1433Swyllys 34775b3e1433Swyllys /* 34785b3e1433Swyllys * If key is found, get fingerprint and create a 34795b3e1433Swyllys * safebag. 34805b3e1433Swyllys */ 34815b3e1433Swyllys if (pkey != NULL) { 34825b3e1433Swyllys (void) X509_digest(xcert, EVP_sha1(), 34835b3e1433Swyllys keyid, &keyidlen); 34845b3e1433Swyllys key_authsafe = add_key_to_safe(pkey, cred, 34855b3e1433Swyllys keyid, keyidlen, 34865b3e1433Swyllys certlist[i].kmf_private.label, 34875b3e1433Swyllys (certlist[i].kmf_private.label ? 34885b3e1433Swyllys strlen(certlist[i].kmf_private.label) : 0)); 34895b3e1433Swyllys 34905b3e1433Swyllys if (key_authsafe == NULL) { 34915b3e1433Swyllys X509_free(xcert); 34925b3e1433Swyllys EVP_PKEY_free(pkey); 34935b3e1433Swyllys goto cleanup; 34945b3e1433Swyllys } 34955b3e1433Swyllys /* Put the key safe into the Auth Safe */ 34965b3e1433Swyllys if (!sk_PKCS7_push(authsafe_stack, 34975b3e1433Swyllys key_authsafe)) { 34985b3e1433Swyllys X509_free(xcert); 34995b3e1433Swyllys EVP_PKEY_free(pkey); 35005b3e1433Swyllys goto cleanup; 35015b3e1433Swyllys } 35025b3e1433Swyllys } 35035b3e1433Swyllys 35045b3e1433Swyllys /* create a certificate safebag */ 35055b3e1433Swyllys cert_authsafe = add_cert_to_safe(xcert, cred, keyid, 35065b3e1433Swyllys keyidlen); 35075b3e1433Swyllys if (cert_authsafe == NULL) { 35085b3e1433Swyllys X509_free(xcert); 35095b3e1433Swyllys EVP_PKEY_free(pkey); 35105b3e1433Swyllys goto cleanup; 35115b3e1433Swyllys } 35125b3e1433Swyllys if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) { 35135b3e1433Swyllys X509_free(xcert); 35145b3e1433Swyllys EVP_PKEY_free(pkey); 35155b3e1433Swyllys goto cleanup; 35165b3e1433Swyllys } 35175b3e1433Swyllys 351899ebb4caSwyllys X509_free(xcert); 351999ebb4caSwyllys if (pkey) 352099ebb4caSwyllys EVP_PKEY_free(pkey); 352199ebb4caSwyllys } 35225b3e1433Swyllys } else if (numcerts == 0 && numkeys > 0) { 35235b3e1433Swyllys /* 35245b3e1433Swyllys * If only adding keys to the file. 35255b3e1433Swyllys */ 35265b3e1433Swyllys for (i = 0; i < numkeys; i++) { 35275b3e1433Swyllys EVP_PKEY *pkey = NULL; 35285b3e1433Swyllys 35295b3e1433Swyllys if (keylist[i].israw) 35305b3e1433Swyllys pkey = raw_key_to_pkey(&keylist[i]); 35315b3e1433Swyllys else 35325b3e1433Swyllys pkey = (EVP_PKEY *)keylist[i].keyp; 35335b3e1433Swyllys 35345b3e1433Swyllys if (pkey == NULL) 35355b3e1433Swyllys continue; 35365b3e1433Swyllys 35375b3e1433Swyllys key_authsafe = add_key_to_safe(pkey, cred, 35385b3e1433Swyllys NULL, 0, NULL, 0); 35395b3e1433Swyllys 35405b3e1433Swyllys if (key_authsafe == NULL) { 35415b3e1433Swyllys EVP_PKEY_free(pkey); 35425b3e1433Swyllys goto cleanup; 35435b3e1433Swyllys } 35445b3e1433Swyllys if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) { 35455b3e1433Swyllys EVP_PKEY_free(pkey); 35465b3e1433Swyllys goto cleanup; 35475b3e1433Swyllys } 35485b3e1433Swyllys } 35495b3e1433Swyllys } 35505b3e1433Swyllys p12_elem = PKCS12_init(NID_pkcs7_data); 35515b3e1433Swyllys if (p12_elem == NULL) { 35525b3e1433Swyllys goto cleanup; 355399ebb4caSwyllys } 355499ebb4caSwyllys 35555b3e1433Swyllys /* Put the PKCS#7 stack into the PKCS#12 element. */ 35565b3e1433Swyllys if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) { 35575b3e1433Swyllys goto cleanup; 35585b3e1433Swyllys } 35595b3e1433Swyllys 35605b3e1433Swyllys /* Set the integrity MAC on the PKCS#12 element. */ 35615b3e1433Swyllys if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen, 35625b3e1433Swyllys NULL, 0, PKCS12_DEFAULT_ITER, NULL)) { 35635b3e1433Swyllys goto cleanup; 35645b3e1433Swyllys } 35655b3e1433Swyllys 35665b3e1433Swyllys /* Write the PKCS#12 element to the export file. */ 35675b3e1433Swyllys if (!i2d_PKCS12_bio(bio, p12_elem)) { 35685b3e1433Swyllys goto cleanup; 35695b3e1433Swyllys } 35705b3e1433Swyllys PKCS12_free(p12_elem); 35715b3e1433Swyllys 357299ebb4caSwyllys cleanup: 35735b3e1433Swyllys /* Clear away the PKCS#7 stack, we're done with it. */ 35745b3e1433Swyllys if (authsafe_stack) 35755b3e1433Swyllys sk_PKCS7_pop_free(authsafe_stack, PKCS7_free); 357699ebb4caSwyllys 357799ebb4caSwyllys if (bio != NULL) 357899ebb4caSwyllys (void) BIO_free_all(bio); 357999ebb4caSwyllys 358099ebb4caSwyllys return (rv); 358199ebb4caSwyllys } 358299ebb4caSwyllys 358399ebb4caSwyllys KMF_RETURN 358430a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts, 358530a5e8faSwyllys KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist, 358630a5e8faSwyllys KMF_CREDENTIAL *p12cred, char *filename) 358730a5e8faSwyllys { 358830a5e8faSwyllys KMF_RETURN rv; 358930a5e8faSwyllys 359030a5e8faSwyllys if (certlist == NULL && keylist == NULL) 359130a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 359230a5e8faSwyllys 35935b3e1433Swyllys rv = local_export_pk12(handle, p12cred, numcerts, certlist, 359430a5e8faSwyllys numkeys, keylist, filename); 359530a5e8faSwyllys 359630a5e8faSwyllys return (rv); 359730a5e8faSwyllys } 359830a5e8faSwyllys 359930a5e8faSwyllys KMF_RETURN 360030a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 360199ebb4caSwyllys { 360299ebb4caSwyllys KMF_RETURN rv; 360399ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 360499ebb4caSwyllys char *fullpath = NULL; 360530a5e8faSwyllys char *dirpath = NULL; 360630a5e8faSwyllys char *certfile = NULL; 360730a5e8faSwyllys char *keyfile = NULL; 360830a5e8faSwyllys char *filename = NULL; 360930a5e8faSwyllys KMF_CREDENTIAL *p12cred = NULL; 36105b3e1433Swyllys KMF_X509_DER_CERT certdata; 36115b3e1433Swyllys KMF_KEY_HANDLE key; 36125b3e1433Swyllys int gotkey = 0; 36135b3e1433Swyllys int gotcert = 0; 361430a5e8faSwyllys 361530a5e8faSwyllys if (handle == NULL) 361630a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 361799ebb4caSwyllys 361899ebb4caSwyllys /* 361999ebb4caSwyllys * First, find the certificate. 362099ebb4caSwyllys */ 362130a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 362230a5e8faSwyllys certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr); 362330a5e8faSwyllys if (certfile != NULL) { 362430a5e8faSwyllys fullpath = get_fullpath(dirpath, certfile); 362599ebb4caSwyllys if (fullpath == NULL) 362699ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 362799ebb4caSwyllys 362899ebb4caSwyllys if (isdir(fullpath)) { 362999ebb4caSwyllys free(fullpath); 363099ebb4caSwyllys return (KMF_ERR_AMBIGUOUS_PATHNAME); 363199ebb4caSwyllys } 363299ebb4caSwyllys 36335b3e1433Swyllys (void) memset(&certdata, 0, sizeof (certdata)); 3634*f810c7e5SToomas Soome rv = kmf_load_cert(kmfh, NULL, NULL, NULL, 0, 36355b3e1433Swyllys fullpath, &certdata.certificate); 363699ebb4caSwyllys if (rv != KMF_OK) 363799ebb4caSwyllys goto end; 363830a5e8faSwyllys 36395b3e1433Swyllys gotcert++; 36405b3e1433Swyllys certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL; 364130a5e8faSwyllys free(fullpath); 364299ebb4caSwyllys } 364399ebb4caSwyllys 364499ebb4caSwyllys /* 364599ebb4caSwyllys * Now find the private key. 364699ebb4caSwyllys */ 364730a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 364830a5e8faSwyllys if (keyfile != NULL) { 364930a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 365099ebb4caSwyllys if (fullpath == NULL) 365199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 365299ebb4caSwyllys 365399ebb4caSwyllys if (isdir(fullpath)) { 365499ebb4caSwyllys free(fullpath); 365599ebb4caSwyllys return (KMF_ERR_AMBIGUOUS_PATHNAME); 365699ebb4caSwyllys } 365799ebb4caSwyllys 36585b3e1433Swyllys (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE)); 36595b3e1433Swyllys rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key); 36605b3e1433Swyllys if (rv != KMF_OK) 366199ebb4caSwyllys goto end; 36625b3e1433Swyllys gotkey++; 366399ebb4caSwyllys } 366499ebb4caSwyllys 366599ebb4caSwyllys /* 366699ebb4caSwyllys * Open the output file. 366799ebb4caSwyllys */ 366830a5e8faSwyllys filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist, 366930a5e8faSwyllys numattr); 367030a5e8faSwyllys if (filename == NULL) { 367130a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 367230a5e8faSwyllys goto end; 367330a5e8faSwyllys } 367430a5e8faSwyllys 367599ebb4caSwyllys /* Stick the key and the cert into a PKCS#12 file */ 367630a5e8faSwyllys p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr); 367730a5e8faSwyllys if (p12cred == NULL) { 367830a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 367930a5e8faSwyllys goto end; 368030a5e8faSwyllys } 368130a5e8faSwyllys 36825b3e1433Swyllys rv = local_export_pk12(handle, p12cred, 1, &certdata, 36835b3e1433Swyllys 1, &key, filename); 368499ebb4caSwyllys 368599ebb4caSwyllys end: 368699ebb4caSwyllys if (fullpath) 368799ebb4caSwyllys free(fullpath); 368899ebb4caSwyllys 36895b3e1433Swyllys if (gotcert) 36905b3e1433Swyllys kmf_free_kmf_cert(handle, &certdata); 36915b3e1433Swyllys if (gotkey) 36925b3e1433Swyllys kmf_free_kmf_key(handle, &key); 369399ebb4caSwyllys return (rv); 369499ebb4caSwyllys } 369599ebb4caSwyllys 369671593db2Swyllys /* 369771593db2Swyllys * Helper function to extract keys and certificates from 369871593db2Swyllys * a single PEM file. Typically the file should contain a 369971593db2Swyllys * private key and an associated public key wrapped in an x509 cert. 370071593db2Swyllys * However, the file may be just a list of X509 certs with no keys. 370171593db2Swyllys */ 370271593db2Swyllys static KMF_RETURN 370330a5e8faSwyllys extract_pem(KMF_HANDLE *kmfh, 370430a5e8faSwyllys char *issuer, char *subject, KMF_BIGINT *serial, 370502744e81Swyllys char *filename, CK_UTF8CHAR *pin, 370671593db2Swyllys CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs, 370771593db2Swyllys int *numcerts) 3708a2d4930dSDan OpenSolaris Anderson /* ARGSUSED6 */ 370971593db2Swyllys { 371071593db2Swyllys KMF_RETURN rv = KMF_OK; 371171593db2Swyllys FILE *fp; 371234acef67Swyllys STACK_OF(X509_INFO) *x509_info_stack = NULL; 371302744e81Swyllys int i, ncerts = 0, matchcerts = 0; 371471593db2Swyllys EVP_PKEY *pkey = NULL; 371571593db2Swyllys X509_INFO *info; 371671593db2Swyllys X509 *x; 37175b3e1433Swyllys X509_INFO **cert_infos = NULL; 371871593db2Swyllys KMF_DATA *certlist = NULL; 371971593db2Swyllys 372071593db2Swyllys if (priv_key) 372171593db2Swyllys *priv_key = NULL; 372271593db2Swyllys if (certs) 372371593db2Swyllys *certs = NULL; 372471593db2Swyllys fp = fopen(filename, "r"); 37255b3e1433Swyllys if (fp == NULL) 372671593db2Swyllys return (KMF_ERR_OPEN_FILE); 37275b3e1433Swyllys 372871593db2Swyllys x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin); 372971593db2Swyllys if (x509_info_stack == NULL) { 373071593db2Swyllys (void) fclose(fp); 373171593db2Swyllys return (KMF_ERR_ENCODING); 373271593db2Swyllys } 37335b3e1433Swyllys cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) * 37345b3e1433Swyllys sizeof (X509_INFO *)); 37355b3e1433Swyllys if (cert_infos == NULL) { 37365b3e1433Swyllys (void) fclose(fp); 37375b3e1433Swyllys rv = KMF_ERR_MEMORY; 37385b3e1433Swyllys goto err; 37395b3e1433Swyllys } 374071593db2Swyllys 37415b3e1433Swyllys for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) { 3742d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 374334acef67Swyllys cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i); 374471593db2Swyllys ncerts++; 374571593db2Swyllys } 374671593db2Swyllys 374771593db2Swyllys if (ncerts == 0) { 374871593db2Swyllys (void) fclose(fp); 374934acef67Swyllys rv = KMF_ERR_CERT_NOT_FOUND; 375034acef67Swyllys goto err; 375171593db2Swyllys } 375271593db2Swyllys 375371593db2Swyllys if (priv_key != NULL) { 375471593db2Swyllys rewind(fp); 375571593db2Swyllys pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin); 375671593db2Swyllys } 375771593db2Swyllys (void) fclose(fp); 375871593db2Swyllys 375971593db2Swyllys x = cert_infos[ncerts - 1]->x509; 376071593db2Swyllys /* 376171593db2Swyllys * Make sure the private key matchs the last cert in the file. 376271593db2Swyllys */ 376371593db2Swyllys if (pkey != NULL && !X509_check_private_key(x, pkey)) { 376471593db2Swyllys EVP_PKEY_free(pkey); 376534acef67Swyllys rv = KMF_ERR_KEY_MISMATCH; 376634acef67Swyllys goto err; 376771593db2Swyllys } 376871593db2Swyllys 3769a2d4930dSDan OpenSolaris Anderson certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA)); 377071593db2Swyllys if (certlist == NULL) { 377171593db2Swyllys if (pkey != NULL) 377271593db2Swyllys EVP_PKEY_free(pkey); 377334acef67Swyllys rv = KMF_ERR_MEMORY; 377434acef67Swyllys goto err; 377571593db2Swyllys } 377671593db2Swyllys 377771593db2Swyllys /* 377871593db2Swyllys * Convert all of the certs to DER format. 377971593db2Swyllys */ 378002744e81Swyllys matchcerts = 0; 378171593db2Swyllys for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) { 378202744e81Swyllys boolean_t match = FALSE; 378371593db2Swyllys info = cert_infos[ncerts - 1 - i]; 378471593db2Swyllys 378530a5e8faSwyllys rv = check_cert(info->x509, issuer, subject, serial, &match); 378602744e81Swyllys if (rv != KMF_OK || match != TRUE) { 378702744e81Swyllys rv = KMF_OK; 378802744e81Swyllys continue; 378902744e81Swyllys } 379002744e81Swyllys 379102744e81Swyllys rv = ssl_cert2KMFDATA(kmfh, info->x509, 379202744e81Swyllys &certlist[matchcerts++]); 379371593db2Swyllys 379471593db2Swyllys if (rv != KMF_OK) { 3795e65e5c2dSWyllys Ingersoll int j; 3796e65e5c2dSWyllys Ingersoll for (j = 0; j < matchcerts; j++) 3797e65e5c2dSWyllys Ingersoll kmf_free_data(&certlist[j]); 379871593db2Swyllys free(certlist); 379971593db2Swyllys certlist = NULL; 380002744e81Swyllys ncerts = matchcerts = 0; 380171593db2Swyllys } 380271593db2Swyllys } 380371593db2Swyllys 380471593db2Swyllys if (numcerts != NULL) 380502744e81Swyllys *numcerts = matchcerts; 3806a2d4930dSDan OpenSolaris Anderson 3807e65e5c2dSWyllys Ingersoll if (certs != NULL) 380871593db2Swyllys *certs = certlist; 3809e65e5c2dSWyllys Ingersoll else if (certlist != NULL) { 3810e65e5c2dSWyllys Ingersoll for (i = 0; i < ncerts; i++) 3811e65e5c2dSWyllys Ingersoll kmf_free_data(&certlist[i]); 3812a2d4930dSDan OpenSolaris Anderson free(certlist); 3813a2d4930dSDan OpenSolaris Anderson certlist = NULL; 3814a2d4930dSDan OpenSolaris Anderson } 381571593db2Swyllys 381671593db2Swyllys if (priv_key == NULL && pkey != NULL) 381771593db2Swyllys EVP_PKEY_free(pkey); 381871593db2Swyllys else if (priv_key != NULL && pkey != NULL) 381971593db2Swyllys *priv_key = pkey; 382071593db2Swyllys 382134acef67Swyllys err: 382234acef67Swyllys /* Cleanup the stack of X509 info records */ 382334acef67Swyllys for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) { 3824d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 382534acef67Swyllys info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i); 382634acef67Swyllys X509_INFO_free(info); 382734acef67Swyllys } 382834acef67Swyllys if (x509_info_stack) 382934acef67Swyllys sk_X509_INFO_free(x509_info_stack); 383034acef67Swyllys 38315b3e1433Swyllys if (cert_infos != NULL) 38325b3e1433Swyllys free(cert_infos); 38335b3e1433Swyllys 383471593db2Swyllys return (rv); 383571593db2Swyllys } 383671593db2Swyllys 38375b3e1433Swyllys static KMF_RETURN 3838300fdee2SAndy Fiddaman openssl_parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, char *pin, 38395b3e1433Swyllys STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs) 38405b3e1433Swyllys { 38415b3e1433Swyllys KMF_RETURN ret; 38425b3e1433Swyllys int i; 38435b3e1433Swyllys 38445b3e1433Swyllys for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { 3845d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 38465b3e1433Swyllys PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i); 38475b3e1433Swyllys ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0), 38485b3e1433Swyllys keys, certs); 38495b3e1433Swyllys 38505b3e1433Swyllys if (ret != KMF_OK) 38515b3e1433Swyllys return (ret); 38525b3e1433Swyllys } 38535b3e1433Swyllys 38545b3e1433Swyllys return (ret); 38555b3e1433Swyllys } 38565b3e1433Swyllys 38575b3e1433Swyllys static KMF_RETURN 38585b3e1433Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid) 38595b3e1433Swyllys { 38605b3e1433Swyllys X509_ATTRIBUTE *attr = NULL; 38615b3e1433Swyllys 38625b3e1433Swyllys if (pkey == NULL || attrib == NULL) 38635b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 38645b3e1433Swyllys 38655b3e1433Swyllys attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr); 38665b3e1433Swyllys if (attr != NULL) { 38675b3e1433Swyllys int i; 3868300fdee2SAndy Fiddaman 3869300fdee2SAndy Fiddaman if ((i = EVP_PKEY_get_attr_by_NID(pkey, nid, -1)) != -1) 3870300fdee2SAndy Fiddaman (void) EVP_PKEY_delete_attr(pkey, i); 3871300fdee2SAndy Fiddaman if (EVP_PKEY_add1_attr(pkey, attr) == 0) { 38725b3e1433Swyllys X509_ATTRIBUTE_free(attr); 38735b3e1433Swyllys return (KMF_ERR_MEMORY); 38745b3e1433Swyllys } 38755b3e1433Swyllys } else { 38765b3e1433Swyllys return (KMF_ERR_MEMORY); 38775b3e1433Swyllys } 38785b3e1433Swyllys 38795b3e1433Swyllys return (KMF_OK); 38805b3e1433Swyllys } 38815b3e1433Swyllys 38825b3e1433Swyllys static KMF_RETURN 38835b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen, 38845b3e1433Swyllys STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist) 38855b3e1433Swyllys { 38865b3e1433Swyllys KMF_RETURN ret = KMF_OK; 38875b3e1433Swyllys PKCS8_PRIV_KEY_INFO *p8 = NULL; 38885b3e1433Swyllys EVP_PKEY *pkey = NULL; 38895b3e1433Swyllys X509 *xcert = NULL; 3890300fdee2SAndy Fiddaman const ASN1_TYPE *keyid = NULL; 3891300fdee2SAndy Fiddaman const ASN1_TYPE *fname = NULL; 38925b3e1433Swyllys uchar_t *data = NULL; 38935b3e1433Swyllys 3894300fdee2SAndy Fiddaman keyid = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID); 3895300fdee2SAndy Fiddaman fname = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName); 38965b3e1433Swyllys 3897300fdee2SAndy Fiddaman switch (PKCS12_SAFEBAG_get_nid(bag)) { 38985b3e1433Swyllys case NID_keyBag: 38995b3e1433Swyllys if (keylist == NULL) 39005b3e1433Swyllys goto end; 3901300fdee2SAndy Fiddaman pkey = EVP_PKCS82PKEY( 3902300fdee2SAndy Fiddaman PKCS12_SAFEBAG_get0_p8inf(bag)); 39035b3e1433Swyllys if (pkey == NULL) 39045b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39055b3e1433Swyllys 39065b3e1433Swyllys break; 39075b3e1433Swyllys case NID_pkcs8ShroudedKeyBag: 39085b3e1433Swyllys if (keylist == NULL) 39095b3e1433Swyllys goto end; 3910300fdee2SAndy Fiddaman p8 = PKCS12_decrypt_skey(bag, pass, passlen); 39115b3e1433Swyllys if (p8 == NULL) 39125b3e1433Swyllys return (KMF_ERR_AUTH_FAILED); 39135b3e1433Swyllys pkey = EVP_PKCS82PKEY(p8); 39145b3e1433Swyllys PKCS8_PRIV_KEY_INFO_free(p8); 39155b3e1433Swyllys if (pkey == NULL) 39165b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39175b3e1433Swyllys break; 39185b3e1433Swyllys case NID_certBag: 39195b3e1433Swyllys if (certlist == NULL) 39205b3e1433Swyllys goto end; 3921300fdee2SAndy Fiddaman if (PKCS12_SAFEBAG_get_bag_nid(bag) != 3922300fdee2SAndy Fiddaman NID_x509Certificate) 39235b3e1433Swyllys return (KMF_ERR_PKCS12_FORMAT); 3924300fdee2SAndy Fiddaman xcert = PKCS12_SAFEBAG_get1_cert(bag); 39255b3e1433Swyllys if (xcert == NULL) { 39265b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39275b3e1433Swyllys goto end; 39285b3e1433Swyllys } 39295b3e1433Swyllys if (keyid != NULL) { 39305b3e1433Swyllys if (X509_keyid_set1(xcert, 39315b3e1433Swyllys keyid->value.octet_string->data, 39325b3e1433Swyllys keyid->value.octet_string->length) == 0) { 39335b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39345b3e1433Swyllys goto end; 39355b3e1433Swyllys } 39365b3e1433Swyllys } 39375b3e1433Swyllys if (fname != NULL) { 39385b3e1433Swyllys int len, r; 39395b3e1433Swyllys len = ASN1_STRING_to_UTF8(&data, 39405b3e1433Swyllys fname->value.asn1_string); 39415b3e1433Swyllys if (len > 0 && data != NULL) { 39425b3e1433Swyllys r = X509_alias_set1(xcert, data, len); 3943*f810c7e5SToomas Soome if (r == 0) { 39445b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39455b3e1433Swyllys goto end; 39465b3e1433Swyllys } 39475b3e1433Swyllys } else { 39485b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39495b3e1433Swyllys goto end; 39505b3e1433Swyllys } 39515b3e1433Swyllys } 39525b3e1433Swyllys if (sk_X509_push(certlist, xcert) == 0) 39535b3e1433Swyllys ret = KMF_ERR_MEMORY; 39545b3e1433Swyllys else 39555b3e1433Swyllys xcert = NULL; 39565b3e1433Swyllys break; 39575b3e1433Swyllys case NID_safeContentsBag: 3958300fdee2SAndy Fiddaman return (openssl_parse_bags( 3959300fdee2SAndy Fiddaman PKCS12_SAFEBAG_get0_safes(bag), 3960300fdee2SAndy Fiddaman pass, keylist, certlist)); 39615b3e1433Swyllys default: 39625b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39635b3e1433Swyllys break; 39645b3e1433Swyllys } 39655b3e1433Swyllys 39665b3e1433Swyllys /* 39675b3e1433Swyllys * Set the ID and/or FriendlyName attributes on the key. 39685b3e1433Swyllys * If converting to PKCS11 objects, these can translate to CKA_ID 39695b3e1433Swyllys * and CKA_LABEL values. 39705b3e1433Swyllys */ 39715b3e1433Swyllys if (pkey != NULL && ret == KMF_OK) { 39725b3e1433Swyllys ASN1_TYPE *attr = NULL; 39735b3e1433Swyllys if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) { 39745b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) 39755b3e1433Swyllys return (KMF_ERR_MEMORY); 39765b3e1433Swyllys attr->value.octet_string = 39775b3e1433Swyllys ASN1_STRING_dup(keyid->value.octet_string); 39785b3e1433Swyllys attr->type = V_ASN1_OCTET_STRING; 39795b3e1433Swyllys attr->value.ptr = (char *)attr->value.octet_string; 39805b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_localKeyID); 39815b3e1433Swyllys OPENSSL_free(attr); 39825b3e1433Swyllys } 39835b3e1433Swyllys 39845b3e1433Swyllys if (ret == KMF_OK && fname != NULL && 39855b3e1433Swyllys fname->type == V_ASN1_BMPSTRING) { 39865b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) 39875b3e1433Swyllys return (KMF_ERR_MEMORY); 39885b3e1433Swyllys attr->value.bmpstring = 39895b3e1433Swyllys ASN1_STRING_dup(fname->value.bmpstring); 39905b3e1433Swyllys attr->type = V_ASN1_BMPSTRING; 39915b3e1433Swyllys attr->value.ptr = (char *)attr->value.bmpstring; 39925b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_friendlyName); 39935b3e1433Swyllys OPENSSL_free(attr); 39945b3e1433Swyllys } 39955b3e1433Swyllys 39965b3e1433Swyllys if (ret == KMF_OK && keylist != NULL && 39975b3e1433Swyllys sk_EVP_PKEY_push(keylist, pkey) == 0) 39985b3e1433Swyllys ret = KMF_ERR_MEMORY; 39995b3e1433Swyllys } 40005b3e1433Swyllys if (ret == KMF_OK && keylist != NULL) 40015b3e1433Swyllys pkey = NULL; 40025b3e1433Swyllys end: 40035b3e1433Swyllys if (pkey != NULL) 40045b3e1433Swyllys EVP_PKEY_free(pkey); 40055b3e1433Swyllys if (xcert != NULL) 40065b3e1433Swyllys X509_free(xcert); 40075b3e1433Swyllys if (data != NULL) 40085b3e1433Swyllys OPENSSL_free(data); 40095b3e1433Swyllys 40105b3e1433Swyllys return (ret); 40115b3e1433Swyllys } 40125b3e1433Swyllys 40135b3e1433Swyllys static KMF_RETURN 40145b3e1433Swyllys openssl_pkcs12_parse(PKCS12 *p12, char *pin, 40155b3e1433Swyllys STACK_OF(EVP_PKEY) *keys, 40165b3e1433Swyllys STACK_OF(X509) *certs, 40175b3e1433Swyllys STACK_OF(X509) *ca) 4018a2d4930dSDan OpenSolaris Anderson /* ARGSUSED3 */ 40195b3e1433Swyllys { 40205b3e1433Swyllys KMF_RETURN ret = KMF_OK; 40215b3e1433Swyllys STACK_OF(PKCS7) *asafes = NULL; 40225b3e1433Swyllys STACK_OF(PKCS12_SAFEBAG) *bags = NULL; 40235b3e1433Swyllys int i, bagnid; 40245b3e1433Swyllys PKCS7 *p7; 40255b3e1433Swyllys 40265b3e1433Swyllys if (p12 == NULL || (keys == NULL && certs == NULL)) 40275b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 40285b3e1433Swyllys 4029*f810c7e5SToomas Soome if (pin == NULL || *pin == '\0') { 40305b3e1433Swyllys if (PKCS12_verify_mac(p12, NULL, 0)) { 40315b3e1433Swyllys pin = NULL; 40325b3e1433Swyllys } else if (PKCS12_verify_mac(p12, "", 0)) { 40335b3e1433Swyllys pin = ""; 40345b3e1433Swyllys } else { 40355b3e1433Swyllys return (KMF_ERR_AUTH_FAILED); 40365b3e1433Swyllys } 40375b3e1433Swyllys } else if (!PKCS12_verify_mac(p12, pin, -1)) { 40385b3e1433Swyllys return (KMF_ERR_AUTH_FAILED); 40395b3e1433Swyllys } 40405b3e1433Swyllys 40415b3e1433Swyllys if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) 40425b3e1433Swyllys return (KMF_ERR_PKCS12_FORMAT); 40435b3e1433Swyllys 40445b3e1433Swyllys for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) { 40455b3e1433Swyllys bags = NULL; 4046d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 40475b3e1433Swyllys p7 = sk_PKCS7_value(asafes, i); 40485b3e1433Swyllys bagnid = OBJ_obj2nid(p7->type); 40495b3e1433Swyllys 40505b3e1433Swyllys if (bagnid == NID_pkcs7_data) { 40515b3e1433Swyllys bags = PKCS12_unpack_p7data(p7); 40525b3e1433Swyllys } else if (bagnid == NID_pkcs7_encrypted) { 40535b3e1433Swyllys bags = PKCS12_unpack_p7encdata(p7, pin, 40545b3e1433Swyllys (pin ? strlen(pin) : 0)); 40555b3e1433Swyllys } else { 40565b3e1433Swyllys continue; 40575b3e1433Swyllys } 40585b3e1433Swyllys if (bags == NULL) { 40595b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 40605b3e1433Swyllys goto out; 40615b3e1433Swyllys } 40625b3e1433Swyllys 40635b3e1433Swyllys if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK) 40645b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 40655b3e1433Swyllys 40665b3e1433Swyllys sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 40675b3e1433Swyllys } 40685b3e1433Swyllys out: 40695b3e1433Swyllys if (asafes != NULL) 40705b3e1433Swyllys sk_PKCS7_pop_free(asafes, PKCS7_free); 40715b3e1433Swyllys 40725b3e1433Swyllys return (ret); 40735b3e1433Swyllys } 40745b3e1433Swyllys 407599ebb4caSwyllys /* 407699ebb4caSwyllys * Helper function to decrypt and parse PKCS#12 import file. 407799ebb4caSwyllys */ 407899ebb4caSwyllys static KMF_RETURN 407999ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen, 40805b3e1433Swyllys STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs, 40815b3e1433Swyllys STACK_OF(X509) **ca) 4082a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */ 408399ebb4caSwyllys { 408499ebb4caSwyllys PKCS12 *pk12, *pk12_tmp; 40855b3e1433Swyllys STACK_OF(EVP_PKEY) *pkeylist = NULL; 40865b3e1433Swyllys STACK_OF(X509) *xcertlist = NULL; 40875b3e1433Swyllys STACK_OF(X509) *cacertlist = NULL; 408899ebb4caSwyllys 408999ebb4caSwyllys if ((pk12 = PKCS12_new()) == NULL) { 409099ebb4caSwyllys return (KMF_ERR_MEMORY); 409199ebb4caSwyllys } 409299ebb4caSwyllys 409399ebb4caSwyllys if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) { 409499ebb4caSwyllys /* This is ok; it seems to mean there is no more to read. */ 409599ebb4caSwyllys if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 && 409699ebb4caSwyllys ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG) 409799ebb4caSwyllys goto end_extract_pkcs12; 409899ebb4caSwyllys 409999ebb4caSwyllys PKCS12_free(pk12); 410099ebb4caSwyllys return (KMF_ERR_PKCS12_FORMAT); 410199ebb4caSwyllys } 410299ebb4caSwyllys pk12 = pk12_tmp; 410399ebb4caSwyllys 41045b3e1433Swyllys xcertlist = sk_X509_new_null(); 41055b3e1433Swyllys if (xcertlist == NULL) { 41065b3e1433Swyllys PKCS12_free(pk12); 41075b3e1433Swyllys return (KMF_ERR_MEMORY); 41085b3e1433Swyllys } 41095b3e1433Swyllys pkeylist = sk_EVP_PKEY_new_null(); 41105b3e1433Swyllys if (pkeylist == NULL) { 41115b3e1433Swyllys sk_X509_pop_free(xcertlist, X509_free); 41125b3e1433Swyllys PKCS12_free(pk12); 41135b3e1433Swyllys return (KMF_ERR_MEMORY); 41145b3e1433Swyllys } 41155b3e1433Swyllys 41165b3e1433Swyllys if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist, 41175b3e1433Swyllys cacertlist) != KMF_OK) { 41185b3e1433Swyllys sk_X509_pop_free(xcertlist, X509_free); 41195b3e1433Swyllys sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free); 412099ebb4caSwyllys PKCS12_free(pk12); 412199ebb4caSwyllys return (KMF_ERR_PKCS12_FORMAT); 412299ebb4caSwyllys } 412399ebb4caSwyllys 41245b3e1433Swyllys if (priv_key && pkeylist) 41255b3e1433Swyllys *priv_key = pkeylist; 41265b3e1433Swyllys else if (pkeylist) 41275b3e1433Swyllys sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free); 41285b3e1433Swyllys if (certs && xcertlist) 41295b3e1433Swyllys *certs = xcertlist; 41305b3e1433Swyllys else if (xcertlist) 41315b3e1433Swyllys sk_X509_pop_free(xcertlist, X509_free); 41325b3e1433Swyllys if (ca && cacertlist) 41335b3e1433Swyllys *ca = cacertlist; 41345b3e1433Swyllys else if (cacertlist) 41355b3e1433Swyllys sk_X509_pop_free(cacertlist, X509_free); 413699ebb4caSwyllys 41375b3e1433Swyllys end_extract_pkcs12: 413899ebb4caSwyllys 413999ebb4caSwyllys PKCS12_free(pk12); 414099ebb4caSwyllys return (KMF_OK); 414199ebb4caSwyllys } 414299ebb4caSwyllys 414399ebb4caSwyllys static KMF_RETURN 414499ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to) 414599ebb4caSwyllys { 414699ebb4caSwyllys KMF_RETURN rv = KMF_OK; 414799ebb4caSwyllys uint32_t sz; 414899ebb4caSwyllys 414999ebb4caSwyllys sz = BN_num_bytes(from); 415099ebb4caSwyllys to->val = (uchar_t *)malloc(sz); 415199ebb4caSwyllys if (to->val == NULL) 415299ebb4caSwyllys return (KMF_ERR_MEMORY); 415399ebb4caSwyllys 415499ebb4caSwyllys if ((to->len = BN_bn2bin(from, to->val)) != sz) { 415599ebb4caSwyllys free(to->val); 415699ebb4caSwyllys to->val = NULL; 415799ebb4caSwyllys to->len = 0; 415899ebb4caSwyllys rv = KMF_ERR_MEMORY; 415999ebb4caSwyllys } 416099ebb4caSwyllys 416199ebb4caSwyllys return (rv); 416299ebb4caSwyllys } 416399ebb4caSwyllys 416499ebb4caSwyllys static KMF_RETURN 416599ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key) 416699ebb4caSwyllys { 416799ebb4caSwyllys KMF_RETURN rv; 416899ebb4caSwyllys KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa; 416999ebb4caSwyllys 4170300fdee2SAndy Fiddaman const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmpq, *iqmp; 4171300fdee2SAndy Fiddaman 4172300fdee2SAndy Fiddaman RSA_get0_key(rsa, &n, &e, &d); 4173300fdee2SAndy Fiddaman RSA_get0_factors(rsa, &p, &q); 4174300fdee2SAndy Fiddaman RSA_get0_crt_params(rsa, &dmp1, &dmpq, &iqmp); 4175300fdee2SAndy Fiddaman 417699ebb4caSwyllys (void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY)); 4177300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)n, &kmfkey->mod)) != KMF_OK) 417899ebb4caSwyllys goto cleanup; 417999ebb4caSwyllys 4180300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)e, &kmfkey->pubexp)) != KMF_OK) 418199ebb4caSwyllys goto cleanup; 418299ebb4caSwyllys 4183300fdee2SAndy Fiddaman if (d != NULL) 4184300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)d, &kmfkey->priexp)) != KMF_OK) 418599ebb4caSwyllys goto cleanup; 418699ebb4caSwyllys 4187300fdee2SAndy Fiddaman if (p != NULL) 4188300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime1)) != KMF_OK) 418999ebb4caSwyllys goto cleanup; 419099ebb4caSwyllys 4191300fdee2SAndy Fiddaman if (q != NULL) 4192300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->prime2)) != KMF_OK) 419399ebb4caSwyllys goto cleanup; 419499ebb4caSwyllys 4195300fdee2SAndy Fiddaman if (dmp1 != NULL) 4196300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)dmp1, &kmfkey->exp1)) != KMF_OK) 419799ebb4caSwyllys goto cleanup; 419899ebb4caSwyllys 4199300fdee2SAndy Fiddaman if (dmpq != NULL) 4200300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)dmpq, &kmfkey->exp2)) != KMF_OK) 420199ebb4caSwyllys goto cleanup; 420299ebb4caSwyllys 4203300fdee2SAndy Fiddaman if (iqmp != NULL) 4204300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)iqmp, &kmfkey->coef)) != KMF_OK) 420599ebb4caSwyllys goto cleanup; 420699ebb4caSwyllys cleanup: 420799ebb4caSwyllys if (rv != KMF_OK) 420830a5e8faSwyllys kmf_free_raw_key(key); 420999ebb4caSwyllys else 421099ebb4caSwyllys key->keytype = KMF_RSA; 421199ebb4caSwyllys 421299ebb4caSwyllys /* 421399ebb4caSwyllys * Free the reference to this key, SSL will not actually free 421499ebb4caSwyllys * the memory until the refcount == 0, so this is safe. 421599ebb4caSwyllys */ 421699ebb4caSwyllys RSA_free(rsa); 421799ebb4caSwyllys 421899ebb4caSwyllys return (rv); 421999ebb4caSwyllys } 422099ebb4caSwyllys 422199ebb4caSwyllys static KMF_RETURN 422299ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key) 422399ebb4caSwyllys { 422499ebb4caSwyllys KMF_RETURN rv; 422599ebb4caSwyllys KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa; 4226300fdee2SAndy Fiddaman const BIGNUM *p, *q, *g, *priv_key; 4227300fdee2SAndy Fiddaman 4228300fdee2SAndy Fiddaman DSA_get0_pqg(dsa, &p, &q, &g); 4229300fdee2SAndy Fiddaman DSA_get0_key(dsa, NULL, &priv_key); 423099ebb4caSwyllys 423199ebb4caSwyllys (void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY)); 4232300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime)) != KMF_OK) 423399ebb4caSwyllys goto cleanup; 423499ebb4caSwyllys 4235300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->subprime)) != KMF_OK) 423699ebb4caSwyllys goto cleanup; 423799ebb4caSwyllys 4238300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)g, &kmfkey->base)) != KMF_OK) 423999ebb4caSwyllys goto cleanup; 424099ebb4caSwyllys 4241300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)priv_key, &kmfkey->value)) != KMF_OK) 424299ebb4caSwyllys goto cleanup; 424399ebb4caSwyllys 424499ebb4caSwyllys cleanup: 424599ebb4caSwyllys if (rv != KMF_OK) 424630a5e8faSwyllys kmf_free_raw_key(key); 424799ebb4caSwyllys else 424899ebb4caSwyllys key->keytype = KMF_DSA; 424999ebb4caSwyllys 425099ebb4caSwyllys /* 425199ebb4caSwyllys * Free the reference to this key, SSL will not actually free 425299ebb4caSwyllys * the memory until the refcount == 0, so this is safe. 425399ebb4caSwyllys */ 425499ebb4caSwyllys DSA_free(dsa); 425599ebb4caSwyllys 425699ebb4caSwyllys return (rv); 425799ebb4caSwyllys } 425899ebb4caSwyllys 425999ebb4caSwyllys static KMF_RETURN 426099ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert, 42615b3e1433Swyllys KMF_X509_DER_CERT **certlist, int *ncerts) 426299ebb4caSwyllys { 426399ebb4caSwyllys KMF_RETURN rv = KMF_OK; 42645b3e1433Swyllys KMF_X509_DER_CERT *list = (*certlist); 42655b3e1433Swyllys KMF_X509_DER_CERT cert; 426699ebb4caSwyllys int n = (*ncerts); 426799ebb4caSwyllys 426899ebb4caSwyllys if (list == NULL) { 42695b3e1433Swyllys list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT)); 427099ebb4caSwyllys } else { 42715b3e1433Swyllys list = (KMF_X509_DER_CERT *)realloc(list, 42725b3e1433Swyllys sizeof (KMF_X509_DER_CERT) * (n + 1)); 427399ebb4caSwyllys } 427499ebb4caSwyllys 427599ebb4caSwyllys if (list == NULL) 427699ebb4caSwyllys return (KMF_ERR_MEMORY); 427799ebb4caSwyllys 42785b3e1433Swyllys (void) memset(&cert, 0, sizeof (cert)); 42795b3e1433Swyllys rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate); 428099ebb4caSwyllys if (rv == KMF_OK) { 42815b3e1433Swyllys int len = 0; 42825b3e1433Swyllys /* Get the alias name for the cert if there is one */ 42835b3e1433Swyllys char *a = (char *)X509_alias_get0(sslcert, &len); 42845b3e1433Swyllys if (a != NULL) 42855b3e1433Swyllys cert.kmf_private.label = strdup(a); 42865b3e1433Swyllys cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL; 42875b3e1433Swyllys 428899ebb4caSwyllys list[n] = cert; 428999ebb4caSwyllys (*ncerts) = n + 1; 429099ebb4caSwyllys 429199ebb4caSwyllys *certlist = list; 429299ebb4caSwyllys } else { 429399ebb4caSwyllys free(list); 429499ebb4caSwyllys } 429599ebb4caSwyllys 429699ebb4caSwyllys return (rv); 429799ebb4caSwyllys } 429899ebb4caSwyllys 429999ebb4caSwyllys static KMF_RETURN 430099ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist, 430199ebb4caSwyllys KMF_RAW_KEY_DATA *newkey, int *nkeys) 430299ebb4caSwyllys { 430399ebb4caSwyllys KMF_RAW_KEY_DATA *list = (*keylist); 430499ebb4caSwyllys int n = (*nkeys); 430599ebb4caSwyllys 430699ebb4caSwyllys if (list == NULL) { 430799ebb4caSwyllys list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA)); 430899ebb4caSwyllys } else { 430999ebb4caSwyllys list = (KMF_RAW_KEY_DATA *)realloc(list, 431099ebb4caSwyllys sizeof (KMF_RAW_KEY_DATA) * (n + 1)); 431199ebb4caSwyllys } 431299ebb4caSwyllys 431399ebb4caSwyllys if (list == NULL) 431499ebb4caSwyllys return (KMF_ERR_MEMORY); 431599ebb4caSwyllys 431699ebb4caSwyllys list[n] = *newkey; 431799ebb4caSwyllys (*nkeys) = n + 1; 431899ebb4caSwyllys 431999ebb4caSwyllys *keylist = list; 432099ebb4caSwyllys 432199ebb4caSwyllys return (KMF_OK); 432299ebb4caSwyllys } 432399ebb4caSwyllys 432430a5e8faSwyllys static KMF_RETURN 432530a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key) 432630a5e8faSwyllys { 432730a5e8faSwyllys KMF_RETURN rv = KMF_OK; 43285b3e1433Swyllys X509_ATTRIBUTE *attr; 4329300fdee2SAndy Fiddaman RSA *rsa; 4330300fdee2SAndy Fiddaman DSA *dsa; 4331300fdee2SAndy Fiddaman int loc; 433230a5e8faSwyllys 433330a5e8faSwyllys if (pkey == NULL || key == NULL) 433430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 433530a5e8faSwyllys /* Convert SSL key to raw key */ 4336300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get1_RSA(pkey)) != NULL) { 4337300fdee2SAndy Fiddaman rv = exportRawRSAKey(rsa, key); 433830a5e8faSwyllys if (rv != KMF_OK) 433930a5e8faSwyllys return (rv); 4340300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get1_DSA(pkey)) != NULL) { 4341300fdee2SAndy Fiddaman rv = exportRawDSAKey(dsa, key); 434230a5e8faSwyllys if (rv != KMF_OK) 434330a5e8faSwyllys return (rv); 4344300fdee2SAndy Fiddaman } else 434530a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 4346300fdee2SAndy Fiddaman 43475b3e1433Swyllys /* 43485b3e1433Swyllys * If friendlyName, add it to record. 43495b3e1433Swyllys */ 4350300fdee2SAndy Fiddaman 4351300fdee2SAndy Fiddaman if ((loc = EVP_PKEY_get_attr_by_NID(pkey, 4352300fdee2SAndy Fiddaman NID_friendlyName, -1)) != -1 && 4353300fdee2SAndy Fiddaman (attr = EVP_PKEY_get_attr(pkey, loc))) { 43545b3e1433Swyllys ASN1_TYPE *ty = NULL; 4355300fdee2SAndy Fiddaman int numattr = X509_ATTRIBUTE_count(attr); 4356300fdee2SAndy Fiddaman if (numattr > 0) { 4357300fdee2SAndy Fiddaman ty = X509_ATTRIBUTE_get0_type(attr, 0); 43585b3e1433Swyllys } 43595b3e1433Swyllys if (ty != NULL) { 436070f9559bSTheo Schlossnagle key->label = OPENSSL_uni2asc(ty->value.bmpstring->data, 436170f9559bSTheo Schlossnagle ty->value.bmpstring->length); 43625b3e1433Swyllys } 43635b3e1433Swyllys } else { 43645b3e1433Swyllys key->label = NULL; 43655b3e1433Swyllys } 43665b3e1433Swyllys 43675b3e1433Swyllys /* 43685b3e1433Swyllys * If KeyID, add it to record as a KMF_DATA object. 43695b3e1433Swyllys */ 4370300fdee2SAndy Fiddaman if ((loc = EVP_PKEY_get_attr_by_NID(pkey, 4371300fdee2SAndy Fiddaman NID_localKeyID, -1)) != -1 && 4372300fdee2SAndy Fiddaman (attr = EVP_PKEY_get_attr(pkey, loc)) != NULL) { 43735b3e1433Swyllys ASN1_TYPE *ty = NULL; 4374300fdee2SAndy Fiddaman int numattr = X509_ATTRIBUTE_count(attr); 4375300fdee2SAndy Fiddaman if (numattr > 0) 4376300fdee2SAndy Fiddaman ty = X509_ATTRIBUTE_get0_type(attr, 0); 43775b3e1433Swyllys key->id.Data = (uchar_t *)malloc( 43785b3e1433Swyllys ty->value.octet_string->length); 43795b3e1433Swyllys if (key->id.Data == NULL) 43805b3e1433Swyllys return (KMF_ERR_MEMORY); 43815b3e1433Swyllys (void) memcpy(key->id.Data, ty->value.octet_string->data, 43825b3e1433Swyllys ty->value.octet_string->length); 43835b3e1433Swyllys key->id.Length = ty->value.octet_string->length; 43845b3e1433Swyllys } else { 43855b3e1433Swyllys (void) memset(&key->id, 0, sizeof (KMF_DATA)); 43865b3e1433Swyllys } 438730a5e8faSwyllys 438830a5e8faSwyllys return (rv); 438930a5e8faSwyllys } 439099ebb4caSwyllys 439199ebb4caSwyllys static KMF_RETURN 439299ebb4caSwyllys convertPK12Objects( 439399ebb4caSwyllys KMF_HANDLE *kmfh, 43945b3e1433Swyllys STACK_OF(EVP_PKEY) *sslkeys, 43955b3e1433Swyllys STACK_OF(X509) *sslcert, 43965b3e1433Swyllys STACK_OF(X509) *sslcacerts, 439799ebb4caSwyllys KMF_RAW_KEY_DATA **keylist, int *nkeys, 43985b3e1433Swyllys KMF_X509_DER_CERT **certlist, int *ncerts) 439999ebb4caSwyllys { 440099ebb4caSwyllys KMF_RETURN rv = KMF_OK; 440199ebb4caSwyllys KMF_RAW_KEY_DATA key; 440299ebb4caSwyllys int i; 440399ebb4caSwyllys 44045b3e1433Swyllys for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) { 4405d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 44065b3e1433Swyllys EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i); 44075b3e1433Swyllys rv = convertToRawKey(pkey, &key); 440830a5e8faSwyllys if (rv == KMF_OK) 440999ebb4caSwyllys rv = add_key_to_list(keylist, &key, nkeys); 441030a5e8faSwyllys 441199ebb4caSwyllys if (rv != KMF_OK) 441299ebb4caSwyllys return (rv); 441399ebb4caSwyllys } 441499ebb4caSwyllys 441599ebb4caSwyllys /* Now add the certificate to the certlist */ 44165b3e1433Swyllys for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) { 4417d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 44185b3e1433Swyllys X509 *cert = sk_X509_value(sslcert, i); 44195b3e1433Swyllys rv = add_cert_to_list(kmfh, cert, certlist, ncerts); 442099ebb4caSwyllys if (rv != KMF_OK) 442199ebb4caSwyllys return (rv); 442299ebb4caSwyllys } 442399ebb4caSwyllys 442499ebb4caSwyllys /* Also add any included CA certs to the list */ 442571593db2Swyllys for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) { 442699ebb4caSwyllys X509 *c; 442799ebb4caSwyllys /* 442899ebb4caSwyllys * sk_X509_value() is macro that embeds a cast to (X509 *). 442999ebb4caSwyllys * Here it translates into ((X509 *)sk_value((ca), (i))). 443099ebb4caSwyllys * Lint is complaining about the embedded casting, and 443199ebb4caSwyllys * to fix it, you need to fix openssl header files. 443299ebb4caSwyllys */ 4433d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 443499ebb4caSwyllys c = sk_X509_value(sslcacerts, i); 443599ebb4caSwyllys 443699ebb4caSwyllys /* Now add the ca cert to the certlist */ 443799ebb4caSwyllys rv = add_cert_to_list(kmfh, c, certlist, ncerts); 443899ebb4caSwyllys if (rv != KMF_OK) 443999ebb4caSwyllys return (rv); 444099ebb4caSwyllys } 444199ebb4caSwyllys return (rv); 444299ebb4caSwyllys } 444399ebb4caSwyllys 444499ebb4caSwyllys KMF_RETURN 444530a5e8faSwyllys openssl_import_objects(KMF_HANDLE *kmfh, 444699ebb4caSwyllys char *filename, KMF_CREDENTIAL *cred, 44475b3e1433Swyllys KMF_X509_DER_CERT **certlist, int *ncerts, 444899ebb4caSwyllys KMF_RAW_KEY_DATA **keylist, int *nkeys) 444999ebb4caSwyllys { 445099ebb4caSwyllys KMF_RETURN rv = KMF_OK; 445130a5e8faSwyllys KMF_ENCODE_FORMAT format; 445230a5e8faSwyllys BIO *bio = NULL; 44535b3e1433Swyllys STACK_OF(EVP_PKEY) *privkeys = NULL; 44545b3e1433Swyllys STACK_OF(X509) *certs = NULL; 445599ebb4caSwyllys STACK_OF(X509) *cacerts = NULL; 445699ebb4caSwyllys 445730a5e8faSwyllys /* 445830a5e8faSwyllys * auto-detect the file format, regardless of what 445930a5e8faSwyllys * the 'format' parameters in the params say. 446030a5e8faSwyllys */ 446130a5e8faSwyllys rv = kmf_get_file_format(filename, &format); 446230a5e8faSwyllys if (rv != KMF_OK) { 446330a5e8faSwyllys return (rv); 446430a5e8faSwyllys } 446530a5e8faSwyllys 446630a5e8faSwyllys /* This function only works for PEM or PKCS#12 files */ 446730a5e8faSwyllys if (format != KMF_FORMAT_PEM && 446830a5e8faSwyllys format != KMF_FORMAT_PEM_KEYPAIR && 446930a5e8faSwyllys format != KMF_FORMAT_PKCS12) 447030a5e8faSwyllys return (KMF_ERR_ENCODING); 447130a5e8faSwyllys 447230a5e8faSwyllys *certlist = NULL; 447330a5e8faSwyllys *keylist = NULL; 447430a5e8faSwyllys *ncerts = 0; 447530a5e8faSwyllys *nkeys = 0; 447630a5e8faSwyllys 447730a5e8faSwyllys if (format == KMF_FORMAT_PKCS12) { 447899ebb4caSwyllys bio = BIO_new_file(filename, "rb"); 447999ebb4caSwyllys if (bio == NULL) { 448099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 448199ebb4caSwyllys rv = KMF_ERR_OPEN_FILE; 448299ebb4caSwyllys goto end; 448399ebb4caSwyllys } 448499ebb4caSwyllys 448534acef67Swyllys rv = extract_pkcs12(bio, (uchar_t *)cred->cred, 44865b3e1433Swyllys (uint32_t)cred->credlen, &privkeys, &certs, &cacerts); 448799ebb4caSwyllys 448899ebb4caSwyllys if (rv == KMF_OK) 448999ebb4caSwyllys /* Convert keys and certs to exportable format */ 44905b3e1433Swyllys rv = convertPK12Objects(kmfh, privkeys, certs, cacerts, 449199ebb4caSwyllys keylist, nkeys, certlist, ncerts); 449230a5e8faSwyllys } else { 44935b3e1433Swyllys EVP_PKEY *pkey; 44945b3e1433Swyllys KMF_DATA *certdata = NULL; 44955b3e1433Swyllys KMF_X509_DER_CERT *kmfcerts = NULL; 44965b3e1433Swyllys int i; 449730a5e8faSwyllys rv = extract_pem(kmfh, NULL, NULL, NULL, filename, 449834acef67Swyllys (uchar_t *)cred->cred, (uint32_t)cred->credlen, 44995b3e1433Swyllys &pkey, &certdata, ncerts); 450071593db2Swyllys 450171593db2Swyllys /* Reached end of import file? */ 45025b3e1433Swyllys if (rv == KMF_OK && pkey != NULL) { 45035b3e1433Swyllys privkeys = sk_EVP_PKEY_new_null(); 45045b3e1433Swyllys if (privkeys == NULL) { 45055b3e1433Swyllys rv = KMF_ERR_MEMORY; 45065b3e1433Swyllys goto end; 45075b3e1433Swyllys } 45085b3e1433Swyllys (void) sk_EVP_PKEY_push(privkeys, pkey); 45095b3e1433Swyllys /* convert the certificate list here */ 45105b3e1433Swyllys if (*ncerts > 0 && certlist != NULL) { 4511e65e5c2dSWyllys Ingersoll kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts, 45125b3e1433Swyllys sizeof (KMF_X509_DER_CERT)); 45135b3e1433Swyllys if (kmfcerts == NULL) { 45145b3e1433Swyllys rv = KMF_ERR_MEMORY; 45155b3e1433Swyllys goto end; 45165b3e1433Swyllys } 45175b3e1433Swyllys for (i = 0; i < *ncerts; i++) { 45185b3e1433Swyllys kmfcerts[i].certificate = certdata[i]; 45195b3e1433Swyllys kmfcerts[i].kmf_private.keystore_type = 45205b3e1433Swyllys KMF_KEYSTORE_OPENSSL; 45215b3e1433Swyllys } 45225b3e1433Swyllys *certlist = kmfcerts; 45235b3e1433Swyllys } 45245b3e1433Swyllys /* 45255b3e1433Swyllys * Convert keys to exportable format, the certs 45265b3e1433Swyllys * are already OK. 45275b3e1433Swyllys */ 45285b3e1433Swyllys rv = convertPK12Objects(kmfh, privkeys, NULL, NULL, 452971593db2Swyllys keylist, nkeys, NULL, NULL); 453030a5e8faSwyllys } 45315b3e1433Swyllys } 453271593db2Swyllys end: 453330a5e8faSwyllys if (bio != NULL) 453499ebb4caSwyllys (void) BIO_free(bio); 453599ebb4caSwyllys 45365b3e1433Swyllys if (privkeys) 45375b3e1433Swyllys sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free); 45385b3e1433Swyllys if (certs) 45395b3e1433Swyllys sk_X509_pop_free(certs, X509_free); 454030a5e8faSwyllys if (cacerts) 45415b3e1433Swyllys sk_X509_pop_free(cacerts, X509_free); 454230a5e8faSwyllys 454399ebb4caSwyllys return (rv); 454499ebb4caSwyllys } 454599ebb4caSwyllys 454699ebb4caSwyllys static KMF_RETURN 454799ebb4caSwyllys create_deskey(DES_cblock **deskey) 454899ebb4caSwyllys { 454999ebb4caSwyllys DES_cblock *key; 455099ebb4caSwyllys 455199ebb4caSwyllys key = (DES_cblock *) malloc(sizeof (DES_cblock)); 455299ebb4caSwyllys if (key == NULL) { 455399ebb4caSwyllys return (KMF_ERR_MEMORY); 455499ebb4caSwyllys } 455599ebb4caSwyllys 455699ebb4caSwyllys if (DES_random_key(key) == 0) { 455799ebb4caSwyllys free(key); 455899ebb4caSwyllys return (KMF_ERR_KEYGEN_FAILED); 455999ebb4caSwyllys } 456099ebb4caSwyllys 456199ebb4caSwyllys *deskey = key; 456299ebb4caSwyllys return (KMF_OK); 456399ebb4caSwyllys } 456499ebb4caSwyllys 456599ebb4caSwyllys #define KEYGEN_RETRY 3 456699ebb4caSwyllys #define DES3_KEY_SIZE 24 456799ebb4caSwyllys 456899ebb4caSwyllys static KMF_RETURN 456999ebb4caSwyllys create_des3key(unsigned char **des3key) 457099ebb4caSwyllys { 457199ebb4caSwyllys KMF_RETURN ret = KMF_OK; 457299ebb4caSwyllys DES_cblock *deskey1 = NULL; 457399ebb4caSwyllys DES_cblock *deskey2 = NULL; 457499ebb4caSwyllys DES_cblock *deskey3 = NULL; 457599ebb4caSwyllys unsigned char *newkey = NULL; 457699ebb4caSwyllys int retry; 457799ebb4caSwyllys 457899ebb4caSwyllys if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) { 457999ebb4caSwyllys return (KMF_ERR_MEMORY); 458099ebb4caSwyllys } 458199ebb4caSwyllys 458299ebb4caSwyllys /* create the 1st DES key */ 458399ebb4caSwyllys if ((ret = create_deskey(&deskey1)) != KMF_OK) { 458499ebb4caSwyllys goto out; 458599ebb4caSwyllys } 458699ebb4caSwyllys 458799ebb4caSwyllys /* 458899ebb4caSwyllys * Create the 2nd DES key and make sure its value is different 458999ebb4caSwyllys * from the 1st DES key. 459099ebb4caSwyllys */ 459199ebb4caSwyllys retry = 0; 459299ebb4caSwyllys do { 459399ebb4caSwyllys if (deskey2 != NULL) { 459499ebb4caSwyllys free(deskey2); 459599ebb4caSwyllys deskey2 = NULL; 459699ebb4caSwyllys } 459799ebb4caSwyllys 459899ebb4caSwyllys if ((ret = create_deskey(&deskey2)) != KMF_OK) { 459999ebb4caSwyllys goto out; 460099ebb4caSwyllys } 460199ebb4caSwyllys 460299ebb4caSwyllys if (memcmp((const void *) deskey1, (const void *) deskey2, 8) 460399ebb4caSwyllys == 0) { 460499ebb4caSwyllys ret = KMF_ERR_KEYGEN_FAILED; 460599ebb4caSwyllys retry++; 460699ebb4caSwyllys } 460799ebb4caSwyllys } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY); 460899ebb4caSwyllys 460999ebb4caSwyllys if (ret != KMF_OK) { 461099ebb4caSwyllys goto out; 461199ebb4caSwyllys } 461299ebb4caSwyllys 461399ebb4caSwyllys /* 461499ebb4caSwyllys * Create the 3rd DES key and make sure its value is different 461599ebb4caSwyllys * from the 2nd DES key. 461699ebb4caSwyllys */ 461799ebb4caSwyllys retry = 0; 461899ebb4caSwyllys do { 461999ebb4caSwyllys if (deskey3 != NULL) { 462099ebb4caSwyllys free(deskey3); 462199ebb4caSwyllys deskey3 = NULL; 462299ebb4caSwyllys } 462399ebb4caSwyllys 462499ebb4caSwyllys if ((ret = create_deskey(&deskey3)) != KMF_OK) { 462599ebb4caSwyllys goto out; 462699ebb4caSwyllys } 462799ebb4caSwyllys 462899ebb4caSwyllys if (memcmp((const void *)deskey2, (const void *)deskey3, 8) 462999ebb4caSwyllys == 0) { 463099ebb4caSwyllys ret = KMF_ERR_KEYGEN_FAILED; 463199ebb4caSwyllys retry++; 463299ebb4caSwyllys } 463399ebb4caSwyllys } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY); 463499ebb4caSwyllys 463599ebb4caSwyllys if (ret != KMF_OK) { 463699ebb4caSwyllys goto out; 463799ebb4caSwyllys } 463899ebb4caSwyllys 463999ebb4caSwyllys /* Concatenate 3 DES keys into a DES3 key */ 464099ebb4caSwyllys (void) memcpy((void *)newkey, (const void *)deskey1, 8); 464199ebb4caSwyllys (void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8); 464299ebb4caSwyllys (void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8); 464399ebb4caSwyllys *des3key = newkey; 464499ebb4caSwyllys 464599ebb4caSwyllys out: 464699ebb4caSwyllys if (deskey1 != NULL) 464799ebb4caSwyllys free(deskey1); 464899ebb4caSwyllys 464999ebb4caSwyllys if (deskey2 != NULL) 465099ebb4caSwyllys free(deskey2); 465199ebb4caSwyllys 465299ebb4caSwyllys if (deskey3 != NULL) 465399ebb4caSwyllys free(deskey3); 465499ebb4caSwyllys 465599ebb4caSwyllys if (ret != KMF_OK && newkey != NULL) 465699ebb4caSwyllys free(newkey); 465799ebb4caSwyllys 465899ebb4caSwyllys return (ret); 465999ebb4caSwyllys } 466099ebb4caSwyllys 466199ebb4caSwyllys KMF_RETURN 466230a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle, 466330a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 466499ebb4caSwyllys { 466599ebb4caSwyllys KMF_RETURN ret = KMF_OK; 466699ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 466799ebb4caSwyllys char *fullpath = NULL; 466899ebb4caSwyllys KMF_RAW_SYM_KEY *rkey = NULL; 466999ebb4caSwyllys DES_cblock *deskey = NULL; 467099ebb4caSwyllys unsigned char *des3key = NULL; 467199ebb4caSwyllys unsigned char *random = NULL; 467299ebb4caSwyllys int fd = -1; 467330a5e8faSwyllys KMF_KEY_HANDLE *symkey; 467430a5e8faSwyllys KMF_KEY_ALG keytype; 467530a5e8faSwyllys uint32_t keylen; 467630a5e8faSwyllys uint32_t keylen_size = sizeof (keylen); 467730a5e8faSwyllys char *dirpath; 467830a5e8faSwyllys char *keyfile; 467999ebb4caSwyllys 468099ebb4caSwyllys if (kmfh == NULL) 468199ebb4caSwyllys return (KMF_ERR_UNINITIALIZED); 468299ebb4caSwyllys 468330a5e8faSwyllys symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 468430a5e8faSwyllys if (symkey == NULL) 468599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 468699ebb4caSwyllys 468730a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 468830a5e8faSwyllys 468930a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 469030a5e8faSwyllys if (keyfile == NULL) 469130a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 469230a5e8faSwyllys 469330a5e8faSwyllys ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, 469430a5e8faSwyllys (void *)&keytype, NULL); 469530a5e8faSwyllys if (ret != KMF_OK) 469630a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 469730a5e8faSwyllys 469830a5e8faSwyllys ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, 469930a5e8faSwyllys &keylen, &keylen_size); 470030a5e8faSwyllys if (ret == KMF_ERR_ATTR_NOT_FOUND && 470130a5e8faSwyllys (keytype == KMF_DES || keytype == KMF_DES3)) 470230a5e8faSwyllys /* keylength is not required for DES and 3DES */ 470330a5e8faSwyllys ret = KMF_OK; 470430a5e8faSwyllys if (ret != KMF_OK) 470530a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 470630a5e8faSwyllys 470730a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 470899ebb4caSwyllys if (fullpath == NULL) 470999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 471099ebb4caSwyllys 471199ebb4caSwyllys /* If the requested file exists, return an error */ 471230a5e8faSwyllys if (test_for_file(fullpath, 0400) == 1) { 471399ebb4caSwyllys free(fullpath); 471499ebb4caSwyllys return (KMF_ERR_DUPLICATE_KEYFILE); 471599ebb4caSwyllys } 471699ebb4caSwyllys 471799ebb4caSwyllys fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400); 471899ebb4caSwyllys if (fd == -1) { 471999ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 472099ebb4caSwyllys goto out; 472199ebb4caSwyllys } 472299ebb4caSwyllys 472399ebb4caSwyllys rkey = malloc(sizeof (KMF_RAW_SYM_KEY)); 472499ebb4caSwyllys if (rkey == NULL) { 472599ebb4caSwyllys ret = KMF_ERR_MEMORY; 472699ebb4caSwyllys goto out; 472799ebb4caSwyllys } 472899ebb4caSwyllys (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 472999ebb4caSwyllys 473030a5e8faSwyllys if (keytype == KMF_DES) { 473199ebb4caSwyllys if ((ret = create_deskey(&deskey)) != KMF_OK) { 473299ebb4caSwyllys goto out; 473399ebb4caSwyllys } 473499ebb4caSwyllys rkey->keydata.val = (uchar_t *)deskey; 473599ebb4caSwyllys rkey->keydata.len = 8; 473699ebb4caSwyllys 473799ebb4caSwyllys symkey->keyalg = KMF_DES; 473899ebb4caSwyllys 473930a5e8faSwyllys } else if (keytype == KMF_DES3) { 474099ebb4caSwyllys if ((ret = create_des3key(&des3key)) != KMF_OK) { 474199ebb4caSwyllys goto out; 474299ebb4caSwyllys } 474399ebb4caSwyllys rkey->keydata.val = (uchar_t *)des3key; 474499ebb4caSwyllys rkey->keydata.len = DES3_KEY_SIZE; 474599ebb4caSwyllys symkey->keyalg = KMF_DES3; 47469b37d296Swyllys 474730a5e8faSwyllys } else if (keytype == KMF_AES || keytype == KMF_RC4 || 474830a5e8faSwyllys keytype == KMF_GENERIC_SECRET) { 474999ebb4caSwyllys int bytes; 475099ebb4caSwyllys 475130a5e8faSwyllys if (keylen % 8 != 0) { 475299ebb4caSwyllys ret = KMF_ERR_BAD_KEY_SIZE; 475399ebb4caSwyllys goto out; 475499ebb4caSwyllys } 475599ebb4caSwyllys 475630a5e8faSwyllys if (keytype == KMF_AES) { 475730a5e8faSwyllys if (keylen != 128 && 475830a5e8faSwyllys keylen != 192 && 475930a5e8faSwyllys keylen != 256) { 476099ebb4caSwyllys ret = KMF_ERR_BAD_KEY_SIZE; 476199ebb4caSwyllys goto out; 476299ebb4caSwyllys } 476399ebb4caSwyllys } 476499ebb4caSwyllys 476530a5e8faSwyllys bytes = keylen/8; 476699ebb4caSwyllys random = malloc(bytes); 476799ebb4caSwyllys if (random == NULL) { 476899ebb4caSwyllys ret = KMF_ERR_MEMORY; 476999ebb4caSwyllys goto out; 477099ebb4caSwyllys } 477199ebb4caSwyllys if (RAND_bytes(random, bytes) != 1) { 477299ebb4caSwyllys ret = KMF_ERR_KEYGEN_FAILED; 477399ebb4caSwyllys goto out; 477499ebb4caSwyllys } 477599ebb4caSwyllys 477699ebb4caSwyllys rkey->keydata.val = (uchar_t *)random; 477799ebb4caSwyllys rkey->keydata.len = bytes; 477830a5e8faSwyllys symkey->keyalg = keytype; 477999ebb4caSwyllys 478099ebb4caSwyllys } else { 478199ebb4caSwyllys ret = KMF_ERR_BAD_KEY_TYPE; 478299ebb4caSwyllys goto out; 478399ebb4caSwyllys } 478499ebb4caSwyllys 478599ebb4caSwyllys (void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len); 478699ebb4caSwyllys 478799ebb4caSwyllys symkey->kstype = KMF_KEYSTORE_OPENSSL; 478899ebb4caSwyllys symkey->keyclass = KMF_SYMMETRIC; 478999ebb4caSwyllys symkey->keylabel = (char *)fullpath; 479099ebb4caSwyllys symkey->israw = TRUE; 479199ebb4caSwyllys symkey->keyp = rkey; 479299ebb4caSwyllys 479399ebb4caSwyllys out: 479499ebb4caSwyllys if (fd != -1) 479599ebb4caSwyllys (void) close(fd); 479699ebb4caSwyllys 479799ebb4caSwyllys if (ret != KMF_OK && fullpath != NULL) { 479899ebb4caSwyllys free(fullpath); 479999ebb4caSwyllys } 480099ebb4caSwyllys if (ret != KMF_OK) { 480130a5e8faSwyllys kmf_free_raw_sym_key(rkey); 480299ebb4caSwyllys symkey->keyp = NULL; 480399ebb4caSwyllys symkey->keyalg = KMF_KEYALG_NONE; 480499ebb4caSwyllys } 480599ebb4caSwyllys 480699ebb4caSwyllys return (ret); 480799ebb4caSwyllys } 480899ebb4caSwyllys 480999ebb4caSwyllys /* 481099ebb4caSwyllys * Check a file to see if it is a CRL file with PEM or DER format. 481199ebb4caSwyllys * If success, return its format in the "pformat" argument. 481299ebb4caSwyllys */ 481399ebb4caSwyllys KMF_RETURN 481499ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat) 481599ebb4caSwyllys { 481699ebb4caSwyllys KMF_RETURN ret = KMF_OK; 481799ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 481899ebb4caSwyllys BIO *bio = NULL; 481999ebb4caSwyllys X509_CRL *xcrl = NULL; 482099ebb4caSwyllys 482199ebb4caSwyllys if (filename == NULL) { 482299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 482399ebb4caSwyllys } 482499ebb4caSwyllys 482599ebb4caSwyllys bio = BIO_new_file(filename, "rb"); 482699ebb4caSwyllys if (bio == NULL) { 482799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 482899ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 482999ebb4caSwyllys goto out; 483099ebb4caSwyllys } 483199ebb4caSwyllys 483299ebb4caSwyllys if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) { 483399ebb4caSwyllys *pformat = KMF_FORMAT_PEM; 483499ebb4caSwyllys goto out; 483599ebb4caSwyllys } 483699ebb4caSwyllys (void) BIO_free(bio); 483799ebb4caSwyllys 483899ebb4caSwyllys /* 483999ebb4caSwyllys * Now try to read it as raw DER data. 484099ebb4caSwyllys */ 484199ebb4caSwyllys bio = BIO_new_file(filename, "rb"); 484299ebb4caSwyllys if (bio == NULL) { 484399ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 484499ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 484599ebb4caSwyllys goto out; 484699ebb4caSwyllys } 484799ebb4caSwyllys 484899ebb4caSwyllys if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) { 484999ebb4caSwyllys *pformat = KMF_FORMAT_ASN1; 485099ebb4caSwyllys } else { 485199ebb4caSwyllys ret = KMF_ERR_BAD_CRLFILE; 485299ebb4caSwyllys } 485399ebb4caSwyllys 485499ebb4caSwyllys out: 485599ebb4caSwyllys if (bio != NULL) 485699ebb4caSwyllys (void) BIO_free(bio); 485799ebb4caSwyllys 485899ebb4caSwyllys if (xcrl != NULL) 485999ebb4caSwyllys X509_CRL_free(xcrl); 486099ebb4caSwyllys 486199ebb4caSwyllys return (ret); 486299ebb4caSwyllys } 486399ebb4caSwyllys 486499ebb4caSwyllys KMF_RETURN 486599ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey, 486699ebb4caSwyllys KMF_RAW_SYM_KEY *rkey) 486799ebb4caSwyllys { 486899ebb4caSwyllys KMF_RETURN rv = KMF_OK; 486999ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 487099ebb4caSwyllys KMF_DATA keyvalue; 487199ebb4caSwyllys 487299ebb4caSwyllys if (kmfh == NULL) 487399ebb4caSwyllys return (KMF_ERR_UNINITIALIZED); 487499ebb4caSwyllys 487599ebb4caSwyllys if (symkey == NULL || rkey == NULL) 487699ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 487799ebb4caSwyllys else if (symkey->keyclass != KMF_SYMMETRIC) 487899ebb4caSwyllys return (KMF_ERR_BAD_KEY_CLASS); 487999ebb4caSwyllys 488099ebb4caSwyllys if (symkey->israw) { 488199ebb4caSwyllys KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp; 488299ebb4caSwyllys 488399ebb4caSwyllys if (rawkey == NULL || 488499ebb4caSwyllys rawkey->keydata.val == NULL || 488599ebb4caSwyllys rawkey->keydata.len == 0) 488699ebb4caSwyllys return (KMF_ERR_BAD_KEYHANDLE); 488799ebb4caSwyllys 488899ebb4caSwyllys rkey->keydata.len = rawkey->keydata.len; 488999ebb4caSwyllys if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL) 489099ebb4caSwyllys return (KMF_ERR_MEMORY); 489199ebb4caSwyllys (void) memcpy(rkey->keydata.val, rawkey->keydata.val, 489299ebb4caSwyllys rkey->keydata.len); 489399ebb4caSwyllys } else { 489430a5e8faSwyllys rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue); 489599ebb4caSwyllys if (rv != KMF_OK) 489699ebb4caSwyllys return (rv); 489799ebb4caSwyllys rkey->keydata.len = keyvalue.Length; 489899ebb4caSwyllys rkey->keydata.val = keyvalue.Data; 489999ebb4caSwyllys } 490099ebb4caSwyllys 490199ebb4caSwyllys return (rv); 490299ebb4caSwyllys } 490302744e81Swyllys 490402744e81Swyllys /* 490530a5e8faSwyllys * substitute for the unsafe access(2) function. 490630a5e8faSwyllys * If the file in question already exists, return 1. 490730a5e8faSwyllys * else 0. If an error occurs during testing (other 490830a5e8faSwyllys * than EEXIST), return -1. 490930a5e8faSwyllys */ 491030a5e8faSwyllys static int 491130a5e8faSwyllys test_for_file(char *filename, mode_t mode) 491230a5e8faSwyllys { 491330a5e8faSwyllys int fd; 491430a5e8faSwyllys 491530a5e8faSwyllys /* 491630a5e8faSwyllys * Try to create the file with the EXCL flag. 491730a5e8faSwyllys * The call should fail if the file exists. 491830a5e8faSwyllys */ 491930a5e8faSwyllys fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode); 492030a5e8faSwyllys if (fd == -1 && errno == EEXIST) 492130a5e8faSwyllys return (1); 492230a5e8faSwyllys else if (fd == -1) /* some other error */ 492330a5e8faSwyllys return (-1); 492430a5e8faSwyllys 492530a5e8faSwyllys /* The file did NOT exist. Delete the testcase. */ 492630a5e8faSwyllys (void) close(fd); 492730a5e8faSwyllys (void) unlink(filename); 492830a5e8faSwyllys return (0); 492930a5e8faSwyllys } 493030a5e8faSwyllys 493130a5e8faSwyllys KMF_RETURN 493230a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr, 493330a5e8faSwyllys KMF_ATTRIBUTE *attrlist) 493430a5e8faSwyllys { 493530a5e8faSwyllys KMF_RETURN rv = KMF_OK; 493630a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 493730a5e8faSwyllys KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL; 493830a5e8faSwyllys KMF_RAW_KEY_DATA *rawkey; 493930a5e8faSwyllys EVP_PKEY *pkey = NULL; 494030a5e8faSwyllys KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM; 494130a5e8faSwyllys KMF_CREDENTIAL cred = { NULL, 0 }; 494230a5e8faSwyllys BIO *out = NULL; 494330a5e8faSwyllys int keys = 0; 494430a5e8faSwyllys char *fullpath = NULL; 494530a5e8faSwyllys char *keyfile = NULL; 494630a5e8faSwyllys char *dirpath = NULL; 494730a5e8faSwyllys 494830a5e8faSwyllys pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr); 494930a5e8faSwyllys if (pubkey != NULL) 495030a5e8faSwyllys keys++; 495130a5e8faSwyllys 495230a5e8faSwyllys prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr); 495330a5e8faSwyllys if (prikey != NULL) 495430a5e8faSwyllys keys++; 495530a5e8faSwyllys 495630a5e8faSwyllys rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr); 495730a5e8faSwyllys if (rawkey != NULL) 495830a5e8faSwyllys keys++; 495930a5e8faSwyllys 496030a5e8faSwyllys /* 496130a5e8faSwyllys * Exactly 1 type of key must be passed to this function. 496230a5e8faSwyllys */ 496330a5e8faSwyllys if (keys != 1) 496430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 496530a5e8faSwyllys 496630a5e8faSwyllys keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, 496730a5e8faSwyllys numattr); 496830a5e8faSwyllys if (keyfile == NULL) 496930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 497030a5e8faSwyllys 497130a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 497230a5e8faSwyllys 497330a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 497430a5e8faSwyllys 497530a5e8faSwyllys /* Once we have the full path, we don't need the pieces */ 497630a5e8faSwyllys if (fullpath == NULL) 497730a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 497830a5e8faSwyllys 497930a5e8faSwyllys /* If the requested file exists, return an error */ 498030a5e8faSwyllys if (test_for_file(fullpath, 0400) == 1) { 498130a5e8faSwyllys free(fullpath); 498230a5e8faSwyllys return (KMF_ERR_DUPLICATE_KEYFILE); 498330a5e8faSwyllys } 498430a5e8faSwyllys 498530a5e8faSwyllys rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 498630a5e8faSwyllys &format, NULL); 498730a5e8faSwyllys if (rv != KMF_OK) 498830a5e8faSwyllys /* format is optional. */ 498930a5e8faSwyllys rv = KMF_OK; 499030a5e8faSwyllys 499130a5e8faSwyllys /* CRED is not required for OpenSSL files */ 499230a5e8faSwyllys (void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr, 499330a5e8faSwyllys &cred, NULL); 499430a5e8faSwyllys 499530a5e8faSwyllys /* Store the private key to the keyfile */ 499630a5e8faSwyllys out = BIO_new_file(fullpath, "wb"); 499730a5e8faSwyllys if (out == NULL) { 499830a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 499930a5e8faSwyllys rv = KMF_ERR_OPEN_FILE; 500030a5e8faSwyllys goto end; 500130a5e8faSwyllys } 500230a5e8faSwyllys 500330a5e8faSwyllys if (prikey != NULL && prikey->keyp != NULL) { 500430a5e8faSwyllys if (prikey->keyalg == KMF_RSA || 500530a5e8faSwyllys prikey->keyalg == KMF_DSA) { 500630a5e8faSwyllys pkey = (EVP_PKEY *)prikey->keyp; 500730a5e8faSwyllys 500830a5e8faSwyllys rv = ssl_write_key(kmfh, format, 500930a5e8faSwyllys out, &cred, pkey, TRUE); 501030a5e8faSwyllys 501130a5e8faSwyllys if (rv == KMF_OK && prikey->keylabel == NULL) { 501230a5e8faSwyllys prikey->keylabel = strdup(fullpath); 501330a5e8faSwyllys if (prikey->keylabel == NULL) 501430a5e8faSwyllys rv = KMF_ERR_MEMORY; 501530a5e8faSwyllys } 501630a5e8faSwyllys } 501730a5e8faSwyllys } else if (pubkey != NULL && pubkey->keyp != NULL) { 501830a5e8faSwyllys if (pubkey->keyalg == KMF_RSA || 501930a5e8faSwyllys pubkey->keyalg == KMF_DSA) { 502030a5e8faSwyllys pkey = (EVP_PKEY *)pubkey->keyp; 502130a5e8faSwyllys 502230a5e8faSwyllys rv = ssl_write_key(kmfh, format, 502330a5e8faSwyllys out, &cred, pkey, FALSE); 502430a5e8faSwyllys 502530a5e8faSwyllys if (rv == KMF_OK && pubkey->keylabel == NULL) { 502630a5e8faSwyllys pubkey->keylabel = strdup(fullpath); 502730a5e8faSwyllys if (pubkey->keylabel == NULL) 502830a5e8faSwyllys rv = KMF_ERR_MEMORY; 502930a5e8faSwyllys } 503030a5e8faSwyllys } 503130a5e8faSwyllys } else if (rawkey != NULL) { 503230a5e8faSwyllys if (rawkey->keytype == KMF_RSA) { 503330a5e8faSwyllys pkey = ImportRawRSAKey(&rawkey->rawdata.rsa); 503430a5e8faSwyllys } else if (rawkey->keytype == KMF_DSA) { 503530a5e8faSwyllys pkey = ImportRawDSAKey(&rawkey->rawdata.dsa); 503630a5e8faSwyllys } else { 503730a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 503830a5e8faSwyllys } 50395b3e1433Swyllys if (pkey != NULL) { 504073cc0e02Swyllys KMF_KEY_CLASS kclass = KMF_ASYM_PRI; 504173cc0e02Swyllys 504273cc0e02Swyllys rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr, 504373cc0e02Swyllys (void *)&kclass, NULL); 504473cc0e02Swyllys if (rv != KMF_OK) 504573cc0e02Swyllys rv = KMF_OK; 50465b3e1433Swyllys rv = ssl_write_key(kmfh, format, out, 504773cc0e02Swyllys &cred, pkey, (kclass == KMF_ASYM_PRI)); 50485b3e1433Swyllys EVP_PKEY_free(pkey); 50495b3e1433Swyllys } 505030a5e8faSwyllys } 505130a5e8faSwyllys 505230a5e8faSwyllys end: 505330a5e8faSwyllys 505430a5e8faSwyllys if (out) 505530a5e8faSwyllys (void) BIO_free(out); 505630a5e8faSwyllys 50575b3e1433Swyllys 505830a5e8faSwyllys if (rv == KMF_OK) 505930a5e8faSwyllys (void) chmod(fullpath, 0400); 506030a5e8faSwyllys 506130a5e8faSwyllys free(fullpath); 506230a5e8faSwyllys return (rv); 506330a5e8faSwyllys } 506430a5e8faSwyllys 506530a5e8faSwyllys KMF_RETURN 506630a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 506730a5e8faSwyllys { 506830a5e8faSwyllys KMF_RETURN ret = KMF_OK; 506930a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 507030a5e8faSwyllys X509_CRL *xcrl = NULL; 507130a5e8faSwyllys X509 *xcert = NULL; 507230a5e8faSwyllys EVP_PKEY *pkey; 507330a5e8faSwyllys KMF_ENCODE_FORMAT format; 507430a5e8faSwyllys BIO *in = NULL, *out = NULL; 507530a5e8faSwyllys int openssl_ret = 0; 507630a5e8faSwyllys KMF_ENCODE_FORMAT outformat; 507730a5e8faSwyllys boolean_t crlcheck = FALSE; 507830a5e8faSwyllys char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile; 507930a5e8faSwyllys 508030a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 508130a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 508230a5e8faSwyllys } 508330a5e8faSwyllys 508430a5e8faSwyllys /* CRL check is optional */ 508530a5e8faSwyllys (void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr, 508630a5e8faSwyllys &crlcheck, NULL); 508730a5e8faSwyllys 508830a5e8faSwyllys certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr); 508930a5e8faSwyllys if (crlcheck == B_TRUE && certfile == NULL) { 509030a5e8faSwyllys return (KMF_ERR_BAD_CERTFILE); 509130a5e8faSwyllys } 509230a5e8faSwyllys 509330a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 509430a5e8faSwyllys incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr); 509530a5e8faSwyllys outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr); 509630a5e8faSwyllys 509730a5e8faSwyllys crlfile = get_fullpath(dirpath, incrl); 509830a5e8faSwyllys 509930a5e8faSwyllys if (crlfile == NULL) 510030a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 510130a5e8faSwyllys 510230a5e8faSwyllys outcrlfile = get_fullpath(dirpath, outcrl); 510330a5e8faSwyllys if (outcrlfile == NULL) 510430a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 510530a5e8faSwyllys 510630a5e8faSwyllys if (isdir(outcrlfile)) { 510730a5e8faSwyllys free(outcrlfile); 510830a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 510930a5e8faSwyllys } 511030a5e8faSwyllys 511130a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 511230a5e8faSwyllys if (ret != KMF_OK) { 511330a5e8faSwyllys free(outcrlfile); 511430a5e8faSwyllys return (ret); 511530a5e8faSwyllys } 511630a5e8faSwyllys 511730a5e8faSwyllys in = BIO_new_file(crlfile, "rb"); 511830a5e8faSwyllys if (in == NULL) { 511930a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 512030a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 512130a5e8faSwyllys goto end; 512230a5e8faSwyllys } 512330a5e8faSwyllys 512430a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 512530a5e8faSwyllys xcrl = d2i_X509_CRL_bio(in, NULL); 512630a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 512730a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); 512830a5e8faSwyllys } 512930a5e8faSwyllys 513030a5e8faSwyllys if (xcrl == NULL) { 513130a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 513230a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 513330a5e8faSwyllys goto end; 513430a5e8faSwyllys } 513530a5e8faSwyllys 513630a5e8faSwyllys /* If bypasscheck is specified, no need to verify. */ 513730a5e8faSwyllys if (crlcheck == B_FALSE) 513830a5e8faSwyllys goto output; 513930a5e8faSwyllys 514030a5e8faSwyllys ret = kmf_is_cert_file(handle, certfile, &format); 514130a5e8faSwyllys if (ret != KMF_OK) 514230a5e8faSwyllys goto end; 514330a5e8faSwyllys 514430a5e8faSwyllys /* Read in the CA cert file and convert to X509 */ 514530a5e8faSwyllys if (BIO_read_filename(in, certfile) <= 0) { 514630a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 514730a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 514830a5e8faSwyllys goto end; 514930a5e8faSwyllys } 515030a5e8faSwyllys 515130a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 515230a5e8faSwyllys xcert = d2i_X509_bio(in, NULL); 515330a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 515430a5e8faSwyllys xcert = PEM_read_bio_X509(in, NULL, NULL, NULL); 515530a5e8faSwyllys } else { 515630a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 515730a5e8faSwyllys goto end; 515830a5e8faSwyllys } 515930a5e8faSwyllys 516030a5e8faSwyllys if (xcert == NULL) { 516130a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 516230a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 516330a5e8faSwyllys goto end; 516430a5e8faSwyllys } 516530a5e8faSwyllys /* Now get the public key from the CA cert */ 516630a5e8faSwyllys pkey = X509_get_pubkey(xcert); 516730a5e8faSwyllys if (pkey == NULL) { 516830a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 516930a5e8faSwyllys ret = KMF_ERR_BAD_CERTFILE; 517030a5e8faSwyllys goto end; 517130a5e8faSwyllys } 517230a5e8faSwyllys 517330a5e8faSwyllys /* Verify the CRL with the CA's public key */ 517430a5e8faSwyllys openssl_ret = X509_CRL_verify(xcrl, pkey); 517530a5e8faSwyllys EVP_PKEY_free(pkey); 517630a5e8faSwyllys if (openssl_ret > 0) { 517730a5e8faSwyllys ret = KMF_OK; /* verify succeed */ 517830a5e8faSwyllys } else { 517930a5e8faSwyllys SET_ERROR(kmfh, openssl_ret); 518030a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 518130a5e8faSwyllys } 518230a5e8faSwyllys 518330a5e8faSwyllys output: 518430a5e8faSwyllys ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 518530a5e8faSwyllys &outformat, NULL); 518630a5e8faSwyllys if (ret != KMF_OK) { 518730a5e8faSwyllys ret = KMF_OK; 518830a5e8faSwyllys outformat = KMF_FORMAT_PEM; 518930a5e8faSwyllys } 519030a5e8faSwyllys 519130a5e8faSwyllys out = BIO_new_file(outcrlfile, "wb"); 519230a5e8faSwyllys if (out == NULL) { 519330a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 519430a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 519530a5e8faSwyllys goto end; 519630a5e8faSwyllys } 519730a5e8faSwyllys 519830a5e8faSwyllys if (outformat == KMF_FORMAT_ASN1) { 519930a5e8faSwyllys openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl); 520030a5e8faSwyllys } else if (outformat == KMF_FORMAT_PEM) { 520130a5e8faSwyllys openssl_ret = PEM_write_bio_X509_CRL(out, xcrl); 520230a5e8faSwyllys } else { 520330a5e8faSwyllys ret = KMF_ERR_BAD_PARAMETER; 520430a5e8faSwyllys goto end; 520530a5e8faSwyllys } 520630a5e8faSwyllys 520730a5e8faSwyllys if (openssl_ret <= 0) { 520830a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 520930a5e8faSwyllys ret = KMF_ERR_WRITE_FILE; 521030a5e8faSwyllys } else { 521130a5e8faSwyllys ret = KMF_OK; 521230a5e8faSwyllys } 521330a5e8faSwyllys 521430a5e8faSwyllys end: 521530a5e8faSwyllys if (xcrl != NULL) 521630a5e8faSwyllys X509_CRL_free(xcrl); 521730a5e8faSwyllys 521830a5e8faSwyllys if (xcert != NULL) 521930a5e8faSwyllys X509_free(xcert); 522030a5e8faSwyllys 522130a5e8faSwyllys if (in != NULL) 522230a5e8faSwyllys (void) BIO_free(in); 522330a5e8faSwyllys 522430a5e8faSwyllys if (out != NULL) 522530a5e8faSwyllys (void) BIO_free(out); 522630a5e8faSwyllys 522730a5e8faSwyllys if (outcrlfile != NULL) 522830a5e8faSwyllys free(outcrlfile); 522930a5e8faSwyllys 523030a5e8faSwyllys return (ret); 523130a5e8faSwyllys } 523230a5e8faSwyllys 523330a5e8faSwyllys KMF_RETURN 523430a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 523530a5e8faSwyllys { 523630a5e8faSwyllys KMF_RETURN ret = KMF_OK; 523730a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 523830a5e8faSwyllys X509_CRL *x = NULL; 523930a5e8faSwyllys KMF_ENCODE_FORMAT format; 524030a5e8faSwyllys char *crlfile = NULL; 524130a5e8faSwyllys BIO *in = NULL; 524230a5e8faSwyllys BIO *mem = NULL; 524330a5e8faSwyllys long len; 524430a5e8faSwyllys char *memptr; 524530a5e8faSwyllys char *data = NULL; 524630a5e8faSwyllys char **crldata; 524730a5e8faSwyllys char *crlfilename, *dirpath; 524830a5e8faSwyllys 524930a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 525030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 525130a5e8faSwyllys } 525230a5e8faSwyllys crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, 525330a5e8faSwyllys attrlist, numattr); 525430a5e8faSwyllys if (crlfilename == NULL) 525530a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 525630a5e8faSwyllys 525730a5e8faSwyllys crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR, 525830a5e8faSwyllys attrlist, numattr); 525930a5e8faSwyllys 526030a5e8faSwyllys if (crldata == NULL) 526130a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 526230a5e8faSwyllys 526330a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 526430a5e8faSwyllys 526530a5e8faSwyllys crlfile = get_fullpath(dirpath, crlfilename); 526630a5e8faSwyllys 526730a5e8faSwyllys if (crlfile == NULL) 526830a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 526930a5e8faSwyllys 527030a5e8faSwyllys if (isdir(crlfile)) { 527130a5e8faSwyllys free(crlfile); 527230a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 527330a5e8faSwyllys } 527430a5e8faSwyllys 527530a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 527630a5e8faSwyllys if (ret != KMF_OK) { 527730a5e8faSwyllys free(crlfile); 527830a5e8faSwyllys return (ret); 527930a5e8faSwyllys } 528030a5e8faSwyllys 528130a5e8faSwyllys if (bio_err == NULL) 528230a5e8faSwyllys bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 528330a5e8faSwyllys 528430a5e8faSwyllys in = BIO_new_file(crlfile, "rb"); 528530a5e8faSwyllys if (in == NULL) { 528630a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 528730a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 528830a5e8faSwyllys goto end; 528930a5e8faSwyllys } 529030a5e8faSwyllys 529130a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 529230a5e8faSwyllys x = d2i_X509_CRL_bio(in, NULL); 529330a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 529430a5e8faSwyllys x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); 529530a5e8faSwyllys } 529630a5e8faSwyllys 529730a5e8faSwyllys if (x == NULL) { /* should not happen */ 529830a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 529930a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 530030a5e8faSwyllys goto end; 530130a5e8faSwyllys } 530230a5e8faSwyllys 530330a5e8faSwyllys mem = BIO_new(BIO_s_mem()); 530430a5e8faSwyllys if (mem == NULL) { 530530a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 530630a5e8faSwyllys ret = KMF_ERR_MEMORY; 530730a5e8faSwyllys goto end; 530830a5e8faSwyllys } 530930a5e8faSwyllys 531030a5e8faSwyllys (void) X509_CRL_print(mem, x); 531130a5e8faSwyllys len = BIO_get_mem_data(mem, &memptr); 531230a5e8faSwyllys if (len <= 0) { 531330a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 531430a5e8faSwyllys ret = KMF_ERR_MEMORY; 531530a5e8faSwyllys goto end; 531630a5e8faSwyllys } 531730a5e8faSwyllys 531830a5e8faSwyllys data = malloc(len + 1); 531930a5e8faSwyllys if (data == NULL) { 532030a5e8faSwyllys ret = KMF_ERR_MEMORY; 532130a5e8faSwyllys goto end; 532230a5e8faSwyllys } 532330a5e8faSwyllys 532430a5e8faSwyllys (void) memcpy(data, memptr, len); 532530a5e8faSwyllys data[len] = '\0'; 532630a5e8faSwyllys *crldata = data; 532730a5e8faSwyllys 532830a5e8faSwyllys end: 532930a5e8faSwyllys if (x != NULL) 533030a5e8faSwyllys X509_CRL_free(x); 533130a5e8faSwyllys 533230a5e8faSwyllys if (crlfile != NULL) 533330a5e8faSwyllys free(crlfile); 533430a5e8faSwyllys 533530a5e8faSwyllys if (in != NULL) 533630a5e8faSwyllys (void) BIO_free(in); 533730a5e8faSwyllys 533830a5e8faSwyllys if (mem != NULL) 533930a5e8faSwyllys (void) BIO_free(mem); 534030a5e8faSwyllys 534130a5e8faSwyllys return (ret); 534230a5e8faSwyllys } 534330a5e8faSwyllys 534430a5e8faSwyllys KMF_RETURN 534530a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 534630a5e8faSwyllys { 534730a5e8faSwyllys KMF_RETURN ret = KMF_OK; 534830a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 534930a5e8faSwyllys KMF_ENCODE_FORMAT format; 535030a5e8faSwyllys char *crlfile = NULL; 535130a5e8faSwyllys BIO *in = NULL; 535230a5e8faSwyllys char *crlfilename, *dirpath; 535330a5e8faSwyllys 535430a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 535530a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 535630a5e8faSwyllys } 535730a5e8faSwyllys 535830a5e8faSwyllys crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, 535930a5e8faSwyllys attrlist, numattr); 536030a5e8faSwyllys 536130a5e8faSwyllys if (crlfilename == NULL) 536230a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 536330a5e8faSwyllys 536430a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 536530a5e8faSwyllys 536630a5e8faSwyllys crlfile = get_fullpath(dirpath, crlfilename); 536730a5e8faSwyllys 536830a5e8faSwyllys if (crlfile == NULL) 536930a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 537030a5e8faSwyllys 537130a5e8faSwyllys if (isdir(crlfile)) { 537230a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 537330a5e8faSwyllys goto end; 537430a5e8faSwyllys } 537530a5e8faSwyllys 537630a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 537730a5e8faSwyllys if (ret != KMF_OK) 537830a5e8faSwyllys goto end; 537930a5e8faSwyllys 538030a5e8faSwyllys if (unlink(crlfile) != 0) { 538130a5e8faSwyllys SET_SYS_ERROR(kmfh, errno); 538230a5e8faSwyllys ret = KMF_ERR_INTERNAL; 538330a5e8faSwyllys goto end; 538430a5e8faSwyllys } 538530a5e8faSwyllys 538630a5e8faSwyllys end: 538730a5e8faSwyllys if (in != NULL) 538830a5e8faSwyllys (void) BIO_free(in); 538930a5e8faSwyllys if (crlfile != NULL) 539030a5e8faSwyllys free(crlfile); 539130a5e8faSwyllys 539230a5e8faSwyllys return (ret); 539330a5e8faSwyllys } 539430a5e8faSwyllys 539530a5e8faSwyllys KMF_RETURN 539630a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 539730a5e8faSwyllys { 539830a5e8faSwyllys KMF_RETURN ret = KMF_OK; 539930a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 540030a5e8faSwyllys KMF_ENCODE_FORMAT format; 540130a5e8faSwyllys BIO *in = NULL; 540230a5e8faSwyllys X509 *xcert = NULL; 540330a5e8faSwyllys X509_CRL *xcrl = NULL; 540430a5e8faSwyllys STACK_OF(X509_REVOKED) *revoke_stack = NULL; 540530a5e8faSwyllys X509_REVOKED *revoke; 540630a5e8faSwyllys int i; 540730a5e8faSwyllys char *crlfilename, *crlfile, *dirpath, *certfile; 540830a5e8faSwyllys 540930a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 541030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 541130a5e8faSwyllys } 541230a5e8faSwyllys 541330a5e8faSwyllys crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, 541430a5e8faSwyllys attrlist, numattr); 541530a5e8faSwyllys 541630a5e8faSwyllys if (crlfilename == NULL) 541730a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 541830a5e8faSwyllys 541930a5e8faSwyllys certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr); 542030a5e8faSwyllys if (certfile == NULL) 542130a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 542230a5e8faSwyllys 542330a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 542430a5e8faSwyllys 542530a5e8faSwyllys crlfile = get_fullpath(dirpath, crlfilename); 542630a5e8faSwyllys 542730a5e8faSwyllys if (crlfile == NULL) 542830a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 542930a5e8faSwyllys 543030a5e8faSwyllys if (isdir(crlfile)) { 543130a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 543230a5e8faSwyllys goto end; 543330a5e8faSwyllys } 543430a5e8faSwyllys 543530a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 543630a5e8faSwyllys if (ret != KMF_OK) 543730a5e8faSwyllys goto end; 543830a5e8faSwyllys 543930a5e8faSwyllys /* Read the CRL file and load it into a X509_CRL structure */ 544030a5e8faSwyllys in = BIO_new_file(crlfilename, "rb"); 544130a5e8faSwyllys if (in == NULL) { 544230a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 544330a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 544430a5e8faSwyllys goto end; 544530a5e8faSwyllys } 544630a5e8faSwyllys 544730a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 544830a5e8faSwyllys xcrl = d2i_X509_CRL_bio(in, NULL); 544930a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 545030a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); 545130a5e8faSwyllys } 545230a5e8faSwyllys 545330a5e8faSwyllys if (xcrl == NULL) { 545430a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 545530a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 545630a5e8faSwyllys goto end; 545730a5e8faSwyllys } 545830a5e8faSwyllys (void) BIO_free(in); 545930a5e8faSwyllys 546030a5e8faSwyllys /* Read the Certificate file and load it into a X509 structure */ 546130a5e8faSwyllys ret = kmf_is_cert_file(handle, certfile, &format); 546230a5e8faSwyllys if (ret != KMF_OK) 546330a5e8faSwyllys goto end; 546430a5e8faSwyllys 546530a5e8faSwyllys in = BIO_new_file(certfile, "rb"); 546630a5e8faSwyllys if (in == NULL) { 546730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 546830a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 546930a5e8faSwyllys goto end; 547030a5e8faSwyllys } 547130a5e8faSwyllys 547230a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 547330a5e8faSwyllys xcert = d2i_X509_bio(in, NULL); 547430a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 547530a5e8faSwyllys xcert = PEM_read_bio_X509(in, NULL, NULL, NULL); 547630a5e8faSwyllys } 547730a5e8faSwyllys 547830a5e8faSwyllys if (xcert == NULL) { 547930a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 548030a5e8faSwyllys ret = KMF_ERR_BAD_CERTFILE; 548130a5e8faSwyllys goto end; 548230a5e8faSwyllys } 548330a5e8faSwyllys 548430a5e8faSwyllys /* Check if the certificate and the CRL have same issuer */ 5485300fdee2SAndy Fiddaman if (X509_NAME_cmp(X509_get_issuer_name(xcert), 5486300fdee2SAndy Fiddaman X509_CRL_get_issuer(xcrl)) != 0) { 548730a5e8faSwyllys ret = KMF_ERR_ISSUER; 548830a5e8faSwyllys goto end; 548930a5e8faSwyllys } 549030a5e8faSwyllys 549130a5e8faSwyllys /* Check to see if the certificate serial number is revoked */ 549230a5e8faSwyllys revoke_stack = X509_CRL_get_REVOKED(xcrl); 549330a5e8faSwyllys if (sk_X509_REVOKED_num(revoke_stack) <= 0) { 549430a5e8faSwyllys /* No revoked certificates in the CRL file */ 549530a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 549630a5e8faSwyllys ret = KMF_ERR_EMPTY_CRL; 549730a5e8faSwyllys goto end; 549830a5e8faSwyllys } 549930a5e8faSwyllys 550030a5e8faSwyllys for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) { 5501d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 550230a5e8faSwyllys revoke = sk_X509_REVOKED_value(revoke_stack, i); 5503300fdee2SAndy Fiddaman if (ASN1_INTEGER_cmp(X509_get_serialNumber(xcert), 5504300fdee2SAndy Fiddaman X509_REVOKED_get0_serialNumber(revoke)) == 0) { 550530a5e8faSwyllys break; 550630a5e8faSwyllys } 550730a5e8faSwyllys } 550830a5e8faSwyllys 550930a5e8faSwyllys if (i < sk_X509_REVOKED_num(revoke_stack)) { 551030a5e8faSwyllys ret = KMF_OK; 551130a5e8faSwyllys } else { 551230a5e8faSwyllys ret = KMF_ERR_NOT_REVOKED; 551330a5e8faSwyllys } 551430a5e8faSwyllys 551530a5e8faSwyllys end: 551630a5e8faSwyllys if (in != NULL) 551730a5e8faSwyllys (void) BIO_free(in); 551830a5e8faSwyllys if (xcrl != NULL) 551930a5e8faSwyllys X509_CRL_free(xcrl); 552030a5e8faSwyllys if (xcert != NULL) 552130a5e8faSwyllys X509_free(xcert); 552230a5e8faSwyllys 552330a5e8faSwyllys return (ret); 552430a5e8faSwyllys } 552530a5e8faSwyllys 552630a5e8faSwyllys KMF_RETURN 552730a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert) 552830a5e8faSwyllys { 552930a5e8faSwyllys KMF_RETURN ret = KMF_OK; 553030a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 553130a5e8faSwyllys BIO *bcrl = NULL; 553230a5e8faSwyllys X509_CRL *xcrl = NULL; 553330a5e8faSwyllys X509 *xcert = NULL; 553430a5e8faSwyllys EVP_PKEY *pkey; 553530a5e8faSwyllys int sslret; 553630a5e8faSwyllys KMF_ENCODE_FORMAT crl_format; 553730a5e8faSwyllys unsigned char *p; 553830a5e8faSwyllys long len; 553930a5e8faSwyllys 554030a5e8faSwyllys if (handle == NULL || crlname == NULL || tacert == NULL) { 554130a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 554230a5e8faSwyllys } 554330a5e8faSwyllys 554430a5e8faSwyllys ret = kmf_get_file_format(crlname, &crl_format); 554530a5e8faSwyllys if (ret != KMF_OK) 554630a5e8faSwyllys return (ret); 554730a5e8faSwyllys 554830a5e8faSwyllys bcrl = BIO_new_file(crlname, "rb"); 554930a5e8faSwyllys if (bcrl == NULL) { 555030a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 555130a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 555230a5e8faSwyllys goto cleanup; 555330a5e8faSwyllys } 555430a5e8faSwyllys 555530a5e8faSwyllys if (crl_format == KMF_FORMAT_ASN1) { 555630a5e8faSwyllys xcrl = d2i_X509_CRL_bio(bcrl, NULL); 555730a5e8faSwyllys } else if (crl_format == KMF_FORMAT_PEM) { 555830a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL); 555930a5e8faSwyllys } else { 556030a5e8faSwyllys ret = KMF_ERR_BAD_PARAMETER; 556130a5e8faSwyllys goto cleanup; 556230a5e8faSwyllys } 556330a5e8faSwyllys 556430a5e8faSwyllys if (xcrl == NULL) { 556530a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 556630a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 556730a5e8faSwyllys goto cleanup; 556830a5e8faSwyllys } 556930a5e8faSwyllys 557030a5e8faSwyllys p = tacert->Data; 557130a5e8faSwyllys len = tacert->Length; 557230a5e8faSwyllys xcert = d2i_X509(NULL, (const uchar_t **)&p, len); 557330a5e8faSwyllys 557430a5e8faSwyllys if (xcert == NULL) { 557530a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 557630a5e8faSwyllys ret = KMF_ERR_BAD_CERTFILE; 557730a5e8faSwyllys goto cleanup; 557830a5e8faSwyllys } 557930a5e8faSwyllys 558030a5e8faSwyllys /* Get issuer certificate public key */ 558130a5e8faSwyllys pkey = X509_get_pubkey(xcert); 558230a5e8faSwyllys if (pkey == NULL) { 558330a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 558430a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 558530a5e8faSwyllys goto cleanup; 558630a5e8faSwyllys } 558730a5e8faSwyllys 558830a5e8faSwyllys /* Verify CRL signature */ 558930a5e8faSwyllys sslret = X509_CRL_verify(xcrl, pkey); 559030a5e8faSwyllys EVP_PKEY_free(pkey); 559130a5e8faSwyllys if (sslret > 0) { 559230a5e8faSwyllys ret = KMF_OK; 559330a5e8faSwyllys } else { 559430a5e8faSwyllys SET_ERROR(kmfh, sslret); 559530a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 559630a5e8faSwyllys } 559730a5e8faSwyllys 559830a5e8faSwyllys cleanup: 559930a5e8faSwyllys if (bcrl != NULL) 560030a5e8faSwyllys (void) BIO_free(bcrl); 560130a5e8faSwyllys 560230a5e8faSwyllys if (xcrl != NULL) 560330a5e8faSwyllys X509_CRL_free(xcrl); 560430a5e8faSwyllys 560530a5e8faSwyllys if (xcert != NULL) 560630a5e8faSwyllys X509_free(xcert); 560730a5e8faSwyllys 560830a5e8faSwyllys return (ret); 560930a5e8faSwyllys 561030a5e8faSwyllys } 561130a5e8faSwyllys 561230a5e8faSwyllys KMF_RETURN 561330a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname) 561430a5e8faSwyllys { 561530a5e8faSwyllys KMF_RETURN ret = KMF_OK; 561630a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 561730a5e8faSwyllys KMF_ENCODE_FORMAT crl_format; 561830a5e8faSwyllys BIO *bcrl = NULL; 561930a5e8faSwyllys X509_CRL *xcrl = NULL; 562030a5e8faSwyllys int i; 562130a5e8faSwyllys 562230a5e8faSwyllys if (handle == NULL || crlname == NULL) { 562330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 562430a5e8faSwyllys } 562530a5e8faSwyllys 562630a5e8faSwyllys ret = kmf_is_crl_file(handle, crlname, &crl_format); 562730a5e8faSwyllys if (ret != KMF_OK) 562830a5e8faSwyllys return (ret); 562930a5e8faSwyllys 563030a5e8faSwyllys bcrl = BIO_new_file(crlname, "rb"); 563130a5e8faSwyllys if (bcrl == NULL) { 563230a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 563330a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 563430a5e8faSwyllys goto cleanup; 563530a5e8faSwyllys } 563630a5e8faSwyllys 56375b3e1433Swyllys if (crl_format == KMF_FORMAT_ASN1) 563830a5e8faSwyllys xcrl = d2i_X509_CRL_bio(bcrl, NULL); 56395b3e1433Swyllys else if (crl_format == KMF_FORMAT_PEM) 564030a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL); 564130a5e8faSwyllys 564230a5e8faSwyllys if (xcrl == NULL) { 564330a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 564430a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 564530a5e8faSwyllys goto cleanup; 564630a5e8faSwyllys } 5647300fdee2SAndy Fiddaman i = X509_cmp_time(X509_CRL_get0_lastUpdate(xcrl), NULL); 564830a5e8faSwyllys if (i >= 0) { 564930a5e8faSwyllys ret = KMF_ERR_VALIDITY_PERIOD; 565030a5e8faSwyllys goto cleanup; 565130a5e8faSwyllys } 5652300fdee2SAndy Fiddaman if (X509_CRL_get0_nextUpdate(xcrl)) { 5653300fdee2SAndy Fiddaman i = X509_cmp_time(X509_CRL_get0_nextUpdate(xcrl), NULL); 565430a5e8faSwyllys 565530a5e8faSwyllys if (i <= 0) { 565630a5e8faSwyllys ret = KMF_ERR_VALIDITY_PERIOD; 565730a5e8faSwyllys goto cleanup; 565830a5e8faSwyllys } 565930a5e8faSwyllys } 566030a5e8faSwyllys 566130a5e8faSwyllys ret = KMF_OK; 566230a5e8faSwyllys 566330a5e8faSwyllys cleanup: 566430a5e8faSwyllys if (bcrl != NULL) 566530a5e8faSwyllys (void) BIO_free(bcrl); 566630a5e8faSwyllys 566730a5e8faSwyllys if (xcrl != NULL) 566830a5e8faSwyllys X509_CRL_free(xcrl); 566930a5e8faSwyllys 567030a5e8faSwyllys return (ret); 567130a5e8faSwyllys } 5672