/**@@@+++@@@@******************************************************************
**
** Microsoft Windows Media
** Copyright (C) Microsoft Corporation. All rights reserved.
**
***@@@---@@@@******************************************************************
*/

#include <drmcommon.h>
#include <drmutilities.h>
#include <drmcrt.h>
#include <drmcontextsizes.h>
#include <drmpkcrypto.h>
#include <drmcipher.h>
#include <drmsha1.h>
#include <drmmanager.h>
#include <oemimpl.h>
#include "DX_VOS_BaseTypes.h"
#include "SEPDriver.h"
#include "error.h"
#include "wmdrm_host_op_code.h" 
#include "DX_VOS_Mem.h"
#include "CRYS.h"
#define HASH_RESIDUAL_LEN 6
#define LEGACY_KID_B64ENC_LEN   24
#define MAX_HOST_BBX_OPERATION_DATA_LENGTH   0x5C00


static DRM_RESULT DRM_BBX_sendBbxContext(IN DRM_BB_CONTEXT     *pcontextBBX,
							  IN OUT DRM_ULONG *sramOffset_ptr)
{
	DRM_RESULT Error;
    /* max length of field */
    DRM_ULONG   maxLength;

	/* send opcode */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&pcontextBBX->fInited,
                            sizeof(DRM_ULONG),
                            sizeof(DRM_ULONG),
                            sramOffset_ptr,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function;
   }
   
   /* send cache  */
   
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(DRM_DEVICE_CERTIFICATE_CACHED_VALUES));

   Error = SEPDriver_WriteParamater((DRM_DWORD)&pcontextBBX->cachedCertValues, 
                                    sizeof(DRM_DEVICE_CERTIFICATE_CACHED_VALUES) ,
                                    maxLength, 
                                    sramOffset_ptr , 
                                    DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function;
   }
end_function:
   return Error;
}


DRM_RESULT DRM_API DRM_BBX_Initialize( 
    IN OUT DRM_BB_CONTEXT     *pcontextBBX )
{
   DRM_RESULT Error = DRM_SUCCESS;
   /* offset into SRAM */
   DRM_ULONG   sramOffset;
   /* read param */
   DRM_ULONG   messageParam[2];
   /* max length */
   DRM_ULONG   maxLength;
	/*buffer for encrypt key*/
	DRM_CHAR privkey[OEM_ENC_KEY_BUFF_LEN];
   
   if (!(pcontextBBX != NULL ))
   {                       
       Error = DRM_E_INVALIDARG; 
       goto ErrorExit;     
   }

	OEM_GetEncGroupCertPrivateKey(privkey);
	/* lock access to the SEP */
    Error = SEPDriver_Lock();
	if(Error != DX_OK)
    {
		goto ErrorExit;
	}

   /*----------------------------
      start sending message to SEP 
   -----------------------------*/
   sramOffset = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);
  
   /* prepare message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_INIT_OP_CODE;
   
   /* send opcode */
   Error = SEPDriver_WriteParamater((DRM_ULONG)(&messageParam[0]),
                            sizeof(DRM_ULONG),
                            sizeof(DRM_ULONG),
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /*send the blackbox parameters*/
   Error = DRM_BBX_sendBbxContext(pcontextBBX,&sramOffset);
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }

   /* send encrypt key */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&privkey[0],
                            OEM_ENC_KEY_BUFF_LEN,
                            OEM_ENC_KEY_BUFF_LEN,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_POLL_FOR_REPONSE();
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*-------------------
      start reading message from the SEP 
   ---------------------*/
   
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
      goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG) * 2,
                            sizeof(DRM_ULONG) * 2,
                            &sramOffset ,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_INIT_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check status */
   if(messageParam[1] != DRM_SUCCESS)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }
   
   /* read the context */
   Error = SEPDriver_ReadParamater((DRM_ULONG)&pcontextBBX->fInited,
                           sizeof(DRM_ULONG) ,
                           sizeof(DRM_ULONG) ,
                           &sramOffset ,
                           DX_FALSE);
  /* read the cache */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(DRM_DEVICE_CERTIFICATE_CACHED_VALUES));

   Error = SEPDriver_ReadParamater((DRM_ULONG)&pcontextBBX->cachedCertValues,
                            sizeof(DRM_DEVICE_CERTIFICATE_CACHED_VALUES),
                            maxLength,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
end_function_unlock:   

   /* lock access to the SEP */
   SEPDriver_Unlock();

ErrorExit:
    return Error;
}


DRM_RESULT DRM_API DRM_BBX_Shutdown( IN DRM_BB_CONTEXT *pcontextBBX )
{
    return DRM_SUCCESS;
}

DRM_RESULT DRM_API DRM_BBX_GetClientId(
    OUT    CLIENTID       *pClientId,
    IN OUT DRM_BB_CONTEXT *pcontextBBX )
{
    DRM_RESULT Error = DRM_SUCCESS;
    /* offset into SRAM */
    DRM_ULONG   sramOffset;
    /* read param */
    DRM_ULONG   messageParam[2];
    /* max length */
    DRM_ULONG   maxLength;
	/*buffer for encrypt key*/
	DRM_CHAR privkey[OEM_ENC_KEY_BUFF_LEN];

	if( !((pClientId   != NULL )
         && (pcontextBBX != NULL)
         && pcontextBBX->fInited))
	{                       
       Error = DRM_E_INVALIDARG; 
       goto ErrorExit;     
    }

	OEM_GetEncGroupCertPrivateKey(privkey);
	/* lock access to the SEP */
    Error = SEPDriver_Lock();
	if(Error != DX_OK)
    {
		goto ErrorExit;
	}
   /*----------------------------
      start sending message to SEP 
   -----------------------------*/
   sramOffset = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);
  
   /* prepare message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_GET_CLIENT_ID_OP_CODE;
   
   /* send opcode */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG),
                            sizeof(DRM_ULONG),
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /*send the blackbox parameters*/
   Error = DRM_BBX_sendBbxContext(pcontextBBX,&sramOffset);
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   /* send encrypt key */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&privkey[0],
                            OEM_ENC_KEY_BUFF_LEN,
                            OEM_ENC_KEY_BUFF_LEN,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_POLL_FOR_REPONSE();
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*-------------------
      start reading message from the SEP 
   ---------------------*/
   
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
      goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG) * 2,
                            sizeof(DRM_ULONG) * 2,
                            &sramOffset ,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_GET_CLIENT_ID_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check status */
   if(messageParam[1] != DRM_SUCCESS)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }
   
   /* read the context */
   Error = SEPDriver_ReadParamater((DRM_ULONG)&pcontextBBX->fInited,
                           sizeof(DRM_ULONG) ,
                           sizeof(DRM_ULONG) ,
                           &sramOffset ,
                           DX_FALSE);
  /* read the cache */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(DRM_DEVICE_CERTIFICATE_CACHED_VALUES));

   Error = SEPDriver_ReadParamater((DRM_ULONG)&pcontextBBX->cachedCertValues,
                            sizeof(DRM_DEVICE_CERTIFICATE_CACHED_VALUES),
                            maxLength,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

   /* read the clientId */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(CLIENTID));

   Error = SEPDriver_ReadParamater((DRM_ULONG)pClientId,
                            sizeof(CLIENTID),
                            maxLength,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

end_function_unlock:   

   /* lock access to the SEP */
   SEPDriver_Unlock();

ErrorExit:
    return Error;
}


