/***********************************************************************
 * 
 *  Copyright (C) 2005-2006 Novell, Inc. All Rights Reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; version 2.1
 *  of the License.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, Novell, Inc.
 * 
 *  To contact Novell about this file by physical or electronic mail, 
 *  you may find current contact information at www.novell.com.
 * 
 ***********************************************************************/



#include <stdlib.h>
#include <memory.h>

#include "micasa_types.h"
#include "micasa.h"	
#include "sscs_lldefs.h"

#include "sscs_cache.h"
#include "sscs_utf8.h"

// delimited tags
//static SS_UTF8_T	SSCS_CRED_SET_DELIMITED[] = {'S','S','_','C','r','e','d','S','e','t',':',0};
static SS_UTF8_T	SSCS_CRED_SET_DELIMITED[] = {"SS_CredSet:"};
#define SSCS_CRED_SET_CHARS_DELIMITED		12

//static SS_UTF8_T	SSCS_APP_SECRET_DELIMITED[] = {'S','S','_','A','p','p',':',0};
static SS_UTF8_T	SSCS_APP_SECRET_DELIMITED[] = {"SS_App:"};
#define SSCS_APP_SECRET_CHARS_DELIMITED	8

//static SS_UTF8_T	SSCS_BINARY_SECRET_DELIMITED[] = {'S','S','_','B','i','n','a','r','y',':',0};
static SS_UTF8_T	SSCS_BINARY_SECRET_DELIMITED[] = {"SS_Binary:"};
#define SSCS_BINARY_CHARS_DELIMITED		11

//static SS_UTF8_T	SSCS_OBITUARY_DELIMITED[] = {'S','S','_','O','b','i','t','u','a','r','y',':', 0};
static SS_UTF8_T	SSCS_OBITUARY_DELIMITED[] = {"SS_Obituary:"};
#define SSCS_OBITUARY_CHARS_DELIMITED		13

#define	sscsshs_AddSHSBinaryEntry	sscsshs_AddSHSEntry




/*
 * NAME - sscsshs_AddSHSEntry
 *
 * DESCRIPTION
 *	 Internal function that adds a new entry in the parser list for a Shared Secret.
 *
 */			  
static int32_t sscsshs_AddSHSEntry
(
	void				*secretHandle,
	uint32_t			keyLen,
	SS_UTF8_T			*key,
	uint32_t			valLen,
	uint8_t				*val 
)
{ /* beginning of the call */
/* ############################## CODE STARTS HERE ############################ */

	if((keyLen) && (secretHandle))
	{
		if(ll_InsertSharedSecretLink((LL_LINKLIST_T*)secretHandle, 
					keyLen, key, valLen, val))
		{
			return(NSSCS_E_LL_SYS_FAILURE);
		}
		else
		{
			return(NSSCS_LL_SUCCESS);
		}
	  
	}
	else
	{
		return(NSSCS_E_LL_SYS_FAILURE);
	}

/* ############################### CODE ENDS HERE ############################# */
}	//* sscsshs_AddSHSEntry





/*
 * NAME - sscsshs_GetNextSHSEntry
 *
 * DESCRIPTION
 *	 Internal function that gets the next entry in the parser list for a Shared Secret.
 *
 */
static int32_t sscsshs_GetNextSHSEntry
(
	int32_t 		restart, 
	void 			*secretHandle, 
	uint32_t		*keyLen,
	SS_UTF8_T		*key, 
	uint32_t		*valLen,
	uint8_t			*val
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	LL_SHSEC_KEY_VAL_T 	*keyVal = {0};

/* ############################## CODE STARTS HERE ############################ */

	*keyLen = 0;
	*valLen = 0;

	if(secretHandle)
	{
		if(restart)
		{
			ll_Head((LL_LINKLIST_T *)secretHandle);
		}
		else
		{
			if(!(ll_Next((LL_LINKLIST_T *)secretHandle)))
			{
				return(NSSCS_E_LL_SYS_FAILURE);
			}
		}

		if(keyVal = (LL_SHSEC_KEY_VAL_T *)ll_GetEntry((LL_LINKLIST_T *)secretHandle))
		{
			if(keyVal->kLen)
			{
				*keyLen = keyVal->kLen;
				sscs_Utf8Strncpy(key, keyVal->key, keyVal->kLen);
				*valLen = keyVal->vLen;
				memcpy(val, keyVal->value, *valLen);

				return(NSSCS_SUCCESS);
			}
		}

		return(NSSCS_E_LL_SYS_FAILURE); 
	}
	else
	{
		return(NSSCS_E_LL_SYS_FAILURE); 
	}

/* ############################### CODE ENDS HERE ############################# */
}	//* sscsshs_GetNextSHSEntry



/*
 * NAME - sscsshs_EscapeString
 *
 * DESCRIPTION
 *	 Internal function that escapes delimited characters in a string.
 *
 */
static void sscsshs_ChkEscapeString
(
	SS_UTF8_T		**entryBuf, 
	uint32_t		*entryBufLen
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int 			len = 0, i, k = 0, tmplen = 0, escaped = 0;
	SS_UTF8_T	 	*tempBuf = NULL;

/* ############################## CODE STARTS HERE ############################ */

	len = *entryBufLen;

	if(len > (NSSCS_MAX_SECRET_BUF_LEN - SSCS_CRED_SET_LEN))
		return;

	/* We assume that all the chars in entryBuf might need escaping */
	if(!(tempBuf = (SS_UTF8_T *)malloc(2 * (NSSCS_MAX_SECRET_BUF_LEN - SSCS_CRED_SET_LEN))))
	{
		return;
	}

	memset(tempBuf, 0, 2 * (NSSCS_MAX_SECRET_BUF_LEN - SSCS_CRED_SET_LEN));

	for(i = 0; i < len; i++)
	{
		SS_UTF8_T c = *((*entryBuf)+i);

		switch(c)
		{
			case (SS_UTF8_T)'\\':
				tempBuf[k++] = (SS_UTF8_T)'\\';
				tempBuf[k++] = (SS_UTF8_T)'\\';
				escaped = 1;
				break;

			 case (SS_UTF8_T)':':
				tempBuf[k++] = (SS_UTF8_T)'\\';
				tempBuf[k++] = (SS_UTF8_T)':';
				escaped = 1;
				break;

			 case (SS_UTF8_T)'=':
				tempBuf[k++] = (SS_UTF8_T)'\\';
				tempBuf[k++] = (SS_UTF8_T)'=';
				escaped = 1;
				break;

			 default:
				tempBuf[k++] = c;
		}
	}

	if(escaped) 
	{
 		memset(*entryBuf, 0, *entryBufLen);
		free (*entryBuf);
		*entryBuf = tempBuf;
		*entryBufLen = *entryBufLen + k;
		return;
	}

/* ############################### CODE EXITS HERE ############################# */

	if(tempBuf)
	{
		free(tempBuf);
	}

	return;

/* ############################### CODE ENDS HERE ############################# */
}	//* sscsshs_ChkEscapeString





/*
 * NAME - sscsshs_PopulateeSecretBuf
 *
 * DESCRIPTION
 *	 Populate the Shared Secret Buffer
 *
 */
static int32_t sscsshs_PopulateSecretBuf
(
	int32_t				type, 
	uint32_t			*kLen,
	SS_UTF8_T			*key, 
	uint32_t			*vLen,
	SS_UTF8_T			*val, 
	uint32_t			*bufLen, 
	SS_UTF8_T			*retBuffer
)
{ /* beginning of the call */
/* ############################## CODE STARTS HERE ############################ */

	if(*kLen == 0)
	{
		return(NSSCS_E_PARSER_FAILURE);  // create error stating non-Sh Sec Format key
	}

	if(*bufLen)
	{
		retBuffer[*bufLen] = (SS_UTF8_T)0x0A; // add a line feed delimiter
	}

	sscsshs_ChkEscapeString(&key, kLen);

	if(sscs_Utf8Strncmp(key, SSCS_CRED_SET, SSCS_CRED_SET_LEN))
	{
		sscs_Utf8Strncat(retBuffer, key, *kLen);
		sscs_Utf8Strncat(retBuffer, CREDSET_DELIMITER, CREDSET_DELIMITER_LEN);
		*bufLen += (CREDSET_DELIMITER_LEN + *kLen - 2);

	}
	else
	{
		if(type & SSCS_CREDENTIAL_TYPE_F)
		{		
			return(NSSCS_E_PARSER_FAILURE);  // create error stating non-Sh Sec Format key
		}

		sscs_Utf8Strncat(retBuffer, key, *kLen);
		sscs_Utf8Strncat(retBuffer, APP_DELIMITER, APP_DELIMITER_LEN);
		*bufLen += (APP_DELIMITER_LEN + *kLen - 2);
	}

	sscsshs_ChkEscapeString(&val, vLen);
	if((*bufLen + *vLen) < NSSCS_MAX_SECRET_BUF_LEN)
	{
		sscs_Utf8Strncat(retBuffer, val, *vLen);
		*bufLen = *bufLen + *vLen - 1;
		return(NSSCS_SUCCESS);
	}
	else
	{
		return(NSSCS_E_BUFFER_LEN);
	}

/* ############################### CODE ENDS HERE ############################# */
}	/* end of sscsshs_PopulateSecretBuf */



/*
 * NAME - sscsshs_PopulateBinarySecretBuf
 *
 * DESCRIPTION
 *	 Populate the Binary Shared Secret Buffer
 *
 */
static int32_t sscsshs_PopulateBinarySecretBuf
(
	int32_t				type, 
	uint32_t			*kLen, 
	SS_UTF8_T			*key,
	uint32_t			valLen, 
	uint8_t				*val,
	uint32_t			*bufLen, 
	uint8_t				*retBuffer
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	uint32_t	len = 0;

/* ############################## CODE STARTS HERE ############################ */

	if((*kLen == 0) || (*bufLen))
	{
		return(NSSCS_E_PARSER_FAILURE);  // create error stating non-Sh Sec Format key
	}									 // can't mix binary data with other data

	if(type & SSCS_BINARY_TYPE_F)
	{
		if(sscs_Utf8Strncmp(key, SSCS_BINARY_SECRET, SSCS_BINARY_CHARS))
		{
			return(NSSCS_E_PARSER_FAILURE);  // create error stating non-binary buffer
		}		

		sscsshs_ChkEscapeString(&key, kLen);	
		sscs_Utf8Strncpy((SS_UTF8_T *)retBuffer, key, *kLen);
		sscs_Utf8Strncat((SS_UTF8_T *)retBuffer, BINARY_DELIMITER, BINARY_DELIMITER_LEN);
		len = *kLen +  BINARY_DELIMITER_LEN - 1;
		*bufLen = len + valLen + sizeof(uint32_t);
		// buffer format ==> [BINARY=][binary data len(uint32_t)][binary data]
		*(uint32_t *)&retBuffer[len] = valLen;
		memcpy(&retBuffer[len + sizeof(uint32_t)], val, valLen);
	}
	else
	{
		return(NSSCS_E_PARSER_FAILURE);  // create error stating non-Sh Sec Format key
	}

	return(NSSCS_SUCCESS);

/* ############################### CODE ENDS HERE ############################# */
}	/* end of sscsshs_PopulateBinarySecretBuf */



/*
 * NAME - sscsshs_ParseBinarySecretBuf
 *
 * DESCRIPTION
 *	 Parses a Shared Secret.
 *
 */
static int32_t sscsshs_ParseBinarySecretBuf
(
	uint32_t			*kLen,
	SS_UTF8_T			*key,
	uint32_t			*valLen,
	uint8_t				*val,
	SSCS_SECRET_T		*secretBuf
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t 		len = (SHS_BINARY_LEN + BINARY_DELIMITER_LEN) - 1; // excluding one Null terminator

/* ############################## CODE STARTS HERE ############################ */

	memcpy(key, secretBuf->data, (SHS_BINARY_LEN - 1));
	if(memcmp(key, SHS_BINARY, (SHS_BINARY_LEN - 1)))
	{
		return(NSSCS_E_PARSER_FAILURE);  // create error stating non-Sh Sec Format key
	}

	*kLen = SHS_BINARY_LEN - 1;

	// get the length of the binary data out;
	*valLen = *(uint32_t *)&secretBuf[len];
	memcpy(val, &secretBuf->data[len + sizeof(uint32_t)], *valLen);

	return(NSSCS_SUCCESS);

/* ############################### CODE ENDS HERE ############################# */
}	/* end of sscsshs_sscsshs_ParseBinarySecretBuf */



/*
 * NAME - sscsshs_UnescapeSecretIDBuf
 *
 * DESCRIPTION
 *	 Parses a Shared Secret.
 *
 */
