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

#include <drmcommon.h>
#include <drmcrt.h>
#include <drmbase64.h>
#include <drmstrings.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"

#if DRM_SUPPORT_PROFILING
static const DRM_WCHAR g_rgwchProfileLog [] = { ONE_WCHAR('C', '\0'), ONE_WCHAR(':', '\0'), ONE_WCHAR('\\', '\0'), ONE_WCHAR('W', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('R', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('P', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('\\', '\0'), ONE_WCHAR('p', '\0'), ONE_WCHAR('r', '\0'), ONE_WCHAR('o', '\0'), ONE_WCHAR('f', '\0'), ONE_WCHAR('i', '\0'), ONE_WCHAR('l', '\0'), ONE_WCHAR('e', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('l', '\0'), ONE_WCHAR('o', '\0'), ONE_WCHAR('g', '\0'), ONE_WCHAR('\0', '\0') };
#endif

static const PRIVKEY oPrivKey = 
{
    TWO_BYTES(0xB6,  0xEE),  TWO_BYTES(0x01,  0x6A),  TWO_BYTES(0x47,  0x2B),  TWO_BYTES(0x20, 0xD4),  
    TWO_BYTES(0x44,  0x84),  TWO_BYTES(0x94,  0x0A),  TWO_BYTES(0xFE,  0xDC),  TWO_BYTES(0x89, 0xD5),  
    TWO_BYTES(0x36,  0x81),  TWO_BYTES(0x8D,  0x5E)
};
static const PRIVKEY oBootStrapPrivKey = 
{
    TWO_BYTES(0x15,  0xA1),  TWO_BYTES(0xA3,  0xF6),  TWO_BYTES(0x2D,  0xD4),  TWO_BYTES(0xC6, 0xA3),  
    TWO_BYTES(0x9C,  0x0D),  TWO_BYTES(0xEC,  0xDB),  TWO_BYTES(0xA7,  0x14),  TWO_BYTES(0xF4, 0x2C),  
    TWO_BYTES(0xFB,  0x8F),  TWO_BYTES(0x75,  0x50) 
};

/* C:\\WMDRMPD\\ */
/*DX: change path*/
#if defined(__unix__)
	/*Linux DX DD*/
	static const DRM_WCHAR g_rgwchDrmPath [] = { ONE_WCHAR('.', '\0'),  ONE_WCHAR('.', '\0'), ONE_WCHAR('/', '\0'), 
					     ONE_WCHAR('W', '\0'),  ONE_WCHAR('M', '\0'),  ONE_WCHAR('D', '\0'),  
					     ONE_WCHAR('R', '\0'),  ONE_WCHAR('M', '\0'),  ONE_WCHAR('P', '\0'),  
					     ONE_WCHAR('D', '\0'),  ONE_WCHAR('/', '\0'), ONE_WCHAR('\0', '\0') };

#else
	#ifndef DX_CC5_SEP_PLAT
static const DRM_WCHAR g_rgwchDrmPath [] = { ONE_WCHAR('.', '\0'),  ONE_WCHAR('.', '\0'), ONE_WCHAR('/', '\0'), 
											 ONE_WCHAR('W', '\0'),  ONE_WCHAR('M', '\0'),  ONE_WCHAR('D', '\0'),  
											 ONE_WCHAR('R', '\0'),  ONE_WCHAR('M', '\0'),  ONE_WCHAR('P', '\0'),  
											 ONE_WCHAR('D', '\0'),  ONE_WCHAR('/', '\0'), ONE_WCHAR('\0', '\0') };
	#else
		static const DRM_WCHAR g_rgwchDrmPath [] = {
		ONE_WCHAR('.', '\0'),  ONE_WCHAR('.', '\0'),  ONE_WCHAR('/', '\0'),
		ONE_WCHAR('.', '\0'),  ONE_WCHAR('.', '\0'),  ONE_WCHAR('/', '\0'), 
		ONE_WCHAR('.', '\0'),  ONE_WCHAR('.', '\0'),  ONE_WCHAR('/', '\0'),
		ONE_WCHAR('.', '\0'),  ONE_WCHAR('.', '\0'),  ONE_WCHAR('/', '\0'),
	    ONE_WCHAR('w', '\0'),  ONE_WCHAR('m', '\0'),  ONE_WCHAR('d', '\0'),  
	    ONE_WCHAR('r', '\0'),  ONE_WCHAR('m', '\0'),  ONE_WCHAR('p', '\0'),  
		ONE_WCHAR('d', '\0'),  ONE_WCHAR('/', '\0'), ONE_WCHAR('\0', '\0') };

		/*DX trunk work branch*/
		//static const DRM_WCHAR g_rgwchDrmPath [] = {
		//ONE_WCHAR('.', '\0'),  ONE_WCHAR('.', '\0'),  ONE_WCHAR('/', '\0'),
		//ONE_WCHAR('.', '\0'),  ONE_WCHAR('.', '\0'),  ONE_WCHAR('/', '\0'), 
		//ONE_WCHAR('.', '\0'),  ONE_WCHAR('.', '\0'),  ONE_WCHAR('/', '\0'),
		//ONE_WCHAR('H', '\0'),  ONE_WCHAR('O', '\0'),  ONE_WCHAR('S', '\0'),
		//ONE_WCHAR('T', '\0'),  ONE_WCHAR('/', '\0'),
		//ONE_WCHAR('w', '\0'),  ONE_WCHAR('m', '\0'),  ONE_WCHAR('d', '\0'),  
		//ONE_WCHAR('r', '\0'),  ONE_WCHAR('m', '\0'),  ONE_WCHAR('p', '\0'),  
		//ONE_WCHAR('d', '\0'),  ONE_WCHAR('/', '\0'), ONE_WCHAR('\0', '\0') };
	#endif /*DX_CC5_SEP_PLAT*/
#endif /*__unix__*/

/* priv.dat */
static const DRM_WCHAR g_rgwchPrivKey [] = 
{
    ONE_WCHAR('p', '\0'),  ONE_WCHAR('r', '\0'),  ONE_WCHAR('i', '\0'),  ONE_WCHAR('v', '\0'),
    ONE_WCHAR('.', '\0'),  ONE_WCHAR('d', '\0'),  ONE_WCHAR('a', '\0'),  ONE_WCHAR('t', '\0'),
    ONE_WCHAR('\0', '\0')
};

/* devcert.dat */
static const DRM_WCHAR g_rgwchDevcert [] =
{
    ONE_WCHAR('d', '\0'),  ONE_WCHAR('e', '\0'),  ONE_WCHAR('v', '\0'),  ONE_WCHAR('c', '\0'),
    ONE_WCHAR('e', '\0'),  ONE_WCHAR('r', '\0'),  ONE_WCHAR('t', '\0'),  ONE_WCHAR('.', '\0'),
    ONE_WCHAR('d', '\0'),  ONE_WCHAR('a', '\0'),  ONE_WCHAR('t', '\0'),  ONE_WCHAR('\0', '\0')
};

/* devcerttemplate.dat */
static const DRM_WCHAR g_rgwchDevcerttemplate [] =
{
    ONE_WCHAR('d', '\0'),  ONE_WCHAR('e', '\0'),  ONE_WCHAR('v', '\0'),  ONE_WCHAR('c', '\0'),
    ONE_WCHAR('e', '\0'),  ONE_WCHAR('r', '\0'),  ONE_WCHAR('t', '\0'),  ONE_WCHAR('t', '\0'),
    ONE_WCHAR('e', '\0'),  ONE_WCHAR('m', '\0'),  ONE_WCHAR('p', '\0'),  ONE_WCHAR('l', '\0'),
    ONE_WCHAR('a', '\0'),  ONE_WCHAR('t', '\0'),  ONE_WCHAR('e', '\0'),  ONE_WCHAR('.', '\0'),
    ONE_WCHAR('d', '\0'),  ONE_WCHAR('a', '\0'),  ONE_WCHAR('t', '\0'),  ONE_WCHAR('\0', '\0')
};

static const DRM_CONST_STRING   g_dstrDrmPath           = CREATE_DRM_STRING( g_rgwchDrmPath );
static const DRM_CONST_STRING   g_dstrPrivKey           = CREATE_DRM_STRING( g_rgwchPrivKey );
static const DRM_CONST_STRING   g_dstrDevcert           = CREATE_DRM_STRING( g_rgwchDevcert );
static const DRM_CONST_STRING   g_dstrDevcerttemplate   = CREATE_DRM_STRING( g_rgwchDevcerttemplate );


DRM_BOOL g_fDeviceResetState = TRUE;


static DRM_RESULT DRM_API _GetDRMFullPathName( 
       OUT   DRM_WCHAR       **ppwszFullPath, 
    IN const DRM_CONST_STRING *pdstrFilename)
{
    DRM_RESULT dr          = DRM_SUCCESS;
    DRM_DWORD  cchFullPath = 0;
    DRM_DWORD  cchPath     = g_dstrDrmPath.cchString;

    ChkArg( ppwszFullPath != NULL );

    ChkDRMString( pdstrFilename );

    *ppwszFullPath = NULL;
    cchFullPath    = pdstrFilename->cchString 
                   + g_dstrDrmPath.cchString 
                   + 1;

    if( pdstrFilename->cchString + g_dstrDrmPath.cchString     < pdstrFilename->cchString
     || pdstrFilename->cchString + g_dstrDrmPath.cchString + 1 < pdstrFilename->cchString
     || cchFullPath > cchFullPath * SIZEOF( DRM_WCHAR ) )
    {
        ChkDR( DRM_E_ARITHMETIC_OVERFLOW );
    }
    
    ChkMem( *ppwszFullPath = ( DRM_WCHAR * )OEM_malloc( cchFullPath * SIZEOF( DRM_WCHAR ) ) );
    ChkDR( OEM_StringCchCopyN( *ppwszFullPath, cchFullPath, g_dstrDrmPath.pwszString, g_dstrDrmPath.cchString ) );

    /* Need to check whether it is ended with "/" */
    if ( (*ppwszFullPath)[ cchPath - 1 ] != DX_VOS_PATH_DIVIDER[0] && (*ppwszFullPath)[ cchPath - 1 ] != '/' )
    {
        (*ppwszFullPath)[ cchPath ] = DX_VOS_PATH_DIVIDER[0];
        cchPath++;
    }

    ChkDR( OEM_StringCchCopyN( *ppwszFullPath + cchPath, 
                               cchFullPath, 
                               pdstrFilename->pwszString, 
                               pdstrFilename->cchString ) );
    
    /* Null Terminate it */
    (*ppwszFullPath)[cchPath + pdstrFilename->cchString] = g_wchNull;

ErrorExit:
    return dr;
}

DRM_RESULT DRM_API OEM_GetUniqueID( 
    DRM_WCHAR  wchUniqueId[MAX_UNIQUEID_LEN], 
    DRM_DWORD *pcchLen )
{    
    DRM_BYTE shaOut [__CB_DECL(SHA_DIGEST_LEN)];
    DRM_DWORD dwSize =0;
    DRM_RESULT dr=DRM_SUCCESS;

    ChkArg( pcchLen!=NULL );
    if ( wchUniqueId==NULL || *pcchLen<CCH_BASE64_EQUIV(SHA_DIGEST_LEN) )
    {
        *pcchLen = CCH_BASE64_EQUIV(SHA_DIGEST_LEN);
        ChkDR(DRM_E_BUFFERTOOSMALL);
    }
    else
    {
        MEMSET( shaOut, 0xa, SHA_DIGEST_LEN );
        dwSize = MAX_UNIQUEID_LEN;
        ChkDR( DRM_B64_EncodeW( shaOut, SHA_DIGEST_LEN, wchUniqueId, &dwSize, 0 ) );
        *pcchLen = dwSize;
    }
    
ErrorExit:
    
    return dr;
}


/**********************************************************************
** Function:    _GetPrivateKey
** Synopsis:    
** Arguments:   [f_fGCprivkey] -- TRUE for GC privkey, FALSE for Fallback signing key
**              [f_pPrivkey]   -- returned privkey
** Returns:     DRM_SUCCESS when success.
** Notes:       GC privkey and Fallback privkey are saying in order in
**              the file.
***********************************************************************/
static DRM_RESULT _GetPrivateKey(
    IN  DRM_BOOL  f_fGCprivkey,
    OUT PRIVKEY  *f_pPrivkey)
{
    DRM_RESULT  dr=DRM_SUCCESS;
    OEM_FILEHDL fp = OEM_INVALID_HANDLE_VALUE;
    DRM_WCHAR  *pwszPath = NULL; 
    DRM_DWORD   iRead=0;
    DRM_DWORD   cbFile=0;

    ChkArg( f_pPrivkey );
    ChkDR( _GetDRMFullPathName ( &pwszPath, &g_dstrPrivKey ) );
    fp = OEM_OpenFile( pwszPath, 
                       OEM_GENERIC_READ, 
                       OEM_FILE_SHARE_READ, 
                       OEM_OPEN_EXISTING, 
                       OEM_ATTRIBUTE_HIDDEN );
    if ( fp == OEM_INVALID_HANDLE_VALUE )
    {
        ChkDR( DRM_E_FILENOTFOUND );
    }

    /* load file content in memory */
    if ( !OEM_GetFileSize( fp, &cbFile ) )
    {
        ChkDR( DRM_E_FILEREADERROR );
    }

    if ( cbFile != (2 * SIZEOF( PRIVKEY )) )
    {
        ChkDR( DRM_E_PRIVKEYREADERROR );
    }

    if ( !OEM_SetFilePointer(fp, (f_fGCprivkey? 0 : SIZEOF(PRIVKEY)),
        OEM_FILE_BEGIN, NULL) )
    {
        ChkDR(DRM_E_FILESEEKERROR);
    }
    if ( !OEM_ReadFile(fp, (DRM_BYTE *)f_pPrivkey, SIZEOF(PRIVKEY), &iRead) 
        || iRead!=SIZEOF(PRIVKEY) )
    {
        ChkDR(DRM_E_FILEREADERROR);
    }
    
ErrorExit:
    if( fp != OEM_INVALID_HANDLE_VALUE )
    {
        OEM_CloseFile( fp );
    }
    fp = OEM_INVALID_HANDLE_VALUE;
    if ( pwszPath )
    {
        OEM_free( pwszPath );
    }
    pwszPath = NULL;
    if ( DRM_FAILED ( dr ) )
    {
        dr = DRM_E_PRIVKEYREADERROR;
    }
    return dr;
}

#ifdef _DX_BLACK_BOX_SIM
/*global variable to hold "clear" key*/
PRIVKEY  privKeyBuff;
/* set key before BBX function */
DRM_RESULT DRM_API OEM_setActionGroupCertPrivKey(
												  DRM_CHAR *    f_wrapKey
												  )
{
	DX_VOS_FastMemCpy(&privKeyBuff,f_wrapKey,sizeof(PRIVKEY));
	return DRM_SUCCESS;
}
/*get the key for BBX functions*/
DRM_RESULT DRM_API OEM_GetGroupCertPrivateKey( 
    OUT PRIVKEY *f_pPrivkey)
{
	DX_VOS_FastMemCpy(f_pPrivkey,&privKeyBuff,sizeof(PRIVKEY));
	return DRM_SUCCESS;
}

#else
DRM_RESULT DRM_API OEM_setActionGroupCertPrivKey(
												  DRM_CHAR *    f_wrapKey
												  )
{
	return DRM_SUCCESS;
}
DRM_RESULT DRM_API OEM_GetGroupCertPrivateKey( 
    OUT PRIVKEY *f_pPrivkey)
{
    return _GetPrivateKey(TRUE, f_pPrivkey);
}
#endif
DRM_RESULT DRM_API OEM_GetFallbackSigningKey( 
    OUT PRIVKEY *f_pPrivkey)
{
    return _GetPrivateKey(FALSE, f_pPrivkey);
}

static const DRM_BYTE _rgbSecStorePassword[__CB_DECL(SHA_DIGEST_LEN)]= 
{
    TWO_BYTES('1','2'), TWO_BYTES('3','4'), TWO_BYTES('5','6'), TWO_BYTES('7','8'), TWO_BYTES('9','0'),
    TWO_BYTES('1','2'), TWO_BYTES('3','4'), TWO_BYTES('5','6'), TWO_BYTES('7','8'), TWO_BYTES('9','0')
};

void OEM_DoubleWChar(DRM_BYTE* pbDevCert, DRM_UINT size)
{
	DRM_UINT i = 0, j=0;
	DRM_BYTE* out = pbDevCert;
	DRM_BYTE* orig =pbDevCert;
	for(i=0;i<size/2;++i)
	{
		out[size-i*2-2] = orig[size/2-i-1];
		out[size-i*2-1] = 0;
	}
}

/**********************************************************************
** Function:    _GetDeviceCert
** Synopsis:    
** Arguments:   []
** Returns:     None
** Notes:
***********************************************************************/
DRM_RESULT _GetDeviceCert(
    OUT    DRM_BYTE  *pbDevCert,
    IN OUT DRM_DWORD *pcbDevCert,
    IN     DRM_BOOL   fTemplate )
{
    DRM_RESULT dr=DRM_SUCCESS;
    OEM_FILEHDL fp = OEM_INVALID_HANDLE_VALUE;
    DRM_WCHAR *pwszPath = NULL; 

    ChkArg( pcbDevCert );

    if ( fTemplate )
    {
        ChkDR( _GetDRMFullPathName ( &pwszPath, &g_dstrDevcerttemplate ) );
    }
    else
    {
        ChkDR( _GetDRMFullPathName ( &pwszPath, &g_dstrDevcert ) );
    }

    fp = OEM_OpenFile( pwszPath, 
                       OEM_GENERIC_READ, 
                       OEM_FILE_SHARE_READ, 
                       OEM_OPEN_EXISTING, 
                       OEM_ATTRIBUTE_HIDDEN );

    if (fp != OEM_INVALID_HANDLE_VALUE)
    {
        DRM_DWORD iRead=0;
        DRM_DWORD  cbFile =0;
        /* load file content in memory */
        if ( !OEM_GetFileSize(fp, &cbFile ) )
        {
            ChkDR(DRM_E_FILEREADERROR);
        }

        if ( *pcbDevCert < cbFile )
        {
            *pcbDevCert = cbFile;
            ChkDR(DRM_E_BUFFERTOOSMALL);
        }
        
        if ( !OEM_SetFilePointer( fp, 0, OEM_FILE_BEGIN, NULL ) )
        {
            ChkDR(DRM_E_FILESEEKERROR);
        }
        *pcbDevCert = cbFile;    
        if (!OEM_ReadFile( fp, pbDevCert, cbFile, &iRead ) ||
            iRead!=cbFile )
        {
            ChkDR( DRM_E_FILEREADERROR );
        }

    }
    else
    {
        ChkDR( DRM_E_FILENOTFOUND );
    }
ErrorExit:    
    if( fp != OEM_INVALID_HANDLE_VALUE )
    {
        OEM_CloseFile( fp );
    }
    fp = OEM_INVALID_HANDLE_VALUE;
    if ( pwszPath )
    {
        OEM_free( pwszPath );
    }
    pwszPath = NULL;
    return dr;

}

/**********************************************************************
** Function:    OEM_GetDeviceCert
** Synopsis:    
** Arguments:   []
** Returns:     None
** Notes:
***********************************************************************/
DRM_RESULT DRM_API OEM_GetDeviceCert(
    OUT    DRM_BYTE  *pbDevCert,
    IN OUT DRM_DWORD *pcbDevCert)
{
    DRM_RESULT dr=DRM_SUCCESS;
    ChkDR( _GetDeviceCert( pbDevCert, pcbDevCert, FALSE ) );

ErrorExit:    
    if ( DRM_FAILED ( dr ) )
    {
        if (DRM_E_BUFFERTOOSMALL != dr) 
        {
            dr = DRM_E_DEVCERTREADERROR;
        }
    }
    return dr;
}

/**********************************************************************
** Function:    OEM_GetDeviceCertTemplate
** Synopsis:    
** Arguments:   []
** Returns:     None
** Notes:
***********************************************************************/
DRM_RESULT DRM_API OEM_GetDeviceCertTemplate(
    OUT    DRM_BYTE  *pbDevCert,
    IN OUT DRM_DWORD *pcbDevCert)
{
    DRM_RESULT dr=DRM_SUCCESS;
    dr = _GetDeviceCert( pbDevCert, pcbDevCert, TRUE );
    if ( DRM_FAILED ( dr ) )
    {
        if ( DRM_E_BUFFERTOOSMALL != dr ) 
        {
            ChkDR( DRM_E_DEVCERTTEMPLATEREADERROR );
        }
    }

ErrorExit:    
    return dr;
}



/**********************************************************************
** Function:    OEM_GetSecureStoreGlobalPasswordSeed
** Synopsis:    
** Arguments:   []
** Returns:     None
** Notes:
***********************************************************************/
DRM_RESULT DRM_API
OEM_GetSecureStoreGlobalPasswordSeed( 
    OUT DRM_BYTE rgbSecStorePassword[__CB_DECL(SHA_DIGEST_LEN)])
{
    DRM_RESULT dr=DRM_SUCCESS;
    
    ChkArg( rgbSecStorePassword != NULL );
        
    MEMCPY(rgbSecStorePassword, _rgbSecStorePassword, SHA_DIGEST_LEN);

ErrorExit:    
    return dr;
}

/**********************************************************************
** Function:    OEM_SetDeviceCert
** Synopsis:    
** Arguments:   []
** Returns:     None
** Notes:
***********************************************************************/
DRM_RESULT DRM_API
OEM_SetDeviceCert(
    IN const DRM_BYTE *pbDevCert,
    IN DRM_DWORD cbDevCert)
{
    DRM_RESULT dr=DRM_SUCCESS;
    OEM_FILEHDL fp = OEM_INVALID_HANDLE_VALUE;
    DRM_WCHAR *pwszPath = NULL; 

    ChkArg( pbDevCert != NULL
         && cbDevCert != 0    );

    ChkDR( _GetDRMFullPathName ( &pwszPath, &g_dstrDevcert ) );


    fp = OEM_OpenFile( pwszPath, 
                       OEM_GENERIC_READ    | OEM_GENERIC_WRITE,
                       OEM_FILE_SHARE_READ | OEM_FILE_SHARE_WRITE, 
                       OEM_CREATE_ALWAYS, 
                       OEM_ATTRIBUTE_HIDDEN );

    if ( fp != OEM_INVALID_HANDLE_VALUE )
    {
        DRM_DWORD iWrite =0;
        if ( !OEM_WriteFile( fp, ( DRM_BYTE * )pbDevCert, cbDevCert, &iWrite ) ||
            iWrite!=cbDevCert )
        {
            ChkDR( DRM_E_FILEWRITEERROR );
        }
    }
    else
    {
        ChkDR( DRM_E_FILENOTFOUND );
    }
ErrorExit:
    if( fp != OEM_INVALID_HANDLE_VALUE )
    {
        OEM_CloseFile( fp );
    }
    fp = OEM_INVALID_HANDLE_VALUE;
    if ( pwszPath )
    {
        OEM_free( pwszPath );
    }

    if ( DRM_FAILED ( dr ) )
    {
        dr = DRM_E_DEVCERTWRITEERROR;
    }

    return dr;
}



/* BUGBUG. Full implementation required */
/**********************************************************************
** Function:    OEM_GetClockResetState
** Synopsis:    Get the Secure Clock Reset state.
** Arguments:   [pfReset] -- Bool to get the state
***********************************************************************/
DRM_RESULT DRM_API OEM_GetClockResetState( DRM_BOOL *pfReset )
{
    DRM_RESULT dr=DRM_SUCCESS;
    ChkArg( pfReset != NULL );

    *pfReset = g_fDeviceResetState;

ErrorExit:
    
    return dr;

}
/* BUGBUG. Full implementation required */
/**********************************************************************
** Function:    OEM_SetClockResetState
** Synopsis:    Set the Secure Clock Reset state.
** Arguments:   [fReset] -- Bool to set the state
***********************************************************************/
DRM_RESULT DRM_API OEM_SetClockResetState( DRM_BOOL fReset )
{
    DRM_RESULT dr=DRM_SUCCESS;
    
    g_fDeviceResetState = fReset;
   
    return dr;

}
#define OEM_ENC_KEY_BUFF_LEN (sizeof(PRIVKEY) + (16 - (sizeof(PRIVKEY)&0x7)))
DRM_CHAR OEM_encPrivateKey[OEM_ENC_KEY_BUFF_LEN];

DRM_RESULT DRM_API OEM_setGroupCertPrivKey(
	DRM_BOOL      isProvision,
	PRIVKEY*         f_clearKey,
	DRM_DWORD   *ccWrapKey,
	DRM_CHAR *    f_wrapKey)
{
   DRM_RESULT Error = DRM_SUCCESS;
   /* offset into SRAM */
   DRM_ULONG   sramOffset;
   /* read param */
   DRM_ULONG   messageParam[2];

	if(((isProvision == TRUE) && (f_clearKey == NULL))||
		(f_wrapKey == NULL) || (*ccWrapKey < OEM_ENC_KEY_BUFF_LEN))
	{                       
       Error = DRM_E_INVALIDARG; 
       goto ErrorExit;     
    }
	if(isProvision)
	{
   		/* 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_SET_PRIV_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 privekey */
	   Error = SEPDriver_WriteParamater((DRM_ULONG)(f_clearKey),
								sizeof(PRIVKEY),
								sizeof(PRIVKEY),
								&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_SET_PRIV_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 encrypt key */
	   Error = SEPDriver_ReadParamater((DRM_ULONG)f_wrapKey,
								OEM_ENC_KEY_BUFF_LEN,
								OEM_ENC_KEY_BUFF_LEN,
								&sramOffset,
								DX_FALSE);
	   if(Error != DX_OK)
	   {
		   goto end_function_unlock;
	   }
	   DX_VOS_FastMemCpy(OEM_encPrivateKey,f_wrapKey,OEM_ENC_KEY_BUFF_LEN);
end_function_unlock:   

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

	}
	else
	{
		DX_VOS_FastMemCpy(OEM_encPrivateKey,f_wrapKey,OEM_ENC_KEY_BUFF_LEN);
	}
   
ErrorExit:
   return Error;



}


DRM_RESULT DRM_API OEM_GetEncGroupCertPrivateKey(DRM_CHAR* encPrivKey)
{

	if(encPrivKey == NULL)
	{                       
       return DRM_E_INVALIDARG; 
    }
	DX_VOS_FastMemCpy(encPrivKey,OEM_encPrivateKey,OEM_ENC_KEY_BUFF_LEN);
	
	return DRM_SUCCESS;
}

#ifdef _DX_BLACK_BOX_SIM
#include "wmdrm_sep_api.h"
DxError_t OEM_SepSetGroupCertPrivKey(DxUint32_t  *msg_ptr,
						   DxUint32_t  *msgSize_ptr)
{
	DRM_CHAR tBuff[32];
	/*imitate encryption of the key*/
	DX_VOS_MemSetZero(tBuff,32);
	DX_VOS_FastMemCpy(tBuff,(DRM_CHAR*)&msg_ptr[DX_SEP_WMDRM_SET_PRIVATE_KEY_PRIV_KEY_DATA_OFFSET],sizeof(PRIVKEY));

	msg_ptr[DX_SEP_HOST_SEP_PROTOCOL_MSG_RC_OFFSET] = DRM_SUCCESS;
	DX_VOS_FastMemCpy((DRM_CHAR*)&msg_ptr[DX_SEP_WMDRM_SET_PRIVATE_KEY_PRIV_KEY_MSG_RPLY_OFFSET],tBuff,32);
	
	*msgSize_ptr = 20 + 32;/*header + "wrap" key length*/
	return DRM_SUCCESS;
}
#endif
#if DRM_SUPPORT_PROFILING

/**********************************************************************
** Function:    OEM_GetProfileLogPath
** Synopsis:    Get the path to the profiling log file
** Arguments:   [f_rgwchPath] -- buffer to fill in with path
**              [f_cchPath]   -- size of f_rgwchPath in chars
***********************************************************************/

DRM_RESULT DRM_API OEM_GetProfileLogPath(
       OUT DRM_WCHAR *f_rgwchPath, 
    IN     DRM_DWORD *f_pcchPath)
{
    DRM_RESULT dr = DRM_SUCCESS;

    ChkArg(f_pcchPath != NULL);

    if (*f_pcchPath < NO_OF(g_rgwchProfileLog))
    {
        *f_pcchPath = NO_OF(g_rgwchProfileLog);
        ChkDR(DRM_E_BUFFERTOOSMALL);
    }

    DRM_wcsncpy(f_rgwchPath, g_rgwchProfileLog, NO_OF(g_rgwchProfileLog));
   *f_pcchPath = NO_OF(g_rgwchProfileLog);

ErrorExit:
    return dr;
}
#endif /* DRM_SUPPORT_PROFILING */




