/* ***************************************************************** *
 * Copyright 1998 International Business Machines Corporation. All   *
 * Rights Reserved.                                                  *
 *                                                                   *
 * Please read this carefully.  Your use of this reference           *
 * implementation of certain of the IETF public-key infrastructure   *
 * specifications ("Software") indicates your acceptance of the      *
 * following.  If you do not agree to the following, do not install  *
 * or use any of the Software.                                       *
 *                                                                   *
 * Permission to use, reproduce, distribute and create derivative    *
 * works from the Software ("Software Derivative Works"), and to     *
 * distribute such Software Derivative Works is hereby granted to    *
 * you by International Business Machines Corporation ("IBM").  This *
 * permission includes a license under the patents of IBM that are   *
 * necessarily infringed by your use of the Software as provided by  *
 * IBM.                                                              *
 *                                                                   *
 * IBM licenses the Software to you on an "AS IS" basis, without     *
 * warranty of any kind.  IBM HEREBY EXPRESSLY DISCLAIMS ALL         *
 * WARRANTIES OR CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING,   *
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OR CONDITIONS OF       *
 * MERCHANTABILITY, NON INFRINGEMENT AND FITNESS FOR A PARTICULAR    *
 * PURPOSE.  You are solely responsible for determining the          *
 * appropriateness of using this Software and assume all risks       *
 * associated with the use of this Software, including but not       *
 * limited to the risks of program errors, damage to or loss of      *
 * data, programs or equipment, and unavailability or interruption   *
 * of operations.                                                    *
 *                                                                   *
 * IBM WILL NOT BE LIABLE FOR ANY DIRECT DAMAGES OR FOR ANY SPECIAL, *
 * INCIDENTAL, OR  INDIRECT DAMAGES OR FOR ANY ECONOMIC              *
 * CONSEQUENTIAL DAMAGES (INCLUDING LOST PROFITS OR SAVINGS), EVEN   *
 * IF IBM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  IBM  *
 * will not be liable for the loss of, or damage to, your records or *
 * data, or any damages claimed by you based on a third party claim. *
 *                                                                   *
 * IBM wishes to obtain your feedback to assist in improving the     *
 * Software.  You grant IBM a world-wide, royalty-free right to use, *
 * copy, distribute, sublicense and prepare derivative works based   *
 * upon any feedback, including materials, error corrections,        *
 * Software Derivatives, enhancements, suggestions and the like that *
 * you provide to IBM relating to the Software (this does not        *
 * include products for which you charge a royalty and distribute to *
 * IBM under other terms and conditions).                            *
 *                                                                   *
 * You agree to distribute the Software and any Software Derivatives *
 * under a license agreement that: 1) is sufficient to notify all    *
 * licensees of the Software and Software Derivatives that IBM       *
 * assumes no liability for any claim that may arise regarding the   *
 * Software or Software Derivatives, and 2) that disclaims all       *
 * warranties, both express and implied, from IBM regarding the      *
 * Software and Software Derivatives.  (If you include this          *
 * Agreement with any distribution of the Software or Software       *
 * Derivatives you will have met this requirement.)  You agree that  *
 * you will not delete any copyright notices in the Software.        *
 *                                                                   *
 * This Agreement is the exclusive statement of your rights in the   *
 * Software as provided by IBM.   Except for the rights granted to   *
 * you in the second paragraph above, You are not granted any other  *
 * patent rights, including but not limited to the right to make     *
 * combinations of the Software with products that infringe IBM      *
 * patents. You agree to comply with all applicable laws and         *
 * regulations, including all export and import laws and regulation. *
 * This Agreement is governed by the laws of the State of New York.  *
 * This Agreement supersedes all other communications,               *
 * understandings or agreements we may have had prior to this        *
 * Agreement.                                                        *
 * ***************************************************************** */

/* -- BEGIN COPYRIGHT -- *
 *
 * IBM PKIX Public Key Infrastructure Version 1 Release 0
 *
 * (C) Copyright IBM Corp. 1998
 * All Rights Reserved
 * Licensed Material - Property of IBM
 *
 * US Government Users Restricted Rights -
 * Use, duplication or disclosure restricted by GSA ADP Schedule Contract
 *     with IBM Corp.
 *
 * -- END COPYRIGHT -- */

/*************************************************************************
 *
 *  Module Name:
 *    JonahCL.cpp
 *
 *  Module Description:
 *    Jonah Certificate Library CDSA addin
 *
 *  Public Functions:
 *
 *  Private Functions:
 *
 *  Notes:
 *
 *  Change History:
 *
 *  Item   Author   Date     Description
 *  ------ -------- -------- -----------------------------------------------
 *  Create J C Wray 4/27/98  Initial revision, based on IBMCL2
 *
 *************************************************************************/


/**************************************************************************
 * Include Files
 **************************************************************************/

#include <limits.h>

#include "cssm.h"
#include "cssmspi.h"
#include "x509.h"
#include "jonahCL.h"
#include "cssminc.h"
#include "JonahAlg.h"
#include "AsnCdsa.h"

#ifdef _WIN32
#include "windows.h"
#endif

/**************************************************************************
 * Prototypes for private functions
 **************************************************************************/

/**************************************************************************
 * Constants, macros, and definitions
 **************************************************************************/

#define CSSM_DATA_PTR_NULL ((CSSM_DATA_PTR) 0)
#define CSSM_FIELD_PTR_NULL ((CSSM_FIELD_PTR) 0)
#define CSSM_KEY_PTR_NULL ((CSSM_KEY_PTR) 0)
#define CSSM_OID_PTR_NULL ((CSSM_OID_PTR) 0)

#define SET_ERROR(x) \
  { CSSM_SetError((CSSM_GUID*)&JONAHCL_GUID, x); \
    goto fail; \
  }

#define OID_MATCH(p, o) \
  ((p->Length == sizeof(o)) && (memcmp(p->Data, o, sizeof(o)) == 0)) 

#define OidCpy(p, o) \
  {p.Length = sizeof(o); \
   p.Data = (unsigned char *)clmUpcallTable.malloc_func(CLHandle, p.Length); \
   memcpy(p.Data, &(o), p.Length); \
  }
 
/**************************************************************************
 * Globals
 **************************************************************************/

CSSM_SPI_MEMORY_FUNCS clmUpcallTable;


