/***********************************************************************
 * 
 *  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 "sscs_ipc.h"

#define MAX_RECV_HEAD_LEN 6
#define WINDOWS_LOGIN_ID 1

// return codes
#define MAX_RETURN_CODE        27    
int32_t static gReturnCodes[27] = {
    NSSCS_SUCCESS,          //SSCS_REPLY_SUCCESS  0
    NSSCS_E_INVALID_PARAM, //SSCS_E_INVALID_MESSAGE -1
    NSSCS_E_INCOMPATIBLE_VERSION, //SSCS_E_VERSION_NOT_SUPPORTED -2
    NSSCS_E_SYSTEM_FAILURE, //SSCS_E_SYSTEM_ERROR -3
    NSSCS_E_SERVICE_NOT_SUPPORTED, //SSCS_E_REPLY_NOT_AVAILABLE -4
    NSSCS_E_INVALID_SECRET_ID, // REQUIRES New	SSCS_E_INVALID_KEYCHAIN -5
    NSSCS_E_INVALID_SECRET_ID, //SSCS_E_INVALID_SECRETID -6
    NSSCS_E_SECRET_ID_EXISTS, // REQUIRES NEW -//SSCS_E_KEYCHAIN_ALREADY_EXISTS -7
    NSSCS_E_SYSTEM_FAILURE, //SSCS_E_MAX_KEYCHAINS_REACHED -8   
    NSSCS_E_SYSTEM_FAILURE, //SSCS_E_ADD_KEYCHAIN_FAILED -9
    NSSCS_E_SYSTEM_FAILURE, //SSCS_E_NO_KEYCHAINS_EXIST -10
    NSSCS_E_SYSTEM_FAILURE, //SSCS_E_KEYCHAIN_DOES_NOT_EXIST        -11
    NSSCS_E_SYSTEM_FAILURE, //SSCS_E_REMOVE_KEYCHAIN_FAILED         -12
    NSSCS_E_SYSTEM_FAILURE, //SSCS_E_WRITE_SECRET_FAILED            -13
    NSSCS_E_SYSTEM_FAILURE, //SSCS_E_ADDING_DEFAULT_KEYCHAIN_FAILED -14
    NSSCS_E_SYSTEM_FAILURE, //SSCS_E_NO_SECRETS_EXIST               -15
    NSSCS_E_SYSTEM_FAILURE, //SSCS_E_REMOVE_SECRET_FAILED           -16
    NSSCS_E_SYSTEM_FAILURE, //SSCS_E_GET_SOCKET_PATH_FAILED         -17
    NSSCS_E_SYSTEM_FAILURE, //SSCS_E_CREATE_SOCKET_FAILED           -18
    NSSCS_E_INVALID_SECRET_ID, //SSCS_E_SECRETID_DOES_NOT_EXIST        -19
    NSSCS_E_INVALID_PARAM, //SSCS_E_INVALID_INPUT                  -20
	NSSCS_E_SYSTEM_FAILURE, //SSCS_E_SETTING_PASSCODE_FAILED		-21
	NSSCS_E_SYSTEM_FAILURE,	//SSCS_STORE_IS_PERSISTENT				-22;
    NSSCS_E_SYSTEM_FAILURE,	//SSCS_STORE_IS_NOT_PERSISTENT           = -23;
    NSSCS_E_SYSTEM_FAILURE, //SSCS_SECRET_IS_PERSISTENT              = -24;
    NSSCS_E_SYSTEM_FAILURE, //SSCS_SECRET_IS_NOT_PERSISTENT          = -25;
    NSSCS_E_ACCESS_DENIED	//SSCS_SECRET_STORE_IS_LOCKED            = -26;
};
   
/*-----------------------------------------------------------------------------
Function - HexDump
Description - Dumps the information in Hex and Ascii. (16 Bytes per line).
Parameters
    lpBuf (IN) - Data to be dumped.
    iBytes (IN) - Number of bytes in lpBuf.
Returns - none
-----------------------------------------------------------------------------*/
#ifdef DEBUG
void HexDump(char *lpBuf, int iBytes)
{
   char buffer[17];
   int count,count1, ch;
   
   printf("\n\n");
   for(count = 0; count < iBytes; )
   {
      for(count1 = 0; count1 < 16;count1++)
      {
         ch = lpBuf[count++];
         ch &= 0x000000FF;
         printf("%02x ",ch);
         if(!(count % 8))
            printf("- ");
         
         buffer[count1] = (ch > 0x20) ? ch : '.';
      }
      buffer[count1] = '\0';
      printf("    %s\n",buffer);
    }
    return;
}
#endif

/* Map the sscs returned return code to NDK error codes */
int32_t mapReturnCode(int32_t sscsCode)
{
    sscsCode *= -1;
    if(sscsCode < 0 || sscsCode > MAX_RETURN_CODE)
        return NSSCS_E_SYSTEM_FAILURE;
    return gReturnCodes[sscsCode];
}

/* Function name :
 *     Tokenize
 * Arguments :
 *     tokenType - 0 for keychainids and 1 for secretids
 *     buffer    - the buffer to be parsed
 *     idList    - the list which needs to be filled with the tokens.
 * Description:
 *     As Windows does not have strtok_r call, this function would
 *     abstract the tokenizing functionality.
 *     On Linux, this would call strtok_r, whereas on Windows
 *     strtok would be used.
 */
int Tokenize( int tokenType, char* buffer, void *idList )
{
	int i = 0;
	char *tok = NULL;

#ifdef SSCS_LINUX_PLAT_F
    
    char *tmpPtr = NULL;
    

    for (tok = strtok_r((char *)buffer,"*",&tmpPtr);
         tok != NULL;
         tok = strtok_r(NULL,"*",&tmpPtr))
    {
         if( 0 == tokenType )
         {
             sscs_Utf8Strcpy(((SSCS_KEYCHAIN_ID_T*)idList)[i].keychainID,tok);
             ((SSCS_KEYCHAIN_ID_T*)idList)[i].len = sscs_Utf8StrSize(tok);
         }
         else
         {
             sscs_Utf8Strcpy(((SSCS_SECRET_ID_T*)idList)[i].id,tok);
             ((SSCS_SECRET_ID_T*)idList)[i].len = sscs_Utf8StrSize(tok);
         }
         i++;
    }
#endif

#ifdef SSCS_WIN32_PLAT_F
		char seps[]   = "*";

			/* Establish string and get the first token: */
			tok = strtok( (char *)buffer, seps );
			while( tok != NULL )
			{
				/* While there are tokens in "string" */
				if( 0 == tokenType )
				{
					sscs_Utf8Strcpy(((SSCS_KEYCHAIN_ID_T*)idList)[i].keychainID,tok);
					((SSCS_KEYCHAIN_ID_T*)idList)[i].len = sscs_Utf8StrSize(tok);
				}
				else
				{
					sscs_Utf8Strcpy(((SSCS_SECRET_ID_T*)idList)[i].id,tok);
					((SSCS_SECRET_ID_T*)idList)[i].len = sscs_Utf8StrSize(tok);
				}
				i++;

				/* Get next token: */
				tok = strtok( NULL, seps );
			}



#endif
    return 0;
}

int32_t ipc_OpenSecretStore
(
    void *secretStoreID,
    SSCS_SECRETSTORE_HANDLE_T *ssHandle
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;

    SSCS_SECRETSTORE_T *ssID = (SSCS_SECRETSTORE_T *)secretStoreID;

    uint16_t msgid     = 0;
    uint32_t ssNameLen = 0;
    uint32_t msgLen    = 0;
    uint32_t version   = 0;

    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if( (NULL == ssHandle) || (NULL == ssHandle->platHandle) || 
            (NULL == secretStoreID) )
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }
    
        *(int *)ssHandle->platHandle = IPC_CREATE();
        if(*(int *)ssHandle->platHandle < 0)
        {
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        // Prepare Request buffer
        ssNameLen = sscs_Utf8StrSize(ssID->ssName);
        msgLen = MSGID_LEN + MSG_LEN +  
                 MSG_DWORD_LEN + 
                 MSG_STRING_LEN + 
                 ssNameLen;

        pReq = gpReqBuf;
    
        msgid = REQ_CACHE_OPEN_SECRET_STORE_MSGID;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
    
        memcpy(pReq, &msgLen, MSG_LEN);
        pReq += MSG_LEN;

        memcpy(pReq,&ssID->version,MSG_DWORD_LEN);
        pReq += MSG_DWORD_LEN;

        memcpy(pReq,&ssNameLen,MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;

        memcpy(pReq,ssID->ssName,ssNameLen);
		pReq += ssNameLen;
    
        retVal = IPC_WRITE(*(int *)ssHandle->platHandle,(char *)gpReqBuf, msgLen);
        if(retVal < 0)
        {
            DMSG(("Write failed : %s\n",strerror(errno)));
            DMSG(("Closing socket : %d\n",*(int*)ssHandle->platHandle));
            DMSG(("ipc_OpenSecretStore:IPC_WRITE returned :%d\n",retVal));
            IPC_CLOSE(*(int *)ssHandle->platHandle);
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        #ifdef DEBUG
        //HexDump(gpReqBuf, msgLen);
        #endif
    
        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_OPENSS);
        if(retVal < 0)
        {
            //log debug info here
            DMSG(("ipc_OpenSecretStore:read returned :%d\n",retVal));
            DMSG(("Read failed : %s\n",strerror(errno)));
            DMSG(("Closing socket : %d\n",*(int*)ssHandle->platHandle));
 
            IPC_CLOSE(*(int *)ssHandle->platHandle);	
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }
    
        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&version, pReply, MSG_DWORD_LEN);
        pReply += MSG_DWORD_LEN;
        // Check for version here.
        memcpy(&sockReturn, pReply, MSG_DWORD_LEN);

        if(sockReturn != SSCS_REPLY_SUCCESS)
        {
            DMSG(("ipc_OpenSecretStore:sscs returned :%d\n",sockReturn));
            DMSG(("Closing socket : %d\n",*(int*)ssHandle->platHandle));
            IPC_CLOSE(*(int *)ssHandle->platHandle);
            retCode = mapReturnCode(sockReturn);
            break;
        }
    }while(0);

    return retCode; // map the return code from sockReturn
}

