/* SCCSID: fwk/cssm/ccapi.c, dss_cdsa_fwk, fwk_rel2, dss_971010 1.17 10/10/97 10:49:13 */
/* ***************************************************************** *
 * 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:   CCAPI.C
 *
 * This file contains the functions that are contained in the context 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 "addin.h"
#include "context.h"

/*---------------------------------------------------------------
 *
 *Name: CSSM_CSP_CreateSignatureContext
 *
 *Description:
 *   Exported function for creating a signature context
 *
 *Parameters:
 *   CSPHandle - handle to CSP providing the service
 *   AlgorithmID - identifier describing the signaturing algotithm
 *   PassPhrase - pointer to structure that defines the passphrase
 *   Key - pointer to structure that defines the public key use
 *
 *Returns:
 *  0 - CSSM unable to create context
 *  non 0 - handle for the created context
 *
 *----------------------------------------------------------------*/
CSSM_CC_HANDLE CSSMAPI CSSM_CSP_CreateSignatureContext(
	CSSM_CSP_HANDLE CSPHandle,
    uint32 AlgorithmID,
    const CSSM_CRYPTO_DATA_PTR PassPhrase,
    const CSSM_KEY_PTR Key)
{
    CSSM_CONTEXT_PTR           Context = NULL;
    CSSM_CONTEXT_ATTRIBUTE_PTR Attribute = NULL;
    uint32                     NumberAttributes = 0;
    CSSM_CC_HANDLE             CCHandle = 0, rc;

	/* clear the error */
    CSSM_ClearError ();

	/* malloc the context */
    if ((Context = cssm_CreateContext (CSSM_ALGCLASS_SIGNATURE, AlgorithmID)) == NULL) {
        goto exit;
    }

	/* count context attributes */
    if (!cssm_IsBadCryptoDataPtr (PassPhrase))
        NumberAttributes++;

    if (!cssm_IsBadCryptoKeyPtr (Key))
        NumberAttributes++;

	NumberAttributes++; /* for CspHandle */

    Context->NumberOfAttributes = NumberAttributes;
	if (cssm_CreateAttribute (&Context->ContextAttributes, NumberAttributes) == CSSM_FAIL) {
        goto exit;
    }

    Attribute = Context->ContextAttributes;
    NumberAttributes--;

	/* set up attribures */
	if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_CSP_HANDLE, (void *) CSPHandle) == CSSM_FAIL) {
            cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
            goto exit;
    }

    if (!cssm_IsBadCryptoDataPtr (PassPhrase))
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_PASSPHRASE, (void *)PassPhrase) == CSSM_FAIL) {
            cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
            goto exit;
        }

    if (!cssm_IsBadCryptoKeyPtr (Key))
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_KEY, (void *)Key) == CSSM_FAIL) {
            cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
            goto exit;
        }

	/* store context in hash table */
	/* on error the Context is freed by calee */
	rc = cssm_InsertContext(Context, CSPHandle);
	return(rc);

exit:
	if (Context != NULL) {
		cssm_free (Context, 0);
	}
	return(0);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CSP_CreateSymmetricContext
 *
 *Description:
 *   Exported function for creating a symmetric encryption context
 *
 *Parameters:
 *   CSPHandle - handle to CSP providing the service
 *   AlgorithmID - identifier describing the symmetric encryption
 *   Mode - type of encryption mode ie. CBC, CBCIV8
 *   Key - pointer to data describing the key to use
 *   InitVector - pointer to data describing an initialization vector
 *   Padding - pointer to data describing padding information
 *   Loops - number of runs to encrypt (RC5 options)
 *
 *Returns:
 *  0 - CSSM unable to create context
 *  non 0 - handle for the created context
 *
 *----------------------------------------------------------------*/
