/* SCCSID: fwk/cssm/context.c, dss_cdsa_fwk, fwk_rel1 1.18 8/28/97 18:20:55 */
/* ***************************************************************** *
 * 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:   CONTEXT.C
 *
 * This file contains the internal functions functions to manage the crypto
 * context.
 */
/*
 * (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 "context.h"

extern CSSM_RETURN	cssm_CopyKeyData(CSSM_KEY_PTR	srcKey,
									 CSSM_KEY_PTR	destKey,
									 CSSM_CALLOC	local_calloc,
									 CSSM_FREE		local_free,
									 void*			local_ref);

extern void	cssm_FreeKeyData(	CSSM_KEY_PTR	srcKey,
								CSSM_FREE		local_free,
								void*			local_ref);


/*---------------------------------------------------------------
 *
 *Name: cssm_IsValidCSP
 *
 *Description:
 *   Given a CSP handle determine if handle is valid
 *
 *Parameters:
 *   CSPHandle (input) - handle to CSP
 *
 *Returns:
 *   CSSM_FALSE - unable to locate CSP handle
 *   CSSM_TRUE - found CSP handle
 *
 *-------------------------------------------------------------*/
CSSM_BOOL cssm_IsValidCSP (CSSM_HANDLE CSPHandle)
{
    extern cssm_INTERNALMODULELIST_PTR ModuleListHead;

    if (cssm_FindMemory (CSPHandle, ModuleListHead) != NULL)
        return(CSSM_TRUE);

    /* CSP handle not found */
    CSSM_SetError (&cssm_GUID, CSSM_INVALID_CSP_HANDLE);
    return(CSSM_FALSE);
}

/*---------------------------------------------------------------
 *
 *Name: cssm_CreateContext
 *
 *Description:
 *   Create the context structure
 *
 *Parameters:
 *   Class (input) - class type to initialize the context info
 *   AlgorithmID (input) - algorithm to initialize context info
 *
 *Returns:
 *   NULL - unable to create the context
 *   non NULL - pointer to context info
 *
 *-------------------------------------------------------------*/
CSSM_CONTEXT_PTR cssm_CreateContext (CSSM_CONTEXT_TYPE Class,
                                     uint32 AlgorithmID)
{
    CSSM_CONTEXT_PTR Context;

	/* allocate memory for structure */
    if ((Context = cssm_calloc (sizeof (CSSM_CONTEXT),1, 0)) == NULL) {
        CSSM_SetError (&cssm_GUID, CSSM_MEMORY_ERROR);
        return(NULL);
    }

    /* initialize the context structure */
    Context->ContextType = Class;
    Context->AlgorithmType = AlgorithmID;


    return(Context);
}

/*---------------------------------------------------------------
 *
 *Name: cssm_CopyDataStruct
 *
 *Description:
 *   Create a pointer for a CSSM_DATA structure and duplicate the
 *   data
 *
 *Parameters:
 *   Data (input) - pointer to the CSSM_DATA struct to copy
 *   Len (output) - length of actual data
 *
 *Returns:
 *   NULL - unable to complete function
 *   non NULL - pointer to the CSSM_DATA structure
 *
 *-------------------------------------------------------------*/
void * cssm_CopyDataStruct (CSSM_DATA_PTR Data, uint32 *Len,
                                         CSSM_CALLOC local_calloc,
                                         CSSM_FREE local_free,
                                         void * local_ref)
{
    CSSM_DATA_PTR	Dest;
	void			*rc;

    /* allocating the CSSM_DATA struct */

    if ((Dest = local_calloc (sizeof (CSSM_DATA),1, local_ref)) == NULL) {
		CSSM_SetError (&cssm_GUID, CSSM_MEMORY_ERROR);
        return(NULL);
	}

    /* allocating the actual data pointer */
    *Len = Data->Length;
    if ((Dest->Data = local_calloc (*Len,1, local_ref)) == NULL) {
        local_free (Dest, local_ref);
		CSSM_SetError (&cssm_GUID, CSSM_MEMORY_ERROR);
        return(NULL);
    }

    /* copying the data */
    Dest->Length = Data->Length;
    if (cssm_CheckCopy (Dest->Data, Data->Data, Data->Length) == CSSM_FAIL) {
        local_free (Dest->Data, local_ref);
        local_free (Dest, local_ref);
        return(NULL);
    }

    rc = (void *)Dest;
	return(rc);
}

/*---------------------------------------------------------------
 *
 *Name: cssm_CopyCryptoDataStruct
 *
 *Description:
 *   Duplicate a CSSM_CRYPTO_DATA structure
 *
 *Parameters:
 *   Data (input) - pointer to CSSM_CRYPTO_DATA structure
 *   Length (output) - siz e of the CSSM_CRYPTO_DATA structure
 *
 *Returns:
 *   NULL - unable to complete function
 *   non NULL - pointer to a duplicated structure
 *
 *-------------------------------------------------------------*/