int32_t ipc_CloseSecretStore
(
    SSCS_SECRETSTORE_HANDLE_T *ssHandle,
    uint32_t   ssFlags
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;

    uint16_t msgid = 0;
    uint32_t msgLen  = 0;
    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));
    
    do
    {
        if((NULL == ssHandle) || (NULL == ssHandle->platHandle))
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }
    
        // Prepare Request buffer
        msgLen = MSGID_LEN + MSG_LEN + MSG_DWORD_LEN;  
        pReq = gpReqBuf;

        msgid = REQ_CACHE_CLOSE_SECRET_STORE_MSGID;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);
	pReq += MSG_LEN;

        //marshall ssflags		
        memcpy(pReq, &ssFlags, MSG_DWORD_LEN);
		
        retVal = IPC_WRITE(*(int *)ssHandle->platHandle, gpReqBuf, msgLen);
        if(retVal < 0)
        {
            retVal = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        // Read reply
        pReply = gpReplyBuf;

        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_GENERAL);
        if(retVal < 0)
        {
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&sockReturn, pReply, MSG_DWORD_LEN);

        retCode = mapReturnCode(sockReturn);

    }while(0);

    DMSG(("Closing socket : %d\n",*(int*)ssHandle->platHandle));
    IPC_CLOSE(*(int *)ssHandle->platHandle);
    return retCode; // map return code
}

int32_t ipc_RemoveSecretStore
(
    SSCS_SECRETSTORE_HANDLE_T *ssHandle
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;

    uint16_t msgid = 0;
    uint32_t msgLen  = 0;
    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if((NULL == ssHandle) || (NULL == ssHandle->platHandle))
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }

        // Prepare Request buffer
        msgLen = MSGID_LEN + MSG_LEN;  

        pReq = gpReqBuf;
    
        msgid = REQ_CACHE_REMOVE_SECRET_STORE_MSGID;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);

        retVal = IPC_WRITE(*(int *)ssHandle->platHandle, gpReqBuf, msgLen);
        if(retVal < 0)
        {
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;               
        }

        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_GENERAL);
        if(retVal < 0)
        {
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&sockReturn, pReply, MSG_DWORD_LEN);
        retCode = mapReturnCode(sockReturn);

    }while(0);

    return retCode;

}


int32_t ipc_EnumerateKeychainIDs
(
    SSCS_SECRETSTORE_HANDLE_T *ssHandle,
    SSCS_KEYCHAIN_ID_LIST_T *kcIDList
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    SS_UTF8_T nulc = '\0';
    SS_UTF8_T delimiter = '*';
    int i = 0,j = 0;

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;

    uint16_t msgid = 0;
    uint32_t msgLen  = 0;
    uint32_t bufLen  = 0;
    uint32_t numIds  = 0;

    SS_UTF8_T *tmpBuf = NULL;
    SS_UTF8_T *tmpPtr = NULL;
    SS_UTF8_T *tok = NULL;
    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if( (NULL == ssHandle) || (NULL == ssHandle->platHandle) || 
            (NULL == kcIDList) )
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }
    
        // Prepare Request buffer
        msgLen = MSGID_LEN + MSG_LEN;  

        pReq = gpReqBuf;
    
        msgid = REQ_CACHE_ENUMERATE_KEYCHAINIDS_MSGID;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);

        retVal = IPC_WRITE(*(int *)ssHandle->platHandle, gpReqBuf, msgLen);
        if(retVal < 0)
        {
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        // Read reply
        pReply = gpReplyBuf;
        memset(pReply,0,MIN_REPLY_BUF_LEN);
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_GENERAL);
        if(retVal < 0)
        {
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        // I would like to get return code here itself 
        //  so that I need not check for other things.
        memcpy(&bufLen,pReply, MSG_DWORD_LEN);
        if( 0 == bufLen )
        {
            retVal = IPC_READ(*(int *)ssHandle->platHandle,&sockReturn, MSG_DWORD_LEN);
            if(retVal < 0)
            {
                //log debug info here
                DMSG(("Reading retcode::%d\n",retVal));
            }
            retCode  = mapReturnCode(sockReturn);
            kcIDList->returnedIDs = 0;
            break;
        }
        // Let me check if the global buffer is sufficient
        if( bufLen < MIN_REPLY_BUF_LEN/(sizeof(char)) )
            pReply = gpReplyBuf;
        else
        {
            pReply = (Byte *)malloc( (bufLen+1) * sizeof(char));
            if( NULL == pReply )
            {
                // Cleanup the channel by reading the remaining and return error.
                int n;
                n = msgLen - MSG_REPLY_GENERAL; 
                while(n)
                {
                    int bytes = IPC_READ(*(int *)ssHandle->platHandle, gpReplyBuf, MIN_REPLY_BUF_LEN);
                    if( bytes > 0 )
                        n -= MIN_REPLY_BUF_LEN;
                    else
                        break;
                }
                retVal = IPC_READ(*(int *)ssHandle->platHandle,
                                  &sockReturn, MSG_DWORD_LEN);
                if(retVal < 0) 
                {
                    //log debug info here
                    DMSG(("Reading retcode::%d\n",retVal));
                }

                retCode = NSSCS_E_SYSTEM_FAILURE;
            } //if malloc fail loop ends here
            else 
                tmpBuf = (SS_UTF8_T *)pReply; // Save this ptr to free later.
        }
        retVal = IPC_READ(*(int *)ssHandle->platHandle,pReply, bufLen*sizeof(char));
        
        tmpPtr = (SS_UTF8_T *)pReply;
        tmpPtr[bufLen] = nulc;
        #ifdef DEBUG
        //HexDump(pReply, retVal);
        #endif
        // Count number of ids
        numIds = 1; // Atleast there is one !!
        while( tmpPtr = sscs_Utf8Strchr(tmpPtr, delimiter) )
        {
            numIds++;
            tmpPtr++;
        }
        if( numIds > kcIDList->returnedIDs )
        {
            kcIDList->returnedIDs = numIds;
            if(tmpBuf)
            {
                free(tmpBuf);
                tmpBuf = NULL;
            }
            retVal = IPC_READ(*(int *)ssHandle->platHandle,&sockReturn, MSG_DWORD_LEN);
            kcIDList->enumHandle = 0;

            retCode = NSSS_E_ENUM_BUFF_TOO_SHORT;
            break;
        }
        else
        {
            Tokenize( 0, (SS_UTF8_T*)pReply, kcIDList->keyChainIDList );
            kcIDList->returnedIDs = numIds;
            kcIDList->enumHandle = 0;
            if(tmpBuf)
            {
                free(tmpBuf);
                tmpBuf = NULL;
            }
        }

        retVal = IPC_READ(*(int *)ssHandle->platHandle,&sockReturn, MSG_DWORD_LEN);
        if(retVal < 0)
        {
            //log debug info here
            DMSG(("Reading retcode::%d\n",retVal));

        }
        retCode = mapReturnCode(sockReturn);

    }while(0);

    return retCode;
}


