/* SCCSID: fwk/cssm/clapi.c, dss_cdsa_fwk, fwk_rel2, dss_971010 1.9 10/10/97 10:47:21 */
/* ***************************************************************** *
 * 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.                                                        *
 * ***************************************************************** */

/*-----------------------------------------------------------------------
 *      File:   CLAPI.C
 *
 * This file contains the functions that are contained in the CLI portion
 * of the CSSM exported functions.
 */
/*
 * (C) COPYRIGHT International Business Machines Corp. 1996, 1997
 * All Rights Reserved
 * Licensed Materials - Property of IBM
 *
 * Copyright (c) 1995, 1996, 1997 Intel Corporation. All rights reserved.
 *
 * US Government Users Restricted Rights - Use, duplication or
 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 *
 */
/*
 * WARNING: EXPORT RESTRICTED.
 * This software listing contains cryptographic methods and technology.
 * It is export restricted by the Office of Defense Trade Controls, United
 * States Department of State and cannot be downloaded or otherwise
 * exported or re-exported (i) into (or to a national or resident of) Cuba,
 * Iraq, Libya, Yugoslavia, North Korea, Iran, Syria or any other country
 * to which the US has embargoed goods; or (ii) to anyone on the US
 * Treasury Department's list of Specially Designated Nationals or the US
 * Commerce Department's Table of Denial Orders. By downloading or using
 * this product, you are agreeing to the foregoing and you are representing
 * and warranting that you are not located in, under the control of, or a
 * national or resident of any such country or on any such list.
 */

#include "cssm.h"
#include "cssmport.h"
#include "internal.h"
#include "cssmcli.h"
#include "addin.h"

/* Proposed Certificate Library API */
/* Certificate Library Operations */

/* Returns the signed certificate */
/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CertSign
 *
 *Description:
 *   Exported function for CL module signs a certificate
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   CCHandle - handle of cryptographic context
 *   SubjectCert - pointer to certificate to be sign
 *   SignerCert - pointer to certificate used in signing
 *   SignScope - pointer to the scope of fields to sign
 *   ScopeSize - number of fields in SignScope
 *
 *Returns:
 *  Null - CL unable to sign certificate
 *  non Null - pointer to signed certificate
 *
 *----------------------------------------------------------------*/
CSSM_DATA_PTR CSSMAPI CSSM_CL_CertSign (CSSM_CL_HANDLE CLHandle,
                                        CSSM_CC_HANDLE CCHandle,
                                        const CSSM_DATA_PTR SubjectCert,
                                        const CSSM_DATA_PTR SignerCert,
                                        const CSSM_FIELD_PTR SignScope,
                                        uint32 ScopeSize)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_DATA_PTR Data = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle,
                       CSSM_SERVICE_CL);

	if (CallBack == NULL)
		return(NULL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            // cssm error is set
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CertSign))
		Data = CallBack->CertSign (CLHandle, CCHandle, SubjectCert,
		SignerCert, SignScope, ScopeSize);
	else {
		Data = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			 // panic and dont free
			Data = NULL;
		}
    }
    return(Data);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CertVerify
 *
 *Description:
 *   Exported function for CL module to verify the signature of
 *   a signed certificate
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   CCHandle - handle of cryptographic context
 *   SubjectCert - pointer to the signed certificate
 *   SignerCert - pointer to certificate used in signing
 *   VerifyScope - pointer to the scope of fields of signature
 *   ScopeSize - number of fields in VerifyScope
 *
 *Returns:
 *  CSSM_FALSE - CL unable to verify signature
 *  CSSM_TRUE - signature is verified
 *
 *----------------------------------------------------------------*/
CSSM_BOOL CSSMAPI CSSM_CL_CertVerify (CSSM_CL_HANDLE CLHandle,
                                      CSSM_CC_HANDLE CCHandle,
                                      const CSSM_DATA_PTR SubjectCert,
                                      const CSSM_DATA_PTR SignerCert,
                                      const CSSM_FIELD_PTR VerifyScope,
                                      uint32 ScopeSize)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_BOOL ret = CSSM_FALSE;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle,
                       CSSM_SERVICE_CL);

	if (CallBack == NULL)
		return(CSSM_FALSE);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
			// cssm error is set
            return(CSSM_FALSE);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CertVerify))
		ret = CallBack->CertVerify (CLHandle, CCHandle, SubjectCert,
		SignerCert, VerifyScope, ScopeSize);
	else {
		ret = CSSM_FALSE;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			ret = CSSM_FALSE;
		}
    }
    return(ret);
}