CSSM_CRYPTO_DATA_PTR cssm_CopyCryptoDataStruct (CSSM_CRYPTO_DATA_PTR Data,
                                                uint32 *Length,
                                         CSSM_CALLOC local_calloc,
                                         CSSM_FREE local_free,
                                         void * local_ref)
{
    CSSM_CRYPTO_DATA_PTR CryptoDest;
    uint32 Len1, Len2;

    /* allocate the top level structure */

    Len1 = sizeof (CSSM_CRYPTO_DATA);
    if (( CryptoDest = local_calloc (Len1,1, local_ref)) == NULL) {
		CSSM_SetError (&cssm_GUID, CSSM_MEMORY_ERROR);
        return(NULL);
	}

    /* initialize the new structure */
    CryptoDest->Callback = Data->Callback;
    CryptoDest->CallbackID = Data->CallbackID;

    /* duplicate the CSSM_DATA structure */
    if (IsBadReadPtr (Data->Param, sizeof (CSSM_DATA)))
        CryptoDest->Param = NULL;
    else {
        if ((CryptoDest->Param = cssm_CopyDataStruct (Data->Param, &Len2, local_calloc, local_free, local_ref)) == NULL) {
            local_free (CryptoDest, local_ref);
			CSSM_SetError (&cssm_GUID, CSSM_MEMORY_ERROR);
            return(NULL);
        }

        CryptoDest->Param->Length = Len2;
    }

    *Length = Len1;
    return(CryptoDest);
}

/*---------------------------------------------------------------
 *
 *Name: cssm_CopyDateStruct
 *
 *Description:
 *   Duplicate a CSSM_DATE structure
 *
 *Parameters:
 *   Data (input) - pointer to CSSM_DATE structure
 *
 *Returns:
 *   NULL - unable to complete function
 *   non NULL - pointer to a duplicated structure
 *
 *-------------------------------------------------------------*/
CSSM_DATE_PTR cssm_CopyDateStruct (CSSM_DATE_PTR Data,
                                         CSSM_CALLOC local_calloc,
                                         CSSM_FREE local_free,
                                         void * local_ref)
{
    CSSM_DATE_PTR DateDest;
    uint32 Len1;

    /* allocate the top level structure */

    Len1 = sizeof (CSSM_DATE);
    if (( DateDest = local_calloc (Len1,1, local_ref)) == NULL) {
		CSSM_SetError (&cssm_GUID, CSSM_MEMORY_ERROR);
        return(NULL);
	}

    /* copying the data */
    if (cssm_CheckCopy (DateDest->Year, Data->Year, Len1) == CSSM_FAIL) {
        local_free (DateDest, local_ref);
		CSSM_SetError (&cssm_GUID, CSSM_MEMORY_ERROR);
        return(NULL);
    }

    return(DateDest);
}
/*---------------------------------------------------------------
 *
 *Name: cssm_CopyRangeStruct
 *
 *Description:
 *   Duplicate a CSSM_CRYPTO_DATA structure
 *
 *Parameters:
 *   Data (input) - pointer to CSSM_CRYPTO_DATA structure
 *   Length (output) - siz e of the CSSM_CRYPTO_DATA structure
 *
 *Returns:
 *   NULL - unable to complete function
 *   non NULL - pointer to a duplicated structure
 *
 *-------------------------------------------------------------*/
CSSM_RANGE_PTR cssm_CopyRangeStruct (CSSM_RANGE_PTR Data,
                                         CSSM_CALLOC local_calloc,
                                         CSSM_FREE local_free,
                                         void * local_ref)
{
    CSSM_RANGE_PTR Dest;
    uint32 Len1;

    Len1 = sizeof (CSSM_RANGE);
    if (IsBadReadPtr (Data, Len1))
        return(NULL);

    /* allocate the top level structure */
    if ((Dest = local_calloc (Len1,1, local_ref)) == NULL) {
		CSSM_SetError (&cssm_GUID, CSSM_MEMORY_ERROR);
        return(NULL);
	}

    Dest->Min = Data->Min;
    Dest->Max = Data->Max;

    return(Dest);
}

/*---------------------------------------------------------------
 *
 *Name: cssm_CopyKeyStruct
 *
 *Description:
 *   Duplicate a CSSM_KEY structure
 *
 *Parameters:
 *   Data (input) - pointer to CSSM_CRYPTO_DATA structure
 *
 *Returns:
 *   NULL - unable to complete function
 *   non NULL - pointer to a duplicated structure
 *
 *-------------------------------------------------------------*/
CSSM_KEY_PTR cssm_CopyKeyStruct (CSSM_KEY_PTR Data,
                                         CSSM_CALLOC local_calloc,
                                         CSSM_FREE local_free,
                                         void * local_ref)
{
    CSSM_KEY_PTR Dest;
    uint32 Len1;

    /* allocate the top level structure */

    Len1 = sizeof (CSSM_KEY);
    if (IsBadReadPtr (Data, Len1))
        return(NULL);

    if ((Dest = local_calloc (Len1,1, local_ref)) == NULL) {
		CSSM_SetError (&cssm_GUID, CSSM_MEMORY_ERROR);
        return(NULL);
	}

    /* initialize the new structure */
    /* duplicate the KeyData structure */
    if (IsBadReadPtr (Data->KeyData.Data, Data->KeyData.Length)) {
        local_free (Dest, local_ref);
        return(NULL);
    } else {

		if (cssm_CopyKeyData(Data, Dest, local_calloc, local_free, local_ref) != CSSM_OK){
			local_free (Dest, local_ref);
			return(NULL);;
		}
   }

    /* copying the keyheader */
    if (cssm_CheckCopy (Dest, Data, sizeof (CSSM_KEYHEADER)) == CSSM_FAIL) {
        local_free (Dest->KeyData.Data, local_ref);
        local_free (Dest, local_ref);
		CSSM_SetError (&cssm_GUID, CSSM_MEMORY_ERROR);
        return(NULL);
    }

    return(Dest);
}

