/***********************************************************************
 * 
 *  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.
 * 
 ***********************************************************************/


#if defined(__cplusplus) || defined(c_plusplus)
extern "C"
{
#endif
#include <stdio.h>

#ifdef SSCS_WIN32_PLAT_F
#include <windows.h>
#include <sscs_ipc.h>
#endif

#include "sscs_cache.h"

/* Starts a session with the cache and returns a handle to the cache.
 * Parametrs:
 * 		secretStoreID
 *			(IN) Points to SecretStoreID structure.
 *
 * Return Values:
 *		returns a pointer to SecretStoreHandle structure.
 */
void* sscs_CacheOpenSecretStore
(
	void 		*secretStoreID,
    uint32_t     ssFlags,
	void		*reserved

)
{
    SSCS_SECRETSTORE_HANDLE_T *ssHandle = NULL;
    SSCS_LINUX_SS_HANDLE_T *platHandle = NULL;
    int32_t retVal = 0;

    ssHandle = (SSCS_SECRETSTORE_HANDLE_T *)malloc((sizeof(SSCS_SECRETSTORE_HANDLE_T) + (sizeof(SSCS_LINUX_SS_HANDLE_T))));
    if(NULL == ssHandle)
    {
        return NULL;
    }

	memset(ssHandle,0,sizeof(SSCS_SECRETSTORE_HANDLE_T));
	ssHandle->platHandle = ssHandle + sizeof(SSCS_SECRETSTORE_HANDLE_T);
    
    retVal = ipc_OpenSecretStore(secretStoreID,ssHandle);
    if(retVal)
    {
		memset(ssHandle, 0, sizeof(SSCS_SECRETSTORE_HANDLE_T) + (sizeof(SSCS_LINUX_SS_HANDLE_T)));
        free(ssHandle);
        return NULL;
    }

    return ssHandle;
}

/* Closes the secretstore and destroys the SecretStore context for that 
 * application.
 *
 * Parameters:
 *		ssHandle
 *			(IN) Handle returned by sscs_CacheOpenSecretStore function. This will have 
 *			context information regarding the SecretStore.
 *
 * 
 * Return Values
 *
 */
int32_t sscs_CacheCloseSecretStore
(
	void 		*ssHandle,
	uint32_t	ssFlags,
	void		*reserved
)
{
    int32_t retVal = 0;
    SSCS_SECRETSTORE_HANDLE_T *ssHandleCopy = (SSCS_SECRETSTORE_HANDLE_T *)ssHandle;

    if(ssHandleCopy->platHandle)
    {
        retVal = ipc_CloseSecretStore(ssHandleCopy, ssFlags);        
    }
	
    if(ssHandleCopy)
        free(ssHandleCopy);

    return retVal;
}

/* Removes all application defined keychains from the store. It also removes 
 * secrets stored in system defined keychains.
 *
 * Parameters:
 *		ssHandle
 *			(IN) Handle returned by sscs_CacheOpenSecretStore function. This will have 
 *			context information regarding the SecretStore.
 *
 *
 * Return Values:
 */
int32_t sscs_CacheRemoveSecretStore
(
	void 			*ssHandle,
        uint32_t	        ssFlags,
	void			*reserved
)
{
    int32_t retVal = 0;
    SSCS_SECRETSTORE_HANDLE_T *ssHandleCopy = (SSCS_SECRETSTORE_HANDLE_T *)ssHandle;

    retVal = ipc_RemoveSecretStore(ssHandleCopy);

    return retVal;
}

/* Enumerates key chain ids available in the store.
 *
 * Parameters:
 *		ssHandle
 *			(IN) Handle returned by sscs_CacheOpenSecretStore function. This will have 
 *			context information regarding the SecretStore.
 *
 *
 *		kcIDList
 *			(OUT) Points to the key chain id enumeration structure. Points to 
 *			KeyChainIDList structure.
 *
 *		bytesRequired
 *			(OUT) Specifies the buffer requirement if it is not possible 
 * 			to copy KeyChain IDs in the buffer passed by the application.
 *
 * Return Values:
 *
 */
int32_t sscs_CacheEnumerateKeychainIDs
(
	void 			*ssHandle,
        uint32_t                ssFlags,
        SSCS_SRCH_KEY_T         *searchKey,
	SSCS_KEYCHAIN_ID_LIST_T *kcIDList,
	void			*reserved
)
{
	int32_t retVal = 0;
	SSCS_SECRETSTORE_HANDLE_T *ssHandleCopy = (SSCS_SECRETSTORE_HANDLE_T *)ssHandle;

	retVal = ipc_EnumerateKeychainIDs(ssHandleCopy,kcIDList);
	
	return retVal;
}

/* Creates a new keychain in the store.
 *
 * Parameters:
 *		ssHandle
 *			(IN) Handle returned by sscs_CacheOpenSecretStore function. This will have 
 *			context information regarding the SecretStore.
 *
 *		ssFlags
 *			(IN) Can be a combination of follwing flags:
 *  			SSCS_HIDDEN_LOCAL_KEY_CHAIN_F	
 *				SSCS_SESSION_KEY_CHAIN_F		
 *				SSCS_LOCAL_KEY_CHAIN_F			
 *				SSCS_REMOTE_KEY_CHAIN_F			
 *				SSCS_LOCAL_REMOTE_CHAIN_F		
 *				SSCS_RESERVED1_KEY_CHAIN_F		
 *				SSCS_RESERVED2_KEY_CHAIN_F	
 *		keychainID
 *			(IN) Specifies the unique keychain ID within the secretstore.
 *
 */
int32_t sscs_CacheAddKeychain 
(
	void 					*ssHandle,
	uint32_t				ssFlags,
	SSCS_KEYCHAIN_ID_T			*keychainID,
	void					*reserved
)
{
    int32_t retVal = 0;
    SSCS_SECRETSTORE_HANDLE_T *ssHandleCopy = (SSCS_SECRETSTORE_HANDLE_T *)ssHandle;

    retVal = ipc_AddKeychain(ssHandleCopy,ssFlags,keychainID);
	
    return retVal;
}


/* Removes the specified keychain from the store.
 *
 * Parameters: 
 *		ssHandle
 *			(IN) Handle returned by sscs_CacheOpenSecretStore function. This will have 
 *			context information regarding the SecretStore.
 *
 *		keychainID
 *			(IN) Specifies the unique keychain ID within the secretstore.
 *
 * Return Values:
 */
int32_t sscs_CacheRemoveKeychain 
(
	void 					*ssHandle,
        uint32_t	   		        ssFlags,
	SSCS_KEYCHAIN_ID_T   			*keyChainID,
	void					*reserved
)
{
    int32_t retVal = 0;
    SSCS_SECRETSTORE_HANDLE_T *ssHandleCopy = (SSCS_SECRETSTORE_HANDLE_T *)ssHandle;
	
    retVal = ipc_RemoveKeychain(ssHandleCopy,keyChainID);
	
    return retVal;
}

/* Enumerates secret ids in a given keychain.
 *
 * Parameters:
 * 		ssHandle
 *			(IN) Handle returned by sscs_CacheOpenSecretStore function. This will have 
 *			context information regarding the SecretStore.
 *
 *		keyChainID
 *			(IN) handle obtained during sscs_CacheOpenKeychain.
 *
 *
 *		secretIDList
 *			(OUT) Points to the secret id enumeration structure. Points to 
 *			SecretIDList structure.
 *
 *		bytesRequired
 *			(OUT) Specifies the buffer requirement if it is not possible 
 * 			to copy Secret IDs in the buffer passed by the application.
 * Return Values:
 */
int32_t sscs_CacheEnumerateSecretIDs
(
	void 			*ssHandle,
        uint32_t	           ssFlags,
	SSCS_KEYCHAIN_ID_T	*keyChainID,
        SSCS_SRCH_KEY_T         *searchKey,
	SSCS_SECRET_ID_LIST_T	*secretIDList,
	void			*reserved
)
{
    int32_t retVal = 0;
    SSCS_SECRETSTORE_HANDLE_T *ssHandleCopy = (SSCS_SECRETSTORE_HANDLE_T *)ssHandle;

    retVal = ipc_EnumerateSecretIDs(ssHandleCopy,keyChainID,secretIDList);
	
    return retVal;
}


/* Reads Secret value for a given Secret ID in a given keychain.
 *
 * Parameters: 
 *		ssHandle
 *			(IN) Handle returned by sscs_CacheOpenSecretStore function. This will have 
 *			context information regarding the SecretStore.
 *
 *		keyChainID
 *			(IN) KeyChainID where the specified SecretID stored.
 *
 *		secretID
 *			(IN) Specifies the unique secret ID within the keychain. This data is 
 *			encoded in SSCS_SECRET_ID_T.
 *
 *		secretData
 *			(IN/OUT) Specifies the information of the secret stored w.r.t the secretID. 
 *			Points to a SSCS_SECRET_T structure.
 *
 *		epPassword
 *			(IN) Points to an optional field to pass in the Enhanced Protection Password 
 *			for reading a secret.When the password is not present, you can pass in a NULL.
 *
 *		bytesRequired
 *			(OUT) Specifies the buffer requirement if it is not possible 
 * 			to copy Secret data in the buffer passed by the application.

 *
 * Return Values :
 */
int32_t sscs_CacheReadSecret 
(
	void 				*ssHandle,
    uint32_t		     ssFlags,
	SSCS_KEYCHAIN_ID_T	*keychainID,
	SSCS_SECRET_ID_T    *secretID,
	SSCS_SECRET_T		*secretData,
	SSCS_PASSWORD_T		*epPassword,
	uint32_t			*bytesRequired,
	void				*reserved
)
{
    int32_t retVal = 0;
    SSCS_SECRETSTORE_HANDLE_T *ssHandleCopy = (SSCS_SECRETSTORE_HANDLE_T *)ssHandle;

    retVal = ipc_ReadSecret(ssHandleCopy,keychainID,secretID,secretData,epPassword,bytesRequired);
	
    return retVal;
}


/* Writes Secret value for a given Secret ID in a given keychain.
 * 
 * Parameters: 
 *		ssHandle
 *			(IN) Handle returned by sscs_CacheOpenSecretStore function. This will have 
 *			context information regarding the SecretStore.
 *
 *		ssFlags
 *			(IN) ...
 *
 *		keyChainID
 *			(IN) KeyChainID where the specified SecretID stored.
 *
 *		secretID
 *			(IN) Specifies the unique secret ID within the keychain. 			This data is 
 *			encoded in SSCS_SECRET_ID_T.
 *
 *		secretData
 *			(IN) Specifies the information of the secret stored w.r.t the secretID. 
 *			Points to a SSCS_SECRET_T structure.
 *
 *
 *		epPassword
 *			(IN) Points to an optional field to pass in the Enhanced Protection Password 
 *			for reading a secret.When the password is not present, you can pass in a NULL.
 *
 *
 *
 * Return Values:
 */
int sscs_CacheWriteSecret 
(
	void 			*ssHandle,
	uint32_t		ssFlags,
	SSCS_KEYCHAIN_ID_T	*keyChainID,
	SSCS_SECRET_ID_T	*secretID,
	SSCS_SECRET_T		*secretData,
	SSCS_PASSWORD_T		*epPassword,
	void			*reserved
)
{
    int32_t retVal = 0;
    SSCS_SECRETSTORE_HANDLE_T *ssHandleCopy = (SSCS_SECRETSTORE_HANDLE_T *)ssHandle;

    retVal = ipc_WriteSecret(ssHandleCopy,ssFlags,keyChainID,secretID,secretData,epPassword, reserved);

    return retVal;
}


/* Removes Secret for a given Secret ID in a given keychain.
 *
 * Parameters:
 *		ssHandle
 *			(IN) Handle returned by sscs_CacheOpenSecretStore function. This will have 
 *			context information regarding the SecretStore.
 *
 *
 *		keyChainID
 *			(IN) KeyChainID where the specified SecretID stored.
 *
 *		secretID
 *			(IN) Specifies the unique secret ID within the keychain. 			This data is 
 *			encoded in SSCS_SECRET_ID_T.
 *
 *
 *		epPassword
 *			(IN) Points to an optional field to pass in the Enhanced Protection Password 
 *			for reading a secret.When the password is not present, you can pass in a NULL.
 *
 * Return Values:
 */
int32_t sscs_CacheRemoveSecret 
(
	void 			*ssHandle,
        uint32_t	           ssFlags,
	SSCS_KEYCHAIN_ID_T	*keyChainID,
	SSCS_SECRET_ID_T	*secredID,
	SSCS_PASSWORD_T 	*epPassword,
        void                    *reserved
)
{
    int32_t retVal = 0;
    SSCS_SECRETSTORE_HANDLE_T *ssHandleCopy = (SSCS_SECRETSTORE_HANDLE_T *)ssHandle;
	
    retVal = ipc_RemoveSecret(ssHandleCopy,keyChainID,secredID,epPassword);
	
    return retVal;
}

/* Returns statistical information regarding the SecretStore and its  Keychains.
 *
 * Parameters:
 *		ssHandle
 *			(IN) Handle returned by sscs_CacheOpenSecretStore function. This will have 
 *			context with respect to the instance of open cache in it. 
 *
 *
 *		ssInfo
 *			(OUT) This structure contains the statistical information regarding the 
 *			SecretStore and its  Keychains. 
 *
 * Return Values:
 */
int32_t sscs_CacheGetSecretStoreInfo 
(
	void 					*ssHandle,
        uint32_t           ssFlags,
	SSCS_SECRETSTORE_INFO_T *ssInfo, 
	void					*reserved
)
{
    int32_t retVal = 0;
    SSCS_SECRETSTORE_HANDLE_T *ssHandleCopy = (SSCS_SECRETSTORE_HANDLE_T *)ssHandle;

    retVal = ipc_GetSecretStoreInfo(ssHandleCopy,ssInfo);

    return retVal;
}

/* Retrieves the statistical information regarding the target Keychain.
 *
 * Parameters: 
 *		ssHandle
 *			(IN) Handle returned by sscs_CacheOpenSecretStore function. This will have 
 *			context with respect to the instance of open cache in it. 
 *
 *		keyChainID
 *			(IN) KeyChainID where the specified SecretID stored.
 *
 *
 *		kcInfo
 *			(OUT) This structure contains the statistical information regarding the  
 *			Keychain. 
 *
 *
 * Return Values:
 */
int32_t sscs_CacheGetKeychainInfo 
(
	void 			*ssHandle,
        uint32_t           ssFlags,
	SSCS_KEYCHAIN_ID_T	*keyChainID,
	SSCS_KEYCHAIN_INFO_T   	*kcInfo,    
	void			*reserved
)
{
    int32_t retVal = 0;
    SSCS_SECRETSTORE_HANDLE_T *ssHandleCopy = (SSCS_SECRETSTORE_HANDLE_T *)ssHandle;

    retVal = ipc_GetKeychainInfo(ssHandleCopy,keyChainID,kcInfo);

    return retVal;
}

/* This call locks that cache to prevent access until the MasterPassword is 
 * supplied.
 *
 * Parameters:
 *		ssHandle
 *			(IN) Handle returned by sscs_CacheOpenSecretStore function. This will have 
 *			context with respect to the instance of open cache in it. 
 *
 * Return Values :
 */
int32_t sscs_LockCache 
(
	void 					*ssHandle,
        uint32_t           ssFlags,
	void					*reserved
)
{
    int32_t retVal = 0;
    SSCS_SECRETSTORE_HANDLE_T *ssHandleCopy = (SSCS_SECRETSTORE_HANDLE_T *)ssHandle;

    retVal = ipc_LockCache(ssHandleCopy);

    return retVal;
}

/* This unlocks previously locked cache using the MasterPassword  
 *
 * Parameters:
 *		ssHandle
 *			(IN) Handle returned by sscs_CacheOpenSecretStore function. This will have 
 *			context with respect to the instance of open cache in it. 
 *      masterPassword
 *
 * Return Values :
 */
int32_t sscs_UnlockCache 
(
	void 				*ssHandle,
        uint32_t           ssFlags,
	SSCS_PASSCODE_T		*passcode,
	void				*reserved
)
{
    int32_t retVal = 0;
    SSCS_SECRETSTORE_HANDLE_T *ssHandleCopy = (SSCS_SECRETSTORE_HANDLE_T *)ssHandle;

    retVal = ipc_UnlockCache(ssHandle,passcode);

    return retVal;
}

int32_t sscs_SetMasterPasscode
(
    void *ssHandle,
    SSCS_PASSCODE_T *passcode,
    void *reserved
)
{
    int32_t retVal = 0;
    retVal = ipc_SetMasterPasscode(ssHandle,passcode);
    return retVal;
}

int32_t sscs_SetMasterPassword
(
    void *ssHandle,
    SSCS_PASSWORD_T *password,
    SSCS_HINT_T *hint,
    void *reserved
)
{
    int32_t retVal = 0;
    retVal = ipc_SetMasterPassword(ssHandle,password,hint);
    return retVal;
}

//#if 0
/* Writes A key-value for a given Secret ID in a given keychain.
 * 
 * Parameters: 
 *		ssHandle
 *			(IN) Handle returned by sscs_CacheOpenSecretStore function. This will have 
 *			context information regarding the SecretStore.
 *
 *		ssFlags
 *			(IN) ...
 *
 *		keyChainID
 *			(IN) KeyChainID where the specified SecretID stored.
 *
 *		secretID
 *			(IN) Specifies the unique secret ID within the keychain. 			This data is 
 *			encoded in SSCS_SECRET_ID_T.
 *
 *		secretData
 *			(IN) Specifies the information of the secret stored w.r.t the secretID. 
 *			Points to a SSCS_SECRET_T structure.
 *
 *
 *		epPassword
 *			(IN) Points to an optional field to pass in the Enhanced Protection Password 
 *			for reading a secret.When the password is not present, you can pass in a NULL.
 *
 *
 *
 * Return Values:
 */
int sscs_CacheWriteKey 
(
	void 				*ssHandle,
	uint32_t			 ssFlags,
	SSCS_KEYCHAIN_ID_T	*keyChainID,
	SSCS_SECRET_ID_T	*secretID,
    SS_UTF8_T           *key,
    uint32_t             keyLen,
    uint8_t             *val,
    int32_t              valLen,
	SSCS_PASSWORD_T		*epPassword,
	void				*reserved
)
{
    int32_t retVal = 0;
    SSCS_SECRETSTORE_HANDLE_T *ssHandleCopy = (SSCS_SECRETSTORE_HANDLE_T *)ssHandle;

    retVal = ipc_WriteKey(ssHandleCopy,ssFlags,keyChainID,secretID,key,keyLen,val,valLen,epPassword, reserved);

    return retVal;
}



int sscs_CacheWriteBinaryKey 
(
	void 				*ssHandle,
	uint32_t			 ssFlags,
	SSCS_KEYCHAIN_ID_T	*keyChainID,
	SSCS_SECRET_ID_T	*secretID,
    SS_UTF8_T           *key,
    uint32_t             keyLen,
    uint8_t             *val,
    uint32_t            valLen,
	SSCS_PASSWORD_T		*epPassword,
	void				*reserved
)
{
    int32_t retVal = 0;
    SSCS_SECRETSTORE_HANDLE_T *ssHandleCopy = (SSCS_SECRETSTORE_HANDLE_T *)ssHandle;

    retVal = ipc_WriteBinaryKey(ssHandleCopy,ssFlags,keyChainID,secretID,key,keyLen,val,valLen,epPassword, reserved);

    return retVal;
}


/* Reads Secret value for a given Secret ID in a given keychain.
 *
 * Parameters: 
 *		ssHandle
 *			(IN) Handle returned by sscs_CacheOpenSecretStore function. This will have 
 *			context information regarding the SecretStore.
 *
 *		keyChainID
 *			(IN) KeyChainID where the specified SecretID stored.
 *
 *		secretID
 *			(IN) Specifies the unique secret ID within the keychain. This data is 
 *			encoded in SSCS_SECRET_ID_T.
 *
 *		secretData
 *			(IN/OUT) Specifies the information of the secret stored w.r.t the secretID. 
 *			Points to a SSCS_SECRET_T structure.
 *
 *		epPassword
 *			(IN) Points to an optional field to pass in the Enhanced Protection Password 
 *			for reading a secret.When the password is not present, you can pass in a NULL.
 *
 *		bytesRequired
 *			(OUT) Specifies the buffer requirement if it is not possible 
 * 			to copy Secret data in the buffer passed by the application.

 *
 * Return Values :
 */
int32_t sscs_CacheReadKey 
(
	void 				*ssHandle,
    uint32_t	         ssFlags,
	SSCS_KEYCHAIN_ID_T	*keychainID,
	SSCS_SECRET_ID_T    *secretID,
    SS_UTF8_T           *key,
    uint32_t             keyLen,
    uint8_t             *val,
    uint32_t            *valLen,
	SSCS_PASSWORD_T		*epPassword,
	uint32_t			*bytesRequired,
	void				*reserved
)
{
    int32_t retVal = 0;
    SSCS_SECRETSTORE_HANDLE_T *ssHandleCopy = (SSCS_SECRETSTORE_HANDLE_T *)ssHandle;

    retVal = ipc_ReadKey(ssHandleCopy,keychainID,secretID,key,keyLen,val,valLen,epPassword,bytesRequired);

    return retVal;
}

int32_t sscs_CacheReadBinaryKey 
(
	void 				*ssHandle,
    uint32_t	         ssFlags,
	SSCS_KEYCHAIN_ID_T	*keychainID,
	SSCS_SECRET_ID_T    *secretID,
    SS_UTF8_T           *key,
    uint32_t             keyLen,
    uint8_t             *val,
    uint32_t            *valLen,
	SSCS_PASSWORD_T		*epPassword,
	uint32_t			*bytesRequired,
	void				*reserved
)
{
    int32_t retVal = 0;
    SSCS_SECRETSTORE_HANDLE_T *ssHandleCopy = (SSCS_SECRETSTORE_HANDLE_T *)ssHandle;

    retVal = ipc_ReadBinaryKey(ssHandleCopy,keychainID,secretID,key,keyLen,val,valLen,epPassword,bytesRequired);

    return retVal;
}

int sscs_IsSecretPersistent 
(
	void 			*ssHandle,
	uint32_t		ssFlags,
	SSCS_KEYCHAIN_ID_T	*keyChainID,
	SSCS_SECRET_ID_T	*secretID,
	void			*reserved
)
{
    int32_t retVal = 0;
    SSCS_SECRETSTORE_HANDLE_T *ssHandleCopy = (SSCS_SECRETSTORE_HANDLE_T *)ssHandle;

    retVal = ipc_IsSecretPersistent(ssHandleCopy,ssFlags,keyChainID,secretID,reserved);

    return retVal;
}

//#endif

#if defined(__cplusplus) || defined(c_plusplus)
}
#endif