int32_t ipc_AddKeychain
(
    SSCS_SECRETSTORE_HANDLE_T *ssHandle,
    uint32_t ssFlags,
    SSCS_KEYCHAIN_ID_T *keychainID
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    uint16_t msgid = 0;
    uint32_t keychainIDLen = 0;
    uint32_t msgLen = 0;

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;

    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if( (NULL == ssHandle) || (NULL == ssHandle->platHandle) ||
            (NULL == keychainID) )
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }

        // Prepare Request buffer
        keychainIDLen = keychainID->len;
        if( keychainIDLen > NSSS_MAX_KEYCHAIN_ID_CHARS )
        {
            retCode = NSSS_E_SECRET_ID_TOO_LONG;
            break;
        }
        msgLen = MSGID_LEN + MSG_LEN + 
                 MSG_DWORD_LEN + // flags 
                 MSG_STRING_LEN +
                 keychainIDLen; // Keychain ID   

        pReq = gpReqBuf;
    
        msgid = REQ_CACHE_ADD_KEYCHAIN_MSGID;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);
        pReq += MSG_LEN;
        memcpy(pReq, &ssFlags, MSG_DWORD_LEN);
        pReq += MSG_DWORD_LEN;
        memcpy(pReq, &keychainIDLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;

        memcpy((SS_UTF8_T*)pReq,keychainID->keychainID,keychainIDLen);

        retVal = IPC_WRITE(*(int *)ssHandle->platHandle, gpReqBuf, msgLen);
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_GENERAL);
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&sockReturn, pReply, MSG_DWORD_LEN);
        retCode = mapReturnCode(sockReturn);

    }while(0);

    return retCode;
}

int32_t ipc_RemoveKeychain
(
    SSCS_SECRETSTORE_HANDLE_T *ssHandle,
    SSCS_KEYCHAIN_ID_T *keychainID
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;

    uint16_t msgid         = 0;
    uint32_t keychainIDLen = 0;
    uint32_t msgLen        = 0;

    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if( (NULL == ssHandle) || (NULL == ssHandle->platHandle) || 
            (NULL == keychainID) )
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }
    
        // Prepare Request buffer
        keychainIDLen = keychainID->len;
        if( keychainIDLen > NSSS_MAX_KEYCHAIN_ID_CHARS )
        {
            retCode = NSSS_E_SECRET_ID_TOO_LONG;
            break;
        }
        msgLen = MSGID_LEN + MSG_LEN + 
                 MSG_STRING_LEN +
                 keychainIDLen; // Keychain ID   

        pReq = gpReqBuf;
    
        msgid = REQ_CACHE_REMOVE_KEYCHAIN_MSGID;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);
        pReq += MSG_LEN;
        memcpy(pReq, &keychainIDLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq,keychainID->keychainID, keychainIDLen);

        retVal = IPC_WRITE(*(int *)ssHandle->platHandle, gpReqBuf, msgLen);
        if(retVal < 0)
        {
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_GENERAL);
        if(retVal < 0)
        {
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&sockReturn, pReply, MSG_DWORD_LEN);
        retCode = mapReturnCode(sockReturn);

    } while(0);

    return retCode;
}


int32_t ipc_EnumerateSecretIDs
(
    SSCS_SECRETSTORE_HANDLE_T *ssHandle,
    SSCS_KEYCHAIN_ID_T        *keychainID,
    SSCS_SECRET_ID_LIST_T     *secretIDList
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server
  
    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];

    Byte *pReq = NULL, *pReply = NULL;
    SS_UTF8_T nulc = '\0';
    SS_UTF8_T delimiter = '*';

    uint16_t msgid = 0;
    uint32_t keychainIDLen = 0;
    uint32_t msgLen = 0;
    uint32_t bufLen = 0;
    uint32_t numIds = 0;

    int i = 0;

    SS_UTF8_T *tmpBuf = NULL;
    SS_UTF8_T *tmpPtr = NULL;  
    SS_UTF8_T *tok = NULL;

    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if( (NULL == ssHandle)  || (NULL == ssHandle->platHandle) || 
            (NULL == keychainID) || (NULL == secretIDList) )
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }

        // Prepare Request buffer
        keychainIDLen = keychainID->len;
  
        if( keychainIDLen > NSSS_MAX_KEYCHAIN_ID_CHARS )
        {
            retCode = NSSS_E_SECRET_ID_TOO_LONG;
            break;
        }
        msgLen = MSGID_LEN + MSG_LEN + 
                 MSG_STRING_LEN +
                 keychainIDLen; // Keychain ID   

        pReq = gpReqBuf;
    
        msgid = REQ_CACHE_ENUMERATE_SECRETIDS_MSGID;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);
        pReq += MSG_LEN;
        memcpy(pReq, &keychainIDLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy((SS_UTF8_T *)pReq,(SS_UTF8_T *)keychainID->keychainID,keychainIDLen);

        retVal = IPC_WRITE(*(int *)ssHandle->platHandle, gpReqBuf, msgLen);
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;    
        }

        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_GENERAL);
        if( retVal < 0 )
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;    
        }

        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        // I would like to get return code here itself 
        // so that I need not check for other things.
        memcpy(&bufLen,pReply, MSG_DWORD_LEN);
        if( 0 == bufLen )
        {
            // Cleanup the channel by reading the return code.
            retVal = IPC_READ(*(int *)ssHandle->platHandle,&sockReturn, MSG_DWORD_LEN);
            secretIDList->returnedIDs = 0;
            retCode = mapReturnCode(sockReturn);
            break;
        }
        // Let me check if the global buffer is sufficient
        if(bufLen < MIN_REPLY_BUF_LEN/(sizeof(SS_UTF8_T)))
            pReply = gpReplyBuf;
        else
        {
            pReply = (Byte *)malloc( (bufLen+1) * sizeof(SS_UTF8_T));
            if(pReply == NULL)
            {
                // Cleanup the channel by reading the remaining and return error.
                int n;
                n = msgLen - MSG_REPLY_GENERAL; 
                while(n)
                {
                    int bytes = IPC_READ((*(int *)ssHandle->platHandle), gpReplyBuf, MIN_REPLY_BUF_LEN);
                    if(bytes > 0 )
                        n -= MIN_REPLY_BUF_LEN;
                    else
                        break;
                }
                retVal = IPC_READ(*(int *)ssHandle->platHandle,
                                 &sockReturn, MSG_DWORD_LEN);
                if(retVal < 0)
                {
                    //log debug info here
                    DMSG(("Reading retcode::%d\n",retVal));

                }

                retCode = NSSCS_E_SYSTEM_FAILURE;
                break;
            }
            else 
                tmpBuf = (SS_UTF8_T *)pReply; // Save this ptr to free later.
        }
        retVal = IPC_READ(*(int *)ssHandle->platHandle,pReply, bufLen*sizeof(SS_UTF8_T));
        DMSG(("Read returns..%d\n",retVal));
        tmpPtr = (SS_UTF8_T *)pReply;
        tmpPtr[bufLen] = nulc;
        DMSG(("Secretid list is %s\n", pReply));

        // Count number of ids
        numIds = 1; // Atleast there is one !!
        while(tmpPtr = sscs_Utf8Strchr(tmpPtr, delimiter))
        {
            numIds++;
            tmpPtr++;
        }
        if( numIds > secretIDList->returnedIDs )
        {
            secretIDList->returnedIDs = numIds;
            if(tmpBuf)
            {
                free(tmpBuf);
                tmpBuf = NULL;
            }
            retVal = IPC_READ(*(int *)ssHandle->platHandle,&sockReturn, MSG_DWORD_LEN);
            secretIDList->enumHandle = 0;
            retCode = NSSS_E_ENUM_BUFF_TOO_SHORT;
            break;
        }
        else
        {
            Tokenize( 1, (SS_UTF8_T*)pReply, secretIDList->secIDList );
            secretIDList->returnedIDs = numIds;
            secretIDList->enumHandle = 0;
            if(tmpBuf)
            {
                free(tmpBuf);
                tmpBuf = NULL;
            }
        }

        retVal = IPC_READ(*(int *)ssHandle->platHandle,&sockReturn, MSG_DWORD_LEN);
        if(retVal < 0)
        {
            //log debug info here
            DMSG(("Reading retcode::%d\n",retVal));
        }
    
        retCode = mapReturnCode(sockReturn);

    }while(0);

    return retCode;
}