/*  
    Test whether or not a key is valid and can be used to decrypt
    content.
*/
DRM_BOOL DRM_API DRM_BBX_CanBind( 
    IN const DRM_BINDING_INFO *rgBindingInfo,
    IN       DRM_DWORD         dwChainLength,
    IN       DRM_BB_CONTEXT   *pcontextBBX )
{
    DRM_RESULT Error = DRM_SUCCESS;
	DRM_BOOL		   res = TRUE;
    /* offset into SRAM */
    DRM_ULONG   sramOffset;
    /* read param */
    DRM_ULONG   messageParam[2];
   /* max length */
   DRM_ULONG   maxLength;
	/*buffer for encrypt key*/
	DRM_CHAR privkey[OEM_ENC_KEY_BUFF_LEN];

	if( !(((pcontextBBX != NULL)
         && pcontextBBX->fInited)
		 &&(dwChainLength <= MAX_HOST_BBX_OPERATION_DATA_LENGTH)))
	{                       
       Error = DRM_E_INVALIDARG; 
       goto ErrorExit;     
    }
   
	OEM_GetEncGroupCertPrivateKey(privkey);
	/* lock access to the SEP */
    Error = SEPDriver_Lock();
	if(Error != DX_OK)
    {
		goto ErrorExit;
	}   
   /*----------------------------
      start sending message to SEP 
   -----------------------------*/
   sramOffset = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);
  
   /* prepare message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_CAN_BIND_OP_CODE;
   
   /* send opcode */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG),
                            sizeof(DRM_ULONG) ,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /*send the blackbox parameters*/
   Error = DRM_BBX_sendBbxContext(pcontextBBX,&sramOffset);
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /* send encrypt key */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&privkey[0],
                            OEM_ENC_KEY_BUFF_LEN,
                            OEM_ENC_KEY_BUFF_LEN,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
    /* send length  , instead of sendign the bind info array I send only the one that will be used*/
	/* with the length of 1 */
   maxLength = 1;
   Error = SEPDriver_WriteParamater((DRM_ULONG)&maxLength/*dwChainLength*/ , 
                             sizeof(DRM_DWORD) ,
                             sizeof(DRM_DWORD), 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

   /* send bindInfo  */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(DRM_BINDING_INFO));
	/*send only one object of binding info*/
   Error = SEPDriver_WriteParamater((DRM_ULONG)&rgBindingInfo[dwChainLength - 1] , 
                             sizeof(DRM_BINDING_INFO) ,
                             maxLength, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_POLL_FOR_REPONSE();
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*-------------------
      start reading message from the SEP 
   ---------------------*/
   
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
      goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG) * 2,
                            sizeof(DRM_ULONG) * 2,
                            &sramOffset ,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_CAN_BIND_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check status */
   if(messageParam[1] != DRM_SUCCESS)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }
   
   /* read the result */
   Error = SEPDriver_ReadParamater((DRM_ULONG)&res,
                           sizeof(DRM_ULONG) ,
                           sizeof(DRM_ULONG) ,
                           &sramOffset ,
                           DX_FALSE);

   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
end_function_unlock:   

   /* lock access to the SEP */
   SEPDriver_Unlock();

ErrorExit:
	if(Error != DRM_SUCCESS)
	{
		res = FALSE;
	}
   return res;
}



/*  
    Decrypt a license that was encryted for privacy reasons (not 
    security reasons) while traveling on the net during license
    acquisition.
*/
DRM_BOOL DRM_API DRM_BBX_DecryptLicense(
    IN OUT DRM_BYTE       *pbEncryptedLicense,
    IN     DRM_DWORD       cbEncryptedLicense,
    OUT    DRM_BYTE       *pbLicense,
    IN     DRM_BB_CONTEXT *pcontextBBX )
{
    DRM_RESULT Error = DRM_SUCCESS;

	DRM_BOOL	res = TRUE;
    /* offset into SRAM */
    DRM_ULONG   sramOffset;
    /* read param */
    DRM_ULONG   messageParam[5];
	/*buffer for encrypt key*/
	DRM_CHAR privkey[OEM_ENC_KEY_BUFF_LEN];
#if (LLF_RC4_ENGINE_TYPE==CRYS_DEFS_SW_ENGINE_TYPE)
   /* max length */
   DRM_ULONG   maxLength;
#else
   /* address of the first table in the input list */
   DxUint32_t         firstInputLLITableAddr;
   /* address of the first table in the output list */
   DxUint32_t         firstOutputLLITableAddr;
   /* number of entries in  the first input tables */
   DxUint32_t         numInTableEntries;
   /* number of entries in  the first pitput tables */
   DxUint32_t         numOutTableEntries;
   /* size of data in the first table */
   DxUint32_t         firstTableSize;
#endif   

	if( !(((pcontextBBX != NULL)
         && pcontextBBX->fInited)
#if (LLF_RC4_ENGINE_TYPE==CRYS_DEFS_SW_ENGINE_TYPE)
		 &&(cbEncryptedLicense <= MAX_HOST_BBX_OPERATION_DATA_LENGTH)
#endif
		 ))
	{                       
       Error = DRM_E_INVALIDARG; 
       goto ErrorExit;     
    }
   
	OEM_GetEncGroupCertPrivateKey(privkey);
	/* lock access to the SEP */
    Error = SEPDriver_Lock();
	if(Error != DX_OK)
    {
		goto ErrorExit;
	}
   /*----------------------------
      start sending message to SEP 
   -----------------------------*/
   sramOffset = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);
  
   /* prepare message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_DECRYPT_LICENSE_OP_CODE;
   
   /* send opcode */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG),
                            sizeof(DRM_ULONG) ,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /*send the blackbox parameters*/
   Error = DRM_BBX_sendBbxContext(pcontextBBX,&sramOffset);
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }

   /* send encrypt key */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&privkey[0],
                            OEM_ENC_KEY_BUFF_LEN,
                            OEM_ENC_KEY_BUFF_LEN,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

#if (LLF_RC4_ENGINE_TYPE==CRYS_DEFS_SW_ENGINE_TYPE)
   /* send length */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&cbEncryptedLicense,
                            sizeof(DRM_DWORD),
                            sizeof(DRM_DWORD) ,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

   /* send Encrypt License  */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(cbEncryptedLicense);

   Error = SEPDriver_WriteParamater((DRM_ULONG)pbEncryptedLicense , 
                             cbEncryptedLicense ,
                             maxLength, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

#else
   /* prepare DMA tables */
   /* The first PK_ENC_CIPHERTEXT_LEN bytes are the encrypted key and only the rest are the 
      license data */
   if( pbLicense == NULL )
   {
        /* This means decrypt emplace.  Caller must know that decrpyted content starts at pELicense + PK_ENC_CIPHERTEXT_LEN */
        pbLicense = pbEncryptedLicense + (PK_ENC_CIPHERTEXT_LEN);
   }
   Error = SEPDriver_PrepareSymDMATables((DxUint32_t)&pbEncryptedLicense[PK_ENC_CIPHERTEXT_LEN],
                                         (DxUint32_t)pbLicense,
                                         (cbEncryptedLicense - PK_ENC_CIPHERTEXT_LEN),
                                         1,
                                         &firstInputLLITableAddr,
                                         &firstOutputLLITableAddr,
                                         &numInTableEntries,
                                         &numOutTableEntries,
                                         &firstTableSize); 

   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   messageParam[0] = firstInputLLITableAddr;
   messageParam[1] = numInTableEntries;
   messageParam[2] = firstOutputLLITableAddr;
   messageParam[3] = numOutTableEntries;
   messageParam[4] = firstTableSize;

	/*Send the encrypted license key */
   Error = SEPDriver_WriteParamater((DRM_ULONG)pbEncryptedLicense , 
                             PK_ENC_CIPHERTEXT_LEN ,
                             PK_ENC_CIPHERTEXT_LEN, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* send message */
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam,
                            sizeof(DxUint32_t) * 5,
                            sizeof(DxUint32_t) * 5,
                            &sramOffset, 
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
#endif

   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_POLL_FOR_REPONSE();
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*-------------------
      start reading message from the SEP 
   ---------------------*/
   
#if (LLF_RC4_ENGINE_TYPE==CRYS_DEFS_SW_ENGINE_TYPE)
#else
   /* free the tables */
   Error = SEPDriver_FreeDMATables();
   if(Error)
   {
      goto end_function_unlock;
   }
#endif
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
      goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG) * 2,
                            sizeof(DRM_ULONG) * 2,
                            &sramOffset ,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_DECRYPT_LICENSE_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check status */
   if(messageParam[1] != DRM_SUCCESS)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }
   
#if (LLF_RC4_ENGINE_TYPE==CRYS_DEFS_SW_ENGINE_TYPE)
   /* read the result */
   Error = SEPDriver_ReadParamater((DRM_ULONG)&res,
                           sizeof(DRM_ULONG) ,
                           sizeof(DRM_ULONG) ,
                           &sramOffset ,
                           DX_FALSE);

   if((Error != DX_OK) || (res == FALSE))
   {
       goto end_function_unlock;
   }
   if( pbLicense == NULL )
   {
        /* This means decrypt in place.  Caller must know that decrpyted content starts at pELicense + PK_ENC_CIPHERTEXT_LEN */
        pbLicense = pbEncryptedLicense + (PK_ENC_CIPHERTEXT_LEN);
   }

	/*The encryptedd license has private encrypted key in it which is not part of the output.*/
   cbEncryptedLicense = cbEncryptedLicense - PK_ENC_CIPHERTEXT_LEN;
   /* read the decrypt license */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(cbEncryptedLicense);

   Error = SEPDriver_ReadParamater((DRM_ULONG)pbLicense,
                           cbEncryptedLicense ,
                           maxLength ,
                           &sramOffset ,
                           DX_FALSE);

   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
#endif   
end_function_unlock:   

   /* lock access to the SEP */
   SEPDriver_Unlock();


ErrorExit:
    if(Error != DRM_SUCCESS)
	{
		res = FALSE;
	}
	return res;
}


