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. 8*300fdee2SAndy Fiddaman * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. 970f9559bSTheo Schlossnagle */ 1070f9559bSTheo Schlossnagle /* 119a767088Shaimay * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL 129a767088Shaimay * project 2000. 139a767088Shaimay */ 149a767088Shaimay /* 159a767088Shaimay * ==================================================================== 169a767088Shaimay * Copyright (c) 2000-2004 The OpenSSL Project. All rights reserved. 179a767088Shaimay * 189a767088Shaimay * Redistribution and use in source and binary forms, with or without 199a767088Shaimay * modification, are permitted provided that the following conditions 209a767088Shaimay * are met: 219a767088Shaimay * 229a767088Shaimay * 1. Redistributions of source code must retain the above copyright 239a767088Shaimay * notice, this list of conditions and the following disclaimer. 249a767088Shaimay * 259a767088Shaimay * 2. Redistributions in binary form must reproduce the above copyright 269a767088Shaimay * notice, this list of conditions and the following disclaimer in 279a767088Shaimay * the documentation and/or other materials provided with the 289a767088Shaimay * distribution. 299a767088Shaimay * 309a767088Shaimay * 3. All advertising materials mentioning features or use of this 319a767088Shaimay * software must display the following acknowledgment: 329a767088Shaimay * "This product includes software developed by the OpenSSL Project 339a767088Shaimay * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 349a767088Shaimay * 359a767088Shaimay * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 369a767088Shaimay * endorse or promote products derived from this software without 379a767088Shaimay * prior written permission. For written permission, please contact 389a767088Shaimay * licensing@OpenSSL.org. 399a767088Shaimay * 409a767088Shaimay * 5. Products derived from this software may not be called "OpenSSL" 419a767088Shaimay * nor may "OpenSSL" appear in their names without prior written 429a767088Shaimay * permission of the OpenSSL Project. 439a767088Shaimay * 449a767088Shaimay * 6. Redistributions of any form whatsoever must retain the following 459a767088Shaimay * acknowledgment: 469a767088Shaimay * "This product includes software developed by the OpenSSL Project 479a767088Shaimay * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 489a767088Shaimay * 499a767088Shaimay * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 509a767088Shaimay * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 519a767088Shaimay * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 529a767088Shaimay * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 539a767088Shaimay * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 549a767088Shaimay * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 559a767088Shaimay * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 569a767088Shaimay * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 579a767088Shaimay * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 589a767088Shaimay * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 599a767088Shaimay * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 609a767088Shaimay * OF THE POSSIBILITY OF SUCH DAMAGE. 619a767088Shaimay * ==================================================================== 629a767088Shaimay * 639a767088Shaimay * This product includes cryptographic software written by Eric Young 649a767088Shaimay * (eay@cryptsoft.com). This product includes software written by Tim 659a767088Shaimay * Hudson (tjh@cryptsoft.com). 669a767088Shaimay * 679a767088Shaimay */ 6899ebb4caSwyllys 6971593db2Swyllys #include <stdlib.h> 7099ebb4caSwyllys #include <kmfapiP.h> 7199ebb4caSwyllys #include <ber_der.h> 7299ebb4caSwyllys #include <fcntl.h> 7399ebb4caSwyllys #include <sys/stat.h> 7499ebb4caSwyllys #include <dirent.h> 7599ebb4caSwyllys #include <cryptoutil.h> 7699ebb4caSwyllys #include <synch.h> 7799ebb4caSwyllys #include <thread.h> 7899ebb4caSwyllys 7999ebb4caSwyllys /* OPENSSL related headers */ 8099ebb4caSwyllys #include <openssl/bio.h> 8199ebb4caSwyllys #include <openssl/bn.h> 8299ebb4caSwyllys #include <openssl/asn1.h> 8399ebb4caSwyllys #include <openssl/err.h> 8499ebb4caSwyllys #include <openssl/x509.h> 8599ebb4caSwyllys #include <openssl/rsa.h> 8699ebb4caSwyllys #include <openssl/dsa.h> 8799ebb4caSwyllys #include <openssl/x509v3.h> 8899ebb4caSwyllys #include <openssl/objects.h> 8999ebb4caSwyllys #include <openssl/pem.h> 9099ebb4caSwyllys #include <openssl/pkcs12.h> 9199ebb4caSwyllys #include <openssl/ocsp.h> 9299ebb4caSwyllys #include <openssl/des.h> 9399ebb4caSwyllys #include <openssl/rand.h> 94*300fdee2SAndy Fiddaman #include "compat.h" 9599ebb4caSwyllys 9699ebb4caSwyllys #define PRINT_ANY_EXTENSION (\ 9799ebb4caSwyllys KMF_X509_EXT_KEY_USAGE |\ 9899ebb4caSwyllys KMF_X509_EXT_CERT_POLICIES |\ 9999ebb4caSwyllys KMF_X509_EXT_SUBJALTNAME |\ 10099ebb4caSwyllys KMF_X509_EXT_BASIC_CONSTRAINTS |\ 10199ebb4caSwyllys KMF_X509_EXT_NAME_CONSTRAINTS |\ 10299ebb4caSwyllys KMF_X509_EXT_POLICY_CONSTRAINTS |\ 10399ebb4caSwyllys KMF_X509_EXT_EXT_KEY_USAGE |\ 10499ebb4caSwyllys KMF_X509_EXT_INHIBIT_ANY_POLICY |\ 10599ebb4caSwyllys KMF_X509_EXT_AUTH_KEY_ID |\ 10699ebb4caSwyllys KMF_X509_EXT_SUBJ_KEY_ID |\ 10799ebb4caSwyllys KMF_X509_EXT_POLICY_MAPPING) 10899ebb4caSwyllys 10999ebb4caSwyllys static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76, 11099ebb4caSwyllys 0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69, 11199ebb4caSwyllys 0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c, 11299ebb4caSwyllys 0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82, 11399ebb4caSwyllys 0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e, 11499ebb4caSwyllys 0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a, 11599ebb4caSwyllys 0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24, 11699ebb4caSwyllys 0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02, 11799ebb4caSwyllys 0x91 }; 11899ebb4caSwyllys 11999ebb4caSwyllys static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8, 12099ebb4caSwyllys 0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4, 12199ebb4caSwyllys 0x8e, 0xda, 0xce, 0x91, 0x5f }; 12299ebb4caSwyllys 12399ebb4caSwyllys static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a, 12499ebb4caSwyllys 0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5, 12599ebb4caSwyllys 0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef, 12699ebb4caSwyllys 0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c, 12799ebb4caSwyllys 0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba, 12899ebb4caSwyllys 0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c, 12999ebb4caSwyllys 0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08, 13099ebb4caSwyllys 0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88, 13199ebb4caSwyllys 0x02 }; 13299ebb4caSwyllys 13399ebb4caSwyllys #define SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \ 13499ebb4caSwyllys h->lasterr.errcode = c; 13599ebb4caSwyllys 13699ebb4caSwyllys #define SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c; 13799ebb4caSwyllys 1385b3e1433Swyllys /* 139bf5d9f18SAndy Fiddaman * Declare some new macros for managing stacks of EVP_PKEYS. 1405b3e1433Swyllys */ 141*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L 1425b3e1433Swyllys DECLARE_STACK_OF(EVP_PKEY) 1435b3e1433Swyllys 1445b3e1433Swyllys #define sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY) 1455b3e1433Swyllys #define sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st)) 1465b3e1433Swyllys #define sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st)) 1475b3e1433Swyllys #define sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i)) 1485b3e1433Swyllys #define sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val)) 1495b3e1433Swyllys #define sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \ 1505b3e1433Swyllys (free_func)) 1515b3e1433Swyllys 152*300fdee2SAndy Fiddaman #else 153*300fdee2SAndy Fiddaman /* LINTED E_STATIC_UNUSED */ 154*300fdee2SAndy Fiddaman DEFINE_STACK_OF(EVP_PKEY) 155*300fdee2SAndy Fiddaman #endif 156*300fdee2SAndy Fiddaman 15799ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX; 15899ebb4caSwyllys static int ssl_initialized = 0; 15930a5e8faSwyllys static BIO *bio_err = NULL; 16030a5e8faSwyllys 16130a5e8faSwyllys static int 16230a5e8faSwyllys test_for_file(char *, mode_t); 1635b3e1433Swyllys static KMF_RETURN 1645b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *, char *, int, 1655b3e1433Swyllys STACK_OF(EVP_PKEY) *, STACK_OF(X509) *); 1665b3e1433Swyllys 1675b3e1433Swyllys static KMF_RETURN 1685b3e1433Swyllys local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *, 1695b3e1433Swyllys int, KMF_KEY_HANDLE *, char *); 1705b3e1433Swyllys 1715b3e1433Swyllys static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int); 17299ebb4caSwyllys 17371593db2Swyllys static KMF_RETURN 17430a5e8faSwyllys extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *, 17502744e81Swyllys CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *); 17671593db2Swyllys 17771593db2Swyllys static KMF_RETURN 17830a5e8faSwyllys kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY, 17930a5e8faSwyllys char *, KMF_DATA *); 18030a5e8faSwyllys 18130a5e8faSwyllys static KMF_RETURN 18230a5e8faSwyllys load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY, 18330a5e8faSwyllys char *, KMF_DATA **, uint32_t *); 18471593db2Swyllys 18502744e81Swyllys static KMF_RETURN 18602744e81Swyllys sslBN2KMFBN(BIGNUM *, KMF_BIGINT *); 18702744e81Swyllys 18802744e81Swyllys static EVP_PKEY * 18902744e81Swyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *); 19002744e81Swyllys 19130a5e8faSwyllys static KMF_RETURN 19230a5e8faSwyllys convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *); 19330a5e8faSwyllys 19499ebb4caSwyllys KMF_RETURN 19530a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 19699ebb4caSwyllys 19799ebb4caSwyllys void 19899ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *); 19999ebb4caSwyllys 20099ebb4caSwyllys KMF_RETURN 20130a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *); 20299ebb4caSwyllys 20399ebb4caSwyllys KMF_RETURN 20430a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *); 20599ebb4caSwyllys 20699ebb4caSwyllys KMF_RETURN 20730a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 20830a5e8faSwyllys 20930a5e8faSwyllys KMF_RETURN 21030a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 21199ebb4caSwyllys 21299ebb4caSwyllys KMF_RETURN 21399ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *); 21499ebb4caSwyllys 21599ebb4caSwyllys KMF_RETURN 21699ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *, 21799ebb4caSwyllys KMF_DATA *, KMF_DATA *); 21899ebb4caSwyllys 21999ebb4caSwyllys KMF_RETURN 22030a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 22199ebb4caSwyllys 22299ebb4caSwyllys KMF_RETURN 22330a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 22499ebb4caSwyllys 22599ebb4caSwyllys KMF_RETURN 22630a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 22799ebb4caSwyllys 22899ebb4caSwyllys KMF_RETURN 22930a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 23099ebb4caSwyllys 23199ebb4caSwyllys KMF_RETURN 23230a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 23399ebb4caSwyllys 23499ebb4caSwyllys KMF_RETURN 23599ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *, 23699ebb4caSwyllys KMF_PRINTABLE_ITEM, char *); 23799ebb4caSwyllys 23899ebb4caSwyllys KMF_RETURN 23999ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T, char **); 24099ebb4caSwyllys 24199ebb4caSwyllys KMF_RETURN 24230a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 24399ebb4caSwyllys 24499ebb4caSwyllys KMF_RETURN 24599ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *, 24699ebb4caSwyllys KMF_DATA *, KMF_DATA *); 24799ebb4caSwyllys 24899ebb4caSwyllys KMF_RETURN 24930a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 25099ebb4caSwyllys 25199ebb4caSwyllys KMF_RETURN 25230a5e8faSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 25399ebb4caSwyllys 25499ebb4caSwyllys KMF_RETURN 25530a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 25699ebb4caSwyllys 25799ebb4caSwyllys KMF_RETURN 25830a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 25999ebb4caSwyllys 26099ebb4caSwyllys KMF_RETURN 26130a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 26299ebb4caSwyllys 26399ebb4caSwyllys KMF_RETURN 26499ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *); 26599ebb4caSwyllys 26699ebb4caSwyllys KMF_RETURN 26730a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *); 26899ebb4caSwyllys 26999ebb4caSwyllys KMF_RETURN 27030a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *); 27199ebb4caSwyllys 27299ebb4caSwyllys static 27399ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table = 27499ebb4caSwyllys { 27599ebb4caSwyllys 1, /* Version */ 27699ebb4caSwyllys NULL, /* ConfigureKeystore */ 27799ebb4caSwyllys OpenSSL_FindCert, 27899ebb4caSwyllys OpenSSL_FreeKMFCert, 27999ebb4caSwyllys OpenSSL_StoreCert, 28099ebb4caSwyllys NULL, /* ImportCert */ 28199ebb4caSwyllys OpenSSL_ImportCRL, 28299ebb4caSwyllys OpenSSL_DeleteCert, 28399ebb4caSwyllys OpenSSL_DeleteCRL, 28499ebb4caSwyllys OpenSSL_CreateKeypair, 28599ebb4caSwyllys OpenSSL_FindKey, 28699ebb4caSwyllys OpenSSL_EncodePubKeyData, 28799ebb4caSwyllys OpenSSL_SignData, 28899ebb4caSwyllys OpenSSL_DeleteKey, 28999ebb4caSwyllys OpenSSL_ListCRL, 29099ebb4caSwyllys NULL, /* FindCRL */ 29199ebb4caSwyllys OpenSSL_FindCertInCRL, 29299ebb4caSwyllys OpenSSL_GetErrorString, 29330a5e8faSwyllys OpenSSL_FindPrikeyByCert, 29499ebb4caSwyllys OpenSSL_DecryptData, 29530a5e8faSwyllys OpenSSL_ExportPK12, 29699ebb4caSwyllys OpenSSL_CreateSymKey, 29799ebb4caSwyllys OpenSSL_GetSymKeyValue, 29899ebb4caSwyllys NULL, /* SetTokenPin */ 29930a5e8faSwyllys OpenSSL_StoreKey, 30099ebb4caSwyllys NULL /* Finalize */ 30199ebb4caSwyllys }; 30299ebb4caSwyllys 303*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L 30499ebb4caSwyllys static mutex_t *lock_cs; 30599ebb4caSwyllys static long *lock_count; 30699ebb4caSwyllys 30799ebb4caSwyllys static void 308a2d4930dSDan OpenSolaris Anderson /* ARGSUSED1 */ 30999ebb4caSwyllys locking_cb(int mode, int type, char *file, int line) 31099ebb4caSwyllys { 31199ebb4caSwyllys if (mode & CRYPTO_LOCK) { 31299ebb4caSwyllys (void) mutex_lock(&(lock_cs[type])); 31399ebb4caSwyllys lock_count[type]++; 31499ebb4caSwyllys } else { 31599ebb4caSwyllys (void) mutex_unlock(&(lock_cs[type])); 31699ebb4caSwyllys } 31799ebb4caSwyllys } 31899ebb4caSwyllys 31999ebb4caSwyllys static unsigned long 32099ebb4caSwyllys thread_id() 32199ebb4caSwyllys { 32299ebb4caSwyllys return ((unsigned long)thr_self()); 32399ebb4caSwyllys } 324*300fdee2SAndy Fiddaman #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ 32599ebb4caSwyllys 32699ebb4caSwyllys KMF_PLUGIN_FUNCLIST * 32799ebb4caSwyllys KMF_Plugin_Initialize() 32899ebb4caSwyllys { 329*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L 33099ebb4caSwyllys int i; 331*300fdee2SAndy Fiddaman #endif 33299ebb4caSwyllys 33399ebb4caSwyllys (void) mutex_lock(&init_lock); 33499ebb4caSwyllys if (!ssl_initialized) { 33599ebb4caSwyllys /* 33699ebb4caSwyllys * Add support for extension OIDs that are not yet in the 33799ebb4caSwyllys * openssl default set. 33899ebb4caSwyllys */ 33999ebb4caSwyllys (void) OBJ_create("2.5.29.30", "nameConstraints", 34099ebb4caSwyllys "X509v3 Name Constraints"); 34199ebb4caSwyllys (void) OBJ_create("2.5.29.33", "policyMappings", 34299ebb4caSwyllys "X509v3 Policy Mappings"); 34399ebb4caSwyllys (void) OBJ_create("2.5.29.36", "policyConstraints", 34499ebb4caSwyllys "X509v3 Policy Constraints"); 34599ebb4caSwyllys (void) OBJ_create("2.5.29.46", "freshestCRL", 34699ebb4caSwyllys "X509v3 Freshest CRL"); 34799ebb4caSwyllys (void) OBJ_create("2.5.29.54", "inhibitAnyPolicy", 34899ebb4caSwyllys "X509v3 Inhibit Any-Policy"); 349*300fdee2SAndy Fiddaman 350*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L 35199ebb4caSwyllys /* 35299ebb4caSwyllys * Set up for thread-safe operation. 353*300fdee2SAndy Fiddaman * This is not required for OpenSSL 1.1 35499ebb4caSwyllys */ 35599ebb4caSwyllys lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t)); 35699ebb4caSwyllys if (lock_cs == NULL) { 35799ebb4caSwyllys (void) mutex_unlock(&init_lock); 35899ebb4caSwyllys return (NULL); 35999ebb4caSwyllys } 36099ebb4caSwyllys 36199ebb4caSwyllys lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long)); 36299ebb4caSwyllys if (lock_count == NULL) { 36399ebb4caSwyllys OPENSSL_free(lock_cs); 36499ebb4caSwyllys (void) mutex_unlock(&init_lock); 36599ebb4caSwyllys return (NULL); 36699ebb4caSwyllys } 36799ebb4caSwyllys 36899ebb4caSwyllys for (i = 0; i < CRYPTO_num_locks(); i++) { 36999ebb4caSwyllys lock_count[i] = 0; 37099ebb4caSwyllys (void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL); 37199ebb4caSwyllys } 37299ebb4caSwyllys 37399ebb4caSwyllys CRYPTO_set_id_callback((unsigned long (*)())thread_id); 3742c9a247fSWyllys Ingersoll if (CRYPTO_get_locking_callback() == NULL) 37599ebb4caSwyllys CRYPTO_set_locking_callback((void (*)())locking_cb); 3762c9a247fSWyllys Ingersoll 377*300fdee2SAndy Fiddaman (void) OpenSSL_add_all_algorithms(); 3782c9a247fSWyllys Ingersoll 3792c9a247fSWyllys Ingersoll /* Enable error strings for reporting */ 380*300fdee2SAndy Fiddaman (void) ERR_load_crypto_strings(); 381*300fdee2SAndy Fiddaman #endif 3822c9a247fSWyllys Ingersoll 38399ebb4caSwyllys ssl_initialized = 1; 38499ebb4caSwyllys } 38599ebb4caSwyllys (void) mutex_unlock(&init_lock); 38699ebb4caSwyllys 38799ebb4caSwyllys return (&openssl_plugin_table); 38899ebb4caSwyllys } 389*300fdee2SAndy Fiddaman 39099ebb4caSwyllys /* 39199ebb4caSwyllys * Convert an SSL DN to a KMF DN. 39299ebb4caSwyllys */ 39399ebb4caSwyllys static KMF_RETURN 39499ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN) 39599ebb4caSwyllys { 39699ebb4caSwyllys KMF_DATA derdata; 39799ebb4caSwyllys KMF_RETURN rv = KMF_OK; 39899ebb4caSwyllys uchar_t *tmp; 39999ebb4caSwyllys 40099ebb4caSwyllys /* Convert to raw DER format */ 40199ebb4caSwyllys derdata.Length = i2d_X509_NAME(sslDN, NULL); 40299ebb4caSwyllys if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length)) 40399ebb4caSwyllys == NULL) { 40499ebb4caSwyllys return (KMF_ERR_MEMORY); 40599ebb4caSwyllys } 40699ebb4caSwyllys (void) i2d_X509_NAME(sslDN, &tmp); 40799ebb4caSwyllys 40899ebb4caSwyllys /* Decode to KMF format */ 40999ebb4caSwyllys rv = DerDecodeName(&derdata, kmfDN); 41099ebb4caSwyllys if (rv != KMF_OK) { 41199ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 41299ebb4caSwyllys } 41399ebb4caSwyllys OPENSSL_free(derdata.Data); 41499ebb4caSwyllys 41599ebb4caSwyllys return (rv); 41699ebb4caSwyllys } 41799ebb4caSwyllys 41830a5e8faSwyllys int 41999ebb4caSwyllys isdir(char *path) 42099ebb4caSwyllys { 42199ebb4caSwyllys struct stat s; 42299ebb4caSwyllys 42399ebb4caSwyllys if (stat(path, &s) == -1) 42499ebb4caSwyllys return (0); 42599ebb4caSwyllys 42630a5e8faSwyllys return ((s.st_mode & S_IFMT) == S_IFDIR); 42799ebb4caSwyllys } 42899ebb4caSwyllys 42999ebb4caSwyllys static KMF_RETURN 43099ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert) 43199ebb4caSwyllys { 43299ebb4caSwyllys KMF_RETURN rv = KMF_OK; 43399ebb4caSwyllys unsigned char *buf = NULL, *p; 43499ebb4caSwyllys int len; 43599ebb4caSwyllys 43699ebb4caSwyllys /* 43799ebb4caSwyllys * Convert the X509 internal struct to DER encoded data 43899ebb4caSwyllys */ 43999ebb4caSwyllys if ((len = i2d_X509(x509cert, NULL)) < 0) { 44099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 44199ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 44299ebb4caSwyllys goto cleanup; 44399ebb4caSwyllys } 44499ebb4caSwyllys if ((buf = malloc(len)) == NULL) { 44599ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 44699ebb4caSwyllys rv = KMF_ERR_MEMORY; 44799ebb4caSwyllys goto cleanup; 44899ebb4caSwyllys } 44999ebb4caSwyllys 45099ebb4caSwyllys /* 45199ebb4caSwyllys * i2d_X509 will increment the buf pointer so that we need to 45299ebb4caSwyllys * save it. 45399ebb4caSwyllys */ 45499ebb4caSwyllys p = buf; 45599ebb4caSwyllys if ((len = i2d_X509(x509cert, &p)) < 0) { 45699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 45799ebb4caSwyllys free(buf); 45899ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 45999ebb4caSwyllys goto cleanup; 46099ebb4caSwyllys } 46199ebb4caSwyllys 46299ebb4caSwyllys /* caller's responsibility to free it */ 46399ebb4caSwyllys cert->Data = buf; 46499ebb4caSwyllys cert->Length = len; 46599ebb4caSwyllys 46699ebb4caSwyllys cleanup: 46799ebb4caSwyllys if (rv != KMF_OK) { 46899ebb4caSwyllys if (buf) 46999ebb4caSwyllys free(buf); 47099ebb4caSwyllys cert->Data = NULL; 47199ebb4caSwyllys cert->Length = 0; 47299ebb4caSwyllys } 47399ebb4caSwyllys 47499ebb4caSwyllys return (rv); 47599ebb4caSwyllys } 47699ebb4caSwyllys 47730a5e8faSwyllys 47899ebb4caSwyllys static KMF_RETURN 47930a5e8faSwyllys check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial, 48030a5e8faSwyllys boolean_t *match) 48199ebb4caSwyllys { 48299ebb4caSwyllys KMF_RETURN rv = KMF_OK; 48399ebb4caSwyllys boolean_t findIssuer = FALSE; 48499ebb4caSwyllys boolean_t findSubject = FALSE; 48599ebb4caSwyllys boolean_t findSerial = FALSE; 48699ebb4caSwyllys KMF_X509_NAME issuerDN, subjectDN; 48799ebb4caSwyllys KMF_X509_NAME certIssuerDN, certSubjectDN; 48899ebb4caSwyllys 48999ebb4caSwyllys *match = FALSE; 49099ebb4caSwyllys if (xcert == NULL) { 49199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 49299ebb4caSwyllys } 49399ebb4caSwyllys 49499ebb4caSwyllys (void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME)); 49599ebb4caSwyllys (void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME)); 49699ebb4caSwyllys (void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME)); 49799ebb4caSwyllys (void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME)); 49899ebb4caSwyllys 49930a5e8faSwyllys if (issuer != NULL && strlen(issuer)) { 50030a5e8faSwyllys rv = kmf_dn_parser(issuer, &issuerDN); 50199ebb4caSwyllys if (rv != KMF_OK) 50299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 50399ebb4caSwyllys 504*300fdee2SAndy Fiddaman rv = get_x509_dn(X509_get_issuer_name(xcert), &certIssuerDN); 50599ebb4caSwyllys if (rv != KMF_OK) { 50630a5e8faSwyllys kmf_free_dn(&issuerDN); 50799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 50899ebb4caSwyllys } 50999ebb4caSwyllys 51099ebb4caSwyllys findIssuer = TRUE; 51199ebb4caSwyllys } 51230a5e8faSwyllys if (subject != NULL && strlen(subject)) { 51330a5e8faSwyllys rv = kmf_dn_parser(subject, &subjectDN); 51499ebb4caSwyllys if (rv != KMF_OK) { 51599ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 51699ebb4caSwyllys goto cleanup; 51799ebb4caSwyllys } 51899ebb4caSwyllys 519*300fdee2SAndy Fiddaman rv = get_x509_dn(X509_get_subject_name(xcert), &certSubjectDN); 52099ebb4caSwyllys if (rv != KMF_OK) { 52199ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 52299ebb4caSwyllys goto cleanup; 52399ebb4caSwyllys } 52499ebb4caSwyllys findSubject = TRUE; 52599ebb4caSwyllys } 52630a5e8faSwyllys if (serial != NULL && serial->val != NULL) 52799ebb4caSwyllys findSerial = TRUE; 52899ebb4caSwyllys 52999ebb4caSwyllys if (findSerial) { 53099ebb4caSwyllys BIGNUM *bn; 53199ebb4caSwyllys 53299ebb4caSwyllys /* Comparing BIGNUMs is a pain! */ 533*300fdee2SAndy Fiddaman bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(xcert), NULL); 53499ebb4caSwyllys if (bn != NULL) { 53599ebb4caSwyllys int bnlen = BN_num_bytes(bn); 53699ebb4caSwyllys 53730a5e8faSwyllys if (bnlen == serial->len) { 53899ebb4caSwyllys uchar_t *a = malloc(bnlen); 53999ebb4caSwyllys if (a == NULL) { 54099ebb4caSwyllys rv = KMF_ERR_MEMORY; 54199ebb4caSwyllys BN_free(bn); 54299ebb4caSwyllys goto cleanup; 54399ebb4caSwyllys } 54499ebb4caSwyllys bnlen = BN_bn2bin(bn, a); 54530a5e8faSwyllys *match = (memcmp(a, serial->val, serial->len) == 54630a5e8faSwyllys 0); 54799ebb4caSwyllys rv = KMF_OK; 54899ebb4caSwyllys free(a); 54999ebb4caSwyllys } 55099ebb4caSwyllys BN_free(bn); 55199ebb4caSwyllys if (!(*match)) 55299ebb4caSwyllys goto cleanup; 55399ebb4caSwyllys } else { 55499ebb4caSwyllys rv = KMF_OK; 55599ebb4caSwyllys goto cleanup; 55699ebb4caSwyllys } 55799ebb4caSwyllys } 55899ebb4caSwyllys if (findIssuer) { 55930a5e8faSwyllys *match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0); 56030a5e8faSwyllys if ((*match) == B_FALSE) { 56130a5e8faSwyllys /* stop checking and bail */ 56299ebb4caSwyllys rv = KMF_OK; 56399ebb4caSwyllys goto cleanup; 56499ebb4caSwyllys } 56599ebb4caSwyllys } 56699ebb4caSwyllys if (findSubject) { 56730a5e8faSwyllys *match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0); 56830a5e8faSwyllys if ((*match) == B_FALSE) { 56930a5e8faSwyllys /* stop checking and bail */ 57099ebb4caSwyllys rv = KMF_OK; 57199ebb4caSwyllys goto cleanup; 57299ebb4caSwyllys } 57399ebb4caSwyllys } 57499ebb4caSwyllys 57599ebb4caSwyllys *match = TRUE; 57699ebb4caSwyllys cleanup: 57799ebb4caSwyllys if (findIssuer) { 57830a5e8faSwyllys kmf_free_dn(&issuerDN); 57930a5e8faSwyllys kmf_free_dn(&certIssuerDN); 58099ebb4caSwyllys } 58199ebb4caSwyllys if (findSubject) { 58230a5e8faSwyllys kmf_free_dn(&subjectDN); 58330a5e8faSwyllys kmf_free_dn(&certSubjectDN); 58499ebb4caSwyllys } 58599ebb4caSwyllys 58699ebb4caSwyllys return (rv); 58799ebb4caSwyllys } 58899ebb4caSwyllys 58930a5e8faSwyllys 59030a5e8faSwyllys /* 59130a5e8faSwyllys * This function loads a certificate file into an X509 data structure, and 59230a5e8faSwyllys * checks if its issuer, subject or the serial number matches with those 59330a5e8faSwyllys * values. If it matches, then return the X509 data structure. 59430a5e8faSwyllys */ 59599ebb4caSwyllys static KMF_RETURN 59699ebb4caSwyllys load_X509cert(KMF_HANDLE *kmfh, 59730a5e8faSwyllys char *issuer, char *subject, KMF_BIGINT *serial, 59830a5e8faSwyllys char *pathname, X509 **outcert) 59999ebb4caSwyllys { 60099ebb4caSwyllys KMF_RETURN rv = KMF_OK; 60199ebb4caSwyllys X509 *xcert = NULL; 60299ebb4caSwyllys BIO *bcert = NULL; 60399ebb4caSwyllys boolean_t match = FALSE; 60499ebb4caSwyllys KMF_ENCODE_FORMAT format; 60599ebb4caSwyllys 60699ebb4caSwyllys /* 60799ebb4caSwyllys * auto-detect the file format, regardless of what 60899ebb4caSwyllys * the 'format' parameters in the params say. 60999ebb4caSwyllys */ 61030a5e8faSwyllys rv = kmf_get_file_format(pathname, &format); 61199ebb4caSwyllys if (rv != KMF_OK) { 61299ebb4caSwyllys if (rv == KMF_ERR_OPEN_FILE) 61399ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND; 61499ebb4caSwyllys return (rv); 61599ebb4caSwyllys } 61699ebb4caSwyllys 61799ebb4caSwyllys /* Not ASN1(DER) format */ 61899ebb4caSwyllys if ((bcert = BIO_new_file(pathname, "rb")) == NULL) { 61999ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 62099ebb4caSwyllys rv = KMF_ERR_OPEN_FILE; 62199ebb4caSwyllys goto cleanup; 62299ebb4caSwyllys } 62399ebb4caSwyllys 62499ebb4caSwyllys if (format == KMF_FORMAT_PEM) 62599ebb4caSwyllys xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL); 62699ebb4caSwyllys else if (format == KMF_FORMAT_ASN1) 62799ebb4caSwyllys xcert = d2i_X509_bio(bcert, NULL); 62899ebb4caSwyllys else if (format == KMF_FORMAT_PKCS12) { 62999ebb4caSwyllys PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL); 63099ebb4caSwyllys if (p12 != NULL) { 63199ebb4caSwyllys (void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL); 63299ebb4caSwyllys PKCS12_free(p12); 63399ebb4caSwyllys p12 = NULL; 63499ebb4caSwyllys } else { 63599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 63699ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 63799ebb4caSwyllys } 63899ebb4caSwyllys } else { 63999ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 64099ebb4caSwyllys goto cleanup; 64199ebb4caSwyllys } 64299ebb4caSwyllys 64399ebb4caSwyllys if (xcert == NULL) { 64499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 64599ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 64699ebb4caSwyllys goto cleanup; 64799ebb4caSwyllys } 64899ebb4caSwyllys 64930a5e8faSwyllys if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK || 65030a5e8faSwyllys match == FALSE) { 65199ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND; 65299ebb4caSwyllys goto cleanup; 65399ebb4caSwyllys } 65499ebb4caSwyllys 65599ebb4caSwyllys if (outcert != NULL) { 65699ebb4caSwyllys *outcert = xcert; 65799ebb4caSwyllys } 65899ebb4caSwyllys 65999ebb4caSwyllys cleanup: 66099ebb4caSwyllys if (bcert != NULL) (void) BIO_free(bcert); 66199ebb4caSwyllys if (rv != KMF_OK && xcert != NULL) 66299ebb4caSwyllys X509_free(xcert); 66399ebb4caSwyllys 66499ebb4caSwyllys return (rv); 66599ebb4caSwyllys } 66699ebb4caSwyllys 66771593db2Swyllys static int 66871593db2Swyllys datacmp(const void *a, const void *b) 66971593db2Swyllys { 67071593db2Swyllys KMF_DATA *adata = (KMF_DATA *)a; 67171593db2Swyllys KMF_DATA *bdata = (KMF_DATA *)b; 67271593db2Swyllys if (adata->Length > bdata->Length) 67371593db2Swyllys return (-1); 67471593db2Swyllys if (adata->Length < bdata->Length) 67571593db2Swyllys return (1); 67671593db2Swyllys return (0); 67771593db2Swyllys } 67871593db2Swyllys 67971593db2Swyllys static KMF_RETURN 68030a5e8faSwyllys load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial, 68130a5e8faSwyllys KMF_CERT_VALIDITY validity, char *pathname, 68271593db2Swyllys KMF_DATA **certlist, uint32_t *numcerts) 68371593db2Swyllys { 68471593db2Swyllys KMF_RETURN rv = KMF_OK; 68571593db2Swyllys int i; 68671593db2Swyllys KMF_DATA *certs = NULL; 68771593db2Swyllys int nc = 0; 68871593db2Swyllys int hits = 0; 68971593db2Swyllys KMF_ENCODE_FORMAT format; 69071593db2Swyllys 69130a5e8faSwyllys rv = kmf_get_file_format(pathname, &format); 69271593db2Swyllys if (rv != KMF_OK) { 69371593db2Swyllys if (rv == KMF_ERR_OPEN_FILE) 69471593db2Swyllys rv = KMF_ERR_CERT_NOT_FOUND; 69571593db2Swyllys return (rv); 69671593db2Swyllys } 69771593db2Swyllys if (format == KMF_FORMAT_ASN1) { 69871593db2Swyllys /* load a single certificate */ 69971593db2Swyllys certs = (KMF_DATA *)malloc(sizeof (KMF_DATA)); 70071593db2Swyllys if (certs == NULL) 70171593db2Swyllys return (KMF_ERR_MEMORY); 70271593db2Swyllys certs->Data = NULL; 70371593db2Swyllys certs->Length = 0; 70430a5e8faSwyllys rv = kmf_load_cert(kmfh, issuer, subject, serial, validity, 70530a5e8faSwyllys pathname, certs); 70671593db2Swyllys if (rv == KMF_OK) { 70771593db2Swyllys *certlist = certs; 70871593db2Swyllys *numcerts = 1; 709a2d4930dSDan OpenSolaris Anderson } else { 710a2d4930dSDan OpenSolaris Anderson kmf_free_data(certs); 711a2d4930dSDan OpenSolaris Anderson free(certs); 712a2d4930dSDan OpenSolaris Anderson certs = NULL; 71371593db2Swyllys } 71471593db2Swyllys return (rv); 71571593db2Swyllys } else if (format == KMF_FORMAT_PKCS12) { 71671593db2Swyllys /* We need a credential to access a PKCS#12 file */ 71771593db2Swyllys rv = KMF_ERR_BAD_CERT_FORMAT; 71871593db2Swyllys } else if (format == KMF_FORMAT_PEM || 71971593db2Swyllys format != KMF_FORMAT_PEM_KEYPAIR) { 720e65e5c2dSWyllys Ingersoll 72171593db2Swyllys /* This function only works on PEM files */ 72230a5e8faSwyllys rv = extract_pem(kmfh, issuer, subject, serial, pathname, 72334acef67Swyllys (uchar_t *)NULL, 0, NULL, &certs, &nc); 72471593db2Swyllys } else { 72571593db2Swyllys return (KMF_ERR_ENCODING); 72671593db2Swyllys } 72771593db2Swyllys 72871593db2Swyllys if (rv != KMF_OK) 72971593db2Swyllys return (rv); 73071593db2Swyllys 73171593db2Swyllys for (i = 0; i < nc; i++) { 73230a5e8faSwyllys if (validity == KMF_NONEXPIRED_CERTS) { 73330a5e8faSwyllys rv = kmf_check_cert_date(kmfh, &certs[i]); 73430a5e8faSwyllys } else if (validity == KMF_EXPIRED_CERTS) { 73530a5e8faSwyllys rv = kmf_check_cert_date(kmfh, &certs[i]); 73671593db2Swyllys if (rv == KMF_OK) 73771593db2Swyllys rv = KMF_ERR_CERT_NOT_FOUND; 73871593db2Swyllys if (rv == KMF_ERR_VALIDITY_PERIOD) 73971593db2Swyllys rv = KMF_OK; 74071593db2Swyllys } 74171593db2Swyllys if (rv != KMF_OK) { 74271593db2Swyllys /* Remove this cert from the list by clearing it. */ 74330a5e8faSwyllys kmf_free_data(&certs[i]); 74471593db2Swyllys } else { 74571593db2Swyllys hits++; /* count valid certs found */ 74671593db2Swyllys } 74771593db2Swyllys rv = KMF_OK; 74871593db2Swyllys } 749a2d4930dSDan OpenSolaris Anderson if (rv == KMF_OK && hits > 0) { 75071593db2Swyllys /* 75171593db2Swyllys * Sort the list of certs by length to put the cleared ones 75271593db2Swyllys * at the end so they don't get accessed by the caller. 75371593db2Swyllys */ 75471593db2Swyllys qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp); 75571593db2Swyllys *certlist = certs; 75671593db2Swyllys 75771593db2Swyllys /* since we sorted the list, just return the number of hits */ 75871593db2Swyllys *numcerts = hits; 759a2d4930dSDan OpenSolaris Anderson } else { 760e65e5c2dSWyllys Ingersoll if (rv == KMF_OK && hits == 0) 761a2d4930dSDan OpenSolaris Anderson rv = KMF_ERR_CERT_NOT_FOUND; 762a2d4930dSDan OpenSolaris Anderson if (certs != NULL) { 763a2d4930dSDan OpenSolaris Anderson free(certs); 764a2d4930dSDan OpenSolaris Anderson certs = NULL; 765a2d4930dSDan OpenSolaris Anderson } 766a2d4930dSDan OpenSolaris Anderson } 76771593db2Swyllys return (rv); 76871593db2Swyllys } 76971593db2Swyllys 77099ebb4caSwyllys static KMF_RETURN 77199ebb4caSwyllys kmf_load_cert(KMF_HANDLE *kmfh, 77230a5e8faSwyllys char *issuer, char *subject, KMF_BIGINT *serial, 77330a5e8faSwyllys KMF_CERT_VALIDITY validity, 77499ebb4caSwyllys char *pathname, 77599ebb4caSwyllys KMF_DATA *cert) 77699ebb4caSwyllys { 77799ebb4caSwyllys KMF_RETURN rv = KMF_OK; 77899ebb4caSwyllys X509 *x509cert = NULL; 77999ebb4caSwyllys 78030a5e8faSwyllys rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert); 78199ebb4caSwyllys if (rv == KMF_OK && x509cert != NULL && cert != NULL) { 78299ebb4caSwyllys rv = ssl_cert2KMFDATA(kmfh, x509cert, cert); 78399ebb4caSwyllys if (rv != KMF_OK) { 78499ebb4caSwyllys goto cleanup; 78599ebb4caSwyllys } 78630a5e8faSwyllys if (validity == KMF_NONEXPIRED_CERTS) { 78730a5e8faSwyllys rv = kmf_check_cert_date(kmfh, cert); 78830a5e8faSwyllys } else if (validity == KMF_EXPIRED_CERTS) { 78930a5e8faSwyllys rv = kmf_check_cert_date(kmfh, cert); 79099ebb4caSwyllys if (rv == KMF_OK) { 79199ebb4caSwyllys /* 79299ebb4caSwyllys * This is a valid cert so skip it. 79399ebb4caSwyllys */ 79499ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND; 79599ebb4caSwyllys } 79699ebb4caSwyllys if (rv == KMF_ERR_VALIDITY_PERIOD) { 79799ebb4caSwyllys /* 79899ebb4caSwyllys * We want to return success when we 79999ebb4caSwyllys * find an invalid cert. 80099ebb4caSwyllys */ 80199ebb4caSwyllys rv = KMF_OK; 80299ebb4caSwyllys goto cleanup; 80399ebb4caSwyllys } 80499ebb4caSwyllys } 80599ebb4caSwyllys } 80699ebb4caSwyllys cleanup: 80799ebb4caSwyllys if (x509cert != NULL) 80899ebb4caSwyllys X509_free(x509cert); 80999ebb4caSwyllys 81099ebb4caSwyllys return (rv); 81199ebb4caSwyllys } 81299ebb4caSwyllys 81302744e81Swyllys static KMF_RETURN 81402744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey) 81502744e81Swyllys { 81602744e81Swyllys KMF_RETURN ret = KMF_OK; 81702744e81Swyllys KMF_RAW_RSA_KEY rsa; 81802744e81Swyllys BerElement *asn1 = NULL; 81902744e81Swyllys BerValue filebuf; 82002744e81Swyllys BerValue OID = { NULL, 0 }; 82102744e81Swyllys BerValue *Mod = NULL, *PubExp = NULL; 82202744e81Swyllys BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL; 82302744e81Swyllys BerValue *Coef = NULL; 82402744e81Swyllys BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL; 82502744e81Swyllys BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL; 82602744e81Swyllys BIGNUM *qminus1 = NULL; 82702744e81Swyllys BN_CTX *ctx = NULL; 82802744e81Swyllys 82902744e81Swyllys *pkey = NULL; 83002744e81Swyllys 83102744e81Swyllys filebuf.bv_val = (char *)filedata->Data; 83202744e81Swyllys filebuf.bv_len = filedata->Length; 83302744e81Swyllys 83402744e81Swyllys asn1 = kmfder_init(&filebuf); 83502744e81Swyllys if (asn1 == NULL) { 83602744e81Swyllys ret = KMF_ERR_MEMORY; 83702744e81Swyllys goto out; 83802744e81Swyllys } 83902744e81Swyllys 84002744e81Swyllys if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}", 84102744e81Swyllys &OID, &Mod, &PubExp, &PriExp, &Prime1, 84202744e81Swyllys &Prime2, &Coef) == -1) { 84302744e81Swyllys ret = KMF_ERR_ENCODING; 84402744e81Swyllys goto out; 84502744e81Swyllys } 84602744e81Swyllys 84702744e81Swyllys /* 84802744e81Swyllys * We have to derive the 2 Exponents using Bignumber math. 84902744e81Swyllys * Exp1 = PriExp mod (Prime1 - 1) 85002744e81Swyllys * Exp2 = PriExp mod (Prime2 - 1) 85102744e81Swyllys */ 85202744e81Swyllys 85302744e81Swyllys /* D = PrivateExponent */ 85402744e81Swyllys D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D); 85502744e81Swyllys if (D == NULL) { 85602744e81Swyllys ret = KMF_ERR_MEMORY; 85702744e81Swyllys goto out; 85802744e81Swyllys } 85902744e81Swyllys 86002744e81Swyllys /* P = Prime1 (first prime factor of Modulus) */ 86102744e81Swyllys P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P); 86202744e81Swyllys if (D == NULL) { 86302744e81Swyllys ret = KMF_ERR_MEMORY; 86402744e81Swyllys goto out; 86502744e81Swyllys } 86602744e81Swyllys 86702744e81Swyllys /* Q = Prime2 (second prime factor of Modulus) */ 86802744e81Swyllys Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q); 86902744e81Swyllys 87002744e81Swyllys if ((ctx = BN_CTX_new()) == NULL) { 87102744e81Swyllys ret = KMF_ERR_MEMORY; 87202744e81Swyllys goto out; 87302744e81Swyllys } 87402744e81Swyllys 87502744e81Swyllys /* Compute (P - 1) */ 87602744e81Swyllys pminus1 = BN_new(); 87702744e81Swyllys (void) BN_sub(pminus1, P, BN_value_one()); 87802744e81Swyllys 87902744e81Swyllys /* Exponent1 = D mod (P - 1) */ 88002744e81Swyllys Exp1 = BN_new(); 88102744e81Swyllys (void) BN_mod(Exp1, D, pminus1, ctx); 88202744e81Swyllys 88302744e81Swyllys /* Compute (Q - 1) */ 88402744e81Swyllys qminus1 = BN_new(); 88502744e81Swyllys (void) BN_sub(qminus1, Q, BN_value_one()); 88602744e81Swyllys 88702744e81Swyllys /* Exponent2 = D mod (Q - 1) */ 88802744e81Swyllys Exp2 = BN_new(); 88902744e81Swyllys (void) BN_mod(Exp2, D, qminus1, ctx); 89002744e81Swyllys 89102744e81Swyllys /* Coef = (Inverse Q) mod P */ 89202744e81Swyllys COEF = BN_new(); 89302744e81Swyllys (void) BN_mod_inverse(COEF, Q, P, ctx); 89402744e81Swyllys 89502744e81Swyllys /* Convert back to KMF format */ 89602744e81Swyllys (void) memset(&rsa, 0, sizeof (rsa)); 89702744e81Swyllys 89802744e81Swyllys if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK) 89902744e81Swyllys goto out; 90002744e81Swyllys if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK) 90102744e81Swyllys goto out; 90202744e81Swyllys if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK) 90302744e81Swyllys goto out; 90402744e81Swyllys 90502744e81Swyllys rsa.mod.val = (uchar_t *)Mod->bv_val; 90602744e81Swyllys rsa.mod.len = Mod->bv_len; 90702744e81Swyllys 90802744e81Swyllys rsa.pubexp.val = (uchar_t *)PubExp->bv_val; 90902744e81Swyllys rsa.pubexp.len = PubExp->bv_len; 91002744e81Swyllys 91102744e81Swyllys rsa.priexp.val = (uchar_t *)PriExp->bv_val; 91202744e81Swyllys rsa.priexp.len = PriExp->bv_len; 91302744e81Swyllys 91402744e81Swyllys rsa.prime1.val = (uchar_t *)Prime1->bv_val; 91502744e81Swyllys rsa.prime1.len = Prime1->bv_len; 91602744e81Swyllys 91702744e81Swyllys rsa.prime2.val = (uchar_t *)Prime2->bv_val; 91802744e81Swyllys rsa.prime2.len = Prime2->bv_len; 91902744e81Swyllys 92002744e81Swyllys *pkey = ImportRawRSAKey(&rsa); 92102744e81Swyllys out: 92202744e81Swyllys if (asn1 != NULL) 92302744e81Swyllys kmfber_free(asn1, 1); 92402744e81Swyllys 92502744e81Swyllys if (OID.bv_val) { 92602744e81Swyllys free(OID.bv_val); 92702744e81Swyllys } 92802744e81Swyllys if (PriExp) 92902744e81Swyllys free(PriExp); 93002744e81Swyllys 93102744e81Swyllys if (Mod) 93202744e81Swyllys free(Mod); 93302744e81Swyllys 93402744e81Swyllys if (PubExp) 93502744e81Swyllys free(PubExp); 93602744e81Swyllys 93702744e81Swyllys if (Coef) { 93802744e81Swyllys (void) memset(Coef->bv_val, 0, Coef->bv_len); 93902744e81Swyllys free(Coef->bv_val); 94002744e81Swyllys free(Coef); 94102744e81Swyllys } 94202744e81Swyllys if (Prime1) 94302744e81Swyllys free(Prime1); 94402744e81Swyllys if (Prime2) 94502744e81Swyllys free(Prime2); 94602744e81Swyllys 94702744e81Swyllys if (ctx != NULL) 94802744e81Swyllys BN_CTX_free(ctx); 94902744e81Swyllys 95002744e81Swyllys if (D) 95102744e81Swyllys BN_clear_free(D); 95202744e81Swyllys if (P) 95302744e81Swyllys BN_clear_free(P); 95402744e81Swyllys if (Q) 95502744e81Swyllys BN_clear_free(Q); 95602744e81Swyllys if (pminus1) 95702744e81Swyllys BN_clear_free(pminus1); 95802744e81Swyllys if (qminus1) 95902744e81Swyllys BN_clear_free(qminus1); 96002744e81Swyllys if (Exp1) 96102744e81Swyllys BN_clear_free(Exp1); 96202744e81Swyllys if (Exp2) 96302744e81Swyllys BN_clear_free(Exp2); 96402744e81Swyllys 96502744e81Swyllys return (ret); 96602744e81Swyllys 96702744e81Swyllys } 96802744e81Swyllys 96999ebb4caSwyllys static EVP_PKEY * 97099ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file) 97199ebb4caSwyllys { 97299ebb4caSwyllys BIO *keyfile = NULL; 97399ebb4caSwyllys EVP_PKEY *pkey = NULL; 97499ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 97599ebb4caSwyllys KMF_ENCODE_FORMAT format; 97602744e81Swyllys KMF_RETURN rv; 97702744e81Swyllys KMF_DATA filedata; 97899ebb4caSwyllys 97999ebb4caSwyllys if (file == NULL) { 98099ebb4caSwyllys return (NULL); 98199ebb4caSwyllys } 98299ebb4caSwyllys 98330a5e8faSwyllys if (kmf_get_file_format((char *)file, &format) != KMF_OK) 98499ebb4caSwyllys return (NULL); 98599ebb4caSwyllys 98699ebb4caSwyllys keyfile = BIO_new_file(file, "rb"); 98799ebb4caSwyllys if (keyfile == NULL) { 98899ebb4caSwyllys goto end; 98999ebb4caSwyllys } 99099ebb4caSwyllys 99102744e81Swyllys if (format == KMF_FORMAT_ASN1) { 99299ebb4caSwyllys pkey = d2i_PrivateKey_bio(keyfile, NULL); 99302744e81Swyllys if (pkey == NULL) { 99402744e81Swyllys 99502744e81Swyllys (void) BIO_free(keyfile); 99602744e81Swyllys keyfile = NULL; 99702744e81Swyllys /* Try odd ASN.1 variations */ 99830a5e8faSwyllys rv = kmf_read_input_file(kmfh, (char *)file, 99902744e81Swyllys &filedata); 100002744e81Swyllys if (rv == KMF_OK) { 100102744e81Swyllys (void) readAltFormatPrivateKey(&filedata, 100202744e81Swyllys &pkey); 100330a5e8faSwyllys kmf_free_data(&filedata); 100402744e81Swyllys } 100502744e81Swyllys } 100602744e81Swyllys } else if (format == KMF_FORMAT_PEM || 100702744e81Swyllys format == KMF_FORMAT_PEM_KEYPAIR) { 100899ebb4caSwyllys pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL); 100902744e81Swyllys if (pkey == NULL) { 101002744e81Swyllys KMF_DATA derdata; 101102744e81Swyllys /* 101202744e81Swyllys * Check if this is the alt. format 101302744e81Swyllys * RSA private key file. 101402744e81Swyllys */ 101530a5e8faSwyllys rv = kmf_read_input_file(kmfh, (char *)file, 101602744e81Swyllys &filedata); 101702744e81Swyllys if (rv == KMF_OK) { 101802744e81Swyllys uchar_t *d = NULL; 101902744e81Swyllys int len; 102030a5e8faSwyllys rv = kmf_pem_to_der(filedata.Data, 102102744e81Swyllys filedata.Length, &d, &len); 102202744e81Swyllys if (rv == KMF_OK && d != NULL) { 102302744e81Swyllys derdata.Data = d; 102402744e81Swyllys derdata.Length = (size_t)len; 102502744e81Swyllys (void) readAltFormatPrivateKey( 102602744e81Swyllys &derdata, &pkey); 102702744e81Swyllys free(d); 102802744e81Swyllys } 102930a5e8faSwyllys kmf_free_data(&filedata); 103002744e81Swyllys } 103102744e81Swyllys } 103202744e81Swyllys } 103399ebb4caSwyllys 103499ebb4caSwyllys end: 103599ebb4caSwyllys if (pkey == NULL) 103699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 103799ebb4caSwyllys 103899ebb4caSwyllys if (keyfile != NULL) 103999ebb4caSwyllys (void) BIO_free(keyfile); 104099ebb4caSwyllys 104199ebb4caSwyllys return (pkey); 104299ebb4caSwyllys } 104399ebb4caSwyllys 104499ebb4caSwyllys KMF_RETURN 104530a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 104699ebb4caSwyllys { 104799ebb4caSwyllys KMF_RETURN rv = KMF_OK; 104899ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 1049f482c776Swyllys int i, n; 1050f482c776Swyllys uint32_t maxcerts = 0; 105130a5e8faSwyllys uint32_t *num_certs; 105230a5e8faSwyllys KMF_X509_DER_CERT *kmf_cert = NULL; 105330a5e8faSwyllys char *dirpath = NULL; 105430a5e8faSwyllys char *filename = NULL; 105530a5e8faSwyllys char *fullpath = NULL; 105630a5e8faSwyllys char *issuer = NULL; 105730a5e8faSwyllys char *subject = NULL; 105830a5e8faSwyllys KMF_BIGINT *serial = NULL; 105930a5e8faSwyllys KMF_CERT_VALIDITY validity; 106099ebb4caSwyllys 106130a5e8faSwyllys num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr); 106230a5e8faSwyllys if (num_certs == NULL) 106399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 106499ebb4caSwyllys 106530a5e8faSwyllys /* num_certs should reference the size of kmf_cert */ 1066f482c776Swyllys maxcerts = *num_certs; 1067f482c776Swyllys if (maxcerts == 0) 1068f482c776Swyllys maxcerts = 0xFFFFFFFF; 106999ebb4caSwyllys *num_certs = 0; 107099ebb4caSwyllys 107130a5e8faSwyllys /* Get the optional returned certificate list */ 107230a5e8faSwyllys kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist, 107330a5e8faSwyllys numattr); 107499ebb4caSwyllys 107530a5e8faSwyllys /* 107630a5e8faSwyllys * The dirpath attribute and the filename attribute can not be NULL 107730a5e8faSwyllys * at the same time. 107830a5e8faSwyllys */ 107930a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 108030a5e8faSwyllys filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, 108130a5e8faSwyllys numattr); 108230a5e8faSwyllys 108330a5e8faSwyllys fullpath = get_fullpath(dirpath, filename); 108499ebb4caSwyllys if (fullpath == NULL) 108599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 108699ebb4caSwyllys 108730a5e8faSwyllys /* Get optional search criteria attributes */ 108830a5e8faSwyllys issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr); 108930a5e8faSwyllys subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr); 109030a5e8faSwyllys serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr); 109130a5e8faSwyllys rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr, 109230a5e8faSwyllys &validity, NULL); 109330a5e8faSwyllys if (rv != KMF_OK) { 109430a5e8faSwyllys validity = KMF_ALL_CERTS; 109530a5e8faSwyllys rv = KMF_OK; 109630a5e8faSwyllys } 109730a5e8faSwyllys 109899ebb4caSwyllys if (isdir(fullpath)) { 109999ebb4caSwyllys DIR *dirp; 110099ebb4caSwyllys struct dirent *dp; 110199ebb4caSwyllys 1102f482c776Swyllys n = 0; 110399ebb4caSwyllys /* open all files in the directory and attempt to read them */ 110499ebb4caSwyllys if ((dirp = opendir(fullpath)) == NULL) { 110599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 110699ebb4caSwyllys } 110799ebb4caSwyllys while ((dp = readdir(dirp)) != NULL) { 110899ebb4caSwyllys char *fname; 110971593db2Swyllys KMF_DATA *certlist = NULL; 1110f482c776Swyllys uint32_t loaded_certs = 0; 111171593db2Swyllys 111299ebb4caSwyllys if (strcmp(dp->d_name, ".") == 0 || 111399ebb4caSwyllys strcmp(dp->d_name, "..") == 0) 111499ebb4caSwyllys continue; 111599ebb4caSwyllys 111634acef67Swyllys fname = get_fullpath(fullpath, (char *)&dp->d_name); 111799ebb4caSwyllys 111830a5e8faSwyllys rv = load_certs(kmfh, issuer, subject, serial, 111930a5e8faSwyllys validity, fname, &certlist, &loaded_certs); 112099ebb4caSwyllys 112199ebb4caSwyllys if (rv != KMF_OK) { 112299ebb4caSwyllys free(fname); 112371593db2Swyllys if (certlist != NULL) { 1124f482c776Swyllys for (i = 0; i < loaded_certs; i++) 112530a5e8faSwyllys kmf_free_data(&certlist[i]); 112671593db2Swyllys free(certlist); 112771593db2Swyllys } 112899ebb4caSwyllys continue; 112999ebb4caSwyllys } 113099ebb4caSwyllys 113199ebb4caSwyllys /* If load succeeds, add certdata to the list */ 113299ebb4caSwyllys if (kmf_cert != NULL) { 1133f482c776Swyllys for (i = 0; i < loaded_certs && 1134b4058258Swyllys n < maxcerts; i++) { 113571593db2Swyllys kmf_cert[n].certificate.Data = 113671593db2Swyllys certlist[i].Data; 113799ebb4caSwyllys kmf_cert[n].certificate.Length = 113871593db2Swyllys certlist[i].Length; 113999ebb4caSwyllys 114099ebb4caSwyllys kmf_cert[n].kmf_private.keystore_type = 114199ebb4caSwyllys KMF_KEYSTORE_OPENSSL; 114299ebb4caSwyllys kmf_cert[n].kmf_private.flags = 114399ebb4caSwyllys KMF_FLAG_CERT_VALID; 114471593db2Swyllys kmf_cert[n].kmf_private.label = 114571593db2Swyllys strdup(fname); 114699ebb4caSwyllys n++; 114799ebb4caSwyllys } 1148b4058258Swyllys /* 1149b4058258Swyllys * If maxcerts < loaded_certs, clean up the 1150b4058258Swyllys * certs that were not used. 1151b4058258Swyllys */ 1152f482c776Swyllys for (; i < loaded_certs; i++) 115330a5e8faSwyllys kmf_free_data(&certlist[i]); 1154f482c776Swyllys } else { 1155f482c776Swyllys for (i = 0; i < loaded_certs; i++) 115630a5e8faSwyllys kmf_free_data(&certlist[i]); 1157f482c776Swyllys n += loaded_certs; 115871593db2Swyllys } 1159f482c776Swyllys free(certlist); 116071593db2Swyllys free(fname); 116171593db2Swyllys } 116299ebb4caSwyllys (*num_certs) = n; 116399ebb4caSwyllys if (*num_certs == 0) 116499ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND; 116530a5e8faSwyllys if (*num_certs > 0) 116699ebb4caSwyllys rv = KMF_OK; 116799ebb4caSwyllys exit: 116899ebb4caSwyllys (void) closedir(dirp); 116999ebb4caSwyllys } else { 117071593db2Swyllys KMF_DATA *certlist = NULL; 1171f482c776Swyllys uint32_t loaded_certs = 0; 117271593db2Swyllys 117330a5e8faSwyllys rv = load_certs(kmfh, issuer, subject, serial, validity, 117430a5e8faSwyllys fullpath, &certlist, &loaded_certs); 117599ebb4caSwyllys if (rv != KMF_OK) { 117699ebb4caSwyllys free(fullpath); 117799ebb4caSwyllys return (rv); 117899ebb4caSwyllys } 117999ebb4caSwyllys 1180f482c776Swyllys n = 0; 118171593db2Swyllys if (kmf_cert != NULL && certlist != NULL) { 1182f482c776Swyllys for (i = 0; i < loaded_certs && i < maxcerts; i++) { 1183f482c776Swyllys kmf_cert[n].certificate.Data = 118471593db2Swyllys certlist[i].Data; 1185f482c776Swyllys kmf_cert[n].certificate.Length = 118671593db2Swyllys certlist[i].Length; 1187f482c776Swyllys kmf_cert[n].kmf_private.keystore_type = 118899ebb4caSwyllys KMF_KEYSTORE_OPENSSL; 1189f482c776Swyllys kmf_cert[n].kmf_private.flags = 119071593db2Swyllys KMF_FLAG_CERT_VALID; 1191f482c776Swyllys kmf_cert[n].kmf_private.label = 119271593db2Swyllys strdup(fullpath); 1193f482c776Swyllys n++; 119471593db2Swyllys } 1195f482c776Swyllys /* If maxcerts < loaded_certs, clean up */ 1196f482c776Swyllys for (; i < loaded_certs; i++) 119730a5e8faSwyllys kmf_free_data(&certlist[i]); 1198f482c776Swyllys } else if (certlist != NULL) { 1199f482c776Swyllys for (i = 0; i < loaded_certs; i++) 120030a5e8faSwyllys kmf_free_data(&certlist[i]); 1201f482c776Swyllys n = loaded_certs; 1202f482c776Swyllys } 120330a5e8faSwyllys if (certlist != NULL) 120471593db2Swyllys free(certlist); 1205f482c776Swyllys *num_certs = n; 120699ebb4caSwyllys } 120799ebb4caSwyllys 120899ebb4caSwyllys free(fullpath); 120999ebb4caSwyllys 121099ebb4caSwyllys return (rv); 121199ebb4caSwyllys } 121299ebb4caSwyllys 121399ebb4caSwyllys void 121499ebb4caSwyllys /*ARGSUSED*/ 121599ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle, 121699ebb4caSwyllys KMF_X509_DER_CERT *kmf_cert) 121799ebb4caSwyllys { 121899ebb4caSwyllys if (kmf_cert != NULL) { 121999ebb4caSwyllys if (kmf_cert->certificate.Data != NULL) { 1220e65e5c2dSWyllys Ingersoll kmf_free_data(&kmf_cert->certificate); 122199ebb4caSwyllys } 122299ebb4caSwyllys if (kmf_cert->kmf_private.label) 122399ebb4caSwyllys free(kmf_cert->kmf_private.label); 122499ebb4caSwyllys } 122599ebb4caSwyllys } 122699ebb4caSwyllys 122730a5e8faSwyllys /*ARGSUSED*/ 122899ebb4caSwyllys KMF_RETURN 122930a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 123099ebb4caSwyllys { 123199ebb4caSwyllys KMF_RETURN ret = KMF_OK; 123230a5e8faSwyllys KMF_DATA *cert = NULL; 123330a5e8faSwyllys char *outfilename = NULL; 123430a5e8faSwyllys char *dirpath = NULL; 123530a5e8faSwyllys char *fullpath = NULL; 123699ebb4caSwyllys KMF_ENCODE_FORMAT format; 123799ebb4caSwyllys 123830a5e8faSwyllys /* Get the cert data */ 123930a5e8faSwyllys cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr); 124030a5e8faSwyllys if (cert == NULL || cert->Data == NULL) 124199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 124299ebb4caSwyllys 124330a5e8faSwyllys /* Check the output filename and directory attributes. */ 124430a5e8faSwyllys outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, 124530a5e8faSwyllys numattr); 124630a5e8faSwyllys if (outfilename == NULL) 124730a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 124899ebb4caSwyllys 124930a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 125030a5e8faSwyllys fullpath = get_fullpath(dirpath, outfilename); 125199ebb4caSwyllys if (fullpath == NULL) 125230a5e8faSwyllys return (KMF_ERR_BAD_CERTFILE); 125399ebb4caSwyllys 125430a5e8faSwyllys /* Check the optional format attribute */ 125530a5e8faSwyllys ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 125630a5e8faSwyllys &format, NULL); 125730a5e8faSwyllys if (ret != KMF_OK) { 125830a5e8faSwyllys /* If there is no format attribute, then default to PEM */ 125930a5e8faSwyllys format = KMF_FORMAT_PEM; 126099ebb4caSwyllys ret = KMF_OK; 126130a5e8faSwyllys } else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) { 126230a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 126399ebb4caSwyllys goto out; 126499ebb4caSwyllys } 126599ebb4caSwyllys 126630a5e8faSwyllys /* Store the certificate in the file with the specified format */ 126730a5e8faSwyllys ret = kmf_create_cert_file(cert, format, fullpath); 126899ebb4caSwyllys 126999ebb4caSwyllys out: 127099ebb4caSwyllys if (fullpath != NULL) 127199ebb4caSwyllys free(fullpath); 127299ebb4caSwyllys 127399ebb4caSwyllys return (ret); 127499ebb4caSwyllys } 127599ebb4caSwyllys 127630a5e8faSwyllys 127799ebb4caSwyllys KMF_RETURN 127830a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 127999ebb4caSwyllys { 128099ebb4caSwyllys KMF_RETURN rv; 128199ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 12826b35cb3cSRichard PALO KMF_DATA certdata = { 0, NULL }; 128330a5e8faSwyllys char *dirpath = NULL; 128430a5e8faSwyllys char *filename = NULL; 128530a5e8faSwyllys char *fullpath = NULL; 128630a5e8faSwyllys char *issuer = NULL; 128730a5e8faSwyllys char *subject = NULL; 128830a5e8faSwyllys KMF_BIGINT *serial = NULL; 128930a5e8faSwyllys KMF_CERT_VALIDITY validity; 129099ebb4caSwyllys 129130a5e8faSwyllys /* 129230a5e8faSwyllys * Get the DIRPATH and CERT_FILENAME attributes. They can not be 129330a5e8faSwyllys * NULL at the same time. 129430a5e8faSwyllys */ 129530a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 129630a5e8faSwyllys filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, 129730a5e8faSwyllys numattr); 129830a5e8faSwyllys fullpath = get_fullpath(dirpath, filename); 129999ebb4caSwyllys if (fullpath == NULL) 130099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 130199ebb4caSwyllys 130230a5e8faSwyllys /* Get optional search criteria attributes */ 130330a5e8faSwyllys issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr); 130430a5e8faSwyllys subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr); 130530a5e8faSwyllys serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr); 130630a5e8faSwyllys rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr, 130730a5e8faSwyllys &validity, NULL); 130830a5e8faSwyllys if (rv != KMF_OK) { 130930a5e8faSwyllys validity = KMF_ALL_CERTS; 131030a5e8faSwyllys rv = KMF_OK; 131130a5e8faSwyllys } 131230a5e8faSwyllys 131399ebb4caSwyllys if (isdir(fullpath)) { 131499ebb4caSwyllys DIR *dirp; 131599ebb4caSwyllys struct dirent *dp; 131699ebb4caSwyllys 131799ebb4caSwyllys /* open all files in the directory and attempt to read them */ 131899ebb4caSwyllys if ((dirp = opendir(fullpath)) == NULL) { 131999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 132099ebb4caSwyllys } 132199ebb4caSwyllys 132299ebb4caSwyllys while ((dp = readdir(dirp)) != NULL) { 132399ebb4caSwyllys if (strcmp(dp->d_name, ".") != 0 && 132499ebb4caSwyllys strcmp(dp->d_name, "..") != 0) { 132599ebb4caSwyllys char *fname; 132699ebb4caSwyllys 132799ebb4caSwyllys fname = get_fullpath(fullpath, 132899ebb4caSwyllys (char *)&dp->d_name); 132999ebb4caSwyllys 133099ebb4caSwyllys if (fname == NULL) { 133199ebb4caSwyllys rv = KMF_ERR_MEMORY; 133299ebb4caSwyllys break; 133399ebb4caSwyllys } 133499ebb4caSwyllys 133530a5e8faSwyllys rv = kmf_load_cert(kmfh, issuer, subject, 133630a5e8faSwyllys serial, validity, fname, &certdata); 133799ebb4caSwyllys 133899ebb4caSwyllys if (rv == KMF_ERR_CERT_NOT_FOUND) { 133999ebb4caSwyllys free(fname); 1340e65e5c2dSWyllys Ingersoll kmf_free_data(&certdata); 134199ebb4caSwyllys rv = KMF_OK; 134299ebb4caSwyllys continue; 134399ebb4caSwyllys } else if (rv != KMF_OK) { 134499ebb4caSwyllys free(fname); 134599ebb4caSwyllys break; 134699ebb4caSwyllys } 134799ebb4caSwyllys 134899ebb4caSwyllys if (unlink(fname) != 0) { 134999ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 135099ebb4caSwyllys rv = KMF_ERR_INTERNAL; 135199ebb4caSwyllys free(fname); 135299ebb4caSwyllys break; 135399ebb4caSwyllys } 135499ebb4caSwyllys free(fname); 1355e65e5c2dSWyllys Ingersoll kmf_free_data(&certdata); 135699ebb4caSwyllys } 135799ebb4caSwyllys } 135899ebb4caSwyllys (void) closedir(dirp); 135999ebb4caSwyllys } else { 136099ebb4caSwyllys /* Just try to load a single certificate */ 136130a5e8faSwyllys rv = kmf_load_cert(kmfh, issuer, subject, serial, validity, 136230a5e8faSwyllys fullpath, &certdata); 136399ebb4caSwyllys if (rv == KMF_OK) { 136499ebb4caSwyllys if (unlink(fullpath) != 0) { 136599ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 136699ebb4caSwyllys rv = KMF_ERR_INTERNAL; 136799ebb4caSwyllys } 136899ebb4caSwyllys } 136999ebb4caSwyllys } 137099ebb4caSwyllys 137199ebb4caSwyllys out: 137299ebb4caSwyllys if (fullpath != NULL) 137399ebb4caSwyllys free(fullpath); 137499ebb4caSwyllys 1375e65e5c2dSWyllys Ingersoll kmf_free_data(&certdata); 137699ebb4caSwyllys 137799ebb4caSwyllys return (rv); 137899ebb4caSwyllys } 137999ebb4caSwyllys 138099ebb4caSwyllys KMF_RETURN 138199ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, 138299ebb4caSwyllys KMF_DATA *keydata) 138399ebb4caSwyllys { 138499ebb4caSwyllys KMF_RETURN rv = KMF_OK; 138599ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 138699ebb4caSwyllys int n; 138799ebb4caSwyllys 138899ebb4caSwyllys if (key == NULL || keydata == NULL || 138999ebb4caSwyllys key->keyp == NULL) 139099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 139199ebb4caSwyllys 139299ebb4caSwyllys if (key->keyalg == KMF_RSA) { 139399ebb4caSwyllys RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp); 139499ebb4caSwyllys 139599ebb4caSwyllys if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) { 139699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 139799ebb4caSwyllys return (KMF_ERR_ENCODING); 139899ebb4caSwyllys } 139999ebb4caSwyllys RSA_free(pubkey); 140099ebb4caSwyllys } else if (key->keyalg == KMF_DSA) { 140199ebb4caSwyllys DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp); 140299ebb4caSwyllys 140399ebb4caSwyllys if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) { 140499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 140599ebb4caSwyllys return (KMF_ERR_ENCODING); 140699ebb4caSwyllys } 140799ebb4caSwyllys DSA_free(pubkey); 140899ebb4caSwyllys } else { 140999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 141099ebb4caSwyllys } 141199ebb4caSwyllys keydata->Length = n; 141299ebb4caSwyllys 141399ebb4caSwyllys cleanup: 141499ebb4caSwyllys if (rv != KMF_OK) { 141599ebb4caSwyllys if (keydata->Data) 141699ebb4caSwyllys free(keydata->Data); 141799ebb4caSwyllys keydata->Data = NULL; 141899ebb4caSwyllys keydata->Length = 0; 141999ebb4caSwyllys } 142099ebb4caSwyllys 142199ebb4caSwyllys return (rv); 142299ebb4caSwyllys } 142399ebb4caSwyllys 142499ebb4caSwyllys static KMF_RETURN 142530a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out, 142630a5e8faSwyllys KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private) 142799ebb4caSwyllys { 142899ebb4caSwyllys int rv = 0; 142999ebb4caSwyllys RSA *rsa; 143099ebb4caSwyllys DSA *dsa; 143199ebb4caSwyllys 14325b3e1433Swyllys if (pkey == NULL || out == NULL) 14335b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 14345b3e1433Swyllys 143599ebb4caSwyllys switch (format) { 143673cc0e02Swyllys case KMF_FORMAT_RAWKEY: 143773cc0e02Swyllys /* same as ASN.1 */ 143899ebb4caSwyllys case KMF_FORMAT_ASN1: 1439*300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) { 144030a5e8faSwyllys if (private) 144199ebb4caSwyllys rv = i2d_RSAPrivateKey_bio(out, rsa); 144230a5e8faSwyllys else 144330a5e8faSwyllys rv = i2d_RSAPublicKey_bio(out, rsa); 1444*300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) { 144599ebb4caSwyllys rv = i2d_DSAPrivateKey_bio(out, dsa); 144699ebb4caSwyllys } 144799ebb4caSwyllys if (rv == 1) { 144899ebb4caSwyllys rv = KMF_OK; 144999ebb4caSwyllys } else { 145099ebb4caSwyllys SET_ERROR(kmfh, rv); 145199ebb4caSwyllys } 145299ebb4caSwyllys break; 145399ebb4caSwyllys case KMF_FORMAT_PEM: 1454*300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) { 145530a5e8faSwyllys if (private) 145699ebb4caSwyllys rv = PEM_write_bio_RSAPrivateKey(out, 145730a5e8faSwyllys rsa, NULL, NULL, 0, NULL, 145830a5e8faSwyllys (cred != NULL ? cred->cred : NULL)); 145930a5e8faSwyllys else 146030a5e8faSwyllys rv = PEM_write_bio_RSAPublicKey(out, 146130a5e8faSwyllys rsa); 1462*300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) { 146399ebb4caSwyllys rv = PEM_write_bio_DSAPrivateKey(out, 146430a5e8faSwyllys dsa, NULL, NULL, 0, NULL, 146530a5e8faSwyllys (cred != NULL ? cred->cred : NULL)); 146699ebb4caSwyllys } 146799ebb4caSwyllys 146899ebb4caSwyllys if (rv == 1) { 146999ebb4caSwyllys rv = KMF_OK; 147099ebb4caSwyllys } else { 147199ebb4caSwyllys SET_ERROR(kmfh, rv); 147299ebb4caSwyllys } 147399ebb4caSwyllys break; 147499ebb4caSwyllys 147599ebb4caSwyllys default: 147699ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 147799ebb4caSwyllys } 147899ebb4caSwyllys 147999ebb4caSwyllys return (rv); 148099ebb4caSwyllys } 148199ebb4caSwyllys 148299ebb4caSwyllys KMF_RETURN 148330a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr, 148430a5e8faSwyllys KMF_ATTRIBUTE *attrlist) 148599ebb4caSwyllys { 148699ebb4caSwyllys KMF_RETURN rv = KMF_OK; 148799ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 1488*300fdee2SAndy Fiddaman uint32_t eValue = RSA_F4; 1489*300fdee2SAndy Fiddaman BIGNUM *eValue_bn = NULL; 149099ebb4caSwyllys RSA *sslPrivKey = NULL; 149199ebb4caSwyllys DSA *sslDSAKey = NULL; 149299ebb4caSwyllys EVP_PKEY *eprikey = NULL; 149399ebb4caSwyllys EVP_PKEY *epubkey = NULL; 149499ebb4caSwyllys BIO *out = NULL; 149530a5e8faSwyllys KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL; 149630a5e8faSwyllys uint32_t keylen = 1024; 149730a5e8faSwyllys uint32_t keylen_size = sizeof (uint32_t); 149830a5e8faSwyllys boolean_t storekey = TRUE; 149930a5e8faSwyllys KMF_KEY_ALG keytype = KMF_RSA; 150099ebb4caSwyllys 1501*300fdee2SAndy Fiddaman eValue_bn = BN_new(); 1502*300fdee2SAndy Fiddaman if (eValue_bn == NULL) 1503*300fdee2SAndy Fiddaman return (KMF_ERR_MEMORY); 1504*300fdee2SAndy Fiddaman if (BN_set_word(eValue_bn, eValue) == 0) { 1505*300fdee2SAndy Fiddaman rv = KMF_ERR_KEYGEN_FAILED; 1506*300fdee2SAndy Fiddaman goto cleanup; 1507*300fdee2SAndy Fiddaman } 1508*300fdee2SAndy Fiddaman 150930a5e8faSwyllys rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr, 151030a5e8faSwyllys &storekey, NULL); 151130a5e8faSwyllys if (rv != KMF_OK) { 151230a5e8faSwyllys /* "storekey" is optional. Default is TRUE */ 151330a5e8faSwyllys rv = KMF_OK; 151499ebb4caSwyllys } 151599ebb4caSwyllys 151630a5e8faSwyllys rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, 151730a5e8faSwyllys (void *)&keytype, NULL); 151830a5e8faSwyllys if (rv != KMF_OK) 151930a5e8faSwyllys /* keytype is optional. KMF_RSA is default */ 152030a5e8faSwyllys rv = KMF_OK; 152199ebb4caSwyllys 152230a5e8faSwyllys pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr); 1523*300fdee2SAndy Fiddaman if (pubkey == NULL) { 1524*300fdee2SAndy Fiddaman rv = KMF_ERR_BAD_PARAMETER; 1525*300fdee2SAndy Fiddaman goto cleanup; 1526*300fdee2SAndy Fiddaman } 152799ebb4caSwyllys 152830a5e8faSwyllys privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr); 1529*300fdee2SAndy Fiddaman if (privkey == NULL) { 1530*300fdee2SAndy Fiddaman rv = KMF_ERR_BAD_PARAMETER; 1531*300fdee2SAndy Fiddaman goto cleanup; 1532*300fdee2SAndy Fiddaman } 153330a5e8faSwyllys 153430a5e8faSwyllys (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE)); 153530a5e8faSwyllys (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE)); 153699ebb4caSwyllys 153799ebb4caSwyllys eprikey = EVP_PKEY_new(); 153899ebb4caSwyllys if (eprikey == NULL) { 153999ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 154099ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 154199ebb4caSwyllys goto cleanup; 154299ebb4caSwyllys } 154399ebb4caSwyllys epubkey = EVP_PKEY_new(); 154499ebb4caSwyllys if (epubkey == NULL) { 154599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 154699ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 154799ebb4caSwyllys goto cleanup; 154899ebb4caSwyllys } 154930a5e8faSwyllys if (keytype == KMF_RSA) { 155030a5e8faSwyllys KMF_BIGINT *rsaexp = NULL; 155199ebb4caSwyllys 155230a5e8faSwyllys rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr); 155330a5e8faSwyllys if (rsaexp != NULL) { 155430a5e8faSwyllys if (rsaexp->len > 0 && 155530a5e8faSwyllys rsaexp->len <= sizeof (eValue) && 155630a5e8faSwyllys rsaexp->val != NULL) { 1557a2d4930dSDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */ 155830a5e8faSwyllys eValue = *(uint32_t *)rsaexp->val; 1559*300fdee2SAndy Fiddaman if (BN_set_word(eValue_bn, eValue) == 0) { 1560*300fdee2SAndy Fiddaman rv = KMF_ERR_BAD_PARAMETER; 1561*300fdee2SAndy Fiddaman goto cleanup; 1562*300fdee2SAndy Fiddaman } 156330a5e8faSwyllys } else { 156430a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 156530a5e8faSwyllys goto cleanup; 156630a5e8faSwyllys } 156730a5e8faSwyllys } else { 156830a5e8faSwyllys /* RSA Exponent is optional. Default is 0x10001 */ 156930a5e8faSwyllys rv = KMF_OK; 157030a5e8faSwyllys } 157130a5e8faSwyllys 157230a5e8faSwyllys rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, 157330a5e8faSwyllys &keylen, &keylen_size); 157430a5e8faSwyllys if (rv == KMF_ERR_ATTR_NOT_FOUND) 157530a5e8faSwyllys /* keylen is optional, default is 1024 */ 157630a5e8faSwyllys rv = KMF_OK; 157730a5e8faSwyllys if (rv != KMF_OK) { 157830a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 157930a5e8faSwyllys goto cleanup; 158030a5e8faSwyllys } 158130a5e8faSwyllys 1582*300fdee2SAndy Fiddaman sslPrivKey = RSA_new(); 1583*300fdee2SAndy Fiddaman if (sslPrivKey == NULL || 1584*300fdee2SAndy Fiddaman RSA_generate_key_ex(sslPrivKey, keylen, eValue_bn, NULL) 1585*300fdee2SAndy Fiddaman == 0) { 158699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 158799ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 158899ebb4caSwyllys } else { 158930a5e8faSwyllys (void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey); 159099ebb4caSwyllys privkey->kstype = KMF_KEYSTORE_OPENSSL; 159199ebb4caSwyllys privkey->keyalg = KMF_RSA; 159299ebb4caSwyllys privkey->keyclass = KMF_ASYM_PRI; 159399ebb4caSwyllys privkey->israw = FALSE; 159499ebb4caSwyllys privkey->keyp = (void *)eprikey; 159530a5e8faSwyllys 159699ebb4caSwyllys /* OpenSSL derives the public key from the private */ 159730a5e8faSwyllys (void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey); 159899ebb4caSwyllys pubkey->kstype = KMF_KEYSTORE_OPENSSL; 159999ebb4caSwyllys pubkey->keyalg = KMF_RSA; 160099ebb4caSwyllys pubkey->israw = FALSE; 160199ebb4caSwyllys pubkey->keyclass = KMF_ASYM_PUB; 160299ebb4caSwyllys pubkey->keyp = (void *)epubkey; 160399ebb4caSwyllys } 160430a5e8faSwyllys } else if (keytype == KMF_DSA) { 1605*300fdee2SAndy Fiddaman BIGNUM *p, *q, *g; 1606*300fdee2SAndy Fiddaman 160799ebb4caSwyllys sslDSAKey = DSA_new(); 160899ebb4caSwyllys if (sslDSAKey == NULL) { 160999ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 161099ebb4caSwyllys return (KMF_ERR_MEMORY); 161199ebb4caSwyllys } 161299ebb4caSwyllys 1613*300fdee2SAndy Fiddaman p = BN_bin2bn(P, sizeof (P), NULL); 1614*300fdee2SAndy Fiddaman q = BN_bin2bn(Q, sizeof (Q), NULL); 1615*300fdee2SAndy Fiddaman g = BN_bin2bn(G, sizeof (G), NULL); 1616*300fdee2SAndy Fiddaman if (p == NULL || q == NULL || g == NULL) { 1617*300fdee2SAndy Fiddaman BN_free(p); 1618*300fdee2SAndy Fiddaman BN_free(q); 1619*300fdee2SAndy Fiddaman BN_free(g); 162099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 162199ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 162299ebb4caSwyllys goto cleanup; 162399ebb4caSwyllys } 1624*300fdee2SAndy Fiddaman 1625*300fdee2SAndy Fiddaman if (DSA_set0_pqg(sslDSAKey, p, q, g) == 0) { 162699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 162799ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 162899ebb4caSwyllys goto cleanup; 162999ebb4caSwyllys } 163099ebb4caSwyllys 163199ebb4caSwyllys if (!DSA_generate_key(sslDSAKey)) { 163299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 163399ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 163499ebb4caSwyllys goto cleanup; 163599ebb4caSwyllys } 163699ebb4caSwyllys 163799ebb4caSwyllys privkey->kstype = KMF_KEYSTORE_OPENSSL; 163899ebb4caSwyllys privkey->keyalg = KMF_DSA; 163999ebb4caSwyllys privkey->keyclass = KMF_ASYM_PRI; 164099ebb4caSwyllys privkey->israw = FALSE; 164199ebb4caSwyllys if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) { 164299ebb4caSwyllys privkey->keyp = (void *)eprikey; 164399ebb4caSwyllys } else { 164499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 164599ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 164699ebb4caSwyllys goto cleanup; 164799ebb4caSwyllys } 164899ebb4caSwyllys 164999ebb4caSwyllys pubkey->kstype = KMF_KEYSTORE_OPENSSL; 165099ebb4caSwyllys pubkey->keyalg = KMF_DSA; 165199ebb4caSwyllys pubkey->keyclass = KMF_ASYM_PUB; 165299ebb4caSwyllys pubkey->israw = FALSE; 165399ebb4caSwyllys 165499ebb4caSwyllys if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) { 165599ebb4caSwyllys pubkey->keyp = (void *)epubkey; 165699ebb4caSwyllys } else { 165799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 165899ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 165999ebb4caSwyllys goto cleanup; 166099ebb4caSwyllys } 166199ebb4caSwyllys } 166299ebb4caSwyllys 166399ebb4caSwyllys if (rv != KMF_OK) { 166499ebb4caSwyllys goto cleanup; 166599ebb4caSwyllys } 166699ebb4caSwyllys 166730a5e8faSwyllys if (storekey) { 166830a5e8faSwyllys KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */ 166930a5e8faSwyllys int i = 0; 167030a5e8faSwyllys char *keyfile = NULL, *dirpath = NULL; 167130a5e8faSwyllys KMF_ENCODE_FORMAT format; 167230a5e8faSwyllys /* 167330a5e8faSwyllys * Construct a new attribute arrray and call openssl_store_key 167430a5e8faSwyllys */ 167530a5e8faSwyllys kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR, 167630a5e8faSwyllys privkey, sizeof (privkey)); 167730a5e8faSwyllys i++; 167830a5e8faSwyllys 167930a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 168030a5e8faSwyllys if (dirpath != NULL) { 168130a5e8faSwyllys storeattrs[i].type = KMF_DIRPATH_ATTR; 168230a5e8faSwyllys storeattrs[i].pValue = dirpath; 168330a5e8faSwyllys storeattrs[i].valueLen = strlen(dirpath); 168430a5e8faSwyllys i++; 168530a5e8faSwyllys } else { 168630a5e8faSwyllys rv = KMF_OK; /* DIRPATH is optional */ 168799ebb4caSwyllys } 168830a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, 168930a5e8faSwyllys attrlist, numattr); 169030a5e8faSwyllys if (keyfile != NULL) { 169130a5e8faSwyllys storeattrs[i].type = KMF_KEY_FILENAME_ATTR; 169230a5e8faSwyllys storeattrs[i].pValue = keyfile; 169330a5e8faSwyllys storeattrs[i].valueLen = strlen(keyfile); 169430a5e8faSwyllys i++; 169530a5e8faSwyllys } else { 169630a5e8faSwyllys goto cleanup; /* KEYFILE is required */ 169730a5e8faSwyllys } 169830a5e8faSwyllys rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 169930a5e8faSwyllys (void *)&format, NULL); 170030a5e8faSwyllys if (rv == KMF_OK) { 170130a5e8faSwyllys storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR; 170230a5e8faSwyllys storeattrs[i].pValue = &format; 170330a5e8faSwyllys storeattrs[i].valueLen = sizeof (format); 170430a5e8faSwyllys i++; 170530a5e8faSwyllys } 170630a5e8faSwyllys 170730a5e8faSwyllys rv = OpenSSL_StoreKey(handle, i, storeattrs); 170830a5e8faSwyllys } 170999ebb4caSwyllys 171099ebb4caSwyllys cleanup: 1711*300fdee2SAndy Fiddaman if (eValue_bn != NULL) 1712*300fdee2SAndy Fiddaman BN_free(eValue_bn); 1713*300fdee2SAndy Fiddaman 171499ebb4caSwyllys if (rv != KMF_OK) { 171599ebb4caSwyllys if (eprikey != NULL) 171699ebb4caSwyllys EVP_PKEY_free(eprikey); 171799ebb4caSwyllys 171899ebb4caSwyllys if (epubkey != NULL) 171999ebb4caSwyllys EVP_PKEY_free(epubkey); 172099ebb4caSwyllys 172199ebb4caSwyllys if (pubkey->keylabel) { 172299ebb4caSwyllys free(pubkey->keylabel); 172399ebb4caSwyllys pubkey->keylabel = NULL; 172499ebb4caSwyllys } 172599ebb4caSwyllys 172699ebb4caSwyllys if (privkey->keylabel) { 172799ebb4caSwyllys free(privkey->keylabel); 172899ebb4caSwyllys privkey->keylabel = NULL; 172999ebb4caSwyllys } 173099ebb4caSwyllys 173199ebb4caSwyllys pubkey->keyp = NULL; 173299ebb4caSwyllys privkey->keyp = NULL; 173399ebb4caSwyllys } 173499ebb4caSwyllys 173599ebb4caSwyllys if (sslPrivKey) 173699ebb4caSwyllys RSA_free(sslPrivKey); 173799ebb4caSwyllys 173899ebb4caSwyllys if (sslDSAKey) 173999ebb4caSwyllys DSA_free(sslDSAKey); 174099ebb4caSwyllys 174199ebb4caSwyllys if (out != NULL) 174299ebb4caSwyllys (void) BIO_free(out); 174399ebb4caSwyllys 174499ebb4caSwyllys return (rv); 174599ebb4caSwyllys } 174699ebb4caSwyllys 1747e65e5c2dSWyllys Ingersoll /* 1748e65e5c2dSWyllys Ingersoll * Make sure the BN conversion is properly padded with 0x00 1749e65e5c2dSWyllys Ingersoll * bytes. If not, signature verification for DSA signatures 1750e65e5c2dSWyllys Ingersoll * may fail in the case where the bignum value does not use 1751e65e5c2dSWyllys Ingersoll * all of the bits. 1752e65e5c2dSWyllys Ingersoll */ 1753e65e5c2dSWyllys Ingersoll static int 1754*300fdee2SAndy Fiddaman fixbnlen(const BIGNUM *bn, unsigned char *buf, int len) { 1755e65e5c2dSWyllys Ingersoll int bytes = len - BN_num_bytes(bn); 17562c9a247fSWyllys Ingersoll 17572c9a247fSWyllys Ingersoll /* prepend with leading 0x00 if necessary */ 1758e65e5c2dSWyllys Ingersoll while (bytes-- > 0) 1759e65e5c2dSWyllys Ingersoll *buf++ = 0; 1760e65e5c2dSWyllys Ingersoll 17612c9a247fSWyllys Ingersoll (void) BN_bn2bin(bn, buf); 17622c9a247fSWyllys Ingersoll /* 17632c9a247fSWyllys Ingersoll * Return the desired length since we prepended it 17642c9a247fSWyllys Ingersoll * with the necessary 0x00 padding. 17652c9a247fSWyllys Ingersoll */ 17662c9a247fSWyllys Ingersoll return (len); 1767e65e5c2dSWyllys Ingersoll } 1768e65e5c2dSWyllys Ingersoll 176999ebb4caSwyllys KMF_RETURN 177099ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, 177199ebb4caSwyllys KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output) 177299ebb4caSwyllys { 177399ebb4caSwyllys KMF_RETURN ret = KMF_OK; 177499ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 177599ebb4caSwyllys KMF_ALGORITHM_INDEX AlgId; 1776*300fdee2SAndy Fiddaman EVP_MD_CTX *ctx; 177799ebb4caSwyllys const EVP_MD *md; 177802744e81Swyllys 177999ebb4caSwyllys if (key == NULL || AlgOID == NULL || 178099ebb4caSwyllys tobesigned == NULL || output == NULL || 178199ebb4caSwyllys tobesigned->Data == NULL || 178299ebb4caSwyllys output->Data == NULL) 178399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 178499ebb4caSwyllys 178599ebb4caSwyllys /* Map the OID to an OpenSSL algorithm */ 178630a5e8faSwyllys AlgId = x509_algoid_to_algid(AlgOID); 178799ebb4caSwyllys if (AlgId == KMF_ALGID_NONE) 1788e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM); 178999ebb4caSwyllys 179099ebb4caSwyllys if (key->keyalg == KMF_RSA) { 179199ebb4caSwyllys EVP_PKEY *pkey = (EVP_PKEY *)key->keyp; 179299ebb4caSwyllys uchar_t *p; 179302744e81Swyllys int len; 179499ebb4caSwyllys if (AlgId == KMF_ALGID_MD5WithRSA) 179599ebb4caSwyllys md = EVP_md5(); 179699ebb4caSwyllys else if (AlgId == KMF_ALGID_SHA1WithRSA) 179799ebb4caSwyllys md = EVP_sha1(); 1798e65e5c2dSWyllys Ingersoll else if (AlgId == KMF_ALGID_SHA256WithRSA) 1799e65e5c2dSWyllys Ingersoll md = EVP_sha256(); 1800e65e5c2dSWyllys Ingersoll else if (AlgId == KMF_ALGID_SHA384WithRSA) 1801e65e5c2dSWyllys Ingersoll md = EVP_sha384(); 1802e65e5c2dSWyllys Ingersoll else if (AlgId == KMF_ALGID_SHA512WithRSA) 1803e65e5c2dSWyllys Ingersoll md = EVP_sha512(); 180402744e81Swyllys else if (AlgId == KMF_ALGID_RSA) 180502744e81Swyllys md = NULL; 180699ebb4caSwyllys else 1807e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM); 180899ebb4caSwyllys 180902744e81Swyllys if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) { 181002744e81Swyllys RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey); 181199ebb4caSwyllys 181202744e81Swyllys p = output->Data; 181302744e81Swyllys if ((len = RSA_private_encrypt(tobesigned->Length, 181402744e81Swyllys tobesigned->Data, p, rsa, 181502744e81Swyllys RSA_PKCS1_PADDING)) <= 0) { 181602744e81Swyllys SET_ERROR(kmfh, ERR_get_error()); 181702744e81Swyllys ret = KMF_ERR_INTERNAL; 181802744e81Swyllys } 181902744e81Swyllys output->Length = len; 182002744e81Swyllys } else { 1821*300fdee2SAndy Fiddaman if ((ctx = EVP_MD_CTX_new()) == NULL) 1822*300fdee2SAndy Fiddaman return (KMF_ERR_MEMORY); 1823*300fdee2SAndy Fiddaman (void) EVP_SignInit_ex(ctx, md, NULL); 1824*300fdee2SAndy Fiddaman (void) EVP_SignUpdate(ctx, tobesigned->Data, 182599ebb4caSwyllys (uint32_t)tobesigned->Length); 182699ebb4caSwyllys len = (uint32_t)output->Length; 182799ebb4caSwyllys p = output->Data; 1828*300fdee2SAndy Fiddaman if (!EVP_SignFinal(ctx, p, (uint32_t *)&len, pkey)) { 182999ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 183002744e81Swyllys len = 0; 183102744e81Swyllys ret = KMF_ERR_INTERNAL; 183299ebb4caSwyllys } 183399ebb4caSwyllys output->Length = len; 1834*300fdee2SAndy Fiddaman EVP_MD_CTX_free(ctx); 183502744e81Swyllys } 183699ebb4caSwyllys } else if (key->keyalg == KMF_DSA) { 183799ebb4caSwyllys DSA *dsa = EVP_PKEY_get1_DSA(key->keyp); 183899ebb4caSwyllys 183999ebb4caSwyllys uchar_t hash[EVP_MAX_MD_SIZE]; 184099ebb4caSwyllys uint32_t hashlen; 184199ebb4caSwyllys DSA_SIG *dsasig; 184299ebb4caSwyllys 1843e65e5c2dSWyllys Ingersoll if (AlgId == KMF_ALGID_DSA || 1844e65e5c2dSWyllys Ingersoll AlgId == KMF_ALGID_SHA1WithDSA) 1845e65e5c2dSWyllys Ingersoll md = EVP_sha1(); 1846e65e5c2dSWyllys Ingersoll else if (AlgId == KMF_ALGID_SHA256WithDSA) 1847e65e5c2dSWyllys Ingersoll md = EVP_sha256(); 1848e65e5c2dSWyllys Ingersoll else /* Bad algorithm */ 1849e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM); 1850e65e5c2dSWyllys Ingersoll 185199ebb4caSwyllys /* 185299ebb4caSwyllys * OpenSSL EVP_Sign operation automatically converts to 185399ebb4caSwyllys * ASN.1 output so we do the operations separately so we 185499ebb4caSwyllys * are assured of NOT getting ASN.1 output returned. 185599ebb4caSwyllys * KMF does not want ASN.1 encoded results because 185699ebb4caSwyllys * not all mechanisms return ASN.1 encodings (PKCS#11 185799ebb4caSwyllys * and NSS return raw signature data). 185899ebb4caSwyllys */ 1859*300fdee2SAndy Fiddaman if ((ctx = EVP_MD_CTX_new()) == NULL) 1860*300fdee2SAndy Fiddaman return (KMF_ERR_MEMORY); 1861*300fdee2SAndy Fiddaman (void) EVP_DigestInit_ex(ctx, md, NULL); 1862*300fdee2SAndy Fiddaman (void) EVP_DigestUpdate(ctx, tobesigned->Data, 186399ebb4caSwyllys tobesigned->Length); 1864*300fdee2SAndy Fiddaman (void) EVP_DigestFinal_ex(ctx, hash, &hashlen); 186599ebb4caSwyllys 1866e65e5c2dSWyllys Ingersoll /* Only sign first 20 bytes for SHA2 */ 1867e65e5c2dSWyllys Ingersoll if (AlgId == KMF_ALGID_SHA256WithDSA) 1868e65e5c2dSWyllys Ingersoll hashlen = 20; 186999ebb4caSwyllys dsasig = DSA_do_sign(hash, hashlen, dsa); 187099ebb4caSwyllys if (dsasig != NULL) { 187199ebb4caSwyllys int i; 1872*300fdee2SAndy Fiddaman const BIGNUM *r, *s; 1873*300fdee2SAndy Fiddaman 1874*300fdee2SAndy Fiddaman DSA_SIG_get0(dsasig, &r, &s); 1875*300fdee2SAndy Fiddaman output->Length = i = fixbnlen(r, output->Data, 1876e65e5c2dSWyllys Ingersoll hashlen); 18772c9a247fSWyllys Ingersoll 1878*300fdee2SAndy Fiddaman output->Length += fixbnlen(s, &output->Data[i], 1879e65e5c2dSWyllys Ingersoll hashlen); 18802c9a247fSWyllys Ingersoll 188199ebb4caSwyllys DSA_SIG_free(dsasig); 188299ebb4caSwyllys } else { 188399ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 188499ebb4caSwyllys } 1885*300fdee2SAndy Fiddaman EVP_MD_CTX_free(ctx); 188699ebb4caSwyllys } else { 188799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 188899ebb4caSwyllys } 188999ebb4caSwyllys cleanup: 189099ebb4caSwyllys return (ret); 189199ebb4caSwyllys } 189299ebb4caSwyllys 189399ebb4caSwyllys KMF_RETURN 189499ebb4caSwyllys /*ARGSUSED*/ 189530a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle, 189630a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 189799ebb4caSwyllys { 189899ebb4caSwyllys KMF_RETURN rv = KMF_OK; 189930a5e8faSwyllys KMF_KEY_HANDLE *key; 190030a5e8faSwyllys boolean_t destroy = B_TRUE; 190130a5e8faSwyllys 190230a5e8faSwyllys key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 190399ebb4caSwyllys if (key == NULL || key->keyp == NULL) 190499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 190599ebb4caSwyllys 190630a5e8faSwyllys rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr, 190730a5e8faSwyllys (void *)&destroy, NULL); 190830a5e8faSwyllys if (rv != KMF_OK) { 190930a5e8faSwyllys /* "destroy" is optional. Default is TRUE */ 191030a5e8faSwyllys rv = KMF_OK; 191130a5e8faSwyllys } 191230a5e8faSwyllys 191399ebb4caSwyllys if (key->keyclass != KMF_ASYM_PUB && 191499ebb4caSwyllys key->keyclass != KMF_ASYM_PRI && 191599ebb4caSwyllys key->keyclass != KMF_SYMMETRIC) 191699ebb4caSwyllys return (KMF_ERR_BAD_KEY_CLASS); 191799ebb4caSwyllys 191899ebb4caSwyllys if (key->keyclass == KMF_SYMMETRIC) { 191930a5e8faSwyllys kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp); 192099ebb4caSwyllys key->keyp = NULL; 192199ebb4caSwyllys } else { 192299ebb4caSwyllys if (key->keyp != NULL) { 192399ebb4caSwyllys EVP_PKEY_free(key->keyp); 192499ebb4caSwyllys key->keyp = NULL; 192599ebb4caSwyllys } 192699ebb4caSwyllys } 192799ebb4caSwyllys 192899ebb4caSwyllys if (key->keylabel != NULL) { 192999ebb4caSwyllys EVP_PKEY *pkey = NULL; 193099ebb4caSwyllys /* If the file exists, make sure it is a proper key. */ 193199ebb4caSwyllys pkey = openssl_load_key(handle, key->keylabel); 193299ebb4caSwyllys if (pkey == NULL) { 19335b3e1433Swyllys if (key->keylabel != NULL) { 193499ebb4caSwyllys free(key->keylabel); 193599ebb4caSwyllys key->keylabel = NULL; 19365b3e1433Swyllys } 193799ebb4caSwyllys return (KMF_ERR_KEY_NOT_FOUND); 193899ebb4caSwyllys } 193999ebb4caSwyllys EVP_PKEY_free(pkey); 194099ebb4caSwyllys 194199ebb4caSwyllys if (destroy) { 194299ebb4caSwyllys if (unlink(key->keylabel) != 0) { 194399ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 194499ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 194599ebb4caSwyllys rv = KMF_ERR_INTERNAL; 194699ebb4caSwyllys } 194799ebb4caSwyllys } 194899ebb4caSwyllys if (key->keylabel != NULL) { 194999ebb4caSwyllys free(key->keylabel); 195099ebb4caSwyllys key->keylabel = NULL; 195199ebb4caSwyllys } 195299ebb4caSwyllys } 195399ebb4caSwyllys return (rv); 195499ebb4caSwyllys } 195599ebb4caSwyllys 195699ebb4caSwyllys KMF_RETURN 195799ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr) 195899ebb4caSwyllys { 195999ebb4caSwyllys KMF_RETURN ret = KMF_OK; 196099ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 196199ebb4caSwyllys char str[256]; /* OpenSSL needs at least 120 byte buffer */ 196299ebb4caSwyllys 196399ebb4caSwyllys ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str)); 196499ebb4caSwyllys if (strlen(str)) { 196599ebb4caSwyllys *msgstr = (char *)strdup(str); 196699ebb4caSwyllys if ((*msgstr) == NULL) 196799ebb4caSwyllys ret = KMF_ERR_MEMORY; 196899ebb4caSwyllys } else { 196999ebb4caSwyllys *msgstr = NULL; 197099ebb4caSwyllys } 197199ebb4caSwyllys 197299ebb4caSwyllys return (ret); 197399ebb4caSwyllys } 197499ebb4caSwyllys 197599ebb4caSwyllys static int 197699ebb4caSwyllys ext2NID(int kmfext) 197799ebb4caSwyllys { 197899ebb4caSwyllys switch (kmfext) { 197999ebb4caSwyllys case KMF_X509_EXT_KEY_USAGE: 198099ebb4caSwyllys return (NID_key_usage); 198199ebb4caSwyllys case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD: 198299ebb4caSwyllys return (NID_private_key_usage_period); 198399ebb4caSwyllys case KMF_X509_EXT_CERT_POLICIES: 198499ebb4caSwyllys return (NID_certificate_policies); 198599ebb4caSwyllys case KMF_X509_EXT_SUBJ_ALTNAME: 198699ebb4caSwyllys return (NID_subject_alt_name); 198799ebb4caSwyllys case KMF_X509_EXT_ISSUER_ALTNAME: 198899ebb4caSwyllys return (NID_issuer_alt_name); 198999ebb4caSwyllys case KMF_X509_EXT_BASIC_CONSTRAINTS: 199099ebb4caSwyllys return (NID_basic_constraints); 199199ebb4caSwyllys case KMF_X509_EXT_EXT_KEY_USAGE: 199299ebb4caSwyllys return (NID_ext_key_usage); 199399ebb4caSwyllys case KMF_X509_EXT_AUTH_KEY_ID: 199499ebb4caSwyllys return (NID_authority_key_identifier); 199599ebb4caSwyllys case KMF_X509_EXT_CRL_DIST_POINTS: 199699ebb4caSwyllys return (NID_crl_distribution_points); 199799ebb4caSwyllys case KMF_X509_EXT_SUBJ_KEY_ID: 199899ebb4caSwyllys return (NID_subject_key_identifier); 199999ebb4caSwyllys case KMF_X509_EXT_POLICY_MAPPINGS: 200099ebb4caSwyllys return (OBJ_sn2nid("policyMappings")); 200199ebb4caSwyllys case KMF_X509_EXT_NAME_CONSTRAINTS: 200299ebb4caSwyllys return (OBJ_sn2nid("nameConstraints")); 200399ebb4caSwyllys case KMF_X509_EXT_POLICY_CONSTRAINTS: 200499ebb4caSwyllys return (OBJ_sn2nid("policyConstraints")); 200599ebb4caSwyllys case KMF_X509_EXT_INHIBIT_ANY_POLICY: 200699ebb4caSwyllys return (OBJ_sn2nid("inhibitAnyPolicy")); 200799ebb4caSwyllys case KMF_X509_EXT_FRESHEST_CRL: 200899ebb4caSwyllys return (OBJ_sn2nid("freshestCRL")); 200999ebb4caSwyllys default: 201099ebb4caSwyllys return (NID_undef); 201199ebb4caSwyllys } 201299ebb4caSwyllys } 201399ebb4caSwyllys 201499ebb4caSwyllys KMF_RETURN 201599ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert, 201699ebb4caSwyllys KMF_PRINTABLE_ITEM flag, char *resultStr) 201799ebb4caSwyllys { 201899ebb4caSwyllys KMF_RETURN ret = KMF_OK; 201999ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 202099ebb4caSwyllys X509 *xcert = NULL; 202199ebb4caSwyllys unsigned char *outbuf = NULL; 202299ebb4caSwyllys unsigned char *outbuf_p; 202399ebb4caSwyllys int j; 202499ebb4caSwyllys int ext_index, nid, len; 202599ebb4caSwyllys BIO *mem = NULL; 202670f9559bSTheo Schlossnagle STACK_OF(OPENSSL_STRING) *emlst = NULL; 202799ebb4caSwyllys X509_EXTENSION *ex; 202899ebb4caSwyllys 202999ebb4caSwyllys if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) { 203099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 203199ebb4caSwyllys } 203299ebb4caSwyllys 203399ebb4caSwyllys /* copy cert data to outbuf */ 203499ebb4caSwyllys outbuf = malloc(pcert->Length); 203599ebb4caSwyllys if (outbuf == NULL) { 203699ebb4caSwyllys return (KMF_ERR_MEMORY); 203799ebb4caSwyllys } 203899ebb4caSwyllys (void) memcpy(outbuf, pcert->Data, pcert->Length); 203999ebb4caSwyllys 204099ebb4caSwyllys outbuf_p = outbuf; /* use a temp pointer; required by openssl */ 204199ebb4caSwyllys xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length); 204299ebb4caSwyllys if (xcert == NULL) { 204399ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 204499ebb4caSwyllys ret = KMF_ERR_ENCODING; 204599ebb4caSwyllys goto out; 204699ebb4caSwyllys } 204799ebb4caSwyllys 204899ebb4caSwyllys mem = BIO_new(BIO_s_mem()); 204999ebb4caSwyllys if (mem == NULL) { 205099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 205199ebb4caSwyllys ret = KMF_ERR_MEMORY; 205299ebb4caSwyllys goto out; 205399ebb4caSwyllys } 205499ebb4caSwyllys 205599ebb4caSwyllys switch (flag) { 205699ebb4caSwyllys case KMF_CERT_ISSUER: 205799ebb4caSwyllys (void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0, 205899ebb4caSwyllys XN_FLAG_SEP_CPLUS_SPC); 205999ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 206099ebb4caSwyllys break; 206199ebb4caSwyllys 206299ebb4caSwyllys case KMF_CERT_SUBJECT: 206399ebb4caSwyllys (void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0, 206499ebb4caSwyllys XN_FLAG_SEP_CPLUS_SPC); 206599ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 206699ebb4caSwyllys break; 206799ebb4caSwyllys 206899ebb4caSwyllys case KMF_CERT_VERSION: 2069*300fdee2SAndy Fiddaman (void) snprintf(resultStr, KMF_CERT_PRINTABLE_LEN, 2070*300fdee2SAndy Fiddaman "%ld", X509_get_version(xcert)); 207199ebb4caSwyllys len = strlen(resultStr); 207299ebb4caSwyllys break; 207399ebb4caSwyllys 207499ebb4caSwyllys case KMF_CERT_SERIALNUM: 207599ebb4caSwyllys if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) { 207699ebb4caSwyllys (void) strcpy(resultStr, "0x"); 207799ebb4caSwyllys len = BIO_gets(mem, &resultStr[2], 207899ebb4caSwyllys KMF_CERT_PRINTABLE_LEN - 2); 207999ebb4caSwyllys } 208099ebb4caSwyllys break; 208199ebb4caSwyllys 208299ebb4caSwyllys case KMF_CERT_NOTBEFORE: 2083*300fdee2SAndy Fiddaman (void) ASN1_TIME_print(mem, X509_getm_notBefore(xcert)); 208499ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 208599ebb4caSwyllys break; 208699ebb4caSwyllys 208799ebb4caSwyllys case KMF_CERT_NOTAFTER: 2088*300fdee2SAndy Fiddaman (void) ASN1_TIME_print(mem, X509_getm_notAfter(xcert)); 208999ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 209099ebb4caSwyllys break; 209199ebb4caSwyllys 209299ebb4caSwyllys case KMF_CERT_PUBKEY_DATA: 209399ebb4caSwyllys { 2094*300fdee2SAndy Fiddaman RSA *rsa; 2095*300fdee2SAndy Fiddaman DSA *dsa; 2096*300fdee2SAndy Fiddaman 209799ebb4caSwyllys EVP_PKEY *pkey = X509_get_pubkey(xcert); 209899ebb4caSwyllys if (pkey == NULL) { 209999ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 210099ebb4caSwyllys ret = KMF_ERR_ENCODING; 210199ebb4caSwyllys goto out; 210299ebb4caSwyllys } 210399ebb4caSwyllys 2104*300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) { 210599ebb4caSwyllys (void) BIO_printf(mem, 210699ebb4caSwyllys "RSA Public Key: (%d bit)\n", 2107*300fdee2SAndy Fiddaman RSA_bits(rsa)); 2108*300fdee2SAndy Fiddaman (void) RSA_print(mem, rsa, 0); 2109*300fdee2SAndy Fiddaman 2110*300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) { 211199ebb4caSwyllys (void) BIO_printf(mem, 211299ebb4caSwyllys "%12sDSA Public Key:\n", ""); 2113*300fdee2SAndy Fiddaman (void) DSA_print(mem, dsa, 0); 211499ebb4caSwyllys } else { 211599ebb4caSwyllys (void) BIO_printf(mem, 211699ebb4caSwyllys "%12sUnknown Public Key:\n", ""); 211799ebb4caSwyllys } 211899ebb4caSwyllys (void) BIO_printf(mem, "\n"); 211999ebb4caSwyllys EVP_PKEY_free(pkey); 212099ebb4caSwyllys } 212199ebb4caSwyllys len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 212299ebb4caSwyllys break; 212399ebb4caSwyllys case KMF_CERT_SIGNATURE_ALG: 212499ebb4caSwyllys case KMF_CERT_PUBKEY_ALG: 2125*300fdee2SAndy Fiddaman { 2126*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L 2127*300fdee2SAndy Fiddaman ASN1_OBJECT *alg = NULL; 2128*300fdee2SAndy Fiddaman #else 2129*300fdee2SAndy Fiddaman const ASN1_OBJECT *alg = NULL; 2130*300fdee2SAndy Fiddaman #endif 2131*300fdee2SAndy Fiddaman 213299ebb4caSwyllys if (flag == KMF_CERT_SIGNATURE_ALG) { 2133*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L 2134*300fdee2SAndy Fiddaman alg = xcert->sig_alg->algorithm; 2135*300fdee2SAndy Fiddaman #else 2136*300fdee2SAndy Fiddaman const X509_ALGOR *sig_alg = NULL; 2137*300fdee2SAndy Fiddaman 2138*300fdee2SAndy Fiddaman X509_get0_signature(NULL, &sig_alg, xcert); 2139*300fdee2SAndy Fiddaman if (sig_alg != NULL) 2140*300fdee2SAndy Fiddaman X509_ALGOR_get0(&alg, NULL, NULL, 2141*300fdee2SAndy Fiddaman sig_alg); 2142*300fdee2SAndy Fiddaman #endif 214399ebb4caSwyllys } else { 2144*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L 2145*300fdee2SAndy Fiddaman alg = xcert->cert_info->key->algor->algorithm; 2146*300fdee2SAndy Fiddaman #else 2147*300fdee2SAndy Fiddaman X509_PUBKEY *key = X509_get_X509_PUBKEY(xcert); 2148*300fdee2SAndy Fiddaman 2149*300fdee2SAndy Fiddaman if (key != NULL) 2150*300fdee2SAndy Fiddaman (void) X509_PUBKEY_get0_param( 2151*300fdee2SAndy Fiddaman (ASN1_OBJECT **)&alg, NULL, 0, 2152*300fdee2SAndy Fiddaman NULL, key); 2153*300fdee2SAndy Fiddaman #endif 215499ebb4caSwyllys } 215599ebb4caSwyllys 2156*300fdee2SAndy Fiddaman if (alg == NULL) 2157*300fdee2SAndy Fiddaman len = -1; 2158*300fdee2SAndy Fiddaman else if ((len = i2a_ASN1_OBJECT(mem, alg)) > 0) 215999ebb4caSwyllys len = BIO_read(mem, resultStr, 216099ebb4caSwyllys KMF_CERT_PRINTABLE_LEN); 216199ebb4caSwyllys } 216299ebb4caSwyllys break; 216399ebb4caSwyllys 216499ebb4caSwyllys case KMF_CERT_EMAIL: 216599ebb4caSwyllys emlst = X509_get1_email(xcert); 216670f9559bSTheo Schlossnagle for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) 216770f9559bSTheo Schlossnagle (void) BIO_printf(mem, "%s\n", 216870f9559bSTheo Schlossnagle sk_OPENSSL_STRING_value(emlst, j)); 216999ebb4caSwyllys 217099ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 217199ebb4caSwyllys X509_email_free(emlst); 217299ebb4caSwyllys break; 217399ebb4caSwyllys case KMF_X509_EXT_ISSUER_ALTNAME: 217499ebb4caSwyllys case KMF_X509_EXT_SUBJ_ALTNAME: 217599ebb4caSwyllys case KMF_X509_EXT_KEY_USAGE: 217699ebb4caSwyllys case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD: 217799ebb4caSwyllys case KMF_X509_EXT_CERT_POLICIES: 217899ebb4caSwyllys case KMF_X509_EXT_BASIC_CONSTRAINTS: 217999ebb4caSwyllys case KMF_X509_EXT_NAME_CONSTRAINTS: 218099ebb4caSwyllys case KMF_X509_EXT_POLICY_CONSTRAINTS: 218199ebb4caSwyllys case KMF_X509_EXT_EXT_KEY_USAGE: 218299ebb4caSwyllys case KMF_X509_EXT_INHIBIT_ANY_POLICY: 218399ebb4caSwyllys case KMF_X509_EXT_AUTH_KEY_ID: 218499ebb4caSwyllys case KMF_X509_EXT_SUBJ_KEY_ID: 218599ebb4caSwyllys case KMF_X509_EXT_POLICY_MAPPINGS: 218699ebb4caSwyllys case KMF_X509_EXT_CRL_DIST_POINTS: 218799ebb4caSwyllys case KMF_X509_EXT_FRESHEST_CRL: 218899ebb4caSwyllys nid = ext2NID(flag); 218999ebb4caSwyllys if (nid == NID_undef) { 219099ebb4caSwyllys ret = KMF_ERR_EXTENSION_NOT_FOUND; 219199ebb4caSwyllys goto out; 219299ebb4caSwyllys } 219399ebb4caSwyllys 2194*300fdee2SAndy Fiddaman ext_index = X509_get_ext_by_NID(xcert, nid, -1); 219599ebb4caSwyllys if (ext_index == -1) { 219699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 219799ebb4caSwyllys 219899ebb4caSwyllys ret = KMF_ERR_EXTENSION_NOT_FOUND; 219999ebb4caSwyllys goto out; 220099ebb4caSwyllys } 2201*300fdee2SAndy Fiddaman ex = X509_get_ext(xcert, ext_index); 220299ebb4caSwyllys 220399ebb4caSwyllys (void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex)); 220499ebb4caSwyllys 220599ebb4caSwyllys if (BIO_printf(mem, ": %s\n", 220630a5e8faSwyllys X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) { 220799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 220899ebb4caSwyllys ret = KMF_ERR_ENCODING; 220999ebb4caSwyllys goto out; 221099ebb4caSwyllys } 221199ebb4caSwyllys if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) { 221299ebb4caSwyllys (void) BIO_printf(mem, "%*s", 4, ""); 2213*300fdee2SAndy Fiddaman (void) ASN1_STRING_print(mem, 2214*300fdee2SAndy Fiddaman X509_EXTENSION_get_data(ex)); 221599ebb4caSwyllys } 221699ebb4caSwyllys if (BIO_write(mem, "\n", 1) <= 0) { 221799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 221899ebb4caSwyllys ret = KMF_ERR_ENCODING; 221999ebb4caSwyllys goto out; 222099ebb4caSwyllys } 222199ebb4caSwyllys len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 222299ebb4caSwyllys } 222399ebb4caSwyllys if (len <= 0) { 222499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 222599ebb4caSwyllys ret = KMF_ERR_ENCODING; 222699ebb4caSwyllys } 222799ebb4caSwyllys 222899ebb4caSwyllys out: 222999ebb4caSwyllys if (outbuf != NULL) { 223099ebb4caSwyllys free(outbuf); 223199ebb4caSwyllys } 223299ebb4caSwyllys 223399ebb4caSwyllys if (xcert != NULL) { 223499ebb4caSwyllys X509_free(xcert); 223599ebb4caSwyllys } 223699ebb4caSwyllys 223799ebb4caSwyllys if (mem != NULL) { 223899ebb4caSwyllys (void) BIO_free(mem); 223999ebb4caSwyllys } 224099ebb4caSwyllys 224199ebb4caSwyllys return (ret); 224299ebb4caSwyllys } 224330a5e8faSwyllys 224499ebb4caSwyllys KMF_RETURN 224599ebb4caSwyllys /*ARGSUSED*/ 224630a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr, 224730a5e8faSwyllys KMF_ATTRIBUTE *attrlist) 224899ebb4caSwyllys { 224999ebb4caSwyllys KMF_RETURN rv = KMF_OK; 225030a5e8faSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL; 225130a5e8faSwyllys KMF_KEY_CLASS keyclass = KMF_ASYM_PRI; 225230a5e8faSwyllys KMF_KEY_HANDLE *key = NULL; 225330a5e8faSwyllys uint32_t numkeys = 1; /* 1 key only */ 225430a5e8faSwyllys char *dirpath = NULL; 225530a5e8faSwyllys char *keyfile = NULL; 225630a5e8faSwyllys KMF_ATTRIBUTE new_attrlist[16]; 225730a5e8faSwyllys int i = 0; 225899ebb4caSwyllys 225999ebb4caSwyllys /* 226099ebb4caSwyllys * This is really just a FindKey operation, reuse the 226199ebb4caSwyllys * FindKey function. 226299ebb4caSwyllys */ 226330a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 226430a5e8faSwyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 226530a5e8faSwyllys i++; 226699ebb4caSwyllys 226730a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 226830a5e8faSwyllys KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t)); 226930a5e8faSwyllys i++; 227099ebb4caSwyllys 227130a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 227230a5e8faSwyllys KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass)); 227330a5e8faSwyllys i++; 227430a5e8faSwyllys 227530a5e8faSwyllys key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 227630a5e8faSwyllys if (key == NULL) { 227730a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 227830a5e8faSwyllys } else { 227930a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 228030a5e8faSwyllys KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE)); 228130a5e8faSwyllys i++; 228230a5e8faSwyllys } 228330a5e8faSwyllys 228430a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 228530a5e8faSwyllys if (dirpath != NULL) { 228630a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 228730a5e8faSwyllys KMF_DIRPATH_ATTR, dirpath, strlen(dirpath)); 228830a5e8faSwyllys i++; 228930a5e8faSwyllys } 229030a5e8faSwyllys 229130a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 229230a5e8faSwyllys if (keyfile == NULL) 229330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 229430a5e8faSwyllys else { 229530a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 229630a5e8faSwyllys KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile)); 229730a5e8faSwyllys i++; 229830a5e8faSwyllys } 229930a5e8faSwyllys 230030a5e8faSwyllys rv = OpenSSL_FindKey(handle, i, new_attrlist); 230199ebb4caSwyllys return (rv); 230299ebb4caSwyllys } 230399ebb4caSwyllys 230499ebb4caSwyllys KMF_RETURN 230599ebb4caSwyllys /*ARGSUSED*/ 230699ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, 230799ebb4caSwyllys KMF_OID *AlgOID, KMF_DATA *ciphertext, 230899ebb4caSwyllys KMF_DATA *output) 230999ebb4caSwyllys { 231099ebb4caSwyllys KMF_RETURN ret = KMF_OK; 231199ebb4caSwyllys RSA *rsa = NULL; 231299ebb4caSwyllys unsigned int in_len = 0, out_len = 0; 231399ebb4caSwyllys unsigned int total_decrypted = 0, modulus_len = 0; 231499ebb4caSwyllys uint8_t *in_data, *out_data; 231599ebb4caSwyllys int i, blocks; 231699ebb4caSwyllys 231799ebb4caSwyllys if (key == NULL || AlgOID == NULL || 231899ebb4caSwyllys ciphertext == NULL || output == NULL || 231999ebb4caSwyllys ciphertext->Data == NULL || 232099ebb4caSwyllys output->Data == NULL) 232199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 232299ebb4caSwyllys 232399ebb4caSwyllys if (key->keyalg == KMF_RSA) { 232499ebb4caSwyllys rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp); 232599ebb4caSwyllys modulus_len = RSA_size(rsa); 232699ebb4caSwyllys } else { 232799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 232899ebb4caSwyllys } 232999ebb4caSwyllys 233099ebb4caSwyllys blocks = ciphertext->Length/modulus_len; 233199ebb4caSwyllys out_data = output->Data; 233299ebb4caSwyllys in_data = ciphertext->Data; 233399ebb4caSwyllys out_len = modulus_len - 11; 233499ebb4caSwyllys in_len = modulus_len; 233599ebb4caSwyllys 233699ebb4caSwyllys for (i = 0; i < blocks; i++) { 233799ebb4caSwyllys out_len = RSA_private_decrypt(in_len, 233899ebb4caSwyllys in_data, out_data, rsa, RSA_PKCS1_PADDING); 233999ebb4caSwyllys 234099ebb4caSwyllys if (out_len == 0) { 234199ebb4caSwyllys ret = KMF_ERR_INTERNAL; 234299ebb4caSwyllys goto cleanup; 234399ebb4caSwyllys } 234499ebb4caSwyllys 234599ebb4caSwyllys out_data += out_len; 234699ebb4caSwyllys total_decrypted += out_len; 234799ebb4caSwyllys in_data += in_len; 234899ebb4caSwyllys } 234999ebb4caSwyllys 235099ebb4caSwyllys output->Length = total_decrypted; 235199ebb4caSwyllys 235299ebb4caSwyllys cleanup: 235399ebb4caSwyllys RSA_free(rsa); 235499ebb4caSwyllys if (ret != KMF_OK) 235599ebb4caSwyllys output->Length = 0; 235699ebb4caSwyllys 235799ebb4caSwyllys return (ret); 235899ebb4caSwyllys 235999ebb4caSwyllys } 236099ebb4caSwyllys 236199ebb4caSwyllys /* 236299ebb4caSwyllys * This function will create a certid from issuer_cert and user_cert. 236399ebb4caSwyllys * The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate 236499ebb4caSwyllys * certid memory after use. 236599ebb4caSwyllys */ 236699ebb4caSwyllys static KMF_RETURN 236799ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert, 236899ebb4caSwyllys const KMF_DATA *user_cert, OCSP_CERTID **certid) 236999ebb4caSwyllys { 237099ebb4caSwyllys KMF_RETURN ret = KMF_OK; 237199ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 237299ebb4caSwyllys X509 *issuer = NULL; 237399ebb4caSwyllys X509 *cert = NULL; 237499ebb4caSwyllys unsigned char *ptmp; 237599ebb4caSwyllys 237699ebb4caSwyllys if (issuer_cert == NULL || user_cert == NULL) { 237799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 237899ebb4caSwyllys } 237999ebb4caSwyllys 238099ebb4caSwyllys /* convert the DER-encoded issuer cert to an internal X509 */ 238199ebb4caSwyllys ptmp = issuer_cert->Data; 238299ebb4caSwyllys issuer = d2i_X509(NULL, (const uchar_t **)&ptmp, 238399ebb4caSwyllys issuer_cert->Length); 238499ebb4caSwyllys if (issuer == NULL) { 238599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 238699ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_ISSUER; 238799ebb4caSwyllys goto end; 238899ebb4caSwyllys } 238999ebb4caSwyllys 239099ebb4caSwyllys /* convert the DER-encoded user cert to an internal X509 */ 239199ebb4caSwyllys ptmp = user_cert->Data; 239299ebb4caSwyllys cert = d2i_X509(NULL, (const uchar_t **)&ptmp, 239399ebb4caSwyllys user_cert->Length); 239499ebb4caSwyllys if (cert == NULL) { 239599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 239699ebb4caSwyllys 239799ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_CERT; 239899ebb4caSwyllys goto end; 239999ebb4caSwyllys } 240099ebb4caSwyllys 240199ebb4caSwyllys /* create a CERTID */ 240299ebb4caSwyllys *certid = OCSP_cert_to_id(NULL, cert, issuer); 240399ebb4caSwyllys if (*certid == NULL) { 240499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 240599ebb4caSwyllys ret = KMF_ERR_OCSP_CERTID; 240699ebb4caSwyllys goto end; 240799ebb4caSwyllys } 240899ebb4caSwyllys 240999ebb4caSwyllys end: 241099ebb4caSwyllys if (issuer != NULL) { 241199ebb4caSwyllys X509_free(issuer); 241299ebb4caSwyllys } 241399ebb4caSwyllys 241499ebb4caSwyllys if (cert != NULL) { 241599ebb4caSwyllys X509_free(cert); 241699ebb4caSwyllys } 241799ebb4caSwyllys 241899ebb4caSwyllys return (ret); 241999ebb4caSwyllys } 242099ebb4caSwyllys 242199ebb4caSwyllys KMF_RETURN 242230a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle, 242330a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 242499ebb4caSwyllys { 242599ebb4caSwyllys KMF_RETURN ret = KMF_OK; 242699ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 242799ebb4caSwyllys OCSP_CERTID *id = NULL; 242899ebb4caSwyllys OCSP_REQUEST *req = NULL; 242999ebb4caSwyllys BIO *derbio = NULL; 243030a5e8faSwyllys char *reqfile; 243130a5e8faSwyllys KMF_DATA *issuer_cert; 243230a5e8faSwyllys KMF_DATA *user_cert; 243399ebb4caSwyllys 243430a5e8faSwyllys user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR, 243530a5e8faSwyllys attrlist, numattr); 243630a5e8faSwyllys if (user_cert == NULL) 243799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 243899ebb4caSwyllys 243930a5e8faSwyllys issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR, 244030a5e8faSwyllys attrlist, numattr); 244130a5e8faSwyllys if (issuer_cert == NULL) 244230a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 244330a5e8faSwyllys 244430a5e8faSwyllys reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR, 244530a5e8faSwyllys attrlist, numattr); 244630a5e8faSwyllys if (reqfile == NULL) 244730a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 244830a5e8faSwyllys 244930a5e8faSwyllys ret = create_certid(handle, issuer_cert, user_cert, &id); 245099ebb4caSwyllys if (ret != KMF_OK) { 245199ebb4caSwyllys return (ret); 245299ebb4caSwyllys } 245399ebb4caSwyllys 245499ebb4caSwyllys /* Create an OCSP request */ 245599ebb4caSwyllys req = OCSP_REQUEST_new(); 245699ebb4caSwyllys if (req == NULL) { 245799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 245899ebb4caSwyllys ret = KMF_ERR_OCSP_CREATE_REQUEST; 245999ebb4caSwyllys goto end; 246099ebb4caSwyllys } 246199ebb4caSwyllys 246299ebb4caSwyllys if (!OCSP_request_add0_id(req, id)) { 246399ebb4caSwyllys ret = KMF_ERR_OCSP_CREATE_REQUEST; 246499ebb4caSwyllys goto end; 246599ebb4caSwyllys } 246699ebb4caSwyllys 246799ebb4caSwyllys /* Write the request to the output file with DER encoding */ 246899ebb4caSwyllys derbio = BIO_new_file(reqfile, "wb"); 246999ebb4caSwyllys if (!derbio) { 247099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 247199ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 247299ebb4caSwyllys goto end; 247399ebb4caSwyllys } 247499ebb4caSwyllys if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) { 247599ebb4caSwyllys ret = KMF_ERR_ENCODING; 247699ebb4caSwyllys } 247799ebb4caSwyllys 247899ebb4caSwyllys end: 247999ebb4caSwyllys /* 2480e65e5c2dSWyllys Ingersoll * We don't need to free "id" explicitely, because OCSP_REQUEST_free() 2481a2d4930dSDan OpenSolaris Anderson * will also deallocate certid's space. 248299ebb4caSwyllys */ 248399ebb4caSwyllys if (req != NULL) { 248499ebb4caSwyllys OCSP_REQUEST_free(req); 248599ebb4caSwyllys } 248699ebb4caSwyllys 248799ebb4caSwyllys if (derbio != NULL) { 248899ebb4caSwyllys (void) BIO_free(derbio); 248999ebb4caSwyllys } 249099ebb4caSwyllys 249199ebb4caSwyllys return (ret); 249299ebb4caSwyllys } 249399ebb4caSwyllys 249499ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */ 2495*300fdee2SAndy Fiddaman static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_BASICRESP *bs) 249699ebb4caSwyllys { 249799ebb4caSwyllys int i; 249899ebb4caSwyllys unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash; 2499*300fdee2SAndy Fiddaman const ASN1_OCTET_STRING *pid; 250099ebb4caSwyllys 2501*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L 2502*300fdee2SAndy Fiddaman OCSP_RESPID *id = bs->tbsResponseData->responderId; 2503*300fdee2SAndy Fiddaman 250499ebb4caSwyllys if (id->type == V_OCSP_RESPID_NAME) 250599ebb4caSwyllys return (X509_find_by_subject(certs, id->value.byName)); 250699ebb4caSwyllys 2507*300fdee2SAndy Fiddaman pid = id->value.byKey; 2508*300fdee2SAndy Fiddaman #else 2509*300fdee2SAndy Fiddaman const X509_NAME *pname; 2510*300fdee2SAndy Fiddaman 2511*300fdee2SAndy Fiddaman if (OCSP_resp_get0_id(bs, &pid, &pname) == 0) 2512*300fdee2SAndy Fiddaman return (NULL); 2513*300fdee2SAndy Fiddaman 2514*300fdee2SAndy Fiddaman if (pname != NULL) 2515*300fdee2SAndy Fiddaman return (X509_find_by_subject(certs, (X509_NAME *)pname)); 2516*300fdee2SAndy Fiddaman #endif 2517*300fdee2SAndy Fiddaman 251899ebb4caSwyllys /* Lookup by key hash */ 251999ebb4caSwyllys 252099ebb4caSwyllys /* If key hash isn't SHA1 length then forget it */ 2521*300fdee2SAndy Fiddaman if (pid->length != SHA_DIGEST_LENGTH) 252299ebb4caSwyllys return (NULL); 252399ebb4caSwyllys 2524*300fdee2SAndy Fiddaman keyhash = pid->data; 252599ebb4caSwyllys /* Calculate hash of each key and compare */ 252699ebb4caSwyllys for (i = 0; i < sk_X509_num(certs); i++) { 2527d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 252899ebb4caSwyllys X509 *x = sk_X509_value(certs, i); 25295b3e1433Swyllys /* Use pubkey_digest to get the key ID value */ 253099ebb4caSwyllys (void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL); 253199ebb4caSwyllys if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH)) 253299ebb4caSwyllys return (x); 253399ebb4caSwyllys } 253499ebb4caSwyllys return (NULL); 253599ebb4caSwyllys } 253699ebb4caSwyllys 253799ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */ 2538a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */ 253999ebb4caSwyllys static int 254099ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs, 254199ebb4caSwyllys X509_STORE *st, unsigned long flags) 254299ebb4caSwyllys { 254399ebb4caSwyllys X509 *signer; 2544*300fdee2SAndy Fiddaman if ((signer = ocsp_find_signer_sk(certs, bs))) { 254599ebb4caSwyllys *psigner = signer; 254699ebb4caSwyllys return (2); 254799ebb4caSwyllys } 2548*300fdee2SAndy Fiddaman 254999ebb4caSwyllys if (!(flags & OCSP_NOINTERN) && 2550*300fdee2SAndy Fiddaman (signer = ocsp_find_signer_sk( 2551*300fdee2SAndy Fiddaman (STACK_OF(X509) *)OCSP_resp_get0_certs(bs), bs))) { 255299ebb4caSwyllys *psigner = signer; 255399ebb4caSwyllys return (1); 255499ebb4caSwyllys } 255599ebb4caSwyllys /* Maybe lookup from store if by subject name */ 255699ebb4caSwyllys 255799ebb4caSwyllys *psigner = NULL; 255899ebb4caSwyllys return (0); 255999ebb4caSwyllys } 256099ebb4caSwyllys 256199ebb4caSwyllys /* 256299ebb4caSwyllys * This function will verify the signature of a basic response, using 256399ebb4caSwyllys * the public key from the OCSP responder certificate. 256499ebb4caSwyllys */ 256599ebb4caSwyllys static KMF_RETURN 256699ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs, 256799ebb4caSwyllys KMF_DATA *signer_cert, KMF_DATA *issuer_cert) 256899ebb4caSwyllys { 256999ebb4caSwyllys KMF_RETURN ret = KMF_OK; 257099ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 257199ebb4caSwyllys STACK_OF(X509) *cert_stack = NULL; 257299ebb4caSwyllys X509 *signer = NULL; 257399ebb4caSwyllys X509 *issuer = NULL; 2574*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L 257599ebb4caSwyllys EVP_PKEY *skey = NULL; 2576*300fdee2SAndy Fiddaman #else 2577*300fdee2SAndy Fiddaman STACK_OF(X509) *cert_stack2 = NULL; 2578*300fdee2SAndy Fiddaman #endif 257999ebb4caSwyllys unsigned char *ptmp; 258099ebb4caSwyllys 258199ebb4caSwyllys if (bs == NULL || issuer_cert == NULL) 258299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 258399ebb4caSwyllys 258499ebb4caSwyllys /* 258599ebb4caSwyllys * Find the certificate that signed the basic response. 258699ebb4caSwyllys * 258799ebb4caSwyllys * If signer_cert is not NULL, we will use that as the signer cert. 258899ebb4caSwyllys * Otherwise, we will check if the issuer cert is actually the signer. 258999ebb4caSwyllys * If we still do not find a signer, we will look for it from the 259099ebb4caSwyllys * certificate list came with the response file. 259199ebb4caSwyllys */ 259299ebb4caSwyllys if (signer_cert != NULL) { 259399ebb4caSwyllys ptmp = signer_cert->Data; 259499ebb4caSwyllys signer = d2i_X509(NULL, (const uchar_t **)&ptmp, 259599ebb4caSwyllys signer_cert->Length); 259699ebb4caSwyllys if (signer == NULL) { 259799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 259899ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_SIGNER; 259999ebb4caSwyllys goto end; 260099ebb4caSwyllys } 260199ebb4caSwyllys } else { 260299ebb4caSwyllys /* 260399ebb4caSwyllys * Convert the issuer cert into X509 and push it into a 260499ebb4caSwyllys * stack to be used by ocsp_find_signer(). 260599ebb4caSwyllys */ 260699ebb4caSwyllys ptmp = issuer_cert->Data; 260799ebb4caSwyllys issuer = d2i_X509(NULL, (const uchar_t **)&ptmp, 260899ebb4caSwyllys issuer_cert->Length); 260999ebb4caSwyllys if (issuer == NULL) { 261099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 261199ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_ISSUER; 261299ebb4caSwyllys goto end; 261399ebb4caSwyllys } 261499ebb4caSwyllys 261599ebb4caSwyllys if ((cert_stack = sk_X509_new_null()) == NULL) { 261699ebb4caSwyllys ret = KMF_ERR_INTERNAL; 261799ebb4caSwyllys goto end; 261899ebb4caSwyllys } 261999ebb4caSwyllys 262099ebb4caSwyllys if (sk_X509_push(cert_stack, issuer) == NULL) { 262199ebb4caSwyllys ret = KMF_ERR_INTERNAL; 262299ebb4caSwyllys goto end; 262399ebb4caSwyllys } 262499ebb4caSwyllys 262599ebb4caSwyllys ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0); 262699ebb4caSwyllys if (!ret) { 262799ebb4caSwyllys /* can not find the signer */ 262899ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_SIGNER; 262999ebb4caSwyllys goto end; 263099ebb4caSwyllys } 263199ebb4caSwyllys } 263299ebb4caSwyllys 263399ebb4caSwyllys /* Verify the signature of the response */ 2634*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L 263599ebb4caSwyllys skey = X509_get_pubkey(signer); 263699ebb4caSwyllys if (skey == NULL) { 263799ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_SIGNER; 263899ebb4caSwyllys goto end; 263999ebb4caSwyllys } 264099ebb4caSwyllys 264199ebb4caSwyllys ret = OCSP_BASICRESP_verify(bs, skey, 0); 2642*300fdee2SAndy Fiddaman #else 2643*300fdee2SAndy Fiddaman /* 2644*300fdee2SAndy Fiddaman * Technique based on 2645*300fdee2SAndy Fiddaman * https://mta.openssl.org/pipermail/openssl-users/ 2646*300fdee2SAndy Fiddaman * 2017-October/006814.html 2647*300fdee2SAndy Fiddaman */ 2648*300fdee2SAndy Fiddaman if ((cert_stack2 = sk_X509_new_null()) == NULL) { 2649*300fdee2SAndy Fiddaman ret = KMF_ERR_INTERNAL; 2650*300fdee2SAndy Fiddaman goto end; 2651*300fdee2SAndy Fiddaman } 2652*300fdee2SAndy Fiddaman 2653*300fdee2SAndy Fiddaman if (sk_X509_push(cert_stack2, signer) == NULL) { 2654*300fdee2SAndy Fiddaman ret = KMF_ERR_INTERNAL; 2655*300fdee2SAndy Fiddaman goto end; 2656*300fdee2SAndy Fiddaman } 2657*300fdee2SAndy Fiddaman 2658*300fdee2SAndy Fiddaman ret = OCSP_basic_verify(bs, cert_stack2, NULL, OCSP_NOVERIFY); 2659*300fdee2SAndy Fiddaman #endif 2660*300fdee2SAndy Fiddaman 266199ebb4caSwyllys if (ret == 0) { 266299ebb4caSwyllys ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE; 266399ebb4caSwyllys goto end; 266499ebb4caSwyllys } 266599ebb4caSwyllys 266699ebb4caSwyllys end: 266799ebb4caSwyllys if (issuer != NULL) { 266899ebb4caSwyllys X509_free(issuer); 266999ebb4caSwyllys } 267099ebb4caSwyllys 267199ebb4caSwyllys if (signer != NULL) { 267299ebb4caSwyllys X509_free(signer); 267399ebb4caSwyllys } 267499ebb4caSwyllys 2675*300fdee2SAndy Fiddaman #if OPENSSL_VERSION_NUMBER < 0x10100000L 267699ebb4caSwyllys if (skey != NULL) { 267799ebb4caSwyllys EVP_PKEY_free(skey); 267899ebb4caSwyllys } 2679*300fdee2SAndy Fiddaman #else 2680*300fdee2SAndy Fiddaman if (cert_stack2 != NULL) { 2681*300fdee2SAndy Fiddaman sk_X509_free(cert_stack2); 2682*300fdee2SAndy Fiddaman } 2683*300fdee2SAndy Fiddaman #endif 268499ebb4caSwyllys 268599ebb4caSwyllys if (cert_stack != NULL) { 268699ebb4caSwyllys sk_X509_free(cert_stack); 268799ebb4caSwyllys } 268899ebb4caSwyllys 268999ebb4caSwyllys return (ret); 269099ebb4caSwyllys } 269199ebb4caSwyllys 269299ebb4caSwyllys KMF_RETURN 269399ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle, 269430a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 269599ebb4caSwyllys { 269699ebb4caSwyllys KMF_RETURN ret = KMF_OK; 269799ebb4caSwyllys BIO *derbio = NULL; 269899ebb4caSwyllys OCSP_RESPONSE *resp = NULL; 269999ebb4caSwyllys OCSP_BASICRESP *bs = NULL; 270099ebb4caSwyllys OCSP_CERTID *id = NULL; 270199ebb4caSwyllys OCSP_SINGLERESP *single = NULL; 270299ebb4caSwyllys ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; 270399ebb4caSwyllys int index, status, reason; 270430a5e8faSwyllys KMF_DATA *issuer_cert; 270530a5e8faSwyllys KMF_DATA *user_cert; 270630a5e8faSwyllys KMF_DATA *signer_cert; 270730a5e8faSwyllys KMF_DATA *response; 270830a5e8faSwyllys int *response_reason, *response_status, *cert_status; 270930a5e8faSwyllys boolean_t ignore_response_sign = B_FALSE; /* default is FALSE */ 271030a5e8faSwyllys uint32_t response_lifetime; 271199ebb4caSwyllys 271230a5e8faSwyllys issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR, 271330a5e8faSwyllys attrlist, numattr); 271430a5e8faSwyllys if (issuer_cert == NULL) 271599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 271699ebb4caSwyllys 271730a5e8faSwyllys user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR, 271830a5e8faSwyllys attrlist, numattr); 271930a5e8faSwyllys if (user_cert == NULL) 272099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 272130a5e8faSwyllys 272230a5e8faSwyllys response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR, 272330a5e8faSwyllys attrlist, numattr); 272430a5e8faSwyllys if (response == NULL) 272530a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 272630a5e8faSwyllys 272730a5e8faSwyllys response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR, 272830a5e8faSwyllys attrlist, numattr); 272930a5e8faSwyllys if (response_status == NULL) 273030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 273130a5e8faSwyllys 273230a5e8faSwyllys response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR, 273330a5e8faSwyllys attrlist, numattr); 273430a5e8faSwyllys if (response_reason == NULL) 273530a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 273630a5e8faSwyllys 273730a5e8faSwyllys cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR, 273830a5e8faSwyllys attrlist, numattr); 273930a5e8faSwyllys if (cert_status == NULL) 274030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 274199ebb4caSwyllys 274299ebb4caSwyllys /* Read in the response */ 274330a5e8faSwyllys derbio = BIO_new_mem_buf(response->Data, response->Length); 274499ebb4caSwyllys if (!derbio) { 274599ebb4caSwyllys ret = KMF_ERR_MEMORY; 274699ebb4caSwyllys return (ret); 274799ebb4caSwyllys } 274899ebb4caSwyllys 274999ebb4caSwyllys resp = d2i_OCSP_RESPONSE_bio(derbio, NULL); 275099ebb4caSwyllys if (resp == NULL) { 275199ebb4caSwyllys ret = KMF_ERR_OCSP_MALFORMED_RESPONSE; 275299ebb4caSwyllys goto end; 275399ebb4caSwyllys } 275499ebb4caSwyllys 275599ebb4caSwyllys /* Check the response status */ 275699ebb4caSwyllys status = OCSP_response_status(resp); 275730a5e8faSwyllys *response_status = status; 275899ebb4caSwyllys if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { 275999ebb4caSwyllys ret = KMF_ERR_OCSP_RESPONSE_STATUS; 276099ebb4caSwyllys goto end; 276199ebb4caSwyllys } 276299ebb4caSwyllys 276399ebb4caSwyllys #ifdef DEBUG 276499ebb4caSwyllys printf("Successfully checked the response file status.\n"); 276599ebb4caSwyllys #endif /* DEBUG */ 276699ebb4caSwyllys 276799ebb4caSwyllys /* Extract basic response */ 276899ebb4caSwyllys bs = OCSP_response_get1_basic(resp); 276999ebb4caSwyllys if (bs == NULL) { 277099ebb4caSwyllys ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE; 277199ebb4caSwyllys goto end; 277299ebb4caSwyllys } 277399ebb4caSwyllys 277499ebb4caSwyllys #ifdef DEBUG 277599ebb4caSwyllys printf("Successfully retrieved the basic response.\n"); 277699ebb4caSwyllys #endif /* DEBUG */ 277799ebb4caSwyllys 277899ebb4caSwyllys /* Check the basic response signature if required */ 277930a5e8faSwyllys ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr, 278030a5e8faSwyllys (void *)&ignore_response_sign, NULL); 278130a5e8faSwyllys if (ret != KMF_OK) 278230a5e8faSwyllys ret = KMF_OK; 278330a5e8faSwyllys 278430a5e8faSwyllys signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR, 278530a5e8faSwyllys attrlist, numattr); 278630a5e8faSwyllys 278730a5e8faSwyllys if (ignore_response_sign == B_FALSE) { 278899ebb4caSwyllys ret = check_response_signature(handle, bs, 278930a5e8faSwyllys signer_cert, issuer_cert); 279099ebb4caSwyllys if (ret != KMF_OK) 279199ebb4caSwyllys goto end; 279299ebb4caSwyllys } 279399ebb4caSwyllys 279499ebb4caSwyllys #ifdef DEBUG 279599ebb4caSwyllys printf("Successfully verified the response signature.\n"); 279699ebb4caSwyllys #endif /* DEBUG */ 279799ebb4caSwyllys 279899ebb4caSwyllys /* Create a certid for the certificate in question */ 279930a5e8faSwyllys ret = create_certid(handle, issuer_cert, user_cert, &id); 280099ebb4caSwyllys if (ret != KMF_OK) { 280199ebb4caSwyllys ret = KMF_ERR_OCSP_CERTID; 280299ebb4caSwyllys goto end; 280399ebb4caSwyllys } 280499ebb4caSwyllys 280599ebb4caSwyllys #ifdef DEBUG 280699ebb4caSwyllys printf("successfully created a certid for the cert.\n"); 280799ebb4caSwyllys #endif /* DEBUG */ 280899ebb4caSwyllys 280999ebb4caSwyllys /* Find the index of the single response for the certid */ 281099ebb4caSwyllys index = OCSP_resp_find(bs, id, -1); 281199ebb4caSwyllys if (index < 0) { 281299ebb4caSwyllys /* cound not find this certificate in the response */ 281399ebb4caSwyllys ret = KMF_ERR_OCSP_UNKNOWN_CERT; 281499ebb4caSwyllys goto end; 281599ebb4caSwyllys } 281699ebb4caSwyllys 281799ebb4caSwyllys #ifdef DEBUG 281899ebb4caSwyllys printf("Successfully found the single response index for the cert.\n"); 281999ebb4caSwyllys #endif /* DEBUG */ 282099ebb4caSwyllys 282199ebb4caSwyllys /* Retrieve the single response and get the cert status */ 282299ebb4caSwyllys single = OCSP_resp_get0(bs, index); 282399ebb4caSwyllys status = OCSP_single_get0_status(single, &reason, &rev, &thisupd, 282499ebb4caSwyllys &nextupd); 282599ebb4caSwyllys if (status == V_OCSP_CERTSTATUS_GOOD) { 282630a5e8faSwyllys *cert_status = OCSP_GOOD; 282799ebb4caSwyllys } else if (status == V_OCSP_CERTSTATUS_UNKNOWN) { 282830a5e8faSwyllys *cert_status = OCSP_UNKNOWN; 282999ebb4caSwyllys } else { /* revoked */ 283030a5e8faSwyllys *cert_status = OCSP_REVOKED; 283130a5e8faSwyllys *response_reason = reason; 283299ebb4caSwyllys } 283399ebb4caSwyllys ret = KMF_OK; 283499ebb4caSwyllys 283530a5e8faSwyllys /* resp. time is optional, so we don't care about the return code. */ 283630a5e8faSwyllys (void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr, 283730a5e8faSwyllys (void *)&response_lifetime, NULL); 283830a5e8faSwyllys 283999ebb4caSwyllys if (!OCSP_check_validity(thisupd, nextupd, 300, 284030a5e8faSwyllys response_lifetime)) { 284199ebb4caSwyllys ret = KMF_ERR_OCSP_STATUS_TIME_INVALID; 284299ebb4caSwyllys goto end; 284399ebb4caSwyllys } 284499ebb4caSwyllys 284599ebb4caSwyllys #ifdef DEBUG 284699ebb4caSwyllys printf("Successfully verify the time.\n"); 284799ebb4caSwyllys #endif /* DEBUG */ 284899ebb4caSwyllys 284999ebb4caSwyllys end: 285099ebb4caSwyllys if (derbio != NULL) 285199ebb4caSwyllys (void) BIO_free(derbio); 285299ebb4caSwyllys 285399ebb4caSwyllys if (resp != NULL) 285499ebb4caSwyllys OCSP_RESPONSE_free(resp); 285599ebb4caSwyllys 285699ebb4caSwyllys if (bs != NULL) 285799ebb4caSwyllys OCSP_BASICRESP_free(bs); 285899ebb4caSwyllys 285999ebb4caSwyllys if (id != NULL) 286099ebb4caSwyllys OCSP_CERTID_free(id); 286199ebb4caSwyllys 286299ebb4caSwyllys return (ret); 286399ebb4caSwyllys } 286499ebb4caSwyllys 286599ebb4caSwyllys static KMF_RETURN 286699ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path, 286799ebb4caSwyllys KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key) 286899ebb4caSwyllys { 286999ebb4caSwyllys KMF_RETURN rv = KMF_OK; 287030a5e8faSwyllys EVP_PKEY *pkey = NULL; 287199ebb4caSwyllys KMF_RAW_SYM_KEY *rkey = NULL; 287299ebb4caSwyllys 287399ebb4caSwyllys if (keyclass == KMF_ASYM_PRI || 287499ebb4caSwyllys keyclass == KMF_ASYM_PUB) { 287599ebb4caSwyllys pkey = openssl_load_key(handle, path); 287699ebb4caSwyllys if (pkey == NULL) { 287799ebb4caSwyllys return (KMF_ERR_KEY_NOT_FOUND); 287899ebb4caSwyllys } 287999ebb4caSwyllys if (key != NULL) { 2880*300fdee2SAndy Fiddaman if (EVP_PKEY_get0_RSA(pkey) != NULL) 288199ebb4caSwyllys key->keyalg = KMF_RSA; 2882*300fdee2SAndy Fiddaman else if (EVP_PKEY_get0_DSA(pkey) != NULL) 288399ebb4caSwyllys key->keyalg = KMF_DSA; 288499ebb4caSwyllys 288599ebb4caSwyllys key->kstype = KMF_KEYSTORE_OPENSSL; 288699ebb4caSwyllys key->keyclass = keyclass; 288799ebb4caSwyllys key->keyp = (void *)pkey; 288899ebb4caSwyllys key->israw = FALSE; 28895b3e1433Swyllys if (path != NULL && 28905b3e1433Swyllys ((key->keylabel = strdup(path)) == NULL)) { 28915b3e1433Swyllys EVP_PKEY_free(pkey); 28925b3e1433Swyllys return (KMF_ERR_MEMORY); 28935b3e1433Swyllys } 289499ebb4caSwyllys } else { 289599ebb4caSwyllys EVP_PKEY_free(pkey); 289699ebb4caSwyllys pkey = NULL; 289799ebb4caSwyllys } 289899ebb4caSwyllys } else if (keyclass == KMF_SYMMETRIC) { 289999ebb4caSwyllys KMF_ENCODE_FORMAT fmt; 290099ebb4caSwyllys /* 290199ebb4caSwyllys * If the file is a recognized format, 290299ebb4caSwyllys * then it is NOT a symmetric key. 290399ebb4caSwyllys */ 290430a5e8faSwyllys rv = kmf_get_file_format(path, &fmt); 290599ebb4caSwyllys if (rv == KMF_OK || fmt != 0) { 290699ebb4caSwyllys return (KMF_ERR_KEY_NOT_FOUND); 290799ebb4caSwyllys } else if (rv == KMF_ERR_ENCODING) { 290899ebb4caSwyllys /* 290999ebb4caSwyllys * If we don't know the encoding, 291099ebb4caSwyllys * it is probably a symmetric key. 291199ebb4caSwyllys */ 291299ebb4caSwyllys rv = KMF_OK; 291330a5e8faSwyllys } else if (rv == KMF_ERR_OPEN_FILE) { 291430a5e8faSwyllys return (KMF_ERR_KEY_NOT_FOUND); 291599ebb4caSwyllys } 291699ebb4caSwyllys 291799ebb4caSwyllys if (key != NULL) { 291899ebb4caSwyllys KMF_DATA keyvalue; 291999ebb4caSwyllys rkey = malloc(sizeof (KMF_RAW_SYM_KEY)); 292099ebb4caSwyllys if (rkey == NULL) { 292199ebb4caSwyllys rv = KMF_ERR_MEMORY; 292299ebb4caSwyllys goto out; 292399ebb4caSwyllys } 292499ebb4caSwyllys 292599ebb4caSwyllys (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 292630a5e8faSwyllys rv = kmf_read_input_file(handle, path, &keyvalue); 292799ebb4caSwyllys if (rv != KMF_OK) 292899ebb4caSwyllys goto out; 292999ebb4caSwyllys 293099ebb4caSwyllys rkey->keydata.len = keyvalue.Length; 293199ebb4caSwyllys rkey->keydata.val = keyvalue.Data; 293299ebb4caSwyllys 293399ebb4caSwyllys key->kstype = KMF_KEYSTORE_OPENSSL; 293499ebb4caSwyllys key->keyclass = keyclass; 293599ebb4caSwyllys key->israw = TRUE; 293699ebb4caSwyllys key->keyp = (void *)rkey; 29375b3e1433Swyllys if (path != NULL && 29385b3e1433Swyllys ((key->keylabel = strdup(path)) == NULL)) { 29395b3e1433Swyllys rv = KMF_ERR_MEMORY; 29405b3e1433Swyllys } 294199ebb4caSwyllys } 294299ebb4caSwyllys } 294399ebb4caSwyllys out: 294499ebb4caSwyllys if (rv != KMF_OK) { 294599ebb4caSwyllys if (rkey != NULL) { 294630a5e8faSwyllys kmf_free_raw_sym_key(rkey); 294799ebb4caSwyllys } 294899ebb4caSwyllys if (pkey != NULL) 294999ebb4caSwyllys EVP_PKEY_free(pkey); 295099ebb4caSwyllys 295199ebb4caSwyllys if (key != NULL) { 295299ebb4caSwyllys key->keyalg = KMF_KEYALG_NONE; 295399ebb4caSwyllys key->keyclass = KMF_KEYCLASS_NONE; 295499ebb4caSwyllys key->keyp = NULL; 295599ebb4caSwyllys } 295699ebb4caSwyllys } 295799ebb4caSwyllys 295899ebb4caSwyllys return (rv); 295999ebb4caSwyllys } 296099ebb4caSwyllys 296199ebb4caSwyllys KMF_RETURN 296230a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle, 296330a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 296499ebb4caSwyllys { 296599ebb4caSwyllys KMF_RETURN rv = KMF_OK; 296699ebb4caSwyllys char *fullpath = NULL; 2967f482c776Swyllys uint32_t maxkeys; 296830a5e8faSwyllys KMF_KEY_HANDLE *key; 296930a5e8faSwyllys uint32_t *numkeys; 297030a5e8faSwyllys KMF_KEY_CLASS keyclass; 297130a5e8faSwyllys KMF_RAW_KEY_DATA *rawkey; 297230a5e8faSwyllys char *dirpath; 297330a5e8faSwyllys char *keyfile; 297499ebb4caSwyllys 297530a5e8faSwyllys if (handle == NULL) 297699ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 297799ebb4caSwyllys 297830a5e8faSwyllys numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr); 297930a5e8faSwyllys if (numkeys == NULL) 298030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 298130a5e8faSwyllys 298230a5e8faSwyllys rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr, 298330a5e8faSwyllys (void *)&keyclass, NULL); 298430a5e8faSwyllys if (rv != KMF_OK) 298530a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 298630a5e8faSwyllys 298730a5e8faSwyllys if (keyclass != KMF_ASYM_PUB && 298830a5e8faSwyllys keyclass != KMF_ASYM_PRI && 298930a5e8faSwyllys keyclass != KMF_SYMMETRIC) 299099ebb4caSwyllys return (KMF_ERR_BAD_KEY_CLASS); 299199ebb4caSwyllys 299230a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 299330a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 299430a5e8faSwyllys 299530a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 299699ebb4caSwyllys 299799ebb4caSwyllys if (fullpath == NULL) 299899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 299999ebb4caSwyllys 3000f482c776Swyllys maxkeys = *numkeys; 3001f482c776Swyllys if (maxkeys == 0) 3002f482c776Swyllys maxkeys = 0xFFFFFFFF; 300399ebb4caSwyllys *numkeys = 0; 300499ebb4caSwyllys 300530a5e8faSwyllys key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 300630a5e8faSwyllys /* it is okay to have "keys" contains NULL */ 300730a5e8faSwyllys 300830a5e8faSwyllys /* 300930a5e8faSwyllys * The caller may want a list of the raw key data as well. 301030a5e8faSwyllys * Useful for importing keys from a file into other keystores. 301130a5e8faSwyllys */ 301230a5e8faSwyllys rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr); 301330a5e8faSwyllys 301499ebb4caSwyllys if (isdir(fullpath)) { 301599ebb4caSwyllys DIR *dirp; 301699ebb4caSwyllys struct dirent *dp; 301799ebb4caSwyllys int n = 0; 301899ebb4caSwyllys 301999ebb4caSwyllys /* open all files in the directory and attempt to read them */ 302099ebb4caSwyllys if ((dirp = opendir(fullpath)) == NULL) { 302199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 302299ebb4caSwyllys } 302399ebb4caSwyllys rewinddir(dirp); 3024f482c776Swyllys while ((dp = readdir(dirp)) != NULL && n < maxkeys) { 302599ebb4caSwyllys if (strcmp(dp->d_name, ".") && 302699ebb4caSwyllys strcmp(dp->d_name, "..")) { 302799ebb4caSwyllys char *fname; 302899ebb4caSwyllys 302999ebb4caSwyllys fname = get_fullpath(fullpath, 303099ebb4caSwyllys (char *)&dp->d_name); 303199ebb4caSwyllys 303299ebb4caSwyllys rv = fetch_key(handle, fname, 303330a5e8faSwyllys keyclass, key ? &key[n] : NULL); 303499ebb4caSwyllys 303530a5e8faSwyllys if (rv == KMF_OK) { 303630a5e8faSwyllys if (key != NULL && rawkey != NULL) 303730a5e8faSwyllys rv = convertToRawKey( 303830a5e8faSwyllys key[n].keyp, &rawkey[n]); 303999ebb4caSwyllys n++; 304030a5e8faSwyllys } 304199ebb4caSwyllys 304299ebb4caSwyllys if (rv != KMF_OK || key == NULL) 304399ebb4caSwyllys free(fname); 304499ebb4caSwyllys } 304599ebb4caSwyllys } 304699ebb4caSwyllys (void) closedir(dirp); 304799ebb4caSwyllys free(fullpath); 304899ebb4caSwyllys (*numkeys) = n; 304999ebb4caSwyllys } else { 305030a5e8faSwyllys rv = fetch_key(handle, fullpath, keyclass, key); 305199ebb4caSwyllys if (rv == KMF_OK) 305299ebb4caSwyllys (*numkeys) = 1; 305399ebb4caSwyllys 305499ebb4caSwyllys if (rv != KMF_OK || key == NULL) 305599ebb4caSwyllys free(fullpath); 305630a5e8faSwyllys 305730a5e8faSwyllys if (rv == KMF_OK && key != NULL && rawkey != NULL) { 305830a5e8faSwyllys rv = convertToRawKey(key->keyp, rawkey); 305930a5e8faSwyllys } 306099ebb4caSwyllys } 306199ebb4caSwyllys 3062f482c776Swyllys if (rv == KMF_OK && (*numkeys) == 0) 306399ebb4caSwyllys rv = KMF_ERR_KEY_NOT_FOUND; 306473cc0e02Swyllys else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0) 306573cc0e02Swyllys rv = KMF_OK; 306699ebb4caSwyllys 306799ebb4caSwyllys return (rv); 306899ebb4caSwyllys } 306999ebb4caSwyllys 307099ebb4caSwyllys #define HANDLE_PK12_ERROR { \ 307199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); \ 307299ebb4caSwyllys rv = KMF_ERR_ENCODING; \ 307399ebb4caSwyllys goto out; \ 307499ebb4caSwyllys } 307599ebb4caSwyllys 30765b3e1433Swyllys static int 30775b3e1433Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert) 307899ebb4caSwyllys { 3079*300fdee2SAndy Fiddaman unsigned char *alias; 3080*300fdee2SAndy Fiddaman int len; 3081*300fdee2SAndy Fiddaman 3082*300fdee2SAndy Fiddaman if (xcert != NULL && (alias = X509_alias_get0(xcert, &len)) != NULL) { 30835b3e1433Swyllys if (PKCS12_add_friendlyname_asc(bag, 3084*300fdee2SAndy Fiddaman (const char *)alias, len) == 0) 30855b3e1433Swyllys return (0); 30865b3e1433Swyllys } 30875b3e1433Swyllys return (1); 30885b3e1433Swyllys } 30895b3e1433Swyllys 30905b3e1433Swyllys static PKCS7 * 30915b3e1433Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred, 30925b3e1433Swyllys uchar_t *keyid, unsigned int keyidlen) 30935b3e1433Swyllys { 309499ebb4caSwyllys PKCS12_SAFEBAG *bag = NULL; 309599ebb4caSwyllys PKCS7 *cert_authsafe = NULL; 30965b3e1433Swyllys STACK_OF(PKCS12_SAFEBAG) *bag_stack; 309799ebb4caSwyllys 309899ebb4caSwyllys bag_stack = sk_PKCS12_SAFEBAG_new_null(); 309999ebb4caSwyllys if (bag_stack == NULL) 31005b3e1433Swyllys return (NULL); 310199ebb4caSwyllys 310299ebb4caSwyllys /* Convert cert from X509 struct to PKCS#12 bag */ 3103*300fdee2SAndy Fiddaman bag = PKCS12_SAFEBAG_create_cert(sslcert); 310499ebb4caSwyllys if (bag == NULL) { 31055b3e1433Swyllys goto out; 310699ebb4caSwyllys } 310799ebb4caSwyllys 310899ebb4caSwyllys /* Add the key id to the certificate bag. */ 31095b3e1433Swyllys if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) { 31105b3e1433Swyllys goto out; 311199ebb4caSwyllys } 311299ebb4caSwyllys 31135b3e1433Swyllys if (!add_alias_to_bag(bag, sslcert)) 31145b3e1433Swyllys goto out; 31155b3e1433Swyllys 311699ebb4caSwyllys /* Pile it on the bag_stack. */ 311799ebb4caSwyllys if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) { 31185b3e1433Swyllys goto out; 311999ebb4caSwyllys } 312099ebb4caSwyllys /* Turn bag_stack of certs into encrypted authsafe. */ 312199ebb4caSwyllys cert_authsafe = PKCS12_pack_p7encdata( 312299ebb4caSwyllys NID_pbe_WithSHA1And40BitRC2_CBC, 312334acef67Swyllys cred->cred, cred->credlen, NULL, 0, 312434acef67Swyllys PKCS12_DEFAULT_ITER, bag_stack); 312599ebb4caSwyllys 31265b3e1433Swyllys out: 31275b3e1433Swyllys if (bag_stack != NULL) 312899ebb4caSwyllys sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); 312999ebb4caSwyllys 31305b3e1433Swyllys return (cert_authsafe); 313199ebb4caSwyllys } 31325b3e1433Swyllys 31335b3e1433Swyllys static PKCS7 * 31345b3e1433Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred, 31355b3e1433Swyllys uchar_t *keyid, unsigned int keyidlen, 31365b3e1433Swyllys char *label, int label_len) 31375b3e1433Swyllys { 31385b3e1433Swyllys PKCS8_PRIV_KEY_INFO *p8 = NULL; 31395b3e1433Swyllys STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL; 31405b3e1433Swyllys PKCS12_SAFEBAG *bag = NULL; 31415b3e1433Swyllys PKCS7 *key_authsafe = NULL; 31425b3e1433Swyllys 314399ebb4caSwyllys p8 = EVP_PKEY2PKCS8(pkey); 314499ebb4caSwyllys if (p8 == NULL) { 31455b3e1433Swyllys return (NULL); 314699ebb4caSwyllys } 314799ebb4caSwyllys /* Put the shrouded key into a PKCS#12 bag. */ 3148*300fdee2SAndy Fiddaman bag = PKCS12_SAFEBAG_create_pkcs8_encrypt( 314999ebb4caSwyllys NID_pbe_WithSHA1And3_Key_TripleDES_CBC, 315099ebb4caSwyllys cred->cred, cred->credlen, 315199ebb4caSwyllys NULL, 0, PKCS12_DEFAULT_ITER, p8); 315299ebb4caSwyllys 315399ebb4caSwyllys /* Clean up the PKCS#8 shrouded key, don't need it now. */ 315499ebb4caSwyllys PKCS8_PRIV_KEY_INFO_free(p8); 315599ebb4caSwyllys p8 = NULL; 315699ebb4caSwyllys 315799ebb4caSwyllys if (bag == NULL) { 31585b3e1433Swyllys return (NULL); 315999ebb4caSwyllys } 31605b3e1433Swyllys if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) 31615b3e1433Swyllys goto out; 31625b3e1433Swyllys if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len)) 31635b3e1433Swyllys goto out; 31645b3e1433Swyllys 316599ebb4caSwyllys /* Start a PKCS#12 safebag container for the private key. */ 316699ebb4caSwyllys bag_stack = sk_PKCS12_SAFEBAG_new_null(); 31675b3e1433Swyllys if (bag_stack == NULL) 31685b3e1433Swyllys goto out; 316999ebb4caSwyllys 317099ebb4caSwyllys /* Pile on the private key on the bag_stack. */ 31715b3e1433Swyllys if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) 31725b3e1433Swyllys goto out; 31735b3e1433Swyllys 317499ebb4caSwyllys key_authsafe = PKCS12_pack_p7data(bag_stack); 317599ebb4caSwyllys 31765b3e1433Swyllys out: 31775b3e1433Swyllys if (bag_stack != NULL) 317899ebb4caSwyllys sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); 317999ebb4caSwyllys bag_stack = NULL; 31805b3e1433Swyllys return (key_authsafe); 318199ebb4caSwyllys } 318299ebb4caSwyllys 318399ebb4caSwyllys static EVP_PKEY * 318499ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key) 318599ebb4caSwyllys { 318699ebb4caSwyllys RSA *rsa = NULL; 318799ebb4caSwyllys EVP_PKEY *newkey = NULL; 3188*300fdee2SAndy Fiddaman BIGNUM *n = NULL, *e = NULL, *d = NULL, 3189*300fdee2SAndy Fiddaman *p = NULL, *q = NULL, 3190*300fdee2SAndy Fiddaman *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; 319199ebb4caSwyllys 319299ebb4caSwyllys if ((rsa = RSA_new()) == NULL) 3193*300fdee2SAndy Fiddaman goto cleanup; 319499ebb4caSwyllys 3195*300fdee2SAndy Fiddaman if ((n = BN_bin2bn(key->mod.val, key->mod.len, NULL)) == NULL) 3196*300fdee2SAndy Fiddaman goto cleanup; 319799ebb4caSwyllys 3198*300fdee2SAndy Fiddaman if ((e = BN_bin2bn(key->pubexp.val, key->pubexp.len, NULL)) == NULL) 3199*300fdee2SAndy Fiddaman goto cleanup; 320099ebb4caSwyllys 3201*300fdee2SAndy Fiddaman if (key->priexp.val != NULL && 3202*300fdee2SAndy Fiddaman (d = BN_bin2bn(key->priexp.val, key->priexp.len, NULL)) == NULL) 3203*300fdee2SAndy Fiddaman goto cleanup; 320499ebb4caSwyllys 3205*300fdee2SAndy Fiddaman if (key->prime1.val != NULL && 3206*300fdee2SAndy Fiddaman (p = BN_bin2bn(key->prime1.val, key->prime1.len, NULL)) == NULL) 3207*300fdee2SAndy Fiddaman goto cleanup; 320899ebb4caSwyllys 3209*300fdee2SAndy Fiddaman if (key->prime2.val != NULL && 3210*300fdee2SAndy Fiddaman (q = BN_bin2bn(key->prime2.val, key->prime2.len, NULL)) == NULL) 3211*300fdee2SAndy Fiddaman goto cleanup; 321299ebb4caSwyllys 3213*300fdee2SAndy Fiddaman if (key->exp1.val != NULL && 3214*300fdee2SAndy Fiddaman (dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len, NULL)) == NULL) 3215*300fdee2SAndy Fiddaman goto cleanup; 321699ebb4caSwyllys 3217*300fdee2SAndy Fiddaman if (key->exp2.val != NULL && 3218*300fdee2SAndy Fiddaman (dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len, NULL)) == NULL) 3219*300fdee2SAndy Fiddaman goto cleanup; 322099ebb4caSwyllys 3221*300fdee2SAndy Fiddaman if (key->coef.val != NULL && 3222*300fdee2SAndy Fiddaman (iqmp = BN_bin2bn(key->coef.val, key->coef.len, NULL)) == NULL) 3223*300fdee2SAndy Fiddaman goto cleanup; 3224*300fdee2SAndy Fiddaman 3225*300fdee2SAndy Fiddaman if (RSA_set0_key(rsa, n, e, d) == 0) 3226*300fdee2SAndy Fiddaman goto cleanup; 3227*300fdee2SAndy Fiddaman n = e = d = NULL; 3228*300fdee2SAndy Fiddaman if (RSA_set0_factors(rsa, p, q) == 0) 3229*300fdee2SAndy Fiddaman goto cleanup; 3230*300fdee2SAndy Fiddaman p = q = NULL; 3231*300fdee2SAndy Fiddaman if (RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp) == 0) 3232*300fdee2SAndy Fiddaman goto cleanup; 3233*300fdee2SAndy Fiddaman dmp1 = dmq1 = iqmp = NULL; 323499ebb4caSwyllys 323599ebb4caSwyllys if ((newkey = EVP_PKEY_new()) == NULL) 3236*300fdee2SAndy Fiddaman goto cleanup; 323799ebb4caSwyllys 323899ebb4caSwyllys (void) EVP_PKEY_set1_RSA(newkey, rsa); 323999ebb4caSwyllys 3240*300fdee2SAndy Fiddaman cleanup: 324199ebb4caSwyllys /* The original key must be freed once here or it leaks memory */ 3242*300fdee2SAndy Fiddaman if (rsa) 324399ebb4caSwyllys RSA_free(rsa); 3244*300fdee2SAndy Fiddaman BN_free(n); 3245*300fdee2SAndy Fiddaman BN_free(e); 3246*300fdee2SAndy Fiddaman BN_free(d); 3247*300fdee2SAndy Fiddaman BN_free(p); 3248*300fdee2SAndy Fiddaman BN_free(q); 3249*300fdee2SAndy Fiddaman BN_free(dmp1); 3250*300fdee2SAndy Fiddaman BN_free(dmq1); 3251*300fdee2SAndy Fiddaman BN_free(iqmp); 325299ebb4caSwyllys 325399ebb4caSwyllys return (newkey); 325499ebb4caSwyllys } 325599ebb4caSwyllys 325699ebb4caSwyllys static EVP_PKEY * 325799ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key) 325899ebb4caSwyllys { 325999ebb4caSwyllys DSA *dsa = NULL; 326099ebb4caSwyllys EVP_PKEY *newkey = NULL; 3261*300fdee2SAndy Fiddaman BIGNUM *p = NULL, *q = NULL, *g = NULL, 3262*300fdee2SAndy Fiddaman *priv_key = NULL, *pub_key = NULL; 326399ebb4caSwyllys 326499ebb4caSwyllys if ((dsa = DSA_new()) == NULL) 3265*300fdee2SAndy Fiddaman goto cleanup; 326699ebb4caSwyllys 3267*300fdee2SAndy Fiddaman if ((p = BN_bin2bn(key->prime.val, key->prime.len, NULL)) == NULL) 3268*300fdee2SAndy Fiddaman goto cleanup; 326999ebb4caSwyllys 3270*300fdee2SAndy Fiddaman if ((q = BN_bin2bn(key->subprime.val, key->subprime.len, NULL)) == NULL) 3271*300fdee2SAndy Fiddaman goto cleanup; 327299ebb4caSwyllys 3273*300fdee2SAndy Fiddaman if ((g = BN_bin2bn(key->base.val, key->base.len, NULL)) == NULL) 3274*300fdee2SAndy Fiddaman goto cleanup; 327599ebb4caSwyllys 3276*300fdee2SAndy Fiddaman if ((priv_key = BN_bin2bn(key->value.val, key->value.len, 3277*300fdee2SAndy Fiddaman NULL)) == NULL) 3278*300fdee2SAndy Fiddaman goto cleanup; 327999ebb4caSwyllys 3280*300fdee2SAndy Fiddaman if (key->pubvalue.val != NULL && (pub_key = 3281*300fdee2SAndy Fiddaman BN_bin2bn(key->pubvalue.val, key->pubvalue.len, NULL)) == NULL) 3282*300fdee2SAndy Fiddaman goto cleanup; 3283*300fdee2SAndy Fiddaman 3284*300fdee2SAndy Fiddaman if (DSA_set0_pqg(dsa, p, q, g) == 0) 3285*300fdee2SAndy Fiddaman goto cleanup; 3286*300fdee2SAndy Fiddaman p = q = g = NULL; 3287*300fdee2SAndy Fiddaman if (DSA_set0_key(dsa, pub_key, priv_key) == 0) 3288*300fdee2SAndy Fiddaman goto cleanup; 3289*300fdee2SAndy Fiddaman pub_key = priv_key = 0; 329030a5e8faSwyllys 329199ebb4caSwyllys if ((newkey = EVP_PKEY_new()) == NULL) 3292*300fdee2SAndy Fiddaman goto cleanup; 329399ebb4caSwyllys 329499ebb4caSwyllys (void) EVP_PKEY_set1_DSA(newkey, dsa); 329599ebb4caSwyllys 3296*300fdee2SAndy Fiddaman cleanup: 329799ebb4caSwyllys /* The original key must be freed once here or it leaks memory */ 3298*300fdee2SAndy Fiddaman if (dsa) 329999ebb4caSwyllys DSA_free(dsa); 3300*300fdee2SAndy Fiddaman BN_free(p); 3301*300fdee2SAndy Fiddaman BN_free(q); 3302*300fdee2SAndy Fiddaman BN_free(g); 3303*300fdee2SAndy Fiddaman BN_free(priv_key); 3304*300fdee2SAndy Fiddaman BN_free(pub_key); 3305*300fdee2SAndy Fiddaman 330699ebb4caSwyllys return (newkey); 330799ebb4caSwyllys } 330899ebb4caSwyllys 33095b3e1433Swyllys static EVP_PKEY * 33105b3e1433Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key) 33115b3e1433Swyllys { 33125b3e1433Swyllys EVP_PKEY *pkey = NULL; 33135b3e1433Swyllys KMF_RAW_KEY_DATA *rawkey; 33145b3e1433Swyllys ASN1_TYPE *attr = NULL; 33155b3e1433Swyllys KMF_RETURN ret; 33165b3e1433Swyllys 33175b3e1433Swyllys if (key == NULL || !key->israw) 33185b3e1433Swyllys return (NULL); 33195b3e1433Swyllys 33205b3e1433Swyllys rawkey = (KMF_RAW_KEY_DATA *)key->keyp; 33215b3e1433Swyllys if (rawkey->keytype == KMF_RSA) { 33225b3e1433Swyllys pkey = ImportRawRSAKey(&rawkey->rawdata.rsa); 33235b3e1433Swyllys } else if (rawkey->keytype == KMF_DSA) { 33245b3e1433Swyllys pkey = ImportRawDSAKey(&rawkey->rawdata.dsa); 3325e65e5c2dSWyllys Ingersoll } else if (rawkey->keytype == KMF_ECDSA) { 3326e65e5c2dSWyllys Ingersoll /* 3327e65e5c2dSWyllys Ingersoll * OpenSSL in Solaris does not support EC for 3328e65e5c2dSWyllys Ingersoll * legal reasons 3329e65e5c2dSWyllys Ingersoll */ 3330e65e5c2dSWyllys Ingersoll return (NULL); 33315b3e1433Swyllys } else { 33325b3e1433Swyllys /* wrong kind of key */ 33335b3e1433Swyllys return (NULL); 33345b3e1433Swyllys } 33355b3e1433Swyllys 33365b3e1433Swyllys if (rawkey->label != NULL) { 33375b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) { 33385b3e1433Swyllys EVP_PKEY_free(pkey); 33395b3e1433Swyllys return (NULL); 33405b3e1433Swyllys } 33415b3e1433Swyllys attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING); 33425b3e1433Swyllys (void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label, 33435b3e1433Swyllys strlen(rawkey->label)); 33445b3e1433Swyllys attr->type = V_ASN1_BMPSTRING; 33455b3e1433Swyllys attr->value.ptr = (char *)attr->value.bmpstring; 33465b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_friendlyName); 33475b3e1433Swyllys if (ret != KMF_OK) { 33485b3e1433Swyllys EVP_PKEY_free(pkey); 33495b3e1433Swyllys ASN1_TYPE_free(attr); 33505b3e1433Swyllys return (NULL); 33515b3e1433Swyllys } 33525b3e1433Swyllys } 33535b3e1433Swyllys if (rawkey->id.Data != NULL) { 33545b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) { 33555b3e1433Swyllys EVP_PKEY_free(pkey); 33565b3e1433Swyllys return (NULL); 33575b3e1433Swyllys } 33585b3e1433Swyllys attr->value.octet_string = 33595b3e1433Swyllys ASN1_STRING_type_new(V_ASN1_OCTET_STRING); 33605b3e1433Swyllys attr->type = V_ASN1_OCTET_STRING; 33615b3e1433Swyllys (void) ASN1_STRING_set(attr->value.octet_string, 33625b3e1433Swyllys rawkey->id.Data, rawkey->id.Length); 33635b3e1433Swyllys attr->value.ptr = (char *)attr->value.octet_string; 33645b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_localKeyID); 33655b3e1433Swyllys if (ret != KMF_OK) { 33665b3e1433Swyllys EVP_PKEY_free(pkey); 33675b3e1433Swyllys ASN1_TYPE_free(attr); 33685b3e1433Swyllys return (NULL); 33695b3e1433Swyllys } 33705b3e1433Swyllys } 33715b3e1433Swyllys return (pkey); 33725b3e1433Swyllys } 33735b3e1433Swyllys 33745b3e1433Swyllys /* 33755b3e1433Swyllys * Search a list of private keys to find one that goes with the certificate. 33765b3e1433Swyllys */ 33775b3e1433Swyllys static EVP_PKEY * 33785b3e1433Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist) 33795b3e1433Swyllys { 33805b3e1433Swyllys int i; 33815b3e1433Swyllys EVP_PKEY *pkey = NULL; 33825b3e1433Swyllys 33835b3e1433Swyllys if (numkeys == 0 || keylist == NULL || xcert == NULL) 33845b3e1433Swyllys return (NULL); 33855b3e1433Swyllys for (i = 0; i < numkeys; i++) { 33865b3e1433Swyllys if (keylist[i].israw) 33875b3e1433Swyllys pkey = raw_key_to_pkey(&keylist[i]); 33885b3e1433Swyllys else 33895b3e1433Swyllys pkey = (EVP_PKEY *)keylist[i].keyp; 33905b3e1433Swyllys if (pkey != NULL) { 33915b3e1433Swyllys if (X509_check_private_key(xcert, pkey)) { 33925b3e1433Swyllys return (pkey); 33935b3e1433Swyllys } else { 33945b3e1433Swyllys EVP_PKEY_free(pkey); 33955b3e1433Swyllys pkey = NULL; 33965b3e1433Swyllys } 33975b3e1433Swyllys } 33985b3e1433Swyllys } 33995b3e1433Swyllys return (pkey); 34005b3e1433Swyllys } 34015b3e1433Swyllys 340299ebb4caSwyllys static KMF_RETURN 34035b3e1433Swyllys local_export_pk12(KMF_HANDLE_T handle, 340499ebb4caSwyllys KMF_CREDENTIAL *cred, 340599ebb4caSwyllys int numcerts, KMF_X509_DER_CERT *certlist, 340699ebb4caSwyllys int numkeys, KMF_KEY_HANDLE *keylist, 340799ebb4caSwyllys char *filename) 340899ebb4caSwyllys { 340999ebb4caSwyllys KMF_RETURN rv = KMF_OK; 341099ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 341199ebb4caSwyllys BIO *bio = NULL; 34125b3e1433Swyllys PKCS7 *cert_authsafe = NULL; 34135b3e1433Swyllys PKCS7 *key_authsafe = NULL; 34145b3e1433Swyllys STACK_OF(PKCS7) *authsafe_stack = NULL; 34155b3e1433Swyllys PKCS12 *p12_elem = NULL; 341699ebb4caSwyllys int i; 341799ebb4caSwyllys 34185b3e1433Swyllys if (numcerts == 0 && numkeys == 0) 34195b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 34205b3e1433Swyllys 342199ebb4caSwyllys /* 342299ebb4caSwyllys * Open the output file. 342399ebb4caSwyllys */ 342499ebb4caSwyllys if ((bio = BIO_new_file(filename, "wb")) == NULL) { 342599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 342699ebb4caSwyllys rv = KMF_ERR_OPEN_FILE; 342799ebb4caSwyllys goto cleanup; 342899ebb4caSwyllys } 342999ebb4caSwyllys 34305b3e1433Swyllys /* Start a PKCS#7 stack. */ 34315b3e1433Swyllys authsafe_stack = sk_PKCS7_new_null(); 34325b3e1433Swyllys if (authsafe_stack == NULL) { 34335b3e1433Swyllys rv = KMF_ERR_MEMORY; 34345b3e1433Swyllys goto cleanup; 34355b3e1433Swyllys } 34365b3e1433Swyllys if (numcerts > 0) { 343799ebb4caSwyllys for (i = 0; rv == KMF_OK && i < numcerts; i++) { 343899ebb4caSwyllys const uchar_t *p = certlist[i].certificate.Data; 343999ebb4caSwyllys long len = certlist[i].certificate.Length; 34405b3e1433Swyllys X509 *xcert = NULL; 34415b3e1433Swyllys EVP_PKEY *pkey = NULL; 34425b3e1433Swyllys unsigned char keyid[EVP_MAX_MD_SIZE]; 34435b3e1433Swyllys unsigned int keyidlen = 0; 344499ebb4caSwyllys 344599ebb4caSwyllys xcert = d2i_X509(NULL, &p, len); 344699ebb4caSwyllys if (xcert == NULL) { 344799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 344899ebb4caSwyllys rv = KMF_ERR_ENCODING; 344999ebb4caSwyllys } 34505b3e1433Swyllys if (certlist[i].kmf_private.label != NULL) { 34515b3e1433Swyllys /* Set alias attribute */ 34525b3e1433Swyllys (void) X509_alias_set1(xcert, 34535b3e1433Swyllys (uchar_t *)certlist[i].kmf_private.label, 34545b3e1433Swyllys strlen(certlist[i].kmf_private.label)); 34555b3e1433Swyllys } 34565b3e1433Swyllys /* Check if there is a key corresponding to this cert */ 34575b3e1433Swyllys pkey = find_matching_key(xcert, numkeys, keylist); 34585b3e1433Swyllys 34595b3e1433Swyllys /* 34605b3e1433Swyllys * If key is found, get fingerprint and create a 34615b3e1433Swyllys * safebag. 34625b3e1433Swyllys */ 34635b3e1433Swyllys if (pkey != NULL) { 34645b3e1433Swyllys (void) X509_digest(xcert, EVP_sha1(), 34655b3e1433Swyllys keyid, &keyidlen); 34665b3e1433Swyllys key_authsafe = add_key_to_safe(pkey, cred, 34675b3e1433Swyllys keyid, keyidlen, 34685b3e1433Swyllys certlist[i].kmf_private.label, 34695b3e1433Swyllys (certlist[i].kmf_private.label ? 34705b3e1433Swyllys strlen(certlist[i].kmf_private.label) : 0)); 34715b3e1433Swyllys 34725b3e1433Swyllys if (key_authsafe == NULL) { 34735b3e1433Swyllys X509_free(xcert); 34745b3e1433Swyllys EVP_PKEY_free(pkey); 34755b3e1433Swyllys goto cleanup; 34765b3e1433Swyllys } 34775b3e1433Swyllys /* Put the key safe into the Auth Safe */ 34785b3e1433Swyllys if (!sk_PKCS7_push(authsafe_stack, 34795b3e1433Swyllys key_authsafe)) { 34805b3e1433Swyllys X509_free(xcert); 34815b3e1433Swyllys EVP_PKEY_free(pkey); 34825b3e1433Swyllys goto cleanup; 34835b3e1433Swyllys } 34845b3e1433Swyllys } 34855b3e1433Swyllys 34865b3e1433Swyllys /* create a certificate safebag */ 34875b3e1433Swyllys cert_authsafe = add_cert_to_safe(xcert, cred, keyid, 34885b3e1433Swyllys keyidlen); 34895b3e1433Swyllys if (cert_authsafe == NULL) { 34905b3e1433Swyllys X509_free(xcert); 34915b3e1433Swyllys EVP_PKEY_free(pkey); 34925b3e1433Swyllys goto cleanup; 34935b3e1433Swyllys } 34945b3e1433Swyllys if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) { 34955b3e1433Swyllys X509_free(xcert); 34965b3e1433Swyllys EVP_PKEY_free(pkey); 34975b3e1433Swyllys goto cleanup; 34985b3e1433Swyllys } 34995b3e1433Swyllys 350099ebb4caSwyllys X509_free(xcert); 350199ebb4caSwyllys if (pkey) 350299ebb4caSwyllys EVP_PKEY_free(pkey); 350399ebb4caSwyllys } 35045b3e1433Swyllys } else if (numcerts == 0 && numkeys > 0) { 35055b3e1433Swyllys /* 35065b3e1433Swyllys * If only adding keys to the file. 35075b3e1433Swyllys */ 35085b3e1433Swyllys for (i = 0; i < numkeys; i++) { 35095b3e1433Swyllys EVP_PKEY *pkey = NULL; 35105b3e1433Swyllys 35115b3e1433Swyllys if (keylist[i].israw) 35125b3e1433Swyllys pkey = raw_key_to_pkey(&keylist[i]); 35135b3e1433Swyllys else 35145b3e1433Swyllys pkey = (EVP_PKEY *)keylist[i].keyp; 35155b3e1433Swyllys 35165b3e1433Swyllys if (pkey == NULL) 35175b3e1433Swyllys continue; 35185b3e1433Swyllys 35195b3e1433Swyllys key_authsafe = add_key_to_safe(pkey, cred, 35205b3e1433Swyllys NULL, 0, NULL, 0); 35215b3e1433Swyllys 35225b3e1433Swyllys if (key_authsafe == NULL) { 35235b3e1433Swyllys EVP_PKEY_free(pkey); 35245b3e1433Swyllys goto cleanup; 35255b3e1433Swyllys } 35265b3e1433Swyllys if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) { 35275b3e1433Swyllys EVP_PKEY_free(pkey); 35285b3e1433Swyllys goto cleanup; 35295b3e1433Swyllys } 35305b3e1433Swyllys } 35315b3e1433Swyllys } 35325b3e1433Swyllys p12_elem = PKCS12_init(NID_pkcs7_data); 35335b3e1433Swyllys if (p12_elem == NULL) { 35345b3e1433Swyllys goto cleanup; 353599ebb4caSwyllys } 353699ebb4caSwyllys 35375b3e1433Swyllys /* Put the PKCS#7 stack into the PKCS#12 element. */ 35385b3e1433Swyllys if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) { 35395b3e1433Swyllys goto cleanup; 35405b3e1433Swyllys } 35415b3e1433Swyllys 35425b3e1433Swyllys /* Set the integrity MAC on the PKCS#12 element. */ 35435b3e1433Swyllys if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen, 35445b3e1433Swyllys NULL, 0, PKCS12_DEFAULT_ITER, NULL)) { 35455b3e1433Swyllys goto cleanup; 35465b3e1433Swyllys } 35475b3e1433Swyllys 35485b3e1433Swyllys /* Write the PKCS#12 element to the export file. */ 35495b3e1433Swyllys if (!i2d_PKCS12_bio(bio, p12_elem)) { 35505b3e1433Swyllys goto cleanup; 35515b3e1433Swyllys } 35525b3e1433Swyllys PKCS12_free(p12_elem); 35535b3e1433Swyllys 355499ebb4caSwyllys cleanup: 35555b3e1433Swyllys /* Clear away the PKCS#7 stack, we're done with it. */ 35565b3e1433Swyllys if (authsafe_stack) 35575b3e1433Swyllys sk_PKCS7_pop_free(authsafe_stack, PKCS7_free); 355899ebb4caSwyllys 355999ebb4caSwyllys if (bio != NULL) 356099ebb4caSwyllys (void) BIO_free_all(bio); 356199ebb4caSwyllys 356299ebb4caSwyllys return (rv); 356399ebb4caSwyllys } 356499ebb4caSwyllys 356599ebb4caSwyllys KMF_RETURN 356630a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts, 356730a5e8faSwyllys KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist, 356830a5e8faSwyllys KMF_CREDENTIAL *p12cred, char *filename) 356930a5e8faSwyllys { 357030a5e8faSwyllys KMF_RETURN rv; 357130a5e8faSwyllys 357230a5e8faSwyllys if (certlist == NULL && keylist == NULL) 357330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 357430a5e8faSwyllys 35755b3e1433Swyllys rv = local_export_pk12(handle, p12cred, numcerts, certlist, 357630a5e8faSwyllys numkeys, keylist, filename); 357730a5e8faSwyllys 357830a5e8faSwyllys return (rv); 357930a5e8faSwyllys } 358030a5e8faSwyllys 358130a5e8faSwyllys KMF_RETURN 358230a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 358399ebb4caSwyllys { 358499ebb4caSwyllys KMF_RETURN rv; 358599ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 358699ebb4caSwyllys char *fullpath = NULL; 358730a5e8faSwyllys char *dirpath = NULL; 358830a5e8faSwyllys char *certfile = NULL; 358930a5e8faSwyllys char *keyfile = NULL; 359030a5e8faSwyllys char *filename = NULL; 359130a5e8faSwyllys KMF_CREDENTIAL *p12cred = NULL; 35925b3e1433Swyllys KMF_X509_DER_CERT certdata; 35935b3e1433Swyllys KMF_KEY_HANDLE key; 35945b3e1433Swyllys int gotkey = 0; 35955b3e1433Swyllys int gotcert = 0; 359630a5e8faSwyllys 359730a5e8faSwyllys if (handle == NULL) 359830a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 359999ebb4caSwyllys 360099ebb4caSwyllys /* 360199ebb4caSwyllys * First, find the certificate. 360299ebb4caSwyllys */ 360330a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 360430a5e8faSwyllys certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr); 360530a5e8faSwyllys if (certfile != NULL) { 360630a5e8faSwyllys fullpath = get_fullpath(dirpath, certfile); 360799ebb4caSwyllys if (fullpath == NULL) 360899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 360999ebb4caSwyllys 361099ebb4caSwyllys if (isdir(fullpath)) { 361199ebb4caSwyllys free(fullpath); 361299ebb4caSwyllys return (KMF_ERR_AMBIGUOUS_PATHNAME); 361399ebb4caSwyllys } 361499ebb4caSwyllys 36155b3e1433Swyllys (void) memset(&certdata, 0, sizeof (certdata)); 36165b3e1433Swyllys rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL, 36175b3e1433Swyllys fullpath, &certdata.certificate); 361899ebb4caSwyllys if (rv != KMF_OK) 361999ebb4caSwyllys goto end; 362030a5e8faSwyllys 36215b3e1433Swyllys gotcert++; 36225b3e1433Swyllys certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL; 362330a5e8faSwyllys free(fullpath); 362499ebb4caSwyllys } 362599ebb4caSwyllys 362699ebb4caSwyllys /* 362799ebb4caSwyllys * Now find the private key. 362899ebb4caSwyllys */ 362930a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 363030a5e8faSwyllys if (keyfile != NULL) { 363130a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 363299ebb4caSwyllys if (fullpath == NULL) 363399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 363499ebb4caSwyllys 363599ebb4caSwyllys if (isdir(fullpath)) { 363699ebb4caSwyllys free(fullpath); 363799ebb4caSwyllys return (KMF_ERR_AMBIGUOUS_PATHNAME); 363899ebb4caSwyllys } 363999ebb4caSwyllys 36405b3e1433Swyllys (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE)); 36415b3e1433Swyllys rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key); 36425b3e1433Swyllys if (rv != KMF_OK) 364399ebb4caSwyllys goto end; 36445b3e1433Swyllys gotkey++; 364599ebb4caSwyllys } 364699ebb4caSwyllys 364799ebb4caSwyllys /* 364899ebb4caSwyllys * Open the output file. 364999ebb4caSwyllys */ 365030a5e8faSwyllys filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist, 365130a5e8faSwyllys numattr); 365230a5e8faSwyllys if (filename == NULL) { 365330a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 365430a5e8faSwyllys goto end; 365530a5e8faSwyllys } 365630a5e8faSwyllys 365799ebb4caSwyllys /* Stick the key and the cert into a PKCS#12 file */ 365830a5e8faSwyllys p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr); 365930a5e8faSwyllys if (p12cred == NULL) { 366030a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 366130a5e8faSwyllys goto end; 366230a5e8faSwyllys } 366330a5e8faSwyllys 36645b3e1433Swyllys rv = local_export_pk12(handle, p12cred, 1, &certdata, 36655b3e1433Swyllys 1, &key, filename); 366699ebb4caSwyllys 366799ebb4caSwyllys end: 366899ebb4caSwyllys if (fullpath) 366999ebb4caSwyllys free(fullpath); 367099ebb4caSwyllys 36715b3e1433Swyllys if (gotcert) 36725b3e1433Swyllys kmf_free_kmf_cert(handle, &certdata); 36735b3e1433Swyllys if (gotkey) 36745b3e1433Swyllys kmf_free_kmf_key(handle, &key); 367599ebb4caSwyllys return (rv); 367699ebb4caSwyllys } 367799ebb4caSwyllys 367871593db2Swyllys /* 367971593db2Swyllys * Helper function to extract keys and certificates from 368071593db2Swyllys * a single PEM file. Typically the file should contain a 368171593db2Swyllys * private key and an associated public key wrapped in an x509 cert. 368271593db2Swyllys * However, the file may be just a list of X509 certs with no keys. 368371593db2Swyllys */ 368471593db2Swyllys static KMF_RETURN 368530a5e8faSwyllys extract_pem(KMF_HANDLE *kmfh, 368630a5e8faSwyllys char *issuer, char *subject, KMF_BIGINT *serial, 368702744e81Swyllys char *filename, CK_UTF8CHAR *pin, 368871593db2Swyllys CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs, 368971593db2Swyllys int *numcerts) 3690a2d4930dSDan OpenSolaris Anderson /* ARGSUSED6 */ 369171593db2Swyllys { 369271593db2Swyllys KMF_RETURN rv = KMF_OK; 369371593db2Swyllys FILE *fp; 369434acef67Swyllys STACK_OF(X509_INFO) *x509_info_stack = NULL; 369502744e81Swyllys int i, ncerts = 0, matchcerts = 0; 369671593db2Swyllys EVP_PKEY *pkey = NULL; 369771593db2Swyllys X509_INFO *info; 369871593db2Swyllys X509 *x; 36995b3e1433Swyllys X509_INFO **cert_infos = NULL; 370071593db2Swyllys KMF_DATA *certlist = NULL; 370171593db2Swyllys 370271593db2Swyllys if (priv_key) 370371593db2Swyllys *priv_key = NULL; 370471593db2Swyllys if (certs) 370571593db2Swyllys *certs = NULL; 370671593db2Swyllys fp = fopen(filename, "r"); 37075b3e1433Swyllys if (fp == NULL) 370871593db2Swyllys return (KMF_ERR_OPEN_FILE); 37095b3e1433Swyllys 371071593db2Swyllys x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin); 371171593db2Swyllys if (x509_info_stack == NULL) { 371271593db2Swyllys (void) fclose(fp); 371371593db2Swyllys return (KMF_ERR_ENCODING); 371471593db2Swyllys } 37155b3e1433Swyllys cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) * 37165b3e1433Swyllys sizeof (X509_INFO *)); 37175b3e1433Swyllys if (cert_infos == NULL) { 37185b3e1433Swyllys (void) fclose(fp); 37195b3e1433Swyllys rv = KMF_ERR_MEMORY; 37205b3e1433Swyllys goto err; 37215b3e1433Swyllys } 372271593db2Swyllys 37235b3e1433Swyllys for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) { 3724d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 372534acef67Swyllys cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i); 372671593db2Swyllys ncerts++; 372771593db2Swyllys } 372871593db2Swyllys 372971593db2Swyllys if (ncerts == 0) { 373071593db2Swyllys (void) fclose(fp); 373134acef67Swyllys rv = KMF_ERR_CERT_NOT_FOUND; 373234acef67Swyllys goto err; 373371593db2Swyllys } 373471593db2Swyllys 373571593db2Swyllys if (priv_key != NULL) { 373671593db2Swyllys rewind(fp); 373771593db2Swyllys pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin); 373871593db2Swyllys } 373971593db2Swyllys (void) fclose(fp); 374071593db2Swyllys 374171593db2Swyllys x = cert_infos[ncerts - 1]->x509; 374271593db2Swyllys /* 374371593db2Swyllys * Make sure the private key matchs the last cert in the file. 374471593db2Swyllys */ 374571593db2Swyllys if (pkey != NULL && !X509_check_private_key(x, pkey)) { 374671593db2Swyllys EVP_PKEY_free(pkey); 374734acef67Swyllys rv = KMF_ERR_KEY_MISMATCH; 374834acef67Swyllys goto err; 374971593db2Swyllys } 375071593db2Swyllys 3751a2d4930dSDan OpenSolaris Anderson certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA)); 375271593db2Swyllys if (certlist == NULL) { 375371593db2Swyllys if (pkey != NULL) 375471593db2Swyllys EVP_PKEY_free(pkey); 375534acef67Swyllys rv = KMF_ERR_MEMORY; 375634acef67Swyllys goto err; 375771593db2Swyllys } 375871593db2Swyllys 375971593db2Swyllys /* 376071593db2Swyllys * Convert all of the certs to DER format. 376171593db2Swyllys */ 376202744e81Swyllys matchcerts = 0; 376371593db2Swyllys for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) { 376402744e81Swyllys boolean_t match = FALSE; 376571593db2Swyllys info = cert_infos[ncerts - 1 - i]; 376671593db2Swyllys 376730a5e8faSwyllys rv = check_cert(info->x509, issuer, subject, serial, &match); 376802744e81Swyllys if (rv != KMF_OK || match != TRUE) { 376902744e81Swyllys rv = KMF_OK; 377002744e81Swyllys continue; 377102744e81Swyllys } 377202744e81Swyllys 377302744e81Swyllys rv = ssl_cert2KMFDATA(kmfh, info->x509, 377402744e81Swyllys &certlist[matchcerts++]); 377571593db2Swyllys 377671593db2Swyllys if (rv != KMF_OK) { 3777e65e5c2dSWyllys Ingersoll int j; 3778e65e5c2dSWyllys Ingersoll for (j = 0; j < matchcerts; j++) 3779e65e5c2dSWyllys Ingersoll kmf_free_data(&certlist[j]); 378071593db2Swyllys free(certlist); 378171593db2Swyllys certlist = NULL; 378202744e81Swyllys ncerts = matchcerts = 0; 378371593db2Swyllys } 378471593db2Swyllys } 378571593db2Swyllys 378671593db2Swyllys if (numcerts != NULL) 378702744e81Swyllys *numcerts = matchcerts; 3788a2d4930dSDan OpenSolaris Anderson 3789e65e5c2dSWyllys Ingersoll if (certs != NULL) 379071593db2Swyllys *certs = certlist; 3791e65e5c2dSWyllys Ingersoll else if (certlist != NULL) { 3792e65e5c2dSWyllys Ingersoll for (i = 0; i < ncerts; i++) 3793e65e5c2dSWyllys Ingersoll kmf_free_data(&certlist[i]); 3794a2d4930dSDan OpenSolaris Anderson free(certlist); 3795a2d4930dSDan OpenSolaris Anderson certlist = NULL; 3796a2d4930dSDan OpenSolaris Anderson } 379771593db2Swyllys 379871593db2Swyllys if (priv_key == NULL && pkey != NULL) 379971593db2Swyllys EVP_PKEY_free(pkey); 380071593db2Swyllys else if (priv_key != NULL && pkey != NULL) 380171593db2Swyllys *priv_key = pkey; 380271593db2Swyllys 380334acef67Swyllys err: 380434acef67Swyllys /* Cleanup the stack of X509 info records */ 380534acef67Swyllys for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) { 3806d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 380734acef67Swyllys info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i); 380834acef67Swyllys X509_INFO_free(info); 380934acef67Swyllys } 381034acef67Swyllys if (x509_info_stack) 381134acef67Swyllys sk_X509_INFO_free(x509_info_stack); 381234acef67Swyllys 38135b3e1433Swyllys if (cert_infos != NULL) 38145b3e1433Swyllys free(cert_infos); 38155b3e1433Swyllys 381671593db2Swyllys return (rv); 381771593db2Swyllys } 381871593db2Swyllys 38195b3e1433Swyllys static KMF_RETURN 3820*300fdee2SAndy Fiddaman openssl_parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, char *pin, 38215b3e1433Swyllys STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs) 38225b3e1433Swyllys { 38235b3e1433Swyllys KMF_RETURN ret; 38245b3e1433Swyllys int i; 38255b3e1433Swyllys 38265b3e1433Swyllys for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { 3827d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 38285b3e1433Swyllys PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i); 38295b3e1433Swyllys ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0), 38305b3e1433Swyllys keys, certs); 38315b3e1433Swyllys 38325b3e1433Swyllys if (ret != KMF_OK) 38335b3e1433Swyllys return (ret); 38345b3e1433Swyllys } 38355b3e1433Swyllys 38365b3e1433Swyllys return (ret); 38375b3e1433Swyllys } 38385b3e1433Swyllys 38395b3e1433Swyllys static KMF_RETURN 38405b3e1433Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid) 38415b3e1433Swyllys { 38425b3e1433Swyllys X509_ATTRIBUTE *attr = NULL; 38435b3e1433Swyllys 38445b3e1433Swyllys if (pkey == NULL || attrib == NULL) 38455b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 38465b3e1433Swyllys 38475b3e1433Swyllys attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr); 38485b3e1433Swyllys if (attr != NULL) { 38495b3e1433Swyllys int i; 3850*300fdee2SAndy Fiddaman 3851*300fdee2SAndy Fiddaman if ((i = EVP_PKEY_get_attr_by_NID(pkey, nid, -1)) != -1) 3852*300fdee2SAndy Fiddaman (void) EVP_PKEY_delete_attr(pkey, i); 3853*300fdee2SAndy Fiddaman if (EVP_PKEY_add1_attr(pkey, attr) == 0) { 38545b3e1433Swyllys X509_ATTRIBUTE_free(attr); 38555b3e1433Swyllys return (KMF_ERR_MEMORY); 38565b3e1433Swyllys } 38575b3e1433Swyllys } else { 38585b3e1433Swyllys return (KMF_ERR_MEMORY); 38595b3e1433Swyllys } 38605b3e1433Swyllys 38615b3e1433Swyllys return (KMF_OK); 38625b3e1433Swyllys } 38635b3e1433Swyllys 38645b3e1433Swyllys static KMF_RETURN 38655b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen, 38665b3e1433Swyllys STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist) 38675b3e1433Swyllys { 38685b3e1433Swyllys KMF_RETURN ret = KMF_OK; 38695b3e1433Swyllys PKCS8_PRIV_KEY_INFO *p8 = NULL; 38705b3e1433Swyllys EVP_PKEY *pkey = NULL; 38715b3e1433Swyllys X509 *xcert = NULL; 3872*300fdee2SAndy Fiddaman const ASN1_TYPE *keyid = NULL; 3873*300fdee2SAndy Fiddaman const ASN1_TYPE *fname = NULL; 38745b3e1433Swyllys uchar_t *data = NULL; 38755b3e1433Swyllys 3876*300fdee2SAndy Fiddaman keyid = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID); 3877*300fdee2SAndy Fiddaman fname = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName); 38785b3e1433Swyllys 3879*300fdee2SAndy Fiddaman switch (PKCS12_SAFEBAG_get_nid(bag)) { 38805b3e1433Swyllys case NID_keyBag: 38815b3e1433Swyllys if (keylist == NULL) 38825b3e1433Swyllys goto end; 3883*300fdee2SAndy Fiddaman pkey = EVP_PKCS82PKEY( 3884*300fdee2SAndy Fiddaman PKCS12_SAFEBAG_get0_p8inf(bag)); 38855b3e1433Swyllys if (pkey == NULL) 38865b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 38875b3e1433Swyllys 38885b3e1433Swyllys break; 38895b3e1433Swyllys case NID_pkcs8ShroudedKeyBag: 38905b3e1433Swyllys if (keylist == NULL) 38915b3e1433Swyllys goto end; 3892*300fdee2SAndy Fiddaman p8 = PKCS12_decrypt_skey(bag, pass, passlen); 38935b3e1433Swyllys if (p8 == NULL) 38945b3e1433Swyllys return (KMF_ERR_AUTH_FAILED); 38955b3e1433Swyllys pkey = EVP_PKCS82PKEY(p8); 38965b3e1433Swyllys PKCS8_PRIV_KEY_INFO_free(p8); 38975b3e1433Swyllys if (pkey == NULL) 38985b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 38995b3e1433Swyllys break; 39005b3e1433Swyllys case NID_certBag: 39015b3e1433Swyllys if (certlist == NULL) 39025b3e1433Swyllys goto end; 3903*300fdee2SAndy Fiddaman if (PKCS12_SAFEBAG_get_bag_nid(bag) != 3904*300fdee2SAndy Fiddaman NID_x509Certificate) 39055b3e1433Swyllys return (KMF_ERR_PKCS12_FORMAT); 3906*300fdee2SAndy Fiddaman xcert = PKCS12_SAFEBAG_get1_cert(bag); 39075b3e1433Swyllys if (xcert == NULL) { 39085b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39095b3e1433Swyllys goto end; 39105b3e1433Swyllys } 39115b3e1433Swyllys if (keyid != NULL) { 39125b3e1433Swyllys if (X509_keyid_set1(xcert, 39135b3e1433Swyllys keyid->value.octet_string->data, 39145b3e1433Swyllys keyid->value.octet_string->length) == 0) { 39155b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39165b3e1433Swyllys goto end; 39175b3e1433Swyllys } 39185b3e1433Swyllys } 39195b3e1433Swyllys if (fname != NULL) { 39205b3e1433Swyllys int len, r; 39215b3e1433Swyllys len = ASN1_STRING_to_UTF8(&data, 39225b3e1433Swyllys fname->value.asn1_string); 39235b3e1433Swyllys if (len > 0 && data != NULL) { 39245b3e1433Swyllys r = X509_alias_set1(xcert, data, len); 39255b3e1433Swyllys if (r == NULL) { 39265b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39275b3e1433Swyllys goto end; 39285b3e1433Swyllys } 39295b3e1433Swyllys } else { 39305b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39315b3e1433Swyllys goto end; 39325b3e1433Swyllys } 39335b3e1433Swyllys } 39345b3e1433Swyllys if (sk_X509_push(certlist, xcert) == 0) 39355b3e1433Swyllys ret = KMF_ERR_MEMORY; 39365b3e1433Swyllys else 39375b3e1433Swyllys xcert = NULL; 39385b3e1433Swyllys break; 39395b3e1433Swyllys case NID_safeContentsBag: 3940*300fdee2SAndy Fiddaman return (openssl_parse_bags( 3941*300fdee2SAndy Fiddaman PKCS12_SAFEBAG_get0_safes(bag), 3942*300fdee2SAndy Fiddaman pass, keylist, certlist)); 39435b3e1433Swyllys default: 39445b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39455b3e1433Swyllys break; 39465b3e1433Swyllys } 39475b3e1433Swyllys 39485b3e1433Swyllys /* 39495b3e1433Swyllys * Set the ID and/or FriendlyName attributes on the key. 39505b3e1433Swyllys * If converting to PKCS11 objects, these can translate to CKA_ID 39515b3e1433Swyllys * and CKA_LABEL values. 39525b3e1433Swyllys */ 39535b3e1433Swyllys if (pkey != NULL && ret == KMF_OK) { 39545b3e1433Swyllys ASN1_TYPE *attr = NULL; 39555b3e1433Swyllys if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) { 39565b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) 39575b3e1433Swyllys return (KMF_ERR_MEMORY); 39585b3e1433Swyllys attr->value.octet_string = 39595b3e1433Swyllys ASN1_STRING_dup(keyid->value.octet_string); 39605b3e1433Swyllys attr->type = V_ASN1_OCTET_STRING; 39615b3e1433Swyllys attr->value.ptr = (char *)attr->value.octet_string; 39625b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_localKeyID); 39635b3e1433Swyllys OPENSSL_free(attr); 39645b3e1433Swyllys } 39655b3e1433Swyllys 39665b3e1433Swyllys if (ret == KMF_OK && fname != NULL && 39675b3e1433Swyllys fname->type == V_ASN1_BMPSTRING) { 39685b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) 39695b3e1433Swyllys return (KMF_ERR_MEMORY); 39705b3e1433Swyllys attr->value.bmpstring = 39715b3e1433Swyllys ASN1_STRING_dup(fname->value.bmpstring); 39725b3e1433Swyllys attr->type = V_ASN1_BMPSTRING; 39735b3e1433Swyllys attr->value.ptr = (char *)attr->value.bmpstring; 39745b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_friendlyName); 39755b3e1433Swyllys OPENSSL_free(attr); 39765b3e1433Swyllys } 39775b3e1433Swyllys 39785b3e1433Swyllys if (ret == KMF_OK && keylist != NULL && 39795b3e1433Swyllys sk_EVP_PKEY_push(keylist, pkey) == 0) 39805b3e1433Swyllys ret = KMF_ERR_MEMORY; 39815b3e1433Swyllys } 39825b3e1433Swyllys if (ret == KMF_OK && keylist != NULL) 39835b3e1433Swyllys pkey = NULL; 39845b3e1433Swyllys end: 39855b3e1433Swyllys if (pkey != NULL) 39865b3e1433Swyllys EVP_PKEY_free(pkey); 39875b3e1433Swyllys if (xcert != NULL) 39885b3e1433Swyllys X509_free(xcert); 39895b3e1433Swyllys if (data != NULL) 39905b3e1433Swyllys OPENSSL_free(data); 39915b3e1433Swyllys 39925b3e1433Swyllys return (ret); 39935b3e1433Swyllys } 39945b3e1433Swyllys 39955b3e1433Swyllys static KMF_RETURN 39965b3e1433Swyllys openssl_pkcs12_parse(PKCS12 *p12, char *pin, 39975b3e1433Swyllys STACK_OF(EVP_PKEY) *keys, 39985b3e1433Swyllys STACK_OF(X509) *certs, 39995b3e1433Swyllys STACK_OF(X509) *ca) 4000a2d4930dSDan OpenSolaris Anderson /* ARGSUSED3 */ 40015b3e1433Swyllys { 40025b3e1433Swyllys KMF_RETURN ret = KMF_OK; 40035b3e1433Swyllys STACK_OF(PKCS7) *asafes = NULL; 40045b3e1433Swyllys STACK_OF(PKCS12_SAFEBAG) *bags = NULL; 40055b3e1433Swyllys int i, bagnid; 40065b3e1433Swyllys PKCS7 *p7; 40075b3e1433Swyllys 40085b3e1433Swyllys if (p12 == NULL || (keys == NULL && certs == NULL)) 40095b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 40105b3e1433Swyllys 40115b3e1433Swyllys if (pin == NULL || *pin == NULL) { 40125b3e1433Swyllys if (PKCS12_verify_mac(p12, NULL, 0)) { 40135b3e1433Swyllys pin = NULL; 40145b3e1433Swyllys } else if (PKCS12_verify_mac(p12, "", 0)) { 40155b3e1433Swyllys pin = ""; 40165b3e1433Swyllys } else { 40175b3e1433Swyllys return (KMF_ERR_AUTH_FAILED); 40185b3e1433Swyllys } 40195b3e1433Swyllys } else if (!PKCS12_verify_mac(p12, pin, -1)) { 40205b3e1433Swyllys return (KMF_ERR_AUTH_FAILED); 40215b3e1433Swyllys } 40225b3e1433Swyllys 40235b3e1433Swyllys if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) 40245b3e1433Swyllys return (KMF_ERR_PKCS12_FORMAT); 40255b3e1433Swyllys 40265b3e1433Swyllys for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) { 40275b3e1433Swyllys bags = NULL; 4028d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 40295b3e1433Swyllys p7 = sk_PKCS7_value(asafes, i); 40305b3e1433Swyllys bagnid = OBJ_obj2nid(p7->type); 40315b3e1433Swyllys 40325b3e1433Swyllys if (bagnid == NID_pkcs7_data) { 40335b3e1433Swyllys bags = PKCS12_unpack_p7data(p7); 40345b3e1433Swyllys } else if (bagnid == NID_pkcs7_encrypted) { 40355b3e1433Swyllys bags = PKCS12_unpack_p7encdata(p7, pin, 40365b3e1433Swyllys (pin ? strlen(pin) : 0)); 40375b3e1433Swyllys } else { 40385b3e1433Swyllys continue; 40395b3e1433Swyllys } 40405b3e1433Swyllys if (bags == NULL) { 40415b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 40425b3e1433Swyllys goto out; 40435b3e1433Swyllys } 40445b3e1433Swyllys 40455b3e1433Swyllys if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK) 40465b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 40475b3e1433Swyllys 40485b3e1433Swyllys sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 40495b3e1433Swyllys } 40505b3e1433Swyllys out: 40515b3e1433Swyllys if (asafes != NULL) 40525b3e1433Swyllys sk_PKCS7_pop_free(asafes, PKCS7_free); 40535b3e1433Swyllys 40545b3e1433Swyllys return (ret); 40555b3e1433Swyllys } 40565b3e1433Swyllys 405799ebb4caSwyllys /* 405899ebb4caSwyllys * Helper function to decrypt and parse PKCS#12 import file. 405999ebb4caSwyllys */ 406099ebb4caSwyllys static KMF_RETURN 406199ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen, 40625b3e1433Swyllys STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs, 40635b3e1433Swyllys STACK_OF(X509) **ca) 4064a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */ 406599ebb4caSwyllys { 406699ebb4caSwyllys PKCS12 *pk12, *pk12_tmp; 40675b3e1433Swyllys STACK_OF(EVP_PKEY) *pkeylist = NULL; 40685b3e1433Swyllys STACK_OF(X509) *xcertlist = NULL; 40695b3e1433Swyllys STACK_OF(X509) *cacertlist = NULL; 407099ebb4caSwyllys 407199ebb4caSwyllys if ((pk12 = PKCS12_new()) == NULL) { 407299ebb4caSwyllys return (KMF_ERR_MEMORY); 407399ebb4caSwyllys } 407499ebb4caSwyllys 407599ebb4caSwyllys if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) { 407699ebb4caSwyllys /* This is ok; it seems to mean there is no more to read. */ 407799ebb4caSwyllys if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 && 407899ebb4caSwyllys ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG) 407999ebb4caSwyllys goto end_extract_pkcs12; 408099ebb4caSwyllys 408199ebb4caSwyllys PKCS12_free(pk12); 408299ebb4caSwyllys return (KMF_ERR_PKCS12_FORMAT); 408399ebb4caSwyllys } 408499ebb4caSwyllys pk12 = pk12_tmp; 408599ebb4caSwyllys 40865b3e1433Swyllys xcertlist = sk_X509_new_null(); 40875b3e1433Swyllys if (xcertlist == NULL) { 40885b3e1433Swyllys PKCS12_free(pk12); 40895b3e1433Swyllys return (KMF_ERR_MEMORY); 40905b3e1433Swyllys } 40915b3e1433Swyllys pkeylist = sk_EVP_PKEY_new_null(); 40925b3e1433Swyllys if (pkeylist == NULL) { 40935b3e1433Swyllys sk_X509_pop_free(xcertlist, X509_free); 40945b3e1433Swyllys PKCS12_free(pk12); 40955b3e1433Swyllys return (KMF_ERR_MEMORY); 40965b3e1433Swyllys } 40975b3e1433Swyllys 40985b3e1433Swyllys if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist, 40995b3e1433Swyllys cacertlist) != KMF_OK) { 41005b3e1433Swyllys sk_X509_pop_free(xcertlist, X509_free); 41015b3e1433Swyllys sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free); 410299ebb4caSwyllys PKCS12_free(pk12); 410399ebb4caSwyllys return (KMF_ERR_PKCS12_FORMAT); 410499ebb4caSwyllys } 410599ebb4caSwyllys 41065b3e1433Swyllys if (priv_key && pkeylist) 41075b3e1433Swyllys *priv_key = pkeylist; 41085b3e1433Swyllys else if (pkeylist) 41095b3e1433Swyllys sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free); 41105b3e1433Swyllys if (certs && xcertlist) 41115b3e1433Swyllys *certs = xcertlist; 41125b3e1433Swyllys else if (xcertlist) 41135b3e1433Swyllys sk_X509_pop_free(xcertlist, X509_free); 41145b3e1433Swyllys if (ca && cacertlist) 41155b3e1433Swyllys *ca = cacertlist; 41165b3e1433Swyllys else if (cacertlist) 41175b3e1433Swyllys sk_X509_pop_free(cacertlist, X509_free); 411899ebb4caSwyllys 41195b3e1433Swyllys end_extract_pkcs12: 412099ebb4caSwyllys 412199ebb4caSwyllys PKCS12_free(pk12); 412299ebb4caSwyllys return (KMF_OK); 412399ebb4caSwyllys } 412499ebb4caSwyllys 412599ebb4caSwyllys static KMF_RETURN 412699ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to) 412799ebb4caSwyllys { 412899ebb4caSwyllys KMF_RETURN rv = KMF_OK; 412999ebb4caSwyllys uint32_t sz; 413099ebb4caSwyllys 413199ebb4caSwyllys sz = BN_num_bytes(from); 413299ebb4caSwyllys to->val = (uchar_t *)malloc(sz); 413399ebb4caSwyllys if (to->val == NULL) 413499ebb4caSwyllys return (KMF_ERR_MEMORY); 413599ebb4caSwyllys 413699ebb4caSwyllys if ((to->len = BN_bn2bin(from, to->val)) != sz) { 413799ebb4caSwyllys free(to->val); 413899ebb4caSwyllys to->val = NULL; 413999ebb4caSwyllys to->len = 0; 414099ebb4caSwyllys rv = KMF_ERR_MEMORY; 414199ebb4caSwyllys } 414299ebb4caSwyllys 414399ebb4caSwyllys return (rv); 414499ebb4caSwyllys } 414599ebb4caSwyllys 414699ebb4caSwyllys static KMF_RETURN 414799ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key) 414899ebb4caSwyllys { 414999ebb4caSwyllys KMF_RETURN rv; 415099ebb4caSwyllys KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa; 415199ebb4caSwyllys 4152*300fdee2SAndy Fiddaman const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmpq, *iqmp; 4153*300fdee2SAndy Fiddaman 4154*300fdee2SAndy Fiddaman RSA_get0_key(rsa, &n, &e, &d); 4155*300fdee2SAndy Fiddaman RSA_get0_factors(rsa, &p, &q); 4156*300fdee2SAndy Fiddaman RSA_get0_crt_params(rsa, &dmp1, &dmpq, &iqmp); 4157*300fdee2SAndy Fiddaman 415899ebb4caSwyllys (void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY)); 4159*300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)n, &kmfkey->mod)) != KMF_OK) 416099ebb4caSwyllys goto cleanup; 416199ebb4caSwyllys 4162*300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)e, &kmfkey->pubexp)) != KMF_OK) 416399ebb4caSwyllys goto cleanup; 416499ebb4caSwyllys 4165*300fdee2SAndy Fiddaman if (d != NULL) 4166*300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)d, &kmfkey->priexp)) != KMF_OK) 416799ebb4caSwyllys goto cleanup; 416899ebb4caSwyllys 4169*300fdee2SAndy Fiddaman if (p != NULL) 4170*300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime1)) != KMF_OK) 417199ebb4caSwyllys goto cleanup; 417299ebb4caSwyllys 4173*300fdee2SAndy Fiddaman if (q != NULL) 4174*300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->prime2)) != KMF_OK) 417599ebb4caSwyllys goto cleanup; 417699ebb4caSwyllys 4177*300fdee2SAndy Fiddaman if (dmp1 != NULL) 4178*300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)dmp1, &kmfkey->exp1)) != KMF_OK) 417999ebb4caSwyllys goto cleanup; 418099ebb4caSwyllys 4181*300fdee2SAndy Fiddaman if (dmpq != NULL) 4182*300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)dmpq, &kmfkey->exp2)) != KMF_OK) 418399ebb4caSwyllys goto cleanup; 418499ebb4caSwyllys 4185*300fdee2SAndy Fiddaman if (iqmp != NULL) 4186*300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)iqmp, &kmfkey->coef)) != KMF_OK) 418799ebb4caSwyllys goto cleanup; 418899ebb4caSwyllys cleanup: 418999ebb4caSwyllys if (rv != KMF_OK) 419030a5e8faSwyllys kmf_free_raw_key(key); 419199ebb4caSwyllys else 419299ebb4caSwyllys key->keytype = KMF_RSA; 419399ebb4caSwyllys 419499ebb4caSwyllys /* 419599ebb4caSwyllys * Free the reference to this key, SSL will not actually free 419699ebb4caSwyllys * the memory until the refcount == 0, so this is safe. 419799ebb4caSwyllys */ 419899ebb4caSwyllys RSA_free(rsa); 419999ebb4caSwyllys 420099ebb4caSwyllys return (rv); 420199ebb4caSwyllys } 420299ebb4caSwyllys 420399ebb4caSwyllys static KMF_RETURN 420499ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key) 420599ebb4caSwyllys { 420699ebb4caSwyllys KMF_RETURN rv; 420799ebb4caSwyllys KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa; 4208*300fdee2SAndy Fiddaman const BIGNUM *p, *q, *g, *priv_key; 4209*300fdee2SAndy Fiddaman 4210*300fdee2SAndy Fiddaman DSA_get0_pqg(dsa, &p, &q, &g); 4211*300fdee2SAndy Fiddaman DSA_get0_key(dsa, NULL, &priv_key); 421299ebb4caSwyllys 421399ebb4caSwyllys (void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY)); 4214*300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime)) != KMF_OK) 421599ebb4caSwyllys goto cleanup; 421699ebb4caSwyllys 4217*300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->subprime)) != KMF_OK) 421899ebb4caSwyllys goto cleanup; 421999ebb4caSwyllys 4220*300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)g, &kmfkey->base)) != KMF_OK) 422199ebb4caSwyllys goto cleanup; 422299ebb4caSwyllys 4223*300fdee2SAndy Fiddaman if ((rv = sslBN2KMFBN((BIGNUM *)priv_key, &kmfkey->value)) != KMF_OK) 422499ebb4caSwyllys goto cleanup; 422599ebb4caSwyllys 422699ebb4caSwyllys cleanup: 422799ebb4caSwyllys if (rv != KMF_OK) 422830a5e8faSwyllys kmf_free_raw_key(key); 422999ebb4caSwyllys else 423099ebb4caSwyllys key->keytype = KMF_DSA; 423199ebb4caSwyllys 423299ebb4caSwyllys /* 423399ebb4caSwyllys * Free the reference to this key, SSL will not actually free 423499ebb4caSwyllys * the memory until the refcount == 0, so this is safe. 423599ebb4caSwyllys */ 423699ebb4caSwyllys DSA_free(dsa); 423799ebb4caSwyllys 423899ebb4caSwyllys return (rv); 423999ebb4caSwyllys } 424099ebb4caSwyllys 424199ebb4caSwyllys static KMF_RETURN 424299ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert, 42435b3e1433Swyllys KMF_X509_DER_CERT **certlist, int *ncerts) 424499ebb4caSwyllys { 424599ebb4caSwyllys KMF_RETURN rv = KMF_OK; 42465b3e1433Swyllys KMF_X509_DER_CERT *list = (*certlist); 42475b3e1433Swyllys KMF_X509_DER_CERT cert; 424899ebb4caSwyllys int n = (*ncerts); 424999ebb4caSwyllys 425099ebb4caSwyllys if (list == NULL) { 42515b3e1433Swyllys list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT)); 425299ebb4caSwyllys } else { 42535b3e1433Swyllys list = (KMF_X509_DER_CERT *)realloc(list, 42545b3e1433Swyllys sizeof (KMF_X509_DER_CERT) * (n + 1)); 425599ebb4caSwyllys } 425699ebb4caSwyllys 425799ebb4caSwyllys if (list == NULL) 425899ebb4caSwyllys return (KMF_ERR_MEMORY); 425999ebb4caSwyllys 42605b3e1433Swyllys (void) memset(&cert, 0, sizeof (cert)); 42615b3e1433Swyllys rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate); 426299ebb4caSwyllys if (rv == KMF_OK) { 42635b3e1433Swyllys int len = 0; 42645b3e1433Swyllys /* Get the alias name for the cert if there is one */ 42655b3e1433Swyllys char *a = (char *)X509_alias_get0(sslcert, &len); 42665b3e1433Swyllys if (a != NULL) 42675b3e1433Swyllys cert.kmf_private.label = strdup(a); 42685b3e1433Swyllys cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL; 42695b3e1433Swyllys 427099ebb4caSwyllys list[n] = cert; 427199ebb4caSwyllys (*ncerts) = n + 1; 427299ebb4caSwyllys 427399ebb4caSwyllys *certlist = list; 427499ebb4caSwyllys } else { 427599ebb4caSwyllys free(list); 427699ebb4caSwyllys } 427799ebb4caSwyllys 427899ebb4caSwyllys return (rv); 427999ebb4caSwyllys } 428099ebb4caSwyllys 428199ebb4caSwyllys static KMF_RETURN 428299ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist, 428399ebb4caSwyllys KMF_RAW_KEY_DATA *newkey, int *nkeys) 428499ebb4caSwyllys { 428599ebb4caSwyllys KMF_RAW_KEY_DATA *list = (*keylist); 428699ebb4caSwyllys int n = (*nkeys); 428799ebb4caSwyllys 428899ebb4caSwyllys if (list == NULL) { 428999ebb4caSwyllys list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA)); 429099ebb4caSwyllys } else { 429199ebb4caSwyllys list = (KMF_RAW_KEY_DATA *)realloc(list, 429299ebb4caSwyllys sizeof (KMF_RAW_KEY_DATA) * (n + 1)); 429399ebb4caSwyllys } 429499ebb4caSwyllys 429599ebb4caSwyllys if (list == NULL) 429699ebb4caSwyllys return (KMF_ERR_MEMORY); 429799ebb4caSwyllys 429899ebb4caSwyllys list[n] = *newkey; 429999ebb4caSwyllys (*nkeys) = n + 1; 430099ebb4caSwyllys 430199ebb4caSwyllys *keylist = list; 430299ebb4caSwyllys 430399ebb4caSwyllys return (KMF_OK); 430499ebb4caSwyllys } 430599ebb4caSwyllys 430630a5e8faSwyllys static KMF_RETURN 430730a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key) 430830a5e8faSwyllys { 430930a5e8faSwyllys KMF_RETURN rv = KMF_OK; 43105b3e1433Swyllys X509_ATTRIBUTE *attr; 4311*300fdee2SAndy Fiddaman RSA *rsa; 4312*300fdee2SAndy Fiddaman DSA *dsa; 4313*300fdee2SAndy Fiddaman int loc; 431430a5e8faSwyllys 431530a5e8faSwyllys if (pkey == NULL || key == NULL) 431630a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 431730a5e8faSwyllys /* Convert SSL key to raw key */ 4318*300fdee2SAndy Fiddaman if ((rsa = EVP_PKEY_get1_RSA(pkey)) != NULL) { 4319*300fdee2SAndy Fiddaman rv = exportRawRSAKey(rsa, key); 432030a5e8faSwyllys if (rv != KMF_OK) 432130a5e8faSwyllys return (rv); 4322*300fdee2SAndy Fiddaman } else if ((dsa = EVP_PKEY_get1_DSA(pkey)) != NULL) { 4323*300fdee2SAndy Fiddaman rv = exportRawDSAKey(dsa, key); 432430a5e8faSwyllys if (rv != KMF_OK) 432530a5e8faSwyllys return (rv); 4326*300fdee2SAndy Fiddaman } else 432730a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 4328*300fdee2SAndy Fiddaman 43295b3e1433Swyllys /* 43305b3e1433Swyllys * If friendlyName, add it to record. 43315b3e1433Swyllys */ 4332*300fdee2SAndy Fiddaman 4333*300fdee2SAndy Fiddaman if ((loc = EVP_PKEY_get_attr_by_NID(pkey, 4334*300fdee2SAndy Fiddaman NID_friendlyName, -1)) != -1 && 4335*300fdee2SAndy Fiddaman (attr = EVP_PKEY_get_attr(pkey, loc))) { 43365b3e1433Swyllys ASN1_TYPE *ty = NULL; 4337*300fdee2SAndy Fiddaman int numattr = X509_ATTRIBUTE_count(attr); 4338*300fdee2SAndy Fiddaman if (numattr > 0) { 4339*300fdee2SAndy Fiddaman ty = X509_ATTRIBUTE_get0_type(attr, 0); 43405b3e1433Swyllys } 43415b3e1433Swyllys if (ty != NULL) { 434270f9559bSTheo Schlossnagle key->label = OPENSSL_uni2asc(ty->value.bmpstring->data, 434370f9559bSTheo Schlossnagle ty->value.bmpstring->length); 43445b3e1433Swyllys } 43455b3e1433Swyllys } else { 43465b3e1433Swyllys key->label = NULL; 43475b3e1433Swyllys } 43485b3e1433Swyllys 43495b3e1433Swyllys /* 43505b3e1433Swyllys * If KeyID, add it to record as a KMF_DATA object. 43515b3e1433Swyllys */ 4352*300fdee2SAndy Fiddaman if ((loc = EVP_PKEY_get_attr_by_NID(pkey, 4353*300fdee2SAndy Fiddaman NID_localKeyID, -1)) != -1 && 4354*300fdee2SAndy Fiddaman (attr = EVP_PKEY_get_attr(pkey, loc)) != NULL) { 43555b3e1433Swyllys ASN1_TYPE *ty = NULL; 4356*300fdee2SAndy Fiddaman int numattr = X509_ATTRIBUTE_count(attr); 4357*300fdee2SAndy Fiddaman if (numattr > 0) 4358*300fdee2SAndy Fiddaman ty = X509_ATTRIBUTE_get0_type(attr, 0); 43595b3e1433Swyllys key->id.Data = (uchar_t *)malloc( 43605b3e1433Swyllys ty->value.octet_string->length); 43615b3e1433Swyllys if (key->id.Data == NULL) 43625b3e1433Swyllys return (KMF_ERR_MEMORY); 43635b3e1433Swyllys (void) memcpy(key->id.Data, ty->value.octet_string->data, 43645b3e1433Swyllys ty->value.octet_string->length); 43655b3e1433Swyllys key->id.Length = ty->value.octet_string->length; 43665b3e1433Swyllys } else { 43675b3e1433Swyllys (void) memset(&key->id, 0, sizeof (KMF_DATA)); 43685b3e1433Swyllys } 436930a5e8faSwyllys 437030a5e8faSwyllys return (rv); 437130a5e8faSwyllys } 437299ebb4caSwyllys 437399ebb4caSwyllys static KMF_RETURN 437499ebb4caSwyllys convertPK12Objects( 437599ebb4caSwyllys KMF_HANDLE *kmfh, 43765b3e1433Swyllys STACK_OF(EVP_PKEY) *sslkeys, 43775b3e1433Swyllys STACK_OF(X509) *sslcert, 43785b3e1433Swyllys STACK_OF(X509) *sslcacerts, 437999ebb4caSwyllys KMF_RAW_KEY_DATA **keylist, int *nkeys, 43805b3e1433Swyllys KMF_X509_DER_CERT **certlist, int *ncerts) 438199ebb4caSwyllys { 438299ebb4caSwyllys KMF_RETURN rv = KMF_OK; 438399ebb4caSwyllys KMF_RAW_KEY_DATA key; 438499ebb4caSwyllys int i; 438599ebb4caSwyllys 43865b3e1433Swyllys for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) { 4387d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 43885b3e1433Swyllys EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i); 43895b3e1433Swyllys rv = convertToRawKey(pkey, &key); 439030a5e8faSwyllys if (rv == KMF_OK) 439199ebb4caSwyllys rv = add_key_to_list(keylist, &key, nkeys); 439230a5e8faSwyllys 439399ebb4caSwyllys if (rv != KMF_OK) 439499ebb4caSwyllys return (rv); 439599ebb4caSwyllys } 439699ebb4caSwyllys 439799ebb4caSwyllys /* Now add the certificate to the certlist */ 43985b3e1433Swyllys for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) { 4399d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 44005b3e1433Swyllys X509 *cert = sk_X509_value(sslcert, i); 44015b3e1433Swyllys rv = add_cert_to_list(kmfh, cert, certlist, ncerts); 440299ebb4caSwyllys if (rv != KMF_OK) 440399ebb4caSwyllys return (rv); 440499ebb4caSwyllys } 440599ebb4caSwyllys 440699ebb4caSwyllys /* Also add any included CA certs to the list */ 440771593db2Swyllys for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) { 440899ebb4caSwyllys X509 *c; 440999ebb4caSwyllys /* 441099ebb4caSwyllys * sk_X509_value() is macro that embeds a cast to (X509 *). 441199ebb4caSwyllys * Here it translates into ((X509 *)sk_value((ca), (i))). 441299ebb4caSwyllys * Lint is complaining about the embedded casting, and 441399ebb4caSwyllys * to fix it, you need to fix openssl header files. 441499ebb4caSwyllys */ 4415d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 441699ebb4caSwyllys c = sk_X509_value(sslcacerts, i); 441799ebb4caSwyllys 441899ebb4caSwyllys /* Now add the ca cert to the certlist */ 441999ebb4caSwyllys rv = add_cert_to_list(kmfh, c, certlist, ncerts); 442099ebb4caSwyllys if (rv != KMF_OK) 442199ebb4caSwyllys return (rv); 442299ebb4caSwyllys } 442399ebb4caSwyllys return (rv); 442499ebb4caSwyllys } 442599ebb4caSwyllys 442699ebb4caSwyllys KMF_RETURN 442730a5e8faSwyllys openssl_import_objects(KMF_HANDLE *kmfh, 442899ebb4caSwyllys char *filename, KMF_CREDENTIAL *cred, 44295b3e1433Swyllys KMF_X509_DER_CERT **certlist, int *ncerts, 443099ebb4caSwyllys KMF_RAW_KEY_DATA **keylist, int *nkeys) 443199ebb4caSwyllys { 443299ebb4caSwyllys KMF_RETURN rv = KMF_OK; 443330a5e8faSwyllys KMF_ENCODE_FORMAT format; 443430a5e8faSwyllys BIO *bio = NULL; 44355b3e1433Swyllys STACK_OF(EVP_PKEY) *privkeys = NULL; 44365b3e1433Swyllys STACK_OF(X509) *certs = NULL; 443799ebb4caSwyllys STACK_OF(X509) *cacerts = NULL; 443899ebb4caSwyllys 443930a5e8faSwyllys /* 444030a5e8faSwyllys * auto-detect the file format, regardless of what 444130a5e8faSwyllys * the 'format' parameters in the params say. 444230a5e8faSwyllys */ 444330a5e8faSwyllys rv = kmf_get_file_format(filename, &format); 444430a5e8faSwyllys if (rv != KMF_OK) { 444530a5e8faSwyllys return (rv); 444630a5e8faSwyllys } 444730a5e8faSwyllys 444830a5e8faSwyllys /* This function only works for PEM or PKCS#12 files */ 444930a5e8faSwyllys if (format != KMF_FORMAT_PEM && 445030a5e8faSwyllys format != KMF_FORMAT_PEM_KEYPAIR && 445130a5e8faSwyllys format != KMF_FORMAT_PKCS12) 445230a5e8faSwyllys return (KMF_ERR_ENCODING); 445330a5e8faSwyllys 445430a5e8faSwyllys *certlist = NULL; 445530a5e8faSwyllys *keylist = NULL; 445630a5e8faSwyllys *ncerts = 0; 445730a5e8faSwyllys *nkeys = 0; 445830a5e8faSwyllys 445930a5e8faSwyllys if (format == KMF_FORMAT_PKCS12) { 446099ebb4caSwyllys bio = BIO_new_file(filename, "rb"); 446199ebb4caSwyllys if (bio == NULL) { 446299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 446399ebb4caSwyllys rv = KMF_ERR_OPEN_FILE; 446499ebb4caSwyllys goto end; 446599ebb4caSwyllys } 446699ebb4caSwyllys 446734acef67Swyllys rv = extract_pkcs12(bio, (uchar_t *)cred->cred, 44685b3e1433Swyllys (uint32_t)cred->credlen, &privkeys, &certs, &cacerts); 446999ebb4caSwyllys 447099ebb4caSwyllys if (rv == KMF_OK) 447199ebb4caSwyllys /* Convert keys and certs to exportable format */ 44725b3e1433Swyllys rv = convertPK12Objects(kmfh, privkeys, certs, cacerts, 447399ebb4caSwyllys keylist, nkeys, certlist, ncerts); 447430a5e8faSwyllys } else { 44755b3e1433Swyllys EVP_PKEY *pkey; 44765b3e1433Swyllys KMF_DATA *certdata = NULL; 44775b3e1433Swyllys KMF_X509_DER_CERT *kmfcerts = NULL; 44785b3e1433Swyllys int i; 447930a5e8faSwyllys rv = extract_pem(kmfh, NULL, NULL, NULL, filename, 448034acef67Swyllys (uchar_t *)cred->cred, (uint32_t)cred->credlen, 44815b3e1433Swyllys &pkey, &certdata, ncerts); 448271593db2Swyllys 448371593db2Swyllys /* Reached end of import file? */ 44845b3e1433Swyllys if (rv == KMF_OK && pkey != NULL) { 44855b3e1433Swyllys privkeys = sk_EVP_PKEY_new_null(); 44865b3e1433Swyllys if (privkeys == NULL) { 44875b3e1433Swyllys rv = KMF_ERR_MEMORY; 44885b3e1433Swyllys goto end; 44895b3e1433Swyllys } 44905b3e1433Swyllys (void) sk_EVP_PKEY_push(privkeys, pkey); 44915b3e1433Swyllys /* convert the certificate list here */ 44925b3e1433Swyllys if (*ncerts > 0 && certlist != NULL) { 4493e65e5c2dSWyllys Ingersoll kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts, 44945b3e1433Swyllys sizeof (KMF_X509_DER_CERT)); 44955b3e1433Swyllys if (kmfcerts == NULL) { 44965b3e1433Swyllys rv = KMF_ERR_MEMORY; 44975b3e1433Swyllys goto end; 44985b3e1433Swyllys } 44995b3e1433Swyllys for (i = 0; i < *ncerts; i++) { 45005b3e1433Swyllys kmfcerts[i].certificate = certdata[i]; 45015b3e1433Swyllys kmfcerts[i].kmf_private.keystore_type = 45025b3e1433Swyllys KMF_KEYSTORE_OPENSSL; 45035b3e1433Swyllys } 45045b3e1433Swyllys *certlist = kmfcerts; 45055b3e1433Swyllys } 45065b3e1433Swyllys /* 45075b3e1433Swyllys * Convert keys to exportable format, the certs 45085b3e1433Swyllys * are already OK. 45095b3e1433Swyllys */ 45105b3e1433Swyllys rv = convertPK12Objects(kmfh, privkeys, NULL, NULL, 451171593db2Swyllys keylist, nkeys, NULL, NULL); 451230a5e8faSwyllys } 45135b3e1433Swyllys } 451471593db2Swyllys end: 451530a5e8faSwyllys if (bio != NULL) 451699ebb4caSwyllys (void) BIO_free(bio); 451799ebb4caSwyllys 45185b3e1433Swyllys if (privkeys) 45195b3e1433Swyllys sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free); 45205b3e1433Swyllys if (certs) 45215b3e1433Swyllys sk_X509_pop_free(certs, X509_free); 452230a5e8faSwyllys if (cacerts) 45235b3e1433Swyllys sk_X509_pop_free(cacerts, X509_free); 452430a5e8faSwyllys 452599ebb4caSwyllys return (rv); 452699ebb4caSwyllys } 452799ebb4caSwyllys 452899ebb4caSwyllys static KMF_RETURN 452999ebb4caSwyllys create_deskey(DES_cblock **deskey) 453099ebb4caSwyllys { 453199ebb4caSwyllys DES_cblock *key; 453299ebb4caSwyllys 453399ebb4caSwyllys key = (DES_cblock *) malloc(sizeof (DES_cblock)); 453499ebb4caSwyllys if (key == NULL) { 453599ebb4caSwyllys return (KMF_ERR_MEMORY); 453699ebb4caSwyllys } 453799ebb4caSwyllys 453899ebb4caSwyllys if (DES_random_key(key) == 0) { 453999ebb4caSwyllys free(key); 454099ebb4caSwyllys return (KMF_ERR_KEYGEN_FAILED); 454199ebb4caSwyllys } 454299ebb4caSwyllys 454399ebb4caSwyllys *deskey = key; 454499ebb4caSwyllys return (KMF_OK); 454599ebb4caSwyllys } 454699ebb4caSwyllys 454799ebb4caSwyllys #define KEYGEN_RETRY 3 454899ebb4caSwyllys #define DES3_KEY_SIZE 24 454999ebb4caSwyllys 455099ebb4caSwyllys static KMF_RETURN 455199ebb4caSwyllys create_des3key(unsigned char **des3key) 455299ebb4caSwyllys { 455399ebb4caSwyllys KMF_RETURN ret = KMF_OK; 455499ebb4caSwyllys DES_cblock *deskey1 = NULL; 455599ebb4caSwyllys DES_cblock *deskey2 = NULL; 455699ebb4caSwyllys DES_cblock *deskey3 = NULL; 455799ebb4caSwyllys unsigned char *newkey = NULL; 455899ebb4caSwyllys int retry; 455999ebb4caSwyllys 456099ebb4caSwyllys if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) { 456199ebb4caSwyllys return (KMF_ERR_MEMORY); 456299ebb4caSwyllys } 456399ebb4caSwyllys 456499ebb4caSwyllys /* create the 1st DES key */ 456599ebb4caSwyllys if ((ret = create_deskey(&deskey1)) != KMF_OK) { 456699ebb4caSwyllys goto out; 456799ebb4caSwyllys } 456899ebb4caSwyllys 456999ebb4caSwyllys /* 457099ebb4caSwyllys * Create the 2nd DES key and make sure its value is different 457199ebb4caSwyllys * from the 1st DES key. 457299ebb4caSwyllys */ 457399ebb4caSwyllys retry = 0; 457499ebb4caSwyllys do { 457599ebb4caSwyllys if (deskey2 != NULL) { 457699ebb4caSwyllys free(deskey2); 457799ebb4caSwyllys deskey2 = NULL; 457899ebb4caSwyllys } 457999ebb4caSwyllys 458099ebb4caSwyllys if ((ret = create_deskey(&deskey2)) != KMF_OK) { 458199ebb4caSwyllys goto out; 458299ebb4caSwyllys } 458399ebb4caSwyllys 458499ebb4caSwyllys if (memcmp((const void *) deskey1, (const void *) deskey2, 8) 458599ebb4caSwyllys == 0) { 458699ebb4caSwyllys ret = KMF_ERR_KEYGEN_FAILED; 458799ebb4caSwyllys retry++; 458899ebb4caSwyllys } 458999ebb4caSwyllys } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY); 459099ebb4caSwyllys 459199ebb4caSwyllys if (ret != KMF_OK) { 459299ebb4caSwyllys goto out; 459399ebb4caSwyllys } 459499ebb4caSwyllys 459599ebb4caSwyllys /* 459699ebb4caSwyllys * Create the 3rd DES key and make sure its value is different 459799ebb4caSwyllys * from the 2nd DES key. 459899ebb4caSwyllys */ 459999ebb4caSwyllys retry = 0; 460099ebb4caSwyllys do { 460199ebb4caSwyllys if (deskey3 != NULL) { 460299ebb4caSwyllys free(deskey3); 460399ebb4caSwyllys deskey3 = NULL; 460499ebb4caSwyllys } 460599ebb4caSwyllys 460699ebb4caSwyllys if ((ret = create_deskey(&deskey3)) != KMF_OK) { 460799ebb4caSwyllys goto out; 460899ebb4caSwyllys } 460999ebb4caSwyllys 461099ebb4caSwyllys if (memcmp((const void *)deskey2, (const void *)deskey3, 8) 461199ebb4caSwyllys == 0) { 461299ebb4caSwyllys ret = KMF_ERR_KEYGEN_FAILED; 461399ebb4caSwyllys retry++; 461499ebb4caSwyllys } 461599ebb4caSwyllys } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY); 461699ebb4caSwyllys 461799ebb4caSwyllys if (ret != KMF_OK) { 461899ebb4caSwyllys goto out; 461999ebb4caSwyllys } 462099ebb4caSwyllys 462199ebb4caSwyllys /* Concatenate 3 DES keys into a DES3 key */ 462299ebb4caSwyllys (void) memcpy((void *)newkey, (const void *)deskey1, 8); 462399ebb4caSwyllys (void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8); 462499ebb4caSwyllys (void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8); 462599ebb4caSwyllys *des3key = newkey; 462699ebb4caSwyllys 462799ebb4caSwyllys out: 462899ebb4caSwyllys if (deskey1 != NULL) 462999ebb4caSwyllys free(deskey1); 463099ebb4caSwyllys 463199ebb4caSwyllys if (deskey2 != NULL) 463299ebb4caSwyllys free(deskey2); 463399ebb4caSwyllys 463499ebb4caSwyllys if (deskey3 != NULL) 463599ebb4caSwyllys free(deskey3); 463699ebb4caSwyllys 463799ebb4caSwyllys if (ret != KMF_OK && newkey != NULL) 463899ebb4caSwyllys free(newkey); 463999ebb4caSwyllys 464099ebb4caSwyllys return (ret); 464199ebb4caSwyllys } 464299ebb4caSwyllys 464399ebb4caSwyllys KMF_RETURN 464430a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle, 464530a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 464699ebb4caSwyllys { 464799ebb4caSwyllys KMF_RETURN ret = KMF_OK; 464899ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 464999ebb4caSwyllys char *fullpath = NULL; 465099ebb4caSwyllys KMF_RAW_SYM_KEY *rkey = NULL; 465199ebb4caSwyllys DES_cblock *deskey = NULL; 465299ebb4caSwyllys unsigned char *des3key = NULL; 465399ebb4caSwyllys unsigned char *random = NULL; 465499ebb4caSwyllys int fd = -1; 465530a5e8faSwyllys KMF_KEY_HANDLE *symkey; 465630a5e8faSwyllys KMF_KEY_ALG keytype; 465730a5e8faSwyllys uint32_t keylen; 465830a5e8faSwyllys uint32_t keylen_size = sizeof (keylen); 465930a5e8faSwyllys char *dirpath; 466030a5e8faSwyllys char *keyfile; 466199ebb4caSwyllys 466299ebb4caSwyllys if (kmfh == NULL) 466399ebb4caSwyllys return (KMF_ERR_UNINITIALIZED); 466499ebb4caSwyllys 466530a5e8faSwyllys symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 466630a5e8faSwyllys if (symkey == NULL) 466799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 466899ebb4caSwyllys 466930a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 467030a5e8faSwyllys 467130a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 467230a5e8faSwyllys if (keyfile == NULL) 467330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 467430a5e8faSwyllys 467530a5e8faSwyllys ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, 467630a5e8faSwyllys (void *)&keytype, NULL); 467730a5e8faSwyllys if (ret != KMF_OK) 467830a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 467930a5e8faSwyllys 468030a5e8faSwyllys ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, 468130a5e8faSwyllys &keylen, &keylen_size); 468230a5e8faSwyllys if (ret == KMF_ERR_ATTR_NOT_FOUND && 468330a5e8faSwyllys (keytype == KMF_DES || keytype == KMF_DES3)) 468430a5e8faSwyllys /* keylength is not required for DES and 3DES */ 468530a5e8faSwyllys ret = KMF_OK; 468630a5e8faSwyllys if (ret != KMF_OK) 468730a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 468830a5e8faSwyllys 468930a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 469099ebb4caSwyllys if (fullpath == NULL) 469199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 469299ebb4caSwyllys 469399ebb4caSwyllys /* If the requested file exists, return an error */ 469430a5e8faSwyllys if (test_for_file(fullpath, 0400) == 1) { 469599ebb4caSwyllys free(fullpath); 469699ebb4caSwyllys return (KMF_ERR_DUPLICATE_KEYFILE); 469799ebb4caSwyllys } 469899ebb4caSwyllys 469999ebb4caSwyllys fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400); 470099ebb4caSwyllys if (fd == -1) { 470199ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 470299ebb4caSwyllys goto out; 470399ebb4caSwyllys } 470499ebb4caSwyllys 470599ebb4caSwyllys rkey = malloc(sizeof (KMF_RAW_SYM_KEY)); 470699ebb4caSwyllys if (rkey == NULL) { 470799ebb4caSwyllys ret = KMF_ERR_MEMORY; 470899ebb4caSwyllys goto out; 470999ebb4caSwyllys } 471099ebb4caSwyllys (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 471199ebb4caSwyllys 471230a5e8faSwyllys if (keytype == KMF_DES) { 471399ebb4caSwyllys if ((ret = create_deskey(&deskey)) != KMF_OK) { 471499ebb4caSwyllys goto out; 471599ebb4caSwyllys } 471699ebb4caSwyllys rkey->keydata.val = (uchar_t *)deskey; 471799ebb4caSwyllys rkey->keydata.len = 8; 471899ebb4caSwyllys 471999ebb4caSwyllys symkey->keyalg = KMF_DES; 472099ebb4caSwyllys 472130a5e8faSwyllys } else if (keytype == KMF_DES3) { 472299ebb4caSwyllys if ((ret = create_des3key(&des3key)) != KMF_OK) { 472399ebb4caSwyllys goto out; 472499ebb4caSwyllys } 472599ebb4caSwyllys rkey->keydata.val = (uchar_t *)des3key; 472699ebb4caSwyllys rkey->keydata.len = DES3_KEY_SIZE; 472799ebb4caSwyllys symkey->keyalg = KMF_DES3; 47289b37d296Swyllys 472930a5e8faSwyllys } else if (keytype == KMF_AES || keytype == KMF_RC4 || 473030a5e8faSwyllys keytype == KMF_GENERIC_SECRET) { 473199ebb4caSwyllys int bytes; 473299ebb4caSwyllys 473330a5e8faSwyllys if (keylen % 8 != 0) { 473499ebb4caSwyllys ret = KMF_ERR_BAD_KEY_SIZE; 473599ebb4caSwyllys goto out; 473699ebb4caSwyllys } 473799ebb4caSwyllys 473830a5e8faSwyllys if (keytype == KMF_AES) { 473930a5e8faSwyllys if (keylen != 128 && 474030a5e8faSwyllys keylen != 192 && 474130a5e8faSwyllys keylen != 256) { 474299ebb4caSwyllys ret = KMF_ERR_BAD_KEY_SIZE; 474399ebb4caSwyllys goto out; 474499ebb4caSwyllys } 474599ebb4caSwyllys } 474699ebb4caSwyllys 474730a5e8faSwyllys bytes = keylen/8; 474899ebb4caSwyllys random = malloc(bytes); 474999ebb4caSwyllys if (random == NULL) { 475099ebb4caSwyllys ret = KMF_ERR_MEMORY; 475199ebb4caSwyllys goto out; 475299ebb4caSwyllys } 475399ebb4caSwyllys if (RAND_bytes(random, bytes) != 1) { 475499ebb4caSwyllys ret = KMF_ERR_KEYGEN_FAILED; 475599ebb4caSwyllys goto out; 475699ebb4caSwyllys } 475799ebb4caSwyllys 475899ebb4caSwyllys rkey->keydata.val = (uchar_t *)random; 475999ebb4caSwyllys rkey->keydata.len = bytes; 476030a5e8faSwyllys symkey->keyalg = keytype; 476199ebb4caSwyllys 476299ebb4caSwyllys } else { 476399ebb4caSwyllys ret = KMF_ERR_BAD_KEY_TYPE; 476499ebb4caSwyllys goto out; 476599ebb4caSwyllys } 476699ebb4caSwyllys 476799ebb4caSwyllys (void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len); 476899ebb4caSwyllys 476999ebb4caSwyllys symkey->kstype = KMF_KEYSTORE_OPENSSL; 477099ebb4caSwyllys symkey->keyclass = KMF_SYMMETRIC; 477199ebb4caSwyllys symkey->keylabel = (char *)fullpath; 477299ebb4caSwyllys symkey->israw = TRUE; 477399ebb4caSwyllys symkey->keyp = rkey; 477499ebb4caSwyllys 477599ebb4caSwyllys out: 477699ebb4caSwyllys if (fd != -1) 477799ebb4caSwyllys (void) close(fd); 477899ebb4caSwyllys 477999ebb4caSwyllys if (ret != KMF_OK && fullpath != NULL) { 478099ebb4caSwyllys free(fullpath); 478199ebb4caSwyllys } 478299ebb4caSwyllys if (ret != KMF_OK) { 478330a5e8faSwyllys kmf_free_raw_sym_key(rkey); 478499ebb4caSwyllys symkey->keyp = NULL; 478599ebb4caSwyllys symkey->keyalg = KMF_KEYALG_NONE; 478699ebb4caSwyllys } 478799ebb4caSwyllys 478899ebb4caSwyllys return (ret); 478999ebb4caSwyllys } 479099ebb4caSwyllys 479199ebb4caSwyllys /* 479299ebb4caSwyllys * Check a file to see if it is a CRL file with PEM or DER format. 479399ebb4caSwyllys * If success, return its format in the "pformat" argument. 479499ebb4caSwyllys */ 479599ebb4caSwyllys KMF_RETURN 479699ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat) 479799ebb4caSwyllys { 479899ebb4caSwyllys KMF_RETURN ret = KMF_OK; 479999ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 480099ebb4caSwyllys BIO *bio = NULL; 480199ebb4caSwyllys X509_CRL *xcrl = NULL; 480299ebb4caSwyllys 480399ebb4caSwyllys if (filename == NULL) { 480499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 480599ebb4caSwyllys } 480699ebb4caSwyllys 480799ebb4caSwyllys bio = BIO_new_file(filename, "rb"); 480899ebb4caSwyllys if (bio == NULL) { 480999ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 481099ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 481199ebb4caSwyllys goto out; 481299ebb4caSwyllys } 481399ebb4caSwyllys 481499ebb4caSwyllys if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) { 481599ebb4caSwyllys *pformat = KMF_FORMAT_PEM; 481699ebb4caSwyllys goto out; 481799ebb4caSwyllys } 481899ebb4caSwyllys (void) BIO_free(bio); 481999ebb4caSwyllys 482099ebb4caSwyllys /* 482199ebb4caSwyllys * Now try to read it as raw DER data. 482299ebb4caSwyllys */ 482399ebb4caSwyllys bio = BIO_new_file(filename, "rb"); 482499ebb4caSwyllys if (bio == NULL) { 482599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 482699ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 482799ebb4caSwyllys goto out; 482899ebb4caSwyllys } 482999ebb4caSwyllys 483099ebb4caSwyllys if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) { 483199ebb4caSwyllys *pformat = KMF_FORMAT_ASN1; 483299ebb4caSwyllys } else { 483399ebb4caSwyllys ret = KMF_ERR_BAD_CRLFILE; 483499ebb4caSwyllys } 483599ebb4caSwyllys 483699ebb4caSwyllys out: 483799ebb4caSwyllys if (bio != NULL) 483899ebb4caSwyllys (void) BIO_free(bio); 483999ebb4caSwyllys 484099ebb4caSwyllys if (xcrl != NULL) 484199ebb4caSwyllys X509_CRL_free(xcrl); 484299ebb4caSwyllys 484399ebb4caSwyllys return (ret); 484499ebb4caSwyllys } 484599ebb4caSwyllys 484699ebb4caSwyllys KMF_RETURN 484799ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey, 484899ebb4caSwyllys KMF_RAW_SYM_KEY *rkey) 484999ebb4caSwyllys { 485099ebb4caSwyllys KMF_RETURN rv = KMF_OK; 485199ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 485299ebb4caSwyllys KMF_DATA keyvalue; 485399ebb4caSwyllys 485499ebb4caSwyllys if (kmfh == NULL) 485599ebb4caSwyllys return (KMF_ERR_UNINITIALIZED); 485699ebb4caSwyllys 485799ebb4caSwyllys if (symkey == NULL || rkey == NULL) 485899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 485999ebb4caSwyllys else if (symkey->keyclass != KMF_SYMMETRIC) 486099ebb4caSwyllys return (KMF_ERR_BAD_KEY_CLASS); 486199ebb4caSwyllys 486299ebb4caSwyllys if (symkey->israw) { 486399ebb4caSwyllys KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp; 486499ebb4caSwyllys 486599ebb4caSwyllys if (rawkey == NULL || 486699ebb4caSwyllys rawkey->keydata.val == NULL || 486799ebb4caSwyllys rawkey->keydata.len == 0) 486899ebb4caSwyllys return (KMF_ERR_BAD_KEYHANDLE); 486999ebb4caSwyllys 487099ebb4caSwyllys rkey->keydata.len = rawkey->keydata.len; 487199ebb4caSwyllys if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL) 487299ebb4caSwyllys return (KMF_ERR_MEMORY); 487399ebb4caSwyllys (void) memcpy(rkey->keydata.val, rawkey->keydata.val, 487499ebb4caSwyllys rkey->keydata.len); 487599ebb4caSwyllys } else { 487630a5e8faSwyllys rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue); 487799ebb4caSwyllys if (rv != KMF_OK) 487899ebb4caSwyllys return (rv); 487999ebb4caSwyllys rkey->keydata.len = keyvalue.Length; 488099ebb4caSwyllys rkey->keydata.val = keyvalue.Data; 488199ebb4caSwyllys } 488299ebb4caSwyllys 488399ebb4caSwyllys return (rv); 488499ebb4caSwyllys } 488502744e81Swyllys 488602744e81Swyllys /* 488730a5e8faSwyllys * substitute for the unsafe access(2) function. 488830a5e8faSwyllys * If the file in question already exists, return 1. 488930a5e8faSwyllys * else 0. If an error occurs during testing (other 489030a5e8faSwyllys * than EEXIST), return -1. 489130a5e8faSwyllys */ 489230a5e8faSwyllys static int 489330a5e8faSwyllys test_for_file(char *filename, mode_t mode) 489430a5e8faSwyllys { 489530a5e8faSwyllys int fd; 489630a5e8faSwyllys 489730a5e8faSwyllys /* 489830a5e8faSwyllys * Try to create the file with the EXCL flag. 489930a5e8faSwyllys * The call should fail if the file exists. 490030a5e8faSwyllys */ 490130a5e8faSwyllys fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode); 490230a5e8faSwyllys if (fd == -1 && errno == EEXIST) 490330a5e8faSwyllys return (1); 490430a5e8faSwyllys else if (fd == -1) /* some other error */ 490530a5e8faSwyllys return (-1); 490630a5e8faSwyllys 490730a5e8faSwyllys /* The file did NOT exist. Delete the testcase. */ 490830a5e8faSwyllys (void) close(fd); 490930a5e8faSwyllys (void) unlink(filename); 491030a5e8faSwyllys return (0); 491130a5e8faSwyllys } 491230a5e8faSwyllys 491330a5e8faSwyllys KMF_RETURN 491430a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr, 491530a5e8faSwyllys KMF_ATTRIBUTE *attrlist) 491630a5e8faSwyllys { 491730a5e8faSwyllys KMF_RETURN rv = KMF_OK; 491830a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 491930a5e8faSwyllys KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL; 492030a5e8faSwyllys KMF_RAW_KEY_DATA *rawkey; 492130a5e8faSwyllys EVP_PKEY *pkey = NULL; 492230a5e8faSwyllys KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM; 492330a5e8faSwyllys KMF_CREDENTIAL cred = { NULL, 0 }; 492430a5e8faSwyllys BIO *out = NULL; 492530a5e8faSwyllys int keys = 0; 492630a5e8faSwyllys char *fullpath = NULL; 492730a5e8faSwyllys char *keyfile = NULL; 492830a5e8faSwyllys char *dirpath = NULL; 492930a5e8faSwyllys 493030a5e8faSwyllys pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr); 493130a5e8faSwyllys if (pubkey != NULL) 493230a5e8faSwyllys keys++; 493330a5e8faSwyllys 493430a5e8faSwyllys prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr); 493530a5e8faSwyllys if (prikey != NULL) 493630a5e8faSwyllys keys++; 493730a5e8faSwyllys 493830a5e8faSwyllys rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr); 493930a5e8faSwyllys if (rawkey != NULL) 494030a5e8faSwyllys keys++; 494130a5e8faSwyllys 494230a5e8faSwyllys /* 494330a5e8faSwyllys * Exactly 1 type of key must be passed to this function. 494430a5e8faSwyllys */ 494530a5e8faSwyllys if (keys != 1) 494630a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 494730a5e8faSwyllys 494830a5e8faSwyllys keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, 494930a5e8faSwyllys numattr); 495030a5e8faSwyllys if (keyfile == NULL) 495130a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 495230a5e8faSwyllys 495330a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 495430a5e8faSwyllys 495530a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 495630a5e8faSwyllys 495730a5e8faSwyllys /* Once we have the full path, we don't need the pieces */ 495830a5e8faSwyllys if (fullpath == NULL) 495930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 496030a5e8faSwyllys 496130a5e8faSwyllys /* If the requested file exists, return an error */ 496230a5e8faSwyllys if (test_for_file(fullpath, 0400) == 1) { 496330a5e8faSwyllys free(fullpath); 496430a5e8faSwyllys return (KMF_ERR_DUPLICATE_KEYFILE); 496530a5e8faSwyllys } 496630a5e8faSwyllys 496730a5e8faSwyllys rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 496830a5e8faSwyllys &format, NULL); 496930a5e8faSwyllys if (rv != KMF_OK) 497030a5e8faSwyllys /* format is optional. */ 497130a5e8faSwyllys rv = KMF_OK; 497230a5e8faSwyllys 497330a5e8faSwyllys /* CRED is not required for OpenSSL files */ 497430a5e8faSwyllys (void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr, 497530a5e8faSwyllys &cred, NULL); 497630a5e8faSwyllys 497730a5e8faSwyllys /* Store the private key to the keyfile */ 497830a5e8faSwyllys out = BIO_new_file(fullpath, "wb"); 497930a5e8faSwyllys if (out == NULL) { 498030a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 498130a5e8faSwyllys rv = KMF_ERR_OPEN_FILE; 498230a5e8faSwyllys goto end; 498330a5e8faSwyllys } 498430a5e8faSwyllys 498530a5e8faSwyllys if (prikey != NULL && prikey->keyp != NULL) { 498630a5e8faSwyllys if (prikey->keyalg == KMF_RSA || 498730a5e8faSwyllys prikey->keyalg == KMF_DSA) { 498830a5e8faSwyllys pkey = (EVP_PKEY *)prikey->keyp; 498930a5e8faSwyllys 499030a5e8faSwyllys rv = ssl_write_key(kmfh, format, 499130a5e8faSwyllys out, &cred, pkey, TRUE); 499230a5e8faSwyllys 499330a5e8faSwyllys if (rv == KMF_OK && prikey->keylabel == NULL) { 499430a5e8faSwyllys prikey->keylabel = strdup(fullpath); 499530a5e8faSwyllys if (prikey->keylabel == NULL) 499630a5e8faSwyllys rv = KMF_ERR_MEMORY; 499730a5e8faSwyllys } 499830a5e8faSwyllys } 499930a5e8faSwyllys } else if (pubkey != NULL && pubkey->keyp != NULL) { 500030a5e8faSwyllys if (pubkey->keyalg == KMF_RSA || 500130a5e8faSwyllys pubkey->keyalg == KMF_DSA) { 500230a5e8faSwyllys pkey = (EVP_PKEY *)pubkey->keyp; 500330a5e8faSwyllys 500430a5e8faSwyllys rv = ssl_write_key(kmfh, format, 500530a5e8faSwyllys out, &cred, pkey, FALSE); 500630a5e8faSwyllys 500730a5e8faSwyllys if (rv == KMF_OK && pubkey->keylabel == NULL) { 500830a5e8faSwyllys pubkey->keylabel = strdup(fullpath); 500930a5e8faSwyllys if (pubkey->keylabel == NULL) 501030a5e8faSwyllys rv = KMF_ERR_MEMORY; 501130a5e8faSwyllys } 501230a5e8faSwyllys } 501330a5e8faSwyllys } else if (rawkey != NULL) { 501430a5e8faSwyllys if (rawkey->keytype == KMF_RSA) { 501530a5e8faSwyllys pkey = ImportRawRSAKey(&rawkey->rawdata.rsa); 501630a5e8faSwyllys } else if (rawkey->keytype == KMF_DSA) { 501730a5e8faSwyllys pkey = ImportRawDSAKey(&rawkey->rawdata.dsa); 501830a5e8faSwyllys } else { 501930a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 502030a5e8faSwyllys } 50215b3e1433Swyllys if (pkey != NULL) { 502273cc0e02Swyllys KMF_KEY_CLASS kclass = KMF_ASYM_PRI; 502373cc0e02Swyllys 502473cc0e02Swyllys rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr, 502573cc0e02Swyllys (void *)&kclass, NULL); 502673cc0e02Swyllys if (rv != KMF_OK) 502773cc0e02Swyllys rv = KMF_OK; 50285b3e1433Swyllys rv = ssl_write_key(kmfh, format, out, 502973cc0e02Swyllys &cred, pkey, (kclass == KMF_ASYM_PRI)); 50305b3e1433Swyllys EVP_PKEY_free(pkey); 50315b3e1433Swyllys } 503230a5e8faSwyllys } 503330a5e8faSwyllys 503430a5e8faSwyllys end: 503530a5e8faSwyllys 503630a5e8faSwyllys if (out) 503730a5e8faSwyllys (void) BIO_free(out); 503830a5e8faSwyllys 50395b3e1433Swyllys 504030a5e8faSwyllys if (rv == KMF_OK) 504130a5e8faSwyllys (void) chmod(fullpath, 0400); 504230a5e8faSwyllys 504330a5e8faSwyllys free(fullpath); 504430a5e8faSwyllys return (rv); 504530a5e8faSwyllys } 504630a5e8faSwyllys 504730a5e8faSwyllys KMF_RETURN 504830a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 504930a5e8faSwyllys { 505030a5e8faSwyllys KMF_RETURN ret = KMF_OK; 505130a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 505230a5e8faSwyllys X509_CRL *xcrl = NULL; 505330a5e8faSwyllys X509 *xcert = NULL; 505430a5e8faSwyllys EVP_PKEY *pkey; 505530a5e8faSwyllys KMF_ENCODE_FORMAT format; 505630a5e8faSwyllys BIO *in = NULL, *out = NULL; 505730a5e8faSwyllys int openssl_ret = 0; 505830a5e8faSwyllys KMF_ENCODE_FORMAT outformat; 505930a5e8faSwyllys boolean_t crlcheck = FALSE; 506030a5e8faSwyllys char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile; 506130a5e8faSwyllys 506230a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 506330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 506430a5e8faSwyllys } 506530a5e8faSwyllys 506630a5e8faSwyllys /* CRL check is optional */ 506730a5e8faSwyllys (void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr, 506830a5e8faSwyllys &crlcheck, NULL); 506930a5e8faSwyllys 507030a5e8faSwyllys certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr); 507130a5e8faSwyllys if (crlcheck == B_TRUE && certfile == NULL) { 507230a5e8faSwyllys return (KMF_ERR_BAD_CERTFILE); 507330a5e8faSwyllys } 507430a5e8faSwyllys 507530a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 507630a5e8faSwyllys incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr); 507730a5e8faSwyllys outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr); 507830a5e8faSwyllys 507930a5e8faSwyllys crlfile = get_fullpath(dirpath, incrl); 508030a5e8faSwyllys 508130a5e8faSwyllys if (crlfile == NULL) 508230a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 508330a5e8faSwyllys 508430a5e8faSwyllys outcrlfile = get_fullpath(dirpath, outcrl); 508530a5e8faSwyllys if (outcrlfile == NULL) 508630a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 508730a5e8faSwyllys 508830a5e8faSwyllys if (isdir(outcrlfile)) { 508930a5e8faSwyllys free(outcrlfile); 509030a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 509130a5e8faSwyllys } 509230a5e8faSwyllys 509330a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 509430a5e8faSwyllys if (ret != KMF_OK) { 509530a5e8faSwyllys free(outcrlfile); 509630a5e8faSwyllys return (ret); 509730a5e8faSwyllys } 509830a5e8faSwyllys 509930a5e8faSwyllys in = BIO_new_file(crlfile, "rb"); 510030a5e8faSwyllys if (in == NULL) { 510130a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 510230a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 510330a5e8faSwyllys goto end; 510430a5e8faSwyllys } 510530a5e8faSwyllys 510630a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 510730a5e8faSwyllys xcrl = d2i_X509_CRL_bio(in, NULL); 510830a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 510930a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); 511030a5e8faSwyllys } 511130a5e8faSwyllys 511230a5e8faSwyllys if (xcrl == NULL) { 511330a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 511430a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 511530a5e8faSwyllys goto end; 511630a5e8faSwyllys } 511730a5e8faSwyllys 511830a5e8faSwyllys /* If bypasscheck is specified, no need to verify. */ 511930a5e8faSwyllys if (crlcheck == B_FALSE) 512030a5e8faSwyllys goto output; 512130a5e8faSwyllys 512230a5e8faSwyllys ret = kmf_is_cert_file(handle, certfile, &format); 512330a5e8faSwyllys if (ret != KMF_OK) 512430a5e8faSwyllys goto end; 512530a5e8faSwyllys 512630a5e8faSwyllys /* Read in the CA cert file and convert to X509 */ 512730a5e8faSwyllys if (BIO_read_filename(in, certfile) <= 0) { 512830a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 512930a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 513030a5e8faSwyllys goto end; 513130a5e8faSwyllys } 513230a5e8faSwyllys 513330a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 513430a5e8faSwyllys xcert = d2i_X509_bio(in, NULL); 513530a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 513630a5e8faSwyllys xcert = PEM_read_bio_X509(in, NULL, NULL, NULL); 513730a5e8faSwyllys } else { 513830a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 513930a5e8faSwyllys goto end; 514030a5e8faSwyllys } 514130a5e8faSwyllys 514230a5e8faSwyllys if (xcert == NULL) { 514330a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 514430a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 514530a5e8faSwyllys goto end; 514630a5e8faSwyllys } 514730a5e8faSwyllys /* Now get the public key from the CA cert */ 514830a5e8faSwyllys pkey = X509_get_pubkey(xcert); 514930a5e8faSwyllys if (pkey == NULL) { 515030a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 515130a5e8faSwyllys ret = KMF_ERR_BAD_CERTFILE; 515230a5e8faSwyllys goto end; 515330a5e8faSwyllys } 515430a5e8faSwyllys 515530a5e8faSwyllys /* Verify the CRL with the CA's public key */ 515630a5e8faSwyllys openssl_ret = X509_CRL_verify(xcrl, pkey); 515730a5e8faSwyllys EVP_PKEY_free(pkey); 515830a5e8faSwyllys if (openssl_ret > 0) { 515930a5e8faSwyllys ret = KMF_OK; /* verify succeed */ 516030a5e8faSwyllys } else { 516130a5e8faSwyllys SET_ERROR(kmfh, openssl_ret); 516230a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 516330a5e8faSwyllys } 516430a5e8faSwyllys 516530a5e8faSwyllys output: 516630a5e8faSwyllys ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 516730a5e8faSwyllys &outformat, NULL); 516830a5e8faSwyllys if (ret != KMF_OK) { 516930a5e8faSwyllys ret = KMF_OK; 517030a5e8faSwyllys outformat = KMF_FORMAT_PEM; 517130a5e8faSwyllys } 517230a5e8faSwyllys 517330a5e8faSwyllys out = BIO_new_file(outcrlfile, "wb"); 517430a5e8faSwyllys if (out == NULL) { 517530a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 517630a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 517730a5e8faSwyllys goto end; 517830a5e8faSwyllys } 517930a5e8faSwyllys 518030a5e8faSwyllys if (outformat == KMF_FORMAT_ASN1) { 518130a5e8faSwyllys openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl); 518230a5e8faSwyllys } else if (outformat == KMF_FORMAT_PEM) { 518330a5e8faSwyllys openssl_ret = PEM_write_bio_X509_CRL(out, xcrl); 518430a5e8faSwyllys } else { 518530a5e8faSwyllys ret = KMF_ERR_BAD_PARAMETER; 518630a5e8faSwyllys goto end; 518730a5e8faSwyllys } 518830a5e8faSwyllys 518930a5e8faSwyllys if (openssl_ret <= 0) { 519030a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 519130a5e8faSwyllys ret = KMF_ERR_WRITE_FILE; 519230a5e8faSwyllys } else { 519330a5e8faSwyllys ret = KMF_OK; 519430a5e8faSwyllys } 519530a5e8faSwyllys 519630a5e8faSwyllys end: 519730a5e8faSwyllys if (xcrl != NULL) 519830a5e8faSwyllys X509_CRL_free(xcrl); 519930a5e8faSwyllys 520030a5e8faSwyllys if (xcert != NULL) 520130a5e8faSwyllys X509_free(xcert); 520230a5e8faSwyllys 520330a5e8faSwyllys if (in != NULL) 520430a5e8faSwyllys (void) BIO_free(in); 520530a5e8faSwyllys 520630a5e8faSwyllys if (out != NULL) 520730a5e8faSwyllys (void) BIO_free(out); 520830a5e8faSwyllys 520930a5e8faSwyllys if (outcrlfile != NULL) 521030a5e8faSwyllys free(outcrlfile); 521130a5e8faSwyllys 521230a5e8faSwyllys return (ret); 521330a5e8faSwyllys } 521430a5e8faSwyllys 521530a5e8faSwyllys KMF_RETURN 521630a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 521730a5e8faSwyllys { 521830a5e8faSwyllys KMF_RETURN ret = KMF_OK; 521930a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 522030a5e8faSwyllys X509_CRL *x = NULL; 522130a5e8faSwyllys KMF_ENCODE_FORMAT format; 522230a5e8faSwyllys char *crlfile = NULL; 522330a5e8faSwyllys BIO *in = NULL; 522430a5e8faSwyllys BIO *mem = NULL; 522530a5e8faSwyllys long len; 522630a5e8faSwyllys char *memptr; 522730a5e8faSwyllys char *data = NULL; 522830a5e8faSwyllys char **crldata; 522930a5e8faSwyllys char *crlfilename, *dirpath; 523030a5e8faSwyllys 523130a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 523230a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 523330a5e8faSwyllys } 523430a5e8faSwyllys crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, 523530a5e8faSwyllys attrlist, numattr); 523630a5e8faSwyllys if (crlfilename == NULL) 523730a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 523830a5e8faSwyllys 523930a5e8faSwyllys crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR, 524030a5e8faSwyllys attrlist, numattr); 524130a5e8faSwyllys 524230a5e8faSwyllys if (crldata == NULL) 524330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 524430a5e8faSwyllys 524530a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 524630a5e8faSwyllys 524730a5e8faSwyllys crlfile = get_fullpath(dirpath, crlfilename); 524830a5e8faSwyllys 524930a5e8faSwyllys if (crlfile == NULL) 525030a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 525130a5e8faSwyllys 525230a5e8faSwyllys if (isdir(crlfile)) { 525330a5e8faSwyllys free(crlfile); 525430a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 525530a5e8faSwyllys } 525630a5e8faSwyllys 525730a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 525830a5e8faSwyllys if (ret != KMF_OK) { 525930a5e8faSwyllys free(crlfile); 526030a5e8faSwyllys return (ret); 526130a5e8faSwyllys } 526230a5e8faSwyllys 526330a5e8faSwyllys if (bio_err == NULL) 526430a5e8faSwyllys bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 526530a5e8faSwyllys 526630a5e8faSwyllys in = BIO_new_file(crlfile, "rb"); 526730a5e8faSwyllys if (in == NULL) { 526830a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 526930a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 527030a5e8faSwyllys goto end; 527130a5e8faSwyllys } 527230a5e8faSwyllys 527330a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 527430a5e8faSwyllys x = d2i_X509_CRL_bio(in, NULL); 527530a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 527630a5e8faSwyllys x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); 527730a5e8faSwyllys } 527830a5e8faSwyllys 527930a5e8faSwyllys if (x == NULL) { /* should not happen */ 528030a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 528130a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 528230a5e8faSwyllys goto end; 528330a5e8faSwyllys } 528430a5e8faSwyllys 528530a5e8faSwyllys mem = BIO_new(BIO_s_mem()); 528630a5e8faSwyllys if (mem == NULL) { 528730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 528830a5e8faSwyllys ret = KMF_ERR_MEMORY; 528930a5e8faSwyllys goto end; 529030a5e8faSwyllys } 529130a5e8faSwyllys 529230a5e8faSwyllys (void) X509_CRL_print(mem, x); 529330a5e8faSwyllys len = BIO_get_mem_data(mem, &memptr); 529430a5e8faSwyllys if (len <= 0) { 529530a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 529630a5e8faSwyllys ret = KMF_ERR_MEMORY; 529730a5e8faSwyllys goto end; 529830a5e8faSwyllys } 529930a5e8faSwyllys 530030a5e8faSwyllys data = malloc(len + 1); 530130a5e8faSwyllys if (data == NULL) { 530230a5e8faSwyllys ret = KMF_ERR_MEMORY; 530330a5e8faSwyllys goto end; 530430a5e8faSwyllys } 530530a5e8faSwyllys 530630a5e8faSwyllys (void) memcpy(data, memptr, len); 530730a5e8faSwyllys data[len] = '\0'; 530830a5e8faSwyllys *crldata = data; 530930a5e8faSwyllys 531030a5e8faSwyllys end: 531130a5e8faSwyllys if (x != NULL) 531230a5e8faSwyllys X509_CRL_free(x); 531330a5e8faSwyllys 531430a5e8faSwyllys if (crlfile != NULL) 531530a5e8faSwyllys free(crlfile); 531630a5e8faSwyllys 531730a5e8faSwyllys if (in != NULL) 531830a5e8faSwyllys (void) BIO_free(in); 531930a5e8faSwyllys 532030a5e8faSwyllys if (mem != NULL) 532130a5e8faSwyllys (void) BIO_free(mem); 532230a5e8faSwyllys 532330a5e8faSwyllys return (ret); 532430a5e8faSwyllys } 532530a5e8faSwyllys 532630a5e8faSwyllys KMF_RETURN 532730a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 532830a5e8faSwyllys { 532930a5e8faSwyllys KMF_RETURN ret = KMF_OK; 533030a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 533130a5e8faSwyllys KMF_ENCODE_FORMAT format; 533230a5e8faSwyllys char *crlfile = NULL; 533330a5e8faSwyllys BIO *in = NULL; 533430a5e8faSwyllys char *crlfilename, *dirpath; 533530a5e8faSwyllys 533630a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 533730a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 533830a5e8faSwyllys } 533930a5e8faSwyllys 534030a5e8faSwyllys crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, 534130a5e8faSwyllys attrlist, numattr); 534230a5e8faSwyllys 534330a5e8faSwyllys if (crlfilename == NULL) 534430a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 534530a5e8faSwyllys 534630a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 534730a5e8faSwyllys 534830a5e8faSwyllys crlfile = get_fullpath(dirpath, crlfilename); 534930a5e8faSwyllys 535030a5e8faSwyllys if (crlfile == NULL) 535130a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 535230a5e8faSwyllys 535330a5e8faSwyllys if (isdir(crlfile)) { 535430a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 535530a5e8faSwyllys goto end; 535630a5e8faSwyllys } 535730a5e8faSwyllys 535830a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 535930a5e8faSwyllys if (ret != KMF_OK) 536030a5e8faSwyllys goto end; 536130a5e8faSwyllys 536230a5e8faSwyllys if (unlink(crlfile) != 0) { 536330a5e8faSwyllys SET_SYS_ERROR(kmfh, errno); 536430a5e8faSwyllys ret = KMF_ERR_INTERNAL; 536530a5e8faSwyllys goto end; 536630a5e8faSwyllys } 536730a5e8faSwyllys 536830a5e8faSwyllys end: 536930a5e8faSwyllys if (in != NULL) 537030a5e8faSwyllys (void) BIO_free(in); 537130a5e8faSwyllys if (crlfile != NULL) 537230a5e8faSwyllys free(crlfile); 537330a5e8faSwyllys 537430a5e8faSwyllys return (ret); 537530a5e8faSwyllys } 537630a5e8faSwyllys 537730a5e8faSwyllys KMF_RETURN 537830a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 537930a5e8faSwyllys { 538030a5e8faSwyllys KMF_RETURN ret = KMF_OK; 538130a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 538230a5e8faSwyllys KMF_ENCODE_FORMAT format; 538330a5e8faSwyllys BIO *in = NULL; 538430a5e8faSwyllys X509 *xcert = NULL; 538530a5e8faSwyllys X509_CRL *xcrl = NULL; 538630a5e8faSwyllys STACK_OF(X509_REVOKED) *revoke_stack = NULL; 538730a5e8faSwyllys X509_REVOKED *revoke; 538830a5e8faSwyllys int i; 538930a5e8faSwyllys char *crlfilename, *crlfile, *dirpath, *certfile; 539030a5e8faSwyllys 539130a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 539230a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 539330a5e8faSwyllys } 539430a5e8faSwyllys 539530a5e8faSwyllys crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, 539630a5e8faSwyllys attrlist, numattr); 539730a5e8faSwyllys 539830a5e8faSwyllys if (crlfilename == NULL) 539930a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 540030a5e8faSwyllys 540130a5e8faSwyllys certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr); 540230a5e8faSwyllys if (certfile == NULL) 540330a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 540430a5e8faSwyllys 540530a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 540630a5e8faSwyllys 540730a5e8faSwyllys crlfile = get_fullpath(dirpath, crlfilename); 540830a5e8faSwyllys 540930a5e8faSwyllys if (crlfile == NULL) 541030a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 541130a5e8faSwyllys 541230a5e8faSwyllys if (isdir(crlfile)) { 541330a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 541430a5e8faSwyllys goto end; 541530a5e8faSwyllys } 541630a5e8faSwyllys 541730a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 541830a5e8faSwyllys if (ret != KMF_OK) 541930a5e8faSwyllys goto end; 542030a5e8faSwyllys 542130a5e8faSwyllys /* Read the CRL file and load it into a X509_CRL structure */ 542230a5e8faSwyllys in = BIO_new_file(crlfilename, "rb"); 542330a5e8faSwyllys if (in == NULL) { 542430a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 542530a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 542630a5e8faSwyllys goto end; 542730a5e8faSwyllys } 542830a5e8faSwyllys 542930a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 543030a5e8faSwyllys xcrl = d2i_X509_CRL_bio(in, NULL); 543130a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 543230a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); 543330a5e8faSwyllys } 543430a5e8faSwyllys 543530a5e8faSwyllys if (xcrl == NULL) { 543630a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 543730a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 543830a5e8faSwyllys goto end; 543930a5e8faSwyllys } 544030a5e8faSwyllys (void) BIO_free(in); 544130a5e8faSwyllys 544230a5e8faSwyllys /* Read the Certificate file and load it into a X509 structure */ 544330a5e8faSwyllys ret = kmf_is_cert_file(handle, certfile, &format); 544430a5e8faSwyllys if (ret != KMF_OK) 544530a5e8faSwyllys goto end; 544630a5e8faSwyllys 544730a5e8faSwyllys in = BIO_new_file(certfile, "rb"); 544830a5e8faSwyllys if (in == NULL) { 544930a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 545030a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 545130a5e8faSwyllys goto end; 545230a5e8faSwyllys } 545330a5e8faSwyllys 545430a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 545530a5e8faSwyllys xcert = d2i_X509_bio(in, NULL); 545630a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 545730a5e8faSwyllys xcert = PEM_read_bio_X509(in, NULL, NULL, NULL); 545830a5e8faSwyllys } 545930a5e8faSwyllys 546030a5e8faSwyllys if (xcert == NULL) { 546130a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 546230a5e8faSwyllys ret = KMF_ERR_BAD_CERTFILE; 546330a5e8faSwyllys goto end; 546430a5e8faSwyllys } 546530a5e8faSwyllys 546630a5e8faSwyllys /* Check if the certificate and the CRL have same issuer */ 5467*300fdee2SAndy Fiddaman if (X509_NAME_cmp(X509_get_issuer_name(xcert), 5468*300fdee2SAndy Fiddaman X509_CRL_get_issuer(xcrl)) != 0) { 546930a5e8faSwyllys ret = KMF_ERR_ISSUER; 547030a5e8faSwyllys goto end; 547130a5e8faSwyllys } 547230a5e8faSwyllys 547330a5e8faSwyllys /* Check to see if the certificate serial number is revoked */ 547430a5e8faSwyllys revoke_stack = X509_CRL_get_REVOKED(xcrl); 547530a5e8faSwyllys if (sk_X509_REVOKED_num(revoke_stack) <= 0) { 547630a5e8faSwyllys /* No revoked certificates in the CRL file */ 547730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 547830a5e8faSwyllys ret = KMF_ERR_EMPTY_CRL; 547930a5e8faSwyllys goto end; 548030a5e8faSwyllys } 548130a5e8faSwyllys 548230a5e8faSwyllys for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) { 5483d7141854SRobert Mustacchi /* LINTED E_BAD_PTR_CAST_ALIGN */ 548430a5e8faSwyllys revoke = sk_X509_REVOKED_value(revoke_stack, i); 5485*300fdee2SAndy Fiddaman if (ASN1_INTEGER_cmp(X509_get_serialNumber(xcert), 5486*300fdee2SAndy Fiddaman X509_REVOKED_get0_serialNumber(revoke)) == 0) { 548730a5e8faSwyllys break; 548830a5e8faSwyllys } 548930a5e8faSwyllys } 549030a5e8faSwyllys 549130a5e8faSwyllys if (i < sk_X509_REVOKED_num(revoke_stack)) { 549230a5e8faSwyllys ret = KMF_OK; 549330a5e8faSwyllys } else { 549430a5e8faSwyllys ret = KMF_ERR_NOT_REVOKED; 549530a5e8faSwyllys } 549630a5e8faSwyllys 549730a5e8faSwyllys end: 549830a5e8faSwyllys if (in != NULL) 549930a5e8faSwyllys (void) BIO_free(in); 550030a5e8faSwyllys if (xcrl != NULL) 550130a5e8faSwyllys X509_CRL_free(xcrl); 550230a5e8faSwyllys if (xcert != NULL) 550330a5e8faSwyllys X509_free(xcert); 550430a5e8faSwyllys 550530a5e8faSwyllys return (ret); 550630a5e8faSwyllys } 550730a5e8faSwyllys 550830a5e8faSwyllys KMF_RETURN 550930a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert) 551030a5e8faSwyllys { 551130a5e8faSwyllys KMF_RETURN ret = KMF_OK; 551230a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 551330a5e8faSwyllys BIO *bcrl = NULL; 551430a5e8faSwyllys X509_CRL *xcrl = NULL; 551530a5e8faSwyllys X509 *xcert = NULL; 551630a5e8faSwyllys EVP_PKEY *pkey; 551730a5e8faSwyllys int sslret; 551830a5e8faSwyllys KMF_ENCODE_FORMAT crl_format; 551930a5e8faSwyllys unsigned char *p; 552030a5e8faSwyllys long len; 552130a5e8faSwyllys 552230a5e8faSwyllys if (handle == NULL || crlname == NULL || tacert == NULL) { 552330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 552430a5e8faSwyllys } 552530a5e8faSwyllys 552630a5e8faSwyllys ret = kmf_get_file_format(crlname, &crl_format); 552730a5e8faSwyllys if (ret != KMF_OK) 552830a5e8faSwyllys return (ret); 552930a5e8faSwyllys 553030a5e8faSwyllys bcrl = BIO_new_file(crlname, "rb"); 553130a5e8faSwyllys if (bcrl == NULL) { 553230a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 553330a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 553430a5e8faSwyllys goto cleanup; 553530a5e8faSwyllys } 553630a5e8faSwyllys 553730a5e8faSwyllys if (crl_format == KMF_FORMAT_ASN1) { 553830a5e8faSwyllys xcrl = d2i_X509_CRL_bio(bcrl, NULL); 553930a5e8faSwyllys } else if (crl_format == KMF_FORMAT_PEM) { 554030a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL); 554130a5e8faSwyllys } else { 554230a5e8faSwyllys ret = KMF_ERR_BAD_PARAMETER; 554330a5e8faSwyllys goto cleanup; 554430a5e8faSwyllys } 554530a5e8faSwyllys 554630a5e8faSwyllys if (xcrl == NULL) { 554730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 554830a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 554930a5e8faSwyllys goto cleanup; 555030a5e8faSwyllys } 555130a5e8faSwyllys 555230a5e8faSwyllys p = tacert->Data; 555330a5e8faSwyllys len = tacert->Length; 555430a5e8faSwyllys xcert = d2i_X509(NULL, (const uchar_t **)&p, len); 555530a5e8faSwyllys 555630a5e8faSwyllys if (xcert == NULL) { 555730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 555830a5e8faSwyllys ret = KMF_ERR_BAD_CERTFILE; 555930a5e8faSwyllys goto cleanup; 556030a5e8faSwyllys } 556130a5e8faSwyllys 556230a5e8faSwyllys /* Get issuer certificate public key */ 556330a5e8faSwyllys pkey = X509_get_pubkey(xcert); 556430a5e8faSwyllys if (pkey == NULL) { 556530a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 556630a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 556730a5e8faSwyllys goto cleanup; 556830a5e8faSwyllys } 556930a5e8faSwyllys 557030a5e8faSwyllys /* Verify CRL signature */ 557130a5e8faSwyllys sslret = X509_CRL_verify(xcrl, pkey); 557230a5e8faSwyllys EVP_PKEY_free(pkey); 557330a5e8faSwyllys if (sslret > 0) { 557430a5e8faSwyllys ret = KMF_OK; 557530a5e8faSwyllys } else { 557630a5e8faSwyllys SET_ERROR(kmfh, sslret); 557730a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 557830a5e8faSwyllys } 557930a5e8faSwyllys 558030a5e8faSwyllys cleanup: 558130a5e8faSwyllys if (bcrl != NULL) 558230a5e8faSwyllys (void) BIO_free(bcrl); 558330a5e8faSwyllys 558430a5e8faSwyllys if (xcrl != NULL) 558530a5e8faSwyllys X509_CRL_free(xcrl); 558630a5e8faSwyllys 558730a5e8faSwyllys if (xcert != NULL) 558830a5e8faSwyllys X509_free(xcert); 558930a5e8faSwyllys 559030a5e8faSwyllys return (ret); 559130a5e8faSwyllys 559230a5e8faSwyllys } 559330a5e8faSwyllys 559430a5e8faSwyllys KMF_RETURN 559530a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname) 559630a5e8faSwyllys { 559730a5e8faSwyllys KMF_RETURN ret = KMF_OK; 559830a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 559930a5e8faSwyllys KMF_ENCODE_FORMAT crl_format; 560030a5e8faSwyllys BIO *bcrl = NULL; 560130a5e8faSwyllys X509_CRL *xcrl = NULL; 560230a5e8faSwyllys int i; 560330a5e8faSwyllys 560430a5e8faSwyllys if (handle == NULL || crlname == NULL) { 560530a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 560630a5e8faSwyllys } 560730a5e8faSwyllys 560830a5e8faSwyllys ret = kmf_is_crl_file(handle, crlname, &crl_format); 560930a5e8faSwyllys if (ret != KMF_OK) 561030a5e8faSwyllys return (ret); 561130a5e8faSwyllys 561230a5e8faSwyllys bcrl = BIO_new_file(crlname, "rb"); 561330a5e8faSwyllys if (bcrl == NULL) { 561430a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 561530a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 561630a5e8faSwyllys goto cleanup; 561730a5e8faSwyllys } 561830a5e8faSwyllys 56195b3e1433Swyllys if (crl_format == KMF_FORMAT_ASN1) 562030a5e8faSwyllys xcrl = d2i_X509_CRL_bio(bcrl, NULL); 56215b3e1433Swyllys else if (crl_format == KMF_FORMAT_PEM) 562230a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL); 562330a5e8faSwyllys 562430a5e8faSwyllys if (xcrl == NULL) { 562530a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 562630a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 562730a5e8faSwyllys goto cleanup; 562830a5e8faSwyllys } 5629*300fdee2SAndy Fiddaman i = X509_cmp_time(X509_CRL_get0_lastUpdate(xcrl), NULL); 563030a5e8faSwyllys if (i >= 0) { 563130a5e8faSwyllys ret = KMF_ERR_VALIDITY_PERIOD; 563230a5e8faSwyllys goto cleanup; 563330a5e8faSwyllys } 5634*300fdee2SAndy Fiddaman if (X509_CRL_get0_nextUpdate(xcrl)) { 5635*300fdee2SAndy Fiddaman i = X509_cmp_time(X509_CRL_get0_nextUpdate(xcrl), NULL); 563630a5e8faSwyllys 563730a5e8faSwyllys if (i <= 0) { 563830a5e8faSwyllys ret = KMF_ERR_VALIDITY_PERIOD; 563930a5e8faSwyllys goto cleanup; 564030a5e8faSwyllys } 564130a5e8faSwyllys } 564230a5e8faSwyllys 564330a5e8faSwyllys ret = KMF_OK; 564430a5e8faSwyllys 564530a5e8faSwyllys cleanup: 564630a5e8faSwyllys if (bcrl != NULL) 564730a5e8faSwyllys (void) BIO_free(bcrl); 564830a5e8faSwyllys 564930a5e8faSwyllys if (xcrl != NULL) 565030a5e8faSwyllys X509_CRL_free(xcrl); 565130a5e8faSwyllys 565230a5e8faSwyllys return (ret); 565330a5e8faSwyllys } 5654