Jegyzet
Az oldalhoz való hozzáférés engedélyezést igényel. Próbálhatod be jelentkezni vagy könyvtárat váltani.
Az oldalhoz való hozzáférés engedélyezést igényel. Megpróbálhatod a könyvtár váltását.
1. Bevezetés
Ez a specifikáció útmutatást nyújt az eredeti berendezés gyártóknak a PlayReady 4.0-alapú digitális jogok kezelésére szolgáló (DRM) beépülő modulok androidos implementálásához. További információért lásd: https://developer.android.com/reference/android/media/MediaDrm.html.
Ez a specifikáció tájékoztatást nyújt arról, hogy a beépülő modul API-k hogyan képeznek le PlayReady-hívásokra.
1.1. Változási előzmények
| verzió | Változás |
|---|---|
| 2016. május | Kezdeti verzió |
2. Interfészek
A PlayReadyDrmPlugin biztosítja a DRM beépülő modul implementációját. A PlayReadyDrmPlugin feladata a DRM Manager API-k burkolása és a paraméterek megfelelő fordítása a felület által megadott formátumban, amelyen a PlayReady képes működni.
A PlayReadyCryptoPlugin biztosítja a Crypto beépülő modul felületének implementálását, amely a minták visszafejtéséért felelős. Az OEM-nek biztosítania kell, hogy a visszafejtett minták soha ne hagyják el a megbízható végrehajtási környezetet (TEE).
3. Művelet
Az alábbi lépések egy egyszerű lejátszási forgatókönyvet írnak le:
Az alkalmazás létrehozza a MediaDrm objektumot, amely a PlayReadyDrmPlugin példányosítását eredményezi.
Ezután hívja meg az openSessiont, amely a DRM-kezelő inicializálását eredményezi.
Az alkalmazás ezután meghívja a getKeyRequest parancsot , és initData paraméterként átadja a tartalomból kinyert tartalomfejlécet. Emellett az alkalmazás a licencszerzési feladat egyéni adatait is átadhatja az opcionálisParameters kulcs-érték vektorban. A licenc megszerzésekor az egyedi adatokat ezután Drm_Content_SetProperty hívásként kell propagálni a DRM-kezelő számára.
Ezen a ponton az alkalmazás végrehajthatja a (getKeyRequest / provideKeyResponse) parancsot, amely létrehozza a DRM Manager megfelelő (Drm_LicenseAcq_GenerateChallenge) / Drm_LicenseAcq_ProcessResponse) hívásait.
Az alkalmazás ezután létrehozhat egy MediaCrypto-objektumot , amely létrehozza a PlayReadyCryptoPlugin felület egy példányát (burkoló DRM_DECRYPT_CONTEXT), amikor a Drm_Reader_Bind hívás visszatér.
Ezután minden visszafejtési hívás a PlayReadyCryptoPlugin::d ecrypt metódust használja, amely egy leírót ad vissza a visszafejtett mintákhoz.
4. PlayReadyDRMPlugin
setPropertyString
Az alkalmazások ezzel a módszerrel adják át a paramétereket a PlayReadynek, amelyek egyébként nem lehetségesek a beépülő modul API-k jelenlegi kialakítása miatt.
DeviceStoreName – Az alkalmazásnak a munkamenet megnyitása előtt tulajdonságként kell beállítania az eszköztároló helyét. Ezután a PlayReady megkeresi a DeviceStoreName tulajdonságot, amikor inicializálja a DRM Managert az openSession hívásai során. Az eszköztároló elérési útjának elérhetőnek kell lennie az alkalmazásnak, például az alkalmazás privát adatkönyvtárának. A tulajdonságnak egy <olyan elérési útra/fájlnévre> kell mutatnia, amely a HDS-t tárolja.
LicenseChallengeCustomData – Az alkalmazás igény szerint beállíthatja ezt a tulajdonságot a getKeyRequest meghívása előtt, ahol a PlayReady megkeresi a tulajdonságot, és létrehoz egy licencszerzési kihívást, és belefoglalja az egyéni adatokat a kérelembe.
SecureStopCustomData – Az alkalmazás igény szerint beállíthatja ezt a tulajdonságot egy hívás előtt a Secure Stop kihívás létrehozásához. A PlayReady megkeresi a tulajdonságot, és összeállítja a Biztonságos leállítás kihívást, és belefoglalja az egyéni adatokat a kérésbe.
SelectKID – Azokban az esetekben, amikor az alkalmazás több memórián belüli licencet szerzett be egyetlen kötegben, megadhat egy base64 kódolású KID-t a kötéshez.
status_t PlayReadyDrmPlugin::setPropertyString(
String8 const &name,
String8 const &value)
{
DRM_RESULT dr = DRM_SUCCESS;
Mutex::Autolock lock(&SessionManager::sLock);
//
// Store the Property in the name/value KeyedVector
// for later usage.
//
ChkDR( mStringProperties.add(name, value));
if (name == "SelectKID")
{
DRM_SUBSTRING dasstrKID = DRM_EMPTY_DRM_SUBSTRING;
DRM_CONST_STRING dstrKID = DRM_EMPTY_DRM_STRING;
DRM_BYTE rgbKID[CCH_BASE64_EQUIV(CCH_BASE64_EQUIV(DRM_ID_SIZE)] = {0};
const char *pszhKID = value.string();
// Convert the ASCII KID to UNICODE
DRM_DSTR_FROM_PB(&dstrKID, rgbKID, sizeof(rgbKID));
DRM_UTL_PromoteASCIItoUNICODE(pszhKID, &dasstrKID, (DRM_STRING *)&dstrKID);
ChkDR(Drm_Content_SetProperty(
&SessionManager::soAppContext, // DRM_APP_CONTEXT pointer
DRM_CSP_SELECT_KID,
dstrKID.pwszString,
dstrKID.cchString * sizeof(DRM_WCHAR)));
}
ErrorExit:
return _DR_TO_STATUS(dr);
}
byteArrayTulajdonságBeállítása
Az alkalmazások ezzel a módszerrel adják át a paramétereket a PlayReadynek, amelyek egyébként nem lehetségesek a beépülő modul API-k jelenlegi kialakítása miatt.
ContentHeader – Az alkalmazásnak be kell állítania a tartalomfejlécet a beépülő modulon, mielőtt kriptoobjektumot próbál létrehozni. A tartalomfejléc a következő formátumok egyikében szerepelhet:
Bájttömb a PlayReady-objektum tartalmával.
Bájttömb a V2, V2.4, V4, V4.1, V4.2 fejlécek (unicode XML) tartalmával.
Széles karaktertömb, amely a 24 karakteres KeyID azonosítót adja meg.
SecureStopPublisherCert – Az alkalmazásnak egyszer be kell állítania a Közzétevő tanúsítványt a biztonságos leállítással kapcsolatos hívások előtt.
status_t PlayReadyDrmPlugin::setPropertyByteArray(
String8 const &name,
Vector<uint8_t> const &value)
{
DRM_RESULT dr = DRM_SUCCESS;
Mutex::Autolock lock(&SessionManager::sLock);
// Add the name/value pair to a KeyedVector
mByteArrayProperties.add(name, value);
// If the provided property is a content header
// go ahead and set the property.
if (name == "ContentHeader")
{
ChkDR(Drm_Content_SetProperty(
&SessionManager::soAppContext, // DRM_APP_CONTEXT pointer
DRM_CSP_AUTODETECT_HEADER,
value.data(),
value.size()));
}
ErrorExit:
return _DR_TO_STATUS(dr);
}
munkamenet megnyitása
Ennek a hívásnak az AppContext inicializálását kell eredményeznie a DRM Manager Drm_Initialize függvény meghívásával.
A hívás előtt az alkalmazásnak be kell állítania a PropertyStringet a beépülő modulon, hogy megadja a HDS tárolására használt eszköztároló elérési útját.
status_t PlayReadyDrmPlugin::openSession(Vector<luint8_t> &sessionId)
{
DRM_RESULT dr = DRM_SUCCESS;
DRM_CONST_STRING dstrDeviceStoreName = { 0 };
String8 deviceStoreName;
Mutex::Autolock lock(&SessionManager::sLock);
ChkMem(mpbOpaqueBuffer =
(DRM_BYTE*)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE));
//
// Application must call setPropertyString to set the DeviceStoreName
// before opening the session.
// So the call to getPropertyString with DeviceStoreName must return a value.
//
ChkDR(getPropertyString(String8("DeviceStoreName"), deviceStoreName));
// Convert the deviceStoreName to a DRM_CONST_STRING */
ChkDR(util_String8ToDrmConstString(deviceStoreName, &dstrDeviceStoreName));
// Initialize AppContext
ChkDR(Drm_Initialize(
&SessionManager::soAppContext,
NULL, // pOEMContext : OEM can initialize and pass if needed.
mpbOpaqueBuffer,
MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE,
&dstrDeviceStoreName));
ErrorExit:
return _DR_TO_STATUS(dr);
}
munkamenet lezárása
A DRM-munkamenet lezárásakor meg kell hívnia a Drm_Uninitialize függvényt az AppContext felszabadításához.
status_t PlayReadyDrmPlugin::closeSession(Vector<uint8_t> const &sessionId)
{
Mutex::Autolock lock(&SessionManager::sLock);
// Clear the App Context
Drm_Uninitialize(&SessionManager::soAppContext);
SAFE_FREE(mpbOpaqueBuffer);
return OK;
}
getKeyRequest
Ez a módszer egy licenckérelem-kihívást fog generálni.
ContentHeader – Az alkalmazás átadhatja a tartalomfejlécet az initData paraméterben, vagy a függvény meghívása előtt az alkalmazásnak be kell állítania a ContentHeader sztringtulajdonságot.
LicenseChallengeCustomData – Az alkalmazás a "LicenseChallengeCustomData" sztringkulccsal átadhatja a feladat egyéni adatait az opcionálisParameters paraméterben. Másik lehetőségként a metódus felveheti a LicenseChallengeCustomData értéket, ha az alkalmazás már beállította tulajdonságként.
A metódus feltölti a defaultUrl értéket, ha az elérhető a tartalomfejlécben, valamint előkészíti a licenckiszolgálónak küldendő kérést.
status_t PlayReadyDrmPlugin::getKeyRequest(
Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &initData, s// ContentHeader
String8 const &mimeType,
KeyType keyType,
KeyedVector<String8, String8=""> const &optionalParameters, // ChallengeCustomData
Vector<uint8_t> &request, // Output Challenge
String8 &defaultUrl, // Output URL
KeyRequestType *keyRequestType)
{
DRM_RESULT dr = DRM_SUCCESS;
DRM_BYTE *pbContentProperty = NULL;
DRM_DWORD cbContentProperty = 0;
DRM_CHAR *pchCustomData = NULL;
DRM_DWORD cchCustomData = 0;
DRM_CHAR *pchSilentURL = NULL;
DRM_DWORD cchSilentURL = 0;
DRM_BYTE *pbChallenge = NULL;
DRM_DWORD cbChallenge = 0;
DRM_BOOL fHasUrl = FALSE;
Vector<uint8_t> contentHeader;
String8 customData;
Mutex::Autolock lock(&SessionManager::sLock);
if (getValue(optionalParameters, String8("LicenseChallengeCustomData"), customData) == OK)
{
//
// The Application can pass the custom data as a part of the optionalParameters.
// The key string would be "LicenseChallengeCustomData".
// If it is provided. The plug-in should use it when generating the license challenge.
//
pchCustomData = customData.data();
cchCustomData = customData.size();
}
else if (getPropertyString(String8("LicenseChallengeCustomData"), customData) == OK)
{
//
// Alternatively the Application could have provided customData for this operation
// via a previous call to setPropertyString.
// Try to retrieve it if available. Otherwise, skip without failing.
//
pchCustomData = customData.data();
cchCustomData = customData.size();
}
//
// The Application could choose to pass the content header as the initData
// If the initData is passed, use it to call Drm_Content_SetProperty
//
if (value.size() != 0)
{
ChkDR(Drm_Content_SetProperty(
&SessionManager::soAppContext, // DRM_APP_CONTEXT pointer
DRM_CSP_AUTODETECT_HEADER,
value.data(),
value.size()));
}
//
// First, try to retrieve the URL.
//
dr = Drm_LicenseAcq_GenerateChallenge(
&SessionManager::soAppContext,
NULL,
0,
NULL,
pchCustomData,
cchCustomData,
pchSilentURL,
&cchSilentURL, // Attempt to get the URL size.
NULL,
NULL,
pbChallenge,
&cbChallenge);
if (dr == DRM_E_BUFFERTOOSMALL)oi
{
fHasUrl = TRUE;
// ContentHeader has a URL. Allocate buffer for it.
ChkMem(pchSilentURL = (DRM_CHAR*)Oem_MemAlloc(cchSilentURL));
}
else if (dr == DRM_E_NO_URL)
{
// No Url in the content header, no need to fail.
// The Application can get the URL independently.
dr = DRM_SUCCESS;
}
else
{
ChkDR(dr);
}
//
// Second, get the challenge size.
//
dr = Drm_LicenseAcq_GenerateChallenge(
poAppContext,
NULL,
0,
NULL,
pchCustomData,
cchCustomData,
pchSilentURL,
fHasUrl ? &cchSilentURL : NULL,
NULL,
NULL,
pbChallenge,
&cbChallenge);
if (dr == DRM_E_BUFFERTOOSMALL)
{
// Allocate buffer that is sufficient
// to store the license acquisition challenge.
ChkMem(pbChallenge = (DRM_BYTE*)Oem_MemAlloc(cbChallenge));
}
else
{
ChkDR(dr);
}
//
// Finally, generate challenge.
//
ChkDR(Drm_LicenseAcq_GenerateChallenge(
&SessionManager::soAppContext,
NULL,
0,
NULL,
pchCustomData,
cchCustomData,
pchSilentURL,
fHasUrl ? &cchSilentURL : NULL,
NULL,
NULL,
pbChallenge,
&cbChallenge));
//
// Write the License Challenge to the request buffer.
//
request.appendArray(pbChallenge, cbChallenge);
if (fHasUrl)
{
defaultUrl.appendArray(pchSilentURL, cchSilentURL);
}
ErrorExit:
SAFE_OEM_FREE(pbChallenge);
SAFE_OEM_FREE(pchSilentURL);
return _DR_TO_STATUS(dr);
}
adja meg a kulcsválaszt
Miután az alkalmazás elküldött egy KeyRequest (LicenseChallenge) a licenckiszolgálónak, tovább kell adnia a KeyResponse (LicenseResponse)-et a beépülő modulnak.
status_t PlayReadyDrmPlugin::provideKeyResponse(
Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &response,
Vector<uint8_t> &keySetId)
{
DRM_RESULT dr = DRM_SUCCESS;
DRM_LICENSE_RESPONSE oLicenseResponse = { 0 };
DRM_DWORD idx = 0;
DRM_BOOL fExceedMaxLic = FALSE;
Mutex::Autolock lock(&SessionManager::sLock);
//
// Process the response.
//
dr = Drm_LicenseAcq_ProcessResponse(
&SessionManager::soAppContext,
0,
NULL,
NULL,
response.data(),
response.size(),
&oLicenseResponse);
if(dr == DRM_E_LICACQ_TOO_MANY_LICENSES)
{
//
// Received more licenses than DRM_MAX_LICENSE_ACK.
// Allocate space for that.
//
oLicenseResponse.m_cMaxAcks = oLicenseResponse.m_cAcks;
ChkMem(oLicenseResponse.m_pAcks=
(DRM_BYTE*)Oem_MemAlloc(sizeof(DRM_LICENSE_ACK)
* oLicenseResponse.m_cAcks ));
ChkDR(Drm_LicenseAcq_ProcessResponse(
&SessionManager::soAppContext,
0,
NULL,
NULL,
response.data(),
response.size(),
&oLicenseResponse);
fExceedMaxLic = TRUE;
}
ChkDR(dr);
//
// Ensure that all licenses were processed successfully.
//
if(fExceedMaxLic)
{
for (idx = 0; idx < oLicenseResponse.m_cAcks; idx++)
{
ChkDR(oLicenseResponse.m_pAcks[idx].m_dwResult);
}
}
else
{
for (idx = 0; idx < oLicenseResponse.m_cAcks; idx++)
{
ChkDR(oLicenseResponse.m_rgoAcks[idx].m_dwResult);
}
}
ErrorExit:
SAFE_FREE(oLicenseResponse.m_pAcks);
return _DR_TO_STATUS(dr);
}
getSecureStop(s)
Az alkalmazások meghívhatják a getSecureStop metódust, hogy biztonságos leállítási kihívást generáljanak a megadott biztonságos leállítási azonosítóhoz. Alternatívaként az alkalmazás meghívhatja a getSecureStops függvényt, hogy kihívást generáljon az összes meglévő biztonságos megállítási munkamenethez.
A biztonságos leállítási feladat létrehozása előtt az alkalmazásnak meg kell adnia a közzétevői tanúsítványt a setPropertyByteArray meghívásával és a SecureStopPublisherCert átadásával.
Az alkalmazás opcionálisan a SecureStopCustomData-t is biztosíthatja a biztonságos leállítási feladat részeként.
A biztonságos leállítási feladat létrehozása után az alkalmazásnak el kell küldenie a kiszolgálónak, és vissza kell adnia a biztonsági leállítási választ a releaseSecureStops metódusra.
DRM_RESULT PlayReadyDrmPlugin::_getSecureStop(
DRM_ID *pIdSession,
DRM_BYTE **ppbChallenge,
DRM_DWORD *pcbChallenge)
{
DRM_RESULT dr = DRM_SUCCESS;
DRM_CHAR *pchCustomData = NULL;
DRM_DWORD cchCustomData = 0;
String8 customData;
Vector<uint8_t> publisherCert;
if (getPropertyString("SecureStopCustomData", customData) == OK)
{
// SecureStop CustomData is optional
pchCustomData = customData.data();
cchCustomData = customData.size();
}
// Application must set SecureStopPublisherCert before calling getSecureStop(s)
ChkDR(getPropertyByteArray("SecureStopPublisherCert", publisherCert));
ChkDR(Drm_SecureStop_GenerateChallenge(
&SessionManager::soAppContext,
pIdSession,
publisherCert.size(),
publisherCert.data(),
cchCustomData,
pchCustomData,
pcbChallenge,
ppbChallenge));
ErrorExit:
return dr;
}
status_t PlayReadyDrmPlugin::getSecureStop(
Vector<uint8_t> const &ssid, // In
Vector<uint8_t> &secureStop) // Out
{
DRM_RESULT dr = DRM_SUCCESS;
DRM_ID idSecureStop = { 0 };
DRM_BYTE *pbChallenge = NULL;
DRM_DWORD cbChallenge = 0;
Mutex::Autolock lock(&SessionManager::sLock);
ChkArg(ssid.size() == sizeof(DRM_ID));
memcpy(&idSecureStop, ssid.data(), sizeof(DRM_ID));
ChkDR(_getSecureStop(
&idSecureStop,
&pbChallenge,
&cbChallenge));
secureStop.appendArray(pbChallenge, cbChallenge);
ErrorExit:
SAFE_FREE(pbChallenge);
return _DR_TO_STATUS(dr);
}
status_t PlayReadyDrmPlugin::getSecureStops(
List<Vector<uint8_t> > &secureStops)
{
DRM_RESULT dr = DRM_SUCCESS;
DRM_BYTE *pbChallenge = NULL;
DRM_DWORD cbChallenge = 0;
Vector<uint8_t> secureStopChallenge;
Mutex::Autolock lock(&SessionManager::sLock);
ChkDR(_getSecureStop(
NULL,
&pbChallenge,
&cbChallenge));
secureStopChallenge.appendArray(pbChallenge, cbChallenge);
secureStops.push_back(secureStopChallenge);
ErrorExit:
SAFE_FREE(pbChallenge);
return _DR_TO_STATUS(dr);
}
releaseSecureStops
Miután az alkalmazás megkapta a biztonságos leállítási választ a kiszolgálótól, az üzenetet le kell adni a beépülő modulnak, hogy eltávolítsa a biztonságos leállítási információkat a tárolóból.
status_t PlayReadyDrmPlugin::releaseSecureStops(
Vector<uint8_t> const &ssRelease)
{
DRM_RESULT dr = DRM_SUCCESS;
DRM_CHAR *pchCustomData = NULL;
DRM_DWORD cchCustomData = 0;
Vector<uint8_t> publisherCert;
Mutex::Autolock lock(&SessionManager::sLock);
// Application must set SecureStopPublisherCert before calling
// releaseSecureStops
ChkDR(getPropertyByteArray("SecureStopPublisherCert", publisherCert));
ChkDR(Drm_SecureStop_ProcessResponse(
&SessionManager::soAppContext,
NULL,
publisherCert.size(),
publisherCert.data(),
ssRelease.size(),
ssRelease.data(),
&cchCustomData,
&pchCustomData));
ErrorExit:
SAFE_FREE(pchCustomData);
return _DR_TO_STATUS(dr);
}
Nem támogatott API-k (nincs művelet)
Az API-k alábbi listája nem rendelkezik megfelelő művelettel a PlayReadyben, és nem szükséges a támogatott forgatókönyvek sikeres végrehajtásához.
lekérdezniKulcsállapotot
status_t PlayReadyDrmPlugin::queryKeyStatus(
Vector<uint8_t> const &sessionId,
KeyedVector<String8, String8=""> &infoMap) const
{ return _DR_TO_STATUS(DRM_E_NOTIMPL); }
getProvisionRequest
A PlayReady csak Android-eszközökön támogatja a helyi kiépítést.
status_t PlayReadyDrmPlugin::getProvisionRequest(
String8 const &certType,
String8 const &certAuthority,
Vector<uint8_t> &request,
String8 &defaultUrl) { return _DR_TO_STATUS(DRM_E_NOTIMPL); }
provideProvisionResponse
A PlayReady csak Android-eszközökön támogatja a helyi kiépítést.
status_t PlayReadyDrmPlugin::provideProvisionResponse(
Vector<uint8_t> const &response,
Vector<uint8_t> &certificate,
Vector<uint8_t> &wrappedKey) { return _DR_TO_STATUS(DRM_E_NOTIMPL); }
unprovisionDevice
A PlayReady csak Android-eszközökön támogatja a helyi kiépítést.
status_t PlayReadyDrmPlugin::unprovisionDevice() { return _DR_TO_STATUS(DRM_E_NOTIMPL); }
titkosítási algoritmus beállítása
A PlayReady nem titkosítja/fejti vissza a tetszőleges adatokat.
status_t PlayReadyDrmPlugin::setCipherAlgorithm(
Vector<uint8_t> const &sessionId,
String8 const &algorithm) { return _DR_TO_STATUS(DRM_E_NOTIMPL); }
MacAlgoritmusBeállítás
A PlayReady nem ír alá/ellenőriz tetszőleges adatokat.
status_t PlayReadyDrmPlugin::setMacAlgorithm(
Vector<uint8_t> const &sessionId,
String8 const &algorithm) { return _DR_TO_STATUS(DRM_E_NOTIMPL); }
titkosít
A PlayReady nem titkosítja/fejti vissza a tetszőleges adatokat.
status_t PlayReadyDrmPlugin::encrypt(
Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId,
Vector<uint8_t> const &input,
Vector<uint8_t> const &iv,
Vector<uint8_t> &output) { return _DR_TO_STATUS(DRM_E_NOTIMPL); }
visszafejt
A PlayReady nem titkosítja/fejti vissza a tetszőleges adatokat.
status_t PlayReadyDrmPlugin::decrypt(
Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId,
Vector<uint8_t> const &input,
Vector<uint8_t> const &iv,
Vector<uint8_t> &output) { return _DR_TO_STATUS(DRM_E_NOTIMPL); }
jel
A PlayReady nem ír alá/ellenőriz tetszőleges adatokat.
status_t PlayReadyDrmPlugin::sign(
Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId,
Vector<uint8_t> const &message,
Vector<uint8_t> &signature) { return _DR_TO_STATUS(DRM_E_NOTIMPL); }
ellenőriz
A PlayReady nem ír alá/ellenőriz tetszőleges adatokat.
status_t PlayReadyDrmPlugin::verify(
Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId,
Vector<uint8_t> const &message,
Vector<uint8_t> const &signature,
bool &match) { return _DR_TO_STATUS(DRM_E_NOTIMPL); }
signRSA
A PlayReady nem ír alá/ellenőriz tetszőleges adatokat.
status_t PlayReadyDrmPlugin::signRSA(
Vector<uint8_t> const &sessionId,
String8 const &algorithm,
Vector<uint8_t> const &message,
Vector<uint8_t> const &wrappedKey,
Vector<uint8_t> &signature) { return _DR_TO_STATUS(DRM_E_NOTIMPL); }
5. PlayReadyCryptoPlugin
PlayReadyCryptoPlugin
PlayReadyCryptoPlugin-objektum létrehozásához szükséges konstruktor.
PlayReadyCryptoPlugin::PlayReadyCryptoPlugin(
const uint8_t sessionId[16],
const void * data,
size_t size);
{
DRM_RESULT dr = DRM_SUCCESS;
Mutex::Autolock lock(&SessionManager::sLock);
ChkDR(Drm_Reader_Bind(
&SessionManager::soAppContext,
NULL,
0,
NULL,
NULL,
&moDecryptContext));
ErrorExit:
// Cache the Bind Result and check for it on the first call to decrypt.
mdrBindResult = dr;
}
biztonságos dekóderkomponens szükséges
A PlayReady titkosított tartalmainak feldolgozásához biztonságos dekóder-összetevőre van szükség.
bool PlayReadyCryptoPlugin::requiresSecureDecoderComponent(const char *mime) const
{
// Must always return true for PlayReady Content.
return true;
}
visszafejt
A MediaCodec által elindított visszafejtés.
Mivel a visszafejtési módszer nem ad egyértelmű mintákat, hanem egy OEM-specifikus leírót, az OEM-nek biztosítania kell, hogy a MediaCodec megfelelően tudjon működni ezen a leírón.
ssize_t PlayReadyCryptoPlugin::decrypt(
bool secure,
const uint8_t key[16],
const uint8_t iv[16],
Mode mode,
const void *srcPtr,
const SubSample *subSamples,
size_t numSubSamples,
void *dstPtr,
AString *errorDetailMsg)
{
DRM_RESULT dr = DRM_SUCCESS;
DRM_DWORD idx = 0;
DRM_DWORD idxSubSample = 0;
DRM_DWORD cbEncryptedContent = 0;
DRM_UINT64 ui64InitializationVector;
DRM_DWORD *pdwEncryptedRegionMappings = NULL;
DRM_DWORD cbOpaqueClearContentHandle = 0;
Mutex::Autolock lock(mLock);
// Only AES_CTR is supported
ChkBOOL(mode == kMode_AES_CTR, DRM_E_UNSUPPORTED_ALGORITHM);
ChkArg(secure == TRUE);
// Ensure that bind returned successfully in the constructor.
ChkDR( mdrBindResult );
// Allocate a list for the region mapping.
ChkMem(pdwEncryptedRegionMappings
= Oem_MemAlloc(sizeof(DRM_DWORD)* numSubSamples * 2));
// Fill the region mappings list with the information
// from the subSamples.
for (idxSubSample = 0; idxSubSample < numSubSamples; idxSubSample++)
{
pdwEncryptedRegionMappings[idx++]
= subSamples[idxSubSample].mNumBytesOfClearData;
pdwEncryptedRegionMappings[idx++]
= subSamples[idxSubSample].mNumBytesOfEncryptedData;
// Calculate the total number of bytes
cbEncryptedContent +=
(subSamples[idxSubSample].mNumBytesOfClearData
+ subSamples[idxSubSample].mNumBytesOfEncryptedData);
}
// Convert the IV from a uint8 array to a DRM_UINT64
// Endianess should be taken into consideration.
ChkStatus(initializeIV(iv, &ui64InitializationVector));
// Decrypt
ChkDR(Drm_Reader_DecryptOpaque(
&moDecryptContext,
numSubSamples * 2,
pdwEncryptedRegionMappings,
ui64InitializationVector,
cbEncryptedContent,
srcPtr,
&cbOpaqueClearContentHandle,
&dstPtr);
ErrorExit:
// Free the Region mappings list.
SAFE_FREE(pdwEncryptedRegionMappings);
if (DRM_FAILED(dr))
{
// If an error occurs, fill the errorMessage
// then return the DRM_RESULT
SetErrorDetails(errorDetailMsg, dr);
return _DR_TO_STATUS(dr);
}
// In case of success, return the size of the handle pointing
// to the clear content.
return cbOpaqueClearContentHandle;
}
~PlayReadyCryptoPlugin
A titkosítási beépülő modul destruktorának be kell zárnia a visszafejtési környezetet.
~PlayReadyCryptoPlugin::PlayReadyCryptoPlugin()
{
Mutex::Autolock lock(mLock);
Drm_Reader_Close(&moDecryptContext);
}
6. PlayReadyDrmFactory és PlayReadyCryptoFactory
A PlayReadyDrmFactory és a PlayReadyCryptoFactory interfészek implementálása szükséges mind a PlayReadyDrmPlugin , mind a PlayReadyCryptoPlugin példányainak létrehozásához.
Mindkét gyári osztálynak jeleznie kell a hívóknak, hogy támogatják a PlayReady által védett tartalmakat használó objektumok létrehozását az isCryptoSchemeSupported API megfelelő implementálásával.
const uint8_t playready_uuid[16] =
{0x79, 0xf0, 0x04, 0x9a, 0x40, 0x98, 0x86, 0x42, 0xab, 0x92, 0xe6, 0x5b, 0xe0, 0x88, 0x5f, 0x95};
bool isCryptoSchemeSupported(const uint8_t uuid[16])
{
return (!memcmp(uuid, playready_uuid, sizeof(playready_uuid)));
}
7. SessionManager
A DRM_APP_CONTEXT tárolásához és a PlayReadyDrmPlugin és a PlayReadyCryptoPlugin közötti megosztás engedélyezéséhez egy egyszeri munkamenet-kezelőt kell implementálnia.
Más tervek is elfogadhatók, amelyek ugyanazt a célt érik el.
| SessionManager |
|---|
| statikus DRM_APP_CONTEXT soAppContext |
| statikus Mutex sLock |