/*---------------------------------------------------------------
 *
 *Name: cssm_DuplicateAttributes
 *
 *Description:
 *   Given a set of attributes, duplicate it and return a pointer
 *   to it.
 *
 *Parameters:
 *   Number (input) - count of attributes
 *   Attributes (input) - attributes to duplicate
 *
 *Returns:
 *   NULL - unable to duplicate attributes
 *   non NULL - pointer to attributes info
 *
 *-------------------------------------------------------------*/
CSSM_CONTEXT_ATTRIBUTE_PTR cssm_DuplicateAttributes (uint32 Number,
                                         CSSM_CONTEXT_ATTRIBUTE_PTR Attributes,
                                         CSSM_CALLOC local_calloc,
                                         CSSM_FREE local_free,
                                         void * local_ref)
{
    sint16 i;
    CSSM_CONTEXT_ATTRIBUTE_PTR AttributesTemp;
	uint32	error=0;


    /* allocate memory for the attributes structure */
    if ((AttributesTemp = (CSSM_CONTEXT_ATTRIBUTE_PTR)local_calloc (Number * sizeof (CSSM_CONTEXT_ATTRIBUTE),1, local_ref)) == NULL) {
		CSSM_SetError (&cssm_GUID, CSSM_MEMORY_ERROR);
        return(NULL);
    }

    /* for every attribute */
    for (i=0; i<(sint16)Number; i++) {

        AttributesTemp[i].AttributeType = Attributes[i].AttributeType;
        AttributesTemp[i].AttributeLength = Attributes[i].AttributeLength;

        /* see if there is data to copy */
        if (Attributes[i].Attribute.Data != NULL ||						
			((Attributes[i].AttributeType & CSSM_ATTRIBUTE_TYPE_MASK) == CSSM_ATTRIBUTE_DATA_UINT32)) {
            uint32 Length;

            /* Get actual length of data */
            Length = Attributes[i].AttributeLength;

            if ((Attributes[i].AttributeType & CSSM_ATTRIBUTE_TYPE_MASK) != CSSM_ATTRIBUTE_DATA_UINT32)
                if (cssm_IsBadReadPtr (Attributes[i].Attribute.Data, Length)) {
					goto Finally;
				}

            /* every attribute type is handled differently */
            switch (Attributes[i].AttributeType & CSSM_ATTRIBUTE_TYPE_MASK) {
                case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA :{
                    CSSM_CRYPTO_DATA_PTR p, q = Attributes[i].Attribute.Crypto;
                    if ((p = (CSSM_CRYPTO_DATA_PTR)local_calloc (sizeof (CSSM_CRYPTO_DATA),1, local_ref)) == NULL) {
						error = CSSM_MEMORY_ERROR;
						goto Finally;
					}
					p->Callback = q->Callback;
                    p->CallbackID = q->CallbackID;
                     if (q->Param == NULL)
                         p->Param = NULL;
                     else {
                         if ((p->Param = (CSSM_DATA_PTR)local_calloc (sizeof (CSSM_DATA),1, local_ref)) == NULL) {

							error = CSSM_MEMORY_ERROR;
							goto Finally;
                         }

                         if ((p->Param->Data = local_calloc (q->Param->Length,1, local_ref)) == NULL) {
                            local_free (p, local_ref);
							error = CSSM_MEMORY_ERROR;
							goto Finally;
                         }

                         p->Param->Length = q->Param->Length;
                         if (cssm_CheckCopy (p->Param->Data, q->Param->Data, q->Param->Length) == CSSM_FAIL) {
                            local_free (p->Param->Data, local_ref);
                            local_free (p, local_ref);
							error = CSSM_MEMORY_ERROR;
							goto Finally;
                         }
                     }
                     AttributesTemp[i].Attribute.Crypto = p;

                 }
                 break;

                 case CSSM_ATTRIBUTE_DATA_KEY: {
                     CSSM_KEY_PTR q = Attributes[i].Attribute.Key;

                     if ((AttributesTemp[i].Attribute.Key =
                             (CSSM_KEY_PTR)cssm_CopyKeyStruct (q, local_calloc, local_free, local_ref)) == NULL) {
						 /* error code is set in cssm_CopyKeyStruct */
						 goto Finally;
                     }
                 }
                 break;

                 case CSSM_ATTRIBUTE_DATA_DATE : {
                     CSSM_DATE_PTR Data;

                     if ((Data = (CSSM_DATE_PTR)local_calloc (sizeof (CSSM_DATE),1, local_ref)) == NULL) {
   							error = CSSM_MEMORY_ERROR;
							goto Finally;
	                  }

                     cssm_CheckCopy (Data, Attributes[i].Attribute.Date, sizeof (CSSM_DATE));
                     AttributesTemp[i].Attribute.Date = Data;
                 }
                 break;

                 case CSSM_ATTRIBUTE_DATA_RANGE : {
                     CSSM_RANGE_PTR Data;

                     if ((Data = (CSSM_RANGE_PTR)local_calloc (sizeof (CSSM_RANGE),1, local_ref)) == NULL) {
						error = CSSM_MEMORY_ERROR;
						goto Finally;
	                 }

                     Data->Min = Attributes[i].Attribute.Range->Min;
                     Data->Max = Attributes[i].Attribute.Range->Max;
                     AttributesTemp[i].Attribute.Range = Data;
                 }
                 break;

                 case CSSM_ATTRIBUTE_DATA_CSSM_DATA: {
                     CSSM_DATA_PTR Data;
                     uint32 Length = Attributes[i].Attribute.Data->Length;

                     if ((Data = (CSSM_DATA_PTR)local_calloc (sizeof (CSSM_DATA),1, local_ref)) == NULL) {
    					error = CSSM_MEMORY_ERROR;
						goto Finally;
	                 }

                     if ((Data->Data = (uint8 *)local_calloc (Length,1, local_ref)) == NULL) {
                        local_free (Data, local_ref);
   							error = CSSM_MEMORY_ERROR;
							goto Finally;
	                 }

                     if (cssm_CheckCopy (Data->Data, Attributes[i].Attribute.Data->Data, Length) == CSSM_FAIL) {
                        /* free memory */
                        local_free (Data->Data, local_ref);
                        local_free (Data, local_ref);
						error = CSSM_MEMORY_ERROR;
						goto Finally;
	                 }
                     Data->Length = Length;
                     AttributesTemp[i].Attribute.Data = (CSSM_DATA_PTR)Data;
                 }
                 break;

                 case CSSM_ATTRIBUTE_DATA_UINT32: {
                     AttributesTemp[i].Attribute.Uint32 =
                                       Attributes[i].Attribute.Uint32;
                    }
                    break;

                 case CSSM_ATTRIBUTE_DATA_STRING: {
                    char *str;

                    if ((str = (char *)local_calloc(strlen(Attributes[i].Attribute.String),1, local_ref)) == NULL) {
						error = CSSM_MEMORY_ERROR;
						goto Finally;
	                }
                    strcpy (str, Attributes[i].Attribute.String);
                    AttributesTemp[i].Attribute.String = str;
                    }
                    break;
                 }
             }
    }

Finally:
	if (error) {
		cssm_FreeAttributes (i,
                             AttributesTemp,
                             local_free, local_ref,
                             CSSM_TRUE);
		CSSM_SetError (&cssm_GUID, error);
		AttributesTemp=NULL;
	}

    return(AttributesTemp);
}