int32_t ipc_ReadSecret
(
    SSCS_SECRETSTORE_HANDLE_T *ssHandle,
    SSCS_KEYCHAIN_ID_T        *keychainID,
    SSCS_SECRET_ID_T          *secretID,
    SSCS_SECRET_T             *secretData,
    SSCS_PASSWORD_T           *epPassword,
    uint32_t              *bytesRequired
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    uint32_t dataLen       = 0;
    uint16_t msgid         = 0;
    uint32_t keychainIDLen = 0;
    uint32_t secretIDLen   = 0;
    uint32_t msgLen        = 0;

    SSCS_PASSWORD_T    myPassword = {0,0,""};

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;
    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if((NULL == ssHandle) || (NULL == ssHandle->platHandle) || (NULL == keychainID) || (NULL == secretID) || (NULL == secretData) || (NULL == bytesRequired))
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }

        // Prepare Request buffer
        
        keychainIDLen = keychainID->len;
        secretIDLen   = secretID->len;

        if( keychainIDLen > NSSS_MAX_KEYCHAIN_ID_CHARS || 
            secretIDLen > NSSS_MAX_SECRET_ID_CHARS )
        {
            retCode = NSSS_E_SECRET_ID_TOO_LONG;
            break;
        }
        // epPassword is optional. So, the code should not break.
        if( NULL == epPassword )
            epPassword = &myPassword;
        msgLen = MSGID_LEN + MSG_LEN + 
                 MSG_STRING_LEN + // KeychainID length
                 keychainIDLen + // Keychain ID
                 MSG_STRING_LEN + // SecretID length
                 secretIDLen + // SecretID
                 MSG_STRING_LEN + // epPassword len
                 epPassword->pwordLen; 
            
        pReq = gpReqBuf;
        msgid = REQ_CACHE_READ_SECRET_MSGID;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);
        pReq += MSG_LEN;
        memcpy(pReq, &keychainIDLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq,keychainID->keychainID,keychainIDLen);
        pReq += keychainIDLen ;
        memcpy(pReq, &secretIDLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq, secretID->id, secretIDLen);
        pReq += secretIDLen;
        memcpy(pReq, &(epPassword->pwordLen), MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq, epPassword->pword, epPassword->pwordLen);
        pReq += epPassword->pwordLen;

        retVal = IPC_WRITE(*(int *)ssHandle->platHandle, gpReqBuf, msgLen);
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_GENERAL);
        if( 0 == retVal )
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&dataLen,pReply, MSG_DWORD_LEN);
        if( 0 == dataLen )
        {
            // Cleanup the channel by reading the return code.
            retVal = IPC_READ(*(int *)ssHandle->platHandle,&sockReturn, MSG_DWORD_LEN);
            if( retVal < 0 )
            {
                retCode = NSSCS_E_SYSTEM_FAILURE;
                break;
            }
            secretData->len = dataLen;
            retCode = mapReturnCode(sockReturn);
            break;
        }
        // Let me check if the buffer passed by application is big enough
        if(dataLen <= (uint32_t)secretData->len)
        {
            // Read the secret into application buffer.
            retVal = IPC_READ(*(int *)ssHandle->platHandle, secretData->data, dataLen);
            if( retVal < 0 )
            {
                retCode = NSSCS_E_SYSTEM_FAILURE;
                break;
            }
            
            secretData->len = dataLen;
        }
        else
        {
        //buffer allocated by application is not sufficient to hold the data.
            *bytesRequired = dataLen;
            {
                // Cleanup the channel by reading the remaining and return error.
                int n;
                n = dataLen; 
                while(n)
                {
                    int bytes = IPC_READ(*(int *)ssHandle->platHandle, gpReplyBuf, MIN_REPLY_BUF_LEN);
                    if( bytes > 0)
                        n -= MIN_REPLY_BUF_LEN;
                    else
                        break;
                }
                // Read the sscs return code also.
                IPC_READ(*(int *)ssHandle->platHandle, (Byte *) &sockReturn, MSG_DWORD_LEN);
                retCode = NSSCS_E_ENUM_BUFF_TOO_SHORT;
                break;
            }
        }
        // Read the sscs return code also.
        IPC_READ(*(int *)ssHandle->platHandle, (Byte *) &sockReturn, MSG_DWORD_LEN);
        retCode = mapReturnCode(sockReturn);

    } while(0);
    return retCode;
}

int ipc_WriteSecret
(
    SSCS_SECRETSTORE_HANDLE_T *ssHandle,
    uint32_t                  ssFlags,
    SSCS_KEYCHAIN_ID_T        *keychainID,
    SSCS_SECRET_ID_T          *secretID,
    SSCS_SECRET_T             *secretData,
    SSCS_PASSWORD_T           *epPassword,
    SSCS_EXT_T				  *ext
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;
    Byte *tmpBuf = NULL;

    uint16_t msgid		   = 0;
    uint32_t keychainIDLen = 0;
    uint32_t secretIDLen   = 0;
    uint32_t msgLen        = 0;

	uint32_t extID		   = 0;
    uint32_t luidLen	   = 0; 
	

    SSCS_PASSWORD_T    myPassword = {0,0,""};
    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if((NULL == ssHandle) || (NULL == ssHandle->platHandle) || (NULL == keychainID) || (NULL == secretID) ||(NULL == secretData))
        {
            retCode = NSSCS_E_INVALID_PARAM; 
            break;
        }
    
        // Prepare Request buffer

        keychainIDLen = keychainID->len;
        secretIDLen   = secretID->len;

        if( keychainIDLen > NSSS_MAX_KEYCHAIN_ID_CHARS || 
                  secretIDLen > NSSS_MAX_SECRET_ID_CHARS )
        {
            retCode = NSSS_E_SECRET_ID_TOO_LONG;
            break;
        }
        // epPassword is optional. So, the code should not break.
        if(epPassword == NULL)
            epPassword = &myPassword;

        msgLen = MSGID_LEN + MSG_LEN + 
                 MSG_STRING_LEN + // KeychainID length
                 keychainIDLen + // Keychain ID
                 MSG_STRING_LEN + // SecretID length
                 secretIDLen + // SecretID
                 MSG_STRING_LEN + // Secret Value Length
                 secretData->len +
                 MSG_STRING_LEN + // epPassword len
                 epPassword->pwordLen; 

		// is there an ext
		if (ext)
		{
			// The login capture on Windows determines the LUID of the user
			// and sends it as an Extension, marshall it across the pipe
			// see the WriteSecret verb for handling it.
			if (ext->extID == WINDOWS_LOGIN_ID)
			{
				// 4 byte ext type, 4 byte len and 8 bytes of LUID
				msgLen += MSG_DWORD_LEN + MSG_DWORD_LEN + WINDOWS_LUID_LEN;   				
				// as setup in the capture module
				//ext.extID = WINDOWS_LOGON_ID;
				//ext.version = 0x00010000;  // 1.0.0
				//ext.ext = (void *)lpLogonId;
				// _LUID {  DWORD LowPart;  LONG HighPart; // 8 byte 
			}						
                        else
                            msgLen += MSG_DWORD_LEN;
		}
		else
		{
			// the cache daemon expects a ext, add it here
			msgLen += MSG_DWORD_LEN;
		}

        if( msgLen > MIN_REQUEST_BUF_LEN )
        {        
            tmpBuf = (Byte*)malloc(msgLen);
            if( NULL == tmpBuf )
            {
                retCode = NSSCS_E_SYSTEM_FAILURE;
                break;
            }
            memset(tmpBuf,0,msgLen);
            pReq = tmpBuf;
        }
        else
        {
            pReq = gpReqBuf;
        }        

        msgid = REQ_CACHE_WRITE_SECRET_MSGID;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);
        pReq += MSG_LEN;
        memcpy(pReq, &keychainIDLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq,keychainID->keychainID,keychainIDLen );
        pReq += keychainIDLen;
        memcpy(pReq, &secretIDLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq, secretID->id,secretIDLen);
        pReq += secretIDLen;
        memcpy(pReq, &(secretData->len), MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq, secretData->data, secretData->len);
        pReq += secretData->len;
        memcpy(pReq, &(epPassword->pwordLen), MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq, epPassword->pword, epPassword->pwordLen);
        pReq += epPassword->pwordLen;
		
        // marshall the extension if there is one
		if (ext)
		{
			if (ext->extID == WINDOWS_LOGIN_ID)
			{
				extID = EXT_TYPE_WINDOWS_LUID;
				memcpy(pReq, &extID, MSG_DWORD_LEN);
				pReq += MSG_DWORD_LEN;

				luidLen = WINDOWS_LUID_LEN;
				memcpy(pReq, &luidLen, MSG_DWORD_LEN);
				pReq += MSG_DWORD_LEN;
				
				memcpy(pReq, ext->ext, 8);
				pReq += 8;
  			}
                        else
                        {
                            uint32_t extID = 0;
                            memcpy(pReq,&extID,MSG_DWORD_LEN); 
                            
                        }
		}
                else
                {
                    uint32_t extID = 0;
                    memcpy(pReq,&extID,MSG_DWORD_LEN);
                }

        if(tmpBuf != NULL)
        {
            retVal = IPC_WRITE(*(int *)ssHandle->platHandle,tmpBuf,msgLen);
        }
        else
        {
            retVal = IPC_WRITE(*(int *)ssHandle->platHandle,gpReqBuf, msgLen);
        }
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;     
        }

        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_GENERAL);
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&sockReturn, pReply, MSG_DWORD_LEN);
        retCode = mapReturnCode(sockReturn);

    }while(0);

    if( tmpBuf != NULL )
    {
        free(tmpBuf);
        tmpBuf = NULL;
    }
    return retCode;
}