static int32_t sscsshs_UnescapeSecretIDBuf
(
	SSCS_SH_SECRET_ID_T	*	shSecID, 
	SSCS_SECRET_ID_T	*	secID 
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t 				i, rc = NSSCS_SUCCESS;
	SSCS_SECRET_ID_T		tmpSecID = {0};
	int32_t 				len = secID->len;	
	int32_t 				k = 0;
	
/* ############################## CODE STARTS HERE ############################ */

	// clear the buffers
	memset(shSecID, 0, sizeof(SSCS_SH_SECRET_ID_T));

	do
	{	// determine the type of secret
		if((sscs_Utf8Strncmp(secID->id, SSCS_CRED_SET_DELIMITED, SSCS_CRED_SET_CHARS_DELIMITED)) == 0)
		{
			shSecID->type |= SSCS_CREDENTIAL_TYPE_F;
			tmpSecID.len = SSCS_CRED_SET_CHARS_DELIMITED;
			sscs_Utf8Strncpy(tmpSecID.id, secID->id, SSCS_CRED_SET_CHARS_DELIMITED);
			break;
		}

		if((sscs_Utf8Strncmp(secID->id, SSCS_APP_SECRET_DELIMITED, SSCS_APP_SECRET_CHARS_DELIMITED)) == 0)
		{
			shSecID->type |= SSCS_APPLICATION_TYPE_F;

			tmpSecID.len = SSCS_APP_SECRET_CHARS_DELIMITED;
			sscs_Utf8Strncpy(tmpSecID.id, secID->id, SSCS_APP_SECRET_CHARS_DELIMITED);
			break;
		}

		if((sscs_Utf8Strncmp(secID->id, SSCS_BINARY_SECRET_DELIMITED, SSCS_BINARY_CHARS_DELIMITED)) == 0)
		{
			shSecID->type |= SSCS_BINARY_TYPE_F;
			tmpSecID.len = SSCS_BINARY_CHARS_DELIMITED;
			sscs_Utf8Strncpy(tmpSecID.id, secID->id, SSCS_BINARY_CHARS_DELIMITED);
			break;
		}

		return(NSSCS_E_WRONG_SH_SEC_TYPE);
	}
	while(1);

	// start passed the tag
	for(k = i = tmpSecID.len; i < len; i++)
	{
		rc = NSSCS_SUCCESS;
		if(secID->id[i] == (SS_UTF8_T)'\\')
		{
			if(i + 1 < len)
			{
				if(secID->id[i + 1] == (SS_UTF8_T)'\\' 
					|| secID->id[i + 1] == (SS_UTF8_T)'=' 
					|| secID->id[i + 1] == (SS_UTF8_T)':')
				{
					tmpSecID.id[k++] = secID->id[i + 1];
					i++;
				}
			}
			else
			{
				tmpSecID.id[k] = secID->id[i];
			}
		}
		else
		{
			tmpSecID.id[k++] = secID->id[i];
		}
	} // end for ...

	shSecID->len = tmpSecID.len + k - 1;
	sscs_Utf8Strncpy(shSecID->name, tmpSecID.id, shSecID->len);
//	shSecID->len = k;

	return(rc);

/* ############################### CODE ENDS HERE ############################# */
}	/* end of sscsshs_UnescapeSecretIDBuf */




/*
 * NAME - sscs_UnescapeString
 *
 * DESCRIPTION
 *	 Parses a string.
 *
 */
static int32_t sscs_UnescapeString
(
	uint8_t		*val, 
	uint32_t	*valueLen
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	uint32_t 	k,i = 0;
	uint32_t 	len = 0;
	uint8_t 	*temp; 
	uint32_t 	rc = NSSCS_SUCCESS;

/* ############################## CODE STARTS HERE ############################ */

	len = *valueLen;
	temp = malloc(len+1);	
	if(temp)
	{
		for(k = i = 0; i < len; i++)
		{
			rc = NSSCS_SUCCESS;
			if(val[i] == (SS_UTF8_T)'\\')
			{
				if(i + 1 < len)
				{
					if(val[i + 1] == (SS_UTF8_T)'\\' 
						|| val[i + 1] == (SS_UTF8_T)'=' 
						|| val[i + 1] == (SS_UTF8_T)':')
					{
						temp[k++] = val[i + 1];
						i++;
					}
				}
				else
				{
					temp[k] = val[i];
				}
			}
			else
			{
				temp[k++] = val[i];
			}
		} // end for ...

		temp[k] = '\0';
		*valueLen = k+1;
		sscs_Utf8Strncpy(val, temp, *valueLen);

		memset(temp, 0, *valueLen);
		free(temp);
		return rc;	
	}	
	else
	{
		return NSSCS_E_PARSER_FAILURE;				
	}

/* ############################### CODE ENDS HERE ############################# */
}	/* end of sscs_UnescapeString */



/*
 * NAME - sscsshs_ParseSecretBuf
 *
 * DESCRIPTION
 *	 Parses a Shared Secret.
 *
 */
static int32_t sscsshs_ParseSecretBuf
(
	int32_t					*index, 
	int32_t					type, 
	int32_t					*keyLen,
	SS_UTF8_T				*key,
	int32_t					*valLen,
	SS_UTF8_T				*val,
	SSCS_SECRET_T			*secretBuf
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t 		i, rc;
	int32_t 		len = secretBuf->len;	
	SS_UTF8_T		*secBuf = (SS_UTF8_T *)(secretBuf->data);
	int32_t 		delimiterIsFound = FALSE;
	int32_t 		k = 0;
	
/* ############################## CODE STARTS HERE ############################ */

	// if we've exhausted the buffer, get out.
	if(*index >= len)
	{ 
		return(NSSCS_E_OBJECT_NOT_FOUND);
	}

	//* extract the key
	for(i = *index; i < len; i++)
	{
		rc = NSSCS_SUCCESS;
		if(secBuf[i] == (SS_UTF8_T)'\\')
		{
			if(i + 1 < len)
			{
				if(secBuf[i + 1] == (SS_UTF8_T)'\\' 
					|| secBuf[i + 1] == (SS_UTF8_T)'=' 
					|| secBuf[i + 1] == (SS_UTF8_T)':')
				{
					key[k] = secBuf[i + 1];
					k++;
					i++;
				}
			}
		}
		else if(secBuf[i] == (SS_UTF8_T)'=' 
			|| secBuf[i] == (SS_UTF8_T)':')
		{
			if(type & SSCS_APPLICATION_TYPE_F)
			{
				if(secBuf[i] == (SS_UTF8_T)':')
				{
					delimiterIsFound = TRUE;
					i++;
					break;
				}
				else if(secBuf[i] == (SS_UTF8_T)'=')
				{
					rc = NSSCS_E_PARSER_FAILURE;
					return(rc);
				}
			}
			else if(type & SSCS_CREDENTIAL_TYPE_F)
			{
				if(secBuf[i] == (SS_UTF8_T)'=')
				{
					delimiterIsFound = TRUE;
					i++;
					break;
				}
				else if(secBuf[i] == (SS_UTF8_T)':')
				{

					rc = NSSCS_E_PARSER_FAILURE;
					return(rc);
				}
			}
		}

		else if(secBuf[i] == (SS_UTF8_T)0x0A) // if the line feed delimiter is found
		{
			i++;
			rc = NSSCS_SUCCESS;
			break;
		}
		else
		{
			key[k] = secBuf[i];
			k++;
		}
	}

	*keyLen = k+1;
	*index = i;

	// extract the value
	if(delimiterIsFound)
	{
		int32_t k = 0;
		for(i = *index; i < len; i++)
		{
			rc = NSSCS_SUCCESS;
			if(secBuf[i] == (SS_UTF8_T)'\\')
			{
				if((i + 1) < len)
				{
					if(secBuf[i+1] == (SS_UTF8_T)'\\' || 
						secBuf[i+1] == (SS_UTF8_T)'=' || 
						secBuf[i+1] == (SS_UTF8_T)':')
					{
						val[k] = secBuf[i + 1];
						k++;
						i++;
					}
				}
			}
			else if(secBuf[i] == (SS_UTF8_T)'=' || 
				secBuf[i] == (SS_UTF8_T)':')
			{
				if(type & SSCS_APPLICATION_TYPE_F)
				{
					if(secBuf[i] == (SS_UTF8_T)':')
					{
						val[k] = secBuf[i];
						k++;
						i++;
						val[k] = secBuf[i];
						k++;
					}
					else if(secBuf[i] == (SS_UTF8_T)'=')
					{
						if(secBuf[i-1] == (SS_UTF8_T)'\\')
						{
							val[k] = secBuf[i];
							k++;
						}
						else
						{
							rc = NSSCS_E_PARSER_FAILURE;
							return(NSSCS_E_PARSER_FAILURE);
						}
					}
				}
				else if(type & SSCS_CREDENTIAL_TYPE_F)
				{
					if(secBuf[i] == (SS_UTF8_T)'=')
					{
						val[k] = secBuf[i];
						k++;
						i++;
						val[k] = secBuf[i];
						k++;
					}
					else if(secBuf[i] == (SS_UTF8_T)':')
					{
						if(secBuf[i-1] == (SS_UTF8_T)'\\')
						{
							val[k] = secBuf[i];
							k++;
						}
						else
						{
							rc = NSSCS_E_PARSER_FAILURE;
							return(NSSCS_E_PARSER_FAILURE);
						}
					}
				}
			}

			else if(secBuf[i] == (SS_UTF8_T)0x0A) // if the line feed delimiter is found
			{
				i++;
				rc = NSSCS_SUCCESS;
				break;
			}
			else
			{
				val[k] = secBuf[i];
				k++;
			}
		}

		*valLen = k+1;
	}
	
	
	*index = i;
	return(rc);

/* ############################### CODE ENDS HERE ############################# */
}	/* end of sscsshs_ParseSecretBuf */




/* ########################################################################## */
/* ################ SECRETSTORE CLIENT SERVICE SDK CALLS #################### */
/* ########################################################################## */


/*
 * NAME - miCASAOpenSecretStoreCache
 *
 * DESCRIPTION
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL_PTR(void)
miCASAOpenSecretStoreCache 
(
	SSCS_SECRETSTORE_T		*	ssid,
	uint32_t			 		ssFlags, 
	SSCS_EXT_T				*	ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	SSCS_CONTEXT_T				*storeContext = NULL;
	SSCS_SECRETSTORE_INFO_T 	ssInfo = {0};
	SSCS_KEYCHAIN_ID_T			kc = {0};
	SSCS_KEYCHAIN_ID_LIST_T		*kcIDList = NULL;
	uint32_t					bytesRequired = 0;
 	SSCS_SRCH_KEY_T				searchKey = {0}; 

/* ############################## CODE STARTS HERE ############################ */

	searchKey.srchKey[0] = NSSCS_ENUM_DELIM;
	searchKey.srchKeyLen = sizeof(NSSCS_ENUM_DELIM) + 1;
	
	if((ssid == NULL))
	{
		return(NULL);
	}
	else
	{
		// set to default for now
		sscs_Utf8Strncpy(ssid->ssName, SSCS_DEFAULT_SECRETSTORE_ID, SSCS_DEFAULT_SECRETSTORE_ID_LEN);
		ssid->version = NSSCS_VERSION_NUMBER;
	}

 
	//* allocate the context
	if((storeContext = (SSCS_CONTEXT_T *)malloc(sizeof(SSCS_CONTEXT_T))) == NULL)
	{
		return(NULL);
	}
	else
	{
		memset(storeContext, 0, sizeof(SSCS_CONTEXT_T));
	}

	//* open the SecretStore to initialize the handle to it
	if((storeContext->ssHandle = sscs_CacheOpenSecretStore(ssid, ssFlags, NULL)) == NULL)
	{
		goto errorLevel1;
	}

	if(sscs_CacheGetSecretStoreInfo(storeContext->ssHandle, ssFlags, &ssInfo, NULL))
	{
		goto errorLevel1;
	}

	if((kcIDList = (SSCS_KEYCHAIN_ID_LIST_T *)malloc(sizeof(SSCS_KEYCHAIN_ID_LIST_T))) == NULL)
	{
		goto errorLevel1;
	}

	memset(kcIDList, 0, sizeof(SSCS_KEYCHAIN_ID_LIST_T));

	if(ssInfo.numKeyChains)
	{
		if((kcIDList->keyChainIDList = (SSCS_KEYCHAIN_ID_T *)
			malloc(sizeof(SSCS_KEYCHAIN_ID_T) *  ssInfo.numKeyChains)) == NULL)
		{
			goto errorLevel2;
		}

		memset(kcIDList->keyChainIDList, 0, (sizeof(SSCS_KEYCHAIN_ID_T) *  ssInfo.numKeyChains));
		
		kcIDList->returnedIDs = ssInfo.numKeyChains;
		kcIDList->enumHandle = 1;
		if(sscs_CacheEnumerateKeychainIDs(storeContext->ssHandle, ssFlags, &searchKey, 
					kcIDList, NULL))
		{
			goto errorLevel3;
		}

		storeContext->kcids = kcIDList;
	}
	else
	{
		// for now
		ssInfo.numKeyChains = NSSCS_MAX_NUM_OF_DEFAULT_KEYCHAINS;
		if((kcIDList->keyChainIDList = (SSCS_KEYCHAIN_ID_T *)
			malloc(sizeof(SSCS_KEYCHAIN_ID_T) *  ssInfo.numKeyChains)) == NULL)
		{
			goto errorLevel2;
		}

		memset(kcIDList->keyChainIDList, 0, (sizeof(SSCS_KEYCHAIN_ID_T) *  ssInfo.numKeyChains));
		
		kcIDList->returnedIDs = ssInfo.numKeyChains;
		kcIDList->enumHandle = 0;
		// create the default Keychains
		// For Phase one only add 
		ssFlags |= SSCS_SESSION_KEY_CHAIN_F; 

		sscs_Utf8Strncpy(kc.keychainID, SSCS_SESSION_KEY_CHAIN_ID, SSCS_S_KC_ID_CHARS);
		kc.len = SSCS_S_KC_ID_CHARS;
		if(sscs_CacheAddKeychain(storeContext->ssHandle, ssFlags, &kc, NULL))
		{
			goto errorLevel2;
		}
	}

/* ############################### CODE EXITS HERE ############################# */
 
	return(storeContext);

	errorLevel3:
		if(kcIDList->keyChainIDList)
		{
			free(kcIDList->keyChainIDList);
		}

	errorLevel2:
		if(kcIDList)
		{
			free(kcIDList);
		}

	errorLevel1:
		free(storeContext);
		return(NULL);

/* ########################## CODE ENDS HERE ##################### */
} //* end of miCASAOpenSecretStoreCache




/*
 * NAME - miCASACloseSecretStoreCache 
 *
 * DESCRIPTION
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASACloseSecretStoreCache 
(
	void			*	context, 
	uint32_t			ssFlags, 
	SSCS_EXT_T		*	ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t				rc = NSSCS_SUCCESS;
	SSCS_CONTEXT_T		*storeContext = (SSCS_CONTEXT_T *)context; 

/* ############################## CODE STARTS HERE ############################ */
 
	if(context == NULL)
	{
		return(NSSCS_E_INVALID_PARAM);
	}

	if(storeContext->ssHandle)
	{
		rc = sscs_CacheCloseSecretStore(storeContext->ssHandle, ssFlags, NULL);
	}

	if(storeContext->kcids)
	{
		if(storeContext->kcids->keyChainIDList)
		{
			free(storeContext->kcids->keyChainIDList);
		}

		free(storeContext->kcids);
	}


	free(context);

	return(rc);