/*---------------------------------------------------------------
 *
 *Name: cssm_DuplicateContext
 *
 *Description:
 *   Given a context, duplicate it.
 *
 *Parameters:
 *   Context (input) - pointer to context to duplicate
 *
 *Returns:
 *   NULL - unable to duplicate context
 *   non NULL - pointer to duplicated context
 *
 *-------------------------------------------------------------*/
CSSM_CONTEXT_PTR cssm_DuplicateContext (CSSM_CONTEXT_PTR Context,
                                        CSSM_CALLOC local_calloc,
                                        CSSM_FREE local_free,
                                        void *mem_ref)
{
    CSSM_CONTEXT_PTR ContextTemp;

    /* allocating memory for context */

    if ((ContextTemp = (CSSM_CONTEXT_PTR)local_calloc (sizeof (CSSM_CONTEXT),1, mem_ref)) == NULL) {
		CSSM_SetError (&cssm_GUID, CSSM_MEMORY_ERROR);
        return(NULL);
	}

    /* assign fields in context */
    ContextTemp->ContextType = Context->ContextType;
    ContextTemp->AlgorithmType = Context->AlgorithmType;
    ContextTemp->Reserve = Context->Reserve;
    ContextTemp->NumberOfAttributes = Context->NumberOfAttributes;
    ContextTemp->ContextAttributes = NULL;

    if (ContextTemp->NumberOfAttributes > 0) {
       /* duplicate every attribute in context */
       if ((ContextTemp->ContextAttributes = cssm_DuplicateAttributes (Context->NumberOfAttributes, Context->ContextAttributes, local_calloc, local_free, mem_ref)) == NULL) {
          local_free (ContextTemp, mem_ref);
		  CSSM_SetError (&cssm_GUID, CSSM_MEMORY_ERROR);
          return(NULL);
       }
    }

    return(ContextTemp);
}

/*---------------------------------------------------------------
 *
 *Name: cssm_InsertContext
 *
 *Description:
 *   Insert the context into an internal list of context
 *
 *Parameters:
 *   Context (input) - pointer to the context
 *   CSPHandle (input) - CSP handle associated with context
 *
 *Returns:
 *   zero - unable to complete function
 *   non zero - crypto handle associated with context
 *
 *-------------------------------------------------------------*/