int32_t ipc_RemoveSecret
(
    SSCS_SECRETSTORE_HANDLE_T *ssHandle,
    SSCS_KEYCHAIN_ID_T        *keychainID,
    SSCS_SECRET_ID_T          *secretID,
    SSCS_PASSWORD_T           *epPassword
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;

    uint16_t  msgid       = 0;
    uint32_t keychainIDLen = 0;
    uint32_t secretIDLen   = 0;
    uint32_t msgLen        = 0;

    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if( (NULL == ssHandle) || (NULL == ssHandle->platHandle) ||
            (NULL == keychainID) || (NULL == secretID) )
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }

        // Prepare Request buffer
        keychainIDLen = keychainID->len;
        secretIDLen = secretID->len;

        if( keychainIDLen > NSSS_MAX_KEYCHAIN_ID_CHARS ||
            secretIDLen > NSSS_MAX_SECRET_ID_CHARS )
        {
            retCode = NSSS_E_SECRET_ID_TOO_LONG;
            break;
        }
        msgLen = MSGID_LEN + MSG_LEN +
                        MSG_STRING_LEN + // KeychainID length
                        keychainIDLen + // Keychain ID
                        MSG_STRING_LEN + // SecretID length
                        secretIDLen + // SecretID
                        MSG_STRING_LEN ; // epPassword len
        if( epPassword )
        {
            msgLen += epPassword->pwordLen;
        }

        pReq = gpReqBuf;

        msgid = REQ_CACHE_REMOVE_SECRET_MSGID;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);
        pReq += MSG_LEN;
        memcpy(pReq, &keychainIDLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq,keychainID->keychainID, keychainIDLen);
        pReq += keychainIDLen;
        memcpy(pReq, &secretIDLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq, secretID->id, secretIDLen);
        pReq += secretIDLen;

        if(epPassword)
        {
            memcpy(pReq, &(epPassword->pwordLen), MSG_STRING_LEN);
            pReq += MSG_STRING_LEN;
            memcpy(pReq, epPassword->pword, epPassword->pwordLen);
            pReq += epPassword->pwordLen;
        }
        else
        {
            int pwordlen = 0;
            memcpy(pReq, &pwordlen, MSG_STRING_LEN);
        }

        retVal = IPC_WRITE(*(int *)ssHandle->platHandle, gpReqBuf, msgLen);
        if(retVal < 0)
        {
                //log debug info here
                retCode = NSSCS_E_SYSTEM_FAILURE;
                break;
        }

        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_GENERAL);
        if(retVal < 0)
        {
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;           
        }
        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&sockReturn, pReply, MSG_DWORD_LEN);
        retCode = mapReturnCode(sockReturn);

    }while(0);

    return retCode;
}

int32_t  ipc_GetSecretStoreInfo
(
    SSCS_SECRETSTORE_HANDLE_T *ssHandle,
    SSCS_SECRETSTORE_INFO_T *ssInfo
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;

    uint16_t msgid = 0;
    uint32_t msgLen  = 0;
    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if((NULL == ssHandle) || (NULL == ssHandle->platHandle))
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }

        if( NULL == ssInfo ) 
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }

        // Prepare Request buffer
        msgLen = MSGID_LEN + MSG_LEN;

        if( msgLen > MIN_REQUEST_BUF_LEN )
        {
            //Allocate more memory for gpReqBuf
        }
        pReq = gpReqBuf;
        msgid = REQ_GET_SECRETSTORE_INFO_MSGID;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);
        pReq += MSG_LEN;

        retVal = IPC_WRITE(*(int *)ssHandle->platHandle, gpReqBuf, msgLen);
        if(retVal < 0)
        {
            //log debug info here
            retCode = SSCS_E_SYSTEM_ERROR;       
            break;  
        }

        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply,
                              MSG_REPLY_GETSSINFO);
        if(retVal < 0)
        {
            //log debug info here
            retCode = SSCS_E_SYSTEM_ERROR;
            break;
        }

        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&(ssInfo->numKeyChains),pReply,MSG_DWORD_LEN);
        pReply += MSG_DWORD_LEN;

        memcpy(&sockReturn, pReply, MSG_DWORD_LEN);

        if(sockReturn != SSCS_REPLY_SUCCESS)
        {
            DMSG(("Ret code :%d\n",sockReturn));
        }
        retCode = sockReturn;
    }while(0);

    return retCode; // map return code
}

int32_t  ipc_GetKeychainInfo
(
    SSCS_SECRETSTORE_HANDLE_T *ssHandle,
    SSCS_KEYCHAIN_ID_T        *keychainID,
    SSCS_KEYCHAIN_INFO_T      *kcInfo
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;

    uint16_t msgid = 0;
    uint32_t msgLen  = 0;
    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if((NULL == ssHandle) || (NULL == ssHandle->platHandle))
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }
        if( (NULL == keychainID) || (NULL == kcInfo) )
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }

        // Prepare Request buffer
        msgLen = MSGID_LEN + MSG_LEN + MSG_DWORD_LEN +
                 (keychainID->len );

        if( msgLen > MIN_REQUEST_BUF_LEN )
        {
            //Allocate more memory for gpReqBuf
        }
        pReq = gpReqBuf;
        msgid = REQ_GET_KEYCHAIN_INFO_MSGID;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);
        pReq += MSG_LEN;
        memcpy(pReq,&(keychainID->len),MSG_LEN);
        pReq += MSG_LEN;
        memcpy(pReq,keychainID->keychainID,keychainID->len);

        retVal = IPC_WRITE(*(int *)ssHandle->platHandle, gpReqBuf, msgLen);
        if(retVal < 0)
        {
           //log debug info here
           retCode = NSSCS_E_SYSTEM_FAILURE;  
           break;
        }

        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply,MSG_REPLY_GETKEYCHAIN_INFO);
        if(retVal < 0)
        {
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&(kcInfo->flags),pReply,MSG_DWORD_LEN);
        pReply += MSG_DWORD_LEN;
        memcpy(&(kcInfo->numSecrets),pReply,MSG_DWORD_LEN);
        pReply += MSG_DWORD_LEN;
        memcpy(&(kcInfo->numOfDeletedSecs),pReply,MSG_DWORD_LEN);
        pReply += MSG_DWORD_LEN;

        memcpy(&sockReturn, pReply, MSG_DWORD_LEN);

        if(sockReturn != SSCS_REPLY_SUCCESS)
        {
            DMSG(("Ret code :%d\n",sockReturn));
        }
        retCode = sockReturn;

    }while(0);

    return retCode; 

}

int32_t  ipc_LockCache
(
    SSCS_SECRETSTORE_HANDLE_T *ssHandle
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;

    uint16_t msgid = 0;
    uint32_t msgLen = 0;

    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if((NULL == ssHandle) || (NULL == ssHandle->platHandle))
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }

        // Prepare Request buffer
        msgLen = MSGID_LEN + MSG_LEN;

        pReq = gpReqBuf;
        msgid = REQ_LOCK_CACHE_MSGID;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);

        retVal = IPC_WRITE(*(int *)ssHandle->platHandle, gpReqBuf, msgLen);
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }
        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_GENERAL)
;
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&sockReturn, pReply, MSG_DWORD_LEN);

        if(sockReturn != SSCS_REPLY_SUCCESS)
        {
            DMSG(("Ret code :%d\n",sockReturn));
        }
        retCode = sockReturn;

    }while(0);
    return retCode; // map return code

}

int32_t ipc_UnlockCache
(
    SSCS_SECRETSTORE_HANDLE_T *ssHandle,
    SSCS_PASSCODE_T *passcode
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;

    uint16_t msgid = 0;
    uint32_t msgLen  = 0;

    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if((NULL == ssHandle) || (NULL == ssHandle->platHandle))
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }

        // Prepare Request buffer
        msgLen = MSGID_LEN + MSG_LEN;

        pReq = gpReqBuf;
        msgid = REQ_UNLOCK_CACHE_MSGID;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);

        retVal = IPC_WRITE(*(int *)ssHandle->platHandle, gpReqBuf, msgLen);
        if(retVal < 0)
        {
           // log debug info here
            retCode = SSCS_E_SYSTEM_ERROR;
            break;
        }
        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_GENERAL);
        if(retVal < 0)
        {
            //log debug info here
            retCode = SSCS_E_SYSTEM_ERROR;
            break;
        }
        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&sockReturn, pReply, MSG_DWORD_LEN);

        if(sockReturn != SSCS_REPLY_SUCCESS)
        {
            DMSG(("Ret code :%d\n",sockReturn));
        }
        retCode = sockReturn;

    }while(0);

    return retCode; // map return code

}

