SmartAudio/package/allwinner/tina_multimedia/libcedarx/android_adapter/awplayer/awPlayReadyLicense.cpp

473 lines
15 KiB
C++
Executable File

//#define LOG_NDEBUG 0
#define LOG_TAG "awPlayReadyLicense"
#include <utils/Log.h>
#include "awPlayReadyLicense.h"
#include "cdx_log.h"
#include <utils/String8.h>
#include <media/mediaplayer.h>
#if BOARD_USE_PLAYREADY
#define DUMP_NETWORK_DATA 1
#include <drmwindowsenv.h>
#include <drmfeatures.h>
#include <drmtypes.h>
#include <drmutilitieslite.h>
#include <drmmanager.h>
#include <drmdomainimp.h>
#include <drmrevocation.h>
#include <drmcmdlnpars.h>
#include <drmtoolsutils.h>
#include <drmtoolsmediafile.h>
#include <drmheaderparser.h>
#include <drmutf.h>
#include <drmsoapxmlutility.h>
#include <drmmeterapi.h>
#include <drmmathsafe.h>
#include <drmtoolsnetio.h>
#include <drmtrace.h>
#include <drmtoolsinit.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#define PLAYREADY_TMPFILE_DIR "/data/mediadrm/"
static DRM_RESULT DRM_CALL PolicyCallback(
__in const DRM_VOID *f_pvPolicyCallbackData,
__in DRM_POLICY_CALLBACK_TYPE f_dwCallbackType,
__in_opt const DRM_KID *f_pKID,
__in_opt const DRM_LID *f_pLID,
__in const DRM_VOID *f_pv )
{
(void)f_pKID;
(void)f_pLID;
(void)f_pv;
return DRMTOOLS_PrintPolicyCallback( f_pvPolicyCallbackData, f_dwCallbackType );
}
static void DebugAnalyze(unsigned long dr, const char* file, unsigned long line, const char* expr)
{
if (dr != 0)
logd("%s:%ld 0x%x(%s)", file, line, (int)dr, expr);
}
static DRM_RESULT DRM_CALL DumpData(
__in const DRM_CONST_STRING *f_path,
__in_ecount(f_cbPacket) DRM_BYTE *f_pbPacket,
__in DRM_DWORD f_cbPacket )
{
DRM_RESULT dr = DRM_SUCCESS;
#if DUMP_NETWORK_DATA
OEM_FILEHDL fp = OEM_INVALID_HANDLE_VALUE;
DRM_DWORD cbWritten = 0;
ChkArg( f_pbPacket != NULL && f_cbPacket > 0 );
fp = Oem_File_Open( NULL,
f_path->pwszString,
OEM_GENERIC_WRITE,
OEM_FILE_SHARE_NONE,
OEM_CREATE_ALWAYS,
OEM_ATTRIBUTE_NORMAL );
if ( fp == OEM_INVALID_HANDLE_VALUE )
{
ChkDR( DRM_E_FAIL );
}
if ( !Oem_File_Write( fp, f_pbPacket, f_cbPacket, &cbWritten ) ||
cbWritten != f_cbPacket )
{
ChkDR( DRM_E_FAIL );
}
ErrorExit:
if ( fp != OEM_INVALID_HANDLE_VALUE )
{
Oem_File_Close( fp );
}
#endif
return dr;
}
static DRM_BOOL DRM_CALL LoadFile(const DRM_CONST_STRING * pPath, DRM_BYTE **ppBuffer, DRM_DWORD *pSize)
{
DRM_RESULT dr = DRM_SUCCESS;
OEM_FILEHDL fp = OEM_INVALID_HANDLE_VALUE;
DRM_DWORD cbRead = 0;
ChkBOOL( ( fp = Oem_File_Open( NULL,
pPath->pwszString,
OEM_GENERIC_READ,
OEM_FILE_SHARE_READ,
OEM_OPEN_EXISTING,
OEM_ATTRIBUTE_NORMAL ) ) != OEM_INVALID_HANDLE_VALUE,
DRM_E_FILEOPEN );
ChkBOOL( Oem_File_SetFilePointer( fp,
0,
OEM_FILE_END,
pSize ), DRM_E_FILE_SEEK_ERROR );
ChkMem( *ppBuffer = ( DRM_BYTE * )Oem_MemAlloc( *pSize ) );
ChkBOOL( Oem_File_SetFilePointer( fp,
0,
OEM_FILE_BEGIN,
NULL ), DRM_E_FILE_SEEK_ERROR );
ChkBOOL( Oem_File_Read( fp,
*ppBuffer,
*pSize,
&cbRead ), DRM_E_FILE_READ_ERROR );
ChkBOOL( cbRead == *pSize, DRM_E_FILE_READ_ERROR );
ErrorExit:
if ( fp != OEM_INVALID_HANDLE_VALUE )
{
Oem_File_Close( fp );
}
return dr;
}
static DRM_RESULT GenerateLicenseChallege(DRM_APP_CONTEXT *AppContext, DRM_BYTE *pbHeader, DRM_DWORD cbHeader, DRM_BYTE **ppbChallenge, DRM_DWORD *pcbChallenge)
{
DRM_RESULT dr = DRM_SUCCESS;
const DRM_CONST_STRING *rgpdstrRights[ 1 ] = { 0 };
DRM_BYTE *pbHeader2 = NULL;
DRM_STRING dstrHeader = DRM_EMPTY_DRM_STRING;
DRM_SUBSTRING dasstrHeader1 = DRM_EMPTY_DRM_SUBSTRING;
DRM_BYTE *pbChallenge = NULL;
DRM_DWORD cbChallenge = 0;
DRM_CHAR rgchURL[ 1024 ];
DRM_DWORD cchURL = 1024;
DRM_ID poBatchID = {0};
rgpdstrRights[ 0 ] = &g_dstrWMDRM_RIGHT_PLAYBACK;
ChkMem( pbHeader2 = (DRM_BYTE *)Oem_MemAlloc( cbHeader * sizeof( DRM_WCHAR ) ) );
DRM_DSTR_FROM_PB( &dstrHeader, pbHeader2, cbHeader * sizeof( DRM_WCHAR ) );
dasstrHeader1.m_cch = cbHeader;
DRM_UTL_PromoteASCIItoUNICODE( (const DRM_CHAR *)pbHeader,
&dasstrHeader1,
( DRM_STRING * )&dstrHeader );
ChkDR( Drm_Content_SetProperty( AppContext,
DRM_CSP_AUTODETECT_HEADER,
DRM_PB_DSTR( &dstrHeader ),
DRM_CB_DSTR( &dstrHeader ) ) );
dr = Drm_LicenseAcq_GenerateChallenge( AppContext,
(const DRM_CONST_STRING **)rgpdstrRights,
DRM_NO_OF (rgpdstrRights),
NULL,
NULL,
0,
rgchURL,
&cchURL,
NULL,
NULL,
NULL,
&cbChallenge,
&poBatchID);
if ( dr != DRM_E_BUFFERTOOSMALL )
{
if (dr!= DRM_SUCCESS)
{
ChkDR( dr );
}
else
{
ChkDR( DRM_E_TEST_UNEXPECTED_OUTPUT);
}
}
ChkBOOL( cchURL <= 1024, DRM_E_FAIL );
ChkMem( pbChallenge = ( DRM_BYTE * )Oem_MemAlloc( cbChallenge ) );
ChkDR( Drm_LicenseAcq_GenerateChallenge( AppContext,
(const DRM_CONST_STRING **)rgpdstrRights,
DRM_NO_OF (rgpdstrRights),
NULL,
NULL,
0,
rgchURL,
&cchURL,
NULL,
NULL,
pbChallenge,
&cbChallenge,
&poBatchID) );
*ppbChallenge = pbChallenge;
*pcbChallenge = cbChallenge;
ErrorExit:
SAFE_OEM_FREE( pbHeader2 );
return dr;
}
DRM_RESULT DRM_CALL GenerateLicenseAck(
DRM_APP_CONTEXT *f_poAppContext,
DRM_LICENSE_RESPONSE *f_poLicResponse,
DRM_BYTE **f_ppbAcknowledgement,
DRM_DWORD *f_pcbAcknowledgement )
{
DRM_RESULT dr = DRM_SUCCESS;
ChkArg( f_poAppContext != NULL );
ChkArg( f_poLicResponse != NULL );
ChkArg( f_ppbAcknowledgement != NULL );
ChkArg( f_pcbAcknowledgement != NULL );
dr = Drm_LicenseAcq_GenerateAck( f_poAppContext,
f_poLicResponse,
NULL,
f_pcbAcknowledgement);
if ( dr == DRM_E_BUFFERTOOSMALL )
{
ChkMem( *f_ppbAcknowledgement =
(DRM_BYTE *)Oem_MemAlloc( *f_pcbAcknowledgement ) );
ChkDR( Drm_LicenseAcq_GenerateAck( f_poAppContext,
f_poLicResponse,
*f_ppbAcknowledgement,
f_pcbAcknowledgement ) );
}
else
{
goto ErrorExit;
}
ErrorExit:
return dr;
}
static inline void stringToWString(DRM_WCHAR *dst, char *src)
{
while ((*dst++ = *src++));
}
static DRM_RESULT doLicensing(const char *la_url)
{
DRM_RESULT dr = DRM_SUCCESS;
logd("%s %d, dr: %08x", __func__, __LINE__, dr);
DRM_APP_CONTEXT *AppContext = NULL;
DRM_BYTE *pbOpaqueBuffer = NULL;
DRM_BYTE *pbRevocationBuffer = NULL;
DRM_LICENSE_RESPONSE oLicResponse;// = { eUnknownProtocol };
DRM_BYTE *pbHeader = NULL;
DRM_DWORD cbHeader = 0;
DRM_BYTE *pbChallenge1 = NULL;
DRM_DWORD cbChallenge1 = 0;
DRM_BYTE *pbChallenge2 = NULL;
DRM_DWORD cbChallenge2 = 0;
DRM_BYTE *pbResponse1 = NULL;
DRM_DWORD cbResponse1 = 0;
DRM_BYTE *pbResponse2 = NULL;
DRM_DWORD cbResponse2 = 0;
int i;
logd("%s %d", __func__, __LINE__);
char *pchar;
short *pshort;
// chl1.dat, mode = w+b
char chl1[] = PLAYREADY_TMPFILE_DIR "chl1.dat";
DRM_WCHAR wchl1[sizeof(chl1)] = {0};
stringToWString(wchl1, chl1);
const DRM_CONST_STRING strchl1 = DRM_CREATE_DRM_STRING(wchl1);
// chl2.dat, mode = w+b
char chl2[] = PLAYREADY_TMPFILE_DIR "chl2.dat";
DRM_WCHAR wchl2[sizeof(chl2)] = {0};
stringToWString(wchl2, chl2);
const DRM_CONST_STRING strchl2 = DRM_CREATE_DRM_STRING(wchl2);
// rsp1.dat, mode = w+b
char rsp1[] = PLAYREADY_TMPFILE_DIR "rsp1.dat";
DRM_WCHAR wrsp1[sizeof(rsp1)] = {0};
stringToWString(wrsp1, rsp1);
const DRM_CONST_STRING strrsp1 = DRM_CREATE_DRM_STRING(wrsp1);
// rsp2.dat, mode = w+b
char rsp2[] = PLAYREADY_TMPFILE_DIR "rsp2.dat";
DRM_WCHAR wrsp2[sizeof(rsp2)] = {0};
stringToWString(wrsp2, rsp2);
const DRM_CONST_STRING strrsp2 = DRM_CREATE_DRM_STRING(wrsp2);
// sstr.xml
char pin[] = PLAYREADY_TMPFILE_DIR "sstr.xml";
DRM_WCHAR wpin[sizeof(pin)] = {0};
stringToWString(wpin, pin);
DRM_CONST_STRING strin = DRM_CREATE_DRM_STRING(wpin);
// pr.hds
char prhds[] = PLAYREADY_TMPFILE_DIR "pr.hds";
DRM_WCHAR wprhds[sizeof(prhds)] = {0};
stringToWString(wprhds, prhds);
const DRM_CONST_STRING strhds = DRM_CREATE_DRM_STRING(wprhds);
// response.xml
char res[] = PLAYREADY_TMPFILE_DIR "response.xml";
DRM_WCHAR wres[sizeof(res)] = {0};
stringToWString(wres, res);
DRM_CONST_STRING strresponse = DRM_CREATE_DRM_STRING(wres);
memset(&oLicResponse, 0, sizeof(oLicResponse));
oLicResponse.m_eType = eUnknownProtocol;
SetDbgAnalyzeFunction(DebugAnalyze);
logd("%s %d", __func__, __LINE__);
ChkDR( DRMTOOLS_DrmInitializeWithOpaqueBuffer(NULL, &strhds, TOOLS_DRM_BUFFER_SIZE, &pbOpaqueBuffer, &AppContext) );
logd("%s %d", __func__, __LINE__);
if( DRM_REVOCATION_IsRevocationSupported() )
{
ChkMem( pbRevocationBuffer = ( DRM_BYTE * )Oem_MemAlloc( REVOCATION_BUFFER_SIZE ) );
ChkDR( Drm_Revocation_SetBuffer( AppContext,
pbRevocationBuffer,
REVOCATION_BUFFER_SIZE ) );
}
logd("%s %d", __func__, __LINE__);
ChkDR( LoadFile(&strin, &pbHeader, &cbHeader) );
logd("%s %d", __func__, __LINE__);
ChkDR( GenerateLicenseChallege(AppContext, pbHeader, cbHeader, &pbChallenge1, &cbChallenge1) );
logd("%s %d", __func__, __LINE__);
ChkDR( DumpData(&strchl1, pbChallenge1, cbChallenge1) );
logd("%s %d", __func__, __LINE__);
ChkDR( DRM_TOOLS_NETIO_SendData( la_url,
eDRM_TOOLS_NET_LICGET,
pbChallenge1,
cbChallenge1,
&pbResponse1,
&cbResponse1) );
logd("%s %d", __func__, __LINE__);
ChkDR( DumpData(&strrsp1, pbResponse1, cbResponse1) );
logd("%s %d", __func__, __LINE__);
oLicResponse.m_dwResult = DRM_SUCCESS;
ChkDR( Drm_LicenseAcq_ProcessResponse( AppContext,
DRM_PROCESS_LIC_RESPONSE_SIGNATURE_NOT_REQUIRED,
pbResponse1,
cbResponse1,
&oLicResponse ) );
logd("%s %d", __func__, __LINE__);
ChkDR( DumpData(&strresponse, pbResponse1, cbResponse1) );
logd("%s %d result: %08x", __func__, __LINE__, oLicResponse.m_dwResult);
if (!DRM_SUCCEEDED(oLicResponse.m_dwResult)) {
ChkDR(DRM_E_FAIL);
} else {
logd("transid:%d\n", oLicResponse.m_cbTransactionID);
if (oLicResponse.m_cbTransactionID > 0) {
ChkDR( GenerateLicenseAck( AppContext,
&oLicResponse,
&pbChallenge2,
&cbChallenge2) );
logd("%s %d", __func__, __LINE__);
ChkDR( DumpData(&strchl2, pbChallenge2, cbChallenge2) );
logd("%s %d", __func__, __LINE__);
ChkDR( DRM_TOOLS_NETIO_SendData( la_url,
eDRM_TOOLS_NET_LICACK,
pbChallenge2,
cbChallenge2,
&pbResponse2,
&cbResponse2) );
logd("%s %d", __func__, __LINE__);
ChkDR( DumpData(&strrsp2, pbResponse2, cbResponse2) );
logd("%s %d", __func__, __LINE__);
DRM_RESULT dr1 = DRM_SUCCESS;
ChkDR( Drm_LicenseAcq_ProcessAckResponse( AppContext,
pbResponse2,
cbResponse2,
&dr1 ) );
logd("%s %d", __func__, __LINE__);
ChkDR(dr1);
logd("%s %d", __func__, __LINE__);
}
}
logd("%s %d", __func__, __LINE__);
ErrorExit:
SAFE_OEM_FREE(pbRevocationBuffer);
DRMTOOLS_DrmUninitializeWithOpaqueBuffer( &pbOpaqueBuffer, &AppContext );
SAFE_OEM_FREE(pbHeader);
SAFE_OEM_FREE(pbChallenge1);
SAFE_OEM_FREE(pbChallenge2);
SAFE_OEM_FREE(pbResponse1);
SAFE_OEM_FREE(pbResponse2);
logd("end, dr=0x%x\n", (int)dr);
return dr;
}
#define FUN_PROCESS_LICENSE 1
status_t PlayReady_Drm_Invoke(const Parcel &request, Parcel *reply)
{
int func;
int ret = request.readInt32(&func);
if(ret != OK)
return ret;
switch (func)
{
case FUN_PROCESS_LICENSE:
{
String8 wrmheader(request.readString8());
String8 la_url(request.readString8());
logd("wrmheader=%s", wrmheader.string());
logd("la_url=%s", la_url.string());
// save to file, will be used in decryption
FILE *fp = fopen(PLAYREADY_TMPFILE_DIR "sstr.xml", "wb");
if (fp) {
fwrite(wrmheader.string(), 1, wrmheader.length(), fp);
fclose(fp);
} else {
loge("write file failed: %s", strerror(errno));
}
ret = doLicensing(la_url.string());
reply->writeInt32(ret);
}
break;
default:
break;
}
return OK;
}
#else
status_t PlayReady_Drm_Invoke(const Parcel &request, Parcel *reply)
{
reply->writeInt32(-1);
return 0;
}
#endif