CSSM_CC_HANDLE CSSMAPI cssm_InsertContext (CSSM_CONTEXT_PTR Context,
                                           CSSM_CSP_HANDLE CSPHandle)
{
    cssm_INTERNALCONTEXT_PTR TempContext;
    CSSM_REGISTRATION_INFO_PTR CallBack = NULL;

    /* make sure that CSP handle is valid */
    if (cssm_IsValidCSP (CSPHandle) != CSSM_TRUE)
    {
        cssm_free (Context, 0);
        return(0);
    }

	/* allocate structure for context */
    if ((TempContext = cssm_calloc (sizeof (cssm_INTERNALCONTEXT),1, 0)) == NULL) {
        CSSM_SetError (&cssm_GUID, CSSM_MEMORY_ERROR);
		cssm_free (Context, 0);
        return(0);
    }

	/* set the CSPHandle in the context */
	Context->CSPHandle = CSPHandle;
    TempContext->Context = Context;
    TempContext->CSPHandle = CSPHandle;

    /* install the internal context in the hash table*/
	if (cssm_InstallCONTEXT (TempContext) != CSSM_OK) {
		cssm_free (Context, 0);
		return(0);
	}

    /* callback to csp to notify context creation */
    CallBack  = cssm_GetModuleCallBackByHandle (CSPHandle);
    if (CallBack) {

        if (CallBack->EventNotify) {

			/* notice that the second parameter - addin type - is 0; for as it*/
			/* turns out neither cssm_GetMultitaskMutexHandle() nor */
			/* cssm_CheckThreadSafe() needs it - they just look at the handle */
			if( cssm_CheckThreadSafe(CSPHandle, 0) == CSSM_FALSE) {
				if (cssm_LockMutex(cssm_GetMultitaskMutexHandle (CSPHandle, 0),CSSM_INFINITE_WAIT) != CSSM_MUTEX_LOCKED) {
					// cssm error is set
					return(0);
				}
			}

            CallBack->EventNotify (CSPHandle, CSSM_EVENT_CREATE_CONTEXT,
                                              TempContext->ContextHandle);

			/* notice that the second parameter - addin type - is 0; for as it*/
			/* turns out neither cssm_GetMultitaskMutexHandle() nor */
			/* cssm_CheckThreadSafe() needs it - they just look at the handle */
			if(cssm_CheckThreadSafe (CSPHandle, 0) == CSSM_FALSE) {
				if (cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (CSPHandle,0)) != CSSM_MUTEX_UNLOCKED) {
					// cssm error is set
					return(0);
				}
			}

		}	/* if (CallBack->EventNotify) */

	}	/* if (CallBack) */

    return(TempContext->ContextHandle);
}

/*---------------------------------------------------------------
 *
 *Name: cssm_FreeAttribute
 *
 *Description:
 *   Free memory that was allocated for attributes
 *
 *Parameters:
 *   NumberOfAttributes (input) - count of attributes to free
 *   Attributes (input) - pointer to the attributes info
 *   local_free (input) - free function to deallocate memory
 *   Free (input) - flag to indicate if the top level pointer
 *                  needs to be freed
 *
 *Returns:
 *   none
 *
 *-------------------------------------------------------------*/
void CSSMAPI cssm_FreeAttributes (uint32 NumberOfAttributes,
                                  CSSM_CONTEXT_ATTRIBUTE_PTR Attributes,
                                  CSSM_FREE local_free, void *mem_ref,
                                  uint32 Free)
{
    sint16 i;

    /* for each attribute */

    for (i=0; i < (sint16)NumberOfAttributes; i++)
    {
        /* make sure there is something that needs freeing */
        if ((Attributes[i].Attribute.Data != NULL) && ((Attributes[i].AttributeType & CSSM_ATTRIBUTE_TYPE_MASK)
                != CSSM_ATTRIBUTE_DATA_UINT32))
        {
            /* for every attribute type, the info is different, free stuff INSIDE the structure */
            /* DO NOT FREE WHAT THE POINTER ACTUALLY POINTS TO */
            switch (Attributes[i].AttributeType & CSSM_ATTRIBUTE_TYPE_MASK)
            {
                case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA:
                    {
                        /* These types use a CSSM_CRYPTO_DATA structure */
                        CSSM_CRYPTO_DATA_PTR q = Attributes[i].Attribute.Crypto;
                        if (q->Param)
                        {
                            if ((q->Param->Data) && (!cssm_IsBadReadPtr (q->Param->Data, q->Param->Length)))
                                local_free (q->Param->Data, mem_ref);
                            local_free (q->Param, mem_ref);
                        }
                    }
                    break;

                case CSSM_ATTRIBUTE_DATA_KEY :
                    {
                        /* These types use a CSSM_DATA structure */
                        CSSM_KEY_PTR q = Attributes[i].Attribute.Key;
                        cssm_FreeKeyData(q,local_free,mem_ref);
                    }
                    break;

                case CSSM_ATTRIBUTE_DATA_CSSM_DATA:
                    if (Attributes[i].Attribute.Data->Data != NULL)
                        local_free(Attributes[i].Attribute.Data->Data, memRef);
					break;
            } // end switch

            // now free the structure that pointer actually points to
            local_free(Attributes[i].Attribute.Data, mem_ref);
        } // endif
    } // endfor

    /* check for need to free the top most pointer */
    if (Free && !cssm_IsBadWritePtr(Attributes, sizeof(*Attributes)))
        local_free (Attributes, mem_ref);
	return;
}

/*---------------------------------------------------------------
 *
 *Name: cssm_FreeIntContext
 *
 *Description:
 *   Free memory that was allocated for internal context information
 *
 *Parameters:
 *   Context (input) - pointer to internal context structure
 *	 event to send to the addin
 *	 flag to indicate if the Internal context struct should be freed
 *
 *Returns:
 *   none
 *
 *-------------------------------------------------------------*/
void CSSMAPI cssm_FreeIntContext (cssm_INTERNALCONTEXT_PTR IntContext,
								  CSSM_EVENT_TYPE event, CSSM_BOOL flag)
{
    /* free the attributes, context and internal context structure */
    cssm_FreeAttributes (IntContext->Context->NumberOfAttributes, IntContext->Context->ContextAttributes, (CSSM_FREE)cssm_free, 0, 1);
    cssm_free (IntContext->Context, 0);
	if (flag) {
		cssm_free (IntContext, 0);
	}

	return;
}