CSSM_CC_HANDLE CSSMAPI CSSM_CSP_CreateSymmetricContext(
	CSSM_CSP_HANDLE CSPHandle,
    uint32 AlgorithmID,
    uint32 Mode,
    const CSSM_KEY_PTR Key,
    const CSSM_DATA_PTR InitVector,
    uint32 Padding,
    uint32 Loops)
{
    CSSM_CONTEXT_PTR           Context = NULL;
    CSSM_CONTEXT_ATTRIBUTE_PTR Attribute = NULL;
    uint32                     NumberAttributes = 0;
    CSSM_CC_HANDLE             CCHandle = 0;
	CSSM_BOOL				   contextCreateFailed=CSSM_FALSE;

    CSSM_ClearError ();

	/* malloc the context */
    if ((Context = cssm_CreateContext (CSSM_ALGCLASS_SYMMETRIC, AlgorithmID)) == NULL) {
        goto exit;
    }

	/* count number of attributes */
    /* for loops & Mode*/
    NumberAttributes+= 2;

    if (!cssm_IsBadCryptoKeyPtr (Key))
        NumberAttributes++;

    if (!cssm_IsBadReadPtr (InitVector, sizeof (CSSM_DATA)))
        NumberAttributes++;

    /* for padding info */
    NumberAttributes++;

    /* for CSP Handle */
	NumberAttributes++;

    Context->NumberOfAttributes = NumberAttributes;

	/* setup context attributes */
    if (cssm_CreateAttribute (&Context->ContextAttributes, Context->NumberOfAttributes) == CSSM_FAIL) {
		contextCreateFailed = CSSM_TRUE;
        goto exit;
    }

    Attribute = Context->ContextAttributes;
    NumberAttributes--;

	if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_CSP_HANDLE, (void *) CSPHandle) == CSSM_FAIL) {
		contextCreateFailed = CSSM_TRUE;
        goto exit;
    }

    if (!cssm_IsBadCryptoKeyPtr (Key))
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_KEY, (void *)Key) == CSSM_FAIL) {
			contextCreateFailed = CSSM_TRUE;
            goto exit;
        }

    if (!cssm_IsBadReadPtr (InitVector, sizeof (CSSM_DATA)))
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_INIT_VECTOR, (void *)InitVector) == CSSM_FAIL) {
    		contextCreateFailed = CSSM_TRUE;
	        goto exit;
        }

    if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_PADDING, (void *)Padding) == CSSM_FAIL) {
    	contextCreateFailed = CSSM_TRUE;
	    goto exit;
    }

    /* check for rounds or effective bits */
    if (AlgorithmID == CSSM_ALGID_RC5) {
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_ROUNDS, (void *)Loops) == CSSM_FAIL) {
    		contextCreateFailed = CSSM_TRUE;
	        goto exit;
        }
    } else {
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_EFFECTIVE_BITS, (void *)Loops) == CSSM_FAIL) {
    		contextCreateFailed = CSSM_TRUE;
	        goto exit;
        }
    }

    if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_MODE, (void *)Mode) == CSSM_FAIL) {
		contextCreateFailed = CSSM_TRUE;
        goto exit;
    }

    CCHandle = cssm_InsertContext (Context, CSPHandle);

	/* Context error free done by InsertContext */

exit:
	if (contextCreateFailed) {
        cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
 		cssm_free (Context, 0);
	}

    return(CCHandle);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CSP_CreateDigestContext
 *
 *Description:
 *   Exported function for creating a digest context
 *
 *Parameters:
 *   CSPHandle - handle to CSP providing the service
 *   AlgorithmID - identifier describing the digest algorithm
 *
 *Returns:
 *  0 - CSSM unable to create context
 *  non 0 - handle for the created context
 *
 *----------------------------------------------------------------*/
CSSM_CC_HANDLE CSSMAPI CSSM_CSP_CreateDigestContext(
	CSSM_CSP_HANDLE CSPHandle,
    uint32 AlgorithmID)
{
    CSSM_CONTEXT_ATTRIBUTE_PTR	Attribute = NULL;
    CSSM_CONTEXT_PTR			Context = NULL;
	CSSM_CC_HANDLE				rc;

	/* clear the error */
    CSSM_ClearError ();

	/* malloc the context */
    if ((Context = cssm_CreateContext (CSSM_ALGCLASS_DIGEST, AlgorithmID)) == NULL) {
        return(0);
    }

	Context->NumberOfAttributes =1; /* CSP Handle attribute */

	if (cssm_CreateAttribute (&Context->ContextAttributes, Context->NumberOfAttributes) == CSSM_FAIL) {
        goto exit;
    }

    Attribute = Context->ContextAttributes;

	if (cssm_AddAttribute (&Attribute[0], CSSM_ATTRIBUTE_CSP_HANDLE, (void *) CSPHandle) == CSSM_FAIL) {
            cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
            goto exit;
    }

	/* free on error is done by callee */
    rc = cssm_InsertContext (Context, CSPHandle);
	return(rc);

exit:
	if (Context != NULL) {
		cssm_free (Context, 0);
	}

	return(0);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CSP_CreateMacContext
 *
 *Description:
 *   Exported function for creating a MAC context
 *
 *Parameters:
 *   CSPHandle - handle to CSP providing the service
 *   AlgorithmID - identifier describing the MAC algorithm
 *   Key - Key for the mac
 *
 *Returns:
 *  0 - CSSM unable to create context
 *  non 0 - handle for the created context
 *
 *----------------------------------------------------------------*/
CSSM_CC_HANDLE CSSMAPI CSSM_CSP_CreateMacContext(
	CSSM_CSP_HANDLE CSPHandle,
    uint32 AlgorithmID,
    const CSSM_KEY_PTR Key)
{
    CSSM_CONTEXT_PTR			Context = NULL;
    CSSM_CONTEXT_ATTRIBUTE_PTR	Attribute = NULL;
	CSSM_CC_HANDLE				CCHandle = 0;
    uint32						NumberAttributes = 0;
	CSSM_CC_HANDLE				rc;

	/* clear the error */
    CSSM_ClearError ();

	/* malloc the context */
    if ((Context = cssm_CreateContext (CSSM_ALGCLASS_MAC, AlgorithmID)) == NULL) {
        goto exit;
    }

	/* count attributes */
    if (!cssm_IsBadCryptoKeyPtr (Key))
	    NumberAttributes++;

	NumberAttributes++; /* for CSP Handle */

    Context->NumberOfAttributes = NumberAttributes;
    if (cssm_CreateAttribute (&Context->ContextAttributes, NumberAttributes) == CSSM_FAIL) {
        goto exit;
    }

    Attribute = Context->ContextAttributes;
    NumberAttributes--;
    if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_CSP_HANDLE, (void *)CSPHandle) == CSSM_FAIL) {
        cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
        goto exit;
    }

    if (!cssm_IsBadCryptoKeyPtr (Key))
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_KEY, (void *)Key) == CSSM_FAIL) {
            cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
            goto exit;
        }

	/* free on error is done by callee */
	rc = cssm_InsertContext (Context, CSPHandle);
	return(rc);

