certop.c revision e65e5c2d2f32a99e8c5f740cabae9075dab03ce7
/*
* 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 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#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
static KMF_RETURN
static KMF_RETURN
static KMF_RETURN
static KMF_RETURN
{
return (rv);
/* Get the algorithm info from the signer certificate */
switch (AlgorithmId) {
case KMF_ALGID_MD5WithRSA:
case KMF_ALGID_SHA1WithRSA:
case KMF_ALGID_SHA256WithRSA:
case KMF_ALGID_SHA384WithRSA:
case KMF_ALGID_SHA512WithRSA:
break;
case KMF_ALGID_SHA1WithDSA:
case KMF_ALGID_SHA256WithDSA:
break;
case KMF_ALGID_SHA1WithECDSA:
case KMF_ALGID_ECDSA:
break;
default:
}
return (rv);
}
/*
* Name: kmf_find_prikey_by_cert
*
* Description:
* This function finds the corresponding private key in keystore
* for a certificate
*/
{
sizeof (KMF_KEY_HANDLE)}
};
int num_req_attrs = sizeof (required_attrs) /
sizeof (KMF_ATTRIBUTE_TESTER);
return (KMF_ERR_BAD_PARAMETER);
return (ret);
/*
* First, get the key algorithm info from the certificate and saves it
* in the returned key handle.
*/
return (KMF_ERR_BAD_PARAMETER);
return (ret);
return (KMF_ERR_BAD_PARAMETER);
/* Call the plugin to do the work. */
return (ret);
return (KMF_ERR_PLUGIN_NOTFOUND);
}
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);
}
{
};
int num_req_attrs = sizeof (required_attrs) /
sizeof (KMF_ATTRIBUTE_TESTER);
return (KMF_ERR_BAD_PARAMETER);
return (ret);
return (ret);
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);
}
/*
* This function is used to setup the attribute list before calling
* kmf_find_prikey_by_cert(). This function is used by
* kmf_decrypt_with_cert
* kmf_sign_cert
* kmf_sign_data
*
* The attribute list in these callers contain all the attributes
* needed by kmf_find_prikey_by_cert(), except the
* KMF_KEY_HANDLE attribute and the KMF_CERT_DATA_ATTR attribute.
* These 2 attributes need to be added or reset.
*
* The caller should free the new_attrlist after use it.
*/
static KMF_RETURN
{
int index;
int i;
return (KMF_ERR_BAD_PARAMETER);
/* Create a new attribute list with 2 more elements */
return (KMF_ERR_MEMORY);
/* Copy the src_attrlist to the new list */
for (i = 0; i < src_num; i++) {
}
/* Add or reset the key handle attribute */
if (index == -1) {
/* not found; add it */
cur_num++;
} else {
/* found; just reset it */
}
/* add or reset the cert data attribute */
if (index == -1) {
/* not found; add it */
cur_num++;
} else {
/* found; just reset it */
}
*new_attrlist = attrlist;
return (KMF_OK);
}
/*
* Name: kmf_sign_cert
*
* Description:
* This function signs a certificate using the signer cert and
* returns a signed and DER-encoded certificate.
*
* The following types of certificate data can be submitted to be signed:
* KMF_TBS_CERT_DATA_ATTR - a KMF_DATA ptr is provided in the attrlist
* and is signed directly.
* KMF_X509_CERTIFICATE_ATTR - a KMF_X509_CERTIFICATE record is provided
* in the attribute list. This is converted to raw KMF_DATA
* prior to signing.
*
* The key for the signing operation can be provided as a KMF_KEY_HANDLE_ATTR
* or the caller may choose to provide a KMF_SIGNER_CERT_ATTR (KMF_DATA *).
* If the latter, this function will then attempt to find the private key
* associated with the certificate. The private key must be stored in
* the same keystore as the signer certificate.
*/
{
int freethekey = 0;
};
int num_req_attrs = sizeof (required_attrs) /
sizeof (KMF_ATTRIBUTE_TESTER);
return (KMF_ERR_BAD_PARAMETER);
return (ret);
/* Get the signer cert and check its keyUsage */
numattr);
numattr);
/*
* Only accept 1 or the other, not both.
*/
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_BAD_PARAMETER);
if (signer_cert != NULL) {
return (ret);
/*
* Find the private key from the signer certificate by calling
* kmf_find_prikey_by_cert().
*/
goto out;
goto out;
}
sign_key_ptr = &sign_key;
freethekey = 1;
}
/* Now we are ready to sign */
numattr);
numattr);
goto out;
}
/* determine signature OID from cert request */
goto out;
tbs_cert = &unsignedCert;
}
/* If OID still not found, decode the TBS Cert and pull it out */
goto out;
}
numattr);
if (signed_cert == NULL) {
goto out;
}
out:
if (new_attrlist)
(void) free(new_attrlist);
/* If we had to find the key, free it here. */
if (freethekey)
if (decodedTbsCert != NULL) {
}
return (ret);
}
static KMF_RETURN
{
*AlgId = KMF_ALGID_NONE;
/* if no OID and no AlgID, use the signer cert */
return (ret);
if (*AlgId == KMF_ALGID_NONE)
}
return (ret);
}
/*
* Name: kmf_sign_data
*
* Description:
* This function signs a block of data using the signer cert and
* returns the the signature in output
*/
{
int new_numattr = numattr;
};
int num_req_attrs = sizeof (required_attrs) /
sizeof (KMF_ATTRIBUTE_TESTER);
return (KMF_ERR_BAD_PARAMETER);
return (ret);
/* Get the signer cert and check its keyUsage. */
numattr);
numattr);
return (KMF_ERR_BAD_PARAMETER);
/*
* If a signer cert was given, use it to find the private key
* to use for signing the data.
*/
if (signer_cert != NULL) {
/*
* Signing generic data does not require the
* KeyUsage extension.
*/
return (ret);
/*
* Find the private key from the signer certificate.
*/
goto cleanup;
}
goto cleanup;
}
sign_key_ptr = &sign_key;
}
/* Get the tbs_data and signed_data attributes now */
goto cleanup;
}
goto cleanup;
}
/*
* Get the algorithm index attribute and its oid. If this attribute
* is not provided, then we use the algorithm in the signer cert.
*/
/*
* We need to know the Algorithm ID, it can be found 3 ways:
* 1. caller supplied OID in the attribute list.
* 2. caller supplied Algorithm Index in the attribute list.
* 3. caller supplied neither, but did supply a certificate, find
* the ALG OID from the certificate.
*/
/* If none of the above, return error. */
goto cleanup;
goto cleanup;
/* AlgID was given by caller, convert it to OID */
} else { /* Else, the OID must have been given */
}
/* Now call the plugin function to sign it */
goto cleanup;
}
output);
goto cleanup;
/*
* For DSA, NSS returns an encoded signature. Decode the
* signature and expect a 40-byte DSA signature.
*/
(AlgId == KMF_ALGID_SHA1WithDSA ||
AlgId == KMF_ALGID_SHA256WithDSA)) {
goto cleanup;
}
if (new_attrlist != NULL)
return (ret);
}
/*
* kmf_verify_data
*
* This routine will try to verify a block of data using
* either a public key or a certificate as the source
* of the verification (the key).
*
* The caller may provider either a KMF_KEY_HANDLE_ATTR or
* a KMF_SIGNER_CERT_DATA_ATTR (with a KMF_DATA record) to
* use for the key to the verification step. If a certificate
* is used and that certificate has the KeyUsage extension,
* the SIGN-DATA bit must be set. Also, if a certificate
* is used, the verification will be done in a specific
* keystore mechanism.
*
* If a KMF_KEY_HANDLE is given in the attribute list, the
* verification will occur in the framework itself using
* PKCS#11 C_Verify functions.
*/
int num_args,
{
sizeof (KMF_DATA)},
sizeof (KMF_DATA)}
};
int num_req_attrs = sizeof (required_attrs) /
sizeof (KMF_ATTRIBUTE_TESTER);
return (KMF_ERR_BAD_PARAMETER);
return (ret);
return (ret);
num_args);
return (KMF_ERR_BAD_PARAMETER);
}
/* We only need the algorithm index if we don't have a signer cert. */
return (ret);
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_BAD_PARAMETER);
/* If the caller passed a signer cert instead of a key use it. */
if (signer_cert != NULL) {
return (ret);
/* Decode the signer cert so we can get the SPKI data */
return (ret);
/* If no algorithm specified, use the certs signature alg */
if (sigAlg == KMF_ALGID_NONE)
if (sigAlg == KMF_ALGID_NONE) {
return (KMF_ERR_BAD_ALGORITHM);
}
/*
* Verify the data locally (i.e. using PKCS#11).
* The verify operation uses a public key and does not
* require access to a specific keystore. Save time
* (and code) by just using the frameworks implementation
* of the verify operation using crypto framework
* APIs.
*/
} else {
/* Retrieve public key data from keystore */
} else {
return (KMF_ERR_PLUGIN_NOTFOUND);
}
}
return (ret);
}
/*
* Name: kmf_verify_cert
*
* Description:
* This function verifies that the a certificate was signed
* using a specific private key and that the certificate has not
* been altered since it was signed using that private key
* The public key used for verification may be given in the
* attribute list as a KMF_KEY_HANDLE or the caller may give
* just the signing certificate (as KMF_SIGNER_CERT_DATA_ATTR)
* from which the public key needed for verification can be
* derived.
*
* Parameters:
* handle(input) - opaque handle for KMF session
* numattr - number of attributes in the list
* attrlist - KMF_ATTRIBUTES
*
* 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.
*/
{
};
int num_req_attrs = sizeof (required_attrs) /
sizeof (KMF_ATTRIBUTE_TESTER);
return (ret);
return (ret);
numattr);
/*
* Caller must provide at least a key handle or a cert to use
* as the "key" for verification.
*/
return (KMF_ERR_BAD_PARAMETER);
numattr);
if (CertToBeVerified == NULL)
return (KMF_ERR_BAD_PARAMETER);
if (SignerCert != NULL) {
} else {
/*
* The keystore must extract the pubkey data because
* the framework doesn't have access to the raw key bytes
* that are needed to construct the DER encoded public
* key information needed for the verify operation.
*/
NULL) {
} else {
return (KMF_ERR_PLUGIN_NOTFOUND);
}
}
}
return (ret);
}
/*
* Name: kmf_encrypt
*
* 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.
*
*/
{
sizeof (KMF_DATA)},
sizeof (KMF_DATA)},
sizeof (KMF_DATA)}
};
int num_req_attrs = sizeof (required_attrs) /
sizeof (KMF_ATTRIBUTE_TESTER);
return (ret);
return (ret);
numattr);
numattr);
numattr);
return (KMF_ERR_BAD_PARAMETER);
/* check the keyUsage of the certificate */
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 */
/* [EC]DSA does not support encrypt */
if (algid == KMF_ALGID_DSA ||
algid == KMF_ALGID_SHA1WithDSA ||
algid == KMF_ALGID_SHA256WithDSA ||
algid == KMF_ALGID_SHA1WithECDSA ||
algid == KMF_ALGID_NONE) {
return (KMF_ERR_BAD_ALGORITHM);
}
/*
* Encrypt using the crypto framework (not the KMF plugin mechanism).
*/
return (ret);
}
/*
* Name: kmf_decrypt
*
* Description:
* Uses the private key associated with the cert to decrypt
* the ciphertext into the plaintext.
*/
{
int new_numattr;
sizeof (KMF_DATA)},
sizeof (KMF_DATA)},
};
int num_req_attrs = sizeof (required_attrs) /
sizeof (KMF_ATTRIBUTE_TESTER);
return (KMF_ERR_BAD_PARAMETER);
return (ret);
/* Get the cert and check its keyUsage */
numattr);
return (KMF_ERR_BAD_PARAMETER);
/* check the keyUsage of the certificate */
return (ret);
/* Get the ciphertext and plaintext attributes */
numattr);
if (ciphertext == NULL)
return (KMF_ERR_BAD_PARAMETER);
numattr);
return (KMF_ERR_BAD_PARAMETER);
/*
* Retrieve the private key from the keystore based on
* the certificate.
*/
goto cleanup;
goto cleanup;
/* Decode the cert so we can get the alogorithm */
goto cleanup;
/* [EC]DSA does not support decrypt */
if (AlgorithmId == KMF_ALGID_DSA ||
AlgorithmId == KMF_ALGID_ECDSA) {
goto cleanup;
}
} else {
}
if (new_attrlist != NULL)
return (ret);
}
{
};
int num_req_attrs = sizeof (required_attrs) /
sizeof (KMF_ATTRIBUTE_TESTER);
return (KMF_ERR_BAD_PARAMETER);
return (ret);
return (ret);
return (KMF_ERR_PLUGIN_NOTFOUND);
}
{
};
int num_req_attrs = sizeof (required_attrs) /
sizeof (KMF_ATTRIBUTE_TESTER);
return (KMF_ERR_BAD_PARAMETER);
return (ret);
return (ret);
return (KMF_ERR_PLUGIN_NOTFOUND);
}
{
};
int num_req_attrs = sizeof (required_attrs) /
sizeof (KMF_ATTRIBUTE_TESTER);
return (KMF_ERR_BAD_PARAMETER);
return (ret);
return (ret);
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
{
return (KMF_ERR_BAD_PARAMETER);
/*
* NSS CRL is not file based, and its signature
* has been verified during CRL import.
* We only check CRL validity for file-based CRLs,
* NSS handles these checks internally.
*/
if (kstype == KMF_KEYSTORE_NSS)
return (KMF_OK);
/*
* Check the CRL signature if needed.
*/
return (ret);
}
/*
* Check the CRL validity if needed.
*/
return (ret);
}
return (ret);
}
static KMF_RETURN
{
int numattr = 0;
int fd;
char user_certfile[MAXPATHLEN];
char crlfile_tmp[MAXPATHLEN];
char *basefilename = NULL;
char *crlfilename = NULL;
issuer_cert == NULL)
return (KMF_ERR_BAD_PARAMETER);
if (!is_valid_keystore_type(*kstype))
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.
*/
/*
* Check to see if we already have this CRL.
*/
if (basefilename == NULL)
if (crlfilename == NULL) {
goto cleanup;
}
/*
* If this file already exists and is valid, we don't need to
* download a new one.
*/
goto checkcrl;
}
}
/*
* 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;
}
/*
* If we just downloaded one, make sure it is OK.
*/
issuer_cert)) != KMF_OK)
return (ret);
/* Cache the CRL file. */
if (*kstype == KMF_KEYSTORE_NSS) {
/*
* For NSS keystore, import this CRL file into th
* internal database.
*/
numattr = 0;
numattr++;
numattr++;
numattr++;
(void) unlink(crlfile_tmp);
goto cleanup;
} else {
(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 (*kstype != KMF_KEYSTORE_NSS) {
if (basefilename == NULL) {
goto cleanup;
}
if (crlfilename == NULL) {
goto cleanup;
}
/*
* Make sure this CRL is still valid.
*/
return (ret);
}
}
/*
* Check the CRL revocation for the certificate.
*/
numattr = 0;
numattr++;
switch (*kstype) {
case KMF_KEYSTORE_NSS:
numattr++;
break;
case KMF_KEYSTORE_PK11TOKEN:
case KMF_KEYSTORE_OPENSSL:
/*
* Create temporary file to hold the user certificate.
*/
sizeof (user_certfile));
goto cleanup;
}
goto cleanup;
}
numattr++;
numattr++;
break;
default:
goto cleanup;
}
if (ret == KMF_ERR_NOT_REVOKED) {
}
(void) unlink(user_certfile);
if (crlfilename != NULL)
return (ret);
}
static KMF_RETURN
{
int response_status;
int reason;
int cert_status;
int numattr;
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;
int fc_numattr = 0;
char *dir = "./";
return (KMF_ERR_POLICY_NOT_FOUND);
if (signer_cert == NULL) {
goto out;
}
goto out;
}
sizeof (KMF_KEYSTORE_TYPE));
fc_numattr++;
fc_numattr++;
&sernum, sizeof (KMF_BIGINT));
fc_numattr++;
fc_numattr++;
}
if (*kstype == KMF_KEYSTORE_OPENSSL) {
fc_numattr++;
} else {
fc_numattr++;
}
}
num = 0;
fc_numattr++;
if (num == 0)
if (num > 0)
goto out;
}
sizeof (KMF_X509_DER_CERT));
fc_numattr++;
} 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.
*/
numattr = 0;
issuer_cert, sizeof (KMF_DATA));
numattr++;
numattr++;
if (signer_cert != NULL) {
numattr++;
}
numattr++;
numattr++;
sizeof (boolean_t));
numattr++;
KMF_OCSP_RESPONSE_STATUS_ATTR, &response_status, sizeof (int));
numattr++;
KMF_OCSP_RESPONSE_REASON_ATTR, &reason, sizeof (int));
numattr++;
KMF_OCSP_RESPONSE_CERT_STATUS_ATTR, &cert_status, sizeof (int));
numattr++;
switch (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);
}
/*
* If KeyCertSign is set, then constraints.cA must be TRUE and
* marked critical.
*/
&critical, &constraint);
/* real error */
return (ret);
}
return (KMF_ERR_KEYUSAGE);
}
/*
* 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);
/*
* If the policy does not have any EKU, then there is
* nothing further to check.
*/
return (KMF_OK);
/* 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
{
int fc_numattr = 0;
char *dir = "./";
issuer_cert == NULL)
return (KMF_ERR_BAD_PARAMETER);
if (!is_valid_keystore_type(*kstype))
return (KMF_ERR_BAD_PARAMETER);
kstype, sizeof (KMF_KEYSTORE_TYPE));
fc_numattr++;
fc_numattr++;
fc_numattr++;
}
if (*kstype == KMF_KEYSTORE_OPENSSL) {
fc_numattr++;
} else {
fc_numattr++;
}
}
num = 0;
fc_numattr++;
sizeof (KMF_X509_DER_CERT));
goto out;
}
sizeof (KMF_X509_DER_CERT));
fc_numattr++;
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;
int fc_numattr = 0;
char *dir = "./";
user_issuerDN == NULL)
return (KMF_ERR_BAD_PARAMETER);
if (!is_valid_keystore_type(*kstype))
return (KMF_ERR_BAD_PARAMETER);
/* Get the TA name and serial number from the policy */
goto out;
}
/* set up fc_attrlist for kmf_find_cert */
kstype, sizeof (KMF_KEYSTORE_TYPE));
fc_numattr++;
fc_numattr++;
&serial, sizeof (KMF_BIGINT));
fc_numattr++;
fc_numattr++;
}
if (*kstype == KMF_KEYSTORE_OPENSSL) {
fc_numattr++;
} else {
fc_numattr++;
}
}
num = 0;
fc_numattr++;
if (num == 0)
if (num > 1)
goto out;
}
fc_numattr++;
goto out;
}
} else {
goto out;
}
/*
* The found TA's name must be matching with issuer name in
* subscriber's certificate.
*/
goto out;
goto out;
/* Make sure the TA cert has the correct extensions */
}
out:
if (ta_subject)
return (ret);
}
{
};
int num_req_attrs = sizeof (required_attrs) /
sizeof (KMF_ATTRIBUTE_TESTER);
return (KMF_ERR_BAD_PARAMETER);
return (ret);
/* Get the attribute values */
return (KMF_ERR_BAD_PARAMETER);
numattr);
/* Initialize the returned result */
/*
* Get the issuer information from the input certficate first.
*/
&user_issuer)) != KMF_OK) {
goto out;
}
goto out;
}
/*
* Check if the certificate is a self-signed cert.
*/
&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;
}
/*
* Verify the signature of subscriber's certificate using
* TA certificate.
*/
if (self_signed) {
} else {
goto out;
}
}
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;
}
goto out;
}
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);
}
/*
* kmf_is_cert_data
*
* Determine if a KMF_DATA buffer contains an encoded X.509 certificate.
*
* Return:
* KMF_OK if it is a certificate
* KMF_ERR_ENCODING (or other error) if not.
*/
{
int len = 0;
return (KMF_ERR_BAD_PARAMETER);
return (rv);
switch (*fmt) {
case KMF_FORMAT_ASN1:
break;
case KMF_FORMAT_PEM:
/* Convert to ASN.1 DER first */
&d, &len);
return (rv);
break;
case KMF_FORMAT_PKCS12:
case KMF_FORMAT_UNDEF:
default:
return (KMF_ERR_ENCODING);
}
}
return (rv);
}
{
return (ret);
return (KMF_ERR_BAD_PARAMETER);
return (ret);
if (ret == KMF_ERR_BAD_CERT_FORMAT)
return (ret);
}
/*
* 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);
}
{
};
int num_req_attrs = sizeof (required_attrs) /
sizeof (KMF_ATTRIBUTE_TESTER);
return (KMF_ERR_BAD_PARAMETER);
return (ret);
return (ret);
return (KMF_ERR_PLUGIN_NOTFOUND);
}
{
int, KMF_KEY_HANDLE *, KMF_CREDENTIAL *, char *);
return (rv);
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_PLUGIN_NOTFOUND);
}
"openssl_build_pk12");
return (KMF_ERR_FUNCTION_NOT_FOUND);
}
filename);
return (rv);
}
{
KMF_X509_DER_CERT **, int *, KMF_RAW_KEY_DATA **, int *);
return (rv);
return (KMF_ERR_BAD_PARAMETER);
/*
* Use the Keypair reader from the OpenSSL plugin.
*/
return (KMF_ERR_PLUGIN_NOTFOUND);
}
"openssl_import_objects");
if (import_objects == 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_OK);
}
{
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_MEMORY);
return (KMF_ERR_MEMORY);
} else {
}
return (ret);
}
static KMF_RETURN
const KMF_DATA *SubjectCert,
{
int i = 0;
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 */
goto cleanup;
if (ret)
goto cleanup;
}
i++;
Signkey, sizeof (KMF_KEY_HANDLE));
i++;
&data_to_sign, sizeof (KMF_DATA));
i++;
&signed_data, sizeof (KMF_DATA));
i++;
signature_oid, sizeof (KMF_OID));
i++;
/* Sign the data */
goto cleanup;
if (algid == KMF_ALGID_SHA1WithECDSA ||
/* ASN.1 encode ECDSA signature */
goto cleanup;
} else if (algid == KMF_ALGID_SHA1WithDSA ||
algid == KMF_ALGID_SHA256WithDSA) {
/*
* For DSA, kmf_sign_data() returns a 40-byte
* signature. We must encode the signature correctly.
*/
goto cleanup;
} else {
}
/* Now, re-encode the cert with the new signature */
/* Cleanup & return */
}
return (ret);
}
static KMF_RETURN
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 ||
algid == KMF_ALGID_SHA256WithDSA) {
goto cleanup;
} else if (algid == KMF_ALGID_SHA1WithECDSA ||
goto cleanup;
} else {
}
&data_to_verify, &signature);
if (signed_cert) {
}
if (algid == KMF_ALGID_SHA1WithDSA ||
algid == KMF_ALGID_SHA256WithDSA ||
algid == KMF_ALGID_SHA1WithECDSA ||
}
return (ret);
}
/*
* Use a signer cert to verify another certificate's signature.
* This code forces the use of the PKCS11 mechanism for the verify
* operation for the Cryptographic Framework's FIPS-140 boundary.
*/
static KMF_RETURN
const KMF_DATA *CertToBeVerifiedData,
const KMF_DATA *SignerCertData)
{
!CertToBeVerifiedData->Data ||
return (KMF_ERR_BAD_PARAMETER);
if (!SignerCertData ||
!SignerCertData->Data ||
return (KMF_ERR_BAD_PARAMETER);
/* Make sure the signer has proper key usage bits */
return (ret);
/* Decode the cert into parts for verification */
goto cleanup;
/* Decode the to-be-verified cert so we know what algorithm to use */
goto cleanup;
if (algid == KMF_ALGID_SHA1WithDSA ||
algid == KMF_ALGID_SHA256WithDSA) {
goto cleanup;
} else if (algid == KMF_ALGID_SHA1WithECDSA ||
goto cleanup;
} else {
}
goto cleanup;
/*
* Force use of PKCS11 API for kcfd/libelfsign. This is
* required for the Cryptographic Framework's FIPS-140 boundary.
*/
&data_to_verify, &signature);
if (SignerCert) {
}
if (ToBeVerifiedCert) {
}
if (algid == KMF_ALGID_SHA1WithDSA ||
algid == KMF_ALGID_SHA256WithDSA ||
algid == KMF_ALGID_SHA1WithECDSA ||
}
return (ret);
}