/*---------------------------------------------------------------
 *Name: cssm_NotifyModule
 *
 *Description:
 *   Notify add-in modules about contex deletion
 *
 *Parameters:
 *   cspHandle - handle of the CSP using this context
 *   contextHandle - handle ofthe removed context
 *	 event - notification event type
 *
 *Returns:
 *   none
 *
 *-------------------------------------------------------------*/
void CSSMAPI cssm_NotifyModule(
	CSSM_CSP_HANDLE cspHandle,
	CSSM_CC_HANDLE contextHandle,
	CSSM_EVENT_TYPE event) 
{
    CSSM_REGISTRATION_INFO_PTR CallBack = NULL;

    /* callback to csp to notify context deletion */

    CallBack  = cssm_GetModuleCallBackByHandle (cspHandle);
    if (CallBack) {
        if (CallBack->EventNotify) {
			/* notice that the second parameter - addin type - is 0; for as it*/
			/* turns out neither cssm_GetMultitaskMutexHandle() nor */
			/* cssm_CheckThreadSafe() needs it - they just look at the handle */
			if( cssm_CheckThreadSafe(cspHandle, 0) == CSSM_FALSE) {
				if (cssm_LockMutex(cssm_GetMultitaskMutexHandle (cspHandle, 0),CSSM_INFINITE_WAIT) != CSSM_MUTEX_LOCKED) {
					return;
				}
			}

            CallBack->EventNotify (cspHandle, event, contextHandle);

			/* notice that the second parameter - addin type - is 0; for as it*/
			/* turns out neither cssm_GetMultitaskMutexHandle() nor */
			/* cssm_CheckThreadSafe() needs it - they just look at the handle */
			if(cssm_CheckThreadSafe (cspHandle, 0) == CSSM_FALSE) {
				if (cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (cspHandle,0)) != CSSM_MUTEX_UNLOCKED) {
					return;
				}
			}
		}	/* if (CallBack->EventNotify) */
	}	/* if (CallBack) */

	return;
}

/*---------------------------------------------------------------
 *
 *Name: cssm_FreeContext
 *
 *Description:
 *   Free memory that was allocated for user context information
 *
 *Parameters:
 *   Context (input) - pointer to user context structure
 *
 *Returns:
 *   none
 *
 *-------------------------------------------------------------*/
void CSSMAPI cssm_FreeContext (CSSM_CONTEXT_PTR Context)
{
    /* free the attributes and context structure */

    cssm_FreeAttributes (Context->NumberOfAttributes, Context->ContextAttributes, (CSSM_FREE)app_free, memRef, 1);
    app_free (Context, memRef);
	return;
}


/*---------------------------------------------------------------
 *
 *Name: cssm_CreateAttribute
 *
 *Description:
 *   Create a pointer for the attribute structure
 *
 *Parameters:
 *   Attributes (output) - pointer to receive the attribute structure
 *   NumberOfAttributes (input) - number of attributes memory to hold
 *
 *Returns:
 *   CSSM_FAIL - unable to complete function
 *   CSSM_OK - operation successful
 *
 *-------------------------------------------------------------*/
CSSM_RETURN CSSMAPI cssm_CreateAttribute (CSSM_CONTEXT_ATTRIBUTE_PTR *Attributes,
                                          uint32 NumberAttributes)
{

    /* allocating the structure */

	if (NumberAttributes ==0) {
		CSSM_SetError(&cssm_GUID, CSSM_INVALID_ATTRIBUTE_COUNT);
		return(CSSM_FAIL);
	}

    *Attributes = cssm_calloc (sizeof (CSSM_CONTEXT_ATTRIBUTE) * NumberAttributes,1, 0);
    if (*Attributes == NULL) {
        CSSM_SetError (&cssm_GUID, CSSM_MEMORY_ERROR);
        return(CSSM_FAIL);
    }

    return(CSSM_OK);
}

/*---------------------------------------------------------------
 *
 *Name: cssm_AddAttribute
 *
 *Description:
 *   Add the attribute data to the pointer
 *
 *Parameters:
 *   Attribute (output) - pointer to attribute info
 *   type (input) - type of attribute data
 *   Data (input) - pointer to attribute data
 *
 *Returns:
 *   CSSM_FAIL - unable to complete function
 *   CSSM_OK - operation successful
 *
 *-------------------------------------------------------------*/