/* Returns the new certificate */
/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CertCreateTemplate
 *
 *Description:
 *   Exported function for CL module for creating a certificate
 *   template
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   CertTemplate - pointer to data that describes certificate
 *   NumberOfFields - number of fields in the template
 *
 *Returns:
 *  Null - CL unable to create ccertificate
 *  non Null - pointer  to the created ccertificate
 *
 *----------------------------------------------------------------*/
CSSM_DATA_PTR CSSMAPI CSSM_CL_CertCreateTemplate (
                                          CSSM_CL_HANDLE CLHandle,
                                          const CSSM_FIELD_PTR CertTemplate,
                                          uint32 NumberOfFields)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_DATA_PTR Data = NULL;
    CSSM_MUTEX retMutex;

	/* clear the error */
    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle,
                       CSSM_SERVICE_CL);

	if (CallBack == NULL)
		return(NULL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CertCreateTemplate))
		Data = CallBack->CertCreateTemplate (CLHandle, CertTemplate,
		NumberOfFields);
	else {
		Data = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			Data = NULL;
		}
    }
    return(Data);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CertGetFirstFieldView
 *
 *Description:
 *   Exported function for CL module to return each field
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   Cert - pointer to the certificate
 *   CertField - pointer to an OID of field
 *   ResultHandle - pointer to handle that describes this search
 *   NumberOfFields - pointer to the number of fields in the
 *
 *Returns:
 *  Null - CL unable to retreive data of certificate
 *  non Null - pointer to the first match OID
 *
 *----------------------------------------------------------------*/
CSSM_DATA_PTR CSSMAPI CSSM_CL_CertGetFirstFieldValue (CSSM_CL_HANDLE CLHandle,
                                                 const CSSM_DATA_PTR Cert,
                                                 const CSSM_OID_PTR CertField,
                                                 CSSM_HANDLE_PTR ResultsHandle,
                                                 uint32 *NumberOfMatchedFields)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_DATA_PTR Data = NULL;
    CSSM_MUTEX retMutex;

	/* clear the error */
    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle, CSSM_SERVICE_CL);

	if (CallBack == NULL) 
		return(NULL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CertGetFirstFieldValue))
		Data = CallBack->CertGetFirstFieldValue (CLHandle, Cert, CertField,
		                                         ResultsHandle, NumberOfMatchedFields);
	else {
		Data = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if (cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			Data = NULL;
		}
    }

    return(Data);
}

/* Returns the field value */
/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CertGetNextFieldValue
 *
 *Description:
 *   Exported function for CL module to retreive the next field
 *   in certificate
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   ResultHandle - handle that describes this search
 *
 *Returns:
 *  Null - CL unable to retreive more data from certificate
 *  non Null - pointer to the next match OID
 *
 *----------------------------------------------------------------*/
CSSM_DATA_PTR CSSMAPI CSSM_CL_CertGetNextFieldValue (CSSM_CL_HANDLE CLHandle,
                                                     CSSM_HANDLE ResultsHandle)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_DATA_PTR Data = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle, CSSM_SERVICE_CL);

	if (CallBack == NULL) 
		return(NULL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE)
    {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CertGetNextFieldValue))
		Data = CallBack->CertGetNextFieldValue (CLHandle, ResultsHandle);
	else {
		Data = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free Data
			Data = NULL;
		}
    }

    return(Data);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CertAbortQuery
 *
 *Description:
 *   Exported function for CL module to abort retreiving fields
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   ResultHandle - handle that describes this search
 *
 *Returns:
 *  CSSM_FAIL - CL unable to terminate search
 *  CSSM_OK - search has been terminated
 *
 *----------------------------------------------------------------*/
CSSM_RETURN CSSMAPI CSSM_CL_CertAbortQuery (CSSM_CL_HANDLE CLHandle,
                                            CSSM_HANDLE ResultsHandle)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_RETURN ret = CSSM_FAIL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle, CSSM_SERVICE_CL);

	if (CallBack == NULL) 
		return(CSSM_FAIL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(CSSM_FAIL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CertAbortQuery))
		ret = CallBack->CertAbortQuery (CLHandle, ResultsHandle);
	else {
		ret = CSSM_FAIL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// cssm error is set
			ret = CSSM_FAIL;
		}
    }

    return(ret);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CertGetKeyInfo
 *
 *Description:
 *   Exported function for CL module to retreiving the key from
 *   the certificate
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   Cert - pointer to the certificate
 *
 *Returns:
 *  Null - CL unable to retreive the key
 *  non Null - pointer to the key
 *
 *----------------------------------------------------------------*/