exit:
	if (Context != NULL) {
		cssm_free (Context, 0);
	}

    return(0);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CSP_CreateRandomGenContext
 *
 *Description:
 *   Exported function for creating a generate random context
 *
 *Parameters:
 *   CSPHandle - handle to CSP providing the service
 *   AlgorithmID - identifier describing the generate random algorithm
 *   Seed - pointer to data describing a seed to the random generator
 *   Length - Number of bytes of random data to generate
 *
 *Returns:
 *  0 - CSSM unable to create context
 *  non 0 - handle for the created context
 *
 *----------------------------------------------------------------*/
CSSM_CC_HANDLE CSSMAPI CSSM_CSP_CreateRandomGenContext(
	CSSM_CSP_HANDLE CSPHandle,
    uint32 AlgorithmID,
    const CSSM_CRYPTO_DATA_PTR Seed,
    uint32 Length)
{
    CSSM_CONTEXT_PTR			Context = NULL;
    CSSM_CONTEXT_ATTRIBUTE_PTR	Attribute = NULL;
    uint32						NumberAttributes = 0;
	CSSM_CC_HANDLE				rc;

	/* clear the error */
    CSSM_ClearError ();

	/* malloc the context */
    if ((Context = cssm_CreateContext (CSSM_ALGCLASS_RANDOMGEN, AlgorithmID)) == NULL) {
        return(0);
    }

    if (!cssm_IsBadCryptoDataPtr (Seed))
        NumberAttributes++;

	/* count attributes */
    /* for length attribute */
    NumberAttributes++;

	/* for CSPHandle */
	NumberAttributes++;

    Context->NumberOfAttributes = NumberAttributes;
    if (cssm_CreateAttribute (&Context->ContextAttributes, NumberAttributes) == CSSM_FAIL) {
        goto exit;
    }

    Attribute = Context->ContextAttributes;
    NumberAttributes--;

    if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_CSP_HANDLE, (void *)CSPHandle) == CSSM_FAIL) {
        cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
        goto exit;
    }

    if (!cssm_IsBadCryptoDataPtr (Seed))
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_SEED, (void *)Seed) == CSSM_FAIL) {
            cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
            goto exit;
        }

    if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_OUTPUT_SIZE, (void *)Length) == CSSM_FAIL) {
        cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
        goto exit;
    }

	/* free on error is done by callee */
    rc = cssm_InsertContext (Context, CSPHandle);
	return(rc);

exit:
	if (Context != NULL) {
		cssm_free (Context, 0);
	}

	return(0);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CSP_CreateUniqueIdContext
 *
 *Description:
 *   Exported function for creating a generate unique ID context
 *
 *Parameters:
 *   CSPHandle - handle to CSP providing the service
 *   AlgorithmID - identifier describing the generate ID algorithm
 *   Seed - pointer to data describing a seed to the ID generator
 *   Length - Number of bytes of ID to generate
 *
 *Returns:
 *  0 - CSSM unable to create context
 *  non 0 - handle for the created context
 *
 *----------------------------------------------------------------*/
CSSM_CC_HANDLE CSSMAPI CSSM_CSP_CreateUniqueIdContext(
	CSSM_CSP_HANDLE CSPHandle,
    uint32 AlgorithmID,
    const CSSM_CRYPTO_DATA_PTR Seed,
    uint32 Length)
{
    CSSM_CONTEXT_PTR			Context = NULL;
    CSSM_CONTEXT_ATTRIBUTE_PTR	Attribute = NULL;
    uint32						NumberAttributes = 0;
	CSSM_CC_HANDLE				rc;

	/* clear the error */
    CSSM_ClearError ();

	/* malloc the context */
    if ((Context = cssm_CreateContext (CSSM_ALGCLASS_UNIQUEGEN, AlgorithmID)) == NULL) {
        goto exit;
    }

	/* count attributes */
    if (!cssm_IsBadCryptoDataPtr (Seed))
        NumberAttributes++;

    /* for length attribute */
    NumberAttributes++;

	/* for CSP Handle */
    NumberAttributes++;

    Context->NumberOfAttributes = NumberAttributes;
    if (cssm_CreateAttribute (&Context->ContextAttributes, NumberAttributes) == CSSM_FAIL) {
        goto exit;
    }

    Attribute = Context->ContextAttributes;
    NumberAttributes--;

    if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_CSP_HANDLE, (void *)CSPHandle) == CSSM_FAIL) {
        cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
        goto exit;
    }

    if (!cssm_IsBadCryptoDataPtr (Seed))
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_SEED, (void *)Seed) == CSSM_FAIL) {
            cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
            goto exit;
        }

    if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_OUTPUT_SIZE, (void *)Length) == CSSM_FAIL) {
        cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
        goto exit;
    }

	/* free on error is done by callee */
    rc = cssm_InsertContext (Context, CSPHandle);
	return(rc);