/* ########################## CODE ENDS HERE ##################### */
} //* end of miCASACloseSecretStoreCache




/*
 * NAME - miCASAReadSecret
 *
 * DESCRIPTION
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASAReadSecret
(
	void				*	context,
	SSCS_KEYCHAIN_ID_T	*	keyChainID, 
	uint32_t				ssFlags, 
	void				*	secretHandle, 
	SSCS_SH_SECRET_ID_T	*	sharedSecretID, 
	SSCS_PASSWORD_T		*	epPassword, 
	SSCS_READEXT_T		*	readData, 
	SSCS_EXT_T			*	ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t				rc = 0, index = 0, escNameLen = 0;
	SSCS_SECRET_ID_T	secretID = {0};
	SS_UTF8_T			*escapedSHSName = NULL, *key = NULL;
	SSCS_SECRET_T		secBuf = {0};
	uint8_t				*val = NULL;
	uint32_t			vLen = 0, kLen = 0;
	uint32_t			bytesRequired = 0;
	SSCS_CONTEXT_T		*storeContext = (SSCS_CONTEXT_T *)context; 
										  
/* ############################## CODE STARTS HERE ############################ */

	// readData and epPassword are optional parameters
	if((context == NULL) || (secretHandle == NULL) || (keyChainID == NULL) || 
				(sharedSecretID == NULL))
	{
		return(NSSCS_E_INVALID_PARAM);
	}

	if((key = (SS_UTF8_T *) malloc(NSSCS_MAX_SECRET_ID_LEN)) == NULL)
	{
		return(NSSCS_E_SYSTEM_FAILURE);
	}

	if((secBuf.data = (uint8_t *) malloc(NSSCS_MAX_SECRET_BUF_LEN)) == NULL)
	{
		rc = NSSCS_E_SYSTEM_FAILURE;
		goto errorLevel5;
	}

	secBuf.len = NSSCS_MAX_SECRET_BUF_LEN;

	if((val = (uint8_t *) malloc(NSSCS_MAX_SECRET_BUF_LEN)) == NULL) 
	{
		rc = NSSCS_E_SYSTEM_FAILURE;
		goto errorLevel4;
	}

	secretID.len = NSSCS_MAX_SECRET_ID_LEN;
	if((escapedSHSName = (SS_UTF8_T *) malloc(NSSCS_MAX_SECRET_ID_LEN)) == NULL) 
	{
		rc = NSSCS_E_SYSTEM_FAILURE;
		goto errorLevel2;
	}

	memset(key, 0, NSSCS_MAX_SECRET_ID_LEN);
	memset(val, 0, NSSCS_MAX_SECRET_BUF_LEN);
	memset(secBuf.data, 0, NSSCS_MAX_SECRET_BUF_LEN);
	memset(secretID.id, 0, NSSCS_MAX_SECRET_ID_LEN);
	memset(escapedSHSName, 0, NSSCS_MAX_SECRET_ID_LEN);

	// escape delimited characters
	if(sharedSecretID->len > NSSCS_MAX_SECRET_ID_LEN)
	{
		rc = NSSCS_E_BUFFER_LEN;
		goto errorLevel1;
	}

	memcpy(escapedSHSName, sharedSecretID->name, sharedSecretID->len);
	escNameLen = sharedSecretID->len;
	sscsshs_ChkEscapeString(&escapedSHSName, &escNameLen);
		
	if(escNameLen < 1)
	{
		rc = NSSCS_E_SECRET_ID_TOO_SHORT;
		goto errorLevel1;
	}

	if(SSCS_APPLICATION_TYPE_F & sharedSecretID->type)
	{
		sscs_Utf8Strncpy((SS_UTF8_T *)secretID.id, SSCS_APP_SECRET_DELIMITED, SSCS_APP_SECRET_CHARS_DELIMITED);
		sscs_Utf8Strncat((SS_UTF8_T *)secretID.id, (SS_UTF8_T *)escapedSHSName, escNameLen);
		
		secretID.len = SSCS_APP_SECRET_CHARS_DELIMITED + escNameLen - 1;
	}
	else if(SSCS_CREDENTIAL_TYPE_F & sharedSecretID->type)
	{
		sscs_Utf8Strncpy((SS_UTF8_T *)secretID.id, SSCS_CRED_SET_DELIMITED, SSCS_CRED_SET_CHARS_DELIMITED);
		sscs_Utf8Strncat((SS_UTF8_T *)secretID.id, (SS_UTF8_T *)escapedSHSName, escNameLen);

		secretID.len = SSCS_CRED_SET_CHARS_DELIMITED + escNameLen - 1;
	}
	else if(SSCS_BINARY_TYPE_F & sharedSecretID->type)
	{
		sscs_Utf8Strncpy((SS_UTF8_T *)secretID.id, SSCS_BINARY_SECRET_DELIMITED, SSCS_BINARY_CHARS_DELIMITED);
		sscs_Utf8Strcat((SS_UTF8_T *)secretID.id, (SS_UTF8_T *)escapedSHSName);

		secretID.len = SSCS_BINARY_CHARS_DELIMITED + escNameLen - 1;
	}
	else
	{
		rc = NSSCS_E_NOT_SUPPORTED;
		goto errorLevel1;
	}

	if(rc = sscs_CacheReadSecret(storeContext->ssHandle, ssFlags, keyChainID, &secretID, &secBuf, 
						epPassword, &bytesRequired, readData))
	{
		goto errorLevel1;
	}

	if(SSCS_BINARY_TYPE_F & sharedSecretID->type)
	{
		if((rc = sscsshs_ParseBinarySecretBuf(&kLen, key, &vLen, val, &secBuf)) == NSSCS_SUCCESS)
		{
			rc = sscsshs_AddSHSBinaryEntry((LL_LINKLIST_T *)secretHandle, kLen, key, vLen, val);
		}
	}
	else
	{
		while ((rc = sscsshs_ParseSecretBuf(&index, sharedSecretID->type, &kLen, key, &vLen, (SS_UTF8_T *)val, &secBuf)) == NSSCS_SUCCESS)
		{
			if(rc = sscsshs_AddSHSEntry((LL_LINKLIST_T *)secretHandle, kLen, key, vLen, val))
			{
				goto errorLevel1;
			}

			memset(key, 0, NSSCS_MAX_SECRET_ID_LEN);
			memset(val, 0, NSSCS_MAX_SECRET_BUF_LEN);
		}

		// did we exhaust the buffer?
		if(rc == NSSCS_E_OBJECT_NOT_FOUND)
		{
			rc = NSSCS_SUCCESS;
		}
	}		

/* ############################### CODE EXITS HERE ############################# */

errorLevel1:
	if(escapedSHSName)
	{
		memset(escapedSHSName, 0, NSSCS_MAX_SECRET_ID_LEN);
		free(escapedSHSName);
	}

errorLevel2:
	if(secretID.id)
	{
		memset(secretID.id, 0, NSSCS_MAX_SECRET_ID_LEN);
	}

	if(secBuf.data)
	{
		memset(secBuf.data, 0, NSSCS_MAX_SECRET_BUF_LEN);
		free(secBuf.data);
	}

errorLevel4:
	if(val)
	{
		memset(val, 0, NSSCS_MAX_SECRET_BUF_LEN);
		free(val);
	}

errorLevel5:
	if(key)
	{
		memset(key, 0, NSSCS_MAX_SECRET_ID_LEN);
		free(key);
	}

	return(rc); 

/* ############################### CODE ENDS HERE ############################# */
} //* end of miCASAReadSecret




/*
 * NAME - miCASARemoveSecret
 *
 * DESCRIPTION
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASARemoveSecret
(
	void				*	context,
	SSCS_KEYCHAIN_ID_T	*	keyChainID, 
	uint32_t				ssFlags, 
	SSCS_SH_SECRET_ID_T	*	sharedSecretID,
	SSCS_PASSWORD_T		*	epPassword, 
	SSCS_EXT_T			*	ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t				rc = 0, index = 0;
	uint32_t			escNameLen = 0;
	SSCS_SECRET_ID_T	secretID = {0};
	SS_UTF8_T			*escapedSHSName = NULL, *key = NULL;
	uint8_t				*val = NULL;
	SSCS_CONTEXT_T		*storeContext = (SSCS_CONTEXT_T *)context; 

/* ############################## CODE STARTS HERE ############################ */

	if((context == NULL) || (keyChainID == NULL) || (sharedSecretID == NULL))
	{
		return(NSSCS_E_INVALID_PARAM);
	}
 
	if((key = (SS_UTF8_T *) malloc(NSSCS_MAX_SECRET_ID_LEN)) == NULL)
	{
		return(NSSCS_E_SYSTEM_FAILURE);
	}

	if((val = (uint8_t *) malloc(NSSCS_MAX_SECRET_BUF_LEN)) == NULL) 
	{
		rc = NSSCS_E_SYSTEM_FAILURE;
		goto errorLevel4;
	}

	secretID.len = NSSCS_MAX_SECRET_ID_LEN;

	if((escapedSHSName = (SS_UTF8_T *) malloc(NSSCS_MAX_SECRET_ID_LEN)) == NULL) 
	{
		rc = NSSCS_E_SYSTEM_FAILURE;
		goto errorLevel2;
	}

	memset(key, 0, NSSCS_MAX_SECRET_ID_LEN);
	memset(val, 0, NSSCS_MAX_SECRET_BUF_LEN);
	memset(secretID.id, 0, NSSCS_MAX_SECRET_ID_LEN);
	memset(escapedSHSName, 0, NSSCS_MAX_SECRET_ID_LEN);

	// escape delimited characters
	if(sharedSecretID->len > NSSCS_MAX_SECRET_ID_LEN)
	{
		rc = NSSCS_E_BUFFER_LEN;
		goto errorLevel1;
	}

	memcpy(escapedSHSName, sharedSecretID->name, sharedSecretID->len);
	escNameLen = sharedSecretID->len;
	sscsshs_ChkEscapeString(&escapedSHSName, &escNameLen);
		
	if(escNameLen < 1)
	{
		rc = NSSCS_E_SECRET_ID_TOO_SHORT;
		goto errorLevel1;
	}

	if(SSCS_APPLICATION_TYPE_F & sharedSecretID->type)
	{
		sscs_Utf8Strncpy((SS_UTF8_T *)secretID.id, SSCS_APP_SECRET_DELIMITED, SSCS_APP_SECRET_CHARS_DELIMITED);
		sscs_Utf8Strncat((SS_UTF8_T *)secretID.id, (SS_UTF8_T *)escapedSHSName, escNameLen);
		
		secretID.len = SSCS_APP_SECRET_CHARS_DELIMITED + escNameLen - 1;
	}
	else if(SSCS_CREDENTIAL_TYPE_F & sharedSecretID->type)
	{
		sscs_Utf8Strncpy((SS_UTF8_T *)secretID.id, SSCS_CRED_SET_DELIMITED, SSCS_CRED_SET_CHARS_DELIMITED);
		sscs_Utf8Strncat((SS_UTF8_T *)secretID.id, (SS_UTF8_T *)escapedSHSName, escNameLen);

		secretID.len = SSCS_CRED_SET_CHARS_DELIMITED + escNameLen - 1;
	}
	else if(SSCS_BINARY_TYPE_F & sharedSecretID->type)
	{
		sscs_Utf8Strncpy((SS_UTF8_T *)secretID.id, SSCS_BINARY_SECRET_DELIMITED, SSCS_BINARY_CHARS_DELIMITED);
		sscs_Utf8Strcat((SS_UTF8_T *)secretID.id, (SS_UTF8_T *)escapedSHSName);

		secretID.len = SSCS_BINARY_CHARS_DELIMITED + escNameLen - 1;
	}
	else
	{
		rc = NSSCS_E_NOT_SUPPORTED;
		goto errorLevel1;
	}

	rc = sscs_CacheRemoveSecret(storeContext->ssHandle, ssFlags, keyChainID, 
					&secretID, epPassword, NULL);


/* ############################### CODE EXITS HERE ############################# */

errorLevel1:
	if(escapedSHSName)
	{
		memset(escapedSHSName, 0, NSSCS_MAX_SECRET_ID_LEN);
		free(escapedSHSName);
	}

errorLevel2:
	memset(secretID.id, 0, NSSCS_MAX_SECRET_ID_LEN);

	if(val)
	{
		memset(val, 0, NSSCS_MAX_SECRET_BUF_LEN);
		free(val);
	}

errorLevel4:
	if(key)
	{
		memset(key, 0, NSSCS_MAX_SECRET_ID_LEN);
		free(key);
	}

	return(rc); 

/* ########################## CODE ENDS HERE ##################### */
} //* end of miCASARemoveSecret




