/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c
C | 5597 lines | 4351 code | 798 blank | 448 comment | 1726 complexity | fe51d8c69f60cf4bf7241d0037c1e994 MD5 | raw file
Possible License(s): LGPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, MPL-2.0-no-copyleft-exception, AGPL-1.0, GPL-3.0, LGPL-3.0, BSD-2-Clause, AGPL-3.0, BSD-3-Clause, GPL-2.0, LGPL-2.1, 0BSD
Large files files are truncated, but you can click here to view the full file
- /*
- * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
- *
- * Use is subject to license terms.
- */
- /*
- * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
- */
- /*
- * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
- * project 2000.
- */
- /*
- * ====================================================================
- * Copyright (c) 2000-2004 The OpenSSL Project. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission. For written permission, please contact
- * licensing@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- * nor may "OpenSSL" appear in their names without prior written
- * permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com). This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
- *
- */
- #include <stdlib.h>
- #include <kmfapiP.h>
- #include <ber_der.h>
- #include <fcntl.h>
- #include <sys/stat.h>
- #include <dirent.h>
- #include <cryptoutil.h>
- #include <synch.h>
- #include <thread.h>
- /* OPENSSL related headers */
- #include <openssl/bio.h>
- #include <openssl/bn.h>
- #include <openssl/asn1.h>
- #include <openssl/err.h>
- #include <openssl/bn.h>
- #include <openssl/x509.h>
- #include <openssl/rsa.h>
- #include <openssl/dsa.h>
- #include <openssl/x509v3.h>
- #include <openssl/objects.h>
- #include <openssl/pem.h>
- #include <openssl/pkcs12.h>
- #include <openssl/ocsp.h>
- #include <openssl/des.h>
- #include <openssl/rand.h>
- #define PRINT_ANY_EXTENSION (\
- KMF_X509_EXT_KEY_USAGE |\
- KMF_X509_EXT_CERT_POLICIES |\
- KMF_X509_EXT_SUBJALTNAME |\
- KMF_X509_EXT_BASIC_CONSTRAINTS |\
- KMF_X509_EXT_NAME_CONSTRAINTS |\
- KMF_X509_EXT_POLICY_CONSTRAINTS |\
- KMF_X509_EXT_EXT_KEY_USAGE |\
- KMF_X509_EXT_INHIBIT_ANY_POLICY |\
- KMF_X509_EXT_AUTH_KEY_ID |\
- KMF_X509_EXT_SUBJ_KEY_ID |\
- KMF_X509_EXT_POLICY_MAPPING)
- static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
- 0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
- 0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
- 0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
- 0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
- 0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
- 0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
- 0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
- 0x91 };
- static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
- 0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
- 0x8e, 0xda, 0xce, 0x91, 0x5f };
- static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
- 0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
- 0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
- 0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
- 0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
- 0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
- 0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
- 0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
- 0x02 };
- #define SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
- h->lasterr.errcode = c;
- #define SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
- /*
- * Declare some new macros for managing stacks of EVP_PKEYS, similar to
- * what wanboot did.
- */
- DECLARE_STACK_OF(EVP_PKEY)
- #define sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
- #define sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
- #define sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
- #define sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
- #define sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
- #define sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
- (free_func))
- mutex_t init_lock = DEFAULTMUTEX;
- static int ssl_initialized = 0;
- static BIO *bio_err = NULL;
- static int
- test_for_file(char *, mode_t);
- static KMF_RETURN
- openssl_parse_bag(PKCS12_SAFEBAG *, char *, int,
- STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
- static KMF_RETURN
- local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *,
- int, KMF_KEY_HANDLE *, char *);
- static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int);
- static KMF_RETURN
- extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *,
- CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
- static KMF_RETURN
- kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
- char *, KMF_DATA *);
- static KMF_RETURN
- load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
- char *, KMF_DATA **, uint32_t *);
- static KMF_RETURN
- sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
- static EVP_PKEY *
- ImportRawRSAKey(KMF_RAW_RSA_KEY *);
- static KMF_RETURN
- convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
- KMF_RETURN
- OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
- void
- OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
- KMF_RETURN
- OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
- KMF_RETURN
- OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
- KMF_RETURN
- OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
- KMF_RETURN
- OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
- KMF_RETURN
- OpenSSL_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *);
- KMF_RETURN
- OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
- KMF_DATA *, KMF_DATA *);
- KMF_RETURN
- OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
- KMF_RETURN
- OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
- KMF_RETURN
- OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
- KMF_RETURN
- OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
- KMF_RETURN
- OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
- KMF_RETURN
- OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
- KMF_PRINTABLE_ITEM, char *);
- KMF_RETURN
- OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
- KMF_RETURN
- OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
- KMF_RETURN
- OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
- KMF_DATA *, KMF_DATA *);
- KMF_RETURN
- OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
- KMF_RETURN
- OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
- KMF_RETURN
- OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
- KMF_RETURN
- OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
- KMF_RETURN
- OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
- KMF_RETURN
- OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
- KMF_RETURN
- OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
- KMF_RETURN
- OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
- static
- KMF_PLUGIN_FUNCLIST openssl_plugin_table =
- {
- 1, /* Version */
- NULL, /* ConfigureKeystore */
- OpenSSL_FindCert,
- OpenSSL_FreeKMFCert,
- OpenSSL_StoreCert,
- NULL, /* ImportCert */
- OpenSSL_ImportCRL,
- OpenSSL_DeleteCert,
- OpenSSL_DeleteCRL,
- OpenSSL_CreateKeypair,
- OpenSSL_FindKey,
- OpenSSL_EncodePubKeyData,
- OpenSSL_SignData,
- OpenSSL_DeleteKey,
- OpenSSL_ListCRL,
- NULL, /* FindCRL */
- OpenSSL_FindCertInCRL,
- OpenSSL_GetErrorString,
- OpenSSL_FindPrikeyByCert,
- OpenSSL_DecryptData,
- OpenSSL_ExportPK12,
- OpenSSL_CreateSymKey,
- OpenSSL_GetSymKeyValue,
- NULL, /* SetTokenPin */
- OpenSSL_StoreKey,
- NULL /* Finalize */
- };
- static mutex_t *lock_cs;
- static long *lock_count;
- static void
- /* ARGSUSED1 */
- locking_cb(int mode, int type, char *file, int line)
- {
- if (mode & CRYPTO_LOCK) {
- (void) mutex_lock(&(lock_cs[type]));
- lock_count[type]++;
- } else {
- (void) mutex_unlock(&(lock_cs[type]));
- }
- }
- static unsigned long
- thread_id()
- {
- return ((unsigned long)thr_self());
- }
- KMF_PLUGIN_FUNCLIST *
- KMF_Plugin_Initialize()
- {
- int i;
- (void) mutex_lock(&init_lock);
- if (!ssl_initialized) {
- /*
- * Add support for extension OIDs that are not yet in the
- * openssl default set.
- */
- (void) OBJ_create("2.5.29.30", "nameConstraints",
- "X509v3 Name Constraints");
- (void) OBJ_create("2.5.29.33", "policyMappings",
- "X509v3 Policy Mappings");
- (void) OBJ_create("2.5.29.36", "policyConstraints",
- "X509v3 Policy Constraints");
- (void) OBJ_create("2.5.29.46", "freshestCRL",
- "X509v3 Freshest CRL");
- (void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
- "X509v3 Inhibit Any-Policy");
- /*
- * Set up for thread-safe operation.
- */
- lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
- if (lock_cs == NULL) {
- (void) mutex_unlock(&init_lock);
- return (NULL);
- }
- lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
- if (lock_count == NULL) {
- OPENSSL_free(lock_cs);
- (void) mutex_unlock(&init_lock);
- return (NULL);
- }
- for (i = 0; i < CRYPTO_num_locks(); i++) {
- lock_count[i] = 0;
- (void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
- }
- CRYPTO_set_id_callback((unsigned long (*)())thread_id);
- if (CRYPTO_get_locking_callback() == NULL)
- CRYPTO_set_locking_callback((void (*)())locking_cb);
- OpenSSL_add_all_algorithms();
- /* Enable error strings for reporting */
- ERR_load_crypto_strings();
- ssl_initialized = 1;
- }
- (void) mutex_unlock(&init_lock);
- return (&openssl_plugin_table);
- }
- /*
- * Convert an SSL DN to a KMF DN.
- */
- static KMF_RETURN
- get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
- {
- KMF_DATA derdata;
- KMF_RETURN rv = KMF_OK;
- uchar_t *tmp;
- /* Convert to raw DER format */
- derdata.Length = i2d_X509_NAME(sslDN, NULL);
- if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
- == NULL) {
- return (KMF_ERR_MEMORY);
- }
- (void) i2d_X509_NAME(sslDN, &tmp);
- /* Decode to KMF format */
- rv = DerDecodeName(&derdata, kmfDN);
- if (rv != KMF_OK) {
- rv = KMF_ERR_BAD_CERT_FORMAT;
- }
- OPENSSL_free(derdata.Data);
- return (rv);
- }
- int
- isdir(char *path)
- {
- struct stat s;
- if (stat(path, &s) == -1)
- return (0);
- return ((s.st_mode & S_IFMT) == S_IFDIR);
- }
- static KMF_RETURN
- ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
- {
- KMF_RETURN rv = KMF_OK;
- unsigned char *buf = NULL, *p;
- int len;
- /*
- * Convert the X509 internal struct to DER encoded data
- */
- if ((len = i2d_X509(x509cert, NULL)) < 0) {
- SET_ERROR(kmfh, ERR_get_error());
- rv = KMF_ERR_BAD_CERT_FORMAT;
- goto cleanup;
- }
- if ((buf = malloc(len)) == NULL) {
- SET_SYS_ERROR(kmfh, errno);
- rv = KMF_ERR_MEMORY;
- goto cleanup;
- }
- /*
- * i2d_X509 will increment the buf pointer so that we need to
- * save it.
- */
- p = buf;
- if ((len = i2d_X509(x509cert, &p)) < 0) {
- SET_ERROR(kmfh, ERR_get_error());
- free(buf);
- rv = KMF_ERR_BAD_CERT_FORMAT;
- goto cleanup;
- }
- /* caller's responsibility to free it */
- cert->Data = buf;
- cert->Length = len;
- cleanup:
- if (rv != KMF_OK) {
- if (buf)
- free(buf);
- cert->Data = NULL;
- cert->Length = 0;
- }
- return (rv);
- }
- static KMF_RETURN
- check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
- boolean_t *match)
- {
- KMF_RETURN rv = KMF_OK;
- boolean_t findIssuer = FALSE;
- boolean_t findSubject = FALSE;
- boolean_t findSerial = FALSE;
- KMF_X509_NAME issuerDN, subjectDN;
- KMF_X509_NAME certIssuerDN, certSubjectDN;
- *match = FALSE;
- if (xcert == NULL) {
- return (KMF_ERR_BAD_PARAMETER);
- }
- (void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
- (void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
- (void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
- (void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
- if (issuer != NULL && strlen(issuer)) {
- rv = kmf_dn_parser(issuer, &issuerDN);
- if (rv != KMF_OK)
- return (KMF_ERR_BAD_PARAMETER);
- rv = get_x509_dn(xcert->cert_info->issuer, &certIssuerDN);
- if (rv != KMF_OK) {
- kmf_free_dn(&issuerDN);
- return (KMF_ERR_BAD_PARAMETER);
- }
- findIssuer = TRUE;
- }
- if (subject != NULL && strlen(subject)) {
- rv = kmf_dn_parser(subject, &subjectDN);
- if (rv != KMF_OK) {
- rv = KMF_ERR_BAD_PARAMETER;
- goto cleanup;
- }
- rv = get_x509_dn(xcert->cert_info->subject, &certSubjectDN);
- if (rv != KMF_OK) {
- rv = KMF_ERR_BAD_PARAMETER;
- goto cleanup;
- }
- findSubject = TRUE;
- }
- if (serial != NULL && serial->val != NULL)
- findSerial = TRUE;
- if (findSerial) {
- BIGNUM *bn;
- /* Comparing BIGNUMs is a pain! */
- bn = ASN1_INTEGER_to_BN(xcert->cert_info->serialNumber, NULL);
- if (bn != NULL) {
- int bnlen = BN_num_bytes(bn);
- if (bnlen == serial->len) {
- uchar_t *a = malloc(bnlen);
- if (a == NULL) {
- rv = KMF_ERR_MEMORY;
- BN_free(bn);
- goto cleanup;
- }
- bnlen = BN_bn2bin(bn, a);
- *match = (memcmp(a, serial->val, serial->len) ==
- 0);
- rv = KMF_OK;
- free(a);
- }
- BN_free(bn);
- if (!(*match))
- goto cleanup;
- } else {
- rv = KMF_OK;
- goto cleanup;
- }
- }
- if (findIssuer) {
- *match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
- if ((*match) == B_FALSE) {
- /* stop checking and bail */
- rv = KMF_OK;
- goto cleanup;
- }
- }
- if (findSubject) {
- *match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
- if ((*match) == B_FALSE) {
- /* stop checking and bail */
- rv = KMF_OK;
- goto cleanup;
- }
- }
- *match = TRUE;
- cleanup:
- if (findIssuer) {
- kmf_free_dn(&issuerDN);
- kmf_free_dn(&certIssuerDN);
- }
- if (findSubject) {
- kmf_free_dn(&subjectDN);
- kmf_free_dn(&certSubjectDN);
- }
- return (rv);
- }
- /*
- * This function loads a certificate file into an X509 data structure, and
- * checks if its issuer, subject or the serial number matches with those
- * values. If it matches, then return the X509 data structure.
- */
- static KMF_RETURN
- load_X509cert(KMF_HANDLE *kmfh,
- char *issuer, char *subject, KMF_BIGINT *serial,
- char *pathname, X509 **outcert)
- {
- KMF_RETURN rv = KMF_OK;
- X509 *xcert = NULL;
- BIO *bcert = NULL;
- boolean_t match = FALSE;
- KMF_ENCODE_FORMAT format;
- /*
- * auto-detect the file format, regardless of what
- * the 'format' parameters in the params say.
- */
- rv = kmf_get_file_format(pathname, &format);
- if (rv != KMF_OK) {
- if (rv == KMF_ERR_OPEN_FILE)
- rv = KMF_ERR_CERT_NOT_FOUND;
- return (rv);
- }
- /* Not ASN1(DER) format */
- if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
- SET_ERROR(kmfh, ERR_get_error());
- rv = KMF_ERR_OPEN_FILE;
- goto cleanup;
- }
- if (format == KMF_FORMAT_PEM)
- xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
- else if (format == KMF_FORMAT_ASN1)
- xcert = d2i_X509_bio(bcert, NULL);
- else if (format == KMF_FORMAT_PKCS12) {
- PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
- if (p12 != NULL) {
- (void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
- PKCS12_free(p12);
- p12 = NULL;
- } else {
- SET_ERROR(kmfh, ERR_get_error());
- rv = KMF_ERR_BAD_CERT_FORMAT;
- }
- } else {
- rv = KMF_ERR_BAD_PARAMETER;
- goto cleanup;
- }
- if (xcert == NULL) {
- SET_ERROR(kmfh, ERR_get_error());
- rv = KMF_ERR_BAD_CERT_FORMAT;
- goto cleanup;
- }
- if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
- match == FALSE) {
- rv = KMF_ERR_CERT_NOT_FOUND;
- goto cleanup;
- }
- if (outcert != NULL) {
- *outcert = xcert;
- }
- cleanup:
- if (bcert != NULL) (void) BIO_free(bcert);
- if (rv != KMF_OK && xcert != NULL)
- X509_free(xcert);
- return (rv);
- }
- static int
- datacmp(const void *a, const void *b)
- {
- KMF_DATA *adata = (KMF_DATA *)a;
- KMF_DATA *bdata = (KMF_DATA *)b;
- if (adata->Length > bdata->Length)
- return (-1);
- if (adata->Length < bdata->Length)
- return (1);
- return (0);
- }
- static KMF_RETURN
- load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
- KMF_CERT_VALIDITY validity, char *pathname,
- KMF_DATA **certlist, uint32_t *numcerts)
- {
- KMF_RETURN rv = KMF_OK;
- int i;
- KMF_DATA *certs = NULL;
- int nc = 0;
- int hits = 0;
- KMF_ENCODE_FORMAT format;
- rv = kmf_get_file_format(pathname, &format);
- if (rv != KMF_OK) {
- if (rv == KMF_ERR_OPEN_FILE)
- rv = KMF_ERR_CERT_NOT_FOUND;
- return (rv);
- }
- if (format == KMF_FORMAT_ASN1) {
- /* load a single certificate */
- certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
- if (certs == NULL)
- return (KMF_ERR_MEMORY);
- certs->Data = NULL;
- certs->Length = 0;
- rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
- pathname, certs);
- if (rv == KMF_OK) {
- *certlist = certs;
- *numcerts = 1;
- } else {
- kmf_free_data(certs);
- free(certs);
- certs = NULL;
- }
- return (rv);
- } else if (format == KMF_FORMAT_PKCS12) {
- /* We need a credential to access a PKCS#12 file */
- rv = KMF_ERR_BAD_CERT_FORMAT;
- } else if (format == KMF_FORMAT_PEM ||
- format != KMF_FORMAT_PEM_KEYPAIR) {
- /* This function only works on PEM files */
- rv = extract_pem(kmfh, issuer, subject, serial, pathname,
- (uchar_t *)NULL, 0, NULL, &certs, &nc);
- } else {
- return (KMF_ERR_ENCODING);
- }
- if (rv != KMF_OK)
- return (rv);
- for (i = 0; i < nc; i++) {
- if (validity == KMF_NONEXPIRED_CERTS) {
- rv = kmf_check_cert_date(kmfh, &certs[i]);
- } else if (validity == KMF_EXPIRED_CERTS) {
- rv = kmf_check_cert_date(kmfh, &certs[i]);
- if (rv == KMF_OK)
- rv = KMF_ERR_CERT_NOT_FOUND;
- if (rv == KMF_ERR_VALIDITY_PERIOD)
- rv = KMF_OK;
- }
- if (rv != KMF_OK) {
- /* Remove this cert from the list by clearing it. */
- kmf_free_data(&certs[i]);
- } else {
- hits++; /* count valid certs found */
- }
- rv = KMF_OK;
- }
- if (rv == KMF_OK && hits > 0) {
- /*
- * Sort the list of certs by length to put the cleared ones
- * at the end so they don't get accessed by the caller.
- */
- qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
- *certlist = certs;
- /* since we sorted the list, just return the number of hits */
- *numcerts = hits;
- } else {
- if (rv == KMF_OK && hits == 0)
- rv = KMF_ERR_CERT_NOT_FOUND;
- if (certs != NULL) {
- free(certs);
- certs = NULL;
- }
- }
- return (rv);
- }
- static KMF_RETURN
- kmf_load_cert(KMF_HANDLE *kmfh,
- char *issuer, char *subject, KMF_BIGINT *serial,
- KMF_CERT_VALIDITY validity,
- char *pathname,
- KMF_DATA *cert)
- {
- KMF_RETURN rv = KMF_OK;
- X509 *x509cert = NULL;
- rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
- if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
- rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
- if (rv != KMF_OK) {
- goto cleanup;
- }
- if (validity == KMF_NONEXPIRED_CERTS) {
- rv = kmf_check_cert_date(kmfh, cert);
- } else if (validity == KMF_EXPIRED_CERTS) {
- rv = kmf_check_cert_date(kmfh, cert);
- if (rv == KMF_OK) {
- /*
- * This is a valid cert so skip it.
- */
- rv = KMF_ERR_CERT_NOT_FOUND;
- }
- if (rv == KMF_ERR_VALIDITY_PERIOD) {
- /*
- * We want to return success when we
- * find an invalid cert.
- */
- rv = KMF_OK;
- goto cleanup;
- }
- }
- }
- cleanup:
- if (x509cert != NULL)
- X509_free(x509cert);
- return (rv);
- }
- static KMF_RETURN
- readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
- {
- KMF_RETURN ret = KMF_OK;
- KMF_RAW_RSA_KEY rsa;
- BerElement *asn1 = NULL;
- BerValue filebuf;
- BerValue OID = { NULL, 0 };
- BerValue *Mod = NULL, *PubExp = NULL;
- BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
- BerValue *Coef = NULL;
- BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
- BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
- BIGNUM *qminus1 = NULL;
- BN_CTX *ctx = NULL;
- *pkey = NULL;
- filebuf.bv_val = (char *)filedata->Data;
- filebuf.bv_len = filedata->Length;
- asn1 = kmfder_init(&filebuf);
- if (asn1 == NULL) {
- ret = KMF_ERR_MEMORY;
- goto out;
- }
- if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
- &OID, &Mod, &PubExp, &PriExp, &Prime1,
- &Prime2, &Coef) == -1) {
- ret = KMF_ERR_ENCODING;
- goto out;
- }
- /*
- * We have to derive the 2 Exponents using Bignumber math.
- * Exp1 = PriExp mod (Prime1 - 1)
- * Exp2 = PriExp mod (Prime2 - 1)
- */
- /* D = PrivateExponent */
- D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
- if (D == NULL) {
- ret = KMF_ERR_MEMORY;
- goto out;
- }
- /* P = Prime1 (first prime factor of Modulus) */
- P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
- if (D == NULL) {
- ret = KMF_ERR_MEMORY;
- goto out;
- }
- /* Q = Prime2 (second prime factor of Modulus) */
- Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
- if ((ctx = BN_CTX_new()) == NULL) {
- ret = KMF_ERR_MEMORY;
- goto out;
- }
- /* Compute (P - 1) */
- pminus1 = BN_new();
- (void) BN_sub(pminus1, P, BN_value_one());
- /* Exponent1 = D mod (P - 1) */
- Exp1 = BN_new();
- (void) BN_mod(Exp1, D, pminus1, ctx);
- /* Compute (Q - 1) */
- qminus1 = BN_new();
- (void) BN_sub(qminus1, Q, BN_value_one());
- /* Exponent2 = D mod (Q - 1) */
- Exp2 = BN_new();
- (void) BN_mod(Exp2, D, qminus1, ctx);
- /* Coef = (Inverse Q) mod P */
- COEF = BN_new();
- (void) BN_mod_inverse(COEF, Q, P, ctx);
- /* Convert back to KMF format */
- (void) memset(&rsa, 0, sizeof (rsa));
- if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
- goto out;
- if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
- goto out;
- if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
- goto out;
- rsa.mod.val = (uchar_t *)Mod->bv_val;
- rsa.mod.len = Mod->bv_len;
- rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
- rsa.pubexp.len = PubExp->bv_len;
- rsa.priexp.val = (uchar_t *)PriExp->bv_val;
- rsa.priexp.len = PriExp->bv_len;
- rsa.prime1.val = (uchar_t *)Prime1->bv_val;
- rsa.prime1.len = Prime1->bv_len;
- rsa.prime2.val = (uchar_t *)Prime2->bv_val;
- rsa.prime2.len = Prime2->bv_len;
- *pkey = ImportRawRSAKey(&rsa);
- out:
- if (asn1 != NULL)
- kmfber_free(asn1, 1);
- if (OID.bv_val) {
- free(OID.bv_val);
- }
- if (PriExp)
- free(PriExp);
- if (Mod)
- free(Mod);
- if (PubExp)
- free(PubExp);
- if (Coef) {
- (void) memset(Coef->bv_val, 0, Coef->bv_len);
- free(Coef->bv_val);
- free(Coef);
- }
- if (Prime1)
- free(Prime1);
- if (Prime2)
- free(Prime2);
- if (ctx != NULL)
- BN_CTX_free(ctx);
- if (D)
- BN_clear_free(D);
- if (P)
- BN_clear_free(P);
- if (Q)
- BN_clear_free(Q);
- if (pminus1)
- BN_clear_free(pminus1);
- if (qminus1)
- BN_clear_free(qminus1);
- if (Exp1)
- BN_clear_free(Exp1);
- if (Exp2)
- BN_clear_free(Exp2);
- return (ret);
- }
- static EVP_PKEY *
- openssl_load_key(KMF_HANDLE_T handle, const char *file)
- {
- BIO *keyfile = NULL;
- EVP_PKEY *pkey = NULL;
- KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
- KMF_ENCODE_FORMAT format;
- KMF_RETURN rv;
- KMF_DATA filedata;
- if (file == NULL) {
- return (NULL);
- }
- if (kmf_get_file_format((char *)file, &format) != KMF_OK)
- return (NULL);
- keyfile = BIO_new_file(file, "rb");
- if (keyfile == NULL) {
- goto end;
- }
- if (format == KMF_FORMAT_ASN1) {
- pkey = d2i_PrivateKey_bio(keyfile, NULL);
- if (pkey == NULL) {
- (void) BIO_free(keyfile);
- keyfile = NULL;
- /* Try odd ASN.1 variations */
- rv = kmf_read_input_file(kmfh, (char *)file,
- &filedata);
- if (rv == KMF_OK) {
- (void) readAltFormatPrivateKey(&filedata,
- &pkey);
- kmf_free_data(&filedata);
- }
- }
- } else if (format == KMF_FORMAT_PEM ||
- format == KMF_FORMAT_PEM_KEYPAIR) {
- pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
- if (pkey == NULL) {
- KMF_DATA derdata;
- /*
- * Check if this is the alt. format
- * RSA private key file.
- */
- rv = kmf_read_input_file(kmfh, (char *)file,
- &filedata);
- if (rv == KMF_OK) {
- uchar_t *d = NULL;
- int len;
- rv = kmf_pem_to_der(filedata.Data,
- filedata.Length, &d, &len);
- if (rv == KMF_OK && d != NULL) {
- derdata.Data = d;
- derdata.Length = (size_t)len;
- (void) readAltFormatPrivateKey(
- &derdata, &pkey);
- free(d);
- }
- kmf_free_data(&filedata);
- }
- }
- }
- end:
- if (pkey == NULL)
- SET_ERROR(kmfh, ERR_get_error());
- if (keyfile != NULL)
- (void) BIO_free(keyfile);
- return (pkey);
- }
- KMF_RETURN
- OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
- {
- KMF_RETURN rv = KMF_OK;
- KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
- int i, n;
- uint32_t maxcerts = 0;
- uint32_t *num_certs;
- KMF_X509_DER_CERT *kmf_cert = NULL;
- char *dirpath = NULL;
- char *filename = NULL;
- char *fullpath = NULL;
- char *issuer = NULL;
- char *subject = NULL;
- KMF_BIGINT *serial = NULL;
- KMF_CERT_VALIDITY validity;
- num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
- if (num_certs == NULL)
- return (KMF_ERR_BAD_PARAMETER);
- /* num_certs should reference the size of kmf_cert */
- maxcerts = *num_certs;
- if (maxcerts == 0)
- maxcerts = 0xFFFFFFFF;
- *num_certs = 0;
- /* Get the optional returned certificate list */
- kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
- numattr);
- /*
- * The dirpath attribute and the filename attribute can not be NULL
- * at the same time.
- */
- dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
- filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
- numattr);
- fullpath = get_fullpath(dirpath, filename);
- if (fullpath == NULL)
- return (KMF_ERR_BAD_PARAMETER);
- /* Get optional search criteria attributes */
- issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
- subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
- serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
- rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
- &validity, NULL);
- if (rv != KMF_OK) {
- validity = KMF_ALL_CERTS;
- rv = KMF_OK;
- }
- if (isdir(fullpath)) {
- DIR *dirp;
- struct dirent *dp;
- n = 0;
- /* open all files in the directory and attempt to read them */
- if ((dirp = opendir(fullpath)) == NULL) {
- return (KMF_ERR_BAD_PARAMETER);
- }
- while ((dp = readdir(dirp)) != NULL) {
- char *fname;
- KMF_DATA *certlist = NULL;
- uint32_t loaded_certs = 0;
- if (strcmp(dp->d_name, ".") == 0 ||
- strcmp(dp->d_name, "..") == 0)
- continue;
- fname = get_fullpath(fullpath, (char *)&dp->d_name);
- rv = load_certs(kmfh, issuer, subject, serial,
- validity, fname, &certlist, &loaded_certs);
- if (rv != KMF_OK) {
- free(fname);
- if (certlist != NULL) {
- for (i = 0; i < loaded_certs; i++)
- kmf_free_data(&certlist[i]);
- free(certlist);
- }
- continue;
- }
- /* If load succeeds, add certdata to the list */
- if (kmf_cert != NULL) {
- for (i = 0; i < loaded_certs &&
- n < maxcerts; i++) {
- kmf_cert[n].certificate.Data =
- certlist[i].Data;
- kmf_cert[n].certificate.Length =
- certlist[i].Length;
- kmf_cert[n].kmf_private.keystore_type =
- KMF_KEYSTORE_OPENSSL;
- kmf_cert[n].kmf_private.flags =
- KMF_FLAG_CERT_VALID;
- kmf_cert[n].kmf_private.label =
- strdup(fname);
- n++;
- }
- /*
- * If maxcerts < loaded_certs, clean up the
- * certs that were not used.
- */
- for (; i < loaded_certs; i++)
- kmf_free_data(&certlist[i]);
- } else {
- for (i = 0; i < loaded_certs; i++)
- kmf_free_data(&certlist[i]);
- n += loaded_certs;
- }
- free(certlist);
- free(fname);
- }
- (*num_certs) = n;
- if (*num_certs == 0)
- rv = KMF_ERR_CERT_NOT_FOUND;
- if (*num_certs > 0)
- rv = KMF_OK;
- exit:
- (void) closedir(dirp);
- } else {
- KMF_DATA *certlist = NULL;
- uint32_t loaded_certs = 0;
- rv = load_certs(kmfh, issuer, subject, serial, validity,
- fullpath, &certlist, &loaded_certs);
- if (rv != KMF_OK) {
- free(fullpath);
- return (rv);
- }
- n = 0;
- if (kmf_cert != NULL && certlist != NULL) {
- for (i = 0; i < loaded_certs && i < maxcerts; i++) {
- kmf_cert[n].certificate.Data =
- certlist[i].Data;
- kmf_cert[n].certificate.Length =
- certlist[i].Length;
- kmf_cert[n].kmf_private.keystore_type =
- KMF_KEYSTORE_OPENSSL;
- kmf_cert[n].kmf_private.flags =
- KMF_FLAG_CERT_VALID;
- kmf_cert[n].kmf_private.label =
- strdup(fullpath);
- n++;
- }
- /* If maxcerts < loaded_certs, clean up */
- for (; i < loaded_certs; i++)
- kmf_free_data(&certlist[i]);
- } else if (certlist != NULL) {
- for (i = 0; i < loaded_certs; i++)
- kmf_free_data(&certlist[i]);
- n = loaded_certs;
- }
- if (certlist != NULL)
- free(certlist);
- *num_certs = n;
- }
- free(fullpath);
- return (rv);
- }
- void
- /*ARGSUSED*/
- OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
- KMF_X509_DER_CERT *kmf_cert)
- {
- if (kmf_cert != NULL) {
- if (kmf_cert->certificate.Data != NULL) {
- kmf_free_data(&kmf_cert->certificate);
- }
- if (kmf_cert->kmf_private.label)
- free(kmf_cert->kmf_private.label);
- }
- }
- /*ARGSUSED*/
- KMF_RETURN
- OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
- {
- KMF_RETURN ret = KMF_OK;
- KMF_DATA *cert = NULL;
- char *outfilename = NULL;
- char *dirpath = NULL;
- char *fullpath = NULL;
- KMF_ENCODE_FORMAT format;
- /* Get the cert data */
- cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
- if (cert == NULL || cert->Data == NULL)
- return (KMF_ERR_BAD_PARAMETER);
- /* Check the output filename and directory attributes. */
- outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
- numattr);
- if (outfilename == NULL)
- return (KMF_ERR_BAD_PARAMETER);
- dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
- fullpath = get_fullpath(dirpath, outfilename);
- if (fullpath == NULL)
- return (KMF_ERR_BAD_CERTFILE);
- /* Check the optional format attribute */
- ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
- &format, NULL);
- if (ret != KMF_OK) {
- /* If there is no format attribute, then default to PEM */
- format = KMF_FORMAT_PEM;
- ret = KMF_OK;
- } else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
- ret = KMF_ERR_BAD_CERT_FORMAT;
- goto out;
- }
- /* Store the certificate in the file with the specified format */
- ret = kmf_create_cert_file(cert, format, fullpath);
- out:
- if (fullpath != NULL)
- free(fullpath);
- return (ret);
- }
- KMF_RETURN
- OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
- {
- KMF_RETURN rv;
- KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
- KMF_DATA certdata = {NULL, 0};
- char *dirpath = NULL;
- char *filename = NULL;
- char *fullpath = NULL;
- char *issuer = NULL;
- char *subject = NULL;
- KMF_BIGINT *serial = NULL;
- KMF_CERT_VALIDITY validity;
- /*
- * Get the DIRPATH and CERT_FILENAME attributes. They can not be
- * NULL at the same time.
- */
- dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
- filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
- numattr);
- fullpath = get_fullpath(dirpath, filename);
- if (fullpath == NULL)
- return (KMF_ERR_BAD_PARAMETER);
- /* Get optional search criteria attributes */
- issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
- subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
- serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
- rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
- &validity, NULL);
- if (rv != KMF_OK) {
- validity = KMF_ALL_CERTS;
- rv = KMF_OK;
- }
- if (isdir(fullpath)) {
- DIR *dirp;
- struct dirent *dp;
- /* open all files in the directory and attempt to read them */
- if ((dirp = opendir(fullpath)) == NULL) {
- return (KMF_ERR_BAD_PARAMETER);
- }
- while ((dp = readdir(dirp)) != NULL) {
- if (strcmp(dp->d_name, ".") != 0 &&
- strcmp(dp->d_name, "..") != 0) {
- char *fname;
- fname = get_fullpath(fullpath,
- (char *)&dp->d_name);
- if (fname == NULL) {
- rv = KMF_ERR_MEMORY;
- break;
- }
- rv = kmf_load_cert(kmfh, issuer, subject,
- serial, validity, fname, &certdata);
- if (rv == KMF_ERR_CERT_NOT_FOUND) {
- free(fname);
- kmf_free_data(&certdata);
- rv = KMF_OK;
- continue;
- } else if (rv != KMF_OK) {
- free(fname);
- break;
- }
- if (unlink(fname) != 0) {
- SET_SYS_ERROR(kmfh, errno);
- rv = KMF_ERR_INTERNAL;
- free(fname);
- break;
- }
- free(fname);
- kmf_free_data(&certdata);
- }
- }
- (void) closedir(dirp);
- } else {
- /* Just try to load a single certificate */
- rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
- fullpath, &certdata);
- if (rv == KMF_OK) {
- if (unlink(fullpath) != 0) {
- SET_SYS_ERROR(kmfh, errno);
- rv = KMF_ERR_INTERNAL;
- }
- }
- }
- out:
- if (fullpath != NULL)
- free(fullpath);
- kmf_free_data(&certdata);
- return (rv);
- }
- KMF_RETURN
- OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
- KMF_DATA *keydata)
- {
- KMF_RETURN rv = KMF_OK;
- KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
- int n;
- if (key == NULL || keydata == NULL ||
- key->keyp == NULL)
- return (KMF_ERR_BAD_PARAMETER);
- if (key->keyalg == KMF_RSA) {
- RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
- if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
- SET_ERROR(kmfh, ERR_get_error());
- return (KMF_ERR_ENCODING);
- }
- RSA_free(pubkey);
- } else if (key->keyalg == KMF_DSA) {
- DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
- if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
- SET_ERROR(kmfh, ERR_get_error());
- return (KMF_ERR_ENCODING);
- }
- DSA_free(pubkey);
- } else {
- return (KMF_ERR_BAD_PARAMETER);
- }
- keydata->Length = n;
- cleanup:
- if (rv != KMF_OK) {
- if (keydata->Data)
- free(keydata->Data);
- keydata->Data = NULL;
- keydata->Length = 0;
- }
- return (rv);
- }
- static KMF_RETURN
- ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
- KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
- {
- int rv = 0;
- RSA *rsa;
- DSA *dsa;
- if (pkey == NULL || out == NULL)
- return (KMF_ERR_BAD_PARAMETER);
- switch (format) {
- case KMF_FORMAT_RAWKEY:
- /* same as ASN.1 */
- case KMF_FORMAT_ASN1:
- if (pkey->type == EVP_PKEY_RSA) {
- rsa = EVP_PKEY_get1_RSA(pkey);
- if (private)
- rv = i2d_RSAPrivateKey_bio(out, rsa);
- else
- rv = i2d_RSAPublicKey_bio(out, rsa);
- RSA_free(rsa);
- } else if (pkey->type == EVP_PKEY_DSA) {
- dsa = EVP_PKEY_get1_DSA(pkey);
- rv = i2d_DSAPrivateKey_bio(out, dsa);
- DSA_free(dsa);
- }
- if (rv == 1) {
- rv = KMF_OK;
- } else {
- SET_ERROR(kmfh, rv);
- }
- break;
- case KMF_FORMAT_PEM:
- if (pkey->type == EVP_PKEY_RSA) {
- rsa = EVP_PKEY_get1_RSA(pkey);
- if (private)
- rv = PEM_write_bio_RSAPrivateKey(out,
- rsa, NULL, NULL, 0, NULL,
- (cred != NULL ? cred->cred : NULL));
- else
- rv = PEM_write_bio_RSAPublicKey(out,
- rsa);
- RSA_free(rsa);
- } else if (pkey->type == EVP_PKEY_DSA) {
- dsa = EVP_PKEY_get1_DSA(pkey);
- rv = PEM_write_bio_DSAPrivateKey(out,
- dsa, NULL, NULL, 0, NULL,
- (cred != NULL ? cred->cred : NULL));
- DSA_free(dsa);
- }
- if (rv == 1) {
- rv = KMF_OK;
- } else {
- SET_ERROR(kmfh, rv);
- }
- break;
- default:
- rv = KMF_ERR_BAD_PARAMETER;
- }
- return (rv);
- }
- KMF_RETURN
- OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
- KMF_ATTRIBUTE *attrlist)
- {
- KMF_RETURN rv = KMF_OK;
- KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
- uint32_t eValue = 0x010001;
- RSA *sslPrivKey = NULL;
- DSA *sslDSAKey = NULL;
- EVP_PKEY *eprikey = NULL;
- EVP_PKEY *epubkey = NULL;
- BIO *out = NULL;
- KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
- uint32_t keylen = 1024;
- uint32_t keylen_size = sizeof (uint32_t);
- boolean_t storekey = TRUE;
- KMF_KEY_ALG keytype = KMF_RSA;
- rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
- &storekey, NULL);
- if (rv != KMF_OK) {
- /* "storekey" is optional. Default is TRUE */
- rv = KMF_OK;
- }
- rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
- (void *)&keytype, NULL);
- if (rv != KMF_OK)
- /* keytype is optional. KMF_RSA is default */
- rv = KMF_OK;
- pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
- if (pubkey == NULL)
- return (KMF_ERR_BAD_PARAMETER);
- privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
- if (privkey == NULL)
- return (KMF_ERR_BAD_PARAMETER);
- (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
- (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
- eprikey = EVP_PKEY_new();
- if (eprikey == NULL) {
- SET_ERROR(kmfh, ERR_get_error());
- rv = KMF_ERR_KEYGEN_FAILED;
- goto cleanup;
- }
- epubkey = EVP_PKEY_new();
- if (epubkey == NULL) {
- SET_ERROR(kmfh, ERR_get_error());
- rv = KMF_ERR_KEYGEN_FAILED;
- goto cleanup;
- }
- if (keytype == KMF_RSA) {
- KMF_BIGINT *rsaexp = NULL;
- rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
- if (rsaexp != NULL) {
- if (rsaexp->len > 0 &&
- rsaexp->len <= sizeof (eValue) &&
- rsaexp->val != NULL) {
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- eValue = *(uint32_t *)rsaexp->val;
- } else {
- rv = KMF_ERR_BAD_PARAMETER;
- goto cleanup;
- }
- } else {
- /* RSA Exponent is optional. Default is 0x10001 */
- rv = KMF_OK;
- }
- rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
- &keylen, &keylen_size);
- if (rv == KMF_ERR_ATTR_NOT_FOUND)
- /* keylen is optional, default is 1024 */
- rv = KMF_OK;
- if (rv != KMF_OK) {
- rv = KMF_ERR_BAD_PARAMETER;
- goto cleanup;
- }
- sslPrivKey = RSA_generate_key(keylen, eValue, NULL, NULL);
- if (sslPrivKey == NULL) {
- SET_ERROR(kmfh, ERR_get_error());
- rv = KMF_ERR_KEYGEN_FAILED;
- } else {
- (void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
- privkey->kstype = KMF_KEYSTORE_OPENSSL;
- privkey->keyalg = KMF_RSA;
- privkey->keyclass = KMF_ASYM_PRI;
- privkey->israw = FALSE;
- privkey->keyp = (void *)eprikey;
- /* OpenSSL derives the public key from the private */
- (void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
- pubkey->kstype = KMF_KEYSTORE_OPENSSL;
- pubkey->keyalg = KMF_RSA;
- pubkey->israw = FALSE;
- pubkey->keyclass = KMF_ASYM_PUB;
- pubkey->keyp = (void *)epubkey;
- }
- } else if (keytype == KMF_DSA) {
- DSA *dp;
- sslDSAKey = DSA_new();
- if (sslDSAKey == NULL) {
- SET_ERROR(kmfh, ERR_get_error());
- return (KMF_ERR_MEMORY);
- }
- if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) ==
- NULL) {
- SET_ERROR(kmfh, ERR_get_error());
- rv = KMF_ERR_KEYGEN_FAILED;
- goto cleanup;
- }
- if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) ==
- NULL) {
- SET_ERROR(kmfh, ERR_get_error());
- rv = KMF_ERR_KEYGEN_FAILED;
- goto cleanup;
- }
- if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) ==
- NULL) {
- SET_ERROR(kmfh, ERR_get_error());
- rv = KMF_ERR_KEYGEN_FAILED;
- goto cleanup;
- }
- if (!DSA_generate_key(sslDSAKey)) {
- SET_ERROR(kmfh, ERR_get_error());
- rv = KMF_ERR_KEYGEN_FAILED;
- goto cleanup;
- }
- privkey->kstype = KMF_KEYSTORE_OPENSSL;
- privkey->keyalg = KMF_DSA;
- privkey->keyclass = KMF_ASYM_PRI;
- privkey->israw = FALSE;
- if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
- privkey->keyp = (void *)eprikey;
- } else {
- SET_ERROR(kmfh, ERR_get_error());
- rv = KMF_ERR_KEYGEN_FAILED;
- goto cleanup;
- }
- dp = DSA_new();
- /* Make a copy for the public key */
- if (dp != NULL) {
- if ((dp->p = BN_new()) == NULL) {
- SET_ERROR(kmfh, ERR_get_error());
- rv = KMF_ERR_MEMORY;
- DSA_free(dp);
- goto cleanup;
- }
- if ((dp->q = BN_new()) == NULL) {
- SET_ERROR(kmfh, ERR_get_error());
- rv = KMF_ERR_MEMORY;
- BN_free(dp->p);
- DSA_free(dp);
- goto cleanup;
- }
- if ((dp->g = BN_new()) == NULL) {
- SET_ERROR(kmfh, ERR_get_error());
- rv = KMF_ERR_MEMORY;
- BN_free(dp->q);
- BN_free(dp->p);
- DSA_free(dp);
- goto cleanup;
- }
- if ((dp->pub_key = BN_new()) == NULL) {
- SET_ERROR(kmfh, ERR_get_error());
- rv = KMF_ERR_MEMORY;
- BN_free(dp->q);
- BN_free(dp->p);
- BN_free(dp->g);
- DSA_free(dp);
- goto cleanup;
- }
- (void) BN_copy(dp->p, sslDSAKey->p);
- (void) BN_copy(dp->q, sslDSAKey->q);
- (void) BN_copy(dp->g, sslDSAKey->g);
- (void) BN_copy(dp->pub_key, sslDSAKey->pub_key);
- pubkey->kstype = KMF_KEYSTORE_OPENSSL;
- pubkey->keyalg = KMF_DSA;
- pubkey->keyclass = KMF_ASYM_PUB;
- pubkey->israw = FALSE;
- if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
- pubkey->keyp = (void *)epubkey;
- } else {
- SET_ERROR(kmfh, ERR_get_error());
- rv = KMF_ERR_KEYGEN_FAILED;
- goto cleanup;
- }
- }
- }
- if (rv != KMF_OK) {
- goto cleanup;
- }
- if (storekey) {
- KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
- int i = 0;
- char *keyfile = NULL, *dirpath = NULL;
- KMF_ENCODE_FORMAT format;
- /*
- * Construct a new attribute arrray and call openssl_store_key
- */
- kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
- privkey, sizeof (privkey));
- i++;
- dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
- if (dirpath != NULL) {
- storeattrs[i].type = KMF_DIRPATH_ATTR;
- storeattrs[i].pValue = dirpath;
- storeattrs[i].valueLen = strlen(dirpath);
- i++;
- } else {
- rv = KMF_OK; /* DIRPATH is optional */
- }
- keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
- attrlist, numattr);
- if (keyfile != NULL) {
- storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
- storeattrs[i].pValue = keyfile;
- storeattrs[i].valueLen = strlen(keyfile);
- i++;
- } else {
- goto cleanup; /* KEYFILE is required */
- }
- rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
- (void *)&format, NULL);
- if (rv == KMF_OK) {
- storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
- storeattrs[i].pValue = &format;
- storeattrs[i].valueLen = sizeof (format);
- i++;
- }
- rv = OpenSSL_StoreKey(handle, i, storeattrs);
- }
- cleanup:
- if (rv != KMF_OK) {
- if (eprikey != NULL)
- EVP_PKEY_free(eprikey);
- if (epubkey != NULL)
- EVP_PKEY_free(epubkey);
- if (pubkey->keylabel) {
- free(pubkey->keylabel);
- pubkey->keylabel = NULL;
- }
- if (privkey->keylabel) {
- free(privkey->keylabel);
- privkey->keylabel = NULL;
- }
- pubkey->keyp = NULL;
- privkey->keyp = NULL;
- }
- if (sslPrivKey)
- RSA_free(sslPrivKey);
- if (sslDSAKey)
- DSA_free(sslDSAKey);
- if (out != NULL)
- (void) BIO_free(out);
- return (rv);
- }
- /*
- * Make sure the BN conversion is properly padded with 0x00
- * bytes. If not, signature verification for DSA signatures
- * may fail in the case where the bignum value does not use
- * all of the bits.
- */
- static int
- fixbnlen(BIGNUM *bn, unsigned char *buf, int len) {
- int bytes = len - BN_num_bytes(bn);
- /* prepend with leading 0x00 if necessary */
- while (bytes-- > 0)
- *buf++ = 0;
- (void) BN_bn2bin(bn, buf);
- /*
- * Return the desired length since we prepended it
- * with the necessary 0x00 padding.
- */
- return (len);
- }
- KMF_RETURN
- OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
- KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
- {
- KMF_RETURN ret = KMF_OK;
- KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
- KMF_ALGORITHM_INDEX AlgId;
- EVP_MD_CTX ctx;
- const EVP_MD *md;
- if (key == NULL || AlgOID == NULL ||
- tobesigned == NULL || output == NULL ||
- tobesigned->Data == NULL ||
- output->Data == NULL)
- return (KMF_ERR_BAD_PARAMETER);
- /* Map the OID to an OpenSSL algorithm */
- AlgId = x509_algoid_to_algid(AlgOID);
- if (AlgId == KMF_ALGID_NONE)
- return (KMF_ERR_BAD_ALGORITHM);
- if (key->keyalg == KMF_RSA) {
- EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
- uchar_t *p;
- int len;
- if (AlgId == KMF_ALGID_MD5WithRSA)
- md = EVP_md5();
- else if (AlgId == KMF_ALGID_MD2WithRSA)
- md = EVP_md2();
- else if (AlgId == KMF_ALGID_SHA1WithRSA)
- md = EVP_sha1();
- else if (AlgId == KMF_ALGID_SHA256WithRSA)
- md = EVP_sha256();
- else if (AlgId == KMF_ALGID_SHA384WithRSA)
- md = EVP_sha384();
- else if (AlgId == KMF_ALGID_SHA512WithRSA)
- md = EVP_sha512();
- else if (AlgId == KMF_ALGID_RSA)
- md = NULL;
- else
- return (KMF_ERR_BAD_ALGORITHM);
- if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
- RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
- p = output->Data;
- if ((len = RSA_private_encrypt(tobesigned->Length,
- tobesigned->Data, p, rsa,
- RSA_PKCS1_PADDING)) <= 0) {
- SET_ERROR(kmfh, ERR_get_error());
- ret = KMF_ERR_INTERNAL;
- }
- output->Length = len;
- } else {
- (void) EVP_MD_CTX_init(&ctx);
- (void) EVP_SignInit_ex(&ctx, md, NULL);
- (void) EVP_SignUpdate(&ctx, tobesigned->Data,
- (uint32_t)tobesigned->Length);
- len = (uint32_t)output->Length;
- p = output->Data;
- if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) {
- SET_ERROR(kmfh, ERR_get_error());
- len = 0;
- ret = KMF_ERR_INTERNAL;
- }
- output->Length = len;
- (void) EVP_MD_CTX_cleanup(&ctx);
- }
- } else if (key->keyalg == KMF_DSA) {
- DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
- uchar_t hash[EVP_MAX_MD_SIZE];
- uint32_t hashlen;
- DSA_SIG *dsasig;
- if (AlgId == KMF_ALGID_DSA ||
- AlgId == KMF_ALGID_SHA1WithDSA)
- md = EVP_sha1();
- else if (AlgId == KMF_ALGID_SHA256WithDSA)
- md = EVP_sha256();
- else /* Bad algorithm */
- return (KMF_ERR_BAD_ALGORITHM);
- /*
- * OpenSSL EVP_Sign operation automatically converts to
- * ASN.1 output so we do the operations separately so we
- * are assured of NOT getting ASN.1 output returned.
- * KMF does not want ASN.1 encoded results because
- * not all mechanisms return ASN.1 encodings (PKCS#11
- * and NSS return raw signature data).
- */
- EVP_MD_CTX_init(&ctx);
- (void) EVP_DigestInit_ex(&ctx, md, NULL);
- (void) EVP_DigestUpdate(&ctx, tobesigned->Data,
- tobesigned->Length);
- (void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
- /* Only sign first 20 bytes for SHA2 */
- if (AlgId == KMF_ALGID_SHA256WithDSA)
- hashlen = 20;
- dsasig = DSA_do_sign(hash, hashlen, dsa);
- if (dsasig != NULL) {
- int i;
- output->Length = i = fixbnlen(dsasig->r, output->Data,
- hashlen);
- output->Length += fixbnlen(dsasig->s, &output->Data[i],
- hashlen);
- DSA_SIG_free(dsasig);
- } else {
- SET_ERROR(kmfh, ERR_get_error());
- }
- (void) EVP_MD_CTX_cleanup(&ctx);
- } else {
- return (KMF_ERR_BAD_PARAMETER);
- }
- cleanup:
- return (ret);
- }
- KMF_RETURN
- /*ARGSUSED*/
- OpenSSL_DeleteKey(KMF_HANDLE_T handle,
- int numattr, KMF_ATTRIBUTE *attrlist)
- {
- KMF_RETURN rv = KMF_OK;
- KMF_KEY_HANDLE *key;
- boolean_t destroy = B_TRUE;
- key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
- if (key == NULL || key->keyp == NULL)
- return (KMF_ERR_BAD_PARAMETER);
- rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
- (void *)&destroy, NULL);
- if (rv != KMF_OK) {
- /* "destroy" is optional. Default is TRUE */
- rv = KMF_OK;
- }
- if (key->keyclass != KMF_ASYM_PUB &&
- key->keyclass != KMF_ASYM_PRI &&
- key->keyclass != KMF_SYMMETRIC)
- return (KMF_ERR_BAD_KEY_CLASS);
- if (key->keyclass == KMF_SYMMETRIC) {
- kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
- key->keyp = NULL;
- } else {
- if (key->keyp != NULL) {
- EVP_PKEY_free(key->keyp);
- key->keyp = NULL;
- }
- }
- if (key->keylabel != NULL) {
- EVP_PKEY *pkey = NULL;
- /* If the file exists, make sure it is a proper key. */
- pkey = openssl_load_key(handle, key->keylabel);
- if (pkey == NULL) {
- if (key->keylabel != NULL) {
- free(key->keylabel);
- key->keylabel = NULL;
- }
- return (KMF_ERR_KEY_NOT_FOUND);
- }
- EVP_PKEY_free(pkey);
- if (destroy) {
- if (unlink(key->keylabel) != 0) {
- KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
- SET_SYS_ERROR(kmfh, errno);
- rv = KMF_ERR_INTERNAL;
- }
- }
- if (key->keylabel != NULL) {
- free(key->keylabel);
- key->keylabel = NULL;
- }
- }
- return (rv);
- }
- KMF_RETURN
- OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
- {
- KMF_RETURN ret = KMF_OK;
- KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
- char str[256]; /* OpenSSL needs at least 120 byte buffer */
- ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
- if (strlen(str)) {
- *msgstr = (char *)strdup(str);
- if ((*msgstr) == NULL)
- ret = KMF_ERR_MEMORY;
- } else {
- *msgstr = NULL;
- }
- return (ret);
- }
- static int
- ext2NID(int kmfext)
- {
- switch (kmfext) {
- case KMF_X509_EXT_KEY_USAGE:
- return (NID_key_usage);
- case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
- return (NID_private_key_usage_period);
- case KMF_X509_EXT_CERT_POLICIES:
- return (NID_certificate_policies);
- case KMF_X509_EXT_SUBJ_ALTNAME:
- return (NID_subject_alt_name);
- case KMF_X509_EXT_ISSUER_ALTNAME:
- return (NID_issuer_alt_name);
- case KMF_X509_EXT_BASIC_CONSTRAINTS:
- return (NID_basic_constraints);
- case KMF_X509_EXT_EXT_KEY_USAGE:
- return (NID_ext_key_usage);
- case KMF_X509_EXT_AUTH_KEY_ID:
- return (NID_authority_key_identifier);
- case KMF_X509_EXT_CRL_DIST_POINTS:
- return (NID_crl_distribution_points);
- case KMF_X509_EXT_SUBJ_KEY_ID:
- return (NID_subject_key_identifier);
- case KMF_X509_EXT_POLICY_MAPPINGS:
- return (OBJ_sn2nid("policyMappings"));
- case KMF_X509_EXT_NAME_CONSTRAINTS:
- return (OBJ_sn2nid("nameConstraints"));
- case KMF_X509_EXT_POLICY_CONSTRAINTS:
- return (OBJ_sn2nid("policyConstraints"));
- case KMF_X509_EXT_INHIBIT_ANY_POLICY:
- return (OBJ_sn2nid…
Large files files are truncated, but you can click here to view the full file