/*  Used for computing the secure store password. */
DRM_RESULT DRM_API DRM_BBX_HashValue(
    IN  const DRM_BYTE       *pbValue,
    IN        DRM_DWORD       cbValue,
    OUT       DRM_BYTE        rgbHashValue [__CB_DECL(SHA_DIGEST_LEN)],
    IN        DRM_BB_CONTEXT *pcontextBBX )
{
    DRM_RESULT Error = DRM_SUCCESS;
    /* offset into SRAM */
    DRM_ULONG   sramOffset;
    /* read param */
    DRM_ULONG   messageParam[4];
	/*buffer for encrypt key*/
	DRM_CHAR privkey[OEM_ENC_KEY_BUFF_LEN];
#ifdef DX_CC5_SEP_PLAT
	/* address of the first table in the input list */
  	DxUint32_t          inputLLITableAddr;
    /* number of entries in each of the first tables */
  	DxUint32_t          numEntriesInTable;
   	/* first table data size */
  	DxUint32_t          firstTableDataSize;
  /* length of the head hash to complete */
  DxUint32_t 		  headBytesLen;
  
  /* length of the tail hash reminder */
  DxUint32_t 		  tailBytesLen;
   
#else
    /* max length */
    DRM_ULONG   maxLength;
#endif

    if(!(( pbValue      != NULL)
         && (cbValue       > 0 )
         && (rgbHashValue != NULL )
         && (pcontextBBX  != NULL )
         && (pcontextBBX->fInited )
#ifndef DX_CC5_SEP_PLAT
		 && (cbValue <= MAX_HOST_BBX_OPERATION_DATA_LENGTH)
#endif
		 ))
	{
       Error = DRM_E_INVALIDARG; 
       goto ErrorExit;     
	}
   
	OEM_GetEncGroupCertPrivateKey(privkey);
	/* lock access to the SEP */
    Error = SEPDriver_Lock();
	if(Error != DX_OK)
    {
		goto ErrorExit;
	}
	/*----------------------------
      start sending message to SEP 
   -----------------------------*/
   sramOffset = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);
  
   /* prepare message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_HASH_VALUE_OP_CODE;
   
   /* send opcode */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG),
                            sizeof(DRM_ULONG),
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   
   /*send the blackbox parameters*/
   Error = DRM_BBX_sendBbxContext(pcontextBBX,&sramOffset);
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }

   /* send encrypt key */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&privkey[0],
                            OEM_ENC_KEY_BUFF_LEN,
                            OEM_ENC_KEY_BUFF_LEN,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

#ifdef DX_CC5_SEP_PLAT

  /* calculate the data reminder length , there is no data since its first operation but  */
  /* during hashvalue operation 6 bytes are added so we need to fill it up.  */
  headBytesLen = (SHA_BLOCK_SIZE - 6);
  
  /* copy the data to a local buffer only if not modulus of CRYS_HASH_BLOCK_SIZE_IN_BYTES*/
  if (headBytesLen > cbValue)
  {
    headBytesLen = cbValue;
  }
    
  /* calculate the context reminder length of the tail part (may be zero) */
  tailBytesLen = (cbValue - headBytesLen) % SHA_BLOCK_SIZE;

   /* prepare tables for the input only */
   Error = SEPDriver_PREPARE_INPUT_SYM_DMA_TABLE((DxUint32_t)pbValue,
                                                            (cbValue - (headBytesLen + tailBytesLen)),
                                                            SHA_BLOCK_SIZE,
                                                            &inputLLITableAddr,
                                                            &numEntriesInTable,
                                                            &firstTableDataSize);
   if(Error != DX_OK)
   {
    	goto end_function_unlock;
   }

   messageParam[0] = inputLLITableAddr;
   messageParam[1] = numEntriesInTable;
   messageParam[2] = firstTableDataSize;
   messageParam[3] = headBytesLen;

   /* send mlli table and tail data size*/
   Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam,
                            4*sizeof(DRM_DWORD),
                            4*sizeof(DRM_DWORD) ,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* send the head data */
   Error = SEPDriver_WriteParamater((DRM_ULONG)pbValue,
                            headBytesLen,
                            SHA_BLOCK_SIZE ,
                            &sramOffset,
                            DX_TRUE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

   /* send tail data size */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&tailBytesLen,
                            sizeof(DRM_DWORD),
                            sizeof(DRM_DWORD) ,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* send tail data */
   Error = SEPDriver_WriteParamater((DRM_ULONG)(pbValue + cbValue - tailBytesLen),
                            tailBytesLen,
                            SHA_BLOCK_SIZE ,
                            &sramOffset,
                            DX_TRUE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

#else
	/* The PC simulation does not support MLLI */
   /* send length */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&cbValue,
                            sizeof(DRM_DWORD),
                            sizeof(DRM_DWORD) ,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* send data */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(cbValue);

   Error = SEPDriver_WriteParamater((DRM_ULONG)pbValue , 
                             cbValue ,
                             maxLength, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
#endif
   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_POLL_FOR_REPONSE();
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*-------------------
      start reading message from the SEP 
   ---------------------*/
   
#ifdef DX_CC5_SEP_PLAT
   /* free the tables */
   Error = SEPDriver_FreeDMATables();
   if(Error)
   {
      goto end_function_unlock;
   }
#endif
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
      goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG) * 2,
                            sizeof(DRM_ULONG) * 2,
                            &sramOffset ,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_HASH_VALUE_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check status */
   if(messageParam[1] != DRM_SUCCESS)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }
   
   /* read the result */
   Error = SEPDriver_ReadParamater((DRM_ULONG)rgbHashValue,
                           SHA_DIGEST_LEN ,
                           SHA_DIGEST_LEN ,
                           &sramOffset ,
                           DX_FALSE);

   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }


end_function_unlock:   

   /* lock access to the SEP */
   SEPDriver_Unlock();


ErrorExit:
    return Error;
}


/*  Key set-up for cipher operations ( decryption or encryption ). */
DRM_RESULT DRM_API DRM_BBX_CipherKeySetup( 
    IN const DRM_BINDING_INFO   *rgBindingInfo,
    IN       DRM_DWORD           dwChainLength,
    OUT      DRM_CIPHER_CONTEXT *pCipherContext,
    IN       DRM_BB_CONTEXT     *pcontextBBX )
{
    DRM_RESULT Error = DRM_SUCCESS;
    /* offset into SRAM */
    DRM_ULONG   sramOffset;
    /* read param */
    DRM_ULONG   messageParam[2];
    /* max length */
    DRM_ULONG   maxLength;
	/*buffer for encrypt key*/
	DRM_CHAR privkey[OEM_ENC_KEY_BUFF_LEN];

	if(!(( rgBindingInfo  != NULL )
         && (pCipherContext != NULL)
         && (pcontextBBX    != NULL)
         && pcontextBBX->fInited
		 &&(dwChainLength <= MAX_HOST_BBX_OPERATION_DATA_LENGTH)))
     {
         Error = DRM_E_INVALIDARG;
         goto ErrorExit;
     } 
   
	OEM_GetEncGroupCertPrivateKey(privkey);
	/* lock access to the SEP */
    Error = SEPDriver_Lock();
	if(Error != DX_OK)
    {
		goto ErrorExit;
	}
   /*----------------------------
      start sending message to SEP 
   -----------------------------*/
   sramOffset = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);
  
   /* prepare message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_CIPHER_KEY_SETUP_OP_CODE;
   
   /* send opcode */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG),
                            sizeof(DRM_ULONG),
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
  
   /*send the blackbox parameters*/
   Error = DRM_BBX_sendBbxContext(pcontextBBX,&sramOffset);
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
 
   /* send encrypt key */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&privkey[0],
                            OEM_ENC_KEY_BUFF_LEN,
                            OEM_ENC_KEY_BUFF_LEN,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

   /* send length */
   maxLength = 1;
   Error = SEPDriver_WriteParamater((DRM_ULONG)&maxLength /*dwChainLength*/,
                            sizeof(DRM_DWORD),
                            sizeof(DRM_DWORD) ,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* send data */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(DRM_BINDING_INFO));

   Error = SEPDriver_WriteParamater((DRM_ULONG)&rgBindingInfo[dwChainLength -1] , 
                             sizeof(DRM_BINDING_INFO) ,
                             maxLength, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_POLL_FOR_REPONSE();
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*-------------------
      start reading message from the SEP 
   ---------------------*/
   
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
      goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG) * 2,
                            sizeof(DRM_ULONG) * 2,
                            &sramOffset ,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_CIPHER_KEY_SETUP_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check status */
   if(messageParam[1] != DRM_SUCCESS)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }
   
   /* read the context */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(DRM_CIPHER_CONTEXT));

   Error = SEPDriver_ReadParamater((DRM_ULONG)pCipherContext,
                           sizeof(DRM_CIPHER_CONTEXT),
                           maxLength ,
                           &sramOffset ,
                           DX_FALSE);

   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }


end_function_unlock:   

   /* lock access to the SEP */
   SEPDriver_Unlock();

ErrorExit:
    return Error;
}