/*
 * NAME - miCASAWriteSecret
 *
 * DESCRIPTION
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASAWriteSecret
(
	void				*	context,
	SSCS_KEYCHAIN_ID_T	*	keyChainID, 
	uint32_t				ssFlags, 
	void				*	secretHandle, 
	SSCS_SH_SECRET_ID_T	*	sharedSecretID, 
	SSCS_PASSWORD_T		*	epPassword, 
	SSCS_EXT_T			*	ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t					rc = 0,	sidLen = 0, index = 0;
	uint32_t				vLen = 0, escNameLen = 0, kLen = 0;
	SSCS_SECRET_ID_T		secretID = {0};
	SS_UTF8_T				*escapedSHSName = NULL, *key = NULL;
	SSCS_SECRET_T			secBuf = {0};
	uint8_t					*val = NULL;
	SSCS_CONTEXT_T			*storeContext = (SSCS_CONTEXT_T *)context; 
										  
/* ############################## CODE STARTS HERE ############################ */

	// readData and epPassword are optional parameters
	if((context == NULL) || (secretHandle == NULL) || (keyChainID == NULL) || 
				(sharedSecretID == NULL))
	{
		return(NSSCS_E_INVALID_PARAM);
	}

	if((key = (SS_UTF8_T *) malloc(NSSCS_MAX_SECRET_ID_LEN)) == NULL)
	{
		return(NSSCS_E_SYSTEM_FAILURE);
	}

	if((secBuf.data = (uint8_t *) malloc(NSSCS_MAX_SECRET_BUF_LEN + 
					sizeof((LL_LINKLIST_T*)secretHandle + sizeof(SSCS_SH_SECRET_ID_T)))) == NULL)
	{
		rc = NSSCS_E_SYSTEM_FAILURE;
		goto errorLevel5;
	}

	if((val = (uint8_t *) malloc(NSSCS_MAX_SECRET_BUF_LEN)) == NULL) 
	{
		rc = NSSCS_E_SYSTEM_FAILURE;
		goto errorLevel4;
	}

	secretID.len = NSSCS_MAX_SECRET_ID_LEN;

	if((escapedSHSName = (SS_UTF8_T *) malloc(NSSCS_MAX_SECRET_ID_LEN)) == NULL) 
	{
		rc = NSSCS_E_SYSTEM_FAILURE;
		goto errorLevel2;
	}

	memset(key, 0, NSSCS_MAX_SECRET_ID_LEN);
	memset(val, 0, NSSCS_MAX_SECRET_BUF_LEN);
	memset(secBuf.data, 0, NSSCS_MAX_SECRET_BUF_LEN +
				sizeof((LL_LINKLIST_T *)secretHandle + sizeof(SSCS_SH_SECRET_ID_T)));
	
	memset(secretID.id, 0, NSSCS_MAX_SECRET_ID_LEN);
	memset(escapedSHSName, 0, NSSCS_MAX_SECRET_ID_LEN);

	// escape delimited characters
	if(sharedSecretID->len > NSSCS_MAX_SECRET_ID_LEN)
	{
		rc = NSSCS_E_BUFFER_LEN;
		goto errorLevel1;
	}

	memcpy(escapedSHSName, sharedSecretID->name, sharedSecretID->len);
	escNameLen = sharedSecretID->len;
	sscsshs_ChkEscapeString(&escapedSHSName, &escNameLen);
		
	if(escNameLen < 1)
	{
		rc = NSSCS_E_SECRET_ID_TOO_SHORT;
		goto errorLevel1;
	}

	if(SSCS_APPLICATION_TYPE_F & sharedSecretID->type)
	{
		sscs_Utf8Strncpy((SS_UTF8_T *)secretID.id, SSCS_APP_SECRET_DELIMITED, SSCS_APP_SECRET_CHARS_DELIMITED);
		sscs_Utf8Strncat((SS_UTF8_T *)secretID.id, (SS_UTF8_T *)escapedSHSName, escNameLen);
		
		secretID.len = SSCS_APP_SECRET_CHARS_DELIMITED + escNameLen - 1;
	}
	else if(SSCS_CREDENTIAL_TYPE_F & sharedSecretID->type)
	{
		sscs_Utf8Strncpy((SS_UTF8_T *)secretID.id, SSCS_CRED_SET_DELIMITED, SSCS_CRED_SET_CHARS_DELIMITED);
		sscs_Utf8Strncat((SS_UTF8_T *)secretID.id, (SS_UTF8_T *)escapedSHSName, escNameLen);

		secretID.len = SSCS_CRED_SET_CHARS_DELIMITED + escNameLen - 1;
	}
	else if(SSCS_BINARY_TYPE_F & sharedSecretID->type)
	{
		sscs_Utf8Strncpy((SS_UTF8_T *)secretID.id, SSCS_BINARY_SECRET_DELIMITED, SSCS_BINARY_CHARS_DELIMITED);
		sscs_Utf8Strcat((SS_UTF8_T *)secretID.id, (SS_UTF8_T *)escapedSHSName);

		secretID.len = SSCS_BINARY_CHARS_DELIMITED + escNameLen - 1;
	}
	else
	{
		rc = NSSCS_E_NOT_SUPPORTED;
		goto errorLevel1;
	}

	secBuf.len = 0;
	if(sharedSecretID->type & SSCS_BINARY_TYPE_F)
	{
		if(!(sscsshs_GetNextSHSEntry(1, (LL_LINKLIST_T *)secretHandle, &kLen, key, &vLen, (char *)val)))
		{
			if(rc = sscsshs_PopulateBinarySecretBuf(sharedSecretID->type, &kLen, key, vLen, val, &secBuf.len, secBuf.data))
			{
				goto errorLevel1;
			}
		}
		else
		{
			rc = NSSCS_E_SH_SECRET_FAILURE;
			goto errorLevel1;
		}
	}
	else
	{
		// get each entry and do a write to SecretStore
		if((rc = sscsshs_GetNextSHSEntry(1, (LL_LINKLIST_T *)secretHandle, &kLen, 
					key, &vLen, (char *)val)) == NSSCS_SUCCESS)
		{
			if(kLen > 2)
			{
				if(rc = sscsshs_PopulateSecretBuf(sharedSecretID->type, &kLen, key, &vLen, (SS_UTF8_T *)val, 
								&secBuf.len, (SS_UTF8_T *)secBuf.data))
				{
					goto errorLevel1;
				}
			}
				
			memset(key, 0, NSSCS_MAX_SECRET_ID_LEN);
			memset(val, 0, NSSCS_MAX_SECRET_BUF_LEN);
		
			while((rc = sscsshs_GetNextSHSEntry(0, (LL_LINKLIST_T *)secretHandle, &kLen, 
						key, &vLen, (char *)val)) == NSSCS_SUCCESS)
			{
				if(kLen > 2)
				{
					if(rc = sscsshs_PopulateSecretBuf(sharedSecretID->type, &kLen, key, &vLen, (SS_UTF8_T *)val, 
								&secBuf.len, (SS_UTF8_T *)secBuf.data))
					{
						goto errorLevel1;
					}
				}

				memset(key, 0, NSSCS_MAX_SECRET_ID_LEN);
				memset(val, 0, NSSCS_MAX_SECRET_BUF_LEN);
			}

			if((secBuf.data == NULL) || (secBuf.len == 0))
			{
				rc = NSSCS_E_SH_SECRET_FAILURE;
				goto errorLevel1;
			}
		}
	}
	
	rc = sscs_CacheWriteSecret(storeContext->ssHandle, ssFlags, keyChainID, &secretID, &secBuf, epPassword, ext);

/* ############################### CODE EXITS HERE ############################# */

errorLevel1:
	if(escapedSHSName)
	{
		memset(escapedSHSName, 0, NSSCS_MAX_SECRET_ID_LEN);
		free(escapedSHSName);
	}

errorLevel2:
	memset(secretID.id, 0, NSSCS_MAX_SECRET_ID_LEN);

	if(secBuf.data)
	{
		memset(secBuf.data, 0, NSSCS_MAX_SECRET_BUF_LEN +
				sizeof((LL_LINKLIST_T*)secretHandle + sizeof(SSCS_SH_SECRET_ID_T)))	;
		free(secBuf.data);
	}

errorLevel4:
	if(val)
	{
		memset(val, 0, NSSCS_MAX_SECRET_BUF_LEN);
		free(val);
	}

errorLevel5:
	if(key)
	{
		memset(key, 0, NSSCS_MAX_SECRET_ID_LEN);
		free(key);
	}

	return(rc); 

/* ############################### CODE ENDS HERE ############################# */
} //* end of miCASAWriteSecret


/*
 * NAME - miCASAWriteKey
 *
 * DESCRIPTION
 * NOTE: This assume a SS_CREDSET SecretType
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASAWriteKey
(
	void				*	context,	
	uint32_t				ssFlags, 
	SSCS_KEYCHAIN_ID_T	*	keyChainID, 	
	SSCS_SECRET_ID_T	*	sharedSecretID,
	SS_UTF8_T           *	key,
	uint32_t                keyLen,
	uint8_t             *	val,
	uint32_t                valLen,	
	SSCS_PASSWORD_T		*	epPassword, 
	SSCS_EXT_T			*	ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t					rc = 0,	sidLen = 0, index = 0;
	uint32_t				escNameLen = 0;
	SSCS_SECRET_ID_T		secretID = {0};
	SS_UTF8_T				*escapedSHSName = NULL;	
	SS_UTF8_T				*escapedSHSKey = NULL;	
	SS_UTF8_T				*escapedSHSValue = NULL;	
	SSCS_CONTEXT_T		*	storeContext = (SSCS_CONTEXT_T *)context; 
										  
/* ############################## CODE STARTS HERE ############################ */

	// readData and epPassword are optional parameters
	if((context == NULL) || (keyChainID == NULL) || (sharedSecretID == NULL)
		|| (key == NULL) || (val == NULL) || (valLen == 0)) 
	{
		return(NSSCS_E_INVALID_PARAM);
	}
	
	if(sharedSecretID->len > NSSCS_MAX_SECRET_ID_LEN/4)
	{
		return(NSSCS_E_BUFFER_LEN);		
	}

	if ((keyLen > NSSCS_MAX_SECRET_ID_LEN/4) || (valLen > NSSCS_MAX_SECRET_BUF_LEN/4))
	{
		return(NSSCS_E_BUFFER_LEN);
	}
	

	if((escapedSHSName = (SS_UTF8_T *) malloc(NSSCS_MAX_SECRET_ID_LEN)) == NULL) 
	{
		rc = NSSCS_E_SYSTEM_FAILURE;
		goto errorLevel2;
	}
	
	if((escapedSHSKey = (SS_UTF8_T *) malloc(NSSCS_MAX_SECRET_ID_LEN)) == NULL) 
	{
		rc = NSSCS_E_SYSTEM_FAILURE;
		goto errorLevel1;
	}

	if((escapedSHSValue = (SS_UTF8_T *) malloc(NSSCS_MAX_SECRET_BUF_LEN)) == NULL) 
	{
		rc = NSSCS_E_SYSTEM_FAILURE;
		goto errorLevel1;
	}


	memset(secretID.id, 0, NSSCS_MAX_SECRET_ID_LEN);
	memset(escapedSHSName, 0, NSSCS_MAX_SECRET_ID_LEN);
	memset(escapedSHSKey, 0, NSSCS_MAX_SECRET_ID_LEN);
	memset(escapedSHSValue, 0, NSSCS_MAX_SECRET_BUF_LEN);
	
	// escape delimited characters
	memcpy(escapedSHSName, sharedSecretID->id, sharedSecretID->len);
	escNameLen = sharedSecretID->len;
	sscsshs_ChkEscapeString(&escapedSHSName, &escNameLen);

	// escape delimited characters
	memcpy(escapedSHSKey, key, keyLen);
	sscsshs_ChkEscapeString(&escapedSHSKey, &keyLen);

	// escape delimited characters
	memcpy(escapedSHSValue, val, valLen);
	sscsshs_ChkEscapeString(&escapedSHSValue, &valLen);
		
	if(escNameLen < 1)
	{
		rc = NSSCS_E_SECRET_ID_TOO_SHORT;
		goto errorLevel1;
	}

	// convert to a SSCS_CRED_SET
	sscs_Utf8Strncpy((SS_UTF8_T *)secretID.id, SSCS_CRED_SET_DELIMITED, SSCS_CRED_SET_CHARS_DELIMITED);
	sscs_Utf8Strncat((SS_UTF8_T *)secretID.id, (SS_UTF8_T *)escapedSHSName, escNameLen);
	secretID.len = SSCS_CRED_SET_CHARS_DELIMITED + escNameLen - 1;
	
	//rc = sscs_CacheWriteSecret(storeContext->ssHandle, ssFlags, keyChainID, &secretID, &secBuf, epPassword, ext);
	// -1 to prevent the null from being cached in micasad


	rc = sscs_CacheWriteKey(storeContext->ssHandle, 
							ssFlags, 
							keyChainID, 
							&secretID, 
							escapedSHSKey,
							keyLen-1,			// NOTE: micasad not saving NULL on key and value
							escapedSHSValue, 
							valLen-1,			// NOTE: micasad not saving NULL on key and value
							epPassword, 
							ext);

/* ############################### CODE EXITS HERE ############################# */

errorLevel1:
	if(escapedSHSName)
	{
		memset(escapedSHSName, 0, NSSCS_MAX_SECRET_ID_LEN);
		free(escapedSHSName);
	}

	if(escapedSHSKey)
	{
		memset(escapedSHSKey, 0, NSSCS_MAX_SECRET_ID_LEN);			
		free(escapedSHSKey);
	}

	if(escapedSHSValue)
	{
		memset(escapedSHSValue, 0, NSSCS_MAX_SECRET_BUF_LEN);			
		free(escapedSHSValue);
	}


errorLevel2:
	memset(secretID.id, 0, NSSCS_MAX_SECRET_ID_LEN);

	return(rc); 

/* ############################### CODE ENDS HERE ############################# */
} //* end of miCASAWriteKey


