199ebb4caSwyllys /* 2*2c9a247fSWyllys Ingersoll * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 3*2c9a247fSWyllys Ingersoll * 499ebb4caSwyllys * Use is subject to license terms. 599ebb4caSwyllys */ 69a767088Shaimay /* 79a767088Shaimay * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL 89a767088Shaimay * project 2000. 99a767088Shaimay */ 109a767088Shaimay /* 119a767088Shaimay * ==================================================================== 129a767088Shaimay * Copyright (c) 2000-2004 The OpenSSL Project. All rights reserved. 139a767088Shaimay * 149a767088Shaimay * Redistribution and use in source and binary forms, with or without 159a767088Shaimay * modification, are permitted provided that the following conditions 169a767088Shaimay * are met: 179a767088Shaimay * 189a767088Shaimay * 1. Redistributions of source code must retain the above copyright 199a767088Shaimay * notice, this list of conditions and the following disclaimer. 209a767088Shaimay * 219a767088Shaimay * 2. Redistributions in binary form must reproduce the above copyright 229a767088Shaimay * notice, this list of conditions and the following disclaimer in 239a767088Shaimay * the documentation and/or other materials provided with the 249a767088Shaimay * distribution. 259a767088Shaimay * 269a767088Shaimay * 3. All advertising materials mentioning features or use of this 279a767088Shaimay * software must display the following acknowledgment: 289a767088Shaimay * "This product includes software developed by the OpenSSL Project 299a767088Shaimay * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 309a767088Shaimay * 319a767088Shaimay * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 329a767088Shaimay * endorse or promote products derived from this software without 339a767088Shaimay * prior written permission. For written permission, please contact 349a767088Shaimay * licensing@OpenSSL.org. 359a767088Shaimay * 369a767088Shaimay * 5. Products derived from this software may not be called "OpenSSL" 379a767088Shaimay * nor may "OpenSSL" appear in their names without prior written 389a767088Shaimay * permission of the OpenSSL Project. 399a767088Shaimay * 409a767088Shaimay * 6. Redistributions of any form whatsoever must retain the following 419a767088Shaimay * acknowledgment: 429a767088Shaimay * "This product includes software developed by the OpenSSL Project 439a767088Shaimay * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 449a767088Shaimay * 459a767088Shaimay * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 469a767088Shaimay * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 479a767088Shaimay * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 489a767088Shaimay * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 499a767088Shaimay * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 509a767088Shaimay * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 519a767088Shaimay * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 529a767088Shaimay * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 539a767088Shaimay * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 549a767088Shaimay * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 559a767088Shaimay * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 569a767088Shaimay * OF THE POSSIBILITY OF SUCH DAMAGE. 579a767088Shaimay * ==================================================================== 589a767088Shaimay * 599a767088Shaimay * This product includes cryptographic software written by Eric Young 609a767088Shaimay * (eay@cryptsoft.com). This product includes software written by Tim 619a767088Shaimay * Hudson (tjh@cryptsoft.com). 629a767088Shaimay * 639a767088Shaimay */ 6499ebb4caSwyllys 6571593db2Swyllys #include <stdlib.h> 6699ebb4caSwyllys #include <kmfapiP.h> 6799ebb4caSwyllys #include <ber_der.h> 6899ebb4caSwyllys #include <fcntl.h> 6999ebb4caSwyllys #include <sys/stat.h> 7099ebb4caSwyllys #include <dirent.h> 7199ebb4caSwyllys #include <cryptoutil.h> 7299ebb4caSwyllys #include <synch.h> 7399ebb4caSwyllys #include <thread.h> 7499ebb4caSwyllys 7599ebb4caSwyllys /* OPENSSL related headers */ 7699ebb4caSwyllys #include <openssl/bio.h> 7799ebb4caSwyllys #include <openssl/bn.h> 7899ebb4caSwyllys #include <openssl/asn1.h> 7999ebb4caSwyllys #include <openssl/err.h> 8099ebb4caSwyllys #include <openssl/bn.h> 8199ebb4caSwyllys #include <openssl/x509.h> 8299ebb4caSwyllys #include <openssl/rsa.h> 8399ebb4caSwyllys #include <openssl/dsa.h> 8499ebb4caSwyllys #include <openssl/x509v3.h> 8599ebb4caSwyllys #include <openssl/objects.h> 8699ebb4caSwyllys #include <openssl/pem.h> 8799ebb4caSwyllys #include <openssl/pkcs12.h> 8899ebb4caSwyllys #include <openssl/ocsp.h> 8999ebb4caSwyllys #include <openssl/des.h> 9099ebb4caSwyllys #include <openssl/rand.h> 9199ebb4caSwyllys 9299ebb4caSwyllys #define PRINT_ANY_EXTENSION (\ 9399ebb4caSwyllys KMF_X509_EXT_KEY_USAGE |\ 9499ebb4caSwyllys KMF_X509_EXT_CERT_POLICIES |\ 9599ebb4caSwyllys KMF_X509_EXT_SUBJALTNAME |\ 9699ebb4caSwyllys KMF_X509_EXT_BASIC_CONSTRAINTS |\ 9799ebb4caSwyllys KMF_X509_EXT_NAME_CONSTRAINTS |\ 9899ebb4caSwyllys KMF_X509_EXT_POLICY_CONSTRAINTS |\ 9999ebb4caSwyllys KMF_X509_EXT_EXT_KEY_USAGE |\ 10099ebb4caSwyllys KMF_X509_EXT_INHIBIT_ANY_POLICY |\ 10199ebb4caSwyllys KMF_X509_EXT_AUTH_KEY_ID |\ 10299ebb4caSwyllys KMF_X509_EXT_SUBJ_KEY_ID |\ 10399ebb4caSwyllys KMF_X509_EXT_POLICY_MAPPING) 10499ebb4caSwyllys 10599ebb4caSwyllys static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76, 10699ebb4caSwyllys 0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69, 10799ebb4caSwyllys 0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c, 10899ebb4caSwyllys 0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82, 10999ebb4caSwyllys 0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e, 11099ebb4caSwyllys 0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a, 11199ebb4caSwyllys 0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24, 11299ebb4caSwyllys 0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02, 11399ebb4caSwyllys 0x91 }; 11499ebb4caSwyllys 11599ebb4caSwyllys static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8, 11699ebb4caSwyllys 0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4, 11799ebb4caSwyllys 0x8e, 0xda, 0xce, 0x91, 0x5f }; 11899ebb4caSwyllys 11999ebb4caSwyllys static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a, 12099ebb4caSwyllys 0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5, 12199ebb4caSwyllys 0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef, 12299ebb4caSwyllys 0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c, 12399ebb4caSwyllys 0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba, 12499ebb4caSwyllys 0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c, 12599ebb4caSwyllys 0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08, 12699ebb4caSwyllys 0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88, 12799ebb4caSwyllys 0x02 }; 12899ebb4caSwyllys 12999ebb4caSwyllys #define SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \ 13099ebb4caSwyllys h->lasterr.errcode = c; 13199ebb4caSwyllys 13299ebb4caSwyllys #define SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c; 13399ebb4caSwyllys 1345b3e1433Swyllys /* 1355b3e1433Swyllys * Declare some new macros for managing stacks of EVP_PKEYS, similar to 1365b3e1433Swyllys * what wanboot did. 1375b3e1433Swyllys */ 1385b3e1433Swyllys DECLARE_STACK_OF(EVP_PKEY) 1395b3e1433Swyllys 1405b3e1433Swyllys #define sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY) 1415b3e1433Swyllys #define sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st)) 1425b3e1433Swyllys #define sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st)) 1435b3e1433Swyllys #define sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i)) 1445b3e1433Swyllys #define sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val)) 1455b3e1433Swyllys #define sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \ 1465b3e1433Swyllys (free_func)) 1475b3e1433Swyllys 14899ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX; 14999ebb4caSwyllys static int ssl_initialized = 0; 15030a5e8faSwyllys static BIO *bio_err = NULL; 15130a5e8faSwyllys 15230a5e8faSwyllys static int 15330a5e8faSwyllys test_for_file(char *, mode_t); 1545b3e1433Swyllys static KMF_RETURN 1555b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *, char *, int, 1565b3e1433Swyllys STACK_OF(EVP_PKEY) *, STACK_OF(X509) *); 1575b3e1433Swyllys 1585b3e1433Swyllys static KMF_RETURN 1595b3e1433Swyllys local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *, 1605b3e1433Swyllys int, KMF_KEY_HANDLE *, char *); 1615b3e1433Swyllys 1625b3e1433Swyllys static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int); 16399ebb4caSwyllys 16471593db2Swyllys static KMF_RETURN 16530a5e8faSwyllys extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *, 16602744e81Swyllys CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *); 16771593db2Swyllys 16871593db2Swyllys static KMF_RETURN 16930a5e8faSwyllys kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY, 17030a5e8faSwyllys char *, KMF_DATA *); 17130a5e8faSwyllys 17230a5e8faSwyllys static KMF_RETURN 17330a5e8faSwyllys load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY, 17430a5e8faSwyllys char *, KMF_DATA **, uint32_t *); 17571593db2Swyllys 17602744e81Swyllys static KMF_RETURN 17702744e81Swyllys sslBN2KMFBN(BIGNUM *, KMF_BIGINT *); 17802744e81Swyllys 17902744e81Swyllys static EVP_PKEY * 18002744e81Swyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *); 18102744e81Swyllys 18230a5e8faSwyllys static KMF_RETURN 18330a5e8faSwyllys convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *); 18430a5e8faSwyllys 18599ebb4caSwyllys KMF_RETURN 18630a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 18799ebb4caSwyllys 18899ebb4caSwyllys void 18999ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *); 19099ebb4caSwyllys 19199ebb4caSwyllys KMF_RETURN 19230a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *); 19399ebb4caSwyllys 19499ebb4caSwyllys KMF_RETURN 19530a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *); 19699ebb4caSwyllys 19799ebb4caSwyllys KMF_RETURN 19830a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 19930a5e8faSwyllys 20030a5e8faSwyllys KMF_RETURN 20130a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 20299ebb4caSwyllys 20399ebb4caSwyllys KMF_RETURN 20499ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *); 20599ebb4caSwyllys 20699ebb4caSwyllys KMF_RETURN 20799ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *, 20899ebb4caSwyllys KMF_DATA *, KMF_DATA *); 20999ebb4caSwyllys 21099ebb4caSwyllys KMF_RETURN 21130a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 21299ebb4caSwyllys 21399ebb4caSwyllys KMF_RETURN 21430a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 21599ebb4caSwyllys 21699ebb4caSwyllys KMF_RETURN 21730a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 21899ebb4caSwyllys 21999ebb4caSwyllys KMF_RETURN 22030a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 22199ebb4caSwyllys 22299ebb4caSwyllys KMF_RETURN 22330a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 22499ebb4caSwyllys 22599ebb4caSwyllys KMF_RETURN 22699ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *, 22799ebb4caSwyllys KMF_PRINTABLE_ITEM, char *); 22899ebb4caSwyllys 22999ebb4caSwyllys KMF_RETURN 23099ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T, char **); 23199ebb4caSwyllys 23299ebb4caSwyllys KMF_RETURN 23330a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 23499ebb4caSwyllys 23599ebb4caSwyllys KMF_RETURN 23699ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *, 23799ebb4caSwyllys KMF_DATA *, KMF_DATA *); 23899ebb4caSwyllys 23999ebb4caSwyllys KMF_RETURN 24030a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 24199ebb4caSwyllys 24299ebb4caSwyllys KMF_RETURN 24330a5e8faSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 24499ebb4caSwyllys 24599ebb4caSwyllys KMF_RETURN 24630a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 24799ebb4caSwyllys 24899ebb4caSwyllys KMF_RETURN 24930a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 25099ebb4caSwyllys 25199ebb4caSwyllys KMF_RETURN 25230a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 25399ebb4caSwyllys 25499ebb4caSwyllys KMF_RETURN 25599ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *); 25699ebb4caSwyllys 25799ebb4caSwyllys KMF_RETURN 25830a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *); 25999ebb4caSwyllys 26099ebb4caSwyllys KMF_RETURN 26130a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *); 26299ebb4caSwyllys 26399ebb4caSwyllys static 26499ebb4caSwyllys KMF_PLUGIN_FUNCLIST openssl_plugin_table = 26599ebb4caSwyllys { 26699ebb4caSwyllys 1, /* Version */ 26799ebb4caSwyllys NULL, /* ConfigureKeystore */ 26899ebb4caSwyllys OpenSSL_FindCert, 26999ebb4caSwyllys OpenSSL_FreeKMFCert, 27099ebb4caSwyllys OpenSSL_StoreCert, 27199ebb4caSwyllys NULL, /* ImportCert */ 27299ebb4caSwyllys OpenSSL_ImportCRL, 27399ebb4caSwyllys OpenSSL_DeleteCert, 27499ebb4caSwyllys OpenSSL_DeleteCRL, 27599ebb4caSwyllys OpenSSL_CreateKeypair, 27699ebb4caSwyllys OpenSSL_FindKey, 27799ebb4caSwyllys OpenSSL_EncodePubKeyData, 27899ebb4caSwyllys OpenSSL_SignData, 27999ebb4caSwyllys OpenSSL_DeleteKey, 28099ebb4caSwyllys OpenSSL_ListCRL, 28199ebb4caSwyllys NULL, /* FindCRL */ 28299ebb4caSwyllys OpenSSL_FindCertInCRL, 28399ebb4caSwyllys OpenSSL_GetErrorString, 28430a5e8faSwyllys OpenSSL_FindPrikeyByCert, 28599ebb4caSwyllys OpenSSL_DecryptData, 28630a5e8faSwyllys OpenSSL_ExportPK12, 28799ebb4caSwyllys OpenSSL_CreateSymKey, 28899ebb4caSwyllys OpenSSL_GetSymKeyValue, 28999ebb4caSwyllys NULL, /* SetTokenPin */ 29030a5e8faSwyllys OpenSSL_StoreKey, 29199ebb4caSwyllys NULL /* Finalize */ 29299ebb4caSwyllys }; 29399ebb4caSwyllys 29499ebb4caSwyllys static mutex_t *lock_cs; 29599ebb4caSwyllys static long *lock_count; 29699ebb4caSwyllys 29799ebb4caSwyllys static void 298a2d4930dSDan OpenSolaris Anderson /* ARGSUSED1 */ 29999ebb4caSwyllys locking_cb(int mode, int type, char *file, int line) 30099ebb4caSwyllys { 30199ebb4caSwyllys if (mode & CRYPTO_LOCK) { 30299ebb4caSwyllys (void) mutex_lock(&(lock_cs[type])); 30399ebb4caSwyllys lock_count[type]++; 30499ebb4caSwyllys } else { 30599ebb4caSwyllys (void) mutex_unlock(&(lock_cs[type])); 30699ebb4caSwyllys } 30799ebb4caSwyllys } 30899ebb4caSwyllys 30999ebb4caSwyllys static unsigned long 31099ebb4caSwyllys thread_id() 31199ebb4caSwyllys { 31299ebb4caSwyllys return ((unsigned long)thr_self()); 31399ebb4caSwyllys } 31499ebb4caSwyllys 31599ebb4caSwyllys KMF_PLUGIN_FUNCLIST * 31699ebb4caSwyllys KMF_Plugin_Initialize() 31799ebb4caSwyllys { 31899ebb4caSwyllys int i; 31999ebb4caSwyllys 32099ebb4caSwyllys (void) mutex_lock(&init_lock); 32199ebb4caSwyllys if (!ssl_initialized) { 32299ebb4caSwyllys /* 32399ebb4caSwyllys * Add support for extension OIDs that are not yet in the 32499ebb4caSwyllys * openssl default set. 32599ebb4caSwyllys */ 32699ebb4caSwyllys (void) OBJ_create("2.5.29.30", "nameConstraints", 32799ebb4caSwyllys "X509v3 Name Constraints"); 32899ebb4caSwyllys (void) OBJ_create("2.5.29.33", "policyMappings", 32999ebb4caSwyllys "X509v3 Policy Mappings"); 33099ebb4caSwyllys (void) OBJ_create("2.5.29.36", "policyConstraints", 33199ebb4caSwyllys "X509v3 Policy Constraints"); 33299ebb4caSwyllys (void) OBJ_create("2.5.29.46", "freshestCRL", 33399ebb4caSwyllys "X509v3 Freshest CRL"); 33499ebb4caSwyllys (void) OBJ_create("2.5.29.54", "inhibitAnyPolicy", 33599ebb4caSwyllys "X509v3 Inhibit Any-Policy"); 33699ebb4caSwyllys /* 33799ebb4caSwyllys * Set up for thread-safe operation. 33899ebb4caSwyllys */ 33999ebb4caSwyllys lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t)); 34099ebb4caSwyllys if (lock_cs == NULL) { 34199ebb4caSwyllys (void) mutex_unlock(&init_lock); 34299ebb4caSwyllys return (NULL); 34399ebb4caSwyllys } 34499ebb4caSwyllys 34599ebb4caSwyllys lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long)); 34699ebb4caSwyllys if (lock_count == NULL) { 34799ebb4caSwyllys OPENSSL_free(lock_cs); 34899ebb4caSwyllys (void) mutex_unlock(&init_lock); 34999ebb4caSwyllys return (NULL); 35099ebb4caSwyllys } 35199ebb4caSwyllys 35299ebb4caSwyllys for (i = 0; i < CRYPTO_num_locks(); i++) { 35399ebb4caSwyllys lock_count[i] = 0; 35499ebb4caSwyllys (void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL); 35599ebb4caSwyllys } 35699ebb4caSwyllys 35799ebb4caSwyllys CRYPTO_set_id_callback((unsigned long (*)())thread_id); 358*2c9a247fSWyllys Ingersoll if (CRYPTO_get_locking_callback() == NULL) 35999ebb4caSwyllys CRYPTO_set_locking_callback((void (*)())locking_cb); 360*2c9a247fSWyllys Ingersoll 361*2c9a247fSWyllys Ingersoll OpenSSL_add_all_algorithms(); 362*2c9a247fSWyllys Ingersoll 363*2c9a247fSWyllys Ingersoll /* Enable error strings for reporting */ 364*2c9a247fSWyllys Ingersoll ERR_load_crypto_strings(); 365*2c9a247fSWyllys Ingersoll 36699ebb4caSwyllys ssl_initialized = 1; 36799ebb4caSwyllys } 36899ebb4caSwyllys (void) mutex_unlock(&init_lock); 36999ebb4caSwyllys 37099ebb4caSwyllys return (&openssl_plugin_table); 37199ebb4caSwyllys } 37299ebb4caSwyllys /* 37399ebb4caSwyllys * Convert an SSL DN to a KMF DN. 37499ebb4caSwyllys */ 37599ebb4caSwyllys static KMF_RETURN 37699ebb4caSwyllys get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN) 37799ebb4caSwyllys { 37899ebb4caSwyllys KMF_DATA derdata; 37999ebb4caSwyllys KMF_RETURN rv = KMF_OK; 38099ebb4caSwyllys uchar_t *tmp; 38199ebb4caSwyllys 38299ebb4caSwyllys /* Convert to raw DER format */ 38399ebb4caSwyllys derdata.Length = i2d_X509_NAME(sslDN, NULL); 38499ebb4caSwyllys if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length)) 38599ebb4caSwyllys == NULL) { 38699ebb4caSwyllys return (KMF_ERR_MEMORY); 38799ebb4caSwyllys } 38899ebb4caSwyllys (void) i2d_X509_NAME(sslDN, &tmp); 38999ebb4caSwyllys 39099ebb4caSwyllys /* Decode to KMF format */ 39199ebb4caSwyllys rv = DerDecodeName(&derdata, kmfDN); 39299ebb4caSwyllys if (rv != KMF_OK) { 39399ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 39499ebb4caSwyllys } 39599ebb4caSwyllys OPENSSL_free(derdata.Data); 39699ebb4caSwyllys 39799ebb4caSwyllys return (rv); 39899ebb4caSwyllys } 39999ebb4caSwyllys 40030a5e8faSwyllys int 40199ebb4caSwyllys isdir(char *path) 40299ebb4caSwyllys { 40399ebb4caSwyllys struct stat s; 40499ebb4caSwyllys 40599ebb4caSwyllys if (stat(path, &s) == -1) 40699ebb4caSwyllys return (0); 40799ebb4caSwyllys 40830a5e8faSwyllys return ((s.st_mode & S_IFMT) == S_IFDIR); 40999ebb4caSwyllys } 41099ebb4caSwyllys 41199ebb4caSwyllys static KMF_RETURN 41299ebb4caSwyllys ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert) 41399ebb4caSwyllys { 41499ebb4caSwyllys KMF_RETURN rv = KMF_OK; 41599ebb4caSwyllys unsigned char *buf = NULL, *p; 41699ebb4caSwyllys int len; 41799ebb4caSwyllys 41899ebb4caSwyllys /* 41999ebb4caSwyllys * Convert the X509 internal struct to DER encoded data 42099ebb4caSwyllys */ 42199ebb4caSwyllys if ((len = i2d_X509(x509cert, NULL)) < 0) { 42299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 42399ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 42499ebb4caSwyllys goto cleanup; 42599ebb4caSwyllys } 42699ebb4caSwyllys if ((buf = malloc(len)) == NULL) { 42799ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 42899ebb4caSwyllys rv = KMF_ERR_MEMORY; 42999ebb4caSwyllys goto cleanup; 43099ebb4caSwyllys } 43199ebb4caSwyllys 43299ebb4caSwyllys /* 43399ebb4caSwyllys * i2d_X509 will increment the buf pointer so that we need to 43499ebb4caSwyllys * save it. 43599ebb4caSwyllys */ 43699ebb4caSwyllys p = buf; 43799ebb4caSwyllys if ((len = i2d_X509(x509cert, &p)) < 0) { 43899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 43999ebb4caSwyllys free(buf); 44099ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 44199ebb4caSwyllys goto cleanup; 44299ebb4caSwyllys } 44399ebb4caSwyllys 44499ebb4caSwyllys /* caller's responsibility to free it */ 44599ebb4caSwyllys cert->Data = buf; 44699ebb4caSwyllys cert->Length = len; 44799ebb4caSwyllys 44899ebb4caSwyllys cleanup: 44999ebb4caSwyllys if (rv != KMF_OK) { 45099ebb4caSwyllys if (buf) 45199ebb4caSwyllys free(buf); 45299ebb4caSwyllys cert->Data = NULL; 45399ebb4caSwyllys cert->Length = 0; 45499ebb4caSwyllys } 45599ebb4caSwyllys 45699ebb4caSwyllys return (rv); 45799ebb4caSwyllys } 45899ebb4caSwyllys 45930a5e8faSwyllys 46099ebb4caSwyllys static KMF_RETURN 46130a5e8faSwyllys check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial, 46230a5e8faSwyllys boolean_t *match) 46399ebb4caSwyllys { 46499ebb4caSwyllys KMF_RETURN rv = KMF_OK; 46599ebb4caSwyllys boolean_t findIssuer = FALSE; 46699ebb4caSwyllys boolean_t findSubject = FALSE; 46799ebb4caSwyllys boolean_t findSerial = FALSE; 46899ebb4caSwyllys KMF_X509_NAME issuerDN, subjectDN; 46999ebb4caSwyllys KMF_X509_NAME certIssuerDN, certSubjectDN; 47099ebb4caSwyllys 47199ebb4caSwyllys *match = FALSE; 47299ebb4caSwyllys if (xcert == NULL) { 47399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 47499ebb4caSwyllys } 47599ebb4caSwyllys 47699ebb4caSwyllys (void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME)); 47799ebb4caSwyllys (void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME)); 47899ebb4caSwyllys (void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME)); 47999ebb4caSwyllys (void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME)); 48099ebb4caSwyllys 48130a5e8faSwyllys if (issuer != NULL && strlen(issuer)) { 48230a5e8faSwyllys rv = kmf_dn_parser(issuer, &issuerDN); 48399ebb4caSwyllys if (rv != KMF_OK) 48499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 48599ebb4caSwyllys 48699ebb4caSwyllys rv = get_x509_dn(xcert->cert_info->issuer, &certIssuerDN); 48799ebb4caSwyllys if (rv != KMF_OK) { 48830a5e8faSwyllys kmf_free_dn(&issuerDN); 48999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 49099ebb4caSwyllys } 49199ebb4caSwyllys 49299ebb4caSwyllys findIssuer = TRUE; 49399ebb4caSwyllys } 49430a5e8faSwyllys if (subject != NULL && strlen(subject)) { 49530a5e8faSwyllys rv = kmf_dn_parser(subject, &subjectDN); 49699ebb4caSwyllys if (rv != KMF_OK) { 49799ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 49899ebb4caSwyllys goto cleanup; 49999ebb4caSwyllys } 50099ebb4caSwyllys 50199ebb4caSwyllys rv = get_x509_dn(xcert->cert_info->subject, &certSubjectDN); 50299ebb4caSwyllys if (rv != KMF_OK) { 50399ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 50499ebb4caSwyllys goto cleanup; 50599ebb4caSwyllys } 50699ebb4caSwyllys findSubject = TRUE; 50799ebb4caSwyllys } 50830a5e8faSwyllys if (serial != NULL && serial->val != NULL) 50999ebb4caSwyllys findSerial = TRUE; 51099ebb4caSwyllys 51199ebb4caSwyllys if (findSerial) { 51299ebb4caSwyllys BIGNUM *bn; 51399ebb4caSwyllys 51499ebb4caSwyllys /* Comparing BIGNUMs is a pain! */ 51599ebb4caSwyllys bn = ASN1_INTEGER_to_BN(xcert->cert_info->serialNumber, NULL); 51699ebb4caSwyllys if (bn != NULL) { 51799ebb4caSwyllys int bnlen = BN_num_bytes(bn); 51899ebb4caSwyllys 51930a5e8faSwyllys if (bnlen == serial->len) { 52099ebb4caSwyllys uchar_t *a = malloc(bnlen); 52199ebb4caSwyllys if (a == NULL) { 52299ebb4caSwyllys rv = KMF_ERR_MEMORY; 52399ebb4caSwyllys BN_free(bn); 52499ebb4caSwyllys goto cleanup; 52599ebb4caSwyllys } 52699ebb4caSwyllys bnlen = BN_bn2bin(bn, a); 52730a5e8faSwyllys *match = (memcmp(a, serial->val, serial->len) == 52830a5e8faSwyllys 0); 52999ebb4caSwyllys rv = KMF_OK; 53099ebb4caSwyllys free(a); 53199ebb4caSwyllys } 53299ebb4caSwyllys BN_free(bn); 53399ebb4caSwyllys if (!(*match)) 53499ebb4caSwyllys goto cleanup; 53599ebb4caSwyllys } else { 53699ebb4caSwyllys rv = KMF_OK; 53799ebb4caSwyllys goto cleanup; 53899ebb4caSwyllys } 53999ebb4caSwyllys } 54099ebb4caSwyllys if (findIssuer) { 54130a5e8faSwyllys *match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0); 54230a5e8faSwyllys if ((*match) == B_FALSE) { 54330a5e8faSwyllys /* stop checking and bail */ 54499ebb4caSwyllys rv = KMF_OK; 54599ebb4caSwyllys goto cleanup; 54699ebb4caSwyllys } 54799ebb4caSwyllys } 54899ebb4caSwyllys if (findSubject) { 54930a5e8faSwyllys *match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0); 55030a5e8faSwyllys if ((*match) == B_FALSE) { 55130a5e8faSwyllys /* stop checking and bail */ 55299ebb4caSwyllys rv = KMF_OK; 55399ebb4caSwyllys goto cleanup; 55499ebb4caSwyllys } 55599ebb4caSwyllys } 55699ebb4caSwyllys 55799ebb4caSwyllys *match = TRUE; 55899ebb4caSwyllys cleanup: 55999ebb4caSwyllys if (findIssuer) { 56030a5e8faSwyllys kmf_free_dn(&issuerDN); 56130a5e8faSwyllys kmf_free_dn(&certIssuerDN); 56299ebb4caSwyllys } 56399ebb4caSwyllys if (findSubject) { 56430a5e8faSwyllys kmf_free_dn(&subjectDN); 56530a5e8faSwyllys kmf_free_dn(&certSubjectDN); 56699ebb4caSwyllys } 56799ebb4caSwyllys 56899ebb4caSwyllys return (rv); 56999ebb4caSwyllys } 57099ebb4caSwyllys 57130a5e8faSwyllys 57230a5e8faSwyllys /* 57330a5e8faSwyllys * This function loads a certificate file into an X509 data structure, and 57430a5e8faSwyllys * checks if its issuer, subject or the serial number matches with those 57530a5e8faSwyllys * values. If it matches, then return the X509 data structure. 57630a5e8faSwyllys */ 57799ebb4caSwyllys static KMF_RETURN 57899ebb4caSwyllys load_X509cert(KMF_HANDLE *kmfh, 57930a5e8faSwyllys char *issuer, char *subject, KMF_BIGINT *serial, 58030a5e8faSwyllys char *pathname, X509 **outcert) 58199ebb4caSwyllys { 58299ebb4caSwyllys KMF_RETURN rv = KMF_OK; 58399ebb4caSwyllys X509 *xcert = NULL; 58499ebb4caSwyllys BIO *bcert = NULL; 58599ebb4caSwyllys boolean_t match = FALSE; 58699ebb4caSwyllys KMF_ENCODE_FORMAT format; 58799ebb4caSwyllys 58899ebb4caSwyllys /* 58999ebb4caSwyllys * auto-detect the file format, regardless of what 59099ebb4caSwyllys * the 'format' parameters in the params say. 59199ebb4caSwyllys */ 59230a5e8faSwyllys rv = kmf_get_file_format(pathname, &format); 59399ebb4caSwyllys if (rv != KMF_OK) { 59499ebb4caSwyllys if (rv == KMF_ERR_OPEN_FILE) 59599ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND; 59699ebb4caSwyllys return (rv); 59799ebb4caSwyllys } 59899ebb4caSwyllys 59999ebb4caSwyllys /* Not ASN1(DER) format */ 60099ebb4caSwyllys if ((bcert = BIO_new_file(pathname, "rb")) == NULL) { 60199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 60299ebb4caSwyllys rv = KMF_ERR_OPEN_FILE; 60399ebb4caSwyllys goto cleanup; 60499ebb4caSwyllys } 60599ebb4caSwyllys 60699ebb4caSwyllys if (format == KMF_FORMAT_PEM) 60799ebb4caSwyllys xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL); 60899ebb4caSwyllys else if (format == KMF_FORMAT_ASN1) 60999ebb4caSwyllys xcert = d2i_X509_bio(bcert, NULL); 61099ebb4caSwyllys else if (format == KMF_FORMAT_PKCS12) { 61199ebb4caSwyllys PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL); 61299ebb4caSwyllys if (p12 != NULL) { 61399ebb4caSwyllys (void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL); 61499ebb4caSwyllys PKCS12_free(p12); 61599ebb4caSwyllys p12 = NULL; 61699ebb4caSwyllys } else { 61799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 61899ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 61999ebb4caSwyllys } 62099ebb4caSwyllys } else { 62199ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 62299ebb4caSwyllys goto cleanup; 62399ebb4caSwyllys } 62499ebb4caSwyllys 62599ebb4caSwyllys if (xcert == NULL) { 62699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 62799ebb4caSwyllys rv = KMF_ERR_BAD_CERT_FORMAT; 62899ebb4caSwyllys goto cleanup; 62999ebb4caSwyllys } 63099ebb4caSwyllys 63130a5e8faSwyllys if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK || 63230a5e8faSwyllys match == FALSE) { 63399ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND; 63499ebb4caSwyllys goto cleanup; 63599ebb4caSwyllys } 63699ebb4caSwyllys 63799ebb4caSwyllys if (outcert != NULL) { 63899ebb4caSwyllys *outcert = xcert; 63999ebb4caSwyllys } 64099ebb4caSwyllys 64199ebb4caSwyllys cleanup: 64299ebb4caSwyllys if (bcert != NULL) (void) BIO_free(bcert); 64399ebb4caSwyllys if (rv != KMF_OK && xcert != NULL) 64499ebb4caSwyllys X509_free(xcert); 64599ebb4caSwyllys 64699ebb4caSwyllys return (rv); 64799ebb4caSwyllys } 64899ebb4caSwyllys 64971593db2Swyllys static int 65071593db2Swyllys datacmp(const void *a, const void *b) 65171593db2Swyllys { 65271593db2Swyllys KMF_DATA *adata = (KMF_DATA *)a; 65371593db2Swyllys KMF_DATA *bdata = (KMF_DATA *)b; 65471593db2Swyllys if (adata->Length > bdata->Length) 65571593db2Swyllys return (-1); 65671593db2Swyllys if (adata->Length < bdata->Length) 65771593db2Swyllys return (1); 65871593db2Swyllys return (0); 65971593db2Swyllys } 66071593db2Swyllys 66171593db2Swyllys static KMF_RETURN 66230a5e8faSwyllys load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial, 66330a5e8faSwyllys KMF_CERT_VALIDITY validity, char *pathname, 66471593db2Swyllys KMF_DATA **certlist, uint32_t *numcerts) 66571593db2Swyllys { 66671593db2Swyllys KMF_RETURN rv = KMF_OK; 66771593db2Swyllys int i; 66871593db2Swyllys KMF_DATA *certs = NULL; 66971593db2Swyllys int nc = 0; 67071593db2Swyllys int hits = 0; 67171593db2Swyllys KMF_ENCODE_FORMAT format; 67271593db2Swyllys 67330a5e8faSwyllys rv = kmf_get_file_format(pathname, &format); 67471593db2Swyllys if (rv != KMF_OK) { 67571593db2Swyllys if (rv == KMF_ERR_OPEN_FILE) 67671593db2Swyllys rv = KMF_ERR_CERT_NOT_FOUND; 67771593db2Swyllys return (rv); 67871593db2Swyllys } 67971593db2Swyllys if (format == KMF_FORMAT_ASN1) { 68071593db2Swyllys /* load a single certificate */ 68171593db2Swyllys certs = (KMF_DATA *)malloc(sizeof (KMF_DATA)); 68271593db2Swyllys if (certs == NULL) 68371593db2Swyllys return (KMF_ERR_MEMORY); 68471593db2Swyllys certs->Data = NULL; 68571593db2Swyllys certs->Length = 0; 68630a5e8faSwyllys rv = kmf_load_cert(kmfh, issuer, subject, serial, validity, 68730a5e8faSwyllys pathname, certs); 68871593db2Swyllys if (rv == KMF_OK) { 68971593db2Swyllys *certlist = certs; 69071593db2Swyllys *numcerts = 1; 691a2d4930dSDan OpenSolaris Anderson } else { 692a2d4930dSDan OpenSolaris Anderson kmf_free_data(certs); 693a2d4930dSDan OpenSolaris Anderson free(certs); 694a2d4930dSDan OpenSolaris Anderson certs = NULL; 69571593db2Swyllys } 69671593db2Swyllys return (rv); 69771593db2Swyllys } else if (format == KMF_FORMAT_PKCS12) { 69871593db2Swyllys /* We need a credential to access a PKCS#12 file */ 69971593db2Swyllys rv = KMF_ERR_BAD_CERT_FORMAT; 70071593db2Swyllys } else if (format == KMF_FORMAT_PEM || 70171593db2Swyllys format != KMF_FORMAT_PEM_KEYPAIR) { 702e65e5c2dSWyllys Ingersoll 70371593db2Swyllys /* This function only works on PEM files */ 70430a5e8faSwyllys rv = extract_pem(kmfh, issuer, subject, serial, pathname, 70534acef67Swyllys (uchar_t *)NULL, 0, NULL, &certs, &nc); 70671593db2Swyllys } else { 70771593db2Swyllys return (KMF_ERR_ENCODING); 70871593db2Swyllys } 70971593db2Swyllys 71071593db2Swyllys if (rv != KMF_OK) 71171593db2Swyllys return (rv); 71271593db2Swyllys 71371593db2Swyllys for (i = 0; i < nc; i++) { 71430a5e8faSwyllys if (validity == KMF_NONEXPIRED_CERTS) { 71530a5e8faSwyllys rv = kmf_check_cert_date(kmfh, &certs[i]); 71630a5e8faSwyllys } else if (validity == KMF_EXPIRED_CERTS) { 71730a5e8faSwyllys rv = kmf_check_cert_date(kmfh, &certs[i]); 71871593db2Swyllys if (rv == KMF_OK) 71971593db2Swyllys rv = KMF_ERR_CERT_NOT_FOUND; 72071593db2Swyllys if (rv == KMF_ERR_VALIDITY_PERIOD) 72171593db2Swyllys rv = KMF_OK; 72271593db2Swyllys } 72371593db2Swyllys if (rv != KMF_OK) { 72471593db2Swyllys /* Remove this cert from the list by clearing it. */ 72530a5e8faSwyllys kmf_free_data(&certs[i]); 72671593db2Swyllys } else { 72771593db2Swyllys hits++; /* count valid certs found */ 72871593db2Swyllys } 72971593db2Swyllys rv = KMF_OK; 73071593db2Swyllys } 731a2d4930dSDan OpenSolaris Anderson if (rv == KMF_OK && hits > 0) { 73271593db2Swyllys /* 73371593db2Swyllys * Sort the list of certs by length to put the cleared ones 73471593db2Swyllys * at the end so they don't get accessed by the caller. 73571593db2Swyllys */ 73671593db2Swyllys qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp); 73771593db2Swyllys *certlist = certs; 73871593db2Swyllys 73971593db2Swyllys /* since we sorted the list, just return the number of hits */ 74071593db2Swyllys *numcerts = hits; 741a2d4930dSDan OpenSolaris Anderson } else { 742e65e5c2dSWyllys Ingersoll if (rv == KMF_OK && hits == 0) 743a2d4930dSDan OpenSolaris Anderson rv = KMF_ERR_CERT_NOT_FOUND; 744a2d4930dSDan OpenSolaris Anderson if (certs != NULL) { 745a2d4930dSDan OpenSolaris Anderson free(certs); 746a2d4930dSDan OpenSolaris Anderson certs = NULL; 747a2d4930dSDan OpenSolaris Anderson } 748a2d4930dSDan OpenSolaris Anderson } 74971593db2Swyllys return (rv); 75071593db2Swyllys } 75171593db2Swyllys 75299ebb4caSwyllys static KMF_RETURN 75399ebb4caSwyllys kmf_load_cert(KMF_HANDLE *kmfh, 75430a5e8faSwyllys char *issuer, char *subject, KMF_BIGINT *serial, 75530a5e8faSwyllys KMF_CERT_VALIDITY validity, 75699ebb4caSwyllys char *pathname, 75799ebb4caSwyllys KMF_DATA *cert) 75899ebb4caSwyllys { 75999ebb4caSwyllys KMF_RETURN rv = KMF_OK; 76099ebb4caSwyllys X509 *x509cert = NULL; 76199ebb4caSwyllys 76230a5e8faSwyllys rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert); 76399ebb4caSwyllys if (rv == KMF_OK && x509cert != NULL && cert != NULL) { 76499ebb4caSwyllys rv = ssl_cert2KMFDATA(kmfh, x509cert, cert); 76599ebb4caSwyllys if (rv != KMF_OK) { 76699ebb4caSwyllys goto cleanup; 76799ebb4caSwyllys } 76830a5e8faSwyllys if (validity == KMF_NONEXPIRED_CERTS) { 76930a5e8faSwyllys rv = kmf_check_cert_date(kmfh, cert); 77030a5e8faSwyllys } else if (validity == KMF_EXPIRED_CERTS) { 77130a5e8faSwyllys rv = kmf_check_cert_date(kmfh, cert); 77299ebb4caSwyllys if (rv == KMF_OK) { 77399ebb4caSwyllys /* 77499ebb4caSwyllys * This is a valid cert so skip it. 77599ebb4caSwyllys */ 77699ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND; 77799ebb4caSwyllys } 77899ebb4caSwyllys if (rv == KMF_ERR_VALIDITY_PERIOD) { 77999ebb4caSwyllys /* 78099ebb4caSwyllys * We want to return success when we 78199ebb4caSwyllys * find an invalid cert. 78299ebb4caSwyllys */ 78399ebb4caSwyllys rv = KMF_OK; 78499ebb4caSwyllys goto cleanup; 78599ebb4caSwyllys } 78699ebb4caSwyllys } 78799ebb4caSwyllys } 78899ebb4caSwyllys cleanup: 78999ebb4caSwyllys if (x509cert != NULL) 79099ebb4caSwyllys X509_free(x509cert); 79199ebb4caSwyllys 79299ebb4caSwyllys return (rv); 79399ebb4caSwyllys } 79499ebb4caSwyllys 79502744e81Swyllys static KMF_RETURN 79602744e81Swyllys readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey) 79702744e81Swyllys { 79802744e81Swyllys KMF_RETURN ret = KMF_OK; 79902744e81Swyllys KMF_RAW_RSA_KEY rsa; 80002744e81Swyllys BerElement *asn1 = NULL; 80102744e81Swyllys BerValue filebuf; 80202744e81Swyllys BerValue OID = { NULL, 0 }; 80302744e81Swyllys BerValue *Mod = NULL, *PubExp = NULL; 80402744e81Swyllys BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL; 80502744e81Swyllys BerValue *Coef = NULL; 80602744e81Swyllys BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL; 80702744e81Swyllys BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL; 80802744e81Swyllys BIGNUM *qminus1 = NULL; 80902744e81Swyllys BN_CTX *ctx = NULL; 81002744e81Swyllys 81102744e81Swyllys *pkey = NULL; 81202744e81Swyllys 81302744e81Swyllys filebuf.bv_val = (char *)filedata->Data; 81402744e81Swyllys filebuf.bv_len = filedata->Length; 81502744e81Swyllys 81602744e81Swyllys asn1 = kmfder_init(&filebuf); 81702744e81Swyllys if (asn1 == NULL) { 81802744e81Swyllys ret = KMF_ERR_MEMORY; 81902744e81Swyllys goto out; 82002744e81Swyllys } 82102744e81Swyllys 82202744e81Swyllys if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}", 82302744e81Swyllys &OID, &Mod, &PubExp, &PriExp, &Prime1, 82402744e81Swyllys &Prime2, &Coef) == -1) { 82502744e81Swyllys ret = KMF_ERR_ENCODING; 82602744e81Swyllys goto out; 82702744e81Swyllys } 82802744e81Swyllys 82902744e81Swyllys /* 83002744e81Swyllys * We have to derive the 2 Exponents using Bignumber math. 83102744e81Swyllys * Exp1 = PriExp mod (Prime1 - 1) 83202744e81Swyllys * Exp2 = PriExp mod (Prime2 - 1) 83302744e81Swyllys */ 83402744e81Swyllys 83502744e81Swyllys /* D = PrivateExponent */ 83602744e81Swyllys D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D); 83702744e81Swyllys if (D == NULL) { 83802744e81Swyllys ret = KMF_ERR_MEMORY; 83902744e81Swyllys goto out; 84002744e81Swyllys } 84102744e81Swyllys 84202744e81Swyllys /* P = Prime1 (first prime factor of Modulus) */ 84302744e81Swyllys P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P); 84402744e81Swyllys if (D == NULL) { 84502744e81Swyllys ret = KMF_ERR_MEMORY; 84602744e81Swyllys goto out; 84702744e81Swyllys } 84802744e81Swyllys 84902744e81Swyllys /* Q = Prime2 (second prime factor of Modulus) */ 85002744e81Swyllys Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q); 85102744e81Swyllys 85202744e81Swyllys if ((ctx = BN_CTX_new()) == NULL) { 85302744e81Swyllys ret = KMF_ERR_MEMORY; 85402744e81Swyllys goto out; 85502744e81Swyllys } 85602744e81Swyllys 85702744e81Swyllys /* Compute (P - 1) */ 85802744e81Swyllys pminus1 = BN_new(); 85902744e81Swyllys (void) BN_sub(pminus1, P, BN_value_one()); 86002744e81Swyllys 86102744e81Swyllys /* Exponent1 = D mod (P - 1) */ 86202744e81Swyllys Exp1 = BN_new(); 86302744e81Swyllys (void) BN_mod(Exp1, D, pminus1, ctx); 86402744e81Swyllys 86502744e81Swyllys /* Compute (Q - 1) */ 86602744e81Swyllys qminus1 = BN_new(); 86702744e81Swyllys (void) BN_sub(qminus1, Q, BN_value_one()); 86802744e81Swyllys 86902744e81Swyllys /* Exponent2 = D mod (Q - 1) */ 87002744e81Swyllys Exp2 = BN_new(); 87102744e81Swyllys (void) BN_mod(Exp2, D, qminus1, ctx); 87202744e81Swyllys 87302744e81Swyllys /* Coef = (Inverse Q) mod P */ 87402744e81Swyllys COEF = BN_new(); 87502744e81Swyllys (void) BN_mod_inverse(COEF, Q, P, ctx); 87602744e81Swyllys 87702744e81Swyllys /* Convert back to KMF format */ 87802744e81Swyllys (void) memset(&rsa, 0, sizeof (rsa)); 87902744e81Swyllys 88002744e81Swyllys if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK) 88102744e81Swyllys goto out; 88202744e81Swyllys if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK) 88302744e81Swyllys goto out; 88402744e81Swyllys if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK) 88502744e81Swyllys goto out; 88602744e81Swyllys 88702744e81Swyllys rsa.mod.val = (uchar_t *)Mod->bv_val; 88802744e81Swyllys rsa.mod.len = Mod->bv_len; 88902744e81Swyllys 89002744e81Swyllys rsa.pubexp.val = (uchar_t *)PubExp->bv_val; 89102744e81Swyllys rsa.pubexp.len = PubExp->bv_len; 89202744e81Swyllys 89302744e81Swyllys rsa.priexp.val = (uchar_t *)PriExp->bv_val; 89402744e81Swyllys rsa.priexp.len = PriExp->bv_len; 89502744e81Swyllys 89602744e81Swyllys rsa.prime1.val = (uchar_t *)Prime1->bv_val; 89702744e81Swyllys rsa.prime1.len = Prime1->bv_len; 89802744e81Swyllys 89902744e81Swyllys rsa.prime2.val = (uchar_t *)Prime2->bv_val; 90002744e81Swyllys rsa.prime2.len = Prime2->bv_len; 90102744e81Swyllys 90202744e81Swyllys *pkey = ImportRawRSAKey(&rsa); 90302744e81Swyllys out: 90402744e81Swyllys if (asn1 != NULL) 90502744e81Swyllys kmfber_free(asn1, 1); 90602744e81Swyllys 90702744e81Swyllys if (OID.bv_val) { 90802744e81Swyllys free(OID.bv_val); 90902744e81Swyllys } 91002744e81Swyllys if (PriExp) 91102744e81Swyllys free(PriExp); 91202744e81Swyllys 91302744e81Swyllys if (Mod) 91402744e81Swyllys free(Mod); 91502744e81Swyllys 91602744e81Swyllys if (PubExp) 91702744e81Swyllys free(PubExp); 91802744e81Swyllys 91902744e81Swyllys if (Coef) { 92002744e81Swyllys (void) memset(Coef->bv_val, 0, Coef->bv_len); 92102744e81Swyllys free(Coef->bv_val); 92202744e81Swyllys free(Coef); 92302744e81Swyllys } 92402744e81Swyllys if (Prime1) 92502744e81Swyllys free(Prime1); 92602744e81Swyllys if (Prime2) 92702744e81Swyllys free(Prime2); 92802744e81Swyllys 92902744e81Swyllys if (ctx != NULL) 93002744e81Swyllys BN_CTX_free(ctx); 93102744e81Swyllys 93202744e81Swyllys if (D) 93302744e81Swyllys BN_clear_free(D); 93402744e81Swyllys if (P) 93502744e81Swyllys BN_clear_free(P); 93602744e81Swyllys if (Q) 93702744e81Swyllys BN_clear_free(Q); 93802744e81Swyllys if (pminus1) 93902744e81Swyllys BN_clear_free(pminus1); 94002744e81Swyllys if (qminus1) 94102744e81Swyllys BN_clear_free(qminus1); 94202744e81Swyllys if (Exp1) 94302744e81Swyllys BN_clear_free(Exp1); 94402744e81Swyllys if (Exp2) 94502744e81Swyllys BN_clear_free(Exp2); 94602744e81Swyllys 94702744e81Swyllys return (ret); 94802744e81Swyllys 94902744e81Swyllys } 95002744e81Swyllys 95199ebb4caSwyllys static EVP_PKEY * 95299ebb4caSwyllys openssl_load_key(KMF_HANDLE_T handle, const char *file) 95399ebb4caSwyllys { 95499ebb4caSwyllys BIO *keyfile = NULL; 95599ebb4caSwyllys EVP_PKEY *pkey = NULL; 95699ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 95799ebb4caSwyllys KMF_ENCODE_FORMAT format; 95802744e81Swyllys KMF_RETURN rv; 95902744e81Swyllys KMF_DATA filedata; 96099ebb4caSwyllys 96199ebb4caSwyllys if (file == NULL) { 96299ebb4caSwyllys return (NULL); 96399ebb4caSwyllys } 96499ebb4caSwyllys 96530a5e8faSwyllys if (kmf_get_file_format((char *)file, &format) != KMF_OK) 96699ebb4caSwyllys return (NULL); 96799ebb4caSwyllys 96899ebb4caSwyllys keyfile = BIO_new_file(file, "rb"); 96999ebb4caSwyllys if (keyfile == NULL) { 97099ebb4caSwyllys goto end; 97199ebb4caSwyllys } 97299ebb4caSwyllys 97302744e81Swyllys if (format == KMF_FORMAT_ASN1) { 97499ebb4caSwyllys pkey = d2i_PrivateKey_bio(keyfile, NULL); 97502744e81Swyllys if (pkey == NULL) { 97602744e81Swyllys 97702744e81Swyllys (void) BIO_free(keyfile); 97802744e81Swyllys keyfile = NULL; 97902744e81Swyllys /* Try odd ASN.1 variations */ 98030a5e8faSwyllys rv = kmf_read_input_file(kmfh, (char *)file, 98102744e81Swyllys &filedata); 98202744e81Swyllys if (rv == KMF_OK) { 98302744e81Swyllys (void) readAltFormatPrivateKey(&filedata, 98402744e81Swyllys &pkey); 98530a5e8faSwyllys kmf_free_data(&filedata); 98602744e81Swyllys } 98702744e81Swyllys } 98802744e81Swyllys } else if (format == KMF_FORMAT_PEM || 98902744e81Swyllys format == KMF_FORMAT_PEM_KEYPAIR) { 99099ebb4caSwyllys pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL); 99102744e81Swyllys if (pkey == NULL) { 99202744e81Swyllys KMF_DATA derdata; 99302744e81Swyllys /* 99402744e81Swyllys * Check if this is the alt. format 99502744e81Swyllys * RSA private key file. 99602744e81Swyllys */ 99730a5e8faSwyllys rv = kmf_read_input_file(kmfh, (char *)file, 99802744e81Swyllys &filedata); 99902744e81Swyllys if (rv == KMF_OK) { 100002744e81Swyllys uchar_t *d = NULL; 100102744e81Swyllys int len; 100230a5e8faSwyllys rv = kmf_pem_to_der(filedata.Data, 100302744e81Swyllys filedata.Length, &d, &len); 100402744e81Swyllys if (rv == KMF_OK && d != NULL) { 100502744e81Swyllys derdata.Data = d; 100602744e81Swyllys derdata.Length = (size_t)len; 100702744e81Swyllys (void) readAltFormatPrivateKey( 100802744e81Swyllys &derdata, &pkey); 100902744e81Swyllys free(d); 101002744e81Swyllys } 101130a5e8faSwyllys kmf_free_data(&filedata); 101202744e81Swyllys } 101302744e81Swyllys } 101402744e81Swyllys } 101599ebb4caSwyllys 101699ebb4caSwyllys end: 101799ebb4caSwyllys if (pkey == NULL) 101899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 101999ebb4caSwyllys 102099ebb4caSwyllys if (keyfile != NULL) 102199ebb4caSwyllys (void) BIO_free(keyfile); 102299ebb4caSwyllys 102399ebb4caSwyllys return (pkey); 102499ebb4caSwyllys } 102599ebb4caSwyllys 102699ebb4caSwyllys KMF_RETURN 102730a5e8faSwyllys OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 102899ebb4caSwyllys { 102999ebb4caSwyllys KMF_RETURN rv = KMF_OK; 103099ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 1031f482c776Swyllys int i, n; 1032f482c776Swyllys uint32_t maxcerts = 0; 103330a5e8faSwyllys uint32_t *num_certs; 103430a5e8faSwyllys KMF_X509_DER_CERT *kmf_cert = NULL; 103530a5e8faSwyllys char *dirpath = NULL; 103630a5e8faSwyllys char *filename = NULL; 103730a5e8faSwyllys char *fullpath = NULL; 103830a5e8faSwyllys char *issuer = NULL; 103930a5e8faSwyllys char *subject = NULL; 104030a5e8faSwyllys KMF_BIGINT *serial = NULL; 104130a5e8faSwyllys KMF_CERT_VALIDITY validity; 104299ebb4caSwyllys 104330a5e8faSwyllys num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr); 104430a5e8faSwyllys if (num_certs == NULL) 104599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 104699ebb4caSwyllys 104730a5e8faSwyllys /* num_certs should reference the size of kmf_cert */ 1048f482c776Swyllys maxcerts = *num_certs; 1049f482c776Swyllys if (maxcerts == 0) 1050f482c776Swyllys maxcerts = 0xFFFFFFFF; 105199ebb4caSwyllys *num_certs = 0; 105299ebb4caSwyllys 105330a5e8faSwyllys /* Get the optional returned certificate list */ 105430a5e8faSwyllys kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist, 105530a5e8faSwyllys numattr); 105699ebb4caSwyllys 105730a5e8faSwyllys /* 105830a5e8faSwyllys * The dirpath attribute and the filename attribute can not be NULL 105930a5e8faSwyllys * at the same time. 106030a5e8faSwyllys */ 106130a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 106230a5e8faSwyllys filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, 106330a5e8faSwyllys numattr); 106430a5e8faSwyllys 106530a5e8faSwyllys fullpath = get_fullpath(dirpath, filename); 106699ebb4caSwyllys if (fullpath == NULL) 106799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 106899ebb4caSwyllys 106930a5e8faSwyllys /* Get optional search criteria attributes */ 107030a5e8faSwyllys issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr); 107130a5e8faSwyllys subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr); 107230a5e8faSwyllys serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr); 107330a5e8faSwyllys rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr, 107430a5e8faSwyllys &validity, NULL); 107530a5e8faSwyllys if (rv != KMF_OK) { 107630a5e8faSwyllys validity = KMF_ALL_CERTS; 107730a5e8faSwyllys rv = KMF_OK; 107830a5e8faSwyllys } 107930a5e8faSwyllys 108099ebb4caSwyllys if (isdir(fullpath)) { 108199ebb4caSwyllys DIR *dirp; 108299ebb4caSwyllys struct dirent *dp; 108399ebb4caSwyllys 1084f482c776Swyllys n = 0; 108599ebb4caSwyllys /* open all files in the directory and attempt to read them */ 108699ebb4caSwyllys if ((dirp = opendir(fullpath)) == NULL) { 108799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 108899ebb4caSwyllys } 108999ebb4caSwyllys while ((dp = readdir(dirp)) != NULL) { 109099ebb4caSwyllys char *fname; 109171593db2Swyllys KMF_DATA *certlist = NULL; 1092f482c776Swyllys uint32_t loaded_certs = 0; 109371593db2Swyllys 109499ebb4caSwyllys if (strcmp(dp->d_name, ".") == 0 || 109599ebb4caSwyllys strcmp(dp->d_name, "..") == 0) 109699ebb4caSwyllys continue; 109799ebb4caSwyllys 109834acef67Swyllys fname = get_fullpath(fullpath, (char *)&dp->d_name); 109999ebb4caSwyllys 110030a5e8faSwyllys rv = load_certs(kmfh, issuer, subject, serial, 110130a5e8faSwyllys validity, fname, &certlist, &loaded_certs); 110299ebb4caSwyllys 110399ebb4caSwyllys if (rv != KMF_OK) { 110499ebb4caSwyllys free(fname); 110571593db2Swyllys if (certlist != NULL) { 1106f482c776Swyllys for (i = 0; i < loaded_certs; i++) 110730a5e8faSwyllys kmf_free_data(&certlist[i]); 110871593db2Swyllys free(certlist); 110971593db2Swyllys } 111099ebb4caSwyllys continue; 111199ebb4caSwyllys } 111299ebb4caSwyllys 111399ebb4caSwyllys /* If load succeeds, add certdata to the list */ 111499ebb4caSwyllys if (kmf_cert != NULL) { 1115f482c776Swyllys for (i = 0; i < loaded_certs && 1116b4058258Swyllys n < maxcerts; i++) { 111771593db2Swyllys kmf_cert[n].certificate.Data = 111871593db2Swyllys certlist[i].Data; 111999ebb4caSwyllys kmf_cert[n].certificate.Length = 112071593db2Swyllys certlist[i].Length; 112199ebb4caSwyllys 112299ebb4caSwyllys kmf_cert[n].kmf_private.keystore_type = 112399ebb4caSwyllys KMF_KEYSTORE_OPENSSL; 112499ebb4caSwyllys kmf_cert[n].kmf_private.flags = 112599ebb4caSwyllys KMF_FLAG_CERT_VALID; 112671593db2Swyllys kmf_cert[n].kmf_private.label = 112771593db2Swyllys strdup(fname); 112899ebb4caSwyllys n++; 112999ebb4caSwyllys } 1130b4058258Swyllys /* 1131b4058258Swyllys * If maxcerts < loaded_certs, clean up the 1132b4058258Swyllys * certs that were not used. 1133b4058258Swyllys */ 1134f482c776Swyllys for (; i < loaded_certs; i++) 113530a5e8faSwyllys kmf_free_data(&certlist[i]); 1136f482c776Swyllys } else { 1137f482c776Swyllys for (i = 0; i < loaded_certs; i++) 113830a5e8faSwyllys kmf_free_data(&certlist[i]); 1139f482c776Swyllys n += loaded_certs; 114071593db2Swyllys } 1141f482c776Swyllys free(certlist); 114271593db2Swyllys free(fname); 114371593db2Swyllys } 114499ebb4caSwyllys (*num_certs) = n; 114599ebb4caSwyllys if (*num_certs == 0) 114699ebb4caSwyllys rv = KMF_ERR_CERT_NOT_FOUND; 114730a5e8faSwyllys if (*num_certs > 0) 114899ebb4caSwyllys rv = KMF_OK; 114999ebb4caSwyllys exit: 115099ebb4caSwyllys (void) closedir(dirp); 115199ebb4caSwyllys } else { 115271593db2Swyllys KMF_DATA *certlist = NULL; 1153f482c776Swyllys uint32_t loaded_certs = 0; 115471593db2Swyllys 115530a5e8faSwyllys rv = load_certs(kmfh, issuer, subject, serial, validity, 115630a5e8faSwyllys fullpath, &certlist, &loaded_certs); 115799ebb4caSwyllys if (rv != KMF_OK) { 115899ebb4caSwyllys free(fullpath); 115999ebb4caSwyllys return (rv); 116099ebb4caSwyllys } 116199ebb4caSwyllys 1162f482c776Swyllys n = 0; 116371593db2Swyllys if (kmf_cert != NULL && certlist != NULL) { 1164f482c776Swyllys for (i = 0; i < loaded_certs && i < maxcerts; i++) { 1165f482c776Swyllys kmf_cert[n].certificate.Data = 116671593db2Swyllys certlist[i].Data; 1167f482c776Swyllys kmf_cert[n].certificate.Length = 116871593db2Swyllys certlist[i].Length; 1169f482c776Swyllys kmf_cert[n].kmf_private.keystore_type = 117099ebb4caSwyllys KMF_KEYSTORE_OPENSSL; 1171f482c776Swyllys kmf_cert[n].kmf_private.flags = 117271593db2Swyllys KMF_FLAG_CERT_VALID; 1173f482c776Swyllys kmf_cert[n].kmf_private.label = 117471593db2Swyllys strdup(fullpath); 1175f482c776Swyllys n++; 117671593db2Swyllys } 1177f482c776Swyllys /* If maxcerts < loaded_certs, clean up */ 1178f482c776Swyllys for (; i < loaded_certs; i++) 117930a5e8faSwyllys kmf_free_data(&certlist[i]); 1180f482c776Swyllys } else if (certlist != NULL) { 1181f482c776Swyllys for (i = 0; i < loaded_certs; i++) 118230a5e8faSwyllys kmf_free_data(&certlist[i]); 1183f482c776Swyllys n = loaded_certs; 1184f482c776Swyllys } 118530a5e8faSwyllys if (certlist != NULL) 118671593db2Swyllys free(certlist); 1187f482c776Swyllys *num_certs = n; 118899ebb4caSwyllys } 118999ebb4caSwyllys 119099ebb4caSwyllys free(fullpath); 119199ebb4caSwyllys 119299ebb4caSwyllys return (rv); 119399ebb4caSwyllys } 119499ebb4caSwyllys 119599ebb4caSwyllys void 119699ebb4caSwyllys /*ARGSUSED*/ 119799ebb4caSwyllys OpenSSL_FreeKMFCert(KMF_HANDLE_T handle, 119899ebb4caSwyllys KMF_X509_DER_CERT *kmf_cert) 119999ebb4caSwyllys { 120099ebb4caSwyllys if (kmf_cert != NULL) { 120199ebb4caSwyllys if (kmf_cert->certificate.Data != NULL) { 1202e65e5c2dSWyllys Ingersoll kmf_free_data(&kmf_cert->certificate); 120399ebb4caSwyllys } 120499ebb4caSwyllys if (kmf_cert->kmf_private.label) 120599ebb4caSwyllys free(kmf_cert->kmf_private.label); 120699ebb4caSwyllys } 120799ebb4caSwyllys } 120899ebb4caSwyllys 120930a5e8faSwyllys /*ARGSUSED*/ 121099ebb4caSwyllys KMF_RETURN 121130a5e8faSwyllys OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 121299ebb4caSwyllys { 121399ebb4caSwyllys KMF_RETURN ret = KMF_OK; 121430a5e8faSwyllys KMF_DATA *cert = NULL; 121530a5e8faSwyllys char *outfilename = NULL; 121630a5e8faSwyllys char *dirpath = NULL; 121730a5e8faSwyllys char *fullpath = NULL; 121899ebb4caSwyllys KMF_ENCODE_FORMAT format; 121999ebb4caSwyllys 122030a5e8faSwyllys /* Get the cert data */ 122130a5e8faSwyllys cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr); 122230a5e8faSwyllys if (cert == NULL || cert->Data == NULL) 122399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 122499ebb4caSwyllys 122530a5e8faSwyllys /* Check the output filename and directory attributes. */ 122630a5e8faSwyllys outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, 122730a5e8faSwyllys numattr); 122830a5e8faSwyllys if (outfilename == NULL) 122930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 123099ebb4caSwyllys 123130a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 123230a5e8faSwyllys fullpath = get_fullpath(dirpath, outfilename); 123399ebb4caSwyllys if (fullpath == NULL) 123430a5e8faSwyllys return (KMF_ERR_BAD_CERTFILE); 123599ebb4caSwyllys 123630a5e8faSwyllys /* Check the optional format attribute */ 123730a5e8faSwyllys ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 123830a5e8faSwyllys &format, NULL); 123930a5e8faSwyllys if (ret != KMF_OK) { 124030a5e8faSwyllys /* If there is no format attribute, then default to PEM */ 124130a5e8faSwyllys format = KMF_FORMAT_PEM; 124299ebb4caSwyllys ret = KMF_OK; 124330a5e8faSwyllys } else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) { 124430a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 124599ebb4caSwyllys goto out; 124699ebb4caSwyllys } 124799ebb4caSwyllys 124830a5e8faSwyllys /* Store the certificate in the file with the specified format */ 124930a5e8faSwyllys ret = kmf_create_cert_file(cert, format, fullpath); 125099ebb4caSwyllys 125199ebb4caSwyllys out: 125299ebb4caSwyllys if (fullpath != NULL) 125399ebb4caSwyllys free(fullpath); 125499ebb4caSwyllys 125599ebb4caSwyllys return (ret); 125699ebb4caSwyllys } 125799ebb4caSwyllys 125830a5e8faSwyllys 125999ebb4caSwyllys KMF_RETURN 126030a5e8faSwyllys OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 126199ebb4caSwyllys { 126299ebb4caSwyllys KMF_RETURN rv; 126399ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 126499ebb4caSwyllys KMF_DATA certdata = {NULL, 0}; 126530a5e8faSwyllys char *dirpath = NULL; 126630a5e8faSwyllys char *filename = NULL; 126730a5e8faSwyllys char *fullpath = NULL; 126830a5e8faSwyllys char *issuer = NULL; 126930a5e8faSwyllys char *subject = NULL; 127030a5e8faSwyllys KMF_BIGINT *serial = NULL; 127130a5e8faSwyllys KMF_CERT_VALIDITY validity; 127299ebb4caSwyllys 127330a5e8faSwyllys /* 127430a5e8faSwyllys * Get the DIRPATH and CERT_FILENAME attributes. They can not be 127530a5e8faSwyllys * NULL at the same time. 127630a5e8faSwyllys */ 127730a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 127830a5e8faSwyllys filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, 127930a5e8faSwyllys numattr); 128030a5e8faSwyllys fullpath = get_fullpath(dirpath, filename); 128199ebb4caSwyllys if (fullpath == NULL) 128299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 128399ebb4caSwyllys 128430a5e8faSwyllys /* Get optional search criteria attributes */ 128530a5e8faSwyllys issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr); 128630a5e8faSwyllys subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr); 128730a5e8faSwyllys serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr); 128830a5e8faSwyllys rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr, 128930a5e8faSwyllys &validity, NULL); 129030a5e8faSwyllys if (rv != KMF_OK) { 129130a5e8faSwyllys validity = KMF_ALL_CERTS; 129230a5e8faSwyllys rv = KMF_OK; 129330a5e8faSwyllys } 129430a5e8faSwyllys 129599ebb4caSwyllys if (isdir(fullpath)) { 129699ebb4caSwyllys DIR *dirp; 129799ebb4caSwyllys struct dirent *dp; 129899ebb4caSwyllys 129999ebb4caSwyllys /* open all files in the directory and attempt to read them */ 130099ebb4caSwyllys if ((dirp = opendir(fullpath)) == NULL) { 130199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 130299ebb4caSwyllys } 130399ebb4caSwyllys 130499ebb4caSwyllys while ((dp = readdir(dirp)) != NULL) { 130599ebb4caSwyllys if (strcmp(dp->d_name, ".") != 0 && 130699ebb4caSwyllys strcmp(dp->d_name, "..") != 0) { 130799ebb4caSwyllys char *fname; 130899ebb4caSwyllys 130999ebb4caSwyllys fname = get_fullpath(fullpath, 131099ebb4caSwyllys (char *)&dp->d_name); 131199ebb4caSwyllys 131299ebb4caSwyllys if (fname == NULL) { 131399ebb4caSwyllys rv = KMF_ERR_MEMORY; 131499ebb4caSwyllys break; 131599ebb4caSwyllys } 131699ebb4caSwyllys 131730a5e8faSwyllys rv = kmf_load_cert(kmfh, issuer, subject, 131830a5e8faSwyllys serial, validity, fname, &certdata); 131999ebb4caSwyllys 132099ebb4caSwyllys if (rv == KMF_ERR_CERT_NOT_FOUND) { 132199ebb4caSwyllys free(fname); 1322e65e5c2dSWyllys Ingersoll kmf_free_data(&certdata); 132399ebb4caSwyllys rv = KMF_OK; 132499ebb4caSwyllys continue; 132599ebb4caSwyllys } else if (rv != KMF_OK) { 132699ebb4caSwyllys free(fname); 132799ebb4caSwyllys break; 132899ebb4caSwyllys } 132999ebb4caSwyllys 133099ebb4caSwyllys if (unlink(fname) != 0) { 133199ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 133299ebb4caSwyllys rv = KMF_ERR_INTERNAL; 133399ebb4caSwyllys free(fname); 133499ebb4caSwyllys break; 133599ebb4caSwyllys } 133699ebb4caSwyllys free(fname); 1337e65e5c2dSWyllys Ingersoll kmf_free_data(&certdata); 133899ebb4caSwyllys } 133999ebb4caSwyllys } 134099ebb4caSwyllys (void) closedir(dirp); 134199ebb4caSwyllys } else { 134299ebb4caSwyllys /* Just try to load a single certificate */ 134330a5e8faSwyllys rv = kmf_load_cert(kmfh, issuer, subject, serial, validity, 134430a5e8faSwyllys fullpath, &certdata); 134599ebb4caSwyllys if (rv == KMF_OK) { 134699ebb4caSwyllys if (unlink(fullpath) != 0) { 134799ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 134899ebb4caSwyllys rv = KMF_ERR_INTERNAL; 134999ebb4caSwyllys } 135099ebb4caSwyllys } 135199ebb4caSwyllys } 135299ebb4caSwyllys 135399ebb4caSwyllys out: 135499ebb4caSwyllys if (fullpath != NULL) 135599ebb4caSwyllys free(fullpath); 135699ebb4caSwyllys 1357e65e5c2dSWyllys Ingersoll kmf_free_data(&certdata); 135899ebb4caSwyllys 135999ebb4caSwyllys return (rv); 136099ebb4caSwyllys } 136199ebb4caSwyllys 136299ebb4caSwyllys KMF_RETURN 136399ebb4caSwyllys OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, 136499ebb4caSwyllys KMF_DATA *keydata) 136599ebb4caSwyllys { 136699ebb4caSwyllys KMF_RETURN rv = KMF_OK; 136799ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 136899ebb4caSwyllys int n; 136999ebb4caSwyllys 137099ebb4caSwyllys if (key == NULL || keydata == NULL || 137199ebb4caSwyllys key->keyp == NULL) 137299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 137399ebb4caSwyllys 137499ebb4caSwyllys if (key->keyalg == KMF_RSA) { 137599ebb4caSwyllys RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp); 137699ebb4caSwyllys 137799ebb4caSwyllys if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) { 137899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 137999ebb4caSwyllys return (KMF_ERR_ENCODING); 138099ebb4caSwyllys } 138199ebb4caSwyllys RSA_free(pubkey); 138299ebb4caSwyllys } else if (key->keyalg == KMF_DSA) { 138399ebb4caSwyllys DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp); 138499ebb4caSwyllys 138599ebb4caSwyllys if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) { 138699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 138799ebb4caSwyllys return (KMF_ERR_ENCODING); 138899ebb4caSwyllys } 138999ebb4caSwyllys DSA_free(pubkey); 139099ebb4caSwyllys } else { 139199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 139299ebb4caSwyllys } 139399ebb4caSwyllys keydata->Length = n; 139499ebb4caSwyllys 139599ebb4caSwyllys cleanup: 139699ebb4caSwyllys if (rv != KMF_OK) { 139799ebb4caSwyllys if (keydata->Data) 139899ebb4caSwyllys free(keydata->Data); 139999ebb4caSwyllys keydata->Data = NULL; 140099ebb4caSwyllys keydata->Length = 0; 140199ebb4caSwyllys } 140299ebb4caSwyllys 140399ebb4caSwyllys return (rv); 140499ebb4caSwyllys } 140599ebb4caSwyllys 140699ebb4caSwyllys static KMF_RETURN 140730a5e8faSwyllys ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out, 140830a5e8faSwyllys KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private) 140999ebb4caSwyllys { 141099ebb4caSwyllys int rv = 0; 141199ebb4caSwyllys RSA *rsa; 141299ebb4caSwyllys DSA *dsa; 141399ebb4caSwyllys 14145b3e1433Swyllys if (pkey == NULL || out == NULL) 14155b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 14165b3e1433Swyllys 141799ebb4caSwyllys switch (format) { 141873cc0e02Swyllys case KMF_FORMAT_RAWKEY: 141973cc0e02Swyllys /* same as ASN.1 */ 142099ebb4caSwyllys case KMF_FORMAT_ASN1: 142199ebb4caSwyllys if (pkey->type == EVP_PKEY_RSA) { 142299ebb4caSwyllys rsa = EVP_PKEY_get1_RSA(pkey); 142330a5e8faSwyllys if (private) 142499ebb4caSwyllys rv = i2d_RSAPrivateKey_bio(out, rsa); 142530a5e8faSwyllys else 142630a5e8faSwyllys rv = i2d_RSAPublicKey_bio(out, rsa); 142799ebb4caSwyllys RSA_free(rsa); 142899ebb4caSwyllys } else if (pkey->type == EVP_PKEY_DSA) { 142999ebb4caSwyllys dsa = EVP_PKEY_get1_DSA(pkey); 143099ebb4caSwyllys rv = i2d_DSAPrivateKey_bio(out, dsa); 143199ebb4caSwyllys DSA_free(dsa); 143299ebb4caSwyllys } 143399ebb4caSwyllys if (rv == 1) { 143499ebb4caSwyllys rv = KMF_OK; 143599ebb4caSwyllys } else { 143699ebb4caSwyllys SET_ERROR(kmfh, rv); 143799ebb4caSwyllys } 143899ebb4caSwyllys break; 143999ebb4caSwyllys case KMF_FORMAT_PEM: 144099ebb4caSwyllys if (pkey->type == EVP_PKEY_RSA) { 144199ebb4caSwyllys rsa = EVP_PKEY_get1_RSA(pkey); 144230a5e8faSwyllys if (private) 144399ebb4caSwyllys rv = PEM_write_bio_RSAPrivateKey(out, 144430a5e8faSwyllys rsa, NULL, NULL, 0, NULL, 144530a5e8faSwyllys (cred != NULL ? cred->cred : NULL)); 144630a5e8faSwyllys else 144730a5e8faSwyllys rv = PEM_write_bio_RSAPublicKey(out, 144830a5e8faSwyllys rsa); 144999ebb4caSwyllys RSA_free(rsa); 145099ebb4caSwyllys } else if (pkey->type == EVP_PKEY_DSA) { 145199ebb4caSwyllys dsa = EVP_PKEY_get1_DSA(pkey); 145299ebb4caSwyllys rv = PEM_write_bio_DSAPrivateKey(out, 145330a5e8faSwyllys dsa, NULL, NULL, 0, NULL, 145430a5e8faSwyllys (cred != NULL ? cred->cred : NULL)); 145599ebb4caSwyllys DSA_free(dsa); 145699ebb4caSwyllys } 145799ebb4caSwyllys 145899ebb4caSwyllys if (rv == 1) { 145999ebb4caSwyllys rv = KMF_OK; 146099ebb4caSwyllys } else { 146199ebb4caSwyllys SET_ERROR(kmfh, rv); 146299ebb4caSwyllys } 146399ebb4caSwyllys break; 146499ebb4caSwyllys 146599ebb4caSwyllys default: 146699ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 146799ebb4caSwyllys } 146899ebb4caSwyllys 146999ebb4caSwyllys return (rv); 147099ebb4caSwyllys } 147199ebb4caSwyllys 147299ebb4caSwyllys KMF_RETURN 147330a5e8faSwyllys OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr, 147430a5e8faSwyllys KMF_ATTRIBUTE *attrlist) 147599ebb4caSwyllys { 147699ebb4caSwyllys KMF_RETURN rv = KMF_OK; 147799ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 147899ebb4caSwyllys uint32_t eValue = 0x010001; 147999ebb4caSwyllys RSA *sslPrivKey = NULL; 148099ebb4caSwyllys DSA *sslDSAKey = NULL; 148199ebb4caSwyllys EVP_PKEY *eprikey = NULL; 148299ebb4caSwyllys EVP_PKEY *epubkey = NULL; 148399ebb4caSwyllys BIO *out = NULL; 148430a5e8faSwyllys KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL; 148530a5e8faSwyllys uint32_t keylen = 1024; 148630a5e8faSwyllys uint32_t keylen_size = sizeof (uint32_t); 148730a5e8faSwyllys boolean_t storekey = TRUE; 148830a5e8faSwyllys KMF_KEY_ALG keytype = KMF_RSA; 148999ebb4caSwyllys 149030a5e8faSwyllys rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr, 149130a5e8faSwyllys &storekey, NULL); 149230a5e8faSwyllys if (rv != KMF_OK) { 149330a5e8faSwyllys /* "storekey" is optional. Default is TRUE */ 149430a5e8faSwyllys rv = KMF_OK; 149599ebb4caSwyllys } 149699ebb4caSwyllys 149730a5e8faSwyllys rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, 149830a5e8faSwyllys (void *)&keytype, NULL); 149930a5e8faSwyllys if (rv != KMF_OK) 150030a5e8faSwyllys /* keytype is optional. KMF_RSA is default */ 150130a5e8faSwyllys rv = KMF_OK; 150299ebb4caSwyllys 150330a5e8faSwyllys pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr); 150430a5e8faSwyllys if (pubkey == NULL) 150599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 150699ebb4caSwyllys 150730a5e8faSwyllys privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr); 150830a5e8faSwyllys if (privkey == NULL) 150930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 151030a5e8faSwyllys 151130a5e8faSwyllys (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE)); 151230a5e8faSwyllys (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE)); 151399ebb4caSwyllys 151499ebb4caSwyllys eprikey = EVP_PKEY_new(); 151599ebb4caSwyllys if (eprikey == NULL) { 151699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 151799ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 151899ebb4caSwyllys goto cleanup; 151999ebb4caSwyllys } 152099ebb4caSwyllys epubkey = EVP_PKEY_new(); 152199ebb4caSwyllys if (epubkey == NULL) { 152299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 152399ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 152499ebb4caSwyllys goto cleanup; 152599ebb4caSwyllys } 152630a5e8faSwyllys if (keytype == KMF_RSA) { 152730a5e8faSwyllys KMF_BIGINT *rsaexp = NULL; 152899ebb4caSwyllys 152930a5e8faSwyllys rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr); 153030a5e8faSwyllys if (rsaexp != NULL) { 153130a5e8faSwyllys if (rsaexp->len > 0 && 153230a5e8faSwyllys rsaexp->len <= sizeof (eValue) && 153330a5e8faSwyllys rsaexp->val != NULL) { 1534a2d4930dSDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */ 153530a5e8faSwyllys eValue = *(uint32_t *)rsaexp->val; 153630a5e8faSwyllys } else { 153730a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 153830a5e8faSwyllys goto cleanup; 153930a5e8faSwyllys } 154030a5e8faSwyllys } else { 154130a5e8faSwyllys /* RSA Exponent is optional. Default is 0x10001 */ 154230a5e8faSwyllys rv = KMF_OK; 154330a5e8faSwyllys } 154430a5e8faSwyllys 154530a5e8faSwyllys rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, 154630a5e8faSwyllys &keylen, &keylen_size); 154730a5e8faSwyllys if (rv == KMF_ERR_ATTR_NOT_FOUND) 154830a5e8faSwyllys /* keylen is optional, default is 1024 */ 154930a5e8faSwyllys rv = KMF_OK; 155030a5e8faSwyllys if (rv != KMF_OK) { 155130a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 155230a5e8faSwyllys goto cleanup; 155330a5e8faSwyllys } 155430a5e8faSwyllys 155530a5e8faSwyllys sslPrivKey = RSA_generate_key(keylen, eValue, NULL, NULL); 155699ebb4caSwyllys if (sslPrivKey == NULL) { 155799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 155899ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 155999ebb4caSwyllys } else { 156030a5e8faSwyllys (void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey); 156199ebb4caSwyllys privkey->kstype = KMF_KEYSTORE_OPENSSL; 156299ebb4caSwyllys privkey->keyalg = KMF_RSA; 156399ebb4caSwyllys privkey->keyclass = KMF_ASYM_PRI; 156499ebb4caSwyllys privkey->israw = FALSE; 156599ebb4caSwyllys privkey->keyp = (void *)eprikey; 156630a5e8faSwyllys 156799ebb4caSwyllys /* OpenSSL derives the public key from the private */ 156830a5e8faSwyllys (void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey); 156999ebb4caSwyllys pubkey->kstype = KMF_KEYSTORE_OPENSSL; 157099ebb4caSwyllys pubkey->keyalg = KMF_RSA; 157199ebb4caSwyllys pubkey->israw = FALSE; 157299ebb4caSwyllys pubkey->keyclass = KMF_ASYM_PUB; 157399ebb4caSwyllys pubkey->keyp = (void *)epubkey; 157499ebb4caSwyllys } 157530a5e8faSwyllys } else if (keytype == KMF_DSA) { 157630a5e8faSwyllys DSA *dp; 157799ebb4caSwyllys sslDSAKey = DSA_new(); 157899ebb4caSwyllys if (sslDSAKey == NULL) { 157999ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 158099ebb4caSwyllys return (KMF_ERR_MEMORY); 158199ebb4caSwyllys } 158299ebb4caSwyllys 158399ebb4caSwyllys if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) == 158499ebb4caSwyllys NULL) { 158599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 158699ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 158799ebb4caSwyllys goto cleanup; 158899ebb4caSwyllys } 158999ebb4caSwyllys if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) == 159099ebb4caSwyllys NULL) { 159199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 159299ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 159399ebb4caSwyllys goto cleanup; 159499ebb4caSwyllys } 159599ebb4caSwyllys if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) == 159699ebb4caSwyllys NULL) { 159799ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 159899ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 159999ebb4caSwyllys goto cleanup; 160099ebb4caSwyllys } 160199ebb4caSwyllys 160299ebb4caSwyllys if (!DSA_generate_key(sslDSAKey)) { 160399ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 160499ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 160599ebb4caSwyllys goto cleanup; 160699ebb4caSwyllys } 160799ebb4caSwyllys 160899ebb4caSwyllys privkey->kstype = KMF_KEYSTORE_OPENSSL; 160999ebb4caSwyllys privkey->keyalg = KMF_DSA; 161099ebb4caSwyllys privkey->keyclass = KMF_ASYM_PRI; 161199ebb4caSwyllys privkey->israw = FALSE; 161299ebb4caSwyllys if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) { 161399ebb4caSwyllys privkey->keyp = (void *)eprikey; 161499ebb4caSwyllys } else { 161599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 161699ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 161799ebb4caSwyllys goto cleanup; 161899ebb4caSwyllys } 161930a5e8faSwyllys dp = DSA_new(); 162099ebb4caSwyllys /* Make a copy for the public key */ 162199ebb4caSwyllys if (dp != NULL) { 162299ebb4caSwyllys if ((dp->p = BN_new()) == NULL) { 162399ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 162499ebb4caSwyllys rv = KMF_ERR_MEMORY; 162599ebb4caSwyllys DSA_free(dp); 162699ebb4caSwyllys goto cleanup; 162799ebb4caSwyllys } 162899ebb4caSwyllys if ((dp->q = BN_new()) == NULL) { 162999ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 163099ebb4caSwyllys rv = KMF_ERR_MEMORY; 163199ebb4caSwyllys BN_free(dp->p); 163299ebb4caSwyllys DSA_free(dp); 163399ebb4caSwyllys goto cleanup; 163499ebb4caSwyllys } 163599ebb4caSwyllys if ((dp->g = BN_new()) == NULL) { 163699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 163799ebb4caSwyllys rv = KMF_ERR_MEMORY; 163899ebb4caSwyllys BN_free(dp->q); 163999ebb4caSwyllys BN_free(dp->p); 164099ebb4caSwyllys DSA_free(dp); 164199ebb4caSwyllys goto cleanup; 164299ebb4caSwyllys } 164399ebb4caSwyllys if ((dp->pub_key = BN_new()) == NULL) { 164499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 164599ebb4caSwyllys rv = KMF_ERR_MEMORY; 164699ebb4caSwyllys BN_free(dp->q); 164799ebb4caSwyllys BN_free(dp->p); 164899ebb4caSwyllys BN_free(dp->g); 164999ebb4caSwyllys DSA_free(dp); 165099ebb4caSwyllys goto cleanup; 165199ebb4caSwyllys } 165299ebb4caSwyllys (void) BN_copy(dp->p, sslDSAKey->p); 165399ebb4caSwyllys (void) BN_copy(dp->q, sslDSAKey->q); 165499ebb4caSwyllys (void) BN_copy(dp->g, sslDSAKey->g); 165599ebb4caSwyllys (void) BN_copy(dp->pub_key, sslDSAKey->pub_key); 165699ebb4caSwyllys 165799ebb4caSwyllys pubkey->kstype = KMF_KEYSTORE_OPENSSL; 165899ebb4caSwyllys pubkey->keyalg = KMF_DSA; 165999ebb4caSwyllys pubkey->keyclass = KMF_ASYM_PUB; 166099ebb4caSwyllys pubkey->israw = FALSE; 166199ebb4caSwyllys 166299ebb4caSwyllys if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) { 166399ebb4caSwyllys pubkey->keyp = (void *)epubkey; 166499ebb4caSwyllys } else { 166599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 166699ebb4caSwyllys rv = KMF_ERR_KEYGEN_FAILED; 166799ebb4caSwyllys goto cleanup; 166899ebb4caSwyllys } 166999ebb4caSwyllys } 167099ebb4caSwyllys } 167199ebb4caSwyllys 167299ebb4caSwyllys if (rv != KMF_OK) { 167399ebb4caSwyllys goto cleanup; 167499ebb4caSwyllys } 167599ebb4caSwyllys 167630a5e8faSwyllys if (storekey) { 167730a5e8faSwyllys KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */ 167830a5e8faSwyllys int i = 0; 167930a5e8faSwyllys char *keyfile = NULL, *dirpath = NULL; 168030a5e8faSwyllys KMF_ENCODE_FORMAT format; 168130a5e8faSwyllys /* 168230a5e8faSwyllys * Construct a new attribute arrray and call openssl_store_key 168330a5e8faSwyllys */ 168430a5e8faSwyllys kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR, 168530a5e8faSwyllys privkey, sizeof (privkey)); 168630a5e8faSwyllys i++; 168730a5e8faSwyllys 168830a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 168930a5e8faSwyllys if (dirpath != NULL) { 169030a5e8faSwyllys storeattrs[i].type = KMF_DIRPATH_ATTR; 169130a5e8faSwyllys storeattrs[i].pValue = dirpath; 169230a5e8faSwyllys storeattrs[i].valueLen = strlen(dirpath); 169330a5e8faSwyllys i++; 169430a5e8faSwyllys } else { 169530a5e8faSwyllys rv = KMF_OK; /* DIRPATH is optional */ 169699ebb4caSwyllys } 169730a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, 169830a5e8faSwyllys attrlist, numattr); 169930a5e8faSwyllys if (keyfile != NULL) { 170030a5e8faSwyllys storeattrs[i].type = KMF_KEY_FILENAME_ATTR; 170130a5e8faSwyllys storeattrs[i].pValue = keyfile; 170230a5e8faSwyllys storeattrs[i].valueLen = strlen(keyfile); 170330a5e8faSwyllys i++; 170430a5e8faSwyllys } else { 170530a5e8faSwyllys goto cleanup; /* KEYFILE is required */ 170630a5e8faSwyllys } 170730a5e8faSwyllys rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 170830a5e8faSwyllys (void *)&format, NULL); 170930a5e8faSwyllys if (rv == KMF_OK) { 171030a5e8faSwyllys storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR; 171130a5e8faSwyllys storeattrs[i].pValue = &format; 171230a5e8faSwyllys storeattrs[i].valueLen = sizeof (format); 171330a5e8faSwyllys i++; 171430a5e8faSwyllys } 171530a5e8faSwyllys 171630a5e8faSwyllys rv = OpenSSL_StoreKey(handle, i, storeattrs); 171730a5e8faSwyllys } 171899ebb4caSwyllys 171999ebb4caSwyllys cleanup: 172099ebb4caSwyllys if (rv != KMF_OK) { 172199ebb4caSwyllys if (eprikey != NULL) 172299ebb4caSwyllys EVP_PKEY_free(eprikey); 172399ebb4caSwyllys 172499ebb4caSwyllys if (epubkey != NULL) 172599ebb4caSwyllys EVP_PKEY_free(epubkey); 172699ebb4caSwyllys 172799ebb4caSwyllys if (pubkey->keylabel) { 172899ebb4caSwyllys free(pubkey->keylabel); 172999ebb4caSwyllys pubkey->keylabel = NULL; 173099ebb4caSwyllys } 173199ebb4caSwyllys 173299ebb4caSwyllys if (privkey->keylabel) { 173399ebb4caSwyllys free(privkey->keylabel); 173499ebb4caSwyllys privkey->keylabel = NULL; 173599ebb4caSwyllys } 173699ebb4caSwyllys 173799ebb4caSwyllys pubkey->keyp = NULL; 173899ebb4caSwyllys privkey->keyp = NULL; 173999ebb4caSwyllys } 174099ebb4caSwyllys 174199ebb4caSwyllys if (sslPrivKey) 174299ebb4caSwyllys RSA_free(sslPrivKey); 174399ebb4caSwyllys 174499ebb4caSwyllys if (sslDSAKey) 174599ebb4caSwyllys DSA_free(sslDSAKey); 174699ebb4caSwyllys 174799ebb4caSwyllys if (out != NULL) 174899ebb4caSwyllys (void) BIO_free(out); 174999ebb4caSwyllys 175099ebb4caSwyllys return (rv); 175199ebb4caSwyllys } 175299ebb4caSwyllys 1753e65e5c2dSWyllys Ingersoll /* 1754e65e5c2dSWyllys Ingersoll * Make sure the BN conversion is properly padded with 0x00 1755e65e5c2dSWyllys Ingersoll * bytes. If not, signature verification for DSA signatures 1756e65e5c2dSWyllys Ingersoll * may fail in the case where the bignum value does not use 1757e65e5c2dSWyllys Ingersoll * all of the bits. 1758e65e5c2dSWyllys Ingersoll */ 1759e65e5c2dSWyllys Ingersoll static int 1760e65e5c2dSWyllys Ingersoll fixbnlen(BIGNUM *bn, unsigned char *buf, int len) { 1761e65e5c2dSWyllys Ingersoll int bytes = len - BN_num_bytes(bn); 1762*2c9a247fSWyllys Ingersoll 1763*2c9a247fSWyllys Ingersoll /* prepend with leading 0x00 if necessary */ 1764e65e5c2dSWyllys Ingersoll while (bytes-- > 0) 1765e65e5c2dSWyllys Ingersoll *buf++ = 0; 1766e65e5c2dSWyllys Ingersoll 1767*2c9a247fSWyllys Ingersoll (void) BN_bn2bin(bn, buf); 1768*2c9a247fSWyllys Ingersoll /* 1769*2c9a247fSWyllys Ingersoll * Return the desired length since we prepended it 1770*2c9a247fSWyllys Ingersoll * with the necessary 0x00 padding. 1771*2c9a247fSWyllys Ingersoll */ 1772*2c9a247fSWyllys Ingersoll return (len); 1773e65e5c2dSWyllys Ingersoll } 1774e65e5c2dSWyllys Ingersoll 177599ebb4caSwyllys KMF_RETURN 177699ebb4caSwyllys OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, 177799ebb4caSwyllys KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output) 177899ebb4caSwyllys { 177999ebb4caSwyllys KMF_RETURN ret = KMF_OK; 178099ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 178199ebb4caSwyllys KMF_ALGORITHM_INDEX AlgId; 178299ebb4caSwyllys EVP_MD_CTX ctx; 178399ebb4caSwyllys const EVP_MD *md; 178402744e81Swyllys 178599ebb4caSwyllys if (key == NULL || AlgOID == NULL || 178699ebb4caSwyllys tobesigned == NULL || output == NULL || 178799ebb4caSwyllys tobesigned->Data == NULL || 178899ebb4caSwyllys output->Data == NULL) 178999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 179099ebb4caSwyllys 179199ebb4caSwyllys /* Map the OID to an OpenSSL algorithm */ 179230a5e8faSwyllys AlgId = x509_algoid_to_algid(AlgOID); 179399ebb4caSwyllys if (AlgId == KMF_ALGID_NONE) 1794e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM); 179599ebb4caSwyllys 179699ebb4caSwyllys if (key->keyalg == KMF_RSA) { 179799ebb4caSwyllys EVP_PKEY *pkey = (EVP_PKEY *)key->keyp; 179899ebb4caSwyllys uchar_t *p; 179902744e81Swyllys int len; 180099ebb4caSwyllys if (AlgId == KMF_ALGID_MD5WithRSA) 180199ebb4caSwyllys md = EVP_md5(); 180299ebb4caSwyllys else if (AlgId == KMF_ALGID_MD2WithRSA) 180399ebb4caSwyllys md = EVP_md2(); 180499ebb4caSwyllys else if (AlgId == KMF_ALGID_SHA1WithRSA) 180599ebb4caSwyllys md = EVP_sha1(); 1806e65e5c2dSWyllys Ingersoll else if (AlgId == KMF_ALGID_SHA256WithRSA) 1807e65e5c2dSWyllys Ingersoll md = EVP_sha256(); 1808e65e5c2dSWyllys Ingersoll else if (AlgId == KMF_ALGID_SHA384WithRSA) 1809e65e5c2dSWyllys Ingersoll md = EVP_sha384(); 1810e65e5c2dSWyllys Ingersoll else if (AlgId == KMF_ALGID_SHA512WithRSA) 1811e65e5c2dSWyllys Ingersoll md = EVP_sha512(); 181202744e81Swyllys else if (AlgId == KMF_ALGID_RSA) 181302744e81Swyllys md = NULL; 181499ebb4caSwyllys else 1815e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM); 181699ebb4caSwyllys 181702744e81Swyllys if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) { 181802744e81Swyllys RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey); 181999ebb4caSwyllys 182002744e81Swyllys p = output->Data; 182102744e81Swyllys if ((len = RSA_private_encrypt(tobesigned->Length, 182202744e81Swyllys tobesigned->Data, p, rsa, 182302744e81Swyllys RSA_PKCS1_PADDING)) <= 0) { 182402744e81Swyllys SET_ERROR(kmfh, ERR_get_error()); 182502744e81Swyllys ret = KMF_ERR_INTERNAL; 182602744e81Swyllys } 182702744e81Swyllys output->Length = len; 182802744e81Swyllys } else { 182999ebb4caSwyllys (void) EVP_MD_CTX_init(&ctx); 183099ebb4caSwyllys (void) EVP_SignInit_ex(&ctx, md, NULL); 183199ebb4caSwyllys (void) EVP_SignUpdate(&ctx, tobesigned->Data, 183299ebb4caSwyllys (uint32_t)tobesigned->Length); 183399ebb4caSwyllys len = (uint32_t)output->Length; 183499ebb4caSwyllys p = output->Data; 183502744e81Swyllys if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) { 183699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 183702744e81Swyllys len = 0; 183802744e81Swyllys ret = KMF_ERR_INTERNAL; 183999ebb4caSwyllys } 184099ebb4caSwyllys output->Length = len; 184199ebb4caSwyllys (void) EVP_MD_CTX_cleanup(&ctx); 184202744e81Swyllys } 184399ebb4caSwyllys } else if (key->keyalg == KMF_DSA) { 184499ebb4caSwyllys DSA *dsa = EVP_PKEY_get1_DSA(key->keyp); 184599ebb4caSwyllys 184699ebb4caSwyllys uchar_t hash[EVP_MAX_MD_SIZE]; 184799ebb4caSwyllys uint32_t hashlen; 184899ebb4caSwyllys DSA_SIG *dsasig; 184999ebb4caSwyllys 1850e65e5c2dSWyllys Ingersoll if (AlgId == KMF_ALGID_DSA || 1851e65e5c2dSWyllys Ingersoll AlgId == KMF_ALGID_SHA1WithDSA) 1852e65e5c2dSWyllys Ingersoll md = EVP_sha1(); 1853e65e5c2dSWyllys Ingersoll else if (AlgId == KMF_ALGID_SHA256WithDSA) 1854e65e5c2dSWyllys Ingersoll md = EVP_sha256(); 1855e65e5c2dSWyllys Ingersoll else /* Bad algorithm */ 1856e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM); 1857e65e5c2dSWyllys Ingersoll 185899ebb4caSwyllys /* 185999ebb4caSwyllys * OpenSSL EVP_Sign operation automatically converts to 186099ebb4caSwyllys * ASN.1 output so we do the operations separately so we 186199ebb4caSwyllys * are assured of NOT getting ASN.1 output returned. 186299ebb4caSwyllys * KMF does not want ASN.1 encoded results because 186399ebb4caSwyllys * not all mechanisms return ASN.1 encodings (PKCS#11 186499ebb4caSwyllys * and NSS return raw signature data). 186599ebb4caSwyllys */ 186699ebb4caSwyllys EVP_MD_CTX_init(&ctx); 186799ebb4caSwyllys (void) EVP_DigestInit_ex(&ctx, md, NULL); 186899ebb4caSwyllys (void) EVP_DigestUpdate(&ctx, tobesigned->Data, 186999ebb4caSwyllys tobesigned->Length); 187099ebb4caSwyllys (void) EVP_DigestFinal_ex(&ctx, hash, &hashlen); 187199ebb4caSwyllys 1872e65e5c2dSWyllys Ingersoll /* Only sign first 20 bytes for SHA2 */ 1873e65e5c2dSWyllys Ingersoll if (AlgId == KMF_ALGID_SHA256WithDSA) 1874e65e5c2dSWyllys Ingersoll hashlen = 20; 187599ebb4caSwyllys dsasig = DSA_do_sign(hash, hashlen, dsa); 187699ebb4caSwyllys if (dsasig != NULL) { 187799ebb4caSwyllys int i; 1878e65e5c2dSWyllys Ingersoll output->Length = i = fixbnlen(dsasig->r, output->Data, 1879e65e5c2dSWyllys Ingersoll hashlen); 1880*2c9a247fSWyllys Ingersoll 1881e65e5c2dSWyllys Ingersoll output->Length += fixbnlen(dsasig->s, &output->Data[i], 1882e65e5c2dSWyllys Ingersoll hashlen); 1883*2c9a247fSWyllys Ingersoll 188499ebb4caSwyllys DSA_SIG_free(dsasig); 188599ebb4caSwyllys } else { 188699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 188799ebb4caSwyllys } 1888e65e5c2dSWyllys Ingersoll (void) EVP_MD_CTX_cleanup(&ctx); 188999ebb4caSwyllys } else { 189099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 189199ebb4caSwyllys } 189299ebb4caSwyllys cleanup: 189399ebb4caSwyllys return (ret); 189499ebb4caSwyllys } 189599ebb4caSwyllys 189699ebb4caSwyllys KMF_RETURN 189799ebb4caSwyllys /*ARGSUSED*/ 189830a5e8faSwyllys OpenSSL_DeleteKey(KMF_HANDLE_T handle, 189930a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 190099ebb4caSwyllys { 190199ebb4caSwyllys KMF_RETURN rv = KMF_OK; 190230a5e8faSwyllys KMF_KEY_HANDLE *key; 190330a5e8faSwyllys boolean_t destroy = B_TRUE; 190430a5e8faSwyllys 190530a5e8faSwyllys key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 190699ebb4caSwyllys if (key == NULL || key->keyp == NULL) 190799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 190899ebb4caSwyllys 190930a5e8faSwyllys rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr, 191030a5e8faSwyllys (void *)&destroy, NULL); 191130a5e8faSwyllys if (rv != KMF_OK) { 191230a5e8faSwyllys /* "destroy" is optional. Default is TRUE */ 191330a5e8faSwyllys rv = KMF_OK; 191430a5e8faSwyllys } 191530a5e8faSwyllys 191699ebb4caSwyllys if (key->keyclass != KMF_ASYM_PUB && 191799ebb4caSwyllys key->keyclass != KMF_ASYM_PRI && 191899ebb4caSwyllys key->keyclass != KMF_SYMMETRIC) 191999ebb4caSwyllys return (KMF_ERR_BAD_KEY_CLASS); 192099ebb4caSwyllys 192199ebb4caSwyllys if (key->keyclass == KMF_SYMMETRIC) { 192230a5e8faSwyllys kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp); 192399ebb4caSwyllys key->keyp = NULL; 192499ebb4caSwyllys } else { 192599ebb4caSwyllys if (key->keyp != NULL) { 192699ebb4caSwyllys EVP_PKEY_free(key->keyp); 192799ebb4caSwyllys key->keyp = NULL; 192899ebb4caSwyllys } 192999ebb4caSwyllys } 193099ebb4caSwyllys 193199ebb4caSwyllys if (key->keylabel != NULL) { 193299ebb4caSwyllys EVP_PKEY *pkey = NULL; 193399ebb4caSwyllys /* If the file exists, make sure it is a proper key. */ 193499ebb4caSwyllys pkey = openssl_load_key(handle, key->keylabel); 193599ebb4caSwyllys if (pkey == NULL) { 19365b3e1433Swyllys if (key->keylabel != NULL) { 193799ebb4caSwyllys free(key->keylabel); 193899ebb4caSwyllys key->keylabel = NULL; 19395b3e1433Swyllys } 194099ebb4caSwyllys return (KMF_ERR_KEY_NOT_FOUND); 194199ebb4caSwyllys } 194299ebb4caSwyllys EVP_PKEY_free(pkey); 194399ebb4caSwyllys 194499ebb4caSwyllys if (destroy) { 194599ebb4caSwyllys if (unlink(key->keylabel) != 0) { 194699ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 194799ebb4caSwyllys SET_SYS_ERROR(kmfh, errno); 194899ebb4caSwyllys rv = KMF_ERR_INTERNAL; 194999ebb4caSwyllys } 195099ebb4caSwyllys } 195199ebb4caSwyllys if (key->keylabel != NULL) { 195299ebb4caSwyllys free(key->keylabel); 195399ebb4caSwyllys key->keylabel = NULL; 195499ebb4caSwyllys } 195599ebb4caSwyllys } 195699ebb4caSwyllys return (rv); 195799ebb4caSwyllys } 195899ebb4caSwyllys 195999ebb4caSwyllys KMF_RETURN 196099ebb4caSwyllys OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr) 196199ebb4caSwyllys { 196299ebb4caSwyllys KMF_RETURN ret = KMF_OK; 196399ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 196499ebb4caSwyllys char str[256]; /* OpenSSL needs at least 120 byte buffer */ 196599ebb4caSwyllys 196699ebb4caSwyllys ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str)); 196799ebb4caSwyllys if (strlen(str)) { 196899ebb4caSwyllys *msgstr = (char *)strdup(str); 196999ebb4caSwyllys if ((*msgstr) == NULL) 197099ebb4caSwyllys ret = KMF_ERR_MEMORY; 197199ebb4caSwyllys } else { 197299ebb4caSwyllys *msgstr = NULL; 197399ebb4caSwyllys } 197499ebb4caSwyllys 197599ebb4caSwyllys return (ret); 197699ebb4caSwyllys } 197799ebb4caSwyllys 197899ebb4caSwyllys static int 197999ebb4caSwyllys ext2NID(int kmfext) 198099ebb4caSwyllys { 198199ebb4caSwyllys switch (kmfext) { 198299ebb4caSwyllys case KMF_X509_EXT_KEY_USAGE: 198399ebb4caSwyllys return (NID_key_usage); 198499ebb4caSwyllys case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD: 198599ebb4caSwyllys return (NID_private_key_usage_period); 198699ebb4caSwyllys case KMF_X509_EXT_CERT_POLICIES: 198799ebb4caSwyllys return (NID_certificate_policies); 198899ebb4caSwyllys case KMF_X509_EXT_SUBJ_ALTNAME: 198999ebb4caSwyllys return (NID_subject_alt_name); 199099ebb4caSwyllys case KMF_X509_EXT_ISSUER_ALTNAME: 199199ebb4caSwyllys return (NID_issuer_alt_name); 199299ebb4caSwyllys case KMF_X509_EXT_BASIC_CONSTRAINTS: 199399ebb4caSwyllys return (NID_basic_constraints); 199499ebb4caSwyllys case KMF_X509_EXT_EXT_KEY_USAGE: 199599ebb4caSwyllys return (NID_ext_key_usage); 199699ebb4caSwyllys case KMF_X509_EXT_AUTH_KEY_ID: 199799ebb4caSwyllys return (NID_authority_key_identifier); 199899ebb4caSwyllys case KMF_X509_EXT_CRL_DIST_POINTS: 199999ebb4caSwyllys return (NID_crl_distribution_points); 200099ebb4caSwyllys case KMF_X509_EXT_SUBJ_KEY_ID: 200199ebb4caSwyllys return (NID_subject_key_identifier); 200299ebb4caSwyllys case KMF_X509_EXT_POLICY_MAPPINGS: 200399ebb4caSwyllys return (OBJ_sn2nid("policyMappings")); 200499ebb4caSwyllys case KMF_X509_EXT_NAME_CONSTRAINTS: 200599ebb4caSwyllys return (OBJ_sn2nid("nameConstraints")); 200699ebb4caSwyllys case KMF_X509_EXT_POLICY_CONSTRAINTS: 200799ebb4caSwyllys return (OBJ_sn2nid("policyConstraints")); 200899ebb4caSwyllys case KMF_X509_EXT_INHIBIT_ANY_POLICY: 200999ebb4caSwyllys return (OBJ_sn2nid("inhibitAnyPolicy")); 201099ebb4caSwyllys case KMF_X509_EXT_FRESHEST_CRL: 201199ebb4caSwyllys return (OBJ_sn2nid("freshestCRL")); 201299ebb4caSwyllys default: 201399ebb4caSwyllys return (NID_undef); 201499ebb4caSwyllys } 201599ebb4caSwyllys } 201699ebb4caSwyllys 201799ebb4caSwyllys KMF_RETURN 201899ebb4caSwyllys OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert, 201999ebb4caSwyllys KMF_PRINTABLE_ITEM flag, char *resultStr) 202099ebb4caSwyllys { 202199ebb4caSwyllys KMF_RETURN ret = KMF_OK; 202299ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 202399ebb4caSwyllys X509 *xcert = NULL; 202499ebb4caSwyllys unsigned char *outbuf = NULL; 202599ebb4caSwyllys unsigned char *outbuf_p; 202699ebb4caSwyllys char *tmpstr = NULL; 202799ebb4caSwyllys int j; 202899ebb4caSwyllys int ext_index, nid, len; 202999ebb4caSwyllys BIO *mem = NULL; 203099ebb4caSwyllys STACK *emlst = NULL; 203199ebb4caSwyllys X509_EXTENSION *ex; 203299ebb4caSwyllys X509_CINF *ci; 203399ebb4caSwyllys 203499ebb4caSwyllys if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) { 203599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 203699ebb4caSwyllys } 203799ebb4caSwyllys 203899ebb4caSwyllys /* copy cert data to outbuf */ 203999ebb4caSwyllys outbuf = malloc(pcert->Length); 204099ebb4caSwyllys if (outbuf == NULL) { 204199ebb4caSwyllys return (KMF_ERR_MEMORY); 204299ebb4caSwyllys } 204399ebb4caSwyllys (void) memcpy(outbuf, pcert->Data, pcert->Length); 204499ebb4caSwyllys 204599ebb4caSwyllys outbuf_p = outbuf; /* use a temp pointer; required by openssl */ 204699ebb4caSwyllys xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length); 204799ebb4caSwyllys if (xcert == NULL) { 204899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 204999ebb4caSwyllys ret = KMF_ERR_ENCODING; 205099ebb4caSwyllys goto out; 205199ebb4caSwyllys } 205299ebb4caSwyllys 205399ebb4caSwyllys mem = BIO_new(BIO_s_mem()); 205499ebb4caSwyllys if (mem == NULL) { 205599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 205699ebb4caSwyllys ret = KMF_ERR_MEMORY; 205799ebb4caSwyllys goto out; 205899ebb4caSwyllys } 205999ebb4caSwyllys 206099ebb4caSwyllys switch (flag) { 206199ebb4caSwyllys case KMF_CERT_ISSUER: 206299ebb4caSwyllys (void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0, 206399ebb4caSwyllys XN_FLAG_SEP_CPLUS_SPC); 206499ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 206599ebb4caSwyllys break; 206699ebb4caSwyllys 206799ebb4caSwyllys case KMF_CERT_SUBJECT: 206899ebb4caSwyllys (void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0, 206999ebb4caSwyllys XN_FLAG_SEP_CPLUS_SPC); 207099ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 207199ebb4caSwyllys break; 207299ebb4caSwyllys 207399ebb4caSwyllys case KMF_CERT_VERSION: 207499ebb4caSwyllys tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version); 207599ebb4caSwyllys (void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN); 207699ebb4caSwyllys OPENSSL_free(tmpstr); 207799ebb4caSwyllys len = strlen(resultStr); 207899ebb4caSwyllys break; 207999ebb4caSwyllys 208099ebb4caSwyllys case KMF_CERT_SERIALNUM: 208199ebb4caSwyllys if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) { 208299ebb4caSwyllys (void) strcpy(resultStr, "0x"); 208399ebb4caSwyllys len = BIO_gets(mem, &resultStr[2], 208499ebb4caSwyllys KMF_CERT_PRINTABLE_LEN - 2); 208599ebb4caSwyllys } 208699ebb4caSwyllys break; 208799ebb4caSwyllys 208899ebb4caSwyllys case KMF_CERT_NOTBEFORE: 208999ebb4caSwyllys (void) ASN1_TIME_print(mem, X509_get_notBefore(xcert)); 209099ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 209199ebb4caSwyllys break; 209299ebb4caSwyllys 209399ebb4caSwyllys case KMF_CERT_NOTAFTER: 209499ebb4caSwyllys (void) ASN1_TIME_print(mem, X509_get_notAfter(xcert)); 209599ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 209699ebb4caSwyllys break; 209799ebb4caSwyllys 209899ebb4caSwyllys case KMF_CERT_PUBKEY_DATA: 209999ebb4caSwyllys { 210099ebb4caSwyllys EVP_PKEY *pkey = X509_get_pubkey(xcert); 210199ebb4caSwyllys if (pkey == NULL) { 210299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 210399ebb4caSwyllys ret = KMF_ERR_ENCODING; 210499ebb4caSwyllys goto out; 210599ebb4caSwyllys } 210699ebb4caSwyllys 210799ebb4caSwyllys if (pkey->type == EVP_PKEY_RSA) { 210899ebb4caSwyllys (void) BIO_printf(mem, 210999ebb4caSwyllys "RSA Public Key: (%d bit)\n", 211099ebb4caSwyllys BN_num_bits(pkey->pkey.rsa->n)); 211199ebb4caSwyllys (void) RSA_print(mem, pkey->pkey.rsa, 0); 211299ebb4caSwyllys } else if (pkey->type == EVP_PKEY_DSA) { 211399ebb4caSwyllys (void) BIO_printf(mem, 211499ebb4caSwyllys "%12sDSA Public Key:\n", ""); 211599ebb4caSwyllys (void) DSA_print(mem, pkey->pkey.dsa, 0); 211699ebb4caSwyllys } else { 211799ebb4caSwyllys (void) BIO_printf(mem, 211899ebb4caSwyllys "%12sUnknown Public Key:\n", ""); 211999ebb4caSwyllys } 212099ebb4caSwyllys (void) BIO_printf(mem, "\n"); 212199ebb4caSwyllys EVP_PKEY_free(pkey); 212299ebb4caSwyllys } 212399ebb4caSwyllys len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 212499ebb4caSwyllys break; 212599ebb4caSwyllys case KMF_CERT_SIGNATURE_ALG: 212699ebb4caSwyllys case KMF_CERT_PUBKEY_ALG: 212799ebb4caSwyllys if (flag == KMF_CERT_SIGNATURE_ALG) { 212899ebb4caSwyllys len = i2a_ASN1_OBJECT(mem, 212999ebb4caSwyllys xcert->sig_alg->algorithm); 213099ebb4caSwyllys } else { 213199ebb4caSwyllys len = i2a_ASN1_OBJECT(mem, 213299ebb4caSwyllys xcert->cert_info->key->algor->algorithm); 213399ebb4caSwyllys } 213499ebb4caSwyllys 213599ebb4caSwyllys if (len > 0) { 213699ebb4caSwyllys len = BIO_read(mem, resultStr, 213799ebb4caSwyllys KMF_CERT_PRINTABLE_LEN); 213899ebb4caSwyllys } 213999ebb4caSwyllys break; 214099ebb4caSwyllys 214199ebb4caSwyllys case KMF_CERT_EMAIL: 214299ebb4caSwyllys emlst = X509_get1_email(xcert); 214399ebb4caSwyllys for (j = 0; j < sk_num(emlst); j++) 214499ebb4caSwyllys (void) BIO_printf(mem, "%s\n", sk_value(emlst, j)); 214599ebb4caSwyllys 214699ebb4caSwyllys len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 214799ebb4caSwyllys X509_email_free(emlst); 214899ebb4caSwyllys break; 214999ebb4caSwyllys case KMF_X509_EXT_ISSUER_ALTNAME: 215099ebb4caSwyllys case KMF_X509_EXT_SUBJ_ALTNAME: 215199ebb4caSwyllys case KMF_X509_EXT_KEY_USAGE: 215299ebb4caSwyllys case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD: 215399ebb4caSwyllys case KMF_X509_EXT_CERT_POLICIES: 215499ebb4caSwyllys case KMF_X509_EXT_BASIC_CONSTRAINTS: 215599ebb4caSwyllys case KMF_X509_EXT_NAME_CONSTRAINTS: 215699ebb4caSwyllys case KMF_X509_EXT_POLICY_CONSTRAINTS: 215799ebb4caSwyllys case KMF_X509_EXT_EXT_KEY_USAGE: 215899ebb4caSwyllys case KMF_X509_EXT_INHIBIT_ANY_POLICY: 215999ebb4caSwyllys case KMF_X509_EXT_AUTH_KEY_ID: 216099ebb4caSwyllys case KMF_X509_EXT_SUBJ_KEY_ID: 216199ebb4caSwyllys case KMF_X509_EXT_POLICY_MAPPINGS: 216299ebb4caSwyllys case KMF_X509_EXT_CRL_DIST_POINTS: 216399ebb4caSwyllys case KMF_X509_EXT_FRESHEST_CRL: 216499ebb4caSwyllys nid = ext2NID(flag); 216599ebb4caSwyllys if (nid == NID_undef) { 216699ebb4caSwyllys ret = KMF_ERR_EXTENSION_NOT_FOUND; 216799ebb4caSwyllys goto out; 216899ebb4caSwyllys } 216999ebb4caSwyllys ci = xcert->cert_info; 217099ebb4caSwyllys 217199ebb4caSwyllys ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1); 217299ebb4caSwyllys if (ext_index == -1) { 217399ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 217499ebb4caSwyllys 217599ebb4caSwyllys ret = KMF_ERR_EXTENSION_NOT_FOUND; 217699ebb4caSwyllys goto out; 217799ebb4caSwyllys } 217899ebb4caSwyllys ex = X509v3_get_ext(ci->extensions, ext_index); 217999ebb4caSwyllys 218099ebb4caSwyllys (void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex)); 218199ebb4caSwyllys 218299ebb4caSwyllys if (BIO_printf(mem, ": %s\n", 218330a5e8faSwyllys X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) { 218499ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 218599ebb4caSwyllys ret = KMF_ERR_ENCODING; 218699ebb4caSwyllys goto out; 218799ebb4caSwyllys } 218899ebb4caSwyllys if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) { 218999ebb4caSwyllys (void) BIO_printf(mem, "%*s", 4, ""); 219099ebb4caSwyllys (void) M_ASN1_OCTET_STRING_print(mem, ex->value); 219199ebb4caSwyllys } 219299ebb4caSwyllys if (BIO_write(mem, "\n", 1) <= 0) { 219399ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 219499ebb4caSwyllys ret = KMF_ERR_ENCODING; 219599ebb4caSwyllys goto out; 219699ebb4caSwyllys } 219799ebb4caSwyllys len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN); 219899ebb4caSwyllys } 219999ebb4caSwyllys if (len <= 0) { 220099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 220199ebb4caSwyllys ret = KMF_ERR_ENCODING; 220299ebb4caSwyllys } 220399ebb4caSwyllys 220499ebb4caSwyllys out: 220599ebb4caSwyllys if (outbuf != NULL) { 220699ebb4caSwyllys free(outbuf); 220799ebb4caSwyllys } 220899ebb4caSwyllys 220999ebb4caSwyllys if (xcert != NULL) { 221099ebb4caSwyllys X509_free(xcert); 221199ebb4caSwyllys } 221299ebb4caSwyllys 221399ebb4caSwyllys if (mem != NULL) { 221499ebb4caSwyllys (void) BIO_free(mem); 221599ebb4caSwyllys } 221699ebb4caSwyllys 221799ebb4caSwyllys return (ret); 221899ebb4caSwyllys } 221930a5e8faSwyllys 222099ebb4caSwyllys KMF_RETURN 222199ebb4caSwyllys /*ARGSUSED*/ 222230a5e8faSwyllys OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr, 222330a5e8faSwyllys KMF_ATTRIBUTE *attrlist) 222499ebb4caSwyllys { 222599ebb4caSwyllys KMF_RETURN rv = KMF_OK; 222630a5e8faSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL; 222730a5e8faSwyllys KMF_KEY_CLASS keyclass = KMF_ASYM_PRI; 222830a5e8faSwyllys KMF_KEY_HANDLE *key = NULL; 222930a5e8faSwyllys uint32_t numkeys = 1; /* 1 key only */ 223030a5e8faSwyllys char *dirpath = NULL; 223130a5e8faSwyllys char *keyfile = NULL; 223230a5e8faSwyllys KMF_ATTRIBUTE new_attrlist[16]; 223330a5e8faSwyllys int i = 0; 223499ebb4caSwyllys 223599ebb4caSwyllys /* 223699ebb4caSwyllys * This is really just a FindKey operation, reuse the 223799ebb4caSwyllys * FindKey function. 223899ebb4caSwyllys */ 223930a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 224030a5e8faSwyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 224130a5e8faSwyllys i++; 224299ebb4caSwyllys 224330a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 224430a5e8faSwyllys KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t)); 224530a5e8faSwyllys i++; 224699ebb4caSwyllys 224730a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 224830a5e8faSwyllys KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass)); 224930a5e8faSwyllys i++; 225030a5e8faSwyllys 225130a5e8faSwyllys key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 225230a5e8faSwyllys if (key == NULL) { 225330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 225430a5e8faSwyllys } else { 225530a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 225630a5e8faSwyllys KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE)); 225730a5e8faSwyllys i++; 225830a5e8faSwyllys } 225930a5e8faSwyllys 226030a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 226130a5e8faSwyllys if (dirpath != NULL) { 226230a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 226330a5e8faSwyllys KMF_DIRPATH_ATTR, dirpath, strlen(dirpath)); 226430a5e8faSwyllys i++; 226530a5e8faSwyllys } 226630a5e8faSwyllys 226730a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 226830a5e8faSwyllys if (keyfile == NULL) 226930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 227030a5e8faSwyllys else { 227130a5e8faSwyllys kmf_set_attr_at_index(new_attrlist, i, 227230a5e8faSwyllys KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile)); 227330a5e8faSwyllys i++; 227430a5e8faSwyllys } 227530a5e8faSwyllys 227630a5e8faSwyllys rv = OpenSSL_FindKey(handle, i, new_attrlist); 227799ebb4caSwyllys return (rv); 227899ebb4caSwyllys } 227999ebb4caSwyllys 228099ebb4caSwyllys KMF_RETURN 228199ebb4caSwyllys /*ARGSUSED*/ 228299ebb4caSwyllys OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, 228399ebb4caSwyllys KMF_OID *AlgOID, KMF_DATA *ciphertext, 228499ebb4caSwyllys KMF_DATA *output) 228599ebb4caSwyllys { 228699ebb4caSwyllys KMF_RETURN ret = KMF_OK; 228799ebb4caSwyllys RSA *rsa = NULL; 228899ebb4caSwyllys unsigned int in_len = 0, out_len = 0; 228999ebb4caSwyllys unsigned int total_decrypted = 0, modulus_len = 0; 229099ebb4caSwyllys uint8_t *in_data, *out_data; 229199ebb4caSwyllys int i, blocks; 229299ebb4caSwyllys 229399ebb4caSwyllys if (key == NULL || AlgOID == NULL || 229499ebb4caSwyllys ciphertext == NULL || output == NULL || 229599ebb4caSwyllys ciphertext->Data == NULL || 229699ebb4caSwyllys output->Data == NULL) 229799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 229899ebb4caSwyllys 229999ebb4caSwyllys if (key->keyalg == KMF_RSA) { 230099ebb4caSwyllys rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp); 230199ebb4caSwyllys modulus_len = RSA_size(rsa); 230299ebb4caSwyllys } else { 230399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 230499ebb4caSwyllys } 230599ebb4caSwyllys 230699ebb4caSwyllys blocks = ciphertext->Length/modulus_len; 230799ebb4caSwyllys out_data = output->Data; 230899ebb4caSwyllys in_data = ciphertext->Data; 230999ebb4caSwyllys out_len = modulus_len - 11; 231099ebb4caSwyllys in_len = modulus_len; 231199ebb4caSwyllys 231299ebb4caSwyllys for (i = 0; i < blocks; i++) { 231399ebb4caSwyllys out_len = RSA_private_decrypt(in_len, 231499ebb4caSwyllys in_data, out_data, rsa, RSA_PKCS1_PADDING); 231599ebb4caSwyllys 231699ebb4caSwyllys if (out_len == 0) { 231799ebb4caSwyllys ret = KMF_ERR_INTERNAL; 231899ebb4caSwyllys goto cleanup; 231999ebb4caSwyllys } 232099ebb4caSwyllys 232199ebb4caSwyllys out_data += out_len; 232299ebb4caSwyllys total_decrypted += out_len; 232399ebb4caSwyllys in_data += in_len; 232499ebb4caSwyllys } 232599ebb4caSwyllys 232699ebb4caSwyllys output->Length = total_decrypted; 232799ebb4caSwyllys 232899ebb4caSwyllys cleanup: 232999ebb4caSwyllys RSA_free(rsa); 233099ebb4caSwyllys if (ret != KMF_OK) 233199ebb4caSwyllys output->Length = 0; 233299ebb4caSwyllys 233399ebb4caSwyllys return (ret); 233499ebb4caSwyllys 233599ebb4caSwyllys } 233699ebb4caSwyllys 233799ebb4caSwyllys /* 233899ebb4caSwyllys * This function will create a certid from issuer_cert and user_cert. 233999ebb4caSwyllys * The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate 234099ebb4caSwyllys * certid memory after use. 234199ebb4caSwyllys */ 234299ebb4caSwyllys static KMF_RETURN 234399ebb4caSwyllys create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert, 234499ebb4caSwyllys const KMF_DATA *user_cert, OCSP_CERTID **certid) 234599ebb4caSwyllys { 234699ebb4caSwyllys KMF_RETURN ret = KMF_OK; 234799ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 234899ebb4caSwyllys X509 *issuer = NULL; 234999ebb4caSwyllys X509 *cert = NULL; 235099ebb4caSwyllys unsigned char *ptmp; 235199ebb4caSwyllys 235299ebb4caSwyllys if (issuer_cert == NULL || user_cert == NULL) { 235399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 235499ebb4caSwyllys } 235599ebb4caSwyllys 235699ebb4caSwyllys /* convert the DER-encoded issuer cert to an internal X509 */ 235799ebb4caSwyllys ptmp = issuer_cert->Data; 235899ebb4caSwyllys issuer = d2i_X509(NULL, (const uchar_t **)&ptmp, 235999ebb4caSwyllys issuer_cert->Length); 236099ebb4caSwyllys if (issuer == NULL) { 236199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 236299ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_ISSUER; 236399ebb4caSwyllys goto end; 236499ebb4caSwyllys } 236599ebb4caSwyllys 236699ebb4caSwyllys /* convert the DER-encoded user cert to an internal X509 */ 236799ebb4caSwyllys ptmp = user_cert->Data; 236899ebb4caSwyllys cert = d2i_X509(NULL, (const uchar_t **)&ptmp, 236999ebb4caSwyllys user_cert->Length); 237099ebb4caSwyllys if (cert == NULL) { 237199ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 237299ebb4caSwyllys 237399ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_CERT; 237499ebb4caSwyllys goto end; 237599ebb4caSwyllys } 237699ebb4caSwyllys 237799ebb4caSwyllys /* create a CERTID */ 237899ebb4caSwyllys *certid = OCSP_cert_to_id(NULL, cert, issuer); 237999ebb4caSwyllys if (*certid == NULL) { 238099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 238199ebb4caSwyllys ret = KMF_ERR_OCSP_CERTID; 238299ebb4caSwyllys goto end; 238399ebb4caSwyllys } 238499ebb4caSwyllys 238599ebb4caSwyllys end: 238699ebb4caSwyllys if (issuer != NULL) { 238799ebb4caSwyllys X509_free(issuer); 238899ebb4caSwyllys } 238999ebb4caSwyllys 239099ebb4caSwyllys if (cert != NULL) { 239199ebb4caSwyllys X509_free(cert); 239299ebb4caSwyllys } 239399ebb4caSwyllys 239499ebb4caSwyllys return (ret); 239599ebb4caSwyllys } 239699ebb4caSwyllys 239799ebb4caSwyllys KMF_RETURN 239830a5e8faSwyllys OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle, 239930a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 240099ebb4caSwyllys { 240199ebb4caSwyllys KMF_RETURN ret = KMF_OK; 240299ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 240399ebb4caSwyllys OCSP_CERTID *id = NULL; 240499ebb4caSwyllys OCSP_REQUEST *req = NULL; 240599ebb4caSwyllys BIO *derbio = NULL; 240630a5e8faSwyllys char *reqfile; 240730a5e8faSwyllys KMF_DATA *issuer_cert; 240830a5e8faSwyllys KMF_DATA *user_cert; 240999ebb4caSwyllys 241030a5e8faSwyllys user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR, 241130a5e8faSwyllys attrlist, numattr); 241230a5e8faSwyllys if (user_cert == NULL) 241399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 241499ebb4caSwyllys 241530a5e8faSwyllys issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR, 241630a5e8faSwyllys attrlist, numattr); 241730a5e8faSwyllys if (issuer_cert == NULL) 241830a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 241930a5e8faSwyllys 242030a5e8faSwyllys reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR, 242130a5e8faSwyllys attrlist, numattr); 242230a5e8faSwyllys if (reqfile == NULL) 242330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 242430a5e8faSwyllys 242530a5e8faSwyllys ret = create_certid(handle, issuer_cert, user_cert, &id); 242699ebb4caSwyllys if (ret != KMF_OK) { 242799ebb4caSwyllys return (ret); 242899ebb4caSwyllys } 242999ebb4caSwyllys 243099ebb4caSwyllys /* Create an OCSP request */ 243199ebb4caSwyllys req = OCSP_REQUEST_new(); 243299ebb4caSwyllys if (req == NULL) { 243399ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 243499ebb4caSwyllys ret = KMF_ERR_OCSP_CREATE_REQUEST; 243599ebb4caSwyllys goto end; 243699ebb4caSwyllys } 243799ebb4caSwyllys 243899ebb4caSwyllys if (!OCSP_request_add0_id(req, id)) { 243999ebb4caSwyllys ret = KMF_ERR_OCSP_CREATE_REQUEST; 244099ebb4caSwyllys goto end; 244199ebb4caSwyllys } 244299ebb4caSwyllys 244399ebb4caSwyllys /* Write the request to the output file with DER encoding */ 244499ebb4caSwyllys derbio = BIO_new_file(reqfile, "wb"); 244599ebb4caSwyllys if (!derbio) { 244699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 244799ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 244899ebb4caSwyllys goto end; 244999ebb4caSwyllys } 245099ebb4caSwyllys if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) { 245199ebb4caSwyllys ret = KMF_ERR_ENCODING; 245299ebb4caSwyllys } 245399ebb4caSwyllys 245499ebb4caSwyllys end: 245599ebb4caSwyllys /* 2456e65e5c2dSWyllys Ingersoll * We don't need to free "id" explicitely, because OCSP_REQUEST_free() 2457a2d4930dSDan OpenSolaris Anderson * will also deallocate certid's space. 245899ebb4caSwyllys */ 245999ebb4caSwyllys if (req != NULL) { 246099ebb4caSwyllys OCSP_REQUEST_free(req); 246199ebb4caSwyllys } 246299ebb4caSwyllys 246399ebb4caSwyllys if (derbio != NULL) { 246499ebb4caSwyllys (void) BIO_free(derbio); 246599ebb4caSwyllys } 246699ebb4caSwyllys 246799ebb4caSwyllys return (ret); 246899ebb4caSwyllys } 246999ebb4caSwyllys 247099ebb4caSwyllys /* ocsp_find_signer_sk() is copied from openssl source */ 247199ebb4caSwyllys static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id) 247299ebb4caSwyllys { 247399ebb4caSwyllys int i; 247499ebb4caSwyllys unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash; 247599ebb4caSwyllys 247699ebb4caSwyllys /* Easy if lookup by name */ 247799ebb4caSwyllys if (id->type == V_OCSP_RESPID_NAME) 247899ebb4caSwyllys return (X509_find_by_subject(certs, id->value.byName)); 247999ebb4caSwyllys 248099ebb4caSwyllys /* Lookup by key hash */ 248199ebb4caSwyllys 248299ebb4caSwyllys /* If key hash isn't SHA1 length then forget it */ 248399ebb4caSwyllys if (id->value.byKey->length != SHA_DIGEST_LENGTH) 248499ebb4caSwyllys return (NULL); 248599ebb4caSwyllys 248699ebb4caSwyllys keyhash = id->value.byKey->data; 248799ebb4caSwyllys /* Calculate hash of each key and compare */ 248899ebb4caSwyllys for (i = 0; i < sk_X509_num(certs); i++) { 2489a2d4930dSDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */ 249099ebb4caSwyllys X509 *x = sk_X509_value(certs, i); 24915b3e1433Swyllys /* Use pubkey_digest to get the key ID value */ 249299ebb4caSwyllys (void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL); 249399ebb4caSwyllys if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH)) 249499ebb4caSwyllys return (x); 249599ebb4caSwyllys } 249699ebb4caSwyllys return (NULL); 249799ebb4caSwyllys } 249899ebb4caSwyllys 249999ebb4caSwyllys /* ocsp_find_signer() is copied from openssl source */ 2500a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */ 250199ebb4caSwyllys static int 250299ebb4caSwyllys ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs, 250399ebb4caSwyllys X509_STORE *st, unsigned long flags) 250499ebb4caSwyllys { 250599ebb4caSwyllys X509 *signer; 250699ebb4caSwyllys OCSP_RESPID *rid = bs->tbsResponseData->responderId; 250799ebb4caSwyllys if ((signer = ocsp_find_signer_sk(certs, rid))) { 250899ebb4caSwyllys *psigner = signer; 250999ebb4caSwyllys return (2); 251099ebb4caSwyllys } 251199ebb4caSwyllys if (!(flags & OCSP_NOINTERN) && 251299ebb4caSwyllys (signer = ocsp_find_signer_sk(bs->certs, rid))) { 251399ebb4caSwyllys *psigner = signer; 251499ebb4caSwyllys return (1); 251599ebb4caSwyllys } 251699ebb4caSwyllys /* Maybe lookup from store if by subject name */ 251799ebb4caSwyllys 251899ebb4caSwyllys *psigner = NULL; 251999ebb4caSwyllys return (0); 252099ebb4caSwyllys } 252199ebb4caSwyllys 252299ebb4caSwyllys /* 252399ebb4caSwyllys * This function will verify the signature of a basic response, using 252499ebb4caSwyllys * the public key from the OCSP responder certificate. 252599ebb4caSwyllys */ 252699ebb4caSwyllys static KMF_RETURN 252799ebb4caSwyllys check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs, 252899ebb4caSwyllys KMF_DATA *signer_cert, KMF_DATA *issuer_cert) 252999ebb4caSwyllys { 253099ebb4caSwyllys KMF_RETURN ret = KMF_OK; 253199ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 253299ebb4caSwyllys STACK_OF(X509) *cert_stack = NULL; 253399ebb4caSwyllys X509 *signer = NULL; 253499ebb4caSwyllys X509 *issuer = NULL; 253599ebb4caSwyllys EVP_PKEY *skey = NULL; 253699ebb4caSwyllys unsigned char *ptmp; 253799ebb4caSwyllys 253899ebb4caSwyllys 253999ebb4caSwyllys if (bs == NULL || issuer_cert == NULL) 254099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 254199ebb4caSwyllys 254299ebb4caSwyllys /* 254399ebb4caSwyllys * Find the certificate that signed the basic response. 254499ebb4caSwyllys * 254599ebb4caSwyllys * If signer_cert is not NULL, we will use that as the signer cert. 254699ebb4caSwyllys * Otherwise, we will check if the issuer cert is actually the signer. 254799ebb4caSwyllys * If we still do not find a signer, we will look for it from the 254899ebb4caSwyllys * certificate list came with the response file. 254999ebb4caSwyllys */ 255099ebb4caSwyllys if (signer_cert != NULL) { 255199ebb4caSwyllys ptmp = signer_cert->Data; 255299ebb4caSwyllys signer = d2i_X509(NULL, (const uchar_t **)&ptmp, 255399ebb4caSwyllys signer_cert->Length); 255499ebb4caSwyllys if (signer == NULL) { 255599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 255699ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_SIGNER; 255799ebb4caSwyllys goto end; 255899ebb4caSwyllys } 255999ebb4caSwyllys } else { 256099ebb4caSwyllys /* 256199ebb4caSwyllys * Convert the issuer cert into X509 and push it into a 256299ebb4caSwyllys * stack to be used by ocsp_find_signer(). 256399ebb4caSwyllys */ 256499ebb4caSwyllys ptmp = issuer_cert->Data; 256599ebb4caSwyllys issuer = d2i_X509(NULL, (const uchar_t **)&ptmp, 256699ebb4caSwyllys issuer_cert->Length); 256799ebb4caSwyllys if (issuer == NULL) { 256899ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 256999ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_ISSUER; 257099ebb4caSwyllys goto end; 257199ebb4caSwyllys } 257299ebb4caSwyllys 257399ebb4caSwyllys if ((cert_stack = sk_X509_new_null()) == NULL) { 257499ebb4caSwyllys ret = KMF_ERR_INTERNAL; 257599ebb4caSwyllys goto end; 257699ebb4caSwyllys } 257799ebb4caSwyllys 257899ebb4caSwyllys if (sk_X509_push(cert_stack, issuer) == NULL) { 257999ebb4caSwyllys ret = KMF_ERR_INTERNAL; 258099ebb4caSwyllys goto end; 258199ebb4caSwyllys } 258299ebb4caSwyllys 258399ebb4caSwyllys ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0); 258499ebb4caSwyllys if (!ret) { 258599ebb4caSwyllys /* can not find the signer */ 258699ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_SIGNER; 258799ebb4caSwyllys goto end; 258899ebb4caSwyllys } 258999ebb4caSwyllys } 259099ebb4caSwyllys 259199ebb4caSwyllys /* Verify the signature of the response */ 259299ebb4caSwyllys skey = X509_get_pubkey(signer); 259399ebb4caSwyllys if (skey == NULL) { 259499ebb4caSwyllys ret = KMF_ERR_OCSP_BAD_SIGNER; 259599ebb4caSwyllys goto end; 259699ebb4caSwyllys } 259799ebb4caSwyllys 259899ebb4caSwyllys ret = OCSP_BASICRESP_verify(bs, skey, 0); 259999ebb4caSwyllys if (ret == 0) { 260099ebb4caSwyllys ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE; 260199ebb4caSwyllys goto end; 260299ebb4caSwyllys } 260399ebb4caSwyllys 260499ebb4caSwyllys end: 260599ebb4caSwyllys if (issuer != NULL) { 260699ebb4caSwyllys X509_free(issuer); 260799ebb4caSwyllys } 260899ebb4caSwyllys 260999ebb4caSwyllys if (signer != NULL) { 261099ebb4caSwyllys X509_free(signer); 261199ebb4caSwyllys } 261299ebb4caSwyllys 261399ebb4caSwyllys if (skey != NULL) { 261499ebb4caSwyllys EVP_PKEY_free(skey); 261599ebb4caSwyllys } 261699ebb4caSwyllys 261799ebb4caSwyllys if (cert_stack != NULL) { 261899ebb4caSwyllys sk_X509_free(cert_stack); 261999ebb4caSwyllys } 262099ebb4caSwyllys 262199ebb4caSwyllys return (ret); 262299ebb4caSwyllys } 262399ebb4caSwyllys 262499ebb4caSwyllys 262599ebb4caSwyllys 262699ebb4caSwyllys KMF_RETURN 262799ebb4caSwyllys OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle, 262830a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 262999ebb4caSwyllys { 263099ebb4caSwyllys KMF_RETURN ret = KMF_OK; 263199ebb4caSwyllys BIO *derbio = NULL; 263299ebb4caSwyllys OCSP_RESPONSE *resp = NULL; 263399ebb4caSwyllys OCSP_BASICRESP *bs = NULL; 263499ebb4caSwyllys OCSP_CERTID *id = NULL; 263599ebb4caSwyllys OCSP_SINGLERESP *single = NULL; 263699ebb4caSwyllys ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; 263799ebb4caSwyllys int index, status, reason; 263830a5e8faSwyllys KMF_DATA *issuer_cert; 263930a5e8faSwyllys KMF_DATA *user_cert; 264030a5e8faSwyllys KMF_DATA *signer_cert; 264130a5e8faSwyllys KMF_DATA *response; 264230a5e8faSwyllys int *response_reason, *response_status, *cert_status; 264330a5e8faSwyllys boolean_t ignore_response_sign = B_FALSE; /* default is FALSE */ 264430a5e8faSwyllys uint32_t response_lifetime; 264599ebb4caSwyllys 264630a5e8faSwyllys issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR, 264730a5e8faSwyllys attrlist, numattr); 264830a5e8faSwyllys if (issuer_cert == NULL) 264999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 265099ebb4caSwyllys 265130a5e8faSwyllys user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR, 265230a5e8faSwyllys attrlist, numattr); 265330a5e8faSwyllys if (user_cert == NULL) 265499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 265530a5e8faSwyllys 265630a5e8faSwyllys response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR, 265730a5e8faSwyllys attrlist, numattr); 265830a5e8faSwyllys if (response == NULL) 265930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 266030a5e8faSwyllys 266130a5e8faSwyllys response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR, 266230a5e8faSwyllys attrlist, numattr); 266330a5e8faSwyllys if (response_status == NULL) 266430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 266530a5e8faSwyllys 266630a5e8faSwyllys response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR, 266730a5e8faSwyllys attrlist, numattr); 266830a5e8faSwyllys if (response_reason == NULL) 266930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 267030a5e8faSwyllys 267130a5e8faSwyllys cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR, 267230a5e8faSwyllys attrlist, numattr); 267330a5e8faSwyllys if (cert_status == NULL) 267430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 267599ebb4caSwyllys 267699ebb4caSwyllys /* Read in the response */ 267730a5e8faSwyllys derbio = BIO_new_mem_buf(response->Data, response->Length); 267899ebb4caSwyllys if (!derbio) { 267999ebb4caSwyllys ret = KMF_ERR_MEMORY; 268099ebb4caSwyllys return (ret); 268199ebb4caSwyllys } 268299ebb4caSwyllys 268399ebb4caSwyllys resp = d2i_OCSP_RESPONSE_bio(derbio, NULL); 268499ebb4caSwyllys if (resp == NULL) { 268599ebb4caSwyllys ret = KMF_ERR_OCSP_MALFORMED_RESPONSE; 268699ebb4caSwyllys goto end; 268799ebb4caSwyllys } 268899ebb4caSwyllys 268999ebb4caSwyllys /* Check the response status */ 269099ebb4caSwyllys status = OCSP_response_status(resp); 269130a5e8faSwyllys *response_status = status; 269299ebb4caSwyllys if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { 269399ebb4caSwyllys ret = KMF_ERR_OCSP_RESPONSE_STATUS; 269499ebb4caSwyllys goto end; 269599ebb4caSwyllys } 269699ebb4caSwyllys 269799ebb4caSwyllys #ifdef DEBUG 269899ebb4caSwyllys printf("Successfully checked the response file status.\n"); 269999ebb4caSwyllys #endif /* DEBUG */ 270099ebb4caSwyllys 270199ebb4caSwyllys /* Extract basic response */ 270299ebb4caSwyllys bs = OCSP_response_get1_basic(resp); 270399ebb4caSwyllys if (bs == NULL) { 270499ebb4caSwyllys ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE; 270599ebb4caSwyllys goto end; 270699ebb4caSwyllys } 270799ebb4caSwyllys 270899ebb4caSwyllys #ifdef DEBUG 270999ebb4caSwyllys printf("Successfully retrieved the basic response.\n"); 271099ebb4caSwyllys #endif /* DEBUG */ 271199ebb4caSwyllys 271299ebb4caSwyllys /* Check the basic response signature if required */ 271330a5e8faSwyllys ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr, 271430a5e8faSwyllys (void *)&ignore_response_sign, NULL); 271530a5e8faSwyllys if (ret != KMF_OK) 271630a5e8faSwyllys ret = KMF_OK; 271730a5e8faSwyllys 271830a5e8faSwyllys signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR, 271930a5e8faSwyllys attrlist, numattr); 272030a5e8faSwyllys 272130a5e8faSwyllys if (ignore_response_sign == B_FALSE) { 272299ebb4caSwyllys ret = check_response_signature(handle, bs, 272330a5e8faSwyllys signer_cert, issuer_cert); 272499ebb4caSwyllys if (ret != KMF_OK) 272599ebb4caSwyllys goto end; 272699ebb4caSwyllys } 272799ebb4caSwyllys 272899ebb4caSwyllys #ifdef DEBUG 272999ebb4caSwyllys printf("Successfully verified the response signature.\n"); 273099ebb4caSwyllys #endif /* DEBUG */ 273199ebb4caSwyllys 273299ebb4caSwyllys /* Create a certid for the certificate in question */ 273330a5e8faSwyllys ret = create_certid(handle, issuer_cert, user_cert, &id); 273499ebb4caSwyllys if (ret != KMF_OK) { 273599ebb4caSwyllys ret = KMF_ERR_OCSP_CERTID; 273699ebb4caSwyllys goto end; 273799ebb4caSwyllys } 273899ebb4caSwyllys 273999ebb4caSwyllys #ifdef DEBUG 274099ebb4caSwyllys printf("successfully created a certid for the cert.\n"); 274199ebb4caSwyllys #endif /* DEBUG */ 274299ebb4caSwyllys 274399ebb4caSwyllys /* Find the index of the single response for the certid */ 274499ebb4caSwyllys index = OCSP_resp_find(bs, id, -1); 274599ebb4caSwyllys if (index < 0) { 274699ebb4caSwyllys /* cound not find this certificate in the response */ 274799ebb4caSwyllys ret = KMF_ERR_OCSP_UNKNOWN_CERT; 274899ebb4caSwyllys goto end; 274999ebb4caSwyllys } 275099ebb4caSwyllys 275199ebb4caSwyllys #ifdef DEBUG 275299ebb4caSwyllys printf("Successfully found the single response index for the cert.\n"); 275399ebb4caSwyllys #endif /* DEBUG */ 275499ebb4caSwyllys 275599ebb4caSwyllys /* Retrieve the single response and get the cert status */ 275699ebb4caSwyllys single = OCSP_resp_get0(bs, index); 275799ebb4caSwyllys status = OCSP_single_get0_status(single, &reason, &rev, &thisupd, 275899ebb4caSwyllys &nextupd); 275999ebb4caSwyllys if (status == V_OCSP_CERTSTATUS_GOOD) { 276030a5e8faSwyllys *cert_status = OCSP_GOOD; 276199ebb4caSwyllys } else if (status == V_OCSP_CERTSTATUS_UNKNOWN) { 276230a5e8faSwyllys *cert_status = OCSP_UNKNOWN; 276399ebb4caSwyllys } else { /* revoked */ 276430a5e8faSwyllys *cert_status = OCSP_REVOKED; 276530a5e8faSwyllys *response_reason = reason; 276699ebb4caSwyllys } 276799ebb4caSwyllys ret = KMF_OK; 276899ebb4caSwyllys 276930a5e8faSwyllys /* resp. time is optional, so we don't care about the return code. */ 277030a5e8faSwyllys (void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr, 277130a5e8faSwyllys (void *)&response_lifetime, NULL); 277230a5e8faSwyllys 277399ebb4caSwyllys if (!OCSP_check_validity(thisupd, nextupd, 300, 277430a5e8faSwyllys response_lifetime)) { 277599ebb4caSwyllys ret = KMF_ERR_OCSP_STATUS_TIME_INVALID; 277699ebb4caSwyllys goto end; 277799ebb4caSwyllys } 277899ebb4caSwyllys 277999ebb4caSwyllys #ifdef DEBUG 278099ebb4caSwyllys printf("Successfully verify the time.\n"); 278199ebb4caSwyllys #endif /* DEBUG */ 278299ebb4caSwyllys 278399ebb4caSwyllys end: 278499ebb4caSwyllys if (derbio != NULL) 278599ebb4caSwyllys (void) BIO_free(derbio); 278699ebb4caSwyllys 278799ebb4caSwyllys if (resp != NULL) 278899ebb4caSwyllys OCSP_RESPONSE_free(resp); 278999ebb4caSwyllys 279099ebb4caSwyllys if (bs != NULL) 279199ebb4caSwyllys OCSP_BASICRESP_free(bs); 279299ebb4caSwyllys 279399ebb4caSwyllys if (id != NULL) 279499ebb4caSwyllys OCSP_CERTID_free(id); 279599ebb4caSwyllys 279699ebb4caSwyllys return (ret); 279799ebb4caSwyllys } 279899ebb4caSwyllys 279999ebb4caSwyllys static KMF_RETURN 280099ebb4caSwyllys fetch_key(KMF_HANDLE_T handle, char *path, 280199ebb4caSwyllys KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key) 280299ebb4caSwyllys { 280399ebb4caSwyllys KMF_RETURN rv = KMF_OK; 280430a5e8faSwyllys EVP_PKEY *pkey = NULL; 280599ebb4caSwyllys KMF_RAW_SYM_KEY *rkey = NULL; 280699ebb4caSwyllys 280799ebb4caSwyllys if (keyclass == KMF_ASYM_PRI || 280899ebb4caSwyllys keyclass == KMF_ASYM_PUB) { 280999ebb4caSwyllys pkey = openssl_load_key(handle, path); 281099ebb4caSwyllys if (pkey == NULL) { 281199ebb4caSwyllys return (KMF_ERR_KEY_NOT_FOUND); 281299ebb4caSwyllys } 281399ebb4caSwyllys if (key != NULL) { 281499ebb4caSwyllys if (pkey->type == EVP_PKEY_RSA) 281599ebb4caSwyllys key->keyalg = KMF_RSA; 281699ebb4caSwyllys else if (pkey->type == EVP_PKEY_DSA) 281799ebb4caSwyllys key->keyalg = KMF_DSA; 281899ebb4caSwyllys 281999ebb4caSwyllys key->kstype = KMF_KEYSTORE_OPENSSL; 282099ebb4caSwyllys key->keyclass = keyclass; 282199ebb4caSwyllys key->keyp = (void *)pkey; 282299ebb4caSwyllys key->israw = FALSE; 28235b3e1433Swyllys if (path != NULL && 28245b3e1433Swyllys ((key->keylabel = strdup(path)) == NULL)) { 28255b3e1433Swyllys EVP_PKEY_free(pkey); 28265b3e1433Swyllys return (KMF_ERR_MEMORY); 28275b3e1433Swyllys } 282899ebb4caSwyllys } else { 282999ebb4caSwyllys EVP_PKEY_free(pkey); 283099ebb4caSwyllys pkey = NULL; 283199ebb4caSwyllys } 283299ebb4caSwyllys } else if (keyclass == KMF_SYMMETRIC) { 283399ebb4caSwyllys KMF_ENCODE_FORMAT fmt; 283499ebb4caSwyllys /* 283599ebb4caSwyllys * If the file is a recognized format, 283699ebb4caSwyllys * then it is NOT a symmetric key. 283799ebb4caSwyllys */ 283830a5e8faSwyllys rv = kmf_get_file_format(path, &fmt); 283999ebb4caSwyllys if (rv == KMF_OK || fmt != 0) { 284099ebb4caSwyllys return (KMF_ERR_KEY_NOT_FOUND); 284199ebb4caSwyllys } else if (rv == KMF_ERR_ENCODING) { 284299ebb4caSwyllys /* 284399ebb4caSwyllys * If we don't know the encoding, 284499ebb4caSwyllys * it is probably a symmetric key. 284599ebb4caSwyllys */ 284699ebb4caSwyllys rv = KMF_OK; 284730a5e8faSwyllys } else if (rv == KMF_ERR_OPEN_FILE) { 284830a5e8faSwyllys return (KMF_ERR_KEY_NOT_FOUND); 284999ebb4caSwyllys } 285099ebb4caSwyllys 285199ebb4caSwyllys if (key != NULL) { 285299ebb4caSwyllys KMF_DATA keyvalue; 285399ebb4caSwyllys rkey = malloc(sizeof (KMF_RAW_SYM_KEY)); 285499ebb4caSwyllys if (rkey == NULL) { 285599ebb4caSwyllys rv = KMF_ERR_MEMORY; 285699ebb4caSwyllys goto out; 285799ebb4caSwyllys } 285899ebb4caSwyllys 285999ebb4caSwyllys (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 286030a5e8faSwyllys rv = kmf_read_input_file(handle, path, &keyvalue); 286199ebb4caSwyllys if (rv != KMF_OK) 286299ebb4caSwyllys goto out; 286399ebb4caSwyllys 286499ebb4caSwyllys rkey->keydata.len = keyvalue.Length; 286599ebb4caSwyllys rkey->keydata.val = keyvalue.Data; 286699ebb4caSwyllys 286799ebb4caSwyllys key->kstype = KMF_KEYSTORE_OPENSSL; 286899ebb4caSwyllys key->keyclass = keyclass; 286999ebb4caSwyllys key->israw = TRUE; 287099ebb4caSwyllys key->keyp = (void *)rkey; 28715b3e1433Swyllys if (path != NULL && 28725b3e1433Swyllys ((key->keylabel = strdup(path)) == NULL)) { 28735b3e1433Swyllys rv = KMF_ERR_MEMORY; 28745b3e1433Swyllys } 287599ebb4caSwyllys } 287699ebb4caSwyllys } 287799ebb4caSwyllys out: 287899ebb4caSwyllys if (rv != KMF_OK) { 287999ebb4caSwyllys if (rkey != NULL) { 288030a5e8faSwyllys kmf_free_raw_sym_key(rkey); 288199ebb4caSwyllys } 288299ebb4caSwyllys if (pkey != NULL) 288399ebb4caSwyllys EVP_PKEY_free(pkey); 288499ebb4caSwyllys 288599ebb4caSwyllys if (key != NULL) { 288699ebb4caSwyllys key->keyalg = KMF_KEYALG_NONE; 288799ebb4caSwyllys key->keyclass = KMF_KEYCLASS_NONE; 288899ebb4caSwyllys key->keyp = NULL; 288999ebb4caSwyllys } 289099ebb4caSwyllys } 289199ebb4caSwyllys 289299ebb4caSwyllys return (rv); 289399ebb4caSwyllys } 289499ebb4caSwyllys 289599ebb4caSwyllys KMF_RETURN 289630a5e8faSwyllys OpenSSL_FindKey(KMF_HANDLE_T handle, 289730a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 289899ebb4caSwyllys { 289999ebb4caSwyllys KMF_RETURN rv = KMF_OK; 290099ebb4caSwyllys char *fullpath = NULL; 2901f482c776Swyllys uint32_t maxkeys; 290230a5e8faSwyllys KMF_KEY_HANDLE *key; 290330a5e8faSwyllys uint32_t *numkeys; 290430a5e8faSwyllys KMF_KEY_CLASS keyclass; 290530a5e8faSwyllys KMF_RAW_KEY_DATA *rawkey; 290630a5e8faSwyllys char *dirpath; 290730a5e8faSwyllys char *keyfile; 290899ebb4caSwyllys 290930a5e8faSwyllys if (handle == NULL) 291099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 291199ebb4caSwyllys 291230a5e8faSwyllys numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr); 291330a5e8faSwyllys if (numkeys == NULL) 291430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 291530a5e8faSwyllys 291630a5e8faSwyllys rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr, 291730a5e8faSwyllys (void *)&keyclass, NULL); 291830a5e8faSwyllys if (rv != KMF_OK) 291930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 292030a5e8faSwyllys 292130a5e8faSwyllys if (keyclass != KMF_ASYM_PUB && 292230a5e8faSwyllys keyclass != KMF_ASYM_PRI && 292330a5e8faSwyllys keyclass != KMF_SYMMETRIC) 292499ebb4caSwyllys return (KMF_ERR_BAD_KEY_CLASS); 292599ebb4caSwyllys 292630a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 292730a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 292830a5e8faSwyllys 292930a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 293099ebb4caSwyllys 293199ebb4caSwyllys if (fullpath == NULL) 293299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 293399ebb4caSwyllys 2934f482c776Swyllys maxkeys = *numkeys; 2935f482c776Swyllys if (maxkeys == 0) 2936f482c776Swyllys maxkeys = 0xFFFFFFFF; 293799ebb4caSwyllys *numkeys = 0; 293899ebb4caSwyllys 293930a5e8faSwyllys key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 294030a5e8faSwyllys /* it is okay to have "keys" contains NULL */ 294130a5e8faSwyllys 294230a5e8faSwyllys /* 294330a5e8faSwyllys * The caller may want a list of the raw key data as well. 294430a5e8faSwyllys * Useful for importing keys from a file into other keystores. 294530a5e8faSwyllys */ 294630a5e8faSwyllys rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr); 294730a5e8faSwyllys 294899ebb4caSwyllys if (isdir(fullpath)) { 294999ebb4caSwyllys DIR *dirp; 295099ebb4caSwyllys struct dirent *dp; 295199ebb4caSwyllys int n = 0; 295299ebb4caSwyllys 295399ebb4caSwyllys /* open all files in the directory and attempt to read them */ 295499ebb4caSwyllys if ((dirp = opendir(fullpath)) == NULL) { 295599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 295699ebb4caSwyllys } 295799ebb4caSwyllys rewinddir(dirp); 2958f482c776Swyllys while ((dp = readdir(dirp)) != NULL && n < maxkeys) { 295999ebb4caSwyllys if (strcmp(dp->d_name, ".") && 296099ebb4caSwyllys strcmp(dp->d_name, "..")) { 296199ebb4caSwyllys char *fname; 296299ebb4caSwyllys 296399ebb4caSwyllys fname = get_fullpath(fullpath, 296499ebb4caSwyllys (char *)&dp->d_name); 296599ebb4caSwyllys 296699ebb4caSwyllys rv = fetch_key(handle, fname, 296730a5e8faSwyllys keyclass, key ? &key[n] : NULL); 296899ebb4caSwyllys 296930a5e8faSwyllys if (rv == KMF_OK) { 297030a5e8faSwyllys if (key != NULL && rawkey != NULL) 297130a5e8faSwyllys rv = convertToRawKey( 297230a5e8faSwyllys key[n].keyp, &rawkey[n]); 297399ebb4caSwyllys n++; 297430a5e8faSwyllys } 297599ebb4caSwyllys 297699ebb4caSwyllys if (rv != KMF_OK || key == NULL) 297799ebb4caSwyllys free(fname); 297899ebb4caSwyllys } 297999ebb4caSwyllys } 298099ebb4caSwyllys (void) closedir(dirp); 298199ebb4caSwyllys free(fullpath); 298299ebb4caSwyllys (*numkeys) = n; 298399ebb4caSwyllys } else { 298430a5e8faSwyllys rv = fetch_key(handle, fullpath, keyclass, key); 298599ebb4caSwyllys if (rv == KMF_OK) 298699ebb4caSwyllys (*numkeys) = 1; 298799ebb4caSwyllys 298899ebb4caSwyllys if (rv != KMF_OK || key == NULL) 298999ebb4caSwyllys free(fullpath); 299030a5e8faSwyllys 299130a5e8faSwyllys if (rv == KMF_OK && key != NULL && rawkey != NULL) { 299230a5e8faSwyllys rv = convertToRawKey(key->keyp, rawkey); 299330a5e8faSwyllys } 299499ebb4caSwyllys } 299599ebb4caSwyllys 2996f482c776Swyllys if (rv == KMF_OK && (*numkeys) == 0) 299799ebb4caSwyllys rv = KMF_ERR_KEY_NOT_FOUND; 299873cc0e02Swyllys else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0) 299973cc0e02Swyllys rv = KMF_OK; 300099ebb4caSwyllys 300199ebb4caSwyllys return (rv); 300299ebb4caSwyllys } 300399ebb4caSwyllys 300499ebb4caSwyllys #define HANDLE_PK12_ERROR { \ 300599ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); \ 300699ebb4caSwyllys rv = KMF_ERR_ENCODING; \ 300799ebb4caSwyllys goto out; \ 300899ebb4caSwyllys } 300999ebb4caSwyllys 30105b3e1433Swyllys static int 30115b3e1433Swyllys add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert) 301299ebb4caSwyllys { 30135b3e1433Swyllys if (xcert != NULL && xcert->aux != NULL && 30145b3e1433Swyllys xcert->aux->alias != NULL) { 30155b3e1433Swyllys if (PKCS12_add_friendlyname_asc(bag, 30165b3e1433Swyllys (const char *)xcert->aux->alias->data, 30175b3e1433Swyllys xcert->aux->alias->length) == 0) 30185b3e1433Swyllys return (0); 30195b3e1433Swyllys } 30205b3e1433Swyllys return (1); 30215b3e1433Swyllys } 30225b3e1433Swyllys 30235b3e1433Swyllys static PKCS7 * 30245b3e1433Swyllys add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred, 30255b3e1433Swyllys uchar_t *keyid, unsigned int keyidlen) 30265b3e1433Swyllys { 302799ebb4caSwyllys PKCS12_SAFEBAG *bag = NULL; 302899ebb4caSwyllys PKCS7 *cert_authsafe = NULL; 30295b3e1433Swyllys STACK_OF(PKCS12_SAFEBAG) *bag_stack; 303099ebb4caSwyllys 303199ebb4caSwyllys bag_stack = sk_PKCS12_SAFEBAG_new_null(); 303299ebb4caSwyllys if (bag_stack == NULL) 30335b3e1433Swyllys return (NULL); 303499ebb4caSwyllys 303599ebb4caSwyllys /* Convert cert from X509 struct to PKCS#12 bag */ 303699ebb4caSwyllys bag = PKCS12_x5092certbag(sslcert); 303799ebb4caSwyllys if (bag == NULL) { 30385b3e1433Swyllys goto out; 303999ebb4caSwyllys } 304099ebb4caSwyllys 304199ebb4caSwyllys /* Add the key id to the certificate bag. */ 30425b3e1433Swyllys if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) { 30435b3e1433Swyllys goto out; 304499ebb4caSwyllys } 304599ebb4caSwyllys 30465b3e1433Swyllys if (!add_alias_to_bag(bag, sslcert)) 30475b3e1433Swyllys goto out; 30485b3e1433Swyllys 304999ebb4caSwyllys /* Pile it on the bag_stack. */ 305099ebb4caSwyllys if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) { 30515b3e1433Swyllys goto out; 305299ebb4caSwyllys } 305399ebb4caSwyllys /* Turn bag_stack of certs into encrypted authsafe. */ 305499ebb4caSwyllys cert_authsafe = PKCS12_pack_p7encdata( 305599ebb4caSwyllys NID_pbe_WithSHA1And40BitRC2_CBC, 305634acef67Swyllys cred->cred, cred->credlen, NULL, 0, 305734acef67Swyllys PKCS12_DEFAULT_ITER, bag_stack); 305899ebb4caSwyllys 30595b3e1433Swyllys out: 30605b3e1433Swyllys if (bag_stack != NULL) 306199ebb4caSwyllys sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); 306299ebb4caSwyllys 30635b3e1433Swyllys return (cert_authsafe); 306499ebb4caSwyllys } 30655b3e1433Swyllys 30665b3e1433Swyllys static PKCS7 * 30675b3e1433Swyllys add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred, 30685b3e1433Swyllys uchar_t *keyid, unsigned int keyidlen, 30695b3e1433Swyllys char *label, int label_len) 30705b3e1433Swyllys { 30715b3e1433Swyllys PKCS8_PRIV_KEY_INFO *p8 = NULL; 30725b3e1433Swyllys STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL; 30735b3e1433Swyllys PKCS12_SAFEBAG *bag = NULL; 30745b3e1433Swyllys PKCS7 *key_authsafe = NULL; 30755b3e1433Swyllys 307699ebb4caSwyllys p8 = EVP_PKEY2PKCS8(pkey); 307799ebb4caSwyllys if (p8 == NULL) { 30785b3e1433Swyllys return (NULL); 307999ebb4caSwyllys } 308099ebb4caSwyllys /* Put the shrouded key into a PKCS#12 bag. */ 308199ebb4caSwyllys bag = PKCS12_MAKE_SHKEYBAG( 308299ebb4caSwyllys NID_pbe_WithSHA1And3_Key_TripleDES_CBC, 308399ebb4caSwyllys cred->cred, cred->credlen, 308499ebb4caSwyllys NULL, 0, PKCS12_DEFAULT_ITER, p8); 308599ebb4caSwyllys 308699ebb4caSwyllys /* Clean up the PKCS#8 shrouded key, don't need it now. */ 308799ebb4caSwyllys PKCS8_PRIV_KEY_INFO_free(p8); 308899ebb4caSwyllys p8 = NULL; 308999ebb4caSwyllys 309099ebb4caSwyllys if (bag == NULL) { 30915b3e1433Swyllys return (NULL); 309299ebb4caSwyllys } 30935b3e1433Swyllys if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) 30945b3e1433Swyllys goto out; 30955b3e1433Swyllys if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len)) 30965b3e1433Swyllys goto out; 30975b3e1433Swyllys 309899ebb4caSwyllys /* Start a PKCS#12 safebag container for the private key. */ 309999ebb4caSwyllys bag_stack = sk_PKCS12_SAFEBAG_new_null(); 31005b3e1433Swyllys if (bag_stack == NULL) 31015b3e1433Swyllys goto out; 310299ebb4caSwyllys 310399ebb4caSwyllys /* Pile on the private key on the bag_stack. */ 31045b3e1433Swyllys if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) 31055b3e1433Swyllys goto out; 31065b3e1433Swyllys 310799ebb4caSwyllys key_authsafe = PKCS12_pack_p7data(bag_stack); 310899ebb4caSwyllys 31095b3e1433Swyllys out: 31105b3e1433Swyllys if (bag_stack != NULL) 311199ebb4caSwyllys sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); 311299ebb4caSwyllys bag_stack = NULL; 31135b3e1433Swyllys return (key_authsafe); 311499ebb4caSwyllys } 311599ebb4caSwyllys 311699ebb4caSwyllys static EVP_PKEY * 311799ebb4caSwyllys ImportRawRSAKey(KMF_RAW_RSA_KEY *key) 311899ebb4caSwyllys { 311999ebb4caSwyllys RSA *rsa = NULL; 312099ebb4caSwyllys EVP_PKEY *newkey = NULL; 312199ebb4caSwyllys 312299ebb4caSwyllys if ((rsa = RSA_new()) == NULL) 312399ebb4caSwyllys return (NULL); 312499ebb4caSwyllys 312599ebb4caSwyllys if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL) 312699ebb4caSwyllys return (NULL); 312799ebb4caSwyllys 312899ebb4caSwyllys if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) == 312999ebb4caSwyllys NULL) 313099ebb4caSwyllys return (NULL); 313199ebb4caSwyllys 313299ebb4caSwyllys if (key->priexp.val != NULL) 313399ebb4caSwyllys if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len, 313499ebb4caSwyllys rsa->d)) == NULL) 313599ebb4caSwyllys return (NULL); 313699ebb4caSwyllys 313799ebb4caSwyllys if (key->prime1.val != NULL) 313899ebb4caSwyllys if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len, 313999ebb4caSwyllys rsa->p)) == NULL) 314099ebb4caSwyllys return (NULL); 314199ebb4caSwyllys 314299ebb4caSwyllys if (key->prime2.val != NULL) 314399ebb4caSwyllys if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len, 314499ebb4caSwyllys rsa->q)) == NULL) 314599ebb4caSwyllys return (NULL); 314699ebb4caSwyllys 314799ebb4caSwyllys if (key->exp1.val != NULL) 314899ebb4caSwyllys if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len, 314999ebb4caSwyllys rsa->dmp1)) == NULL) 315099ebb4caSwyllys return (NULL); 315199ebb4caSwyllys 315299ebb4caSwyllys if (key->exp2.val != NULL) 315399ebb4caSwyllys if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len, 315499ebb4caSwyllys rsa->dmq1)) == NULL) 315599ebb4caSwyllys return (NULL); 315699ebb4caSwyllys 315799ebb4caSwyllys if (key->coef.val != NULL) 315899ebb4caSwyllys if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len, 315999ebb4caSwyllys rsa->iqmp)) == NULL) 316099ebb4caSwyllys return (NULL); 316199ebb4caSwyllys 316299ebb4caSwyllys if ((newkey = EVP_PKEY_new()) == NULL) 316399ebb4caSwyllys return (NULL); 316499ebb4caSwyllys 316599ebb4caSwyllys (void) EVP_PKEY_set1_RSA(newkey, rsa); 316699ebb4caSwyllys 316799ebb4caSwyllys /* The original key must be freed once here or it leaks memory */ 316899ebb4caSwyllys RSA_free(rsa); 316999ebb4caSwyllys 317099ebb4caSwyllys return (newkey); 317199ebb4caSwyllys } 317299ebb4caSwyllys 317399ebb4caSwyllys static EVP_PKEY * 317499ebb4caSwyllys ImportRawDSAKey(KMF_RAW_DSA_KEY *key) 317599ebb4caSwyllys { 317699ebb4caSwyllys DSA *dsa = NULL; 317799ebb4caSwyllys EVP_PKEY *newkey = NULL; 317899ebb4caSwyllys 317999ebb4caSwyllys if ((dsa = DSA_new()) == NULL) 318099ebb4caSwyllys return (NULL); 318199ebb4caSwyllys 318299ebb4caSwyllys if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len, 318399ebb4caSwyllys dsa->p)) == NULL) 318499ebb4caSwyllys return (NULL); 318599ebb4caSwyllys 318699ebb4caSwyllys if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len, 318799ebb4caSwyllys dsa->q)) == NULL) 318899ebb4caSwyllys return (NULL); 318999ebb4caSwyllys 319099ebb4caSwyllys if ((dsa->g = BN_bin2bn(key->base.val, key->base.len, 319199ebb4caSwyllys dsa->g)) == NULL) 319299ebb4caSwyllys return (NULL); 319399ebb4caSwyllys 319499ebb4caSwyllys if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len, 319599ebb4caSwyllys dsa->priv_key)) == NULL) 319699ebb4caSwyllys return (NULL); 319799ebb4caSwyllys 319830a5e8faSwyllys if (key->pubvalue.val != NULL) { 319930a5e8faSwyllys if ((dsa->pub_key = BN_bin2bn(key->pubvalue.val, 320030a5e8faSwyllys key->pubvalue.len, dsa->pub_key)) == NULL) 320130a5e8faSwyllys return (NULL); 320230a5e8faSwyllys } 320330a5e8faSwyllys 320499ebb4caSwyllys if ((newkey = EVP_PKEY_new()) == NULL) 320599ebb4caSwyllys return (NULL); 320699ebb4caSwyllys 320799ebb4caSwyllys (void) EVP_PKEY_set1_DSA(newkey, dsa); 320899ebb4caSwyllys 320999ebb4caSwyllys /* The original key must be freed once here or it leaks memory */ 321099ebb4caSwyllys DSA_free(dsa); 321199ebb4caSwyllys return (newkey); 321299ebb4caSwyllys } 321399ebb4caSwyllys 32145b3e1433Swyllys static EVP_PKEY * 32155b3e1433Swyllys raw_key_to_pkey(KMF_KEY_HANDLE *key) 32165b3e1433Swyllys { 32175b3e1433Swyllys EVP_PKEY *pkey = NULL; 32185b3e1433Swyllys KMF_RAW_KEY_DATA *rawkey; 32195b3e1433Swyllys ASN1_TYPE *attr = NULL; 32205b3e1433Swyllys KMF_RETURN ret; 32215b3e1433Swyllys 32225b3e1433Swyllys if (key == NULL || !key->israw) 32235b3e1433Swyllys return (NULL); 32245b3e1433Swyllys 32255b3e1433Swyllys rawkey = (KMF_RAW_KEY_DATA *)key->keyp; 32265b3e1433Swyllys if (rawkey->keytype == KMF_RSA) { 32275b3e1433Swyllys pkey = ImportRawRSAKey(&rawkey->rawdata.rsa); 32285b3e1433Swyllys } else if (rawkey->keytype == KMF_DSA) { 32295b3e1433Swyllys pkey = ImportRawDSAKey(&rawkey->rawdata.dsa); 3230e65e5c2dSWyllys Ingersoll } else if (rawkey->keytype == KMF_ECDSA) { 3231e65e5c2dSWyllys Ingersoll /* 3232e65e5c2dSWyllys Ingersoll * OpenSSL in Solaris does not support EC for 3233e65e5c2dSWyllys Ingersoll * legal reasons 3234e65e5c2dSWyllys Ingersoll */ 3235e65e5c2dSWyllys Ingersoll return (NULL); 32365b3e1433Swyllys } else { 32375b3e1433Swyllys /* wrong kind of key */ 32385b3e1433Swyllys return (NULL); 32395b3e1433Swyllys } 32405b3e1433Swyllys 32415b3e1433Swyllys if (rawkey->label != NULL) { 32425b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) { 32435b3e1433Swyllys EVP_PKEY_free(pkey); 32445b3e1433Swyllys return (NULL); 32455b3e1433Swyllys } 32465b3e1433Swyllys attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING); 32475b3e1433Swyllys (void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label, 32485b3e1433Swyllys strlen(rawkey->label)); 32495b3e1433Swyllys attr->type = V_ASN1_BMPSTRING; 32505b3e1433Swyllys attr->value.ptr = (char *)attr->value.bmpstring; 32515b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_friendlyName); 32525b3e1433Swyllys if (ret != KMF_OK) { 32535b3e1433Swyllys EVP_PKEY_free(pkey); 32545b3e1433Swyllys ASN1_TYPE_free(attr); 32555b3e1433Swyllys return (NULL); 32565b3e1433Swyllys } 32575b3e1433Swyllys } 32585b3e1433Swyllys if (rawkey->id.Data != NULL) { 32595b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) { 32605b3e1433Swyllys EVP_PKEY_free(pkey); 32615b3e1433Swyllys return (NULL); 32625b3e1433Swyllys } 32635b3e1433Swyllys attr->value.octet_string = 32645b3e1433Swyllys ASN1_STRING_type_new(V_ASN1_OCTET_STRING); 32655b3e1433Swyllys attr->type = V_ASN1_OCTET_STRING; 32665b3e1433Swyllys (void) ASN1_STRING_set(attr->value.octet_string, 32675b3e1433Swyllys rawkey->id.Data, rawkey->id.Length); 32685b3e1433Swyllys attr->value.ptr = (char *)attr->value.octet_string; 32695b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_localKeyID); 32705b3e1433Swyllys if (ret != KMF_OK) { 32715b3e1433Swyllys EVP_PKEY_free(pkey); 32725b3e1433Swyllys ASN1_TYPE_free(attr); 32735b3e1433Swyllys return (NULL); 32745b3e1433Swyllys } 32755b3e1433Swyllys } 32765b3e1433Swyllys return (pkey); 32775b3e1433Swyllys } 32785b3e1433Swyllys 32795b3e1433Swyllys /* 32805b3e1433Swyllys * Search a list of private keys to find one that goes with the certificate. 32815b3e1433Swyllys */ 32825b3e1433Swyllys static EVP_PKEY * 32835b3e1433Swyllys find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist) 32845b3e1433Swyllys { 32855b3e1433Swyllys int i; 32865b3e1433Swyllys EVP_PKEY *pkey = NULL; 32875b3e1433Swyllys 32885b3e1433Swyllys if (numkeys == 0 || keylist == NULL || xcert == NULL) 32895b3e1433Swyllys return (NULL); 32905b3e1433Swyllys for (i = 0; i < numkeys; i++) { 32915b3e1433Swyllys if (keylist[i].israw) 32925b3e1433Swyllys pkey = raw_key_to_pkey(&keylist[i]); 32935b3e1433Swyllys else 32945b3e1433Swyllys pkey = (EVP_PKEY *)keylist[i].keyp; 32955b3e1433Swyllys if (pkey != NULL) { 32965b3e1433Swyllys if (X509_check_private_key(xcert, pkey)) { 32975b3e1433Swyllys return (pkey); 32985b3e1433Swyllys } else { 32995b3e1433Swyllys EVP_PKEY_free(pkey); 33005b3e1433Swyllys pkey = NULL; 33015b3e1433Swyllys } 33025b3e1433Swyllys } 33035b3e1433Swyllys } 33045b3e1433Swyllys return (pkey); 33055b3e1433Swyllys } 33065b3e1433Swyllys 330799ebb4caSwyllys static KMF_RETURN 33085b3e1433Swyllys local_export_pk12(KMF_HANDLE_T handle, 330999ebb4caSwyllys KMF_CREDENTIAL *cred, 331099ebb4caSwyllys int numcerts, KMF_X509_DER_CERT *certlist, 331199ebb4caSwyllys int numkeys, KMF_KEY_HANDLE *keylist, 331299ebb4caSwyllys char *filename) 331399ebb4caSwyllys { 331499ebb4caSwyllys KMF_RETURN rv = KMF_OK; 331599ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 331699ebb4caSwyllys BIO *bio = NULL; 33175b3e1433Swyllys PKCS7 *cert_authsafe = NULL; 33185b3e1433Swyllys PKCS7 *key_authsafe = NULL; 33195b3e1433Swyllys STACK_OF(PKCS7) *authsafe_stack = NULL; 33205b3e1433Swyllys PKCS12 *p12_elem = NULL; 332199ebb4caSwyllys int i; 332299ebb4caSwyllys 33235b3e1433Swyllys if (numcerts == 0 && numkeys == 0) 33245b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 33255b3e1433Swyllys 332699ebb4caSwyllys /* 332799ebb4caSwyllys * Open the output file. 332899ebb4caSwyllys */ 332999ebb4caSwyllys if ((bio = BIO_new_file(filename, "wb")) == NULL) { 333099ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 333199ebb4caSwyllys rv = KMF_ERR_OPEN_FILE; 333299ebb4caSwyllys goto cleanup; 333399ebb4caSwyllys } 333499ebb4caSwyllys 33355b3e1433Swyllys /* Start a PKCS#7 stack. */ 33365b3e1433Swyllys authsafe_stack = sk_PKCS7_new_null(); 33375b3e1433Swyllys if (authsafe_stack == NULL) { 33385b3e1433Swyllys rv = KMF_ERR_MEMORY; 33395b3e1433Swyllys goto cleanup; 33405b3e1433Swyllys } 33415b3e1433Swyllys if (numcerts > 0) { 334299ebb4caSwyllys for (i = 0; rv == KMF_OK && i < numcerts; i++) { 334399ebb4caSwyllys const uchar_t *p = certlist[i].certificate.Data; 334499ebb4caSwyllys long len = certlist[i].certificate.Length; 33455b3e1433Swyllys X509 *xcert = NULL; 33465b3e1433Swyllys EVP_PKEY *pkey = NULL; 33475b3e1433Swyllys unsigned char keyid[EVP_MAX_MD_SIZE]; 33485b3e1433Swyllys unsigned int keyidlen = 0; 334999ebb4caSwyllys 335099ebb4caSwyllys xcert = d2i_X509(NULL, &p, len); 335199ebb4caSwyllys if (xcert == NULL) { 335299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 335399ebb4caSwyllys rv = KMF_ERR_ENCODING; 335499ebb4caSwyllys } 33555b3e1433Swyllys if (certlist[i].kmf_private.label != NULL) { 33565b3e1433Swyllys /* Set alias attribute */ 33575b3e1433Swyllys (void) X509_alias_set1(xcert, 33585b3e1433Swyllys (uchar_t *)certlist[i].kmf_private.label, 33595b3e1433Swyllys strlen(certlist[i].kmf_private.label)); 33605b3e1433Swyllys } 33615b3e1433Swyllys /* Check if there is a key corresponding to this cert */ 33625b3e1433Swyllys pkey = find_matching_key(xcert, numkeys, keylist); 33635b3e1433Swyllys 33645b3e1433Swyllys /* 33655b3e1433Swyllys * If key is found, get fingerprint and create a 33665b3e1433Swyllys * safebag. 33675b3e1433Swyllys */ 33685b3e1433Swyllys if (pkey != NULL) { 33695b3e1433Swyllys (void) X509_digest(xcert, EVP_sha1(), 33705b3e1433Swyllys keyid, &keyidlen); 33715b3e1433Swyllys key_authsafe = add_key_to_safe(pkey, cred, 33725b3e1433Swyllys keyid, keyidlen, 33735b3e1433Swyllys certlist[i].kmf_private.label, 33745b3e1433Swyllys (certlist[i].kmf_private.label ? 33755b3e1433Swyllys strlen(certlist[i].kmf_private.label) : 0)); 33765b3e1433Swyllys 33775b3e1433Swyllys if (key_authsafe == NULL) { 33785b3e1433Swyllys X509_free(xcert); 33795b3e1433Swyllys EVP_PKEY_free(pkey); 33805b3e1433Swyllys goto cleanup; 33815b3e1433Swyllys } 33825b3e1433Swyllys /* Put the key safe into the Auth Safe */ 33835b3e1433Swyllys if (!sk_PKCS7_push(authsafe_stack, 33845b3e1433Swyllys key_authsafe)) { 33855b3e1433Swyllys X509_free(xcert); 33865b3e1433Swyllys EVP_PKEY_free(pkey); 33875b3e1433Swyllys goto cleanup; 33885b3e1433Swyllys } 33895b3e1433Swyllys } 33905b3e1433Swyllys 33915b3e1433Swyllys /* create a certificate safebag */ 33925b3e1433Swyllys cert_authsafe = add_cert_to_safe(xcert, cred, keyid, 33935b3e1433Swyllys keyidlen); 33945b3e1433Swyllys if (cert_authsafe == NULL) { 33955b3e1433Swyllys X509_free(xcert); 33965b3e1433Swyllys EVP_PKEY_free(pkey); 33975b3e1433Swyllys goto cleanup; 33985b3e1433Swyllys } 33995b3e1433Swyllys if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) { 34005b3e1433Swyllys X509_free(xcert); 34015b3e1433Swyllys EVP_PKEY_free(pkey); 34025b3e1433Swyllys goto cleanup; 34035b3e1433Swyllys } 34045b3e1433Swyllys 340599ebb4caSwyllys X509_free(xcert); 340699ebb4caSwyllys if (pkey) 340799ebb4caSwyllys EVP_PKEY_free(pkey); 340899ebb4caSwyllys } 34095b3e1433Swyllys } else if (numcerts == 0 && numkeys > 0) { 34105b3e1433Swyllys /* 34115b3e1433Swyllys * If only adding keys to the file. 34125b3e1433Swyllys */ 34135b3e1433Swyllys for (i = 0; i < numkeys; i++) { 34145b3e1433Swyllys EVP_PKEY *pkey = NULL; 34155b3e1433Swyllys 34165b3e1433Swyllys if (keylist[i].israw) 34175b3e1433Swyllys pkey = raw_key_to_pkey(&keylist[i]); 34185b3e1433Swyllys else 34195b3e1433Swyllys pkey = (EVP_PKEY *)keylist[i].keyp; 34205b3e1433Swyllys 34215b3e1433Swyllys if (pkey == NULL) 34225b3e1433Swyllys continue; 34235b3e1433Swyllys 34245b3e1433Swyllys key_authsafe = add_key_to_safe(pkey, cred, 34255b3e1433Swyllys NULL, 0, NULL, 0); 34265b3e1433Swyllys 34275b3e1433Swyllys if (key_authsafe == NULL) { 34285b3e1433Swyllys EVP_PKEY_free(pkey); 34295b3e1433Swyllys goto cleanup; 34305b3e1433Swyllys } 34315b3e1433Swyllys if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) { 34325b3e1433Swyllys EVP_PKEY_free(pkey); 34335b3e1433Swyllys goto cleanup; 34345b3e1433Swyllys } 34355b3e1433Swyllys } 34365b3e1433Swyllys } 34375b3e1433Swyllys p12_elem = PKCS12_init(NID_pkcs7_data); 34385b3e1433Swyllys if (p12_elem == NULL) { 34395b3e1433Swyllys goto cleanup; 344099ebb4caSwyllys } 344199ebb4caSwyllys 34425b3e1433Swyllys /* Put the PKCS#7 stack into the PKCS#12 element. */ 34435b3e1433Swyllys if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) { 34445b3e1433Swyllys goto cleanup; 34455b3e1433Swyllys } 34465b3e1433Swyllys 34475b3e1433Swyllys /* Set the integrity MAC on the PKCS#12 element. */ 34485b3e1433Swyllys if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen, 34495b3e1433Swyllys NULL, 0, PKCS12_DEFAULT_ITER, NULL)) { 34505b3e1433Swyllys goto cleanup; 34515b3e1433Swyllys } 34525b3e1433Swyllys 34535b3e1433Swyllys /* Write the PKCS#12 element to the export file. */ 34545b3e1433Swyllys if (!i2d_PKCS12_bio(bio, p12_elem)) { 34555b3e1433Swyllys goto cleanup; 34565b3e1433Swyllys } 34575b3e1433Swyllys PKCS12_free(p12_elem); 34585b3e1433Swyllys 345999ebb4caSwyllys cleanup: 34605b3e1433Swyllys /* Clear away the PKCS#7 stack, we're done with it. */ 34615b3e1433Swyllys if (authsafe_stack) 34625b3e1433Swyllys sk_PKCS7_pop_free(authsafe_stack, PKCS7_free); 346399ebb4caSwyllys 346499ebb4caSwyllys if (bio != NULL) 346599ebb4caSwyllys (void) BIO_free_all(bio); 346699ebb4caSwyllys 346799ebb4caSwyllys return (rv); 346899ebb4caSwyllys } 346999ebb4caSwyllys 347099ebb4caSwyllys KMF_RETURN 347130a5e8faSwyllys openssl_build_pk12(KMF_HANDLE_T handle, int numcerts, 347230a5e8faSwyllys KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist, 347330a5e8faSwyllys KMF_CREDENTIAL *p12cred, char *filename) 347430a5e8faSwyllys { 347530a5e8faSwyllys KMF_RETURN rv; 347630a5e8faSwyllys 347730a5e8faSwyllys if (certlist == NULL && keylist == NULL) 347830a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 347930a5e8faSwyllys 34805b3e1433Swyllys rv = local_export_pk12(handle, p12cred, numcerts, certlist, 348130a5e8faSwyllys numkeys, keylist, filename); 348230a5e8faSwyllys 348330a5e8faSwyllys return (rv); 348430a5e8faSwyllys } 348530a5e8faSwyllys 348630a5e8faSwyllys KMF_RETURN 348730a5e8faSwyllys OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 348899ebb4caSwyllys { 348999ebb4caSwyllys KMF_RETURN rv; 349099ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 349199ebb4caSwyllys char *fullpath = NULL; 349230a5e8faSwyllys char *dirpath = NULL; 349330a5e8faSwyllys char *certfile = NULL; 349430a5e8faSwyllys char *keyfile = NULL; 349530a5e8faSwyllys char *filename = NULL; 349630a5e8faSwyllys KMF_CREDENTIAL *p12cred = NULL; 34975b3e1433Swyllys KMF_X509_DER_CERT certdata; 34985b3e1433Swyllys KMF_KEY_HANDLE key; 34995b3e1433Swyllys int gotkey = 0; 35005b3e1433Swyllys int gotcert = 0; 350130a5e8faSwyllys 350230a5e8faSwyllys if (handle == NULL) 350330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 350499ebb4caSwyllys 350599ebb4caSwyllys /* 350699ebb4caSwyllys * First, find the certificate. 350799ebb4caSwyllys */ 350830a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 350930a5e8faSwyllys certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr); 351030a5e8faSwyllys if (certfile != NULL) { 351130a5e8faSwyllys fullpath = get_fullpath(dirpath, certfile); 351299ebb4caSwyllys if (fullpath == NULL) 351399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 351499ebb4caSwyllys 351599ebb4caSwyllys if (isdir(fullpath)) { 351699ebb4caSwyllys free(fullpath); 351799ebb4caSwyllys return (KMF_ERR_AMBIGUOUS_PATHNAME); 351899ebb4caSwyllys } 351999ebb4caSwyllys 35205b3e1433Swyllys (void) memset(&certdata, 0, sizeof (certdata)); 35215b3e1433Swyllys rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL, 35225b3e1433Swyllys fullpath, &certdata.certificate); 352399ebb4caSwyllys if (rv != KMF_OK) 352499ebb4caSwyllys goto end; 352530a5e8faSwyllys 35265b3e1433Swyllys gotcert++; 35275b3e1433Swyllys certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL; 352830a5e8faSwyllys free(fullpath); 352999ebb4caSwyllys } 353099ebb4caSwyllys 353199ebb4caSwyllys /* 353299ebb4caSwyllys * Now find the private key. 353399ebb4caSwyllys */ 353430a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 353530a5e8faSwyllys if (keyfile != NULL) { 353630a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 353799ebb4caSwyllys if (fullpath == NULL) 353899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 353999ebb4caSwyllys 354099ebb4caSwyllys if (isdir(fullpath)) { 354199ebb4caSwyllys free(fullpath); 354299ebb4caSwyllys return (KMF_ERR_AMBIGUOUS_PATHNAME); 354399ebb4caSwyllys } 354499ebb4caSwyllys 35455b3e1433Swyllys (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE)); 35465b3e1433Swyllys rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key); 35475b3e1433Swyllys if (rv != KMF_OK) 354899ebb4caSwyllys goto end; 35495b3e1433Swyllys gotkey++; 355099ebb4caSwyllys } 355199ebb4caSwyllys 355299ebb4caSwyllys /* 355399ebb4caSwyllys * Open the output file. 355499ebb4caSwyllys */ 355530a5e8faSwyllys filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist, 355630a5e8faSwyllys numattr); 355730a5e8faSwyllys if (filename == NULL) { 355830a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 355930a5e8faSwyllys goto end; 356030a5e8faSwyllys } 356130a5e8faSwyllys 356299ebb4caSwyllys /* Stick the key and the cert into a PKCS#12 file */ 356330a5e8faSwyllys p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr); 356430a5e8faSwyllys if (p12cred == NULL) { 356530a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 356630a5e8faSwyllys goto end; 356730a5e8faSwyllys } 356830a5e8faSwyllys 35695b3e1433Swyllys rv = local_export_pk12(handle, p12cred, 1, &certdata, 35705b3e1433Swyllys 1, &key, filename); 357199ebb4caSwyllys 357299ebb4caSwyllys end: 357399ebb4caSwyllys if (fullpath) 357499ebb4caSwyllys free(fullpath); 357599ebb4caSwyllys 35765b3e1433Swyllys if (gotcert) 35775b3e1433Swyllys kmf_free_kmf_cert(handle, &certdata); 35785b3e1433Swyllys if (gotkey) 35795b3e1433Swyllys kmf_free_kmf_key(handle, &key); 358099ebb4caSwyllys return (rv); 358199ebb4caSwyllys } 358299ebb4caSwyllys 358371593db2Swyllys /* 358471593db2Swyllys * Helper function to extract keys and certificates from 358571593db2Swyllys * a single PEM file. Typically the file should contain a 358671593db2Swyllys * private key and an associated public key wrapped in an x509 cert. 358771593db2Swyllys * However, the file may be just a list of X509 certs with no keys. 358871593db2Swyllys */ 358971593db2Swyllys static KMF_RETURN 359030a5e8faSwyllys extract_pem(KMF_HANDLE *kmfh, 359130a5e8faSwyllys char *issuer, char *subject, KMF_BIGINT *serial, 359202744e81Swyllys char *filename, CK_UTF8CHAR *pin, 359371593db2Swyllys CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs, 359471593db2Swyllys int *numcerts) 3595a2d4930dSDan OpenSolaris Anderson /* ARGSUSED6 */ 359671593db2Swyllys { 359771593db2Swyllys KMF_RETURN rv = KMF_OK; 359871593db2Swyllys FILE *fp; 359934acef67Swyllys STACK_OF(X509_INFO) *x509_info_stack = NULL; 360002744e81Swyllys int i, ncerts = 0, matchcerts = 0; 360171593db2Swyllys EVP_PKEY *pkey = NULL; 360271593db2Swyllys X509_INFO *info; 360371593db2Swyllys X509 *x; 36045b3e1433Swyllys X509_INFO **cert_infos = NULL; 360571593db2Swyllys KMF_DATA *certlist = NULL; 360671593db2Swyllys 360771593db2Swyllys if (priv_key) 360871593db2Swyllys *priv_key = NULL; 360971593db2Swyllys if (certs) 361071593db2Swyllys *certs = NULL; 361171593db2Swyllys fp = fopen(filename, "r"); 36125b3e1433Swyllys if (fp == NULL) 361371593db2Swyllys return (KMF_ERR_OPEN_FILE); 36145b3e1433Swyllys 361571593db2Swyllys x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin); 361671593db2Swyllys if (x509_info_stack == NULL) { 361771593db2Swyllys (void) fclose(fp); 361871593db2Swyllys return (KMF_ERR_ENCODING); 361971593db2Swyllys } 36205b3e1433Swyllys cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) * 36215b3e1433Swyllys sizeof (X509_INFO *)); 36225b3e1433Swyllys if (cert_infos == NULL) { 36235b3e1433Swyllys (void) fclose(fp); 36245b3e1433Swyllys rv = KMF_ERR_MEMORY; 36255b3e1433Swyllys goto err; 36265b3e1433Swyllys } 362771593db2Swyllys 36285b3e1433Swyllys for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) { 3629a2d4930dSDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */ 363034acef67Swyllys cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i); 363171593db2Swyllys ncerts++; 363271593db2Swyllys } 363371593db2Swyllys 363471593db2Swyllys if (ncerts == 0) { 363571593db2Swyllys (void) fclose(fp); 363634acef67Swyllys rv = KMF_ERR_CERT_NOT_FOUND; 363734acef67Swyllys goto err; 363871593db2Swyllys } 363971593db2Swyllys 364071593db2Swyllys if (priv_key != NULL) { 364171593db2Swyllys rewind(fp); 364271593db2Swyllys pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin); 364371593db2Swyllys } 364471593db2Swyllys (void) fclose(fp); 364571593db2Swyllys 364671593db2Swyllys x = cert_infos[ncerts - 1]->x509; 364771593db2Swyllys /* 364871593db2Swyllys * Make sure the private key matchs the last cert in the file. 364971593db2Swyllys */ 365071593db2Swyllys if (pkey != NULL && !X509_check_private_key(x, pkey)) { 365171593db2Swyllys EVP_PKEY_free(pkey); 365234acef67Swyllys rv = KMF_ERR_KEY_MISMATCH; 365334acef67Swyllys goto err; 365471593db2Swyllys } 365571593db2Swyllys 3656a2d4930dSDan OpenSolaris Anderson certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA)); 365771593db2Swyllys if (certlist == NULL) { 365871593db2Swyllys if (pkey != NULL) 365971593db2Swyllys EVP_PKEY_free(pkey); 366034acef67Swyllys rv = KMF_ERR_MEMORY; 366134acef67Swyllys goto err; 366271593db2Swyllys } 366371593db2Swyllys 366471593db2Swyllys /* 366571593db2Swyllys * Convert all of the certs to DER format. 366671593db2Swyllys */ 366702744e81Swyllys matchcerts = 0; 366871593db2Swyllys for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) { 366902744e81Swyllys boolean_t match = FALSE; 367071593db2Swyllys info = cert_infos[ncerts - 1 - i]; 367171593db2Swyllys 367230a5e8faSwyllys rv = check_cert(info->x509, issuer, subject, serial, &match); 367302744e81Swyllys if (rv != KMF_OK || match != TRUE) { 367402744e81Swyllys rv = KMF_OK; 367502744e81Swyllys continue; 367602744e81Swyllys } 367702744e81Swyllys 367802744e81Swyllys rv = ssl_cert2KMFDATA(kmfh, info->x509, 367902744e81Swyllys &certlist[matchcerts++]); 368071593db2Swyllys 368171593db2Swyllys if (rv != KMF_OK) { 3682e65e5c2dSWyllys Ingersoll int j; 3683e65e5c2dSWyllys Ingersoll for (j = 0; j < matchcerts; j++) 3684e65e5c2dSWyllys Ingersoll kmf_free_data(&certlist[j]); 368571593db2Swyllys free(certlist); 368671593db2Swyllys certlist = NULL; 368702744e81Swyllys ncerts = matchcerts = 0; 368871593db2Swyllys } 368971593db2Swyllys } 369071593db2Swyllys 369171593db2Swyllys if (numcerts != NULL) 369202744e81Swyllys *numcerts = matchcerts; 3693a2d4930dSDan OpenSolaris Anderson 3694e65e5c2dSWyllys Ingersoll if (certs != NULL) 369571593db2Swyllys *certs = certlist; 3696e65e5c2dSWyllys Ingersoll else if (certlist != NULL) { 3697e65e5c2dSWyllys Ingersoll for (i = 0; i < ncerts; i++) 3698e65e5c2dSWyllys Ingersoll kmf_free_data(&certlist[i]); 3699a2d4930dSDan OpenSolaris Anderson free(certlist); 3700a2d4930dSDan OpenSolaris Anderson certlist = NULL; 3701a2d4930dSDan OpenSolaris Anderson } 370271593db2Swyllys 370371593db2Swyllys if (priv_key == NULL && pkey != NULL) 370471593db2Swyllys EVP_PKEY_free(pkey); 370571593db2Swyllys else if (priv_key != NULL && pkey != NULL) 370671593db2Swyllys *priv_key = pkey; 370771593db2Swyllys 370834acef67Swyllys err: 370934acef67Swyllys /* Cleanup the stack of X509 info records */ 371034acef67Swyllys for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) { 3711a2d4930dSDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */ 371234acef67Swyllys info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i); 371334acef67Swyllys X509_INFO_free(info); 371434acef67Swyllys } 371534acef67Swyllys if (x509_info_stack) 371634acef67Swyllys sk_X509_INFO_free(x509_info_stack); 371734acef67Swyllys 37185b3e1433Swyllys if (cert_infos != NULL) 37195b3e1433Swyllys free(cert_infos); 37205b3e1433Swyllys 372171593db2Swyllys return (rv); 372271593db2Swyllys } 372371593db2Swyllys 37245b3e1433Swyllys static KMF_RETURN 37255b3e1433Swyllys openssl_parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *pin, 37265b3e1433Swyllys STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs) 37275b3e1433Swyllys { 37285b3e1433Swyllys KMF_RETURN ret; 37295b3e1433Swyllys int i; 37305b3e1433Swyllys 37315b3e1433Swyllys for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { 3732a2d4930dSDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */ 37335b3e1433Swyllys PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i); 37345b3e1433Swyllys ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0), 37355b3e1433Swyllys keys, certs); 37365b3e1433Swyllys 37375b3e1433Swyllys if (ret != KMF_OK) 37385b3e1433Swyllys return (ret); 37395b3e1433Swyllys } 37405b3e1433Swyllys 37415b3e1433Swyllys return (ret); 37425b3e1433Swyllys } 37435b3e1433Swyllys 37445b3e1433Swyllys static KMF_RETURN 37455b3e1433Swyllys set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid) 37465b3e1433Swyllys { 37475b3e1433Swyllys X509_ATTRIBUTE *attr = NULL; 37485b3e1433Swyllys 37495b3e1433Swyllys if (pkey == NULL || attrib == NULL) 37505b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 37515b3e1433Swyllys 37525b3e1433Swyllys if (pkey->attributes == NULL) { 37535b3e1433Swyllys pkey->attributes = sk_X509_ATTRIBUTE_new_null(); 37545b3e1433Swyllys if (pkey->attributes == NULL) 37555b3e1433Swyllys return (KMF_ERR_MEMORY); 37565b3e1433Swyllys } 37575b3e1433Swyllys attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr); 37585b3e1433Swyllys if (attr != NULL) { 37595b3e1433Swyllys int i; 37605b3e1433Swyllys X509_ATTRIBUTE *a; 37615b3e1433Swyllys for (i = 0; 37625b3e1433Swyllys i < sk_X509_ATTRIBUTE_num(pkey->attributes); i++) { 3763e65e5c2dSWyllys Ingersoll /* LINTED E_BAD_PTR_CASE_ALIGN */ 37645b3e1433Swyllys a = sk_X509_ATTRIBUTE_value(pkey->attributes, i); 37655b3e1433Swyllys if (OBJ_obj2nid(a->object) == nid) { 37665b3e1433Swyllys X509_ATTRIBUTE_free(a); 3767a2d4930dSDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */ 37685b3e1433Swyllys sk_X509_ATTRIBUTE_set(pkey->attributes, 37695b3e1433Swyllys i, attr); 37705b3e1433Swyllys return (KMF_OK); 37715b3e1433Swyllys } 37725b3e1433Swyllys } 37735b3e1433Swyllys if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == NULL) { 37745b3e1433Swyllys X509_ATTRIBUTE_free(attr); 37755b3e1433Swyllys return (KMF_ERR_MEMORY); 37765b3e1433Swyllys } 37775b3e1433Swyllys } else { 37785b3e1433Swyllys return (KMF_ERR_MEMORY); 37795b3e1433Swyllys } 37805b3e1433Swyllys 37815b3e1433Swyllys return (KMF_OK); 37825b3e1433Swyllys } 37835b3e1433Swyllys 37845b3e1433Swyllys static KMF_RETURN 37855b3e1433Swyllys openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen, 37865b3e1433Swyllys STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist) 37875b3e1433Swyllys { 37885b3e1433Swyllys KMF_RETURN ret = KMF_OK; 37895b3e1433Swyllys PKCS8_PRIV_KEY_INFO *p8 = NULL; 37905b3e1433Swyllys EVP_PKEY *pkey = NULL; 37915b3e1433Swyllys X509 *xcert = NULL; 37925b3e1433Swyllys ASN1_TYPE *keyid = NULL; 37935b3e1433Swyllys ASN1_TYPE *fname = NULL; 37945b3e1433Swyllys uchar_t *data = NULL; 37955b3e1433Swyllys 37965b3e1433Swyllys keyid = PKCS12_get_attr(bag, NID_localKeyID); 37975b3e1433Swyllys fname = PKCS12_get_attr(bag, NID_friendlyName); 37985b3e1433Swyllys 37995b3e1433Swyllys switch (M_PKCS12_bag_type(bag)) { 38005b3e1433Swyllys case NID_keyBag: 38015b3e1433Swyllys if (keylist == NULL) 38025b3e1433Swyllys goto end; 38035b3e1433Swyllys pkey = EVP_PKCS82PKEY(bag->value.keybag); 38045b3e1433Swyllys if (pkey == NULL) 38055b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 38065b3e1433Swyllys 38075b3e1433Swyllys break; 38085b3e1433Swyllys case NID_pkcs8ShroudedKeyBag: 38095b3e1433Swyllys if (keylist == NULL) 38105b3e1433Swyllys goto end; 38115b3e1433Swyllys p8 = M_PKCS12_decrypt_skey(bag, pass, passlen); 38125b3e1433Swyllys if (p8 == NULL) 38135b3e1433Swyllys return (KMF_ERR_AUTH_FAILED); 38145b3e1433Swyllys pkey = EVP_PKCS82PKEY(p8); 38155b3e1433Swyllys PKCS8_PRIV_KEY_INFO_free(p8); 38165b3e1433Swyllys if (pkey == NULL) 38175b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 38185b3e1433Swyllys break; 38195b3e1433Swyllys case NID_certBag: 38205b3e1433Swyllys if (certlist == NULL) 38215b3e1433Swyllys goto end; 38225b3e1433Swyllys if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate) 38235b3e1433Swyllys return (KMF_ERR_PKCS12_FORMAT); 38245b3e1433Swyllys xcert = M_PKCS12_certbag2x509(bag); 38255b3e1433Swyllys if (xcert == NULL) { 38265b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 38275b3e1433Swyllys goto end; 38285b3e1433Swyllys } 38295b3e1433Swyllys if (keyid != NULL) { 38305b3e1433Swyllys if (X509_keyid_set1(xcert, 38315b3e1433Swyllys keyid->value.octet_string->data, 38325b3e1433Swyllys keyid->value.octet_string->length) == 0) { 38335b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 38345b3e1433Swyllys goto end; 38355b3e1433Swyllys } 38365b3e1433Swyllys } 38375b3e1433Swyllys if (fname != NULL) { 38385b3e1433Swyllys int len, r; 38395b3e1433Swyllys len = ASN1_STRING_to_UTF8(&data, 38405b3e1433Swyllys fname->value.asn1_string); 38415b3e1433Swyllys if (len > 0 && data != NULL) { 38425b3e1433Swyllys r = X509_alias_set1(xcert, data, len); 38435b3e1433Swyllys if (r == NULL) { 38445b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 38455b3e1433Swyllys goto end; 38465b3e1433Swyllys } 38475b3e1433Swyllys } else { 38485b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 38495b3e1433Swyllys goto end; 38505b3e1433Swyllys } 38515b3e1433Swyllys } 38525b3e1433Swyllys if (sk_X509_push(certlist, xcert) == 0) 38535b3e1433Swyllys ret = KMF_ERR_MEMORY; 38545b3e1433Swyllys else 38555b3e1433Swyllys xcert = NULL; 38565b3e1433Swyllys break; 38575b3e1433Swyllys case NID_safeContentsBag: 38585b3e1433Swyllys return (openssl_parse_bags(bag->value.safes, pass, 38595b3e1433Swyllys keylist, certlist)); 38605b3e1433Swyllys default: 38615b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 38625b3e1433Swyllys break; 38635b3e1433Swyllys } 38645b3e1433Swyllys 38655b3e1433Swyllys /* 38665b3e1433Swyllys * Set the ID and/or FriendlyName attributes on the key. 38675b3e1433Swyllys * If converting to PKCS11 objects, these can translate to CKA_ID 38685b3e1433Swyllys * and CKA_LABEL values. 38695b3e1433Swyllys */ 38705b3e1433Swyllys if (pkey != NULL && ret == KMF_OK) { 38715b3e1433Swyllys ASN1_TYPE *attr = NULL; 38725b3e1433Swyllys if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) { 38735b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) 38745b3e1433Swyllys return (KMF_ERR_MEMORY); 38755b3e1433Swyllys attr->value.octet_string = 38765b3e1433Swyllys ASN1_STRING_dup(keyid->value.octet_string); 38775b3e1433Swyllys attr->type = V_ASN1_OCTET_STRING; 38785b3e1433Swyllys attr->value.ptr = (char *)attr->value.octet_string; 38795b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_localKeyID); 38805b3e1433Swyllys OPENSSL_free(attr); 38815b3e1433Swyllys } 38825b3e1433Swyllys 38835b3e1433Swyllys if (ret == KMF_OK && fname != NULL && 38845b3e1433Swyllys fname->type == V_ASN1_BMPSTRING) { 38855b3e1433Swyllys if ((attr = ASN1_TYPE_new()) == NULL) 38865b3e1433Swyllys return (KMF_ERR_MEMORY); 38875b3e1433Swyllys attr->value.bmpstring = 38885b3e1433Swyllys ASN1_STRING_dup(fname->value.bmpstring); 38895b3e1433Swyllys attr->type = V_ASN1_BMPSTRING; 38905b3e1433Swyllys attr->value.ptr = (char *)attr->value.bmpstring; 38915b3e1433Swyllys ret = set_pkey_attrib(pkey, attr, NID_friendlyName); 38925b3e1433Swyllys OPENSSL_free(attr); 38935b3e1433Swyllys } 38945b3e1433Swyllys 38955b3e1433Swyllys if (ret == KMF_OK && keylist != NULL && 38965b3e1433Swyllys sk_EVP_PKEY_push(keylist, pkey) == 0) 38975b3e1433Swyllys ret = KMF_ERR_MEMORY; 38985b3e1433Swyllys } 38995b3e1433Swyllys if (ret == KMF_OK && keylist != NULL) 39005b3e1433Swyllys pkey = NULL; 39015b3e1433Swyllys end: 39025b3e1433Swyllys if (pkey != NULL) 39035b3e1433Swyllys EVP_PKEY_free(pkey); 39045b3e1433Swyllys if (xcert != NULL) 39055b3e1433Swyllys X509_free(xcert); 39065b3e1433Swyllys if (data != NULL) 39075b3e1433Swyllys OPENSSL_free(data); 39085b3e1433Swyllys 39095b3e1433Swyllys return (ret); 39105b3e1433Swyllys } 39115b3e1433Swyllys 39125b3e1433Swyllys static KMF_RETURN 39135b3e1433Swyllys openssl_pkcs12_parse(PKCS12 *p12, char *pin, 39145b3e1433Swyllys STACK_OF(EVP_PKEY) *keys, 39155b3e1433Swyllys STACK_OF(X509) *certs, 39165b3e1433Swyllys STACK_OF(X509) *ca) 3917a2d4930dSDan OpenSolaris Anderson /* ARGSUSED3 */ 39185b3e1433Swyllys { 39195b3e1433Swyllys KMF_RETURN ret = KMF_OK; 39205b3e1433Swyllys STACK_OF(PKCS7) *asafes = NULL; 39215b3e1433Swyllys STACK_OF(PKCS12_SAFEBAG) *bags = NULL; 39225b3e1433Swyllys int i, bagnid; 39235b3e1433Swyllys PKCS7 *p7; 39245b3e1433Swyllys 39255b3e1433Swyllys if (p12 == NULL || (keys == NULL && certs == NULL)) 39265b3e1433Swyllys return (KMF_ERR_BAD_PARAMETER); 39275b3e1433Swyllys 39285b3e1433Swyllys if (pin == NULL || *pin == NULL) { 39295b3e1433Swyllys if (PKCS12_verify_mac(p12, NULL, 0)) { 39305b3e1433Swyllys pin = NULL; 39315b3e1433Swyllys } else if (PKCS12_verify_mac(p12, "", 0)) { 39325b3e1433Swyllys pin = ""; 39335b3e1433Swyllys } else { 39345b3e1433Swyllys return (KMF_ERR_AUTH_FAILED); 39355b3e1433Swyllys } 39365b3e1433Swyllys } else if (!PKCS12_verify_mac(p12, pin, -1)) { 39375b3e1433Swyllys return (KMF_ERR_AUTH_FAILED); 39385b3e1433Swyllys } 39395b3e1433Swyllys 39405b3e1433Swyllys if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) 39415b3e1433Swyllys return (KMF_ERR_PKCS12_FORMAT); 39425b3e1433Swyllys 39435b3e1433Swyllys for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) { 39445b3e1433Swyllys bags = NULL; 3945a2d4930dSDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */ 39465b3e1433Swyllys p7 = sk_PKCS7_value(asafes, i); 39475b3e1433Swyllys bagnid = OBJ_obj2nid(p7->type); 39485b3e1433Swyllys 39495b3e1433Swyllys if (bagnid == NID_pkcs7_data) { 39505b3e1433Swyllys bags = PKCS12_unpack_p7data(p7); 39515b3e1433Swyllys } else if (bagnid == NID_pkcs7_encrypted) { 39525b3e1433Swyllys bags = PKCS12_unpack_p7encdata(p7, pin, 39535b3e1433Swyllys (pin ? strlen(pin) : 0)); 39545b3e1433Swyllys } else { 39555b3e1433Swyllys continue; 39565b3e1433Swyllys } 39575b3e1433Swyllys if (bags == NULL) { 39585b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39595b3e1433Swyllys goto out; 39605b3e1433Swyllys } 39615b3e1433Swyllys 39625b3e1433Swyllys if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK) 39635b3e1433Swyllys ret = KMF_ERR_PKCS12_FORMAT; 39645b3e1433Swyllys 39655b3e1433Swyllys sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 39665b3e1433Swyllys } 39675b3e1433Swyllys out: 39685b3e1433Swyllys if (asafes != NULL) 39695b3e1433Swyllys sk_PKCS7_pop_free(asafes, PKCS7_free); 39705b3e1433Swyllys 39715b3e1433Swyllys return (ret); 39725b3e1433Swyllys } 39735b3e1433Swyllys 397499ebb4caSwyllys /* 397599ebb4caSwyllys * Helper function to decrypt and parse PKCS#12 import file. 397699ebb4caSwyllys */ 397799ebb4caSwyllys static KMF_RETURN 397899ebb4caSwyllys extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen, 39795b3e1433Swyllys STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs, 39805b3e1433Swyllys STACK_OF(X509) **ca) 3981a2d4930dSDan OpenSolaris Anderson /* ARGSUSED2 */ 398299ebb4caSwyllys { 398399ebb4caSwyllys PKCS12 *pk12, *pk12_tmp; 39845b3e1433Swyllys STACK_OF(EVP_PKEY) *pkeylist = NULL; 39855b3e1433Swyllys STACK_OF(X509) *xcertlist = NULL; 39865b3e1433Swyllys STACK_OF(X509) *cacertlist = NULL; 398799ebb4caSwyllys 398899ebb4caSwyllys if ((pk12 = PKCS12_new()) == NULL) { 398999ebb4caSwyllys return (KMF_ERR_MEMORY); 399099ebb4caSwyllys } 399199ebb4caSwyllys 399299ebb4caSwyllys if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) { 399399ebb4caSwyllys /* This is ok; it seems to mean there is no more to read. */ 399499ebb4caSwyllys if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 && 399599ebb4caSwyllys ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG) 399699ebb4caSwyllys goto end_extract_pkcs12; 399799ebb4caSwyllys 399899ebb4caSwyllys PKCS12_free(pk12); 399999ebb4caSwyllys return (KMF_ERR_PKCS12_FORMAT); 400099ebb4caSwyllys } 400199ebb4caSwyllys pk12 = pk12_tmp; 400299ebb4caSwyllys 40035b3e1433Swyllys xcertlist = sk_X509_new_null(); 40045b3e1433Swyllys if (xcertlist == NULL) { 40055b3e1433Swyllys PKCS12_free(pk12); 40065b3e1433Swyllys return (KMF_ERR_MEMORY); 40075b3e1433Swyllys } 40085b3e1433Swyllys pkeylist = sk_EVP_PKEY_new_null(); 40095b3e1433Swyllys if (pkeylist == NULL) { 40105b3e1433Swyllys sk_X509_pop_free(xcertlist, X509_free); 40115b3e1433Swyllys PKCS12_free(pk12); 40125b3e1433Swyllys return (KMF_ERR_MEMORY); 40135b3e1433Swyllys } 40145b3e1433Swyllys 40155b3e1433Swyllys if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist, 40165b3e1433Swyllys cacertlist) != KMF_OK) { 40175b3e1433Swyllys sk_X509_pop_free(xcertlist, X509_free); 40185b3e1433Swyllys sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free); 401999ebb4caSwyllys PKCS12_free(pk12); 402099ebb4caSwyllys return (KMF_ERR_PKCS12_FORMAT); 402199ebb4caSwyllys } 402299ebb4caSwyllys 40235b3e1433Swyllys if (priv_key && pkeylist) 40245b3e1433Swyllys *priv_key = pkeylist; 40255b3e1433Swyllys else if (pkeylist) 40265b3e1433Swyllys sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free); 40275b3e1433Swyllys if (certs && xcertlist) 40285b3e1433Swyllys *certs = xcertlist; 40295b3e1433Swyllys else if (xcertlist) 40305b3e1433Swyllys sk_X509_pop_free(xcertlist, X509_free); 40315b3e1433Swyllys if (ca && cacertlist) 40325b3e1433Swyllys *ca = cacertlist; 40335b3e1433Swyllys else if (cacertlist) 40345b3e1433Swyllys sk_X509_pop_free(cacertlist, X509_free); 403599ebb4caSwyllys 40365b3e1433Swyllys end_extract_pkcs12: 403799ebb4caSwyllys 403899ebb4caSwyllys PKCS12_free(pk12); 403999ebb4caSwyllys return (KMF_OK); 404099ebb4caSwyllys } 404199ebb4caSwyllys 404299ebb4caSwyllys static KMF_RETURN 404399ebb4caSwyllys sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to) 404499ebb4caSwyllys { 404599ebb4caSwyllys KMF_RETURN rv = KMF_OK; 404699ebb4caSwyllys uint32_t sz; 404799ebb4caSwyllys 404899ebb4caSwyllys sz = BN_num_bytes(from); 404999ebb4caSwyllys to->val = (uchar_t *)malloc(sz); 405099ebb4caSwyllys if (to->val == NULL) 405199ebb4caSwyllys return (KMF_ERR_MEMORY); 405299ebb4caSwyllys 405399ebb4caSwyllys if ((to->len = BN_bn2bin(from, to->val)) != sz) { 405499ebb4caSwyllys free(to->val); 405599ebb4caSwyllys to->val = NULL; 405699ebb4caSwyllys to->len = 0; 405799ebb4caSwyllys rv = KMF_ERR_MEMORY; 405899ebb4caSwyllys } 405999ebb4caSwyllys 406099ebb4caSwyllys return (rv); 406199ebb4caSwyllys } 406299ebb4caSwyllys 406399ebb4caSwyllys static KMF_RETURN 406499ebb4caSwyllys exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key) 406599ebb4caSwyllys { 406699ebb4caSwyllys KMF_RETURN rv; 406799ebb4caSwyllys KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa; 406899ebb4caSwyllys 406999ebb4caSwyllys (void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY)); 407099ebb4caSwyllys if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK) 407199ebb4caSwyllys goto cleanup; 407299ebb4caSwyllys 407399ebb4caSwyllys if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK) 407499ebb4caSwyllys goto cleanup; 407599ebb4caSwyllys 407699ebb4caSwyllys if (rsa->d != NULL) 407799ebb4caSwyllys if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK) 407899ebb4caSwyllys goto cleanup; 407999ebb4caSwyllys 408099ebb4caSwyllys if (rsa->p != NULL) 408199ebb4caSwyllys if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK) 408299ebb4caSwyllys goto cleanup; 408399ebb4caSwyllys 408499ebb4caSwyllys if (rsa->q != NULL) 408599ebb4caSwyllys if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK) 408699ebb4caSwyllys goto cleanup; 408799ebb4caSwyllys 408899ebb4caSwyllys if (rsa->dmp1 != NULL) 408999ebb4caSwyllys if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK) 409099ebb4caSwyllys goto cleanup; 409199ebb4caSwyllys 409299ebb4caSwyllys if (rsa->dmq1 != NULL) 409399ebb4caSwyllys if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK) 409499ebb4caSwyllys goto cleanup; 409599ebb4caSwyllys 409699ebb4caSwyllys if (rsa->iqmp != NULL) 409799ebb4caSwyllys if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK) 409899ebb4caSwyllys goto cleanup; 409999ebb4caSwyllys cleanup: 410099ebb4caSwyllys if (rv != KMF_OK) 410130a5e8faSwyllys kmf_free_raw_key(key); 410299ebb4caSwyllys else 410399ebb4caSwyllys key->keytype = KMF_RSA; 410499ebb4caSwyllys 410599ebb4caSwyllys /* 410699ebb4caSwyllys * Free the reference to this key, SSL will not actually free 410799ebb4caSwyllys * the memory until the refcount == 0, so this is safe. 410899ebb4caSwyllys */ 410999ebb4caSwyllys RSA_free(rsa); 411099ebb4caSwyllys 411199ebb4caSwyllys return (rv); 411299ebb4caSwyllys } 411399ebb4caSwyllys 411499ebb4caSwyllys static KMF_RETURN 411599ebb4caSwyllys exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key) 411699ebb4caSwyllys { 411799ebb4caSwyllys KMF_RETURN rv; 411899ebb4caSwyllys KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa; 411999ebb4caSwyllys 412099ebb4caSwyllys (void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY)); 412199ebb4caSwyllys if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK) 412299ebb4caSwyllys goto cleanup; 412399ebb4caSwyllys 412499ebb4caSwyllys if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK) 412599ebb4caSwyllys goto cleanup; 412699ebb4caSwyllys 412799ebb4caSwyllys if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK) 412899ebb4caSwyllys goto cleanup; 412999ebb4caSwyllys 413099ebb4caSwyllys if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK) 413199ebb4caSwyllys goto cleanup; 413299ebb4caSwyllys 413399ebb4caSwyllys cleanup: 413499ebb4caSwyllys if (rv != KMF_OK) 413530a5e8faSwyllys kmf_free_raw_key(key); 413699ebb4caSwyllys else 413799ebb4caSwyllys key->keytype = KMF_DSA; 413899ebb4caSwyllys 413999ebb4caSwyllys /* 414099ebb4caSwyllys * Free the reference to this key, SSL will not actually free 414199ebb4caSwyllys * the memory until the refcount == 0, so this is safe. 414299ebb4caSwyllys */ 414399ebb4caSwyllys DSA_free(dsa); 414499ebb4caSwyllys 414599ebb4caSwyllys return (rv); 414699ebb4caSwyllys } 414799ebb4caSwyllys 414899ebb4caSwyllys static KMF_RETURN 414999ebb4caSwyllys add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert, 41505b3e1433Swyllys KMF_X509_DER_CERT **certlist, int *ncerts) 415199ebb4caSwyllys { 415299ebb4caSwyllys KMF_RETURN rv = KMF_OK; 41535b3e1433Swyllys KMF_X509_DER_CERT *list = (*certlist); 41545b3e1433Swyllys KMF_X509_DER_CERT cert; 415599ebb4caSwyllys int n = (*ncerts); 415699ebb4caSwyllys 415799ebb4caSwyllys if (list == NULL) { 41585b3e1433Swyllys list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT)); 415999ebb4caSwyllys } else { 41605b3e1433Swyllys list = (KMF_X509_DER_CERT *)realloc(list, 41615b3e1433Swyllys sizeof (KMF_X509_DER_CERT) * (n + 1)); 416299ebb4caSwyllys } 416399ebb4caSwyllys 416499ebb4caSwyllys if (list == NULL) 416599ebb4caSwyllys return (KMF_ERR_MEMORY); 416699ebb4caSwyllys 41675b3e1433Swyllys (void) memset(&cert, 0, sizeof (cert)); 41685b3e1433Swyllys rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate); 416999ebb4caSwyllys if (rv == KMF_OK) { 41705b3e1433Swyllys int len = 0; 41715b3e1433Swyllys /* Get the alias name for the cert if there is one */ 41725b3e1433Swyllys char *a = (char *)X509_alias_get0(sslcert, &len); 41735b3e1433Swyllys if (a != NULL) 41745b3e1433Swyllys cert.kmf_private.label = strdup(a); 41755b3e1433Swyllys cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL; 41765b3e1433Swyllys 417799ebb4caSwyllys list[n] = cert; 417899ebb4caSwyllys (*ncerts) = n + 1; 417999ebb4caSwyllys 418099ebb4caSwyllys *certlist = list; 418199ebb4caSwyllys } else { 418299ebb4caSwyllys free(list); 418399ebb4caSwyllys } 418499ebb4caSwyllys 418599ebb4caSwyllys return (rv); 418699ebb4caSwyllys } 418799ebb4caSwyllys 418899ebb4caSwyllys static KMF_RETURN 418999ebb4caSwyllys add_key_to_list(KMF_RAW_KEY_DATA **keylist, 419099ebb4caSwyllys KMF_RAW_KEY_DATA *newkey, int *nkeys) 419199ebb4caSwyllys { 419299ebb4caSwyllys KMF_RAW_KEY_DATA *list = (*keylist); 419399ebb4caSwyllys int n = (*nkeys); 419499ebb4caSwyllys 419599ebb4caSwyllys if (list == NULL) { 419699ebb4caSwyllys list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA)); 419799ebb4caSwyllys } else { 419899ebb4caSwyllys list = (KMF_RAW_KEY_DATA *)realloc(list, 419999ebb4caSwyllys sizeof (KMF_RAW_KEY_DATA) * (n + 1)); 420099ebb4caSwyllys } 420199ebb4caSwyllys 420299ebb4caSwyllys if (list == NULL) 420399ebb4caSwyllys return (KMF_ERR_MEMORY); 420499ebb4caSwyllys 420599ebb4caSwyllys list[n] = *newkey; 420699ebb4caSwyllys (*nkeys) = n + 1; 420799ebb4caSwyllys 420899ebb4caSwyllys *keylist = list; 420999ebb4caSwyllys 421099ebb4caSwyllys return (KMF_OK); 421199ebb4caSwyllys } 421299ebb4caSwyllys 42135b3e1433Swyllys static X509_ATTRIBUTE * 42145b3e1433Swyllys find_attr(STACK_OF(X509_ATTRIBUTE) *attrs, int nid) 42155b3e1433Swyllys { 42165b3e1433Swyllys X509_ATTRIBUTE *a; 42175b3e1433Swyllys int i; 42185b3e1433Swyllys 42195b3e1433Swyllys if (attrs == NULL) 42205b3e1433Swyllys return (NULL); 42215b3e1433Swyllys 42225b3e1433Swyllys for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) { 4223a2d4930dSDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */ 42245b3e1433Swyllys a = sk_X509_ATTRIBUTE_value(attrs, i); 42255b3e1433Swyllys if (OBJ_obj2nid(a->object) == nid) 42265b3e1433Swyllys return (a); 42275b3e1433Swyllys } 42285b3e1433Swyllys return (NULL); 42295b3e1433Swyllys } 42305b3e1433Swyllys 423130a5e8faSwyllys static KMF_RETURN 423230a5e8faSwyllys convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key) 423330a5e8faSwyllys { 423430a5e8faSwyllys KMF_RETURN rv = KMF_OK; 42355b3e1433Swyllys X509_ATTRIBUTE *attr; 423630a5e8faSwyllys 423730a5e8faSwyllys if (pkey == NULL || key == NULL) 423830a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 423930a5e8faSwyllys /* Convert SSL key to raw key */ 424030a5e8faSwyllys switch (pkey->type) { 424130a5e8faSwyllys case EVP_PKEY_RSA: 424230a5e8faSwyllys rv = exportRawRSAKey(EVP_PKEY_get1_RSA(pkey), 424330a5e8faSwyllys key); 424430a5e8faSwyllys if (rv != KMF_OK) 424530a5e8faSwyllys return (rv); 424630a5e8faSwyllys break; 424730a5e8faSwyllys case EVP_PKEY_DSA: 424830a5e8faSwyllys rv = exportRawDSAKey(EVP_PKEY_get1_DSA(pkey), 424930a5e8faSwyllys key); 425030a5e8faSwyllys if (rv != KMF_OK) 425130a5e8faSwyllys return (rv); 425230a5e8faSwyllys break; 425330a5e8faSwyllys default: 425430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 425530a5e8faSwyllys } 42565b3e1433Swyllys /* 42575b3e1433Swyllys * If friendlyName, add it to record. 42585b3e1433Swyllys */ 42595b3e1433Swyllys attr = find_attr(pkey->attributes, NID_friendlyName); 42605b3e1433Swyllys if (attr != NULL) { 42615b3e1433Swyllys ASN1_TYPE *ty = NULL; 42625b3e1433Swyllys int numattr = sk_ASN1_TYPE_num(attr->value.set); 42635b3e1433Swyllys if (attr->single == 0 && numattr > 0) { 4264a2d4930dSDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */ 42655b3e1433Swyllys ty = sk_ASN1_TYPE_value(attr->value.set, 0); 42665b3e1433Swyllys } 42675b3e1433Swyllys if (ty != NULL) { 42685b3e1433Swyllys key->label = uni2asc(ty->value.bmpstring->data, 42695b3e1433Swyllys ty->value.bmpstring->length); 42705b3e1433Swyllys } 42715b3e1433Swyllys } else { 42725b3e1433Swyllys key->label = NULL; 42735b3e1433Swyllys } 42745b3e1433Swyllys 42755b3e1433Swyllys /* 42765b3e1433Swyllys * If KeyID, add it to record as a KMF_DATA object. 42775b3e1433Swyllys */ 42785b3e1433Swyllys attr = find_attr(pkey->attributes, NID_localKeyID); 42795b3e1433Swyllys if (attr != NULL) { 42805b3e1433Swyllys ASN1_TYPE *ty = NULL; 42815b3e1433Swyllys int numattr = sk_ASN1_TYPE_num(attr->value.set); 42825b3e1433Swyllys if (attr->single == 0 && numattr > 0) { 4283a2d4930dSDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */ 42845b3e1433Swyllys ty = sk_ASN1_TYPE_value(attr->value.set, 0); 42855b3e1433Swyllys } 42865b3e1433Swyllys key->id.Data = (uchar_t *)malloc( 42875b3e1433Swyllys ty->value.octet_string->length); 42885b3e1433Swyllys if (key->id.Data == NULL) 42895b3e1433Swyllys return (KMF_ERR_MEMORY); 42905b3e1433Swyllys (void) memcpy(key->id.Data, ty->value.octet_string->data, 42915b3e1433Swyllys ty->value.octet_string->length); 42925b3e1433Swyllys key->id.Length = ty->value.octet_string->length; 42935b3e1433Swyllys } else { 42945b3e1433Swyllys (void) memset(&key->id, 0, sizeof (KMF_DATA)); 42955b3e1433Swyllys } 429630a5e8faSwyllys 429730a5e8faSwyllys return (rv); 429830a5e8faSwyllys } 429999ebb4caSwyllys 430099ebb4caSwyllys static KMF_RETURN 430199ebb4caSwyllys convertPK12Objects( 430299ebb4caSwyllys KMF_HANDLE *kmfh, 43035b3e1433Swyllys STACK_OF(EVP_PKEY) *sslkeys, 43045b3e1433Swyllys STACK_OF(X509) *sslcert, 43055b3e1433Swyllys STACK_OF(X509) *sslcacerts, 430699ebb4caSwyllys KMF_RAW_KEY_DATA **keylist, int *nkeys, 43075b3e1433Swyllys KMF_X509_DER_CERT **certlist, int *ncerts) 430899ebb4caSwyllys { 430999ebb4caSwyllys KMF_RETURN rv = KMF_OK; 431099ebb4caSwyllys KMF_RAW_KEY_DATA key; 431199ebb4caSwyllys int i; 431299ebb4caSwyllys 43135b3e1433Swyllys for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) { 4314a2d4930dSDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */ 43155b3e1433Swyllys EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i); 43165b3e1433Swyllys rv = convertToRawKey(pkey, &key); 431730a5e8faSwyllys if (rv == KMF_OK) 431899ebb4caSwyllys rv = add_key_to_list(keylist, &key, nkeys); 431930a5e8faSwyllys 432099ebb4caSwyllys if (rv != KMF_OK) 432199ebb4caSwyllys return (rv); 432299ebb4caSwyllys } 432399ebb4caSwyllys 432499ebb4caSwyllys /* Now add the certificate to the certlist */ 43255b3e1433Swyllys for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) { 4326a2d4930dSDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */ 43275b3e1433Swyllys X509 *cert = sk_X509_value(sslcert, i); 43285b3e1433Swyllys rv = add_cert_to_list(kmfh, cert, certlist, ncerts); 432999ebb4caSwyllys if (rv != KMF_OK) 433099ebb4caSwyllys return (rv); 433199ebb4caSwyllys } 433299ebb4caSwyllys 433399ebb4caSwyllys /* Also add any included CA certs to the list */ 433471593db2Swyllys for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) { 433599ebb4caSwyllys X509 *c; 433699ebb4caSwyllys /* 433799ebb4caSwyllys * sk_X509_value() is macro that embeds a cast to (X509 *). 433899ebb4caSwyllys * Here it translates into ((X509 *)sk_value((ca), (i))). 433999ebb4caSwyllys * Lint is complaining about the embedded casting, and 434099ebb4caSwyllys * to fix it, you need to fix openssl header files. 434199ebb4caSwyllys */ 434299ebb4caSwyllys /* LINTED E_BAD_PTR_CAST_ALIGN */ 434399ebb4caSwyllys c = sk_X509_value(sslcacerts, i); 434499ebb4caSwyllys 434599ebb4caSwyllys /* Now add the ca cert to the certlist */ 434699ebb4caSwyllys rv = add_cert_to_list(kmfh, c, certlist, ncerts); 434799ebb4caSwyllys if (rv != KMF_OK) 434899ebb4caSwyllys return (rv); 434999ebb4caSwyllys } 435099ebb4caSwyllys return (rv); 435199ebb4caSwyllys } 435299ebb4caSwyllys 435399ebb4caSwyllys KMF_RETURN 435430a5e8faSwyllys openssl_import_objects(KMF_HANDLE *kmfh, 435599ebb4caSwyllys char *filename, KMF_CREDENTIAL *cred, 43565b3e1433Swyllys KMF_X509_DER_CERT **certlist, int *ncerts, 435799ebb4caSwyllys KMF_RAW_KEY_DATA **keylist, int *nkeys) 435899ebb4caSwyllys { 435999ebb4caSwyllys KMF_RETURN rv = KMF_OK; 436030a5e8faSwyllys KMF_ENCODE_FORMAT format; 436130a5e8faSwyllys BIO *bio = NULL; 43625b3e1433Swyllys STACK_OF(EVP_PKEY) *privkeys = NULL; 43635b3e1433Swyllys STACK_OF(X509) *certs = NULL; 436499ebb4caSwyllys STACK_OF(X509) *cacerts = NULL; 436599ebb4caSwyllys 436630a5e8faSwyllys /* 436730a5e8faSwyllys * auto-detect the file format, regardless of what 436830a5e8faSwyllys * the 'format' parameters in the params say. 436930a5e8faSwyllys */ 437030a5e8faSwyllys rv = kmf_get_file_format(filename, &format); 437130a5e8faSwyllys if (rv != KMF_OK) { 437230a5e8faSwyllys return (rv); 437330a5e8faSwyllys } 437430a5e8faSwyllys 437530a5e8faSwyllys /* This function only works for PEM or PKCS#12 files */ 437630a5e8faSwyllys if (format != KMF_FORMAT_PEM && 437730a5e8faSwyllys format != KMF_FORMAT_PEM_KEYPAIR && 437830a5e8faSwyllys format != KMF_FORMAT_PKCS12) 437930a5e8faSwyllys return (KMF_ERR_ENCODING); 438030a5e8faSwyllys 438130a5e8faSwyllys *certlist = NULL; 438230a5e8faSwyllys *keylist = NULL; 438330a5e8faSwyllys *ncerts = 0; 438430a5e8faSwyllys *nkeys = 0; 438530a5e8faSwyllys 438630a5e8faSwyllys if (format == KMF_FORMAT_PKCS12) { 438799ebb4caSwyllys bio = BIO_new_file(filename, "rb"); 438899ebb4caSwyllys if (bio == NULL) { 438999ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 439099ebb4caSwyllys rv = KMF_ERR_OPEN_FILE; 439199ebb4caSwyllys goto end; 439299ebb4caSwyllys } 439399ebb4caSwyllys 439434acef67Swyllys rv = extract_pkcs12(bio, (uchar_t *)cred->cred, 43955b3e1433Swyllys (uint32_t)cred->credlen, &privkeys, &certs, &cacerts); 439699ebb4caSwyllys 439799ebb4caSwyllys if (rv == KMF_OK) 439899ebb4caSwyllys /* Convert keys and certs to exportable format */ 43995b3e1433Swyllys rv = convertPK12Objects(kmfh, privkeys, certs, cacerts, 440099ebb4caSwyllys keylist, nkeys, certlist, ncerts); 440130a5e8faSwyllys } else { 44025b3e1433Swyllys EVP_PKEY *pkey; 44035b3e1433Swyllys KMF_DATA *certdata = NULL; 44045b3e1433Swyllys KMF_X509_DER_CERT *kmfcerts = NULL; 44055b3e1433Swyllys int i; 440630a5e8faSwyllys rv = extract_pem(kmfh, NULL, NULL, NULL, filename, 440734acef67Swyllys (uchar_t *)cred->cred, (uint32_t)cred->credlen, 44085b3e1433Swyllys &pkey, &certdata, ncerts); 440971593db2Swyllys 441071593db2Swyllys /* Reached end of import file? */ 44115b3e1433Swyllys if (rv == KMF_OK && pkey != NULL) { 44125b3e1433Swyllys privkeys = sk_EVP_PKEY_new_null(); 44135b3e1433Swyllys if (privkeys == NULL) { 44145b3e1433Swyllys rv = KMF_ERR_MEMORY; 44155b3e1433Swyllys goto end; 44165b3e1433Swyllys } 44175b3e1433Swyllys (void) sk_EVP_PKEY_push(privkeys, pkey); 44185b3e1433Swyllys /* convert the certificate list here */ 44195b3e1433Swyllys if (*ncerts > 0 && certlist != NULL) { 4420e65e5c2dSWyllys Ingersoll kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts, 44215b3e1433Swyllys sizeof (KMF_X509_DER_CERT)); 44225b3e1433Swyllys if (kmfcerts == NULL) { 44235b3e1433Swyllys rv = KMF_ERR_MEMORY; 44245b3e1433Swyllys goto end; 44255b3e1433Swyllys } 44265b3e1433Swyllys for (i = 0; i < *ncerts; i++) { 44275b3e1433Swyllys kmfcerts[i].certificate = certdata[i]; 44285b3e1433Swyllys kmfcerts[i].kmf_private.keystore_type = 44295b3e1433Swyllys KMF_KEYSTORE_OPENSSL; 44305b3e1433Swyllys } 44315b3e1433Swyllys *certlist = kmfcerts; 44325b3e1433Swyllys } 44335b3e1433Swyllys /* 44345b3e1433Swyllys * Convert keys to exportable format, the certs 44355b3e1433Swyllys * are already OK. 44365b3e1433Swyllys */ 44375b3e1433Swyllys rv = convertPK12Objects(kmfh, privkeys, NULL, NULL, 443871593db2Swyllys keylist, nkeys, NULL, NULL); 443930a5e8faSwyllys } 44405b3e1433Swyllys } 444171593db2Swyllys end: 444230a5e8faSwyllys if (bio != NULL) 444399ebb4caSwyllys (void) BIO_free(bio); 444499ebb4caSwyllys 44455b3e1433Swyllys if (privkeys) 44465b3e1433Swyllys sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free); 44475b3e1433Swyllys if (certs) 44485b3e1433Swyllys sk_X509_pop_free(certs, X509_free); 444930a5e8faSwyllys if (cacerts) 44505b3e1433Swyllys sk_X509_pop_free(cacerts, X509_free); 445130a5e8faSwyllys 445299ebb4caSwyllys return (rv); 445399ebb4caSwyllys } 445499ebb4caSwyllys 445599ebb4caSwyllys static KMF_RETURN 445699ebb4caSwyllys create_deskey(DES_cblock **deskey) 445799ebb4caSwyllys { 445899ebb4caSwyllys DES_cblock *key; 445999ebb4caSwyllys 446099ebb4caSwyllys key = (DES_cblock *) malloc(sizeof (DES_cblock)); 446199ebb4caSwyllys if (key == NULL) { 446299ebb4caSwyllys return (KMF_ERR_MEMORY); 446399ebb4caSwyllys } 446499ebb4caSwyllys 446599ebb4caSwyllys if (DES_random_key(key) == 0) { 446699ebb4caSwyllys free(key); 446799ebb4caSwyllys return (KMF_ERR_KEYGEN_FAILED); 446899ebb4caSwyllys } 446999ebb4caSwyllys 447099ebb4caSwyllys *deskey = key; 447199ebb4caSwyllys return (KMF_OK); 447299ebb4caSwyllys } 447399ebb4caSwyllys 447499ebb4caSwyllys #define KEYGEN_RETRY 3 447599ebb4caSwyllys #define DES3_KEY_SIZE 24 447699ebb4caSwyllys 447799ebb4caSwyllys static KMF_RETURN 447899ebb4caSwyllys create_des3key(unsigned char **des3key) 447999ebb4caSwyllys { 448099ebb4caSwyllys KMF_RETURN ret = KMF_OK; 448199ebb4caSwyllys DES_cblock *deskey1 = NULL; 448299ebb4caSwyllys DES_cblock *deskey2 = NULL; 448399ebb4caSwyllys DES_cblock *deskey3 = NULL; 448499ebb4caSwyllys unsigned char *newkey = NULL; 448599ebb4caSwyllys int retry; 448699ebb4caSwyllys 448799ebb4caSwyllys if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) { 448899ebb4caSwyllys return (KMF_ERR_MEMORY); 448999ebb4caSwyllys } 449099ebb4caSwyllys 449199ebb4caSwyllys /* create the 1st DES key */ 449299ebb4caSwyllys if ((ret = create_deskey(&deskey1)) != KMF_OK) { 449399ebb4caSwyllys goto out; 449499ebb4caSwyllys } 449599ebb4caSwyllys 449699ebb4caSwyllys /* 449799ebb4caSwyllys * Create the 2nd DES key and make sure its value is different 449899ebb4caSwyllys * from the 1st DES key. 449999ebb4caSwyllys */ 450099ebb4caSwyllys retry = 0; 450199ebb4caSwyllys do { 450299ebb4caSwyllys if (deskey2 != NULL) { 450399ebb4caSwyllys free(deskey2); 450499ebb4caSwyllys deskey2 = NULL; 450599ebb4caSwyllys } 450699ebb4caSwyllys 450799ebb4caSwyllys if ((ret = create_deskey(&deskey2)) != KMF_OK) { 450899ebb4caSwyllys goto out; 450999ebb4caSwyllys } 451099ebb4caSwyllys 451199ebb4caSwyllys if (memcmp((const void *) deskey1, (const void *) deskey2, 8) 451299ebb4caSwyllys == 0) { 451399ebb4caSwyllys ret = KMF_ERR_KEYGEN_FAILED; 451499ebb4caSwyllys retry++; 451599ebb4caSwyllys } 451699ebb4caSwyllys } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY); 451799ebb4caSwyllys 451899ebb4caSwyllys if (ret != KMF_OK) { 451999ebb4caSwyllys goto out; 452099ebb4caSwyllys } 452199ebb4caSwyllys 452299ebb4caSwyllys /* 452399ebb4caSwyllys * Create the 3rd DES key and make sure its value is different 452499ebb4caSwyllys * from the 2nd DES key. 452599ebb4caSwyllys */ 452699ebb4caSwyllys retry = 0; 452799ebb4caSwyllys do { 452899ebb4caSwyllys if (deskey3 != NULL) { 452999ebb4caSwyllys free(deskey3); 453099ebb4caSwyllys deskey3 = NULL; 453199ebb4caSwyllys } 453299ebb4caSwyllys 453399ebb4caSwyllys if ((ret = create_deskey(&deskey3)) != KMF_OK) { 453499ebb4caSwyllys goto out; 453599ebb4caSwyllys } 453699ebb4caSwyllys 453799ebb4caSwyllys if (memcmp((const void *)deskey2, (const void *)deskey3, 8) 453899ebb4caSwyllys == 0) { 453999ebb4caSwyllys ret = KMF_ERR_KEYGEN_FAILED; 454099ebb4caSwyllys retry++; 454199ebb4caSwyllys } 454299ebb4caSwyllys } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY); 454399ebb4caSwyllys 454499ebb4caSwyllys if (ret != KMF_OK) { 454599ebb4caSwyllys goto out; 454699ebb4caSwyllys } 454799ebb4caSwyllys 454899ebb4caSwyllys /* Concatenate 3 DES keys into a DES3 key */ 454999ebb4caSwyllys (void) memcpy((void *)newkey, (const void *)deskey1, 8); 455099ebb4caSwyllys (void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8); 455199ebb4caSwyllys (void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8); 455299ebb4caSwyllys *des3key = newkey; 455399ebb4caSwyllys 455499ebb4caSwyllys out: 455599ebb4caSwyllys if (deskey1 != NULL) 455699ebb4caSwyllys free(deskey1); 455799ebb4caSwyllys 455899ebb4caSwyllys if (deskey2 != NULL) 455999ebb4caSwyllys free(deskey2); 456099ebb4caSwyllys 456199ebb4caSwyllys if (deskey3 != NULL) 456299ebb4caSwyllys free(deskey3); 456399ebb4caSwyllys 456499ebb4caSwyllys if (ret != KMF_OK && newkey != NULL) 456599ebb4caSwyllys free(newkey); 456699ebb4caSwyllys 456799ebb4caSwyllys return (ret); 456899ebb4caSwyllys } 456999ebb4caSwyllys 457099ebb4caSwyllys KMF_RETURN 457130a5e8faSwyllys OpenSSL_CreateSymKey(KMF_HANDLE_T handle, 457230a5e8faSwyllys int numattr, KMF_ATTRIBUTE *attrlist) 457399ebb4caSwyllys { 457499ebb4caSwyllys KMF_RETURN ret = KMF_OK; 457599ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 457699ebb4caSwyllys char *fullpath = NULL; 457799ebb4caSwyllys KMF_RAW_SYM_KEY *rkey = NULL; 457899ebb4caSwyllys DES_cblock *deskey = NULL; 457999ebb4caSwyllys unsigned char *des3key = NULL; 458099ebb4caSwyllys unsigned char *random = NULL; 458199ebb4caSwyllys int fd = -1; 458230a5e8faSwyllys KMF_KEY_HANDLE *symkey; 458330a5e8faSwyllys KMF_KEY_ALG keytype; 458430a5e8faSwyllys uint32_t keylen; 458530a5e8faSwyllys uint32_t keylen_size = sizeof (keylen); 458630a5e8faSwyllys char *dirpath; 458730a5e8faSwyllys char *keyfile; 458899ebb4caSwyllys 458999ebb4caSwyllys if (kmfh == NULL) 459099ebb4caSwyllys return (KMF_ERR_UNINITIALIZED); 459199ebb4caSwyllys 459230a5e8faSwyllys symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 459330a5e8faSwyllys if (symkey == NULL) 459499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 459599ebb4caSwyllys 459630a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 459730a5e8faSwyllys 459830a5e8faSwyllys keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr); 459930a5e8faSwyllys if (keyfile == NULL) 460030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 460130a5e8faSwyllys 460230a5e8faSwyllys ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, 460330a5e8faSwyllys (void *)&keytype, NULL); 460430a5e8faSwyllys if (ret != KMF_OK) 460530a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 460630a5e8faSwyllys 460730a5e8faSwyllys ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, 460830a5e8faSwyllys &keylen, &keylen_size); 460930a5e8faSwyllys if (ret == KMF_ERR_ATTR_NOT_FOUND && 461030a5e8faSwyllys (keytype == KMF_DES || keytype == KMF_DES3)) 461130a5e8faSwyllys /* keylength is not required for DES and 3DES */ 461230a5e8faSwyllys ret = KMF_OK; 461330a5e8faSwyllys if (ret != KMF_OK) 461430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 461530a5e8faSwyllys 461630a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 461799ebb4caSwyllys if (fullpath == NULL) 461899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 461999ebb4caSwyllys 462099ebb4caSwyllys /* If the requested file exists, return an error */ 462130a5e8faSwyllys if (test_for_file(fullpath, 0400) == 1) { 462299ebb4caSwyllys free(fullpath); 462399ebb4caSwyllys return (KMF_ERR_DUPLICATE_KEYFILE); 462499ebb4caSwyllys } 462599ebb4caSwyllys 462699ebb4caSwyllys fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400); 462799ebb4caSwyllys if (fd == -1) { 462899ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 462999ebb4caSwyllys goto out; 463099ebb4caSwyllys } 463199ebb4caSwyllys 463299ebb4caSwyllys rkey = malloc(sizeof (KMF_RAW_SYM_KEY)); 463399ebb4caSwyllys if (rkey == NULL) { 463499ebb4caSwyllys ret = KMF_ERR_MEMORY; 463599ebb4caSwyllys goto out; 463699ebb4caSwyllys } 463799ebb4caSwyllys (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 463899ebb4caSwyllys 463930a5e8faSwyllys if (keytype == KMF_DES) { 464099ebb4caSwyllys if ((ret = create_deskey(&deskey)) != KMF_OK) { 464199ebb4caSwyllys goto out; 464299ebb4caSwyllys } 464399ebb4caSwyllys rkey->keydata.val = (uchar_t *)deskey; 464499ebb4caSwyllys rkey->keydata.len = 8; 464599ebb4caSwyllys 464699ebb4caSwyllys symkey->keyalg = KMF_DES; 464799ebb4caSwyllys 464830a5e8faSwyllys } else if (keytype == KMF_DES3) { 464999ebb4caSwyllys if ((ret = create_des3key(&des3key)) != KMF_OK) { 465099ebb4caSwyllys goto out; 465199ebb4caSwyllys } 465299ebb4caSwyllys rkey->keydata.val = (uchar_t *)des3key; 465399ebb4caSwyllys rkey->keydata.len = DES3_KEY_SIZE; 465499ebb4caSwyllys symkey->keyalg = KMF_DES3; 46559b37d296Swyllys 465630a5e8faSwyllys } else if (keytype == KMF_AES || keytype == KMF_RC4 || 465730a5e8faSwyllys keytype == KMF_GENERIC_SECRET) { 465899ebb4caSwyllys int bytes; 465999ebb4caSwyllys 466030a5e8faSwyllys if (keylen % 8 != 0) { 466199ebb4caSwyllys ret = KMF_ERR_BAD_KEY_SIZE; 466299ebb4caSwyllys goto out; 466399ebb4caSwyllys } 466499ebb4caSwyllys 466530a5e8faSwyllys if (keytype == KMF_AES) { 466630a5e8faSwyllys if (keylen != 128 && 466730a5e8faSwyllys keylen != 192 && 466830a5e8faSwyllys keylen != 256) { 466999ebb4caSwyllys ret = KMF_ERR_BAD_KEY_SIZE; 467099ebb4caSwyllys goto out; 467199ebb4caSwyllys } 467299ebb4caSwyllys } 467399ebb4caSwyllys 467430a5e8faSwyllys bytes = keylen/8; 467599ebb4caSwyllys random = malloc(bytes); 467699ebb4caSwyllys if (random == NULL) { 467799ebb4caSwyllys ret = KMF_ERR_MEMORY; 467899ebb4caSwyllys goto out; 467999ebb4caSwyllys } 468099ebb4caSwyllys if (RAND_bytes(random, bytes) != 1) { 468199ebb4caSwyllys ret = KMF_ERR_KEYGEN_FAILED; 468299ebb4caSwyllys goto out; 468399ebb4caSwyllys } 468499ebb4caSwyllys 468599ebb4caSwyllys rkey->keydata.val = (uchar_t *)random; 468699ebb4caSwyllys rkey->keydata.len = bytes; 468730a5e8faSwyllys symkey->keyalg = keytype; 468899ebb4caSwyllys 468999ebb4caSwyllys } else { 469099ebb4caSwyllys ret = KMF_ERR_BAD_KEY_TYPE; 469199ebb4caSwyllys goto out; 469299ebb4caSwyllys } 469399ebb4caSwyllys 469499ebb4caSwyllys (void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len); 469599ebb4caSwyllys 469699ebb4caSwyllys symkey->kstype = KMF_KEYSTORE_OPENSSL; 469799ebb4caSwyllys symkey->keyclass = KMF_SYMMETRIC; 469899ebb4caSwyllys symkey->keylabel = (char *)fullpath; 469999ebb4caSwyllys symkey->israw = TRUE; 470099ebb4caSwyllys symkey->keyp = rkey; 470199ebb4caSwyllys 470299ebb4caSwyllys out: 470399ebb4caSwyllys if (fd != -1) 470499ebb4caSwyllys (void) close(fd); 470599ebb4caSwyllys 470699ebb4caSwyllys if (ret != KMF_OK && fullpath != NULL) { 470799ebb4caSwyllys free(fullpath); 470899ebb4caSwyllys } 470999ebb4caSwyllys if (ret != KMF_OK) { 471030a5e8faSwyllys kmf_free_raw_sym_key(rkey); 471199ebb4caSwyllys symkey->keyp = NULL; 471299ebb4caSwyllys symkey->keyalg = KMF_KEYALG_NONE; 471399ebb4caSwyllys } 471499ebb4caSwyllys 471599ebb4caSwyllys return (ret); 471699ebb4caSwyllys } 471799ebb4caSwyllys 471899ebb4caSwyllys /* 471999ebb4caSwyllys * Check a file to see if it is a CRL file with PEM or DER format. 472099ebb4caSwyllys * If success, return its format in the "pformat" argument. 472199ebb4caSwyllys */ 472299ebb4caSwyllys KMF_RETURN 472399ebb4caSwyllys OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat) 472499ebb4caSwyllys { 472599ebb4caSwyllys KMF_RETURN ret = KMF_OK; 472699ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 472799ebb4caSwyllys BIO *bio = NULL; 472899ebb4caSwyllys X509_CRL *xcrl = NULL; 472999ebb4caSwyllys 473099ebb4caSwyllys if (filename == NULL) { 473199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 473299ebb4caSwyllys } 473399ebb4caSwyllys 473499ebb4caSwyllys bio = BIO_new_file(filename, "rb"); 473599ebb4caSwyllys if (bio == NULL) { 473699ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 473799ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 473899ebb4caSwyllys goto out; 473999ebb4caSwyllys } 474099ebb4caSwyllys 474199ebb4caSwyllys if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) { 474299ebb4caSwyllys *pformat = KMF_FORMAT_PEM; 474399ebb4caSwyllys goto out; 474499ebb4caSwyllys } 474599ebb4caSwyllys (void) BIO_free(bio); 474699ebb4caSwyllys 474799ebb4caSwyllys /* 474899ebb4caSwyllys * Now try to read it as raw DER data. 474999ebb4caSwyllys */ 475099ebb4caSwyllys bio = BIO_new_file(filename, "rb"); 475199ebb4caSwyllys if (bio == NULL) { 475299ebb4caSwyllys SET_ERROR(kmfh, ERR_get_error()); 475399ebb4caSwyllys ret = KMF_ERR_OPEN_FILE; 475499ebb4caSwyllys goto out; 475599ebb4caSwyllys } 475699ebb4caSwyllys 475799ebb4caSwyllys if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) { 475899ebb4caSwyllys *pformat = KMF_FORMAT_ASN1; 475999ebb4caSwyllys } else { 476099ebb4caSwyllys ret = KMF_ERR_BAD_CRLFILE; 476199ebb4caSwyllys } 476299ebb4caSwyllys 476399ebb4caSwyllys out: 476499ebb4caSwyllys if (bio != NULL) 476599ebb4caSwyllys (void) BIO_free(bio); 476699ebb4caSwyllys 476799ebb4caSwyllys if (xcrl != NULL) 476899ebb4caSwyllys X509_CRL_free(xcrl); 476999ebb4caSwyllys 477099ebb4caSwyllys return (ret); 477199ebb4caSwyllys } 477299ebb4caSwyllys 477399ebb4caSwyllys KMF_RETURN 477499ebb4caSwyllys OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey, 477599ebb4caSwyllys KMF_RAW_SYM_KEY *rkey) 477699ebb4caSwyllys { 477799ebb4caSwyllys KMF_RETURN rv = KMF_OK; 477899ebb4caSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 477999ebb4caSwyllys KMF_DATA keyvalue; 478099ebb4caSwyllys 478199ebb4caSwyllys if (kmfh == NULL) 478299ebb4caSwyllys return (KMF_ERR_UNINITIALIZED); 478399ebb4caSwyllys 478499ebb4caSwyllys if (symkey == NULL || rkey == NULL) 478599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 478699ebb4caSwyllys else if (symkey->keyclass != KMF_SYMMETRIC) 478799ebb4caSwyllys return (KMF_ERR_BAD_KEY_CLASS); 478899ebb4caSwyllys 478999ebb4caSwyllys if (symkey->israw) { 479099ebb4caSwyllys KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp; 479199ebb4caSwyllys 479299ebb4caSwyllys if (rawkey == NULL || 479399ebb4caSwyllys rawkey->keydata.val == NULL || 479499ebb4caSwyllys rawkey->keydata.len == 0) 479599ebb4caSwyllys return (KMF_ERR_BAD_KEYHANDLE); 479699ebb4caSwyllys 479799ebb4caSwyllys rkey->keydata.len = rawkey->keydata.len; 479899ebb4caSwyllys if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL) 479999ebb4caSwyllys return (KMF_ERR_MEMORY); 480099ebb4caSwyllys (void) memcpy(rkey->keydata.val, rawkey->keydata.val, 480199ebb4caSwyllys rkey->keydata.len); 480299ebb4caSwyllys } else { 480330a5e8faSwyllys rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue); 480499ebb4caSwyllys if (rv != KMF_OK) 480599ebb4caSwyllys return (rv); 480699ebb4caSwyllys rkey->keydata.len = keyvalue.Length; 480799ebb4caSwyllys rkey->keydata.val = keyvalue.Data; 480899ebb4caSwyllys } 480999ebb4caSwyllys 481099ebb4caSwyllys return (rv); 481199ebb4caSwyllys } 481202744e81Swyllys 481302744e81Swyllys /* 481430a5e8faSwyllys * substitute for the unsafe access(2) function. 481530a5e8faSwyllys * If the file in question already exists, return 1. 481630a5e8faSwyllys * else 0. If an error occurs during testing (other 481730a5e8faSwyllys * than EEXIST), return -1. 481830a5e8faSwyllys */ 481930a5e8faSwyllys static int 482030a5e8faSwyllys test_for_file(char *filename, mode_t mode) 482130a5e8faSwyllys { 482230a5e8faSwyllys int fd; 482330a5e8faSwyllys 482430a5e8faSwyllys /* 482530a5e8faSwyllys * Try to create the file with the EXCL flag. 482630a5e8faSwyllys * The call should fail if the file exists. 482730a5e8faSwyllys */ 482830a5e8faSwyllys fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode); 482930a5e8faSwyllys if (fd == -1 && errno == EEXIST) 483030a5e8faSwyllys return (1); 483130a5e8faSwyllys else if (fd == -1) /* some other error */ 483230a5e8faSwyllys return (-1); 483330a5e8faSwyllys 483430a5e8faSwyllys /* The file did NOT exist. Delete the testcase. */ 483530a5e8faSwyllys (void) close(fd); 483630a5e8faSwyllys (void) unlink(filename); 483730a5e8faSwyllys return (0); 483830a5e8faSwyllys } 483930a5e8faSwyllys 484030a5e8faSwyllys KMF_RETURN 484130a5e8faSwyllys OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr, 484230a5e8faSwyllys KMF_ATTRIBUTE *attrlist) 484330a5e8faSwyllys { 484430a5e8faSwyllys KMF_RETURN rv = KMF_OK; 484530a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 484630a5e8faSwyllys KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL; 484730a5e8faSwyllys KMF_RAW_KEY_DATA *rawkey; 484830a5e8faSwyllys EVP_PKEY *pkey = NULL; 484930a5e8faSwyllys KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM; 485030a5e8faSwyllys KMF_CREDENTIAL cred = {NULL, 0}; 485130a5e8faSwyllys BIO *out = NULL; 485230a5e8faSwyllys int keys = 0; 485330a5e8faSwyllys char *fullpath = NULL; 485430a5e8faSwyllys char *keyfile = NULL; 485530a5e8faSwyllys char *dirpath = NULL; 485630a5e8faSwyllys 485730a5e8faSwyllys pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr); 485830a5e8faSwyllys if (pubkey != NULL) 485930a5e8faSwyllys keys++; 486030a5e8faSwyllys 486130a5e8faSwyllys prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr); 486230a5e8faSwyllys if (prikey != NULL) 486330a5e8faSwyllys keys++; 486430a5e8faSwyllys 486530a5e8faSwyllys rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr); 486630a5e8faSwyllys if (rawkey != NULL) 486730a5e8faSwyllys keys++; 486830a5e8faSwyllys 486930a5e8faSwyllys /* 487030a5e8faSwyllys * Exactly 1 type of key must be passed to this function. 487130a5e8faSwyllys */ 487230a5e8faSwyllys if (keys != 1) 487330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 487430a5e8faSwyllys 487530a5e8faSwyllys keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, 487630a5e8faSwyllys numattr); 487730a5e8faSwyllys if (keyfile == NULL) 487830a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 487930a5e8faSwyllys 488030a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 488130a5e8faSwyllys 488230a5e8faSwyllys fullpath = get_fullpath(dirpath, keyfile); 488330a5e8faSwyllys 488430a5e8faSwyllys /* Once we have the full path, we don't need the pieces */ 488530a5e8faSwyllys if (fullpath == NULL) 488630a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 488730a5e8faSwyllys 488830a5e8faSwyllys /* If the requested file exists, return an error */ 488930a5e8faSwyllys if (test_for_file(fullpath, 0400) == 1) { 489030a5e8faSwyllys free(fullpath); 489130a5e8faSwyllys return (KMF_ERR_DUPLICATE_KEYFILE); 489230a5e8faSwyllys } 489330a5e8faSwyllys 489430a5e8faSwyllys rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 489530a5e8faSwyllys &format, NULL); 489630a5e8faSwyllys if (rv != KMF_OK) 489730a5e8faSwyllys /* format is optional. */ 489830a5e8faSwyllys rv = KMF_OK; 489930a5e8faSwyllys 490030a5e8faSwyllys /* CRED is not required for OpenSSL files */ 490130a5e8faSwyllys (void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr, 490230a5e8faSwyllys &cred, NULL); 490330a5e8faSwyllys 490430a5e8faSwyllys /* Store the private key to the keyfile */ 490530a5e8faSwyllys out = BIO_new_file(fullpath, "wb"); 490630a5e8faSwyllys if (out == NULL) { 490730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 490830a5e8faSwyllys rv = KMF_ERR_OPEN_FILE; 490930a5e8faSwyllys goto end; 491030a5e8faSwyllys } 491130a5e8faSwyllys 491230a5e8faSwyllys if (prikey != NULL && prikey->keyp != NULL) { 491330a5e8faSwyllys if (prikey->keyalg == KMF_RSA || 491430a5e8faSwyllys prikey->keyalg == KMF_DSA) { 491530a5e8faSwyllys pkey = (EVP_PKEY *)prikey->keyp; 491630a5e8faSwyllys 491730a5e8faSwyllys rv = ssl_write_key(kmfh, format, 491830a5e8faSwyllys out, &cred, pkey, TRUE); 491930a5e8faSwyllys 492030a5e8faSwyllys if (rv == KMF_OK && prikey->keylabel == NULL) { 492130a5e8faSwyllys prikey->keylabel = strdup(fullpath); 492230a5e8faSwyllys if (prikey->keylabel == NULL) 492330a5e8faSwyllys rv = KMF_ERR_MEMORY; 492430a5e8faSwyllys } 492530a5e8faSwyllys } 492630a5e8faSwyllys } else if (pubkey != NULL && pubkey->keyp != NULL) { 492730a5e8faSwyllys if (pubkey->keyalg == KMF_RSA || 492830a5e8faSwyllys pubkey->keyalg == KMF_DSA) { 492930a5e8faSwyllys pkey = (EVP_PKEY *)pubkey->keyp; 493030a5e8faSwyllys 493130a5e8faSwyllys rv = ssl_write_key(kmfh, format, 493230a5e8faSwyllys out, &cred, pkey, FALSE); 493330a5e8faSwyllys 493430a5e8faSwyllys if (rv == KMF_OK && pubkey->keylabel == NULL) { 493530a5e8faSwyllys pubkey->keylabel = strdup(fullpath); 493630a5e8faSwyllys if (pubkey->keylabel == NULL) 493730a5e8faSwyllys rv = KMF_ERR_MEMORY; 493830a5e8faSwyllys } 493930a5e8faSwyllys } 494030a5e8faSwyllys } else if (rawkey != NULL) { 494130a5e8faSwyllys if (rawkey->keytype == KMF_RSA) { 494230a5e8faSwyllys pkey = ImportRawRSAKey(&rawkey->rawdata.rsa); 494330a5e8faSwyllys } else if (rawkey->keytype == KMF_DSA) { 494430a5e8faSwyllys pkey = ImportRawDSAKey(&rawkey->rawdata.dsa); 494530a5e8faSwyllys } else { 494630a5e8faSwyllys rv = KMF_ERR_BAD_PARAMETER; 494730a5e8faSwyllys } 49485b3e1433Swyllys if (pkey != NULL) { 494973cc0e02Swyllys KMF_KEY_CLASS kclass = KMF_ASYM_PRI; 495073cc0e02Swyllys 495173cc0e02Swyllys rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr, 495273cc0e02Swyllys (void *)&kclass, NULL); 495373cc0e02Swyllys if (rv != KMF_OK) 495473cc0e02Swyllys rv = KMF_OK; 49555b3e1433Swyllys rv = ssl_write_key(kmfh, format, out, 495673cc0e02Swyllys &cred, pkey, (kclass == KMF_ASYM_PRI)); 49575b3e1433Swyllys EVP_PKEY_free(pkey); 49585b3e1433Swyllys } 495930a5e8faSwyllys } 496030a5e8faSwyllys 496130a5e8faSwyllys end: 496230a5e8faSwyllys 496330a5e8faSwyllys if (out) 496430a5e8faSwyllys (void) BIO_free(out); 496530a5e8faSwyllys 49665b3e1433Swyllys 496730a5e8faSwyllys if (rv == KMF_OK) 496830a5e8faSwyllys (void) chmod(fullpath, 0400); 496930a5e8faSwyllys 497030a5e8faSwyllys free(fullpath); 497130a5e8faSwyllys return (rv); 497230a5e8faSwyllys } 497330a5e8faSwyllys 497430a5e8faSwyllys KMF_RETURN 497530a5e8faSwyllys OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 497630a5e8faSwyllys { 497730a5e8faSwyllys KMF_RETURN ret = KMF_OK; 497830a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 497930a5e8faSwyllys X509_CRL *xcrl = NULL; 498030a5e8faSwyllys X509 *xcert = NULL; 498130a5e8faSwyllys EVP_PKEY *pkey; 498230a5e8faSwyllys KMF_ENCODE_FORMAT format; 498330a5e8faSwyllys BIO *in = NULL, *out = NULL; 498430a5e8faSwyllys int openssl_ret = 0; 498530a5e8faSwyllys KMF_ENCODE_FORMAT outformat; 498630a5e8faSwyllys boolean_t crlcheck = FALSE; 498730a5e8faSwyllys char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile; 498830a5e8faSwyllys 498930a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 499030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 499130a5e8faSwyllys } 499230a5e8faSwyllys 499330a5e8faSwyllys /* CRL check is optional */ 499430a5e8faSwyllys (void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr, 499530a5e8faSwyllys &crlcheck, NULL); 499630a5e8faSwyllys 499730a5e8faSwyllys certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr); 499830a5e8faSwyllys if (crlcheck == B_TRUE && certfile == NULL) { 499930a5e8faSwyllys return (KMF_ERR_BAD_CERTFILE); 500030a5e8faSwyllys } 500130a5e8faSwyllys 500230a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 500330a5e8faSwyllys incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr); 500430a5e8faSwyllys outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr); 500530a5e8faSwyllys 500630a5e8faSwyllys crlfile = get_fullpath(dirpath, incrl); 500730a5e8faSwyllys 500830a5e8faSwyllys if (crlfile == NULL) 500930a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 501030a5e8faSwyllys 501130a5e8faSwyllys outcrlfile = get_fullpath(dirpath, outcrl); 501230a5e8faSwyllys if (outcrlfile == NULL) 501330a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 501430a5e8faSwyllys 501530a5e8faSwyllys if (isdir(outcrlfile)) { 501630a5e8faSwyllys free(outcrlfile); 501730a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 501830a5e8faSwyllys } 501930a5e8faSwyllys 502030a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 502130a5e8faSwyllys if (ret != KMF_OK) { 502230a5e8faSwyllys free(outcrlfile); 502330a5e8faSwyllys return (ret); 502430a5e8faSwyllys } 502530a5e8faSwyllys 502630a5e8faSwyllys in = BIO_new_file(crlfile, "rb"); 502730a5e8faSwyllys if (in == NULL) { 502830a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 502930a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 503030a5e8faSwyllys goto end; 503130a5e8faSwyllys } 503230a5e8faSwyllys 503330a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 503430a5e8faSwyllys xcrl = d2i_X509_CRL_bio(in, NULL); 503530a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 503630a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); 503730a5e8faSwyllys } 503830a5e8faSwyllys 503930a5e8faSwyllys if (xcrl == NULL) { 504030a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 504130a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 504230a5e8faSwyllys goto end; 504330a5e8faSwyllys } 504430a5e8faSwyllys 504530a5e8faSwyllys /* If bypasscheck is specified, no need to verify. */ 504630a5e8faSwyllys if (crlcheck == B_FALSE) 504730a5e8faSwyllys goto output; 504830a5e8faSwyllys 504930a5e8faSwyllys ret = kmf_is_cert_file(handle, certfile, &format); 505030a5e8faSwyllys if (ret != KMF_OK) 505130a5e8faSwyllys goto end; 505230a5e8faSwyllys 505330a5e8faSwyllys /* Read in the CA cert file and convert to X509 */ 505430a5e8faSwyllys if (BIO_read_filename(in, certfile) <= 0) { 505530a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 505630a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 505730a5e8faSwyllys goto end; 505830a5e8faSwyllys } 505930a5e8faSwyllys 506030a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 506130a5e8faSwyllys xcert = d2i_X509_bio(in, NULL); 506230a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 506330a5e8faSwyllys xcert = PEM_read_bio_X509(in, NULL, NULL, NULL); 506430a5e8faSwyllys } else { 506530a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 506630a5e8faSwyllys goto end; 506730a5e8faSwyllys } 506830a5e8faSwyllys 506930a5e8faSwyllys if (xcert == NULL) { 507030a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 507130a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 507230a5e8faSwyllys goto end; 507330a5e8faSwyllys } 507430a5e8faSwyllys /* Now get the public key from the CA cert */ 507530a5e8faSwyllys pkey = X509_get_pubkey(xcert); 507630a5e8faSwyllys if (pkey == NULL) { 507730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 507830a5e8faSwyllys ret = KMF_ERR_BAD_CERTFILE; 507930a5e8faSwyllys goto end; 508030a5e8faSwyllys } 508130a5e8faSwyllys 508230a5e8faSwyllys /* Verify the CRL with the CA's public key */ 508330a5e8faSwyllys openssl_ret = X509_CRL_verify(xcrl, pkey); 508430a5e8faSwyllys EVP_PKEY_free(pkey); 508530a5e8faSwyllys if (openssl_ret > 0) { 508630a5e8faSwyllys ret = KMF_OK; /* verify succeed */ 508730a5e8faSwyllys } else { 508830a5e8faSwyllys SET_ERROR(kmfh, openssl_ret); 508930a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 509030a5e8faSwyllys } 509130a5e8faSwyllys 509230a5e8faSwyllys output: 509330a5e8faSwyllys ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr, 509430a5e8faSwyllys &outformat, NULL); 509530a5e8faSwyllys if (ret != KMF_OK) { 509630a5e8faSwyllys ret = KMF_OK; 509730a5e8faSwyllys outformat = KMF_FORMAT_PEM; 509830a5e8faSwyllys } 509930a5e8faSwyllys 510030a5e8faSwyllys out = BIO_new_file(outcrlfile, "wb"); 510130a5e8faSwyllys if (out == NULL) { 510230a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 510330a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 510430a5e8faSwyllys goto end; 510530a5e8faSwyllys } 510630a5e8faSwyllys 510730a5e8faSwyllys if (outformat == KMF_FORMAT_ASN1) { 510830a5e8faSwyllys openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl); 510930a5e8faSwyllys } else if (outformat == KMF_FORMAT_PEM) { 511030a5e8faSwyllys openssl_ret = PEM_write_bio_X509_CRL(out, xcrl); 511130a5e8faSwyllys } else { 511230a5e8faSwyllys ret = KMF_ERR_BAD_PARAMETER; 511330a5e8faSwyllys goto end; 511430a5e8faSwyllys } 511530a5e8faSwyllys 511630a5e8faSwyllys if (openssl_ret <= 0) { 511730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 511830a5e8faSwyllys ret = KMF_ERR_WRITE_FILE; 511930a5e8faSwyllys } else { 512030a5e8faSwyllys ret = KMF_OK; 512130a5e8faSwyllys } 512230a5e8faSwyllys 512330a5e8faSwyllys end: 512430a5e8faSwyllys if (xcrl != NULL) 512530a5e8faSwyllys X509_CRL_free(xcrl); 512630a5e8faSwyllys 512730a5e8faSwyllys if (xcert != NULL) 512830a5e8faSwyllys X509_free(xcert); 512930a5e8faSwyllys 513030a5e8faSwyllys if (in != NULL) 513130a5e8faSwyllys (void) BIO_free(in); 513230a5e8faSwyllys 513330a5e8faSwyllys if (out != NULL) 513430a5e8faSwyllys (void) BIO_free(out); 513530a5e8faSwyllys 513630a5e8faSwyllys if (outcrlfile != NULL) 513730a5e8faSwyllys free(outcrlfile); 513830a5e8faSwyllys 513930a5e8faSwyllys return (ret); 514030a5e8faSwyllys } 514130a5e8faSwyllys 514230a5e8faSwyllys KMF_RETURN 514330a5e8faSwyllys OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 514430a5e8faSwyllys { 514530a5e8faSwyllys KMF_RETURN ret = KMF_OK; 514630a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 514730a5e8faSwyllys X509_CRL *x = NULL; 514830a5e8faSwyllys KMF_ENCODE_FORMAT format; 514930a5e8faSwyllys char *crlfile = NULL; 515030a5e8faSwyllys BIO *in = NULL; 515130a5e8faSwyllys BIO *mem = NULL; 515230a5e8faSwyllys long len; 515330a5e8faSwyllys char *memptr; 515430a5e8faSwyllys char *data = NULL; 515530a5e8faSwyllys char **crldata; 515630a5e8faSwyllys char *crlfilename, *dirpath; 515730a5e8faSwyllys 515830a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 515930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 516030a5e8faSwyllys } 516130a5e8faSwyllys crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, 516230a5e8faSwyllys attrlist, numattr); 516330a5e8faSwyllys if (crlfilename == NULL) 516430a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 516530a5e8faSwyllys 516630a5e8faSwyllys crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR, 516730a5e8faSwyllys attrlist, numattr); 516830a5e8faSwyllys 516930a5e8faSwyllys if (crldata == NULL) 517030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 517130a5e8faSwyllys 517230a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 517330a5e8faSwyllys 517430a5e8faSwyllys crlfile = get_fullpath(dirpath, crlfilename); 517530a5e8faSwyllys 517630a5e8faSwyllys if (crlfile == NULL) 517730a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 517830a5e8faSwyllys 517930a5e8faSwyllys if (isdir(crlfile)) { 518030a5e8faSwyllys free(crlfile); 518130a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 518230a5e8faSwyllys } 518330a5e8faSwyllys 518430a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 518530a5e8faSwyllys if (ret != KMF_OK) { 518630a5e8faSwyllys free(crlfile); 518730a5e8faSwyllys return (ret); 518830a5e8faSwyllys } 518930a5e8faSwyllys 519030a5e8faSwyllys if (bio_err == NULL) 519130a5e8faSwyllys bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 519230a5e8faSwyllys 519330a5e8faSwyllys in = BIO_new_file(crlfile, "rb"); 519430a5e8faSwyllys if (in == NULL) { 519530a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 519630a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 519730a5e8faSwyllys goto end; 519830a5e8faSwyllys } 519930a5e8faSwyllys 520030a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 520130a5e8faSwyllys x = d2i_X509_CRL_bio(in, NULL); 520230a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 520330a5e8faSwyllys x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); 520430a5e8faSwyllys } 520530a5e8faSwyllys 520630a5e8faSwyllys if (x == NULL) { /* should not happen */ 520730a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 520830a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 520930a5e8faSwyllys goto end; 521030a5e8faSwyllys } 521130a5e8faSwyllys 521230a5e8faSwyllys mem = BIO_new(BIO_s_mem()); 521330a5e8faSwyllys if (mem == NULL) { 521430a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 521530a5e8faSwyllys ret = KMF_ERR_MEMORY; 521630a5e8faSwyllys goto end; 521730a5e8faSwyllys } 521830a5e8faSwyllys 521930a5e8faSwyllys (void) X509_CRL_print(mem, x); 522030a5e8faSwyllys len = BIO_get_mem_data(mem, &memptr); 522130a5e8faSwyllys if (len <= 0) { 522230a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 522330a5e8faSwyllys ret = KMF_ERR_MEMORY; 522430a5e8faSwyllys goto end; 522530a5e8faSwyllys } 522630a5e8faSwyllys 522730a5e8faSwyllys data = malloc(len + 1); 522830a5e8faSwyllys if (data == NULL) { 522930a5e8faSwyllys ret = KMF_ERR_MEMORY; 523030a5e8faSwyllys goto end; 523130a5e8faSwyllys } 523230a5e8faSwyllys 523330a5e8faSwyllys (void) memcpy(data, memptr, len); 523430a5e8faSwyllys data[len] = '\0'; 523530a5e8faSwyllys *crldata = data; 523630a5e8faSwyllys 523730a5e8faSwyllys end: 523830a5e8faSwyllys if (x != NULL) 523930a5e8faSwyllys X509_CRL_free(x); 524030a5e8faSwyllys 524130a5e8faSwyllys if (crlfile != NULL) 524230a5e8faSwyllys free(crlfile); 524330a5e8faSwyllys 524430a5e8faSwyllys if (in != NULL) 524530a5e8faSwyllys (void) BIO_free(in); 524630a5e8faSwyllys 524730a5e8faSwyllys if (mem != NULL) 524830a5e8faSwyllys (void) BIO_free(mem); 524930a5e8faSwyllys 525030a5e8faSwyllys return (ret); 525130a5e8faSwyllys } 525230a5e8faSwyllys 525330a5e8faSwyllys KMF_RETURN 525430a5e8faSwyllys OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 525530a5e8faSwyllys { 525630a5e8faSwyllys KMF_RETURN ret = KMF_OK; 525730a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 525830a5e8faSwyllys KMF_ENCODE_FORMAT format; 525930a5e8faSwyllys char *crlfile = NULL; 526030a5e8faSwyllys BIO *in = NULL; 526130a5e8faSwyllys char *crlfilename, *dirpath; 526230a5e8faSwyllys 526330a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 526430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 526530a5e8faSwyllys } 526630a5e8faSwyllys 526730a5e8faSwyllys crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, 526830a5e8faSwyllys attrlist, numattr); 526930a5e8faSwyllys 527030a5e8faSwyllys if (crlfilename == NULL) 527130a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 527230a5e8faSwyllys 527330a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 527430a5e8faSwyllys 527530a5e8faSwyllys crlfile = get_fullpath(dirpath, crlfilename); 527630a5e8faSwyllys 527730a5e8faSwyllys if (crlfile == NULL) 527830a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 527930a5e8faSwyllys 528030a5e8faSwyllys if (isdir(crlfile)) { 528130a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 528230a5e8faSwyllys goto end; 528330a5e8faSwyllys } 528430a5e8faSwyllys 528530a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 528630a5e8faSwyllys if (ret != KMF_OK) 528730a5e8faSwyllys goto end; 528830a5e8faSwyllys 528930a5e8faSwyllys if (unlink(crlfile) != 0) { 529030a5e8faSwyllys SET_SYS_ERROR(kmfh, errno); 529130a5e8faSwyllys ret = KMF_ERR_INTERNAL; 529230a5e8faSwyllys goto end; 529330a5e8faSwyllys } 529430a5e8faSwyllys 529530a5e8faSwyllys end: 529630a5e8faSwyllys if (in != NULL) 529730a5e8faSwyllys (void) BIO_free(in); 529830a5e8faSwyllys if (crlfile != NULL) 529930a5e8faSwyllys free(crlfile); 530030a5e8faSwyllys 530130a5e8faSwyllys return (ret); 530230a5e8faSwyllys } 530330a5e8faSwyllys 530430a5e8faSwyllys KMF_RETURN 530530a5e8faSwyllys OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 530630a5e8faSwyllys { 530730a5e8faSwyllys KMF_RETURN ret = KMF_OK; 530830a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 530930a5e8faSwyllys KMF_ENCODE_FORMAT format; 531030a5e8faSwyllys BIO *in = NULL; 531130a5e8faSwyllys X509 *xcert = NULL; 531230a5e8faSwyllys X509_CRL *xcrl = NULL; 531330a5e8faSwyllys STACK_OF(X509_REVOKED) *revoke_stack = NULL; 531430a5e8faSwyllys X509_REVOKED *revoke; 531530a5e8faSwyllys int i; 531630a5e8faSwyllys char *crlfilename, *crlfile, *dirpath, *certfile; 531730a5e8faSwyllys 531830a5e8faSwyllys if (numattr == 0 || attrlist == NULL) { 531930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 532030a5e8faSwyllys } 532130a5e8faSwyllys 532230a5e8faSwyllys crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, 532330a5e8faSwyllys attrlist, numattr); 532430a5e8faSwyllys 532530a5e8faSwyllys if (crlfilename == NULL) 532630a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 532730a5e8faSwyllys 532830a5e8faSwyllys certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr); 532930a5e8faSwyllys if (certfile == NULL) 533030a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 533130a5e8faSwyllys 533230a5e8faSwyllys dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 533330a5e8faSwyllys 533430a5e8faSwyllys crlfile = get_fullpath(dirpath, crlfilename); 533530a5e8faSwyllys 533630a5e8faSwyllys if (crlfile == NULL) 533730a5e8faSwyllys return (KMF_ERR_BAD_CRLFILE); 533830a5e8faSwyllys 533930a5e8faSwyllys if (isdir(crlfile)) { 534030a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 534130a5e8faSwyllys goto end; 534230a5e8faSwyllys } 534330a5e8faSwyllys 534430a5e8faSwyllys ret = kmf_is_crl_file(handle, crlfile, &format); 534530a5e8faSwyllys if (ret != KMF_OK) 534630a5e8faSwyllys goto end; 534730a5e8faSwyllys 534830a5e8faSwyllys /* Read the CRL file and load it into a X509_CRL structure */ 534930a5e8faSwyllys in = BIO_new_file(crlfilename, "rb"); 535030a5e8faSwyllys if (in == NULL) { 535130a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 535230a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 535330a5e8faSwyllys goto end; 535430a5e8faSwyllys } 535530a5e8faSwyllys 535630a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 535730a5e8faSwyllys xcrl = d2i_X509_CRL_bio(in, NULL); 535830a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 535930a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); 536030a5e8faSwyllys } 536130a5e8faSwyllys 536230a5e8faSwyllys if (xcrl == NULL) { 536330a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 536430a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 536530a5e8faSwyllys goto end; 536630a5e8faSwyllys } 536730a5e8faSwyllys (void) BIO_free(in); 536830a5e8faSwyllys 536930a5e8faSwyllys /* Read the Certificate file and load it into a X509 structure */ 537030a5e8faSwyllys ret = kmf_is_cert_file(handle, certfile, &format); 537130a5e8faSwyllys if (ret != KMF_OK) 537230a5e8faSwyllys goto end; 537330a5e8faSwyllys 537430a5e8faSwyllys in = BIO_new_file(certfile, "rb"); 537530a5e8faSwyllys if (in == NULL) { 537630a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 537730a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 537830a5e8faSwyllys goto end; 537930a5e8faSwyllys } 538030a5e8faSwyllys 538130a5e8faSwyllys if (format == KMF_FORMAT_ASN1) { 538230a5e8faSwyllys xcert = d2i_X509_bio(in, NULL); 538330a5e8faSwyllys } else if (format == KMF_FORMAT_PEM) { 538430a5e8faSwyllys xcert = PEM_read_bio_X509(in, NULL, NULL, NULL); 538530a5e8faSwyllys } 538630a5e8faSwyllys 538730a5e8faSwyllys if (xcert == NULL) { 538830a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 538930a5e8faSwyllys ret = KMF_ERR_BAD_CERTFILE; 539030a5e8faSwyllys goto end; 539130a5e8faSwyllys } 539230a5e8faSwyllys 539330a5e8faSwyllys /* Check if the certificate and the CRL have same issuer */ 539430a5e8faSwyllys if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) { 539530a5e8faSwyllys ret = KMF_ERR_ISSUER; 539630a5e8faSwyllys goto end; 539730a5e8faSwyllys } 539830a5e8faSwyllys 539930a5e8faSwyllys /* Check to see if the certificate serial number is revoked */ 540030a5e8faSwyllys revoke_stack = X509_CRL_get_REVOKED(xcrl); 540130a5e8faSwyllys if (sk_X509_REVOKED_num(revoke_stack) <= 0) { 540230a5e8faSwyllys /* No revoked certificates in the CRL file */ 540330a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 540430a5e8faSwyllys ret = KMF_ERR_EMPTY_CRL; 540530a5e8faSwyllys goto end; 540630a5e8faSwyllys } 540730a5e8faSwyllys 540830a5e8faSwyllys for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) { 5409a2d4930dSDan OpenSolaris Anderson /* LINTED E_BAD_PTR_CAST_ALIGN */ 541030a5e8faSwyllys revoke = sk_X509_REVOKED_value(revoke_stack, i); 541130a5e8faSwyllys if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber, 541230a5e8faSwyllys revoke->serialNumber) == 0) { 541330a5e8faSwyllys break; 541430a5e8faSwyllys } 541530a5e8faSwyllys } 541630a5e8faSwyllys 541730a5e8faSwyllys if (i < sk_X509_REVOKED_num(revoke_stack)) { 541830a5e8faSwyllys ret = KMF_OK; 541930a5e8faSwyllys } else { 542030a5e8faSwyllys ret = KMF_ERR_NOT_REVOKED; 542130a5e8faSwyllys } 542230a5e8faSwyllys 542330a5e8faSwyllys end: 542430a5e8faSwyllys if (in != NULL) 542530a5e8faSwyllys (void) BIO_free(in); 542630a5e8faSwyllys if (xcrl != NULL) 542730a5e8faSwyllys X509_CRL_free(xcrl); 542830a5e8faSwyllys if (xcert != NULL) 542930a5e8faSwyllys X509_free(xcert); 543030a5e8faSwyllys 543130a5e8faSwyllys return (ret); 543230a5e8faSwyllys } 543330a5e8faSwyllys 543430a5e8faSwyllys KMF_RETURN 543530a5e8faSwyllys OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert) 543630a5e8faSwyllys { 543730a5e8faSwyllys KMF_RETURN ret = KMF_OK; 543830a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 543930a5e8faSwyllys BIO *bcrl = NULL; 544030a5e8faSwyllys X509_CRL *xcrl = NULL; 544130a5e8faSwyllys X509 *xcert = NULL; 544230a5e8faSwyllys EVP_PKEY *pkey; 544330a5e8faSwyllys int sslret; 544430a5e8faSwyllys KMF_ENCODE_FORMAT crl_format; 544530a5e8faSwyllys unsigned char *p; 544630a5e8faSwyllys long len; 544730a5e8faSwyllys 544830a5e8faSwyllys if (handle == NULL || crlname == NULL || tacert == NULL) { 544930a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 545030a5e8faSwyllys } 545130a5e8faSwyllys 545230a5e8faSwyllys ret = kmf_get_file_format(crlname, &crl_format); 545330a5e8faSwyllys if (ret != KMF_OK) 545430a5e8faSwyllys return (ret); 545530a5e8faSwyllys 545630a5e8faSwyllys bcrl = BIO_new_file(crlname, "rb"); 545730a5e8faSwyllys if (bcrl == NULL) { 545830a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 545930a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 546030a5e8faSwyllys goto cleanup; 546130a5e8faSwyllys } 546230a5e8faSwyllys 546330a5e8faSwyllys if (crl_format == KMF_FORMAT_ASN1) { 546430a5e8faSwyllys xcrl = d2i_X509_CRL_bio(bcrl, NULL); 546530a5e8faSwyllys } else if (crl_format == KMF_FORMAT_PEM) { 546630a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL); 546730a5e8faSwyllys } else { 546830a5e8faSwyllys ret = KMF_ERR_BAD_PARAMETER; 546930a5e8faSwyllys goto cleanup; 547030a5e8faSwyllys } 547130a5e8faSwyllys 547230a5e8faSwyllys if (xcrl == NULL) { 547330a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 547430a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 547530a5e8faSwyllys goto cleanup; 547630a5e8faSwyllys } 547730a5e8faSwyllys 547830a5e8faSwyllys p = tacert->Data; 547930a5e8faSwyllys len = tacert->Length; 548030a5e8faSwyllys xcert = d2i_X509(NULL, (const uchar_t **)&p, len); 548130a5e8faSwyllys 548230a5e8faSwyllys if (xcert == NULL) { 548330a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 548430a5e8faSwyllys ret = KMF_ERR_BAD_CERTFILE; 548530a5e8faSwyllys goto cleanup; 548630a5e8faSwyllys } 548730a5e8faSwyllys 548830a5e8faSwyllys /* Get issuer certificate public key */ 548930a5e8faSwyllys pkey = X509_get_pubkey(xcert); 549030a5e8faSwyllys if (pkey == NULL) { 549130a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 549230a5e8faSwyllys ret = KMF_ERR_BAD_CERT_FORMAT; 549330a5e8faSwyllys goto cleanup; 549430a5e8faSwyllys } 549530a5e8faSwyllys 549630a5e8faSwyllys /* Verify CRL signature */ 549730a5e8faSwyllys sslret = X509_CRL_verify(xcrl, pkey); 549830a5e8faSwyllys EVP_PKEY_free(pkey); 549930a5e8faSwyllys if (sslret > 0) { 550030a5e8faSwyllys ret = KMF_OK; 550130a5e8faSwyllys } else { 550230a5e8faSwyllys SET_ERROR(kmfh, sslret); 550330a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 550430a5e8faSwyllys } 550530a5e8faSwyllys 550630a5e8faSwyllys cleanup: 550730a5e8faSwyllys if (bcrl != NULL) 550830a5e8faSwyllys (void) BIO_free(bcrl); 550930a5e8faSwyllys 551030a5e8faSwyllys if (xcrl != NULL) 551130a5e8faSwyllys X509_CRL_free(xcrl); 551230a5e8faSwyllys 551330a5e8faSwyllys if (xcert != NULL) 551430a5e8faSwyllys X509_free(xcert); 551530a5e8faSwyllys 551630a5e8faSwyllys return (ret); 551730a5e8faSwyllys 551830a5e8faSwyllys } 551930a5e8faSwyllys 552030a5e8faSwyllys KMF_RETURN 552130a5e8faSwyllys OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname) 552230a5e8faSwyllys { 552330a5e8faSwyllys KMF_RETURN ret = KMF_OK; 552430a5e8faSwyllys KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 552530a5e8faSwyllys KMF_ENCODE_FORMAT crl_format; 552630a5e8faSwyllys BIO *bcrl = NULL; 552730a5e8faSwyllys X509_CRL *xcrl = NULL; 552830a5e8faSwyllys int i; 552930a5e8faSwyllys 553030a5e8faSwyllys if (handle == NULL || crlname == NULL) { 553130a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER); 553230a5e8faSwyllys } 553330a5e8faSwyllys 553430a5e8faSwyllys ret = kmf_is_crl_file(handle, crlname, &crl_format); 553530a5e8faSwyllys if (ret != KMF_OK) 553630a5e8faSwyllys return (ret); 553730a5e8faSwyllys 553830a5e8faSwyllys bcrl = BIO_new_file(crlname, "rb"); 553930a5e8faSwyllys if (bcrl == NULL) { 554030a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 554130a5e8faSwyllys ret = KMF_ERR_OPEN_FILE; 554230a5e8faSwyllys goto cleanup; 554330a5e8faSwyllys } 554430a5e8faSwyllys 55455b3e1433Swyllys if (crl_format == KMF_FORMAT_ASN1) 554630a5e8faSwyllys xcrl = d2i_X509_CRL_bio(bcrl, NULL); 55475b3e1433Swyllys else if (crl_format == KMF_FORMAT_PEM) 554830a5e8faSwyllys xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL); 554930a5e8faSwyllys 555030a5e8faSwyllys if (xcrl == NULL) { 555130a5e8faSwyllys SET_ERROR(kmfh, ERR_get_error()); 555230a5e8faSwyllys ret = KMF_ERR_BAD_CRLFILE; 555330a5e8faSwyllys goto cleanup; 555430a5e8faSwyllys } 555530a5e8faSwyllys i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL); 555630a5e8faSwyllys if (i >= 0) { 555730a5e8faSwyllys ret = KMF_ERR_VALIDITY_PERIOD; 555830a5e8faSwyllys goto cleanup; 555930a5e8faSwyllys } 556030a5e8faSwyllys if (X509_CRL_get_nextUpdate(xcrl)) { 556130a5e8faSwyllys i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL); 556230a5e8faSwyllys 556330a5e8faSwyllys if (i <= 0) { 556430a5e8faSwyllys ret = KMF_ERR_VALIDITY_PERIOD; 556530a5e8faSwyllys goto cleanup; 556630a5e8faSwyllys } 556730a5e8faSwyllys } 556830a5e8faSwyllys 556930a5e8faSwyllys ret = KMF_OK; 557030a5e8faSwyllys 557130a5e8faSwyllys cleanup: 557230a5e8faSwyllys if (bcrl != NULL) 557330a5e8faSwyllys (void) BIO_free(bcrl); 557430a5e8faSwyllys 557530a5e8faSwyllys if (xcrl != NULL) 557630a5e8faSwyllys X509_CRL_free(xcrl); 557730a5e8faSwyllys 557830a5e8faSwyllys return (ret); 557930a5e8faSwyllys } 5580