CSSM_KEY_PTR CSSMAPI CSSM_CL_CertGetKeyInfo (CSSM_CL_HANDLE CLHandle,
                                            const CSSM_DATA_PTR Cert)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_KEY_PTR key = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle,
                       CSSM_SERVICE_CL);

	if (CallBack == NULL) 
		return(NULL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CertGetKeyInfo))
		key = CallBack->CertGetKeyInfo (CLHandle, Cert);
	else {
		key = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			key = NULL;
		}
    }

    return(key);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CertGetAllFields
 *
 *Description:
 *   Exported function for CL module to retreive all fields
 *   in the certificate
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   Cert - pointer to the certificate
 *   NumberOfFields - pointer to the number of fields in the
 *             returning field pointer
 *
 *Returns:
 *  Null - CL unable to get fields of certificate
 *  non Null - pointer to the field information of the certificate
 *
 *----------------------------------------------------------------*/
CSSM_FIELD_PTR CSSMAPI CSSM_CL_CertGetAllFields(CSSM_CL_HANDLE CLHandle,
                                                const CSSM_DATA_PTR Cert,
                                                uint32 *NumberOfFields)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_FIELD_PTR field = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle, CSSM_SERVICE_CL);

	if (CallBack == NULL) 
		return(NULL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE)
    {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CertGetAllFields))
		field = CallBack->CertGetAllFields (CLHandle, Cert, NumberOfFields);
	else {
		field = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			field = NULL;
		}
    }

    return(field);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CertImport
 *
 *Description:
 *   Exported function for CL module to import certificates of
 *   foreign type to a native certificate
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   ForeignCertType - identification of foreign certificate
 *   ForeignCert - pointer to the certificate
 *
 *Returns:
 *  Null - CL unable to import certificate
 *  non Null - pointer to imported certificate
 *
 *----------------------------------------------------------------*/
CSSM_DATA_PTR CSSMAPI CSSM_CL_CertImport (CSSM_CL_HANDLE CLHandle,
                                          CSSM_CERT_TYPE ForeignCertType,
                                          const CSSM_DATA_PTR ForeignCert)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_DATA_PTR Data = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle, CSSM_SERVICE_CL);

	if (CallBack == NULL) 
		return(NULL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CertImport))
		Data = CallBack->CertImport (CLHandle, ForeignCertType, ForeignCert);
	else {
		Data = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			/* panic and dont free */
			Data = NULL;
		}
    }

    return(Data);
}

/* Returns the certificate in the foreign format */
/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CertExport
 *
 *Description:
 *   Exported function for CL module to export certificate
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   TargetCertType - identification of foreign certificate
 *   NativeCert - pointer to the native certificate
 *
 *Returns:
 *  Null - CL unable to export certificate
 *  non Null - pointer to exported certificate
 *
 *----------------------------------------------------------------*/
CSSM_DATA_PTR CSSMAPI CSSM_CL_CertExport (CSSM_CL_HANDLE CLHandle,
                                          CSSM_CERT_TYPE TargetCertType,
                                          const CSSM_DATA_PTR NativeCert)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_DATA_PTR Data = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle, CSSM_SERVICE_CL);

	if (CallBack == NULL)
		return(NULL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CertExport))
		Data = CallBack->CertExport (CLHandle, TargetCertType, NativeCert);
	else {
		Data = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			Data = NULL;
		}
    }

    return(Data);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CertDescribeFormat
 *
 *Description:
 *   Exported function for CL module to desrcibe its native format
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   NumberOfFields - pointer to the number of oids in the
 *             returning oid pointer
 *
 *Returns:
 *  Null - CL unable to describe its format
 *  non Null - pointer to oids that describes the native certificate
 *             format
 *
 *----------------------------------------------------------------*/