/*
 * NAME - miCASAWriteBinaryKey
 *
 * DESCRIPTION
 * NOTE: This assume a SS_CREDSET SecretType
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASAWriteBinaryKey
(
	void				*	context,	
	uint32_t				ssFlags, 
	SSCS_KEYCHAIN_ID_T	*	keyChainID, 	
	SSCS_SECRET_ID_T	*	sharedSecretID,
    SS_UTF8_T           *	key,
    uint32_t                keyLen,
    uint8_t             *	val,
    uint32_t            *   valLen,	
	SSCS_PASSWORD_T		*	epPassword, 
	SSCS_EXT_T			*	ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t					rc = 0,	sidLen = 0, index = 0;
	uint32_t				escNameLen = 0;
	SSCS_SECRET_ID_T		secretID = {0};
	SS_UTF8_T				*escapedSHSName = NULL;	
	SS_UTF8_T				*escapedSHSKey = NULL;	
	//SS_UTF8_T				*escapedSHSValue = NULL;	
	SSCS_CONTEXT_T		*	storeContext = (SSCS_CONTEXT_T *)context; 
										  
/* ############################## CODE STARTS HERE ############################ */

	// readData and epPassword are optional parameters
	if((context == NULL) || (keyChainID == NULL) || (sharedSecretID == NULL)
		|| (key == NULL) || (val == NULL) || (valLen == 0)) 
	{
		return(NSSCS_E_INVALID_PARAM);
	}
	
	if(sharedSecretID->len > NSSCS_MAX_SECRET_ID_LEN/4)
	{
		return(NSSCS_E_BUFFER_LEN);		
	}

	if ((keyLen > NSSCS_MAX_SECRET_ID_LEN/4) || (*valLen > NSSCS_MAX_SECRET_BUF_LEN/4))
	{
		return(NSSCS_E_BUFFER_LEN);
	}


	if((escapedSHSName = (SS_UTF8_T *) malloc(NSSCS_MAX_SECRET_ID_LEN)) == NULL) 
	{
		rc = NSSCS_E_SYSTEM_FAILURE;
		goto errorLevel2;
	}
	
	if((escapedSHSKey = (SS_UTF8_T *) malloc(NSSCS_MAX_PASSCODE_LEN)) == NULL) 
	{
		rc = NSSCS_E_SYSTEM_FAILURE;
		goto errorLevel1;
	}

	memset(secretID.id, 0, NSSCS_MAX_SECRET_ID_LEN);
	memset(escapedSHSName, 0, NSSCS_MAX_SECRET_ID_LEN);
	memset(escapedSHSKey, 0, NSSCS_MAX_PASSCODE_LEN);
		
	// escape delimited characters
	if(sharedSecretID->len > NSSCS_MAX_SECRET_ID_LEN)
	{
		rc = NSSCS_E_BUFFER_LEN;
		goto errorLevel1;
	}

	memcpy(escapedSHSName, sharedSecretID->id, sharedSecretID->len);
	escNameLen = sharedSecretID->len;
	sscsshs_ChkEscapeString(&escapedSHSName, &escNameLen);

	memcpy(escapedSHSKey, key, keyLen);
	sscsshs_ChkEscapeString(&escapedSHSKey, &keyLen);
		
	if(escNameLen < 1)
	{
		rc = NSSCS_E_SECRET_ID_TOO_SHORT;
		goto errorLevel1;
	}

	// convert to a SSCS_CRED_SET
	sscs_Utf8Strncpy((SS_UTF8_T *)secretID.id, SSCS_CRED_SET_DELIMITED, SSCS_CRED_SET_CHARS_DELIMITED);
	sscs_Utf8Strncat((SS_UTF8_T *)secretID.id, (SS_UTF8_T *)escapedSHSName, escNameLen);
	secretID.len = SSCS_CRED_SET_CHARS_DELIMITED + escNameLen - 1;
	
	//rc = sscs_CacheWriteSecret(storeContext->ssHandle, ssFlags, keyChainID, &secretID, &secBuf, epPassword, ext);
	// -1 to prevent the null from being cached in micasad


	rc = sscs_CacheWriteBinaryKey(storeContext->ssHandle, 
							ssFlags, 
							keyChainID, 
							&secretID, 
							escapedSHSKey,
							escNameLen, 
							val,
							*valLen,
							epPassword, 
							ext);

/* ############################### CODE EXITS HERE ############################# */

errorLevel1:
	if(escapedSHSName)
	{
		memset(escapedSHSName, 0, NSSCS_MAX_SECRET_ID_LEN);
		free(escapedSHSName);
	}

	if(escapedSHSKey)
	{
		memset(escapedSHSKey, 0, NSSCS_MAX_SECRET_ID_LEN);			
		free(escapedSHSKey);
	}	

errorLevel2:
	memset(secretID.id, 0, NSSCS_MAX_SECRET_ID_LEN);
	return(rc); 

/* ############################### CODE ENDS HERE ############################# */
} //* end of miCASAWriteBinaryKey




/*
 * NAME - miCASAReadKey
 *
 * DESCRIPTION
 * NOTE: This assume a SS_CREDSET SecretType
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASAReadKey
(
	void				*	context,	
	uint32_t				ssFlags, 
	SSCS_KEYCHAIN_ID_T	*	keyChainID, 	
	SSCS_SECRET_ID_T	*	sharedSecretID,
    SS_UTF8_T			*	key,
    uint32_t				keyLen,
    uint8_t				*	val,
    uint32_t			*   valLen,	
	SSCS_PASSWORD_T		*	epPassword, 
	uint32_t			*   bytesRequired,
	SSCS_EXT_T			*	ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t					rc = 0,	sidLen = 0, index = 0;
	uint32_t				escNameLen = 0;
	SSCS_SECRET_ID_T		secretID = {0};
	SS_UTF8_T				*escapedSHSName = NULL;	
	SS_UTF8_T				*escapedSHSKey = NULL;		
	SSCS_CONTEXT_T			*storeContext = (SSCS_CONTEXT_T *)context; 
										  
/* ############################## CODE STARTS HERE ############################ */

	// readData and epPassword are optional parameters
	if((context == NULL) || (keyChainID == NULL) || (sharedSecretID == NULL) || (key == NULL))
	{
		return(NSSCS_E_INVALID_PARAM);
	}

	if(sharedSecretID->len > NSSCS_MAX_SECRET_ID_LEN/4)
	{
		return(NSSCS_E_BUFFER_LEN);		
	}

	if (keyLen > NSSCS_MAX_SECRET_ID_LEN/4)
	{
		return(NSSCS_E_BUFFER_LEN);
	}
	
	if((escapedSHSName = (SS_UTF8_T *) malloc(NSSCS_MAX_SECRET_ID_LEN)) == NULL) 
	{
		rc = NSSCS_E_SYSTEM_FAILURE;
		goto errorLevel2;
	}
	
	if((escapedSHSKey = (SS_UTF8_T *) malloc(NSSCS_MAX_SECRET_ID_LEN)) == NULL) 
	{
		rc = NSSCS_E_SYSTEM_FAILURE;
		goto errorLevel1;
	}

	memset(secretID.id, 0, NSSCS_MAX_SECRET_ID_LEN);
	memset(escapedSHSName, 0, NSSCS_MAX_SECRET_ID_LEN);
	memset(escapedSHSKey, 0, NSSCS_MAX_SECRET_ID_LEN);	
	
	// escape delimited characters
	if(sharedSecretID->len > NSSCS_MAX_SECRET_ID_LEN)
	{
		rc = NSSCS_E_BUFFER_LEN;
		goto errorLevel1;
	}

	memcpy(escapedSHSName, sharedSecretID->id, sharedSecretID->len);
	escNameLen = sharedSecretID->len;
	sscsshs_ChkEscapeString(&escapedSHSName, &escNameLen);

	memcpy(escapedSHSKey, key, keyLen);
	sscsshs_ChkEscapeString(&escapedSHSKey, &keyLen);	
		
	if(escNameLen < 1)
	{
		rc = NSSCS_E_SECRET_ID_TOO_SHORT;
		goto errorLevel1;
	}

	// convert to a SSCS_CRED_SET
	sscs_Utf8Strncpy((SS_UTF8_T *)secretID.id, SSCS_CRED_SET_DELIMITED, SSCS_CRED_SET_CHARS_DELIMITED);
	sscs_Utf8Strncat((SS_UTF8_T *)secretID.id, (SS_UTF8_T *)escapedSHSName, escNameLen);
	secretID.len = SSCS_CRED_SET_CHARS_DELIMITED + escNameLen - 1;
	
	rc = sscs_CacheReadKey(storeContext->ssHandle, 
								ssFlags, 
								keyChainID, 
								&secretID, 
								escapedSHSKey,
								keyLen-1,   // NOTE: micasad not saving NULL on key and value
								val,
								valLen,		// NOTE: micasad not saving NULL on key and value					
								epPassword, 
								bytesRequired,
								ext);
	
	if(rc == NSSCS_SUCCESS)
	{				
		sscs_UnescapeString(val, valLen);		
	}

/* ############################### CODE EXITS HERE ############################# */

errorLevel1:
	if(escapedSHSName)
	{
		memset(escapedSHSName, 0, NSSCS_MAX_SECRET_ID_LEN);
		free(escapedSHSName);
	}

	if(escapedSHSKey)
	{
		memset(escapedSHSKey, 0, NSSCS_MAX_SECRET_ID_LEN);			
		free(escapedSHSKey);
	}

errorLevel2:
	memset(secretID.id, 0, NSSCS_MAX_SECRET_ID_LEN);

	return(rc); 

/* ############################### CODE ENDS HERE ############################# */
} //* end of miCASAReadKey

/*
 * NAME - miCASAReadBinaryKey
 *
 * DESCRIPTION
 * NOTE: This assume a SS_CREDSET SecretType
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASAReadBinaryKey
(
	void				*	context,	
	uint32_t				ssFlags, 
	SSCS_KEYCHAIN_ID_T	*	keyChainID, 	
	SSCS_SECRET_ID_T	*	sharedSecretID,
    SS_UTF8_T           *	key,
    uint32_t                keyLen,
    uint8_t             *	val,
    uint32_t            *   valLen,	
	SSCS_PASSWORD_T		*	epPassword, 
	uint32_t			*   bytesRequired,
	SSCS_EXT_T			*	ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t					rc = 0,	sidLen = 0, index = 0;
	uint32_t				escNameLen = 0;
	SSCS_SECRET_ID_T		secretID = {0};
	SS_UTF8_T				*escapedSHSName = NULL;	
	SS_UTF8_T				*escapedSHSKey = NULL;		
	SSCS_CONTEXT_T		*	storeContext = (SSCS_CONTEXT_T *)context; 
										  
/* ############################## CODE STARTS HERE ############################ */

	// readData and epPassword are optional parameters
	if((context == NULL) || (keyChainID == NULL) || (sharedSecretID == NULL) || (key == NULL))
	{
		return(NSSCS_E_INVALID_PARAM);
	}

	if(sharedSecretID->len > NSSCS_MAX_SECRET_ID_LEN/4)
	{
		return(NSSCS_E_BUFFER_LEN);		
	}

	if (keyLen > NSSCS_MAX_SECRET_ID_LEN/4)
	{
		return(NSSCS_E_BUFFER_LEN);
	}


	if((escapedSHSName = (SS_UTF8_T *) malloc(NSSCS_MAX_SECRET_ID_LEN)) == NULL) 
	{
		rc = NSSCS_E_SYSTEM_FAILURE;
		goto errorLevel2;
	}
	
	if((escapedSHSKey = (SS_UTF8_T *) malloc(NSSCS_MAX_SECRET_ID_LEN)) == NULL) 
	{
		rc = NSSCS_E_SYSTEM_FAILURE;
		goto errorLevel1;
	}

	memset(secretID.id, 0, NSSCS_MAX_SECRET_ID_LEN);
	memset(escapedSHSName, 0, NSSCS_MAX_SECRET_ID_LEN);
	memset(escapedSHSKey, 0, NSSCS_MAX_SECRET_ID_LEN);	
	
	memcpy(escapedSHSName, sharedSecretID->id, sharedSecretID->len);
	escNameLen = sharedSecretID->len;
	sscsshs_ChkEscapeString(&escapedSHSName, &escNameLen);

	memcpy(escapedSHSKey, key, keyLen);
	sscsshs_ChkEscapeString(&escapedSHSKey, &keyLen);	
		
	if(escNameLen < 1)
	{
		rc = NSSCS_E_SECRET_ID_TOO_SHORT;
		goto errorLevel1;
	}

	// convert to a SSCS_CRED_SET
	sscs_Utf8Strncpy((SS_UTF8_T *)secretID.id, SSCS_CRED_SET_DELIMITED, SSCS_CRED_SET_CHARS_DELIMITED);
	sscs_Utf8Strncat((SS_UTF8_T *)secretID.id, (SS_UTF8_T *)escapedSHSName, escNameLen);
	secretID.len = SSCS_CRED_SET_CHARS_DELIMITED + escNameLen - 1;
	
	rc = sscs_CacheReadBinaryKey(storeContext->ssHandle, 
								ssFlags, 
								keyChainID, 
								&secretID, 
								escapedSHSKey,
								keyLen, 
								val,
								valLen,							
								epPassword, 
								bytesRequired,
								ext);

/* ############################### CODE EXITS HERE ############################# */

errorLevel1:
	if(escapedSHSName)
	{
		memset(escapedSHSName, 0, NSSCS_MAX_SECRET_ID_LEN);
		free(escapedSHSName);
	}

	if(escapedSHSKey)
	{
		memset(escapedSHSKey, 0, NSSCS_MAX_SECRET_ID_LEN);			
		free(escapedSHSKey);
	}

errorLevel2:
	memset(secretID.id, 0, NSSCS_MAX_SECRET_ID_LEN);

	return(rc); 

/* ############################### CODE ENDS HERE ############################# */
} //* end of miCASAReadBinaryKey



/*
 * NAME - miCASAGetStoreInfomaion 
 *
 * DESCRIPTION
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASAGetStoreInformation 
(
	void					*	context, 
	uint32_t					ssFlags, 
	SSCS_SECRETSTORE_INFO_T	*	ssInfo,
	SSCS_EXT_T				*	ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t					rc = 0;
	SSCS_CONTEXT_T			*storeContext = (SSCS_CONTEXT_T *)context; 

/* ############################## CODE STARTS HERE ############################ */

	if((context == NULL) || (ssInfo == NULL))
	{
		return(NSSCS_E_INVALID_PARAM);
	}

	return(sscs_CacheGetSecretStoreInfo(storeContext, ssFlags, ssInfo, NULL));
 
/* ########################## CODE ENDS HERE ##################### */
} //* end of miCASAGetStoreInfomaion 