/******************************************************************************
** Function :   DRM_BBX_InitDecrypt
** Synopsis :   Initializes state for phased decryption
** Arguments :  f_pcontextCipher - Cipher context initialized with DRM_CPHR_Init
**              f_pbLast15    - Last 15 bytes of ciphertext
**              f_cbData      - # of bytes in ENTIRE ciphertext              
******************************************************************************/
DRM_RESULT DRM_API DRM_BBX_InitDecrypt( 
    IN     DRM_CIPHER_CONTEXT *f_pcontextCipher,
    IN     DRM_BYTE           *f_pbLast15,
    IN     DRM_DWORD           f_cbData )
{
    DRM_RESULT Error = DRM_SUCCESS;
    /* offset into SRAM */
    DRM_ULONG   sramOffset;
    /* read param */
    DRM_ULONG   messageParam[2];
    /* max length */
    DRM_ULONG   maxLength;

    if(!(( f_cbData          > 0  )
         && (f_pbLast15       != NULL )
         && (f_pcontextCipher != NULL )))
	{
         Error = DRM_E_INVALIDARG;
         goto ErrorExit;
	}
   
	/* lock access to the SEP */
    Error = SEPDriver_Lock();
	if(Error != DX_OK)
    {
		goto ErrorExit;
	}
	/*----------------------------
      start sending message to SEP 
   -----------------------------*/
   sramOffset = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);
  
   /* prepare message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_INIT_DECRYPT_OP_CODE;
   messageParam[1] = f_cbData;
   /* send opcode */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG) * 2,
                            sizeof(DRM_ULONG) * 2,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* send data */
   Error = SEPDriver_WriteParamater((DRM_ULONG)f_pbLast15 , 
                             sizeof(DRM_ULONG) * 4 ,
                             sizeof(DRM_ULONG) * 4, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(DRM_CIPHER_CONTEXT));

   /* send the context  */
   Error = SEPDriver_WriteParamater((DRM_ULONG)f_pcontextCipher , 
                             sizeof(DRM_CIPHER_CONTEXT),
                             maxLength, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_POLL_FOR_REPONSE();
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*-------------------
      start reading message from the SEP 
   ---------------------*/
   
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
      goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG) * 2,
                            sizeof(DRM_ULONG) * 2,
                            &sramOffset ,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_INIT_DECRYPT_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check status */
   if(messageParam[1] != DRM_SUCCESS)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }
   
   /* read the context */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(DRM_CIPHER_CONTEXT));

   Error = SEPDriver_ReadParamater((DRM_ULONG)f_pcontextCipher,
                           sizeof(DRM_CIPHER_CONTEXT),
                           maxLength ,
                           &sramOffset ,
                           DX_FALSE);

   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }


end_function_unlock:   

   /* lock access to the SEP */
   SEPDriver_Unlock();

    
ErrorExit:
    return Error;
}

/******************************************************************************
** Function :   DRM_BBX_Decrypt
** Synopsis :   Decrypts part of the ciphertext. This function must be called 
**              after DRM_BBX_InitDecrypt has been successful
** Arguments :  f_pcontextCipher - Cipher context initialized with DRM_CPHR_Init,
**                                 followed by DRM_BBX_InitDecrypt
**              f_cbData  - # of bytes of data to be decrypted
**              f_pbData  - Pointer to encrypted buffer
** Notes :      IMPORTANT: Phased decrypt should be called on segments of 
**              encrypted data sequentially, i.e. if encrypted data is divided 
**              four segments, the order of decryption should be segment 1,
**              followed by 2, 3, 4.
******************************************************************************/
DRM_RESULT DRM_API DRM_BBX_Decrypt( 
    IN     DRM_DWORD           f_cbData,
    IN OUT DRM_BYTE           *f_pbData,
    IN     DRM_CIPHER_CONTEXT *f_pcontextCipher)
{
	DRM_RESULT Error = DRM_SUCCESS;
	DRM_ULONG	numOfLoops;

	/* offset into SRAM */
    DRM_ULONG   sramOffset;
    /* read param */
    DRM_ULONG   messageParam[2];
    /* max length */
    DRM_ULONG   maxLength;
	/* temporary data*/
	DRM_ULONG   tempLen;
    
	if(!(( f_cbData          > 0  )
         && (f_pbData         != NULL) 
         && (f_pcontextCipher != NULL )))
	{
         Error = DRM_E_INVALIDARG;
         goto ErrorExit;
	}
	numOfLoops = f_cbData / MAX_HOST_BBX_OPERATION_DATA_LENGTH;
	if(f_cbData % MAX_HOST_BBX_OPERATION_DATA_LENGTH )
	{
		numOfLoops = numOfLoops +1;
	}
   
	/* lock access to the SEP */
    Error = SEPDriver_Lock();
	if(Error != DX_OK)
    {
		goto ErrorExit;
	}

	while(numOfLoops)
	{
		/*----------------------------
		start sending message to SEP 
		-----------------------------*/
		sramOffset = 0;

		/* start the message */
		SEPDriver_StartMessage(&sramOffset);

		/* prepare message */
		messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_DECRYPT_OP_CODE;

		/* send opcode */
		Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam[0],
							sizeof(DRM_ULONG),
							sizeof(DRM_ULONG),
							&sramOffset,
							DX_FALSE);
		if(Error != DX_OK)
		{
			goto end_function_unlock;
		}
		/*Due to decrypt limitation the last 15 bytes must be at one segment*/
		if(f_cbData > (MAX_HOST_BBX_OPERATION_DATA_LENGTH + 15 ))
		{
			tempLen = MAX_HOST_BBX_OPERATION_DATA_LENGTH;
		}
		else if(f_cbData > MAX_HOST_BBX_OPERATION_DATA_LENGTH)
		{
			tempLen = (MAX_HOST_BBX_OPERATION_DATA_LENGTH - 15 );
		}
		else
		{
			tempLen = f_cbData;		
		}
	   /* send context */
	   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(DRM_CIPHER_CONTEXT));

	   Error = SEPDriver_WriteParamater((DRM_ULONG)f_pcontextCipher,
							   sizeof(DRM_CIPHER_CONTEXT),
							   maxLength ,
							   &sramOffset ,
							   DX_FALSE);
		/* send data length */
		Error = SEPDriver_WriteParamater((DRM_ULONG)&tempLen,
							sizeof(DRM_DWORD),
							sizeof(DRM_DWORD) ,
							&sramOffset,
							DX_FALSE);
		if(Error != DX_OK)
		{
		 goto end_function_unlock;
		}
		/* send data */
	   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(tempLen);

	   Error = SEPDriver_WriteParamater((DRM_ULONG)f_pbData , 
							 tempLen ,
							 maxLength, 
							 &sramOffset , 
							 DX_FALSE);
		if(Error != DX_OK)
		 {
		  goto end_function_unlock;
		 }
		/* end message */
		SEPDriver_EndMessage(sramOffset);
		          
		/* wait for the response */
		Error = SEPDriver_POLL_FOR_REPONSE();
		if(Error != DX_OK)
		{
		goto end_function_unlock;
		}
 
		 /*-------------------
		 start reading message from the SEP 
		 ---------------------*/
		 
		 /* start the message */
		 Error = SEPDriver_StartIncomingMessage(&sramOffset);
		 if(Error)
		 {
		 goto end_function_unlock;
		 }
 
		 /* read opcode + status  */
		 Error = SEPDriver_ReadParamater((DRM_ULONG)&messageParam[0],
							sizeof(DRM_ULONG) * 2,
							sizeof(DRM_ULONG) * 2,
							&sramOffset ,
							DX_FALSE);
		 if(Error != DX_OK)
		 {
		  goto end_function_unlock;
		 }
		 
		 /* check the opcode */
		 if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_DECRYPT_OP_CODE)
		 {
			 Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
			 goto end_function_unlock;
		 }
		 
		 /* check status */
		 if(messageParam[1] != DRM_SUCCESS)
		 {
			 Error = messageParam[1];
			 goto end_function_unlock;
		 }
 
		/* read the context */
	   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(DRM_CIPHER_CONTEXT));

	   Error = SEPDriver_ReadParamater((DRM_ULONG)f_pcontextCipher,
						   sizeof(DRM_CIPHER_CONTEXT),
						   maxLength ,
						   &sramOffset ,
						   DX_FALSE);

		if(Error != DX_OK)
		{
			goto end_function_unlock;
		}
		/* read the data */
	   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(tempLen);

	   Error = SEPDriver_ReadParamater((DRM_ULONG)f_pbData,
						   tempLen,
						   maxLength ,
						   &sramOffset ,
						   DX_FALSE);

		if(Error != DX_OK)
		{
			goto end_function_unlock;
		}


		f_pbData = f_pbData + tempLen;
		f_cbData = f_cbData - tempLen;
		
		numOfLoops--;
	} /* while(numOfLoops) */
end_function_unlock:   
	/* lock access to the SEP */
	SEPDriver_Unlock();
    