CSSM_OID_PTR CSSMAPI CSSM_CL_CertDescribeFormat (CSSM_CL_HANDLE CLHandle,
                                                 uint32 *NumberOfFields)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_OID_PTR oid = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle, CSSM_SERVICE_CL);

	if (CallBack == NULL)
		return(NULL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CertDescribeFormat))
		oid = CallBack->CertDescribeFormat (CLHandle, NumberOfFields);
	else {
		oid = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			oid = NULL;
		}
    }
    return(oid);
}

/* Returns the new CRL */
/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CrlCreateTemplate
 *
 *Description:
 *   Exported function for CL module to create a crl template
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *
 *Returns:
 *  Null - CL unable to create a crl
 *  non Null - pointer to the created crl
 *
 *----------------------------------------------------------------*/
CSSM_DATA_PTR CSSMAPI CSSM_CL_CrlCreateTemplate (CSSM_CL_HANDLE CLHandle,
                                               const CSSM_FIELD_PTR CrlTemplate,
                                               uint32 NumberOfFields)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_DATA_PTR Data = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle, CSSM_SERVICE_CL);

	if (CallBack == NULL)
		return(NULL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CrlCreateTemplate))
		Data = CallBack->CrlCreateTemplate (CLHandle, CrlTemplate,
		NumberOfFields);
	else {
		Data = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			Data = NULL;
		}
    }

    return(Data);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CrlSetFields
 *
 *Description:
 *   Exported function for CL module set fields in a crl
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   CrlTemplate - array of field OID/value pairs containing the
 *                 values to initialize the CRL
 *   NumberOfFields - number of values in array
 *   OldCrl - pointer to the existing crl
 *
 *Returns:
 *  Null - CL unable to update crl
 *  non Null - pointer to new crl with new record
 *
 *----------------------------------------------------------------*/
CSSM_DATA_PTR CSSMAPI CSSM_CL_CrlSetFields (CSSM_CL_HANDLE CLHandle,
                                            const CSSM_FIELD_PTR CrlTemplate,
                                            uint32 NumberOfFields,
                                            const CSSM_DATA_PTR OldCrl)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_DATA_PTR Data = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle, CSSM_SERVICE_CL);

	if (CallBack == NULL)
		return(NULL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CrlSetFields))
		Data = CallBack->CrlSetFields (CLHandle, CrlTemplate,
		NumberOfFields, OldCrl);
	else {
		Data = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and don't free
			Data = NULL;
		}
    }
    return(Data);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CrlAddCert
 *
 *Description:
 *   Exported function for CL module adding a certificate to
 *   a crl
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   CCHandle - handle of cryptographic context
 *   Cert - pointer to the certificate to add to crl
 *   RevokerCert - pointer to certificate used in revoking the Cert
 *   RevokeReason - reason for revoking the certificate
 *   OldCrl - pointer to the existing crl
 *
 *Returns:
 *  Null - CL unable to update crl
 *  non Null - pointer to new crl with new Cert as an entry
 *
 *----------------------------------------------------------------*/
CSSM_DATA_PTR CSSMAPI CSSM_CL_CrlAddCert (CSSM_CL_HANDLE CLHandle,
                                          CSSM_CC_HANDLE CCHandle,
                                          const CSSM_DATA_PTR Cert,
                                          const CSSM_DATA_PTR RevokerCert,
                                          const CSSM_FIELD_PTR CrlEntryFields,
                                          uint32 NumberOfFields,
                                          const CSSM_DATA_PTR OldCrl)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_DATA_PTR Data = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle, CSSM_SERVICE_CL);

	if (CallBack == NULL)
		return(NULL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CrlAddCert))
		Data = CallBack->CrlAddCert (CLHandle, CCHandle, Cert, RevokerCert,
		0, OldCrl);
	else {
		Data = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and donr free
			Data = NULL;
		}
    }

    return(Data);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CrlRemoveCert
 *
 *Description:
 *   Exported function for CL module for removing a certificate
 *   from the crl
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   Cert - pointer to the certificate to remove from crl
 *   OldCrl - pointer to the existing crl
 *
 *Returns:
 *  Null - CL unable to update crl
 *  non Null - pointer to new crl with new Cert removed
 *
 *----------------------------------------------------------------*/