/**************************************************************************
 * Types
 **************************************************************************/


/**************************************************************************
 * Certificate operations
 **************************************************************************/


/*************************************************************************
 *
 *  Function Name:  CL_CertSign
 *
 *  Functional Description:  Sign a certificate
 *
 *  Input:  CertTobeSigned - Certificate data to which a signature will 
 *                           be added
 *          SignedCert - Pretty much ignored
 *          CCHandle - Crypto context, which already includes signer's 
 *                     private key
 *
 *
 *  Output: Function return - Signed certificate
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/

CSSM_DATA_PTR CSSMAPI CL_CertSign(CSSM_CL_HANDLE CLHandle,
                                  CSSM_CC_HANDLE CCHandle,
                                  const CSSM_DATA_PTR CertToBeSigned,
                                  const CSSM_DATA_PTR SignerCert,
                                  const CSSM_FIELD_PTR SignScope,
                                  uint32 ScopeSize)
{
  memory_funcs_t mems(CLHandle,
                      clmUpcallTable.malloc_func,
                      clmUpcallTable.free_func,
                      clmUpcallTable.realloc_func,
                      clmUpcallTable.calloc_func);
  x509_certificate cert;
  x509_certificate scert;
  buffer_t buf(mems);
  r_buffer_t rbuf;
  uint32 status;

  try {
    if ((CertToBeSigned == NULL) || (SignerCert == NULL))
      SET_ERROR(CSSM_CL_INVALID_DATA_POINTER);
  
    if ((SignScope != NULL) || (ScopeSize != 0))
      SET_ERROR(CSSM_CL_INVALID_SCOPE);
  

    rbuf.data = CertToBeSigned->Data;
    rbuf.data_len = CertToBeSigned->Length;
    if ((status = cert.tbsCertificate.read(rbuf)) != 0)
      SET_ERROR(CSSM_CL_UNKNOWN_FORMAT);
    
/*
  We're not going to use the SignerCert, so why waste time 
  validating its syntax?

    rbuf.data = SignerCert->Data;
    rbuf.data_len = Signercert->Length;
    if ((status = scert.read(rbuf)) != 0)
      SET_ERROR(CSSM_CL_UNKNOWN_FORMAT);
*/

// Should verify that ucert.signatureAlgorithm matches the algo in the CCHandle

    unsigned char signatureBuffer[256];
    memset(signatureBuffer, 0, sizeof(signatureBuffer));
    CSSM_DATA signedBuffer;
    signedBuffer.Length = sizeof(signatureBuffer);
    signedBuffer.Data = signatureBuffer;
  
    CSSM_RETURN rc = CSSM_SignData(CCHandle, CertToBeSigned, 1, &signedBuffer);
  
    if (rc != CSSM_OK) SET_ERROR(CSSM_CL_CERT_SIGN_FAIL);
  
// Got signature, create signed certificate.
  
    buf.clear();
    if ((status = cert.tbsCertificate.signature.write(buf)) != 0)
      SET_ERROR(CSSM_CL_CERT_SIGN_FAIL);
    if ((status = cert.signatureAlgorithm.read(buf)) != 0)
      SET_ERROR(CSSM_CL_CERT_SIGN_FAIL);
    buf.clear();
  
    if ((status = cert.signature.set_value(signedBuffer.Data, 
                                           signedBuffer.Length * CHAR_BIT)) != 0)
      SET_ERROR(CSSM_CL_CERT_SIGN_FAIL);
    
    CSSM_DATA_PTR cssmStructPtr = (CSSM_DATA_PTR)clmUpcallTable.malloc_func(CLHandle, sizeof(CSSM_DATA));
    if ((status = cert.write(buf)) != 0) SET_ERROR(CSSM_CL_CERT_SIGN_FAIL);
  
    cssmStructPtr->Data = buf.data;
    cssmStructPtr->Length = buf.data_len;
    buf.detach();

    return cssmStructPtr;
  }
  catch (...) {
    SET_ERROR(CSSM_CL_CERT_SIGN_FAIL);
  }
fail:
  return CSSM_DATA_PTR_NULL;
}



/*************************************************************************
 *
 *  Function Name:  CL_CertVerify
 *
 *  Functional Description:  Verify a certificate for syntax and signature
 *
 *  Input:  CertTobeSigned - Certificate data to be checked
 *          SignedCert - Pretty much ignored
 *          CCHandle - Crypto context, which already includes 
 *                     signer's public key
 *
 *
 *  Output: Function return - CSSM_TRUE for success, CSSM_FALSE for failure
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/

CSSM_BOOL CSSMAPI CL_CertVerify(CSSM_CL_HANDLE CLHandle,
                                CSSM_CC_HANDLE CCHandle,
                                const CSSM_DATA_PTR CertToBeVerified,
                                const CSSM_DATA_PTR SignerCert,
                                const CSSM_FIELD_PTR VerifyScope,
                                uint32 ScopeSize)
{

  memory_funcs_t mems(CLHandle,
                      clmUpcallTable.malloc_func,
                      clmUpcallTable.free_func,
                      clmUpcallTable.realloc_func,
                      clmUpcallTable.calloc_func);
  x509_certificate cert;
  x509_certificate scert;
  buffer_t buf(mems);
  r_buffer_t rbuf;
  uint32 status;

  try {
    if ((CertToBeVerified == NULL) || (SignerCert == NULL))
      SET_ERROR(CSSM_CL_INVALID_DATA_POINTER);

    if ((VerifyScope != NULL) || (ScopeSize != 0))
      SET_ERROR(CSSM_CL_INVALID_SCOPE);


    rbuf.data = CertToBeVerified->Data; 
    rbuf.data_len = CertToBeVerified->Length;
    if ((status = cert.read(rbuf)) != 0)
      SET_ERROR(CSSM_CL_UNKNOWN_FORMAT);

/*
  We're not going to use the SignerCert, so why waste time 
  validating its syntax?

    rbuf.data = SignerCert->Data;
    rbuf.data_len = Signercert->Length;
    if ((status = scert.read(rbuf)) != 0)
      SET_ERROR(CSSM_CL_UNKNOWN_FORMAT);
*/

    CSSM_DATA signatureBuffer;
    status = cert.signature.get_value(signatureBuffer.Data, signatureBuffer.Length);
    signatureBuffer.Length = signatureBuffer.Length / CHAR_BIT;

    if ((status = cert.tbsCertificate.write(buf)) != 0)
      SET_ERROR(CSSM_CL_CERT_VERIFY_FAIL);

    CSSM_DATA signedBuffer;

    signedBuffer.Data = buf.data;
    signedBuffer.Length = buf.data_len;

    CSSM_BOOL rc = CSSM_VerifyData(CCHandle, &signedBuffer, 1, &signatureBuffer);

    if (rc != CSSM_TRUE) SET_ERROR(CSSM_CL_CERT_VERIFY_FAIL);

    return CSSM_TRUE;
  } catch (...) {
    SET_ERROR(CSSM_CL_CERT_VERIFY_FAIL);
  }