ErrorExit:
    return Error;
}

/*  Encrypt content. */
/*  Encrypt is done always in one shut. The contant can not be divided to some chunks of data */
DRM_RESULT DRM_API DRM_BBX_Encrypt( 
    IN     DRM_DWORD           cbData,
    IN OUT DRM_BYTE           *pbData,
    IN     DRM_CIPHER_CONTEXT *pEncryptContext )
{
	DRM_RESULT Error = DRM_SUCCESS;
    /* offset into SRAM */
    DRM_ULONG   sramOffset;
    /* read param */
    DRM_ULONG   messageParam[2];
    /* max length */
    DRM_ULONG   maxLength;
	/* temporary data*/
    
	if(!(( cbData          > 0  )
         && (pbData         != NULL) 
         && (pEncryptContext != NULL )
		 &&(cbData <= MAX_HOST_BBX_OPERATION_DATA_LENGTH)))
	{
         Error = DRM_E_INVALIDARG;
         goto ErrorExit;
	}

	/* lock access to the SEP */
    Error = SEPDriver_Lock();
	if(Error != DX_OK)
    {
		goto ErrorExit;
	}

	/*----------------------------
	start sending message to SEP 
	-----------------------------*/
	sramOffset = 0;

	/* start the message */
	SEPDriver_StartMessage(&sramOffset);

	/* prepare message */
	messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_ENCRYPT_OP_CODE;

	/* send opcode */
	Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam[0],
						sizeof(DRM_ULONG),
						sizeof(DRM_ULONG),
						&sramOffset,
						DX_FALSE);
	if(Error != DX_OK)
	{
		goto end_function_unlock;
	}

	/* send context */
	maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(DRM_CIPHER_CONTEXT));

	Error = SEPDriver_WriteParamater((DRM_ULONG)pEncryptContext,
						   sizeof(DRM_CIPHER_CONTEXT),
						   maxLength ,
						   &sramOffset ,
						   DX_FALSE);
	/* send data length */
	Error = SEPDriver_WriteParamater((DRM_ULONG)&cbData,
						sizeof(DRM_DWORD),
						sizeof(DRM_DWORD) ,
						&sramOffset,
						DX_FALSE);
	if(Error != DX_OK)
	{
	 goto end_function_unlock;
	}
	/* send data */
	maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(cbData);

	Error = SEPDriver_WriteParamater((DRM_ULONG)pbData , 
						 cbData ,
						 maxLength, 
						 &sramOffset , 
						 DX_FALSE);
	if(Error != DX_OK)
	 {
	  goto end_function_unlock;
	 }
	/* end message */
	SEPDriver_EndMessage(sramOffset);
	          
	/* wait for the response */
	Error = SEPDriver_POLL_FOR_REPONSE();
	if(Error != DX_OK)
	{
	goto end_function_unlock;
	}
 
	 /*-------------------
	 start reading message from the SEP 
	 ---------------------*/
	 
	 /* start the message */
	 Error = SEPDriver_StartIncomingMessage(&sramOffset);
	 if(Error)
	 {
	 goto end_function_unlock;
	 }
 
	 /* read opcode + status  */
	 Error = SEPDriver_ReadParamater((DRM_ULONG)&messageParam[0],
						sizeof(DRM_ULONG) * 2,
						sizeof(DRM_ULONG) * 2,
						&sramOffset ,
						DX_FALSE);
	 if(Error != DX_OK)
	 {
	  goto end_function_unlock;
	 }
	 
	 /* check the opcode */
	 if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_ENCRYPT_OP_CODE)
	 {
		 Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
		 goto end_function_unlock;
	 }
	 
	 /* check status */
	 if(messageParam[1] != DRM_SUCCESS)
	 {
		 Error = messageParam[1];
		 goto end_function_unlock;
	 }
 

	 /* read the context */
	maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(DRM_CIPHER_CONTEXT));

	Error = SEPDriver_ReadParamater((DRM_ULONG)pEncryptContext,
					   sizeof(DRM_CIPHER_CONTEXT),
					   maxLength ,
					   &sramOffset ,
					   DX_FALSE);

	if(Error != DX_OK)
	{
		goto end_function_unlock;
	}

	/* read the data */
	maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(cbData);

	Error = SEPDriver_ReadParamater((DRM_ULONG)pbData,
					   cbData,
					   maxLength ,
					   &sramOffset ,
					   DX_FALSE);

	if(Error != DX_OK)
	{
		goto end_function_unlock;
	}

end_function_unlock:   

	/* lock access to the SEP */
	SEPDriver_Unlock();
    
ErrorExit:
    return Error;
}




/*  Key set-up for cipher operations ( decryption or encryption ). for v1 */
DRM_RESULT DRM_API DRM_BBX_LegacyCipherKeySetup( 
    IN  DRM_BINDING_INFO   *pBindInfo, 
    IN  DRM_BYTE           *pbKID,
    IN  DRM_DWORD           cbKID,
    IN  DRM_BYTE           *pbSecretData,
    IN  DRM_DWORD           cbSecretData,
    OUT DRM_CIPHER_CONTEXT *pCipherContext, 
    IN  DRM_BB_CONTEXT     *pcontextBBX )
{
    DRM_RESULT         Error = DRM_SUCCESS;
    /* offset into SRAM */
    DRM_ULONG   sramOffset;
    /* read param */
    DRM_ULONG   messageParam[2];
    /* max length */
    DRM_ULONG   maxLength;
	/*buffer for encrypt key*/
	DRM_CHAR privkey[OEM_ENC_KEY_BUFF_LEN];

    
    if(!(( pbKID != NULL)
		&&( cbKID == LEGACY_KID_B64ENC_LEN )
		&&( pbSecretData != NULL )
		&&( cbSecretData == LEGACY_KID_B64ENC_LEN )
		&&( pCipherContext != NULL)
        &&( pcontextBBX    != NULL)
        &&( pcontextBBX->fInited )))
	{
         Error = DRM_E_INVALIDARG;
         goto ErrorExit;
	}
   
	OEM_GetEncGroupCertPrivateKey(privkey);
	/* lock access to the SEP */
    Error = SEPDriver_Lock();
	if(Error != DX_OK)
    {
		goto ErrorExit;
	}
	/*----------------------------
      start sending message to SEP 
   -----------------------------*/
   sramOffset = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);
  
   /* prepare message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_LEGACY_CIPHER_KEY_SETUP_OP_CODE;
   /* send opcode */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG),
                            sizeof(DRM_ULONG),
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

   /*send the blackbox parameters*/
   Error = DRM_BBX_sendBbxContext(pcontextBBX,&sramOffset);
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }

   /* send encrypt key */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&privkey[0],
                            OEM_ENC_KEY_BUFF_LEN,
                            OEM_ENC_KEY_BUFF_LEN,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* send bind info */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(DRM_BINDING_INFO));

   Error = SEPDriver_WriteParamater((DRM_ULONG)pBindInfo , 
                             sizeof(DRM_BINDING_INFO) ,
                             maxLength, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* send KID length */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&cbKID , 
                             sizeof(DRM_DWORD),
                             sizeof(DRM_DWORD), 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* send KID data */
   Error = SEPDriver_WriteParamater((DRM_ULONG)pbKID , 
                             cbKID,
                             sizeof(DRM_ULONG) * 32, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

   /* send secret data length */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&cbSecretData , 
                             sizeof(DRM_DWORD),
                             sizeof(DRM_DWORD), 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* send secret data */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(cbSecretData);

   Error = SEPDriver_WriteParamater((DRM_ULONG)pbSecretData , 
                             cbSecretData,
                             maxLength, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_POLL_FOR_REPONSE();
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*-------------------
      start reading message from the SEP 
   ---------------------*/
   
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
      goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG) * 2,
                            sizeof(DRM_ULONG) * 2,
                            &sramOffset ,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_LEGACY_CIPHER_KEY_SETUP_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check status */
   if(messageParam[1] != DRM_SUCCESS)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }
   
   /* read the context */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(DRM_CIPHER_CONTEXT));

   Error = SEPDriver_ReadParamater((DRM_ULONG)pCipherContext,
                           sizeof(DRM_CIPHER_CONTEXT),
                           maxLength ,
                           &sramOffset ,
                           DX_FALSE);

   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }


end_function_unlock:   

   /* lock access to the SEP */
   SEPDriver_Unlock();

    
ErrorExit:
    return Error;
}