CSSM_RETURN CSSMAPI cssm_AddAttribute (CSSM_CONTEXT_ATTRIBUTE_PTR Attributes,
                                       CSSM_ATTRIBUTE_TYPE type,
                                       void *Data)
{

    switch (type & CSSM_ATTRIBUTE_TYPE_MASK) {
        case CSSM_ATTRIBUTE_DATA_STRING : {
            char *Description = Data;
            uint32 size = strlen (Description);

            if ((Attributes->Attribute.String = cssm_calloc (size+1,1, 0)) == NULL) {
				CSSM_SetError (&cssm_GUID, CSSM_MEMORY_ERROR);
                return(CSSM_FAIL);
			}

            strcpy (Attributes->Attribute.String, Description);
            Attributes->Attribute.String[size] = 0;
            Attributes->AttributeType = type;
            Attributes->AttributeLength = size;
        }
        break;

        case CSSM_ATTRIBUTE_DATA_UINT32 :{
            uint32 i = (uint32)Data;

            Attributes->AttributeType = type;
            Attributes->Attribute.Uint32 = i;
            Attributes->AttributeLength = sizeof (uint32);
        }
        break;

        case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA : {
            CSSM_CRYPTO_DATA_PTR Source = Data;

            Attributes->AttributeType = type;
            if ((Attributes->Attribute.Crypto = (CSSM_CRYPTO_DATA_PTR)cssm_CopyCryptoDataStruct (Source, &Attributes->AttributeLength, cssm_calloc, cssm_free, 0)) == NULL) {
                return(CSSM_FAIL);
			}
        }
        break;

        case CSSM_ATTRIBUTE_DATA_KEY: {
            CSSM_KEY_PTR Source = Data;

            Attributes->AttributeType = type;
            Attributes->AttributeLength = sizeof (CSSM_KEY);
			
            if ((Attributes->Attribute.Key = (CSSM_KEY_PTR)cssm_CopyKeyStruct (Source, cssm_calloc, cssm_free, 0)) == NULL) {
                return(CSSM_FAIL);
			}
        }
        break;

        case CSSM_ATTRIBUTE_DATA_DATE: {
            CSSM_DATE_PTR Source = Data;

            Attributes->AttributeType = type;
            Attributes->AttributeLength = sizeof (CSSM_DATE);
            if ((Attributes->Attribute.Date = (CSSM_DATE_PTR)cssm_CopyDateStruct (Source, cssm_calloc, cssm_free, 0)) == NULL) {
                return(CSSM_FAIL);
			}
        }
        break;

        case CSSM_ATTRIBUTE_DATA_CSSM_DATA : {
            CSSM_DATA_PTR Source = Data;
            uint32 i;

            Attributes->AttributeType = type;
            Attributes->AttributeLength = sizeof (CSSM_DATA);
            if ((Attributes->Attribute.Data = (CSSM_DATA_PTR)cssm_CopyDataStruct (Source, &i, cssm_calloc, cssm_free, 0)) == NULL) {
                return(CSSM_FAIL);
			}
        }
        break;

        case CSSM_ATTRIBUTE_DATA_RANGE: {
            CSSM_RANGE_PTR Source = Data;

            Attributes->AttributeType = type;
            Attributes->AttributeLength = sizeof (CSSM_RANGE);
            if ((Attributes->Attribute.Range = (CSSM_RANGE_PTR)cssm_CopyRangeStruct (Source, cssm_calloc, cssm_free, 0)) == NULL) {
                return(CSSM_FAIL);
			}
        }
        break;

        default:
            return(CSSM_FAIL);
    }

    return(CSSM_OK);
}

/*---------------------------------------------------------------
 *
 *Name: cssm_
 *
 *Description:
 *
 *Parameters:
 *
 *Returns:
 *   CSSM_FAIL - unable to complete function
 *   CSSM_OK - operation successful
 *
 *-------------------------------------------------------------*/
CSSM_BOOL cssm_IsBadCryptoKeyPtr (CSSM_KEY_PTR Key)
{

    if (Key == 0 || cssm_IsBadReadPtr (Key, sizeof (CSSM_KEY)))
        return(CSSM_TRUE);

	if (Key->KeyData.Data == 0 ||
        cssm_IsBadReadPtr (Key->KeyData.Data, Key->KeyData.Length))
            return(CSSM_TRUE);

    return(CSSM_FALSE);
}

/*---------------------------------------------------------------
 *
 *Name: cssm_
 *
 *Description:
 *
 *Parameters:
 *
 *Returns:
 *   CSSM_FAIL - unable to complete function
 *   CSSM_OK - operation successful
 *
 *-------------------------------------------------------------*/
CSSM_BOOL cssm_IsBadCryptoDataPtr (CSSM_CRYPTO_DATA_PTR Data)
{

    if (cssm_IsBadReadPtr (Data, sizeof (CSSM_CRYPTO_DATA)))
        return(CSSM_TRUE);

    if (Data->Callback == NULL) {
        if (cssm_IsBadReadPtr (Data->Param, sizeof (CSSM_DATA)))
            return(CSSM_TRUE);

        if (cssm_IsBadReadPtr (Data->Param->Data, Data->Param->Length))
            return(CSSM_TRUE);
    }

    return(FALSE);
}

/*---------------------------------------------------------------
 *
 *Name: cssm_
 *
 *Description:
 *
 *Parameters:
 *
 *Returns:
 *   CSSM_FAIL - unable to complete function
 *   CSSM_OK - operation successful
 *
 *-------------------------------------------------------------*/