exit:
	if (Context != NULL) {
		cssm_free (Context, 0);
	}

	return(0);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CSP_AsymmetricContext
 *
 *Description:
 *   Exported function for creating an asymmetric encryption context
 *
 *Parameters:
 *   CSPHandle - handle to CSP providing the service
 *   AlgorithmID - identifier describing the symmetric encryption
 *   PassPhrase - pointer to data describing the pass phrase
 *   Key - pointer to data describing the key to use
 *   Padding - pointer to data describing padding information
 *   KeyMode - indicate whether to use public or private key
 *
 *Returns:
 *  0 - CSSM unable to create context
 *  non 0 - handle for the created context
 *
 *----------------------------------------------------------------*/
CSSM_CC_HANDLE CSSMAPI CSSM_CSP_CreateAsymmetricContext(
	CSSM_CSP_HANDLE CSPHandle,
    uint32 AlgorithmID,
    const CSSM_CRYPTO_DATA_PTR PassPhrase,
    const CSSM_KEY_PTR Key,
    uint32 Padding)
{
    CSSM_CONTEXT_PTR           Context = NULL;
    CSSM_CONTEXT_ATTRIBUTE_PTR Attribute = NULL;
	CSSM_CC_HANDLE             CCHandle = 0;
    uint32                     NumberAttributes = 0;
    CSSM_BOOL				   contextCreateFailed = CSSM_FALSE;

	/* clear the error */
    CSSM_ClearError ();

	/* malloc the context */
    if ((Context = cssm_CreateContext (CSSM_ALGCLASS_ASYMMETRIC, AlgorithmID)) == NULL) {
		goto exit;
	}

	/* count attributes */
    if (!cssm_IsBadCryptoDataPtr (PassPhrase))
        NumberAttributes++;

    if (!cssm_IsBadCryptoKeyPtr (Key))
        NumberAttributes++;

    if (Padding != CSSM_PADDING_NONE)
        NumberAttributes++;

	NumberAttributes++; /* for CSPHandle */

    Context->NumberOfAttributes = NumberAttributes;
    if (cssm_CreateAttribute (&Context->ContextAttributes, NumberAttributes) == CSSM_FAIL) {
		contextCreateFailed = CSSM_TRUE;
		goto exit;
    }

    Attribute = Context->ContextAttributes;
    NumberAttributes--;

    if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_CSP_HANDLE, (void *)CSPHandle) == CSSM_FAIL) {
		contextCreateFailed = CSSM_TRUE;
        goto exit;
    }

    if (!cssm_IsBadCryptoKeyPtr (Key))
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_KEY, (void *)Key) == CSSM_FAIL) {
			contextCreateFailed = CSSM_TRUE;
			goto exit;
        }

    if (!cssm_IsBadCryptoDataPtr (PassPhrase))
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_PASSPHRASE, (void *)PassPhrase) == CSSM_FAIL) {
			contextCreateFailed = CSSM_TRUE;
			goto exit;
        }

    if (Padding != CSSM_PADDING_NONE)
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_PADDING, (void *)Padding) == CSSM_FAIL) {
			contextCreateFailed = CSSM_TRUE;
			goto exit;
        }

	/* free on error is done by callee */
    CCHandle = cssm_InsertContext (Context, CSPHandle);

exit:
	if(contextCreateFailed) {
	    cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
		cssm_free(Context, NULL);
	}

    return(CCHandle);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CSP_CreateKeyGenContext
 *
 *Description:
 *   Exported function for creating a generate key context
 *
 *Parameters:
 *   CSPHandle - handle to CSP providing the service
 *   AlgorithmID - identifier describing the symmetric encryption
 *   ModulusSize - used to describe the modulus size for public/private keys
 *   KeySizeInBits - used to describe the size of symmetric key
 *   PassPhrase - pointer to data describing the pass phrase
 *   Seed - pointer to data describing seeding information
 *   Salt - pointer to data describing a salt
 *
 *Returns:
 *  0 - CSSM unable to create context
 *  non 0 - handle for the created context
 *
 *----------------------------------------------------------------*/