fail:
  return CSSM_FALSE;
}

/*************************************************************************
 *
 *  Function Name:  CL_CertCreateTemplate
 *
 *  Functional Description:  Create a certificate from a template.
 *                           Function not implemented.
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/



CSSM_DATA_PTR CSSMAPI CL_CertCreateTemplate(CSSM_CL_HANDLE CLHandle,
                                            const CSSM_FIELD_PTR CertTemplate,
                                            uint32 NumberOfFields)
{
  SET_ERROR(CSSM_CL_UNSUPPORTED_OPERATION);
fail:
  return CSSM_DATA_PTR_NULL;
}


/*************************************************************************
 *
 *  Function Name:  CL_CertGetFirstFieldValue
 *
 *  Functional Description:  Extract a list of fields from the certificate
 *                           which match the requested field.  Place the
 *                           list of fields into a CSSM_INCREMENTAL_DATA_PTR,
 *                           cast to CSSM_HANDLE_PTR and returned in
 *                           ResultsHandle.  Extract the first matching
 *                           field into the function result.
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/


CSSM_DATA_PTR CSSMAPI CL_CertGetFirstFieldValue(CSSM_CL_HANDLE CLHandle,
                                                const CSSM_DATA_PTR Cert,
                                                const CSSM_OID_PTR CertField,
                                                CSSM_HANDLE_PTR ResultsHandle,
                                                uint32 * NumberOfMatchedFields)
{
  memory_funcs_t mems(CLHandle,
                      clmUpcallTable.malloc_func,
                      clmUpcallTable.free_func,
                      clmUpcallTable.realloc_func,
                      clmUpcallTable.calloc_func);    
  buffer_t buf(mems);
  cssm_inc results(mems);
  r_buffer_t rbuf;
  x509_certificate cert;
  uint32 status;

  try {
    if ((Cert == NULL) || 
        (CertField == NULL) || 
        (ResultsHandle == NULL) || 
        (NumberOfMatchedFields == NULL))
      SET_ERROR(CSSM_CL_INVALID_DATA_POINTER);
    
    rbuf.data = Cert->Data;
    rbuf.data_len = Cert->Length;
    *ResultsHandle = (CSSM_HANDLE) 0;
    if ((status = cert.read(rbuf)) != 0)
      SET_ERROR(CSSM_CL_INVALID_CERT_POINTER);

// Now to find the field(s) requested...

    if OID_MATCH(CertField, JONAH_x509_cert_signatureAlgorithmIdentifier_DER) {
      
      if ((status = cert.signatureAlgorithm.write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      results.append_own(buf);
      return results.extract();

    } else if OID_MATCH(CertField, JONAH_x509_cert_signatureAlgorithmIdentifier_objectIdentifier_DER) {
    
      if ((status = cert.signatureAlgorithm.algorithm.write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      results.append_own(buf);
      return results.extract();

    } else if OID_MATCH(CertField, JONAH_x509_cert_signatureAlgorithmIdentifier_parameters_DER) {
    
      if ((status = cert.signatureAlgorithm.parameters.write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      results.append_own(buf);
      return results.extract();

    } else if OID_MATCH(CertField, JONAH_x509_ucert_version_DER) {
      x509_version_t ver;
      unsigned char v;
      rbuf.data = &v;
      rbuf.data_len = 1;

      if ((status = cert.tbsCertificate.version.get_value(ver)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      switch (ver) {
        case X509_V1: v = 0; break;
        case X509_V2: v = 1; break;
        case X509_V3: v = 2; break;
        default:
          SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      };

      results.append(rbuf);
      return results.extract();
    
    } else if OID_MATCH(CertField, JONAH_x509_ucert_signatureAlgorithmIdentifier_DER) {
    
      if ((status = cert.tbsCertificate.signature.write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      results.append_own(buf);
      return results.extract();
    
    } else if OID_MATCH(CertField, JONAH_x509_ucert_signatureAlgorithmIdentifier_objectIdentifier_DER) {
    
      if ((status = cert.tbsCertificate.signature.algorithm.write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      results.append_own(buf);
      return results.extract();
    
    } else if OID_MATCH(CertField, JONAH_x509_ucert_signatureAlgorithmIdentifier_parameters_DER) {
    
      if ((status = cert.tbsCertificate.signature.parameters.write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      results.append_own(buf);
      return results.extract();
    
    } else if OID_MATCH(CertField, JONAH_x509_ucert_issuerName_DER) {
    
      if ((status = cert.tbsCertificate.issuer.write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      results.append_own(buf);
      return results.extract();
    
    } else if OID_MATCH(CertField, JONAH_x509_ucert_subjectName_DER) {
    
      if ((status = cert.tbsCertificate.subject.write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      results.append_own(buf);
      return results.extract();
    
    } else if OID_MATCH(CertField, JONAH_x509_ucert_certificateSerialNumber_DER) {
    
      if ((status = cert.tbsCertificate.serialNumber.write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      results.append_own(buf);
      return results.extract();
    
    } else if OID_MATCH(CertField, JONAH_x509_ucert_validity_notbefore_DER) {
    
      if ((status = cert.tbsCertificate.validity.notBefore.write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      results.append_own(buf);
      return results.extract();
    
    } else if OID_MATCH(CertField, JONAH_x509_ucert_validity_notafter_DER) {
    
      if ((status = cert.tbsCertificate.validity.notAfter.write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      results.append_own(buf);
      return results.extract();
    
    } else if OID_MATCH(CertField, JONAH_x509_ucert_subjectPublicKeyInfo_DER) { 
    
      if ((status = cert.tbsCertificate.subjectPublicKeyInfo.write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      results.append_own(buf);
      return results.extract();
    
    } else if OID_MATCH(CertField, JONAH_x509_ucert_subjectPublicKeyInfo_algorithm_DER) {
    
      if ((status = cert.tbsCertificate.subjectPublicKeyInfo.algorithm.write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      results.append_own(buf);
      return results.extract();
    
    } else if OID_MATCH(CertField, JONAH_x509_ucert_subjectPublicKeyInfo_algorithm_oid_DER) {
    
      if ((status = cert.tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm.write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      results.append_own(buf);
      return results.extract();
    
    } else if OID_MATCH(CertField, JONAH_x509_ucert_subjectPublicKeyInfo_algorithm_parameters_DER) {
    
      if ((status = cert.tbsCertificate.subjectPublicKeyInfo.algorithm.parameters.write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      results.append_own(buf);
      return results.extract();
    
    } else if OID_MATCH(CertField, JONAH_x509_ucert_subjectPublicKeyInfo_publicKey_DER) {
    
      if ((status = cert.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      results.append_own(buf);
      return results.extract();
    
    } else if OID_MATCH(CertField, JONAH_x509_ucert_issuerUniqueID_DER) {
    
      if (!cert.tbsCertificate.issuerUniqueID.is_present())
        return CSSM_DATA_PTR_NULL;
      if ((status = cert.tbsCertificate.issuerUniqueID.write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      results.append_own(buf);
      return results.extract();
    
    } else if OID_MATCH(CertField, JONAH_x509_ucert_subjectUniqueID_DER) {
    
      if (!cert.tbsCertificate.subjectUniqueID.is_present())
        return CSSM_DATA_PTR_NULL;
      if ((status = cert.tbsCertificate.subjectUniqueID.write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      results.append_own(buf);
      return results.extract();
    
    } else if OID_MATCH(CertField, JONAH_x509_ucert_extensions_DER) {
      
      int i;
      cssm_inc * results;
      results = new cssm_inc(mems);

      if (!cert.tbsCertificate.extensions.is_present())
        return CSSM_DATA_PTR_NULL;
      
      for (i=0; i<cert.tbsCertificate.extensions.get_child_count(); i++) {
        if ((status = cert.tbsCertificate.extensions[i]->write(buf)) != 0) 
          SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
        results->append_own(buf);
      };
// Now we have the extensions in *results.  Cast results to a CSSM_HANDLE_PTR 
// and extract the first extension.
      *ResultsHandle = ptrToHandle(results);
      return results->extract();

    } else {
      SET_ERROR(CSSM_CL_UNKNOWN_TAG);
    };
  } catch (...) {
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
  }
fail:
  return CSSM_DATA_PTR_NULL;
}



/*************************************************************************
 *
 *  Function Name:  CL_CertGetNextFieldValue
 *
 *  Functional Description:  Extract the next of a list of fields from the 
 *                           CSSM_INCREMENTAL_DATA_PTR, passed via a
 *                           CSSM_HANDLE_PTR.
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/


CSSM_DATA_PTR CSSMAPI CL_CertGetNextFieldValue(CSSM_CL_HANDLE CLHandle,
                                               CSSM_HANDLE ResultsHandle)
{
  cssm_inc * results;

  if (ResultsHandle == 0) SET_ERROR(CSSM_CL_INVALID_RESULTS_HANDLE);
  
  results = (cssm_inc *)handleToPtr(ResultsHandle);

  if (results = NULL) SET_ERROR(CSSM_CL_INVALID_RESULTS_HANDLE);

  return results->extract();

fail:
  return CSSM_DATA_PTR_NULL;
}


/*************************************************************************
 *
 *  Function Name:  CL_CertAbortQuery
 *
 *  Functional Description:  Release the ResultsHandle object
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/


CSSM_RETURN CSSMAPI CL_CertAbortQuery(CSSM_CL_HANDLE CLHandle,
                                      CSSM_HANDLE ResultsHandle)
{
  cssm_inc * results;

  if (ResultsHandle == 0) SET_ERROR(CSSM_CL_INVALID_RESULTS_HANDLE);
  
  results = (cssm_inc *)handleToPtr(ResultsHandle, true);

  if (results = NULL) SET_ERROR(CSSM_CL_INVALID_RESULTS_HANDLE);

  delete results;

  return CSSM_OK;

fail:
  return CSSM_FAIL;
}




/*************************************************************************
 *
 *  Function Name:  CL_CertGetKeyInfo
 *
 *  Functional Description:  Returns a cssm_keyheader object describing
 *                           the public-key in the certificate.
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/

CSSM_KEY_PTR CSSMAPI CL_CertGetKeyInfo(CSSM_CL_HANDLE CLHandle,
                                       const CSSM_DATA_PTR Cert)
{
  memory_funcs_t mems(CLHandle,
                      clmUpcallTable.malloc_func,
                      clmUpcallTable.free_func,
                      clmUpcallTable.realloc_func,
                      clmUpcallTable.calloc_func);
  x509_certificate cert;
  r_buffer_t rbuf;
  buffer_t buf(mems);
  uint32 status;
  uint32 alg = CSSM_ALGID_RSA;
  CSSM_KEY_PTR cssmKeyPtr = NULL;

  CSSM_GUID zeroGUID = { 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0} };
  
  if (Cert == NULL) SET_ERROR(CSSM_CL_INVALID_DATA_POINTER);
  rbuf.data = Cert->Data;
  rbuf.data_len = Cert->Length;
  if ((status = cert.read(rbuf)) != 0) 
    SET_ERROR(CSSM_CL_UNKNOWN_FORMAT);

  if ((status = cert.tbsCertificate.subjectPublicKeyInfo.write(buf)) != 0)
    SET_ERROR(CSSM_CL_UNKNOWN_FORMAT);

  cssmKeyPtr = (CSSM_KEY_PTR)clmUpcallTable.malloc_func(CLHandle, sizeof(CSSM_KEY));
  if (cssmKeyPtr == NULL) SET_ERROR(CSSM_CL_MEMORY_ERROR);

  cssmKeyPtr->KeyData.Data = buf.data;
  cssmKeyPtr->KeyData.Length = buf.data_len;
  buf.detach();

  cssmKeyPtr->KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION;
  memcpy(&(cssmKeyPtr->KeyHeader.CspId), &zeroGUID, sizeof(CSSM_GUID));
  cssmKeyPtr->KeyHeader.BlobType = CSSM_KEYBLOB_RAW_BERDER;
  cssmKeyPtr->KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_OTHER;

  cssmKeyPtr->KeyHeader.AlgorithmId = alg;

  cssmKeyPtr->KeyHeader.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY;
  cssmKeyPtr->KeyHeader.KeySizeInBits = GetKeySize(cert.tbsCertificate.subjectPublicKeyInfo);
  cssmKeyPtr->KeyHeader.KeyAttr = CSSM_KEYATTR_MODIFIABLE;
  cssmKeyPtr->KeyHeader.KeyUsage = CSSM_KEYUSE_ANY; 
// Any extension restrictions on keyusage must be enforced externally
  cssmKeyPtr->KeyHeader.StartDate = asnTimeToCSSMTime(cert.tbsCertificate.validity.notBefore);
  cssmKeyPtr->KeyHeader.EndDate = asnTimeToCSSMTime(cert.tbsCertificate.validity.notAfter);
  cssmKeyPtr->KeyHeader.WrapAlgorithmId = CSSM_ALGID_NONE;
  cssmKeyPtr->KeyHeader.WrapMode = 0;
  cssmKeyPtr->KeyHeader.Reserved = 0;

  return cssmKeyPtr;

fail:
  return CSSM_KEY_PTR_NULL;
}



/*************************************************************************
 *
 *  Function Name:  CL_CertGetAllFields
 *
 *  Functional Description:  Returns a list of field/value pairs, 
 *                           listing all the fields in the certificate.
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/

CSSM_FIELD_PTR CSSMAPI CL_CertGetAllFields(CSSM_CL_HANDLE CLHandle,
                                           const CSSM_DATA_PTR Cert,
                                           uint32 * NumberOfFields)
{
  memory_funcs_t mems(CLHandle,
                      clmUpcallTable.malloc_func,
                      clmUpcallTable.free_func,
                      clmUpcallTable.realloc_func,
                      clmUpcallTable.calloc_func);
  CSSM_FIELD_PTR FieldPtr = NULL;
  x509_certificate cert;
  buffer_t buf(mems);
  r_buffer_t rbuf;
  uint32 status;
  int i;
  int j;

  if (Cert == NULL) SET_ERROR(CSSM_CL_INVALID_DATA_POINTER);
  
  rbuf.data = Cert->Data;
  rbuf.data_len = Cert->Length;
  
  if ((status = cert.read(rbuf)) != 0) 
    SET_ERROR(CSSM_CL_UNKNOWN_FORMAT);

// First, count the fields we're going to return.  An X509 cert has 18 
// mandatory fields, plus optional issuer and subject UUID fields, plus
// an arbitrary number of extensions.

  *NumberOfFields = 18;
  if (cert.tbsCertificate.issuerUniqueID.is_present()) (*NumberOfFields)++;
  if (cert.tbsCertificate.subjectUniqueID.is_present()) (*NumberOfFields)++;
  if (cert.tbsCertificate.extensions.is_present()) (*NumberOfFields) += cert.tbsCertificate.extensions.get_child_count();

// Allocate a structure to hold the fields, then encode them.
  FieldPtr = (CSSM_FIELD_PTR)clmUpcallTable.malloc_func(CLHandle, *NumberOfFields + sizeof(CSSM_FIELD));
  
  OidCpy(FieldPtr[0].FieldOid, JONAH_x509_cert_signature_DER);
  if ((status = cert.signatureAlgorithm.write(buf)) != 0) 
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
  FieldPtr[0].FieldValue.Length = buf.data_len;
  FieldPtr[0].FieldValue.Data = buf.data;
  buf.detach();


  OidCpy(FieldPtr[1].FieldOid, JONAH_x509_cert_signatureAlgorithmIdentifier_DER);
  if ((status = cert.signatureAlgorithm.write(buf)) != 0) 
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
  FieldPtr[1].FieldValue.Length = buf.data_len;
  FieldPtr[1].FieldValue.Data = buf.data;
  buf.detach();

  OidCpy(FieldPtr[2].FieldOid, JONAH_x509_cert_signatureAlgorithmIdentifier_objectIdentifier_DER);
  if ((status = cert.signatureAlgorithm.algorithm.write(buf)) != 0) 
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
  FieldPtr[2].FieldValue.Length = buf.data_len;
  FieldPtr[2].FieldValue.Data = buf.data;
  buf.detach();

  OidCpy(FieldPtr[3].FieldOid, JONAH_x509_cert_signatureAlgorithmIdentifier_parameters_DER);
  if ((status = cert.signatureAlgorithm.parameters.write(buf)) != 0) 
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
  FieldPtr[3].FieldValue.Length = buf.data_len;
  FieldPtr[3].FieldValue.Data = buf.data;
  buf.detach();

  {
    OidCpy(FieldPtr[4].FieldOid, JONAH_x509_ucert_version_DER);
    x509_version_t ver;

    if ((status = cert.tbsCertificate.version.get_value(ver)) != 0) 
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
    switch (ver) {
      case X509_V1: buf.append((unsigned char)0); break;
      case X509_V2: buf.append(1); break;
      case X509_V3: buf.append(2); break;
      default:
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
    };
  };
  FieldPtr[4].FieldValue.Length = buf.data_len;
  FieldPtr[4].FieldValue.Data = buf.data;
  buf.detach();

  OidCpy(FieldPtr[5].FieldOid, JONAH_x509_ucert_signatureAlgorithmIdentifier_DER);
  if ((status = cert.tbsCertificate.signature.write(buf)) != 0) 
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
  FieldPtr[5].FieldValue.Length = buf.data_len;
  FieldPtr[5].FieldValue.Data = buf.data;
  buf.detach();
    
  OidCpy(FieldPtr[6].FieldOid, JONAH_x509_ucert_signatureAlgorithmIdentifier_objectIdentifier_DER);
  if ((status = cert.tbsCertificate.signature.algorithm.write(buf)) != 0) 
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
  FieldPtr[6].FieldValue.Length = buf.data_len;
  FieldPtr[6].FieldValue.Data = buf.data;
  buf.detach();
    
  OidCpy(FieldPtr[7].FieldOid, JONAH_x509_ucert_signatureAlgorithmIdentifier_parameters_DER);
  if ((status = cert.tbsCertificate.signature.parameters.write(buf)) != 0) 
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
  FieldPtr[7].FieldValue.Length = buf.data_len;
  FieldPtr[7].FieldValue.Data = buf.data;
  buf.detach();
    
  OidCpy(FieldPtr[8].FieldOid, JONAH_x509_ucert_issuerName_DER);
  if ((status = cert.tbsCertificate.issuer.write(buf)) != 0) 
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
  FieldPtr[8].FieldValue.Length = buf.data_len;
  FieldPtr[8].FieldValue.Data = buf.data;
  buf.detach();
    
  OidCpy(FieldPtr[9].FieldOid, JONAH_x509_ucert_subjectName_DER);
  if ((status = cert.tbsCertificate.subject.write(buf)) != 0) 
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
  FieldPtr[9].FieldValue.Length = buf.data_len;
  FieldPtr[9].FieldValue.Data = buf.data;
  buf.detach();
    
  OidCpy(FieldPtr[10].FieldOid, JONAH_x509_ucert_certificateSerialNumber_DER);
  if ((status = cert.tbsCertificate.serialNumber.write(buf)) != 0) 
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
  FieldPtr[10].FieldValue.Length = buf.data_len;
  FieldPtr[10].FieldValue.Data = buf.data;
  buf.detach();
    
  OidCpy(FieldPtr[11].FieldOid, JONAH_x509_ucert_validity_notbefore_DER);
  if ((status = cert.tbsCertificate.validity.notBefore.write(buf)) != 0) 
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
  FieldPtr[11].FieldValue.Length = buf.data_len;
  FieldPtr[11].FieldValue.Data = buf.data;
  buf.detach();
    
  OidCpy(FieldPtr[12].FieldOid, JONAH_x509_ucert_validity_notafter_DER);
  if ((status = cert.tbsCertificate.validity.notAfter.write(buf)) != 0) 
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
  FieldPtr[12].FieldValue.Length = buf.data_len;
  FieldPtr[12].FieldValue.Data = buf.data;
  buf.detach();
    
  OidCpy(FieldPtr[13].FieldOid, JONAH_x509_ucert_subjectPublicKeyInfo_DER);
  if ((status = cert.tbsCertificate.subjectPublicKeyInfo.write(buf)) != 0) 
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
  FieldPtr[13].FieldValue.Length = buf.data_len;
  FieldPtr[13].FieldValue.Data = buf.data;
  buf.detach();
    
  OidCpy(FieldPtr[14].FieldOid, JONAH_x509_ucert_subjectPublicKeyInfo_algorithm_DER);
  if ((status = cert.tbsCertificate.subjectPublicKeyInfo.algorithm.write(buf)) != 0) 
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
  FieldPtr[14].FieldValue.Length = buf.data_len;
  FieldPtr[14].FieldValue.Data = buf.data;
  buf.detach();
    
  OidCpy(FieldPtr[15].FieldOid, JONAH_x509_ucert_subjectPublicKeyInfo_algorithm_oid_DER);
  if ((status = cert.tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm.write(buf)) != 0) 
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
  FieldPtr[15].FieldValue.Length = buf.data_len;
  FieldPtr[15].FieldValue.Data = buf.data;
  buf.detach();
    
  OidCpy(FieldPtr[16].FieldOid, JONAH_x509_ucert_subjectPublicKeyInfo_algorithm_parameters_DER);
  if ((status = cert.tbsCertificate.subjectPublicKeyInfo.algorithm.parameters.write(buf)) != 0) 
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
  FieldPtr[16].FieldValue.Length = buf.data_len;
  FieldPtr[16].FieldValue.Data = buf.data;
  buf.detach();
    
  OidCpy(FieldPtr[17].FieldOid, JONAH_x509_ucert_subjectPublicKeyInfo_publicKey_DER);
  if ((status = cert.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.write(buf)) != 0) 
    SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
  FieldPtr[17].FieldValue.Length = buf.data_len;
  FieldPtr[17].FieldValue.Data = buf.data;
  buf.detach();
  
// Now the optional fields...
  i = 18;
  if (cert.tbsCertificate.issuerUniqueID.is_present()) {
    OidCpy(FieldPtr[i].FieldOid, JONAH_x509_ucert_issuerUniqueID_DER);
    if ((status = cert.tbsCertificate.issuerUniqueID.write(buf)) != 0) 
      SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
    FieldPtr[i].FieldValue.Length = buf.data_len;
    FieldPtr[i++].FieldValue.Data = buf.data;
    buf.detach();
  };
    
  if (cert.tbsCertificate.subjectUniqueID.is_present()) {
    OidCpy(FieldPtr[i].FieldOid, JONAH_x509_ucert_subjectUniqueID_DER);
    if ((status = cert.tbsCertificate.subjectUniqueID.write(buf)) != 0) 
      SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
    FieldPtr[i].FieldValue.Length = buf.data_len;
    FieldPtr[i++].FieldValue.Data = buf.data;
    buf.detach();
  };
    
  if (cert.tbsCertificate.extensions.is_present()) {
    for (j=0;j<cert.tbsCertificate.extensions.get_child_count(); i++,j++) {
      OidCpy(FieldPtr[i].FieldOid, JONAH_x509_ucert_extensions_DER);
      if ((status = cert.tbsCertificate.extensions[j]->write(buf)) != 0) 
        SET_ERROR(CSSM_CL_CERT_GET_FIELD_VALUE_FAIL);
      FieldPtr[i].FieldValue.Length = buf.data_len;
      FieldPtr[i].FieldValue.Data = buf.data;
      buf.detach();
    }
  };

  return FieldPtr;
fail:
  return CSSM_FIELD_PTR_NULL;

}


/*************************************************************************
 *
 *  Function Name:  CL_CertImport
 *
 *  Functional Description:  Not implemented
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/

CSSM_DATA_PTR CSSMAPI CL_CertImport(CSSM_CL_HANDLE CLHandle,
                                    CSSM_CERT_TYPE ForeignCertType,
                                    const CSSM_DATA_PTR ForeignCert)
{
  SET_ERROR(CSSM_CL_UNSUPPORTED_OPERATION);
fail:
  return CSSM_DATA_PTR_NULL;
}



/*************************************************************************
 *
 *  Function Name:  CL_CertExport
 *
 *  Functional Description:  Not implemented
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/

CSSM_DATA_PTR CSSMAPI CL_CertExport(CSSM_CL_HANDLE CLHandle,
                                    CSSM_CERT_TYPE TargetCertType,
                                    const CSSM_DATA_PTR Cert)
{
  SET_ERROR(CSSM_CL_UNSUPPORTED_OPERATION);
fail:
  return CSSM_DATA_PTR_NULL;
}


/*************************************************************************
 *
 *  Function Name:  CL_CertDescribeFormat
 *
 *  Functional Description:  Not implemented
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/

CSSM_OID_PTR CSSMAPI CL_CertDescribeFormat(CSSM_CL_HANDLE CLHandle,
                                           uint32 * NumberOfFields)
{
  SET_ERROR(CSSM_CL_UNSUPPORTED_OPERATION);
fail:
  return CSSM_OID_PTR_NULL;
}




/**************************************************************************
 * CRL operations
 **************************************************************************/