CSSM_DATA_PTR CSSMAPI CSSM_CL_CrlRemoveCert (CSSM_CL_HANDLE CLHandle,
                                            const CSSM_DATA_PTR Cert,
                                            const CSSM_DATA_PTR OldCrl)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_DATA_PTR Data = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle, CSSM_SERVICE_CL);

	if (CallBack == NULL)
		return(NULL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CrlRemoveCert))
		Data = CallBack->CrlRemoveCert (CLHandle, Cert, OldCrl);
	else {
		Data = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free;
			Data = NULL;
		}
    }

    return(Data);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CrlSign
 *
 *Description:
 *   Exported function for CL module to sign crl
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   CCHandle - handle of cryptographic context
 *   UnsignedCrl - pointer to crl to be sign
 *   SignerCert - pointer to certificate used in signing
 *   SignScope - pointer to the scope of fields to sign
 *   ScopeSize - number of fields in SignScope
 *
 *Returns:
 *  Null - CL unable to sign crl
 *  non Null - pointer to the signed crl
 *
 *----------------------------------------------------------------*/
CSSM_DATA_PTR CSSMAPI CSSM_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)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_DATA_PTR Data = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle, CSSM_SERVICE_CL);

	if (CallBack == NULL)
		return(NULL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CrlSign))
		Data = CallBack->CrlSign (CLHandle, CCHandle, UnsignedCrl,
		SignerCert, SignScope, ScopeSize);
	else {
		Data = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			Data = NULL;
		}
    }

    return(Data);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CrlVerify
 *
 *Description:
 *   Exported function for CL module to verify signature of crl
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   CCHandle - handle of cryptographic context
 *   SubjectCrl - pointer to crl to be verified
 *   SignerCert - pointer to certificate used in signing
 *   VerifyScope - pointer to the scope of fields to verify
 *   ScopeSize - number of fields in VeriftScope
 *
 *Returns:
 *  CSSM_FALSE - CL unable to verify signature in crl
 *  CSSM_TRUE - signature in crl is verified
 *
 *----------------------------------------------------------------*/
CSSM_BOOL CSSMAPI CSSM_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)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_BOOL ret = CSSM_FALSE;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle, CSSM_SERVICE_CL);

	if (CallBack == NULL)
		return(CSSM_FALSE);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(CSSM_FALSE);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CrlVerify))
		ret = CallBack->CrlVerify (CLHandle, CCHandle, SubjectCrl,
		SignerCert, VerifyScope, ScopeSize);
	else {
		ret = CSSM_FALSE;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			ret = CSSM_FALSE;
		}
    }

    return(ret);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_IsCertInCrl
 *
 *Description:
 *   Exported function for CL module testing whether a certificate
 *   is in the crl.
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   Cert - pointer to certificate
 *   Crl - pointer to crl
 *
 *Returns:
 *  CSSM_FALSE - certificate is not in the crl or error in execution
 *  CSSM_TRUE - certificate was found in the crl
 *
 *----------------------------------------------------------------*/
CSSM_BOOL CSSMAPI CSSM_CL_IsCertInCrl (CSSM_CL_HANDLE CLHandle,
                                       const CSSM_DATA_PTR Cert,
                                       const CSSM_DATA_PTR Crl)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_BOOL ret = CSSM_FALSE;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();


    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle, CSSM_SERVICE_CL);

	if (CallBack == NULL)
		return(CSSM_FALSE);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE)
    {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(CSSM_FALSE);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->IsCertInCrl))
		ret = CallBack->IsCertInCrl (CLHandle, Cert, Crl);
	else {
		ret = CSSM_FALSE;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if (cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			ret = CSSM_FALSE;
		}
    }
    return(ret);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CrlGetFirstFieldValue
 *
 *Description:
 *   Exported function for CL module for retreiving the first field
 *   from the crl
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   Crl - pointer to the crl
 *   CrlField - pointer to an OID of field
 *   ResultHandle - pointer to handle that describes this search
 *   NumberOfMatchedFields - pointer to the number of fields in the
 *
 *Returns:
 *  Null - CL unable to retreive data of crl
 *  non Null - pointer to the first match OID
 *
 *----------------------------------------------------------------*/