CSSM_CC_HANDLE CSSMAPI CSSM_CSP_CreateKeyGenContext(
	CSSM_CSP_HANDLE CSPHandle,
    uint32 AlgorithmID,
    const CSSM_CRYPTO_DATA_PTR PassPhrase,
    uint32 KeySizeInBits,
    const CSSM_CRYPTO_DATA_PTR Seed,
    const CSSM_DATA_PTR Salt,
    const CSSM_DATE_PTR StartDate,
    const CSSM_DATE_PTR EndDate,
    const CSSM_DATA_PTR Params)
{
    CSSM_CONTEXT_PTR           Context = NULL;
    CSSM_CONTEXT_ATTRIBUTE_PTR Attribute = NULL;
    uint32                     NumberAttributes = 0;
	CSSM_CC_HANDLE				rc;

	/* clear the error */
    CSSM_ClearError ();

	/* malloc the context */
    if ((Context = cssm_CreateContext (CSSM_ALGCLASS_KEYGEN, AlgorithmID)) == NULL) {
        goto exit;
    }

	/* count attributes */
    if (!cssm_IsBadCryptoDataPtr (PassPhrase))
        NumberAttributes++;

    if (!cssm_IsBadCryptoDataPtr (Seed))
        NumberAttributes++;

    if (!cssm_IsBadReadPtr (Salt, sizeof (CSSM_DATA)))
        NumberAttributes++;

    if (!cssm_IsBadReadPtr (StartDate, sizeof (CSSM_DATE)))
        NumberAttributes++;

    if (!cssm_IsBadReadPtr (EndDate, sizeof (CSSM_DATE)))
        NumberAttributes++;

    if (!cssm_IsBadReadPtr (Params, sizeof (CSSM_DATA)))
        NumberAttributes++;

    /* for key size, keyattribute, keyusage */
    NumberAttributes++;

	/* CSP handle */
	NumberAttributes++;

    Context->NumberOfAttributes = NumberAttributes;
    if (cssm_CreateAttribute (&Context->ContextAttributes, NumberAttributes) == CSSM_FAIL) {
        goto exit;
    }

    Attribute = Context->ContextAttributes;
    NumberAttributes--;

    if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_CSP_HANDLE, (void *)CSPHandle) == CSSM_FAIL) {
        cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
        goto exit;
    }

    if (!cssm_IsBadCryptoDataPtr (PassPhrase))
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_PASSPHRASE, (void *)PassPhrase) == CSSM_FAIL) {
            cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
            goto exit;
        }

    if (!cssm_IsBadCryptoDataPtr (Seed))
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_SEED, (void *)Seed) == CSSM_FAIL) {
            cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
            goto exit;
        }

    if (!cssm_IsBadReadPtr (Salt, sizeof (CSSM_DATA)))
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_SALT, (void *)Salt) == CSSM_FAIL) {
            cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
            goto exit;
        }

    if (!cssm_IsBadReadPtr (StartDate, sizeof (CSSM_DATE)))
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_START_DATE, (void *)StartDate) == CSSM_FAIL) {
            cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
            goto exit;
        }

    if (!cssm_IsBadReadPtr (EndDate, sizeof (CSSM_DATE)))
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_END_DATE, (void *)EndDate) == CSSM_FAIL) {
            cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
            goto exit;
        }

    if (!cssm_IsBadReadPtr (Params, sizeof (CSSM_DATA)))
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_ALG_PARAMS, (void *)Params) == CSSM_FAIL) {
            cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
            goto exit;
        }


    if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_KEY_LENGTH, (void *)KeySizeInBits) == CSSM_FAIL) {
        cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
        goto exit;
    }

	/* free on error is done by callee */
    rc = cssm_InsertContext (Context, CSPHandle);
	return(rc);

exit:
	if (Context != NULL) {
		cssm_free (Context, 0);
	}

    return(0);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CSP_CreateDeriveKeyContext
 *
 *Description:
 *   Exported function for creating a derive key context
 *
 *Parameters:
 *   CSPHandle - handle to CSP providing the service
 *   AlgorithmID - identifier describing the derive method
 *   DeriveKeyType - identifier describing the derived key type
 *   DeriveKeyLength - used to describe the size of derived key
 *   InterationCount - Number of repetitions used in the derive
 *   Seed - pointer to data describing seeding information
 *   PassPhrase - passphrase used to encrypt the derived key if
 *                    it is stored in private memory.
 *
 *Returns:
 *  0 - CSSM unable to create context
 *  non 0 - handle for the created context
 *
 *----------------------------------------------------------------*/