/*************************************************************************
 *
 *  Function Name:  CL_CrlCreateTemplate
 *
 *  Functional Description:  Not implemented
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/

CSSM_DATA_PTR CSSMAPI CL_CrlCreateTemplate(CSSM_CL_HANDLE CLHandle,
                                           const CSSM_FIELD_PTR Crltemplate,
                                           uint32 NumberOfFields)
{
  SET_ERROR(CSSM_CL_UNSUPPORTED_OPERATION);
fail:
  return CSSM_DATA_PTR_NULL;
}



/*************************************************************************
 *
 *  Function Name:  CL_CrlAddCert
 *
 *  Functional Description:  Not implemented
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/

CSSM_DATA_PTR CSSMAPI CL_CrlAddCert(CSSM_CL_HANDLE CLHandle,
                                    CSSM_CC_HANDLE CCHandle,
                                    const CSSM_DATA_PTR Cert,
                                    const CSSM_DATA_PTR RevokerCert,
                                    CSSM_REVOKE_REASON RevokeReason,
                                    const CSSM_DATA_PTR OldCrl)
{
  SET_ERROR(CSSM_CL_UNSUPPORTED_OPERATION);
fail:
  return CSSM_DATA_PTR_NULL;
}



/*************************************************************************
 *
 *  Function Name:  CL_CrlRemoveCert
 *
 *  Functional Description:  Not implemented
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/

CSSM_DATA_PTR CSSMAPI CL_CrlRemoveCert(CSSM_CL_HANDLE CLHandle,
                                       const CSSM_DATA_PTR Cert,
                                       const CSSM_DATA_PTR OldCrl)
{
  SET_ERROR(CSSM_CL_UNSUPPORTED_OPERATION);
fail:
  return CSSM_DATA_PTR_NULL;
}



/*************************************************************************
 *
 *  Function Name:  CL_CrlSign
 *
 *  Functional Description:  Not implemented
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/

CSSM_DATA_PTR CSSMAPI CL_CrlSign(CSSM_CL_HANDLE CLHandle,
                                 CSSM_CC_HANDLE CCHandle,
                                 const CSSM_DATA_PTR UnsignedCrl,
                                 const CSSM_DATA_PTR SignerCert,
                                 const CSSM_FIELD_PTR SignScope,
                                 uint32 ScopeSize)
{
  SET_ERROR(CSSM_CL_UNSUPPORTED_OPERATION);
fail:
  return CSSM_DATA_PTR_NULL;
}



/*************************************************************************
 *
 *  Function Name:  CL_CrlVerify
 *
 *  Functional Description:  Not implemented
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/

CSSM_BOOL CSSMAPI CL_CrlVerify(CSSM_CL_HANDLE CLHandle,
                                   CSSM_CC_HANDLE CCHandle,
                                   const CSSM_DATA_PTR SubjectCrl,
                                   const CSSM_DATA_PTR SignerCert,
                                   const CSSM_FIELD_PTR VerifyScope,
                                   uint32 ScopeSize)
{
  SET_ERROR(CSSM_CL_UNSUPPORTED_OPERATION);
fail:
  return CSSM_FALSE;
}



/*************************************************************************
 *
 *  Function Name:  CL_IsCertInCrl
 *
 *  Functional Description:  Not implemented
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/

CSSM_BOOL CSSMAPI CL_IsCertInCrl(CSSM_CL_HANDLE CLHandle,
                                 const CSSM_DATA_PTR Cert,
                                 const CSSM_DATA_PTR Crl)
{
  SET_ERROR(CSSM_CL_UNSUPPORTED_OPERATION);
fail:
  return CSSM_FALSE;
}



/*************************************************************************
 *
 *  Function Name:  CL_CrlGetFirstFieldValue
 *
 *  Functional Description:  Return the first field that matches the
 *                           provided criteria.
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/

CSSM_DATA_PTR CSSMAPI CL_CrlGetFirstFieldValue(CSSM_CL_HANDLE CLHandle,
                                               const CSSM_DATA_PTR Crl,
                                               const CSSM_OID_PTR CrlField,
                                               CSSM_HANDLE_PTR ResultsHandle,
                                               uint32 * NumberOfMatchedFields)
{
  SET_ERROR(CSSM_CL_UNSUPPORTED_OPERATION);
fail:
  return CSSM_DATA_PTR_NULL;
}


/*************************************************************************
 *
 *  Function Name:  CL_CrlGetNextFieldValue
 *
 *  Functional Description:  Return the next matching field
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/

CSSM_DATA_PTR CSSMAPI CL_CrlGetNextFieldValue(CSSM_CL_HANDLE CLHandle,
                                              CSSM_HANDLE ResultsHandle)
{
  cssm_inc * results;

  if (ResultsHandle == 0) SET_ERROR(CSSM_CL_INVALID_RESULTS_HANDLE);
  
  results = (cssm_inc *)handleToPtr(ResultsHandle);

  if (results = NULL) SET_ERROR(CSSM_CL_INVALID_RESULTS_HANDLE);

  return results->extract();

fail:
  return CSSM_DATA_PTR_NULL;
}




/*************************************************************************
 *
 *  Function Name:  CL_CrlAbortQuery
 *
 *  Functional Description:  Release the ResultsHandle
  *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/

CSSM_RETURN CSSMAPI CL_CrlAbortQuery(CSSM_CL_HANDLE CLHandle,
                                     CSSM_HANDLE ResultsHandle)
{
  cssm_inc * results;

  if (ResultsHandle == 0) SET_ERROR(CSSM_CL_INVALID_RESULTS_HANDLE);
  
  results = (cssm_inc *)handleToPtr(ResultsHandle, true);

  if (results = NULL) SET_ERROR(CSSM_CL_INVALID_RESULTS_HANDLE);

  delete results;

  return CSSM_OK;

fail:
  return CSSM_FAIL;
}



/*************************************************************************
 *
 *  Function Name:  CL_CrlDescribeFormat
 *
 *  Functional Description:  Not Implemented
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/

CSSM_OID_PTR CSSMAPI CL_CrlDescribeFormat(CSSM_CL_HANDLE CLHandle,
                                          uint32 * NumberOfFields)
{
  SET_ERROR(CSSM_CL_UNSUPPORTED_OPERATION);
fail:
  return CSSM_OID_PTR_NULL;
}


/*************************************************************************
 *
 *  Function Name:  CL_PassThrough
 *
 *  Functional Description:  Not Implemented
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/

void * CSSMAPI CL_PassThrough(CSSM_CL_HANDLE CLHandle,
                              CSSM_CC_HANDLE CCHandle,
                              uint32 PassThroughId,
                              const void * InputParams)
{
  SET_ERROR(CSSM_CL_UNSUPPORTED_OPERATION);
fail:
  return NULL;
}






/*************************************************************************
*
*   CDSA Module Management stuff
*
*************************************************************************/