/******************************************************************************
** Function :   DRM_BBX_SignData
** Synopsis :   Sign data with the machine private key 
** Arguments :  f_pcontextBBX       - Blackbox context
**              f_pbData            - Data to be signed
**              f_cbData            - Size of data to be signed
**              f_rgbSignature      - Signature
******************************************************************************/
DRM_RESULT DRM_API DRM_BBX_SignData(
    IN       DRM_BB_CONTEXT *f_pcontextBBX,
    IN const DRM_BYTE       *f_pbData,
    IN       DRM_DWORD       f_cbData,
    IN       DRM_DWORD       f_ePrivKeyType,
       OUT   DRM_BYTE        f_rgbSignature[__CB_DECL(PK_ENC_SIGNATURE_LEN)])
{
    DRM_RESULT         Error = DRM_SUCCESS;
    /* offset into SRAM */
    DRM_ULONG   sramOffset;
    /* read param */
    DRM_ULONG   messageParam[4];
    /* max length */
	DRM_CHAR privkey[OEM_ENC_KEY_BUFF_LEN];
#ifdef DX_CC5_SEP_PLAT
	/* address of the first table in the input list */
  	DxUint32_t          inputLLITableAddr;
    /* number of entries in each of the first tables */
  	DxUint32_t          numEntriesInTable;
   	/* first table data size */
  	DxUint32_t          firstTableDataSize;
    /* number of into the message from the start of user buffer */
    DxUint32_t              numBytesFromEnd;
#else
    /* max length */
    DRM_ULONG   maxLength;
#endif
   
    if(!(( f_pcontextBBX  != NULL )
         && (f_ePrivKeyType == eBBX_PRIVKEY_MACHINE)
         && (f_pcontextBBX->fInited )
#ifndef DX_CC5_SEP_PLAT
		 &&(f_cbData <= MAX_HOST_BBX_OPERATION_DATA_LENGTH)
#endif
		 ))
	{
         Error = DRM_E_INVALIDARG;
         goto ErrorExit;
	}
   
	OEM_GetEncGroupCertPrivateKey(privkey);
	/* lock access to the SEP */
    Error = SEPDriver_Lock();
	if(Error != DX_OK)
    {
		goto ErrorExit;
	}
	/*----------------------------
      start sending message to SEP 
   -----------------------------*/
   sramOffset = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);
  
   /* prepare message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_SIGN_DATA_OP_CODE;
   /* send opcode */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG),
                            sizeof(DRM_ULONG),
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /*send the blackbox parameters*/
   Error = DRM_BBX_sendBbxContext(f_pcontextBBX,&sramOffset);
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }

   /* send encrypt key */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&privkey[0],
                            OEM_ENC_KEY_BUFF_LEN,
                            OEM_ENC_KEY_BUFF_LEN,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* send key type */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&f_ePrivKeyType , 
                             sizeof(DRM_DWORD),
                             sizeof(DRM_DWORD), 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

#ifdef DX_CC5_SEP_PLAT
   numBytesFromEnd = f_cbData % SHA_BLOCK_SIZE; 
   /* prepare tables for the input only */
   Error = SEPDriver_PREPARE_INPUT_SYM_DMA_TABLE((DxUint32_t)f_pbData,
                                                            (f_cbData - numBytesFromEnd),
                                                            SHA_BLOCK_SIZE,
                                                            &inputLLITableAddr,
                                                            &numEntriesInTable,
                                                            &firstTableDataSize);
   if(Error != DX_OK)
   {
    	goto end_function_unlock;
   }

   messageParam[0] = inputLLITableAddr;
   messageParam[1] = numEntriesInTable;
   messageParam[2] = firstTableDataSize;
   messageParam[3] = numBytesFromEnd;

   /* send mlli table with tail data size */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam,
                            4*sizeof(DRM_DWORD),
                            4*sizeof(DRM_DWORD) ,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* send tail data  */
   Error = SEPDriver_WriteParamater((DRM_ULONG)(f_pbData + f_cbData -numBytesFromEnd),
                            numBytesFromEnd,
                            SHA_BLOCK_SIZE ,
                            &sramOffset,
                            DX_TRUE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

#else
   /* send data length */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&f_cbData , 
                             sizeof(DRM_DWORD),
                             sizeof(DRM_DWORD), 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* send  data */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(f_cbData);

   Error = SEPDriver_WriteParamater((DRM_ULONG)f_pbData , 
                             f_cbData,
                             maxLength, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
#endif

   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_POLL_FOR_REPONSE();
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*-------------------
      start reading message from the SEP 
   ---------------------*/
   
#ifdef DX_CC5_SEP_PLAT
   /* free the tables */
   Error = SEPDriver_FreeDMATables();
   if(Error)
   {
      goto end_function_unlock;
   }
#endif
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
      goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG) * 2,
                            sizeof(DRM_ULONG) * 2,
                            &sramOffset ,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_SIGN_DATA_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check status */
   if(messageParam[1] != DRM_SUCCESS)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }
   
   /* read the signature */
   Error = SEPDriver_ReadParamater((DxUint32_t)f_rgbSignature,
                           PK_ENC_SIGNATURE_LEN,
                           PK_ENC_SIGNATURE_LEN ,
                           &sramOffset ,
                           DX_FALSE);

   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }


end_function_unlock:   

   /* lock access to the SEP */
   SEPDriver_Unlock();

    
ErrorExit:
    return Error;
}

#if DRM_SUPPORT_SYMMETRIC_OPTIMIZATIONS

/*********************************************************************
**
**  Function:  DRM_BBX_SymmetricSign
**
**  Synopsis:  Creates a symmetric signature (that only the current blackbox can verify) over the data provided 
**             by the caller
**
**  Arguments:  
**     [f_pcontextBBX] -- Pointer to an initialized blackbox context
**     [f_pbData]      -- Pointer to the data to sign
**     [f_cbData]      -- Length of f_pbData in DRM_BYTEs
**     [f_rgbSymSig]   -- Buffer to place the resultant 'symmetric signature'
**
*********************************************************************/

DRM_RESULT DRM_API DRM_BBX_SymmetricSign(
    IN       DRM_BB_CONTEXT *f_pcontextBBX,
    IN const DRM_BYTE       *f_pbData,
    IN       DRM_DWORD       f_cbData,
       OUT   DRM_BYTE        f_rgbSymSig[__CB_DECL( SHA_DIGEST_LEN )] )
{
    DRM_RESULT         Error = DRM_SUCCESS;
    /* offset into SRAM */
    DRM_ULONG   sramOffset;
    /* read param */
    DRM_ULONG   messageParam[5];
	/*buffer for encrypt key*/
	DRM_CHAR privkey[OEM_ENC_KEY_BUFF_LEN];
#ifdef DX_CC5_SEP_PLAT
	/* address of the first table in the input list */
  	DxUint32_t          inputLLITableAddr;
    /* number of entries in each of the first tables */
  	DxUint32_t          numEntriesInTable;
   	/* first table data size */
  	DxUint32_t          firstTableDataSize;
    /* number of into the message from the start of user buffer */
    DxUint32_t              numBytesFromEnd;
#else
    /* max length */
    DRM_ULONG   maxLength;
#endif
    
    if(!(( f_pcontextBBX  != NULL )
         && (f_pcontextBBX->fInited )
#ifndef DX_CC5_SEP_PLAT
		 &&(f_cbData <= MAX_HOST_BBX_OPERATION_DATA_LENGTH)
#endif
		 ))
	{
         Error = DRM_E_INVALIDARG;
         goto ErrorExit;
	}
   
	OEM_GetEncGroupCertPrivateKey(privkey);
	/* lock access to the SEP */
    Error = SEPDriver_Lock();
	if(Error != DX_OK)
    {
		goto ErrorExit;
	}
	/*----------------------------
      start sending message to SEP 
   -----------------------------*/
   sramOffset = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);
  
   /* prepare message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_SYM_SIGN_DATA_OP_CODE;
   /* send opcode */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG),
                            sizeof(DRM_ULONG),
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

   /*send the blackbox parameters*/
   Error = DRM_BBX_sendBbxContext(f_pcontextBBX,&sramOffset);
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }

   /* send encrypt key */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&privkey[0],
                            OEM_ENC_KEY_BUFF_LEN,
                            OEM_ENC_KEY_BUFF_LEN,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