int32_t ipc_SetMasterPasscode
(
    SSCS_SECRETSTORE_HANDLE_T *ssHandle,
    SSCS_PASSCODE_T *passcode
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    uint16_t msgid = 0;
    uint32_t passcodeType = 0;
    uint32_t passcodeLen = 0;
    uint32_t msgLen = 0;

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;

    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if( (NULL == ssHandle) || (NULL == ssHandle->platHandle) ||
            (NULL == passcode) )
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }
        
        passcodeType = passcode->passcodeType;
        passcodeLen = ((SSCS_PASSWORD_T*)(passcode->passcodeHandle))->pwordLen;
       
        
        // Prepare Request buffer
        msgLen = MSGID_LEN + MSG_LEN + 
                 MSG_DWORD_LEN + // passcodetype 
                 MSG_STRING_LEN + //passcodeLen
                 passcodeLen;
                  
        pReq = gpReqBuf;
    
        msgid = REQ_SET_MASTER_PASSCODE;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);
        pReq += MSG_LEN;
        memcpy(pReq, &passcodeType, MSG_DWORD_LEN);
        pReq += MSG_DWORD_LEN;
        memcpy(pReq, &passcodeLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;

        memcpy((SS_UTF8_T*)pReq,((SSCS_PASSWORD_T*)(passcode->passcodeHandle))->pword,passcodeLen);

        retVal = IPC_WRITE(*(int *)ssHandle->platHandle, gpReqBuf, msgLen);
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_GENERAL);
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&sockReturn, pReply, MSG_DWORD_LEN);
        retCode = sockReturn;

    }while(0);

    return retCode;
}

int32_t ipc_ReadKey
(
    SSCS_SECRETSTORE_HANDLE_T *ssHandle,
    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
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    uint32_t dataLen       = 0;
    uint16_t msgid         = 0;
    uint32_t keychainIDLen = 0;
    uint32_t secretIDLen   = 0;
    uint32_t msgLen        = 0;

    SSCS_PASSWORD_T    myPassword = {0,0,""};

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;
    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if((NULL == ssHandle) || (NULL == ssHandle->platHandle) || (NULL == keychainID) || (NULL == secretID) || (NULL == bytesRequired))
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }

        // Prepare Request buffer
        
        keychainIDLen = keychainID->len;
        secretIDLen   = secretID->len;

        if( keychainIDLen > NSSS_MAX_KEYCHAIN_ID_CHARS || 
            secretIDLen > NSSS_MAX_SECRET_ID_CHARS )
        {
            retCode = NSSS_E_SECRET_ID_TOO_LONG;
            break;
        }
        // epPassword is optional. So, the code should not break.
        if( NULL == epPassword )
            epPassword = &myPassword;
        msgLen = MSGID_LEN + MSG_LEN + 
                 MSG_STRING_LEN + // KeychainID length
                 keychainIDLen + // Keychain ID
                 MSG_STRING_LEN + // SecretID length
                 secretIDLen + // SecretID
                 MSG_STRING_LEN + //keyLen
                 keyLen + //key
                 MSG_STRING_LEN + // epPassword len
                 epPassword->pwordLen; 
            
        pReq = gpReqBuf;
        msgid = REQ_READ_KEY_MSGID;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);
        pReq += MSG_LEN;
        memcpy(pReq, &keychainIDLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq,keychainID->keychainID,keychainIDLen);
        pReq += keychainIDLen ;
        memcpy(pReq, &secretIDLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq, secretID->id, secretIDLen);
        pReq += secretIDLen;
        
        memcpy(pReq, &keyLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq, key, keyLen);
        pReq += keyLen;
 
        memcpy(pReq, &(epPassword->pwordLen), MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq, epPassword->pword, epPassword->pwordLen);
        pReq += epPassword->pwordLen;

        retVal = IPC_WRITE(*(int *)ssHandle->platHandle, gpReqBuf, msgLen);
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_GENERAL);
        if( 0 == retVal )
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&dataLen,pReply, MSG_DWORD_LEN);
        if( 0 == dataLen )
        {
            // Cleanup the channel by reading the return code.
            retVal = IPC_READ(*(int *)ssHandle->platHandle,&sockReturn, MSG_DWORD_LEN);
            if( retVal < 0 )
            {
                retCode = NSSCS_E_SYSTEM_FAILURE;
                break;
            }
            retCode = mapReturnCode(sockReturn);
            break;
        }
        // Let me check if the buffer passed by application is big enough
        if(dataLen <= *valLen)
        {
            // Read the secret into application buffer.
            retVal = IPC_READ(*(int *)ssHandle->platHandle, val, dataLen);
            if( retVal < 0 )
            {
                retCode = NSSCS_E_SYSTEM_FAILURE;
                break;
            }
			// set the length of the data
			*valLen = dataLen;
            
        }
        else
        {
        //buffer allocated by application is not sufficient to hold the data.
            *bytesRequired = dataLen;
            {
                // Cleanup the channel by reading the remaining and return error.
                int n;
                n = dataLen; 
                while(n)
                {
                    int bytes = IPC_READ(*(int *)ssHandle->platHandle, gpReplyBuf, MIN_REPLY_BUF_LEN);
                    if( bytes > 0)
                        n -= MIN_REPLY_BUF_LEN;
                    else
                        break;
                }
                // Read the sscs return code also.
                IPC_READ(*(int *)ssHandle->platHandle, (Byte *) &sockReturn, MSG_DWORD_LEN);
                retCode = NSSCS_E_ENUM_BUFF_TOO_SHORT;
                break;
            }
        }
        // Read the sscs return code also.
        IPC_READ(*(int *)ssHandle->platHandle, (Byte *) &sockReturn, MSG_DWORD_LEN);
        retCode = mapReturnCode(sockReturn);

    } while(0);
    return retCode;
}

int32_t ipc_ReadBinaryKey
(
    SSCS_SECRETSTORE_HANDLE_T *ssHandle,
    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
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    uint32_t dataLen       = 0;
    uint16_t msgid         = 0;
    uint32_t keychainIDLen = 0;
    uint32_t secretIDLen   = 0;
    uint32_t msgLen        = 0;

    SSCS_PASSWORD_T    myPassword = {0,0,""};

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;
    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if((NULL == ssHandle) || (NULL == ssHandle->platHandle) || (NULL == keychainID) || (NULL == secretID) || (NULL == bytesRequired))
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }

        // Prepare Request buffer        
        keychainIDLen = keychainID->len;
        secretIDLen   = secretID->len;

        if( keychainIDLen > NSSS_MAX_KEYCHAIN_ID_CHARS || 
            secretIDLen > NSSS_MAX_SECRET_ID_CHARS )
        {
            retCode = NSSS_E_SECRET_ID_TOO_LONG;
            break;
        }
        // epPassword is optional. So, the code should not break.
        if( NULL == epPassword )
            epPassword = &myPassword;
        msgLen = MSGID_LEN + MSG_LEN + 
                 MSG_STRING_LEN + // KeychainID length
                 keychainIDLen + // Keychain ID
                 MSG_STRING_LEN + // SecretID length
                 secretIDLen + // SecretID
                 MSG_STRING_LEN + //keyLen
                 keyLen + //key
                 MSG_STRING_LEN + // epPassword len
                 epPassword->pwordLen; 
            
        pReq = gpReqBuf;
        msgid = REQ_READ_BINARY_KEY_MSGID;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);
        pReq += MSG_LEN;
        memcpy(pReq, &keychainIDLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq,keychainID->keychainID,keychainIDLen);
        pReq += keychainIDLen ;
        memcpy(pReq, &secretIDLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq, secretID->id, secretIDLen);
        pReq += secretIDLen;
        
        memcpy(pReq, &keyLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq, key, keyLen);
        pReq += keyLen;
 
        memcpy(pReq, &(epPassword->pwordLen), MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq, epPassword->pword, epPassword->pwordLen);
        pReq += epPassword->pwordLen;

        retVal = IPC_WRITE(*(int *)ssHandle->platHandle, gpReqBuf, msgLen);
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_GENERAL);
        if( 0 == retVal )
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&dataLen,pReply, MSG_DWORD_LEN);
        if( 0 == dataLen )
        {
            // Cleanup the channel by reading the return code.
            retVal = IPC_READ(*(int *)ssHandle->platHandle,&sockReturn, MSG_DWORD_LEN);
            if( retVal < 0 )
            {
                retCode = NSSCS_E_SYSTEM_FAILURE;
                break;
            }
            retCode = mapReturnCode(sockReturn);
            break;
        }
        // Let me check if the buffer passed by application is big enough
        if(dataLen <= *valLen)
        {
            // Read the secret into application buffer.
            retVal = IPC_READ(*(int *)ssHandle->platHandle, val, dataLen);
            if( retVal < 0 )
            {
                retCode = NSSCS_E_SYSTEM_FAILURE;
                break;
            }
			*valLen = dataLen;
            
        }
        else
        {
        //buffer allocated by application is not sufficient to hold the data.
            *bytesRequired = dataLen;
            {
                // Cleanup the channel by reading the remaining and return error.
                int n;
                n = dataLen; 
                while(n)
                {
                    int bytes = IPC_READ(*(int *)ssHandle->platHandle, gpReplyBuf, MIN_REPLY_BUF_LEN);
                    if( bytes > 0)
                        n -= MIN_REPLY_BUF_LEN;
                    else
                        break;
                }
                // Read the sscs return code also.
                IPC_READ(*(int *)ssHandle->platHandle, (Byte *) &sockReturn, MSG_DWORD_LEN);
                retCode = NSSCS_E_ENUM_BUFF_TOO_SHORT;
                break;
            }
        }
        // Read the sscs return code also.
        IPC_READ(*(int *)ssHandle->platHandle, (Byte *) &sockReturn, MSG_DWORD_LEN);
        retCode = mapReturnCode(sockReturn);

    } while(0);
    return retCode;
}