CSSM_DATA_PTR CSSMAPI CSSM_CL_CrlGetFirstFieldValue (CSSM_CL_HANDLE CLHandle,
                                               const CSSM_DATA_PTR Crl,
                                               const CSSM_OID_PTR CrlField,
                                               CSSM_HANDLE_PTR ResultsHandle,
                                               uint32 *NumberOfMatchedFields)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_DATA_PTR Data = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle, CSSM_SERVICE_CL);

	if (CallBack == NULL)
		return(NULL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CrlGetFirstFieldValue))
		Data = CallBack->CrlGetFirstFieldValue (CLHandle, Crl,
		CrlField, ResultsHandle, NumberOfMatchedFields);
	else {
		Data = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			Data = NULL;
		}
    }

    return(Data);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CrlGetNextFieldValue
 *
 *Description:
 *   Exported function for CL module to get next field in crl
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   ResultHandle - handle that describes this search
 *
 *Returns:
 *  Null - CL unable to retreive more data from crl
 *  non Null - pointer to the next match OID
 *
 *----------------------------------------------------------------*/
CSSM_DATA_PTR CSSMAPI CSSM_CL_CrlGetNextFieldValue (CSSM_CL_HANDLE CLHandle,
                                                    CSSM_HANDLE ResultsHandle)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_DATA_PTR Data = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle, CSSM_SERVICE_CL);

	if (CallBack == NULL)
		return(NULL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CrlGetNextFieldValue))
		Data = CallBack->CrlGetNextFieldValue (CLHandle, ResultsHandle);
	else {
		Data = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			Data = NULL;
		}
    }

    return(Data);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CrlAbortQuery
 *
 *Description:
 *   Exported function for CL module to terminate search in crl
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   ResultHandle - handle that describes this search
 *
 *Returns:
 *  CSSM_FAIL - CL unable to terminate search
 *  CSSM_OK - search has been terminated
 *
 *----------------------------------------------------------------*/
CSSM_RETURN CSSMAPI CSSM_CL_CrlAbortQuery (CSSM_CL_HANDLE CLHandle,
                                           CSSM_HANDLE ResultsHandle)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_RETURN ret = CSSM_FAIL;
    CSSM_MUTEX retMutex;


    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle, CSSM_SERVICE_CL);

	if (CallBack == NULL)
		return(CSSM_FAIL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            ret = CSSM_FAIL;
			goto exit;
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CrlAbortQuery))
		ret = CallBack->CrlAbortQuery (CLHandle, ResultsHandle);
	else {
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
		ret = CSSM_FAIL;
	}

exit:
    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			ret = CSSM_FAIL;
		}
    }

    return(ret);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_CrlDescribeFormat
 *
 *Description:
 *   Exported function for CL module to desribe its native crl format
 *
 *Parameters:
 *   CLHandle - handle of CL module
 *   NumberOfFields - pointer to the number of oids in the
 *             returning oid pointer
 *
 *Returns:
 *  Null - CL unable to describe its format
 *  non Null - pointer to oids that describes the native crl
 *             format
 *
 *----------------------------------------------------------------*/
CSSM_OID_PTR CSSMAPI CSSM_CL_CrlDescribeFormat (CSSM_CL_HANDLE CLHandle,
                                                uint32 *NumberOfFields)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    CSSM_OID_PTR oid = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle, CSSM_SERVICE_CL);

	if (CallBack == NULL) 
		return(NULL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->CrlDescribeFormat))
		oid = CallBack->CrlDescribeFormat (CLHandle, NumberOfFields);
	else {
		oid = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			oid = NULL;
		}
    }

    return(oid);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CL_PassThrough
 *
 *Description:
 *   Exported function for CL module passing private functions
 *
 *Parameters:
 *   CLHandle - CL handle
 *   CCHandle - CC handle
 *   PassThroughId - identifier suupiled by the TP module
 *   InputParams - data associated with pass through function
 *
 *Returns:
 *  NULL - unable to complete pass through call
 *  non NULL - result from pass through call
 *
 *----------------------------------------------------------------*/
void * CSSMAPI CSSM_CL_PassThrough (CSSM_CL_HANDLE CLHandle,
                                           CSSM_CC_HANDLE CCHandle,
                                           uint32 PassThroughId,
                                           const void * InputParams)
{
    CSSM_SPI_CL_FUNCS_PTR CallBack = NULL;
    void * Data = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_CL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(CLHandle,CSSM_SERVICE_CL);

	if (CallBack == NULL)
		return(NULL);

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->PassThrough))
		Data = CallBack->PassThrough (CLHandle, CCHandle, PassThroughId,
		InputParams);
	else {
		Data = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
	}

    if(cssm_CheckThreadSafe (CLHandle, CSSM_SERVICE_CL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CLHandle,CSSM_SERVICE_CL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			Data = NULL;
		}
    }

    return(Data);
}