CSSM_CC_HANDLE CSSMAPI CSSM_CSP_CreateDeriveKeyContext(
	CSSM_CSP_HANDLE CSPHandle,
    uint32 AlgorithmID,
    CSSM_KEY_TYPE DeriveKeyType,
    uint32 DeriveKeyLength,
    uint32 IterationCount,
    const CSSM_DATA_PTR Salt,
    const CSSM_CRYPTO_DATA_PTR Seed,
    const CSSM_CRYPTO_DATA_PTR PassPhrase)
{
    CSSM_CONTEXT_PTR           Context = NULL;
    CSSM_CONTEXT_ATTRIBUTE_PTR Attribute = NULL;
    uint32                     NumberAttributes = 0;
	CSSM_CC_HANDLE				rc;

	/* clear the error */
    CSSM_ClearError ();

	/* malloc the context */
    if ((Context = cssm_CreateContext (CSSM_ALGCLASS_DERIVEKEY, AlgorithmID)) == NULL) {
        goto exit;
    }

	/* cont attributes */
    if (!cssm_IsBadCryptoDataPtr (PassPhrase))
        NumberAttributes++;

    if (!cssm_IsBadCryptoDataPtr (Seed))
        NumberAttributes++;

    if (IterationCount > 0)
        NumberAttributes++;

    /* for key size, and type, CSPHandle */
    NumberAttributes += 3;

    Context->NumberOfAttributes = NumberAttributes;
    if (cssm_CreateAttribute (&Context->ContextAttributes, NumberAttributes) == CSSM_FAIL) {
        goto exit;
    }

    Attribute = Context->ContextAttributes;
    NumberAttributes--;

    if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_CSP_HANDLE, (void *)CSPHandle) == CSSM_FAIL) {
        cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
        goto exit;
    }

    if (!cssm_IsBadCryptoDataPtr (PassPhrase))
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_PASSPHRASE, (void *)PassPhrase) == CSSM_FAIL) {
            cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
            goto exit;
        }

    if (!cssm_IsBadCryptoDataPtr (Seed))
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_SEED, (void *)Seed) == CSSM_FAIL) {
            cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
            goto exit;
        }

    if (IterationCount) {
        if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_ROUNDS, (void *)IterationCount) == CSSM_FAIL) {
            cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
            goto exit;
        }
    }

    if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_KEY_TYPE, (void *)DeriveKeyType) == CSSM_FAIL) {
        cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
        goto exit;
    }

    if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_KEY_LENGTH, (void *)DeriveKeyLength) == CSSM_FAIL) {
        cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
        goto exit;
    }

	/* free on error is done by callee */
    rc = cssm_InsertContext (Context, CSPHandle);
	return(rc);

exit:
	if (Context != NULL) {
		cssm_free (Context, 0);
	}

    return(0);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_CSP_CreatePassThroughContext
 *
 *Description:
 *   Exported function for creating a pass through context
 *
 *Parameters:
 *   CSPHandle - handle to CSP providing the service
 *   Key - pointer to data describing the key to use
 *   ParamBuf - array of pointer to data for pass through context
 *   ParamBufCount - number of entries in ParamBuf
 *
 *Returns:
 *  0 - CSSM unable to create context
 *  non 0 - handle for the created context
 *
 *----------------------------------------------------------------*/
CSSM_CC_HANDLE CSSMAPI CSSM_CSP_CreatePassThroughContext(
	CSSM_CSP_HANDLE CSPHandle,
    const CSSM_KEY_PTR Key,
    const CSSM_DATA_PTR ParamBufs,
    uint32 ParamBufCount)