int ipc_WriteKey
(
    SSCS_SECRETSTORE_HANDLE_T *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,
    SSCS_EXT_T				  *ext
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;
    Byte *tmpBuf = NULL;

    uint16_t msgid		   = 0;
    uint32_t keychainIDLen = 0;
    uint32_t secretIDLen   = 0;
    uint32_t msgLen        = 0;

    uint32_t extID		   = 0;
    uint32_t luidLen	   = 0; 
	

    SSCS_PASSWORD_T    myPassword = {0,0,""};
    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if((NULL == ssHandle) || (NULL == ssHandle->platHandle) || (NULL == keychainID) || (NULL == secretID) ||(NULL == key))
        {
            retCode = NSSCS_E_INVALID_PARAM; 
            break;
        }
    
        // Prepare Request buffer

        keychainIDLen = keychainID->len;
        secretIDLen   = secretID->len;

        if( keychainIDLen > NSSS_MAX_KEYCHAIN_ID_CHARS || 
                  secretIDLen > NSSS_MAX_SECRET_ID_CHARS )
        {
            retCode = NSSS_E_SECRET_ID_TOO_LONG;
            break;
        }
        // epPassword is optional. So, the code should not break.
        if(epPassword == NULL)
            epPassword = &myPassword;

        msgLen = MSGID_LEN + MSG_LEN + 
                 MSG_STRING_LEN + // KeychainID length
                 keychainIDLen + // Keychain ID
                 MSG_STRING_LEN + // SecretID length
                 secretIDLen + // SecretID
                 MSG_STRING_LEN + // Secret Value Length
                 keyLen +
                 MSG_STRING_LEN + 
                 valLen +
                 MSG_STRING_LEN + // epPassword len
                 epPassword->pwordLen; 

		// is there an ext, account for it
		if (ext)
		{
			// The login capture on Windows determines the LUID of the user
			// and sends it as an Extension, marshall it across the pipe
			// see the WriteSecret verb for handling it.
			if (ext->extID == WINDOWS_LOGIN_ID)
			{
				// 4 byte ext type, 4 byte len and 8 bytes of LUID
				msgLen += MSG_DWORD_LEN + MSG_DWORD_LEN + WINDOWS_LUID_LEN;   				
				// as setup in the capture module
				//ext.extID = WINDOWS_LOGON_ID;
				//ext.version = 0x00010000;  // 1.0.0
				//ext.ext = (void *)lpLogonId;
				// _LUID {  DWORD LowPart;  LONG HighPart; // 8 byte 
			}						
                        else
                            msgLen += MSG_DWORD_LEN;
		}
		else
		{
			// the cache daemon expects a ext, add it here
			msgLen += MSG_DWORD_LEN;
		}

        if( msgLen > MIN_REQUEST_BUF_LEN )
        {        
            tmpBuf = (Byte*)malloc(msgLen);
            if( NULL == tmpBuf )
            {
                retCode = NSSCS_E_SYSTEM_FAILURE;
                break;
            }
            memset(tmpBuf,0,msgLen);
            pReq = tmpBuf;
        }
        else
        {
            pReq = gpReqBuf;
        }        

		msgid = REQ_WRITE_KEY_MSGID;

        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);
        pReq += MSG_LEN;
        memcpy(pReq, &keychainIDLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq,keychainID->keychainID,keychainIDLen );
        pReq += keychainIDLen;
        memcpy(pReq, &secretIDLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq, secretID->id,secretIDLen);
        pReq += secretIDLen;

        memcpy(pReq,&keyLen,MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq,key,keyLen);
        pReq += keyLen;
        memcpy(pReq,&valLen,MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;       
        memcpy(pReq,val,valLen);
        pReq += valLen;

        memcpy(pReq, &(epPassword->pwordLen), MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq, epPassword->pword, epPassword->pwordLen);
        pReq += epPassword->pwordLen;
		
        // marshall the extension if there is one
		if (ext)
		{
			if (ext->extID == WINDOWS_LOGIN_ID)
			{
				extID = EXT_TYPE_WINDOWS_LUID;
				memcpy(pReq, &extID, MSG_DWORD_LEN);
				pReq += MSG_DWORD_LEN;

				luidLen = WINDOWS_LUID_LEN;
				memcpy(pReq, &luidLen, MSG_DWORD_LEN);
				pReq += MSG_DWORD_LEN;
				
				memcpy(pReq, ext->ext, 8);
				pReq += 8;
  			}
            else
            {
                uint32_t extID = 0;
                memcpy(pReq,&extID,MSG_DWORD_LEN); 
                
            }
		}
        else
        {
			uint32_t extID = 0;
            memcpy(pReq,&extID,MSG_DWORD_LEN);
        }

        if(tmpBuf != NULL)
        {
            retVal = IPC_WRITE(*(int *)ssHandle->platHandle,tmpBuf,msgLen);
        }
        else
        {
            retVal = IPC_WRITE(*(int *)ssHandle->platHandle,gpReqBuf, msgLen);
        }
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;     
        }

        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_GENERAL);
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&sockReturn, pReply, MSG_DWORD_LEN);
        retCode = mapReturnCode(sockReturn);

    }while(0);

    if( tmpBuf != NULL )
    {
        free(tmpBuf);
        tmpBuf = NULL;
    }
    return retCode;
}



int ipc_WriteBinaryKey
(
    SSCS_SECRETSTORE_HANDLE_T *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,
    SSCS_EXT_T				  *ext
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;
    Byte *tmpBuf = NULL;

    uint16_t msgid		   = 0;
    uint32_t keychainIDLen = 0;
    uint32_t secretIDLen   = 0;
    uint32_t msgLen        = 0;

    uint32_t extID		   = 0;
    uint32_t luidLen	   = 0; 
	

    SSCS_PASSWORD_T    myPassword = {0,0,""};
    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if((NULL == ssHandle) || (NULL == ssHandle->platHandle) || (NULL == keychainID) || (NULL == secretID) ||(NULL == key))
        {
            retCode = NSSCS_E_INVALID_PARAM; 
            break;
        }
    
        // Prepare Request buffer

        keychainIDLen = keychainID->len;
        secretIDLen   = secretID->len;

        if( keychainIDLen > NSSS_MAX_KEYCHAIN_ID_CHARS || 
                  secretIDLen > NSSS_MAX_SECRET_ID_CHARS )
        {
            retCode = NSSS_E_SECRET_ID_TOO_LONG;
            break;
        }
        // epPassword is optional. So, the code should not break.
        if(epPassword == NULL)
            epPassword = &myPassword;

        msgLen = MSGID_LEN + MSG_LEN + 
                 MSG_STRING_LEN + // KeychainID length
                 keychainIDLen + // Keychain ID
                 MSG_STRING_LEN + // SecretID length
                 secretIDLen + // SecretID
                 MSG_STRING_LEN + // Secret Value Length
                 keyLen +
                 MSG_STRING_LEN + 
                 valLen +
                 MSG_STRING_LEN + // epPassword len
                 epPassword->pwordLen; 

		// is there an ext, account for it
		if (ext)
		{
			// The login capture on Windows determines the LUID of the user
			// and sends it as an Extension, marshall it across the pipe
			// see the WriteSecret verb for handling it.
			if (ext->extID == WINDOWS_LOGIN_ID)
			{
				// 4 byte ext type, 4 byte len and 8 bytes of LUID
				msgLen += MSG_DWORD_LEN + MSG_DWORD_LEN + WINDOWS_LUID_LEN;   				
				// as setup in the capture module
				//ext.extID = WINDOWS_LOGON_ID;
				//ext.version = 0x00010000;  // 1.0.0
				//ext.ext = (void *)lpLogonId;
				// _LUID {  DWORD LowPart;  LONG HighPart; // 8 byte 
			}						
                        else
                            msgLen += MSG_DWORD_LEN;
		}
		else
		{
			// the cache daemon expects a ext, add it here
			msgLen += MSG_DWORD_LEN;
		}

        if( msgLen > MIN_REQUEST_BUF_LEN )
        {        
            tmpBuf = (Byte*)malloc(msgLen);
            if( NULL == tmpBuf )
            {
                retCode = NSSCS_E_SYSTEM_FAILURE;
                break;
            }
            memset(tmpBuf,0,msgLen);
            pReq = tmpBuf;
        }
        else
        {
            pReq = gpReqBuf;
        }        

		
		msgid = REQ_WRITE_BINARY_KEY_MSGID;		
	
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);
        pReq += MSG_LEN;
        memcpy(pReq, &keychainIDLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq,keychainID->keychainID,keychainIDLen );
        pReq += keychainIDLen;
        memcpy(pReq, &secretIDLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq, secretID->id,secretIDLen);
        pReq += secretIDLen;

        memcpy(pReq,&keyLen,MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq,key,keyLen);
        pReq += keyLen;
        memcpy(pReq,&valLen,MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;       
        memcpy(pReq,val,valLen);
        pReq += valLen;

        memcpy(pReq, &(epPassword->pwordLen), MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;
        memcpy(pReq, epPassword->pword, epPassword->pwordLen);
        pReq += epPassword->pwordLen;
		
        // marshall the extension if there is one
		if (ext)
		{
			if (ext->extID == WINDOWS_LOGIN_ID)
			{
				extID = EXT_TYPE_WINDOWS_LUID;
				memcpy(pReq, &extID, MSG_DWORD_LEN);
				pReq += MSG_DWORD_LEN;

				luidLen = WINDOWS_LUID_LEN;
				memcpy(pReq, &luidLen, MSG_DWORD_LEN);
				pReq += MSG_DWORD_LEN;
				
				memcpy(pReq, ext->ext, 8);
				pReq += 8;
  			}
            else
            {
                uint32_t extID = 0;
                memcpy(pReq,&extID,MSG_DWORD_LEN); 
                
            }
		}
        else
        {
			uint32_t extID = 0;
            memcpy(pReq,&extID,MSG_DWORD_LEN);
        }

        if(tmpBuf != NULL)
        {
            retVal = IPC_WRITE(*(int *)ssHandle->platHandle,tmpBuf,msgLen);
        }
        else
        {
            retVal = IPC_WRITE(*(int *)ssHandle->platHandle,gpReqBuf, msgLen);
        }
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;     
        }

        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_GENERAL);
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&sockReturn, pReply, MSG_DWORD_LEN);
        retCode = mapReturnCode(sockReturn);

    }while(0);

    if( tmpBuf != NULL )
    {
        free(tmpBuf);
        tmpBuf = NULL;
    }
    return retCode;
}