/*
 * NAME - miCASAEnumerateSecretIDs 
 *
 * DESCRIPTION
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASAEnumerateSecretIDs 
(
	void						*	context, 
	SSCS_KEYCHAIN_ID_T			*	keyChainID, 
	uint32_t						ssFlags, 
	SSCS_SRCH_KEY_T				*	searchKey, 
	SSCS_SH_SECRET_ID_LIST_T	*	secretIDList, 
	SSCS_EXT_T					*	ext
)
{ /* beginning of the call */										   
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t							rc = NSSCS_SUCCESS;
	uint32_t				 i;
	SSCS_CONTEXT_T				*storeContext = (SSCS_CONTEXT_T *)context;
	SSCS_SECRET_ID_LIST_T		intSecIDList = {0}; 

/* ############################## CODE STARTS HERE ############################ */
 
	if((context == NULL) || (keyChainID == NULL) || (secretIDList == NULL))
	{
		secretIDList->enumHandle = 0;
		return(NSSCS_E_INVALID_PARAM);
	}

	if((secretIDList->returnedIDs == 0))
	{
		secretIDList->enumHandle = 0;
		return(NSSCS_E_INVALID_PARAM);
	}

	// enumeration handle should be set to false by the cache after we are done
	//secretIDList->enumHandle = 1;

	if((intSecIDList.secIDList = 
		(SSCS_SECRET_ID_T *)malloc(sizeof(SSCS_SECRET_ID_T) * secretIDList->returnedIDs)) == NULL)
	{
		secretIDList->enumHandle = 0;
		return(NSSCS_E_SYSTEM_FAILURE);
	}
	else
	{
		// initialzie the arrary
		memset(intSecIDList.secIDList, 0, (sizeof(SSCS_SECRET_ID_T) * secretIDList->returnedIDs));
		intSecIDList.enumHandle = secretIDList->enumHandle;		
		intSecIDList.returnedIDs = secretIDList->returnedIDs;		
	}

	// check the search key and escape it here


	if(rc = sscs_CacheEnumerateSecretIDs(storeContext->ssHandle, ssFlags, keyChainID, searchKey,
					&intSecIDList, NULL))
	{

		if(rc == NSSCS_E_ENUM_BUFF_TOO_SHORT)
		{
			secretIDList->returnedIDs = intSecIDList.returnedIDs; 
		}

		secretIDList->enumHandle = 0;

		goto errorLevel1;
	}

	for(secretIDList->returnedIDs = i = 0; i < intSecIDList.returnedIDs; i++)
	{
		if(sscsshs_UnescapeSecretIDBuf(&secretIDList->secIDList[i], &intSecIDList.secIDList[i]) )
		{
			// go to the next one
			continue;
		}
		else
		{
			secretIDList->returnedIDs++;
		}		
	}

	secretIDList->enumHandle = intSecIDList.enumHandle; 

/* ############################### CODE EXITS HERE ############################# */

errorLevel1:
	free(intSecIDList.secIDList);

	return(rc);

/* ########################## CODE ENDS HERE ##################### */
} //* end of miCASAEnumerateSecretIDs 





/*
 * NAME - miCASARemoveSecretStore
 *
 * DESCRIPTION
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASARemoveSecretStore 
(
	void				*	context,
	uint32_t				ssFlags, 
	SSCS_EXT_T			*	ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t					rc = 0; // need this for debugging.
	SSCS_CONTEXT_T		*storeContext = (SSCS_CONTEXT_T *)context; 

/* ############################## CODE STARTS HERE ############################ */
 
	if(storeContext == NULL)
	{
		return(NSSCS_E_INVALID_PARAM);
	}

	rc = sscs_CacheRemoveSecretStore(storeContext->ssHandle, ssFlags, NULL);
	return(rc); 

/* ########################## CODE ENDS HERE ##################### */
} //* end of miCASARemoveSecretStore





/*
 * NAME - miCASASetMasterPassword 
 *
 * DESCRIPTION
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASASetMasterPassword 
(
	uint32_t 			ssFlags, 
	SSCS_PASSWORD_T		*passwd, 
	SSCS_HINT_T			*hint, 
	SSCS_EXT_T			*ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t 				rc = 0;
    void 					*context = NULL;

    SSCS_SECRETSTORE_T		store = {0};

/* ############################## CODE STARTS HERE ############################ */

  // open secretStore
  sscs_Utf8Strncpy(store.ssName, SSCS_DEFAULT_SECRETSTORE_ID, SSCS_DEFAULT_SECRETSTORE_ID_LEN);
  store.version = 1;

  context = miCASAOpenSecretStoreCache(&store, ssFlags, NULL);

  if((context == NULL) || (passwd == NULL))
  {
      return(NSSCS_E_INVALID_PARAM);
  }

  rc = sscs_SetMasterPassword(((SSCS_CONTEXT_T*)context)->ssHandle, passwd, hint, NULL);
  // close the secretstore
  miCASACloseSecretStoreCache(context, ssFlags, NULL);

  return(rc);

/* ########################## CODE ENDS HERE ##################### */
} //* end of miCASASetMasterPassword 





/*
 * NAME - miCASAUnlockSecrets 
 *
 * DESCRIPTION
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASAUnlockSecrets 
(
   void				*	context, 
   uint32_t				ssFlags, 
   SSCS_PASSWORD_T	*	password, 
   SSCS_EXT_T       *	ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

/* ############################## CODE STARTS HERE ############################ */
 
	return(NSSCS_E_NOT_IMPLEMENTED);

/* ############################### CODE EXITS HERE ############################# */

/* ########################## CODE ENDS HERE ##################### */
} //* end of miCASAUnlockSecrets 



/*
 * NAME - miCASALockStore 
 *
 * DESCRIPTION
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASALockStore
(
   void				*	context, 
   uint32_t				ssFlags, 
   SSCS_EXT_T         *	ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t					rc;
	SSCS_CONTEXT_T		*storeContext = (SSCS_CONTEXT_T *)context; 

/* ############################## CODE STARTS HERE ############################ */
 
	if(context == NULL)
	{
		return(NSSCS_E_INVALID_PARAM);
	}

	rc = sscs_LockCache(storeContext->ssHandle, ssFlags, NULL);
	return(rc);

/* ########################## CODE ENDS HERE ##################### */
} //* end of miCASALockStore 



/*
 * NAME - miCASAUnlockStore
 *
 * DESCRIPTION
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASAUnlockStore
(
	void				*	context, 
	uint32_t				ssFlags, 
	SSCS_PASSCODE_T		*	passcode,
	SSCS_EXT_T			*	ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t					rc;
	SSCS_CONTEXT_T			*storeContext = (SSCS_CONTEXT_T *)context; 

/* ############################## CODE STARTS HERE ############################ */
 
	if(context == NULL)
	{
		return(NSSCS_E_INVALID_PARAM);
	}

	rc = sscs_UnlockCache(storeContext->ssHandle, ssFlags, passcode, NULL);
	return(rc);

/* ########################## CODE ENDS HERE ##################### */
} //* end of miCASAUnlockStore 



/*
 * NAME - miCASARemoveKeyChain
 *
 * DESCRIPTION
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASARemoveKeyChain 
(
	void				*	context,
	uint32_t				ssFlags, 
	SSCS_KEYCHAIN_ID_T	*	keyChainID, 
	SSCS_EXT_T			*	ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t					rc = 0;
	SSCS_CONTEXT_T		*storeContext = (SSCS_CONTEXT_T *)context; 

/* ############################## CODE STARTS HERE ############################ */
 
	if((context == NULL) || (keyChainID == NULL))
	{
		return(NSSCS_E_INVALID_PARAM);
	}

	rc = sscs_CacheRemoveKeychain(storeContext, ssFlags, keyChainID, NULL);
	return(rc);

/* ########################## CODE ENDS HERE ##################### */
} //* end of miCASARemoveKeyChain


/*
 * NAME - miCASAEnumerteKeyChainIDs
 *
 * DESCRIPTION
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASAEnumerateKeyChainIDs 
(
	void					*	context,
	uint32_t					ssFlags, 
	SSCS_SRCH_KEY_T			*	searchKey,
	SSCS_KEYCHAIN_ID_LIST_T	*	kcIDList,
	SSCS_EXT_T				*	ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t					rc = 0;
	SSCS_CONTEXT_T		*storeContext = (SSCS_CONTEXT_T *)context; 

/* ############################## CODE STARTS HERE ############################ */
 
	if((context == NULL) || (kcIDList == NULL))
	{
		return(NSSCS_E_INVALID_PARAM);
	}

	rc = sscs_CacheEnumerateKeychainIDs(storeContext, ssFlags, searchKey, kcIDList, NULL);
	return(rc);

/* ########################## CODE ENDS HERE ##################### */
} //* end of miCASAEnumerateKeyChainIDs



/*
 * NAME - miCASAAddKeyChain
 *
 * DESCRIPTION
 *	
 *		   
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASAAddKeyChain 
(
	void				*	context,
	uint32_t				ssFlags, 
	SSCS_KEYCHAIN_ID_T	*	keyChainID, 
	SSCS_EXT_T			*	ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t					rc = 0;
	SSCS_CONTEXT_T		*storeContext = (SSCS_CONTEXT_T *)context; 

/* ############################## CODE STARTS HERE ############################ */
 
	if((context == NULL) || (keyChainID == NULL))
	{
		return(NSSCS_E_INVALID_PARAM);
	}

	rc = sscs_CacheAddKeychain(storeContext, ssFlags, keyChainID, NULL);
	return(rc);

/* ########################## CODE ENDS HERE ##################### */
} //* end of miCASAAddKeyChain



/* ########################################################################## */
/* ############ SECRETSTORE CLIENT SHARED SECRET SUPPORT CALLS ############## */
/* ########################################################################## */

/*
 * NAME - miCASA_CreateSHSHandle
 *
 * DESCRIPTION
 *	 Create a parser list handle for a Shared Secret.
 *
 */
SSCS_GLOBAL_LIBCALL_PTR(void)
miCASA_CreateSHSHandle()
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	LL_LINKLIST_T		*newList;

/* ############################## CODE STARTS HERE ############################ */

	if((newList = (LL_LINKLIST_T *)(malloc(NSSCS_MAX_SECRET_BUF_LEN))))
	{
		memset(newList, 0, NSSCS_MAX_SECRET_BUF_LEN);
		newList->elemCount = 0;
		newList->head = NULL;
		newList->clp = NULL;

		return(newList);
	}
	else
	{
		return(NULL);
	}

/* ############################### CODE ENDS HERE ############################# */
}	//* end of miCASA_CreateSHSHandle





/*
 * NAME - miCASA_DestorySHSHandle
 *
 * DESCRIPTION
 *	 Destroys a parser list handle for a Shared Secrets.
 *
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASA_DestroySHSHandle(void *secretHandle)
{ /* beginning of the call */
/* ############################## CODE STARTS HERE ############################ */

	if(secretHandle)
	{
		ll_DestroyList((LL_LINKLIST_T *)secretHandle);

		free(secretHandle);

		return(NSSCS_SUCCESS);
	}
	else
	{
		return(NSSCS_E_SYSTEM_FAILURE);
	}

/* ############################### CODE ENDS HERE ############################# */
}	//* end of miCASA_DestroySHSHandle





/*
 * NAME - miCASA_GetNextSHSEntry
 *
 * DESCRIPTION
 *	 Gets the next entry in the parser list for a Shared Secret.
 *
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASA_GetNextSHSEntry
(
	int32_t 		restart, 
	void 			*secretHandle, 
	uint32_t		*keyLen,
	SS_UTF8_T		*key, 
	uint32_t		*valLen,
	uint8_t			*val
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	LL_SHSEC_KEY_VAL_T		*keyVal = {0};
	int32_t					n = 0;

/* ############################## CODE STARTS HERE ############################ */

	if(secretHandle)
	{
		if(restart)
		{
			ll_Head((LL_LINKLIST_T *)secretHandle);
		}
		else
		{
			if(!(ll_Next((LL_LINKLIST_T *)secretHandle)))
			{
				return(NSSCS_E_LL_SYS_FAILURE); 
			}
		}

		if(keyVal = (LL_SHSEC_KEY_VAL_T *)ll_GetEntry((LL_LINKLIST_T *)secretHandle))
		{
			if(keyVal->kLen > 1)
			{
				*keyLen = keyVal->kLen;
				sscs_Utf8Strncpy(key, keyVal->key, *keyLen);
				*valLen = keyVal->vLen;
				// if binary value just copy
				memcpy(val, keyVal->value, keyVal->vLen);

				for(n = 0; n < (int32_t)*keyLen - 2; n++)
				{
					if(key[n] != 63)
					{
						break;
					}
					else
					{
						if(n == (int32_t)*keyLen - 3)
						{
							return(NSSCS_E_SH_SECRET_FAILURE);
						}
					}
				}

				return(NSSCS_SUCCESS);
			}
		}

		return(NSSCS_SUCCESS); 

	}
	else
	{
		return(NSSCS_E_LL_SYS_FAILURE); 
	}

/* ############################### CODE ENDS HERE ############################# */
}	//* end of miCASA_GetNextSHSEntry





/*
 * NAME - miCASA_AddSHSEntry
 *
 * DESCRIPTION
 *	 Adds a new entry in the parser list for a Shared Secret.
 *
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASA_AddSHSEntry
(
	void			*secretHandle,
	uint32_t		keyLen,
	SS_UTF8_T		*key,
	uint32_t		valueLen,
	uint8_t			*value
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t			rc = NSSCS_LL_SUCCESS;

/* ############################## CODE STARTS HERE ############################ */
	
	if((keyLen) && (secretHandle))
	{
		if(ll_InsertSharedSecretLink((LL_LINKLIST_T*)secretHandle, 
					keyLen, key, valueLen, value))
		{
			return(NSSCS_E_LL_SYS_FAILURE);
		}
		else
		{
			return(NSSCS_LL_SUCCESS);
		}
	}
	else
	{
		return(NSSCS_E_LL_SYS_FAILURE);
	}
	
