certop.c revision 99ebb4ca412cb0a19d77a3899a87c055b9c30fa8
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Copyright(c) 1995-2000 Intel Corporation. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <link.h>
#include <fcntl.h>
#include <ctype.h>
#include <ber_der.h>
#include <kmfapiP.h>
#include <pem_encode.h>
#include <libgen.h>
#include <cryptoutil.h>
#define CERTFILE_TEMPNAME "/tmp/user.certXXXXXX"
#define CRLFILE_TEMPNAME "/tmp/crlXXXXXX"
#define X509_FORMAT_VERSION 2
static KMF_RETURN
{
return (rv);
/* Get the algorithm info from the signer certificate */
switch (AlgorithmId) {
case KMF_ALGID_MD5WithRSA:
case KMF_ALGID_MD2WithRSA:
case KMF_ALGID_SHA1WithRSA:
break;
case KMF_ALGID_SHA1WithDSA:
break;
default:
}
return (rv);
}
/*
*
* Name: find_private_key_by_cert
*
* Description:
* This function finds the corresponding private key in keystore
* for a certificate
*
* Parameters:
* handle(input) - opaque handle for KMF session
* params(input) - contains parameters used to find the private key
* SignerCertData(input) - pointer to a KMF_DATA structure containing a
* signer certificate
* key(output) - contains the found private key handle
*
* Returns:
* A KMF_RETURN value indicating success or specifying a particular
* error condition.
* The value KMF_OK indicates success. All other values represent
* an error condition.
*
*/
static KMF_RETURN
{
return (KMF_ERR_BAD_PARAMETER);
return (ret);
/* Find the private key from the keystore */
} else {
return (KMF_ERR_PLUGIN_NOTFOUND);
}
}
static KMF_RETURN
check_key_usage(void *handle,
const KMF_KU_PURPOSE purpose)
{
return (KMF_ERR_BAD_PARAMETER);
/*
* If absent or error, the cert is assumed to be invalid
* for all key usage checking.
*/
return (ret);
switch (purpose) {
case KMF_KU_SIGN_CERT:
/*
* RFC 3280:
* The keyCertSign bit is asserted when the subject
* public key is used for verifying a signature on
* public key certificates. If the keyCertSign bit
* is asserted, then the cA bit in the basic constraints
* extension (section 4.2.1.10) MUST also be asserted.
* The basic constraints extension MUST appear as a
* critical extension in all CA certificates that
* contain public keys used to validate digital
* signatures on certificates.
*/
&constraint);
/* real error */
return (ret);
}
return (KMF_ERR_KEYUSAGE);
break;
case KMF_KU_SIGN_DATA:
/*
* RFC 3280:
* The digitalSignature bit is asserted when the subject
* public key is used with a digital signature mechanism
* to support security services other than certificate
* signing(bit 5), or CRL signing(bit 6).
*/
return (KMF_ERR_KEYUSAGE);
break;
case KMF_KU_ENCRYPT_DATA:
/*
* RFC 3280:
* The dataEncipherment bit is asserted when the subject
* public key is used for enciphering user data, other than
* cryptographic keys.
*/
return (KMF_ERR_KEYUSAGE);
break;
default:
return (KMF_ERR_BAD_PARAMETER);
}
return (KMF_OK);
}
{
return (rv);
return (KMF_ERR_BAD_PARAMETER); /* ILLEGAL ARGS ERROR */
return (KMF_ERR_BAD_PARAMETER);
}
return (KMF_ERR_PLUGIN_NOTFOUND);
}
{
return (KMF_ERR_BAD_PARAMETER);
/*
* Validate that all required fields are present.
*/
return (KMF_ERR_INCOMPLETE_TBS_CERT);
}
encodedCert->Length = 0;
/* Pack the new certificate */
return (ret);
}
/*
*
* Name: KMF_SignCertWithKey
*
* Description:
* This function signs a certificate using the private key and
* returns the result as a signed, encoded certificate in SignedCert
*
* Parameters:
* handle(input) - opaque handle for KMF session
* CertToBeSigned(input) - pointer to a KMF_DATA structure containing a
* DER encoded certificate to be signed
* Signkey(input) - pointer to private key handle needed for signing
* SignedCert(output) - pointer to the KMF_DATA structure containing the
* signed certificate
*
* Returns:
* A KMF_RETURN value indicating success or specifying a particular
* error condition.
* The value KMF_OK indicates success. All other values represent
* an error condition.
*
*/
const KMF_DATA *CertToBeSigned,
{
return (err);
if (CertToBeSigned == NULL ||
return (KMF_ERR_BAD_PARAMETER);
return (err);
}
/*
*
* Name: KMF_SignCertWithCert
*
* Description:
* This function signs a certificate using the signer cert and
* returns the result as a signed, encoded certificate in SignedCert
*
* Parameters:
* handle(input) - opaque handle for KMF session
* params(input) - contains parameters to be used for signing
* CertToBeSigned(input) - pointer to a KMF_DATA structure containing a
* DER encoded certificate to be signed
* SignerCert(input) - pointer to a KMF_DATA structure containing a
* signer certificate
* SignedCert(output) - pointer to the KMF_DATA structure containing the
* DER encoded signed certificate
*
* Returns:
* A KMF_RETURN value indicating success or specifying a particular
* error condition.
* The value KMF_OK indicates success. All other values represent
* an error condition.
*
*/
const KMF_DATA *CertToBeSigned,
{
return (ret);
if (CertToBeSigned == NULL ||
return (KMF_ERR_BAD_PARAMETER);
/* check the keyUsage of signer's certificate */
return (ret);
/*
* Retrieve the private key from the keystore for the
* signer certificate.
*/
return (ret);
return (ret);
}
/*
*
* Name: KMF_SignDataWithCert
*
* Description:
* This function signs a block of data using the signer cert and
* returns the the signature in output
*
* Parameters:
* handle(input) - opaque handle for KMF session
* params(input) - contains parameters to be used for signing
* tobesigned(input) - pointer to a KMF_DATA structure containing a
* the data to be signed
* output(output) - pointer to the KMF_DATA structure containing the
* signed data
* SignerCertData(input) - pointer to a KMF_DATA structure containing a
* signer certificate
*
* Returns:
* A KMF_RETURN value indicating success or specifying a particular
* error condition.
* The value KMF_OK indicates success. All other values represent
* an error condition.
*
*/
{
return (ret);
if (tobesigned == NULL ||
return (KMF_ERR_BAD_PARAMETER);
/* check the keyUsage of signer's certificate */
return (ret);
/*
* Retrieve the private key from the keystore based on
* the signer certificate.
*/
&Signkey);
goto cleanup;
}
goto cleanup;
goto cleanup;
/*
* For DSA, NSS returns an encoded signature. Decode the
* signature as DSA signature should be 40-byte long.
*/
if ((AlgId == KMF_ALGID_SHA1WithDSA) &&
goto cleanup;
} else {
}
} else if (AlgId == KMF_ALGID_NONE) {
}
} else {
}
if (SignerCert != NULL) {
}
return (ret);
}
/*
*
* Name: KMF_VerifyCertWithKey
*
* Description:
* This function verifies that the CertToBeVerified was signed
* using a specific private key and that the certificate has not
* been altered since it was signed using that private key
*
* Parameters:
* handle(input) - opaque handle for KMF session
* KMFKey(input) - holds public key information for verification
* CertToBeVerified(input) - A signed certificate whose signature
* is to be verified
*
* Returns:
* A KMF_RETURN value indicating success or specifying a particular
* error condition. The value KMF_OK indicates success. All other
* values represent an error condition.
*/
const KMF_DATA *CertToBeVerified)
{
return (err);
CertToBeVerified == NULL)
return (KMF_ERR_BAD_PARAMETER);
/* The keystore must extract the pubkey data */
} else {
return (KMF_ERR_PLUGIN_NOTFOUND);
}
/* check the caller and do other setup for this SPI call */
}
return (err);
}
/*
*
* Name: KMF_VerifyCertWithCert
*
* Description:
* Function to verify the signature of a signed certificate
*
* Parameters:
* handle - pointer to KMF handle
* CertToBeVerified(input) - pointer to the signed certificate
* SignerCert(input) - pointer to certificate used in signing
*
* Returns:
* A KMF_RETURN value.
* The value KMF_OK indicates success.
* All other values represent an error condition.
*/
const KMF_DATA *CertToBeVerified,
const KMF_DATA *SignerCert)
{
return (ret);
if (CertToBeVerified == NULL ||
SignerCert == NULL)
return (KMF_ERR_BAD_PARAMETER);
/* check the keyUsage of signer's certificate */
return (ret);
return (ret);
}
/*
*
* Name: KMF_VerifyDataWithCert
*
* Description:
* This function verifies the signature of a block of data using a signer
* certificate.
*
* Parameters:
* handle(input) - opaque handle for KMF session
* indata(input) - pointer to the block of data whose signature
* is to be verified
* insig(input) - pointer to the signature to be verified
* SignerCert(input) - pointer to signer cert for verification
*
* Returns:
* A KMF_RETURN value indicating success or specifying a particular
* error condition.
* The value KMF_OK indicates success. All other values represent
* an error condition.
*
*/
const KMF_DATA *SignerCert)
{
return (ret);
if (SignerCert == NULL ||
return (KMF_ERR_BAD_PARAMETER);
/* check the keyUsage of signer's certificate */
return (ret);
}
/*
* Name: KMF_EncryptWithCert
*
* Description:
* Uses the public key from the cert to encrypt the plaintext
* into the ciphertext.
*
* Parameters:
* handle(input) - opaque handle for KMF session
* cert(input) - pointer to a DER encoded certificate for encryption
* by using its public key
* plaintext(input) - pointer to the plaintext to be encrypted
* ciphertext(output) - pointer to the ciphertext contains
* encrypted data
*
* Returns:
* A KMF_RETURN value indicating success or specifying a particular
* error condition.
* The value KMF_OK indicates success. All other values represent
* an error condition.
*
*/
{
return (ret);
return (KMF_ERR_BAD_PARAMETER);
/* check the keyUsage of the certificate */
return (ret);
}
/*
* Name: KMF_DecryptWithCert
*
* Description:
* Uses the private key associated with the cert to decrypt
* the ciphertext into the plaintext.
*
* Parameters:
* handle(input) - opaque handle for KMF session
* params(input) - contains parameters to be used to find the private
* key for decryption
* cert(input) - pointer to a DER encoded certificate for decryption
* by using its private key
* ciphertext(input) - pointer to the ciphertext contains to be
* decrypted data
* plaintext(output) - pointer to the plaintext after decryption
*
* Returns:
* A KMF_RETURN value indicating success or specifying a particular
* error condition.
* The value KMF_OK indicates success. All other values represent
* an error condition.
*
*/
{
return (ret);
return (KMF_ERR_BAD_PARAMETER);
/* check the keyUsage of the certificate */
return (ret);
/*
* Retrieve the private key from the keystore based on
* the certificate.
*/
return (ret);
}
/* Decode the cert so we can get the alogorithm */
goto cleanup;
/* DSA does not support decrypt */
if (AlgorithmId == KMF_ALGID_DSA) {
goto cleanup;
}
} else {
}
return (ret);
}
{
return (ret);
return (KMF_ERR_BAD_PARAMETER);
} else {
return (KMF_ERR_PLUGIN_NOTFOUND);
}
}
{
return (ret);
return (KMF_ERR_BAD_PARAMETER);
} else {
return (KMF_ERR_PLUGIN_NOTFOUND);
}
}
{
return (ret);
return (KMF_ERR_BAD_PARAMETER);
} else {
return (KMF_ERR_PLUGIN_NOTFOUND);
}
}
/*
* This function gets the CRL URI entries from the certificate's Distribution
* points extension, and downloads the CRL file. The function also returns
* the URI string and the format of the CRL file. The caller should free
* the space allocated for the returned URI string.
*/
static KMF_RETURN
{
char uri[1024];
char *proxy_port_s = NULL;
int proxy_port = 0;
int i, j;
return (KMF_ERR_BAD_PARAMETER);
/* Get the proxy info */
if (proxy_port_s != NULL) {
} else {
}
}
/*
* Get the CRL URI from the certificate's CRL Distribution
* Points extension and download the CRL file. There maybe more than
* one CRL URI entries in the DP extension, so we will continue
* the process until a CRL file is sucessfully downloaded or we
* are running out the CRL URI's.
*/
&crl_dps);
goto out;
if (done)
break;
goto out;
}
break;
}
}
}
out:
return (ret);
}
static KMF_RETURN
{
char user_certfile[MAXPATHLEN];
char crlfile_tmp[MAXPATHLEN];
char *basefilename = NULL;
char *crlfilename = NULL;
return (KMF_ERR_BAD_PARAMETER);
/*
* If the get-crl-uri policy is TRUE, then download the CRL
* file first. The newly downloaded file will be stored in the
* NSS internal database for NSS keystore, and stored in a file for
* the File-based CRL plugins (OpenSSL and PKCS11).
*
* For file-based plugins, if the get-crl-uri policy is FALSE,
* then the caller should provide a CRL file in the policy.
* Also, after this step is done, the "crlfilename" variable should
* contain the proper CRL file to be used for the rest of CRL
* validation process.
*/
/*
* Create a temporary file to hold the new CRL file initially.
*/
sizeof (crlfile_tmp));
goto cleanup;
}
/*
* Get the URI entry from the certificate's CRL distribution
* points extension and download the CRL file.
*/
(void) unlink(crlfile_tmp);
goto cleanup;
}
/* Cache the CRL file. */
/*
* For NSS keystore, import this CRL file into th
* internal database.
*/
(void) unlink(crlfile_tmp);
goto cleanup;
} else {
/*
* For File-based CRL plugin's, find the cache
* location from the CRL policy's attributes and
* cache it.
*/
if (basefilename == NULL)
if (crlfilename == NULL) {
(void) unlink(crlfile_tmp);
goto cleanup;
}
(void) unlink(crlfile_tmp);
goto cleanup;
}
}
} else {
/*
* If the get_crl_uri policy is FALSE, for File-based CRL
* plugins, get the input CRL file from the policy.
*/
if (basefilename == NULL) {
goto cleanup;
}
if (crlfilename == NULL) {
goto cleanup;
}
}
}
/*
* Check the CRL signature if needed.
*/
/*
* NSS CRL is not file based, and its signature
* has been verified during CRL import.
*/
goto cleanup;
}
}
}
/*
* Check the CRL validity if needed.
*/
/*
* This is for file-based CRL, but not for NSS CRL.
*/
goto cleanup;
}
}
}
/*
* Check the CRL revocation for the certificate.
*/
case KMF_KEYSTORE_NSS:
break;
case KMF_KEYSTORE_PK11TOKEN:
/*
* Create temporary file to hold the user certificate.
*/
sizeof (user_certfile));
goto cleanup;
}
goto cleanup;
}
break;
case KMF_KEYSTORE_OPENSSL:
break;
default:
goto cleanup;
}
if (ret == KMF_ERR_NOT_REVOKED) {
}
(void) unlink(user_certfile);
if (crlfilename != NULL)
return (ret);
}
static KMF_RETURN
{
issuer_cert == NULL)
return (KMF_ERR_BAD_PARAMETER);
/*
* Get the response lifetime from policy.
*/
< 0))
return (KMF_ERR_OCSP_RESPONSE_LIFETIME);
/*
* Get the ignore_response_sign policy.
*
* If ignore_response_sign is FALSE, we need to verify the response.
* Find the OCSP Responder certificate if it is specified in the OCSP
* policy.
*/
if (ignore_response_sign == B_FALSE &&
char *signer_name;
return (KMF_ERR_POLICY_NOT_FOUND);
if (signer_cert == NULL) {
goto out;
}
goto out;
}
case KMF_KEYSTORE_NSS:
break;
case KMF_KEYSTORE_OPENSSL:
break;
case KMF_KEYSTORE_PK11TOKEN:
break;
default:
goto out;
break;
}
num = 0;
if (num == 0)
if (num > 0)
goto out;
}
} else {
goto out;
}
}
/*
* If the caller provides an OCSP response, we will use it directly.
* Otherwise, we will try to fetch an OCSP response for the given
* certificate now.
*/
if (new_response == NULL) {
goto out;
}
new_response->Length = 0;
goto out;
}
/*
* Process the OCSP response and retrieve the certificate status.
*/
switch (resp_params_out.cert_status) {
case OCSP_GOOD:
break;
case OCSP_UNKNOWN:
break;
case OCSP_REVOKED:
break;
}
}
out:
if (new_response) {
}
if (signer_cert) {
}
return (ret);
}
static KMF_RETURN
{
return (KMF_ERR_BAD_PARAMETER);
if (ret == KMF_ERR_EXTENSION_NOT_FOUND) {
/* keyusage is not set in cert but is set in policy */
return (KMF_ERR_KEYUSAGE);
} else {
/* no keyusage set in both cert and policy */
return (KMF_OK);
}
}
/* real error */
return (ret);
}
/*
* Rule: if the KU bit is set in policy, the corresponding KU bit
* must be set in the certificate (but not vice versa).
*/
return (KMF_OK);
} else {
return (KMF_ERR_KEYUSAGE);
}
}
static KMF_RETURN
{
int i;
return (KMF_ERR_BAD_PARAMETER);
&critical, &constraint);
/* real error */
return (ret);
}
if (constraint.cA) {
/* EKU extension appears only in end entity certificates */
return (KMF_ERR_KEYUSAGE);
}
/* real error */
return (ret);
}
if (ret == KMF_ERR_EXTENSION_NOT_FOUND) {
cert_eku = 0;
} else {
/*
* Build the EKU bitmap based on the certificate
*/
(KMF_OID *)&KMFOID_PKIX_KP_ServerAuth)) {
(KMF_OID *)&KMFOID_PKIX_KP_ClientAuth)) {
(KMF_OID *)&KMFOID_PKIX_KP_CodeSigning)) {
(KMF_OID *)&KMFOID_PKIX_KP_TimeStamping)) {
(KMF_OID *)&KMFOID_PKIX_KP_OCSPSigning)) {
} else if (!policy->ignore_unknown_ekus) {
return (KMF_ERR_KEYUSAGE);
}
} /* for */
}
/*
* Build the EKU bitmap based on the policy
*/
(KMF_OID *)&KMFOID_PKIX_KP_ServerAuth)) {
(KMF_OID *)&KMFOID_PKIX_KP_ClientAuth)) {
(KMF_OID *)&KMFOID_PKIX_KP_CodeSigning)) {
(KMF_OID *)&KMFOID_PKIX_KP_TimeStamping)) {
(KMF_OID *)&KMFOID_PKIX_KP_OCSPSigning)) {
} else if (!policy->ignore_unknown_ekus) {
return (KMF_ERR_KEYUSAGE);
}
} /* for */
/*
* Rule: if the EKU OID is set in policy, the corresponding EKU OID
* must be set in the certificate (but not vice versa).
*/
return (KMF_OK);
} else {
return (KMF_ERR_KEYUSAGE);
}
}
static KMF_RETURN
char *user_issuer,
{
return (KMF_ERR_BAD_PARAMETER);
case KMF_KEYSTORE_NSS:
break;
case KMF_KEYSTORE_OPENSSL:
/* setup dirpath to search for TA in a directory */
} else {
}
break;
case KMF_KEYSTORE_PK11TOKEN:
break;
default:
return (KMF_ERR_PLUGIN_NOTFOUND);
}
num = 0;
sizeof (KMF_X509_DER_CERT));
goto out;
}
sizeof (KMF_X509_DER_CERT));
goto out;
}
} else {
goto out;
}
if (num == 1) {
/* only one issuer cert is found */
} else {
/*
* More than one issuer certs are found. We will
* pick the latest one.
*/
latest = 0;
for (i = 0; i < num; i++) {
&t_notbefore, &t_notafter);
goto out;
}
if (t_notbefore > latest) {
}
}
}
goto out;
}
out:
for (i = 0; i < num; i++)
}
return (ret);
}
static KMF_RETURN
{
char *ta_name;
char *ta_subject = NULL;
return (KMF_ERR_BAD_PARAMETER);
goto out;
}
case KMF_KEYSTORE_NSS:
break;
case KMF_KEYSTORE_OPENSSL:
/* setup dirpath to search for TA in a directory */
} else {
}
break;
case KMF_KEYSTORE_PK11TOKEN:
break;
default:
goto out;
}
num = 0;
if (num == 0)
if (num > 1)
goto out;
}
goto out;
}
} else {
goto out;
}
/*
* The found TA's name must be matching with issuer name in
* subscriber's certificate.
*/
goto out;
goto out;
out:
if (ta_subject)
return (ret);
}
int *result)
{
return (ret);
return (KMF_ERR_BAD_PARAMETER);
else
return (KMF_ERR_PLUGIN_NOTFOUND);
/*
* Find the Subscriber's certificate based on the input parameter
*/
if (num == 0)
if (num > 1)
goto out;
}
} else {
goto out;
}
&user_issuer)) != KMF_OK) {
goto out;
}
goto out;
}
&user_subject)) != KMF_OK) {
goto out;
}
goto out;
}
/*
* this is a self-signed cert
*/
}
/*
* Check KeyUsage extension of the subscriber's certificate
*/
goto out;
}
/*
* Validate Extended KeyUsage extension
*/
goto out;
}
/*
* Check the certificate's validity period
*
* This step is needed when "ignore_date" in policy is set
* to false.
*/
if (!policy->ignore_date) {
/*
* Validate expiration date
*/
goto out;
}
}
/*
* When "ignore_trust_anchor" in policy is set to FALSE,
* we will try to find the TA cert based on the TA policy
* attributes.
*
* TA's subject name (ta_name) and serial number (ta_serial)
* are defined as optional attributes in policy dtd, but they
* should exist in policy when "ignore_trust_anchor" is set
* to FALSE. The policy verification code has enforced that.
*/
if (policy->ignore_trust_anchor) {
goto check_revocation;
}
goto out;
}
/*
* Verify the signature of subscriber's certificate using
* TA certificate.
*/
if (self_signed) {
} else {
}
goto out;
}
/*
* Check certificate revocation
*/
if (self_signed) {
/* skip revocation checking */
goto out;
}
/*
* When CRL or OCSP revocation method is set in the policy,
* we will try to find the issuer of the subscriber certificate
* using the issuer name of the subscriber certificate. The
* issuer certificate will be used to do the CRL checking
* and OCSP checking.
*/
goto out;
}
&issuer_cert);
goto out;
}
&user_cert, &issuer_cert);
goto out;
}
}
goto out;
}
}
out:
if (user_issuer) {
}
if (user_subject)
if (issuer_cert.Data)
return (ret);
}
char *certfile)
{
int fd = -1;
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_BAD_PARAMETER);
if (format == KMF_FORMAT_PEM) {
int len;
goto cleanup;
}
goto cleanup;
}
if (format == KMF_FORMAT_PEM) {
}
} else {
}
}
if (fd != -1)
return (rv);
}
{
return (ret);
return (KMF_ERR_BAD_PARAMETER);
}
/*
* This framework function is actually implemented in the openssl
* plugin library, so we find the function address and call it.
*/
return (KMF_ERR_PLUGIN_NOTFOUND);
}
"OpenSSL_IsCertFile");
if (IsCertFileFn == NULL) {
return (KMF_ERR_FUNCTION_NOT_FOUND);
}
}
/*
* This function checks the validity period of a der-encoded certificate.
*/
{
return (rv);
return (KMF_ERR_BAD_PARAMETER);
return (rv);
/*
* Get the current time. The time returned from time() is local which
*/
/*
* Adjust the validity time
*/
return (KMF_ERR_VALIDITY_PERIOD);
} else {
adj = 0;
}
t_notafter += adj;
t_notbefore -= adj;
} else {
}
return (rv);
}
char *filename)
{
int i;
return (rv);
return (KMF_ERR_BAD_PARAMETER);
if (kstype == KMF_KEYSTORE_PK11TOKEN) {
/*
* Special processing because PKCS11 doesn't have
* a native PKCS12 operation.
*/
sizeof (KMF_X509_DER_CERT));
return (KMF_ERR_MEMORY);
sizeof (KMF_X509_DER_CERT));
return (rv);
}
} else {
return (rv);
}
numkeys = 0;
for (i = 0; i < numcerts; i++) {
numkeys++;
numkeys * sizeof (KMF_KEY_HANDLE));
rv = KMF_ERR_MEMORY;
goto out;
}
} else if (rv == KMF_ERR_KEY_NOT_FOUND) {
/* it is OK if a key is not found */
}
}
/*
* Switch the keystore type to use OpenSSL for
* exporting the raw cert and key data as PKCS12.
*/
} else {
goto out;
}
}
} else {
}
out:
for (i = 0; i < numcerts; i++)
}
for (i = 0; i < numkeys; i++)
}
return (rv);
}
{
char *, KMF_CREDENTIAL *,
KMF_DATA **, int *,
KMF_RAW_KEY_DATA **, int *);
return (rv);
return (KMF_ERR_BAD_PARAMETER);
/*
* Use the pkcs12 reader from the OpenSSL plugin.
*/
return (KMF_ERR_PLUGIN_NOTFOUND);
}
"openssl_read_pkcs12");
if (openpkcs12 == NULL) {
return (KMF_ERR_FUNCTION_NOT_FOUND);
}
/* Use OpenSSL interfaces to get raw key and cert data */
return (rv);
}
{
}
static KMF_RETURN
{
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_MEMORY);
return (KMF_ERR_MEMORY);
} else {
}
return (ret);
}
const KMF_DATA *SubjectCert,
{
if (!SignedCert)
return (KMF_ERR_BAD_PARAMETER);
SignedCert->Length = 0;
if (!SubjectCert)
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_BAD_PARAMETER);
/*
* Shortcut - just extract the already encoded TBS cert data from
* the original data buffer. Since we haven't changed anything,
* there is no need to re-encode it.
*/
&data_to_sign, NULL);
goto cleanup;
}
/* Estimate the signed data length generously */
if (!signed_data.Data) {
goto cleanup;
}
/*
* If we got here OK, decode into a structure and then re-encode
* the complete certificate.
*/
goto cleanup;
}
/* We are re-signing this cert, so clear out old signature data */
}
if (ret)
goto cleanup;
/* Sign the data */
&data_to_sign, &signed_data);
goto cleanup;
/*
* For DSA, KMF_SignDataWithKey() returns a 40-bytes decoded
* signature. So we must encode the signature correctly.
*/
if (algid == KMF_ALGID_SHA1WithDSA) {
goto cleanup;
} else {
}
/* Now, re-encode the cert with the new signature */
/* Cleanup & return */
}
return (ret);
}
const KMF_DATA *CertToBeVerified)
{
/* check the caller and do other setup for this SPI call */
return (KMF_ERR_BAD_PARAMETER);
goto cleanup;
goto cleanup;
/* Decode the signer cert so we can get the Algorithm data */
return (ret);
if (algid == KMF_ALGID_NONE)
return (KMF_ERR_BAD_ALGORITHM);
if (algid == KMF_ALGID_SHA1WithDSA) {
goto cleanup;
} else {
}
&data_to_verify, &signature);
if (signed_cert) {
}
if (algid == KMF_ALGID_SHA1WithDSA) {
}
return (ret);
}
{
return (KMF_ERR_BAD_PARAMETER);
goto cleanup;
return (ret);
}
const KMF_DATA *CertToBeVerifiedData,
const KMF_DATA *SignerCertData)
{
if (!CertToBeVerifiedData ||
!CertToBeVerifiedData->Data ||
return (KMF_ERR_BAD_PARAMETER);
if (!SignerCertData ||
!SignerCertData->Data ||
return (KMF_ERR_BAD_PARAMETER);
/* Decode the cert into parts for verification */
goto cleanup;
/* Decode the signer cert so we can get the SPKI data */
goto cleanup;
/*
* TODO ! Validate the SignerCert to make sure it is OK to be
* used to verify other certs. Or - should this be done the calling
* application?
*/
/* ValidateCert(SignerCert); */
/* Get the public key info from the signer certificate */
/* Decode the to-be-verified cert so we know what algorithm to use */
goto cleanup;
if (algid == KMF_ALGID_SHA1WithDSA) {
goto cleanup;
} else {
}
&data_to_verify, &signature);
if (SignerCert) {
}
if (ToBeVerifiedCert) {
}
if (algid == KMF_ALGID_SHA1WithDSA) {
}
return (ret);
}
const KMF_DATA *SignerCertData)
{
if (!indata ||
return (KMF_ERR_BAD_PARAMETER);
if (!insig ||
return (KMF_ERR_BAD_PARAMETER);
if (!SignerCertData ||
!SignerCertData->Data ||
return (KMF_ERR_BAD_PARAMETER);
/* Decode the signer cert so we can get the SPKI data */
goto cleanup;
/* Get the public key info from the signer certificate */
if (algid == KMF_ALGID_NONE) {
} else {
}
if (SignerCert) {
}
return (ret);
}
const KMF_DATA *SubjectCsr,
{
if (!SignedCsr)
return (KMF_ERR_BAD_PARAMETER);
if (!SubjectCsr)
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_BAD_PARAMETER);
/* Estimate the signed data length generously */
if (!signed_data.Data) {
goto cleanup;
}
/* Sign the data */
goto cleanup;
/*
* If we got here OK, decode into a structure and then re-encode
* the complete CSR.
*/
if (ret)
goto cleanup;
if (ret)
goto cleanup;
/* Now, re-encode the CSR with the new signature */
goto cleanup;
}
/* Cleanup & return */
return (ret);
}
{
/* Decode the cert so we can get the SPKI data */
return (ret);
/* Get the public key info from the certificate */
/* Use the algorithm in SPKI to encrypt data */
/* DSA does not support encrypt */
return (KMF_ERR_BAD_ALGORITHM);
}
return (ret);
}