CSSM_RETURN cssm_UpdateAttribute (CSSM_CONTEXT_ATTRIBUTE_PTR Des,
                                  CSSM_CONTEXT_ATTRIBUTE_PTR Src)
{

    switch (Src->AttributeType & CSSM_ATTRIBUTE_TYPE_MASK) {
        case CSSM_ATTRIBUTE_DATA_STRING : {
            if ((Des->Attribute.String = cssm_realloc (Des->Attribute.String,
                                             Src->AttributeLength, 0)) == NULL)
                return(CSSM_FAIL);

            strcpy (Des->Attribute.String, Src->Attribute.String);
        }
        break;

        case CSSM_ATTRIBUTE_DATA_KEY : {
            CSSM_KEY_PTR Key = Src->Attribute.Key;

            if ((Des->Attribute.Key = (CSSM_KEY_PTR)cssm_CopyKeyStruct (Key, cssm_calloc, cssm_free, 0)) == NULL) {
                return(CSSM_FAIL);
			}
        }
        break;

        case CSSM_ATTRIBUTE_DATA_UINT32 :
            Des->Attribute.Uint32 = Src->Attribute.Uint32;
        break;

        case CSSM_ATTRIBUTE_DATA_CSSM_DATA : {
            CSSM_DATA_PTR Source = Src->Attribute.Data,
                                Dest = Des->Attribute.Data;

            if ((Dest->Data = cssm_realloc (Dest->Data, Source->Length, 0))
                                                       == NULL)
                return(CSSM_FAIL);

            Dest->Length = Source->Length;
            if (cssm_CheckCopy (Dest->Data, Source->Data,
                                      Source->Length) == CSSM_FAIL) {
                return(CSSM_FAIL);
            }
        }
        break;

        case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA : {
            CSSM_CRYPTO_DATA_PTR Source = Src->Attribute.Crypto,
                                 Dest = Des->Attribute.Crypto;

            Dest->Callback = Source->Callback;
            Dest->CallbackID = Source->CallbackID;

            if (IsBadReadPtr (Source->Param, sizeof (CSSM_DATA)))
                Dest->Param = NULL;
            else {
                if ((Dest->Param->Data = cssm_realloc (Dest->Param->Data,
                                            Source->Param->Length, 0)) == NULL)
                    return(CSSM_FAIL);

                Dest->Param->Length = Source->Param->Length;
                if (cssm_CheckCopy (Dest->Param->Data, Source->Param->Data,
                                         Source->Param->Length) == CSSM_FAIL)
                    return(CSSM_FAIL);
            }
        }
        break;

        default:
            return(CSSM_FAIL);
    }

    return(CSSM_OK);
}

/*---------------------------------------------------------------
 *
 *Name: cssm_UpdateContext
 *
 *Description:
 *
 *Parameters:
 *
 *Returns:
 *   CSSM_FAIL - unable to complete function
 *   CSSM_OK - operation successful
 *
 *-------------------------------------------------------------*/
CSSM_RETURN cssm_UpdateContext (CSSM_CONTEXT_PTR Context,
                                CSSM_CONTEXT_ATTRIBUTE_PTR Attribute)
{
    uint32		i;
	CSSM_RETURN	rc;

    for (i = 0; i<Context->NumberOfAttributes; i++) {
        if (Context->ContextAttributes[i].AttributeType == Attribute->AttributeType) {
            rc = cssm_UpdateAttribute (&Context->ContextAttributes[i], Attribute);
			return(rc);
        }
    }

    Context->NumberOfAttributes++;
    if ((Context->ContextAttributes = cssm_realloc (Context->ContextAttributes, sizeof (CSSM_CONTEXT_ATTRIBUTE) * Context->NumberOfAttributes, 0)) == NULL) {
		CSSM_SetError (&cssm_GUID, CSSM_REALLOC_FAILED);
        return(CSSM_FAIL);
	}

    if (!cssm_IsBadReadPtr (Attribute, sizeof (CSSM_CONTEXT_ATTRIBUTE)))
        if (cssm_AddAttribute (&Context->ContextAttributes[Context->NumberOfAttributes - 1], Attribute->AttributeType, (void *)Attribute->Attribute.Data) == CSSM_FAIL) {
            return(CSSM_FAIL);
        }

    return(CSSM_OK);
}

/*---------------------------------------------------------------
 *
 *Name: cssm_
 *
 *Description:
 *
 *Parameters:
 *
 *Returns:
 *   CSSM_FAIL - unable to complete function
 *   CSSM_OK - operation successful
 *
 *-------------------------------------------------------------*/
CSSM_RETURN cssm_DelContextAttr (CSSM_CONTEXT_PTR Context,
                                 CSSM_CONTEXT_ATTRIBUTE_PTR Attribute)
{
    uint32 i;

    for (i = 0; i<Context->NumberOfAttributes; i++) {
        if (Context->ContextAttributes[i].AttributeType == Attribute->AttributeType)
            if (Context->ContextAttributes[i].AttributeLength == Attribute->AttributeLength) {
                    cssm_FreeAttributes (1, &Context->ContextAttributes[i], (CSSM_FREE)cssm_free, 0, 0);

					Context->NumberOfAttributes--;
                    for (; i<Context->NumberOfAttributes; i++) {
						if (cssm_CheckCopy (&Context->ContextAttributes[i], &Context->ContextAttributes[i+1], sizeof (CSSM_CONTEXT_ATTRIBUTE)) == CSSM_FAIL)
                            return(CSSM_FAIL);
					}

                    return(CSSM_OK);
                }
    }

    return(CSSM_FAIL);
}

/*---------------------------------------------------------------
 *
 *Name: cssm_
 *
 *Description:
 *
 *Parameters:
 *
 *Returns:
 *   CSSM_FAIL - unable to complete function
 *   CSSM_OK - operation successful
 *
 *-------------------------------------------------------------*/
CSSM_CSP_HANDLE cssm_FindCSPHandle (CSSM_CC_HANDLE CCHandle)
{
	cssm_INTERNALCONTEXT_PTR TempContext = NULL;

	TempContext = cssm_LookupCONTEXT(CCHandle);
	if (TempContext == NULL)
		return(0);
	else
		return(TempContext->CSPHandle);
}