/* ############################### CODE ENDS HERE ############################# */
}	//* end of miCASA_AddSHSEntry






/*
 * NAME - miCASA_RemoveSHSEntry
 *
 * DESCRIPTION
 *	 Removes a Shared Secret.
 *
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASA_RemoveSHSEntry
(
	void 				*secretHandle,
	uint32_t			keyLen,
	SS_UTF8_T			*key, 
	uint32_t			valueLen,
	uint8_t				*value
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t				rc;

/* ############################## CODE STARTS HERE ############################ */

	return(rc = ll_RemoveSharedSecretLink((LL_LINKLIST_T*)secretHandle, keyLen, key));

/* ############################### CODE ENDS HERE ############################# */
}	//* end of miCASA_RemoveSHSEntry



/* ##################################################################################### */
/* ######################### INTERNAL MANAGED CODE STARTS HERE ######################### */
/* ##################################################################################### */


static int32_t sscsshs_GetUsernamePassword
(
	void 					*secretHandle, 
	SSCS_BASIC_CREDENTIAL	*basicCred
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t				rcode = 0;
	int32_t				userFound = 0, passFound = 0;
	SS_UTF8_T			*key = NULL;
	uint8_t				*value = NULL;
	uint32_t			unkLen = 0;
	uint32_t			kLen = 0;
	uint32_t			vLen = 0;
	
	SS_UTF8_T 			*usernameKeyname; // = SSCS_USERNAME_OTHER;
	
/* ############################## CODE STARTS HERE ############################ */

	if((value = (uint8_t *)malloc(NSSCS_MAX_SECRET_BUF_LEN)) == NULL)
	{
		return NSSCS_E_INVALID_SECRET_ID;
	}

	if((key = (SS_UTF8_T *)malloc(NSSCS_MAX_SECRET_ID_LEN)) == NULL)
	{
		free(value);
		return NSSCS_E_INVALID_SECRET_ID;				
	}

	// determine username key name, ie CN, LDAPDN, etc
	if(basicCred->unFlags & USERNAME_TYPE_NDS_DN_F)
	{
		usernameKeyname = SHS_DN_NDAP;
		unkLen = SHS_DNNDAP_LEN;
	}
	else if(basicCred->unFlags & USERNAME_TYPE_NDS_FDN_F)
	{
		usernameKeyname = SHS_FDN_NDAP;
		unkLen = SHS_FDNNDAP_LEN;
	}
	else if(basicCred->unFlags & USERNAME_TYPE_LDAP_DN_F)
	{
		usernameKeyname = SHS_DN_LDAP;
		unkLen = SHS_DNLDAP_LEN;
	}
	else if(basicCred->unFlags & USERNAME_TYPE_EMAIL_F)
	{
		usernameKeyname = SHS_EMAIL;
		unkLen = SHS_EMAIL_LEN;
	}
	else if(basicCred->unFlags & USERNAME_TYPE_OTHER_F)
	{
		usernameKeyname = SHS_OTHER;
		unkLen = SHS_OTHER_LEN;
	}
	else
	{
		usernameKeyname = SHS_CN;
		unkLen = SHS_CN_LEN;
	}

	// enumerate this list looking for username and password			
	if(!(rcode = miCASA_GetNextSHSEntry(1, secretHandle, &kLen, key, &vLen, value)))
	{
		do
		{
			if(kLen == 0)
			{
				break;
			}

			if(!sscs_Utf8Strncmp(key, usernameKeyname, unkLen))
			{
				userFound = 1;
				sscs_Utf8Strncpy((SS_UTF8_T *)basicCred->username, (SS_UTF8_T *)value, vLen);
				basicCred->unLen = vLen;
			}

			if(!sscs_Utf8Strncmp(key, SHS_PASSWORD, SHS_PASSWORD_LEN))
			{
				passFound = 1;
				sscs_Utf8Strncpy((SS_UTF8_T *)basicCred->password, (SS_UTF8_T *)value, vLen);
				basicCred->pwordLen = vLen;
			}

			if(userFound && passFound)
			{
				break;
			}
							
			// clear the buffers							
			memset(key, 0, NSSCS_MAX_SECRET_ID_LEN);
			memset(value, 0, NSSCS_MAX_SECRET_BUF_LEN);

			rcode = miCASA_GetNextSHSEntry(0, secretHandle, &kLen, key, &vLen, value);
		}
		while(rcode == NSSCS_SUCCESS);
	}


	memset(key, 0, NSSCS_MAX_SECRET_ID_LEN);
	free(key);
	memset(value, 0, NSSCS_MAX_SECRET_BUF_LEN);
	free(value);

	if(userFound && passFound)
	{
		return NSSCS_SUCCESS;
	}
	else
	{
		return NSSCS_E_INVALID_SECRET_ID;
	}

/* ############################### CODE ENDS HERE ############################# */
} // end of sscsshs_GetUsernamePassword




/*
 * NAME - sscsshs_GetCredSetName
 *
 * DESCRIPTION
 *	 Internal function that adds a new entry in the parser list for a Shared Secret.
 *
 */
static int32_t sscsshs_GetCredSetName
(
	void 		  	*secretHandle,
	uint32_t		*credSetNameLen, 
	uint8_t 		*credSetName
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int32_t				rcode = 0;	
	SS_UTF8_T			*key = NULL;
	uint8_t				*value = NULL;
	uint32_t			kLen = 0;
	uint32_t			vLen = 0;

/* ############################## CODE STARTS HERE ############################ */

	if((value = (uint8_t *)malloc(NSSCS_MAX_SECRET_BUF_LEN)) == NULL)
	{
		return NSSCS_E_INVALID_SECRET_ID;
	}

	if((key = (SS_UTF8_T *)malloc(NSSCS_MAX_SECRET_ID_LEN)) == NULL)
	{
		free(value);
		return NSSCS_E_INVALID_SECRET_ID;				
	}

	// enumerate this list looking for username and password			
	if(!(rcode = miCASA_GetNextSHSEntry(1, secretHandle, &kLen, key, &vLen, value)))
	{
		if(kLen)
		{
			sscs_Utf8Strncpy((SS_UTF8_T *)credSetName, (SS_UTF8_T *)value, vLen);	
			*credSetNameLen = vLen;
		}
	}

	memset(key, 0, NSSCS_MAX_SECRET_ID_LEN);
	free(key);
	memset(value, 0, NSSCS_MAX_SECRET_BUF_LEN);
	free(value);

	return rcode;
	
/* ############################### CODE ENDS HERE ############################# */
} // end of sscsshs_GetCredSetName





/* ################################################################################# */
/* ############################### Managed Access APIs ############################# */
/* ################################################################################# */


/*
 * NAME - miCASAGetCredential
 *
 * DESCRIPTION
 *  There is a relationship between the appSecretID and the sharedSecretID
 *  A SS_APP secrets points to the SS_CredSet secret to be used
 *  So we'll first deal with the appSecretID as a SS_APP type
 *
 *
 *  This API gets the credential asked for
 *	1. Check the SS_App for the appSecretID passed in
 *  2. If found, use it to locate the correct Shared Secret
 *  3. If not found, use the SS_CredSet for the appSecretID if there is one
 *  4. If not found, use the SS_CredSet for the sharedSecretID passed in.
 *	5. Else return the default credential if there is one.
 *
 */

SSCS_GLOBAL_LIBCALL(int32_t)
miCASAGetCredential
(            
	uint32_t	 			ssFlags, 				// IN
	SSCS_SECRET_ID_T	*	appSecretID,			// IN
	SSCS_SECRET_ID_T	*	sharedSecretID,			// Optional IN
	uint32_t			*	credentialType,			// IN/OUT
	void				*	credential,				// OUT
	SSCS_EXT_T			*	ext						// Reserved
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */
	
	void 					*context;
	int32_t 				rcode = 0;
		
	SSCS_SECRETSTORE_T 		store = {0};
	SSCS_SH_SECRET_ID_T 	secID = {0};
	void 					*secretHandle = 0;
	SSCS_READEXT_T			readData = {0};
	SSCS_KEYCHAIN_ID_T 		kc = {0};

	SSCS_BASIC_CREDENTIAL 	*basicCred = (SSCS_BASIC_CREDENTIAL *)credential;	
	SSCS_BINARY_CREDENTIAL  *binaryCred = (SSCS_BINARY_CREDENTIAL *)credential;
	int32_t bytesRequired	= 0;
	
/* ############################## CODE STARTS HERE ############################ */
			
	// check params
	if((appSecretID == NULL) || (credential == NULL))
	{
		return(NSSCS_E_INVALID_PARAM);
	}

	if (appSecretID->len > NSSCS_MAX_SECRET_ID_LEN/4)  			
	{
		return NSSCS_E_BUFFER_LEN;
	}
	
	if ((sharedSecretID) &&	(sharedSecretID->len > NSSCS_MAX_SECRET_ID_LEN/4))
	{
		return NSSCS_E_BUFFER_LEN;
	}

	// set default keychain
	kc.len = SSCS_S_KC_ID_CHARS;
	sscs_Utf8Strncpy(kc.keychainID, SSCS_SESSION_KEY_CHAIN_ID, SSCS_S_KC_ID_CHARS);

	// open secretStore
	sscs_Utf8Strncpy(store.ssName, SSCS_DEFAULT_SECRETSTORE_ID, SSCS_DEFAULT_SECRETSTORE_ID_LEN);
	store.version = 1;
	context = miCASAOpenSecretStoreCache(&store, ssFlags, NULL);

	if(context == NULL)
	{
		return NSSCS_E_SYSTEM_FAILURE;
	}

	if(*credentialType == SSCS_CRED_TYPE_BINARY_F)
	{
		// first check appSecretID
		rcode = miCASAReadBinaryKey(
					context,	
					ssFlags, 
					&kc, 	
					appSecretID,
					binaryCred->id,
					binaryCred->idLen,
					binaryCred->data,
					binaryCred->dataLen,
					NULL,
					&bytesRequired,
					ext);

		if((rcode != NSSCS_SUCCESS) && (sharedSecretID != NULL))
		{
			// try shared if set
			rcode = miCASAReadBinaryKey(
					context,	
					ssFlags, 
					&kc, 	
					sharedSecretID,
					binaryCred->id,
					binaryCred->idLen,
					binaryCred->data,
					binaryCred->dataLen,
					NULL,
					&bytesRequired,
					ext);
		}

		miCASACloseSecretStoreCache(context, ssFlags, NULL);
		return rcode;
	}

	// create a SHS Handle
	secretHandle = miCASA_CreateSHSHandle();
	if(secretHandle == NULL)
	{
		return NSSCS_E_SYSTEM_FAILURE;
	}

	// 1&2. look up the SS_App for this secretID, if not found use the sharedSecretID	
	secID.type = SSCS_APPLICATION_TYPE_F;
	secID.len = appSecretID->len;
	sscs_Utf8Strncpy(secID.name, appSecretID->id, appSecretID->len);

	rcode = miCASAReadSecret(context, &kc, ssFlags, secretHandle, &secID, NULL, &readData, NULL);
	if(rcode == NSSCS_SUCCESS)
	{		
		// we found a link for this app which should be a SS_CredSet secretID.  
		// Get the key called SS_CredSet, it's value is the CredSet ID
		rcode = sscsshs_GetCredSetName(secretHandle, &secID.len, secID.name);
		
		if(rcode == NSSCS_SUCCESS)
		{
			if(secretHandle)
			{
				miCASA_DestroySHSHandle(secretHandle);
			}

			secretHandle = miCASA_CreateSHSHandle();

			// read credset for this app
			secID.type = SSCS_CREDENTIAL_TYPE_F;
			rcode = miCASAReadSecret(context, &kc, ssFlags, secretHandle, &secID, NULL, &readData, NULL);
			
			if(rcode == NSSCS_SUCCESS)
			{
				// read the username and password
				rcode = sscsshs_GetUsernamePassword(secretHandle, basicCred);
			}
		}							
	}

	// 3. if we still don't have a secret, try the SS_CredSet for the appSecretID
	if(rcode)
	{		
		if(secretHandle)
		{
			miCASA_DestroySHSHandle(secretHandle);
		}

		secretHandle = miCASA_CreateSHSHandle();

		// read credset for this app
		secID.type = SSCS_CREDENTIAL_TYPE_F;
		secID.len = appSecretID->len;		
		sscs_Utf8Strncpy(secID.name, appSecretID->id, secID.len);
		rcode = miCASAReadSecret(context, &kc, ssFlags, secretHandle, &secID, NULL, &readData, NULL);
		if(rcode == NSSCS_SUCCESS)
		{
			// read the username and password
			rcode = sscsshs_GetUsernamePassword(secretHandle, basicCred);
		}
	}

	// 4. if still no secret, did caller pass in a suggested sharedSecretID?
	if(rcode && sharedSecretID)
	{
		// let's look for it.
		secID.type = SSCS_CREDENTIAL_TYPE_F;
		secID.len = sharedSecretID->len;
		sscs_Utf8Strncpy(secID.name, sharedSecretID->id, secID.len);

		// get a new handle
		if(secretHandle)
		{
			miCASA_DestroySHSHandle(secretHandle);
		}

		secretHandle = miCASA_CreateSHSHandle();
		
		rcode = miCASAReadSecret(context, &kc, ssFlags, secretHandle, &secID, NULL, &readData, NULL);
		if(rcode == NSSCS_SUCCESS)
		{
			//get the username and password						
			rcode = sscsshs_GetUsernamePassword(secretHandle, basicCred);
		}		
	}

	// if we still haven't found a credential, return the default credential
	if(rcode)
	{	
		secID.type = SSCS_CREDENTIAL_TYPE_F;
		secID.len = SECRET_ID_DEFAULT_LEN;		
		sscs_Utf8Strncpy(secID.name, SECRET_ID_DEFAULT, secID.len);

		if(secretHandle)
		{
			miCASA_DestroySHSHandle(secretHandle);
		}

		secretHandle = miCASA_CreateSHSHandle();

		rcode = miCASAReadSecret(context, &kc, ssFlags, secretHandle, &secID, NULL, &readData, NULL);
		if(rcode == NSSCS_SUCCESS)
		{
			rcode = sscsshs_GetUsernamePassword(secretHandle, basicCred);
		}
	}


	if(secretHandle)
	{
		miCASA_DestroySHSHandle(secretHandle);
	}

	miCASACloseSecretStoreCache(context, ssFlags, NULL);
	return rcode;

/* ############################### CODE ENDS HERE ############################# */
} // end of miCASAGetCredential