/*************************************************************************
 *
 *  Function Name:  CL_Initialize
 *
 *  Functional Description:  Initialize the CL
 
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/


CSSM_RETURN CSSMAPI CL_Initialize(CSSM_MODULE_HANDLE Handle,
                                  uint32 VerMajor,
                                  uint32 VerMinor)
{

  if ((VerMajor != JONAHCL_MAJOR_VERSION) || (VerMinor != JONAHCL_MINOR_VERSION))
    SET_ERROR(CSSM_INCOMPATIBLE_VERSION);

  return CSSM_OK;

fail:
  return CSSM_FAIL;
}




/*************************************************************************
 *
 *  Function Name:  CL_Terminate
 *
 *  Functional Description:  Terminate the CL
 
 *
 *  Input:  
 *
 *  Output: 
 *
 *  Data Members Modified:
 *
 *  Return Values:
 *
 *
 *  Side Effects:
 *
 *  Notes:
 *
 *************************************************************************/


CSSM_RETURN CSSMAPI CL_Terminate(CSSM_MODULE_HANDLE Handle)
{
  return CSSM_OK;


}


BOOL WINAPI DllMain(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved) {
  BOOL returnVal = TRUE;

  switch(dwReason) {
  case DLL_PROCESS_ATTACH:
    {
      CSSM_REGISTRATION_INFO regInfo;
      CSSM_MODULE_FUNCS moduleFuncs;
      CSSM_SPI_CL_FUNCS functionTable;

      regInfo.Initialize = CL_Initialize;
      regInfo.Terminate = CL_Terminate;
      regInfo.EventNotify = NULL;
      regInfo.GetModuleInfo = NULL;
      regInfo.FreeModuleInfo = NULL;
      regInfo.ThreadSafe = JONAHCL_THREADSAFE;
      regInfo.ServiceSummary = CSSM_SERVICE_CL;
      regInfo.NumberOfServiceTables = JONAHCL_NUMSUBSERVICE;
      regInfo.Services = &moduleFuncs;
  
      moduleFuncs.ServiceType = CSSM_SERVICE_CL;
      moduleFuncs.ClFuncs = &functionTable;
  
      functionTable.CertSign = CL_CertSign;
      functionTable.CertVerify = CL_CertVerify;
      functionTable.CertCreateTemplate = CL_CertCreateTemplate;
      functionTable.CertGetFirstFieldValue = CL_CertGetFirstFieldValue;
      functionTable.CertGetNextFieldValue = CL_CertGetNextFieldValue;
      functionTable.CertAbortQuery = CL_CertAbortQuery;
      functionTable.CertGetKeyInfo = CL_CertGetKeyInfo;
      functionTable.CertGetAllFields = CL_CertGetAllFields;
      functionTable.CertImport = CL_CertImport;
      functionTable.CertExport = CL_CertExport;
      functionTable.CertDescribeFormat = CL_CertDescribeFormat;
      functionTable.CrlCreateTemplate = CL_CrlCreateTemplate;
      functionTable.CrlAddCert = CL_CrlAddCert;
      functionTable.CrlRemoveCert = CL_CrlRemoveCert;
      functionTable.CrlSign = CL_CrlSign;
      functionTable.CrlVerify = CL_CrlVerify;
      functionTable.IsCertInCrl = CL_IsCertInCrl;
      functionTable.CrlGetFirstFieldValue = CL_CrlGetFirstFieldValue;
      functionTable.CrlGetNextFieldValue = CL_CrlGetNextFieldValue;
      functionTable.CrlAbortQuery = CL_CrlAbortQuery;
      functionTable.CrlDescribeFormat = CL_CrlDescribeFormat;
      functionTable.PassThrough = CL_PassThrough;
  
      if (CSSM_RegisterServices((CSSM_GUID * const)&JONAHCL_GUID,
                                &regInfo,
                                &clmUpcallTable,
                                NULL) != CSSM_OK) {
        returnVal = FALSE;
      };
      CSSM_ClearError();
    };
    break;
  
  case DLL_PROCESS_DETACH:
    {
      if (CSSM_DeregisterServices((CSSM_GUID * const)&JONAHCL_GUID) != CSSM_OK) {
        returnVal = FALSE;
      };
    };
    break;
  
  case DLL_THREAD_ATTACH:
    break;

  case DLL_THREAD_DETACH:
    break;
  };

  return returnVal;

}

// this func is for use on Unix systems, and just calls the DllMain routine, faking
// a DLL_PROCESS_ATTACH

BOOL _init(void) {
  return (DllMain(NULL, DLL_PROCESS_ATTACH, NULL));
}
