Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
1. Giriş
Bu belirtim, OEM'lerin Android'de PlayReady 4.0 tabanlı dijital hak yönetimi (DRM) eklentilerini uygulaması için rehberlik sağlar. Referans için bkz. https://developer.android.com/reference/android/media/MediaDrm.html.
Bu belirtim, eklenti API'lerinin PlayReady çağrılarıyla nasıl eş olduğu hakkında bilgi sağlar.
1.1. Değişiklik Geçmişi
| Sürüm | Değişiklik |
|---|---|
| Mayıs 2016 | İlk sürüm |
2. Arabirimler
PlayReadyDrmPlugin , DRM eklenti arabirimi için uygulamayı sağlar. PlayReadyDrmPlugin , DRM Yöneticisi API'lerini sarmalamaktan ve arabirim tarafından belirtilen parametreler için uygun çeviriyi PlayReady'nin üzerinde çalışabileceği bir biçime yapmaktan sorumludur.
PlayReadyCryptoPlugin , örneklerin şifresini çözmekle sorumlu olan Şifreleme eklentisi arabiriminin uygulamasını sağlar. OEM, şifresi çözülen örneklerin güvenilir yürütme ortamından (TEE) asla ayrılmadığından emin olmalıdır.
3. İşlem
Aşağıdaki adımlarda basit bir oynatma senaryosu açıklanmaktadır.
Uygulama MediaDrm nesnesini oluşturur ve bu da PlayReadyDrmPlugin örneğini oluşturur.
Ardından openSession'ı çağırın; bu da DRM Yöneticisi'nin başlatılmasına neden olur.
Uygulama daha sonra getKeyRequest'i çağırır ve içerikten ayıklanan içerik üst bilgisini initData parametresi olarak geçirir. Buna ek olarak, uygulama isteğe bağlı parametreler anahtar-değer vektöründeki lisans alma sınaması özelleşmiş verilerini de geçirebilir. Lisans alma sınaması özel verileri daha sonra Drm_Content_SetProperty çağrısı olarak DRM Yöneticisi'ne yayılmalıdır.
Bu noktada uygulama, DRM Yöneticisi'nde eşdeğer (Drm_LicenseAcq_GenerateChallenge) / Drm_LicenseAcq_ProcessResponse) çağrıları üretecek olan (getKeyRequest / provideKeyResponse) işlemini yürütebilecektir.
Uygulama daha sonra, Drm_Reader_Bind çağrısının geri dönmesiyle PlayReadyCryptoPlugin arabirimini (DRM_DECRYPT_CONTEXT saran) oluşturacak bir MediaCrypto nesnesi örneği oluşturabilir.
Daha sonra tüm şifre çözme çağrıları PlayReadyCryptoPlugin::d ecrypt yöntemini kullanır ve bu yöntem şifresi çözülen örneklere bir tanıtıcı döndürür.
4. PlayReadyDRMPlugin
setPropertyString
Uygulamalar, eklenti API'lerinin geçerli tasarımı nedeniyle başka türlü mümkün olmayan parametreleri PlayReady'ye geçirmek için bu yöntemi kullanır.
DeviceStoreName — Uygulamanın bir oturumu açmadan önce cihaz deposunun konumunu özellik olarak ayarlaması gerekir. Ardından PlayReady, openSession çağrıları sırasında DRM Yöneticisi'ni başlatırken DeviceStoreName özelliğini arar. Cihaz deposunun yolu, uygulamanın özel veri dizini gibi uygulama tarafından erişilebilir olmalıdır. Bu özellik, HDS'yi barındırması gereken bir <yol veya dosya adına> işaret etmelidir.
LicenseChallengeCustomData — Uygulama isteğe bağlı olarak bu özelliği getKeyRequest çağrısından önce ayarlayabilir. Burada PlayReady özelliği arar ve bir lisans alma sınaması oluşturur ve özel verileri isteğe ekler.
SecureStopCustomData — Uygulama, Güvenli Durdurma sınamasını oluşturmak için bir çağrıdan önce isteğe bağlı olarak bu özelliği ayarlayabilir. PlayReady özelliği arar, Güvenli Durdurma sınamasını oluşturur ve özel verileri isteğe ekler.
SelectKID — Uygulamanın tek bir toplu işlemde birden çok bellek içi lisans aldığı durumlarda bağlama için base64 kodlu bir KID belirtebilir.
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);
}
setPropertyByteArray
Uygulamalar, Eklenti API'lerinin geçerli tasarımı nedeniyle başka türlü mümkün olmayan parametreleri PlayReady'ye geçirmek için bu yöntemi kullanır.
ContentHeader— Uygulama, Bir Crypto nesnesi oluşturmaya çalışmadan önce eklentideki içerik üst bilgisini ayarlamalıdır. İçerik üst bilgisi aşağıdaki biçimlerden birinde olabilir:
PlayReady Nesnesinin içeriğiyle bayt dizisi.
V2, V2.4, V4, V4.1, V4.2 üst bilgilerinin (unicode XML) içeriğine sahip bayt dizisi.
24 karakterlik KeyID değerini belirten geniş karakter dizisi.
SecureStopPublisherCert— Uygulama, tüm güvenli durdurma ile ilgili çağrılardan önce Yayımcı Sertifikası'nı bir kez ayarlamalıdır.
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);
}
oturumAç
Bu çağrı, DRM Yöneticisi'nin Drm_Initialize işlevini çağırarak AppContext'in başlatılmasına neden olmalıdır.
Bu çağrıdan önce uygulamanın, HDS'yi depolamak için kullanılacak cihaz deposunun yolunu sağlamak için eklentide PropertyString'i ayarlaması gerekir.
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);
}
oturumu kapat
Bir DRM Oturumunu kapatmak, AppContext'i serbest bırakmak için Drm_Uninitialize'ı çağırmalıdır.
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;
}
anahtar isteği al
Bu yöntem bir lisans isteği sınaması oluşturur.
ContentHeader— Uygulama, initData parametresindeki içerik üst bilgisini geçirebilir veya bu işlevi çağırmadan önce uygulamanın ContentHeader dize özelliğini ayarlaması gerekir.
LicenseChallengeCustomData—Uygulama optionalParameters parametresinde izin sınama özel verilerini "LicenseChallengeCustomData" dize anahtarıyla geçirebilir. Yöntem, alternatif olarak, uygulama zaten onu bir özellik olarak ayarlamışsa, LicenseChallengeCustomData'yı alabilir.
yöntemi, hem içerik üst bilgisinde hem de Lisans Sunucusu'na gönderilme isteğinde varsa defaultUrl dosyasını doldurur.
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);
}
anahtarYanıtVer
Uygulama tarafından Lisans Sunucusu'na bir KeyRequest (LicenseChallenge) gönderildikten sonra, KeyResponse (LicenseResponse) eklentiye iletilmelidir.
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)
Uygulamalar, belirtilen güvenli durdurma kimliği için güvenli bir durdurma sınaması oluşturmak üzere getSecureStop yöntemini çağırabilir. Alternatif olarak, uygulama mevcut tüm güvenli durdurma oturumları için bir sınama oluşturmak üzere getSecureStops çağrısı yapabilir.
Güvenli durdurma sınamasını oluşturmadan önce uygulamanın setPropertyByteArray çağrısı yaparak ve SecureStopPublisherCert geçirerek yayımcı sertifikası sağlaması gerekir.
İsteğe bağlı olarak uygulama, güvenli durdurma sınamasının bir parçası olarak eklenmesi için SecureStopCustomData da sağlayabilir.
Güvenli durdurma sınaması oluşturulduktan sonra uygulama bunu Sunucu'ya göndermeli ve releaseSecureStops yöntemine güvenli durdurma yanıtını geri sağlamalıdır.
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
Uygulama Sunucudan güvenli durdurma yanıtını aldıktan sonra, güvenli durdurma bilgilerini depolama alanından kaldırmak için ileti eklentiye geçirilmelidir.
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);
}
Desteklenmeyen API'ler (İşlem Yok)
Aşağıdaki API'lerin listesinde PlayReady'de karşılık gelen bir işlem yoktur ve desteklenen senaryoların başarıyla yürütülmesi için gerekli değildir.
queryKeyStatus
status_t PlayReadyDrmPlugin::queryKeyStatus(
Vector<uint8_t> const &sessionId,
KeyedVector<String8, String8=""> &infoMap) const
{ return _DR_TO_STATUS(DRM_E_NOTIMPL); }
getProvisionRequest
PlayReady yalnızca Android cihazlarda yerel sağlamayı destekler.
status_t PlayReadyDrmPlugin::getProvisionRequest(
String8 const &certType,
String8 const &certAuthority,
Vector<uint8_t> &request,
String8 &defaultUrl) { return _DR_TO_STATUS(DRM_E_NOTIMPL); }
provideProvisionResponse
PlayReady yalnızca Android cihazlarda yerel sağlamayı destekler.
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
PlayReady yalnızca Android cihazlarda yerel sağlamayı destekler.
status_t PlayReadyDrmPlugin::unprovisionDevice() { return _DR_TO_STATUS(DRM_E_NOTIMPL); }
şifreleme algoritması ayarla
PlayReady rastgele verileri şifrelemez/şifresini çözmez.
status_t PlayReadyDrmPlugin::setCipherAlgorithm(
Vector<uint8_t> const &sessionId,
String8 const &algorithm) { return _DR_TO_STATUS(DRM_E_NOTIMPL); }
MacAlgoritmasiniAyarla
PlayReady rastgele verileri imzalamaz/doğrulamaz.
status_t PlayReadyDrmPlugin::setMacAlgorithm(
Vector<uint8_t> const &sessionId,
String8 const &algorithm) { return _DR_TO_STATUS(DRM_E_NOTIMPL); }
şifrelemek
PlayReady rastgele verileri şifrelemez/şifresini çözmez.
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); }
Şifresini çöz
PlayReady rastgele verileri şifrelemez/şifresini çözmez.
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); }
işaret
PlayReady rastgele verileri imzalamaz/doğrulamaz.
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); }
doğrulamak
PlayReady, rasgele verileri imzalama veya doğrulama işlevini yerine getirmez.
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
PlayReady rastgele verileri imzalamaz/doğrulamaz.
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 nesnesi oluşturmak için oluşturucu.
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;
}
güvenli kod çözücü bileşeni gerektirir
PlayReady şifreli içeriği işlemek için güvenli bir kod çözücü bileşeni gereklidir.
bool PlayReadyCryptoPlugin::requiresSecureDecoderComponent(const char *mime) const
{
// Must always return true for PlayReady Content.
return true;
}
Şifresini çöz
MediaCodec tarafından çağrılan şifre çözme.
Şifre çözme yöntemi net örnekler vermeyeceğinden, OEM'e özgü bir tanıtıcı sağlayacağından, OEM MediaCodec'un bu tanıtıcı üzerinde doğru şekilde çalışabildiğinden emin olmalıdır.
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
Şifreleme eklentisi yıkıcısının şifre çözücü bağlamını kapatması gerekir.
~PlayReadyCryptoPlugin::PlayReadyCryptoPlugin()
{
Mutex::Autolock lock(mLock);
Drm_Reader_Close(&moDecryptContext);
}
6. PlayReadyDrmFactory ve PlayReadyCryptoFactory
Sırasıyla PlayReadyDrmPlugin ve PlayReadyCryptoPlugin örneklerini oluşturmak için PlayReadyDrmFactory ve PlayReadyCryptoFactory arabirimlerinin uygulanması gerekir.
Her iki fabrika sınıfı da çağıranlara isCryptoSchemeSupported API'sini düzgün bir şekilde uygulayarak PlayReady korumalı içerik kullanabilen nesneler oluşturmayı desteklediklerini belirtmelidir.
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
DRM_APP_CONTEXT tutmak ve PlayReadyDrmPlugin ile PlayReadyCryptoPlugin arasında paylaşılması için tek bir oturum yöneticisinin uygulanması gerekir.
Aynı amaca ulaşan diğer tasarımlar da kabul edilebilir.
| SessionManager |
|---|
| static DRM_APP_CONTEXT soAppContext |
| statik Mutex sLock |