/*
 * NAME - miCASASetCredential
 *
 * DESCRIPTION
 *  This API sets the credential 
 *	1. Check the SS_App for the appSecretID passed in
 *  2. If found, use the SS_CredSet it points to.
 *  3. If not found, use the sharedSecretID (SS_CredSet) if there is one, and it's not set yet
 *  4. Else create a credential, SS_Cred for this appSecretID
 *
 */

SSCS_GLOBAL_LIBCALL(int32_t)
miCASASetCredential
(
	uint32_t	 			ssFlags, 				// IN
	SSCS_SECRET_ID_T	*	appSecretID,			// IN
	SSCS_SECRET_ID_T	*	sharedSecretID,			// Optional IN
	uint32_t				credentialType,			// IN
	void				*	credential,				// IN
	SSCS_EXT_T			*	ext						// Reserved
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	void 					*context;
	int32_t 				rcode = 0;
	int32_t 				vLen = 0;
	
	SSCS_SECRETSTORE_T 		store = {0};
	SSCS_SH_SECRET_ID_T 	secID = {0};
	void 					*secretHandle = 0;
	SSCS_READEXT_T			readData = {0};
	SSCS_KEYCHAIN_ID_T 		kc = {0};

	SS_UTF8_T 				*usernameKeyname; // = SSCS_USERNAME_OTHER;
	uint32_t				kLen = 0;
	uint32_t				unkLen = 0;

	SSCS_CONTEXT_T			*storeContext; 
	
/* ############################## CODE STARTS HERE ############################ */

	SSCS_BASIC_CREDENTIAL *basicCred;
	SSCS_BINARY_CREDENTIAL *binaryCred;

	// check params
	if((appSecretID == NULL) || (credential == NULL))
	{
		return(NSSCS_E_INVALID_PARAM);
	}

	if (appSecretID->len > NSSCS_MAX_SECRET_ID_LEN/4)  				
	{
		return NSSCS_E_BUFFER_LEN;
	}

	if ((sharedSecretID) &&	(sharedSecretID->len > NSSCS_MAX_SECRET_ID_LEN/4))
	{
		return NSSCS_E_BUFFER_LEN;
	}



	// open secretStore
	sscs_Utf8Strncpy(store.ssName, SSCS_DEFAULT_SECRETSTORE_ID, SSCS_DEFAULT_SECRETSTORE_ID_LEN);
	store.version = 1;
	context = miCASAOpenSecretStoreCache(&store, ssFlags, NULL);

	storeContext = (SSCS_CONTEXT_T *)context;

	if(context == NULL)
	{
		return NSSCS_E_SYSTEM_FAILURE;
	}

	kc.len = SSCS_S_KC_ID_CHARS;
	sscs_Utf8Strncpy(kc.keychainID, SSCS_SESSION_KEY_CHAIN_ID, SSCS_S_KC_ID_CHARS);

	if(credentialType == SSCS_CRED_TYPE_BINARY_F)
	{
		binaryCred = (SSCS_BINARY_CREDENTIAL *)credential;

		// TODO: set shared if passed in
		

		// set apps binary key
		rcode = miCASAWriteBinaryKey(
				context,	
				ssFlags, 
				&kc, 	
				appSecretID,
				binaryCred->id,
				binaryCred->idLen,
				binaryCred->data,
				binaryCred->dataLen,
				NULL, 
				ext);

		miCASACloseSecretStoreCache(context, ssFlags, NULL);
		return rcode;

	}
	else
	{
		basicCred = (SSCS_BASIC_CREDENTIAL *)credential;				
	}

	// determine username key name, ie CN, LDAPDN, etc
	if(basicCred->unFlags & USERNAME_TYPE_NDS_DN_F)
	{
		usernameKeyname = SHS_DN_NDAP;
		unkLen = SHS_DNNDAP_LEN;
	}
	else if(basicCred->unFlags & USERNAME_TYPE_NDS_FDN_F)
	{
		usernameKeyname = SHS_FDN_NDAP;
		unkLen = SHS_FDNNDAP_LEN;
	}
	else if(basicCred->unFlags & USERNAME_TYPE_LDAP_DN_F)
	{
		usernameKeyname = SHS_DN_LDAP;
		unkLen = SHS_DNLDAP_LEN;
	}
	else if(basicCred->unFlags & USERNAME_TYPE_EMAIL_F)
	{
		usernameKeyname = SHS_EMAIL;
		unkLen = SHS_EMAIL_LEN;
	}
	else if(basicCred->unFlags & USERNAME_TYPE_OTHER_F)
	{
		usernameKeyname = SHS_OTHER;
		unkLen = SHS_OTHER_LEN;
	}
	else
	{
		usernameKeyname = SHS_CN;
		unkLen = SHS_CN_LEN;
	}

	// create a SHS Handle
	secretHandle = miCASA_CreateSHSHandle();
	if(secretHandle == NULL)
	{
		return NSSCS_E_SYSTEM_FAILURE;
	}

	// 1&2. Look up the SS_App for this secretID in case we should use an shared override, 
	// if not found use the sharedSecretID passed in.
	secID.type = SSCS_APPLICATION_TYPE_F;
	secID.len = appSecretID->len;	
	sscs_Utf8Strncpy(secID.name, appSecretID->id, secID.len);

	rcode = miCASAReadSecret(context, &kc, ssFlags, secretHandle, &secID, NULL, &readData, NULL);
	if(rcode == NSSCS_SUCCESS)
	{		
		// we found a link for this app which should be a SS_CredSet secretID.  
		// Get the key called SS_CredSet, it's value is the CredSet ID
		rcode = sscsshs_GetCredSetName(secretHandle, &secID.len, (uint8_t*)secID.name);
		
		if(rcode == NSSCS_SUCCESS)
		{
			if(secretHandle)
			{
				miCASA_DestroySHSHandle(secretHandle);
			}

			secretHandle = miCASA_CreateSHSHandle();

			// read credset for this app
			secID.type = SSCS_CREDENTIAL_TYPE_F;			
			secID.len = secID.len;			
			rcode = miCASAReadSecret(context, &kc, ssFlags, secretHandle, &secID, NULL, &readData, NULL);
						
			// set the username and password			
			vLen = basicCred->unLen; 
			miCASA_AddSHSEntry(secretHandle, unkLen, usernameKeyname, vLen, basicCred->username);

			vLen = basicCred->pwordLen; 
			miCASA_AddSHSEntry(secretHandle, SHS_PASSWORD_LEN , SHS_PASSWORD, vLen, basicCred->password);
			rcode = miCASAWriteSecret(context, &kc, ssFlags, secretHandle, &secID, NULL, ext);
		
		}							
	}

	// 3. did caller pass in a suggested sharedSecretID?
	if(rcode && sharedSecretID)
	{				
		vLen = basicCred->unLen;
		rcode = miCASAWriteKey(context, ssFlags, &kc, sharedSecretID, usernameKeyname, unkLen, basicCred->username, vLen, NULL, ext);

		vLen = basicCred->pwordLen;
		rcode = miCASAWriteKey(context, ssFlags, &kc, sharedSecretID, SHS_PASSWORD, 9, basicCred->password, vLen, NULL, ext);
	}


	// 4. Set the appSecretID at least
	if(rcode)
	{
		// write the keys
		vLen = basicCred->unLen; 
		rcode = miCASAWriteKey(context, ssFlags, &kc, appSecretID, usernameKeyname, unkLen, basicCred->username, vLen, NULL, ext);

		vLen = basicCred->pwordLen;
		rcode = miCASAWriteKey(context, ssFlags, &kc, appSecretID, SHS_PASSWORD, 9, basicCred->password, vLen, NULL, ext);
	}

	if(secretHandle)
	{
		miCASA_DestroySHSHandle(secretHandle);
	}

	miCASACloseSecretStoreCache(context, ssFlags, NULL);

	return rcode;

/* ############################### CODE ENDS HERE ############################# */
}	// end of miCASASetCredential


/*
 * NAME - miCASARemoveCredential
 *
 * DESCRIPTION
 *	 This call removes a managed credential with given the appSecretID
 *   the sharedSecretID is ignored now - TBD
 *
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASARemoveCredential
	(      		
		uint32_t	 			ssFlags, 				// IN
		SSCS_SECRET_ID_T	*	appSecretID,			// IN
		SSCS_SECRET_ID_T	*	sharedSecretID,			// Optional IN
		SSCS_EXT_T			*	ext						// Reserved
	)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */
	
	void 					*context = NULL;
	int32_t 				rcode = 0;
	int32_t 				vLen = 0;
	
	SSCS_SECRETSTORE_T 		store = {0};
	SSCS_KEYCHAIN_ID_T 		kc = {0};
	SSCS_SH_SECRET_ID_T 	secID = {0};
	
/* ############################## CODE STARTS HERE ############################ */

	if(appSecretID == NULL)
	{
		return(NSSCS_E_INVALID_PARAM);
	}

	if(appSecretID->len > NSSCS_MAX_SECRET_ID_LEN/4)
	{
		return NSSCS_E_BUFFER_LEN;
	}

	// open secretStore
	sscs_Utf8Strncpy(store.ssName, SSCS_DEFAULT_SECRETSTORE_ID, SSCS_DEFAULT_SECRETSTORE_ID_LEN);
	store.version = 1;
	context = miCASAOpenSecretStoreCache(&store, ssFlags, NULL);	
	
	if(context == NULL)
	{
		return NSSCS_E_SYSTEM_FAILURE;
	}

	// remove the secret for the appSecretID passed in
	kc.len = SSCS_S_KC_ID_CHARS;
	sscs_Utf8Strncpy(kc.keychainID, SSCS_SESSION_KEY_CHAIN_ID, SSCS_S_KC_ID_CHARS);
	
	secID.type = SSCS_CREDENTIAL_TYPE_F;
	secID.len = appSecretID->len;	
	sscs_Utf8Strncpy(secID.name, appSecretID->id, secID.len);
		
	rcode = miCASARemoveSecret (context, &kc, ssFlags, &secID, NULL, NULL);
	
	// close the secretstore
	miCASACloseSecretStoreCache(context, ssFlags, NULL);

	return(rcode);

/* ############################### CODE ENDS HERE ############################# */
}	// end of miCASARemoveCredential


/*
 * NAME - miCASASetMasterPasscode
 *
 * DESCRIPTION
 *	 This call sets the Master Passcode
 *
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASASetMasterPasscode
(
        uint32_t                         ssFlags,
        SSCS_PASSCODE_T                 *passcode,
        SSCS_EXT_T                      *ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

    int32_t 				rc = 0;
    void 					*context = NULL;

    SSCS_SECRETSTORE_T		store = {0};

/* ############################## CODE STARTS HERE ############################ */

  if(passcode == NULL)
  {
      return(NSSCS_E_INVALID_PARAM);
  }

  // open secretStore
  sscs_Utf8Strncpy(store.ssName, SSCS_DEFAULT_SECRETSTORE_ID, SSCS_DEFAULT_SECRETSTORE_ID_LEN);
  store.version = 1;
  context = miCASAOpenSecretStoreCache(&store, ssFlags, NULL);

	if(context == NULL)
	{
		return NSSCS_E_SYSTEM_FAILURE;
	}

  rc = sscs_SetMasterPasscode(((SSCS_CONTEXT_T*)context)->ssHandle,passcode, NULL);
  // close the secretstore
  miCASACloseSecretStoreCache(context, ssFlags, NULL);
  return(rc);

/* ############################### CODE ENDS HERE ############################# */
} //* end of miCASASetMasterPasscode


/*
 * NAME - miCASAIsSecretPersistent
 *
 * DESCRIPTION
 *	 This call checks for the persistence of the secret.
 *
 */
SSCS_GLOBAL_LIBCALL(int32_t)
miCASAIsSecretPersistent
(
    uint32_t 			ssFlags,
    SSCS_SECRET_ID_T	*secretID,
    SSCS_EXT_T			*ext
)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

    void 				*context = NULL;
    int32_t				rcode = 0;
    SSCS_SECRETSTORE_T	store = {0};
    SSCS_KEYCHAIN_ID_T	kc = {0};
    SSCS_CONTEXT_T		*storeContext;
 
/* ############################## CODE STARTS HERE ############################ */

    if((ssFlags == 0) && (secretID == NULL))
	{
        return NSSCS_E_INVALID_PARAM;
	}

	if(secretID && secretID->len > NSSCS_MAX_SECRET_ID_LEN)
	{
		return NSSCS_E_BUFFER_LEN;
	}

    // open secretStore
    sscs_Utf8Strncpy(store.ssName, SSCS_DEFAULT_SECRETSTORE_ID, SSCS_DEFAULT_SECRETSTORE_ID_LEN);
    store.version = 1;
    context = miCASAOpenSecretStoreCache(&store, 0, NULL);

    storeContext = (SSCS_CONTEXT_T *)context;

    if(context == NULL)
    {
        return NSSCS_E_SYSTEM_FAILURE;
    }

    kc.len = SSCS_S_KC_ID_CHARS;
    sscs_Utf8Strncpy(kc.keychainID, SSCS_SESSION_KEY_CHAIN_ID, kc.len);

    rcode = sscs_IsSecretPersistent(storeContext->ssHandle, ssFlags, &kc, secretID, ext);

    miCASACloseSecretStoreCache(context, 0, NULL);

    return rcode;

/* ############################### CODE ENDS HERE ############################# */
}	// end of miCASAIsSecretPersistent