2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A *
2N/A * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A#include <stdio.h>
2N/A#include <link.h>
2N/A#include <fcntl.h>
2N/A#include <ctype.h>
2N/A#include <sys/param.h>
2N/A#include <sys/types.h>
2N/A#include <sys/stat.h>
2N/A#include <sys/socket.h>
2N/A
2N/A#include <ber_der.h>
2N/A#include <kmfapiP.h>
2N/A
2N/A#include <pem_encode.h>
2N/A#include <libgen.h>
2N/A#include <cryptoutil.h>
2N/A
2N/Astatic KMF_RETURN
2N/Asetup_crl_call(KMF_HANDLE_T, int, KMF_ATTRIBUTE *, KMF_PLUGIN **);
2N/A
2N/A/*
2N/A *
2N/A * Name: kmf_set_csr_pubkey
2N/A *
2N/A * Description:
2N/A * This function converts the specified plugin public key to SPKI form,
2N/A * and save it in the KMF_CSR_DATA internal structure
2N/A *
2N/A * Parameters:
2N/A * KMFkey(input) - pointer to the KMF_KEY_HANDLE structure containing the
2N/A * public key generated by the plug-in CreateKeypair
2N/A * Csr(input/output) - pointer to a KMF_CSR_DATA structure containing
2N/A * SPKI
2N/A *
2N/A * Returns:
2N/A * A KMF_RETURN value indicating success or specifying a particular
2N/A * error condition.
2N/A * The value KMF_OK indicates success. All other values represent
2N/A * an error condition.
2N/A *
2N/A */
2N/AKMF_RETURN
2N/Akmf_set_csr_pubkey(KMF_HANDLE_T handle,
2N/A KMF_KEY_HANDLE *KMFKey,
2N/A KMF_CSR_DATA *Csr)
2N/A{
2N/A KMF_RETURN ret;
2N/A KMF_X509_SPKI *spki_ptr;
2N/A KMF_PLUGIN *plugin;
2N/A KMF_DATA KeyData = {NULL, 0};
2N/A
2N/A CLEAR_ERROR(handle, ret);
2N/A if (ret != KMF_OK)
2N/A return (ret);
2N/A
2N/A if (KMFKey == NULL || Csr == NULL) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A /* The keystore must extract the pubkey data */
2N/A plugin = FindPlugin(handle, KMFKey->kstype);
2N/A if (plugin != NULL && plugin->funclist->EncodePubkeyData != NULL) {
2N/A ret = plugin->funclist->EncodePubkeyData(handle,
2N/A KMFKey, &KeyData);
2N/A } else {
2N/A return (KMF_ERR_PLUGIN_NOTFOUND);
2N/A }
2N/A
2N/A spki_ptr = &Csr->csr.subjectPublicKeyInfo;
2N/A
2N/A ret = DerDecodeSPKI(&KeyData, spki_ptr);
2N/A
2N/A kmf_free_data(&KeyData);
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/AKMF_RETURN
2N/Akmf_set_csr_version(KMF_CSR_DATA *CsrData, uint32_t version)
2N/A{
2N/A if (CsrData == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A /*
2N/A * From RFC 3280:
2N/A * Version ::= INTEGER { v1(0), v2(1), v3(2) }
2N/A */
2N/A if (version != 0 && version != 1 && version != 2)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A return (set_integer(&CsrData->csr.version, (void *)&version,
2N/A sizeof (uint32_t)));
2N/A}
2N/A
2N/AKMF_RETURN
2N/Akmf_set_csr_subject(KMF_CSR_DATA *CsrData,
2N/A KMF_X509_NAME *subject_name_ptr)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_X509_NAME *temp_name_ptr = NULL;
2N/A
2N/A if (CsrData != NULL && subject_name_ptr != NULL) {
2N/A rv = CopyRDN(subject_name_ptr, &temp_name_ptr);
2N/A if (rv == KMF_OK) {
2N/A CsrData->csr.subject = *temp_name_ptr;
2N/A }
2N/A } else {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A return (rv);
2N/A}
2N/AKMF_RETURN
2N/Akmf_create_csr_file(KMF_DATA *csrdata, KMF_ENCODE_FORMAT format,
2N/A char *csrfile)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A int fd = -1;
2N/A KMF_DATA pemdata = {NULL, 0};
2N/A
2N/A if (csrdata == NULL || csrfile == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A if (format != KMF_FORMAT_PEM && format != KMF_FORMAT_ASN1)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A if (format == KMF_FORMAT_PEM) {
2N/A int len;
2N/A rv = kmf_der_to_pem(KMF_CSR,
2N/A csrdata->Data, csrdata->Length,
2N/A &pemdata.Data, &len);
2N/A if (rv != KMF_OK)
2N/A goto cleanup;
2N/A pemdata.Length = (size_t)len;
2N/A }
2N/A
2N/A if ((fd = open(csrfile, O_CREAT |O_RDWR, 0644)) == -1) {
2N/A rv = KMF_ERR_OPEN_FILE;
2N/A goto cleanup;
2N/A }
2N/A
2N/A if (format == KMF_FORMAT_PEM) {
2N/A if (write(fd, pemdata.Data, pemdata.Length) !=
2N/A pemdata.Length) {
2N/A rv = KMF_ERR_WRITE_FILE;
2N/A }
2N/A } else {
2N/A if (write(fd, csrdata->Data, csrdata->Length) !=
2N/A csrdata->Length) {
2N/A rv = KMF_ERR_WRITE_FILE;
2N/A }
2N/A }
2N/A
2N/Acleanup:
2N/A if (fd != -1)
2N/A (void) close(fd);
2N/A
2N/A kmf_free_data(&pemdata);
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/Akmf_set_csr_extn(KMF_CSR_DATA *Csr, KMF_X509_EXTENSION *extn)
2N/A{
2N/A KMF_RETURN ret = KMF_OK;
2N/A KMF_X509_EXTENSIONS *exts;
2N/A
2N/A if (Csr == NULL || extn == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A exts = &Csr->csr.extensions;
2N/A
2N/A ret = add_an_extension(exts, extn);
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/AKMF_RETURN
2N/Akmf_set_csr_sig_alg(KMF_CSR_DATA *CsrData,
2N/A KMF_ALGORITHM_INDEX sigAlg)
2N/A{
2N/A KMF_OID *alg;
2N/A
2N/A if (CsrData == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A alg = x509_algid_to_algoid(sigAlg);
2N/A
2N/A if (alg != NULL) {
2N/A (void) copy_data((KMF_DATA *)
2N/A &CsrData->signature.algorithmIdentifier.algorithm,
2N/A (KMF_DATA *)alg);
2N/A (void) copy_data(
2N/A &CsrData->signature.algorithmIdentifier.parameters,
2N/A &CsrData->csr.subjectPublicKeyInfo.algorithm.parameters);
2N/A } else {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A return (KMF_OK);
2N/A}
2N/A
2N/AKMF_RETURN
2N/Akmf_set_csr_subject_altname(KMF_CSR_DATA *Csr,
2N/A char *altname, int critical,
2N/A KMF_GENERALNAMECHOICES alttype)
2N/A{
2N/A KMF_RETURN ret = KMF_OK;
2N/A
2N/A if (Csr == NULL || altname == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A ret = kmf_set_altname(&Csr->csr.extensions,
2N/A (KMF_OID *)&KMFOID_SubjectAltName, critical, alttype,
2N/A altname);
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/AKMF_RETURN
2N/Akmf_set_csr_ku(KMF_CSR_DATA *CSRData,
2N/A int critical, uint16_t kubits)
2N/A{
2N/A KMF_RETURN ret = KMF_OK;
2N/A
2N/A if (CSRData == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A ret = set_key_usage_extension(
2N/A &CSRData->csr.extensions, critical, kubits);
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/AKMF_RETURN
2N/Akmf_add_csr_eku(KMF_CSR_DATA *CSRData, KMF_OID *ekuOID,
2N/A int critical)
2N/A{
2N/A KMF_RETURN ret = KMF_OK;
2N/A KMF_X509_EXTENSION *foundextn;
2N/A KMF_X509_EXTENSION newextn;
2N/A BerElement *asn1 = NULL;
2N/A BerValue *extdata = NULL;
2N/A char *olddata = NULL;
2N/A size_t oldsize = 0;
2N/A KMF_X509EXT_EKU ekudata;
2N/A
2N/A if (CSRData == NULL || ekuOID == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A (void) memset(&ekudata, 0, sizeof (KMF_X509EXT_EKU));
2N/A (void) memset(&newextn, 0, sizeof (newextn));
2N/A
2N/A foundextn = FindExtn(&CSRData->csr.extensions,
2N/A (KMF_OID *)&KMFOID_ExtendedKeyUsage);
2N/A if (foundextn != NULL) {
2N/A ret = GetSequenceContents((char *)foundextn->BERvalue.Data,
2N/A foundextn->BERvalue.Length, &olddata, &oldsize);
2N/A if (ret != KMF_OK)
2N/A goto out;
2N/A
2N/A /*
2N/A * If the EKU is already in the cert, then just return OK.
2N/A */
2N/A ret = parse_eku_data(&foundextn->BERvalue, &ekudata);
2N/A if (ret == KMF_OK) {
2N/A if (is_eku_present(&ekudata, ekuOID)) {
2N/A goto out;
2N/A }
2N/A }
2N/A }
2N/A if ((asn1 = kmfder_alloc()) == NULL)
2N/A return (KMF_ERR_MEMORY);
2N/A
2N/A if (kmfber_printf(asn1, "{") == -1) {
2N/A ret = KMF_ERR_ENCODING;
2N/A goto out;
2N/A }
2N/A
2N/A /* Write the old extension data first */
2N/A if (olddata != NULL && oldsize > 0) {
2N/A if (kmfber_write(asn1, olddata, oldsize, 0) == -1) {
2N/A ret = KMF_ERR_ENCODING;
2N/A goto out;
2N/A }
2N/A }
2N/A
2N/A /* Append this EKU OID and close the sequence */
2N/A if (kmfber_printf(asn1, "D}", ekuOID) == -1) {
2N/A ret = KMF_ERR_ENCODING;
2N/A goto out;
2N/A }
2N/A
2N/A if (kmfber_flatten(asn1, &extdata) == -1) {
2N/A ret = KMF_ERR_ENCODING;
2N/A goto out;
2N/A }
2N/A
2N/A /*
2N/A * If we are just adding to an existing list of EKU OIDs,
2N/A * just replace the BER data associated with the found extension.
2N/A */
2N/A if (foundextn != NULL) {
2N/A free(foundextn->BERvalue.Data);
2N/A foundextn->critical = critical;
2N/A foundextn->BERvalue.Data = (uchar_t *)extdata->bv_val;
2N/A foundextn->BERvalue.Length = extdata->bv_len;
2N/A } else {
2N/A ret = copy_data(&newextn.extnId,
2N/A (KMF_DATA *)&KMFOID_ExtendedKeyUsage);
2N/A if (ret != KMF_OK)
2N/A goto out;
2N/A newextn.critical = critical;
2N/A newextn.format = KMF_X509_DATAFORMAT_ENCODED;
2N/A newextn.BERvalue.Data = (uchar_t *)extdata->bv_val;
2N/A newextn.BERvalue.Length = extdata->bv_len;
2N/A ret = kmf_set_csr_extn(CSRData, &newextn);
2N/A if (ret != KMF_OK)
2N/A free(newextn.BERvalue.Data);
2N/A }
2N/A
2N/Aout:
2N/A kmf_free_eku(&ekudata);
2N/A if (extdata != NULL)
2N/A free(extdata);
2N/A
2N/A if (olddata != NULL)
2N/A free(olddata);
2N/A
2N/A if (asn1 != NULL)
2N/A kmfber_free(asn1, 1);
2N/A
2N/A if (ret != KMF_OK)
2N/A kmf_free_data(&newextn.extnId);
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/Astatic KMF_RETURN
2N/Asign_csr(KMF_HANDLE_T handle,
2N/A const KMF_DATA *SubjectCsr,
2N/A KMF_KEY_HANDLE *Signkey,
2N/A KMF_X509_ALGORITHM_IDENTIFIER *algo,
2N/A KMF_DATA *SignedCsr)
2N/A{
2N/A KMF_CSR_DATA subj_csr;
2N/A KMF_TBS_CSR *tbs_csr = NULL;
2N/A KMF_DATA signed_data = {0, NULL};
2N/A KMF_RETURN ret = KMF_OK;
2N/A KMF_ATTRIBUTE attlist[5];
2N/A KMF_ALGORITHM_INDEX algid;
2N/A int i = 0;
2N/A
2N/A if (!SignedCsr)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A SignedCsr->Length = 0;
2N/A SignedCsr->Data = NULL;
2N/A
2N/A if (!SubjectCsr)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A if (!SubjectCsr->Data || !SubjectCsr->Length)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A (void) memset(&subj_csr, 0, sizeof (subj_csr));
2N/A /* Estimate the signed data length generously */
2N/A signed_data.Length = SubjectCsr->Length*2;
2N/A signed_data.Data = calloc(1, signed_data.Length);
2N/A if (!signed_data.Data) {
2N/A ret = KMF_ERR_MEMORY;
2N/A goto cleanup;
2N/A }
2N/A
2N/A kmf_set_attr_at_index(attlist, i++,
2N/A KMF_KEYSTORE_TYPE_ATTR, &Signkey->kstype,
2N/A sizeof (Signkey->kstype));
2N/A
2N/A kmf_set_attr_at_index(attlist, i++,
2N/A KMF_KEY_HANDLE_ATTR, Signkey, sizeof (KMF_KEY_HANDLE));
2N/A
2N/A kmf_set_attr_at_index(attlist, i++, KMF_OID_ATTR, &algo->algorithm,
2N/A sizeof (KMF_OID));
2N/A
2N/A kmf_set_attr_at_index(attlist, i++, KMF_DATA_ATTR,
2N/A (KMF_DATA *)SubjectCsr, sizeof (KMF_DATA));
2N/A
2N/A kmf_set_attr_at_index(attlist, i++, KMF_OUT_DATA_ATTR,
2N/A &signed_data, sizeof (KMF_DATA));
2N/A
2N/A ret = kmf_sign_data(handle, i, attlist);
2N/A if (KMF_OK != ret)
2N/A goto cleanup;
2N/A /*
2N/A * If we got here OK, decode into a structure and then re-encode
2N/A * the complete CSR.
2N/A */
2N/A ret = DerDecodeTbsCsr(SubjectCsr, &tbs_csr);
2N/A if (ret)
2N/A goto cleanup;
2N/A
2N/A (void) memcpy(&subj_csr.csr, tbs_csr, sizeof (KMF_TBS_CSR));
2N/A
2N/A ret = copy_algoid(&subj_csr.signature.algorithmIdentifier, algo);
2N/A if (ret)
2N/A goto cleanup;
2N/A
2N/A algid = x509_algoid_to_algid(&algo->algorithm);
2N/A if (algid == KMF_ALGID_SHA1WithDSA ||
2N/A algid == KMF_ALGID_SHA256WithDSA ||
2N/A algid == KMF_ALGID_SHA1WithECDSA ||
2N/A algid == KMF_ALGID_SHA256WithECDSA ||
2N/A algid == KMF_ALGID_SHA384WithECDSA ||
2N/A algid == KMF_ALGID_SHA512WithECDSA) {
2N/A /*
2N/A * For DSA and ECDSA, we must encode the
2N/A * signature correctly.
2N/A */
2N/A KMF_DATA signature;
2N/A
2N/A ret = DerEncodeDSASignature(&signed_data, &signature);
2N/A kmf_free_data(&signed_data);
2N/A
2N/A if (ret != KMF_OK)
2N/A goto cleanup;
2N/A
2N/A subj_csr.signature.encrypted = signature;
2N/A } else {
2N/A subj_csr.signature.encrypted = signed_data;
2N/A }
2N/A
2N/A /* Now, re-encode the CSR with the new signature */
2N/A ret = DerEncodeSignedCsr(&subj_csr, SignedCsr);
2N/A if (ret != KMF_OK) {
2N/A kmf_free_data(SignedCsr);
2N/A goto cleanup;
2N/A }
2N/A
2N/A /* Cleanup & return */
2N/Acleanup:
2N/A free(tbs_csr);
2N/A
2N/A kmf_free_tbs_csr(&subj_csr.csr);
2N/A
2N/A kmf_free_algoid(&subj_csr.signature.algorithmIdentifier);
2N/A kmf_free_data(&signed_data);
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/A/*
2N/A *
2N/A * Name: kmf_sign_csr
2N/A *
2N/A * Description:
2N/A * This function signs a CSR and returns the result as a
2N/A * signed, encoded CSR in SignedCsr
2N/A *
2N/A * Parameters:
2N/A * tbsCsr(input) - pointer to a KMF_DATA structure containing a
2N/A * DER encoded TBS CSR data
2N/A * Signkey(input) - pointer to the KMF_KEY_HANDLE structure containing
2N/A * the private key generated by the plug-in CreateKeypair
2N/A * algo(input) - contains algorithm info needed for signing
2N/A * SignedCsr(output) - pointer to the KMF_DATA structure containing
2N/A * the signed CSR
2N/A *
2N/A * Returns:
2N/A * A KMF_RETURN value indicating success or specifying a particular
2N/A * error condition.
2N/A * The value KMF_OK indicates success. All other values represent
2N/A * an error condition.
2N/A *
2N/A */
2N/AKMF_RETURN
2N/Akmf_sign_csr(KMF_HANDLE_T handle,
2N/A const KMF_CSR_DATA *tbsCsr,
2N/A KMF_KEY_HANDLE *Signkey,
2N/A KMF_DATA *SignedCsr)
2N/A{
2N/A KMF_RETURN err;
2N/A KMF_DATA csrdata = { NULL, 0 };
2N/A
2N/A CLEAR_ERROR(handle, err);
2N/A if (err != KMF_OK)
2N/A return (err);
2N/A
2N/A if (tbsCsr == NULL || Signkey == NULL || SignedCsr == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A SignedCsr->Data = NULL;
2N/A SignedCsr->Length = 0;
2N/A
2N/A err = DerEncodeTbsCsr((KMF_TBS_CSR *)&tbsCsr->csr, &csrdata);
2N/A if (err == KMF_OK) {
2N/A err = sign_csr(handle, &csrdata, Signkey,
2N/A (KMF_X509_ALGORITHM_IDENTIFIER *)
2N/A &tbsCsr->signature.algorithmIdentifier,
2N/A SignedCsr);
2N/A }
2N/A
2N/A if (err != KMF_OK) {
2N/A kmf_free_data(SignedCsr);
2N/A }
2N/A kmf_free_data(&csrdata);
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * kmf_decode_csr
2N/A *
2N/A * Description:
2N/A * This function decodes raw CSR data and fills in the KMF_CSR_DATA
2N/A * record.
2N/A *
2N/A * Inputs:
2N/A * KMF_HANDLE_T handle
2N/A * KMF_DATA *rawcsr
2N/A * KMF_CSR_DATA *csrdata;
2N/A */
2N/AKMF_RETURN
2N/Akmf_decode_csr(KMF_HANDLE_T handle, KMF_DATA *rawcsr, KMF_CSR_DATA *csrdata)
2N/A{
2N/A KMF_RETURN rv;
2N/A KMF_CSR_DATA *cdata = NULL;
2N/A
2N/A if (handle == NULL || rawcsr == NULL || csrdata == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = DerDecodeSignedCsr(rawcsr, &cdata);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A
2N/A (void) memcpy(csrdata, cdata, sizeof (KMF_CSR_DATA));
2N/A
2N/A free(cdata);
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/Akmf_verify_csr(KMF_HANDLE_T handle, int numattr,
2N/A KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_CSR_DATA *csrdata = NULL;
2N/A KMF_ALGORITHM_INDEX algid;
2N/A KMF_X509_ALGORITHM_IDENTIFIER *x509alg;
2N/A KMF_DATA rawcsr;
2N/A
2N/A KMF_ATTRIBUTE_TESTER required_attrs[] = {
2N/A {KMF_CSR_DATA_ATTR, FALSE, sizeof (KMF_CSR_DATA),
2N/A sizeof (KMF_CSR_DATA)},
2N/A };
2N/A
2N/A int num_req_attrs = sizeof (required_attrs) /
2N/A sizeof (KMF_ATTRIBUTE_TESTER);
2N/A
2N/A if (handle == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A CLEAR_ERROR(handle, rv);
2N/A
2N/A rv = test_attributes(num_req_attrs, required_attrs,
2N/A 0, NULL, numattr, attrlist);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A
2N/A csrdata = kmf_get_attr_ptr(KMF_CSR_DATA_ATTR, attrlist, numattr);
2N/A if (csrdata == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = DerEncodeTbsCsr(&csrdata->csr, &rawcsr);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A
2N/A x509alg = &csrdata->signature.algorithmIdentifier;
2N/A algid = x509_algoid_to_algid(&x509alg->algorithm);
2N/A if (algid == KMF_ALGID_SHA1WithDSA ||
2N/A algid == KMF_ALGID_SHA256WithDSA) {
2N/A /* Decode the DSA signature before verifying it */
2N/A KMF_DATA signature;
2N/A rv = DerDecodeDSASignature(&csrdata->signature.encrypted,
2N/A &signature);
2N/A if (rv != KMF_OK)
2N/A goto end;
2N/A
2N/A rv = PKCS_VerifyData(handle, algid,
2N/A &csrdata->csr.subjectPublicKeyInfo,
2N/A &rawcsr, &signature);
2N/A
2N/A kmf_free_data(&signature);
2N/A } else if (algid == KMF_ALGID_SHA1WithECDSA ||
2N/A algid == KMF_ALGID_SHA256WithECDSA ||
2N/A algid == KMF_ALGID_SHA384WithECDSA ||
2N/A algid == KMF_ALGID_SHA512WithECDSA) {
2N/A KMF_DATA signature;
2N/A rv = DerDecodeECDSASignature(&csrdata->signature.encrypted,
2N/A &signature);
2N/A if (rv != KMF_OK)
2N/A goto end;
2N/A
2N/A rv = PKCS_VerifyData(handle, algid,
2N/A &csrdata->csr.subjectPublicKeyInfo,
2N/A &rawcsr, &signature);
2N/A
2N/A kmf_free_data(&signature);
2N/A } else {
2N/A rv = PKCS_VerifyData(handle, algid,
2N/A &csrdata->csr.subjectPublicKeyInfo,
2N/A &rawcsr,
2N/A &csrdata->signature.encrypted);
2N/A }
2N/A
2N/Aend:
2N/A kmf_free_data(&rawcsr);
2N/A return (rv);
2N/A}
2N/A
2N/Astatic KMF_RETURN
2N/Asetup_crl_call(KMF_HANDLE_T handle, int numattr,
2N/A KMF_ATTRIBUTE *attrlist, KMF_PLUGIN **plugin)
2N/A{
2N/A KMF_RETURN ret;
2N/A KMF_KEYSTORE_TYPE kstype;
2N/A uint32_t len = sizeof (kstype);
2N/A
2N/A KMF_ATTRIBUTE_TESTER required_attrs[] = {
2N/A {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)}
2N/A };
2N/A
2N/A int num_req_attrs = sizeof (required_attrs) /
2N/A sizeof (KMF_ATTRIBUTE_TESTER);
2N/A
2N/A if (handle == NULL || plugin == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A CLEAR_ERROR(handle, ret);
2N/A
2N/A ret = test_attributes(num_req_attrs, required_attrs,
2N/A 0, NULL, numattr, attrlist);
2N/A if (ret != KMF_OK)
2N/A return (ret);
2N/A
2N/A ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, numattr,
2N/A &kstype, &len);
2N/A if (ret != KMF_OK)
2N/A return (ret);
2N/A
2N/A switch (kstype) {
2N/A case KMF_KEYSTORE_NSS:
2N/A *plugin = FindPlugin(handle, kstype);
2N/A break;
2N/A
2N/A case KMF_KEYSTORE_OPENSSL:
2N/A case KMF_KEYSTORE_PK11TOKEN: /* PKCS#11 CRL is file-based */
2N/A *plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
2N/A break;
2N/A default:
2N/A return (KMF_ERR_PLUGIN_NOTFOUND);
2N/A }
2N/A return (KMF_OK);
2N/A}
2N/A
2N/AKMF_RETURN
2N/Akmf_import_crl(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN ret;
2N/A KMF_PLUGIN *plugin;
2N/A
2N/A ret = setup_crl_call(handle, numattr, attrlist, &plugin);
2N/A if (ret != KMF_OK)
2N/A return (ret);
2N/A
2N/A if (plugin == NULL)
2N/A return (KMF_ERR_PLUGIN_NOTFOUND);
2N/A else if (plugin->funclist->ImportCRL != NULL)
2N/A return (plugin->funclist->ImportCRL(handle, numattr, attrlist));
2N/A
2N/A return (KMF_ERR_FUNCTION_NOT_FOUND);
2N/A}
2N/A
2N/AKMF_RETURN
2N/Akmf_delete_crl(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN ret;
2N/A KMF_PLUGIN *plugin;
2N/A
2N/A ret = setup_crl_call(handle, numattr, attrlist, &plugin);
2N/A if (ret != KMF_OK)
2N/A return (ret);
2N/A
2N/A if (plugin == NULL)
2N/A return (KMF_ERR_PLUGIN_NOTFOUND);
2N/A else if (plugin->funclist->DeleteCRL != NULL)
2N/A return (plugin->funclist->DeleteCRL(handle, numattr, attrlist));
2N/A
2N/A return (KMF_ERR_FUNCTION_NOT_FOUND);
2N/A}
2N/A
2N/AKMF_RETURN
2N/Akmf_list_crl(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_PLUGIN *plugin;
2N/A KMF_RETURN ret;
2N/A
2N/A ret = setup_crl_call(handle, numattr, attrlist, &plugin);
2N/A if (ret != KMF_OK)
2N/A return (ret);
2N/A
2N/A if (plugin == NULL)
2N/A return (KMF_ERR_PLUGIN_NOTFOUND);
2N/A else if (plugin->funclist->ListCRL != NULL)
2N/A return (plugin->funclist->ListCRL(handle, numattr, attrlist));
2N/A return (KMF_ERR_FUNCTION_NOT_FOUND);
2N/A}
2N/A
2N/AKMF_RETURN
2N/Akmf_find_crl(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_PLUGIN *plugin;
2N/A KMF_RETURN ret;
2N/A KMF_KEYSTORE_TYPE kstype;
2N/A uint32_t len = sizeof (kstype);
2N/A
2N/A KMF_ATTRIBUTE_TESTER required_attrs[] = {
2N/A {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1,
2N/A sizeof (KMF_KEYSTORE_TYPE)},
2N/A {KMF_CRL_COUNT_ATTR, FALSE,
2N/A sizeof (char *), sizeof (char *)}
2N/A };
2N/A
2N/A int num_req_attrs = sizeof (required_attrs) /
2N/A sizeof (KMF_ATTRIBUTE_TESTER);
2N/A if (handle == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A CLEAR_ERROR(handle, ret);
2N/A
2N/A ret = test_attributes(num_req_attrs, required_attrs,
2N/A 0, NULL, numattr, attrlist);
2N/A if (ret != KMF_OK)
2N/A return (ret);
2N/A
2N/A ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, numattr,
2N/A &kstype, &len);
2N/A if (ret != KMF_OK)
2N/A return (ret);
2N/A
2N/A switch (kstype) {
2N/A case KMF_KEYSTORE_NSS:
2N/A plugin = FindPlugin(handle, kstype);
2N/A break;
2N/A case KMF_KEYSTORE_OPENSSL:
2N/A case KMF_KEYSTORE_PK11TOKEN:
2N/A return (KMF_ERR_FUNCTION_NOT_FOUND);
2N/A default:
2N/A /*
2N/A * FindCRL is only implemented for NSS. PKCS#11
2N/A * and file-based keystores just store in a file
2N/A * and don't need a "Find" function.
2N/A */
2N/A return (KMF_ERR_PLUGIN_NOTFOUND);
2N/A }
2N/A
2N/A if (plugin == NULL)
2N/A return (KMF_ERR_PLUGIN_NOTFOUND);
2N/A else if (plugin->funclist->FindCRL != NULL) {
2N/A return (plugin->funclist->FindCRL(handle, numattr,
2N/A attrlist));
2N/A }
2N/A return (KMF_ERR_FUNCTION_NOT_FOUND);
2N/A}
2N/A
2N/AKMF_RETURN
2N/Akmf_find_cert_in_crl(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN ret;
2N/A KMF_PLUGIN *plugin;
2N/A
2N/A ret = setup_crl_call(handle, numattr, attrlist, &plugin);
2N/A if (ret != KMF_OK)
2N/A return (ret);
2N/A
2N/A if (plugin == NULL)
2N/A return (KMF_ERR_PLUGIN_NOTFOUND);
2N/A else if (plugin->funclist->FindCertInCRL != NULL)
2N/A return (plugin->funclist->FindCertInCRL(handle, numattr,
2N/A attrlist));
2N/A
2N/A return (KMF_ERR_FUNCTION_NOT_FOUND);
2N/A}
2N/A
2N/AKMF_RETURN
2N/Akmf_verify_crl_file(KMF_HANDLE_T handle, char *crlfile, KMF_DATA *tacert)
2N/A{
2N/A KMF_PLUGIN *plugin;
2N/A KMF_RETURN (*verifyCRLFile)(KMF_HANDLE_T, char *, KMF_DATA *);
2N/A
2N/A if (handle == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
2N/A if (plugin == NULL || plugin->dldesc == NULL) {
2N/A return (KMF_ERR_PLUGIN_NOTFOUND);
2N/A }
2N/A
2N/A verifyCRLFile = (KMF_RETURN(*)())dlsym(plugin->dldesc,
2N/A "OpenSSL_VerifyCRLFile");
2N/A
2N/A if (verifyCRLFile == NULL) {
2N/A return (KMF_ERR_FUNCTION_NOT_FOUND);
2N/A }
2N/A
2N/A return (verifyCRLFile(handle, crlfile, tacert));
2N/A}
2N/A
2N/AKMF_RETURN
2N/Akmf_check_crl_date(KMF_HANDLE_T handle, char *crlname)
2N/A{
2N/A KMF_PLUGIN *plugin;
2N/A KMF_RETURN (*checkCRLDate)(void *, char *);
2N/A KMF_RETURN ret = KMF_OK;
2N/A
2N/A if (handle == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A CLEAR_ERROR(handle, ret);
2N/A if (ret != KMF_OK)
2N/A return (ret);
2N/A
2N/A plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
2N/A if (plugin == NULL || plugin->dldesc == NULL) {
2N/A return (KMF_ERR_PLUGIN_NOTFOUND);
2N/A }
2N/A
2N/A checkCRLDate = (KMF_RETURN(*)())dlsym(plugin->dldesc,
2N/A "OpenSSL_CheckCRLDate");
2N/A
2N/A if (checkCRLDate == NULL) {
2N/A return (KMF_ERR_FUNCTION_NOT_FOUND);
2N/A }
2N/A
2N/A return (checkCRLDate(handle, crlname));
2N/A}
2N/A
2N/AKMF_RETURN
2N/Akmf_is_crl_file(KMF_HANDLE_T handle, char *filename, KMF_ENCODE_FORMAT *pformat)
2N/A{
2N/A KMF_PLUGIN *plugin;
2N/A KMF_RETURN (*IsCRLFileFn)(void *, char *, KMF_ENCODE_FORMAT *);
2N/A KMF_RETURN ret = KMF_OK;
2N/A
2N/A CLEAR_ERROR(handle, ret);
2N/A if (ret != KMF_OK)
2N/A return (ret);
2N/A
2N/A if (filename == NULL || pformat == NULL) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A /*
2N/A * This framework function is actually implemented in the openssl
2N/A * plugin library, so we find the function address and call it.
2N/A */
2N/A plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
2N/A if (plugin == NULL || plugin->dldesc == NULL) {
2N/A return (KMF_ERR_PLUGIN_NOTFOUND);
2N/A }
2N/A
2N/A IsCRLFileFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
2N/A "OpenSSL_IsCRLFile");
2N/A if (IsCRLFileFn == NULL) {
2N/A return (KMF_ERR_FUNCTION_NOT_FOUND);
2N/A }
2N/A
2N/A return (IsCRLFileFn(handle, filename, pformat));
2N/A}