#ifdef DX_CC5_SEP_PLAT
   numBytesFromEnd = f_cbData % SHA_BLOCK_SIZE; 
   /* prepare tables for the input only */
   Error = SEPDriver_PREPARE_INPUT_SYM_DMA_TABLE((DxUint32_t)f_pbData,
                                                            (f_cbData - numBytesFromEnd),
                                                            SHA_BLOCK_SIZE,
                                                            &inputLLITableAddr,
                                                            &numEntriesInTable,
                                                            &firstTableDataSize);
   if(Error != DX_OK)
   {
    	goto end_function_unlock;
   }

   messageParam[0] = inputLLITableAddr;
   messageParam[1] = numEntriesInTable;
   messageParam[2] = firstTableDataSize;
   messageParam[3] = numBytesFromEnd;

   /* send mlli table with tail data size*/
   Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam,
                            4*sizeof(DRM_DWORD),
                            4*sizeof(DRM_DWORD) ,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

      /* send mlli table with tail data size*/
   Error = SEPDriver_WriteParamater((DRM_ULONG)(f_pbData + f_cbData - numBytesFromEnd),
                            numBytesFromEnd,
                            SHA_BLOCK_SIZE ,
                            &sramOffset,
                            DX_TRUE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

#else
   /* send data length */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&f_cbData , 
                             sizeof(DRM_DWORD),
                             sizeof(DRM_DWORD), 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* send  data */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(f_cbData);

   Error = SEPDriver_WriteParamater((DRM_ULONG)f_pbData , 
                             f_cbData,
                             maxLength, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
#endif

   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_POLL_FOR_REPONSE();
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*-------------------
      start reading message from the SEP 
   ---------------------*/
   
#ifdef DX_CC5_SEP_PLAT
   /* free the tables */
   Error = SEPDriver_FreeDMATables();
   if(Error)
   {
      goto end_function_unlock;
   }
#endif
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
      goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG) * 2,
                            sizeof(DRM_ULONG) * 2,
                            &sramOffset ,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_SYM_SIGN_DATA_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check status */
   if(messageParam[1] != DRM_SUCCESS)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }
   
   /* read the signature */
   Error = SEPDriver_ReadParamater((DxUint32_t)f_rgbSymSig,
                           SHA_DIGEST_LEN,
                           SHA_DIGEST_LEN ,
                           &sramOffset ,
                           DX_FALSE);

   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }


end_function_unlock:   

   /* lock access to the SEP */
   SEPDriver_Unlock();

    
ErrorExit:
    return Error;
}

/*********************************************************************
**
**  Function:  DRM_BBX_SymmetricVerify
**
**  Synopsis:  Verifies a symmetric signtaure that was created by a call to DRM_BBX_SymmetricSign
**
**  Arguments:  
**     [f_pcontextBBX] -- Pointer to an initialized blackbox context
**     [f_pbData]      -- Pointer to the data to sign
**     [f_cbData]      -- Length of f_pbData in DRM_BYTEs
**     [f_pslk]        -- Optional.  If this parameter is provided the caller is asking to verify
**                        the signature with a BBX protected SLK key.
**     [f_rgbSymSig]   -- Buffer containing the signtature to compare against.
**
*********************************************************************/

DRM_RESULT DRM_API DRM_BBX_SymmetricVerify(
    IN       DRM_BB_CONTEXT *f_pcontextBBX,
    IN const DRM_BYTE       *f_pbData,
    IN       DRM_DWORD       f_cbData,
    IN const DRM_SLK        *f_pslk,
    IN const DRM_BYTE        f_rgbSymSig[__CB_DECL( SHA_DIGEST_LEN )] )
{
    DRM_RESULT         Error = DRM_SUCCESS;
    /* offset into SRAM */
    DRM_ULONG   sramOffset;
    /* read param */
    DRM_ULONG   messageParam[5];
	/*buffer for encrypt key*/
	DRM_CHAR privkey[OEM_ENC_KEY_BUFF_LEN];
	/* address of the first table in the input list */
#ifdef DX_CC5_SEP_PLAT
	/* address of the first table in the input list */
  	DxUint32_t          inputLLITableAddr;
    /* number of entries in each of the first tables */
  	DxUint32_t          numEntriesInTable;
   	/* first table data size */
  	DxUint32_t          firstTableDataSize;
    /* number of into the message from the start of user buffer */
    DxUint32_t              numBytesFromEnd;
#else
    /* max length */
    DRM_ULONG   maxLength;
#endif

    
    if( !( ( f_pcontextBBX  != NULL )
         && (f_pbData       != NULL)
         && (f_cbData       != 0 )
         && f_pcontextBBX->fInited
#ifndef DX_CC5_SEP_PLAT
		 &&(f_cbData <= MAX_HOST_BBX_OPERATION_DATA_LENGTH)
#endif
		 ))
	{
         Error = DRM_E_INVALIDARG;
         goto ErrorExit;
	}
    
	OEM_GetEncGroupCertPrivateKey(privkey);
	/* lock access to the SEP */
    Error = SEPDriver_Lock();
	if(Error != DX_OK)
    {
		goto ErrorExit;
	}
	/*----------------------------
      start sending message to SEP 
   -----------------------------*/
   sramOffset = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);
  
   /* prepare message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_SYM_VERIFY_DATA_OP_CODE;
   /* send opcode */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG),
                            sizeof(DRM_ULONG),
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

   /*send the blackbox parameters*/
   Error = DRM_BBX_sendBbxContext(f_pcontextBBX,&sramOffset);
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
 
   /* send encrypt key */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&privkey[0],
                            OEM_ENC_KEY_BUFF_LEN,
                            OEM_ENC_KEY_BUFF_LEN,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
  

	/* send SLK */
   if( f_pslk == NULL )
   {
		messageParam[0] = 0x0;
		/* The SLK key does exist*/
		Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam[0],
									sizeof(DRM_ULONG),
									sizeof(DRM_ULONG),
									&sramOffset,
									DX_FALSE);
		sramOffset = sramOffset + sizeof(DRM_SLK);
   }
   else
   {
		messageParam[0] = 0x1;
		/* The SLK key exists*/
		Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam[0],
									sizeof(DRM_ULONG),
									sizeof(DRM_ULONG),
									&sramOffset,
									DX_FALSE);
		Error = SEPDriver_WriteParamater((DRM_ULONG)&f_pslk , 
				                         sizeof(DRM_SLK),
								         sizeof(DRM_SLK), 
										 &sramOffset , 
										 DX_FALSE);
   }
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /*send the signature */
   Error = SEPDriver_WriteParamater((DxUint32_t)f_rgbSymSig,
                           SHA_DIGEST_LEN,
                           SHA_DIGEST_LEN ,
                           &sramOffset ,
                           DX_FALSE);

   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
#ifdef DX_CC5_SEP_PLAT
   numBytesFromEnd = f_cbData % SHA_BLOCK_SIZE; 
   /* prepare tables for the input only */
   Error = SEPDriver_PREPARE_INPUT_SYM_DMA_TABLE((DxUint32_t)f_pbData,
                                                            (f_cbData - numBytesFromEnd),
                                                            SHA_BLOCK_SIZE,
                                                            &inputLLITableAddr,
                                                            &numEntriesInTable,
                                                            &firstTableDataSize);
   if(Error != DX_OK)
   {
    	goto end_function_unlock;
   }

   messageParam[0] = inputLLITableAddr;
   messageParam[1] = numEntriesInTable;
   messageParam[2] = firstTableDataSize;
   messageParam[3] = numBytesFromEnd;

   /* send mlli table with tail data size*/
   Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam,
                            4*sizeof(DRM_DWORD),
                            4*sizeof(DRM_DWORD) ,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* send tail data */
   Error = SEPDriver_WriteParamater((DRM_ULONG)(f_pbData + f_cbData - numBytesFromEnd),
                            numBytesFromEnd,
                            SHA_BLOCK_SIZE ,
                            &sramOffset,
                            DX_TRUE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

#else
   /* send data length */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&f_cbData , 
                             sizeof(DRM_DWORD),
                             sizeof(DRM_DWORD), 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* send  data */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(f_cbData);

   Error = SEPDriver_WriteParamater((DRM_ULONG)f_pbData , 
                             f_cbData,
                             maxLength, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
#endif

   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_POLL_FOR_REPONSE();
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*-------------------
      start reading message from the SEP 
   ---------------------*/
   
#ifdef DX_CC5_SEP_PLAT
   /* free the tables */
   Error = SEPDriver_FreeDMATables();
   if(Error)
   {
      goto end_function_unlock;
   }
#endif
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
      goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG) * 2,
                            sizeof(DRM_ULONG) * 2,
                            &sramOffset ,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_SYM_VERIFY_DATA_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check status */
   if(messageParam[1] != DRM_SUCCESS)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }
   
end_function_unlock:   

   /* lock access to the SEP */
   SEPDriver_Unlock();

    
ErrorExit:
    return Error;
}

/*********************************************************************
**
**  Function:  DRM_BBX_AsymmetricToSymmetricKey
**
**  Synopsis:  Takes an asymmetrically encrypted content key and symmetrically rebinds it to the current blackbox.
**
**  Arguments:  
**     [f_pcontextBBX]       -- Pointer to an initialized blackbox context
**     [f_pbindinfo]         -- Pointer to the binding info of the license that is being optmized
**     [f_pcbSymmKey]        -- Length of the resultant symmetric content key
**
**  Notes:  The content key will be reencrypted and returned in the same buffer.  The new length of the symmetric key
**          is returned in f_pcbSymmKey
**
*********************************************************************/