int32_t ipc_SetMasterPassword
(
    SSCS_SECRETSTORE_HANDLE_T *ssHandle,
    SSCS_PASSWORD_T *passwd,
    SSCS_HINT_T *hint
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    uint16_t msgid = 0;
    uint32_t passwdType = 0;
    uint32_t passwdLen = 0;
    uint32_t msgLen = 0;

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;

    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if( (NULL == ssHandle) || (NULL == ssHandle->platHandle) ||
            (NULL == passwd) )
        {
            retCode = NSSCS_E_INVALID_PARAM;
            break;
        }
        
        passwdType = passwd->pwordType;
        passwdLen  = passwd->pwordLen;
       
        
        // Prepare Request buffer
        msgLen = MSGID_LEN + MSG_LEN + 
                 MSG_DWORD_LEN + // passwdtype 
                 MSG_STRING_LEN + //passwdLen
                 passwdLen;
                  
        pReq = gpReqBuf;
    
        msgid = REQ_SET_MASTER_PASSWORD;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);
        pReq += MSG_LEN;
        memcpy(pReq, &passwdType, MSG_DWORD_LEN);
        pReq += MSG_DWORD_LEN;
        memcpy(pReq, &passwdLen, MSG_STRING_LEN);
        pReq += MSG_STRING_LEN;

        memcpy((SS_UTF8_T*)pReq,passwd->pword,passwdLen);

        retVal = IPC_WRITE(*(int *)ssHandle->platHandle, gpReqBuf, msgLen);
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_GENERAL);
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&sockReturn, pReply, MSG_DWORD_LEN);
        retCode = sockReturn;

    }while(0);

    return retCode;
}

int ipc_IsSecretPersistent
(
    SSCS_SECRETSTORE_HANDLE_T *ssHandle,
    uint32_t                  ssFlags,
    SSCS_KEYCHAIN_ID_T        *keychainID,
    SSCS_SECRET_ID_T          *secretID,
    SSCS_EXT_T				  *ext
)
{
    int retVal         = 0; //to be used in the function internally
    int32_t retCode    = NSSCS_SUCCESS; //to be returned to caller
    int32_t sockReturn = 0; //obtained from the server

    Byte gpReqBuf[MIN_REQUEST_BUF_LEN];
    Byte gpReplyBuf[MIN_REPLY_BUF_LEN];
    Byte *pReq = NULL, *pReply = NULL;
    Byte *tmpBuf = NULL;

    uint16_t msgid		   = 0;
    uint32_t keychainIDLen = 0;
    uint32_t secretIDLen   = 0;
    uint32_t msgLen        = 0;

    memset(gpReqBuf,0,sizeof(gpReqBuf));
    memset(gpReplyBuf,0,sizeof(gpReplyBuf));

    do
    {
        if((NULL == ssHandle) || (NULL == ssHandle->platHandle))
        {
            retCode = NSSCS_E_INVALID_PARAM; 
            break;
        }

        if(ssFlags == 0)
        {
            if( (NULL == keychainID) || ( NULL == secretID ))
            {
                retCode = NSSCS_E_INVALID_PARAM; 
                break;
            }
        }

        // Prepare Request buffer

        if( ssFlags == 0 )
        {
            keychainIDLen = keychainID->len;
            secretIDLen   = secretID->len;

            if( keychainIDLen > NSSS_MAX_KEYCHAIN_ID_CHARS || 
                      secretIDLen > NSSS_MAX_SECRET_ID_CHARS )
            {
                retCode = NSSS_E_SECRET_ID_TOO_LONG;
                break;
            }
            msgLen = MSGID_LEN + MSG_LEN + 
                     MSG_DWORD_LEN + //ssFlags
                     MSG_STRING_LEN + // KeychainID length
                     keychainIDLen + // Keychain ID
                     MSG_STRING_LEN + // SecretID length
                     secretIDLen; // SecretID
        }
        else
        {
            msgLen = MSGID_LEN + MSG_LEN + 
                     MSG_DWORD_LEN; //ssFlags
        }

        if( msgLen > MIN_REQUEST_BUF_LEN )
        {        
            tmpBuf = (Byte*)malloc(msgLen);
            if( NULL == tmpBuf )
            {
                retCode = NSSCS_E_SYSTEM_FAILURE;
                break;
            }
            memset(tmpBuf,0,msgLen);
            pReq = tmpBuf;
        }
        else
        {
            pReq = gpReqBuf;
        }        

        msgid = REQ_IS_SECRET_PERSISTENT;
        memcpy(pReq, &msgid, MSGID_LEN);
        pReq += MSGID_LEN;
        memcpy(pReq, &msgLen, MSG_LEN);
        pReq += MSG_LEN;
        memcpy(pReq,&ssFlags,MSG_DWORD_LEN);
        pReq += MSG_DWORD_LEN;
  
        if( ssFlags == 0 )
        {
            memcpy(pReq, &keychainIDLen, MSG_STRING_LEN);
            pReq += MSG_STRING_LEN;
            memcpy(pReq,keychainID->keychainID,keychainIDLen );
            pReq += keychainIDLen;
            memcpy(pReq, &secretIDLen, MSG_STRING_LEN);
            pReq += MSG_STRING_LEN;
            memcpy(pReq, secretID->id,secretIDLen);
            pReq += secretIDLen;
        }
        if(tmpBuf != NULL)
        {
            retVal = IPC_WRITE(*(int *)ssHandle->platHandle,tmpBuf,msgLen);
        }
        else
        {
            retVal = IPC_WRITE(*(int *)ssHandle->platHandle,gpReqBuf, msgLen);
        }
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;     
        }

        // Read reply
        pReply = gpReplyBuf;
        retVal = IPC_READ(*(int *)ssHandle->platHandle, pReply, MSG_REPLY_GENERAL);
        if(retVal < 0)
        {
            //log debug info here
            retCode = NSSCS_E_SYSTEM_FAILURE;
            break;
        }

        memcpy(&msgid,pReply, MSGID_LEN);
        pReply += MSGID_LEN;
        memcpy(&msgLen,pReply, MSG_LEN);
        pReply += MSG_LEN;
        memcpy(&sockReturn, pReply, MSG_DWORD_LEN);
        if( (sockReturn == SSCS_SECRET_IS_PERSISTENT) ||
            (sockReturn == SSCS_STORE_IS_PERSISTENT) )
            retCode = 1;
        else if( (sockReturn == SSCS_SECRET_IS_NOT_PERSISTENT) ||
                 (sockReturn == SSCS_STORE_IS_NOT_PERSISTENT) )
             retCode = 0;
        else
            retCode = mapReturnCode(sockReturn);
    }while(0);

    if( tmpBuf != NULL )
    {
        free(tmpBuf);
        tmpBuf = NULL;
    }
    return retCode;
}