From 4c63a239c404af1e055e5f9939939ab0fd09d98a Mon Sep 17 00:00:00 2001 From: Jeff Tinker Date: Sat, 30 Mar 2013 16:19:44 -0700 Subject: MediaDrm API update Clarify offline usage of sessions and keys and implement implement CryptoSession to support additional crypto use cases. Change-Id: I5d8000ce7e1dd7eba08969fc50296c9e1456c4fc --- drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp | 279 ++++++++++++++++++++-- drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h | 57 ++++- 2 files changed, 303 insertions(+), 33 deletions(-) (limited to 'drm') diff --git a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp index 91f5c9c..c34690b 100644 --- a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp +++ b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp @@ -21,6 +21,7 @@ #include "drm/DrmAPI.h" #include "MockDrmCryptoPlugin.h" +#include "media/stagefright/MediaErrors.h" using namespace android; @@ -98,17 +99,17 @@ namespace android { } - status_t MockDrmPlugin::getLicenseRequest(Vector const &sessionId, - Vector const &initData, - String8 const &mimeType, LicenseType licenseType, - KeyedVector const &optionalParameters, - Vector &request, String8 &defaultUrl) + status_t MockDrmPlugin::getKeyRequest(Vector const &sessionId, + Vector const &initData, + String8 const &mimeType, KeyType keyType, + KeyedVector const &optionalParameters, + Vector &request, String8 &defaultUrl) { Mutex::Autolock lock(mLock); - ALOGD("MockDrmPlugin::getLicenseRequest(sessionId=%s, initData=%s, mimeType=%s" - ", licenseType=%d, optionalParameters=%s))", + ALOGD("MockDrmPlugin::getKeyRequest(sessionId=%s, initData=%s, mimeType=%s" + ", keyType=%d, optionalParameters=%s))", vectorToString(sessionId).string(), vectorToString(initData).string(), mimeType.string(), - licenseType, stringMapToString(optionalParameters).string()); + keyType, stringMapToString(optionalParameters).string()); ssize_t index = findSession(sessionId); if (index == kNotFound) { @@ -119,15 +120,15 @@ namespace android { // Properties used in mock test, set by mock plugin and verifed cts test app // byte[] initData -> mock-initdata // string mimeType -> mock-mimetype - // string licenseType -> mock-licensetype + // string keyType -> mock-keytype // string optionalParameters -> mock-optparams formatted as {key1,value1},{key2,value2} mByteArrayProperties.add(String8("mock-initdata"), initData); mStringProperties.add(String8("mock-mimetype"), mimeType); - String8 licenseTypeStr; - licenseTypeStr.appendFormat("%d", (int)licenseType); - mStringProperties.add(String8("mock-licensetype"), licenseTypeStr); + String8 keyTypeStr; + keyTypeStr.appendFormat("%d", (int)keyType); + mStringProperties.add(String8("mock-keytype"), keyTypeStr); String8 params; for (size_t i = 0; i < optionalParameters.size(); i++) { @@ -159,11 +160,12 @@ namespace android { return OK; } - status_t MockDrmPlugin::provideLicenseResponse(Vector const &sessionId, - Vector const &response) + status_t MockDrmPlugin::provideKeyResponse(Vector const &sessionId, + Vector const &response, + Vector &keySetId) { Mutex::Autolock lock(mLock); - ALOGD("MockDrmPlugin::provideLicenseResponse(sessionId=%s, response=%s)", + ALOGD("MockDrmPlugin::provideKeyResponse(sessionId=%s, response=%s)", vectorToString(sessionId).string(), vectorToString(response).string()); ssize_t index = findSession(sessionId); if (index == kNotFound) { @@ -176,30 +178,61 @@ namespace android { // Properties used in mock test, set by mock plugin and verifed cts test app // byte[] response -> mock-response - mByteArrayProperties.add(String8("mock-response"), response); + const size_t kKeySetIdSize = 8; + + for (size_t i = 0; i < kKeySetIdSize / sizeof(long); i++) { + long r = random(); + keySetId.appendArray((uint8_t *)&r, sizeof(long)); + } + mKeySets.add(keySetId); + return OK; } - status_t MockDrmPlugin::removeLicense(Vector const &sessionId) + status_t MockDrmPlugin::removeKeys(Vector const &keySetId) { Mutex::Autolock lock(mLock); - ALOGD("MockDrmPlugin::removeLicense(sessionId=%s)", - vectorToString(sessionId).string()); + ALOGD("MockDrmPlugin::removeKeys(keySetId=%s)", + vectorToString(keySetId).string()); + + ssize_t index = findKeySet(keySetId); + if (index == kNotFound) { + ALOGD("Invalid keySetId"); + return BAD_VALUE; + } + mKeySets.removeAt(index); + + return OK; + } + + status_t MockDrmPlugin::restoreKeys(Vector const &sessionId, + Vector const &keySetId) + { + Mutex::Autolock lock(mLock); + ALOGD("MockDrmPlugin::restoreKeys(sessionId=%s, keySetId=%s)", + vectorToString(sessionId).string(), + vectorToString(keySetId).string()); ssize_t index = findSession(sessionId); if (index == kNotFound) { ALOGD("Invalid sessionId"); return BAD_VALUE; } + index = findKeySet(keySetId); + if (index == kNotFound) { + ALOGD("Invalid keySetId"); + return BAD_VALUE; + } + return OK; } - status_t MockDrmPlugin::queryLicenseStatus(Vector const &sessionId, + status_t MockDrmPlugin::queryKeyStatus(Vector const &sessionId, KeyedVector &infoMap) const { - ALOGD("MockDrmPlugin::queryLicenseStatus(sessionId=%s)", + ALOGD("MockDrmPlugin::queryKeyStatus(sessionId=%s)", vectorToString(sessionId).string()); ssize_t index = findSession(sessionId); @@ -324,6 +357,198 @@ namespace android { return OK; } + status_t MockDrmPlugin::setCipherAlgorithm(Vector const &sessionId, + String8 const &algorithm) + { + Mutex::Autolock lock(mLock); + + ALOGD("MockDrmPlugin::setCipherAlgorithm(sessionId=%s, algorithm=%s)", + vectorToString(sessionId).string(), algorithm.string()); + + ssize_t index = findSession(sessionId); + if (index == kNotFound) { + ALOGD("Invalid sessionId"); + return BAD_VALUE; + } + + if (algorithm == "AES/CBC/NoPadding") { + return OK; + } + return BAD_VALUE; + } + + status_t MockDrmPlugin::setMacAlgorithm(Vector const &sessionId, + String8 const &algorithm) + { + Mutex::Autolock lock(mLock); + + ALOGD("MockDrmPlugin::setMacAlgorithm(sessionId=%s, algorithm=%s)", + vectorToString(sessionId).string(), algorithm.string()); + + ssize_t index = findSession(sessionId); + if (index == kNotFound) { + ALOGD("Invalid sessionId"); + return BAD_VALUE; + } + + if (algorithm == "HmacSHA256") { + return OK; + } + return BAD_VALUE; + } + + status_t MockDrmPlugin::encrypt(Vector const &sessionId, + Vector const &keyId, + Vector const &input, + Vector const &iv, + Vector &output) + { + Mutex::Autolock lock(mLock); + ALOGD("MockDrmPlugin::encrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)", + vectorToString(sessionId).string(), + vectorToString(keyId).string(), + vectorToString(input).string(), + vectorToString(iv).string()); + + ssize_t index = findSession(sessionId); + if (index == kNotFound) { + ALOGD("Invalid sessionId"); + return BAD_VALUE; + } + + // Properties used in mock test, set by mock plugin and verifed cts test app + // byte[] keyId -> mock-keyid + // byte[] input -> mock-input + // byte[] iv -> mock-iv + mByteArrayProperties.add(String8("mock-keyid"), keyId); + mByteArrayProperties.add(String8("mock-input"), input); + mByteArrayProperties.add(String8("mock-iv"), iv); + + // Properties used in mock test, set by cts test app returned from mock plugin + // byte[] mock-output -> output + index = mByteArrayProperties.indexOfKey(String8("mock-output")); + if (index < 0) { + ALOGD("Missing 'mock-request' parameter for mock"); + return BAD_VALUE; + } else { + output = mByteArrayProperties.valueAt(index); + } + return OK; + } + + status_t MockDrmPlugin::decrypt(Vector const &sessionId, + Vector const &keyId, + Vector const &input, + Vector const &iv, + Vector &output) + { + Mutex::Autolock lock(mLock); + ALOGD("MockDrmPlugin::decrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)", + vectorToString(sessionId).string(), + vectorToString(keyId).string(), + vectorToString(input).string(), + vectorToString(iv).string()); + + ssize_t index = findSession(sessionId); + if (index == kNotFound) { + ALOGD("Invalid sessionId"); + return BAD_VALUE; + } + + // Properties used in mock test, set by mock plugin and verifed cts test app + // byte[] keyId -> mock-keyid + // byte[] input -> mock-input + // byte[] iv -> mock-iv + mByteArrayProperties.add(String8("mock-keyid"), keyId); + mByteArrayProperties.add(String8("mock-input"), input); + mByteArrayProperties.add(String8("mock-iv"), iv); + + // Properties used in mock test, set by cts test app returned from mock plugin + // byte[] mock-output -> output + index = mByteArrayProperties.indexOfKey(String8("mock-output")); + if (index < 0) { + ALOGD("Missing 'mock-request' parameter for mock"); + return BAD_VALUE; + } else { + output = mByteArrayProperties.valueAt(index); + } + return OK; + } + + status_t MockDrmPlugin::sign(Vector const &sessionId, + Vector const &keyId, + Vector const &message, + Vector &signature) + { + Mutex::Autolock lock(mLock); + ALOGD("MockDrmPlugin::sign(sessionId=%s, keyId=%s, message=%s)", + vectorToString(sessionId).string(), + vectorToString(keyId).string(), + vectorToString(message).string()); + + ssize_t index = findSession(sessionId); + if (index == kNotFound) { + ALOGD("Invalid sessionId"); + return BAD_VALUE; + } + + // Properties used in mock test, set by mock plugin and verifed cts test app + // byte[] keyId -> mock-keyid + // byte[] message -> mock-message + mByteArrayProperties.add(String8("mock-keyid"), keyId); + mByteArrayProperties.add(String8("mock-message"), message); + + // Properties used in mock test, set by cts test app returned from mock plugin + // byte[] mock-signature -> signature + index = mByteArrayProperties.indexOfKey(String8("mock-signature")); + if (index < 0) { + ALOGD("Missing 'mock-request' parameter for mock"); + return BAD_VALUE; + } else { + signature = mByteArrayProperties.valueAt(index); + } + return OK; + } + + status_t MockDrmPlugin::verify(Vector const &sessionId, + Vector const &keyId, + Vector const &message, + Vector const &signature, + bool &match) + { + Mutex::Autolock lock(mLock); + ALOGD("MockDrmPlugin::verify(sessionId=%s, keyId=%s, message=%s, signature=%s)", + vectorToString(sessionId).string(), + vectorToString(keyId).string(), + vectorToString(message).string(), + vectorToString(signature).string()); + + ssize_t index = findSession(sessionId); + if (index == kNotFound) { + ALOGD("Invalid sessionId"); + return BAD_VALUE; + } + + // Properties used in mock test, set by mock plugin and verifed cts test app + // byte[] keyId -> mock-keyid + // byte[] message -> mock-message + // byte[] signature -> mock-signature + mByteArrayProperties.add(String8("mock-keyid"), keyId); + mByteArrayProperties.add(String8("mock-message"), message); + mByteArrayProperties.add(String8("mock-signature"), signature); + + // Properties used in mock test, set by cts test app returned from mock plugin + // String mock-match "1" or "0" -> match + index = mStringProperties.indexOfKey(String8("mock-match")); + if (index < 0) { + ALOGD("Missing 'mock-request' parameter for mock"); + return BAD_VALUE; + } else { + match = atol(mStringProperties.valueAt(index).string()); + } + return OK; + } + ssize_t MockDrmPlugin::findSession(Vector const &sessionId) const { ALOGD("findSession: nsessions=%d, size=%d", mSessions.size(), sessionId.size()); @@ -335,6 +560,18 @@ namespace android { return kNotFound; } + ssize_t MockDrmPlugin::findKeySet(Vector const &keySetId) const + { + ALOGD("findKeySet: nkeySets=%d, size=%d", mKeySets.size(), keySetId.size()); + for (size_t i = 0; i < mKeySets.size(); ++i) { + if (memcmp(mKeySets[i].array(), keySetId.array(), keySetId.size()) == 0) { + return i; + } + } + return kNotFound; + } + + // Conversion utilities String8 MockDrmPlugin::vectorToString(Vector const &vector) const { diff --git a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h index d46a127..ca9eac7 100644 --- a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h +++ b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h @@ -57,21 +57,23 @@ namespace android { status_t openSession(Vector &sessionId); status_t closeSession(Vector const &sessionId); - status_t - getLicenseRequest(Vector const &sessionId, - Vector const &initData, - String8 const &mimeType, LicenseType licenseType, - KeyedVector const &optionalParameters, - Vector &request, String8 &defaultUrl); + status_t getKeyRequest(Vector const &sessionId, + Vector const &initData, + String8 const &mimeType, KeyType keyType, + KeyedVector const &optionalParameters, + Vector &request, String8 &defaultUrl); - status_t provideLicenseResponse(Vector const &sessionId, - Vector const &response); + status_t provideKeyResponse(Vector const &sessionId, + Vector const &response, + Vector &keySetId); - status_t removeLicense(Vector const &sessionId); + status_t removeKeys(Vector const &keySetId); - status_t - queryLicenseStatus(Vector const &sessionId, - KeyedVector &infoMap) const; + status_t restoreKeys(Vector const &sessionId, + Vector const &keySetId); + + status_t queryKeyStatus(Vector const &sessionId, + KeyedVector &infoMap) const; status_t getProvisionRequest(Vector &request, String8 &defaultUrl); @@ -90,15 +92,46 @@ namespace android { status_t setPropertyByteArray(String8 const &name, Vector const &value ); + status_t setCipherAlgorithm(Vector const &sessionId, + String8 const &algorithm); + + status_t setMacAlgorithm(Vector const &sessionId, + String8 const &algorithm); + + status_t encrypt(Vector const &sessionId, + Vector const &keyId, + Vector const &input, + Vector const &iv, + Vector &output); + + status_t decrypt(Vector const &sessionId, + Vector const &keyId, + Vector const &input, + Vector const &iv, + Vector &output); + + status_t sign(Vector const &sessionId, + Vector const &keyId, + Vector const &message, + Vector &signature); + + status_t verify(Vector const &sessionId, + Vector const &keyId, + Vector const &message, + Vector const &signature, + bool &match); + private: String8 vectorToString(Vector const &vector) const; String8 arrayToString(uint8_t const *array, size_t len) const; String8 stringMapToString(KeyedVector map) const; SortedVector > mSessions; + SortedVector > mKeySets; static const ssize_t kNotFound = -1; ssize_t findSession(Vector const &sessionId) const; + ssize_t findKeySet(Vector const &keySetId) const; Mutex mLock; KeyedVector mStringProperties; -- cgit v1.1