DRM_RESULT DRM_API DRM_BBX_AsymmetricToSymmetricKey(
    IN     DRM_BB_CONTEXT   *f_pcontextBBX,
    IN OUT DRM_BINDING_INFO *f_pbindinfo,
       OUT DRM_DWORD        *f_pcbSymmKey )
{
    DRM_RESULT Error = DRM_SUCCESS;
    /* offset into SRAM */
    DRM_ULONG   sramOffset;
    /* read param */
    DRM_ULONG   messageParam[2];
    /* max length */
    DRM_ULONG   maxLength;
	/*buffer for encrypt key*/
	DRM_CHAR privkey[OEM_ENC_KEY_BUFF_LEN];

    if( !( (f_pcontextBBX              != NULL )
         && (f_pbindinfo                != NULL)
         && (f_pcbSymmKey               != NULL)
         && (f_pbindinfo->m_dwAlgorithm == eMSDRM_PK) /* Must be an assymetric encryption */
         && f_pcontextBBX->fInited ))
	{
         Error = DRM_E_INVALIDARG;
         goto ErrorExit;
	}
   
	OEM_GetEncGroupCertPrivateKey(privkey);
	/* lock access to the SEP */
    Error = SEPDriver_Lock();
	if(Error != DX_OK)
    {
		goto ErrorExit;
	}
	/*----------------------------
      start sending message to SEP 
   -----------------------------*/
   sramOffset = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);
  
   /* prepare message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_ASYM_TO_SYM_KEY_OP_CODE;
   /* send opcode */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG),
                            sizeof(DRM_ULONG),
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

   /*send the blackbox parameters*/
   Error = DRM_BBX_sendBbxContext(f_pcontextBBX,&sramOffset);
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
  
   /* send encrypt key */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&privkey[0],
                            OEM_ENC_KEY_BUFF_LEN,
                            OEM_ENC_KEY_BUFF_LEN,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
  
   /* send  info */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(DRM_BINDING_INFO));

   Error = SEPDriver_WriteParamater((DRM_ULONG)f_pbindinfo , 
                             sizeof(DRM_BINDING_INFO),
                             maxLength, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_POLL_FOR_REPONSE();
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*-------------------
      start reading message from the SEP 
   ---------------------*/
   
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
      goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG) * 2,
                            sizeof(DRM_ULONG) * 2,
                            &sramOffset ,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_ASYM_TO_SYM_KEY_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check status */
   if(messageParam[1] != DRM_SUCCESS)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }
   
    /* read the key length  */
   Error = SEPDriver_ReadParamater((DRM_DWORD)f_pcbSymmKey,
                            sizeof(DRM_DWORD),
                            sizeof(DRM_DWORD),
                            &sramOffset ,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
  /*read info */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(DRM_BINDING_INFO));

   Error = SEPDriver_ReadParamater((DRM_ULONG)f_pbindinfo , 
                             sizeof(DRM_BINDING_INFO),
                             maxLength, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

end_function_unlock:   

   /* lock access to the SEP */
   SEPDriver_Unlock();

    
ErrorExit:
    return Error;
}


DRM_RESULT DRM_API DRM_BBX_RebindSymmetricKey(
    IN       DRM_BB_CONTEXT *f_pcontextBBX,
    IN const DRM_SLK        *f_pslk,
    IN OUT   DRM_BYTE       *f_pbSymmKey,
       OUT   DRM_DWORD       f_cbSymmKey )
{
    DRM_RESULT Error = DRM_SUCCESS;
    /* offset into SRAM */
    DRM_ULONG   sramOffset;
    /* read param */
    DRM_ULONG   messageParam[2];
    /* max length */
    DRM_ULONG   maxLength;
	/*buffer for encrypt key*/
	DRM_CHAR privkey[OEM_ENC_KEY_BUFF_LEN];

    if( !( (f_pcontextBBX  != NULL )
         && ( f_pslk         != NULL )
         && ( f_pbSymmKey    != NULL )
         && ( f_cbSymmKey    != 0 )
         && f_pcontextBBX->fInited ))
	{
         Error = DRM_E_INVALIDARG;
         goto ErrorExit;
	}
   
	OEM_GetEncGroupCertPrivateKey(privkey);
	/* lock access to the SEP */
    Error = SEPDriver_Lock();
	if(Error != DX_OK)
    {
		goto ErrorExit;
	}
	/*----------------------------
      start sending message to SEP 
   -----------------------------*/
   sramOffset = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);
  
   /* prepare message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_REBIND_SYM_KEY_OP_CODE;
   /* send opcode */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG),
                            sizeof(DRM_ULONG),
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

   /*send the blackbox parameters*/
   Error = DRM_BBX_sendBbxContext(f_pcontextBBX,&sramOffset);
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }

   /* send encrypt key */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&privkey[0],
                            OEM_ENC_KEY_BUFF_LEN,
                            OEM_ENC_KEY_BUFF_LEN,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* send  SLK */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(DRM_SLK));

   Error = SEPDriver_WriteParamater((DRM_ULONG)f_pslk , 
                             sizeof(DRM_SLK),
                             maxLength, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   /* send  sym key len */
   Error = SEPDriver_WriteParamater((DRM_DWORD)f_cbSymmKey , 
                             sizeof(DRM_DWORD),
                             sizeof(DRM_DWORD), 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

   /* send  key */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(f_cbSymmKey));

   Error = SEPDriver_WriteParamater((DRM_ULONG)f_pbSymmKey , 
                             f_cbSymmKey,
                             maxLength, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_POLL_FOR_REPONSE();
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*-------------------
      start reading message from the SEP 
   ---------------------*/
   
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
      goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG) * 2,
                            sizeof(DRM_ULONG) * 2,
                            &sramOffset ,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_REBIND_SYM_KEY_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check status */
   if(messageParam[1] != DRM_SUCCESS)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }
   
  /*read key */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(f_cbSymmKey);

   Error = SEPDriver_ReadParamater((DRM_ULONG)f_pbSymmKey , 
                             f_cbSymmKey,
                             maxLength, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

end_function_unlock:   

   /* lock access to the SEP */
   SEPDriver_Unlock();

    
ErrorExit:
    return Error;
}

DRM_RESULT DRM_API DRM_BBX_RebindSLK(
    IN       DRM_BB_CONTEXT *f_pcontextBBX,
    IN const DRM_BYTE        f_rgbEncSLK[__CB_DECL(PK_ENC_CIPHERTEXT_LEN)],
       OUT   DRM_SLK        *f_pslk )
{
    DRM_RESULT Error = DRM_SUCCESS;
    /* offset into SRAM */
    DRM_ULONG   sramOffset;
    /* read param */
    DRM_ULONG   messageParam[2];
    /* max length */
    DRM_ULONG   maxLength;
	/*buffer for encrypt key*/
	DRM_CHAR privkey[OEM_ENC_KEY_BUFF_LEN];

    if(!(( f_pcontextBBX  != NULL )
         && ( f_rgbEncSLK    != NULL )
         && ( f_pslk         != NULL )
         && f_pcontextBBX->fInited ))
	{
         Error = DRM_E_INVALIDARG;
         goto ErrorExit;
	}
   
	OEM_GetEncGroupCertPrivateKey(privkey);
	/* lock access to the SEP */
    Error = SEPDriver_Lock();
	if(Error != DX_OK)
    {
		goto ErrorExit;
	}
	/*----------------------------
      start sending message to SEP 
   -----------------------------*/
   sramOffset = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);
  
   /* prepare message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_SYM_REBIND_SLK_OP_CODE;
   /* send opcode */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG),
                            sizeof(DRM_ULONG),
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

   /*send the blackbox parameters*/
   Error = DRM_BBX_sendBbxContext(f_pcontextBBX,&sramOffset);
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }

   /* send encrypt key */
   Error = SEPDriver_WriteParamater((DRM_ULONG)&privkey[0],
                            OEM_ENC_KEY_BUFF_LEN,
                            OEM_ENC_KEY_BUFF_LEN,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* send enc SLK */
   Error = SEPDriver_WriteParamater((DRM_ULONG)f_pslk , 
                             PK_ENC_CIPHERTEXT_LEN,
                             PK_ENC_CIPHERTEXT_LEN, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_POLL_FOR_REPONSE();
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*-------------------
      start reading message from the SEP 
   ---------------------*/
   
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
      goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater((DRM_ULONG)&messageParam[0],
                            sizeof(DRM_ULONG) * 2,
                            sizeof(DRM_ULONG) * 2,
                            &sramOffset ,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_BBX_SYM_REBIND_SLK_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check status */
   if(messageParam[1] != DRM_SUCCESS)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }
   
  /*read info */
   maxLength = SEPDriver_ALIGNED_TO_MAX_LENGTH(sizeof(DRM_SLK));

   Error = SEPDriver_ReadParamater((DRM_ULONG)f_pslk , 
                             sizeof(DRM_SLK),
                             maxLength, 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

end_function_unlock:   

   /* lock access to the SEP */
   SEPDriver_Unlock();

    
ErrorExit:
    return Error;
}


#endif