{
    CSSM_CONTEXT_ATTRIBUTE_PTR Attribute = NULL;
    CSSM_CONTEXT_PTR           Context = NULL;
    uint32 NumberAttributes =0;
    uint32 Count = 0;
    uint32 i;
	CSSM_CC_HANDLE				rc;

	/* clear the error */
    CSSM_ClearError ();

	/* malloc the context */
    if ((Context = cssm_CreateContext (CSSM_ALGCLASS_CUSTOM, CSSM_ALGID_NONE)) == NULL) {
        goto exit;
    }

	/* count attributes */
    if (!cssm_IsBadReadPtr (Key, sizeof (CSSM_KEY)))
        NumberAttributes++;

    if (!cssm_IsBadReadPtr (ParamBufs, sizeof (CSSM_DATA)))
        NumberAttributes += ParamBufCount;

    /* for CSP handle */
    NumberAttributes++;

    Context->NumberOfAttributes = NumberAttributes;
    if (cssm_CreateAttribute (&Context->ContextAttributes, NumberAttributes) == CSSM_FAIL) {
        goto exit;
    }

    Attribute = Context->ContextAttributes;
    NumberAttributes--;

    if (cssm_AddAttribute (&Attribute[NumberAttributes--], CSSM_ATTRIBUTE_CSP_HANDLE, (void *)CSPHandle) == CSSM_FAIL) {
        cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
        goto exit;
    }

    if (!cssm_IsBadReadPtr (Key, sizeof (CSSM_KEY))) {
        if (cssm_AddAttribute (&Attribute[Count++], CSSM_ATTRIBUTE_KEY, (void *)Key) == CSSM_FAIL) {
            cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
            goto exit;
        }
    }

    for (i=0; i<ParamBufCount; i++) {
        if (!cssm_IsBadReadPtr (&ParamBufs[i], sizeof (CSSM_DATA))) {
            if (cssm_AddAttribute (&Attribute[Count++], CSSM_ATTRIBUTE_CUSTOM, (void *)&ParamBufs[i]) == CSSM_FAIL) {
                cssm_FreeAttributes (Context->NumberOfAttributes, Attribute, (CSSM_FREE)cssm_free, 0, 1);
                goto exit;
            }
        }
    }

	/* context free on error is done by callee */
    rc = cssm_InsertContext (Context, CSPHandle);
	return(rc);

exit:
	if (Context != NULL) {
		cssm_free (Context, 0);
	}

    return(0);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_GetContext
 *
 *Description:
 *   Exported function for retreiving the context structure given
 *   a handle to the context.
 *
 *Parameters:
 *   CCHandle - handle to a created context
 *
 *Returns:
 *  NULL - unable to retreive context information
 *  non NULL - pointer to structure that describes the context
 *
 *----------------------------------------------------------------*/
CSSM_CONTEXT_PTR
CSSMAPI CSSM_GetContext (CSSM_CC_HANDLE CCHandle)
{
	cssm_INTERNALCONTEXT_PTR	TempContext = NULL;
	CSSM_CONTEXT_PTR			Duplicate = NULL;
	int							bucket = 0;

    CSSM_ClearError ();

	if ((TempContext = cssm_LookupAndLockBucket(CCHandle, &bucket)) == NULL) {
		// cssm error is set
		return(NULL);
	}

	// return 0 on error
	Duplicate = cssm_DuplicateContext(TempContext->Context, app_calloc, app_free, memRef);

	if (cssm_UnlockBucket(bucket) != CSSM_OK) {
		// cssm error is set
		CSSM_FreeContext(Duplicate);
		Duplicate = NULL;
	}

	return(Duplicate);;
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_SetContext
 *
 *Description:
 *   Exported function for setting a context.  Given a context handle,
 *   set the handle to point to the new context information.  Does not
 *	 call cssm_KR_ApplyPolicy because cssm_AssignContext does that.
 *
 *Parameters:
 *   CCHandle - handle to a created context
 *   Context - pointer to new context information
 *
 *Returns:
 *  CSSM_FAIL - unable to set the context
 *  CSSM_OK - new context information associated with handle
 *
 *----------------------------------------------------------------*/
CSSM_RETURN CSSMAPI CSSM_SetContext (CSSM_CC_HANDLE CCHandle,
                                     const CSSM_CONTEXT_PTR Context)
{
	CSSM_RETURN				rc;
	CSSM_CONTEXT_PTR		newContext, oldContext;

    /* clear the error */
    CSSM_ClearError ();

	/* perform sanity check on the supplied context before
	   attempting update
	*/
	if (cssm_IsBadReadPtr(Context, sizeof(*Context)) ) {
		CSSM_SetError (&cssm_GUID, CSSM_INVALID_POINTER);
        return(CSSM_FAIL);
    }

	/* save the old context */
	oldContext = CSSM_GetContext(CCHandle);
	if (oldContext == NULL) {
		/* error code is set in CSSM_GetContext */
		return(CSSM_FAIL);
	}

	/* make a copy to put on the queue */
	newContext = cssm_DuplicateContext(Context, cssm_calloc, cssm_free, 0);
	if (newContext==NULL) {
		return(CSSM_FAIL);;
	}

	rc = cssm_UpdateContextPtr(CCHandle, newContext);
	if (rc != CSSM_OK) {
		/* error code is set in the UpdateContextPtr function */
		return(CSSM_FAIL);
	}

	/* if we get here it means things went ok, so free the old backup */
	CSSM_FreeContext(oldContext);

	return(rc);

}

/*---------------------------------------------------------------
 *
 *Name: CSSM_DeleteContext
 *
 *Description:
 *   Exported function for deleting the internal respresentation of
 *   the context
 *
 *Parameters:
 *   CCHandle - handle to a created context
 *
 *Returns:
 *  CSSM_FAIL - unable to delete data poin	ted to by handle
 *  CSSM_OK - context is deleted
 *
 *----------------------------------------------------------------*/
CSSM_RETURN CSSMAPI CSSM_DeleteContext (CSSM_CC_HANDLE CCHandle)
{
	CSSM_RETURN				rc;

    CSSM_ClearError ();

	// do the work
	rc = cssm_RemoveCONTEXT(CCHandle);
	return(rc);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_GetContextAttribute
 *
 *Description:
 *   Exported function for retreiving an attribute from the context
 *
 *Parameters:
 *   Context - pointer to context information
 *   AttributeType - identifier for the interested attribute type
 *
 *Returns:
 *  NULL - Unable to find attribute in context data
 *  non NULL - pointer to attribute
 *
 *Note :
 *  return pointer is an offset to the context data.  Do not free
 *  this pointer.
 *----------------------------------------------------------------*/
CSSM_CONTEXT_ATTRIBUTE_PTR CSSMAPI CSSM_GetContextAttribute(
	const CSSM_CONTEXT_PTR Context,
    uint32 AttributeType)
{
    uint32 i;

    /* clear the error */

    CSSM_ClearError ();

    if (cssm_IsBadReadPtr (Context, sizeof (CSSM_CONTEXT))) {
        CSSM_SetError (&cssm_GUID, CSSM_INVALID_POINTER);
        return(NULL);
    }

    for (i=0; i<Context->NumberOfAttributes; i++)
        if (Context->ContextAttributes[i].AttributeType == AttributeType)
            return(&Context->ContextAttributes[i]);

    CSSM_SetError (&cssm_GUID, CSSM_INVALID_ATTRIBUTE);
    return(NULL);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_FreeContext
 *
 *Description:
 *   Exported function for free the context data.  This function
 *   walks the context structure to free all the memory.
 *
 *Parameters:
 *   Context - pointer to context information
 *
 *Returns:
 *  CSSM_FAIL - unable to free context data
 *  CSSM_OK - context data is freed
 *
 *----------------------------------------------------------------*/
CSSM_RETURN CSSMAPI CSSM_FreeContext (CSSM_CONTEXT_PTR Context)
{
    uint32 NumberAttributes;
    CSSM_CONTEXT_ATTRIBUTE_PTR ContextAttributes;

    /* clear the error */

    CSSM_ClearError ();

    /* make sure that pointer is good */
    if (cssm_IsBadReadPtr (Context, sizeof (CSSM_CONTEXT))) {
        CSSM_SetError (&cssm_GUID, CSSM_INVALID_POINTER);
        return(CSSM_FAIL);
    }

    NumberAttributes = Context->NumberOfAttributes;
    ContextAttributes = Context->ContextAttributes;

    /* make sure that pointer is good */
    if (ContextAttributes != NULL)
        if (cssm_IsBadReadPtr (ContextAttributes, sizeof (CSSM_CONTEXT_ATTRIBUTE) * NumberAttributes)) {
            CSSM_SetError (&cssm_GUID, CSSM_INVALID_POINTER);
            return(CSSM_FAIL);
        }

    cssm_FreeContext (Context);
    return(CSSM_OK);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_UpdateContextAttribute
 *
 *Description:
 *   Exported function updates an attribute in the context handle.
 *	 Before returning, passes the context along to cssm_KR_ApplyPolicy
 *	 because the key size may have changed.
 *
 *Parameters:
 *   CCHandle - handle to context data
 *   NumberOfAttributes - number of attributes to update
 *   ContextAttributes - pointer to data that describes new attributes
 *
 *Returns:
 *  CSSM_FAIL - CSSM unable to update context
 *  CSSM_OK - context is updated
 *
 *----------------------------------------------------------------*/
CSSM_RETURN CSSMAPI CSSM_UpdateContextAttributes(
	CSSM_CC_HANDLE CCHandle,
    uint32 NumberAttributes,
    const CSSM_CONTEXT_ATTRIBUTE_PTR ContextAttributes)
{
    cssm_INTERNALCONTEXT_PTR TempContext = 0;
	CSSM_RETURN rc = CSSM_FAIL;
	int			bucket = 0;
	uint32		i;

    /* clear the error */

    CSSM_ClearError ();

    /* make sure pointer are valid */
    if (cssm_IsBadReadPtr (ContextAttributes, sizeof (CSSM_CONTEXT_ATTRIBUTE) * NumberAttributes)) {
        CSSM_SetError (&cssm_GUID, CSSM_INVALID_POINTER);
        return(CSSM_FAIL);
    }

	/* lookup and lock context bucket */
	if ((TempContext = cssm_LookupAndLockBucket(CCHandle, &bucket)) == NULL) {
		// cssm error is set
		return(CSSM_FAIL);
	}

	/* found the context */
	/* update the data */
	for (i=0; i<NumberAttributes; i++)
	{
		rc = cssm_UpdateContext (TempContext->Context, &ContextAttributes[i]);
	}

	// unlock and set cssm error
	rc = cssm_UnlockBucket(bucket);

    return(rc);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_DeleteContextAttribute
 *
 *Description:
 *   Function for deleting attributes from a context
 *
 *Parameters:
 *   CCHandle - handle to context data
 *   NumberOfAttributes - number of attributes to delete
 *   ContextAttributes - pointer to data that describes delete attributes
 *
 *Returns:
 *  0 - CSSM unable to create context
 *  non 0 - handle for the created context
 *
 *----------------------------------------------------------------*/
CSSM_RETURN CSSMAPI CSSM_DeleteContextAttributes(
	CSSM_CC_HANDLE CCHandle,
    uint32 NumberAttributes,
    const CSSM_CONTEXT_ATTRIBUTE_PTR ContextAttributes)
{
	cssm_INTERNALCONTEXT_PTR TempContext = NULL;
	CSSM_RETURN rc = CSSM_FAIL;
	uint32      i;
	int	        bucket = 0;

    /* clear the error */

    CSSM_ClearError ();

    /* make sure that pointer is good */
    if (cssm_IsBadReadPtr (ContextAttributes, sizeof (CSSM_CONTEXT_ATTRIBUTE) * NumberAttributes)) {
        CSSM_SetError (&cssm_GUID, CSSM_INVALID_POINTER);
        return(CSSM_FAIL);
    }

	/* lock bucket */
	if ((TempContext = cssm_LookupAndLockBucket(CCHandle, &bucket)) == NULL) {
		// cssm error is set
		return(CSSM_FAIL);
	}

	/* found the context */
	for (i=0; i<NumberAttributes; i++) {
		 if (cssm_DelContextAttr (TempContext->Context, &ContextAttributes[i]) == CSSM_FAIL) {
			// error is already set
			rc = CSSM_FAIL;
			goto exit;
		 }
	}
	rc = CSSM_OK;

exit:
	// sets cssm error
	cssm_UnlockBucket(bucket);
	return(rc);;
}
