openssl_spi.c revision f482c776bc557f0256e776932c7842b9db390de1
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* 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
* 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).
*
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdlib.h>
#include <kmfapiP.h>
#include <ber_der.h>
#include <fcntl.h>
#include <dirent.h>
#include <cryptoutil.h>
#include <synch.h>
#include <thread.h>
/* OPENSSL related headers */
#define PRINT_ANY_EXTENSION (\
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 };
0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
0x8e, 0xda, 0xce, 0x91, 0x5f };
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 };
static int ssl_initialized = 0;
static KMF_RETURN
static KMF_RETURN
static KMF_RETURN
static EVP_PKEY *
uint32_t *);
void
KMF_KEY_HANDLE *, KMF_KEY_HANDLE *);
KMF_KEY_HANDLE *, boolean_t);
KMF_PRINTABLE_ITEM, char *);
OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
char *reqfile);
KMF_KEY_HANDLE *, uint32_t *);
int, KMF_X509_DER_CERT *,
int, KMF_KEY_HANDLE *,
char *);
KMF_RAW_KEY_DATA *);
KMF_KEY_HANDLE *);
static
{
1, /* Version */
NULL, /* ConfigureKeystore */
NULL, /* ImportCert */
NULL, /* FindCRL */
NULL, /* SetTokenPin */
NULL /* Finalize */
};
static long *lock_count;
static void
/*ARGSUSED*/
{
if (mode & CRYPTO_LOCK) {
lock_count[type]++;
} else {
}
}
static unsigned long
{
return ((unsigned long)thr_self());
}
{
int i;
(void) mutex_lock(&init_lock);
if (!ssl_initialized) {
/* Enable error strings for reporting */
/*
* Add support for extension OIDs that are not yet in the
* openssl default set.
*/
"X509v3 Name Constraints");
"X509v3 Policy Mappings");
"X509v3 Policy Constraints");
"X509v3 Freshest CRL");
"X509v3 Inhibit Any-Policy");
/*
* Set up for thread-safe operation.
*/
(void) mutex_unlock(&init_lock);
return (NULL);
}
if (lock_count == NULL) {
(void) mutex_unlock(&init_lock);
return (NULL);
}
for (i = 0; i < CRYPTO_num_locks(); i++) {
lock_count[i] = 0;
}
CRYPTO_set_id_callback((unsigned long (*)())thread_id);
CRYPTO_set_locking_callback((void (*)())locking_cb);
ssl_initialized = 1;
}
(void) mutex_unlock(&init_lock);
return (&openssl_plugin_table);
}
/*
* Convert an SSL DN to a KMF DN.
*/
static KMF_RETURN
{
/* Convert to raw DER format */
== NULL) {
return (KMF_ERR_MEMORY);
}
/* Decode to KMF format */
}
return (rv);
}
static int
{
struct stat s;
return (0);
}
static KMF_RETURN
{
int len;
/*
* Convert the X509 internal struct to DER encoded data
*/
goto cleanup;
}
rv = KMF_ERR_MEMORY;
goto cleanup;
}
/*
* i2d_X509 will increment the buf pointer so that we need to
* save it.
*/
p = buf;
goto cleanup;
}
/* caller's responsibility to free it */
if (buf)
}
return (rv);
}
static KMF_RETURN
{
return (KMF_ERR_BAD_PARAMETER);
}
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_BAD_PARAMETER);
}
findIssuer = TRUE;
}
goto cleanup;
}
goto cleanup;
}
findSubject = TRUE;
}
findSerial = TRUE;
if (findSerial) {
/* Comparing BIGNUMs is a pain! */
if (a == NULL) {
rv = KMF_ERR_MEMORY;
goto cleanup;
}
free(a);
}
if (!(*match))
goto cleanup;
} else {
goto cleanup;
}
}
if (findIssuer) {
if (!(*match)) {
goto cleanup;
}
}
if (findSubject) {
if (!(*match)) {
goto cleanup;
}
}
if (findIssuer) {
}
if (findSubject) {
}
return (rv);
}
static KMF_RETURN
char *pathname,
{
/*
* auto-detect the file format, regardless of what
* the 'format' parameters in the params say.
*/
if (rv == KMF_ERR_OPEN_FILE)
return (rv);
}
/* Not ASN1(DER) format */
goto cleanup;
}
if (format == KMF_FORMAT_PEM)
else if (format == KMF_FORMAT_ASN1)
else if (format == KMF_FORMAT_PKCS12) {
} else {
}
} else {
goto cleanup;
}
goto cleanup;
}
goto cleanup;
}
}
return (rv);
}
static int
datacmp(const void *a, const void *b)
{
return (-1);
return (1);
return (0);
}
static KMF_RETURN
{
int i;
int nc = 0;
int hits = 0;
if (rv == KMF_ERR_OPEN_FILE)
return (rv);
}
if (format == KMF_FORMAT_ASN1) {
/* load a single certificate */
return (KMF_ERR_MEMORY);
*numcerts = 1;
}
return (rv);
} else if (format == KMF_FORMAT_PKCS12) {
/* We need a credential to access a PKCS#12 file */
} else if (format == KMF_FORMAT_PEM ||
format != KMF_FORMAT_PEM_KEYPAIR) {
/* This function only works on PEM files */
} else {
return (KMF_ERR_ENCODING);
}
return (rv);
for (i = 0; i < nc; i++) {
if (rv == KMF_ERR_VALIDITY_PERIOD)
}
/* Remove this cert from the list by clearing it. */
KMF_FreeData(&certs[i]);
} else {
hits++; /* count valid certs found */
}
}
/*
* Sort the list of certs by length to put the cleared ones
* at the end so they don't get accessed by the caller.
*/
/* since we sorted the list, just return the number of hits */
}
return (rv);
}
static KMF_RETURN
char *pathname,
{
goto cleanup;
}
/*
* This is a valid cert so skip it.
*/
}
if (rv == KMF_ERR_VALIDITY_PERIOD) {
/*
* We want to return success when we
* find an invalid cert.
*/
goto cleanup;
}
}
}
return (rv);
}
static KMF_RETURN
{
goto out;
}
goto out;
}
/*
* We have to derive the 2 Exponents using Bignumber math.
* Exp1 = PriExp mod (Prime1 - 1)
* Exp2 = PriExp mod (Prime2 - 1)
*/
/* D = PrivateExponent */
if (D == NULL) {
goto out;
}
/* P = Prime1 (first prime factor of Modulus) */
if (D == NULL) {
goto out;
}
/* Q = Prime2 (second prime factor of Modulus) */
goto out;
}
/* Compute (P - 1) */
/* Exponent1 = D mod (P - 1) */
/* Compute (Q - 1) */
/* Exponent2 = D mod (Q - 1) */
/* Coef = (Inverse Q) mod P */
/* Convert back to KMF format */
goto out;
goto out;
goto out;
out:
}
if (PriExp)
if (Mod)
if (PubExp)
if (Coef) {
}
if (Prime1)
if (Prime2)
if (D)
BN_clear_free(D);
if (P)
BN_clear_free(P);
if (Q)
BN_clear_free(Q);
if (pminus1)
if (qminus1)
if (Exp1)
if (Exp2)
return (ret);
}
static EVP_PKEY *
{
return (NULL);
}
return (NULL);
goto end;
}
if (format == KMF_FORMAT_ASN1) {
/* Try odd ASN.1 variations */
&filedata);
(void) readAltFormatPrivateKey(&filedata,
&pkey);
}
}
} else if (format == KMF_FORMAT_PEM ||
format == KMF_FORMAT_PEM_KEYPAIR) {
/*
* Check if this is the alt. format
* RSA private key file.
*/
&filedata);
int len;
(void) readAltFormatPrivateKey(
free(d);
}
}
}
}
end:
return (pkey);
}
{
char *fullpath;
int i, n;
return (KMF_ERR_BAD_PARAMETER);
if (maxcerts == 0)
maxcerts = 0xFFFFFFFF;
*num_certs = 0;
return (KMF_ERR_BAD_PARAMETER);
n = 0;
/* open all files in the directory and attempt to read them */
return (KMF_ERR_BAD_PARAMETER);
}
char *fname;
uint32_t loaded_certs = 0;
continue;
&loaded_certs);
for (i = 0; i < loaded_certs; i++)
KMF_FreeData(&certlist[i]);
}
continue;
}
/* If load succeeds, add certdata to the list */
for (i = 0; i < loaded_certs &&
i < maxcerts; i++) {
n++;
}
/* If maxcerts < loaded_certs, clean up */
for (; i < loaded_certs; i++)
KMF_FreeData(&certlist[i]);
} else {
for (i = 0; i < loaded_certs; i++)
KMF_FreeData(&certlist[i]);
n += loaded_certs;
}
}
(*num_certs) = n;
if (*num_certs == 0)
else
exit:
} else {
uint32_t loaded_certs = 0;
&certlist, &loaded_certs);
return (rv);
}
n = 0;
for (i = 0; i < loaded_certs && i < maxcerts; i++) {
n++;
}
/* If maxcerts < loaded_certs, clean up */
for (; i < loaded_certs; i++)
KMF_FreeData(&certlist[i]);
for (i = 0; i < loaded_certs; i++)
KMF_FreeData(&certlist[i]);
n = loaded_certs;
}
if (certlist)
*num_certs = n;
}
return (rv);
}
void
/*ARGSUSED*/
{
}
}
}
{
unsigned char *outbuf;
unsigned char *outbuf_p;
char *fullpath;
int outbuflen;
int len;
return (KMF_ERR_BAD_PARAMETER);
}
/*
* check if the cert output format is supported by OPENSSL.
* however, since the keystore for OPENSSL is just a file, we have
* no way to store the format along with the file.
*/
return (KMF_ERR_BAD_CERT_FORMAT);
return (KMF_ERR_BAD_PARAMETER);
/*
* When storing a certificate, you must specify a filename.
*/
return (KMF_ERR_BAD_PARAMETER);
}
/* copy cert data to outbuf */
return (KMF_ERR_MEMORY);
}
NULL) {
goto out;
}
if (format == KMF_FORMAT_ASN1) {
} else {
}
goto out;
}
/*
* The output format is not KMF_FORMAT_ASN1, so we will
* Convert the cert data to OpenSSL internal X509 first.
*/
goto out;
}
if (format == KMF_FORMAT_PEM) {
/* Convert to the PEM format and write it out */
} else {
}
goto out;
}
out:
}
}
}
return (ret);
}
{
return (KMF_ERR_BAD_PARAMETER);
}
return (KMF_ERR_BAD_PARAMETER);
/* open all files in the directory and attempt to read them */
return (KMF_ERR_BAD_PARAMETER);
}
char *fname;
rv = KMF_ERR_MEMORY;
break;
}
&certdata);
if (rv == KMF_ERR_CERT_NOT_FOUND) {
continue;
break;
}
break;
}
}
}
} else {
/* Just try to load a single certificate */
}
}
}
out:
return (rv);
}
{
int n;
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_ENCODING);
}
return (KMF_ERR_ENCODING);
}
} else {
return (KMF_ERR_BAD_PARAMETER);
}
}
return (rv);
}
static KMF_RETURN
{
int rv = 0;
switch (format) {
case KMF_FORMAT_ASN1:
}
if (rv == 1) {
} else {
}
break;
case KMF_FORMAT_PEM:
rsa,
NULL /* encryption type */,
dsa,
NULL /* encryption type */,
}
if (rv == 1) {
} else {
}
break;
default:
}
return (rv);
}
{
int format;
return (KMF_ERR_BAD_PARAMETER);
}
return (KMF_ERR_BAD_PARAMETER);
/* If the requested file exists, return an error */
return (KMF_ERR_DUPLICATE_KEYFILE);
}
eprikey = EVP_PKEY_new();
goto cleanup;
}
epubkey = EVP_PKEY_new();
goto cleanup;
}
/*LINTED*/
if (sslPrivKey == NULL) {
} else {
}
/* OpenSSL derives the public key from the private */
}
}
return (KMF_ERR_MEMORY);
}
NULL) {
goto cleanup;
}
NULL) {
goto cleanup;
}
NULL) {
goto cleanup;
}
if (!DSA_generate_key(sslDSAKey)) {
goto cleanup;
}
} else {
goto cleanup;
}
}
/* Make a copy for the public key */
rv = KMF_ERR_MEMORY;
goto cleanup;
}
rv = KMF_ERR_MEMORY;
goto cleanup;
}
rv = KMF_ERR_MEMORY;
goto cleanup;
}
rv = KMF_ERR_MEMORY;
goto cleanup;
}
} else {
goto cleanup;
}
}
}
}
goto cleanup;
}
/* Store the private key to the keyfile */
goto cleanup;
}
}
}
}
if (sslPrivKey)
if (sslDSAKey)
if (fullpath)
/* Protect the file by making it read-only */
}
return (rv);
}
{
return (KMF_ERR_BAD_PARAMETER);
/* Map the OID to an OpenSSL algorithm */
if (AlgId == KMF_ALGID_NONE)
return (KMF_ERR_BAD_PARAMETER);
uchar_t *p;
int len;
if (AlgId == KMF_ALGID_MD5WithRSA)
else if (AlgId == KMF_ALGID_MD2WithRSA)
else if (AlgId == KMF_ALGID_SHA1WithRSA)
else if (AlgId == KMF_ALGID_RSA)
else
return (KMF_ERR_BAD_PARAMETER);
RSA_PKCS1_PADDING)) <= 0) {
}
} else {
(void) EVP_MD_CTX_init(&ctx);
len = 0;
}
(void) EVP_MD_CTX_cleanup(&ctx);
}
/*
* 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).
*/
tobesigned->Length);
(void) EVP_MD_CTX_cleanup(&ctx);
int i;
} else {
}
} else {
return (KMF_ERR_BAD_PARAMETER);
}
return (ret);
}
/*ARGSUSED*/
{
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_BAD_KEY_CLASS);
} else {
}
}
/* If the file exists, make sure it is a proper key. */
return (KMF_ERR_KEY_NOT_FOUND);
}
if (destroy) {
}
}
}
}
return (rv);
}
{
int openssl_ret = 0;
char *outcrlfile = NULL;
return (KMF_ERR_BAD_PARAMETER);
}
return (KMF_ERR_BAD_PARAMETER);
}
if (outcrlfile == NULL)
return (KMF_ERR_BAD_PARAMETER);
if (isdir(outcrlfile)) {
return (KMF_ERR_BAD_PARAMETER);
}
return (ret);
}
goto end;
}
if (format == KMF_FORMAT_ASN1) {
} else if (format == KMF_FORMAT_PEM) {
}
goto end;
}
/* If bypasscheck is specified, no need to verify. */
goto output;
}
goto end;
/* Read in the CA cert file and convert to X509 */
goto end;
}
if (format == KMF_FORMAT_ASN1) {
} else if (format == KMF_FORMAT_PEM) {
} else {
goto end;
}
goto end;
}
/* Now get the public key from the CA cert */
if (!pkey) {
goto end;
}
/* Verify the CRL with the CA's public key */
if (openssl_ret > 0) {
} else {
}
goto end;
}
if (outformat == KMF_FORMAT_ASN1) {
} else if (outformat == KMF_FORMAT_PEM) {
} else {
goto end;
}
if (openssl_ret <= 0) {
} else {
}
end:
if (outcrlfile != NULL)
return (ret);
}
char **crldata)
{
long len;
char *memptr;
return (KMF_ERR_BAD_PARAMETER);
}
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_BAD_PARAMETER);
}
return (ret);
}
goto end;
}
if (format == KMF_FORMAT_ASN1) {
} else if (format == KMF_FORMAT_PEM) {
}
if (x == NULL) { /* should not happen */
goto end;
}
goto end;
}
(void) X509_CRL_print(mem, x);
if (len <= 0) {
goto end;
}
goto end;
}
end:
if (x != NULL)
X509_CRL_free(x);
return (ret);
}
{
return (KMF_ERR_BAD_PARAMETER);
}
return (KMF_ERR_BAD_PARAMETER);
goto end;
}
goto end;
goto end;
}
end:
return (ret);
}
{
int i;
return (KMF_ERR_BAD_PARAMETER);
}
return (ret);
/* Read the CRL file and load it into a X509_CRL structure */
goto end;
}
if (format == KMF_FORMAT_ASN1) {
} else if (format == KMF_FORMAT_PEM) {
}
goto end;
}
/* Read the Certificate file and load it into a X509 structure */
goto end;
goto end;
}
if (format == KMF_FORMAT_ASN1) {
} else if (format == KMF_FORMAT_PEM) {
}
goto end;
}
/* Check if the certificate and the CRL have same issuer */
goto end;
}
/* Check to see if the certificate serial number is revoked */
if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
/* No revoked certificates in the CRL file */
goto end;
}
for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
/*LINTED*/
revoke->serialNumber) == 0) {
break;
}
}
if (i < sk_X509_REVOKED_num(revoke_stack)) {
} else {
}
end:
return (ret);
}
{
} else {
}
return (ret);
}
static int
{
switch (kmfext) {
case KMF_X509_EXT_KEY_USAGE:
return (NID_key_usage);
return (NID_private_key_usage_period);
return (NID_certificate_policies);
return (NID_subject_alt_name);
return (NID_issuer_alt_name);
return (NID_basic_constraints);
return (NID_ext_key_usage);
case KMF_X509_EXT_AUTH_KEY_ID:
return (NID_authority_key_identifier);
return (NID_crl_distribution_points);
case KMF_X509_EXT_SUBJ_KEY_ID:
return (NID_subject_key_identifier);
return (OBJ_sn2nid("policyMappings"));
return (OBJ_sn2nid("nameConstraints"));
return (OBJ_sn2nid("policyConstraints"));
return (OBJ_sn2nid("inhibitAnyPolicy"));
return (OBJ_sn2nid("freshestCRL"));
default:
return (NID_undef);
}
}
{
unsigned char *outbuf_p;
int j;
return (KMF_ERR_BAD_PARAMETER);
}
/* copy cert data to outbuf */
return (KMF_ERR_MEMORY);
}
goto out;
}
goto out;
}
switch (flag) {
case KMF_CERT_ISSUER:
break;
case KMF_CERT_SUBJECT:
break;
case KMF_CERT_VERSION:
break;
case KMF_CERT_SERIALNUM:
KMF_CERT_PRINTABLE_LEN - 2);
}
break;
case KMF_CERT_NOTBEFORE:
break;
case KMF_CERT_NOTAFTER:
break;
case KMF_CERT_PUBKEY_DATA:
{
goto out;
}
(void) BIO_printf(mem,
"RSA Public Key: (%d bit)\n",
(void) BIO_printf(mem,
"%12sDSA Public Key:\n", "");
} else {
(void) BIO_printf(mem,
"%12sUnknown Public Key:\n", "");
}
}
break;
case KMF_CERT_SIGNATURE_ALG:
case KMF_CERT_PUBKEY_ALG:
if (flag == KMF_CERT_SIGNATURE_ALG) {
} else {
}
if (len > 0) {
}
break;
case KMF_CERT_EMAIL:
break;
case KMF_X509_EXT_KEY_USAGE:
case KMF_X509_EXT_AUTH_KEY_ID:
case KMF_X509_EXT_SUBJ_KEY_ID:
goto out;
}
if (ext_index == -1) {
goto out;
}
0) {
goto out;
}
}
goto out;
}
}
if (len <= 0) {
}
out:
}
}
}
return (ret);
}
/*ARGSUSED*/
{
return (KMF_ERR_BAD_PARAMETER);
/*
* This is really just a FindKey operation, reuse the
* FindKey function.
*/
return (rv);
}
/*ARGSUSED*/
{
unsigned int total_decrypted = 0, modulus_len = 0;
int i, blocks;
return (KMF_ERR_BAD_PARAMETER);
} else {
return (KMF_ERR_BAD_PARAMETER);
}
for (i = 0; i < blocks; i++) {
if (out_len == 0) {
goto cleanup;
}
}
return (ret);
}
/*
* This function will create a certid from issuer_cert and user_cert.
* The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
* certid memory after use.
*/
static KMF_RETURN
{
unsigned char *ptmp;
return (KMF_ERR_BAD_PARAMETER);
}
/* convert the DER-encoded issuer cert to an internal X509 */
goto end;
}
/* convert the DER-encoded user cert to an internal X509 */
goto end;
}
/* create a CERTID */
goto end;
}
end:
}
}
return (ret);
}
char *reqfile)
{
return (KMF_ERR_BAD_PARAMETER);
}
&id);
return (ret);
}
/* Create an OCSP request */
req = OCSP_REQUEST_new();
goto end;
}
goto end;
}
/* Write the request to the output file with DER encoding */
if (!derbio) {
goto end;
}
}
end:
/*
* We don't need to free "id" explicitely, because OCSP_REQUEST_free()
* will deallocate certid's space also.
*/
}
}
return (ret);
}
/* ocsp_find_signer_sk() is copied from openssl source */
{
int i;
/* Easy if lookup by name */
/* Lookup by key hash */
/* If key hash isn't SHA1 length then forget it */
return (NULL);
/* Calculate hash of each key and compare */
for (i = 0; i < sk_X509_num(certs); i++) {
/*LINTED*/
return (x);
}
return (NULL);
}
/* ocsp_find_signer() is copied from openssl source */
/*ARGSUSED*/
static int
{
return (2);
}
if (!(flags & OCSP_NOINTERN) &&
return (1);
}
/* Maybe lookup from store if by subject name */
return (0);
}
/*
* This function will verify the signature of a basic response, using
* the public key from the OCSP responder certificate.
*/
static KMF_RETURN
{
unsigned char *ptmp;
return (KMF_ERR_BAD_PARAMETER);
/*
* Find the certificate that signed the basic response.
*
* If signer_cert is not NULL, we will use that as the signer cert.
* Otherwise, we will check if the issuer cert is actually the signer.
* If we still do not find a signer, we will look for it from the
* certificate list came with the response file.
*/
if (signer_cert != NULL) {
goto end;
}
} else {
/*
* Convert the issuer cert into X509 and push it into a
* stack to be used by ocsp_find_signer().
*/
goto end;
}
goto end;
}
goto end;
}
if (!ret) {
/* can not find the signer */
goto end;
}
}
/* Verify the signature of the response */
goto end;
}
if (ret == 0) {
goto end;
}
end:
}
}
}
if (cert_stack != NULL) {
}
return (ret);
}
{
return (KMF_ERR_BAD_PARAMETER);
}
if (params_out == NULL) {
return (KMF_ERR_BAD_PARAMETER);
}
/* Read in the response */
if (!derbio) {
return (ret);
}
goto end;
}
/* Check the response status */
if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
goto end;
}
#ifdef DEBUG
printf("Successfully checked the response file status.\n");
#endif /* DEBUG */
/* Extract basic response */
goto end;
}
#ifdef DEBUG
printf("Successfully retrieved the basic response.\n");
#endif /* DEBUG */
/* Check the basic response signature if required */
goto end;
}
#ifdef DEBUG
printf("Successfully verified the response signature.\n");
#endif /* DEBUG */
/* Create a certid for the certificate in question */
goto end;
}
#ifdef DEBUG
printf("successfully created a certid for the cert.\n");
#endif /* DEBUG */
/* Find the index of the single response for the certid */
if (index < 0) {
/* cound not find this certificate in the response */
goto end;
}
#ifdef DEBUG
printf("Successfully found the single response index for the cert.\n");
#endif /* DEBUG */
/* Retrieve the single response and get the cert status */
&nextupd);
if (status == V_OCSP_CERTSTATUS_GOOD) {
} else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
} else { /* revoked */
}
/* Verify the time */
goto end;
}
#ifdef DEBUG
printf("Successfully verify the time.\n");
#endif /* DEBUG */
end:
return (ret);
}
static KMF_RETURN
{
/* Make sure the requested file actually exists. */
return (KMF_ERR_KEY_NOT_FOUND);
}
if (keyclass == KMF_ASYM_PRI ||
keyclass == KMF_ASYM_PUB) {
return (KMF_ERR_KEY_NOT_FOUND);
}
} else {
}
} else if (keyclass == KMF_SYMMETRIC) {
/*
* If the file is a recognized format,
* then it is NOT a symmetric key.
*/
return (KMF_ERR_KEY_NOT_FOUND);
} else if (rv == KMF_ERR_ENCODING) {
/*
* If we don't know the encoding,
* it is probably a symmetric key.
*/
}
rv = KMF_ERR_MEMORY;
goto out;
}
goto out;
}
}
out:
}
}
}
return (rv);
}
{
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_BAD_KEY_CLASS);
return (KMF_ERR_BAD_PARAMETER);
if (maxkeys == 0)
maxkeys = 0xFFFFFFFF;
*numkeys = 0;
int n = 0;
/* open all files in the directory and attempt to read them */
return (KMF_ERR_BAD_PARAMETER);
}
char *fname;
n++;
}
}
(*numkeys) = n;
} else {
(*numkeys) = 1;
}
return (rv);
}
#define HANDLE_PK12_ERROR { \
rv = KMF_ERR_ENCODING; \
goto out; \
}
static KMF_RETURN
{
int lab_len = 0;
unsigned char keyid[EVP_MAX_MD_SIZE];
unsigned int keyidlen = 0;
/* Must have at least a cert OR a key */
return (KMF_ERR_BAD_PARAMETER);
/*
* Section 1:
*
* The first PKCS#12 container (safebag) will hold the certificates
* associated with this key. The result of this section is a
* PIN-encrypted PKCS#7 container (authsafe). If there are no
* certificates, there is no point in creating the "safebag" or the
* "authsafe" so we go to the next section.
*/
&keyidlen);
} else {
/* The key doesn't match the cert */
}
}
return (KMF_ERR_MEMORY);
/* Convert cert from X509 struct to PKCS#12 bag */
}
/* Add the key id to the certificate bag. */
if (keyidlen > 0 &&
}
/* Pile it on the bag_stack. */
}
#if 0
/* No support for CA certs yet */
int i;
for (i = 0; i < ncacerts; i++) {
KMF_X509_DER_CERT *c = &cacerts[i];
c->certificate.Length);
}
/* Convert CA cert to PKCS#12 bag. */
}
/* Pile it onto the bag_stack. */
}
}
}
#endif
/* Turn bag_stack of certs into encrypted authsafe. */
/* Clear away this bag_stack, we're done with it. */
if (cert_authsafe == NULL) {
}
}
/*
* Section 2:
*
* The second PKCS#12 container (safebag) will hold the private key
* that goes with the certificates above. The results of this section
* is an unencrypted PKCS#7 container (authsafe). If there is no
* private key, there is no point in creating the "safebag" or the
* "authsafe" so we go to the next section.
*/
}
/* Put the shrouded key into a PKCS#12 bag. */
/* Clean up the PKCS#8 shrouded key, don't need it now. */
}
if (keyidlen &&
}
if (!PKCS12_add_friendlyname(bag,
}
}
/* Start a PKCS#12 safebag container for the private key. */
}
/* Pile on the private key on the bag_stack. */
}
/* Clear away this bag_stack, we're done with it. */
if (key_authsafe == NULL) {
}
}
/*
* Section 3:
*
* This is where the two PKCS#7 containers, one for the certificates
* and one for the private key, are put together into a PKCS#12
* element. This final PKCS#12 element is written to the export file.
*/
/* Start a PKCS#7 stack. */
if (authsafe_stack == NULL) {
}
if (key_authsafe != NULL) {
}
}
if (cert_authsafe != NULL) {
}
}
}
/* Put the PKCS#7 stack into the PKCS#12 element. */
}
/* Clear away the PKCS#7 stack, we're done with it. */
/* Set the integrity MAC on the PKCS#12 element. */
}
/* Write the PKCS#12 element to the export file. */
}
out:
/* Clear away this bag_stack, we're done with it. */
}
return (rv);
}
static EVP_PKEY *
{
return (NULL);
return (NULL);
NULL)
return (NULL);
return (NULL);
return (NULL);
return (NULL);
return (NULL);
return (NULL);
return (NULL);
return (NULL);
/* The original key must be freed once here or it leaks memory */
return (newkey);
}
static EVP_PKEY *
{
return (NULL);
return (NULL);
return (NULL);
return (NULL);
return (NULL);
return (NULL);
/* The original key must be freed once here or it leaks memory */
return (newkey);
}
static KMF_RETURN
char *filename)
{
int i;
/*
* Open the output file.
*/
goto cleanup;
}
if (i < numkeys) {
} else {
}
}
}
/* Stick the key and the cert into a PKCS#12 file */
if (xcert)
if (pkey)
}
}
(void) BIO_free_all(bio);
return (rv);
}
char *filename)
{
/*
* First, find the certificate.
*/
return (KMF_ERR_BAD_PARAMETER);
/*
* If the caller already sent the raw keys and certs,
* shortcut the search and just export that
* data.
*
* One *may* export a key OR a cert by itself.
*/
filename);
return (rv);
}
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_AMBIGUOUS_PATHNAME);
}
goto end;
}
/*
* Now find the private key.
*/
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_AMBIGUOUS_PATHNAME);
}
goto end;
}
}
/*
* Open the output file.
*/
goto end;
}
/* Stick the key and the cert into a PKCS#12 file */
end:
if (fullpath)
if (xcert)
if (pkey)
if (bio)
return (rv);
}
#define MAX_CHAIN_LENGTH 100
/*
* Helper function to extract keys and certificates from
* a single PEM file. Typically the file should contain a
* private key and an associated public key wrapped in an x509 cert.
* However, the file may be just a list of X509 certs with no keys.
*/
static KMF_RETURN
int *numcerts)
/* ARGSUSED */
{
int i, ncerts = 0, matchcerts = 0;
X509 *x;
if (priv_key)
if (certs)
return (KMF_ERR_OPEN_FILE);
}
if (x509_info_stack == NULL) {
return (KMF_ERR_ENCODING);
}
/*LINTED*/
ncerts++;
}
if (ncerts == 0) {
return (KMF_ERR_CERT_NOT_FOUND);
}
}
/*
* Make sure the private key matchs the last cert in the file.
*/
return (KMF_ERR_KEY_MISMATCH);
}
return (KMF_ERR_MEMORY);
}
/*
* Convert all of the certs to DER format.
*/
matchcerts = 0;
continue;
}
}
&certlist[matchcerts++]);
ncerts = matchcerts = 0;
}
}
*numcerts = matchcerts;
return (rv);
}
/*
* Helper function to decrypt and parse PKCS#12 import file.
*/
static KMF_RETURN
/* ARGSUSED */
{
return (KMF_ERR_MEMORY);
}
/* This is ok; it seems to mean there is no more to read. */
goto end_extract_pkcs12;
return (KMF_ERR_PKCS12_FORMAT);
}
&temp_ca) <= 0) {
return (KMF_ERR_PKCS12_FORMAT);
}
return (KMF_OK);
}
static KMF_RETURN
{
return (KMF_ERR_MEMORY);
rv = KMF_ERR_MEMORY;
}
return (rv);
}
static KMF_RETURN
{
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
else
/*
* Free the reference to this key, SSL will not actually free
* the memory until the refcount == 0, so this is safe.
*/
return (rv);
}
static KMF_RETURN
{
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
else
/*
* Free the reference to this key, SSL will not actually free
* the memory until the refcount == 0, so this is safe.
*/
return (rv);
}
static KMF_RETURN
{
int n = (*ncerts);
} else {
}
return (KMF_ERR_MEMORY);
(*ncerts) = n + 1;
} else {
}
return (rv);
}
static KMF_RETURN
{
int n = (*nkeys);
} else {
sizeof (KMF_RAW_KEY_DATA) * (n + 1));
}
return (KMF_ERR_MEMORY);
(*nkeys) = n + 1;
return (KMF_OK);
}
static KMF_RETURN
{
int i;
/* Convert SSL key to raw key */
case EVP_PKEY_RSA:
&key);
return (rv);
break;
case EVP_PKEY_DSA:
&key);
return (rv);
break;
default:
return (KMF_ERR_BAD_PARAMETER);
}
return (rv);
}
/* Now add the certificate to the certlist */
return (rv);
}
/* Also add any included CA certs to the list */
X509 *c;
/*
* sk_X509_value() is macro that embeds a cast to (X509 *).
* Here it translates into ((X509 *)sk_value((ca), (i))).
* Lint is complaining about the embedded casting, and
* to fix it, you need to fix openssl header files.
*/
/* LINTED E_BAD_PTR_CAST_ALIGN */
c = sk_X509_value(sslcacerts, i);
/* Now add the ca cert to the certlist */
return (rv);
}
return (rv);
}
{
goto end;
}
*ncerts = 0;
*nkeys = 0;
/* Reached end of import file? */
break;
/* Convert keys and certs to exportable format */
if (privkey)
if (cert)
if (cacerts)
}
end:
if (privkey)
if (cert)
if (cacerts)
return (rv);
}
{
/*
* auto-detect the file format, regardless of what
* the 'format' parameters in the params say.
*/
if (rv == KMF_ERR_OPEN_FILE)
return (rv);
}
/* This function only works on PEM files */
if (format != KMF_FORMAT_PEM &&
return (KMF_ERR_ENCODING);
*ncerts = 0;
*nkeys = 0;
/* Reached end of import file? */
/* Convert keys and certs to exportable format */
end:
if (privkey)
return (rv);
}
{
char *fullpath;
} else {
}
} else {
}
return (rv);
return (KMF_ERR_BAD_PARAMETER);
/* If the requested file exists, return an error */
return (KMF_ERR_DUPLICATE_KEYFILE);
}
goto cleanup;
}
if (fullpath)
if (pkey)
if (bio)
/* Protect the file by making it read-only */
}
return (rv);
}
static KMF_RETURN
{
return (KMF_ERR_MEMORY);
}
if (DES_random_key(key) == 0) {
return (KMF_ERR_KEYGEN_FAILED);
}
return (KMF_OK);
}
#define KEYGEN_RETRY 3
#define DES3_KEY_SIZE 24
static KMF_RETURN
create_des3key(unsigned char **des3key)
{
int retry;
return (KMF_ERR_MEMORY);
}
/* create the 1st DES key */
goto out;
}
/*
* Create the 2nd DES key and make sure its value is different
* from the 1st DES key.
*/
retry = 0;
do {
}
goto out;
}
== 0) {
retry++;
}
goto out;
}
/*
* Create the 3rd DES key and make sure its value is different
* from the 2nd DES key.
*/
retry = 0;
do {
}
goto out;
}
== 0) {
retry++;
}
goto out;
}
/* Concatenate 3 DES keys into a DES3 key */
out:
return (ret);
}
{
int fd = -1;
return (KMF_ERR_UNINITIALIZED);
return (KMF_ERR_BAD_PARAMETER);
}
return (KMF_ERR_BAD_PARAMETER);
/* If the requested file exists, return an error */
return (KMF_ERR_DUPLICATE_KEYFILE);
}
if (fd == -1) {
goto out;
}
goto out;
}
goto out;
}
goto out;
}
int bytes;
goto out;
}
goto out;
}
}
goto out;
}
goto out;
}
} else {
goto out;
}
out:
if (fd != -1)
}
}
return (ret);
}
{
int sslret;
unsigned char *p;
long len;
return (KMF_ERR_BAD_PARAMETER);
}
return (ret);
goto cleanup;
}
if (crl_format == KMF_FORMAT_ASN1) {
} else if (crl_format == KMF_FORMAT_PEM) {
} else {
goto cleanup;
}
goto cleanup;
}
goto cleanup;
}
/* Get issuer certificate public key */
if (!pkey) {
goto cleanup;
}
/* Verify CRL signature */
if (sslret > 0) {
} else {
}
return (ret);
}
{
int i;
return (KMF_ERR_BAD_PARAMETER);
}
return (ret);
goto cleanup;
}
if (crl_format == KMF_FORMAT_ASN1) {
} else if (crl_format == KMF_FORMAT_PEM) {
}
goto cleanup;
}
if (i >= 0) {
goto cleanup;
}
if (X509_CRL_get_nextUpdate(xcrl)) {
if (i <= 0) {
goto cleanup;
}
}
return (ret);
}
/*
* Check a file to see if it is a CRL file with PEM or DER format.
* If success, return its format in the "pformat" argument.
*/
{
return (KMF_ERR_BAD_PARAMETER);
}
goto out;
}
goto out;
}
/*
* Now try to read it as raw DER data.
*/
goto out;
}
} else {
}
out:
return (ret);
}
/*
* Check a file to see if it is a certficate file with PEM or DER format.
* If success, return its format in the pformat argument.
*/
{
return (KMF_ERR_BAD_PARAMETER);
}
return (ret);
goto out;
}
if ((*pformat) == KMF_FORMAT_PEM) {
}
} else if ((*pformat) == KMF_FORMAT_ASN1) {
}
} else {
}
out:
return (ret);
}
{
return (KMF_ERR_UNINITIALIZED);
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_BAD_KEY_CLASS);
return (KMF_ERR_BAD_KEYHANDLE);
return (KMF_ERR_MEMORY);
} else {
return (rv);
}
return (rv);
}
/*
* id-sha1 OBJECT IDENTIFIER ::= {
* iso(1) identified-organization(3) oiw(14) secsig(3)
* algorithms(2) 26
* }
*/
#define ASN1_SHA1_OID_PREFIX_LEN 15
0x30, 0x21, 0x30, 0x09,
0x06, 0x05, 0x2b, 0x0e,
0x03, 0x02, 0x1a, 0x05,
0x00, 0x04, 0x14
};
/*
* id-md2 OBJECT IDENTIFIER ::= {
* iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2
* }
*/
#define ASN1_MD2_OID_PREFIX_LEN 18
0x30, 0x20, 0x30, 0x0c,
0x06, 0x08, 0x2a, 0x86,
0x48, 0x86, 0xf7, 0x0d,
0x02, 0x02, 0x05, 0x00,
0x04, 0x10
};
/*
* id-md5 OBJECT IDENTIFIER ::= {
* iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5
* }
*/
#define ASN1_MD5_OID_PREFIX_LEN 18
0x30, 0x20, 0x30, 0x0c,
0x06, 0x08, 0x2a, 0x86,
0x48, 0x86, 0xf7, 0x0d,
0x02, 0x05, 0x05, 0x00,
0x04, 0x10
};
{
uchar_t *p;
return (KMF_ERR_BAD_PARAMETER);
goto cleanup;
}
if (!pkey) {
goto cleanup;
}
if (algid != KMF_ALGID_NONE) {
switch (algid) {
case KMF_ALGID_MD5WithRSA:
break;
case KMF_ALGID_MD2WithRSA:
break;
case KMF_ALGID_SHA1WithRSA:
break;
case KMF_ALGID_RSA:
break;
default:
goto cleanup;
}
} else {
/* Get the hash type from the cert signature */
goto cleanup;
}
}
switch (EVP_MD_type(md)) {
case NID_md2:
case NID_md2WithRSAEncryption:
break;
case NID_md5:
case NID_md5WithRSAEncryption:
break;
case NID_sha1:
break;
default: /* Unsupported */
pfxlen = 0;
break;
}
}
/* RSA with no hash is a special case */
return (KMF_ERR_MEMORY);
/* Decrypt the input signature */
if (len < 1) {
} else {
/*
* If the AlgId requires it, hash the input data before
* comparing it to the decrypted signature.
*/
if (md) {
return (KMF_ERR_MEMORY);
/* Add the prefix to the comparison buffer. */
}
/* Add the digest AFTER the ASN1 prefix */
(void) EVP_DigestFinal(&ctx,
} else {
}
/*
* The result of the RSA decryption should be ASN1(OID | Hash).
* Compare the output hash to the input data for the final
* result.
*/
else
/* If we had to allocate space for the digest, free it now */
if (hashlen)
}
if (pkey)
if (xcert)
if (rsaout)
return (ret);
}